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/>. */
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 has the given WIDTH (0 for
89 a numeric field, otherwise the string width).
91 If no decimal point is included in a numeric format, then
92 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
93 decimal places should be implied.
95 If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
96 be the 1-based column number of the first and
97 one-past-the-last-character in INPUT, for use in error
98 messages. (LAST_COLUMN cannot always be calculated from
99 FIRST_COLUMN plus the length of the input because of the
100 possibility of escaped quotes in strings, etc.) */
102 data_in (struct substring input, enum legacy_encoding encoding,
103 enum fmt_type format, int implied_decimals,
104 int first_column, int last_column, union value *output, int width)
106 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
108 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
109 #include "format.def"
116 assert ((width != 0) == fmt_is_string (format));
118 if (encoding == LEGACY_NATIVE
119 || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
122 i.encoding = encoding;
126 ss_alloc_uninit (&i.input, ss_length (input));
127 legacy_recode (encoding, ss_data (input), LEGACY_NATIVE,
128 ss_data (i.input), ss_length (input));
129 i.encoding = LEGACY_NATIVE;
130 copy = ss_data (i.input);
133 i.implied_decimals = implied_decimals;
138 i.first_column = first_column;
139 i.last_column = last_column;
141 if (!ss_is_empty (i.input))
143 ok = handlers[i.format] (&i);
160 /* Format parsers. */
162 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
164 parse_number (struct data_in *i)
166 const struct fmt_number_style *style =
167 settings_get_style (i->format);
171 bool explicit_decimals = false;
175 if (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
177 style = settings_get_style (FMT_F);
180 /* Trim spaces and check for missing value representation. */
181 if (trim_spaces_and_check_missing (i))
184 ds_init_empty (&tmp);
185 ds_extend (&tmp, 64);
187 /* Prefix character may precede sign. */
188 if (!ss_is_empty (style->prefix))
190 ss_match_char (&i->input, ss_first (style->prefix));
191 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
195 if (ss_match_char (&i->input, '-'))
197 ds_put_char (&tmp, '-');
198 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
202 ss_match_char (&i->input, '+');
203 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
206 /* Prefix character may follow sign. */
207 if (!ss_is_empty (style->prefix))
209 ss_match_char (&i->input, ss_first (style->prefix));
210 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
213 /* Digits before decimal point. */
214 while (c_isdigit (ss_first (i->input)))
216 ds_put_char (&tmp, ss_get_char (&i->input));
217 if (style->grouping != 0)
218 ss_match_char (&i->input, style->grouping);
221 /* Decimal point and following digits. */
222 if (ss_match_char (&i->input, style->decimal))
224 explicit_decimals = true;
225 ds_put_char (&tmp, '.');
226 while (c_isdigit (ss_first (i->input)))
227 ds_put_char (&tmp, ss_get_char (&i->input));
231 if (!ds_is_empty (&tmp)
232 && !ss_is_empty (i->input)
233 && strchr ("eEdD-+", ss_first (i->input)))
235 explicit_decimals = true;
236 ds_put_char (&tmp, 'e');
238 if (strchr ("eEdD", ss_first (i->input)))
240 ss_advance (&i->input, 1);
241 ss_match_char (&i->input, ' ');
244 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
246 if (ss_get_char (&i->input) == '-')
247 ds_put_char (&tmp, '-');
248 ss_match_char (&i->input, ' ');
251 while (c_isdigit (ss_first (i->input)))
252 ds_put_char (&tmp, ss_get_char (&i->input));
255 /* Suffix character. */
256 if (!ss_is_empty (style->suffix))
257 ss_match_char (&i->input, ss_first (style->suffix));
259 if (!ss_is_empty (i->input))
261 if (ds_is_empty (&tmp))
262 data_warning (i, _("Field contents are not numeric."));
264 data_warning (i, _("Number followed by garbage."));
269 /* Let c_strtod() do the conversion. */
272 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
275 data_warning (i, _("Invalid numeric syntax."));
280 else if (errno == ERANGE)
282 if (fabs (i->output->f) > 1)
284 data_warning (i, _("Too-large number set to system-missing."));
285 i->output->f = SYSMIS;
289 data_warning (i, _("Too-small number set to zero."));
296 if (!explicit_decimals)
297 apply_implied_decimals (i);
304 /* Parses N format. */
306 parse_N (struct data_in *i)
311 while ((c = ss_get_char (&i->input)) != EOF)
315 data_warning (i, _("All characters in field must be digits."));
318 i->output->f = i->output->f * 10.0 + (c - '0');
321 apply_implied_decimals (i);
325 /* Parses PIBHEX format. */
327 parse_PIBHEX (struct data_in *i)
334 while ((c = ss_get_char (&i->input)) != EOF)
338 data_warning (i, _("Unrecognized character in field."));
341 n = n * 16.0 + hexit_value (c);
348 /* Parses RBHEX format. */
350 parse_RBHEX (struct data_in *i)
355 memset (&d, 0, sizeof d);
356 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
358 int hi = ss_get_char (&i->input);
359 int lo = ss_get_char (&i->input);
362 data_warning (i, _("Field must have even length."));
365 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
367 data_warning (i, _("Field must contain only hex digits."));
370 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
378 /* Digits for Z format. */
379 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
381 /* Returns true if C is a Z format digit, false otherwise. */
385 return c > 0 && strchr (z_digits, c) != NULL;
388 /* Returns the (absolute value of the) value of C as a Z format
391 z_digit_value (int c)
393 assert (is_z_digit (c));
394 return (strchr (z_digits, c) - z_digits) % 10;
397 /* Returns true if Z format digit C represents a negative value,
400 is_negative_z_digit (int c)
402 assert (is_z_digit (c));
403 return (strchr (z_digits, c) - z_digits) >= 20;
406 /* Parses Z format. */
408 parse_Z (struct data_in *i)
414 bool got_dot = false;
415 bool got_final_digit = false;
417 /* Trim spaces and check for missing value representation. */
418 if (trim_spaces_and_check_missing (i))
421 ds_init_empty (&tmp);
422 ds_extend (&tmp, 64);
424 ds_put_char (&tmp, '+');
425 while (!ss_is_empty (i->input))
427 int c = ss_get_char (&i->input);
428 if (c_isdigit (c) && !got_final_digit)
429 ds_put_char (&tmp, c);
430 else if (is_z_digit (c) && !got_final_digit)
432 ds_put_char (&tmp, z_digit_value (c) + '0');
433 if (is_negative_z_digit (c))
434 ds_data (&tmp)[0] = '-';
435 got_final_digit = true;
437 else if (c == '.' && !got_dot)
439 ds_put_char (&tmp, '.');
449 if (!ss_is_empty (i->input))
451 if (ds_length (&tmp) == 1)
452 data_warning (i, _("Field contents are not numeric."));
454 data_warning (i, _("Number followed by garbage."));
459 /* Let c_strtod() do the conversion. */
462 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
465 if (fabs (i->output->f) > 1)
467 data_warning (i, _("Too-large number set to system-missing."));
468 i->output->f = SYSMIS;
472 data_warning (i, _("Too-small number set to zero."));
480 apply_implied_decimals (i);
487 /* Parses IB format. */
489 parse_IB (struct data_in *i)
495 bytes = MIN (8, ss_length (i->input));
496 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
498 sign_bit = UINT64_C(1) << (8 * bytes - 1);
499 if (!(value & sign_bit))
500 i->output->f = value;
503 /* Sign-extend to full 64 bits. */
504 value -= sign_bit << 1;
505 i->output->f = -(double) -value;
508 apply_implied_decimals (i);
513 /* Parses PIB format. */
515 parse_PIB (struct data_in *i)
517 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
518 MIN (8, ss_length (i->input)));
520 apply_implied_decimals (i);
525 /* Consumes the first character of S. Stores its high 4 bits in
526 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
528 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
530 int c = ss_get_char (s);
532 *high_nibble = (c >> 4) & 15;
533 *low_nibble = c & 15;
536 /* Parses P format. */
538 parse_P (struct data_in *i)
540 int high_nibble, low_nibble;
544 while (ss_length (i->input) > 1)
546 get_nibbles (&i->input, &high_nibble, &low_nibble);
547 if (high_nibble > 9 || low_nibble > 9)
549 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
552 get_nibbles (&i->input, &high_nibble, &low_nibble);
555 i->output->f = (10 * i->output->f) + high_nibble;
557 i->output->f = (10 * i->output->f) + low_nibble;
558 else if (low_nibble == 0xb || low_nibble == 0xd)
559 i->output->f = -i->output->f;
561 apply_implied_decimals (i);
566 /* Parses PK format. */
568 parse_PK (struct data_in *i)
571 while (!ss_is_empty (i->input))
573 int high_nibble, low_nibble;
575 get_nibbles (&i->input, &high_nibble, &low_nibble);
576 if (high_nibble > 9 || low_nibble > 9)
578 i->output->f = SYSMIS;
581 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
584 apply_implied_decimals (i);
589 /* Parses RB format. */
591 parse_RB (struct data_in *i)
593 enum float_format ff = settings_get_input_float_format ();
594 size_t size = float_get_size (ff);
595 if (ss_length (i->input) >= size)
596 float_convert (ff, ss_data (i->input),
597 FLOAT_NATIVE_DOUBLE, &i->output->f);
599 i->output->f = SYSMIS;
604 /* Parses A format. */
606 parse_A (struct data_in *i)
608 /* This is equivalent to buf_copy_rpad, except that we posibly
609 do a character set recoding in the middle. */
610 char *dst = i->output->s;
611 size_t dst_size = i->width;
612 const char *src = ss_data (i->input);
613 size_t src_size = ss_length (i->input);
615 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
616 if (dst_size > src_size)
617 memset (&dst[src_size], ' ', dst_size - src_size);
622 /* Parses AHEX format. */
624 parse_AHEX (struct data_in *i)
630 int hi = ss_get_char (&i->input);
631 int lo = ss_get_char (&i->input);
636 data_warning (i, _("Field must have even length."));
640 if (i->encoding != LEGACY_NATIVE)
642 hi = legacy_to_native (i->encoding, hi);
643 lo = legacy_to_native (i->encoding, lo);
645 if (!c_isxdigit (hi) || !c_isxdigit (lo))
647 data_warning (i, _("Field must contain only hex digits."));
652 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
655 memset (i->output->s + j, ' ', i->width - j);
660 /* Date & time format components. */
662 /* Sign of a time value. */
665 SIGN_NO_TIME, /* No time yet encountered. */
666 SIGN_POSITIVE, /* Positive time. */
667 SIGN_NEGATIVE /* Negative time. */
670 /* Parses a signed decimal integer from at most the first
671 MAX_DIGITS characters in I, storing the result into *RESULT.
672 Returns true if successful, false if no integer was
675 parse_int (struct data_in *i, long *result, size_t max_digits)
677 struct substring head = ss_head (i->input, max_digits);
678 size_t n = ss_get_long (&head, result);
681 ss_advance (&i->input, n);
686 data_warning (i, _("Syntax error in date field."));
691 /* Parses a date integer between 1 and 31 from I, storing it into
693 Returns true if successful, false if no date was present. */
695 parse_day (struct data_in *i, long *day)
697 if (!parse_int (i, day, SIZE_MAX))
699 if (*day >= 1 && *day <= 31)
702 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
706 /* Parses an integer from the beginning of I.
707 Adds SECONDS_PER_UNIT times the absolute value of the integer
709 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
710 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
711 Returns true if successful, false if no integer was present. */
713 parse_time_units (struct data_in *i, double seconds_per_unit,
714 enum time_sign *time_sign, double *time)
719 if (*time_sign == SIGN_NO_TIME)
721 if (ss_match_char (&i->input, '-'))
722 *time_sign = SIGN_NEGATIVE;
725 ss_match_char (&i->input, '+');
726 *time_sign = SIGN_POSITIVE;
729 if (!parse_int (i, &units, SIZE_MAX))
733 data_warning (i, _("Syntax error in date field."));
736 *time += units * seconds_per_unit;
740 /* Parses a data delimiter from the beginning of I.
741 Returns true if successful, false if no delimiter was
744 parse_date_delimiter (struct data_in *i)
746 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
749 data_warning (i, _("Delimiter expected between fields in date."));
753 /* Parses spaces at the beginning of I. */
755 parse_spaces (struct data_in *i)
757 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
760 static struct substring
761 parse_name_token (struct data_in *i)
763 struct substring token;
764 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
768 /* Reads a name from I and sets *OUTPUT to the value associated
769 with that name. If ALLOW_SUFFIXES is true, then names that
770 begin with one of the names are accepted; otherwise, only
771 exact matches (except for case) are allowed.
772 Returns true if successful, false otherwise. */
774 match_name (struct substring token, const char *const *names, long *output)
778 for (i = 1; *names != NULL; i++)
779 if (ss_equals_case (ss_cstr (*names++), token))
788 /* Parses a month name or number from the beginning of I,
789 storing the month (in range 1...12) into *MONTH.
790 Returns true if successful, false if no month was present. */
792 parse_month (struct data_in *i, long *month)
794 if (c_isdigit (ss_first (i->input)))
796 if (!parse_int (i, month, SIZE_MAX))
798 if (*month >= 1 && *month <= 12)
803 static const char *const english_names[] =
805 "jan", "feb", "mar", "apr", "may", "jun",
806 "jul", "aug", "sep", "oct", "nov", "dec",
810 static const char *const roman_names[] =
812 "i", "ii", "iii", "iv", "v", "vi",
813 "vii", "viii", "ix", "x", "xi", "xii",
817 struct substring token = parse_name_token (i);
818 if (match_name (ss_head (token, 3), english_names, month)
819 || match_name (ss_head (token, 4), roman_names, month))
823 data_warning (i, _("Unrecognized month format. Months may be specified "
824 "as Arabic or Roman numerals or as at least 3 letters "
825 "of their English names."));
829 /* Parses a year of at most MAX_DIGITS from the beginning of I,
830 storing a "4-digit" year into *YEAR. */
832 parse_year (struct data_in *i, long *year, size_t max_digits)
834 if (!parse_int (i, year, max_digits))
837 if (*year >= 0 && *year <= 99)
839 int epoch = settings_get_epoch ();
840 int epoch_century = ROUND_DOWN (epoch, 100);
841 int epoch_offset = epoch - epoch_century;
842 if (*year >= epoch_offset)
843 *year += epoch_century;
845 *year += epoch_century + 100;
847 if (*year >= 1582 || *year <= 19999)
850 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
854 /* Returns true if input in I has been exhausted,
857 parse_trailer (struct data_in *i)
859 if (ss_is_empty (i->input))
862 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
863 (int) ss_length (i->input), ss_data (i->input));
867 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
868 Returns true if successful, false on failure. */
870 parse_yday (struct data_in *i, long *yday)
872 struct substring num_s;
875 ss_get_chars (&i->input, 3, &num_s);
876 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
878 data_warning (i, _("Julian day must have exactly three digits."));
881 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
883 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
891 /* Parses a quarter-of-year integer between 1 and 4 from I.
892 Stores the corresponding month into *MONTH.
893 Returns true if successful, false if no quarter was present. */
895 parse_quarter (struct data_in *i, long int *month)
899 if (!parse_int (i, &quarter, SIZE_MAX))
901 if (quarter >= 1 && quarter <= 4)
903 *month = (quarter - 1) * 3 + 1;
907 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
911 /* Parses a week-of-year integer between 1 and 53 from I,
912 Stores the corresponding year-of-day into *YDAY.
913 Returns true if successful, false if no week was present. */
915 parse_week (struct data_in *i, long int *yday)
919 if (!parse_int (i, &week, SIZE_MAX))
921 if (week >= 1 && week <= 53)
923 *yday = (week - 1) * 7 + 1;
927 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
931 /* Parses a time delimiter from the beginning of I.
932 Returns true if successful, false if no delimiter was
935 parse_time_delimiter (struct data_in *i)
937 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
940 data_warning (i, _("Delimiter expected between fields in time."));
944 /* Parses minutes and optional seconds from the beginning of I.
945 The time is converted into seconds, which are added to
947 Returns true if successful, false if an error was found. */
949 parse_minute_second (struct data_in *i, double *time)
956 if (!parse_int (i, &minute, SIZE_MAX))
958 if (minute < 0 || minute > 59)
960 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
963 *time += 60. * minute;
965 /* Check for seconds. */
966 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
967 || !c_isdigit (ss_first (i->input)))
972 while (c_isdigit (ss_first (i->input)))
973 *cp++ = ss_get_char (&i->input);
974 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
976 while (c_isdigit (ss_first (i->input)))
977 *cp++ = ss_get_char (&i->input);
980 *time += strtod (buf, NULL);
985 /* Parses a weekday name from the beginning of I,
986 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
987 Returns true if successful, false if an error was found. */
989 parse_weekday (struct data_in *i, long *weekday)
991 static const char *const weekday_names[] =
993 "su", "mo", "tu", "we", "th", "fr", "sa",
997 struct substring token = parse_name_token (i);
998 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1000 data_warning (i, _("Unrecognized weekday name. At least the first two "
1001 "letters of an English weekday name must be "
1006 /* Date & time formats. */
1008 /* Helper function for passing to
1009 calendar_gregorian_to_offset. */
1011 calendar_error (void *i_, const char *format, ...)
1013 struct data_in *i = i_;
1016 va_start (args, format);
1017 vdata_warning (i, format, args);
1021 /* Parses WKDAY format. */
1023 parse_WKDAY (struct data_in *i)
1027 if (trim_spaces_and_check_missing (i))
1030 if (!parse_weekday (i, &weekday)
1031 || !parse_trailer (i))
1034 i->output->f = weekday;
1038 /* Parses MONTH format. */
1040 parse_MONTH (struct data_in *i)
1044 if (trim_spaces_and_check_missing (i))
1047 if (!parse_month (i, &month)
1048 || !parse_trailer (i))
1051 i->output->f = month;
1055 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1056 DATETIME, TIME and DTIME formats. */
1058 parse_date (struct data_in *i)
1060 long int year = INT_MIN;
1064 double time = 0, date = 0;
1065 enum time_sign time_sign = SIGN_NO_TIME;
1067 const char *template = fmt_date_template (i->format);
1068 size_t template_width = strlen (template);
1070 if (trim_spaces_and_check_missing (i))
1073 while (*template != '\0')
1075 unsigned char ch = *template;
1079 while (template[count] == ch)
1087 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1090 ok = parse_month (i, &month);
1095 if (!c_isalpha (*template))
1096 max_digits = SIZE_MAX;
1099 if (ss_length (i->input) >= template_width + 2)
1104 ok = parse_year (i, &year, max_digits);
1108 ok = parse_quarter (i, &month);
1111 ok = parse_week (i, &yday);
1114 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1117 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1120 ok = parse_minute_second (i, &time);
1126 ok = parse_date_delimiter (i);
1129 ok = parse_time_delimiter (i);
1134 assert (count == 1);
1135 if (!ss_match_char (&i->input, c_toupper (ch))
1136 && !ss_match_char (&i->input, c_tolower (ch)))
1138 data_warning (i, _("`%c' expected in date field."), ch);
1146 if (!parse_trailer (i))
1149 if (year != INT_MIN)
1151 double ofs = calendar_gregorian_to_offset (year, month, day,
1155 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1159 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1164 /* Utility functions. */
1166 /* Outputs FORMAT with the given ARGS as a warning for input
1169 vdata_warning (const struct data_in *i, const char *format, va_list args)
1174 ds_init_empty (&text);
1175 ds_put_char (&text, '(');
1176 if (i->first_column != 0)
1178 if (i->first_column == i->last_column - 1)
1179 ds_put_format (&text, _("column %d"), i->first_column);
1181 ds_put_format (&text, _("columns %d-%d"),
1182 i->first_column, i->last_column - 1);
1183 ds_put_cstr (&text, ", ");
1185 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1186 ds_put_vformat (&text, format, args);
1188 m.category = MSG_DATA;
1189 m.severity = MSG_WARNING;
1190 m.text = ds_cstr (&text);
1195 /* Outputs FORMAT with the given ARGS as a warning for input
1198 data_warning (const struct data_in *i, const char *format, ...)
1202 va_start (args, format);
1203 vdata_warning (i, format, args);
1207 /* Apply implied decimal places to output. */
1209 apply_implied_decimals (struct data_in *i)
1211 if (i->implied_decimals > 0)
1212 i->output->f /= pow (10., i->implied_decimals);
1215 /* Sets the default result for I.
1216 For a numeric format, this is the value set on SET BLANKS
1217 (typically system-missing); for a string format, it is all
1220 default_result (struct data_in *i)
1222 if (fmt_is_string (i->format))
1223 memset (i->output->s, ' ', i->width);
1225 i->output->f = settings_get_blanks ();
1228 /* Trims leading and trailing spaces from I.
1229 If the result is empty, or a single period character, then
1230 sets the default result and returns true; otherwise, returns
1233 trim_spaces_and_check_missing (struct data_in *i)
1235 ss_trim (&i->input, ss_cstr (" "));
1236 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1244 /* Returns the integer value of hex digit C. */
1248 const char s[] = "0123456789abcdef";
1249 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1251 assert (cp != NULL);