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