Fix bug #20427.
[pspp] / src / data / por-file-writer.c
index b956ef459a507b78f6756c1a2a1aefb72ebe5dc7..0bb1df60251929d656d8c8241cfca336971abad6 100644 (file)
@@ -35,6 +35,7 @@
 #include <data/file-handle-def.h>
 #include <data/format.h>
 #include <data/missing-values.h>
+#include <data/short-names.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 
@@ -49,6 +50,9 @@
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
+/* Maximum width of a variable in a portable file. */
+#define MAX_POR_WIDTH 255
+
 /* Portable file writer. */
 struct pfm_writer
   {
@@ -138,7 +142,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
     {
       const struct variable *dv = dict_get_var (dict, i);
       struct pfm_var *pv = &w->vars[i];
-      pv->width = var_get_width (dv);
+      pv->width = MIN (var_get_width (dv), MAX_POR_WIDTH);
       pv->fv = var_get_case_index (dv);
     }
 
@@ -283,13 +287,17 @@ write_version_data (struct pfm_writer *w)
   write_string (w, host_system);
 }
 
-/* Write format F to file H. */
+/* Write format F to file H.  The format is first resized to fit
+   a value of the given WIDTH, which is handy in case F
+   represents a string longer than 255 bytes and thus WIDTH is
+   truncated to 255 bytes.  */
 static void
-write_format (struct pfm_writer *w, const struct fmt_spec *f)
+write_format (struct pfm_writer *w, struct fmt_spec f, int width)
 {
-  write_int (w, fmt_to_io (f->type));
-  write_int (w, f->w);
-  write_int (w, f->d);
+  fmt_resize (&f, width);
+  write_int (w, fmt_to_io (f.type));
+  write_int (w, f.w);
+  write_int (w, f.d);
 }
 
 /* Write value V for variable VV to file H. */
@@ -300,8 +308,9 @@ write_value (struct pfm_writer *w, union value *v, struct variable *vv)
     write_float (w, v->f);
   else
     {
-      write_int (w, var_get_width (vv));
-      buf_write (w, v->s, var_get_width (vv));
+      int width = MIN (var_get_width (vv), MAX_POR_WIDTH);
+      write_int (w, width);
+      buf_write (w, v->s, width);
     }
 }
 
@@ -311,8 +320,14 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
 {
   int i;
 
-  dict_assign_short_names (dict);
+  short_names_assign (dict);
 
+  if (dict_get_weight (dict) != NULL) 
+    {
+      buf_write (w, "6", 1);
+      write_string (w, var_get_short_name (dict_get_weight (dict), 0));
+    }
+  
   buf_write (w, "4", 1);
   write_int (w, dict_get_var_cnt (dict));
   write_int (w, 161);
@@ -321,12 +336,13 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
     {
       struct variable *v = dict_get_var (dict, i);
       struct missing_values mv;
+      int width = MIN (var_get_width (v), MAX_POR_WIDTH);
 
       buf_write (w, "7", 1);
-      write_int (w, var_get_width (v));
-      write_string (w, var_get_short_name (v));
-      write_format (w, var_get_print_format (v));
-      write_format (w, var_get_write_format (v));
+      write_int (w, width);
+      write_string (w, var_get_short_name (v, 0));
+      write_format (w, *var_get_print_format (v), width);
+      write_format (w, *var_get_write_format (v), width);
 
       /* Write missing values. */
       mv_copy (&mv, var_get_missing_values (v));
@@ -386,7 +402,7 @@ write_value_labels (struct pfm_writer *w, const struct dictionary *dict)
 
       buf_write (w, "D", 1);
       write_int (w, 1);
-      write_string (w, var_get_short_name (v));
+      write_string (w, var_get_short_name (v, 0));
       write_int (w, val_labs_count (val_labs));
 
       for (vl = val_labs_first_sorted (val_labs, &j); vl != NULL;