1 2 #ifndef lint 3 static char sccsid[] = "@(#)lpass2.c 1.1 (Berkeley) 08/30/82"; 4 #endif lint 5 6 # include "manifest" 7 # include "lmanifest" 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 2048 16 # define TYSZ 3500 17 # define FSZ 250 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 66 int cfno; /* current file number */ 67 68 main( argc, argv ) char *argv[]; { 69 register char *p; 70 71 /* first argument is intermediate file */ 72 /* second argument is - options */ 73 74 for( ; argc>2 && argv[argc-1][0] == '-' ; --argc ){ 75 for( p=argv[argc-1]; *p; ++p ){ 76 switch( *p ){ 77 78 case 'h': 79 hflag = 1; 80 break; 81 82 case 'p': 83 pflag = 1; 84 break; 85 86 case 'x': 87 xflag = 1; 88 break; 89 90 case 'X': 91 ddddd = 1; 92 break; 93 94 case 'u': 95 uflag = 0; 96 break; 97 98 } 99 } 100 } 101 102 if( argc < 2 || !freopen( argv[1], "r", stdin ) ){ 103 error( "cannot open intermediate file" ); 104 exit( 1 ); 105 } 106 107 mloop( LDI|LIB ); 108 rewind( stdin ); 109 mloop( LDC|LDX ); 110 rewind( stdin ); 111 mloop( LRV|LUV|LUE|LUM ); 112 cleanup(); 113 return(0); 114 } 115 116 mloop( m ){ 117 /* do the main loop */ 118 register STAB *q; 119 120 while( lread(m) ){ 121 q = find(); 122 if( q->decflag ) chkcompat(q); 123 else setuse(q); 124 } 125 } 126 127 lread(m){ /* read a line into r.l */ 128 129 register n; 130 131 for(;;) { 132 if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0); 133 if( r.l.decflag & LFN ){ 134 /* new filename */ 135 #ifdef FLEXNAMES 136 r.f.fn = getstr(); 137 #endif 138 setfno( r.f.fn ); 139 continue; 140 } 141 #ifdef FLEXNAMES 142 r.l.name = getstr(); 143 #endif 144 145 n = r.l.nargs; 146 if( n<0 ) n = -n; 147 if( n ){ 148 if( n>=NTY ) error( "more than %d args?", n ); 149 fread( (char *)atyp, sizeof(ATYPE), n, stdin ); 150 } 151 if( ( r.l.decflag & m ) ) return( 1 ); 152 } 153 } 154 155 setfno( s ) char *s; { 156 /* look up current file names */ 157 /* first, strip backwards to the beginning or to the first / */ 158 int i; 159 160 /* now look up s */ 161 for( i=0; i<ffree; ++i ){ 162 #ifndef FLEXNAMES 163 if( !strncmp( s, fnm[i], LFNM ) ){ 164 #else 165 if (fnm[i] == s){ 166 #endif 167 cfno = i; 168 return; 169 } 170 } 171 /* make a new entry */ 172 if( ffree >= FSZ ) error( "more than %d files", FSZ ); 173 #ifndef FLEXNAMES 174 strncpy( fnm[ffree], s, LFNM ); 175 #else 176 fnm[ffree] = s; 177 #endif 178 cfno = ffree++; 179 } 180 181 /* VARARGS */ 182 error( s, a ) char *s; { 183 184 #ifndef FLEXNAMES 185 fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] ); 186 #else 187 fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] ); 188 #endif 189 fprintf( stderr, s, a ); 190 fprintf( stderr, "\n" ); 191 exit(1); 192 } 193 194 STAB * 195 find(){ 196 /* for this to work, NSZ should be a power of 2 */ 197 register h=0; 198 #ifndef FLEXNAMES 199 { register char *p, *q; 200 for( h=0,p=r.l.name,q=p+LCHNM; *p&&p<q; ++p) { 201 h = (h<<1)+ *p; 202 if( h>=NSZ ){ 203 h = (h+1)&(NSZ-1); 204 } 205 } 206 } 207 #else 208 h = ((int)r.l.name)%NSZ; 209 #endif 210 { register STAB *p, *q; 211 for( p=q= &stab[h]; q->decflag; ){ 212 /* this call to strncmp should be taken out... */ 213 #ifndef FLEXNAMES 214 if( !strncmp( r.l.name, q->name, LCHNM)) return(q); 215 #else 216 if (r.l.name == q->name) return (q); 217 #endif 218 if( ++q >= &stab[NSZ] ) q = stab; 219 if( q == p ) error( "too many names defined" ); 220 } 221 #ifndef FLEXNAMES 222 strncpy( q->name, r.l.name, LCHNM ); 223 #else 224 q->name = r.l.name; 225 #endif 226 return( q ); 227 } 228 } 229 230 STYPE * 231 tget(){ 232 if( tfree >= TYSZ ){ 233 error( "too many types needed" ); 234 } 235 return( &tary[tfree++] ); 236 } 237 238 chkcompat(q) STAB *q; { 239 /* are the types, etc. in r.l and q compatible */ 240 register int i; 241 STYPE *qq; 242 243 setuse(q); 244 245 /* argument check */ 246 247 if( q->decflag & (LDI|LIB|LUV|LUE) ){ 248 if( r.l.decflag & (LUV|LIB|LUE) ){ 249 if( q->nargs != r.l.nargs ){ 250 if( !(q->use&VARARGS) ){ 251 #ifndef FLEXNAMES 252 printf( "%.8s: variable # of args.", q->name ); 253 #else 254 printf( "%s: variable # of args.", q->name ); 255 #endif 256 viceversa(q); 257 } 258 if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs; 259 if( !(q->decflag & (LDI|LIB) ) ) { 260 q->nargs = r.l.nargs; 261 q->use |= VARARGS; 262 } 263 } 264 for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){ 265 if( chktype( &qq->t, &atyp[i] ) ){ 266 #ifndef FLEXNAMES 267 printf( "%.8s, arg. %d used inconsistently", 268 #else 269 printf( "%s, arg. %d used inconsistently", 270 #endif 271 q->name, i+1 ); 272 viceversa(q); 273 } 274 } 275 } 276 } 277 278 if( (q->decflag&(LDI|LIB|LUV)) && r.l.decflag==LUV ){ 279 if( chktype( &r.l.type, &q->symty.t ) ){ 280 #ifndef FLEXNAMES 281 printf( "%.8s value used inconsistently", q->name ); 282 #else 283 printf( "%s value used inconsistently", q->name ); 284 #endif 285 viceversa(q); 286 } 287 } 288 289 /* check for multiple declaration */ 290 291 if( (q->decflag&LDI) && (r.l.decflag&(LDI|LIB)) ){ 292 #ifndef FLEXNAMES 293 printf( "%.8s multiply declared", q->name ); 294 #else 295 printf( "%s multiply declared", q->name ); 296 #endif 297 viceversa(q); 298 } 299 300 /* do a bit of checking of definitions and uses... */ 301 302 if( (q->decflag & (LDI|LIB|LDX|LDC|LUM)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){ 303 #ifndef FLEXNAMES 304 printf( "%.8s value declared inconsistently", q->name ); 305 #else 306 printf( "%s value declared inconsistently", q->name ); 307 #endif 308 viceversa(q); 309 } 310 311 /* better not call functions which are declared to be structure or union returning */ 312 313 if( (q->decflag & (LDI|LIB|LDX|LDC)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){ 314 /* only matters if the function returns union or structure */ 315 TWORD ty; 316 ty = q->symty.t.aty; 317 if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){ 318 #ifndef FLEXNAMES 319 printf( "%.8s function value type must be declared before use", q->name ); 320 #else 321 printf( "%s function value type must be declared before use", q->name ); 322 #endif 323 viceversa(q); 324 } 325 } 326 327 if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){ 328 /* make the external declaration go away */ 329 /* in effect, it was used without being defined */ 330 } 331 } 332 333 viceversa(q) STAB *q; { 334 /* print out file comparison */ 335 #ifndef FLEXNAMES 336 printf( " %.*s(%d) :: %.*s(%d)\n", 337 LFNM, fnm[q->fno], q->fline, 338 LFNM, fnm[cfno], r.l.fline ); 339 #else 340 printf( " %s(%d) :: %s(%d)\n", 341 fnm[q->fno], q->fline, 342 fnm[cfno], r.l.fline ); 343 #endif 344 } 345 346 /* messages for defintion/use */ 347 char * 348 mess[2][2] ={ 349 "", 350 #ifndef FLEXNAMES 351 "%.8s used( %.*s(%d) ), but not defined\n", 352 "%.8s defined( %.*s(%d) ), but never used\n", 353 "%.8s declared( %.*s(%d) ), but never used or defined\n" 354 #else 355 "%s used( %s(%d) ), but not defined\n", 356 "%s defined( %s(%d) ), but never used\n", 357 "%s declared( %s(%d) ), but never used or defined\n" 358 #endif 359 }; 360 361 lastone(q) STAB *q; { 362 363 register nu, nd, uses; 364 365 if( ddddd ) pst(q); 366 367 nu = nd = 0; 368 uses = q->use; 369 370 if( !(uses&USED) && q->decflag != LIB ) { 371 #ifndef FLEXNAMES 372 if( strncmp(q->name,"main",7) ) 373 #else 374 if (strcmp(q->name, "main")) 375 #endif 376 nu = 1; 377 } 378 379 if( !ISFTN(q->symty.t.aty) ){ 380 switch( q->decflag ){ 381 382 case LIB: 383 nu = nd = 0; /* don't complain about uses on libraries */ 384 break; 385 case LDX: 386 if( !xflag ) break; 387 case LUV: 388 case LUE: 389 /* 01/04/80 */ case LUV | LUE: 390 case LUM: 391 nd = 1; 392 } 393 } 394 if( uflag && ( nu || nd ) ) printf( mess[nu][nd], 395 #ifndef FLEXNAMES 396 q->name, LFNM, fnm[q->fno], q->fline ); 397 #else 398 q->name, fnm[q->fno], q->fline ); 399 #endif 400 401 if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){ 402 #ifndef FLEXNAMES 403 printf( "%.8s returns value which is %s ignored\n", q->name, 404 #else 405 printf( "%s returns value which is %s ignored\n", q->name, 406 #endif 407 uses&VUSED ? "sometimes" : "always" ); 408 } 409 410 if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB)) ){ 411 #ifndef FLEXNAMES 412 printf( "%.8s value is used, but none returned\n", q->name ); 413 #else 414 printf( "%s value is used, but none returned\n", q->name ); 415 #endif 416 } 417 } 418 419 cleanup(){ /* call lastone and die gracefully */ 420 STAB *q; 421 for( q=stab; q< &stab[NSZ]; ++q ){ 422 if( q->decflag ) lastone(q); 423 } 424 exit(0); 425 } 426 427 setuse(q) STAB *q; { /* check new type to ensure that it is used */ 428 429 if( !q->decflag ){ /* new one */ 430 q->decflag = r.l.decflag; 431 q->symty.t = r.l.type; 432 if( r.l.nargs < 0 ){ 433 q->nargs = -r.l.nargs; 434 q->use = VARARGS; 435 } 436 else { 437 q->nargs = r.l.nargs; 438 q->use = 0; 439 } 440 q->fline = r.l.fline; 441 q->fno = cfno; 442 if( q->nargs ){ 443 int i; 444 STYPE *qq; 445 for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){ 446 qq->next = tget(); 447 qq->next->t = atyp[i]; 448 } 449 } 450 } 451 452 switch( r.l.decflag ){ 453 454 case LRV: 455 q->use |= RVAL; 456 return; 457 case LUV: 458 q->use |= VUSED+USED; 459 return; 460 case LUE: 461 q->use |= EUSED+USED; 462 return; 463 /* 01/04/80 */ case LUV | LUE: 464 case LUM: 465 q->use |= USED; 466 return; 467 468 } 469 } 470 471 chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; { 472 TWORD t; 473 474 /* check the two type words to see if they are compatible */ 475 /* for the moment, enums are turned into ints, and should be checked as such */ 476 if( pt1->aty == ENUMTY ) pt1->aty = INT; 477 if( pt2->aty == ENUMTY ) pt2->aty = INT; 478 479 if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){ 480 return( pt1->aty!=pt2->aty || ( 481 pt1->extra!=pt2->extra ) ); 482 } 483 484 if( pt2->extra ){ /* constant passed in */ 485 if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 ); 486 else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 ); 487 } 488 else if( pt1->extra ){ /* for symmetry */ 489 if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 ); 490 else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 ); 491 } 492 493 return( pt1->aty != pt2->aty ); 494 } 495 496 struct tb { int m; char * nm }; 497 ptb( v, tp ) struct tb *tp; { 498 /* print a value from the table */ 499 int flag; 500 flag = 0; 501 for( ; tp->m; ++tp ){ 502 if( v&tp->m ){ 503 if( flag++ ) putchar( '|' ); 504 printf( "%s", tp->nm ); 505 } 506 } 507 } 508 509 pst( q ) STAB *q; { 510 /* give a debugging output for q */ 511 static struct tb dfs[] = { 512 LDI, "LDI", 513 LIB, "LIB", 514 LDC, "LDC", 515 LDX, "LDX", 516 LRV, "LRV", 517 LUV, "LUV", 518 LUE, "LUE", 519 LUM, "LUM", 520 0, "" }; 521 522 static struct tb us[] = { 523 USED, "USED", 524 VUSED, "VUSED", 525 EUSED, "EUSED", 526 RVAL, "RVAL", 527 VARARGS, "VARARGS", 528 0, 0, 529 }; 530 531 #ifndef FLEXNAMES 532 printf( "%.8s (", q->name ); 533 #else 534 printf( "%s (", q->name ); 535 #endif 536 ptb( q->decflag, dfs ); 537 printf( "), use= " ); 538 ptb( q->use, us ); 539 printf( ", line %d, nargs=%d\n", q->fline, q->nargs ); 540 } 541 542 #ifdef FLEXNAMES 543 char * 544 getstr() 545 { 546 char buf[BUFSIZ]; 547 register char *cp = buf; 548 register int c; 549 550 if (feof(stdin) || ferror(stdin)) 551 return(""); 552 while ((c = getchar()) > 0) 553 *cp++ = c; 554 if (c < 0) { 555 fprintf(stderr, "pass 2 error: intermediate file format error (getstr)"); 556 exit(1); 557 } 558 *cp++ = 0; 559 return (hash(buf)); 560 } 561 562 #define NSAVETAB 4096 563 char *savetab; 564 int saveleft; 565 566 char * 567 savestr(cp) 568 register char *cp; 569 { 570 register int len; 571 572 len = strlen(cp) + 1; 573 if (len > saveleft) { 574 saveleft = NSAVETAB; 575 if (len > saveleft) 576 saveleft = len; 577 savetab = (char *)malloc(saveleft); 578 if (savetab == 0) { 579 fprintf(stderr, "pass 2 error: ran out of memory (savestr)"); 580 exit(1); 581 } 582 } 583 strncpy(savetab, cp, len); 584 cp = savetab; 585 savetab += len; 586 saveleft -= len; 587 return (cp); 588 } 589 590 /* 591 * The definition for the segmented hash tables. 592 */ 593 #define MAXHASH 20 594 #define HASHINC 1013 595 struct ht { 596 char **ht_low; 597 char **ht_high; 598 int ht_used; 599 } htab[MAXHASH]; 600 601 char * 602 hash(s) 603 char *s; 604 { 605 register char **h; 606 register i; 607 register char *cp; 608 struct ht *htp; 609 int sh; 610 611 /* 612 * The hash function is a modular hash of 613 * the sum of the characters with the sum 614 * doubled before each successive character 615 * is added. 616 */ 617 cp = s; 618 i = 0; 619 while (*cp) 620 i = i*2 + *cp++; 621 sh = (i&077777) % HASHINC; 622 cp = s; 623 /* 624 * There are as many as MAXHASH active 625 * hash tables at any given point in time. 626 * The search starts with the first table 627 * and continues through the active tables 628 * as necessary. 629 */ 630 for (htp = htab; htp < &htab[MAXHASH]; htp++) { 631 if (htp->ht_low == 0) { 632 register char **hp = 633 (char **) calloc(sizeof (char **), HASHINC); 634 if (hp == 0) { 635 fprintf(stderr, "pass 2 error: ran out of memory (hash)"); 636 exit(1); 637 } 638 htp->ht_low = hp; 639 htp->ht_high = htp->ht_low + HASHINC; 640 } 641 h = htp->ht_low + sh; 642 /* 643 * quadratic rehash increment 644 * starts at 1 and incremented 645 * by two each rehash. 646 */ 647 i = 1; 648 do { 649 if (*h == 0) { 650 if (htp->ht_used > (HASHINC * 3)/4) 651 break; 652 htp->ht_used++; 653 *h = savestr(cp); 654 return (*h); 655 } 656 if (**h == *cp && strcmp(*h, cp) == 0) 657 return (*h); 658 h += i; 659 i += 2; 660 if (h >= htp->ht_high) 661 h -= HASHINC; 662 } while (i < HASHINC); 663 } 664 fprintf(stderr, "pass 2 error: ran out of hash tables"); 665 exit(1); 666 } 667 char *tstrbuf[1]; 668 #endif 669