xref: /plan9/sys/src/cmd/lex/sub1.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 # include "ldefs.h"
2 uchar *
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
20 printerr(char *type, char *fmt, va_list argl)
21 {
22 	char buf[1024];
23 
24 	if(!eof)fprint(errorf,"%d: ",yyline);
25 	fprint(errorf,"(%s) ", type);
26 	doprint(buf, buf+sizeof(buf), fmt, argl);
27 	fprint(errorf, "%s\n", buf);
28 }
29 
30 
31 void
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
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
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");
75 		Binit(&fout, fd, OWRITE);
76 		foutopen = 1;
77 		}
78 	phead1();
79 }
80 
81 void
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
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
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
173 cpyact(void)
174 { /* copy C action to the next ; or closing } */
175 	int brac, c, mth;
176 	int savline, sw;
177 
178 	brac = 0;
179 	sw = TRUE;
180 	savline = 0;
181 
182 while(!eof){
183 	c = gch();
184 swt:
185 	switch( c ){
186 
187 case '|':	if(brac == 0 && sw == TRUE){
188 			if(peek == '|')gch();		/* eat up an extra '|' */
189 			return(0);
190 		}
191 		break;
192 
193 case ';':
194 		if( brac == 0 ){
195 			Bputc(&fout, c);
196 			Bputc(&fout, '\n');
197 			return(1);
198 		}
199 		break;
200 
201 case '{':
202 		brac++;
203 		savline=yyline;
204 		break;
205 
206 case '}':
207 		brac--;
208 		if( brac == 0 ){
209 			Bputc(&fout, c);
210 			Bputc(&fout, '\n');
211 			return(1);
212 		}
213 		break;
214 
215 case '/':	/* look for comments */
216 		Bputc(&fout, c);
217 		c = gch();
218 		if( c != '*' ) goto swt;
219 
220 		/* it really is a comment */
221 
222 		Bputc(&fout, c);
223 		savline=yyline;
224 		while( c=gch() ){
225 			if( c=='*' ){
226 				Bputc(&fout, c);
227 				if( (c=gch()) == '/' ) goto loop;
228 			}
229 			Bputc(&fout, c);
230 		}
231 		yyline=savline;
232 		error( "EOF inside comment" );
233 
234 case '\'':	/* character constant */
235 		mth = '\'';
236 		goto string;
237 
238 case '"':	/* character string */
239 		mth = '"';
240 
241 	string:
242 
243 		Bputc(&fout, c);
244 		while( c=gch() ){
245 			if( c=='\\' ){
246 				Bputc(&fout, c);
247 				c=gch();
248 			}
249 			else if( c==mth ) goto loop;
250 			Bputc(&fout, c);
251 			if (c == '\n') {
252 				yyline--;
253 				error( "Non-terminated string or character constant");
254 			}
255 		}
256 		error( "EOF in string or character constant" );
257 
258 case '\0':
259 		yyline = savline;
260 		error("Action does not terminate");
261 default:
262 		break;		/* usual character */
263 		}
264 loop:
265 	if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
266 	Bputc(&fout, c);
267 	}
268 	error("Premature EOF");
269 	return(0);
270 }
271 
272 int
273 gch(void){
274 	int c;
275 	prev = pres;
276 	c = pres = peek;
277 	peek = pushptr > pushc ? *--pushptr : Bgetc(fin);
278 	if(peek == Beof && sargc > 1){
279 		Bterm(fin);
280 		fin = Bopen(sargv[fptr++],OREAD);
281 		if(fin == 0)
282 			error("Cannot open file %s",sargv[fptr-1]);
283 		peek = Bgetc(fin);
284 		sargc--;
285 		sargv++;
286 	}
287 	if(c == Beof) {
288 		eof = TRUE;
289 		Bterm(fin);
290 		return(0);
291 	}
292 	if(c == '\n')yyline++;
293 	return(c);
294 }
295 
296 int
297 mn2(int a, int d, int c)
298 {
299 	name[tptr] = a;
300 	left[tptr] = d;
301 	right[tptr] = c;
302 	parent[tptr] = 0;
303 	nullstr[tptr] = 0;
304 	switch(a){
305 	case RSTR:
306 		parent[d] = tptr;
307 		break;
308 	case BAR:
309 	case RNEWE:
310 		if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
311 		parent[d] = parent[c] = tptr;
312 		break;
313 	case RCAT:
314 	case DIV:
315 		if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
316 		parent[d] = parent[c] = tptr;
317 		break;
318 	case RSCON:
319 		parent[d] = tptr;
320 		nullstr[tptr] = nullstr[d];
321 		break;
322 # ifdef DEBUG
323 	default:
324 		warning("bad switch mn2 %d %d",a,d);
325 		break;
326 # endif
327 		}
328 	if(tptr > treesize)
329 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
330 	return(tptr++);
331 }
332 
333 int
334 mn1(int a, int d)
335 {
336 	name[tptr] = a;
337 	left[tptr] = d;
338 	parent[tptr] = 0;
339 	nullstr[tptr] = 0;
340 	switch(a){
341 	case RCCL:
342 	case RNCCL:
343 		if(strlen((char *)d) == 0) nullstr[tptr] = TRUE;
344 		break;
345 	case STAR:
346 	case QUEST:
347 		nullstr[tptr] = TRUE;
348 		parent[d] = tptr;
349 		break;
350 	case PLUS:
351 	case CARAT:
352 		nullstr[tptr] = nullstr[d];
353 		parent[d] = tptr;
354 		break;
355 	case S2FINAL:
356 		nullstr[tptr] = TRUE;
357 		break;
358 # ifdef DEBUG
359 	case FINAL:
360 	case S1FINAL:
361 		break;
362 	default:
363 		warning("bad switch mn1 %d %d",a,d);
364 		break;
365 # endif
366 	}
367 	if(tptr > treesize)
368 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
369 	return(tptr++);
370 }
371 
372 int
373 mn0(int a)
374 {
375 	name[tptr] = a;
376 	parent[tptr] = 0;
377 	nullstr[tptr] = 0;
378 	if(a >= NCH) switch(a){
379 	case RNULLS: nullstr[tptr] = TRUE; break;
380 # ifdef DEBUG
381 	default:
382 		warning("bad switch mn0 %d",a);
383 		break;
384 # endif
385 	}
386 	if(tptr > treesize)
387 		error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
388 	return(tptr++);
389 }
390 
391 void
392 munputc(int p)
393 {
394 	*pushptr++ = peek;		/* watch out for this */
395 	peek = p;
396 	if(pushptr >= pushc+TOKENSIZE)
397 		error("Too many characters pushed");
398 }
399 
400 void
401 munputs(uchar *p)
402 {
403 	int i,j;
404 	*pushptr++ = peek;
405 	peek = p[0];
406 	i = strlen((char*)p);
407 	for(j = i-1; j>=1; j--)
408 		*pushptr++ = p[j];
409 	if(pushptr >= pushc+TOKENSIZE)
410 		error("Too many characters pushed");
411 }
412 
413 int
414 dupl(int n)
415 {
416 	/* duplicate the subtree whose root is n, return ptr to it */
417 	int i;
418 
419 	i = name[n];
420 	if(i < NCH) return(mn0(i));
421 	switch(i){
422 	case RNULLS:
423 		return(mn0(i));
424 	case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
425 		return(mn1(i,left[n]));
426 	case STAR: case QUEST: case PLUS: case CARAT:
427 		return(mn1(i,dupl(left[n])));
428 	case RSTR: case RSCON:
429 		return(mn2(i,dupl(left[n]),right[n]));
430 	case BAR: case RNEWE: case RCAT: case DIV:
431 		return(mn2(i,dupl(left[n]),dupl(right[n])));
432 # ifdef DEBUG
433 	default:
434 		warning("bad switch dupl %d",n);
435 # endif
436 	}
437 	return(0);
438 }
439 
440 # ifdef DEBUG
441 void
442 allprint(int c)
443 {
444 	switch(c){
445 		case 014:
446 			print("\\f");
447 			charc++;
448 			break;
449 		case '\n':
450 			print("\\n");
451 			charc++;
452 			break;
453 		case '\t':
454 			print("\\t");
455 			charc++;
456 			break;
457 		case '\b':
458 			print("\\b");
459 			charc++;
460 			break;
461 		case ' ':
462 			print("\\\bb");
463 			break;
464 		default:
465 			if(!isprint(c)){
466 				print("\\%-3o",c);
467 				charc += 3;
468 			} else
469 				print("%c", c);
470 			break;
471 	}
472 	charc++;
473 }
474 
475 void
476 strpt(uchar *s)
477 {
478 	charc = 0;
479 	while(*s){
480 		allprint(*s++);
481 		if(charc > LINESIZE){
482 			charc = 0;
483 			print("\n\t");
484 		}
485 	}
486 }
487 
488 void
489 sect1dump(void)
490 {
491 	int i;
492 
493 	print("Sect 1:\n");
494 	if(def[0]){
495 		print("str	trans\n");
496 		i = -1;
497 		while(def[++i])
498 			print("%s\t%s\n",def[i],subs[i]);
499 	}
500 	if(sname[0]){
501 		print("start names\n");
502 		i = -1;
503 		while(sname[++i])
504 			print("%s\n",sname[i]);
505 	}
506 }
507 
508 void
509 sect2dump(void)
510 {
511 	print("Sect 2:\n");
512 	treedump();
513 }
514 
515 void
516 treedump(void)
517 {
518 	int t;
519 	uchar *p;
520 	print("treedump %d nodes:\n",tptr);
521 	for(t=0;t<tptr;t++){
522 		print("%4d ",t);
523 		parent[t] ? print("p=%4d",parent[t]) : print("      ");
524 		print("  ");
525 		if(name[t] < NCH)
526 				allprint(name[t]);
527 		else switch(name[t]){
528 			case RSTR:
529 				print("%d ",left[t]);
530 				allprint(right[t]);
531 				break;
532 			case RCCL:
533 				print("ccl ");
534 				strpt(left[t]);
535 				break;
536 			case RNCCL:
537 				print("nccl ");
538 				strpt(left[t]);
539 				break;
540 			case DIV:
541 				print("/ %d %d",left[t],right[t]);
542 				break;
543 			case BAR:
544 				print("| %d %d",left[t],right[t]);
545 				break;
546 			case RCAT:
547 				print("cat %d %d",left[t],right[t]);
548 				break;
549 			case PLUS:
550 				print("+ %d",left[t]);
551 				break;
552 			case STAR:
553 				print("* %d",left[t]);
554 				break;
555 			case CARAT:
556 				print("^ %d",left[t]);
557 				break;
558 			case QUEST:
559 				print("? %d",left[t]);
560 				break;
561 			case RNULLS:
562 				print("nullstring");
563 				break;
564 			case FINAL:
565 				print("final %d",left[t]);
566 				break;
567 			case S1FINAL:
568 				print("s1final %d",left[t]);
569 				break;
570 			case S2FINAL:
571 				print("s2final %d",left[t]);
572 				break;
573 			case RNEWE:
574 				print("new %d %d",left[t],right[t]);
575 				break;
576 			case RSCON:
577 				p = (uchar *)right[t];
578 				print("start %s",sname[*p++-1]);
579 				while(*p)
580 					print(", %s",sname[*p++-1]);
581 				print(" %d",left[t]);
582 				break;
583 			default:
584 				print("unknown %d %d %d",name[t],left[t],right[t]);
585 				break;
586 		}
587 		if(nullstr[t])print("\t(null poss.)");
588 		print("\n");
589 	}
590 }
591 # endif
592