1 
2 /*  A Bison parser, made from parsedate.y
3     by GNU Bison version 1.28  */
4 
5 #define YYBISON 1  /* Identify Bison output.  */
6 
7 #define	tDAY	257
8 #define	tDAYZONE	258
9 #define	tMERIDIAN	259
10 #define	tMONTH	260
11 #define	tMONTH_UNIT	261
12 #define	tSEC_UNIT	262
13 #define	tSNUMBER	263
14 #define	tUNUMBER	264
15 #define	tZONE	265
16 #define	tDST	266
17 
18 #line 1 "parsedate.y"
19 
20 /*:ts=8*/
21 /*****************************************************************************
22  * FIDOGATE --- Gateway UNIX Mail/News <-> FIDO NetMail/EchoMail
23  *
24  * $Id: parsedate.c,v 4.3 2000/10/18 21:53:57 mj Exp $
25  *
26  * parsedate() date/time parser. Taken from ifmail 1.7 / inn 1.4 and
27  * adopted for FIDOGATE. Added DST from old getdate.y.
28  *
29  *****************************************************************************/
30 /* Original %Revision: 1.13 %
31 **
32 **  Originally written by Steven M. Bellovin <smb@research.att.com> while
33 **  at the University of North Carolina at Chapel Hill.  Later tweaked by
34 **  a couple of people on Usenet.  Completely overhauled by Rich $alz
35 **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
36 **  Further revised (removed obsolete constructs and cleaned up timezone
37 **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
38 **  helped in September, 1992.
39 **
40 **  This grammar has six shift/reduce conflicts.
41 **
42 **  This code is in the public domain and has no copyright.
43 */
44 /* SUPPRESS 530 *//* Empty body for statement */
45 /* SUPPRESS 593 on yyerrlab *//* Label was not used */
46 /* SUPPRESS 593 on yynewstate *//* Label was not used */
47 /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
48 
49 #include "fidogate.h"
50 
51 #include <sys/time.h>
52 
53 /* Stuff from inn configdata.h */
54 #if defined(__STDC__)
55 typedef char const  *STRING;
56 typedef char * const    CSTRING;
57 #else
58 typedef char        *STRING;
59 typedef char        *CSTRING;
60 #endif  /* defined(__STDC__) */
61 
62 #define CTYPE(isXXXXX, c)   ((isascii((c)) && isXXXXX((c))))
63 
64 /* Stuff from inn macros.h */
65 #define SIZEOF(array)  ((int)(sizeof array / sizeof array[0]))
66 #define ENDOF(array)   (&array[SIZEOF(array)])
67 
68 
69 
70 #define yyparse		date_parse
71 #define yylex		date_lex
72 #define yyerror		date_error
73 
74 static int date_lex(void);
75 
76 
77 
78     /* See the LeapYears table in Convert. */
79 #define EPOCH		1970
80 #define END_OF_TIME	2038
81     /* Constants for general time calculations. */
82 #define DST_OFFSET	1
83 #define SECSPERDAY	(24L * 60L * 60L)
84     /* Readability for TABLE stuff. */
85 #define HOUR(x)		(x * 60)
86 
87 #define LPAREN		'('
88 #define RPAREN		')'
89 #define IS7BIT(x)	((unsigned int)(x) < 0200)
90 
91 
92 /*
93 **  An entry in the lexical lookup table.
94 */
95 typedef struct _TABLE {
96     STRING	name;
97     int		type;
98     time_t	value;
99 } TABLE;
100 
101 /*
102 **  Daylight-savings mode:  on, off, or not yet known.
103 */
104 typedef enum _DSTMODE {
105     DSTon, DSToff, DSTmaybe
106 } DSTMODE;
107 
108 /*
109 **  Meridian:  am, pm, or 24-hour style.
110 */
111 typedef enum _MERIDIAN {
112     MERam, MERpm, MER24
113 } MERIDIAN;
114 
115 
116 /*
117 **  Global variables.  We could get rid of most of them by using a yacc
118 **  union, but this is more efficient.  (This routine predates the
119 **  yacc %union construct.)
120 */
121 static char	*yyInput;
122 static DSTMODE	yyDSTmode;
123 static int	yyHaveDate;
124 static int	yyHaveRel;
125 static int	yyHaveTime;
126 static time_t	yyTimezone;
127 static time_t	yyDay;
128 static time_t	yyHour;
129 static time_t	yyMinutes;
130 static time_t	yyMonth;
131 static time_t	yySeconds;
132 static time_t	yyYear;
133 static MERIDIAN	yyMeridian;
134 static time_t	yyRelMonth;
135 static time_t	yyRelSeconds;
136 
137 
138 extern struct tm	*localtime(const time_t *);
139 
140 static void		date_error(char *s);
141 
142 #line 125 "parsedate.y"
143 typedef union {
144     time_t		Number;
145     enum _MERIDIAN	Meridian;
146 } YYSTYPE;
147 #include <stdio.h>
148 
149 #ifndef __cplusplus
150 #ifndef __STDC__
151 #define const
152 #endif
153 #endif
154 
155 
156 
157 #define	YYFINAL		48
158 #define	YYFLAG		-32768
159 #define	YYNTBASE	16
160 
161 #define YYTRANSLATE(x) ((unsigned)(x) <= 266 ? yytranslate[x] : 24)
162 
163 static const char yytranslate[] = {     0,
164      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
165      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
166      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
167      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
168      2,     2,     2,    15,     2,     2,    14,     2,     2,     2,
169      2,     2,     2,     2,     2,     2,     2,    13,     2,     2,
170      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
171      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
172      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
173      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
174      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
175      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
176      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
177      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
178      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
179      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
180      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
181      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
182      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
183      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
184      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
185      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
186      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
187      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
188      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
189      2,     2,     2,     2,     2,     1,     3,     4,     5,     6,
190      7,     8,     9,    10,    11,    12
191 };
192 
193 #if YYDEBUG != 0
194 static const short yyprhs[] = {     0,
195      0,     1,     4,     6,     9,    11,    13,    16,    21,    26,
196     33,    40,    42,    44,    47,    50,    52,    54,    58,    64,
197     67,    72,    75,    79,    85,    90,    93,    96,    99,   102,
198    103
199 };
200 
201 static const short yyrhs[] = {    -1,
202     16,    17,     0,    18,     0,    18,    19,     0,    21,     0,
203     22,     0,    10,    23,     0,    10,    13,    10,    23,     0,
204     10,    13,    10,    20,     0,    10,    13,    10,    13,    10,
205     23,     0,    10,    13,    10,    13,    10,    20,     0,    11,
206      0,     4,     0,    11,    12,     0,    11,    20,     0,    20,
207      0,     9,     0,    10,    14,    10,     0,    10,    14,    10,
208     14,    10,     0,     6,    10,     0,     6,    10,    15,    10,
209      0,    10,     6,     0,    10,     6,    10,     0,     3,    15,
210     10,     6,    10,     0,     3,    10,     6,    10,     0,     9,
211      8,     0,    10,     8,     0,     9,     7,     0,    10,     7,
212      0,     0,     5,     0
213 };
214 
215 #endif
216 
217 #if YYDEBUG != 0
218 static const short yyrline[] = { 0,
219    139,   140,   143,   152,   156,   159,   164,   176,   182,   189,
220    195,   205,   209,   213,   217,   225,   231,   252,   256,   268,
221    272,   277,   281,   286,   291,   298,   301,   304,   307,   312,
222    315
223 };
224 #endif
225 
226 
227 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
228 
229 static const char * const yytname[] = {   "$","error","$undefined.","tDAY","tDAYZONE",
230 "tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
231 "tDST","':'","'/'","','","spec","item","time","zone","numzone","date","rel",
232 "o_merid", NULL
233 };
234 #endif
235 
236 static const short yyr1[] = {     0,
237     16,    16,    17,    17,    17,    17,    18,    18,    18,    18,
238     18,    19,    19,    19,    19,    19,    20,    21,    21,    21,
239     21,    21,    21,    21,    21,    22,    22,    22,    22,    23,
240     23
241 };
242 
243 static const short yyr2[] = {     0,
244      0,     2,     1,     2,     1,     1,     2,     4,     4,     6,
245      6,     1,     1,     2,     2,     1,     1,     3,     5,     2,
246      4,     2,     3,     5,     4,     2,     2,     2,     2,     0,
247      1
248 };
249 
250 static const short yydefact[] = {     1,
251      0,     0,     0,     0,    30,     2,     3,     5,     6,     0,
252      0,    20,    28,    26,    31,    22,    29,    27,     0,     0,
253      7,    13,    17,    12,     4,    16,     0,     0,     0,    23,
254     30,    18,    14,    15,    25,     0,    21,     0,     9,     8,
255      0,    24,    30,    19,    11,    10,     0,     0
256 };
257 
258 static const short yydefgoto[] = {     1,
259      6,     7,    25,    26,     8,     9,    21
260 };
261 
262 static const short yypact[] = {-32768,
263      2,    -6,    -7,    26,     9,-32768,    21,-32768,-32768,    12,
264     11,    16,-32768,-32768,-32768,    25,-32768,-32768,    27,    28,
265 -32768,-32768,-32768,    17,-32768,-32768,    29,    30,    31,-32768,
266     15,    13,-32768,-32768,-32768,    32,-32768,    33,-32768,-32768,
267     34,-32768,     1,-32768,-32768,-32768,    40,-32768
268 };
269 
270 static const short yypgoto[] = {-32768,
271 -32768,-32768,-32768,   -24,-32768,-32768,   -30
272 };
273 
274 
275 #define	YYLAST		44
276 
277 
278 static const short yytable[] = {    34,
279     40,    47,    12,    10,     2,    15,    39,     3,    11,    23,
280      4,     5,    46,    15,    16,    17,    18,    27,    45,    15,
281     28,    19,    20,    23,    22,    23,    41,    38,    33,    23,
282     29,    24,    13,    14,    30,    36,    31,    32,    35,    48,
283     37,    42,    43,    44
284 };
285 
286 static const short yycheck[] = {    24,
287     31,     0,    10,    10,     3,     5,    31,     6,    15,     9,
288      9,    10,    43,     5,     6,     7,     8,     6,    43,     5,
289     10,    13,    14,     9,     4,     9,    14,    13,    12,     9,
290     15,    11,     7,     8,    10,     6,    10,    10,    10,     0,
291     10,    10,    10,    10
292 };
293 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
294 #line 3 "/usr/lib/bison.simple"
295 /* This file comes from bison-1.28.  */
296 
297 /* Skeleton output parser for bison,
298    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
299 
300    This program is free software; you can redistribute it and/or modify
301    it under the terms of the GNU General Public License as published by
302    the Free Software Foundation; either version 2, or (at your option)
303    any later version.
304 
305    This program is distributed in the hope that it will be useful,
306    but WITHOUT ANY WARRANTY; without even the implied warranty of
307    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
308    GNU General Public License for more details.
309 
310    You should have received a copy of the GNU General Public License
311    along with this program; if not, write to the Free Software
312    Foundation, Inc., 59 Temple Place - Suite 330,
313    Boston, MA 02111-1307, USA.  */
314 
315 /* As a special exception, when this file is copied by Bison into a
316    Bison output file, you may use that output file without restriction.
317    This special exception was added by the Free Software Foundation
318    in version 1.24 of Bison.  */
319 
320 /* This is the parser code that is written into each bison parser
321   when the %semantic_parser declaration is not specified in the grammar.
322   It was written by Richard Stallman by simplifying the hairy parser
323   used when %semantic_parser is specified.  */
324 
325 #ifndef YYSTACK_USE_ALLOCA
326 #ifdef alloca
327 #define YYSTACK_USE_ALLOCA
328 #else /* alloca not defined */
329 #ifdef __GNUC__
330 #define YYSTACK_USE_ALLOCA
331 #define alloca __builtin_alloca
332 #else /* not GNU C.  */
333 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
334 #define YYSTACK_USE_ALLOCA
335 #include <alloca.h>
336 #else /* not sparc */
337 /* We think this test detects Watcom and Microsoft C.  */
338 /* This used to test MSDOS, but that is a bad idea
339    since that symbol is in the user namespace.  */
340 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
341 #if 0 /* No need for malloc.h, which pollutes the namespace;
342 	 instead, just don't use alloca.  */
343 #include <malloc.h>
344 #endif
345 #else /* not MSDOS, or __TURBOC__ */
346 #if defined(_AIX)
347 /* I don't know what this was needed for, but it pollutes the namespace.
348    So I turned it off.   rms, 2 May 1997.  */
349 /* #include <malloc.h>  */
350  #pragma alloca
351 #define YYSTACK_USE_ALLOCA
352 #else /* not MSDOS, or __TURBOC__, or _AIX */
353 #if 0
354 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
355 		 and on HPUX 10.  Eventually we can turn this on.  */
356 #define YYSTACK_USE_ALLOCA
357 #define alloca __builtin_alloca
358 #endif /* __hpux */
359 #endif
360 #endif /* not _AIX */
361 #endif /* not MSDOS, or __TURBOC__ */
362 #endif /* not sparc */
363 #endif /* not GNU C */
364 #endif /* alloca not defined */
365 #endif /* YYSTACK_USE_ALLOCA not defined */
366 
367 #ifdef YYSTACK_USE_ALLOCA
368 #define YYSTACK_ALLOC alloca
369 #else
370 #define YYSTACK_ALLOC malloc
371 #endif
372 
373 /* Note: there must be only one dollar sign in this file.
374    It is replaced by the list of actions, each action
375    as one case of the switch.  */
376 
377 #define yyerrok		(yyerrstatus = 0)
378 #define yyclearin	(yychar = YYEMPTY)
379 #define YYEMPTY		-2
380 #define YYEOF		0
381 #define YYACCEPT	goto yyacceptlab
382 #define YYABORT 	goto yyabortlab
383 #define YYERROR		goto yyerrlab1
384 /* Like YYERROR except do call yyerror.
385    This remains here temporarily to ease the
386    transition to the new meaning of YYERROR, for GCC.
387    Once GCC version 2 has supplanted version 1, this can go.  */
388 #define YYFAIL		goto yyerrlab
389 #define YYRECOVERING()  (!!yyerrstatus)
390 #define YYBACKUP(token, value) \
391 do								\
392   if (yychar == YYEMPTY && yylen == 1)				\
393     { yychar = (token), yylval = (value);			\
394       yychar1 = YYTRANSLATE (yychar);				\
395       YYPOPSTACK;						\
396       goto yybackup;						\
397     }								\
398   else								\
399     { yyerror ("syntax error: cannot back up"); YYERROR; }	\
400 while (0)
401 
402 #define YYTERROR	1
403 #define YYERRCODE	256
404 
405 #ifndef YYPURE
406 #define YYLEX		yylex()
407 #endif
408 
409 #ifdef YYPURE
410 #ifdef YYLSP_NEEDED
411 #ifdef YYLEX_PARAM
412 #define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
413 #else
414 #define YYLEX		yylex(&yylval, &yylloc)
415 #endif
416 #else /* not YYLSP_NEEDED */
417 #ifdef YYLEX_PARAM
418 #define YYLEX		yylex(&yylval, YYLEX_PARAM)
419 #else
420 #define YYLEX		yylex(&yylval)
421 #endif
422 #endif /* not YYLSP_NEEDED */
423 #endif
424 
425 /* If nonreentrant, generate the variables here */
426 
427 #ifndef YYPURE
428 
429 int	yychar;			/*  the lookahead symbol		*/
430 YYSTYPE	yylval;			/*  the semantic value of the		*/
431 				/*  lookahead symbol			*/
432 
433 #ifdef YYLSP_NEEDED
434 YYLTYPE yylloc;			/*  location data for the lookahead	*/
435 				/*  symbol				*/
436 #endif
437 
438 int yynerrs;			/*  number of parse errors so far       */
439 #endif  /* not YYPURE */
440 
441 #if YYDEBUG != 0
442 int yydebug;			/*  nonzero means print parse trace	*/
443 /* Since this is uninitialized, it does not stop multiple parsers
444    from coexisting.  */
445 #endif
446 
447 /*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
448 
449 #ifndef	YYINITDEPTH
450 #define YYINITDEPTH 200
451 #endif
452 
453 /*  YYMAXDEPTH is the maximum size the stacks can grow to
454     (effective only if the built-in stack extension method is used).  */
455 
456 #if YYMAXDEPTH == 0
457 #undef YYMAXDEPTH
458 #endif
459 
460 #ifndef YYMAXDEPTH
461 #define YYMAXDEPTH 10000
462 #endif
463 
464 /* Define __yy_memcpy.  Note that the size argument
465    should be passed with type unsigned int, because that is what the non-GCC
466    definitions require.  With GCC, __builtin_memcpy takes an arg
467    of type size_t, but it can handle unsigned int.  */
468 
469 #if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
470 #define __yy_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
471 #else				/* not GNU C or C++ */
472 #ifndef __cplusplus
473 
474 /* This is the most reliable way to avoid incompatibilities
475    in available built-in functions on various systems.  */
476 static void
__yy_memcpy(to,from,count)477 __yy_memcpy (to, from, count)
478      char *to;
479      char *from;
480      unsigned int count;
481 {
482   register char *f = from;
483   register char *t = to;
484   register int i = count;
485 
486   while (i-- > 0)
487     *t++ = *f++;
488 }
489 
490 #else /* __cplusplus */
491 
492 /* This is the most reliable way to avoid incompatibilities
493    in available built-in functions on various systems.  */
494 static void
__yy_memcpy(char * to,char * from,unsigned int count)495 __yy_memcpy (char *to, char *from, unsigned int count)
496 {
497   register char *t = to;
498   register char *f = from;
499   register int i = count;
500 
501   while (i-- > 0)
502     *t++ = *f++;
503 }
504 
505 #endif
506 #endif
507 
508 #line 217 "/usr/lib/bison.simple"
509 
510 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
511    into yyparse.  The argument should have type void *.
512    It should actually point to an object.
513    Grammar actions can access the variable by casting it
514    to the proper pointer type.  */
515 
516 #ifdef YYPARSE_PARAM
517 #ifdef __cplusplus
518 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
519 #define YYPARSE_PARAM_DECL
520 #else /* not __cplusplus */
521 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
522 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
523 #endif /* not __cplusplus */
524 #else /* not YYPARSE_PARAM */
525 #define YYPARSE_PARAM_ARG
526 #define YYPARSE_PARAM_DECL
527 #endif /* not YYPARSE_PARAM */
528 
529 /* Prevent warning if -Wstrict-prototypes.  */
530 #ifdef __GNUC__
531 #ifdef YYPARSE_PARAM
532 int yyparse (void *);
533 #else
534 int yyparse (void);
535 #endif
536 #endif
537 
538 int
yyparse(YYPARSE_PARAM_ARG)539 yyparse(YYPARSE_PARAM_ARG)
540      YYPARSE_PARAM_DECL
541 {
542   register int yystate;
543   register int yyn;
544   register short *yyssp;
545   register YYSTYPE *yyvsp;
546   int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
547   int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
548 
549   short	yyssa[YYINITDEPTH];	/*  the state stack			*/
550   YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
551 
552   short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
553   YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
554 
555 #ifdef YYLSP_NEEDED
556   YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
557   YYLTYPE *yyls = yylsa;
558   YYLTYPE *yylsp;
559 
560 #define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
561 #else
562 #define YYPOPSTACK   (yyvsp--, yyssp--)
563 #endif
564 
565   int yystacksize = YYINITDEPTH;
566   int yyfree_stacks = 0;
567 
568 #ifdef YYPURE
569   int yychar;
570   YYSTYPE yylval;
571   int yynerrs;
572 #ifdef YYLSP_NEEDED
573   YYLTYPE yylloc;
574 #endif
575 #endif
576 
577   YYSTYPE yyval;		/*  the variable used to return		*/
578 				/*  semantic values from the action	*/
579 				/*  routines				*/
580 
581   int yylen;
582 
583 #if YYDEBUG != 0
584   if (yydebug)
585     fprintf(stderr, "Starting parse\n");
586 #endif
587 
588   yystate = 0;
589   yyerrstatus = 0;
590   yynerrs = 0;
591   yychar = YYEMPTY;		/* Cause a token to be read.  */
592 
593   /* Initialize stack pointers.
594      Waste one element of value and location stack
595      so that they stay on the same level as the state stack.
596      The wasted elements are never initialized.  */
597 
598   yyssp = yyss - 1;
599   yyvsp = yyvs;
600 #ifdef YYLSP_NEEDED
601   yylsp = yyls;
602 #endif
603 
604 /* Push a new state, which is found in  yystate  .  */
605 /* In all cases, when you get here, the value and location stacks
606    have just been pushed. so pushing a state here evens the stacks.  */
607 yynewstate:
608 
609   *++yyssp = yystate;
610 
611   if (yyssp >= yyss + yystacksize - 1)
612     {
613       /* Give user a chance to reallocate the stack */
614       /* Use copies of these so that the &'s don't force the real ones into memory. */
615       YYSTYPE *yyvs1 = yyvs;
616       short *yyss1 = yyss;
617 #ifdef YYLSP_NEEDED
618       YYLTYPE *yyls1 = yyls;
619 #endif
620 
621       /* Get the current used size of the three stacks, in elements.  */
622       int size = yyssp - yyss + 1;
623 
624 #ifdef yyoverflow
625       /* Each stack pointer address is followed by the size of
626 	 the data in use in that stack, in bytes.  */
627 #ifdef YYLSP_NEEDED
628       /* This used to be a conditional around just the two extra args,
629 	 but that might be undefined if yyoverflow is a macro.  */
630       yyoverflow("parser stack overflow",
631 		 &yyss1, size * sizeof (*yyssp),
632 		 &yyvs1, size * sizeof (*yyvsp),
633 		 &yyls1, size * sizeof (*yylsp),
634 		 &yystacksize);
635 #else
636       yyoverflow("parser stack overflow",
637 		 &yyss1, size * sizeof (*yyssp),
638 		 &yyvs1, size * sizeof (*yyvsp),
639 		 &yystacksize);
640 #endif
641 
642       yyss = yyss1; yyvs = yyvs1;
643 #ifdef YYLSP_NEEDED
644       yyls = yyls1;
645 #endif
646 #else /* no yyoverflow */
647       /* Extend the stack our own way.  */
648       if (yystacksize >= YYMAXDEPTH)
649 	{
650 	  yyerror("parser stack overflow");
651 	  if (yyfree_stacks)
652 	    {
653 	      free (yyss);
654 	      free (yyvs);
655 #ifdef YYLSP_NEEDED
656 	      free (yyls);
657 #endif
658 	    }
659 	  return 2;
660 	}
661       yystacksize *= 2;
662       if (yystacksize > YYMAXDEPTH)
663 	yystacksize = YYMAXDEPTH;
664 #ifndef YYSTACK_USE_ALLOCA
665       yyfree_stacks = 1;
666 #endif
667       yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
668       __yy_memcpy ((char *)yyss, (char *)yyss1,
669 		   size * (unsigned int) sizeof (*yyssp));
670       yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
671       __yy_memcpy ((char *)yyvs, (char *)yyvs1,
672 		   size * (unsigned int) sizeof (*yyvsp));
673 #ifdef YYLSP_NEEDED
674       yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
675       __yy_memcpy ((char *)yyls, (char *)yyls1,
676 		   size * (unsigned int) sizeof (*yylsp));
677 #endif
678 #endif /* no yyoverflow */
679 
680       yyssp = yyss + size - 1;
681       yyvsp = yyvs + size - 1;
682 #ifdef YYLSP_NEEDED
683       yylsp = yyls + size - 1;
684 #endif
685 
686 #if YYDEBUG != 0
687       if (yydebug)
688 	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
689 #endif
690 
691       if (yyssp >= yyss + yystacksize - 1)
692 	YYABORT;
693     }
694 
695 #if YYDEBUG != 0
696   if (yydebug)
697     fprintf(stderr, "Entering state %d\n", yystate);
698 #endif
699 
700   goto yybackup;
701  yybackup:
702 
703 /* Do appropriate processing given the current state.  */
704 /* Read a lookahead token if we need one and don't already have one.  */
705 /* yyresume: */
706 
707   /* First try to decide what to do without reference to lookahead token.  */
708 
709   yyn = yypact[yystate];
710   if (yyn == YYFLAG)
711     goto yydefault;
712 
713   /* Not known => get a lookahead token if don't already have one.  */
714 
715   /* yychar is either YYEMPTY or YYEOF
716      or a valid token in external form.  */
717 
718   if (yychar == YYEMPTY)
719     {
720 #if YYDEBUG != 0
721       if (yydebug)
722 	fprintf(stderr, "Reading a token: ");
723 #endif
724       yychar = YYLEX;
725     }
726 
727   /* Convert token to internal form (in yychar1) for indexing tables with */
728 
729   if (yychar <= 0)		/* This means end of input. */
730     {
731       yychar1 = 0;
732       yychar = YYEOF;		/* Don't call YYLEX any more */
733 
734 #if YYDEBUG != 0
735       if (yydebug)
736 	fprintf(stderr, "Now at end of input.\n");
737 #endif
738     }
739   else
740     {
741       yychar1 = YYTRANSLATE(yychar);
742 
743 #if YYDEBUG != 0
744       if (yydebug)
745 	{
746 	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
747 	  /* Give the individual parser a way to print the precise meaning
748 	     of a token, for further debugging info.  */
749 #ifdef YYPRINT
750 	  YYPRINT (stderr, yychar, yylval);
751 #endif
752 	  fprintf (stderr, ")\n");
753 	}
754 #endif
755     }
756 
757   yyn += yychar1;
758   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
759     goto yydefault;
760 
761   yyn = yytable[yyn];
762 
763   /* yyn is what to do for this token type in this state.
764      Negative => reduce, -yyn is rule number.
765      Positive => shift, yyn is new state.
766        New state is final state => don't bother to shift,
767        just return success.
768      0, or most negative number => error.  */
769 
770   if (yyn < 0)
771     {
772       if (yyn == YYFLAG)
773 	goto yyerrlab;
774       yyn = -yyn;
775       goto yyreduce;
776     }
777   else if (yyn == 0)
778     goto yyerrlab;
779 
780   if (yyn == YYFINAL)
781     YYACCEPT;
782 
783   /* Shift the lookahead token.  */
784 
785 #if YYDEBUG != 0
786   if (yydebug)
787     fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
788 #endif
789 
790   /* Discard the token being shifted unless it is eof.  */
791   if (yychar != YYEOF)
792     yychar = YYEMPTY;
793 
794   *++yyvsp = yylval;
795 #ifdef YYLSP_NEEDED
796   *++yylsp = yylloc;
797 #endif
798 
799   /* count tokens shifted since error; after three, turn off error status.  */
800   if (yyerrstatus) yyerrstatus--;
801 
802   yystate = yyn;
803   goto yynewstate;
804 
805 /* Do the default action for the current state.  */
806 yydefault:
807 
808   yyn = yydefact[yystate];
809   if (yyn == 0)
810     goto yyerrlab;
811 
812 /* Do a reduction.  yyn is the number of a rule to reduce with.  */
813 yyreduce:
814   yylen = yyr2[yyn];
815   if (yylen > 0)
816     yyval = yyvsp[1-yylen]; /* implement default value of the action */
817 
818 #if YYDEBUG != 0
819   if (yydebug)
820     {
821       int i;
822 
823       fprintf (stderr, "Reducing via rule %d (line %d), ",
824 	       yyn, yyrline[yyn]);
825 
826       /* Print the symbols being reduced, and their result.  */
827       for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
828 	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
829       fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
830     }
831 #endif
832 
833 
834   switch (yyn) {
835 
836 case 3:
837 #line 143 "parsedate.y"
838 {
839 	    yyHaveTime++;
840 #if	defined(lint)
841 	    /* I am compulsive about lint natterings... */
842 	    if (yyHaveTime == -1) {
843 		YYERROR;
844 	    }
845 #endif	/* defined(lint) */
846 	;
847     break;}
848 case 4:
849 #line 152 "parsedate.y"
850 {
851 	    yyHaveTime++;
852 	    yyTimezone = yyvsp[0].Number;
853 	;
854     break;}
855 case 5:
856 #line 156 "parsedate.y"
857 {
858 	    yyHaveDate++;
859 	;
860     break;}
861 case 6:
862 #line 159 "parsedate.y"
863 {
864 	    yyHaveRel = 1;
865 	;
866     break;}
867 case 7:
868 #line 164 "parsedate.y"
869 {
870 	    if (yyvsp[-1].Number < 100) {
871 		yyHour = yyvsp[-1].Number;
872 		yyMinutes = 0;
873 	    }
874 	    else {
875 		yyHour = yyvsp[-1].Number / 100;
876 		yyMinutes = yyvsp[-1].Number % 100;
877 	    }
878 	    yySeconds = 0;
879 	    yyMeridian = yyvsp[0].Meridian;
880 	;
881     break;}
882 case 8:
883 #line 176 "parsedate.y"
884 {
885 	    yyHour = yyvsp[-3].Number;
886 	    yyMinutes = yyvsp[-1].Number;
887 	    yySeconds = 0;
888 	    yyMeridian = yyvsp[0].Meridian;
889 	;
890     break;}
891 case 9:
892 #line 182 "parsedate.y"
893 {
894 	    yyHour = yyvsp[-3].Number;
895 	    yyMinutes = yyvsp[-1].Number;
896 	    yyTimezone = yyvsp[0].Number;
897 	    yyMeridian = MER24;
898 	    yyDSTmode = DSToff;
899 	;
900     break;}
901 case 10:
902 #line 189 "parsedate.y"
903 {
904 	    yyHour = yyvsp[-5].Number;
905 	    yyMinutes = yyvsp[-3].Number;
906 	    yySeconds = yyvsp[-1].Number;
907 	    yyMeridian = yyvsp[0].Meridian;
908 	;
909     break;}
910 case 11:
911 #line 195 "parsedate.y"
912 {
913 	    yyHour = yyvsp[-5].Number;
914 	    yyMinutes = yyvsp[-3].Number;
915 	    yySeconds = yyvsp[-1].Number;
916 	    yyTimezone = yyvsp[0].Number;
917 	    yyMeridian = MER24;
918 	    yyDSTmode = DSToff;
919 	;
920     break;}
921 case 12:
922 #line 205 "parsedate.y"
923 {
924 	    yyval.Number = yyvsp[0].Number;
925 	    yyDSTmode = DSToff;
926 	;
927     break;}
928 case 13:
929 #line 209 "parsedate.y"
930 {
931 	    yyval.Number = yyvsp[0].Number;
932 	    yyDSTmode = DSTon;
933 	;
934     break;}
935 case 14:
936 #line 213 "parsedate.y"
937 {
938 	    yyTimezone = yyvsp[-1].Number;
939 	    yyDSTmode = DSTon;
940 	;
941     break;}
942 case 15:
943 #line 217 "parsedate.y"
944 {
945 	    /* Only allow "GMT+300" and "GMT-0800" */
946 	    if (yyvsp[-1].Number != 0) {
947 		YYABORT;
948 	    }
949 	    yyval.Number = yyvsp[0].Number;
950 	    yyDSTmode = DSToff;
951 	;
952     break;}
953 case 16:
954 #line 225 "parsedate.y"
955 {
956 	    yyval.Number = yyvsp[0].Number;
957 	    yyDSTmode = DSToff;
958 	;
959     break;}
960 case 17:
961 #line 231 "parsedate.y"
962 {
963 	    int		i;
964 
965 	    /* Unix and GMT and numeric timezones -- a little confusing. */
966 	    if (yyvsp[0].Number < 0) {
967 		/* Don't work with negative modulus. */
968 		yyvsp[0].Number = -yyvsp[0].Number;
969 		if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
970 		    YYABORT;
971 		}
972 		yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
973 	    }
974 	    else {
975 		if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
976 		    YYABORT;
977 		}
978 		yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
979 	    }
980 	;
981     break;}
982 case 18:
983 #line 252 "parsedate.y"
984 {
985 	    yyMonth = yyvsp[-2].Number;
986 	    yyDay = yyvsp[0].Number;
987 	;
988     break;}
989 case 19:
990 #line 256 "parsedate.y"
991 {
992 	    if (yyvsp[-4].Number > 100) {
993 		yyYear = yyvsp[-4].Number;
994 		yyMonth = yyvsp[-2].Number;
995 		yyDay = yyvsp[0].Number;
996 	    }
997 	    else {
998 		yyMonth = yyvsp[-4].Number;
999 		yyDay = yyvsp[-2].Number;
1000 		yyYear = yyvsp[0].Number;
1001 	    }
1002 	;
1003     break;}
1004 case 20:
1005 #line 268 "parsedate.y"
1006 {
1007 	    yyMonth = yyvsp[-1].Number;
1008 	    yyDay = yyvsp[0].Number;
1009 	;
1010     break;}
1011 case 21:
1012 #line 272 "parsedate.y"
1013 {
1014 	    yyMonth = yyvsp[-3].Number;
1015 	    yyDay = yyvsp[-2].Number;
1016 	    yyYear = yyvsp[0].Number;
1017 	;
1018     break;}
1019 case 22:
1020 #line 277 "parsedate.y"
1021 {
1022 	    yyDay = yyvsp[-1].Number;
1023 	    yyMonth = yyvsp[0].Number;
1024 	;
1025     break;}
1026 case 23:
1027 #line 281 "parsedate.y"
1028 {
1029 	    yyDay = yyvsp[-2].Number;
1030 	    yyMonth = yyvsp[-1].Number;
1031 	    yyYear = yyvsp[0].Number;
1032 	;
1033     break;}
1034 case 24:
1035 #line 286 "parsedate.y"
1036 {
1037 	    yyDay = yyvsp[-2].Number;
1038 	    yyMonth = yyvsp[-1].Number;
1039 	    yyYear = yyvsp[0].Number;
1040 	;
1041     break;}
1042 case 25:
1043 #line 291 "parsedate.y"
1044 {
1045 	    yyDay = yyvsp[-2].Number;
1046 	    yyMonth = yyvsp[-1].Number;
1047 	    yyYear = yyvsp[0].Number;
1048 	;
1049     break;}
1050 case 26:
1051 #line 298 "parsedate.y"
1052 {
1053 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1054 	;
1055     break;}
1056 case 27:
1057 #line 301 "parsedate.y"
1058 {
1059 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1060 	;
1061     break;}
1062 case 28:
1063 #line 304 "parsedate.y"
1064 {
1065 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1066 	;
1067     break;}
1068 case 29:
1069 #line 307 "parsedate.y"
1070 {
1071 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1072 	;
1073     break;}
1074 case 30:
1075 #line 312 "parsedate.y"
1076 {
1077 	    yyval.Meridian = MER24;
1078 	;
1079     break;}
1080 case 31:
1081 #line 315 "parsedate.y"
1082 {
1083 	    yyval.Meridian = yyvsp[0].Meridian;
1084 	;
1085     break;}
1086 }
1087    /* the action file gets copied in in place of this dollarsign */
1088 #line 543 "/usr/lib/bison.simple"
1089 
1090   yyvsp -= yylen;
1091   yyssp -= yylen;
1092 #ifdef YYLSP_NEEDED
1093   yylsp -= yylen;
1094 #endif
1095 
1096 #if YYDEBUG != 0
1097   if (yydebug)
1098     {
1099       short *ssp1 = yyss - 1;
1100       fprintf (stderr, "state stack now");
1101       while (ssp1 != yyssp)
1102 	fprintf (stderr, " %d", *++ssp1);
1103       fprintf (stderr, "\n");
1104     }
1105 #endif
1106 
1107   *++yyvsp = yyval;
1108 
1109 #ifdef YYLSP_NEEDED
1110   yylsp++;
1111   if (yylen == 0)
1112     {
1113       yylsp->first_line = yylloc.first_line;
1114       yylsp->first_column = yylloc.first_column;
1115       yylsp->last_line = (yylsp-1)->last_line;
1116       yylsp->last_column = (yylsp-1)->last_column;
1117       yylsp->text = 0;
1118     }
1119   else
1120     {
1121       yylsp->last_line = (yylsp+yylen-1)->last_line;
1122       yylsp->last_column = (yylsp+yylen-1)->last_column;
1123     }
1124 #endif
1125 
1126   /* Now "shift" the result of the reduction.
1127      Determine what state that goes to,
1128      based on the state we popped back to
1129      and the rule number reduced by.  */
1130 
1131   yyn = yyr1[yyn];
1132 
1133   yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1134   if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1135     yystate = yytable[yystate];
1136   else
1137     yystate = yydefgoto[yyn - YYNTBASE];
1138 
1139   goto yynewstate;
1140 
1141 yyerrlab:   /* here on detecting error */
1142 
1143   if (! yyerrstatus)
1144     /* If not already recovering from an error, report this error.  */
1145     {
1146       ++yynerrs;
1147 
1148 #ifdef YYERROR_VERBOSE
1149       yyn = yypact[yystate];
1150 
1151       if (yyn > YYFLAG && yyn < YYLAST)
1152 	{
1153 	  int size = 0;
1154 	  char *msg;
1155 	  int x, count;
1156 
1157 	  count = 0;
1158 	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
1159 	  for (x = (yyn < 0 ? -yyn : 0);
1160 	       x < (sizeof(yytname) / sizeof(char *)); x++)
1161 	    if (yycheck[x + yyn] == x)
1162 	      size += strlen(yytname[x]) + 15, count++;
1163 	  msg = (char *) malloc(size + 15);
1164 	  if (msg != 0)
1165 	    {
1166 	      strcpy(msg, "parse error");
1167 
1168 	      if (count < 5)
1169 		{
1170 		  count = 0;
1171 		  for (x = (yyn < 0 ? -yyn : 0);
1172 		       x < (sizeof(yytname) / sizeof(char *)); x++)
1173 		    if (yycheck[x + yyn] == x)
1174 		      {
1175 			strcat(msg, count == 0 ? ", expecting `" : " or `");
1176 			strcat(msg, yytname[x]);
1177 			strcat(msg, "'");
1178 			count++;
1179 		      }
1180 		}
1181 	      yyerror(msg);
1182 	      free(msg);
1183 	    }
1184 	  else
1185 	    yyerror ("parse error; also virtual memory exceeded");
1186 	}
1187       else
1188 #endif /* YYERROR_VERBOSE */
1189 	yyerror("parse error");
1190     }
1191 
1192   goto yyerrlab1;
1193 yyerrlab1:   /* here on error raised explicitly by an action */
1194 
1195   if (yyerrstatus == 3)
1196     {
1197       /* if just tried and failed to reuse lookahead token after an error, discard it.  */
1198 
1199       /* return failure if at end of input */
1200       if (yychar == YYEOF)
1201 	YYABORT;
1202 
1203 #if YYDEBUG != 0
1204       if (yydebug)
1205 	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1206 #endif
1207 
1208       yychar = YYEMPTY;
1209     }
1210 
1211   /* Else will try to reuse lookahead token
1212      after shifting the error token.  */
1213 
1214   yyerrstatus = 3;		/* Each real token shifted decrements this */
1215 
1216   goto yyerrhandle;
1217 
1218 yyerrdefault:  /* current state does not do anything special for the error token. */
1219 
1220 #if 0
1221   /* This is wrong; only states that explicitly want error tokens
1222      should shift them.  */
1223   yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
1224   if (yyn) goto yydefault;
1225 #endif
1226 
1227 yyerrpop:   /* pop the current state because it cannot handle the error token */
1228 
1229   if (yyssp == yyss) YYABORT;
1230   yyvsp--;
1231   yystate = *--yyssp;
1232 #ifdef YYLSP_NEEDED
1233   yylsp--;
1234 #endif
1235 
1236 #if YYDEBUG != 0
1237   if (yydebug)
1238     {
1239       short *ssp1 = yyss - 1;
1240       fprintf (stderr, "Error: state stack now");
1241       while (ssp1 != yyssp)
1242 	fprintf (stderr, " %d", *++ssp1);
1243       fprintf (stderr, "\n");
1244     }
1245 #endif
1246 
1247 yyerrhandle:
1248 
1249   yyn = yypact[yystate];
1250   if (yyn == YYFLAG)
1251     goto yyerrdefault;
1252 
1253   yyn += YYTERROR;
1254   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1255     goto yyerrdefault;
1256 
1257   yyn = yytable[yyn];
1258   if (yyn < 0)
1259     {
1260       if (yyn == YYFLAG)
1261 	goto yyerrpop;
1262       yyn = -yyn;
1263       goto yyreduce;
1264     }
1265   else if (yyn == 0)
1266     goto yyerrpop;
1267 
1268   if (yyn == YYFINAL)
1269     YYACCEPT;
1270 
1271 #if YYDEBUG != 0
1272   if (yydebug)
1273     fprintf(stderr, "Shifting error token, ");
1274 #endif
1275 
1276   *++yyvsp = yylval;
1277 #ifdef YYLSP_NEEDED
1278   *++yylsp = yylloc;
1279 #endif
1280 
1281   yystate = yyn;
1282   goto yynewstate;
1283 
1284  yyacceptlab:
1285   /* YYACCEPT comes here.  */
1286   if (yyfree_stacks)
1287     {
1288       free (yyss);
1289       free (yyvs);
1290 #ifdef YYLSP_NEEDED
1291       free (yyls);
1292 #endif
1293     }
1294   return 0;
1295 
1296  yyabortlab:
1297   /* YYABORT comes here.  */
1298   if (yyfree_stacks)
1299     {
1300       free (yyss);
1301       free (yyvs);
1302 #ifdef YYLSP_NEEDED
1303       free (yyls);
1304 #endif
1305     }
1306   return 1;
1307 }
1308 #line 320 "parsedate.y"
1309 
1310 
1311 /* Month and day table. */
1312 static TABLE	MonthDayTable[] = {
1313     { "january",	tMONTH,  1 },
1314     { "february",	tMONTH,  2 },
1315     { "march",		tMONTH,  3 },
1316     { "april",		tMONTH,  4 },
1317     { "may",		tMONTH,  5 },
1318     { "june",		tMONTH,  6 },
1319     { "july",		tMONTH,  7 },
1320     { "august",		tMONTH,  8 },
1321     { "september",	tMONTH,  9 },
1322     { "october",	tMONTH, 10 },
1323     { "november",	tMONTH, 11 },
1324     { "december",	tMONTH, 12 },
1325 	/* The value of the day isn't used... */
1326     { "sunday",		tDAY, 0 },
1327     { "monday",		tDAY, 0 },
1328     { "tuesday",	tDAY, 0 },
1329     { "wednesday",	tDAY, 0 },
1330     { "thursday",	tDAY, 0 },
1331     { "friday",		tDAY, 0 },
1332     { "saturday",	tDAY, 0 },
1333 };
1334 
1335 /* Time units table. */
1336 static TABLE	UnitsTable[] = {
1337     { "year",		tMONTH_UNIT,	12 },
1338     { "month",		tMONTH_UNIT,	1 },
1339     { "week",		tSEC_UNIT,	7 * 24 * 60 * 60 },
1340     { "day",		tSEC_UNIT,	1 * 24 * 60 * 60 },
1341     { "hour",		tSEC_UNIT,	60 * 60 },
1342     { "minute",		tSEC_UNIT,	60 },
1343     { "min",		tSEC_UNIT,	60 },
1344     { "second",		tSEC_UNIT,	1 },
1345     { "sec",		tSEC_UNIT,	1 },
1346 };
1347 
1348 /* Timezone table. */
1349 static TABLE	TimezoneTable[] = {
1350     { "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
1351     { "ut",	tZONE,     HOUR( 0) },	/* Universal */
1352     { "utc",	tZONE,     HOUR( 0) },	/* Universal Coordinated */
1353     { "cut",	tZONE,     HOUR( 0) },	/* Coordinated Universal */
1354     { "z",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
1355     { "wet",	tZONE,     HOUR( 0) },	/* Western European */
1356     { "bst",	tDAYZONE,  HOUR( 0) },	/* British Summer */
1357     { "nst",	tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
1358     { "ndt",	tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
1359     { "ast",	tZONE,     HOUR( 4) },	/* Atlantic Standard */
1360     { "adt",	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
1361     { "est",	tZONE,     HOUR( 5) },	/* Eastern Standard */
1362     { "edt",	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
1363     { "cst",	tZONE,     HOUR( 6) },	/* Central Standard */
1364     { "cdt",	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
1365     { "mst",	tZONE,     HOUR( 7) },	/* Mountain Standard */
1366     { "mdt",	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
1367     { "pst",	tZONE,     HOUR( 8) },	/* Pacific Standard */
1368     { "pdt",	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
1369     { "yst",	tZONE,     HOUR( 9) },	/* Yukon Standard */
1370     { "ydt",	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
1371     { "akst",	tZONE,     HOUR( 9) },	/* Alaska Standard */
1372     { "akdt",	tDAYZONE,  HOUR( 9) },	/* Alaska Daylight */
1373     { "hst",	tZONE,     HOUR(10) },	/* Hawaii Standard */
1374     { "hast",	tZONE,     HOUR(10) },	/* Hawaii-Aleutian Standard */
1375     { "hadt",	tDAYZONE,  HOUR(10) },	/* Hawaii-Aleutian Daylight */
1376     { "ces",	tDAYZONE,  -HOUR(1) },	/* Central European Summer */
1377     { "cest",	tDAYZONE,  -HOUR(1) },	/* Central European Summer */
1378     { "mez",	tZONE,     -HOUR(1) },	/* Middle European */
1379     { "mezt",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1380     { "cet",	tZONE,     -HOUR(1) },	/* Central European */
1381     { "met",	tZONE,     -HOUR(1) },	/* Middle European */
1382 /* Additional aliases for MET / MET DST *************************************/
1383     { "mez",	tZONE,     -HOUR(1) },	/* Middle European */
1384     { "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
1385     { "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1386     { "mes",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1387     { "mesz",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1388     { "msz",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1389     { "metdst",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1390 /****************************************************************************/
1391     { "eet",	tZONE,     -HOUR(2) },	/* Eastern Europe */
1392     { "msk",	tZONE,     -HOUR(3) },	/* Moscow Winter */
1393     { "msd",	tDAYZONE,  -HOUR(3) },	/* Moscow Summer */
1394     { "wast",	tZONE,     -HOUR(8) },	/* West Australian Standard */
1395     { "wadt",	tDAYZONE,  -HOUR(8) },	/* West Australian Daylight */
1396     { "hkt",	tZONE,     -HOUR(8) },	/* Hong Kong */
1397     { "cct",	tZONE,     -HOUR(8) },	/* China Coast */
1398     { "jst",	tZONE,     -HOUR(9) },	/* Japan Standard */
1399     { "kst",	tZONE,     -HOUR(9) },	/* Korean Standard */
1400     { "kdt",	tZONE,     -HOUR(9) },	/* Korean Daylight */
1401     { "cast",	tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
1402     { "cadt",	tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
1403     { "east",	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
1404     { "eadt",	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
1405     { "nzst",	tZONE,     -HOUR(12) },	/* New Zealand Standard */
1406     { "nzdt",	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
1407 
1408     /* For completeness we include the following entries. */
1409 #if	0
1410 
1411     /* Duplicate names.  Either they conflict with a zone listed above
1412      * (which is either more likely to be seen or just been in circulation
1413      * longer), or they conflict with another zone in this section and
1414      * we could not reasonably choose one over the other. */
1415     { "fst",	tZONE,     HOUR( 2) },	/* Fernando De Noronha Standard */
1416     { "fdt",	tDAYZONE,  HOUR( 2) },	/* Fernando De Noronha Daylight */
1417     { "bst",	tZONE,     HOUR( 3) },	/* Brazil Standard */
1418     { "est",	tZONE,     HOUR( 3) },	/* Eastern Standard (Brazil) */
1419     { "edt",	tDAYZONE,  HOUR( 3) },	/* Eastern Daylight (Brazil) */
1420     { "wst",	tZONE,     HOUR( 4) },	/* Western Standard (Brazil) */
1421     { "wdt",	tDAYZONE,  HOUR( 4) },	/* Western Daylight (Brazil) */
1422     { "cst",	tZONE,     HOUR( 5) },	/* Chile Standard */
1423     { "cdt",	tDAYZONE,  HOUR( 5) },	/* Chile Daylight */
1424     { "ast",	tZONE,     HOUR( 5) },	/* Acre Standard */
1425     { "adt",	tDAYZONE,  HOUR( 5) },	/* Acre Daylight */
1426     { "cst",	tZONE,     HOUR( 5) },	/* Cuba Standard */
1427     { "cdt",	tDAYZONE,  HOUR( 5) },	/* Cuba Daylight */
1428     { "est",	tZONE,     HOUR( 6) },	/* Easter Island Standard */
1429     { "edt",	tDAYZONE,  HOUR( 6) },	/* Easter Island Daylight */
1430     { "sst",	tZONE,     HOUR(11) },	/* Samoa Standard */
1431     { "ist",	tZONE,     -HOUR(2) },	/* Israel Standard */
1432     { "idt",	tDAYZONE,  -HOUR(2) },	/* Israel Daylight */
1433     { "idt",	tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
1434     { "ist",	tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
1435     { "cst",	 tZONE,     -HOUR(8) },	/* China Standard */
1436     { "cdt",	 tDAYZONE,  -HOUR(8) },	/* China Daylight */
1437     { "sst",	 tZONE,     -HOUR(8) },	/* Singapore Standard */
1438 
1439     /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
1440     { "gst",	tZONE,     HOUR( 3) },	/* Greenland Standard */
1441     { "wat",	tZONE,     -HOUR(1) },	/* West Africa */
1442     { "at",	tZONE,     HOUR( 2) },	/* Azores */
1443     { "gst",	tZONE,     -HOUR(10) },	/* Guam Standard */
1444     { "nft",	tZONE,     HOUR(3)+30 }, /* Newfoundland */
1445     { "idlw",	tZONE,     HOUR(12) },	/* International Date Line West */
1446     { "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
1447     { "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
1448     { "swt",	tZONE,     -HOUR(1) },	/* Swedish Winter */
1449     { "sst",	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
1450     { "fwt",	tZONE,     -HOUR(1) },	/* French Winter */
1451     { "fst",	tDAYZONE,  -HOUR(1) },	/* French Summer */
1452     { "bt",	tZONE,     -HOUR(3) },	/* Baghdad */
1453     { "it",	tZONE,     -(HOUR(3)+30) }, /* Iran */
1454     { "zp4",	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
1455     { "zp5",	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
1456     { "ist",	tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
1457     { "zp6",	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
1458     { "nst",	tZONE,     -HOUR(7) },	/* North Sumatra */
1459     { "sst",	tZONE,     -HOUR(7) },	/* South Sumatra */
1460     { "jt",	tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
1461     { "nzt",	tZONE,     -HOUR(12) },	/* New Zealand */
1462     { "idle",	tZONE,     -HOUR(12) },	/* International Date Line East */
1463     { "cat",	tZONE,     HOUR(10) },	/* -- expired 1967 */
1464     { "nt",	tZONE,     HOUR(11) },	/* -- expired 1967 */
1465     { "ahst",	tZONE,     HOUR(10) },	/* -- expired 1983 */
1466     { "hdt",	tDAYZONE,  HOUR(10) },	/* -- expired 1986 */
1467 #endif	/* 0 */
1468 };
1469 
1470 
1471 
1472 /* ARGSUSED */
1473 static void
date_error(char * s)1474 date_error(char *s)
1475 {
1476     /* NOTREACHED */
1477 }
1478 
1479 
1480 static time_t
ToSeconds(time_t Hours,time_t Minutes,time_t Seconds,MERIDIAN Meridian)1481 ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
1482 {
1483     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
1484 	return -1;
1485     if (Meridian == MER24) {
1486 	if (Hours < 0 || Hours > 23)
1487 	    return -1;
1488     }
1489     else {
1490 	if (Hours < 1 || Hours > 12)
1491 	    return -1;
1492 	if (Hours == 12)
1493 	    Hours = 0;
1494 	if (Meridian == MERpm)
1495 	    Hours += 12;
1496     }
1497     return (Hours * 60L + Minutes) * 60L + Seconds;
1498 }
1499 
1500 
1501 static time_t
Convert(time_t Month,time_t Day,time_t Year,time_t Hours,time_t Minutes,time_t Seconds,MERIDIAN Meridian,DSTMODE dst)1502 Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian, DSTMODE dst)
1503 {
1504     static int	DaysNormal[13] = {
1505 	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1506     };
1507     static int	DaysLeap[13] = {
1508 	0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1509     };
1510     static int	LeapYears[] = {
1511 	1972, 1976, 1980, 1984, 1988, 1992, 1996,
1512 	2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
1513     };
1514     register int	*yp;
1515     register int	*mp;
1516     register time_t	Julian;
1517     register int	i;
1518     time_t		tod;
1519 
1520     if (Year < 0)
1521 	Year = -Year;
1522     if (Year < 100)
1523 	Year += 1900;
1524     if (Year < EPOCH)
1525 	Year += 100;
1526     for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
1527 	if (Year == *yp) {
1528 	    mp = DaysLeap;
1529 	    break;
1530 	}
1531     if (Year < EPOCH || Year > END_OF_TIME
1532      || Month < 1 || Month > 12
1533      /* NOSTRICT *//* conversion from long may lose accuracy */
1534      || Day < 1 || Day > mp[(int)Month])
1535 	return -1;
1536 
1537     Julian = Day - 1 + (Year - EPOCH) * 365;
1538     for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
1539 	if (Year <= *yp)
1540 	    break;
1541     for (i = 1; i < Month; i++)
1542 	Julian += *++mp;
1543     Julian *= SECSPERDAY;
1544     Julian += yyTimezone * 60L;
1545     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
1546 	return -1;
1547     Julian += tod;
1548     tod = Julian;
1549     if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
1550 	Julian -= DST_OFFSET * 60 * 60;
1551     return Julian;
1552 }
1553 
1554 
1555 static time_t
DSTcorrect(time_t Start,time_t Future)1556 DSTcorrect(time_t Start, time_t Future)
1557 {
1558     time_t	StartDay;
1559     time_t	FutureDay;
1560 
1561     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
1562     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
1563     return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60 * 60;
1564 }
1565 
1566 
1567 static time_t
RelativeMonth(time_t Start,time_t RelMonth)1568 RelativeMonth(time_t Start, time_t RelMonth)
1569 {
1570     struct tm	*tm;
1571     time_t	Month;
1572     time_t	Year;
1573 
1574     tm = localtime(&Start);
1575     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
1576     Year = Month / 12;
1577     Month = Month % 12 + 1;
1578     return DSTcorrect(Start,
1579 	    Convert(Month, (time_t)tm->tm_mday, Year,
1580 		(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
1581 		MER24, DSTmaybe));
1582 }
1583 
1584 
1585 static int
LookupWord(char * buff,register int length)1586 LookupWord(char *buff, register int length)
1587 {
1588     register char	*p;
1589     register STRING	q;
1590     register TABLE	*tp;
1591     register int	c;
1592 
1593     p = buff;
1594     c = p[0];
1595 
1596     /* See if we have an abbreviation for a month. */
1597     if (length == 3 || (length == 4 && p[3] == '.'))
1598 	for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
1599 	    q = tp->name;
1600 	    if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
1601 		yylval.Number = tp->value;
1602 		return tp->type;
1603 	    }
1604 	}
1605     else
1606 	for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
1607 	    if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1608 		yylval.Number = tp->value;
1609 		return tp->type;
1610 	    }
1611 
1612     /* Try for a timezone. */
1613     for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1614 	if (c == tp->name[0] && p[1] == tp->name[1]
1615 	 && strcmp(p, tp->name) == 0) {
1616 	    yylval.Number = tp->value;
1617 	    return tp->type;
1618 	}
1619 
1620     if (strcmp(buff, "dst") == 0)
1621 	return tDST;
1622 
1623     /* Try the units table. */
1624     for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1625 	if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1626 	    yylval.Number = tp->value;
1627 	    return tp->type;
1628 	}
1629 
1630     /* Strip off any plural and try the units table again. */
1631     if (--length > 0 && p[length] == 's') {
1632 	p[length] = '\0';
1633 	for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1634 	    if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1635 		p[length] = 's';
1636 		yylval.Number = tp->value;
1637 		return tp->type;
1638 	    }
1639 	p[length] = 's';
1640     }
1641     length++;
1642 
1643     /* Drop out any periods. */
1644     for (p = buff, q = (STRING)buff; *q; q++)
1645 	if (*q != '.')
1646 	    *p++ = *q;
1647     *p = '\0';
1648 
1649     /* Try the meridians. */
1650     if (buff[1] == 'm' && buff[2] == '\0') {
1651 	if (buff[0] == 'a') {
1652 	    yylval.Meridian = MERam;
1653 	    return tMERIDIAN;
1654 	}
1655 	if (buff[0] == 'p') {
1656 	    yylval.Meridian = MERpm;
1657 	    return tMERIDIAN;
1658 	}
1659     }
1660 
1661     /* If we saw any periods, try the timezones again. */
1662     if (p - buff != length) {
1663 	c = buff[0];
1664 	for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1665 	    if (c == tp->name[0] && p[1] == tp->name[1]
1666 	    && strcmp(p, tp->name) == 0) {
1667 		yylval.Number = tp->value;
1668 		return tp->type;
1669 	    }
1670     }
1671 
1672     /* Unknown word -- assume GMT timezone. */
1673     yylval.Number = 0;
1674     return tZONE;
1675 }
1676 
1677 
1678 static int
date_lex(void)1679 date_lex(void)
1680 {
1681     register char	c;
1682     register char	*p;
1683     char		buff[20];
1684     register int	sign;
1685     register int	i;
1686     register int	nesting;
1687 
1688     for ( ; ; ) {
1689 	/* Get first character after the whitespace. */
1690 	for ( ; ; ) {
1691 	    while (CTYPE(isspace, *yyInput))
1692 		yyInput++;
1693 	    c = *yyInput;
1694 
1695 	    /* Ignore RFC 822 comments, typically time zone names. */
1696 	    if (c != LPAREN)
1697 		break;
1698 	    for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
1699 		if (c == LPAREN)
1700 		    nesting++;
1701 		else if (!IS7BIT(c) || c == '\0' || c == '\r'
1702 		     || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
1703 		    /* Lexical error: bad comment. */
1704 		    return '?';
1705 	    yyInput++;
1706 	}
1707 
1708 	/* A number? */
1709 	if (CTYPE(isdigit, c) || c == '-' || c == '+') {
1710 	    if (c == '-' || c == '+') {
1711 		sign = c == '-' ? -1 : 1;
1712 		yyInput++;
1713 		if (!CTYPE(isdigit, *yyInput))
1714 		    /* Skip the plus or minus sign. */
1715 		    continue;
1716 	    }
1717 	    else
1718 		sign = 0;
1719 	    for (i = 0; (c = *yyInput++) != '\0' && CTYPE(isdigit, c); )
1720 		i = 10 * i + c - '0';
1721 	    yyInput--;
1722 	    yylval.Number = sign < 0 ? -i : i;
1723 	    return sign ? tSNUMBER : tUNUMBER;
1724 	}
1725 
1726 	/* A word? */
1727 	if (CTYPE(isalpha, c)) {
1728 	    for (p = buff; (c = *yyInput++) == '.' || CTYPE(isalpha, c); )
1729 		if (p < &buff[sizeof buff - 1])
1730 		    *p++ = CTYPE(isupper, c) ? tolower(c) : c;
1731 	    *p = '\0';
1732 	    yyInput--;
1733 	    return LookupWord(buff, p - buff);
1734 	}
1735 
1736 	return *yyInput++;
1737     }
1738 }
1739 
1740 
1741 time_t
parsedate(char * p,TIMEINFO * now)1742 parsedate(char *p, TIMEINFO *now)
1743 {
1744     extern int		date_parse(void);
1745     struct tm		*tm;
1746     TIMEINFO		ti;
1747     time_t		Start;
1748 
1749     yyInput = p;
1750     if (now == NULL) {
1751 	now = &ti;
1752 	(void)GetTimeInfo(&ti);
1753     }
1754 
1755     tm = localtime(&now->time);
1756     yyYear = tm->tm_year;
1757     yyMonth = tm->tm_mon + 1;
1758     yyDay = tm->tm_mday;
1759     yyTimezone = now->tzone;
1760     if(tm->tm_isdst)			/* Correct timezone offset for DST */
1761 	yyTimezone += DST_OFFSET * 60;
1762     yyDSTmode = DSTmaybe;
1763     yyHour = 0;
1764     yyMinutes = 0;
1765     yySeconds = 0;
1766     yyMeridian = MER24;
1767     yyRelSeconds = 0;
1768     yyRelMonth = 0;
1769     yyHaveDate = 0;
1770     yyHaveRel = 0;
1771     yyHaveTime = 0;
1772 
1773     if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
1774 	return -1;
1775 
1776     if (yyHaveDate || yyHaveTime) {
1777 	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1778 		    yyMeridian, yyDSTmode);
1779 	if (Start < 0)
1780 	    return -1;
1781     }
1782     else {
1783 	Start = now->time;
1784 	if (!yyHaveRel)
1785 	    Start -= (tm->tm_hour * 60L + tm->tm_min) * 60L + tm->tm_sec;
1786     }
1787 
1788     Start += yyRelSeconds;
1789     if (yyRelMonth)
1790 	Start += RelativeMonth(Start, yyRelMonth);
1791 
1792     /* Have to do *something* with a legitimate -1 so it's distinguishable
1793      * from the error return value.  (Alternately could set errno on error.) */
1794     return Start == -1 ? 0 : Start;
1795 }
1796 
1797 
1798 
1799 /***** TEST main ************************************************************/
1800 #ifdef TEST
1801 
1802 /*
1803  * Parser test
1804  */
main(int argc,char * argv[])1805 int main(int argc, char *argv[])
1806 {
1807     time_t t;
1808 
1809     if(argc != 2)
1810     {
1811 	fprintf(stderr, "usage: testdate DATE-STRING\n");
1812 	exit(1);
1813     }
1814 
1815     t = parsedate(argv[1], NULL);
1816 
1817     printf("parsedate(%s) = %ld\n", argv[1], t);
1818     if(t != ERROR)
1819     {
1820 	printf("date() = %s\n",
1821 	       date("%Y-%m-%d %X", &t));
1822 
1823 	printf("         %s\n",
1824 	       date("%a %b %d %H %j %m %M %S %w %x %X %y %Y %Z %O", &t) );
1825     }
1826 
1827     exit(0);
1828 
1829     /**NOT REACHED**/
1830     return 0;
1831 }
1832 
1833 #endif /**TEST**/
1834