1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009, 2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
33 #include "dictionary.h"
35 #include "identifier.h"
36 #include "libpspp/assertion.h"
37 #include "libpspp/compiler.h"
38 #include "libpspp/i18n.h"
39 #include "libpspp/integer-format.h"
40 #include "libpspp/legacy-encoding.h"
41 #include "libpspp/message.h"
42 #include "libpspp/misc.h"
43 #include "libpspp/str.h"
47 #include "gl/c-ctype.h"
48 #include "gl/c-strtod.h"
49 #include "gl/minmax.h"
50 #include "gl/xalloc.h"
53 #define _(msgid) gettext (msgid)
55 /* Information about parsing one data field. */
58 const char *src_enc; /* Encoding of source. */
59 struct substring input; /* Source. */
60 enum fmt_type format; /* Input format. */
62 union value *output; /* Destination. */
63 int width; /* Output width. */
65 int first_column; /* First column of field; 0 if inapplicable. */
66 int last_column; /* Last column. */
71 typedef bool data_in_parser_func (struct data_in *);
72 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
73 static data_in_parser_func parse_##METHOD;
76 static void data_warning (const struct data_in *, const char *, ...)
79 static void default_result (struct data_in *);
80 static bool trim_spaces_and_check_missing (struct data_in *);
82 static int hexit_value (int c);
84 /* Parses the characters in INPUT, which are encoded in the given
85 ENCODING, according to FORMAT. Stores the parsed
86 representation in OUTPUT, which the caller must have
87 initialized with the given WIDTH (0 for a numeric field,
88 otherwise the string width).
89 Iff FORMAT is a string format, then DICT must be a pointer
90 to the dictionary associated with OUTPUT. Otherwise, DICT
93 data_in (struct substring input, const char *encoding,
94 enum fmt_type format, int first_column, int last_column,
95 const struct dictionary *dict, union value *output, int width)
97 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
99 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
100 #include "format.def"
108 assert ((width != 0) == fmt_is_string (format));
115 i.first_column = first_column;
116 i.last_column = last_column;
117 i.src_enc = encoding;
119 if (ss_is_empty (input))
125 if (fmt_get_category (format) & ( FMT_CAT_BINARY | FMT_CAT_HEXADECIMAL | FMT_CAT_LEGACY))
131 const char *dest_encoding;
135 assert (0 == (fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING)));
136 dest_encoding = LEGACY_NATIVE;
139 dest_encoding = dict_get_encoding (dict);
141 s = recode_string (dest_encoding, i.src_enc, ss_data (input), ss_length (input));
142 i.input = ss_cstr (s);
145 ok = handlers[i.format] (&i);
154 number_has_implied_decimals (const char *s, enum fmt_type type)
156 int decimal = settings_get_style (type)->decimal;
157 bool got_digit = false;
162 case '0': case '1': case '2': case '3': case '4':
163 case '5': case '6': case '7': case '8': case '9':
172 case 'e': case 'E': case 'd': case 'D':
192 has_implied_decimals (struct substring input, const char *encoding,
193 enum fmt_type format)
220 s = recode_string (LEGACY_NATIVE, encoding,
221 ss_data (input), ss_length (input));
222 retval = (format == FMT_Z
223 ? strchr (s, '.') == NULL
224 : number_has_implied_decimals (s, format));
230 /* In some cases, when no decimal point is explicitly included in numeric
231 input, its position is implied by the number of decimal places in the input
232 format. In such a case, this function may be called just after data_in().
233 Its arguments are a subset of that function's arguments plus D, the number
234 of decimal places associated with FORMAT.
236 If it is appropriate, this function modifies the numeric value in OUTPUT. */
238 data_in_imply_decimals (struct substring input, const char *encoding,
239 enum fmt_type format, int d, union value *output)
241 if (d > 0 && output->f != SYSMIS
242 && has_implied_decimals (input, encoding, format))
243 output->f /= pow (10., d);
246 /* Format parsers. */
248 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
250 parse_number (struct data_in *i)
252 const struct fmt_number_style *style =
253 settings_get_style (i->format);
257 bool explicit_decimals = false;
261 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
263 style = settings_get_style (FMT_F);
266 /* Trim spaces and check for missing value representation. */
267 if (trim_spaces_and_check_missing (i))
270 ds_init_empty (&tmp);
271 ds_extend (&tmp, 64);
273 /* Prefix character may precede sign. */
274 if (!ss_is_empty (style->prefix))
276 ss_match_char (&i->input, ss_first (style->prefix));
277 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
281 if (ss_match_char (&i->input, '-'))
283 ds_put_char (&tmp, '-');
284 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
288 ss_match_char (&i->input, '+');
289 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
292 /* Prefix character may follow sign. */
293 if (!ss_is_empty (style->prefix))
295 ss_match_char (&i->input, ss_first (style->prefix));
296 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
299 /* Digits before decimal point. */
300 while (c_isdigit (ss_first (i->input)))
302 ds_put_char (&tmp, ss_get_char (&i->input));
303 if (style->grouping != 0)
304 ss_match_char (&i->input, style->grouping);
307 /* Decimal point and following digits. */
308 if (ss_match_char (&i->input, style->decimal))
310 explicit_decimals = true;
311 ds_put_char (&tmp, '.');
312 while (c_isdigit (ss_first (i->input)))
313 ds_put_char (&tmp, ss_get_char (&i->input));
317 if (!ds_is_empty (&tmp)
318 && !ss_is_empty (i->input)
319 && strchr ("eEdD-+", ss_first (i->input)))
321 explicit_decimals = true;
322 ds_put_char (&tmp, 'e');
324 if (strchr ("eEdD", ss_first (i->input)))
326 ss_advance (&i->input, 1);
327 ss_match_char (&i->input, ' ');
330 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
332 if (ss_get_char (&i->input) == '-')
333 ds_put_char (&tmp, '-');
334 ss_match_char (&i->input, ' ');
337 while (c_isdigit (ss_first (i->input)))
338 ds_put_char (&tmp, ss_get_char (&i->input));
341 /* Suffix character. */
342 if (!ss_is_empty (style->suffix))
343 ss_match_char (&i->input, ss_first (style->suffix));
345 if (!ss_is_empty (i->input))
347 if (ds_is_empty (&tmp))
348 data_warning (i, _("Field contents are not numeric."));
350 data_warning (i, _("Number followed by garbage."));
355 /* Let c_strtod() do the conversion. */
358 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
361 data_warning (i, _("Invalid numeric syntax."));
366 else if (errno == ERANGE)
368 if (fabs (i->output->f) > 1)
370 data_warning (i, _("Too-large number set to system-missing."));
371 i->output->f = SYSMIS;
375 data_warning (i, _("Too-small number set to zero."));
388 /* Parses N format. */
390 parse_N (struct data_in *i)
395 while ((c = ss_get_char (&i->input)) != EOF)
399 data_warning (i, _("All characters in field must be digits."));
402 i->output->f = i->output->f * 10.0 + (c - '0');
408 /* Parses PIBHEX format. */
410 parse_PIBHEX (struct data_in *i)
417 while ((c = ss_get_char (&i->input)) != EOF)
421 data_warning (i, _("Unrecognized character in field."));
424 n = n * 16.0 + hexit_value (c);
431 /* Parses RBHEX format. */
433 parse_RBHEX (struct data_in *i)
438 memset (&d, 0, sizeof d);
439 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
441 int hi = ss_get_char (&i->input);
442 int lo = ss_get_char (&i->input);
445 data_warning (i, _("Field must have even length."));
448 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
450 data_warning (i, _("Field must contain only hex digits."));
453 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
461 /* Digits for Z format. */
462 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
464 /* Returns true if C is a Z format digit, false otherwise. */
468 return c > 0 && strchr (z_digits, c) != NULL;
471 /* Returns the (absolute value of the) value of C as a Z format
474 z_digit_value (int c)
476 assert (is_z_digit (c));
477 return (strchr (z_digits, c) - z_digits) % 10;
480 /* Returns true if Z format digit C represents a negative value,
483 is_negative_z_digit (int c)
485 assert (is_z_digit (c));
486 return (strchr (z_digits, c) - z_digits) >= 20;
489 /* Parses Z format. */
491 parse_Z (struct data_in *i)
497 bool got_dot = false;
498 bool got_final_digit = false;
500 /* Trim spaces and check for missing value representation. */
501 if (trim_spaces_and_check_missing (i))
504 ds_init_empty (&tmp);
505 ds_extend (&tmp, 64);
507 ds_put_char (&tmp, '+');
508 while (!ss_is_empty (i->input))
510 int c = ss_get_char (&i->input);
511 if (c_isdigit (c) && !got_final_digit)
512 ds_put_char (&tmp, c);
513 else if (is_z_digit (c) && !got_final_digit)
515 ds_put_char (&tmp, z_digit_value (c) + '0');
516 if (is_negative_z_digit (c))
517 ds_data (&tmp)[0] = '-';
518 got_final_digit = true;
520 else if (c == '.' && !got_dot)
522 ds_put_char (&tmp, '.');
532 if (!ss_is_empty (i->input))
534 if (ds_length (&tmp) == 1)
535 data_warning (i, _("Field contents are not numeric."));
537 data_warning (i, _("Number followed by garbage."));
542 /* Let c_strtod() do the conversion. */
545 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
548 if (fabs (i->output->f) > 1)
550 data_warning (i, _("Too-large number set to system-missing."));
551 i->output->f = SYSMIS;
555 data_warning (i, _("Too-small number set to zero."));
566 /* Parses IB format. */
568 parse_IB (struct data_in *i)
574 bytes = MIN (8, ss_length (i->input));
575 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
577 sign_bit = UINT64_C(1) << (8 * bytes - 1);
578 if (!(value & sign_bit))
579 i->output->f = value;
582 /* Sign-extend to full 64 bits. */
583 value -= sign_bit << 1;
584 i->output->f = -(double) -value;
590 /* Parses PIB format. */
592 parse_PIB (struct data_in *i)
594 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
595 MIN (8, ss_length (i->input)));
600 /* Consumes the first character of S. Stores its high 4 bits in
601 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
603 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
605 int c = ss_get_char (s);
607 *high_nibble = (c >> 4) & 15;
608 *low_nibble = c & 15;
611 /* Parses P format. */
613 parse_P (struct data_in *i)
615 int high_nibble, low_nibble;
619 while (ss_length (i->input) > 1)
621 get_nibbles (&i->input, &high_nibble, &low_nibble);
622 if (high_nibble > 9 || low_nibble > 9)
624 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
627 get_nibbles (&i->input, &high_nibble, &low_nibble);
630 i->output->f = (10 * i->output->f) + high_nibble;
632 i->output->f = (10 * i->output->f) + low_nibble;
633 else if (low_nibble == 0xb || low_nibble == 0xd)
634 i->output->f = -i->output->f;
639 /* Parses PK format. */
641 parse_PK (struct data_in *i)
644 while (!ss_is_empty (i->input))
646 int high_nibble, low_nibble;
648 get_nibbles (&i->input, &high_nibble, &low_nibble);
649 if (high_nibble > 9 || low_nibble > 9)
651 i->output->f = SYSMIS;
654 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
660 /* Parses RB format. */
662 parse_RB (struct data_in *i)
664 enum float_format ff = settings_get_input_float_format ();
665 size_t size = float_get_size (ff);
666 if (ss_length (i->input) >= size)
667 float_convert (ff, ss_data (i->input),
668 FLOAT_NATIVE_DOUBLE, &i->output->f);
670 i->output->f = SYSMIS;
675 /* Parses A format. */
677 parse_A (struct data_in *i)
679 /* This is equivalent to buf_copy_rpad, except that we posibly
680 do a character set recoding in the middle. */
681 uint8_t *dst = value_str_rw (i->output, i->width);
682 size_t dst_size = i->width;
683 const char *src = ss_data (i->input);
684 size_t src_size = ss_length (i->input);
686 memcpy (dst, src, MIN (src_size, dst_size));
688 if (dst_size > src_size)
689 memset (&dst[src_size], ' ', dst_size - src_size);
694 /* Parses AHEX format. */
696 parse_AHEX (struct data_in *i)
698 uint8_t *s = value_str_rw (i->output, i->width);
703 int hi = ss_get_char (&i->input);
704 int lo = ss_get_char (&i->input);
709 data_warning (i, _("Field must have even length."));
713 if (0 != strcmp (i->src_enc, LEGACY_NATIVE))
715 hi = legacy_to_native (i->src_enc, hi);
716 lo = legacy_to_native (i->src_enc, lo);
718 if (!c_isxdigit (hi) || !c_isxdigit (lo))
720 data_warning (i, _("Field must contain only hex digits."));
725 s[j] = hexit_value (hi) * 16 + hexit_value (lo);
728 memset (&s[j], ' ', i->width - j);
733 /* Date & time format components. */
735 /* Sign of a time value. */
738 SIGN_NO_TIME, /* No time yet encountered. */
739 SIGN_POSITIVE, /* Positive time. */
740 SIGN_NEGATIVE /* Negative time. */
743 /* Parses a signed decimal integer from at most the first
744 MAX_DIGITS characters in I, storing the result into *RESULT.
745 Returns true if successful, false if no integer was
748 parse_int (struct data_in *i, long *result, size_t max_digits)
750 struct substring head = ss_head (i->input, max_digits);
751 size_t n = ss_get_long (&head, result);
754 ss_advance (&i->input, n);
759 data_warning (i, _("Syntax error in date field."));
764 /* Parses a date integer between 1 and 31 from I, storing it into
766 Returns true if successful, false if no date was present. */
768 parse_day (struct data_in *i, long *day)
770 if (!parse_int (i, day, SIZE_MAX))
772 if (*day >= 1 && *day <= 31)
775 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
779 /* Parses an integer from the beginning of I.
780 Adds SECONDS_PER_UNIT times the absolute value of the integer
782 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
783 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
784 Returns true if successful, false if no integer was present. */
786 parse_time_units (struct data_in *i, double seconds_per_unit,
787 enum time_sign *time_sign, double *time)
792 if (*time_sign == SIGN_NO_TIME)
794 if (ss_match_char (&i->input, '-'))
795 *time_sign = SIGN_NEGATIVE;
798 ss_match_char (&i->input, '+');
799 *time_sign = SIGN_POSITIVE;
802 if (!parse_int (i, &units, SIZE_MAX))
806 data_warning (i, _("Syntax error in date field."));
809 *time += units * seconds_per_unit;
813 /* Parses a data delimiter from the beginning of I.
814 Returns true if successful, false if no delimiter was
817 parse_date_delimiter (struct data_in *i)
819 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
822 data_warning (i, _("Delimiter expected between fields in date."));
826 /* Parses spaces at the beginning of I. */
828 parse_spaces (struct data_in *i)
830 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
833 static struct substring
834 parse_name_token (struct data_in *i)
836 struct substring token;
837 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
841 /* Reads a name from I and sets *OUTPUT to the value associated
842 with that name. If ALLOW_SUFFIXES is true, then names that
843 begin with one of the names are accepted; otherwise, only
844 exact matches (except for case) are allowed.
845 Returns true if successful, false otherwise. */
847 match_name (struct substring token, const char *const *names, long *output)
851 for (i = 1; *names != NULL; i++)
852 if (ss_equals_case (ss_cstr (*names++), token))
861 /* Parses a month name or number from the beginning of I,
862 storing the month (in range 1...12) into *MONTH.
863 Returns true if successful, false if no month was present. */
865 parse_month (struct data_in *i, long *month)
867 if (c_isdigit (ss_first (i->input)))
869 if (!parse_int (i, month, SIZE_MAX))
871 if (*month >= 1 && *month <= 12)
876 static const char *const english_names[] =
878 "jan", "feb", "mar", "apr", "may", "jun",
879 "jul", "aug", "sep", "oct", "nov", "dec",
883 static const char *const roman_names[] =
885 "i", "ii", "iii", "iv", "v", "vi",
886 "vii", "viii", "ix", "x", "xi", "xii",
890 struct substring token = parse_name_token (i);
891 if (match_name (ss_head (token, 3), english_names, month)
892 || match_name (ss_head (token, 4), roman_names, month))
896 data_warning (i, _("Unrecognized month format. Months may be specified "
897 "as Arabic or Roman numerals or as at least 3 letters "
898 "of their English names."));
902 /* Parses a year of at most MAX_DIGITS from the beginning of I,
903 storing a "4-digit" year into *YEAR. */
905 parse_year (struct data_in *i, long *year, size_t max_digits)
907 if (!parse_int (i, year, max_digits))
910 if (*year >= 0 && *year <= 99)
912 int epoch = settings_get_epoch ();
913 int epoch_century = ROUND_DOWN (epoch, 100);
914 int epoch_offset = epoch - epoch_century;
915 if (*year >= epoch_offset)
916 *year += epoch_century;
918 *year += epoch_century + 100;
920 if (*year >= 1582 || *year <= 19999)
923 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
927 /* Returns true if input in I has been exhausted,
930 parse_trailer (struct data_in *i)
932 if (ss_is_empty (i->input))
935 data_warning (i, _("Trailing garbage `%.*s' following date."),
936 (int) ss_length (i->input), ss_data (i->input));
940 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
941 Returns true if successful, false on failure. */
943 parse_yday (struct data_in *i, long *yday)
945 struct substring num_s;
948 ss_get_chars (&i->input, 3, &num_s);
949 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
951 data_warning (i, _("Julian day must have exactly three digits."));
954 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
956 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
964 /* Parses a quarter-of-year integer between 1 and 4 from I.
965 Stores the corresponding month into *MONTH.
966 Returns true if successful, false if no quarter was present. */
968 parse_quarter (struct data_in *i, long int *month)
972 if (!parse_int (i, &quarter, SIZE_MAX))
974 if (quarter >= 1 && quarter <= 4)
976 *month = (quarter - 1) * 3 + 1;
980 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
984 /* Parses a week-of-year integer between 1 and 53 from I,
985 Stores the corresponding year-of-day into *YDAY.
986 Returns true if successful, false if no week was present. */
988 parse_week (struct data_in *i, long int *yday)
992 if (!parse_int (i, &week, SIZE_MAX))
994 if (week >= 1 && week <= 53)
996 *yday = (week - 1) * 7 + 1;
1000 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
1004 /* Parses a time delimiter from the beginning of I.
1005 Returns true if successful, false if no delimiter was
1008 parse_time_delimiter (struct data_in *i)
1010 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
1013 data_warning (i, _("Delimiter expected between fields in time."));
1017 /* Parses minutes and optional seconds from the beginning of I.
1018 The time is converted into seconds, which are added to
1020 Returns true if successful, false if an error was found. */
1022 parse_minute_second (struct data_in *i, double *time)
1028 /* Parse minutes. */
1029 if (!parse_int (i, &minute, SIZE_MAX))
1031 if (minute < 0 || minute > 59)
1033 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
1036 *time += 60. * minute;
1038 /* Check for seconds. */
1039 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
1040 || !c_isdigit (ss_first (i->input)))
1043 /* Parse seconds. */
1045 while (c_isdigit (ss_first (i->input)))
1046 *cp++ = ss_get_char (&i->input);
1047 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
1049 while (c_isdigit (ss_first (i->input)))
1050 *cp++ = ss_get_char (&i->input);
1053 *time += strtod (buf, NULL);
1058 /* Parses a weekday name from the beginning of I,
1059 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
1060 Returns true if successful, false if an error was found. */
1062 parse_weekday (struct data_in *i, long *weekday)
1064 static const char *const weekday_names[] =
1066 "su", "mo", "tu", "we", "th", "fr", "sa",
1070 struct substring token = parse_name_token (i);
1071 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1073 data_warning (i, _("Unrecognized weekday name. At least the first two "
1074 "letters of an English weekday name must be "
1079 /* Date & time formats. */
1081 /* Parses WKDAY format. */
1083 parse_WKDAY (struct data_in *i)
1087 if (trim_spaces_and_check_missing (i))
1090 if (!parse_weekday (i, &weekday)
1091 || !parse_trailer (i))
1094 i->output->f = weekday;
1098 /* Parses MONTH format. */
1100 parse_MONTH (struct data_in *i)
1104 if (trim_spaces_and_check_missing (i))
1107 if (!parse_month (i, &month)
1108 || !parse_trailer (i))
1111 i->output->f = month;
1115 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1116 DATETIME, TIME and DTIME formats. */
1118 parse_date (struct data_in *i)
1120 long int year = INT_MIN;
1124 double time = 0, date = 0;
1125 enum time_sign time_sign = SIGN_NO_TIME;
1127 const char *template = fmt_date_template (i->format);
1128 size_t template_width = strlen (template);
1130 if (trim_spaces_and_check_missing (i))
1133 while (*template != '\0')
1135 unsigned char ch = *template;
1139 while (template[count] == ch)
1147 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1150 ok = parse_month (i, &month);
1155 if (!c_isalpha (*template))
1156 max_digits = SIZE_MAX;
1159 if (ss_length (i->input) >= template_width + 2)
1164 ok = parse_year (i, &year, max_digits);
1168 ok = parse_quarter (i, &month);
1171 ok = parse_week (i, &yday);
1174 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1177 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1180 ok = parse_minute_second (i, &time);
1186 ok = parse_date_delimiter (i);
1189 ok = parse_time_delimiter (i);
1194 assert (count == 1);
1195 if (!ss_match_char (&i->input, c_toupper (ch))
1196 && !ss_match_char (&i->input, c_tolower (ch)))
1198 data_warning (i, _("`%c' expected in date field."), ch);
1206 if (!parse_trailer (i))
1209 if (year != INT_MIN)
1214 ofs = calendar_gregorian_to_offset (year, month, day, &error);
1217 data_warning (i, "%s", error);
1221 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1225 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1231 /* Utility functions. */
1233 /* Outputs FORMAT with as a warning for input I. */
1235 data_warning (const struct data_in *i, const char *format, ...)
1241 ds_init_empty (&text);
1242 ds_put_char (&text, '(');
1243 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1245 va_start (args, format);
1246 ds_put_vformat (&text, format, args);
1249 m.category = MSG_C_DATA;
1250 m.severity = MSG_S_WARNING;
1251 m.text = ds_cstr (&text);
1252 m.where.file_name = NULL;
1253 m.where.line_number = 0;
1254 m.where.first_column = i->first_column;
1255 m.where.last_column = i->last_column;
1260 /* Sets the default result for I.
1261 For a numeric format, this is the value set on SET BLANKS
1262 (typically system-missing); for a string format, it is all
1265 default_result (struct data_in *i)
1267 if (fmt_is_string (i->format))
1268 memset (value_str_rw (i->output, i->width), ' ', i->width);
1270 i->output->f = settings_get_blanks ();
1273 /* Trims leading and trailing spaces from I.
1274 If the result is empty, or a single period character, then
1275 sets the default result and returns true; otherwise, returns
1278 trim_spaces_and_check_missing (struct data_in *i)
1280 ss_trim (&i->input, ss_cstr (" "));
1281 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1289 /* Returns the integer value of hex digit C. */
1293 const char s[] = "0123456789abcdef";
1294 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1296 assert (cp != NULL);