Improve the way we handle the various parsing "states". Until now
[pspp-builds.git] / src / language / data-io / data-list.c
index e3324cf20f354f575315da1fbfa25b9b2d11082b..3a6f807c00f63a4b11af204da886b27fcd59b9f8 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
-#include <language/data-io/data-list.h>
-#include <libpspp/message.h>
+
+#include "data-list.h"
+
 #include <ctype.h>
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <libpspp/alloc.h>
+
 #include <data/case.h>
-#include <language/command.h>
-#include <libpspp/compiler.h>
 #include <data/data-in.h>
-#include <libpspp/debug-print.h>
-#include <language/data-io/data-reader.h>
 #include <data/dictionary.h>
-#include <libpspp/message.h>
-#include <language/data-io/file-handle.h>
 #include <data/format.h>
+#include <data/settings.h>
+#include <data/variable.h>
+#include <language/command.h>
+#include <language/data-io/data-list.h>
+#include <language/data-io/data-reader.h>
+#include <language/data-io/file-handle.h>
+#include <language/data-io/file-type.h>
+#include <language/data-io/inpt-pgm.h>
 #include <language/lexer/lexer.h>
+#include <libpspp/alloc.h>
+#include <libpspp/compiler.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <data/settings.h>
 #include <libpspp/str.h>
 #include <output/table.h>
-#include <data/variable.h>
 #include <procedure.h>
 
 #include "gettext.h"
@@ -97,6 +102,7 @@ struct data_list_pgm
 
 static const struct case_source_class data_list_source_class;
 
+static void rpd_msg (enum msg_class, const char *format, ...);
 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 *,
@@ -107,9 +113,6 @@ static void destroy_dls_var_spec (struct dls_var_spec *);
 static trns_free_func data_list_trns_free;
 static trns_proc_func data_list_trns_proc;
 
-/* Message title for REPEATING DATA. */
-#define RPD_ERR "REPEATING DATA: "
-
 int
 cmd_data_list (void)
 {
@@ -117,7 +120,7 @@ cmd_data_list (void)
   int table = -1;                /* Print table if nonzero, -1=undecided. */
   struct file_handle *fh = fh_inline_file ();
 
-  if (!case_source_is_complex (vfm_source))
+  if (!in_input_program () && !in_file_type ())
     discard_variables ();
 
   dls = xmalloc (sizeof *dls);
@@ -137,8 +140,7 @@ cmd_data_list (void)
          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 != fh_get_default_handle ())
+         if (in_file_type () && fh != fh_get_default_handle ())
            {
              msg (SE, _("DATA LIST must use the same file "
                         "as the enclosing FILE TYPE."));
@@ -543,7 +545,7 @@ fixed_parse_compatible (struct fixed_parsing_state *fx,
        {
          convert_fmt_ItoO (&input, &v->print);
          v->write = v->print;
-          if (!case_source_is_complex (vfm_source))
+          if (!in_input_program () && !in_file_type ())
             v->init = 0;
        }
       else
@@ -651,7 +653,7 @@ dump_fmt_list (struct fixed_parsing_state *fx, struct fmt_list *f,
                return 0;
              }
            
-            if (!case_source_is_complex (vfm_source))
+            if (!in_input_program () && !in_file_type ())
               v->init = 0;
 
             spec = xmalloc (sizeof *spec);
@@ -860,7 +862,7 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last)
            }
          v->print = v->write = output;
 
-          if (!case_source_is_complex (vfm_source))
+          if (!in_input_program () && !in_file_type ())
             v->init = 0;
 
           spec = xmalloc (sizeof *spec);
@@ -1346,6 +1348,8 @@ static int parse_repeating_data (struct dls_var_spec **,
 static void find_variable_input_spec (struct variable *v,
                                      struct fmt_spec *spec);
 
+int cmd_repeating_data (void);
+
 /* Parses the REPEATING DATA command. */
 int
 cmd_repeating_data (void)
@@ -1359,7 +1363,7 @@ cmd_repeating_data (void)
   bool saw_id = false;          /* Saw ID subcommand? */
   struct file_handle *const fh = fh_get_default_handle ();
   
-  assert (case_source_is_complex (vfm_source));
+  assert (in_input_program () || in_file_type ());
 
   rpd = xmalloc (sizeof *rpd);
   rpd->reader = dfm_open_reader (fh);
@@ -1811,9 +1815,10 @@ rpd_parse_record (const struct rpd_parse_info *info)
          data_out (actual_str, &t->id_var->print, id_temp);
           actual_str[t->id_var->print.w] = '\0';
            
-         tmsg (SE, RPD_ERR, 
-               _("Encountered mismatched record ID \"%s\" expecting \"%s\"."),
-               actual_str, expected_str);
+         rpd_msg (SE, 
+                   _("Encountered mismatched record ID \"%s\" "
+                     "expecting \"%s\"."),
+                   actual_str, expected_str);
 
          return 0;
        }
