[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/parse.c, Revision 1.1.1.3

1.1       maekawa     1: #ifndef lint
1.1.1.3 ! ohara       2: static char *RCSid = "$Id: parse.c,v 1.9.2.4 2002/03/11 16:07:20 lhecking Exp $";
1.1       maekawa     3: #endif
                      4:
                      5: /* GNUPLOT - parse.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
1.1.1.3 ! ohara      37: #ifdef HAVE_CONFIG_H
        !            38: # include "config.h"
        !            39: #endif
        !            40:
1.1       maekawa    41: #include <signal.h>
1.1.1.3 ! ohara      42: #include <setjmp.h>
        !            43:
1.1       maekawa    44: #include "plot.h"
                     45: #include "help.h"
                     46:
                     47: RETSIGTYPE fpe __PROTO((int an_int));
                     48: static void extend_at __PROTO((void));
                     49: static union argument *add_action __PROTO((enum operators sf_index));
                     50: static void express __PROTO((void));
                     51: static void xterm __PROTO((void));
                     52: static void aterm __PROTO((void));
                     53: static void bterm __PROTO((void));
                     54: static void cterm __PROTO((void));
                     55: static void dterm __PROTO((void));
                     56: static void eterm __PROTO((void));
                     57: static void fterm __PROTO((void));
                     58: static void gterm __PROTO((void));
                     59: static void hterm __PROTO((void));
                     60: static void factor __PROTO((void));
                     61: static void xterms __PROTO((void));
                     62: static void aterms __PROTO((void));
                     63: static void bterms __PROTO((void));
                     64: static void cterms __PROTO((void));
                     65: static void dterms __PROTO((void));
                     66: static void eterms __PROTO((void));
                     67: static void fterms __PROTO((void));
                     68: static void gterms __PROTO((void));
                     69: static void hterms __PROTO((void));
                     70: static void iterms __PROTO((void));
                     71: static void unary __PROTO((void));
                     72:
                     73: static struct at_type *at = NULL;
                     74: static int at_size = 0;
                     75: #if defined(_Windows) && !defined(WIN32)
1.1.1.3 ! ohara      76: static JMP_BUF far fpe_env;
1.1       maekawa    77: #else
1.1.1.3 ! ohara      78: static JMP_BUF fpe_env;
1.1       maekawa    79: #endif
                     80:
                     81: #define dummy (struct value *) 0
                     82:
                     83: RETSIGTYPE fpe(an_int)
                     84: int an_int;
                     85: {
                     86: #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
                     87:     /* thanks to lotto@wjh12.UUCP for telling us about this  */
                     88:     _fpreset();
                     89: #endif
                     90:
                     91: #ifdef OS2
                     92:     (void) signal(an_int, SIG_ACK);
                     93: #else
                     94:     (void) signal(SIGFPE, (sigfunc) fpe);
                     95: #endif
                     96:     undefined = TRUE;
1.1.1.3 ! ohara      97:     LONGJMP(fpe_env, TRUE);
1.1       maekawa    98: }
                     99:
                    100:
                    101: #ifdef apollo
                    102: #include <apollo/base.h>
                    103: #include <apollo/pfm.h>
                    104: #include <apollo/fault.h>
                    105:
                    106: /*
                    107:  * On an Apollo, the OS can signal a couple errors that are not mapped into
                    108:  * SIGFPE, namely signalling NaN and branch on an unordered comparison.  I
                    109:  * suppose there are others, but none of these are documented, so I handle
                    110:  * them as they arise.
                    111:  *
                    112:  * Anyway, we need to catch these faults and signal SIGFPE.
                    113:  */
                    114:
                    115: pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
                    116: {
                    117:     kill(getpid(), SIGFPE);
                    118:     return pfm_$continue_fault_handling;
                    119: }
                    120:
                    121: apollo_pfm_catch()
                    122: {
                    123:     status_$t status;
                    124:     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
                    125:                                 apollo_sigfpe, &status);
                    126:     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
                    127:                                 apollo_sigfpe, &status);
                    128: }
                    129: #endif
                    130:
                    131:
                    132: void evaluate_at(at_ptr, val_ptr)
                    133: struct at_type *at_ptr;
                    134: struct value *val_ptr;
                    135: {
                    136:     double temp;
                    137:
                    138:     undefined = FALSE;
                    139:     errno = 0;
                    140:     reset_stack();
                    141:
                    142: #ifndef DOSX286
1.1.1.3 ! ohara     143:     if (SETJMP(fpe_env, 1))
1.1       maekawa   144:        return;                 /* just bail out */
                    145:     (void) signal(SIGFPE, (sigfunc) fpe);
                    146: #endif
                    147:
                    148:     execute_at(at_ptr);
                    149:
                    150: #ifndef DOSX286
                    151:     (void) signal(SIGFPE, SIG_DFL);
                    152: #endif
                    153:
                    154:     if (errno == EDOM || errno == ERANGE) {
                    155:        undefined = TRUE;
                    156:     } else if (!undefined) {   /* undefined (but not errno) may have been set by matherr */
                    157:        (void) pop(val_ptr);
                    158:        check_stack();
                    159:        /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
                    160:        temp = real(val_ptr);
                    161:        if (temp > VERYLARGE || temp < -VERYLARGE) {
                    162:            undefined = TRUE;
                    163:        }
                    164:     }
                    165: #if defined(NeXT) || defined(ultrix)
                    166:     /*
                    167:      * linux was able to fit curves which NeXT gave up on -- traced it to
                    168:      * silently returning NaN for the undefined cases and plowing ahead
                    169:      * I can force that behavior this way.  (0.0/0.0 generates NaN)
                    170:      */
                    171:     if (undefined && (errno == EDOM || errno == ERANGE)) {     /* corey@cac */
                    172:        undefined = FALSE;
                    173:        errno = 0;
                    174:        Gcomplex(val_ptr, 0.0 / 0.0, 0.0 / 0.0);
                    175:     }
                    176: #endif /* NeXT || ultrix */
                    177: }
                    178:
                    179:
                    180: struct value *
                    181:  const_express(valptr)
                    182: struct value *valptr;
                    183: {
                    184:     register int tkn = c_token;
                    185:
                    186:     if (END_OF_COMMAND)
                    187:        int_error("constant expression required", c_token);
                    188:
                    189:     /* div - no dummy variables in a constant expression */
                    190:     dummy_func = NULL;
                    191:
                    192:     evaluate_at(temp_at(), valptr);    /* run it and send answer back */
                    193:     if (undefined) {
                    194:        int_error("undefined value", tkn);
                    195:     }
                    196:     return (valptr);
                    197: }
                    198:
                    199:
                    200: /* if dummy_dunc == NULL on entry, do not attempt to compile dummy variables
                    201:  * - div
                    202:  */
                    203: struct at_type *
                    204:  temp_at()
                    205: {
                    206:     /* build a static action table and return its
                    207:      * pointer */
                    208:
                    209:     if (at != NULL) {
                    210:        free(at);
                    211:        at = NULL;
                    212:     }
                    213:     at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
                    214:
                    215:     at->a_count = 0;           /* reset action table !!! */
                    216:     at_size = MAX_AT_LEN;
                    217:     express();
                    218:     return (at);
                    219: }
                    220:
                    221:
                    222: /* build an action table, put it in dynamic memory, and return its pointer */
                    223:
                    224: struct at_type *
                    225:  perm_at()
                    226: {
                    227:     register struct at_type *at_ptr;
                    228:     unsigned int len;
                    229:
                    230:     (void) temp_at();
                    231:     len = sizeof(struct at_type) +
                    232:      (int) (at->a_count - MAX_AT_LEN) * (int) sizeof(struct at_entry);
                    233:     at_ptr = (struct at_type *) gp_realloc(at, (unsigned long) len, "perm_at");
                    234:     at = NULL;                 /* invalidate at pointer */
                    235:     return (at_ptr);
                    236: }
                    237:
                    238: static void extend_at()
                    239: {
                    240:     int newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);
                    241:
                    242:     at = gp_realloc(at, newsize, "extend_at");
                    243:     at_size += MAX_AT_LEN;
                    244:     FPRINTF((stderr, "Extending at size to %d\n", at_size));
                    245: }
                    246:
                    247: /* moved from eval.c, the function is only called from this module */
                    248: static union argument *
                    249:  add_action(sf_index)
                    250: enum operators sf_index;       /* index of p-code function */
                    251: {
                    252:     if (at->a_count >= at_size) {
                    253:        extend_at();
                    254:     }
                    255:     at->actions[at->a_count].index = sf_index;
                    256:     return (&(at->actions[at->a_count++].arg));
                    257: }
                    258:
                    259:
                    260: static void express()
                    261: {                              /* full expressions */
                    262:     xterm();
                    263:     xterms();
                    264: }
                    265:
                    266: static void xterm()
                    267: {                              /* ? : expressions */
                    268:     aterm();
                    269:     aterms();
                    270: }
                    271:
                    272:
                    273: static void aterm()
                    274: {
                    275:     bterm();
                    276:     bterms();
                    277: }
                    278:
                    279:
                    280: static void bterm()
                    281: {
                    282:     cterm();
                    283:     cterms();
                    284: }
                    285:
                    286:
                    287: static void cterm()
                    288: {
                    289:     dterm();
                    290:     dterms();
                    291: }
                    292:
                    293:
                    294: static void dterm()
                    295: {
                    296:     eterm();
                    297:     eterms();
                    298: }
                    299:
                    300:
                    301: static void eterm()
                    302: {
                    303:     fterm();
                    304:     fterms();
                    305: }
                    306:
                    307:
                    308: static void fterm()
                    309: {
                    310:     gterm();
                    311:     gterms();
                    312: }
                    313:
                    314:
                    315: static void gterm()
                    316: {
                    317:     hterm();
                    318:     hterms();
                    319: }
                    320:
                    321:
                    322: static void hterm()
                    323: {
                    324:     unary();                   /* - things */
                    325:     iterms();                  /* * / % */
                    326: }
                    327:
                    328:
                    329: static void factor()
                    330: {
                    331:     if (equals(c_token, "(")) {
                    332:        c_token++;
                    333:        express();
                    334:        if (!equals(c_token, ")"))
                    335:            int_error("')' expected", c_token);
                    336:        c_token++;
                    337:     } else if (equals(c_token, "$")) {
                    338:        struct value a;
                    339:        if (!isanumber(++c_token))
                    340:            int_error("Column number expected", c_token);
                    341:        convert(&a, c_token++);
                    342:        if (a.type != INTGR || a.v.int_val < 0)
                    343:            int_error("Positive integer expected", c_token);
                    344:        add_action(DOLLARS)->v_arg = a;
                    345:     } else if (isanumber(c_token)) {
                    346:        /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */
1.1.1.3 ! ohara     347:        /* HBB 20010724: use this code for all platforms, then */
        !           348:
1.1       maekawa   349:        union argument *foo = add_action(PUSHC);
                    350:        convert(&(foo->v_arg), c_token);
                    351:        c_token++;
                    352:     } else if (isletter(c_token)) {
                    353:        if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
                    354:            enum operators value = standard(c_token);
                    355:            if (value) {        /* it's a standard function */
                    356:                c_token += 2;
                    357:                express();
                    358:                if (equals(c_token, ",")) {
                    359:                    while (equals(c_token, ",")) {
                    360:                        c_token += 1;
                    361:                        express();
                    362:                    }
                    363:                }
                    364:                if (!equals(c_token, ")"))
                    365:                    int_error("')' expected", c_token);
                    366:                c_token++;
                    367:                (void) add_action(value);
                    368:            } else {
                    369:                enum operators call_type = (int) CALL;
                    370:                int tok = c_token;
                    371:                c_token += 2;
                    372:                express();
                    373:                if (equals(c_token, ",")) {
                    374:                    struct value num_params;
                    375:                    num_params.type = INTGR;
                    376:                    num_params.v.int_val = 1;
                    377:                    while (equals(c_token, ",")) {
                    378:                        num_params.v.int_val += 1;
                    379:                        c_token += 1;
                    380:                        express();
                    381:                    }
                    382:                    add_action(PUSHC)->v_arg = num_params;
                    383:                    call_type = (int) CALLN;
                    384:                }
                    385:                if (!equals(c_token, ")"))
                    386:                    int_error("')' expected", c_token);
                    387:                c_token++;
                    388:                add_action(call_type)->udf_arg = add_udf(tok);
                    389:            }
                    390:            /* dummy_func==NULL is a flag to say no dummy variables active */
                    391:        } else if (dummy_func) {
                    392:            if (equals(c_token, c_dummy_var[0])) {
                    393:                c_token++;
                    394:                add_action(PUSHD1)->udf_arg = dummy_func;
                    395:            } else if (equals(c_token, c_dummy_var[1])) {
                    396:                c_token++;
                    397:                add_action(PUSHD2)->udf_arg = dummy_func;
                    398:            } else {
                    399:                int i, param = 0;
                    400:                for (i = 2; i < MAX_NUM_VAR; i++) {
                    401:                    if (equals(c_token, c_dummy_var[i])) {
                    402:                        struct value num_params;
                    403:                        num_params.type = INTGR;
                    404:                        num_params.v.int_val = i;
                    405:                        param = 1;
                    406:                        c_token++;
                    407:                        add_action(PUSHC)->v_arg = num_params;
                    408:                        add_action(PUSHD)->udf_arg = dummy_func;
                    409:                        break;
                    410:                    }
                    411:                }
                    412:                if (!param) {   /* defined variable */
                    413:                    add_action(PUSH)->udv_arg = add_udv(c_token);
                    414:                    c_token++;
                    415:                }
                    416:            }
                    417:            /* its a variable, with no dummies active - div */
                    418:        } else {
                    419:            add_action(PUSH)->udv_arg = add_udv(c_token);
                    420:            c_token++;
                    421:        }
                    422:     }
                    423:     /* end if letter */
                    424:     else
                    425:        int_error("invalid expression ", c_token);
                    426:
                    427:     /* add action code for ! (factorial) operator */
                    428:     while (equals(c_token, "!")) {
                    429:        c_token++;
                    430:        (void) add_action(FACTORIAL);
                    431:     }
                    432:     /* add action code for ** operator */
                    433:     if (equals(c_token, "**")) {
                    434:        c_token++;
                    435:        unary();
                    436:        (void) add_action(POWER);
                    437:     }
                    438: }
                    439:
                    440:
