117748Sralph #ifndef lint 2*32839Sdonn static char *sccsid ="@(#)scan.c 2.15 (Berkeley) 12/10/87"; 317748Sralph #endif lint 417748Sralph 518395Sralph # include "pass1.h" 69813Slinton # include <a.out.h> 79813Slinton # include <stab.h> 89813Slinton # include <ctype.h> 924407Smckusick # include <signal.h> 1024407Smckusick 119813Slinton /* temporarily */ 129813Slinton 139813Slinton int asm_esc = 0; /* asm escaped used in file */ 149813Slinton /* lexical actions */ 159813Slinton 169813Slinton # define A_ERR 0 /* illegal character */ 179813Slinton # define A_LET 1 /* saw a letter */ 189813Slinton # define A_DIG 2 /* saw a digit */ 199813Slinton # define A_1C 3 /* return a single character */ 209813Slinton # define A_STR 4 /* string */ 219813Slinton # define A_CC 5 /* character constant */ 229813Slinton # define A_BCD 6 /* GCOS BCD constant */ 239813Slinton # define A_SL 7 /* saw a / */ 249813Slinton # define A_DOT 8 /* saw a . */ 259813Slinton # define A_PL 9 /* + */ 269813Slinton # define A_MI 10 /* - */ 279813Slinton # define A_EQ 11 /* = */ 289813Slinton # define A_NOT 12 /* ! */ 299813Slinton # define A_LT 13 /* < */ 309813Slinton # define A_GT 14 /* > */ 319813Slinton # define A_AND 16 /* & */ 329813Slinton # define A_OR 17 /* | */ 339813Slinton # define A_WS 18 /* whitespace (not \n) */ 349813Slinton # define A_NL 19 /* \n */ 359813Slinton 369813Slinton /* character classes */ 379813Slinton 389813Slinton # define LEXLET 01 399813Slinton # define LEXDIG 02 409813Slinton # define LEXOCT 04 419813Slinton # define LEXHEX 010 429813Slinton # define LEXWS 020 439813Slinton # define LEXDOT 040 449813Slinton 459813Slinton /* reserved word actions */ 469813Slinton 479813Slinton # define AR_TY 0 /* type word */ 489813Slinton # define AR_RW 1 /* simple reserved word */ 499813Slinton # define AR_CL 2 /* storage class word */ 509813Slinton # define AR_S 3 /* struct */ 519813Slinton # define AR_U 4 /* union */ 529813Slinton # define AR_E 5 /* enum */ 539813Slinton # define AR_A 6 /* asm */ 549813Slinton 559813Slinton /* text buffer */ 569813Slinton #ifndef FLEXNAMES 579813Slinton # define LXTSZ 100 589813Slinton #else 599813Slinton #define LXTSZ BUFSIZ 609813Slinton #endif 619813Slinton char yytext[LXTSZ]; 629813Slinton char * lxgcp; 639813Slinton 649813Slinton extern int proflg; 659813Slinton extern int gdebug; 6624407Smckusick extern int fpe(); 6724407Smckusick struct sigvec fpe_sigvec; 689905Ssam int oldway; /* allocate storage so lint will compile as well */ 699813Slinton #ifndef LINT 709813Slinton extern int lastloc; 719813Slinton #endif 729813Slinton 739813Slinton unsigned caloff(); 749813Slinton /* ARGSUSED */ 759813Slinton mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */ 769813Slinton 779813Slinton register i; 789813Slinton register char *cp; 7917748Sralph extern int idebug, bdebug, tdebug, edebug; 8017748Sralph extern int ddebug, xdebug, gdebug, adebug; 819813Slinton extern unsigned int offsz; 829813Slinton int fdef = 0; 8332835Sdonn extern char *release; 849813Slinton 859813Slinton offsz = caloff(); 869813Slinton for( i=1; i<argc; ++i ){ 879813Slinton if( *(cp=argv[i]) == '-' && *++cp == 'X' ){ 889813Slinton while( *++cp ){ 899813Slinton switch( *cp ){ 909813Slinton 919813Slinton case 'r': 929813Slinton fprintf( stderr, "Release: %s\n", 939813Slinton release ); 949813Slinton break; 959813Slinton 969813Slinton case 'd': 979813Slinton ++ddebug; 989813Slinton break; 999813Slinton case 'i': 1009813Slinton ++idebug; 1019813Slinton break; 1029813Slinton case 'b': 1039813Slinton ++bdebug; 1049813Slinton break; 1059813Slinton case 't': 1069813Slinton ++tdebug; 1079813Slinton break; 1089813Slinton case 'e': 1099813Slinton ++edebug; 1109813Slinton break; 1119813Slinton case 'x': 1129813Slinton ++xdebug; 1139813Slinton break; 1149813Slinton case 'P': /* profiling */ 1159813Slinton ++proflg; 1169813Slinton break; 1179813Slinton case 'g': 1189813Slinton ++gdebug; 1199813Slinton break; 12017748Sralph case 'a': 12117748Sralph ++adebug; 12217748Sralph break; 1239816Slinton case 'G': 1249816Slinton ++gdebug; 1259816Slinton oldway = 1; 1269816Slinton break; 1279813Slinton } 1289813Slinton } 1299813Slinton } 1309813Slinton else { 1319813Slinton if( *(argv[i]) != '-' ) switch( fdef++ ) { 1329813Slinton case 0: 1339813Slinton case 1: 1349813Slinton if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) { 1359813Slinton fprintf(stderr, "ccom:can't open %s\n", argv[i]); 1369813Slinton exit(1); 1379813Slinton } 1389813Slinton break; 1399813Slinton 1409813Slinton default: 1419813Slinton ; 1429813Slinton } 1439813Slinton } 1449813Slinton } 1459813Slinton 1469813Slinton # ifdef ONEPASS 14732836Sdonn (void) p2init( argc, argv ); 1489813Slinton # endif 1499813Slinton 1509813Slinton for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL; 1519813Slinton 15217601Sralph lineno = 1; 15317601Sralph 1549813Slinton lxinit(); 1559813Slinton tinit(); 1569813Slinton mkdope(); 1579813Slinton 1589813Slinton /* dimension table initialization */ 1599813Slinton 1609813Slinton dimtab[NULL] = 0; 1619813Slinton dimtab[CHAR] = SZCHAR; 1629813Slinton dimtab[INT] = SZINT; 1639813Slinton dimtab[FLOAT] = SZFLOAT; 1649813Slinton dimtab[DOUBLE] = SZDOUBLE; 1659813Slinton dimtab[LONG] = SZLONG; 1669813Slinton dimtab[SHORT] = SZSHORT; 1679813Slinton dimtab[UCHAR] = SZCHAR; 1689813Slinton dimtab[USHORT] = SZSHORT; 1699813Slinton dimtab[UNSIGNED] = SZINT; 1709813Slinton dimtab[ULONG] = SZLONG; 1719813Slinton /* starts past any of the above */ 1729813Slinton curdim = 16; 1739813Slinton reached = 1; 1749813Slinton 17524407Smckusick fpe_sigvec.sv_handler = fpe; 17624407Smckusick (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL); 17724407Smckusick 17832836Sdonn (void) yyparse(); 1799813Slinton yyaccpt(); 1809813Slinton 1819813Slinton ejobcode( nerrors ? 1 : 0 ); 1829813Slinton return(nerrors?1:0); 1839813Slinton 1849813Slinton } 1859813Slinton 1869813Slinton # ifdef ibm 1879813Slinton 1889813Slinton # define CSMASK 0377 1899813Slinton # define CSSZ 256 1909813Slinton 1919813Slinton # else 1929813Slinton 1939813Slinton # define CSMASK 0177 1949813Slinton # define CSSZ 128 1959813Slinton 1969813Slinton # endif 1979813Slinton 1989813Slinton short lxmask[CSSZ+1]; 1999813Slinton 2009813Slinton lxenter( s, m ) register char *s; register short m; { 2019813Slinton /* enter a mask into lxmask */ 2029813Slinton register c; 2039813Slinton 2049813Slinton while( c= *s++ ) lxmask[c+1] |= m; 2059813Slinton 2069813Slinton } 2079813Slinton 2089813Slinton 2099813Slinton # define lxget(c,m) (lxgcp=yytext,lxmore(c,m)) 2109813Slinton 2119813Slinton lxmore( c, m ) register c, m; { 2129813Slinton register char *cp; 2139813Slinton 2149813Slinton *(cp = lxgcp) = c; 2159813Slinton while( c=getchar(), lxmask[c+1]&m ){ 2169813Slinton if( cp < &yytext[LXTSZ-1] ){ 2179813Slinton *++cp = c; 2189813Slinton } 2199813Slinton } 2209813Slinton ungetc(c,stdin); 2219813Slinton *(lxgcp = cp+1) = '\0'; 2229813Slinton } 2239813Slinton 2249813Slinton struct lxdope { 2259813Slinton short lxch; /* the character */ 2269813Slinton short lxact; /* the action to be performed */ 2279813Slinton short lxtok; /* the token number to be returned */ 2289813Slinton short lxval; /* the value to be returned */ 2299813Slinton } lxdope[] = { 2309813Slinton 2319813Slinton '@', A_ERR, 0, 0, /* illegal characters go here... */ 2329813Slinton '_', A_LET, 0, 0, /* letters point here */ 2339813Slinton '0', A_DIG, 0, 0, /* digits point here */ 2349813Slinton ' ', A_WS, 0, 0, /* whitespace goes here */ 2359813Slinton '\n', A_NL, 0, 0, 2369813Slinton '"', A_STR, 0, 0, /* character string */ 2379813Slinton '\'', A_CC, 0, 0, /* character constant */ 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 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 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 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 5109813Slinton yylex(){ 511*32839Sdonn double atof(); 512*32839Sdonn 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 } 631*32839Sdonn dcon = atof( yytext ); 632*32839Sdonn if( (lxchar = getchar()) == 'F' || lxchar == 'f' ){ 633*32839Sdonn fcon = dcon; 634*32839Sdonn return( FCON ); 635*32839Sdonn } 636*32839Sdonn else ungetc( lxchar ,stdin); 637*32839Sdonn 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 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 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 * 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 * 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