xref: /plan9/sys/src/cmd/lex/sub1.c (revision 169d3509e3830be480b499459c3245b23637fe07)
1 # include "ldefs.h"
2 uchar *
getl(uchar * p)3 getl(uchar *p)	/* return next line of input, throw away trailing '\n' */
4 	/* returns 0 if eof is had immediately */
5 {
6 	int c;
7 	uchar *s, *t;
8 
9 	t = s = p;
10 	while(((c = gch()) != 0) && c != '\n')
11 		*t++ = c;
12 	*t = 0;
13 	if(c == 0 && s == t) return((uchar *)0);
14 	prev = '\n';
15 	pres = '\n';
16 	return(s);
17 }
18 
19 void
printerr(char * type,char * fmt,va_list argl)20 printerr(char *type, char *fmt, va_list argl)
21 {
22 	char buf[1024];
23 
24 	if(!eof)fprint(errorf,"%s:%d  ", yyfile, yyline);
25 	fprint(errorf,"(%s) ", type);
26 	vseprint(buf, buf+sizeof(buf), fmt, argl);
27 	fprint(errorf, "%s\n", buf);
28 }
29 
30 
31 void
error(char * s,...)32 error(char *s,...)
33 {
34 	va_list argl;
35 
36 	va_start(argl, s);
37 	printerr("Error", s, argl);
38 	va_end(argl);
39 # ifdef DEBUG
40 	if(debug && sect != ENDSECTION) {
41 		sect1dump();
42 		sect2dump();
43 	}
44 # endif
45 	if(
46 # ifdef DEBUG
47 		debug ||
48 # endif
49 		report == 1) statistics();
50 	exits("error");	/* error return code */
51 }
52 
53 void
warning(char * s,...)54 warning(char *s,...)
55 {
56 	va_list argl;
57 
58 	va_start(argl, s);
59 	printerr("Warning", s, argl);
60 	va_end(argl);
61 	Bflush(&fout);
62 }
63 
64 void
lgate(void)65 lgate(void)
66 {
67 	int fd;
68 
69 	if (lgatflg) return;
70 	lgatflg=1;
71 	if(foutopen == 0){
72 		fd = create("lex.yy.c", OWRITE, 0666);
73 		if(fd < 0)
74 			error("Can't open lex.yy.c: %r");
75 		Binit(&fout, fd, OWRITE);
76 		foutopen = 1;
77 		}
78 	phead1();
79 }
80 
81 void
cclinter(int sw)82 cclinter(int sw)
83 {
84 		/* sw = 1 ==> ccl */
85 	int i, j, k;
86 	int m;
87 	if(!sw){		/* is NCCL */
88 		for(i=1;i<NCH;i++)
89 			symbol[i] ^= 1;			/* reverse value */
90 	}
91 	for(i=1;i<NCH;i++)
92 		if(symbol[i]) break;
93 	if(i >= NCH) return;
94 	i = cindex[i];
95 	/* see if ccl is already in our table */
96 	j = 0;
97 	if(i){
98 		for(j=1;j<NCH;j++){
99 			if((symbol[j] && cindex[j] != i) ||
100 			   (!symbol[j] && cindex[j] == i)) break;
101 		}
102 	}
103 	if(j >= NCH) return;		/* already in */
104 	m = 0;
105 	k = 0;
106 	for(i=1;i<NCH;i++)
107 		if(symbol[i]){
108 			if(!cindex[i]){
109 				cindex[i] = ccount;
110 				symbol[i] = 0;
111 				m = 1;
112 			} else k = 1;
113 		}
114 			/* m == 1 implies last value of ccount has been used */
115 	if(m)ccount++;
116 	if(k == 0) return;	/* is now in as ccount wholly */
117 	/* intersection must be computed */
118 	for(i=1;i<NCH;i++){
119 		if(symbol[i]){
120 			m = 0;
121 			j = cindex[i];	/* will be non-zero */
122 			for(k=1;k<NCH;k++){
123 				if(cindex[k] == j){
124 					if(symbol[k]) symbol[k] = 0;
125 					else {
126 						cindex[k] = ccount;
127 						m = 1;
128 					}
129 				}
130 			}
131 			if(m)ccount++;
132 		}
133 	}
134 }
135 
136 int
usescape(int c)137 usescape(int c)
138 {
139 	int d;
140 	switch(c){
141 	case 'n': c = '\n'; break;
142 	case 'r': c = '\r'; break;
143 	case 't': c = '\t'; break;
144 	case 'b': c = '\b'; break;
145 	case 'f': c = 014; break;		/* form feed for ascii */
146 	case '0': case '1': case '2': case '3':
147 	case '4': case '5': case '6': case '7':
148 		c -= '0';
149 		while('0' <= (d=gch()) && d <= '7'){
150 			c = c * 8 + (d-'0');
151 			if(!('0' <= peek && peek <= '7')) break;
152 			}
153 		break;
154 	}
155 	return(c);
156 }
157 
158 int
lookup(uchar * s,uchar ** t)159 lookup(uchar *s, uchar **t)
160 {
161 	int i;
162 	i = 0;
163 	while(*t){
164 		if(strcmp((char *)s, *(char **)t) == 0)
165 			return(i);
166 		i++;
167 		t++;
168 	}
169 	return(-1);
170 }
171 
172 int
cpyact(void)173 cpyact(void)
174 { /* copy C action to the next ; or closing } */
175 	int brac, c, mth;
176 	int savline, sw;
177 	char *savfile;
178 
179 	brac = 0;
180 	sw = TRUE;
181 	savline = 0;
182 	savfile = "?";
183 
184 while(!eof){
185 	c = gch();
186 swt:
187 	switch( c ){
188 
189 case '|':	if(brac == 0 && sw == TRUE){
190 			if(peek == '|')gch();		/* eat up an extra '|' */
191 			return(0);
192 		}
193 		break;
194 
195 case ';':
196 		if( brac == 0 ){
197 			Bputc(&fout, c);
198 			Bputc(&fout, '\n');
199 			return(1);
200 		}
201 		break;
202 
203 case '{':
204 		brac++;
205 		savline=yyline;
206 		savfile=yyfile;
207 		break;
208 
209 case '}':
210 		brac--;
211 		if( brac == 0 ){
212 			Bputc(&fout, c);
213 			Bputc(&fout, '\n');
214 			return(1);
215 		}
216 		break;
217 
218 case '/':	/* look for comments */
219 		Bputc(&fout, c);
220 		c = gch();
221 		if( c != '*' ) goto swt;
222 
223 		/* it really is a comment */
224 
225 		Bputc(&fout, c);
226 		savline=yyline;
227 		savfile=yyfile;
228 		while( c=gch() ){
229 			if( c=='*' ){
230 				Bputc(&fout, c);
231 				if( (c=gch()) == '/' ) goto loop;
232 			}
233 			Bputc(&fout, c);
234 		}
235 		yyline=savline;
236 		yyfile=savfile;
237 		error( "EOF inside comment" );
238 
239 case '\'':	/* character constant */
240 		mth = '\'';
241 		goto string;
242 
243 case '"':	/* character string */
244 		mth = '"';
245 
246 	string:
247 
248 		Bputc(&fout, c);
249 		while( c=gch() ){
250 			if( c=='\\' ){
251 				Bputc(&fout, c);
252 				c=gch();
253 			}
254 			else if( c==mth ) goto loop;
255 			Bputc(&fout, c);
256 			if (c == '\n') {
257 				yyline--;
258 				error( "Non-terminated string or character constant");
259 			}
260 		}
261 		error( "EOF in string or character constant" );
262 
263 case '\0':
264 		yyline = savline;
265 		yyfile = savfile;
266 		error("Action does not terminate");
267 default:
268 		break;		/* usual character */
269 		}
270 loop:
271 	if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
272 	Bputc(&fout, c);
273 	}
274 	error("Premature EOF");
275 	return(0);
276 }
277 
278 int
gch(void)279 gch(void){
280 	int c;
281 	prev = pres;
282 	c = pres = peek;
283 	peek = pushptr > pushc ? *--pushptr : Bgetc(fin);
284 	if(peek == Beof && sargc > 1){
285 		Bterm(fin);
286 		yyfile = sargv[fptr++];
287 		fin = Bopen(yyfile,OREAD);
288 		if(fin == 0)
289 			error("%s - cannot open file: %r",yyfile);
290 		peek = Bgetc(fin);
291 		sargc--;
292 		sargv++;
293 	}
294 	if(c == Beof) {
295 		eof = TRUE;
296 		Bterm(fin);
297 		fin = 0;
298 		return(0);
299 	}
300 	if(c == '\n')yyline++;
301 	return(c);
302 }
303 
304 int
mn2(int a,int d,uintptr c)305 mn2(int a, int d, uintptr c)
306 {
307 	name[tptr] = a;
308 	left[tptr] = d;
309 	right[tptr] = c;
310 	parent[tptr] = 0;
311 	nullstr[tptr] = 0;
312 	switch(a){
313 	case RSTR:
314 		parent[d] = tptr;
315 		break;
316 	case BAR:
317 	case RNEWE:
318 		if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
319 		parent[d] = parent[c] = tptr;
320 		break;
321 	case RCAT:
322 	case DIV:
323 		if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
324 		parent[d] = parent[c] = tptr;
325 		break;
326 	case RSCON:
327 		parent[d] = tptr;
328 		nullstr[tptr] = nullstr[d];
329 		break;
330 # ifdef DEBUG
331 	default:
332 		warning("bad switch mn2 %d %d",a,d);
333 		break;
334 # endif
335 		}
336 	if(tptr > treesize)
337 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
338 	return(tptr++);
339 }
340 
341 int
mnp(int a,void * p)342 mnp(int a, void *p)
343 {
344 	name[tptr] = a;
345 	left[tptr] = 0;
346 	parent[tptr] = 0;
347 	nullstr[tptr] = 0;
348 	ptr[tptr] = p;
349 	switch(a){
350 	case RCCL:
351 	case RNCCL:
352 		if(strlen(p) == 0) nullstr[tptr] = TRUE;
353 		break;
354 	default:
355 		error("bad switch mnp %d %P", a, p);
356 		break;
357 	}
358 	if(tptr > treesize)
359 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
360 	return(tptr++);
361 }
362 
363 int
mn1(int a,int d)364 mn1(int a, int d)
365 {
366 	name[tptr] = a;
367 	left[tptr] = d;
368 	parent[tptr] = 0;
369 	nullstr[tptr] = 0;
370 	switch(a){
371 	case STAR:
372 	case QUEST:
373 		nullstr[tptr] = TRUE;
374 		parent[d] = tptr;
375 		break;
376 	case PLUS:
377 	case CARAT:
378 		nullstr[tptr] = nullstr[d];
379 		parent[d] = tptr;
380 		break;
381 	case S2FINAL:
382 		nullstr[tptr] = TRUE;
383 		break;
384 # ifdef DEBUG
385 	case FINAL:
386 	case S1FINAL:
387 		break;
388 	default:
389 		warning("bad switch mn1 %d %d",a,d);
390 		break;
391 # endif
392 	}
393 	if(tptr > treesize)
394 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
395 	return(tptr++);
396 }
397 
398 int
mn0(int a)399 mn0(int a)
400 {
401 	name[tptr] = a;
402 	parent[tptr] = 0;
403 	nullstr[tptr] = 0;
404 	if(a >= NCH) switch(a){
405 	case RNULLS: nullstr[tptr] = TRUE; break;
406 # ifdef DEBUG
407 	default:
408 		warning("bad switch mn0 %d",a);
409 		break;
410 # endif
411 	}
412 	if(tptr > treesize)
413 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
414 	return(tptr++);
415 }
416 
417 void
munputc(int p)418 munputc(int p)
419 {
420 	*pushptr++ = peek;		/* watch out for this */
421 	peek = p;
422 	if(pushptr >= pushc+TOKENSIZE)
423 		error("Too many characters pushed");
424 }
425 
426 void
munputs(uchar * p)427 munputs(uchar *p)
428 {
429 	int i,j;
430 	*pushptr++ = peek;
431 	peek = p[0];
432 	i = strlen((char*)p);
433 	for(j = i-1; j>=1; j--)
434 		*pushptr++ = p[j];
435 	if(pushptr >= pushc+TOKENSIZE)
436 		error("Too many characters pushed");
437 }
438 
439 int
dupl(int n)440 dupl(int n)
441 {
442 	/* duplicate the subtree whose root is n, return ptr to it */
443 	int i;
444 
445 	i = name[n];
446 	if(i < NCH) return(mn0(i));
447 	switch(i){
448 	case RNULLS:
449 		return(mn0(i));
450 	case RCCL: case RNCCL:
451 		return(mnp(i,ptr[n]));
452 	case FINAL: case S1FINAL: case S2FINAL:
453 		return(mn1(i,left[n]));
454 	case STAR: case QUEST: case PLUS: case CARAT:
455 		return(mn1(i,dupl(left[n])));
456 	case RSTR: case RSCON:
457 		return(mn2(i,dupl(left[n]),right[n]));
458 	case BAR: case RNEWE: case RCAT: case DIV:
459 		return(mn2(i,dupl(left[n]),dupl(right[n])));
460 # ifdef DEBUG
461 	default:
462 		warning("bad switch dupl %d",n);
463 # endif
464 	}
465 	return(0);
466 }
467 
468 # ifdef DEBUG
469 void
allprint(int c)470 allprint(int c)
471 {
472 	if(c < 0)
473 		c += 256;	/* signed char */
474 	switch(c){
475 		case 014:
476 			print("\\f");
477 			charc++;
478 			break;
479 		case '\n':
480 			print("\\n");
481 			charc++;
482 			break;
483 		case '\t':
484 			print("\\t");
485 			charc++;
486 			break;
487 		case '\b':
488 			print("\\b");
489 			charc++;
490 			break;
491 		case ' ':
492 			print("\\\bb");
493 			break;
494 		default:
495 			if(!isprint(c)){
496 				print("\\%-3o",c);
497 				charc += 3;
498 			} else
499 				print("%c", c);
500 			break;
501 	}
502 	charc++;
503 }
504 
505 void
strpt(uchar * s)506 strpt(uchar *s)
507 {
508 	charc = 0;
509 	while(*s){
510 		allprint(*s++);
511 		if(charc > LINESIZE){
512 			charc = 0;
513 			print("\n\t");
514 		}
515 	}
516 }
517 
518 void
sect1dump(void)519 sect1dump(void)
520 {
521 	int i;
522 
523 	print("Sect 1:\n");
524 	if(def[0]){
525 		print("str	trans\n");
526 		i = -1;
527 		while(def[++i])
528 			print("%s\t%s\n",def[i],subs[i]);
529 	}
530 	if(sname[0]){
531 		print("start names\n");
532 		i = -1;
533 		while(sname[++i])
534 			print("%s\n",sname[i]);
535 	}
536 }
537 
538 void
sect2dump(void)539 sect2dump(void)
540 {
541 	print("Sect 2:\n");
542 	treedump();
543 }
544 
545 void
treedump(void)546 treedump(void)
547 {
548 	int t;
549 	uchar *p;
550 	print("treedump %d nodes:\n",tptr);
551 	for(t=0;t<tptr;t++){
552 		print("%4d ",t);
553 		parent[t] ? print("p=%4d",parent[t]) : print("      ");
554 		print("  ");
555 		if(name[t] < NCH)
556 				allprint(name[t]);
557 		else switch(name[t]){
558 			case RSTR:
559 				print("%d ",left[t]);
560 				allprint(right[t]);
561 				break;
562 			case RCCL:
563 				print("ccl ");
564 				allprint(ptr[t]);
565 				break;
566 			case RNCCL:
567 				print("nccl ");
568 				allprint(ptr[t]);
569 				break;
570 			case DIV:
571 				print("/ %d %d",left[t],right[t]);
572 				break;
573 			case BAR:
574 				print("| %d %d",left[t],right[t]);
575 				break;
576 			case RCAT:
577 				print("cat %d %d",left[t],right[t]);
578 				break;
579 			case PLUS:
580 				print("+ %d",left[t]);
581 				break;
582 			case STAR:
583 				print("* %d",left[t]);
584 				break;
585 			case CARAT:
586 				print("^ %d",left[t]);
587 				break;
588 			case QUEST:
589 				print("? %d",left[t]);
590 				break;
591 			case RNULLS:
592 				print("nullstring");
593 				break;
594 			case FINAL:
595 				print("final %d",left[t]);
596 				break;
597 			case S1FINAL:
598 				print("s1final %d",left[t]);
599 				break;
600 			case S2FINAL:
601 				print("s2final %d",left[t]);
602 				break;
603 			case RNEWE:
604 				print("new %d %d",left[t],right[t]);
605 				break;
606 			case RSCON:
607 				p = (uchar *)right[t];
608 				print("start %s",sname[*p++-1]);
609 				while(*p)
610 					print(", %s",sname[*p++-1]);
611 				print(" %d",left[t]);
612 				break;
613 			default:
614 				print("unknown %d %d %d",name[t],left[t],right[t]);
615 				break;
616 		}
617 		if(nullstr[t])print("\t(null poss.)");
618 		print("\n");
619 	}
620 }
621 # endif
622