Detect absence of rl_outstream and handle accordingly.
[pspp] / utilities / pspp-dump-sav.c
index 98cb6f3b22ed7ae6673081365fce531c52984069..c6b5823660a140d3575d7d7559b47c87bf899f30 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 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
@@ -65,6 +65,8 @@ static void read_machine_integer_info (struct sfm_reader *,
                                        size_t size, size_t count);
 static void read_machine_float_info (struct sfm_reader *,
                                      size_t size, size_t count);
+static void read_extra_product_info (struct sfm_reader *,
+                                     size_t size, size_t count);
 static void read_mrsets (struct sfm_reader *, size_t size, size_t count);
 static void read_display_parameters (struct sfm_reader *,
                                      size_t size, size_t count);
@@ -81,6 +83,8 @@ static void read_character_encoding (struct sfm_reader *r,
                                       size_t size, size_t count);
 static void read_long_string_value_labels (struct sfm_reader *r,
                                            size_t size, size_t count);
+static void read_long_string_missing_values (struct sfm_reader *r,
+                                             size_t size, size_t count);
 static void read_unknown_extension (struct sfm_reader *,
                                     size_t size, size_t count);
 static void read_compressed_data (struct sfm_reader *, int max_cases);
@@ -94,6 +98,7 @@ static char *text_tokenize (struct text_record *, int delimiter);
 static bool text_match (struct text_record *text, int c);
 static const char *text_parse_counted_string (struct text_record *);
 static size_t text_pos (const struct text_record *);
+static const char *text_get_all (const struct text_record *);
 
 static void usage (void);
 static void sys_warn (struct sfm_reader *, const char *, ...)
@@ -111,6 +116,8 @@ static void read_string (struct sfm_reader *, char *, size_t);
 static void skip_bytes (struct sfm_reader *, size_t);
 static void trim_spaces (char *);
 
+static void print_string (const char *s, size_t len);
+
 int
 main (int argc, char *argv[])
 {
@@ -574,6 +581,10 @@ read_extension_record (struct sfm_reader *r)
       read_mrsets (r, size, count);
       return;
 
+    case 10:
+      read_extra_product_info (r, size, count);
+      return;
+
     case 11:
       read_display_parameters (r, size, count);
       return;
@@ -606,6 +617,10 @@ read_extension_record (struct sfm_reader *r)
       read_long_string_value_labels (r, size, count);
       return;
 
+    case 22:
+      read_long_string_missing_values (r, size, count);
+      return;
+
     default:
       sys_warn (r, "Unrecognized record type 7, subtype %d.", subtype);
       read_unknown_extension (r, size, count);
@@ -663,20 +678,34 @@ read_machine_float_info (struct sfm_reader *r, size_t size, size_t count)
     sys_error (r, "Bad size (%zu) or count (%zu) on extension 4.",
                size, count);
 
-  printf ("\tsysmis: %g\n", sysmis);
+  printf ("\tsysmis: %g (%a)\n", sysmis, sysmis);
   if (sysmis != SYSMIS)
-    sys_warn (r, "File specifies unexpected value %g as %s.",
-              sysmis, "SYSMIS");
+    sys_warn (r, "File specifies unexpected value %g (%a) as %s.",
+              sysmis, sysmis, "SYSMIS");
 
-  printf ("\thighest: %g\n", highest);
+  printf ("\thighest: %g (%a)\n", highest, highest);
   if (highest != HIGHEST)
-    sys_warn (r, "File specifies unexpected value %g as %s.",
-              highest, "HIGHEST");
+    sys_warn (r, "File specifies unexpected value %g (%a) as %s.",
+              highest, highest, "HIGHEST");
+
+  printf ("\tlowest: %g (%a)\n", lowest, lowest);
+  if (lowest != LOWEST && lowest != SYSMIS)
+    sys_warn (r, "File specifies unexpected value %g (%a) as %s.",
+              lowest, lowest, "LOWEST");
+}
+
+static void
+read_extra_product_info (struct sfm_reader *r,
+                         size_t size, size_t count)
+{
+  struct text_record *text;
+  const char *s;
 
-  printf ("\tlowest: %g\n", lowest);
-  if (lowest != LOWEST)
-    sys_warn (r, "File specifies unexpected value %g as %s.",
-              lowest, "LOWEST");
+  printf ("%08llx: extra product info\n", (long long int) ftello (r->file));
+  text = open_text_record (r, size * count);
+  s = text_get_all (text);
+  print_string (s, strlen (s));
+  close_text_record (text);
 }
 
 /* Read record type 7, subtype 7. */
