02111-1307, USA. */
#include <config.h>
+#include "expr.h"
+#include "exprP.h"
#include <assert.h>
#include <math.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "alloc.h"
-#include "approx.h"
#include "data-in.h"
#include "error.h"
-#include "expr.h"
-#include "exprP.h"
#include "julcal/julcal.h"
#include "misc.h"
+#include "pool.h"
#include "stats.h"
#include "str.h"
#include "var.h"
int nvar = 0;
/* New node. */
- struct nonterm_node *m;
+ struct nonterm_node *m = NULL;
/* Argument copying counter. */
int c;
/* 0*SYSMIS=0, 0/SYSMIS=0; otherwise, SYSMIS and infinities
produce SYSMIS. */
- if (approx_eq (cval, 0.0) && n->type == OP_MUL)
+ if (cval == 0.0 && n->type == OP_MUL)
nvar = 0;
else if (sysmis || !finite (cval))
{
{
/* Otherwise consolidate all the nonconstant terms. */
m = xmalloc (sizeof (struct nonterm_node)
- + ((nvar + approx_ne (cval, def) - 1)
+ + ((nvar + (cval != def) - 1)
* sizeof (union any_node *)));
for (i = c = 0; i < n->n; i++)
if (n->arg[i]->type != OP_NUM_CON)
else
free_node (n->arg[i]);
- if (approx_ne (cval, def))
+ if (cval != def)
{
m->arg[c] = xmalloc (sizeof (struct num_con_node));
m->arg[c]->num_con.type = OP_NUM_CON;
{
if (n->arg[1]->type == OP_NUM_CON)
{
- if (approx_eq (n1, 1.0))
+ if (n1 == 1.0)
{
struct nonterm_node *m = (struct nonterm_node *) n->arg[0];
free (n);
return m;
}
- else if (approx_eq (n1, 2.0))
+ else if (n1 == 2.0)
{
n = xrealloc (n, sizeof (struct nonterm_node));
n->type = OP_SQUARE;
return optimize_tree (n);
case OP_POW:
- if (approx_eq (n0, 0.0) && approx_eq (n1, 0.0))
+ if (n0 == 0.0 && n1 == 0.0)
frnc (SYSMIS);
else if (n0 == SYSMIS && n1 == 0.0)
frnc (1.0);
break;
case OP_EQ:
- rnc (approx_eq (n0, n1));
+ rnc (n0 == n1);
break;
case OP_GE:
- rnc (approx_ge (n0, n1));
+ rnc (n0 >= n1);
break;
case OP_GT:
- rnc (approx_gt (n0, n1));
+ rnc (n0 > n1);
break;
case OP_LE:
- rnc (approx_le (n0, n1));
+ rnc (n0 <= n1);
break;
case OP_LT:
- rnc (approx_lt (n0, n1));
+ rnc (n0 < n1);
break;
case OP_NE:
- rnc (approx_ne (n0, n1));
+ rnc (n0 != n1);
break;
/* String operators. */
for (i = 1; i < n->n; i++)
{
ni = n->arg[i]->num_con.value;
- if (approx_eq (n0, ni))
+ if (n0 == ni)
{
frnc (1.0);
goto any_done;
if (min == SYSMIS || max == SYSMIS)
continue;
sysmis = 0;
- if (approx_ge (n0, min) && approx_le (n0, max))
+ if (n0 >= min && n0 <= max)
{
frnc (1.0);
goto range_done;
case OP_RTRIM:
case OP_RTRIM_OPT:
{
- int c;
+ int c = ' ';
char *cp = s0;
if (n->type == OP_LTRIM_OPT || n->type == OP_RTRIM_OPT)
c = n->type == OP_LTRIM_OPT ? 'L' : 'R';
msg (SE, _("Second argument to %cTRIM() must be at least one "
"character in length."), c);
- c = ' ';
}
else
c = s1[0];
f.d = (int) n->arg[3];
v.f = n0;
+ assert ((formats[f.type].cat & FCAT_STRING) == 0);
data_out (strbuf, &f, &v);
n = repl_str_con (n, strbuf, f.w);
}
rnc (1.0 / n0);
break;
case OP_MOD:
- if (approx_eq (n0, 0.0) && n1 == SYSMIS)
+ if (n0 == 0.0 && n1 == SYSMIS)
frnc (0.0);
else
rnc (fmod (n0, n1));
break;
case OP_NUM_TO_BOOL:
- if (approx_eq (n0, 0.0))
+ if (n0 == 0.0)
n0 = 0.0;
- else if (approx_eq (n0, 1.0))
+ else if (n0 == 1.0)
n0 = 1.0;
else if (n0 != SYSMIS)
{
\f
/* Expression dumper. */
-static struct expression *e;
-static int nop, mop;
-static int ndbl, mdbl;
-static int nstr, mstr;
-static int nvars, mvars;
-
-static void dump_node (union any_node * n);
-static void emit (int);
-static void emit_num_con (double);
-static void emit_str_con (char *, int);
-static void emit_var (struct variable *);
+struct expr_dump_state
+ {
+ struct expression *expr; /* Output expression. */
+ int op_cnt, op_cap; /* Number of ops, allocated space. */
+ int dbl_cnt, dbl_cap; /* Number of doubles, allocated space. */
+ int str_cnt, str_cap; /* Number of strings, allocated space. */
+ int var_cnt, var_cap; /* Number of variables, allocated space. */
+ };
+
+static void dump_node (struct expr_dump_state *, union any_node * n);
+static void emit (struct expr_dump_state *, int);
+static void emit_num_con (struct expr_dump_state *, double);
+static void emit_str_con (struct expr_dump_state *, char *, int);
+static void emit_var (struct expr_dump_state *, struct variable *);
void
dump_expression (union any_node * n, struct expression * expr)
{
+ struct expr_dump_state eds;
unsigned char *o;
-
int height = 0;
-
int max_height = 0;
- e = expr;
- e->op = NULL;
- e->num = NULL;
- e->str = NULL;
- e->var = NULL;
- nop = mop = 0;
- ndbl = mdbl = 0;
- nstr = mstr = 0;
- nvars = mvars = 0;
- dump_node (n);
- emit (OP_SENTINEL);
+ expr->op = NULL;
+ expr->num = NULL;
+ expr->str = NULL;
+ expr->var = NULL;
+ eds.expr = expr;
+ eds.op_cnt = eds.op_cap = 0;
+ eds.dbl_cnt = eds.dbl_cap = 0;
+ eds.str_cnt = eds.str_cap = 0;
+ eds.var_cnt = eds.var_cap = 0;
+ dump_node (&eds, n);
+ emit (&eds, OP_SENTINEL);
/* Now compute the stack height needed to evaluate the expression. */
- for (o = e->op; *o != OP_SENTINEL; o++)
+ for (o = expr->op; *o != OP_SENTINEL; o++)
{
if (ops[*o].flags & OP_VAR_ARGS)
height += 1 - o[1];
max_height = height;
}
- /* ANSI says we have to waste space for one `value' since pointers
- are not guaranteed to be able to point to a spot *before* a
- block. If only all the world were a VAX... */
+ /* We waste space for one `value' since pointers are not
+ guaranteed to be able to point to a spot before a block. */
max_height++;
- e->stack = xmalloc (max_height * sizeof *e->stack);
+ expr->stack = xmalloc (max_height * sizeof *expr->stack);
-#if PAGED_STACK
- e->str_stack = e->type == EX_STRING ? xmalloc (256) : NULL;
-#else
- e->str_stack = xmalloc (256);
- e->str_size = 256;
-#endif
+ expr->pool = pool_create ();
}
static void
-dump_node (union any_node * n)
+dump_node (struct expr_dump_state *eds, union any_node * n)
{
if (n->type == OP_AND || n->type == OP_OR)
{
int i;
- dump_node (n->nonterm.arg[0]);
+ dump_node (eds, n->nonterm.arg[0]);
for (i = 1; i < n->nonterm.n; i++)
{
- dump_node (n->nonterm.arg[i]);
- emit (n->type);
+ dump_node (eds, n->nonterm.arg[i]);
+ emit (eds, n->type);
}
return;
}
{
int i;
for (i = 0; i < n->nonterm.n; i++)
- dump_node (n->nonterm.arg[i]);
- emit (n->type);
+ dump_node (eds, n->nonterm.arg[i]);
+ emit (eds, n->type);
if (ops[n->type].flags & OP_VAR_ARGS)
- emit (n->nonterm.n);
+ emit (eds, n->nonterm.n);
if (ops[n->type].flags & OP_MIN_ARGS)
- emit ((int) n->nonterm.arg[n->nonterm.n]);
+ emit (eds, (int) n->nonterm.arg[n->nonterm.n]);
if (ops[n->type].flags & OP_FMT_SPEC)
{
- emit ((int) n->nonterm.arg[n->nonterm.n]);
- emit ((int) n->nonterm.arg[n->nonterm.n + 1]);
- emit ((int) n->nonterm.arg[n->nonterm.n + 2]);
+ emit (eds, (int) n->nonterm.arg[n->nonterm.n]);
+ emit (eds, (int) n->nonterm.arg[n->nonterm.n + 1]);
+ emit (eds, (int) n->nonterm.arg[n->nonterm.n + 2]);
}
return;
}
- emit (n->type);
+ emit (eds, n->type);
if (n->type == OP_NUM_CON)
- emit_num_con (n->num_con.value);
+ emit_num_con (eds, n->num_con.value);
else if (n->type == OP_STR_CON)
- emit_str_con (n->str_con.s, n->str_con.len);
+ emit_str_con (eds, n->str_con.s, n->str_con.len);
else if (n->type == OP_NUM_VAR || n->type == OP_STR_VAR
|| n->type == OP_STR_MIS)
- emit_var (n->var.v);
+ emit_var (eds, n->var.v);
else if (n->type == OP_NUM_LAG || n->type == OP_STR_LAG)
{
- emit_var (n->lag.v);
- emit (n->lag.lag);
+ emit_var (eds, n->lag.v);
+ emit (eds, n->lag.lag);
}
else if (n->type == OP_NUM_SYS || n->type == OP_NUM_VAL)
- emit (n->var.v->fv);
+ emit (eds, n->var.v->fv);
else
assert (n->type == OP_CASENUM);
}
static void
-emit (int op)
+emit (struct expr_dump_state *eds, int op)
{
- if (nop >= mop)
+ if (eds->op_cnt >= eds->op_cap)
{
- mop += 16;
- e->op = xrealloc (e->op, mop * sizeof *e->op);
+ eds->op_cap += 16;
+ eds->expr->op = xrealloc (eds->expr->op,
+ eds->op_cap * sizeof *eds->expr->op);
}
- e->op[nop++] = op;
+ eds->expr->op[eds->op_cnt++] = op;
}
static void
-emit_num_con (double dbl)
+emit_num_con (struct expr_dump_state *eds, double dbl)
{
- if (ndbl >= mdbl)
+ if (eds->dbl_cnt >= eds->dbl_cap)
{
- mdbl += 16;
- e->num = xrealloc (e->num, mdbl * sizeof *e->num);
+ eds->dbl_cap += 16;
+ eds->expr->num = xrealloc (eds->expr->num,
+ eds->dbl_cap * sizeof *eds->expr->num);
}
- e->num[ndbl++] = dbl;
+ eds->expr->num[eds->dbl_cnt++] = dbl;
}
static void
-emit_str_con (char *str, int len)
+emit_str_con (struct expr_dump_state *eds, char *str, int len)
{
- if (nstr + len + 1 > mstr)
+ if (eds->str_cnt + len + 1 > eds->str_cap)
{
- mstr += 256;
- e->str = xrealloc (e->str, mstr);
+ eds->str_cap += 256;
+ eds->expr->str = xrealloc (eds->expr->str, eds->str_cap);
}
- e->str[nstr++] = len;
- memcpy (&e->str[nstr], str, len);
- nstr += len;
+ eds->expr->str[eds->str_cnt++] = len;
+ memcpy (&eds->expr->str[eds->str_cnt], str, len);
+ eds->str_cnt += len;
}
static void
-emit_var (struct variable * v)
+emit_var (struct expr_dump_state *eds, struct variable * v)
{
- if (nvars >= mvars)
+ if (eds->var_cnt >= eds->var_cap)
{
- mvars += 16;
- e->var = xrealloc (e->var, mvars * sizeof *e->var);
+ eds->var_cap += 16;
+ eds->expr->var = xrealloc (eds->expr->var,
+ eds->var_cap * sizeof *eds->expr->var);
}
- e->var[nvars++] = v;
+ eds->expr->var[eds->var_cnt++] = v;
}