str: Add function xstrdup_if_nonnull() and introduce many users.
[pspp] / src / data / sys-file-reader.c
index c0bdf0ba61594db25dc177eb68d26cf423662d79..3a54801c3b648b7a92854f6a75d22022e332e15c 100644 (file)
@@ -493,10 +493,7 @@ read_record (struct sfm_reader *r, int type,
 
     case 6:
       if (r->document != NULL)
-        {
-          sys_error (r, r->pos, _("Duplicate type 6 (document) record."));
-          return false;
-        }
+        sys_warn (r, r->pos, _("Duplicate type 6 (document) record."));
       return read_document_record (r);
 
     case 7:
@@ -643,6 +640,13 @@ add_id (struct get_strings_aux *aux, const char *id, const char *title, ...)
   va_end (args);
 }
 
+static const char *
+skip_prefix (const char *s, const char *prefix)
+{
+  size_t prefix_len = strlen (prefix);
+  return !strncmp (s, prefix, prefix_len) ? s + prefix_len : s;
+}
+
 /* Retrieves significant string data from R in its raw format, to allow the
    caller to try to detect the encoding in use.
 
@@ -692,7 +696,7 @@ sfm_get_strings (const struct any_reader *r_, struct pool *pool,
 
   add_string (&aux, r->header.creation_date, _("Creation Date"));
   add_string (&aux, r->header.creation_time, _("Creation Time"));
-  add_string (&aux, r->header.eye_catcher, _("Product"));
+  add_string (&aux, skip_prefix (r->header.eye_catcher, "@(#) "), _("Product"));
   add_string (&aux, r->header.file_label, _("File Label"));
 
   if (r->extensions[EXT_PRODUCT_INFO])
@@ -1392,6 +1396,15 @@ parse_header (struct sfm_reader *r, const struct sfm_header_record *header,
   info->product = ss_xstrdup (product);
 }
 
+static struct variable *
+add_var_with_generated_name (struct dictionary *dict, int width)
+{
+  char *name = dict_make_unique_var_name (dict, NULL, NULL);
+  struct variable *var = dict_create_var_assert (dict, name, width);
+  free (name);
+  return var;
+}
+
 /* Reads a variable (type 2) record from R and adds the
    corresponding variable to DICT.
    Also skips past additional variable records for long string
@@ -1406,7 +1419,6 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict,
 
   for (rec = var_recs; rec < &var_recs[n_var_recs];)
     {
-      struct variable *var;
       size_t n_values;
       char *name;
       size_t i;
@@ -1415,13 +1427,6 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict,
                                  rec->name, -1, r->pool);
       name[strcspn (name, " ")] = '\0';
 
-      if (!dict_id_is_valid (dict, name, false)
-          || name[0] == '$' || name[0] == '#')
-        {
-          sys_error (r, rec->pos, _("Invalid variable name `%s'."), name);
-          return false;
-        }
-
       if (rec->width < 0 || rec->width > 255)
         {
           sys_error (r, rec->pos,
@@ -1429,17 +1434,26 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict,
           return false;
         }
 
-      var = rec->var = dict_create_var (dict, name, rec->width);
-      if (var == NULL)
+      struct variable *var;
+      if (!dict_id_is_valid (dict, name, false)
+          || name[0] == '$' || name[0] == '#')
         {
-          char *new_name = dict_make_unique_var_name (dict, NULL, NULL);
-          sys_warn (r, rec->pos, _("Renaming variable with duplicate name "
-                                   "`%s' to `%s'."),
-                    name, new_name);
-          var = rec->var = dict_create_var_assert (dict, new_name, rec->width);
-          var_set_short_name (var, 0, new_name);
-          free (new_name);
+          var = add_var_with_generated_name (dict, rec->width);
+          sys_warn (r, rec->pos, _("Renaming variable with invalid name "
+                                   "`%s' to `%s'."), name, var_get_name (var));
+        }
+      else
+        {
+          var = dict_create_var (dict, name, rec->width);
+          if (var == NULL)
+            {
+              var = add_var_with_generated_name (dict, rec->width);
+              sys_warn (r, rec->pos, _("Renaming variable with duplicate name "
+                                       "`%s' to `%s'."),
+                        name, var_get_name (var));
+            }
         }
+      rec->var = var;
 
       /* Set the short name the same as the long name (even if we renamed
          it). */
@@ -1680,9 +1694,9 @@ parse_mrsets (struct sfm_reader *r, const struct sfm_extension_record *record,
   text = open_text_record (r, record, false);
   for (;;)
     {
-      struct sfm_mrset *mrset;
-      size_t allocated_vars;
-      char delimiter;
+      struct sfm_mrset *mrset = NULL;
+      size_t allocated_vars = 0;
+      char delimiter = '4';
 
       /* Skip extra line feeds if present. */
       while (text_match (text, '\n'))
@@ -1985,7 +1999,7 @@ rename_var_and_save_short_names (struct sfm_reader *r, off_t pos,
   for (i = 0; i < n_short_names; i++)
     {
       const char *s = var_get_short_name (var, i);
-      short_names[i] = s != NULL ? xstrdup (s) : NULL;
+      short_names[i] = xstrdup_if_nonnull (s);
     }
 
   /* Set long name. */
@@ -3112,7 +3126,11 @@ text_get_token (struct text_record *text, struct substring delimiters,
   char *end;
 
   if (!ss_tokenize (text->buffer, delimiters, &text->pos, &token))
-    return NULL;
+    {
+      if (delimiter != NULL)
+       *delimiter = ss_data (text->buffer)[text->pos-1];
+      return NULL;
+    }
 
   end = &ss_data (token)[ss_length (token)];
   if (delimiter != NULL)