Add scratch file handles.
[pspp-builds.git] / src / data-list.c
index d1dbbc248858b3607e71e2e0db1326616baaa641..49fbf0d76a6a0df876bc7976a4b79b9581681c97 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
    Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
@@ -83,8 +83,6 @@ enum
 /* DATA LIST private data structure. */
 struct data_list_pgm
   {
-    struct trns_header h;
-
     struct dls_var_spec *first, *last; /* Variable parsing specifications. */
     struct dfm_reader *reader;  /* Data file reader. */
 
@@ -97,6 +95,8 @@ struct data_list_pgm
     size_t delim_cnt;           /* Number of delimiter, or 0 for spaces. */
   };
 
+static const struct case_source_class data_list_source_class;
+
 static int parse_fixed (struct data_list_pgm *);
 static int parse_free (struct dls_var_spec **, struct dls_var_spec **);
 static void dump_fixed_table (const struct dls_var_spec *,
@@ -113,9 +113,9 @@ static trns_proc_func data_list_trns_proc;
 int
 cmd_data_list (void)
 {
-  struct data_list_pgm *dls;     /* DATA LIST program under construction. */
+  struct data_list_pgm *dls;
   int table = -1;                /* Print table if nonzero, -1=undecided. */
-  struct file_handle *fh = NULL; /* File handle of source, NULL=inline file. */
+  struct file_handle *fh = fh_inline_file ();
 
   if (!case_source_is_complex (vfm_source))
     discard_variables ();
@@ -135,14 +135,14 @@ cmd_data_list (void)
       if (lex_match_id ("FILE"))
        {
          lex_match ('=');
-         fh = fh_parse ();
+         fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
          if (fh == NULL)
            goto error;
          if (case_source_is_class (vfm_source, &file_type_source_class)
-              && fh != default_handle)
+              && fh != fh_get_default_handle ())
            {
-             msg (SE, _("DATA LIST may not use a different file from "
-                        "that specified on its surrounding FILE TYPE."));
+             msg (SE, _("DATA LIST must use the same file "
+                        "as the enclosing FILE TYPE."));
              goto error;
            }
        }
@@ -237,7 +237,7 @@ cmd_data_list (void)
     }
 
   dls->case_size = dict_get_case_size (default_dict);
-  default_handle = fh;
+  fh_set_default_handle (fh);
 
   if (dls->type == -1)
     dls->type = DLS_FIXED;
@@ -270,20 +270,14 @@ cmd_data_list (void)
     goto error;
 
   if (vfm_source != NULL)
-    {
-      dls->h.proc = data_list_trns_proc;
-      dls->h.free = data_list_trns_free;
-      add_transformation (&dls->h);
-    }
+    add_transformation (data_list_trns_proc, data_list_trns_free, dls);
   else 
     vfm_source = create_case_source (&data_list_source_class, dls);
 
   return CMD_SUCCESS;
 
  error:
-  destroy_dls_var_spec (dls->first);
-  free (dls->delims);
-  free (dls);
+  data_list_trns_free (dls);
   return CMD_FAILURE;
 }
 
@@ -803,15 +797,9 @@ dump_fixed_table (const struct dls_var_spec *specs,
                    fmt_to_string (&spec->input));
     }
 
-  if (fh != NULL)
-    tab_title (t, 1, ngettext ("Reading %d record from file %s.",
-                               "Reading %d records from file %s.", rec_cnt),
-               rec_cnt, handle_get_filename (fh));
-  else
-    tab_title (t, 1, ngettext ("Reading %d record from the command file.",
-                               "Reading %d records from the command file.",
-                               rec_cnt),
-               rec_cnt);
+  tab_title (t, 1, ngettext ("Reading %d record from %s.",
+                             "Reading %d records from %s.", rec_cnt),
+             rec_cnt, fh_get_name (fh));
   tab_submit (t);
 }
 \f
@@ -852,7 +840,7 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last)
        {
          lex_match ('*');
           input = make_input_format (FMT_F, 8, 0);
-         output = get_format ();
+         output = *get_format ();
        }
 
       if (input.type == FMT_A || input.type == FMT_AHEX)
@@ -925,11 +913,7 @@ dump_free_table (const struct data_list_pgm *dls,
       }
   }
 
