GET: Add an ENCODING subcommand.
[pspp] / src / data / sys-file-writer.c
index 9586cbc2e38e503c75ede6be7ea754bd93d80a11..5003ca2b89bf1d1b4a4fbf3b98efdec02040f8b1 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1997-2000, 2006-2012 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
@@ -74,6 +74,7 @@ struct sfm_writer
 
     bool compress;             /* 1=compressed, 0=not compressed. */
     casenumber case_cnt;       /* Number of cases written so far. */
+    uint8_t space;              /* ' ' in the file's character encoding. */
 
     /* Compression buffering.
 
@@ -176,6 +177,7 @@ struct casewriter *
 sfm_open_writer (struct file_handle *fh, struct dictionary *d,
                  struct sfm_write_options opts)
 {
+  struct encoding_info encoding_info;
   struct sfm_writer *w;
   mode_t mode;
   int i;
@@ -227,6 +229,9 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d,
       goto error;
     }
 
+  get_encoding_info (&encoding_info, dict_get_encoding (d));
+  w->space = encoding_info.space[0];
+
   /* Write the file header. */
   write_header (w, d);
 
@@ -311,6 +316,7 @@ calc_oct_idx (const struct dictionary *d, struct variable *target_var)
 static void
 write_header (struct sfm_writer *w, const struct dictionary *d)
 {
+  const char *dict_encoding = dict_get_encoding (d);
   char prod_name[61];
   char creation_date[10];
   char creation_time[9];
@@ -320,12 +326,15 @@ write_header (struct sfm_writer *w, const struct dictionary *d)
   time_t t;
 
   /* Record-type code. */
-  write_string (w, "$FL2", 4);
+  if (is_encoding_ebcdic_compatible (dict_encoding))
+    write_string (w, EBCDIC_MAGIC, 4);
+  else
+    write_string (w, ASCII_MAGIC, 4);
 
   /* Product identification. */
   snprintf (prod_name, sizeof prod_name, "@(#) SPSS DATA FILE %s - %s",
             version, host_system);
-  write_string (w, prod_name, 60);
+  write_utf8_string (w, dict_encoding, prod_name, 60);
 
   /* Layout code. */
   write_int (w, 2);
@@ -374,14 +383,14 @@ write_header (struct sfm_writer *w, const struct dictionary *d)
       snprintf (creation_time, sizeof creation_time,
                 "%02d:%02d:%02d", hour - 1, min - 1, sec - 1);
     }
-  write_string (w, creation_date, 9);
-  write_string (w, creation_time, 8);
+  write_utf8_string (w, dict_encoding, creation_date, 9);
+  write_utf8_string (w, dict_encoding, creation_time, 8);
 
   /* File label. */
   file_label = dict_get_label (d);
   if (file_label == NULL)
     file_label = "";
-  write_utf8_string (w, dict_get_encoding (d), file_label, 64);
+  write_utf8_string (w, dict_encoding, file_label, 64);
 
   /* Padding. */
   write_zeros (w, 3);
@@ -708,6 +717,12 @@ write_mrsets (struct sfm_writer *w, const struct dictionary *dict,
   size_t n_mrsets;
   size_t i;
 
+  if (is_encoding_ebcdic_compatible (encoding))
+    {
+      /* FIXME. */
+      return;
+    }
+
   n_mrsets = dict_get_n_mrsets (dict);
   if (n_mrsets == 0)
     return;
@@ -952,6 +967,7 @@ static void
 write_integer_info_record (struct sfm_writer *w,
                            const struct dictionary *d)
 {
+  const char *dict_encoding = dict_get_encoding (d);
   int version_component[3];
   int float_format;
   int codepage;
@@ -973,13 +989,21 @@ write_integer_info_record (struct sfm_writer *w,
     abort ();
 
   /* Choose codepage. */
-  codepage = sys_get_codepage_from_encoding (dict_get_encoding (d));
+  codepage = sys_get_codepage_from_encoding (dict_encoding);
   if (codepage == 0)
     {
-      /* Default to "7-bit ASCII" if the codepage number is unknown, because
+      /* The codepage is unknown.  Choose a default.
+
+         For an EBCDIC-compatible encoding, use the value for EBCDIC.
+
+         For an ASCII-compatible encoding, default to "7-bit ASCII", because
          many files use this codepage number regardless of their actual
-         encoding. */
-      codepage = 2;
+         encoding.
+      */
+      if (is_encoding_ascii_compatible (dict_encoding))
+        codepage = 2;
+      else if (is_encoding_ebcdic_compatible (dict_encoding))
+        codepage = 1;
     }
 
   /* Write record. */
@@ -1238,7 +1262,7 @@ put_cmp_string (struct sfm_writer *w, const void *data, size_t size)
   assert (w->data_cnt < 8);
   assert (size <= 8);
 
-  memset (w->data[w->data_cnt], ' ', 8);
+  memset (w->data[w->data_cnt], w->space, 8);
   memcpy (w->data[w->data_cnt], data, size);
   w->data_cnt++;
 }
@@ -1300,7 +1324,7 @@ write_string (struct sfm_writer *w, const char *string, size_t width)
   size_t pad_bytes = width - data_bytes;
   write_bytes (w, string, data_bytes);
   while (pad_bytes-- > 0)
-    putc (' ', w->file);
+    putc (w->space, w->file);
 }
 
 /* Recodes null-terminated UTF-8 encoded STRING into ENCODING, and writes the
@@ -1361,5 +1385,5 @@ static void
 write_spaces (struct sfm_writer *w, size_t n)
 {
   while (n-- > 0)
-    putc (' ', w->file);
+    putc (w->space, w->file);
 }