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 "identifier.h"
37 #include "dictionary.h"
39 #include <libpspp/assertion.h>
40 #include <libpspp/legacy-encoding.h>
41 #include <libpspp/i18n.h>
42 #include <libpspp/compiler.h>
43 #include <libpspp/integer-format.h>
44 #include <libpspp/message.h>
45 #include <libpspp/misc.h>
46 #include <libpspp/str.h>
53 #define _(msgid) gettext (msgid)
55 /* Information about parsing one data field. */
58 const char *src_enc; /* Encoding of source. */
59 struct substring input; /* Source. */
60 enum fmt_type format; /* Input format. */
61 int implied_decimals; /* Number of implied decimal places. */
63 union value *output; /* Destination. */
64 int width; /* Output width. */
66 int first_column; /* First column of field; 0 if inapplicable. */
67 int last_column; /* Last column. */
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 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).
91 Iff FORMAT is a string format, then DICT must be a pointer
92 to the dictionary associated with OUTPUT. Otherwise, DICT
95 If no decimal point is included in a numeric format, then
96 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
97 decimal places should be implied.
99 If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
100 be the 1-based column number of the first and
101 one-past-the-last-character in INPUT, for use in error
102 messages. (LAST_COLUMN cannot always be calculated from
103 FIRST_COLUMN plus the length of the input because of the
104 possibility of escaped quotes in strings, etc.) */
106 data_in (struct substring input, const char *encoding,
107 enum fmt_type format, int implied_decimals,
108 int first_column, int last_column,
109 const struct dictionary *dict,
110 union value *output, int width)
112 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
114 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
115 #include "format.def"
123 assert ((width != 0) == fmt_is_string (format));
126 i.implied_decimals = implied_decimals;
131 i.first_column = first_column;
132 i.last_column = last_column;
133 i.src_enc = encoding;
135 if (ss_is_empty (input))
141 if (fmt_get_category (format) & ( FMT_CAT_BINARY | FMT_CAT_HEXADECIMAL | FMT_CAT_LEGACY))
147 const char *dest_encoding;
151 assert (0 == (fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING)));
152 dest_encoding = LEGACY_NATIVE;
155 dest_encoding = dict_get_encoding (dict);
157 s = recode_string (dest_encoding, i.src_enc, ss_data (input), ss_length (input));
158 i.input = ss_cstr (s);
161 ok = handlers[i.format] (&i);
170 /* Format parsers. */
172 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
174 parse_number (struct data_in *i)
176 const struct fmt_number_style *style =
177 settings_get_style (i->format);
181 bool explicit_decimals = false;
185 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
187 style = settings_get_style (FMT_F);
190 /* Trim spaces and check for missing value representation. */
191 if (trim_spaces_and_check_missing (i))
194 ds_init_empty (&tmp);
195 ds_extend (&tmp, 64);
197 /* Prefix character may precede sign. */
198 if (!ss_is_empty (style->prefix))
200 ss_match_char (&i->input, ss_first (style->prefix));
201 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
205 if (ss_match_char (&i->input, '-'))
207 ds_put_char (&tmp, '-');
208 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
212 ss_match_char (&i->input, '+');
213 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
216 /* Prefix character may follow sign. */
217 if (!ss_is_empty (style->prefix))
219 ss_match_char (&i->input, ss_first (style->prefix));
220 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
223 /* Digits before decimal point. */
224 while (c_isdigit (ss_first (i->input)))
226 ds_put_char (&tmp, ss_get_char (&i->input));
227 if (style->grouping != 0)
228 ss_match_char (&i->input, style->grouping);
231 /* Decimal point and following digits. */
232 if (ss_match_char (&i->input, style->decimal))
234 explicit_decimals = true;
235 ds_put_char (&tmp, '.');
236 while (c_isdigit (ss_first (i->input)))
237 ds_put_char (&tmp, ss_get_char (&i->input));
241 if (!ds_is_empty (&tmp)
242 && !ss_is_empty (i->input)
243 && strchr ("eEdD-+", ss_first (i->input)))
245 explicit_decimals = true;
246 ds_put_char (&tmp, 'e');
248 if (strchr ("eEdD", ss_first (i->input)))
250 ss_advance (&i->input, 1);
251 ss_match_char (&i->input, ' ');
254 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
256 if (ss_get_char (&i->input) == '-')
257 ds_put_char (&tmp, '-');
258 ss_match_char (&i->input, ' ');
261 while (c_isdigit (ss_first (i->input)))
262 ds_put_char (&tmp, ss_get_char (&i->input));
265 /* Suffix character. */
266 if (!ss_is_empty (style->suffix))
267 ss_match_char (&i->input, ss_first (style->suffix));
269 if (!ss_is_empty (i->input))
271 if (ds_is_empty (&tmp))
272 data_warning (i, _("Field contents are not numeric."));
274 data_warning (i, _("Number followed by garbage."));
279 /* Let c_strtod() do the conversion. */
282 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
285 data_warning (i, _("Invalid numeric syntax."));
290 else if (errno == ERANGE)
292 if (fabs (i->output->f) > 1)
294 data_warning (i, _("Too-large number set to system-missing."));
295 i->output->f = SYSMIS;
299 data_warning (i, _("Too-small number set to zero."));
306 if (!explicit_decimals)
307 apply_implied_decimals (i);
314 /* Parses N format. */
316 parse_N (struct data_in *i)
321 while ((c = ss_get_char (&i->input)) != EOF)
325 data_warning (i, _("All characters in field must be digits."));
328 i->output->f = i->output->f * 10.0 + (c - '0');
331 apply_implied_decimals (i);
335 /* Parses PIBHEX format. */
337 parse_PIBHEX (struct data_in *i)
344 while ((c = ss_get_char (&i->input)) != EOF)
348 data_warning (i, _("Unrecognized character in field."));
351 n = n * 16.0 + hexit_value (c);
358 /* Parses RBHEX format. */
360 parse_RBHEX (struct data_in *i)
365 memset (&d, 0, sizeof d);
366 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
368 int hi = ss_get_char (&i->input);
369 int lo = ss_get_char (&i->input);
372 data_warning (i, _("Field must have even length."));
375 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
377 data_warning (i, _("Field must contain only hex digits."));
380 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
388 /* Digits for Z format. */
389 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
391 /* Returns true if C is a Z format digit, false otherwise. */
395 return c > 0 && strchr (z_digits, c) != NULL;
398 /* Returns the (absolute value of the) value of C as a Z format
401 z_digit_value (int c)
403 assert (is_z_digit (c));
404 return (strchr (z_digits, c) - z_digits) % 10;
407 /* Returns true if Z format digit C represents a negative value,
410 is_negative_z_digit (int c)
412 assert (is_z_digit (c));
413 return (strchr (z_digits, c) - z_digits) >= 20;
416 /* Parses Z format. */
418 parse_Z (struct data_in *i)
424 bool got_dot = false;
425 bool got_final_digit = false;
427 /* Trim spaces and check for missing value representation. */
428 if (trim_spaces_and_check_missing (i))
431 ds_init_empty (&tmp);
432 ds_extend (&tmp, 64);
434 ds_put_char (&tmp, '+');
435 while (!ss_is_empty (i->input))
437 int c = ss_get_char (&i->input);
438 if (c_isdigit (c) && !got_final_digit)
439 ds_put_char (&tmp, c);
440 else if (is_z_digit (c) && !got_final_digit)
442 ds_put_char (&tmp, z_digit_value (c) + '0');
443 if (is_negative_z_digit (c))
444 ds_data (&tmp)[0] = '-';
445 got_final_digit = true;
447 else if (c == '.' && !got_dot)
449 ds_put_char (&tmp, '.');
459 if (!ss_is_empty (i->input))
461 if (ds_length (&tmp) == 1)
462 data_warning (i, _("Field contents are not numeric."));
464 data_warning (i, _("Number followed by garbage."));
469 /* Let c_strtod() do the conversion. */
472 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
475 if (fabs (i->output->f) > 1)
477 data_warning (i, _("Too-large number set to system-missing."));
478 i->output->f = SYSMIS;
482 data_warning (i, _("Too-small number set to zero."));
490 apply_implied_decimals (i);
497 /* Parses IB format. */
499 parse_IB (struct data_in *i)
505 bytes = MIN (8, ss_length (i->input));
506 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
508 sign_bit = UINT64_C(1) << (8 * bytes - 1);
509 if (!(value & sign_bit))
510 i->output->f = value;
513 /* Sign-extend to full 64 bits. */
514 value -= sign_bit << 1;
515 i->output->f = -(double) -value;
518 apply_implied_decimals (i);
523 /* Parses PIB format. */
525 parse_PIB (struct data_in *i)
527 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
528 MIN (8, ss_length (i->input)));
530 apply_implied_decimals (i);
535 /* Consumes the first character of S. Stores its high 4 bits in
536 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
538 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
540 int c = ss_get_char (s);
542 *high_nibble = (c >> 4) & 15;
543 *low_nibble = c & 15;
546 /* Parses P format. */
548 parse_P (struct data_in *i)
550 int high_nibble, low_nibble;
554 while (ss_length (i->input) > 1)
556 get_nibbles (&i->input, &high_nibble, &low_nibble);
557 if (high_nibble > 9 || low_nibble > 9)
559 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
562 get_nibbles (&i->input, &high_nibble, &low_nibble);
565 i->output->f = (10 * i->output->f) + high_nibble;
567 i->output->f = (10 * i->output->f) + low_nibble;
568 else if (low_nibble == 0xb || low_nibble == 0xd)
569 i->output->f = -i->output->f;
571 apply_implied_decimals (i);
576 /* Parses PK format. */
578 parse_PK (struct data_in *i)
581 while (!ss_is_empty (i->input))
583 int high_nibble, low_nibble;
585 get_nibbles (&i->input, &high_nibble, &low_nibble);
586 if (high_nibble > 9 || low_nibble > 9)
588 i->output->f = SYSMIS;
591 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
594 apply_implied_decimals (i);
599 /* Parses RB format. */
601 parse_RB (struct data_in *i)
603 enum float_format ff = settings_get_input_float_format ();
604 size_t size = float_get_size (ff);
605 if (ss_length (i->input) >= size)
606 float_convert (ff, ss_data (i->input),
607 FLOAT_NATIVE_DOUBLE, &i->output->f);
609 i->output->f = SYSMIS;
614 /* Parses A format. */
616 parse_A (struct data_in *i)
618 /* This is equivalent to buf_copy_rpad, except that we posibly
619 do a character set recoding in the middle. */
620 uint8_t *dst = value_str_rw (i->output, i->width);
621 size_t dst_size = i->width;
622 const char *src = ss_data (i->input);
623 size_t src_size = ss_length (i->input);
625 memcpy (dst, src, MIN (src_size, dst_size));
627 if (dst_size > src_size)
628 memset (&dst[src_size], ' ', dst_size - src_size);
633 /* Parses AHEX format. */
635 parse_AHEX (struct data_in *i)
637 uint8_t *s = value_str_rw (i->output, i->width);
642 int hi = ss_get_char (&i->input);
643 int lo = ss_get_char (&i->input);
648 data_warning (i, _("Field must have even length."));
652 if (0 != strcmp (i->src_enc, LEGACY_NATIVE))
654 hi = legacy_to_native (i->src_enc, hi);
655 lo = legacy_to_native (i->src_enc, lo);
657 if (!c_isxdigit (hi) || !c_isxdigit (lo))
659 data_warning (i, _("Field must contain only hex digits."));
664 s[j] = hexit_value (hi) * 16 + hexit_value (lo);
667 memset (&s[j], ' ', i->width - j);
672 /* Date & time format components. */
674 /* Sign of a time value. */
677 SIGN_NO_TIME, /* No time yet encountered. */
678 SIGN_POSITIVE, /* Positive time. */
679 SIGN_NEGATIVE /* Negative time. */
682 /* Parses a signed decimal integer from at most the first
683 MAX_DIGITS characters in I, storing the result into *RESULT.
684 Returns true if successful, false if no integer was
687 parse_int (struct data_in *i, long *result, size_t max_digits)
689 struct substring head = ss_head (i->input, max_digits);
690 size_t n = ss_get_long (&head, result);
693 ss_advance (&i->input, n);
698 data_warning (i, _("Syntax error in date field."));
703 /* Parses a date integer between 1 and 31 from I, storing it into
705 Returns true if successful, false if no date was present. */
707 parse_day (struct data_in *i, long *day)
709 if (!parse_int (i, day, SIZE_MAX))
711 if (*day >= 1 && *day <= 31)
714 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
718 /* Parses an integer from the beginning of I.
719 Adds SECONDS_PER_UNIT times the absolute value of the integer
721 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
722 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
723 Returns true if successful, false if no integer was present. */
725 parse_time_units (struct data_in *i, double seconds_per_unit,
726 enum time_sign *time_sign, double *time)
731 if (*time_sign == SIGN_NO_TIME)
733 if (ss_match_char (&i->input, '-'))
734 *time_sign = SIGN_NEGATIVE;
737 ss_match_char (&i->input, '+');
738 *time_sign = SIGN_POSITIVE;
741 if (!parse_int (i, &units, SIZE_MAX))
745 data_warning (i, _("Syntax error in date field."));
748 *time += units * seconds_per_unit;
752 /* Parses a data delimiter from the beginning of I.
753 Returns true if successful, false if no delimiter was
756 parse_date_delimiter (struct data_in *i)
758 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
761 data_warning (i, _("Delimiter expected between fields in date."));
765 /* Parses spaces at the beginning of I. */
767 parse_spaces (struct data_in *i)
769 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
772 static struct substring
773 parse_name_token (struct data_in *i)
775 struct substring token;
776 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
780 /* Reads a name from I and sets *OUTPUT to the value associated
781 with that name. If ALLOW_SUFFIXES is true, then names that
782 begin with one of the names are accepted; otherwise, only
783 exact matches (except for case) are allowed.
784 Returns true if successful, false otherwise. */
786 match_name (struct substring token, const char *const *names, long *output)
790 for (i = 1; *names != NULL; i++)
791 if (ss_equals_case (ss_cstr (*names++), token))
800 /* Parses a month name or number from the beginning of I,
801 storing the month (in range 1...12) into *MONTH.
802 Returns true if successful, false if no month was present. */
804 parse_month (struct data_in *i, long *month)
806 if (c_isdigit (ss_first (i->input)))
808 if (!parse_int (i, month, SIZE_MAX))
810 if (*month >= 1 && *month <= 12)
815 static const char *const english_names[] =
817 "jan", "feb", "mar", "apr", "may", "jun",
818 "jul", "aug", "sep", "oct", "nov", "dec",
822 static const char *const roman_names[] =
824 "i", "ii", "iii", "iv", "v", "vi",
825 "vii", "viii", "ix", "x", "xi", "xii",
829 struct substring token = parse_name_token (i);
830 if (match_name (ss_head (token, 3), english_names, month)
831 || match_name (ss_head (token, 4), roman_names, month))
835 data_warning (i, _("Unrecognized month format. Months may be specified "
836 "as Arabic or Roman numerals or as at least 3 letters "
837 "of their English names."));
841 /* Parses a year of at most MAX_DIGITS from the beginning of I,
842 storing a "4-digit" year into *YEAR. */
844 parse_year (struct data_in *i, long *year, size_t max_digits)
846 if (!parse_int (i, year, max_digits))
849 if (*year >= 0 && *year <= 99)
851 int epoch = settings_get_epoch ();
852 int epoch_century = ROUND_DOWN (epoch, 100);
853 int epoch_offset = epoch - epoch_century;
854 if (*year >= epoch_offset)
855 *year += epoch_century;
857 *year += epoch_century + 100;
859 if (*year >= 1582 || *year <= 19999)
862 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
866 /* Returns true if input in I has been exhausted,
869 parse_trailer (struct data_in *i)
871 if (ss_is_empty (i->input))
874 data_warning (i, _("Trailing garbage `%.*s' following date."),
875 (int) ss_length (i->input), ss_data (i->input));
879 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
880 Returns true if successful, false on failure. */
882 parse_yday (struct data_in *i, long *yday)
884 struct substring num_s;
887 ss_get_chars (&i->input, 3, &num_s);
888 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
890 data_warning (i, _("Julian day must have exactly three digits."));
893 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
895 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
903 /* Parses a quarter-of-year integer between 1 and 4 from I.
904 Stores the corresponding month into *MONTH.
905 Returns true if successful, false if no quarter was present. */
907 parse_quarter (struct data_in *i, long int *month)
911 if (!parse_int (i, &quarter, SIZE_MAX))
913 if (quarter >= 1 && quarter <= 4)
915 *month = (quarter - 1) * 3 + 1;
919 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
923 /* Parses a week-of-year integer between 1 and 53 from I,
924 Stores the corresponding year-of-day into *YDAY.
925 Returns true if successful, false if no week was present. */
927 parse_week (struct data_in *i, long int *yday)
931 if (!parse_int (i, &week, SIZE_MAX))
933 if (week >= 1 && week <= 53)
935 *yday = (week - 1) * 7 + 1;
939 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
943 /* Parses a time delimiter from the beginning of I.
944 Returns true if successful, false if no delimiter was
947 parse_time_delimiter (struct data_in *i)
949 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
952 data_warning (i, _("Delimiter expected between fields in time."));
956 /* Parses minutes and optional seconds from the beginning of I.
957 The time is converted into seconds, which are added to
959 Returns true if successful, false if an error was found. */
961 parse_minute_second (struct data_in *i, double *time)
968 if (!parse_int (i, &minute, SIZE_MAX))
970 if (minute < 0 || minute > 59)
972 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
975 *time += 60. * minute;
977 /* Check for seconds. */
978 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
979 || !c_isdigit (ss_first (i->input)))
984 while (c_isdigit (ss_first (i->input)))
985 *cp++ = ss_get_char (&i->input);
986 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
988 while (c_isdigit (ss_first (i->input)))
989 *cp++ = ss_get_char (&i->input);
992 *time += strtod (buf, NULL);
997 /* Parses a weekday name from the beginning of I,
998 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
999 Returns true if successful, false if an error was found. */
1001 parse_weekday (struct data_in *i, long *weekday)
1003 static const char *const weekday_names[] =
1005 "su", "mo", "tu", "we", "th", "fr", "sa",
1009 struct substring token = parse_name_token (i);
1010 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1012 data_warning (i, _("Unrecognized weekday name. At least the first two "
1013 "letters of an English weekday name must be "
1018 /* Date & time formats. */
1020 /* Parses WKDAY format. */
1022 parse_WKDAY (struct data_in *i)
1026 if (trim_spaces_and_check_missing (i))
1029 if (!parse_weekday (i, &weekday)
1030 || !parse_trailer (i))
1033 i->output->f = weekday;
1037 /* Parses MONTH format. */
1039 parse_MONTH (struct data_in *i)
1043 if (trim_spaces_and_check_missing (i))
1046 if (!parse_month (i, &month)
1047 || !parse_trailer (i))
1050 i->output->f = month;
1054 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1055 DATETIME, TIME and DTIME formats. */
1057 parse_date (struct data_in *i)
1059 long int year = INT_MIN;
1063 double time = 0, date = 0;
1064 enum time_sign time_sign = SIGN_NO_TIME;
1066 const char *template = fmt_date_template (i->format);
1067 size_t template_width = strlen (template);
1069 if (trim_spaces_and_check_missing (i))
1072 while (*template != '\0')
1074 unsigned char ch = *template;
1078 while (template[count] == ch)
1086 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1089 ok = parse_month (i, &month);
1094 if (!c_isalpha (*template))
1095 max_digits = SIZE_MAX;
1098 if (ss_length (i->input) >= template_width + 2)
1103 ok = parse_year (i, &year, max_digits);
1107 ok = parse_quarter (i, &month);
1110 ok = parse_week (i, &yday);
1113 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1116 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1119 ok = parse_minute_second (i, &time);
1125 ok = parse_date_delimiter (i);
1128 ok = parse_time_delimiter (i);
1133 assert (count == 1);
1134 if (!ss_match_char (&i->input, c_toupper (ch))
1135 && !ss_match_char (&i->input, c_tolower (ch)))
1137 data_warning (i, _("`%c' expected in date field."), ch);
1145 if (!parse_trailer (i))
1148 if (year != INT_MIN)
1153 ofs = calendar_gregorian_to_offset (year, month, day, &error);
1156 data_warning (i, "%s", error);
1160 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1164 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1169 /* Utility functions. */
1171 /* Outputs FORMAT with as a warning for input I. */
1173 data_warning (const struct data_in *i, const char *format, ...)
1179 ds_init_empty (&text);
1180 ds_put_char (&text, '(');
1181 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1183 va_start (args, format);
1184 ds_put_vformat (&text, format, args);
1187 m.category = MSG_C_DATA;
1188 m.severity = MSG_S_WARNING;
1189 m.text = ds_cstr (&text);
1190 m.where.file_name = NULL;
1191 m.where.line_number = 0;
1192 m.where.first_column = i->first_column;
1193 m.where.last_column = i->last_column;
1198 /* Apply implied decimal places to output. */
1200 apply_implied_decimals (struct data_in *i)
1202 if (i->implied_decimals > 0)
1203 i->output->f /= pow (10., i->implied_decimals);
1206 /* Sets the default result for I.
1207 For a numeric format, this is the value set on SET BLANKS
1208 (typically system-missing); for a string format, it is all
1211 default_result (struct data_in *i)
1213 if (fmt_is_string (i->format))
1214 memset (value_str_rw (i->output, i->width), ' ', i->width);
1216 i->output->f = settings_get_blanks ();
1219 /* Trims leading and trailing spaces from I.
1220 If the result is empty, or a single period character, then
1221 sets the default result and returns true; otherwise, returns
1224 trim_spaces_and_check_missing (struct data_in *i)
1226 ss_trim (&i->input, ss_cstr (" "));
1227 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1235 /* Returns the integer value of hex digit C. */
1239 const char s[] = "0123456789abcdef";
1240 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1242 assert (cp != NULL);