1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006 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/>. */
32 #include "identifier.h"
36 #include <libpspp/assertion.h>
37 #include <libpspp/legacy-encoding.h>
38 #include <libpspp/compiler.h>
39 #include <libpspp/integer-format.h>
40 #include <libpspp/message.h>
41 #include <libpspp/misc.h>
42 #include <libpspp/str.h>
49 #define _(msgid) gettext (msgid)
51 /* Information about parsing one data field. */
54 enum legacy_encoding encoding;/* Encoding of source. */
55 struct substring input; /* Source. */
56 enum fmt_type format; /* Input format. */
57 int implied_decimals; /* Number of implied decimal places. */
59 union value *output; /* Destination. */
60 int width; /* Output width. */
62 int first_column; /* First column of field; 0 if inapplicable. */
63 int last_column; /* Last column. */
66 /* Integer format used for IB and PIB input. */
67 static enum integer_format input_integer_format = INTEGER_NATIVE;
69 /* Floating-point format used for RB and RBHEX input. */
70 static enum float_format input_float_format = FLOAT_NATIVE_DOUBLE;
72 typedef bool data_in_parser_func (struct data_in *);
73 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
74 static data_in_parser_func parse_##METHOD;
77 static void vdata_warning (const struct data_in *, const char *, va_list)
79 static void data_warning (const struct data_in *, const char *, ...)
82 static void apply_implied_decimals (struct data_in *);
83 static void default_result (struct data_in *);
84 static bool trim_spaces_and_check_missing (struct data_in *);
86 static int hexit_value (int c);
88 /* Parses the characters in INPUT, which are encoded in the given
89 ENCODING, according to FORMAT. Stores the parsed
90 representation in OUTPUT, which has the given WIDTH (0 for
91 a numeric field, otherwise the string width).
93 If no decimal point is included in a numeric format, then
94 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
95 decimal places should be implied.
97 If FIRST_COLUMN is nonzero, then it should be the 1-based
98 column number of the first character in INPUT, used in error
101 data_in (struct substring input, enum legacy_encoding encoding,
102 enum fmt_type format, int implied_decimals,
103 int first_column, union value *output, int width)
105 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
107 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
108 #include "format.def"
115 assert ((width != 0) == fmt_is_string (format));
117 if (encoding == LEGACY_NATIVE
118 || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
121 i.encoding = encoding;
125 ss_alloc_uninit (&i.input, ss_length (input));
126 legacy_recode (encoding, ss_data (input), LEGACY_NATIVE,
127 ss_data (i.input), ss_length (input));
128 i.encoding = LEGACY_NATIVE;
129 copy = ss_data (i.input);
132 i.implied_decimals = implied_decimals;
137 i.first_column = first_column;
138 i.last_column = first_column + ss_length (input) - 1;
140 if (!ss_is_empty (i.input))
142 ok = handlers[i.format] (&i);
158 /* Returns the integer format used for IB and PIB input. */
160 data_in_get_integer_format (void)
162 return input_integer_format;
165 /* Sets the integer format used for IB and PIB input to
168 data_in_set_integer_format (enum integer_format format)
170 input_integer_format = format;
173 /* Returns the floating-point format used for RB and RBHEX
176 data_in_get_float_format (void)
178 return input_float_format;
181 /* Sets the floating-point format used for RB and RBHEX input to
184 data_in_set_float_format (enum float_format format)
186 input_float_format = format;
189 /* Format parsers. */
191 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
193 parse_number (struct data_in *i)
195 const struct fmt_number_style *style = fmt_get_style (i->format);
199 bool explicit_decimals = false;
203 assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
205 /* Trim spaces and check for missing value representation. */
206 if (trim_spaces_and_check_missing (i))
209 ds_init_empty (&tmp);
210 ds_extend (&tmp, 64);
212 /* Prefix character may precede sign. */
213 if (!ss_is_empty (style->prefix))
215 ss_match_char (&i->input, ss_first (style->prefix));
216 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
220 if (ss_match_char (&i->input, '-'))
222 ds_put_char (&tmp, '-');
223 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
227 ss_match_char (&i->input, '+');
228 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
231 /* Prefix character may follow sign. */
232 if (!ss_is_empty (style->prefix))
234 ss_match_char (&i->input, ss_first (style->prefix));
235 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
238 /* Digits before decimal point. */
239 while (c_isdigit (ss_first (i->input)))
241 ds_put_char (&tmp, ss_get_char (&i->input));
242 if (style->grouping != 0)
243 ss_match_char (&i->input, style->grouping);
246 /* Decimal point and following digits. */
247 if (ss_match_char (&i->input, style->decimal))
249 explicit_decimals = true;
250 ds_put_char (&tmp, '.');
251 while (c_isdigit (ss_first (i->input)))
252 ds_put_char (&tmp, ss_get_char (&i->input));
256 if (!ds_is_empty (&tmp)
257 && !ss_is_empty (i->input)
258 && strchr ("eEdD-+", ss_first (i->input)))
260 explicit_decimals = true;
261 ds_put_char (&tmp, 'e');
263 if (strchr ("eEdD", ss_first (i->input)))
265 ss_advance (&i->input, 1);
266 ss_match_char (&i->input, ' ');
269 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
271 if (ss_get_char (&i->input) == '-')
272 ds_put_char (&tmp, '-');
273 ss_match_char (&i->input, ' ');
276 while (c_isdigit (ss_first (i->input)))
277 ds_put_char (&tmp, ss_get_char (&i->input));
280 /* Suffix character. */
281 if (!ss_is_empty (style->suffix))
282 ss_match_char (&i->input, ss_first (style->suffix));
284 if (!ss_is_empty (i->input))
286 if (ds_is_empty (&tmp))
287 data_warning (i, _("Field contents are not numeric."));
289 data_warning (i, _("Number followed by garbage."));
294 /* Let c_strtod() do the conversion. */
297 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
300 data_warning (i, _("Invalid numeric syntax."));
305 else if (errno == ERANGE)
307 if (fabs (i->output->f) > 1)
309 data_warning (i, _("Too-large number set to system-missing."));
310 i->output->f = SYSMIS;
314 data_warning (i, _("Too-small number set to zero."));
321 if (!explicit_decimals)
322 apply_implied_decimals (i);
329 /* Parses N format. */
331 parse_N (struct data_in *i)
336 while ((c = ss_get_char (&i->input)) != EOF)
340 data_warning (i, _("All characters in field must be digits."));
343 i->output->f = i->output->f * 10.0 + (c - '0');
346 apply_implied_decimals (i);
350 /* Parses PIBHEX format. */
352 parse_PIBHEX (struct data_in *i)
359 while ((c = ss_get_char (&i->input)) != EOF)
363 data_warning (i, _("Unrecognized character in field."));
366 n = n * 16.0 + hexit_value (c);
373 /* Parses RBHEX format. */
375 parse_RBHEX (struct data_in *i)
380 memset (&d, 0, sizeof d);
381 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
383 int hi = ss_get_char (&i->input);
384 int lo = ss_get_char (&i->input);
387 data_warning (i, _("Field must have even length."));
390 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
392 data_warning (i, _("Field must contain only hex digits."));
395 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
403 /* Digits for Z format. */
404 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
406 /* Returns true if C is a Z format digit, false otherwise. */
410 return c > 0 && strchr (z_digits, c) != NULL;
413 /* Returns the (absolute value of the) value of C as a Z format
416 z_digit_value (int c)
418 assert (is_z_digit (c));
419 return (strchr (z_digits, c) - z_digits) % 10;
422 /* Returns true if Z format digit C represents a negative value,
425 is_negative_z_digit (int c)
427 assert (is_z_digit (c));
428 return (strchr (z_digits, c) - z_digits) >= 20;
431 /* Parses Z format. */
433 parse_Z (struct data_in *i)
439 bool got_dot = false;
440 bool got_final_digit = false;
442 /* Trim spaces and check for missing value representation. */
443 if (trim_spaces_and_check_missing (i))
446 ds_init_empty (&tmp);
447 ds_extend (&tmp, 64);
449 ds_put_char (&tmp, '+');
450 while (!ss_is_empty (i->input))
452 int c = ss_get_char (&i->input);
453 if (c_isdigit (c) && !got_final_digit)
454 ds_put_char (&tmp, c);
455 else if (is_z_digit (c) && !got_final_digit)
457 ds_put_char (&tmp, z_digit_value (c) + '0');
458 if (is_negative_z_digit (c))
459 ds_data (&tmp)[0] = '-';
460 got_final_digit = true;
462 else if (c == '.' && !got_dot)
464 ds_put_char (&tmp, '.');
474 if (!ss_is_empty (i->input))
476 if (ds_length (&tmp) == 1)
477 data_warning (i, _("Field contents are not numeric."));
479 data_warning (i, _("Number followed by garbage."));
484 /* Let c_strtod() do the conversion. */
487 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
490 if (fabs (i->output->f) > 1)
492 data_warning (i, _("Too-large number set to system-missing."));
493 i->output->f = SYSMIS;
497 data_warning (i, _("Too-small number set to zero."));
505 apply_implied_decimals (i);
512 /* Parses IB format. */
514 parse_IB (struct data_in *i)
520 bytes = MIN (8, ss_length (i->input));
521 value = integer_get (input_integer_format, ss_data (i->input), bytes);
523 sign_bit = UINT64_C(1) << (8 * bytes - 1);
524 if (!(value & sign_bit))
525 i->output->f = value;
528 /* Sign-extend to full 64 bits. */
529 value -= sign_bit << 1;
530 i->output->f = -(double) -value;
533 apply_implied_decimals (i);
538 /* Parses PIB format. */
540 parse_PIB (struct data_in *i)
542 i->output->f = integer_get (input_integer_format, ss_data (i->input),
543 MIN (8, ss_length (i->input)));
545 apply_implied_decimals (i);
550 /* Consumes the first character of S. Stores its high 4 bits in
551 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
553 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
555 int c = ss_get_char (s);
557 *high_nibble = (c >> 4) & 15;
558 *low_nibble = c & 15;
561 /* Parses P format. */
563 parse_P (struct data_in *i)
565 int high_nibble, low_nibble;
569 while (ss_length (i->input) > 1)
571 get_nibbles (&i->input, &high_nibble, &low_nibble);
572 if (high_nibble > 9 || low_nibble > 9)
574 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
577 get_nibbles (&i->input, &high_nibble, &low_nibble);
580 i->output->f = (10 * i->output->f) + high_nibble;
582 i->output->f = (10 * i->output->f) + low_nibble;
583 else if (low_nibble == 0xb || low_nibble == 0xd)
584 i->output->f = -i->output->f;
586 apply_implied_decimals (i);
591 /* Parses PK format. */
593 parse_PK (struct data_in *i)
596 while (!ss_is_empty (i->input))
598 int high_nibble, low_nibble;
600 get_nibbles (&i->input, &high_nibble, &low_nibble);
601 if (high_nibble > 9 || low_nibble > 9)
603 i->output->f = SYSMIS;
606 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
609 apply_implied_decimals (i);
614 /* Parses RB format. */
616 parse_RB (struct data_in *i)
618 size_t size = float_get_size (input_float_format);
619 if (ss_length (i->input) >= size)
620 float_convert (input_float_format, ss_data (i->input),
621 FLOAT_NATIVE_DOUBLE, &i->output->f);
623 i->output->f = SYSMIS;
628 /* Parses A format. */
630 parse_A (struct data_in *i)
632 /* This is equivalent to buf_copy_rpad, except that we posibly
633 do a character set recoding in the middle. */
634 char *dst = i->output->s;
635 size_t dst_size = i->width;
636 const char *src = ss_data (i->input);
637 size_t src_size = ss_length (i->input);
639 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
640 if (dst_size > src_size)
641 memset (&dst[src_size], ' ', dst_size - src_size);
646 /* Parses AHEX format. */
648 parse_AHEX (struct data_in *i)
654 int hi = ss_get_char (&i->input);
655 int lo = ss_get_char (&i->input);
660 data_warning (i, _("Field must have even length."));
664 if (i->encoding != LEGACY_NATIVE)
666 hi = legacy_to_native (i->encoding, hi);
667 lo = legacy_to_native (i->encoding, lo);
669 if (!c_isxdigit (hi) || !c_isxdigit (lo))
671 data_warning (i, _("Field must contain only hex digits."));
676 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
679 memset (i->output->s + j, ' ', i->width - j);
684 /* Date & time format components. */
686 /* Sign of a time value. */
689 SIGN_NO_TIME, /* No time yet encountered. */
690 SIGN_POSITIVE, /* Positive time. */
691 SIGN_NEGATIVE /* Negative time. */
694 /* Parses a signed decimal integer from at most the first
695 MAX_DIGITS characters in I, storing the result into *RESULT.
696 Returns true if successful, false if no integer was
699 parse_int (struct data_in *i, long *result, size_t max_digits)
701 struct substring head = ss_head (i->input, max_digits);
702 size_t n = ss_get_long (&head, result);
705 ss_advance (&i->input, n);
710 data_warning (i, _("Syntax error in date field."));
715 /* Parses a date integer between 1 and 31 from I, storing it into
717 Returns true if successful, false if no date was present. */
719 parse_day (struct data_in *i, long *day)
721 if (!parse_int (i, day, SIZE_MAX))
723 if (*day >= 1 && *day <= 31)
726 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
730 /* Parses an integer from the beginning of I.
731 Adds SECONDS_PER_UNIT times the absolute value of the integer
733 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
734 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
735 Returns true if successful, false if no integer was present. */
737 parse_time_units (struct data_in *i, double seconds_per_unit,
738 enum time_sign *time_sign, double *time)
743 if (*time_sign == SIGN_NO_TIME)
745 if (ss_match_char (&i->input, '-'))
746 *time_sign = SIGN_NEGATIVE;
749 ss_match_char (&i->input, '+');
750 *time_sign = SIGN_POSITIVE;
753 if (!parse_int (i, &units, SIZE_MAX))
757 data_warning (i, _("Syntax error in date field."));
760 *time += units * seconds_per_unit;
764 /* Parses a data delimiter from the beginning of I.
765 Returns true if successful, false if no delimiter was
768 parse_date_delimiter (struct data_in *i)
770 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
773 data_warning (i, _("Delimiter expected between fields in date."));
777 /* Parses spaces at the beginning of I. */
779 parse_spaces (struct data_in *i)
781 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
784 static struct substring
785 parse_name_token (struct data_in *i)
787 struct substring token;
788 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
792 /* Reads a name from I and sets *OUTPUT to the value associated
793 with that name. If ALLOW_SUFFIXES is true, then names that
794 begin with one of the names are accepted; otherwise, only
795 exact matches (except for case) are allowed.
796 Returns true if successful, false otherwise. */
798 match_name (struct substring token, const char **names, long *output)
802 for (i = 1; *names != NULL; i++)
803 if (ss_equals_case (ss_cstr (*names++), token))
812 /* Parses a month name or number from the beginning of I,
813 storing the month (in range 1...12) into *MONTH.
814 Returns true if successful, false if no month was present. */
816 parse_month (struct data_in *i, long *month)
818 if (c_isdigit (ss_first (i->input)))
820 if (!parse_int (i, month, SIZE_MAX))
822 if (*month >= 1 && *month <= 12)
827 static const char *english_names[] =
829 "jan", "feb", "mar", "apr", "may", "jun",
830 "jul", "aug", "sep", "oct", "nov", "dec",
834 static const char *roman_names[] =
836 "i", "ii", "iii", "iv", "v", "vi",
837 "vii", "viii", "ix", "x", "xi", "xii",
841 struct substring token = parse_name_token (i);
842 if (match_name (ss_head (token, 3), english_names, month)
843 || match_name (ss_head (token, 4), roman_names, month))
847 data_warning (i, _("Unrecognized month format. Months may be specified "
848 "as Arabic or Roman numerals or as at least 3 letters "
849 "of their English names."));
853 /* Parses a year of at most MAX_DIGITS from the beginning of I,
854 storing a "4-digit" year into *YEAR. */
856 parse_year (struct data_in *i, long *year, size_t max_digits)
858 if (!parse_int (i, year, max_digits))
861 if (*year >= 0 && *year <= 99)
863 int epoch = get_epoch ();
864 int epoch_century = ROUND_DOWN (epoch, 100);
865 int epoch_offset = epoch - epoch_century;
866 if (*year >= epoch_offset)
867 *year += epoch_century;
869 *year += epoch_century + 100;
871 if (*year >= 1582 || *year <= 19999)
874 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
878 /* Returns true if input in I has been exhausted,
881 parse_trailer (struct data_in *i)
883 if (ss_is_empty (i->input))
886 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
887 (int) ss_length (i->input), ss_data (i->input));
891 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
892 Returns true if successful, false on failure. */
894 parse_yday (struct data_in *i, long *yday)
896 struct substring num_s;
899 ss_get_chars (&i->input, 3, &num_s);
900 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
902 data_warning (i, _("Julian day must have exactly three digits."));
905 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
907 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
915 /* Parses a quarter-of-year integer between 1 and 4 from I.
916 Stores the corresponding month into *MONTH.
917 Returns true if successful, false if no quarter was present. */
919 parse_quarter (struct data_in *i, long int *month)
923 if (!parse_int (i, &quarter, SIZE_MAX))
925 if (quarter >= 1 && quarter <= 4)
927 *month = (quarter - 1) * 3 + 1;
931 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
935 /* Parses a week-of-year integer between 1 and 53 from I,
936 Stores the corresponding year-of-day into *YDAY.
937 Returns true if successful, false if no week was present. */
939 parse_week (struct data_in *i, long int *yday)
943 if (!parse_int (i, &week, SIZE_MAX))
945 if (week >= 1 && week <= 53)
947 *yday = (week - 1) * 7 + 1;
951 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
955 /* Parses a time delimiter from the beginning of I.
956 Returns true if successful, false if no delimiter was
959 parse_time_delimiter (struct data_in *i)
961 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
964 data_warning (i, _("Delimiter expected between fields in time."));
968 /* Parses minutes and optional seconds from the beginning of I.
969 The time is converted into seconds, which are added to
971 Returns true if successful, false if an error was found. */
973 parse_minute_second (struct data_in *i, double *time)
980 if (!parse_int (i, &minute, SIZE_MAX))
982 if (minute < 0 || minute > 59)
984 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
987 *time += 60. * minute;
989 /* Check for seconds. */
990 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
991 || !c_isdigit (ss_first (i->input)))
996 while (c_isdigit (ss_first (i->input)))
997 *cp++ = ss_get_char (&i->input);
998 if (ss_match_char (&i->input, fmt_decimal_char (FMT_F)))
1000 while (c_isdigit (ss_first (i->input)))
1001 *cp++ = ss_get_char (&i->input);
1004 *time += strtod (buf, NULL);
1009 /* Parses a weekday name from the beginning of I,
1010 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
1011 Returns true if successful, false if an error was found. */
1013 parse_weekday (struct data_in *i, long *weekday)
1015 static const char *weekday_names[] =
1017 "su", "mo", "tu", "we", "th", "fr", "sa",
1021 struct substring token = parse_name_token (i);
1022 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1024 data_warning (i, _("Unrecognized weekday name. At least the first two "
1025 "letters of an English weekday name must be "
1030 /* Date & time formats. */
1032 /* Helper function for passing to
1033 calendar_gregorian_to_offset. */
1035 calendar_error (void *i_, const char *format, ...)
1037 struct data_in *i = i_;
1040 va_start (args, format);
1041 vdata_warning (i, format, args);
1045 /* Parses WKDAY format. */
1047 parse_WKDAY (struct data_in *i)
1051 if (trim_spaces_and_check_missing (i))
1054 if (!parse_weekday (i, &weekday)
1055 || !parse_trailer (i))
1058 i->output->f = weekday;
1062 /* Parses MONTH format. */
1064 parse_MONTH (struct data_in *i)
1068 if (trim_spaces_and_check_missing (i))
1071 if (!parse_month (i, &month)
1072 || !parse_trailer (i))
1075 i->output->f = month;
1079 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1080 DATETIME, TIME and DTIME formats. */
1082 parse_date (struct data_in *i)
1084 long int year = INT_MIN;
1088 double time = 0, date = 0;
1089 enum time_sign time_sign = SIGN_NO_TIME;
1091 const char *template = fmt_date_template (i->format);
1092 size_t template_width = strlen (template);
1094 if (trim_spaces_and_check_missing (i))
1097 while (*template != '\0')
1099 unsigned char ch = *template;
1103 while (template[count] == ch)
1111 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1114 ok = parse_month (i, &month);
1119 if (!c_isalpha (*template))
1120 max_digits = SIZE_MAX;
1123 if (ss_length (i->input) >= template_width + 2)
1128 ok = parse_year (i, &year, max_digits);
1132 ok = parse_quarter (i, &month);
1135 ok = parse_week (i, &yday);
1138 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1141 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1144 ok = parse_minute_second (i, &time);
1150 ok = parse_date_delimiter (i);
1153 ok = parse_time_delimiter (i);
1158 assert (count == 1);
1159 if (!ss_match_char (&i->input, c_toupper (ch))
1160 && !ss_match_char (&i->input, c_tolower (ch)))
1162 data_warning (i, _("`%c' expected in date field."), ch);
1170 if (!parse_trailer (i))
1173 if (year != INT_MIN)
1175 double ofs = calendar_gregorian_to_offset (year, month, day,
1179 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1183 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1188 /* Utility functions. */
1190 /* Outputs FORMAT with the given ARGS as a warning for input
1193 vdata_warning (const struct data_in *i, const char *format, va_list args)
1198 ds_init_empty (&text);
1199 ds_put_char (&text, '(');
1200 if (i->first_column != 0)
1202 if (i->first_column == i->last_column)
1203 ds_put_format (&text, _("column %d"), i->first_column);
1205 ds_put_format (&text, _("columns %d-%d"),
1206 i->first_column, i->last_column);
1207 ds_put_cstr (&text, ", ");
1209 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1210 ds_put_vformat (&text, format, args);
1212 m.category = MSG_DATA;
1213 m.severity = MSG_WARNING;
1214 m.text = ds_cstr (&text);
1219 /* Outputs FORMAT with the given ARGS as a warning for input
1222 data_warning (const struct data_in *i, const char *format, ...)
1226 va_start (args, format);
1227 vdata_warning (i, format, args);
1231 /* Apply implied decimal places to output. */
1233 apply_implied_decimals (struct data_in *i)
1235 if (i->implied_decimals > 0)
1236 i->output->f /= pow (10., i->implied_decimals);
1239 /* Sets the default result for I.
1240 For a numeric format, this is the value set on SET BLANKS
1241 (typically system-missing); for a string format, it is all
1244 default_result (struct data_in *i)
1246 if (fmt_is_string (i->format))
1247 memset (i->output->s, ' ', i->width);
1249 i->output->f = get_blanks ();
1252 /* Trims leading and trailing spaces from I.
1253 If the result is empty, or a single period character, then
1254 sets the default result and returns true; otherwise, returns
1257 trim_spaces_and_check_missing (struct data_in *i)
1259 ss_trim (&i->input, ss_cstr (" "));
1260 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1268 /* Returns the integer value of hex digit C. */
1272 const char s[] = "0123456789abcdef";
1273 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1275 assert (cp != NULL);