#ifndef lint
static char *RCSid() { return RCSid("$Id: eval.c,v 1.9 1999/11/08 19:24:28 lhecking Exp $"); }
#endif
/* GNUPLOT - eval.c */
/*[
* Copyright 1986 - 1993, 1998 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 complete modified source code. Modifications are to
* be distributed as patches to the released version. Permission to
* distribute binaries produced by compiling modified sources is granted,
* provided you
* 1. distribute the corresponding source modifications from the
* released version in the form of a patch file along with the binaries,
* 2. add special version identification to distinguish your version
* in addition to the base release version number,
* 3. provide your name and address as the primary contact for the
* support of your modified version, and
* 4. retain our contact information in regard to use of the base
* software.
* Permission to distribute the released version of the source code along
* with corresponding source modifications in the form of a patch file is
* granted with same provisions 2 through 4 for binary distributions.
*
* This software is provided "as is" without express or implied warranty
* to the extent permitted by applicable law.
]*/
#include "eval.h"
#include "alloc.h"
#include "datafile.h"
#include "internal.h"
#include "parse.h"
#include "specfun.h"
#include "standard.h"
#include "util.h"
/* HBB 990829: the following was moved here, from plot.c, where it
* wasn't used, anyway... */
struct udvt_entry udv_pi = { NULL, "pi", FALSE, {INTGR, {0} } };
/* first in linked list */
struct udvt_entry *first_udv = &udv_pi;
struct udft_entry *first_udf = NULL;
/* The table of built-in functions */
struct ft_entry GPFAR ft[] =
{
/* internal functions: */
{"push", (FUNC_PTR) f_push},
{"pushc", (FUNC_PTR) f_pushc},
{"pushd1", (FUNC_PTR) f_pushd1},
{"pushd2", (FUNC_PTR) f_pushd2},
{"pushd", (FUNC_PTR) f_pushd},
{"call", (FUNC_PTR) f_call},
{"calln", (FUNC_PTR) f_calln},
{"lnot", (FUNC_PTR) f_lnot},
{"bnot", (FUNC_PTR) f_bnot},
{"uminus", (FUNC_PTR) f_uminus},
{"lor", (FUNC_PTR) f_lor},
{"land", (FUNC_PTR) f_land},
{"bor", (FUNC_PTR) f_bor},
{"xor", (FUNC_PTR) f_xor},
{"band", (FUNC_PTR) f_band},
{"eq", (FUNC_PTR) f_eq},
{"ne", (FUNC_PTR) f_ne},
{"gt", (FUNC_PTR) f_gt},
{"lt", (FUNC_PTR) f_lt},
{"ge", (FUNC_PTR) f_ge},
{"le", (FUNC_PTR) f_le},
{"plus", (FUNC_PTR) f_plus},
{"minus", (FUNC_PTR) f_minus},
{"mult", (FUNC_PTR) f_mult},
{"div", (FUNC_PTR) f_div},
{"mod", (FUNC_PTR) f_mod},
{"power", (FUNC_PTR) f_power},
{"factorial", (FUNC_PTR) f_factorial},
{"bool", (FUNC_PTR) f_bool},
{"dollars", (FUNC_PTR) f_dollars}, /* for using extension */
{"jump", (FUNC_PTR) f_jump},
{"jumpz", (FUNC_PTR) f_jumpz},
{"jumpnz", (FUNC_PTR) f_jumpnz},
{"jtern", (FUNC_PTR) f_jtern},
/* standard functions: */
{"real", (FUNC_PTR) f_real},
{"imag", (FUNC_PTR) f_imag},
{"arg", (FUNC_PTR) f_arg},
{"conjg", (FUNC_PTR) f_conjg},
{"sin", (FUNC_PTR) f_sin},
{"cos", (FUNC_PTR) f_cos},
{"tan", (FUNC_PTR) f_tan},
{"asin", (FUNC_PTR) f_asin},
{"acos", (FUNC_PTR) f_acos},
{"atan", (FUNC_PTR) f_atan},
{"atan2", (FUNC_PTR) f_atan2},
{"sinh", (FUNC_PTR) f_sinh},
{"cosh", (FUNC_PTR) f_cosh},
{"tanh", (FUNC_PTR) f_tanh},
{"int", (FUNC_PTR) f_int},
{"abs", (FUNC_PTR) f_abs},
{"sgn", (FUNC_PTR) f_sgn},
{"sqrt", (FUNC_PTR) f_sqrt},
{"exp", (FUNC_PTR) f_exp},
{"log10", (FUNC_PTR) f_log10},
{"log", (FUNC_PTR) f_log},
{"besj0", (FUNC_PTR) f_besj0},
{"besj1", (FUNC_PTR) f_besj1},
{"besy0", (FUNC_PTR) f_besy0},
{"besy1", (FUNC_PTR) f_besy1},
{"erf", (FUNC_PTR) f_erf},
{"erfc", (FUNC_PTR) f_erfc},
{"gamma", (FUNC_PTR) f_gamma},
{"lgamma", (FUNC_PTR) f_lgamma},
{"ibeta", (FUNC_PTR) f_ibeta},
{"igamma", (FUNC_PTR) f_igamma},
{"rand", (FUNC_PTR) f_rand},
{"floor", (FUNC_PTR) f_floor},
{"ceil", (FUNC_PTR) f_ceil},
{"norm", (FUNC_PTR) f_normal}, /* XXX-JG */
{"inverf", (FUNC_PTR) f_inverse_erf}, /* XXX-JG */
{"invnorm", (FUNC_PTR) f_inverse_normal}, /* XXX-JG */
{"asinh", (FUNC_PTR) f_asinh},
{"acosh", (FUNC_PTR) f_acosh},
{"atanh", (FUNC_PTR) f_atanh},
{"column", (FUNC_PTR) f_column}, /* for using */
{"valid", (FUNC_PTR) f_valid}, /* for using */
{"timecolumn", (FUNC_PTR) f_timecolumn}, /* for using */
{"tm_sec", (FUNC_PTR) f_tmsec}, /* for timeseries */
{"tm_min", (FUNC_PTR) f_tmmin}, /* for timeseries */
{"tm_hour", (FUNC_PTR) f_tmhour}, /* for timeseries */
{"tm_mday", (FUNC_PTR) f_tmmday}, /* for timeseries */
{"tm_mon", (FUNC_PTR) f_tmmon}, /* for timeseries */
{"tm_year", (FUNC_PTR) f_tmyear}, /* for timeseries */
{"tm_wday", (FUNC_PTR) f_tmwday}, /* for timeseries */
{"tm_yday", (FUNC_PTR) f_tmyday}, /* for timeseries */
{NULL, NULL}
};
struct udvt_entry *
add_udv(t_num) /* find or add value and return pointer */
int t_num;
{
register struct udvt_entry **udv_ptr = &first_udv;
/* check if it's already in the table... */
while (*udv_ptr) {
if (equals(t_num, (*udv_ptr)->udv_name))
return (*udv_ptr);
udv_ptr = &((*udv_ptr)->next_udv);
}
*udv_ptr = (struct udvt_entry *)
gp_alloc(sizeof(struct udvt_entry), "value");
(*udv_ptr)->next_udv = NULL;
(*udv_ptr)->udv_name = gp_alloc (token_len(t_num)+1, "user var");
copy_str((*udv_ptr)->udv_name, t_num, token_len(t_num)+1);
(*udv_ptr)->udv_value.type = INTGR; /* not necessary, but safe! */
(*udv_ptr)->udv_undef = TRUE;
return (*udv_ptr);
}
struct udft_entry *
add_udf(t_num) /* find or add function and return pointer */
int t_num; /* index to token[] */
{
register struct udft_entry **udf_ptr = &first_udf;
int i;
while (*udf_ptr) {
if (equals(t_num, (*udf_ptr)->udf_name))
return (*udf_ptr);
udf_ptr = &((*udf_ptr)->next_udf);
}
/* get here => not found. udf_ptr points at first_udf or
* next_udf field of last udf
*/
if (standard(t_num))
int_warn(t_num, "Warning : udf shadowed by built-in function of the same name");
/* create and return a new udf slot */
*udf_ptr = (struct udft_entry *)
gp_alloc(sizeof(struct udft_entry), "function");
(*udf_ptr)->next_udf = (struct udft_entry *) NULL;
(*udf_ptr)->definition = NULL;
(*udf_ptr)->at = NULL;
(*udf_ptr)->udf_name = gp_alloc (token_len(t_num)+1, "user func");
copy_str((*udf_ptr)->udf_name, t_num, token_len(t_num)+1);
for (i = 0; i < MAX_NUM_VAR; i++)
(void) Ginteger(&((*udf_ptr)->dummy_values[i]), 0);
return (*udf_ptr);
}
int
standard(t_num) /* return standard function index or 0 */
int t_num;
{
register int i;
for (i = (int) SF_START; ft[i].f_name != NULL; i++) {
if (equals(t_num, ft[i].f_name))
return (i);
}
return (0);
}
void
execute_at(at_ptr)
struct at_type *at_ptr;
{
register int i, index, count, offset;
count = at_ptr->a_count;
for (i = 0; i < count;) {
index = (int) at_ptr->actions[i].index;
offset = (*ft[index].func) (&(at_ptr->actions[i].arg));
if (is_jump(index))
i += offset;
else
i++;
}
}
/*
'ft' is a table containing C functions within this program.
An 'action_table' contains pointers to these functions and arguments to be
passed to them.
at_ptr is a pointer to the action table which must be executed (evaluated)
so the iterated line exectues the function indexed by the at_ptr and
passes the address of the argument which is pointed to by the arg_ptr
*/