Adopt use of gnulib for portability.
[pspp-builds.git] / src / compute.c
index b08e76feddd9a62f2eb296312b147ab3961a06a9..6e6bd96ad18992c1b361b2d191825d6c0459ff7a 100644 (file)
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
-#include <assert.h>
+#include "error.h"
 #include <stdlib.h>
 #include "alloc.h"
+#include "case.h"
 #include "command.h"
+#include "dictionary.h"
 #include "error.h"
-#include "expr.h"
+#include "expressions/public.h"
 #include "lexer.h"
 #include "misc.h"
 #include "str.h"
 #include "var.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 struct compute_trns;
 struct lvalue;
 
@@ -110,10 +115,9 @@ compute_num (struct trns_header *compute_, struct ccase *c,
   struct compute_trns *compute = (struct compute_trns *) compute_;
 
   if (compute->test == NULL
-      || expr_evaluate (compute->test, c, case_num, NULL) == 1.0) 
-    {
-      expr_evaluate (compute->rvalue, c, case_num, &c->data[compute->fv]); 
-    }
+      || expr_evaluate_num (compute->test, c, case_num) == 1.0) 
+    case_data_rw (c, compute->fv)->f = expr_evaluate_num (compute->rvalue, c,
+                                                          case_num); 
   
   return -1;
 }
@@ -127,29 +131,26 @@ compute_num_vec (struct trns_header *compute_, struct ccase *c,
   struct compute_trns *compute = (struct compute_trns *) compute_;
 
   if (compute->test == NULL
-      || expr_evaluate (compute->test, c, case_num, NULL) == 1.0) 
+      || expr_evaluate_num (compute->test, c, case_num) == 1.0) 
     {
-      /* Index into the vector. */
-      union value index;
-
-      /* Rounded index value. */
-      int rindx;
+      double index;     /* Index into the vector. */
+      int rindx;        /* Rounded index value. */
 
-      expr_evaluate (compute->element, c, case_num, &index);
-      rindx = floor (index.f + EPSILON);
-      if (index.f == SYSMIS || rindx < 1 || rindx > compute->vector->cnt)
+      index = expr_evaluate_num (compute->element, c, case_num);
+      rindx = floor (index + EPSILON);
+      if (index == SYSMIS || rindx < 1 || rindx > compute->vector->cnt)
         {
-          if (index.f == SYSMIS)
+          if (index == SYSMIS)
             msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
                        "an index into vector %s."), compute->vector->name);
           else
             msg (SW, _("When executing COMPUTE: %g is not a valid value as "
                        "an index into vector %s."),
-                 index.f, compute->vector->name);
+                 index, compute->vector->name);
           return -1;
         }
-      expr_evaluate (compute->rvalue, c, case_num,
-                     &c->data[compute->vector->var[rindx - 1]->fv]); 
+      case_data_rw (c, compute->vector->var[rindx - 1]->fv)->f
+        = expr_evaluate_num (compute->rvalue, c, case_num);
     }
   
   return -1;
@@ -163,15 +164,9 @@ compute_str (struct trns_header *compute_, struct ccase *c,
   struct compute_trns *compute = (struct compute_trns *) compute_;
 
   if (compute->test == NULL
-      || expr_evaluate (compute->test, c, case_num, NULL) == 1.0) 
-    {
-      /* Temporary storage for string expression return value. */
-      union value v;
-
-      expr_evaluate (compute->rvalue, c, case_num, &v);
-      st_bare_pad_len_copy (c->data[compute->fv].s, &v.c[1], compute->width,
-                            v.c[0]); 
-    }
+      || expr_evaluate_num (compute->test, c, case_num) == 1.0) 
+    expr_evaluate_str (compute->rvalue, c, case_num,
+                       case_data_rw (c, compute->fv)->s, compute->width);
   
   return -1;
 }