@@ -1013,6 +1042,56 @@ read_long_string_value_labels (struct sfm_reader *r, size_t size, size_t count)
     }
 }
 
+static void
+read_long_string_missing_values (struct sfm_reader *r,
+                                 size_t size, size_t count)
+{
+  long long int start = ftello (r->file);
+
+  printf ("%08llx: long string missing values\n", start);
+  while (ftello (r->file) - start < size * count)
+    {
+      long long posn = ftello (r->file);
+      char var_name[ID_MAX_LEN + 1];
+      uint8_t n_missing_values;
+      int var_name_len;
+      int i;
+
+      /* Read variable name. */
+      var_name_len = read_int (r);
+      if (var_name_len > ID_MAX_LEN)
+        sys_error (r, "Variable name length in long string value label "
+                   "record (%d) exceeds %d-byte limit.",
+                   var_name_len, ID_MAX_LEN);
+      read_string (r, var_name, var_name_len + 1);
+
+      /* Read number of values. */
+      read_bytes (r, &n_missing_values, 1);
+
+      printf ("\t%08llx: %s, %d missing values:",
+              posn, var_name, n_missing_values);
+
+      /* Read values. */
+      for (i = 0; i < n_missing_values; i++)
+       {
+          char *value;
+          int value_length;
+
+          posn = ftello (r->file);
+
+          /* Read value. */
+          value_length = read_int (r);
+          value = xmalloc (value_length + 1);
+          read_string (r, value, value_length + 1);
+
+          printf (" \"%s\"", value);
+
+          free (value);
+       }
+      printf ("\n");
+    }
+}
+
 static void
 hex_dump (size_t offset, const void *buffer_, size_t buffer_size)
 {
@@ -1069,23 +1148,7 @@ read_unknown_extension (struct sfm_reader *r, size_t size, size_t count)
     {
       buffer = xmalloc (count);
       read_bytes (r, buffer, count);
-      if (memchr (buffer, 0, count) == 0)
-        {
-          for (i = 0; i < count; i++)
-            {
-              unsigned char c = buffer[i];
-
-              if (c == '\\')
-                printf ("\\\\");
-              else if (c == '\n' || isprint (c))
-                putchar (c);
-              else
-                printf ("\\%02x", c);
-            }
-          putchar ('\n');
-        }
-      else
-        hex_dump (0, buffer, count);
+      print_string (CHAR_CAST (char *, buffer), count);
       free (buffer);
     }
 }
@@ -1333,6 +1396,12 @@ text_pos (const struct text_record *text)
 {
   return text->pos;
 }
+
+static const char *
+text_get_all (const struct text_record *text)
+{
+  return text->buffer;
+}
 \f
 static void
 usage (void)
@@ -1485,3 +1554,27 @@ trim_spaces (char *s)
     end--;
   *end = '\0';
 }
+
+static void
+print_string (const char *s, size_t len)
+{
+  if (memchr (s, 0, len) == 0)
+    {
+      size_t i;
+
+      for (i = 0; i < len; i++)
+        {
+          unsigned char c = s[i];
+
+          if (c == '\\')
+            printf ("\\\\");
+          else if (c == '\n' || isprint (c))
+            putchar (c);
+          else
+            printf ("\\%02x", c);
+        }
+      putchar ('\n');
+    }
+  else
+    hex_dump (0, s, len);
+}