17988Srrh #ifndef lint 2*26916Sdonn static char sccsid[] = "@(#)lint.c 1.10 (Berkeley) 03/20/86"; 37988Srrh #endif lint 47988Srrh 518598Sralph # include "pass1.h" 67988Srrh 718598Sralph # include "lmanifest.h" 87988Srrh 97988Srrh # include <ctype.h> 107988Srrh 117988Srrh # define VAL 0 127988Srrh # define EFF 1 137988Srrh 147988Srrh /* these are appropriate for the -p flag */ 157988Srrh int SZCHAR = 8; 167988Srrh int SZINT = 16; 177988Srrh int SZFLOAT = 32; 187988Srrh int SZDOUBLE = 64; 197988Srrh int SZLONG = 32; 207988Srrh int SZSHORT = 16; 217988Srrh int SZPOINT = 16; 227988Srrh int ALCHAR = 8; 237988Srrh int ALINT = 16; 247988Srrh int ALFLOAT = 32; 257988Srrh int ALDOUBLE = 64; 267988Srrh int ALLONG = 32; 277988Srrh int ALSHORT = 16; 287988Srrh int ALPOINT = 16; 297988Srrh int ALSTRUCT = 16; 307988Srrh 317988Srrh int vflag = 1; /* tell about unused argments */ 327988Srrh int xflag = 0; /* tell about unused externals */ 337988Srrh int argflag = 0; /* used to turn off complaints about arguments */ 347988Srrh int libflag = 0; /* used to generate library descriptions */ 357988Srrh int vaflag = -1; /* used to signal functions with a variable number of args */ 367988Srrh int aflag = 0; /* used to check precision of assignments */ 3711761Sedward int zflag = 0; /* no 'structure never defined' error */ 3811403Snicklin int Cflag = 0; /* filter out certain output, for generating libraries */ 3911403Snicklin char *libname = 0; /* name of the library we're generating */ 407988Srrh 417988Srrh /* flags for the "outdef" function */ 427988Srrh # define USUAL (-101) 437988Srrh # define DECTY (-102) 447988Srrh # define NOFILE (-103) 457988Srrh # define SVLINE (-104) 467988Srrh 477988Srrh # define LNAMES 250 487988Srrh 497988Srrh struct lnm { 507988Srrh short lid, flgs; 517988Srrh } lnames[LNAMES], *lnp; 527988Srrh 537988Srrh contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; { 547988Srrh 557988Srrh *pl = *pr = VAL; 567988Srrh switch( p->in.op ){ 577988Srrh 587988Srrh case ANDAND: 597988Srrh case OROR: 607988Srrh case QUEST: 617988Srrh *pr = down; 627988Srrh break; 637988Srrh 647988Srrh case SCONV: 657988Srrh case PCONV: 667988Srrh case COLON: 677988Srrh *pr = *pl = down; 687988Srrh break; 697988Srrh 707988Srrh case COMOP: 717988Srrh *pl = EFF; 727988Srrh *pr = down; 737988Srrh 747988Srrh case FORCE: 757988Srrh case INIT: 767988Srrh case UNARY CALL: 777988Srrh case STCALL: 787988Srrh case UNARY STCALL: 797988Srrh case CALL: 807988Srrh case UNARY FORTCALL: 817988Srrh case FORTCALL: 827988Srrh case CBRANCH: 837988Srrh break; 847988Srrh 857988Srrh default: 867988Srrh if( asgop(p->in.op) ) break; 877988Srrh if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) { 887988Srrh /* struct x f( ); main( ) { (void) f( ); } 897988Srrh * the the cast call appears as U* UNDEF 907988Srrh */ 917988Srrh break; /* the compiler does this... */ 927988Srrh } 937988Srrh if( down == EFF && hflag ) werror( "null effect" ); 947988Srrh 957988Srrh } 967988Srrh } 977988Srrh 987988Srrh ecode( p ) NODE *p; { 997988Srrh /* compile code for p */ 1007988Srrh 1017988Srrh fwalk( p, contx, EFF ); 1027988Srrh lnp = lnames; 1037988Srrh lprt( p, EFF, 0 ); 1047988Srrh } 1057988Srrh 1067988Srrh ejobcode( flag ){ 1077988Srrh /* called after processing each job */ 1087988Srrh /* flag is nonzero if errors were detected */ 1097988Srrh register k; 1107988Srrh register struct symtab *p; 1117988Srrh 1127988Srrh for( p=stab; p< &stab[SYMTSZ]; ++p ){ 1137988Srrh 1147988Srrh if( p->stype != TNULL ) { 1157988Srrh 1167988Srrh if( p->stype == STRTY || p->stype == UNIONTY ){ 11711761Sedward if( !zflag && dimtab[p->sizoff+1] < 0 ){ 11811761Sedward /* never defined */ 1197988Srrh #ifndef FLEXNAMES 1207988Srrh if( hflag ) werror( "struct/union %.8s never defined", p->sname ); 1217988Srrh #else 1227988Srrh if( hflag ) werror( "struct/union %s never defined", p->sname ); 1237988Srrh #endif 1247988Srrh } 1257988Srrh } 1267988Srrh 1277988Srrh switch( p->sclass ){ 1287988Srrh 1297988Srrh case STATIC: 1307988Srrh if( p->suse > 0 ){ 1317988Srrh k = lineno; 1327988Srrh lineno = p->suse; 1337988Srrh #ifndef FLEXNAMES 1347988Srrh uerror( "static variable %.8s unused", 1357988Srrh #else 1367988Srrh uerror( "static variable %s unused", 1377988Srrh #endif 1387988Srrh p->sname ); 1397988Srrh lineno = k; 1407988Srrh break; 1417988Srrh } 14211403Snicklin /* no statics in libraries */ 14311403Snicklin if( Cflag ) break; 1447988Srrh 1457988Srrh case EXTERN: 1467988Srrh case USTATIC: 1477988Srrh /* with the xflag, worry about externs not used */ 1487988Srrh /* the filename may be wrong here... */ 1497988Srrh if( xflag && p->suse >= 0 && !libflag ){ 1507988Srrh outdef( p, LDX, NOFILE ); 1517988Srrh } 1527988Srrh 1537988Srrh case EXTDEF: 1547988Srrh if( p->suse < 0 ){ /* used */ 1557988Srrh outdef( p, LUM, SVLINE ); 1567988Srrh } 1577988Srrh break; 1587988Srrh } 1597988Srrh 1607988Srrh } 1617988Srrh 1627988Srrh } 1637988Srrh exit( 0 ); 1647988Srrh } 1657988Srrh 1667988Srrh astype( t, i ) ATYPE *t; { 1677988Srrh TWORD tt; 16811761Sedward int j, k=0, l=0; 1697988Srrh 1707988Srrh if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){ 1717988Srrh if( i<0 || i>= DIMTABSZ-3 ){ 1727988Srrh werror( "lint's little mind is blown" ); 1737988Srrh } 1747988Srrh else { 1757988Srrh j = dimtab[i+3]; 1767988Srrh if( j<0 || j>SYMTSZ ){ 17711761Sedward k = dimtab[i]; 17811761Sedward l = X_NONAME | stab[j].suse; 1797988Srrh } 1807988Srrh else { 1817988Srrh if( stab[j].suse <= 0 ) { 1827988Srrh #ifndef FLEXNAMES 1837988Srrh werror( "no line number for %.8s", 1847988Srrh #else 1857988Srrh werror( "no line number for %s", 1867988Srrh #endif 1877988Srrh stab[j].sname ); 1887988Srrh } 18911761Sedward else { 19011761Sedward k = dimtab[i]; 19111761Sedward #ifdef FLEXNAMES 19211761Sedward l = hashstr(stab[j].sname); 19311761Sedward #else 19411761Sedward l = hashstr(stab[j].sname, LCHNM); 19511761Sedward #endif 19611761Sedward } 1977988Srrh } 1987988Srrh } 1997988Srrh 2007988Srrh t->extra = k; 20111761Sedward t->extra1 = l; 2027988Srrh return( 1 ); 2037988Srrh } 2047988Srrh else return( 0 ); 2057988Srrh } 2067988Srrh 2077988Srrh bfcode( a, n ) int a[]; { 2087988Srrh /* code for the beginning of a function; a is an array of 2097988Srrh indices in stab for the arguments; n is the number */ 2107988Srrh /* this must also set retlab */ 2117988Srrh register i; 2127988Srrh register struct symtab *cfp; 2137988Srrh static ATYPE t; 2147988Srrh 2157988Srrh retlab = 1; 21611403Snicklin 2177988Srrh cfp = &stab[curftn]; 2187988Srrh 21911403Snicklin /* if creating library, don't do static functions */ 22011403Snicklin if( Cflag && cfp->sclass == STATIC ) return; 22111403Snicklin 2227988Srrh /* if variable number of arguments, only print the ones which will be checked */ 2237988Srrh if( vaflag > 0 ){ 2247988Srrh if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" ); 2257988Srrh else n = vaflag; 2267988Srrh } 2277988Srrh fsave( ftitle ); 22811761Sedward if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?-n:n ); 22911761Sedward else outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n ); 2307988Srrh vaflag = -1; 2317988Srrh 2327988Srrh /* output the arguments */ 2337988Srrh if( n ){ 2347988Srrh for( i=0; i<n; ++i ) { 2357988Srrh t.aty = stab[a[i]].stype; 2367988Srrh t.extra = 0; 23711761Sedward t.extra1 = 0; 2387988Srrh if( !astype( &t, stab[a[i]].sizoff ) ) { 2397988Srrh switch( t.aty ){ 2407988Srrh 2417988Srrh case ULONG: 2427988Srrh break; 2437988Srrh 2447988Srrh case CHAR: 2457988Srrh case SHORT: 2467988Srrh t.aty = INT; 2477988Srrh break; 2487988Srrh 2497988Srrh case UCHAR: 2507988Srrh case USHORT: 2517988Srrh case UNSIGNED: 2527988Srrh t.aty = UNSIGNED; 2537988Srrh break; 2547988Srrh 2557988Srrh } 2567988Srrh } 2577988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 2587988Srrh } 2597988Srrh } 2607988Srrh } 2617988Srrh 2627988Srrh ctargs( p ) NODE *p; { 2637988Srrh /* count arguments; p points to at least one */ 2647988Srrh /* the arguemnts are a tower of commas to the left */ 2657988Srrh register c; 2667988Srrh c = 1; /* count the rhs */ 2677988Srrh while( p->in.op == CM ){ 2687988Srrh ++c; 2697988Srrh p = p->in.left; 2707988Srrh } 2717988Srrh return( c ); 2727988Srrh } 2737988Srrh 2747988Srrh lpta( p ) NODE *p; { 2757988Srrh static ATYPE t; 2767988Srrh 2777988Srrh if( p->in.op == CM ){ 2787988Srrh lpta( p->in.left ); 2797988Srrh p = p->in.right; 2807988Srrh } 2817988Srrh 2827988Srrh t.aty = p->in.type; 2837988Srrh t.extra = (p->in.op==ICON); 28411761Sedward t.extra1 = 0; 2857988Srrh 28618598Sralph if( !astype( &t, p->fn.csiz ) ) { 2877988Srrh switch( t.aty ){ 2887988Srrh 2897988Srrh case CHAR: 2907988Srrh case SHORT: 2917988Srrh t.aty = INT; 2927988Srrh case LONG: 2937988Srrh case ULONG: 2947988Srrh case INT: 2957988Srrh case UNSIGNED: 2967988Srrh break; 2977988Srrh 2987988Srrh case UCHAR: 2997988Srrh case USHORT: 3007988Srrh t.aty = UNSIGNED; 3017988Srrh break; 3027988Srrh 3037988Srrh case FLOAT: 3047988Srrh t.aty = DOUBLE; 3057988Srrh t.extra = 0; 3067988Srrh break; 3077988Srrh 3087988Srrh default: 3097988Srrh t.extra = 0; 3107988Srrh break; 3117988Srrh } 3127988Srrh } 3137988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 3147988Srrh } 3157988Srrh 3167988Srrh # define VALSET 1 3177988Srrh # define VALUSED 2 3187988Srrh # define VALASGOP 4 3197988Srrh # define VALADDR 8 3207988Srrh 3217988Srrh lprt( p, down, uses ) register NODE *p; { 3227988Srrh register struct symtab *q; 3237988Srrh register id; 3247988Srrh register acount; 3257988Srrh register down1, down2; 3267988Srrh register use1, use2; 3277988Srrh register struct lnm *np1, *np2; 3287988Srrh 3297988Srrh /* first, set variables which are set... */ 3307988Srrh 3317988Srrh use1 = use2 = VALUSED; 3327988Srrh if( p->in.op == ASSIGN ) use1 = VALSET; 3337988Srrh else if( p->in.op == UNARY AND ) use1 = VALADDR; 3347988Srrh else if( asgop( p->in.op ) ){ /* =ops */ 3357988Srrh use1 = VALUSED|VALSET; 3367988Srrh if( down == EFF ) use1 |= VALASGOP; 3377988Srrh } 3387988Srrh 3397988Srrh 3407988Srrh /* print the lines for lint */ 3417988Srrh 3427988Srrh down2 = down1 = VAL; 3437988Srrh acount = 0; 3447988Srrh 3457988Srrh switch( p->in.op ){ 3467988Srrh 3477988Srrh case EQ: 3487988Srrh case NE: 3497988Srrh case GT: 3507988Srrh case GE: 3517988Srrh case LT: 3527988Srrh case LE: 3537988Srrh if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){ 3547988Srrh werror( "nonportable character comparison" ); 3557988Srrh } 3567988Srrh if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){ 3577988Srrh if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){ 3587988Srrh werror( "comparison of unsigned with negative constant" ); 3597988Srrh } 3607988Srrh } 3617988Srrh break; 3627988Srrh 3637988Srrh case UGE: 3647988Srrh case ULT: 3657988Srrh if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){ 3667988Srrh werror( "unsigned comparison with 0?" ); 3677988Srrh break; 3687988Srrh } 3697988Srrh case UGT: 3707988Srrh case ULE: 3717988Srrh 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 ){ 3727988Srrh werror( "degenerate unsigned comparison" ); 3737988Srrh } 3747988Srrh break; 3757988Srrh 3767988Srrh case COMOP: 3777988Srrh down1 = EFF; 3787988Srrh 3797988Srrh case ANDAND: 3807988Srrh case OROR: 3817988Srrh case QUEST: 3827988Srrh down2 = down; 3837988Srrh /* go recursively left, then right */ 3847988Srrh np1 = lnp; 3857988Srrh lprt( p->in.left, down1, use1 ); 3867988Srrh np2 = lnp; 3877988Srrh lprt( p->in.right, down2, use2 ); 3887988Srrh lmerge( np1, np2, 0 ); 3897988Srrh return; 3907988Srrh 3917988Srrh case SCONV: 3927988Srrh case PCONV: 3937988Srrh case COLON: 3947988Srrh down1 = down2 = down; 3957988Srrh break; 3967988Srrh 3977988Srrh case CALL: 3987988Srrh case STCALL: 3997988Srrh case FORTCALL: 4007988Srrh acount = ctargs( p->in.right ); 4017988Srrh case UNARY CALL: 4027988Srrh case UNARY STCALL: 4037988Srrh case UNARY FORTCALL: 4047988Srrh if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */ 4057988Srrh struct symtab *sp = &stab[id]; 4067988Srrh int lty; 40711403Snicklin 40811403Snicklin fsave( ftitle ); 40911403Snicklin /* 41011403Snicklin * if we're generating a library -C then 41111403Snicklin * we don't want to output references to functions 41211403Snicklin */ 41311403Snicklin if( Cflag ) break; 4147988Srrh /* if a function used in an effects context is 4157988Srrh * cast to type void then consider its value 4167988Srrh * to have been disposed of properly 4177988Srrh * thus a call of type undef in an effects 4187988Srrh * context is construed to be used in a value 4197988Srrh * context 4207988Srrh */ 4217988Srrh if ((down == EFF) && (p->in.type != UNDEF)) { 4227988Srrh lty = LUE; 4237988Srrh } else if (down == EFF) { 4247988Srrh lty = LUV | LUE; 4257988Srrh } else { 4267988Srrh lty = LUV; 4277988Srrh } 42811403Snicklin outdef( sp, lty, acount ); 4297988Srrh if( acount ) { 4307988Srrh lpta( p->in.right ); 4317988Srrh } 4327988Srrh } 4337988Srrh break; 4347988Srrh 4357988Srrh case ICON: 4367988Srrh /* look for &name case */ 4377988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4387988Srrh q = &stab[id]; 4397988Srrh q->sflags |= (SREF|SSET); 4407988Srrh q->suse = -lineno; 4417988Srrh } 4427988Srrh return; 4437988Srrh 4447988Srrh case NAME: 4457988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4467988Srrh q = &stab[id]; 4477988Srrh if( (uses&VALUSED) && !(q->sflags&SSET) ){ 4487988Srrh if( q->sclass == AUTO || q->sclass == REGISTER ){ 44911761Sedward if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){ 4507988Srrh #ifndef FLEXNAMES 4517988Srrh werror( "%.8s may be used before set", q->sname ); 4527988Srrh #else 4537988Srrh werror( "%s may be used before set", q->sname ); 4547988Srrh #endif 4557988Srrh q->sflags |= SSET; 4567988Srrh } 4577988Srrh } 4587988Srrh } 4597988Srrh if( uses & VALASGOP ) break; /* not a real use */ 4607988Srrh if( uses & VALSET ) q->sflags |= SSET; 4617988Srrh if( uses & VALUSED ) q->sflags |= SREF; 4627988Srrh if( uses & VALADDR ) q->sflags |= (SREF|SSET); 4637988Srrh if( p->tn.lval == 0 ){ 4647988Srrh lnp->lid = id; 4657988Srrh lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); 4667988Srrh if( ++lnp >= &lnames[LNAMES] ) --lnp; 4677988Srrh } 4687988Srrh } 4697988Srrh return; 4707988Srrh 4717988Srrh } 4727988Srrh 4737988Srrh /* recurse, going down the right side first if we can */ 4747988Srrh 4757988Srrh switch( optype(p->in.op) ){ 4767988Srrh 4777988Srrh case BITYPE: 4787988Srrh np1 = lnp; 4797988Srrh lprt( p->in.right, down2, use2 ); 4807988Srrh case UTYPE: 4817988Srrh np2 = lnp; 4827988Srrh lprt( p->in.left, down1, use1 ); 4837988Srrh } 4847988Srrh 4857988Srrh if( optype(p->in.op) == BITYPE ){ 4867988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */ 4877988Srrh lmerge( np1, np2, 0 ); 4887988Srrh } 4897988Srrh else lmerge( np1, np2, p->in.op != COLON ); 4907988Srrh /* look for assignments to fields, and complain */ 4917988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p ); 4927988Srrh } 4937988Srrh 4947988Srrh } 4957988Srrh 4967988Srrh lmerge( np1, np2, flag ) struct lnm *np1, *np2; { 4977988Srrh /* np1 and np2 point to lists of lnm members, for the two sides 4987988Srrh * of a binary operator 4997988Srrh * flag is 1 if commutation is possible, 0 otherwise 5007988Srrh * lmerge returns a merged list, starting at np1, resetting lnp 5017988Srrh * it also complains, if appropriate, about side effects 5027988Srrh */ 5037988Srrh 5047988Srrh register struct lnm *npx, *npy; 5057988Srrh 5067988Srrh for( npx = np2; npx < lnp; ++npx ){ 5077988Srrh 5087988Srrh /* is it already there? */ 5097988Srrh for( npy = np1; npy < np2; ++npy ){ 5107988Srrh if( npx->lid == npy->lid ){ /* yes */ 5117988Srrh if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) 5127988Srrh ; /* do nothing */ 5137988Srrh else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || 5147988Srrh (npx->flgs&npy->flgs&VALSET) ){ 5157988Srrh #ifndef FLEXNAMES 5167988Srrh if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); 5177988Srrh #else 5187988Srrh if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname ); 5197988Srrh #endif 5207988Srrh } 5217988Srrh if( npy->flgs == 0 ) npx->flgs = 0; 5227988Srrh else npy->flgs |= npx->flgs; 5237988Srrh goto foundit; 5247988Srrh } 5257988Srrh } 5267988Srrh 5277988Srrh /* not there: update entry */ 5287988Srrh np2->lid = npx->lid; 5297988Srrh np2->flgs = npx->flgs; 5307988Srrh ++np2; 5317988Srrh 5327988Srrh foundit: ; 5337988Srrh } 5347988Srrh 5357988Srrh /* all finished: merged list is at np1 */ 5367988Srrh lnp = np2; 5377988Srrh } 5387988Srrh 5397988Srrh efcode(){ 5407988Srrh /* code for the end of a function */ 5417988Srrh register struct symtab *cfp; 5427988Srrh 5437988Srrh cfp = &stab[curftn]; 54411403Snicklin if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) ) 54511403Snicklin outdef( cfp, LRV, DECTY ); 5467988Srrh if( !vflag ){ 5477988Srrh vflag = argflag; 5487988Srrh argflag = 0; 5497988Srrh } 5507988Srrh if( retstat == RETVAL+NRETVAL ) 5517988Srrh #ifndef FLEXNAMES 5527988Srrh werror( "function %.8s has return(e); and return;", cfp->sname); 5537988Srrh #else 5547988Srrh werror( "function %s has return(e); and return;", cfp->sname); 5557988Srrh #endif 5567988Srrh } 5577988Srrh 5587988Srrh aocode(p) struct symtab *p; { 5597988Srrh /* called when automatic p removed from stab */ 5607988Srrh register struct symtab *cfs; 5617988Srrh cfs = &stab[curftn]; 5627988Srrh if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){ 5637988Srrh if( p->sclass == PARAM ){ 5647988Srrh #ifndef FLEXNAMES 5657988Srrh if( vflag ) werror( "argument %.8s unused in function %.8s", 5667988Srrh #else 5677988Srrh if( vflag ) werror( "argument %s unused in function %s", 5687988Srrh #endif 5697988Srrh p->sname, 5707988Srrh cfs->sname ); 5717988Srrh } 5727988Srrh else { 5737988Srrh #ifndef FLEXNAMES 5747988Srrh if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s", 5757988Srrh #else 5767988Srrh if( p->sclass != TYPEDEF ) werror( "%s unused in function %s", 5777988Srrh #endif 5787988Srrh p->sname, cfs->sname ); 5797988Srrh } 5807988Srrh } 5817988Srrh 5827988Srrh if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET && 5837988Srrh !ISARY(p->stype) && !ISFTN(p->stype) ){ 5847988Srrh 5857988Srrh #ifndef FLEXNAMES 5867988Srrh werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname ); 5877988Srrh #else 5887988Srrh werror( "%s set but not used in function %s", p->sname, cfs->sname ); 5897988Srrh #endif 5907988Srrh } 5917988Srrh 5927988Srrh if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){ 59311761Sedward if( !zflag && dimtab[p->sizoff+1] < 0 ) 5947988Srrh #ifndef FLEXNAMES 59511761Sedward werror( "structure %.8s never defined", p->sname ); 5967988Srrh #else 59711761Sedward werror( "structure %s never defined", p->sname ); 5987988Srrh #endif 5997988Srrh } 6007988Srrh 6017988Srrh } 6027988Srrh 6037988Srrh defnam( p ) register struct symtab *p; { 6047988Srrh /* define the current location as the name p->sname */ 6057988Srrh 60611403Snicklin if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return; 6077988Srrh 60811761Sedward if( !ISFTN( p->stype ) ) 60911761Sedward if( p->sclass == STATIC ) outdef( p, LST, USUAL ); 61011761Sedward else outdef( p, libflag?LIB:LDI, USUAL ); 6117988Srrh } 6127988Srrh 6137988Srrh zecode( n ){ 6147988Srrh /* n integer words of zeros */ 6157988Srrh OFFSZ temp; 6167988Srrh temp = n; 6177988Srrh inoff += temp*SZINT; 6187988Srrh ; 6197988Srrh } 6207988Srrh 6217988Srrh andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ 6227988Srrh register r; 6237988Srrh 6247988Srrh if( p->in.op != NAME ) cerror( "andable error" ); 6257988Srrh 6267988Srrh if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */ 6277988Srrh 6287988Srrh if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); 6297988Srrh #ifndef FLEXNAMES 6307988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname ); 6317988Srrh #else 6327988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname ); 6337988Srrh #endif 6347988Srrh return(1); 6357988Srrh } 6367988Srrh 6377988Srrh NODE * 6387988Srrh clocal(p) NODE *p; { 6397988Srrh 6407988Srrh /* this is called to do local transformations on 6417988Srrh an expression tree preparitory to its being 6427988Srrh written out in intermediate code. 6437988Srrh */ 6447988Srrh 6457988Srrh /* the major essential job is rewriting the 6467988Srrh automatic variables and arguments in terms of 6477988Srrh REG and OREG nodes */ 6487988Srrh /* conversion ops which are not necessary are also clobbered here */ 6497988Srrh /* in addition, any special features (such as rewriting 6507988Srrh exclusive or) are easily handled here as well */ 6517988Srrh 6527988Srrh register o; 6537988Srrh register unsigned t, tl; 65425757Sdonn int s; 6557988Srrh 6567988Srrh switch( o = p->in.op ){ 6577988Srrh 6587988Srrh case SCONV: 6597988Srrh case PCONV: 6607988Srrh if( p->in.left->in.type==ENUMTY ){ 6617988Srrh p->in.left = pconvert( p->in.left ); 6627988Srrh } 6637988Srrh /* assume conversion takes place; type is inherited */ 6647988Srrh t = p->in.type; 6657988Srrh tl = p->in.left->in.type; 66626403Sdonn if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){ 6677988Srrh werror( "long assignment may lose accuracy" ); 6687988Srrh } 6697988Srrh if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){ 6707988Srrh werror( "assignment to long may sign-extend incorrectly" ); 6717988Srrh } 6727988Srrh if( ISPTR(tl) && ISPTR(t) ){ 6737988Srrh tl = DECREF(tl); 6747988Srrh t = DECREF(t); 6757988Srrh switch( ISFTN(t) + ISFTN(tl) ){ 6767988Srrh 6777988Srrh case 0: /* neither is a function pointer */ 6787988Srrh if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){ 6797988Srrh if( hflag||pflag ) werror( "possible pointer alignment problem" ); 6807988Srrh } 6817988Srrh break; 6827988Srrh 6837988Srrh case 1: 6847988Srrh werror( "questionable conversion of function pointer" ); 6857988Srrh 6867988Srrh case 2: 6877988Srrh ; 6887988Srrh } 6897988Srrh } 6907988Srrh p->in.left->in.type = p->in.type; 6917988Srrh p->in.left->fn.cdim = p->fn.cdim; 6927988Srrh p->in.left->fn.csiz = p->fn.csiz; 6937988Srrh p->in.op = FREE; 6947988Srrh return( p->in.left ); 6957988Srrh 6967988Srrh case PVCONV: 6977988Srrh case PMCONV: 6987988Srrh if( p->in.right->in.op != ICON ) cerror( "bad conversion"); 6997988Srrh p->in.op = FREE; 7007988Srrh return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 7017988Srrh 70225757Sdonn case RS: 70325757Sdonn case LS: 70425757Sdonn case ASG RS: 70525757Sdonn case ASG LS: 70625757Sdonn if( p->in.right->in.op != ICON ) 70725757Sdonn break; 70825757Sdonn s = p->in.right->tn.lval; 70925757Sdonn if( s < 0 ) 71025757Sdonn werror( "negative shift" ); 71125757Sdonn else 71225757Sdonn if( s >= dimtab[ p->fn.csiz ] ) 71325757Sdonn werror( "shift greater than size of object" ); 71425757Sdonn break; 71525757Sdonn 7167988Srrh } 7177988Srrh 7187988Srrh return(p); 7197988Srrh } 7207988Srrh 7217988Srrh NODE * 7227988Srrh offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ 7237988Srrh register NODE *p; 7247988Srrh p = bcon(0); 7257988Srrh p->tn.lval = off/SZCHAR; 7267988Srrh return(p); 7277988Srrh } 7287988Srrh 7297988Srrh noinit(){ 7307988Srrh /* storage class for such as "int a;" */ 7317988Srrh return( pflag ? EXTDEF : EXTERN ); 7327988Srrh } 7337988Srrh 7347988Srrh 7357988Srrh cinit( p, sz ) NODE *p; { /* initialize p into size sz */ 7367988Srrh inoff += sz; 7377988Srrh if( p->in.op == INIT ){ 7387988Srrh if( p->in.left->in.op == ICON ) return; 7397988Srrh if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return; 7407988Srrh } 7417988Srrh uerror( "illegal initialization" ); 7427988Srrh } 7437988Srrh 7447988Srrh char * 7457988Srrh exname( p ) char *p; { 7467988Srrh /* make a name look like an external name in the local machine */ 7477988Srrh static char aa[8]; 7487988Srrh register int i; 7497988Srrh 7507988Srrh if( !pflag ) return(p); 7517988Srrh for( i=0; i<6; ++i ){ 7527988Srrh if( isupper(*p ) ) aa[i] = tolower( *p ); 7537988Srrh else aa[i] = *p; 7547988Srrh if( *p ) ++p; 7557988Srrh } 7567988Srrh aa[6] = '\0'; 7577988Srrh return( aa ); 7587988Srrh } 7597988Srrh 7607988Srrh char * 7617988Srrh strip(s) char *s; { 7627988Srrh #ifndef FLEXNAMES 7637988Srrh static char x[LFNM+1]; 7647988Srrh #else 7657988Srrh static char x[BUFSIZ]; 7667988Srrh #endif 7677988Srrh register char *p; 7687996Srrh static int stripping = 0; 7697988Srrh 7707996Srrh if (stripping) 7717996Srrh return(s); 7727996Srrh stripping++; 7737988Srrh for( p=x; *s; ++s ){ 7747996Srrh if( *s != '"' ){ 7757988Srrh #ifndef FLEXNAMES 7767988Srrh /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */ 7777988Srrh if( p >= &x[LFNM] ) 77811403Snicklin #else 77911403Snicklin if( p >= &x[BUFSIZ] ) 78011403Snicklin #endif 7817988Srrh cerror( "filename too long" ); 7827988Srrh *p++ = *s; 7837988Srrh } 7847988Srrh } 7857996Srrh stripping = 0; 7867988Srrh *p = '\0'; 7877988Srrh #ifndef FLEXNAMES 7887988Srrh return( x ); 7897988Srrh #else 7907988Srrh return( hash(x) ); 7917988Srrh #endif 7927988Srrh } 7937988Srrh 7947988Srrh fsave( s ) char *s; { 7957988Srrh static union rec fsname; 7967988Srrh s = strip( s ); 7977988Srrh #ifndef FLEXNAMES 798*26916Sdonn if( strncmp( s, fsname.f.fn, LFNM ) ) 7997988Srrh #else 800*26916Sdonn if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn)) 8017988Srrh #endif 802*26916Sdonn { 8037988Srrh /* new one */ 8047988Srrh #ifndef FLEXNAMES 8057988Srrh strncpy( fsname.f.fn, s, LFNM ); 8067988Srrh #else 8077988Srrh fsname.f.fn = s; 8087988Srrh #endif 8097988Srrh fsname.f.decflag = LFN; 8107988Srrh fwrite( (char *)&fsname, sizeof(fsname), 1, stdout ); 8117988Srrh #ifdef FLEXNAMES 81211403Snicklin /* if generating a library, prefix with the library name */ 81311403Snicklin /* only do this for flexnames */ 81411403Snicklin if( libname ){ 81511403Snicklin fwrite( libname, strlen(libname), 1, stdout ); 81611403Snicklin putchar( ':' ); 81711403Snicklin } 8187988Srrh fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout ); 8197988Srrh #endif 8207988Srrh } 8217988Srrh } 8227988Srrh 8237988Srrh where(f){ /* print true location of error */ 8247996Srrh if( f == 'u' && nerrors > 1 ) 8257996Srrh --nerrors; /* don't get "too many errors" */ 8267996Srrh fprintf( stderr, "%s(%d): ", strip(ftitle), lineno); 8277988Srrh } 8287988Srrh 8297988Srrh /* a number of dummy routines, unneeded by lint */ 8307988Srrh 8317988Srrh branch(n){;} 8327988Srrh defalign(n){;} 8337988Srrh deflab(n){;} 8347988Srrh bycode(t,i){;} 8357988Srrh cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */ 8367988Srrh 8377988Srrh fldty(p) struct symtab *p; { 8387988Srrh ; /* all types are OK here... */ 8397988Srrh } 8407988Srrh 8417988Srrh fldal(t) unsigned t; { /* field alignment... */ 8427988Srrh if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */ 8437988Srrh if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */ 8447988Srrh if( pflag ) uerror( "nonportable field type" ); 8457988Srrh } 8467988Srrh else uerror( "illegal field type" ); 8477988Srrh return(ALINT); 8487988Srrh } 8497988Srrh 8507988Srrh main( argc, argv ) char *argv[]; { 8517988Srrh char *p; 85211403Snicklin int i; 8537988Srrh 8547988Srrh /* handle options */ 8557988Srrh 85611403Snicklin for( i = 1; i < argc; i++ ) 85711403Snicklin for( p=argv[i]; *p; ++p ){ 8587988Srrh 85911403Snicklin switch( *p ){ 8607988Srrh 86111403Snicklin case '-': 86211403Snicklin continue; 8637988Srrh 86411403Snicklin case '\0': 86511403Snicklin break; 8667988Srrh 86711403Snicklin case 'b': 86811403Snicklin brkflag = 1; 86911403Snicklin continue; 8707988Srrh 87111403Snicklin case 'p': 87211403Snicklin pflag = 1; 87311403Snicklin continue; 8747988Srrh 87511403Snicklin case 'c': 87611403Snicklin cflag = 1; 87711403Snicklin continue; 8787988Srrh 87911403Snicklin case 's': 88011403Snicklin /* for the moment, -s triggers -h */ 8817988Srrh 88211403Snicklin case 'h': 88311403Snicklin hflag = 1; 88411403Snicklin continue; 8857988Srrh 88611403Snicklin case 'L': 88711403Snicklin libflag = 1; 88811403Snicklin case 'v': 88911403Snicklin vflag = 0; 89011403Snicklin continue; 8917988Srrh 89211403Snicklin case 'x': 89311403Snicklin xflag = 1; 89411403Snicklin continue; 8957988Srrh 89611403Snicklin case 'a': 89711403Snicklin ++aflag; 89811403Snicklin case 'u': /* done in second pass */ 89911403Snicklin case 'n': /* done in shell script */ 90011403Snicklin continue; 9017988Srrh 90211761Sedward case 'z': 90311761Sedward zflag = 1; 90411761Sedward continue; 90511761Sedward 90611403Snicklin case 't': 90711403Snicklin werror( "option %c now default: see `man 6 lint'", *p ); 90811403Snicklin continue; 9097988Srrh 91011761Sedward case 'P': /* debugging, done in second pass */ 91111761Sedward continue; 91211761Sedward 91311403Snicklin case 'C': 91411403Snicklin Cflag = 1; 91511403Snicklin if( p[1] ) libname = p + 1; 91611403Snicklin while( p[1] ) p++; 91711403Snicklin continue; 9187988Srrh 91911403Snicklin default: 92011403Snicklin uerror( "illegal option: %c", *p ); 92111403Snicklin continue; 92211403Snicklin 92311403Snicklin } 9247988Srrh } 9257988Srrh 9267988Srrh if( !pflag ){ /* set sizes to sizes of target machine */ 9277988Srrh # ifdef gcos 9287988Srrh SZCHAR = ALCHAR = 9; 9297988Srrh # else 9307988Srrh SZCHAR = ALCHAR = 8; 9317988Srrh # endif 9327988Srrh SZINT = ALINT = sizeof(int)*SZCHAR; 9337988Srrh SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; 9347988Srrh SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; 9357988Srrh SZLONG = ALLONG = sizeof(long)*SZCHAR; 9367988Srrh SZSHORT = ALSHORT = sizeof(short)*SZCHAR; 9377988Srrh SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; 9387988Srrh ALSTRUCT = ALINT; 9397988Srrh /* now, fix some things up for various machines (I wish we had "alignof") */ 9407988Srrh 9417988Srrh # ifdef pdp11 9427988Srrh ALLONG = ALDOUBLE = ALFLOAT = ALINT; 9437988Srrh #endif 9447988Srrh # ifdef ibm 9457988Srrh ALSTRUCT = ALCHAR; 9467988Srrh #endif 9477988Srrh } 9487988Srrh 9497988Srrh return( mainp1( argc, argv ) ); 9507988Srrh } 9517988Srrh 9527988Srrh ctype( type ) unsigned type; { /* are there any funny types? */ 9537988Srrh return( type ); 9547988Srrh } 9557988Srrh 9567988Srrh commdec( i ){ 9577988Srrh /* put out a common declaration */ 95811761Sedward if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL ); 95911761Sedward else outdef( &stab[i], libflag?LIB:LDC, USUAL ); 9607988Srrh } 9617988Srrh 9627988Srrh isitfloat ( s ) char *s; { 9637988Srrh /* s is a character string; 9647988Srrh if floating point is implemented, set dcon to the value of s */ 9657988Srrh /* lint version 9667988Srrh */ 9677988Srrh dcon = atof( s ); 96825304Sbloom return( DCON ); 9697988Srrh } 9707988Srrh 9717988Srrh fldcon( p ) register NODE *p; { 9727988Srrh /* p is an assignment of a constant to a field */ 9737988Srrh /* check to see if the assignment is going to overflow, or otherwise cause trouble */ 9747988Srrh register s; 9757988Srrh CONSZ v; 9767988Srrh 9777988Srrh if( !hflag & !pflag ) return; 9787988Srrh 9797988Srrh s = UPKFSZ(p->in.left->tn.rval); 9807988Srrh v = p->in.right->tn.lval; 9817988Srrh 9827988Srrh switch( p->in.left->in.type ){ 9837988Srrh 9847988Srrh case CHAR: 9857988Srrh case INT: 9867988Srrh case SHORT: 9877988Srrh case LONG: 9887988Srrh case ENUMTY: 9897988Srrh if( v>=0 && (v>>(s-1))==0 ) return; 9907988Srrh werror( "precision lost in assignment to (possibly sign-extended) field" ); 9917988Srrh default: 9927988Srrh return; 9937988Srrh 9947988Srrh case UNSIGNED: 9957988Srrh case UCHAR: 9967988Srrh case USHORT: 9977988Srrh case ULONG: 9987988Srrh if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); 9997988Srrh 10007988Srrh return; 10017988Srrh } 10027988Srrh 10037988Srrh } 10047988Srrh 10057988Srrh outdef( p, lty, mode ) struct symtab *p; { 10067988Srrh /* output a definition for the second pass */ 10077988Srrh /* if mode is > USUAL, it is the number of args */ 10087988Srrh char *fname; 10097988Srrh TWORD t; 10107988Srrh int line; 10117988Srrh static union rec rc; 10127988Srrh 10137988Srrh if( mode == NOFILE ){ 10147988Srrh fname = "???"; 10157988Srrh line = p->suse; 10167988Srrh } 10177988Srrh else if( mode == SVLINE ){ 10187988Srrh fname = ftitle; 10197988Srrh line = -p->suse; 10207988Srrh } 10217988Srrh else { 10227988Srrh fname = ftitle; 10237988Srrh line = lineno; 10247988Srrh } 10257988Srrh fsave( fname ); 10267988Srrh #ifndef FLEXNAMES 10277988Srrh strncpy( rc.l.name, exname(p->sname), LCHNM ); 10287988Srrh #endif 10297988Srrh rc.l.decflag = lty; 10307988Srrh t = p->stype; 10317988Srrh if( mode == DECTY ) t = DECREF(t); 10327988Srrh rc.l.type.aty = t; 10337988Srrh rc.l.type.extra = 0; 103411761Sedward rc.l.type.extra1 = 0; 10357988Srrh astype( &rc.l.type, p->sizoff ); 10367988Srrh rc.l.nargs = (mode>USUAL) ? mode : 0; 10377988Srrh rc.l.fline = line; 10387988Srrh fwrite( (char *)&rc, sizeof(rc), 1, stdout ); 10397988Srrh #ifdef FLEXNAMES 10407988Srrh rc.l.name = exname(p->sname); 10417988Srrh fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout ); 10427988Srrh #endif 10437988Srrh } 10447988Srrh int proflg; 10457988Srrh int gdebug; 1046