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"
37 #include <libpspp/assertion.h>
38 #include <libpspp/legacy-encoding.h>
39 #include <libpspp/compiler.h>
40 #include <libpspp/integer-format.h>
41 #include <libpspp/message.h>
42 #include <libpspp/misc.h>
43 #include <libpspp/str.h>
50 #define _(msgid) gettext (msgid)
52 /* Information about parsing one data field. */
55 enum legacy_encoding encoding;/* Encoding of source. */
56 struct substring input; /* Source. */
57 enum fmt_type format; /* Input format. */
58 int implied_decimals; /* Number of implied decimal places. */
60 union value *output; /* Destination. */
61 int width; /* Output width. */
63 int first_column; /* First column of field; 0 if inapplicable. */
64 int last_column; /* Last column. */
69 typedef bool data_in_parser_func (struct data_in *);
70 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
71 static data_in_parser_func parse_##METHOD;
74 static void vdata_warning (const struct data_in *, const char *, va_list)
76 static void data_warning (const struct data_in *, const char *, ...)
79 static void apply_implied_decimals (struct data_in *);
80 static void default_result (struct data_in *);
81 static bool trim_spaces_and_check_missing (struct data_in *);
83 static int hexit_value (int c);
85 /* Parses the characters in INPUT, which are encoded in the given
86 ENCODING, according to FORMAT. Stores the parsed
87 representation in OUTPUT, which has the given WIDTH (0 for
88 a numeric field, otherwise the string width).
90 If no decimal point is included in a numeric format, then
91 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
92 decimal places should be implied.
94 If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
95 be the 1-based column number of the first and
96 one-past-the-last-character in INPUT, for use in error
97 messages. (LAST_COLUMN cannot always be calculated from
98 FIRST_COLUMN plus the length of the input because of the
99 possibility of escaped quotes in strings, etc.) */
101 data_in (struct substring input, enum legacy_encoding encoding,
102 enum fmt_type format, int implied_decimals,
103 int first_column, int last_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 = last_column;
140 if (!ss_is_empty (i.input))
142 ok = handlers[i.format] (&i);
159 /* Format parsers. */
161 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
163 parse_number (struct data_in *i)
165 const struct fmt_number_style *style =
166 settings_get_style (i->format);
170 bool explicit_decimals = false;
174 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
176 style = settings_get_style (FMT_F);
179 /* Trim spaces and check for missing value representation. */
180 if (trim_spaces_and_check_missing (i))
183 ds_init_empty (&tmp);
184 ds_extend (&tmp, 64);
186 /* Prefix character may precede sign. */
187 if (!ss_is_empty (style->prefix))
189 ss_match_char (&i->input, ss_first (style->prefix));
190 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
194 if (ss_match_char (&i->input, '-'))
196 ds_put_char (&tmp, '-');
197 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
201 ss_match_char (&i->input, '+');
202 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
205 /* Prefix character may follow sign. */
206 if (!ss_is_empty (style->prefix))
208 ss_match_char (&i->input, ss_first (style->prefix));
209 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
212 /* Digits before decimal point. */
213 while (c_isdigit (ss_first (i->input)))
215 ds_put_char (&tmp, ss_get_char (&i->input));
216 if (style->grouping != 0)
217 ss_match_char (&i->input, style->grouping);
220 /* Decimal point and following digits. */
221 if (ss_match_char (&i->input, style->decimal))
223 explicit_decimals = true;
224 ds_put_char (&tmp, '.');
225 while (c_isdigit (ss_first (i->input)))
226 ds_put_char (&tmp, ss_get_char (&i->input));
230 if (!ds_is_empty (&tmp)
231 && !ss_is_empty (i->input)
232 && strchr ("eEdD-+", ss_first (i->input)))
234 explicit_decimals = true;
235 ds_put_char (&tmp, 'e');
237 if (strchr ("eEdD", ss_first (i->input)))
239 ss_advance (&i->input, 1);
240 ss_match_char (&i->input, ' ');
243 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
245 if (ss_get_char (&i->input) == '-')
246 ds_put_char (&tmp, '-');
247 ss_match_char (&i->input, ' ');
250 while (c_isdigit (ss_first (i->input)))
251 ds_put_char (&tmp, ss_get_char (&i->input));
254 /* Suffix character. */
255 if (!ss_is_empty (style->suffix))
256 ss_match_char (&i->input, ss_first (style->suffix));
258 if (!ss_is_empty (i->input))
260 if (ds_is_empty (&tmp))
261 data_warning (i, _("Field contents are not numeric."));
263 data_warning (i, _("Number followed by garbage."));
268 /* Let c_strtod() do the conversion. */
271 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
274 data_warning (i, _("Invalid numeric syntax."));
279 else if (errno == ERANGE)
281 if (fabs (i->output->f) > 1)
283 data_warning (i, _("Too-large number set to system-missing."));
284 i->output->f = SYSMIS;
288 data_warning (i, _("Too-small number set to zero."));
295 if (!explicit_decimals)
296 apply_implied_decimals (i);
303 /* Parses N format. */
305 parse_N (struct data_in *i)
310 while ((c = ss_get_char (&i->input)) != EOF)
314 data_warning (i, _("All characters in field must be digits."));
317 i->output->f = i->output->f * 10.0 + (c - '0');
320 apply_implied_decimals (i);
324 /* Parses PIBHEX format. */
326 parse_PIBHEX (struct data_in *i)
333 while ((c = ss_get_char (&i->input)) != EOF)
337 data_warning (i, _("Unrecognized character in field."));
340 n = n * 16.0 + hexit_value (c);
347 /* Parses RBHEX format. */
349 parse_RBHEX (struct data_in *i)
354 memset (&d, 0, sizeof d);
355 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
357 int hi = ss_get_char (&i->input);
358 int lo = ss_get_char (&i->input);
361 data_warning (i, _("Field must have even length."));
364 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
366 data_warning (i, _("Field must contain only hex digits."));
369 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
377 /* Digits for Z format. */
378 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
380 /* Returns true if C is a Z format digit, false otherwise. */
384 return c > 0 && strchr (z_digits, c) != NULL;
387 /* Returns the (absolute value of the) value of C as a Z format
390 z_digit_value (int c)
392 assert (is_z_digit (c));
393 return (strchr (z_digits, c) - z_digits) % 10;
396 /* Returns true if Z format digit C represents a negative value,
399 is_negative_z_digit (int c)
401 assert (is_z_digit (c));
402 return (strchr (z_digits, c) - z_digits) >= 20;
405 /* Parses Z format. */
407 parse_Z (struct data_in *i)
413 bool got_dot = false;
414 bool got_final_digit = false;
416 /* Trim spaces and check for missing value representation. */
417 if (trim_spaces_and_check_missing (i))
420 ds_init_empty (&tmp);
421 ds_extend (&tmp, 64);
423 ds_put_char (&tmp, '+');
424 while (!ss_is_empty (i->input))
426 int c = ss_get_char (&i->input);
427 if (c_isdigit (c) && !got_final_digit)
428 ds_put_char (&tmp, c);
429 else if (is_z_digit (c) && !got_final_digit)
431 ds_put_char (&tmp, z_digit_value (c) + '0');
432 if (is_negative_z_digit (c))
433 ds_data (&tmp)[0] = '-';
434 got_final_digit = true;
436 else if (c == '.' && !got_dot)
438 ds_put_char (&tmp, '.');
448 if (!ss_is_empty (i->input))
450 if (ds_length (&tmp) == 1)
451 data_warning (i, _("Field contents are not numeric."));
453 data_warning (i, _("Number followed by garbage."));
458 /* Let c_strtod() do the conversion. */
461 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
464 if (fabs (i->output->f) > 1)
466 data_warning (i, _("Too-large number set to system-missing."));
467 i->output->f = SYSMIS;
471 data_warning (i, _("Too-small number set to zero."));
479 apply_implied_decimals (i);
486 /* Parses IB format. */
488 parse_IB (struct data_in *i)
494 bytes = MIN (8, ss_length (i->input));
495 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
497 sign_bit = UINT64_C(1) << (8 * bytes - 1);
498 if (!(value & sign_bit))
499 i->output->f = value;
502 /* Sign-extend to full 64 bits. */
503 value -= sign_bit << 1;
504 i->output->f = -(double) -value;
507 apply_implied_decimals (i);
512 /* Parses PIB format. */
514 parse_PIB (struct data_in *i)
516 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
517 MIN (8, ss_length (i->input)));
519 apply_implied_decimals (i);
524 /* Consumes the first character of S. Stores its high 4 bits in
525 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
527 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
529 int c = ss_get_char (s);
531 *high_nibble = (c >> 4) & 15;
532 *low_nibble = c & 15;
535 /* Parses P format. */
537 parse_P (struct data_in *i)
539 int high_nibble, low_nibble;
543 while (ss_length (i->input) > 1)
545 get_nibbles (&i->input, &high_nibble, &low_nibble);
546 if (high_nibble > 9 || low_nibble > 9)
548 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
551 get_nibbles (&i->input, &high_nibble, &low_nibble);
554 i->output->f = (10 * i->output->f) + high_nibble;
556 i->output->f = (10 * i->output->f) + low_nibble;
557 else if (low_nibble == 0xb || low_nibble == 0xd)
558 i->output->f = -i->output->f;
560 apply_implied_decimals (i);
565 /* Parses PK format. */
567 parse_PK (struct data_in *i)
570 while (!ss_is_empty (i->input))
572 int high_nibble, low_nibble;
574 get_nibbles (&i->input, &high_nibble, &low_nibble);
575 if (high_nibble > 9 || low_nibble > 9)
577 i->output->f = SYSMIS;
580 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
583 apply_implied_decimals (i);
588 /* Parses RB format. */
590 parse_RB (struct data_in *i)
592 enum float_format ff = settings_get_input_float_format ();
593 size_t size = float_get_size (ff);
594 if (ss_length (i->input) >= size)
595 float_convert (ff, ss_data (i->input),
596 FLOAT_NATIVE_DOUBLE, &i->output->f);
598 i->output->f = SYSMIS;
603 /* Parses A format. */
605 parse_A (struct data_in *i)
607 /* This is equivalent to buf_copy_rpad, except that we posibly
608 do a character set recoding in the middle. */
609 char *dst = i->output->s;
610 size_t dst_size = i->width;
611 const char *src = ss_data (i->input);
612 size_t src_size = ss_length (i->input);
614 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
615 if (dst_size > src_size)
616 memset (&dst[src_size], ' ', dst_size - src_size);
621 /* Parses AHEX format. */
623 parse_AHEX (struct data_in *i)
629 int hi = ss_get_char (&i->input);
630 int lo = ss_get_char (&i->input);
635 data_warning (i, _("Field must have even length."));
639 if (i->encoding != LEGACY_NATIVE)
641 hi = legacy_to_native (i->encoding, hi);
642 lo = legacy_to_native (i->encoding, lo);
644 if (!c_isxdigit (hi) || !c_isxdigit (lo))
646 data_warning (i, _("Field must contain only hex digits."));
651 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
654 memset (i->output->s + j, ' ', i->width - j);
659 /* Date & time format components. */
661 /* Sign of a time value. */
664 SIGN_NO_TIME, /* No time yet encountered. */
665 SIGN_POSITIVE, /* Positive time. */
666 SIGN_NEGATIVE /* Negative time. */
669 /* Parses a signed decimal integer from at most the first
670 MAX_DIGITS characters in I, storing the result into *RESULT.
671 Returns true if successful, false if no integer was
674 parse_int (struct data_in *i, long *result, size_t max_digits)
676 struct substring head = ss_head (i->input, max_digits);
677 size_t n = ss_get_long (&head, result);
680 ss_advance (&i->input, n);
685 data_warning (i, _("Syntax error in date field."));
690 /* Parses a date integer between 1 and 31 from I, storing it into
692 Returns true if successful, false if no date was present. */
694 parse_day (struct data_in *i, long *day)
696 if (!parse_int (i, day, SIZE_MAX))
698 if (*day >= 1 && *day <= 31)
701 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
705 /* Parses an integer from the beginning of I.
706 Adds SECONDS_PER_UNIT times the absolute value of the integer
708 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
709 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
710 Returns true if successful, false if no integer was present. */
712 parse_time_units (struct data_in *i, double seconds_per_unit,
713 enum time_sign *time_sign, double *time)
718 if (*time_sign == SIGN_NO_TIME)
720 if (ss_match_char (&i->input, '-'))
721 *time_sign = SIGN_NEGATIVE;
724 ss_match_char (&i->input, '+');
725 *time_sign = SIGN_POSITIVE;
728 if (!parse_int (i, &units, SIZE_MAX))
732 data_warning (i, _("Syntax error in date field."));
735 *time += units * seconds_per_unit;
739 /* Parses a data delimiter from the beginning of I.
740 Returns true if successful, false if no delimiter was
743 parse_date_delimiter (struct data_in *i)
745 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
748 data_warning (i, _("Delimiter expected between fields in date."));
752 /* Parses spaces at the beginning of I. */
754 parse_spaces (struct data_in *i)
756 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
759 static struct substring
760 parse_name_token (struct data_in *i)
762 struct substring token;
763 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
767 /* Reads a name from I and sets *OUTPUT to the value associated
768 with that name. If ALLOW_SUFFIXES is true, then names that
769 begin with one of the names are accepted; otherwise, only
770 exact matches (except for case) are allowed.
771 Returns true if successful, false otherwise. */
773 match_name (struct substring token, const char *const *names, long *output)
777 for (i = 1; *names != NULL; i++)
778 if (ss_equals_case (ss_cstr (*names++), token))
787 /* Parses a month name or number from the beginning of I,
788 storing the month (in range 1...12) into *MONTH.
789 Returns true if successful, false if no month was present. */
791 parse_month (struct data_in *i, long *month)
793 if (c_isdigit (ss_first (i->input)))
795 if (!parse_int (i, month, SIZE_MAX))
797 if (*month >= 1 && *month <= 12)
802 static const char *const english_names[] =
804 "jan", "feb", "mar", "apr", "may", "jun",
805 "jul", "aug", "sep", "oct", "nov", "dec",
809 static const char *const roman_names[] =
811 "i", "ii", "iii", "iv", "v", "vi",
812 "vii", "viii", "ix", "x", "xi", "xii",
816 struct substring token = parse_name_token (i);
817 if (match_name (ss_head (token, 3), english_names, month)
818 || match_name (ss_head (token, 4), roman_names, month))
822 data_warning (i, _("Unrecognized month format. Months may be specified "
823 "as Arabic or Roman numerals or as at least 3 letters "
824 "of their English names."));
828 /* Parses a year of at most MAX_DIGITS from the beginning of I,
829 storing a "4-digit" year into *YEAR. */
831 parse_year (struct data_in *i, long *year, size_t max_digits)
833 if (!parse_int (i, year, max_digits))
836 if (*year >= 0 && *year <= 99)
838 int epoch = settings_get_epoch ();
839 int epoch_century = ROUND_DOWN (epoch, 100);
840 int epoch_offset = epoch - epoch_century;
841 if (*year >= epoch_offset)
842 *year += epoch_century;
844 *year += epoch_century + 100;
846 if (*year >= 1582 || *year <= 19999)
849 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
853 /* Returns true if input in I has been exhausted,
856 parse_trailer (struct data_in *i)
858 if (ss_is_empty (i->input))
861 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
862 (int) ss_length (i->input), ss_data (i->input));
866 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
867 Returns true if successful, false on failure. */
869 parse_yday (struct data_in *i, long *yday)
871 struct substring num_s;
874 ss_get_chars (&i->input, 3, &num_s);
875 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
877 data_warning (i, _("Julian day must have exactly three digits."));
880 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
882 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
890 /* Parses a quarter-of-year integer between 1 and 4 from I.
891 Stores the corresponding month into *MONTH.
892 Returns true if successful, false if no quarter was present. */
894 parse_quarter (struct data_in *i, long int *month)
898 if (!parse_int (i, &quarter, SIZE_MAX))
900 if (quarter >= 1 && quarter <= 4)
902 *month = (quarter - 1) * 3 + 1;
906 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
910 /* Parses a week-of-year integer between 1 and 53 from I,
911 Stores the corresponding year-of-day into *YDAY.
912 Returns true if successful, false if no week was present. */
914 parse_week (struct data_in *i, long int *yday)
918 if (!parse_int (i, &week, SIZE_MAX))
920 if (week >= 1 && week <= 53)
922 *yday = (week - 1) * 7 + 1;
926 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
930 /* Parses a time delimiter from the beginning of I.
931 Returns true if successful, false if no delimiter was
934 parse_time_delimiter (struct data_in *i)
936 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
939 data_warning (i, _("Delimiter expected between fields in time."));
943 /* Parses minutes and optional seconds from the beginning of I.
944 The time is converted into seconds, which are added to
946 Returns true if successful, false if an error was found. */
948 parse_minute_second (struct data_in *i, double *time)
955 if (!parse_int (i, &minute, SIZE_MAX))
957 if (minute < 0 || minute > 59)
959 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
962 *time += 60. * minute;
964 /* Check for seconds. */
965 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
966 || !c_isdigit (ss_first (i->input)))
971 while (c_isdigit (ss_first (i->input)))
972 *cp++ = ss_get_char (&i->input);
973 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
975 while (c_isdigit (ss_first (i->input)))
976 *cp++ = ss_get_char (&i->input);
979 *time += strtod (buf, NULL);
984 /* Parses a weekday name from the beginning of I,
985 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
986 Returns true if successful, false if an error was found. */
988 parse_weekday (struct data_in *i, long *weekday)
990 static const char *const weekday_names[] =
992 "su", "mo", "tu", "we", "th", "fr", "sa",
996 struct substring token = parse_name_token (i);
997 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
999 data_warning (i, _("Unrecognized weekday name. At least the first two "
1000 "letters of an English weekday name must be "
1005 /* Date & time formats. */
1007 /* Helper function for passing to
1008 calendar_gregorian_to_offset. */
1010 calendar_error (void *i_, const char *format, ...)
1012 struct data_in *i = i_;
1015 va_start (args, format);
1016 vdata_warning (i, format, args);
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)
1150 double ofs = calendar_gregorian_to_offset (year, month, day,
1154 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1158 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1163 /* Utility functions. */
1165 /* Outputs FORMAT with the given ARGS as a warning for input
1168 vdata_warning (const struct data_in *i, const char *format, va_list args)
1173 ds_init_empty (&text);
1174 ds_put_char (&text, '(');
1175 if (i->first_column != 0)
1177 if (i->first_column == i->last_column - 1)
1178 ds_put_format (&text, _("column %d"), i->first_column);
1180 ds_put_format (&text, _("columns %d-%d"),
1181 i->first_column, i->last_column - 1);
1182 ds_put_cstr (&text, ", ");
1184 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1185 ds_put_vformat (&text, format, args);
1187 m.category = MSG_DATA;
1188 m.severity = MSG_WARNING;
1189 m.text = ds_cstr (&text);
1194 /* Outputs FORMAT with the given ARGS as a warning for input
1197 data_warning (const struct data_in *i, const char *format, ...)
1201 va_start (args, format);
1202 vdata_warning (i, format, args);
1206 /* Apply implied decimal places to output. */
1208 apply_implied_decimals (struct data_in *i)
1210 if (i->implied_decimals > 0)
1211 i->output->f /= pow (10., i->implied_decimals);
1214 /* Sets the default result for I.
1215 For a numeric format, this is the value set on SET BLANKS
1216 (typically system-missing); for a string format, it is all
1219 default_result (struct data_in *i)
1221 if (fmt_is_string (i->format))
1222 memset (i->output->s, ' ', i->width);
1224 i->output->f = settings_get_blanks ();
1227 /* Trims leading and trailing spaces from I.
1228 If the result is empty, or a single period character, then
1229 sets the default result and returns true; otherwise, returns
1232 trim_spaces_and_check_missing (struct data_in *i)
1234 ss_trim (&i->input, ss_cstr (" "));
1235 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1243 /* Returns the integer value of hex digit C. */
1247 const char s[] = "0123456789abcdef";
1248 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1250 assert (cp != NULL);