xref: /csrg-svn/old/pcc/mip/scan.c (revision 9813)
1*9813Slinton static char *sccsid ="@(#)scan.c	1.1 (Berkeley) 12/17/82";
2*9813Slinton # include "mfile1"
3*9813Slinton # include <a.out.h>
4*9813Slinton # include <stab.h>
5*9813Slinton # include <ctype.h>
6*9813Slinton 	/* temporarily */
7*9813Slinton 
8*9813Slinton int asm_esc = 0; /* asm escaped used in file */
9*9813Slinton 	/* lexical actions */
10*9813Slinton 
11*9813Slinton # define A_ERR 0		/* illegal character */
12*9813Slinton # define A_LET 1		/* saw a letter */
13*9813Slinton # define A_DIG 2		/* saw a digit */
14*9813Slinton # define A_1C 3			/* return a single character */
15*9813Slinton # define A_STR 4		/* string */
16*9813Slinton # define A_CC 5			/* character constant */
17*9813Slinton # define A_BCD 6		/* GCOS BCD constant */
18*9813Slinton # define A_SL 7			/* saw a / */
19*9813Slinton # define A_DOT 8		/* saw a . */
20*9813Slinton # define A_PL 9		/* + */
21*9813Slinton # define A_MI 10		/* - */
22*9813Slinton # define A_EQ 11		/* = */
23*9813Slinton # define A_NOT 12		/* ! */
24*9813Slinton # define A_LT 13		/* < */
25*9813Slinton # define A_GT 14		/* > */
26*9813Slinton # define A_AND 16		/* & */
27*9813Slinton # define A_OR 17		/* | */
28*9813Slinton # define A_WS 18		/* whitespace (not \n) */
29*9813Slinton # define A_NL 19		/* \n */
30*9813Slinton 
31*9813Slinton 	/* character classes */
32*9813Slinton 
33*9813Slinton # define LEXLET 01
34*9813Slinton # define LEXDIG 02
35*9813Slinton # define LEXOCT 04
36*9813Slinton # define LEXHEX 010
37*9813Slinton # define LEXWS 020
38*9813Slinton # define LEXDOT 040
39*9813Slinton 
40*9813Slinton 	/* reserved word actions */
41*9813Slinton 
42*9813Slinton # define AR_TY 0		/* type word */
43*9813Slinton # define AR_RW 1		/* simple reserved word */
44*9813Slinton # define AR_CL 2		/* storage class word */
45*9813Slinton # define AR_S 3		/* struct */
46*9813Slinton # define AR_U 4		/* union */
47*9813Slinton # define AR_E 5		/* enum */
48*9813Slinton # define AR_A 6		/* asm */
49*9813Slinton 
50*9813Slinton 	/* text buffer */
51*9813Slinton #ifndef FLEXNAMES
52*9813Slinton # define LXTSZ 100
53*9813Slinton #else
54*9813Slinton #define	LXTSZ	BUFSIZ
55*9813Slinton #endif
56*9813Slinton char yytext[LXTSZ];
57*9813Slinton char * lxgcp;
58*9813Slinton 
59*9813Slinton extern int proflg;
60*9813Slinton extern int gdebug;
61*9813Slinton #ifndef LINT
62*9813Slinton extern int lastloc;
63*9813Slinton #endif
64*9813Slinton 
65*9813Slinton unsigned caloff();
66*9813Slinton 	/* ARGSUSED */
67*9813Slinton mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
68*9813Slinton 
69*9813Slinton 	register i;
70*9813Slinton 	register char *cp;
71*9813Slinton 	extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, gdebug;
72*9813Slinton 	extern unsigned int offsz;
73*9813Slinton 	int fdef = 0;
74*9813Slinton 	char *release = "PCC/364r1 vax uts3.0";
75*9813Slinton 
76*9813Slinton 	offsz = caloff();
77*9813Slinton 	for( i=1; i<argc; ++i ){
78*9813Slinton 		if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
79*9813Slinton 			while( *++cp ){
80*9813Slinton 				switch( *cp ){
81*9813Slinton 
82*9813Slinton 				case 'r':
83*9813Slinton 					fprintf( stderr, "Release: %s\n",
84*9813Slinton 						release );
85*9813Slinton 					break;
86*9813Slinton 
87*9813Slinton 				case 'd':
88*9813Slinton 					++ddebug;
89*9813Slinton 					break;
90*9813Slinton 				case 'i':
91*9813Slinton 					++idebug;
92*9813Slinton 					break;
93*9813Slinton 				case 'b':
94*9813Slinton 					++bdebug;
95*9813Slinton 					break;
96*9813Slinton 				case 't':
97*9813Slinton 					++tdebug;
98*9813Slinton 					break;
99*9813Slinton 				case 'e':
100*9813Slinton 					++edebug;
101*9813Slinton 					break;
102*9813Slinton 				case 'x':
103*9813Slinton 					++xdebug;
104*9813Slinton 					break;
105*9813Slinton 				case 'P':	/* profiling */
106*9813Slinton 					++proflg;
107*9813Slinton 					break;
108*9813Slinton 				case 'g':
109*9813Slinton 					++gdebug;
110*9813Slinton 					break;
111*9813Slinton 					}
112*9813Slinton 				}
113*9813Slinton 			}
114*9813Slinton 			else {
115*9813Slinton 			if( *(argv[i]) != '-' ) switch( fdef++ ) {
116*9813Slinton 				case 0:
117*9813Slinton 				case 1:
118*9813Slinton 					if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
119*9813Slinton 						fprintf(stderr, "ccom:can't open %s\n", argv[i]);
120*9813Slinton 						exit(1);
121*9813Slinton 					}
122*9813Slinton 					break;
123*9813Slinton 
124*9813Slinton 				default:
125*9813Slinton 					;
126*9813Slinton 				}
127*9813Slinton 			}
128*9813Slinton 		}
129*9813Slinton 
130*9813Slinton # ifdef ONEPASS
131*9813Slinton 	p2init( argc, argv );
132*9813Slinton # endif
133*9813Slinton 
134*9813Slinton 	for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
135*9813Slinton 
136*9813Slinton 	lxinit();
137*9813Slinton 	tinit();
138*9813Slinton 	mkdope();
139*9813Slinton 
140*9813Slinton 	lineno = 1;
141*9813Slinton 
142*9813Slinton 	/* dimension table initialization */
143*9813Slinton 
144*9813Slinton 	dimtab[NULL] = 0;
145*9813Slinton 	dimtab[CHAR] = SZCHAR;
146*9813Slinton 	dimtab[INT] = SZINT;
147*9813Slinton 	dimtab[FLOAT] = SZFLOAT;
148*9813Slinton 	dimtab[DOUBLE] = SZDOUBLE;
149*9813Slinton 	dimtab[LONG] = SZLONG;
150*9813Slinton 	dimtab[SHORT] = SZSHORT;
151*9813Slinton 	dimtab[UCHAR] = SZCHAR;
152*9813Slinton 	dimtab[USHORT] = SZSHORT;
153*9813Slinton 	dimtab[UNSIGNED] = SZINT;
154*9813Slinton 	dimtab[ULONG] = SZLONG;
155*9813Slinton 	/* starts past any of the above */
156*9813Slinton 	curdim = 16;
157*9813Slinton 	reached = 1;
158*9813Slinton 
159*9813Slinton 	yyparse();
160*9813Slinton 	yyaccpt();
161*9813Slinton 
162*9813Slinton 	ejobcode( nerrors ? 1 : 0 );
163*9813Slinton 	return(nerrors?1:0);
164*9813Slinton 
165*9813Slinton 	}
166*9813Slinton 
167*9813Slinton # ifdef ibm
168*9813Slinton 
169*9813Slinton # define CSMASK 0377
170*9813Slinton # define CSSZ 256
171*9813Slinton 
172*9813Slinton # else
173*9813Slinton 
174*9813Slinton # define CSMASK 0177
175*9813Slinton # define CSSZ 128
176*9813Slinton 
177*9813Slinton # endif
178*9813Slinton 
179*9813Slinton short lxmask[CSSZ+1];
180*9813Slinton 
181*9813Slinton lxenter( s, m ) register char *s; register short m; {
182*9813Slinton 	/* enter a mask into lxmask */
183*9813Slinton 	register c;
184*9813Slinton 
185*9813Slinton 	while( c= *s++ ) lxmask[c+1] |= m;
186*9813Slinton 
187*9813Slinton 	}
188*9813Slinton 
189*9813Slinton 
190*9813Slinton # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
191*9813Slinton 
192*9813Slinton lxmore( c, m )  register c, m; {
193*9813Slinton 	register char *cp;
194*9813Slinton 
195*9813Slinton 	*(cp = lxgcp) = c;
196*9813Slinton 	while( c=getchar(), lxmask[c+1]&m ){
197*9813Slinton 		if( cp < &yytext[LXTSZ-1] ){
198*9813Slinton 			*++cp = c;
199*9813Slinton 			}
200*9813Slinton 		}
201*9813Slinton 	ungetc(c,stdin);
202*9813Slinton 	*(lxgcp = cp+1) = '\0';
203*9813Slinton 	}
204*9813Slinton 
205*9813Slinton struct lxdope {
206*9813Slinton 	short lxch;	/* the character */
207*9813Slinton 	short lxact;	/* the action to be performed */
208*9813Slinton 	short lxtok;	/* the token number to be returned */
209*9813Slinton 	short lxval;	/* the value to be returned */
210*9813Slinton 	} lxdope[] = {
211*9813Slinton 
212*9813Slinton 	'@',	A_ERR,	0,	0,	/* illegal characters go here... */
213*9813Slinton 	'_',	A_LET,	0,	0,	/* letters point here */
214*9813Slinton 	'0',	A_DIG,	0,	0,	/* digits point here */
215*9813Slinton 	' ',	A_WS,	0,	0,	/* whitespace goes here */
216*9813Slinton 	'\n',	A_NL,	0,	0,
217*9813Slinton 	'"',	A_STR,	0,	0,	/* character string */
218*9813Slinton 	'\'',	A_CC,	0,	0,	/* character constant */
219*9813Slinton 	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
220*9813Slinton 	'(',	A_1C,	LP,	0,
221*9813Slinton 	')',	A_1C,	RP,	0,
222*9813Slinton 	'{',	A_1C,	LC,	0,
223*9813Slinton 	'}',	A_1C,	RC,	0,
224*9813Slinton 	'[',	A_1C,	LB,	0,
225*9813Slinton 	']',	A_1C,	RB,	0,
226*9813Slinton 	'*',	A_1C,	MUL,	MUL,
227*9813Slinton 	'?',	A_1C,	QUEST,	0,
228*9813Slinton 	':',	A_1C,	COLON,	0,
229*9813Slinton 	'+',	A_PL,	PLUS,	PLUS,
230*9813Slinton 	'-',	A_MI,	MINUS,	MINUS,
231*9813Slinton 	'/',	A_SL,	DIVOP,	DIV,
232*9813Slinton 	'%',	A_1C,	DIVOP,	MOD,
233*9813Slinton 	'&',	A_AND,	AND,	AND,
234*9813Slinton 	'|',	A_OR,	OR,	OR,
235*9813Slinton 	'^',	A_1C,	ER,	ER,
236*9813Slinton 	'!',	A_NOT,	UNOP,	NOT,
237*9813Slinton 	'~',	A_1C,	UNOP,	COMPL,
238*9813Slinton 	',',	A_1C,	CM,	CM,
239*9813Slinton 	';',	A_1C,	SM,	0,
240*9813Slinton 	'.',	A_DOT,	STROP,	DOT,
241*9813Slinton 	'<',	A_LT,	RELOP,	LT,
242*9813Slinton 	'>',	A_GT,	RELOP,	GT,
243*9813Slinton 	'=',	A_EQ,	ASSIGN,	ASSIGN,
244*9813Slinton 	-1,	A_1C,	0,	0,
245*9813Slinton 	};
246*9813Slinton 
247*9813Slinton struct lxdope *lxcp[CSSZ+1];
248*9813Slinton 
249*9813Slinton lxinit(){
250*9813Slinton 	register struct lxdope *p;
251*9813Slinton 	register i;
252*9813Slinton 	register char *cp;
253*9813Slinton 	/* set up character classes */
254*9813Slinton 
255*9813Slinton 	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
256*9813Slinton 	lxenter( "0123456789", LEXDIG );
257*9813Slinton 	lxenter( "0123456789abcdefABCDEF", LEXHEX );
258*9813Slinton 		/* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
259*9813Slinton 	lxenter( " \t\r\b\f\013", LEXWS );
260*9813Slinton 	lxenter( "01234567", LEXOCT );
261*9813Slinton 	lxmask['.'+1] |= LEXDOT;
262*9813Slinton 
263*9813Slinton 	/* make lxcp point to appropriate lxdope entry for each character */
264*9813Slinton 
265*9813Slinton 	/* initialize error entries */
266*9813Slinton 
267*9813Slinton 	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
268*9813Slinton 
269*9813Slinton 	/* make unique entries */
270*9813Slinton 
271*9813Slinton 	for( p=lxdope; ; ++p ) {
272*9813Slinton 		lxcp[p->lxch+1] = p;
273*9813Slinton 		if( p->lxch < 0 ) break;
274*9813Slinton 		}
275*9813Slinton 
276*9813Slinton 	/* handle letters, digits, and whitespace */
277*9813Slinton 	/* by convention, first, second, and third places */
278*9813Slinton 
279*9813Slinton 	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
280*9813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
281*9813Slinton 	cp = "123456789";
282*9813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
283*9813Slinton 	cp = "\t\b\r\f\013";
284*9813Slinton 	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
285*9813Slinton 
286*9813Slinton 	/* first line might have title */
287*9813Slinton 	lxtitle();
288*9813Slinton 
289*9813Slinton 	}
290*9813Slinton 
291*9813Slinton int lxmatch;  /* character to be matched in char or string constant */
292*9813Slinton 
293*9813Slinton lxstr(ct){
294*9813Slinton 	/* match a string or character constant, up to lxmatch */
295*9813Slinton 
296*9813Slinton 	register c;
297*9813Slinton 	register val;
298*9813Slinton 	register i;
299*9813Slinton 
300*9813Slinton 	i=0;
301*9813Slinton 	while( (c=getchar()) != lxmatch ){
302*9813Slinton 		switch( c ) {
303*9813Slinton 
304*9813Slinton 		case EOF:
305*9813Slinton 			uerror( "unexpected EOF" );
306*9813Slinton 			break;
307*9813Slinton 
308*9813Slinton 		case '\n':
309*9813Slinton 			uerror( "newline in string or char constant" );
310*9813Slinton 			++lineno;
311*9813Slinton 			break;
312*9813Slinton 
313*9813Slinton 		case '\\':
314*9813Slinton 			switch( c = getchar() ){
315*9813Slinton 
316*9813Slinton 			case '\n':
317*9813Slinton 				++lineno;
318*9813Slinton 				continue;
319*9813Slinton 
320*9813Slinton 			default:
321*9813Slinton 				val = c;
322*9813Slinton 				goto mkcc;
323*9813Slinton 
324*9813Slinton 			case 'n':
325*9813Slinton 				val = '\n';
326*9813Slinton 				goto mkcc;
327*9813Slinton 
328*9813Slinton 			case 'r':
329*9813Slinton 				val = '\r';
330*9813Slinton 				goto mkcc;
331*9813Slinton 
332*9813Slinton 			case 'b':
333*9813Slinton 				val = '\b';
334*9813Slinton 				goto mkcc;
335*9813Slinton 
336*9813Slinton 			case 't':
337*9813Slinton 				val = '\t';
338*9813Slinton 				goto mkcc;
339*9813Slinton 
340*9813Slinton 			case 'f':
341*9813Slinton 				val = '\f';
342*9813Slinton 				goto mkcc;
343*9813Slinton 
344*9813Slinton 			case 'v':
345*9813Slinton 				val = '\013';
346*9813Slinton 				goto mkcc;
347*9813Slinton 
348*9813Slinton 			case '0':
349*9813Slinton 			case '1':
350*9813Slinton 			case '2':
351*9813Slinton 			case '3':
352*9813Slinton 			case '4':
353*9813Slinton 			case '5':
354*9813Slinton 			case '6':
355*9813Slinton 			case '7':
356*9813Slinton 				val = c-'0';
357*9813Slinton 				c=getchar();  /* try for 2 */
358*9813Slinton 				if( lxmask[c+1] & LEXOCT ){
359*9813Slinton 					val = (val<<3) | (c-'0');
360*9813Slinton 					c = getchar();  /* try for 3 */
361*9813Slinton 					if( lxmask[c+1] & LEXOCT ){
362*9813Slinton 						val = (val<<3) | (c-'0');
363*9813Slinton 						}
364*9813Slinton 					else ungetc( c ,stdin);
365*9813Slinton 					}
366*9813Slinton 				else ungetc( c ,stdin);
367*9813Slinton 
368*9813Slinton 				goto mkcc1;
369*9813Slinton 
370*9813Slinton 				}
371*9813Slinton 		default:
372*9813Slinton 			val =c;
373*9813Slinton 		mkcc:
374*9813Slinton 			val = CCTRANS(val);
375*9813Slinton 		mkcc1:
376*9813Slinton 			if( lxmatch == '\'' ){
377*9813Slinton 				val = CHARCAST(val);  /* it is, after all, a "character" constant */
378*9813Slinton 				makecc( val, i );
379*9813Slinton 				}
380*9813Slinton 			else { /* stash the byte into the string */
381*9813Slinton 				if( strflg ) {
382*9813Slinton 					if( ct==0 || i<ct ) putbyte( val );
383*9813Slinton 					else if( i == ct ) werror( "non-null byte ignored in string initializer" );
384*9813Slinton 					}
385*9813Slinton 				else bycode( val, i );
386*9813Slinton 				}
387*9813Slinton 			++i;
388*9813Slinton 			continue;
389*9813Slinton 			}
390*9813Slinton 		break;
391*9813Slinton 		}
392*9813Slinton 	/* end of string or  char constant */
393*9813Slinton 
394*9813Slinton 	if( lxmatch == '"' ){
395*9813Slinton 		if( strflg ){ /* end the string */
396*9813Slinton 			if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
397*9813Slinton 			}
398*9813Slinton 		else {  /* the initializer gets a null byte */
399*9813Slinton 			bycode( 0, i++ );
400*9813Slinton 			bycode( -1, i );
401*9813Slinton 			dimtab[curdim] = i;  /* in case of later sizeof ... */
402*9813Slinton 			}
403*9813Slinton 		}
404*9813Slinton 	else { /* end the character constant */
405*9813Slinton 		if( i == 0 ) uerror( "empty character constant" );
406*9813Slinton 		if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
407*9813Slinton 			uerror( "too many characters in character constant" );
408*9813Slinton 		}
409*9813Slinton 	}
410*9813Slinton 
411*9813Slinton lxcom(){
412*9813Slinton 	register c;
413*9813Slinton 	/* saw a /*: process a comment */
414*9813Slinton 
415*9813Slinton 	for(;;){
416*9813Slinton 
417*9813Slinton 		switch( c = getchar() ){
418*9813Slinton 
419*9813Slinton 		case EOF:
420*9813Slinton 			uerror( "unexpected EOF" );
421*9813Slinton 			return;
422*9813Slinton 
423*9813Slinton 		case '\n':
424*9813Slinton 			++lineno;
425*9813Slinton 
426*9813Slinton 		default:
427*9813Slinton 			continue;
428*9813Slinton 
429*9813Slinton 		case '*':
430*9813Slinton 			if( (c = getchar()) == '/' ) return;
431*9813Slinton 			else ungetc( c ,stdin);
432*9813Slinton 			continue;
433*9813Slinton 
434*9813Slinton # ifdef LINT
435*9813Slinton 		case 'V':
436*9813Slinton 			lxget( c, LEXLET|LEXDIG );
437*9813Slinton 			{
438*9813Slinton 				extern int vaflag;
439*9813Slinton 				int i;
440*9813Slinton 				i = yytext[7]?yytext[7]-'0':0;
441*9813Slinton 				yytext[7] = '\0';
442*9813Slinton 				if( strcmp( yytext, "VARARGS" ) ) continue;
443*9813Slinton 				vaflag = i;
444*9813Slinton 				continue;
445*9813Slinton 				}
446*9813Slinton 		case 'L':
447*9813Slinton 			lxget( c, LEXLET );
448*9813Slinton 			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
449*9813Slinton 			{
450*9813Slinton 				extern int libflag;
451*9813Slinton 				libflag = 1;
452*9813Slinton 				}
453*9813Slinton 			continue;
454*9813Slinton 
455*9813Slinton 		case 'A':
456*9813Slinton 			lxget( c, LEXLET );
457*9813Slinton 			if( strcmp( yytext, "ARGSUSED" ) ) continue;
458*9813Slinton 			{
459*9813Slinton 				extern int argflag, vflag;
460*9813Slinton 				argflag = 1;
461*9813Slinton 				vflag = 0;
462*9813Slinton 				}
463*9813Slinton 			continue;
464*9813Slinton 
465*9813Slinton 		case 'N':
466*9813Slinton 			lxget( c, LEXLET );
467*9813Slinton 			if( strcmp( yytext, "NOTREACHED" ) ) continue;
468*9813Slinton 			reached = 0;
469*9813Slinton 			continue;
470*9813Slinton # endif
471*9813Slinton 			}
472*9813Slinton 		}
473*9813Slinton 	}
474*9813Slinton 
475*9813Slinton yylex(){
476*9813Slinton 	for(;;){
477*9813Slinton 
478*9813Slinton 		register lxchar;
479*9813Slinton 		register struct lxdope *p;
480*9813Slinton 		register struct symtab *sp;
481*9813Slinton 		int id;
482*9813Slinton 
483*9813Slinton 		switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
484*9813Slinton 
485*9813Slinton 		onechar:
486*9813Slinton 			ungetc( lxchar ,stdin);
487*9813Slinton 
488*9813Slinton 		case A_1C:
489*9813Slinton 			/* eat up a single character, and return an opcode */
490*9813Slinton 
491*9813Slinton 			yylval.intval = p->lxval;
492*9813Slinton 			return( p->lxtok );
493*9813Slinton 
494*9813Slinton 		case A_ERR:
495*9813Slinton 			uerror( "illegal character: %03o (octal)", lxchar );
496*9813Slinton 			break;
497*9813Slinton 
498*9813Slinton 		case A_LET:
499*9813Slinton 			/* collect an identifier, check for reserved word, and return */
500*9813Slinton 			lxget( lxchar, LEXLET|LEXDIG );
501*9813Slinton 			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
502*9813Slinton 			if( lxchar== 0 ) continue;
503*9813Slinton #ifdef FLEXNAMES
504*9813Slinton 			id = lookup( hash(yytext),
505*9813Slinton #else
506*9813Slinton 			id = lookup( yytext,
507*9813Slinton #endif
508*9813Slinton 				/* tag name for struct/union/enum */
509*9813Slinton 				(stwart&TAGNAME)? STAG:
510*9813Slinton 				/* member name for struct/union */
511*9813Slinton 				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
512*9813Slinton 			sp = &stab[id];
513*9813Slinton 			if( sp->sclass == TYPEDEF && !stwart ){
514*9813Slinton 				stwart = instruct;
515*9813Slinton 				yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
516*9813Slinton 				return( TYPE );
517*9813Slinton 				}
518*9813Slinton 			stwart = (stwart&SEENAME) ? instruct : 0;
519*9813Slinton 			yylval.intval = id;
520*9813Slinton 			return( NAME );
521*9813Slinton 
522*9813Slinton 		case A_DIG:
523*9813Slinton 			/* collect a digit string, then look at last one... */
524*9813Slinton 			lastcon = 0;
525*9813Slinton 			lxget( lxchar, LEXDIG );
526*9813Slinton 			switch( lxchar=getchar() ){
527*9813Slinton 
528*9813Slinton 			case 'x':
529*9813Slinton 			case 'X':
530*9813Slinton 				if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
531*9813Slinton 				lxmore( lxchar, LEXHEX );
532*9813Slinton 				/* convert the value */
533*9813Slinton 				{
534*9813Slinton 					register char *cp;
535*9813Slinton 					for( cp = yytext+2; *cp; ++cp ){
536*9813Slinton 						/* this code won't work for all wild character sets,
537*9813Slinton 						   but seems ok for ascii and ebcdic */
538*9813Slinton 						lastcon <<= 4;
539*9813Slinton 						if( isdigit( *cp ) ) lastcon += *cp-'0';
540*9813Slinton 						else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
541*9813Slinton 						else lastcon += *cp - 'a'+ 10;
542*9813Slinton 						}
543*9813Slinton 					}
544*9813Slinton 
545*9813Slinton 			hexlong:
546*9813Slinton 				/* criterion for longness for hex and octal constants is that it
547*9813Slinton 				   fit within 0177777 */
548*9813Slinton 				if( lastcon & ~0177777L ) yylval.intval = 1;
549*9813Slinton 				else yylval.intval = 0;
550*9813Slinton 
551*9813Slinton 				goto islong;
552*9813Slinton 
553*9813Slinton 			case '.':
554*9813Slinton 				lxmore( lxchar, LEXDIG );
555*9813Slinton 
556*9813Slinton 			getfp:
557*9813Slinton 				if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
558*9813Slinton 
559*9813Slinton 			case 'e':
560*9813Slinton 			case 'E':
561*9813Slinton 					if( (lxchar=getchar()) == '+' || lxchar == '-' ){
562*9813Slinton 						*lxgcp++ = 'e';
563*9813Slinton 						}
564*9813Slinton 					else {
565*9813Slinton 						ungetc(lxchar,stdin);
566*9813Slinton 						lxchar = 'e';
567*9813Slinton 						}
568*9813Slinton 					lxmore( lxchar, LEXDIG );
569*9813Slinton 					/* now have the whole thing... */
570*9813Slinton 					}
571*9813Slinton 				else {  /* no exponent */
572*9813Slinton 					ungetc( lxchar ,stdin);
573*9813Slinton 					}
574*9813Slinton 				return( isitfloat( yytext ) );
575*9813Slinton 
576*9813Slinton 			default:
577*9813Slinton 				ungetc( lxchar ,stdin);
578*9813Slinton 				if( yytext[0] == '0' ){
579*9813Slinton 					/* convert in octal */
580*9813Slinton 					register char *cp;
581*9813Slinton 					for( cp = yytext+1; *cp; ++cp ){
582*9813Slinton 						lastcon <<= 3;
583*9813Slinton 						lastcon += *cp - '0';
584*9813Slinton 						}
585*9813Slinton 					goto hexlong;
586*9813Slinton 					}
587*9813Slinton 				else {
588*9813Slinton 					/* convert in decimal */
589*9813Slinton 					register char *cp;
590*9813Slinton 					for( cp = yytext; *cp; ++cp ){
591*9813Slinton 						lastcon = lastcon * 10 + *cp - '0';
592*9813Slinton 						}
593*9813Slinton 					}
594*9813Slinton 
595*9813Slinton 				/* decide if it is long or not (decimal case) */
596*9813Slinton 
597*9813Slinton 				/* if it is positive and fits in 15 bits, or negative and
598*9813Slinton 				   and fits in 15 bits plus an extended sign, it is int; otherwise long */
599*9813Slinton 				/* if there is an l or L following, all bets are off... */
600*9813Slinton 
601*9813Slinton 				{	CONSZ v;
602*9813Slinton 					v = lastcon & ~077777L;
603*9813Slinton 					if( v == 0 || v == ~077777L ) yylval.intval = 0;
604*9813Slinton 					else yylval.intval = 1;
605*9813Slinton 					}
606*9813Slinton 
607*9813Slinton 			islong:
608*9813Slinton 				/* finally, look for trailing L or l */
609*9813Slinton 				if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
610*9813Slinton 				else ungetc( lxchar ,stdin);
611*9813Slinton 				return( ICON );
612*9813Slinton 				}
613*9813Slinton 
614*9813Slinton 		case A_DOT:
615*9813Slinton 			/* look for a dot: if followed by a digit, floating point */
616*9813Slinton 			lxchar = getchar();
617*9813Slinton 			if( lxmask[lxchar+1] & LEXDIG ){
618*9813Slinton 				ungetc(lxchar,stdin);
619*9813Slinton 				lxget( '.', LEXDIG );
620*9813Slinton 				goto getfp;
621*9813Slinton 				}
622*9813Slinton 			stwart = FUNNYNAME;
623*9813Slinton 			goto onechar;
624*9813Slinton 
625*9813Slinton 		case A_STR:
626*9813Slinton 			/* string constant */
627*9813Slinton 			lxmatch = '"';
628*9813Slinton 			return( STRING );
629*9813Slinton 
630*9813Slinton 		case A_CC:
631*9813Slinton 			/* character constant */
632*9813Slinton 			lxmatch = '\'';
633*9813Slinton 			lastcon = 0;
634*9813Slinton 			lxstr(0);
635*9813Slinton 			yylval.intval = 0;
636*9813Slinton 			return( ICON );
637*9813Slinton 
638*9813Slinton 		case A_BCD:
639*9813Slinton 			{
640*9813Slinton 				register i;
641*9813Slinton 				int j;
642*9813Slinton 				for( i=0; i<LXTSZ; ++i ){
643*9813Slinton 					if( ( j = getchar() ) == '`' ) break;
644*9813Slinton 					if( j == '\n' ){
645*9813Slinton 						uerror( "newline in BCD constant" );
646*9813Slinton 						break;
647*9813Slinton 						}
648*9813Slinton 					yytext[i] = j;
649*9813Slinton 					}
650*9813Slinton 				yytext[i] = '\0';
651*9813Slinton 				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
652*9813Slinton # ifdef gcos
653*9813Slinton 				else strtob( yytext, &lastcon, i );
654*9813Slinton 				lastcon >>= 6*(6-i);
655*9813Slinton # else
656*9813Slinton 				uerror( "gcos BCD constant illegal" );
657*9813Slinton # endif
658*9813Slinton 				yylval.intval = 0;  /* not long */
659*9813Slinton 				return( ICON );
660*9813Slinton 				}
661*9813Slinton 
662*9813Slinton 		case A_SL:
663*9813Slinton 			/* / */
664*9813Slinton 			if( (lxchar=getchar()) != '*' ) goto onechar;
665*9813Slinton 			lxcom();
666*9813Slinton 		case A_WS:
667*9813Slinton 			continue;
668*9813Slinton 
669*9813Slinton 		case A_NL:
670*9813Slinton 			++lineno;
671*9813Slinton 			lxtitle();
672*9813Slinton 			continue;
673*9813Slinton 
674*9813Slinton 		case A_NOT:
675*9813Slinton 			/* ! */
676*9813Slinton 			if( (lxchar=getchar()) != '=' ) goto onechar;
677*9813Slinton 			yylval.intval = NE;
678*9813Slinton 			return( EQUOP );
679*9813Slinton 
680*9813Slinton 		case A_MI:
681*9813Slinton 			/* - */
682*9813Slinton 			if( (lxchar=getchar()) == '-' ){
683*9813Slinton 				yylval.intval = DECR;
684*9813Slinton 				return( INCOP );
685*9813Slinton 				}
686*9813Slinton 			if( lxchar != '>' ) goto onechar;
687*9813Slinton 			stwart = FUNNYNAME;
688*9813Slinton 			yylval.intval=STREF;
689*9813Slinton 			return( STROP );
690*9813Slinton 
691*9813Slinton 		case A_PL:
692*9813Slinton 			/* + */
693*9813Slinton 			if( (lxchar=getchar()) != '+' ) goto onechar;
694*9813Slinton 			yylval.intval = INCR;
695*9813Slinton 			return( INCOP );
696*9813Slinton 
697*9813Slinton 		case A_AND:
698*9813Slinton 			/* & */
699*9813Slinton 			if( (lxchar=getchar()) != '&' ) goto onechar;
700*9813Slinton 			return( yylval.intval = ANDAND );
701*9813Slinton 
702*9813Slinton 		case A_OR:
703*9813Slinton 			/* | */
704*9813Slinton 			if( (lxchar=getchar()) != '|' ) goto onechar;
705*9813Slinton 			return( yylval.intval = OROR );
706*9813Slinton 
707*9813Slinton 		case A_LT:
708*9813Slinton 			/* < */
709*9813Slinton 			if( (lxchar=getchar()) == '<' ){
710*9813Slinton 				yylval.intval = LS;
711*9813Slinton 				return( SHIFTOP );
712*9813Slinton 				}
713*9813Slinton 			if( lxchar != '=' ) goto onechar;
714*9813Slinton 			yylval.intval = LE;
715*9813Slinton 			return( RELOP );
716*9813Slinton 
717*9813Slinton 		case A_GT:
718*9813Slinton 			/* > */
719*9813Slinton 			if( (lxchar=getchar()) == '>' ){
720*9813Slinton 				yylval.intval = RS;
721*9813Slinton 				return(SHIFTOP );
722*9813Slinton 				}
723*9813Slinton 			if( lxchar != '=' ) goto onechar;
724*9813Slinton 			yylval.intval = GE;
725*9813Slinton 			return( RELOP );
726*9813Slinton 
727*9813Slinton 		case A_EQ:
728*9813Slinton 			/* = */
729*9813Slinton 			switch( lxchar = getchar() ){
730*9813Slinton 
731*9813Slinton 			case '=':
732*9813Slinton 				yylval.intval = EQ;
733*9813Slinton 				return( EQUOP );
734*9813Slinton 
735*9813Slinton 			case '+':
736*9813Slinton 				yylval.intval = ASG PLUS;
737*9813Slinton 				break;
738*9813Slinton 
739*9813Slinton 			case '-':
740*9813Slinton 				yylval.intval = ASG MINUS;
741*9813Slinton 
742*9813Slinton 			warn:
743*9813Slinton 				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
744*9813Slinton 					werror( "ambiguous assignment: assignment op taken" );
745*9813Slinton 					}
746*9813Slinton 				ungetc( lxchar ,stdin);
747*9813Slinton 				break;
748*9813Slinton 
749*9813Slinton 			case '*':
750*9813Slinton 				yylval.intval = ASG MUL;
751*9813Slinton 				goto warn;
752*9813Slinton 
753*9813Slinton 			case '/':
754*9813Slinton 				yylval.intval = ASG DIV;
755*9813Slinton 				break;
756*9813Slinton 
757*9813Slinton 			case '%':
758*9813Slinton 				yylval.intval = ASG MOD;
759*9813Slinton 				break;
760*9813Slinton 
761*9813Slinton 			case '&':
762*9813Slinton 				yylval.intval = ASG AND;
763*9813Slinton 				break;
764*9813Slinton 
765*9813Slinton 			case '|':
766*9813Slinton 				yylval.intval = ASG OR;
767*9813Slinton 				break;
768*9813Slinton 
769*9813Slinton 			case '^':
770*9813Slinton 				yylval.intval = ASG ER;
771*9813Slinton 				break;
772*9813Slinton 
773*9813Slinton 			case '<':
774*9813Slinton 				if( (lxchar=getchar()) != '<' ){
775*9813Slinton 					uerror( "=<%c illegal", lxchar );
776*9813Slinton 					}
777*9813Slinton 				yylval.intval = ASG LS;
778*9813Slinton 				break;
779*9813Slinton 
780*9813Slinton 			case '>':
781*9813Slinton 				if( (lxchar=getchar()) != '>' ){
782*9813Slinton 					uerror( "=>%c illegal", lxchar );
783*9813Slinton 					}
784*9813Slinton 				yylval.intval = ASG RS;
785*9813Slinton 				break;
786*9813Slinton 
787*9813Slinton 			default:
788*9813Slinton 				goto onechar;
789*9813Slinton 
790*9813Slinton 				}
791*9813Slinton 
792*9813Slinton 			return( ASOP );
793*9813Slinton 
794*9813Slinton 		default:
795*9813Slinton 			cerror( "yylex error, character %03o (octal)", lxchar );
796*9813Slinton 
797*9813Slinton 			}
798*9813Slinton 
799*9813Slinton 		/* ordinarily, repeat here... */
800*9813Slinton 		cerror( "out of switch in yylex" );
801*9813Slinton 
802*9813Slinton 		}
803*9813Slinton 
804*9813Slinton 	}
805*9813Slinton 
806*9813Slinton struct lxrdope {
807*9813Slinton 	/* dope for reserved, in alphabetical order */
808*9813Slinton 
809*9813Slinton 	char *lxrch;	/* name of reserved word */
810*9813Slinton 	short lxract;	/* reserved word action */
811*9813Slinton 	short lxrval;	/* value to be returned */
812*9813Slinton 	} lxrdope[] = {
813*9813Slinton 
814*9813Slinton 	"asm",		AR_A,	0,
815*9813Slinton 	"auto",		AR_CL,	AUTO,
816*9813Slinton 	"break",	AR_RW,	BREAK,
817*9813Slinton 	"char",		AR_TY,	CHAR,
818*9813Slinton 	"case",		AR_RW,	CASE,
819*9813Slinton 	"continue",	AR_RW,	CONTINUE,
820*9813Slinton 	"double",	AR_TY,	DOUBLE,
821*9813Slinton 	"default",	AR_RW,	DEFAULT,
822*9813Slinton 	"do",		AR_RW,	DO,
823*9813Slinton 	"extern",	AR_CL,	EXTERN,
824*9813Slinton 	"else",		AR_RW,	ELSE,
825*9813Slinton 	"enum",		AR_E,	ENUM,
826*9813Slinton 	"for",		AR_RW,	FOR,
827*9813Slinton 	"float",	AR_TY,	FLOAT,
828*9813Slinton 	"fortran",	AR_CL,	FORTRAN,
829*9813Slinton 	"goto",		AR_RW,	GOTO,
830*9813Slinton 	"if",		AR_RW,	IF,
831*9813Slinton 	"int",		AR_TY,	INT,
832*9813Slinton 	"long",		AR_TY,	LONG,
833*9813Slinton 	"return",	AR_RW,	RETURN,
834*9813Slinton 	"register",	AR_CL,	REGISTER,
835*9813Slinton 	"switch",	AR_RW,	SWITCH,
836*9813Slinton 	"struct",	AR_S,	0,
837*9813Slinton 	"sizeof",	AR_RW,	SIZEOF,
838*9813Slinton 	"short",	AR_TY,	SHORT,
839*9813Slinton 	"static",	AR_CL,	STATIC,
840*9813Slinton 	"typedef",	AR_CL,	TYPEDEF,
841*9813Slinton 	"unsigned",	AR_TY,	UNSIGNED,
842*9813Slinton 	"union",	AR_U,	0,
843*9813Slinton 	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
844*9813Slinton 	"while",	AR_RW,	WHILE,
845*9813Slinton 	"",		0,	0,	/* to stop the search */
846*9813Slinton 	};
847*9813Slinton 
848*9813Slinton lxres() {
849*9813Slinton 	/* check to see of yytext is reserved; if so,
850*9813Slinton 	/* do the appropriate action and return */
851*9813Slinton 	/* otherwise, return -1 */
852*9813Slinton 
853*9813Slinton 	register c, ch;
854*9813Slinton 	register struct lxrdope *p;
855*9813Slinton 
856*9813Slinton 	ch = yytext[0];
857*9813Slinton 
858*9813Slinton 	if( !islower(ch) ) return( -1 );
859*9813Slinton 
860*9813Slinton 	switch( ch ){
861*9813Slinton 
862*9813Slinton 	case 'a':
863*9813Slinton 		c=0; break;
864*9813Slinton 	case 'b':
865*9813Slinton 		c=2; break;
866*9813Slinton 	case 'c':
867*9813Slinton 		c=3; break;
868*9813Slinton 	case 'd':
869*9813Slinton 		c=6; break;
870*9813Slinton 	case 'e':
871*9813Slinton 		c=9; break;
872*9813Slinton 	case 'f':
873*9813Slinton 		c=12; break;
874*9813Slinton 	case 'g':
875*9813Slinton 		c=15; break;
876*9813Slinton 	case 'i':
877*9813Slinton 		c=16; break;
878*9813Slinton 	case 'l':
879*9813Slinton 		c=18; break;
880*9813Slinton 	case 'r':
881*9813Slinton 		c=19; break;
882*9813Slinton 	case 's':
883*9813Slinton 		c=21; break;
884*9813Slinton 	case 't':
885*9813Slinton 		c=26; break;
886*9813Slinton 	case 'u':
887*9813Slinton 		c=27; break;
888*9813Slinton 	case 'v':
889*9813Slinton 		c=29; break;
890*9813Slinton 	case 'w':
891*9813Slinton 		c=30; break;
892*9813Slinton 
893*9813Slinton 	default:
894*9813Slinton 		return( -1 );
895*9813Slinton 		}
896*9813Slinton 
897*9813Slinton 	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
898*9813Slinton 		if( !strcmp( yytext, p->lxrch ) ){ /* match */
899*9813Slinton 			switch( p->lxract ){
900*9813Slinton 
901*9813Slinton 			case AR_TY:
902*9813Slinton 				/* type word */
903*9813Slinton 				stwart = instruct;
904*9813Slinton 				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
905*9813Slinton 				return( TYPE );
906*9813Slinton 
907*9813Slinton 			case AR_RW:
908*9813Slinton 				/* ordinary reserved word */
909*9813Slinton 				return( yylval.intval = p->lxrval );
910*9813Slinton 
911*9813Slinton 			case AR_CL:
912*9813Slinton 				/* class word */
913*9813Slinton 				yylval.intval = p->lxrval;
914*9813Slinton 				return( CLASS );
915*9813Slinton 
916*9813Slinton 			case AR_S:
917*9813Slinton 				/* struct */
918*9813Slinton 				stwart = INSTRUCT|SEENAME|TAGNAME;
919*9813Slinton 				yylval.intval = INSTRUCT;
920*9813Slinton 				return( STRUCT );
921*9813Slinton 
922*9813Slinton 			case AR_U:
923*9813Slinton 				/* union */
924*9813Slinton 				stwart = INUNION|SEENAME|TAGNAME;
925*9813Slinton 				yylval.intval = INUNION;
926*9813Slinton 				return( STRUCT );
927*9813Slinton 
928*9813Slinton 			case AR_E:
929*9813Slinton 				/* enums */
930*9813Slinton 				stwart = SEENAME|TAGNAME;
931*9813Slinton 				return( yylval.intval = ENUM );
932*9813Slinton 
933*9813Slinton 			case AR_A:
934*9813Slinton 				/* asm */
935*9813Slinton 				asm_esc = 1; /* warn the world! */
936*9813Slinton 				lxget( ' ', LEXWS );
937*9813Slinton 				if( getchar() != '(' ) goto badasm;
938*9813Slinton 				lxget( ' ', LEXWS );
939*9813Slinton 				if( getchar() != '"' ) goto badasm;
940*9813Slinton # ifndef ONEPASS
941*9813Slinton # ifndef LINT
942*9813Slinton 				putchar(')');
943*9813Slinton # endif
944*9813Slinton # endif
945*9813Slinton 				while( (c=getchar()) != '"' ){
946*9813Slinton 					if( c=='\n' || c==EOF ) goto badasm;
947*9813Slinton # ifndef LINT
948*9813Slinton 					putchar(c);
949*9813Slinton # endif
950*9813Slinton 					}
951*9813Slinton 				lxget( ' ', LEXWS );
952*9813Slinton 				if( getchar() != ')' ) goto badasm;
953*9813Slinton # ifndef LINT
954*9813Slinton 				putchar('\n');
955*9813Slinton # endif
956*9813Slinton 				return( 0 );
957*9813Slinton 
958*9813Slinton 			badasm:
959*9813Slinton 				uerror( "bad asm construction" );
960*9813Slinton 				return( 0 );
961*9813Slinton 
962*9813Slinton 			default:
963*9813Slinton 				cerror( "bad AR_?? action" );
964*9813Slinton 				}
965*9813Slinton 			}
966*9813Slinton 		}
967*9813Slinton 	return( -1 );
968*9813Slinton 	}
969*9813Slinton 
970*9813Slinton extern int	labelno;
971*9813Slinton 
972*9813Slinton lxtitle(){
973*9813Slinton 	/* called after a newline; set linenumber and file name */
974*9813Slinton 
975*9813Slinton 	register c, val;
976*9813Slinton 	register char *cp, *cq;
977*9813Slinton 
978*9813Slinton 	for(;;){  /* might be several such lines in a row */
979*9813Slinton 		if( (c=getchar()) != '#' ){
980*9813Slinton 			if( c != EOF ) ungetc(c,stdin);
981*9813Slinton #ifndef LINT
982*9813Slinton 			if ( lastloc != PROG) return;
983*9813Slinton 			cp = ftitle;
984*9813Slinton 			cq = ititle;
985*9813Slinton 			while ( *cp ) if (*cp++ != *cq++) return;
986*9813Slinton 			if ( *cq ) return;
987*9813Slinton 			psline();
988*9813Slinton #endif
989*9813Slinton 			return;
990*9813Slinton 			}
991*9813Slinton 
992*9813Slinton 		lxget( ' ', LEXWS );
993*9813Slinton 		val = 0;
994*9813Slinton 		for( c=getchar(); isdigit(c); c=getchar() ){
995*9813Slinton 			val = val*10+ c - '0';
996*9813Slinton 			}
997*9813Slinton 		ungetc( c, stdin );
998*9813Slinton 		lineno = val;
999*9813Slinton 		lxget( ' ', LEXWS );
1000*9813Slinton 		if( (c=getchar()) != '\n' ){
1001*9813Slinton 			for( cp=ftitle; c!='\n'; c=getchar(),++cp ){
1002*9813Slinton 				*cp = c;
1003*9813Slinton 				}
1004*9813Slinton 			*cp = '\0';
1005*9813Slinton #ifndef LINT
1006*9813Slinton 			if (ititle[0] == '\0') {
1007*9813Slinton 				cp = ftitle;
1008*9813Slinton 				cq = ititle;
1009*9813Slinton 				while ( *cp )
1010*9813Slinton 					*cq++ = *cp++;
1011*9813Slinton 				*cq = '\0';
1012*9813Slinton 				*--cq = '\0';
1013*9813Slinton #ifndef FLEXNAMES
1014*9813Slinton 				for ( cp = ititle+1; *(cp-1); cp += 8 ) {
1015*9813Slinton 					pstab(cp, N_SO);
1016*9813Slinton 					if (gdebug) printf("0,0,LL%d\n", labelno);
1017*9813Slinton 					}
1018*9813Slinton #else
1019*9813Slinton 				pstab(ititle+1, N_SO);
1020*9813Slinton 				if (gdebug) printf("0,0,LL%d\n", labelno);
1021*9813Slinton #endif
1022*9813Slinton 
1023*9813Slinton 				*cq = '"';
1024*9813Slinton 				printf("LL%d:\n", labelno++);
1025*9813Slinton 				}
1026*9813Slinton #endif
1027*9813Slinton 			}
1028*9813Slinton 		}
1029*9813Slinton 	}
1030*9813Slinton 
1031*9813Slinton #ifdef FLEXNAMES
1032*9813Slinton #define	NSAVETAB	4096
1033*9813Slinton char	*savetab;
1034*9813Slinton int	saveleft;
1035*9813Slinton 
1036*9813Slinton char *
1037*9813Slinton savestr(cp)
1038*9813Slinton 	register char *cp;
1039*9813Slinton {
1040*9813Slinton 	register int len;
1041*9813Slinton 
1042*9813Slinton 	len = strlen(cp) + 1;
1043*9813Slinton 	if (len > saveleft) {
1044*9813Slinton 		saveleft = NSAVETAB;
1045*9813Slinton 		if (len > saveleft)
1046*9813Slinton 			saveleft = len;
1047*9813Slinton 		savetab = (char *)malloc(saveleft);
1048*9813Slinton 		if (savetab == 0)
1049*9813Slinton 			cerror("Ran out of memory (savestr)");
1050*9813Slinton 	}
1051*9813Slinton 	strncpy(savetab, cp, len);
1052*9813Slinton 	cp = savetab;
1053*9813Slinton 	savetab += len;
1054*9813Slinton 	saveleft -= len;
1055*9813Slinton 	return (cp);
1056*9813Slinton }
1057*9813Slinton 
1058*9813Slinton /*
1059*9813Slinton  * The definition for the segmented hash tables.
1060*9813Slinton  */
1061*9813Slinton #define	MAXHASH	20
1062*9813Slinton #define	HASHINC	1013
1063*9813Slinton struct ht {
1064*9813Slinton 	char	**ht_low;
1065*9813Slinton 	char	**ht_high;
1066*9813Slinton 	int	ht_used;
1067*9813Slinton } htab[MAXHASH];
1068*9813Slinton 
1069*9813Slinton char *
1070*9813Slinton hash(s)
1071*9813Slinton 	char *s;
1072*9813Slinton {
1073*9813Slinton 	register char **h;
1074*9813Slinton 	register i;
1075*9813Slinton 	register char *cp;
1076*9813Slinton 	struct ht *htp;
1077*9813Slinton 	int sh;
1078*9813Slinton 
1079*9813Slinton 	/*
1080*9813Slinton 	 * The hash function is a modular hash of
1081*9813Slinton 	 * the sum of the characters with the sum
1082*9813Slinton 	 * doubled before each successive character
1083*9813Slinton 	 * is added.
1084*9813Slinton 	 */
1085*9813Slinton 	cp = s;
1086*9813Slinton 	i = 0;
1087*9813Slinton 	while (*cp)
1088*9813Slinton 		i = i*2 + *cp++;
1089*9813Slinton 	sh = (i&077777) % HASHINC;
1090*9813Slinton 	cp = s;
1091*9813Slinton 	/*
1092*9813Slinton 	 * There are as many as MAXHASH active
1093*9813Slinton 	 * hash tables at any given point in time.
1094*9813Slinton 	 * The search starts with the first table
1095*9813Slinton 	 * and continues through the active tables
1096*9813Slinton 	 * as necessary.
1097*9813Slinton 	 */
1098*9813Slinton 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
1099*9813Slinton 		if (htp->ht_low == 0) {
1100*9813Slinton 			register char **hp =
1101*9813Slinton 			    (char **) calloc(sizeof (char **), HASHINC);
1102*9813Slinton 			if (hp == 0)
1103*9813Slinton 				cerror("ran out of memory (hash)");
1104*9813Slinton 			htp->ht_low = hp;
1105*9813Slinton 			htp->ht_high = htp->ht_low + HASHINC;
1106*9813Slinton 		}
1107*9813Slinton 		h = htp->ht_low + sh;
1108*9813Slinton 		/*
1109*9813Slinton 		 * quadratic rehash increment
1110*9813Slinton 		 * starts at 1 and incremented
1111*9813Slinton 		 * by two each rehash.
1112*9813Slinton 		 */
1113*9813Slinton 		i = 1;
1114*9813Slinton 		do {
1115*9813Slinton 			if (*h == 0) {
1116*9813Slinton 				if (htp->ht_used > (HASHINC * 3)/4)
1117*9813Slinton 					break;
1118*9813Slinton 				htp->ht_used++;
1119*9813Slinton 				*h = savestr(cp);
1120*9813Slinton 				return (*h);
1121*9813Slinton 			}
1122*9813Slinton 			if (**h == *cp && strcmp(*h, cp) == 0)
1123*9813Slinton 				return (*h);
1124*9813Slinton 			h += i;
1125*9813Slinton 			i += 2;
1126*9813Slinton 			if (h >= htp->ht_high)
1127*9813Slinton 				h -= HASHINC;
1128*9813Slinton 		} while (i < HASHINC);
1129*9813Slinton 	}
1130*9813Slinton 	cerror("ran out of hash tables");
1131*9813Slinton }
1132*9813Slinton #endif
1133