-  if (fh != NULL)
-    tab_title (t, 1, _("Reading free-form data from file %s."),
-               handle_get_filename (fh));
-  else
-    tab_title (t, 1, _("Reading free-form data from the command file."));
+  tab_title (t, 1, _("Reading free-form data from %s."), fh_get_name (fh));
   
   tab_submit (t);
 }
@@ -1233,22 +1217,22 @@ destroy_dls_var_spec (struct dls_var_spec *spec)
     }
 }
 
-/* Destroys DATA LIST transformation PGM. */
+/* Destroys DATA LIST transformation DLS. */
 static void
-data_list_trns_free (struct trns_header *pgm)
+data_list_trns_free (void *dls_)
 {
-  struct data_list_pgm *dls = (struct data_list_pgm *) pgm;
+  struct data_list_pgm *dls = dls_;
   free (dls->delims);
   destroy_dls_var_spec (dls->first);
   dfm_close_reader (dls->reader);
+  free (dls);
 }
 
-/* Handle DATA LIST transformation T, parsing data into C. */
+/* Handle DATA LIST transformation DLS, parsing data into C. */
 static int
-data_list_trns_proc (struct trns_header *t, struct ccase *c,
-                     int case_num UNUSED)
+data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED)
 {
-  struct data_list_pgm *dls = (struct data_list_pgm *) t;
+  struct data_list_pgm *dls = dls_;
   data_list_read_func *read_func;
   int retval;
 
@@ -1315,10 +1299,9 @@ static void
 data_list_source_destroy (struct case_source *source)
 {
   data_list_trns_free (source->aux);
-  free (source->aux);
 }
 
-const struct case_source_class data_list_source_class = 
+static const struct case_source_class data_list_source_class = 
   {
     "DATA LIST",
     NULL,
@@ -1338,7 +1321,6 @@ struct rpd_num_or_var
 /* REPEATING DATA private data structure. */
 struct repeating_data_trns
   {
-    struct trns_header h;
     struct dls_var_spec *first, *last; /* Variable parsing specifications. */
     struct dfm_reader *reader;         /* Input file, never NULL. */
 
@@ -1377,12 +1359,12 @@ cmd_repeating_data (void)
   bool saw_length = false;      /* Saw LENGTH subcommand? */
   bool saw_continued = false;   /* Saw CONTINUED subcommand? */
   bool saw_id = false;          /* Saw ID subcommand? */
-  struct file_handle *const fh = default_handle;
+  struct file_handle *const fh = fh_get_default_handle ();
   
   assert (case_source_is_complex (vfm_source));
 
   rpd = xmalloc (sizeof *rpd);
-  rpd->reader = dfm_open_reader (default_handle);
+  rpd->reader = dfm_open_reader (fh);
   rpd->first = rpd->last = NULL;
   rpd->starts_beg.num = 0;
   rpd->starts_beg.var = NULL;
@@ -1400,7 +1382,7 @@ cmd_repeating_data (void)
        {
           struct file_handle *file;
          lex_match ('=');
-         file = fh_parse ();
+         file = fh_parse (FH_REF_FILE | FH_REF_INLINE);
          if (file == NULL)
            goto error;
          if (file != fh)
@@ -1452,7 +1434,7 @@ cmd_repeating_data (void)
              msg (SE, _("%s subcommand given multiple times."),"OCCURS");
              goto error;
            }
-         saw_occurs |= 2;
+         saw_occurs = true;
 
          if (!parse_num_or_var (&rpd->occurs, "OCCURS"))
            goto error;
@@ -1460,12 +1442,12 @@ cmd_repeating_data (void)
       else if (lex_match_id ("LENGTH"))
        {
          lex_match ('=');
-         if (saw_length & 4)
+         if (saw_length)
            {
              msg (SE, _("%s subcommand given multiple times."),"LENGTH");
              goto error;
            }
-         saw_length |= 4;
+         saw_length = true;
 
          if (!parse_num_or_var (&rpd->length, "LENGTH"))
            goto error;
@@ -1473,12 +1455,12 @@ cmd_repeating_data (void)
       else if (lex_match_id ("CONTINUED"))
        {
          lex_match ('=');
-         if (saw_continued & 8)
+         if (saw_continued)
            {
              msg (SE, _("%s subcommand given multiple times."),"CONTINUED");
              goto error;
            }
-         saw_continued |= 8;
+         saw_continued = true;
 
          if (!lex_match ('/'))
            {
@@ -1507,12 +1489,12 @@ cmd_repeating_data (void)
       else if (lex_match_id ("ID"))
        {
          lex_match ('=');
-         if (saw_id & 16)
+         if (saw_id)
            {
              msg (SE, _("%s subcommand given multiple times."),"ID");
              goto error;
            }
-         saw_id |= 16;
+         saw_id = true;
          
          if (!lex_force_int ())
            goto error;
@@ -1595,7 +1577,7 @@ cmd_repeating_data (void)
   /* Calculate and check starts_end, cont_end if necessary. */
   if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL) 
     {
-      rpd->starts_end.num = fh != NULL ? handle_get_record_width (fh) : 80;
+      rpd->starts_end.num = fh_get_record_width (fh);
       if (rpd->starts_beg.num != 0 
           && rpd->starts_beg.num > rpd->starts_end.num)
         {
@@ -1608,7 +1590,7 @@ cmd_repeating_data (void)
     }
   if (rpd->cont_end.num == 0 && rpd->cont_end.var == NULL) 
     {
-      rpd->cont_end.num = fh != NULL ? handle_get_record_width (fh) : 80;
+      rpd->cont_end.num = fh_get_record_width (fh);
       if (rpd->cont_beg.num != 0
           && rpd->cont_beg.num > rpd->cont_end.num)
         {
@@ -1638,15 +1620,12 @@ cmd_repeating_data (void)
   if (table)
     dump_fixed_table (rpd->first, fh, rpd->last->rec);
 
-  rpd->h.proc = repeating_data_trns_proc;
-  rpd->h.free = repeating_data_trns_free;
-  add_transformation (&rpd->h);
+  add_transformation (repeating_data_trns_proc, repeating_data_trns_free, rpd);
 
   return lex_end_of_command ();
 
  error:
-  destroy_dls_var_spec (rpd->first);
-  free (rpd->id_value);
+  repeating_data_trns_free (rpd);
   return CMD_FAILURE;
 }
 
@@ -1656,14 +1635,15 @@ cmd_repeating_data (void)
 static void 
 find_variable_input_spec (struct variable *v, struct fmt_spec *spec)
 {
-  int i;
+  size_t i;
   
   for (i = 0; i < n_trns; i++)
     {
-      struct data_list_pgm *pgm = (struct data_list_pgm *) t_trns[i];
+      struct transformation *trns = &t_trns[i];
       
-      if (pgm->h.proc == data_list_trns_proc)
+      if (trns->proc == data_list_trns_proc)
        {
+          struct data_list_pgm *pgm = trns->private;
          struct dls_var_spec *iter;
 
          for (iter = pgm->first; iter; iter = iter->next)
@@ -1900,10 +1880,9 @@ rpd_parse_record (const struct rpd_parse_info *info)
    DATA structure.  Returns -1 on success, -2 on end of file or
    on failure. */
 int
-repeating_data_trns_proc (struct trns_header *trns, struct ccase *c,
-                          int case_num UNUSED)
+repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
 {
-  struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+  struct repeating_data_trns *t = trns_;
     
   struct fixed_string line;       /* Current record. */
 
@@ -2055,25 +2034,26 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c,
 
 /* Frees a REPEATING DATA transformation. */
 void
-repeating_data_trns_free (struct trns_header *rpd_) 
+repeating_data_trns_free (void *rpd_) 
 {
-  struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_;
+  struct repeating_data_trns *rpd = rpd_;
 
   destroy_dls_var_spec (rpd->first);
   dfm_close_reader (rpd->reader);
   free (rpd->id_value);
+  free (rpd);
 }
 
 /* Lets repeating_data_trns_proc() know how to write the cases
    that it composes.  Not elegant. */
 void
-repeating_data_set_write_case (struct trns_header *trns,
+repeating_data_set_write_case (struct transformation *trns_,
                                write_case_func *write_case,
                                write_case_data wc_data) 
 {
-  struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+  struct repeating_data_trns *t = trns_->private;
 
-  assert (trns->proc == repeating_data_trns_proc);
+  assert (trns_->proc == repeating_data_trns_proc);
   t->write_case = write_case;
   t->wc_data = wc_data;
 }