Change enum legacy_encoding to const char *.
[pspp-builds.git] / src / data / data-in.c
index d84b806a77003d364422716fe336d06ad5708831..e7a83f25b44a5f7a55d2c46e20aed4dc7785e40e 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009 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
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <limits.h>
 
 #include "calendar.h"
 #include "identifier.h"
 #include "settings.h"
 #include "value.h"
+#include "format.h"
 
 #include <libpspp/assertion.h>
 #include <libpspp/legacy-encoding.h>
@@ -51,7 +53,7 @@
 /* Information about parsing one data field. */
 struct data_in
   {
-    enum legacy_encoding encoding;/* Encoding of source. */
+    const char *encoding;       /* Encoding of source. */
     struct substring input;     /* Source. */
     enum fmt_type format;       /* Input format. */
     int implied_decimals;       /* Number of implied decimal places. */
@@ -63,11 +65,7 @@ struct data_in
     int last_column;           /* Last column. */
   };
 
-/* Integer format used for IB and PIB input. */
-static enum integer_format input_integer_format = INTEGER_NATIVE;
 
-/* Floating-point format used for RB and RBHEX input. */
-static enum float_format input_float_format = FLOAT_NATIVE_DOUBLE;
 
 typedef bool data_in_parser_func (struct data_in *);
 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
@@ -87,20 +85,24 @@ static int hexit_value (int c);
 \f
 /* Parses the characters in INPUT, which are encoded in the given
    ENCODING, according to FORMAT.  Stores the parsed
-   representation in OUTPUT, which has the given WIDTH (0 for
-   a numeric field, otherwise the string width).
+   representation in OUTPUT, which the caller must have
+   initialized with the given WIDTH (0 for a numeric field,
+   otherwise the string width).
 
    If no decimal point is included in a numeric format, then
    IMPLIED_DECIMALS decimal places are implied.  Specify 0 if no
    decimal places should be implied.
 
-   If FIRST_COLUMN is nonzero, then it should be the 1-based
-   column number of the first character in INPUT, used in error
-   messages. */
+   If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
+   be the 1-based column number of the first and
+   one-past-the-last-character in INPUT, for use in error
+   messages.  (LAST_COLUMN cannot always be calculated from
+   FIRST_COLUMN plus the length of the input because of the
+   possibility of escaped quotes in strings, etc.) */
 bool
