17988Srrh #ifndef lint 2*30819Sbostic static char sccsid[] = "@(#)lint.c 1.11 (Berkeley) 04/06/87"; 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 31*30819Sbostic int nflag = 0; /* avoid gripes about printf et al. */ 32*30819Sbostic int vflag = 1; /* tell about unused argments */ 33*30819Sbostic int xflag = 0; /* tell about unused externals */ 34*30819Sbostic int argflag = 0; /* used to turn off complaints about arguments */ 35*30819Sbostic int libflag = 0; /* used to generate library descriptions */ 36*30819Sbostic int vaflag = -1; /* signal functions with a variable number of args */ 37*30819Sbostic int aflag = 0; /* used to check precision of assignments */ 38*30819Sbostic int zflag = 0; /* no 'structure never defined' error */ 39*30819Sbostic int Cflag = 0; /* filter out certain output, for generating libraries */ 40*30819Sbostic char *libname = 0; /* name of the library we're generating */ 417988Srrh 42*30819Sbostic /* flags for the "outdef" function */ 437988Srrh # define USUAL (-101) 447988Srrh # define DECTY (-102) 457988Srrh # define NOFILE (-103) 467988Srrh # define SVLINE (-104) 477988Srrh 487988Srrh # define LNAMES 250 497988Srrh 507988Srrh struct lnm { 517988Srrh short lid, flgs; 527988Srrh } lnames[LNAMES], *lnp; 537988Srrh 547988Srrh contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; { 557988Srrh 567988Srrh *pl = *pr = VAL; 577988Srrh switch( p->in.op ){ 587988Srrh 597988Srrh case ANDAND: 607988Srrh case OROR: 617988Srrh case QUEST: 627988Srrh *pr = down; 637988Srrh break; 647988Srrh 657988Srrh case SCONV: 667988Srrh case PCONV: 677988Srrh case COLON: 687988Srrh *pr = *pl = down; 697988Srrh break; 707988Srrh 717988Srrh case COMOP: 727988Srrh *pl = EFF; 737988Srrh *pr = down; 747988Srrh 757988Srrh case FORCE: 767988Srrh case INIT: 777988Srrh case UNARY CALL: 787988Srrh case STCALL: 797988Srrh case UNARY STCALL: 807988Srrh case CALL: 817988Srrh case UNARY FORTCALL: 827988Srrh case FORTCALL: 837988Srrh case CBRANCH: 847988Srrh break; 857988Srrh 867988Srrh default: 877988Srrh if( asgop(p->in.op) ) break; 887988Srrh if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) { 897988Srrh /* struct x f( ); main( ) { (void) f( ); } 907988Srrh * the the cast call appears as U* UNDEF 917988Srrh */ 927988Srrh break; /* the compiler does this... */ 937988Srrh } 947988Srrh if( down == EFF && hflag ) werror( "null effect" ); 957988Srrh 967988Srrh } 977988Srrh } 987988Srrh 997988Srrh ecode( p ) NODE *p; { 1007988Srrh /* compile code for p */ 1017988Srrh 1027988Srrh fwalk( p, contx, EFF ); 1037988Srrh lnp = lnames; 1047988Srrh lprt( p, EFF, 0 ); 105*30819Sbostic strforget(); 1067988Srrh } 1077988Srrh 1087988Srrh ejobcode( flag ){ 1097988Srrh /* called after processing each job */ 1107988Srrh /* flag is nonzero if errors were detected */ 1117988Srrh register k; 1127988Srrh register struct symtab *p; 1137988Srrh 1147988Srrh for( p=stab; p< &stab[SYMTSZ]; ++p ){ 1157988Srrh 1167988Srrh if( p->stype != TNULL ) { 1177988Srrh 1187988Srrh if( p->stype == STRTY || p->stype == UNIONTY ){ 11911761Sedward if( !zflag && dimtab[p->sizoff+1] < 0 ){ 12011761Sedward /* never defined */ 1217988Srrh #ifndef FLEXNAMES 1227988Srrh if( hflag ) werror( "struct/union %.8s never defined", p->sname ); 1237988Srrh #else 1247988Srrh if( hflag ) werror( "struct/union %s never defined", p->sname ); 1257988Srrh #endif 1267988Srrh } 1277988Srrh } 1287988Srrh 1297988Srrh switch( p->sclass ){ 1307988Srrh 1317988Srrh case STATIC: 1327988Srrh if( p->suse > 0 ){ 1337988Srrh k = lineno; 1347988Srrh lineno = p->suse; 1357988Srrh #ifndef FLEXNAMES 1367988Srrh uerror( "static variable %.8s unused", 1377988Srrh #else 1387988Srrh uerror( "static variable %s unused", 1397988Srrh #endif 1407988Srrh p->sname ); 1417988Srrh lineno = k; 1427988Srrh break; 1437988Srrh } 14411403Snicklin /* no statics in libraries */ 14511403Snicklin if( Cflag ) break; 1467988Srrh 1477988Srrh case EXTERN: 1487988Srrh case USTATIC: 1497988Srrh /* with the xflag, worry about externs not used */ 1507988Srrh /* the filename may be wrong here... */ 1517988Srrh if( xflag && p->suse >= 0 && !libflag ){ 1527988Srrh outdef( p, LDX, NOFILE ); 1537988Srrh } 1547988Srrh 1557988Srrh case EXTDEF: 1567988Srrh if( p->suse < 0 ){ /* used */ 1577988Srrh outdef( p, LUM, SVLINE ); 1587988Srrh } 1597988Srrh break; 1607988Srrh } 1617988Srrh 1627988Srrh } 1637988Srrh 1647988Srrh } 1657988Srrh exit( 0 ); 1667988Srrh } 1677988Srrh 1687988Srrh astype( t, i ) ATYPE *t; { 1697988Srrh TWORD tt; 17011761Sedward int j, k=0, l=0; 1717988Srrh 1727988Srrh if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){ 1737988Srrh if( i<0 || i>= DIMTABSZ-3 ){ 1747988Srrh werror( "lint's little mind is blown" ); 1757988Srrh } 1767988Srrh else { 1777988Srrh j = dimtab[i+3]; 1787988Srrh if( j<0 || j>SYMTSZ ){ 17911761Sedward k = dimtab[i]; 18011761Sedward l = X_NONAME | stab[j].suse; 1817988Srrh } 1827988Srrh else { 1837988Srrh if( stab[j].suse <= 0 ) { 1847988Srrh #ifndef FLEXNAMES 1857988Srrh werror( "no line number for %.8s", 1867988Srrh #else 1877988Srrh werror( "no line number for %s", 1887988Srrh #endif 1897988Srrh stab[j].sname ); 1907988Srrh } 19111761Sedward else { 19211761Sedward k = dimtab[i]; 19311761Sedward #ifdef FLEXNAMES 19411761Sedward l = hashstr(stab[j].sname); 19511761Sedward #else 19611761Sedward l = hashstr(stab[j].sname, LCHNM); 19711761Sedward #endif 19811761Sedward } 1997988Srrh } 2007988Srrh } 2017988Srrh 2027988Srrh t->extra = k; 20311761Sedward t->extra1 = l; 2047988Srrh return( 1 ); 2057988Srrh } 2067988Srrh else return( 0 ); 2077988Srrh } 2087988Srrh 2097988Srrh bfcode( a, n ) int a[]; { 2107988Srrh /* code for the beginning of a function; a is an array of 2117988Srrh indices in stab for the arguments; n is the number */ 2127988Srrh /* this must also set retlab */ 2137988Srrh register i; 2147988Srrh register struct symtab *cfp; 2157988Srrh static ATYPE t; 2167988Srrh 217*30819Sbostic strforget(); 2187988Srrh retlab = 1; 21911403Snicklin 2207988Srrh cfp = &stab[curftn]; 2217988Srrh 22211403Snicklin /* if creating library, don't do static functions */ 22311403Snicklin if( Cflag && cfp->sclass == STATIC ) return; 22411403Snicklin 2257988Srrh /* if variable number of arguments, only print the ones which will be checked */ 2267988Srrh if( vaflag > 0 ){ 2277988Srrh if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" ); 2287988Srrh else n = vaflag; 2297988Srrh } 2307988Srrh fsave( ftitle ); 23111761Sedward if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?-n:n ); 23211761Sedward else outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n ); 2337988Srrh vaflag = -1; 2347988Srrh 2357988Srrh /* output the arguments */ 2367988Srrh if( n ){ 2377988Srrh for( i=0; i<n; ++i ) { 2387988Srrh t.aty = stab[a[i]].stype; 2397988Srrh t.extra = 0; 24011761Sedward t.extra1 = 0; 2417988Srrh if( !astype( &t, stab[a[i]].sizoff ) ) { 2427988Srrh switch( t.aty ){ 2437988Srrh 2447988Srrh case ULONG: 2457988Srrh break; 2467988Srrh 2477988Srrh case CHAR: 2487988Srrh case SHORT: 2497988Srrh t.aty = INT; 2507988Srrh break; 2517988Srrh 2527988Srrh case UCHAR: 2537988Srrh case USHORT: 2547988Srrh case UNSIGNED: 2557988Srrh t.aty = UNSIGNED; 2567988Srrh break; 2577988Srrh 2587988Srrh } 2597988Srrh } 2607988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 2617988Srrh } 2627988Srrh } 2637988Srrh } 2647988Srrh 2657988Srrh ctargs( p ) NODE *p; { 2667988Srrh /* count arguments; p points to at least one */ 2677988Srrh /* the arguemnts are a tower of commas to the left */ 2687988Srrh register c; 2697988Srrh c = 1; /* count the rhs */ 2707988Srrh while( p->in.op == CM ){ 2717988Srrh ++c; 2727988Srrh p = p->in.left; 2737988Srrh } 2747988Srrh return( c ); 2757988Srrh } 2767988Srrh 2777988Srrh lpta( p ) NODE *p; { 2787988Srrh static ATYPE t; 2797988Srrh 2807988Srrh if( p->in.op == CM ){ 2817988Srrh lpta( p->in.left ); 2827988Srrh p = p->in.right; 2837988Srrh } 2847988Srrh 2857988Srrh t.aty = p->in.type; 2867988Srrh t.extra = (p->in.op==ICON); 28711761Sedward t.extra1 = 0; 2887988Srrh 28918598Sralph if( !astype( &t, p->fn.csiz ) ) { 2907988Srrh switch( t.aty ){ 2917988Srrh 2927988Srrh case CHAR: 2937988Srrh case SHORT: 2947988Srrh t.aty = INT; 2957988Srrh case LONG: 2967988Srrh case ULONG: 2977988Srrh case INT: 2987988Srrh case UNSIGNED: 2997988Srrh break; 3007988Srrh 3017988Srrh case UCHAR: 3027988Srrh case USHORT: 3037988Srrh t.aty = UNSIGNED; 3047988Srrh break; 3057988Srrh 3067988Srrh case FLOAT: 3077988Srrh t.aty = DOUBLE; 3087988Srrh t.extra = 0; 3097988Srrh break; 3107988Srrh 3117988Srrh default: 3127988Srrh t.extra = 0; 3137988Srrh break; 3147988Srrh } 3157988Srrh } 3167988Srrh fwrite( (char *)&t, sizeof(ATYPE), 1, stdout ); 3177988Srrh } 3187988Srrh 3197988Srrh # define VALSET 1 3207988Srrh # define VALUSED 2 3217988Srrh # define VALASGOP 4 3227988Srrh # define VALADDR 8 3237988Srrh 3247988Srrh lprt( p, down, uses ) register NODE *p; { 3257988Srrh register struct symtab *q; 3267988Srrh register id; 3277988Srrh register acount; 3287988Srrh register down1, down2; 3297988Srrh register use1, use2; 3307988Srrh register struct lnm *np1, *np2; 3317988Srrh 3327988Srrh /* first, set variables which are set... */ 3337988Srrh 3347988Srrh use1 = use2 = VALUSED; 3357988Srrh if( p->in.op == ASSIGN ) use1 = VALSET; 3367988Srrh else if( p->in.op == UNARY AND ) use1 = VALADDR; 3377988Srrh else if( asgop( p->in.op ) ){ /* =ops */ 3387988Srrh use1 = VALUSED|VALSET; 3397988Srrh if( down == EFF ) use1 |= VALASGOP; 3407988Srrh } 3417988Srrh 3427988Srrh 3437988Srrh /* print the lines for lint */ 3447988Srrh 3457988Srrh down2 = down1 = VAL; 3467988Srrh acount = 0; 3477988Srrh 3487988Srrh switch( p->in.op ){ 3497988Srrh 3507988Srrh case EQ: 3517988Srrh case NE: 3527988Srrh case GT: 3537988Srrh case GE: 3547988Srrh case LT: 3557988Srrh case LE: 3567988Srrh if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){ 3577988Srrh werror( "nonportable character comparison" ); 3587988Srrh } 3597988Srrh if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){ 3607988Srrh if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){ 3617988Srrh werror( "comparison of unsigned with negative constant" ); 3627988Srrh } 3637988Srrh } 3647988Srrh break; 3657988Srrh 3667988Srrh case UGE: 3677988Srrh case ULT: 3687988Srrh if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){ 3697988Srrh werror( "unsigned comparison with 0?" ); 3707988Srrh break; 3717988Srrh } 3727988Srrh case UGT: 3737988Srrh case ULE: 3747988Srrh 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 ){ 3757988Srrh werror( "degenerate unsigned comparison" ); 3767988Srrh } 3777988Srrh break; 3787988Srrh 3797988Srrh case COMOP: 3807988Srrh down1 = EFF; 3817988Srrh 3827988Srrh case ANDAND: 3837988Srrh case OROR: 3847988Srrh case QUEST: 3857988Srrh down2 = down; 3867988Srrh /* go recursively left, then right */ 3877988Srrh np1 = lnp; 3887988Srrh lprt( p->in.left, down1, use1 ); 3897988Srrh np2 = lnp; 3907988Srrh lprt( p->in.right, down2, use2 ); 3917988Srrh lmerge( np1, np2, 0 ); 3927988Srrh return; 3937988Srrh 3947988Srrh case SCONV: 3957988Srrh case PCONV: 3967988Srrh case COLON: 3977988Srrh down1 = down2 = down; 3987988Srrh break; 3997988Srrh 4007988Srrh case CALL: 4017988Srrh case STCALL: 4027988Srrh case FORTCALL: 4037988Srrh acount = ctargs( p->in.right ); 4047988Srrh case UNARY CALL: 4057988Srrh case UNARY STCALL: 4067988Srrh case UNARY FORTCALL: 4077988Srrh if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */ 4087988Srrh struct symtab *sp = &stab[id]; 4097988Srrh int lty; 41011403Snicklin 41111403Snicklin fsave( ftitle ); 412*30819Sbostic if (hflag && !nflag) 413*30819Sbostic doform(p, sp, acount); 41411403Snicklin /* 41511403Snicklin * if we're generating a library -C then 41611403Snicklin * we don't want to output references to functions 41711403Snicklin */ 41811403Snicklin if( Cflag ) break; 4197988Srrh /* if a function used in an effects context is 4207988Srrh * cast to type void then consider its value 4217988Srrh * to have been disposed of properly 4227988Srrh * thus a call of type undef in an effects 4237988Srrh * context is construed to be used in a value 4247988Srrh * context 4257988Srrh */ 4267988Srrh if ((down == EFF) && (p->in.type != UNDEF)) { 4277988Srrh lty = LUE; 4287988Srrh } else if (down == EFF) { 4297988Srrh lty = LUV | LUE; 4307988Srrh } else { 4317988Srrh lty = LUV; 4327988Srrh } 43311403Snicklin outdef( sp, lty, acount ); 4347988Srrh if( acount ) { 4357988Srrh lpta( p->in.right ); 4367988Srrh } 4377988Srrh } 4387988Srrh break; 4397988Srrh 4407988Srrh case ICON: 4417988Srrh /* look for &name case */ 4427988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4437988Srrh q = &stab[id]; 4447988Srrh q->sflags |= (SREF|SSET); 4457988Srrh q->suse = -lineno; 4467988Srrh } 4477988Srrh return; 4487988Srrh 4497988Srrh case NAME: 4507988Srrh if( (id = p->tn.rval) >= 0 && id != NONAME ){ 4517988Srrh q = &stab[id]; 4527988Srrh if( (uses&VALUSED) && !(q->sflags&SSET) ){ 4537988Srrh if( q->sclass == AUTO || q->sclass == REGISTER ){ 45411761Sedward if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){ 4557988Srrh #ifndef FLEXNAMES 4567988Srrh werror( "%.8s may be used before set", q->sname ); 4577988Srrh #else 4587988Srrh werror( "%s may be used before set", q->sname ); 4597988Srrh #endif 4607988Srrh q->sflags |= SSET; 4617988Srrh } 4627988Srrh } 4637988Srrh } 4647988Srrh if( uses & VALASGOP ) break; /* not a real use */ 4657988Srrh if( uses & VALSET ) q->sflags |= SSET; 4667988Srrh if( uses & VALUSED ) q->sflags |= SREF; 4677988Srrh if( uses & VALADDR ) q->sflags |= (SREF|SSET); 4687988Srrh if( p->tn.lval == 0 ){ 4697988Srrh lnp->lid = id; 4707988Srrh lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); 4717988Srrh if( ++lnp >= &lnames[LNAMES] ) --lnp; 4727988Srrh } 4737988Srrh } 4747988Srrh return; 4757988Srrh 4767988Srrh } 4777988Srrh 4787988Srrh /* recurse, going down the right side first if we can */ 4797988Srrh 4807988Srrh switch( optype(p->in.op) ){ 4817988Srrh 4827988Srrh case BITYPE: 4837988Srrh np1 = lnp; 4847988Srrh lprt( p->in.right, down2, use2 ); 4857988Srrh case UTYPE: 4867988Srrh np2 = lnp; 4877988Srrh lprt( p->in.left, down1, use1 ); 4887988Srrh } 4897988Srrh 4907988Srrh if( optype(p->in.op) == BITYPE ){ 4917988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a = .. a .. */ 4927988Srrh lmerge( np1, np2, 0 ); 4937988Srrh } 4947988Srrh else lmerge( np1, np2, p->in.op != COLON ); 4957988Srrh /* look for assignments to fields, and complain */ 4967988Srrh if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p ); 4977988Srrh } 4987988Srrh 4997988Srrh } 5007988Srrh 5017988Srrh lmerge( np1, np2, flag ) struct lnm *np1, *np2; { 5027988Srrh /* np1 and np2 point to lists of lnm members, for the two sides 5037988Srrh * of a binary operator 5047988Srrh * flag is 1 if commutation is possible, 0 otherwise 5057988Srrh * lmerge returns a merged list, starting at np1, resetting lnp 5067988Srrh * it also complains, if appropriate, about side effects 5077988Srrh */ 5087988Srrh 5097988Srrh register struct lnm *npx, *npy; 5107988Srrh 5117988Srrh for( npx = np2; npx < lnp; ++npx ){ 5127988Srrh 5137988Srrh /* is it already there? */ 5147988Srrh for( npy = np1; npy < np2; ++npy ){ 5157988Srrh if( npx->lid == npy->lid ){ /* yes */ 5167988Srrh if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) 5177988Srrh ; /* do nothing */ 5187988Srrh else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || 5197988Srrh (npx->flgs&npy->flgs&VALSET) ){ 5207988Srrh #ifndef FLEXNAMES 5217988Srrh if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); 5227988Srrh #else 5237988Srrh if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname ); 5247988Srrh #endif 5257988Srrh } 5267988Srrh if( npy->flgs == 0 ) npx->flgs = 0; 5277988Srrh else npy->flgs |= npx->flgs; 5287988Srrh goto foundit; 5297988Srrh } 5307988Srrh } 5317988Srrh 5327988Srrh /* not there: update entry */ 5337988Srrh np2->lid = npx->lid; 5347988Srrh np2->flgs = npx->flgs; 5357988Srrh ++np2; 5367988Srrh 5377988Srrh foundit: ; 5387988Srrh } 5397988Srrh 5407988Srrh /* all finished: merged list is at np1 */ 5417988Srrh lnp = np2; 5427988Srrh } 5437988Srrh 5447988Srrh efcode(){ 5457988Srrh /* code for the end of a function */ 5467988Srrh register struct symtab *cfp; 5477988Srrh 5487988Srrh cfp = &stab[curftn]; 54911403Snicklin if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) ) 55011403Snicklin outdef( cfp, LRV, DECTY ); 5517988Srrh if( !vflag ){ 5527988Srrh vflag = argflag; 5537988Srrh argflag = 0; 5547988Srrh } 5557988Srrh if( retstat == RETVAL+NRETVAL ) 5567988Srrh #ifndef FLEXNAMES 5577988Srrh werror( "function %.8s has return(e); and return;", cfp->sname); 5587988Srrh #else 5597988Srrh werror( "function %s has return(e); and return;", cfp->sname); 5607988Srrh #endif 5617988Srrh } 5627988Srrh 5637988Srrh aocode(p) struct symtab *p; { 5647988Srrh /* called when automatic p removed from stab */ 5657988Srrh register struct symtab *cfs; 5667988Srrh cfs = &stab[curftn]; 5677988Srrh if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){ 5687988Srrh if( p->sclass == PARAM ){ 5697988Srrh #ifndef FLEXNAMES 5707988Srrh if( vflag ) werror( "argument %.8s unused in function %.8s", 5717988Srrh #else 5727988Srrh if( vflag ) werror( "argument %s unused in function %s", 5737988Srrh #endif 5747988Srrh p->sname, 5757988Srrh cfs->sname ); 5767988Srrh } 5777988Srrh else { 5787988Srrh #ifndef FLEXNAMES 5797988Srrh if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s", 5807988Srrh #else 5817988Srrh if( p->sclass != TYPEDEF ) werror( "%s unused in function %s", 5827988Srrh #endif 5837988Srrh p->sname, cfs->sname ); 5847988Srrh } 5857988Srrh } 5867988Srrh 5877988Srrh if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET && 5887988Srrh !ISARY(p->stype) && !ISFTN(p->stype) ){ 5897988Srrh 5907988Srrh #ifndef FLEXNAMES 5917988Srrh werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname ); 5927988Srrh #else 5937988Srrh werror( "%s set but not used in function %s", p->sname, cfs->sname ); 5947988Srrh #endif 5957988Srrh } 5967988Srrh 5977988Srrh if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){ 59811761Sedward if( !zflag && dimtab[p->sizoff+1] < 0 ) 5997988Srrh #ifndef FLEXNAMES 60011761Sedward werror( "structure %.8s never defined", p->sname ); 6017988Srrh #else 60211761Sedward werror( "structure %s never defined", p->sname ); 6037988Srrh #endif 6047988Srrh } 6057988Srrh 6067988Srrh } 6077988Srrh 6087988Srrh defnam( p ) register struct symtab *p; { 6097988Srrh /* define the current location as the name p->sname */ 6107988Srrh 61111403Snicklin if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return; 6127988Srrh 61311761Sedward if( !ISFTN( p->stype ) ) 61411761Sedward if( p->sclass == STATIC ) outdef( p, LST, USUAL ); 61511761Sedward else outdef( p, libflag?LIB:LDI, USUAL ); 6167988Srrh } 6177988Srrh 6187988Srrh zecode( n ){ 6197988Srrh /* n integer words of zeros */ 6207988Srrh OFFSZ temp; 6217988Srrh temp = n; 6227988Srrh inoff += temp*SZINT; 6237988Srrh ; 6247988Srrh } 6257988Srrh 6267988Srrh andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ 6277988Srrh register r; 6287988Srrh 6297988Srrh if( p->in.op != NAME ) cerror( "andable error" ); 6307988Srrh 6317988Srrh if( (r = p->tn.rval) < 0 ) return(1); /* labels are andable */ 6327988Srrh 6337988Srrh if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); 6347988Srrh #ifndef FLEXNAMES 6357988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname ); 6367988Srrh #else 6377988Srrh if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname ); 6387988Srrh #endif 6397988Srrh return(1); 6407988Srrh } 6417988Srrh 6427988Srrh NODE * 6437988Srrh clocal(p) NODE *p; { 6447988Srrh 6457988Srrh /* this is called to do local transformations on 6467988Srrh an expression tree preparitory to its being 6477988Srrh written out in intermediate code. 6487988Srrh */ 6497988Srrh 6507988Srrh /* the major essential job is rewriting the 6517988Srrh automatic variables and arguments in terms of 6527988Srrh REG and OREG nodes */ 6537988Srrh /* conversion ops which are not necessary are also clobbered here */ 6547988Srrh /* in addition, any special features (such as rewriting 6557988Srrh exclusive or) are easily handled here as well */ 6567988Srrh 6577988Srrh register o; 6587988Srrh register unsigned t, tl; 65925757Sdonn int s; 6607988Srrh 6617988Srrh switch( o = p->in.op ){ 662*30819Sbostic case NAME: 663*30819Sbostic { 664*30819Sbostic extern int didstr, subscr; 665*30819Sbostic extern NODE * strnodes[]; 6667988Srrh 667*30819Sbostic if (didstr) { 668*30819Sbostic didstr = 0; 669*30819Sbostic strnodes[subscr] = p; 670*30819Sbostic } 671*30819Sbostic } 672*30819Sbostic break; 673*30819Sbostic 6747988Srrh case SCONV: 6757988Srrh case PCONV: 6767988Srrh if( p->in.left->in.type==ENUMTY ){ 6777988Srrh p->in.left = pconvert( p->in.left ); 6787988Srrh } 6797988Srrh /* assume conversion takes place; type is inherited */ 6807988Srrh t = p->in.type; 6817988Srrh tl = p->in.left->in.type; 68226403Sdonn if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){ 6837988Srrh werror( "long assignment may lose accuracy" ); 6847988Srrh } 6857988Srrh if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){ 6867988Srrh werror( "assignment to long may sign-extend incorrectly" ); 6877988Srrh } 6887988Srrh if( ISPTR(tl) && ISPTR(t) ){ 6897988Srrh tl = DECREF(tl); 6907988Srrh t = DECREF(t); 6917988Srrh switch( ISFTN(t) + ISFTN(tl) ){ 6927988Srrh 6937988Srrh case 0: /* neither is a function pointer */ 6947988Srrh if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){ 6957988Srrh if( hflag||pflag ) werror( "possible pointer alignment problem" ); 6967988Srrh } 6977988Srrh break; 6987988Srrh 6997988Srrh case 1: 7007988Srrh werror( "questionable conversion of function pointer" ); 7017988Srrh 7027988Srrh case 2: 7037988Srrh ; 7047988Srrh } 7057988Srrh } 7067988Srrh p->in.left->in.type = p->in.type; 7077988Srrh p->in.left->fn.cdim = p->fn.cdim; 7087988Srrh p->in.left->fn.csiz = p->fn.csiz; 7097988Srrh p->in.op = FREE; 7107988Srrh return( p->in.left ); 7117988Srrh 7127988Srrh case PVCONV: 7137988Srrh case PMCONV: 7147988Srrh if( p->in.right->in.op != ICON ) cerror( "bad conversion"); 7157988Srrh p->in.op = FREE; 7167988Srrh return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 7177988Srrh 71825757Sdonn case RS: 71925757Sdonn case LS: 72025757Sdonn case ASG RS: 72125757Sdonn case ASG LS: 72225757Sdonn if( p->in.right->in.op != ICON ) 72325757Sdonn break; 72425757Sdonn s = p->in.right->tn.lval; 72525757Sdonn if( s < 0 ) 72625757Sdonn werror( "negative shift" ); 72725757Sdonn else 72825757Sdonn if( s >= dimtab[ p->fn.csiz ] ) 72925757Sdonn werror( "shift greater than size of object" ); 73025757Sdonn break; 73125757Sdonn 7327988Srrh } 7337988Srrh 7347988Srrh return(p); 7357988Srrh } 7367988Srrh 7377988Srrh NODE * 7387988Srrh offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ 7397988Srrh register NODE *p; 7407988Srrh p = bcon(0); 7417988Srrh p->tn.lval = off/SZCHAR; 7427988Srrh return(p); 7437988Srrh } 7447988Srrh 7457988Srrh noinit(){ 7467988Srrh /* storage class for such as "int a;" */ 7477988Srrh return( pflag ? EXTDEF : EXTERN ); 7487988Srrh } 7497988Srrh 7507988Srrh 7517988Srrh cinit( p, sz ) NODE *p; { /* initialize p into size sz */ 7527988Srrh inoff += sz; 7537988Srrh if( p->in.op == INIT ){ 7547988Srrh if( p->in.left->in.op == ICON ) return; 7557988Srrh if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return; 7567988Srrh } 7577988Srrh uerror( "illegal initialization" ); 7587988Srrh } 7597988Srrh 7607988Srrh char * 7617988Srrh exname( p ) char *p; { 7627988Srrh /* make a name look like an external name in the local machine */ 7637988Srrh static char aa[8]; 7647988Srrh register int i; 7657988Srrh 7667988Srrh if( !pflag ) return(p); 7677988Srrh for( i=0; i<6; ++i ){ 7687988Srrh if( isupper(*p ) ) aa[i] = tolower( *p ); 7697988Srrh else aa[i] = *p; 7707988Srrh if( *p ) ++p; 7717988Srrh } 7727988Srrh aa[6] = '\0'; 7737988Srrh return( aa ); 7747988Srrh } 7757988Srrh 7767988Srrh char * 7777988Srrh strip(s) char *s; { 7787988Srrh #ifndef FLEXNAMES 7797988Srrh static char x[LFNM+1]; 7807988Srrh #else 7817988Srrh static char x[BUFSIZ]; 7827988Srrh #endif 7837988Srrh register char *p; 7847996Srrh static int stripping = 0; 7857988Srrh 7867996Srrh if (stripping) 7877996Srrh return(s); 7887996Srrh stripping++; 7897988Srrh for( p=x; *s; ++s ){ 7907996Srrh if( *s != '"' ){ 7917988Srrh #ifndef FLEXNAMES 7927988Srrh /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */ 7937988Srrh if( p >= &x[LFNM] ) 79411403Snicklin #else 79511403Snicklin if( p >= &x[BUFSIZ] ) 79611403Snicklin #endif 7977988Srrh cerror( "filename too long" ); 7987988Srrh *p++ = *s; 7997988Srrh } 8007988Srrh } 8017996Srrh stripping = 0; 8027988Srrh *p = '\0'; 8037988Srrh #ifndef FLEXNAMES 8047988Srrh return( x ); 8057988Srrh #else 8067988Srrh return( hash(x) ); 8077988Srrh #endif 8087988Srrh } 8097988Srrh 8107988Srrh fsave( s ) char *s; { 8117988Srrh static union rec fsname; 8127988Srrh s = strip( s ); 8137988Srrh #ifndef FLEXNAMES 81426916Sdonn if( strncmp( s, fsname.f.fn, LFNM ) ) 8157988Srrh #else 81626916Sdonn if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn)) 8177988Srrh #endif 81826916Sdonn { 8197988Srrh /* new one */ 8207988Srrh #ifndef FLEXNAMES 8217988Srrh strncpy( fsname.f.fn, s, LFNM ); 8227988Srrh #else 8237988Srrh fsname.f.fn = s; 8247988Srrh #endif 8257988Srrh fsname.f.decflag = LFN; 8267988Srrh fwrite( (char *)&fsname, sizeof(fsname), 1, stdout ); 8277988Srrh #ifdef FLEXNAMES 82811403Snicklin /* if generating a library, prefix with the library name */ 82911403Snicklin /* only do this for flexnames */ 83011403Snicklin if( libname ){ 83111403Snicklin fwrite( libname, strlen(libname), 1, stdout ); 83211403Snicklin putchar( ':' ); 83311403Snicklin } 8347988Srrh fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout ); 8357988Srrh #endif 8367988Srrh } 8377988Srrh } 8387988Srrh 8397988Srrh where(f){ /* print true location of error */ 8407996Srrh if( f == 'u' && nerrors > 1 ) 8417996Srrh --nerrors; /* don't get "too many errors" */ 8427996Srrh fprintf( stderr, "%s(%d): ", strip(ftitle), lineno); 8437988Srrh } 8447988Srrh 8457988Srrh /* a number of dummy routines, unneeded by lint */ 8467988Srrh 8477988Srrh branch(n){;} 8487988Srrh defalign(n){;} 8497988Srrh deflab(n){;} 8507988Srrh 851*30819Sbostic extern char * strchr(); 8527988Srrh 853*30819Sbostic #define SBUFSIZE 16 854*30819Sbostic #define SCLICK 80 855*30819Sbostic 856*30819Sbostic #ifndef size_t 857*30819Sbostic #define size_t unsigned 858*30819Sbostic #endif /* !size_t */ 859*30819Sbostic 860*30819Sbostic static char * strings[SBUFSIZE]; 861*30819Sbostic static NODE * strnodes[SBUFSIZE]; 862*30819Sbostic static int didstr; 863*30819Sbostic static int subscr; 864*30819Sbostic static int strapped; 865*30819Sbostic 866*30819Sbostic bycode(t, i) 867*30819Sbostic { 868*30819Sbostic extern char * calloc(); 869*30819Sbostic extern char * realloc(); 870*30819Sbostic 871*30819Sbostic if (!hflag || nflag || strapped) 872*30819Sbostic return; 873*30819Sbostic if (i == 0) 874*30819Sbostic if (subscr < (SBUFSIZE - 1)) 875*30819Sbostic ++subscr; 876*30819Sbostic if (subscr >= SBUFSIZE) 877*30819Sbostic return; 878*30819Sbostic didstr = 1; 879*30819Sbostic if ((i % SCLICK) == 0) { 880*30819Sbostic strings[subscr] = (strings[subscr] == NULL) ? 881*30819Sbostic calloc((size_t) (SCLICK + 1), 1) : 882*30819Sbostic realloc(strings[subscr], (size_t) (i + SCLICK + 1)); 883*30819Sbostic if (strings[subscr] == NULL) { 884*30819Sbostic strapped = 1; 885*30819Sbostic return; 8867988Srrh } 8877988Srrh } 888*30819Sbostic strings[subscr][i] = t; 889*30819Sbostic } 8907988Srrh 891*30819Sbostic strforget() 892*30819Sbostic { 893*30819Sbostic didstr = subscr = 0; 894*30819Sbostic } 8957988Srrh 896*30819Sbostic static char * 897*30819Sbostic typestr(t) 898*30819Sbostic { 899*30819Sbostic switch (t) { 900*30819Sbostic case CHAR: return "char"; 901*30819Sbostic case UCHAR: return "unsigned char"; 902*30819Sbostic case SHORT: return "short"; 903*30819Sbostic case USHORT: return "unsigned short"; 904*30819Sbostic case INT: return "int"; 905*30819Sbostic case UNSIGNED: return "unsigned"; 906*30819Sbostic case ENUMTY: return "enum"; 907*30819Sbostic case LONG: return "long"; 908*30819Sbostic case ULONG: return "unsigned long"; 909*30819Sbostic case FLOAT: return "float"; 910*30819Sbostic case DOUBLE: return "double"; 911*30819Sbostic case STRTY: return "struct"; 912*30819Sbostic case UNIONTY: return "union"; 913*30819Sbostic case PTR|CHAR: return "char *"; 914*30819Sbostic case PTR|UCHAR: return "unsigned char *"; 915*30819Sbostic case PTR|SHORT: return "short *"; 916*30819Sbostic case PTR|USHORT: return "unsigned short *"; 917*30819Sbostic case PTR|INT: return "int *"; 918*30819Sbostic case PTR|UNSIGNED: return "unsigned *"; 919*30819Sbostic case PTR|ENUMTY: return "enum *"; 920*30819Sbostic case PTR|LONG: return "long *"; 921*30819Sbostic case PTR|ULONG: return "unsigned long *"; 922*30819Sbostic case PTR|FLOAT: return "float *"; 923*30819Sbostic case PTR|DOUBLE: return "double *"; 924*30819Sbostic case PTR|STRTY: return "struct *"; 925*30819Sbostic case PTR|UNIONTY: return "union *"; 926*30819Sbostic default: return ISPTR(t) ? 927*30819Sbostic "pointer" : "non-scalar"; 928*30819Sbostic } 929*30819Sbostic } 9307988Srrh 931*30819Sbostic NODE * 932*30819Sbostic ntharg(p, n, acount) 933*30819Sbostic NODE * p; 934*30819Sbostic register int n; 935*30819Sbostic register int acount; 936*30819Sbostic { 937*30819Sbostic if (n > acount) 938*30819Sbostic return NULL; 939*30819Sbostic p = p->in.right; 940*30819Sbostic while (n != acount) { 941*30819Sbostic p = p->in.left; 942*30819Sbostic --acount; 943*30819Sbostic } 944*30819Sbostic return (n == 1) ? p : p->in.right; 945*30819Sbostic } 9467988Srrh 947*30819Sbostic struct entry { 948*30819Sbostic /* If argument to print/scan is of type... */ int argtype; 949*30819Sbostic /* ...and this length character is used... */ char lchar; 950*30819Sbostic /* ...and one of these is control char... */ char * cchars; 951*30819Sbostic /* ...then use this format with werror... */ char * werror; 952*30819Sbostic /* ...(where NULL means it's hunky dory)... */ 953*30819Sbostic }; 9547988Srrh 955*30819Sbostic /* 956*30819Sbostic ** Portable printf. 957*30819Sbostic ** H&S says "%o" takes an unsigned argument; 958*30819Sbostic ** X3J11 says "%o" takes an int argument; 959*30819Sbostic ** we'll allow either here. 960*30819Sbostic */ 9617988Srrh 962*30819Sbostic static struct entry pprintf[] = { 963*30819Sbostic CHAR, '\0', "c", NULL, /* this is deliberate */ 964*30819Sbostic INT, '\0', "cdoxX", NULL, 965*30819Sbostic UNSIGNED, '\0', "uoxX", NULL, 966*30819Sbostic CHAR, '\0', "cdoxX", NULL, 967*30819Sbostic UCHAR, '\0', "udoxX", NULL, /* yes, d is okay */ 968*30819Sbostic SHORT, '\0', "cdoxX", NULL, 969*30819Sbostic USHORT, '\0', "uoxX", NULL, 970*30819Sbostic ENUMTY, '\0', "duoxX", NULL, 971*30819Sbostic LONG, 'l', "doxX", NULL, 972*30819Sbostic ULONG, 'l', "uoxX", NULL, 973*30819Sbostic FLOAT, '\0', "eEfgG", NULL, 974*30819Sbostic DOUBLE, '\0', "eEfgG", NULL, 975*30819Sbostic PTR|CHAR, '\0', "s", NULL, 976*30819Sbostic UNDEF, '\0', "", NULL 977*30819Sbostic }; 9787988Srrh 979*30819Sbostic /* 980*30819Sbostic ** Berkeley printf. 981*30819Sbostic ** It allows %D, %O, and %U, which we deprecate. 982*30819Sbostic ** Since 983*30819Sbostic ** sizeof (char *) == sizeof (int) && 984*30819Sbostic ** sizeof (int) == sizeof (long) && 985*30819Sbostic ** sizeof (char *) == sizeof (int *) 986*30819Sbostic ** you can be lax--and we tolerate *some* laxness. 987*30819Sbostic ** g/lax/p to find lax table entries and code. 988*30819Sbostic */ 9897988Srrh 990*30819Sbostic static char uppercase[] = "deprecated upper-case control character (%c)"; 991*30819Sbostic #define lax NULL 9927988Srrh 993*30819Sbostic static struct entry bprintf[] = { 994*30819Sbostic CHAR, '\0', "c", NULL, /* this is deliberate */ 995*30819Sbostic INT, '\0', "cdoxX", NULL, 996*30819Sbostic INT, '\0', "DO", uppercase, 997*30819Sbostic UNSIGNED, '\0', "uoxX", NULL, 998*30819Sbostic UNSIGNED, '\0', "UO", uppercase, 999*30819Sbostic CHAR, '\0', "cdoxX", NULL, 1000*30819Sbostic CHAR, '\0', "DO", uppercase, 1001*30819Sbostic UCHAR, '\0', "duoxX", NULL, /* yes, d is okay */ 1002*30819Sbostic UCHAR, '\0', "DUO", uppercase, 1003*30819Sbostic SHORT, '\0', "cdoxX", NULL, 1004*30819Sbostic SHORT, '\0', "DO", uppercase, 1005*30819Sbostic USHORT, '\0', "duoxX", NULL, /* d okay on BSD */ 1006*30819Sbostic USHORT, '\0', "DUO", uppercase, 1007*30819Sbostic ENUMTY, '\0', "duoxX", NULL, 1008*30819Sbostic ENUMTY, '\0', "DUO", uppercase, 1009*30819Sbostic LONG, '\0', "doxX", lax, 1010*30819Sbostic LONG, '\0', "DO", uppercase, 1011*30819Sbostic LONG, 'l', "doxX", NULL, 1012*30819Sbostic INT, 'l', "doxX", lax, 1013*30819Sbostic ULONG, '\0', "uoxX", lax, 1014*30819Sbostic ULONG, '\0', "UO", uppercase, 1015*30819Sbostic ULONG, 'l', "uoxX", NULL, 1016*30819Sbostic UNSIGNED, 'l', "uoxX", lax, 1017*30819Sbostic FLOAT, '\0', "eEfgG", NULL, 1018*30819Sbostic DOUBLE, '\0', "eEfgG", NULL, 1019*30819Sbostic PTR|CHAR, '\0', "s", NULL, 1020*30819Sbostic UNDEF, '\0', NULL, NULL, 1021*30819Sbostic }; 10227988Srrh 1023*30819Sbostic /* 1024*30819Sbostic ** Portable scanf. 'l' and 'h' are universally ignored preceding 'c' and 's', 1025*30819Sbostic ** and 'h' is universally ignored preceding 'e' and 'f', 1026*30819Sbostic ** but you won't find such cruft here. 1027*30819Sbostic */ 10287988Srrh 1029*30819Sbostic static struct entry pscanf[] = { 1030*30819Sbostic INT, '\0', "dox", NULL, 1031*30819Sbostic UNSIGNED, '\0', "uox", NULL, 1032*30819Sbostic CHAR, '\0', "cs[", NULL, 1033*30819Sbostic SHORT, 'h', "dox", NULL, 1034*30819Sbostic USHORT, 'h', "uox", NULL, 1035*30819Sbostic LONG, 'l', "dox", NULL, 1036*30819Sbostic ULONG, 'l', "uox", NULL, 1037*30819Sbostic FLOAT, '\0', "ef", NULL, /* BSD doesn't handle g */ 1038*30819Sbostic DOUBLE, 'l', "ef", NULL, 1039*30819Sbostic UNDEF, '\0', NULL, NULL, 1040*30819Sbostic }; 10417988Srrh 1042*30819Sbostic /* 1043*30819Sbostic ** Berkeley scanf. An upper case letter equals an l plus the lower case char, 1044*30819Sbostic ** but this is deprecated. 1045*30819Sbostic ** Even though sizeof (int) == sizeof (long), we'll be picky here. 1046*30819Sbostic */ 10477988Srrh 1048*30819Sbostic static struct entry bscanf[] = { 1049*30819Sbostic INT, '\0', "dox", NULL, 1050*30819Sbostic UNSIGNED, '\0', "uox", NULL, 1051*30819Sbostic CHAR, '\0', "cs[", NULL, 1052*30819Sbostic SHORT, 'h', "dox", NULL, 1053*30819Sbostic USHORT, 'h', "uox", NULL, 1054*30819Sbostic LONG, '\0', "dox", lax, 1055*30819Sbostic LONG, '\0', "DOX", uppercase, 1056*30819Sbostic LONG, 'l', "dox", NULL, 1057*30819Sbostic ULONG, '\0', "uox", lax, 1058*30819Sbostic ULONG, '\0', "UOX", uppercase, 1059*30819Sbostic ULONG, 'l', "uox", NULL, 1060*30819Sbostic FLOAT, '\0', "ef", NULL, 1061*30819Sbostic DOUBLE, '\0', "EF", uppercase, 1062*30819Sbostic DOUBLE, 'l', "ef", NULL, 1063*30819Sbostic UNDEF, '\0', NULL, NULL, 1064*30819Sbostic }; 10657988Srrh 1066*30819Sbostic static struct item { 1067*30819Sbostic char * name; /* such as "printf" */ 1068*30819Sbostic int isscan; /* scanf/printf */ 1069*30819Sbostic int fmtarg; /* number of format argument */ 1070*30819Sbostic struct entry * ptable; /* portable checking table */ 1071*30819Sbostic struct entry * btable; /* berkeley checking table */ 1072*30819Sbostic } items[] = { 1073*30819Sbostic "printf", 0, 1, pprintf, bprintf, 1074*30819Sbostic "fprintf", 0, 2, pprintf, bprintf, 1075*30819Sbostic "sprintf", 0, 2, pprintf, bprintf, 1076*30819Sbostic "scanf", 1, 1, pscanf, bscanf, 1077*30819Sbostic "fscanf", 1, 2, pscanf, bscanf, 1078*30819Sbostic "sscanf", 1, 2, pscanf, bscanf, 1079*30819Sbostic NULL, -1, -1, NULL, NULL 1080*30819Sbostic }; 10817988Srrh 1082*30819Sbostic static char pwf[] = "possible wild format"; 1083*30819Sbostic static char pfacm[] = "possible format/argument count mismatch"; 108411761Sedward 1085*30819Sbostic static struct entry * 1086*30819Sbostic findlc(ep, lchar, cchar) 1087*30819Sbostic register struct entry * ep; 1088*30819Sbostic register int lchar; 1089*30819Sbostic register int cchar; 1090*30819Sbostic { 1091*30819Sbostic for ( ; ep->argtype != UNDEF; ++ep) 1092*30819Sbostic if (ep->lchar == lchar && strchr(ep->cchars, cchar) != 0) 1093*30819Sbostic return ep; 1094*30819Sbostic return NULL; 1095*30819Sbostic } 10967988Srrh 1097*30819Sbostic static char * 1098*30819Sbostic subform(p, sp, acount) 1099*30819Sbostic register NODE * p; 1100*30819Sbostic register struct symtab * sp; 1101*30819Sbostic { 1102*30819Sbostic register int i, j, isscan; 1103*30819Sbostic register NODE * tp; 1104*30819Sbostic register char * cp; 1105*30819Sbostic register struct entry * basep; 1106*30819Sbostic register struct entry * ep; 1107*30819Sbostic register struct item * ip; 1108*30819Sbostic register int lchar; 1109*30819Sbostic register int cchar; 1110*30819Sbostic register int t; 1111*30819Sbostic register int suppressed; 1112*30819Sbostic static char errbuf[132]; 111311761Sedward 1114*30819Sbostic if (!hflag || nflag || strapped) 1115*30819Sbostic return NULL; 1116*30819Sbostic cp = sp->sname; 1117*30819Sbostic for (ip = items; ; ++ip) 1118*30819Sbostic if (ip->name == NULL) 1119*30819Sbostic return NULL; /* not a print/scan function */ 1120*30819Sbostic else if (strcmp(ip->name, sp->sname) == 0) 1121*30819Sbostic break; 1122*30819Sbostic isscan = ip->isscan; 1123*30819Sbostic i = ip->fmtarg; 1124*30819Sbostic if (i > acount) 1125*30819Sbostic return NULL; /* handled in pass 2 */ 1126*30819Sbostic tp = ntharg(p, i, acount); 1127*30819Sbostic if (tp->in.type != (PTR|CHAR)) 1128*30819Sbostic return NULL; /* handled in pass 2 */ 1129*30819Sbostic if (tp->in.op != ICON || tp->tn.lval != 0) 1130*30819Sbostic return NULL; /* can't check it */ 1131*30819Sbostic for (j = 1; j <= subscr; ++j) 1132*30819Sbostic if (tp == strnodes[j]) 1133*30819Sbostic break; 1134*30819Sbostic if (j > subscr) 1135*30819Sbostic return NULL; /* oh well. . . */ 1136*30819Sbostic cp = strings[j]; 1137*30819Sbostic /* 1138*30819Sbostic ** cp now points to format string. 1139*30819Sbostic */ 1140*30819Sbostic basep = pflag ? ip->ptable : ip->btable; 1141*30819Sbostic for ( ; ; ) { 1142*30819Sbostic if (*cp == '\0') 1143*30819Sbostic return (i == acount) ? NULL : pfacm; 1144*30819Sbostic if (*cp++ != '%') 1145*30819Sbostic continue; 1146*30819Sbostic if (*cp == '\0') 1147*30819Sbostic return "wild trailing %% in format"; 1148*30819Sbostic if (*cp == '%') { 1149*30819Sbostic ++cp; 1150*30819Sbostic continue; 1151*30819Sbostic } 1152*30819Sbostic if (isscan) { 1153*30819Sbostic suppressed = *cp == '*'; 1154*30819Sbostic if (suppressed) 1155*30819Sbostic ++cp; 1156*30819Sbostic while (isdigit(*cp)) 1157*30819Sbostic ++cp; 1158*30819Sbostic if (!suppressed && ++i <= acount) { 1159*30819Sbostic t = ntharg(p, i, acount)->in.type; 1160*30819Sbostic if (!ISPTR(t)) { 1161*30819Sbostic (void) sprintf(errbuf, 1162*30819Sbostic "%s argument is type (%s) rather than pointer (arg %d)", 1163*30819Sbostic ip->name, typestr(t), i); 1164*30819Sbostic return errbuf; 1165*30819Sbostic } 1166*30819Sbostic t = DECREF(t); 1167*30819Sbostic } 1168*30819Sbostic } else { 1169*30819Sbostic int nspace, ndash, nplus, nhash; 1170*30819Sbostic 1171*30819Sbostic suppressed = 0; 1172*30819Sbostic nspace = ndash = nplus = nhash = 0; 1173*30819Sbostic for ( ; ; ) { 1174*30819Sbostic if (*cp == ' ') 1175*30819Sbostic ++nspace; 1176*30819Sbostic else if (*cp == '+') 1177*30819Sbostic ++nplus; 1178*30819Sbostic else if (*cp == '-') 1179*30819Sbostic ++ndash; 1180*30819Sbostic else if (*cp == '#') 1181*30819Sbostic ++nhash; 1182*30819Sbostic else break; 1183*30819Sbostic ++cp; 1184*30819Sbostic } 1185*30819Sbostic if (nspace > 1 || ndash > 1 || nplus > 1 || nhash > 1) 1186*30819Sbostic return "wild repeated flag character in format"; 1187*30819Sbostic if (*cp == '*') { 1188*30819Sbostic ++cp; 1189*30819Sbostic if (++i > acount) 1190*30819Sbostic break; 1191*30819Sbostic t = ntharg(p, i, acount)->in.type; 1192*30819Sbostic /* 1193*30819Sbostic ** Width other than INT or UNSIGNED is suspect. 1194*30819Sbostic */ 1195*30819Sbostic if (t != INT && t != UNSIGNED) { 1196*30819Sbostic (void) sprintf(errbuf, 1197*30819Sbostic "field width argument is type (%s) rather than (int) (arg %d)", 1198*30819Sbostic typestr(t), i); 1199*30819Sbostic return errbuf; 1200*30819Sbostic } 1201*30819Sbostic } else while (isdigit(*cp)) 1202*30819Sbostic ++cp; 1203*30819Sbostic if (*cp == '.') { 1204*30819Sbostic ++cp; 1205*30819Sbostic if (*cp == '*') { 1206*30819Sbostic ++cp; 1207*30819Sbostic if (++i > acount) 1208*30819Sbostic return pfacm; 1209*30819Sbostic t = ntharg(p, i, acount)->in.type; 1210*30819Sbostic if (t != INT && t != UNSIGNED) { 1211*30819Sbostic (void) sprintf(errbuf, 1212*30819Sbostic "precision argument is type (%s) rather than (int) (arg %d)", 1213*30819Sbostic typestr(t), i); 1214*30819Sbostic return errbuf; 1215*30819Sbostic } 1216*30819Sbostic } else while (isdigit(*cp)) 1217*30819Sbostic ++cp; 1218*30819Sbostic } 1219*30819Sbostic if (++i <= acount) 1220*30819Sbostic t = ntharg(p, i, acount)->in.type; 1221*30819Sbostic } 1222*30819Sbostic if (*cp == 'h' || *cp == 'l') 1223*30819Sbostic lchar = *cp++; 1224*30819Sbostic else lchar = '\0'; 1225*30819Sbostic if ((cchar = *cp++) == '\0') 1226*30819Sbostic return pwf; 1227*30819Sbostic if (i > acount) 1228*30819Sbostic return (findlc(basep, lchar, cchar) == NULL) ? 1229*30819Sbostic pwf : pfacm; 1230*30819Sbostic if (!isscan && !pflag && ISPTR(t) && 1231*30819Sbostic strchr("douxX", cchar) != 0) 1232*30819Sbostic continue; /* lax--printf("%d", (int *)) */ 1233*30819Sbostic if (suppressed) { 1234*30819Sbostic if (findlc(basep, lchar, cchar) == NULL) 1235*30819Sbostic return pwf; 1236*30819Sbostic } else for (ep = basep; ; ++ep) { 1237*30819Sbostic if (ep->argtype == UNDEF) { /* end of table */ 1238*30819Sbostic ep = findlc(basep, lchar, cchar); 1239*30819Sbostic if (ep == NULL) 1240*30819Sbostic return pwf; 1241*30819Sbostic (void) sprintf(errbuf, "%s: (%s) format, (%s) arg (arg %d)", 1242*30819Sbostic ip->name, 1243*30819Sbostic typestr(ep->argtype), 1244*30819Sbostic typestr(isscan ? (t | PTR) : t), i); 1245*30819Sbostic return errbuf; 1246*30819Sbostic } 1247*30819Sbostic if (ep->argtype == t && ep->lchar == lchar && 1248*30819Sbostic strchr(ep->cchars, cchar) != 0) 1249*30819Sbostic if (ep->werror == 0) 1250*30819Sbostic break; 1251*30819Sbostic else { 1252*30819Sbostic werror(ep->werror, cchar); 1253*30819Sbostic return NULL; 1254*30819Sbostic } 1255*30819Sbostic } 1256*30819Sbostic if (cchar != '[') 1257*30819Sbostic continue; 1258*30819Sbostic do { 1259*30819Sbostic if (*cp == '\0') 1260*30819Sbostic return "possible unmatched '[' in format"; 1261*30819Sbostic } while (*cp++ != ']'); 1262*30819Sbostic } 1263*30819Sbostic /*NOTREACHED*/ 1264*30819Sbostic } 1265*30819Sbostic 1266*30819Sbostic doform(p, sp, acount) 1267*30819Sbostic NODE * p; 1268*30819Sbostic struct symtab * sp; 1269*30819Sbostic { 1270*30819Sbostic char * cp; 1271*30819Sbostic 1272*30819Sbostic if ((cp = subform(p, sp, acount)) != NULL) 1273*30819Sbostic werror(cp); 1274*30819Sbostic } 1275*30819Sbostic 1276*30819Sbostic cisreg(t) TWORD t; {return(1);} /* everyting is a register variable! */ 1277*30819Sbostic 1278*30819Sbostic fldty(p) struct symtab *p; { 1279*30819Sbostic ; /* all types are OK here... */ 1280*30819Sbostic } 1281*30819Sbostic 1282*30819Sbostic fldal(t) unsigned t; { /* field alignment... */ 1283*30819Sbostic if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */ 1284*30819Sbostic if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */ 1285*30819Sbostic if( pflag ) uerror( "nonportable field type" ); 1286*30819Sbostic } 1287*30819Sbostic else uerror( "illegal field type" ); 1288*30819Sbostic return(ALINT); 1289*30819Sbostic } 1290*30819Sbostic 1291*30819Sbostic main(argc, argv) 1292*30819Sbostic int argc; 1293*30819Sbostic char **argv; 1294*30819Sbostic { 1295*30819Sbostic extern char *optarg; 1296*30819Sbostic extern int optind; 1297*30819Sbostic int ch; 1298*30819Sbostic 1299*30819Sbostic while ((ch = getopt(argc,argv,"C:D:I:U:LPabchnpuvxz")) != EOF) 1300*30819Sbostic switch((char)ch) { 130111403Snicklin case 'C': 130211403Snicklin Cflag = 1; 1303*30819Sbostic libname = optarg; 130411403Snicklin continue; 1305*30819Sbostic case 'D': /* #define */ 1306*30819Sbostic case 'I': /* include path */ 1307*30819Sbostic case 'U': /* #undef */ 1308*30819Sbostic case 'P': /* debugging, done in second pass */ 1309*30819Sbostic break; 1310*30819Sbostic case 'L': 1311*30819Sbostic libflag = 1; 1312*30819Sbostic /*FALLTHROUGH*/ 1313*30819Sbostic case 'v': /* unused arguments in functions */ 1314*30819Sbostic vflag = 0; 1315*30819Sbostic break; 1316*30819Sbostic case 'a': /* long to int assignment */ 1317*30819Sbostic ++aflag; 1318*30819Sbostic break; 1319*30819Sbostic case 'b': /* unreached break statements */ 1320*30819Sbostic brkflag = 1; 1321*30819Sbostic break; 1322*30819Sbostic case 'c': /* questionable casts */ 1323*30819Sbostic cflag = 1; 1324*30819Sbostic break; 1325*30819Sbostic case 'h': /* heuristics */ 1326*30819Sbostic hflag = 1; 1327*30819Sbostic break; 1328*30819Sbostic case 'n': /* standard library check */ 1329*30819Sbostic nflag = 1; 1330*30819Sbostic break; 1331*30819Sbostic case 'p': /* IBM & GCOS portability */ 1332*30819Sbostic pflag = 1; 1333*30819Sbostic break; 1334*30819Sbostic case 'u': /* 2nd pass: undefined or unused */ 1335*30819Sbostic break; 1336*30819Sbostic case 'x': /* unused externs */ 1337*30819Sbostic xflag = 1; 1338*30819Sbostic break; 1339*30819Sbostic case 'z': /* use of undefined structures */ 1340*30819Sbostic zflag = 1; 1341*30819Sbostic break; 1342*30819Sbostic case '?': 134311403Snicklin default: 1344*30819Sbostic fputs("usage: lint [-C lib] [-D def] [-I include] [-U undef] [-Labchnpuvx] file ...\n",stderr); 1345*30819Sbostic exit(1); 1346*30819Sbostic } 134711403Snicklin 1348*30819Sbostic if (!pflag) { /* set sizes to sizes of target machine */ 13497988Srrh # ifdef gcos 13507988Srrh SZCHAR = ALCHAR = 9; 13517988Srrh # else 13527988Srrh SZCHAR = ALCHAR = 8; 13537988Srrh # endif 13547988Srrh SZINT = ALINT = sizeof(int)*SZCHAR; 13557988Srrh SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; 13567988Srrh SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; 13577988Srrh SZLONG = ALLONG = sizeof(long)*SZCHAR; 13587988Srrh SZSHORT = ALSHORT = sizeof(short)*SZCHAR; 13597988Srrh SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; 13607988Srrh ALSTRUCT = ALINT; 13617988Srrh /* now, fix some things up for various machines (I wish we had "alignof") */ 13627988Srrh 13637988Srrh # ifdef pdp11 13647988Srrh ALLONG = ALDOUBLE = ALFLOAT = ALINT; 1365*30819Sbostic # endif 13667988Srrh # ifdef ibm 13677988Srrh ALSTRUCT = ALCHAR; 1368*30819Sbostic # endif 13697988Srrh } 1370*30819Sbostic return(mainp1(argc,argv)); 1371*30819Sbostic } 13727988Srrh 13737988Srrh ctype( type ) unsigned type; { /* are there any funny types? */ 13747988Srrh return( type ); 13757988Srrh } 13767988Srrh 13777988Srrh commdec( i ){ 13787988Srrh /* put out a common declaration */ 137911761Sedward if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL ); 138011761Sedward else outdef( &stab[i], libflag?LIB:LDC, USUAL ); 13817988Srrh } 13827988Srrh 13837988Srrh isitfloat ( s ) char *s; { 13847988Srrh /* s is a character string; 13857988Srrh if floating point is implemented, set dcon to the value of s */ 13867988Srrh /* lint version 13877988Srrh */ 13887988Srrh dcon = atof( s ); 138925304Sbloom return( DCON ); 13907988Srrh } 13917988Srrh 13927988Srrh fldcon( p ) register NODE *p; { 13937988Srrh /* p is an assignment of a constant to a field */ 13947988Srrh /* check to see if the assignment is going to overflow, or otherwise cause trouble */ 13957988Srrh register s; 13967988Srrh CONSZ v; 13977988Srrh 13987988Srrh if( !hflag & !pflag ) return; 13997988Srrh 14007988Srrh s = UPKFSZ(p->in.left->tn.rval); 14017988Srrh v = p->in.right->tn.lval; 14027988Srrh 14037988Srrh switch( p->in.left->in.type ){ 14047988Srrh 14057988Srrh case CHAR: 14067988Srrh case INT: 14077988Srrh case SHORT: 14087988Srrh case LONG: 14097988Srrh case ENUMTY: 14107988Srrh if( v>=0 && (v>>(s-1))==0 ) return; 14117988Srrh werror( "precision lost in assignment to (possibly sign-extended) field" ); 14127988Srrh default: 14137988Srrh return; 14147988Srrh 14157988Srrh case UNSIGNED: 14167988Srrh case UCHAR: 14177988Srrh case USHORT: 14187988Srrh case ULONG: 14197988Srrh if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); 14207988Srrh 14217988Srrh return; 14227988Srrh } 14237988Srrh 14247988Srrh } 14257988Srrh 14267988Srrh outdef( p, lty, mode ) struct symtab *p; { 14277988Srrh /* output a definition for the second pass */ 14287988Srrh /* if mode is > USUAL, it is the number of args */ 14297988Srrh char *fname; 14307988Srrh TWORD t; 14317988Srrh int line; 14327988Srrh static union rec rc; 14337988Srrh 14347988Srrh if( mode == NOFILE ){ 14357988Srrh fname = "???"; 14367988Srrh line = p->suse; 14377988Srrh } 14387988Srrh else if( mode == SVLINE ){ 14397988Srrh fname = ftitle; 14407988Srrh line = -p->suse; 14417988Srrh } 14427988Srrh else { 14437988Srrh fname = ftitle; 14447988Srrh line = lineno; 14457988Srrh } 14467988Srrh fsave( fname ); 14477988Srrh #ifndef FLEXNAMES 14487988Srrh strncpy( rc.l.name, exname(p->sname), LCHNM ); 14497988Srrh #endif 14507988Srrh rc.l.decflag = lty; 14517988Srrh t = p->stype; 14527988Srrh if( mode == DECTY ) t = DECREF(t); 14537988Srrh rc.l.type.aty = t; 14547988Srrh rc.l.type.extra = 0; 145511761Sedward rc.l.type.extra1 = 0; 14567988Srrh astype( &rc.l.type, p->sizoff ); 14577988Srrh rc.l.nargs = (mode>USUAL) ? mode : 0; 14587988Srrh rc.l.fline = line; 14597988Srrh fwrite( (char *)&rc, sizeof(rc), 1, stdout ); 14607988Srrh #ifdef FLEXNAMES 14617988Srrh rc.l.name = exname(p->sname); 14627988Srrh fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout ); 14637988Srrh #endif 14647988Srrh } 14657988Srrh int proflg; 14667988Srrh int gdebug; 1467