1: #ifndef lint 2: static char sccsid[] = "@(#)lpass2.c 1.6 (Berkeley) 2/21/86"; 3: #endif lint 4: 5: # include "macdefs.h" 6: # include "manifest.h" 7: # include "lmanifest.h" 8: 9: # define USED 01 10: # define VUSED 02 11: # define EUSED 04 12: # define RVAL 010 13: # define VARARGS 0100 14: 15: # define NSZ 4096 16: # define TYSZ 3500 17: # define FSZ 500 18: # define NTY 50 19: 20: typedef struct sty STYPE; 21: struct sty { ATYPE t; STYPE *next; }; 22: 23: typedef struct sym { 24: #ifndef FLEXNAMES 25: char name[LCHNM]; 26: #else 27: char *name; 28: #endif 29: short nargs; 30: int decflag; 31: int fline; 32: STYPE symty; 33: int fno; 34: int use; 35: } STAB; 36: 37: STAB stab[NSZ]; 38: STAB *find(); 39: 40: STYPE tary[TYSZ]; 41: STYPE *tget(); 42: 43: #ifndef FLEXNAMES 44: char fnm[FSZ][LFNM]; 45: #else 46: char *fnm[FSZ]; 47: #endif 48: 49: #ifdef FLEXNAMES 50: char *getstr(); 51: #endif 52: 53: int tfree; /* used to allocate types */ 54: int ffree; /* used to save filenames */ 55: 56: struct ty atyp[NTY]; 57: /* r is where all the input ends up */ 58: union rec r; 59: 60: int hflag = 0; 61: int pflag = 0; 62: int xflag = 0; 63: int uflag = 1; 64: int ddddd = 0; 65: int zflag = 0; 66: int Pflag = 0; 67: 68: int cfno; /* current file number */ 69: 70: main( argc, argv ) char *argv[]; { 71: register char *p; 72: 73: /* first argument is intermediate file */ 74: /* second argument is - options */ 75: 76: for( ; argc>2 && argv[argc-1][0] == '-' ; --argc ){ 77: for( p=argv[argc-1]; *p; ++p ){ 78: switch( *p ){ 79: 80: case 'h': 81: hflag = 1; 82: break; 83: 84: case 'p': 85: pflag = 1; 86: break; 87: 88: case 'x': 89: xflag = 1; 90: break; 91: 92: case 'X': 93: ddddd = 1; 94: break; 95: 96: case 'u': 97: uflag = 0; 98: break; 99: 100: case 'z': 101: zflag = 1; 102: break; 103: 104: case 'P': 105: Pflag = 1; 106: break; 107: 108: } 109: } 110: } 111: 112: if( argc < 2 || !freopen( argv[1], "r", stdin ) ){ 113: error( "cannot open intermediate file" ); 114: exit( 1 ); 115: } 116: if( Pflag ){ 117: pfile(); 118: return( 0 ); 119: } 120: mloop( LDI|LIB|LST ); 121: rewind( stdin ); 122: mloop( LDC|LDX ); 123: rewind( stdin ); 124: mloop( LRV|LUV|LUE|LUM ); 125: cleanup(); 126: return(0); 127: } 128: 129: mloop( m ){ 130: /* do the main loop */ 131: register STAB *q; 132: 133: while( lread(m) ){ 134: q = find(); 135: if( q->decflag ) chkcompat(q); 136: else setuse(q); 137: } 138: } 139: 140: lread(m){ /* read a line into r.l */ 141: 142: register n; 143: 144: for(;;) { 145: if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0); 146: if( r.l.decflag & LFN ){ 147: /* new filename */ 148: #ifdef FLEXNAMES 149: r.f.fn = getstr(); 150: #endif 151: if( Pflag ) return( 1 ); 152: setfno( r.f.fn ); 153: continue; 154: } 155: #ifdef FLEXNAMES 156: r.l.name = getstr(); 157: #endif 158: n = r.l.nargs; 159: if( n<0 ) n = -n; 160: if( n>=NTY ) error( "more than %d args?", n ); 161: fread( (char *)atyp, sizeof(ATYPE), n, stdin ); 162: if( ( r.l.decflag & m ) ) return( 1 ); 163: } 164: } 165: 166: setfno( s ) char *s; { 167: /* look up current file names */ 168: /* first, strip backwards to the beginning or to the first / */ 169: int i; 170: 171: /* now look up s */ 172: for( i=0; i<ffree; ++i ){ 173: #ifndef FLEXNAMES 174: if( !strncmp( s, fnm[i], LFNM ) ) 175: #else 176: if (fnm[i] == s) 177: #endif 178: { 179: cfno = i; 180: return; 181: } 182: } 183: /* make a new entry */ 184: if( ffree >= FSZ ) error( "more than %d files", FSZ ); 185: #ifndef FLEXNAMES 186: strncpy( fnm[ffree], s, LFNM ); 187: #else 188: fnm[ffree] = s; 189: #endif 190: cfno = ffree++; 191: } 192: 193: /* VARARGS */ 194: error( s, a ) char *s; { 195: 196: #ifndef FLEXNAMES 197: fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] ); 198: #else 199: fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] ); 200: #endif 201: fprintf( stderr, s, a ); 202: fprintf( stderr, "\n" ); 203: exit(1); 204: } 205: 206: STAB * 207: find(){ 208: register h=0; 209: #ifndef FLEXNAMES 210: h = hashstr(r.l.name, LCHNM) % NSZ; 211: #else 212: h = (int)r.l.name % NSZ; 213: #endif 214: { register STAB *p, *q; 215: for( p=q= &stab[h]; q->decflag; ){ 216: #ifndef FLEXNAMES 217: if( !strncmp( r.l.name, q->name, LCHNM)) 218: #else 219: if (r.l.name == q->name) 220: #endif 221: if( ((q->decflag|r.l.decflag)&LST)==0 || q->fno==cfno ) 222: return(q); 223: if( ++q >= &stab[NSZ] ) q = stab; 224: if( q == p ) error( "too many names defined" ); 225: } 226: #ifndef FLEXNAMES 227: strncpy( q->name, r.l.name, LCHNM ); 228: #else 229: q->name = r.l.name; 230: #endif 231: return( q ); 232: } 233: } 234: 235: STYPE * 236: tget(){ 237: if( tfree >= TYSZ ){ 238: error( "too many types needed" ); 239: } 240: return( &tary[tfree++] ); 241: } 242: 243: chkcompat(q) STAB *q; { 244: /* are the types, etc. in r.l and q compatible */ 245: register int i; 246: STYPE *qq; 247: 248: setuse(q); 249: 250: /* argument check */ 251: 252: if( q->decflag & (LDI|LIB|LUV|LUE|LST) ){ 253: if( r.l.decflag & (LUV|LIB|LUE) ){ 254: if( q->nargs != r.l.nargs ){ 255: if( !(q->use&VARARGS) ){ 256: #ifndef FLEXNAMES 257: printf( "%.8s: variable # of args.", q->name ); 258: #else 259: printf( "%s: variable # of args.", q->name ); 260: #endif 261: viceversa(q); 262: } 263: if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs; 264: if( !(q->decflag & (LDI|LIB|LST) ) ) { 265: q->nargs = r.l.nargs; 266: q->use |= VARARGS; 267: } 268: } 269: for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){ 270: if( chktype( &qq->t, &atyp[i] ) ){ 271: #ifndef FLEXNAMES 272: printf( "%.8s, arg. %d used inconsistently", 273: #else 274: printf( "%s, arg. %d used inconsistently", 275: #endif 276: q->name, i+1 ); 277: viceversa(q); 278: } 279: } 280: } 281: } 282: 283: if( (q->decflag&(LDI|LIB|LUV|LST)) && r.l.decflag==LUV ){ 284: if( chktype( &r.l.type, &q->symty.t ) ){ 285: #ifndef FLEXNAMES 286: printf( "%.8s value used inconsistently", q->name ); 287: #else 288: printf( "%s value used inconsistently", q->name ); 289: #endif 290: viceversa(q); 291: } 292: } 293: 294: /* check for multiple declaration */ 295: 296: if( (q->decflag&(LDI|LST)) && (r.l.decflag&(LDI|LIB|LST)) ){ 297: #ifndef FLEXNAMES 298: printf( "%.8s multiply declared", q->name ); 299: #else 300: printf( "%s multiply declared", q->name ); 301: #endif 302: viceversa(q); 303: } 304: 305: /* do a bit of checking of definitions and uses... */ 306: 307: if( (q->decflag & (LDI|LIB|LDX|LDC|LUM|LST)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){ 308: #ifndef FLEXNAMES 309: printf( "%.8s value declared inconsistently", q->name ); 310: #else 311: printf( "%s value declared inconsistently", q->name ); 312: #endif 313: viceversa(q); 314: } 315: 316: /* better not call functions which are declared to be structure or union returning */ 317: 318: if( (q->decflag & (LDI|LIB|LDX|LDC|LST)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){ 319: /* only matters if the function returns union or structure */ 320: TWORD ty; 321: ty = q->symty.t.aty; 322: if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){ 323: #ifndef FLEXNAMES 324: printf( "%.8s function value type must be declared before use", q->name ); 325: #else 326: printf( "%s function value type must be declared before use", q->name ); 327: #endif 328: viceversa(q); 329: } 330: } 331: 332: if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){ 333: /* make the external declaration go away */ 334: /* in effect, it was used without being defined */ 335: } 336: } 337: 338: viceversa(q) STAB *q; { 339: /* print out file comparison */ 340: #ifndef FLEXNAMES 341: printf( " %.*s(%d) :: %.*s(%d)\n", 342: LFNM, fnm[q->fno], q->fline, 343: LFNM, fnm[cfno], r.l.fline ); 344: #else 345: printf( " %s(%d) :: %s(%d)\n", 346: fnm[q->fno], q->fline, 347: fnm[cfno], r.l.fline ); 348: #endif 349: } 350: 351: /* messages for defintion/use */ 352: char * 353: mess[2][2] ={ 354: "", 355: #ifndef FLEXNAMES 356: "%.8s used( %.*s(%d) ), but not defined\n", 357: "%.8s defined( %.*s(%d) ), but never used\n", 358: "%.8s declared( %.*s(%d) ), but never used or defined\n" 359: #else 360: "%s used( %s(%d) ), but not defined\n", 361: "%s defined( %s(%d) ), but never used\n", 362: "%s declared( %s(%d) ), but never used or defined\n" 363: #endif 364: }; 365: 366: lastone(q) STAB *q; { 367: 368: register nu, nd, uses; 369: 370: if( ddddd ) pst(q); 371: 372: nu = nd = 0; 373: uses = q->use; 374: 375: if( !(uses&USED) && q->decflag != LIB ) { 376: #ifndef FLEXNAMES 377: if( strncmp(q->name,"main",7) ) 378: #else 379: if (strcmp(q->name, "main")) 380: #endif 381: nu = 1; 382: } 383: 384: if( !ISFTN(q->symty.t.aty) ){ 385: switch( q->decflag ){ 386: 387: case LIB: 388: nu = nd = 0; /* don't complain about uses on libraries */ 389: break; 390: case LDX: 391: if( !xflag ) break; 392: case LUV: 393: case LUE: 394: /* 01/04/80 */ case LUV | LUE: 395: case LUM: 396: nd = 1; 397: } 398: } 399: if( uflag && ( nu || nd ) ) 400: #ifndef FLEXNAMES 401: printf( mess[nu][nd], q->name, LFNM, fnm[q->fno], q->fline ); 402: #else 403: printf( mess[nu][nd], q->name, fnm[q->fno], q->fline ); 404: #endif 405: 406: if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){ 407: /* if functions is static, then print the file name too */ 408: if( q->decflag & LST ) 409: #ifndef FLEXNAMES 410: printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline ); 411: #else 412: printf( "%s(%d):", fnm[q->fno], q->fline ); 413: #endif 414: #ifndef FLEXNAMES 415: printf( "%.*s returns value which is %s ignored\n", 416: LCHNM, q->name, uses&VUSED ? "sometimes" : "always" ); 417: #else 418: printf( "%s returns value which is %s ignored\n", 419: q->name, uses&VUSED ? "sometimes" : "always" ); 420: #endif 421: } 422: 423: if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB|LST)) ){ 424: if( q->decflag & LST ) 425: #ifndef FLEXNAMES 426: printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline ); 427: #else 428: printf( "%s(%d):", fnm[q->fno], q->fline ); 429: #endif 430: #ifndef FLEXNAMES 431: printf( "%.*s value is used, but none returned\n", 432: LCHNM, q->name); 433: #else 434: printf( "%s value is used, but none returned\n", q->name); 435: #endif 436: } 437: } 438: 439: cleanup(){ /* call lastone and die gracefully */ 440: STAB *q; 441: for( q=stab; q< &stab[NSZ]; ++q ){ 442: if( q->decflag ) lastone(q); 443: } 444: exit(0); 445: } 446: 447: setuse(q) STAB *q; { /* check new type to ensure that it is used */ 448: 449: if( !q->decflag ){ /* new one */ 450: q->decflag = r.l.decflag; 451: q->symty.t = r.l.type; 452: if( r.l.nargs < 0 ){ 453: q->nargs = -r.l.nargs; 454: q->use = VARARGS; 455: } 456: else { 457: q->nargs = r.l.nargs; 458: q->use = 0; 459: } 460: q->fline = r.l.fline; 461: q->fno = cfno; 462: if( q->nargs ){ 463: int i; 464: STYPE *qq; 465: for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){ 466: qq->next = tget(); 467: qq->next->t = atyp[i]; 468: } 469: } 470: } 471: 472: switch( r.l.decflag ){ 473: 474: case LRV: 475: q->use |= RVAL; 476: return; 477: case LUV: 478: q->use |= VUSED+USED; 479: return; 480: case LUE: 481: q->use |= EUSED+USED; 482: return; 483: /* 01/04/80 */ case LUV | LUE: 484: case LUM: 485: q->use |= USED; 486: return; 487: 488: } 489: } 490: 491: chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; { 492: TWORD t; 493: 494: /* check the two type words to see if they are compatible */ 495: /* for the moment, enums are turned into ints, and should be checked as such */ 496: if( pt1->aty == ENUMTY ) pt1->aty = INT; 497: if( pt2->aty == ENUMTY ) pt2->aty = INT; 498: 499: if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){ 500: if( pt1->aty != pt2->aty || pt1->extra1 != pt2->extra1 ) 501: return 1; 502: /* if -z then don't worry about undefined structures, 503: as long as the names match */ 504: if( zflag && (pt1->extra == 0 || pt2->extra == 0) ) return 0; 505: return pt1->extra != pt2->extra; 506: } 507: 508: if( pt2->extra ){ /* constant passed in */ 509: if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 ); 510: else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 ); 511: } 512: else if( pt1->extra ){ /* for symmetry */ 513: if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 ); 514: else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 ); 515: } 516: 517: return( pt1->aty != pt2->aty ); 518: } 519: 520: struct tb { int m; char * nm }; 521: 522: struct tb dfs[] = { 523: LDI, "LDI", 524: LIB, "LIB", 525: LDC, "LDC", 526: LDX, "LDX", 527: LRV, "LRV", 528: LUV, "LUV", 529: LUE, "LUE", 530: LUM, "LUM", 531: LST, "LST", 532: LFN, "LFN", 533: 0, "" }; 534: 535: struct tb us[] = { 536: USED, "USED", 537: VUSED, "VUSED", 538: EUSED, "EUSED", 539: RVAL, "RVAL", 540: VARARGS, "VARARGS", 541: 0, "" }; 542: 543: ptb( v, tp ) struct tb *tp; { 544: /* print a value from the table */ 545: int flag; 546: flag = 0; 547: for( ; tp->m; ++tp ){ 548: if( v&tp->m ){ 549: if( flag++ ) putchar( '|' ); 550: printf( "%s", tp->nm ); 551: } 552: } 553: } 554: 555: pst( q ) STAB *q; { 556: /* give a debugging output for q */ 557: 558: #ifndef FLEXNAMES 559: printf( "%.8s (", q->name ); 560: #else 561: printf( "%s (", q->name ); 562: #endif 563: ptb( q->decflag, dfs ); 564: printf( "), use= " ); 565: ptb( q->use, us ); 566: printf( ", line %d, nargs=%d\n", q->fline, q->nargs ); 567: } 568: 569: pfile() { 570: /* print the input file in readable form */ 571: while( lread( LDI|LIB|LDC|LDX|LRV|LUV|LUE|LUM|LST|LFN ) ) 572: prc(); 573: } 574: 575: prc() { 576: /* print out 'r' for debugging */ 577: register i, j, k; 578: 579: printf( "decflag\t" ); 580: ptb( r.l.decflag, dfs ); 581: putchar( '\n' ); 582: if( r.l.decflag & LFN ){ 583: #ifdef FLEXNAMES 584: printf( "fn\t\t%s\n", r.f.fn ); 585: #else 586: printf( "fn\t%\t.*s\n", LFNM, r.f.fn ); 587: #endif 588: } 589: else { 590: #ifdef FLEXNAMES 591: printf( "name\t%s\n", r.l.name ); 592: #else 593: printf( "name\t%.*s\n", LCHNM, r.l.name ); 594: #endif 595: printf( "nargs\t%d\n", r.l.nargs ); 596: printf( "fline\t%d\n", r.l.fline ); 597: printf( "type.aty\t0%o (", r.l.type.aty ); 598: pty( r.l.type.aty, r.l.name ); 599: printf( ")\ntype.extra\t%d\n", r.l.type.extra ); 600: j = r.l.type.extra1; 601: printf( "type.extra1\t0x%x (%d,%d)\n", 602: j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 603: k = r.l.nargs; 604: if( k < 0 ) k = -k; 605: for( i = 0; i < k; i++ ){ 606: printf( "atyp[%d].aty\t0%o (", i, atyp[i].aty ); 607: pty( atyp[i].aty, "" ); 608: printf( ")\natyp[%d].extra\t%d\n", i, atyp[i].extra); 609: j = atyp[i].extra1; 610: printf( "atyp[%d].extra1\t0x%x (%d,%d)\n", 611: i, j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 612: } 613: } 614: putchar( '\n' ); 615: } 616: 617: pty( t, name ) TWORD t; { 618: static char * tnames[] = { 619: "void", "farg", "char", "short", 620: "int", "long", "float", "double", 621: "struct xxx", "union %s", "enum", "moety", 622: "unsigned char", "unsigned short", "unsigned", "unsigned long", 623: "?", "?" 624: }; 625: 626: printf( "%s ", tnames[BTYPE(t)] ); 627: pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT ); 628: } 629: 630: pty1( t, name, level ) TWORD t; { 631: register TWORD u; 632: 633: if( level < 0 ){ 634: printf( "%s", name ); 635: return; 636: } 637: u = t >> level * TSHIFT; 638: if( ISPTR(u) ){ 639: printf( "*" ); 640: pty1( t, name, level-1 ); 641: } 642: else if( ISFTN(u) ){ 643: if( level > 0 && ISPTR(u << TSHIFT) ){ 644: printf( "(" ); 645: pty1( t, name, level-1 ); 646: printf( ")()" ); 647: } 648: else { 649: pty1( t, name, level-1 ); 650: printf( "()" ); 651: } 652: } 653: else if( ISARY(u) ){ 654: if( level > 0 && ISPTR(u << TSHIFT) ){ 655: printf( "(" ); 656: pty1( t, name, level-1 ); 657: printf( ")[]" ); 658: } 659: else { 660: pty1( t, name, level-1 ); 661: printf( "[]" ); 662: } 663: } 664: else { 665: pty1( t, name, level-1 ); 666: } 667: } 668: 669: #ifdef FLEXNAMES 670: char * 671: getstr() 672: { 673: char buf[BUFSIZ]; 674: register char *cp = buf; 675: register int c; 676: 677: if (feof(stdin) || ferror(stdin)) 678: return(""); 679: while ((c = getchar()) > 0) 680: *cp++ = c; 681: if (c < 0) { 682: error("intermediate file format error (getstr)"); 683: exit(1); 684: } 685: *cp++ = 0; 686: return (hash(buf)); 687: } 688: 689: #define NSAVETAB 4096 690: char *savetab; 691: int saveleft; 692: 693: char * 694: savestr(cp) 695: register char *cp; 696: { 697: register int len; 698: 699: len = strlen(cp) + 1; 700: if (len > saveleft) { 701: saveleft = NSAVETAB; 702: if (len > saveleft) 703: saveleft = len; 704: savetab = (char *)malloc(saveleft); 705: if (savetab == 0) { 706: error("ran out of memory (savestr)"); 707: exit(1); 708: } 709: } 710: strncpy(savetab, cp, len); 711: cp = savetab; 712: savetab += len; 713: saveleft -= len; 714: return (cp); 715: } 716: 717: /* 718: * The definition for the segmented hash tables. 719: */ 720: #define MAXHASH 20 721: #define HASHINC 1013 722: struct ht { 723: char **ht_low; 724: char **ht_high; 725: int ht_used; 726: } htab[MAXHASH]; 727: 728: char * 729: hash(s) 730: char *s; 731: { 732: register char **h; 733: register i; 734: register char *cp; 735: struct ht *htp; 736: int sh; 737: 738: sh = hashstr(s) % HASHINC; 739: cp = s; 740: /* 741: * There are as many as MAXHASH active 742: * hash tables at any given point in time. 743: * The search starts with the first table 744: * and continues through the active tables 745: * as necessary. 746: */ 747: for (htp = htab; htp < &htab[MAXHASH]; htp++) { 748: if (htp->ht_low == 0) { 749: register char **hp = 750: (char **) calloc(sizeof (char **), HASHINC); 751: if (hp == 0) { 752: error("ran out of memory (hash)"); 753: exit(1); 754: } 755: htp->ht_low = hp; 756: htp->ht_high = htp->ht_low + HASHINC; 757: } 758: h = htp->ht_low + sh; 759: /* 760: * quadratic rehash increment 761: * starts at 1 and incremented 762: * by two each rehash. 763: */ 764: i = 1; 765: do { 766: if (*h == 0) { 767: if (htp->ht_used > (HASHINC * 3)/4) 768: break; 769: htp->ht_used++; 770: *h = savestr(cp); 771: return (*h); 772: } 773: if (**h == *cp && strcmp(*h, cp) == 0) 774: return (*h); 775: h += i; 776: i += 2; 777: if (h >= htp->ht_high) 778: h -= HASHINC; 779: } while (i < HASHINC); 780: } 781: error("ran out of hash tables"); 782: exit(1); 783: } 784: char *tstrbuf[1]; 785: #endif