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