X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdata-in.c;h=d84b806a77003d364422716fe336d06ad5708831;hb=6e22b03f96f0edbace5bce45abdc57e94cf6957c;hp=75e22a4840dedc91980d9d5e90d09f4a6cf7bc07;hpb=c3bd77adba5746aae895e6a354aada4e694c0e3f;p=pspp-builds.git diff --git a/src/data/data-in.c b/src/data/data-in.c index 75e22a48..d84b806a 100644 --- a/src/data/data-in.c +++ b/src/data/data-in.c @@ -34,15 +34,15 @@ #include "value.h" #include +#include #include #include #include #include #include - #include "c-ctype.h" +#include "c-strtod.h" #include "minmax.h" -#include "size_max.h" #include "xalloc.h" #include "gettext.h" @@ -51,6 +51,7 @@ /* Information about parsing one data field. */ struct data_in { + enum legacy_encoding encoding;/* Encoding of source. */ struct substring input; /* Source. */ enum fmt_type format; /* Input format. */ int implied_decimals; /* Number of implied decimal places. */ @@ -84,9 +85,10 @@ static bool trim_spaces_and_check_missing (struct data_in *); static int hexit_value (int c); -/* Parses the characters in INPUT according to FORMAT. Stores - the parsed representation in OUTPUT, which has the given WIDTH - (0 for a numeric field, otherwise the string width). +/* 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). If no decimal point is included in a numeric format, then IMPLIED_DECIMALS decimal places are implied. Specify 0 if no @@ -96,7 +98,7 @@ static int hexit_value (int c); column number of the first character in INPUT, used in error messages. */ bool -data_in (struct substring input, +data_in (struct substring input, enum legacy_encoding encoding, enum fmt_type format, int implied_decimals, int first_column, union value *output, int width) { @@ -107,11 +109,25 @@ data_in (struct substring input, }; struct data_in i; + void *copy = NULL; bool ok; assert ((width != 0) == fmt_is_string (format)); - i.input = input; + if (encoding == LEGACY_NATIVE + || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING)) + { + i.input = input; + i.encoding = encoding; + } + else + { + ss_alloc_uninit (&i.input, ss_length (input)); + legacy_recode (encoding, ss_data (input), LEGACY_NATIVE, + ss_data (i.input), ss_length (input)); + i.encoding = LEGACY_NATIVE; + copy = ss_data (i.input); + } i.format = format; i.implied_decimals = implied_decimals; @@ -133,6 +149,9 @@ data_in (struct substring input, ok = true; } + if (copy) + free (copy); + return ok; } @@ -272,10 +291,10 @@ parse_number (struct data_in *i) return false; } - /* Let strtod() do the conversion. */ + /* Let c_strtod() do the conversion. */ save_errno = errno; errno = 0; - i->output->f = strtod (ds_cstr (&tmp), &tail); + i->output->f = c_strtod (ds_cstr (&tmp), &tail); if (*tail != '\0') { data_warning (i, _("Invalid numeric syntax.")); @@ -462,10 +481,10 @@ parse_Z (struct data_in *i) return false; } - /* Let strtod() do the conversion. */ + /* Let c_strtod() do the conversion. */ save_errno = errno; errno = 0; - i->output->f = strtod (ds_cstr (&tmp), NULL); + i->output->f = c_strtod (ds_cstr (&tmp), NULL); if (errno == ERANGE) { if (fabs (i->output->f) > 1) @@ -610,8 +629,17 @@ parse_RB (struct data_in *i) static bool parse_A (struct data_in *i) { - buf_copy_rpad (i->output->s, i->width, - ss_data (i->input), ss_length (i->input)); + /* This is equivalent to buf_copy_rpad, except that we posibly + do a character set recoding in the middle. */ + char *dst = i->output->s; + size_t dst_size = i->width; + const char *src = ss_data (i->input); + size_t src_size = ss_length (i->input); + + legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size)); + if (dst_size > src_size) + memset (&dst[src_size], ' ', dst_size - src_size); + return true; } @@ -633,6 +661,11 @@ parse_AHEX (struct data_in *i) return false; } + if (i->encoding != LEGACY_NATIVE) + { + hi = legacy_to_native (i->encoding, hi); + lo = legacy_to_native (i->encoding, lo); + } if (!c_isxdigit (hi) || !c_isxdigit (lo)) { data_warning (i, _("Field must contain only hex digits.")); @@ -762,7 +795,7 @@ parse_name_token (struct data_in *i) exact matches (except for case) are allowed. Returns true if successful, false otherwise. */ static bool -match_name (struct substring token, const char **names, long *output) +match_name (struct substring token, const char *const *names, long *output) { int i; @@ -791,14 +824,14 @@ parse_month (struct data_in *i, long *month) } else { - static const char *english_names[] = + static const char *const english_names[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", NULL, }; - static const char *roman_names[] = + static const char *const roman_names[] = { "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", @@ -979,7 +1012,7 @@ parse_minute_second (struct data_in *i, double *time) static bool parse_weekday (struct data_in *i, long *weekday) { - static const char *weekday_names[] = + static const char *const weekday_names[] = { "su", "mo", "tu", "we", "th", "fr", "sa", NULL,