[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.1

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

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