xref: /original-bsd/old/pcc/lint/lpass2/lpass2.c (revision f0fd5f8a)
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