1 #ifndef lint
2 static char sccsid[] = "@(#)lpass2.c 1.12 (Berkeley) 05/12/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
main(argc,argv)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
mloop(m)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
lread(m)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
setfno(s)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 */
error(s,a)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 *
find()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 *
tget()238 tget(){
239 if( tfree >= TYSZ ){
240 error( "too many types needed" );
241 }
242 return( &tary[tfree++] );
243 }
244
chkcompat(q)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
viceversa(q)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
lastone(q)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
cleanup()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
setuse(q)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
chktype(pt1,pt2,fno)493 chktype( pt1, pt2, fno ) 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 /* if -p and pt1 is "too big" and
508 ** pt1 came from a llib-l file, we can't pass judgment on it.
509 */
510 if ( pflag && pt1->extra > pt2->extra &&
511 strncmp(fnm[fno], "llib-l", 6) == 0)
512 return 0;
513 return pt1->extra != pt2->extra;
514 }
515
516 if( pt2->extra ){ /* constant passed in */
517 if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
518 else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
519 }
520 else if( pt1->extra ){ /* for symmetry */
521 if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
522 else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
523 }
524
525 return( pt1->aty != pt2->aty );
526 }
527
528 struct tb { int m; char *nm; };
529
530 struct tb dfs[] = {
531 LDI, "LDI",
532 LIB, "LIB",
533 LDC, "LDC",
534 LDX, "LDX",
535 LRV, "LRV",
536 LUV, "LUV",
537 LUE, "LUE",
538 LUM, "LUM",
539 LST, "LST",
540 LFN, "LFN",
541 0, "" };
542
543 struct tb us[] = {
544 USED, "USED",
545 VUSED, "VUSED",
546 EUSED, "EUSED",
547 RVAL, "RVAL",
548 VARARGS, "VARARGS",
549 0, "" };
550
551 ptb( v, tp ) struct tb *tp; {
552 /* print a value from the table */
553 int flag;
554 flag = 0;
555 for( ; tp->m; ++tp ){
556 if( v&tp->m ){
557 if( flag++ ) putchar( '|' );
558 printf( "%s", tp->nm );
559 }
560 }
561 }
562
pst(q)563 pst( q ) STAB *q; {
564 /* give a debugging output for q */
565
566 #ifndef FLEXNAMES
567 printf( "%.8s (", q->name );
568 #else
569 printf( "%s (", q->name );
570 #endif
571 ptb( q->decflag, dfs );
572 printf( "), use= " );
573 ptb( q->use, us );
574 printf( ", line %d, nargs=%d\n", q->fline, q->nargs );
575 }
576
pfile()577 pfile() {
578 /* print the input file in readable form */
579 while( lread( LDI|LIB|LDC|LDX|LRV|LUV|LUE|LUM|LST|LFN ) )
580 prc();
581 }
582
prc()583 prc() {
584 /* print out 'r' for debugging */
585 register i, j, k;
586
587 printf( "decflag\t" );
588 ptb( r.l.decflag, dfs );
589 putchar( '\n' );
590 if( r.l.decflag & LFN ){
591 #ifdef FLEXNAMES
592 printf( "fn\t\t%s\n", r.f.fn );
593 #else
594 printf( "fn\t%\t.*s\n", LFNM, r.f.fn );
595 #endif
596 }
597 else {
598 #ifdef FLEXNAMES
599 printf( "name\t%s\n", r.l.name );
600 #else
601 printf( "name\t%.*s\n", LCHNM, r.l.name );
602 #endif
603 printf( "nargs\t%d\n", r.l.nargs );
604 printf( "fline\t%d\n", r.l.fline );
605 printf( "type.aty\t0%o (", r.l.type.aty );
606 pty( r.l.type.aty, r.l.name );
607 printf( ")\ntype.extra\t%d\n", r.l.type.extra );
608 j = r.l.type.extra1;
609 printf( "type.extra1\t0x%x (%d,%d)\n",
610 j, j & X_NONAME ? 1 : 0, j & ~X_NONAME );
611 k = r.l.nargs;
612 if( k < 0 ) k = ~k;
613 for( i = 0; i < k; i++ ){
614 printf( "atyp[%d].aty\t0%o (", i, atyp[i].aty );
615 pty( atyp[i].aty, "" );
616 printf( ")\natyp[%d].extra\t%d\n", i, atyp[i].extra);
617 j = atyp[i].extra1;
618 printf( "atyp[%d].extra1\t0x%x (%d,%d)\n",
619 i, j, j & X_NONAME ? 1 : 0, j & ~X_NONAME );
620 }
621 }
622 putchar( '\n' );
623 }
624
pty(t,name)625 pty( t, name ) TWORD t; {
626 static char * tnames[] = {
627 "void", "farg", "char", "short",
628 "int", "long", "float", "double",
629 "struct xxx", "union %s", "enum", "moety",
630 "unsigned char", "unsigned short", "unsigned", "unsigned long",
631 "?", "?"
632 };
633
634 printf( "%s ", tnames[BTYPE(t)] );
635 pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT );
636 }
637
pty1(t,name,level)638 pty1( t, name, level ) TWORD t; {
639 register TWORD u;
640
641 if( level < 0 ){
642 printf( "%s", name );
643 return;
644 }
645 u = t >> level * TSHIFT;
646 if( ISPTR(u) ){
647 printf( "*" );
648 pty1( t, name, level-1 );
649 }
650 else if( ISFTN(u) ){
651 if( level > 0 && ISPTR(u << TSHIFT) ){
652 printf( "(" );
653 pty1( t, name, level-1 );
654 printf( ")()" );
655 }
656 else {
657 pty1( t, name, level-1 );
658 printf( "()" );
659 }
660 }
661 else if( ISARY(u) ){
662 if( level > 0 && ISPTR(u << TSHIFT) ){
663 printf( "(" );
664 pty1( t, name, level-1 );
665 printf( ")[]" );
666 }
667 else {
668 pty1( t, name, level-1 );
669 printf( "[]" );
670 }
671 }
672 else {
673 pty1( t, name, level-1 );
674 }
675 }
676
677 #ifdef FLEXNAMES
678 char *
getstr(doport)679 getstr(doport)
680 {
681 char buf[BUFSIZ];
682 register char *cp = buf;
683 register int c;
684
685 if (feof(stdin) || ferror(stdin))
686 return("");
687 while ((c = getchar()) > 0)
688 *cp++ = c;
689 if (c < 0) {
690 error("intermediate file format error (getstr)");
691 exit(1);
692 }
693 *cp++ = 0;
694 if (doport)
695 portify(buf);
696 return (hash(buf));
697 }
698
699 #define NSAVETAB 4096
700 char *savetab;
701 int saveleft;
702
703 char *
savestr(cp)704 savestr(cp)
705 register char *cp;
706 {
707 register int len;
708
709 len = strlen(cp) + 1;
710 if (len > saveleft) {
711 saveleft = NSAVETAB;
712 if (len > saveleft)
713 saveleft = len;
714 savetab = (char *)malloc(saveleft);
715 if (savetab == 0) {
716 error("ran out of memory (savestr)");
717 exit(1);
718 }
719 }
720 strncpy(savetab, cp, len);
721 cp = savetab;
722 savetab += len;
723 saveleft -= len;
724 return (cp);
725 }
726
727 /*
728 * The definition for the segmented hash tables.
729 */
730 #define MAXHASH 20
731 #define HASHINC 1013
732 struct ht {
733 char **ht_low;
734 char **ht_high;
735 int ht_used;
736 } htab[MAXHASH];
737
738 char *
hash(s)739 hash(s)
740 char *s;
741 {
742 register char **h;
743 register i;
744 register char *cp;
745 struct ht *htp;
746 int sh;
747
748 sh = hashstr(s) % HASHINC;
749 cp = s;
750 /*
751 * There are as many as MAXHASH active
752 * hash tables at any given point in time.
753 * The search starts with the first table
754 * and continues through the active tables
755 * as necessary.
756 */
757 for (htp = htab; htp < &htab[MAXHASH]; htp++) {
758 if (htp->ht_low == 0) {
759 register char **hp =
760 (char **) calloc(sizeof (char **), HASHINC);
761 if (hp == 0) {
762 error("ran out of memory (hash)");
763 exit(1);
764 }
765 htp->ht_low = hp;
766 htp->ht_high = htp->ht_low + HASHINC;
767 }
768 h = htp->ht_low + sh;
769 /*
770 * quadratic rehash increment
771 * starts at 1 and incremented
772 * by two each rehash.
773 */
774 i = 1;
775 do {
776 if (*h == 0) {
777 if (htp->ht_used > (HASHINC * 3)/4)
778 break;
779 htp->ht_used++;
780 *h = savestr(cp);
781 return (*h);
782 }
783 if (**h == *cp && strcmp(*h, cp) == 0)
784 return (*h);
785 h += i;
786 i += 2;
787 if (h >= htp->ht_high)
788 h -= HASHINC;
789 } while (i < HASHINC);
790 }
791 error("ran out of hash tables");
792 exit(1);
793 }
794 char *tstrbuf[1];
795 #endif
796
797 #include "ctype.h"
798
portify(cp)799 portify(cp)
800 register char * cp;
801 {
802 register int i;
803
804 if (!pflag)
805 return;
806 for (i = 0; i < 6; ++i)
807 if (cp[i] == '\0')
808 return;
809 else if (isascii(cp[i]) && isupper(cp[i]))
810 cp[i] = tolower(cp[i]);
811 cp[i] = '\0';
812 }
813