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