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 struct substring input; /* Source. */
59 enum fmt_type format; /* Input format. */
61 union value *output; /* Destination. */
62 int width; /* Output width. */
64 int first_column; /* First column of field; 0 if inapplicable. */
65 int last_column; /* Last column. */
68 typedef bool data_in_parser_func (struct data_in *);
69 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
70 static data_in_parser_func parse_##METHOD;
73 static void data_warning (const struct data_in *, const char *, ...)
76 static void default_result (struct data_in *);
77 static bool trim_spaces_and_check_missing (struct data_in *);
79 static int hexit_value (int c);
81 /* Parses the characters in INPUT, which are encoded in the given
82 ENCODING, according to FORMAT. Stores the parsed
83 representation in OUTPUT, which the caller must have
84 initialized with the given WIDTH (0 for a numeric field,
85 otherwise the string width).
86 Iff FORMAT is a string format, then DICT must be a pointer
87 to the dictionary associated with OUTPUT. Otherwise, DICT
90 data_in (struct substring input, const char *encoding,
91 enum fmt_type format, int first_column, int last_column,
92 const struct dictionary *dict, union value *output, int width)
94 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
96 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
102 enum fmt_category cat;
103 const char *dest_encoding;
107 assert ((width != 0) == fmt_is_string (format));
114 i.first_column = first_column;
115 i.last_column = last_column;
117 if (ss_is_empty (input))
123 cat = fmt_get_category (format);
124 if (cat & (FMT_CAT_BASIC | FMT_CAT_HEXADECIMAL
125 | FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT))
127 /* We're going to parse these into numbers. For this purpose we want to
128 deal with them in the local "C" encoding. Any character not in that
129 encoding wouldn't be valid anyhow. */
130 dest_encoding = LEGACY_NATIVE;
132 else if (cat & (FMT_CAT_BINARY | FMT_CAT_LEGACY))
134 /* Don't recode these binary formats at all, since they are not text. */
135 dest_encoding = NULL;
139 assert (cat == FMT_CAT_STRING);
140 if (format == FMT_AHEX)
142 /* We want the hex digits in the local "C" encoding, even though the
143 result may not be in that encoding. */
144 dest_encoding = LEGACY_NATIVE;
148 /* Use the final output encoding. */
149 dest_encoding = dict_get_encoding (dict);
153 if (dest_encoding != NULL)
155 i.input = recode_substring_pool (dest_encoding, encoding, input, NULL);
164 ok = handlers[i.format] (&i);
174 number_has_implied_decimals (const char *s, enum fmt_type type)
176 int decimal = settings_get_style (type)->decimal;
177 bool got_digit = false;
182 case '0': case '1': case '2': case '3': case '4':
183 case '5': case '6': case '7': case '8': case '9':
192 case 'e': case 'E': case 'd': case 'D':
212 has_implied_decimals (struct substring input, const char *encoding,
213 enum fmt_type format)
240 s = recode_string (LEGACY_NATIVE, encoding,
241 ss_data (input), ss_length (input));
242 retval = (format == FMT_Z
243 ? strchr (s, '.') == NULL
244 : number_has_implied_decimals (s, format));
250 /* In some cases, when no decimal point is explicitly included in numeric
251 input, its position is implied by the number of decimal places in the input
252 format. In such a case, this function may be called just after data_in().
253 Its arguments are a subset of that function's arguments plus D, the number
254 of decimal places associated with FORMAT.
256 If it is appropriate, this function modifies the numeric value in OUTPUT. */
258 data_in_imply_decimals (struct substring input, const char *encoding,
259 enum fmt_type format, int d, union value *output)
261 if (d > 0 && output->f != SYSMIS
262 && has_implied_decimals (input, encoding, format))
263 output->f /= pow (10., d);
266 /* Format parsers. */
268 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
270 parse_number (struct data_in *i)
272 const struct fmt_number_style *style =
273 settings_get_style (i->format);
277 bool explicit_decimals = false;
281 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
283 style = settings_get_style (FMT_F);
286 /* Trim spaces and check for missing value representation. */
287 if (trim_spaces_and_check_missing (i))
290 ds_init_empty (&tmp);
291 ds_extend (&tmp, 64);
293 /* Prefix character may precede sign. */
294 if (!ss_is_empty (style->prefix))
296 ss_match_char (&i->input, ss_first (style->prefix));
297 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
301 if (ss_match_char (&i->input, '-'))
303 ds_put_char (&tmp, '-');
304 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
308 ss_match_char (&i->input, '+');
309 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
312 /* Prefix character may follow sign. */
313 if (!ss_is_empty (style->prefix))
315 ss_match_char (&i->input, ss_first (style->prefix));
316 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
319 /* Digits before decimal point. */
320 while (c_isdigit (ss_first (i->input)))
322 ds_put_char (&tmp, ss_get_char (&i->input));
323 if (style->grouping != 0)
324 ss_match_char (&i->input, style->grouping);
327 /* Decimal point and following digits. */
328 if (ss_match_char (&i->input, style->decimal))
330 explicit_decimals = true;
331 ds_put_char (&tmp, '.');
332 while (c_isdigit (ss_first (i->input)))
333 ds_put_char (&tmp, ss_get_char (&i->input));
337 if (!ds_is_empty (&tmp)
338 && !ss_is_empty (i->input)
339 && strchr ("eEdD-+", ss_first (i->input)))
341 explicit_decimals = true;
342 ds_put_char (&tmp, 'e');
344 if (strchr ("eEdD", ss_first (i->input)))
346 ss_advance (&i->input, 1);
347 ss_match_char (&i->input, ' ');
350 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
352 if (ss_get_char (&i->input) == '-')
353 ds_put_char (&tmp, '-');
354 ss_match_char (&i->input, ' ');
357 while (c_isdigit (ss_first (i->input)))
358 ds_put_char (&tmp, ss_get_char (&i->input));
361 /* Suffix character. */
362 if (!ss_is_empty (style->suffix))
363 ss_match_char (&i->input, ss_first (style->suffix));
365 if (!ss_is_empty (i->input))
367 if (ds_is_empty (&tmp))
368 data_warning (i, _("Field contents are not numeric."));
370 data_warning (i, _("Number followed by garbage."));
375 /* Let c_strtod() do the conversion. */
378 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
381 data_warning (i, _("Invalid numeric syntax."));
386 else if (errno == ERANGE)
388 if (fabs (i->output->f) > 1)
390 data_warning (i, _("Too-large number set to system-missing."));
391 i->output->f = SYSMIS;
395 data_warning (i, _("Too-small number set to zero."));
408 /* Parses N format. */
410 parse_N (struct data_in *i)
415 while ((c = ss_get_char (&i->input)) != EOF)
419 data_warning (i, _("All characters in field must be digits."));
422 i->output->f = i->output->f * 10.0 + (c - '0');
428 /* Parses PIBHEX format. */
430 parse_PIBHEX (struct data_in *i)
437 while ((c = ss_get_char (&i->input)) != EOF)
441 data_warning (i, _("Unrecognized character in field."));
444 n = n * 16.0 + hexit_value (c);
451 /* Parses RBHEX format. */
453 parse_RBHEX (struct data_in *i)
458 memset (&d, 0, sizeof d);
459 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
461 int hi = ss_get_char (&i->input);
462 int lo = ss_get_char (&i->input);
465 data_warning (i, _("Field must have even length."));
468 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
470 data_warning (i, _("Field must contain only hex digits."));
473 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
481 /* Digits for Z format. */
482 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
484 /* Returns true if C is a Z format digit, false otherwise. */
488 return c > 0 && strchr (z_digits, c) != NULL;
491 /* Returns the (absolute value of the) value of C as a Z format
494 z_digit_value (int c)
496 assert (is_z_digit (c));
497 return (strchr (z_digits, c) - z_digits) % 10;
500 /* Returns true if Z format digit C represents a negative value,
503 is_negative_z_digit (int c)
505 assert (is_z_digit (c));
506 return (strchr (z_digits, c) - z_digits) >= 20;
509 /* Parses Z format. */
511 parse_Z (struct data_in *i)
517 bool got_dot = false;
518 bool got_final_digit = false;
520 /* Trim spaces and check for missing value representation. */
521 if (trim_spaces_and_check_missing (i))
524 ds_init_empty (&tmp);
525 ds_extend (&tmp, 64);
527 ds_put_char (&tmp, '+');
528 while (!ss_is_empty (i->input))
530 int c = ss_get_char (&i->input);
531 if (c_isdigit (c) && !got_final_digit)
532 ds_put_char (&tmp, c);
533 else if (is_z_digit (c) && !got_final_digit)
535 ds_put_char (&tmp, z_digit_value (c) + '0');
536 if (is_negative_z_digit (c))
537 ds_data (&tmp)[0] = '-';
538 got_final_digit = true;
540 else if (c == '.' && !got_dot)
542 ds_put_char (&tmp, '.');
552 if (!ss_is_empty (i->input))
554 if (ds_length (&tmp) == 1)
555 data_warning (i, _("Field contents are not numeric."));
557 data_warning (i, _("Number followed by garbage."));
562 /* Let c_strtod() do the conversion. */
565 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
568 if (fabs (i->output->f) > 1)
570 data_warning (i, _("Too-large number set to system-missing."));
571 i->output->f = SYSMIS;
575 data_warning (i, _("Too-small number set to zero."));
586 /* Parses IB format. */
588 parse_IB (struct data_in *i)
594 bytes = MIN (8, ss_length (i->input));
595 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
597 sign_bit = UINT64_C(1) << (8 * bytes - 1);
598 if (!(value & sign_bit))
599 i->output->f = value;
602 /* Sign-extend to full 64 bits. */
603 value -= sign_bit << 1;
604 i->output->f = -(double) -value;
610 /* Parses PIB format. */
612 parse_PIB (struct data_in *i)
614 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
615 MIN (8, ss_length (i->input)));
620 /* Consumes the first character of S. Stores its high 4 bits in
621 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
623 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
625 int c = ss_get_char (s);
627 *high_nibble = (c >> 4) & 15;
628 *low_nibble = c & 15;
631 /* Parses P format. */
633 parse_P (struct data_in *i)
635 int high_nibble, low_nibble;
639 while (ss_length (i->input) > 1)
641 get_nibbles (&i->input, &high_nibble, &low_nibble);
642 if (high_nibble > 9 || low_nibble > 9)
644 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
647 get_nibbles (&i->input, &high_nibble, &low_nibble);
650 i->output->f = (10 * i->output->f) + high_nibble;
652 i->output->f = (10 * i->output->f) + low_nibble;
653 else if (low_nibble == 0xb || low_nibble == 0xd)
654 i->output->f = -i->output->f;
659 /* Parses PK format. */
661 parse_PK (struct data_in *i)
664 while (!ss_is_empty (i->input))
666 int high_nibble, low_nibble;
668 get_nibbles (&i->input, &high_nibble, &low_nibble);
669 if (high_nibble > 9 || low_nibble > 9)
671 i->output->f = SYSMIS;
674 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
680 /* Parses RB format. */
682 parse_RB (struct data_in *i)
684 enum float_format ff = settings_get_input_float_format ();
685 size_t size = float_get_size (ff);
686 if (ss_length (i->input) >= size)
687 float_convert (ff, ss_data (i->input),
688 FLOAT_NATIVE_DOUBLE, &i->output->f);
690 i->output->f = SYSMIS;
695 /* Parses A format. */
697 parse_A (struct data_in *i)
699 /* This is equivalent to buf_copy_rpad, except that we posibly
700 do a character set recoding in the middle. */
701 uint8_t *dst = value_str_rw (i->output, i->width);
702 size_t dst_size = i->width;
703 const char *src = ss_data (i->input);
704 size_t src_size = ss_length (i->input);
706 memcpy (dst, src, MIN (src_size, dst_size));
708 if (dst_size > src_size)
709 memset (&dst[src_size], ' ', dst_size - src_size);
714 /* Parses AHEX format. */
716 parse_AHEX (struct data_in *i)
718 uint8_t *s = value_str_rw (i->output, i->width);
723 int hi = ss_get_char (&i->input);
724 int lo = ss_get_char (&i->input);
729 data_warning (i, _("Field must have even length."));
733 if (!c_isxdigit (hi) || !c_isxdigit (lo))
735 data_warning (i, _("Field must contain only hex digits."));
740 s[j] = hexit_value (hi) * 16 + hexit_value (lo);
743 memset (&s[j], ' ', i->width - j);
748 /* Date & time format components. */
750 /* Sign of a time value. */
753 SIGN_NO_TIME, /* No time yet encountered. */
754 SIGN_POSITIVE, /* Positive time. */
755 SIGN_NEGATIVE /* Negative time. */
758 /* Parses a signed decimal integer from at most the first
759 MAX_DIGITS characters in I, storing the result into *RESULT.
760 Returns true if successful, false if no integer was
763 parse_int (struct data_in *i, long *result, size_t max_digits)
765 struct substring head = ss_head (i->input, max_digits);
766 size_t n = ss_get_long (&head, result);
769 ss_advance (&i->input, n);
774 data_warning (i, _("Syntax error in date field."));
779 /* Parses a date integer between 1 and 31 from I, storing it into
781 Returns true if successful, false if no date was present. */
783 parse_day (struct data_in *i, long *day)
785 if (!parse_int (i, day, SIZE_MAX))
787 if (*day >= 1 && *day <= 31)
790 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
794 /* Parses an integer from the beginning of I.
795 Adds SECONDS_PER_UNIT times the absolute value of the integer
797 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
798 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
799 Returns true if successful, false if no integer was present. */
801 parse_time_units (struct data_in *i, double seconds_per_unit,
802 enum time_sign *time_sign, double *time)
807 if (*time_sign == SIGN_NO_TIME)
809 if (ss_match_char (&i->input, '-'))
810 *time_sign = SIGN_NEGATIVE;
813 ss_match_char (&i->input, '+');
814 *time_sign = SIGN_POSITIVE;
817 if (!parse_int (i, &units, SIZE_MAX))
821 data_warning (i, _("Syntax error in date field."));
824 *time += units * seconds_per_unit;
828 /* Parses a data delimiter from the beginning of I.
829 Returns true if successful, false if no delimiter was
832 parse_date_delimiter (struct data_in *i)
834 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
837 data_warning (i, _("Delimiter expected between fields in date."));
841 /* Parses spaces at the beginning of I. */
843 parse_spaces (struct data_in *i)
845 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
848 static struct substring
849 parse_name_token (struct data_in *i)
851 struct substring token;
852 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
856 /* Reads a name from I and sets *OUTPUT to the value associated
857 with that name. If ALLOW_SUFFIXES is true, then names that
858 begin with one of the names are accepted; otherwise, only
859 exact matches (except for case) are allowed.
860 Returns true if successful, false otherwise. */
862 match_name (struct substring token, const char *const *names, long *output)
866 for (i = 1; *names != NULL; i++)
867 if (ss_equals_case (ss_cstr (*names++), token))
876 /* Parses a month name or number from the beginning of I,
877 storing the month (in range 1...12) into *MONTH.
878 Returns true if successful, false if no month was present. */
880 parse_month (struct data_in *i, long *month)
882 if (c_isdigit (ss_first (i->input)))
884 if (!parse_int (i, month, SIZE_MAX))
886 if (*month >= 1 && *month <= 12)
891 static const char *const english_names[] =
893 "jan", "feb", "mar", "apr", "may", "jun",
894 "jul", "aug", "sep", "oct", "nov", "dec",
898 static const char *const roman_names[] =
900 "i", "ii", "iii", "iv", "v", "vi",
901 "vii", "viii", "ix", "x", "xi", "xii",
905 struct substring token = parse_name_token (i);
906 if (match_name (ss_head (token, 3), english_names, month)
907 || match_name (ss_head (token, 4), roman_names, month))
911 data_warning (i, _("Unrecognized month format. Months may be specified "
912 "as Arabic or Roman numerals or as at least 3 letters "
913 "of their English names."));
917 /* Parses a year of at most MAX_DIGITS from the beginning of I,
918 storing a "4-digit" year into *YEAR. */
920 parse_year (struct data_in *i, long *year, size_t max_digits)
922 if (!parse_int (i, year, max_digits))
925 if (*year >= 0 && *year <= 99)
927 int epoch = settings_get_epoch ();
928 int epoch_century = ROUND_DOWN (epoch, 100);
929 int epoch_offset = epoch - epoch_century;
930 if (*year >= epoch_offset)
931 *year += epoch_century;
933 *year += epoch_century + 100;
935 if (*year >= 1582 || *year <= 19999)
938 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
942 /* Returns true if input in I has been exhausted,
945 parse_trailer (struct data_in *i)
947 if (ss_is_empty (i->input))
950 data_warning (i, _("Trailing garbage `%.*s' following date."),
951 (int) ss_length (i->input), ss_data (i->input));
955 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
956 Returns true if successful, false on failure. */
958 parse_yday (struct data_in *i, long *yday)
960 struct substring num_s;
963 ss_get_chars (&i->input, 3, &num_s);
964 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
966 data_warning (i, _("Julian day must have exactly three digits."));
969 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
971 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
979 /* Parses a quarter-of-year integer between 1 and 4 from I.
980 Stores the corresponding month into *MONTH.
981 Returns true if successful, false if no quarter was present. */
983 parse_quarter (struct data_in *i, long int *month)
987 if (!parse_int (i, &quarter, SIZE_MAX))
989 if (quarter >= 1 && quarter <= 4)
991 *month = (quarter - 1) * 3 + 1;
995 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
999 /* Parses a week-of-year integer between 1 and 53 from I,
1000 Stores the corresponding year-of-day into *YDAY.
1001 Returns true if successful, false if no week was present. */
1003 parse_week (struct data_in *i, long int *yday)
1007 if (!parse_int (i, &week, SIZE_MAX))
1009 if (week >= 1 && week <= 53)
1011 *yday = (week - 1) * 7 + 1;
1015 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
1019 /* Parses a time delimiter from the beginning of I.
1020 Returns true if successful, false if no delimiter was
1023 parse_time_delimiter (struct data_in *i)
1025 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
1028 data_warning (i, _("Delimiter expected between fields in time."));
1032 /* Parses minutes and optional seconds from the beginning of I.
1033 The time is converted into seconds, which are added to
1035 Returns true if successful, false if an error was found. */
1037 parse_minute_second (struct data_in *i, double *time)
1043 /* Parse minutes. */
1044 if (!parse_int (i, &minute, SIZE_MAX))
1046 if (minute < 0 || minute > 59)
1048 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
1051 *time += 60. * minute;
1053 /* Check for seconds. */
1054 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
1055 || !c_isdigit (ss_first (i->input)))
1058 /* Parse seconds. */
1060 while (c_isdigit (ss_first (i->input)))
1061 *cp++ = ss_get_char (&i->input);
1062 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
1064 while (c_isdigit (ss_first (i->input)))
1065 *cp++ = ss_get_char (&i->input);
1068 *time += strtod (buf, NULL);
1073 /* Parses a weekday name from the beginning of I,
1074 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
1075 Returns true if successful, false if an error was found. */
1077 parse_weekday (struct data_in *i, long *weekday)
1079 static const char *const weekday_names[] =
1081 "su", "mo", "tu", "we", "th", "fr", "sa",
1085 struct substring token = parse_name_token (i);
1086 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1088 data_warning (i, _("Unrecognized weekday name. At least the first two "
1089 "letters of an English weekday name must be "
1094 /* Date & time formats. */
1096 /* Parses WKDAY format. */
1098 parse_WKDAY (struct data_in *i)
1102 if (trim_spaces_and_check_missing (i))
1105 if (!parse_weekday (i, &weekday)
1106 || !parse_trailer (i))
1109 i->output->f = weekday;
1113 /* Parses MONTH format. */
1115 parse_MONTH (struct data_in *i)
1119 if (trim_spaces_and_check_missing (i))
1122 if (!parse_month (i, &month)
1123 || !parse_trailer (i))
1126 i->output->f = month;
1130 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1131 DATETIME, TIME and DTIME formats. */
1133 parse_date (struct data_in *i)
1135 long int year = INT_MIN;
1139 double time = 0, date = 0;
1140 enum time_sign time_sign = SIGN_NO_TIME;
1142 const char *template = fmt_date_template (i->format);
1143 size_t template_width = strlen (template);
1145 if (trim_spaces_and_check_missing (i))
1148 while (*template != '\0')
1150 unsigned char ch = *template;
1154 while (template[count] == ch)
1162 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1165 ok = parse_month (i, &month);
1170 if (!c_isalpha (*template))
1171 max_digits = SIZE_MAX;
1174 if (ss_length (i->input) >= template_width + 2)
1179 ok = parse_year (i, &year, max_digits);
1183 ok = parse_quarter (i, &month);
1186 ok = parse_week (i, &yday);
1189 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1192 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1195 ok = parse_minute_second (i, &time);
1201 ok = parse_date_delimiter (i);
1204 ok = parse_time_delimiter (i);
1209 assert (count == 1);
1210 if (!ss_match_char (&i->input, c_toupper (ch))
1211 && !ss_match_char (&i->input, c_tolower (ch)))
1213 data_warning (i, _("`%c' expected in date field."), ch);
1221 if (!parse_trailer (i))
1224 if (year != INT_MIN)
1229 ofs = calendar_gregorian_to_offset (year, month, day, &error);
1232 data_warning (i, "%s", error);
1236 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1240 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1246 /* Utility functions. */
1248 /* Outputs FORMAT with as a warning for input I. */
1250 data_warning (const struct data_in *i, const char *format, ...)
1256 ds_init_empty (&text);
1257 ds_put_char (&text, '(');
1258 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1260 va_start (args, format);
1261 ds_put_vformat (&text, format, args);
1264 m.category = MSG_C_DATA;
1265 m.severity = MSG_S_WARNING;
1266 m.text = ds_cstr (&text);
1267 m.where.file_name = NULL;
1268 m.where.line_number = 0;
1269 m.where.first_column = i->first_column;
1270 m.where.last_column = i->last_column;
1275 /* Sets the default result for I.
1276 For a numeric format, this is the value set on SET BLANKS
1277 (typically system-missing); for a string format, it is all
1280 default_result (struct data_in *i)
1282 if (fmt_is_string (i->format))
1283 memset (value_str_rw (i->output, i->width), ' ', i->width);
1285 i->output->f = settings_get_blanks ();
1288 /* Trims leading and trailing spaces from I.
1289 If the result is empty, or a single period character, then
1290 sets the default result and returns true; otherwise, returns
1293 trim_spaces_and_check_missing (struct data_in *i)
1295 ss_trim (&i->input, ss_cstr (" "));
1296 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1304 /* Returns the integer value of hex digit C. */
1308 const char s[] = "0123456789abcdef";
1309 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1311 assert (cp != NULL);