data-in: Eliminate "implied_decimals" parameter from data_in().
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 20 Sep 2010 03:55:06 +0000 (20:55 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 24 Sep 2010 04:13:11 +0000 (21:13 -0700)
This parameter is usually 0, so break out the associated functionality into
a new function that callers can use if they really need it.

12 files changed:
perl-module/PSPP.xs
src/data/data-in.c
src/data/data-in.h
src/language/data-io/data-parser.c
src/language/expressions/operations.def
src/language/lexer/value-parser.c
src/language/stats/flip.c
src/language/xforms/recode.c
src/ui/gui/helper.c
src/ui/gui/psppire-data-store.c
src/ui/gui/text-data-import-dialog.c
src/ui/syntax-gen.c

index ca3f873ae110be68520c63a09c4f4601ca623c06..0e918a9fc25a8b35ae03a3b985331aae61616bfe 100644 (file)
@@ -654,7 +654,7 @@ CODE:
     if ( ifmt )
       {
        struct substring ss = ss_cstr (SvPV_nolen (sv));
-       if ( ! data_in (ss, LEGACY_NATIVE, ifmt->type, 0, 0, 0,
+       if ( ! data_in (ss, LEGACY_NATIVE, ifmt->type, 0, 0,
                        sfi->dict,
                        case_data_rw (c, v),
                        var_get_width (v)) )
index 2b842b8dcd93eb71fd5324eda0c4d7bd7c8c5c8c..673ebea0599b18f42a200c42fef4c9ae75743177 100644 (file)
 
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <math.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdbool.h>
-#include <limits.h>
 
 #include "calendar.h"
+#include "dictionary.h"
+#include "format.h"
 #include "identifier.h"
+#include "libpspp/assertion.h"
+#include "libpspp/compiler.h"
+#include "libpspp/i18n.h"
+#include "libpspp/integer-format.h"
+#include "libpspp/legacy-encoding.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "libpspp/str.h"
 #include "settings.h"
 #include "value.h"
-#include "format.h"
-#include "dictionary.h"
 
-#include <libpspp/assertion.h>
-#include <libpspp/legacy-encoding.h>
-#include <libpspp/i18n.h>
-#include <libpspp/compiler.h>
-#include <libpspp/integer-format.h>
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
-#include <libpspp/str.h>
-#include "c-ctype.h"
-#include "c-strtod.h"
-#include "minmax.h"
-#include "xalloc.h"
+#include "gl/c-ctype.h"
+#include "gl/c-strtod.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -58,7 +58,6 @@ struct data_in
     const char *src_enc;        /* Encoding of source. */
     struct substring input;     /* Source. */
     enum fmt_type format;       /* Input format. */
-    int implied_decimals;       /* Number of implied decimal places. */
 
     union value *output;        /* Destination. */
     int width;                  /* Output width. */
@@ -77,7 +76,6 @@ typedef bool data_in_parser_func (struct data_in *);
 static void data_warning (const struct data_in *, const char *, ...)
      PRINTF_FORMAT (2, 3);
 
-static void apply_implied_decimals (struct data_in *);
 static void default_result (struct data_in *);
 static bool trim_spaces_and_check_missing (struct data_in *);
 
@@ -90,24 +88,11 @@ static int hexit_value (int c);
    otherwise the string width).
    Iff FORMAT is a string format, then DICT must be a pointer
    to the dictionary associated with OUTPUT.  Otherwise, DICT
-   may be null.
-
-   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 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.) */
+   may be null. */
 bool
 data_in (struct substring input, const char *encoding,
-         enum fmt_type format, int implied_decimals,
-         int first_column, int last_column,
-        const struct dictionary *dict,
-        union value *output, int width)
+         enum fmt_type format, int first_column, int last_column,
+         const struct dictionary *dict, union value *output, int width)
 {
   static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
     {
@@ -123,7 +108,6 @@ data_in (struct substring input, const char *encoding,
   assert ((width != 0) == fmt_is_string (format));
 
   i.format = format;
-  i.implied_decimals = implied_decimals;
 
   i.output = output;
   i.width = width;
@@ -166,6 +150,98 @@ data_in (struct substring input, const char *encoding,
   return ok;
 }
 
+static bool
+number_has_implied_decimals (const char *s, enum fmt_type type)
+{
+  int decimal = settings_get_style (type)->decimal;
+  bool got_digit = false;
+  for (;;)
+    {
+      switch (*s)
+        {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+          got_digit = true;
+          break;
+
+        case '+': case '-':
+          if (got_digit)
+            return false;
+          break;
+
+        case 'e': case 'E': case 'd': case 'D':
+          return false;
+
+        case '.': case ',':
+          if (*s == decimal)
+            return false;
+          break;
+
+        case '\0':
+          return true;
+
+        default:
+          break;
+        }
+
+      s++;
+    }
+}
+
+static bool
+has_implied_decimals (struct substring input, const char *encoding,
+                      enum fmt_type format)
+{
+  bool retval;
+  char *s;
+
+  switch (format)
+    {
+    case FMT_F:
+    case FMT_COMMA:
+    case FMT_DOT:
+    case FMT_DOLLAR:
+    case FMT_PCT:
+    case FMT_E:
+    case FMT_Z:
+      break;
+
+    case FMT_N:
+    case FMT_IB:
+    case FMT_PIB:
+    case FMT_P:
+    case FMT_PK:
+      return true;
+
+    default:
+      return false;
+    }
+
+  s = recode_string (LEGACY_NATIVE, encoding,
+                     ss_data (input), ss_length (input));
+  retval = (format == FMT_Z
+            ? strchr (s, '.') == NULL
+            : number_has_implied_decimals (s, format));
+  free (s);
+
+  return retval;
+}
+
+/* In some cases, when no decimal point is explicitly included in numeric
+   input, its position is implied by the number of decimal places in the input
+   format.  In such a case, this function may be called just after data_in().
+   Its arguments are a subset of that function's arguments plus D, the number
+   of decimal places associated with FORMAT.
+
+   If it is appropriate, this function modifies the numeric value in OUTPUT. */
+void
+data_in_imply_decimals (struct substring input, const char *encoding,
+                        enum fmt_type format, int d, union value *output)
+{
+  if (d > 0 && output->f != SYSMIS
+      && has_implied_decimals (input, encoding, format))
+    output->f /= pow (10., d);
+}
 \f
 /* Format parsers. */
 
@@ -303,8 +379,6 @@ parse_number (struct data_in *i)
   else
     {
       errno = save_errno;
-      if (!explicit_decimals)
-        apply_implied_decimals (i);
     }
 
   ds_destroy (&tmp);
@@ -328,7 +402,6 @@ parse_N (struct data_in *i)
       i->output->f = i->output->f * 10.0 + (c - '0');
     }
 
-  apply_implied_decimals (i);
   return true;
 }
 
@@ -484,11 +557,7 @@ parse_Z (struct data_in *i)
         }
     }
   else
