xref: /csrg-svn/old/pcc/mip/scan.c (revision 32838)
117748Sralph #ifndef lint
2*32838Sdonn static char *sccsid ="@(#)scan.c	2.14 (Berkeley) 12/10/87";
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;
6624407Smckusick extern int 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 */
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 
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 
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 */
238*32838Sdonn #ifdef gcos
2399813Slinton 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
240*32838Sdonn #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 
2709813Slinton lxinit(){
2719813Slinton 	register struct lxdope *p;
2729813Slinton 	register i;
2739813Slinton 	register char *cp;
2749813Slinton 	/* set up character classes */
2759813Slinton 
276*32838Sdonn 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
277*32838Sdonn #ifdef VMS
278*32838Sdonn 	lxmask['$'+1] |= LEXLET;
279*32838Sdonn #endif
2809813Slinton 	lxenter( "0123456789", LEXDIG );
2819813Slinton 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
282*32838Sdonn 	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 
302*32838Sdonn 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
3039813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
304*32838Sdonn #ifdef VMS
305*32838Sdonn 	lxcp['$'+1] = &lxdope[1];
306*32838Sdonn #endif
3079813Slinton 	cp = "123456789";
3089813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
309*32838Sdonn 	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 
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:
347*32838Sdonn #ifdef LINT
348*32838Sdonn 				if( hflag )
349*32838Sdonn 					uerror( "superfluous backslash in %s constant", lxmatch == '\'' ? "char" : "string" );
350*32838Sdonn 				/*FALLTHROUGH*/
351*32838Sdonn #endif
352*32838Sdonn 			case '\\':
353*32838Sdonn 			case '\"':
354*32838Sdonn 			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':
379*32838Sdonn 				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 
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 
5109813Slinton yylex(){
51132837Sdonn 	if (lxmatch != 0) {
51232837Sdonn 		/* recover from a syntax error that consumes a STRING token */
51332837Sdonn 		strflg = 1;
51432837Sdonn 		lxstr(0);
51532837Sdonn 	}
5169813Slinton 	for(;;){
5179813Slinton 
5189813Slinton 		register lxchar;
5199813Slinton 		register struct lxdope *p;
5209813Slinton 		register struct symtab *sp;
5219813Slinton 		int id;
52232834Sdonn 		char *s;
52332834Sdonn 		static char sc[5];
5249813Slinton 
5259813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
5269813Slinton 
5279813Slinton 		onechar:
5289813Slinton 			ungetc( lxchar ,stdin);
5299813Slinton 
5309813Slinton 		case A_1C:
5319813Slinton 			/* eat up a single character, and return an opcode */
5329813Slinton 
5339813Slinton 			yylval.intval = p->lxval;
5349813Slinton 			return( p->lxtok );
5359813Slinton 
5369813Slinton 		case A_ERR:
53732834Sdonn 			switch( lxchar ){
53832834Sdonn 			case '\\':	s = "\\\\"; break;
53932834Sdonn 			case '\0':	s = "\\0"; break;
54032834Sdonn 			default:
54132834Sdonn 				if( isgraph( lxchar ) ){
54232834Sdonn 					sc[0] = lxchar;
54332834Sdonn 					sc[1] = '\0';
54432834Sdonn 					}
54532834Sdonn 				else
54632834Sdonn 					sprintf( sc, "\\%03.3o", (unsigned char) lxchar );
54732834Sdonn 				s = sc;
54832834Sdonn 				break;
54932834Sdonn 				}
55032834Sdonn 			uerror( "illegal character: '%s'", s );
551*32838Sdonn 			continue; /* ignore it and see if we find more */
5529813Slinton 
5539813Slinton 		case A_LET:
5549813Slinton 			/* collect an identifier, check for reserved word, and return */
5559813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
5569813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5579813Slinton 			if( lxchar== 0 ) continue;
5589813Slinton #ifdef FLEXNAMES
5599813Slinton 			id = lookup( hash(yytext),
5609813Slinton #else
5619813Slinton 			id = lookup( yytext,
5629813Slinton #endif
5639813Slinton 				/* tag name for struct/union/enum */
5649813Slinton 				(stwart&TAGNAME)? STAG:
5659813Slinton 				/* member name for struct/union */
5669813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5679813Slinton 			sp = &stab[id];
5689813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
5699813Slinton 				stwart = instruct;
5709813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5719813Slinton 				return( TYPE );
5729813Slinton 				}
5739813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
5749813Slinton 			yylval.intval = id;
5759813Slinton 			return( NAME );
5769813Slinton 
5779813Slinton 		case A_DIG:
5789813Slinton 			/* collect a digit string, then look at last one... */
5799813Slinton 			lastcon = 0;
5809813Slinton 			lxget( lxchar, LEXDIG );
5819813Slinton 			switch( lxchar=getchar() ){
5829813Slinton 
5839813Slinton 			case 'x':
5849813Slinton 			case 'X':
5859813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5869813Slinton 				lxmore( lxchar, LEXHEX );
5879813Slinton 				/* convert the value */
5889813Slinton 				{
5899813Slinton 					register char *cp;
5909813Slinton 					for( cp = yytext+2; *cp; ++cp ){
5919813Slinton 						/* this code won't work for all wild character sets,
5929813Slinton 						   but seems ok for ascii and ebcdic */
5939813Slinton 						lastcon <<= 4;
5949813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
5959813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5969813Slinton 						else lastcon += *cp - 'a'+ 10;
5979813Slinton 						}
5989813Slinton 					}
5999813Slinton 
6009813Slinton 			hexlong:
6019813Slinton 				/* criterion for longness for hex and octal constants is that it
6029813Slinton 				   fit within 0177777 */
6039813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
6049813Slinton 				else yylval.intval = 0;
6059813Slinton 
6069813Slinton 				goto islong;
6079813Slinton 
6089813Slinton 			case '.':
6099813Slinton 				lxmore( lxchar, LEXDIG );
6109813Slinton 
6119813Slinton 			getfp:
6129813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
6139813Slinton 
6149813Slinton 			case 'e':
6159813Slinton 			case 'E':
6169813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
6179813Slinton 						*lxgcp++ = 'e';
6189813Slinton 						}
6199813Slinton 					else {
6209813Slinton 						ungetc(lxchar,stdin);
6219813Slinton 						lxchar = 'e';
6229813Slinton 						}
6239813Slinton 					lxmore( lxchar, LEXDIG );
6249813Slinton 					/* now have the whole thing... */
6259813Slinton 					}
6269813Slinton 				else {  /* no exponent */
6279813Slinton 					ungetc( lxchar ,stdin);
6289813Slinton 					}
6299813Slinton 				return( isitfloat( yytext ) );
6309813Slinton 
6319813Slinton 			default:
6329813Slinton 				ungetc( lxchar ,stdin);
6339813Slinton 				if( yytext[0] == '0' ){
6349813Slinton 					/* convert in octal */
6359813Slinton 					register char *cp;
6369813Slinton 					for( cp = yytext+1; *cp; ++cp ){
6379813Slinton 						lastcon <<= 3;
6389813Slinton 						lastcon += *cp - '0';
6399813Slinton 						}
6409813Slinton 					goto hexlong;
6419813Slinton 					}
6429813Slinton 				else {
6439813Slinton 					/* convert in decimal */
6449813Slinton 					register char *cp;
6459813Slinton 					for( cp = yytext; *cp; ++cp ){
6469813Slinton 						lastcon = lastcon * 10 + *cp - '0';
6479813Slinton 						}
6489813Slinton 					}
6499813Slinton 
6509813Slinton 				/* decide if it is long or not (decimal case) */
6519813Slinton 
6529813Slinton 				/* if it is positive and fits in 15 bits, or negative and
6539813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
6549813Slinton 				/* if there is an l or L following, all bets are off... */
6559813Slinton 
6569813Slinton 				{	CONSZ v;
6579813Slinton 					v = lastcon & ~077777L;
6589813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
6599813Slinton 					else yylval.intval = 1;
6609813Slinton 					}
6619813Slinton 
6629813Slinton 			islong:
6639813Slinton 				/* finally, look for trailing L or l */
6649813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6659813Slinton 				else ungetc( lxchar ,stdin);
6669813Slinton 				return( ICON );
6679813Slinton 				}
6689813Slinton 
6699813Slinton 		case A_DOT:
6709813Slinton 			/* look for a dot: if followed by a digit, floating point */
6719813Slinton 			lxchar = getchar();
6729813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
6739813Slinton 				ungetc(lxchar,stdin);
6749813Slinton 				lxget( '.', LEXDIG );
6759813Slinton 				goto getfp;
6769813Slinton 				}
6779813Slinton 			stwart = FUNNYNAME;
6789813Slinton 			goto onechar;
6799813Slinton 
6809813Slinton 		case A_STR:
6819813Slinton 			/* string constant */
6829813Slinton 			lxmatch = '"';
6839813Slinton 			return( STRING );
6849813Slinton 
6859813Slinton 		case A_CC:
6869813Slinton 			/* character constant */
6879813Slinton 			lxmatch = '\'';
6889813Slinton 			lastcon = 0;
6899813Slinton 			lxstr(0);
6909813Slinton 			yylval.intval = 0;
6919813Slinton 			return( ICON );
6929813Slinton 
693*32838Sdonn #ifdef gcos
6949813Slinton 		case A_BCD:
6959813Slinton 			{
6969813Slinton 				register i;
6979813Slinton 				int j;
6989813Slinton 				for( i=0; i<LXTSZ; ++i ){
6999813Slinton 					if( ( j = getchar() ) == '`' ) break;
7009813Slinton 					if( j == '\n' ){
7019813Slinton 						uerror( "newline in BCD constant" );
7029813Slinton 						break;
7039813Slinton 						}
7049813Slinton 					yytext[i] = j;
7059813Slinton 					}
7069813Slinton 				yytext[i] = '\0';
7079813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
708*32838Sdonn # ifndef unix
7099813Slinton 				else strtob( yytext, &lastcon, i );
7109813Slinton 				lastcon >>= 6*(6-i);
7119813Slinton # else
7129813Slinton 				uerror( "gcos BCD constant illegal" );
7139813Slinton # endif
7149813Slinton 				yylval.intval = 0;  /* not long */
7159813Slinton 				return( ICON );
7169813Slinton 				}
717*32838Sdonn #endif
7189813Slinton 
7199813Slinton 		case A_SL:
7209813Slinton 			/* / */
7219813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
7229813Slinton 			lxcom();
7239813Slinton 		case A_WS:
7249813Slinton 			continue;
7259813Slinton 
7269813Slinton 		case A_NL:
7279813Slinton 			++lineno;
7289813Slinton 			lxtitle();
7299813Slinton 			continue;
7309813Slinton 
7319813Slinton 		case A_NOT:
7329813Slinton 			/* ! */
7339813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
7349813Slinton 			yylval.intval = NE;
7359813Slinton 			return( EQUOP );
7369813Slinton 
7379813Slinton 		case A_MI:
7389813Slinton 			/* - */
7399813Slinton 			if( (lxchar=getchar()) == '-' ){
7409813Slinton 				yylval.intval = DECR;
7419813Slinton 				return( INCOP );
7429813Slinton 				}
7439813Slinton 			if( lxchar != '>' ) goto onechar;
7449813Slinton 			stwart = FUNNYNAME;
7459813Slinton 			yylval.intval=STREF;
7469813Slinton 			return( STROP );
7479813Slinton 
7489813Slinton 		case A_PL:
7499813Slinton 			/* + */
7509813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
7519813Slinton 			yylval.intval = INCR;
7529813Slinton 			return( INCOP );
7539813Slinton 
7549813Slinton 		case A_AND:
7559813Slinton 			/* & */
7569813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
7579813Slinton 			return( yylval.intval = ANDAND );
7589813Slinton 
7599813Slinton 		case A_OR:
7609813Slinton 			/* | */
7619813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
7629813Slinton 			return( yylval.intval = OROR );
7639813Slinton 
7649813Slinton 		case A_LT:
7659813Slinton 			/* < */
7669813Slinton 			if( (lxchar=getchar()) == '<' ){
7679813Slinton 				yylval.intval = LS;
7689813Slinton 				return( SHIFTOP );
7699813Slinton 				}
7709813Slinton 			if( lxchar != '=' ) goto onechar;
7719813Slinton 			yylval.intval = LE;
7729813Slinton 			return( RELOP );
7739813Slinton 
7749813Slinton 		case A_GT:
7759813Slinton 			/* > */
7769813Slinton 			if( (lxchar=getchar()) == '>' ){
7779813Slinton 				yylval.intval = RS;
7789813Slinton 				return(SHIFTOP );
7799813Slinton 				}
7809813Slinton 			if( lxchar != '=' ) goto onechar;
7819813Slinton 			yylval.intval = GE;
7829813Slinton 			return( RELOP );
7839813Slinton 
7849813Slinton 		case A_EQ:
7859813Slinton 			/* = */
7869813Slinton 			switch( lxchar = getchar() ){
7879813Slinton 
7889813Slinton 			case '=':
7899813Slinton 				yylval.intval = EQ;
7909813Slinton 				return( EQUOP );
7919813Slinton 
79232829Sdonn #ifdef old_assignment_ops
7939813Slinton 			case '+':
7949813Slinton 				yylval.intval = ASG PLUS;
7959813Slinton 				break;
7969813Slinton 
7979813Slinton 			case '-':
7989813Slinton 				yylval.intval = ASG MINUS;
7999813Slinton 
8009813Slinton 			warn:
8019813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
8029813Slinton 					werror( "ambiguous assignment: assignment op taken" );
8039813Slinton 					}
8049813Slinton 				ungetc( lxchar ,stdin);
8059813Slinton 				break;
8069813Slinton 
8079813Slinton 			case '*':
8089813Slinton 				yylval.intval = ASG MUL;
8099813Slinton 				goto warn;
8109813Slinton 
8119813Slinton 			case '/':
8129813Slinton 				yylval.intval = ASG DIV;
8139813Slinton 				break;
8149813Slinton 
8159813Slinton 			case '%':
8169813Slinton 				yylval.intval = ASG MOD;
8179813Slinton 				break;
8189813Slinton 
8199813Slinton 			case '&':
8209813Slinton 				yylval.intval = ASG AND;
8219813Slinton 				break;
8229813Slinton 
8239813Slinton 			case '|':
8249813Slinton 				yylval.intval = ASG OR;
8259813Slinton 				break;
8269813Slinton 
8279813Slinton 			case '^':
8289813Slinton 				yylval.intval = ASG ER;
8299813Slinton 				break;
8309813Slinton 
8319813Slinton 			case '<':
8329813Slinton 				if( (lxchar=getchar()) != '<' ){
8339813Slinton 					uerror( "=<%c illegal", lxchar );
8349813Slinton 					}
8359813Slinton 				yylval.intval = ASG LS;
8369813Slinton 				break;
8379813Slinton 
8389813Slinton 			case '>':
8399813Slinton 				if( (lxchar=getchar()) != '>' ){
8409813Slinton 					uerror( "=>%c illegal", lxchar );
8419813Slinton 					}
8429813Slinton 				yylval.intval = ASG RS;
8439813Slinton 				break;
84432829Sdonn #endif old_assignment_ops
8459813Slinton 
8469813Slinton 			default:
8479813Slinton 				goto onechar;
8489813Slinton 
8499813Slinton 				}
8509813Slinton 
85132831Sdonn #ifdef old_assignment_ops	/* defeat 'unreachable code' warning */
8529813Slinton 			return( ASOP );
85332831Sdonn #endif old_assignment_ops
8549813Slinton 
8559813Slinton 		default:
8569813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
8579813Slinton 
8589813Slinton 			}
8599813Slinton 
8609813Slinton 		/* ordinarily, repeat here... */
8619813Slinton 		cerror( "out of switch in yylex" );
8629813Slinton 
8639813Slinton 		}
8649813Slinton 
8659813Slinton 	}
8669813Slinton 
8679813Slinton struct lxrdope {
8689813Slinton 	/* dope for reserved, in alphabetical order */
8699813Slinton 
8709813Slinton 	char *lxrch;	/* name of reserved word */
8719813Slinton 	short lxract;	/* reserved word action */
8729813Slinton 	short lxrval;	/* value to be returned */
8739813Slinton 	} lxrdope[] = {
8749813Slinton 
8759813Slinton 	"asm",		AR_A,	0,
8769813Slinton 	"auto",		AR_CL,	AUTO,
8779813Slinton 	"break",	AR_RW,	BREAK,
8789813Slinton 	"char",		AR_TY,	CHAR,
8799813Slinton 	"case",		AR_RW,	CASE,
8809813Slinton 	"continue",	AR_RW,	CONTINUE,
8819813Slinton 	"double",	AR_TY,	DOUBLE,
8829813Slinton 	"default",	AR_RW,	DEFAULT,
8839813Slinton 	"do",		AR_RW,	DO,
8849813Slinton 	"extern",	AR_CL,	EXTERN,
8859813Slinton 	"else",		AR_RW,	ELSE,
8869813Slinton 	"enum",		AR_E,	ENUM,
8879813Slinton 	"for",		AR_RW,	FOR,
8889813Slinton 	"float",	AR_TY,	FLOAT,
8899813Slinton 	"fortran",	AR_CL,	FORTRAN,
8909813Slinton 	"goto",		AR_RW,	GOTO,
8919813Slinton 	"if",		AR_RW,	IF,
8929813Slinton 	"int",		AR_TY,	INT,
8939813Slinton 	"long",		AR_TY,	LONG,
8949813Slinton 	"return",	AR_RW,	RETURN,
8959813Slinton 	"register",	AR_CL,	REGISTER,
8969813Slinton 	"switch",	AR_RW,	SWITCH,
8979813Slinton 	"struct",	AR_S,	0,
8989813Slinton 	"sizeof",	AR_RW,	SIZEOF,
8999813Slinton 	"short",	AR_TY,	SHORT,
9009813Slinton 	"static",	AR_CL,	STATIC,
9019813Slinton 	"typedef",	AR_CL,	TYPEDEF,
9029813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
9039813Slinton 	"union",	AR_U,	0,
9049813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
9059813Slinton 	"while",	AR_RW,	WHILE,
9069813Slinton 	"",		0,	0,	/* to stop the search */
9079813Slinton 	};
9089813Slinton 
9099813Slinton lxres() {
9109813Slinton 	/* check to see of yytext is reserved; if so,
9119813Slinton 	/* do the appropriate action and return */
9129813Slinton 	/* otherwise, return -1 */
9139813Slinton 
9149813Slinton 	register c, ch;
9159813Slinton 	register struct lxrdope *p;
9169813Slinton 
9179813Slinton 	ch = yytext[0];
9189813Slinton 
9199813Slinton 	if( !islower(ch) ) return( -1 );
9209813Slinton 
9219813Slinton 	switch( ch ){
9229813Slinton 
9239813Slinton 	case 'a':
9249813Slinton 		c=0; break;
9259813Slinton 	case 'b':
9269813Slinton 		c=2; break;
9279813Slinton 	case 'c':
9289813Slinton 		c=3; break;
9299813Slinton 	case 'd':
9309813Slinton 		c=6; break;
9319813Slinton 	case 'e':
9329813Slinton 		c=9; break;
9339813Slinton 	case 'f':
9349813Slinton 		c=12; break;
9359813Slinton 	case 'g':
9369813Slinton 		c=15; break;
9379813Slinton 	case 'i':
9389813Slinton 		c=16; break;
9399813Slinton 	case 'l':
9409813Slinton 		c=18; break;
9419813Slinton 	case 'r':
9429813Slinton 		c=19; break;
9439813Slinton 	case 's':
9449813Slinton 		c=21; break;
9459813Slinton 	case 't':
9469813Slinton 		c=26; break;
9479813Slinton 	case 'u':
9489813Slinton 		c=27; break;
9499813Slinton 	case 'v':
9509813Slinton 		c=29; break;
9519813Slinton 	case 'w':
9529813Slinton 		c=30; break;
9539813Slinton 
9549813Slinton 	default:
9559813Slinton 		return( -1 );
9569813Slinton 		}
9579813Slinton 
9589813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9599813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
9609813Slinton 			switch( p->lxract ){
9619813Slinton 
9629813Slinton 			case AR_TY:
9639813Slinton 				/* type word */
9649813Slinton 				stwart = instruct;
9659813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9669813Slinton 				return( TYPE );
9679813Slinton 
9689813Slinton 			case AR_RW:
9699813Slinton 				/* ordinary reserved word */
9709813Slinton 				return( yylval.intval = p->lxrval );
9719813Slinton 
9729813Slinton 			case AR_CL:
9739813Slinton 				/* class word */
9749813Slinton 				yylval.intval = p->lxrval;
9759813Slinton 				return( CLASS );
9769813Slinton 
9779813Slinton 			case AR_S:
9789813Slinton 				/* struct */
9799813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
9809813Slinton 				yylval.intval = INSTRUCT;
9819813Slinton 				return( STRUCT );
9829813Slinton 
9839813Slinton 			case AR_U:
9849813Slinton 				/* union */
9859813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
9869813Slinton 				yylval.intval = INUNION;
9879813Slinton 				return( STRUCT );
9889813Slinton 
9899813Slinton 			case AR_E:
9909813Slinton 				/* enums */
9919813Slinton 				stwart = SEENAME|TAGNAME;
9929813Slinton 				return( yylval.intval = ENUM );
9939813Slinton 
9949813Slinton 			case AR_A:
9959813Slinton 				/* asm */
9969813Slinton 				asm_esc = 1; /* warn the world! */
9979813Slinton 				lxget( ' ', LEXWS );
9989813Slinton 				if( getchar() != '(' ) goto badasm;
9999813Slinton 				lxget( ' ', LEXWS );
10009813Slinton 				if( getchar() != '"' ) goto badasm;
10019813Slinton # ifndef ONEPASS
10029813Slinton # ifndef LINT
10039813Slinton 				putchar(')');
10049813Slinton # endif
10059813Slinton # endif
10069813Slinton 				while( (c=getchar()) != '"' ){
10079813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
10089813Slinton # ifndef LINT
10099813Slinton 					putchar(c);
10109813Slinton # endif
10119813Slinton 					}
10129813Slinton 				lxget( ' ', LEXWS );
10139813Slinton 				if( getchar() != ')' ) goto badasm;
10149813Slinton # ifndef LINT
10159813Slinton 				putchar('\n');
10169813Slinton # endif
10179813Slinton 				return( 0 );
10189813Slinton 
10199813Slinton 			badasm:
10209813Slinton 				uerror( "bad asm construction" );
10219813Slinton 				return( 0 );
10229813Slinton 
10239813Slinton 			default:
10249813Slinton 				cerror( "bad AR_?? action" );
10259813Slinton 				}
10269813Slinton 			}
10279813Slinton 		}
10289813Slinton 	return( -1 );
10299813Slinton 	}
10309813Slinton 
10319813Slinton extern int	labelno;
10329813Slinton 
10339813Slinton lxtitle(){
10349813Slinton 	/* called after a newline; set linenumber and file name */
10359813Slinton 
10369813Slinton 	register c, val;
10379813Slinton 	register char *cp, *cq;
10389813Slinton 
10399813Slinton 	for(;;){  /* might be several such lines in a row */
10409813Slinton 		if( (c=getchar()) != '#' ){
10419813Slinton 			if( c != EOF ) ungetc(c,stdin);
10429813Slinton #ifndef LINT
10439813Slinton 			if ( lastloc != PROG) return;
10449813Slinton 			cp = ftitle;
10459813Slinton 			cq = ititle;
10469813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
10479813Slinton 			if ( *cq ) return;
104832830Sdonn 			if( nerrors == 0 ) psline();
10499813Slinton #endif
10509813Slinton 			return;
10519813Slinton 			}
10529813Slinton 
10539813Slinton 		lxget( ' ', LEXWS );
105432832Sdonn 		c = getchar();
105532832Sdonn 		if( c == 'i' ){
105632832Sdonn 			/* #ident -- currently a no-op */
105732832Sdonn 			lxget( c, LEXLET );
105832832Sdonn 			if( strcmp( yytext, "ident" ) )
105932832Sdonn 				werror( "%s: undefined control", yytext );
106032832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
106132832Sdonn 				;
106232832Sdonn 			continue;
106332832Sdonn 			}
106432832Sdonn 		if( c == 'p' ){
106532832Sdonn 			/* #pragma -- special instructions */
106632832Sdonn 			lxget( c, LEXLET );
106732832Sdonn 			if( strcmp( yytext, "pragma" ) ) {
106832832Sdonn 				werror( "%s: undefined control", yytext );
106932832Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
107032832Sdonn 					;
107132832Sdonn 				continue;
107232832Sdonn 				}
107332832Sdonn 			lxget( ' ' , LEXWS );
107432832Sdonn 			switch( c = getchar() ){
107532832Sdonn # ifdef LINT
107632832Sdonn 			case 'V':
107732832Sdonn 				lxget( c, LEXLET|LEXDIG );
107832832Sdonn 				{
107932832Sdonn 					extern int vaflag;
108032832Sdonn 					int i;
108132832Sdonn 					i = yytext[7]?yytext[7]-'0':0;
108232832Sdonn 					yytext[7] = '\0';
108332832Sdonn 					if( strcmp( yytext, "VARARGS" ) ) break;
108432832Sdonn 					vaflag = i;
108532832Sdonn 					break;
108632832Sdonn 					}
108732832Sdonn 			case 'L':
108832832Sdonn 				lxget( c, LEXLET );
108932832Sdonn 				if( strcmp( yytext, "LINTLIBRARY" ) ) break;
109032832Sdonn 				{
109132832Sdonn 					extern int libflag;
109232832Sdonn 					libflag = 1;
109332832Sdonn 					}
109432832Sdonn 				break;
109532832Sdonn 
109632832Sdonn 			case 'A':
109732832Sdonn 				lxget( c, LEXLET );
109832832Sdonn 				if( strcmp( yytext, "ARGSUSED" ) ) break;
109932832Sdonn 				{
110032832Sdonn 					extern int argflag, vflag;
110132832Sdonn 					argflag = 1;
110232832Sdonn 					vflag = 0;
110332832Sdonn 					}
110432832Sdonn 				break;
110532832Sdonn 
110632832Sdonn 			case 'N':
110732832Sdonn 				lxget( c, LEXLET );
110832832Sdonn 				if( strcmp( yytext, "NOTREACHED" ) ) break;
110932832Sdonn 				reached = 0;
111032832Sdonn 				break;
111132832Sdonn #endif
111232832Sdonn 
111332832Sdonn 			case '\n':
111432832Sdonn 			case EOF:
111532832Sdonn 				continue;
111632832Sdonn 				}
111732832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
111832832Sdonn 				;
111932832Sdonn 			continue;
112032832Sdonn 			}
112132833Sdonn 		if( c == 'l' ){
112232833Sdonn 			/* #line -- just like # */
112332833Sdonn 			lxget( c, LEXLET );
112432833Sdonn 			if( strcmp( yytext, "line" ) ){
112532833Sdonn 				werror( "%s: undefined control", yytext );
112632833Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
112732833Sdonn 					;
112832833Sdonn 				continue;
112932833Sdonn 				}
113032833Sdonn 			lxget( ' ', LEXWS );
113132833Sdonn 			c = getchar();
113232833Sdonn 			}
113332832Sdonn 		if( !isdigit(c) ){
113432832Sdonn 			if( isalpha(c) ){
113532832Sdonn 				lxget( c, LEXLET );
113632832Sdonn 				werror( "%s: undefined control", yytext );
113732832Sdonn 				}
113832833Sdonn 			while( c != '\n' && c != EOF )
113932833Sdonn 				c = getchar();
114032832Sdonn 			continue;
114132832Sdonn 			}
114232832Sdonn 
11439813Slinton 		val = 0;
114432832Sdonn 		do {
11459813Slinton 			val = val*10+ c - '0';
11469813Slinton 			}
114732832Sdonn 		while( isdigit( c = getchar() ) );
114832832Sdonn 
114917748Sralph 		if( c == EOF )
115017748Sralph 			continue;
11519813Slinton 		ungetc( c, stdin );
11529813Slinton 		lineno = val;
11539813Slinton 		lxget( ' ', LEXWS );
115417748Sralph 		if( (c=getchar()) != '\n' && c != EOF ){
115517748Sralph 			for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
11569813Slinton 				*cp = c;
11579813Slinton 				}
11589813Slinton 			*cp = '\0';
11599813Slinton #ifndef LINT
11609813Slinton 			if (ititle[0] == '\0') {
11619813Slinton 				cp = ftitle;
11629813Slinton 				cq = ititle;
11639813Slinton 				while ( *cp )
11649813Slinton 					*cq++ = *cp++;
11659813Slinton 				*cq = '\0';
11669813Slinton 				*--cq = '\0';
11679813Slinton #ifndef FLEXNAMES
11689813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
11699813Slinton 					pstab(cp, N_SO);
11709813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
11719813Slinton 					}
11729813Slinton #else
11739813Slinton 				pstab(ititle+1, N_SO);
11749813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
11759813Slinton #endif
11769813Slinton 
11779813Slinton 				*cq = '"';
11789813Slinton 				printf("LL%d:\n", labelno++);
11799813Slinton 				}
11809813Slinton #endif
11819813Slinton 			}
11829813Slinton 		}
11839813Slinton 	}
11849813Slinton 
11859813Slinton #ifdef FLEXNAMES
11869813Slinton #define	NSAVETAB	4096
11879813Slinton char	*savetab;
118832836Sdonn unsigned saveleft;
118932836Sdonn char	*malloc();
119032836Sdonn char	*calloc();
119132836Sdonn char	*strncpy();
11929813Slinton 
11939813Slinton char *
11949813Slinton savestr(cp)
11959813Slinton 	register char *cp;
11969813Slinton {
11979813Slinton 	register int len;
11989813Slinton 
11999813Slinton 	len = strlen(cp) + 1;
12009813Slinton 	if (len > saveleft) {
12019813Slinton 		saveleft = NSAVETAB;
12029813Slinton 		if (len > saveleft)
12039813Slinton 			saveleft = len;
120432836Sdonn 		savetab = malloc(saveleft);
12059813Slinton 		if (savetab == 0)
12069813Slinton 			cerror("Ran out of memory (savestr)");
12079813Slinton 	}
120832836Sdonn 	(void) strncpy(savetab, cp, len);
12099813Slinton 	cp = savetab;
12109813Slinton 	savetab += len;
12119813Slinton 	saveleft -= len;
12129813Slinton 	return (cp);
12139813Slinton }
12149813Slinton 
12159813Slinton /*
12169813Slinton  * The definition for the segmented hash tables.
12179813Slinton  */
12189813Slinton #define	MAXHASH	20
12199813Slinton #define	HASHINC	1013
12209813Slinton struct ht {
12219813Slinton 	char	**ht_low;
12229813Slinton 	char	**ht_high;
12239813Slinton 	int	ht_used;
12249813Slinton } htab[MAXHASH];
12259813Slinton 
12269813Slinton char *
12279813Slinton hash(s)
12289813Slinton 	char *s;
12299813Slinton {
12309813Slinton 	register char **h;
12319813Slinton 	register i;
12329813Slinton 	register char *cp;
12339813Slinton 	struct ht *htp;
12349813Slinton 	int sh;
12359813Slinton 
12369813Slinton 	/*
12379813Slinton 	 * The hash function is a modular hash of
12389813Slinton 	 * the sum of the characters with the sum
12399813Slinton 	 * doubled before each successive character
12409813Slinton 	 * is added.
12419813Slinton 	 */
12429813Slinton 	cp = s;
12439813Slinton 	i = 0;
12449813Slinton 	while (*cp)
12459813Slinton 		i = i*2 + *cp++;
12469813Slinton 	sh = (i&077777) % HASHINC;
12479813Slinton 	cp = s;
12489813Slinton 	/*
12499813Slinton 	 * There are as many as MAXHASH active
12509813Slinton 	 * hash tables at any given point in time.
12519813Slinton 	 * The search starts with the first table
12529813Slinton 	 * and continues through the active tables
12539813Slinton 	 * as necessary.
12549813Slinton 	 */
12559813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
12569813Slinton 		if (htp->ht_low == 0) {
12579813Slinton 			register char **hp =
12589813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
12599813Slinton 			if (hp == 0)
12609813Slinton 				cerror("ran out of memory (hash)");
12619813Slinton 			htp->ht_low = hp;
12629813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
12639813Slinton 		}
12649813Slinton 		h = htp->ht_low + sh;
12659813Slinton 		/*
12669813Slinton 		 * quadratic rehash increment
12679813Slinton 		 * starts at 1 and incremented
12689813Slinton 		 * by two each rehash.
12699813Slinton 		 */
12709813Slinton 		i = 1;
12719813Slinton 		do {
12729813Slinton 			if (*h == 0) {
12739813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
12749813Slinton 					break;
12759813Slinton 				htp->ht_used++;
12769813Slinton 				*h = savestr(cp);
12779813Slinton 				return (*h);
12789813Slinton 			}
12799813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
12809813Slinton 				return (*h);
12819813Slinton 			h += i;
12829813Slinton 			i += 2;
12839813Slinton 			if (h >= htp->ht_high)
12849813Slinton 				h -= HASHINC;
12859813Slinton 		} while (i < HASHINC);
12869813Slinton 	}
12879813Slinton 	cerror("ran out of hash tables");
128832836Sdonn 	/*NOTREACHED*/
12899813Slinton }
12909813Slinton #endif
1291