1 #ifndef lint
2 static char sccsid[] = "@(#)lint.c 1.14 (Berkeley) 12/11/87";
3 #endif lint
4
5 # include "pass1.h"
6
7 # include "lmanifest.h"
8
9 # include <ctype.h>
10
11 # define VAL 0
12 # define EFF 1
13
14 /* these are appropriate for the -p flag */
15 int SZCHAR = 8;
16 int SZINT = 16;
17 int SZFLOAT = 32;
18 int SZDOUBLE = 64;
19 int SZLONG = 32;
20 int SZSHORT = 16;
21 int SZPOINT = 16;
22 int ALCHAR = 8;
23 int ALINT = 16;
24 int ALFLOAT = 32;
25 int ALDOUBLE = 64;
26 int ALLONG = 32;
27 int ALSHORT = 16;
28 int ALPOINT = 16;
29 int ALSTRUCT = 16;
30
31 int nflag = 0; /* avoid gripes about printf et al. */
32 int vflag = 1; /* tell about unused argments */
33 int xflag = 0; /* tell about unused externals */
34 int argflag = 0; /* used to turn off complaints about arguments */
35 int libflag = 0; /* used to generate library descriptions */
36 int vaflag = -1; /* signal functions with a variable number of args */
37 int aflag = 0; /* used to check precision of assignments */
38 int zflag = 0; /* no 'structure never defined' error */
39 int Cflag = 0; /* filter out certain output, for generating libraries */
40 char *libname = 0; /* name of the library we're generating */
41
42 /* flags for the "outdef" function */
43 # define USUAL (-101)
44 # define DECTY (-102)
45 # define NOFILE (-103)
46 # define SVLINE (-104)
47
48 # define LNAMES 250
49
50 struct lnm {
51 short lid, flgs;
52 } lnames[LNAMES], *lnp;
53
contx(p,down,pl,pr)54 contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; {
55
56 *pl = *pr = VAL;
57 switch( p->in.op ){
58
59 case ANDAND:
60 case OROR:
61 case QUEST:
62 *pr = down;
63 break;
64
65 case SCONV:
66 case PCONV:
67 case COLON:
68 *pr = *pl = down;
69 break;
70
71 case COMOP:
72 *pl = EFF;
73 *pr = down;
74
75 case FORCE:
76 case INIT:
77 case UNARY CALL:
78 case STCALL:
79 case UNARY STCALL:
80 case CALL:
81 case UNARY FORTCALL:
82 case FORTCALL:
83 case CBRANCH:
84 break;
85
86 default:
87 if( asgop(p->in.op) ) break;
88 if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) {
89 /* struct x f( ); main( ) { (void) f( ); }
90 * the the cast call appears as U* UNDEF
91 */
92 break; /* the compiler does this... */
93 }
94 if( down == EFF && hflag ) werror( "null effect" );
95
96 }
97 }
98
ecode(p)99 ecode( p ) NODE *p; {
100 /* compile code for p */
101
102 fwalk( p, contx, EFF );
103 lnp = lnames;
104 lprt( p, EFF, 0 );
105 strforget();
106 }
107
ejobcode(flag)108 ejobcode( flag ){
109 /* called after processing each job */
110 /* flag is nonzero if errors were detected */
111 register k;
112 register struct symtab *p;
113
114 for( p=stab; p< &stab[SYMTSZ]; ++p ){
115
116 if( p->stype != TNULL ) {
117
118 if( p->stype == STRTY || p->stype == UNIONTY ){
119 if( !zflag && dimtab[p->sizoff+1] < 0 ){
120 /* never defined */
121 #ifndef FLEXNAMES
122 if( hflag ) werror( "struct/union %.8s never defined", p->sname );
123 #else
124 if( hflag ) werror( "struct/union %s never defined", p->sname );
125 #endif
126 }
127 }
128
129 switch( p->sclass ){
130
131 case STATIC:
132 if( p->suse > 0 ){
133 k = lineno;
134 lineno = p->suse;
135 #ifndef FLEXNAMES
136 uerror( "static variable %.8s unused",
137 #else
138 uerror( "static variable %s unused",
139 #endif
140 p->sname );
141 lineno = k;
142 break;
143 }
144 /* no statics in libraries */
145 if( Cflag ) break;
146
147 case EXTERN:
148 case USTATIC:
149 /* with the xflag, worry about externs not used */
150 /* the filename may be wrong here... */
151 if( xflag && p->suse >= 0 && !libflag ){
152 outdef( p, LDX, NOFILE );
153 }
154
155 case EXTDEF:
156 if( p->suse < 0 ){ /* used */
157 outdef( p, LUM, SVLINE );
158 }
159 break;
160 }
161
162 }
163
164 }
165 exit( 0 );
166 }
167
astype(t,i)168 astype( t, i ) ATYPE *t; {
169 TWORD tt;
170 int j, k=0, l=0;
171
172 if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){
173 if( i<0 || i>= DIMTABSZ-3 ){
174 werror( "lint's little mind is blown" );
175 }
176 else {
177 j = dimtab[i+3];
178 if( j<0 || j>SYMTSZ ){
179 k = dimtab[i];
180 l = X_NONAME | stab[j].suse;
181 }
182 else {
183 if( stab[j].suse <= 0 ) {
184 #ifndef FLEXNAMES
185 werror( "no line number for %.8s",
186 #else
187 werror( "no line number for %s",
188 #endif
189 stab[j].sname );
190 }
191 else {
192 k = dimtab[i];
193 #ifdef FLEXNAMES
194 l = hashstr(stab[j].sname);
195 #else
196 l = hashstr(stab[j].sname, LCHNM);
197 #endif
198 }
199 }
200 }
201
202 t->extra = k;
203 t->extra1 = l;
204 return( 1 );
205 }
206 else return( 0 );
207 }
208
bfcode(a,n)209 bfcode( a, n ) int a[]; {
210 /* code for the beginning of a function; a is an array of
211 indices in stab for the arguments; n is the number */
212 /* this must also set retlab */
213 register i;
214 register struct symtab *cfp;
215 static ATYPE t;
216
217 strforget();
218 retlab = 1;
219
220 cfp = &stab[curftn];
221
222 /* if creating library, don't do static functions */
223 if( Cflag && cfp->sclass == STATIC ) return;
224
225 /* if variable number of arguments, only print the ones which will be checked */
226 if( vaflag >= 0 ){
227 if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" );
228 else n = vaflag;
229 }
230 fsave( ftitle );
231 if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?~n:n );
232 else outdef( cfp, libflag?LIB:LDI, vaflag>=0?~n:n );
233 vaflag = -1;
234
235 /* output the arguments */
236 if( n ){
237 for( i=0; i<n; ++i ) {
238 t.aty = stab[a[i]].stype;
239 t.extra = 0;
240 t.extra1 = 0;
241 if( !astype( &t, stab[a[i]].sizoff ) ) {
242 switch( t.aty ){
243
244 case ULONG:
245 break;
246
247 case CHAR:
248 case SHORT:
249 t.aty = INT;
250 break;
251
252 case UCHAR:
253 case USHORT:
254 case UNSIGNED:
255 t.aty = UNSIGNED;
256 break;
257
258 }
259 }
260 fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
261 }
262 }
263 }
264
ctargs(p)265 ctargs( p ) NODE *p; {
266 /* count arguments; p points to at least one */
267 /* the arguemnts are a tower of commas to the left */
268 register c;
269 c = 1; /* count the rhs */
270 while( p->in.op == CM ){
271 ++c;
272 p = p->in.left;
273 }
274 return( c );
275 }
276
lpta(p)277 lpta( p ) NODE *p; {
278 static ATYPE t;
279
280 if( p->in.op == CM ){
281 lpta( p->in.left );
282 p = p->in.right;
283 }
284
285 t.aty = p->in.type;
286 t.extra = (p->in.op==ICON);
287 t.extra1 = 0;
288
289 if( !astype( &t, p->fn.csiz ) ) {
290 switch( t.aty ){
291
292 case CHAR:
293 case SHORT:
294 t.aty = INT;
295 case LONG:
296 case ULONG:
297 case INT:
298 case UNSIGNED:
299 break;
300
301 case UCHAR:
302 case USHORT:
303 t.aty = UNSIGNED;
304 break;
305
306 case FLOAT:
307 t.aty = DOUBLE;
308 t.extra = 0;
309 break;
310
311 default:
312 t.extra = 0;
313 break;
314 }
315 }
316 fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
317 }
318
319 # define VALSET 1
320 # define VALUSED 2
321 # define VALASGOP 4
322 # define VALADDR 8
323
lprt(p,down,uses)324 lprt( p, down, uses ) register NODE *p; {
325 register struct symtab *q;
326 register id;
327 register acount;
328 register down1, down2;
329 register use1, use2;
330 register struct lnm *np1, *np2;
331
332 /* first, set variables which are set... */
333
334 use1 = use2 = VALUSED;
335 if( p->in.op == ASSIGN ) use1 = VALSET;
336 else if( p->in.op == UNARY AND ) use1 = VALADDR;
337 else if( asgop( p->in.op ) ){ /* =ops */
338 use1 = VALUSED|VALSET;
339 if( down == EFF ) use1 |= VALASGOP;
340 }
341
342
343 /* print the lines for lint */
344
345 down2 = down1 = VAL;
346 acount = 0;
347
348 switch( p->in.op ){
349
350 case EQ:
351 case NE:
352 case GT:
353 case GE:
354 case LT:
355 case LE:
356 if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){
357 werror( "nonportable character comparison" );
358 }
359 if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){
360 if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){
361 werror( "comparison of unsigned with negative constant" );
362 }
363 }
364 break;
365
366 case UGE:
367 case ULT:
368 if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){
369 werror( "unsigned comparison with 0?" );
370 break;
371 }
372 case UGT:
373 case ULE:
374 if( p->in.right->in.op == ICON && p->in.right->tn.lval <= 0 && !ISUNSIGNED(p->in.right->in.type) && p->in.right->tn.rval == NONAME ){
375 werror( "degenerate unsigned comparison" );
376 }
377 break;
378
379 case COMOP:
380 down1 = EFF;
381
382 case ANDAND:
383 case OROR:
384 case QUEST:
385 down2 = down;
386 /* go recursively left, then right */
387 np1 = lnp;
388 lprt( p->in.left, down1, use1 );
389 np2 = lnp;
390 lprt( p->in.right, down2, use2 );
391 lmerge( np1, np2, 0 );
392 return;
393
394 case SCONV:
395 case PCONV:
396 case COLON:
397 down1 = down2 = down;
398 break;
399
400 case CALL:
401 case STCALL:
402 case FORTCALL:
403 acount = ctargs( p->in.right );
404 case UNARY CALL:
405 case UNARY STCALL:
406 case UNARY FORTCALL:
407 if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */
408 struct symtab *sp = &stab[id];
409 int lty;
410
411 fsave( ftitle );
412 if (!nflag)
413 doform(p, sp, acount);
414 /*
415 * if we're generating a library -C then
416 * we don't want to output references to functions
417 */
418 if( Cflag ) break;
419 /* if a function used in an effects context is
420 * cast to type void then consider its value
421 * to have been disposed of properly
422 * thus a call of type undef in an effects
423 * context is construed to be used in a value
424 * context
425 */
426 if ((down == EFF) && (p->in.type != UNDEF)) {
427 lty = LUE;
428 } else if (down == EFF) {
429 lty = LUV | LUE;
430 } else {
431 lty = LUV;
432 }
433 outdef( sp, lty, acount );
434 if( acount ) {
435 lpta( p->in.right );
436 }
437 }
438 break;
439
440 case ICON:
441 /* look for &name case */
442 if( (id = p->tn.rval) >= 0 && id != NONAME ){
443 q = &stab[id];
444 q->sflags |= (SREF|SSET);
445 q->suse = -lineno;
446 }
447 return;
448
449 case NAME:
450 if( (id = p->tn.rval) >= 0 && id != NONAME ){
451 q = &stab[id];
452 if( (uses&VALUSED) && !(q->sflags&SSET) ){
453 if( q->sclass == AUTO || q->sclass == REGISTER ){
454 if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){
455 #ifndef FLEXNAMES
456 werror( "%.8s may be used before set", q->sname );
457 #else
458 werror( "%s may be used before set", q->sname );
459 #endif
460 q->sflags |= SSET;
461 }
462 }
463 }
464 if( uses & VALASGOP ) break; /* not a real use */
465 if( uses & VALSET ) q->sflags |= SSET;
466 if( uses & VALUSED ) q->sflags |= SREF;
467 if( uses & VALADDR ) q->sflags |= (SREF|SSET);
468 if( p->tn.lval == 0 ){
469 lnp->lid = id;
470 lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED);
471 if( ++lnp >= &lnames[LNAMES] ) --lnp;
472 }
473 }
474 return;
475
476 }
477
478 /* recurse, going down the right side first if we can */
479
480 switch( optype(p->in.op) ){
481
482 case BITYPE:
483 np1 = lnp;
484 lprt( p->in.right, down2, use2 );
485 case UTYPE:
486 np2 = lnp;
487 lprt( p->in.left, down1, use1 );
488 }
489
490 if( optype(p->in.op) == BITYPE ){
491 if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */
492 lmerge( np1, np2, 0 );
493 }
494 else lmerge( np1, np2, p->in.op != COLON );
495 /* look for assignments to fields, and complain */
496 if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p );
497 }
498
499 }
500
501 lmerge( np1, np2, flag ) struct lnm *np1, *np2; {
502 /* np1 and np2 point to lists of lnm members, for the two sides
503 * of a binary operator
504 * flag is 1 if commutation is possible, 0 otherwise
505 * lmerge returns a merged list, starting at np1, resetting lnp
506 * it also complains, if appropriate, about side effects
507 */
508
509 register struct lnm *npx, *npy;
510
511 for( npx = np2; npx < lnp; ++npx ){
512
513 /* is it already there? */
514 for( npy = np1; npy < np2; ++npy ){
515 if( npx->lid == npy->lid ){ /* yes */
516 if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) )
517 ; /* do nothing */
518 else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) ||
519 (npx->flgs&npy->flgs&VALSET) ){
520 #ifndef FLEXNAMES
521 if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname );
522 #else
523 if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname );
524 #endif
525 }
526 if( npy->flgs == 0 ) npx->flgs = 0;
527 else npy->flgs |= npx->flgs;
528 goto foundit;
529 }
530 }
531
532 /* not there: update entry */
533 np2->lid = npx->lid;
534 np2->flgs = npx->flgs;
535 ++np2;
536
537 foundit: ;
538 }
539
540 /* all finished: merged list is at np1 */
541 lnp = np2;
542 }
543
efcode()544 efcode(){
545 /* code for the end of a function */
546 register struct symtab *cfp;
547
548 cfp = &stab[curftn];
549 if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) )
550 outdef( cfp, LRV, DECTY );
551 if( !vflag ){
552 vflag = argflag;
553 argflag = 0;
554 }
555 if( retstat == RETVAL+NRETVAL )
556 #ifndef FLEXNAMES
557 werror( "function %.8s has return(e); and return;", cfp->sname);
558 #else
559 werror( "function %s has return(e); and return;", cfp->sname);
560 #endif
561 }
562
563 aocode(p) struct symtab *p; {
564 /* called when automatic p removed from stab */
565 register struct symtab *cfs;
566 cfs = &stab[curftn];
567 if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){
568 if( p->sclass == PARAM ){
569 #ifndef FLEXNAMES
570 if( vflag ) werror( "argument %.8s unused in function %.8s",
571 #else
572 if( vflag ) werror( "argument %s unused in function %s",
573 #endif
574 p->sname,
575 cfs->sname );
576 }
577 else {
578 #ifndef FLEXNAMES
579 if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s",
580 #else
581 if( p->sclass != TYPEDEF ) werror( "%s unused in function %s",
582 #endif
583 p->sname, cfs->sname );
584 }
585 }
586
587 if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET &&
588 !ISARY(p->stype) && !ISFTN(p->stype) ){
589
590 #ifndef FLEXNAMES
591 werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname );
592 #else
593 werror( "%s set but not used in function %s", p->sname, cfs->sname );
594 #endif
595 }
596
597 if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){
598 if( !zflag && dimtab[p->sizoff+1] < 0 )
599 #ifndef FLEXNAMES
600 werror( "structure %.8s never defined", p->sname );
601 #else
602 werror( "structure %s never defined", p->sname );
603 #endif
604 }
605
606 }
607
defnam(p)608 defnam( p ) register struct symtab *p; {
609 /* define the current location as the name p->sname */
610
611 if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return;
612
613 if( !ISFTN( p->stype ) )
614 if( p->sclass == STATIC ) outdef( p, LST, USUAL );
615 else outdef( p, libflag?LIB:LDI, USUAL );
616 }
617
zecode(n)618 zecode( n ){
619 /* n integer words of zeros */
620 OFFSZ temp;
621 temp = n;
622 inoff += temp*SZINT;
623 ;
624 }
625
andable(p)626 andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */
627 register r;
628
629 if( p->in.op != NAME ) cerror( "andable error" );
630
631 if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */
632
633 if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0);
634 #ifndef FLEXNAMES
635 if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname );
636 #else
637 if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname );
638 #endif
639 return(1);
640 }
641
642 NODE *
clocal(p)643 clocal(p) NODE *p; {
644
645 /* this is called to do local transformations on
646 an expression tree preparitory to its being
647 written out in intermediate code.
648 */
649
650 /* the major essential job is rewriting the
651 automatic variables and arguments in terms of
652 REG and OREG nodes */
653 /* conversion ops which are not necessary are also clobbered here */
654 /* in addition, any special features (such as rewriting
655 exclusive or) are easily handled here as well */
656
657 register o;
658 register unsigned t, tl;
659 int s;
660
661 switch( o = p->in.op ){
662 case NAME:
663 {
664 extern int didstr, subscr;
665 extern NODE * strnodes[];
666
667 if (didstr) {
668 didstr = 0;
669 strnodes[subscr] = p;
670 }
671 }
672 break;
673
674 case SCONV:
675 case PCONV:
676 if( p->in.left->in.type==ENUMTY ){
677 p->in.left = pconvert( p->in.left );
678 }
679 /* assume conversion takes place; type is inherited */
680 t = p->in.type;
681 tl = p->in.left->in.type;
682 if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){
683 werror( "long assignment may lose accuracy" );
684 }
685 if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){
686 werror( "assignment to long may sign-extend incorrectly" );
687 }
688 if( ISPTR(tl) && ISPTR(t) ){
689 tl = DECREF(tl);
690 t = DECREF(t);
691 switch( ISFTN(t) + ISFTN(tl) ){
692
693 case 0: /* neither is a function pointer */
694 if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){
695 if( hflag||pflag ) werror( "possible pointer alignment problem" );
696 }
697 break;
698
699 case 1:
700 werror( "questionable conversion of function pointer" );
701
702 case 2:
703 ;
704 }
705 }
706 p->in.left->in.type = p->in.type;
707 p->in.left->fn.cdim = p->fn.cdim;
708 p->in.left->fn.csiz = p->fn.csiz;
709 p->in.op = FREE;
710 return( p->in.left );
711
712 case PVCONV:
713 case PMCONV:
714 if( p->in.right->in.op != ICON ) cerror( "bad conversion");
715 p->in.op = FREE;
716 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
717
718 case RS:
719 case LS:
720 case ASG RS:
721 case ASG LS:
722 if( p->in.right->in.op != ICON )
723 break;
724 s = p->in.right->tn.lval;
725 if( s < 0 )
726 werror( "negative shift" );
727 else
728 if( s >= dimtab[ p->fn.csiz ] )
729 werror( "shift greater than size of object" );
730 break;
731
732 }
733
734 return(p);
735 }
736
737 NODE *
offcon(off,t,d,s)738 offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */
739 register NODE *p;
740 p = bcon(0);
741 p->tn.lval = off/SZCHAR;
742 return(p);
743 }
744
noinit()745 noinit(){
746 /* storage class for such as "int a;" */
747 return( pflag ? EXTDEF : EXTERN );
748 }
749
750
cinit(p,sz)751 cinit( p, sz ) NODE *p; { /* initialize p into size sz */
752 register int id;
753
754 inoff += sz;
755 if( p->in.op == INIT ){
756 if( p->in.left->in.op == ICON ) return;
757 if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return;
758 }
759 uerror( "illegal initialization" );
760 }
761
762 char *
exname(p)763 exname( p ) char *p; {
764 /* make a name look like an external name in the local machine */
765 static char aa[8];
766 register int i;
767
768 if( !pflag ) return(p);
769 for( i=0; i<6; ++i ){
770 if( isupper(*p ) ) aa[i] = tolower( *p );
771 else aa[i] = *p;
772 if( *p ) ++p;
773 }
774 aa[6] = '\0';
775 return( aa );
776 }
777
778 char *
strip(s)779 strip(s) char *s; {
780 #ifndef FLEXNAMES
781 static char x[LFNM+1];
782 #else
783 static char x[BUFSIZ];
784 #endif
785 register char *p;
786 static int stripping = 0;
787
788 if (stripping)
789 return(s);
790 stripping++;
791 for( p=x; *s; ++s ){
792 if( *s != '"' ){
793 #ifndef FLEXNAMES
794 /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */
795 if( p >= &x[LFNM] )
796 #else
797 if( p >= &x[BUFSIZ] )
798 #endif
799 cerror( "filename too long" );
800 *p++ = *s;
801 }
802 }
803 stripping = 0;
804 *p = '\0';
805 #ifndef FLEXNAMES
806 return( x );
807 #else
808 return( hash(x) );
809 #endif
810 }
811
fsave(s)812 fsave( s ) char *s; {
813 static union rec fsname;
814 s = strip( s );
815 #ifndef FLEXNAMES
816 if( strncmp( s, fsname.f.fn, LFNM ) )
817 #else
818 if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn))
819 #endif
820 {
821 /* new one */
822 #ifndef FLEXNAMES
823 strncpy( fsname.f.fn, s, LFNM );
824 #else
825 fsname.f.fn = s;
826 #endif
827 fsname.f.decflag = LFN;
828 fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
829 #ifdef FLEXNAMES
830 /* if generating a library, prefix with the library name */
831 /* only do this for flexnames */
832 if( libname ){
833 fwrite( libname, strlen(libname), 1, stdout );
834 putchar( ':' );
835 }
836 fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
837 #endif
838 }
839 }
840
where(f)841 where(f){ /* print true location of error */
842 if( f == 'u' && nerrors > 1 )
843 --nerrors; /* don't get "too many errors" */
844 fprintf( stderr, "%s(%d): ", strip(ftitle), lineno);
845 }
846
847 /* a number of dummy routines, unneeded by lint */
848
branch(n)849 branch(n){;}
defalign(n)850 defalign(n){;}
deflab(n)851 deflab(n){;}
852
853 extern char * strchr();
854
855 #define SBUFSIZE 16
856 #define SCLICK 80
857
858 #ifndef size_t
859 #define size_t unsigned
860 #endif /* !size_t */
861
862 static char * strings[SBUFSIZE];
863 static NODE * strnodes[SBUFSIZE];
864 static int didstr;
865 static int subscr;
866 static int strapped;
867
bycode(t,i)868 bycode(t, i)
869 {
870 extern char * calloc();
871 extern char * realloc();
872
873 if (nflag || strapped)
874 return;
875 if (i == 0)
876 if (subscr < (SBUFSIZE - 1))
877 ++subscr;
878 if (subscr >= SBUFSIZE)
879 return;
880 didstr = 1;
881 if ((i % SCLICK) == 0) {
882 strings[subscr] = (strings[subscr] == NULL) ?
883 calloc((size_t) (SCLICK + 1), 1) :
884 realloc(strings[subscr], (size_t) (i + SCLICK + 1));
885 if (strings[subscr] == NULL) {
886 strapped = 1;
887 return;
888 }
889 }
890 strings[subscr][i] = t;
891 }
892
strforget()893 strforget()
894 {
895 didstr = subscr = 0;
896 }
897
898 static char *
typestr(t)899 typestr(t)
900 {
901 switch (t) {
902 case CHAR: return "char";
903 case UCHAR: return "unsigned char";
904 case SHORT: return "short";
905 case USHORT: return "unsigned short";
906 case INT: return "int";
907 case UNSIGNED: return "unsigned";
908 case ENUMTY: return "enum";
909 case LONG: return "long";
910 case ULONG: return "unsigned long";
911 case FLOAT: return "float";
912 case DOUBLE: return "double";
913 case STRTY: return "struct";
914 case UNIONTY: return "union";
915 case PTR|CHAR: return "char *";
916 case PTR|UCHAR: return "unsigned char *";
917 case PTR|SHORT: return "short *";
918 case PTR|USHORT: return "unsigned short *";
919 case PTR|INT: return "int *";
920 case PTR|UNSIGNED: return "unsigned *";
921 case PTR|ENUMTY: return "enum *";
922 case PTR|LONG: return "long *";
923 case PTR|ULONG: return "unsigned long *";
924 case PTR|FLOAT: return "float *";
925 case PTR|DOUBLE: return "double *";
926 case PTR|STRTY: return "struct *";
927 case PTR|UNIONTY: return "union *";
928 default: return ISPTR(t) ?
929 "pointer" : "non-scalar";
930 }
931 }
932
933 NODE *
ntharg(p,n,acount)934 ntharg(p, n, acount)
935 NODE * p;
936 register int n;
937 register int acount;
938 {
939 if (n > acount)
940 return NULL;
941 p = p->in.right;
942 while (n != acount) {
943 p = p->in.left;
944 --acount;
945 }
946 return (n == 1) ? p : p->in.right;
947 }
948
949 struct entry {
950 /* If argument to print/scan is of type... */ int argtype;
951 /* ...and this length character is used... */ char lchar;
952 /* ...and one of these is control char... */ char * cchars;
953 /* ...then use this format with werror... */ char * werror;
954 /* ...(where NULL means it's hunky dory)... */
955 };
956
957 /*
958 ** Portable printf.
959 ** H&S says "%o" takes an unsigned argument;
960 ** X3J11 says "%o" takes an int argument;
961 ** we'll allow either here.
962 */
963
964 static struct entry pprintf[] = {
965 CHAR, '\0', "c", NULL, /* this is deliberate */
966 INT, '\0', "cdoxX", NULL,
967 UNSIGNED, '\0', "uoxX", NULL,
968 CHAR, '\0', "cdoxX", NULL,
969 UCHAR, '\0', "udoxX", NULL, /* yes, d is okay */
970 SHORT, '\0', "cdoxX", NULL,
971 USHORT, '\0', "uoxX", NULL,
972 ENUMTY, '\0', "duoxX", NULL,
973 LONG, 'l', "doxX", NULL,
974 ULONG, 'l', "uoxX", NULL,
975 FLOAT, '\0', "eEfgG", NULL,
976 DOUBLE, '\0', "eEfgG", NULL,
977 PTR|CHAR, '\0', "s", NULL,
978 UNDEF, '\0', "", NULL
979 };
980
981 /*
982 ** Berkeley printf.
983 ** It allows %D, %O, and %U, which we deprecate.
984 ** Since
985 ** sizeof (char *) == sizeof (int) &&
986 ** sizeof (int) == sizeof (long) &&
987 ** sizeof (char *) == sizeof (int *)
988 ** you can be lax--and we tolerate *some* laxness.
989 ** g/lax/p to find lax table entries and code.
990 */
991
992 static char uppercase[] = "deprecated upper-case control character (%c)";
993 #define lax NULL
994
995 static struct entry bprintf[] = {
996 CHAR, '\0', "c", NULL, /* this is deliberate */
997 INT, '\0', "cdoxX", NULL,
998 INT, '\0', "DO", uppercase,
999 UNSIGNED, '\0', "uoxX", NULL,
1000 UNSIGNED, '\0', "UO", uppercase,
1001 CHAR, '\0', "cdoxX", NULL,
1002 CHAR, '\0', "DO", uppercase,
1003 UCHAR, '\0', "duoxX", NULL, /* yes, d is okay */
1004 UCHAR, '\0', "DUO", uppercase,
1005 SHORT, '\0', "cdoxX", NULL,
1006 SHORT, '\0', "DO", uppercase,
1007 USHORT, '\0', "duoxX", NULL, /* d okay on BSD */
1008 USHORT, '\0', "DUO", uppercase,
1009 ENUMTY, '\0', "duoxX", NULL,
1010 ENUMTY, '\0', "DUO", uppercase,
1011 LONG, '\0', "doxX", lax,
1012 LONG, '\0', "DO", uppercase,
1013 LONG, 'l', "doxX", NULL,
1014 INT, 'l', "doxX", lax,
1015 ULONG, '\0', "uoxX", lax,
1016 ULONG, '\0', "UO", uppercase,
1017 ULONG, 'l', "uoxX", NULL,
1018 UNSIGNED, 'l', "uoxX", lax,
1019 FLOAT, '\0', "eEfgG", NULL,
1020 DOUBLE, '\0', "eEfgG", NULL,
1021 PTR|CHAR, '\0', "s", NULL,
1022 UNDEF, '\0', NULL, NULL,
1023 };
1024
1025 /*
1026 ** Portable scanf. 'l' and 'h' are universally ignored preceding 'c' and 's',
1027 ** and 'h' is universally ignored preceding 'e' and 'f',
1028 ** but you won't find such cruft here.
1029 */
1030
1031 static struct entry pscanf[] = {
1032 INT, '\0', "dox", NULL,
1033 UNSIGNED, '\0', "uox", NULL,
1034 CHAR, '\0', "cs[", NULL,
1035 SHORT, 'h', "dox", NULL,
1036 USHORT, 'h', "uox", NULL,
1037 LONG, 'l', "dox", NULL,
1038 ULONG, 'l', "uox", NULL,
1039 FLOAT, '\0', "ef", NULL, /* BSD doesn't handle g */
1040 DOUBLE, 'l', "ef", NULL,
1041 UNDEF, '\0', NULL, NULL,
1042 };
1043
1044 /*
1045 ** Berkeley scanf. An upper case letter equals an l plus the lower case char,
1046 ** but this is deprecated.
1047 ** Even though sizeof (int) == sizeof (long), we'll be picky here.
1048 */
1049
1050 static struct entry bscanf[] = {
1051 INT, '\0', "dox", NULL,
1052 UNSIGNED, '\0', "uox", NULL,
1053 CHAR, '\0', "cs[", NULL,
1054 SHORT, 'h', "dox", NULL,
1055 USHORT, 'h', "uox", NULL,
1056 LONG, '\0', "dox", lax,
1057 LONG, '\0', "DOX", uppercase,
1058 LONG, 'l', "dox", NULL,
1059 ULONG, '\0', "uox", lax,
1060 ULONG, '\0', "UOX", uppercase,
1061 ULONG, 'l', "uox", NULL,
1062 FLOAT, '\0', "ef", NULL,
1063 DOUBLE, '\0', "EF", uppercase,
1064 DOUBLE, 'l', "ef", NULL,
1065 UNDEF, '\0', NULL, NULL,
1066 };
1067
1068 static struct item {
1069 char * name; /* such as "printf" */
1070 int isscan; /* scanf/printf */
1071 int fmtarg; /* number of format argument */
1072 struct entry * ptable; /* portable checking table */
1073 struct entry * btable; /* berkeley checking table */
1074 } items[] = {
1075 "printf", 0, 1, pprintf, bprintf,
1076 "fprintf", 0, 2, pprintf, bprintf,
1077 "sprintf", 0, 2, pprintf, bprintf,
1078 "scanf", 1, 1, pscanf, bscanf,
1079 "fscanf", 1, 2, pscanf, bscanf,
1080 "sscanf", 1, 2, pscanf, bscanf,
1081 NULL, -1, -1, NULL, NULL
1082 };
1083
1084 static char pwf[] = "possible wild format";
1085 static char pfacm[] = "possible format/argument count mismatch";
1086
1087 static struct entry *
findlc(ep,lchar,cchar)1088 findlc(ep, lchar, cchar)
1089 register struct entry * ep;
1090 register int lchar;
1091 register int cchar;
1092 {
1093 for ( ; ep->argtype != UNDEF; ++ep)
1094 if (ep->lchar == lchar && strchr(ep->cchars, cchar) != 0)
1095 return ep;
1096 return NULL;
1097 }
1098
1099 static char *
subform(p,sp,acount)1100 subform(p, sp, acount)
1101 register NODE * p;
1102 register struct symtab * sp;
1103 {
1104 register int i, j, isscan;
1105 register NODE * tp;
1106 register char * cp;
1107 register struct entry * basep;
1108 register struct entry * ep;
1109 register struct item * ip;
1110 register int lchar;
1111 register int cchar;
1112 register int t;
1113 register int suppressed;
1114 static char errbuf[132];
1115
1116 if (nflag || strapped)
1117 return NULL;
1118 cp = sp->sname;
1119 for (ip = items; ; ++ip)
1120 if (ip->name == NULL)
1121 return NULL; /* not a print/scan function */
1122 else if (strcmp(ip->name, sp->sname) == 0)
1123 break;
1124 isscan = ip->isscan;
1125 i = ip->fmtarg;
1126 if (i > acount)
1127 return NULL; /* handled in pass 2 */
1128 tp = ntharg(p, i, acount);
1129 if (tp->in.type != (PTR|CHAR))
1130 return NULL; /* handled in pass 2 */
1131 if (tp->in.op != ICON || tp->tn.lval != 0)
1132 return NULL; /* can't check it */
1133 for (j = 1; j <= subscr; ++j)
1134 if (tp == strnodes[j])
1135 break;
1136 if (j > subscr)
1137 return NULL; /* oh well. . . */
1138 cp = strings[j];
1139 /*
1140 ** cp now points to format string.
1141 */
1142 /*
1143 ** For now, ALWAYS use "portable" table, rather than doing this:
1144 ** basep = pflag ? ip->ptable : ip->btable;
1145 */
1146 basep = ip->ptable;
1147 for ( ; ; ) {
1148 if (*cp == '\0')
1149 return (i == acount) ? NULL : pfacm;
1150 if (*cp++ != '%')
1151 continue;
1152 if (*cp == '\0')
1153 return "wild trailing %% in format";
1154 if (*cp == '%') {
1155 ++cp;
1156 continue;
1157 }
1158 if (isscan) {
1159 suppressed = *cp == '*';
1160 if (suppressed)
1161 ++cp;
1162 while (isdigit(*cp))
1163 ++cp;
1164 if (!suppressed && ++i <= acount) {
1165 t = ntharg(p, i, acount)->in.type;
1166 if (!ISPTR(t)) {
1167 (void) sprintf(errbuf,
1168 "%s argument is type (%s) rather than pointer (arg %d)",
1169 ip->name, typestr(t), i);
1170 return errbuf;
1171 }
1172 t = DECREF(t);
1173 }
1174 } else {
1175 int nspace, ndash, nplus, nhash;
1176
1177 suppressed = 0;
1178 nspace = ndash = nplus = nhash = 0;
1179 for ( ; ; ) {
1180 if (*cp == ' ')
1181 ++nspace;
1182 else if (*cp == '+')
1183 ++nplus;
1184 else if (*cp == '-')
1185 ++ndash;
1186 else if (*cp == '#')
1187 ++nhash;
1188 else break;
1189 ++cp;
1190 }
1191 if (nspace > 1 || ndash > 1 || nplus > 1 || nhash > 1)
1192 return "wild repeated flag character in format";
1193 if (*cp == '*') {
1194 ++cp;
1195 if (++i > acount)
1196 break;
1197 t = ntharg(p, i, acount)->in.type;
1198 /*
1199 ** Width other than INT or UNSIGNED is suspect.
1200 */
1201 if (t != INT && t != UNSIGNED) {
1202 (void) sprintf(errbuf,
1203 "field width argument is type (%s) rather than (int) (arg %d)",
1204 typestr(t), i);
1205 return errbuf;
1206 }
1207 } else while (isdigit(*cp))
1208 ++cp;
1209 if (*cp == '.') {
1210 ++cp;
1211 if (*cp == '*') {
1212 ++cp;
1213 if (++i > acount)
1214 return pfacm;
1215 t = ntharg(p, i, acount)->in.type;
1216 if (t != INT && t != UNSIGNED) {
1217 (void) sprintf(errbuf,
1218 "precision argument is type (%s) rather than (int) (arg %d)",
1219 typestr(t), i);
1220 return errbuf;
1221 }
1222 } else while (isdigit(*cp))
1223 ++cp;
1224 }
1225 if (++i <= acount)
1226 t = ntharg(p, i, acount)->in.type;
1227 }
1228 if (*cp == 'h' || *cp == 'l')
1229 lchar = *cp++;
1230 else lchar = '\0';
1231 if ((cchar = *cp++) == '\0')
1232 return pwf;
1233 if (i > acount)
1234 return (findlc(basep, lchar, cchar) == NULL) ?
1235 pwf : pfacm;
1236 if (!isscan && !pflag && ISPTR(t) &&
1237 strchr("douxX", cchar) != 0)
1238 continue; /* lax--printf("%d", (int *)) */
1239 if (suppressed) {
1240 if (findlc(basep, lchar, cchar) == NULL)
1241 return pwf;
1242 } else for (ep = basep; ; ++ep) {
1243 if (ep->argtype == UNDEF) { /* end of table */
1244 ep = findlc(basep, lchar, cchar);
1245 if (ep == NULL)
1246 return pwf;
1247 (void) sprintf(errbuf, "%s: (%s) format, (%s) arg (arg %d)",
1248 ip->name,
1249 typestr(ep->argtype),
1250 typestr(isscan ? (t | PTR) : t), i);
1251 return errbuf;
1252 }
1253 if (ep->argtype == t && ep->lchar == lchar &&
1254 strchr(ep->cchars, cchar) != 0)
1255 if (ep->werror == 0)
1256 break;
1257 else {
1258 werror(ep->werror, cchar);
1259 return NULL;
1260 }
1261 }
1262 if (cchar != '[')
1263 continue;
1264 do {
1265 if (*cp == '\0')
1266 return "possible unmatched '[' in format";
1267 } while (*cp++ != ']');
1268 }
1269 /*NOTREACHED*/
1270 }
1271
doform(p,sp,acount)1272 doform(p, sp, acount)
1273 NODE * p;
1274 struct symtab * sp;
1275 {
1276 char * cp;
1277
1278 if ((cp = subform(p, sp, acount)) != NULL)
1279 werror(cp);
1280 }
1281
cisreg(t)1282 cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */
1283
1284 fldty(p) struct symtab *p; {
1285 ; /* all types are OK here... */
1286 }
1287
fldal(t)1288 fldal(t) unsigned t; { /* field alignment... */
1289 if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */
1290 if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
1291 if( pflag ) uerror( "nonportable field type" );
1292 }
1293 else uerror( "illegal field type" );
1294 return(ALINT);
1295 }
1296
main(argc,argv)1297 main(argc, argv)
1298 int argc;
1299 char **argv;
1300 {
1301 extern char *optarg;
1302 extern int optind;
1303 int ch;
1304
1305 while ((ch = getopt(argc,argv,"C:D:I:U:LX:Pabchnpuvxz")) != EOF)
1306 switch((char)ch) {
1307 case 'C':
1308 Cflag = 1;
1309 libname = optarg;
1310 continue;
1311 case 'D': /* #define */
1312 case 'I': /* include path */
1313 case 'U': /* #undef */
1314 case 'X': /* debugging, done in first pass */
1315 case 'P': /* debugging, done in second pass */
1316 break;
1317 case 'L':
1318 libflag = 1;
1319 /*FALLTHROUGH*/
1320 case 'v': /* unused arguments in functions */
1321 vflag = 0;
1322 break;
1323 case 'a': /* long to int assignment */
1324 ++aflag;
1325 break;
1326 case 'b': /* unreached break statements */
1327 brkflag = 1;
1328 break;
1329 case 'c': /* questionable casts */
1330 cflag = 1;
1331 break;
1332 case 'h': /* heuristics */
1333 hflag = 1;
1334 break;
1335 case 'n': /* standard library check */
1336 nflag = 1;
1337 break;
1338 case 'p': /* IBM & GCOS portability */
1339 pflag = 1;
1340 break;
1341 case 'u': /* 2nd pass: undefined or unused */
1342 break;
1343 case 'x': /* unused externs */
1344 xflag = 1;
1345 break;
1346 case 'z': /* use of undefined structures */
1347 zflag = 1;
1348 break;
1349 case '?':
1350 default:
1351 fputs("usage: lint [-C lib] [-D def] [-I include] [-U undef] [-Labchnpuvx] file ...\n",stderr);
1352 exit(1);
1353 }
1354
1355 if (!pflag) { /* set sizes to sizes of target machine */
1356 # ifdef gcos
1357 SZCHAR = ALCHAR = 9;
1358 # else
1359 SZCHAR = ALCHAR = 8;
1360 # endif
1361 SZINT = ALINT = sizeof(int)*SZCHAR;
1362 SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
1363 SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
1364 SZLONG = ALLONG = sizeof(long)*SZCHAR;
1365 SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
1366 SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
1367 ALSTRUCT = ALINT;
1368 /* now, fix some things up for various machines (I wish we had "alignof") */
1369
1370 # ifdef pdp11
1371 ALLONG = ALDOUBLE = ALFLOAT = ALINT;
1372 # endif
1373 # ifdef ibm
1374 ALSTRUCT = ALCHAR;
1375 # endif
1376 }
1377 return(mainp1(argc,argv));
1378 }
1379
ctype(type)1380 ctype( type ) unsigned type; { /* are there any funny types? */
1381 return( type );
1382 }
1383
commdec(i)1384 commdec( i ){
1385 /* put out a common declaration */
1386 if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL );
1387 else outdef( &stab[i], libflag?LIB:LDC, USUAL );
1388 }
1389
isitfloat(s)1390 isitfloat ( s ) char *s; {
1391 /* s is a character string;
1392 if floating point is implemented, set dcon to the value of s */
1393 /* lint version
1394 */
1395 dcon = atof( s );
1396 return( DCON );
1397 }
1398
fldcon(p)1399 fldcon( p ) register NODE *p; {
1400 /* p is an assignment of a constant to a field */
1401 /* check to see if the assignment is going to overflow, or otherwise cause trouble */
1402 register s;
1403 CONSZ v;
1404
1405 if( !hflag & !pflag ) return;
1406
1407 s = UPKFSZ(p->in.left->tn.rval);
1408 v = p->in.right->tn.lval;
1409
1410 switch( p->in.left->in.type ){
1411
1412 case CHAR:
1413 case INT:
1414 case SHORT:
1415 case LONG:
1416 case ENUMTY:
1417 if( v>=0 && (v>>(s-1))==0 ) return;
1418 werror( "precision lost in assignment to (possibly sign-extended) field" );
1419 default:
1420 return;
1421
1422 case UNSIGNED:
1423 case UCHAR:
1424 case USHORT:
1425 case ULONG:
1426 if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
1427
1428 return;
1429 }
1430
1431 }
1432
1433 outdef( p, lty, mode ) struct symtab *p; {
1434 /* output a definition for the second pass */
1435 /* if mode is > USUAL, it is the number of args */
1436 char *fname;
1437 TWORD t;
1438 int line;
1439 static union rec rc;
1440
1441 if( mode == NOFILE ){
1442 fname = "???";
1443 line = p->suse;
1444 }
1445 else if( mode == SVLINE ){
1446 fname = ftitle;
1447 line = -p->suse;
1448 }
1449 else {
1450 fname = ftitle;
1451 line = lineno;
1452 }
1453 fsave( fname );
1454 #ifndef FLEXNAMES
1455 strncpy( rc.l.name, exname(p->sname), LCHNM );
1456 #endif
1457 rc.l.decflag = lty;
1458 t = p->stype;
1459 if( mode == DECTY ) t = DECREF(t);
1460 rc.l.type.aty = t;
1461 rc.l.type.extra = 0;
1462 rc.l.type.extra1 = 0;
1463 astype( &rc.l.type, p->sizoff );
1464 rc.l.nargs = (mode>USUAL) ? mode : 0;
1465 rc.l.fline = line;
1466 fwrite( (char *)&rc, sizeof(rc), 1, stdout );
1467 #ifdef FLEXNAMES
1468 rc.l.name = exname(p->sname);
1469 fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
1470 #endif
1471 }
1472 int proflg;
1473 int gdebug;
1474