-    {
-      errno = save_errno;
-      if (!got_dot)
-        apply_implied_decimals (i);
-    }
+    errno = save_errno;
 
   ds_destroy (&tmp);
   return true;
@@ -515,8 +584,6 @@ parse_IB (struct data_in *i)
       i->output->f = -(double) -value;
     }
 
-  apply_implied_decimals (i);
-
   return true;
 }
 
@@ -527,8 +594,6 @@ parse_PIB (struct data_in *i)
   i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
                               MIN (8, ss_length (i->input)));
 
-  apply_implied_decimals (i);
-
   return true;
 }
 
@@ -568,8 +633,6 @@ parse_P (struct data_in *i)
   else if (low_nibble == 0xb || low_nibble == 0xd)
     i->output->f = -i->output->f;
 
-  apply_implied_decimals (i);
-
   return true;
 }
 
@@ -591,8 +654,6 @@ parse_PK (struct data_in *i)
       i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
     }
 
-  apply_implied_decimals (i);
-
   return true;
 }
 
@@ -1165,6 +1226,7 @@ parse_date (struct data_in *i)
 
   return true;
 }
+
 \f
 /* Utility functions. */
 
@@ -1195,14 +1257,6 @@ data_warning (const struct data_in *i, const char *format, ...)
   msg_emit (&m);
 }
 
