continue crypto work
[pspp] / src / data / sys-file-writer.c
index c94d13d85994037042ea236ac85c89600c50f339..147605ecb95e998e9df4682a036bac96e85b5b8f 100644 (file)
@@ -41,6 +41,7 @@
 #include "data/short-names.h"
 #include "data/value-labels.h"
 #include "data/variable.h"
+#include "data/varset.h"
 #include "libpspp/float-format.h"
 #include "libpspp/i18n.h"
 #include "libpspp/integer-format.h"
@@ -69,7 +70,7 @@ struct sfm_writer
   {
     struct file_handle *fh;     /* File handle. */
     struct fh_lock *lock;       /* Mutual exclusion for file. */
-    FILE *file;                        /* File stream. */
+    FILE *file;                        /* File stream. */
     struct replace_file *rf;    /* Ticket for replacing output file. */
 
     enum any_compression compression;
@@ -122,16 +123,17 @@ static void write_longvar_table (struct sfm_writer *w,
                                  const struct dictionary *dict);
 
 static void write_encoding_record (struct sfm_writer *w,
-                                  const struct dictionary *);
+                                   const struct dictionary *);
 
 static void write_vls_length_table (struct sfm_writer *w,
-                             const struct dictionary *dict);
+                              const struct dictionary *dict);
 
 static void write_long_string_value_labels (struct sfm_writer *,
                                             const struct dictionary *);
 static void write_long_string_missing_values (struct sfm_writer *,
                                               const struct dictionary *);
 
+static void write_varsets (struct sfm_writer *, const struct dictionary *);
 static void write_mrsets (struct sfm_writer *, const struct dictionary *,
                           bool pre_v14);
 
@@ -275,6 +277,7 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d,
   write_integer_info_record (w, d);
   write_float_info_record (w);
 
+  write_varsets (w, d);
   write_mrsets (w, d, true);
 
   write_variable_display_parameters (w, d);
@@ -450,7 +453,7 @@ write_header (struct sfm_writer *w, const struct dictionary *d)
 static void
 write_format (struct sfm_writer *w, struct fmt_spec fmt, int width)
 {
-  assert (fmt_check_output (&fmt));
+  assert (fmt_check_output (fmt));
   assert (sfm_width_to_segments (width) == 1);
 
   if (width > 0)
@@ -518,8 +521,8 @@ write_variable (struct sfm_writer *w, const struct variable *v)
     write_int (w, 0);
 
   /* Print and write formats. */
-  write_format (w, *var_get_print_format (v), seg0_width);
-  write_format (w, *var_get_write_format (v), seg0_width);
+  write_format (w, var_get_print_format (v), seg0_width);
+  write_format (w, var_get_write_format (v), seg0_width);
 
   /* Short name.
      The full name is in a translation table written
@@ -804,6 +807,49 @@ write_variable_attributes (struct sfm_writer *w, const struct dictionary *d)
   ds_destroy (&s);
 }
 
+/* Write variable sets. */
+static void
+write_varsets (struct sfm_writer *w, const struct dictionary *dict)
+{
+  const char *encoding = dict_get_encoding (dict);
+
+  if (is_encoding_ebcdic_compatible (encoding))
+    {
+      /* FIXME. */
+      return;
+    }
+
+  size_t n_varsets = dict_get_n_varsets (dict);
+  if (n_varsets == 0)
+    return;
+
+  struct string s = DS_EMPTY_INITIALIZER;
+  for (size_t i = 0; i < n_varsets; i++)
+    {
+      const struct varset *varset = dict_get_varset (dict, i);
+
+      char *name = recode_string (encoding, "UTF-8", varset->name, -1);
+      ds_put_format (&s, "%s= ", name);
+      free (name);
+
+      for (size_t j = 0; j < varset->n_vars; j++)
+        {
+          if (j)
+            ds_put_byte (&s, ' ');
+
+          const char *name_utf8 = var_get_name (varset->vars[j]);
+          char *name = recode_string (encoding, "UTF-8", name_utf8, -1);
+          ds_put_cstr (&s, name);
+          free (name);
+        }
+      ds_put_byte (&s, '\n');
+    }
+
+  if (!ds_is_empty (&s))
+    write_string_record (w, ds_ss (&s), 5);
+  ds_destroy (&s);
+}
+
 /* Write multiple response sets.  If PRE_V14 is true, writes sets supported by
    SPSS before release 14, otherwise writes sets supported only by later
    versions. */
@@ -890,7 +936,7 @@ write_mrsets (struct sfm_writer *w, const struct dictionary *dict,
 /* Write the alignment, width and scale values. */
 static void
 write_variable_display_parameters (struct sfm_writer *w,
-                                  const struct dictionary *dict)
+                                   const struct dictionary *dict)
 {
   int i;
 
@@ -926,7 +972,7 @@ write_variable_display_parameters (struct sfm_writer *w,
 /* Writes the table of lengths for very long string variables. */
 static void
 write_vls_length_table (struct sfm_writer *w,
-                       const struct dictionary *dict)
+                        const struct dictionary *dict)
 {
   struct string map;
   int i;
@@ -1041,7 +1087,8 @@ write_long_string_missing_values (struct sfm_writer *w,
       size += 4;
       size += recode_string_len (encoding, "UTF-8", var_get_name (var), -1);
       size += 1;
-      size += mv_n_values (mv) * (4 + 8);
+      size += 4;
+      size += mv_n_values (mv) * 8;
     }
   if (size == 0)
     return;
@@ -1071,11 +1118,11 @@ write_long_string_missing_values (struct sfm_writer *w,
       n_missing_values = mv_n_values (mv);
       write_bytes (w, &n_missing_values, 1);
 
+      write_int (w, 8);
+
       for (j = 0; j < n_missing_values; j++)
         {
           const union value *value = mv_get_value (mv, j);
-
-          write_int (w, 8);
           write_bytes (w, value->s, 8);
         }
     }
@@ -1083,7 +1130,7 @@ write_long_string_missing_values (struct sfm_writer *w,
 
 static void
 write_encoding_record (struct sfm_writer *w,
-                      const struct dictionary *d)
+                       const struct dictionary *d)
 {
   /* IANA says "...character set names may be up to 40 characters taken
      from the printable characters of US-ASCII," so character set names