xref: /illumos-gate/usr/src/cmd/sgs/lex/common/parser.y (revision b66926aad422ad350796a2770d6b2d328a63b92c)
1 %{
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 %}
23 /*
24  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*	Copyright (c) 1988 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 
32 %{
33 
34 /*
35  * Lint is unable to properly handle formats with wide strings
36  * (e.g. %ws) and misdiagnoses them as being malformed.
37  * This macro is used to work around that, by substituting
38  * a pointer to a null string when compiled by lint. This
39  * trick works because lint is not able to evaluate the
40  * variable.
41  *
42  * When lint is able to handle %ws, it would be appropriate
43  * to come back through and remove the use of this macro.
44  */
45 #if defined(__lint)
46 static const char *lint_ws_fmt = "";
47 #define	WSFMT(_fmt) lint_ws_fmt
48 #else
49 #define	WSFMT(_fmt) _fmt
50 #endif
51 
52 void yyerror(char *);
53 
54 %}
55 /* parser.y */
56 
57 /* XCU4: add XSCON: %x exclusive start token */
58 /* XCU4: add ARRAY: %a yytext is char array */
59 /* XCU4: add POINTER: %p yytext is a pointer to char */
60 %token CHAR CCL NCCL STR DELIM SCON ITER NEWE NULLS XSCON ARRAY POINTER
61 
62 %nonassoc ARRAY POINTER
63 %left XSCON SCON NEWE
64 %left '/'
65 /*
66  * XCU4: lower the precedence of $ and ^ to less than the or operator
67  * per Spec. 1170
68  */
69 %left '$' '^'
70 %left '|'
71 %left CHAR CCL NCCL '(' '.' STR NULLS
72 %left ITER
73 %left CAT
74 %left '*' '+' '?'
75 
76 %{
77 #include "ldefs.h"
78 
79 #define YYSTYPE union _yystype_
80 union _yystype_
81 {
82 	int	i;
83 	CHR	*cp;
84 };
85 int	peekon = 0; /* need this to check if "^" came in a definition section */
86 
87 %}
88 %%
89 %{
90 int i;
91 int j,k;
92 int g;
93 CHR *p;
94 static wchar_t  L_PctUpT[]= {'%', 'T', 0};
95 static wchar_t  L_PctLoT[]= {'%', 't', 0};
96 static wchar_t  L_PctCbr[]= {'%', '}', 0};
97 %}
98 acc	:	lexinput
99 	={
100 # ifdef DEBUG
101 		if(debug) sect2dump();
102 # endif
103 	}
104 	;
105 lexinput:	defns delim prods end
106 	|	defns delim end
107 	={
108 		if(!funcflag)phead2();
109 		funcflag = TRUE;
110 	}
111 	| error
112 	={
113 # ifdef DEBUG
114 		if(debug) {
115 			sect1dump();
116 			sect2dump();
117 			}
118 # endif
119 		fatal = 0;
120 		n_error++;
121 		error("Illegal definition");
122 		fatal = 1;
123 		}
124 	;
125 end:		delim | ;
126 defns:	defns STR STR
127 	={	scopy($2.cp,dp);
128 		def[dptr] = dp;
129 		dp += slength($2.cp) + 1;
130 		scopy($3.cp,dp);
131 		subs[dptr++] = dp;
132 		if(dptr >= DEFSIZE)
133 			error("Too many definitions");
134 		dp += slength($3.cp) + 1;
135 		if(dp >= dchar+DEFCHAR)
136 			error("Definitions too long");
137 		subs[dptr]=def[dptr]=0;	/* for lookup - require ending null */
138 	}
139 	|
140 	;
141 delim:	DELIM
142 	={
143 # ifdef DEBUG
144 		if(sect == DEFSECTION && debug) sect1dump();
145 # endif
146 		sect++;
147 		}
148 	;
149 prods:	prods pr
150 	={	$$.i = mn2(RNEWE,$1.i,$2.i);
151 		}
152 	|	pr
153 	={	$$.i = $1.i;}
154 	;
155 pr:	r NEWE
156 	={
157 		if(divflg == TRUE)
158 			i = mn1(S1FINAL,casecount);
159 		else i = mn1(FINAL,casecount);
160 		$$.i = mn2(RCAT,$1.i,i);
161 		divflg = FALSE;
162 		if((++casecount)>NACTIONS)
163 			error("Too many (>%d) pattern-action rules.", NACTIONS);
164 		}
165 	| error NEWE
166 	={
167 # ifdef DEBUG
168 		if(debug) sect2dump();
169 # endif
170 		fatal = 0;
171 		yyline--;
172 		n_error++;
173 		error("Illegal rule");
174 		fatal = 1;
175 		yyline++;
176 		}
177 r:	CHAR
178 	={	$$.i = mn0($1.i); }
179 	| STR
180 	={
181 		p = (CHR *)$1.cp;
182 		i = mn0((unsigned)(*p++));
183 		while(*p)
184 			i = mn2(RSTR,i,(unsigned)(*p++));
185 		$$.i = i;
186 		}
187 	| '.'
188 	={
189 		$$.i = mn0(DOT);
190 		}
191 	| CCL
192 	={	$$.i = mn1(RCCL,$1.i); }
193 	| NCCL
194 	={	$$.i = mn1(RNCCL,$1.i); }
195 	| r '*'
196 	={	$$.i = mn1(STAR,$1.i); }
197 	| r '+'
198 	={	$$.i = mn1(PLUS,$1.i); }
199 	| r '?'
200 	={	$$.i = mn1(QUEST,$1.i); }
201 	| r '|' r
202 	={	$$.i = mn2(BAR,$1.i,$3.i); }
203 	| r r %prec CAT
204 	={	$$.i = mn2(RCAT,$1.i,$2.i); }
205 	| r '/' r
206 	={	if(!divflg){
207 			j = mn1(S2FINAL,-casecount);
208 			i = mn2(RCAT,$1.i,j);
209 			$$.i = mn2(DIV,i,$3.i);
210 			}
211 		else {
212 			$$.i = mn2(RCAT,$1.i,$3.i);
213 			error("illegal extra slash");
214 			}
215 		divflg = TRUE;
216 		}
217 	| r ITER ',' ITER '}'
218 	={	if($2.i > $4.i){
219 			i = $2.i;
220 			$2.i = $4.i;
221 			$4.i = i;
222 			}
223 		if($4.i <= 0)
224 			error("iteration range must be positive");
225 		else {
226 			j = $1.i;
227 			for(k = 2; k<=$2.i;k++)
228 				j = mn2(RCAT,j,dupl($1.i));
229 			for(i = $2.i+1; i<=$4.i; i++){
230 				g = dupl($1.i);
231 				for(k=2;k<=i;k++)
232 					g = mn2(RCAT,g,dupl($1.i));
233 				j = mn2(BAR,j,g);
234 				}
235 			$$.i = j;
236 			}
237 	}
238 	| r ITER '}'
239 	={
240 		if($2.i < 0)error("can't have negative iteration");
241 		else if($2.i == 0) $$.i = mn0(RNULLS);
242 		else {
243 			j = $1.i;
244 			for(k=2;k<=$2.i;k++)
245 				j = mn2(RCAT,j,dupl($1.i));
246 			$$.i = j;
247 			}
248 		}
249 	| r ITER ',' '}'
250 	={
251 				/* from n to infinity */
252 		if($2.i < 0)error("can't have negative iteration");
253 		else if($2.i == 0) $$.i = mn1(STAR,$1.i);
254 		else if($2.i == 1)$$.i = mn1(PLUS,$1.i);
255 		else {		/* >= 2 iterations minimum */
256 			j = $1.i;
257 			for(k=2;k<$2.i;k++)
258 				j = mn2(RCAT,j,dupl($1.i));
259 			k = mn1(PLUS,dupl($1.i));
260 			$$.i = mn2(RCAT,j,k);
261 			}
262 		}
263 	| SCON r
264 	={	$$.i = mn2(RSCON,$2.i,(uintptr_t)$1.cp); }
265 
266 	/* XCU4: add XSCON */
267 	| XSCON r
268 	={	$$.i = mn2(RXSCON,$2.i,(uintptr_t)$1.cp); }
269 	| '^' r
270 	={	$$.i = mn1(CARAT,$2.i); }
271 	| r '$'
272 	={	i = mn0('\n');
273 		if(!divflg){
274 			j = mn1(S2FINAL,-casecount);
275 			k = mn2(RCAT,$1.i,j);
276 			$$.i = mn2(DIV,k,i);
277 			}
278 		else $$.i = mn2(RCAT,$1.i,i);
279 		divflg = TRUE;
280 		}
281 	| '(' r ')'
282 	={	$$.i = $2.i; }
283 	|	NULLS
284 	={	$$.i = mn0(RNULLS); }
285 
286 	/* XCU4: add ARRAY and POINTER */
287 	| ARRAY
288 	={ isArray = 1; };
289 	|     POINTER
290 	={ isArray = 0; };
291 	;
292 
293 %%
294 int
295 yylex(void)
296 {
297 	CHR *p;
298 	int  i;
299 	CHR *xp;
300 	int lex_startcond_lookupval;
301 	CHR  *t, c;
302 	int n, j = 0, k, x;
303 	CHR ch;
304 	static int sectbegin;
305 	static CHR token[TOKENSIZE];
306 	static int iter;
307 	int ccs; /* Current CodeSet. */
308 	CHR *ccp;
309 	int exclusive_flag;	/* XCU4: exclusive start flag */
310 
311 # ifdef DEBUG
312 	yylval.i = 0;
313 # endif
314 
315 	if(sect == DEFSECTION) {		/* definitions section */
316 		while(!eof) {
317 			if(prev == '\n'){    /* next char is at beginning of line */
318 				(void)getl(p=buf);
319 				switch(*p){
320 				case '%':
321 					switch(c= *(p+1)){
322 					case '%':
323 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
324 						if(scomp(p, (CHR *)"%%")) {
325 							p++;
326 							while(*(++p))
327 								if(!space(*p)) {
328 									warning("invalid string following %%%% be ignored");
329 									break;
330 								}
331 						}
332 						lgate();
333 						if(!ratfor)(void) fprintf(fout,"# ");
334 						(void) fprintf(fout,"define YYNEWLINE %d\n",ctable['\n']);
335 						if(!ratfor)(void) fprintf(fout,"int yylex(){\nint nstr; extern int yyprevious;\n");
336 						sectbegin = TRUE;
337 						i = treesize*(sizeof(*name)+sizeof(*left)+
338 							sizeof(*right)+sizeof(*nullstr)+sizeof(*parent))+ALITTLEEXTRA;
339 						c = (int)myalloc(i,1);
340 						if(c == 0)
341 							error("Too little core for parse tree");
342 						p = (CHR *)c;
343 						free(p);
344 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
345 						name = (int *)myalloc(treesize,sizeof(*name));
346 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
347 						left = (int *)myalloc(treesize,sizeof(*left));
348 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
349 						right = (int *)myalloc(treesize,sizeof(*right));
350 						nullstr = myalloc(treesize,sizeof(*nullstr));
351 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
352 						parent = (int *)myalloc(treesize,sizeof(*parent));
353 						if(name == 0 || left == 0 || right == 0 || parent == 0 || nullstr == 0)
354 							error("Too little core for parse tree");
355 						return(freturn(DELIM));
356 					case 'p': case 'P':
357 					        /* %p or %pointer */
358 						if ((*(p+2) == 'o') ||
359 						    (*(p+2) == 'O')) {
360 						    if(lgatflg)
361 							error("Too late for %%pointer");
362 						    while(*p && !iswspace(*p))
363 							p++;
364 						    isArray = 0;
365 						    continue;
366 						}
367 						/* has overridden number of positions */
368 						p += 2;
369 						maxpos = siconv(p);
370 						if (maxpos<=0)error("illegal position number");
371 # ifdef DEBUG
372 						if (debug) (void) printf("positions (%%p) now %d\n",maxpos);
373 # endif
374 						if(report == 2)report = 1;
375 						continue;
376 					case 'n': case 'N':	/* has overridden number of states */
377 						p += 2;
378 						nstates = siconv(p);
379 						if(nstates<=0)error("illegal state number");
380 # ifdef DEBUG
381 						if(debug)(void) printf( " no. states (%%n) now %d\n",nstates);
382 # endif
383 						if(report == 2)report = 1;
384 						continue;
385 					case 'e': case 'E':		/* has overridden number of tree nodes */
386 						p += 2;
387 						treesize = siconv(p);
388 						if(treesize<=0)error("illegal number of parse tree nodes");
389 # ifdef DEBUG
390 						if (debug) (void) printf("treesize (%%e) now %d\n",treesize);
391 # endif
392 						if(report == 2)report = 1;
393 						continue;
394 					case 'o': case 'O':
395 						p += 2;
396 						outsize = siconv(p);
397 						if(outsize<=0)error("illegal size of output array");
398 						if (report ==2) report=1;
399 						continue;
400 					case 'a': case 'A':
401 					        /* %a or %array */
402 						if ((*(p+2) == 'r') ||
403 						    (*(p+2) == 'R')) {
404 						    if(lgatflg)
405 							error("Too late for %%array");
406 						    while(*p && !iswspace(*p))
407 							p++;
408 						    isArray = 1;
409 						    continue;
410 						}
411 						/* has overridden number of transitions */
412 						p += 2;
413 						ntrans = siconv(p);
414 						if(ntrans<=0)error("illegal translation number");
415 # ifdef DEBUG
416 						if (debug)(void) printf("N. trans (%%a) now %d\n",ntrans);
417 # endif
418 						if(report == 2)report = 1;
419 						continue;
420 					case 'k': case 'K': /* overriden packed char classes */
421 						p += 2;
422 						free(pchar);
423 						pchlen = siconv(p);
424 						if(pchlen<=0)error("illegal number of packed character class");
425 # ifdef DEBUG
426 						if (debug) (void) printf( "Size classes (%%k) now %d\n",pchlen);
427 # endif
428 						/*LINTED: E_BAD_PTR_CAST_ALIGN*/
429 						pchar=pcptr=(CHR *)myalloc(pchlen, sizeof(*pchar));
430 						if (report==2) report=1;
431 						continue;
432 					case 't': case 'T': 	/* character set specifier */
433 						if(handleeuc)
434 							error("\
435 Character table (%t) is supported only in ASCII compatibility mode.\n");
436 						ZCH = watoi(p+2);
437 						if (ZCH < NCH) ZCH = NCH;
438 						if (ZCH > 2*NCH) error("ch table needs redeclaration");
439 						chset = TRUE;
440 						for(i = 0; i<ZCH; i++)
441 							ctable[i] = 0;
442 						while(getl(p) && scomp(p,L_PctUpT) != 0 && scomp(p,L_PctLoT) != 0){
443 							if((n = siconv(p)) <= 0 || n > ZCH){
444 								error("Character value %d out of range",n);
445 								continue;
446 								}
447 							while(digit(*p)) p++;
448 							if(!iswspace(*p)) error("bad translation format");
449 							while(iswspace(*p)) p++;
450 							t = p;
451 							while(*t){
452 								c = ctrans(&t);
453 								if(ctable[(unsigned)c]){
454 									if (iswprint(c))
455 										warning("Character '%wc' used twice",c);
456 
457 									else
458 										error("Chararter %o used twice",c);
459 									}
460 								else ctable[(unsigned)c] = n;
461 								t++;
462 								}
463 							p = buf;
464 							}
465 						{
466 						char chused[2*NCH]; int kr;
467 						for(i=0; i<ZCH; i++)
468 							chused[i]=0;
469 						for(i=0; i<NCH; i++)
470 							chused[ctable[i]]=1;
471 						for(kr=i=1; i<NCH; i++)
472 							if (ctable[i]==0)
473 								{
474 								while (chused[kr] == 0)
475 									kr++;
476 								ctable[i]=kr;
477 								chused[kr]=1;
478 								}
479 						}
480 						lgate();
481 						continue;
482 					case 'r': case 'R':
483 						c = 'r';
484 						/* FALLTHRU */
485 					case 'c': case 'C':
486 						if(lgatflg)
487 							error("Too late for language specifier");
488 						ratfor = (c == 'r');
489 						continue;
490 					case '{':
491 						lgate();
492 						while(getl(p) && scomp(p, L_PctCbr) != 0)
493 							if(p[0]=='/' && p[1]=='*')
494 								cpycom(p);
495 							else
496 								(void) fprintf(fout,WSFMT("%ws\n"),p);
497 						if(p[0] == '%') continue;
498 						if (*p) error("EOF before %%%%");
499 						else error("EOF before %%}");
500 						break;
501 
502 					case 'x': case 'X':		/* XCU4: exclusive start conditions */
503 						exclusive_flag = 1;
504 						goto start;
505 
506 					case 's': case 'S':		/* start conditions */
507 						exclusive_flag = 0;
508 start:
509 						lgate();
510 
511 						while(*p && !iswspace(*p) && ((*p) != (wchar_t)',')) p++;
512 						n = TRUE;
513 						while(n){
514 							while(*p && (iswspace(*p) || ((*p) == (wchar_t)','))) p++;
515 							t = p;
516 							while(*p && !iswspace(*p) && ((*p) != (wchar_t)',')) {
517 							    if(!isascii(*p))
518 								error("None-ASCII characters in start condition.");
519 							    p++;
520 							}
521 							if(!*p) n = FALSE;
522 							*p++ = 0;
523 							if (*t == 0) continue;
524 							i = sptr*2;
525 							if(!ratfor)(void) fprintf(fout,"# ");
526 							(void) fprintf(fout,WSFMT("define %ws %d\n"),t,i);
527 							scopy(t,sp);
528 							sname[sptr] = sp;
529 							/* XCU4: save exclusive flag with start name */
530 							exclusive[sptr++] = exclusive_flag;
531 							sname[sptr] = 0;	/* required by lookup */
532 							if(sptr >= STARTSIZE)
533 								error("Too many start conditions");
534 							sp += slength(sp) + 1;
535 							if(sp >= schar+STARTCHAR)
536 								error("Start conditions too long");
537 							}
538 						continue;
539 					default:
540 						error("Invalid request %s",p);
541 						continue;
542 						}	/* end of switch after seeing '%' */
543 					break;
544 				case ' ': case '\t':		/* must be code */
545 					lgate();
546 					if( p[1]=='/' && p[2]=='*' ) cpycom(p);
547 					else (void) fprintf(fout, WSFMT("%ws\n"),p);
548 					continue;
549 				case '/':	/* look for comments */
550 					lgate();
551 					if((*(p+1))=='*') cpycom(p);
552 					/* FALLTHRU */
553 				default:		/* definition */
554 					while(*p && !iswspace(*p)) p++;
555 					if(*p == 0)
556 						continue;
557 					prev = *p;
558 					*p = 0;
559 					bptr = p+1;
560 					yylval.cp = (CHR *)buf;
561 					if(digit(buf[0]))
562 						warning("Substitution strings may not begin with digits");
563 					return(freturn(STR));
564 				}
565 			} else { /* still sect 1, but prev != '\n' */
566 				p = bptr;
567 				while(*p && iswspace(*p)) p++;
568 				if(*p == 0)
569 					warning("No translation given - null string assumed");
570 				scopy(p,token);
571 				yylval.cp = (CHR *)token;
572 				prev = '\n';
573 				return(freturn(STR));
574 				}
575 			}
576 		error("unexpected EOF before %%%%");
577 		/* end of section one processing */
578 	} else if(sect == RULESECTION){		/* rules and actions */
579 		lgate();
580 		while(!eof){
581 			static int first_test=TRUE, first_value;
582 			static int reverse=FALSE;
583 			switch(c=gch()){
584 			case '\0':
585 				if(n_error)error_tail();
586 				return(freturn(0));
587 			case '\n':
588 				if(prev == '\n') continue;
589 				x = NEWE;
590 				break;
591 			case ' ':
592 			case '\t':
593 				if(prev == '\n') copy_line = TRUE;
594 				if(sectbegin == TRUE){
595 					(void)cpyact();
596 					copy_line = FALSE;
597 					/*LINTED: E_EQUALITY_NOT_ASSIGNMENT*/
598 					while((c=gch()) && c != '\n');
599 					continue;
600 					}
601 				if(!funcflag)phead2();
602 				funcflag = TRUE;
603 				if(ratfor)(void) fprintf(fout,"%d\n",30000+casecount);
604 				else (void) fprintf(fout,"case %d:\n",casecount);
605 				if(cpyact()){
606 					if(ratfor)(void) fprintf(fout,"goto 30997\n");
607 					else (void) fprintf(fout,"break;\n");
608 					}
609 				/*LINTED: E_EQUALITY_NOT_ASSIGNMENT*/
610 				while((c=gch()) && c != '\n') {
611 					if (c=='/') {
612 						if((c=gch())=='*') {
613 							c=gch();
614 							while(c !=EOF) {
615 								while (c=='*')
616 									if ((c=gch()) == '/') goto w_loop;
617 								c = gch();
618 							}
619 							error("EOF inside comment");
620 						} else
621 							warning("undefined string");
622 					} else if (c=='}')
623 						error("illegal extra \"}\"");
624 				w_loop: ;
625 				}
626 				/* while ((c=gch())== ' ' || c == '\t') ; */
627 				/* if (!space(c)) error("undefined action string"); */
628 				if(peek == ' ' || peek == '\t' || sectbegin == TRUE){
629 					fatal = 0;
630 					n_error++;
631 					error("executable statements should occur right after %%%%");
632 					fatal = 1;
633 					continue;
634 					}
635 				x = NEWE;
636 				break;
637 			case '%':
638 				if(prev != '\n') goto character;
639 				if(peek == '{'){	/* included code */
640 					(void)getl(buf);
641 					while(!eof&& getl(buf) && scomp(L_PctCbr,buf)!=0)
642 						if(buf[0]=='/' && buf[1]=='*')
643 							cpycom(buf);
644 						else
645 							(void) fprintf(fout,WSFMT("%ws\n"),buf);
646 					continue;
647 					}
648 				if(peek == '%'){
649 					c = gch();
650 					c = gch();
651 					x = DELIM;
652 					break;
653 					}
654 				goto character;
655 			case '|':
656 				if(peek == ' ' || peek == '\t' || peek == '\n'){
657 					if(ratfor)(void) fprintf(fout,"%d\n",30000+casecount++);
658 					else (void) fprintf(fout,"case %d:\n",casecount++);
659 					continue;
660 					}
661 				x = '|';
662 				break;
663 			case '$':
664 				if(peek == '\n' || peek == ' ' || peek == '\t' || peek == '|' || peek == '/'){
665 					x = c;
666 					break;
667 					}
668 				goto character;
669 			case '^':
670                                 if(peekon && (prev == '}')){
671                                         x = c;
672                                         break;
673                                 }
674 				if(prev != '\n' && scon != TRUE) goto character;
675 				/* valid only at line begin */
676 				x = c;
677 				break;
678 			case '?':
679 			case '+':
680 			case '*':
681 				if(prev == '\n' ) {
682 					fatal = 0;
683 					n_error++;
684 					error("illegal operator -- %c",c);
685 					fatal = 1;
686 				}
687 				/* FALLTHRU */
688 			case '.':
689 			case '(':
690 			case ')':
691 			case ',':
692 			case '/':
693 				x = c;
694 				break;
695 			case '}':
696 				iter = FALSE;
697 				x = c;
698 				break;
699 			case '{':	/* either iteration or definition */
700 				if(digit(c=gch())){	/* iteration */
701 					iter = TRUE;
702 					if(prev=='{') first_test = TRUE;
703 				ieval:
704 					i = 0;
705 					while(digit(c)){
706 						token[i++] = c;
707 						c = gch();
708 						}
709 					token[i] = 0;
710 					yylval.i = siconv(token);
711 					if(first_test) {
712 						first_test = FALSE;
713 						first_value = yylval.i;
714 					} else
715 						if(first_value>yylval.i)warning("the values between braces are reversed");
716 					ch = c;
717 					munput('c',&ch);
718 					x = ITER;
719 					break;
720 					}
721 				else {		/* definition */
722 					i = 0;
723 					while(c && c!='}'){
724 						token[i++] = c;
725 						if(i >= TOKENSIZE)
726 							error("definition too long");
727 						c = gch();
728 						}
729 					token[i] = 0;
730 					i = lookup(token,def);
731 					if(i < 0)
732 						error("definition %ws not found",token);
733 					else
734 						munput('s',(CHR *)(subs[i]));
735             				if (peek == '^')
736                                                 peekon = 1;
737 					continue;
738 					}
739 			case '<':		/* start condition ? */
740 				if(prev != '\n')  /* not at line begin, not start */
741 					goto character;
742 				t = slptr;
743 				do {
744 					i = 0;
745 					if(!isascii(c = gch()))
746 					    error("Non-ASCII characters in start condition.");
747 					while(c != ',' && c && c != '>'){
748 						token[i++] = c;
749 						if(i >= TOKENSIZE)
750 							error("string name too long");
751 						if(!isascii(c = gch()))
752 						    error("None-ASCII characters in start condition.");
753 						}
754 					token[i] = 0;
755 					if(i == 0)
756 						goto character;
757 					i = lookup(token,sname);
758 					lex_startcond_lookupval = i;
759 					if(i < 0) {
760 						fatal = 0;
761 						n_error++;
762 						error("undefined start condition %ws",token);
763 						fatal = 1;
764 						continue;
765 						}
766 					*slptr++ = i+1;
767 					} while(c && c != '>');
768 				*slptr++ = 0;
769 				/* check if previous value re-usable */
770 				for (xp=slist; xp<t; )
771 					{
772 					if (scomp(xp, t)==0)
773 						break;
774 					while (*xp++);
775 					}
776 				if (xp<t)
777 					{
778 					/* re-use previous pointer to string */
779 					slptr=t;
780 					t=xp;
781 					}
782 				if(slptr > slist+STARTSIZE)	/* note not packed */
783 					error("Too many start conditions used");
784 				yylval.cp = (CHR *)t;
785 
786 				/* XCU4: add XSCON */
787 
788 				if (exclusive[lex_startcond_lookupval])
789 					x = XSCON;
790 				else
791 					x = SCON;
792 				break;
793 			case '"':
794 				i = 0;
795 				/*LINTED: E_EQUALITY_NOT_ASSIGNMENT*/
796 				while((c=gch()) && c != '"' && c != '\n'){
797 					if(c == '\\') c = usescape(c=gch());
798 					remch(c);
799 					token[i++] = c;
800 					if(i >= TOKENSIZE){
801 						warning("String too long");
802 						i = TOKENSIZE-1;
803 						break;
804 						}
805 					}
806 				if(c == '\n') {
807 					yyline--;
808 					warning("Non-terminated string");
809 					yyline++;
810 					}
811 				token[i] = 0;
812 				if(i == 0)x = NULLS;
813 				else if(i == 1){
814 					yylval.i = (unsigned)token[0];
815 					x = CHAR;
816 					}
817 				else {
818 					yylval.cp = (CHR *)token;
819 					x = STR;
820 					}
821 				break;
822 			case '[':
823 				reverse = FALSE;
824 				x = CCL;
825 				if((c = gch()) == '^'){
826 					x = NCCL;
827 					reverse = TRUE;
828 					c = gch();
829 					}
830 				i = 0;
831 				while(c != ']' && c){
832 					static int light=TRUE, ESCAPE=FALSE;
833 					if(c == '-' && prev == '^' && reverse){
834 						symbol[(unsigned)c] = 1;
835 						c = gch();
836 						continue;
837 					}
838 					if(c == '\\') {
839 						c = usescape(c=gch());
840 						ESCAPE = TRUE;
841 					}
842 					if(c=='-' && !ESCAPE && prev!='[' && peek!=']'){
843 					/* range specified */
844 						if (light) {
845 							c = gch();
846 							if(c == '\\')
847 								c=usescape(c=gch());
848 							remch(c);
849 							k = c;
850 							ccs=wcsetno(k);
851 							if(wcsetno(j)!=ccs)
852 							    error("\
853 Character range specified between different codesets.");
854 							if((unsigned)j > (unsigned)k) {
855 								n = j;
856 								j = k;
857 								k = n;
858 								}
859 							if(!handleeuc)
860 							if(!(('A'<=j && k<='Z') ||
861 						     	     ('a'<=j && k<='z') ||
862 						     	     ('0'<=j && k<='9')))
863 								warning("Non-portable Character Class");
864 							token[i++] = RANGE;
865 							token[i++] = j;
866 							token[i++] = k;
867 							light = FALSE;
868 						} else {
869 							error("unmatched hyphen");
870 							if(symbol[(unsigned)c])warning("\"%c\" redefined inside brackets",c);
871 							else symbol[(unsigned)c] = 1;
872 						}
873 						ESCAPE = FALSE;
874 					} else {
875 						j = c;
876 						remch(c);
877 						token[i++] = c; /* Remember whatever.*/
878 						light = TRUE;
879 						ESCAPE = FALSE;
880 					}
881 					c = gch();
882 				}
883 				/* try to pack ccl's */
884 
885 				token[i] = 0;
886 				ccp = ccl;
887 				while (ccp < ccptr && scomp(token, ccp) != 0) ccp++;
888 				if (ccp < ccptr) {  /* found in ccl */
889 				    yylval.cp = ccp;
890 				} else {            /* not in ccl, add it */
891 				    scopy(token,ccptr);
892 				    yylval.cp = ccptr;
893 				    ccptr += slength(token) + 1;
894 				    if(ccptr >= ccl+CCLSIZE)
895 				      error("Too many large character classes");
896 				}
897 				break;
898 			case '\\':
899 				c = usescape(c=gch());
900 				/* FALLTHROUGH */
901 			default:
902 			character:
903 				if(iter){	/* second part of an iteration */
904 					iter = FALSE;
905 					if('0' <= c && c <= '9')
906 						goto ieval;
907 					}
908 				remch(c);
909 				if(alpha(peek)){
910 					i = 0;
911 					yylval.cp = (CHR *)token;
912 					token[i++] = c;
913 					while(alpha(peek)) {
914 						remch(token[i++] = gch());
915 						if(i >= TOKENSIZE) {
916 							warning("string too long");
917 							i = TOKENSIZE - 1;
918 							break;
919 							}
920 						}
921 					if(peek == '?' || peek == '*' || peek == '+')
922 						munput('c',&token[--i]);
923 					token[i] = 0;
924 					if(i == 1){
925 						yylval.i = (unsigned)(token[0]);
926 						x = CHAR;
927 						}
928 					else x = STR;
929 					}
930 				else {
931 					yylval.i = (unsigned)c;
932 					x = CHAR;
933 					}
934 				}
935 			scon = FALSE;
936 			peekon = 0;
937 			if((x == SCON) || (x == XSCON))
938 				scon = TRUE;
939 			sectbegin = FALSE;
940 			return(freturn(x));
941 			/* NOTREACHED */
942 			}
943 		}
944 	/* section three */
945 	lgate();
946 	ptail();
947 # ifdef DEBUG
948 	if(debug)
949 		(void) fprintf(fout,"\n/*this comes from section three - debug */\n");
950 # endif
951 
952 	if(getl(buf) && !eof) {
953   		if (sargv[optind] == NULL)
954 			(void) fprintf(fout, "\n# line %d\n", yyline-1);
955 		else
956 			(void) fprintf(fout,
957 				"\n# line %d \"%s\"\n", yyline-1, sargv[optind]);
958 		(void) fprintf(fout,WSFMT("%ws\n"),buf);
959 		while(getl(buf) && !eof)
960 			(void) fprintf(fout,WSFMT("%ws\n"),buf);
961         }
962 
963 	return(freturn(0));
964 	}
965 /* end of yylex */
966 # ifdef DEBUG
967 freturn(i)
968   int i; {
969 	if(yydebug) {
970 		(void) printf("now return ");
971 		if((unsigned)i < NCH) allprint(i);
972 		else (void) printf("%d",i);
973 		(void) printf("   yylval = ");
974 		switch(i){
975 			case STR: case CCL: case NCCL:
976 				strpt(yylval.cp);
977 				break;
978 			case CHAR:
979 				allprint(yylval.i);
980 				break;
981 			default:
982 				(void) printf("%d",yylval.i);
983 				break;
984 			}
985 		(void) putchar('\n');
986 		}
987 	return(i);
988 	}
989 # endif
990