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/compiler.h>
41 #include <libpspp/integer-format.h>
42 #include <libpspp/message.h>
43 #include <libpspp/misc.h>
44 #include <libpspp/str.h>
51 #define _(msgid) gettext (msgid)
53 /* Information about parsing one data field. */
56 enum legacy_encoding encoding;/* Encoding of source. */
57 struct substring input; /* Source. */
58 enum fmt_type format; /* Input format. */
59 int implied_decimals; /* Number of implied decimal places. */
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. */
70 typedef bool data_in_parser_func (struct data_in *);
71 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
72 static data_in_parser_func parse_##METHOD;
75 static void vdata_warning (const struct data_in *, const char *, va_list)
77 static void data_warning (const struct data_in *, const char *, ...)
80 static void apply_implied_decimals (struct data_in *);
81 static void default_result (struct data_in *);
82 static bool trim_spaces_and_check_missing (struct data_in *);
84 static int hexit_value (int c);
86 /* Parses the characters in INPUT, which are encoded in the given
87 ENCODING, according to FORMAT. Stores the parsed
88 representation in OUTPUT, which the caller must have
89 initialized with the given WIDTH (0 for a numeric field,
90 otherwise the string width).
92 If no decimal point is included in a numeric format, then
93 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
94 decimal places should be implied.
96 If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
97 be the 1-based column number of the first and
98 one-past-the-last-character in INPUT, for use in error
99 messages. (LAST_COLUMN cannot always be calculated from
100 FIRST_COLUMN plus the length of the input because of the
101 possibility of escaped quotes in strings, etc.) */
103 data_in (struct substring input, enum legacy_encoding encoding,
104 enum fmt_type format, int implied_decimals,
105 int first_column, int last_column, union value *output, int width)
107 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
109 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
110 #include "format.def"
117 assert ((width != 0) == fmt_is_string (format));
119 if (encoding == LEGACY_NATIVE
120 || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
123 i.encoding = encoding;
127 ss_alloc_uninit (&i.input, ss_length (input));
128 legacy_recode (encoding, ss_data (input), LEGACY_NATIVE,
129 ss_data (i.input), ss_length (input));
130 i.encoding = LEGACY_NATIVE;
131 copy = ss_data (i.input);
134 i.implied_decimals = implied_decimals;
139 i.first_column = first_column;
140 i.last_column = last_column;
142 if (!ss_is_empty (i.input))
144 ok = handlers[i.format] (&i);
161 /* Format parsers. */
163 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
165 parse_number (struct data_in *i)
167 const struct fmt_number_style *style =
168 settings_get_style (i->format);
172 bool explicit_decimals = false;
176 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
178 style = settings_get_style (FMT_F);
181 /* Trim spaces and check for missing value representation. */
182 if (trim_spaces_and_check_missing (i))
185 ds_init_empty (&tmp);
186 ds_extend (&tmp, 64);
188 /* Prefix character may precede sign. */
189 if (!ss_is_empty (style->prefix))
191 ss_match_char (&i->input, ss_first (style->prefix));
192 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
196 if (ss_match_char (&i->input, '-'))
198 ds_put_char (&tmp, '-');
199 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
203 ss_match_char (&i->input, '+');
204 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
207 /* Prefix character may follow sign. */
208 if (!ss_is_empty (style->prefix))
210 ss_match_char (&i->input, ss_first (style->prefix));
211 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
214 /* Digits before decimal point. */
215 while (c_isdigit (ss_first (i->input)))
217 ds_put_char (&tmp, ss_get_char (&i->input));
218 if (style->grouping != 0)
219 ss_match_char (&i->input, style->grouping);
222 /* Decimal point and following digits. */
223 if (ss_match_char (&i->input, style->decimal))
225 explicit_decimals = true;
226 ds_put_char (&tmp, '.');
227 while (c_isdigit (ss_first (i->input)))
228 ds_put_char (&tmp, ss_get_char (&i->input));
232 if (!ds_is_empty (&tmp)
233 && !ss_is_empty (i->input)
234 && strchr ("eEdD-+", ss_first (i->input)))
236 explicit_decimals = true;
237 ds_put_char (&tmp, 'e');
239 if (strchr ("eEdD", ss_first (i->input)))
241 ss_advance (&i->input, 1);
242 ss_match_char (&i->input, ' ');
245 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
247 if (ss_get_char (&i->input) == '-')
248 ds_put_char (&tmp, '-');
249 ss_match_char (&i->input, ' ');
252 while (c_isdigit (ss_first (i->input)))
253 ds_put_char (&tmp, ss_get_char (&i->input));
256 /* Suffix character. */
257 if (!ss_is_empty (style->suffix))
258 ss_match_char (&i->input, ss_first (style->suffix));
260 if (!ss_is_empty (i->input))
262 if (ds_is_empty (&tmp))
263 data_warning (i, _("Field contents are not numeric."));
265 data_warning (i, _("Number followed by garbage."));
270 /* Let c_strtod() do the conversion. */
273 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
276 data_warning (i, _("Invalid numeric syntax."));
281 else if (errno == ERANGE)
283 if (fabs (i->output->f) > 1)
285 data_warning (i, _("Too-large number set to system-missing."));
286 i->output->f = SYSMIS;
290 data_warning (i, _("Too-small number set to zero."));
297 if (!explicit_decimals)
298 apply_implied_decimals (i);
305 /* Parses N format. */
307 parse_N (struct data_in *i)
312 while ((c = ss_get_char (&i->input)) != EOF)
316 data_warning (i, _("All characters in field must be digits."));
319 i->output->f = i->output->f * 10.0 + (c - '0');
322 apply_implied_decimals (i);
326 /* Parses PIBHEX format. */
328 parse_PIBHEX (struct data_in *i)
335 while ((c = ss_get_char (&i->input)) != EOF)
339 data_warning (i, _("Unrecognized character in field."));
342 n = n * 16.0 + hexit_value (c);
349 /* Parses RBHEX format. */
351 parse_RBHEX (struct data_in *i)
356 memset (&d, 0, sizeof d);
357 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
359 int hi = ss_get_char (&i->input);
360 int lo = ss_get_char (&i->input);
363 data_warning (i, _("Field must have even length."));
366 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
368 data_warning (i, _("Field must contain only hex digits."));
371 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
379 /* Digits for Z format. */
380 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
382 /* Returns true if C is a Z format digit, false otherwise. */
386 return c > 0 && strchr (z_digits, c) != NULL;
389 /* Returns the (absolute value of the) value of C as a Z format
392 z_digit_value (int c)
394 assert (is_z_digit (c));
395 return (strchr (z_digits, c) - z_digits) % 10;
398 /* Returns true if Z format digit C represents a negative value,
401 is_negative_z_digit (int c)
403 assert (is_z_digit (c));
404 return (strchr (z_digits, c) - z_digits) >= 20;
407 /* Parses Z format. */
409 parse_Z (struct data_in *i)
415 bool got_dot = false;
416 bool got_final_digit = false;
418 /* Trim spaces and check for missing value representation. */
419 if (trim_spaces_and_check_missing (i))
422 ds_init_empty (&tmp);
423 ds_extend (&tmp, 64);
425 ds_put_char (&tmp, '+');
426 while (!ss_is_empty (i->input))
428 int c = ss_get_char (&i->input);
429 if (c_isdigit (c) && !got_final_digit)
430 ds_put_char (&tmp, c);
431 else if (is_z_digit (c) && !got_final_digit)
433 ds_put_char (&tmp, z_digit_value (c) + '0');
434 if (is_negative_z_digit (c))
435 ds_data (&tmp)[0] = '-';
436 got_final_digit = true;
438 else if (c == '.' && !got_dot)
440 ds_put_char (&tmp, '.');
450 if (!ss_is_empty (i->input))
452 if (ds_length (&tmp) == 1)
453 data_warning (i, _("Field contents are not numeric."));
455 data_warning (i, _("Number followed by garbage."));
460 /* Let c_strtod() do the conversion. */
463 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
466 if (fabs (i->output->f) > 1)
468 data_warning (i, _("Too-large number set to system-missing."));
469 i->output->f = SYSMIS;
473 data_warning (i, _("Too-small number set to zero."));
481 apply_implied_decimals (i);
488 /* Parses IB format. */
490 parse_IB (struct data_in *i)
496 bytes = MIN (8, ss_length (i->input));
497 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
499 sign_bit = UINT64_C(1) << (8 * bytes - 1);
500 if (!(value & sign_bit))
501 i->output->f = value;
504 /* Sign-extend to full 64 bits. */
505 value -= sign_bit << 1;
506 i->output->f = -(double) -value;
509 apply_implied_decimals (i);
514 /* Parses PIB format. */
516 parse_PIB (struct data_in *i)
518 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
519 MIN (8, ss_length (i->input)));
521 apply_implied_decimals (i);
526 /* Consumes the first character of S. Stores its high 4 bits in
527 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
529 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
531 int c = ss_get_char (s);
533 *high_nibble = (c >> 4) & 15;
534 *low_nibble = c & 15;
537 /* Parses P format. */
539 parse_P (struct data_in *i)
541 int high_nibble, low_nibble;
545 while (ss_length (i->input) > 1)
547 get_nibbles (&i->input, &high_nibble, &low_nibble);
548 if (high_nibble > 9 || low_nibble > 9)
550 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
553 get_nibbles (&i->input, &high_nibble, &low_nibble);
556 i->output->f = (10 * i->output->f) + high_nibble;
558 i->output->f = (10 * i->output->f) + low_nibble;
559 else if (low_nibble == 0xb || low_nibble == 0xd)
560 i->output->f = -i->output->f;
562 apply_implied_decimals (i);
567 /* Parses PK format. */
569 parse_PK (struct data_in *i)
572 while (!ss_is_empty (i->input))
574 int high_nibble, low_nibble;
576 get_nibbles (&i->input, &high_nibble, &low_nibble);
577 if (high_nibble > 9 || low_nibble > 9)
579 i->output->f = SYSMIS;
582 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
585 apply_implied_decimals (i);
590 /* Parses RB format. */
592 parse_RB (struct data_in *i)
594 enum float_format ff = settings_get_input_float_format ();
595 size_t size = float_get_size (ff);
596 if (ss_length (i->input) >= size)
597 float_convert (ff, ss_data (i->input),
598 FLOAT_NATIVE_DOUBLE, &i->output->f);
600 i->output->f = SYSMIS;
605 /* Parses A format. */
607 parse_A (struct data_in *i)
609 /* This is equivalent to buf_copy_rpad, except that we posibly
610 do a character set recoding in the middle. */
611 char *dst = value_str_rw (i->output, i->width);
612 size_t dst_size = i->width;
613 const char *src = ss_data (i->input);
614 size_t src_size = ss_length (i->input);
616 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
617 if (dst_size > src_size)
618 memset (&dst[src_size], ' ', dst_size - src_size);
623 /* Parses AHEX format. */
625 parse_AHEX (struct data_in *i)
627 char *s = value_str_rw (i->output, i->width);
632 int hi = ss_get_char (&i->input);
633 int lo = ss_get_char (&i->input);
638 data_warning (i, _("Field must have even length."));
642 if (i->encoding != LEGACY_NATIVE)
644 hi = legacy_to_native (i->encoding, hi);
645 lo = legacy_to_native (i->encoding, lo);
647 if (!c_isxdigit (hi) || !c_isxdigit (lo))
649 data_warning (i, _("Field must contain only hex digits."));
654 s[j] = hexit_value (hi) * 16 + hexit_value (lo);
657 memset (&s[j], ' ', i->width - j);
662 /* Date & time format components. */
664 /* Sign of a time value. */
667 SIGN_NO_TIME, /* No time yet encountered. */
668 SIGN_POSITIVE, /* Positive time. */
669 SIGN_NEGATIVE /* Negative time. */
672 /* Parses a signed decimal integer from at most the first
673 MAX_DIGITS characters in I, storing the result into *RESULT.
674 Returns true if successful, false if no integer was
677 parse_int (struct data_in *i, long *result, size_t max_digits)
679 struct substring head = ss_head (i->input, max_digits);
680 size_t n = ss_get_long (&head, result);
683 ss_advance (&i->input, n);
688 data_warning (i, _("Syntax error in date field."));
693 /* Parses a date integer between 1 and 31 from I, storing it into
695 Returns true if successful, false if no date was present. */
697 parse_day (struct data_in *i, long *day)
699 if (!parse_int (i, day, SIZE_MAX))
701 if (*day >= 1 && *day <= 31)
704 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
708 /* Parses an integer from the beginning of I.
709 Adds SECONDS_PER_UNIT times the absolute value of the integer
711 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
712 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
713 Returns true if successful, false if no integer was present. */
715 parse_time_units (struct data_in *i, double seconds_per_unit,
716 enum time_sign *time_sign, double *time)
721 if (*time_sign == SIGN_NO_TIME)
723 if (ss_match_char (&i->input, '-'))
724 *time_sign = SIGN_NEGATIVE;
727 ss_match_char (&i->input, '+');
728 *time_sign = SIGN_POSITIVE;
731 if (!parse_int (i, &units, SIZE_MAX))
735 data_warning (i, _("Syntax error in date field."));
738 *time += units * seconds_per_unit;
742 /* Parses a data delimiter from the beginning of I.
743 Returns true if successful, false if no delimiter was
746 parse_date_delimiter (struct data_in *i)
748 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
751 data_warning (i, _("Delimiter expected between fields in date."));
755 /* Parses spaces at the beginning of I. */
757 parse_spaces (struct data_in *i)
759 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
762 static struct substring
763 parse_name_token (struct data_in *i)
765 struct substring token;
766 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
770 /* Reads a name from I and sets *OUTPUT to the value associated
771 with that name. If ALLOW_SUFFIXES is true, then names that
772 begin with one of the names are accepted; otherwise, only
773 exact matches (except for case) are allowed.
774 Returns true if successful, false otherwise. */
776 match_name (struct substring token, const char *const *names, long *output)
780 for (i = 1; *names != NULL; i++)
781 if (ss_equals_case (ss_cstr (*names++), token))
790 /* Parses a month name or number from the beginning of I,
791 storing the month (in range 1...12) into *MONTH.
792 Returns true if successful, false if no month was present. */
794 parse_month (struct data_in *i, long *month)
796 if (c_isdigit (ss_first (i->input)))
798 if (!parse_int (i, month, SIZE_MAX))
800 if (*month >= 1 && *month <= 12)
805 static const char *const english_names[] =
807 "jan", "feb", "mar", "apr", "may", "jun",
808 "jul", "aug", "sep", "oct", "nov", "dec",
812 static const char *const roman_names[] =
814 "i", "ii", "iii", "iv", "v", "vi",
815 "vii", "viii", "ix", "x", "xi", "xii",
819 struct substring token = parse_name_token (i);
820 if (match_name (ss_head (token, 3), english_names, month)
821 || match_name (ss_head (token, 4), roman_names, month))
825 data_warning (i, _("Unrecognized month format. Months may be specified "
826 "as Arabic or Roman numerals or as at least 3 letters "
827 "of their English names."));
831 /* Parses a year of at most MAX_DIGITS from the beginning of I,
832 storing a "4-digit" year into *YEAR. */
834 parse_year (struct data_in *i, long *year, size_t max_digits)
836 if (!parse_int (i, year, max_digits))
839 if (*year >= 0 && *year <= 99)
841 int epoch = settings_get_epoch ();
842 int epoch_century = ROUND_DOWN (epoch, 100);
843 int epoch_offset = epoch - epoch_century;
844 if (*year >= epoch_offset)
845 *year += epoch_century;
847 *year += epoch_century + 100;
849 if (*year >= 1582 || *year <= 19999)
852 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
856 /* Returns true if input in I has been exhausted,
859 parse_trailer (struct data_in *i)
861 if (ss_is_empty (i->input))
864 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
865 (int) ss_length (i->input), ss_data (i->input));
869 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
870 Returns true if successful, false on failure. */
872 parse_yday (struct data_in *i, long *yday)
874 struct substring num_s;
877 ss_get_chars (&i->input, 3, &num_s);
878 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
880 data_warning (i, _("Julian day must have exactly three digits."));
883 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
885 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
893 /* Parses a quarter-of-year integer between 1 and 4 from I.
894 Stores the corresponding month into *MONTH.
895 Returns true if successful, false if no quarter was present. */
897 parse_quarter (struct data_in *i, long int *month)
901 if (!parse_int (i, &quarter, SIZE_MAX))
903 if (quarter >= 1 && quarter <= 4)
905 *month = (quarter - 1) * 3 + 1;
909 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
913 /* Parses a week-of-year integer between 1 and 53 from I,
914 Stores the corresponding year-of-day into *YDAY.
915 Returns true if successful, false if no week was present. */
917 parse_week (struct data_in *i, long int *yday)
921 if (!parse_int (i, &week, SIZE_MAX))
923 if (week >= 1 && week <= 53)
925 *yday = (week - 1) * 7 + 1;
929 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
933 /* Parses a time delimiter from the beginning of I.
934 Returns true if successful, false if no delimiter was
937 parse_time_delimiter (struct data_in *i)
939 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
942 data_warning (i, _("Delimiter expected between fields in time."));
946 /* Parses minutes and optional seconds from the beginning of I.
947 The time is converted into seconds, which are added to
949 Returns true if successful, false if an error was found. */
951 parse_minute_second (struct data_in *i, double *time)
958 if (!parse_int (i, &minute, SIZE_MAX))
960 if (minute < 0 || minute > 59)
962 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
965 *time += 60. * minute;
967 /* Check for seconds. */
968 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
969 || !c_isdigit (ss_first (i->input)))
974 while (c_isdigit (ss_first (i->input)))
975 *cp++ = ss_get_char (&i->input);
976 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
978 while (c_isdigit (ss_first (i->input)))
979 *cp++ = ss_get_char (&i->input);
982 *time += strtod (buf, NULL);
987 /* Parses a weekday name from the beginning of I,
988 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
989 Returns true if successful, false if an error was found. */
991 parse_weekday (struct data_in *i, long *weekday)
993 static const char *const weekday_names[] =
995 "su", "mo", "tu", "we", "th", "fr", "sa",
999 struct substring token = parse_name_token (i);
1000 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1002 data_warning (i, _("Unrecognized weekday name. At least the first two "
1003 "letters of an English weekday name must be "
1008 /* Date & time formats. */
1010 /* Helper function for passing to
1011 calendar_gregorian_to_offset. */
1013 calendar_error (void *i_, const char *format, ...)
1015 struct data_in *i = i_;
1018 va_start (args, format);
1019 vdata_warning (i, format, args);
1023 /* Parses WKDAY format. */
1025 parse_WKDAY (struct data_in *i)
1029 if (trim_spaces_and_check_missing (i))
1032 if (!parse_weekday (i, &weekday)
1033 || !parse_trailer (i))
1036 i->output->f = weekday;
1040 /* Parses MONTH format. */
1042 parse_MONTH (struct data_in *i)
1046 if (trim_spaces_and_check_missing (i))
1049 if (!parse_month (i, &month)
1050 || !parse_trailer (i))
1053 i->output->f = month;
1057 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1058 DATETIME, TIME and DTIME formats. */
1060 parse_date (struct data_in *i)
1062 long int year = INT_MIN;
1066 double time = 0, date = 0;
1067 enum time_sign time_sign = SIGN_NO_TIME;
1069 const char *template = fmt_date_template (i->format);
1070 size_t template_width = strlen (template);
1072 if (trim_spaces_and_check_missing (i))
1075 while (*template != '\0')
1077 unsigned char ch = *template;
1081 while (template[count] == ch)
1089 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1092 ok = parse_month (i, &month);
1097 if (!c_isalpha (*template))
1098 max_digits = SIZE_MAX;
1101 if (ss_length (i->input) >= template_width + 2)
1106 ok = parse_year (i, &year, max_digits);
1110 ok = parse_quarter (i, &month);
1113 ok = parse_week (i, &yday);
1116 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1119 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1122 ok = parse_minute_second (i, &time);
1128 ok = parse_date_delimiter (i);
1131 ok = parse_time_delimiter (i);
1136 assert (count == 1);
1137 if (!ss_match_char (&i->input, c_toupper (ch))
1138 && !ss_match_char (&i->input, c_tolower (ch)))
1140 data_warning (i, _("`%c' expected in date field."), ch);
1148 if (!parse_trailer (i))
1151 if (year != INT_MIN)
1153 double ofs = calendar_gregorian_to_offset (year, month, day,
1157 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1161 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1166 /* Utility functions. */
1168 /* Outputs FORMAT with the given ARGS as a warning for input
1171 vdata_warning (const struct data_in *i, const char *format, va_list args)
1176 ds_init_empty (&text);
1177 ds_put_char (&text, '(');
1178 if (i->first_column != 0)
1180 if (i->first_column == i->last_column - 1)
1181 ds_put_format (&text, _("column %d"), i->first_column);
1183 ds_put_format (&text, _("columns %d-%d"),
1184 i->first_column, i->last_column - 1);
1185 ds_put_cstr (&text, ", ");
1187 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1188 ds_put_vformat (&text, format, args);
1190 m.category = MSG_DATA;
1191 m.severity = MSG_WARNING;
1192 m.text = ds_cstr (&text);
1197 /* Outputs FORMAT with the given ARGS as a warning for input
1200 data_warning (const struct data_in *i, const char *format, ...)
1204 va_start (args, format);
1205 vdata_warning (i, format, args);
1209 /* Apply implied decimal places to output. */
1211 apply_implied_decimals (struct data_in *i)
1213 if (i->implied_decimals > 0)
1214 i->output->f /= pow (10., i->implied_decimals);
1217 /* Sets the default result for I.
1218 For a numeric format, this is the value set on SET BLANKS
1219 (typically system-missing); for a string format, it is all
1222 default_result (struct data_in *i)
1224 if (fmt_is_string (i->format))
1225 memset (value_str_rw (i->output, i->width), ' ', i->width);
1227 i->output->f = settings_get_blanks ();
1230 /* Trims leading and trailing spaces from I.
1231 If the result is empty, or a single period character, then
1232 sets the default result and returns true; otherwise, returns
1235 trim_spaces_and_check_missing (struct data_in *i)
1237 ss_trim (&i->input, ss_cstr (" "));
1238 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1246 /* Returns the integer value of hex digit C. */
1250 const char s[] = "0123456789abcdef";
1251 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1253 assert (cp != NULL);