|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)lint.c 1.14 (Berkeley) 12/11/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( p->tn.lval == 0 ){ ! 469: lnp->lid = id; ! 470: lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); ! 471: if( ++lnp >= &lnames[LNAMES] ) --lnp; ! 472: } ! 473: } ! 474: return; ! 475: ! 476: } ! 477: ! 478: /* recurse, going down the right side first if we can */ ! 479: ! 480: switch( optype(p->in.op) ){ ! 481: ! 482: case BITYPE: ! 483: np1 = lnp; ! 484: lprt( p->in.right, down2, use2 ); ! 485: case UTYPE: ! 486: np2 = lnp; ! 487: lprt( p->in.left, down1, use1 ); ! 488: } ! 489: ! 490: if( optype(p->in.op) == BITYPE ){ ! 491: if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */ ! 492: lmerge( np1, np2, 0 ); ! 493: } ! 494: else lmerge( np1, np2, p->in.op != COLON ); ! 495: /* look for assignments to fields, and complain */ ! 496: if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p ); ! 497: } ! 498: ! 499: } ! 500: ! 501: lmerge( np1, np2, flag ) struct lnm *np1, *np2; { ! 502: /* np1 and np2 point to lists of lnm members, for the two sides ! 503: * of a binary operator ! 504: * flag is 1 if commutation is possible, 0 otherwise ! 505: * lmerge returns a merged list, starting at np1, resetting lnp ! 506: * it also complains, if appropriate, about side effects ! 507: */ ! 508: ! 509: register struct lnm *npx, *npy; ! 510: ! 511: for( npx = np2; npx < lnp; ++npx ){ ! 512: ! 513: /* is it already there? */ ! 514: for( npy = np1; npy < np2; ++npy ){ ! 515: if( npx->lid == npy->lid ){ /* yes */ ! 516: if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) ! 517: ; /* do nothing */ ! 518: else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || ! 519: (npx->flgs&npy->flgs&VALSET) ){ ! 520: #ifndef FLEXNAMES ! 521: if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); ! 522: #else ! 523: if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname ); ! 524: #endif ! 525: } ! 526: if( npy->flgs == 0 ) npx->flgs = 0; ! 527: else npy->flgs |= npx->flgs; ! 528: goto foundit; ! 529: } ! 530: } ! 531: ! 532: /* not there: update entry */ ! 533: np2->lid = npx->lid; ! 534: np2->flgs = npx->flgs; ! 535: ++np2; ! 536: ! 537: foundit: ; ! 538: } ! 539: ! 540: /* all finished: merged list is at np1 */ ! 541: lnp = np2; ! 542: } ! 543: ! 544: efcode(){ ! 545: /* code for the end of a function */ ! 546: register struct symtab *cfp; ! 547: ! 548: cfp = &stab[curftn]; ! 549: if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) ) ! 550: 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: if( !zflag && dimtab[p->sizoff+1] < 0 ) ! 599: #ifndef FLEXNAMES ! 600: werror( "structure %.8s never defined", p->sname ); ! 601: #else ! 602: werror( "structure %s never defined", p->sname ); ! 603: #endif ! 604: } ! 605: ! 606: } ! 607: ! 608: defnam( p ) register struct symtab *p; { ! 609: /* define the current location as the name p->sname */ ! 610: ! 611: if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return; ! 612: ! 613: if( !ISFTN( p->stype ) ) ! 614: if( p->sclass == STATIC ) outdef( p, LST, USUAL ); ! 615: else outdef( p, libflag?LIB:LDI, USUAL ); ! 616: } ! 617: ! 618: zecode( n ){ ! 619: /* n integer words of zeros */ ! 620: OFFSZ temp; ! 621: temp = n; ! 622: inoff += temp*SZINT; ! 623: ; ! 624: } ! 625: ! 626: andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ ! 627: register r; ! 628: ! 629: if( p->in.op != NAME ) cerror( "andable error" ); ! 630: ! 631: if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */ ! 632: ! 633: if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); ! 634: #ifndef FLEXNAMES ! 635: if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname ); ! 636: #else ! 637: if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname ); ! 638: #endif ! 639: return(1); ! 640: } ! 641: ! 642: NODE * ! 643: clocal(p) NODE *p; { ! 644: ! 645: /* this is called to do local transformations on ! 646: an expression tree preparitory to its being ! 647: written out in intermediate code. ! 648: */ ! 649: ! 650: /* the major essential job is rewriting the ! 651: automatic variables and arguments in terms of ! 652: REG and OREG nodes */ ! 653: /* conversion ops which are not necessary are also clobbered here */ ! 654: /* in addition, any special features (such as rewriting ! 655: exclusive or) are easily handled here as well */ ! 656: ! 657: register o; ! 658: register unsigned t, tl; ! 659: int s; ! 660: ! 661: switch( o = p->in.op ){ ! 662: case NAME: ! 663: { ! 664: extern int didstr, subscr; ! 665: extern NODE * strnodes[]; ! 666: ! 667: if (didstr) { ! 668: didstr = 0; ! 669: strnodes[subscr] = p; ! 670: } ! 671: } ! 672: break; ! 673: ! 674: case SCONV: ! 675: case PCONV: ! 676: if( p->in.left->in.type==ENUMTY ){ ! 677: p->in.left = pconvert( p->in.left ); ! 678: } ! 679: /* assume conversion takes place; type is inherited */ ! 680: t = p->in.type; ! 681: tl = p->in.left->in.type; ! 682: if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){ ! 683: werror( "long assignment may lose accuracy" ); ! 684: } ! 685: if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){ ! 686: werror( "assignment to long may sign-extend incorrectly" ); ! 687: } ! 688: if( ISPTR(tl) && ISPTR(t) ){ ! 689: tl = DECREF(tl); ! 690: t = DECREF(t); ! 691: switch( ISFTN(t) + ISFTN(tl) ){ ! 692: ! 693: case 0: /* neither is a function pointer */ ! 694: if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){ ! 695: if( hflag||pflag ) werror( "possible pointer alignment problem" ); ! 696: } ! 697: break; ! 698: ! 699: case 1: ! 700: werror( "questionable conversion of function pointer" ); ! 701: ! 702: case 2: ! 703: ; ! 704: } ! 705: } ! 706: p->in.left->in.type = p->in.type; ! 707: p->in.left->fn.cdim = p->fn.cdim; ! 708: p->in.left->fn.csiz = p->fn.csiz; ! 709: p->in.op = FREE; ! 710: return( p->in.left ); ! 711: ! 712: case PVCONV: ! 713: case PMCONV: ! 714: if( p->in.right->in.op != ICON ) cerror( "bad conversion"); ! 715: p->in.op = FREE; ! 716: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); ! 717: ! 718: case RS: ! 719: case LS: ! 720: case ASG RS: ! 721: case ASG LS: ! 722: if( p->in.right->in.op != ICON ) ! 723: break; ! 724: s = p->in.right->tn.lval; ! 725: if( s < 0 ) ! 726: werror( "negative shift" ); ! 727: else ! 728: if( s >= dimtab[ p->fn.csiz ] ) ! 729: werror( "shift greater than size of object" ); ! 730: break; ! 731: ! 732: } ! 733: ! 734: return(p); ! 735: } ! 736: ! 737: NODE * ! 738: offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ ! 739: register NODE *p; ! 740: p = bcon(0); ! 741: p->tn.lval = off/SZCHAR; ! 742: return(p); ! 743: } ! 744: ! 745: noinit(){ ! 746: /* storage class for such as "int a;" */ ! 747: return( pflag ? EXTDEF : EXTERN ); ! 748: } ! 749: ! 750: ! 751: cinit( p, sz ) NODE *p; { /* initialize p into size sz */ ! 752: register int id; ! 753: ! 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:LX:Pabchnpuvxz")) != 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 'X': /* debugging, done in first pass */ ! 1315: case 'P': /* debugging, done in second pass */ ! 1316: break; ! 1317: case 'L': ! 1318: libflag = 1; ! 1319: /*FALLTHROUGH*/ ! 1320: case 'v': /* unused arguments in functions */ ! 1321: vflag = 0; ! 1322: break; ! 1323: case 'a': /* long to int assignment */ ! 1324: ++aflag; ! 1325: break; ! 1326: case 'b': /* unreached break statements */ ! 1327: brkflag = 1; ! 1328: break; ! 1329: case 'c': /* questionable casts */ ! 1330: cflag = 1; ! 1331: break; ! 1332: case 'h': /* heuristics */ ! 1333: hflag = 1; ! 1334: break; ! 1335: case 'n': /* standard library check */ ! 1336: nflag = 1; ! 1337: break; ! 1338: case 'p': /* IBM & GCOS portability */ ! 1339: pflag = 1; ! 1340: break; ! 1341: case 'u': /* 2nd pass: undefined or unused */ ! 1342: break; ! 1343: case 'x': /* unused externs */ ! 1344: xflag = 1; ! 1345: break; ! 1346: case 'z': /* use of undefined structures */ ! 1347: zflag = 1; ! 1348: break; ! 1349: case '?': ! 1350: default: ! 1351: fputs("usage: lint [-C lib] [-D def] [-I include] [-U undef] [-Labchnpuvx] file ...\n",stderr); ! 1352: exit(1); ! 1353: } ! 1354: ! 1355: if (!pflag) { /* set sizes to sizes of target machine */ ! 1356: # ifdef gcos ! 1357: SZCHAR = ALCHAR = 9; ! 1358: # else ! 1359: SZCHAR = ALCHAR = 8; ! 1360: # endif ! 1361: SZINT = ALINT = sizeof(int)*SZCHAR; ! 1362: SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; ! 1363: SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; ! 1364: SZLONG = ALLONG = sizeof(long)*SZCHAR; ! 1365: SZSHORT = ALSHORT = sizeof(short)*SZCHAR; ! 1366: SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; ! 1367: ALSTRUCT = ALINT; ! 1368: /* now, fix some things up for various machines (I wish we had "alignof") */ ! 1369: ! 1370: # ifdef pdp11 ! 1371: ALLONG = ALDOUBLE = ALFLOAT = ALINT; ! 1372: # endif ! 1373: # ifdef ibm ! 1374: ALSTRUCT = ALCHAR; ! 1375: # endif ! 1376: } ! 1377: return(mainp1(argc,argv)); ! 1378: } ! 1379: ! 1380: ctype( type ) unsigned type; { /* are there any funny types? */ ! 1381: return( type ); ! 1382: } ! 1383: ! 1384: commdec( i ){ ! 1385: /* put out a common declaration */ ! 1386: if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL ); ! 1387: else outdef( &stab[i], libflag?LIB:LDC, USUAL ); ! 1388: } ! 1389: ! 1390: isitfloat ( s ) char *s; { ! 1391: /* s is a character string; ! 1392: if floating point is implemented, set dcon to the value of s */ ! 1393: /* lint version ! 1394: */ ! 1395: dcon = atof( s ); ! 1396: return( DCON ); ! 1397: } ! 1398: ! 1399: fldcon( p ) register NODE *p; { ! 1400: /* p is an assignment of a constant to a field */ ! 1401: /* check to see if the assignment is going to overflow, or otherwise cause trouble */ ! 1402: register s; ! 1403: CONSZ v; ! 1404: ! 1405: if( !hflag & !pflag ) return; ! 1406: ! 1407: s = UPKFSZ(p->in.left->tn.rval); ! 1408: v = p->in.right->tn.lval; ! 1409: ! 1410: switch( p->in.left->in.type ){ ! 1411: ! 1412: case CHAR: ! 1413: case INT: ! 1414: case SHORT: ! 1415: case LONG: ! 1416: case ENUMTY: ! 1417: if( v>=0 && (v>>(s-1))==0 ) return; ! 1418: werror( "precision lost in assignment to (possibly sign-extended) field" ); ! 1419: default: ! 1420: return; ! 1421: ! 1422: case UNSIGNED: ! 1423: case UCHAR: ! 1424: case USHORT: ! 1425: case ULONG: ! 1426: if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); ! 1427: ! 1428: return; ! 1429: } ! 1430: ! 1431: } ! 1432: ! 1433: outdef( p, lty, mode ) struct symtab *p; { ! 1434: /* output a definition for the second pass */ ! 1435: /* if mode is > USUAL, it is the number of args */ ! 1436: char *fname; ! 1437: TWORD t; ! 1438: int line; ! 1439: static union rec rc; ! 1440: ! 1441: if( mode == NOFILE ){ ! 1442: fname = "???"; ! 1443: line = p->suse; ! 1444: } ! 1445: else if( mode == SVLINE ){ ! 1446: fname = ftitle; ! 1447: line = -p->suse; ! 1448: } ! 1449: else { ! 1450: fname = ftitle; ! 1451: line = lineno; ! 1452: } ! 1453: fsave( fname ); ! 1454: #ifndef FLEXNAMES ! 1455: strncpy( rc.l.name, exname(p->sname), LCHNM ); ! 1456: #endif ! 1457: rc.l.decflag = lty; ! 1458: t = p->stype; ! 1459: if( mode == DECTY ) t = DECREF(t); ! 1460: rc.l.type.aty = t; ! 1461: rc.l.type.extra = 0; ! 1462: rc.l.type.extra1 = 0; ! 1463: astype( &rc.l.type, p->sizoff ); ! 1464: rc.l.nargs = (mode>USUAL) ? mode : 0; ! 1465: rc.l.fline = line; ! 1466: fwrite( (char *)&rc, sizeof(rc), 1, stdout ); ! 1467: #ifdef FLEXNAMES ! 1468: rc.l.name = exname(p->sname); ! 1469: fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout ); ! 1470: #endif ! 1471: } ! 1472: int proflg; ! 1473: int gdebug;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.