-/* Apply implied decimal places to output. */
-static void
-apply_implied_decimals (struct data_in *i)
-{
-  if (i->implied_decimals > 0)
-    i->output->f /= pow (10., i->implied_decimals);
-}
-
 /* Sets the default result for I.
    For a numeric format, this is the value set on SET BLANKS
    (typically system-missing); for a string format, it is all
index 3ebd5933c43b0370e29cfd279cd3b22fcdbb0b4d..af62b3aecba9ec019356d179005b8a633184de36 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, 2010 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
 #define DATA_DATA_IN_H 1
 
 #include <stdbool.h>
-#include <libpspp/legacy-encoding.h>
-#include <libpspp/float-format.h>
-#include <libpspp/integer-format.h>
-#include <libpspp/str.h>
-#include <data/format.h>
+#include "data/format.h"
+#include "libpspp/legacy-encoding.h"
+#include "libpspp/str.h"
 
-enum fmt_type;
 union value;
 struct dictionary;
+
 bool data_in (struct substring input, const char *encoding,
-              enum fmt_type, int implied_decimals,
-              int first_column, int last_column,
-             const struct dictionary *dict,
-              union value *output, int width);
+               enum fmt_type, int first_column, int last_column,
+               const struct dictionary *dict,
+               union value *output, int width);
+
+void data_in_imply_decimals (struct substring input, const char *encoding,
+                             enum fmt_type format, int d, union value *output);
 
 #endif /* data/data-in.h */
index 2d7f9f4cd4a0528ba1131cc51daa7a43f9df13aa..0802bba8c5971117b2ebf9db50ca7ed35b9a0d02 100644 (file)
@@ -531,13 +531,18 @@ parse_fixed (const struct data_parser *parser, struct dfm_reader *reader,
       line = dfm_get_record (reader);
 
       for (; f < &parser->fields[parser->field_cnt] && f->record == row; f++)
-        data_in (ss_substr (line, f->first_column - 1,
-                            f->format.w),
-                 encoding, f->format.type, f->format.d,
-                 f->first_column, f->first_column + f->format.w,
-                parser->dict,
-                 case_data_rw_idx (c, f->case_idx),
-                 fmt_var_width (&f->format));
+        {
+          struct substring s = ss_substr (line, f->first_column - 1,
+                                          f->format.w);
+          union value *value = case_data_rw_idx (c, f->case_idx);
+
+          data_in (s, encoding, f->format.type,
+                   f->first_column, f->first_column + f->format.w,
+                   parser->dict, value, fmt_var_width (&f->format));
+
+          data_in_imply_decimals (s, encoding, f->format.type, f->format.d,
+                                  value);
+        }
 
       dfm_forward_record (reader);
     }
@@ -577,8 +582,7 @@ parse_delimited_span (const struct data_parser *parser,
            }
        }
 
