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