X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdata-in.c;h=33eeb111384971179087e368c3bff10005ce8b54;hb=db7d86c511e47ccbf28263889c8060fd3a97edbc;hp=e72d1b6ad4e1fd45ff5026f301bd3ee034e4b4b3;hpb=c41cd1fefc98bb4abed33754276d93db9ffe2e0e;p=pspp diff --git a/src/data/data-in.c b/src/data/data-in.c index e72d1b6ad4..33eeb11138 100644 --- a/src/data/data-in.c +++ b/src/data/data-in.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 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 @@ -76,7 +76,11 @@ static int hexit_value (int c); Stores the parsed representation in OUTPUT, which the caller must have initialized with the given WIDTH (0 for a numeric field, otherwise the string width). If FORMAT is FMT_A, then OUTPUT_ENCODING must specify the - correct encoding for OUTPUT (normally obtained via dict_get_encoding()). */ + correct encoding for OUTPUT (normally obtained via dict_get_encoding()). + + If successful NULL is the return value. Otherwise a string describing + the problem is returned. The caller must free this string. + */ char * data_in (struct substring input, const char *input_encoding, enum fmt_type format, @@ -109,7 +113,7 @@ data_in (struct substring input, const char *input_encoding, } cat = fmt_get_category (format); - if (cat & (FMT_CAT_BASIC | FMT_CAT_HEXADECIMAL + if (cat & (FMT_CAT_BASIC | FMT_CAT_HEXADECIMAL | FMT_CAT_CUSTOM | FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT)) { /* We're going to parse these into numbers. For this purpose we want to @@ -168,7 +172,7 @@ data_in_msg (struct substring input, const char *input_encoding, output, width, output_encoding); if (error != NULL) { - msg (SW,_("Data is not valid as format %s: %s"), + msg (SW, _("Data is not valid as format %s: %s"), fmt_name (format), error); free (error); return false; @@ -281,7 +285,6 @@ parse_number (struct data_in *i) struct string tmp; - bool explicit_decimals = false; int save_errno; char *tail; @@ -334,7 +337,6 @@ parse_number (struct data_in *i) /* Decimal point and following digits. */ if (ss_match_byte (&i->input, style->decimal)) { - explicit_decimals = true; ds_put_byte (&tmp, '.'); while (c_isdigit (ss_first (i->input))) ds_put_byte (&tmp, ss_get_byte (&i->input)); @@ -345,7 +347,6 @@ parse_number (struct data_in *i) && !ss_is_empty (i->input) && strchr ("eEdD-+", ss_first (i->input))) { - explicit_decimals = true; ds_put_byte (&tmp, 'e'); if (strchr ("eEdD", ss_first (i->input))) @@ -698,7 +699,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. */ - uint8_t *dst = value_str_rw (i->output, i->width); + uint8_t *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); @@ -715,7 +716,7 @@ parse_A (struct data_in *i) static char * parse_AHEX (struct data_in *i) { - uint8_t *s = value_str_rw (i->output, i->width); + uint8_t *s = i->output->s; size_t j; for (j = 0; ; j++) @@ -782,20 +783,11 @@ parse_day (struct data_in *i, long *day) return xasprintf (_("Day (%ld) must be between 1 and 31."), *day); } -/* Parses an integer from the beginning of I. - Adds SECONDS_PER_UNIT times the absolute value of the integer - to *TIME. - If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the - time and sets *TIME_SIGN. Otherwise, does not allow a sign. - Returns true if successful, false if no integer was present. */ -static char * -parse_time_units (struct data_in *i, double seconds_per_unit, - enum time_sign *time_sign, double *time) - +/* If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the + time and sets *TIME_SIGN. Otherwise, does not allow a sign. */ +static void +parse_time_sign (struct data_in *i, enum time_sign *time_sign) { - char *error; - long units; - if (*time_sign == SIGN_NO_TIME) { if (ss_match_byte (&i->input, '-')) @@ -806,6 +798,19 @@ parse_time_units (struct data_in *i, double seconds_per_unit, *time_sign = SIGN_POSITIVE; } } +} + +/* Parses an integer from the beginning of I. + Adds SECONDS_PER_UNIT times the absolute value of the integer + to *TIME. + Returns true if successful, false if no integer was present. */ +static char * +parse_time_units (struct data_in *i, double seconds_per_unit, double *time) + +{ + char *error; + long units; + error = parse_int (i, &units, SIZE_MAX); if (error != NULL) return error; @@ -922,7 +927,7 @@ parse_year (struct data_in *i, long *year, size_t max_digits) else *year += epoch_century + 100; } - if (*year >= 1582 || *year <= 19999) + if (*year >= 1582 && *year <= 19999) return NULL; return xasprintf (_("Year (%ld) must be between 1582 and 19999."), *year); @@ -1028,7 +1033,7 @@ parse_minute_second (struct data_in *i, double *time) error = parse_int (i, &minute, SIZE_MAX); if (error != NULL) return error; - if (minute < 0 || minute > 59) + if (i->format != FMT_MTIME && (minute < 0 || minute > 59)) return xasprintf (_("Minute (%ld) must be between 0 and 59."), minute); *time += 60. * minute; @@ -1047,7 +1052,7 @@ parse_minute_second (struct data_in *i, double *time) *cp++ = ss_get_byte (&i->input); *cp = '\0'; - *time += strtod (buf, NULL); + *time += c_strtod (buf, NULL); return NULL; } @@ -1112,7 +1117,7 @@ parse_MONTH (struct data_in *i) } /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR, - DATETIME, TIME and DTIME formats. */ + DATETIME, YMDHMS, MTIME, TIME, and DTIME formats. */ static char * parse_date (struct data_in *i) { @@ -1123,7 +1128,7 @@ parse_date (struct data_in *i) double time = 0, date = 0; enum time_sign time_sign = SIGN_NO_TIME; - const char *template = fmt_date_template (i->format); + const char *template = fmt_date_template (i->format, 0); size_t template_width = strlen (template); char *error; @@ -1169,25 +1174,34 @@ parse_date (struct data_in *i) error = parse_week (i, &yday); break; case 'D': - error = parse_time_units (i, 60. * 60. * 24., &time_sign, &time); + parse_time_sign (i, &time_sign); + error = parse_time_units (i, 60. * 60. * 24., &time); break; case 'H': - error = parse_time_units (i, 60. * 60., &time_sign, &time); + parse_time_sign (i, &time_sign); + error = parse_time_units (i, 60. * 60., &time); break; case 'M': + if (i->format == FMT_MTIME) + parse_time_sign (i, &time_sign); error = parse_minute_second (i, &time); break; case '-': case '/': case '.': - case 'X': error = parse_date_delimiter (i); break; case ':': error = parse_time_delimiter (i); + break; case ' ': - parse_spaces (i); - error = NULL; + if (i->format != FMT_MOYR) + { + parse_spaces (i); + error = NULL; + } + else + error = parse_date_delimiter (i); break; default: assert (count == 1); @@ -1232,7 +1246,7 @@ static void default_result (struct data_in *i) { if (fmt_is_string (i->format)) - memset (value_str_rw (i->output, i->width), ' ', i->width); + memset (i->output->s, ' ', i->width); else i->output->f = settings_get_blanks (); }