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