1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009 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 "identifier.h"
38 #include <libpspp/assertion.h>
39 #include <libpspp/legacy-encoding.h>
40 #include <libpspp/i18n.h>
41 #include <libpspp/compiler.h>
42 #include <libpspp/integer-format.h>
43 #include <libpspp/message.h>
44 #include <libpspp/misc.h>
45 #include <libpspp/str.h>
52 #define _(msgid) gettext (msgid)
54 /* Information about parsing one data field. */
57 const char *encoding; /* Encoding of source. */
58 struct substring input; /* Source. */
59 enum fmt_type format; /* Input format. */
60 int implied_decimals; /* Number of implied decimal places. */
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 vdata_warning (const struct data_in *, const char *, va_list)
78 static void data_warning (const struct data_in *, const char *, ...)
81 static void apply_implied_decimals (struct data_in *);
82 static void default_result (struct data_in *);
83 static bool trim_spaces_and_check_missing (struct data_in *);
85 static int hexit_value (int c);
87 /* Parses the characters in INPUT, which are encoded in the given
88 ENCODING, according to FORMAT. Stores the parsed
89 representation in OUTPUT, which the caller must have
90 initialized with the given WIDTH (0 for a numeric field,
91 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 and LAST_COLUMN are nonzero, then they should
98 be the 1-based column number of the first and
99 one-past-the-last-character in INPUT, for use in error
100 messages. (LAST_COLUMN cannot always be calculated from
101 FIRST_COLUMN plus the length of the input because of the
102 possibility of escaped quotes in strings, etc.) */
104 data_in (struct substring input, const char *encoding,
105 enum fmt_type format, int implied_decimals,
106 int first_column, int last_column, union value *output, int width)
108 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
110 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
111 #include "format.def"
118 assert ((width != 0) == fmt_is_string (format));
120 if (0 == strcmp (encoding, LEGACY_NATIVE)
121 || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
124 i.encoding = encoding;
129 ss_alloc_uninit (&i.input, ss_length (input));
131 s = recode_string (LEGACY_NATIVE, encoding, ss_data (input), ss_length (input));
132 memcpy (ss_data (i.input), s, ss_length (input));
134 i.encoding = LEGACY_NATIVE;
135 copy = ss_data (i.input);
138 i.implied_decimals = implied_decimals;
143 i.first_column = first_column;
144 i.last_column = last_column;
146 if (!ss_is_empty (i.input))
148 ok = handlers[i.format] (&i);
165 /* Format parsers. */
167 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
169 parse_number (struct data_in *i)
171 const struct fmt_number_style *style =
172 settings_get_style (i->format);
176 bool explicit_decimals = false;
180 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
182 style = settings_get_style (FMT_F);
185 /* Trim spaces and check for missing value representation. */
186 if (trim_spaces_and_check_missing (i))
189 ds_init_empty (&tmp);
190 ds_extend (&tmp, 64);
192 /* Prefix character may precede sign. */
193 if (!ss_is_empty (style->prefix))
195 ss_match_char (&i->input, ss_first (style->prefix));
196 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
200 if (ss_match_char (&i->input, '-'))
202 ds_put_char (&tmp, '-');
203 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
207 ss_match_char (&i->input, '+');
208 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
211 /* Prefix character may follow sign. */
212 if (!ss_is_empty (style->prefix))
214 ss_match_char (&i->input, ss_first (style->prefix));
215 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
218 /* Digits before decimal point. */
219 while (c_isdigit (ss_first (i->input)))
221 ds_put_char (&tmp, ss_get_char (&i->input));
222 if (style->grouping != 0)
223 ss_match_char (&i->input, style->grouping);
226 /* Decimal point and following digits. */
227 if (ss_match_char (&i->input, style->decimal))
229 explicit_decimals = true;
230 ds_put_char (&tmp, '.');
231 while (c_isdigit (ss_first (i->input)))
232 ds_put_char (&tmp, ss_get_char (&i->input));
236 if (!ds_is_empty (&tmp)
237 && !ss_is_empty (i->input)
238 && strchr ("eEdD-+", ss_first (i->input)))
240 explicit_decimals = true;
241 ds_put_char (&tmp, 'e');
243 if (strchr ("eEdD", ss_first (i->input)))
245 ss_advance (&i->input, 1);
246 ss_match_char (&i->input, ' ');
249 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
251 if (ss_get_char (&i->input) == '-')
252 ds_put_char (&tmp, '-');
253 ss_match_char (&i->input, ' ');
256 while (c_isdigit (ss_first (i->input)))
257 ds_put_char (&tmp, ss_get_char (&i->input));
260 /* Suffix character. */
261 if (!ss_is_empty (style->suffix))
262 ss_match_char (&i->input, ss_first (style->suffix));
264 if (!ss_is_empty (i->input))
266 if (ds_is_empty (&tmp))
267 data_warning (i, _("Field contents are not numeric."));
269 data_warning (i, _("Number followed by garbage."));
274 /* Let c_strtod() do the conversion. */
277 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
280 data_warning (i, _("Invalid numeric syntax."));
285 else if (errno == ERANGE)
287 if (fabs (i->output->f) > 1)
289 data_warning (i, _("Too-large number set to system-missing."));
290 i->output->f = SYSMIS;
294 data_warning (i, _("Too-small number set to zero."));
301 if (!explicit_decimals)
302 apply_implied_decimals (i);
309 /* Parses N format. */
311 parse_N (struct data_in *i)
316 while ((c = ss_get_char (&i->input)) != EOF)
320 data_warning (i, _("All characters in field must be digits."));
323 i->output->f = i->output->f * 10.0 + (c - '0');
326 apply_implied_decimals (i);
330 /* Parses PIBHEX format. */
332 parse_PIBHEX (struct data_in *i)
339 while ((c = ss_get_char (&i->input)) != EOF)
343 data_warning (i, _("Unrecognized character in field."));
346 n = n * 16.0 + hexit_value (c);
353 /* Parses RBHEX format. */
355 parse_RBHEX (struct data_in *i)
360 memset (&d, 0, sizeof d);
361 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
363 int hi = ss_get_char (&i->input);
364 int lo = ss_get_char (&i->input);
367 data_warning (i, _("Field must have even length."));
370 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
372 data_warning (i, _("Field must contain only hex digits."));
375 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
383 /* Digits for Z format. */
384 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
386 /* Returns true if C is a Z format digit, false otherwise. */
390 return c > 0 && strchr (z_digits, c) != NULL;
393 /* Returns the (absolute value of the) value of C as a Z format
396 z_digit_value (int c)
398 assert (is_z_digit (c));
399 return (strchr (z_digits, c) - z_digits) % 10;
402 /* Returns true if Z format digit C represents a negative value,
405 is_negative_z_digit (int c)
407 assert (is_z_digit (c));
408 return (strchr (z_digits, c) - z_digits) >= 20;
411 /* Parses Z format. */
413 parse_Z (struct data_in *i)
419 bool got_dot = false;
420 bool got_final_digit = false;
422 /* Trim spaces and check for missing value representation. */
423 if (trim_spaces_and_check_missing (i))
426 ds_init_empty (&tmp);
427 ds_extend (&tmp, 64);
429 ds_put_char (&tmp, '+');
430 while (!ss_is_empty (i->input))
432 int c = ss_get_char (&i->input);
433 if (c_isdigit (c) && !got_final_digit)
434 ds_put_char (&tmp, c);
435 else if (is_z_digit (c) && !got_final_digit)
437 ds_put_char (&tmp, z_digit_value (c) + '0');
438 if (is_negative_z_digit (c))
439 ds_data (&tmp)[0] = '-';
440 got_final_digit = true;
442 else if (c == '.' && !got_dot)
444 ds_put_char (&tmp, '.');
454 if (!ss_is_empty (i->input))
456 if (ds_length (&tmp) == 1)
457 data_warning (i, _("Field contents are not numeric."));
459 data_warning (i, _("Number followed by garbage."));
464 /* Let c_strtod() do the conversion. */
467 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
470 if (fabs (i->output->f) > 1)
472 data_warning (i, _("Too-large number set to system-missing."));
473 i->output->f = SYSMIS;
477 data_warning (i, _("Too-small number set to zero."));
485 apply_implied_decimals (i);
492 /* Parses IB format. */
494 parse_IB (struct data_in *i)
500 bytes = MIN (8, ss_length (i->input));
501 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
503 sign_bit = UINT64_C(1) << (8 * bytes - 1);
504 if (!(value & sign_bit))
505 i->output->f = value;
508 /* Sign-extend to full 64 bits. */
509 value -= sign_bit << 1;
510 i->output->f = -(double) -value;
513 apply_implied_decimals (i);
518 /* Parses PIB format. */
520 parse_PIB (struct data_in *i)
522 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
523 MIN (8, ss_length (i->input)));
525 apply_implied_decimals (i);
530 /* Consumes the first character of S. Stores its high 4 bits in
531 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
533 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
535 int c = ss_get_char (s);
537 *high_nibble = (c >> 4) & 15;
538 *low_nibble = c & 15;
541 /* Parses P format. */
543 parse_P (struct data_in *i)
545 int high_nibble, low_nibble;
549 while (ss_length (i->input) > 1)
551 get_nibbles (&i->input, &high_nibble, &low_nibble);
552 if (high_nibble > 9 || low_nibble > 9)
554 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
557 get_nibbles (&i->input, &high_nibble, &low_nibble);
560 i->output->f = (10 * i->output->f) + high_nibble;
562 i->output->f = (10 * i->output->f) + low_nibble;
563 else if (low_nibble == 0xb || low_nibble == 0xd)
564 i->output->f = -i->output->f;
566 apply_implied_decimals (i);
571 /* Parses PK format. */
573 parse_PK (struct data_in *i)
576 while (!ss_is_empty (i->input))
578 int high_nibble, low_nibble;
580 get_nibbles (&i->input, &high_nibble, &low_nibble);
581 if (high_nibble > 9 || low_nibble > 9)
583 i->output->f = SYSMIS;
586 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
589 apply_implied_decimals (i);
594 /* Parses RB format. */
596 parse_RB (struct data_in *i)
598 enum float_format ff = settings_get_input_float_format ();
599 size_t size = float_get_size (ff);
600 if (ss_length (i->input) >= size)
601 float_convert (ff, ss_data (i->input),
602 FLOAT_NATIVE_DOUBLE, &i->output->f);
604 i->output->f = SYSMIS;
609 /* Parses A format. */
611 parse_A (struct data_in *i)
613 /* This is equivalent to buf_copy_rpad, except that we posibly
614 do a character set recoding in the middle. */
615 char *dst = value_str_rw (i->output, i->width);
616 size_t dst_size = i->width;
617 const char *src = ss_data (i->input);
618 size_t src_size = ss_length (i->input);
620 char *s = recode_string (LEGACY_NATIVE, i->encoding, src, MIN (src_size, dst_size));
621 memcpy (dst, s, dst_size);
623 if (dst_size > src_size)
624 memset (&dst[src_size], ' ', dst_size - src_size);
629 /* Parses AHEX format. */
631 parse_AHEX (struct data_in *i)
633 char *s = value_str_rw (i->output, i->width);
638 int hi = ss_get_char (&i->input);
639 int lo = ss_get_char (&i->input);
644 data_warning (i, _("Field must have even length."));
648 if (0 != strcmp (i->encoding, LEGACY_NATIVE))
650 hi = legacy_to_native (i->encoding, hi);
651 lo = legacy_to_native (i->encoding, lo);
653 if (!c_isxdigit (hi) || !c_isxdigit (lo))
655 data_warning (i, _("Field must contain only hex digits."));
660 s[j] = hexit_value (hi) * 16 + hexit_value (lo);
663 memset (&s[j], ' ', i->width - j);
668 /* Date & time format components. */
670 /* Sign of a time value. */
673 SIGN_NO_TIME, /* No time yet encountered. */
674 SIGN_POSITIVE, /* Positive time. */
675 SIGN_NEGATIVE /* Negative time. */
678 /* Parses a signed decimal integer from at most the first
679 MAX_DIGITS characters in I, storing the result into *RESULT.
680 Returns true if successful, false if no integer was
683 parse_int (struct data_in *i, long *result, size_t max_digits)
685 struct substring head = ss_head (i->input, max_digits);
686 size_t n = ss_get_long (&head, result);
689 ss_advance (&i->input, n);
694 data_warning (i, _("Syntax error in date field."));
699 /* Parses a date integer between 1 and 31 from I, storing it into
701 Returns true if successful, false if no date was present. */
703 parse_day (struct data_in *i, long *day)
705 if (!parse_int (i, day, SIZE_MAX))
707 if (*day >= 1 && *day <= 31)
710 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
714 /* Parses an integer from the beginning of I.
715 Adds SECONDS_PER_UNIT times the absolute value of the integer
717 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
718 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
719 Returns true if successful, false if no integer was present. */
721 parse_time_units (struct data_in *i, double seconds_per_unit,
722 enum time_sign *time_sign, double *time)
727 if (*time_sign == SIGN_NO_TIME)
729 if (ss_match_char (&i->input, '-'))
730 *time_sign = SIGN_NEGATIVE;
733 ss_match_char (&i->input, '+');
734 *time_sign = SIGN_POSITIVE;
737 if (!parse_int (i, &units, SIZE_MAX))
741 data_warning (i, _("Syntax error in date field."));
744 *time += units * seconds_per_unit;
748 /* Parses a data delimiter from the beginning of I.
749 Returns true if successful, false if no delimiter was
752 parse_date_delimiter (struct data_in *i)
754 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
757 data_warning (i, _("Delimiter expected between fields in date."));
761 /* Parses spaces at the beginning of I. */
763 parse_spaces (struct data_in *i)
765 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
768 static struct substring
769 parse_name_token (struct data_in *i)
771 struct substring token;
772 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
776 /* Reads a name from I and sets *OUTPUT to the value associated
777 with that name. If ALLOW_SUFFIXES is true, then names that
778 begin with one of the names are accepted; otherwise, only
779 exact matches (except for case) are allowed.
780 Returns true if successful, false otherwise. */
782 match_name (struct substring token, const char *const *names, long *output)
786 for (i = 1; *names != NULL; i++)
787 if (ss_equals_case (ss_cstr (*names++), token))
796 /* Parses a month name or number from the beginning of I,
797 storing the month (in range 1...12) into *MONTH.
798 Returns true if successful, false if no month was present. */
800 parse_month (struct data_in *i, long *month)
802 if (c_isdigit (ss_first (i->input)))
804 if (!parse_int (i, month, SIZE_MAX))
806 if (*month >= 1 && *month <= 12)
811 static const char *const english_names[] =
813 "jan", "feb", "mar", "apr", "may", "jun",
814 "jul", "aug", "sep", "oct", "nov", "dec",
818 static const char *const roman_names[] =
820 "i", "ii", "iii", "iv", "v", "vi",
821 "vii", "viii", "ix", "x", "xi", "xii",
825 struct substring token = parse_name_token (i);
826 if (match_name (ss_head (token, 3), english_names, month)
827 || match_name (ss_head (token, 4), roman_names, month))
831 data_warning (i, _("Unrecognized month format. Months may be specified "
832 "as Arabic or Roman numerals or as at least 3 letters "
833 "of their English names."));
837 /* Parses a year of at most MAX_DIGITS from the beginning of I,
838 storing a "4-digit" year into *YEAR. */
840 parse_year (struct data_in *i, long *year, size_t max_digits)
842 if (!parse_int (i, year, max_digits))
845 if (*year >= 0 && *year <= 99)
847 int epoch = settings_get_epoch ();
848 int epoch_century = ROUND_DOWN (epoch, 100);
849 int epoch_offset = epoch - epoch_century;
850 if (*year >= epoch_offset)
851 *year += epoch_century;
853 *year += epoch_century + 100;
855 if (*year >= 1582 || *year <= 19999)
858 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
862 /* Returns true if input in I has been exhausted,
865 parse_trailer (struct data_in *i)
867 if (ss_is_empty (i->input))
870 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
871 (int) ss_length (i->input), ss_data (i->input));
875 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
876 Returns true if successful, false on failure. */
878 parse_yday (struct data_in *i, long *yday)
880 struct substring num_s;
883 ss_get_chars (&i->input, 3, &num_s);
884 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
886 data_warning (i, _("Julian day must have exactly three digits."));
889 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
891 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
899 /* Parses a quarter-of-year integer between 1 and 4 from I.
900 Stores the corresponding month into *MONTH.
901 Returns true if successful, false if no quarter was present. */
903 parse_quarter (struct data_in *i, long int *month)
907 if (!parse_int (i, &quarter, SIZE_MAX))
909 if (quarter >= 1 && quarter <= 4)
911 *month = (quarter - 1) * 3 + 1;
915 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
919 /* Parses a week-of-year integer between 1 and 53 from I,
920 Stores the corresponding year-of-day into *YDAY.
921 Returns true if successful, false if no week was present. */
923 parse_week (struct data_in *i, long int *yday)
927 if (!parse_int (i, &week, SIZE_MAX))
929 if (week >= 1 && week <= 53)
931 *yday = (week - 1) * 7 + 1;
935 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
939 /* Parses a time delimiter from the beginning of I.
940 Returns true if successful, false if no delimiter was
943 parse_time_delimiter (struct data_in *i)
945 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
948 data_warning (i, _("Delimiter expected between fields in time."));
952 /* Parses minutes and optional seconds from the beginning of I.
953 The time is converted into seconds, which are added to
955 Returns true if successful, false if an error was found. */
957 parse_minute_second (struct data_in *i, double *time)
964 if (!parse_int (i, &minute, SIZE_MAX))
966 if (minute < 0 || minute > 59)
968 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
971 *time += 60. * minute;
973 /* Check for seconds. */
974 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
975 || !c_isdigit (ss_first (i->input)))
980 while (c_isdigit (ss_first (i->input)))
981 *cp++ = ss_get_char (&i->input);
982 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
984 while (c_isdigit (ss_first (i->input)))
985 *cp++ = ss_get_char (&i->input);
988 *time += strtod (buf, NULL);
993 /* Parses a weekday name from the beginning of I,
994 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
995 Returns true if successful, false if an error was found. */
997 parse_weekday (struct data_in *i, long *weekday)
999 static const char *const weekday_names[] =
1001 "su", "mo", "tu", "we", "th", "fr", "sa",
1005 struct substring token = parse_name_token (i);
1006 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1008 data_warning (i, _("Unrecognized weekday name. At least the first two "
1009 "letters of an English weekday name must be "
1014 /* Date & time formats. */
1016 /* Helper function for passing to
1017 calendar_gregorian_to_offset. */
1019 calendar_error (void *i_, const char *format, ...)
1021 struct data_in *i = i_;
1024 va_start (args, format);
1025 vdata_warning (i, format, args);
1029 /* Parses WKDAY format. */
1031 parse_WKDAY (struct data_in *i)
1035 if (trim_spaces_and_check_missing (i))
1038 if (!parse_weekday (i, &weekday)
1039 || !parse_trailer (i))
1042 i->output->f = weekday;
1046 /* Parses MONTH format. */
1048 parse_MONTH (struct data_in *i)
1052 if (trim_spaces_and_check_missing (i))
1055 if (!parse_month (i, &month)
1056 || !parse_trailer (i))
1059 i->output->f = month;
1063 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1064 DATETIME, TIME and DTIME formats. */
1066 parse_date (struct data_in *i)
1068 long int year = INT_MIN;
1072 double time = 0, date = 0;
1073 enum time_sign time_sign = SIGN_NO_TIME;
1075 const char *template = fmt_date_template (i->format);
1076 size_t template_width = strlen (template);
1078 if (trim_spaces_and_check_missing (i))
1081 while (*template != '\0')
1083 unsigned char ch = *template;
1087 while (template[count] == ch)
1095 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1098 ok = parse_month (i, &month);
1103 if (!c_isalpha (*template))
1104 max_digits = SIZE_MAX;
1107 if (ss_length (i->input) >= template_width + 2)
1112 ok = parse_year (i, &year, max_digits);
1116 ok = parse_quarter (i, &month);
1119 ok = parse_week (i, &yday);
1122 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1125 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1128 ok = parse_minute_second (i, &time);
1134 ok = parse_date_delimiter (i);
1137 ok = parse_time_delimiter (i);
1142 assert (count == 1);
1143 if (!ss_match_char (&i->input, c_toupper (ch))
1144 && !ss_match_char (&i->input, c_tolower (ch)))
1146 data_warning (i, _("`%c' expected in date field."), ch);
1154 if (!parse_trailer (i))
1157 if (year != INT_MIN)
1159 double ofs = calendar_gregorian_to_offset (year, month, day,
1163 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1167 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1172 /* Utility functions. */
1174 /* Outputs FORMAT with the given ARGS as a warning for input
1177 vdata_warning (const struct data_in *i, const char *format, va_list args)
1182 ds_init_empty (&text);
1183 ds_put_char (&text, '(');
1184 if (i->first_column != 0)
1186 if (i->first_column == i->last_column - 1)
1187 ds_put_format (&text, _("column %d"), i->first_column);
1189 ds_put_format (&text, _("columns %d-%d"),
1190 i->first_column, i->last_column - 1);
1191 ds_put_cstr (&text, ", ");
1193 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1194 ds_put_vformat (&text, format, args);
1196 m.category = MSG_DATA;
1197 m.severity = MSG_WARNING;
1198 m.text = ds_cstr (&text);
1203 /* Outputs FORMAT with the given ARGS as a warning for input
1206 data_warning (const struct data_in *i, const char *format, ...)
1210 va_start (args, format);
1211 vdata_warning (i, format, args);
1215 /* Apply implied decimal places to output. */
1217 apply_implied_decimals (struct data_in *i)
1219 if (i->implied_decimals > 0)
1220 i->output->f /= pow (10., i->implied_decimals);
1223 /* Sets the default result for I.
1224 For a numeric format, this is the value set on SET BLANKS
1225 (typically system-missing); for a string format, it is all
1228 default_result (struct data_in *i)
1230 if (fmt_is_string (i->format))
1231 memset (value_str_rw (i->output, i->width), ' ', i->width);
1233 i->output->f = settings_get_blanks ();
1236 /* Trims leading and trailing spaces from I.
1237 If the result is empty, or a single period character, then
1238 sets the default result and returns true; otherwise, returns
1241 trim_spaces_and_check_missing (struct data_in *i)
1243 ss_trim (&i->input, ss_cstr (" "));
1244 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1252 /* Returns the integer value of hex digit C. */
1256 const char s[] = "0123456789abcdef";
1257 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1259 assert (cp != NULL);