Annotation of researchv10no/cmd/lint/olint1.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.