117748Sralph #ifndef lint
2*39158Sbostic static char *sccsid ="@(#)scan.c 2.16 (Berkeley) 09/15/89";
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;
66*39158Sbostic extern void 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 */
mainp1(argc,argv)759813Slinton mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */
769813Slinton
779813Slinton register i;
789813Slinton register char *cp;
7917748Sralph extern int idebug, bdebug, tdebug, edebug;
8017748Sralph extern int ddebug, xdebug, gdebug, adebug;
819813Slinton extern unsigned int offsz;
829813Slinton int fdef = 0;
8332835Sdonn extern char *release;
849813Slinton
859813Slinton offsz = caloff();
869813Slinton for( i=1; i<argc; ++i ){
879813Slinton if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
889813Slinton while( *++cp ){
899813Slinton switch( *cp ){
909813Slinton
919813Slinton case 'r':
929813Slinton fprintf( stderr, "Release: %s\n",
939813Slinton release );
949813Slinton break;
959813Slinton
969813Slinton case 'd':
979813Slinton ++ddebug;
989813Slinton break;
999813Slinton case 'i':
1009813Slinton ++idebug;
1019813Slinton break;
1029813Slinton case 'b':
1039813Slinton ++bdebug;
1049813Slinton break;
1059813Slinton case 't':
1069813Slinton ++tdebug;
1079813Slinton break;
1089813Slinton case 'e':
1099813Slinton ++edebug;
1109813Slinton break;
1119813Slinton case 'x':
1129813Slinton ++xdebug;
1139813Slinton break;
1149813Slinton case 'P': /* profiling */
1159813Slinton ++proflg;
1169813Slinton break;
1179813Slinton case 'g':
1189813Slinton ++gdebug;
1199813Slinton break;
12017748Sralph case 'a':
12117748Sralph ++adebug;
12217748Sralph break;
1239816Slinton case 'G':
1249816Slinton ++gdebug;
1259816Slinton oldway = 1;
1269816Slinton break;
1279813Slinton }
1289813Slinton }
1299813Slinton }
1309813Slinton else {
1319813Slinton if( *(argv[i]) != '-' ) switch( fdef++ ) {
1329813Slinton case 0:
1339813Slinton case 1:
1349813Slinton if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
1359813Slinton fprintf(stderr, "ccom:can't open %s\n", argv[i]);
1369813Slinton exit(1);
1379813Slinton }
1389813Slinton break;
1399813Slinton
1409813Slinton default:
1419813Slinton ;
1429813Slinton }
1439813Slinton }
1449813Slinton }
1459813Slinton
1469813Slinton # ifdef ONEPASS
14732836Sdonn (void) p2init( argc, argv );
1489813Slinton # endif
1499813Slinton
1509813Slinton for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
1519813Slinton
15217601Sralph lineno = 1;
15317601Sralph
1549813Slinton lxinit();
1559813Slinton tinit();
1569813Slinton mkdope();
1579813Slinton
1589813Slinton /* dimension table initialization */
1599813Slinton
1609813Slinton dimtab[NULL] = 0;
1619813Slinton dimtab[CHAR] = SZCHAR;
1629813Slinton dimtab[INT] = SZINT;
1639813Slinton dimtab[FLOAT] = SZFLOAT;
1649813Slinton dimtab[DOUBLE] = SZDOUBLE;
1659813Slinton dimtab[LONG] = SZLONG;
1669813Slinton dimtab[SHORT] = SZSHORT;
1679813Slinton dimtab[UCHAR] = SZCHAR;
1689813Slinton dimtab[USHORT] = SZSHORT;
1699813Slinton dimtab[UNSIGNED] = SZINT;
1709813Slinton dimtab[ULONG] = SZLONG;
1719813Slinton /* starts past any of the above */
1729813Slinton curdim = 16;
1739813Slinton reached = 1;
1749813Slinton
17524407Smckusick fpe_sigvec.sv_handler = fpe;
17624407Smckusick (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL);
17724407Smckusick
17832836Sdonn (void) yyparse();
1799813Slinton yyaccpt();
1809813Slinton
1819813Slinton ejobcode( nerrors ? 1 : 0 );
1829813Slinton return(nerrors?1:0);
1839813Slinton
1849813Slinton }
1859813Slinton
1869813Slinton # ifdef ibm
1879813Slinton
1889813Slinton # define CSMASK 0377
1899813Slinton # define CSSZ 256
1909813Slinton
1919813Slinton # else
1929813Slinton
1939813Slinton # define CSMASK 0177
1949813Slinton # define CSSZ 128
1959813Slinton
1969813Slinton # endif
1979813Slinton
1989813Slinton short lxmask[CSSZ+1];
1999813Slinton
lxenter(s,m)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
lxmore(c,m)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 */
23832838Sdonn #ifdef gcos
2399813Slinton '`', A_BCD, 0, 0, /* GCOS BCD constant */
24032838Sdonn #endif
2419813Slinton '(', A_1C, LP, 0,
2429813Slinton ')', A_1C, RP, 0,
2439813Slinton '{', A_1C, LC, 0,
2449813Slinton '}', A_1C, RC, 0,
2459813Slinton '[', A_1C, LB, 0,
2469813Slinton ']', A_1C, RB, 0,
2479813Slinton '*', A_1C, MUL, MUL,
2489813Slinton '?', A_1C, QUEST, 0,
2499813Slinton ':', A_1C, COLON, 0,
2509813Slinton '+', A_PL, PLUS, PLUS,
2519813Slinton '-', A_MI, MINUS, MINUS,
2529813Slinton '/', A_SL, DIVOP, DIV,
2539813Slinton '%', A_1C, DIVOP, MOD,
2549813Slinton '&', A_AND, AND, AND,
2559813Slinton '|', A_OR, OR, OR,
2569813Slinton '^', A_1C, ER, ER,
2579813Slinton '!', A_NOT, UNOP, NOT,
2589813Slinton '~', A_1C, UNOP, COMPL,
2599813Slinton ',', A_1C, CM, CM,
2609813Slinton ';', A_1C, SM, 0,
2619813Slinton '.', A_DOT, STROP, DOT,
2629813Slinton '<', A_LT, RELOP, LT,
2639813Slinton '>', A_GT, RELOP, GT,
2649813Slinton '=', A_EQ, ASSIGN, ASSIGN,
2659813Slinton -1, A_1C, 0, 0,
2669813Slinton };
2679813Slinton
2689813Slinton struct lxdope *lxcp[CSSZ+1];
2699813Slinton
lxinit()2709813Slinton lxinit(){
2719813Slinton register struct lxdope *p;
2729813Slinton register i;
2739813Slinton register char *cp;
2749813Slinton /* set up character classes */
2759813Slinton
27632838Sdonn lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
27732838Sdonn #ifdef VMS
27832838Sdonn lxmask['$'+1] |= LEXLET;
27932838Sdonn #endif
2809813Slinton lxenter( "0123456789", LEXDIG );
2819813Slinton lxenter( "0123456789abcdefABCDEF", LEXHEX );
28232838Sdonn lxenter( " \t\r\b\f\v", LEXWS );
2839813Slinton lxenter( "01234567", LEXOCT );
2849813Slinton lxmask['.'+1] |= LEXDOT;
2859813Slinton
2869813Slinton /* make lxcp point to appropriate lxdope entry for each character */
2879813Slinton
2889813Slinton /* initialize error entries */
2899813Slinton
2909813Slinton for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
2919813Slinton
2929813Slinton /* make unique entries */
2939813Slinton
2949813Slinton for( p=lxdope; ; ++p ) {
2959813Slinton lxcp[p->lxch+1] = p;
2969813Slinton if( p->lxch < 0 ) break;
2979813Slinton }
2989813Slinton
2999813Slinton /* handle letters, digits, and whitespace */
3009813Slinton /* by convention, first, second, and third places */
3019813Slinton
30232838Sdonn cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
3039813Slinton while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
30432838Sdonn #ifdef VMS
30532838Sdonn lxcp['$'+1] = &lxdope[1];
30632838Sdonn #endif
3079813Slinton cp = "123456789";
3089813Slinton while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
30932838Sdonn cp = "\t\b\r\f\v";
3109813Slinton while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
3119813Slinton
3129813Slinton /* first line might have title */
3139813Slinton lxtitle();
3149813Slinton
3159813Slinton }
3169813Slinton
31732837Sdonn int lxmatch = 0; /* character to be matched in char or string constant */
3189813Slinton
lxstr(ct)3199813Slinton lxstr(ct){
3209813Slinton /* match a string or character constant, up to lxmatch */
3219813Slinton
3229813Slinton register c;
3239813Slinton register val;
3249813Slinton register i;
3259813Slinton
3269813Slinton i=0;
3279813Slinton while( (c=getchar()) != lxmatch ){
3289813Slinton switch( c ) {
3299813Slinton
3309813Slinton case EOF:
3319813Slinton uerror( "unexpected EOF" );
3329813Slinton break;
3339813Slinton
3349813Slinton case '\n':
3359813Slinton uerror( "newline in string or char constant" );
3369813Slinton ++lineno;
3379813Slinton break;
3389813Slinton
3399813Slinton case '\\':
3409813Slinton switch( c = getchar() ){
3419813Slinton
3429813Slinton case '\n':
3439813Slinton ++lineno;
3449813Slinton continue;
3459813Slinton
3469813Slinton default:
34732838Sdonn #ifdef LINT
34832838Sdonn if( hflag )
34932838Sdonn uerror( "superfluous backslash in %s constant", lxmatch == '\'' ? "char" : "string" );
35032838Sdonn /*FALLTHROUGH*/
35132838Sdonn #endif
35232838Sdonn case '\\':
35332838Sdonn case '\"':
35432838Sdonn case '\'':
3559813Slinton val = c;
3569813Slinton goto mkcc;
3579813Slinton
3589813Slinton case 'n':
3599813Slinton val = '\n';
3609813Slinton goto mkcc;
3619813Slinton
3629813Slinton case 'r':
3639813Slinton val = '\r';
3649813Slinton goto mkcc;
3659813Slinton
3669813Slinton case 'b':
3679813Slinton val = '\b';
3689813Slinton goto mkcc;
3699813Slinton
3709813Slinton case 't':
3719813Slinton val = '\t';
3729813Slinton goto mkcc;
3739813Slinton
3749813Slinton case 'f':
3759813Slinton val = '\f';
3769813Slinton goto mkcc;
3779813Slinton
3789813Slinton case 'v':
37932838Sdonn val = '\v';
3809813Slinton goto mkcc;
3819813Slinton
3829813Slinton case '0':
3839813Slinton case '1':
3849813Slinton case '2':
3859813Slinton case '3':
3869813Slinton case '4':
3879813Slinton case '5':
3889813Slinton case '6':
3899813Slinton case '7':
3909813Slinton val = c-'0';
3919813Slinton c=getchar(); /* try for 2 */
3929813Slinton if( lxmask[c+1] & LEXOCT ){
3939813Slinton val = (val<<3) | (c-'0');
3949813Slinton c = getchar(); /* try for 3 */
3959813Slinton if( lxmask[c+1] & LEXOCT ){
3969813Slinton val = (val<<3) | (c-'0');
3979813Slinton }
3989813Slinton else ungetc( c ,stdin);
3999813Slinton }
4009813Slinton else ungetc( c ,stdin);
4019813Slinton
4029813Slinton goto mkcc1;
4039813Slinton
4049813Slinton }
4059813Slinton default:
4069813Slinton val =c;
4079813Slinton mkcc:
4089813Slinton val = CCTRANS(val);
4099813Slinton mkcc1:
4109813Slinton if( lxmatch == '\'' ){
4119813Slinton val = CHARCAST(val); /* it is, after all, a "character" constant */
4129813Slinton makecc( val, i );
4139813Slinton }
4149813Slinton else { /* stash the byte into the string */
4159813Slinton if( strflg ) {
4169813Slinton if( ct==0 || i<ct ) putbyte( val );
4179813Slinton else if( i == ct ) werror( "non-null byte ignored in string initializer" );
4189813Slinton }
4199813Slinton else bycode( val, i );
4209813Slinton }
4219813Slinton ++i;
4229813Slinton continue;
4239813Slinton }
4249813Slinton break;
4259813Slinton }
4269813Slinton /* end of string or char constant */
4279813Slinton
4289813Slinton if( lxmatch == '"' ){
4299813Slinton if( strflg ){ /* end the string */
4309813Slinton if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */
4319813Slinton }
4329813Slinton else { /* the initializer gets a null byte */
4339813Slinton bycode( 0, i++ );
4349813Slinton bycode( -1, i );
4359813Slinton dimtab[curdim] = i; /* in case of later sizeof ... */
4369813Slinton }
4379813Slinton }
4389813Slinton else { /* end the character constant */
4399813Slinton if( i == 0 ) uerror( "empty character constant" );
4409813Slinton if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
4419813Slinton uerror( "too many characters in character constant" );
4429813Slinton }
44332837Sdonn lxmatch = 0; /* handshake with yylex() */
4449813Slinton }
4459813Slinton
lxcom()4469813Slinton lxcom(){
4479813Slinton register c;
4489813Slinton /* saw a /*: process a comment */
4499813Slinton
4509813Slinton for(;;){
4519813Slinton
4529813Slinton switch( c = getchar() ){
4539813Slinton
4549813Slinton case EOF:
4559813Slinton uerror( "unexpected EOF" );
4569813Slinton return;
4579813Slinton
4589813Slinton case '\n':
4599813Slinton ++lineno;
4609813Slinton
4619813Slinton default:
4629813Slinton continue;
4639813Slinton
4649813Slinton case '*':
4659813Slinton if( (c = getchar()) == '/' ) return;
4669813Slinton else ungetc( c ,stdin);
4679813Slinton continue;
4689813Slinton
4699813Slinton # ifdef LINT
4709813Slinton case 'V':
4719813Slinton lxget( c, LEXLET|LEXDIG );
4729813Slinton {
4739813Slinton extern int vaflag;
4749813Slinton int i;
4759813Slinton i = yytext[7]?yytext[7]-'0':0;
4769813Slinton yytext[7] = '\0';
4779813Slinton if( strcmp( yytext, "VARARGS" ) ) continue;
4789813Slinton vaflag = i;
4799813Slinton continue;
4809813Slinton }
4819813Slinton case 'L':
4829813Slinton lxget( c, LEXLET );
4839813Slinton if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
4849813Slinton {
4859813Slinton extern int libflag;
4869813Slinton libflag = 1;
4879813Slinton }
4889813Slinton continue;
4899813Slinton
4909813Slinton case 'A':
4919813Slinton lxget( c, LEXLET );
4929813Slinton if( strcmp( yytext, "ARGSUSED" ) ) continue;
4939813Slinton {
4949813Slinton extern int argflag, vflag;
4959813Slinton argflag = 1;
4969813Slinton vflag = 0;
4979813Slinton }
4989813Slinton continue;
4999813Slinton
5009813Slinton case 'N':
5019813Slinton lxget( c, LEXLET );
5029813Slinton if( strcmp( yytext, "NOTREACHED" ) ) continue;
5039813Slinton reached = 0;
5049813Slinton continue;
5059813Slinton # endif
5069813Slinton }
5079813Slinton }
5089813Slinton }
5099813Slinton
yylex()5109813Slinton yylex(){
51132839Sdonn double atof();
51232839Sdonn
51332837Sdonn if (lxmatch != 0) {
51432837Sdonn /* recover from a syntax error that consumes a STRING token */
51532837Sdonn strflg = 1;
51632837Sdonn lxstr(0);
51732837Sdonn }
5189813Slinton for(;;){
5199813Slinton
5209813Slinton register lxchar;
5219813Slinton register struct lxdope *p;
5229813Slinton register struct symtab *sp;
5239813Slinton int id;
52432834Sdonn char *s;
52532834Sdonn static char sc[5];
5269813Slinton
5279813Slinton switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
5289813Slinton
5299813Slinton onechar:
5309813Slinton ungetc( lxchar ,stdin);
5319813Slinton
5329813Slinton case A_1C:
5339813Slinton /* eat up a single character, and return an opcode */
5349813Slinton
5359813Slinton yylval.intval = p->lxval;
5369813Slinton return( p->lxtok );
5379813Slinton
5389813Slinton case A_ERR:
53932834Sdonn switch( lxchar ){
54032834Sdonn case '\\': s = "\\\\"; break;
54132834Sdonn case '\0': s = "\\0"; break;
54232834Sdonn default:
54332834Sdonn if( isgraph( lxchar ) ){
54432834Sdonn sc[0] = lxchar;
54532834Sdonn sc[1] = '\0';
54632834Sdonn }
54732834Sdonn else
54832834Sdonn sprintf( sc, "\\%03.3o", (unsigned char) lxchar );
54932834Sdonn s = sc;
55032834Sdonn break;
55132834Sdonn }
55232834Sdonn uerror( "illegal character: '%s'", s );
55332838Sdonn continue; /* ignore it and see if we find more */
5549813Slinton
5559813Slinton case A_LET:
5569813Slinton /* collect an identifier, check for reserved word, and return */
5579813Slinton lxget( lxchar, LEXLET|LEXDIG );
5589813Slinton if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
5599813Slinton if( lxchar== 0 ) continue;
5609813Slinton #ifdef FLEXNAMES
5619813Slinton id = lookup( hash(yytext),
5629813Slinton #else
5639813Slinton id = lookup( yytext,
5649813Slinton #endif
5659813Slinton /* tag name for struct/union/enum */
5669813Slinton (stwart&TAGNAME)? STAG:
5679813Slinton /* member name for struct/union */
5689813Slinton (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
5699813Slinton sp = &stab[id];
5709813Slinton if( sp->sclass == TYPEDEF && !stwart ){
5719813Slinton stwart = instruct;
5729813Slinton yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
5739813Slinton return( TYPE );
5749813Slinton }
5759813Slinton stwart = (stwart&SEENAME) ? instruct : 0;
5769813Slinton yylval.intval = id;
5779813Slinton return( NAME );
5789813Slinton
5799813Slinton case A_DIG:
5809813Slinton /* collect a digit string, then look at last one... */
5819813Slinton lastcon = 0;
5829813Slinton lxget( lxchar, LEXDIG );
5839813Slinton switch( lxchar=getchar() ){
5849813Slinton
5859813Slinton case 'x':
5869813Slinton case 'X':
5879813Slinton if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
5889813Slinton lxmore( lxchar, LEXHEX );
5899813Slinton /* convert the value */
5909813Slinton {
5919813Slinton register char *cp;
5929813Slinton for( cp = yytext+2; *cp; ++cp ){
5939813Slinton /* this code won't work for all wild character sets,
5949813Slinton but seems ok for ascii and ebcdic */
5959813Slinton lastcon <<= 4;
5969813Slinton if( isdigit( *cp ) ) lastcon += *cp-'0';
5979813Slinton else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
5989813Slinton else lastcon += *cp - 'a'+ 10;
5999813Slinton }
6009813Slinton }
6019813Slinton
6029813Slinton hexlong:
6039813Slinton /* criterion for longness for hex and octal constants is that it
6049813Slinton fit within 0177777 */
6059813Slinton if( lastcon & ~0177777L ) yylval.intval = 1;
6069813Slinton else yylval.intval = 0;
6079813Slinton
6089813Slinton goto islong;
6099813Slinton
6109813Slinton case '.':
6119813Slinton lxmore( lxchar, LEXDIG );
6129813Slinton
6139813Slinton getfp:
6149813Slinton if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
6159813Slinton
6169813Slinton case 'e':
6179813Slinton case 'E':
6189813Slinton if( (lxchar=getchar()) == '+' || lxchar == '-' ){
6199813Slinton *lxgcp++ = 'e';
6209813Slinton }
6219813Slinton else {
6229813Slinton ungetc(lxchar,stdin);
6239813Slinton lxchar = 'e';
6249813Slinton }
6259813Slinton lxmore( lxchar, LEXDIG );
6269813Slinton /* now have the whole thing... */
6279813Slinton }
6289813Slinton else { /* no exponent */
6299813Slinton ungetc( lxchar ,stdin);
6309813Slinton }
63132839Sdonn dcon = atof( yytext );
63232839Sdonn if( (lxchar = getchar()) == 'F' || lxchar == 'f' ){
63332839Sdonn fcon = dcon;
63432839Sdonn return( FCON );
63532839Sdonn }
63632839Sdonn else ungetc( lxchar ,stdin);
63732839Sdonn return( DCON );
6389813Slinton
6399813Slinton default:
6409813Slinton ungetc( lxchar ,stdin);
6419813Slinton if( yytext[0] == '0' ){
6429813Slinton /* convert in octal */
6439813Slinton register char *cp;
6449813Slinton for( cp = yytext+1; *cp; ++cp ){
6459813Slinton lastcon <<= 3;
6469813Slinton lastcon += *cp - '0';
6479813Slinton }
6489813Slinton goto hexlong;
6499813Slinton }
6509813Slinton else {
6519813Slinton /* convert in decimal */
6529813Slinton register char *cp;
6539813Slinton for( cp = yytext; *cp; ++cp ){
6549813Slinton lastcon = lastcon * 10 + *cp - '0';
6559813Slinton }
6569813Slinton }
6579813Slinton
6589813Slinton /* decide if it is long or not (decimal case) */
6599813Slinton
6609813Slinton /* if it is positive and fits in 15 bits, or negative and
6619813Slinton and fits in 15 bits plus an extended sign, it is int; otherwise long */
6629813Slinton /* if there is an l or L following, all bets are off... */
6639813Slinton
6649813Slinton { CONSZ v;
6659813Slinton v = lastcon & ~077777L;
6669813Slinton if( v == 0 || v == ~077777L ) yylval.intval = 0;
6679813Slinton else yylval.intval = 1;
6689813Slinton }
6699813Slinton
6709813Slinton islong:
6719813Slinton /* finally, look for trailing L or l */
6729813Slinton if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
6739813Slinton else ungetc( lxchar ,stdin);
6749813Slinton return( ICON );
6759813Slinton }
6769813Slinton
6779813Slinton case A_DOT:
6789813Slinton /* look for a dot: if followed by a digit, floating point */
6799813Slinton lxchar = getchar();
6809813Slinton if( lxmask[lxchar+1] & LEXDIG ){
6819813Slinton ungetc(lxchar,stdin);
6829813Slinton lxget( '.', LEXDIG );
6839813Slinton goto getfp;
6849813Slinton }
6859813Slinton stwart = FUNNYNAME;
6869813Slinton goto onechar;
6879813Slinton
6889813Slinton case A_STR:
6899813Slinton /* string constant */
6909813Slinton lxmatch = '"';
6919813Slinton return( STRING );
6929813Slinton
6939813Slinton case A_CC:
6949813Slinton /* character constant */
6959813Slinton lxmatch = '\'';
6969813Slinton lastcon = 0;
6979813Slinton lxstr(0);
6989813Slinton yylval.intval = 0;
6999813Slinton return( ICON );
7009813Slinton
70132838Sdonn #ifdef gcos
7029813Slinton case A_BCD:
7039813Slinton {
7049813Slinton register i;
7059813Slinton int j;
7069813Slinton for( i=0; i<LXTSZ; ++i ){
7079813Slinton if( ( j = getchar() ) == '`' ) break;
7089813Slinton if( j == '\n' ){
7099813Slinton uerror( "newline in BCD constant" );
7109813Slinton break;
7119813Slinton }
7129813Slinton yytext[i] = j;
7139813Slinton }
7149813Slinton yytext[i] = '\0';
7159813Slinton if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
71632838Sdonn # ifndef unix
7179813Slinton else strtob( yytext, &lastcon, i );
7189813Slinton lastcon >>= 6*(6-i);
7199813Slinton # else
7209813Slinton uerror( "gcos BCD constant illegal" );
7219813Slinton # endif
7229813Slinton yylval.intval = 0; /* not long */
7239813Slinton return( ICON );
7249813Slinton }
72532838Sdonn #endif
7269813Slinton
7279813Slinton case A_SL:
7289813Slinton /* / */
7299813Slinton if( (lxchar=getchar()) != '*' ) goto onechar;
7309813Slinton lxcom();
7319813Slinton case A_WS:
7329813Slinton continue;
7339813Slinton
7349813Slinton case A_NL:
7359813Slinton ++lineno;
7369813Slinton lxtitle();
7379813Slinton continue;
7389813Slinton
7399813Slinton case A_NOT:
7409813Slinton /* ! */
7419813Slinton if( (lxchar=getchar()) != '=' ) goto onechar;
7429813Slinton yylval.intval = NE;
7439813Slinton return( EQUOP );
7449813Slinton
7459813Slinton case A_MI:
7469813Slinton /* - */
7479813Slinton if( (lxchar=getchar()) == '-' ){
7489813Slinton yylval.intval = DECR;
7499813Slinton return( INCOP );
7509813Slinton }
7519813Slinton if( lxchar != '>' ) goto onechar;
7529813Slinton stwart = FUNNYNAME;
7539813Slinton yylval.intval=STREF;
7549813Slinton return( STROP );
7559813Slinton
7569813Slinton case A_PL:
7579813Slinton /* + */
7589813Slinton if( (lxchar=getchar()) != '+' ) goto onechar;
7599813Slinton yylval.intval = INCR;
7609813Slinton return( INCOP );
7619813Slinton
7629813Slinton case A_AND:
7639813Slinton /* & */
7649813Slinton if( (lxchar=getchar()) != '&' ) goto onechar;
7659813Slinton return( yylval.intval = ANDAND );
7669813Slinton
7679813Slinton case A_OR:
7689813Slinton /* | */
7699813Slinton if( (lxchar=getchar()) != '|' ) goto onechar;
7709813Slinton return( yylval.intval = OROR );
7719813Slinton
7729813Slinton case A_LT:
7739813Slinton /* < */
7749813Slinton if( (lxchar=getchar()) == '<' ){
7759813Slinton yylval.intval = LS;
7769813Slinton return( SHIFTOP );
7779813Slinton }
7789813Slinton if( lxchar != '=' ) goto onechar;
7799813Slinton yylval.intval = LE;
7809813Slinton return( RELOP );
7819813Slinton
7829813Slinton case A_GT:
7839813Slinton /* > */
7849813Slinton if( (lxchar=getchar()) == '>' ){
7859813Slinton yylval.intval = RS;
7869813Slinton return(SHIFTOP );
7879813Slinton }
7889813Slinton if( lxchar != '=' ) goto onechar;
7899813Slinton yylval.intval = GE;
7909813Slinton return( RELOP );
7919813Slinton
7929813Slinton case A_EQ:
7939813Slinton /* = */
7949813Slinton switch( lxchar = getchar() ){
7959813Slinton
7969813Slinton case '=':
7979813Slinton yylval.intval = EQ;
7989813Slinton return( EQUOP );
7999813Slinton
80032829Sdonn #ifdef old_assignment_ops
8019813Slinton case '+':
8029813Slinton yylval.intval = ASG PLUS;
8039813Slinton break;
8049813Slinton
8059813Slinton case '-':
8069813Slinton yylval.intval = ASG MINUS;
8079813Slinton
8089813Slinton warn:
8099813Slinton if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
8109813Slinton werror( "ambiguous assignment: assignment op taken" );
8119813Slinton }
8129813Slinton ungetc( lxchar ,stdin);
8139813Slinton break;
8149813Slinton
8159813Slinton case '*':
8169813Slinton yylval.intval = ASG MUL;
8179813Slinton goto warn;
8189813Slinton
8199813Slinton case '/':
8209813Slinton yylval.intval = ASG DIV;
8219813Slinton break;
8229813Slinton
8239813Slinton case '%':
8249813Slinton yylval.intval = ASG MOD;
8259813Slinton break;
8269813Slinton
8279813Slinton case '&':
8289813Slinton yylval.intval = ASG AND;
8299813Slinton break;
8309813Slinton
8319813Slinton case '|':
8329813Slinton yylval.intval = ASG OR;
8339813Slinton break;
8349813Slinton
8359813Slinton case '^':
8369813Slinton yylval.intval = ASG ER;
8379813Slinton break;
8389813Slinton
8399813Slinton case '<':
8409813Slinton if( (lxchar=getchar()) != '<' ){
8419813Slinton uerror( "=<%c illegal", lxchar );
8429813Slinton }
8439813Slinton yylval.intval = ASG LS;
8449813Slinton break;
8459813Slinton
8469813Slinton case '>':
8479813Slinton if( (lxchar=getchar()) != '>' ){
8489813Slinton uerror( "=>%c illegal", lxchar );
8499813Slinton }
8509813Slinton yylval.intval = ASG RS;
8519813Slinton break;
85232829Sdonn #endif old_assignment_ops
8539813Slinton
8549813Slinton default:
8559813Slinton goto onechar;
8569813Slinton
8579813Slinton }
8589813Slinton
85932831Sdonn #ifdef old_assignment_ops /* defeat 'unreachable code' warning */
8609813Slinton return( ASOP );
86132831Sdonn #endif old_assignment_ops
8629813Slinton
8639813Slinton default:
8649813Slinton cerror( "yylex error, character %03o (octal)", lxchar );
8659813Slinton
8669813Slinton }
8679813Slinton
8689813Slinton /* ordinarily, repeat here... */
8699813Slinton cerror( "out of switch in yylex" );
8709813Slinton
8719813Slinton }
8729813Slinton
8739813Slinton }
8749813Slinton
8759813Slinton struct lxrdope {
8769813Slinton /* dope for reserved, in alphabetical order */
8779813Slinton
8789813Slinton char *lxrch; /* name of reserved word */
8799813Slinton short lxract; /* reserved word action */
8809813Slinton short lxrval; /* value to be returned */
8819813Slinton } lxrdope[] = {
8829813Slinton
8839813Slinton "asm", AR_A, 0,
8849813Slinton "auto", AR_CL, AUTO,
8859813Slinton "break", AR_RW, BREAK,
8869813Slinton "char", AR_TY, CHAR,
8879813Slinton "case", AR_RW, CASE,
8889813Slinton "continue", AR_RW, CONTINUE,
8899813Slinton "double", AR_TY, DOUBLE,
8909813Slinton "default", AR_RW, DEFAULT,
8919813Slinton "do", AR_RW, DO,
8929813Slinton "extern", AR_CL, EXTERN,
8939813Slinton "else", AR_RW, ELSE,
8949813Slinton "enum", AR_E, ENUM,
8959813Slinton "for", AR_RW, FOR,
8969813Slinton "float", AR_TY, FLOAT,
8979813Slinton "fortran", AR_CL, FORTRAN,
8989813Slinton "goto", AR_RW, GOTO,
8999813Slinton "if", AR_RW, IF,
9009813Slinton "int", AR_TY, INT,
9019813Slinton "long", AR_TY, LONG,
9029813Slinton "return", AR_RW, RETURN,
9039813Slinton "register", AR_CL, REGISTER,
9049813Slinton "switch", AR_RW, SWITCH,
9059813Slinton "struct", AR_S, 0,
9069813Slinton "sizeof", AR_RW, SIZEOF,
9079813Slinton "short", AR_TY, SHORT,
9089813Slinton "static", AR_CL, STATIC,
9099813Slinton "typedef", AR_CL, TYPEDEF,
9109813Slinton "unsigned", AR_TY, UNSIGNED,
9119813Slinton "union", AR_U, 0,
9129813Slinton "void", AR_TY, UNDEF, /* tymerge adds FTN */
9139813Slinton "while", AR_RW, WHILE,
9149813Slinton "", 0, 0, /* to stop the search */
9159813Slinton };
9169813Slinton
lxres()9179813Slinton lxres() {
9189813Slinton /* check to see of yytext is reserved; if so,
9199813Slinton /* do the appropriate action and return */
9209813Slinton /* otherwise, return -1 */
9219813Slinton
9229813Slinton register c, ch;
9239813Slinton register struct lxrdope *p;
9249813Slinton
9259813Slinton ch = yytext[0];
9269813Slinton
9279813Slinton if( !islower(ch) ) return( -1 );
9289813Slinton
9299813Slinton switch( ch ){
9309813Slinton
9319813Slinton case 'a':
9329813Slinton c=0; break;
9339813Slinton case 'b':
9349813Slinton c=2; break;
9359813Slinton case 'c':
9369813Slinton c=3; break;
9379813Slinton case 'd':
9389813Slinton c=6; break;
9399813Slinton case 'e':
9409813Slinton c=9; break;
9419813Slinton case 'f':
9429813Slinton c=12; break;
9439813Slinton case 'g':
9449813Slinton c=15; break;
9459813Slinton case 'i':
9469813Slinton c=16; break;
9479813Slinton case 'l':
9489813Slinton c=18; break;
9499813Slinton case 'r':
9509813Slinton c=19; break;
9519813Slinton case 's':
9529813Slinton c=21; break;
9539813Slinton case 't':
9549813Slinton c=26; break;
9559813Slinton case 'u':
9569813Slinton c=27; break;
9579813Slinton case 'v':
9589813Slinton c=29; break;
9599813Slinton case 'w':
9609813Slinton c=30; break;
9619813Slinton
9629813Slinton default:
9639813Slinton return( -1 );
9649813Slinton }
9659813Slinton
9669813Slinton for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
9679813Slinton if( !strcmp( yytext, p->lxrch ) ){ /* match */
9689813Slinton switch( p->lxract ){
9699813Slinton
9709813Slinton case AR_TY:
9719813Slinton /* type word */
9729813Slinton stwart = instruct;
9739813Slinton yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
9749813Slinton return( TYPE );
9759813Slinton
9769813Slinton case AR_RW:
9779813Slinton /* ordinary reserved word */
9789813Slinton return( yylval.intval = p->lxrval );
9799813Slinton
9809813Slinton case AR_CL:
9819813Slinton /* class word */
9829813Slinton yylval.intval = p->lxrval;
9839813Slinton return( CLASS );
9849813Slinton
9859813Slinton case AR_S:
9869813Slinton /* struct */
9879813Slinton stwart = INSTRUCT|SEENAME|TAGNAME;
9889813Slinton yylval.intval = INSTRUCT;
9899813Slinton return( STRUCT );
9909813Slinton
9919813Slinton case AR_U:
9929813Slinton /* union */
9939813Slinton stwart = INUNION|SEENAME|TAGNAME;
9949813Slinton yylval.intval = INUNION;
9959813Slinton return( STRUCT );
9969813Slinton
9979813Slinton case AR_E:
9989813Slinton /* enums */
9999813Slinton stwart = SEENAME|TAGNAME;
10009813Slinton return( yylval.intval = ENUM );
10019813Slinton
10029813Slinton case AR_A:
10039813Slinton /* asm */
10049813Slinton asm_esc = 1; /* warn the world! */
10059813Slinton lxget( ' ', LEXWS );
10069813Slinton if( getchar() != '(' ) goto badasm;
10079813Slinton lxget( ' ', LEXWS );
10089813Slinton if( getchar() != '"' ) goto badasm;
10099813Slinton # ifndef ONEPASS
10109813Slinton # ifndef LINT
10119813Slinton putchar(')');
10129813Slinton # endif
10139813Slinton # endif
10149813Slinton while( (c=getchar()) != '"' ){
10159813Slinton if( c=='\n' || c==EOF ) goto badasm;
10169813Slinton # ifndef LINT
10179813Slinton putchar(c);
10189813Slinton # endif
10199813Slinton }
10209813Slinton lxget( ' ', LEXWS );
10219813Slinton if( getchar() != ')' ) goto badasm;
10229813Slinton # ifndef LINT
10239813Slinton putchar('\n');
10249813Slinton # endif
10259813Slinton return( 0 );
10269813Slinton
10279813Slinton badasm:
10289813Slinton uerror( "bad asm construction" );
10299813Slinton return( 0 );
10309813Slinton
10319813Slinton default:
10329813Slinton cerror( "bad AR_?? action" );
10339813Slinton }
10349813Slinton }
10359813Slinton }
10369813Slinton return( -1 );
10379813Slinton }
10389813Slinton
10399813Slinton extern int labelno;
10409813Slinton
lxtitle()10419813Slinton lxtitle(){
10429813Slinton /* called after a newline; set linenumber and file name */
10439813Slinton
10449813Slinton register c, val;
10459813Slinton register char *cp, *cq;
10469813Slinton
10479813Slinton for(;;){ /* might be several such lines in a row */
10489813Slinton if( (c=getchar()) != '#' ){
10499813Slinton if( c != EOF ) ungetc(c,stdin);
10509813Slinton #ifndef LINT
10519813Slinton if ( lastloc != PROG) return;
10529813Slinton cp = ftitle;
10539813Slinton cq = ititle;
10549813Slinton while ( *cp ) if (*cp++ != *cq++) return;
10559813Slinton if ( *cq ) return;
105632830Sdonn if( nerrors == 0 ) psline();
10579813Slinton #endif
10589813Slinton return;
10599813Slinton }
10609813Slinton
10619813Slinton lxget( ' ', LEXWS );
106232832Sdonn c = getchar();
106332832Sdonn if( c == 'i' ){
106432832Sdonn /* #ident -- currently a no-op */
106532832Sdonn lxget( c, LEXLET );
106632832Sdonn if( strcmp( yytext, "ident" ) )
106732832Sdonn werror( "%s: undefined control", yytext );
106832832Sdonn while( (c = getchar()) != '\n' && c != EOF )
106932832Sdonn ;
107032832Sdonn continue;
107132832Sdonn }
107232832Sdonn if( c == 'p' ){
107332832Sdonn /* #pragma -- special instructions */
107432832Sdonn lxget( c, LEXLET );
107532832Sdonn if( strcmp( yytext, "pragma" ) ) {
107632832Sdonn werror( "%s: undefined control", yytext );
107732832Sdonn while( (c = getchar()) != '\n' && c != EOF )
107832832Sdonn ;
107932832Sdonn continue;
108032832Sdonn }
108132832Sdonn lxget( ' ' , LEXWS );
108232832Sdonn switch( c = getchar() ){
108332832Sdonn # ifdef LINT
108432832Sdonn case 'V':
108532832Sdonn lxget( c, LEXLET|LEXDIG );
108632832Sdonn {
108732832Sdonn extern int vaflag;
108832832Sdonn int i;
108932832Sdonn i = yytext[7]?yytext[7]-'0':0;
109032832Sdonn yytext[7] = '\0';
109132832Sdonn if( strcmp( yytext, "VARARGS" ) ) break;
109232832Sdonn vaflag = i;
109332832Sdonn break;
109432832Sdonn }
109532832Sdonn case 'L':
109632832Sdonn lxget( c, LEXLET );
109732832Sdonn if( strcmp( yytext, "LINTLIBRARY" ) ) break;
109832832Sdonn {
109932832Sdonn extern int libflag;
110032832Sdonn libflag = 1;
110132832Sdonn }
110232832Sdonn break;
110332832Sdonn
110432832Sdonn case 'A':
110532832Sdonn lxget( c, LEXLET );
110632832Sdonn if( strcmp( yytext, "ARGSUSED" ) ) break;
110732832Sdonn {
110832832Sdonn extern int argflag, vflag;
110932832Sdonn argflag = 1;
111032832Sdonn vflag = 0;
111132832Sdonn }
111232832Sdonn break;
111332832Sdonn
111432832Sdonn case 'N':
111532832Sdonn lxget( c, LEXLET );
111632832Sdonn if( strcmp( yytext, "NOTREACHED" ) ) break;
111732832Sdonn reached = 0;
111832832Sdonn break;
111932832Sdonn #endif
112032832Sdonn
112132832Sdonn case '\n':
112232832Sdonn case EOF:
112332832Sdonn continue;
112432832Sdonn }
112532832Sdonn while( (c = getchar()) != '\n' && c != EOF )
112632832Sdonn ;
112732832Sdonn continue;
112832832Sdonn }
112932833Sdonn if( c == 'l' ){
113032833Sdonn /* #line -- just like # */
113132833Sdonn lxget( c, LEXLET );
113232833Sdonn if( strcmp( yytext, "line" ) ){
113332833Sdonn werror( "%s: undefined control", yytext );
113432833Sdonn while( (c = getchar()) != '\n' && c != EOF )
113532833Sdonn ;
113632833Sdonn continue;
113732833Sdonn }
113832833Sdonn lxget( ' ', LEXWS );
113932833Sdonn c = getchar();
114032833Sdonn }
114132832Sdonn if( !isdigit(c) ){
114232832Sdonn if( isalpha(c) ){
114332832Sdonn lxget( c, LEXLET );
114432832Sdonn werror( "%s: undefined control", yytext );
114532832Sdonn }
114632833Sdonn while( c != '\n' && c != EOF )
114732833Sdonn c = getchar();
114832832Sdonn continue;
114932832Sdonn }
115032832Sdonn
11519813Slinton val = 0;
115232832Sdonn do {
11539813Slinton val = val*10+ c - '0';
11549813Slinton }
115532832Sdonn while( isdigit( c = getchar() ) );
115632832Sdonn
115717748Sralph if( c == EOF )
115817748Sralph continue;
11599813Slinton ungetc( c, stdin );
11609813Slinton lineno = val;
11619813Slinton lxget( ' ', LEXWS );
116217748Sralph if( (c=getchar()) != '\n' && c != EOF ){
116317748Sralph for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
11649813Slinton *cp = c;
11659813Slinton }
11669813Slinton *cp = '\0';
11679813Slinton #ifndef LINT
11689813Slinton if (ititle[0] == '\0') {
11699813Slinton cp = ftitle;
11709813Slinton cq = ititle;
11719813Slinton while ( *cp )
11729813Slinton *cq++ = *cp++;
11739813Slinton *cq = '\0';
11749813Slinton *--cq = '\0';
11759813Slinton #ifndef FLEXNAMES
11769813Slinton for ( cp = ititle+1; *(cp-1); cp += 8 ) {
11779813Slinton pstab(cp, N_SO);
11789813Slinton if (gdebug) printf("0,0,LL%d\n", labelno);
11799813Slinton }
11809813Slinton #else
11819813Slinton pstab(ititle+1, N_SO);
11829813Slinton if (gdebug) printf("0,0,LL%d\n", labelno);
11839813Slinton #endif
11849813Slinton
11859813Slinton *cq = '"';
11869813Slinton printf("LL%d:\n", labelno++);
11879813Slinton }
11889813Slinton #endif
11899813Slinton }
11909813Slinton }
11919813Slinton }
11929813Slinton
11939813Slinton #ifdef FLEXNAMES
11949813Slinton #define NSAVETAB 4096
11959813Slinton char *savetab;
119632836Sdonn unsigned saveleft;
119732836Sdonn char *malloc();
119832836Sdonn char *calloc();
119932836Sdonn char *strncpy();
12009813Slinton
12019813Slinton char *
savestr(cp)12029813Slinton savestr(cp)
12039813Slinton register char *cp;
12049813Slinton {
12059813Slinton register int len;
12069813Slinton
12079813Slinton len = strlen(cp) + 1;
12089813Slinton if (len > saveleft) {
12099813Slinton saveleft = NSAVETAB;
12109813Slinton if (len > saveleft)
12119813Slinton saveleft = len;
121232836Sdonn savetab = malloc(saveleft);
12139813Slinton if (savetab == 0)
12149813Slinton cerror("Ran out of memory (savestr)");
12159813Slinton }
121632836Sdonn (void) strncpy(savetab, cp, len);
12179813Slinton cp = savetab;
12189813Slinton savetab += len;
12199813Slinton saveleft -= len;
12209813Slinton return (cp);
12219813Slinton }
12229813Slinton
12239813Slinton /*
12249813Slinton * The definition for the segmented hash tables.
12259813Slinton */
12269813Slinton #define MAXHASH 20
12279813Slinton #define HASHINC 1013
12289813Slinton struct ht {
12299813Slinton char **ht_low;
12309813Slinton char **ht_high;
12319813Slinton int ht_used;
12329813Slinton } htab[MAXHASH];
12339813Slinton
12349813Slinton char *
hash(s)12359813Slinton hash(s)
12369813Slinton char *s;
12379813Slinton {
12389813Slinton register char **h;
12399813Slinton register i;
12409813Slinton register char *cp;
12419813Slinton struct ht *htp;
12429813Slinton int sh;
12439813Slinton
12449813Slinton /*
12459813Slinton * The hash function is a modular hash of
12469813Slinton * the sum of the characters with the sum
12479813Slinton * doubled before each successive character
12489813Slinton * is added.
12499813Slinton */
12509813Slinton cp = s;
12519813Slinton i = 0;
12529813Slinton while (*cp)
12539813Slinton i = i*2 + *cp++;
12549813Slinton sh = (i&077777) % HASHINC;
12559813Slinton cp = s;
12569813Slinton /*
12579813Slinton * There are as many as MAXHASH active
12589813Slinton * hash tables at any given point in time.
12599813Slinton * The search starts with the first table
12609813Slinton * and continues through the active tables
12619813Slinton * as necessary.
12629813Slinton */
12639813Slinton for (htp = htab; htp < &htab[MAXHASH]; htp++) {
12649813Slinton if (htp->ht_low == 0) {
12659813Slinton register char **hp =
12669813Slinton (char **) calloc(sizeof (char **), HASHINC);
12679813Slinton if (hp == 0)
12689813Slinton cerror("ran out of memory (hash)");
12699813Slinton htp->ht_low = hp;
12709813Slinton htp->ht_high = htp->ht_low + HASHINC;
12719813Slinton }
12729813Slinton h = htp->ht_low + sh;
12739813Slinton /*
12749813Slinton * quadratic rehash increment
12759813Slinton * starts at 1 and incremented
12769813Slinton * by two each rehash.
12779813Slinton */
12789813Slinton i = 1;
12799813Slinton do {
12809813Slinton if (*h == 0) {
12819813Slinton if (htp->ht_used > (HASHINC * 3)/4)
12829813Slinton break;
12839813Slinton htp->ht_used++;
12849813Slinton *h = savestr(cp);
12859813Slinton return (*h);
12869813Slinton }
12879813Slinton if (**h == *cp && strcmp(*h, cp) == 0)
12889813Slinton return (*h);
12899813Slinton h += i;
12909813Slinton i += 2;
12919813Slinton if (h >= htp->ht_high)
12929813Slinton h -= HASHINC;
12939813Slinton } while (i < HASHINC);
12949813Slinton }
12959813Slinton cerror("ran out of hash tables");
129632836Sdonn /*NOTREACHED*/
12979813Slinton }
12989813Slinton #endif
1299