1 #ifndef lint 2 static char sccsid[] = "@(#)lpass2.c 1.11 (Berkeley) 02/21/90"; 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(0); 150 #endif 151 if( Pflag ) return( 1 ); 152 setfno( r.f.fn ); 153 continue; 154 } 155 #ifdef FLEXNAMES 156 r.l.name = getstr(1); 157 #else /* !FLEXNAMES */ 158 portify(r.l.name); 159 #endif /* !FLEXNAMES */ 160 n = r.l.nargs; 161 if( n<0 ) n = ~n; 162 if( n>=NTY ) error( "more than %d args?", n ); 163 fread( (char *)atyp, sizeof(ATYPE), n, stdin ); 164 if( ( r.l.decflag & m ) ) return( 1 ); 165 } 166 } 167 168 setfno( s ) char *s; { 169 /* look up current file names */ 170 /* first, strip backwards to the beginning or to the first / */ 171 int i; 172 173 /* now look up s */ 174 for( i=0; i<ffree; ++i ){ 175 #ifndef FLEXNAMES 176 if( !strncmp( s, fnm[i], LFNM ) ) 177 #else 178 if (fnm[i] == s) 179 #endif 180 { 181 cfno = i; 182 return; 183 } 184 } 185 /* make a new entry */ 186 if( ffree >= FSZ ) error( "more than %d files", FSZ ); 187 #ifndef FLEXNAMES 188 strncpy( fnm[ffree], s, LFNM ); 189 #else 190 fnm[ffree] = s; 191 #endif 192 cfno = ffree++; 193 } 194 195 /* VARARGS */ 196 error( s, a ) char *s; { 197 198 #ifndef FLEXNAMES 199 fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] ); 200 #else 201 fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] ); 202 #endif 203 fprintf( stderr, s, a ); 204 fprintf( stderr, "\n" ); 205 exit(1); 206 } 207 208 STAB * 209 find(){ 210 register h=0; 211 #ifndef FLEXNAMES 212 h = hashstr(r.l.name, LCHNM) % NSZ; 213 #else 214 h = *(int *)r.l.name % NSZ; 215 #endif 216 { register STAB *p, *q; 217 for( p=q= &stab[h]; q->decflag; ){ 218 #ifndef FLEXNAMES 219 if( !strncmp( r.l.name, q->name, LCHNM)) 220 #else 221 if (strcmp(r.l.name, q->name) == 0) 222 #endif 223 if( ((q->decflag|r.l.decflag)&LST)==0 || q->fno==cfno ) 224 return(q); 225 if( ++q >= &stab[NSZ] ) q = stab; 226 if( q == p ) error( "too many names defined" ); 227 } 228 #ifndef FLEXNAMES 229 strncpy( q->name, r.l.name, LCHNM ); 230 #else 231 q->name = r.l.name; 232 #endif 233 return( q ); 234 } 235 } 236 237 STYPE * 238 tget(){ 239 if( tfree >= TYSZ ){ 240 error( "too many types needed" ); 241 } 242 return( &tary[tfree++] ); 243 } 244 245 chkcompat(q) STAB *q; { 246 /* are the types, etc. in r.l and q compatible */ 247 register int i; 248 STYPE *qq; 249 250 setuse(q); 251 252 /* argument check */ 253 254 if( q->decflag & (LDI|LIB|LUV|LUE|LST) ){ 255 if( r.l.decflag & (LUV|LIB|LUE) ){ 256 if( q->nargs != r.l.nargs ){ 257 if( !(q->use&VARARGS) ){ 258 #ifndef FLEXNAMES 259 printf( "%.8s: variable # of args.", q->name ); 260 #else 261 printf( "%s: variable # of args.", q->name ); 262 #endif 263 viceversa(q); 264 } 265 if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs; 266 if( !(q->decflag & (LDI|LIB|LST) ) ) { 267 q->nargs = r.l.nargs; 268 q->use |= VARARGS; 269 } 270 } 271 for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){ 272 if( chktype( &qq->t, &atyp[i], q->fno ) ){ 273 #ifndef FLEXNAMES 274 printf( "%.8s, arg. %d used inconsistently", 275 #else 276 printf( "%s, arg. %d used inconsistently", 277 #endif 278 q->name, i+1 ); 279 viceversa(q); 280 } 281 } 282 } 283 } 284 285 if( (q->decflag&(LDI|LIB|LUV|LST)) && r.l.decflag==LUV ){ 286 if( chktype( &r.l.type, &q->symty.t, q->fno ) ){ 287 #ifndef FLEXNAMES 288 printf( "%.8s value used inconsistently", q->name ); 289 #else 290 printf( "%s value used inconsistently", q->name ); 291 #endif 292 viceversa(q); 293 } 294 } 295 296 /* check for multiple declaration */ 297 298 if( (q->decflag&(LDI|LST)) && (r.l.decflag&(LDI|LIB|LST)) ){ 299 #ifndef FLEXNAMES 300 printf( "%.8s multiply declared", q->name ); 301 #else 302 printf( "%s multiply declared", q->name ); 303 #endif 304 viceversa(q); 305 } 306 307 /* do a bit of checking of definitions and uses... */ 308 309 if( (q->decflag & (LDI|LIB|LDX|LDC|LUM|LST)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){ 310 #ifndef FLEXNAMES 311 printf( "%.8s value declared inconsistently", q->name ); 312 #else 313 printf( "%s value declared inconsistently", q->name ); 314 #endif 315 viceversa(q); 316 } 317 318 /* better not call functions which are declared to be structure or union returning */ 319 320 if( (q->decflag & (LDI|LIB|LDX|LDC|LST)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){ 321 /* only matters if the function returns union or structure */ 322 TWORD ty; 323 ty = q->symty.t.aty; 324 if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){ 325 #ifndef FLEXNAMES 326 printf( "%.8s function value type must be declared before use", q->name ); 327 #else 328 printf( "%s function value type must be declared before use", q->name ); 329 #endif 330 viceversa(q); 331 } 332 } 333 334 if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){ 335 /* make the external declaration go away */ 336 /* in effect, it was used without being defined */ 337 } 338 } 339 340 viceversa(q) STAB *q; { 341 /* print out file comparison */ 342 #ifndef FLEXNAMES 343 printf( " %.*s(%d) :: %.*s(%d)\n", 344 LFNM, fnm[q->fno], q->fline, 345 LFNM, fnm[cfno], r.l.fline ); 346 #else 347 printf( " %s(%d) :: %s(%d)\n", 348 fnm[q->fno], q->fline, 349 fnm[cfno], r.l.fline ); 350 #endif 351 } 352 353 /* messages for defintion/use */ 354 char * 355 mess[2][2] ={ 356 "", 357 #ifndef FLEXNAMES 358 "%.8s used( %.*s(%d) ), but not defined\n", 359 "%.8s defined( %.*s(%d) ), but never used\n", 360 "%.8s declared( %.*s(%d) ), but never used or defined\n" 361 #else 362 "%s used( %s(%d) ), but not defined\n", 363 "%s defined( %s(%d) ), but never used\n", 364 "%s declared( %s(%d) ), but never used or defined\n" 365 #endif 366 }; 367 368 lastone(q) STAB *q; { 369 370 register nu, nd, uses; 371 372 if( ddddd ) pst(q); 373 374 nu = nd = 0; 375 uses = q->use; 376 377 if( !(uses&USED) && q->decflag != LIB ) { 378 #ifndef FLEXNAMES 379 if( strncmp(q->name,"main",7) ) 380 #else 381 if (strcmp(q->name, "main")) 382 #endif 383 nu = 1; 384 } 385 386 switch( q->decflag ){ 387 388 case LIB: 389 nu = nd = 0; /* don't complain about uses on libraries */ 390 break; 391 case LDX: 392 if( !xflag ) break; 393 case LUV: 394 case LUE: 395 /* 01/04/80 */ case LUV | LUE: 396 case LUM: 397 nd = 1; 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, fno ) 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 /* if -p and pt1 is "too big" and 506 ** pt1 came from a llib-l file, we can't pass judgment on it. 507 */ 508 if ( pflag && pt1->extra > pt2->extra && 509 strncmp(fnm[fno], "llib-l", 6) == 0) 510 return 0; 511 return pt1->extra != pt2->extra; 512 } 513 514 if( pt2->extra ){ /* constant passed in */ 515 if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 ); 516 else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 ); 517 } 518 else if( pt1->extra ){ /* for symmetry */ 519 if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 ); 520 else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 ); 521 } 522 523 return( pt1->aty != pt2->aty ); 524 } 525 526 struct tb { int m; char *nm; }; 527 528 struct tb dfs[] = { 529 LDI, "LDI", 530 LIB, "LIB", 531 LDC, "LDC", 532 LDX, "LDX", 533 LRV, "LRV", 534 LUV, "LUV", 535 LUE, "LUE", 536 LUM, "LUM", 537 LST, "LST", 538 LFN, "LFN", 539 0, "" }; 540 541 struct tb us[] = { 542 USED, "USED", 543 VUSED, "VUSED", 544 EUSED, "EUSED", 545 RVAL, "RVAL", 546 VARARGS, "VARARGS", 547 0, "" }; 548 549 ptb( v, tp ) struct tb *tp; { 550 /* print a value from the table */ 551 int flag; 552 flag = 0; 553 for( ; tp->m; ++tp ){ 554 if( v&tp->m ){ 555 if( flag++ ) putchar( '|' ); 556 printf( "%s", tp->nm ); 557 } 558 } 559 } 560 561 pst( q ) STAB *q; { 562 /* give a debugging output for q */ 563 564 #ifndef FLEXNAMES 565 printf( "%.8s (", q->name ); 566 #else 567 printf( "%s (", q->name ); 568 #endif 569 ptb( q->decflag, dfs ); 570 printf( "), use= " ); 571 ptb( q->use, us ); 572 printf( ", line %d, nargs=%d\n", q->fline, q->nargs ); 573 } 574 575 pfile() { 576 /* print the input file in readable form */ 577 while( lread( LDI|LIB|LDC|LDX|LRV|LUV|LUE|LUM|LST|LFN ) ) 578 prc(); 579 } 580 581 prc() { 582 /* print out 'r' for debugging */ 583 register i, j, k; 584 585 printf( "decflag\t" ); 586 ptb( r.l.decflag, dfs ); 587 putchar( '\n' ); 588 if( r.l.decflag & LFN ){ 589 #ifdef FLEXNAMES 590 printf( "fn\t\t%s\n", r.f.fn ); 591 #else 592 printf( "fn\t%\t.*s\n", LFNM, r.f.fn ); 593 #endif 594 } 595 else { 596 #ifdef FLEXNAMES 597 printf( "name\t%s\n", r.l.name ); 598 #else 599 printf( "name\t%.*s\n", LCHNM, r.l.name ); 600 #endif 601 printf( "nargs\t%d\n", r.l.nargs ); 602 printf( "fline\t%d\n", r.l.fline ); 603 printf( "type.aty\t0%o (", r.l.type.aty ); 604 pty( r.l.type.aty, r.l.name ); 605 printf( ")\ntype.extra\t%d\n", r.l.type.extra ); 606 j = r.l.type.extra1; 607 printf( "type.extra1\t0x%x (%d,%d)\n", 608 j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 609 k = r.l.nargs; 610 if( k < 0 ) k = ~k; 611 for( i = 0; i < k; i++ ){ 612 printf( "atyp[%d].aty\t0%o (", i, atyp[i].aty ); 613 pty( atyp[i].aty, "" ); 614 printf( ")\natyp[%d].extra\t%d\n", i, atyp[i].extra); 615 j = atyp[i].extra1; 616 printf( "atyp[%d].extra1\t0x%x (%d,%d)\n", 617 i, j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 618 } 619 } 620 putchar( '\n' ); 621 } 622 623 pty( t, name ) TWORD t; { 624 static char * tnames[] = { 625 "void", "farg", "char", "short", 626 "int", "long", "float", "double", 627 "struct xxx", "union %s", "enum", "moety", 628 "unsigned char", "unsigned short", "unsigned", "unsigned long", 629 "?", "?" 630 }; 631 632 printf( "%s ", tnames[BTYPE(t)] ); 633 pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT ); 634 } 635 636 pty1( t, name, level ) TWORD t; { 637 register TWORD u; 638 639 if( level < 0 ){ 640 printf( "%s", name ); 641 return; 642 } 643 u = t >> level * TSHIFT; 644 if( ISPTR(u) ){ 645 printf( "*" ); 646 pty1( t, name, level-1 ); 647 } 648 else if( ISFTN(u) ){ 649 if( level > 0 && ISPTR(u << TSHIFT) ){ 650 printf( "(" ); 651 pty1( t, name, level-1 ); 652 printf( ")()" ); 653 } 654 else { 655 pty1( t, name, level-1 ); 656 printf( "()" ); 657 } 658 } 659 else if( ISARY(u) ){ 660 if( level > 0 && ISPTR(u << TSHIFT) ){ 661 printf( "(" ); 662 pty1( t, name, level-1 ); 663 printf( ")[]" ); 664 } 665 else { 666 pty1( t, name, level-1 ); 667 printf( "[]" ); 668 } 669 } 670 else { 671 pty1( t, name, level-1 ); 672 } 673 } 674 675 #ifdef FLEXNAMES 676 char * 677 getstr(doport) 678 { 679 char buf[BUFSIZ]; 680 register char *cp = buf; 681 register int c; 682 683 if (feof(stdin) || ferror(stdin)) 684 return(""); 685 while ((c = getchar()) > 0) 686 *cp++ = c; 687 if (c < 0) { 688 error("intermediate file format error (getstr)"); 689 exit(1); 690 } 691 *cp++ = 0; 692 if (doport) 693 portify(buf); 694 return (hash(buf)); 695 } 696 697 #define NSAVETAB 4096 698 char *savetab; 699 int saveleft; 700 701 char * 702 savestr(cp) 703 register char *cp; 704 { 705 register int len; 706 707 len = strlen(cp) + 1; 708 if (len > saveleft) { 709 saveleft = NSAVETAB; 710 if (len > saveleft) 711 saveleft = len; 712 savetab = (char *)malloc(saveleft); 713 if (savetab == 0) { 714 error("ran out of memory (savestr)"); 715 exit(1); 716 } 717 } 718 strncpy(savetab, cp, len); 719 cp = savetab; 720 savetab += len; 721 saveleft -= len; 722 return (cp); 723 } 724 725 /* 726 * The definition for the segmented hash tables. 727 */ 728 #define MAXHASH 20 729 #define HASHINC 1013 730 struct ht { 731 char **ht_low; 732 char **ht_high; 733 int ht_used; 734 } htab[MAXHASH]; 735 736 char * 737 hash(s) 738 char *s; 739 { 740 register char **h; 741 register i; 742 register char *cp; 743 struct ht *htp; 744 int sh; 745 746 sh = hashstr(s) % HASHINC; 747 cp = s; 748 /* 749 * There are as many as MAXHASH active 750 * hash tables at any given point in time. 751 * The search starts with the first table 752 * and continues through the active tables 753 * as necessary. 754 */ 755 for (htp = htab; htp < &htab[MAXHASH]; htp++) { 756 if (htp->ht_low == 0) { 757 register char **hp = 758 (char **) calloc(sizeof (char **), HASHINC); 759 if (hp == 0) { 760 error("ran out of memory (hash)"); 761 exit(1); 762 } 763 htp->ht_low = hp; 764 htp->ht_high = htp->ht_low + HASHINC; 765 } 766 h = htp->ht_low + sh; 767 /* 768 * quadratic rehash increment 769 * starts at 1 and incremented 770 * by two each rehash. 771 */ 772 i = 1; 773 do { 774 if (*h == 0) { 775 if (htp->ht_used > (HASHINC * 3)/4) 776 break; 777 htp->ht_used++; 778 *h = savestr(cp); 779 return (*h); 780 } 781 if (**h == *cp && strcmp(*h, cp) == 0) 782 return (*h); 783 h += i; 784 i += 2; 785 if (h >= htp->ht_high) 786 h -= HASHINC; 787 } while (i < HASHINC); 788 } 789 error("ran out of hash tables"); 790 exit(1); 791 } 792 char *tstrbuf[1]; 793 #endif 794 795 #include "ctype.h" 796 797 portify(cp) 798 register char * cp; 799 { 800 register int i; 801 802 if (!pflag) 803 return; 804 for (i = 0; i < 6; ++i) 805 if (cp[i] == '\0') 806 return; 807 else if (isascii(cp[i]) && isupper(cp[i])) 808 cp[i] = tolower(cp[i]); 809 cp[i] = '\0'; 810 } 811