pspp-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pspp-cvs] Changes to pspp/src/mis-val.c


From: Ben Pfaff
Subject: [Pspp-cvs] Changes to pspp/src/mis-val.c
Date: Sun, 07 Aug 2005 00:39:32 -0400

Index: pspp/src/mis-val.c
diff -u pspp/src/mis-val.c:1.11 pspp/src/mis-val.c:1.12
--- pspp/src/mis-val.c:1.11     Sun Jul 31 21:42:46 2005
+++ pspp/src/mis-val.c  Sun Aug  7 04:39:28 2005
@@ -21,6 +21,7 @@
 #include "error.h"
 #include <stdlib.h>
 #include "command.h"
+#include "data-in.h"
 #include "error.h"
 #include "lexer.h"
 #include "magic.h"
@@ -32,317 +33,180 @@
 
 #include "debug-print.h"
 
-/* Variables on MIS VAL. */
-static struct variable **v;
-static int nv;
-
-/* Type of the variables on MIS VAL. */
-static int type;
-
-/* Width of string variables on MIS VAL. */
-static size_t width;
-
-/* Items to fill-in var structs with. */
-static int miss_type;
-static union value missing[3];
-
-static int parse_varnames (void);
-static int parse_numeric (void);
-static int parse_alpha (void);
+static bool parse_number (double *, const struct fmt_spec *);
 
 int
 cmd_missing_values (void)
 {
-  int i;
+  struct variable **v;
+  int nv;
+
+  int retval = CMD_PART_SUCCESS_MAYBE;
+  bool deferred_errors = false;
 
   while (token != '.')
     {
-      if (!parse_varnames ())
-       goto fail;
+      int i;
+      
+
+      if (!parse_variables (default_dict, &v, &nv, PV_NONE)) 
+        goto done;
 
-      if (token != ')')
-       {
-         if ((type == NUMERIC && !parse_numeric ())
-             || (type == ALPHA && !parse_alpha ()))
-           goto fail;
-       }
-      else
-       miss_type = MISSING_NONE;
-
-      if (!lex_match (')'))
-       {
-         msg (SE, _("`)' expected after value specification."));
-         goto fail;
-       }
+      if (!lex_match ('('))
+        {
+          lex_error (_("expecting `('"));
+          goto done;
+        }
 
       for (i = 0; i < nv; i++)
-       {
-         v[i]->miss_type = miss_type;
-         memcpy (v[i]->missing, missing, sizeof v[i]->missing);
-       }
+        mv_init (&v[i]->miss, v[i]->width);
+
+      if (!lex_match (')')) 
+        {
+          struct missing_values mv;
+
+          for (i = 0; i < nv; i++)
+            if (v[i]->type != v[0]->type)
+              {
+                const struct variable *n = v[0]->type == NUMERIC ? v[0] : v[i];
+                const struct variable *s = v[0]->type == NUMERIC ? v[i] : v[0];
+                msg (SE, _("Cannot mix numeric variables (e.g. %s) and "
+                           "string variables (e.g. %s) within a single list."),
+                     n->name, s->name);
+                goto done;
+              }
+
+          if (v[0]->type == NUMERIC) 
+            {
+              mv_init (&mv, 0);
+              while (!lex_match (')'))
+                {
+                  double x;
+
+                  if (lex_match_id ("LO") || lex_match_id ("LOWEST"))
+                    x = LOWEST;
+                  else if (!parse_number (&x, &v[0]->print))
+                    goto done;
+
+                  if (lex_match_id ("THRU")) 
+                    {
+                      double y;
+                      
+                      if (lex_match_id ("HI") || lex_match_id ("HIGHEST"))
+                        y = HIGHEST;
+                      else if (!parse_number (&y, &v[0]->print))
+                        goto done;
+
+                      if (x == LOWEST && y == HIGHEST)
+                        {
+                          msg (SE, _("LO THRU HI is an invalid range."));
+                          deferred_errors = true;
+                        }
+                      else if (!mv_add_num_range (&mv, x, y))
+                        deferred_errors = true;
+                    }
+                  else
+                    {
+                      if (x == LOWEST) 
+                        {
+                          msg (SE, _("LO or LOWEST must be part of a range."));
+                          deferred_errors = true;
+                        }
+                      else if (!mv_add_num (&mv, x))
+                        deferred_errors = true;
+                    }
+
+                  lex_match (',');
+                }
+            }
+          else 
+            {
+              mv_init (&mv, MAX_SHORT_STRING);
+              while (!lex_match (')')) 
+                {
+                  if (!lex_force_string ())
+                    {
+                      deferred_errors = true;
+                      break;
+                    }
+
+                  if (ds_length (&tokstr) > MAX_SHORT_STRING) 
+                    {
+                      ds_truncate (&tokstr, MAX_SHORT_STRING);
+                      msg (SE, _("Truncating missing value to short string "
+                                 "length (%d characters)."),
+                           MAX_SHORT_STRING);
+                    }
+                  else
+                    ds_rpad (&tokstr, MAX_SHORT_STRING, ' ');
+
+                  if (!mv_add_str (&mv, ds_data (&tokstr)))
+                    deferred_errors = true;
+
+                  lex_get ();
+                  lex_match (',');
+                }
+            }
+          
+          for (i = 0; i < nv; i++) 
+            {
+              if (!mv_is_resizable (&mv, v[i]->width)) 
+                {
+                  msg (SE, _("Missing values provided are too long to assign "
+                             "to variable of width %d."),
+                       v[i]->width);
+                  deferred_errors = true;
+                }
+              else 
+                {
+                  mv_copy (&v[i]->miss, &mv);
+                  mv_resize (&v[i]->miss, v[i]->width);
+                }
+            }
+        }
 
       lex_match ('/');
       free (v);
+      v = NULL;
     }
-
-  return lex_end_of_command ();
-
-fail:
+  retval = lex_end_of_command ();
+  
+ done:
   free (v);
-  return CMD_PART_SUCCESS_MAYBE;
-}
-
-static int
-parse_varnames (void)
-{
-  int i;
-
-  if (!parse_variables (default_dict, &v, &nv, PV_SAME_TYPE))
-    return 0;
-  if (!lex_match ('('))
-    {
-      msg (SE, _("`(' expected after variable name%s."), nv > 1 ? "s" : "");
-      return 0;
-    }
-
-  type = v[0]->type;
-  if (type == NUMERIC)
-    return 1;
-
-  width = v[0]->width;
-  for (i = 1; i < nv; i++)
-    if (v[i]->type == ALPHA && v[i]->nv != 1)
-      {
-       msg (SE, _("Long string value specified."));
-       return 0;
-      }
-    else if (v[i]->type == ALPHA && (int) width != v[i]->width)
-      {
-       msg (SE, _("Short strings must be of equal width."));
-       return 0;
-      }
-
-  return 1;
+  if (deferred_errors)
+    retval = CMD_PART_SUCCESS_MAYBE;
+  return retval;
 }
 
