2 static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
7 #define yyclearin (yychar=(-1))
8 #define yyerrok (yyerrflag=0)
9 #define YYRECOVERING (yyerrflag!=0)
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.
22 ** This grammar has six shift/reduce conflicts.
24 ** This code is in the public domain and has no copyright.
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 */
31 #include <sys/types.h>
37 #define yyparse date_parse
38 #define yylex date_lex
39 #define yyerror date_error
42 /* See the LeapYears table in Convert. */
44 #define END_OF_TIME 2038
45 /* Constants for general time calculations. */
47 #define SECSPERDAY (24L * 60L * 60L)
48 /* Readability for TABLE stuff. */
49 #define HOUR(x) (x * 60)
53 #define IS7BIT(x) ((unsigned int)(x) < 0200)
55 #define SIZEOF(array) ((int)(sizeof array / sizeof array[0]))
56 #define ENDOF(array) (&array[SIZEOF(array)])
60 ** An entry in the lexical lookup table.
62 typedef struct _TABLE {
69 ** Daylight-savings mode: on, off, or not yet known.
71 typedef enum _DSTMODE {
72 DSTon, DSToff, DSTmaybe
76 ** Meridian: am, pm, or 24-hour style.
78 typedef enum _MERIDIAN {
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.)
89 static DSTMODE yyDSTmode;
90 static int yyHaveDate;
92 static int yyHaveTime;
93 static time_t yyTimezone;
96 static time_t yyMinutes;
97 static time_t yyMonth;
98 static time_t yySeconds;
100 static MERIDIAN yyMeridian;
101 static time_t yyRelMonth;
102 static time_t yyRelSeconds;
105 extern struct tm *localtime();
107 static void date_error();
108 #line 100 "parsedate.y"
111 enum _MERIDIAN Meridian;
116 #define tMERIDIAN 259
118 #define tMONTH_UNIT 261
119 #define tSEC_UNIT 262
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,
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,
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,
141 short yydgoto[] = { 1,
142 24, 25, 20, 6, 7, 8, 9,
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,
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,
158 short yygindex[] = { 0,
159 -19, 0, -24, 0, 0, 0, 0,
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,
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,
230 #define YYMAXTOKEN 265
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",
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",
257 "zone : tZONE 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",
272 "o_merid : tMERIDIAN",
277 #define YYMAXDEPTH YYSTACKSIZE
280 #define YYSTACKSIZE YYMAXDEPTH
282 #define YYSTACKSIZE 500
283 #define YYMAXDEPTH 500
294 short yyss[YYSTACKSIZE];
295 YYSTYPE yyvs[YYSTACKSIZE];
296 #define yystacksize YYSTACKSIZE
297 #line 287 "parsedate.y"
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 },
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 },
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 */
387 /* For completeness we include the following entries. */
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 */
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 */
460 ToSeconds(Hours, Minutes, Seconds, Meridian)
466 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
468 if (Meridian == MER24) {
469 if (Hours < 0 || Hours > 23)
473 if (Hours < 1 || Hours > 12)
477 if (Meridian == MERpm)
480 return (Hours * 60L + Minutes) * 60L + Seconds;
485 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
495 static int DaysNormal[13] = {
496 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
498 static int DaysLeap[13] = {
499 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
501 static int LeapYears[] = {
502 1972, 1976, 1980, 1984, 1988, 1992, 1996,
503 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
507 register time_t Julian;
517 for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
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])
528 Julian = Day - 1 + (Year - EPOCH) * 365;
529 for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
532 for (i = 1; i < Month; i++)
534 Julian *= SECSPERDAY;
535 Julian += yyTimezone * 60L;
536 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
540 if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
541 Julian -= DST_OFFSET * 60L * 60L;
547 DSTcorrect(Start, Future)
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;
561 RelativeMonth(Start, RelMonth)
569 tm = localtime(&Start);
570 Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
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,
581 LookupWord(buff, length)
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++) {
597 if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
598 yylval.Number = tp->value;
603 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
604 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
605 yylval.Number = tp->value;
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;
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;
624 /* Strip off any plural and try the units table again. */
625 if (--length > 0 && p[length] == 's') {
627 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
628 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
630 yylval.Number = tp->value;
637 /* Drop out any periods. */
638 for (p = buff, q = (char*)buff; *q; q++)
643 /* Try the meridians. */
644 if (buff[1] == 'm' && buff[2] == '\0') {
645 if (buff[0] == 'a') {
646 yylval.Meridian = MERam;
649 if (buff[0] == 'p') {
650 yylval.Meridian = MERpm;
655 /* If we saw any periods, try the timezones again. */
656 if (p - buff != length) {
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;
666 /* Unknown word -- assume GMT timezone. */
680 register int nesting;
683 /* Get first character after the whitespace. */
685 while (isspace(*yyInput))
689 /* Ignore RFC 822 comments, typically time zone names. */
692 for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
695 else if (!IS7BIT(c) || c == '\0' || c == '\r'
696 || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
697 /* Lexical error: bad comment. */
703 if (isdigit(c) || c == '-' || c == '+') {
704 if (c == '-' || c == '+') {
705 sign = c == '-' ? -1 : 1;
707 if (!isdigit(*yyInput))
708 /* Skip the plus or minus sign. */
713 for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
714 i = 10 * i + c - '0';
716 yylval.Number = sign < 0 ? -i : i;
717 return sign ? tSNUMBER : tUNUMBER;
722 for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
723 if (p < &buff[sizeof buff - 1])
724 *p++ = isupper(c) ? tolower(c) : c;
727 return LookupWord(buff, p - buff);
739 extern int date_parse();
748 yyDSTmode = DSTmaybe;
759 if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
762 if (yyHaveDate || yyHaveTime) {
763 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
764 yyMeridian, yyDSTmode);
771 Start += yyRelSeconds;
773 Start += RelativeMonth(Start, yyRelMonth);
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;
800 (void)printf("Enter date, or blank line to exit.\n\t> ");
802 (void)printf("\t> ");
803 (void)fflush(stdout);
804 if (gets(buff) == NULL || buff[0] == '\n')
807 if (strcmp(buff, "yydebug") == 0) {
809 printf("yydebug = %s\n", yydebug ? "on" : "off");
813 d = parsedate(buff, (TIMEINFO *)NULL);
815 (void)printf("Bad format - couldn't convert.\n");
817 (void)printf("%s", ctime(&d));
825 #define YYABORT goto yyabort
826 #define YYREJECT goto yyabort
827 #define YYACCEPT goto yyaccept
828 #define YYERROR goto yyerrlab
832 register int yym, yyn, yystate;
835 extern char *getenv();
837 if (yys = getenv("YYDEBUG"))
840 if (yyn >= '0' && yyn <= '9')
851 *yyssp = yystate = 0;
854 if (yyn = yydefred[yystate]) goto yyreduce;
857 if ((yychar = yylex()) < 0) yychar = 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);
869 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
870 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
874 printf("%sdebug: state %d, shifting to state %d\n",
875 YYPREFIX, yystate, yytable[yyn]);
877 if (yyssp >= yyss + yystacksize - 1)
881 *++yyssp = yystate = yytable[yyn];
884 if (yyerrflag > 0) --yyerrflag;
887 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
888 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
893 if (yyerrflag) goto yyinrecovery;
898 yyerror("syntax error");
910 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
911 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
915 printf("%sdebug: state %d, error recovery shifting\
916 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
918 if (yyssp >= yyss + yystacksize - 1)
922 *++yyssp = yystate = yytable[yyn];
930 printf("%sdebug: error recovery discarding state %d\n",
933 if (yyssp <= yyss) goto yyabort;
941 if (yychar == 0) goto yyabort;
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);
958 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
959 YYPREFIX, yystate, yyn, yyrule[yyn]);
962 yyval = yyvsp[1-yym];
966 #line 118 "parsedate.y"
970 /* I am compulsive about lint natterings... */
971 if (yyHaveTime == -1) {
978 #line 127 "parsedate.y"
981 yyTimezone = yyvsp[0].Number;
985 #line 131 "parsedate.y"
991 #line 134 "parsedate.y"
997 #line 139 "parsedate.y"
999 if (yyvsp[-1].Number < 100) {
1000 yyHour = yyvsp[-1].Number;
1004 yyHour = yyvsp[-1].Number / 100;
1005 yyMinutes = yyvsp[-1].Number % 100;
1008 yyMeridian = yyvsp[0].Meridian;
1012 #line 151 "parsedate.y"
1014 yyHour = yyvsp[-3].Number;
1015 yyMinutes = yyvsp[-1].Number;
1017 yyMeridian = yyvsp[0].Meridian;
1021 #line 157 "parsedate.y"
1023 yyHour = yyvsp[-3].Number;
1024 yyMinutes = yyvsp[-1].Number;
1025 yyTimezone = yyvsp[0].Number;
1031 #line 164 "parsedate.y"
1033 yyHour = yyvsp[-5].Number;
1034 yyMinutes = yyvsp[-3].Number;
1035 yySeconds = yyvsp[-1].Number;
1036 yyMeridian = yyvsp[0].Meridian;
1040 #line 170 "parsedate.y"
1042 yyHour = yyvsp[-5].Number;
1043 yyMinutes = yyvsp[-3].Number;
1044 yySeconds = yyvsp[-1].Number;
1045 yyTimezone = yyvsp[0].Number;
1051 #line 180 "parsedate.y"
1053 yyval.Number = yyvsp[0].Number;
1058 #line 184 "parsedate.y"
1060 yyval.Number = yyvsp[0].Number;
1065 #line 188 "parsedate.y"
1067 /* Only allow "GMT+300" and "GMT-0800" */
1068 if (yyvsp[-1].Number != 0) {
1071 yyval.Number = yyvsp[0].Number;
1076 #line 196 "parsedate.y"
1078 yyval.Number = yyvsp[0].Number;
1083 #line 202 "parsedate.y"
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) {
1094 yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
1097 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
1100 yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
1105 #line 223 "parsedate.y"
1107 yyMonth = yyvsp[-2].Number;
1108 yyDay = yyvsp[0].Number;
1112 #line 227 "parsedate.y"
1114 if (yyvsp[-4].Number > 100) {
1115 yyYear = yyvsp[-4].Number;
1116 yyMonth = yyvsp[-2].Number;
1117 yyDay = yyvsp[0].Number;
1120 yyMonth = yyvsp[-4].Number;
1121 yyDay = yyvsp[-2].Number;
1122 yyYear = yyvsp[0].Number;
1127 #line 239 "parsedate.y"
1129 yyMonth = yyvsp[-1].Number;
1130 yyDay = yyvsp[0].Number;
1134 #line 243 "parsedate.y"
1136 yyMonth = yyvsp[-3].Number;
1137 yyDay = yyvsp[-2].Number;
1138 yyYear = yyvsp[0].Number;
1142 #line 248 "parsedate.y"
1144 yyDay = yyvsp[-1].Number;
1145 yyMonth = yyvsp[0].Number;
1149 #line 252 "parsedate.y"
1151 yyDay = yyvsp[-2].Number;
1152 yyMonth = yyvsp[-1].Number;
1153 yyYear = yyvsp[0].Number;
1157 #line 257 "parsedate.y"
1159 yyDay = yyvsp[-2].Number;
1160 yyMonth = yyvsp[-1].Number;
1161 yyYear = yyvsp[0].Number;
1165 #line 264 "parsedate.y"
1167 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1171 #line 267 "parsedate.y"
1173 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
1177 #line 270 "parsedate.y"
1179 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1183 #line 273 "parsedate.y"
1185 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1189 #line 278 "parsedate.y"
1191 yyval.Meridian = MER24;
1195 #line 281 "parsedate.y"
1197 yyval.Meridian = yyvsp[0].Meridian;
1200 #line 1201 "y.tab.c"
1206 if (yystate == 0 && yym == 0)
1210 printf("%sdebug: after reduction, shifting from state 0 to\
1211 state %d\n", YYPREFIX, YYFINAL);
1218 if ((yychar = yylex()) < 0) yychar = 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);
1230 if (yychar == 0) goto yyaccept;
1233 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1234 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1235 yystate = yytable[yyn];
1237 yystate = yydgoto[yym];
1240 printf("%sdebug: after reduction, shifting from state %d \
1241 to state %d\n", YYPREFIX, *yyssp, yystate);
1243 if (yyssp >= yyss + yystacksize - 1)
1251 yyerror("yacc stack overflow");