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>
49 #define _(msgid) gettext (msgid)
51 /* Information about parsing one data field. */
54 struct substring input; /* Source. */
55 enum fmt_type format; /* Input format. */
56 int implied_decimals; /* Number of implied decimal places. */
58 union value *output; /* Destination. */
59 int width; /* Output width. */
61 int first_column; /* First column of field; 0 if inapplicable. */
62 int last_column; /* Last column. */
65 /* Integer format used for IB and PIB input. */
66 static enum integer_format input_integer_format = INTEGER_NATIVE;
68 /* Floating-point format used for RB and RBHEX input. */
69 static enum float_format input_float_format = FLOAT_NATIVE_DOUBLE;
71 typedef bool data_in_parser_func (struct data_in *);
72 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
73 static data_in_parser_func parse_##METHOD;
76 static void vdata_warning (const struct data_in *, const char *, va_list)
78 static void data_warning (const struct data_in *, const char *, ...)
81 static void apply_implied_decimals (struct data_in *);
82 static void default_result (struct data_in *);
83 static bool trim_spaces_and_check_missing (struct data_in *);
85 static int hexit_value (int c);
87 /* Parses the characters in INPUT according to FORMAT. Stores
88 the parsed representation in OUTPUT, which has the given WIDTH
89 (0 for 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 is nonzero, then it should be the 1-based
96 column number of the first character in INPUT, used in error
99 data_in (struct substring input,
100 enum fmt_type format, int implied_decimals,
101 int first_column, union value *output, int width)
103 static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
105 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
106 #include "format.def"
112 assert ((width != 0) == fmt_is_string (format));
116 i.implied_decimals = implied_decimals;
121 i.first_column = first_column;
122 i.last_column = first_column + ss_length (input) - 1;
124 if (!ss_is_empty (i.input))
126 ok = handlers[i.format] (&i);
139 /* Returns the integer format used for IB and PIB input. */
141 data_in_get_integer_format (void)
143 return input_integer_format;
146 /* Sets the integer format used for IB and PIB input to
149 data_in_set_integer_format (enum integer_format format)
151 input_integer_format = format;
154 /* Returns the floating-point format used for RB and RBHEX
157 data_in_get_float_format (void)
159 return input_float_format;
162 /* Sets the floating-point format used for RB and RBHEX input to
165 data_in_set_float_format (enum float_format format)
167 input_float_format = format;
170 /* Format parsers. */
172 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
174 parse_number (struct data_in *i)
176 const struct fmt_number_style *style = fmt_get_style (i->format);
180 bool explicit_decimals = false;
184 assert (fmt_get_category (i->format) != FMT_CAT_CUSTOM);
186 /* Trim spaces and check for missing value representation. */
187 if (trim_spaces_and_check_missing (i))
190 ds_init_empty (&tmp);
191 ds_extend (&tmp, 64);
193 /* Prefix character may precede sign. */
194 if (!ss_is_empty (style->prefix))
196 ss_match_char (&i->input, ss_first (style->prefix));
197 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
201 if (ss_match_char (&i->input, '-'))
203 ds_put_char (&tmp, '-');
204 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
208 ss_match_char (&i->input, '+');
209 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
212 /* Prefix character may follow sign. */
213 if (!ss_is_empty (style->prefix))
215 ss_match_char (&i->input, ss_first (style->prefix));
216 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
219 /* Digits before decimal point. */
220 while (c_isdigit (ss_first (i->input)))
222 ds_put_char (&tmp, ss_get_char (&i->input));
223 if (style->grouping != 0)
224 ss_match_char (&i->input, style->grouping);
227 /* Decimal point and following digits. */
228 if (ss_match_char (&i->input, style->decimal))
230 explicit_decimals = true;
231 ds_put_char (&tmp, '.');
232 while (c_isdigit (ss_first (i->input)))
233 ds_put_char (&tmp, ss_get_char (&i->input));
237 if (!ds_is_empty (&tmp)
238 && !ss_is_empty (i->input)
239 && strchr ("eEdD-+", ss_first (i->input)))
241 explicit_decimals = true;
242 ds_put_char (&tmp, 'e');
244 if (strchr ("eEdD", ss_first (i->input)))
246 ss_advance (&i->input, 1);
247 ss_match_char (&i->input, ' ');
250 if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
252 if (ss_get_char (&i->input) == '-')
253 ds_put_char (&tmp, '-');
254 ss_match_char (&i->input, ' ');
257 while (c_isdigit (ss_first (i->input)))
258 ds_put_char (&tmp, ss_get_char (&i->input));
261 /* Suffix character. */
262 if (!ss_is_empty (style->suffix))
263 ss_match_char (&i->input, ss_first (style->suffix));
265 if (!ss_is_empty (i->input))
267 if (ds_is_empty (&tmp))
268 data_warning (i, _("Field contents are not numeric."));
270 data_warning (i, _("Number followed by garbage."));
275 /* Let strtod() do the conversion. */
278 i->output->f = strtod (ds_cstr (&tmp), &tail);
281 data_warning (i, _("Invalid numeric syntax."));
286 else if (errno == ERANGE)
288 if (fabs (i->output->f) > 1)
290 data_warning (i, _("Too-large number set to system-missing."));
291 i->output->f = SYSMIS;
295 data_warning (i, _("Too-small number set to zero."));
302 if (!explicit_decimals)
303 apply_implied_decimals (i);
310 /* Parses N format. */
312 parse_N (struct data_in *i)
317 while ((c = ss_get_char (&i->input)) != EOF)
321 data_warning (i, _("All characters in field must be digits."));
324 i->output->f = i->output->f * 10.0 + (c - '0');
327 apply_implied_decimals (i);
331 /* Parses PIBHEX format. */
333 parse_PIBHEX (struct data_in *i)
340 while ((c = ss_get_char (&i->input)) != EOF)
344 data_warning (i, _("Unrecognized character in field."));
347 n = n * 16.0 + hexit_value (c);
354 /* Parses RBHEX format. */
356 parse_RBHEX (struct data_in *i)
361 memset (&d, 0, sizeof d);
362 for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
364 int hi = ss_get_char (&i->input);
365 int lo = ss_get_char (&i->input);
368 data_warning (i, _("Field must have even length."));
371 else if (!c_isxdigit (hi) || !c_isxdigit (lo))
373 data_warning (i, _("Field must contain only hex digits."));
376 ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
384 /* Digits for Z format. */
385 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
387 /* Returns true if C is a Z format digit, false otherwise. */
391 return c > 0 && strchr (z_digits, c) != NULL;
394 /* Returns the (absolute value of the) value of C as a Z format
397 z_digit_value (int c)
399 assert (is_z_digit (c));
400 return (strchr (z_digits, c) - z_digits) % 10;
403 /* Returns true if Z format digit C represents a negative value,
406 is_negative_z_digit (int c)
408 assert (is_z_digit (c));
409 return (strchr (z_digits, c) - z_digits) >= 20;
412 /* Parses Z format. */
414 parse_Z (struct data_in *i)
420 bool got_dot = false;
421 bool got_final_digit = false;
423 /* Trim spaces and check for missing value representation. */
424 if (trim_spaces_and_check_missing (i))
427 ds_init_empty (&tmp);
428 ds_extend (&tmp, 64);
430 ds_put_char (&tmp, '+');
431 while (!ss_is_empty (i->input))
433 int c = ss_get_char (&i->input);
434 if (c_isdigit (c) && !got_final_digit)
435 ds_put_char (&tmp, c);
436 else if (is_z_digit (c) && !got_final_digit)
438 ds_put_char (&tmp, z_digit_value (c) + '0');
439 if (is_negative_z_digit (c))
440 ds_data (&tmp)[0] = '-';
441 got_final_digit = true;
443 else if (c == '.' && !got_dot)
445 ds_put_char (&tmp, '.');
455 if (!ss_is_empty (i->input))
457 if (ds_length (&tmp) == 1)
458 data_warning (i, _("Field contents are not numeric."));
460 data_warning (i, _("Number followed by garbage."));
465 /* Let strtod() do the conversion. */
468 i->output->f = strtod (ds_cstr (&tmp), NULL);
471 if (fabs (i->output->f) > 1)
473 data_warning (i, _("Too-large number set to system-missing."));
474 i->output->f = SYSMIS;
478 data_warning (i, _("Too-small number set to zero."));
486 apply_implied_decimals (i);
493 /* Parses IB format. */
495 parse_IB (struct data_in *i)
501 bytes = MIN (8, ss_length (i->input));
502 value = integer_get (input_integer_format, ss_data (i->input), bytes);
504 sign_bit = UINT64_C(1) << (8 * bytes - 1);
505 if (!(value & sign_bit))
506 i->output->f = value;
509 /* Sign-extend to full 64 bits. */
510 value -= sign_bit << 1;
511 i->output->f = -(double) -value;
514 apply_implied_decimals (i);
519 /* Parses PIB format. */
521 parse_PIB (struct data_in *i)
523 i->output->f = integer_get (input_integer_format, ss_data (i->input),
524 MIN (8, ss_length (i->input)));
526 apply_implied_decimals (i);
531 /* Consumes the first character of S. Stores its high 4 bits in
532 HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
534 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
536 int c = ss_get_char (s);
538 *high_nibble = (c >> 4) & 15;
539 *low_nibble = c & 15;
542 /* Parses P format. */
544 parse_P (struct data_in *i)
546 int high_nibble, low_nibble;
550 while (ss_length (i->input) > 1)
552 get_nibbles (&i->input, &high_nibble, &low_nibble);
553 if (high_nibble > 9 || low_nibble > 9)
555 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
558 get_nibbles (&i->input, &high_nibble, &low_nibble);
561 i->output->f = (10 * i->output->f) + high_nibble;
563 i->output->f = (10 * i->output->f) + low_nibble;
564 else if (low_nibble == 0xb || low_nibble == 0xd)
565 i->output->f = -i->output->f;
567 apply_implied_decimals (i);
572 /* Parses PK format. */
574 parse_PK (struct data_in *i)
577 while (!ss_is_empty (i->input))
579 int high_nibble, low_nibble;
581 get_nibbles (&i->input, &high_nibble, &low_nibble);
582 if (high_nibble > 9 || low_nibble > 9)
584 i->output->f = SYSMIS;
587 i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
590 apply_implied_decimals (i);
595 /* Parses RB format. */
597 parse_RB (struct data_in *i)
599 size_t size = float_get_size (input_float_format);
600 if (ss_length (i->input) >= size)
601 float_convert (input_float_format, ss_data (i->input),
602 FLOAT_NATIVE_DOUBLE, &i->output->f);
604 i->output->f = SYSMIS;
609 /* Parses A format. */
611 parse_A (struct data_in *i)
613 buf_copy_rpad (i->output->s, i->width,
614 ss_data (i->input), ss_length (i->input));
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 (!c_isxdigit (hi) || !c_isxdigit (lo))
638 data_warning (i, _("Field must contain only hex digits."));
643 i->output->s[j] = hexit_value (hi) * 16 + hexit_value (lo);
646 memset (i->output->s + j, ' ', i->width - j);
651 /* Date & time format components. */
653 /* Sign of a time value. */
656 SIGN_NO_TIME, /* No time yet encountered. */
657 SIGN_POSITIVE, /* Positive time. */
658 SIGN_NEGATIVE /* Negative time. */
661 /* Parses a signed decimal integer from at most the first
662 MAX_DIGITS characters in I, storing the result into *RESULT.
663 Returns true if successful, false if no integer was
666 parse_int (struct data_in *i, long *result, size_t max_digits)
668 struct substring head = ss_head (i->input, max_digits);
669 size_t n = ss_get_long (&head, result);
672 ss_advance (&i->input, n);
677 data_warning (i, _("Syntax error in date field."));
682 /* Parses a date integer between 1 and 31 from I, storing it into
684 Returns true if successful, false if no date was present. */
686 parse_day (struct data_in *i, long *day)
688 if (!parse_int (i, day, SIZE_MAX))
690 if (*day >= 1 && *day <= 31)
693 data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
697 /* Parses an integer from the beginning of I.
698 Adds SECONDS_PER_UNIT times the absolute value of the integer
700 If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
701 time and sets *TIME_SIGN. Otherwise, does not allow a sign.
702 Returns true if successful, false if no integer was present. */
704 parse_time_units (struct data_in *i, double seconds_per_unit,
705 enum time_sign *time_sign, double *time)
710 if (*time_sign == SIGN_NO_TIME)
712 if (ss_match_char (&i->input, '-'))
713 *time_sign = SIGN_NEGATIVE;
716 ss_match_char (&i->input, '+');
717 *time_sign = SIGN_POSITIVE;
720 if (!parse_int (i, &units, SIZE_MAX))
724 data_warning (i, _("Syntax error in date field."));
727 *time += units * seconds_per_unit;
731 /* Parses a data delimiter from the beginning of I.
732 Returns true if successful, false if no delimiter was
735 parse_date_delimiter (struct data_in *i)
737 if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
740 data_warning (i, _("Delimiter expected between fields in date."));
744 /* Parses spaces at the beginning of I. */
746 parse_spaces (struct data_in *i)
748 ss_ltrim (&i->input, ss_cstr (CC_SPACES));
751 static struct substring
752 parse_name_token (struct data_in *i)
754 struct substring token;
755 ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
759 /* Reads a name from I and sets *OUTPUT to the value associated
760 with that name. If ALLOW_SUFFIXES is true, then names that
761 begin with one of the names are accepted; otherwise, only
762 exact matches (except for case) are allowed.
763 Returns true if successful, false otherwise. */
765 match_name (struct substring token, const char **names, long *output)
769 for (i = 1; *names != NULL; i++)
770 if (ss_equals_case (ss_cstr (*names++), token))
779 /* Parses a month name or number from the beginning of I,
780 storing the month (in range 1...12) into *MONTH.
781 Returns true if successful, false if no month was present. */
783 parse_month (struct data_in *i, long *month)
785 if (c_isdigit (ss_first (i->input)))
787 if (!parse_int (i, month, SIZE_MAX))
789 if (*month >= 1 && *month <= 12)
794 static const char *english_names[] =
796 "jan", "feb", "mar", "apr", "may", "jun",
797 "jul", "aug", "sep", "oct", "nov", "dec",
801 static const char *roman_names[] =
803 "i", "ii", "iii", "iv", "v", "vi",
804 "vii", "viii", "ix", "x", "xi", "xii",
808 struct substring token = parse_name_token (i);
809 if (match_name (ss_head (token, 3), english_names, month)
810 || match_name (ss_head (token, 4), roman_names, month))
814 data_warning (i, _("Unrecognized month format. Months may be specified "
815 "as Arabic or Roman numerals or as at least 3 letters "
816 "of their English names."));
820 /* Parses a year of at most MAX_DIGITS from the beginning of I,
821 storing a "4-digit" year into *YEAR. */
823 parse_year (struct data_in *i, long *year, size_t max_digits)
825 if (!parse_int (i, year, max_digits))
828 if (*year >= 0 && *year <= 99)
830 int epoch = get_epoch ();
831 int epoch_century = ROUND_DOWN (epoch, 100);
832 int epoch_offset = epoch - epoch_century;
833 if (*year >= epoch_offset)
834 *year += epoch_century;
836 *year += epoch_century + 100;
838 if (*year >= 1582 || *year <= 19999)
841 data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
845 /* Returns true if input in I has been exhausted,
848 parse_trailer (struct data_in *i)
850 if (ss_is_empty (i->input))
853 data_warning (i, _("Trailing garbage \"%.*s\" following date."),
854 (int) ss_length (i->input), ss_data (i->input));
858 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
859 Returns true if successful, false on failure. */
861 parse_yday (struct data_in *i, long *yday)
863 struct substring num_s;
866 ss_get_chars (&i->input, 3, &num_s);
867 if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
869 data_warning (i, _("Julian day must have exactly three digits."));
872 else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
874 data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
882 /* Parses a quarter-of-year integer between 1 and 4 from I.
883 Stores the corresponding month into *MONTH.
884 Returns true if successful, false if no quarter was present. */
886 parse_quarter (struct data_in *i, long int *month)
890 if (!parse_int (i, &quarter, SIZE_MAX))
892 if (quarter >= 1 && quarter <= 4)
894 *month = (quarter - 1) * 3 + 1;
898 data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
902 /* Parses a week-of-year integer between 1 and 53 from I,
903 Stores the corresponding year-of-day into *YDAY.
904 Returns true if successful, false if no week was present. */
906 parse_week (struct data_in *i, long int *yday)
910 if (!parse_int (i, &week, SIZE_MAX))
912 if (week >= 1 && week <= 53)
914 *yday = (week - 1) * 7 + 1;
918 data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
922 /* Parses a time delimiter from the beginning of I.
923 Returns true if successful, false if no delimiter was
926 parse_time_delimiter (struct data_in *i)
928 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
931 data_warning (i, _("Delimiter expected between fields in time."));
935 /* Parses minutes and optional seconds from the beginning of I.
936 The time is converted into seconds, which are added to
938 Returns true if successful, false if an error was found. */
940 parse_minute_second (struct data_in *i, double *time)
947 if (!parse_int (i, &minute, SIZE_MAX))
949 if (minute < 0 || minute > 59)
951 data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
954 *time += 60. * minute;
956 /* Check for seconds. */
957 if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
958 || !c_isdigit (ss_first (i->input)))
963 while (c_isdigit (ss_first (i->input)))
964 *cp++ = ss_get_char (&i->input);
965 if (ss_match_char (&i->input, fmt_decimal_char (FMT_F)))
967 while (c_isdigit (ss_first (i->input)))
968 *cp++ = ss_get_char (&i->input);
971 *time += strtod (buf, NULL);
976 /* Parses a weekday name from the beginning of I,
977 storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
978 Returns true if successful, false if an error was found. */
980 parse_weekday (struct data_in *i, long *weekday)
982 static const char *weekday_names[] =
984 "su", "mo", "tu", "we", "th", "fr", "sa",
988 struct substring token = parse_name_token (i);
989 bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
991 data_warning (i, _("Unrecognized weekday name. At least the first two "
992 "letters of an English weekday name must be "
997 /* Date & time formats. */
999 /* Helper function for passing to
1000 calendar_gregorian_to_offset. */
1002 calendar_error (void *i_, const char *format, ...)
1004 struct data_in *i = i_;
1007 va_start (args, format);
1008 vdata_warning (i, format, args);
1012 /* Parses WKDAY format. */
1014 parse_WKDAY (struct data_in *i)
1018 if (trim_spaces_and_check_missing (i))
1021 if (!parse_weekday (i, &weekday)
1022 || !parse_trailer (i))
1025 i->output->f = weekday;
1029 /* Parses MONTH format. */
1031 parse_MONTH (struct data_in *i)
1035 if (trim_spaces_and_check_missing (i))
1038 if (!parse_month (i, &month)
1039 || !parse_trailer (i))
1042 i->output->f = month;
1046 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1047 DATETIME, TIME and DTIME formats. */
1049 parse_date (struct data_in *i)
1051 long int year = INT_MIN;
1055 double time = 0, date = 0;
1056 enum time_sign time_sign = SIGN_NO_TIME;
1058 const char *template = fmt_date_template (i->format);
1059 size_t template_width = strlen (template);
1061 if (trim_spaces_and_check_missing (i))
1064 while (*template != '\0')
1066 unsigned char ch = *template;
1070 while (template[count] == ch)
1078 ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1081 ok = parse_month (i, &month);
1086 if (!c_isalpha (*template))
1087 max_digits = SIZE_MAX;
1090 if (ss_length (i->input) >= template_width + 2)
1095 ok = parse_year (i, &year, max_digits);
1099 ok = parse_quarter (i, &month);
1102 ok = parse_week (i, &yday);
1105 ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1108 ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1111 ok = parse_minute_second (i, &time);
1117 ok = parse_date_delimiter (i);
1120 ok = parse_time_delimiter (i);
1125 assert (count == 1);
1126 if (!ss_match_char (&i->input, c_toupper (ch))
1127 && !ss_match_char (&i->input, c_tolower (ch)))
1129 data_warning (i, _("`%c' expected in date field."), ch);
1137 if (!parse_trailer (i))
1140 if (year != INT_MIN)
1142 double ofs = calendar_gregorian_to_offset (year, month, day,
1146 date = (yday - 1 + ofs) * 60. * 60. * 24.;
1150 i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1155 /* Utility functions. */
1157 /* Outputs FORMAT with the given ARGS as a warning for input
1160 vdata_warning (const struct data_in *i, const char *format, va_list args)
1165 ds_init_empty (&text);
1166 ds_put_char (&text, '(');
1167 if (i->first_column != 0)
1169 if (i->first_column == i->last_column)
1170 ds_put_format (&text, _("column %d"), i->first_column);
1172 ds_put_format (&text, _("columns %d-%d"),
1173 i->first_column, i->last_column);
1174 ds_put_cstr (&text, ", ");
1176 ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1177 ds_put_vformat (&text, format, args);
1179 m.category = MSG_DATA;
1180 m.severity = MSG_WARNING;
1181 m.text = ds_cstr (&text);
1186 /* Outputs FORMAT with the given ARGS as a warning for input
1189 data_warning (const struct data_in *i, const char *format, ...)
1193 va_start (args, format);
1194 vdata_warning (i, format, args);
1198 /* Apply implied decimal places to output. */
1200 apply_implied_decimals (struct data_in *i)
1202 if (i->implied_decimals > 0)
1203 i->output->f /= pow (10., i->implied_decimals);
1206 /* Sets the default result for I.
1207 For a numeric format, this is the value set on SET BLANKS
1208 (typically system-missing); for a string format, it is all
1211 default_result (struct data_in *i)
1213 if (fmt_is_string (i->format))
1214 memset (i->output->s, ' ', i->width);
1216 i->output->f = get_blanks ();
1219 /* Trims leading and trailing spaces from I.
1220 If the result is empty, or a single period character, then
1221 sets the default result and returns true; otherwise, returns
1224 trim_spaces_and_check_missing (struct data_in *i)
1226 ss_trim (&i->input, ss_cstr (" "));
1227 if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1235 /* Returns the integer value of hex digit C. */
1239 const char s[] = "0123456789abcdef";
1240 const char *cp = strchr (s, c_tolower ((unsigned char) c));
1242 assert (cp != NULL);