Adopt use of gnulib for portability.
[pspp-builds.git] / src / sfm-write.c
index aedb5a8a4ad4d5ebe10b384912c10ccdb18d4603..e1e103e5005c247dd9477c6dbd3c280a7f7bcef8 100644 (file)
@@ -14,8 +14,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "sfm-write.h"
@@ -33,7 +33,7 @@
 #include "dictionary.h"
 #include "error.h"
 #include "file-handle.h"
-#include "getline.h"
+#include "getl.h"
 #include "hash.h"
 #include "magic.h"
 #include "misc.h"
@@ -42,6 +42,9 @@
 #include "var.h"
 #include "version.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #include "debug-print.h"
 
 /* Compression bias used by PSPP.  Values between (1 -
@@ -87,6 +90,14 @@ static int write_variable (struct sfm_writer *, struct variable *);
 static int write_value_labels (struct sfm_writer *,
                                struct variable *, int idx);
 static int write_rec_7_34 (struct sfm_writer *);
+
+static int write_longvar_table (struct sfm_writer *w, 
+                               const struct dictionary *dict);
+
+static int write_variable_display_parameters (struct sfm_writer *w, 
+                                             const struct dictionary *dict);
+
+
 static int write_documents (struct sfm_writer *, const struct dictionary *);
 static int does_dict_need_translation (const struct dictionary *);
 
@@ -98,13 +109,16 @@ var_flt64_cnt (const struct variable *v)
 
 /* Opens the system file designated by file handle FH for writing
    cases from dictionary D.  If COMPRESS is nonzero, the
-   system file will be compressed.
+   system file will be compressed.  If OMIT_LONG_NAMES is nonzero, the
+   long name table will be omitted.
 
    No reference to D is retained, so it may be modified or
-   destroyed at will after this function returns. */
+   destroyed at will after this function returns.  D is not
+   modified by this function, except to assign short names. */
 struct sfm_writer *
 sfm_open_writer (struct file_handle *fh,
-                 const struct dictionary *d, int compress)
+                 struct dictionary *d, int compress, 
+                short omit_long_names)
 {
   struct sfm_writer *w = NULL;
   int idx;
@@ -152,6 +166,7 @@ sfm_open_writer (struct file_handle *fh,
     goto error;
 
   /* Write basic variable info. */
+  dict_assign_short_names (d);
   for (i = 0; i < dict_get_var_cnt (d); i++)
     write_variable (w, dict_get_var (d, i));
 
@@ -167,10 +182,20 @@ sfm_open_writer (struct file_handle *fh,
 
   if (dict_get_documents (d) != NULL && !write_documents (w, d))
     goto error;
+
   if (!write_rec_7_34 (w))
     goto error;
 
-  /* Write record 999. */
+  if (!write_variable_display_parameters (w, d))
+    goto error;
+
+  if (!omit_long_names) 
+    {
+      if (!write_longvar_table (w, d))
+       goto error;
+    }
+
+  /* Write end-of-headers record. */
   {
     struct
       {
@@ -311,7 +336,7 @@ write_header (struct sfm_writer *w, const struct dictionary *d)
     if (label == NULL)
       label = "";
 
-    st_bare_pad_copy (hdr.file_label, label, sizeof hdr.file_label); 
+    buf_copy_str_rpad (hdr.file_label, sizeof hdr.file_label, label); 
   }
   
   memset (hdr.padding, 0, sizeof hdr.padding);
@@ -396,8 +421,7 @@ write_variable (struct sfm_writer *w, struct variable *v)
   sv.n_missing_values = nm;
   write_format_spec (&v->print, &sv.print);
   write_format_spec (&v->write, &sv.write);
-  memcpy (sv.name, v->name, strlen (v->name));
-  memset (&sv.name[strlen (v->name)], ' ', 8 - strlen (v->name));
+  buf_copy_str_rpad (sv.name, sizeof sv.name, v->short_name);
   if (!buf_write (w, &sv, sizeof sv))
     return 0;
 
@@ -543,6 +567,96 @@ write_documents (struct sfm_writer *w, const struct dictionary *d)
   return 1;
 }
 
+/* Write the alignment, width and scale values */
+static int
+write_variable_display_parameters (struct sfm_writer *w, 
+                                  const struct dictionary *dict)
+{
+  int i;
+
+  struct
+  {
+    int32 rec_type P;
+    int32 subtype P;
+    int32 elem_size P;
+    int32 n_elem P;
+  } vdp_hdr;
+
+  vdp_hdr.rec_type = 7;
+  vdp_hdr.subtype = 11;
+  vdp_hdr.elem_size = 4;
+  vdp_hdr.n_elem = w->var_cnt * 3;
+
+  if (!buf_write (w, &vdp_hdr, sizeof vdp_hdr))
+    return 0;
+
+  for ( i = 0 ; i < w->var_cnt ; ++i ) 
+    {
+      struct variable *v;
+      struct
+      {
+       int32 measure P;
+       int32 width P;
+       int32 align P;
+      }
+      params;
+
+      v = dict_get_var(dict, i);
+
+      params.measure = v->measure;
+      params.width = v->display_width;
+      params.align = v->alignment;
+      
+      if (!buf_write (w, &params, sizeof(params)))
+       return 0;
+    }
+  
+  return 1;
+}
+
+/* Writes the long variable name table */
+static int
+write_longvar_table (struct sfm_writer *w, const struct dictionary *dict)
+{
+  struct
+    {
+      int32 rec_type P;
+      int32 subtype P;
+      int32 elem_size P;
+      int32 n_elem P;
+    }
+  lv_hdr;
+
+  struct string long_name_map;
+  size_t i;
+
+  ds_init (&long_name_map, 10 * dict_get_var_cnt (dict));
+  for (i = 0; i < dict_get_var_cnt (dict); i++)
+    {
+      struct variable *v = dict_get_var (dict, i);
+      
+      if (i)
+        ds_putc (&long_name_map, '\t');
+      ds_printf (&long_name_map, "%s=%s", v->short_name, v->name);
+    }
+
+  lv_hdr.rec_type = 7;
+  lv_hdr.subtype = 13;
+  lv_hdr.elem_size = 1;
+  lv_hdr.n_elem = ds_length (&long_name_map);
+
+  if (!buf_write (w, &lv_hdr, sizeof lv_hdr)
+      || !buf_write (w, ds_data (&long_name_map), ds_length (&long_name_map)))
+    goto error;
+
+  ds_destroy (&long_name_map);
+  return 1;
+
+ error:
+  ds_destroy (&long_name_map);
+  return 0;
+}
+
 /* Writes record type 7, subtypes 3 and 4. */
 static int
 write_rec_7_34 (struct sfm_writer *w)