@@ -1843,10 +1848,10 @@ rpd_parse_record (const struct rpd_parse_info *info)
                {
                  warned = 1;
 
-                 tmsg (SW, RPD_ERR,
-                       _("Variable %s starting in column %d extends "
-                         "beyond physical record length of %d."),
-                       var_spec->v->name, fc, info->len);
+                 rpd_msg (SW,
+                           _("Variable %s starting in column %d extends "
+                             "beyond physical record length of %d."),
+                           var_spec->v->name, fc, info->len);
                }
              
              {
@@ -1911,46 +1916,45 @@ repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
   occurs_left = occurs = realize_value (&t->occurs, c);
   if (occurs <= 0)
     {
-      tmsg (SE, RPD_ERR, _("Invalid value %d for OCCURS."), occurs);
+      rpd_msg (SE, _("Invalid value %d for OCCURS."), occurs);
       return TRNS_NEXT_CASE;
     }
   starts_beg = realize_value (&t->starts_beg, c);
   if (starts_beg <= 0)
     {
-      tmsg (SE, RPD_ERR, _("Beginning column for STARTS (%d) must be "
-                           "at least 1."),
-            starts_beg);
+      rpd_msg (SE, _("Beginning column for STARTS (%d) must be at least 1."),
+               starts_beg);
       return TRNS_NEXT_CASE;
     }
   starts_end = realize_value (&t->starts_end, c);
   if (starts_end < starts_beg)
     {
-      tmsg (SE, RPD_ERR, _("Ending column for STARTS (%d) is less than "
-                           "beginning column (%d)."),
-            starts_end, starts_beg);
+      rpd_msg (SE, _("Ending column for STARTS (%d) is less than "
+                     "beginning column (%d)."),
+               starts_end, starts_beg);
       skip_first_record = 1;
     }
   length = realize_value (&t->length, c);
   if (length < 0)
     {
-      tmsg (SE, RPD_ERR, _("Invalid value %d for LENGTH."), length);
+      rpd_msg (SE, _("Invalid value %d for LENGTH."), length);
       length = 1;
       occurs = occurs_left = 1;
     }
   cont_beg = realize_value (&t->cont_beg, c);
   if (cont_beg < 0)
     {
-      tmsg (SE, RPD_ERR, _("Beginning column for CONTINUED (%d) must be "
-                           "at least 1."),
-            cont_beg);
+      rpd_msg (SE, _("Beginning column for CONTINUED (%d) must be "
+                     "at least 1."),
+               cont_beg);
       return TRNS_DROP_CASE;
     }
   cont_end = realize_value (&t->cont_end, c);
   if (cont_end < cont_beg)
     {
-      tmsg (SE, RPD_ERR, _("Ending column for CONTINUED (%d) is less than "
-                           "beginning column (%d)."),
-            cont_end, cont_beg);
+      rpd_msg (SE, _("Ending column for CONTINUED (%d) is less than "
+                     "beginning column (%d)."),
+               cont_end, cont_beg);
       return TRNS_DROP_CASE;
     }
 
@@ -1979,11 +1983,11 @@ repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
      continuation records. */
   if (occurs_left > 0 && cont_beg == 0)
     {
-      tmsg (SE, RPD_ERR,
-            _("Number of repetitions specified on OCCURS (%d) "
-              "exceed number of repetitions available in "
-              "space on STARTS (%d), and CONTINUED not specified."),
-            occurs, (starts_end - starts_beg + 1) / length);
+      rpd_msg (SE,
+               _("Number of repetitions specified on OCCURS (%d) "
+                 "exceed number of repetitions available in "
+                 "space on STARTS (%d), and CONTINUED not specified."),
+               occurs, (starts_end - starts_beg + 1) / length);
       return TRNS_DROP_CASE;
     }
 
@@ -1997,10 +2001,10 @@ repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
       /* Read in another record. */
       if (dfm_eof (t->reader))
         {
-          tmsg (SE, RPD_ERR,
-                _("Unexpected end of file with %d repetitions "
-                  "remaining out of %d."),
-                occurs_left, occurs);
+          rpd_msg (SE,
+                   _("Unexpected end of file with %d repetitions "
+                     "remaining out of %d."),
+                   occurs_left, occurs);
           return TRNS_DROP_CASE;
         }
       dfm_expand_tabs (t->reader);
@@ -2057,3 +2061,27 @@ repeating_data_set_write_case (struct transformation *trns_,
   t->write_case = write_case;
   t->wc_data = wc_data;
 }
+
+/* Reports a message in CLASS with the given FORMAT as text,
+   prefixing the message with "REPEATING DATA: " to make the
+   cause clear. */
+static void
+rpd_msg (enum msg_class class, const char *format, ...)
+{
+  struct msg m;
+  va_list args;
+  struct string text;
+
+  ds_create (&text, "REPEATING DATA: ");
+  va_start (args, format);
+  ds_vprintf (&text, format, args);
+  va_end (args);
+
+  m.category = msg_class_to_category (class);
+  m.severity = msg_class_to_severity (class);
+  m.where.file_name = NULL;
+  m.where.line_number = 0;
+  m.text = ds_c_str (&text);
+
+  msg_emit (&m);
+}