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"
36 #include <libpspp/assertion.h>
37 #include <libpspp/legacy-encoding.h>
38 #include <libpspp/compiler.h>
39 #include <libpspp/integer-format.h>
40 #include <libpspp/message.h>
41 #include <libpspp/misc.h>
42 #include <libpspp/str.h>
49 #define _(msgid) gettext (msgid)
51 /* Information about parsing one data field. */
54 enum legacy_encoding encoding;/* Encoding of source. */
55 struct substring input; /* Source. */
56 enum fmt_type format; /* Input format. */
57 int implied_decimals; /* Number of implied decimal places. */
59 union value *output; /* Destination. */
60 int width; /* Output width. */
62 int first_column; /* First column of field; 0 if inapplicable. */
63 int last_column; /* Last column. */
68 typedef bool data_in_parser_func (struct data_in *);
69 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
70 static data_in_parser_func parse_##METHOD;
73 static void vdata_warning (const struct data_in *, const char *, va_list)
75 static void data_warning (const struct data_in *, const char *, ...)
78 static void apply_implied_decimals (struct data_in *);
79 static void default_result (struct data_in *);
80 static bool trim_spaces_and_check_missing (struct data_in *);
82 static int hexit_value (int c);
84 /* Parses the characters in INPUT, which are encoded in the given
85 ENCODING, according to FORMAT. Stores the parsed
86 representation in OUTPUT, which has the given WIDTH (0 for
87 a numeric field, otherwise the string width).
89 If no decimal point is included in a numeric format, then
90 IMPLIED_DECIMALS decimal places are implied. Specify 0 if no
91 decimal places should be implied.
93 If FIRST_COLUMN is nonzero, then it should be the 1-based
94 column number of the first character in INPUT, used in error
97 data_in (struct substring input, enum legacy_encoding encoding,
98 enum fmt_type format, int implied_decimals,
99 int first_column, union value *output, int width)
101 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
103 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
104 #include "format.def"
111 assert ((width != 0) == fmt_is_string (format));
113 if (encoding == LEGACY_NATIVE
114 || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
117 i.encoding = encoding;
121 ss_alloc_uninit (&i.input, ss_length (input));
122 legacy_recode (encoding, ss_data (input), LEGACY_NATIVE,
123 ss_data (i.input), ss_length (input));
124 i.encoding = LEGACY_NATIVE;
125 copy = ss_data (i.input);
128 i.implied_decimals = implied_decimals;
133 i.first_column = first_column;
134 i.last_column = first_column + ss_length (input) - 1;
136 if (!ss_is_empty (i.input))
138 ok = handlers[i.format] (&i);
155 /* Format parsers. */
157 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
159 parse_number (struct data_in *i)
161 const struct fmt_number_style *style =
162 settings_get_style (i->format);
166 bool explicit_decimals = false;
170 assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
172 /* Trim spaces and check for missing value representation. */
173 if (trim_spaces_and_check_missing (i))
176 ds_init_empty (&tmp);
177 ds_extend (&tmp, 64);
179 /* Prefix character may precede sign. */
180 if (!ss_is_empty (style->prefix))
182 ss_match_char (&i->input, ss_first (style->prefix));
183 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
187 if (ss_match_char (&i->input, '-'))
189 ds_put_char (&tmp, '-');
190 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
194 ss_match_char (&i->input, '+');
195 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
198 /* Prefix character may follow sign. */
199 if (!ss_is_empty (style->prefix))
201 ss_match_char (&i->input, ss_first (style->prefix));
202 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
205 /* Digits before decimal point. */
206 while (c_isdigit (ss_first (i->input)))
208 ds_put_char (&tmp, ss_get_char (&i->input));
209 if (style->grouping != 0)
210 ss_match_char (&i->input, style->grouping);
213 /* Decimal point and following digits. */
214 if (ss_match_char (&i->input, style->decimal))
216 explicit_decimals = true;
217 ds_put_char (&tmp, '.');
218 while (c_isdigit (ss_first (i->input)))
219 ds_put_char (&tmp, ss_get_char (&i->input));
223 if (!ds_is_empty (&tmp)
224 && !ss_is_empty (i->input)
225 && strchr ("eEdD-+", ss_first (i->input)))
227 explicit_decimals = true;
228 ds_put_char (&tmp, 'e');
230 if (strchr ("eEdD", ss_first (i->input)))
232 ss_advance (&i->input, 1);
233 ss_match_char (&i->input, ' ');
236 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
238 if (ss_get_char (&i->input) == '-')
239 ds_put_char (&tmp, '-');
240 ss_match_char (&i->input, ' ');
243 while (c_isdigit (ss_first (i->input)))
244 ds_put_char (&tmp, ss_get_char (&i->input));
247 /* Suffix character. */
248 if (!ss_is_empty (style->suffix))
249 ss_match_char (&i->input, ss_first (style->suffix));
251 if (!ss_is_empty (i->input))
253 if (ds_is_empty (&tmp))
254 data_warning (i, _("Field contents are not numeric."));
256 data_warning (i, _("Number followed by garbage."));
261 /* Let c_strtod() do the conversion. */
264 i->output->f = c_strtod (ds_cstr (&tmp), &tail);
267 data_warning (i, _("Invalid numeric syntax."));
272 else if (errno == ERANGE)
274 if (fabs (i->output->f) > 1)
276 data_warning (i, _("Too-large number set to system-missing."));
277 i->output->f = SYSMIS;
281 data_warning (i, _("Too-small number set to zero."));
288 if (!explicit_decimals)
289 apply_implied_decimals (i);
296 /* Parses N format. */
298 parse_N (struct data_in *i)
303 while ((c = ss_get_char (&i->input)) != EOF)
307 data_warning (i, _("All characters in field must be digits."));
310 i->output->f = i->output->f * 10.0 + (c - '0');
313 apply_implied_decimals (i);
317 /* Parses PIBHEX format. */
319 parse_PIBHEX (struct data_in *i)
326 while ((c = ss_get_char (&i->input)) != EOF)
330 data_warning (i, _("Unrecognized character in field."));
333 n = n * 16.0 + hexit_value (c);
340 /* Parses RBHEX format. */
342 parse_RBHEX (struct data_in *i)
347 memset (&d, 0, sizeof d);
348 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
350 int hi = ss_get_char (&i->input);
351 int lo = ss_get_char (&i->input);
354 data_warning (i, _("Field must have even length."));
357 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
359 data_warning (i, _("Field must contain only hex digits."));
362 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
370 /* Digits for Z format. */
371 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
373 /* Returns true if C is a Z format digit, false otherwise. */
377 return c > 0 && strchr (z_digits, c) != NULL;
380 /* Returns the (absolute value of the) value of C as a Z format
383 z_digit_value (int c)
385 assert (is_z_digit (c));
386 return (strchr (z_digits, c) - z_digits) % 10;
389 /* Returns true if Z format digit C represents a negative value,
392 is_negative_z_digit (int c)
394 assert (is_z_digit (c));
395 return (strchr (z_digits, c) - z_digits) >= 20;
398 /* Parses Z format. */
400 parse_Z (struct data_in *i)
406 bool got_dot = false;
407 bool got_final_digit = false;
409 /* Trim spaces and check for missing value representation. */
410 if (trim_spaces_and_check_missing (i))
413 ds_init_empty (&tmp);
414 ds_extend (&tmp, 64);
416 ds_put_char (&tmp, '+');
417 while (!ss_is_empty (i->input))
419 int c = ss_get_char (&i->input);
420 if (c_isdigit (c) && !got_final_digit)
421 ds_put_char (&tmp, c);
422 else if (is_z_digit (c) && !got_final_digit)
424 ds_put_char (&tmp, z_digit_value (c) + '0');
425 if (is_negative_z_digit (c))
426 ds_data (&tmp)[0] = '-';
427 got_final_digit = true;
429 else if (c == '.' && !got_dot)
431 ds_put_char (&tmp, '.');
441 if (!ss_is_empty (i->input))
443 if (ds_length (&tmp) == 1)
444 data_warning (i, _("Field contents are not numeric."));
446 data_warning (i, _("Number followed by garbage."));
451 /* Let c_strtod() do the conversion. */
454 i->output->f = c_strtod (ds_cstr (&tmp), NULL);
457 if (fabs (i->output->f) > 1)
459 data_warning (i, _("Too-large number set to system-missing."));
460 i->output->f = SYSMIS;
464 data_warning (i, _("Too-small number set to zero."));
472 apply_implied_decimals (i);
479 /* Parses IB format. */
481 parse_IB (struct data_in *i)
487 bytes = MIN (8, ss_length (i->input));
488 value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
490 sign_bit = UINT64_C(1) << (8 * bytes - 1);
491 if (!(value & sign_bit))
492 i->output->f = value;
495 /* Sign-extend to full 64 bits. */
496 value -= sign_bit << 1;
497 i->output->f = -(double) -value;
500 apply_implied_decimals (i);
505 /* Parses PIB format. */
507 parse_PIB (struct data_in *i)
509 i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
510 MIN (8, ss_length (i->input)));
512 apply_implied_decimals (i);
517 /* Consumes the first character of S. Stores its high 4 bits in
518 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
520 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
522 int c = ss_get_char (s);
524 *high_nibble = (c >> 4) & 15;
525 *low_nibble = c & 15;
528 /* Parses P format. */
530 parse_P (struct data_in *i)
532 int high_nibble, low_nibble;
536 while (ss_length (i->input) > 1)
538 get_nibbles (&i->input, &high_nibble, &low_nibble);
539 if (high_nibble > 9 || low_nibble > 9)
541 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
544 get_nibbles (&i->input, &high_nibble, &low_nibble);
547 i->output->f = (10 * i->output->f) + high_nibble;
549 i->output->f = (10 * i->output->f) + low_nibble;
550 else if (low_nibble == 0xb || low_nibble == 0xd)
551 i->output->f = -i->output->f;
553 apply_implied_decimals (i);
558 /* Parses PK format. */
560 parse_PK (struct data_in *i)
563 while (!ss_is_empty (i->input))
565 int high_nibble, low_nibble;
567 get_nibbles (&i->input, &high_nibble, &low_nibble);
568 if (high_nibble > 9 || low_nibble > 9)
570 i->output->f = SYSMIS;
573 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
576 apply_implied_decimals (i);
581 /* Parses RB format. */
583 parse_RB (struct data_in *i)
585 enum float_format ff = settings_get_input_float_format ();
586 size_t size = float_get_size (ff);
587 if (ss_length (i->input) >= size)
588 float_convert (ff, ss_data (i->input),
589 FLOAT_NATIVE_DOUBLE, &i->output->f);
591 i->output->f = SYSMIS;
596 /* Parses A format. */
598 parse_A (struct data_in *i)
600 /* This is equivalent to buf_copy_rpad, except that we posibly
601 do a character set recoding in the middle. */
602 char *dst = i->output->s;
603 size_t dst_size = i->width;
604 const char *src = ss_data (i->input);
605 size_t src_size = ss_length (i->input);
607 legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
608 if (dst_size > src_size)
609 memset (&dst[src_size], ' ', dst_size - src_size);
614 /* Parses AHEX format. */
616 parse_AHEX (struct data_in *i)
622 int hi = ss_get_char (&i->input);
623 int lo = ss_get_char (&i->input);
628 data_warning (i, _("Field must have even length."));
632 if (i->encoding != LEGACY_NATIVE)
634 hi = legacy_to_native (i->encoding, hi);
635 lo = legacy_to_native (i->encoding, lo);
637 if (!c_isxdigit (hi) || !c_isxdigit (lo))
639 data_warning (i, _("Field must contain only hex digits."));
644 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
647 memset (i->output->s + j, ' ', i->width - j);
652 /* Date & time format components. */
654 /* Sign of a time value. */
657 SIGN_NO_TIME, /* No time yet encountered. */
658 SIGN_POSITIVE, /* Positive time. */
659 SIGN_NEGATIVE /* Negative time. */
662 /* Parses a signed decimal integer from at most the first
663 MAX_DIGITS characters in I, storing the result into *RESULT.
664 Returns true if successful, false if no integer was
667 parse_int (struct data_in *i, long *result, size_t max_digits)
669 struct substring head = ss_head (i->input, max_digits);
670 size_t n = ss_get_long (&head, result);
673 ss_advance (&i->input, n);
678 data_warning (i, _("Syntax error in date field."));
683 /* Parses a date integer between 1 and 31 from I, storing it into
685 Returns true if successful, false if no date was present. */
687 parse_day (struct data_in *i, long *day)
689 if (!parse_int (i, day, SIZE_MAX))
691 if (*day >= 1 && *day <= 31)
694 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
698 /* Parses an integer from the beginning of I.
699 Adds SECONDS_PER_UNIT times the absolute value of the integer
701 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
702 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
703 Returns true if successful, false if no integer was present. */
705 parse_time_units (struct data_in *i, double seconds_per_unit,
706 enum time_sign *time_sign, double *time)
711 if (*time_sign == SIGN_NO_TIME)
713 if (ss_match_char (&i->input, '-'))
714 *time_sign = SIGN_NEGATIVE;
717 ss_match_char (&i->input, '+');
718 *time_sign = SIGN_POSITIVE;
721 if (!parse_int (i, &units, SIZE_MAX))
725 data_warning (i, _("Syntax error in date field."));
728 *time += units * seconds_per_unit;
732 /* Parses a data delimiter from the beginning of I.
733 Returns true if successful, false if no delimiter was
736 parse_date_delimiter (struct data_in *i)
738 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
741 data_warning (i, _("Delimiter expected between fields in date."));
745 /* Parses spaces at the beginning of I. */
747 parse_spaces (struct data_in *i)
749 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
752 static struct substring
753 parse_name_token (struct data_in *i)
755 struct substring token;
756 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
760 /* Reads a name from I and sets *OUTPUT to the value associated
761 with that name. If ALLOW_SUFFIXES is true, then names that
762 begin with one of the names are accepted; otherwise, only
763 exact matches (except for case) are allowed.
764 Returns true if successful, false otherwise. */
766 match_name (struct substring token, const char *const *names, long *output)
770 for (i = 1; *names != NULL; i++)
771 if (ss_equals_case (ss_cstr (*names++), token))
780 /* Parses a month name or number from the beginning of I,
781 storing the month (in range 1...12) into *MONTH.
782 Returns true if successful, false if no month was present. */
784 parse_month (struct data_in *i, long *month)
786 if (c_isdigit (ss_first (i->input)))
788 if (!parse_int (i, month, SIZE_MAX))
790 if (*month >= 1 && *month <= 12)
795 static const char *const english_names[] =
797 "jan", "feb", "mar", "apr", "may", "jun",
798 "jul", "aug", "sep", "oct", "nov", "dec",
802 static const char *const roman_names[] =
804 "i", "ii", "iii", "iv", "v", "vi",
805 "vii", "viii", "ix", "x", "xi", "xii",
809 struct substring token = parse_name_token (i);
810 if (match_name (ss_head (token, 3), english_names, month)
811 || match_name (ss_head (token, 4), roman_names, month))
815 data_warning (i, _("Unrecognized month format. Months may be specified "
816 "as Arabic or Roman numerals or as at least 3 letters "
817 "of their English names."));
821 /* Parses a year of at most MAX_DIGITS from the beginning of I,
822 storing a "4-digit" year into *YEAR. */
824 parse_year (struct data_in *i, long *year, size_t max_digits)
826 if (!parse_int (i, year, max_digits))
829 if (*year >= 0 && *year <= 99)
831 int epoch = settings_get_epoch ();
832 int epoch_century = ROUND_DOWN (epoch, 100);
833 int epoch_offset = epoch - epoch_century;
834 if (*year >= epoch_offset)
835 *year += epoch_century;
837 *year += epoch_century + 100;
839 if (*year >= 1582 || *year <= 19999)
842 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
846 /* Returns true if input in I has been exhausted,
849 parse_trailer (struct data_in *i)
851 if (ss_is_empty (i->input))
854 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
855 (int) ss_length (i->input), ss_data (i->input));
859 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
860 Returns true if successful, false on failure. */
862 parse_yday (struct data_in *i, long *yday)
864 struct substring num_s;
867 ss_get_chars (&i->input, 3, &num_s);
868 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
870 data_warning (i, _("Julian day must have exactly three digits."));
873 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
875 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
883 /* Parses a quarter-of-year integer between 1 and 4 from I.
884 Stores the corresponding month into *MONTH.
885 Returns true if successful, false if no quarter was present. */
887 parse_quarter (struct data_in *i, long int *month)
891 if (!parse_int (i, &quarter, SIZE_MAX))
893 if (quarter >= 1 && quarter <= 4)
895 *month = (quarter - 1) * 3 + 1;
899 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
903 /* Parses a week-of-year integer between 1 and 53 from I,
904 Stores the corresponding year-of-day into *YDAY.
905 Returns true if successful, false if no week was present. */
907 parse_week (struct data_in *i, long int *yday)
911 if (!parse_int (i, &week, SIZE_MAX))
913 if (week >= 1 && week <= 53)
915 *yday = (week - 1) * 7 + 1;
919 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
923 /* Parses a time delimiter from the beginning of I.
924 Returns true if successful, false if no delimiter was
927 parse_time_delimiter (struct data_in *i)
929 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
932 data_warning (i, _("Delimiter expected between fields in time."));
936 /* Parses minutes and optional seconds from the beginning of I.
937 The time is converted into seconds, which are added to
939 Returns true if successful, false if an error was found. */
941 parse_minute_second (struct data_in *i, double *time)
948 if (!parse_int (i, &minute, SIZE_MAX))
950 if (minute < 0 || minute > 59)
952 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
955 *time += 60. * minute;
957 /* Check for seconds. */
958 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
959 || !c_isdigit (ss_first (i->input)))
964 while (c_isdigit (ss_first (i->input)))
965 *cp++ = ss_get_char (&i->input);
966 if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
968 while (c_isdigit (ss_first (i->input)))
969 *cp++ = ss_get_char (&i->input);
972 *time += strtod (buf, NULL);
977 /* Parses a weekday name from the beginning of I,
978 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
979 Returns true if successful, false if an error was found. */
981 parse_weekday (struct data_in *i, long *weekday)
983 static const char *const weekday_names[] =
985 "su", "mo", "tu", "we", "th", "fr", "sa",
989 struct substring token = parse_name_token (i);
990 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
992 data_warning (i, _("Unrecognized weekday name. At least the first two "
993 "letters of an English weekday name must be "
998 /* Date & time formats. */
1000 /* Helper function for passing to
1001 calendar_gregorian_to_offset. */
1003 calendar_error (void *i_, const char *format, ...)
1005 struct data_in *i = i_;
1008 va_start (args, format);
1009 vdata_warning (i, format, args);
1013 /* Parses WKDAY format. */
1015 parse_WKDAY (struct data_in *i)
1019 if (trim_spaces_and_check_missing (i))
1022 if (!parse_weekday (i, &weekday)
1023 || !parse_trailer (i))
1026 i->output->f = weekday;
1030 /* Parses MONTH format. */
1032 parse_MONTH (struct data_in *i)
1036 if (trim_spaces_and_check_missing (i))
1039 if (!parse_month (i, &month)
1040 || !parse_trailer (i))
1043 i->output->f = month;
1047 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1048 DATETIME, TIME and DTIME formats. */
1050 parse_date (struct data_in *i)
1052 long int year = INT_MIN;
1056 double time = 0, date = 0;
1057 enum time_sign time_sign = SIGN_NO_TIME;
1059 const char *template = fmt_date_template (i->format);
1060 size_t template_width = strlen (template);
1062 if (trim_spaces_and_check_missing (i))
1065 while (*template != '\0')
1067 unsigned char ch = *template;
1071 while (template[count] == ch)
1079 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1082 ok = parse_month (i, &month);
1087 if (!c_isalpha (*template))
1088 max_digits = SIZE_MAX;
1091 if (ss_length (i->input) >= template_width + 2)
1096 ok = parse_year (i, &year, max_digits);
1100 ok = parse_quarter (i, &month);
1103 ok = parse_week (i, &yday);
1106 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1109 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1112 ok = parse_minute_second (i, &time);
1118 ok = parse_date_delimiter (i);
1121 ok = parse_time_delimiter (i);
1126 assert (count == 1);
1127 if (!ss_match_char (&i->input, c_toupper (ch))
1128 && !ss_match_char (&i->input, c_tolower (ch)))
1130 data_warning (i, _("`%c' expected in date field."), ch);
1138 if (!parse_trailer (i))
1141 if (year != INT_MIN)
1143 double ofs = calendar_gregorian_to_offset (year, month, day,
1147 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1151 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1156 /* Utility functions. */
1158 /* Outputs FORMAT with the given ARGS as a warning for input
1161 vdata_warning (const struct data_in *i, const char *format, va_list args)
1166 ds_init_empty (&text);
1167 ds_put_char (&text, '(');
1168 if (i->first_column != 0)
1170 if (i->first_column == i->last_column)
1171 ds_put_format (&text, _("column %d"), i->first_column);
1173 ds_put_format (&text, _("columns %d-%d"),
1174 i->first_column, i->last_column);
1175 ds_put_cstr (&text, ", ");
1177 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1178 ds_put_vformat (&text, format, args);
1180 m.category = MSG_DATA;
1181 m.severity = MSG_WARNING;
1182 m.text = ds_cstr (&text);
1187 /* Outputs FORMAT with the given ARGS as a warning for input
1190 data_warning (const struct data_in *i, const char *format, ...)
1194 va_start (args, format);
1195 vdata_warning (i, format, args);
1199 /* Apply implied decimal places to output. */
1201 apply_implied_decimals (struct data_in *i)
1203 if (i->implied_decimals > 0)
1204 i->output->f /= pow (10., i->implied_decimals);
1207 /* Sets the default result for I.
1208 For a numeric format, this is the value set on SET BLANKS
1209 (typically system-missing); for a string format, it is all
1212 default_result (struct data_in *i)
1214 if (fmt_is_string (i->format))
1215 memset (i->output->s, ' ', i->width);
1217 i->output->f = settings_get_blanks ();
1220 /* Trims leading and trailing spaces from I.
1221 If the result is empty, or a single period character, then
1222 sets the default result and returns true; otherwise, returns
1225 trim_spaces_and_check_missing (struct data_in *i)
1227 ss_trim (&i->input, ss_cstr (" "));
1228 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1236 /* Returns the integer value of hex digit C. */
1240 const char s[] = "0123456789abcdef";
1241 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1243 assert (cp != NULL);