1 #ifndef lint 2 static char sccsid[] = "@(#)lpass2.c 1.7 (Berkeley) 04/22/87"; 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 (r.l.name == q->name) 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] ) ){ 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 ) ){ 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 if( !ISFTN(q->symty.t.aty) ){ 387 switch( q->decflag ){ 388 389 case LIB: 390 nu = nd = 0; /* don't complain about uses on libraries */ 391 break; 392 case LDX: 393 if( !xflag ) break; 394 case LUV: 395 case LUE: 396 /* 01/04/80 */ case LUV | LUE: 397 case LUM: 398 nd = 1; 399 } 400 } 401 if( uflag && ( nu || nd ) ) 402 #ifndef FLEXNAMES 403 printf( mess[nu][nd], q->name, LFNM, fnm[q->fno], q->fline ); 404 #else 405 printf( mess[nu][nd], q->name, fnm[q->fno], q->fline ); 406 #endif 407 408 if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){ 409 /* if functions is static, then print the file name too */ 410 if( q->decflag & LST ) 411 #ifndef FLEXNAMES 412 printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline ); 413 #else 414 printf( "%s(%d):", fnm[q->fno], q->fline ); 415 #endif 416 #ifndef FLEXNAMES 417 printf( "%.*s returns value which is %s ignored\n", 418 LCHNM, q->name, uses&VUSED ? "sometimes" : "always" ); 419 #else 420 printf( "%s returns value which is %s ignored\n", 421 q->name, uses&VUSED ? "sometimes" : "always" ); 422 #endif 423 } 424 425 if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB|LST)) ){ 426 if( q->decflag & LST ) 427 #ifndef FLEXNAMES 428 printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline ); 429 #else 430 printf( "%s(%d):", fnm[q->fno], q->fline ); 431 #endif 432 #ifndef FLEXNAMES 433 printf( "%.*s value is used, but none returned\n", 434 LCHNM, q->name); 435 #else 436 printf( "%s value is used, but none returned\n", q->name); 437 #endif 438 } 439 } 440 441 cleanup(){ /* call lastone and die gracefully */ 442 STAB *q; 443 for( q=stab; q< &stab[NSZ]; ++q ){ 444 if( q->decflag ) lastone(q); 445 } 446 exit(0); 447 } 448 449 setuse(q) STAB *q; { /* check new type to ensure that it is used */ 450 451 if( !q->decflag ){ /* new one */ 452 q->decflag = r.l.decflag; 453 q->symty.t = r.l.type; 454 if( r.l.nargs < 0 ){ 455 q->nargs = -r.l.nargs; 456 q->use = VARARGS; 457 } 458 else { 459 q->nargs = r.l.nargs; 460 q->use = 0; 461 } 462 q->fline = r.l.fline; 463 q->fno = cfno; 464 if( q->nargs ){ 465 int i; 466 STYPE *qq; 467 for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){ 468 qq->next = tget(); 469 qq->next->t = atyp[i]; 470 } 471 } 472 } 473 474 switch( r.l.decflag ){ 475 476 case LRV: 477 q->use |= RVAL; 478 return; 479 case LUV: 480 q->use |= VUSED+USED; 481 return; 482 case LUE: 483 q->use |= EUSED+USED; 484 return; 485 /* 01/04/80 */ case LUV | LUE: 486 case LUM: 487 q->use |= USED; 488 return; 489 490 } 491 } 492 493 chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; { 494 TWORD t; 495 496 /* check the two type words to see if they are compatible */ 497 /* for the moment, enums are turned into ints, and should be checked as such */ 498 if( pt1->aty == ENUMTY ) pt1->aty = INT; 499 if( pt2->aty == ENUMTY ) pt2->aty = INT; 500 501 if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){ 502 if( pt1->aty != pt2->aty || pt1->extra1 != pt2->extra1 ) 503 return 1; 504 /* if -z then don't worry about undefined structures, 505 as long as the names match */ 506 if( zflag && (pt1->extra == 0 || pt2->extra == 0) ) return 0; 507 return pt1->extra != pt2->extra; 508 } 509 510 if( pt2->extra ){ /* constant passed in */ 511 if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 ); 512 else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 ); 513 } 514 else if( pt1->extra ){ /* for symmetry */ 515 if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 ); 516 else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 ); 517 } 518 519 return( pt1->aty != pt2->aty ); 520 } 521 522 struct tb { int m; char * nm }; 523 524 struct tb dfs[] = { 525 LDI, "LDI", 526 LIB, "LIB", 527 LDC, "LDC", 528 LDX, "LDX", 529 LRV, "LRV", 530 LUV, "LUV", 531 LUE, "LUE", 532 LUM, "LUM", 533 LST, "LST", 534 LFN, "LFN", 535 0, "" }; 536 537 struct tb us[] = { 538 USED, "USED", 539 VUSED, "VUSED", 540 EUSED, "EUSED", 541 RVAL, "RVAL", 542 VARARGS, "VARARGS", 543 0, "" }; 544 545 ptb( v, tp ) struct tb *tp; { 546 /* print a value from the table */ 547 int flag; 548 flag = 0; 549 for( ; tp->m; ++tp ){ 550 if( v&tp->m ){ 551 if( flag++ ) putchar( '|' ); 552 printf( "%s", tp->nm ); 553 } 554 } 555 } 556 557 pst( q ) STAB *q; { 558 /* give a debugging output for q */ 559 560 #ifndef FLEXNAMES 561 printf( "%.8s (", q->name ); 562 #else 563 printf( "%s (", q->name ); 564 #endif 565 ptb( q->decflag, dfs ); 566 printf( "), use= " ); 567 ptb( q->use, us ); 568 printf( ", line %d, nargs=%d\n", q->fline, q->nargs ); 569 } 570 571 pfile() { 572 /* print the input file in readable form */ 573 while( lread( LDI|LIB|LDC|LDX|LRV|LUV|LUE|LUM|LST|LFN ) ) 574 prc(); 575 } 576 577 prc() { 578 /* print out 'r' for debugging */ 579 register i, j, k; 580 581 printf( "decflag\t" ); 582 ptb( r.l.decflag, dfs ); 583 putchar( '\n' ); 584 if( r.l.decflag & LFN ){ 585 #ifdef FLEXNAMES 586 printf( "fn\t\t%s\n", r.f.fn ); 587 #else 588 printf( "fn\t%\t.*s\n", LFNM, r.f.fn ); 589 #endif 590 } 591 else { 592 #ifdef FLEXNAMES 593 printf( "name\t%s\n", r.l.name ); 594 #else 595 printf( "name\t%.*s\n", LCHNM, r.l.name ); 596 #endif 597 printf( "nargs\t%d\n", r.l.nargs ); 598 printf( "fline\t%d\n", r.l.fline ); 599 printf( "type.aty\t0%o (", r.l.type.aty ); 600 pty( r.l.type.aty, r.l.name ); 601 printf( ")\ntype.extra\t%d\n", r.l.type.extra ); 602 j = r.l.type.extra1; 603 printf( "type.extra1\t0x%x (%d,%d)\n", 604 j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 605 k = r.l.nargs; 606 if( k < 0 ) k = -k; 607 for( i = 0; i < k; i++ ){ 608 printf( "atyp[%d].aty\t0%o (", i, atyp[i].aty ); 609 pty( atyp[i].aty, "" ); 610 printf( ")\natyp[%d].extra\t%d\n", i, atyp[i].extra); 611 j = atyp[i].extra1; 612 printf( "atyp[%d].extra1\t0x%x (%d,%d)\n", 613 i, j, j & X_NONAME ? 1 : 0, j & ~X_NONAME ); 614 } 615 } 616 putchar( '\n' ); 617 } 618 619 pty( t, name ) TWORD t; { 620 static char * tnames[] = { 621 "void", "farg", "char", "short", 622 "int", "long", "float", "double", 623 "struct xxx", "union %s", "enum", "moety", 624 "unsigned char", "unsigned short", "unsigned", "unsigned long", 625 "?", "?" 626 }; 627 628 printf( "%s ", tnames[BTYPE(t)] ); 629 pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT ); 630 } 631 632 pty1( t, name, level ) TWORD t; { 633 register TWORD u; 634 635 if( level < 0 ){ 636 printf( "%s", name ); 637 return; 638 } 639 u = t >> level * TSHIFT; 640 if( ISPTR(u) ){ 641 printf( "*" ); 642 pty1( t, name, level-1 ); 643 } 644 else if( ISFTN(u) ){ 645 if( level > 0 && ISPTR(u << TSHIFT) ){ 646 printf( "(" ); 647 pty1( t, name, level-1 ); 648 printf( ")()" ); 649 } 650 else { 651 pty1( t, name, level-1 ); 652 printf( "()" ); 653 } 654 } 655 else if( ISARY(u) ){ 656 if( level > 0 && ISPTR(u << TSHIFT) ){ 657 printf( "(" ); 658 pty1( t, name, level-1 ); 659 printf( ")[]" ); 660 } 661 else { 662 pty1( t, name, level-1 ); 663 printf( "[]" ); 664 } 665 } 666 else { 667 pty1( t, name, level-1 ); 668 } 669 } 670 671 #ifdef FLEXNAMES 672 char * 673 getstr(doport) 674 { 675 char buf[BUFSIZ]; 676 register char *cp = buf; 677 register int c; 678 679 if (feof(stdin) || ferror(stdin)) 680 return(""); 681 while ((c = getchar()) > 0) 682 *cp++ = c; 683 if (c < 0) { 684 error("intermediate file format error (getstr)"); 685 exit(1); 686 } 687 *cp++ = 0; 688 if (doport) 689 portify(buf); 690 return (hash(buf)); 691 } 692 693 #define NSAVETAB 4096 694 char *savetab; 695 int saveleft; 696 697 char * 698 savestr(cp) 699 register char *cp; 700 { 701 register int len; 702 703 len = strlen(cp) + 1; 704 if (len > saveleft) { 705 saveleft = NSAVETAB; 706 if (len > saveleft) 707 saveleft = len; 708 savetab = (char *)malloc(saveleft); 709 if (savetab == 0) { 710 error("ran out of memory (savestr)"); 711 exit(1); 712 } 713 } 714 strncpy(savetab, cp, len); 715 cp = savetab; 716 savetab += len; 717 saveleft -= len; 718 return (cp); 719 } 720 721 /* 722 * The definition for the segmented hash tables. 723 */ 724 #define MAXHASH 20 725 #define HASHINC 1013 726 struct ht { 727 char **ht_low; 728 char **ht_high; 729 int ht_used; 730 } htab[MAXHASH]; 731 732 char * 733 hash(s) 734 char *s; 735 { 736 register char **h; 737 register i; 738 register char *cp; 739 struct ht *htp; 740 int sh; 741 742 sh = hashstr(s) % HASHINC; 743 cp = s; 744 /* 745 * There are as many as MAXHASH active 746 * hash tables at any given point in time. 747 * The search starts with the first table 748 * and continues through the active tables 749 * as necessary. 750 */ 751 for (htp = htab; htp < &htab[MAXHASH]; htp++) { 752 if (htp->ht_low == 0) { 753 register char **hp = 754 (char **) calloc(sizeof (char **), HASHINC); 755 if (hp == 0) { 756 error("ran out of memory (hash)"); 757 exit(1); 758 } 759 htp->ht_low = hp; 760 htp->ht_high = htp->ht_low + HASHINC; 761 } 762 h = htp->ht_low + sh; 763 /* 764 * quadratic rehash increment 765 * starts at 1 and incremented 766 * by two each rehash. 767 */ 768 i = 1; 769 do { 770 if (*h == 0) { 771 if (htp->ht_used > (HASHINC * 3)/4) 772 break; 773 htp->ht_used++; 774 *h = savestr(cp); 775 return (*h); 776 } 777 if (**h == *cp && strcmp(*h, cp) == 0) 778 return (*h); 779 h += i; 780 i += 2; 781 if (h >= htp->ht_high) 782 h -= HASHINC; 783 } while (i < HASHINC); 784 } 785 error("ran out of hash tables"); 786 exit(1); 787 } 788 char *tstrbuf[1]; 789 #endif 790 791 #include "ctype.h" 792 793 portify(cp) 794 register char * cp; 795 { 796 register int i; 797 798 if (!pflag) 799 return; 800 for (i = 0; i < 6; ++i) 801 if (cp[i] == '\0') 802 return; 803 else if (isascii(cp[i]) && isupper(cp[i])) 804 cp[i] = tolower(cp[i]); 805 cp[i] = '\0'; 806 } 807