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