2 static char *RCSid() { return RCSid("$Id: eval.c,v 1.51.2.6 2009/02/05 17:17:25 sfeam Exp $"); }
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
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.
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,
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
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.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
37 /* HBB 20010724: I moved several variables and functions from parse.c
38 * to here, because they're involved with *evaluating* functions, not
39 * with parsing them: evaluate_at(), fpe(), the APOLLO signal handling
40 * stuff, and fpe_env */
56 /* Internal prototypes */
57 static RETSIGTYPE fpe __PROTO((int an_int));
59 static pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
62 /* Global variables exported by this module */
63 struct udvt_entry udv_pi = { NULL, "pi", FALSE, {INTGR, {0} } };
64 struct udvt_entry *udv_NaN;
65 /* first in linked list */
66 struct udvt_entry *first_udv = &udv_pi;
67 struct udft_entry *first_udf = NULL;
71 /* The stack this operates on */
72 static struct value stack[STACK_DEPTH];
73 static int s_p = -1; /* stack pointer */
74 #define top_of_stack stack[s_p]
76 static int jump_offset; /* to be modified by 'jump' operators */
78 /* The table of built-in functions */
79 /* HBB 20010725: I've removed all the casts to type (FUNC_PTR) ---
80 * According to ANSI/ISO C Standards it causes undefined behaviouf if
81 * you cast a function pointer to any other type, including a function
82 * pointer with a different set of arguments, and then call the
83 * function. Instead, I made all these functions adhere to the common
85 const struct ft_entry GPFAR ft[] =
87 /* internal functions: */
115 {"factorial", f_factorial},
117 {"dollars", f_dollars}, /* for using extension */
118 #ifdef GP_STRING_VARS
119 {"concatenate", f_concatenate}, /* for string variables only */
120 {"eqs", f_eqs}, /* for string variables only */
121 {"nes", f_nes}, /* for string variables only */
122 {"[]", f_range}, /* for string variables only */
126 {"jumpnz", f_jumpnz},
129 /* standard functions: */
158 {"lgamma", f_lgamma},
160 {"igamma", f_igamma},
164 #ifdef BACKWARDS_COMPATIBLE
165 {"defined", f_exists}, /* deprecated syntax defined(foo) */
168 {"norm", f_normal}, /* XXX-JG */
169 {"inverf", f_inverse_erf}, /* XXX-JG */
170 {"invnorm", f_inverse_normal}, /* XXX-JG */
174 {"lambertw", f_lambertw}, /* HBB, from G.Kuhnle 20001107 */
176 {"column", f_column}, /* for using */
177 {"valid", f_valid}, /* for using */
178 {"timecolumn", f_timecolumn}, /* for using */
180 {"tm_sec", f_tmsec}, /* for timeseries */
181 {"tm_min", f_tmmin}, /* for timeseries */
182 {"tm_hour", f_tmhour}, /* for timeseries */
183 {"tm_mday", f_tmmday}, /* for timeseries */
184 {"tm_mon", f_tmmon}, /* for timeseries */
185 {"tm_year", f_tmyear}, /* for timeseries */
186 {"tm_wday", f_tmwday}, /* for timeseries */
187 {"tm_yday", f_tmyday}, /* for timeseries */
189 #ifdef GP_STRING_VARS
190 {"stringcolumn", f_stringcolumn}, /* for using */
191 {"strcol", f_stringcolumn}, /* shorthand form */
192 {"sprintf", f_sprintf}, /* for string variables only */
193 {"gprintf", f_gprintf}, /* for string variables only */
194 {"strlen", f_strlen}, /* for string variables only */
195 {"strstrt", f_strstrt}, /* for string variables only */
196 {"substr", f_range}, /* for string variables only */
197 {"word", f_words}, /* for string variables only */
198 {"words", f_words}, /* implemented as word(s,-1) */
199 {"strftime", f_strftime}, /* time to string */
200 {"strptime", f_strptime}, /* string to time */
201 {"system", f_system}, /* "dynamic backtics" */
202 {"exist", f_exists}, /* exists("foo") replaces defined(foo) */
203 {"exists", f_exists}, /* exists("foo") replaces defined(foo) */
209 /* Module-local variables: */
211 #if defined(_Windows) && !defined(WIN32)
212 static JMP_BUF far fpe_env;
214 static JMP_BUF fpe_env;
217 /* Internal helper functions: */
222 #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
223 /* thanks to lotto@wjh12.UUCP for telling us about this */
227 (void) an_int; /* avoid -Wunused warning */
228 (void) signal(SIGFPE, (sigfunc) fpe);
230 LONGJMP(fpe_env, TRUE);
233 /* FIXME HBB 20010724: do we really want this in *here*? Maybe it
234 * should be in syscfg.c or somewhere similar. */
236 # include <apollo/base.h>
237 # include <apollo/pfm.h>
238 # include <apollo/fault.h>
241 * On an Apollo, the OS can signal a couple errors that are not mapped into
242 * SIGFPE, namely signalling NaN and branch on an unordered comparison. I
243 * suppose there are others, but none of these are documented, so I handle
244 * them as they arise.
246 * Anyway, we need to catch these faults and signal SIGFPE.
249 static pfm_$fh_func_val_t
250 apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
252 kill(getpid(), SIGFPE);
253 return pfm_$continue_fault_handling;
256 /* This is called from main(), if the platform is an APOLLO */
261 pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
262 apollo_sigfpe, &status);
263 pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
264 apollo_sigfpe, &status);
268 /* Exported functions */
270 /* First, some functions tha help other modules use 'struct value' ---
271 * these might justify a separate module, but I'll stick with this,
274 /* returns the real part of val */
276 real(struct value *val)
280 return ((double) val->v.int_val);
282 return (val->v.cmplx_val.real);
283 #ifdef GP_STRING_VARS
284 case STRING: /* is this ever used? */
285 return (atof(val->v.string_val));
288 int_error(NO_CARET, "unknown type in real()");
291 return ((double) 0.0);
295 /* returns the imag part of val */
297 imag(struct value *val)
303 return (val->v.cmplx_val.imag);
304 #ifdef GP_STRING_VARS
306 /* This is where we end up if the user tries: */
307 /* x = 2; plot sprintf(format,x) */
308 int_warn(NO_CARET, "encountered a string when expecting a number");
309 int_error(NO_CARET, "Did you try to generate a file name using dummy variable x or y?");
312 int_error(NO_CARET, "unknown type in imag()");
315 return ((double) 0.0);
320 /* returns the magnitude of val */
322 magnitude(struct value *val)
326 return ((double) abs(val->v.int_val));
328 return (sqrt(val->v.cmplx_val.real *
329 val->v.cmplx_val.real +
330 val->v.cmplx_val.imag *
331 val->v.cmplx_val.imag));
333 int_error(NO_CARET, "unknown type in magnitude()");
336 return ((double) 0.0);
341 /* returns the angle of val */
343 angle(struct value *val)
347 return ((val->v.int_val >= 0) ? 0.0 : M_PI);
349 if (val->v.cmplx_val.imag == 0.0) {
350 if (val->v.cmplx_val.real >= 0.0)
355 return (atan2(val->v.cmplx_val.imag,
356 val->v.cmplx_val.real));
358 int_error(NO_CARET, "unknown type in angle()");
361 return ((double) 0.0);
366 Gcomplex(struct value *a, double realpart, double imagpart)
369 a->v.cmplx_val.real = realpart;
370 a->v.cmplx_val.imag = imagpart;
376 Ginteger(struct value *a, int i)
383 #ifdef GP_STRING_VARS
385 Gstring(struct value *a, char *s)
393 /* It is always safe to call gpfree_string with a->type is INTGR or CMPLX.
394 * However it would be fatal to call it with a->type = STRING if a->string_val
395 * was not obtained by a previous call to gp_alloc(), or has already been freed.
396 * Thus 'a->type' is set to INTGR afterwards to make subsequent calls safe.
399 gpfree_string(struct value *a)
401 #ifdef GP_STRING_VARS
402 if (a->type == STRING) {
403 free(a->v.string_val);
404 /* I would have set it to INVALID if such a type existed */
411 /* some machines have trouble with exp(-x) for large x
412 * if E_MINEXP is defined at compile time, use gp_exp(x) instead,
413 * which returns 0 for exp(x) with x < E_MINEXP
414 * exp(x) will already have been defined as gp_exp(x) in plot.h
421 return (x < (E_MINEXP)) ? 0.0 : exp(x);
423 int old_errno = errno;
424 double result = exp(x);
426 /* exp(-large) quite uselessly raises ERANGE --- stop that */
430 #endif /* E_MINEXP */
442 { /* make sure stack's empty */
445 warning: internal error--stack not empty!\n\
446 (function called with too many parameters?)\n");
459 int_error(NO_CARET, "stack underflow (function call with missing parameters?)");
464 #if (GP_STRING_VARS > 1)
466 * Allow autoconversion of string variables to floats if they
467 * are dereferenced in a numeric context.
470 pop_or_convert_from_string(struct value *v)
473 if (v->type == STRING) {
474 double d = atof(v->v.string_val);
477 FPRINTF((stderr,"converted string to CMPLX value %g\n",real(v)));
484 push(struct value *x)
486 if (s_p == STACK_DEPTH - 1)
487 int_error(NO_CARET, "stack overflow");
489 #ifdef GP_STRING_VARS
490 /* WARNING - This is a memory leak if the string is not later freed */
491 if (x->type == STRING && x->v.string_val)
492 stack[s_p].v.string_val = gp_strdup(x->v.string_val);
498 int_check(struct value *v)
500 if (v->type != INTGR)
501 int_error(NO_CARET, "non-integer passed to boolean operator");
506 /* Internal operators of the stack-machine, not directly represented
507 * by any user-visible operator, or using private status variables
510 /* converts top-of-stack to boolean */
512 f_bool(union argument *x)
514 (void) x; /* avoid -Wunused warning */
516 int_check(&top_of_stack);
517 top_of_stack.v.int_val = !!top_of_stack.v.int_val;
522 f_jump(union argument *x)
524 (void) x; /* avoid -Wunused warning */
525 jump_offset = x->j_arg;
530 f_jumpz(union argument *x)
534 (void) x; /* avoid -Wunused warning */
535 int_check(&top_of_stack);
536 if (top_of_stack.v.int_val) { /* non-zero --> no jump*/
539 jump_offset = x->j_arg; /* leave the argument on TOS */
544 f_jumpnz(union argument *x)
548 (void) x; /* avoid -Wunused warning */
549 int_check(&top_of_stack);
550 if (top_of_stack.v.int_val) /* non-zero */
551 jump_offset = x->j_arg; /* leave the argument on TOS */
558 f_jtern(union argument *x)
562 (void) x; /* avoid -Wunused warning */
565 jump_offset = x->j_arg; /* go jump to FALSE code */
568 /* This is the heart of the expression evaluation module: the stack
569 program execution loop.
571 'ft' is a table containing C functions within this program.
573 An 'action_table' contains pointers to these functions and
574 arguments to be passed to them.
576 at_ptr is a pointer to the action table which must be executed
579 so the iterated line exectues the function indexed by the at_ptr
580 and passes the address of the argument which is pointed to by the
586 execute_at(struct at_type *at_ptr)
588 int instruction_index, operator, count;
589 int saved_jump_offset = jump_offset;
591 count = at_ptr->a_count;
592 for (instruction_index = 0; instruction_index < count;) {
593 operator = (int) at_ptr->actions[instruction_index].index;
594 jump_offset = 1; /* jump operators can modify this */
595 (*ft[operator].func) (&(at_ptr->actions[instruction_index].arg));
596 assert(is_jump(operator) || (jump_offset == 1));
597 instruction_index += jump_offset;
600 jump_offset = saved_jump_offset;
603 /* 20010724: moved here from parse.c, where it didn't belong */
605 evaluate_at(struct at_type *at_ptr, struct value *val_ptr)
614 if (SETJMP(fpe_env, 1))
615 return; /* just bail out */
616 (void) signal(SIGFPE, (sigfunc) fpe);
622 (void) signal(SIGFPE, SIG_DFL);
625 if (errno == EDOM || errno == ERANGE) {
627 } else if (!undefined) { /* undefined (but not errno) may have been set by matherr */
630 /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
631 #if (GP_STRING_VARS > 1)
632 if (val_ptr->type != STRING)
634 temp = real(val_ptr);
635 if (temp > VERYLARGE || temp < -VERYLARGE) {
639 #if defined(NeXT) || defined(ultrix)
641 * linux was able to fit curves which NeXT gave up on -- traced it to
642 * silently returning NaN for the undefined cases and plowing ahead
643 * I can force that behavior this way. (0.0/0.0 generates NaN)
645 if (undefined && (errno == EDOM || errno == ERANGE)) { /* corey@cac */
648 Gcomplex(val_ptr, 0.0 / 0.0, 0.0 / 0.0);
650 #endif /* NeXT || ultrix */
655 free_at(struct at_type *at_ptr)
657 #ifdef GP_STRING_VARS
659 /* All string constants belonging to this action table have to be
660 * freed before destruction. */
663 for(i=0; i<at_ptr->a_count; i++) {
664 struct at_entry *a = &(at_ptr->actions[i]);
665 /* if union a->arg is used as a->arg.v_arg free potential string */
666 if ( a->index == PUSHC || a->index == DOLLARS )
667 gpfree_string(&(a->arg.v_arg));
673 /* EAM July 2003 - Return pointer to udv with this name; if the key does not
674 * match any existing udv names, create a new one and return a pointer to it.
677 add_udv_by_name(char *key)
679 struct udvt_entry **udv_ptr = &first_udv;
681 /* check if it's already in the table... */
684 if (!strcmp(key, (*udv_ptr)->udv_name))
686 udv_ptr = &((*udv_ptr)->next_udv);
689 *udv_ptr = (struct udvt_entry *)
690 gp_alloc(sizeof(struct udvt_entry), "value");
691 (*udv_ptr)->next_udv = NULL;
692 (*udv_ptr)->udv_name = gp_strdup(key);
693 (*udv_ptr)->udv_undef = TRUE;
694 (*udv_ptr)->udv_value.type = 0;
699 static void fill_gpval_axis __PROTO((AXIS_INDEX axis));
700 static void set_gpval_axis_sth_double __PROTO((const char *prefix, AXIS_INDEX axis, const char *suffix, double value, int is_int));
701 static void fill_gpval_string __PROTO((char *var, const char *value));
704 set_gpval_axis_sth_double(const char *prefix, AXIS_INDEX axis, const char *suffix, double value, int is_int)
706 struct udvt_entry *v;
708 sprintf(s, "%s_%s_%s", prefix, axis_defaults[axis].name, suffix);
709 for (cc=s; *cc; cc++) *cc = toupper(*cc); /* make the name uppercase */
710 v = add_udv_by_name(s);
711 if (!v) return; /* should not happen */
712 v->udv_undef = FALSE;
714 Ginteger(&v->udv_value, (int)(value+0.5));
716 Gcomplex(&v->udv_value, value, 0);
720 fill_gpval_axis(AXIS_INDEX axis)
722 const char *prefix = "GPVAL";
723 #define A axis_array[axis]
724 double a = AXIS_DE_LOG_VALUE(axis, A.min); /* FIXME GPVAL: This should be replaced by a = A.real_min and */
725 double b = AXIS_DE_LOG_VALUE(axis, A.max); /* FIXME GPVAL: b = A.real_max when true (delogged) min/max range values are implemented in the axis structure */
726 set_gpval_axis_sth_double(prefix, axis, "MIN", ((a < b) ? a : b), 0);
727 set_gpval_axis_sth_double(prefix, axis, "MAX", ((a < b) ? b : a), 0);
728 set_gpval_axis_sth_double(prefix, axis, "REVERSE", (A.range_flags & RANGE_REVERSE), 1);
729 set_gpval_axis_sth_double(prefix, axis, "LOG", A.base, 0);
732 if (axis == T_AXIS) axis = COLOR_AXIS; /* T axis is never drawn; colorbar is. */
733 set_gpval_axis_sth_double("GPVAL_DATA", axis, "MIN", AXIS_DE_LOG_VALUE(axis, A.data_min), 0);
734 set_gpval_axis_sth_double("GPVAL_DATA", axis, "MAX", AXIS_DE_LOG_VALUE(axis, A.data_max), 0);
740 fill_gpval_string(char *var, const char *stringvalue)
742 #ifdef GP_STRING_VARS
743 struct udvt_entry *v = add_udv_by_name(var);
746 if (v->udv_undef == FALSE && !strcmp(v->udv_value.v.string_val, stringvalue))
749 v->udv_undef = FALSE;
751 gpfree_string(&v->udv_value);
752 Gstring(&v->udv_value, gp_strdup(stringvalue));
757 * Put all the handling for GPVAL_* variables in this one routine.
758 * We call it from one of several contexts:
759 * 0: following a successful set/unset command
760 * 1: following a successful plot/splot
761 * 2: following an unsuccessful command (int_error)
765 update_gpval_variables(int context)
768 /* These values may change during a plot command due to auto range */
770 fill_gpval_axis(FIRST_X_AXIS);
771 fill_gpval_axis(FIRST_Y_AXIS);
772 fill_gpval_axis(SECOND_X_AXIS);
773 fill_gpval_axis(SECOND_Y_AXIS);
774 fill_gpval_axis(FIRST_Z_AXIS);
775 fill_gpval_axis(COLOR_AXIS);
776 fill_gpval_axis(T_AXIS);
777 fill_gpval_axis(U_AXIS);
778 fill_gpval_axis(V_AXIS);
782 /* These are set every time, which is kind of silly because they */
783 /* only change after 'set term' 'set output' ... */
785 /* FIXME! This preventa a segfault if term==NULL, which can */
786 /* happen if set_terminal() exits via int_error(). */
788 fill_gpval_string("GPVAL_TERM", "unknown");
790 fill_gpval_string("GPVAL_TERM", (char *)(term->name));
792 fill_gpval_string("GPVAL_TERMOPTIONS", term_options);
793 fill_gpval_string("GPVAL_OUTPUT", (outstr) ? outstr : "");
796 /* These initializations need only be done once, on program entry */
798 struct udvt_entry *v = add_udv_by_name("GPVAL_VERSION");
799 if (v && v->udv_undef == TRUE) {
800 v->udv_undef = FALSE;
801 Gcomplex(&v->udv_value, atof(gnuplot_version), 0);
803 v = add_udv_by_name("GPVAL_PATCHLEVEL");
804 if (v && v->udv_undef == TRUE) {
805 #ifdef GP_STRING_VARS
806 fill_gpval_string("GPVAL_PATCHLEVEL", gnuplot_patchlevel);
808 v->udv_undef = FALSE;
809 Ginteger(&v->udv_value, atoi(gnuplot_patchlevel));
812 v = add_udv_by_name("GPVAL_COMPILE_OPTIONS");
813 if (v && v->udv_undef == TRUE)
814 fill_gpval_string("GPVAL_COMPILE_OPTIONS", compile_options);
816 /* Permanent copy of user-clobberable variables pi and NaN */
817 v = add_udv_by_name("GPVAL_pi");
818 v->udv_undef = FALSE;
819 Gcomplex(&v->udv_value, M_PI, 0);
821 v = add_udv_by_name("GPVAL_NaN");
822 v->udv_undef = FALSE;
823 Gcomplex(&v->udv_value, atof("NaN"), 0);