@@ -185,38 +180,32 @@ compute_str_vec (struct trns_header *compute_, struct ccase *c,
   struct compute_trns *compute = (struct compute_trns *) compute_;
 
   if (compute->test == NULL
-      || expr_evaluate (compute->test, c, case_num, NULL) == 1.0) 
+      || expr_evaluate_num (compute->test, c, case_num) == 1.0) 
     {
-      /* Temporary storage for string expression return value. */
-      union value v;
-
-      /* Index into the vector. */
-      union value index;
+      double index;             /* Index into the vector. */
+      int rindx;                /* Rounded index value. */
+      struct variable *vr;      /* Variable reference by indexed vector. */
 
-      /* Rounded index value. */
-      int rindx;
-
-      /* Variable reference by indexed vector. */
-      struct variable *vr;
-
-      expr_evaluate (compute->element, c, case_num, &index);
-      rindx = floor (index.f + EPSILON);
-      if (index.f == SYSMIS || rindx < 1 || rindx > compute->vector->cnt)
+      index = expr_evaluate_num (compute->element, c, case_num);
+      rindx = floor (index + EPSILON);
+      if (index == SYSMIS) 
         {
-          if (index.f == SYSMIS)
-            msg (SW, _("When executing COMPUTE: SYSMIS is not a valid "
-                       "value as an index into vector %s."),
-                 compute->vector->name);
-          else
-            msg (SW, _("When executing COMPUTE: %g is not a valid value as "
-                       "an index into vector %s."),
-                 index.f, compute->vector->name);
+          msg (SW, _("When executing COMPUTE: SYSMIS is not a valid "
+                     "value as an index into vector %s."),
+               compute->vector->name);
+          return -1; 
+        }
+      else if (rindx < 1 || rindx > compute->vector->cnt)
+        {
+          msg (SW, _("When executing COMPUTE: %g is not a valid value as "
+                     "an index into vector %s."),
+               index, compute->vector->name);
           return -1;
         }
 
-      expr_evaluate (compute->rvalue, c, case_num, &v);
       vr = compute->vector->var[rindx - 1];
-      st_bare_pad_len_copy (c->data[vr->fv].s, &v.c[1], vr->width, v.c[0]); 
+      expr_evaluate_str (compute->rvalue, c, case_num,
+                         case_data_rw (c, vr->fv)->s, vr->width);
     }
   
   return -1;
@@ -233,7 +222,7 @@ cmd_if (void)
   compute = compute_trns_create ();
 
   /* Test expression. */
-  compute->test = expr_parse (PXP_BOOLEAN);
+  compute->test = expr_parse (default_dict, EXPR_BOOLEAN);
   if (compute->test == NULL)
     goto fail;
 
@@ -276,7 +265,8 @@ parse_rvalue_expression (struct compute_trns *compute,
 
   assert (type == NUMERIC || type == ALPHA);
 
-  compute->rvalue = expr_parse (type == ALPHA ? PXP_STRING : PXP_NUMERIC);
+  compute->rvalue = expr_parse (default_dict,
+                                type == ALPHA ? EXPR_STRING : EXPR_NUMBER);
   if (compute->rvalue == NULL)
     return 0;
 
@@ -323,12 +313,12 @@ compute_trns_free (struct trns_header *compute_)
 /* COMPUTE or IF target variable or vector element. */
 struct lvalue
   {
-    char var_name[9];            /* Destination variable name, or "". */
+    char var_name[LONG_NAME_LEN + 1];   /* Destination variable name, or "". */
     const struct vector *vector; /* Destination vector, if any, or NULL. */
     struct expression *element;  /* Destination vector element, or NULL. */
   };
 
-/* Parses the target variable or vector elector into a new
+/* Parses the target variable or vector element into a new
    `struct lvalue', which is returned. */
 static struct lvalue *
 lvalue_parse (void) 
@@ -357,7 +347,7 @@ lvalue_parse (void)
       lex_get ();
       if (!lex_force_match ('('))
        goto lossage;
-      lvalue->element = expr_parse (PXP_NUMERIC);
+      lvalue->element = expr_parse (default_dict, EXPR_NUMBER);
       if (lvalue->element == NULL)
         goto lossage;
       if (!lex_force_match (')'))
@@ -366,8 +356,7 @@ lvalue_parse (void)
   else
     {
       /* Variable name. */
-      strncpy (lvalue->var_name, tokid, 8);
-      lvalue->var_name[8] = '\0';
+      str_copy_trunc (lvalue->var_name, sizeof lvalue->var_name, tokid);
       lex_get ();
     }
   return lvalue;
@@ -384,8 +373,7 @@ lvalue_get_type (const struct lvalue *lvalue)
 {
   if (lvalue->vector == NULL) 
     {
-      struct variable *var
-        = dict_lookup_var (default_dict, lvalue->var_name);
+      struct variable *var = dict_lookup_var (default_dict, lvalue->var_name);
       if (var == NULL)
         return NUMERIC;
       else
@@ -436,6 +424,9 @@ lvalue_finalize (struct lvalue *lvalue,
 static void 
 lvalue_destroy (struct lvalue *lvalue) 
 {
+  if ( ! lvalue ) 
+     return ;
+
   expr_free (lvalue->element);
   free (lvalue);
 }