|
|
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.