xref: /csrg-svn/old/pcc/mip/scan.c (revision 9905)
1*9905Ssam static char *sccsid ="@(#)scan.c	1.3 (Berkeley) 12/24/82";
29813Slinton # include "mfile1"
39813Slinton # include <a.out.h>
49813Slinton # include <stab.h>
59813Slinton # include <ctype.h>
69813Slinton 	/* temporarily */
79813Slinton 
89813Slinton int asm_esc = 0; /* asm escaped used in file */
99813Slinton 	/* lexical actions */
109813Slinton 
119813Slinton # define A_ERR 0		/* illegal character */
129813Slinton # define A_LET 1		/* saw a letter */
139813Slinton # define A_DIG 2		/* saw a digit */
149813Slinton # define A_1C 3			/* return a single character */
159813Slinton # define A_STR 4		/* string */
169813Slinton # define A_CC 5			/* character constant */
179813Slinton # define A_BCD 6		/* GCOS BCD constant */
189813Slinton # define A_SL 7			/* saw a / */
199813Slinton # define A_DOT 8		/* saw a . */
209813Slinton # define A_PL 9		/* + */
219813Slinton # define A_MI 10		/* - */
229813Slinton # define A_EQ 11		/* = */
239813Slinton # define A_NOT 12		/* ! */
249813Slinton # define A_LT 13		/* < */
259813Slinton # define A_GT 14		/* > */
269813Slinton # define A_AND 16		/* & */
279813Slinton # define A_OR 17		/* | */
289813Slinton # define A_WS 18		/* whitespace (not \n) */
299813Slinton # define A_NL 19		/* \n */
309813Slinton 
319813Slinton 	/* character classes */
329813Slinton 
339813Slinton # define LEXLET 01
349813Slinton # define LEXDIG 02
359813Slinton # define LEXOCT 04
369813Slinton # define LEXHEX 010
379813Slinton # define LEXWS 020
389813Slinton # define LEXDOT 040
399813Slinton 
409813Slinton 	/* reserved word actions */
419813Slinton 
429813Slinton # define AR_TY 0		/* type word */
439813Slinton # define AR_RW 1		/* simple reserved word */
449813Slinton # define AR_CL 2		/* storage class word */
459813Slinton # define AR_S 3		/* struct */
469813Slinton # define AR_U 4		/* union */
479813Slinton # define AR_E 5		/* enum */
489813Slinton # define AR_A 6		/* asm */
499813Slinton 
509813Slinton 	/* text buffer */
519813Slinton #ifndef FLEXNAMES
529813Slinton # define LXTSZ 100
539813Slinton #else
549813Slinton #define	LXTSZ	BUFSIZ
559813Slinton #endif
569813Slinton char yytext[LXTSZ];
579813Slinton char * lxgcp;
589813Slinton 
599813Slinton extern int proflg;
609813Slinton extern int gdebug;
61*9905Ssam int oldway;		/* allocate storage so lint will compile as well */
629813Slinton #ifndef LINT
639813Slinton extern int lastloc;
649813Slinton #endif
659813Slinton 
669813Slinton unsigned caloff();
679813Slinton 	/* ARGSUSED */
689813Slinton mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
699813Slinton 
709813Slinton 	register i;
719813Slinton 	register char *cp;
729813Slinton 	extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, gdebug;
739813Slinton 	extern unsigned int offsz;
749813Slinton 	int fdef = 0;
759813Slinton 	char *release = "PCC/364r1 vax uts3.0";
769813Slinton 
779813Slinton 	offsz = caloff();
789813Slinton 	for( i=1; i<argc; ++i ){
799813Slinton 		if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
809813Slinton 			while( *++cp ){
819813Slinton 				switch( *cp ){
829813Slinton 
839813Slinton 				case 'r':
849813Slinton 					fprintf( stderr, "Release: %s\n",
859813Slinton 						release );
869813Slinton 					break;
879813Slinton 
889813Slinton 				case 'd':
899813Slinton 					++ddebug;
909813Slinton 					break;
919813Slinton 				case 'i':
929813Slinton 					++idebug;
939813Slinton 					break;
949813Slinton 				case 'b':
959813Slinton 					++bdebug;
969813Slinton 					break;
979813Slinton 				case 't':
989813Slinton 					++tdebug;
999813Slinton 					break;
1009813Slinton 				case 'e':
1019813Slinton 					++edebug;
1029813Slinton 					break;
1039813Slinton 				case 'x':
1049813Slinton 					++xdebug;
1059813Slinton 					break;
1069813Slinton 				case 'P':	/* profiling */
1079813Slinton 					++proflg;
1089813Slinton 					break;
1099813Slinton 				case 'g':
1109813Slinton 					++gdebug;
1119813Slinton 					break;
1129816Slinton 				case 'G':
1139816Slinton 					++gdebug;
1149816Slinton 					oldway = 1;
1159816Slinton 					break;
1169813Slinton 					}
1179813Slinton 				}
1189813Slinton 			}
1199813Slinton 			else {
1209813Slinton 			if( *(argv[i]) != '-' ) switch( fdef++ ) {
1219813Slinton 				case 0:
1229813Slinton 				case 1:
1239813Slinton 					if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
1249813Slinton 						fprintf(stderr, "ccom:can't open %s\n", argv[i]);
1259813Slinton 						exit(1);
1269813Slinton 					}
1279813Slinton 					break;
1289813Slinton 
1299813Slinton 				default:
1309813Slinton 					;
1319813Slinton 				}
1329813Slinton 			}
1339813Slinton 		}
1349813Slinton 
1359813Slinton # ifdef ONEPASS
1369813Slinton 	p2init( argc, argv );
1379813Slinton # endif
1389813Slinton 
1399813Slinton 	for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
1409813Slinton 
1419813Slinton 	lxinit();
1429813Slinton 	tinit();
1439813Slinton 	mkdope();
1449813Slinton 
1459813Slinton 	lineno = 1;
1469813Slinton 
1479813Slinton 	/* dimension table initialization */
1489813Slinton 
1499813Slinton 	dimtab[NULL] = 0;
1509813Slinton 	dimtab[CHAR] = SZCHAR;
1519813Slinton 	dimtab[INT] = SZINT;
1529813Slinton 	dimtab[FLOAT] = SZFLOAT;
1539813Slinton 	dimtab[DOUBLE] = SZDOUBLE;
1549813Slinton 	dimtab[LONG] = SZLONG;
1559813Slinton 	dimtab[SHORT] = SZSHORT;
1569813Slinton 	dimtab[UCHAR] = SZCHAR;
1579813Slinton 	dimtab[USHORT] = SZSHORT;
1589813Slinton 	dimtab[UNSIGNED] = SZINT;
1599813Slinton 	dimtab[ULONG] = SZLONG;
1609813Slinton 	/* starts past any of the above */
1619813Slinton 	curdim = 16;
1629813Slinton 	reached = 1;
1639813Slinton 
1649813Slinton 	yyparse();
1659813Slinton 	yyaccpt();
1669813Slinton 
1679813Slinton 	ejobcode( nerrors ? 1 : 0 );
1689813Slinton 	return(nerrors?1:0);
1699813Slinton 
1709813Slinton 	}
1719813Slinton 
1729813Slinton # ifdef ibm
1739813Slinton 
1749813Slinton # define CSMASK 0377
1759813Slinton # define CSSZ 256
1769813Slinton 
1779813Slinton # else
1789813Slinton 
1799813Slinton # define CSMASK 0177
1809813Slinton # define CSSZ 128
1819813Slinton 
1829813Slinton # endif
1839813Slinton 
1849813Slinton short lxmask[CSSZ+1];
1859813Slinton 
1869813Slinton lxenter( s, m ) register char *s; register short m; {
1879813Slinton 	/* enter a mask into lxmask */
1889813Slinton 	register c;
1899813Slinton 
1909813Slinton 	while( c= *s++ ) lxmask[c+1] |= m;
1919813Slinton 
1929813Slinton 	}
1939813Slinton 
1949813Slinton 
1959813Slinton # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
1969813Slinton 
1979813Slinton lxmore( c, m )  register c, m; {
1989813Slinton 	register char *cp;
1999813Slinton 
2009813Slinton 	*(cp = lxgcp) = c;
2019813Slinton 	while( c=getchar(), lxmask[c+1]&m ){
2029813Slinton 		if( cp < &yytext[LXTSZ-1] ){
2039813Slinton 			*++cp = c;
2049813Slinton 			}
2059813Slinton 		}
2069813Slinton 	ungetc(c,stdin);
2079813Slinton 	*(lxgcp = cp+1) = '\0';
2089813Slinton 	}
2099813Slinton 
2109813Slinton struct lxdope {
2119813Slinton 	short lxch;	/* the character */
2129813Slinton 	short lxact;	/* the action to be performed */
2139813Slinton 	short lxtok;	/* the token number to be returned */
2149813Slinton 	short lxval;	/* the value to be returned */
2159813Slinton 	} lxdope[] = {
2169813Slinton 
2179813Slinton 	'@',	A_ERR,	0,	0,	/* illegal characters go here... */
2189813Slinton 	'_',	A_LET,	0,	0,	/* letters point here */
2199813Slinton 	'0',	A_DIG,	0,	0,	/* digits point here */
2209813Slinton 	' ',	A_WS,	0,	0,	/* whitespace goes here */
2219813Slinton 	'\n',	A_NL,	0,	0,
2229813Slinton 	'"',	A_STR,	0,	0,	/* character string */
2239813Slinton 	'\'',	A_CC,	0,	0,	/* character constant */
2249813Slinton 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
2259813Slinton 	'(',	A_1C,	LP,	0,
2269813Slinton 	')',	A_1C,	RP,	0,
2279813Slinton 	'{',	A_1C,	LC,	0,
2289813Slinton 	'}',	A_1C,	RC,	0,
2299813Slinton 	'[',	A_1C,	LB,	0,
2309813Slinton 	']',	A_1C,	RB,	0,
2319813Slinton 	'*',	A_1C,	MUL,	MUL,
2329813Slinton 	'?',	A_1C,	QUEST,	0,
2339813Slinton 	':',	A_1C,	COLON,	0,
2349813Slinton 	'+',	A_PL,	PLUS,	PLUS,
2359813Slinton 	'-',	A_MI,	MINUS,	MINUS,
2369813Slinton 	'/',	A_SL,	DIVOP,	DIV,
2379813Slinton 	'%',	A_1C,	DIVOP,	MOD,
2389813Slinton 	'&',	A_AND,	AND,	AND,
2399813Slinton 	'|',	A_OR,	OR,	OR,
2409813Slinton 	'^',	A_1C,	ER,	ER,
2419813Slinton 	'!',	A_NOT,	UNOP,	NOT,
2429813Slinton 	'~',	A_1C,	UNOP,	COMPL,
2439813Slinton 	',',	A_1C,	CM,	CM,
2449813Slinton 	';',	A_1C,	SM,	0,
2459813Slinton 	'.',	A_DOT,	STROP,	DOT,
2469813Slinton 	'<',	A_LT,	RELOP,	LT,
2479813Slinton 	'>',	A_GT,	RELOP,	GT,
2489813Slinton 	'=',	A_EQ,	ASSIGN,	ASSIGN,
2499813Slinton 	-1,	A_1C,	0,	0,
2509813Slinton 	};
2519813Slinton 
2529813Slinton struct lxdope *lxcp[CSSZ+1];
2539813Slinton 
2549813Slinton lxinit(){
2559813Slinton 	register struct lxdope *p;
2569813Slinton 	register i;
2579813Slinton 	register char *cp;
2589813Slinton 	/* set up character classes */
2599813Slinton 
2609813Slinton 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
2619813Slinton 	lxenter( "0123456789", LEXDIG );
2629813Slinton 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
2639813Slinton 		/* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
2649813Slinton 	lxenter( " \t\r\b\f\013", LEXWS );
2659813Slinton 	lxenter( "01234567", LEXOCT );
2669813Slinton 	lxmask['.'+1] |= LEXDOT;
2679813Slinton 
2689813Slinton 	/* make lxcp point to appropriate lxdope entry for each character */
2699813Slinton 
2709813Slinton 	/* initialize error entries */
2719813Slinton 
2729813Slinton 	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
2739813Slinton 
2749813Slinton 	/* make unique entries */
2759813Slinton 
2769813Slinton 	for( p=lxdope; ; ++p ) {
2779813Slinton 		lxcp[p->lxch+1] = p;
2789813Slinton 		if( p->lxch < 0 ) break;
2799813Slinton 		}
2809813Slinton 
2819813Slinton 	/* handle letters, digits, and whitespace */
2829813Slinton 	/* by convention, first, second, and third places */
2839813Slinton 
2849813Slinton 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
2859813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
2869813Slinton 	cp = "123456789";
2879813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
2889813Slinton 	cp = "\t\b\r\f\013";
2899813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
2909813Slinton 
2919813Slinton 	/* first line might have title */
2929813Slinton 	lxtitle();
2939813Slinton 
2949813Slinton 	}
2959813Slinton 
2969813Slinton int lxmatch;  /* character to be matched in char or string constant */
2979813Slinton 
2989813Slinton lxstr(ct){
2999813Slinton 	/* match a string or character constant, up to lxmatch */
3009813Slinton 
3019813Slinton 	register c;
3029813Slinton 	register val;
3039813Slinton 	register i;
3049813Slinton 
3059813Slinton 	i=0;
3069813Slinton 	while( (c=getchar()) != lxmatch ){
3079813Slinton 		switch( c ) {
3089813Slinton 
3099813Slinton 		case EOF:
3109813Slinton 			uerror( "unexpected EOF" );
3119813Slinton 			break;
3129813Slinton 
3139813Slinton 		case '\n':
3149813Slinton 			uerror( "newline in string or char constant" );
3159813Slinton 			++lineno;
3169813Slinton 			break;
3179813Slinton 
3189813Slinton 		case '\\':
3199813Slinton 			switch( c = getchar() ){
3209813Slinton 
3219813Slinton 			case '\n':
3229813Slinton 				++lineno;
3239813Slinton 				continue;
3249813Slinton 
3259813Slinton 			default:
3269813Slinton 				val = c;
3279813Slinton 				goto mkcc;
3289813Slinton 
3299813Slinton 			case 'n':
3309813Slinton 				val = '\n';
3319813Slinton 				goto mkcc;
3329813Slinton 
3339813Slinton 			case 'r':
3349813Slinton 				val = '\r';
3359813Slinton 				goto mkcc;
3369813Slinton 
3379813Slinton 			case 'b':
3389813Slinton 				val = '\b';
3399813Slinton 				goto mkcc;
3409813Slinton 
3419813Slinton 			case 't':
3429813Slinton 				val = '\t';
3439813Slinton 				goto mkcc;
3449813Slinton 
3459813Slinton 			case 'f':
3469813Slinton 				val = '\f';
3479813Slinton 				goto mkcc;
3489813Slinton 
3499813Slinton 			case 'v':
3509813Slinton 				val = '\013';
3519813Slinton 				goto mkcc;
3529813Slinton 
3539813Slinton 			case '0':
3549813Slinton 			case '1':
3559813Slinton 			case '2':
3569813Slinton 			case '3':
3579813Slinton 			case '4':
3589813Slinton 			case '5':
3599813Slinton 			case '6':
3609813Slinton 			case '7':
3619813Slinton 				val = c-'0';
3629813Slinton 				c=getchar();  /* try for 2 */
3639813Slinton 				if( lxmask[c+1] & LEXOCT ){
3649813Slinton 					val = (val<<3) | (c-'0');
3659813Slinton 					c = getchar();  /* try for 3 */
3669813Slinton 					if( lxmask[c+1] & LEXOCT ){
3679813Slinton 						val = (val<<3) | (c-'0');
3689813Slinton 						}
3699813Slinton 					else ungetc( c ,stdin);
3709813Slinton 					}
3719813Slinton 				else ungetc( c ,stdin);
3729813Slinton 
3739813Slinton 				goto mkcc1;
3749813Slinton 
3759813Slinton 				}
3769813Slinton 		default:
3779813Slinton 			val =c;
3789813Slinton 		mkcc:
3799813Slinton 			val = CCTRANS(val);
3809813Slinton 		mkcc1:
3819813Slinton 			if( lxmatch == '\'' ){
3829813Slinton 				val = CHARCAST(val);  /* it is, after all, a "character" constant */
3839813Slinton 				makecc( val, i );
3849813Slinton 				}
3859813Slinton 			else { /* stash the byte into the string */
3869813Slinton 				if( strflg ) {
3879813Slinton 					if( ct==0 || i<ct ) putbyte( val );
3889813Slinton 					else if( i == ct ) werror( "non-null byte ignored in string initializer" );
3899813Slinton 					}
3909813Slinton 				else bycode( val, i );
3919813Slinton 				}
3929813Slinton 			++i;
3939813Slinton 			continue;
3949813Slinton 			}
3959813Slinton 		break;
3969813Slinton 		}
3979813Slinton 	/* end of string or  char constant */
3989813Slinton 
3999813Slinton 	if( lxmatch == '"' ){
4009813Slinton 		if( strflg ){ /* end the string */
4019813Slinton 			if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
4029813Slinton 			}
4039813Slinton 		else {  /* the initializer gets a null byte */
4049813Slinton 			bycode( 0, i++ );
4059813Slinton 			bycode( -1, i );
4069813Slinton 			dimtab[curdim] = i;  /* in case of later sizeof ... */
4079813Slinton 			}
4089813Slinton 		}
4099813Slinton 	else { /* end the character constant */
4109813Slinton 		if( i == 0 ) uerror( "empty character constant" );
4119813Slinton 		if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
4129813Slinton 			uerror( "too many characters in character constant" );
4139813Slinton 		}
4149813Slinton 	}
4159813Slinton 
4169813Slinton lxcom(){
4179813Slinton 	register c;
4189813Slinton 	/* saw a /*: process a comment */
4199813Slinton 
4209813Slinton 	for(;;){
4219813Slinton 
4229813Slinton 		switch( c = getchar() ){
4239813Slinton 
4249813Slinton 		case EOF:
4259813Slinton 			uerror( "unexpected EOF" );
4269813Slinton 			return;
4279813Slinton 
4289813Slinton 		case '\n':
4299813Slinton 			++lineno;
4309813Slinton 
4319813Slinton 		default:
4329813Slinton 			continue;
4339813Slinton 
4349813Slinton 		case '*':
4359813Slinton 			if( (c = getchar()) == '/' ) return;
4369813Slinton 			else ungetc( c ,stdin);
4379813Slinton 			continue;
4389813Slinton 
4399813Slinton # ifdef LINT
4409813Slinton 		case 'V':
4419813Slinton 			lxget( c, LEXLET|LEXDIG );
4429813Slinton 			{
4439813Slinton 				extern int vaflag;
4449813Slinton 				int i;
4459813Slinton 				i = yytext[7]?yytext[7]-'0':0;
4469813Slinton 				yytext[7] = '\0';
4479813Slinton 				if( strcmp( yytext, "VARARGS" ) ) continue;
4489813Slinton 				vaflag = i;
4499813Slinton 				continue;
4509813Slinton 				}
4519813Slinton 		case 'L':
4529813Slinton 			lxget( c, LEXLET );
4539813Slinton 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
4549813Slinton 			{
4559813Slinton 				extern int libflag;
4569813Slinton 				libflag = 1;
4579813Slinton 				}
4589813Slinton 			continue;
4599813Slinton 
4609813Slinton 		case 'A':
4619813Slinton 			lxget( c, LEXLET );
4629813Slinton 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
4639813Slinton 			{
4649813Slinton 				extern int argflag, vflag;
4659813Slinton 				argflag = 1;
4669813Slinton 				vflag = 0;
4679813Slinton 				}
4689813Slinton 			continue;
4699813Slinton 
4709813Slinton 		case 'N':
4719813Slinton 			lxget( c, LEXLET );
4729813Slinton 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
4739813Slinton 			reached = 0;
4749813Slinton 			continue;
4759813Slinton # endif
4769813Slinton 			}
4779813Slinton 		}
4789813Slinton 	}
4799813Slinton 
4809813Slinton yylex(){
4819813Slinton 	for(;;){
4829813Slinton 
4839813Slinton 		register lxchar;
4849813Slinton 		register struct lxdope *p;
4859813Slinton 		register struct symtab *sp;
4869813Slinton 		int id;
4879813Slinton 
4889813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
4899813Slinton 
4909813Slinton 		onechar:
4919813Slinton 			ungetc( lxchar ,stdin);
4929813Slinton 
4939813Slinton 		case A_1C:
4949813Slinton 			/* eat up a single character, and return an opcode */
4959813Slinton 
4969813Slinton 			yylval.intval = p->lxval;
4979813Slinton 			return( p->lxtok );
4989813Slinton 
4999813Slinton 		case A_ERR:
5009813Slinton 			uerror( "illegal character: %03o (octal)", lxchar );
5019813Slinton 			break;
5029813Slinton 
5039813Slinton 		case A_LET:
5049813Slinton 			/* collect an identifier, check for reserved word, and return */
5059813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
5069813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5079813Slinton 			if( lxchar== 0 ) continue;
5089813Slinton #ifdef FLEXNAMES
5099813Slinton 			id = lookup( hash(yytext),
5109813Slinton #else
5119813Slinton 			id = lookup( yytext,
5129813Slinton #endif
5139813Slinton 				/* tag name for struct/union/enum */
5149813Slinton 				(stwart&TAGNAME)? STAG:
5159813Slinton 				/* member name for struct/union */
5169813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5179813Slinton 			sp = &stab[id];
5189813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
5199813Slinton 				stwart = instruct;
5209813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5219813Slinton 				return( TYPE );
5229813Slinton 				}
5239813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
5249813Slinton 			yylval.intval = id;
5259813Slinton 			return( NAME );
5269813Slinton 
5279813Slinton 		case A_DIG:
5289813Slinton 			/* collect a digit string, then look at last one... */
5299813Slinton 			lastcon = 0;
5309813Slinton 			lxget( lxchar, LEXDIG );
5319813Slinton 			switch( lxchar=getchar() ){
5329813Slinton 
5339813Slinton 			case 'x':
5349813Slinton 			case 'X':
5359813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5369813Slinton 				lxmore( lxchar, LEXHEX );
5379813Slinton 				/* convert the value */
5389813Slinton 				{
5399813Slinton 					register char *cp;
5409813Slinton 					for( cp = yytext+2; *cp; ++cp ){
5419813Slinton 						/* this code won't work for all wild character sets,
5429813Slinton 						   but seems ok for ascii and ebcdic */
5439813Slinton 						lastcon <<= 4;
5449813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
5459813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5469813Slinton 						else lastcon += *cp - 'a'+ 10;
5479813Slinton 						}
5489813Slinton 					}
5499813Slinton 
5509813Slinton 			hexlong:
5519813Slinton 				/* criterion for longness for hex and octal constants is that it
5529813Slinton 				   fit within 0177777 */
5539813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
5549813Slinton 				else yylval.intval = 0;
5559813Slinton 
5569813Slinton 				goto islong;
5579813Slinton 
5589813Slinton 			case '.':
5599813Slinton 				lxmore( lxchar, LEXDIG );
5609813Slinton 
5619813Slinton 			getfp:
5629813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
5639813Slinton 
5649813Slinton 			case 'e':
5659813Slinton 			case 'E':
5669813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
5679813Slinton 						*lxgcp++ = 'e';
5689813Slinton 						}
5699813Slinton 					else {
5709813Slinton 						ungetc(lxchar,stdin);
5719813Slinton 						lxchar = 'e';
5729813Slinton 						}
5739813Slinton 					lxmore( lxchar, LEXDIG );
5749813Slinton 					/* now have the whole thing... */
5759813Slinton 					}
5769813Slinton 				else {  /* no exponent */
5779813Slinton 					ungetc( lxchar ,stdin);
5789813Slinton 					}
5799813Slinton 				return( isitfloat( yytext ) );
5809813Slinton 
5819813Slinton 			default:
5829813Slinton 				ungetc( lxchar ,stdin);
5839813Slinton 				if( yytext[0] == '0' ){
5849813Slinton 					/* convert in octal */
5859813Slinton 					register char *cp;
5869813Slinton 					for( cp = yytext+1; *cp; ++cp ){
5879813Slinton 						lastcon <<= 3;
5889813Slinton 						lastcon += *cp - '0';
5899813Slinton 						}
5909813Slinton 					goto hexlong;
5919813Slinton 					}
5929813Slinton 				else {
5939813Slinton 					/* convert in decimal */
5949813Slinton 					register char *cp;
5959813Slinton 					for( cp = yytext; *cp; ++cp ){
5969813Slinton 						lastcon = lastcon * 10 + *cp - '0';
5979813Slinton 						}
5989813Slinton 					}
5999813Slinton 
6009813Slinton 				/* decide if it is long or not (decimal case) */
6019813Slinton 
6029813Slinton 				/* if it is positive and fits in 15 bits, or negative and
6039813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
6049813Slinton 				/* if there is an l or L following, all bets are off... */
6059813Slinton 
6069813Slinton 				{	CONSZ v;
6079813Slinton 					v = lastcon & ~077777L;
6089813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
6099813Slinton 					else yylval.intval = 1;
6109813Slinton 					}
6119813Slinton 
6129813Slinton 			islong:
6139813Slinton 				/* finally, look for trailing L or l */
6149813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6159813Slinton 				else ungetc( lxchar ,stdin);
6169813Slinton 				return( ICON );
6179813Slinton 				}
6189813Slinton 
6199813Slinton 		case A_DOT:
6209813Slinton 			/* look for a dot: if followed by a digit, floating point */
6219813Slinton 			lxchar = getchar();
6229813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
6239813Slinton 				ungetc(lxchar,stdin);
6249813Slinton 				lxget( '.', LEXDIG );
6259813Slinton 				goto getfp;
6269813Slinton 				}
6279813Slinton 			stwart = FUNNYNAME;
6289813Slinton 			goto onechar;
6299813Slinton 
6309813Slinton 		case A_STR:
6319813Slinton 			/* string constant */
6329813Slinton 			lxmatch = '"';
6339813Slinton 			return( STRING );
6349813Slinton 
6359813Slinton 		case A_CC:
6369813Slinton 			/* character constant */
6379813Slinton 			lxmatch = '\'';
6389813Slinton 			lastcon = 0;
6399813Slinton 			lxstr(0);
6409813Slinton 			yylval.intval = 0;
6419813Slinton 			return( ICON );
6429813Slinton 
6439813Slinton 		case A_BCD:
6449813Slinton 			{
6459813Slinton 				register i;
6469813Slinton 				int j;
6479813Slinton 				for( i=0; i<LXTSZ; ++i ){
6489813Slinton 					if( ( j = getchar() ) == '`' ) break;
6499813Slinton 					if( j == '\n' ){
6509813Slinton 						uerror( "newline in BCD constant" );
6519813Slinton 						break;
6529813Slinton 						}
6539813Slinton 					yytext[i] = j;
6549813Slinton 					}
6559813Slinton 				yytext[i] = '\0';
6569813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
6579813Slinton # ifdef gcos
6589813Slinton 				else strtob( yytext, &lastcon, i );
6599813Slinton 				lastcon >>= 6*(6-i);
6609813Slinton # else
6619813Slinton 				uerror( "gcos BCD constant illegal" );
6629813Slinton # endif
6639813Slinton 				yylval.intval = 0;  /* not long */
6649813Slinton 				return( ICON );
6659813Slinton 				}
6669813Slinton 
6679813Slinton 		case A_SL:
6689813Slinton 			/* / */
6699813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
6709813Slinton 			lxcom();
6719813Slinton 		case A_WS:
6729813Slinton 			continue;
6739813Slinton 
6749813Slinton 		case A_NL:
6759813Slinton 			++lineno;
6769813Slinton 			lxtitle();
6779813Slinton 			continue;
6789813Slinton 
6799813Slinton 		case A_NOT:
6809813Slinton 			/* ! */
6819813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
6829813Slinton 			yylval.intval = NE;
6839813Slinton 			return( EQUOP );
6849813Slinton 
6859813Slinton 		case A_MI:
6869813Slinton 			/* - */
6879813Slinton 			if( (lxchar=getchar()) == '-' ){
6889813Slinton 				yylval.intval = DECR;
6899813Slinton 				return( INCOP );
6909813Slinton 				}
6919813Slinton 			if( lxchar != '>' ) goto onechar;
6929813Slinton 			stwart = FUNNYNAME;
6939813Slinton 			yylval.intval=STREF;
6949813Slinton 			return( STROP );
6959813Slinton 
6969813Slinton 		case A_PL:
6979813Slinton 			/* + */
6989813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
6999813Slinton 			yylval.intval = INCR;
7009813Slinton 			return( INCOP );
7019813Slinton 
7029813Slinton 		case A_AND:
7039813Slinton 			/* & */
7049813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
7059813Slinton 			return( yylval.intval = ANDAND );
7069813Slinton 
7079813Slinton 		case A_OR:
7089813Slinton 			/* | */
7099813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
7109813Slinton 			return( yylval.intval = OROR );
7119813Slinton 
7129813Slinton 		case A_LT:
7139813Slinton 			/* < */
7149813Slinton 			if( (lxchar=getchar()) == '<' ){
7159813Slinton 				yylval.intval = LS;
7169813Slinton 				return( SHIFTOP );
7179813Slinton 				}
7189813Slinton 			if( lxchar != '=' ) goto onechar;
7199813Slinton 			yylval.intval = LE;
7209813Slinton 			return( RELOP );
7219813Slinton 
7229813Slinton 		case A_GT:
7239813Slinton 			/* > */
7249813Slinton 			if( (lxchar=getchar()) == '>' ){
7259813Slinton 				yylval.intval = RS;
7269813Slinton 				return(SHIFTOP );
7279813Slinton 				}
7289813Slinton 			if( lxchar != '=' ) goto onechar;
7299813Slinton 			yylval.intval = GE;
7309813Slinton 			return( RELOP );
7319813Slinton 
7329813Slinton 		case A_EQ:
7339813Slinton 			/* = */
7349813Slinton 			switch( lxchar = getchar() ){
7359813Slinton 
7369813Slinton 			case '=':
7379813Slinton 				yylval.intval = EQ;
7389813Slinton 				return( EQUOP );
7399813Slinton 
7409813Slinton 			case '+':
7419813Slinton 				yylval.intval = ASG PLUS;
7429813Slinton 				break;
7439813Slinton 
7449813Slinton 			case '-':
7459813Slinton 				yylval.intval = ASG MINUS;
7469813Slinton 
7479813Slinton 			warn:
7489813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
7499813Slinton 					werror( "ambiguous assignment: assignment op taken" );
7509813Slinton 					}
7519813Slinton 				ungetc( lxchar ,stdin);
7529813Slinton 				break;
7539813Slinton 
7549813Slinton 			case '*':
7559813Slinton 				yylval.intval = ASG MUL;
7569813Slinton 				goto warn;
7579813Slinton 
7589813Slinton 			case '/':
7599813Slinton 				yylval.intval = ASG DIV;
7609813Slinton 				break;
7619813Slinton 
7629813Slinton 			case '%':
7639813Slinton 				yylval.intval = ASG MOD;
7649813Slinton 				break;
7659813Slinton 
7669813Slinton 			case '&':
7679813Slinton 				yylval.intval = ASG AND;
7689813Slinton 				break;
7699813Slinton 
7709813Slinton 			case '|':
7719813Slinton 				yylval.intval = ASG OR;
7729813Slinton 				break;
7739813Slinton 
7749813Slinton 			case '^':
7759813Slinton 				yylval.intval = ASG ER;
7769813Slinton 				break;
7779813Slinton 
7789813Slinton 			case '<':
7799813Slinton 				if( (lxchar=getchar()) != '<' ){
7809813Slinton 					uerror( "=<%c illegal", lxchar );
7819813Slinton 					}
7829813Slinton 				yylval.intval = ASG LS;
7839813Slinton 				break;
7849813Slinton 
7859813Slinton 			case '>':
7869813Slinton 				if( (lxchar=getchar()) != '>' ){
7879813Slinton 					uerror( "=>%c illegal", lxchar );
7889813Slinton 					}
7899813Slinton 				yylval.intval = ASG RS;
7909813Slinton 				break;
7919813Slinton 
7929813Slinton 			default:
7939813Slinton 				goto onechar;
7949813Slinton 
7959813Slinton 				}
7969813Slinton 
7979813Slinton 			return( ASOP );
7989813Slinton 
7999813Slinton 		default:
8009813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
8019813Slinton 
8029813Slinton 			}
8039813Slinton 
8049813Slinton 		/* ordinarily, repeat here... */
8059813Slinton 		cerror( "out of switch in yylex" );
8069813Slinton 
8079813Slinton 		}
8089813Slinton 
8099813Slinton 	}
8109813Slinton 
8119813Slinton struct lxrdope {
8129813Slinton 	/* dope for reserved, in alphabetical order */
8139813Slinton 
8149813Slinton 	char *lxrch;	/* name of reserved word */
8159813Slinton 	short lxract;	/* reserved word action */
8169813Slinton 	short lxrval;	/* value to be returned */
8179813Slinton 	} lxrdope[] = {
8189813Slinton 
8199813Slinton 	"asm",		AR_A,	0,
8209813Slinton 	"auto",		AR_CL,	AUTO,
8219813Slinton 	"break",	AR_RW,	BREAK,
8229813Slinton 	"char",		AR_TY,	CHAR,
8239813Slinton 	"case",		AR_RW,	CASE,
8249813Slinton 	"continue",	AR_RW,	CONTINUE,
8259813Slinton 	"double",	AR_TY,	DOUBLE,
8269813Slinton 	"default",	AR_RW,	DEFAULT,
8279813Slinton 	"do",		AR_RW,	DO,
8289813Slinton 	"extern",	AR_CL,	EXTERN,
8299813Slinton 	"else",		AR_RW,	ELSE,
8309813Slinton 	"enum",		AR_E,	ENUM,
8319813Slinton 	"for",		AR_RW,	FOR,
8329813Slinton 	"float",	AR_TY,	FLOAT,
8339813Slinton 	"fortran",	AR_CL,	FORTRAN,
8349813Slinton 	"goto",		AR_RW,	GOTO,
8359813Slinton 	"if",		AR_RW,	IF,
8369813Slinton 	"int",		AR_TY,	INT,
8379813Slinton 	"long",		AR_TY,	LONG,
8389813Slinton 	"return",	AR_RW,	RETURN,
8399813Slinton 	"register",	AR_CL,	REGISTER,
8409813Slinton 	"switch",	AR_RW,	SWITCH,
8419813Slinton 	"struct",	AR_S,	0,
8429813Slinton 	"sizeof",	AR_RW,	SIZEOF,
8439813Slinton 	"short",	AR_TY,	SHORT,
8449813Slinton 	"static",	AR_CL,	STATIC,
8459813Slinton 	"typedef",	AR_CL,	TYPEDEF,
8469813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
8479813Slinton 	"union",	AR_U,	0,
8489813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
8499813Slinton 	"while",	AR_RW,	WHILE,
8509813Slinton 	"",		0,	0,	/* to stop the search */
8519813Slinton 	};
8529813Slinton 
8539813Slinton lxres() {
8549813Slinton 	/* check to see of yytext is reserved; if so,
8559813Slinton 	/* do the appropriate action and return */
8569813Slinton 	/* otherwise, return -1 */
8579813Slinton 
8589813Slinton 	register c, ch;
8599813Slinton 	register struct lxrdope *p;
8609813Slinton 
8619813Slinton 	ch = yytext[0];
8629813Slinton 
8639813Slinton 	if( !islower(ch) ) return( -1 );
8649813Slinton 
8659813Slinton 	switch( ch ){
8669813Slinton 
8679813Slinton 	case 'a':
8689813Slinton 		c=0; break;
8699813Slinton 	case 'b':
8709813Slinton 		c=2; break;
8719813Slinton 	case 'c':
8729813Slinton 		c=3; break;
8739813Slinton 	case 'd':
8749813Slinton 		c=6; break;
8759813Slinton 	case 'e':
8769813Slinton 		c=9; break;
8779813Slinton 	case 'f':
8789813Slinton 		c=12; break;
8799813Slinton 	case 'g':
8809813Slinton 		c=15; break;
8819813Slinton 	case 'i':
8829813Slinton 		c=16; break;
8839813Slinton 	case 'l':
8849813Slinton 		c=18; break;
8859813Slinton 	case 'r':
8869813Slinton 		c=19; break;
8879813Slinton 	case 's':
8889813Slinton 		c=21; break;
8899813Slinton 	case 't':
8909813Slinton 		c=26; break;
8919813Slinton 	case 'u':
8929813Slinton 		c=27; break;
8939813Slinton 	case 'v':
8949813Slinton 		c=29; break;
8959813Slinton 	case 'w':
8969813Slinton 		c=30; break;
8979813Slinton 
8989813Slinton 	default:
8999813Slinton 		return( -1 );
9009813Slinton 		}
9019813Slinton 
9029813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9039813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
9049813Slinton 			switch( p->lxract ){
9059813Slinton 
9069813Slinton 			case AR_TY:
9079813Slinton 				/* type word */
9089813Slinton 				stwart = instruct;
9099813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9109813Slinton 				return( TYPE );
9119813Slinton 
9129813Slinton 			case AR_RW:
9139813Slinton 				/* ordinary reserved word */
9149813Slinton 				return( yylval.intval = p->lxrval );
9159813Slinton 
9169813Slinton 			case AR_CL:
9179813Slinton 				/* class word */
9189813Slinton 				yylval.intval = p->lxrval;
9199813Slinton 				return( CLASS );
9209813Slinton 
9219813Slinton 			case AR_S:
9229813Slinton 				/* struct */
9239813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
9249813Slinton 				yylval.intval = INSTRUCT;
9259813Slinton 				return( STRUCT );
9269813Slinton 
9279813Slinton 			case AR_U:
9289813Slinton 				/* union */
9299813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
9309813Slinton 				yylval.intval = INUNION;
9319813Slinton 				return( STRUCT );
9329813Slinton 
9339813Slinton 			case AR_E:
9349813Slinton 				/* enums */
9359813Slinton 				stwart = SEENAME|TAGNAME;
9369813Slinton 				return( yylval.intval = ENUM );
9379813Slinton 
9389813Slinton 			case AR_A:
9399813Slinton 				/* asm */
9409813Slinton 				asm_esc = 1; /* warn the world! */
9419813Slinton 				lxget( ' ', LEXWS );
9429813Slinton 				if( getchar() != '(' ) goto badasm;
9439813Slinton 				lxget( ' ', LEXWS );
9449813Slinton 				if( getchar() != '"' ) goto badasm;
9459813Slinton # ifndef ONEPASS
9469813Slinton # ifndef LINT
9479813Slinton 				putchar(')');
9489813Slinton # endif
9499813Slinton # endif
9509813Slinton 				while( (c=getchar()) != '"' ){
9519813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
9529813Slinton # ifndef LINT
9539813Slinton 					putchar(c);
9549813Slinton # endif
9559813Slinton 					}
9569813Slinton 				lxget( ' ', LEXWS );
9579813Slinton 				if( getchar() != ')' ) goto badasm;
9589813Slinton # ifndef LINT
9599813Slinton 				putchar('\n');
9609813Slinton # endif
9619813Slinton 				return( 0 );
9629813Slinton 
9639813Slinton 			badasm:
9649813Slinton 				uerror( "bad asm construction" );
9659813Slinton 				return( 0 );
9669813Slinton 
9679813Slinton 			default:
9689813Slinton 				cerror( "bad AR_?? action" );
9699813Slinton 				}
9709813Slinton 			}
9719813Slinton 		}
9729813Slinton 	return( -1 );
9739813Slinton 	}
9749813Slinton 
9759813Slinton extern int	labelno;
9769813Slinton 
9779813Slinton lxtitle(){
9789813Slinton 	/* called after a newline; set linenumber and file name */
9799813Slinton 
9809813Slinton 	register c, val;
9819813Slinton 	register char *cp, *cq;
9829813Slinton 
9839813Slinton 	for(;;){  /* might be several such lines in a row */
9849813Slinton 		if( (c=getchar()) != '#' ){
9859813Slinton 			if( c != EOF ) ungetc(c,stdin);
9869813Slinton #ifndef LINT
9879813Slinton 			if ( lastloc != PROG) return;
9889813Slinton 			cp = ftitle;
9899813Slinton 			cq = ititle;
9909813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
9919813Slinton 			if ( *cq ) return;
9929813Slinton 			psline();
9939813Slinton #endif
9949813Slinton 			return;
9959813Slinton 			}
9969813Slinton 
9979813Slinton 		lxget( ' ', LEXWS );
9989813Slinton 		val = 0;
9999813Slinton 		for( c=getchar(); isdigit(c); c=getchar() ){
10009813Slinton 			val = val*10+ c - '0';
10019813Slinton 			}
10029813Slinton 		ungetc( c, stdin );
10039813Slinton 		lineno = val;
10049813Slinton 		lxget( ' ', LEXWS );
10059813Slinton 		if( (c=getchar()) != '\n' ){
10069813Slinton 			for( cp=ftitle; c!='\n'; c=getchar(),++cp ){
10079813Slinton 				*cp = c;
10089813Slinton 				}
10099813Slinton 			*cp = '\0';
10109813Slinton #ifndef LINT
10119813Slinton 			if (ititle[0] == '\0') {
10129813Slinton 				cp = ftitle;
10139813Slinton 				cq = ititle;
10149813Slinton 				while ( *cp )
10159813Slinton 					*cq++ = *cp++;
10169813Slinton 				*cq = '\0';
10179813Slinton 				*--cq = '\0';
10189813Slinton #ifndef FLEXNAMES
10199813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
10209813Slinton 					pstab(cp, N_SO);
10219813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
10229813Slinton 					}
10239813Slinton #else
10249813Slinton 				pstab(ititle+1, N_SO);
10259813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
10269813Slinton #endif
10279813Slinton 
10289813Slinton 				*cq = '"';
10299813Slinton 				printf("LL%d:\n", labelno++);
10309813Slinton 				}
10319813Slinton #endif
10329813Slinton 			}
10339813Slinton 		}
10349813Slinton 	}
10359813Slinton 
10369813Slinton #ifdef FLEXNAMES
10379813Slinton #define	NSAVETAB	4096
10389813Slinton char	*savetab;
10399813Slinton int	saveleft;
10409813Slinton 
10419813Slinton char *
10429813Slinton savestr(cp)
10439813Slinton 	register char *cp;
10449813Slinton {
10459813Slinton 	register int len;
10469813Slinton 
10479813Slinton 	len = strlen(cp) + 1;
10489813Slinton 	if (len > saveleft) {
10499813Slinton 		saveleft = NSAVETAB;
10509813Slinton 		if (len > saveleft)
10519813Slinton 			saveleft = len;
10529813Slinton 		savetab = (char *)malloc(saveleft);
10539813Slinton 		if (savetab == 0)
10549813Slinton 			cerror("Ran out of memory (savestr)");
10559813Slinton 	}
10569813Slinton 	strncpy(savetab, cp, len);
10579813Slinton 	cp = savetab;
10589813Slinton 	savetab += len;
10599813Slinton 	saveleft -= len;
10609813Slinton 	return (cp);
10619813Slinton }
10629813Slinton 
10639813Slinton /*
10649813Slinton  * The definition for the segmented hash tables.
10659813Slinton  */
10669813Slinton #define	MAXHASH	20
10679813Slinton #define	HASHINC	1013
10689813Slinton struct ht {
10699813Slinton 	char	**ht_low;
10709813Slinton 	char	**ht_high;
10719813Slinton 	int	ht_used;
10729813Slinton } htab[MAXHASH];
10739813Slinton 
10749813Slinton char *
10759813Slinton hash(s)
10769813Slinton 	char *s;
10779813Slinton {
10789813Slinton 	register char **h;
10799813Slinton 	register i;
10809813Slinton 	register char *cp;
10819813Slinton 	struct ht *htp;
10829813Slinton 	int sh;
10839813Slinton 
10849813Slinton 	/*
10859813Slinton 	 * The hash function is a modular hash of
10869813Slinton 	 * the sum of the characters with the sum
10879813Slinton 	 * doubled before each successive character
10889813Slinton 	 * is added.
10899813Slinton 	 */
10909813Slinton 	cp = s;
10919813Slinton 	i = 0;
10929813Slinton 	while (*cp)
10939813Slinton 		i = i*2 + *cp++;
10949813Slinton 	sh = (i&077777) % HASHINC;
10959813Slinton 	cp = s;
10969813Slinton 	/*
10979813Slinton 	 * There are as many as MAXHASH active
10989813Slinton 	 * hash tables at any given point in time.
10999813Slinton 	 * The search starts with the first table
11009813Slinton 	 * and continues through the active tables
11019813Slinton 	 * as necessary.
11029813Slinton 	 */
11039813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
11049813Slinton 		if (htp->ht_low == 0) {
11059813Slinton 			register char **hp =
11069813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
11079813Slinton 			if (hp == 0)
11089813Slinton 				cerror("ran out of memory (hash)");
11099813Slinton 			htp->ht_low = hp;
11109813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
11119813Slinton 		}
11129813Slinton 		h = htp->ht_low + sh;
11139813Slinton 		/*
11149813Slinton 		 * quadratic rehash increment
11159813Slinton 		 * starts at 1 and incremented
11169813Slinton 		 * by two each rehash.
11179813Slinton 		 */
11189813Slinton 		i = 1;
11199813Slinton 		do {
11209813Slinton 			if (*h == 0) {
11219813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
11229813Slinton 					break;
11239813Slinton 				htp->ht_used++;
11249813Slinton 				*h = savestr(cp);
11259813Slinton 				return (*h);
11269813Slinton 			}
11279813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
11289813Slinton 				return (*h);
11299813Slinton 			h += i;
11309813Slinton 			i += 2;
11319813Slinton 			if (h >= htp->ht_high)
11329813Slinton 				h -= HASHINC;
11339813Slinton 		} while (i < HASHINC);
11349813Slinton 	}
11359813Slinton 	cerror("ran out of hash tables");
11369813Slinton }
11379813Slinton #endif
1138