1 #ifndef lint 2 static char sccsid[] = "@(#)lpass2.c 1.6 (Berkeley) 02/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 786