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 assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
176 /* Trim spaces and check for missing value representation. */
177 if (trim_spaces_and_check_missing (i))
180 ds_init_empty (&tmp);
181 ds_extend (&tmp, 64);
183 /* Prefix character may precede sign. */
184 if (!ss_is_empty (style->prefix))
186 ss_match_char (&i->input, ss_first (style->prefix));
187 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
191 if (ss_match_char (&i->input, '-'))
193 ds_put_char (&tmp, '-');
194 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
198 ss_match_char (&i->input, '+');
199 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
202 /* Prefix character may follow sign. */
203 if (!ss_is_empty (style->prefix))
205 ss_match_char (&i->input, ss_first (style->prefix));
206 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
209 /* Digits before decimal point. */
210 while (c_isdigit (ss_first (i->input)))
212 ds_put_char (&tmp, ss_get_char (&i->input));
213 if (style->grouping != 0)
214 ss_match_char (&i->input, style->grouping);
217 /* Decimal point and following digits. */
218 if (ss_match_char (&i->input, style->decimal))
220 explicit_decimals = true;
221 ds_put_char (&tmp, '.');
222 while (c_isdigit (ss_first (i->input)))
223 ds_put_char (&tmp, ss_get_char (&i->input));
227 if (!ds_is_empty (&tmp)
228 && !ss_is_empty (i->input)
229 && strchr ("eEdD-+", ss_first (i->input)))
231 explicit_decimals = true;
232 ds_put_char (&tmp, 'e');
234 if (strchr ("eEdD", ss_first (i->input)))
236 ss_advance (&i->input, 1);
237 ss_match_char (&i->input, ' ');
240 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
242 if (ss_get_char (&i->input) == '-')
243 ds_put_char (&tmp, '-');
244 ss_match_char (&i->input, ' ');
247 while (c_isdigit (ss_first (i->input)))
248 ds_put_char (&tmp, ss_get_char (&i->input));
251 /* Suffix character. */
252 if (!ss_is_empty (style->suffix))
253 ss_match_char (&i->input, ss_first (style->suffix));
255 if (!ss_is_empty (i->input))
257 if (ds_is_empty (&tmp))
258 data_warning (i, _("Field contents are not numeric."));
260 data_warning (i, _("Number followed by garbage."));
265 /* Let c_strtod() do the conversion. */
268 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
271 data_warning (i, _("Invalid numeric syntax."));
276 else if (errno == ERANGE)
278 if (fabs (i->output->f) > 1)
280 data_warning (i, _("Too-large number set to system-missing."));
281 i->output->f = SYSMIS;
285 data_warning (i, _("Too-small number set to zero."));
292 if (!explicit_decimals)
293 apply_implied_decimals (i);
300 /* Parses N format. */
302 parse_N (struct data_in *i)
307 while ((c = ss_get_char (&i->input)) != EOF)
311 data_warning (i, _("All characters in field must be digits."));
314 i->output->f = i->output->f * 10.0 + (c - '0');
317 apply_implied_decimals (i);
321 /* Parses PIBHEX format. */
323 parse_PIBHEX (struct data_in *i)
330 while ((c = ss_get_char (&i->input)) != EOF)
334 data_warning (i, _("Unrecognized character in field."));
337 n = n * 16.0 + hexit_value (c);
344 /* Parses RBHEX format. */
346 parse_RBHEX (struct data_in *i)
351 memset (&d, 0, sizeof d);
352 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
354 int hi = ss_get_char (&i->input);
355 int lo = ss_get_char (&i->input);
358 data_warning (i, _("Field must have even length."));
361 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
363 data_warning (i, _("Field must contain only hex digits."));
366 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
374 /* Digits for Z format. */
375 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
377 /* Returns true if C is a Z format digit, false otherwise. */
381 return c > 0 && strchr (z_digits, c) != NULL;
384 /* Returns the (absolute value of the) value of C as a Z format
387 z_digit_value (int c)
389 assert (is_z_digit (c));
390 return (strchr (z_digits, c) - z_digits) % 10;
393 /* Returns true if Z format digit C represents a negative value,
396 is_negative_z_digit (int c)
398 assert (is_z_digit (c));
399 return (strchr (z_digits, c) - z_digits) >= 20;
402 /* Parses Z format. */
404 parse_Z (struct data_in *i)
410 bool got_dot = false;
411 bool got_final_digit = false;
413 /* Trim spaces and check for missing value representation. */
414 if (trim_spaces_and_check_missing (i))
417 ds_init_empty (&tmp);
418 ds_extend (&tmp, 64);
420 ds_put_char (&tmp, '+');
421 while (!ss_is_empty (i->input))
423 int c = ss_get_char (&i->input);
424 if (c_isdigit (c) && !got_final_digit)
425 ds_put_char (&tmp, c);
426 else if (is_z_digit (c) && !got_final_digit)
428 ds_put_char (&tmp, z_digit_value (c) + '0');
429 if (is_negative_z_digit (c))
430 ds_data (&tmp)[0] = '-';
431 got_final_digit = true;
433 else if (c == '.' && !got_dot)
435 ds_put_char (&tmp, '.');
445 if (!ss_is_empty (i->input))
447 if (ds_length (&tmp) == 1)
448 data_warning (i, _("Field contents are not numeric."));
450 data_warning (i, _("Number followed by garbage."));
455 /* Let c_strtod() do the conversion. */
458 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
461 if (fabs (i->output->f) > 1)
463 data_warning (i, _("Too-large number set to system-missing."));
464 i->output->f = SYSMIS;
468 data_warning (i, _("Too-small number set to zero."));
476 apply_implied_decimals (i);
483 /* Parses IB format. */
485 parse_IB (struct data_in *i)
491 bytes = MIN (8, ss_length (i->input));
492 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
494 sign_bit = UINT64_C(1) << (8 * bytes - 1);
495 if (!(value & sign_bit))
496 i->output->f = value;
499 /* Sign-extend to full 64 bits. */
500 value -= sign_bit << 1;
501 i->output->f = -(double) -value;
504 apply_implied_decimals (i);
509 /* Parses PIB format. */
511 parse_PIB (struct data_in *i)
513 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
514 MIN (8, ss_length (i->input)));
516 apply_implied_decimals (i);
521 /* Consumes the first character of S. Stores its high 4 bits in
522 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
524 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
526 int c = ss_get_char (s);
528 *high_nibble = (c >> 4) & 15;
529 *low_nibble = c & 15;
532 /* Parses P format. */
534 parse_P (struct data_in *i)
536 int high_nibble, low_nibble;
540 while (ss_length (i->input) > 1)
542 get_nibbles (&i->input, &high_nibble, &low_nibble);
543 if (high_nibble > 9 || low_nibble > 9)
545 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
548 get_nibbles (&i->input, &high_nibble, &low_nibble);
551 i->output->f = (10 * i->output->f) + high_nibble;
553 i->output->f = (10 * i->output->f) + low_nibble;
554 else if (low_nibble == 0xb || low_nibble == 0xd)
555 i->output->f = -i->output->f;
557 apply_implied_decimals (i);
562 /* Parses PK format. */
564 parse_PK (struct data_in *i)
567 while (!ss_is_empty (i->input))
569 int high_nibble, low_nibble;
571 get_nibbles (&i->input, &high_nibble, &low_nibble);
572 if (high_nibble > 9 || low_nibble > 9)
574 i->output->f = SYSMIS;
577 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
580 apply_implied_decimals (i);
585 /* Parses RB format. */
587 parse_RB (struct data_in *i)
589 enum float_format ff = settings_get_input_float_format ();
590 size_t size = float_get_size (ff);
591 if (ss_length (i->input) >= size)
592 float_convert (ff, ss_data (i->input),
593 FLOAT_NATIVE_DOUBLE, &i->output->f);
595 i->output->f = SYSMIS;
600 /* Parses A format. */
602 parse_A (struct data_in *i)
604 /* This is equivalent to buf_copy_rpad, except that we posibly
605 do a character set recoding in the middle. */
606 char *dst = i->output->s;
607 size_t dst_size = i->width;
608 const char *src = ss_data (i->input);
609 size_t src_size = ss_length (i->input);
611 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
612 if (dst_size > src_size)
613 memset (&dst[src_size], ' ', dst_size - src_size);
618 /* Parses AHEX format. */
620 parse_AHEX (struct data_in *i)
626 int hi = ss_get_char (&i->input);
627 int lo = ss_get_char (&i->input);
632 data_warning (i, _("Field must have even length."));
636 if (i->encoding != LEGACY_NATIVE)
638 hi = legacy_to_native (i->encoding, hi);
639 lo = legacy_to_native (i->encoding, lo);
641 if (!c_isxdigit (hi) || !c_isxdigit (lo))
643 data_warning (i, _("Field must contain only hex digits."));
648 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
651 memset (i->output->s + j, ' ', i->width - j);
656 /* Date & time format components. */
658 /* Sign of a time value. */
661 SIGN_NO_TIME, /* No time yet encountered. */
662 SIGN_POSITIVE, /* Positive time. */
663 SIGN_NEGATIVE /* Negative time. */
666 /* Parses a signed decimal integer from at most the first
667 MAX_DIGITS characters in I, storing the result into *RESULT.
668 Returns true if successful, false if no integer was
671 parse_int (struct data_in *i, long *result, size_t max_digits)
673 struct substring head = ss_head (i->input, max_digits);
674 size_t n = ss_get_long (&head, result);
677 ss_advance (&i->input, n);
682 data_warning (i, _("Syntax error in date field."));
687 /* Parses a date integer between 1 and 31 from I, storing it into
689 Returns true if successful, false if no date was present. */
691 parse_day (struct data_in *i, long *day)
693 if (!parse_int (i, day, SIZE_MAX))
695 if (*day >= 1 && *day <= 31)
698 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
702 /* Parses an integer from the beginning of I.
703 Adds SECONDS_PER_UNIT times the absolute value of the integer
705 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
706 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
707 Returns true if successful, false if no integer was present. */
709 parse_time_units (struct data_in *i, double seconds_per_unit,
710 enum time_sign *time_sign, double *time)
715 if (*time_sign == SIGN_NO_TIME)
717 if (ss_match_char (&i->input, '-'))
718 *time_sign = SIGN_NEGATIVE;
721 ss_match_char (&i->input, '+');
722 *time_sign = SIGN_POSITIVE;
725 if (!parse_int (i, &units, SIZE_MAX))
729 data_warning (i, _("Syntax error in date field."));
732 *time += units * seconds_per_unit;
736 /* Parses a data delimiter from the beginning of I.
737 Returns true if successful, false if no delimiter was
740 parse_date_delimiter (struct data_in *i)
742 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
745 data_warning (i, _("Delimiter expected between fields in date."));
749 /* Parses spaces at the beginning of I. */
751 parse_spaces (struct data_in *i)
753 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
756 static struct substring
757 parse_name_token (struct data_in *i)
759 struct substring token;
760 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
764 /* Reads a name from I and sets *OUTPUT to the value associated
765 with that name. If ALLOW_SUFFIXES is true, then names that
766 begin with one of the names are accepted; otherwise, only
767 exact matches (except for case) are allowed.
768 Returns true if successful, false otherwise. */
770 match_name (struct substring token, const char *const *names, long *output)
774 for (i = 1; *names != NULL; i++)
775 if (ss_equals_case (ss_cstr (*names++), token))
784 /* Parses a month name or number from the beginning of I,
785 storing the month (in range 1...12) into *MONTH.
786 Returns true if successful, false if no month was present. */
788 parse_month (struct data_in *i, long *month)
790 if (c_isdigit (ss_first (i->input)))
792 if (!parse_int (i, month, SIZE_MAX))
794 if (*month >= 1 && *month <= 12)
799 static const char *const english_names[] =
801 "jan", "feb", "mar", "apr", "may", "jun",
802 "jul", "aug", "sep", "oct", "nov", "dec",
806 static const char *const roman_names[] =
808 "i", "ii", "iii", "iv", "v", "vi",
809 "vii", "viii", "ix", "x", "xi", "xii",
813 struct substring token = parse_name_token (i);
814 if (match_name (ss_head (token, 3), english_names, month)
815 || match_name (ss_head (token, 4), roman_names, month))
819 data_warning (i, _("Unrecognized month format. Months may be specified "
820 "as Arabic or Roman numerals or as at least 3 letters "
821 "of their English names."));
825 /* Parses a year of at most MAX_DIGITS from the beginning of I,
826 storing a "4-digit" year into *YEAR. */
828 parse_year (struct data_in *i, long *year, size_t max_digits)
830 if (!parse_int (i, year, max_digits))
833 if (*year >= 0 && *year <= 99)
835 int epoch = settings_get_epoch ();
836 int epoch_century = ROUND_DOWN (epoch, 100);
837 int epoch_offset = epoch - epoch_century;
838 if (*year >= epoch_offset)
839 *year += epoch_century;
841 *year += epoch_century + 100;
843 if (*year >= 1582 || *year <= 19999)
846 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
850 /* Returns true if input in I has been exhausted,
853 parse_trailer (struct data_in *i)
855 if (ss_is_empty (i->input))
858 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
859 (int) ss_length (i->input), ss_data (i->input));
863 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
864 Returns true if successful, false on failure. */
866 parse_yday (struct data_in *i, long *yday)
868 struct substring num_s;
871 ss_get_chars (&i->input, 3, &num_s);
872 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
874 data_warning (i, _("Julian day must have exactly three digits."));
877 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
879 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
887 /* Parses a quarter-of-year integer between 1 and 4 from I.
888 Stores the corresponding month into *MONTH.
889 Returns true if successful, false if no quarter was present. */
891 parse_quarter (struct data_in *i, long int *month)
895 if (!parse_int (i, &quarter, SIZE_MAX))
897 if (quarter >= 1 && quarter <= 4)
899 *month = (quarter - 1) * 3 + 1;
903 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
907 /* Parses a week-of-year integer between 1 and 53 from I,
908 Stores the corresponding year-of-day into *YDAY.
909 Returns true if successful, false if no week was present. */
911 parse_week (struct data_in *i, long int *yday)
915 if (!parse_int (i, &week, SIZE_MAX))
917 if (week >= 1 && week <= 53)
919 *yday = (week - 1) * 7 + 1;
923 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
927 /* Parses a time delimiter from the beginning of I.
928 Returns true if successful, false if no delimiter was
931 parse_time_delimiter (struct data_in *i)
933 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
936 data_warning (i, _("Delimiter expected between fields in time."));
940 /* Parses minutes and optional seconds from the beginning of I.
941 The time is converted into seconds, which are added to
943 Returns true if successful, false if an error was found. */
945 parse_minute_second (struct data_in *i, double *time)
952 if (!parse_int (i, &minute, SIZE_MAX))
954 if (minute < 0 || minute > 59)
956 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
959 *time += 60. * minute;
961 /* Check for seconds. */
962 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
963 || !c_isdigit (ss_first (i->input)))
968 while (c_isdigit (ss_first (i->input)))
969 *cp++ = ss_get_char (&i->input);
970 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
972 while (c_isdigit (ss_first (i->input)))
973 *cp++ = ss_get_char (&i->input);
976 *time += strtod (buf, NULL);
981 /* Parses a weekday name from the beginning of I,
982 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
983 Returns true if successful, false if an error was found. */
985 parse_weekday (struct data_in *i, long *weekday)
987 static const char *const weekday_names[] =
989 "su", "mo", "tu", "we", "th", "fr", "sa",
993 struct substring token = parse_name_token (i);
994 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
996 data_warning (i, _("Unrecognized weekday name. At least the first two "
997 "letters of an English weekday name must be "
1002 /* Date & time formats. */
1004 /* Helper function for passing to
1005 calendar_gregorian_to_offset. */
1007 calendar_error (void *i_, const char *format, ...)
1009 struct data_in *i = i_;
1012 va_start (args, format);
1013 vdata_warning (i, format, args);
1017 /* Parses WKDAY format. */
1019 parse_WKDAY (struct data_in *i)
1023 if (trim_spaces_and_check_missing (i))
1026 if (!parse_weekday (i, &weekday)
1027 || !parse_trailer (i))
1030 i->output->f = weekday;
1034 /* Parses MONTH format. */
1036 parse_MONTH (struct data_in *i)
1040 if (trim_spaces_and_check_missing (i))
1043 if (!parse_month (i, &month)
1044 || !parse_trailer (i))
1047 i->output->f = month;
1051 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1052 DATETIME, TIME and DTIME formats. */
1054 parse_date (struct data_in *i)
1056 long int year = INT_MIN;
1060 double time = 0, date = 0;
1061 enum time_sign time_sign = SIGN_NO_TIME;
1063 const char *template = fmt_date_template (i->format);
1064 size_t template_width = strlen (template);
1066 if (trim_spaces_and_check_missing (i))
1069 while (*template != '\0')
1071 unsigned char ch = *template;
1075 while (template[count] == ch)
1083 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1086 ok = parse_month (i, &month);
1091 if (!c_isalpha (*template))
1092 max_digits = SIZE_MAX;
1095 if (ss_length (i->input) >= template_width + 2)
1100 ok = parse_year (i, &year, max_digits);
1104 ok = parse_quarter (i, &month);
1107 ok = parse_week (i, &yday);
1110 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1113 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1116 ok = parse_minute_second (i, &time);
1122 ok = parse_date_delimiter (i);
1125 ok = parse_time_delimiter (i);
1130 assert (count == 1);
1131 if (!ss_match_char (&i->input, c_toupper (ch))
1132 && !ss_match_char (&i->input, c_tolower (ch)))
1134 data_warning (i, _("`%c' expected in date field."), ch);
1142 if (!parse_trailer (i))
1145 if (year != INT_MIN)
1147 double ofs = calendar_gregorian_to_offset (year, month, day,
1151 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1155 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1160 /* Utility functions. */
1162 /* Outputs FORMAT with the given ARGS as a warning for input
1165 vdata_warning (const struct data_in *i, const char *format, va_list args)
1170 ds_init_empty (&text);
1171 ds_put_char (&text, '(');
1172 if (i->first_column != 0)
1174 if (i->first_column == i->last_column - 1)
1175 ds_put_format (&text, _("column %d"), i->first_column);
1177 ds_put_format (&text, _("columns %d-%d"),
1178 i->first_column, i->last_column - 1);
1179 ds_put_cstr (&text, ", ");
1181 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1182 ds_put_vformat (&text, format, args);
1184 m.category = MSG_DATA;
1185 m.severity = MSG_WARNING;
1186 m.text = ds_cstr (&text);
1191 /* Outputs FORMAT with the given ARGS as a warning for input
1194 data_warning (const struct data_in *i, const char *format, ...)
1198 va_start (args, format);
1199 vdata_warning (i, format, args);
1203 /* Apply implied decimal places to output. */
1205 apply_implied_decimals (struct data_in *i)
1207 if (i->implied_decimals > 0)
1208 i->output->f /= pow (10., i->implied_decimals);
1211 /* Sets the default result for I.
1212 For a numeric format, this is the value set on SET BLANKS
1213 (typically system-missing); for a string format, it is all
1216 default_result (struct data_in *i)
1218 if (fmt_is_string (i->format))
1219 memset (i->output->s, ' ', i->width);
1221 i->output->f = settings_get_blanks ();
1224 /* Trims leading and trailing spaces from I.
1225 If the result is empty, or a single period character, then
1226 sets the default result and returns true; otherwise, returns
1229 trim_spaces_and_check_missing (struct data_in *i)
1231 ss_trim (&i->input, ss_cstr (" "));
1232 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1240 /* Returns the integer value of hex digit C. */
1244 const char s[] = "0123456789abcdef";
1245 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1247 assert (cp != NULL);