Get rid of static vars in expr-opt.c.
[pspp-builds.git] / src / expr-opt.c
index 8724b9e017ec58482d7fba2c466e29fb5034581a..4c8fc7e12c87a44f7c777b5e05eb8dc2149bd1b0 100644 (file)
    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"
@@ -145,7 +145,7 @@ optimize_tree (struct nonterm_node * n)
       int nvar = 0;
 
       /* New node. */
-      struct nonterm_node *m;
+      struct nonterm_node *m = NULL;
 
       /* Argument copying counter. */
       int c;
@@ -171,7 +171,7 @@ optimize_tree (struct nonterm_node * n)
 
       /* 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))
        {
@@ -197,7 +197,7 @@ optimize_tree (struct nonterm_node * n)
        {
          /* 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)
@@ -205,7 +205,7 @@ optimize_tree (struct nonterm_node * n)
            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;
@@ -223,7 +223,7 @@ optimize_tree (struct nonterm_node * n)
     {
       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];
 
@@ -231,7 +231,7 @@ optimize_tree (struct nonterm_node * n)
              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;
@@ -285,7 +285,7 @@ evaluate_tree (struct nonterm_node * n)
       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);
@@ -316,22 +316,22 @@ evaluate_tree (struct nonterm_node * n)
       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. */
@@ -413,7 +413,7 @@ evaluate_tree (struct nonterm_node * n)
          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;
@@ -518,7 +518,7 @@ evaluate_tree (struct nonterm_node * n)
              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;
@@ -768,7 +768,7 @@ evaluate_tree (struct nonterm_node * n)
     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)
@@ -778,7 +778,6 @@ evaluate_tree (struct nonterm_node * n)
                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];
@@ -834,6 +833,7 @@ evaluate_tree (struct nonterm_node * n)
        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);
       }
@@ -865,15 +865,15 @@ evaluate_tree (struct nonterm_node * n)
       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)
        {
@@ -976,41 +976,43 @@ yrmoda (double year, double month, double day)
 \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];
@@ -1021,33 +1023,27 @@ dump_expression (union any_node * n, struct expression * expr)
        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;
     }
@@ -1055,82 +1051,85 @@ dump_node (union any_node * n)
     {
       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;
 }