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