* New parsedate
[citadel.git] / citadel / parsedate.c
1 #ifndef lint
2 static char yysccsid[] = "@(#)yaccpar   1.9 (Berkeley) 02/21/93";
3 #endif
4 #define YYBYACC 1
5 #define YYMAJOR 1
6 #define YYMINOR 9
7 #define yyclearin (yychar=(-1))
8 #define yyerrok (yyerrflag=0)
9 #define YYRECOVERING (yyerrflag!=0)
10 #define YYPREFIX "yy"
11 #line 2 "parsedate.y"
12 /* $Revision$
13 **
14 **  Originally written by Steven M. Bellovin <smb@research.att.com> while
15 **  at the University of North Carolina at Chapel Hill.  Later tweaked by
16 **  a couple of people on Usenet.  Completely overhauled by Rich $alz
17 **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
18 **  Further revised (removed obsolete constructs and cleaned up timezone
19 **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
20 **  helped in September, 1992.
21 **
22 **  This grammar has six shift/reduce conflicts.
23 **
24 **  This code is in the public domain and has no copyright.
25 */
26 /* SUPPRESS 530 *//* Empty body for statement */
27 /* SUPPRESS 593 on yyerrlab *//* Label was not used */
28 /* SUPPRESS 593 on yynewstate *//* Label was not used */
29 /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <ctype.h>
33 #include <time.h>
34
35 int date_lex();
36
37 #define yyparse         date_parse
38 #define yylex           date_lex
39 #define yyerror         date_error
40
41
42     /* See the LeapYears table in Convert. */
43 #define EPOCH           1970
44 #define END_OF_TIME     2038
45     /* Constants for general time calculations. */
46 #define DST_OFFSET      1
47 #define SECSPERDAY      (24L * 60L * 60L)
48     /* Readability for TABLE stuff. */
49 #define HOUR(x)         (x * 60)
50
51 #define LPAREN          '('
52 #define RPAREN          ')'
53 #define IS7BIT(x)       ((unsigned int)(x) < 0200)
54
55 #define SIZEOF(array)   ((int)(sizeof array / sizeof array[0]))
56 #define ENDOF(array)    (&array[SIZEOF(array)])
57
58
59 /*
60 **  An entry in the lexical lookup table.
61 */
62 typedef struct _TABLE {
63     char        *name;
64     int         type;
65     time_t      value;
66 } TABLE;
67
68 /*
69 **  Daylight-savings mode:  on, off, or not yet known.
70 */
71 typedef enum _DSTMODE {
72     DSTon, DSToff, DSTmaybe
73 } DSTMODE;
74
75 /*
76 **  Meridian:  am, pm, or 24-hour style.
77 */
78 typedef enum _MERIDIAN {
79     MERam, MERpm, MER24
80 } MERIDIAN;
81
82
83 /*
84 **  Global variables.  We could get rid of most of them by using a yacc
85 **  union, but this is more efficient.  (This routine predates the
86 **  yacc %union construct.)
87 */
88 static char     *yyInput;
89 static DSTMODE  yyDSTmode;
90 static int      yyHaveDate;
91 static int      yyHaveRel;
92 static int      yyHaveTime;
93 static time_t   yyTimezone;
94 static time_t   yyDay;
95 static time_t   yyHour;
96 static time_t   yyMinutes;
97 static time_t   yyMonth;
98 static time_t   yySeconds;
99 static time_t   yyYear;
100 static MERIDIAN yyMeridian;
101 static time_t   yyRelMonth;
102 static time_t   yyRelSeconds;
103
104
105 extern struct tm        *localtime();
106
107 static void             date_error();
108 #line 100 "parsedate.y"
109 typedef union {
110     time_t              Number;
111     enum _MERIDIAN      Meridian;
112 } YYSTYPE;
113 #line 114 "y.tab.c"
114 #define tDAY 257
115 #define tDAYZONE 258
116 #define tMERIDIAN 259
117 #define tMONTH 260
118 #define tMONTH_UNIT 261
119 #define tSEC_UNIT 262
120 #define tSNUMBER 263
121 #define tUNUMBER 264
122 #define tZONE 265
123 #define YYERRCODE 256
124 short yylhs[] = {                                        -1,
125     0,    0,    4,    4,    4,    4,    5,    5,    5,    5,
126     5,    2,    2,    2,    2,    1,    6,    6,    6,    6,
127     6,    6,    6,    7,    7,    7,    7,    3,    3,
128 };
129 short yylen[] = {                                         2,
130     0,    2,    1,    2,    1,    1,    2,    4,    4,    6,
131     6,    1,    1,    2,    1,    1,    3,    5,    2,    4,
132     2,    3,    5,    2,    2,    2,    2,    0,    1,
133 };
134 short yydefred[] = {                                      1,
135     0,    0,    0,    0,    0,    2,    0,    5,    6,    0,
136     0,   26,   24,   29,    0,   27,   25,    0,    0,    7,
137    13,   16,    0,   15,    4,    0,    0,   22,    0,    0,
138    14,    0,   20,    0,    9,    8,    0,   23,    0,   18,
139    11,   10,
140 };
141 short yydgoto[] = {                                       1,
142    24,   25,   20,    6,    7,    8,    9,
143 };
144 short yysindex[] = {                                      0,
145  -239,  -36, -248, -255,  -47,    0, -232,    0,    0, -247,
146   -25,    0,    0,    0, -237,    0,    0, -235, -234,    0,
147     0,    0, -231,    0,    0, -226, -229,    0,  -56,  -11,
148     0, -227,    0, -225,    0,    0, -224,    0, -250,    0,
149     0,    0,
150 };
151 short yyrindex[] = {                                      0,
152     0,    0,    0,    0,    1,    0,   22,    0,    0,    0,
153    12,    0,    0,    0,   28,    0,    0,    0,    0,    0,
154     0,    0,   23,    0,    0,    0,    0,    0,    3,   14,
155     0,    0,    0,    0,    0,    0,    0,    0,    3,    0,
156     0,    0,
157 };
158 short yygindex[] = {                                      0,
159   -19,    0,  -24,    0,    0,    0,    0,
160 };
161 #define YYTABLESIZE 291
162 short yytable[] = {                                      19,
163    28,   34,   28,   31,   36,   12,   13,   10,   14,   35,
164    18,   19,   22,   17,   42,   11,   26,    2,   27,   41,
165     3,    3,   12,    4,    5,   21,   28,   21,   29,   30,
166    22,   22,   23,   32,   33,   37,   38,    0,   39,   40,
167     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
168     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
169     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
170     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
171     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
172     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
173     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
174     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
175     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
176     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
177     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
178     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
179     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
180     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
181     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
182     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
183     0,    0,   14,    0,    0,    0,   22,    0,    0,    0,
184     0,   14,   15,   16,   17,    0,    0,    0,    0,    0,
185     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
186     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
187     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
188     0,    0,    0,    0,    0,    0,    0,   28,   28,   28,
189    28,    0,   28,   28,   28,   28,   28,   28,   19,    0,
190    17,   19,    0,   17,   19,   19,   17,   17,    3,   12,
191     0,    3,   12,    0,   21,    3,   12,   21,    0,    0,
192    21,
193 };
194 short yycheck[] = {                                      47,
195     0,   58,    0,   23,   29,  261,  262,   44,  259,   29,
196    58,    0,  263,    0,   39,  264,  264,  257,   44,   39,
197   260,    0,    0,  263,  264,  258,  264,    0,  264,  264,
198   263,  263,  265,  260,  264,   47,  264,   -1,  264,  264,
199    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
200    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
201    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
202    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
203    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
204    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
206    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
207    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
208    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
209    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
210    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
211    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
212    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
213    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
214    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
215    -1,   -1,  259,   -1,   -1,   -1,  263,   -1,   -1,   -1,
216    -1,  259,  260,  261,  262,   -1,   -1,   -1,   -1,   -1,
217    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
218    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
219    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
220    -1,   -1,   -1,   -1,   -1,   -1,   -1,  257,  258,  257,
221   258,   -1,  260,  263,  264,  265,  264,  265,  257,   -1,
222   257,  260,   -1,  260,  263,  264,  263,  264,  257,  257,
223    -1,  260,  260,   -1,  257,  264,  264,  260,   -1,   -1,
224   263,
225 };
226 #define YYFINAL 1
227 #ifndef YYDEBUG
228 #define YYDEBUG 0
229 #endif
230 #define YYMAXTOKEN 265
231 #if YYDEBUG
232 char *yyname[] = {
233 "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,
234 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,
235 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,
236 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,
237 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,
238 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,
239 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,"tDAY","tDAYZONE",
240 "tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
241 };
242 char *yyrule[] = {
243 "$accept : spec",
244 "spec :",
245 "spec : spec item",
246 "item : time",
247 "item : time zone",
248 "item : date",
249 "item : rel",
250 "time : tUNUMBER o_merid",
251 "time : tUNUMBER ':' tUNUMBER o_merid",
252 "time : tUNUMBER ':' tUNUMBER numzone",
253 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
254 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone",
255 "zone : tZONE",
256 "zone : tDAYZONE",
257 "zone : tZONE numzone",
258 "zone : numzone",
259 "numzone : tSNUMBER",
260 "date : tUNUMBER '/' tUNUMBER",
261 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
262 "date : tMONTH tUNUMBER",
263 "date : tMONTH tUNUMBER ',' tUNUMBER",
264 "date : tUNUMBER tMONTH",
265 "date : tUNUMBER tMONTH tUNUMBER",
266 "date : tDAY ',' tUNUMBER tMONTH tUNUMBER",
267 "rel : tSNUMBER tSEC_UNIT",
268 "rel : tUNUMBER tSEC_UNIT",
269 "rel : tSNUMBER tMONTH_UNIT",
270 "rel : tUNUMBER tMONTH_UNIT",
271 "o_merid :",
272 "o_merid : tMERIDIAN",
273 };
274 #endif
275 #ifdef YYSTACKSIZE
276 #undef YYMAXDEPTH
277 #define YYMAXDEPTH YYSTACKSIZE
278 #else
279 #ifdef YYMAXDEPTH
280 #define YYSTACKSIZE YYMAXDEPTH
281 #else
282 #define YYSTACKSIZE 500
283 #define YYMAXDEPTH 500
284 #endif
285 #endif
286 int yydebug;
287 int yynerrs;
288 int yyerrflag;
289 int yychar;
290 short *yyssp;
291 YYSTYPE *yyvsp;
292 YYSTYPE yyval;
293 YYSTYPE yylval;
294 short yyss[YYSTACKSIZE];
295 YYSTYPE yyvs[YYSTACKSIZE];
296 #define yystacksize YYSTACKSIZE
297 #line 287 "parsedate.y"
298
299 /* Month and day table. */
300 static TABLE    MonthDayTable[] = {
301     { "january",        tMONTH,  1 },
302     { "february",       tMONTH,  2 },
303     { "march",          tMONTH,  3 },
304     { "april",          tMONTH,  4 },
305     { "may",            tMONTH,  5 },
306     { "june",           tMONTH,  6 },
307     { "july",           tMONTH,  7 },
308     { "august",         tMONTH,  8 },
309     { "september",      tMONTH,  9 },
310     { "october",        tMONTH, 10 },
311     { "november",       tMONTH, 11 },
312     { "december",       tMONTH, 12 },
313         /* The value of the day isn't used... */
314     { "sunday",         tDAY, 0 },
315     { "monday",         tDAY, 0 },
316     { "tuesday",        tDAY, 0 },
317     { "wednesday",      tDAY, 0 },
318     { "thursday",       tDAY, 0 },
319     { "friday",         tDAY, 0 },
320     { "saturday",       tDAY, 0 },
321 };
322
323 /* Time units table. */
324 static TABLE    UnitsTable[] = {
325     { "year",           tMONTH_UNIT,    12 },
326     { "month",          tMONTH_UNIT,    1 },
327     { "week",           tSEC_UNIT,      7L * 24 * 60 * 60 },
328     { "day",            tSEC_UNIT,      1L * 24 * 60 * 60 },
329     { "hour",           tSEC_UNIT,      60 * 60 },
330     { "minute",         tSEC_UNIT,      60 },
331     { "min",            tSEC_UNIT,      60 },
332     { "second",         tSEC_UNIT,      1 },
333     { "sec",            tSEC_UNIT,      1 },
334 };
335
336 /* Timezone table. */
337 static TABLE    TimezoneTable[] = {
338     { "gmt",    tZONE,     HOUR( 0) },  /* Greenwich Mean */
339     { "ut",     tZONE,     HOUR( 0) },  /* Universal */
340     { "utc",    tZONE,     HOUR( 0) },  /* Universal Coordinated */
341     { "cut",    tZONE,     HOUR( 0) },  /* Coordinated Universal */
342     { "z",      tZONE,     HOUR( 0) },  /* Greenwich Mean */
343     { "wet",    tZONE,     HOUR( 0) },  /* Western European */
344     { "bst",    tDAYZONE,  HOUR( 0) },  /* British Summer */
345     { "nst",    tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
346     { "ndt",    tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
347     { "ast",    tZONE,     HOUR( 4) },  /* Atlantic Standard */
348     { "adt",    tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
349     { "est",    tZONE,     HOUR( 5) },  /* Eastern Standard */
350     { "edt",    tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
351     { "cst",    tZONE,     HOUR( 6) },  /* Central Standard */
352     { "cdt",    tDAYZONE,  HOUR( 6) },  /* Central Daylight */
353     { "mst",    tZONE,     HOUR( 7) },  /* Mountain Standard */
354     { "mdt",    tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
355     { "pst",    tZONE,     HOUR( 8) },  /* Pacific Standard */
356     { "pdt",    tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
357     { "yst",    tZONE,     HOUR( 9) },  /* Yukon Standard */
358     { "ydt",    tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
359     { "akst",   tZONE,     HOUR( 9) },  /* Alaska Standard */
360     { "akdt",   tDAYZONE,  HOUR( 9) },  /* Alaska Daylight */
361     { "hst",    tZONE,     HOUR(10) },  /* Hawaii Standard */
362     { "hast",   tZONE,     HOUR(10) },  /* Hawaii-Aleutian Standard */
363     { "hadt",   tDAYZONE,  HOUR(10) },  /* Hawaii-Aleutian Daylight */
364     { "ces",    tDAYZONE,  -HOUR(1) },  /* Central European Summer */
365     { "cest",   tDAYZONE,  -HOUR(1) },  /* Central European Summer */
366     { "mez",    tZONE,     -HOUR(1) },  /* Middle European */
367     { "mezt",   tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
368     { "cet",    tZONE,     -HOUR(1) },  /* Central European */
369     { "met",    tZONE,     -HOUR(1) },  /* Middle European */
370     { "eet",    tZONE,     -HOUR(2) },  /* Eastern Europe */
371     { "msk",    tZONE,     -HOUR(3) },  /* Moscow Winter */
372     { "msd",    tDAYZONE,  -HOUR(3) },  /* Moscow Summer */
373     { "wast",   tZONE,     -HOUR(8) },  /* West Australian Standard */
374     { "wadt",   tDAYZONE,  -HOUR(8) },  /* West Australian Daylight */
375     { "hkt",    tZONE,     -HOUR(8) },  /* Hong Kong */
376     { "cct",    tZONE,     -HOUR(8) },  /* China Coast */
377     { "jst",    tZONE,     -HOUR(9) },  /* Japan Standard */
378     { "kst",    tZONE,     -HOUR(9) },  /* Korean Standard */
379     { "kdt",    tZONE,     -HOUR(9) },  /* Korean Daylight */
380     { "cast",   tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
381     { "cadt",   tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
382     { "east",   tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
383     { "eadt",   tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
384     { "nzst",   tZONE,     -HOUR(12) }, /* New Zealand Standard */
385     { "nzdt",   tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
386
387     /* For completeness we include the following entries. */
388 #if 0
389
390     /* Duplicate names.  Either they conflict with a zone listed above
391      * (which is either more likely to be seen or just been in circulation
392      * longer), or they conflict with another zone in this section and
393      * we could not reasonably choose one over the other. */
394     { "fst",    tZONE,     HOUR( 2) },  /* Fernando De Noronha Standard */
395     { "fdt",    tDAYZONE,  HOUR( 2) },  /* Fernando De Noronha Daylight */
396     { "bst",    tZONE,     HOUR( 3) },  /* Brazil Standard */
397     { "est",    tZONE,     HOUR( 3) },  /* Eastern Standard (Brazil) */
398     { "edt",    tDAYZONE,  HOUR( 3) },  /* Eastern Daylight (Brazil) */
399     { "wst",    tZONE,     HOUR( 4) },  /* Western Standard (Brazil) */
400     { "wdt",    tDAYZONE,  HOUR( 4) },  /* Western Daylight (Brazil) */
401     { "cst",    tZONE,     HOUR( 5) },  /* Chile Standard */
402     { "cdt",    tDAYZONE,  HOUR( 5) },  /* Chile Daylight */
403     { "ast",    tZONE,     HOUR( 5) },  /* Acre Standard */
404     { "adt",    tDAYZONE,  HOUR( 5) },  /* Acre Daylight */
405     { "cst",    tZONE,     HOUR( 5) },  /* Cuba Standard */
406     { "cdt",    tDAYZONE,  HOUR( 5) },  /* Cuba Daylight */
407     { "est",    tZONE,     HOUR( 6) },  /* Easter Island Standard */
408     { "edt",    tDAYZONE,  HOUR( 6) },  /* Easter Island Daylight */
409     { "sst",    tZONE,     HOUR(11) },  /* Samoa Standard */
410     { "ist",    tZONE,     -HOUR(2) },  /* Israel Standard */
411     { "idt",    tDAYZONE,  -HOUR(2) },  /* Israel Daylight */
412     { "idt",    tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
413     { "ist",    tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
414     { "cst",     tZONE,     -HOUR(8) }, /* China Standard */
415     { "cdt",     tDAYZONE,  -HOUR(8) }, /* China Daylight */
416     { "sst",     tZONE,     -HOUR(8) }, /* Singapore Standard */
417
418     /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
419     { "gst",    tZONE,     HOUR( 3) },  /* Greenland Standard */
420     { "wat",    tZONE,     -HOUR(1) },  /* West Africa */
421     { "at",     tZONE,     HOUR( 2) },  /* Azores */
422     { "gst",    tZONE,     -HOUR(10) }, /* Guam Standard */
423     { "nft",    tZONE,     HOUR(3)+30 }, /* Newfoundland */
424     { "idlw",   tZONE,     HOUR(12) },  /* International Date Line West */
425     { "mewt",   tZONE,     -HOUR(1) },  /* Middle European Winter */
426     { "mest",   tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
427     { "swt",    tZONE,     -HOUR(1) },  /* Swedish Winter */
428     { "sst",    tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
429     { "fwt",    tZONE,     -HOUR(1) },  /* French Winter */
430     { "fst",    tDAYZONE,  -HOUR(1) },  /* French Summer */
431     { "bt",     tZONE,     -HOUR(3) },  /* Baghdad */
432     { "it",     tZONE,     -(HOUR(3)+30) }, /* Iran */
433     { "zp4",    tZONE,     -HOUR(4) },  /* USSR Zone 3 */
434     { "zp5",    tZONE,     -HOUR(5) },  /* USSR Zone 4 */
435     { "ist",    tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
436     { "zp6",    tZONE,     -HOUR(6) },  /* USSR Zone 5 */
437     { "nst",    tZONE,     -HOUR(7) },  /* North Sumatra */
438     { "sst",    tZONE,     -HOUR(7) },  /* South Sumatra */
439     { "jt",     tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
440     { "nzt",    tZONE,     -HOUR(12) }, /* New Zealand */
441     { "idle",   tZONE,     -HOUR(12) }, /* International Date Line East */
442     { "cat",    tZONE,     HOUR(10) },  /* -- expired 1967 */
443     { "nt",     tZONE,     HOUR(11) },  /* -- expired 1967 */
444     { "ahst",   tZONE,     HOUR(10) },  /* -- expired 1983 */
445     { "hdt",    tDAYZONE,  HOUR(10) },  /* -- expired 1986 */
446 #endif /* 0 */
447 };
448
449
450 /* ARGSUSED */
451 static void
452 date_error(s)
453     char        *s;
454 {
455     /* NOTREACHED */
456 }
457
458
459 static time_t
460 ToSeconds(Hours, Minutes, Seconds, Meridian)
461     time_t      Hours;
462     time_t      Minutes;
463     time_t      Seconds;
464     MERIDIAN    Meridian;
465 {
466     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
467         return -1;
468     if (Meridian == MER24) {
469         if (Hours < 0 || Hours > 23)
470             return -1;
471     }
472     else {
473         if (Hours < 1 || Hours > 12)
474             return -1;
475         if (Hours == 12)
476             Hours = 0;
477         if (Meridian == MERpm)
478             Hours += 12;
479     }
480     return (Hours * 60L + Minutes) * 60L + Seconds;
481 }
482
483
484 static time_t
485 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
486     time_t      Month;
487     time_t      Day;
488     time_t      Year;
489     time_t      Hours;
490     time_t      Minutes;
491     time_t      Seconds;
492     MERIDIAN    Meridian;
493     DSTMODE     dst;
494 {
495     static int  DaysNormal[13] = {
496         0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
497     };
498     static int  DaysLeap[13] = {
499         0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
500     };
501     static int  LeapYears[] = {
502         1972, 1976, 1980, 1984, 1988, 1992, 1996,
503         2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
504     };
505     register int        *yp;
506     register int        *mp;
507     register time_t     Julian;
508     register int        i;
509     time_t              tod;
510
511     if (Year < 0)
512         Year = -Year;
513     if (Year < 100)
514         Year += 1900;
515     if (Year < EPOCH)
516         Year += 100;
517     for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
518         if (Year == *yp) {
519             mp = DaysLeap;
520             break;
521         }
522     if (Year < EPOCH || Year > END_OF_TIME
523      || Month < 1 || Month > 12
524      /* NOSTRICT *//* conversion from long may lose accuracy */
525      || Day < 1 || Day > mp[(int)Month])
526         return -1;
527
528     Julian = Day - 1 + (Year - EPOCH) * 365;
529     for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
530         if (Year <= *yp)
531             break;
532     for (i = 1; i < Month; i++)
533         Julian += *++mp;
534     Julian *= SECSPERDAY;
535     Julian += yyTimezone * 60L;
536     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
537         return -1;
538     Julian += tod;
539     tod = Julian;
540     if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
541         Julian -= DST_OFFSET * 60L * 60L;
542     return Julian;
543 }
544
545
546 static time_t
547 DSTcorrect(Start, Future)
548     time_t      Start;
549     time_t      Future;
550 {
551     time_t      StartDay;
552     time_t      FutureDay;
553
554     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
555     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
556     return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
557 }
558
559
560 static time_t
561 RelativeMonth(Start, RelMonth)
562     time_t      Start;
563     time_t      RelMonth;
564 {
565     struct tm   *tm;
566     time_t      Month;
567     time_t      Year;
568
569     tm = localtime(&Start);
570     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
571     Year = Month / 12;
572     Month = Month % 12 + 1;
573     return DSTcorrect(Start,
574             Convert(Month, (time_t)tm->tm_mday, Year,
575                 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
576                 MER24, DSTmaybe));
577 }
578
579
580 static int
581 LookupWord(buff, length)
582     char                *buff;
583     register int        length;
584 {
585     register char       *p;
586     register char       *q;
587     register TABLE      *tp;
588     register int        c;
589
590     p = buff;
591     c = p[0];
592
593     /* See if we have an abbreviation for a month. */
594     if (length == 3 || (length == 4 && p[3] == '.'))
595         for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
596             q = tp->name;
597             if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
598                 yylval.Number = tp->value;
599                 return tp->type;
600             }
601         }
602     else
603         for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
604             if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
605                 yylval.Number = tp->value;
606                 return tp->type;
607             }
608
609     /* Try for a timezone. */
610     for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
611         if (c == tp->name[0] && p[1] == tp->name[1]
612          && strcmp(p, tp->name) == 0) {
613             yylval.Number = tp->value;
614             return tp->type;
615         }
616
617     /* Try the units table. */
618     for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
619         if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
620             yylval.Number = tp->value;
621             return tp->type;
622         }
623
624     /* Strip off any plural and try the units table again. */
625     if (--length > 0 && p[length] == 's') {
626         p[length] = '\0';
627         for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
628             if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
629                 p[length] = 's';
630                 yylval.Number = tp->value;
631                 return tp->type;
632             }
633         p[length] = 's';
634     }
635     length++;
636
637     /* Drop out any periods. */
638     for (p = buff, q = (char*)buff; *q; q++)
639         if (*q != '.')
640             *p++ = *q;
641     *p = '\0';
642
643     /* Try the meridians. */
644     if (buff[1] == 'm' && buff[2] == '\0') {
645         if (buff[0] == 'a') {
646             yylval.Meridian = MERam;
647             return tMERIDIAN;
648         }
649         if (buff[0] == 'p') {
650             yylval.Meridian = MERpm;
651             return tMERIDIAN;
652         }
653     }
654
655     /* If we saw any periods, try the timezones again. */
656     if (p - buff != length) {
657         c = buff[0];
658         for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
659             if (c == tp->name[0] && p[1] == tp->name[1]
660             && strcmp(p, tp->name) == 0) {
661                 yylval.Number = tp->value;
662                 return tp->type;
663             }
664     }
665
666     /* Unknown word -- assume GMT timezone. */
667     yylval.Number = 0;
668     return tZONE;
669 }
670
671
672 int
673 date_lex()
674 {
675     register char       c;
676     register char       *p;
677     char                buff[20];
678     register int        sign;
679     register int        i;
680     register int        nesting;
681
682     for ( ; ; ) {
683         /* Get first character after the whitespace. */
684         for ( ; ; ) {
685             while (isspace(*yyInput))
686                 yyInput++;
687             c = *yyInput;
688
689             /* Ignore RFC 822 comments, typically time zone names. */
690             if (c != LPAREN)
691                 break;
692             for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
693                 if (c == LPAREN)
694                     nesting++;
695                 else if (!IS7BIT(c) || c == '\0' || c == '\r'
696                      || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
697                     /* Lexical error: bad comment. */
698                     return '?';
699             yyInput++;
700         }
701
702         /* A number? */
703         if (isdigit(c) || c == '-' || c == '+') {
704             if (c == '-' || c == '+') {
705                 sign = c == '-' ? -1 : 1;
706                 yyInput++;
707                 if (!isdigit(*yyInput))
708                     /* Skip the plus or minus sign. */
709                     continue;
710             }
711             else
712                 sign = 0;
713             for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
714                 i = 10 * i + c - '0';
715             yyInput--;
716             yylval.Number = sign < 0 ? -i : i;
717             return sign ? tSNUMBER : tUNUMBER;
718         }
719
720         /* A word? */
721         if (isalpha(c)) {
722             for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
723                 if (p < &buff[sizeof buff - 1])
724                     *p++ = isupper(c) ? tolower(c) : c;
725             *p = '\0';
726             yyInput--;
727             return LookupWord(buff, p - buff);
728         }
729
730         return *yyInput++;
731     }
732 }
733
734
735 time_t
736 parsedate(p)
737     char                *p;
738 {
739     extern int          date_parse();
740     time_t              Start;
741
742     yyInput = p;
743
744     yyYear = 0;
745     yyMonth = 0;
746     yyDay = 0;
747     yyTimezone = 0;
748     yyDSTmode = DSTmaybe;
749     yyHour = 0;
750     yyMinutes = 0;
751     yySeconds = 0;
752     yyMeridian = MER24;
753     yyRelSeconds = 0;
754     yyRelMonth = 0;
755     yyHaveDate = 0;
756     yyHaveRel = 0;
757     yyHaveTime = 0;
758
759     if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
760         return -1;
761
762     if (yyHaveDate || yyHaveTime) {
763         Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
764                     yyMeridian, yyDSTmode);
765         if (Start < 0)
766             return -1;
767     }
768     else
769         return -1;
770
771     Start += yyRelSeconds;
772     if (yyRelMonth)
773         Start += RelativeMonth(Start, yyRelMonth);
774
775     /* Have to do *something* with a legitimate -1 so it's distinguishable
776      * from the error return value.  (Alternately could set errno on error.) */
777     return Start == -1 ? 0 : Start;
778 }
779
780
781 #ifdef TEST
782
783 #if YYDEBUG
784 extern int      yydebug;
785 #endif /* YYDEBUG */
786
787 /* ARGSUSED */
788 int
789 main(ac, av)
790     int         ac;
791     char        *av[];
792 {
793     char        buff[128];
794     time_t      d;
795
796 #if YYDEBUG
797     yydebug = 1;
798 #endif /* YYDEBUG */
799
800     (void)printf("Enter date, or blank line to exit.\n\t> ");
801     for ( ; ; ) {
802         (void)printf("\t> ");
803         (void)fflush(stdout);
804         if (gets(buff) == NULL || buff[0] == '\n')
805             break;
806 #if YYDEBUG
807         if (strcmp(buff, "yydebug") == 0) {
808             yydebug = !yydebug;
809             printf("yydebug = %s\n", yydebug ? "on" : "off");
810             continue;
811         }
812 #endif /* YYDEBUG */
813         d = parsedate(buff, (TIMEINFO *)NULL);
814         if (d == -1)
815             (void)printf("Bad format - couldn't convert.\n");
816         else
817             (void)printf("%s", ctime(&d));
818     }
819
820     exit(0);
821     /* NOTREACHED */
822 }
823 #endif /* TEST */
824 #line 825 "y.tab.c"
825 #define YYABORT goto yyabort
826 #define YYREJECT goto yyabort
827 #define YYACCEPT goto yyaccept
828 #define YYERROR goto yyerrlab
829 int
830 yyparse()
831 {
832     register int yym, yyn, yystate;
833 #if YYDEBUG
834     register char *yys;
835     extern char *getenv();
836
837     if (yys = getenv("YYDEBUG"))
838     {
839         yyn = *yys;
840         if (yyn >= '0' && yyn <= '9')
841             yydebug = yyn - '0';
842     }
843 #endif
844
845     yynerrs = 0;
846     yyerrflag = 0;
847     yychar = (-1);
848
849     yyssp = yyss;
850     yyvsp = yyvs;
851     *yyssp = yystate = 0;
852
853 yyloop:
854     if (yyn = yydefred[yystate]) goto yyreduce;
855     if (yychar < 0)
856     {
857         if ((yychar = yylex()) < 0) yychar = 0;
858 #if YYDEBUG
859         if (yydebug)
860         {
861             yys = 0;
862             if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
863             if (!yys) yys = "illegal-symbol";
864             printf("%sdebug: state %d, reading %d (%s)\n",
865                     YYPREFIX, yystate, yychar, yys);
866         }
867 #endif
868     }
869     if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
870             yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
871     {
872 #if YYDEBUG
873         if (yydebug)
874             printf("%sdebug: state %d, shifting to state %d\n",
875                     YYPREFIX, yystate, yytable[yyn]);
876 #endif
877         if (yyssp >= yyss + yystacksize - 1)
878         {
879             goto yyoverflow;
880         }
881         *++yyssp = yystate = yytable[yyn];
882         *++yyvsp = yylval;
883         yychar = (-1);
884         if (yyerrflag > 0)  --yyerrflag;
885         goto yyloop;
886     }
887     if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
888             yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
889     {
890         yyn = yytable[yyn];
891         goto yyreduce;
892     }
893     if (yyerrflag) goto yyinrecovery;
894 #ifdef lint
895     goto yynewerror;
896 #endif
897 yynewerror:
898     yyerror("syntax error");
899 #ifdef lint
900     goto yyerrlab;
901 #endif
902 yyerrlab:
903     ++yynerrs;
904 yyinrecovery:
905     if (yyerrflag < 3)
906     {
907         yyerrflag = 3;
908         for (;;)
909         {
910             if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
911                     yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
912             {
913 #if YYDEBUG
914                 if (yydebug)
915                     printf("%sdebug: state %d, error recovery shifting\
916  to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
917 #endif
918                 if (yyssp >= yyss + yystacksize - 1)
919                 {
920                     goto yyoverflow;
921                 }
922                 *++yyssp = yystate = yytable[yyn];
923                 *++yyvsp = yylval;
924                 goto yyloop;
925             }
926             else
927             {
928 #if YYDEBUG
929                 if (yydebug)
930                     printf("%sdebug: error recovery discarding state %d\n",
931                             YYPREFIX, *yyssp);
932 #endif
933                 if (yyssp <= yyss) goto yyabort;
934                 --yyssp;
935                 --yyvsp;
936             }
937         }
938     }
939     else
940     {
941         if (yychar == 0) goto yyabort;
942 #if YYDEBUG
943         if (yydebug)
944         {
945             yys = 0;
946             if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
947             if (!yys) yys = "illegal-symbol";
948             printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
949                     YYPREFIX, yystate, yychar, yys);
950         }
951 #endif
952         yychar = (-1);
953         goto yyloop;
954     }
955 yyreduce:
956 #if YYDEBUG
957     if (yydebug)
958         printf("%sdebug: state %d, reducing by rule %d (%s)\n",
959                 YYPREFIX, yystate, yyn, yyrule[yyn]);
960 #endif
961     yym = yylen[yyn];
962     yyval = yyvsp[1-yym];
963     switch (yyn)
964     {
965 case 3:
966 #line 118 "parsedate.y"
967 {
968             yyHaveTime++;
969 #ifdef lint
970             /* I am compulsive about lint natterings... */
971             if (yyHaveTime == -1) {
972                 YYERROR;
973             }
974 #endif /* lint */
975         }
976 break;
977 case 4:
978 #line 127 "parsedate.y"
979 {
980             yyHaveTime++;
981             yyTimezone = yyvsp[0].Number;
982         }
983 break;
984 case 5:
985 #line 131 "parsedate.y"
986 {
987             yyHaveDate++;
988         }
989 break;
990 case 6:
991 #line 134 "parsedate.y"
992 {
993             yyHaveRel = 1;
994         }
995 break;
996 case 7:
997 #line 139 "parsedate.y"
998 {
999             if (yyvsp[-1].Number < 100) {
1000                 yyHour = yyvsp[-1].Number;
1001                 yyMinutes = 0;
1002             }
1003             else {
1004                 yyHour = yyvsp[-1].Number / 100;
1005                 yyMinutes = yyvsp[-1].Number % 100;
1006             }
1007             yySeconds = 0;
1008             yyMeridian = yyvsp[0].Meridian;
1009         }
1010 break;
1011 case 8:
1012 #line 151 "parsedate.y"
1013 {
1014             yyHour = yyvsp[-3].Number;
1015             yyMinutes = yyvsp[-1].Number;
1016             yySeconds = 0;
1017             yyMeridian = yyvsp[0].Meridian;
1018         }
1019 break;
1020 case 9:
1021 #line 157 "parsedate.y"
1022 {
1023             yyHour = yyvsp[-3].Number;
1024             yyMinutes = yyvsp[-1].Number;
1025             yyTimezone = yyvsp[0].Number;
1026             yyMeridian = MER24;
1027             yyDSTmode = DSToff;
1028         }
1029 break;
1030 case 10:
1031 #line 164 "parsedate.y"
1032 {
1033             yyHour = yyvsp[-5].Number;
1034             yyMinutes = yyvsp[-3].Number;
1035             yySeconds = yyvsp[-1].Number;
1036             yyMeridian = yyvsp[0].Meridian;
1037         }
1038 break;
1039 case 11:
1040 #line 170 "parsedate.y"
1041 {
1042             yyHour = yyvsp[-5].Number;
1043             yyMinutes = yyvsp[-3].Number;
1044             yySeconds = yyvsp[-1].Number;
1045             yyTimezone = yyvsp[0].Number;
1046             yyMeridian = MER24;
1047             yyDSTmode = DSToff;
1048         }
1049 break;
1050 case 12:
1051 #line 180 "parsedate.y"
1052 {
1053             yyval.Number = yyvsp[0].Number;
1054             yyDSTmode = DSToff;
1055         }
1056 break;
1057 case 13:
1058 #line 184 "parsedate.y"
1059 {
1060             yyval.Number = yyvsp[0].Number;
1061             yyDSTmode = DSTon;
1062         }
1063 break;
1064 case 14:
1065 #line 188 "parsedate.y"
1066 {
1067             /* Only allow "GMT+300" and "GMT-0800" */
1068             if (yyvsp[-1].Number != 0) {
1069                 YYABORT;
1070             }
1071             yyval.Number = yyvsp[0].Number;
1072             yyDSTmode = DSToff;
1073         }
1074 break;
1075 case 15:
1076 #line 196 "parsedate.y"
1077 {
1078             yyval.Number = yyvsp[0].Number;
1079             yyDSTmode = DSToff;
1080         }
1081 break;
1082 case 16:
1083 #line 202 "parsedate.y"
1084 {
1085             int         i;
1086
1087             /* Unix and GMT and numeric timezones -- a little confusing. */
1088             if (yyvsp[0].Number < 0) {
1089                 /* Don't work with negative modulus. */
1090                 yyvsp[0].Number = -yyvsp[0].Number;
1091                 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1092                     YYABORT;
1093                 }
1094                 yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
1095             }
1096             else {
1097                 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1098                     YYABORT;
1099                 }
1100                 yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
1101             }
1102         }
1103 break;
1104 case 17:
1105 #line 223 "parsedate.y"
1106 {
1107             yyMonth = yyvsp[-2].Number;
1108             yyDay = yyvsp[0].Number;
1109         }
1110 break;
1111 case 18:
1112 #line 227 "parsedate.y"
1113 {
1114             if (yyvsp[-4].Number > 100) {
1115                 yyYear = yyvsp[-4].Number;
1116                 yyMonth = yyvsp[-2].Number;
1117                 yyDay = yyvsp[0].Number;
1118             }
1119             else {
1120                 yyMonth = yyvsp[-4].Number;
1121                 yyDay = yyvsp[-2].Number;
1122                 yyYear = yyvsp[0].Number;
1123             }
1124         }
1125 break;
1126 case 19:
1127 #line 239 "parsedate.y"
1128 {
1129             yyMonth = yyvsp[-1].Number;
1130             yyDay = yyvsp[0].Number;
1131         }
1132 break;
1133 case 20:
1134 #line 243 "parsedate.y"
1135 {
1136             yyMonth = yyvsp[-3].Number;
1137             yyDay = yyvsp[-2].Number;
1138             yyYear = yyvsp[0].Number;
1139         }
1140 break;
1141 case 21:
1142 #line 248 "parsedate.y"
1143 {
1144             yyDay = yyvsp[-1].Number;
1145             yyMonth = yyvsp[0].Number;
1146         }
1147 break;
1148 case 22:
1149 #line 252 "parsedate.y"
1150 {
1151             yyDay = yyvsp[-2].Number;
1152             yyMonth = yyvsp[-1].Number;
1153             yyYear = yyvsp[0].Number;
1154         }
1155 break;
1156 case 23:
1157 #line 257 "parsedate.y"
1158 {
1159             yyDay = yyvsp[-2].Number;
1160             yyMonth = yyvsp[-1].Number;
1161             yyYear = yyvsp[0].Number;
1162         }
1163 break;
1164 case 24:
1165 #line 264 "parsedate.y"
1166 {
1167             yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1168         }
1169 break;
1170 case 25:
1171 #line 267 "parsedate.y"
1172 {
1173             yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1174         }
1175 break;
1176 case 26:
1177 #line 270 "parsedate.y"
1178 {
1179             yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1180         }
1181 break;
1182 case 27:
1183 #line 273 "parsedate.y"
1184 {
1185             yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1186         }
1187 break;
1188 case 28:
1189 #line 278 "parsedate.y"
1190 {
1191             yyval.Meridian = MER24;
1192         }
1193 break;
1194 case 29:
1195 #line 281 "parsedate.y"
1196 {
1197             yyval.Meridian = yyvsp[0].Meridian;
1198         }
1199 break;
1200 #line 1201 "y.tab.c"
1201     }
1202     yyssp -= yym;
1203     yystate = *yyssp;
1204     yyvsp -= yym;
1205     yym = yylhs[yyn];
1206     if (yystate == 0 && yym == 0)
1207     {
1208 #if YYDEBUG
1209         if (yydebug)
1210             printf("%sdebug: after reduction, shifting from state 0 to\
1211  state %d\n", YYPREFIX, YYFINAL);
1212 #endif
1213         yystate = YYFINAL;
1214         *++yyssp = YYFINAL;
1215         *++yyvsp = yyval;
1216         if (yychar < 0)
1217         {
1218             if ((yychar = yylex()) < 0) yychar = 0;
1219 #if YYDEBUG
1220             if (yydebug)
1221             {
1222                 yys = 0;
1223                 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1224                 if (!yys) yys = "illegal-symbol";
1225                 printf("%sdebug: state %d, reading %d (%s)\n",
1226                         YYPREFIX, YYFINAL, yychar, yys);
1227             }
1228 #endif
1229         }
1230         if (yychar == 0) goto yyaccept;
1231         goto yyloop;
1232     }
1233     if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1234             yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1235         yystate = yytable[yyn];
1236     else
1237         yystate = yydgoto[yym];
1238 #if YYDEBUG
1239     if (yydebug)
1240         printf("%sdebug: after reduction, shifting from state %d \
1241 to state %d\n", YYPREFIX, *yyssp, yystate);
1242 #endif
1243     if (yyssp >= yyss + yystacksize - 1)
1244     {
1245         goto yyoverflow;
1246     }
1247     *++yyssp = yystate;
1248     *++yyvsp = yyval;
1249     goto yyloop;
1250 yyoverflow:
1251     yyerror("yacc stack overflow");
1252 yyabort:
1253     return (1);
1254 yyaccept:
1255     return (0);
1256 }