Got rid of "struct long_vec", envector(), devector(), etc.
[pspp-builds.git] / src / data-list.c
index c775c8daac14ede01bd6e8b2727db870eb3edcc6..f4ed8d874d7c2986e530b8dec777225a09fce73f 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-/* AIX requires this to be the first thing in the file.  */
 #include <config.h>
-#if __GNUC__
-#define alloca __builtin_alloca
-#else
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
-#pragma alloca
-#else
-#ifndef alloca                 /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#endif
-#endif
-#endif
-#endif
-
+#include "data-list.h"
 #include <assert.h>
 #include <ctype.h>
 #include <float.h>
@@ -74,7 +58,7 @@ struct dls_var_spec
     int fc, lc;                        /* Fixed-format: Column numbers in record. */
     struct fmt_spec input;     /* Input format of this field. */
     int fv;                    /* First value in case. */
-    int type;                  /* 0=numeric, >0=width of alpha field. */
+    int width;                 /* 0=numeric, >0=width of alpha field. */
   };
 
 /* Constants for DATA LIST type. */
@@ -177,9 +161,9 @@ cmd_data_list (void)
          lex_match ('=');
          if (!lex_force_id ())
            return CMD_FAILURE;
-         dls.end = find_variable (tokid);
-         if (!dls.end)
-           dls.end = force_create_variable (&default_dict, tokid, NUMERIC, 0);
+         dls.end = dict_lookup_var (default_dict, tokid);
+         if (!dls.end) 
+            dls.end = dict_create_var_assert (default_dict, tokid, 0);
          lex_get ();
        }
       else if (token == T_ID)
@@ -276,10 +260,6 @@ append_var_spec (struct dls_var_spec *spec)
   else
     next = next->next = xmalloc (sizeof *spec);
 
-#if __CHECKER__
-  spec->type = ROUND_UP (spec->type, 8);
-#endif
-
   memcpy (next, spec, sizeof *spec);
   next->next = NULL;
 }
