xref: /csrg-svn/old/pcc/mip/scan.c (revision 32833)
117748Sralph #ifndef lint
2*32833Sdonn static char *sccsid ="@(#)scan.c	2.9 (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;
8332829Sdonn 	char *release = "PCC/364r1 vax uts3.0";
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
1479813Slinton 	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 
1789813Slinton 	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 
3109813Slinton int lxmatch;  /* 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 		}
4289813Slinton 	}
4299813Slinton 
4309813Slinton lxcom(){
4319813Slinton 	register c;
4329813Slinton 	/* saw a /*: process a comment */
4339813Slinton 
4349813Slinton 	for(;;){
4359813Slinton 
4369813Slinton 		switch( c = getchar() ){
4379813Slinton 
4389813Slinton 		case EOF:
4399813Slinton 			uerror( "unexpected EOF" );
4409813Slinton 			return;
4419813Slinton 
4429813Slinton 		case '\n':
4439813Slinton 			++lineno;
4449813Slinton 
4459813Slinton 		default:
4469813Slinton 			continue;
4479813Slinton 
4489813Slinton 		case '*':
4499813Slinton 			if( (c = getchar()) == '/' ) return;
4509813Slinton 			else ungetc( c ,stdin);
4519813Slinton 			continue;
4529813Slinton 
4539813Slinton # ifdef LINT
4549813Slinton 		case 'V':
4559813Slinton 			lxget( c, LEXLET|LEXDIG );
4569813Slinton 			{
4579813Slinton 				extern int vaflag;
4589813Slinton 				int i;
4599813Slinton 				i = yytext[7]?yytext[7]-'0':0;
4609813Slinton 				yytext[7] = '\0';
4619813Slinton 				if( strcmp( yytext, "VARARGS" ) ) continue;
4629813Slinton 				vaflag = i;
4639813Slinton 				continue;
4649813Slinton 				}
4659813Slinton 		case 'L':
4669813Slinton 			lxget( c, LEXLET );
4679813Slinton 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
4689813Slinton 			{
4699813Slinton 				extern int libflag;
4709813Slinton 				libflag = 1;
4719813Slinton 				}
4729813Slinton 			continue;
4739813Slinton 
4749813Slinton 		case 'A':
4759813Slinton 			lxget( c, LEXLET );
4769813Slinton 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
4779813Slinton 			{
4789813Slinton 				extern int argflag, vflag;
4799813Slinton 				argflag = 1;
4809813Slinton 				vflag = 0;
4819813Slinton 				}
4829813Slinton 			continue;
4839813Slinton 
4849813Slinton 		case 'N':
4859813Slinton 			lxget( c, LEXLET );
4869813Slinton 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
4879813Slinton 			reached = 0;
4889813Slinton 			continue;
4899813Slinton # endif
4909813Slinton 			}
4919813Slinton 		}
4929813Slinton 	}
4939813Slinton 
4949813Slinton yylex(){
4959813Slinton 	for(;;){
4969813Slinton 
4979813Slinton 		register lxchar;
4989813Slinton 		register struct lxdope *p;
4999813Slinton 		register struct symtab *sp;
5009813Slinton 		int id;
5019813Slinton 
5029813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
5039813Slinton 
5049813Slinton 		onechar:
5059813Slinton 			ungetc( lxchar ,stdin);
5069813Slinton 
5079813Slinton 		case A_1C:
5089813Slinton 			/* eat up a single character, and return an opcode */
5099813Slinton 
5109813Slinton 			yylval.intval = p->lxval;
5119813Slinton 			return( p->lxtok );
5129813Slinton 
5139813Slinton 		case A_ERR:
5149813Slinton 			uerror( "illegal character: %03o (octal)", lxchar );
5159813Slinton 			break;
5169813Slinton 
5179813Slinton 		case A_LET:
5189813Slinton 			/* collect an identifier, check for reserved word, and return */
5199813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
5209813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5219813Slinton 			if( lxchar== 0 ) continue;
5229813Slinton #ifdef FLEXNAMES
5239813Slinton 			id = lookup( hash(yytext),
5249813Slinton #else
5259813Slinton 			id = lookup( yytext,
5269813Slinton #endif
5279813Slinton 				/* tag name for struct/union/enum */
5289813Slinton 				(stwart&TAGNAME)? STAG:
5299813Slinton 				/* member name for struct/union */
5309813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5319813Slinton 			sp = &stab[id];
5329813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
5339813Slinton 				stwart = instruct;
5349813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5359813Slinton 				return( TYPE );
5369813Slinton 				}
5379813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
5389813Slinton 			yylval.intval = id;
5399813Slinton 			return( NAME );
5409813Slinton 
5419813Slinton 		case A_DIG:
5429813Slinton 			/* collect a digit string, then look at last one... */
5439813Slinton 			lastcon = 0;
5449813Slinton 			lxget( lxchar, LEXDIG );
5459813Slinton 			switch( lxchar=getchar() ){
5469813Slinton 
5479813Slinton 			case 'x':
5489813Slinton 			case 'X':
5499813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5509813Slinton 				lxmore( lxchar, LEXHEX );
5519813Slinton 				/* convert the value */
5529813Slinton 				{
5539813Slinton 					register char *cp;
5549813Slinton 					for( cp = yytext+2; *cp; ++cp ){
5559813Slinton 						/* this code won't work for all wild character sets,
5569813Slinton 						   but seems ok for ascii and ebcdic */
5579813Slinton 						lastcon <<= 4;
5589813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
5599813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5609813Slinton 						else lastcon += *cp - 'a'+ 10;
5619813Slinton 						}
5629813Slinton 					}
5639813Slinton 
5649813Slinton 			hexlong:
5659813Slinton 				/* criterion for longness for hex and octal constants is that it
5669813Slinton 				   fit within 0177777 */
5679813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
5689813Slinton 				else yylval.intval = 0;
5699813Slinton 
5709813Slinton 				goto islong;
5719813Slinton 
5729813Slinton 			case '.':
5739813Slinton 				lxmore( lxchar, LEXDIG );
5749813Slinton 
5759813Slinton 			getfp:
5769813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
5779813Slinton 
5789813Slinton 			case 'e':
5799813Slinton 			case 'E':
5809813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
5819813Slinton 						*lxgcp++ = 'e';
5829813Slinton 						}
5839813Slinton 					else {
5849813Slinton 						ungetc(lxchar,stdin);
5859813Slinton 						lxchar = 'e';
5869813Slinton 						}
5879813Slinton 					lxmore( lxchar, LEXDIG );
5889813Slinton 					/* now have the whole thing... */
5899813Slinton 					}
5909813Slinton 				else {  /* no exponent */
5919813Slinton 					ungetc( lxchar ,stdin);
5929813Slinton 					}
5939813Slinton 				return( isitfloat( yytext ) );
5949813Slinton 
5959813Slinton 			default:
5969813Slinton 				ungetc( lxchar ,stdin);
5979813Slinton 				if( yytext[0] == '0' ){
5989813Slinton 					/* convert in octal */
5999813Slinton 					register char *cp;
6009813Slinton 					for( cp = yytext+1; *cp; ++cp ){
6019813Slinton 						lastcon <<= 3;
6029813Slinton 						lastcon += *cp - '0';
6039813Slinton 						}
6049813Slinton 					goto hexlong;
6059813Slinton 					}
6069813Slinton 				else {
6079813Slinton 					/* convert in decimal */
6089813Slinton 					register char *cp;
6099813Slinton 					for( cp = yytext; *cp; ++cp ){
6109813Slinton 						lastcon = lastcon * 10 + *cp - '0';
6119813Slinton 						}
6129813Slinton 					}
6139813Slinton 
6149813Slinton 				/* decide if it is long or not (decimal case) */
6159813Slinton 
6169813Slinton 				/* if it is positive and fits in 15 bits, or negative and
6179813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
6189813Slinton 				/* if there is an l or L following, all bets are off... */
6199813Slinton 
6209813Slinton 				{	CONSZ v;
6219813Slinton 					v = lastcon & ~077777L;
6229813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
6239813Slinton 					else yylval.intval = 1;
6249813Slinton 					}
6259813Slinton 
6269813Slinton 			islong:
6279813Slinton 				/* finally, look for trailing L or l */
6289813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6299813Slinton 				else ungetc( lxchar ,stdin);
6309813Slinton 				return( ICON );
6319813Slinton 				}
6329813Slinton 
6339813Slinton 		case A_DOT:
6349813Slinton 			/* look for a dot: if followed by a digit, floating point */
6359813Slinton 			lxchar = getchar();
6369813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
6379813Slinton 				ungetc(lxchar,stdin);
6389813Slinton 				lxget( '.', LEXDIG );
6399813Slinton 				goto getfp;
6409813Slinton 				}
6419813Slinton 			stwart = FUNNYNAME;
6429813Slinton 			goto onechar;
6439813Slinton 
6449813Slinton 		case A_STR:
6459813Slinton 			/* string constant */
6469813Slinton 			lxmatch = '"';
6479813Slinton 			return( STRING );
6489813Slinton 
6499813Slinton 		case A_CC:
6509813Slinton 			/* character constant */
6519813Slinton 			lxmatch = '\'';
6529813Slinton 			lastcon = 0;
6539813Slinton 			lxstr(0);
6549813Slinton 			yylval.intval = 0;
6559813Slinton 			return( ICON );
6569813Slinton 
6579813Slinton 		case A_BCD:
6589813Slinton 			{
6599813Slinton 				register i;
6609813Slinton 				int j;
6619813Slinton 				for( i=0; i<LXTSZ; ++i ){
6629813Slinton 					if( ( j = getchar() ) == '`' ) break;
6639813Slinton 					if( j == '\n' ){
6649813Slinton 						uerror( "newline in BCD constant" );
6659813Slinton 						break;
6669813Slinton 						}
6679813Slinton 					yytext[i] = j;
6689813Slinton 					}
6699813Slinton 				yytext[i] = '\0';
6709813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
6719813Slinton # ifdef gcos
6729813Slinton 				else strtob( yytext, &lastcon, i );
6739813Slinton 				lastcon >>= 6*(6-i);
6749813Slinton # else
6759813Slinton 				uerror( "gcos BCD constant illegal" );
6769813Slinton # endif
6779813Slinton 				yylval.intval = 0;  /* not long */
6789813Slinton 				return( ICON );
6799813Slinton 				}
6809813Slinton 
6819813Slinton 		case A_SL:
6829813Slinton 			/* / */
6839813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
6849813Slinton 			lxcom();
6859813Slinton 		case A_WS:
6869813Slinton 			continue;
6879813Slinton 
6889813Slinton 		case A_NL:
6899813Slinton 			++lineno;
6909813Slinton 			lxtitle();
6919813Slinton 			continue;
6929813Slinton 
6939813Slinton 		case A_NOT:
6949813Slinton 			/* ! */
6959813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
6969813Slinton 			yylval.intval = NE;
6979813Slinton 			return( EQUOP );
6989813Slinton 
6999813Slinton 		case A_MI:
7009813Slinton 			/* - */
7019813Slinton 			if( (lxchar=getchar()) == '-' ){
7029813Slinton 				yylval.intval = DECR;
7039813Slinton 				return( INCOP );
7049813Slinton 				}
7059813Slinton 			if( lxchar != '>' ) goto onechar;
7069813Slinton 			stwart = FUNNYNAME;
7079813Slinton 			yylval.intval=STREF;
7089813Slinton 			return( STROP );
7099813Slinton 
7109813Slinton 		case A_PL:
7119813Slinton 			/* + */
7129813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
7139813Slinton 			yylval.intval = INCR;
7149813Slinton 			return( INCOP );
7159813Slinton 
7169813Slinton 		case A_AND:
7179813Slinton 			/* & */
7189813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
7199813Slinton 			return( yylval.intval = ANDAND );
7209813Slinton 
7219813Slinton 		case A_OR:
7229813Slinton 			/* | */
7239813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
7249813Slinton 			return( yylval.intval = OROR );
7259813Slinton 
7269813Slinton 		case A_LT:
7279813Slinton 			/* < */
7289813Slinton 			if( (lxchar=getchar()) == '<' ){
7299813Slinton 				yylval.intval = LS;
7309813Slinton 				return( SHIFTOP );
7319813Slinton 				}
7329813Slinton 			if( lxchar != '=' ) goto onechar;
7339813Slinton 			yylval.intval = LE;
7349813Slinton 			return( RELOP );
7359813Slinton 
7369813Slinton 		case A_GT:
7379813Slinton 			/* > */
7389813Slinton 			if( (lxchar=getchar()) == '>' ){
7399813Slinton 				yylval.intval = RS;
7409813Slinton 				return(SHIFTOP );
7419813Slinton 				}
7429813Slinton 			if( lxchar != '=' ) goto onechar;
7439813Slinton 			yylval.intval = GE;
7449813Slinton 			return( RELOP );
7459813Slinton 
7469813Slinton 		case A_EQ:
7479813Slinton 			/* = */
7489813Slinton 			switch( lxchar = getchar() ){
7499813Slinton 
7509813Slinton 			case '=':
7519813Slinton 				yylval.intval = EQ;
7529813Slinton 				return( EQUOP );
7539813Slinton 
75432829Sdonn #ifdef old_assignment_ops
7559813Slinton 			case '+':
7569813Slinton 				yylval.intval = ASG PLUS;
7579813Slinton 				break;
7589813Slinton 
7599813Slinton 			case '-':
7609813Slinton 				yylval.intval = ASG MINUS;
7619813Slinton 
7629813Slinton 			warn:
7639813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
7649813Slinton 					werror( "ambiguous assignment: assignment op taken" );
7659813Slinton 					}
7669813Slinton 				ungetc( lxchar ,stdin);
7679813Slinton 				break;
7689813Slinton 
7699813Slinton 			case '*':
7709813Slinton 				yylval.intval = ASG MUL;
7719813Slinton 				goto warn;
7729813Slinton 
7739813Slinton 			case '/':
7749813Slinton 				yylval.intval = ASG DIV;
7759813Slinton 				break;
7769813Slinton 
7779813Slinton 			case '%':
7789813Slinton 				yylval.intval = ASG MOD;
7799813Slinton 				break;
7809813Slinton 
7819813Slinton 			case '&':
7829813Slinton 				yylval.intval = ASG AND;
7839813Slinton 				break;
7849813Slinton 
7859813Slinton 			case '|':
7869813Slinton 				yylval.intval = ASG OR;
7879813Slinton 				break;
7889813Slinton 
7899813Slinton 			case '^':
7909813Slinton 				yylval.intval = ASG ER;
7919813Slinton 				break;
7929813Slinton 
7939813Slinton 			case '<':
7949813Slinton 				if( (lxchar=getchar()) != '<' ){
7959813Slinton 					uerror( "=<%c illegal", lxchar );
7969813Slinton 					}
7979813Slinton 				yylval.intval = ASG LS;
7989813Slinton 				break;
7999813Slinton 
8009813Slinton 			case '>':
8019813Slinton 				if( (lxchar=getchar()) != '>' ){
8029813Slinton 					uerror( "=>%c illegal", lxchar );
8039813Slinton 					}
8049813Slinton 				yylval.intval = ASG RS;
8059813Slinton 				break;
80632829Sdonn #endif old_assignment_ops
8079813Slinton 
8089813Slinton 			default:
8099813Slinton 				goto onechar;
8109813Slinton 
8119813Slinton 				}
8129813Slinton 
81332831Sdonn #ifdef old_assignment_ops	/* defeat 'unreachable code' warning */
8149813Slinton 			return( ASOP );
81532831Sdonn #endif old_assignment_ops
8169813Slinton 
8179813Slinton 		default:
8189813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
8199813Slinton 
8209813Slinton 			}
8219813Slinton 
8229813Slinton 		/* ordinarily, repeat here... */
8239813Slinton 		cerror( "out of switch in yylex" );
8249813Slinton 
8259813Slinton 		}
8269813Slinton 
8279813Slinton 	}
8289813Slinton 
8299813Slinton struct lxrdope {
8309813Slinton 	/* dope for reserved, in alphabetical order */
8319813Slinton 
8329813Slinton 	char *lxrch;	/* name of reserved word */
8339813Slinton 	short lxract;	/* reserved word action */
8349813Slinton 	short lxrval;	/* value to be returned */
8359813Slinton 	} lxrdope[] = {
8369813Slinton 
8379813Slinton 	"asm",		AR_A,	0,
8389813Slinton 	"auto",		AR_CL,	AUTO,
8399813Slinton 	"break",	AR_RW,	BREAK,
8409813Slinton 	"char",		AR_TY,	CHAR,
8419813Slinton 	"case",		AR_RW,	CASE,
8429813Slinton 	"continue",	AR_RW,	CONTINUE,
8439813Slinton 	"double",	AR_TY,	DOUBLE,
8449813Slinton 	"default",	AR_RW,	DEFAULT,
8459813Slinton 	"do",		AR_RW,	DO,
8469813Slinton 	"extern",	AR_CL,	EXTERN,
8479813Slinton 	"else",		AR_RW,	ELSE,
8489813Slinton 	"enum",		AR_E,	ENUM,
8499813Slinton 	"for",		AR_RW,	FOR,
8509813Slinton 	"float",	AR_TY,	FLOAT,
8519813Slinton 	"fortran",	AR_CL,	FORTRAN,
8529813Slinton 	"goto",		AR_RW,	GOTO,
8539813Slinton 	"if",		AR_RW,	IF,
8549813Slinton 	"int",		AR_TY,	INT,
8559813Slinton 	"long",		AR_TY,	LONG,
8569813Slinton 	"return",	AR_RW,	RETURN,
8579813Slinton 	"register",	AR_CL,	REGISTER,
8589813Slinton 	"switch",	AR_RW,	SWITCH,
8599813Slinton 	"struct",	AR_S,	0,
8609813Slinton 	"sizeof",	AR_RW,	SIZEOF,
8619813Slinton 	"short",	AR_TY,	SHORT,
8629813Slinton 	"static",	AR_CL,	STATIC,
8639813Slinton 	"typedef",	AR_CL,	TYPEDEF,
8649813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
8659813Slinton 	"union",	AR_U,	0,
8669813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
8679813Slinton 	"while",	AR_RW,	WHILE,
8689813Slinton 	"",		0,	0,	/* to stop the search */
8699813Slinton 	};
8709813Slinton 
8719813Slinton lxres() {
8729813Slinton 	/* check to see of yytext is reserved; if so,
8739813Slinton 	/* do the appropriate action and return */
8749813Slinton 	/* otherwise, return -1 */
8759813Slinton 
8769813Slinton 	register c, ch;
8779813Slinton 	register struct lxrdope *p;
8789813Slinton 
8799813Slinton 	ch = yytext[0];
8809813Slinton 
8819813Slinton 	if( !islower(ch) ) return( -1 );
8829813Slinton 
8839813Slinton 	switch( ch ){
8849813Slinton 
8859813Slinton 	case 'a':
8869813Slinton 		c=0; break;
8879813Slinton 	case 'b':
8889813Slinton 		c=2; break;
8899813Slinton 	case 'c':
8909813Slinton 		c=3; break;
8919813Slinton 	case 'd':
8929813Slinton 		c=6; break;
8939813Slinton 	case 'e':
8949813Slinton 		c=9; break;
8959813Slinton 	case 'f':
8969813Slinton 		c=12; break;
8979813Slinton 	case 'g':
8989813Slinton 		c=15; break;
8999813Slinton 	case 'i':
9009813Slinton 		c=16; break;
9019813Slinton 	case 'l':
9029813Slinton 		c=18; break;
9039813Slinton 	case 'r':
9049813Slinton 		c=19; break;
9059813Slinton 	case 's':
9069813Slinton 		c=21; break;
9079813Slinton 	case 't':
9089813Slinton 		c=26; break;
9099813Slinton 	case 'u':
9109813Slinton 		c=27; break;
9119813Slinton 	case 'v':
9129813Slinton 		c=29; break;
9139813Slinton 	case 'w':
9149813Slinton 		c=30; break;
9159813Slinton 
9169813Slinton 	default:
9179813Slinton 		return( -1 );
9189813Slinton 		}
9199813Slinton 
9209813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9219813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
9229813Slinton 			switch( p->lxract ){
9239813Slinton 
9249813Slinton 			case AR_TY:
9259813Slinton 				/* type word */
9269813Slinton 				stwart = instruct;
9279813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9289813Slinton 				return( TYPE );
9299813Slinton 
9309813Slinton 			case AR_RW:
9319813Slinton 				/* ordinary reserved word */
9329813Slinton 				return( yylval.intval = p->lxrval );
9339813Slinton 
9349813Slinton 			case AR_CL:
9359813Slinton 				/* class word */
9369813Slinton 				yylval.intval = p->lxrval;
9379813Slinton 				return( CLASS );
9389813Slinton 
9399813Slinton 			case AR_S:
9409813Slinton 				/* struct */
9419813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
9429813Slinton 				yylval.intval = INSTRUCT;
9439813Slinton 				return( STRUCT );
9449813Slinton 
9459813Slinton 			case AR_U:
9469813Slinton 				/* union */
9479813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
9489813Slinton 				yylval.intval = INUNION;
9499813Slinton 				return( STRUCT );
9509813Slinton 
9519813Slinton 			case AR_E:
9529813Slinton 				/* enums */
9539813Slinton 				stwart = SEENAME|TAGNAME;
9549813Slinton 				return( yylval.intval = ENUM );
9559813Slinton 
9569813Slinton 			case AR_A:
9579813Slinton 				/* asm */
9589813Slinton 				asm_esc = 1; /* warn the world! */
9599813Slinton 				lxget( ' ', LEXWS );
9609813Slinton 				if( getchar() != '(' ) goto badasm;
9619813Slinton 				lxget( ' ', LEXWS );
9629813Slinton 				if( getchar() != '"' ) goto badasm;
9639813Slinton # ifndef ONEPASS
9649813Slinton # ifndef LINT
9659813Slinton 				putchar(')');
9669813Slinton # endif
9679813Slinton # endif
9689813Slinton 				while( (c=getchar()) != '"' ){
9699813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
9709813Slinton # ifndef LINT
9719813Slinton 					putchar(c);
9729813Slinton # endif
9739813Slinton 					}
9749813Slinton 				lxget( ' ', LEXWS );
9759813Slinton 				if( getchar() != ')' ) goto badasm;
9769813Slinton # ifndef LINT
9779813Slinton 				putchar('\n');
9789813Slinton # endif
9799813Slinton 				return( 0 );
9809813Slinton 
9819813Slinton 			badasm:
9829813Slinton 				uerror( "bad asm construction" );
9839813Slinton 				return( 0 );
9849813Slinton 
9859813Slinton 			default:
9869813Slinton 				cerror( "bad AR_?? action" );
9879813Slinton 				}
9889813Slinton 			}
9899813Slinton 		}
9909813Slinton 	return( -1 );
9919813Slinton 	}
9929813Slinton 
9939813Slinton extern int	labelno;
9949813Slinton 
9959813Slinton lxtitle(){
9969813Slinton 	/* called after a newline; set linenumber and file name */
9979813Slinton 
9989813Slinton 	register c, val;
9999813Slinton 	register char *cp, *cq;
10009813Slinton 
10019813Slinton 	for(;;){  /* might be several such lines in a row */
10029813Slinton 		if( (c=getchar()) != '#' ){
10039813Slinton 			if( c != EOF ) ungetc(c,stdin);
10049813Slinton #ifndef LINT
10059813Slinton 			if ( lastloc != PROG) return;
10069813Slinton 			cp = ftitle;
10079813Slinton 			cq = ititle;
10089813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
10099813Slinton 			if ( *cq ) return;
101032830Sdonn 			if( nerrors == 0 ) psline();
10119813Slinton #endif
10129813Slinton 			return;
10139813Slinton 			}
10149813Slinton 
10159813Slinton 		lxget( ' ', LEXWS );
101632832Sdonn 		c = getchar();
101732832Sdonn 		if( c == 'i' ){
101832832Sdonn 			/* #ident -- currently a no-op */
101932832Sdonn 			lxget( c, LEXLET );
102032832Sdonn 			if( strcmp( yytext, "ident" ) )
102132832Sdonn 				werror( "%s: undefined control", yytext );
102232832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
102332832Sdonn 				;
102432832Sdonn 			continue;
102532832Sdonn 			}
102632832Sdonn 		if( c == 'p' ){
102732832Sdonn 			/* #pragma -- special instructions */
102832832Sdonn 			lxget( c, LEXLET );
102932832Sdonn 			if( strcmp( yytext, "pragma" ) ) {
103032832Sdonn 				werror( "%s: undefined control", yytext );
103132832Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
103232832Sdonn 					;
103332832Sdonn 				continue;
103432832Sdonn 				}
103532832Sdonn 			lxget( ' ' , LEXWS );
103632832Sdonn 			switch( c = getchar() ){
103732832Sdonn # ifdef LINT
103832832Sdonn 			case 'V':
103932832Sdonn 				lxget( c, LEXLET|LEXDIG );
104032832Sdonn 				{
104132832Sdonn 					extern int vaflag;
104232832Sdonn 					int i;
104332832Sdonn 					i = yytext[7]?yytext[7]-'0':0;
104432832Sdonn 					yytext[7] = '\0';
104532832Sdonn 					if( strcmp( yytext, "VARARGS" ) ) break;
104632832Sdonn 					vaflag = i;
104732832Sdonn 					break;
104832832Sdonn 					}
104932832Sdonn 			case 'L':
105032832Sdonn 				lxget( c, LEXLET );
105132832Sdonn 				if( strcmp( yytext, "LINTLIBRARY" ) ) break;
105232832Sdonn 				{
105332832Sdonn 					extern int libflag;
105432832Sdonn 					libflag = 1;
105532832Sdonn 					}
105632832Sdonn 				break;
105732832Sdonn 
105832832Sdonn 			case 'A':
105932832Sdonn 				lxget( c, LEXLET );
106032832Sdonn 				if( strcmp( yytext, "ARGSUSED" ) ) break;
106132832Sdonn 				{
106232832Sdonn 					extern int argflag, vflag;
106332832Sdonn 					argflag = 1;
106432832Sdonn 					vflag = 0;
106532832Sdonn 					}
106632832Sdonn 				break;
106732832Sdonn 
106832832Sdonn 			case 'N':
106932832Sdonn 				lxget( c, LEXLET );
107032832Sdonn 				if( strcmp( yytext, "NOTREACHED" ) ) break;
107132832Sdonn 				reached = 0;
107232832Sdonn 				break;
107332832Sdonn #endif
107432832Sdonn 
107532832Sdonn 			case '\n':
107632832Sdonn 			case EOF:
107732832Sdonn 				continue;
107832832Sdonn 				}
107932832Sdonn 			while( (c = getchar()) != '\n' && c != EOF )
108032832Sdonn 				;
108132832Sdonn 			continue;
108232832Sdonn 			}
1083*32833Sdonn 		if( c == 'l' ){
1084*32833Sdonn 			/* #line -- just like # */
1085*32833Sdonn 			lxget( c, LEXLET );
1086*32833Sdonn 			if( strcmp( yytext, "line" ) ){
1087*32833Sdonn 				werror( "%s: undefined control", yytext );
1088*32833Sdonn 				while( (c = getchar()) != '\n' && c != EOF )
1089*32833Sdonn 					;
1090*32833Sdonn 				continue;
1091*32833Sdonn 				}
1092*32833Sdonn 			lxget( ' ', LEXWS );
1093*32833Sdonn 			c = getchar();
1094*32833Sdonn 			}
109532832Sdonn 		if( !isdigit(c) ){
109632832Sdonn 			if( isalpha(c) ){
109732832Sdonn 				lxget( c, LEXLET );
109832832Sdonn 				werror( "%s: undefined control", yytext );
109932832Sdonn 				}
1100*32833Sdonn 			while( c != '\n' && c != EOF )
1101*32833Sdonn 				c = getchar();
110232832Sdonn 			continue;
110332832Sdonn 			}
110432832Sdonn 
11059813Slinton 		val = 0;
110632832Sdonn 		do {
11079813Slinton 			val = val*10+ c - '0';
11089813Slinton 			}
110932832Sdonn 		while( isdigit( c = getchar() ) );
111032832Sdonn 
111117748Sralph 		if( c == EOF )
111217748Sralph 			continue;
11139813Slinton 		ungetc( c, stdin );
11149813Slinton 		lineno = val;
11159813Slinton 		lxget( ' ', LEXWS );
111617748Sralph 		if( (c=getchar()) != '\n' && c != EOF ){
111717748Sralph 			for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
11189813Slinton 				*cp = c;
11199813Slinton 				}
11209813Slinton 			*cp = '\0';
11219813Slinton #ifndef LINT
11229813Slinton 			if (ititle[0] == '\0') {
11239813Slinton 				cp = ftitle;
11249813Slinton 				cq = ititle;
11259813Slinton 				while ( *cp )
11269813Slinton 					*cq++ = *cp++;
11279813Slinton 				*cq = '\0';
11289813Slinton 				*--cq = '\0';
11299813Slinton #ifndef FLEXNAMES
11309813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
11319813Slinton 					pstab(cp, N_SO);
11329813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
11339813Slinton 					}
11349813Slinton #else
11359813Slinton 				pstab(ititle+1, N_SO);
11369813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
11379813Slinton #endif
11389813Slinton 
11399813Slinton 				*cq = '"';
11409813Slinton 				printf("LL%d:\n", labelno++);
11419813Slinton 				}
11429813Slinton #endif
11439813Slinton 			}
11449813Slinton 		}
11459813Slinton 	}
11469813Slinton 
11479813Slinton #ifdef FLEXNAMES
11489813Slinton #define	NSAVETAB	4096
11499813Slinton char	*savetab;
11509813Slinton int	saveleft;
11519813Slinton 
11529813Slinton char *
11539813Slinton savestr(cp)
11549813Slinton 	register char *cp;
11559813Slinton {
11569813Slinton 	register int len;
11579813Slinton 
11589813Slinton 	len = strlen(cp) + 1;
11599813Slinton 	if (len > saveleft) {
11609813Slinton 		saveleft = NSAVETAB;
11619813Slinton 		if (len > saveleft)
11629813Slinton 			saveleft = len;
11639813Slinton 		savetab = (char *)malloc(saveleft);
11649813Slinton 		if (savetab == 0)
11659813Slinton 			cerror("Ran out of memory (savestr)");
11669813Slinton 	}
11679813Slinton 	strncpy(savetab, cp, len);
11689813Slinton 	cp = savetab;
11699813Slinton 	savetab += len;
11709813Slinton 	saveleft -= len;
11719813Slinton 	return (cp);
11729813Slinton }
11739813Slinton 
11749813Slinton /*
11759813Slinton  * The definition for the segmented hash tables.
11769813Slinton  */
11779813Slinton #define	MAXHASH	20
11789813Slinton #define	HASHINC	1013
11799813Slinton struct ht {
11809813Slinton 	char	**ht_low;
11819813Slinton 	char	**ht_high;
11829813Slinton 	int	ht_used;
11839813Slinton } htab[MAXHASH];
11849813Slinton 
11859813Slinton char *
11869813Slinton hash(s)
11879813Slinton 	char *s;
11889813Slinton {
11899813Slinton 	register char **h;
11909813Slinton 	register i;
11919813Slinton 	register char *cp;
11929813Slinton 	struct ht *htp;
11939813Slinton 	int sh;
11949813Slinton 
11959813Slinton 	/*
11969813Slinton 	 * The hash function is a modular hash of
11979813Slinton 	 * the sum of the characters with the sum
11989813Slinton 	 * doubled before each successive character
11999813Slinton 	 * is added.
12009813Slinton 	 */
12019813Slinton 	cp = s;
12029813Slinton 	i = 0;
12039813Slinton 	while (*cp)
12049813Slinton 		i = i*2 + *cp++;
12059813Slinton 	sh = (i&077777) % HASHINC;
12069813Slinton 	cp = s;
12079813Slinton 	/*
12089813Slinton 	 * There are as many as MAXHASH active
12099813Slinton 	 * hash tables at any given point in time.
12109813Slinton 	 * The search starts with the first table
12119813Slinton 	 * and continues through the active tables
12129813Slinton 	 * as necessary.
12139813Slinton 	 */
12149813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
12159813Slinton 		if (htp->ht_low == 0) {
12169813Slinton 			register char **hp =
12179813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
12189813Slinton 			if (hp == 0)
12199813Slinton 				cerror("ran out of memory (hash)");
12209813Slinton 			htp->ht_low = hp;
12219813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
12229813Slinton 		}
12239813Slinton 		h = htp->ht_low + sh;
12249813Slinton 		/*
12259813Slinton 		 * quadratic rehash increment
12269813Slinton 		 * starts at 1 and incremented
12279813Slinton 		 * by two each rehash.
12289813Slinton 		 */
12299813Slinton 		i = 1;
12309813Slinton 		do {
12319813Slinton 			if (*h == 0) {
12329813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
12339813Slinton 					break;
12349813Slinton 				htp->ht_used++;
12359813Slinton 				*h = savestr(cp);
12369813Slinton 				return (*h);
12379813Slinton 			}
12389813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
12399813Slinton 				return (*h);
12409813Slinton 			h += i;
12419813Slinton 			i += 2;
12429813Slinton 			if (h >= htp->ht_high)
12439813Slinton 				h -= HASHINC;
12449813Slinton 		} while (i < HASHINC);
12459813Slinton 	}
12469813Slinton 	cerror("ran out of hash tables");
12479813Slinton }
12489813Slinton #endif
1249