7 yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.37 2003/02/12 18:03:55 davidc Exp $";
14 #define yyclearin (yychar=(YYEMPTY))
15 #define yyerrok (yyerrflag=0)
16 #define YYRECOVERING() (yyerrflag!=0)
17 #if defined(__cplusplus) || __STDC__
18 static int yygrowstack(void);
20 static int yygrowstack();
26 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
27 ** at the University of North Carolina at Chapel Hill. Later tweaked by
28 ** a couple of people on Usenet. Completely overhauled by Rich $alz
29 ** <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
30 ** Further revised (removed obsolete constructs and cleaned up timezone
31 ** names) in August, 1991, by Rich. Paul Eggert <eggert@twinsun.com>
32 ** helped in September, 1992. Art Cancro <ajc@uncensored.citadel.org> cleaned
33 ** it up for ANSI C in December, 1999.
35 ** This grammar has six shift/reduce conflicts.
37 ** This code is in the public domain and has no copyright.
39 /* SUPPRESS 530 *//* Empty body for statement */
40 /* SUPPRESS 593 on yyerrlab *//* Label was not used */
41 /* SUPPRESS 593 on yynewstate *//* Label was not used */
42 /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
48 #include <sys/types.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
56 # include <sys/time.h>
63 # if !STDC_HEADERS && HAVE_MEMORY_H
72 #include "parsedate.h"
76 #define yyparse date_parse
77 #define yylex date_lex
78 #define yyerror date_error
81 /* See the LeapYears table in Convert. */
83 #define END_OF_TIME 2038
84 /* Constants for general time calculations. */
86 #define SECSPERDAY (24L * 60L * 60L)
87 /* Readability for TABLE stuff. */
88 #define HOUR(x) (x * 60)
92 #define IS7BIT(x) ((unsigned int)(x) < 0200)
94 #define SIZEOF(array) ((int)(sizeof array / sizeof array[0]))
95 #define ENDOF(array) (&array[SIZEOF(array)])
99 ** An entry in the lexical lookup table.
101 typedef struct _TABLE {
108 ** Daylight-savings mode: on, off, or not yet known.
110 typedef enum _DSTMODE {
111 DSTon, DSToff, DSTmaybe
115 ** Meridian: am, pm, or 24-hour style.
117 typedef enum _MERIDIAN {
123 ** Global variables. We could get rid of most of them by using a yacc
124 ** union, but this is more efficient. (This routine predates the
125 ** yacc %union construct.)
127 static char *yyInput;
128 static DSTMODE yyDSTmode;
129 static int yyHaveDate;
130 static int yyHaveRel;
131 static int yyHaveTime;
132 static time_t yyTimezone;
134 static time_t yyHour;
135 static time_t yyMinutes;
136 static time_t yyMonth;
137 static time_t yySeconds;
138 static time_t yyYear;
139 static MERIDIAN yyMeridian;
140 static time_t yyRelMonth;
141 static time_t yyRelSeconds;
144 static void date_error(char *);
145 #line 125 "parsedate.y"
148 enum _MERIDIAN Meridian;
151 #define YYERRCODE 256
154 #define tMERIDIAN 259
156 #define tMONTH_UNIT 261
157 #define tSEC_UNIT 262
161 const short yylhs[] = { -1,
162 0, 0, 4, 4, 4, 4, 5, 5, 5, 5,
163 5, 2, 2, 2, 2, 1, 6, 6, 6, 6,
164 6, 6, 6, 7, 7, 7, 7, 3, 3,
166 const short yylen[] = { 2,
167 0, 2, 1, 2, 1, 1, 2, 4, 4, 6,
168 6, 1, 1, 2, 1, 1, 3, 5, 2, 4,
169 2, 3, 5, 2, 2, 2, 2, 0, 1,
171 const short yydefred[] = { 1,
172 0, 0, 0, 0, 0, 2, 0, 5, 6, 0,
173 0, 26, 24, 29, 0, 27, 25, 0, 0, 7,
174 13, 16, 0, 15, 4, 0, 0, 22, 0, 0,
175 14, 0, 20, 0, 9, 8, 0, 23, 0, 18,
178 const short yydgoto[] = { 1,
179 24, 25, 20, 6, 7, 8, 9,
181 const short yysindex[] = { 0,
182 -239, -36, -248, -255, -47, 0, -232, 0, 0, -247,
183 -25, 0, 0, 0, -237, 0, 0, -235, -234, 0,
184 0, 0, -231, 0, 0, -226, -229, 0, -56, -11,
185 0, -227, 0, -225, 0, 0, -224, 0, -250, 0,
188 const short yyrindex[] = { 0,
189 0, 0, 0, 0, 1, 0, 22, 0, 0, 0,
190 12, 0, 0, 0, 28, 0, 0, 0, 0, 0,
191 0, 0, 23, 0, 0, 0, 0, 0, 3, 14,
192 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
195 const short yygindex[] = { 0,
196 -19, 0, -24, 0, 0, 0, 0,
198 #define YYTABLESIZE 291
199 const short yytable[] = { 19,
200 28, 34, 28, 31, 36, 12, 13, 10, 14, 35,
201 18, 19, 22, 17, 42, 11, 26, 2, 27, 41,
202 3, 3, 12, 4, 5, 21, 28, 21, 29, 30,
203 22, 22, 23, 32, 33, 37, 38, 0, 39, 40,
204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 14, 0, 0, 0, 22, 0, 0, 0,
221 0, 14, 15, 16, 17, 0, 0, 0, 0, 0,
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 28, 28, 28,
226 28, 0, 28, 28, 28, 28, 28, 28, 19, 0,
227 17, 19, 0, 17, 19, 19, 17, 17, 3, 12,
228 0, 3, 12, 0, 21, 3, 12, 21, 0, 0,
231 const short yycheck[] = { 47,
232 0, 58, 0, 23, 29, 261, 262, 44, 259, 29,
233 58, 0, 263, 0, 39, 264, 264, 257, 44, 39,
234 260, 0, 0, 263, 264, 258, 264, 0, 264, 264,
235 263, 263, 265, 260, 264, 47, 264, -1, 264, 264,
236 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
237 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
238 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
243 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
244 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
245 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
246 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
247 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
248 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
249 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
250 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
252 -1, -1, 259, -1, -1, -1, 263, -1, -1, -1,
253 -1, 259, 260, 261, 262, -1, -1, -1, -1, -1,
254 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
255 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
256 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
257 -1, -1, -1, -1, -1, -1, -1, 257, 258, 257,
258 258, -1, 260, 263, 264, 265, 264, 265, 257, -1,
259 257, 260, -1, 260, 263, 264, 263, 264, 257, 257,
260 -1, 260, 260, -1, 257, 264, 264, 260, -1, -1,
267 #define YYMAXTOKEN 265
269 const char * const yyname[] = {
270 "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,
271 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,
272 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,
273 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,
274 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,
275 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,
276 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",
277 "tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
279 const char * const yyrule[] = {
287 "time : tUNUMBER o_merid",
288 "time : tUNUMBER ':' tUNUMBER o_merid",
289 "time : tUNUMBER ':' tUNUMBER numzone",
290 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
291 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone",
294 "zone : tZONE numzone",
296 "numzone : tSNUMBER",
297 "date : tUNUMBER '/' tUNUMBER",
298 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
299 "date : tMONTH tUNUMBER",
300 "date : tMONTH tUNUMBER ',' tUNUMBER",
301 "date : tUNUMBER tMONTH",
302 "date : tUNUMBER tMONTH tUNUMBER",
303 "date : tDAY ',' tUNUMBER tMONTH tUNUMBER",
304 "rel : tSNUMBER tSEC_UNIT",
305 "rel : tUNUMBER tSEC_UNIT",
306 "rel : tSNUMBER tMONTH_UNIT",
307 "rel : tUNUMBER tMONTH_UNIT",
309 "o_merid : tMERIDIAN",
317 #define YYMAXDEPTH YYSTACKSIZE
320 #define YYSTACKSIZE YYMAXDEPTH
322 #define YYSTACKSIZE 10000
323 #define YYMAXDEPTH 10000
326 #define YYINITSTACKSIZE 200
339 #line 312 "parsedate.y"
341 /* Month and day table. */
342 static TABLE MonthDayTable[] = {
343 { "january", tMONTH, 1 },
344 { "february", tMONTH, 2 },
345 { "march", tMONTH, 3 },
346 { "april", tMONTH, 4 },
347 { "may", tMONTH, 5 },
348 { "june", tMONTH, 6 },
349 { "july", tMONTH, 7 },
350 { "august", tMONTH, 8 },
351 { "september", tMONTH, 9 },
352 { "october", tMONTH, 10 },
353 { "november", tMONTH, 11 },
354 { "december", tMONTH, 12 },
355 /* The value of the day isn't used... */
356 { "sunday", tDAY, 0 },
357 { "monday", tDAY, 0 },
358 { "tuesday", tDAY, 0 },
359 { "wednesday", tDAY, 0 },
360 { "thursday", tDAY, 0 },
361 { "friday", tDAY, 0 },
362 { "saturday", tDAY, 0 },
365 /* Time units table. */
366 static TABLE UnitsTable[] = {
367 { "year", tMONTH_UNIT, 12 },
368 { "month", tMONTH_UNIT, 1 },
369 { "week", tSEC_UNIT, 7L * 24 * 60 * 60 },
370 { "day", tSEC_UNIT, 1L * 24 * 60 * 60 },
371 { "hour", tSEC_UNIT, 60 * 60 },
372 { "minute", tSEC_UNIT, 60 },
373 { "min", tSEC_UNIT, 60 },
374 { "second", tSEC_UNIT, 1 },
375 { "sec", tSEC_UNIT, 1 },
378 /* Timezone table. */
379 static TABLE TimezoneTable[] = {
380 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
381 { "ut", tZONE, HOUR( 0) }, /* Universal */
382 { "utc", tZONE, HOUR( 0) }, /* Universal Coordinated */
383 { "cut", tZONE, HOUR( 0) }, /* Coordinated Universal */
384 { "z", tZONE, HOUR( 0) }, /* Greenwich Mean */
385 { "wet", tZONE, HOUR( 0) }, /* Western European */
386 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
387 { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
388 { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
389 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
390 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
391 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
392 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
393 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
394 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
395 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
396 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
397 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
398 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
399 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
400 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
401 { "akst", tZONE, HOUR( 9) }, /* Alaska Standard */
402 { "akdt", tDAYZONE, HOUR( 9) }, /* Alaska Daylight */
403 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
404 { "hast", tZONE, HOUR(10) }, /* Hawaii-Aleutian Standard */
405 { "hadt", tDAYZONE, HOUR(10) }, /* Hawaii-Aleutian Daylight */
406 { "ces", tDAYZONE, -HOUR(1) }, /* Central European Summer */
407 { "cest", tDAYZONE, -HOUR(1) }, /* Central European Summer */
408 { "mez", tZONE, -HOUR(1) }, /* Middle European */
409 { "mezt", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
410 { "cet", tZONE, -HOUR(1) }, /* Central European */
411 { "met", tZONE, -HOUR(1) }, /* Middle European */
412 { "eet", tZONE, -HOUR(2) }, /* Eastern Europe */
413 { "msk", tZONE, -HOUR(3) }, /* Moscow Winter */
414 { "msd", tDAYZONE, -HOUR(3) }, /* Moscow Summer */
415 { "wast", tZONE, -HOUR(8) }, /* West Australian Standard */
416 { "wadt", tDAYZONE, -HOUR(8) }, /* West Australian Daylight */
417 { "hkt", tZONE, -HOUR(8) }, /* Hong Kong */
418 { "cct", tZONE, -HOUR(8) }, /* China Coast */
419 { "jst", tZONE, -HOUR(9) }, /* Japan Standard */
420 { "kst", tZONE, -HOUR(9) }, /* Korean Standard */
421 { "kdt", tZONE, -HOUR(9) }, /* Korean Daylight */
422 { "cast", tZONE, -(HOUR(9)+30) }, /* Central Australian Standard */
423 { "cadt", tDAYZONE, -(HOUR(9)+30) }, /* Central Australian Daylight */
424 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
425 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
426 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
427 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
429 /* For completeness we include the following entries. */
432 /* Duplicate names. Either they conflict with a zone listed above
433 * (which is either more likely to be seen or just been in circulation
434 * longer), or they conflict with another zone in this section and
435 * we could not reasonably choose one over the other. */
436 { "fst", tZONE, HOUR( 2) }, /* Fernando De Noronha Standard */
437 { "fdt", tDAYZONE, HOUR( 2) }, /* Fernando De Noronha Daylight */
438 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
439 { "est", tZONE, HOUR( 3) }, /* Eastern Standard (Brazil) */
440 { "edt", tDAYZONE, HOUR( 3) }, /* Eastern Daylight (Brazil) */
441 { "wst", tZONE, HOUR( 4) }, /* Western Standard (Brazil) */
442 { "wdt", tDAYZONE, HOUR( 4) }, /* Western Daylight (Brazil) */
443 { "cst", tZONE, HOUR( 5) }, /* Chile Standard */
444 { "cdt", tDAYZONE, HOUR( 5) }, /* Chile Daylight */
445 { "ast", tZONE, HOUR( 5) }, /* Acre Standard */
446 { "adt", tDAYZONE, HOUR( 5) }, /* Acre Daylight */
447 { "cst", tZONE, HOUR( 5) }, /* Cuba Standard */
448 { "cdt", tDAYZONE, HOUR( 5) }, /* Cuba Daylight */
449 { "est", tZONE, HOUR( 6) }, /* Easter Island Standard */
450 { "edt", tDAYZONE, HOUR( 6) }, /* Easter Island Daylight */
451 { "sst", tZONE, HOUR(11) }, /* Samoa Standard */
452 { "ist", tZONE, -HOUR(2) }, /* Israel Standard */
453 { "idt", tDAYZONE, -HOUR(2) }, /* Israel Daylight */
454 { "idt", tDAYZONE, -(HOUR(3)+30) }, /* Iran Daylight */
455 { "ist", tZONE, -(HOUR(3)+30) }, /* Iran Standard */
456 { "cst", tZONE, -HOUR(8) }, /* China Standard */
457 { "cdt", tDAYZONE, -HOUR(8) }, /* China Daylight */
458 { "sst", tZONE, -HOUR(8) }, /* Singapore Standard */
460 /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
461 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
462 { "wat", tZONE, -HOUR(1) }, /* West Africa */
463 { "at", tZONE, HOUR( 2) }, /* Azores */
464 { "gst", tZONE, -HOUR(10) }, /* Guam Standard */
465 { "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
466 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
467 { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
468 { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
469 { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
470 { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
471 { "fwt", tZONE, -HOUR(1) }, /* French Winter */
472 { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
473 { "bt", tZONE, -HOUR(3) }, /* Baghdad */
474 { "it", tZONE, -(HOUR(3)+30) }, /* Iran */
475 { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
476 { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
477 { "ist", tZONE, -(HOUR(5)+30) }, /* Indian Standard */
478 { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
479 { "nst", tZONE, -HOUR(7) }, /* North Sumatra */
480 { "sst", tZONE, -HOUR(7) }, /* South Sumatra */
481 { "jt", tZONE, -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
482 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
483 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
484 { "cat", tZONE, HOUR(10) }, /* -- expired 1967 */
485 { "nt", tZONE, HOUR(11) }, /* -- expired 1967 */
486 { "ahst", tZONE, HOUR(10) }, /* -- expired 1983 */
487 { "hdt", tDAYZONE, HOUR(10) }, /* -- expired 1986 */
501 ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
503 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
505 if (Meridian == MER24) {
506 if (Hours < 0 || Hours > 23)
510 if (Hours < 1 || Hours > 12)
514 if (Meridian == MERpm)
517 return (Hours * 60L + Minutes) * 60L + Seconds;
522 Convert(time_t Month, time_t Day, time_t Year,
523 time_t Hours, time_t Minutes, time_t Seconds,
524 MERIDIAN Meridian, DSTMODE dst)
526 static int DaysNormal[13] = {
527 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
529 static int DaysLeap[13] = {
530 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
532 static int LeapYears[] = {
533 1972, 1976, 1980, 1984, 1988, 1992, 1996,
534 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
538 register time_t Julian;
548 for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
553 if (Year < EPOCH || Year > END_OF_TIME
554 || Month < 1 || Month > 12
555 /* NOSTRICT *//* conversion from long may lose accuracy */
556 || Day < 1 || Day > mp[(int)Month])
559 Julian = Day - 1 + (Year - EPOCH) * 365;
560 for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
563 for (i = 1; i < Month; i++)
565 Julian *= SECSPERDAY;
566 Julian += yyTimezone * 60L;
567 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
571 if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
572 Julian -= DST_OFFSET * 60L * 60L;
578 DSTcorrect(time_t Start, time_t Future)
583 StartDay = (localtime(&Start)->tm_hour + 1) % 24;
584 FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
585 return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
590 RelativeMonth(time_t Start, time_t RelMonth)
596 tm = localtime(&Start);
597 Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
599 Month = Month % 12 + 1;
600 return DSTcorrect(Start,
601 Convert(Month, (time_t)tm->tm_mday, Year,
602 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
608 LookupWord(char *buff, register int length)
618 /* See if we have an abbreviation for a month. */
619 if (length == 3 || (length == 4 && p[3] == '.'))
620 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
622 if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
623 yylval.Number = tp->value;
628 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
629 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
630 yylval.Number = tp->value;
634 /* Try for a timezone. */
635 for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
636 if (c == tp->name[0] && p[1] == tp->name[1]
637 && strcmp(p, tp->name) == 0) {
638 yylval.Number = tp->value;
642 /* Try the units table. */
643 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
644 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
645 yylval.Number = tp->value;
649 /* Strip off any plural and try the units table again. */
650 if (--length > 0 && p[length] == 's') {
652 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
653 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
655 yylval.Number = tp->value;
662 /* Drop out any periods. */
663 for (p = buff, q = (char*)buff; *q; q++)
668 /* Try the meridians. */
669 if (buff[1] == 'm' && buff[2] == '\0') {
670 if (buff[0] == 'a') {
671 yylval.Meridian = MERam;
674 if (buff[0] == 'p') {
675 yylval.Meridian = MERpm;
680 /* If we saw any periods, try the timezones again. */
681 if (p - buff != length) {
683 for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
684 if (c == tp->name[0] && p[1] == tp->name[1]
685 && strcmp(p, tp->name) == 0) {
686 yylval.Number = tp->value;
691 /* Unknown word -- assume GMT timezone. */
705 register int nesting;
708 /* Get first character after the whitespace. */
710 while (isspace(*yyInput))
714 /* Ignore RFC 822 comments, typically time zone names. */
717 for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
720 else if (!IS7BIT(c) || c == '\0' || c == '\r'
721 || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
722 /* Lexical error: bad comment. */
728 if (isdigit(c) || c == '-' || c == '+') {
729 if (c == '-' || c == '+') {
730 sign = c == '-' ? -1 : 1;
732 if (!isdigit(*yyInput))
733 /* Skip the plus or minus sign. */
738 for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
739 i = 10 * i + c - '0';
741 yylval.Number = sign < 0 ? -i : i;
742 return sign ? tSNUMBER : tUNUMBER;
747 for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
748 if (p < &buff[sizeof buff - 1])
749 *p++ = isupper(c) ? tolower(c) : c;
752 return LookupWord(buff, p - buff);
763 extern int date_parse(void);
772 yyDSTmode = DSTmaybe;
783 if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
786 if (yyHaveDate || yyHaveTime) {
787 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
788 yyMeridian, yyDSTmode);
795 Start += yyRelSeconds;
797 Start += RelativeMonth(Start, yyRelMonth);
799 /* Have to do *something* with a legitimate -1 so it's distinguishable
800 * from the error return value. (Alternately could set errno on error.) */
801 return Start == -1 ? 0 : Start;
813 main(int ac, char *av[])
822 (void)printf("Enter date, or blank line to exit.\n\t> ");
824 (void)printf("\t> ");
825 (void)fflush(stdout);
826 if (fgets(buff, sizeof buff, stdin) == NULL || buff[0] == '\n')
829 if (strcmp(buff, "yydebug") == 0) {
831 printf("yydebug = %s\n", yydebug ? "on" : "off");
835 d = parsedate(buff, (TIMEINFO *)NULL);
837 (void)printf("Bad format - couldn't convert.\n");
839 (void)printf("%s", ctime(&d));
847 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
848 static int yygrowstack()
854 if ((newsize = yystacksize) == 0)
855 newsize = YYINITSTACKSIZE;
856 else if (newsize >= YYMAXDEPTH)
858 else if ((newsize *= 2) > YYMAXDEPTH)
859 newsize = YYMAXDEPTH;
861 newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
862 (short *)malloc(newsize * sizeof *newss);
867 newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
868 (YYSTYPE *)malloc(newsize * sizeof *newvs);
873 yystacksize = newsize;
874 yysslim = yyss + newsize - 1;
878 #define YYABORT goto yyabort
879 #define YYREJECT goto yyabort
880 #define YYACCEPT goto yyaccept
881 #define YYERROR goto yyerrlab
883 #ifndef YYPARSE_PARAM
884 #if defined(__cplusplus) || __STDC__
885 #define YYPARSE_PARAM_ARG void
886 #define YYPARSE_PARAM_DECL
887 #else /* ! ANSI-C/C++ */
888 #define YYPARSE_PARAM_ARG
889 #define YYPARSE_PARAM_DECL
890 #endif /* ANSI-C/C++ */
891 #else /* YYPARSE_PARAM */
892 #ifndef YYPARSE_PARAM_TYPE
893 #define YYPARSE_PARAM_TYPE void *
895 #if defined(__cplusplus) || __STDC__
896 #define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM
897 #define YYPARSE_PARAM_DECL
898 #else /* ! ANSI-C/C++ */
899 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
900 #define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM;
901 #endif /* ANSI-C/C++ */
902 #endif /* ! YYPARSE_PARAM */
905 yyparse (YYPARSE_PARAM_ARG)
908 int yym, yyn, yystate;
912 if ((yys = getenv("YYDEBUG")))
915 if (yyn >= '0' && yyn <= '9')
924 if (yyss == NULL && yygrowstack()) goto yyoverflow;
927 *yyssp = yystate = 0;
930 if ((yyn = yydefred[yystate])) goto yyreduce;
933 if ((yychar = yylex()) < 0) yychar = 0;
938 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
939 if (!yys) yys = "illegal-symbol";
940 printf("%sdebug: state %d, reading %d (%s)\n",
941 YYPREFIX, yystate, yychar, yys);
945 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
946 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
950 printf("%sdebug: state %d, shifting to state %d\n",
951 YYPREFIX, yystate, yytable[yyn]);
953 if (yyssp >= yysslim && yygrowstack())
957 *++yyssp = yystate = yytable[yyn];
960 if (yyerrflag > 0) --yyerrflag;
963 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
964 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
969 if (yyerrflag) goto yyinrecovery;
970 #if defined(lint) || defined(__GNUC__)
974 yyerror("syntax error");
975 #if defined(lint) || defined(__GNUC__)
986 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
987 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
991 printf("%sdebug: state %d, error recovery shifting\
992 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
994 if (yyssp >= yysslim && yygrowstack())
998 *++yyssp = yystate = yytable[yyn];
1006 printf("%sdebug: error recovery discarding state %d\n",
1009 if (yyssp <= yyss) goto yyabort;
1017 if (yychar == 0) goto yyabort;
1022 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1023 if (!yys) yys = "illegal-symbol";
1024 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1025 YYPREFIX, yystate, yychar, yys);
1034 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1035 YYPREFIX, yystate, yyn, yyrule[yyn]);
1038 yyval = yyvsp[1-yym];
1042 #line 143 "parsedate.y"
1046 /* I am compulsive about lint natterings... */
1047 if (yyHaveTime == -1) {
1054 #line 152 "parsedate.y"
1057 yyTimezone = yyvsp[0].Number;
1061 #line 156 "parsedate.y"
1067 #line 159 "parsedate.y"
1073 #line 164 "parsedate.y"
1075 if (yyvsp[-1].Number < 100) {
1076 yyHour = yyvsp[-1].Number;
1080 yyHour = yyvsp[-1].Number / 100;
1081 yyMinutes = yyvsp[-1].Number % 100;
1084 yyMeridian = yyvsp[0].Meridian;
1088 #line 176 "parsedate.y"
1090 yyHour = yyvsp[-3].Number;
1091 yyMinutes = yyvsp[-1].Number;
1093 yyMeridian = yyvsp[0].Meridian;
1097 #line 182 "parsedate.y"
1099 yyHour = yyvsp[-3].Number;
1100 yyMinutes = yyvsp[-1].Number;
1101 yyTimezone = yyvsp[0].Number;
1107 #line 189 "parsedate.y"
1109 yyHour = yyvsp[-5].Number;
1110 yyMinutes = yyvsp[-3].Number;
1111 yySeconds = yyvsp[-1].Number;
1112 yyMeridian = yyvsp[0].Meridian;
1116 #line 195 "parsedate.y"
1118 yyHour = yyvsp[-5].Number;
1119 yyMinutes = yyvsp[-3].Number;
1120 yySeconds = yyvsp[-1].Number;
1121 yyTimezone = yyvsp[0].Number;
1127 #line 205 "parsedate.y"
1129 yyval.Number = yyvsp[0].Number;
1134 #line 209 "parsedate.y"
1136 yyval.Number = yyvsp[0].Number;
1141 #line 213 "parsedate.y"
1143 /* Only allow "GMT+300" and "GMT-0800" */
1144 if (yyvsp[-1].Number != 0) {
1147 yyval.Number = yyvsp[0].Number;
1152 #line 221 "parsedate.y"
1154 yyval.Number = yyvsp[0].Number;
1159 #line 227 "parsedate.y"
1163 /* Unix and GMT and numeric timezones -- a little confusing. */
1164 if (yyvsp[0].Number < 0) {
1165 /* Don't work with negative modulus. */
1166 yyvsp[0].Number = -yyvsp[0].Number;
1167 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1170 yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
1173 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1176 yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
1181 #line 248 "parsedate.y"
1183 yyMonth = yyvsp[-2].Number;
1184 yyDay = yyvsp[0].Number;
1188 #line 252 "parsedate.y"
1190 if (yyvsp[-4].Number > 100) {
1191 yyYear = yyvsp[-4].Number;
1192 yyMonth = yyvsp[-2].Number;
1193 yyDay = yyvsp[0].Number;
1196 yyMonth = yyvsp[-4].Number;
1197 yyDay = yyvsp[-2].Number;
1198 yyYear = yyvsp[0].Number;
1203 #line 264 "parsedate.y"
1205 yyMonth = yyvsp[-1].Number;
1206 yyDay = yyvsp[0].Number;
1210 #line 268 "parsedate.y"
1212 yyMonth = yyvsp[-3].Number;
1213 yyDay = yyvsp[-2].Number;
1214 yyYear = yyvsp[0].Number;
1218 #line 273 "parsedate.y"
1220 yyDay = yyvsp[-1].Number;
1221 yyMonth = yyvsp[0].Number;
1225 #line 277 "parsedate.y"
1227 yyDay = yyvsp[-2].Number;
1228 yyMonth = yyvsp[-1].Number;
1229 yyYear = yyvsp[0].Number;
1233 #line 282 "parsedate.y"
1235 yyDay = yyvsp[-2].Number;
1236 yyMonth = yyvsp[-1].Number;
1237 yyYear = yyvsp[0].Number;
1241 #line 289 "parsedate.y"
1243 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1247 #line 292 "parsedate.y"
1249 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1253 #line 295 "parsedate.y"
1255 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1259 #line 298 "parsedate.y"
1261 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1265 #line 303 "parsedate.y"
1267 yyval.Meridian = MER24;
1271 #line 306 "parsedate.y"
1273 yyval.Meridian = yyvsp[0].Meridian;
1276 #line 1277 "y.tab.c"
1282 if (yystate == 0 && yym == 0)
1286 printf("%sdebug: after reduction, shifting from state 0 to\
1287 state %d\n", YYPREFIX, YYFINAL);
1294 if ((yychar = yylex()) < 0) yychar = 0;
1299 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1300 if (!yys) yys = "illegal-symbol";
1301 printf("%sdebug: state %d, reading %d (%s)\n",
1302 YYPREFIX, YYFINAL, yychar, yys);
1306 if (yychar == 0) goto yyaccept;
1309 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1310 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1311 yystate = yytable[yyn];
1313 yystate = yydgoto[yym];
1316 printf("%sdebug: after reduction, shifting from state %d \
1317 to state %d\n", YYPREFIX, *yyssp, yystate);
1319 if (yyssp >= yysslim && yygrowstack())
1327 yyerror("yacc stack overflow");