-data_in (struct substring input, enum legacy_encoding encoding,
+data_in (struct substring input, const char *encoding,
          enum fmt_type format, int implied_decimals,
-         int first_column, union value *output, int width)
+         int first_column, int last_column, union value *output, int width)
 {
   static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
     {
@@ -114,7 +116,7 @@ data_in (struct substring input, enum legacy_encoding encoding,
 
   assert ((width != 0) == fmt_is_string (format));
 
-  if (encoding == LEGACY_NATIVE
+  if (0 == strcmp (encoding, LEGACY_NATIVE)
       || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
     {
       i.input = input;
@@ -135,7 +137,7 @@ data_in (struct substring input, enum legacy_encoding encoding,
   i.width = width;
 
   i.first_column = first_column;
-  i.last_column = first_column + ss_length (input) - 1;
+  i.last_column = last_column;
 
   if (!ss_is_empty (i.input))
     {
@@ -155,36 +157,6 @@ data_in (struct substring input, enum legacy_encoding encoding,
   return ok;
 }
 
-/* Returns the integer format used for IB and PIB input. */
-enum integer_format
-data_in_get_integer_format (void)
-{
-  return input_integer_format;
-}
-
-/* Sets the integer format used for IB and PIB input to
-   FORMAT. */
-void
-data_in_set_integer_format (enum integer_format format)
-{
-  input_integer_format = format;
-}
-
-/* Returns the floating-point format used for RB and RBHEX
-   input. */
-enum float_format
-data_in_get_float_format (void)
-{
-  return input_float_format;
-}
-
-/* Sets the floating-point format used for RB and RBHEX input to
-   FORMAT. */
-void
-data_in_set_float_format (enum float_format format)
-{
-  input_float_format = format;
-}
 \f
 /* Format parsers. */
 
@@ -192,7 +164,8 @@ data_in_set_float_format (enum float_format format)
 static bool
 parse_number (struct data_in *i)
 {
-  const struct fmt_number_style *style = fmt_get_style (i->format);
+  const struct fmt_number_style *style =
+    settings_get_style (i->format);
 
   struct string tmp;
 
@@ -200,7 +173,10 @@ parse_number (struct data_in *i)
   int save_errno;
   char *tail;
 
-  assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
+  if  (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
+    {
+      style = settings_get_style (FMT_F);
+    }
 
   /* Trim spaces and check for missing value representation. */
   if (trim_spaces_and_check_missing (i))
@@ -518,7 +494,7 @@ parse_IB (struct data_in *i)
   uint64_t sign_bit;
 
   bytes = MIN (8, ss_length (i->input));
-  value = integer_get (input_integer_format, ss_data (i->input), bytes);
+  value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
 
   sign_bit = UINT64_C(1) << (8 * bytes - 1);
   if (!(value & sign_bit))
@@ -539,7 +515,7 @@ parse_IB (struct data_in *i)
 static bool
 parse_PIB (struct data_in *i)
 {
-  i->output->f = integer_get (input_integer_format, ss_data (i->input),
+  i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
                               MIN (8, ss_length (i->input)));
 
   apply_implied_decimals (i);
@@ -615,9 +591,10 @@ parse_PK (struct data_in *i)
 static bool
 parse_RB (struct data_in *i)
 {
-  size_t size = float_get_size (input_float_format);
+  enum float_format ff = settings_get_input_float_format ();
+  size_t size = float_get_size (ff);
   if (ss_length (i->input) >= size)
-    float_convert (input_float_format, ss_data (i->input),
+    float_convert (ff, ss_data (i->input),
                    FLOAT_NATIVE_DOUBLE, &i->output->f);
   else
     i->output->f = SYSMIS;
@@ -631,7 +608,7 @@ parse_A (struct data_in *i)
 {
   /* This is equivalent to buf_copy_rpad, except that we posibly
      do a character set recoding in the middle. */
-  char *dst = i->output->s;
+  char *dst = value_str_rw (i->output, i->width);
   size_t dst_size = i->width;
   const char *src = ss_data (i->input);
   size_t src_size = ss_length (i->input);
@@ -647,6 +624,7 @@ parse_A (struct data_in *i)
 static bool
 parse_AHEX (struct data_in *i)
 {
+  char *s = value_str_rw (i->output, i->width);
   size_t j;
 
   for (j = 0; ; j++)
@@ -661,7 +639,7 @@ parse_AHEX (struct data_in *i)
           return false;
         }
 
-      if (i->encoding != LEGACY_NATIVE)
+      if (0 != strcmp (i->encoding, LEGACY_NATIVE))
         {
           hi = legacy_to_native (i->encoding, hi);
           lo = legacy_to_native (i->encoding, lo);
@@ -673,10 +651,10 @@ parse_AHEX (struct data_in *i)
        }
 
       if (j < i->width)
-        i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
+        s[j] = hexit_value (hi) * 16 + hexit_value (lo);
     }
 
-  memset (i->output->s + j, ' ', i->width - j);
+  memset (&s[j], ' ', i->width - j);
 
   return true;
 }
@@ -860,7 +838,7 @@ parse_year (struct data_in *i, long *year, size_t max_digits)
 
   if (*year >= 0 && *year <= 99)
     {
-      int epoch = get_epoch ();
+      int epoch = settings_get_epoch ();
       int epoch_century = ROUND_DOWN (epoch, 100);
       int epoch_offset = epoch - epoch_century;
       if (*year >= epoch_offset)
@@ -995,7 +973,7 @@ parse_minute_second (struct data_in *i, double *time)
   cp = buf;
   while (c_isdigit (ss_first (i->input)))
     *cp++ = ss_get_char (&i->input);
-  if (ss_match_char (&i->input, fmt_decimal_char (FMT_F)))
+  if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
     *cp++ = '.';
   while (c_isdigit (ss_first (i->input)))
     *cp++ = ss_get_char (&i->input);
@@ -1199,11 +1177,11 @@ vdata_warning (const struct data_in *i, const char *format, va_list args)
   ds_put_char (&text, '(');
   if (i->first_column != 0)
     {
-      if (i->first_column == i->last_column)
+      if (i->first_column == i->last_column - 1)
         ds_put_format (&text, _("column %d"), i->first_column);
       else
         ds_put_format (&text, _("columns %d-%d"),
-                       i->first_column, i->last_column);
+                       i->first_column, i->last_column - 1);
       ds_put_cstr (&text, ", ");
     }
   ds_put_format (&text, _("%s field) "), fmt_name (i->format));
@@ -1244,9 +1222,9 @@ static void
 default_result (struct data_in *i)
 {
   if (fmt_is_string (i->format))
-    memset (i->output->s, ' ', i->width);
+    memset (value_str_rw (i->output, i->width), ' ', i->width);
   else
-    i->output->f = get_blanks ();
+    i->output->f = settings_get_blanks ();
 }
 
 /* Trims leading and trailing spaces from I.