xref: /csrg-svn/old/pcc/mip/scan.c (revision 39158)
117748Sralph #ifndef lint
2*39158Sbostic static char *sccsid ="@(#)scan.c	2.16 (Berkeley) 09/15/89";
317748Sralph #endif lint
417748Sralph 
518395Sralph # include "pass1.h"
69813Slinton # include <a.out.h>
79813Slinton # include <stab.h>
89813Slinton # include <ctype.h>
924407Smckusick # include <signal.h>
1024407Smckusick 
119813Slinton 	/* temporarily */
129813Slinton 
139813Slinton int asm_esc = 0; /* asm escaped used in file */
149813Slinton 	/* lexical actions */
159813Slinton 
169813Slinton # define A_ERR 0		/* illegal character */
179813Slinton # define A_LET 1		/* saw a letter */
189813Slinton # define A_DIG 2		/* saw a digit */
199813Slinton # define A_1C 3			/* return a single character */
209813Slinton # define A_STR 4		/* string */
219813Slinton # define A_CC 5			/* character constant */
229813Slinton # define A_BCD 6		/* GCOS BCD constant */
239813Slinton # define A_SL 7			/* saw a / */
249813Slinton # define A_DOT 8		/* saw a . */
259813Slinton # define A_PL 9		/* + */
269813Slinton # define A_MI 10		/* - */
279813Slinton # define A_EQ 11		/* = */
289813Slinton # define A_NOT 12		/* ! */
299813Slinton # define A_LT 13		/* < */
309813Slinton # define A_GT 14		/* > */
319813Slinton # define A_AND 16		/* & */
329813Slinton # define A_OR 17		/* | */
339813Slinton # define A_WS 18		/* whitespace (not \n) */
349813Slinton # define A_NL 19		/* \n */
359813Slinton 
369813Slinton 	/* character classes */
379813Slinton 
389813Slinton # define LEXLET 01
399813Slinton # define LEXDIG 02
409813Slinton # define LEXOCT 04
419813Slinton # define LEXHEX 010
429813Slinton # define LEXWS 020
439813Slinton # define LEXDOT 040
449813Slinton 
459813Slinton 	/* reserved word actions */
469813Slinton 
479813Slinton # define AR_TY 0		/* type word */
489813Slinton # define AR_RW 1		/* simple reserved word */
499813Slinton # define AR_CL 2		/* storage class word */
509813Slinton # define AR_S 3		/* struct */
519813Slinton # define AR_U 4		/* union */
529813Slinton # define AR_E 5		/* enum */
539813Slinton # define AR_A 6		/* asm */
549813Slinton 
559813Slinton 	/* text buffer */
569813Slinton #ifndef FLEXNAMES
579813Slinton # define LXTSZ 100
589813Slinton #else
599813Slinton #define	LXTSZ	BUFSIZ
609813Slinton #endif
619813Slinton char yytext[LXTSZ];
629813Slinton char * lxgcp;
639813Slinton 
649813Slinton extern int proflg;
659813Slinton extern int gdebug;
66*39158Sbostic extern void fpe();
6724407Smckusick struct sigvec fpe_sigvec;
689905Ssam int oldway;		/* allocate storage so lint will compile as well */
699813Slinton #ifndef LINT
709813Slinton extern int lastloc;
719813Slinton #endif
729813Slinton 
739813Slinton unsigned caloff();
749813Slinton 	/* ARGSUSED */
mainp1(argc,argv)759813Slinton mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
769813Slinton 
779813Slinton 	register i;
789813Slinton 	register char *cp;
7917748Sralph 	extern int idebug, bdebug, tdebug, edebug;
8017748Sralph 	extern int ddebug, xdebug, gdebug, adebug;
819813Slinton 	extern unsigned int offsz;
829813Slinton 	int fdef = 0;
8332835Sdonn 	extern char *release;
849813Slinton 
859813Slinton 	offsz = caloff();
869813Slinton 	for( i=1; i<argc; ++i ){
879813Slinton 		if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
889813Slinton 			while( *++cp ){
899813Slinton 				switch( *cp ){
909813Slinton 
919813Slinton 				case 'r':
929813Slinton 					fprintf( stderr, "Release: %s\n",
939813Slinton 						release );
949813Slinton 					break;
959813Slinton 
969813Slinton 				case 'd':
979813Slinton 					++ddebug;
989813Slinton 					break;
999813Slinton 				case 'i':
1009813Slinton 					++idebug;
1019813Slinton 					break;
1029813Slinton 				case 'b':
1039813Slinton 					++bdebug;
1049813Slinton 					break;
1059813Slinton 				case 't':
1069813Slinton 					++tdebug;
1079813Slinton 					break;
1089813Slinton 				case 'e':
1099813Slinton 					++edebug;
1109813Slinton 					break;
1119813Slinton 				case 'x':
1129813Slinton 					++xdebug;
1139813Slinton 					break;
1149813Slinton 				case 'P':	/* profiling */
1159813Slinton 					++proflg;
1169813Slinton 					break;
1179813Slinton 				case 'g':
1189813Slinton 					++gdebug;
1199813Slinton 					break;
12017748Sralph 				case 'a':
12117748Sralph 					++adebug;
12217748Sralph 					break;
1239816Slinton 				case 'G':
1249816Slinton 					++gdebug;
1259816Slinton 					oldway = 1;
1269816Slinton 					break;
1279813Slinton 					}
1289813Slinton 				}
1299813Slinton 			}
1309813Slinton 			else {
1319813Slinton 			if( *(argv[i]) != '-' ) switch( fdef++ ) {
1329813Slinton 				case 0:
1339813Slinton 				case 1:
1349813Slinton 					if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
1359813Slinton 						fprintf(stderr, "ccom:can't open %s\n", argv[i]);
1369813Slinton 						exit(1);
1379813Slinton 					}
1389813Slinton 					break;
1399813Slinton 
1409813Slinton 				default:
1419813Slinton 					;
1429813Slinton 				}
1439813Slinton 			}
1449813Slinton 		}
1459813Slinton 
1469813Slinton # ifdef ONEPASS
14732836Sdonn 	(void) p2init( argc, argv );
1489813Slinton # endif
1499813Slinton 
1509813Slinton 	for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
1519813Slinton 
15217601Sralph 	lineno = 1;
15317601Sralph 
1549813Slinton 	lxinit();
1559813Slinton 	tinit();
1569813Slinton 	mkdope();
1579813Slinton 
1589813Slinton 	/* dimension table initialization */
1599813Slinton 
1609813Slinton 	dimtab[NULL] = 0;
1619813Slinton 	dimtab[CHAR] = SZCHAR;
1629813Slinton 	dimtab[INT] = SZINT;
1639813Slinton 	dimtab[FLOAT] = SZFLOAT;
1649813Slinton 	dimtab[DOUBLE] = SZDOUBLE;
1659813Slinton 	dimtab[LONG] = SZLONG;
1669813Slinton 	dimtab[SHORT] = SZSHORT;
1679813Slinton 	dimtab[UCHAR] = SZCHAR;
1689813Slinton 	dimtab[USHORT] = SZSHORT;
1699813Slinton 	dimtab[UNSIGNED] = SZINT;
1709813Slinton 	dimtab[ULONG] = SZLONG;
1719813Slinton 	/* starts past any of the above */
1729813Slinton 	curdim = 16;
1739813Slinton 	reached = 1;
1749813Slinton 
17524407Smckusick 	fpe_sigvec.sv_handler = fpe;
17624407Smckusick 	(void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL);
17724407Smckusick 
17832836Sdonn 	(void) yyparse();
1799813Slinton 	yyaccpt();
1809813Slinton 
1819813Slinton 	ejobcode( nerrors ? 1 : 0 );
1829813Slinton 	return(nerrors?1:0);
1839813Slinton 
1849813Slinton 	}
1859813Slinton 
1869813Slinton # ifdef ibm
1879813Slinton 
1889813Slinton # define CSMASK 0377
1899813Slinton # define CSSZ 256
1909813Slinton 
1919813Slinton # else
1929813Slinton 
1939813Slinton # define CSMASK 0177
1949813Slinton # define CSSZ 128
1959813Slinton 
1969813Slinton # endif
1979813Slinton 
1989813Slinton short lxmask[CSSZ+1];
1999813Slinton 
lxenter(s,m)2009813Slinton lxenter( s, m ) register char *s; register short m; {
2019813Slinton 	/* enter a mask into lxmask */
2029813Slinton 	register c;
2039813Slinton 
2049813Slinton 	while( c= *s++ ) lxmask[c+1] |= m;
2059813Slinton 
2069813Slinton 	}
2079813Slinton 
2089813Slinton 
2099813Slinton # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
2109813Slinton 
lxmore(c,m)2119813Slinton lxmore( c, m )  register c, m; {
2129813Slinton 	register char *cp;
2139813Slinton 
2149813Slinton 	*(cp = lxgcp) = c;
2159813Slinton 	while( c=getchar(), lxmask[c+1]&m ){
2169813Slinton 		if( cp < &yytext[LXTSZ-1] ){
2179813Slinton 			*++cp = c;
2189813Slinton 			}
2199813Slinton 		}
2209813Slinton 	ungetc(c,stdin);
2219813Slinton 	*(lxgcp = cp+1) = '\0';
2229813Slinton 	}
2239813Slinton 
2249813Slinton struct lxdope {
2259813Slinton 	short lxch;	/* the character */
2269813Slinton 	short lxact;	/* the action to be performed */
2279813Slinton 	short lxtok;	/* the token number to be returned */
2289813Slinton 	short lxval;	/* the value to be returned */
2299813Slinton 	} lxdope[] = {
2309813Slinton 
2319813Slinton 	'@',	A_ERR,	0,	0,	/* illegal characters go here... */
2329813Slinton 	'_',	A_LET,	0,	0,	/* letters point here */
2339813Slinton 	'0',	A_DIG,	0,	0,	/* digits point here */
2349813Slinton 	' ',	A_WS,	0,	0,	/* whitespace goes here */
2359813Slinton 	'\n',	A_NL,	0,	0,
2369813Slinton 	'"',	A_STR,	0,	0,	/* character string */
2379813Slinton 	'\'',	A_CC,	0,	0,	/* character constant */
23832838Sdonn #ifdef gcos
2399813Slinton 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
24032838Sdonn #endif
2419813Slinton 	'(',	A_1C,	LP,	0,
2429813Slinton 	')',	A_1C,	RP,	0,
2439813Slinton 	'{',	A_1C,	LC,	0,
2449813Slinton 	'}',	A_1C,	RC,	0,
2459813Slinton 	'[',	A_1C,	LB,	0,
2469813Slinton 	']',	A_1C,	RB,	0,
2479813Slinton 	'*',	A_1C,	MUL,	MUL,
2489813Slinton 	'?',	A_1C,	QUEST,	0,
2499813Slinton 	':',	A_1C,	COLON,	0,
2509813Slinton 	'+',	A_PL,	PLUS,	PLUS,
2519813Slinton 	'-',	A_MI,	MINUS,	MINUS,
2529813Slinton 	'/',	A_SL,	DIVOP,	DIV,
2539813Slinton 	'%',	A_1C,	DIVOP,	MOD,
2549813Slinton 	'&',	A_AND,	AND,	AND,
2559813Slinton 	'|',	A_OR,	OR,	OR,
2569813Slinton 	'^',	A_1C,	ER,	ER,
2579813Slinton 	'!',	A_NOT,	UNOP,	NOT,
2589813Slinton 	'~',	A_1C,	UNOP,	COMPL,
2599813Slinton 	',',	A_1C,	CM,	CM,
2609813Slinton 	';',	A_1C,	SM,	0,
2619813Slinton 	'.',	A_DOT,	STROP,	DOT,
2629813Slinton 	'<',	A_LT,	RELOP,	LT,
2639813Slinton 	'>',	A_GT,	RELOP,	GT,
2649813Slinton 	'=',	A_EQ,	ASSIGN,	ASSIGN,
2659813Slinton 	-1,	A_1C,	0,	0,
2669813Slinton 	};
2679813Slinton 
2689813Slinton struct lxdope *lxcp[CSSZ+1];
2699813Slinton 
lxinit()2709813Slinton lxinit(){
2719813Slinton 	register struct lxdope *p;
2729813Slinton 	register i;
2739813Slinton 	register char *cp;
2749813Slinton 	/* set up character classes */
2759813Slinton 
27632838Sdonn 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
27732838Sdonn #ifdef VMS
27832838Sdonn 	lxmask['$'+1] |= LEXLET;
27932838Sdonn #endif
2809813Slinton 	lxenter( "0123456789", LEXDIG );
2819813Slinton 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
28232838Sdonn 	lxenter( " \t\r\b\f\v", LEXWS );
2839813Slinton 	lxenter( "01234567", LEXOCT );
2849813Slinton 	lxmask['.'+1] |= LEXDOT;
2859813Slinton 
2869813Slinton 	/* make lxcp point to appropriate lxdope entry for each character */
2879813Slinton 
2889813Slinton 	/* initialize error entries */
2899813Slinton 
2909813Slinton 	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
2919813Slinton 
2929813Slinton 	/* make unique entries */
2939813Slinton 
2949813Slinton 	for( p=lxdope; ; ++p ) {
2959813Slinton 		lxcp[p->lxch+1] = p;
2969813Slinton 		if( p->lxch < 0 ) break;
2979813Slinton 		}
2989813Slinton 
2999813Slinton 	/* handle letters, digits, and whitespace */
3009813Slinton 	/* by convention, first, second, and third places */
3019813Slinton 
30232838Sdonn 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
3039813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
30432838Sdonn #ifdef VMS
30532838Sdonn 	lxcp['$'+1] = &lxdope[1];
30632838Sdonn #endif
3079813Slinton 	cp = "123456789";
3089813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
30932838Sdonn 	cp = "\t\b\r\f\v";
3109813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
3119813Slinton 
3129813Slinton 	/* first line might have title */
3139813Slinton 	lxtitle();
3149813Slinton 
3159813Slinton 	}
3169813Slinton 
31732837Sdonn int lxmatch = 0;  /* character to be matched in char or string constant */
3189813Slinton 
lxstr(ct)3199813Slinton lxstr(ct){
3209813Slinton 	/* match a string or character constant, up to lxmatch */
3219813Slinton 
3229813Slinton 	register c;
3239813Slinton 	register val;
3249813Slinton 	register i;
3259813Slinton 
3269813Slinton 	i=0;
3279813Slinton 	while( (c=getchar()) != lxmatch ){
3289813Slinton 		switch( c ) {
3299813Slinton 
3309813Slinton 		case EOF:
3319813Slinton 			uerror( "unexpected EOF" );
3329813Slinton 			break;
3339813Slinton 
3349813Slinton 		case '\n':
3359813Slinton 			uerror( "newline in string or char constant" );
3369813Slinton 			++lineno;
3379813Slinton 			break;
3389813Slinton 
3399813Slinton 		case '\\':
3409813Slinton 			switch( c = getchar() ){
3419813Slinton 
3429813Slinton 			case '\n':
3439813Slinton 				++lineno;
3449813Slinton 				continue;
3459813Slinton 
3469813Slinton 			default:
34732838Sdonn #ifdef LINT
34832838Sdonn 				if( hflag )
34932838Sdonn 					uerror( "superfluous backslash in %s constant", lxmatch == '\'' ? "char" : "string" );
35032838Sdonn 				/*FALLTHROUGH*/
35132838Sdonn #endif
35232838Sdonn 			case '\\':
35332838Sdonn 			case '\"':
35432838Sdonn 			case '\'':
3559813Slinton 				val = c;
3569813Slinton 				goto mkcc;
3579813Slinton 
3589813Slinton 			case 'n':
3599813Slinton 				val = '\n';
3609813Slinton 				goto mkcc;
3619813Slinton 
3629813Slinton 			case 'r':
3639813Slinton 				val = '\r';
3649813Slinton 				goto mkcc;
3659813Slinton 
3669813Slinton 			case 'b':
3679813Slinton 				val = '\b';
3689813Slinton 				goto mkcc;
3699813Slinton 
3709813Slinton 			case 't':
3719813Slinton 				val = '\t';
3729813Slinton 				goto mkcc;
3739813Slinton 
3749813Slinton 			case 'f':
3759813Slinton 				val = '\f';
3769813Slinton 				goto mkcc;
3779813Slinton 
3789813Slinton 			case 'v':
37932838Sdonn 				val = '\v';
3809813Slinton 				goto mkcc;
3819813Slinton 
3829813Slinton 			case '0':
3839813Slinton 			case '1':
3849813Slinton 			case '2':
3859813Slinton 			case '3':
3869813Slinton 			case '4':
3879813Slinton 			case '5':
3889813Slinton 			case '6':
3899813Slinton 			case '7':
3909813Slinton 				val = c-'0';
3919813Slinton 				c=getchar();  /* try for 2 */
3929813Slinton 				if( lxmask[c+1] & LEXOCT ){
3939813Slinton 					val = (val<<3) | (c-'0');
3949813Slinton 					c = getchar();  /* try for 3 */
3959813Slinton 					if( lxmask[c+1] & LEXOCT ){
3969813Slinton 						val = (val<<3) | (c-'0');
3979813Slinton 						}
3989813Slinton 					else ungetc( c ,stdin);
3999813Slinton 					}
4009813Slinton 				else ungetc( c ,stdin);
4019813Slinton 
4029813Slinton 				goto mkcc1;
4039813Slinton 
4049813Slinton 				}
4059813Slinton 		default:
4069813Slinton 			val =c;
4079813Slinton 		mkcc:
4089813Slinton 			val = CCTRANS(val);
4099813Slinton 		mkcc1:
4109813Slinton 			if( lxmatch == '\'' ){
4119813Slinton 				val = CHARCAST(val);  /* it is, after all, a "character" constant */
4129813Slinton 				makecc( val, i );
4139813Slinton 				}
4149813Slinton 			else { /* stash the byte into the string */
4159813Slinton 				if( strflg ) {
4169813Slinton 					if( ct==0 || i<ct ) putbyte( val );
4179813Slinton 					else if( i == ct ) werror( "non-null byte ignored in string initializer" );
4189813Slinton 					}
4199813Slinton 				else bycode( val, i );
4209813Slinton 				}
4219813Slinton 			++i;
4229813Slinton 			continue;
4239813Slinton 			}
4249813Slinton 		break;
4259813Slinton 		}
4269813Slinton 	/* end of string or  char constant */
4279813Slinton 
4289813Slinton 	if( lxmatch == '"' ){
4299813Slinton 		if( strflg ){ /* end the string */
4309813Slinton 			if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
4319813Slinton 			}
4329813Slinton 		else {  /* the initializer gets a null byte */
4339813Slinton 			bycode( 0, i++ );
4349813Slinton 			bycode( -1, i );
4359813Slinton 			dimtab[curdim] = i;  /* in case of later sizeof ... */
4369813Slinton 			}
4379813Slinton 		}
4389813Slinton 	else { /* end the character constant */
4399813Slinton 		if( i == 0 ) uerror( "empty character constant" );
4409813Slinton 		if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
4419813Slinton 			uerror( "too many characters in character constant" );
4429813Slinton 		}
44332837Sdonn 	lxmatch = 0;	/* handshake with yylex() */
4449813Slinton 	}
4459813Slinton 
lxcom()4469813Slinton lxcom(){
4479813Slinton 	register c;
4489813Slinton 	/* saw a /*: process a comment */
4499813Slinton 
4509813Slinton 	for(;;){
4519813Slinton 
4529813Slinton 		switch( c = getchar() ){
4539813Slinton 
4549813Slinton 		case EOF:
4559813Slinton 			uerror( "unexpected EOF" );
4569813Slinton 			return;
4579813Slinton 
4589813Slinton 		case '\n':
4599813Slinton 			++lineno;
4609813Slinton 
4619813Slinton 		default:
4629813Slinton 			continue;
4639813Slinton 
4649813Slinton 		case '*':
4659813Slinton 			if( (c = getchar()) == '/' ) return;
4669813Slinton 			else ungetc( c ,stdin);
4679813Slinton 			continue;
4689813Slinton 
4699813Slinton # ifdef LINT
4709813Slinton 		case 'V':
4719813Slinton 			lxget( c, LEXLET|LEXDIG );
4729813Slinton 			{
4739813Slinton 				extern int vaflag;
4749813Slinton 				int i;
4759813Slinton 				i = yytext[7]?yytext[7]-'0':0;
4769813Slinton 				yytext[7] = '\0';
4779813Slinton 				if( strcmp( yytext, "VARARGS" ) ) continue;
4789813Slinton 				vaflag = i;
4799813Slinton 				continue;
4809813Slinton 				}
4819813Slinton 		case 'L':
4829813Slinton 			lxget( c, LEXLET );
4839813Slinton 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
4849813Slinton 			{
4859813Slinton 				extern int libflag;
4869813Slinton 				libflag = 1;
4879813Slinton 				}
4889813Slinton 			continue;
4899813Slinton 
4909813Slinton 		case 'A':
4919813Slinton 			lxget( c, LEXLET );
4929813Slinton 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
4939813Slinton 			{
4949813Slinton 				extern int argflag, vflag;
4959813Slinton 				argflag = 1;
4969813Slinton 				vflag = 0;
4979813Slinton 				}
4989813Slinton 			continue;
4999813Slinton 
5009813Slinton 		case 'N':
5019813Slinton 			lxget( c, LEXLET );
5029813Slinton 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
5039813Slinton 			reached = 0;
5049813Slinton 			continue;
5059813Slinton # endif
5069813Slinton 			}
5079813Slinton 		}
5089813Slinton 	}
5099813Slinton 
yylex()5109813Slinton yylex(){
51132839Sdonn 	double atof();
51232839Sdonn 
51332837Sdonn 	if (lxmatch != 0) {
51432837Sdonn 		/* recover from a syntax error that consumes a STRING token */
51532837Sdonn 		strflg = 1;
51632837Sdonn 		lxstr(0);
51732837Sdonn 	}
5189813Slinton 	for(;;){
5199813Slinton 
5209813Slinton 		register lxchar;
5219813Slinton 		register struct lxdope *p;
5229813Slinton 		register struct symtab *sp;
5239813Slinton 		int id;
52432834Sdonn 		char *s;
52532834Sdonn 		static char sc[5];
5269813Slinton 
5279813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
5289813Slinton 
5299813Slinton 		onechar:
5309813Slinton 			ungetc( lxchar ,stdin);
5319813Slinton 
5329813Slinton 		case A_1C:
5339813Slinton 			/* eat up a single character, and return an opcode */
5349813Slinton 
5359813Slinton 			yylval.intval = p->lxval;
5369813Slinton 			return( p->lxtok );
5379813Slinton 
5389813Slinton 		case A_ERR:
53932834Sdonn 			switch( lxchar ){
54032834Sdonn 			case '\\':	s = "\\\\"; break;
54132834Sdonn 			case '\0':	s = "\\0"; break;
54232834Sdonn 			default:
54332834Sdonn 				if( isgraph( lxchar ) ){
54432834Sdonn 					sc[0] = lxchar;
54532834Sdonn 					sc[1] = '\0';
54632834Sdonn 					}
54732834Sdonn 				else
54832834Sdonn 					sprintf( sc, "\\%03.3o", (unsigned char) lxchar );
54932834Sdonn 				s = sc;
55032834Sdonn 				break;
55132834Sdonn 				}
55232834Sdonn 			uerror( "illegal character: '%s'", s );
55332838Sdonn 			continue; /* ignore it and see if we find more */
5549813Slinton 
5559813Slinton 		case A_LET:
5569813Slinton 			/* collect an identifier, check for reserved word, and return */
5579813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
5589813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5599813Slinton 			if( lxchar== 0 ) continue;
5609813Slinton #ifdef FLEXNAMES
5619813Slinton 			id = lookup( hash(yytext),
5629813Slinton #else
5639813Slinton 			id = lookup( yytext,
5649813Slinton #endif
5659813Slinton 				/* tag name for struct/union/enum */
5669813Slinton 				(stwart&TAGNAME)? STAG:
5679813Slinton 				/* member name for struct/union */
5689813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5699813Slinton 			sp = &stab[id];
5709813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
5719813Slinton 				stwart = instruct;
5729813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5739813Slinton 				return( TYPE );
5749813Slinton 				}
5759813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
5769813Slinton 			yylval.intval = id;
5779813Slinton 			return( NAME );
5789813Slinton 
5799813Slinton 		case A_DIG:
5809813Slinton 			/* collect a digit string, then look at last one... */
5819813Slinton 			lastcon = 0;
5829813Slinton 			lxget( lxchar, LEXDIG );
5839813Slinton 			switch( lxchar=getchar() ){
5849813Slinton 
5859813Slinton 			case 'x':
5869813Slinton 			case 'X':
5879813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5889813Slinton 				lxmore( lxchar, LEXHEX );
5899813Slinton 				/* convert the value */
5909813Slinton 				{
5919813Slinton 					register char *cp;
5929813Slinton 					for( cp = yytext+2; *cp; ++cp ){
5939813Slinton 						/* this code won't work for all wild character sets,
5949813Slinton 						   but seems ok for ascii and ebcdic */
5959813Slinton 						lastcon <<= 4;
5969813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
5979813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5989813Slinton 						else lastcon += *cp - 'a'+ 10;
5999813Slinton 						}
6009813Slinton 					}
6019813Slinton 
6029813Slinton 			hexlong:
6039813Slinton 				/* criterion for longness for hex and octal constants is that it
6049813Slinton 				   fit within 0177777 */
6059813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
6069813Slinton 				else yylval.intval = 0;
6079813Slinton 
6089813Slinton 				goto islong;
6099813Slinton 
6109813Slinton 			case '.':
6119813Slinton 				lxmore( lxchar, LEXDIG );
6129813Slinton 
6139813Slinton 			getfp:
6149813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
6159813Slinton 
6169813Slinton 			case 'e':
6179813Slinton 			case 'E':
6189813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
6199813Slinton 						*lxgcp++ = 'e';
6209813Slinton 						}
6219813Slinton 					else {
6229813Slinton 						ungetc(lxchar,stdin);
6239813Slinton 						lxchar = 'e';
6249813Slinton 						}
6259813Slinton 					lxmore( lxchar, LEXDIG );
6269813Slinton 					/* now have the whole thing... */
6279813Slinton 					}
6289813Slinton 				else {  /* no exponent */
6299813Slinton 					ungetc( lxchar ,stdin);
6309813Slinton 					}
63132839Sdonn 				dcon = atof( yytext );
63232839Sdonn 				if( (lxchar = getchar()) == 'F' || lxchar == 'f' ){
63332839Sdonn 					fcon = dcon;
63432839Sdonn 					return( FCON );
63532839Sdonn 					}
63632839Sdonn 				else ungetc( lxchar ,stdin);
63732839Sdonn 				return( DCON );
6389813Slinton 
6399813Slinton 			default:
6409813Slinton 				ungetc( lxchar ,stdin);
6419813Slinton 				if( yytext[0] == '0' ){
6429813Slinton 					/* convert in octal */
6439813Slinton 					register char *cp;
6449813Slinton 					for( cp = yytext+1; *cp; ++cp ){
6459813Slinton 						lastcon <<= 3;
6469813Slinton 						lastcon += *cp - '0';
6479813Slinton 						}
6489813Slinton 					goto hexlong;
6499813Slinton 					}
6509813Slinton 				else {
6519813Slinton 					/* convert in decimal */
6529813Slinton 					register char *cp;
6539813Slinton 					for( cp = yytext; *cp; ++cp ){
6549813Slinton 						lastcon = lastcon * 10 + *cp - '0';
6559813Slinton 						}
6569813Slinton 					}
6579813Slinton 
6589813Slinton 				/* decide if it is long or not (decimal case) */
6599813Slinton 
6609813Slinton 				/* if it is positive and fits in 15 bits, or negative and
6619813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
6629813Slinton 				/* if there is an l or L following, all bets are off... */
6639813Slinton 
6649813Slinton 				{	CONSZ v;
6659813Slinton 					v = lastcon & ~077777L;
6669813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
6679813Slinton 					else yylval.intval = 1;
6689813Slinton 					}
6699813Slinton 
6709813Slinton 			islong:
6719813Slinton 				/* finally, look for trailing L or l */
6729813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6739813Slinton 				else ungetc( lxchar ,stdin);
6749813Slinton 				return( ICON );
6759813Slinton 				}
6769813Slinton 
6779813Slinton 		case A_DOT:
6789813Slinton 			/* look for a dot: if followed by a digit, floating point */
6799813Slinton 			lxchar = getchar();
6809813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
6819813Slinton 				ungetc(lxchar,stdin);
6829813Slinton 				lxget( '.', LEXDIG );
6839813Slinton 				goto getfp;
6849813Slinton 				}
6859813Slinton 			stwart = FUNNYNAME;
6869813Slinton 			goto onechar;
6879813Slinton 
6889813Slinton 		case A_STR:
6899813Slinton 			/* string constant */
6909813Slinton 			lxmatch = '"';
6919813Slinton 			return( STRING );
6929813Slinton 
6939813Slinton 		case A_CC:
6949813Slinton 			/* character constant */
6959813Slinton 			lxmatch = '\'';
6969813Slinton 			lastcon = 0;
6979813Slinton 			lxstr(0);
6989813Slinton 			yylval.intval = 0;
6999813Slinton 			return( ICON );
7009813Slinton 
70132838Sdonn #ifdef gcos
7029813Slinton 		case A_BCD:
7039813Slinton 			{
7049813Slinton 				register i;
7059813Slinton 				int j;
7069813Slinton 				for( i=0; i<LXTSZ; ++i ){
7079813Slinton 					if( ( j = getchar() ) == '`' ) break;
7089813Slinton 					if( j == '\n' ){
7099813Slinton 						uerror( "newline in BCD constant" );
7109813Slinton 						break;
7119813Slinton 						}
7129813Slinton 					yytext[i] = j;
7139813Slinton 					}
7149813Slinton 				yytext[i] = '\0';
7159813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
71632838Sdonn # ifndef unix
7179813Slinton 				else strtob( yytext, &lastcon, i );
7189813Slinton 				lastcon >>= 6*(6-i);
7199813Slinton # else
7209813Slinton 				uerror( "gcos BCD constant illegal" );
7219813Slinton # endif
7229813Slinton 				yylval.intval = 0;  /* not long */
7239813Slinton 				return( ICON );
7249813Slinton 				}
72532838Sdonn #endif
7269813Slinton 
7279813Slinton 		case A_SL:
7289813Slinton 			/* / */
7299813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
7309813Slinton 			lxcom();
7319813Slinton 		case A_WS:
7329813Slinton 			continue;
7339813Slinton 
7349813Slinton 		case A_NL:
7359813Slinton 			++lineno;
7369813Slinton 			lxtitle();
7379813Slinton 			continue;
7389813Slinton 
7399813Slinton 		case A_NOT:
7409813Slinton 			/* ! */
7419813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
7429813Slinton 			yylval.intval = NE;
7439813Slinton 			return( EQUOP );
7449813Slinton 
7459813Slinton 		case A_MI:
7469813Slinton 			/* - */
7479813Slinton 			if( (lxchar=getchar()) == '-' ){
7489813Slinton 				yylval.intval = DECR;
7499813Slinton 				return( INCOP );
7509813Slinton 				}
7519813Slinton 			if( lxchar != '>' ) goto onechar;
7529813Slinton 			stwart = FUNNYNAME;
7539813Slinton 			yylval.intval=STREF;
7549813Slinton 			return( STROP );
7559813Slinton 
7569813Slinton 		case A_PL:
7579813Slinton 			/* + */
7589813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
7599813Slinton 			yylval.intval = INCR;
7609813Slinton 			return( INCOP );
7619813Slinton 
7629813Slinton 		case A_AND:
7639813Slinton 			/* & */
7649813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
7659813Slinton 			return( yylval.intval = ANDAND );
7669813Slinton 
7679813Slinton 		case A_OR:
7689813Slinton 			/* | */
7699813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
7709813Slinton 			return( yylval.intval = OROR );
7719813Slinton 
7729813Slinton 		case A_LT:
7739813Slinton 			/* < */
7749813Slinton 			if( (lxchar=getchar()) == '<' ){
7759813Slinton 				yylval.intval = LS;
7769813Slinton 				return( SHIFTOP );
7779813Slinton 				}
7789813Slinton 			if( lxchar != '=' ) goto onechar;
7799813Slinton 			yylval.intval = LE;
7809813Slinton 			return( RELOP );
7819813Slinton 
7829813Slinton 		case A_GT:
7839813Slinton 			/* > */
7849813Slinton 			if( (lxchar=getchar()) == '>' ){
7859813Slinton 				yylval.intval = RS;
7869813Slinton 				return(SHIFTOP );
7879813Slinton 				}
7889813Slinton 			if( lxchar != '=' ) goto onechar;
7899813Slinton 			yylval.intval = GE;
7909813Slinton 			return( RELOP );
7919813Slinton 
7929813Slinton 		case A_EQ:
7939813Slinton 			/* = */
7949813Slinton 			switch( lxchar = getchar() ){
7959813Slinton 
7969813Slinton 			case '=':
7979813Slinton 				yylval.intval = EQ;
7989813Slinton 				return( EQUOP );
7999813Slinton 
80032829Sdonn #ifdef old_assignment_ops
8019813Slinton 			case '+':
8029813Slinton 				yylval.intval = ASG PLUS;
8039813Slinton 				break;
8049813Slinton 
8059813Slinton 			case '-':
8069813Slinton 				yylval.intval = ASG MINUS;
8079813Slinton 
8089813Slinton 			warn:
8099813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
8109813Slinton 					werror( "ambiguous assignment: assignment op taken" );
8119813Slinton 					}
8129813Slinton 				ungetc( lxchar ,stdin);
8139813Slinton 				break;
8149813Slinton 
8159813Slinton 			case '*':
8169813Slinton 				yylval.intval = ASG MUL;
8179813Slinton 				goto warn;
8189813Slinton 
8199813Slinton 			case '/':
8209813Slinton 				yylval.intval = ASG DIV;
8219813Slinton 				break;
8229813Slinton 
8239813Slinton 			case '%':
8249813Slinton 				yylval.intval = ASG MOD;
8259813Slinton 				break;
8269813Slinton 
8279813Slinton 			case '&':
8289813Slinton 				yylval.intval = ASG AND;
8299813Slinton 				break;
8309813Slinton 
8319813Slinton 			case '|':
8329813Slinton 				yylval.intval = ASG OR;
8339813Slinton 				break;
8349813Slinton 
8359813Slinton 			case '^':
8369813Slinton 				yylval.intval = ASG ER;
8379813Slinton 				break;
8389813Slinton 
8399813Slinton 			case '<':
8409813Slinton 				if( (lxchar=getchar()) != '<' ){
8419813Slinton 					uerror( "=<%c illegal", lxchar );
8429813Slinton 					}
8439813Slinton 				yylval.intval = ASG LS;
8449813Slinton 				break;
8459813Slinton 
8469813Slinton 			case '>':
8479813Slinton 				if( (lxchar=getchar()) != '>' ){
8489813Slinton 					uerror( "=>%c illegal", lxchar );
8499813Slinton 					}
8509813Slinton 				yylval.intval = ASG RS;
8519813Slinton 				break;
85232829Sdonn #endif old_assignment_ops
8539813Slinton 
8549813Slinton 			default:
8559813Slinton 				goto onechar;
8569813Slinton 
8579813Slinton 				}
8589813Slinton 
85932831Sdonn #ifdef old_assignment_ops	/* defeat 'unreachable code' warning */
8609813Slinton 			return( ASOP );
86132831Sdonn #endif old_assignment_ops
8629813Slinton 
8639813Slinton 		default:
8649813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
8659813Slinton 
8669813Slinton 			}
8679813Slinton 
8689813Slinton 		/* ordinarily, repeat here... */
8699813Slinton 		cerror( "out of switch in yylex" );
8709813Slinton 
8719813Slinton 		}
8729813Slinton 
8739813Slinton 	}
8749813Slinton 
8759813Slinton struct lxrdope {
8769813Slinton 	/* dope for reserved, in alphabetical order */
8779813Slinton 
8789813Slinton 	char *lxrch;	/* name of reserved word */
8799813Slinton 	short lxract;	/* reserved word action */
8809813Slinton 	short lxrval;	/* value to be returned */
8819813Slinton 	} lxrdope[] = {
8829813Slinton 
8839813Slinton 	"asm",		AR_A,	0,
8849813Slinton 	"auto",		AR_CL,	AUTO,
8859813Slinton 	"break",	AR_RW,	BREAK,
8869813Slinton 	"char",		AR_TY,	CHAR,
8879813Slinton 	"case",		AR_RW,	CASE,
8889813Slinton 	"continue",	AR_RW,	CONTINUE,
8899813Slinton 	"double",	AR_TY,	DOUBLE,
8909813Slinton 	"default",	AR_RW,	DEFAULT,
8919813Slinton 	"do",		AR_RW,	DO,
8929813Slinton 	"extern",	AR_CL,	EXTERN,
8939813Slinton 	"else",		AR_RW,	ELSE,
8949813Slinton 	"enum",		AR_E,	ENUM,
8959813Slinton 	"for",		AR_RW,	FOR,
8969813Slinton 	"float",	AR_TY,	FLOAT,
8979813Slinton 	"fortran",	AR_CL,	FORTRAN,
8989813Slinton 	"goto",		AR_RW,	GOTO,
8999813Slinton 	"if",		AR_RW,	IF,
9009813Slinton 	"int",		AR_TY,	INT,
9019813Slinton 	"long",		AR_TY,	LONG,
9029813Slinton 	"return",	AR_RW,	RETURN,
9039813Slinton 	"register",	AR_CL,	REGISTER,
9049813Slinton 	"switch",	AR_RW,	SWITCH,
9059813Slinton 	"struct",	AR_S,	0,
9069813Slinton 	"sizeof",	AR_RW,	SIZEOF,
9079813Slinton 	"short",	AR_TY,	SHORT,
9089813Slinton 	"static",	AR_CL,	STATIC,
9099813Slinton 	"typedef",	AR_CL,	TYPEDEF,
9109813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
9119813Slinton 	"union",	AR_U,	0,
9129813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
9139813Slinton 	"while",	AR_RW,	WHILE,
9149813Slinton 	"",		0,	0,	/* to stop the search */
9159813Slinton 	};
9169813Slinton 
lxres()9179813Slinton lxres() {
9189813Slinton 	/* check to see of yytext is reserved; if so,
9199813Slinton 	/* do the appropriate action and return */
9209813Slinton 	/* otherwise, return -1 */
9219813Slinton 
9229813Slinton 	register c, ch;
9239813Slinton 	register struct lxrdope *p;
9249813Slinton 
9259813Slinton 	ch = yytext[0];
9269813Slinton 
9279813Slinton 	if( !islower(ch) ) return( -1 );
9289813Slinton 
9299813Slinton 	switch( ch ){
9309813Slinton 
9319813Slinton 	case 'a':
9329813Slinton 		c=0; break;
9339813Slinton 	case 'b':
9349813Slinton 		c=2; break;
9359813Slinton 	case 'c':
9369813Slinton 		c=3; break;
9379813Slinton 	case 'd':
9389813Slinton 		c=6; break;
9399813Slinton 	case 'e':
9409813Slinton 		c=9; break;
9419813Slinton 	case 'f':
9429813Slinton 		c=12; break;
9439813Slinton 	case 'g':
9449813Slinton 		c=15; break;
9459813Slinton 	case 'i':
9469813Slinton 		c=16; break;
9479813Slinton 	case 'l':
9489813Slinton 		c=18; break;
9499813Slinton 	case 'r':
9509813Slinton 		c=19; break;
9519813Slinton 	case 's':
9529813Slinton 		c=21; break;
9539813Slinton 	case 't':
9549813Slinton 		c=26; break;
9559813Slinton 	case 'u':
9569813Slinton 		c=27; break;
9579813Slinton 	case 'v':
9589813Slinton 		c=29; break;
9599813Slinton 	case 'w':
9609813Slinton 		c=30; break;
9619813Slinton 
9629813Slinton 	default:
9639813Slinton 		return( -1 );
9649813Slinton 		}
9659813Slinton 
9669813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9679813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
9689813Slinton 			switch( p->lxract ){
9699813Slinton 
9709813Slinton 			case AR_TY:
9719813Slinton 				/* type word */
9729813Slinton 				stwart = instruct;
9739813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9749813Slinton 				return( TYPE );
9759813Slinton 
9769813Slinton 			case AR_RW:
9779813Slinton 				/* ordinary reserved word */
9789813Slinton 				return( yylval.intval = p->lxrval );
9799813Slinton 
9809813Slinton 			case AR_CL:
9819813Slinton 				/* class word */
9829813Slinton 				yylval.intval = p->lxrval;
9839813Slinton 				return( CLASS );
9849813Slinton 
9859813Slinton 			case AR_S:
9869813Slinton 				/* struct */
9879813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
9889813Slinton 				yylval.intval = INSTRUCT;
9899813Slinton 				return( STRUCT );
9909813Slinton 
9919813Slinton 			case AR_U:
9929813Slinton 				/* union */
9939813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
9949813Slinton 				yylval.intval = INUNION;
9959813Slinton 				return( STRUCT );
9969813Slinton 
9979813Slinton 			case AR_E:
9989813Slinton 				/* enums */
9999813Slinton 				stwart = SEENAME|TAGNAME;
10009813Slinton 				return( yylval.intval = ENUM );
10019813Slinton 
10029813Slinton 			case AR_A:
10039813Slinton 				/* asm */
10049813Slinton 				asm_esc = 1; /* warn the world! */
10059813Slinton 				lxget( ' ', LEXWS );
10069813Slinton 				if( getchar() != '(' ) goto badasm;
10079813Slinton 				lxget( ' ', LEXWS );
10089813Slinton 				if( getchar() != '"' ) goto badasm;
10099813Slinton # ifndef ONEPASS
10109813Slinton # ifndef LINT
10119813Slinton 				putchar(')');
10129813Slinton # endif
10139813Slinton # endif
10149813Slinton 				while( (c=getchar()) != '"' ){
10159813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
10169813Slinton # ifndef LINT
10179813Slinton 					putchar(c);
10189813Slinton # endif
10199813Slinton 					}
10209813Slinton 				lxget( ' ', LEXWS );
10219813Slinton 				if( getchar() != ')' ) goto badasm;
10229813Slinton # ifndef LINT
10239813Slinton 				putchar('\n');
10249813Slinton # endif
10259813Slinton 				return( 0 );
10269813Slinton 
10279813Slinton 			badasm:
10289813Slinton 				uerror( "bad asm construction" );
10299813Slinton 				return( 0 );
10309813Slinton 
10319813Slinton 			default:
10329813Slinton 				cerror( "bad AR_?? action" );
10339813Slinton 				}
10349813Slinton 			}
10359813Slinton 		}
10369813Slinton 	return( -1 );
10379813Slinton 	}
10389813Slinton 
10399813Slinton extern int	labelno;
10409813Slinton 
lxtitle()10419813Slinton lxtitle(){
10429813Slinton 	/* called after a newline; set linenumber and file name */
10439813Slinton 
10449813Slinton 	register c, val;
10459813Slinton 	register char *cp, *cq;
10469813Slinton 
10479813Slinton 	for(;;){  /* might be several such lines in a row */
10489813Slinton 		if( (c=getchar()) != '#' ){
10499813Slinton 			if( c != EOF ) ungetc(c,stdin);
10509813Slinton #ifndef LINT
10519813Slinton 			if ( lastloc != PROG) return;
10529813Slinton 			cp = ftitle;
10539813Slinton 			cq = ititle;
10549813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
10559813Slinton 			if ( *cq ) return;
105632830Sdonn 			if( nerrors == 0 ) psline();
10579813Slinton #endif
10589813Slinton 			return;
10599813Slinton 			}
10609813Slinton 
10619813Slinton 		lxget( ' ', LEXWS );
106232832Sdonn 		c = getchar();
106332832Sdonn 		if( c == 'i' ){
106432832Sdonn 			/* #ident -- currently a no-op */
106532832Sdonn 			lxget( c, LEXLET );
106632832Sdonn 			if( strcmp( yytext, "ident" ) )
106732832Sdonn 				werror( "%s: undefined control", yytext );
106832832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
106932832Sdonn 				;
107032832Sdonn 			continue;
107132832Sdonn 			}
107232832Sdonn 		if( c == 'p' ){
107332832Sdonn 			/* #pragma -- special instructions */
107432832Sdonn 			lxget( c, LEXLET );
107532832Sdonn 			if( strcmp( yytext, "pragma" ) ) {
107632832Sdonn 				werror( "%s: undefined control", yytext );
107732832Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
107832832Sdonn 					;
107932832Sdonn 				continue;
108032832Sdonn 				}
108132832Sdonn 			lxget( ' ' , LEXWS );
108232832Sdonn 			switch( c = getchar() ){
108332832Sdonn # ifdef LINT
108432832Sdonn 			case 'V':
108532832Sdonn 				lxget( c, LEXLET|LEXDIG );
108632832Sdonn 				{
108732832Sdonn 					extern int vaflag;
108832832Sdonn 					int i;
108932832Sdonn 					i = yytext[7]?yytext[7]-'0':0;
109032832Sdonn 					yytext[7] = '\0';
109132832Sdonn 					if( strcmp( yytext, "VARARGS" ) ) break;
109232832Sdonn 					vaflag = i;
109332832Sdonn 					break;
109432832Sdonn 					}
109532832Sdonn 			case 'L':
109632832Sdonn 				lxget( c, LEXLET );
109732832Sdonn 				if( strcmp( yytext, "LINTLIBRARY" ) ) break;
109832832Sdonn 				{
109932832Sdonn 					extern int libflag;
110032832Sdonn 					libflag = 1;
110132832Sdonn 					}
110232832Sdonn 				break;
110332832Sdonn 
110432832Sdonn 			case 'A':
110532832Sdonn 				lxget( c, LEXLET );
110632832Sdonn 				if( strcmp( yytext, "ARGSUSED" ) ) break;
110732832Sdonn 				{
110832832Sdonn 					extern int argflag, vflag;
110932832Sdonn 					argflag = 1;
111032832Sdonn 					vflag = 0;
111132832Sdonn 					}
111232832Sdonn 				break;
111332832Sdonn 
111432832Sdonn 			case 'N':
111532832Sdonn 				lxget( c, LEXLET );
111632832Sdonn 				if( strcmp( yytext, "NOTREACHED" ) ) break;
111732832Sdonn 				reached = 0;
111832832Sdonn 				break;
111932832Sdonn #endif
112032832Sdonn 
112132832Sdonn 			case '\n':
112232832Sdonn 			case EOF:
112332832Sdonn 				continue;
112432832Sdonn 				}
112532832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
112632832Sdonn 				;
112732832Sdonn 			continue;
112832832Sdonn 			}
112932833Sdonn 		if( c == 'l' ){
113032833Sdonn 			/* #line -- just like # */
113132833Sdonn 			lxget( c, LEXLET );
113232833Sdonn 			if( strcmp( yytext, "line" ) ){
113332833Sdonn 				werror( "%s: undefined control", yytext );
113432833Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
113532833Sdonn 					;
113632833Sdonn 				continue;
113732833Sdonn 				}
113832833Sdonn 			lxget( ' ', LEXWS );
113932833Sdonn 			c = getchar();
114032833Sdonn 			}
114132832Sdonn 		if( !isdigit(c) ){
114232832Sdonn 			if( isalpha(c) ){
114332832Sdonn 				lxget( c, LEXLET );
114432832Sdonn 				werror( "%s: undefined control", yytext );
114532832Sdonn 				}
114632833Sdonn 			while( c != '\n' && c != EOF )
114732833Sdonn 				c = getchar();
114832832Sdonn 			continue;
114932832Sdonn 			}
115032832Sdonn 
11519813Slinton 		val = 0;
115232832Sdonn 		do {
11539813Slinton 			val = val*10+ c - '0';
11549813Slinton 			}
115532832Sdonn 		while( isdigit( c = getchar() ) );
115632832Sdonn 
115717748Sralph 		if( c == EOF )
115817748Sralph 			continue;
11599813Slinton 		ungetc( c, stdin );
11609813Slinton 		lineno = val;
11619813Slinton 		lxget( ' ', LEXWS );
116217748Sralph 		if( (c=getchar()) != '\n' && c != EOF ){
116317748Sralph 			for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
11649813Slinton 				*cp = c;
11659813Slinton 				}
11669813Slinton 			*cp = '\0';
11679813Slinton #ifndef LINT
11689813Slinton 			if (ititle[0] == '\0') {
11699813Slinton 				cp = ftitle;
11709813Slinton 				cq = ititle;
11719813Slinton 				while ( *cp )
11729813Slinton 					*cq++ = *cp++;
11739813Slinton 				*cq = '\0';
11749813Slinton 				*--cq = '\0';
11759813Slinton #ifndef FLEXNAMES
11769813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
11779813Slinton 					pstab(cp, N_SO);
11789813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
11799813Slinton 					}
11809813Slinton #else
11819813Slinton 				pstab(ititle+1, N_SO);
11829813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
11839813Slinton #endif
11849813Slinton 
11859813Slinton 				*cq = '"';
11869813Slinton 				printf("LL%d:\n", labelno++);
11879813Slinton 				}
11889813Slinton #endif
11899813Slinton 			}
11909813Slinton 		}
11919813Slinton 	}
11929813Slinton 
11939813Slinton #ifdef FLEXNAMES
11949813Slinton #define	NSAVETAB	4096
11959813Slinton char	*savetab;
119632836Sdonn unsigned saveleft;
119732836Sdonn char	*malloc();
119832836Sdonn char	*calloc();
119932836Sdonn char	*strncpy();
12009813Slinton 
12019813Slinton char *
savestr(cp)12029813Slinton savestr(cp)
12039813Slinton 	register char *cp;
12049813Slinton {
12059813Slinton 	register int len;
12069813Slinton 
12079813Slinton 	len = strlen(cp) + 1;
12089813Slinton 	if (len > saveleft) {
12099813Slinton 		saveleft = NSAVETAB;
12109813Slinton 		if (len > saveleft)
12119813Slinton 			saveleft = len;
121232836Sdonn 		savetab = malloc(saveleft);
12139813Slinton 		if (savetab == 0)
12149813Slinton 			cerror("Ran out of memory (savestr)");
12159813Slinton 	}
121632836Sdonn 	(void) strncpy(savetab, cp, len);
12179813Slinton 	cp = savetab;
12189813Slinton 	savetab += len;
12199813Slinton 	saveleft -= len;
12209813Slinton 	return (cp);
12219813Slinton }
12229813Slinton 
12239813Slinton /*
12249813Slinton  * The definition for the segmented hash tables.
12259813Slinton  */
12269813Slinton #define	MAXHASH	20
12279813Slinton #define	HASHINC	1013
12289813Slinton struct ht {
12299813Slinton 	char	**ht_low;
12309813Slinton 	char	**ht_high;
12319813Slinton 	int	ht_used;
12329813Slinton } htab[MAXHASH];
12339813Slinton 
12349813Slinton char *
hash(s)12359813Slinton hash(s)
12369813Slinton 	char *s;
12379813Slinton {
12389813Slinton 	register char **h;
12399813Slinton 	register i;
12409813Slinton 	register char *cp;
12419813Slinton 	struct ht *htp;
12429813Slinton 	int sh;
12439813Slinton 
12449813Slinton 	/*
12459813Slinton 	 * The hash function is a modular hash of
12469813Slinton 	 * the sum of the characters with the sum
12479813Slinton 	 * doubled before each successive character
12489813Slinton 	 * is added.
12499813Slinton 	 */
12509813Slinton 	cp = s;
12519813Slinton 	i = 0;
12529813Slinton 	while (*cp)
12539813Slinton 		i = i*2 + *cp++;
12549813Slinton 	sh = (i&077777) % HASHINC;
12559813Slinton 	cp = s;
12569813Slinton 	/*
12579813Slinton 	 * There are as many as MAXHASH active
12589813Slinton 	 * hash tables at any given point in time.
12599813Slinton 	 * The search starts with the first table
12609813Slinton 	 * and continues through the active tables
12619813Slinton 	 * as necessary.
12629813Slinton 	 */
12639813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
12649813Slinton 		if (htp->ht_low == 0) {
12659813Slinton 			register char **hp =
12669813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
12679813Slinton 			if (hp == 0)
12689813Slinton 				cerror("ran out of memory (hash)");
12699813Slinton 			htp->ht_low = hp;
12709813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
12719813Slinton 		}
12729813Slinton 		h = htp->ht_low + sh;
12739813Slinton 		/*
12749813Slinton 		 * quadratic rehash increment
12759813Slinton 		 * starts at 1 and incremented
12769813Slinton 		 * by two each rehash.
12779813Slinton 		 */
12789813Slinton 		i = 1;
12799813Slinton 		do {
12809813Slinton 			if (*h == 0) {
12819813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
12829813Slinton 					break;
12839813Slinton 				htp->ht_used++;
12849813Slinton 				*h = savestr(cp);
12859813Slinton 				return (*h);
12869813Slinton 			}
12879813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
12889813Slinton 				return (*h);
12899813Slinton 			h += i;
12909813Slinton 			i += 2;
12919813Slinton 			if (h >= htp->ht_high)
12929813Slinton 				h -= HASHINC;
12939813Slinton 		} while (i < HASHINC);
12949813Slinton 	}
12959813Slinton 	cerror("ran out of hash tables");
129632836Sdonn 	/*NOTREACHED*/
12979813Slinton }
12989813Slinton #endif
1299