[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[pre-lexer 18/21] data-in: Eliminate "implied_decimals" parameter from d
From: |
Ben Pfaff |
Subject: |
[pre-lexer 18/21] data-in: Eliminate "implied_decimals" parameter from data_in(). |
Date: |
Thu, 23 Sep 2010 21:20:54 -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.
---
perl-module/PSPP.xs | 2 +-
src/data/data-in.c | 172 ++++++++++++++++++++-----------
src/data/data-in.h | 22 ++--
src/language/data-io/data-parser.c | 25 +++--
src/language/expressions/operations.def | 3 +-
src/language/lexer/value-parser.c | 4 +-
src/language/stats/flip.c | 2 +-
src/language/xforms/recode.c | 2 +-
src/ui/gui/helper.c | 4 +-
src/ui/gui/psppire-data-store.c | 5 +-
src/ui/gui/text-data-import-dialog.c | 3 +-
src/ui/syntax-gen.c | 2 +-
12 files changed, 150 insertions(+), 96 deletions(-)
diff --git a/perl-module/PSPP.xs b/perl-module/PSPP.xs
index ca3f873..0e918a9 100644
--- a/perl-module/PSPP.xs
+++ b/perl-module/PSPP.xs
@@ -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)) )
diff --git a/src/data/data-in.c b/src/data/data-in.c
index 2b842b8..673ebea 100644
--- a/src/data/data-in.c
+++ b/src/data/data-in.c
@@ -20,34 +20,34 @@
#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);
+}
/* 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;
}
+
/* 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
diff --git a/src/data/data-in.h b/src/data/data-in.h
index 3ebd593..af62b3a 100644
--- a/src/data/data-in.h
+++ b/src/data/data-in.h
@@ -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
@@ -18,19 +18,19 @@
#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 */
diff --git a/src/language/data-io/data-parser.c
b/src/language/data-io/data-parser.c
index 2d7f9f4..0802bba 100644
--- a/src/language/data-io/data-parser.c
+++ b/src/language/data-io/data-parser.c
@@ -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));
diff --git a/src/language/expressions/operations.def
b/src/language/expressions/operations.def
index c25f113..a945f7b 100644
--- a/src/language/expressions/operations.def
+++ b/src/language/expressions/operations.def
@@ -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;
}
diff --git a/src/language/lexer/value-parser.c
b/src/language/lexer/value-parser.c
index 6fa4319..c2020d3 100644
--- a/src/language/lexer/value-parser.c
+++ b/src/language/lexer/value-parser.c
@@ -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)
diff --git a/src/language/stats/flip.c b/src/language/stats/flip.c
index a0e1e28..3474979 100644
--- a/src/language/stats/flip.c
+++ b/src/language/stats/flip.c
@@ -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);
diff --git a/src/language/xforms/recode.c b/src/language/xforms/recode.c
index 8c44e14..7f45865 100644
--- a/src/language/xforms/recode.c
+++ b/src/language/xforms/recode.c
@@ -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;
diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c
index 9a1172a..70e3c27 100644
--- a/src/ui/gui/helper.c
+++ b/src/ui/gui/helper.c
@@ -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;
diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c
index 9a59638..fb9c817 100644
--- a/src/ui/gui/psppire-data-store.c
+++ b/src/ui/gui/psppire-data-store.c
@@ -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);
diff --git a/src/ui/gui/text-data-import-dialog.c
b/src/ui/gui/text-data-import-dialog.c
index 3eda12f..070c4f6 100644
--- a/src/ui/gui/text-data-import-dialog.c
+++ b/src/ui/gui/text-data-import-dialog.c
@@ -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];
diff --git a/src/ui/syntax-gen.c b/src/ui/syntax-gen.c
index 229e478..b204fbf 100644
--- a/src/ui/syntax-gen.c
+++ b/src/ui/syntax-gen.c
@@ -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)
{
--
1.7.1
- [pre-lexer 12/21] command: Remove INSERT from list of unimplemented commands., (continued)
- [pre-lexer 12/21] command: Remove INSERT from list of unimplemented commands., Ben Pfaff, 2010/09/24
- [pre-lexer 20/21] data-in: Make data_in() parameters more uniform., Ben Pfaff, 2010/09/24
- [pre-lexer 02/21] i18n: Use UTF8 macro instead of "UTF8" literal string., Ben Pfaff, 2010/09/24
- [pre-lexer 09/21] lexer: Improve translatability of lex_error()., Ben Pfaff, 2010/09/24
- [pre-lexer 15/21] message: Consistently initialize locator; use 0 for "no line number"., Ben Pfaff, 2010/09/24
- [pre-lexer 06/21] AGGREGATE: Simplify code., Ben Pfaff, 2010/09/24
- [pre-lexer 17/21] calendar: Use sensible error reporting in calendar_gregorian_to_offset()., Ben Pfaff, 2010/09/24
- [pre-lexer 16/21] message: Add column range to struct msg_locator., Ben Pfaff, 2010/09/24
- [pre-lexer 05/21] PERMISSIONS: Add missing check for string token., Ben Pfaff, 2010/09/24
- [pre-lexer 10/21] lexer: Remove DUMP_TOKENS debugging feature., Ben Pfaff, 2010/09/24
- [pre-lexer 18/21] data-in: Eliminate "implied_decimals" parameter from data_in().,
Ben Pfaff <=
- [pre-lexer 21/21] data-in: Get rid of first_column, last_column arguments., Ben Pfaff, 2010/09/24
- [pre-lexer 07/21] HOST: Use more modern syntax., Ben Pfaff, 2010/09/24
- Re: [pre-lexer 00/21] preparation for work on lexer, John Darrington, 2010/09/24