1.1.1.3 ! ohara     441: /* HBB 20010309: Here and below: can't store pointers into the middle
        !           442:  * of at->actions[]. That array may be realloc()ed by add_action() or
        !           443:  * express() calls!. Access via index savepc1/savepc2, instead. */
1.1       maekawa   444:
1.1.1.3 ! ohara     445: static void
        !           446: xterms()
1.1       maekawa   447: {
                    448:     /* create action code for ? : expressions */
                    449:
                    450:     if (equals(c_token, "?")) {
                    451:        register int savepc1, savepc2;
1.1.1.3 ! ohara     452:
1.1       maekawa   453:        c_token++;
                    454:        savepc1 = at->a_count;
1.1.1.3 ! ohara     455:        add_action(JTERN);
1.1       maekawa   456:        express();
                    457:        if (!equals(c_token, ":"))
                    458:            int_error("expecting ':'", c_token);
1.1.1.3 ! ohara     459:
1.1       maekawa   460:        c_token++;
                    461:        savepc2 = at->a_count;
1.1.1.3 ! ohara     462:        add_action(JUMP);
        !           463:        at->actions[savepc1].arg.j_arg = at->a_count - savepc1;
1.1       maekawa   464:        express();
1.1.1.3 ! ohara     465:        at->actions[savepc2].arg.j_arg = at->a_count - savepc2;
1.1       maekawa   466:     }
                    467: }
                    468:
