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