Annotation of researchv10no/cmd/ccom/common/sty.y, revision 1.1.1.1

1.1       root        1: /* @(#) sty.y: 1.1 12/22/83                            */
                      2: %{
                      3: static char    SCCSID[] = "@(#) sty.y: 1.1 83/08/02";
                      4: /*
                      5:        This program turns machine descriptions into a table.c file
                      6: */
                      7: %}
                      8: /*     The input language uses many C conventions and notations */
                      9: /*     Types are represented as a shorthand:
                     10:        c       char
                     11:        i       int
                     12:        s       short
                     13:        l       long
                     14:        p       pointer
                     15:        P       alternate form of pointer
                     16:        t       structure
                     17:        v       void
                     18:        ux      unsigned x
                     19:        f       float
                     20:        d       double
                     21: /*     There are a number of builtin cost names:
                     22:        NONAME          a constant with no name field (not an address)
                     23:        CONVAL n        the constant n
                     24:        NCONVAL n       the constant -n
                     25:        POSRANGE n      constants in the range [0,2**n -1]
                     26:        SGRANGE n       constants in the range [-2**n, 2**n - 1]
                     27:        */
                     28: /*     There are also several incedental needs, etc, specified
                     29:        1,2,3   Number of needed registers
                     30:        $P      need pairs
                     31:        $<      share left
                     32:        $>      share right
                     33:        $L      result left
                     34:        $R      result right
                     35:        $1,2,3  result in reg 1, 2, 3
                     36:        $C      operation produces correct condition codes
                     37:        $N      no value produced: side effects only
                     38:        $A      need them all
                     39:        $[      share left, RHS is preferred (if a temp register)
                     40:        $]      share right, RHS is preferred (if a temp register)
                     41:        $l      left side is referenced once more
                     42:        $r      right side is referenced once more
                     43:        */
                     44: 
                     45: /* NOTE:
                     46:        When several templates match with equal cost, the first is chosen.
                     47:        Thus, when side-effects only are desired, the first template matching
                     48:        is taken, if it is of lowest cost.
                     49:        Moral:  $N templates should be cheaper or should preceed $L, $1, etc.
                     50:        */
                     51: 
                     52: %{
                     53: # include "ctype.h"
                     54: # include "mfile2.h"
                     55: # include "dope.h"
                     56: 
                     57: typedef struct {
                     58:        int     sha;    /* shape */
                     59:        int     ty;     /* type */
                     60: } SHTY;
                     61: SHTY   lshty,  /* left and right shape type */
                     62:        rshty;
                     63: static int     dcost = 0;      /* default cost */
                     64: static int     op,
                     65:                tyop,
                     66:                needs,
                     67:                rewrite,
                     68:                cost;
                     69: static int     lcount, rcount;
                     70: static int     opno;
                     71: static int     ophd[DSIZE];
                     72: static int     optl[DSIZE];
                     73: static int     opsh[DSIZE];
                     74: 
                     75: struct optb {          /* operation table */
                     76:        int     op;     /* what operation is to be matched */
                     77:        int     tyop;   /* the type associated with the op node */
                     78:        int     nxop;   /* index of the next op */
                     79:        int     line;   /* stin file line number */
                     80:        SHTY    l,      /* shapes of the left side */
                     81:                r;      /*              right side */
                     82:        int     oneeds, /* needs */
                     83:                orew,   /* rewrite info */
                     84:                ocost;  /* op cost */
                     85:        char    *string;/* the output */
                     86:        int     strdef, 
                     87:                struse;
                     88:        int     olcount,/* usage count for left side */
                     89:                orcount;/* and right side */
                     90: };
                     91: typedef struct optb OPTB;
                     92: 
                     93: # ifndef NOPTB
                     94: # define NOPTB 400
                     95: # endif
                     96: 
                     97: OPTB optb[NOPTB];
                     98: 
                     99: # ifndef NSTRING
                    100: # define NSTRING 10000
                    101: # endif
                    102: 
                    103: # ifndef NSTYSHPS
                    104: # define NSTYSHPS 4000
                    105: # endif
                    106: 
                    107: typedef struct {
                    108:        int     sop,
                    109:                sleft,
                    110:                sright,
                    111:                ssh,
                    112:                scset,  /* ==1 after cost for shape has been set, else 0 */
                    113:                scost,
                    114:                scnt;
                    115:        char    shname[8];
                    116: } STYSHP;
                    117: 
                    118: static int     was_cost;       /* set if a cost was actually specified */
                    119: static int     nshp = 0;
                    120: static int     nmshp = NSTYSHPS - 1;
                    121: /*static*/ STYSHP      shp[NSTYSHPS];
                    122: static char    strng[NSTRING];
                    123: static char    *string;
                    124: static char    *pstring = strng;
                    125: static char    *asstring;
                    126: 
                    127: %}
                    128: 
                    129: %union {
                    130:        int     ival;
                    131:        char    *str;
                    132:        SHTY    shh;
                    133: };
                    134: 
                    135: %token STR DEF LPRF RPRF LSHR RSHR GOODCC NOVAL PNEED LRES RRES LCOUNT RCOUNT
                    136: %token USERCOST CONVAL NCONVAL POSRANGE SGRANGE NONAME DCOST SHAPES OPCODES
                    137: %token <ival> OP NM DIG STYPE RREG
                    138: %left OP
                    139: %left STYPE
                    140: 
                    141: %type <str> STR
                    142: %type <ival> opcost num slist nterm opop shape
                    143: %type <ival> costnexp nexp
                    144: %type <ival> cost cexpr cterm
                    145: %type <shh> sref
                    146: 
                    147:        /*
                    148:        OP      the ops <, <<, >, >>, <=, >=, +, -, *, /, %, &, ^, ~, !
                    149:        NM      names (letter, followed by 0 or more letters or digits
                    150:        STR     a string in ""
                    151:        DIG     a digit, 0-9
                    152:        Other letters are returned: (, ), {, }, etc.
                    153:        */
                    154: 
                    155: %%
                    156: 
                    157: file   :       SHAPES lshapes OPCODES lops
                    158:                {       finished(); }
                    159:        ;
                    160: 
                    161: lshapes        :       /* EMPTY */
                    162:        |       lshapes NM ':' slist ',' costnexp ';'
                    163:                {       shp[$2].sop = MANY;
                    164:                        shp[$2].sleft = $4;
                    165:                        shp[$2].sright = $6;
                    166:                        shp[$2].scost = 0;
                    167:                        shp[$2].scset = 1;
                    168:                        shp[$2].ssh = 0;
                    169:                }
                    170:        |       lshapes NM ':' costnexp ';'
                    171:                {       
                    172:                        shp[$2].sop = MANY;
                    173:                        shp[$2].sleft = $4;
                    174:                        shp[$2].sright = -1;
                    175:                        shp[$2].scost = 0;
                    176:                        shp[$2].scset = 1;
                    177:                        shp[$2].ssh = 0;
                    178:                }
                    179:        |       lshapes NM ':' opop shape opcost ';'
                    180:                {       shp[nshp].scost = $6;
                    181:                        shp[nshp].scset = was_cost;
                    182:                        shp[nshp].ssh = $5;
                    183:                        shp[nshp].sop = $4;
                    184:                        shp[nshp].sleft = -1;
                    185:                        shp[nshp].sright = -1;
                    186:                        ++nshp;
                    187:                        checkit( nshp-1 );
                    188:                        shp[$2].sop = MANY;
                    189:                        shp[$2].sleft = nshp-1;
                    190:                        shp[$2].sright = -1;
                    191:                        shp[$2].scost = 0;
                    192:                        shp[$2].scset = 1;
                    193:                        shp[$2].ssh = 0;
                    194:                        if( nshp >= nmshp ) {
                    195:                                yyerror( "out of node space" );
                    196:                                exit( 1 );
                    197:                        }
                    198:                }
                    199:        ;
                    200: 
                    201: opop   :       /* EMPTY */
                    202:                {       $$ = ICON; }
                    203:        |       OP
                    204:        ;
                    205: 
                    206: lops   :       /* EMPTY */
                    207:                {       needs = op = rewrite = cost = 0;
                    208:                        lcount = rcount = 1;
                    209:                }
                    210: 
                    211:        |       lops lop
                    212:        ;
                    213: 
                    214: lop    :       OP sref ',' sref ltail
                    215:                {       lshty = $2;
                    216:                        rshty = $4;
                    217:                        op = $1;
                    218:                        tyop = TANY;
                    219:                        output();
                    220:                        tyop = needs = op = rewrite = cost = 0;
                    221:                        lcount = rcount = 1;
                    222:                }
                    223:        |       OP STYPE sref ',' sref ltail
                    224:                {       lshty = $3;
                    225:                        rshty = $5;
                    226:                        op = $1;
                    227:                        tyop = $2;
                    228:                        output();
                    229:                        tyop = needs = op = rewrite = cost = 0;
                    230:                        lcount = rcount = 1;
                    231:                }
                    232:        |       OP sref ltail
                    233:                {       lshty = $2;
                    234:                        rshty.sha = -1;
                    235:                        rshty.ty = TANY;
                    236:                        op = $1;
                    237:                        tyop = TANY;
                    238:                        output();
                    239:                        tyop = needs = op = rewrite = cost = 0;
                    240:                        lcount = rcount = 1;
                    241:                }
                    242:        |       OP STYPE sref ltail
                    243:                {       lshty = $3;
                    244:                        rshty.sha = -1;
                    245:                        rshty.ty = $2;
                    246:                        op = $1;
                    247:                        tyop = TANY;
                    248:                        output();
                    249:                        tyop = needs = op = rewrite = cost = 0;
                    250:                        lcount = rcount = 1;
                    251:                }
                    252:        |       sref ltail
                    253:                {       rshty = $1;
                    254:                        lshty.sha = -1;
                    255:                        lshty.ty = TANY;
                    256:                        loutput();
                    257:                        tyop = needs = op = rewrite = cost = 0;
                    258:                        lcount = rcount = 1;
                    259:                        }
                    260:        |       DCOST {dcost=0;} opcost ';'
                    261:                        {       dcost = $3; }
                    262:        ;
                    263: 
                    264: ltail  :       needs STR opcost ';'
                    265:                {       
                    266:                        cost = $3;
                    267:                        asstring = $2;
                    268:                        }
                    269:        ;
                    270: 
                    271: needs  :       /* EMPTY */
                    272:                {       needs = 0; }
                    273:        |       '{' nlist '}'
                    274:        ;
                    275: 
                    276: nlist  :       /* EMPTY */
                    277:                {       needs = 0; }
                    278:        |       nlist DIG
                    279:                {       needs = (needs&~NCOUNT) | $2; }
                    280:        |       nlist RPRF
                    281:                {       needs |= RSHARE|RPREF; }
                    282:        |       nlist LPRF
                    283:                {       needs |= LSHARE|LPREF; }
                    284:        |       nlist RSHR
                    285:                {       needs |= RSHARE; }
                    286:        |       nlist LSHR
                    287:                {       needs |= LSHARE; }
                    288:        |       nlist PNEED
                    289:                {       needs |= NPAIR; }
                    290:        |       nlist GOODCC
                    291:                {       rewrite |= RESCC; }
                    292:        |       nlist NOVAL
                    293:                {
                    294:                        if (rewrite)
                    295:                                yyerror("$N incompatible with other results");
                    296:                        rewrite = RNULL;
                    297:                }
                    298:        |       nlist LRES
                    299:                {       rewrite |= RLEFT; }
                    300:        |       nlist RRES
                    301:                {       rewrite |= RRIGHT; }
                    302:        |       nlist RREG
                    303:                {       if( !(needs&NCOUNT) ) needs |= $2;
                    304:                        rewrite |= (($2==1)?RESC1:(($2==2)?RESC2:RESC3));
                    305:                        }
                    306:        |       nlist LCOUNT
                    307:                {       lcount += 1; }
                    308:        |       nlist RCOUNT
                    309:                {       rcount += 1; }
                    310:        ;
                    311: 
                    312: num    :       DIG
                    313:        |       num DIG
                    314:                {       $$ = 10*$1 + $2; }
                    315:        ;
                    316: 
                    317: opcost :       cost
                    318:                {       was_cost = 1; }
                    319:        |       /* EMPTY */
                    320:                {       was_cost = 0; $$ = dcost; }
                    321:        ;
                    322: 
                    323: cost   :       ':' cexpr
                    324:                {       $$ = $2; }
                    325:        ;
                    326: 
                    327: cexpr  :       cterm
                    328:        |       OP cterm
                    329:                {       $$ = uopcost( $1, $2 ); }
                    330:        |       cterm OP cterm
                    331:                {       $$ = bopcost( $2, $1, $3 ); }
                    332:        ;
                    333: 
                    334: cterm  :       '(' cexpr ')'
                    335:                {       $$ = $2; }
                    336:        |       num
                    337:        ;
                    338: 
                    339: shape  :       /* EMPTY */
                    340:                {       $$ = 0; }
                    341:        |       NONAME
                    342:                {       $$ = NACON;     /* constant with no name */ }
                    343:        |       USERCOST num
                    344:                {       $$ = $2|SUSER;  /* user's cost ftn */ }
                    345:        |       CONVAL num
                    346:                {       $$ = $2|SVAL;  /* positive constant value */ }
                    347:        |       NCONVAL num
                    348:                {       $$ = $2|SNVAL;  /* negative constant value */ }
                    349:        |       POSRANGE num
                    350:                {       $$ = $2|SRANGE0;  /* positive range */ }
                    351:        |       SGRANGE num
                    352:                {       $$ = $2|SSRANGE;  /* signed range */ }
                    353:        ;
                    354: 
                    355: sref   :       nterm
                    356:                {       $$.ty = 0;
                    357:                        $$.sha = $1;
                    358:                        }
                    359:        |       nterm STYPE     /* do this before doing in nterm */
                    360:                {       $$.sha = $1;
                    361:                        $$.ty = $2; }
                    362:        ;
                    363: 
                    364: slist  :       costnexp
                    365:        |       slist ',' costnexp
                    366:                {       $$ = bop( MANY, $1, $3, 0 ); }
                    367:        ;
                    368: 
                    369: costnexp:      nexp opcost
                    370:                {       $$ = sharecost($1, $2); }
                    371:        ;
                    372:        
                    373: nexp   :       nterm
                    374:        |       OP nterm
                    375:                {       $$ = uop( $1, $2 ); }
                    376:        |       nterm OP nterm
                    377:                {       $$ = bop( $2, $1, $3, 0 ); }
                    378:        ;
                    379: 
                    380: nterm  :       '(' nexp ')'
                    381:                {       $$ = $2; }
                    382:        |       NM
                    383:        |       nterm STYPE
                    384:                {       $$ = top( $1, $2 );  }
                    385:        ;
                    386: 
                    387: %%
                    388: static int     lineno = 1;     /* line number of stin file */
                    389: static char    filename[100] = "<stdin>";
                    390: 
                    391: main(argc, argv)
                    392: int argc;
                    393: char **argv;
                    394: {
                    395:        register int i;
                    396:        for( i=0; i<DSIZE; ++i ) {
                    397:                opsh[i] = 0;
                    398:                optl[i] = ophd[i] = -1;
                    399:        }
                    400:        mkdope();
                    401:        yyparse();
                    402:        exit( 0 );
                    403: }
                    404: 
                    405: 
                    406: checkit( n )
                    407: {
                    408:        /* check a shape */
                    409:        STYSHP *p;
                    410:        if( n<0 ) return;
                    411:        if( n>=nshp && n<=nmshp || n>=NSTYSHPS ) {
                    412:                yyerror( "out of range shape: %d", n );
                    413:        }
                    414:        p = &shp[n];
                    415:        if( p->sop < 0 || p->sop > MANY ) {
                    416:                yyerror( "out of range op: %d", p->sop );
                    417:        }
                    418: 
                    419:        switch( optype(p->sop) ) {
                    420: 
                    421:        case BITYPE:
                    422:                if( p->sright < 0 && p->sop != MANY ) {
                    423:                        yyerror( "right side empty" );
                    424:                }
                    425:                checkit( p->sright );
                    426:        case UTYPE:
                    427:                if( p->sleft < 0 ) {
                    428:                        yyerror( "left side empty" );
                    429:                }
                    430:                checkit( p->sleft );
                    431:        }
                    432: }
                    433: 
                    434:        /* VARARGS */
                    435: yyerror( s, a )
                    436: char *s;
                    437: {
                    438:        fprintf( stderr, s, a );
                    439:        fprintf( stderr, ", file \"%s\", line %d\n", filename, lineno );
                    440:        abort();
                    441:        exit( 1 );
                    442: }
                    443: 
                    444: 
                    445: static int     otb[20];        /* ops that are part of the shape */
                    446: static int     notb;           /* number of otb entries */
                    447: 
                    448: loutput()
                    449: {
                    450:        /*
                    451:         * rhs has a leaf: output templates for all interesting
                    452:         * operators in this leaf. 
                    453:         * An interesting operator is one that is NOT MANY.
                    454:         * This allows us to access the table for each operator
                    455:         * that this leaf may implement.
                    456:         */
                    457:        register int    i;
                    458:        register int    s;
                    459:        register int    ocost = cost;
                    460: 
                    461:        notb = 0;
                    462:        lout1( s = rshty.sha );
                    463:        if( !notb ) yyerror( "lout1() error" );
                    464:        for( i = notb-1;  i >= 0;  --i )
                    465:        {
                    466:                op = otb[i];
                    467:                tyop = TANY;
                    468:                if( optype(op) == LTYPE ) {
                    469:                        lcount = 0;
                    470:                        cost = ocost + (rcount * refine(s));
                    471:                }
                    472:                else if( optype(op) == BITYPE ) {
                    473:                        yyerror( "binary op in shape not done right" );
                    474:                }
                    475:                else {  /* op is unary */
                    476:                        lcount = rcount;
                    477:                        rcount = 0;
                    478:                        cost = ocost + (lcount * urefine(s));
                    479:                }
                    480:                output();
                    481:        }
                    482: }
                    483: 
                    484: urefine( s ) {  /* construct an entry for a unary op matching shape s */
                    485:        /* for now, punt on the costs */
                    486:        rcount = lcount;
                    487:        lcount = 0;
                    488:        return( refine( s ) );
                    489: }
                    490: 
                    491: smat(s)
                    492: register s;
                    493: {
                    494:        /*
                    495:         *      return 1 if we can find the op anyplace in the
                    496:         *      shape tree `s'
                    497:         */
                    498:        if( s < 0 )
                    499:                return( 0 );
                    500:        if( shp[s].sop == MANY )
                    501:        {
                    502:                if( shp[s].sleft>=0 && smat( shp[s].sleft ) ) return( 1 );
                    503:                if( shp[s].sright>=0 && smat( shp[s].sright ) ) return( 1 );
                    504:                return( 0 );
                    505:        }
                    506:        return( shp[s].sop == op );
                    507: }
                    508: 
                    509: refine(s)
                    510: register s;
                    511: {
                    512:        /*
                    513:         * find the largest subshape of `s' that contains
                    514:         * the operator `op' (op is global).
                    515:         * We descend MANY nodes until we run out,
                    516:         * or until the operator `op' is found in both descendents.
                    517:         * Since we are throwing away costs buried in the MANY nodes
                    518:         * on the way down, we must keep track of those, to
                    519:         * adjust the costs appropriately in the operator table.
                    520:         */
                    521:        register int bc = 0;
                    522: 
                    523:        while( shp[s].sop == MANY )
                    524:        {
                    525:                bc += shp[s].scost;
                    526:                if( smat( shp[s].sleft ) )
                    527:                {
                    528:                        if( smat( shp[s].sright ) ) break;
                    529:                        else s = shp[s].sleft;
                    530:                }
                    531:                else s = shp[s].sright;
                    532:        }
                    533:        lshty.sha = -1;
                    534:        rshty.sha = mkshp(s);
                    535:        return( bc + shp[s].scost );
                    536: }
                    537: 
                    538: lout1( n )
                    539: register n;
                    540: {
                    541:        register int i;
                    542:        while( n >= 0  &&  shp[n].sop == MANY )
                    543:        {
                    544:                lout1( shp[n].sleft );
                    545:                n = shp[n].sright;
                    546:        }
                    547:        if( n < 0 )
                    548:                return;
                    549:        for( i=0; i<notb; ++i )
                    550:        {
                    551:                if( otb[i] == shp[n].sop ) return;
                    552:        }
                    553:        otb[notb++] = shp[n].sop;
                    554: }
                    555: 
                    556: mkshp(s)
                    557: {
                    558:        /* make a shape that yields s */
                    559:        /* first, make s a MANY node */
                    560:        register i;
                    561: 
                    562:        if( s < 0 ) return( s );
                    563:        if( shp[s].sop == MANY ) i = s;
                    564:        else {
                    565:                /* look for a MANY node pointing to s */
                    566:                for( i= NSTYSHPS; i>nmshp; --i ) {
                    567:                        if( shp[i].sright >= 0 ) continue;
                    568:                        if( shp[i].sleft == s ) goto foundit;
                    569:                }
                    570:                /* must make a MANY node */
                    571:                i = bop( MANY, s, -1, 0 );
                    572:        }
                    573: 
                    574:        /* now, make sure that i has a name, so it will be output */
                    575: 
                    576:        foundit: ;
                    577: 
                    578:        if( !shp[i].shname[0] ) {
                    579:                strcpy( shp[i].shname, "mkshp" );
                    580:        }
                    581:        return(i);
                    582: }
                    583: 
                    584: onebit(x)
                    585: register x;
                    586: {
                    587:        /* return 1 if x has at most 1 bit on, 0 otherwise */
                    588:        return( !(x&(x-1)) );
                    589: }
                    590: 
                    591: output()
                    592: {
                    593:        register OPTB *q;
                    594:        register int j;
                    595: 
                    596:        if( lshty.ty == 0 ) lshty.ty = TANY;
                    597:        if( rshty.ty == 0 ) rshty.ty = TANY;
                    598: 
                    599:        switch( op )
                    600:        {
                    601: 
                    602:        case 0:
                    603:                yyerror( "0 op" );
                    604: 
                    605:        case STAR:
                    606:        case REG:
                    607:        case UNARY MINUS:
                    608:        case UNARY AND:
                    609:        case FLD:
                    610:                if( needs&(LSHARE|RSHARE) ) needs |= (LSHARE|RSHARE);
                    611:                break;
                    612: 
                    613:        case ASSIGN:
                    614:        case ASG PLUS:
                    615:        case ASG MINUS:
                    616:        case ASG MUL:
                    617:        case ASG DIV:
                    618:        case ASG MOD:
                    619:        case ASG AND:
                    620:        case ASG OR:
                    621:        case ASG ER:
                    622:        case ASG LS:
                    623:        case ASG RS:
                    624:                if( !(rewrite & (RNULL|RESC1|RESC2|RESC3|RRIGHT)) )
                    625:                {
                    626:                        rewrite |= RLEFT;
                    627:                }
                    628:        }
                    629:        if( !rewrite ) rewrite = RNULL;
                    630: 
                    631:        if( !onebit( rewrite & (RNULL|RLEFT|RRIGHT|RESC1|RESC2|RESC3) ) )
                    632:        {
                    633:                yyerror( "multiple results -- illegal (%o)", rewrite );
                    634:        }
                    635:        if( ((rewrite&RLEFT)&&(needs&LSHARE)) ||
                    636:                        ((rewrite&RRIGHT)&&(needs&RSHARE)) )
                    637:        {
                    638:                if( asstring[0] != 'Y' )
                    639:                        yyerror( "don't share on result side of tree" );
                    640:        }
                    641:        if( needs && (needs&(LSHARE|RSHARE)) == needs )
                    642:        {
                    643:                yyerror( "don't share without allocating something" );
                    644:        }
                    645:        checkout(asstring);
                    646: 
                    647:        q = &optb[opno];
                    648:        if( opno >= NOPTB ) yyerror( "too many templates" );
                    649:        q->line = lineno;
                    650:        q->op = op;
                    651:        q->tyop = tyop;
                    652:        if( ophd[op]>=0 )
                    653:        {
                    654:                optb[optl[op]].nxop = opno;
                    655:                optl[op] = opno;
                    656:        }
                    657:        else
                    658:        {
                    659:                optl[op] = ophd[op] = opno;
                    660:        }
                    661:        q->nxop = -1;
                    662:        q->l = lshty;
                    663:        q->r = rshty;
                    664:        q->oneeds = needs;
                    665:        q->orew = rewrite;
                    666:        q->ocost = cost;
                    667:        q->string = asstring;
                    668:        q->olcount = lcount;
                    669:        q->orcount = rcount;
                    670:        /* now, take care of special cases */
                    671:        if( optype(op) == LTYPE ) {  /* leaf */
                    672:                int s;
                    673:                if( (s=q->r.sha) >= 0 && trivial(s) ) {
                    674:                        q->r.sha = -1;  /* clobber any right shape */
                    675:                }
                    676:        }
                    677:        else if( optype(op) == UTYPE ) {
                    678:                if( q->r.sha >=0 ) {
                    679:                        /* someday, look for things below op */
                    680:                        /* for now, we get the cost wrong so back up */
                    681:                }
                    682:        }
                    683:        ++opno;
                    684: }
                    685: 
                    686: trivial( s ) {
                    687:        /* is shape s a trivial match for op */
                    688:        if( shp[s].sop == MANY ) {
                    689:                if( shp[s].sright >= 0 ) {
                    690:                        return( 0 );  /* nontrivial */
                    691:                }
                    692:                s = shp[s].sleft;
                    693:        }
                    694:        if( shp[s].sop != op ) {
                    695:                return( 0 );
                    696:        }
                    697:        if( shp[s].ssh ) {
                    698:                return( 0 );
                    699:        }
                    700:        return( 1 );  /* ok to clobber */
                    701: }
                    702: 
                    703: checkout(string)
                    704: char *string;
                    705: {
                    706:        /* check out the string, looking at rewrite and needs */
                    707:        /* look for {U,I,C,A}{L,R,1,2,3} and \n */
                    708:        /* complain about:
                    709:        ***     1, 2, 3 used, not allocated
                    710:        ***     shared side after \n after temp used
                    711:        ***     AL or AR used, w. side effect possible, more than once 
                    712:        */
                    713: 
                    714:        /* flagl and flagr are 1 if L and R legal, 0 if not, -1 if
                    715:        /* they will be illegal after the next \n */
                    716: 
                    717:        register int flagl, flagr, prn, min, cond;
                    718:        register char *s;
                    719: 
                    720:        flagl = flagr = 1;
                    721:        cond = 0;
                    722: 
                    723:        for( s=string; *s; ++s )
                    724:        {
                    725:                switch( *s )
                    726:                {
                    727: 
                    728:                case '\\':
                    729:                        ++s;
                    730:                        if( *s == '\\' ) ++s;
                    731:                        else if( *s == 'n' )
                    732:                        {
                    733:                                if( flagl<0 ) flagl=0;
                    734:                                if( flagr<0 ) flagr=0;
                    735:                        }
                    736:                        break;
                    737: 
                    738:                case 'Z':
                    739:                        ++s;
                    740:                        if( *s=='(' )
                    741:                        {
                    742:                                while( *++s != ')' ) {;}
                    743:                        }
                    744:                        break;
                    745: 
                    746:                case 'Y':
                    747:                        /* this string is asserted to be good; don't check */
                    748:                        return;
                    749: 
                    750:                case 'R':
                    751:                case 'D':
                    752:                        /* conditional; a lot of stuff no longer is true */
                    753:                        cond = 1;
                    754:                        break;
                    755: 
                    756:                case 'A':
                    757:                case 'C':
                    758:                case 'U':
                    759:                case 'I':
                    760:                        ++s;
                    761:                        if( *s == '-' )
                    762:                        {
                    763:                                ++s;
                    764:                                min = 1;
                    765:                        }
                    766:                        else min = 0;
                    767:                        if( *s == '(' )
                    768:                        {
                    769:                                ++s;
                    770:                                prn = 1;
                    771:                        }
                    772:                        else prn = 0;
                    773:                        switch( *s )
                    774:                        {
                    775: 
                    776:                        case 'L':
                    777:                                if( !flagl && !cond )
                    778:                                {
                    779:                                        yyerror( "illegal L just at \"%s\"",
                    780:                                                        s );
                    781:                                }
                    782:                                /* look for side-effects here */
                    783:                                if( !min && seff(lshty.sha)) flagl = 0;
                    784:                                break;
                    785: 
                    786:                        case 'R':
                    787:                                if( !flagr && !cond )
                    788:                                {
                    789:                                        yyerror( "illegal R just at \"%s\"",
                    790:                                                        s );
                    791:                                }
                    792:                                /* look for side-effects here */
                    793:                                if( !min && seff(rshty.sha)) flagr = 0;
                    794:                                break;
                    795: 
                    796:                        case '1':
                    797:                        case '2':
                    798:                        case '3':
                    799:                                if( (*s - '0') > (needs&NCOUNT) )
                    800:                                {
                    801:                                        yyerror( "reg %c used, not allocated",
                    802:                                                *s );
                    803:                                }
                    804:                                if( (needs&LSHARE) && flagl ) flagl = -1;
                    805:                                if( (needs&RSHARE) && flagr ) flagr = -1;
                    806: 
                    807:                        case '.':
                    808:                                break;
                    809: 
                    810:                        default:
                    811:                                yyerror( "illegal qualifier just at \"%s\"",
                    812:                                        s );
                    813:                        }
                    814:                        if( prn ) while( *s != ')' ) ++s;
                    815:                }
                    816:        }
                    817: }
                    818: 
                    819: seff( s )
                    820: register s;
                    821: {
                    822:        if( shp[s].sop == INCR || shp[s].sop == DECR ) return( 1 );
                    823:        if( shp[s].sleft >= 0 && seff( shp[s].sleft ) ) return( 1 );
                    824:        if( shp[s].sright >= 0 && seff( shp[s].sright ) ) return( 1 );
                    825:        return( 0 );
                    826: }
                    827: 
                    828: uop( o, a )
                    829: register o,a;
                    830: {
                    831:        if( o == MUL ) o = STAR;
                    832:        else if( o == MINUS ) o = UNARY MINUS;
                    833:        else if( o == AND ) o = UNARY AND;
                    834:        return( bop( o, a, -1, 0 ) );
                    835: }
                    836: 
                    837: top( a, ty )
                    838: register a,ty;
                    839: {
                    840:        /* build a type node over a */
                    841:        /* must be done differently than uop, since types must be copied */
                    842:        register STYSHP *p;
                    843: 
                    844:        if( a < 0 )
                    845:                return( a );
                    846:        checkit( a );
                    847:        if( shp[a].sop == MANY )
                    848:        {
                    849:                register l, r;
                    850:                l = shp[a].sleft;
                    851:                r = shp[a].sright;
                    852:                if( l >= 0 )
                    853:                        l = top( l, ty );
                    854:                if( r >= 0 )
                    855:                        r = top( r, ty );
                    856:                return( bop( MANY, l, r, 0 ) );
                    857:        }
                    858:        if( shp[a].ssh )
                    859:        {
                    860:                yyerror( "can't type a special node" );
                    861:        }
                    862:        shp[nshp] = shp[a];
                    863:        shp[nshp].shname[0] = '\0';
                    864:        shp[nshp].ssh = ty|SPTYPE;
                    865:        shp[nshp].scset = 0;
                    866:        nshp++;
                    867:        checkit( nshp-1 );
                    868:        return( nshp-1 );
                    869: }
                    870: 
                    871: bop( o, a, b, cst )
                    872: register o, a, b, cst;
                    873: {
                    874:        register STYSHP *p;
                    875:        register int    l, r, ret;
                    876: 
                    877:        checkit( a );
                    878:        checkit( b );
                    879: 
                    880:        if( o != MANY )
                    881:        {
                    882:                while( shp[a].sop == MANY && shp[a].sright < 0 ) {
                    883:                        a = shp[a].sleft;
                    884:                }
                    885:                while( b >= 0 && shp[b].sop == MANY && shp[b].sright < 0 ) {
                    886:                        b = shp[b].sleft;
                    887:                }
                    888:                if( a>=0  &&  shp[a].sop == MANY )
                    889:                {
                    890:                        /* distribute MANY nodes to top */
                    891:                        l = bop( o, shp[a].sleft, b, cst + shp[a].scost );
                    892:                        r = bop( o, shp[a].sright, b, cst + shp[a].scost );
                    893:                        return( bop( MANY, l, r, 0 ) );
                    894:                }
                    895:                if( b>=0 && shp[b].sop == MANY )
                    896:                {
                    897:                        /* distribute MANY nodes to top */
                    898:                        l = bop( o, a, shp[b].sleft, cst + shp[b].scost );
                    899:                        r = bop( o, a, shp[b].sright, cst + shp[b].scost );
                    900:                        return( bop( MANY, l, r, 0 ) );
                    901:                }
                    902:        }
                    903: 
                    904:        if( o == MANY )
                    905:                /* MANY nodes go at the end */
                    906:                p = &shp[ ret = nmshp-- ];
                    907:        else
                    908:                p = &shp[ ret = nshp++ ];
                    909:        if( nshp >= nmshp ) {
                    910:                yyerror( "out of node space" );
                    911:                exit( 1 );
                    912:        }
                    913: 
                    914:        p->sop = o;
                    915:        p->sleft = a;
                    916:        p->sright =b;
                    917:        p->scost = cst;
                    918:        p->scset = 0;
                    919:        p->ssh = 0;
                    920:        p->shname[0] = '\0';
                    921:        checkit( ret );
                    922:        return( ret );
                    923: }
                    924: 
                    925: int olist[] = { PLUS, MINUS, MUL, DIV, MOD, LS, RS, OR, ER, AND, -1 };
                    926: 
                    927: struct nam
                    928: {
                    929:        char    *tntn;
                    930:        int     tnty;
                    931: };
                    932: #define NameV(x)       "x",    x       /* name-value pairs */
                    933: struct nam Tnam[] = {
                    934:        NameV(TANY),
                    935:        NameV(TCHAR),
                    936:        NameV(TSHORT),
                    937:        NameV(TINT),
                    938:        NameV(TLONG),
                    939:        NameV(TFLOAT),
                    940:        NameV(TDOUBLE),
                    941:        NameV(TUCHAR),
                    942:        NameV(TUSHORT),
                    943:        NameV(TUNSIGNED),
                    944:        NameV(TULONG),
                    945:        NameV(TSTRUCT),
                    946:        NameV(TPOINT),
                    947:        NameV(TPOINT2),
                    948:        NameV(TVOID),
                    949:        NameV(urTINT),
                    950:        NameV(urTUNSIGNED),
                    951:        0,              0,
                    952: };
                    953: struct nam Rwnam[] = {
                    954:        NameV(RLEFT),
                    955:        NameV(RRIGHT),
                    956:        NameV(RESC1),
                    957:        NameV(RESC2),
                    958:        NameV(RESC3),
                    959:        NameV(RESCC),
                    960:        NameV(RNOP),
                    961:        NameV(RNULL),
                    962:        0,      0
                    963: };
                    964: struct nam Ndnam[] = {
                    965:        NameV(LSHARE),
                    966:        NameV(RSHARE),
                    967:        NameV(NPAIR),
                    968:        NameV(LPREF),
                    969:        NameV(RPREF),
                    970:        0,      0,
                    971: };
                    972: finished()
                    973: {
                    974:        register STYSHP *p;
                    975:        register OPTB   *q, *q1;
                    976:        register int    i, j;
                    977: 
                    978:        /* terminate the templates */
                    979:        printf( "# include \"mfile2.h\"\n\n" );
                    980: 
                    981:        /* chain binary ops together with the op= form */
                    982:        for( i=0; (op=olist[i])>=0; ++i )
                    983:        {
                    984:                if( ophd[op]<0 )
                    985:                        ophd[op] = ophd[ASG op];
                    986:                else
                    987:                        optb[optl[op]].nxop = ophd[ASG op];
                    988:        }
                    989:        if( ophd[STCALL]<0 )
                    990:                ophd[STCALL] = ophd[CALL];
                    991:        if( ophd[UNARY STCALL]<0 )
                    992:                ophd[UNARY STCALL] = ophd[UNARY CALL];
                    993: 
                    994:        optbck();
                    995: 
                    996:        /* everything that gets used should be a MANY shape with name */
                    997:        /* mkshp is called to cause this to be true */
                    998: 
                    999:        for( i=0; i<opno; ++i )
                   1000:        {
                   1001:                q = &optb[i];
                   1002:                q->l.sha = mkshp(q->l.sha);
                   1003:                q->r.sha = mkshp(q->r.sha);
                   1004:        }
                   1005: 
                   1006:        /* avoid identical strings in optb[] by finding identical strings,
                   1007:        giving them names and putting them at the front of table.c */
                   1008:        for( i=0; i<opno; ++i )
                   1009:        {
                   1010:                q = &optb[i];
                   1011:                q->struse = 1;
                   1012:                q->strdef = -1;
                   1013:                for(j = 0; j < i; j++)
                   1014:                {
                   1015:                        q1 = &optb[j];
                   1016:                        if(!q1->struse)
                   1017:                                continue;
                   1018:                        if(strcmp(q->string,q1->string)==0)
                   1019:                        {
                   1020:                                q->strdef = j;
                   1021:                                q1->struse++;
                   1022:                                q->struse = 0;
                   1023:                                break;
                   1024:                        }
                   1025:                }
                   1026:        }
                   1027:        for(i=0; i<opno; i++)
                   1028:        {
                   1029:                q = &optb[i];
                   1030:                if(q->struse>1)
                   1031:                {
                   1032:                        printf("static char Str%d[] = \"%s\";\n", i, q->string);
                   1033:                        q->struse = 0;
                   1034:                        q->strdef = i;
                   1035:                }
                   1036:        }
                   1037: 
                   1038:        /* set the ssh flags in shp, but don't print yet */
                   1039: 
                   1040:        for( j=0,i=NSTYSHPS-1; i>nmshp; --i ) {
                   1041:                if( !shp[i].shname[0] ) continue;
                   1042:                shp[i].ssh = j;
                   1043:                j += manycount( i );
                   1044:                ++j;  /* count the null */
                   1045:        }
                   1046: 
                   1047:        printf( "\n# define SHNL ((SHAPE *)0)\n" );
                   1048:        printf( "# define S(x) (&shapes[x])\n" );
                   1049: 
                   1050:        printf( "\nSHAPE shapes[] = {\n" );
                   1051:        for( i=0, p=shp; i<nshp; ++i,++p )
                   1052:        {
                   1053:                if( p->sop<0 )
                   1054:                        yyerror( "undefined shape: %.8s", p->shname );
                   1055:                printf( "/*%4d */ ", i);
                   1056:                printf( "%4d,\t",p->sop );
                   1057:                saaddr(p->sleft);
                   1058:                saaddr(p->sright);
                   1059:                printf( "%#o,\t%d,", p->ssh, p->scost );
                   1060:                if( p->shname[0] )
                   1061:                        printf( "\t/* %.8s */\n", p->shname );
                   1062:                else
                   1063:                        putchar( '\n' );
                   1064:                if(p->shname[0])
                   1065:                        chkdups(i);
                   1066:        }
                   1067:        printf( "\n};\n" );
                   1068: 
                   1069:        printf( "\n# define PSHNL ((SHAPE **)0)\n" );
                   1070:        printf( "# define P(x) (&pshape[x])\n" );
                   1071: 
                   1072:        printf( "\nSHAPE *pshape[] = {\n" );
                   1073:        for( j = 0, i = NSTYSHPS-1;  i > nmshp; --i ) {
                   1074:                if( !shp[i].shname[0] )
                   1075:                        continue;
                   1076:                if( shp[i].ssh != j ) {
                   1077:                        fprintf( stderr, "shape %d, ssh=%d, j=%d\n",
                   1078:                                i, shp[i].ssh, j );
                   1079:                }
                   1080:                printf( "/*%4d %.8s */\t", j, shp[i].shname  );
                   1081:                j = manylist( i, j );
                   1082:                printf( "SHNL,\n");
                   1083:                ++j;
                   1084:        }
                   1085:        printf( "};\n" );
                   1086: 
                   1087:        printf( "struct optab table[] = {\n\n" );
                   1088:        for( i=0; i<opno; ++i )
                   1089:        {
                   1090:                q = &optb[i];
                   1091:                printf( "/* # %d, line %d */\n", i, q->line );
                   1092:                prop( q->op );
                   1093:                prnam( q->tyop, Tnam );
                   1094:                if( q->nxop >= 0 )
                   1095:                        printf( "\t&table[%d],\n", q->nxop );
                   1096:                else
                   1097:                        printf( "\t0,\n" );
                   1098: 
                   1099:                shpprint(q->l.sha, q->l.ty);
                   1100:                shpprint(q->r.sha, q->r.ty);
                   1101:                printf("\t\t");
                   1102:                prnam(q->oneeds, Ndnam);
                   1103:                printf("\t\t");
                   1104:                prnam(q->orew, Rwnam);
                   1105:                if(q->strdef>=0)
                   1106:                        printf("\t\tStr%d,\n", q->strdef);
                   1107:                else
                   1108:                        printf("\t\t\"%s\",\n", q->string);
                   1109:                printf("\t\t%d,%d,%d,%d,\n", q->ocost, q->olcount, q->orcount,
                   1110:                        q->line );
                   1111:        }
                   1112:        printf( "\n};\n" );
                   1113: 
                   1114:        printf( "OPTAB *ophead[] = {\n" );
                   1115: 
                   1116:        for( i=0; i<DSIZE; ++i )
                   1117:        {
                   1118:                if( ophd[i] < 0 ) printf( "     0,\n" );
                   1119:                else printf( "  &table[%d],\n", ophd[i] );
                   1120:        }
                   1121:        printf( "};\n" );
                   1122: }
                   1123: 
                   1124: manycount( i )
                   1125: {      /* count the descendents of shp[i] */
                   1126:        int c;
                   1127: 
                   1128:        if( shp[i].sop == MANY ) {
                   1129:                c = 0;
                   1130:                if( shp[i].sleft >= 0 ) c += manycount( shp[i].sleft );
                   1131:                if( shp[i].sright >= 0 ) c += manycount( shp[i].sright );
                   1132:                return( c );
                   1133:        }
                   1134:        return( 1 );
                   1135: }
                   1136: 
                   1137: manylist( i, j ) {
                   1138:        /* put out a list of S(x) for shp[i], starting at j */
                   1139:        /* first, put out CCODES and FREE */
                   1140:        /* next, put out REG and TEMP */
                   1141:        /* next, everything else */
                   1142:        int k;
                   1143:        int outcount = 0;
                   1144: 
                   1145:        if( i<0 ) return(j);
                   1146: 
                   1147:        setopsh( i );  /* set opsh[k] if op k is legal at head of i */
                   1148:        if( opsh[FREE] ) {
                   1149:                j = manyop( i, j, FREE, &outcount );
                   1150:                opsh[FREE] = 0;
                   1151:                }
                   1152:        if( opsh[CCODES] ) {
                   1153:                j = manyop( i, j, CCODES, &outcount );
                   1154:                opsh[CCODES] = 0;
                   1155:                }
                   1156:        if( opsh[REG] ) {
                   1157:                j = manyop( i, j, REG, &outcount );
                   1158:                opsh[REG] = 0;
                   1159:                }
                   1160:        if( opsh[TEMP] ) {
                   1161:                j = manyop( i, j, TEMP, &outcount );
                   1162:                opsh[TEMP] = 0;
                   1163:                }
                   1164:        for( k=0; k<DSIZE; ++k ) {
                   1165:                if( opsh[k] ) {
                   1166:                        j = manyop( i, j, k, &outcount );
                   1167:                        opsh[k] = 0;
                   1168:                        }
                   1169:                }
                   1170:        return( j );
                   1171:        }
                   1172: 
                   1173: manyop( i, j, o, cp )
                   1174: int    *cp;
                   1175: {
                   1176:        /* put out a list of S(x) for shapes matching op */
                   1177: 
                   1178:        if( i<0 ) return( j );
                   1179:        if( shp[i].sop == MANY ) {
                   1180:                j = manyop( shp[i].sleft, j, o, cp );
                   1181:                return( manyop( shp[i].sright, j, o, cp ) );
                   1182:                }
                   1183:        if( shp[i].sop == o ) {
                   1184:                printf( "S(%d), ", i );
                   1185:                if( !((++*cp)&07) ) printf( "\n\t\t" );
                   1186:                return( j+1 );
                   1187:                }
                   1188:        return( j );
                   1189:        }
                   1190: 
                   1191: setopsh( i ) {
                   1192:        /* set opsh[k] to 1 for every op appearing in shp[i] */
                   1193:        int s;
                   1194: 
                   1195:        if( i<0 ) return;
                   1196:        s = shp[i].sop;
                   1197: 
                   1198:        if( s == MANY ) {
                   1199:                setopsh( shp[i].sleft );
                   1200:                setopsh( shp[i].sright );
                   1201:                }
                   1202:        else opsh[s] = 1;
                   1203:        }
                   1204: 
                   1205: saaddr(sp)
                   1206: register sp;
                   1207: {
                   1208:        if( sp < 0 ) printf( "SHNL,\t" );
                   1209:        else printf( "S(%d),\t", sp );
                   1210: }
                   1211: 
                   1212: 
                   1213: int nodcnt;
                   1214: int treecnt;
                   1215: chkdups(ii)
                   1216: register ii;
                   1217: {
                   1218:        treecnt = nodcnt = 0;
                   1219:        chkdup1(ii);
                   1220:        if(treecnt!=nodcnt)
                   1221:        {
                   1222:                fprintf(stderr,"DUPLICATE SHAPES IN TREE %s\n",shp[ii].shname);
                   1223:                prtree("T",ii);
                   1224:        }
                   1225:        clrcnt(ii);
                   1226: }
                   1227: chkdup1(nn)
                   1228: register nn;
                   1229: {
                   1230:        register STYSHP *p;
                   1231: 
                   1232:        p = &shp[nn];
                   1233:        if((p->sleft >= 0) && (p->sop==MANY)) chkdup1(p->sleft);
                   1234:        if((p->sright >= 0) && (p->sop==MANY)) chkdup1(p->sright);
                   1235:        p->scnt++;
                   1236:        nodcnt++;
                   1237:        treecnt += p->scnt;
                   1238: }
                   1239: clrcnt(nn)
                   1240: register nn;
                   1241: {
                   1242:        register STYSHP *p;
                   1243: 
                   1244:        p = &shp[nn];
                   1245:        if(p->sleft >= 0) clrcnt(p->sleft);
                   1246:        if(p->sright >= 0) clrcnt(p->sright);
                   1247:        p->scnt = 0;
                   1248: }
                   1249: 
                   1250: prtree(str,ii)
                   1251: register ii;
                   1252: char *str;
                   1253: {
                   1254:        register STYSHP *p;
                   1255:        p = &shp[ii];
                   1256:        fprintf(stderr,"%s.%d   =       %d",str,ii,p->scnt);
                   1257:        if(p->shname[0]) fprintf(stderr,"       /* %s */",p->shname);
                   1258:        fprintf(stderr,"\n");
                   1259:        if(p->sright>=0) prtree("R",p->sright);
                   1260:        if(p->sleft>=0) prtree("L",p->sleft);
                   1261: }
                   1262: shpprint(sha, ty)
                   1263: register sha,ty;
                   1264: {
                   1265:        if( sha < 0 ) printf( "\tPSHNL,\t");
                   1266:        else printf( "\tP(%d),\t", shp[sha].ssh );
                   1267:        prnam( ty, Tnam );
                   1268: }
                   1269: 
                   1270: prnam(ty,src)
                   1271: register struct nam *src;
                   1272: register ty;
                   1273: {
                   1274:        register int ii,jj;
                   1275:        register flag = 0;
                   1276:        register struct nam *tn;
                   1277: 
                   1278:        if(!ty)
                   1279:        {
                   1280:                printf("0x0,\n");
                   1281:                return;
                   1282:        }
                   1283:        for(tn = src; tn->tntn; tn++)
                   1284:                if( tn->tnty == ty )
                   1285:                {
                   1286:                        printf( "%s,\n", tn->tntn );
                   1287:                        return;
                   1288:                }
                   1289:        for(ii = 0; ; ii++)
                   1290:        {
                   1291:                if((jj = (01<<ii))>ty)
                   1292:                {
                   1293:                        printf(",\n");
                   1294:                        return;
                   1295:                }
                   1296:                if(!(jj & ty))
                   1297:                        continue;
                   1298:                for(tn = src; tn->tntn; tn++)
                   1299:                        if(tn->tnty==jj)
                   1300:                                break;
                   1301:                if(flag++)
                   1302:                        printf("|");
                   1303:                if(tn->tntn)
                   1304:                        printf("%s",tn->tntn);
                   1305:                else
                   1306:                        printf("%#o",jj);
                   1307:        }
                   1308: }
                   1309: 
                   1310: static char    name[100];  /* had better be long enough */
                   1311: 
                   1312: yylex()
                   1313: {
                   1314:        register int c, i;
                   1315: 
                   1316:        for(;;)
                   1317:        {
                   1318: 
                   1319:                c = getchar();
                   1320:                if( c<0 ) return( -1 );
                   1321:                switch( c )
                   1322:                {
                   1323: 
                   1324:                case '\n':
                   1325:                        ++lineno;
                   1326:                case ' ':
                   1327:                case '\b':
                   1328:                case '\f':
                   1329:                case '\v':
                   1330:                case '\t':
                   1331:                        continue;
                   1332: 
                   1333:                case '<':
                   1334:                case '>':
                   1335:                case '+':
                   1336:                case '-':
                   1337:                case '=':
                   1338:                case '*':
                   1339:                case '%':
                   1340:                case '/':
                   1341:                case '&':
                   1342:                case '|':
                   1343:                case '^':
                   1344:                case '!':
                   1345:                        name[0] = c;
                   1346:                        name[1] = getchar();
                   1347:                        name[2] = '\0';
                   1348:                        if( oplook() )
                   1349:                        {
                   1350:                                if( yylval.ival == LS || yylval.ival == RS )
                   1351:                                {
                   1352:                                        if( (c=getchar()) == '=' )
                   1353:                                                yylval.ival = ASG yylval.ival;
                   1354:                                        else ungetc( c, stdin );
                   1355:                                }
                   1356:                                return( OP );
                   1357:                        }
                   1358:                        ungetc( name[1], stdin );
                   1359:                        name[1] = '\0';
                   1360:                        if( oplook() ) return( OP );
                   1361:                        yyerror( "cannot deal with %c", name[0] );
                   1362:                        return( OP );
                   1363: 
                   1364:                case '~':
                   1365:                        yylval.ival = COMPL;
                   1366:                        return( OP );
                   1367: 
                   1368:                case '"':
                   1369:                        string = pstring;
                   1370:                        while( pstring < &strng[NSTRING-2] )
                   1371:                        {
                   1372:                                switch( c = getchar() ) {
                   1373:                                case '\t':
                   1374:                                        *pstring++ = '\\';
                   1375:                                        *pstring++ = 't';
                   1376:                                        break;
                   1377:                                case '\n':
                   1378:                                        *pstring++ = '\\';
                   1379:                                        *pstring++ = 'n';
                   1380:                                        ++lineno;
                   1381:                                        break;
                   1382:                                case '\\':      /* escape */
                   1383:                                        *pstring++ = '\\';
                   1384:                                        c = getchar();
                   1385:                                        if( c == '\n' )
                   1386:                                                ++lineno;
                   1387:                                        else if( c<0 )
                   1388:                                                yyerror( "missing \"" );
                   1389:                                        else if( isalpha(c) && isupper(c) )
                   1390:                                                *pstring++ = '\\';
                   1391:                                        *pstring++ = c;
                   1392:                                        break;
                   1393:                                case '"':
                   1394:                                        *pstring++ = '\0';
                   1395:                                        goto eos;
                   1396:                                default:
                   1397:                                        if( c<0 )
                   1398:                                                yyerror( "missing \"" );
                   1399:                                        *pstring++ = c;
                   1400:                                }
                   1401:                        }
                   1402:                   eos:
                   1403:                        if( pstring >= &strng[NSTRING] )
                   1404:                                yyerror( "s_table overflow" );
                   1405:                        yylval.str = string;
                   1406:                        return( STR );
                   1407: 
                   1408:                case '\'':
                   1409:                        for( i = 0;  i < sizeof name - 1;  ++i )
                   1410:                        {
                   1411:                                c = getchar();
                   1412:                                if( c == '\'' ) break;
                   1413:                                if( c == '\n' ) yyerror( "missing '" );
                   1414:                                name[i] = c;
                   1415:                        }
                   1416:                        name[i] = '\0';
                   1417:                        if( oplook() ) return( OP );
                   1418:                        yyerror( "bad op name: '%s'", name );
                   1419: 
                   1420:                case '[':
                   1421:                        for( i = 0;  i < sizeof name - 1;  ++i )
                   1422:                        {
                   1423:                                c = getchar();
                   1424:                                if( c == ']' ) break;
                   1425:                                if( c == '\n' ) yyerror( "missing ]" );
                   1426:                                name[i] = c;
                   1427:                        }
                   1428:                        name[i] = '\0';
                   1429:                        yylval.ival = tystr(name);
                   1430:                        return( STYPE );
                   1431: 
                   1432:                case '#':  /* comment */
                   1433:                        while( (c = getchar()) != '\n' )
                   1434:                        {
                   1435:                                if( c < 0 ) yyerror( "unexpected EOF" );
                   1436:                        }
                   1437:                        ++lineno;
                   1438:                        continue;
                   1439: 
                   1440:                case '$':
                   1441:                        c = getchar();
                   1442:                        if( isdigit(c) )
                   1443:                        {
                   1444:                                yylval.ival = c-'0';
                   1445:                                return( RREG );
                   1446:                        }
                   1447:                        switch( c )
                   1448:                        {
                   1449:                        case '[':       return( LPRF );
                   1450:                        case ']':       return( RPRF );
                   1451:                        case '<':       return( LSHR );
                   1452:                        case '>':       return( RSHR );
                   1453:                        case 'L':       return( LRES );
                   1454:                        case 'R':       return( RRES );
                   1455:                        case 'P':       return( PNEED );
                   1456:                        case 'C':       return( GOODCC );
                   1457:                        case 'N':       return( NOVAL );
                   1458:                        case 'r':       return( RCOUNT );
                   1459:                        case 'l':       return( LCOUNT );
                   1460:                        case 'A':       yylval.ival = NRGS;
                   1461:                                        return( DIG );
                   1462:                        }
                   1463:                        yyerror( "$%c illegal", c );
                   1464: 
                   1465:                default:
                   1466:                        if( isdigit(c) )
                   1467:                        {
                   1468:                                yylval.ival = c-'0';
                   1469:                                return( DIG );
                   1470:                        }
                   1471:                        if( isalpha(c) )
                   1472:                        {
                   1473:                                /* collect the name */
                   1474:                                int i = 1;
                   1475:                                name[0] = c;
                   1476:                                while( isalpha( (c=getchar()) ) || isdigit(c) )
                   1477:                                {
                   1478:                                        name[i++] = c;
                   1479:                                }
                   1480:                                name[i] = '\0';
                   1481:                                ungetc( c, stdin );
                   1482:                                return( lookup() );
                   1483:                        }
                   1484:                        return( c );
                   1485:                }
                   1486:        }
                   1487: }
                   1488: 
                   1489: struct nlist {
                   1490:        char *shop;
                   1491:        int vop;
                   1492: } ot[] = {
                   1493: 
                   1494:        "++",   INCR,
                   1495:        "+",    PLUS,
                   1496:        "--",   DECR,
                   1497:        "-",    MINUS,
                   1498:        "*",    MUL,
                   1499:        "%",    MOD,
                   1500:        "/",    DIV,
                   1501:        "&",    AND,
                   1502:        "^",    ER,
                   1503:        "!=",   NE,
                   1504:        "==",   EQ,
                   1505:        "UMINUS",       UNARY MINUS,
                   1506:        "UAND", UNARY AND,
                   1507:        "STAR", STAR,
                   1508:        "+=",   ASG PLUS,
                   1509:        "-=",   ASG MINUS,
                   1510:        "*=",   ASG MUL,
                   1511:        "/=",   ASG DIV,
                   1512:        "%=",   ASG MOD,
                   1513:        "&=",   ASG AND,
                   1514:        "|=",   ASG OR,
                   1515:        "|",    OR,
                   1516:        "^=",   ASG ER,
                   1517:        "=",    ASSIGN,
                   1518:        "<",    LT,
                   1519:        "<=",   LE,
                   1520:        "<<",   LS,
                   1521:        ">",    GT,
                   1522:        ">=",   GE,
                   1523:        ">>",   RS,
                   1524:        "FLD",  FLD,
                   1525:        "CMP",  CMP,
                   1526:        "COMOP",        COMOP,
                   1527:        "CM",           CM,
                   1528:        "GENLAB",       GENLAB,
                   1529:        "GENUBR",       GENUBR,
                   1530:        "GENBR",        GENBR,
                   1531:        "ARG",          FUNARG,
                   1532:        "STARG",        STARG,
                   1533:        "STASG",        STASG,
                   1534:        "INIT",         INIT,
                   1535:        "GOTO",         GOTO,
                   1536:        "CALL",         CALL,
                   1537:        "UCALL",        UNARY CALL,
                   1538:        "STCALL",       STCALL,
                   1539:        "USTCALL",      UNARY STCALL,
                   1540:        "CONV",         CONV,
                   1541:        "PDIV",         PDIV,
                   1542:        "PMUL",         PMUL,
                   1543:        "REG",  REG,
                   1544:        "CON",  ICON,
                   1545:        "TEMP", TEMP,
                   1546:        "AUTO", VAUTO,
                   1547:        "PARAM",        VPARAM,
                   1548:        "NAME", NAME,
                   1549:        "RNODE",        RNODE,
                   1550:        "SNODE",        SNODE,
                   1551:        "QNODE",        QNODE,
                   1552:        "CC",   CCODES,
                   1553:        "FREE", FREE,
                   1554:        "UOP0", UOP0,
                   1555:        "UOP1", UOP1,
                   1556:        "UOP2", UOP2,
                   1557:        "UOP3", UOP3,
                   1558:        "UOP4", UOP4,
                   1559:        "UOP5", UOP5,
                   1560:        "UOP6", UOP6,
                   1561:        "UOP7", UOP7,
                   1562:        "UOP8", UOP8,
                   1563:        "UOP9", UOP9,
                   1564:        "",     -1 };
                   1565: 
                   1566: oplook()
                   1567: {
                   1568:        /* look up the first n chars of name in the above table */
                   1569:        /* return 1 if it is an op, after setting yylval */
                   1570:        register int i;
                   1571:        for( i=0; ot[i].vop >= 0; ++i )
                   1572:        {
                   1573:                if( !strcmp( name, ot[i].shop ) )
                   1574:                {
                   1575:                        yylval.ival = ot[i].vop;
                   1576:                        return( 1 );
                   1577:                }
                   1578:        }
                   1579:        return( 0 );
                   1580: }
                   1581: 
                   1582: tystr( p )
                   1583: register char *p;      /* pointer to name */
                   1584: {
                   1585:        register i;
                   1586: 
                   1587:        /* lookup the types in name */
                   1588:        if( !*p )
                   1589:                return( TANY );
                   1590:        else
                   1591:                i = 0;
                   1592:        for(;;)
                   1593:        {
                   1594:                switch( *p++ )
                   1595:                {
                   1596:                case '\0':
                   1597:                        return( i );
                   1598: 
                   1599:                case 'c':
                   1600:                        i |= TCHAR;
                   1601:                case ' ':
                   1602:                case ',':
                   1603:                        continue;
                   1604: 
                   1605:                case 's':
                   1606:                        i |= TSHORT;
                   1607:                        continue;
                   1608: 
                   1609:                case 'i':
                   1610:                        i |= TINT;
                   1611:                        continue;
                   1612: 
                   1613:                case 'l':
                   1614:                        i |= TLONG;
                   1615:                        continue;
                   1616: 
                   1617:                case 'f':
                   1618:                        i |= TFLOAT;
                   1619:                        continue;
                   1620: 
                   1621:                case 'd':
                   1622:                        i |= TDOUBLE;
                   1623:                        continue;
                   1624: 
                   1625:                case 'P':
                   1626:                        i |= TPOINT2;
                   1627:                        continue;
                   1628: 
                   1629:                case 'p':
                   1630:                        i |= TPOINT;
                   1631:                        continue;
                   1632: 
                   1633:                case 't':
                   1634:                        i |= TSTRUCT;
                   1635:                        continue;
                   1636: 
                   1637:                case 'v':
                   1638:                        /* later..
                   1639:                        i |= TVOID;
                   1640:                        */
                   1641:                        continue;
                   1642: 
                   1643:                case 'u':
                   1644:                        switch( *p )
                   1645:                        {
                   1646:                        case 'i':       i |= TUNSIGNED;  break;
                   1647:                        case 's':       i |= TUSHORT;  break;
                   1648:                        case 'c':       i |= TUCHAR;  break;
                   1649:                        case 'l':       i |= TULONG;  break;
                   1650:                        default:        yyerror( "bad u%c type", *p );
                   1651:                        }
                   1652:                        ++p;
                   1653:                        continue;
                   1654: 
                   1655:                default:
                   1656:                        yyerror( "illegal type: %c", p[-1] );
                   1657:                }
                   1658:        }
                   1659: }
                   1660: 
                   1661: struct nlist resw[] = {
                   1662:        NameV(DCOST),
                   1663:        NameV(SHAPES),
                   1664:        NameV(OPCODES),
                   1665:        NameV(USERCOST),
                   1666:        NameV(CONVAL),
                   1667:        NameV(NCONVAL),
                   1668:        NameV(POSRANGE),
                   1669:        NameV(SGRANGE),
                   1670:        NameV(NONAME),
                   1671:        "",     -1,
                   1672: };
                   1673: 
                   1674: lookup()
                   1675: {
                   1676:        /* look up the shape name in name, and return the index */
                   1677:        register STYSHP *p;
                   1678:        register int i;
                   1679:        for( i=0; resw[i].vop >= 0; ++i )
                   1680:        {
                   1681:                if( !strcmp( name, resw[i].shop ) ) return( resw[i].vop );
                   1682:        }
                   1683:        for( i=NSTYSHPS-1, p= &shp[NSTYSHPS-1]; i>nmshp; --i,--p )
                   1684:        {
                   1685:                if( !strncmp( name, p->shname, 8 ) )
                   1686:                {
                   1687:                         /* match */
                   1688:                        yylval.ival = i;
                   1689:                        return( NM );
                   1690:                }
                   1691:        }
                   1692:        /* new entry */
                   1693:        strncpy( p->shname, name, 8 );
                   1694:        p->scset = p->ssh = p->scost = 0;
                   1695:        p->sleft = p->sright = -1;
                   1696:        p->sop = -1;
                   1697:        yylval.ival = nmshp--;
                   1698:        if( nmshp <= nshp ) {
                   1699:                yyerror( "out of node space" );
                   1700:                exit( 1 );
                   1701:        }
                   1702:        return( NM );
                   1703: }
                   1704: 
                   1705: setcost ( sn, cst )
                   1706: register int sn,cst;
                   1707: {
                   1708:        /* set costs for shape at all reference points.
                   1709:        /* reference points all are just below MANY ops
                   1710:        */
                   1711:        if ( sn < 0 )
                   1712:                return;
                   1713:        if ( shp[sn].sop == MANY )
                   1714:        {
                   1715:                setcost( shp[sn].sleft, cst );
                   1716:                setcost( shp[sn].sright, cst );
                   1717:        }
                   1718:        else if ( was_cost )
                   1719:        {
                   1720:                if ( shp[sn].scset )
                   1721:                {
                   1722:                        if ( shp[sn].scost == cst )
                   1723:                                return;
                   1724:                        yyerror( "Inconsistent cost values for shared shape" );
                   1725:                }
                   1726:                else
                   1727:                {
                   1728:                        shp[sn].scost = cst;
                   1729:                        shp[sn].scset = 1;
                   1730:                }
                   1731:        }
                   1732:        else
                   1733:        {
                   1734:                shp[sn].scset = 1;
                   1735:        }
                   1736: }
                   1737: 
                   1738: sharecost ( sn, cst )
                   1739: register int sn,cst;
                   1740: {
                   1741:        if ( sn == nshp - 1 )   /* quick opt. there is only one choice */
                   1742:        {
                   1743:                shp[sn].scost = cst;
                   1744:                shp[sn].scset = 1;
                   1745:                return(sn);
                   1746:        }
                   1747: /*     if ( cst == 0 )
                   1748: /*             return( sn );
                   1749: */
                   1750: 
                   1751:        setcost(sn, cst);
                   1752:        return (sn);
                   1753: /*     if (nshp >= NSTYSHPS)
                   1754: /*             yyerror("too many shapes");
                   1755: /*     shp[nshp] = shp[sn];
                   1756: /*     shp[nshp].scost += cst;
                   1757: /*     nshp++;
                   1758: /*     checkit( nshp-1 );
                   1759: /*     return( nshp-1 );
                   1760: */
                   1761: }
                   1762:        
                   1763: uopcost (o, a)
                   1764: register int o,a;
                   1765: {
                   1766:        switch(o)
                   1767:        {
                   1768:        default:
                   1769:        case MUL:
                   1770:        case AND:       yyerror("Illegal unary cost operator");
                   1771:                        return(0);
                   1772:        case MINUS:
                   1773:                return(-a);
                   1774:        }
                   1775: }
                   1776: 
                   1777: bopcost (o, a, b)
                   1778: register int o,a,b;
                   1779: {
                   1780:        switch(o)
                   1781:        {
                   1782:        case INCR:
                   1783:        case PLUS:      return(a+b);
                   1784:        case DECR:
                   1785:        case MINUS:     return(a-b);
                   1786:        case MUL:       return(a*b);
                   1787:        case DIV:       return(a/b);
                   1788:        case MOD:       return(a%b);
                   1789:        case LS:        return(a>>b);
                   1790:        case RS:        return(a<<b);
                   1791:        case OR:        return(a|b);
                   1792:        case ER:        return(a^b);
                   1793:        case AND:       return(a&b);
                   1794:        case LT:        return(a<b);
                   1795:        case GT:        return(a>b);
                   1796:        case LE:        return(a<=b);
                   1797:        case GE:        return(a>=b);
                   1798:        case NE:        return(a!=b);
                   1799:        case EQ:        return(a==b);
                   1800:        default:        yyerror("Illegal binary operator");
                   1801:                        return(0);
                   1802:        }
                   1803: }
                   1804: 
                   1805: /*     print operator name
                   1806: */
                   1807: static
                   1808: prop( op )
                   1809: register int   op;
                   1810: {
                   1811:        register struct nam     *np;
                   1812:        static struct nam       Opnam[] = {
                   1813:                NameV(INCR),
                   1814:                NameV(PLUS),
                   1815:                NameV(DECR),
                   1816:                NameV(MINUS),
                   1817:                NameV(MUL),
                   1818:                NameV(MOD),
                   1819:                NameV(DIV),
                   1820:                NameV(AND),
                   1821:                NameV(ER),
                   1822:                NameV(NE),
                   1823:                NameV(EQ),
                   1824:                NameV(UNARY MINUS),
                   1825:                NameV(UNARY AND),
                   1826:                NameV(STAR),
                   1827:                NameV(ASG PLUS),
                   1828:                NameV(ASG MINUS),
                   1829:                NameV(ASG MUL),
                   1830:                NameV(ASG DIV),
                   1831:                NameV(ASG MOD),
                   1832:                NameV(ASG AND),
                   1833:                NameV(ASG OR),
                   1834:                NameV(OR),
                   1835:                NameV(ASG ER),
                   1836:                NameV(ASSIGN),
                   1837:                NameV(LT),
                   1838:                NameV(LE),
                   1839:                NameV(LS),
                   1840:                NameV(GT),
                   1841:                NameV(GE),
                   1842:                NameV(RS),
                   1843:                NameV(FLD),
                   1844:                NameV(CMP),
                   1845:                NameV(COMOP),
                   1846:                NameV(CM),
                   1847:                NameV(GENLAB),
                   1848:                NameV(GENUBR),
                   1849:                NameV(GENBR),
                   1850:                NameV(FUNARG),
                   1851:                NameV(STARG),
                   1852:                NameV(STASG),
                   1853:                NameV(INIT),
                   1854:                NameV(GOTO),
                   1855:                NameV(CALL),
                   1856:                NameV(UNARY CALL),
                   1857:                NameV(STCALL),
                   1858:                NameV(UNARY STCALL),
                   1859:                NameV(CONV),
                   1860:                NameV(PDIV),
                   1861:                NameV(PMUL),
                   1862:                NameV(REG),
                   1863:                NameV(ICON),
                   1864:                NameV(TEMP),
                   1865:                NameV(VAUTO),
                   1866:                NameV(VPARAM),
                   1867:                NameV(NAME),
                   1868:                NameV(RNODE),
                   1869:                NameV(SNODE),
                   1870:                NameV(QNODE),
                   1871:                NameV(CCODES),
                   1872:                NameV(FREE),
                   1873:                0,      0,
                   1874:        };
                   1875:        for( np = Opnam;  np->tnty;  np++ )
                   1876:        {
                   1877:                if( op == np->tnty )
                   1878:                {
                   1879:                        printf( "%s,", np->tntn );
                   1880:                        return;
                   1881:                }
                   1882:        }
                   1883:        printf( "%d,", op );
                   1884: }
                   1885: 
                   1886: 
                   1887: /*
                   1888:        check the op table for duplicate or partially duplicate templates
                   1889: */
                   1890: static
                   1891: optbck()
                   1892: {
                   1893: #define        EqOptb(a)       (q->a == q1->a)
                   1894:        register int    i;
                   1895:        register int    j;
                   1896:        register OPTB   *q;
                   1897:        register OPTB   *q1;
                   1898: 
                   1899:        for( i = 0;  i < opno;  i++ )
                   1900:        {
                   1901:                q = &optb[i];
                   1902:                for( j = 0;  j < i;  j++ )
                   1903:                {
                   1904:                        q1 = &optb[j];
                   1905:                        if(
                   1906:                                EqOptb(op)  &&
                   1907:                                EqOptb(l.ty)  &&
                   1908:                                EqOptb(r.ty)  &&
                   1909:                                EqOptb(orew)  &&
                   1910:                                EqOptb(oneeds)  &&
                   1911:                                shapeshr(q->l.sha, q1->l.sha)  &&
                   1912:                                shapeshr(q->r.sha, q1->r.sha)
                   1913:                          )
                   1914:                        {
                   1915:                                fprintf( stderr,
                   1916:                                        "line %d may be covered by line %d\n",
                   1917:                                        q->line, q1->line );
                   1918:                                break;
                   1919:                        }
                   1920:                }
                   1921:        }
                   1922: }
                   1923: 
                   1924: 
                   1925: /*     do the shape trees starting at s1 and s2 share any elements?
                   1926: */
                   1927: static
                   1928: shapeshr( s1, s2 )
                   1929: register int   s1;     /* indexes into shape table */
                   1930: register int   s2;
                   1931: {
                   1932:        register int    i1;
                   1933: 
                   1934:        for( i1 = s1;  shp[i1].sleft >= 0;  i1 = shp[i1].sleft )
                   1935:        {
                   1936:                if( i1 == s2  ||  shp[i1].sright == s2 )
                   1937:                        return  1;
                   1938:        }
                   1939:        return  0;
                   1940: }

unix.superglobalmegacorp.com

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