BSD 4 development
[unix-history] / usr / src / cmd / lint / lint.c
CommitLineData
88221cd5
BJ
1# include "mfile1"
2
3# include "lmanifest"
4
5# include <ctype.h>
6
7# define VAL 0
8# define EFF 1
9
10/* these are appropriate for the -p flag */
11int SZCHAR = 8;
12int SZINT = 16;
13int SZFLOAT = 32;
14int SZDOUBLE = 64;
15int SZLONG = 32;
16int SZSHORT = 16;
17int SZPOINT = 16;
18int ALCHAR = 8;
19int ALINT = 16;
20int ALFLOAT = 32;
21int ALDOUBLE = 64;
22int ALLONG = 32;
23int ALSHORT = 16;
24int ALPOINT = 16;
25int ALSTRUCT = 16;
26
27int vflag = 1; /* tell about unused argments */
28int xflag = 0; /* tell about unused externals */
29int argflag = 0; /* used to turn off complaints about arguments */
30int libflag = 0; /* used to generate library descriptions */
31int vaflag = -1; /* used to signal functions with a variable number of args */
32int aflag = 0; /* used to check precision of assignments */
33
34 /* flags for the "outdef" function */
35# define USUAL (-101)
36# define DECTY (-102)
37# define NOFILE (-103)
38# define SVLINE (-104)
39
40# define LNAMES 250
41
42struct lnm {
43 short lid, flgs;
44 } lnames[LNAMES], *lnp;
45
46contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; {
47
48 *pl = *pr = VAL;
49 switch( p->in.op ){
50
51 case ANDAND:
52 case OROR:
53 case QUEST:
54 *pr = down;
55 break;
56
57 case SCONV:
58 case PCONV:
59 case COLON:
60 *pr = *pl = down;
61 break;
62
63 case COMOP:
64 *pl = EFF;
65 *pr = down;
66
67 case FORCE:
68 case INIT:
69 case UNARY CALL:
70 case STCALL:
71 case UNARY STCALL:
72 case CALL:
73 case UNARY FORTCALL:
74 case FORTCALL:
75 case CBRANCH:
76 break;
77
78 default:
79 if( asgop(p->in.op) ) break;
80 if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) {
81 /* struct x f( ); main( ) { (void) f( ); }
82 * the the cast call appears as U* UNDEF
83 */
84 break; /* the compiler does this... */
85 }
86 if( down == EFF && hflag ) werror( "null effect" );
87
88 }
89 }
90
91ecode( p ) NODE *p; {
92 /* compile code for p */
93
94 fwalk( p, contx, EFF );
95 lnp = lnames;
96 lprt( p, EFF, 0 );
97 }
98
99ejobcode( flag ){
100 /* called after processing each job */
101 /* flag is nonzero if errors were detected */
102 register k;
103 register struct symtab *p;
104
105 for( p=stab; p< &stab[SYMTSZ]; ++p ){
106
107 if( p->stype != TNULL ) {
108
109 if( p->stype == STRTY || p->stype == UNIONTY ){
110 if( dimtab[p->sizoff+1] < 0 ){ /* never defined */
111#ifndef FLEXNAMES
112 if( hflag ) werror( "struct/union %.8s never defined", p->sname );
113#else
114 if( hflag ) werror( "struct/union %s never defined", p->sname );
115#endif
116 }
117 }
118
119 switch( p->sclass ){
120
121 case STATIC:
122 if( p->suse > 0 ){
123 k = lineno;
124 lineno = p->suse;
125#ifndef FLEXNAMES
126 uerror( "static variable %.8s unused",
127#else
128 uerror( "static variable %s unused",
129#endif
130 p->sname );
131 lineno = k;
132 break;
133 }
134
135 case EXTERN:
136 case USTATIC:
137 /* with the xflag, worry about externs not used */
138 /* the filename may be wrong here... */
139 if( xflag && p->suse >= 0 && !libflag ){
140 outdef( p, LDX, NOFILE );
141 }
142
143 case EXTDEF:
144 if( p->suse < 0 ){ /* used */
145 outdef( p, LUM, SVLINE );
146 }
147 break;
148 }
149
150 }
151
152 }
153 exit( 0 );
154 }
155
156astype( t, i ) ATYPE *t; {
157 TWORD tt;
158 int j, k=0;
159
160 if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){
161 if( i<0 || i>= DIMTABSZ-3 ){
162 werror( "lint's little mind is blown" );
163 }
164 else {
165 j = dimtab[i+3];
166 if( j<0 || j>SYMTSZ ){
167 k = ((-j)<<5)^dimtab[i]|1;
168 }
169 else {
170 if( stab[j].suse <= 0 ) {
171#ifndef FLEXNAMES
172 werror( "no line number for %.8s",
173#else
174 werror( "no line number for %s",
175#endif
176 stab[j].sname );
177 }
178 else k = (stab[j].suse<<5) ^ dimtab[i];
179 }
180 }
181
182 t->extra = k;
183 return( 1 );
184 }
185 else return( 0 );
186 }
187
188bfcode( a, n ) int a[]; {
189 /* code for the beginning of a function; a is an array of
190 indices in stab for the arguments; n is the number */
191 /* this must also set retlab */
192 register i;
193 register struct symtab *cfp;
194 static ATYPE t;
195
196 retlab = 1;
197 cfp = &stab[curftn];
198
199 /* if variable number of arguments, only print the ones which will be checked */
200 if( vaflag > 0 ){
201 if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" );
202 else n = vaflag;
203 }
204 fsave( ftitle );
205 outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n );
206 vaflag = -1;
207
208 /* output the arguments */
209 if( n ){
210 for( i=0; i<n; ++i ) {
211 t.aty = stab[a[i]].stype;
212 t.extra = 0;
213 if( !astype( &t, stab[a[i]].sizoff ) ) {
214 switch( t.aty ){
215
216 case ULONG:
217 break;
218
219 case CHAR:
220 case SHORT:
221 t.aty = INT;
222 break;
223
224 case UCHAR:
225 case USHORT:
226 case UNSIGNED:
227 t.aty = UNSIGNED;
228 break;
229
230 }
231 }
232 fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
233 }
234 }
235 }
236
237ctargs( p ) NODE *p; {
238 /* count arguments; p points to at least one */
239 /* the arguemnts are a tower of commas to the left */
240 register c;
241 c = 1; /* count the rhs */
242 while( p->in.op == CM ){
243 ++c;
244 p = p->in.left;
245 }
246 return( c );
247 }
248
249lpta( p ) NODE *p; {
250 static ATYPE t;
251
252 if( p->in.op == CM ){
253 lpta( p->in.left );
254 p = p->in.right;
255 }
256
257 t.aty = p->in.type;
258 t.extra = (p->in.op==ICON);
259
260 if( !astype( &t, p->in.csiz ) ) {
261 switch( t.aty ){
262
263 case CHAR:
264 case SHORT:
265 t.aty = INT;
266 case LONG:
267 case ULONG:
268 case INT:
269 case UNSIGNED:
270 break;
271
272 case UCHAR:
273 case USHORT:
274 t.aty = UNSIGNED;
275 break;
276
277 case FLOAT:
278 t.aty = DOUBLE;
279 t.extra = 0;
280 break;
281
282 default:
283 t.extra = 0;
284 break;
285 }
286 }
287 fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
288 }
289
290# define VALSET 1
291# define VALUSED 2
292# define VALASGOP 4
293# define VALADDR 8
294
295lprt( p, down, uses ) register NODE *p; {
296 register struct symtab *q;
297 register id;
298 register acount;
299 register down1, down2;
300 register use1, use2;
301 register struct lnm *np1, *np2;
302
303 /* first, set variables which are set... */
304
305 use1 = use2 = VALUSED;
306 if( p->in.op == ASSIGN ) use1 = VALSET;
307 else if( p->in.op == UNARY AND ) use1 = VALADDR;
308 else if( asgop( p->in.op ) ){ /* =ops */
309 use1 = VALUSED|VALSET;
310 if( down == EFF ) use1 |= VALASGOP;
311 }
312
313
314 /* print the lines for lint */
315
316 down2 = down1 = VAL;
317 acount = 0;
318
319 switch( p->in.op ){
320
321 case EQ:
322 case NE:
323 case GT:
324 case GE:
325 case LT:
326 case LE:
327 if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){
328 werror( "nonportable character comparison" );
329 }
330 if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){
331 if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){
332 werror( "comparison of unsigned with negative constant" );
333 }
334 }
335 break;
336
337 case UGE:
338 case ULT:
339 if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){
340 werror( "unsigned comparison with 0?" );
341 break;
342 }
343 case UGT:
344 case ULE:
345 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 ){
346 werror( "degenerate unsigned comparison" );
347 }
348 break;
349
350 case COMOP:
351 down1 = EFF;
352
353 case ANDAND:
354 case OROR:
355 case QUEST:
356 down2 = down;
357 /* go recursively left, then right */
358 np1 = lnp;
359 lprt( p->in.left, down1, use1 );
360 np2 = lnp;
361 lprt( p->in.right, down2, use2 );
362 lmerge( np1, np2, 0 );
363 return;
364
365 case SCONV:
366 case PCONV:
367 case COLON:
368 down1 = down2 = down;
369 break;
370
371 case CALL:
372 case STCALL:
373 case FORTCALL:
374 acount = ctargs( p->in.right );
375 case UNARY CALL:
376 case UNARY STCALL:
377 case UNARY FORTCALL:
378 if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */
379 struct symtab *sp = &stab[id];
380 int lty;
381 /* if a function used in an effects context is
382 * cast to type void then consider its value
383 * to have been disposed of properly
384 * thus a call of type undef in an effects
385 * context is construed to be used in a value
386 * context
387 */
388 if ((down == EFF) && (p->in.type != UNDEF)) {
389 lty = LUE;
390 } else if (down == EFF) {
391 lty = LUV | LUE;
392 } else {
393 lty = LUV;
394 }
395 fsave( ftitle );
396 outdef(sp, lty, acount);
397 if( acount ) {
398 lpta( p->in.right );
399 }
400 }
401 break;
402
403 case ICON:
404 /* look for &name case */
405 if( (id = p->tn.rval) >= 0 && id != NONAME ){
406 q = &stab[id];
407 q->sflags |= (SREF|SSET);
408 q->suse = -lineno;
409 }
410 return;
411
412 case NAME:
413 if( (id = p->tn.rval) >= 0 && id != NONAME ){
414 q = &stab[id];
415 if( (uses&VALUSED) && !(q->sflags&SSET) ){
416 if( q->sclass == AUTO || q->sclass == REGISTER ){
417 if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY ){
418#ifndef FLEXNAMES
419 werror( "%.8s may be used before set", q->sname );
420#else
421 werror( "%s may be used before set", q->sname );
422#endif
423 q->sflags |= SSET;
424 }
425 }
426 }
427 if( uses & VALASGOP ) break; /* not a real use */
428 if( uses & VALSET ) q->sflags |= SSET;
429 if( uses & VALUSED ) q->sflags |= SREF;
430 if( uses & VALADDR ) q->sflags |= (SREF|SSET);
431 if( p->tn.lval == 0 ){
432 lnp->lid = id;
433 lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED);
434 if( ++lnp >= &lnames[LNAMES] ) --lnp;
435 }
436 }
437 return;
438
439 }
440
441 /* recurse, going down the right side first if we can */
442
443 switch( optype(p->in.op) ){
444
445 case BITYPE:
446 np1 = lnp;
447 lprt( p->in.right, down2, use2 );
448 case UTYPE:
449 np2 = lnp;
450 lprt( p->in.left, down1, use1 );
451 }
452
453 if( optype(p->in.op) == BITYPE ){
454 if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */
455 lmerge( np1, np2, 0 );
456 }
457 else lmerge( np1, np2, p->in.op != COLON );
458 /* look for assignments to fields, and complain */
459 if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p );
460 }
461
462 }
463
464lmerge( np1, np2, flag ) struct lnm *np1, *np2; {
465 /* np1 and np2 point to lists of lnm members, for the two sides
466 * of a binary operator
467 * flag is 1 if commutation is possible, 0 otherwise
468 * lmerge returns a merged list, starting at np1, resetting lnp
469 * it also complains, if appropriate, about side effects
470 */
471
472 register struct lnm *npx, *npy;
473
474 for( npx = np2; npx < lnp; ++npx ){
475
476 /* is it already there? */
477 for( npy = np1; npy < np2; ++npy ){
478 if( npx->lid == npy->lid ){ /* yes */
479 if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) )
480 ; /* do nothing */
481 else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) ||
482 (npx->flgs&npy->flgs&VALSET) ){
483#ifndef FLEXNAMES
484 if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname );
485#else
486 if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname );
487#endif
488 }
489 if( npy->flgs == 0 ) npx->flgs = 0;
490 else npy->flgs |= npx->flgs;
491 goto foundit;
492 }
493 }
494
495 /* not there: update entry */
496 np2->lid = npx->lid;
497 np2->flgs = npx->flgs;
498 ++np2;
499
500 foundit: ;
501 }
502
503 /* all finished: merged list is at np1 */
504 lnp = np2;
505 }
506
507efcode(){
508 /* code for the end of a function */
509 register struct symtab *cfp;
510
511 cfp = &stab[curftn];
512 if( retstat & RETVAL ) outdef( cfp, LRV, DECTY );
513 if( !vflag ){
514 vflag = argflag;
515 argflag = 0;
516 }
517 if( retstat == RETVAL+NRETVAL )
518#ifndef FLEXNAMES
519 werror( "function %.8s has return(e); and return;", cfp->sname);
520#else
521 werror( "function %s has return(e); and return;", cfp->sname);
522#endif
523 }
524
525aocode(p) struct symtab *p; {
526 /* called when automatic p removed from stab */
527 register struct symtab *cfs;
528 cfs = &stab[curftn];
529 if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){
530 if( p->sclass == PARAM ){
531#ifndef FLEXNAMES
532 if( vflag ) werror( "argument %.8s unused in function %.8s",
533#else
534 if( vflag ) werror( "argument %s unused in function %s",
535#endif
536 p->sname,
537 cfs->sname );
538 }
539 else {
540#ifndef FLEXNAMES
541 if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s",
542#else
543 if( p->sclass != TYPEDEF ) werror( "%s unused in function %s",
544#endif
545 p->sname, cfs->sname );
546 }
547 }
548
549 if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET &&
550 !ISARY(p->stype) && !ISFTN(p->stype) ){
551
552#ifndef FLEXNAMES
553 werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname );
554#else
555 werror( "%s set but not used in function %s", p->sname, cfs->sname );
556#endif
557 }
558
559 if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){
560#ifndef FLEXNAMES
561 if( dimtab[p->sizoff+1] < 0 ) werror( "structure %.8s never defined", p->sname );
562#else
563 if( dimtab[p->sizoff+1] < 0 ) werror( "structure %s never defined", p->sname );
564#endif
565 }
566
567 }
568
569defnam( p ) register struct symtab *p; {
570 /* define the current location as the name p->sname */
571
572 if( p->sclass == STATIC && p->slevel>1 ) return;
573
574 if( !ISFTN( p->stype ) ) outdef( p, libflag?LIB:LDI, USUAL );
575 }
576
577zecode( n ){
578 /* n integer words of zeros */
579 OFFSZ temp;
580 temp = n;
581 inoff += temp*SZINT;
582 ;
583 }
584
585andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */
586 register r;
587
588 if( p->in.op != NAME ) cerror( "andable error" );
589
590 if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */
591
592 if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0);
593#ifndef FLEXNAMES
594 if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname );
595#else
596 if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname );
597#endif
598 return(1);
599 }
600
601NODE *
602clocal(p) NODE *p; {
603
604 /* this is called to do local transformations on
605 an expression tree preparitory to its being
606 written out in intermediate code.
607 */
608
609 /* the major essential job is rewriting the
610 automatic variables and arguments in terms of
611 REG and OREG nodes */
612 /* conversion ops which are not necessary are also clobbered here */
613 /* in addition, any special features (such as rewriting
614 exclusive or) are easily handled here as well */
615
616 register o;
617 register unsigned t, tl;
618
619 switch( o = p->in.op ){
620
621 case SCONV:
622 case PCONV:
623 if( p->in.left->in.type==ENUMTY ){
624 p->in.left = pconvert( p->in.left );
625 }
626 /* assume conversion takes place; type is inherited */
627 t = p->in.type;
628 tl = p->in.left->in.type;
629 if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG) ){
630 werror( "long assignment may lose accuracy" );
631 }
632 if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){
633 werror( "assignment to long may sign-extend incorrectly" );
634 }
635 if( ISPTR(tl) && ISPTR(t) ){
636 tl = DECREF(tl);
637 t = DECREF(t);
638 switch( ISFTN(t) + ISFTN(tl) ){
639
640 case 0: /* neither is a function pointer */
641 if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){
642 if( hflag||pflag ) werror( "possible pointer alignment problem" );
643 }
644 break;
645
646 case 1:
647 werror( "questionable conversion of function pointer" );
648
649 case 2:
650 ;
651 }
652 }
653 p->in.left->in.type = p->in.type;
654 p->in.left->fn.cdim = p->fn.cdim;
655 p->in.left->fn.csiz = p->fn.csiz;
656 p->in.op = FREE;
657 return( p->in.left );
658
659 case PVCONV:
660 case PMCONV:
661 if( p->in.right->in.op != ICON ) cerror( "bad conversion");
662 p->in.op = FREE;
663 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
664
665 }
666
667 return(p);
668 }
669
670NODE *
671offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */
672 register NODE *p;
673 p = bcon(0);
674 p->tn.lval = off/SZCHAR;
675 return(p);
676 }
677
678noinit(){
679 /* storage class for such as "int a;" */
680 return( pflag ? EXTDEF : EXTERN );
681 }
682
683
684cinit( p, sz ) NODE *p; { /* initialize p into size sz */
685 inoff += sz;
686 if( p->in.op == INIT ){
687 if( p->in.left->in.op == ICON ) return;
688 if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return;
689 }
690 uerror( "illegal initialization" );
691 }
692
693char *
694exname( p ) char *p; {
695 /* make a name look like an external name in the local machine */
696 static char aa[8];
697 register int i;
698
699 if( !pflag ) return(p);
700 for( i=0; i<6; ++i ){
701 if( isupper(*p ) ) aa[i] = tolower( *p );
702 else aa[i] = *p;
703 if( *p ) ++p;
704 }
705 aa[6] = '\0';
706 return( aa );
707 }
708
709char *
710strip(s) char *s; {
711#ifndef FLEXNAMES
712 static char x[LFNM+1];
713#else
714 static char x[BUFSIZ];
715#endif
716 register char *p;
717
718 for( p=x; *s; ++s ){
719 if( *s == '/' ) p=x;
720 else if( *s != '"' ){
721#ifndef FLEXNAMES
722/* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */
723 if( p >= &x[LFNM] )
724 cerror( "filename too long" );
725#endif
726 *p++ = *s;
727 }
728 }
729 *p = '\0';
730#ifndef FLEXNAMES
731 return( x );
732#else
733 return( hash(x) );
734#endif
735 }
736
737fsave( s ) char *s; {
738 static union rec fsname;
739 s = strip( s );
740#ifndef FLEXNAMES
741 if( strncmp( s, fsname.f.fn, LFNM ) ){
742#else
743 if( strcmp(s, fsname.f.fn)) {
744#endif
745 /* new one */
746#ifndef FLEXNAMES
747 strncpy( fsname.f.fn, s, LFNM );
748#else
749 fsname.f.fn = s;
750#endif
751 fsname.f.decflag = LFN;
752 fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
753#ifdef FLEXNAMES
754 fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
755#endif
756 }
757 }
758
759where(f){ /* print true location of error */
760 if( f == 'u' && nerrors>1 ) --nerrors; /* don't get "too many errors" */
761 fprintf( stderr, "%s(%d): ", (f == 'c') ? ftitle : strip(ftitle), lineno );
762 }
763
764 /* a number of dummy routines, unneeded by lint */
765
766branch(n){;}
767defalign(n){;}
768deflab(n){;}
769bycode(t,i){;}
770cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */
771
772fldty(p) struct symtab *p; {
773 ; /* all types are OK here... */
774 }
775
776fldal(t) unsigned t; { /* field alignment... */
777 if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */
778 if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
779 if( pflag ) uerror( "nonportable field type" );
780 }
781 else uerror( "illegal field type" );
782 return(ALINT);
783 }
784
785main( argc, argv ) char *argv[]; {
786 char *p;
787
788 /* handle options */
789
790 for( p=argv[1]; argc>1 && *p; ++p ){
791
792 switch( *p ){
793
794 case '-':
795 continue;
796
797 case '\0':
798 break;
799
800 case 'b':
801 brkflag = 1;
802 continue;
803
804 case 'p':
805 pflag = 1;
806 continue;
807
808 case 'c':
809 cflag = 1;
810 continue;
811
812 case 's':
813 /* for the moment, -s triggers -h */
814
815 case 'h':
816 hflag = 1;
817 continue;
818
819 case 'L':
820 libflag = 1;
821 case 'v':
822 vflag = 0;
823 continue;
824
825 case 'x':
826 xflag = 1;
827 continue;
828
829 case 'a':
830 ++aflag;
831 case 'u': /* done in second pass */
832 case 'n': /* done in shell script */
833 continue;
834
835 case 't':
836 werror( "option %c now default: see `man 6 lint'", *p );
837 continue;
838
839 default:
840 uerror( "illegal option: %c", *p );
841 continue;
842
843 }
844 }
845
846 if( !pflag ){ /* set sizes to sizes of target machine */
847# ifdef gcos
848 SZCHAR = ALCHAR = 9;
849# else
850 SZCHAR = ALCHAR = 8;
851# endif
852 SZINT = ALINT = sizeof(int)*SZCHAR;
853 SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
854 SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
855 SZLONG = ALLONG = sizeof(long)*SZCHAR;
856 SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
857 SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
858 ALSTRUCT = ALINT;
859 /* now, fix some things up for various machines (I wish we had "alignof") */
860
861# ifdef pdp11
862 ALLONG = ALDOUBLE = ALFLOAT = ALINT;
863#endif
864# ifdef ibm
865 ALSTRUCT = ALCHAR;
866#endif
867 }
868
869 return( mainp1( argc, argv ) );
870 }
871
872ctype( type ) unsigned type; { /* are there any funny types? */
873 return( type );
874 }
875
876commdec( i ){
877 /* put out a common declaration */
878 outdef( &stab[i], libflag?LIB:LDC, USUAL );
879 }
880
881isitfloat ( s ) char *s; {
882 /* s is a character string;
883 if floating point is implemented, set dcon to the value of s */
884 /* lint version
885 */
886 dcon = atof( s );
887 return( FCON );
888 }
889
890fldcon( p ) register NODE *p; {
891 /* p is an assignment of a constant to a field */
892 /* check to see if the assignment is going to overflow, or otherwise cause trouble */
893 register s;
894 CONSZ v;
895
896 if( !hflag & !pflag ) return;
897
898 s = UPKFSZ(p->in.left->tn.rval);
899 v = p->in.right->tn.lval;
900
901 switch( p->in.left->in.type ){
902
903 case CHAR:
904 case INT:
905 case SHORT:
906 case LONG:
907 case ENUMTY:
908 if( v>=0 && (v>>(s-1))==0 ) return;
909 werror( "precision lost in assignment to (possibly sign-extended) field" );
910 default:
911 return;
912
913 case UNSIGNED:
914 case UCHAR:
915 case USHORT:
916 case ULONG:
917 if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
918
919 return;
920 }
921
922 }
923
924outdef( p, lty, mode ) struct symtab *p; {
925 /* output a definition for the second pass */
926 /* if mode is > USUAL, it is the number of args */
927 char *fname;
928 TWORD t;
929 int line;
930 static union rec rc;
931
932 if( mode == NOFILE ){
933 fname = "???";
934 line = p->suse;
935 }
936 else if( mode == SVLINE ){
937 fname = ftitle;
938 line = -p->suse;
939 }
940 else {
941 fname = ftitle;
942 line = lineno;
943 }
944 fsave( fname );
945#ifndef FLEXNAMES
946 strncpy( rc.l.name, exname(p->sname), LCHNM );
947#endif
948 rc.l.decflag = lty;
949 t = p->stype;
950 if( mode == DECTY ) t = DECREF(t);
951 rc.l.type.aty = t;
952 rc.l.type.extra = 0;
953 astype( &rc.l.type, p->sizoff );
954 rc.l.nargs = (mode>USUAL) ? mode : 0;
955 rc.l.fline = line;
956 fwrite( (char *)&rc, sizeof(rc), 1, stdout );
957#ifdef FLEXNAMES
958 rc.l.name = exname(p->sname);
959 fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
960#endif
961 }
962int proflg;
963int gdebug;