@@ -517,23 +497,32 @@ fixed_parse_compatible (void)
   for (i = 0; i < fx.nname; i++)
     {
       int type;
+      int width;
       struct variable *v;
 
-      if (fx.spec.input.type == FMT_A || fx.spec.input.type == FMT_AHEX)
-       type = ALPHA;
-      else
-       type = NUMERIC;
-
-      v = create_variable (&default_dict, fx.name[i], type, dividend);
+      if (fx.spec.input.type == FMT_A || fx.spec.input.type == FMT_AHEX) 
+        {
+          type = ALPHA;
+          width = dividend; 
+        }
+      else 
+        {
+          type = NUMERIC;
+          width = 0;
+        }
+
+      v = dict_create_var (default_dict, fx.name[i], width);
       if (v)
        {
          convert_fmt_ItoO (&fx.spec.input, &v->print);
          v->write = v->print;
+          if (vfm_source != &input_program_source
+              && vfm_source != &file_type_source)
+            v->init = 0;
        }
       else
        {
-         v = find_variable (fx.name[i]);
-         assert (v);
+         v = dict_lookup_var_assert (default_dict, fx.name[i]);
          if (!vfm_source)
            {
              msg (SE, _("%s is a duplicate variable name."), fx.name[i]);
@@ -558,7 +547,7 @@ fixed_parse_compatible (void)
       fx.spec.fc = fx.fc + dividend * i;
       fx.spec.lc = fx.spec.fc + dividend - 1;
       fx.spec.fv = v->fv;
-      fx.spec.type = v->type == NUMERIC ? 0 : v->width;
+      fx.spec.width = v->width;
       append_var_spec (&fx.spec);
     }
   return 1;
@@ -607,9 +596,19 @@ dump_fmt_list (struct fmt_list *f)
        else
          {
            int type;
+            int width;
            struct variable *v;
 
-           type = (formats[f->f.type].cat & FCAT_STRING) ? ALPHA : NUMERIC;
+            if (formats[f->f.type].cat & FCAT_STRING) 
+              {
+                type = ALPHA;
+                width = f->f.w;
+              }
+            else 
+              {
+                type = NUMERIC;
+                width = 0;
+              }
            if (fx.cname >= fx.nname)
              {
                msg (SE, _("The number of format "
@@ -618,15 +617,19 @@ dump_fmt_list (struct fmt_list *f)
                return 0;
              }
            
-           fx.spec.v = v = create_variable (&default_dict,
+           fx.spec.v = v = dict_create_var (default_dict,
                                             fx.name[fx.cname++],
-                                            type, f->f.w);
+                                            width);
            if (!v)
              {
                msg (SE, _("%s is a duplicate variable name."), fx.name[i]);
                return 0;
              }
            
+            if (vfm_source != &input_program_source
+                && vfm_source != &file_type_source)
+              v->init = 0;
+
            fx.spec.input = f->f;
            convert_fmt_ItoO (&fx.spec.input, &v->print);
            v->write = v->print;
@@ -635,7 +638,7 @@ dump_fmt_list (struct fmt_list *f)
            fx.spec.fc = fx.sc;
            fx.spec.lc = fx.sc + f->f.w - 1;
            fx.spec.fv = v->fv;
-           fx.spec.type = v->type == NUMERIC ? 0 : v->width;
+           fx.spec.width = v->width;
            append_var_spec (&fx.spec);
 
            fx.sc += f->f.w;
@@ -755,9 +758,14 @@ dump_fixed_table (void)
        filename = "";
       buf = local_alloc (strlen (filename) + INT_DIGITS + 80);
       sprintf (buf, (dls.handle != inline_file
-                    ? _("Reading %d record%s from file %s.")
-                    : _("Reading %d record%s from the command file.")),
-              dls.nrec, dls.nrec != 1 ? "s" : "", filename);
+                    ? 
+                    ngettext("Reading %d record from file %s.",
+                             "Reading %d records from file %s.",dls.nrec)
+                    : 
+                    ngettext("Reading %d record from the command file.",
+                             "Reading %d records from the command file.",
+                             dls.nrec)),
+              dls.nrec, filename);
     }
   else
     {
@@ -781,14 +789,12 @@ parse_free (void)
   char **name;
   int nname;
   int i;
-  int type;
 
-#if __CHECKER__
-  memset (&spec, 0, sizeof spec);
-#endif
   lex_get ();
   while (token != '.')
     {
+      int width;
+
       if (!parse_DATA_LIST_vars (&name, &nname, PV_NONE))
        return 0;
       if (lex_match ('('))
@@ -810,14 +816,14 @@ parse_free (void)
 
       spec.input = in;
       if (in.type == FMT_A || in.type == FMT_AHEX)
-       type = ALPHA;
+       width = in.w;
       else
-       type = NUMERIC;
+       width = 0;
       for (i = 0; i < nname; i++)
        {
          struct variable *v;
 
-         spec.v = v = create_variable (&default_dict, name[i], type, in.w);
+         spec.v = v = dict_create_var (default_dict, name[i], width);
          if (!v)
            {
              msg (SE, _("%s is a duplicate variable name."), name[i]);
@@ -826,9 +832,13 @@ parse_free (void)
          
          v->print = v->write = out;
 
+          if (vfm_source != &input_program_source
+              && vfm_source != &file_type_source)
+            v->init = 0;
+
          strcpy (spec.name, name[i]);
          spec.fv = v->fv;
-         spec.type = type == NUMERIC ? 0 : v->width;
+         spec.width = width;
          append_var_spec (&spec);
        }
       for (i = 0; i < nname; i++)
@@ -965,14 +975,13 @@ cut_field (char **ret_cp, int *ret_len)
 static int read_from_data_list_fixed (void);
 static int read_from_data_list_free (void);
 static int read_from_data_list_list (void);
-static int do_reading (int flag);
 
 /* FLAG==0: reads any number of cases into temp_case and calls
    write_case() for each one, returns garbage.  FLAG!=0: reads one
    case into temp_case and returns -2 on eof, -1 otherwise.
    Uses dlsp as the relevant parsing description. */
 static int
-do_reading (int flag)
+do_reading (int flag, write_case_func *write_case, write_case_data wc_data)
 {
   int (*func) (void);
 
@@ -1028,15 +1037,12 @@ do_reading (int flag)
   else
     {
       while (func () != -2)
-       if (!write_case ())
+       if (!write_case (wc_data))
          {
            debug_printf ((_("abort in write_case()\n")));
            break;
          }
       fh_close_handle (dlsp->handle);
-#if __CHECKER__
-      code = 0;                        /* prevent error at `return code;' */
-#endif
     }
   dfm_pop (dlsp->handle);
 
@@ -1156,10 +1162,10 @@ read_from_data_list_list (void)
                 "or blanks, as appropriate."),
                 var_spec->name);
          for (; var_spec; var_spec = var_spec->next)
-           if (!var_spec->type)
+           if (var_spec->width == 0)
              temp_case->data[var_spec->fv].f = SYSMIS;
            else
-             memset (temp_case->data[var_spec->fv].s, ' ', var_spec->type);
+             memset (temp_case->data[var_spec->fv].s, ' ', var_spec->width);
          break;
        }
       
@@ -1200,19 +1206,19 @@ destroy_dls (struct trns_header *pgm)
 /* Note that since this is exclusively an input program, C is
    guaranteed to be temp_case. */
 static int
-read_one_case (struct trns_header *t, struct ccase *c unused)
+read_one_case (struct trns_header *t, struct ccase *c UNUSED)
 {
   dlsp = (struct data_list_pgm *) t;
-  return do_reading (1);
+  return do_reading (1, NULL, NULL);
 }
 \f
 /* Reads all the records from the data file and passes them to
    write_case(). */
 static void
-data_list_source_read (void)
+data_list_source_read (write_case_func *write_case, write_case_data wc_data)
 {
   dlsp = &dls;
-  do_reading (0);
+  do_reading (0, write_case, wc_data);
 }
 
 /* Destroys the source's internal data. */
@@ -1259,12 +1265,14 @@ struct repeating_data_trns
     int id_beg, id_end;                        /* ID subcommand, beginning & end columns. */
     struct variable *id_var;           /* ID subcommand, DATA LIST variable. */
     struct fmt_spec id_spec;           /* ID subcommand, input format spec. */
+    write_case_func *write_case;
+    write_case_data wc_data;
   };
 
 /* Information about the transformation being parsed. */
 static struct repeating_data_trns rpd;
 
-static int read_one_set_of_repetitions (struct trns_header *, struct ccase *);
+int repeating_data_trns_proc (struct trns_header *, struct ccase *);
 static int parse_num_or_var (struct rpd_num_or_var *, const char *);
 static int parse_repeating_data (void);
 static void find_variable_input_spec (struct variable *v,
@@ -1319,7 +1327,7 @@ cmd_repeating_data (void)
          lex_match ('=');
          if (seen & 1)
            {
-             msg (SE, _("STARTS subcommand given multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"STARTS");
              return CMD_FAILURE;
            }
          seen |= 1;
@@ -1354,7 +1362,7 @@ cmd_repeating_data (void)
          lex_match ('=');
          if (seen & 2)
            {
-             msg (SE, _("OCCURS subcommand given multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"OCCURS");
              return CMD_FAILURE;
            }
          seen |= 2;
@@ -1367,7 +1375,7 @@ cmd_repeating_data (void)
          lex_match ('=');
          if (seen & 4)
            {
-             msg (SE, _("LENGTH subcommand given multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"LENGTH");
              return CMD_FAILURE;
            }
          seen |= 4;
@@ -1380,7 +1388,7 @@ cmd_repeating_data (void)
          lex_match ('=');
          if (seen & 8)
            {
-             msg (SE, _("CONTINUED subcommand given multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"CONTINUED");
              return CMD_FAILURE;
            }
          seen |= 8;
@@ -1413,7 +1421,7 @@ cmd_repeating_data (void)
          lex_match ('=');
          if (seen & 16)
            {
-             msg (SE, _("ID subcommand given multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"ID");
              return CMD_FAILURE;
            }
          seen |= 16;
@@ -1524,7 +1532,7 @@ cmd_repeating_data (void)
   {
     struct repeating_data_trns *new_trns;
 
-    rpd.h.proc = read_one_set_of_repetitions;
+    rpd.h.proc = repeating_data_trns_proc;
     rpd.h.free = destroy_dls;
 
     new_trns = xmalloc (sizeof *new_trns);
@@ -1766,7 +1774,7 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
                  warned = 1;
 
                  tmsg (SW, RPD_ERR,
-                       _("Variable %s startging in column %d extends "
+                       _("Variable %s starting in column %d extends "
                          "beyond physical record length of %d."),
                        var_spec->v->name, fc, len);
                }
@@ -1788,7 +1796,7 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
 
        cur += ofs;
 
-       if (!write_case ())
+       if (!t->write_case (t->wc_data))
          return 0;
       }
   }
@@ -1799,8 +1807,8 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
 /* Analogous to read_one_case; reads one set of repetitions of the
    elements in the REPEATING DATA structure.  Returns -1 on success,
    -2 on end of file or on failure. */
-static int
-read_one_set_of_repetitions (struct trns_header *trns, struct ccase *c)
+int
+repeating_data_trns_proc (struct trns_header *trns, struct ccase *c)
 {
   dfm_push (dlsp->handle);
   
@@ -1933,3 +1941,19 @@ read_one_set_of_repetitions (struct trns_header *trns, struct ccase *c)
      transformations. */
   return -3;
 }
+
+/* This is a kluge.  It is only here until I have more time
+   tocome up with something better.  It lets
+   repeating_data_trns_proc() know how to write the cases that it
+   composes. */
+void
+repeating_data_set_write_case (struct trns_header *trns,
+                               write_case_func *write_case,
+                               write_case_data wc_data) 
+{
+  struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+
+  assert (trns->proc == repeating_data_trns_proc);
+  t->write_case = write_case;
+  t->wc_data = wc_data;
+}