Annotation of coherent/b/bin/as/asm.y, revision 1.1

1.1     ! root        1: %{
        !             2: #include <asm.h>
        !             3: /*
        !             4:  * count macro parms.
        !             5:  */
        !             6: static 
        !             7: parmCt()
        !             8: {
        !             9:        if(NULL == trueMac) {
        !            10:                yyerror(".parmct not in macro");
        !            11:                /* \fB.parmct\fR returns the number of
        !            12:                 * parameters in the current macro. */
        !            13:                return(0);
        !            14:        }
        !            15:        else
        !            16:                return(countList(trueMac->parms));
        !            17: }
        !            18: 
        !            19: /*
        !            20:  * Verify that 2 symbols have the same segment.
        !            21:  */
        !            22: static void
        !            23: ckseg(s1, s2)
        !            24: sym *s1, *s2;
        !            25: {
        !            26:        if(s1->sg != s2->sg)
        !            27:                yyerror("Arithmetic between addresses on different segments");
        !            28:                /* You may only add or subtract addresses if they
        !            29:                 * are in the same segment. */
        !            30: }
        !            31: 
        !            32: /*
        !            33:  * Create Immediate exps.
        !            34:  */
        !            35: static expr *
        !            36: setImm(val, symRef)
        !            37: long val;
        !            38: sym  *symRef;
        !            39: {
        !            40:        register expr *oper;
        !            41:        register short w;
        !            42: 
        !            43:        oper = xalloc();
        !            44:        oper->mode = T_IMM;
        !            45:        if (NULL != (oper->ref = symRef))
        !            46:                oper->ref = symRef->ref;
        !            47:        w = oper->exp = val;
        !            48:        if(w == val)
        !            49:                oper->size = 2;
        !            50:        else
        !            51:                oper->size = 4;
        !            52:        return(oper);
        !            53: }
        !            54: 
        !            55: /*
        !            56:  * Set up for most addressing modes.
        !            57:  */
        !            58: static expr *
        !            59: qbild(val, mode, r1, r2, scale, symRef)
        !            60: long val;
        !            61: int mode;
        !            62: psym *r1, *r2;
        !            63: long scale;
        !            64: sym *symRef;
        !            65: {
        !            66:        register expr *oper;
        !            67:        char i;
        !            68: 
        !            69:        if (NULL != r1 && T_R != mode) {
        !            70:                switch((int)r1->size) {
        !            71:                case 2:
        !            72:                        lflags |= A_SHORT;
        !            73:                        if (!scale)
        !            74:                                break;
        !            75:                case 1:
        !            76:                        regerror(r1);
        !            77:                        break;
        !            78:                case 4:
        !            79:                        lflags |= A_LONG;
        !            80:                        break;
        !            81:                }
        !            82: 
        !            83:                if (ORD_REG != r1->flag)        /* cant ind via ctl regs */
        !            84:                        regerror(r1);
        !            85: 
        !            86:                if (NULL != r2) {
        !            87:                        if (ORD_REG != r2->flag)
        !            88:                                regerror(r2);
        !            89:                        if (r1->size != r2->size)
        !            90:                                yyerror("Mixed length addressing registers");
        !            91:                /* Addressing registers must both be the same length. */
        !            92:                }
        !            93:        }
        !            94:        else if ((T_R == mode) && (r1->flag == ORD_REG)) {
        !            95:                switch ((int)r1->size) {
        !            96:                case 4:
        !            97:                        lflags |= O_LONG;
        !            98:                        break;
        !            99:                case 2:
        !           100:                        lflags |= O_SHORT;
        !           101:                }
        !           102:        }
        !           103: 
        !           104:        oper = xalloc();
        !           105:        oper->exp  = val;
        !           106:        oper->r1 = r1;
        !           107:        oper->r2 = r2;
        !           108:        oper->mode = mode;
        !           109: 
        !           110:        i = scale;
        !           111:        if (i != scale)
        !           112:                i = 3;  /* set a bad scale */
        !           113: 
        !           114:        switch (i) {
        !           115:        case 0:
        !           116:        case 1: /* for generated code */
        !           117:                oper->scale = 0; break;
        !           118:        case 2:
        !           119:                oper->scale = 1; break;
        !           120:        case 4:
        !           121:                oper->scale = 2; break;
        !           122:        case 8:
        !           123:                oper->scale = 3; break;
        !           124:        default:
        !           125:                yyerror("Bad scale");
        !           126:                /* Address scale must be 0, 1, 2, 4, or 8. */
        !           127:        }
        !           128: 
        !           129:        if (NULL != (oper->ref = symRef))
        !           130:                oper->ref = symRef->ref;
        !           131:        return(oper);
        !           132: }
        !           133: 
        !           134: /*
        !           135:  * Floating point register expr.
        !           136:  */
        !           137: static expr *
        !           138: fbild(regno)
        !           139: long regno;
        !           140: {
        !           141:        register expr *oper;
        !           142: 
        !           143:        if (regno < 0 || regno > 7) {
        !           144:                regno &= 7;
        !           145:                yyerror("Invalid floating point register number"); /**/
        !           146:        }
        !           147: 
        !           148:        oper = xalloc();
        !           149:        oper->exp = regno;
        !           150:        oper->mode = T_FP;
        !           151:        return (oper);
        !           152: }
        !           153:        
        !           154: /*
        !           155:  * Report register error.
        !           156:  */
        !           157: regerror(rg)
        !           158: psym *rg;
        !           159: {
        !           160:        yyerror("%s is an improper register in this context", rg->name); /**/
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * Concatinate strings.
        !           165:  */
        !           166: static char *
        !           167: concat(s1, s2)
        !           168: char *s1, *s2;
        !           169: {
        !           170:        long l;
        !           171:        unsigned short u;
        !           172:        char *res;
        !           173: 
        !           174:        u = l = (long)strlen(s1) + (long)strlen(s2) + 1;
        !           175:        if(u != l) {
        !           176:                yyerror("Length %ld string range exceeded", l);
        !           177:                /* Strings may not exceed 32 kilobytes. */
        !           178:                return(galloc(1));
        !           179:        }
        !           180:        res = galloc(u);
        !           181:        sprintf(res, "%s%s", s1, s2);
        !           182:        return(res);
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Substring.
        !           187:  * Assumes that all strings are created from unsigned lengths.
        !           188:  */
        !           189: static char *
        !           190: substr(s, from, len)
        !           191: char *s;
        !           192: long from, len;
        !           193: {
        !           194:        register char *p, *res;
        !           195:        unsigned short l;
        !           196: 
        !           197:        l = strlen(s);
        !           198:        s += from;
        !           199:        from = l - from;        /* from now len to end */
        !           200: 
        !           201:        if(len > from)
        !           202:                len = from;     /* since strlen fit unsigned len must */
        !           203:        if(len < 0)
        !           204:                len = 0;
        !           205: 
        !           206:        for(p = res = galloc((unsigned)(len + 1)); len--; )
        !           207:                *p++ = *s++;
        !           208:        return(res);
        !           209: }
        !           210: 
        !           211: /*
        !           212:  * String search.
        !           213:  */
        !           214: static
        !           215: stringSearch(s1, s2)
        !           216: char *s1, *s2;
        !           217: {
        !           218:        char *p;
        !           219: 
        !           220:        if(NULL == (p = strstr(s1, s2)))
        !           221:                return(-1);
        !           222:        return(p - s1);
        !           223: }
        !           224: 
        !           225: /*
        !           226:  * Do long comparisons.
        !           227:  * < > <= >= != ==  compare operator
        !           228:  * 1 2  5  6  3  4  t
        !           229:  */
        !           230: static
        !           231: compare(t, v)
        !           232: int t;
        !           233: long v;
        !           234: {
        !           235:        return(((v < 0) ? t : (v > 0) ? (t >> 1) : (t >> 2)) & 1);
        !           236: }
        !           237: 
        !           238: /*
        !           239:  * Do double comparisons.
        !           240:  * < > <= >= != ==  compare operator
        !           241:  * 1 2  5  6  3  4  t
        !           242:  */
        !           243: static
        !           244: fcompare(t, v)
        !           245: int t;
        !           246: double v;
        !           247: {
        !           248:        return(((v < 0.0) ? t : (v > 0.0) ? (t >> 1) : (t >> 2)) & 1);
        !           249: }
        !           250: 
        !           251: static void
        !           252: unmatched(c)
        !           253: {
        !           254:        yyerror("Unmatched '%c'", c);
        !           255:        /* A delimeter, [, (, ), or ] is unmatched in this command. */
        !           256: }
        !           257: 
        !           258: %}
        !           259: %union {
        !           260:        long    val;    /* numeric value */
        !           261:        double  dbl;
        !           262:        sym     *s;     /* name size loc bitd bitl flag */
        !           263:        opc     *o;     /* opcode kind */
        !           264:        expr    *e;     /* mode loc size exp bitd bitl chain next */
        !           265:        char    *t;     /* token */
        !           266:        parm    *p;     /* parm  */
        !           267:        data    *d;     /* data item */
        !           268:        }
        !           269: %token PC              /* The PC reg */
        !           270: %token <val> NUMBER    /* a number */
        !           271: %token <dbl> FNUM      /* floating point number */
        !           272: %token <val> COMPARISON        /* =  < > <= >= !=*/
        !           273: %token <o> OP          /* a 386 opcode */
        !           274: %token <o> DATA                /* dc.w etc */
        !           275: %token <o> CMD         /* an assembler command or macro call */
        !           276: %token <o> DCMD                /* a command with string parms */
        !           277: %token <o> ICMD                /* an assembler command taking a numexp parm */
        !           278: %token <o> NCMD                /* an assembler command without parms */
        !           279: %token <o> ECMD                /* an assembler command with a name and an expr */
        !           280: %token <o> ECMDX       /* an assembler command with a name and a datalist */
        !           281: %token <s> IDENTIFIER  /* a symbol */
        !           282: %token <s> REG         /* A register */
        !           283: 
        !           284: %token DEFINED         /* the word .defined */
        !           285: %token SIZEOF          /* the word .sizeof */
        !           286: %token SEGMENT         /* the word .segment */
        !           287: %token LOCATION                /* the word .location */
        !           288: %token PLUS            /* + */
        !           289: %token MINUS           /* - */
        !           290: %token TIMES           /* * */
        !           291: %token DIVIDE          /* / */
        !           292: %token REM             /* % */
        !           293: %token LSHIFT          /* << */
        !           294: %token RSHIFT          /* >> */
        !           295: %token AND             /* & */
        !           296: %token OR              /* | */
        !           297: %token XOR             /* ^ */
        !           298: %token COMMA           /* , */
        !           299: %token LPAREN          /* [ reversed with () */
        !           300: %token RPAREN          /* ] */
        !           301: %token LBRACK          /* ( */
        !           302: %token RBRACK          /* ) */
        !           303: %token AT              /* @ */
        !           304: %token D_SIGN          /* $ */
        !           305: %token NOT             /* ~ */
        !           306: %token BANG            /* ! */
        !           307: %token COLON           /* : */
        !           308: %token PARMCT          /* .parmct */
        !           309: %token TOSTRING                /* .string */
        !           310: %token TONUMBER                /* .number */
        !           311: %token TOFLOAT         /* .float */
        !           312: %token FSTACK          /* %st */
        !           313: %token NL              /* \n */
        !           314: 
        !           315: %token <t> TOKEN       /* a token in an assembler command or macro call */
        !           316: %type <p> label parm plist
        !           317: %type  <t> string
        !           318: 
        !           319: %right COMMA           /* low presidence to hi */
        !           320: %right COLON
        !           321: %right AT P_SIGN
        !           322: %left  OR
        !           323: %left  XOR
        !           324: %left  AND
        !           325: %left  COMPARISON
        !           326: %left  LSHIFT RSHIFT
        !           327: %left  PLUS MINUS
        !           328: %left  TIMES DIVIDE REM
        !           329: %right DEFINED SIZEOF SEGMENT LOCATION NOT LEN BANG
        !           330: %right TOKEN
        !           331: %left  LPAREN LBRACK TOSTRING TONUMBER TOFLOAT
        !           332: %right NL
        !           333: 
        !           334: %type <dbl> dblexp
        !           335: %type <val> numexp
        !           336: /* addressing modes */
        !           337: %type <e> operand oper escoper
        !           338: 
        !           339: %type <s> addexp
        !           340: 
        !           341: /* for dc.? */
        !           342: %type <d> item itemlist
        !           343: %%
        !           344: 
        !           345: /* oper types */
        !           346: /*
        !           347:  * label opcode operand comment NL
        !           348:  * label and comment eaten by lexer.
        !           349:  */ 
        !           350: file   : line | file line;
        !           351: 
        !           352: line   : label CMD plist NL { /* assembler command with parms */
        !           353:                docmd($1, $2, $3); }
        !           354:        | label DCMD plist NL { /* a command with string parms */
        !           355:                docmd($1, $2, $3); }
        !           356:        | label ECMD parm COMMA item NL { /* command with a name & an expr */
        !           357:                ecmd($1, $2, $3, $5); }
        !           358:         /* command with a name & a datalist */
        !           359:        | label ECMDX parm COMMA itemlist NL {
        !           360:                ecmd($1, $2, $3, $5); }
        !           361:        | label ECMD NL {
        !           362:                ecmd($1, $2, NULL, NULL); }
        !           363:        | label NCMD NL {       /* assembler command takes no parms */
        !           364:                docmd($1, $2, (parm *)NULL); }
        !           365:        | label ICMD item NL { /* assembler command with data parm */
        !           366:                ncmd($1, $2, $3); }
        !           367:        | label DATA itemlist NL { /* data list */
        !           368:                dcmd($1, $2, $3); }
        !           369:        | label OP operand NL { /* opcode operands */
        !           370:                buildind($1, $2, $3); }
        !           371:        | label OP OP NL {      /* built by rep instr */
        !           372:                buildind($1, $2, NULL);
        !           373:                buildind(NULL, $3, NULL ); }
        !           374:        | label NL {    /* label alone on line */
        !           375:                buildlab($1); }
        !           376:        | error NL {    /* syntax error */
        !           377:                if (bcnt > 0)
        !           378:                        unmatched('[');
        !           379:                if (bcnt < 0)
        !           380:                        unmatched(']');
        !           381:                if (pcnt > 0)
        !           382:                        unmatched('(');
        !           383:                if (pcnt < 0)
        !           384:                        unmatched(')');
        !           385:                yyerrok; };
        !           386: 
        !           387: itemlist : item COMMA itemlist {
        !           388:                $$ = $1;
        !           389:                $$->next = $3; }
        !           390:        | item {
        !           391:                $$ = $1; }
        !           392:        | {
        !           393:                $$ = NULL; };
        !           394: 
        !           395: item   : addexp {
        !           396:                $$ = gitem('y');
        !           397:                $$->d.y  = $1; }
        !           398:        | dblexp {
        !           399:                $$ = gitem('d');
        !           400:                $$->d.d = $1; }
        !           401:        | numexp {
        !           402:                $$ = gitem('l');
        !           403:                $$->d.l = $1; }
        !           404:        | string {
        !           405:                $$ = gitem('s');
        !           406:                $$->d.s = $1; }
        !           407:        | numexp P_SIGN item {
        !           408:                $$ = $3;
        !           409:                $$->count = $1; };
        !           410: 
        !           411: plist  : parm {                /* start parm list */
        !           412:                $$ = $1; }
        !           413:        | parm COMMA plist {    /* chain parm list */
        !           414:                $$ = $1;
        !           415:                $$->next = $3; }
        !           416:        | {
        !           417:                $$ = NULL; };
        !           418: 
        !           419: parm   : TOKEN {               /* start a parm */
        !           420:                $$ = (parm *)gcpy($1, offset(parm, str)); };
        !           421: 
        !           422: label  : { 
        !           423:                $$ = NULL; }
        !           424:        | TOKEN {
        !           425:                $$ = (parm *)gcpy($1, offset(parm, str)); };
        !           426: 
        !           427: /* operand may be stuff separated by commas */
        !           428: operand : escoper COMMA operand {
        !           429:                $$ = $1;
        !           430:                $$->next = $3; }
        !           431:        | escoper {
        !           432:                $$ = $1; }
        !           433:        | TIMES escoper {
        !           434:                lflags |= A_INDIR;
        !           435:                $$ = $2; }
        !           436:        | {
        !           437:                $$ = NULL; };
        !           438: 
        !           439: escoper : oper {
        !           440:        $$->sg = -1;
        !           441:        $$ = $1; }
        !           442:        | REG COLON oper {
        !           443:                $$ = $3;
        !           444:                if ($1->flag != SEG_REG)
        !           445:                        regerror($1);
        !           446:                $$->sg = $1->loc; };
        !           447: 
        !           448: /* operands are one of these */
        !           449: oper : REG {
        !           450:                $$ = qbild(0L, T_R, $1, NULL, 0L, NULL); }
        !           451: 
        !           452:      | FSTACK {
        !           453:                $$ = fbild(0L); }
        !           454: 
        !           455:      | FSTACK LBRACK numexp RBRACK {
        !           456:                $$ = fbild($3); }
        !           457: 
        !           458:      | LBRACK REG RBRACK {
        !           459:                $$ = qbild(0L, T_RI, $2, NULL, 0L, NULL); }
        !           460: 
        !           461:      | LBRACK REG COMMA numexp RBRACK {
        !           462:                $$ = qbild(0L, T_RIS, $2, NULL, $4, NULL); }
        !           463: 
        !           464:      | LBRACK COMMA REG COMMA numexp RBRACK {
        !           465:                $$ = qbild(0L, T_RIS, $3, NULL, $5, NULL); }
        !           466: 
        !           467:      | LBRACK REG COMMA REG RBRACK {
        !           468:                $$ = qbild(0L, T_RIX, $2, $4, 0L, NULL); }
        !           469: 
        !           470:      | LBRACK REG COMMA REG COMMA numexp RBRACK {
        !           471:                $$ = qbild(0L, T_RIXS, $2, $4, $6, NULL); }
        !           472: 
        !           473:      | numexp LBRACK REG RBRACK {
        !           474:                $$ = qbild($1, T_RID, $3, NULL, 0L, NULL); }
        !           475: 
        !           476:      | numexp LBRACK REG COMMA numexp RBRACK {
        !           477:                $$ = qbild($1, T_RIDS, $3, NULL, $5, NULL); }
        !           478: 
        !           479:      | numexp LBRACK COMMA REG COMMA numexp RBRACK {
        !           480:                $$ = qbild($1, T_RIDS, $4, NULL, $6, NULL); }
        !           481: 
        !           482:      | numexp LBRACK REG COMMA REG RBRACK {
        !           483:                $$ = qbild($1, T_RIXD, $3, $5, 0L, NULL); }
        !           484: 
        !           485:      | numexp LBRACK REG COMMA REG COMMA numexp RBRACK {
        !           486:                $$ = qbild($1, T_RIXDS, $3, $5, $7, NULL); }
        !           487: 
        !           488:      | addexp LBRACK REG RBRACK {
        !           489:                $$ = qbild($1->loc, T_RID, $3, NULL, 0L, $1); }
        !           490: 
        !           491:      | addexp LBRACK REG COMMA numexp RBRACK {
        !           492:                $$ = qbild($1->loc, T_RIDS, $3, NULL, $5, $1); }
        !           493: 
        !           494:      | addexp LBRACK COMMA REG COMMA numexp RBRACK {
        !           495:                $$ = qbild($1->loc, T_RIDS, $4, NULL, $6, $1); }
        !           496: 
        !           497:      | addexp LBRACK REG COMMA REG RBRACK {
        !           498:                $$ = qbild($1->loc, T_RIXD, $3, $5, 0L, $1); }
        !           499: 
        !           500:      | addexp LBRACK REG COMMA REG COMMA numexp RBRACK {
        !           501:                $$ = qbild($1->loc, T_RIXDS, $3, $5, $7, $1); }
        !           502: 
        !           503:      | addexp {
        !           504:                $$ = qbild($1->loc, T_D, NULL, NULL, 0L, $1); }
        !           505: 
        !           506:      | numexp {
        !           507:                $$ = qbild($1, T_D, NULL, NULL, 0L, NULL); }
        !           508: 
        !           509:      | D_SIGN numexp {
        !           510:                $$ = setImm($2, (sym *)NULL); }
        !           511: 
        !           512:      | D_SIGN addexp {
        !           513:                $$ = setImm($2->loc, $2); };
        !           514: 
        !           515: 
        !           516: /* Various expressions */
        !           517: 
        !           518: addexp : IDENTIFIER  { $$ = $1; }
        !           519:        | LPAREN addexp RPAREN { $$=$2; }
        !           520:        | addexp PLUS numexp { $$ = copySym($1); $$->loc += $3; }
        !           521:        | addexp MINUS numexp { $$ = copySym($1); $$->loc -= $3; }
        !           522:        | numexp PLUS addexp { $$ = copySym($3); $$->loc += $1; };
        !           523: 
        !           524: /* numeric expressions done here */
        !           525: numexp : NUMBER {
        !           526:                $$ = $1; }
        !           527:        | LPAREN numexp RPAREN {
        !           528:                $$ = $2; }
        !           529:        | addexp MINUS addexp {
        !           530:                ckseg($1, $3); $$ = $1->loc - $3->loc; }
        !           531:        | addexp COMPARISON addexp {
        !           532:                ckseg($1, $3); $$ = compare((int)$2, $1->loc - $3->loc); }
        !           533:        | numexp COMPARISON numexp {
        !           534:                $$ = compare((int)$2, $1 - $3); }
        !           535:        | string COMPARISON string {
        !           536:                $$ = compare((int)$2, (long)strcmp($1, $3)); }
        !           537:        | dblexp COMPARISON dblexp {
        !           538:                $$ = fcompare((int)$2, $1 - $3); }
        !           539: 
        !           540:        | SIZEOF addexp {
        !           541:                $$ = $2->size; }
        !           542: 
        !           543:        | LOCATION addexp {
        !           544:                $$ = $2->loc; }
        !           545: 
        !           546:        | SEGMENT addexp {
        !           547:                $$ = $2->sg + 1; }
        !           548: 
        !           549:        | DEFINED IDENTIFIER {
        !           550:                $$ = $2->statement && (statement >= $2->statement); }
        !           551:        | DEFINED NUMBER {
        !           552:                $$ = 1; }
        !           553:        | PARMCT {
        !           554:                $$ = parmCt(); }
        !           555: 
        !           556:        | numexp PLUS numexp {
        !           557:                $$ = $1 + $3; }
        !           558:        | numexp MINUS numexp {
        !           559:                $$ = $1 - $3; }
        !           560:        | numexp TIMES numexp {
        !           561:                $$ = $1 * $3; }
        !           562:        | numexp DIVIDE numexp {
        !           563:                $$ = $1 / $3; }
        !           564:        | numexp REM numexp {
        !           565:                $$ = $1 % $3; }
        !           566: 
        !           567:        | numexp LSHIFT numexp {
        !           568:                $$ = $1 << $3; }
        !           569:        | numexp RSHIFT numexp {
        !           570:                $$ = $1 >> $3; }
        !           571: 
        !           572: 
        !           573:        | numexp AND numexp {
        !           574:                $$ = $1 & $3; }
        !           575:        | numexp OR numexp {
        !           576:                $$ = $1 | $3; }
        !           577:        | numexp XOR numexp {
        !           578:                $$ = $1 ^ $3; }
        !           579:        | MINUS numexp %prec TIMES {
        !           580:                $$ = - $2; }
        !           581:        | BANG numexp {
        !           582:                $$ = !$2; }
        !           583:        | NOT numexp {
        !           584:                $$ = ~$2; }
        !           585: 
        !           586:        | string LBRACK numexp RBRACK {
        !           587:                $$ = ($3 > strlen($1)) ? 0 : $1[(short)$3]; }
        !           588:        | string AT string {
        !           589:                $$ = stringSearch($1, $3); }
        !           590:        | TONUMBER string {
        !           591:                $$ = atol($2); }
        !           592:        | TONUMBER dblexp {
        !           593:                $$ = $2; };
        !           594: 
        !           595: string : TOKEN {
        !           596:                $$ = gcpy($1, 0); }
        !           597:        | LPAREN string RPAREN {
        !           598:                $$ = $2; }
        !           599:        | string PLUS string {
        !           600:                $$ = concat($1, $3); }
        !           601:        | string LPAREN numexp COMMA numexp RPAREN {
        !           602:                $$ = substr($1, $3, $5); }
        !           603:        | string LPAREN numexp RPAREN {
        !           604:                $$ = substr($1, $3, strlen($1) - $3); }
        !           605:        | TOSTRING numexp {
        !           606:                $$ = galloc(12);
        !           607:                sprintf($$, "%ld", $2); }
        !           608:        | TOSTRING dblexp {
        !           609:                $$ = galloc(20);
        !           610:                sprintf($$, "%g", $2); };
        !           611: 
        !           612: /* floating point done here */
        !           613: dblexp : FNUM {
        !           614:                $$ = $1; }
        !           615:        | LPAREN dblexp RPAREN {
        !           616:                $$ = $2; }
        !           617:        | dblexp PLUS dblexp {
        !           618:                $$ = $1 + $3; }
        !           619:        | dblexp MINUS dblexp {
        !           620:                $$ = $1 - $3; }
        !           621:        | dblexp TIMES dblexp {
        !           622:                $$ = $1 * $3; }
        !           623:        | dblexp DIVIDE dblexp {
        !           624:                $$ = $1 / $3; }
        !           625:        | MINUS dblexp %prec TIMES {
        !           626:                $$ = - $2; }
        !           627:        | TOFLOAT string {
        !           628:                $$ = strtod($2, (char **)NULL); }
        !           629:        | TOFLOAT numexp {
        !           630:                $$ = $2; };
        !           631: 

unix.superglobalmegacorp.com

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