|
|
1.1 root 1: # include "lmanifest"
2: # include "manifest"
3:
4: # define USED 01
5: # define VUSED 02
6: # define EUSED 04
7: # define RVAL 010
8: # define VARARGS 0100
9:
10: typedef struct { TWORD aty; int extra; } atype;
11:
12: struct line {
13: char name[8];
14: int decflag;
15: atype type;
16: int nargs;
17: atype atyp[50];
18: int fline;
19: char file[100];
20: }
21:
22: l1,
23: l2,
24: *pd, /* pointer to line having definition */
25: *pc, /* pointer to current line read */
26: *p3; /* used for swapping pc and pd */
27:
28: int uses = USED;
29: int hflag = 0;
30: int pflag = 0;
31: int xflag = 0;
32: int uflag = 1;
33:
34:
35: main( argc, argv ) char *argv[]; {
36:
37: register char *p;
38:
39: /* first argument is - options */
40:
41: if( argc>=2 && argv[1][0] == '-' ){
42: for( p=argv[1]; *p; ++p ){
43: switch( *p ){
44:
45: case 'h':
46: hflag = 1;
47: break;
48:
49: case 'p':
50: pflag = 1;
51: break;
52:
53: case 'x':
54: xflag = 1;
55: break;
56:
57: case 'u':
58: uflag = 0;
59: break;
60:
61: }
62: }
63: }
64:
65:
66:
67: pd = &l1;
68: pc = &l2;
69: pd->name[0] = '\0' ;
70: pd->fline = 0;
71: pd->file[0] = '\0';
72: pd->decflag = LDI;
73:
74: /* main loop: read a line;
75: if same as last line, check compatibility
76: if not same as last line, becomes df.
77: */
78:
79: for(;;){
80: lread();
81: if( steq(pc->name, pd->name) ) chkcompat();
82: else {
83: lastone();
84: setuse();
85: p3=pc;
86: pc = pd;
87: pd = p3;
88: }
89: }
90:
91: }
92:
93: lread(){ /* read a line into pc */
94:
95: register i, n;
96:
97: getnam( pc->name );
98:
99: pc->decflag = rdin10();
100: rdinty( &pc->type );
101: n = pc->nargs = rdin10();
102: if( n<0 ) n = -n;
103:
104: for( i=0; i<n; ++i ){
105: rdinty( &pc->atyp[i] );
106: }
107:
108: getnam( pc->file );
109: pc->fline = rdin10();
110:
111: while( getchar() != '\n' ) ; /* VOID */
112: }
113:
114: rdin10(){
115: register val, c, s;
116:
117: val = 0;
118: s = 1;
119:
120: while( (c=getchar()) != '\t' ){
121: if( c <= 0 ) error( "unexpected EOF" );
122: else if( c == '-' ) {
123: s = -1;
124: continue;
125: }
126: else if( c<'0' || c>'9' ) {
127: error("rotten digit: %o\n", c );
128: }
129: val = val*10 + c - '0';
130: }
131: return( val*s );
132: }
133:
134: rdinty( p ) atype *p; {
135: register val, c, s;
136:
137: val = 0;
138: s = 1;
139:
140: while( (c=getchar()) != '\t' && c!= '<' ){
141: if( c <= 0 ) error( "unexpected EOF" );
142: else if( c == '-' ) {
143: s = -1;
144: continue;
145: }
146: else if( c<'0' || c>'7' ) {
147: error("rotten digit: %o\n", c );
148: }
149: val = (val<<3) + c - '0';
150: }
151: p->aty = val*s;
152: if( c == '<' ) p->extra = rdin10();
153: else p->extra = 0;
154: }
155:
156: getnam(p) char *p; {
157: register c;
158: while( (c=getchar()) != '\t' ){
159: if( c == '\n' ) error( "rotten name\n" );
160: if( c <= 0 ) cleanup();
161: *p++ = c;
162: }
163: *p = '\0';
164: }
165:
166: /* VARARGS */
167: error( s, a ) char *s; {
168:
169: fprintf( stderr, "pass 2 error: " );
170: fprintf( stderr, s, a );
171: fprintf( stderr, "\n" );
172: exit(1);
173: }
174:
175: steq(p,q) char *p,*q; { /* check that the p and q names are the same */
176:
177:
178: while( *p == *q ){
179: if( *p == 0 ) return(1);
180: ++p;
181: ++q;
182: }
183:
184: return(0);
185: }
186:
187: chkcompat(){
188: /* are the types, etc. in pc and pd compatible */
189: register int i;
190:
191: setuse();
192:
193: /* argument check */
194:
195: if( pd->decflag & (LDI|LIB|LUV|LUE) ){
196: if( pc->decflag & (LUV|LIB|LUE) ){
197: if( pd->nargs != pc->nargs ){
198: if( !(uses&VARARGS) ){
199: printf( "%.7s: variable # of args.", pd->name );
200: viceversa();
201: }
202: if( pc->nargs > pd->nargs ) pc->nargs = pd->nargs;
203: if( !(pd->decflag & (LDI|LIB) ) ) {
204: pd->nargs = pc->nargs;
205: uses |= VARARGS;
206: }
207: }
208: for( i=0; i<pc->nargs; ++i ){
209: if( chktype(&pd->atyp[i], &pc->atyp[i]) ){
210: printf( "%.7s, arg. %d used inconsistently",
211: pd->name, i+1 );
212: viceversa();
213: }
214: }
215: }
216: }
217:
218: if( (pd->decflag&(LDI|LIB|LUV)) && pc->decflag==LUV ){
219: if( chktype( &pc->type, &pd->type ) ){
220: printf( "%.7s value used inconsistently", pd->name );
221: viceversa();
222: }
223: }
224:
225: /* check for multiple declaration */
226:
227: if( (pd->decflag&LDI) && (pc->decflag&(LDI|LIB)) ){
228: printf( "%.7s multiply declared", pd->name );
229: viceversa();
230: }
231:
232: /* do a bit of checking of definitions and uses... */
233:
234: if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & (LDX|LDC)) && pd->type.aty != pc->type.aty ){
235: printf( "%.7s value declared inconsistently", pd->name );
236: viceversa();
237: }
238:
239: /* better not call functions which are declared to be structure or union returning */
240:
241: if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & LUE) && pd->type.aty != pc->type.aty ){
242: /* only matters if the function returns union or structure */
243: TWORD ty;
244: ty = pd->type.aty;
245: if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
246: printf( "%.7s function value type must be declared before use", pd->name );
247: viceversa();
248: }
249: }
250:
251: if( pflag && pd->decflag==LDX && pc->decflag == LUM && !ISFTN(pd->type.aty) ){
252: /* make the external declaration go away */
253: /* in effect, it was used without being defined */
254:
255: /* swap pc and pd */
256: p3 = pc;
257: pc = pd;
258: pd = p3;
259: }
260:
261: }
262:
263: viceversa(){
264: /* print out file comparison */
265: printf( " %s(%d) :: %s(%d)\n", pd->file, pd->fline, pc->file, pc->fline );
266: }
267:
268: /* messages for defintion/use */
269: char *
270: mess[2][2] = {
271: "",
272: "%.7s used( %s(%d) ), but not defined\n",
273: "%.7s defined( %s(%d) ), but never used\n",
274: "%.7s declared( %s(%d) ), but never used or defined\n"
275: };
276:
277: lastone(){
278:
279: /* called when pc and pd are at last different */
280: register nu, nd;
281:
282: nu = nd = 0;
283:
284: if( !(uses&USED) && pd->decflag != LIB ) {
285: if( !steq(pd->name,"main") )
286: nu = 1;
287: }
288:
289: if( !ISFTN(pd->type.aty) ){
290: switch( pd->decflag ){
291:
292: case LIB:
293: nu = nd = 0; /* don't complain about uses on libraries */
294: break;
295: case LDX:
296: if( !xflag ) break;
297: case LUV:
298: case LUE:
299: case LUM:
300: nd = 1;
301: }
302: }
303:
304: if( uflag && ( nu || nd ) ) printf( mess[nu][nd], pd->name, pd->file, pd->fline );
305:
306: if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
307: printf( "%.7s returns value which is %s ignored\n", pd->name,
308: uses&VUSED ? "sometimes" : "always" );
309: }
310:
311: if( (uses&(RVAL+VUSED)) == (VUSED) && (pd->decflag&(LDI|LIB)) ){
312: printf( "%.7s value is used, but none returned\n", pd->name );
313: }
314:
315: /* clean up pc, in preparation for the next thing */
316:
317: uses = 0;
318: if( pc->nargs < 0 ){
319: pc->nargs = -pc->nargs;
320: uses = VARARGS;
321: }
322:
323: }
324:
325: cleanup(){ /* call lastone and die gracefully */
326: lastone();
327: exit(0);
328: }
329:
330: setuse(){ /* check new type to ensure that it is used */
331:
332: switch( pc->decflag ){
333:
334: case LRV:
335: uses |= RVAL;
336: return;
337: case LUV:
338: uses |= VUSED+USED;
339: return;
340: case LUE:
341: uses |= EUSED+USED;
342: return;
343: case LUM:
344: uses |= USED;
345: return;
346:
347: }
348: }
349:
350: chktype( pt1, pt2 ) register atype *pt1, *pt2; {
351:
352: /* check the two type words to see if they are compatible */
353: /* for the moment, enums are turned into ints, and should be checked as such */
354: if( pt1->aty == ENUMTY ) pt1->aty = INT;
355: if( pt2->aty == ENUMTY ) pt2->aty = INT;
356:
357: if( pt2->extra ){ /* constant passed in */
358: if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
359: else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
360: }
361: else if( pt1->extra ){ /* for symmetry */
362: if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
363: else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
364: }
365:
366: return( pt1->aty != pt2->aty );
367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.