xref: /original-bsd/old/pcc/mip/scan.c (revision 804a2614)
1 #ifndef lint
2 static char *sccsid ="@(#)scan.c	2.16 (Berkeley) 09/15/89";
3 #endif lint
4 
5 # include "pass1.h"
6 # include <a.out.h>
7 # include <stab.h>
8 # include <ctype.h>
9 # include <signal.h>
10 
11 	/* temporarily */
12 
13 int asm_esc = 0; /* asm escaped used in file */
14 	/* lexical actions */
15 
16 # define A_ERR 0		/* illegal character */
17 # define A_LET 1		/* saw a letter */
18 # define A_DIG 2		/* saw a digit */
19 # define A_1C 3			/* return a single character */
20 # define A_STR 4		/* string */
21 # define A_CC 5			/* character constant */
22 # define A_BCD 6		/* GCOS BCD constant */
23 # define A_SL 7			/* saw a / */
24 # define A_DOT 8		/* saw a . */
25 # define A_PL 9		/* + */
26 # define A_MI 10		/* - */
27 # define A_EQ 11		/* = */
28 # define A_NOT 12		/* ! */
29 # define A_LT 13		/* < */
30 # define A_GT 14		/* > */
31 # define A_AND 16		/* & */
32 # define A_OR 17		/* | */
33 # define A_WS 18		/* whitespace (not \n) */
34 # define A_NL 19		/* \n */
35 
36 	/* character classes */
37 
38 # define LEXLET 01
39 # define LEXDIG 02
40 # define LEXOCT 04
41 # define LEXHEX 010
42 # define LEXWS 020
43 # define LEXDOT 040
44 
45 	/* reserved word actions */
46 
47 # define AR_TY 0		/* type word */
48 # define AR_RW 1		/* simple reserved word */
49 # define AR_CL 2		/* storage class word */
50 # define AR_S 3		/* struct */
51 # define AR_U 4		/* union */
52 # define AR_E 5		/* enum */
53 # define AR_A 6		/* asm */
54 
55 	/* text buffer */
56 #ifndef FLEXNAMES
57 # define LXTSZ 100
58 #else
59 #define	LXTSZ	BUFSIZ
60 #endif
61 char yytext[LXTSZ];
62 char * lxgcp;
63 
64 extern int proflg;
65 extern int gdebug;
66 extern void fpe();
67 struct sigvec fpe_sigvec;
68 int oldway;		/* allocate storage so lint will compile as well */
69 #ifndef LINT
70 extern int lastloc;
71 #endif
72 
73 unsigned caloff();
74 	/* ARGSUSED */
mainp1(argc,argv)75 mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
76 
77 	register i;
78 	register char *cp;
79 	extern int idebug, bdebug, tdebug, edebug;
80 	extern int ddebug, xdebug, gdebug, adebug;
81 	extern unsigned int offsz;
82 	int fdef = 0;
83 	extern char *release;
84 
85 	offsz = caloff();
86 	for( i=1; i<argc; ++i ){
87 		if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
88 			while( *++cp ){
89 				switch( *cp ){
90 
91 				case 'r':
92 					fprintf( stderr, "Release: %s\n",
93 						release );
94 					break;
95 
96 				case 'd':
97 					++ddebug;
98 					break;
99 				case 'i':
100 					++idebug;
101 					break;
102 				case 'b':
103 					++bdebug;
104 					break;
105 				case 't':
106 					++tdebug;
107 					break;
108 				case 'e':
109 					++edebug;
110 					break;
111 				case 'x':
112 					++xdebug;
113 					break;
114 				case 'P':	/* profiling */
115 					++proflg;
116 					break;
117 				case 'g':
118 					++gdebug;
119 					break;
120 				case 'a':
121 					++adebug;
122 					break;
123 				case 'G':
124 					++gdebug;
125 					oldway = 1;
126 					break;
127 					}
128 				}
129 			}
130 			else {
131 			if( *(argv[i]) != '-' ) switch( fdef++ ) {
132 				case 0:
133 				case 1:
134 					if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
135 						fprintf(stderr, "ccom:can't open %s\n", argv[i]);
136 						exit(1);
137 					}
138 					break;
139 
140 				default:
141 					;
142 				}
143 			}
144 		}
145 
146 # ifdef ONEPASS
147 	(void) p2init( argc, argv );
148 # endif
149 
150 	for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
151 
152 	lineno = 1;
153 
154 	lxinit();
155 	tinit();
156 	mkdope();
157 
158 	/* dimension table initialization */
159 
160 	dimtab[NULL] = 0;
161 	dimtab[CHAR] = SZCHAR;
162 	dimtab[INT] = SZINT;
163 	dimtab[FLOAT] = SZFLOAT;
164 	dimtab[DOUBLE] = SZDOUBLE;
165 	dimtab[LONG] = SZLONG;
166 	dimtab[SHORT] = SZSHORT;
167 	dimtab[UCHAR] = SZCHAR;
168 	dimtab[USHORT] = SZSHORT;
169 	dimtab[UNSIGNED] = SZINT;
170 	dimtab[ULONG] = SZLONG;
171 	/* starts past any of the above */
172 	curdim = 16;
173 	reached = 1;
174 
175 	fpe_sigvec.sv_handler = fpe;
176 	(void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL);
177 
178 	(void) yyparse();
179 	yyaccpt();
180 
181 	ejobcode( nerrors ? 1 : 0 );
182 	return(nerrors?1:0);
183 
184 	}
185 
186 # ifdef ibm
187 
188 # define CSMASK 0377
189 # define CSSZ 256
190 
191 # else
192 
193 # define CSMASK 0177
194 # define CSSZ 128
195 
196 # endif
197 
198 short lxmask[CSSZ+1];
199 
lxenter(s,m)200 lxenter( s, m ) register char *s; register short m; {
201 	/* enter a mask into lxmask */
202 	register c;
203 
204 	while( c= *s++ ) lxmask[c+1] |= m;
205 
206 	}
207 
208 
209 # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
210 
lxmore(c,m)211 lxmore( c, m )  register c, m; {
212 	register char *cp;
213 
214 	*(cp = lxgcp) = c;
215 	while( c=getchar(), lxmask[c+1]&m ){
216 		if( cp < &yytext[LXTSZ-1] ){
217 			*++cp = c;
218 			}
219 		}
220 	ungetc(c,stdin);
221 	*(lxgcp = cp+1) = '\0';
222 	}
223 
224 struct lxdope {
225 	short lxch;	/* the character */
226 	short lxact;	/* the action to be performed */
227 	short lxtok;	/* the token number to be returned */
228 	short lxval;	/* the value to be returned */
229 	} lxdope[] = {
230 
231 	'@',	A_ERR,	0,	0,	/* illegal characters go here... */
232 	'_',	A_LET,	0,	0,	/* letters point here */
233 	'0',	A_DIG,	0,	0,	/* digits point here */
234 	' ',	A_WS,	0,	0,	/* whitespace goes here */
235 	'\n',	A_NL,	0,	0,
236 	'"',	A_STR,	0,	0,	/* character string */
237 	'\'',	A_CC,	0,	0,	/* character constant */
238 #ifdef gcos
239 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
240 #endif
241 	'(',	A_1C,	LP,	0,
242 	')',	A_1C,	RP,	0,
243 	'{',	A_1C,	LC,	0,
244 	'}',	A_1C,	RC,	0,
245 	'[',	A_1C,	LB,	0,
246 	']',	A_1C,	RB,	0,
247 	'*',	A_1C,	MUL,	MUL,
248 	'?',	A_1C,	QUEST,	0,
249 	':',	A_1C,	COLON,	0,
250 	'+',	A_PL,	PLUS,	PLUS,
251 	'-',	A_MI,	MINUS,	MINUS,
252 	'/',	A_SL,	DIVOP,	DIV,
253 	'%',	A_1C,	DIVOP,	MOD,
254 	'&',	A_AND,	AND,	AND,
255 	'|',	A_OR,	OR,	OR,
256 	'^',	A_1C,	ER,	ER,
257 	'!',	A_NOT,	UNOP,	NOT,
258 	'~',	A_1C,	UNOP,	COMPL,
259 	',',	A_1C,	CM,	CM,
260 	';',	A_1C,	SM,	0,
261 	'.',	A_DOT,	STROP,	DOT,
262 	'<',	A_LT,	RELOP,	LT,
263 	'>',	A_GT,	RELOP,	GT,
264 	'=',	A_EQ,	ASSIGN,	ASSIGN,
265 	-1,	A_1C,	0,	0,
266 	};
267 
268 struct lxdope *lxcp[CSSZ+1];
269 
lxinit()270 lxinit(){
271 	register struct lxdope *p;
272 	register i;
273 	register char *cp;
274 	/* set up character classes */
275 
276 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
277 #ifdef VMS
278 	lxmask['$'+1] |= LEXLET;
279 #endif
280 	lxenter( "0123456789", LEXDIG );
281 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
282 	lxenter( " \t\r\b\f\v", LEXWS );
283 	lxenter( "01234567", LEXOCT );
284 	lxmask['.'+1] |= LEXDOT;
285 
286 	/* make lxcp point to appropriate lxdope entry for each character */
287 
288 	/* initialize error entries */
289 
290 	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
291 
292 	/* make unique entries */
293 
294 	for( p=lxdope; ; ++p ) {
295 		lxcp[p->lxch+1] = p;
296 		if( p->lxch < 0 ) break;
297 		}
298 
299 	/* handle letters, digits, and whitespace */
300 	/* by convention, first, second, and third places */
301 
302 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
303 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
304 #ifdef VMS
305 	lxcp['$'+1] = &lxdope[1];
306 #endif
307 	cp = "123456789";
308 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
309 	cp = "\t\b\r\f\v";
310 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
311 
312 	/* first line might have title */
313 	lxtitle();
314 
315 	}
316 
317 int lxmatch = 0;  /* character to be matched in char or string constant */
318 
lxstr(ct)319 lxstr(ct){
320 	/* match a string or character constant, up to lxmatch */
321 
322 	register c;
323 	register val;
324 	register i;
325 
326 	i=0;
327 	while( (c=getchar()) != lxmatch ){
328 		switch( c ) {
329 
330 		case EOF:
331 			uerror( "unexpected EOF" );
332 			break;
333 
334 		case '\n':
335 			uerror( "newline in string or char constant" );
336 			++lineno;
337 			break;
338 
339 		case '\\':
340 			switch( c = getchar() ){
341 
342 			case '\n':
343 				++lineno;
344 				continue;
345 
346 			default:
347 #ifdef LINT
348 				if( hflag )
349 					uerror( "superfluous backslash in %s constant", lxmatch == '\'' ? "char" : "string" );
350 				/*FALLTHROUGH*/
351 #endif
352 			case '\\':
353 			case '\"':
354 			case '\'':
355 				val = c;
356 				goto mkcc;
357 
358 			case 'n':
359 				val = '\n';
360 				goto mkcc;
361 
362 			case 'r':
363 				val = '\r';
364 				goto mkcc;
365 
366 			case 'b':
367 				val = '\b';
368 				goto mkcc;
369 
370 			case 't':
371 				val = '\t';
372 				goto mkcc;
373 
374 			case 'f':
375 				val = '\f';
376 				goto mkcc;
377 
378 			case 'v':
379 				val = '\v';
380 				goto mkcc;
381 
382 			case '0':
383 			case '1':
384 			case '2':
385 			case '3':
386 			case '4':
387 			case '5':
388 			case '6':
389 			case '7':
390 				val = c-'0';
391 				c=getchar();  /* try for 2 */
392 				if( lxmask[c+1] & LEXOCT ){
393 					val = (val<<3) | (c-'0');
394 					c = getchar();  /* try for 3 */
395 					if( lxmask[c+1] & LEXOCT ){
396 						val = (val<<3) | (c-'0');
397 						}
398 					else ungetc( c ,stdin);
399 					}
400 				else ungetc( c ,stdin);
401 
402 				goto mkcc1;
403 
404 				}
405 		default:
406 			val =c;
407 		mkcc:
408 			val = CCTRANS(val);
409 		mkcc1:
410 			if( lxmatch == '\'' ){
411 				val = CHARCAST(val);  /* it is, after all, a "character" constant */
412 				makecc( val, i );
413 				}
414 			else { /* stash the byte into the string */
415 				if( strflg ) {
416 					if( ct==0 || i<ct ) putbyte( val );
417 					else if( i == ct ) werror( "non-null byte ignored in string initializer" );
418 					}
419 				else bycode( val, i );
420 				}
421 			++i;
422 			continue;
423 			}
424 		break;
425 		}
426 	/* end of string or  char constant */
427 
428 	if( lxmatch == '"' ){
429 		if( strflg ){ /* end the string */
430 			if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
431 			}
432 		else {  /* the initializer gets a null byte */
433 			bycode( 0, i++ );
434 			bycode( -1, i );
435 			dimtab[curdim] = i;  /* in case of later sizeof ... */
436 			}
437 		}
438 	else { /* end the character constant */
439 		if( i == 0 ) uerror( "empty character constant" );
440 		if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
441 			uerror( "too many characters in character constant" );
442 		}
443 	lxmatch = 0;	/* handshake with yylex() */
444 	}
445 
lxcom()446 lxcom(){
447 	register c;
448 	/* saw a /*: process a comment */
449 
450 	for(;;){
451 
452 		switch( c = getchar() ){
453 
454 		case EOF:
455 			uerror( "unexpected EOF" );
456 			return;
457 
458 		case '\n':
459 			++lineno;
460 
461 		default:
462 			continue;
463 
464 		case '*':
465 			if( (c = getchar()) == '/' ) return;
466 			else ungetc( c ,stdin);
467 			continue;
468 
469 # ifdef LINT
470 		case 'V':
471 			lxget( c, LEXLET|LEXDIG );
472 			{
473 				extern int vaflag;
474 				int i;
475 				i = yytext[7]?yytext[7]-'0':0;
476 				yytext[7] = '\0';
477 				if( strcmp( yytext, "VARARGS" ) ) continue;
478 				vaflag = i;
479 				continue;
480 				}
481 		case 'L':
482 			lxget( c, LEXLET );
483 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
484 			{
485 				extern int libflag;
486 				libflag = 1;
487 				}
488 			continue;
489 
490 		case 'A':
491 			lxget( c, LEXLET );
492 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
493 			{
494 				extern int argflag, vflag;
495 				argflag = 1;
496 				vflag = 0;
497 				}
498 			continue;
499 
500 		case 'N':
501 			lxget( c, LEXLET );
502 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
503 			reached = 0;
504 			continue;
505 # endif
506 			}
507 		}
508 	}
509 
yylex()510 yylex(){
511 	double atof();
512 
513 	if (lxmatch != 0) {
514 		/* recover from a syntax error that consumes a STRING token */
515 		strflg = 1;
516 		lxstr(0);
517 	}
518 	for(;;){
519 
520 		register lxchar;
521 		register struct lxdope *p;
522 		register struct symtab *sp;
523 		int id;
524 		char *s;
525 		static char sc[5];
526 
527 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
528 
529 		onechar:
530 			ungetc( lxchar ,stdin);
531 
532 		case A_1C:
533 			/* eat up a single character, and return an opcode */
534 
535 			yylval.intval = p->lxval;
536 			return( p->lxtok );
537 
538 		case A_ERR:
539 			switch( lxchar ){
540 			case '\\':	s = "\\\\"; break;
541 			case '\0':	s = "\\0"; break;
542 			default:
543 				if( isgraph( lxchar ) ){
544 					sc[0] = lxchar;
545 					sc[1] = '\0';
546 					}
547 				else
548 					sprintf( sc, "\\%03.3o", (unsigned char) lxchar );
549 				s = sc;
550 				break;
551 				}
552 			uerror( "illegal character: '%s'", s );
553 			continue; /* ignore it and see if we find more */
554 
555 		case A_LET:
556 			/* collect an identifier, check for reserved word, and return */
557 			lxget( lxchar, LEXLET|LEXDIG );
558 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
559 			if( lxchar== 0 ) continue;
560 #ifdef FLEXNAMES
561 			id = lookup( hash(yytext),
562 #else
563 			id = lookup( yytext,
564 #endif
565 				/* tag name for struct/union/enum */
566 				(stwart&TAGNAME)? STAG:
567 				/* member name for struct/union */
568 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
569 			sp = &stab[id];
570 			if( sp->sclass == TYPEDEF && !stwart ){
571 				stwart = instruct;
572 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
573 				return( TYPE );
574 				}
575 			stwart = (stwart&SEENAME) ? instruct : 0;
576 			yylval.intval = id;
577 			return( NAME );
578 
579 		case A_DIG:
580 			/* collect a digit string, then look at last one... */
581 			lastcon = 0;
582 			lxget( lxchar, LEXDIG );
583 			switch( lxchar=getchar() ){
584 
585 			case 'x':
586 			case 'X':
587 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
588 				lxmore( lxchar, LEXHEX );
589 				/* convert the value */
590 				{
591 					register char *cp;
592 					for( cp = yytext+2; *cp; ++cp ){
593 						/* this code won't work for all wild character sets,
594 						   but seems ok for ascii and ebcdic */
595 						lastcon <<= 4;
596 						if( isdigit( *cp ) ) lastcon += *cp-'0';
597 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
598 						else lastcon += *cp - 'a'+ 10;
599 						}
600 					}
601 
602 			hexlong:
603 				/* criterion for longness for hex and octal constants is that it
604 				   fit within 0177777 */
605 				if( lastcon & ~0177777L ) yylval.intval = 1;
606 				else yylval.intval = 0;
607 
608 				goto islong;
609 
610 			case '.':
611 				lxmore( lxchar, LEXDIG );
612 
613 			getfp:
614 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
615 
616 			case 'e':
617 			case 'E':
618 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
619 						*lxgcp++ = 'e';
620 						}
621 					else {
622 						ungetc(lxchar,stdin);
623 						lxchar = 'e';
624 						}
625 					lxmore( lxchar, LEXDIG );
626 					/* now have the whole thing... */
627 					}
628 				else {  /* no exponent */
629 					ungetc( lxchar ,stdin);
630 					}
631 				dcon = atof( yytext );
632 				if( (lxchar = getchar()) == 'F' || lxchar == 'f' ){
633 					fcon = dcon;
634 					return( FCON );
635 					}
636 				else ungetc( lxchar ,stdin);
637 				return( DCON );
638 
639 			default:
640 				ungetc( lxchar ,stdin);
641 				if( yytext[0] == '0' ){
642 					/* convert in octal */
643 					register char *cp;
644 					for( cp = yytext+1; *cp; ++cp ){
645 						lastcon <<= 3;
646 						lastcon += *cp - '0';
647 						}
648 					goto hexlong;
649 					}
650 				else {
651 					/* convert in decimal */
652 					register char *cp;
653 					for( cp = yytext; *cp; ++cp ){
654 						lastcon = lastcon * 10 + *cp - '0';
655 						}
656 					}
657 
658 				/* decide if it is long or not (decimal case) */
659 
660 				/* if it is positive and fits in 15 bits, or negative and
661 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
662 				/* if there is an l or L following, all bets are off... */
663 
664 				{	CONSZ v;
665 					v = lastcon & ~077777L;
666 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
667 					else yylval.intval = 1;
668 					}
669 
670 			islong:
671 				/* finally, look for trailing L or l */
672 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
673 				else ungetc( lxchar ,stdin);
674 				return( ICON );
675 				}
676 
677 		case A_DOT:
678 			/* look for a dot: if followed by a digit, floating point */
679 			lxchar = getchar();
680 			if( lxmask[lxchar+1] & LEXDIG ){
681 				ungetc(lxchar,stdin);
682 				lxget( '.', LEXDIG );
683 				goto getfp;
684 				}
685 			stwart = FUNNYNAME;
686 			goto onechar;
687 
688 		case A_STR:
689 			/* string constant */
690 			lxmatch = '"';
691 			return( STRING );
692 
693 		case A_CC:
694 			/* character constant */
695 			lxmatch = '\'';
696 			lastcon = 0;
697 			lxstr(0);
698 			yylval.intval = 0;
699 			return( ICON );
700 
701 #ifdef gcos
702 		case A_BCD:
703 			{
704 				register i;
705 				int j;
706 				for( i=0; i<LXTSZ; ++i ){
707 					if( ( j = getchar() ) == '`' ) break;
708 					if( j == '\n' ){
709 						uerror( "newline in BCD constant" );
710 						break;
711 						}
712 					yytext[i] = j;
713 					}
714 				yytext[i] = '\0';
715 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
716 # ifndef unix
717 				else strtob( yytext, &lastcon, i );
718 				lastcon >>= 6*(6-i);
719 # else
720 				uerror( "gcos BCD constant illegal" );
721 # endif
722 				yylval.intval = 0;  /* not long */
723 				return( ICON );
724 				}
725 #endif
726 
727 		case A_SL:
728 			/* / */
729 			if( (lxchar=getchar()) != '*' ) goto onechar;
730 			lxcom();
731 		case A_WS:
732 			continue;
733 
734 		case A_NL:
735 			++lineno;
736 			lxtitle();
737 			continue;
738 
739 		case A_NOT:
740 			/* ! */
741 			if( (lxchar=getchar()) != '=' ) goto onechar;
742 			yylval.intval = NE;
743 			return( EQUOP );
744 
745 		case A_MI:
746 			/* - */
747 			if( (lxchar=getchar()) == '-' ){
748 				yylval.intval = DECR;
749 				return( INCOP );
750 				}
751 			if( lxchar != '>' ) goto onechar;
752 			stwart = FUNNYNAME;
753 			yylval.intval=STREF;
754 			return( STROP );
755 
756 		case A_PL:
757 			/* + */
758 			if( (lxchar=getchar()) != '+' ) goto onechar;
759 			yylval.intval = INCR;
760 			return( INCOP );
761 
762 		case A_AND:
763 			/* & */
764 			if( (lxchar=getchar()) != '&' ) goto onechar;
765 			return( yylval.intval = ANDAND );
766 
767 		case A_OR:
768 			/* | */
769 			if( (lxchar=getchar()) != '|' ) goto onechar;
770 			return( yylval.intval = OROR );
771 
772 		case A_LT:
773 			/* < */
774 			if( (lxchar=getchar()) == '<' ){
775 				yylval.intval = LS;
776 				return( SHIFTOP );
777 				}
778 			if( lxchar != '=' ) goto onechar;
779 			yylval.intval = LE;
780 			return( RELOP );
781 
782 		case A_GT:
783 			/* > */
784 			if( (lxchar=getchar()) == '>' ){
785 				yylval.intval = RS;
786 				return(SHIFTOP );
787 				}
788 			if( lxchar != '=' ) goto onechar;
789 			yylval.intval = GE;
790 			return( RELOP );
791 
792 		case A_EQ:
793 			/* = */
794 			switch( lxchar = getchar() ){
795 
796 			case '=':
797 				yylval.intval = EQ;
798 				return( EQUOP );
799 
800 #ifdef old_assignment_ops
801 			case '+':
802 				yylval.intval = ASG PLUS;
803 				break;
804 
805 			case '-':
806 				yylval.intval = ASG MINUS;
807 
808 			warn:
809 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
810 					werror( "ambiguous assignment: assignment op taken" );
811 					}
812 				ungetc( lxchar ,stdin);
813 				break;
814 
815 			case '*':
816 				yylval.intval = ASG MUL;
817 				goto warn;
818 
819 			case '/':
820 				yylval.intval = ASG DIV;
821 				break;
822 
823 			case '%':
824 				yylval.intval = ASG MOD;
825 				break;
826 
827 			case '&':
828 				yylval.intval = ASG AND;
829 				break;
830 
831 			case '|':
832 				yylval.intval = ASG OR;
833 				break;
834 
835 			case '^':
836 				yylval.intval = ASG ER;
837 				break;
838 
839 			case '<':
840 				if( (lxchar=getchar()) != '<' ){
841 					uerror( "=<%c illegal", lxchar );
842 					}
843 				yylval.intval = ASG LS;
844 				break;
845 
846 			case '>':
847 				if( (lxchar=getchar()) != '>' ){
848 					uerror( "=>%c illegal", lxchar );
849 					}
850 				yylval.intval = ASG RS;
851 				break;
852 #endif old_assignment_ops
853 
854 			default:
855 				goto onechar;
856 
857 				}
858 
859 #ifdef old_assignment_ops	/* defeat 'unreachable code' warning */
860 			return( ASOP );
861 #endif old_assignment_ops
862 
863 		default:
864 			cerror( "yylex error, character %03o (octal)", lxchar );
865 
866 			}
867 
868 		/* ordinarily, repeat here... */
869 		cerror( "out of switch in yylex" );
870 
871 		}
872 
873 	}
874 
875 struct lxrdope {
876 	/* dope for reserved, in alphabetical order */
877 
878 	char *lxrch;	/* name of reserved word */
879 	short lxract;	/* reserved word action */
880 	short lxrval;	/* value to be returned */
881 	} lxrdope[] = {
882 
883 	"asm",		AR_A,	0,
884 	"auto",		AR_CL,	AUTO,
885 	"break",	AR_RW,	BREAK,
886 	"char",		AR_TY,	CHAR,
887 	"case",		AR_RW,	CASE,
888 	"continue",	AR_RW,	CONTINUE,
889 	"double",	AR_TY,	DOUBLE,
890 	"default",	AR_RW,	DEFAULT,
891 	"do",		AR_RW,	DO,
892 	"extern",	AR_CL,	EXTERN,
893 	"else",		AR_RW,	ELSE,
894 	"enum",		AR_E,	ENUM,
895 	"for",		AR_RW,	FOR,
896 	"float",	AR_TY,	FLOAT,
897 	"fortran",	AR_CL,	FORTRAN,
898 	"goto",		AR_RW,	GOTO,
899 	"if",		AR_RW,	IF,
900 	"int",		AR_TY,	INT,
901 	"long",		AR_TY,	LONG,
902 	"return",	AR_RW,	RETURN,
903 	"register",	AR_CL,	REGISTER,
904 	"switch",	AR_RW,	SWITCH,
905 	"struct",	AR_S,	0,
906 	"sizeof",	AR_RW,	SIZEOF,
907 	"short",	AR_TY,	SHORT,
908 	"static",	AR_CL,	STATIC,
909 	"typedef",	AR_CL,	TYPEDEF,
910 	"unsigned",	AR_TY,	UNSIGNED,
911 	"union",	AR_U,	0,
912 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
913 	"while",	AR_RW,	WHILE,
914 	"",		0,	0,	/* to stop the search */
915 	};
916 
lxres()917 lxres() {
918 	/* check to see of yytext is reserved; if so,
919 	/* do the appropriate action and return */
920 	/* otherwise, return -1 */
921 
922 	register c, ch;
923 	register struct lxrdope *p;
924 
925 	ch = yytext[0];
926 
927 	if( !islower(ch) ) return( -1 );
928 
929 	switch( ch ){
930 
931 	case 'a':
932 		c=0; break;
933 	case 'b':
934 		c=2; break;
935 	case 'c':
936 		c=3; break;
937 	case 'd':
938 		c=6; break;
939 	case 'e':
940 		c=9; break;
941 	case 'f':
942 		c=12; break;
943 	case 'g':
944 		c=15; break;
945 	case 'i':
946 		c=16; break;
947 	case 'l':
948 		c=18; break;
949 	case 'r':
950 		c=19; break;
951 	case 's':
952 		c=21; break;
953 	case 't':
954 		c=26; break;
955 	case 'u':
956 		c=27; break;
957 	case 'v':
958 		c=29; break;
959 	case 'w':
960 		c=30; break;
961 
962 	default:
963 		return( -1 );
964 		}
965 
966 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
967 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
968 			switch( p->lxract ){
969 
970 			case AR_TY:
971 				/* type word */
972 				stwart = instruct;
973 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
974 				return( TYPE );
975 
976 			case AR_RW:
977 				/* ordinary reserved word */
978 				return( yylval.intval = p->lxrval );
979 
980 			case AR_CL:
981 				/* class word */
982 				yylval.intval = p->lxrval;
983 				return( CLASS );
984 
985 			case AR_S:
986 				/* struct */
987 				stwart = INSTRUCT|SEENAME|TAGNAME;
988 				yylval.intval = INSTRUCT;
989 				return( STRUCT );
990 
991 			case AR_U:
992 				/* union */
993 				stwart = INUNION|SEENAME|TAGNAME;
994 				yylval.intval = INUNION;
995 				return( STRUCT );
996 
997 			case AR_E:
998 				/* enums */
999 				stwart = SEENAME|TAGNAME;
1000 				return( yylval.intval = ENUM );
1001 
1002 			case AR_A:
1003 				/* asm */
1004 				asm_esc = 1; /* warn the world! */
1005 				lxget( ' ', LEXWS );
1006 				if( getchar() != '(' ) goto badasm;
1007 				lxget( ' ', LEXWS );
1008 				if( getchar() != '"' ) goto badasm;
1009 # ifndef ONEPASS
1010 # ifndef LINT
1011 				putchar(')');
1012 # endif
1013 # endif
1014 				while( (c=getchar()) != '"' ){
1015 					if( c=='\n' || c==EOF ) goto badasm;
1016 # ifndef LINT
1017 					putchar(c);
1018 # endif
1019 					}
1020 				lxget( ' ', LEXWS );
1021 				if( getchar() != ')' ) goto badasm;
1022 # ifndef LINT
1023 				putchar('\n');
1024 # endif
1025 				return( 0 );
1026 
1027 			badasm:
1028 				uerror( "bad asm construction" );
1029 				return( 0 );
1030 
1031 			default:
1032 				cerror( "bad AR_?? action" );
1033 				}
1034 			}
1035 		}
1036 	return( -1 );
1037 	}
1038 
1039 extern int	labelno;
1040 
lxtitle()1041 lxtitle(){
1042 	/* called after a newline; set linenumber and file name */
1043 
1044 	register c, val;
1045 	register char *cp, *cq;
1046 
1047 	for(;;){  /* might be several such lines in a row */
1048 		if( (c=getchar()) != '#' ){
1049 			if( c != EOF ) ungetc(c,stdin);
1050 #ifndef LINT
1051 			if ( lastloc != PROG) return;
1052 			cp = ftitle;
1053 			cq = ititle;
1054 			while ( *cp ) if (*cp++ != *cq++) return;
1055 			if ( *cq ) return;
1056 			if( nerrors == 0 ) psline();
1057 #endif
1058 			return;
1059 			}
1060 
1061 		lxget( ' ', LEXWS );
1062 		c = getchar();
1063 		if( c == 'i' ){
1064 			/* #ident -- currently a no-op */
1065 			lxget( c, LEXLET );
1066 			if( strcmp( yytext, "ident" ) )
1067 				werror( "%s: undefined control", yytext );
1068 			while( (c = getchar()) != '\n' && c != EOF )
1069 				;
1070 			continue;
1071 			}
1072 		if( c == 'p' ){
1073 			/* #pragma -- special instructions */
1074 			lxget( c, LEXLET );
1075 			if( strcmp( yytext, "pragma" ) ) {
1076 				werror( "%s: undefined control", yytext );
1077 				while( (c = getchar()) != '\n' && c != EOF )
1078 					;
1079 				continue;
1080 				}
1081 			lxget( ' ' , LEXWS );
1082 			switch( c = getchar() ){
1083 # ifdef LINT
1084 			case 'V':
1085 				lxget( c, LEXLET|LEXDIG );
1086 				{
1087 					extern int vaflag;
1088 					int i;
1089 					i = yytext[7]?yytext[7]-'0':0;
1090 					yytext[7] = '\0';
1091 					if( strcmp( yytext, "VARARGS" ) ) break;
1092 					vaflag = i;
1093 					break;
1094 					}
1095 			case 'L':
1096 				lxget( c, LEXLET );
1097 				if( strcmp( yytext, "LINTLIBRARY" ) ) break;
1098 				{
1099 					extern int libflag;
1100 					libflag = 1;
1101 					}
1102 				break;
1103 
1104 			case 'A':
1105 				lxget( c, LEXLET );
1106 				if( strcmp( yytext, "ARGSUSED" ) ) break;
1107 				{
1108 					extern int argflag, vflag;
1109 					argflag = 1;
1110 					vflag = 0;
1111 					}
1112 				break;
1113 
1114 			case 'N':
1115 				lxget( c, LEXLET );
1116 				if( strcmp( yytext, "NOTREACHED" ) ) break;
1117 				reached = 0;
1118 				break;
1119 #endif
1120 
1121 			case '\n':
1122 			case EOF:
1123 				continue;
1124 				}
1125 			while( (c = getchar()) != '\n' && c != EOF )
1126 				;
1127 			continue;
1128 			}
1129 		if( c == 'l' ){
1130 			/* #line -- just like # */
1131 			lxget( c, LEXLET );
1132 			if( strcmp( yytext, "line" ) ){
1133 				werror( "%s: undefined control", yytext );
1134 				while( (c = getchar()) != '\n' && c != EOF )
1135 					;
1136 				continue;
1137 				}
1138 			lxget( ' ', LEXWS );
1139 			c = getchar();
1140 			}
1141 		if( !isdigit(c) ){
1142 			if( isalpha(c) ){
1143 				lxget( c, LEXLET );
1144 				werror( "%s: undefined control", yytext );
1145 				}
1146 			while( c != '\n' && c != EOF )
1147 				c = getchar();
1148 			continue;
1149 			}
1150 
1151 		val = 0;
1152 		do {
1153 			val = val*10+ c - '0';
1154 			}
1155 		while( isdigit( c = getchar() ) );
1156 
1157 		if( c == EOF )
1158 			continue;
1159 		ungetc( c, stdin );
1160 		lineno = val;
1161 		lxget( ' ', LEXWS );
1162 		if( (c=getchar()) != '\n' && c != EOF ){
1163 			for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
1164 				*cp = c;
1165 				}
1166 			*cp = '\0';
1167 #ifndef LINT
1168 			if (ititle[0] == '\0') {
1169 				cp = ftitle;
1170 				cq = ititle;
1171 				while ( *cp )
1172 					*cq++ = *cp++;
1173 				*cq = '\0';
1174 				*--cq = '\0';
1175 #ifndef FLEXNAMES
1176 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
1177 					pstab(cp, N_SO);
1178 					if (gdebug) printf("0,0,LL%d\n", labelno);
1179 					}
1180 #else
1181 				pstab(ititle+1, N_SO);
1182 				if (gdebug) printf("0,0,LL%d\n", labelno);
1183 #endif
1184 
1185 				*cq = '"';
1186 				printf("LL%d:\n", labelno++);
1187 				}
1188 #endif
1189 			}
1190 		}
1191 	}
1192 
1193 #ifdef FLEXNAMES
1194 #define	NSAVETAB	4096
1195 char	*savetab;
1196 unsigned saveleft;
1197 char	*malloc();
1198 char	*calloc();
1199 char	*strncpy();
1200 
1201 char *
savestr(cp)1202 savestr(cp)
1203 	register char *cp;
1204 {
1205 	register int len;
1206 
1207 	len = strlen(cp) + 1;
1208 	if (len > saveleft) {
1209 		saveleft = NSAVETAB;
1210 		if (len > saveleft)
1211 			saveleft = len;
1212 		savetab = malloc(saveleft);
1213 		if (savetab == 0)
1214 			cerror("Ran out of memory (savestr)");
1215 	}
1216 	(void) strncpy(savetab, cp, len);
1217 	cp = savetab;
1218 	savetab += len;
1219 	saveleft -= len;
1220 	return (cp);
1221 }
1222 
1223 /*
1224  * The definition for the segmented hash tables.
1225  */
1226 #define	MAXHASH	20
1227 #define	HASHINC	1013
1228 struct ht {
1229 	char	**ht_low;
1230 	char	**ht_high;
1231 	int	ht_used;
1232 } htab[MAXHASH];
1233 
1234 char *
hash(s)1235 hash(s)
1236 	char *s;
1237 {
1238 	register char **h;
1239 	register i;
1240 	register char *cp;
1241 	struct ht *htp;
1242 	int sh;
1243 
1244 	/*
1245 	 * The hash function is a modular hash of
1246 	 * the sum of the characters with the sum
1247 	 * doubled before each successive character
1248 	 * is added.
1249 	 */
1250 	cp = s;
1251 	i = 0;
1252 	while (*cp)
1253 		i = i*2 + *cp++;
1254 	sh = (i&077777) % HASHINC;
1255 	cp = s;
1256 	/*
1257 	 * There are as many as MAXHASH active
1258 	 * hash tables at any given point in time.
1259 	 * The search starts with the first table
1260 	 * and continues through the active tables
1261 	 * as necessary.
1262 	 */
1263 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
1264 		if (htp->ht_low == 0) {
1265 			register char **hp =
1266 			    (char **) calloc(sizeof (char **), HASHINC);
1267 			if (hp == 0)
1268 				cerror("ran out of memory (hash)");
1269 			htp->ht_low = hp;
1270 			htp->ht_high = htp->ht_low + HASHINC;
1271 		}
1272 		h = htp->ht_low + sh;
1273 		/*
1274 		 * quadratic rehash increment
1275 		 * starts at 1 and incremented
1276 		 * by two each rehash.
1277 		 */
1278 		i = 1;
1279 		do {
1280 			if (*h == 0) {
1281 				if (htp->ht_used > (HASHINC * 3)/4)
1282 					break;
1283 				htp->ht_used++;
1284 				*h = savestr(cp);
1285 				return (*h);
1286 			}
1287 			if (**h == *cp && strcmp(*h, cp) == 0)
1288 				return (*h);
1289 			h += i;
1290 			i += 2;
1291 			if (h >= htp->ht_high)
1292 				h -= HASHINC;
1293 		} while (i < HASHINC);
1294 	}
1295 	cerror("ran out of hash tables");
1296 	/*NOTREACHED*/
1297 }
1298 #endif
1299