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