|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)lint.c 1.12 (Berkeley) 4/13/87"; ! 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 nflag = 0; /* avoid gripes about printf et al. */ ! 32: int vflag = 1; /* tell about unused argments */ ! 33: int xflag = 0; /* tell about unused externals */ ! 34: int argflag = 0; /* used to turn off complaints about arguments */ ! 35: int libflag = 0; /* used to generate library descriptions */ ! 36: int vaflag = -1; /* signal functions with a variable number of args */ ! 37: int aflag = 0; /* used to check precision of assignments */ ! 38: int zflag = 0; /* no 'structure never defined' error */ ! 39: int Cflag = 0; /* filter out certain output, for generating libraries */ ! 40: char *libname = 0; /* name of the library we're generating */ ! 41: ! 42: /* flags for the "outdef" function */ ! 43: # define USUAL (-101) ! 44: # define DECTY (-102) ! 45: # define NOFILE (-103) ! 46: # define SVLINE (-104) ! 47: ! 48: # define LNAMES 250 ! 49: ! 50: struct lnm { ! 51: short lid, flgs; ! 52: } lnames[LNAMES], *lnp; ! 53: ! 54: contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; { ! 55: ! 56: *pl = *pr = VAL; ! 57: switch( p->in.op ){ ! 58: ! 59: case ANDAND: ! 60: case OROR: ! 61: case QUEST: ! 62: *pr = down; ! 63: break; ! 64: ! 65: case SCONV: ! 66: case PCONV: ! 67: case COLON: ! 68: *pr = *pl = down; ! 69: break; ! 70: ! 71: case COMOP: ! 72: *pl = EFF; ! 73: *pr = down; ! 74: ! 75: case FORCE: ! 76: case INIT: ! 77: case UNARY CALL: ! 78: case STCALL: ! 79: case UNARY STCALL: ! 80: case CALL: ! 81: case UNARY FORTCALL: ! 82: case FORTCALL: ! 83: case CBRANCH: ! 84: break; ! 85: ! 86: default: ! 87: if( asgop(p->in.op) ) break; ! 88: if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) { ! 89: /* struct x f( ); main( ) { (void) f( ); } ! 90: * the the cast call appears as U* UNDEF ! 91: */ ! 92: break; /* the compiler does this... */ ! 93: } ! 94: if( down == EFF && hflag ) werror( "null effect" ); ! 95: ! 96: } ! 97: } ! 98: ! 99: ecode( p ) NODE *p; { ! 100: /* compile code for p */ ! 101: ! 102: fwalk( p, contx, EFF ); ! 103: lnp = lnames; ! 104: lprt( p, EFF, 0 ); ! 105: strforget(); ! 106: } ! 107: ! 108: ejobcode( flag ){ ! 109: /* called after processing each job */ ! 110: /* flag is nonzero if errors were detected */ ! 111: register k; ! 112: register struct symtab *p; ! 113: ! 114: for( p=stab; p< &stab[SYMTSZ]; ++p ){ ! 115: ! 116: if( p->stype != TNULL ) { ! 117: ! 118: if( p->stype == STRTY || p->stype == UNIONTY ){ ! 119: if( !zflag && dimtab[p->sizoff+1] < 0 ){ ! 120: /* never defined */ ! 121: #ifndef FLEXNAMES ! 122: if( hflag ) werror( "struct/union %.8s never defined", p->sname ); ! 123: #else ! 124: if( hflag ) werror( "struct/union %s never defined", p->sname ); ! 125: #endif ! 126: } ! 127: } ! 128: ! 129: switch( p->sclass ){ ! 130: ! 131: case STATIC: ! 132: if( p->suse > 0 ){ ! 133: k = lineno; ! 134: lineno = p->suse; ! 135: #ifndef FLEXNAMES ! 136: uerror( "static variable %.8s unused", ! 137: #else ! 138: uerror( "static variable %s unused", ! 139: #endif ! 140: p->sname ); ! 141: lineno = k; ! 142: break; ! 143: } ! 144: /* no statics in libraries */ ! 145: if( Cflag ) break; ! 146: ! 147: case EXTERN: ! 148: case USTATIC: ! 149: /* with the xflag, worry about externs not used */ ! 150: /* the filename may be wrong here... */ ! 151: if( xflag && p->suse >= 0 && !libflag ){ ! 152: outdef( p, LDX, NOFILE ); ! 153: } ! 154: ! 155: case EXTDEF: ! 156: if( p->suse < 0 ){ /* used */ ! 157: outdef( p, LUM, SVLINE ); ! 158: } ! 159: break; ! 160: } ! 161: ! 162: } ! 163: ! 164: } ! 165: exit( 0 ); ! 166: } ! 167: ! 168: astype( t, i ) ATYPE *t; { ! 169: TWORD tt; ! 170: int j, k=0, l=0; ! 171: ! 172: if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){ ! 173: if( i<0 || i>= DIMTABSZ-3 ){ ! 174: werror( "lint's little mind is blown" ); ! 175: } ! 176: else { ! 177: j = dimtab[i+3]; ! 178: if( j<0 || j>SYMTSZ ){ ! 179: k = dimtab[i]; ! 180: l = X_NONAME | stab[j].suse; ! 181: } ! 182: else { ! 183: if( stab[j].suse <= 0 ) { ! 184: #ifndef FLEXNAMES ! 185: werror( "no line number for %.8s", ! 186: #else ! 187: werror( "no line number for %s", ! 188: #endif ! 189: stab[j].sname ); ! 190: } ! 191: else { ! 192: k = dimtab[i]; ! 193: #ifdef FLEXNAMES ! 194: l = hashstr(stab[j].sname); ! 195: #else ! 196: l = hashstr(stab[j].sname, LCHNM); ! 197: #endif ! 198: } ! 199: } ! 200: } ! 201: ! 202: t->extra = k; ! 203: t->extra1 = l; ! 204: return( 1 ); ! 205: } ! 206: else return( 0 ); ! 207: } ! 208: ! 209: bfcode( a, n ) int a[]; { ! 210: /* code for the beginning of a function; a is an array of ! 211: indices in stab for the arguments; n is the number */ ! 212: /* this must also set retlab */ ! 213: register i; ! 214: register struct symtab *cfp; ! 215: static ATYPE t; ! 216: ! 217: strforget(); ! 218: retlab = 1; ! 219: ! 220: cfp = &stab[curftn]; ! 221: ! 222: /* if creating library, don't do static functions */ ! 223: if( Cflag && cfp->sclass == STATIC ) return; ! 224: ! 225: /* if variable number of arguments, only print the ones which will be checked */ ! 226: if( vaflag > 0 ){ ! 227: if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" ); ! 228: else n = vaflag; ! 229: } ! 230: fsave( ftitle ); ! 231: if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?-n:n ); ! 232: else outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n ); ! 233: vaflag = -1; ! 234: ! 235: /* output the arguments */ ! 236: if( n ){ ! 237: for( i=0; i<n; ++i ) { ! 238: t.aty = stab[a[i]].stype; ! 239: t.extra = 0; ! 240: t.extra1 = 0; ! 241: if( !astype( &t, stab[a[i]].sizoff ) ) { ! 242: switch( t.aty ){ ! 243: ! 244: case ULONG: ! 245: break; ! 246: ! 247: case CHAR: ! 248: case SHORT: ! 249: t.aty = INT; ! 250: break; ! 251: ! 252: case UCHAR: ! 253: case USHORT: ! 254: case UNSIGNED: ! 255: t.aty = UNSIGNED; ! 256: break; ! 257: ! 258: } ! 259: } ! 260: fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); ! 261: } ! 262: } ! 263: } ! 264: ! 265: ctargs( p ) NODE *p; { ! 266: /* count arguments; p points to at least one */ ! 267: /* the arguemnts are a tower of commas to the left */ ! 268: register c; ! 269: c = 1; /* count the rhs */ ! 270: while( p->in.op == CM ){ ! 271: ++c; ! 272: p = p->in.left; ! 273: } ! 274: return( c ); ! 275: } ! 276: ! 277: lpta( p ) NODE *p; { ! 278: static ATYPE t; ! 279: ! 280: if( p->in.op == CM ){ ! 281: lpta( p->in.left ); ! 282: p = p->in.right; ! 283: } ! 284: ! 285: t.aty = p->in.type; ! 286: t.extra = (p->in.op==ICON); ! 287: t.extra1 = 0; ! 288: ! 289: if( !astype( &t, p->fn.csiz ) ) { ! 290: switch( t.aty ){ ! 291: ! 292: case CHAR: ! 293: case SHORT: ! 294: t.aty = INT; ! 295: case LONG: ! 296: case ULONG: ! 297: case INT: ! 298: case UNSIGNED: ! 299: break; ! 300: ! 301: case UCHAR: ! 302: case USHORT: ! 303: t.aty = UNSIGNED; ! 304: break; ! 305: ! 306: case FLOAT: ! 307: t.aty = DOUBLE; ! 308: t.extra = 0; ! 309: break; ! 310: ! 311: default: ! 312: t.extra = 0; ! 313: break; ! 314: } ! 315: } ! 316: fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); ! 317: } ! 318: ! 319: # define VALSET 1 ! 320: # define VALUSED 2 ! 321: # define VALASGOP 4 ! 322: # define VALADDR 8 ! 323: ! 324: lprt( p, down, uses ) register NODE *p; { ! 325: register struct symtab *q; ! 326: register id; ! 327: register acount; ! 328: register down1, down2; ! 329: register use1, use2; ! 330: register struct lnm *np1, *np2; ! 331: ! 332: /* first, set variables which are set... */ ! 333: ! 334: use1 = use2 = VALUSED; ! 335: if( p->in.op == ASSIGN ) use1 = VALSET; ! 336: else if( p->in.op == UNARY AND ) use1 = VALADDR; ! 337: else if( asgop( p->in.op ) ){ /* =ops */ ! 338: use1 = VALUSED|VALSET; ! 339: if( down == EFF ) use1 |= VALASGOP; ! 340: } ! 341: ! 342: ! 343: /* print the lines for lint */ ! 344: ! 345: down2 = down1 = VAL; ! 346: acount = 0; ! 347: ! 348: switch( p->in.op ){ ! 349: ! 350: case EQ: ! 351: case NE: ! 352: case GT: ! 353: case GE: ! 354: case LT: ! 355: case LE: ! 356: if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){ ! 357: werror( "nonportable character comparison" ); ! 358: } ! 359: if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){ ! 360: if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){ ! 361: werror( "comparison of unsigned with negative constant" ); ! 362: } ! 363: } ! 364: break; ! 365: ! 366: case UGE: ! 367: case ULT: ! 368: if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){ ! 369: werror( "unsigned comparison with 0?" ); ! 370: break; ! 371: } ! 372: case UGT: ! 373: case ULE: ! 374: 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 ){ ! 375: werror( "degenerate unsigned comparison" ); ! 376: } ! 377: break; ! 378: ! 379: case COMOP: ! 380: down1 = EFF; ! 381: ! 382: case ANDAND: ! 383: case OROR: ! 384: case QUEST: ! 385: down2 = down; ! 386: /* go recursively left, then right */ ! 387: np1 = lnp; ! 388: lprt( p->in.left, down1, use1 ); ! 389: np2 = lnp; ! 390: lprt( p->in.right, down2, use2 ); ! 391: lmerge( np1, np2, 0 ); ! 392: return; ! 393: ! 394: case SCONV: ! 395: case PCONV: ! 396: case COLON: ! 397: down1 = down2 = down; ! 398: break; ! 399: ! 400: case CALL: ! 401: case STCALL: ! 402: case FORTCALL: ! 403: acount = ctargs( p->in.right ); ! 404: case UNARY CALL: ! 405: case UNARY STCALL: ! 406: case UNARY FORTCALL: ! 407: if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */ ! 408: struct symtab *sp = &stab[id]; ! 409: int lty; ! 410: ! 411: fsave( ftitle ); ! 412: if (!nflag) ! 413: doform(p, sp, acount); ! 414: /* ! 415: * if we're generating a library -C then ! 416: * we don't want to output references to functions ! 417: */ ! 418: if( Cflag ) break; ! 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: outdef( sp, lty, acount ); ! 434: if( acount ) { ! 435: lpta( p->in.right ); ! 436: } ! 437: } ! 438: break; ! 439: ! 440: case ICON: ! 441: /* look for &name case */ ! 442: if( (id = p->tn.rval) >= 0 && id != NONAME ){ ! 443: q = &stab[id]; ! 444: q->sflags |= (SREF|SSET); ! 445: q->suse = -lineno; ! 446: } ! 447: return; ! 448: ! 449: case NAME: ! 450: if( (id = p->tn.rval) >= 0 && id != NONAME ){ ! 451: q = &stab[id]; ! 452: if( (uses&VALUSED) && !(q->sflags&SSET) ){ ! 453: if( q->sclass == AUTO || q->sclass == REGISTER ){ ! 454: if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){ ! 455: #ifndef FLEXNAMES ! 456: werror( "%.8s may be used before set", q->sname ); ! 457: #else ! 458: werror( "%s may be used before set", q->sname ); ! 459: #endif ! 460: q->sflags |= SSET; ! 461: } ! 462: } ! 463: } ! 464: if( uses & VALASGOP ) break; /* not a real use */ ! 465: if( uses & VALSET ) q->sflags |= SSET; ! 466: if( uses & VALUSED ) q->sflags |= SREF; ! 467: if( uses & VALADDR ) q->sflags |= (SREF|SSET); ! 468: if (uses & (VALSET | VALADDR)) ! 469: q->suse = -lineno; ! 470: if( p->tn.lval == 0 ){ ! 471: lnp->lid = id; ! 472: lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); ! 473: if( ++lnp >= &lnames[LNAMES] ) --lnp; ! 474: } ! 475: } ! 476: return; ! 477: ! 478: } ! 479: ! 480: /* recurse, going down the right side first if we can */ ! 481: ! 482: switch( optype(p->in.op) ){ ! 483: ! 484: case BITYPE: ! 485: np1 = lnp; ! 486: lprt( p->in.right, down2, use2 ); ! 487: case UTYPE: ! 488: np2 = lnp; ! 489: lprt( p->in.left, down1, use1 ); ! 490: } ! 491: ! 492: if( optype(p->in.op) == BITYPE ){ ! 493: if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */ ! 494: lmerge( np1, np2, 0 ); ! 495: } ! 496: else lmerge( np1, np2, p->in.op != COLON ); ! 497: /* look for assignments to fields, and complain */ ! 498: if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p ); ! 499: } ! 500: ! 501: } ! 502: ! 503: lmerge( np1, np2, flag ) struct lnm *np1, *np2; { ! 504: /* np1 and np2 point to lists of lnm members, for the two sides ! 505: * of a binary operator ! 506: * flag is 1 if commutation is possible, 0 otherwise ! 507: * lmerge returns a merged list, starting at np1, resetting lnp ! 508: * it also complains, if appropriate, about side effects ! 509: */ ! 510: ! 511: register struct lnm *npx, *npy; ! 512: ! 513: for( npx = np2; npx < lnp; ++npx ){ ! 514: ! 515: /* is it already there? */ ! 516: for( npy = np1; npy < np2; ++npy ){ ! 517: if( npx->lid == npy->lid ){ /* yes */ ! 518: if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) ! 519: ; /* do nothing */ ! 520: else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || ! 521: (npx->flgs&npy->flgs&VALSET) ){ ! 522: #ifndef FLEXNAMES ! 523: if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); ! 524: #else ! 525: if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname ); ! 526: #endif ! 527: } ! 528: if( npy->flgs == 0 ) npx->flgs = 0; ! 529: else npy->flgs |= npx->flgs; ! 530: goto foundit; ! 531: } ! 532: } ! 533: ! 534: /* not there: update entry */ ! 535: np2->lid = npx->lid; ! 536: np2->flgs = npx->flgs; ! 537: ++np2; ! 538: ! 539: foundit: ; ! 540: } ! 541: ! 542: /* all finished: merged list is at np1 */ ! 543: lnp = np2; ! 544: } ! 545: ! 546: efcode(){ ! 547: /* code for the end of a function */ ! 548: register struct symtab *cfp; ! 549: ! 550: cfp = &stab[curftn]; ! 551: if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) ) ! 552: outdef( cfp, LRV, DECTY ); ! 553: if( !vflag ){ ! 554: vflag = argflag; ! 555: argflag = 0; ! 556: } ! 557: if( retstat == RETVAL+NRETVAL ) ! 558: #ifndef FLEXNAMES ! 559: werror( "function %.8s has return(e); and return;", cfp->sname); ! 560: #else ! 561: werror( "function %s has return(e); and return;", cfp->sname); ! 562: #endif ! 563: } ! 564: ! 565: aocode(p) struct symtab *p; { ! 566: /* called when automatic p removed from stab */ ! 567: register struct symtab *cfs; ! 568: cfs = &stab[curftn]; ! 569: if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){ ! 570: if( p->sclass == PARAM ){ ! 571: #ifndef FLEXNAMES ! 572: if( vflag ) werror( "argument %.8s unused in function %.8s", ! 573: #else ! 574: if( vflag ) werror( "argument %s unused in function %s", ! 575: #endif ! 576: p->sname, ! 577: cfs->sname ); ! 578: } ! 579: else { ! 580: #ifndef FLEXNAMES ! 581: if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s", ! 582: #else ! 583: if( p->sclass != TYPEDEF ) werror( "%s unused in function %s", ! 584: #endif ! 585: p->sname, cfs->sname ); ! 586: } ! 587: } ! 588: ! 589: if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET && ! 590: !ISARY(p->stype) && !ISFTN(p->stype) ){ ! 591: ! 592: #ifndef FLEXNAMES ! 593: werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname ); ! 594: #else ! 595: werror( "%s set but not used in function %s", p->sname, cfs->sname ); ! 596: #endif ! 597: } ! 598: ! 599: if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){ ! 600: if( !zflag && dimtab[p->sizoff+1] < 0 ) ! 601: #ifndef FLEXNAMES ! 602: werror( "structure %.8s never defined", p->sname ); ! 603: #else ! 604: werror( "structure %s never defined", p->sname ); ! 605: #endif ! 606: } ! 607: ! 608: } ! 609: ! 610: defnam( p ) register struct symtab *p; { ! 611: /* define the current location as the name p->sname */ ! 612: ! 613: if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return; ! 614: ! 615: if( !ISFTN( p->stype ) ) ! 616: if( p->sclass == STATIC ) outdef( p, LST, USUAL ); ! 617: else outdef( p, libflag?LIB:LDI, USUAL ); ! 618: } ! 619: ! 620: zecode( n ){ ! 621: /* n integer words of zeros */ ! 622: OFFSZ temp; ! 623: temp = n; ! 624: inoff += temp*SZINT; ! 625: ; ! 626: } ! 627: ! 628: andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ ! 629: register r; ! 630: ! 631: if( p->in.op != NAME ) cerror( "andable error" ); ! 632: ! 633: if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */ ! 634: ! 635: if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); ! 636: #ifndef FLEXNAMES ! 637: if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname ); ! 638: #else ! 639: if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname ); ! 640: #endif ! 641: return(1); ! 642: } ! 643: ! 644: NODE * ! 645: clocal(p) NODE *p; { ! 646: ! 647: /* this is called to do local transformations on ! 648: an expression tree preparitory to its being ! 649: written out in intermediate code. ! 650: */ ! 651: ! 652: /* the major essential job is rewriting the ! 653: automatic variables and arguments in terms of ! 654: REG and OREG nodes */ ! 655: /* conversion ops which are not necessary are also clobbered here */ ! 656: /* in addition, any special features (such as rewriting ! 657: exclusive or) are easily handled here as well */ ! 658: ! 659: register o; ! 660: register unsigned t, tl; ! 661: int s; ! 662: ! 663: switch( o = p->in.op ){ ! 664: case NAME: ! 665: { ! 666: extern int didstr, subscr; ! 667: extern NODE * strnodes[]; ! 668: ! 669: if (didstr) { ! 670: didstr = 0; ! 671: strnodes[subscr] = p; ! 672: } ! 673: } ! 674: break; ! 675: ! 676: case SCONV: ! 677: case PCONV: ! 678: if( p->in.left->in.type==ENUMTY ){ ! 679: p->in.left = pconvert( p->in.left ); ! 680: } ! 681: /* assume conversion takes place; type is inherited */ ! 682: t = p->in.type; ! 683: tl = p->in.left->in.type; ! 684: if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){ ! 685: werror( "long assignment may lose accuracy" ); ! 686: } ! 687: if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){ ! 688: werror( "assignment to long may sign-extend incorrectly" ); ! 689: } ! 690: if( ISPTR(tl) && ISPTR(t) ){ ! 691: tl = DECREF(tl); ! 692: t = DECREF(t); ! 693: switch( ISFTN(t) + ISFTN(tl) ){ ! 694: ! 695: case 0: /* neither is a function pointer */ ! 696: if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){ ! 697: if( hflag||pflag ) werror( "possible pointer alignment problem" ); ! 698: } ! 699: break; ! 700: ! 701: case 1: ! 702: werror( "questionable conversion of function pointer" ); ! 703: ! 704: case 2: ! 705: ; ! 706: } ! 707: } ! 708: p->in.left->in.type = p->in.type; ! 709: p->in.left->fn.cdim = p->fn.cdim; ! 710: p->in.left->fn.csiz = p->fn.csiz; ! 711: p->in.op = FREE; ! 712: return( p->in.left ); ! 713: ! 714: case PVCONV: ! 715: case PMCONV: ! 716: if( p->in.right->in.op != ICON ) cerror( "bad conversion"); ! 717: p->in.op = FREE; ! 718: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); ! 719: ! 720: case RS: ! 721: case LS: ! 722: case ASG RS: ! 723: case ASG LS: ! 724: if( p->in.right->in.op != ICON ) ! 725: break; ! 726: s = p->in.right->tn.lval; ! 727: if( s < 0 ) ! 728: werror( "negative shift" ); ! 729: else ! 730: if( s >= dimtab[ p->fn.csiz ] ) ! 731: werror( "shift greater than size of object" ); ! 732: break; ! 733: ! 734: } ! 735: ! 736: return(p); ! 737: } ! 738: ! 739: NODE * ! 740: offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ ! 741: register NODE *p; ! 742: p = bcon(0); ! 743: p->tn.lval = off/SZCHAR; ! 744: return(p); ! 745: } ! 746: ! 747: noinit(){ ! 748: /* storage class for such as "int a;" */ ! 749: return( pflag ? EXTDEF : EXTERN ); ! 750: } ! 751: ! 752: ! 753: cinit( p, sz ) NODE *p; { /* initialize p into size sz */ ! 754: inoff += sz; ! 755: if( p->in.op == INIT ){ ! 756: if( p->in.left->in.op == ICON ) return; ! 757: if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return; ! 758: } ! 759: uerror( "illegal initialization" ); ! 760: } ! 761: ! 762: char * ! 763: exname( p ) char *p; { ! 764: /* make a name look like an external name in the local machine */ ! 765: static char aa[8]; ! 766: register int i; ! 767: ! 768: if( !pflag ) return(p); ! 769: for( i=0; i<6; ++i ){ ! 770: if( isupper(*p ) ) aa[i] = tolower( *p ); ! 771: else aa[i] = *p; ! 772: if( *p ) ++p; ! 773: } ! 774: aa[6] = '\0'; ! 775: return( aa ); ! 776: } ! 777: ! 778: char * ! 779: strip(s) char *s; { ! 780: #ifndef FLEXNAMES ! 781: static char x[LFNM+1]; ! 782: #else ! 783: static char x[BUFSIZ]; ! 784: #endif ! 785: register char *p; ! 786: static int stripping = 0; ! 787: ! 788: if (stripping) ! 789: return(s); ! 790: stripping++; ! 791: for( p=x; *s; ++s ){ ! 792: if( *s != '"' ){ ! 793: #ifndef FLEXNAMES ! 794: /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */ ! 795: if( p >= &x[LFNM] ) ! 796: #else ! 797: if( p >= &x[BUFSIZ] ) ! 798: #endif ! 799: cerror( "filename too long" ); ! 800: *p++ = *s; ! 801: } ! 802: } ! 803: stripping = 0; ! 804: *p = '\0'; ! 805: #ifndef FLEXNAMES ! 806: return( x ); ! 807: #else ! 808: return( hash(x) ); ! 809: #endif ! 810: } ! 811: ! 812: fsave( s ) char *s; { ! 813: static union rec fsname; ! 814: s = strip( s ); ! 815: #ifndef FLEXNAMES ! 816: if( strncmp( s, fsname.f.fn, LFNM ) ) ! 817: #else ! 818: if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn)) ! 819: #endif ! 820: { ! 821: /* new one */ ! 822: #ifndef FLEXNAMES ! 823: strncpy( fsname.f.fn, s, LFNM ); ! 824: #else ! 825: fsname.f.fn = s; ! 826: #endif ! 827: fsname.f.decflag = LFN; ! 828: fwrite( (char *)&fsname, sizeof(fsname), 1, stdout ); ! 829: #ifdef FLEXNAMES ! 830: /* if generating a library, prefix with the library name */ ! 831: /* only do this for flexnames */ ! 832: if( libname ){ ! 833: fwrite( libname, strlen(libname), 1, stdout ); ! 834: putchar( ':' ); ! 835: } ! 836: fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout ); ! 837: #endif ! 838: } ! 839: } ! 840: ! 841: where(f){ /* print true location of error */ ! 842: if( f == 'u' && nerrors > 1 ) ! 843: --nerrors; /* don't get "too many errors" */ ! 844: fprintf( stderr, "%s(%d): ", strip(ftitle), lineno); ! 845: } ! 846: ! 847: /* a number of dummy routines, unneeded by lint */ ! 848: ! 849: branch(n){;} ! 850: defalign(n){;} ! 851: deflab(n){;} ! 852: ! 853: extern char * strchr(); ! 854: ! 855: #define SBUFSIZE 16 ! 856: #define SCLICK 80 ! 857: ! 858: #ifndef size_t ! 859: #define size_t unsigned ! 860: #endif /* !size_t */ ! 861: ! 862: static char * strings[SBUFSIZE]; ! 863: static NODE * strnodes[SBUFSIZE]; ! 864: static int didstr; ! 865: static int subscr; ! 866: static int strapped; ! 867: ! 868: bycode(t, i) ! 869: { ! 870: extern char * calloc(); ! 871: extern char * realloc(); ! 872: ! 873: if (nflag || strapped) ! 874: return; ! 875: if (i == 0) ! 876: if (subscr < (SBUFSIZE - 1)) ! 877: ++subscr; ! 878: if (subscr >= SBUFSIZE) ! 879: return; ! 880: didstr = 1; ! 881: if ((i % SCLICK) == 0) { ! 882: strings[subscr] = (strings[subscr] == NULL) ? ! 883: calloc((size_t) (SCLICK + 1), 1) : ! 884: realloc(strings[subscr], (size_t) (i + SCLICK + 1)); ! 885: if (strings[subscr] == NULL) { ! 886: strapped = 1; ! 887: return; ! 888: } ! 889: } ! 890: strings[subscr][i] = t; ! 891: } ! 892: ! 893: strforget() ! 894: { ! 895: didstr = subscr = 0; ! 896: } ! 897: ! 898: static char * ! 899: typestr(t) ! 900: { ! 901: switch (t) { ! 902: case CHAR: return "char"; ! 903: case UCHAR: return "unsigned char"; ! 904: case SHORT: return "short"; ! 905: case USHORT: return "unsigned short"; ! 906: case INT: return "int"; ! 907: case UNSIGNED: return "unsigned"; ! 908: case ENUMTY: return "enum"; ! 909: case LONG: return "long"; ! 910: case ULONG: return "unsigned long"; ! 911: case FLOAT: return "float"; ! 912: case DOUBLE: return "double"; ! 913: case STRTY: return "struct"; ! 914: case UNIONTY: return "union"; ! 915: case PTR|CHAR: return "char *"; ! 916: case PTR|UCHAR: return "unsigned char *"; ! 917: case PTR|SHORT: return "short *"; ! 918: case PTR|USHORT: return "unsigned short *"; ! 919: case PTR|INT: return "int *"; ! 920: case PTR|UNSIGNED: return "unsigned *"; ! 921: case PTR|ENUMTY: return "enum *"; ! 922: case PTR|LONG: return "long *"; ! 923: case PTR|ULONG: return "unsigned long *"; ! 924: case PTR|FLOAT: return "float *"; ! 925: case PTR|DOUBLE: return "double *"; ! 926: case PTR|STRTY: return "struct *"; ! 927: case PTR|UNIONTY: return "union *"; ! 928: default: return ISPTR(t) ? ! 929: "pointer" : "non-scalar"; ! 930: } ! 931: } ! 932: ! 933: NODE * ! 934: ntharg(p, n, acount) ! 935: NODE * p; ! 936: register int n; ! 937: register int acount; ! 938: { ! 939: if (n > acount) ! 940: return NULL; ! 941: p = p->in.right; ! 942: while (n != acount) { ! 943: p = p->in.left; ! 944: --acount; ! 945: } ! 946: return (n == 1) ? p : p->in.right; ! 947: } ! 948: ! 949: struct entry { ! 950: /* If argument to print/scan is of type... */ int argtype; ! 951: /* ...and this length character is used... */ char lchar; ! 952: /* ...and one of these is control char... */ char * cchars; ! 953: /* ...then use this format with werror... */ char * werror; ! 954: /* ...(where NULL means it's hunky dory)... */ ! 955: }; ! 956: ! 957: /* ! 958: ** Portable printf. ! 959: ** H&S says "%o" takes an unsigned argument; ! 960: ** X3J11 says "%o" takes an int argument; ! 961: ** we'll allow either here. ! 962: */ ! 963: ! 964: static struct entry pprintf[] = { ! 965: CHAR, '\0', "c", NULL, /* this is deliberate */ ! 966: INT, '\0', "cdoxX", NULL, ! 967: UNSIGNED, '\0', "uoxX", NULL, ! 968: CHAR, '\0', "cdoxX", NULL, ! 969: UCHAR, '\0', "udoxX", NULL, /* yes, d is okay */ ! 970: SHORT, '\0', "cdoxX", NULL, ! 971: USHORT, '\0', "uoxX", NULL, ! 972: ENUMTY, '\0', "duoxX", NULL, ! 973: LONG, 'l', "doxX", NULL, ! 974: ULONG, 'l', "uoxX", NULL, ! 975: FLOAT, '\0', "eEfgG", NULL, ! 976: DOUBLE, '\0', "eEfgG", NULL, ! 977: PTR|CHAR, '\0', "s", NULL, ! 978: UNDEF, '\0', "", NULL ! 979: }; ! 980: ! 981: /* ! 982: ** Berkeley printf. ! 983: ** It allows %D, %O, and %U, which we deprecate. ! 984: ** Since ! 985: ** sizeof (char *) == sizeof (int) && ! 986: ** sizeof (int) == sizeof (long) && ! 987: ** sizeof (char *) == sizeof (int *) ! 988: ** you can be lax--and we tolerate *some* laxness. ! 989: ** g/lax/p to find lax table entries and code. ! 990: */ ! 991: ! 992: static char uppercase[] = "deprecated upper-case control character (%c)"; ! 993: #define lax NULL ! 994: ! 995: static struct entry bprintf[] = { ! 996: CHAR, '\0', "c", NULL, /* this is deliberate */ ! 997: INT, '\0', "cdoxX", NULL, ! 998: INT, '\0', "DO", uppercase, ! 999: UNSIGNED, '\0', "uoxX", NULL, ! 1000: UNSIGNED, '\0', "UO", uppercase, ! 1001: CHAR, '\0', "cdoxX", NULL, ! 1002: CHAR, '\0', "DO", uppercase, ! 1003: UCHAR, '\0', "duoxX", NULL, /* yes, d is okay */ ! 1004: UCHAR, '\0', "DUO", uppercase, ! 1005: SHORT, '\0', "cdoxX", NULL, ! 1006: SHORT, '\0', "DO", uppercase, ! 1007: USHORT, '\0', "duoxX", NULL, /* d okay on BSD */ ! 1008: USHORT, '\0', "DUO", uppercase, ! 1009: ENUMTY, '\0', "duoxX", NULL, ! 1010: ENUMTY, '\0', "DUO", uppercase, ! 1011: LONG, '\0', "doxX", lax, ! 1012: LONG, '\0', "DO", uppercase, ! 1013: LONG, 'l', "doxX", NULL, ! 1014: INT, 'l', "doxX", lax, ! 1015: ULONG, '\0', "uoxX", lax, ! 1016: ULONG, '\0', "UO", uppercase, ! 1017: ULONG, 'l', "uoxX", NULL, ! 1018: UNSIGNED, 'l', "uoxX", lax, ! 1019: FLOAT, '\0', "eEfgG", NULL, ! 1020: DOUBLE, '\0', "eEfgG", NULL, ! 1021: PTR|CHAR, '\0', "s", NULL, ! 1022: UNDEF, '\0', NULL, NULL, ! 1023: }; ! 1024: ! 1025: /* ! 1026: ** Portable scanf. 'l' and 'h' are universally ignored preceding 'c' and 's', ! 1027: ** and 'h' is universally ignored preceding 'e' and 'f', ! 1028: ** but you won't find such cruft here. ! 1029: */ ! 1030: ! 1031: static struct entry pscanf[] = { ! 1032: INT, '\0', "dox", NULL, ! 1033: UNSIGNED, '\0', "uox", NULL, ! 1034: CHAR, '\0', "cs[", NULL, ! 1035: SHORT, 'h', "dox", NULL, ! 1036: USHORT, 'h', "uox", NULL, ! 1037: LONG, 'l', "dox", NULL, ! 1038: ULONG, 'l', "uox", NULL, ! 1039: FLOAT, '\0', "ef", NULL, /* BSD doesn't handle g */ ! 1040: DOUBLE, 'l', "ef", NULL, ! 1041: UNDEF, '\0', NULL, NULL, ! 1042: }; ! 1043: ! 1044: /* ! 1045: ** Berkeley scanf. An upper case letter equals an l plus the lower case char, ! 1046: ** but this is deprecated. ! 1047: ** Even though sizeof (int) == sizeof (long), we'll be picky here. ! 1048: */ ! 1049: ! 1050: static struct entry bscanf[] = { ! 1051: INT, '\0', "dox", NULL, ! 1052: UNSIGNED, '\0', "uox", NULL, ! 1053: CHAR, '\0', "cs[", NULL, ! 1054: SHORT, 'h', "dox", NULL, ! 1055: USHORT, 'h', "uox", NULL, ! 1056: LONG, '\0', "dox", lax, ! 1057: LONG, '\0', "DOX", uppercase, ! 1058: LONG, 'l', "dox", NULL, ! 1059: ULONG, '\0', "uox", lax, ! 1060: ULONG, '\0', "UOX", uppercase, ! 1061: ULONG, 'l', "uox", NULL, ! 1062: FLOAT, '\0', "ef", NULL, ! 1063: DOUBLE, '\0', "EF", uppercase, ! 1064: DOUBLE, 'l', "ef", NULL, ! 1065: UNDEF, '\0', NULL, NULL, ! 1066: }; ! 1067: ! 1068: static struct item { ! 1069: char * name; /* such as "printf" */ ! 1070: int isscan; /* scanf/printf */ ! 1071: int fmtarg; /* number of format argument */ ! 1072: struct entry * ptable; /* portable checking table */ ! 1073: struct entry * btable; /* berkeley checking table */ ! 1074: } items[] = { ! 1075: "printf", 0, 1, pprintf, bprintf, ! 1076: "fprintf", 0, 2, pprintf, bprintf, ! 1077: "sprintf", 0, 2, pprintf, bprintf, ! 1078: "scanf", 1, 1, pscanf, bscanf, ! 1079: "fscanf", 1, 2, pscanf, bscanf, ! 1080: "sscanf", 1, 2, pscanf, bscanf, ! 1081: NULL, -1, -1, NULL, NULL ! 1082: }; ! 1083: ! 1084: static char pwf[] = "possible wild format"; ! 1085: static char pfacm[] = "possible format/argument count mismatch"; ! 1086: ! 1087: static struct entry * ! 1088: findlc(ep, lchar, cchar) ! 1089: register struct entry * ep; ! 1090: register int lchar; ! 1091: register int cchar; ! 1092: { ! 1093: for ( ; ep->argtype != UNDEF; ++ep) ! 1094: if (ep->lchar == lchar && strchr(ep->cchars, cchar) != 0) ! 1095: return ep; ! 1096: return NULL; ! 1097: } ! 1098: ! 1099: static char * ! 1100: subform(p, sp, acount) ! 1101: register NODE * p; ! 1102: register struct symtab * sp; ! 1103: { ! 1104: register int i, j, isscan; ! 1105: register NODE * tp; ! 1106: register char * cp; ! 1107: register struct entry * basep; ! 1108: register struct entry * ep; ! 1109: register struct item * ip; ! 1110: register int lchar; ! 1111: register int cchar; ! 1112: register int t; ! 1113: register int suppressed; ! 1114: static char errbuf[132]; ! 1115: ! 1116: if (nflag || strapped) ! 1117: return NULL; ! 1118: cp = sp->sname; ! 1119: for (ip = items; ; ++ip) ! 1120: if (ip->name == NULL) ! 1121: return NULL; /* not a print/scan function */ ! 1122: else if (strcmp(ip->name, sp->sname) == 0) ! 1123: break; ! 1124: isscan = ip->isscan; ! 1125: i = ip->fmtarg; ! 1126: if (i > acount) ! 1127: return NULL; /* handled in pass 2 */ ! 1128: tp = ntharg(p, i, acount); ! 1129: if (tp->in.type != (PTR|CHAR)) ! 1130: return NULL; /* handled in pass 2 */ ! 1131: if (tp->in.op != ICON || tp->tn.lval != 0) ! 1132: return NULL; /* can't check it */ ! 1133: for (j = 1; j <= subscr; ++j) ! 1134: if (tp == strnodes[j]) ! 1135: break; ! 1136: if (j > subscr) ! 1137: return NULL; /* oh well. . . */ ! 1138: cp = strings[j]; ! 1139: /* ! 1140: ** cp now points to format string. ! 1141: */ ! 1142: /* ! 1143: ** For now, ALWAYS use "portable" table, rather than doing this: ! 1144: ** basep = pflag ? ip->ptable : ip->btable; ! 1145: */ ! 1146: basep = ip->ptable; ! 1147: for ( ; ; ) { ! 1148: if (*cp == '\0') ! 1149: return (i == acount) ? NULL : pfacm; ! 1150: if (*cp++ != '%') ! 1151: continue; ! 1152: if (*cp == '\0') ! 1153: return "wild trailing %% in format"; ! 1154: if (*cp == '%') { ! 1155: ++cp; ! 1156: continue; ! 1157: } ! 1158: if (isscan) { ! 1159: suppressed = *cp == '*'; ! 1160: if (suppressed) ! 1161: ++cp; ! 1162: while (isdigit(*cp)) ! 1163: ++cp; ! 1164: if (!suppressed && ++i <= acount) { ! 1165: t = ntharg(p, i, acount)->in.type; ! 1166: if (!ISPTR(t)) { ! 1167: (void) sprintf(errbuf, ! 1168: "%s argument is type (%s) rather than pointer (arg %d)", ! 1169: ip->name, typestr(t), i); ! 1170: return errbuf; ! 1171: } ! 1172: t = DECREF(t); ! 1173: } ! 1174: } else { ! 1175: int nspace, ndash, nplus, nhash; ! 1176: ! 1177: suppressed = 0; ! 1178: nspace = ndash = nplus = nhash = 0; ! 1179: for ( ; ; ) { ! 1180: if (*cp == ' ') ! 1181: ++nspace; ! 1182: else if (*cp == '+') ! 1183: ++nplus; ! 1184: else if (*cp == '-') ! 1185: ++ndash; ! 1186: else if (*cp == '#') ! 1187: ++nhash; ! 1188: else break; ! 1189: ++cp; ! 1190: } ! 1191: if (nspace > 1 || ndash > 1 || nplus > 1 || nhash > 1) ! 1192: return "wild repeated flag character in format"; ! 1193: if (*cp == '*') { ! 1194: ++cp; ! 1195: if (++i > acount) ! 1196: break; ! 1197: t = ntharg(p, i, acount)->in.type; ! 1198: /* ! 1199: ** Width other than INT or UNSIGNED is suspect. ! 1200: */ ! 1201: if (t != INT && t != UNSIGNED) { ! 1202: (void) sprintf(errbuf, ! 1203: "field width argument is type (%s) rather than (int) (arg %d)", ! 1204: typestr(t), i); ! 1205: return errbuf; ! 1206: } ! 1207: } else while (isdigit(*cp)) ! 1208: ++cp; ! 1209: if (*cp == '.') { ! 1210: ++cp; ! 1211: if (*cp == '*') { ! 1212: ++cp; ! 1213: if (++i > acount) ! 1214: return pfacm; ! 1215: t = ntharg(p, i, acount)->in.type; ! 1216: if (t != INT && t != UNSIGNED) { ! 1217: (void) sprintf(errbuf, ! 1218: "precision argument is type (%s) rather than (int) (arg %d)", ! 1219: typestr(t), i); ! 1220: return errbuf; ! 1221: } ! 1222: } else while (isdigit(*cp)) ! 1223: ++cp; ! 1224: } ! 1225: if (++i <= acount) ! 1226: t = ntharg(p, i, acount)->in.type; ! 1227: } ! 1228: if (*cp == 'h' || *cp == 'l') ! 1229: lchar = *cp++; ! 1230: else lchar = '\0'; ! 1231: if ((cchar = *cp++) == '\0') ! 1232: return pwf; ! 1233: if (i > acount) ! 1234: return (findlc(basep, lchar, cchar) == NULL) ? ! 1235: pwf : pfacm; ! 1236: if (!isscan && !pflag && ISPTR(t) && ! 1237: strchr("douxX", cchar) != 0) ! 1238: continue; /* lax--printf("%d", (int *)) */ ! 1239: if (suppressed) { ! 1240: if (findlc(basep, lchar, cchar) == NULL) ! 1241: return pwf; ! 1242: } else for (ep = basep; ; ++ep) { ! 1243: if (ep->argtype == UNDEF) { /* end of table */ ! 1244: ep = findlc(basep, lchar, cchar); ! 1245: if (ep == NULL) ! 1246: return pwf; ! 1247: (void) sprintf(errbuf, "%s: (%s) format, (%s) arg (arg %d)", ! 1248: ip->name, ! 1249: typestr(ep->argtype), ! 1250: typestr(isscan ? (t | PTR) : t), i); ! 1251: return errbuf; ! 1252: } ! 1253: if (ep->argtype == t && ep->lchar == lchar && ! 1254: strchr(ep->cchars, cchar) != 0) ! 1255: if (ep->werror == 0) ! 1256: break; ! 1257: else { ! 1258: werror(ep->werror, cchar); ! 1259: return NULL; ! 1260: } ! 1261: } ! 1262: if (cchar != '[') ! 1263: continue; ! 1264: do { ! 1265: if (*cp == '\0') ! 1266: return "possible unmatched '[' in format"; ! 1267: } while (*cp++ != ']'); ! 1268: } ! 1269: /*NOTREACHED*/ ! 1270: } ! 1271: ! 1272: doform(p, sp, acount) ! 1273: NODE * p; ! 1274: struct symtab * sp; ! 1275: { ! 1276: char * cp; ! 1277: ! 1278: if ((cp = subform(p, sp, acount)) != NULL) ! 1279: werror(cp); ! 1280: } ! 1281: ! 1282: cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */ ! 1283: ! 1284: fldty(p) struct symtab *p; { ! 1285: ; /* all types are OK here... */ ! 1286: } ! 1287: ! 1288: fldal(t) unsigned t; { /* field alignment... */ ! 1289: if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */ ! 1290: if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */ ! 1291: if( pflag ) uerror( "nonportable field type" ); ! 1292: } ! 1293: else uerror( "illegal field type" ); ! 1294: return(ALINT); ! 1295: } ! 1296: ! 1297: main(argc, argv) ! 1298: int argc; ! 1299: char **argv; ! 1300: { ! 1301: extern char *optarg; ! 1302: extern int optind; ! 1303: int ch; ! 1304: ! 1305: while ((ch = getopt(argc,argv,"C:D:I:U:LPabchnpuvxz")) != EOF) ! 1306: switch((char)ch) { ! 1307: case 'C': ! 1308: Cflag = 1; ! 1309: libname = optarg; ! 1310: continue; ! 1311: case 'D': /* #define */ ! 1312: case 'I': /* include path */ ! 1313: case 'U': /* #undef */ ! 1314: case 'P': /* debugging, done in second pass */ ! 1315: break; ! 1316: case 'L': ! 1317: libflag = 1; ! 1318: /*FALLTHROUGH*/ ! 1319: case 'v': /* unused arguments in functions */ ! 1320: vflag = 0; ! 1321: break; ! 1322: case 'a': /* long to int assignment */ ! 1323: ++aflag; ! 1324: break; ! 1325: case 'b': /* unreached break statements */ ! 1326: brkflag = 1; ! 1327: break; ! 1328: case 'c': /* questionable casts */ ! 1329: cflag = 1; ! 1330: break; ! 1331: case 'h': /* heuristics */ ! 1332: hflag = 1; ! 1333: break; ! 1334: case 'n': /* standard library check */ ! 1335: nflag = 1; ! 1336: break; ! 1337: case 'p': /* IBM & GCOS portability */ ! 1338: pflag = 1; ! 1339: break; ! 1340: case 'u': /* 2nd pass: undefined or unused */ ! 1341: break; ! 1342: case 'x': /* unused externs */ ! 1343: xflag = 1; ! 1344: break; ! 1345: case 'z': /* use of undefined structures */ ! 1346: zflag = 1; ! 1347: break; ! 1348: case '?': ! 1349: default: ! 1350: fputs("usage: lint [-C lib] [-D def] [-I include] [-U undef] [-Labchnpuvx] file ...\n",stderr); ! 1351: exit(1); ! 1352: } ! 1353: ! 1354: if (!pflag) { /* set sizes to sizes of target machine */ ! 1355: # ifdef gcos ! 1356: SZCHAR = ALCHAR = 9; ! 1357: # else ! 1358: SZCHAR = ALCHAR = 8; ! 1359: # endif ! 1360: SZINT = ALINT = sizeof(int)*SZCHAR; ! 1361: SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; ! 1362: SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; ! 1363: SZLONG = ALLONG = sizeof(long)*SZCHAR; ! 1364: SZSHORT = ALSHORT = sizeof(short)*SZCHAR; ! 1365: SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; ! 1366: ALSTRUCT = ALINT; ! 1367: /* now, fix some things up for various machines (I wish we had "alignof") */ ! 1368: ! 1369: # ifdef pdp11 ! 1370: ALLONG = ALDOUBLE = ALFLOAT = ALINT; ! 1371: # endif ! 1372: # ifdef ibm ! 1373: ALSTRUCT = ALCHAR; ! 1374: # endif ! 1375: } ! 1376: return(mainp1(argc,argv)); ! 1377: } ! 1378: ! 1379: ctype( type ) unsigned type; { /* are there any funny types? */ ! 1380: return( type ); ! 1381: } ! 1382: ! 1383: commdec( i ){ ! 1384: /* put out a common declaration */ ! 1385: if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL ); ! 1386: else outdef( &stab[i], libflag?LIB:LDC, USUAL ); ! 1387: } ! 1388: ! 1389: isitfloat ( s ) char *s; { ! 1390: /* s is a character string; ! 1391: if floating point is implemented, set dcon to the value of s */ ! 1392: /* lint version ! 1393: */ ! 1394: dcon = atof( s ); ! 1395: return( DCON ); ! 1396: } ! 1397: ! 1398: fldcon( p ) register NODE *p; { ! 1399: /* p is an assignment of a constant to a field */ ! 1400: /* check to see if the assignment is going to overflow, or otherwise cause trouble */ ! 1401: register s; ! 1402: CONSZ v; ! 1403: ! 1404: if( !hflag & !pflag ) return; ! 1405: ! 1406: s = UPKFSZ(p->in.left->tn.rval); ! 1407: v = p->in.right->tn.lval; ! 1408: ! 1409: switch( p->in.left->in.type ){ ! 1410: ! 1411: case CHAR: ! 1412: case INT: ! 1413: case SHORT: ! 1414: case LONG: ! 1415: case ENUMTY: ! 1416: if( v>=0 && (v>>(s-1))==0 ) return; ! 1417: werror( "precision lost in assignment to (possibly sign-extended) field" ); ! 1418: default: ! 1419: return; ! 1420: ! 1421: case UNSIGNED: ! 1422: case UCHAR: ! 1423: case USHORT: ! 1424: case ULONG: ! 1425: if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); ! 1426: ! 1427: return; ! 1428: } ! 1429: ! 1430: } ! 1431: ! 1432: outdef( p, lty, mode ) struct symtab *p; { ! 1433: /* output a definition for the second pass */ ! 1434: /* if mode is > USUAL, it is the number of args */ ! 1435: char *fname; ! 1436: TWORD t; ! 1437: int line; ! 1438: static union rec rc; ! 1439: ! 1440: if( mode == NOFILE ){ ! 1441: fname = "???"; ! 1442: line = p->suse; ! 1443: } ! 1444: else if( mode == SVLINE ){ ! 1445: fname = ftitle; ! 1446: line = -p->suse; ! 1447: } ! 1448: else { ! 1449: fname = ftitle; ! 1450: line = lineno; ! 1451: } ! 1452: fsave( fname ); ! 1453: #ifndef FLEXNAMES ! 1454: strncpy( rc.l.name, exname(p->sname), LCHNM ); ! 1455: #endif ! 1456: rc.l.decflag = lty; ! 1457: t = p->stype; ! 1458: if( mode == DECTY ) t = DECREF(t); ! 1459: rc.l.type.aty = t; ! 1460: rc.l.type.extra = 0; ! 1461: rc.l.type.extra1 = 0; ! 1462: astype( &rc.l.type, p->sizoff ); ! 1463: rc.l.nargs = (mode>USUAL) ? mode : 0; ! 1464: rc.l.fline = line; ! 1465: fwrite( (char *)&rc, sizeof(rc), 1, stdout ); ! 1466: #ifdef FLEXNAMES ! 1467: rc.l.name = exname(p->sname); ! 1468: fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout ); ! 1469: #endif ! 1470: } ! 1471: int proflg; ! 1472: int gdebug;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.