Change how checking for missing values works.
[pspp] / src / data / csv-file-writer.c
index cbc617b3d2a2634e77fe35ac1d02be2039308591..c00a2cffed4df0a5a91e87b21f05ed8780d07fbe 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2010, 2011, 2012, 2013, 2014 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
@@ -33,7 +33,6 @@
 #include "data/data-out.h"
 #include "data/dictionary.h"
 #include "data/file-handle-def.h"
-#include "data/file-name.h"
 #include "data/format.h"
 #include "data/make-file.h"
 #include "data/missing-values.h"
@@ -88,19 +87,6 @@ static void write_var_names (struct csv_writer *, const struct dictionary *);
 static bool write_error (const struct csv_writer *);
 static bool close_writer (struct csv_writer *);
 
-/* Initializes OPTS with default options for writing a CSV file. */
-void
-csv_writer_options_init (struct csv_writer_options *opts)
-{
-  opts->recode_user_missing = false;
-  opts->include_var_names = false;
-  opts->use_value_labels = false;
-  opts->use_print_formats = false;
-  opts->decimal = settings_get_decimal_char (FMT_F);
-  opts->delimiter = 0;
-  opts->qualifier = '"';
-}
-
 /* Opens the CSV file designated by file handle FH for writing cases from
    dictionary DICT according to the given OPTS.
 
@@ -124,7 +110,7 @@ csv_writer_open (struct file_handle *fh, const struct dictionary *dict,
 
   w->encoding = xstrdup (dict_get_encoding (dict));
 
-  w->n_csv_vars = dict_get_var_cnt (dict);
+  w->n_csv_vars = dict_get_n_vars (dict);
   w->csv_vars = xnmalloc (w->n_csv_vars, sizeof *w->csv_vars);
   for (i = 0; i < w->n_csv_vars; i++)
     {
@@ -154,11 +140,10 @@ csv_writer_open (struct file_handle *fh, const struct dictionary *dict,
     goto error;
 
   /* Create the file on disk. */
-  w->rf = replace_file_start (fh_get_file_name (fh), "w", 0666,
-                              &w->file, NULL);
+  w->rf = replace_file_start (fh, "w", 0666,  &w->file);
   if (w->rf == NULL)
     {
-      msg (ME, _("Error opening `%s' for writing as a system file: %s."),
+      msg (ME, _("Error opening `%s' for writing as a CSV file: %s."),
            fh_get_file_name (fh), strerror (errno));
       goto error;
     }
@@ -200,6 +185,12 @@ csv_output_buffer (struct csv_writer *w, const char *s, size_t len)
       putc (w->opts.qualifier, w->file);
       for (p = s; p < &s[len]; p++)
         {
+          /* We are writing the output file in text mode, so transform any
+             explicit CR-LF line breaks into LF only, to allow the C library to
+             use correct system-specific new-lines. */
+          if (*p == '\r' && p[1] == '\n')
+            continue;
+
           if (*p == w->opts.qualifier)
             putc (w->opts.qualifier, w->file);
           putc (*p, w->file);
@@ -234,7 +225,8 @@ static void
 csv_output_format (struct csv_writer *w, const struct csv_var *cv,
                    const union value *value)
 {
-  char *s = data_out (value, w->encoding, &cv->format);
+  char *s = data_out (value, w->encoding, &cv->format,
+                      settings_get_fmt_settings ());
   struct substring ss = ss_cstr (s);
   if (cv->format.type != FMT_A)
     ss_trim (&ss, ss_cstr (" "));
@@ -281,6 +273,7 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv,
   else
     {
       char s[MAX (DBL_STRLEN_BOUND, 128)];
+      char *cp;
 
       switch (cv->format.type)
         {
@@ -307,12 +300,9 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv,
         case FMT_WKDAY:
         case FMT_MONTH:
           dtoastr (s, sizeof s, 0, 0, value->f);
-          if (w->opts.decimal != '.')
-            {
-              char *cp = strchr (s, '.');
-              if (cp != NULL)
-                *cp = w->opts.decimal;
-            }
+          cp = strpbrk (s, ".,");
+          if (cp != NULL)
+            *cp = w->opts.decimal;
           break;
 
         case FMT_DATE:
@@ -335,6 +325,7 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv,
           break;
 
         case FMT_DATETIME:
+        case FMT_YMDHMS:
           if (value->f < 0)
             strcpy (s, " ");
           else
@@ -348,6 +339,7 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv,
             }
           break;
 
+        case FMT_MTIME:
         case FMT_TIME:
         case FMT_DTIME:
           {
@@ -376,7 +368,7 @@ static void
 csv_write_var (struct csv_writer *w, const struct csv_var *cv,
                const union value *value)
 {
-  if (mv_is_value_missing (&cv->missing, value, MV_USER))
+  if (mv_is_value_missing (&cv->missing, value) == MV_USER)
     {
       union value missing;