1.1.1.3 ! ohara     469: static void
        !           470: aterms()
1.1       maekawa   471: {
                    472:     /* create action codes for || operator */
                    473:
                    474:     while (equals(c_token, "||")) {
                    475:        register int savepc;
1.1.1.3 ! ohara     476:
1.1       maekawa   477:        c_token++;
                    478:        savepc = at->a_count;
1.1.1.3 ! ohara     479:        add_action(JUMPNZ);     /* short-circuit if already TRUE */
1.1       maekawa   480:        aterm();
1.1.1.3 ! ohara     481:        /* offset for jump */
        !           482:        at->actions[savepc].arg.j_arg = at->a_count - savepc;
1.1       maekawa   483:        (void) add_action(BOOLE);
                    484:     }
                    485: }
                    486:
                    487:
1.1.1.3 ! ohara     488: static void
        !           489: bterms()
1.1       maekawa   490: {
                    491:     /* create action code for && operator */
                    492:
                    493:     while (equals(c_token, "&&")) {
                    494:        register int savepc;
1.1.1.3 ! ohara     495:
1.1       maekawa   496:        c_token++;
                    497:        savepc = at->a_count;
1.1.1.3 ! ohara     498:        add_action(JUMPZ);      /* short-circuit if already FALSE */
1.1       maekawa   499:        bterm();
1.1.1.3 ! ohara     500:        at->actions[savepc].arg.j_arg = at->a_count - savepc; /* offset for jump */
1.1       maekawa   501:        (void) add_action(BOOLE);
                    502:     }
                    503: }
                    504:
                    505:
                    506: static void cterms()
                    507: {
                    508:     /* create action code for | operator */
                    509:
                    510:     while (equals(c_token, "|")) {
                    511:        c_token++;
                    512:        cterm();
                    513:        (void) add_action(BOR);
                    514:     }
                    515: }
                    516:
                    517:
                    518: static void dterms()
                    519: {
                    520:     /* create action code for ^ operator */
                    521:
                    522:     while (equals(c_token, "^")) {
                    523:        c_token++;
                    524:        dterm();
                    525:        (void) add_action(XOR);
                    526:     }
                    527: }
                    528:
                    529:
                    530: static void eterms()
                    531: {
                    532:     /* create action code for & operator */
                    533:
                    534:     while (equals(c_token, "&")) {
                    535:        c_token++;
                    536:        eterm();
                    537:        (void) add_action(BAND);
                    538:     }
                    539: }
                    540:
                    541:
                    542: static void fterms()
                    543: {
                    544:     /* create action codes for == and !=
                    545:      * operators */
                    546:
                    547:     while (TRUE) {
                    548:        if (equals(c_token, "==")) {
                    549:            c_token++;
                    550:            fterm();
                    551:            (void) add_action(EQ);
                    552:        } else if (equals(c_token, "!=")) {
                    553:            c_token++;
                    554:            fterm();
                    555:            (void) add_action(NE);
                    556:        } else
                    557:            break;
                    558:     }
                    559: }
                    560:
                    561:
                    562: static void gterms()
                    563: {
                    564:     /* create action code for < > >= or <=
                    565:      * operators */
                    566:
                    567:     while (TRUE) {
                    568:        /* I hate "else if" statements */
                    569:        if (equals(c_token, ">")) {
                    570:            c_token++;
                    571:            gterm();
                    572:            (void) add_action(GT);
                    573:        } else if (equals(c_token, "<")) {
                    574:            c_token++;
                    575:            gterm();
                    576:            (void) add_action(LT);
                    577:        } else if (equals(c_token, ">=")) {
                    578:            c_token++;
                    579:            gterm();
                    580:            (void) add_action(GE);
                    581:        } else if (equals(c_token, "<=")) {
                    582:            c_token++;
                    583:            gterm();
                    584:            (void) add_action(LE);
                    585:        } else
                    586:            break;
                    587:     }
                    588:
                    589: }
                    590:
                    591:
                    592:
                    593: static void hterms()
                    594: {
                    595:     /* create action codes for + and - operators */
                    596:
                    597:     while (TRUE) {
                    598:        if (equals(c_token, "+")) {
                    599:            c_token++;
                    600:            hterm();
                    601:            (void) add_action(PLUS);
                    602:        } else if (equals(c_token, "-")) {
                    603:            c_token++;
                    604:            hterm();
                    605:            (void) add_action(MINUS);
                    606:        } else
                    607:            break;
                    608:     }
                    609: }
                    610:
                    611:
                    612: static void iterms()
                    613: {
                    614:     /* add action code for * / and % operators */
                    615:
                    616:     while (TRUE) {
                    617:        if (equals(c_token, "*")) {
                    618:            c_token++;
                    619:            unary();
                    620:            (void) add_action(MULT);
                    621:        } else if (equals(c_token, "/")) {
                    622:            c_token++;
                    623:            unary();
                    624:            (void) add_action(DIV);
                    625:        } else if (equals(c_token, "%")) {
                    626:            c_token++;
                    627:            unary();
                    628:            (void) add_action(MOD);
                    629:        } else
                    630:            break;
                    631:     }
                    632: }
                    633:
                    634:
                    635: static void unary()
                    636: {
                    637:     /* add code for unary operators */
                    638:
                    639:     if (equals(c_token, "!")) {
                    640:        c_token++;
                    641:        unary();
                    642:        (void) add_action(LNOT);
                    643:     } else if (equals(c_token, "~")) {
                    644:        c_token++;
                    645:        unary();
                    646:        (void) add_action(BNOT);
                    647:     } else if (equals(c_token, "-")) {
                    648:        c_token++;
                    649:        unary();
                    650:        (void) add_action(UMINUS);
                    651:     } else if (equals(c_token, "+")) { /* unary + is no-op */
                    652:        c_token++;
                    653:        unary();
                    654:     } else
                    655:        factor();
                    656: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>