xref: /csrg-svn/old/pcc/mip/scan.c (revision 32837)
117748Sralph #ifndef lint
2*32837Sdonn static char *sccsid ="@(#)scan.c	2.13 (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 */
2389813Slinton 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
2399813Slinton 	'(',	A_1C,	LP,	0,
2409813Slinton 	')',	A_1C,	RP,	0,
2419813Slinton 	'{',	A_1C,	LC,	0,
2429813Slinton 	'}',	A_1C,	RC,	0,
2439813Slinton 	'[',	A_1C,	LB,	0,
2449813Slinton 	']',	A_1C,	RB,	0,
2459813Slinton 	'*',	A_1C,	MUL,	MUL,
2469813Slinton 	'?',	A_1C,	QUEST,	0,
2479813Slinton 	':',	A_1C,	COLON,	0,
2489813Slinton 	'+',	A_PL,	PLUS,	PLUS,
2499813Slinton 	'-',	A_MI,	MINUS,	MINUS,
2509813Slinton 	'/',	A_SL,	DIVOP,	DIV,
2519813Slinton 	'%',	A_1C,	DIVOP,	MOD,
2529813Slinton 	'&',	A_AND,	AND,	AND,
2539813Slinton 	'|',	A_OR,	OR,	OR,
2549813Slinton 	'^',	A_1C,	ER,	ER,
2559813Slinton 	'!',	A_NOT,	UNOP,	NOT,
2569813Slinton 	'~',	A_1C,	UNOP,	COMPL,
2579813Slinton 	',',	A_1C,	CM,	CM,
2589813Slinton 	';',	A_1C,	SM,	0,
2599813Slinton 	'.',	A_DOT,	STROP,	DOT,
2609813Slinton 	'<',	A_LT,	RELOP,	LT,
2619813Slinton 	'>',	A_GT,	RELOP,	GT,
2629813Slinton 	'=',	A_EQ,	ASSIGN,	ASSIGN,
2639813Slinton 	-1,	A_1C,	0,	0,
2649813Slinton 	};
2659813Slinton 
2669813Slinton struct lxdope *lxcp[CSSZ+1];
2679813Slinton 
2689813Slinton lxinit(){
2699813Slinton 	register struct lxdope *p;
2709813Slinton 	register i;
2719813Slinton 	register char *cp;
2729813Slinton 	/* set up character classes */
2739813Slinton 
2749813Slinton 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
2759813Slinton 	lxenter( "0123456789", LEXDIG );
2769813Slinton 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
2779813Slinton 		/* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
2789813Slinton 	lxenter( " \t\r\b\f\013", LEXWS );
2799813Slinton 	lxenter( "01234567", LEXOCT );
2809813Slinton 	lxmask['.'+1] |= LEXDOT;
2819813Slinton 
2829813Slinton 	/* make lxcp point to appropriate lxdope entry for each character */
2839813Slinton 
2849813Slinton 	/* initialize error entries */
2859813Slinton 
2869813Slinton 	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
2879813Slinton 
2889813Slinton 	/* make unique entries */
2899813Slinton 
2909813Slinton 	for( p=lxdope; ; ++p ) {
2919813Slinton 		lxcp[p->lxch+1] = p;
2929813Slinton 		if( p->lxch < 0 ) break;
2939813Slinton 		}
2949813Slinton 
2959813Slinton 	/* handle letters, digits, and whitespace */
2969813Slinton 	/* by convention, first, second, and third places */
2979813Slinton 
2989813Slinton 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
2999813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
3009813Slinton 	cp = "123456789";
3019813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
3029813Slinton 	cp = "\t\b\r\f\013";
3039813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
3049813Slinton 
3059813Slinton 	/* first line might have title */
3069813Slinton 	lxtitle();
3079813Slinton 
3089813Slinton 	}
3099813Slinton 
310*32837Sdonn int lxmatch = 0;  /* character to be matched in char or string constant */
3119813Slinton 
3129813Slinton lxstr(ct){
3139813Slinton 	/* match a string or character constant, up to lxmatch */
3149813Slinton 
3159813Slinton 	register c;
3169813Slinton 	register val;
3179813Slinton 	register i;
3189813Slinton 
3199813Slinton 	i=0;
3209813Slinton 	while( (c=getchar()) != lxmatch ){
3219813Slinton 		switch( c ) {
3229813Slinton 
3239813Slinton 		case EOF:
3249813Slinton 			uerror( "unexpected EOF" );
3259813Slinton 			break;
3269813Slinton 
3279813Slinton 		case '\n':
3289813Slinton 			uerror( "newline in string or char constant" );
3299813Slinton 			++lineno;
3309813Slinton 			break;
3319813Slinton 
3329813Slinton 		case '\\':
3339813Slinton 			switch( c = getchar() ){
3349813Slinton 
3359813Slinton 			case '\n':
3369813Slinton 				++lineno;
3379813Slinton 				continue;
3389813Slinton 
3399813Slinton 			default:
3409813Slinton 				val = c;
3419813Slinton 				goto mkcc;
3429813Slinton 
3439813Slinton 			case 'n':
3449813Slinton 				val = '\n';
3459813Slinton 				goto mkcc;
3469813Slinton 
3479813Slinton 			case 'r':
3489813Slinton 				val = '\r';
3499813Slinton 				goto mkcc;
3509813Slinton 
3519813Slinton 			case 'b':
3529813Slinton 				val = '\b';
3539813Slinton 				goto mkcc;
3549813Slinton 
3559813Slinton 			case 't':
3569813Slinton 				val = '\t';
3579813Slinton 				goto mkcc;
3589813Slinton 
3599813Slinton 			case 'f':
3609813Slinton 				val = '\f';
3619813Slinton 				goto mkcc;
3629813Slinton 
3639813Slinton 			case 'v':
3649813Slinton 				val = '\013';
3659813Slinton 				goto mkcc;
3669813Slinton 
3679813Slinton 			case '0':
3689813Slinton 			case '1':
3699813Slinton 			case '2':
3709813Slinton 			case '3':
3719813Slinton 			case '4':
3729813Slinton 			case '5':
3739813Slinton 			case '6':
3749813Slinton 			case '7':
3759813Slinton 				val = c-'0';
3769813Slinton 				c=getchar();  /* try for 2 */
3779813Slinton 				if( lxmask[c+1] & LEXOCT ){
3789813Slinton 					val = (val<<3) | (c-'0');
3799813Slinton 					c = getchar();  /* try for 3 */
3809813Slinton 					if( lxmask[c+1] & LEXOCT ){
3819813Slinton 						val = (val<<3) | (c-'0');
3829813Slinton 						}
3839813Slinton 					else ungetc( c ,stdin);
3849813Slinton 					}
3859813Slinton 				else ungetc( c ,stdin);
3869813Slinton 
3879813Slinton 				goto mkcc1;
3889813Slinton 
3899813Slinton 				}
3909813Slinton 		default:
3919813Slinton 			val =c;
3929813Slinton 		mkcc:
3939813Slinton 			val = CCTRANS(val);
3949813Slinton 		mkcc1:
3959813Slinton 			if( lxmatch == '\'' ){
3969813Slinton 				val = CHARCAST(val);  /* it is, after all, a "character" constant */
3979813Slinton 				makecc( val, i );
3989813Slinton 				}
3999813Slinton 			else { /* stash the byte into the string */
4009813Slinton 				if( strflg ) {
4019813Slinton 					if( ct==0 || i<ct ) putbyte( val );
4029813Slinton 					else if( i == ct ) werror( "non-null byte ignored in string initializer" );
4039813Slinton 					}
4049813Slinton 				else bycode( val, i );
4059813Slinton 				}
4069813Slinton 			++i;
4079813Slinton 			continue;
4089813Slinton 			}
4099813Slinton 		break;
4109813Slinton 		}
4119813Slinton 	/* end of string or  char constant */
4129813Slinton 
4139813Slinton 	if( lxmatch == '"' ){
4149813Slinton 		if( strflg ){ /* end the string */
4159813Slinton 			if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
4169813Slinton 			}
4179813Slinton 		else {  /* the initializer gets a null byte */
4189813Slinton 			bycode( 0, i++ );
4199813Slinton 			bycode( -1, i );
4209813Slinton 			dimtab[curdim] = i;  /* in case of later sizeof ... */
4219813Slinton 			}
4229813Slinton 		}
4239813Slinton 	else { /* end the character constant */
4249813Slinton 		if( i == 0 ) uerror( "empty character constant" );
4259813Slinton 		if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
4269813Slinton 			uerror( "too many characters in character constant" );
4279813Slinton 		}
428*32837Sdonn 	lxmatch = 0;	/* handshake with yylex() */
4299813Slinton 	}
4309813Slinton 
4319813Slinton lxcom(){
4329813Slinton 	register c;
4339813Slinton 	/* saw a /*: process a comment */
4349813Slinton 
4359813Slinton 	for(;;){
4369813Slinton 
4379813Slinton 		switch( c = getchar() ){
4389813Slinton 
4399813Slinton 		case EOF:
4409813Slinton 			uerror( "unexpected EOF" );
4419813Slinton 			return;
4429813Slinton 
4439813Slinton 		case '\n':
4449813Slinton 			++lineno;
4459813Slinton 
4469813Slinton 		default:
4479813Slinton 			continue;
4489813Slinton 
4499813Slinton 		case '*':
4509813Slinton 			if( (c = getchar()) == '/' ) return;
4519813Slinton 			else ungetc( c ,stdin);
4529813Slinton 			continue;
4539813Slinton 
4549813Slinton # ifdef LINT
4559813Slinton 		case 'V':
4569813Slinton 			lxget( c, LEXLET|LEXDIG );
4579813Slinton 			{
4589813Slinton 				extern int vaflag;
4599813Slinton 				int i;
4609813Slinton 				i = yytext[7]?yytext[7]-'0':0;
4619813Slinton 				yytext[7] = '\0';
4629813Slinton 				if( strcmp( yytext, "VARARGS" ) ) continue;
4639813Slinton 				vaflag = i;
4649813Slinton 				continue;
4659813Slinton 				}
4669813Slinton 		case 'L':
4679813Slinton 			lxget( c, LEXLET );
4689813Slinton 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
4699813Slinton 			{
4709813Slinton 				extern int libflag;
4719813Slinton 				libflag = 1;
4729813Slinton 				}
4739813Slinton 			continue;
4749813Slinton 
4759813Slinton 		case 'A':
4769813Slinton 			lxget( c, LEXLET );
4779813Slinton 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
4789813Slinton 			{
4799813Slinton 				extern int argflag, vflag;
4809813Slinton 				argflag = 1;
4819813Slinton 				vflag = 0;
4829813Slinton 				}
4839813Slinton 			continue;
4849813Slinton 
4859813Slinton 		case 'N':
4869813Slinton 			lxget( c, LEXLET );
4879813Slinton 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
4889813Slinton 			reached = 0;
4899813Slinton 			continue;
4909813Slinton # endif
4919813Slinton 			}
4929813Slinton 		}
4939813Slinton 	}
4949813Slinton 
4959813Slinton yylex(){
496*32837Sdonn 	if (lxmatch != 0) {
497*32837Sdonn 		/* recover from a syntax error that consumes a STRING token */
498*32837Sdonn 		strflg = 1;
499*32837Sdonn 		lxstr(0);
500*32837Sdonn 	}
5019813Slinton 	for(;;){
5029813Slinton 
5039813Slinton 		register lxchar;
5049813Slinton 		register struct lxdope *p;
5059813Slinton 		register struct symtab *sp;
5069813Slinton 		int id;
50732834Sdonn 		char *s;
50832834Sdonn 		static char sc[5];
5099813Slinton 
5109813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
5119813Slinton 
5129813Slinton 		onechar:
5139813Slinton 			ungetc( lxchar ,stdin);
5149813Slinton 
5159813Slinton 		case A_1C:
5169813Slinton 			/* eat up a single character, and return an opcode */
5179813Slinton 
5189813Slinton 			yylval.intval = p->lxval;
5199813Slinton 			return( p->lxtok );
5209813Slinton 
5219813Slinton 		case A_ERR:
52232834Sdonn 			switch( lxchar ){
52332834Sdonn 			case '\\':	s = "\\\\"; break;
52432834Sdonn 			case '\0':	s = "\\0"; break;
52532834Sdonn 			default:
52632834Sdonn 				if( isgraph( lxchar ) ){
52732834Sdonn 					sc[0] = lxchar;
52832834Sdonn 					sc[1] = '\0';
52932834Sdonn 					}
53032834Sdonn 				else
53132834Sdonn 					sprintf( sc, "\\%03.3o", (unsigned char) lxchar );
53232834Sdonn 				s = sc;
53332834Sdonn 				break;
53432834Sdonn 				}
53532834Sdonn 			uerror( "illegal character: '%s'", s );
5369813Slinton 			break;
5379813Slinton 
5389813Slinton 		case A_LET:
5399813Slinton 			/* collect an identifier, check for reserved word, and return */
5409813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
5419813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5429813Slinton 			if( lxchar== 0 ) continue;
5439813Slinton #ifdef FLEXNAMES
5449813Slinton 			id = lookup( hash(yytext),
5459813Slinton #else
5469813Slinton 			id = lookup( yytext,
5479813Slinton #endif
5489813Slinton 				/* tag name for struct/union/enum */
5499813Slinton 				(stwart&TAGNAME)? STAG:
5509813Slinton 				/* member name for struct/union */
5519813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5529813Slinton 			sp = &stab[id];
5539813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
5549813Slinton 				stwart = instruct;
5559813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5569813Slinton 				return( TYPE );
5579813Slinton 				}
5589813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
5599813Slinton 			yylval.intval = id;
5609813Slinton 			return( NAME );
5619813Slinton 
5629813Slinton 		case A_DIG:
5639813Slinton 			/* collect a digit string, then look at last one... */
5649813Slinton 			lastcon = 0;
5659813Slinton 			lxget( lxchar, LEXDIG );
5669813Slinton 			switch( lxchar=getchar() ){
5679813Slinton 
5689813Slinton 			case 'x':
5699813Slinton 			case 'X':
5709813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5719813Slinton 				lxmore( lxchar, LEXHEX );
5729813Slinton 				/* convert the value */
5739813Slinton 				{
5749813Slinton 					register char *cp;
5759813Slinton 					for( cp = yytext+2; *cp; ++cp ){
5769813Slinton 						/* this code won't work for all wild character sets,
5779813Slinton 						   but seems ok for ascii and ebcdic */
5789813Slinton 						lastcon <<= 4;
5799813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
5809813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5819813Slinton 						else lastcon += *cp - 'a'+ 10;
5829813Slinton 						}
5839813Slinton 					}
5849813Slinton 
5859813Slinton 			hexlong:
5869813Slinton 				/* criterion for longness for hex and octal constants is that it
5879813Slinton 				   fit within 0177777 */
5889813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
5899813Slinton 				else yylval.intval = 0;
5909813Slinton 
5919813Slinton 				goto islong;
5929813Slinton 
5939813Slinton 			case '.':
5949813Slinton 				lxmore( lxchar, LEXDIG );
5959813Slinton 
5969813Slinton 			getfp:
5979813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
5989813Slinton 
5999813Slinton 			case 'e':
6009813Slinton 			case 'E':
6019813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
6029813Slinton 						*lxgcp++ = 'e';
6039813Slinton 						}
6049813Slinton 					else {
6059813Slinton 						ungetc(lxchar,stdin);
6069813Slinton 						lxchar = 'e';
6079813Slinton 						}
6089813Slinton 					lxmore( lxchar, LEXDIG );
6099813Slinton 					/* now have the whole thing... */
6109813Slinton 					}
6119813Slinton 				else {  /* no exponent */
6129813Slinton 					ungetc( lxchar ,stdin);
6139813Slinton 					}
6149813Slinton 				return( isitfloat( yytext ) );
6159813Slinton 
6169813Slinton 			default:
6179813Slinton 				ungetc( lxchar ,stdin);
6189813Slinton 				if( yytext[0] == '0' ){
6199813Slinton 					/* convert in octal */
6209813Slinton 					register char *cp;
6219813Slinton 					for( cp = yytext+1; *cp; ++cp ){
6229813Slinton 						lastcon <<= 3;
6239813Slinton 						lastcon += *cp - '0';
6249813Slinton 						}
6259813Slinton 					goto hexlong;
6269813Slinton 					}
6279813Slinton 				else {
6289813Slinton 					/* convert in decimal */
6299813Slinton 					register char *cp;
6309813Slinton 					for( cp = yytext; *cp; ++cp ){
6319813Slinton 						lastcon = lastcon * 10 + *cp - '0';
6329813Slinton 						}
6339813Slinton 					}
6349813Slinton 
6359813Slinton 				/* decide if it is long or not (decimal case) */
6369813Slinton 
6379813Slinton 				/* if it is positive and fits in 15 bits, or negative and
6389813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
6399813Slinton 				/* if there is an l or L following, all bets are off... */
6409813Slinton 
6419813Slinton 				{	CONSZ v;
6429813Slinton 					v = lastcon & ~077777L;
6439813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
6449813Slinton 					else yylval.intval = 1;
6459813Slinton 					}
6469813Slinton 
6479813Slinton 			islong:
6489813Slinton 				/* finally, look for trailing L or l */
6499813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6509813Slinton 				else ungetc( lxchar ,stdin);
6519813Slinton 				return( ICON );
6529813Slinton 				}
6539813Slinton 
6549813Slinton 		case A_DOT:
6559813Slinton 			/* look for a dot: if followed by a digit, floating point */
6569813Slinton 			lxchar = getchar();
6579813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
6589813Slinton 				ungetc(lxchar,stdin);
6599813Slinton 				lxget( '.', LEXDIG );
6609813Slinton 				goto getfp;
6619813Slinton 				}
6629813Slinton 			stwart = FUNNYNAME;
6639813Slinton 			goto onechar;
6649813Slinton 
6659813Slinton 		case A_STR:
6669813Slinton 			/* string constant */
6679813Slinton 			lxmatch = '"';
6689813Slinton 			return( STRING );
6699813Slinton 
6709813Slinton 		case A_CC:
6719813Slinton 			/* character constant */
6729813Slinton 			lxmatch = '\'';
6739813Slinton 			lastcon = 0;
6749813Slinton 			lxstr(0);
6759813Slinton 			yylval.intval = 0;
6769813Slinton 			return( ICON );
6779813Slinton 
6789813Slinton 		case A_BCD:
6799813Slinton 			{
6809813Slinton 				register i;
6819813Slinton 				int j;
6829813Slinton 				for( i=0; i<LXTSZ; ++i ){
6839813Slinton 					if( ( j = getchar() ) == '`' ) break;
6849813Slinton 					if( j == '\n' ){
6859813Slinton 						uerror( "newline in BCD constant" );
6869813Slinton 						break;
6879813Slinton 						}
6889813Slinton 					yytext[i] = j;
6899813Slinton 					}
6909813Slinton 				yytext[i] = '\0';
6919813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
6929813Slinton # ifdef gcos
6939813Slinton 				else strtob( yytext, &lastcon, i );
6949813Slinton 				lastcon >>= 6*(6-i);
6959813Slinton # else
6969813Slinton 				uerror( "gcos BCD constant illegal" );
6979813Slinton # endif
6989813Slinton 				yylval.intval = 0;  /* not long */
6999813Slinton 				return( ICON );
7009813Slinton 				}
7019813Slinton 
7029813Slinton 		case A_SL:
7039813Slinton 			/* / */
7049813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
7059813Slinton 			lxcom();
7069813Slinton 		case A_WS:
7079813Slinton 			continue;
7089813Slinton 
7099813Slinton 		case A_NL:
7109813Slinton 			++lineno;
7119813Slinton 			lxtitle();
7129813Slinton 			continue;
7139813Slinton 
7149813Slinton 		case A_NOT:
7159813Slinton 			/* ! */
7169813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
7179813Slinton 			yylval.intval = NE;
7189813Slinton 			return( EQUOP );
7199813Slinton 
7209813Slinton 		case A_MI:
7219813Slinton 			/* - */
7229813Slinton 			if( (lxchar=getchar()) == '-' ){
7239813Slinton 				yylval.intval = DECR;
7249813Slinton 				return( INCOP );
7259813Slinton 				}
7269813Slinton 			if( lxchar != '>' ) goto onechar;
7279813Slinton 			stwart = FUNNYNAME;
7289813Slinton 			yylval.intval=STREF;
7299813Slinton 			return( STROP );
7309813Slinton 
7319813Slinton 		case A_PL:
7329813Slinton 			/* + */
7339813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
7349813Slinton 			yylval.intval = INCR;
7359813Slinton 			return( INCOP );
7369813Slinton 
7379813Slinton 		case A_AND:
7389813Slinton 			/* & */
7399813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
7409813Slinton 			return( yylval.intval = ANDAND );
7419813Slinton 
7429813Slinton 		case A_OR:
7439813Slinton 			/* | */
7449813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
7459813Slinton 			return( yylval.intval = OROR );
7469813Slinton 
7479813Slinton 		case A_LT:
7489813Slinton 			/* < */
7499813Slinton 			if( (lxchar=getchar()) == '<' ){
7509813Slinton 				yylval.intval = LS;
7519813Slinton 				return( SHIFTOP );
7529813Slinton 				}
7539813Slinton 			if( lxchar != '=' ) goto onechar;
7549813Slinton 			yylval.intval = LE;
7559813Slinton 			return( RELOP );
7569813Slinton 
7579813Slinton 		case A_GT:
7589813Slinton 			/* > */
7599813Slinton 			if( (lxchar=getchar()) == '>' ){
7609813Slinton 				yylval.intval = RS;
7619813Slinton 				return(SHIFTOP );
7629813Slinton 				}
7639813Slinton 			if( lxchar != '=' ) goto onechar;
7649813Slinton 			yylval.intval = GE;
7659813Slinton 			return( RELOP );
7669813Slinton 
7679813Slinton 		case A_EQ:
7689813Slinton 			/* = */
7699813Slinton 			switch( lxchar = getchar() ){
7709813Slinton 
7719813Slinton 			case '=':
7729813Slinton 				yylval.intval = EQ;
7739813Slinton 				return( EQUOP );
7749813Slinton 
77532829Sdonn #ifdef old_assignment_ops
7769813Slinton 			case '+':
7779813Slinton 				yylval.intval = ASG PLUS;
7789813Slinton 				break;
7799813Slinton 
7809813Slinton 			case '-':
7819813Slinton 				yylval.intval = ASG MINUS;
7829813Slinton 
7839813Slinton 			warn:
7849813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
7859813Slinton 					werror( "ambiguous assignment: assignment op taken" );
7869813Slinton 					}
7879813Slinton 				ungetc( lxchar ,stdin);
7889813Slinton 				break;
7899813Slinton 
7909813Slinton 			case '*':
7919813Slinton 				yylval.intval = ASG MUL;
7929813Slinton 				goto warn;
7939813Slinton 
7949813Slinton 			case '/':
7959813Slinton 				yylval.intval = ASG DIV;
7969813Slinton 				break;
7979813Slinton 
7989813Slinton 			case '%':
7999813Slinton 				yylval.intval = ASG MOD;
8009813Slinton 				break;
8019813Slinton 
8029813Slinton 			case '&':
8039813Slinton 				yylval.intval = ASG AND;
8049813Slinton 				break;
8059813Slinton 
8069813Slinton 			case '|':
8079813Slinton 				yylval.intval = ASG OR;
8089813Slinton 				break;
8099813Slinton 
8109813Slinton 			case '^':
8119813Slinton 				yylval.intval = ASG ER;
8129813Slinton 				break;
8139813Slinton 
8149813Slinton 			case '<':
8159813Slinton 				if( (lxchar=getchar()) != '<' ){
8169813Slinton 					uerror( "=<%c illegal", lxchar );
8179813Slinton 					}
8189813Slinton 				yylval.intval = ASG LS;
8199813Slinton 				break;
8209813Slinton 
8219813Slinton 			case '>':
8229813Slinton 				if( (lxchar=getchar()) != '>' ){
8239813Slinton 					uerror( "=>%c illegal", lxchar );
8249813Slinton 					}
8259813Slinton 				yylval.intval = ASG RS;
8269813Slinton 				break;
82732829Sdonn #endif old_assignment_ops
8289813Slinton 
8299813Slinton 			default:
8309813Slinton 				goto onechar;
8319813Slinton 
8329813Slinton 				}
8339813Slinton 
83432831Sdonn #ifdef old_assignment_ops	/* defeat 'unreachable code' warning */
8359813Slinton 			return( ASOP );
83632831Sdonn #endif old_assignment_ops
8379813Slinton 
8389813Slinton 		default:
8399813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
8409813Slinton 
8419813Slinton 			}
8429813Slinton 
8439813Slinton 		/* ordinarily, repeat here... */
8449813Slinton 		cerror( "out of switch in yylex" );
8459813Slinton 
8469813Slinton 		}
8479813Slinton 
8489813Slinton 	}
8499813Slinton 
8509813Slinton struct lxrdope {
8519813Slinton 	/* dope for reserved, in alphabetical order */
8529813Slinton 
8539813Slinton 	char *lxrch;	/* name of reserved word */
8549813Slinton 	short lxract;	/* reserved word action */
8559813Slinton 	short lxrval;	/* value to be returned */
8569813Slinton 	} lxrdope[] = {
8579813Slinton 
8589813Slinton 	"asm",		AR_A,	0,
8599813Slinton 	"auto",		AR_CL,	AUTO,
8609813Slinton 	"break",	AR_RW,	BREAK,
8619813Slinton 	"char",		AR_TY,	CHAR,
8629813Slinton 	"case",		AR_RW,	CASE,
8639813Slinton 	"continue",	AR_RW,	CONTINUE,
8649813Slinton 	"double",	AR_TY,	DOUBLE,
8659813Slinton 	"default",	AR_RW,	DEFAULT,
8669813Slinton 	"do",		AR_RW,	DO,
8679813Slinton 	"extern",	AR_CL,	EXTERN,
8689813Slinton 	"else",		AR_RW,	ELSE,
8699813Slinton 	"enum",		AR_E,	ENUM,
8709813Slinton 	"for",		AR_RW,	FOR,
8719813Slinton 	"float",	AR_TY,	FLOAT,
8729813Slinton 	"fortran",	AR_CL,	FORTRAN,
8739813Slinton 	"goto",		AR_RW,	GOTO,
8749813Slinton 	"if",		AR_RW,	IF,
8759813Slinton 	"int",		AR_TY,	INT,
8769813Slinton 	"long",		AR_TY,	LONG,
8779813Slinton 	"return",	AR_RW,	RETURN,
8789813Slinton 	"register",	AR_CL,	REGISTER,
8799813Slinton 	"switch",	AR_RW,	SWITCH,
8809813Slinton 	"struct",	AR_S,	0,
8819813Slinton 	"sizeof",	AR_RW,	SIZEOF,
8829813Slinton 	"short",	AR_TY,	SHORT,
8839813Slinton 	"static",	AR_CL,	STATIC,
8849813Slinton 	"typedef",	AR_CL,	TYPEDEF,
8859813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
8869813Slinton 	"union",	AR_U,	0,
8879813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
8889813Slinton 	"while",	AR_RW,	WHILE,
8899813Slinton 	"",		0,	0,	/* to stop the search */
8909813Slinton 	};
8919813Slinton 
8929813Slinton lxres() {
8939813Slinton 	/* check to see of yytext is reserved; if so,
8949813Slinton 	/* do the appropriate action and return */
8959813Slinton 	/* otherwise, return -1 */
8969813Slinton 
8979813Slinton 	register c, ch;
8989813Slinton 	register struct lxrdope *p;
8999813Slinton 
9009813Slinton 	ch = yytext[0];
9019813Slinton 
9029813Slinton 	if( !islower(ch) ) return( -1 );
9039813Slinton 
9049813Slinton 	switch( ch ){
9059813Slinton 
9069813Slinton 	case 'a':
9079813Slinton 		c=0; break;
9089813Slinton 	case 'b':
9099813Slinton 		c=2; break;
9109813Slinton 	case 'c':
9119813Slinton 		c=3; break;
9129813Slinton 	case 'd':
9139813Slinton 		c=6; break;
9149813Slinton 	case 'e':
9159813Slinton 		c=9; break;
9169813Slinton 	case 'f':
9179813Slinton 		c=12; break;
9189813Slinton 	case 'g':
9199813Slinton 		c=15; break;
9209813Slinton 	case 'i':
9219813Slinton 		c=16; break;
9229813Slinton 	case 'l':
9239813Slinton 		c=18; break;
9249813Slinton 	case 'r':
9259813Slinton 		c=19; break;
9269813Slinton 	case 's':
9279813Slinton 		c=21; break;
9289813Slinton 	case 't':
9299813Slinton 		c=26; break;
9309813Slinton 	case 'u':
9319813Slinton 		c=27; break;
9329813Slinton 	case 'v':
9339813Slinton 		c=29; break;
9349813Slinton 	case 'w':
9359813Slinton 		c=30; break;
9369813Slinton 
9379813Slinton 	default:
9389813Slinton 		return( -1 );
9399813Slinton 		}
9409813Slinton 
9419813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9429813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
9439813Slinton 			switch( p->lxract ){
9449813Slinton 
9459813Slinton 			case AR_TY:
9469813Slinton 				/* type word */
9479813Slinton 				stwart = instruct;
9489813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9499813Slinton 				return( TYPE );
9509813Slinton 
9519813Slinton 			case AR_RW:
9529813Slinton 				/* ordinary reserved word */
9539813Slinton 				return( yylval.intval = p->lxrval );
9549813Slinton 
9559813Slinton 			case AR_CL:
9569813Slinton 				/* class word */
9579813Slinton 				yylval.intval = p->lxrval;
9589813Slinton 				return( CLASS );
9599813Slinton 
9609813Slinton 			case AR_S:
9619813Slinton 				/* struct */
9629813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
9639813Slinton 				yylval.intval = INSTRUCT;
9649813Slinton 				return( STRUCT );
9659813Slinton 
9669813Slinton 			case AR_U:
9679813Slinton 				/* union */
9689813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
9699813Slinton 				yylval.intval = INUNION;
9709813Slinton 				return( STRUCT );
9719813Slinton 
9729813Slinton 			case AR_E:
9739813Slinton 				/* enums */
9749813Slinton 				stwart = SEENAME|TAGNAME;
9759813Slinton 				return( yylval.intval = ENUM );
9769813Slinton 
9779813Slinton 			case AR_A:
9789813Slinton 				/* asm */
9799813Slinton 				asm_esc = 1; /* warn the world! */
9809813Slinton 				lxget( ' ', LEXWS );
9819813Slinton 				if( getchar() != '(' ) goto badasm;
9829813Slinton 				lxget( ' ', LEXWS );
9839813Slinton 				if( getchar() != '"' ) goto badasm;
9849813Slinton # ifndef ONEPASS
9859813Slinton # ifndef LINT
9869813Slinton 				putchar(')');
9879813Slinton # endif
9889813Slinton # endif
9899813Slinton 				while( (c=getchar()) != '"' ){
9909813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
9919813Slinton # ifndef LINT
9929813Slinton 					putchar(c);
9939813Slinton # endif
9949813Slinton 					}
9959813Slinton 				lxget( ' ', LEXWS );
9969813Slinton 				if( getchar() != ')' ) goto badasm;
9979813Slinton # ifndef LINT
9989813Slinton 				putchar('\n');
9999813Slinton # endif
10009813Slinton 				return( 0 );
10019813Slinton 
10029813Slinton 			badasm:
10039813Slinton 				uerror( "bad asm construction" );
10049813Slinton 				return( 0 );
10059813Slinton 
10069813Slinton 			default:
10079813Slinton 				cerror( "bad AR_?? action" );
10089813Slinton 				}
10099813Slinton 			}
10109813Slinton 		}
10119813Slinton 	return( -1 );
10129813Slinton 	}
10139813Slinton 
10149813Slinton extern int	labelno;
10159813Slinton 
10169813Slinton lxtitle(){
10179813Slinton 	/* called after a newline; set linenumber and file name */
10189813Slinton 
10199813Slinton 	register c, val;
10209813Slinton 	register char *cp, *cq;
10219813Slinton 
10229813Slinton 	for(;;){  /* might be several such lines in a row */
10239813Slinton 		if( (c=getchar()) != '#' ){
10249813Slinton 			if( c != EOF ) ungetc(c,stdin);
10259813Slinton #ifndef LINT
10269813Slinton 			if ( lastloc != PROG) return;
10279813Slinton 			cp = ftitle;
10289813Slinton 			cq = ititle;
10299813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
10309813Slinton 			if ( *cq ) return;
103132830Sdonn 			if( nerrors == 0 ) psline();
10329813Slinton #endif
10339813Slinton 			return;
10349813Slinton 			}
10359813Slinton 
10369813Slinton 		lxget( ' ', LEXWS );
103732832Sdonn 		c = getchar();
103832832Sdonn 		if( c == 'i' ){
103932832Sdonn 			/* #ident -- currently a no-op */
104032832Sdonn 			lxget( c, LEXLET );
104132832Sdonn 			if( strcmp( yytext, "ident" ) )
104232832Sdonn 				werror( "%s: undefined control", yytext );
104332832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
104432832Sdonn 				;
104532832Sdonn 			continue;
104632832Sdonn 			}
104732832Sdonn 		if( c == 'p' ){
104832832Sdonn 			/* #pragma -- special instructions */
104932832Sdonn 			lxget( c, LEXLET );
105032832Sdonn 			if( strcmp( yytext, "pragma" ) ) {
105132832Sdonn 				werror( "%s: undefined control", yytext );
105232832Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
105332832Sdonn 					;
105432832Sdonn 				continue;
105532832Sdonn 				}
105632832Sdonn 			lxget( ' ' , LEXWS );
105732832Sdonn 			switch( c = getchar() ){
105832832Sdonn # ifdef LINT
105932832Sdonn 			case 'V':
106032832Sdonn 				lxget( c, LEXLET|LEXDIG );
106132832Sdonn 				{
106232832Sdonn 					extern int vaflag;
106332832Sdonn 					int i;
106432832Sdonn 					i = yytext[7]?yytext[7]-'0':0;
106532832Sdonn 					yytext[7] = '\0';
106632832Sdonn 					if( strcmp( yytext, "VARARGS" ) ) break;
106732832Sdonn 					vaflag = i;
106832832Sdonn 					break;
106932832Sdonn 					}
107032832Sdonn 			case 'L':
107132832Sdonn 				lxget( c, LEXLET );
107232832Sdonn 				if( strcmp( yytext, "LINTLIBRARY" ) ) break;
107332832Sdonn 				{
107432832Sdonn 					extern int libflag;
107532832Sdonn 					libflag = 1;
107632832Sdonn 					}
107732832Sdonn 				break;
107832832Sdonn 
107932832Sdonn 			case 'A':
108032832Sdonn 				lxget( c, LEXLET );
108132832Sdonn 				if( strcmp( yytext, "ARGSUSED" ) ) break;
108232832Sdonn 				{
108332832Sdonn 					extern int argflag, vflag;
108432832Sdonn 					argflag = 1;
108532832Sdonn 					vflag = 0;
108632832Sdonn 					}
108732832Sdonn 				break;
108832832Sdonn 
108932832Sdonn 			case 'N':
109032832Sdonn 				lxget( c, LEXLET );
109132832Sdonn 				if( strcmp( yytext, "NOTREACHED" ) ) break;
109232832Sdonn 				reached = 0;
109332832Sdonn 				break;
109432832Sdonn #endif
109532832Sdonn 
109632832Sdonn 			case '\n':
109732832Sdonn 			case EOF:
109832832Sdonn 				continue;
109932832Sdonn 				}
110032832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
110132832Sdonn 				;
110232832Sdonn 			continue;
110332832Sdonn 			}
110432833Sdonn 		if( c == 'l' ){
110532833Sdonn 			/* #line -- just like # */
110632833Sdonn 			lxget( c, LEXLET );
110732833Sdonn 			if( strcmp( yytext, "line" ) ){
110832833Sdonn 				werror( "%s: undefined control", yytext );
110932833Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
111032833Sdonn 					;
111132833Sdonn 				continue;
111232833Sdonn 				}
111332833Sdonn 			lxget( ' ', LEXWS );
111432833Sdonn 			c = getchar();
111532833Sdonn 			}
111632832Sdonn 		if( !isdigit(c) ){
111732832Sdonn 			if( isalpha(c) ){
111832832Sdonn 				lxget( c, LEXLET );
111932832Sdonn 				werror( "%s: undefined control", yytext );
112032832Sdonn 				}
112132833Sdonn 			while( c != '\n' && c != EOF )
112232833Sdonn 				c = getchar();
112332832Sdonn 			continue;
112432832Sdonn 			}
112532832Sdonn 
11269813Slinton 		val = 0;
112732832Sdonn 		do {
11289813Slinton 			val = val*10+ c - '0';
11299813Slinton 			}
113032832Sdonn 		while( isdigit( c = getchar() ) );
113132832Sdonn 
113217748Sralph 		if( c == EOF )
113317748Sralph 			continue;
11349813Slinton 		ungetc( c, stdin );
11359813Slinton 		lineno = val;
11369813Slinton 		lxget( ' ', LEXWS );
113717748Sralph 		if( (c=getchar()) != '\n' && c != EOF ){
113817748Sralph 			for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
11399813Slinton 				*cp = c;
11409813Slinton 				}
11419813Slinton 			*cp = '\0';
11429813Slinton #ifndef LINT
11439813Slinton 			if (ititle[0] == '\0') {
11449813Slinton 				cp = ftitle;
11459813Slinton 				cq = ititle;
11469813Slinton 				while ( *cp )
11479813Slinton 					*cq++ = *cp++;
11489813Slinton 				*cq = '\0';
11499813Slinton 				*--cq = '\0';
11509813Slinton #ifndef FLEXNAMES
11519813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
11529813Slinton 					pstab(cp, N_SO);
11539813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
11549813Slinton 					}
11559813Slinton #else
11569813Slinton 				pstab(ititle+1, N_SO);
11579813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
11589813Slinton #endif
11599813Slinton 
11609813Slinton 				*cq = '"';
11619813Slinton 				printf("LL%d:\n", labelno++);
11629813Slinton 				}
11639813Slinton #endif
11649813Slinton 			}
11659813Slinton 		}
11669813Slinton 	}
11679813Slinton 
11689813Slinton #ifdef FLEXNAMES
11699813Slinton #define	NSAVETAB	4096
11709813Slinton char	*savetab;
117132836Sdonn unsigned saveleft;
117232836Sdonn char	*malloc();
117332836Sdonn char	*calloc();
117432836Sdonn char	*strncpy();
11759813Slinton 
11769813Slinton char *
11779813Slinton savestr(cp)
11789813Slinton 	register char *cp;
11799813Slinton {
11809813Slinton 	register int len;
11819813Slinton 
11829813Slinton 	len = strlen(cp) + 1;
11839813Slinton 	if (len > saveleft) {
11849813Slinton 		saveleft = NSAVETAB;
11859813Slinton 		if (len > saveleft)
11869813Slinton 			saveleft = len;
118732836Sdonn 		savetab = malloc(saveleft);
11889813Slinton 		if (savetab == 0)
11899813Slinton 			cerror("Ran out of memory (savestr)");
11909813Slinton 	}
119132836Sdonn 	(void) strncpy(savetab, cp, len);
11929813Slinton 	cp = savetab;
11939813Slinton 	savetab += len;
11949813Slinton 	saveleft -= len;
11959813Slinton 	return (cp);
11969813Slinton }
11979813Slinton 
11989813Slinton /*
11999813Slinton  * The definition for the segmented hash tables.
12009813Slinton  */
12019813Slinton #define	MAXHASH	20
12029813Slinton #define	HASHINC	1013
12039813Slinton struct ht {
12049813Slinton 	char	**ht_low;
12059813Slinton 	char	**ht_high;
12069813Slinton 	int	ht_used;
12079813Slinton } htab[MAXHASH];
12089813Slinton 
12099813Slinton char *
12109813Slinton hash(s)
12119813Slinton 	char *s;
12129813Slinton {
12139813Slinton 	register char **h;
12149813Slinton 	register i;
12159813Slinton 	register char *cp;
12169813Slinton 	struct ht *htp;
12179813Slinton 	int sh;
12189813Slinton 
12199813Slinton 	/*
12209813Slinton 	 * The hash function is a modular hash of
12219813Slinton 	 * the sum of the characters with the sum
12229813Slinton 	 * doubled before each successive character
12239813Slinton 	 * is added.
12249813Slinton 	 */
12259813Slinton 	cp = s;
12269813Slinton 	i = 0;
12279813Slinton 	while (*cp)
12289813Slinton 		i = i*2 + *cp++;
12299813Slinton 	sh = (i&077777) % HASHINC;
12309813Slinton 	cp = s;
12319813Slinton 	/*
12329813Slinton 	 * There are as many as MAXHASH active
12339813Slinton 	 * hash tables at any given point in time.
12349813Slinton 	 * The search starts with the first table
12359813Slinton 	 * and continues through the active tables
12369813Slinton 	 * as necessary.
12379813Slinton 	 */
12389813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
12399813Slinton 		if (htp->ht_low == 0) {
12409813Slinton 			register char **hp =
12419813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
12429813Slinton 			if (hp == 0)
12439813Slinton 				cerror("ran out of memory (hash)");
12449813Slinton 			htp->ht_low = hp;
12459813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
12469813Slinton 		}
12479813Slinton 		h = htp->ht_low + sh;
12489813Slinton 		/*
12499813Slinton 		 * quadratic rehash increment
12509813Slinton 		 * starts at 1 and incremented
12519813Slinton 		 * by two each rehash.
12529813Slinton 		 */
12539813Slinton 		i = 1;
12549813Slinton 		do {
12559813Slinton 			if (*h == 0) {
12569813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
12579813Slinton 					break;
12589813Slinton 				htp->ht_used++;
12599813Slinton 				*h = savestr(cp);
12609813Slinton 				return (*h);
12619813Slinton 			}
12629813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
12639813Slinton 				return (*h);
12649813Slinton 			h += i;
12659813Slinton 			i += 2;
12669813Slinton 			if (h >= htp->ht_high)
12679813Slinton 				h -= HASHINC;
12689813Slinton 		} while (i < HASHINC);
12699813Slinton 	}
12709813Slinton 	cerror("ran out of hash tables");
127132836Sdonn 	/*NOTREACHED*/
12729813Slinton }
12739813Slinton #endif
1274