-      data_in (s, encoding, f->format.type, 0,
-               first_column, last_column,
+      data_in (s, encoding, f->format.type, first_column, last_column,
               parser->dict,
                case_data_rw_idx (c, f->case_idx),
                fmt_var_width (&f->format));
@@ -619,8 +623,7 @@ parse_delimited_no_span (const struct data_parser *parser,
           goto exit;
        }
 
-      data_in (s, encoding, f->format.type, 0,
-               first_column, last_column,
+      data_in (s, encoding, f->format.type, first_column, last_column,
               parser->dict,
                case_data_rw_idx (c, f->case_idx),
                fmt_var_width (&f->format));
index c25f113c319c4b214a46c923d2fdceffcf46fc75..a945f7bf998a25c25e28a97b2f14348680c85e26 100644 (file)
@@ -581,7 +581,8 @@ string function RTRIM (string s, string c)
 function NUMBER (string s, ni_format f)
 {
   union value out;
-  data_in (ss_head (s, f->w), LEGACY_NATIVE, f->type, f->d, 0, 0, NULL, &out, 0);
+  data_in (ss_head (s, f->w), LEGACY_NATIVE, f->type, 0, 0, NULL, &out, 0);
+  data_in_imply_decimals (s, LEGACY_NATIVE, f->type, f->d, &out);
   return out.f;
 }
 
index 6fa4319a6584fdedda62f9df0532e08385e416a0..c2020d36581bf9263cbf366884aa2071c4643f17 100644 (file)
@@ -104,8 +104,8 @@ parse_number (struct lexer *lexer, double *x, const enum fmt_type *format)
     {
       union value v;
       assert (! (fmt_get_category (*format) & ( FMT_CAT_STRING )));
-      data_in (ds_ss (lex_tokstr (lexer)), LEGACY_NATIVE,
-               *format, 0, 0, 0, NULL, &v, 0);
+      data_in (ds_ss (lex_tokstr (lexer)), LEGACY_NATIVE, *format, 0, 0,
+               NULL, &v, 0);
       lex_get (lexer);
       *x = v.f;
       if (*x == SYSMIS)
index a0e1e284174550e807f269c088953f677636d041..3474979aa2702f3163d0223f33a37227f5c26e37 100644 (file)
@@ -405,7 +405,7 @@ flip_casereader_read (struct casereader *reader, void *flip_)
 
   c = case_create (casereader_get_proto (reader));
   data_in (ss_cstr (flip->old_names.names[flip->cases_read]), dict_get_encoding (flip->dict), 
-       FMT_A, 0,
+       FMT_A,
        0, 0,
        flip->dict, 
        case_data_rw_idx (c, 0), 8);
index 8c44e14697e2804ffd4fdf8a839dcc27c3e2a87b..7f45865739ce4691cba7fa984a5b64a933267740 100644 (file)
@@ -632,7 +632,7 @@ find_src_string (struct recode_trns *trns, const uint8_t *value,
 
             msg_disable ();
             match = data_in (ss_buffer (CHAR_CAST_BUG (char *, value), width),
-                             LEGACY_NATIVE, FMT_F, 0, 0, 0, trns->dst_dict,
+                             LEGACY_NATIVE, FMT_F, 0, 0, trns->dst_dict,
                              &uv, 0);
             msg_enable ();
             out->value.f = uv.f;
index 9a1172a4db3329fd93f8bbcb75ac0d5a78839764..70e3c27394e7dbf913c3de93939d0bb8e12da1d4 100644 (file)
@@ -98,9 +98,7 @@ text_to_value (const gchar *text,
 
   value_init (val, width);
   msg_disable ();
-  data_in (ss_cstr (text), UTF8, format->type, 0, 0, 0,
-               dict->dict,
-                val, width);
+  data_in (ss_cstr (text), UTF8, format->type, 0, 0, dict->dict, val, width);
   msg_enable ();
 
   return val;
index 9a59638fc897fe1239fbfacb990f7d1277134391..fb9c81797f54a995c09a9e5d95ce872bdb935960 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2006, 2008, 2009  Free Software Foundation
+   Copyright (C) 2006, 2008, 2009, 2010  Free Software Foundation
 
    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
@@ -959,8 +959,7 @@ psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
                         FALSE);
   value_init (&value, width);
   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
-        && data_in (input, UTF8, fmt->type, 0, 0, 0,
-                   dict->dict, &value, width)
+        && data_in (input, UTF8, fmt->type, 0, 0, dict->dict, &value, width)
         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
   value_destroy (&value, width);
 
index 3eda12f83ac35ac63c283a0719de99459adad2ec..070c4f6b3cd3b05b3428994cb307326463599a6c 100644 (file)
@@ -1777,8 +1777,7 @@ parse_field (struct import_assistant *ia,
     {
       msg_disable ();
 
-      if (!data_in (field, LEGACY_NATIVE, in->type, 0, 0, 0,
-                   ia->formats.dict,
+      if (!data_in (field, LEGACY_NATIVE, in->type, 0, 0, ia->formats.dict,
                     &val, var_get_width (var)))
         {
           char fmt_string[FMT_STRING_LEN_MAX + 1];
index 229e478161299794664b7048eb464fb69b7bfb81..b204fbf6f314929fc8656aac20d3002624612818 100644 (file)
@@ -155,7 +155,7 @@ syntax_gen_number (struct string *output,
       msg_disable ();
       /* FIXME: UTF8 encoded strings will fail here */
       ok = data_in (ss_cstr (s), LEGACY_NATIVE,
-                    format->type, false, 0, 0, NULL, &v_out, 0);
+                    format->type, 0, 0, NULL, &v_out, 0);
       msg_enable ();
       if (ok && v_out.f == number)
         {