/* 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
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,
}
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
struct string tmp;
- bool explicit_decimals = false;
int save_errno;
char *tail;
/* 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));
&& !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)))
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, '-'))
*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;
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);
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;
*cp++ = ss_get_byte (&i->input);
*cp = '\0';
- *time += strtod (buf, NULL);
+ *time += c_strtod (buf, NULL);
return NULL;
}
}
/* 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)
{
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;
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);