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