sys-file-reader: Add missing periods at end of error messages.
[pspp-builds.git] / src / data / sys-file-reader.c
index f284f56e3f36a5de36d9acbe610626b55920f513..cce41642bec191e9f705579215735e76bba0586b 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -42,7 +42,6 @@
 #include "libpspp/array.h"
 #include "libpspp/assertion.h"
 #include "libpspp/compiler.h"
-#include "libpspp/hash.h"
 #include "libpspp/i18n.h"
 #include "libpspp/message.h"
 #include "libpspp/misc.h"
@@ -133,6 +132,10 @@ static void text_warn (struct sfm_reader *r, struct text_record *text,
 static char *text_get_token (struct text_record *,
                              struct substring delimiters, char *delimiter);
 static bool text_match (struct text_record *, char c);
+static bool text_read_variable_name (struct sfm_reader *, struct dictionary *,
+                                     struct text_record *,
+                                     struct substring delimiters,
+                                     struct variable **);
 static bool text_read_short_name (struct sfm_reader *, struct dictionary *,
                                   struct text_record *,
                                   struct substring delimiters,
@@ -290,7 +293,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   r->file = fn_open (fh_get_file_name (fh), "rb");
   if (r->file == NULL)
     {
-      msg (ME, _("Error opening \"%s\" for reading as a system file: %s."),
+      msg (ME, _("Error opening `%s' for reading as a system file: %s."),
            fh_get_file_name (r->fh), strerror (errno));
       goto error;
     }
@@ -421,7 +424,7 @@ close_reader (struct sfm_reader *r)
     {
       if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
         {
-          msg (ME, _("Error closing system file \"%s\": %s."),
+          msg (ME, _("Error closing system file `%s': %s."),
                fh_get_file_name (r->fh), strerror (errno));
           r->error = true;
         }
@@ -592,7 +595,7 @@ read_variable_record (struct sfm_reader *r, struct dictionary *dict,
 
   /* Check variable name. */
   if (name[0] == '$' || name[0] == '#')
-    sys_error (r, "Variable name begins with invalid character `%c'.",
+    sys_error (r, _("Variable name begins with invalid character `%c'."),
                name[0]);
   if (!var_is_plausible_name (name, false))
     sys_error (r, _("Invalid variable name `%s'."), name);
@@ -614,16 +617,20 @@ read_variable_record (struct sfm_reader *r, struct dictionary *dict,
     sys_error (r, _("Variable label indicator field is not 0 or 1."));
   if (has_variable_label == 1)
     {
-      size_t len;
+      size_t len, read_len;
       char label[255 + 1];
 
       len = read_int (r);
-      if (len >= sizeof label)
-        sys_error (r, _("Variable %s has label of invalid length %zu."),
-                   name, len);
-      read_string (r, label, len + 1);
+
+      /* Read up to 255 bytes of label. */
+      read_len = MIN (sizeof label - 1, len);
+      read_string (r, label, read_len + 1);
       var_set_label (var, label);
 
+      /* Skip unread label bytes. */
+      skip_bytes (r, len - read_len);
+
+      /* Skip label padding up to multiple of 4 bytes. */
       skip_bytes (r, ROUND_UP (len, 4) - len);
     }
 
@@ -882,7 +889,9 @@ read_extension_record (struct sfm_reader *r, struct dictionary *dict,
       return;
 
     default:
-      sys_warn (r, _("Unrecognized record type 7, subtype %d.  Please send a copy of this file, and the syntax which created it to %s"),
+      sys_warn (r, _("Unrecognized record type 7, subtype %d.  Please send "
+                     "a copy of this file, and the syntax which created it "
+                     "to %s."),
                subtype, PACKAGE_BUGREPORT);
       break;
     }
@@ -1040,13 +1049,20 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count,
         break;
       mrset->name = xstrdup (name);
 
+      if (mrset->name[0] != '$')
+        {
+          sys_warn (r, _("`%s' does not begin with `$' at offset %zu "
+                         "in MRSETS record."), mrset->name, text_pos (text));
+          break;
+        }
+
       if (text_match (text, 'C'))
         {
           mrset->type = MRSET_MC;
           if (!text_match (text, ' '))
             {
-              sys_warn (r, _("Missing space following 'C' at offset %zu "
-                             "in MRSETS record"), text_pos (text));
+              sys_warn (r, _("Missing space following `%c' at offset %zu "
+                             "in MRSETS record."), 'C', text_pos (text));
               break;
             }
         }
@@ -1063,8 +1079,8 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count,
           mrset->cat_source = MRSET_COUNTEDVALUES;
           if (!text_match (text, ' '))
             {
-              sys_warn (r, _("Missing space following 'E' at offset %zu "
-                             "in MRSETS record"), text_pos (text));
+              sys_warn (r, _("Missing space following `%c' at offset %zu "
+                             "in MRSETS record."), 'E',  text_pos (text));
               break;
             }
 
@@ -1072,13 +1088,13 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count,
           if (!strcmp (number, "11"))
             mrset->label_from_var_label = true;
           else if (strcmp (number, "1"))
-            sys_warn (r, _("Unexpected label source value \"%s\" "
-                           "following 'E' at offset %zu in MRSETS record"),
+            sys_warn (r, _("Unexpected label source value `%s' "
+                           "following `E' at offset %zu in MRSETS record."),
                       number, text_pos (text));
         }
       else
         {
-          sys_warn (r, _("Missing 'C', 'D', or 'E' at offset %zu "
+          sys_warn (r, _("Missing `C', `D', or `E' at offset %zu "
                          "in MRSETS record."),
                     text_pos (text));
           break;
@@ -1165,6 +1181,7 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count,
 
       dict_add_mrset (dict, mrset);
       mrset = NULL;
+      stringi_set_destroy (&var_names);
     }
   mrset_destroy (mrset);
   close_text_record (r, text);
@@ -1324,7 +1341,7 @@ read_long_string_map (struct sfm_reader *r, size_t size, size_t count,
       if (length < 1 || length > MAX_STRING)
         {
           sys_warn (r, _("%s listed as string of invalid length %s "
-                         "in very length string record."),
+                         "in very long string record."),
                     var_get_name (var), length_s);
           continue;
         }
@@ -1354,7 +1371,7 @@ read_long_string_map (struct sfm_reader *r, size_t size, size_t count,
             var_set_short_name (var, i, var_get_short_name (seg, 0));
           if (ROUND_UP (width, 8) != ROUND_UP (alloc_width, 8))
             sys_error (r, _("Very long string with width %ld has segment %d "
-                            "of width %d (expected %d)"),
+                            "of width %d (expected %d)."),
                        length, i, width, alloc_width);
         }
       dict_delete_consecutive_vars (dict, idx + 1, segment_cnt - 1);
@@ -1494,7 +1511,7 @@ read_value_labels (struct sfm_reader *r,
                 sys_warn (r, _("Duplicate value label for %g on %s."),
                           label->value.f, var_get_name (v));
               else
-                sys_warn (r, _("Duplicate value label for \"%.*s\" on %s."),
+                sys_warn (r, _("Duplicate value label for `%.*s' on %s."),
                           max_width, value_str (&label->value, max_width),
                           var_get_name (v));
             }
@@ -1532,7 +1549,7 @@ read_attributes (struct sfm_reader *r, struct text_record *text,
           value = text_get_token (text, ss_cstr ("\n"), NULL);
           if (value == NULL)
             {
-              text_warn (r, text, _("Error parsing attribute value %s[%d]"),
+              text_warn (r, text, _("Error parsing attribute value %s[%d]."),
                          key, index);
               break;
             }              
@@ -1546,7 +1563,7 @@ read_attributes (struct sfm_reader *r, struct text_record *text,
           else 
             {
               text_warn (r, text,
-                         _("Attribute value %s[%d] is not quoted: %s"),
+                         _("Attribute value %s[%d] is not quoted: %s."),
                          key, index, value);
               attribute_add_value (attr, value); 
             }
@@ -1635,7 +1652,7 @@ read_long_string_value_labels (struct sfm_reader *r,
         {
           sys_warn (r, _("Ignoring long string value record for variable %s "
                          "because the record's width (%d) does not match the "
-                         "variable's width (%d)"),
+                         "variable's width (%d)."),
                     var_name, width, var_get_width (v));
           skip_long_string_value_labels (r, n_labels);
           continue;
@@ -1671,11 +1688,11 @@ read_long_string_value_labels (struct sfm_reader *r,
                  first 255 bytes.  The maximum documented length
                  of a label is 120 bytes so this is more than
                  generous. */
-              skip_bytes (r, sizeof label - (label_length + 1));
+              skip_bytes (r, (label_length + 1) - sizeof label);
             }
 
           if (!skip && !var_add_value_label (v, &value, label))
-            sys_warn (r, _("Duplicate value label for \"%.*s\" on %s."),
+            sys_warn (r, _("Duplicate value label for `%.*s' on %s."),
                       width, value_str (&value, width), var_get_name (v));
         }
     }
@@ -1693,7 +1710,7 @@ read_variable_attributes (struct sfm_reader *r,
   for (;;) 
     {
       struct variable *var;
-      if (!text_read_short_name (r, dict, text, ss_cstr (":"), &var))
+      if (!text_read_variable_name (r, dict, text, ss_cstr (":"), &var))
         break;
       read_attributes (r, text, var != NULL ? var_get_attributes (var) : NULL);
     }
@@ -1758,11 +1775,11 @@ sys_file_casereader_read (struct casereader *reader, void *r_)
   return c;
 
 eof:
-  case_unref (c);
   if (i != 0)
     partial_record (r);
   if (r->case_cnt != -1)
     read_error (reader, r);
+  case_unref (c);
   return NULL;
 }
 
@@ -1933,7 +1950,7 @@ read_compressed_string (struct sfm_reader *r, uint8_t *dst)
           {
             r->corruption_warning = true;
             sys_warn (r, _("Possible compressed data corruption: "
-                           "string contains compressed integer (opcode %d)"),
+                           "string contains compressed integer (opcode %d)."),
                       opcode);
           }
       }
@@ -2127,6 +2144,27 @@ read_variable_to_value_pair (struct sfm_reader *r, struct dictionary *dict,
     }
 }
 
+static bool
+text_read_variable_name (struct sfm_reader *r, struct dictionary *dict,
+                         struct text_record *text, struct substring delimiters,
+                         struct variable **var)
+{
+  char *name;
+
+  name = text_get_token (text, delimiters, NULL);
+  if (name == NULL)
+    return false;
+
+  *var = dict_lookup_var (dict, name);
+  if (*var != NULL)
+    return true;
+
+  text_warn (r, text, _("Dictionary record refers to unknown variable %s."),
+             name);
+  return false;
+}
+
+
 static bool
 text_read_short_name (struct sfm_reader *r, struct dictionary *dict,
                       struct text_record *text, struct substring delimiters,
@@ -2261,14 +2299,16 @@ sys_msg (struct sfm_reader *r, int class, const char *format, va_list args)
   struct string text;
 
   ds_init_empty (&text);
-  ds_put_format (&text, "\"%s\" near offset 0x%lx: ",
-                 fh_get_file_name (r->fh), (unsigned long) ftell (r->file));
+  ds_put_format (&text, "`%s' near offset 0x%llx: ",
+                 fh_get_file_name (r->fh), (long long int) ftello (r->file));
   ds_put_vformat (&text, format, 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.where.first_column = 0;
+  m.where.last_column = 0;
   m.text = ds_cstr (&text);
 
   msg_emit (&m);