eda6d1258f729b8d05352fb71fe1a24a0cdb1ef6
[pspp-builds.git] / src / data / data-in.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include "data-in.h"
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <math.h>
24 #include <stdarg.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdbool.h>
30 #include <limits.h>
31
32 #include "calendar.h"
33 #include "identifier.h"
34 #include "settings.h"
35 #include "value.h"
36 #include "format.h"
37
38 #include <libpspp/assertion.h>
39 #include <libpspp/legacy-encoding.h>
40 #include <libpspp/compiler.h>
41 #include <libpspp/integer-format.h>
42 #include <libpspp/message.h>
43 #include <libpspp/misc.h>
44 #include <libpspp/str.h>
45 #include "c-ctype.h"
46 #include "c-strtod.h"
47 #include "minmax.h"
48 #include "xalloc.h"
49
50 #include "gettext.h"
51 #define _(msgid) gettext (msgid)
52 \f
53 /* Information about parsing one data field. */
54 struct data_in
55   {
56     enum legacy_encoding encoding;/* Encoding of source. */
57     struct substring input;     /* Source. */
58     enum fmt_type format;       /* Input format. */
59     int implied_decimals;       /* Number of implied decimal places. */
60
61     union value *output;        /* Destination. */
62     int width;                  /* Output width. */
63
64     int first_column;           /* First column of field; 0 if inapplicable. */
65     int last_column;            /* Last column. */
66   };
67
68
69
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;
73 #include "format.def"
74
75 static void vdata_warning (const struct data_in *, const char *, va_list)
76      PRINTF_FORMAT (2, 0);
77 static void data_warning (const struct data_in *, const char *, ...)
78      PRINTF_FORMAT (2, 3);
79
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 *);
83
84 static int hexit_value (int c);
85 \f
86 /* Parses the characters in INPUT, which are encoded in the given
87    ENCODING, according to FORMAT.  Stores the parsed
88    representation in OUTPUT, which the caller must have
89    initialized with the given WIDTH (0 for a numeric field,
90    otherwise the string width).
91
92    If no decimal point is included in a numeric format, then
93    IMPLIED_DECIMALS decimal places are implied.  Specify 0 if no
94    decimal places should be implied.
95
96    If FIRST_COLUMN and LAST_COLUMN are nonzero, then they should
97    be the 1-based column number of the first and
98    one-past-the-last-character in INPUT, for use in error
99    messages.  (LAST_COLUMN cannot always be calculated from
100    FIRST_COLUMN plus the length of the input because of the
101    possibility of escaped quotes in strings, etc.) */
102 bool
103 data_in (struct substring input, enum legacy_encoding encoding,
104          enum fmt_type format, int implied_decimals,
105          int first_column, int last_column, union value *output, int width)
106 {
107   static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
108     {
109 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) parse_##METHOD,
110 #include "format.def"
111     };
112
113   struct data_in i;
114   void *copy = NULL;
115   bool ok;
116
117   assert ((width != 0) == fmt_is_string (format));
118
119   if (encoding == LEGACY_NATIVE
120       || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
121     {
122       i.input = input;
123       i.encoding = encoding;
124     }
125   else
126     {
127       ss_alloc_uninit (&i.input, ss_length (input));
128       legacy_recode (encoding, ss_data (input), LEGACY_NATIVE,
129                      ss_data (i.input), ss_length (input));
130       i.encoding = LEGACY_NATIVE;
131       copy = ss_data (i.input);
132     }
133   i.format = format;
134   i.implied_decimals = implied_decimals;
135
136   i.output = output;
137   i.width = width;
138
139   i.first_column = first_column;
140   i.last_column = last_column;
141
142   if (!ss_is_empty (i.input))
143     {
144       ok = handlers[i.format] (&i);
145       if (!ok)
146         default_result (&i);
147     }
148   else
149     {
150       default_result (&i);
151       ok = true;
152     }
153
154   if (copy)
155     free (copy);
156
157   return ok;
158 }
159
160 \f
161 /* Format parsers. */
162
163 /* Parses F, COMMA, DOT, DOLLAR, PCT, and E input formats. */
164 static bool
165 parse_number (struct data_in *i)
166 {
167   const struct fmt_number_style *style =
168     settings_get_style (i->format);
169
170   struct string tmp;
171
172   bool explicit_decimals = false;
173   int save_errno;
174   char *tail;
175
176   if  (fmt_get_category (i->format) == FMT_CAT_CUSTOM)
177     {
178       style = settings_get_style (FMT_F);
179     }
180
181   /* Trim spaces and check for missing value representation. */
182   if (trim_spaces_and_check_missing (i))
183     return true;
184
185   ds_init_empty (&tmp);
186   ds_extend (&tmp, 64);
187
188   /* Prefix character may precede sign. */
189   if (!ss_is_empty (style->prefix))
190     {
191       ss_match_char (&i->input, ss_first (style->prefix));
192       ss_ltrim (&i->input, ss_cstr (CC_SPACES));
193     }
194
195   /* Sign. */
196   if (ss_match_char (&i->input, '-'))
197     {
198       ds_put_char (&tmp, '-');
199       ss_ltrim (&i->input, ss_cstr (CC_SPACES));
200     }
201   else
202     {
203       ss_match_char (&i->input, '+');
204       ss_ltrim (&i->input, ss_cstr (CC_SPACES));
205     }
206
207   /* Prefix character may follow sign. */
208   if (!ss_is_empty (style->prefix))
209     {
210       ss_match_char (&i->input, ss_first (style->prefix));
211       ss_ltrim (&i->input, ss_cstr (CC_SPACES));
212     }
213
214   /* Digits before decimal point. */
215   while (c_isdigit (ss_first (i->input)))
216     {
217       ds_put_char (&tmp, ss_get_char (&i->input));
218       if (style->grouping != 0)
219         ss_match_char (&i->input, style->grouping);
220     }
221
222   /* Decimal point and following digits. */
223   if (ss_match_char (&i->input, style->decimal))
224     {
225       explicit_decimals = true;
226       ds_put_char (&tmp, '.');
227       while (c_isdigit (ss_first (i->input)))
228         ds_put_char (&tmp, ss_get_char (&i->input));
229     }
230
231   /* Exponent. */
232   if (!ds_is_empty (&tmp)
233       && !ss_is_empty (i->input)
234       && strchr ("eEdD-+", ss_first (i->input)))
235     {
236       explicit_decimals = true;
237       ds_put_char (&tmp, 'e');
238
239       if (strchr ("eEdD", ss_first (i->input)))
240         {
241           ss_advance (&i->input, 1);
242           ss_match_char (&i->input, ' ');
243         }
244
245       if (ss_first (i->input) == '-' || ss_first (i->input) == '+')
246         {
247           if (ss_get_char (&i->input) == '-')
248             ds_put_char (&tmp, '-');
249           ss_match_char (&i->input, ' ');
250         }
251
252       while (c_isdigit (ss_first (i->input)))
253         ds_put_char (&tmp, ss_get_char (&i->input));
254     }
255
256   /* Suffix character. */
257   if (!ss_is_empty (style->suffix))
258     ss_match_char (&i->input, ss_first (style->suffix));
259
260   if (!ss_is_empty (i->input))
261     {
262       if (ds_is_empty (&tmp))
263         data_warning (i, _("Field contents are not numeric."));
264       else
265         data_warning (i, _("Number followed by garbage."));
266       ds_destroy (&tmp);
267       return false;
268     }
269
270   /* Let c_strtod() do the conversion. */
271   save_errno = errno;
272   errno = 0;
273   i->output->f = c_strtod (ds_cstr (&tmp), &tail);
274   if (*tail != '\0')
275     {
276       data_warning (i, _("Invalid numeric syntax."));
277       errno = save_errno;
278       ds_destroy (&tmp);
279       return false;
280     }
281   else if (errno == ERANGE)
282     {
283       if (fabs (i->output->f) > 1)
284         {
285           data_warning (i, _("Too-large number set to system-missing."));
286           i->output->f = SYSMIS;
287         }
288       else
289         {
290           data_warning (i, _("Too-small number set to zero."));
291           i->output->f = 0.0;
292         }
293     }
294   else
295     {
296       errno = save_errno;
297       if (!explicit_decimals)
298         apply_implied_decimals (i);
299     }
300
301   ds_destroy (&tmp);
302   return true;
303 }
304
305 /* Parses N format. */
306 static bool
307 parse_N (struct data_in *i)
308 {
309   int c;
310
311   i->output->f = 0;
312   while ((c = ss_get_char (&i->input)) != EOF)
313     {
314       if (!c_isdigit (c))
315         {
316           data_warning (i, _("All characters in field must be digits."));
317           return false;
318         }
319       i->output->f = i->output->f * 10.0 + (c - '0');
320     }
321
322   apply_implied_decimals (i);
323   return true;
324 }
325
326 /* Parses PIBHEX format. */
327 static bool
328 parse_PIBHEX (struct data_in *i)
329 {
330   double n;
331   int c;
332
333   n = 0.0;
334
335   while ((c = ss_get_char (&i->input)) != EOF)
336     {
337       if (!c_isxdigit (c))
338         {
339           data_warning (i, _("Unrecognized character in field."));
340           return false;
341         }
342       n = n * 16.0 + hexit_value (c);
343     }
344
345   i->output->f = n;
346   return true;
347 }
348
349 /* Parses RBHEX format. */
350 static bool
351 parse_RBHEX (struct data_in *i)
352 {
353   double d;
354   size_t j;
355
356   memset (&d, 0, sizeof d);
357   for (j = 0; !ss_is_empty (i->input) && j < sizeof d; j++)
358     {
359       int hi = ss_get_char (&i->input);
360       int lo = ss_get_char (&i->input);
361       if (lo == EOF)
362         {
363           data_warning (i, _("Field must have even length."));
364           return false;
365         }
366       else if (!c_isxdigit (hi) || !c_isxdigit (lo))
367         {
368           data_warning (i, _("Field must contain only hex digits."));
369           return false;
370         }
371       ((unsigned char *) &d)[j] = 16 * hexit_value (hi) + hexit_value (lo);
372     }
373
374   i->output->f = d;
375
376   return true;
377 }
378
379 /* Digits for Z format. */
380 static const char z_digits[] = "0123456789{ABCDEFGHI}JKLMNOPQR";
381
382 /* Returns true if C is a Z format digit, false otherwise. */
383 static bool
384 is_z_digit (int c)
385 {
386   return c > 0 && strchr (z_digits, c) != NULL;
387 }
388
389 /* Returns the (absolute value of the) value of C as a Z format
390    digit. */
391 static int
392 z_digit_value (int c)
393 {
394   assert (is_z_digit (c));
395   return (strchr (z_digits, c) - z_digits) % 10;
396 }
397
398 /* Returns true if Z format digit C represents a negative value,
399    false otherwise. */
400 static bool
401 is_negative_z_digit (int c)
402 {
403   assert (is_z_digit (c));
404   return (strchr (z_digits, c) - z_digits) >= 20;
405 }
406
407 /* Parses Z format. */
408 static bool
409 parse_Z (struct data_in *i)
410 {
411   struct string tmp;
412
413   int save_errno;
414
415   bool got_dot = false;
416   bool got_final_digit = false;
417
418   /* Trim spaces and check for missing value representation. */
419   if (trim_spaces_and_check_missing (i))
420     return true;
421
422   ds_init_empty (&tmp);
423   ds_extend (&tmp, 64);
424
425   ds_put_char (&tmp, '+');
426   while (!ss_is_empty (i->input))
427     {
428       int c = ss_get_char (&i->input);
429       if (c_isdigit (c) && !got_final_digit)
430         ds_put_char (&tmp, c);
431       else if (is_z_digit (c) && !got_final_digit)
432         {
433           ds_put_char (&tmp, z_digit_value (c) + '0');
434           if (is_negative_z_digit (c))
435             ds_data (&tmp)[0] = '-';
436           got_final_digit = true;
437         }
438       else if (c == '.' && !got_dot)
439         {
440           ds_put_char (&tmp, '.');
441           got_dot = true;
442         }
443       else
444         {
445           ds_destroy (&tmp);
446           return false;
447         }
448     }
449
450   if (!ss_is_empty (i->input))
451     {
452       if (ds_length (&tmp) == 1)
453         data_warning (i, _("Field contents are not numeric."));
454       else
455         data_warning (i, _("Number followed by garbage."));
456       ds_destroy (&tmp);
457       return false;
458     }
459
460   /* Let c_strtod() do the conversion. */
461   save_errno = errno;
462   errno = 0;
463   i->output->f = c_strtod (ds_cstr (&tmp), NULL);
464   if (errno == ERANGE)
465     {
466       if (fabs (i->output->f) > 1)
467         {
468           data_warning (i, _("Too-large number set to system-missing."));
469           i->output->f = SYSMIS;
470         }
471       else
472         {
473           data_warning (i, _("Too-small number set to zero."));
474           i->output->f = 0.0;
475         }
476     }
477   else
478     {
479       errno = save_errno;
480       if (!got_dot)
481         apply_implied_decimals (i);
482     }
483
484   ds_destroy (&tmp);
485   return true;
486 }
487
488 /* Parses IB format. */
489 static bool
490 parse_IB (struct data_in *i)
491 {
492   size_t bytes;
493   uint64_t value;
494   uint64_t sign_bit;
495
496   bytes = MIN (8, ss_length (i->input));
497   value = integer_get (settings_get_input_integer_format (), ss_data (i->input), bytes);
498
499   sign_bit = UINT64_C(1) << (8 * bytes - 1);
500   if (!(value & sign_bit))
501     i->output->f = value;
502   else
503     {
504       /* Sign-extend to full 64 bits. */
505       value -= sign_bit << 1;
506       i->output->f = -(double) -value;
507     }
508
509   apply_implied_decimals (i);
510
511   return true;
512 }
513
514 /* Parses PIB format. */
515 static bool
516 parse_PIB (struct data_in *i)
517 {
518   i->output->f = integer_get (settings_get_input_integer_format (), ss_data (i->input),
519                               MIN (8, ss_length (i->input)));
520
521   apply_implied_decimals (i);
522
523   return true;
524 }
525
526 /* Consumes the first character of S.  Stores its high 4 bits in
527    HIGH_NIBBLE and its low 4 bits in LOW_NIBBLE. */
528 static void
529 get_nibbles (struct substring *s, int *high_nibble, int *low_nibble)
530 {
531   int c = ss_get_char (s);
532   assert (c != EOF);
533   *high_nibble = (c >> 4) & 15;
534   *low_nibble = c & 15;
535 }
536
537 /* Parses P format. */
538 static bool
539 parse_P (struct data_in *i)
540 {
541   int high_nibble, low_nibble;
542
543   i->output->f = 0.0;
544
545   while (ss_length (i->input) > 1)
546     {
547       get_nibbles (&i->input, &high_nibble, &low_nibble);
548       if (high_nibble > 9 || low_nibble > 9)
549         return false;
550       i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
551     }
552
553   get_nibbles (&i->input, &high_nibble, &low_nibble);
554   if (high_nibble > 9)
555     return false;
556   i->output->f = (10 * i->output->f) + high_nibble;
557   if (low_nibble < 10)
558     i->output->f = (10 * i->output->f) + low_nibble;
559   else if (low_nibble == 0xb || low_nibble == 0xd)
560     i->output->f = -i->output->f;
561
562   apply_implied_decimals (i);
563
564   return true;
565 }
566
567 /* Parses PK format. */
568 static bool
569 parse_PK (struct data_in *i)
570 {
571   i->output->f = 0.0;
572   while (!ss_is_empty (i->input))
573     {
574       int high_nibble, low_nibble;
575
576       get_nibbles (&i->input, &high_nibble, &low_nibble);
577       if (high_nibble > 9 || low_nibble > 9)
578         {
579           i->output->f = SYSMIS;
580           return true;
581         }
582       i->output->f = (100 * i->output->f) + (10 * high_nibble) + low_nibble;
583     }
584
585   apply_implied_decimals (i);
586
587   return true;
588 }
589
590 /* Parses RB format. */
591 static bool
592 parse_RB (struct data_in *i)
593 {
594   enum float_format ff = settings_get_input_float_format ();
595   size_t size = float_get_size (ff);
596   if (ss_length (i->input) >= size)
597     float_convert (ff, ss_data (i->input),
598                    FLOAT_NATIVE_DOUBLE, &i->output->f);
599   else
600     i->output->f = SYSMIS;
601
602   return true;
603 }
604
605 /* Parses A format. */
606 static bool
607 parse_A (struct data_in *i)
608 {
609   /* This is equivalent to buf_copy_rpad, except that we posibly
610      do a character set recoding in the middle. */
611   char *dst = value_str_rw (i->output, i->width);
612   size_t dst_size = i->width;
613   const char *src = ss_data (i->input);
614   size_t src_size = ss_length (i->input);
615
616   legacy_recode (i->encoding, src, LEGACY_NATIVE, dst, MIN (src_size, dst_size));
617   if (dst_size > src_size)
618     memset (&dst[src_size], ' ', dst_size - src_size);
619
620   return true;
621 }
622
623 /* Parses AHEX format. */
624 static bool
625 parse_AHEX (struct data_in *i)
626 {
627   char *s = value_str_rw (i->output, i->width);
628   size_t j;
629
630   for (j = 0; ; j++)
631     {
632       int hi = ss_get_char (&i->input);
633       int lo = ss_get_char (&i->input);
634       if (hi == EOF)
635         break;
636       else if (lo == EOF)
637         {
638           data_warning (i, _("Field must have even length."));
639           return false;
640         }
641
642       if (i->encoding != LEGACY_NATIVE)
643         {
644           hi = legacy_to_native (i->encoding, hi);
645           lo = legacy_to_native (i->encoding, lo);
646         }
647       if (!c_isxdigit (hi) || !c_isxdigit (lo))
648         {
649           data_warning (i, _("Field must contain only hex digits."));
650           return false;
651         }
652
653       if (j < i->width)
654         s[j] = hexit_value (hi) * 16 + hexit_value (lo);
655     }
656
657   memset (&s[j], ' ', i->width - j);
658
659   return true;
660 }
661 \f
662 /* Date & time format components. */
663
664 /* Sign of a time value. */
665 enum time_sign
666   {
667     SIGN_NO_TIME,       /* No time yet encountered. */
668     SIGN_POSITIVE,      /* Positive time. */
669     SIGN_NEGATIVE       /* Negative time. */
670   };
671
672 /* Parses a signed decimal integer from at most the first
673    MAX_DIGITS characters in I, storing the result into *RESULT.
674    Returns true if successful, false if no integer was
675    present. */
676 static bool
677 parse_int (struct data_in *i, long *result, size_t max_digits)
678 {
679   struct substring head = ss_head (i->input, max_digits);
680   size_t n = ss_get_long (&head, result);
681   if (n)
682     {
683       ss_advance (&i->input, n);
684       return true;
685     }
686   else
687     {
688       data_warning (i, _("Syntax error in date field."));
689       return false;
690     }
691 }
692
693 /* Parses a date integer between 1 and 31 from I, storing it into
694    *DAY.
695    Returns true if successful, false if no date was present. */
696 static bool
697 parse_day (struct data_in *i, long *day)
698 {
699   if (!parse_int (i, day, SIZE_MAX))
700     return false;
701   if (*day >= 1 && *day <= 31)
702     return true;
703
704   data_warning (i, _("Day (%ld) must be between 1 and 31."), *day);
705   return false;
706 }
707
708 /* Parses an integer from the beginning of I.
709    Adds SECONDS_PER_UNIT times the absolute value of the integer
710    to *TIME.
711    If *TIME_SIGN is SIGN_NO_TIME, allows a sign to precede the
712    time and sets *TIME_SIGN.  Otherwise, does not allow a sign.
713    Returns true if successful, false if no integer was present. */
714 static bool
715 parse_time_units (struct data_in *i, double seconds_per_unit,
716                   enum time_sign *time_sign, double *time)
717
718 {
719   long units;
720
721   if (*time_sign == SIGN_NO_TIME)
722     {
723       if (ss_match_char (&i->input, '-'))
724         *time_sign = SIGN_NEGATIVE;
725       else
726         {
727           ss_match_char (&i->input, '+');
728           *time_sign = SIGN_POSITIVE;
729         }
730     }
731   if (!parse_int (i, &units, SIZE_MAX))
732     return false;
733   if (units < 0)
734     {
735       data_warning (i, _("Syntax error in date field."));
736       return false;
737     }
738   *time += units * seconds_per_unit;
739   return true;
740 }
741
742 /* Parses a data delimiter from the beginning of I.
743    Returns true if successful, false if no delimiter was
744    present. */
745 static bool
746 parse_date_delimiter (struct data_in *i)
747 {
748   if (ss_ltrim (&i->input, ss_cstr ("-/.," CC_SPACES)))
749     return true;
750
751   data_warning (i, _("Delimiter expected between fields in date."));
752   return false;
753 }
754
755 /* Parses spaces at the beginning of I. */
756 static void
757 parse_spaces (struct data_in *i)
758 {
759   ss_ltrim (&i->input, ss_cstr (CC_SPACES));
760 }
761
762 static struct substring
763 parse_name_token (struct data_in *i)
764 {
765   struct substring token;
766   ss_get_chars (&i->input, ss_span (i->input, ss_cstr (CC_LETTERS)), &token);
767   return token;
768 }
769
770 /* Reads a name from I and sets *OUTPUT to the value associated
771    with that name.  If ALLOW_SUFFIXES is true, then names that
772    begin with one of the names are accepted; otherwise, only
773    exact matches (except for case) are allowed.
774    Returns true if successful, false otherwise. */
775 static bool
776 match_name (struct substring token, const char *const *names, long *output)
777 {
778   int i;
779
780   for (i = 1; *names != NULL; i++)
781     if (ss_equals_case (ss_cstr (*names++), token))
782       {
783         *output = i;
784         return true;
785       }
786
787   return false;
788 }
789
790 /* Parses a month name or number from the beginning of I,
791    storing the month (in range 1...12) into *MONTH.
792    Returns true if successful, false if no month was present. */
793 static bool
794 parse_month (struct data_in *i, long *month)
795 {
796   if (c_isdigit (ss_first (i->input)))
797     {
798       if (!parse_int (i, month, SIZE_MAX))
799         return false;
800       if (*month >= 1 && *month <= 12)
801         return true;
802     }
803   else
804     {
805       static const char *const english_names[] =
806         {
807           "jan", "feb", "mar", "apr", "may", "jun",
808           "jul", "aug", "sep", "oct", "nov", "dec",
809           NULL,
810         };
811
812       static const char *const roman_names[] =
813         {
814           "i", "ii", "iii", "iv", "v", "vi",
815           "vii", "viii", "ix", "x", "xi", "xii",
816           NULL,
817         };
818
819       struct substring token = parse_name_token (i);
820       if (match_name (ss_head (token, 3), english_names, month)
821           || match_name (ss_head (token, 4), roman_names, month))
822         return true;
823     }
824
825   data_warning (i, _("Unrecognized month format.  Months may be specified "
826                      "as Arabic or Roman numerals or as at least 3 letters "
827                      "of their English names."));
828   return false;
829 }
830
831 /* Parses a year of at most MAX_DIGITS from the beginning of I,
832    storing a "4-digit" year into *YEAR. */
833 static bool
834 parse_year (struct data_in *i, long *year, size_t max_digits)
835 {
836   if (!parse_int (i, year, max_digits))
837     return false;
838
839   if (*year >= 0 && *year <= 99)
840     {
841       int epoch = settings_get_epoch ();
842       int epoch_century = ROUND_DOWN (epoch, 100);
843       int epoch_offset = epoch - epoch_century;
844       if (*year >= epoch_offset)
845         *year += epoch_century;
846       else
847         *year += epoch_century + 100;
848     }
849   if (*year >= 1582 || *year <= 19999)
850     return true;
851
852   data_warning (i, _("Year (%ld) must be between 1582 and 19999."), *year);
853   return false;
854 }
855
856 /* Returns true if input in I has been exhausted,
857    false otherwise. */
858 static bool
859 parse_trailer (struct data_in *i)
860 {
861   if (ss_is_empty (i->input))
862     return true;
863
864   data_warning (i, _("Trailing garbage \"%.*s\" following date."),
865               (int) ss_length (i->input), ss_data (i->input));
866   return false;
867 }
868
869 /* Parses a 3-digit Julian day-of-year value from I into *YDAY.
870    Returns true if successful, false on failure. */
871 static bool
872 parse_yday (struct data_in *i, long *yday)
873 {
874   struct substring num_s;
875   long num;
876
877   ss_get_chars (&i->input, 3, &num_s);
878   if (ss_span (num_s, ss_cstr (CC_DIGITS)) != 3)
879     {
880       data_warning (i, _("Julian day must have exactly three digits."));
881       return false;
882     }
883   else if (!ss_get_long (&num_s, &num) || num < 1 || num > 366)
884     {
885       data_warning (i, _("Julian day (%ld) must be between 1 and 366."), num);
886       return false;
887     }
888
889   *yday = num;
890   return true;
891 }
892
893 /* Parses a quarter-of-year integer between 1 and 4 from I.
894    Stores the corresponding month into *MONTH.
895    Returns true if successful, false if no quarter was present. */
896 static bool
897 parse_quarter (struct data_in *i, long int *month)
898 {
899   long quarter;
900
901   if (!parse_int (i, &quarter, SIZE_MAX))
902     return false;
903   if (quarter >= 1 && quarter <= 4)
904     {
905       *month = (quarter - 1) * 3 + 1;
906       return true;
907     }
908
909   data_warning (i, _("Quarter (%ld) must be between 1 and 4."), quarter);
910   return false;
911 }
912
913 /* Parses a week-of-year integer between 1 and 53 from I,
914    Stores the corresponding year-of-day into *YDAY.
915    Returns true if successful, false if no week was present. */
916 static bool
917 parse_week (struct data_in *i, long int *yday)
918 {
919   long week;
920
921   if (!parse_int (i, &week, SIZE_MAX))
922     return false;
923   if (week >= 1 && week <= 53)
924     {
925       *yday = (week - 1) * 7 + 1;
926       return true;
927     }
928
929   data_warning (i, _("Week (%ld) must be between 1 and 53."), week);
930   return false;
931 }
932
933 /* Parses a time delimiter from the beginning of I.
934    Returns true if successful, false if no delimiter was
935    present. */
936 static bool
937 parse_time_delimiter (struct data_in *i)
938 {
939   if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) > 0)
940     return true;
941
942   data_warning (i, _("Delimiter expected between fields in time."));
943   return false;
944 }
945
946 /* Parses minutes and optional seconds from the beginning of I.
947    The time is converted into seconds, which are added to
948    *TIME.
949    Returns true if successful, false if an error was found. */
950 static bool
951 parse_minute_second (struct data_in *i, double *time)
952 {
953   long minute;
954   char buf[64];
955   char *cp;
956
957   /* Parse minutes. */
958   if (!parse_int (i, &minute, SIZE_MAX))
959     return false;
960   if (minute < 0 || minute > 59)
961     {
962       data_warning (i, _("Minute (%ld) must be between 0 and 59."), minute);
963       return false;
964     }
965   *time += 60. * minute;
966
967   /* Check for seconds. */
968   if (ss_ltrim (&i->input, ss_cstr (":" CC_SPACES)) == 0
969       || !c_isdigit (ss_first (i->input)))
970    return true;
971
972   /* Parse seconds. */
973   cp = buf;
974   while (c_isdigit (ss_first (i->input)))
975     *cp++ = ss_get_char (&i->input);
976   if (ss_match_char (&i->input, settings_get_decimal_char (FMT_F)))
977     *cp++ = '.';
978   while (c_isdigit (ss_first (i->input)))
979     *cp++ = ss_get_char (&i->input);
980   *cp = '\0';
981
982   *time += strtod (buf, NULL);
983
984   return true;
985 }
986
987 /* Parses a weekday name from the beginning of I,
988    storing a value of 1=Sunday...7=Saturday into *WEEKDAY.
989    Returns true if successful, false if an error was found. */
990 static bool
991 parse_weekday (struct data_in *i, long *weekday)
992 {
993   static const char *const weekday_names[] =
994     {
995       "su", "mo", "tu", "we", "th", "fr", "sa",
996       NULL,
997     };
998
999   struct substring token = parse_name_token (i);
1000   bool ok = match_name (ss_head (token, 2), weekday_names, weekday);
1001   if (!ok)
1002     data_warning (i, _("Unrecognized weekday name.  At least the first two "
1003                        "letters of an English weekday name must be "
1004                        "specified."));
1005   return ok;
1006 }
1007 \f
1008 /* Date & time formats. */
1009
1010 /* Helper function for passing to
1011    calendar_gregorian_to_offset. */
1012 static void
1013 calendar_error (void *i_, const char *format, ...)
1014 {
1015   struct data_in *i = i_;
1016   va_list args;
1017
1018   va_start (args, format);
1019   vdata_warning (i, format, args);
1020   va_end (args);
1021 }
1022
1023 /* Parses WKDAY format. */
1024 static bool
1025 parse_WKDAY (struct data_in *i)
1026 {
1027   long weekday;
1028
1029   if (trim_spaces_and_check_missing (i))
1030     return true;
1031
1032   if (!parse_weekday (i, &weekday)
1033       || !parse_trailer (i))
1034     return false;
1035
1036   i->output->f = weekday;
1037   return true;
1038 }
1039
1040 /* Parses MONTH format. */
1041 static bool
1042 parse_MONTH (struct data_in *i)
1043 {
1044   long month;
1045
1046   if (trim_spaces_and_check_missing (i))
1047     return true;
1048
1049   if (!parse_month (i, &month)
1050       || !parse_trailer (i))
1051     return false;
1052
1053   i->output->f = month;
1054   return true;
1055 }
1056
1057 /* Parses DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, KWYR,
1058    DATETIME, TIME and DTIME formats. */
1059 static bool
1060 parse_date (struct data_in *i)
1061 {
1062   long int year = INT_MIN;
1063   long int month = 1;
1064   long int day = 1;
1065   long int yday = 1;
1066   double time = 0, date = 0;
1067   enum time_sign time_sign = SIGN_NO_TIME;
1068
1069   const char *template = fmt_date_template (i->format);
1070   size_t template_width = strlen (template);
1071
1072   if (trim_spaces_and_check_missing (i))
1073     return true;
1074
1075   while (*template != '\0')
1076     {
1077       unsigned char ch = *template;
1078       int count = 1;
1079       bool ok;
1080
1081       while (template[count] == ch)
1082         count++;
1083       template += count;
1084
1085       ok = true;
1086       switch (ch)
1087         {
1088         case 'd':
1089           ok = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
1090           break;
1091         case 'm':
1092           ok = parse_month (i, &month);
1093           break;
1094         case 'y':
1095           {
1096             size_t max_digits;
1097             if (!c_isalpha (*template))
1098               max_digits = SIZE_MAX;
1099             else
1100               {
1101                 if (ss_length (i->input) >= template_width + 2)
1102                   max_digits = 4;
1103                 else
1104                   max_digits = 2;
1105               }
1106             ok = parse_year (i, &year, max_digits);
1107           }
1108           break;
1109         case 'q':
1110           ok = parse_quarter (i, &month);
1111           break;
1112         case 'w':
1113           ok = parse_week (i, &yday);
1114           break;
1115         case 'D':
1116           ok = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
1117           break;
1118         case 'H':
1119           ok = parse_time_units (i, 60. * 60., &time_sign, &time);
1120           break;
1121         case 'M':
1122           ok = parse_minute_second (i, &time);
1123           break;
1124         case '-':
1125         case '/':
1126         case '.':
1127         case 'X':
1128           ok = parse_date_delimiter (i);
1129           break;
1130         case ':':
1131           ok = parse_time_delimiter (i);
1132         case ' ':
1133           parse_spaces (i);
1134           break;
1135         default:
1136           assert (count == 1);
1137           if (!ss_match_char (&i->input, c_toupper (ch))
1138               && !ss_match_char (&i->input, c_tolower (ch)))
1139             {
1140               data_warning (i, _("`%c' expected in date field."), ch);
1141               return false;
1142             }
1143           break;
1144         }
1145       if (!ok)
1146         return false;
1147     }
1148   if (!parse_trailer (i))
1149     return false;
1150
1151   if (year != INT_MIN)
1152     {
1153       double ofs = calendar_gregorian_to_offset (year, month, day,
1154                                                  calendar_error, i);
1155       if (ofs == SYSMIS)
1156         return false;
1157       date = (yday - 1 + ofs) * 60. * 60. * 24.;
1158     }
1159   else
1160     date = 0.;
1161   i->output->f = date + (time_sign == SIGN_NEGATIVE ? -time : time);
1162
1163   return true;
1164 }
1165 \f
1166 /* Utility functions. */
1167
1168 /* Outputs FORMAT with the given ARGS as a warning for input
1169    I. */
1170 static void
1171 vdata_warning (const struct data_in *i, const char *format, va_list args)
1172 {
1173   struct msg m;
1174   struct string text;
1175
1176   ds_init_empty (&text);
1177   ds_put_char (&text, '(');
1178   if (i->first_column != 0)
1179     {
1180       if (i->first_column == i->last_column - 1)
1181         ds_put_format (&text, _("column %d"), i->first_column);
1182       else
1183         ds_put_format (&text, _("columns %d-%d"),
1184                        i->first_column, i->last_column - 1);
1185       ds_put_cstr (&text, ", ");
1186     }
1187   ds_put_format (&text, _("%s field) "), fmt_name (i->format));
1188   ds_put_vformat (&text, format, args);
1189
1190   m.category = MSG_DATA;
1191   m.severity = MSG_WARNING;
1192   m.text = ds_cstr (&text);
1193
1194   msg_emit (&m);
1195 }
1196
1197 /* Outputs FORMAT with the given ARGS as a warning for input
1198    I. */
1199 static void
1200 data_warning (const struct data_in *i, const char *format, ...)
1201 {
1202   va_list args;
1203
1204   va_start (args, format);
1205   vdata_warning (i, format, args);
1206   va_end (args);
1207 }
1208
1209 /* Apply implied decimal places to output. */
1210 static void
1211 apply_implied_decimals (struct data_in *i)
1212 {
1213   if (i->implied_decimals > 0)
1214     i->output->f /= pow (10., i->implied_decimals);
1215 }
1216
1217 /* Sets the default result for I.
1218    For a numeric format, this is the value set on SET BLANKS
1219    (typically system-missing); for a string format, it is all
1220    spaces. */
1221 static void
1222 default_result (struct data_in *i)
1223 {
1224   if (fmt_is_string (i->format))
1225     memset (value_str_rw (i->output, i->width), ' ', i->width);
1226   else
1227     i->output->f = settings_get_blanks ();
1228 }
1229
1230 /* Trims leading and trailing spaces from I.
1231    If the result is empty, or a single period character, then
1232    sets the default result and returns true; otherwise, returns
1233    false. */
1234 static bool
1235 trim_spaces_and_check_missing (struct data_in *i)
1236 {
1237   ss_trim (&i->input, ss_cstr (" "));
1238   if (ss_is_empty (i->input) || ss_equals (i->input, ss_cstr (".")))
1239     {
1240       default_result (i);
1241       return true;
1242     }
1243   return false;
1244 }
1245
1246 /* Returns the integer value of hex digit C. */
1247 static int
1248 hexit_value (int c)
1249 {
1250   const char s[] = "0123456789abcdef";
1251   const char *cp = strchr (s, c_tolower ((unsigned char) c));
1252
1253   assert (cp != NULL);
1254   return cp - s;
1255 }