-/* Number or range? */
-enum
-  {
-    MV_NOR_NOTHING,            /* Empty. */
-    MV_NOR_NUMBER,             /* Single number. */
-    MV_NOR_RANGE               /* Range. */
-  };
-
-/* A single value or a range. */
-struct num_or_range
-  {
-    int type;                  /* One of NOR_*. */
-    double d[2];               /* d[0]=lower bound or value, d[1]=upper bound. 
*/
-  };
-
-/* Parses something of the form <num>, or LO[WEST] THRU <num>, or
-   <num> THRU HI[GHEST], or <num> THRU <num>, and sets the appropriate
-   members of NOR.  Returns success. */
-static int
-parse_num_or_range (struct num_or_range * nor)
+static bool
+parse_number (double *x, const struct fmt_spec *f)
 {
-  if (lex_match_id ("LO") || lex_match_id ("LOWEST"))
+  if (lex_is_number ()) 
     {
-      nor->type = MV_NOR_RANGE;
-      if (!lex_force_match_id ("THRU"))
-       return 0;
-      if (!lex_force_num ())
-       return 0;
-      nor->d[0] = LOWEST;
-      nor->d[1] = tokval;
-    }
-  else if (lex_is_number ())
-    {
-      nor->d[0] = tokval;
+      *x = lex_number ();
       lex_get ();
-
-      if (lex_match_id ("THRU"))
-       {
-         nor->type = MV_NOR_RANGE;
-         if (lex_match_id ("HI") || lex_match_id ("HIGHEST"))
-           nor->d[1] = HIGHEST;
-         else
-           {
-             if (!lex_force_num ())
-               return 0;
-             nor->d[1] = tokval;
-             lex_get ();
-
-             if (nor->d[0] > nor->d[1])
-               {
-                 msg (SE, _("Range %g THRU %g is not valid because %g is "
-                            "greater than %g."),
-                      nor->d[0], nor->d[1], nor->d[0], nor->d[1]);
-                 return 0;
-               }
-           }
-       }
-      else
-       nor->type = MV_NOR_NUMBER;
-    }
-  else
-    return -1;
-
-  return 1;
-}
-
-/* Parses a set of numeric missing values and stores them into
-   `missing[]' and `miss_type' global variables. */
-static int
-parse_numeric (void)
-{
-  struct num_or_range set[3];
-  int r;
-
-  set[1].type = set[2].type = MV_NOR_NOTHING;
-
-  /* Get first number or range. */
-  r = parse_num_or_range (&set[0]);
-  if (r < 1)
-    {
-      if (r == -1)
-       msg (SE, _("Number or range expected."));
-      return 0;
-    }
-
-  /* Get second and third optional number or range. */
-  lex_match (',');
-  r = parse_num_or_range (&set[1]);
-  if (r == 1)
-    {
-      lex_match (',');
-      r = parse_num_or_range (&set[2]);
-    }
-  if (r == 0)
-    return 0;
-
-  /* Force range, if present, into set[0]. */
-  if (set[1].type == MV_NOR_RANGE)
-    {
-      struct num_or_range t = set[1];
-      set[1] = set[0];
-      set[0] = t;
-    }
-  if (set[2].type == MV_NOR_RANGE)
-    {
-      struct num_or_range t = set[2];
-      set[2] = set[0];
-      set[0] = t;
-    }
-  
-  /* Ensure there's not more than one range, or one range
-     plus one value. */
-  if (set[1].type == MV_NOR_RANGE || set[2].type == MV_NOR_RANGE)
-    {
-      msg (SE, _("At most one range can exist in the missing values "
-                "for any one variable."));
-      return 0;
+      return true;
     }
-  if (set[0].type == MV_NOR_RANGE && set[2].type != MV_NOR_NOTHING)
+  else if (token == T_STRING) 
     {
-      msg (SE, _("At most one individual value can be missing along "
-                "with one range."));
-      return 0;
-    }
-
-  /* Set missing[] from set[]. */
-  if (set[0].type == MV_NOR_RANGE)
-    {
-      int x = 0;
-
-      if (set[0].d[0] == LOWEST)
-       {
-         miss_type = MISSING_LOW;
-         missing[x++].f = set[0].d[1];
-       }
-      else if (set[0].d[1] == HIGHEST)
-       {
-         miss_type = MISSING_HIGH;
-         missing[x++].f = set[0].d[0];
-       }
-      else
-       {
-         miss_type = MISSING_RANGE;
-         missing[x++].f = set[0].d[0];
-         missing[x++].f = set[0].d[1];
-       }
-
-      if (set[1].type == MV_NOR_NUMBER)
-       {
-         miss_type += 3;
-         missing[x].f = set[1].d[0];
-       }
-    }
-  else
-    {
-      if (set[0].type == MV_NOR_NUMBER)
-       {
-         miss_type = MISSING_1;
-         missing[0].f = set[0].d[0];
-       }
-      if (set[1].type == MV_NOR_NUMBER)
-       {
-         miss_type = MISSING_2;
-         missing[1].f = set[1].d[0];
-       }
-      if (set[2].type == MV_NOR_NUMBER)
-       {
-         miss_type = MISSING_3;
-         missing[2].f = set[2].d[0];
-       }
-    }
-
-  return 1;
-}
-
-static int
-parse_alpha (void)
-{
-  for (miss_type = 0; token == T_STRING && miss_type < 3; miss_type++)
-    {
-      if (ds_length (&tokstr) != width)
-       {
-         msg (SE, _("String is not of proper length."));
-         return 0;
-       }
-      strncpy (missing[miss_type].s, ds_c_str (&tokstr), MAX_SHORT_STRING);
+      struct data_in di;
+      union value v;
+      di.s = ds_data (&tokstr);
+      di.e = ds_end (&tokstr);
+      di.v = &v;
+      di.flags = 0;
+      di.f1 = 1;
+      di.f2 = ds_length (&tokstr);
+      di.format = *f;
+      data_in (&di);
       lex_get ();
-      lex_match (',');
+      *x = v.f;
+      return true;
     }
-  if (miss_type < 1)
+  else 
     {
-      msg (SE, _("String expected."));
-      return 0;
+      lex_error (_("expecting number or data string"));
+      return false; 
     }
-
-  return 1;
 }
 
-/* Copy the missing values from variable SRC to variable DEST. */
-void
-copy_missing_values (struct variable *dest, const struct variable *src)
-{
-  static const int n_values[MISSING_COUNT] = 
-    {
-      0, 1, 2, 3, 2, 1, 1, 3, 2, 2,
-    };
-    
-  assert (dest->width == src->width);
-  assert (src->miss_type >= 0 && src->miss_type < MISSING_COUNT);
-  
-  {
-    int i;
-
-    dest->miss_type = src->miss_type;
-    for (i = 0; i < n_values[src->miss_type]; i++)
-      if (src->type == NUMERIC)
-       dest->missing[i].f = src->missing[i].f;
-      else
-       memcpy (dest->missing[i].s, src->missing[i].s, src->width);
-  }
-}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]