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