html.c: removed extra newlines entering/exiting blockquote sections.
[citadel.git] / citadel / parsedate.c
1 /* A Bison parser, made by GNU Bison 1.875d.  */
2
3 /* Skeleton parser for Yacc-like parsing with Bison,
4    Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 /* As a special exception, when this file is copied by Bison into a
22    Bison output file, you may use that output file without restriction.
23    This special exception was added by the Free Software Foundation
24    in version 1.24 of Bison.  */
25
26 /* Written by Richard Stallman by simplifying the original so called
27    ``semantic'' parser.  */
28
29 /* All symbols defined below should begin with yy or YY, to avoid
30    infringing on user name space.  This should be done even for local
31    variables, as they might otherwise be expanded by user macros.
32    There are some unavoidable exceptions within include files to
33    define necessary library symbols; they are noted "INFRINGES ON
34    USER NAME SPACE" below.  */
35
36 /* Identify Bison output.  */
37 #define YYBISON 1
38
39 /* Skeleton name.  */
40 #define YYSKELETON_NAME "yacc.c"
41
42 /* Pure parsers.  */
43 #define YYPURE 0
44
45 /* Using locations.  */
46 #define YYLSP_NEEDED 0
47
48
49
50 /* Tokens.  */
51 #ifndef YYTOKENTYPE
52 # define YYTOKENTYPE
53    /* Put the tokens into the symbol table, so that GDB and other debuggers
54       know about them.  */
55    enum yytokentype {
56      tDAY = 258,
57      tDAYZONE = 259,
58      tMERIDIAN = 260,
59      tMONTH = 261,
60      tMONTH_UNIT = 262,
61      tSEC_UNIT = 263,
62      tSNUMBER = 264,
63      tUNUMBER = 265,
64      tZONE = 266
65    };
66 #endif
67 #define tDAY 258
68 #define tDAYZONE 259
69 #define tMERIDIAN 260
70 #define tMONTH 261
71 #define tMONTH_UNIT 262
72 #define tSEC_UNIT 263
73 #define tSNUMBER 264
74 #define tUNUMBER 265
75 #define tZONE 266
76
77
78
79
80 /* Copy the first part of user declarations.  */
81 #line 1 "parsedate.y"
82
83 /* $Revision: 4003 $
84 **
85 **  Originally written by Steven M. Bellovin <smb@research.att.com> while
86 **  at the University of North Carolina at Chapel Hill.  Later tweaked by
87 **  a couple of people on Usenet.  Completely overhauled by Rich $alz
88 **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
89 **  Further revised (removed obsolete constructs and cleaned up timezone
90 **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
91 **  helped in September, 1992.  Art Cancro <ajc@uncensored.citadel.org> cleaned
92 **  it up for ANSI C in December, 1999.
93 **
94 **  This grammar has six shift/reduce conflicts.
95 **
96 **  This code is in the public domain and has no copyright.
97 */
98 /* SUPPRESS 530 *//* Empty body for statement */
99 /* SUPPRESS 593 on yyerrlab *//* Label was not used */
100 /* SUPPRESS 593 on yynewstate *//* Label was not used */
101 /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
102
103 #include "sysdep.h"
104
105 #include <stdio.h>
106 #include <stdlib.h>
107 #include <sys/types.h>
108 #include <ctype.h>
109
110 #if TIME_WITH_SYS_TIME
111 # include <sys/time.h>
112 # include <time.h>
113 #else
114 # if HAVE_SYS_TIME_H
115 #  include <sys/time.h>
116 # else
117 #  include <time.h>
118 # endif
119 #endif
120
121 #if HAVE_STRING_H
122 # if !STDC_HEADERS && HAVE_MEMORY_H
123 #  include <memory.h>
124 # endif
125 # include <string.h>
126 #endif
127 #if HAVE_STRINGS_H
128 # include <strings.h>
129 #endif
130
131 #include "parsedate.h"
132
133 int date_lex(void);
134
135 #define yyparse         date_parse
136 #define yylex           date_lex
137 #define yyerror         date_error
138
139
140     /* See the LeapYears table in Convert. */
141 #define EPOCH           1970
142 #define END_OF_TIME     2038
143     /* Constants for general time calculations. */
144 #define DST_OFFSET      1
145 #define SECSPERDAY      (24L * 60L * 60L)
146     /* Readability for TABLE stuff. */
147 #define HOUR(x)         (x * 60)
148
149 #define LPAREN          '('
150 #define RPAREN          ')'
151 #define IS7BIT(x)       ((unsigned int)(x) < 0200)
152
153 #define SIZEOF(array)   ((int)(sizeof array / sizeof array[0]))
154 #define ENDOF(array)    (&array[SIZEOF(array)])
155
156
157 /*
158 **  An entry in the lexical lookup table.
159 */
160 typedef struct _TABLE {
161     char        *name;
162     int         type;
163     time_t      value;
164 } TABLE;
165
166 /*
167 **  Daylight-savings mode:  on, off, or not yet known.
168 */
169 typedef enum _DSTMODE {
170     DSTon, DSToff, DSTmaybe
171 } DSTMODE;
172
173 /*
174 **  Meridian:  am, pm, or 24-hour style.
175 */
176 typedef enum _MERIDIAN {
177     MERam, MERpm, MER24
178 } MERIDIAN;
179
180
181 /*
182 **  Global variables.  We could get rid of most of them by using a yacc
183 **  union, but this is more efficient.  (This routine predates the
184 **  yacc %union construct.)
185 */
186 static char     *yyInput;
187 static DSTMODE  yyDSTmode;
188 static int      yyHaveDate;
189 static int      yyHaveRel;
190 static int      yyHaveTime;
191 static time_t   yyTimezone;
192 static time_t   yyDay;
193 static time_t   yyHour;
194 static time_t   yyMinutes;
195 static time_t   yyMonth;
196 static time_t   yySeconds;
197 static time_t   yyYear;
198 static MERIDIAN yyMeridian;
199 static time_t   yyRelMonth;
200 static time_t   yyRelSeconds;
201
202
203 static void             date_error(char *);
204
205
206 /* Enabling traces.  */
207 #ifndef YYDEBUG
208 # define YYDEBUG 0
209 #endif
210
211 /* Enabling verbose error messages.  */
212 #ifdef YYERROR_VERBOSE
213 # undef YYERROR_VERBOSE
214 # define YYERROR_VERBOSE 1
215 #else
216 # define YYERROR_VERBOSE 0
217 #endif
218
219 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
220 #line 125 "parsedate.y"
221 typedef union YYSTYPE {
222     time_t              Number;
223     enum _MERIDIAN      Meridian;
224 } YYSTYPE;
225 /* Line 191 of yacc.c.  */
226 #line 227 "y.tab.c"
227 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
228 # define YYSTYPE_IS_DECLARED 1
229 # define YYSTYPE_IS_TRIVIAL 1
230 #endif
231
232
233
234 /* Copy the second part of user declarations.  */
235
236
237 /* Line 214 of yacc.c.  */
238 #line 239 "y.tab.c"
239
240 #if ! defined (yyoverflow) || YYERROR_VERBOSE
241
242 # ifndef YYFREE
243 #  define YYFREE free
244 # endif
245 # ifndef YYMALLOC
246 #  define YYMALLOC malloc
247 # endif
248
249 /* The parser invokes alloca or malloc; define the necessary symbols.  */
250
251 # ifdef YYSTACK_USE_ALLOCA
252 #  if YYSTACK_USE_ALLOCA
253 #   define YYSTACK_ALLOC alloca
254 #  endif
255 # else
256 #  if defined (alloca) || defined (_ALLOCA_H)
257 #   define YYSTACK_ALLOC alloca
258 #  else
259 #   ifdef __GNUC__
260 #    define YYSTACK_ALLOC __builtin_alloca
261 #   endif
262 #  endif
263 # endif
264
265 # ifdef YYSTACK_ALLOC
266    /* Pacify GCC's `empty if-body' warning. */
267 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
268 # else
269 #  if defined (__STDC__) || defined (__cplusplus)
270 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
271 #   define YYSIZE_T size_t
272 #  endif
273 #  define YYSTACK_ALLOC YYMALLOC
274 #  define YYSTACK_FREE YYFREE
275 # endif
276 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
277
278
279 #if (! defined (yyoverflow) \
280      && (! defined (__cplusplus) \
281          || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
282
283 /* A type that is properly aligned for any stack member.  */
284 union yyalloc
285 {
286   short int yyss;
287   YYSTYPE yyvs;
288   };
289
290 /* The size of the maximum gap between one aligned stack and the next.  */
291 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
292
293 /* The size of an array large to enough to hold all stacks, each with
294    N elements.  */
295 # define YYSTACK_BYTES(N) \
296      ((N) * (sizeof (short int) + sizeof (YYSTYPE))                     \
297       + YYSTACK_GAP_MAXIMUM)
298
299 /* Copy COUNT objects from FROM to TO.  The source and destination do
300    not overlap.  */
301 # ifndef YYCOPY
302 #  if defined (__GNUC__) && 1 < __GNUC__
303 #   define YYCOPY(To, From, Count) \
304       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
305 #  else
306 #   define YYCOPY(To, From, Count)              \
307       do                                        \
308         {                                       \
309           register YYSIZE_T yyi;                \
310           for (yyi = 0; yyi < (Count); yyi++)   \
311             (To)[yyi] = (From)[yyi];            \
312         }                                       \
313       while (0)
314 #  endif
315 # endif
316
317 /* Relocate STACK from its old location to the new one.  The
318    local variables YYSIZE and YYSTACKSIZE give the old and new number of
319    elements in the stack, and YYPTR gives the new location of the
320    stack.  Advance YYPTR to a properly aligned location for the next
321    stack.  */
322 # define YYSTACK_RELOCATE(Stack)                                        \
323     do                                                                  \
324       {                                                                 \
325         YYSIZE_T yynewbytes;                                            \
326         YYCOPY (&yyptr->Stack, Stack, yysize);                          \
327         Stack = &yyptr->Stack;                                          \
328         yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
329         yyptr += yynewbytes / sizeof (*yyptr);                          \
330       }                                                                 \
331     while (0)
332
333 #endif
334
335 #if defined (__STDC__) || defined (__cplusplus)
336    typedef signed char yysigned_char;
337 #else
338    typedef short int yysigned_char;
339 #endif
340
341 /* YYFINAL -- State number of the termination state. */
342 #define YYFINAL  2
343 /* YYLAST -- Last index in YYTABLE.  */
344 #define YYLAST   40
345
346 /* YYNTOKENS -- Number of terminals. */
347 #define YYNTOKENS  15
348 /* YYNNTS -- Number of nonterminals. */
349 #define YYNNTS  9
350 /* YYNRULES -- Number of rules. */
351 #define YYNRULES  30
352 /* YYNRULES -- Number of states. */
353 #define YYNSTATES  44
354
355 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
356 #define YYUNDEFTOK  2
357 #define YYMAXUTOK   266
358
359 #define YYTRANSLATE(YYX)                                                \
360   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
361
362 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
363 static const unsigned char yytranslate[] =
364 {
365        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
366        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
367        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
368        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
369        2,     2,     2,     2,    14,     2,     2,    13,     2,     2,
370        2,     2,     2,     2,     2,     2,     2,     2,    12,     2,
371        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
372        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
373        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
374        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
375        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
376        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
377        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
378        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
379        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
380        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
381        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
382        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
383        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
384        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
385        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
386        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
387        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
388        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
389        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
390        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
391        5,     6,     7,     8,     9,    10,    11
392 };
393
394 #if YYDEBUG
395 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
396    YYRHS.  */
397 static const unsigned char yyprhs[] =
398 {
399        0,     0,     3,     4,     7,     9,    12,    14,    16,    19,
400       24,    29,    36,    43,    45,    47,    50,    52,    54,    58,
401       64,    67,    72,    75,    79,    85,    88,    91,    94,    97,
402       98
403 };
404
405 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
406 static const yysigned_char yyrhs[] =
407 {
408       16,     0,    -1,    -1,    16,    17,    -1,    18,    -1,    18,
409       19,    -1,    21,    -1,    22,    -1,    10,    23,    -1,    10,
410       12,    10,    23,    -1,    10,    12,    10,    20,    -1,    10,
411       12,    10,    12,    10,    23,    -1,    10,    12,    10,    12,
412       10,    20,    -1,    11,    -1,     4,    -1,    11,    20,    -1,
413       20,    -1,     9,    -1,    10,    13,    10,    -1,    10,    13,
414       10,    13,    10,    -1,     6,    10,    -1,     6,    10,    14,
415       10,    -1,    10,     6,    -1,    10,     6,    10,    -1,     3,
416       14,    10,     6,    10,    -1,     9,     8,    -1,    10,     8,
417       -1,     9,     7,    -1,    10,     7,    -1,    -1,     5,    -1
418 };
419
420 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
421 static const unsigned short int yyrline[] =
422 {
423        0,   139,   139,   140,   143,   152,   156,   159,   164,   176,
424      182,   189,   195,   205,   209,   213,   221,   227,   248,   252,
425      264,   268,   273,   277,   282,   289,   292,   295,   298,   303,
426      306
427 };
428 #endif
429
430 #if YYDEBUG || YYERROR_VERBOSE
431 /* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
432    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
433 static const char *const yytname[] =
434 {
435   "$end", "error", "$undefined", "tDAY", "tDAYZONE", "tMERIDIAN",
436   "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tSNUMBER", "tUNUMBER", "tZONE",
437   "':'", "'/'", "','", "$accept", "spec", "item", "time", "zone",
438   "numzone", "date", "rel", "o_merid", 0
439 };
440 #endif
441
442 # ifdef YYPRINT
443 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
444    token YYLEX-NUM.  */
445 static const unsigned short int yytoknum[] =
446 {
447        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
448      265,   266,    58,    47,    44
449 };
450 # endif
451
452 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
453 static const unsigned char yyr1[] =
454 {
455        0,    15,    16,    16,    17,    17,    17,    17,    18,    18,
456       18,    18,    18,    19,    19,    19,    19,    20,    21,    21,
457       21,    21,    21,    21,    21,    22,    22,    22,    22,    23,
458       23
459 };
460
461 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
462 static const unsigned char yyr2[] =
463 {
464        0,     2,     0,     2,     1,     2,     1,     1,     2,     4,
465        4,     6,     6,     1,     1,     2,     1,     1,     3,     5,
466        2,     4,     2,     3,     5,     2,     2,     2,     2,     0,
467        1
468 };
469
470 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
471    STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
472    means the default is an error.  */
473 static const unsigned char yydefact[] =
474 {
475        2,     0,     1,     0,     0,     0,    29,     3,     4,     6,
476        7,     0,    20,    27,    25,    30,    22,    28,    26,     0,
477        0,     8,    14,    17,    13,     5,    16,     0,     0,    23,
478       29,    18,    15,     0,    21,     0,    10,     9,     0,    24,
479       29,    19,    12,    11
480 };
481
482 /* YYDEFGOTO[NTERM-NUM]. */
483 static const yysigned_char yydefgoto[] =
484 {
485       -1,     1,     7,     8,    25,    26,     9,    10,    21
486 };
487
488 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
489    STATE-NUM.  */
490 #define YYPACT_NINF -29
491 static const yysigned_char yypact[] =
492 {
493      -29,     1,   -29,   -11,    11,    20,    12,   -29,     4,   -29,
494      -29,    13,    16,   -29,   -29,   -29,    21,   -29,   -29,    22,
495       23,   -29,   -29,   -29,     5,   -29,   -29,    28,    25,   -29,
496       17,    24,   -29,    26,   -29,    29,   -29,   -29,    30,   -29,
497        0,   -29,   -29,   -29
498 };
499
500 /* YYPGOTO[NTERM-NUM].  */
501 static const yysigned_char yypgoto[] =
502 {
503      -29,   -29,   -29,   -29,   -29,   -24,   -29,   -29,   -28
504 };
505
506 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
507    positive, shift that token.  If negative, reduce the rule which
508    number is the opposite.  If zero, do what YYDEFACT says.
509    If YYTABLE_NINF, syntax error.  */
510 #define YYTABLE_NINF -1
511 static const unsigned char yytable[] =
512 {
513       32,     2,    37,    11,     3,    15,    36,     4,    22,    23,
514        5,     6,    43,    23,    23,    24,    42,    15,    16,    17,
515       18,    12,    15,    27,    19,    20,    23,    13,    14,    35,
516       28,    29,    30,    31,    33,    34,    39,    38,     0,    40,
517       41
518 };
519
520 static const yysigned_char yycheck[] =
521 {
522       24,     0,    30,    14,     3,     5,    30,     6,     4,     9,
523        9,    10,    40,     9,     9,    11,    40,     5,     6,     7,
524        8,    10,     5,    10,    12,    13,     9,     7,     8,    12,
525       14,    10,    10,    10,     6,    10,    10,    13,    -1,    10,
526       10
527 };
528
529 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
530    symbol of state STATE-NUM.  */
531 static const unsigned char yystos[] =
532 {
533        0,    16,     0,     3,     6,     9,    10,    17,    18,    21,
534       22,    14,    10,     7,     8,     5,     6,     7,     8,    12,
535       13,    23,     4,     9,    11,    19,    20,    10,    14,    10,
536       10,    10,    20,     6,    10,    12,    20,    23,    13,    10,
537       10,    10,    20,    23
538 };
539
540 #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
541 # define YYSIZE_T __SIZE_TYPE__
542 #endif
543 #if ! defined (YYSIZE_T) && defined (size_t)
544 # define YYSIZE_T size_t
545 #endif
546 #if ! defined (YYSIZE_T)
547 # if defined (__STDC__) || defined (__cplusplus)
548 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
549 #  define YYSIZE_T size_t
550 # endif
551 #endif
552 #if ! defined (YYSIZE_T)
553 # define YYSIZE_T unsigned int
554 #endif
555
556 #define yyerrok         (yyerrstatus = 0)
557 #define yyclearin       (yychar = YYEMPTY)
558 #define YYEMPTY         (-2)
559 #define YYEOF           0
560
561 #define YYACCEPT        goto yyacceptlab
562 #define YYABORT         goto yyabortlab
563 #define YYERROR         goto yyerrorlab
564
565
566 /* Like YYERROR except do call yyerror.  This remains here temporarily
567    to ease the transition to the new meaning of YYERROR, for GCC.
568    Once GCC version 2 has supplanted version 1, this can go.  */
569
570 #define YYFAIL          goto yyerrlab
571
572 #define YYRECOVERING()  (!!yyerrstatus)
573
574 #define YYBACKUP(Token, Value)                                  \
575 do                                                              \
576   if (yychar == YYEMPTY && yylen == 1)                          \
577     {                                                           \
578       yychar = (Token);                                         \
579       yylval = (Value);                                         \
580       yytoken = YYTRANSLATE (yychar);                           \
581       YYPOPSTACK;                                               \
582       goto yybackup;                                            \
583     }                                                           \
584   else                                                          \
585     {                                                           \
586       yyerror ("syntax error: cannot back up");\
587       YYERROR;                                                  \
588     }                                                           \
589 while (0)
590
591 #define YYTERROR        1
592 #define YYERRCODE       256
593
594 /* YYLLOC_DEFAULT -- Compute the default location (before the actions
595    are run).  */
596
597 #ifndef YYLLOC_DEFAULT
598 # define YYLLOC_DEFAULT(Current, Rhs, N)                \
599    ((Current).first_line   = (Rhs)[1].first_line,       \
600     (Current).first_column = (Rhs)[1].first_column,     \
601     (Current).last_line    = (Rhs)[N].last_line,        \
602     (Current).last_column  = (Rhs)[N].last_column)
603 #endif
604
605 /* YYLEX -- calling `yylex' with the right arguments.  */
606
607 #ifdef YYLEX_PARAM
608 # define YYLEX yylex (YYLEX_PARAM)
609 #else
610 # define YYLEX yylex ()
611 #endif
612
613 /* Enable debugging if requested.  */
614 #if YYDEBUG
615
616 # ifndef YYFPRINTF
617 #  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
618 #  define YYFPRINTF fprintf
619 # endif
620
621 # define YYDPRINTF(Args)                        \
622 do {                                            \
623   if (yydebug)                                  \
624     YYFPRINTF Args;                             \
625 } while (0)
626
627 # define YYDSYMPRINT(Args)                      \
628 do {                                            \
629   if (yydebug)                                  \
630     yysymprint Args;                            \
631 } while (0)
632
633 # define YYDSYMPRINTF(Title, Token, Value, Location)            \
634 do {                                                            \
635   if (yydebug)                                                  \
636     {                                                           \
637       YYFPRINTF (stderr, "%s ", Title);                         \
638       yysymprint (stderr,                                       \
639                   Token, Value);        \
640       YYFPRINTF (stderr, "\n");                                 \
641     }                                                           \
642 } while (0)
643
644 /*------------------------------------------------------------------.
645 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
646 | TOP (included).                                                   |
647 `------------------------------------------------------------------*/
648
649 #if defined (__STDC__) || defined (__cplusplus)
650 static void
651 yy_stack_print (short int *bottom, short int *top)
652 #else
653 static void
654 yy_stack_print (bottom, top)
655     short int *bottom;
656     short int *top;
657 #endif
658 {
659   YYFPRINTF (stderr, "Stack now");
660   for (/* Nothing. */; bottom <= top; ++bottom)
661     YYFPRINTF (stderr, " %d", *bottom);
662   YYFPRINTF (stderr, "\n");
663 }
664
665 # define YY_STACK_PRINT(Bottom, Top)                            \
666 do {                                                            \
667   if (yydebug)                                                  \
668     yy_stack_print ((Bottom), (Top));                           \
669 } while (0)
670
671
672 /*------------------------------------------------.
673 | Report that the YYRULE is going to be reduced.  |
674 `------------------------------------------------*/
675
676 #if defined (__STDC__) || defined (__cplusplus)
677 static void
678 yy_reduce_print (int yyrule)
679 #else
680 static void
681 yy_reduce_print (yyrule)
682     int yyrule;
683 #endif
684 {
685   int yyi;
686   unsigned int yylno = yyrline[yyrule];
687   YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
688              yyrule - 1, yylno);
689   /* Print the symbols being reduced, and their result.  */
690   for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
691     YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
692   YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
693 }
694
695 # define YY_REDUCE_PRINT(Rule)          \
696 do {                                    \
697   if (yydebug)                          \
698     yy_reduce_print (Rule);             \
699 } while (0)
700
701 /* Nonzero means print parse trace.  It is left uninitialized so that
702    multiple parsers can coexist.  */
703 int yydebug;
704 #else /* !YYDEBUG */
705 # define YYDPRINTF(Args)
706 # define YYDSYMPRINT(Args)
707 # define YYDSYMPRINTF(Title, Token, Value, Location)
708 # define YY_STACK_PRINT(Bottom, Top)
709 # define YY_REDUCE_PRINT(Rule)
710 #endif /* !YYDEBUG */
711
712
713 /* YYINITDEPTH -- initial size of the parser's stacks.  */
714 #ifndef YYINITDEPTH
715 # define YYINITDEPTH 200
716 #endif
717
718 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
719    if the built-in stack extension method is used).
720
721    Do not make this value too large; the results are undefined if
722    SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
723    evaluated with infinite-precision integer arithmetic.  */
724
725 #if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
726 # undef YYMAXDEPTH
727 #endif
728
729 #ifndef YYMAXDEPTH
730 # define YYMAXDEPTH 10000
731 #endif
732
733 \f
734
735 #if YYERROR_VERBOSE
736
737 # ifndef yystrlen
738 #  if defined (__GLIBC__) && defined (_STRING_H)
739 #   define yystrlen strlen
740 #  else
741 /* Return the length of YYSTR.  */
742 static YYSIZE_T
743 #   if defined (__STDC__) || defined (__cplusplus)
744 yystrlen (const char *yystr)
745 #   else
746 yystrlen (yystr)
747      const char *yystr;
748 #   endif
749 {
750   register const char *yys = yystr;
751
752   while (*yys++ != '\0')
753     continue;
754
755   return yys - yystr - 1;
756 }
757 #  endif
758 # endif
759
760 # ifndef yystpcpy
761 #  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
762 #   define yystpcpy stpcpy
763 #  else
764 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
765    YYDEST.  */
766 static char *
767 #   if defined (__STDC__) || defined (__cplusplus)
768 yystpcpy (char *yydest, const char *yysrc)
769 #   else
770 yystpcpy (yydest, yysrc)
771      char *yydest;
772      const char *yysrc;
773 #   endif
774 {
775   register char *yyd = yydest;
776   register const char *yys = yysrc;
777
778   while ((*yyd++ = *yys++) != '\0')
779     continue;
780
781   return yyd - 1;
782 }
783 #  endif
784 # endif
785
786 #endif /* !YYERROR_VERBOSE */
787
788 \f
789
790 #if YYDEBUG
791 /*--------------------------------.
792 | Print this symbol on YYOUTPUT.  |
793 `--------------------------------*/
794
795 #if defined (__STDC__) || defined (__cplusplus)
796 static void
797 yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
798 #else
799 static void
800 yysymprint (yyoutput, yytype, yyvaluep)
801     FILE *yyoutput;
802     int yytype;
803     YYSTYPE *yyvaluep;
804 #endif
805 {
806   /* Pacify ``unused variable'' warnings.  */
807   (void) yyvaluep;
808
809   if (yytype < YYNTOKENS)
810     {
811       YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
812 # ifdef YYPRINT
813       YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
814 # endif
815     }
816   else
817     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
818
819   switch (yytype)
820     {
821       default:
822         break;
823     }
824   YYFPRINTF (yyoutput, ")");
825 }
826
827 #endif /* ! YYDEBUG */
828 /*-----------------------------------------------.
829 | Release the memory associated to this symbol.  |
830 `-----------------------------------------------*/
831
832 #if defined (__STDC__) || defined (__cplusplus)
833 static void
834 yydestruct (int yytype, YYSTYPE *yyvaluep)
835 #else
836 static void
837 yydestruct (yytype, yyvaluep)
838     int yytype;
839     YYSTYPE *yyvaluep;
840 #endif
841 {
842   /* Pacify ``unused variable'' warnings.  */
843   (void) yyvaluep;
844
845   switch (yytype)
846     {
847
848       default:
849         break;
850     }
851 }
852 \f
853
854 /* Prevent warnings from -Wmissing-prototypes.  */
855
856 #ifdef YYPARSE_PARAM
857 # if defined (__STDC__) || defined (__cplusplus)
858 int yyparse (void *YYPARSE_PARAM);
859 # else
860 int yyparse ();
861 # endif
862 #else /* ! YYPARSE_PARAM */
863 #if defined (__STDC__) || defined (__cplusplus)
864 int yyparse (void);
865 #else
866 int yyparse ();
867 #endif
868 #endif /* ! YYPARSE_PARAM */
869
870
871
872 /* The lookahead symbol.  */
873 int yychar;
874
875 /* The semantic value of the lookahead symbol.  */
876 YYSTYPE yylval;
877
878 /* Number of syntax errors so far.  */
879 int yynerrs;
880
881
882
883 /*----------.
884 | yyparse.  |
885 `----------*/
886
887 #ifdef YYPARSE_PARAM
888 # if defined (__STDC__) || defined (__cplusplus)
889 int yyparse (void *YYPARSE_PARAM)
890 # else
891 int yyparse (YYPARSE_PARAM)
892   void *YYPARSE_PARAM;
893 # endif
894 #else /* ! YYPARSE_PARAM */
895 #if defined (__STDC__) || defined (__cplusplus)
896 int
897 yyparse (void)
898 #else
899 int
900 yyparse ()
901
902 #endif
903 #endif
904 {
905   
906   register int yystate;
907   register int yyn;
908   int yyresult;
909   /* Number of tokens to shift before error messages enabled.  */
910   int yyerrstatus;
911   /* Lookahead token as an internal (translated) token number.  */
912   int yytoken = 0;
913
914   /* Three stacks and their tools:
915      `yyss': related to states,
916      `yyvs': related to semantic values,
917      `yyls': related to locations.
918
919      Refer to the stacks thru separate pointers, to allow yyoverflow
920      to reallocate them elsewhere.  */
921
922   /* The state stack.  */
923   short int yyssa[YYINITDEPTH];
924   short int *yyss = yyssa;
925   register short int *yyssp;
926
927   /* The semantic value stack.  */
928   YYSTYPE yyvsa[YYINITDEPTH];
929   YYSTYPE *yyvs = yyvsa;
930   register YYSTYPE *yyvsp;
931
932
933
934 #define YYPOPSTACK   (yyvsp--, yyssp--)
935
936   YYSIZE_T yystacksize = YYINITDEPTH;
937
938   /* The variables used to return semantic value and location from the
939      action routines.  */
940   YYSTYPE yyval;
941
942
943   /* When reducing, the number of symbols on the RHS of the reduced
944      rule.  */
945   int yylen;
946
947   YYDPRINTF ((stderr, "Starting parse\n"));
948
949   yystate = 0;
950   yyerrstatus = 0;
951   yynerrs = 0;
952   yychar = YYEMPTY;             /* Cause a token to be read.  */
953
954   /* Initialize stack pointers.
955      Waste one element of value and location stack
956      so that they stay on the same level as the state stack.
957      The wasted elements are never initialized.  */
958
959   yyssp = yyss;
960   yyvsp = yyvs;
961
962
963   goto yysetstate;
964
965 /*------------------------------------------------------------.
966 | yynewstate -- Push a new state, which is found in yystate.  |
967 `------------------------------------------------------------*/
968  yynewstate:
969   /* In all cases, when you get here, the value and location stacks
970      have just been pushed. so pushing a state here evens the stacks.
971      */
972   yyssp++;
973
974  yysetstate:
975   *yyssp = yystate;
976
977   if (yyss + yystacksize - 1 <= yyssp)
978     {
979       /* Get the current used size of the three stacks, in elements.  */
980       YYSIZE_T yysize = yyssp - yyss + 1;
981
982 #ifdef yyoverflow
983       {
984         /* Give user a chance to reallocate the stack. Use copies of
985            these so that the &'s don't force the real ones into
986            memory.  */
987         YYSTYPE *yyvs1 = yyvs;
988         short int *yyss1 = yyss;
989
990
991         /* Each stack pointer address is followed by the size of the
992            data in use in that stack, in bytes.  This used to be a
993            conditional around just the two extra args, but that might
994            be undefined if yyoverflow is a macro.  */
995         yyoverflow ("parser stack overflow",
996                     &yyss1, yysize * sizeof (*yyssp),
997                     &yyvs1, yysize * sizeof (*yyvsp),
998
999                     &yystacksize);
1000
1001         yyss = yyss1;
1002         yyvs = yyvs1;
1003       }
1004 #else /* no yyoverflow */
1005 # ifndef YYSTACK_RELOCATE
1006       goto yyoverflowlab;
1007 # else
1008       /* Extend the stack our own way.  */
1009       if (YYMAXDEPTH <= yystacksize)
1010         goto yyoverflowlab;
1011       yystacksize *= 2;
1012       if (YYMAXDEPTH < yystacksize)
1013         yystacksize = YYMAXDEPTH;
1014
1015       {
1016         short int *yyss1 = yyss;
1017         union yyalloc *yyptr =
1018           (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1019         if (! yyptr)
1020           goto yyoverflowlab;
1021         YYSTACK_RELOCATE (yyss);
1022         YYSTACK_RELOCATE (yyvs);
1023
1024 #  undef YYSTACK_RELOCATE
1025         if (yyss1 != yyssa)
1026           YYSTACK_FREE (yyss1);
1027       }
1028 # endif
1029 #endif /* no yyoverflow */
1030
1031       yyssp = yyss + yysize - 1;
1032       yyvsp = yyvs + yysize - 1;
1033
1034
1035       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1036                   (unsigned long int) yystacksize));
1037
1038       if (yyss + yystacksize - 1 <= yyssp)
1039         YYABORT;
1040     }
1041
1042   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1043
1044   goto yybackup;
1045
1046 /*-----------.
1047 | yybackup.  |
1048 `-----------*/
1049 yybackup:
1050
1051 /* Do appropriate processing given the current state.  */
1052 /* Read a lookahead token if we need one and don't already have one.  */
1053 /* yyresume: */
1054
1055   /* First try to decide what to do without reference to lookahead token.  */
1056
1057   yyn = yypact[yystate];
1058   if (yyn == YYPACT_NINF)
1059     goto yydefault;
1060
1061   /* Not known => get a lookahead token if don't already have one.  */
1062
1063   /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
1064   if (yychar == YYEMPTY)
1065     {
1066       YYDPRINTF ((stderr, "Reading a token: "));
1067       yychar = YYLEX;
1068     }
1069
1070   if (yychar <= YYEOF)
1071     {
1072       yychar = yytoken = YYEOF;
1073       YYDPRINTF ((stderr, "Now at end of input.\n"));
1074     }
1075   else
1076     {
1077       yytoken = YYTRANSLATE (yychar);
1078       YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
1079     }
1080
1081   /* If the proper action on seeing token YYTOKEN is to reduce or to
1082      detect an error, take that action.  */
1083   yyn += yytoken;
1084   if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1085     goto yydefault;
1086   yyn = yytable[yyn];
1087   if (yyn <= 0)
1088     {
1089       if (yyn == 0 || yyn == YYTABLE_NINF)
1090         goto yyerrlab;
1091       yyn = -yyn;
1092       goto yyreduce;
1093     }
1094
1095   if (yyn == YYFINAL)
1096     YYACCEPT;
1097
1098   /* Shift the lookahead token.  */
1099   YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
1100
1101   /* Discard the token being shifted unless it is eof.  */
1102   if (yychar != YYEOF)
1103     yychar = YYEMPTY;
1104
1105   *++yyvsp = yylval;
1106
1107
1108   /* Count tokens shifted since error; after three, turn off error
1109      status.  */
1110   if (yyerrstatus)
1111     yyerrstatus--;
1112
1113   yystate = yyn;
1114   goto yynewstate;
1115
1116
1117 /*-----------------------------------------------------------.
1118 | yydefault -- do the default action for the current state.  |
1119 `-----------------------------------------------------------*/
1120 yydefault:
1121   yyn = yydefact[yystate];
1122   if (yyn == 0)
1123     goto yyerrlab;
1124   goto yyreduce;
1125
1126
1127 /*-----------------------------.
1128 | yyreduce -- Do a reduction.  |
1129 `-----------------------------*/
1130 yyreduce:
1131   /* yyn is the number of a rule to reduce with.  */
1132   yylen = yyr2[yyn];
1133
1134   /* If YYLEN is nonzero, implement the default value of the action:
1135      `$$ = $1'.
1136
1137      Otherwise, the following line sets YYVAL to garbage.
1138      This behavior is undocumented and Bison
1139      users should not rely upon it.  Assigning to YYVAL
1140      unconditionally makes the parser a bit smaller, and it avoids a
1141      GCC warning that YYVAL may be used uninitialized.  */
1142   yyval = yyvsp[1-yylen];
1143
1144
1145   YY_REDUCE_PRINT (yyn);
1146   switch (yyn)
1147     {
1148         case 4:
1149 #line 143 "parsedate.y"
1150     {
1151             yyHaveTime++;
1152 #ifdef lint
1153             /* I am compulsive about lint natterings... */
1154             if (yyHaveTime == -1) {
1155                 YYERROR;
1156             }
1157 #endif /* lint */
1158         }
1159     break;
1160
1161   case 5:
1162 #line 152 "parsedate.y"
1163     {
1164             yyHaveTime++;
1165             yyTimezone = yyvsp[0].Number;
1166         }
1167     break;
1168
1169   case 6:
1170 #line 156 "parsedate.y"
1171     {
1172             yyHaveDate++;
1173         }
1174     break;
1175
1176   case 7:
1177 #line 159 "parsedate.y"
1178     {
1179             yyHaveRel = 1;
1180         }
1181     break;
1182
1183   case 8:
1184 #line 164 "parsedate.y"
1185     {
1186             if (yyvsp[-1].Number < 100) {
1187                 yyHour = yyvsp[-1].Number;
1188                 yyMinutes = 0;
1189             }
1190             else {
1191                 yyHour = yyvsp[-1].Number / 100;
1192                 yyMinutes = yyvsp[-1].Number % 100;
1193             }
1194             yySeconds = 0;
1195             yyMeridian = yyvsp[0].Meridian;
1196         }
1197     break;
1198
1199   case 9:
1200 #line 176 "parsedate.y"
1201     {
1202             yyHour = yyvsp[-3].Number;
1203             yyMinutes = yyvsp[-1].Number;
1204             yySeconds = 0;
1205             yyMeridian = yyvsp[0].Meridian;
1206         }
1207     break;
1208
1209   case 10:
1210 #line 182 "parsedate.y"
1211     {
1212             yyHour = yyvsp[-3].Number;
1213             yyMinutes = yyvsp[-1].Number;
1214             yyTimezone = yyvsp[0].Number;
1215             yyMeridian = MER24;
1216             yyDSTmode = DSToff;
1217         }
1218     break;
1219
1220   case 11:
1221 #line 189 "parsedate.y"
1222     {
1223             yyHour = yyvsp[-5].Number;
1224             yyMinutes = yyvsp[-3].Number;
1225             yySeconds = yyvsp[-1].Number;
1226             yyMeridian = yyvsp[0].Meridian;
1227         }
1228     break;
1229
1230   case 12:
1231 #line 195 "parsedate.y"
1232     {
1233             yyHour = yyvsp[-5].Number;
1234             yyMinutes = yyvsp[-3].Number;
1235             yySeconds = yyvsp[-1].Number;
1236             yyTimezone = yyvsp[0].Number;
1237             yyMeridian = MER24;
1238             yyDSTmode = DSToff;
1239         }
1240     break;
1241
1242   case 13:
1243 #line 205 "parsedate.y"
1244     {
1245             yyval.Number = yyvsp[0].Number;
1246             yyDSTmode = DSToff;
1247         }
1248     break;
1249
1250   case 14:
1251 #line 209 "parsedate.y"
1252     {
1253             yyval.Number = yyvsp[0].Number;
1254             yyDSTmode = DSTon;
1255         }
1256     break;
1257
1258   case 15:
1259 #line 213 "parsedate.y"
1260     {
1261             /* Only allow "GMT+300" and "GMT-0800" */
1262             if (yyvsp[-1].Number != 0) {
1263                 YYABORT;
1264             }
1265             yyval.Number = yyvsp[0].Number;
1266             yyDSTmode = DSToff;
1267         }
1268     break;
1269
1270   case 16:
1271 #line 221 "parsedate.y"
1272     {
1273             yyval.Number = yyvsp[0].Number;
1274             yyDSTmode = DSToff;
1275         }
1276     break;
1277
1278   case 17:
1279 #line 227 "parsedate.y"
1280     {
1281             int         i;
1282
1283             /* Unix and GMT and numeric timezones -- a little confusing. */
1284             if (yyvsp[0].Number < 0) {
1285                 /* Don't work with negative modulus. */
1286                 yyvsp[0].Number = -yyvsp[0].Number;
1287                 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1288                     YYABORT;
1289                 }
1290                 yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
1291             }
1292             else {
1293                 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1294                     YYABORT;
1295                 }
1296                 yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
1297             }
1298         }
1299     break;
1300
1301   case 18:
1302 #line 248 "parsedate.y"
1303     {
1304             yyMonth = yyvsp[-2].Number;
1305             yyDay = yyvsp[0].Number;
1306         }
1307     break;
1308
1309   case 19:
1310 #line 252 "parsedate.y"
1311     {
1312             if (yyvsp[-4].Number > 100) {
1313                 yyYear = yyvsp[-4].Number;
1314                 yyMonth = yyvsp[-2].Number;
1315                 yyDay = yyvsp[0].Number;
1316             }
1317             else {
1318                 yyMonth = yyvsp[-4].Number;
1319                 yyDay = yyvsp[-2].Number;
1320                 yyYear = yyvsp[0].Number;
1321             }
1322         }
1323     break;
1324
1325   case 20:
1326 #line 264 "parsedate.y"
1327     {
1328             yyMonth = yyvsp[-1].Number;
1329             yyDay = yyvsp[0].Number;
1330         }
1331     break;
1332
1333   case 21:
1334 #line 268 "parsedate.y"
1335     {
1336             yyMonth = yyvsp[-3].Number;
1337             yyDay = yyvsp[-2].Number;
1338             yyYear = yyvsp[0].Number;
1339         }
1340     break;
1341
1342   case 22:
1343 #line 273 "parsedate.y"
1344     {
1345             yyDay = yyvsp[-1].Number;
1346             yyMonth = yyvsp[0].Number;
1347         }
1348     break;
1349
1350   case 23:
1351 #line 277 "parsedate.y"
1352     {
1353             yyDay = yyvsp[-2].Number;
1354             yyMonth = yyvsp[-1].Number;
1355             yyYear = yyvsp[0].Number;
1356         }
1357     break;
1358
1359   case 24:
1360 #line 282 "parsedate.y"
1361     {
1362             yyDay = yyvsp[-2].Number;
1363             yyMonth = yyvsp[-1].Number;
1364             yyYear = yyvsp[0].Number;
1365         }
1366     break;
1367
1368   case 25:
1369 #line 289 "parsedate.y"
1370     {
1371             yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1372         }
1373     break;
1374
1375   case 26:
1376 #line 292 "parsedate.y"
1377     {
1378             yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1379         }
1380     break;
1381
1382   case 27:
1383 #line 295 "parsedate.y"
1384     {
1385             yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1386         }
1387     break;
1388
1389   case 28:
1390 #line 298 "parsedate.y"
1391     {
1392             yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1393         }
1394     break;
1395
1396   case 29:
1397 #line 303 "parsedate.y"
1398     {
1399             yyval.Meridian = MER24;
1400         }
1401     break;
1402
1403   case 30:
1404 #line 306 "parsedate.y"
1405     {
1406             yyval.Meridian = yyvsp[0].Meridian;
1407         }
1408     break;
1409
1410
1411     }
1412
1413 /* Line 1010 of yacc.c.  */
1414 #line 1415 "y.tab.c"
1415 \f
1416   yyvsp -= yylen;
1417   yyssp -= yylen;
1418
1419
1420   YY_STACK_PRINT (yyss, yyssp);
1421
1422   *++yyvsp = yyval;
1423
1424
1425   /* Now `shift' the result of the reduction.  Determine what state
1426      that goes to, based on the state we popped back to and the rule
1427      number reduced by.  */
1428
1429   yyn = yyr1[yyn];
1430
1431   yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1432   if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1433     yystate = yytable[yystate];
1434   else
1435     yystate = yydefgoto[yyn - YYNTOKENS];
1436
1437   goto yynewstate;
1438
1439
1440 /*------------------------------------.
1441 | yyerrlab -- here on detecting error |
1442 `------------------------------------*/
1443 yyerrlab:
1444   /* If not already recovering from an error, report this error.  */
1445   if (!yyerrstatus)
1446     {
1447       ++yynerrs;
1448 #if YYERROR_VERBOSE
1449       yyn = yypact[yystate];
1450
1451       if (YYPACT_NINF < yyn && yyn < YYLAST)
1452         {
1453           YYSIZE_T yysize = 0;
1454           int yytype = YYTRANSLATE (yychar);
1455           const char* yyprefix;
1456           char *yymsg;
1457           int yyx;
1458
1459           /* Start YYX at -YYN if negative to avoid negative indexes in
1460              YYCHECK.  */
1461           int yyxbegin = yyn < 0 ? -yyn : 0;
1462
1463           /* Stay within bounds of both yycheck and yytname.  */
1464           int yychecklim = YYLAST - yyn;
1465           int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1466           int yycount = 0;
1467
1468           yyprefix = ", expecting ";
1469           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1470             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1471               {
1472                 yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
1473                 yycount += 1;
1474                 if (yycount == 5)
1475                   {
1476                     yysize = 0;
1477                     break;
1478                   }
1479               }
1480           yysize += (sizeof ("syntax error, unexpected ")
1481                      + yystrlen (yytname[yytype]));
1482           yymsg = (char *) YYSTACK_ALLOC (yysize);
1483           if (yymsg != 0)
1484             {
1485               char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
1486               yyp = yystpcpy (yyp, yytname[yytype]);
1487
1488               if (yycount < 5)
1489                 {
1490                   yyprefix = ", expecting ";
1491                   for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1492                     if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1493                       {
1494                         yyp = yystpcpy (yyp, yyprefix);
1495                         yyp = yystpcpy (yyp, yytname[yyx]);
1496                         yyprefix = " or ";
1497                       }
1498                 }
1499               yyerror (yymsg);
1500               YYSTACK_FREE (yymsg);
1501             }
1502           else
1503             yyerror ("syntax error; also virtual memory exhausted");
1504         }
1505       else
1506 #endif /* YYERROR_VERBOSE */
1507         yyerror ("syntax error");
1508     }
1509
1510
1511
1512   if (yyerrstatus == 3)
1513     {
1514       /* If just tried and failed to reuse lookahead token after an
1515          error, discard it.  */
1516
1517       if (yychar <= YYEOF)
1518         {
1519           /* If at end of input, pop the error token,
1520              then the rest of the stack, then return failure.  */
1521           if (yychar == YYEOF)
1522              for (;;)
1523                {
1524                  YYPOPSTACK;
1525                  if (yyssp == yyss)
1526                    YYABORT;
1527                  YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
1528                  yydestruct (yystos[*yyssp], yyvsp);
1529                }
1530         }
1531       else
1532         {
1533           YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
1534           yydestruct (yytoken, &yylval);
1535           yychar = YYEMPTY;
1536
1537         }
1538     }
1539
1540   /* Else will try to reuse lookahead token after shifting the error
1541      token.  */
1542   goto yyerrlab1;
1543
1544
1545 /*---------------------------------------------------.
1546 | yyerrorlab -- error raised explicitly by YYERROR.  |
1547 `---------------------------------------------------*/
1548 yyerrorlab:
1549
1550 #ifdef __GNUC__
1551   /* Pacify GCC when the user code never invokes YYERROR and the label
1552      yyerrorlab therefore never appears in user code.  */
1553   if (0)
1554      goto yyerrorlab;
1555 #endif
1556
1557   yyvsp -= yylen;
1558   yyssp -= yylen;
1559   yystate = *yyssp;
1560   goto yyerrlab1;
1561
1562
1563 /*-------------------------------------------------------------.
1564 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
1565 `-------------------------------------------------------------*/
1566 yyerrlab1:
1567   yyerrstatus = 3;      /* Each real token shifted decrements this.  */
1568
1569   for (;;)
1570     {
1571       yyn = yypact[yystate];
1572       if (yyn != YYPACT_NINF)
1573         {
1574           yyn += YYTERROR;
1575           if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1576             {
1577               yyn = yytable[yyn];
1578               if (0 < yyn)
1579                 break;
1580             }
1581         }
1582
1583       /* Pop the current state because it cannot handle the error token.  */
1584       if (yyssp == yyss)
1585         YYABORT;
1586
1587       YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
1588       yydestruct (yystos[yystate], yyvsp);
1589       YYPOPSTACK;
1590       yystate = *yyssp;
1591       YY_STACK_PRINT (yyss, yyssp);
1592     }
1593
1594   if (yyn == YYFINAL)
1595     YYACCEPT;
1596
1597   YYDPRINTF ((stderr, "Shifting error token, "));
1598
1599   *++yyvsp = yylval;
1600
1601
1602   yystate = yyn;
1603   goto yynewstate;
1604
1605
1606 /*-------------------------------------.
1607 | yyacceptlab -- YYACCEPT comes here.  |
1608 `-------------------------------------*/
1609 yyacceptlab:
1610   yyresult = 0;
1611   goto yyreturn;
1612
1613 /*-----------------------------------.
1614 | yyabortlab -- YYABORT comes here.  |
1615 `-----------------------------------*/
1616 yyabortlab:
1617   yyresult = 1;
1618   goto yyreturn;
1619
1620 #ifndef yyoverflow
1621 /*----------------------------------------------.
1622 | yyoverflowlab -- parser overflow comes here.  |
1623 `----------------------------------------------*/
1624 yyoverflowlab:
1625   yyerror ("parser stack overflow");
1626   yyresult = 2;
1627   /* Fall through.  */
1628 #endif
1629
1630 yyreturn:
1631 #ifndef yyoverflow
1632   if (yyss != yyssa)
1633     YYSTACK_FREE (yyss);
1634 #endif
1635   return yyresult;
1636 }
1637
1638
1639 #line 311 "parsedate.y"
1640
1641
1642 /* Month and day table. */
1643 static TABLE    MonthDayTable[] = {
1644     { "january",        tMONTH,  1 },
1645     { "february",       tMONTH,  2 },
1646     { "march",          tMONTH,  3 },
1647     { "april",          tMONTH,  4 },
1648     { "may",            tMONTH,  5 },
1649     { "june",           tMONTH,  6 },
1650     { "july",           tMONTH,  7 },
1651     { "august",         tMONTH,  8 },
1652     { "september",      tMONTH,  9 },
1653     { "october",        tMONTH, 10 },
1654     { "november",       tMONTH, 11 },
1655     { "december",       tMONTH, 12 },
1656         /* The value of the day isn't used... */
1657     { "sunday",         tDAY, 0 },
1658     { "monday",         tDAY, 0 },
1659     { "tuesday",        tDAY, 0 },
1660     { "wednesday",      tDAY, 0 },
1661     { "thursday",       tDAY, 0 },
1662     { "friday",         tDAY, 0 },
1663     { "saturday",       tDAY, 0 },
1664 };
1665
1666 /* Time units table. */
1667 static TABLE    UnitsTable[] = {
1668     { "year",           tMONTH_UNIT,    12 },
1669     { "month",          tMONTH_UNIT,    1 },
1670     { "week",           tSEC_UNIT,      7L * 24 * 60 * 60 },
1671     { "day",            tSEC_UNIT,      1L * 24 * 60 * 60 },
1672     { "hour",           tSEC_UNIT,      60 * 60 },
1673     { "minute",         tSEC_UNIT,      60 },
1674     { "min",            tSEC_UNIT,      60 },
1675     { "second",         tSEC_UNIT,      1 },
1676     { "sec",            tSEC_UNIT,      1 },
1677 };
1678
1679 /* Timezone table. */
1680 static TABLE    TimezoneTable[] = {
1681     { "gmt",    tZONE,     HOUR( 0) },  /* Greenwich Mean */
1682     { "ut",     tZONE,     HOUR( 0) },  /* Universal */
1683     { "utc",    tZONE,     HOUR( 0) },  /* Universal Coordinated */
1684     { "cut",    tZONE,     HOUR( 0) },  /* Coordinated Universal */
1685     { "z",      tZONE,     HOUR( 0) },  /* Greenwich Mean */
1686     { "wet",    tZONE,     HOUR( 0) },  /* Western European */
1687     { "bst",    tDAYZONE,  HOUR( 0) },  /* British Summer */
1688     { "nst",    tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
1689     { "ndt",    tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
1690     { "ast",    tZONE,     HOUR( 4) },  /* Atlantic Standard */
1691     { "adt",    tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
1692     { "est",    tZONE,     HOUR( 5) },  /* Eastern Standard */
1693     { "edt",    tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
1694     { "cst",    tZONE,     HOUR( 6) },  /* Central Standard */
1695     { "cdt",    tDAYZONE,  HOUR( 6) },  /* Central Daylight */
1696     { "mst",    tZONE,     HOUR( 7) },  /* Mountain Standard */
1697     { "mdt",    tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
1698     { "pst",    tZONE,     HOUR( 8) },  /* Pacific Standard */
1699     { "pdt",    tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
1700     { "yst",    tZONE,     HOUR( 9) },  /* Yukon Standard */
1701     { "ydt",    tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
1702     { "akst",   tZONE,     HOUR( 9) },  /* Alaska Standard */
1703     { "akdt",   tDAYZONE,  HOUR( 9) },  /* Alaska Daylight */
1704     { "hst",    tZONE,     HOUR(10) },  /* Hawaii Standard */
1705     { "hast",   tZONE,     HOUR(10) },  /* Hawaii-Aleutian Standard */
1706     { "hadt",   tDAYZONE,  HOUR(10) },  /* Hawaii-Aleutian Daylight */
1707     { "ces",    tDAYZONE,  -HOUR(1) },  /* Central European Summer */
1708     { "cest",   tDAYZONE,  -HOUR(1) },  /* Central European Summer */
1709     { "mez",    tZONE,     -HOUR(1) },  /* Middle European */
1710     { "mezt",   tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
1711     { "cet",    tZONE,     -HOUR(1) },  /* Central European */
1712     { "met",    tZONE,     -HOUR(1) },  /* Middle European */
1713     { "eet",    tZONE,     -HOUR(2) },  /* Eastern Europe */
1714     { "msk",    tZONE,     -HOUR(3) },  /* Moscow Winter */
1715     { "msd",    tDAYZONE,  -HOUR(3) },  /* Moscow Summer */
1716     { "wast",   tZONE,     -HOUR(8) },  /* West Australian Standard */
1717     { "wadt",   tDAYZONE,  -HOUR(8) },  /* West Australian Daylight */
1718     { "hkt",    tZONE,     -HOUR(8) },  /* Hong Kong */
1719     { "cct",    tZONE,     -HOUR(8) },  /* China Coast */
1720     { "jst",    tZONE,     -HOUR(9) },  /* Japan Standard */
1721     { "kst",    tZONE,     -HOUR(9) },  /* Korean Standard */
1722     { "kdt",    tZONE,     -HOUR(9) },  /* Korean Daylight */
1723     { "cast",   tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
1724     { "cadt",   tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
1725     { "east",   tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
1726     { "eadt",   tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
1727     { "nzst",   tZONE,     -HOUR(12) }, /* New Zealand Standard */
1728     { "nzdt",   tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
1729
1730     /* For completeness we include the following entries. */
1731 #if 0
1732
1733     /* Duplicate names.  Either they conflict with a zone listed above
1734      * (which is either more likely to be seen or just been in circulation
1735      * longer), or they conflict with another zone in this section and
1736      * we could not reasonably choose one over the other. */
1737     { "fst",    tZONE,     HOUR( 2) },  /* Fernando De Noronha Standard */
1738     { "fdt",    tDAYZONE,  HOUR( 2) },  /* Fernando De Noronha Daylight */
1739     { "bst",    tZONE,     HOUR( 3) },  /* Brazil Standard */
1740     { "est",    tZONE,     HOUR( 3) },  /* Eastern Standard (Brazil) */
1741     { "edt",    tDAYZONE,  HOUR( 3) },  /* Eastern Daylight (Brazil) */
1742     { "wst",    tZONE,     HOUR( 4) },  /* Western Standard (Brazil) */
1743     { "wdt",    tDAYZONE,  HOUR( 4) },  /* Western Daylight (Brazil) */
1744     { "cst",    tZONE,     HOUR( 5) },  /* Chile Standard */
1745     { "cdt",    tDAYZONE,  HOUR( 5) },  /* Chile Daylight */
1746     { "ast",    tZONE,     HOUR( 5) },  /* Acre Standard */
1747     { "adt",    tDAYZONE,  HOUR( 5) },  /* Acre Daylight */
1748     { "cst",    tZONE,     HOUR( 5) },  /* Cuba Standard */
1749     { "cdt",    tDAYZONE,  HOUR( 5) },  /* Cuba Daylight */
1750     { "est",    tZONE,     HOUR( 6) },  /* Easter Island Standard */
1751     { "edt",    tDAYZONE,  HOUR( 6) },  /* Easter Island Daylight */
1752     { "sst",    tZONE,     HOUR(11) },  /* Samoa Standard */
1753     { "ist",    tZONE,     -HOUR(2) },  /* Israel Standard */
1754     { "idt",    tDAYZONE,  -HOUR(2) },  /* Israel Daylight */
1755     { "idt",    tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
1756     { "ist",    tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
1757     { "cst",     tZONE,     -HOUR(8) }, /* China Standard */
1758     { "cdt",     tDAYZONE,  -HOUR(8) }, /* China Daylight */
1759     { "sst",     tZONE,     -HOUR(8) }, /* Singapore Standard */
1760
1761     /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
1762     { "gst",    tZONE,     HOUR( 3) },  /* Greenland Standard */
1763     { "wat",    tZONE,     -HOUR(1) },  /* West Africa */
1764     { "at",     tZONE,     HOUR( 2) },  /* Azores */
1765     { "gst",    tZONE,     -HOUR(10) }, /* Guam Standard */
1766     { "nft",    tZONE,     HOUR(3)+30 }, /* Newfoundland */
1767     { "idlw",   tZONE,     HOUR(12) },  /* International Date Line West */
1768     { "mewt",   tZONE,     -HOUR(1) },  /* Middle European Winter */
1769     { "mest",   tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
1770     { "swt",    tZONE,     -HOUR(1) },  /* Swedish Winter */
1771     { "sst",    tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
1772     { "fwt",    tZONE,     -HOUR(1) },  /* French Winter */
1773     { "fst",    tDAYZONE,  -HOUR(1) },  /* French Summer */
1774     { "bt",     tZONE,     -HOUR(3) },  /* Baghdad */
1775     { "it",     tZONE,     -(HOUR(3)+30) }, /* Iran */
1776     { "zp4",    tZONE,     -HOUR(4) },  /* USSR Zone 3 */
1777     { "zp5",    tZONE,     -HOUR(5) },  /* USSR Zone 4 */
1778     { "ist",    tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
1779     { "zp6",    tZONE,     -HOUR(6) },  /* USSR Zone 5 */
1780     { "nst",    tZONE,     -HOUR(7) },  /* North Sumatra */
1781     { "sst",    tZONE,     -HOUR(7) },  /* South Sumatra */
1782     { "jt",     tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
1783     { "nzt",    tZONE,     -HOUR(12) }, /* New Zealand */
1784     { "idle",   tZONE,     -HOUR(12) }, /* International Date Line East */
1785     { "cat",    tZONE,     HOUR(10) },  /* -- expired 1967 */
1786     { "nt",     tZONE,     HOUR(11) },  /* -- expired 1967 */
1787     { "ahst",   tZONE,     HOUR(10) },  /* -- expired 1983 */
1788     { "hdt",    tDAYZONE,  HOUR(10) },  /* -- expired 1986 */
1789 #endif /* 0 */
1790 };
1791
1792
1793 /* ARGSUSED */
1794 static void
1795 date_error(char *s)
1796 {
1797     /* NOTREACHED */
1798 }
1799
1800
1801 static time_t
1802 ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
1803 {
1804     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
1805         return -1;
1806     if (Meridian == MER24) {
1807         if (Hours < 0 || Hours > 23)
1808             return -1;
1809     }
1810     else {
1811         if (Hours < 1 || Hours > 12)
1812             return -1;
1813         if (Hours == 12)
1814             Hours = 0;
1815         if (Meridian == MERpm)
1816             Hours += 12;
1817     }
1818     return (Hours * 60L + Minutes) * 60L + Seconds;
1819 }
1820
1821
1822 static time_t
1823 Convert(time_t Month, time_t Day, time_t Year,
1824         time_t Hours, time_t Minutes, time_t Seconds,
1825         MERIDIAN Meridian, DSTMODE dst)
1826 {
1827     static int  DaysNormal[13] = {
1828         0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1829     };
1830     static int  DaysLeap[13] = {
1831         0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1832     };
1833     static int  LeapYears[] = {
1834         1972, 1976, 1980, 1984, 1988, 1992, 1996,
1835         2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
1836     };
1837     register int        *yp;
1838     register int        *mp;
1839     register time_t     Julian;
1840     register int        i;
1841     time_t              tod;
1842
1843     if (Year < 0)
1844         Year = -Year;
1845     if (Year < 100)
1846         Year += 1900;
1847     if (Year < EPOCH)
1848         Year += 100;
1849     for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
1850         if (Year == *yp) {
1851             mp = DaysLeap;
1852             break;
1853         }
1854     if (Year < EPOCH || Year > END_OF_TIME
1855      || Month < 1 || Month > 12
1856      /* NOSTRICT *//* conversion from long may lose accuracy */
1857      || Day < 1 || Day > mp[(int)Month])
1858         return -1;
1859
1860     Julian = Day - 1 + (Year - EPOCH) * 365;
1861     for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
1862         if (Year <= *yp)
1863             break;
1864     for (i = 1; i < Month; i++)
1865         Julian += *++mp;
1866     Julian *= SECSPERDAY;
1867     Julian += yyTimezone * 60L;
1868     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
1869         return -1;
1870     Julian += tod;
1871     tod = Julian;
1872     if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
1873         Julian -= DST_OFFSET * 60L * 60L;
1874     return Julian;
1875 }
1876
1877
1878 static time_t
1879 DSTcorrect(time_t Start, time_t Future)
1880 {
1881     time_t      StartDay;
1882     time_t      FutureDay;
1883
1884     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
1885     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
1886     return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
1887 }
1888
1889
1890 static time_t
1891 RelativeMonth(time_t Start, time_t RelMonth)
1892 {
1893     struct tm   *tm;
1894     time_t      Month;
1895     time_t      Year;
1896
1897     tm = localtime(&Start);
1898     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
1899     Year = Month / 12;
1900     Month = Month % 12 + 1;
1901     return DSTcorrect(Start,
1902             Convert(Month, (time_t)tm->tm_mday, Year,
1903                 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
1904                 MER24, DSTmaybe));
1905 }
1906
1907
1908 static int
1909 LookupWord(char *buff, register int length)
1910 {
1911     register char       *p;
1912     register char       *q;
1913     register TABLE      *tp;
1914     register int        c;
1915
1916     p = buff;
1917     c = p[0];
1918
1919     /* See if we have an abbreviation for a month. */
1920     if (length == 3 || (length == 4 && p[3] == '.'))
1921         for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
1922             q = tp->name;
1923             if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
1924                 yylval.Number = tp->value;
1925                 return tp->type;
1926             }
1927         }
1928     else
1929         for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
1930             if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1931                 yylval.Number = tp->value;
1932                 return tp->type;
1933             }
1934
1935     /* Try for a timezone. */
1936     for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1937         if (c == tp->name[0] && p[1] == tp->name[1]
1938          && strcmp(p, tp->name) == 0) {
1939             yylval.Number = tp->value;
1940             return tp->type;
1941         }
1942
1943     /* Try the units table. */
1944     for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1945         if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1946             yylval.Number = tp->value;
1947             return tp->type;
1948         }
1949
1950     /* Strip off any plural and try the units table again. */
1951     if (--length > 0 && p[length] == 's') {
1952         p[length] = '\0';
1953         for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1954             if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1955                 p[length] = 's';
1956                 yylval.Number = tp->value;
1957                 return tp->type;
1958             }
1959         p[length] = 's';
1960     }
1961     length++;
1962
1963     /* Drop out any periods. */
1964     for (p = buff, q = (char*)buff; *q; q++)
1965         if (*q != '.')
1966             *p++ = *q;
1967     *p = '\0';
1968
1969     /* Try the meridians. */
1970     if (buff[1] == 'm' && buff[2] == '\0') {
1971         if (buff[0] == 'a') {
1972             yylval.Meridian = MERam;
1973             return tMERIDIAN;
1974         }
1975         if (buff[0] == 'p') {
1976             yylval.Meridian = MERpm;
1977             return tMERIDIAN;
1978         }
1979     }
1980
1981     /* If we saw any periods, try the timezones again. */
1982     if (p - buff != length) {
1983         c = buff[0];
1984         for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1985             if (c == tp->name[0] && p[1] == tp->name[1]
1986             && strcmp(p, tp->name) == 0) {
1987                 yylval.Number = tp->value;
1988                 return tp->type;
1989             }
1990     }
1991
1992     /* Unknown word -- assume GMT timezone. */
1993     yylval.Number = 0;
1994     return tZONE;
1995 }
1996
1997
1998 int
1999 date_lex(void)
2000 {
2001     register char       c;
2002     register char       *p;
2003     char                buff[20];
2004     register int        sign;
2005     register int        i;
2006     register int        nesting;
2007
2008     for ( ; ; ) {
2009         /* Get first character after the whitespace. */
2010         for ( ; ; ) {
2011             while (isspace(*yyInput))
2012                 yyInput++;
2013             c = *yyInput;
2014
2015             /* Ignore RFC 822 comments, typically time zone names. */
2016             if (c != LPAREN)
2017                 break;
2018             for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
2019                 if (c == LPAREN)
2020                     nesting++;
2021                 else if (!IS7BIT(c) || c == '\0' || c == '\r'
2022                      || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
2023                     /* Lexical error: bad comment. */
2024                     return '?';
2025             yyInput++;
2026         }
2027
2028         /* A number? */
2029         if (isdigit(c) || c == '-' || c == '+') {
2030             if (c == '-' || c == '+') {
2031                 sign = c == '-' ? -1 : 1;
2032                 yyInput++;
2033                 if (!isdigit(*yyInput))
2034                     /* Skip the plus or minus sign. */
2035                     continue;
2036             }
2037             else
2038                 sign = 0;
2039             for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
2040                 i = 10 * i + c - '0';
2041             yyInput--;
2042             yylval.Number = sign < 0 ? -i : i;
2043             return sign ? tSNUMBER : tUNUMBER;
2044         }
2045
2046         /* A word? */
2047         if (isalpha(c)) {
2048             for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
2049                 if (p < &buff[sizeof buff - 1])
2050                     *p++ = isupper(c) ? tolower(c) : c;
2051             *p = '\0';
2052             yyInput--;
2053             return LookupWord(buff, p - buff);
2054         }
2055
2056         return *yyInput++;
2057     }
2058 }
2059
2060
2061 time_t
2062 parsedate(char *p)
2063 {
2064     extern int          date_parse(void);
2065     time_t              Start;
2066
2067     yyInput = p;
2068
2069     yyYear = 0;
2070     yyMonth = 0;
2071     yyDay = 0;
2072     yyTimezone = 0;
2073     yyDSTmode = DSTmaybe;
2074     yyHour = 0;
2075     yyMinutes = 0;
2076     yySeconds = 0;
2077     yyMeridian = MER24;
2078     yyRelSeconds = 0;
2079     yyRelMonth = 0;
2080     yyHaveDate = 0;
2081     yyHaveRel = 0;
2082     yyHaveTime = 0;
2083
2084     if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
2085         return -1;
2086
2087     if (yyHaveDate || yyHaveTime) {
2088         Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
2089                     yyMeridian, yyDSTmode);
2090         if (Start < 0)
2091             return -1;
2092     }
2093     else
2094         return -1;
2095
2096     Start += yyRelSeconds;
2097     if (yyRelMonth)
2098         Start += RelativeMonth(Start, yyRelMonth);
2099
2100     /* Have to do *something* with a legitimate -1 so it's distinguishable
2101      * from the error return value.  (Alternately could set errno on error.) */
2102     return Start == -1 ? 0 : Start;
2103 }
2104
2105
2106 #ifdef TEST
2107
2108 #if YYDEBUG
2109 extern int      yydebug;
2110 #endif /* YYDEBUG */
2111
2112 /* ARGSUSED */
2113 int
2114 main(int ac, char *av[])
2115 {
2116     char        buff[128];
2117     time_t      d;
2118
2119 #if YYDEBUG
2120     yydebug = 1;
2121 #endif /* YYDEBUG */
2122
2123     (void)printf("Enter date, or blank line to exit.\n\t> ");
2124     for ( ; ; ) {
2125         (void)printf("\t> ");
2126         (void)fflush(stdout);
2127         if (fgets(buff, sizeof buff, stdin) == NULL || buff[0] == '\n')
2128             break;
2129 #if YYDEBUG
2130         if (strcmp(buff, "yydebug") == 0) {
2131             yydebug = !yydebug;
2132             printf("yydebug = %s\n", yydebug ? "on" : "off");
2133             continue;
2134         }
2135 #endif /* YYDEBUG */
2136         d = parsedate(buff, (TIMEINFO *)NULL);
2137         if (d == -1)
2138             (void)printf("Bad format - couldn't convert.\n");
2139         else
2140             (void)printf("%s", ctime(&d));
2141     }
2142
2143     exit(0);
2144     /* NOTREACHED */
2145 }
2146 #endif /* TEST */
2147
2148