1 /* original parser id follows */
2 /* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
3 /* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
4
5 #define YYBYACC 1
6 #define YYMAJOR 1
7 #define YYMINOR 9
8 #define YYPATCH 20170709
9
10 #define YYEMPTY (-1)
11 #define yyclearin (yychar = YYEMPTY)
12 #define yyerrok (yyerrflag = 0)
13 #define YYRECOVERING() (yyerrflag != 0)
14 #define YYENOMEM (-2)
15 #define YYEOF 0
16 #define YYPREFIX "yy"
17
18 #define YYPURE 0
19
20 #line 2 "./parsdate.y"
21
22 #include <LYLeaks.h>
23
24 /*
25 * $LynxId: parsdate.c,v 1.18 2018/04/01 22:22:06 tom Exp $
26 *
27 * This module is adapted and extended from tin, to use for LYmktime().
28 *
29 * Project : tin - a Usenet reader
30 * Module : parsedate.y
31 * Author : S. Bellovin, R. $alz, J. Berets, P. Eggert
32 * Created : 1990-08-01
33 * Updated : 2008-06-30 (by Thomas Dickey, for Lynx)
34 * Notes : This grammar has 8 shift/reduce conflicts.
35 *
36 * Originally written by Steven M. Bellovin <smb@research.att.com>
37 * while at the University of North Carolina at Chapel Hill.
38 * Later tweaked by a couple of people on Usenet. Completely
39 * overhauled by Rich $alz <rsalz@osf.org> and Jim Berets
40 * <jberets@bbn.com> in August, 1990.
41 *
42 * Further revised (removed obsolete constructs and cleaned up
43 * timezone names) in August, 1991, by Rich.
44 * Paul Eggert <eggert@twinsun.com> helped in September 1992.
45 * Roland Rosenfeld added MET DST code in April 1994.
46 *
47 * Revision : 1.13
48 * Copyright : This code is in the public domain and has no copyright.
49 */
50
51 /* SUPPRESS 530 */ /* Empty body for statement */
52 /* SUPPRESS 593 on yyerrlab */ /* Label was not used */
53 /* SUPPRESS 593 on yynewstate */ /* Label was not used */
54 /* SUPPRESS 595 on yypvt */ /* Automatic variable may be used before set */
55
56 #undef alloca /* conflicting def may be set by yacc */
57 #include <parsdate.h>
58
59 /*
60 ** Get the number of elements in a fixed-size array, or a pointer just
61 ** past the end of it.
62 */
63 #define ENDOF(array) (&array[ARRAY_SIZE(array)])
64
65 #ifdef EBCDIC
66 #define TO_ASCII(c) TOASCII(c)
67 #define TO_LOCAL(c) FROMASCII(c)
68 #else
69 #define TO_ASCII(c) (c)
70 #define TO_LOCAL(c) (c)
71 #endif
72
73 #define IS7BIT(x) ((unsigned) TO_ASCII(x) < 128)
74 #define CTYPE(isXXXXX, c) (IS7BIT(c) && isXXXXX(((unsigned char)c)))
75
76 typedef char *PD_STRING;
77
78 extern int date_parse(void);
79
80 #define yyparse date_parse
81 #define yylex date_lex
82 #define yyerror date_error
83
84 /* See the LeapYears table in Convert. */
85 #define EPOCH 1970
86 #define END_OF_TIME 2038
87
88 /* Constants for general time calculations. */
89 #define DST_OFFSET 1
90 #define SECSPERDAY (24L * 60L * 60L)
91 /* Readability for TABLE stuff. */
92 #define HOUR(x) (x * 60)
93
94 #define LPAREN '('
95 #define RPAREN ')'
96
97 /*
98 ** Daylight-savings mode: on, off, or not yet known.
99 */
100 typedef enum _DSTMODE {
101 DSTon, DSToff, DSTmaybe
102 } DSTMODE;
103
104 /*
105 ** Meridian: am, pm, or 24-hour style.
106 */
107 typedef enum _MERIDIAN {
108 MERam, MERpm, MER24
109 } MERIDIAN;
110
111 /*
112 ** Global variables. We could get rid of most of them by using a yacc
113 ** union, but this is more efficient. (This routine predates the
114 ** yacc %union construct.)
115 */
116 static char *yyInput;
117 static DSTMODE yyDSTmode;
118 static int yyHaveDate;
119 static int yyHaveRel;
120 static int yyHaveTime;
121 static time_t yyTimezone;
122 static time_t yyDay;
123 static time_t yyHour;
124 static time_t yyMinutes;
125 static time_t yyMonth;
126 static time_t yySeconds;
127 static time_t yyYear;
128 static MERIDIAN yyMeridian;
129 static time_t yyRelMonth;
130 static time_t yyRelSeconds;
131
132 static time_t ToSeconds(time_t, time_t, time_t, MERIDIAN);
133 static time_t Convert(time_t, time_t, time_t, time_t, time_t, time_t,
134 MERIDIAN, DSTMODE);
135 static time_t DSTcorrect(time_t, time_t);
136 static time_t RelativeMonth(time_t, time_t);
137 static int LookupWord(char *, int);
138 static int date_lex(void);
139 static int GetTimeInfo(TIMEINFO * Now);
140
141 /*
142 * The 'date_error()' function is declared here to work around a defect in
143 * bison 1.22, which redefines 'const' further down in this file, making it
144 * impossible to put a prototype here, and the function later. We're using
145 * 'const' on the parameter to quiet gcc's -Wwrite-strings warning.
146 */
147 /*ARGSUSED*/
date_error(const char GCC_UNUSED * s)148 static void date_error(const char GCC_UNUSED *s)
149 {
150 /*NOTREACHED */
151 }
152
153 #ifdef YYSTYPE
154 #undef YYSTYPE_IS_DECLARED
155 #define YYSTYPE_IS_DECLARED 1
156 #endif
157 #ifndef YYSTYPE_IS_DECLARED
158 #define YYSTYPE_IS_DECLARED 1
159 #line 136 "./parsdate.y"
160 typedef union {
161 time_t Number;
162 enum _MERIDIAN Meridian;
163 } YYSTYPE;
164 #endif /* !YYSTYPE_IS_DECLARED */
165 #line 166 "y.tab.c"
166
167 /* compatibility with bison */
168 #ifdef YYPARSE_PARAM
169 /* compatibility with FreeBSD */
170 # ifdef YYPARSE_PARAM_TYPE
171 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
172 # else
173 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
174 # endif
175 #else
176 # define YYPARSE_DECL() yyparse(void)
177 #endif
178
179 /* Parameters sent to lex. */
180 #ifdef YYLEX_PARAM
181 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
182 # define YYLEX yylex(YYLEX_PARAM)
183 #else
184 # define YYLEX_DECL() yylex(void)
185 # define YYLEX yylex()
186 #endif
187
188 /* Parameters sent to yyerror. */
189 #ifndef YYERROR_DECL
190 #define YYERROR_DECL() yyerror(const char *s)
191 #endif
192 #ifndef YYERROR_CALL
193 #define YYERROR_CALL(msg) yyerror(msg)
194 #endif
195
196 extern int YYPARSE_DECL();
197
198 #define tDAY 257
199 #define tDAYZONE 258
200 #define tMERIDIAN 259
201 #define tMONTH 260
202 #define tMONTH_UNIT 261
203 #define tSEC_UNIT 262
204 #define tSNUMBER 263
205 #define tUNUMBER 264
206 #define tZONE 265
207 #define tDST 266
208 #define YYERRCODE 256
209 typedef short YYINT;
210 static const YYINT yylhs[] = { -1,
211 0, 0, 4, 4, 4, 4, 4, 4, 5, 5,
212 5, 5, 5, 2, 2, 2, 2, 2, 1, 6,
213 6, 6, 6, 6, 6, 6, 6, 6, 7, 8,
214 8, 8, 8, 3, 3,
215 };
216 static const YYINT yylen[] = { 2,
217 0, 2, 1, 2, 1, 1, 2, 1, 2, 4,
218 4, 6, 6, 1, 1, 2, 2, 1, 1, 3,
219 5, 2, 4, 2, 3, 5, 6, 3, 9, 2,
220 2, 2, 2, 0, 1,
221 };
222 static const YYINT yydefred[] = { 1,
223 0, 0, 0, 0, 0, 2, 0, 5, 0, 8,
224 0, 0, 0, 32, 30, 35, 0, 33, 31, 0,
225 0, 0, 9, 0, 19, 0, 18, 4, 7, 0,
226 0, 0, 25, 28, 0, 0, 16, 17, 0, 0,
227 0, 23, 0, 11, 10, 0, 0, 26, 0, 0,
228 21, 0, 27, 13, 12, 0, 0, 29,
229 };
230 static const YYINT yydgoto[] = { 1,
231 27, 28, 23, 6, 7, 8, 9, 10,
232 };
233 static const YYINT yysindex[] = { 0,
234 -240, -41, -256, -227, -45, 0, -251, 0, -251, 0,
235 -254, -249, -22, 0, 0, 0, -237, 0, 0, -235,
236 -228, -226, 0, -236, 0, -224, 0, 0, 0, -223,
237 -39, -222, 0, 0, -58, -7, 0, 0, -15, -220,
238 -215, 0, -218, 0, 0, -217, -216, 0, -214, -234,
239 0, -8, 0, 0, 0, -213, -212, 0,
240 };
241 static const YYINT yyrindex[] = { 0,
242 0, 0, 0, 0, 5, 0, 26, 0, 31, 0,
243 0, 0, 11, 0, 0, 0, 37, 0, 0, 0,
244 0, 0, 0, 16, 0, 32, 0, 0, 0, 0,
245 0, 0, 0, 0, 1, 21, 0, 0, 0, 0,
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
247 0, 0, 0, 0, 0, 0, 0, 0,
248 };
249 static const YYINT yygindex[] = { 0,
250 -17, 44, -31, 0, 0, 0, 0, 0,
251 };
252 #define YYTABLESIZE 300
253 static const YYINT yytable[] = { 43,
254 34, 22, 12, 45, 34, 41, 24, 13, 38, 30,
255 22, 25, 21, 26, 31, 15, 2, 44, 55, 3,
256 20, 32, 4, 5, 16, 3, 33, 34, 25, 37,
257 6, 14, 54, 14, 15, 35, 24, 36, 25, 46,
258 39, 42, 47, 48, 49, 50, 51, 52, 53, 56,
259 57, 58, 29, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
274 16, 0, 0, 0, 25, 0, 0, 0, 0, 0,
275 0, 0, 0, 16, 17, 18, 19, 20, 11, 0,
276 40, 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, 0, 0,
279 0, 0, 0, 0, 0, 0, 0, 34, 34, 0,
280 34, 34, 34, 0, 34, 34, 0, 22, 34, 34,
281 22, 0, 15, 22, 22, 15, 0, 20, 15, 15,
282 20, 0, 3, 20, 20, 3, 0, 6, 14, 3,
283 6, 14, 0, 24, 6, 14, 24, 0, 0, 24,
284 };
285 static const YYINT yycheck[] = { 58,
286 0, 47, 44, 35, 0, 45, 258, 264, 26, 264,
287 0, 263, 58, 265, 264, 0, 257, 35, 50, 260,
288 0, 44, 263, 264, 259, 0, 264, 263, 263, 266,
289 0, 0, 50, 261, 262, 264, 0, 264, 263, 47,
290 264, 264, 58, 264, 260, 264, 264, 264, 263, 58,
291 264, 264, 9, -1, -1, -1, -1, -1, -1, -1,
292 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
295 -1, -1, -1, -1, -1, -1, -1, -1, -1, -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 259, -1, -1, -1, 263, -1, -1, -1, -1, -1,
307 -1, -1, -1, 259, 260, 261, 262, 263, 260, -1,
308 260, -1, -1, -1, -1, -1, -1, -1, -1, -1,
309 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
310 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
311 -1, -1, -1, -1, -1, -1, -1, 257, 258, -1,
312 260, 257, 258, -1, 264, 265, -1, 257, 264, 265,
313 260, -1, 257, 263, 264, 260, -1, 257, 263, 264,
314 260, -1, 257, 263, 264, 260, -1, 257, 257, 264,
315 260, 260, -1, 257, 264, 264, 260, -1, -1, 263,
316 };
317 #define YYFINAL 1
318 #ifndef YYDEBUG
319 #define YYDEBUG 0
320 #endif
321 #define YYMAXTOKEN 266
322 #define YYUNDFTOKEN 277
323 #define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
324 #if YYDEBUG
325 static const char *const yyname[] = {
326
327 "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,
328 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,
329 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,
330 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,
331 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,
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,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,"tDAY","tDAYZONE",
334 "tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
335 "tDST",0,0,0,0,0,0,0,0,0,0,"illegal-symbol",
336 };
337 static const char *const yyrule[] = {
338 "$accept : spec",
339 "spec :",
340 "spec : spec item",
341 "item : time",
342 "item : time zone",
343 "item : date",
344 "item : both",
345 "item : both zone",
346 "item : rel",
347 "time : tUNUMBER o_merid",
348 "time : tUNUMBER ':' tUNUMBER o_merid",
349 "time : tUNUMBER ':' tUNUMBER numzone",
350 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
351 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone",
352 "zone : tZONE",
353 "zone : tDAYZONE",
354 "zone : tDAYZONE tDST",
355 "zone : tZONE numzone",
356 "zone : numzone",
357 "numzone : tSNUMBER",
358 "date : tUNUMBER '/' tUNUMBER",
359 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
360 "date : tMONTH tUNUMBER",
361 "date : tMONTH tUNUMBER ',' tUNUMBER",
362 "date : tUNUMBER tMONTH",
363 "date : tUNUMBER tMONTH tUNUMBER",
364 "date : tDAY ',' tUNUMBER tMONTH tUNUMBER",
365 "date : tDAY ',' tUNUMBER '-' tMONTH tSNUMBER",
366 "date : tUNUMBER tSNUMBER tSNUMBER",
367 "both : tDAY tMONTH tUNUMBER tUNUMBER ':' tUNUMBER ':' tUNUMBER tUNUMBER",
368 "rel : tSNUMBER tSEC_UNIT",
369 "rel : tUNUMBER tSEC_UNIT",
370 "rel : tSNUMBER tMONTH_UNIT",
371 "rel : tUNUMBER tMONTH_UNIT",
372 "o_merid :",
373 "o_merid : tMERIDIAN",
374
375 };
376 #endif
377
378 int yydebug;
379 int yynerrs;
380
381 int yyerrflag;
382 int yychar;
383 YYSTYPE yyval;
384 YYSTYPE yylval;
385
386 /* define the initial stack-sizes */
387 #ifdef YYSTACKSIZE
388 #undef YYMAXDEPTH
389 #define YYMAXDEPTH YYSTACKSIZE
390 #else
391 #ifdef YYMAXDEPTH
392 #define YYSTACKSIZE YYMAXDEPTH
393 #else
394 #define YYSTACKSIZE 10000
395 #define YYMAXDEPTH 10000
396 #endif
397 #endif
398
399 #define YYINITSTACKSIZE 200
400
401 typedef struct {
402 unsigned stacksize;
403 YYINT *s_base;
404 YYINT *s_mark;
405 YYINT *s_last;
406 YYSTYPE *l_base;
407 YYSTYPE *l_mark;
408 } YYSTACKDATA;
409 /* variables for the parser stack */
410 static YYSTACKDATA yystack;
411 #line 358 "./parsdate.y"
412
413
414 /*
415 ** An entry in the lexical lookup table.
416 */
417 /* *INDENT-OFF* */
418 typedef struct _TABLE {
419 const char *name;
420 int type;
421 time_t value;
422 } TABLE;
423
424 /* Month and day table. */
425 static const TABLE MonthDayTable[] = {
426 { "january", tMONTH, 1 },
427 { "february", tMONTH, 2 },
428 { "march", tMONTH, 3 },
429 { "april", tMONTH, 4 },
430 { "may", tMONTH, 5 },
431 { "june", tMONTH, 6 },
432 { "july", tMONTH, 7 },
433 { "august", tMONTH, 8 },
434 { "september", tMONTH, 9 },
435 { "october", tMONTH, 10 },
436 { "november", tMONTH, 11 },
437 { "december", tMONTH, 12 },
438 /* The value of the day isn't used... */
439 { "sunday", tDAY, 0 },
440 { "monday", tDAY, 0 },
441 { "tuesday", tDAY, 0 },
442 { "wednesday", tDAY, 0 },
443 { "thursday", tDAY, 0 },
444 { "friday", tDAY, 0 },
445 { "saturday", tDAY, 0 },
446 };
447
448 /* Time units table. */
449 static const TABLE UnitsTable[] = {
450 { "year", tMONTH_UNIT, 12 },
451 { "month", tMONTH_UNIT, 1 },
452 { "week", tSEC_UNIT, 7 * 24 * 60 * 60 },
453 { "day", tSEC_UNIT, 1 * 24 * 60 * 60 },
454 { "hour", tSEC_UNIT, 60 * 60 },
455 { "minute", tSEC_UNIT, 60 },
456 { "min", tSEC_UNIT, 60 },
457 { "second", tSEC_UNIT, 1 },
458 { "sec", tSEC_UNIT, 1 },
459 };
460
461 /* Timezone table. */
462 static const TABLE TimezoneTable[] = {
463 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
464 { "ut", tZONE, HOUR( 0) }, /* Universal */
465 { "utc", tZONE, HOUR( 0) }, /* Universal Coordinated */
466 { "cut", tZONE, HOUR( 0) }, /* Coordinated Universal */
467 { "z", tZONE, HOUR( 0) }, /* Greenwich Mean */
468 { "wet", tZONE, HOUR( 0) }, /* Western European */
469 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
470 { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
471 { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
472 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
473 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
474 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
475 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
476 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
477 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
478 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
479 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
480 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
481 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
482 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
483 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
484 { "akst", tZONE, HOUR( 9) }, /* Alaska Standard */
485 { "akdt", tDAYZONE, HOUR( 9) }, /* Alaska Daylight */
486 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
487 { "hast", tZONE, HOUR(10) }, /* Hawaii-Aleutian Standard */
488 { "hadt", tDAYZONE, HOUR(10) }, /* Hawaii-Aleutian Daylight */
489 { "ces", tDAYZONE, -HOUR(1) }, /* Central European Summer */
490 { "cest", tDAYZONE, -HOUR(1) }, /* Central European Summer */
491 { "mez", tZONE, -HOUR(1) }, /* Middle European */
492 { "mezt", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
493 { "cet", tZONE, -HOUR(1) }, /* Central European */
494 { "met", tZONE, -HOUR(1) }, /* Middle European */
495 /* Additional aliases for MET / MET DST *************************************/
496 { "mez", tZONE, -HOUR(1) }, /* Middle European */
497 { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
498 { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
499 { "mes", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
500 { "mesz", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
501 { "msz", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
502 { "metdst", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
503 /****************************************************************************/
504 { "eet", tZONE, -HOUR(2) }, /* Eastern Europe */
505 { "msk", tZONE, -HOUR(3) }, /* Moscow Winter */
506 { "msd", tDAYZONE, -HOUR(3) }, /* Moscow Summer */
507 { "wast", tZONE, -HOUR(8) }, /* West Australian Standard */
508 { "wadt", tDAYZONE, -HOUR(8) }, /* West Australian Daylight */
509 { "hkt", tZONE, -HOUR(8) }, /* Hong Kong */
510 { "cct", tZONE, -HOUR(8) }, /* China Coast */
511 { "jst", tZONE, -HOUR(9) }, /* Japan Standard */
512 { "kst", tZONE, -HOUR(9) }, /* Korean Standard */
513 { "kdt", tZONE, -HOUR(9) }, /* Korean Daylight */
514 { "cast", tZONE, -(HOUR(9)+30) }, /* Central Australian Standard */
515 { "cadt", tDAYZONE, -(HOUR(9)+30) }, /* Central Australian Daylight */
516 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
517 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
518 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
519 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
520
521 /* For completeness we include the following entries. */
522 #if 0
523
524 /* Duplicate names. Either they conflict with a zone listed above
525 * (which is either more likely to be seen or just been in circulation
526 * longer), or they conflict with another zone in this section and
527 * we could not reasonably choose one over the other. */
528 { "fst", tZONE, HOUR( 2) }, /* Fernando De Noronha Standard */
529 { "fdt", tDAYZONE, HOUR( 2) }, /* Fernando De Noronha Daylight */
530 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
531 { "est", tZONE, HOUR( 3) }, /* Eastern Standard (Brazil) */
532 { "edt", tDAYZONE, HOUR( 3) }, /* Eastern Daylight (Brazil) */
533 { "wst", tZONE, HOUR( 4) }, /* Western Standard (Brazil) */
534 { "wdt", tDAYZONE, HOUR( 4) }, /* Western Daylight (Brazil) */
535 { "cst", tZONE, HOUR( 5) }, /* Chile Standard */
536 { "cdt", tDAYZONE, HOUR( 5) }, /* Chile Daylight */
537 { "ast", tZONE, HOUR( 5) }, /* Acre Standard */
538 { "adt", tDAYZONE, HOUR( 5) }, /* Acre Daylight */
539 { "cst", tZONE, HOUR( 5) }, /* Cuba Standard */
540 { "cdt", tDAYZONE, HOUR( 5) }, /* Cuba Daylight */
541 { "est", tZONE, HOUR( 6) }, /* Easter Island Standard */
542 { "edt", tDAYZONE, HOUR( 6) }, /* Easter Island Daylight */
543 { "sst", tZONE, HOUR(11) }, /* Samoa Standard */
544 { "ist", tZONE, -HOUR(2) }, /* Israel Standard */
545 { "idt", tDAYZONE, -HOUR(2) }, /* Israel Daylight */
546 { "idt", tDAYZONE, -(HOUR(3)+30) }, /* Iran Daylight */
547 { "ist", tZONE, -(HOUR(3)+30) }, /* Iran Standard */
548 { "cst", tZONE, -HOUR(8) }, /* China Standard */
549 { "cdt", tDAYZONE, -HOUR(8) }, /* China Daylight */
550 { "sst", tZONE, -HOUR(8) }, /* Singapore Standard */
551
552 /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
553 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
554 { "wat", tZONE, -HOUR(1) }, /* West Africa */
555 { "at", tZONE, HOUR( 2) }, /* Azores */
556 { "gst", tZONE, -HOUR(10) }, /* Guam Standard */
557 { "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
558 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
559 { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
560 { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
561 { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
562 { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
563 { "fwt", tZONE, -HOUR(1) }, /* French Winter */
564 { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
565 { "bt", tZONE, -HOUR(3) }, /* Baghdad */
566 { "it", tZONE, -(HOUR(3)+30) }, /* Iran */
567 { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
568 { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
569 { "ist", tZONE, -(HOUR(5)+30) }, /* Indian Standard */
570 { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
571 { "nst", tZONE, -HOUR(7) }, /* North Sumatra */
572 { "sst", tZONE, -HOUR(7) }, /* South Sumatra */
573 { "jt", tZONE, -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
574 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
575 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
576 { "cat", tZONE, HOUR(10) }, /* -- expired 1967 */
577 { "nt", tZONE, HOUR(11) }, /* -- expired 1967 */
578 { "ahst", tZONE, HOUR(10) }, /* -- expired 1983 */
579 { "hdt", tDAYZONE, HOUR(10) }, /* -- expired 1986 */
580 #endif /* 0 */
581 };
582 /* *INDENT-ON* */
583
ToSeconds(time_t Hours,time_t Minutes,time_t Seconds,MERIDIAN Meridian)584 static time_t ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
585 {
586 if ((long) Minutes < 0 || Minutes > 59 || (long) Seconds < 0 || Seconds > 61)
587 return -1;
588 if (Meridian == MER24) {
589 if ((long) Hours < 0 || Hours > 23)
590 return -1;
591 } else {
592 if (Hours < 1 || Hours > 12)
593 return -1;
594 if (Hours == 12)
595 Hours = 0;
596 if (Meridian == MERpm)
597 Hours += 12;
598 }
599 return (Hours * 60L + Minutes) * 60L + Seconds;
600 }
601
Convert(time_t Month,time_t Day,time_t Year,time_t Hours,time_t Minutes,time_t Seconds,MERIDIAN Meridian,DSTMODE dst)602 static time_t Convert(time_t Month, time_t Day, time_t Year, time_t Hours,
603 time_t Minutes, time_t Seconds, MERIDIAN Meridian,
604 DSTMODE dst)
605 {
606 static const int DaysNormal[13] =
607 {
608 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
609 };
610 static const int DaysLeap[13] =
611 {
612 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
613 };
614 static const int LeapYears[] =
615 {
616 1972, 1976, 1980, 1984, 1988, 1992, 1996,
617 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
618 };
619 const int *yp;
620 const int *mp;
621 int i;
622 time_t Julian;
623 time_t tod;
624
625 if ((long) Year < 0)
626 Year = -Year;
627 if (Year < 70)
628 Year += 2000;
629 if (Year < 100)
630 Year += 1900;
631 if (Year < EPOCH)
632 Year += 100;
633 for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
634 if (Year == *yp) {
635 mp = DaysLeap;
636 break;
637 }
638 if (Year < EPOCH || Year > END_OF_TIME
639 || Month < 1 || Month > 12
640 /* NOSTRICT */
641 /* conversion from long may lose accuracy */
642 || Day < 1 || Day > mp[(int) Month]) {
643 return -1;
644 }
645
646 Julian = Day - 1 + (Year - EPOCH) * 365;
647 for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++) {
648 if (Year <= *yp)
649 break;
650 }
651 for (i = 1; i < Month; i++)
652 Julian += *++mp;
653 Julian *= SECSPERDAY;
654 Julian += yyTimezone * 60L;
655 if ((long) (tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0) {
656 return -1;
657 }
658 Julian += tod;
659 tod = Julian;
660 if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
661 Julian -= DST_OFFSET * 60 * 60;
662 return Julian;
663 }
664
DSTcorrect(time_t Start,time_t Future)665 static time_t DSTcorrect(time_t Start, time_t Future)
666 {
667 time_t StartDay;
668 time_t FutureDay;
669
670 StartDay = (localtime(&Start)->tm_hour + 1) % 24;
671 FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
672 return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60 * 60;
673 }
674
RelativeMonth(time_t Start,time_t RelMonth)675 static time_t RelativeMonth(time_t Start, time_t RelMonth)
676 {
677 struct tm *tm;
678 time_t Month;
679 time_t Year;
680
681 tm = localtime(&Start);
682 Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
683 Year = Month / 12 + 1900;
684 Month = Month % 12 + 1;
685 return DSTcorrect(Start,
686 Convert(Month, (time_t) tm->tm_mday, Year,
687 (time_t) tm->tm_hour, (time_t) tm->tm_min,
688 (time_t) tm->tm_sec,
689 MER24, DSTmaybe));
690 }
691
LookupWord(char * buff,int length)692 static int LookupWord(char *buff,
693 int length)
694 {
695 char *p;
696 const char *q;
697 const TABLE *tp;
698 int c;
699
700 p = buff;
701 c = p[0];
702
703 /* See if we have an abbreviation for a month. */
704 if (length == 3 || (length == 4 && p[3] == '.')) {
705 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
706 q = tp->name;
707 if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
708 yylval.Number = tp->value;
709 return tp->type;
710 }
711 }
712 } else {
713 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
714 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
715 yylval.Number = tp->value;
716 return tp->type;
717 }
718 }
719 }
720
721 /* Try for a timezone. */
722 for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++) {
723 if (c == tp->name[0] && p[1] == tp->name[1]
724 && strcmp(p, tp->name) == 0) {
725 yylval.Number = tp->value;
726 return tp->type;
727 }
728 }
729
730 if (strcmp(buff, "dst") == 0)
731 return tDST;
732
733 /* Try the units table. */
734 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++) {
735 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
736 yylval.Number = tp->value;
737 return tp->type;
738 }
739 }
740
741 /* Strip off any plural and try the units table again. */
742 if (--length > 0 && p[length] == 's') {
743 p[length] = '\0';
744 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++) {
745 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
746 p[length] = 's';
747 yylval.Number = tp->value;
748 return tp->type;
749 }
750 }
751 p[length] = 's';
752 }
753 length++;
754
755 /* Drop out any periods. */
756 for (p = buff, q = (PD_STRING) buff; *q; q++) {
757 if (*q != '.')
758 *p++ = *q;
759 }
760 *p = '\0';
761
762 /* Try the meridians. */
763 if (buff[1] == 'm' && buff[2] == '\0') {
764 if (buff[0] == 'a') {
765 yylval.Meridian = MERam;
766 return tMERIDIAN;
767 }
768 if (buff[0] == 'p') {
769 yylval.Meridian = MERpm;
770 return tMERIDIAN;
771 }
772 }
773
774 /* If we saw any periods, try the timezones again. */
775 if (p - buff != length) {
776 c = buff[0];
777 for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++) {
778 if (c == tp->name[0] && p[1] == tp->name[1]
779 && strcmp(p, tp->name) == 0) {
780 yylval.Number = tp->value;
781 return tp->type;
782 }
783 }
784 }
785
786 /* Unknown word -- assume GMT timezone. */
787 yylval.Number = 0;
788 return tZONE;
789 }
790
791 /*
792 * This returns characters as-is (the ones that are not part of some token),
793 * and codes greater than 256 (the token values).
794 *
795 * yacc generates tables that may use the character value. In particular,
796 * byacc's yycheck[] table contains integer values for the expected codes from
797 * this function, which (unless byacc is run locally) are ASCII codes.
798 *
799 * The TO_LOCAL() function assumes its input is in ASCII, and the output is
800 * whatever native encoding is used on the machine, e.g., EBCDIC.
801 *
802 * The TO_ASCII() function is the inverse of TO_LOCAL().
803 */
date_lex(void)804 static int date_lex(void)
805 {
806 int c;
807 char *p;
808 char buff[20];
809 int sign;
810 int i;
811 int nesting;
812
813 /* Get first character after the whitespace. */
814 for (;;) {
815 while (CTYPE(isspace, *yyInput))
816 yyInput++;
817 c = *yyInput;
818
819 /* Ignore RFC 822 comments, typically time zone names. */
820 if (c != LPAREN)
821 break;
822 for (nesting = 1;
823 (c = *++yyInput) != RPAREN || --nesting;
824 ) {
825 if (c == LPAREN) {
826 nesting++;
827 } else if (!IS7BIT(c) || c == '\0' || c == '\r'
828 || (c == '\\'
829 && ((c = *++yyInput) == '\0'
830 || !IS7BIT(c)))) {
831 /* Lexical error: bad comment. */
832 return '?';
833 }
834 }
835 yyInput++;
836 }
837
838 /* A number? */
839 if (CTYPE(isdigit, c) || c == '-' || c == '+') {
840 if (c == '-' || c == '+') {
841 sign = c == '-' ? -1 : 1;
842 yyInput++;
843 if (!CTYPE(isdigit, *yyInput)) {
844 /* Return the isolated plus or minus sign. */
845 --yyInput;
846 return *yyInput++;
847 }
848 } else {
849 sign = 0;
850 }
851 for (p = buff;
852 (c = *yyInput++) != '\0' && CTYPE(isdigit, c);
853 ) {
854 if (p < &buff[sizeof buff - 1])
855 *p++ = (char) c;
856 }
857 *p = '\0';
858 i = atoi(buff);
859
860 yyInput--;
861 yylval.Number = sign < 0 ? -i : i;
862 return sign ? tSNUMBER : tUNUMBER;
863 }
864
865 /* A word? */
866 if (CTYPE(isalpha, c)) {
867 for (p = buff;
868 (c = *yyInput++) == '.' || CTYPE(isalpha, c);
869 ) {
870 if (p < &buff[sizeof buff - 1])
871 *p++ = (char) (CTYPE(isupper, c) ? tolower(c) : c);
872 }
873 *p = '\0';
874 yyInput--;
875 return LookupWord(buff, (int) (p - buff));
876 }
877
878 return *yyInput++;
879 }
880
GetTimeInfo(TIMEINFO * Now)881 static int GetTimeInfo(TIMEINFO * Now)
882 {
883 static time_t LastTime;
884 static long LastTzone;
885 struct tm *tm;
886
887 #if defined(HAVE_GETTIMEOFDAY)
888 struct timeval tv;
889 #endif /* defined(HAVE_GETTIMEOFDAY) */
890 #if defined(DONT_HAVE_TM_GMTOFF)
891 struct tm local;
892 struct tm gmt;
893 #endif /* !defined(DONT_HAVE_TM_GMTOFF) */
894
895 /* Get the basic time. */
896 #if defined(HAVE_GETTIMEOFDAY)
897 if (gettimeofday(&tv, (struct timezone *) NULL) == -1)
898 return -1;
899 Now->time = tv.tv_sec;
900 Now->usec = tv.tv_usec;
901 #else
902 /* Can't check for -1 since that might be a time, I guess. */
903 (void) time(&Now->time);
904 Now->usec = 0;
905 #endif /* defined(HAVE_GETTIMEOFDAY) */
906
907 /* Now get the timezone if it's been an hour since the last time. */
908 if (Now->time - LastTime > 60 * 60) {
909 LastTime = Now->time;
910 if ((tm = localtime(&Now->time)) == NULL)
911 return -1;
912 #if defined(DONT_HAVE_TM_GMTOFF)
913 /* To get the timezone, compare localtime with GMT. */
914 local = *tm;
915 if ((tm = gmtime(&Now->time)) == NULL)
916 return -1;
917 gmt = *tm;
918
919 /* Assume we are never more than 24 hours away. */
920 LastTzone = gmt.tm_yday - local.tm_yday;
921 if (LastTzone > 1)
922 LastTzone = -24;
923 else if (LastTzone < -1)
924 LastTzone = 24;
925 else
926 LastTzone *= 24;
927
928 /* Scale in the hours and minutes; ignore seconds. */
929 LastTzone += gmt.tm_hour - local.tm_hour;
930 LastTzone *= 60;
931 LastTzone += gmt.tm_min - local.tm_min;
932 #else
933 LastTzone = (0 - tm->tm_gmtoff) / 60;
934 #endif /* defined(DONT_HAVE_TM_GMTOFF) */
935 }
936 Now->tzone = LastTzone;
937 return 0;
938 }
939
940 #if defined(YYBYACC) && defined(YYPURE) && defined(LY_FIND_LEAKS)
941 #undef YYPURE
942 #define YYPURE 1
943 static void yyfreestack(YYSTACKDATA *);
parsedate_leaks(void)944 static void parsedate_leaks(void)
945 {
946 yyfreestack(&yystack);
947 }
948 #endif
949
parsedate(char * p,TIMEINFO * now)950 time_t parsedate(char *p,
951 TIMEINFO * now)
952 {
953 struct tm *tm;
954 TIMEINFO ti;
955 time_t Start;
956
957 #if defined(YYBYACC) && defined(YYPURE) && defined(LY_FIND_LEAKS)
958 static int initialized;
959
960 if (!initialized) {
961 initialized = 1;
962 atexit(parsedate_leaks);
963 }
964 #endif
965
966 yyInput = p;
967 if (now == NULL) {
968 now = &ti;
969 (void) GetTimeInfo(&ti);
970 }
971
972 tm = localtime(&now->time);
973 yyYear = tm->tm_year + 1900;
974 yyMonth = tm->tm_mon + 1;
975 yyDay = tm->tm_mday;
976 yyTimezone = now->tzone;
977 if (tm->tm_isdst) /* Correct timezone offset for DST */
978 yyTimezone += DST_OFFSET * 60;
979 yyDSTmode = DSTmaybe;
980 yyHour = 0;
981 yyMinutes = 0;
982 yySeconds = 0;
983 yyMeridian = MER24;
984 yyRelSeconds = 0;
985 yyRelMonth = 0;
986 yyHaveDate = 0;
987 yyHaveRel = 0;
988 yyHaveTime = 0;
989
990 if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
991 return -1;
992
993 if (yyHaveDate || yyHaveTime) {
994 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
995 yyMeridian, yyDSTmode);
996 if ((long) Start < 0)
997 return -1;
998 } else {
999 Start = now->time;
1000 if (!yyHaveRel)
1001 Start -= (tm->tm_hour * 60L + tm->tm_min) * 60L + tm->tm_sec;
1002 }
1003
1004 Start += yyRelSeconds;
1005 if (yyRelMonth)
1006 Start += RelativeMonth(Start, yyRelMonth);
1007
1008 /* Have to do *something* with a legitimate -1 so it's distinguishable
1009 * from the error return value. (Alternately could set errno on error.) */
1010 return (Start == (time_t) -1) ? 0 : Start;
1011 }
1012 #line 1013 "y.tab.c"
1013
1014 #if YYDEBUG
1015 #include <stdio.h> /* needed for printf */
1016 #endif
1017
1018 #include <stdlib.h> /* needed for malloc, etc */
1019 #include <string.h> /* needed for memset */
1020
1021 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
yygrowstack(YYSTACKDATA * data)1022 static int yygrowstack(YYSTACKDATA *data)
1023 {
1024 int i;
1025 unsigned newsize;
1026 YYINT *newss;
1027 YYSTYPE *newvs;
1028
1029 if ((newsize = data->stacksize) == 0)
1030 newsize = YYINITSTACKSIZE;
1031 else if (newsize >= YYMAXDEPTH)
1032 return YYENOMEM;
1033 else if ((newsize *= 2) > YYMAXDEPTH)
1034 newsize = YYMAXDEPTH;
1035
1036 i = (int) (data->s_mark - data->s_base);
1037 newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss));
1038 if (newss == 0)
1039 return YYENOMEM;
1040
1041 data->s_base = newss;
1042 data->s_mark = newss + i;
1043
1044 newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1045 if (newvs == 0)
1046 return YYENOMEM;
1047
1048 data->l_base = newvs;
1049 data->l_mark = newvs + i;
1050
1051 data->stacksize = newsize;
1052 data->s_last = data->s_base + newsize - 1;
1053 return 0;
1054 }
1055
1056 #if YYPURE || defined(YY_NO_LEAKS)
yyfreestack(YYSTACKDATA * data)1057 static void yyfreestack(YYSTACKDATA *data)
1058 {
1059 free(data->s_base);
1060 free(data->l_base);
1061 memset(data, 0, sizeof(*data));
1062 }
1063 #else
1064 #define yyfreestack(data) /* nothing */
1065 #endif
1066
1067 #define YYABORT goto yyabort
1068 #define YYREJECT goto yyabort
1069 #define YYACCEPT goto yyaccept
1070 #define YYERROR goto yyerrlab
1071
1072 int
YYPARSE_DECL()1073 YYPARSE_DECL()
1074 {
1075 int yym, yyn, yystate;
1076 #if YYDEBUG
1077 const char *yys;
1078
1079 if ((yys = getenv("YYDEBUG")) != 0)
1080 {
1081 yyn = *yys;
1082 if (yyn >= '0' && yyn <= '9')
1083 yydebug = yyn - '0';
1084 }
1085 #endif
1086
1087 yym = 0;
1088 yyn = 0;
1089 yynerrs = 0;
1090 yyerrflag = 0;
1091 yychar = YYEMPTY;
1092 yystate = 0;
1093
1094 #if YYPURE
1095 memset(&yystack, 0, sizeof(yystack));
1096 #endif
1097
1098 if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
1099 yystack.s_mark = yystack.s_base;
1100 yystack.l_mark = yystack.l_base;
1101 yystate = 0;
1102 *yystack.s_mark = 0;
1103
1104 yyloop:
1105 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1106 if (yychar < 0)
1107 {
1108 yychar = YYLEX;
1109 if (yychar < 0) yychar = YYEOF;
1110 #if YYDEBUG
1111 if (yydebug)
1112 {
1113 if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
1114 printf("%sdebug: state %d, reading %d (%s)\n",
1115 YYPREFIX, yystate, yychar, yys);
1116 }
1117 #endif
1118 }
1119 if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
1120 yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
1121 {
1122 #if YYDEBUG
1123 if (yydebug)
1124 printf("%sdebug: state %d, shifting to state %d\n",
1125 YYPREFIX, yystate, yytable[yyn]);
1126 #endif
1127 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
1128 yystate = yytable[yyn];
1129 *++yystack.s_mark = yytable[yyn];
1130 *++yystack.l_mark = yylval;
1131 yychar = YYEMPTY;
1132 if (yyerrflag > 0) --yyerrflag;
1133 goto yyloop;
1134 }
1135 if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
1136 yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
1137 {
1138 yyn = yytable[yyn];
1139 goto yyreduce;
1140 }
1141 if (yyerrflag != 0) goto yyinrecovery;
1142
1143 YYERROR_CALL("syntax error");
1144
1145 goto yyerrlab; /* redundant goto avoids 'unused label' warning */
1146 yyerrlab:
1147 ++yynerrs;
1148
1149 yyinrecovery:
1150 if (yyerrflag < 3)
1151 {
1152 yyerrflag = 3;
1153 for (;;)
1154 {
1155 if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
1156 yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
1157 {
1158 #if YYDEBUG
1159 if (yydebug)
1160 printf("%sdebug: state %d, error recovery shifting\
1161 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1162 #endif
1163 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
1164 yystate = yytable[yyn];
1165 *++yystack.s_mark = yytable[yyn];
1166 *++yystack.l_mark = yylval;
1167 goto yyloop;
1168 }
1169 else
1170 {
1171 #if YYDEBUG
1172 if (yydebug)
1173 printf("%sdebug: error recovery discarding state %d\n",
1174 YYPREFIX, *yystack.s_mark);
1175 #endif
1176 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1177 --yystack.s_mark;
1178 --yystack.l_mark;
1179 }
1180 }
1181 }
1182 else
1183 {
1184 if (yychar == YYEOF) goto yyabort;
1185 #if YYDEBUG
1186 if (yydebug)
1187 {
1188 if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
1189 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1190 YYPREFIX, yystate, yychar, yys);
1191 }
1192 #endif
1193 yychar = YYEMPTY;
1194 goto yyloop;
1195 }
1196
1197 yyreduce:
1198 #if YYDEBUG
1199 if (yydebug)
1200 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1201 YYPREFIX, yystate, yyn, yyrule[yyn]);
1202 #endif
1203 yym = yylen[yyn];
1204 if (yym > 0)
1205 yyval = yystack.l_mark[1-yym];
1206 else
1207 memset(&yyval, 0, sizeof yyval);
1208
1209 switch (yyn)
1210 {
1211 case 3:
1212 #line 154 "./parsdate.y"
1213 {
1214 yyHaveTime++;
1215 #if defined(lint)
1216 /* I am compulsive about lint natterings... */
1217 if (yyHaveTime == -1) {
1218 YYERROR;
1219 }
1220 #endif /* defined(lint) */
1221 }
1222 break;
1223 case 4:
1224 #line 163 "./parsdate.y"
1225 {
1226 yyHaveTime++;
1227 yyTimezone = yystack.l_mark[0].Number;
1228 }
1229 break;
1230 case 5:
1231 #line 167 "./parsdate.y"
1232 {
1233 yyHaveDate++;
1234 }
1235 break;
1236 case 6:
1237 #line 170 "./parsdate.y"
1238 {
1239 yyHaveDate++;
1240 yyHaveTime++;
1241 }
1242 break;
1243 case 7:
1244 #line 174 "./parsdate.y"
1245 {
1246 yyHaveDate++;
1247 yyHaveTime++;
1248 yyTimezone = yystack.l_mark[0].Number;
1249 }
1250 break;
1251 case 8:
1252 #line 179 "./parsdate.y"
1253 {
1254 yyHaveRel = 1;
1255 }
1256 break;
1257 case 9:
1258 #line 184 "./parsdate.y"
1259 {
1260 if (yystack.l_mark[-1].Number < 100) {
1261 yyHour = yystack.l_mark[-1].Number;
1262 yyMinutes = 0;
1263 }
1264 else {
1265 yyHour = yystack.l_mark[-1].Number / 100;
1266 yyMinutes = yystack.l_mark[-1].Number % 100;
1267 }
1268 yySeconds = 0;
1269 yyMeridian = yystack.l_mark[0].Meridian;
1270 }
1271 break;
1272 case 10:
1273 #line 196 "./parsdate.y"
1274 {
1275 yyHour = yystack.l_mark[-3].Number;
1276 yyMinutes = yystack.l_mark[-1].Number;
1277 yySeconds = 0;
1278 yyMeridian = yystack.l_mark[0].Meridian;
1279 }
1280 break;
1281 case 11:
1282 #line 202 "./parsdate.y"
1283 {
1284 yyHour = yystack.l_mark[-3].Number;
1285 yyMinutes = yystack.l_mark[-1].Number;
1286 yyTimezone = yystack.l_mark[0].Number;
1287 yyMeridian = MER24;
1288 yyDSTmode = DSToff;
1289 }
1290 break;
1291 case 12:
1292 #line 209 "./parsdate.y"
1293 {
1294 yyHour = yystack.l_mark[-5].Number;
1295 yyMinutes = yystack.l_mark[-3].Number;
1296 yySeconds = yystack.l_mark[-1].Number;
1297 yyMeridian = yystack.l_mark[0].Meridian;
1298 }
1299 break;
1300 case 13:
1301 #line 215 "./parsdate.y"
1302 {
1303 yyHour = yystack.l_mark[-5].Number;
1304 yyMinutes = yystack.l_mark[-3].Number;
1305 yySeconds = yystack.l_mark[-1].Number;
1306 yyTimezone = yystack.l_mark[0].Number;
1307 yyMeridian = MER24;
1308 yyDSTmode = DSToff;
1309 }
1310 break;
1311 case 14:
1312 #line 225 "./parsdate.y"
1313 {
1314 yyval.Number = yystack.l_mark[0].Number;
1315 yyDSTmode = DSToff;
1316 }
1317 break;
1318 case 15:
1319 #line 229 "./parsdate.y"
1320 {
1321 yyval.Number = yystack.l_mark[0].Number;
1322 yyDSTmode = DSTon;
1323 }
1324 break;
1325 case 16:
1326 #line 233 "./parsdate.y"
1327 {
1328 yyTimezone = yystack.l_mark[-1].Number;
1329 yyDSTmode = DSTon;
1330 }
1331 break;
1332 case 17:
1333 #line 237 "./parsdate.y"
1334 {
1335 /* Only allow "GMT+300" and "GMT-0800" */
1336 if (yystack.l_mark[-1].Number != 0) {
1337 YYABORT;
1338 }
1339 yyval.Number = yystack.l_mark[0].Number;
1340 yyDSTmode = DSToff;
1341 }
1342 break;
1343 case 18:
1344 #line 245 "./parsdate.y"
1345 {
1346 yyval.Number = yystack.l_mark[0].Number;
1347 yyDSTmode = DSToff;
1348 }
1349 break;
1350 case 19:
1351 #line 251 "./parsdate.y"
1352 {
1353 int i;
1354
1355 /* Unix and GMT and numeric timezones -- a little confusing. */
1356 if ((int)yystack.l_mark[0].Number < 0) {
1357 /* Don't work with negative modulus. */
1358 yystack.l_mark[0].Number = -(int)yystack.l_mark[0].Number;
1359 if (yystack.l_mark[0].Number > 9999 || (i = (int) (yystack.l_mark[0].Number % 100)) >= 60) {
1360 YYABORT;
1361 }
1362 yyval.Number = (yystack.l_mark[0].Number / 100) * 60 + i;
1363 }
1364 else {
1365 if (yystack.l_mark[0].Number > 9999 || (i = (int) (yystack.l_mark[0].Number % 100)) >= 60) {
1366 YYABORT;
1367 }
1368 yyval.Number = -((yystack.l_mark[0].Number / 100) * 60 + i);
1369 }
1370 }
1371 break;
1372 case 20:
1373 #line 272 "./parsdate.y"
1374 {
1375 yyMonth = yystack.l_mark[-2].Number;
1376 yyDay = yystack.l_mark[0].Number;
1377 }
1378 break;
1379 case 21:
1380 #line 276 "./parsdate.y"
1381 {
1382 if (yystack.l_mark[-4].Number > 100) {
1383 yyYear = yystack.l_mark[-4].Number;
1384 yyMonth = yystack.l_mark[-2].Number;
1385 yyDay = yystack.l_mark[0].Number;
1386 }
1387 else {
1388 yyMonth = yystack.l_mark[-4].Number;
1389 yyDay = yystack.l_mark[-2].Number;
1390 yyYear = yystack.l_mark[0].Number;
1391 }
1392 }
1393 break;
1394 case 22:
1395 #line 288 "./parsdate.y"
1396 {
1397 yyMonth = yystack.l_mark[-1].Number;
1398 yyDay = yystack.l_mark[0].Number;
1399 }
1400 break;
1401 case 23:
1402 #line 292 "./parsdate.y"
1403 {
1404 yyMonth = yystack.l_mark[-3].Number;
1405 yyDay = yystack.l_mark[-2].Number;
1406 yyYear = yystack.l_mark[0].Number;
1407 }
1408 break;
1409 case 24:
1410 #line 297 "./parsdate.y"
1411 {
1412 yyDay = yystack.l_mark[-1].Number;
1413 yyMonth = yystack.l_mark[0].Number;
1414 }
1415 break;
1416 case 25:
1417 #line 301 "./parsdate.y"
1418 {
1419 yyDay = yystack.l_mark[-2].Number;
1420 yyMonth = yystack.l_mark[-1].Number;
1421 yyYear = yystack.l_mark[0].Number;
1422 }
1423 break;
1424 case 26:
1425 #line 306 "./parsdate.y"
1426 {
1427 yyDay = yystack.l_mark[-2].Number;
1428 yyMonth = yystack.l_mark[-1].Number;
1429 yyYear = yystack.l_mark[0].Number;
1430 }
1431 break;
1432 case 27:
1433 #line 311 "./parsdate.y"
1434 {
1435 yyDay = yystack.l_mark[-3].Number;
1436 yyMonth = yystack.l_mark[-1].Number;
1437 yyYear = -yystack.l_mark[0].Number;
1438 }
1439 break;
1440 case 28:
1441 #line 316 "./parsdate.y"
1442 {
1443 yyDay = yystack.l_mark[-2].Number;
1444 yyMonth = -yystack.l_mark[-1].Number;
1445 yyYear = -yystack.l_mark[0].Number;
1446 yyDSTmode = DSToff; /* assume midnight if no time given */
1447 yyTimezone = 0; /* Lynx assumes GMT for this format */
1448 }
1449 break;
1450 case 29:
1451 #line 325 "./parsdate.y"
1452 {
1453 yyMonth = yystack.l_mark[-7].Number;
1454 yyDay = yystack.l_mark[-6].Number;
1455 yyYear = yystack.l_mark[0].Number;
1456 yyHour = yystack.l_mark[-5].Number;
1457 yyMinutes = yystack.l_mark[-3].Number;
1458 yySeconds = yystack.l_mark[-1].Number;
1459 }
1460 break;
1461 case 30:
1462 #line 335 "./parsdate.y"
1463 {
1464 yyRelSeconds += yystack.l_mark[-1].Number * yystack.l_mark[0].Number;
1465 }
1466 break;
1467 case 31:
1468 #line 338 "./parsdate.y"
1469 {
1470 yyRelSeconds += yystack.l_mark[-1].Number * yystack.l_mark[0].Number;
1471 }
1472 break;
1473 case 32:
1474 #line 341 "./parsdate.y"
1475 {
1476 yyRelMonth += yystack.l_mark[-1].Number * yystack.l_mark[0].Number;
1477 }
1478 break;
1479 case 33:
1480 #line 344 "./parsdate.y"
1481 {
1482 yyRelMonth += yystack.l_mark[-1].Number * yystack.l_mark[0].Number;
1483 }
1484 break;
1485 case 34:
1486 #line 349 "./parsdate.y"
1487 {
1488 yyval.Meridian = MER24;
1489 }
1490 break;
1491 case 35:
1492 #line 352 "./parsdate.y"
1493 {
1494 yyval.Meridian = yystack.l_mark[0].Meridian;
1495 }
1496 break;
1497 #line 1498 "y.tab.c"
1498 }
1499 yystack.s_mark -= yym;
1500 yystate = *yystack.s_mark;
1501 yystack.l_mark -= yym;
1502 yym = yylhs[yyn];
1503 if (yystate == 0 && yym == 0)
1504 {
1505 #if YYDEBUG
1506 if (yydebug)
1507 printf("%sdebug: after reduction, shifting from state 0 to\
1508 state %d\n", YYPREFIX, YYFINAL);
1509 #endif
1510 yystate = YYFINAL;
1511 *++yystack.s_mark = YYFINAL;
1512 *++yystack.l_mark = yyval;
1513 if (yychar < 0)
1514 {
1515 yychar = YYLEX;
1516 if (yychar < 0) yychar = YYEOF;
1517 #if YYDEBUG
1518 if (yydebug)
1519 {
1520 if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
1521 printf("%sdebug: state %d, reading %d (%s)\n",
1522 YYPREFIX, YYFINAL, yychar, yys);
1523 }
1524 #endif
1525 }
1526 if (yychar == YYEOF) goto yyaccept;
1527 goto yyloop;
1528 }
1529 if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
1530 yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
1531 yystate = yytable[yyn];
1532 else
1533 yystate = yydgoto[yym];
1534 #if YYDEBUG
1535 if (yydebug)
1536 printf("%sdebug: after reduction, shifting from state %d \
1537 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1538 #endif
1539 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
1540 *++yystack.s_mark = (YYINT) yystate;
1541 *++yystack.l_mark = yyval;
1542 goto yyloop;
1543
1544 yyoverflow:
1545 YYERROR_CALL("yacc stack overflow");
1546
1547 yyabort:
1548 yyfreestack(&yystack);
1549 return (1);
1550
1551 yyaccept:
1552 yyfreestack(&yystack);
1553 return (0);
1554 }
1555