17990Srrh 27990Srrh #ifndef lint 3*11550Ssam static char sccsid[] = "@(#)lpass2.c 1.2 (Berkeley) 03/12/83"; 47990Srrh #endif lint 57990Srrh 67990Srrh # include "manifest" 77990Srrh # include "lmanifest" 87990Srrh 97990Srrh # define USED 01 107990Srrh # define VUSED 02 117990Srrh # define EUSED 04 127990Srrh # define RVAL 010 137990Srrh # define VARARGS 0100 147990Srrh 157990Srrh # define NSZ 2048 167990Srrh # define TYSZ 3500 17*11550Ssam # define FSZ 500 187990Srrh # define NTY 50 197990Srrh 207990Srrh typedef struct sty STYPE; 217990Srrh struct sty { ATYPE t; STYPE *next; }; 227990Srrh 237990Srrh typedef struct sym { 247990Srrh #ifndef FLEXNAMES 257990Srrh char name[LCHNM]; 267990Srrh #else 277990Srrh char *name; 287990Srrh #endif 297990Srrh short nargs; 307990Srrh int decflag; 317990Srrh int fline; 327990Srrh STYPE symty; 337990Srrh int fno; 347990Srrh int use; 357990Srrh } STAB; 367990Srrh 377990Srrh STAB stab[NSZ]; 387990Srrh STAB *find(); 397990Srrh 407990Srrh STYPE tary[TYSZ]; 417990Srrh STYPE *tget(); 427990Srrh 437990Srrh #ifndef FLEXNAMES 447990Srrh char fnm[FSZ][LFNM]; 457990Srrh #else 467990Srrh char *fnm[FSZ]; 477990Srrh #endif 487990Srrh 497990Srrh #ifdef FLEXNAMES 507990Srrh char *getstr(); 517990Srrh #endif 527990Srrh 537990Srrh int tfree; /* used to allocate types */ 547990Srrh int ffree; /* used to save filenames */ 557990Srrh 567990Srrh struct ty atyp[NTY]; 577990Srrh /* r is where all the input ends up */ 587990Srrh union rec r; 597990Srrh 607990Srrh int hflag = 0; 617990Srrh int pflag = 0; 627990Srrh int xflag = 0; 637990Srrh int uflag = 1; 647990Srrh int ddddd = 0; 657990Srrh 667990Srrh int cfno; /* current file number */ 677990Srrh 687990Srrh main( argc, argv ) char *argv[]; { 697990Srrh register char *p; 707990Srrh 717990Srrh /* first argument is intermediate file */ 727990Srrh /* second argument is - options */ 737990Srrh 747990Srrh for( ; argc>2 && argv[argc-1][0] == '-' ; --argc ){ 757990Srrh for( p=argv[argc-1]; *p; ++p ){ 767990Srrh switch( *p ){ 777990Srrh 787990Srrh case 'h': 797990Srrh hflag = 1; 807990Srrh break; 817990Srrh 827990Srrh case 'p': 837990Srrh pflag = 1; 847990Srrh break; 857990Srrh 867990Srrh case 'x': 877990Srrh xflag = 1; 887990Srrh break; 897990Srrh 907990Srrh case 'X': 917990Srrh ddddd = 1; 927990Srrh break; 937990Srrh 947990Srrh case 'u': 957990Srrh uflag = 0; 967990Srrh break; 977990Srrh 987990Srrh } 997990Srrh } 1007990Srrh } 1017990Srrh 1027990Srrh if( argc < 2 || !freopen( argv[1], "r", stdin ) ){ 1037990Srrh error( "cannot open intermediate file" ); 1047990Srrh exit( 1 ); 1057990Srrh } 1067990Srrh 1077990Srrh mloop( LDI|LIB ); 1087990Srrh rewind( stdin ); 1097990Srrh mloop( LDC|LDX ); 1107990Srrh rewind( stdin ); 1117990Srrh mloop( LRV|LUV|LUE|LUM ); 1127990Srrh cleanup(); 1137990Srrh return(0); 1147990Srrh } 1157990Srrh 1167990Srrh mloop( m ){ 1177990Srrh /* do the main loop */ 1187990Srrh register STAB *q; 1197990Srrh 1207990Srrh while( lread(m) ){ 1217990Srrh q = find(); 1227990Srrh if( q->decflag ) chkcompat(q); 1237990Srrh else setuse(q); 1247990Srrh } 1257990Srrh } 1267990Srrh 1277990Srrh lread(m){ /* read a line into r.l */ 1287990Srrh 1297990Srrh register n; 1307990Srrh 1317990Srrh for(;;) { 1327990Srrh if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0); 1337990Srrh if( r.l.decflag & LFN ){ 1347990Srrh /* new filename */ 1357990Srrh #ifdef FLEXNAMES 1367990Srrh r.f.fn = getstr(); 1377990Srrh #endif 1387990Srrh setfno( r.f.fn ); 1397990Srrh continue; 1407990Srrh } 1417990Srrh #ifdef FLEXNAMES 1427990Srrh r.l.name = getstr(); 1437990Srrh #endif 1447990Srrh 1457990Srrh n = r.l.nargs; 1467990Srrh if( n<0 ) n = -n; 1477990Srrh if( n ){ 1487990Srrh if( n>=NTY ) error( "more than %d args?", n ); 1497990Srrh fread( (char *)atyp, sizeof(ATYPE), n, stdin ); 1507990Srrh } 1517990Srrh if( ( r.l.decflag & m ) ) return( 1 ); 1527990Srrh } 1537990Srrh } 1547990Srrh 1557990Srrh setfno( s ) char *s; { 1567990Srrh /* look up current file names */ 1577990Srrh /* first, strip backwards to the beginning or to the first / */ 1587990Srrh int i; 1597990Srrh 1607990Srrh /* now look up s */ 1617990Srrh for( i=0; i<ffree; ++i ){ 1627990Srrh #ifndef FLEXNAMES 1637990Srrh if( !strncmp( s, fnm[i], LFNM ) ){ 1647990Srrh #else 1657990Srrh if (fnm[i] == s){ 1667990Srrh #endif 1677990Srrh cfno = i; 1687990Srrh return; 1697990Srrh } 1707990Srrh } 1717990Srrh /* make a new entry */ 1727990Srrh if( ffree >= FSZ ) error( "more than %d files", FSZ ); 1737990Srrh #ifndef FLEXNAMES 1747990Srrh strncpy( fnm[ffree], s, LFNM ); 1757990Srrh #else 1767990Srrh fnm[ffree] = s; 1777990Srrh #endif 1787990Srrh cfno = ffree++; 1797990Srrh } 1807990Srrh 1817990Srrh /* VARARGS */ 1827990Srrh error( s, a ) char *s; { 1837990Srrh 1847990Srrh #ifndef FLEXNAMES 1857990Srrh fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] ); 1867990Srrh #else 1877990Srrh fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] ); 1887990Srrh #endif 1897990Srrh fprintf( stderr, s, a ); 1907990Srrh fprintf( stderr, "\n" ); 1917990Srrh exit(1); 1927990Srrh } 1937990Srrh 1947990Srrh STAB * 1957990Srrh find(){ 1967990Srrh /* for this to work, NSZ should be a power of 2 */ 1977990Srrh register h=0; 1987990Srrh #ifndef FLEXNAMES 1997990Srrh { register char *p, *q; 2007990Srrh for( h=0,p=r.l.name,q=p+LCHNM; *p&&p<q; ++p) { 2017990Srrh h = (h<<1)+ *p; 2027990Srrh if( h>=NSZ ){ 2037990Srrh h = (h+1)&(NSZ-1); 2047990Srrh } 2057990Srrh } 2067990Srrh } 2077990Srrh #else 2087990Srrh h = ((int)r.l.name)%NSZ; 2097990Srrh #endif 2107990Srrh { register STAB *p, *q; 2117990Srrh for( p=q= &stab[h]; q->decflag; ){ 2127990Srrh /* this call to strncmp should be taken out... */ 2137990Srrh #ifndef FLEXNAMES 2147990Srrh if( !strncmp( r.l.name, q->name, LCHNM)) return(q); 2157990Srrh #else 2167990Srrh if (r.l.name == q->name) return (q); 2177990Srrh #endif 2187990Srrh if( ++q >= &stab[NSZ] ) q = stab; 2197990Srrh if( q == p ) error( "too many names defined" ); 2207990Srrh } 2217990Srrh #ifndef FLEXNAMES 2227990Srrh strncpy( q->name, r.l.name, LCHNM ); 2237990Srrh #else 2247990Srrh q->name = r.l.name; 2257990Srrh #endif 2267990Srrh return( q ); 2277990Srrh } 2287990Srrh } 2297990Srrh 2307990Srrh STYPE * 2317990Srrh tget(){ 2327990Srrh if( tfree >= TYSZ ){ 2337990Srrh error( "too many types needed" ); 2347990Srrh } 2357990Srrh return( &tary[tfree++] ); 2367990Srrh } 2377990Srrh 2387990Srrh chkcompat(q) STAB *q; { 2397990Srrh /* are the types, etc. in r.l and q compatible */ 2407990Srrh register int i; 2417990Srrh STYPE *qq; 2427990Srrh 2437990Srrh setuse(q); 2447990Srrh 2457990Srrh /* argument check */ 2467990Srrh 2477990Srrh if( q->decflag & (LDI|LIB|LUV|LUE) ){ 2487990Srrh if( r.l.decflag & (LUV|LIB|LUE) ){ 2497990Srrh if( q->nargs != r.l.nargs ){ 2507990Srrh if( !(q->use&VARARGS) ){ 2517990Srrh #ifndef FLEXNAMES 2527990Srrh printf( "%.8s: variable # of args.", q->name ); 2537990Srrh #else 2547990Srrh printf( "%s: variable # of args.", q->name ); 2557990Srrh #endif 2567990Srrh viceversa(q); 2577990Srrh } 2587990Srrh if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs; 2597990Srrh if( !(q->decflag & (LDI|LIB) ) ) { 2607990Srrh q->nargs = r.l.nargs; 2617990Srrh q->use |= VARARGS; 2627990Srrh } 2637990Srrh } 2647990Srrh for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){ 2657990Srrh if( chktype( &qq->t, &atyp[i] ) ){ 2667990Srrh #ifndef FLEXNAMES 2677990Srrh printf( "%.8s, arg. %d used inconsistently", 2687990Srrh #else 2697990Srrh printf( "%s, arg. %d used inconsistently", 2707990Srrh #endif 2717990Srrh q->name, i+1 ); 2727990Srrh viceversa(q); 2737990Srrh } 2747990Srrh } 2757990Srrh } 2767990Srrh } 2777990Srrh 2787990Srrh if( (q->decflag&(LDI|LIB|LUV)) && r.l.decflag==LUV ){ 2797990Srrh if( chktype( &r.l.type, &q->symty.t ) ){ 2807990Srrh #ifndef FLEXNAMES 2817990Srrh printf( "%.8s value used inconsistently", q->name ); 2827990Srrh #else 2837990Srrh printf( "%s value used inconsistently", q->name ); 2847990Srrh #endif 2857990Srrh viceversa(q); 2867990Srrh } 2877990Srrh } 2887990Srrh 2897990Srrh /* check for multiple declaration */ 2907990Srrh 2917990Srrh if( (q->decflag&LDI) && (r.l.decflag&(LDI|LIB)) ){ 2927990Srrh #ifndef FLEXNAMES 2937990Srrh printf( "%.8s multiply declared", q->name ); 2947990Srrh #else 2957990Srrh printf( "%s multiply declared", q->name ); 2967990Srrh #endif 2977990Srrh viceversa(q); 2987990Srrh } 2997990Srrh 3007990Srrh /* do a bit of checking of definitions and uses... */ 3017990Srrh 3027990Srrh if( (q->decflag & (LDI|LIB|LDX|LDC|LUM)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){ 3037990Srrh #ifndef FLEXNAMES 3047990Srrh printf( "%.8s value declared inconsistently", q->name ); 3057990Srrh #else 3067990Srrh printf( "%s value declared inconsistently", q->name ); 3077990Srrh #endif 3087990Srrh viceversa(q); 3097990Srrh } 3107990Srrh 3117990Srrh /* better not call functions which are declared to be structure or union returning */ 3127990Srrh 3137990Srrh if( (q->decflag & (LDI|LIB|LDX|LDC)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){ 3147990Srrh /* only matters if the function returns union or structure */ 3157990Srrh TWORD ty; 3167990Srrh ty = q->symty.t.aty; 3177990Srrh if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){ 3187990Srrh #ifndef FLEXNAMES 3197990Srrh printf( "%.8s function value type must be declared before use", q->name ); 3207990Srrh #else 3217990Srrh printf( "%s function value type must be declared before use", q->name ); 3227990Srrh #endif 3237990Srrh viceversa(q); 3247990Srrh } 3257990Srrh } 3267990Srrh 3277990Srrh if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){ 3287990Srrh /* make the external declaration go away */ 3297990Srrh /* in effect, it was used without being defined */ 3307990Srrh } 3317990Srrh } 3327990Srrh 3337990Srrh viceversa(q) STAB *q; { 3347990Srrh /* print out file comparison */ 3357990Srrh #ifndef FLEXNAMES 3367990Srrh printf( " %.*s(%d) :: %.*s(%d)\n", 3377990Srrh LFNM, fnm[q->fno], q->fline, 3387990Srrh LFNM, fnm[cfno], r.l.fline ); 3397990Srrh #else 3407990Srrh printf( " %s(%d) :: %s(%d)\n", 3417990Srrh fnm[q->fno], q->fline, 3427990Srrh fnm[cfno], r.l.fline ); 3437990Srrh #endif 3447990Srrh } 3457990Srrh 3467990Srrh /* messages for defintion/use */ 3477990Srrh char * 3487990Srrh mess[2][2] ={ 3497990Srrh "", 3507990Srrh #ifndef FLEXNAMES 3517990Srrh "%.8s used( %.*s(%d) ), but not defined\n", 3527990Srrh "%.8s defined( %.*s(%d) ), but never used\n", 3537990Srrh "%.8s declared( %.*s(%d) ), but never used or defined\n" 3547990Srrh #else 3557990Srrh "%s used( %s(%d) ), but not defined\n", 3567990Srrh "%s defined( %s(%d) ), but never used\n", 3577990Srrh "%s declared( %s(%d) ), but never used or defined\n" 3587990Srrh #endif 3597990Srrh }; 3607990Srrh 3617990Srrh lastone(q) STAB *q; { 3627990Srrh 3637990Srrh register nu, nd, uses; 3647990Srrh 3657990Srrh if( ddddd ) pst(q); 3667990Srrh 3677990Srrh nu = nd = 0; 3687990Srrh uses = q->use; 3697990Srrh 3707990Srrh if( !(uses&USED) && q->decflag != LIB ) { 3717990Srrh #ifndef FLEXNAMES 3727990Srrh if( strncmp(q->name,"main",7) ) 3737990Srrh #else 3747990Srrh if (strcmp(q->name, "main")) 3757990Srrh #endif 3767990Srrh nu = 1; 3777990Srrh } 3787990Srrh 3797990Srrh if( !ISFTN(q->symty.t.aty) ){ 3807990Srrh switch( q->decflag ){ 3817990Srrh 3827990Srrh case LIB: 3837990Srrh nu = nd = 0; /* don't complain about uses on libraries */ 3847990Srrh break; 3857990Srrh case LDX: 3867990Srrh if( !xflag ) break; 3877990Srrh case LUV: 3887990Srrh case LUE: 3897990Srrh /* 01/04/80 */ case LUV | LUE: 3907990Srrh case LUM: 3917990Srrh nd = 1; 3927990Srrh } 3937990Srrh } 3947990Srrh if( uflag && ( nu || nd ) ) printf( mess[nu][nd], 3957990Srrh #ifndef FLEXNAMES 3967990Srrh q->name, LFNM, fnm[q->fno], q->fline ); 3977990Srrh #else 3987990Srrh q->name, fnm[q->fno], q->fline ); 3997990Srrh #endif 4007990Srrh 4017990Srrh if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){ 4027990Srrh #ifndef FLEXNAMES 4037990Srrh printf( "%.8s returns value which is %s ignored\n", q->name, 4047990Srrh #else 4057990Srrh printf( "%s returns value which is %s ignored\n", q->name, 4067990Srrh #endif 4077990Srrh uses&VUSED ? "sometimes" : "always" ); 4087990Srrh } 4097990Srrh 4107990Srrh if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB)) ){ 4117990Srrh #ifndef FLEXNAMES 4127990Srrh printf( "%.8s value is used, but none returned\n", q->name ); 4137990Srrh #else 4147990Srrh printf( "%s value is used, but none returned\n", q->name ); 4157990Srrh #endif 4167990Srrh } 4177990Srrh } 4187990Srrh 4197990Srrh cleanup(){ /* call lastone and die gracefully */ 4207990Srrh STAB *q; 4217990Srrh for( q=stab; q< &stab[NSZ]; ++q ){ 4227990Srrh if( q->decflag ) lastone(q); 4237990Srrh } 4247990Srrh exit(0); 4257990Srrh } 4267990Srrh 4277990Srrh setuse(q) STAB *q; { /* check new type to ensure that it is used */ 4287990Srrh 4297990Srrh if( !q->decflag ){ /* new one */ 4307990Srrh q->decflag = r.l.decflag; 4317990Srrh q->symty.t = r.l.type; 4327990Srrh if( r.l.nargs < 0 ){ 4337990Srrh q->nargs = -r.l.nargs; 4347990Srrh q->use = VARARGS; 4357990Srrh } 4367990Srrh else { 4377990Srrh q->nargs = r.l.nargs; 4387990Srrh q->use = 0; 4397990Srrh } 4407990Srrh q->fline = r.l.fline; 4417990Srrh q->fno = cfno; 4427990Srrh if( q->nargs ){ 4437990Srrh int i; 4447990Srrh STYPE *qq; 4457990Srrh for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){ 4467990Srrh qq->next = tget(); 4477990Srrh qq->next->t = atyp[i]; 4487990Srrh } 4497990Srrh } 4507990Srrh } 4517990Srrh 4527990Srrh switch( r.l.decflag ){ 4537990Srrh 4547990Srrh case LRV: 4557990Srrh q->use |= RVAL; 4567990Srrh return; 4577990Srrh case LUV: 4587990Srrh q->use |= VUSED+USED; 4597990Srrh return; 4607990Srrh case LUE: 4617990Srrh q->use |= EUSED+USED; 4627990Srrh return; 4637990Srrh /* 01/04/80 */ case LUV | LUE: 4647990Srrh case LUM: 4657990Srrh q->use |= USED; 4667990Srrh return; 4677990Srrh 4687990Srrh } 4697990Srrh } 4707990Srrh 4717990Srrh chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; { 4727990Srrh TWORD t; 4737990Srrh 4747990Srrh /* check the two type words to see if they are compatible */ 4757990Srrh /* for the moment, enums are turned into ints, and should be checked as such */ 4767990Srrh if( pt1->aty == ENUMTY ) pt1->aty = INT; 4777990Srrh if( pt2->aty == ENUMTY ) pt2->aty = INT; 4787990Srrh 4797990Srrh if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){ 4807990Srrh return( pt1->aty!=pt2->aty || ( 4817990Srrh pt1->extra!=pt2->extra ) ); 4827990Srrh } 4837990Srrh 4847990Srrh if( pt2->extra ){ /* constant passed in */ 4857990Srrh if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 ); 4867990Srrh else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 ); 4877990Srrh } 4887990Srrh else if( pt1->extra ){ /* for symmetry */ 4897990Srrh if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 ); 4907990Srrh else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 ); 4917990Srrh } 4927990Srrh 4937990Srrh return( pt1->aty != pt2->aty ); 4947990Srrh } 4957990Srrh 4967990Srrh struct tb { int m; char * nm }; 4977990Srrh ptb( v, tp ) struct tb *tp; { 4987990Srrh /* print a value from the table */ 4997990Srrh int flag; 5007990Srrh flag = 0; 5017990Srrh for( ; tp->m; ++tp ){ 5027990Srrh if( v&tp->m ){ 5037990Srrh if( flag++ ) putchar( '|' ); 5047990Srrh printf( "%s", tp->nm ); 5057990Srrh } 5067990Srrh } 5077990Srrh } 5087990Srrh 5097990Srrh pst( q ) STAB *q; { 5107990Srrh /* give a debugging output for q */ 5117990Srrh static struct tb dfs[] = { 5127990Srrh LDI, "LDI", 5137990Srrh LIB, "LIB", 5147990Srrh LDC, "LDC", 5157990Srrh LDX, "LDX", 5167990Srrh LRV, "LRV", 5177990Srrh LUV, "LUV", 5187990Srrh LUE, "LUE", 5197990Srrh LUM, "LUM", 5207990Srrh 0, "" }; 5217990Srrh 5227990Srrh static struct tb us[] = { 5237990Srrh USED, "USED", 5247990Srrh VUSED, "VUSED", 5257990Srrh EUSED, "EUSED", 5267990Srrh RVAL, "RVAL", 5277990Srrh VARARGS, "VARARGS", 5287990Srrh 0, 0, 5297990Srrh }; 5307990Srrh 5317990Srrh #ifndef FLEXNAMES 5327990Srrh printf( "%.8s (", q->name ); 5337990Srrh #else 5347990Srrh printf( "%s (", q->name ); 5357990Srrh #endif 5367990Srrh ptb( q->decflag, dfs ); 5377990Srrh printf( "), use= " ); 5387990Srrh ptb( q->use, us ); 5397990Srrh printf( ", line %d, nargs=%d\n", q->fline, q->nargs ); 5407990Srrh } 5417990Srrh 5427990Srrh #ifdef FLEXNAMES 5437990Srrh char * 5447990Srrh getstr() 5457990Srrh { 5467990Srrh char buf[BUFSIZ]; 5477990Srrh register char *cp = buf; 5487990Srrh register int c; 5497990Srrh 5507990Srrh if (feof(stdin) || ferror(stdin)) 5517990Srrh return(""); 5527990Srrh while ((c = getchar()) > 0) 5537990Srrh *cp++ = c; 5547990Srrh if (c < 0) { 5557990Srrh fprintf(stderr, "pass 2 error: intermediate file format error (getstr)"); 5567990Srrh exit(1); 5577990Srrh } 5587990Srrh *cp++ = 0; 5597990Srrh return (hash(buf)); 5607990Srrh } 5617990Srrh 5627990Srrh #define NSAVETAB 4096 5637990Srrh char *savetab; 5647990Srrh int saveleft; 5657990Srrh 5667990Srrh char * 5677990Srrh savestr(cp) 5687990Srrh register char *cp; 5697990Srrh { 5707990Srrh register int len; 5717990Srrh 5727990Srrh len = strlen(cp) + 1; 5737990Srrh if (len > saveleft) { 5747990Srrh saveleft = NSAVETAB; 5757990Srrh if (len > saveleft) 5767990Srrh saveleft = len; 5777990Srrh savetab = (char *)malloc(saveleft); 5787990Srrh if (savetab == 0) { 5797990Srrh fprintf(stderr, "pass 2 error: ran out of memory (savestr)"); 5807990Srrh exit(1); 5817990Srrh } 5827990Srrh } 5837990Srrh strncpy(savetab, cp, len); 5847990Srrh cp = savetab; 5857990Srrh savetab += len; 5867990Srrh saveleft -= len; 5877990Srrh return (cp); 5887990Srrh } 5897990Srrh 5907990Srrh /* 5917990Srrh * The definition for the segmented hash tables. 5927990Srrh */ 5937990Srrh #define MAXHASH 20 5947990Srrh #define HASHINC 1013 5957990Srrh struct ht { 5967990Srrh char **ht_low; 5977990Srrh char **ht_high; 5987990Srrh int ht_used; 5997990Srrh } htab[MAXHASH]; 6007990Srrh 6017990Srrh char * 6027990Srrh hash(s) 6037990Srrh char *s; 6047990Srrh { 6057990Srrh register char **h; 6067990Srrh register i; 6077990Srrh register char *cp; 6087990Srrh struct ht *htp; 6097990Srrh int sh; 6107990Srrh 6117990Srrh /* 6127990Srrh * The hash function is a modular hash of 6137990Srrh * the sum of the characters with the sum 6147990Srrh * doubled before each successive character 6157990Srrh * is added. 6167990Srrh */ 6177990Srrh cp = s; 6187990Srrh i = 0; 6197990Srrh while (*cp) 6207990Srrh i = i*2 + *cp++; 6217990Srrh sh = (i&077777) % HASHINC; 6227990Srrh cp = s; 6237990Srrh /* 6247990Srrh * There are as many as MAXHASH active 6257990Srrh * hash tables at any given point in time. 6267990Srrh * The search starts with the first table 6277990Srrh * and continues through the active tables 6287990Srrh * as necessary. 6297990Srrh */ 6307990Srrh for (htp = htab; htp < &htab[MAXHASH]; htp++) { 6317990Srrh if (htp->ht_low == 0) { 6327990Srrh register char **hp = 6337990Srrh (char **) calloc(sizeof (char **), HASHINC); 6347990Srrh if (hp == 0) { 6357990Srrh fprintf(stderr, "pass 2 error: ran out of memory (hash)"); 6367990Srrh exit(1); 6377990Srrh } 6387990Srrh htp->ht_low = hp; 6397990Srrh htp->ht_high = htp->ht_low + HASHINC; 6407990Srrh } 6417990Srrh h = htp->ht_low + sh; 6427990Srrh /* 6437990Srrh * quadratic rehash increment 6447990Srrh * starts at 1 and incremented 6457990Srrh * by two each rehash. 6467990Srrh */ 6477990Srrh i = 1; 6487990Srrh do { 6497990Srrh if (*h == 0) { 6507990Srrh if (htp->ht_used > (HASHINC * 3)/4) 6517990Srrh break; 6527990Srrh htp->ht_used++; 6537990Srrh *h = savestr(cp); 6547990Srrh return (*h); 6557990Srrh } 6567990Srrh if (**h == *cp && strcmp(*h, cp) == 0) 6577990Srrh return (*h); 6587990Srrh h += i; 6597990Srrh i += 2; 6607990Srrh if (h >= htp->ht_high) 6617990Srrh h -= HASHINC; 6627990Srrh } while (i < HASHINC); 6637990Srrh } 6647990Srrh fprintf(stderr, "pass 2 error: ran out of hash tables"); 6657990Srrh exit(1); 6667990Srrh } 6677990Srrh char *tstrbuf[1]; 6687990Srrh #endif 669