xref: /openbsd-src/gnu/usr.bin/cvs/lib/getdate.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 #ifndef lint
2 static char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93 (BSDI)";
3 #endif
4 #include <stdlib.h>
5 #define YYBYACC 1
6 #define YYMAJOR 1
7 #define YYMINOR 9
8 #define YYEMPTY (-1)
9 #define YYLEX yylex()
10 #define yyclearin (yychar=YYEMPTY)
11 #define yyerrok (yyerrflag=0)
12 #define YYRECOVERING (yyerrflag!=0)
13 #define YYPREFIX "yy"
14 #line 2 "/u/scjones/cvs-nightly/lib/getdate.y"
15 /*
16 **  Originally written by Steven M. Bellovin <smb@research.att.com> while
17 **  at the University of North Carolina at Chapel Hill.  Later tweaked by
18 **  a couple of people on Usenet.  Completely overhauled by Rich $alz
19 **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
20 **
21 **  This grammar has 10 shift/reduce conflicts.
22 **
23 **  This code is in the public domain and has no copyright.
24 */
25 /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
26 /* SUPPRESS 288 on yyerrlab *//* Label unused */
27 
28 #ifdef HAVE_CONFIG_H
29 #if defined (emacs) || defined (CONFIG_BROKETS)
30 #include <config.h>
31 #else
32 #include "config.h"
33 #endif
34 #endif
35 
36 /* Since the code of getdate.y is not included in the Emacs executable
37    itself, there is no need to #define static in this file.  Even if
38    the code were included in the Emacs executable, it probably
39    wouldn't do any harm to #undef it here; this will only cause
40    problems if we try to write to a static variable, which I don't
41    think this code needs to do.  */
42 #ifdef emacs
43 #undef static
44 #endif
45 
46 #include <stdio.h>
47 #include <ctype.h>
48 
49 /* The code at the top of get_date which figures out the offset of the
50    current time zone checks various CPP symbols to see if special
51    tricks are need, but defaults to using the gettimeofday system call.
52    Include <sys/time.h> if that will be used.  */
53 
54 #if	defined(vms)
55 
56 #include <types.h>
57 #include <time.h>
58 
59 #else
60 
61 #include <sys/types.h>
62 
63 #ifdef TIME_WITH_SYS_TIME
64 #include <sys/time.h>
65 #include <time.h>
66 #else
67 #ifdef HAVE_SYS_TIME_H
68 #include <sys/time.h>
69 #else
70 #include <time.h>
71 #endif
72 #endif
73 
74 #ifdef timezone
75 #undef timezone /* needed for sgi */
76 #endif
77 
78 #if defined(HAVE_SYS_TIMEB_H)
79 #include <sys/timeb.h>
80 #else
81 /*
82 ** We use the obsolete `struct timeb' as part of our interface!
83 ** Since the system doesn't have it, we define it here;
84 ** our callers must do likewise.
85 */
86 struct timeb {
87     time_t		time;		/* Seconds since the epoch	*/
88     unsigned short	millitm;	/* Field not used		*/
89     short		timezone;	/* Minutes west of GMT		*/
90     short		dstflag;	/* Field not used		*/
91 };
92 #endif /* defined(HAVE_SYS_TIMEB_H) */
93 
94 #endif	/* defined(vms) */
95 
96 #if defined (STDC_HEADERS) || defined (USG)
97 #include <string.h>
98 #endif
99 
100 /* Some old versions of bison generate parsers that use bcopy.
101    That loses on systems that don't provide the function, so we have
102    to redefine it here.  */
103 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
104 #define bcopy(from, to, len) memcpy ((to), (from), (len))
105 #endif
106 
107 #if defined (STDC_HEADERS)
108 #include <stdlib.h>
109 #endif
110 
111 /* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
112    releases):
113 
114    We don't want to mess with all the portability hassles of alloca.
115    In particular, most (all?) versions of bison will use alloca in
116    their parser.  If bison works on your system (e.g. it should work
117    with gcc), then go ahead and use it, but the more general solution
118    is to use byacc instead of bison, which should generate a portable
119    parser.  I played with adding "#define alloca dont_use_alloca", to
120    give an error if the parser generator uses alloca (and thus detect
121    unportable getdate.c's), but that seems to cause as many problems
122    as it solves.  */
123 
124 extern struct tm	*gmtime();
125 extern struct tm	*localtime();
126 
127 #define yyparse getdate_yyparse
128 #define yylex getdate_yylex
129 #define yyerror getdate_yyerror
130 
131 static int yylex ();
132 static int yyerror ();
133 
134 #define EPOCH		1970
135 #define HOUR(x)		((time_t)(x) * 60)
136 #define SECSPERDAY	(24L * 60L * 60L)
137 
138 
139 /*
140 **  An entry in the lexical lookup table.
141 */
142 typedef struct _TABLE {
143     char	*name;
144     int		type;
145     time_t	value;
146 } TABLE;
147 
148 
149 /*
150 **  Daylight-savings mode:  on, off, or not yet known.
151 */
152 typedef enum _DSTMODE {
153     DSTon, DSToff, DSTmaybe
154 } DSTMODE;
155 
156 /*
157 **  Meridian:  am, pm, or 24-hour style.
158 */
159 typedef enum _MERIDIAN {
160     MERam, MERpm, MER24
161 } MERIDIAN;
162 
163 
164 /*
165 **  Global variables.  We could get rid of most of these by using a good
166 **  union as the yacc stack.  (This routine was originally written before
167 **  yacc had the %union construct.)  Maybe someday; right now we only use
168 **  the %union very rarely.
169 */
170 static char	*yyInput;
171 static DSTMODE	yyDSTmode;
172 static time_t	yyDayOrdinal;
173 static time_t	yyDayNumber;
174 static int	yyHaveDate;
175 static int	yyHaveDay;
176 static int	yyHaveRel;
177 static int	yyHaveTime;
178 static int	yyHaveZone;
179 static time_t	yyTimezone;
180 static time_t	yyDay;
181 static time_t	yyHour;
182 static time_t	yyMinutes;
183 static time_t	yyMonth;
184 static time_t	yySeconds;
185 static time_t	yyYear;
186 static MERIDIAN	yyMeridian;
187 static time_t	yyRelMonth;
188 static time_t	yyRelSeconds;
189 
190 #line 179 "/u/scjones/cvs-nightly/lib/getdate.y"
191 typedef union {
192     time_t		Number;
193     enum _MERIDIAN	Meridian;
194 } YYSTYPE;
195 #line 196 "y.tab.c"
196 #define tAGO 257
197 #define tDAY 258
198 #define tDAYZONE 259
199 #define tID 260
200 #define tMERIDIAN 261
201 #define tMINUTE_UNIT 262
202 #define tMONTH 263
203 #define tMONTH_UNIT 264
204 #define tSEC_UNIT 265
205 #define tSNUMBER 266
206 #define tUNUMBER 267
207 #define tZONE 268
208 #define tDST 269
209 #define YYERRCODE 256
210 short yylhs[] = {                                        -1,
211     0,    0,    2,    2,    2,    2,    2,    2,    3,    3,
212     3,    3,    3,    4,    4,    4,    6,    6,    6,    5,
213     5,    5,    5,    5,    5,    5,    5,    7,    7,    9,
214     9,    9,    9,    9,    9,    9,    9,    9,    8,    1,
215     1,
216 };
217 short yylen[] = {                                         2,
218     0,    2,    1,    1,    1,    1,    1,    1,    2,    4,
219     4,    6,    6,    1,    1,    2,    1,    2,    2,    3,
220     5,    3,    3,    2,    4,    2,    3,    2,    1,    2,
221     2,    1,    2,    2,    1,    2,    2,    1,    1,    0,
222     1,
223 };
224 short yydefred[] = {                                      1,
225     0,    0,   15,   32,    0,   38,   35,    0,    0,    0,
226     2,    3,    4,    5,    6,    7,    8,    0,   18,    0,
227    31,   36,   33,   19,    9,   30,    0,   37,   34,    0,
228     0,    0,   16,   28,    0,   23,   27,   22,    0,    0,
229    25,   41,   11,    0,   10,    0,    0,   21,   13,   12,
230 };
231 short yydgoto[] = {                                       1,
232    45,   11,   12,   13,   14,   15,   16,   17,   18,
233 };
234 short yysindex[] = {                                      0,
235  -249,  -38,    0,    0, -260,    0,    0, -240,  -47, -248,
236     0,    0,    0,    0,    0,    0,    0, -237,    0,  -18,
237     0,    0,    0,    0,    0,    0, -262,    0,    0, -239,
238  -238, -236,    0,    0, -235,    0,    0,    0,  -56,  -19,
239     0,    0,    0, -234,    0, -232, -258,    0,    0,    0,
240 };
241 short yyrindex[] = {                                      0,
242     0,    1,    0,    0,    0,    0,    0,    0,   69,   12,
243     0,    0,    0,    0,    0,    0,    0,   23,    0,   34,
244     0,    0,    0,    0,    0,    0,   67,    0,    0,    0,
245     0,    0,    0,    0,    0,    0,    0,    0,   56,   45,
246     0,    0,    0,    0,    0,    0,   56,    0,    0,    0,
247 };
248 short yygindex[] = {                                      0,
249   -17,    0,    0,    0,    0,    0,    0,    0,    0,
250 };
251 #define YYTABLESIZE 337
252 short yytable[] = {                                      32,
253    17,   44,   42,   36,   37,   19,   20,   49,    2,    3,
254    31,   14,    4,    5,    6,    7,    8,    9,   10,   34,
255    33,   21,   29,   22,   23,   35,   38,   46,   39,   50,
256    40,   41,   47,   24,   48,    0,    0,    0,    0,    0,
257     0,    0,    0,    0,   20,    0,    0,    0,    0,    0,
258     0,    0,    0,    0,    0,   40,    0,    0,    0,    0,
259     0,    0,    0,    0,    0,    0,   26,    0,   39,    0,
260     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
261     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
262     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
263     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
264     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
265     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
266     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
267     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
268     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
269     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
270     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
271     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
272     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
273     0,    0,    0,    0,   42,    0,    0,    0,    0,   43,
274    24,    0,    0,   25,   26,   27,   28,   29,   30,    0,
275     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
276     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
277     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
278     0,    0,    0,    0,    0,    0,    0,    0,   17,   17,
279     0,    0,   17,   17,   17,   17,   17,   17,   17,   14,
280    14,    0,    0,   14,   14,   14,   14,   14,   14,   14,
281    29,   29,    0,    0,   29,   29,   29,   29,   29,   29,
282    29,   24,   24,    0,    0,   24,   24,   24,   24,   24,
283    24,   24,   20,   20,    0,    0,   20,   20,   20,   20,
284    20,   20,   20,   40,   40,    0,    0,   40,   40,   40,
285    40,    0,   40,   40,   26,   26,    0,   39,   26,   26,
286    26,   26,    0,    0,   26,   39,   39,
287 };
288 short yycheck[] = {                                      47,
289     0,   58,  261,  266,  267,   44,  267,  266,  258,  259,
290    58,    0,  262,  263,  264,  265,  266,  267,  268,  257,
291   269,  262,    0,  264,  265,   44,  266,   47,  267,   47,
292   267,  267,  267,    0,  267,   -1,   -1,   -1,   -1,   -1,
293    -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
294    -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,
295    -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,    0,   -1,
296    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
297    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
298    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
299    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
300    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
301    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
302    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
303    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
304    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
305    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
306    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
307    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
308    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
309    -1,   -1,   -1,   -1,  261,   -1,   -1,   -1,   -1,  266,
310   258,   -1,   -1,  261,  262,  263,  264,  265,  266,   -1,
311    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
312    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
313    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
314    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  258,  259,
315    -1,   -1,  262,  263,  264,  265,  266,  267,  268,  258,
316   259,   -1,   -1,  262,  263,  264,  265,  266,  267,  268,
317   258,  259,   -1,   -1,  262,  263,  264,  265,  266,  267,
318   268,  258,  259,   -1,   -1,  262,  263,  264,  265,  266,
319   267,  268,  258,  259,   -1,   -1,  262,  263,  264,  265,
320   266,  267,  268,  258,  259,   -1,   -1,  262,  263,  264,
321   265,   -1,  267,  268,  258,  259,   -1,  259,  262,  263,
322   264,  265,   -1,   -1,  268,  267,  268,
323 };
324 #define YYFINAL 1
325 #ifndef YYDEBUG
326 #define YYDEBUG 0
327 #endif
328 #define YYMAXTOKEN 269
329 #if YYDEBUG
330 char *yyname[] = {
331 "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
332 0,0,0,0,0,0,0,0,0,0,"','",0,0,"'/'",0,0,0,0,0,0,0,0,0,0,"':'",0,0,0,0,0,0,0,0,0,
333 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
334 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
335 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
336 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
337 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tAGO","tDAY",
338 "tDAYZONE","tID","tMERIDIAN","tMINUTE_UNIT","tMONTH","tMONTH_UNIT","tSEC_UNIT",
339 "tSNUMBER","tUNUMBER","tZONE","tDST",
340 };
341 char *yyrule[] = {
342 "$accept : spec",
343 "spec :",
344 "spec : spec item",
345 "item : time",
346 "item : zone",
347 "item : date",
348 "item : day",
349 "item : rel",
350 "item : number",
351 "time : tUNUMBER tMERIDIAN",
352 "time : tUNUMBER ':' tUNUMBER o_merid",
353 "time : tUNUMBER ':' tUNUMBER tSNUMBER",
354 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
355 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
356 "zone : tZONE",
357 "zone : tDAYZONE",
358 "zone : tZONE tDST",
359 "day : tDAY",
360 "day : tDAY ','",
361 "day : tUNUMBER tDAY",
362 "date : tUNUMBER '/' tUNUMBER",
363 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
364 "date : tUNUMBER tSNUMBER tSNUMBER",
365 "date : tUNUMBER tMONTH tSNUMBER",
366 "date : tMONTH tUNUMBER",
367 "date : tMONTH tUNUMBER ',' tUNUMBER",
368 "date : tUNUMBER tMONTH",
369 "date : tUNUMBER tMONTH tUNUMBER",
370 "rel : relunit tAGO",
371 "rel : relunit",
372 "relunit : tUNUMBER tMINUTE_UNIT",
373 "relunit : tSNUMBER tMINUTE_UNIT",
374 "relunit : tMINUTE_UNIT",
375 "relunit : tSNUMBER tSEC_UNIT",
376 "relunit : tUNUMBER tSEC_UNIT",
377 "relunit : tSEC_UNIT",
378 "relunit : tSNUMBER tMONTH_UNIT",
379 "relunit : tUNUMBER tMONTH_UNIT",
380 "relunit : tMONTH_UNIT",
381 "number : tUNUMBER",
382 "o_merid :",
383 "o_merid : tMERIDIAN",
384 };
385 #endif
386 #ifdef YYSTACKSIZE
387 #undef YYMAXDEPTH
388 #define YYMAXDEPTH YYSTACKSIZE
389 #else
390 #ifdef YYMAXDEPTH
391 #define YYSTACKSIZE YYMAXDEPTH
392 #else
393 #define YYSTACKSIZE 10000
394 #define YYMAXDEPTH 10000
395 #endif
396 #endif
397 #define YYINITSTACKSIZE 200
398 int yydebug;
399 int yynerrs;
400 struct yystack {
401     short *ssp;
402     YYSTYPE *vsp;
403     short *ss;
404     YYSTYPE *vs;
405     int stacksize;
406     short *sslim;
407 };
408 int yychar; /* some people use this, so we copy it in & out */
409 int yyerrflag; /* must be global for yyerrok & YYRECOVERING */
410 YYSTYPE yylval;
411 #line 398 "/u/scjones/cvs-nightly/lib/getdate.y"
412 
413 /* Month and day table. */
414 static TABLE const MonthDayTable[] = {
415     { "january",	tMONTH,  1 },
416     { "february",	tMONTH,  2 },
417     { "march",		tMONTH,  3 },
418     { "april",		tMONTH,  4 },
419     { "may",		tMONTH,  5 },
420     { "june",		tMONTH,  6 },
421     { "july",		tMONTH,  7 },
422     { "august",		tMONTH,  8 },
423     { "september",	tMONTH,  9 },
424     { "sept",		tMONTH,  9 },
425     { "october",	tMONTH, 10 },
426     { "november",	tMONTH, 11 },
427     { "december",	tMONTH, 12 },
428     { "sunday",		tDAY, 0 },
429     { "monday",		tDAY, 1 },
430     { "tuesday",	tDAY, 2 },
431     { "tues",		tDAY, 2 },
432     { "wednesday",	tDAY, 3 },
433     { "wednes",		tDAY, 3 },
434     { "thursday",	tDAY, 4 },
435     { "thur",		tDAY, 4 },
436     { "thurs",		tDAY, 4 },
437     { "friday",		tDAY, 5 },
438     { "saturday",	tDAY, 6 },
439     { NULL }
440 };
441 
442 /* Time units table. */
443 static TABLE const UnitsTable[] = {
444     { "year",		tMONTH_UNIT,	12 },
445     { "month",		tMONTH_UNIT,	1 },
446     { "fortnight",	tMINUTE_UNIT,	14 * 24 * 60 },
447     { "week",		tMINUTE_UNIT,	7 * 24 * 60 },
448     { "day",		tMINUTE_UNIT,	1 * 24 * 60 },
449     { "hour",		tMINUTE_UNIT,	60 },
450     { "minute",		tMINUTE_UNIT,	1 },
451     { "min",		tMINUTE_UNIT,	1 },
452     { "second",		tSEC_UNIT,	1 },
453     { "sec",		tSEC_UNIT,	1 },
454     { NULL }
455 };
456 
457 /* Assorted relative-time words. */
458 static TABLE const OtherTable[] = {
459     { "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
460     { "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
461     { "today",		tMINUTE_UNIT,	0 },
462     { "now",		tMINUTE_UNIT,	0 },
463     { "last",		tUNUMBER,	-1 },
464     { "this",		tMINUTE_UNIT,	0 },
465     { "next",		tUNUMBER,	2 },
466     { "first",		tUNUMBER,	1 },
467 /*  { "second",		tUNUMBER,	2 }, */
468     { "third",		tUNUMBER,	3 },
469     { "fourth",		tUNUMBER,	4 },
470     { "fifth",		tUNUMBER,	5 },
471     { "sixth",		tUNUMBER,	6 },
472     { "seventh",	tUNUMBER,	7 },
473     { "eighth",		tUNUMBER,	8 },
474     { "ninth",		tUNUMBER,	9 },
475     { "tenth",		tUNUMBER,	10 },
476     { "eleventh",	tUNUMBER,	11 },
477     { "twelfth",	tUNUMBER,	12 },
478     { "ago",		tAGO,	1 },
479     { NULL }
480 };
481 
482 /* The timezone table. */
483 /* Some of these are commented out because a time_t can't store a float. */
484 static TABLE const TimezoneTable[] = {
485     { "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
486     { "ut",	tZONE,     HOUR( 0) },	/* Universal (Coordinated) */
487     { "utc",	tZONE,     HOUR( 0) },
488     { "wet",	tZONE,     HOUR( 0) },	/* Western European */
489     { "bst",	tDAYZONE,  HOUR( 0) },	/* British Summer */
490     { "wat",	tZONE,     HOUR( 1) },	/* West Africa */
491     { "at",	tZONE,     HOUR( 2) },	/* Azores */
492 #if	0
493     /* For completeness.  BST is also British Summer, and GST is
494      * also Guam Standard. */
495     { "bst",	tZONE,     HOUR( 3) },	/* Brazil Standard */
496     { "gst",	tZONE,     HOUR( 3) },	/* Greenland Standard */
497 #endif
498 #if 0
499     { "nft",	tZONE,     HOUR(3.5) },	/* Newfoundland */
500     { "nst",	tZONE,     HOUR(3.5) },	/* Newfoundland Standard */
501     { "ndt",	tDAYZONE,  HOUR(3.5) },	/* Newfoundland Daylight */
502 #endif
503     { "ast",	tZONE,     HOUR( 4) },	/* Atlantic Standard */
504     { "adt",	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
505     { "est",	tZONE,     HOUR( 5) },	/* Eastern Standard */
506     { "edt",	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
507     { "cst",	tZONE,     HOUR( 6) },	/* Central Standard */
508     { "cdt",	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
509     { "mst",	tZONE,     HOUR( 7) },	/* Mountain Standard */
510     { "mdt",	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
511     { "pst",	tZONE,     HOUR( 8) },	/* Pacific Standard */
512     { "pdt",	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
513     { "yst",	tZONE,     HOUR( 9) },	/* Yukon Standard */
514     { "ydt",	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
515     { "hst",	tZONE,     HOUR(10) },	/* Hawaii Standard */
516     { "hdt",	tDAYZONE,  HOUR(10) },	/* Hawaii Daylight */
517     { "cat",	tZONE,     HOUR(10) },	/* Central Alaska */
518     { "ahst",	tZONE,     HOUR(10) },	/* Alaska-Hawaii Standard */
519     { "nt",	tZONE,     HOUR(11) },	/* Nome */
520     { "idlw",	tZONE,     HOUR(12) },	/* International Date Line West */
521     { "cet",	tZONE,     -HOUR(1) },	/* Central European */
522     { "met",	tZONE,     -HOUR(1) },	/* Middle European */
523     { "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
524     { "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
525     { "swt",	tZONE,     -HOUR(1) },	/* Swedish Winter */
526     { "sst",	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
527     { "fwt",	tZONE,     -HOUR(1) },	/* French Winter */
528     { "fst",	tDAYZONE,  -HOUR(1) },	/* French Summer */
529     { "eet",	tZONE,     -HOUR(2) },	/* Eastern Europe, USSR Zone 1 */
530     { "bt",	tZONE,     -HOUR(3) },	/* Baghdad, USSR Zone 2 */
531 #if 0
532     { "it",	tZONE,     -HOUR(3.5) },/* Iran */
533 #endif
534     { "zp4",	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
535     { "zp5",	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
536 #if 0
537     { "ist",	tZONE,     -HOUR(5.5) },/* Indian Standard */
538 #endif
539     { "zp6",	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
540 #if	0
541     /* For completeness.  NST is also Newfoundland Stanard, and SST is
542      * also Swedish Summer. */
543     { "nst",	tZONE,     -HOUR(6.5) },/* North Sumatra */
544     { "sst",	tZONE,     -HOUR(7) },	/* South Sumatra, USSR Zone 6 */
545 #endif	/* 0 */
546     { "wast",	tZONE,     -HOUR(7) },	/* West Australian Standard */
547     { "wadt",	tDAYZONE,  -HOUR(7) },	/* West Australian Daylight */
548 #if 0
549     { "jt",	tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
550 #endif
551     { "cct",	tZONE,     -HOUR(8) },	/* China Coast, USSR Zone 7 */
552     { "jst",	tZONE,     -HOUR(9) },	/* Japan Standard, USSR Zone 8 */
553 #if 0
554     { "cast",	tZONE,     -HOUR(9.5) },/* Central Australian Standard */
555     { "cadt",	tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
556 #endif
557     { "east",	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
558     { "eadt",	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
559     { "gst",	tZONE,     -HOUR(10) },	/* Guam Standard, USSR Zone 9 */
560     { "nzt",	tZONE,     -HOUR(12) },	/* New Zealand */
561     { "nzst",	tZONE,     -HOUR(12) },	/* New Zealand Standard */
562     { "nzdt",	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
563     { "idle",	tZONE,     -HOUR(12) },	/* International Date Line East */
564     {  NULL  }
565 };
566 
567 /* Military timezone table. */
568 static TABLE const MilitaryTable[] = {
569     { "a",	tZONE,	HOUR(  1) },
570     { "b",	tZONE,	HOUR(  2) },
571     { "c",	tZONE,	HOUR(  3) },
572     { "d",	tZONE,	HOUR(  4) },
573     { "e",	tZONE,	HOUR(  5) },
574     { "f",	tZONE,	HOUR(  6) },
575     { "g",	tZONE,	HOUR(  7) },
576     { "h",	tZONE,	HOUR(  8) },
577     { "i",	tZONE,	HOUR(  9) },
578     { "k",	tZONE,	HOUR( 10) },
579     { "l",	tZONE,	HOUR( 11) },
580     { "m",	tZONE,	HOUR( 12) },
581     { "n",	tZONE,	HOUR(- 1) },
582     { "o",	tZONE,	HOUR(- 2) },
583     { "p",	tZONE,	HOUR(- 3) },
584     { "q",	tZONE,	HOUR(- 4) },
585     { "r",	tZONE,	HOUR(- 5) },
586     { "s",	tZONE,	HOUR(- 6) },
587     { "t",	tZONE,	HOUR(- 7) },
588     { "u",	tZONE,	HOUR(- 8) },
589     { "v",	tZONE,	HOUR(- 9) },
590     { "w",	tZONE,	HOUR(-10) },
591     { "x",	tZONE,	HOUR(-11) },
592     { "y",	tZONE,	HOUR(-12) },
593     { "z",	tZONE,	HOUR(  0) },
594     { NULL }
595 };
596 
597 
598 
599 
600 /* ARGSUSED */
601 static int
602 yyerror(s)
603     char	*s;
604 {
605   return 0;
606 }
607 
608 
609 static time_t
610 ToSeconds(Hours, Minutes, Seconds, Meridian)
611     time_t	Hours;
612     time_t	Minutes;
613     time_t	Seconds;
614     MERIDIAN	Meridian;
615 {
616     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
617 	return -1;
618     switch (Meridian) {
619     case MER24:
620 	if (Hours < 0 || Hours > 23)
621 	    return -1;
622 	return (Hours * 60L + Minutes) * 60L + Seconds;
623     case MERam:
624 	if (Hours < 1 || Hours > 12)
625 	    return -1;
626 	if (Hours == 12)
627 	    Hours = 0;
628 	return (Hours * 60L + Minutes) * 60L + Seconds;
629     case MERpm:
630 	if (Hours < 1 || Hours > 12)
631 	    return -1;
632 	if (Hours == 12)
633 	    Hours = 0;
634 	return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
635     default:
636 	abort ();
637     }
638     /* NOTREACHED */
639 }
640 
641 
642 /* Year is either
643    * A negative number, which means to use its absolute value (why?)
644    * A number from 0 to 99, which means a year from 1900 to 1999, or
645    * The actual year (>=100).  */
646 static time_t
647 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
648     time_t	Month;
649     time_t	Day;
650     time_t	Year;
651     time_t	Hours;
652     time_t	Minutes;
653     time_t	Seconds;
654     MERIDIAN	Meridian;
655     DSTMODE	DSTmode;
656 {
657     static int DaysInMonth[12] = {
658 	31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
659     };
660     time_t	tod;
661     time_t	Julian;
662     int		i;
663 
664     if (Year < 0)
665 	Year = -Year;
666     if (Year < 69)
667 	Year += 2000;
668     else if (Year < 100)
669 	Year += 1900;
670     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
671 		    ? 29 : 28;
672     /* Checking for 2038 bogusly assumes that time_t is 32 bits.  But
673        I'm too lazy to try to check for time_t overflow in another way.  */
674     if (Year < EPOCH || Year > 2038
675      || Month < 1 || Month > 12
676      /* Lint fluff:  "conversion from long may lose accuracy" */
677      || Day < 1 || Day > DaysInMonth[(int)--Month])
678 	return -1;
679 
680     for (Julian = Day - 1, i = 0; i < Month; i++)
681 	Julian += DaysInMonth[i];
682     for (i = EPOCH; i < Year; i++)
683 	Julian += 365 + (i % 4 == 0);
684     Julian *= SECSPERDAY;
685     Julian += yyTimezone * 60L;
686     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
687 	return -1;
688     Julian += tod;
689     if (DSTmode == DSTon
690      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
691 	Julian -= 60 * 60;
692     return Julian;
693 }
694 
695 
696 static time_t
697 DSTcorrect(Start, Future)
698     time_t	Start;
699     time_t	Future;
700 {
701     time_t	StartDay;
702     time_t	FutureDay;
703 
704     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
705     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
706     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
707 }
708 
709 
710 static time_t
711 RelativeDate(Start, DayOrdinal, DayNumber)
712     time_t	Start;
713     time_t	DayOrdinal;
714     time_t	DayNumber;
715 {
716     struct tm	*tm;
717     time_t	now;
718 
719     now = Start;
720     tm = localtime(&now);
721     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
722     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
723     return DSTcorrect(Start, now);
724 }
725 
726 
727 static time_t
728 RelativeMonth(Start, RelMonth)
729     time_t	Start;
730     time_t	RelMonth;
731 {
732     struct tm	*tm;
733     time_t	Month;
734     time_t	Year;
735 
736     if (RelMonth == 0)
737 	return 0;
738     tm = localtime(&Start);
739     Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
740     Year = Month / 12;
741     Month = Month % 12 + 1;
742     return DSTcorrect(Start,
743 	    Convert(Month, (time_t)tm->tm_mday, Year,
744 		(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
745 		MER24, DSTmaybe));
746 }
747 
748 
749 static int
750 LookupWord(buff)
751     char		*buff;
752 {
753     register char	*p;
754     register char	*q;
755     register const TABLE	*tp;
756     int			i;
757     int			abbrev;
758 
759     /* Make it lowercase. */
760     for (p = buff; *p; p++)
761 	if (isupper(*p))
762 	    *p = tolower(*p);
763 
764     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
765 	yylval.Meridian = MERam;
766 	return tMERIDIAN;
767     }
768     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
769 	yylval.Meridian = MERpm;
770 	return tMERIDIAN;
771     }
772 
773     /* See if we have an abbreviation for a month. */
774     if (strlen(buff) == 3)
775 	abbrev = 1;
776     else if (strlen(buff) == 4 && buff[3] == '.') {
777 	abbrev = 1;
778 	buff[3] = '\0';
779     }
780     else
781 	abbrev = 0;
782 
783     for (tp = MonthDayTable; tp->name; tp++) {
784 	if (abbrev) {
785 	    if (strncmp(buff, tp->name, 3) == 0) {
786 		yylval.Number = tp->value;
787 		return tp->type;
788 	    }
789 	}
790 	else if (strcmp(buff, tp->name) == 0) {
791 	    yylval.Number = tp->value;
792 	    return tp->type;
793 	}
794     }
795 
796     for (tp = TimezoneTable; tp->name; tp++)
797 	if (strcmp(buff, tp->name) == 0) {
798 	    yylval.Number = tp->value;
799 	    return tp->type;
800 	}
801 
802     if (strcmp(buff, "dst") == 0)
803 	return tDST;
804 
805     for (tp = UnitsTable; tp->name; tp++)
806 	if (strcmp(buff, tp->name) == 0) {
807 	    yylval.Number = tp->value;
808 	    return tp->type;
809 	}
810 
811     /* Strip off any plural and try the units table again. */
812     i = strlen(buff) - 1;
813     if (buff[i] == 's') {
814 	buff[i] = '\0';
815 	for (tp = UnitsTable; tp->name; tp++)
816 	    if (strcmp(buff, tp->name) == 0) {
817 		yylval.Number = tp->value;
818 		return tp->type;
819 	    }
820 	buff[i] = 's';		/* Put back for "this" in OtherTable. */
821     }
822 
823     for (tp = OtherTable; tp->name; tp++)
824 	if (strcmp(buff, tp->name) == 0) {
825 	    yylval.Number = tp->value;
826 	    return tp->type;
827 	}
828 
829     /* Military timezones. */
830     if (buff[1] == '\0' && isalpha(*buff)) {
831 	for (tp = MilitaryTable; tp->name; tp++)
832 	    if (strcmp(buff, tp->name) == 0) {
833 		yylval.Number = tp->value;
834 		return tp->type;
835 	    }
836     }
837 
838     /* Drop out any periods and try the timezone table again. */
839     for (i = 0, p = q = buff; *q; q++)
840 	if (*q != '.')
841 	    *p++ = *q;
842 	else
843 	    i++;
844     *p = '\0';
845     if (i)
846 	for (tp = TimezoneTable; tp->name; tp++)
847 	    if (strcmp(buff, tp->name) == 0) {
848 		yylval.Number = tp->value;
849 		return tp->type;
850 	    }
851 
852     return tID;
853 }
854 
855 
856 static int
857 yylex()
858 {
859     register char	c;
860     register char	*p;
861     char		buff[20];
862     int			Count;
863     int			sign;
864 
865     for ( ; ; ) {
866 	while (isspace(*yyInput))
867 	    yyInput++;
868 
869 	if (isdigit(c = *yyInput) || c == '-' || c == '+') {
870 	    if (c == '-' || c == '+') {
871 		sign = c == '-' ? -1 : 1;
872 		if (!isdigit(*++yyInput))
873 		    /* skip the '-' sign */
874 		    continue;
875 	    }
876 	    else
877 		sign = 0;
878 	    for (yylval.Number = 0; isdigit(c = *yyInput++); )
879 		yylval.Number = 10 * yylval.Number + c - '0';
880 	    yyInput--;
881 	    if (sign < 0)
882 		yylval.Number = -yylval.Number;
883 	    return sign ? tSNUMBER : tUNUMBER;
884 	}
885 	if (isalpha(c)) {
886 	    for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
887 		if (p < &buff[sizeof buff - 1])
888 		    *p++ = c;
889 	    *p = '\0';
890 	    yyInput--;
891 	    return LookupWord(buff);
892 	}
893 	if (c != '(')
894 	    return *yyInput++;
895 	Count = 0;
896 	do {
897 	    c = *yyInput++;
898 	    if (c == '\0')
899 		return c;
900 	    if (c == '(')
901 		Count++;
902 	    else if (c == ')')
903 		Count--;
904 	} while (Count > 0);
905     }
906 }
907 
908 #define TM_YEAR_ORIGIN 1900
909 
910 /* Yield A - B, measured in seconds.  */
911 static long
912 difftm (a, b)
913      struct tm *a, *b;
914 {
915   int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
916   int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
917   int days = (
918 	      /* difference in day of year */
919 	      a->tm_yday - b->tm_yday
920 	      /* + intervening leap days */
921 	      +  ((ay >> 2) - (by >> 2))
922 	      -  (ay/100 - by/100)
923 	      +  ((ay/100 >> 2) - (by/100 >> 2))
924 	      /* + difference in years * 365 */
925 	      +  (long)(ay-by) * 365
926 	      );
927   return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
928 	      + (a->tm_min - b->tm_min))
929 	  + (a->tm_sec - b->tm_sec));
930 }
931 
932 time_t
933 get_date(p, now)
934     char		*p;
935     struct timeb	*now;
936 {
937     struct tm		*tm, gmt;
938     struct timeb	ftz;
939     time_t		Start;
940     time_t		tod;
941     time_t nowtime;
942 
943     yyInput = p;
944     if (now == NULL) {
945 	struct tm *gmt_ptr;
946 
947         now = &ftz;
948 	(void)time (&nowtime);
949 
950 	gmt_ptr = gmtime (&nowtime);
951 	if (gmt_ptr != NULL)
952 	{
953 	    /* Make a copy, in case localtime modifies *tm (I think
954 	       that comment now applies to *gmt_ptr, but I am too
955 	       lazy to dig into how gmtime and locatime allocate the
956 	       structures they return pointers to).  */
957 	    gmt = *gmt_ptr;
958 	}
959 
960 	if (! (tm = localtime (&nowtime)))
961 	    return -1;
962 
963 	if (gmt_ptr != NULL)
964 	    ftz.timezone = difftm (&gmt, tm) / 60;
965 	else
966 	    /* We are on a system like VMS, where the system clock is
967 	       in local time and the system has no concept of timezones.
968 	       Hopefully we can fake this out (for the case in which the
969 	       user specifies no timezone) by just saying the timezone
970 	       is zero.  */
971 	    ftz.timezone = 0;
972 
973 	if(tm->tm_isdst)
974 	    ftz.timezone += 60;
975     }
976     else
977     {
978 	nowtime = now->time;
979     }
980 
981     tm = localtime(&nowtime);
982     yyYear = tm->tm_year + 1900;
983     yyMonth = tm->tm_mon + 1;
984     yyDay = tm->tm_mday;
985     yyTimezone = now->timezone;
986     yyDSTmode = DSTmaybe;
987     yyHour = 0;
988     yyMinutes = 0;
989     yySeconds = 0;
990     yyMeridian = MER24;
991     yyRelSeconds = 0;
992     yyRelMonth = 0;
993     yyHaveDate = 0;
994     yyHaveDay = 0;
995     yyHaveRel = 0;
996     yyHaveTime = 0;
997     yyHaveZone = 0;
998 
999     if (yyparse()
1000      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
1001 	return -1;
1002 
1003     if (yyHaveDate || yyHaveTime || yyHaveDay) {
1004 	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1005 		    yyMeridian, yyDSTmode);
1006 	if (Start < 0)
1007 	    return -1;
1008     }
1009     else {
1010 	Start = nowtime;
1011 	if (!yyHaveRel)
1012 	    Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
1013     }
1014 
1015     Start += yyRelSeconds;
1016     Start += RelativeMonth(Start, yyRelMonth);
1017 
1018     if (yyHaveDay && !yyHaveDate) {
1019 	tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
1020 	Start += tod;
1021     }
1022 
1023     /* Have to do *something* with a legitimate -1 so it's distinguishable
1024      * from the error return value.  (Alternately could set errno on error.) */
1025     return Start == -1 ? 0 : Start;
1026 }
1027 
1028 
1029 #if	defined(TEST)
1030 
1031 /* ARGSUSED */
1032 int
1033 main(ac, av)
1034     int		ac;
1035     char	*av[];
1036 {
1037     char	buff[128];
1038     time_t	d;
1039 
1040     (void)printf("Enter date, or blank line to exit.\n\t> ");
1041     (void)fflush(stdout);
1042     while (gets(buff) && buff[0]) {
1043 	d = get_date(buff, (struct timeb *)NULL);
1044 	if (d == -1)
1045 	    (void)printf("Bad format - couldn't convert.\n");
1046 	else
1047 	    (void)printf("%s", ctime(&d));
1048 	(void)printf("\t> ");
1049 	(void)fflush(stdout);
1050     }
1051     exit(0);
1052     /* NOTREACHED */
1053 }
1054 #endif	/* defined(TEST) */
1055 #line 1056 "y.tab.c"
1056 /* allocate initial stack */
1057 #if defined(__STDC__) || defined(__cplusplus)
1058 static int yyinitstack(struct yystack *sp)
1059 #else
1060 static int yyinitstack(sp)
1061     struct yystack *sp;
1062 #endif
1063 {
1064     int newsize;
1065     short *newss;
1066     YYSTYPE *newvs;
1067 
1068     newsize = YYINITSTACKSIZE;
1069     newss = (short *)malloc(newsize * sizeof *newss);
1070     newvs = (YYSTYPE *)malloc(newsize * sizeof *newvs);
1071     sp->ss = sp->ssp = newss;
1072     sp->vs = sp->vsp = newvs;
1073     if (newss == NULL || newvs == NULL) return -1;
1074     sp->stacksize = newsize;
1075     sp->sslim = newss + newsize - 1;
1076     return 0;
1077 }
1078 
1079 /* double stack size, up to YYMAXDEPTH */
1080 #if defined(__STDC__) || defined(__cplusplus)
1081 static int yygrowstack(struct yystack *sp)
1082 #else
1083 static int yygrowstack(sp)
1084     struct yystack *sp;
1085 #endif
1086 {
1087     int newsize, i;
1088     short *newss;
1089     YYSTYPE *newvs;
1090 
1091     if ((newsize = sp->stacksize) >= YYMAXDEPTH) return -1;
1092     if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH;
1093     i = sp->ssp - sp->ss;
1094     if ((newss = (short *)realloc(sp->ss, newsize * sizeof *newss)) == NULL)
1095         return -1;
1096     sp->ss = newss;
1097     sp->ssp = newss + i;
1098     if ((newvs = (YYSTYPE *)realloc(sp->vs, newsize * sizeof *newvs)) == NULL)
1099         return -1;
1100     sp->vs = newvs;
1101     sp->vsp = newvs + i;
1102     sp->stacksize = newsize;
1103     sp->sslim = newss + newsize - 1;
1104     return 0;
1105 }
1106 
1107 #define YYFREESTACK(sp) { free((sp)->ss); free((sp)->vs); }
1108 
1109 #define YYABORT goto yyabort
1110 #define YYREJECT goto yyabort
1111 #define YYACCEPT goto yyaccept
1112 #define YYERROR goto yyerrlab
1113 int
1114 yyparse()
1115 {
1116     register int yym, yyn, yystate, yych;
1117     register YYSTYPE *yyvsp;
1118     YYSTYPE yyval;
1119     struct yystack yystk;
1120 #if YYDEBUG
1121     register char *yys;
1122     extern char *getenv();
1123 
1124     if (yys = getenv("YYDEBUG"))
1125     {
1126         yyn = *yys;
1127         if (yyn >= '0' && yyn <= '9')
1128             yydebug = yyn - '0';
1129     }
1130 #endif
1131 
1132     yynerrs = 0;
1133     yyerrflag = 0;
1134     yychar = yych = YYEMPTY;
1135 
1136     if (yyinitstack(&yystk)) goto yyoverflow;
1137     *yystk.ssp = yystate = 0;
1138 
1139 yyloop:
1140     if (yyn = yydefred[yystate]) goto yyreduce;
1141     if (yych < 0)
1142     {
1143         if ((yych = YYLEX) < 0) yych = 0;
1144         yychar = yych;
1145 #if YYDEBUG
1146         if (yydebug)
1147         {
1148             yys = 0;
1149             if (yych <= YYMAXTOKEN) yys = yyname[yych];
1150             if (!yys) yys = "illegal-symbol";
1151             printf("%sdebug: state %d, reading %d (%s)\n",
1152                     YYPREFIX, yystate, yych, yys);
1153         }
1154 #endif
1155     }
1156     if ((yyn = yysindex[yystate]) && (yyn += yych) >= 0 &&
1157             yyn <= YYTABLESIZE && yycheck[yyn] == yych)
1158     {
1159 #if YYDEBUG
1160         if (yydebug)
1161             printf("%sdebug: state %d, shifting to state %d\n",
1162                     YYPREFIX, yystate, yytable[yyn]);
1163 #endif
1164         if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk))
1165             goto yyoverflow;
1166         *++yystk.ssp = yystate = yytable[yyn];
1167         *++yystk.vsp = yylval;
1168         yychar = yych = YYEMPTY;
1169         if (yyerrflag > 0)  --yyerrflag;
1170         goto yyloop;
1171     }
1172     if ((yyn = yyrindex[yystate]) && (yyn += yych) >= 0 &&
1173             yyn <= YYTABLESIZE && yycheck[yyn] == yych)
1174     {
1175         yyn = yytable[yyn];
1176         goto yyreduce;
1177     }
1178     if (yyerrflag) goto yyinrecovery;
1179 #ifdef lint
1180     goto yynewerror;
1181 #endif
1182 yynewerror:
1183     yyerror("syntax error");
1184 #ifdef lint
1185     goto yyerrlab;
1186 #endif
1187 yyerrlab:
1188     ++yynerrs;
1189 yyinrecovery:
1190     if (yyerrflag < 3)
1191     {
1192         yyerrflag = 3;
1193         for (;;)
1194         {
1195             if ((yyn = yysindex[*yystk.ssp]) &&
1196                     (yyn += YYERRCODE) >= 0 &&
1197                     yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1198             {
1199 #if YYDEBUG
1200                 if (yydebug)
1201                     printf("%sdebug: state %d, error recovery shifting\
1202  to state %d\n", YYPREFIX, *yystk.ssp, yytable[yyn]);
1203 #endif
1204                 if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk))
1205                     goto yyoverflow;
1206                 *++yystk.ssp = yystate = yytable[yyn];
1207                 *++yystk.vsp = yylval;
1208                 goto yyloop;
1209             }
1210             else
1211             {
1212 #if YYDEBUG
1213                 if (yydebug)
1214                     printf("%sdebug: error recovery discarding state %d\n",
1215                             YYPREFIX, *yystk.ssp);
1216 #endif
1217                 if (yystk.ssp <= yystk.ss) goto yyabort;
1218                 --yystk.ssp;
1219                 --yystk.vsp;
1220             }
1221         }
1222     }
1223     else
1224     {
1225         if (yych == 0) goto yyabort;
1226 #if YYDEBUG
1227         if (yydebug)
1228         {
1229             yys = 0;
1230             if (yych <= YYMAXTOKEN) yys = yyname[yych];
1231             if (!yys) yys = "illegal-symbol";
1232             printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1233                     YYPREFIX, yystate, yych, yys);
1234         }
1235 #endif
1236         yychar = yych = YYEMPTY;
1237         goto yyloop;
1238     }
1239 yyreduce:
1240 #if YYDEBUG
1241     if (yydebug)
1242         printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1243                 YYPREFIX, yystate, yyn, yyrule[yyn]);
1244 #endif
1245     yym = yylen[yyn];
1246     yyvsp = yystk.vsp; /* for speed in code under switch() */
1247     yyval = yyvsp[1-yym];
1248     switch (yyn)
1249     {
1250 case 3:
1251 #line 197 "/u/scjones/cvs-nightly/lib/getdate.y"
1252 {
1253 	    yyHaveTime++;
1254 	}
1255 break;
1256 case 4:
1257 #line 200 "/u/scjones/cvs-nightly/lib/getdate.y"
1258 {
1259 	    yyHaveZone++;
1260 	}
1261 break;
1262 case 5:
1263 #line 203 "/u/scjones/cvs-nightly/lib/getdate.y"
1264 {
1265 	    yyHaveDate++;
1266 	}
1267 break;
1268 case 6:
1269 #line 206 "/u/scjones/cvs-nightly/lib/getdate.y"
1270 {
1271 	    yyHaveDay++;
1272 	}
1273 break;
1274 case 7:
1275 #line 209 "/u/scjones/cvs-nightly/lib/getdate.y"
1276 {
1277 	    yyHaveRel++;
1278 	}
1279 break;
1280 case 9:
1281 #line 215 "/u/scjones/cvs-nightly/lib/getdate.y"
1282 {
1283 	    yyHour = yyvsp[-1].Number;
1284 	    yyMinutes = 0;
1285 	    yySeconds = 0;
1286 	    yyMeridian = yyvsp[0].Meridian;
1287 	}
1288 break;
1289 case 10:
1290 #line 221 "/u/scjones/cvs-nightly/lib/getdate.y"
1291 {
1292 	    yyHour = yyvsp[-3].Number;
1293 	    yyMinutes = yyvsp[-1].Number;
1294 	    yySeconds = 0;
1295 	    yyMeridian = yyvsp[0].Meridian;
1296 	}
1297 break;
1298 case 11:
1299 #line 227 "/u/scjones/cvs-nightly/lib/getdate.y"
1300 {
1301 	    yyHour = yyvsp[-3].Number;
1302 	    yyMinutes = yyvsp[-1].Number;
1303 	    yyMeridian = MER24;
1304 	    yyDSTmode = DSToff;
1305 	    yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
1306 	}
1307 break;
1308 case 12:
1309 #line 234 "/u/scjones/cvs-nightly/lib/getdate.y"
1310 {
1311 	    yyHour = yyvsp[-5].Number;
1312 	    yyMinutes = yyvsp[-3].Number;
1313 	    yySeconds = yyvsp[-1].Number;
1314 	    yyMeridian = yyvsp[0].Meridian;
1315 	}
1316 break;
1317 case 13:
1318 #line 240 "/u/scjones/cvs-nightly/lib/getdate.y"
1319 {
1320 	    yyHour = yyvsp[-5].Number;
1321 	    yyMinutes = yyvsp[-3].Number;
1322 	    yySeconds = yyvsp[-1].Number;
1323 	    yyMeridian = MER24;
1324 	    yyDSTmode = DSToff;
1325 	    yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
1326 	}
1327 break;
1328 case 14:
1329 #line 250 "/u/scjones/cvs-nightly/lib/getdate.y"
1330 {
1331 	    yyTimezone = yyvsp[0].Number;
1332 	    yyDSTmode = DSToff;
1333 	}
1334 break;
1335 case 15:
1336 #line 254 "/u/scjones/cvs-nightly/lib/getdate.y"
1337 {
1338 	    yyTimezone = yyvsp[0].Number;
1339 	    yyDSTmode = DSTon;
1340 	}
1341 break;
1342 case 16:
1343 #line 259 "/u/scjones/cvs-nightly/lib/getdate.y"
1344 {
1345 	    yyTimezone = yyvsp[-1].Number;
1346 	    yyDSTmode = DSTon;
1347 	}
1348 break;
1349 case 17:
1350 #line 265 "/u/scjones/cvs-nightly/lib/getdate.y"
1351 {
1352 	    yyDayOrdinal = 1;
1353 	    yyDayNumber = yyvsp[0].Number;
1354 	}
1355 break;
1356 case 18:
1357 #line 269 "/u/scjones/cvs-nightly/lib/getdate.y"
1358 {
1359 	    yyDayOrdinal = 1;
1360 	    yyDayNumber = yyvsp[-1].Number;
1361 	}
1362 break;
1363 case 19:
1364 #line 273 "/u/scjones/cvs-nightly/lib/getdate.y"
1365 {
1366 	    yyDayOrdinal = yyvsp[-1].Number;
1367 	    yyDayNumber = yyvsp[0].Number;
1368 	}
1369 break;
1370 case 20:
1371 #line 279 "/u/scjones/cvs-nightly/lib/getdate.y"
1372 {
1373 	    yyMonth = yyvsp[-2].Number;
1374 	    yyDay = yyvsp[0].Number;
1375 	}
1376 break;
1377 case 21:
1378 #line 283 "/u/scjones/cvs-nightly/lib/getdate.y"
1379 {
1380 	    if (yyvsp[-4].Number >= 100) {
1381 		yyYear = yyvsp[-4].Number;
1382 		yyMonth = yyvsp[-2].Number;
1383 		yyDay = yyvsp[0].Number;
1384 	    } else {
1385 		yyMonth = yyvsp[-4].Number;
1386 		yyDay = yyvsp[-2].Number;
1387 		yyYear = yyvsp[0].Number;
1388 	    }
1389 	}
1390 break;
1391 case 22:
1392 #line 294 "/u/scjones/cvs-nightly/lib/getdate.y"
1393 {
1394 	    /* ISO 8601 format.  yyyy-mm-dd.  */
1395 	    yyYear = yyvsp[-2].Number;
1396 	    yyMonth = -yyvsp[-1].Number;
1397 	    yyDay = -yyvsp[0].Number;
1398 	}
1399 break;
1400 case 23:
1401 #line 300 "/u/scjones/cvs-nightly/lib/getdate.y"
1402 {
1403 	    /* e.g. 17-JUN-1992.  */
1404 	    yyDay = yyvsp[-2].Number;
1405 	    yyMonth = yyvsp[-1].Number;
1406 	    yyYear = -yyvsp[0].Number;
1407 	}
1408 break;
1409 case 24:
1410 #line 306 "/u/scjones/cvs-nightly/lib/getdate.y"
1411 {
1412 	    yyMonth = yyvsp[-1].Number;
1413 	    yyDay = yyvsp[0].Number;
1414 	}
1415 break;
1416 case 25:
1417 #line 310 "/u/scjones/cvs-nightly/lib/getdate.y"
1418 {
1419 	    yyMonth = yyvsp[-3].Number;
1420 	    yyDay = yyvsp[-2].Number;
1421 	    yyYear = yyvsp[0].Number;
1422 	}
1423 break;
1424 case 26:
1425 #line 315 "/u/scjones/cvs-nightly/lib/getdate.y"
1426 {
1427 	    yyMonth = yyvsp[0].Number;
1428 	    yyDay = yyvsp[-1].Number;
1429 	}
1430 break;
1431 case 27:
1432 #line 319 "/u/scjones/cvs-nightly/lib/getdate.y"
1433 {
1434 	    yyMonth = yyvsp[-1].Number;
1435 	    yyDay = yyvsp[-2].Number;
1436 	    yyYear = yyvsp[0].Number;
1437 	}
1438 break;
1439 case 28:
1440 #line 326 "/u/scjones/cvs-nightly/lib/getdate.y"
1441 {
1442 	    yyRelSeconds = -yyRelSeconds;
1443 	    yyRelMonth = -yyRelMonth;
1444 	}
1445 break;
1446 case 30:
1447 #line 333 "/u/scjones/cvs-nightly/lib/getdate.y"
1448 {
1449 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1450 	}
1451 break;
1452 case 31:
1453 #line 336 "/u/scjones/cvs-nightly/lib/getdate.y"
1454 {
1455 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1456 	}
1457 break;
1458 case 32:
1459 #line 339 "/u/scjones/cvs-nightly/lib/getdate.y"
1460 {
1461 	    yyRelSeconds += yyvsp[0].Number * 60L;
1462 	}
1463 break;
1464 case 33:
1465 #line 342 "/u/scjones/cvs-nightly/lib/getdate.y"
1466 {
1467 	    yyRelSeconds += yyvsp[-1].Number;
1468 	}
1469 break;
1470 case 34:
1471 #line 345 "/u/scjones/cvs-nightly/lib/getdate.y"
1472 {
1473 	    yyRelSeconds += yyvsp[-1].Number;
1474 	}
1475 break;
1476 case 35:
1477 #line 348 "/u/scjones/cvs-nightly/lib/getdate.y"
1478 {
1479 	    yyRelSeconds++;
1480 	}
1481 break;
1482 case 36:
1483 #line 351 "/u/scjones/cvs-nightly/lib/getdate.y"
1484 {
1485 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1486 	}
1487 break;
1488 case 37:
1489 #line 354 "/u/scjones/cvs-nightly/lib/getdate.y"
1490 {
1491 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1492 	}
1493 break;
1494 case 38:
1495 #line 357 "/u/scjones/cvs-nightly/lib/getdate.y"
1496 {
1497 	    yyRelMonth += yyvsp[0].Number;
1498 	}
1499 break;
1500 case 39:
1501 #line 362 "/u/scjones/cvs-nightly/lib/getdate.y"
1502 {
1503 	    if (yyHaveTime && yyHaveDate && !yyHaveRel)
1504 		yyYear = yyvsp[0].Number;
1505 	    else {
1506 		if(yyvsp[0].Number>10000) {
1507 		    yyHaveDate++;
1508 		    yyDay= (yyvsp[0].Number)%100;
1509 		    yyMonth= (yyvsp[0].Number/100)%100;
1510 		    yyYear = yyvsp[0].Number/10000;
1511 		}
1512 		else {
1513 		    yyHaveTime++;
1514 		    if (yyvsp[0].Number < 100) {
1515 			yyHour = yyvsp[0].Number;
1516 			yyMinutes = 0;
1517 		    }
1518 		    else {
1519 		    	yyHour = yyvsp[0].Number / 100;
1520 		    	yyMinutes = yyvsp[0].Number % 100;
1521 		    }
1522 		    yySeconds = 0;
1523 		    yyMeridian = MER24;
1524 	        }
1525 	    }
1526 	}
1527 break;
1528 case 40:
1529 #line 389 "/u/scjones/cvs-nightly/lib/getdate.y"
1530 {
1531 	    yyval.Meridian = MER24;
1532 	}
1533 break;
1534 case 41:
1535 #line 392 "/u/scjones/cvs-nightly/lib/getdate.y"
1536 {
1537 	    yyval.Meridian = yyvsp[0].Meridian;
1538 	}
1539 break;
1540 #line 1541 "y.tab.c"
1541     }
1542     yystk.ssp -= yym;
1543     yystate = *yystk.ssp;
1544     yystk.vsp -= yym;
1545     yym = yylhs[yyn];
1546     yych = yychar;
1547     if (yystate == 0 && yym == 0)
1548     {
1549 #if YYDEBUG
1550         if (yydebug)
1551             printf("%sdebug: after reduction, shifting from state 0 to\
1552  state %d\n", YYPREFIX, YYFINAL);
1553 #endif
1554         yystate = YYFINAL;
1555         *++yystk.ssp = YYFINAL;
1556         *++yystk.vsp = yyval;
1557         if (yych < 0)
1558         {
1559             if ((yych = YYLEX) < 0) yych = 0;
1560             yychar = yych;
1561 #if YYDEBUG
1562             if (yydebug)
1563             {
1564                 yys = 0;
1565                 if (yych <= YYMAXTOKEN) yys = yyname[yych];
1566                 if (!yys) yys = "illegal-symbol";
1567                 printf("%sdebug: state %d, reading %d (%s)\n",
1568                         YYPREFIX, YYFINAL, yych, yys);
1569             }
1570 #endif
1571         }
1572         if (yych == 0) goto yyaccept;
1573         goto yyloop;
1574     }
1575     if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1576             yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1577         yystate = yytable[yyn];
1578     else
1579         yystate = yydgoto[yym];
1580 #if YYDEBUG
1581     if (yydebug)
1582         printf("%sdebug: after reduction, shifting from state %d \
1583 to state %d\n", YYPREFIX, *yystk.ssp, yystate);
1584 #endif
1585     if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk))
1586         goto yyoverflow;
1587     *++yystk.ssp = yystate;
1588     *++yystk.vsp = yyval;
1589     goto yyloop;
1590 yyoverflow:
1591     yyerror("yacc stack overflow");
1592 yyabort:
1593     YYFREESTACK(&yystk);
1594     return (1);
1595 yyaccept:
1596     YYFREESTACK(&yystk);
1597     return (0);
1598 }
1599