This is parse.c in view mode; [Download] [Up]
#ifndef lint static char *RCSid = "$Id: parse.c%v 3.38.2.121 1993/04/30 00:02:32 woo Exp woo $"; #endif /* GNUPLOT - parse.c */ /* * Copyright (C) 1986 - 1993 Thomas Williams, Colin Kelley * * Permission to use, copy, and distribute this software and its documentation * for any purpose with or without fee is hereby granted, provided that the * above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation. * * Permission to modify the software is granted, but not the right to distribute * the modified code. Modifications are to be distributed as patches to * released version. * * This software is provided "as is" without express or implied warranty. * * * AUTHORS * * Original Software: Thomas Williams, Colin Kelley. * * Gnuplot 2.0 additions: Russell Lang, Dave Kotz, John Campbell. * * Gnuplot 3.0 additions: Gershon Elber and many others. * * Send your comments or suggestions to info-gnuplot@dartmouth.edu. This is * a mailing list; to join it send a note to * info-gnuplot-request@dartmouth.edu. Send bug reports to * bug-gnuplot@dartmouth.edu. */ #include <stdio.h> #include <setjmp.h> #include <signal.h> #include <errno.h> #include <math.h> #include "plot.h" #ifndef vms #if !defined(__ZTC__) && !defined(__MSC__) extern int errno; #endif #endif extern int num_tokens, c_token; extern struct lexical_unit token[]; extern char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN + 1]; /* name of current dummy * vars */ extern struct udft_entry *dummy_func; /* pointer to dummy variable's func */ struct value * pop(), *Ginteger(), *Gcomplex(); struct at_type * temp_at(), *perm_at(); struct udft_entry *add_udf(); struct udvt_entry *add_udv(); union argument *add_action(); struct at_type at; #ifdef _Windows static jmp_buf far fpe_env; #else static jmp_buf fpe_env; #endif #define dummy (struct value *) 0 #if defined(__TURBOC__) || defined(DJGPP) void fpe() #else #if defined( __ZTC__ ) || defined( _CRAY ) || defined( sgi )|| defined( OS2 ) || defined(__EMX__) void fpe(an_int) int an_int; #else #if defined( NEXT ) || defined( VMS) void fpe(int an_int) #else #ifdef sgi void fpe(int sig, int code, struct sigcontext * sc) /* * void fpe(an_int) int an_int; */ #else fpe() #endif #endif #endif /* __ZTC__ || _CRAY */ #endif /* __TURBOC__ */ { #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386) /* thanks to lotto@wjh12.UUCP for telling us about this */ _fpreset(); #endif #if defined(MSDOS) && defined(__EMX__) (void)signal(SIGFPE, (void *)fpe); #else #ifdef DJGPP (void)signal(SIGFPE, (SignalHandler)fpe); #else #ifdef OS2 (void) signal(an_int, SIG_ACK); #else (void)signal(SIGFPE, fpe); #endif #endif #endif #ifdef ATARI /* do we need this ? (AL) */ fprintf(stderr, "floating point exception!\n"); #endif undefined = TRUE; longjmp(fpe_env, TRUE); } #ifdef apollo #include <apollo/base.h> #include <apollo/pfm.h> #include <apollo/fault.h> /* * On an Apollo, the OS can signal a couple errors that are not mapped into * SIGFPE, namely signalling NaN and branch on an unordered comparison. I * suppose there are others, but none of these are documented, so I handle * them as they arise. * * Anyway, we need to catch these faults and signal SIGFPE. */ pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec) { kill(getpid(), SIGFPE); return pfm_$continue_fault_handling; } apollo_pfm_catch() { status_$t status; pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop, apollo_sigfpe, &status); pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop, apollo_sigfpe, &status); } #endif evaluate_at(at_ptr, val_ptr) struct at_type *at_ptr; struct value *val_ptr; { double temp, real(); undefined = FALSE; errno = 0; reset_stack(); #ifndef DOSX286 if (setjmp(fpe_env)) return(0); /* just bail out */ #if defined(MSDOS) && defined(__EMX__) (void)signal(SIGFPE, (void *)fpe); #else #if DJGPP (void)signal(SIGFPE, (SignalHandler)fpe); #else (void)signal(SIGFPE, fpe); /* catch core dumps on FPEs */ #endif #endif #endif execute_at(at_ptr); #ifndef DOSX286 (void)signal(SIGFPE, SIG_DFL); #endif if (errno == EDOM || errno == ERANGE) { undefined = TRUE; } else { (void)pop(val_ptr); check_stack(); } /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */ temp = real(val_ptr); if (temp > VERYLARGE || temp < -VERYLARGE) { undefined = TRUE; } } struct value * const_express(valptr) struct value *valptr; { register int tkn = c_token; if (END_OF_COMMAND) int_error("constant expression required", c_token); evaluate_at(temp_at(), valptr); /* run it and send answer back */ if (undefined) { int_error("undefined value", tkn); } return (valptr); } struct at_type * temp_at() { /* build a static action table and return its * pointer */ at.a_count = 0; /* reset action table !!! */ express(); return (&at); } /* build an action table, put it in dynamic memory, and return its pointer */ struct at_type * perm_at() { register struct at_type *at_ptr; register unsigned int len; (void)temp_at(); len = sizeof(struct at_type) - (MAX_AT_LEN - at.a_count) * sizeof(struct at_entry); at_ptr = (struct at_type *) alloc((unsigned long)len, "action table"); (void)memcpy(at_ptr, &at, len); return (at_ptr); } #ifdef NOCOPY /* * cheap and slow version of memcpy() in case you don't have one */ memcpy(dest, src, len) char *dest, *src; unsigned int len; { while (len--) *dest++ = *src++; } #endif /* NOCOPY */ express() { /* full expressions */ xterm(); xterms(); } xterm() { /* ? : expressions */ aterm(); aterms(); } aterm() { bterm(); bterms(); } bterm() { cterm(); cterms(); } cterm() { dterm(); dterms(); } dterm() { eterm(); eterms(); } eterm() { fterm(); fterms(); } fterm() { gterm(); gterms(); } gterm() { hterm(); hterms(); } hterm() { unary(); /* - things */ iterms(); /* * / % */ } factor() { register int value; if (equals(c_token, "(")) { c_token++; express(); if (!equals(c_token, ")")) int_error("')' expected", c_token); c_token++; } else if (isnumber(c_token)) { convert(&(add_action(PUSHC)->v_arg), c_token); c_token++; } else if (isletter(c_token)) { if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) { value = standard(c_token); if (value) { /* it's a standard function */ c_token += 2; express(); if (equals(c_token, ",")) { while (equals(c_token, ",")) { c_token += 1; express(); } } if (!equals(c_token, ")")) int_error("')' expected", c_token); c_token++; (void)add_action(value); } else { int call_type = (int)CALL; value = c_token; c_token += 2; express(); if (equals(c_token, ",")) { struct value num_params; num_params.type = INTGR; num_params.v.int_val = 1; while (equals(c_token, ",")) { num_params.v.int_val += 1; c_token += 1; express(); } add_action(PUSHC)->v_arg = num_params; call_type = (int)CALLN; } if (!equals(c_token, ")")) int_error("')' expected", c_token); c_token++; add_action(call_type)->udf_arg = add_udf(value); } } else { if (equals(c_token, c_dummy_var[0])) { c_token++; add_action(PUSHD1)->udf_arg = dummy_func; } else if (equals(c_token, c_dummy_var[1])) { c_token++; add_action(PUSHD2)->udf_arg = dummy_func; } else { int i, param = 0; for (i = 2; i < MAX_NUM_VAR; i++) { if (equals(c_token, c_dummy_var[i])) { struct value num_params; num_params.type = INTGR; num_params.v.int_val = i; param = 1; c_token++; add_action(PUSHC)->v_arg = num_params; add_action(PUSHD)->udf_arg = dummy_func; break; } } if (!param) { /* defined variable */ add_action(PUSH)->udv_arg = add_udv(c_token); c_token++; } } } } /* end if letter */ else int_error("invalid expression ", c_token); /* add action code for ! (factorial) operator */ while (equals(c_token, "!")) { c_token++; (void)add_action(FACTORIAL); } /* add action code for ** operator */ if (equals(c_token, "**")) { c_token++; unary(); (void)add_action(POWER); } } xterms() { /* create action code for ? : expressions */ if (equals(c_token, "?")) { register int savepc1, savepc2; register union argument *argptr1, *argptr2; c_token++; savepc1 = at.a_count; argptr1 = add_action(JTERN); express(); if (!equals(c_token, ":")) int_error("expecting ':'", c_token); c_token++; savepc2 = at.a_count; argptr2 = add_action(JUMP); argptr1->j_arg = at.a_count - savepc1; express(); argptr2->j_arg = at.a_count - savepc2; } } aterms() { /* create action codes for || operator */ while (equals(c_token, "||")) { register int savepc; register union argument *argptr; c_token++; savepc = at.a_count; argptr = add_action(JUMPNZ); /* short-circuit if already * TRUE */ aterm(); argptr->j_arg = at.a_count - savepc; /* offset for jump */ (void)add_action(BOOLE); } } bterms() { /* create action code for && operator */ while (equals(c_token, "&&")) { register int savepc; register union argument *argptr; c_token++; savepc = at.a_count; argptr = add_action(JUMPZ); /* short-circuit if already * FALSE */ bterm(); argptr->j_arg = at.a_count - savepc; /* offset for jump */ (void)add_action(BOOLE); } } cterms() { /* create action code for | operator */ while (equals(c_token, "|")) { c_token++; cterm(); (void)add_action(BOR); } } dterms() { /* create action code for ^ operator */ while (equals(c_token, "^")) { c_token++; dterm(); (void)add_action(XOR); } } eterms() { /* create action code for & operator */ while (equals(c_token, "&")) { c_token++; eterm(); (void)add_action(BAND); } } fterms() { /* create action codes for == and != * operators */ while (TRUE) { if (equals(c_token, "==")) { c_token++; fterm(); (void)add_action(EQ); } else if (equals(c_token, "!=")) { c_token++; fterm(); (void)add_action(NE); } else break; } } gterms() { /* create action code for < > >= or <= * operators */ while (TRUE) { /* I hate "else if" statements */ if (equals(c_token, ">")) { c_token++; gterm(); (void)add_action(GT); } else if (equals(c_token, "<")) { c_token++; gterm(); (void)add_action(LT); } else if (equals(c_token, ">=")) { c_token++; gterm(); (void)add_action(GE); } else if (equals(c_token, "<=")) { c_token++; gterm(); (void)add_action(LE); } else break; } } hterms() { /* create action codes for + and - operators */ while (TRUE) { if (equals(c_token, "+")) { c_token++; hterm(); (void)add_action(PLUS); } else if (equals(c_token, "-")) { c_token++; hterm(); (void)add_action(MINUS); } else break; } } iterms() { /* add action code for * / and % operators */ while (TRUE) { if (equals(c_token, "*")) { c_token++; unary(); (void)add_action(MULT); } else if (equals(c_token, "/")) { c_token++; unary(); (void)add_action(DIV); } else if (equals(c_token, "%")) { c_token++; unary(); (void)add_action(MOD); } else break; } } unary() { /* add code for unary operators */ if (equals(c_token, "!")) { c_token++; unary(); (void)add_action(LNOT); } else if (equals(c_token, "~")) { c_token++; unary(); (void)add_action(BNOT); } else if (equals(c_token, "-")) { c_token++; unary(); (void)add_action(UMINUS); } else factor(); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.