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