Annotation of OpenXM_contrib/gnuplot/parse.c, Revision 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>