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/compiler.h>
38 #include <libpspp/integer-format.h>
39 #include <libpspp/message.h>
40 #include <libpspp/misc.h>
41 #include <libpspp/str.h>
48 #define _(msgid) gettext (msgid)
50 /* Information about parsing one data field. */
53 struct substring input; /* Source. */
54 enum fmt_type format; /* Input format. */
55 int implied_decimals; /* Number of implied decimal places. */
57 union value *output; /* Destination. */
58 int width; /* Output width. */
60 int first_column; /* First column of field; 0 if inapplicable. */
61 int last_column; /* Last column. */
64 /* Integer format used for IB and PIB input. */
65 static enum integer_format input_integer_format = INTEGER_NATIVE;
67 /* Floating-point format used for RB and RBHEX input. */
68 static enum float_format input_float_format = FLOAT_NATIVE_DOUBLE;
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 according to FORMAT. Stores
87 the parsed representation in OUTPUT, which has the given WIDTH
88 (0 for 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 is nonzero, then it should be the 1-based
95 column number of the first character in INPUT, used in error
98 data_in (struct substring input,
99 enum fmt_type format, int implied_decimals,
100 int first_column, union value *output, int width)
102 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
104 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
105 #include "format.def"
111 assert ((width != 0) == fmt_is_string (format));
115 i.implied_decimals = implied_decimals;
120 i.first_column = first_column;
121 i.last_column = first_column + ss_length (input) - 1;
123 if (!ss_is_empty (i.input))
125 ok = handlers[i.format] (&i);
138 /* Returns the integer format used for IB and PIB input. */
140 data_in_get_integer_format (void)
142 return input_integer_format;
145 /* Sets the integer format used for IB and PIB input to
148 data_in_set_integer_format (enum integer_format format)
150 input_integer_format = format;
153 /* Returns the floating-point format used for RB and RBHEX
156 data_in_get_float_format (void)
158 return input_float_format;
161 /* Sets the floating-point format used for RB and RBHEX input to
164 data_in_set_float_format (enum float_format format)
166 input_float_format = format;
169 /* Format parsers. */
171 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
173 parse_number (struct data_in *i)
175 const struct fmt_number_style *style = fmt_get_style (i->format);
179 bool explicit_decimals = false;
183 assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
185 /* Trim spaces and check for missing value representation. */
186 if (trim_spaces_and_check_missing (i))
189 ds_init_empty (&tmp);
190 ds_extend (&tmp, 64);
192 /* Prefix character may precede sign. */
193 if (!ss_is_empty (style->prefix))
195 ss_match_char (&i->input, ss_first (style->prefix));
196 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
200 if (ss_match_char (&i->input, '-'))
202 ds_put_char (&tmp, '-');
203 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
207 ss_match_char (&i->input, '+');
208 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
211 /* Prefix character may follow sign. */
212 if (!ss_is_empty (style->prefix))
214 ss_match_char (&i->input, ss_first (style->prefix));
215 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
218 /* Digits before decimal point. */
219 while (c_isdigit (ss_first (i->input)))
221 ds_put_char (&tmp, ss_get_char (&i->input));
222 if (style->grouping != 0)
223 ss_match_char (&i->input, style->grouping);
226 /* Decimal point and following digits. */
227 if (ss_match_char (&i->input, style->decimal))
229 explicit_decimals = true;
230 ds_put_char (&tmp, '.');
231 while (c_isdigit (ss_first (i->input)))
232 ds_put_char (&tmp, ss_get_char (&i->input));
236 if (!ds_is_empty (&tmp)
237 && !ss_is_empty (i->input)
238 && strchr ("eEdD-+", ss_first (i->input)))
240 explicit_decimals = true;
241 ds_put_char (&tmp, 'e');
243 if (strchr ("eEdD", ss_first (i->input)))
245 ss_advance (&i->input, 1);
246 ss_match_char (&i->input, ' ');
249 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
251 if (ss_get_char (&i->input) == '-')
252 ds_put_char (&tmp, '-');
253 ss_match_char (&i->input, ' ');
256 while (c_isdigit (ss_first (i->input)))
257 ds_put_char (&tmp, ss_get_char (&i->input));
260 /* Suffix character. */
261 if (!ss_is_empty (style->suffix))
262 ss_match_char (&i->input, ss_first (style->suffix));
264 if (!ss_is_empty (i->input))
266 if (ds_is_empty (&tmp))
267 data_warning (i, _("Field contents are not numeric."));
269 data_warning (i, _("Number followed by garbage."));
274 /* Let strtod() do the conversion. */
277 i->output->f = strtod (ds_cstr (&tmp), &tail);
280 data_warning (i, _("Invalid numeric syntax."));
285 else if (errno == ERANGE)
287 if (fabs (i->output->f) > 1)
289 data_warning (i, _("Too-large number set to system-missing."));
290 i->output->f = SYSMIS;
294 data_warning (i, _("Too-small number set to zero."));
301 if (!explicit_decimals)
302 apply_implied_decimals (i);
309 /* Parses N format. */
311 parse_N (struct data_in *i)
316 while ((c = ss_get_char (&i->input)) != EOF)
320 data_warning (i, _("All characters in field must be digits."));
323 i->output->f = i->output->f * 10.0 + (c - '0');
326 apply_implied_decimals (i);
330 /* Parses PIBHEX format. */
332 parse_PIBHEX (struct data_in *i)
339 while ((c = ss_get_char (&i->input)) != EOF)
343 data_warning (i, _("Unrecognized character in field."));
346 n = n * 16.0 + hexit_value (c);
353 /* Parses RBHEX format. */
355 parse_RBHEX (struct data_in *i)
360 memset (&d, 0, sizeof d);
361 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
363 int hi = ss_get_char (&i->input);
364 int lo = ss_get_char (&i->input);
367 data_warning (i, _("Field must have even length."));
370 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
372 data_warning (i, _("Field must contain only hex digits."));
375 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
383 /* Digits for Z format. */
384 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
386 /* Returns true if C is a Z format digit, false otherwise. */
390 return c > 0 && strchr (z_digits, c) != NULL;
393 /* Returns the (absolute value of the) value of C as a Z format
396 z_digit_value (int c)
398 assert (is_z_digit (c));
399 return (strchr (z_digits, c) - z_digits) % 10;
402 /* Returns true if Z format digit C represents a negative value,
405 is_negative_z_digit (int c)
407 assert (is_z_digit (c));
408 return (strchr (z_digits, c) - z_digits) >= 20;
411 /* Parses Z format. */
413 parse_Z (struct data_in *i)
419 bool got_dot = false;
420 bool got_final_digit = false;
422 /* Trim spaces and check for missing value representation. */
423 if (trim_spaces_and_check_missing (i))
426 ds_init_empty (&tmp);
427 ds_extend (&tmp, 64);
429 ds_put_char (&tmp, '+');
430 while (!ss_is_empty (i->input))
432 int c = ss_get_char (&i->input);
433 if (c_isdigit (c) && !got_final_digit)
434 ds_put_char (&tmp, c);
435 else if (is_z_digit (c) && !got_final_digit)
437 ds_put_char (&tmp, z_digit_value (c) + '0');
438 if (is_negative_z_digit (c))
439 ds_data (&tmp)[0] = '-';
440 got_final_digit = true;
442 else if (c == '.' && !got_dot)
444 ds_put_char (&tmp, '.');
454 if (!ss_is_empty (i->input))
456 if (ds_length (&tmp) == 1)
457 data_warning (i, _("Field contents are not numeric."));
459 data_warning (i, _("Number followed by garbage."));
464 /* Let strtod() do the conversion. */
467 i->output->f = strtod (ds_cstr (&tmp), NULL);
470 if (fabs (i->output->f) > 1)
472 data_warning (i, _("Too-large number set to system-missing."));
473 i->output->f = SYSMIS;
477 data_warning (i, _("Too-small number set to zero."));
485 apply_implied_decimals (i);
492 /* Parses IB format. */
494 parse_IB (struct data_in *i)
500 bytes = MIN (8, ss_length (i->input));
501 value = integer_get (input_integer_format, ss_data (i->input), bytes);
503 sign_bit = UINT64_C(1) << (8 * bytes - 1);
504 if (!(value & sign_bit))
505 i->output->f = value;
508 /* Sign-extend to full 64 bits. */
509 value -= sign_bit << 1;
510 i->output->f = -(double) -value;
513 apply_implied_decimals (i);
518 /* Parses PIB format. */
520 parse_PIB (struct data_in *i)
522 i->output->f = integer_get (input_integer_format, ss_data (i->input),
523 MIN (8, ss_length (i->input)));
525 apply_implied_decimals (i);
530 /* Consumes the first character of S. Stores its high 4 bits in
531 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
533 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
535 int c = ss_get_char (s);
537 *high_nibble = (c >> 4) & 15;
538 *low_nibble = c & 15;
541 /* Parses P format. */
543 parse_P (struct data_in *i)
545 int high_nibble, low_nibble;
549 while (ss_length (i->input) > 1)
551 get_nibbles (&i->input, &high_nibble, &low_nibble);
552 if (high_nibble > 9 || low_nibble > 9)
554 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
557 get_nibbles (&i->input, &high_nibble, &low_nibble);
560 i->output->f = (10 * i->output->f) + high_nibble;
562 i->output->f = (10 * i->output->f) + low_nibble;
563 else if (low_nibble == 0xb || low_nibble == 0xd)
564 i->output->f = -i->output->f;
566 apply_implied_decimals (i);
571 /* Parses PK format. */
573 parse_PK (struct data_in *i)
576 while (!ss_is_empty (i->input))
578 int high_nibble, low_nibble;
580 get_nibbles (&i->input, &high_nibble, &low_nibble);
581 if (high_nibble > 9 || low_nibble > 9)
583 i->output->f = SYSMIS;
586 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
589 apply_implied_decimals (i);
594 /* Parses RB format. */
596 parse_RB (struct data_in *i)
598 size_t size = float_get_size (input_float_format);
599 if (ss_length (i->input) >= size)
600 float_convert (input_float_format, ss_data (i->input),
601 FLOAT_NATIVE_DOUBLE, &i->output->f);
603 i->output->f = SYSMIS;
608 /* Parses A format. */
610 parse_A (struct data_in *i)
612 buf_copy_rpad (i->output->s, i->width,
613 ss_data (i->input), ss_length (i->input));
617 /* Parses AHEX format. */
619 parse_AHEX (struct data_in *i)
625 int hi = ss_get_char (&i->input);
626 int lo = ss_get_char (&i->input);
631 data_warning (i, _("Field must have even length."));
635 if (!c_isxdigit (hi) || !c_isxdigit (lo))
637 data_warning (i, _("Field must contain only hex digits."));
642 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
645 memset (i->output->s + j, ' ', i->width - j);
650 /* Date & time format components. */
652 /* Sign of a time value. */
655 SIGN_NO_TIME, /* No time yet encountered. */
656 SIGN_POSITIVE, /* Positive time. */
657 SIGN_NEGATIVE /* Negative time. */
660 /* Parses a signed decimal integer from at most the first
661 MAX_DIGITS characters in I, storing the result into *RESULT.
662 Returns true if successful, false if no integer was
665 parse_int (struct data_in *i, long *result, size_t max_digits)
667 struct substring head = ss_head (i->input, max_digits);
668 size_t n = ss_get_long (&head, result);
671 ss_advance (&i->input, n);
676 data_warning (i, _("Syntax error in date field."));
681 /* Parses a date integer between 1 and 31 from I, storing it into
683 Returns true if successful, false if no date was present. */
685 parse_day (struct data_in *i, long *day)
687 if (!parse_int (i, day, SIZE_MAX))
689 if (*day >= 1 && *day <= 31)
692 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
696 /* Parses an integer from the beginning of I.
697 Adds SECONDS_PER_UNIT times the absolute value of the integer
699 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
700 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
701 Returns true if successful, false if no integer was present. */
703 parse_time_units (struct data_in *i, double seconds_per_unit,
704 enum time_sign *time_sign, double *time)
709 if (*time_sign == SIGN_NO_TIME)
711 if (ss_match_char (&i->input, '-'))
712 *time_sign = SIGN_NEGATIVE;
715 ss_match_char (&i->input, '+');
716 *time_sign = SIGN_POSITIVE;
719 if (!parse_int (i, &units, SIZE_MAX))
723 data_warning (i, _("Syntax error in date field."));
726 *time += units * seconds_per_unit;
730 /* Parses a data delimiter from the beginning of I.
731 Returns true if successful, false if no delimiter was
734 parse_date_delimiter (struct data_in *i)
736 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
739 data_warning (i, _("Delimiter expected between fields in date."));
743 /* Parses spaces at the beginning of I. */
745 parse_spaces (struct data_in *i)
747 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
750 static struct substring
751 parse_name_token (struct data_in *i)
753 struct substring token;
754 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
758 /* Reads a name from I and sets *OUTPUT to the value associated
759 with that name. If ALLOW_SUFFIXES is true, then names that
760 begin with one of the names are accepted; otherwise, only
761 exact matches (except for case) are allowed.
762 Returns true if successful, false otherwise. */
764 match_name (struct substring token, const char **names, long *output)
768 for (i = 1; *names != NULL; i++)
769 if (ss_equals_case (ss_cstr (*names++), token))
778 /* Parses a month name or number from the beginning of I,
779 storing the month (in range 1...12) into *MONTH.
780 Returns true if successful, false if no month was present. */
782 parse_month (struct data_in *i, long *month)
784 if (c_isdigit (ss_first (i->input)))
786 if (!parse_int (i, month, SIZE_MAX))
788 if (*month >= 1 && *month <= 12)
793 static const char *english_names[] =
795 "jan", "feb", "mar", "apr", "may", "jun",
796 "jul", "aug", "sep", "oct", "nov", "dec",
800 static const char *roman_names[] =
802 "i", "ii", "iii", "iv", "v", "vi",
803 "vii", "viii", "ix", "x", "xi", "xii",
807 struct substring token = parse_name_token (i);
808 if (match_name (ss_head (token, 3), english_names, month)
809 || match_name (ss_head (token, 4), roman_names, month))
813 data_warning (i, _("Unrecognized month format. Months may be specified "
814 "as Arabic or Roman numerals or as at least 3 letters "
815 "of their English names."));
819 /* Parses a year of at most MAX_DIGITS from the beginning of I,
820 storing a "4-digit" year into *YEAR. */
822 parse_year (struct data_in *i, long *year, size_t max_digits)
824 if (!parse_int (i, year, max_digits))
827 if (*year >= 0 && *year <= 99)
829 int epoch = get_epoch ();
830 int epoch_century = ROUND_DOWN (epoch, 100);
831 int epoch_offset = epoch - epoch_century;
832 if (*year >= epoch_offset)
833 *year += epoch_century;
835 *year += epoch_century + 100;
837 if (*year >= 1582 || *year <= 19999)
840 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
844 /* Returns true if input in I has been exhausted,
847 parse_trailer (struct data_in *i)
849 if (ss_is_empty (i->input))
852 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
853 (int) ss_length (i->input), ss_data (i->input));
857 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
858 Returns true if successful, false on failure. */
860 parse_yday (struct data_in *i, long *yday)
862 struct substring num_s;
865 ss_get_chars (&i->input, 3, &num_s);
866 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
868 data_warning (i, _("Julian day must have exactly three digits."));
871 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
873 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
881 /* Parses a quarter-of-year integer between 1 and 4 from I.
882 Stores the corresponding month into *MONTH.
883 Returns true if successful, false if no quarter was present. */
885 parse_quarter (struct data_in *i, long int *month)
889 if (!parse_int (i, &quarter, SIZE_MAX))
891 if (quarter >= 1 && quarter <= 4)
893 *month = (quarter - 1) * 3 + 1;
897 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
901 /* Parses a week-of-year integer between 1 and 53 from I,
902 Stores the corresponding year-of-day into *YDAY.
903 Returns true if successful, false if no week was present. */
905 parse_week (struct data_in *i, long int *yday)
909 if (!parse_int (i, &week, SIZE_MAX))
911 if (week >= 1 && week <= 53)
913 *yday = (week - 1) * 7 + 1;
917 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
921 /* Parses a time delimiter from the beginning of I.
922 Returns true if successful, false if no delimiter was
925 parse_time_delimiter (struct data_in *i)
927 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
930 data_warning (i, _("Delimiter expected between fields in time."));
934 /* Parses minutes and optional seconds from the beginning of I.
935 The time is converted into seconds, which are added to
937 Returns true if successful, false if an error was found. */
939 parse_minute_second (struct data_in *i, double *time)
946 if (!parse_int (i, &minute, SIZE_MAX))
948 if (minute < 0 || minute > 59)
950 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
953 *time += 60. * minute;
955 /* Check for seconds. */
956 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
957 || !c_isdigit (ss_first (i->input)))
962 while (c_isdigit (ss_first (i->input)))
963 *cp++ = ss_get_char (&i->input);
964 if (ss_match_char (&i->input, fmt_decimal_char (FMT_F)))
966 while (c_isdigit (ss_first (i->input)))
967 *cp++ = ss_get_char (&i->input);
970 *time += strtod (buf, NULL);
975 /* Parses a weekday name from the beginning of I,
976 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
977 Returns true if successful, false if an error was found. */
979 parse_weekday (struct data_in *i, long *weekday)
981 static const char *weekday_names[] =
983 "su", "mo", "tu", "we", "th", "fr", "sa",
987 struct substring token = parse_name_token (i);
988 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
990 data_warning (i, _("Unrecognized weekday name. At least the first two "
991 "letters of an English weekday name must be "
996 /* Date & time formats. */
998 /* Helper function for passing to
999 calendar_gregorian_to_offset. */
1001 calendar_error (void *i_, const char *format, ...)
1003 struct data_in *i = i_;
1006 va_start (args, format);
1007 vdata_warning (i, format, args);
1011 /* Parses WKDAY format. */
1013 parse_WKDAY (struct data_in *i)
1017 if (trim_spaces_and_check_missing (i))
1020 if (!parse_weekday (i, &weekday)
1021 || !parse_trailer (i))
1024 i->output->f = weekday;
1028 /* Parses MONTH format. */
1030 parse_MONTH (struct data_in *i)
1034 if (trim_spaces_and_check_missing (i))
1037 if (!parse_month (i, &month)
1038 || !parse_trailer (i))
1041 i->output->f = month;
1045 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1046 DATETIME, TIME and DTIME formats. */
1048 parse_date (struct data_in *i)
1050 long int year = INT_MIN;
1054 double time = 0, date = 0;
1055 enum time_sign time_sign = SIGN_NO_TIME;
1057 const char *template = fmt_date_template (i->format);
1058 size_t template_width = strlen (template);
1060 if (trim_spaces_and_check_missing (i))
1063 while (*template != '\0')
1065 unsigned char ch = *template;
1069 while (template[count] == ch)
1077 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1080 ok = parse_month (i, &month);
1085 if (!c_isalpha (*template))
1086 max_digits = SIZE_MAX;
1089 if (ss_length (i->input) >= template_width + 2)
1094 ok = parse_year (i, &year, max_digits);
1098 ok = parse_quarter (i, &month);
1101 ok = parse_week (i, &yday);
1104 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1107 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1110 ok = parse_minute_second (i, &time);
1116 ok = parse_date_delimiter (i);
1119 ok = parse_time_delimiter (i);
1124 assert (count == 1);
1125 if (!ss_match_char (&i->input, c_toupper (ch))
1126 && !ss_match_char (&i->input, c_tolower (ch)))
1128 data_warning (i, _("`%c' expected in date field."), ch);
1136 if (!parse_trailer (i))
1139 if (year != INT_MIN)
1141 double ofs = calendar_gregorian_to_offset (year, month, day,
1145 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1149 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1154 /* Utility functions. */
1156 /* Outputs FORMAT with the given ARGS as a warning for input
1159 vdata_warning (const struct data_in *i, const char *format, va_list args)
1164 ds_init_empty (&text);
1165 ds_put_char (&text, '(');
1166 if (i->first_column != 0)
1168 if (i->first_column == i->last_column)
1169 ds_put_format (&text, _("column %d"), i->first_column);
1171 ds_put_format (&text, _("columns %d-%d"),
1172 i->first_column, i->last_column);
1173 ds_put_cstr (&text, ", ");
1175 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1176 ds_put_vformat (&text, format, args);
1178 m.category = MSG_DATA;
1179 m.severity = MSG_WARNING;
1180 m.text = ds_cstr (&text);
1185 /* Outputs FORMAT with the given ARGS as a warning for input
1188 data_warning (const struct data_in *i, const char *format, ...)
1192 va_start (args, format);
1193 vdata_warning (i, format, args);
1197 /* Apply implied decimal places to output. */
1199 apply_implied_decimals (struct data_in *i)
1201 if (i->implied_decimals > 0)
1202 i->output->f /= pow (10., i->implied_decimals);
1205 /* Sets the default result for I.
1206 For a numeric format, this is the value set on SET BLANKS
1207 (typically system-missing); for a string format, it is all
1210 default_result (struct data_in *i)
1212 if (fmt_is_string (i->format))
1213 memset (i->output->s, ' ', i->width);
1215 i->output->f = get_blanks ();
1218 /* Trims leading and trailing spaces from I.
1219 If the result is empty, or a single period character, then
1220 sets the default result and returns true; otherwise, returns
1223 trim_spaces_and_check_missing (struct data_in *i)
1225 ss_trim (&i->input, ss_cstr (" "));
1226 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1234 /* Returns the integer value of hex digit C. */
1238 const char s[] = "0123456789abcdef";
1239 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1241 assert (cp != NULL);