17988Srrh #ifndef lint 2*11403Snicklin static char sccsid[] = "@(#)lint.c 1.3 (Berkeley) 03/05/83"; 37988Srrh #endif lint 47988Srrh 57988Srrh # include "mfile1" 67988Srrh 77988Srrh # include "lmanifest" 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 */ 37*11403Snicklin int Cflag = 0; /* filter out certain output, for generating libraries */ 38*11403Snicklin char *libname = 0; /* name of the library we're generating */ 397988Srrh 407988Srrh /* flags for the "outdef" function */ 417988Srrh # define USUAL (-101) 427988Srrh # define DECTY (-102) 437988Srrh # define NOFILE (-103) 447988Srrh # define SVLINE (-104) 457988Srrh 467988Srrh # define LNAMES 250 477988Srrh 487988Srrh struct lnm { 497988Srrh short lid, flgs; 507988Srrh } lnames[LNAMES], *lnp; 517988Srrh 527988Srrh contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; { 537988Srrh 547988Srrh *pl = *pr = VAL; 557988Srrh switch( p->in.op ){ 567988Srrh 577988Srrh case ANDAND: 587988Srrh case OROR: 597988Srrh case QUEST: 607988Srrh *pr = down; 617988Srrh break; 627988Srrh 637988Srrh case SCONV: 647988Srrh case PCONV: 657988Srrh case COLON: 667988Srrh *pr = *pl = down; 677988Srrh break; 687988Srrh 697988Srrh case COMOP: 707988Srrh *pl = EFF; 717988Srrh *pr = down; 727988Srrh 737988Srrh case FORCE: 747988Srrh case INIT: 757988Srrh case UNARY CALL: 767988Srrh case STCALL: 777988Srrh case UNARY STCALL: 787988Srrh case CALL: 797988Srrh case UNARY FORTCALL: 807988Srrh case FORTCALL: 817988Srrh case CBRANCH: 827988Srrh break; 837988Srrh 847988Srrh default: 857988Srrh if( asgop(p->in.op) ) break; 867988Srrh if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) { 877988Srrh /* struct x f( ); main( ) { (void) f( ); } 887988Srrh * the the cast call appears as U* UNDEF 897988Srrh */ 907988Srrh break; /* the compiler does this... */ 917988Srrh } 927988Srrh if( down == EFF && hflag ) werror( "null effect" ); 937988Srrh 947988Srrh } 957988Srrh } 967988Srrh 977988Srrh ecode( p ) NODE *p; { 987988Srrh /* compile code for p */ 997988Srrh 1007988Srrh fwalk( p, contx, EFF ); 1017988Srrh lnp = lnames; 1027988Srrh lprt( p, EFF, 0 ); 1037988Srrh } 1047988Srrh 1057988Srrh ejobcode( flag ){ 1067988Srrh /* called after processing each job */ 1077988Srrh /* flag is nonzero if errors were detected */ 1087988Srrh register k; 1097988Srrh register struct symtab *p; 1107988Srrh 1117988Srrh for( p=stab; p< &stab[SYMTSZ]; ++p ){ 1127988Srrh 1137988Srrh if( p->stype != TNULL ) { 1147988Srrh 1157988Srrh if( p->stype == STRTY || p->stype == UNIONTY ){ 1167988Srrh if( dimtab[p->sizoff+1] < 0 ){ /* never defined */ 1177988Srrh #ifndef FLEXNAMES 1187988Srrh if( hflag ) werror( "struct/union %.8s never defined", p->sname ); 1197988Srrh #else 1207988Srrh if( hflag ) werror( "struct/union %s never defined", p->sname ); 1217988Srrh #endif 1227988Srrh } 1237988Srrh } 1247988Srrh 1257988Srrh switch( p->sclass ){ 1267988Srrh 1277988Srrh case STATIC: 1287988Srrh if( p->suse > 0 ){ 1297988Srrh k = lineno; 1307988Srrh lineno = p->suse; 1317988Srrh #ifndef FLEXNAMES 1327988Srrh uerror( "static variable %.8s unused", 1337988Srrh #else 1347988Srrh uerror( "static variable %s unused", 1357988Srrh #endif 1367988Srrh p->sname ); 1377988Srrh lineno = k; 1387988Srrh break; 1397988Srrh } 140*11403Snicklin /* no statics in libraries */ 141*11403Snicklin if( Cflag ) break; 1427988Srrh 1437988Srrh case EXTERN: 1447988Srrh case USTATIC: 1457988Srrh /* with the xflag, worry about externs not used */ 1467988Srrh /* the filename may be wrong here... */ 1477988Srrh if( xflag && p->suse >= 0 && !libflag ){ 1487988Srrh outdef( p, LDX, NOFILE ); 1497988Srrh } 1507988Srrh 1517988Srrh case EXTDEF: 1527988Srrh if( p->suse < 0 ){ /* used */ 1537988Srrh outdef( p, LUM, SVLINE ); 1547988Srrh } 1557988Srrh break; 1567988Srrh } 1577988Srrh 1587988Srrh } 1597988Srrh 1607988Srrh } 1617988Srrh exit( 0 ); 1627988Srrh } 1637988Srrh 1647988Srrh astype( t, i ) ATYPE *t; { 1657988Srrh TWORD tt; 1667988Srrh int j, k=0; 1677988Srrh 1687988Srrh if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){ 1697988Srrh if( i<0 || i>= DIMTABSZ-3 ){ 1707988Srrh werror( "lint's little mind is blown" ); 1717988Srrh } 1727988Srrh else { 1737988Srrh j = dimtab[i+3]; 1747988Srrh if( j<0 || j>SYMTSZ ){ 1757988Srrh k = ((-j)<<5)^dimtab[i]|1; 1767988Srrh } 1777988Srrh else { 1787988Srrh if( stab[j].suse <= 0 ) { 1797988Srrh #ifndef FLEXNAMES 1807988Srrh werror( "no line number for %.8s", 1817988Srrh #else 1827988Srrh werror( "no line number for %s", 1837988Srrh #endif 1847988Srrh stab[j].sname ); 1857988Srrh } 1867988Srrh else k = (stab[j].suse<<5) ^ dimtab[i]; 1877988Srrh } 1887988Srrh } 1897988Srrh 1907988Srrh t->extra = k; 1917988Srrh return( 1 ); 1927988Srrh } 1937988Srrh else return( 0 ); 1947988Srrh } 1957988Srrh 1967988Srrh bfcode( a, n ) int a[]; { 1977988Srrh /* code for the beginning of a function; a is an array of 1987988Srrh indices in stab for the arguments; n is the number */ 1997988Srrh /* this must also set retlab */ 2007988Srrh register i; 2017988Srrh register struct symtab *cfp; 2027988Srrh static ATYPE t; 2037988Srrh 2047988Srrh retlab = 1; 205*11403Snicklin 2067988Srrh cfp = &stab[curftn]; 2077988Srrh 208*11403Snicklin /* if creating library, don't do static functions */ 209*11403Snicklin if( Cflag && cfp->sclass == STATIC ) return; 210*11403Snicklin 2117988Srrh /* if variable number of arguments, only print the ones which will be checked */ 2127988Srrh if( vaflag > 0 ){ 2137988Srrh if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" ); 2147988Srrh else n = vaflag; 2157988Srrh } 2167988Srrh fsave( ftitle ); 2177988Srrh outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n ); 2187988Srrh vaflag = -1; 2197988Srrh 2207988Srrh /* output the arguments */ 2217988Srrh if( n ){ 2227988Srrh for( i=0; i<n; ++i ) { 2237988Srrh t.aty = stab[a[i]].stype; 2247988Srrh t.extra = 0; 2257988Srrh if( !astype( &t, stab[a[i]].sizoff ) ) { 2267988Srrh switch( t.aty ){ 2277988Srrh 2287988Srrh case ULONG: 2297988Srrh break; 2307988Srrh 2317988Srrh case CHAR: 2327988Srrh case SHORT: 2337988Srrh t.aty = INT; 2347988Srrh break; 2357988Srrh 2367988Srrh case UCHAR: 2377988Srrh case USHORT: 2387988Srrh case UNSIGNED: 2397988Srrh t.aty = UNSIGNED; 2407988Srrh break; 2417988Srrh 2427988Srrh } 2437988Srrh } 2447988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 2457988Srrh } 2467988Srrh } 2477988Srrh } 2487988Srrh 2497988Srrh ctargs( p ) NODE *p; { 2507988Srrh /* count arguments; p points to at least one */ 2517988Srrh /* the arguemnts are a tower of commas to the left */ 2527988Srrh register c; 2537988Srrh c = 1; /* count the rhs */ 2547988Srrh while( p->in.op == CM ){ 2557988Srrh ++c; 2567988Srrh p = p->in.left; 2577988Srrh } 2587988Srrh return( c ); 2597988Srrh } 2607988Srrh 2617988Srrh lpta( p ) NODE *p; { 2627988Srrh static ATYPE t; 2637988Srrh 2647988Srrh if( p->in.op == CM ){ 2657988Srrh lpta( p->in.left ); 2667988Srrh p = p->in.right; 2677988Srrh } 2687988Srrh 2697988Srrh t.aty = p->in.type; 2707988Srrh t.extra = (p->in.op==ICON); 2717988Srrh 2727988Srrh if( !astype( &t, p->in.csiz ) ) { 2737988Srrh switch( t.aty ){ 2747988Srrh 2757988Srrh case CHAR: 2767988Srrh case SHORT: 2777988Srrh t.aty = INT; 2787988Srrh case LONG: 2797988Srrh case ULONG: 2807988Srrh case INT: 2817988Srrh case UNSIGNED: 2827988Srrh break; 2837988Srrh 2847988Srrh case UCHAR: 2857988Srrh case USHORT: 2867988Srrh t.aty = UNSIGNED; 2877988Srrh break; 2887988Srrh 2897988Srrh case FLOAT: 2907988Srrh t.aty = DOUBLE; 2917988Srrh t.extra = 0; 2927988Srrh break; 2937988Srrh 2947988Srrh default: 2957988Srrh t.extra = 0; 2967988Srrh break; 2977988Srrh } 2987988Srrh } 2997988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 3007988Srrh } 3017988Srrh 3027988Srrh # define VALSET 1 3037988Srrh # define VALUSED 2 3047988Srrh # define VALASGOP 4 3057988Srrh # define VALADDR 8 3067988Srrh 3077988Srrh lprt( p, down, uses ) register NODE *p; { 3087988Srrh register struct symtab *q; 3097988Srrh register id; 3107988Srrh register acount; 3117988Srrh register down1, down2; 3127988Srrh register use1, use2; 3137988Srrh register struct lnm *np1, *np2; 3147988Srrh 3157988Srrh /* first, set variables which are set... */ 3167988Srrh 3177988Srrh use1 = use2 = VALUSED; 3187988Srrh if( p->in.op == ASSIGN ) use1 = VALSET; 3197988Srrh else if( p->in.op == UNARY AND ) use1 = VALADDR; 3207988Srrh else if( asgop( p->in.op ) ){ /* =ops */ 3217988Srrh use1 = VALUSED|VALSET; 3227988Srrh if( down == EFF ) use1 |= VALASGOP; 3237988Srrh } 3247988Srrh 3257988Srrh 3267988Srrh /* print the lines for lint */ 3277988Srrh 3287988Srrh down2 = down1 = VAL; 3297988Srrh acount = 0; 3307988Srrh 3317988Srrh switch( p->in.op ){ 3327988Srrh 3337988Srrh case EQ: 3347988Srrh case NE: 3357988Srrh case GT: 3367988Srrh case GE: 3377988Srrh case LT: 3387988Srrh case LE: 3397988Srrh if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){ 3407988Srrh werror( "nonportable character comparison" ); 3417988Srrh } 3427988Srrh if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){ 3437988Srrh if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){ 3447988Srrh werror( "comparison of unsigned with negative constant" ); 3457988Srrh } 3467988Srrh } 3477988Srrh break; 3487988Srrh 3497988Srrh case UGE: 3507988Srrh case ULT: 3517988Srrh if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){ 3527988Srrh werror( "unsigned comparison with 0?" ); 3537988Srrh break; 3547988Srrh } 3557988Srrh case UGT: 3567988Srrh case ULE: 3577988Srrh 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 ){ 3587988Srrh werror( "degenerate unsigned comparison" ); 3597988Srrh } 3607988Srrh break; 3617988Srrh 3627988Srrh case COMOP: 3637988Srrh down1 = EFF; 3647988Srrh 3657988Srrh case ANDAND: 3667988Srrh case OROR: 3677988Srrh case QUEST: 3687988Srrh down2 = down; 3697988Srrh /* go recursively left, then right */ 3707988Srrh np1 = lnp; 3717988Srrh lprt( p->in.left, down1, use1 ); 3727988Srrh np2 = lnp; 3737988Srrh lprt( p->in.right, down2, use2 ); 3747988Srrh lmerge( np1, np2, 0 ); 3757988Srrh return; 3767988Srrh 3777988Srrh case SCONV: 3787988Srrh case PCONV: 3797988Srrh case COLON: 3807988Srrh down1 = down2 = down; 3817988Srrh break; 3827988Srrh 3837988Srrh case CALL: 3847988Srrh case STCALL: 3857988Srrh case FORTCALL: 3867988Srrh acount = ctargs( p->in.right ); 3877988Srrh case UNARY CALL: 3887988Srrh case UNARY STCALL: 3897988Srrh case UNARY FORTCALL: 3907988Srrh if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */ 3917988Srrh struct symtab *sp = &stab[id]; 3927988Srrh int lty; 393*11403Snicklin 394*11403Snicklin fsave( ftitle ); 395*11403Snicklin /* 396*11403Snicklin * if we're generating a library -C then 397*11403Snicklin * we don't want to output references to functions 398*11403Snicklin */ 399*11403Snicklin if( Cflag ) break; 4007988Srrh /* if a function used in an effects context is 4017988Srrh * cast to type void then consider its value 4027988Srrh * to have been disposed of properly 4037988Srrh * thus a call of type undef in an effects 4047988Srrh * context is construed to be used in a value 4057988Srrh * context 4067988Srrh */ 4077988Srrh if ((down == EFF) && (p->in.type != UNDEF)) { 4087988Srrh lty = LUE; 4097988Srrh } else if (down == EFF) { 4107988Srrh lty = LUV | LUE; 4117988Srrh } else { 4127988Srrh lty = LUV; 4137988Srrh } 414*11403Snicklin outdef( sp, lty, acount ); 4157988Srrh if( acount ) { 4167988Srrh lpta( p->in.right ); 4177988Srrh } 4187988Srrh } 4197988Srrh break; 4207988Srrh 4217988Srrh case ICON: 4227988Srrh /* look for &name case */ 4237988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4247988Srrh q = &stab[id]; 4257988Srrh q->sflags |= (SREF|SSET); 4267988Srrh q->suse = -lineno; 4277988Srrh } 4287988Srrh return; 4297988Srrh 4307988Srrh case NAME: 4317988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4327988Srrh q = &stab[id]; 4337988Srrh if( (uses&VALUSED) && !(q->sflags&SSET) ){ 4347988Srrh if( q->sclass == AUTO || q->sclass == REGISTER ){ 4357988Srrh if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY ){ 4367988Srrh #ifndef FLEXNAMES 4377988Srrh werror( "%.8s may be used before set", q->sname ); 4387988Srrh #else 4397988Srrh werror( "%s may be used before set", q->sname ); 4407988Srrh #endif 4417988Srrh q->sflags |= SSET; 4427988Srrh } 4437988Srrh } 4447988Srrh } 4457988Srrh if( uses & VALASGOP ) break; /* not a real use */ 4467988Srrh if( uses & VALSET ) q->sflags |= SSET; 4477988Srrh if( uses & VALUSED ) q->sflags |= SREF; 4487988Srrh if( uses & VALADDR ) q->sflags |= (SREF|SSET); 4497988Srrh if( p->tn.lval == 0 ){ 4507988Srrh lnp->lid = id; 4517988Srrh lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); 4527988Srrh if( ++lnp >= &lnames[LNAMES] ) --lnp; 4537988Srrh } 4547988Srrh } 4557988Srrh return; 4567988Srrh 4577988Srrh } 4587988Srrh 4597988Srrh /* recurse, going down the right side first if we can */ 4607988Srrh 4617988Srrh switch( optype(p->in.op) ){ 4627988Srrh 4637988Srrh case BITYPE: 4647988Srrh np1 = lnp; 4657988Srrh lprt( p->in.right, down2, use2 ); 4667988Srrh case UTYPE: 4677988Srrh np2 = lnp; 4687988Srrh lprt( p->in.left, down1, use1 ); 4697988Srrh } 4707988Srrh 4717988Srrh if( optype(p->in.op) == BITYPE ){ 4727988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */ 4737988Srrh lmerge( np1, np2, 0 ); 4747988Srrh } 4757988Srrh else lmerge( np1, np2, p->in.op != COLON ); 4767988Srrh /* look for assignments to fields, and complain */ 4777988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p ); 4787988Srrh } 4797988Srrh 4807988Srrh } 4817988Srrh 4827988Srrh lmerge( np1, np2, flag ) struct lnm *np1, *np2; { 4837988Srrh /* np1 and np2 point to lists of lnm members, for the two sides 4847988Srrh * of a binary operator 4857988Srrh * flag is 1 if commutation is possible, 0 otherwise 4867988Srrh * lmerge returns a merged list, starting at np1, resetting lnp 4877988Srrh * it also complains, if appropriate, about side effects 4887988Srrh */ 4897988Srrh 4907988Srrh register struct lnm *npx, *npy; 4917988Srrh 4927988Srrh for( npx = np2; npx < lnp; ++npx ){ 4937988Srrh 4947988Srrh /* is it already there? */ 4957988Srrh for( npy = np1; npy < np2; ++npy ){ 4967988Srrh if( npx->lid == npy->lid ){ /* yes */ 4977988Srrh if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) 4987988Srrh ; /* do nothing */ 4997988Srrh else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || 5007988Srrh (npx->flgs&npy->flgs&VALSET) ){ 5017988Srrh #ifndef FLEXNAMES 5027988Srrh if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); 5037988Srrh #else 5047988Srrh if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname ); 5057988Srrh #endif 5067988Srrh } 5077988Srrh if( npy->flgs == 0 ) npx->flgs = 0; 5087988Srrh else npy->flgs |= npx->flgs; 5097988Srrh goto foundit; 5107988Srrh } 5117988Srrh } 5127988Srrh 5137988Srrh /* not there: update entry */ 5147988Srrh np2->lid = npx->lid; 5157988Srrh np2->flgs = npx->flgs; 5167988Srrh ++np2; 5177988Srrh 5187988Srrh foundit: ; 5197988Srrh } 5207988Srrh 5217988Srrh /* all finished: merged list is at np1 */ 5227988Srrh lnp = np2; 5237988Srrh } 5247988Srrh 5257988Srrh efcode(){ 5267988Srrh /* code for the end of a function */ 5277988Srrh register struct symtab *cfp; 5287988Srrh 5297988Srrh cfp = &stab[curftn]; 530*11403Snicklin if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) ) 531*11403Snicklin outdef( cfp, LRV, DECTY ); 5327988Srrh if( !vflag ){ 5337988Srrh vflag = argflag; 5347988Srrh argflag = 0; 5357988Srrh } 5367988Srrh if( retstat == RETVAL+NRETVAL ) 5377988Srrh #ifndef FLEXNAMES 5387988Srrh werror( "function %.8s has return(e); and return;", cfp->sname); 5397988Srrh #else 5407988Srrh werror( "function %s has return(e); and return;", cfp->sname); 5417988Srrh #endif 5427988Srrh } 5437988Srrh 5447988Srrh aocode(p) struct symtab *p; { 5457988Srrh /* called when automatic p removed from stab */ 5467988Srrh register struct symtab *cfs; 5477988Srrh cfs = &stab[curftn]; 5487988Srrh if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){ 5497988Srrh if( p->sclass == PARAM ){ 5507988Srrh #ifndef FLEXNAMES 5517988Srrh if( vflag ) werror( "argument %.8s unused in function %.8s", 5527988Srrh #else 5537988Srrh if( vflag ) werror( "argument %s unused in function %s", 5547988Srrh #endif 5557988Srrh p->sname, 5567988Srrh cfs->sname ); 5577988Srrh } 5587988Srrh else { 5597988Srrh #ifndef FLEXNAMES 5607988Srrh if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s", 5617988Srrh #else 5627988Srrh if( p->sclass != TYPEDEF ) werror( "%s unused in function %s", 5637988Srrh #endif 5647988Srrh p->sname, cfs->sname ); 5657988Srrh } 5667988Srrh } 5677988Srrh 5687988Srrh if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET && 5697988Srrh !ISARY(p->stype) && !ISFTN(p->stype) ){ 5707988Srrh 5717988Srrh #ifndef FLEXNAMES 5727988Srrh werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname ); 5737988Srrh #else 5747988Srrh werror( "%s set but not used in function %s", p->sname, cfs->sname ); 5757988Srrh #endif 5767988Srrh } 5777988Srrh 5787988Srrh if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){ 5797988Srrh #ifndef FLEXNAMES 5807988Srrh if( dimtab[p->sizoff+1] < 0 ) werror( "structure %.8s never defined", p->sname ); 5817988Srrh #else 5827988Srrh if( dimtab[p->sizoff+1] < 0 ) werror( "structure %s never defined", p->sname ); 5837988Srrh #endif 5847988Srrh } 5857988Srrh 5867988Srrh } 5877988Srrh 5887988Srrh defnam( p ) register struct symtab *p; { 5897988Srrh /* define the current location as the name p->sname */ 5907988Srrh 591*11403Snicklin if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return; 5927988Srrh 5937988Srrh if( !ISFTN( p->stype ) ) outdef( p, libflag?LIB:LDI, USUAL ); 5947988Srrh } 5957988Srrh 5967988Srrh zecode( n ){ 5977988Srrh /* n integer words of zeros */ 5987988Srrh OFFSZ temp; 5997988Srrh temp = n; 6007988Srrh inoff += temp*SZINT; 6017988Srrh ; 6027988Srrh } 6037988Srrh 6047988Srrh andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ 6057988Srrh register r; 6067988Srrh 6077988Srrh if( p->in.op != NAME ) cerror( "andable error" ); 6087988Srrh 6097988Srrh if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */ 6107988Srrh 6117988Srrh if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); 6127988Srrh #ifndef FLEXNAMES 6137988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname ); 6147988Srrh #else 6157988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname ); 6167988Srrh #endif 6177988Srrh return(1); 6187988Srrh } 6197988Srrh 6207988Srrh NODE * 6217988Srrh clocal(p) NODE *p; { 6227988Srrh 6237988Srrh /* this is called to do local transformations on 6247988Srrh an expression tree preparitory to its being 6257988Srrh written out in intermediate code. 6267988Srrh */ 6277988Srrh 6287988Srrh /* the major essential job is rewriting the 6297988Srrh automatic variables and arguments in terms of 6307988Srrh REG and OREG nodes */ 6317988Srrh /* conversion ops which are not necessary are also clobbered here */ 6327988Srrh /* in addition, any special features (such as rewriting 6337988Srrh exclusive or) are easily handled here as well */ 6347988Srrh 6357988Srrh register o; 6367988Srrh register unsigned t, tl; 6377988Srrh 6387988Srrh switch( o = p->in.op ){ 6397988Srrh 6407988Srrh case SCONV: 6417988Srrh case PCONV: 6427988Srrh if( p->in.left->in.type==ENUMTY ){ 6437988Srrh p->in.left = pconvert( p->in.left ); 6447988Srrh } 6457988Srrh /* assume conversion takes place; type is inherited */ 6467988Srrh t = p->in.type; 6477988Srrh tl = p->in.left->in.type; 6487988Srrh if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG) ){ 6497988Srrh werror( "long assignment may lose accuracy" ); 6507988Srrh } 6517988Srrh if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){ 6527988Srrh werror( "assignment to long may sign-extend incorrectly" ); 6537988Srrh } 6547988Srrh if( ISPTR(tl) && ISPTR(t) ){ 6557988Srrh tl = DECREF(tl); 6567988Srrh t = DECREF(t); 6577988Srrh switch( ISFTN(t) + ISFTN(tl) ){ 6587988Srrh 6597988Srrh case 0: /* neither is a function pointer */ 6607988Srrh if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){ 6617988Srrh if( hflag||pflag ) werror( "possible pointer alignment problem" ); 6627988Srrh } 6637988Srrh break; 6647988Srrh 6657988Srrh case 1: 6667988Srrh werror( "questionable conversion of function pointer" ); 6677988Srrh 6687988Srrh case 2: 6697988Srrh ; 6707988Srrh } 6717988Srrh } 6727988Srrh p->in.left->in.type = p->in.type; 6737988Srrh p->in.left->fn.cdim = p->fn.cdim; 6747988Srrh p->in.left->fn.csiz = p->fn.csiz; 6757988Srrh p->in.op = FREE; 6767988Srrh return( p->in.left ); 6777988Srrh 6787988Srrh case PVCONV: 6797988Srrh case PMCONV: 6807988Srrh if( p->in.right->in.op != ICON ) cerror( "bad conversion"); 6817988Srrh p->in.op = FREE; 6827988Srrh return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 6837988Srrh 6847988Srrh } 6857988Srrh 6867988Srrh return(p); 6877988Srrh } 6887988Srrh 6897988Srrh NODE * 6907988Srrh offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ 6917988Srrh register NODE *p; 6927988Srrh p = bcon(0); 6937988Srrh p->tn.lval = off/SZCHAR; 6947988Srrh return(p); 6957988Srrh } 6967988Srrh 6977988Srrh noinit(){ 6987988Srrh /* storage class for such as "int a;" */ 6997988Srrh return( pflag ? EXTDEF : EXTERN ); 7007988Srrh } 7017988Srrh 7027988Srrh 7037988Srrh cinit( p, sz ) NODE *p; { /* initialize p into size sz */ 7047988Srrh inoff += sz; 7057988Srrh if( p->in.op == INIT ){ 7067988Srrh if( p->in.left->in.op == ICON ) return; 7077988Srrh if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return; 7087988Srrh } 7097988Srrh uerror( "illegal initialization" ); 7107988Srrh } 7117988Srrh 7127988Srrh char * 7137988Srrh exname( p ) char *p; { 7147988Srrh /* make a name look like an external name in the local machine */ 7157988Srrh static char aa[8]; 7167988Srrh register int i; 7177988Srrh 7187988Srrh if( !pflag ) return(p); 7197988Srrh for( i=0; i<6; ++i ){ 7207988Srrh if( isupper(*p ) ) aa[i] = tolower( *p ); 7217988Srrh else aa[i] = *p; 7227988Srrh if( *p ) ++p; 7237988Srrh } 7247988Srrh aa[6] = '\0'; 7257988Srrh return( aa ); 7267988Srrh } 7277988Srrh 7287988Srrh char * 7297988Srrh strip(s) char *s; { 7307988Srrh #ifndef FLEXNAMES 7317988Srrh static char x[LFNM+1]; 7327988Srrh #else 7337988Srrh static char x[BUFSIZ]; 7347988Srrh #endif 7357988Srrh register char *p; 7367996Srrh static int stripping = 0; 7377988Srrh 7387996Srrh if (stripping) 7397996Srrh return(s); 7407996Srrh stripping++; 7417988Srrh for( p=x; *s; ++s ){ 7427996Srrh if( *s != '"' ){ 7437988Srrh #ifndef FLEXNAMES 7447988Srrh /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */ 7457988Srrh if( p >= &x[LFNM] ) 746*11403Snicklin #else 747*11403Snicklin if( p >= &x[BUFSIZ] ) 748*11403Snicklin #endif 7497988Srrh cerror( "filename too long" ); 7507988Srrh *p++ = *s; 7517988Srrh } 7527988Srrh } 7537996Srrh stripping = 0; 7547988Srrh *p = '\0'; 7557988Srrh #ifndef FLEXNAMES 7567988Srrh return( x ); 7577988Srrh #else 7587988Srrh return( hash(x) ); 7597988Srrh #endif 7607988Srrh } 7617988Srrh 7627988Srrh fsave( s ) char *s; { 7637988Srrh static union rec fsname; 7647988Srrh s = strip( s ); 7657988Srrh #ifndef FLEXNAMES 7667988Srrh if( strncmp( s, fsname.f.fn, LFNM ) ){ 7677988Srrh #else 7687988Srrh if( strcmp(s, fsname.f.fn)) { 7697988Srrh #endif 7707988Srrh /* new one */ 7717988Srrh #ifndef FLEXNAMES 7727988Srrh strncpy( fsname.f.fn, s, LFNM ); 7737988Srrh #else 7747988Srrh fsname.f.fn = s; 7757988Srrh #endif 7767988Srrh fsname.f.decflag = LFN; 7777988Srrh fwrite( (char *)&fsname, sizeof(fsname), 1, stdout ); 7787988Srrh #ifdef FLEXNAMES 779*11403Snicklin /* if generating a library, prefix with the library name */ 780*11403Snicklin /* only do this for flexnames */ 781*11403Snicklin if( libname ){ 782*11403Snicklin fwrite( libname, strlen(libname), 1, stdout ); 783*11403Snicklin putchar( ':' ); 784*11403Snicklin } 7857988Srrh fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout ); 7867988Srrh #endif 7877988Srrh } 7887988Srrh } 7897988Srrh 7907988Srrh where(f){ /* print true location of error */ 7917996Srrh if( f == 'u' && nerrors > 1 ) 7927996Srrh --nerrors; /* don't get "too many errors" */ 7937996Srrh fprintf( stderr, "%s(%d): ", strip(ftitle), lineno); 7947988Srrh } 7957988Srrh 7967988Srrh /* a number of dummy routines, unneeded by lint */ 7977988Srrh 7987988Srrh branch(n){;} 7997988Srrh defalign(n){;} 8007988Srrh deflab(n){;} 8017988Srrh bycode(t,i){;} 8027988Srrh cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */ 8037988Srrh 8047988Srrh fldty(p) struct symtab *p; { 8057988Srrh ; /* all types are OK here... */ 8067988Srrh } 8077988Srrh 8087988Srrh fldal(t) unsigned t; { /* field alignment... */ 8097988Srrh if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */ 8107988Srrh if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */ 8117988Srrh if( pflag ) uerror( "nonportable field type" ); 8127988Srrh } 8137988Srrh else uerror( "illegal field type" ); 8147988Srrh return(ALINT); 8157988Srrh } 8167988Srrh 8177988Srrh main( argc, argv ) char *argv[]; { 8187988Srrh char *p; 819*11403Snicklin int i; 8207988Srrh 8217988Srrh /* handle options */ 8227988Srrh 823*11403Snicklin for( i = 1; i < argc; i++ ) 824*11403Snicklin for( p=argv[i]; *p; ++p ){ 8257988Srrh 826*11403Snicklin switch( *p ){ 8277988Srrh 828*11403Snicklin case '-': 829*11403Snicklin continue; 8307988Srrh 831*11403Snicklin case '\0': 832*11403Snicklin break; 8337988Srrh 834*11403Snicklin case 'b': 835*11403Snicklin brkflag = 1; 836*11403Snicklin continue; 8377988Srrh 838*11403Snicklin case 'p': 839*11403Snicklin pflag = 1; 840*11403Snicklin continue; 8417988Srrh 842*11403Snicklin case 'c': 843*11403Snicklin cflag = 1; 844*11403Snicklin continue; 8457988Srrh 846*11403Snicklin case 's': 847*11403Snicklin /* for the moment, -s triggers -h */ 8487988Srrh 849*11403Snicklin case 'h': 850*11403Snicklin hflag = 1; 851*11403Snicklin continue; 8527988Srrh 853*11403Snicklin case 'L': 854*11403Snicklin libflag = 1; 855*11403Snicklin case 'v': 856*11403Snicklin vflag = 0; 857*11403Snicklin continue; 8587988Srrh 859*11403Snicklin case 'x': 860*11403Snicklin xflag = 1; 861*11403Snicklin continue; 8627988Srrh 863*11403Snicklin case 'a': 864*11403Snicklin ++aflag; 865*11403Snicklin case 'u': /* done in second pass */ 866*11403Snicklin case 'n': /* done in shell script */ 867*11403Snicklin continue; 8687988Srrh 869*11403Snicklin case 't': 870*11403Snicklin werror( "option %c now default: see `man 6 lint'", *p ); 871*11403Snicklin continue; 8727988Srrh 873*11403Snicklin case 'C': 874*11403Snicklin Cflag = 1; 875*11403Snicklin if( p[1] ) libname = p + 1; 876*11403Snicklin while( p[1] ) p++; 877*11403Snicklin continue; 8787988Srrh 879*11403Snicklin default: 880*11403Snicklin uerror( "illegal option: %c", *p ); 881*11403Snicklin continue; 882*11403Snicklin 883*11403Snicklin } 8847988Srrh } 8857988Srrh 8867988Srrh if( !pflag ){ /* set sizes to sizes of target machine */ 8877988Srrh # ifdef gcos 8887988Srrh SZCHAR = ALCHAR = 9; 8897988Srrh # else 8907988Srrh SZCHAR = ALCHAR = 8; 8917988Srrh # endif 8927988Srrh SZINT = ALINT = sizeof(int)*SZCHAR; 8937988Srrh SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; 8947988Srrh SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; 8957988Srrh SZLONG = ALLONG = sizeof(long)*SZCHAR; 8967988Srrh SZSHORT = ALSHORT = sizeof(short)*SZCHAR; 8977988Srrh SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; 8987988Srrh ALSTRUCT = ALINT; 8997988Srrh /* now, fix some things up for various machines (I wish we had "alignof") */ 9007988Srrh 9017988Srrh # ifdef pdp11 9027988Srrh ALLONG = ALDOUBLE = ALFLOAT = ALINT; 9037988Srrh #endif 9047988Srrh # ifdef ibm 9057988Srrh ALSTRUCT = ALCHAR; 9067988Srrh #endif 9077988Srrh } 9087988Srrh 9097988Srrh return( mainp1( argc, argv ) ); 9107988Srrh } 9117988Srrh 9127988Srrh ctype( type ) unsigned type; { /* are there any funny types? */ 9137988Srrh return( type ); 9147988Srrh } 9157988Srrh 9167988Srrh commdec( i ){ 9177988Srrh /* put out a common declaration */ 9187988Srrh outdef( &stab[i], libflag?LIB:LDC, USUAL ); 9197988Srrh } 9207988Srrh 9217988Srrh isitfloat ( s ) char *s; { 9227988Srrh /* s is a character string; 9237988Srrh if floating point is implemented, set dcon to the value of s */ 9247988Srrh /* lint version 9257988Srrh */ 9267988Srrh dcon = atof( s ); 9277988Srrh return( FCON ); 9287988Srrh } 9297988Srrh 9307988Srrh fldcon( p ) register NODE *p; { 9317988Srrh /* p is an assignment of a constant to a field */ 9327988Srrh /* check to see if the assignment is going to overflow, or otherwise cause trouble */ 9337988Srrh register s; 9347988Srrh CONSZ v; 9357988Srrh 9367988Srrh if( !hflag & !pflag ) return; 9377988Srrh 9387988Srrh s = UPKFSZ(p->in.left->tn.rval); 9397988Srrh v = p->in.right->tn.lval; 9407988Srrh 9417988Srrh switch( p->in.left->in.type ){ 9427988Srrh 9437988Srrh case CHAR: 9447988Srrh case INT: 9457988Srrh case SHORT: 9467988Srrh case LONG: 9477988Srrh case ENUMTY: 9487988Srrh if( v>=0 && (v>>(s-1))==0 ) return; 9497988Srrh werror( "precision lost in assignment to (possibly sign-extended) field" ); 9507988Srrh default: 9517988Srrh return; 9527988Srrh 9537988Srrh case UNSIGNED: 9547988Srrh case UCHAR: 9557988Srrh case USHORT: 9567988Srrh case ULONG: 9577988Srrh if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); 9587988Srrh 9597988Srrh return; 9607988Srrh } 9617988Srrh 9627988Srrh } 9637988Srrh 9647988Srrh outdef( p, lty, mode ) struct symtab *p; { 9657988Srrh /* output a definition for the second pass */ 9667988Srrh /* if mode is > USUAL, it is the number of args */ 9677988Srrh char *fname; 9687988Srrh TWORD t; 9697988Srrh int line; 9707988Srrh static union rec rc; 9717988Srrh 9727988Srrh if( mode == NOFILE ){ 9737988Srrh fname = "???"; 9747988Srrh line = p->suse; 9757988Srrh } 9767988Srrh else if( mode == SVLINE ){ 9777988Srrh fname = ftitle; 9787988Srrh line = -p->suse; 9797988Srrh } 9807988Srrh else { 9817988Srrh fname = ftitle; 9827988Srrh line = lineno; 9837988Srrh } 9847988Srrh fsave( fname ); 9857988Srrh #ifndef FLEXNAMES 9867988Srrh strncpy( rc.l.name, exname(p->sname), LCHNM ); 9877988Srrh #endif 9887988Srrh rc.l.decflag = lty; 9897988Srrh t = p->stype; 9907988Srrh if( mode == DECTY ) t = DECREF(t); 9917988Srrh rc.l.type.aty = t; 9927988Srrh rc.l.type.extra = 0; 9937988Srrh astype( &rc.l.type, p->sizoff ); 9947988Srrh rc.l.nargs = (mode>USUAL) ? mode : 0; 9957988Srrh rc.l.fline = line; 9967988Srrh fwrite( (char *)&rc, sizeof(rc), 1, stdout ); 9977988Srrh #ifdef FLEXNAMES 9987988Srrh rc.l.name = exname(p->sname); 9997988Srrh fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout ); 10007988Srrh #endif 10017988Srrh } 10027988Srrh int proflg; 10037988Srrh int gdebug; 1004