2 /* A Bison parser, made from getdate.y
5 #define YYBISON 1 /* Identify Bison output. */
10 # define tDAY_UNIT 260
12 # define tHOUR_UNIT 262
13 # define tLOCAL_ZONE 263
14 # define tMERIDIAN 264
15 # define tMINUTE_UNIT 265
17 # define tMONTH_UNIT 267
18 # define tSEC_UNIT 268
19 # define tYEAR_UNIT 269
26 /* Parse a string into an internal time stamp.
27 Copyright 1999, 2000 Free Software Foundation, Inc.
29 This program is free software; you can redistribute it and/or modify
30 it under the terms of the GNU General Public License as published by
31 the Free Software Foundation; either version 2, or (at your option)
34 This program is distributed in the hope that it will be useful,
35 but WITHOUT ANY WARRANTY; without even the implied warranty of
36 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 GNU General Public License for more details.
39 You should have received a copy of the GNU General Public License
40 along with this program; if not, write to the Free Software Foundation,
41 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
43 /* Originally written by Steven M. Bellovin <smb@research.att.com> while
44 at the University of North Carolina at Chapel Hill. Later tweaked by
45 a couple of people on Usenet. Completely overhauled by Rich $alz
46 <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
48 Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
49 the right thing about local DST. Unlike previous versions, this
50 version is reentrant. */
59 /* Since the code of getdate.y is not included in the Emacs executable
60 itself, there is no need to #define static in this file. Even if
61 the code were included in the Emacs executable, it probably
62 wouldn't do any harm to #undef it here; this will only cause
63 problems if we try to write to a static variable, which I don't
64 think this code needs to do. */
72 # include <stdlib.h> /* for `free'; used by Bison 1.27 */
75 #if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
76 # define IN_CTYPE_DOMAIN(c) 1
78 # define IN_CTYPE_DOMAIN(c) isascii (c)
81 #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
82 #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
83 #define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
84 #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
86 /* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
87 - Its arg may be any int or unsigned int; it need not be an unsigned char.
88 - It's guaranteed to evaluate its argument exactly once.
89 - It's typically faster.
90 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
91 only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless
92 it's important to use the locale's definition of `digit' even when the
93 host does not conform to Posix. */
94 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
96 #if STDC_HEADERS || HAVE_STRING_H
100 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
101 # define __attribute__(x)
104 #ifndef ATTRIBUTE_UNUSED
105 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
108 #define EPOCH_YEAR 1970
109 #define TM_YEAR_BASE 1900
111 #define HOUR(x) ((x) * 60)
113 /* An integer value, and the number of digits in its textual
121 /* An entry in the lexical lookup table. */
129 /* Meridian: am, pm, or 24-hour style. */
130 enum { MERam, MERpm, MER24 };
132 /* Information passed to and from the parser. */
135 /* The input string remaining to be parsed. */
138 /* N, if this is the Nth Tuesday. */
141 /* Day of week; Sunday is 0. */
144 /* tm_isdst flag for the local zone. */
147 /* Time zone, in minutes east of UTC. */
150 /* Style used for time. */
153 /* Gregorian year, month, day, hour, minutes, and seconds. */
161 /* Relative year, month, day, hour, minutes, and seconds. */
169 /* Counts of nonterminals of various flavors parsed so far. */
172 int local_zones_seen;
177 /* Table of local time zone abbrevations, terminated by a null entry. */
178 table local_time_zone_table[3];
181 #define PC (* (parser_control *) parm)
182 #define YYLEX_PARAM parm
183 #define YYPARSE_PARAM parm
185 static int yyerror ();
189 #line 172 "getdate.y"
200 #define YYFLAG -32768
203 /* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
204 #define YYTRANSLATE(x) ((unsigned)(x) <= 272 ? yytranslate[x] : 33)
206 /* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
207 static const char yytranslate[] =
209 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
210 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
211 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
212 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
213 2, 2, 2, 2, 20, 2, 2, 21, 2, 2,
214 2, 2, 2, 2, 2, 2, 2, 2, 19, 2,
215 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
216 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
217 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
218 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
219 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
220 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
221 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
222 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
223 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
224 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
225 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
226 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
227 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
228 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
229 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
230 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
231 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
232 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
233 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
234 2, 2, 2, 2, 2, 2, 1, 3, 4, 5,
235 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
240 static const short yyprhs[] =
242 0, 0, 1, 4, 6, 8, 10, 12, 14, 16,
243 18, 21, 26, 31, 38, 45, 47, 50, 52, 54,
244 57, 59, 62, 65, 69, 75, 79, 83, 86, 91,
245 94, 98, 101, 103, 106, 109, 111, 114, 117, 119,
246 122, 125, 127, 130, 133, 135, 138, 141, 143, 146,
249 static const short yyrhs[] =
251 -1, 22, 23, 0, 24, 0, 25, 0, 26, 0,
252 28, 0, 27, 0, 29, 0, 31, 0, 18, 10,
253 0, 18, 19, 18, 32, 0, 18, 19, 18, 17,
254 0, 18, 19, 18, 19, 18, 32, 0, 18, 19,
255 18, 19, 18, 17, 0, 9, 0, 9, 4, 0,
256 16, 0, 7, 0, 16, 4, 0, 5, 0, 5,
257 20, 0, 18, 5, 0, 18, 21, 18, 0, 18,
258 21, 18, 21, 18, 0, 18, 17, 17, 0, 18,
259 12, 17, 0, 12, 18, 0, 12, 18, 20, 18,
260 0, 18, 12, 0, 18, 12, 18, 0, 30, 3,
261 0, 30, 0, 18, 15, 0, 17, 15, 0, 15,
262 0, 18, 13, 0, 17, 13, 0, 13, 0, 18,
263 6, 0, 17, 6, 0, 6, 0, 18, 8, 0,
264 17, 8, 0, 8, 0, 18, 11, 0, 17, 11,
265 0, 11, 0, 18, 14, 0, 17, 14, 0, 14,
272 /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
273 static const short yyrline[] =
275 0, 189, 191, 194, 197, 199, 201, 203, 205, 207,
276 210, 218, 225, 233, 240, 251, 254, 258, 261, 263,
277 267, 273, 278, 285, 291, 311, 318, 326, 331, 337,
278 342, 350, 360, 363, 366, 368, 370, 372, 374, 376,
279 378, 380, 382, 384, 386, 388, 390, 392, 394, 396,
285 #if YYDEBUG != 0 || defined YYERROR_VERBOSE
287 /* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
288 static const char *const yytname[] =
290 "$", "error", "$undefined.", "tAGO", "tDST", "tDAY", "tDAY_UNIT",
291 "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT",
292 "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER",
293 "tUNUMBER", "':'", "','", "'/'", "spec", "item", "time", "local_zone",
294 "zone", "day", "date", "rel", "relunit", "number", "o_merid", NULL
298 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
299 static const short yyr1[] =
301 0, 22, 22, 23, 23, 23, 23, 23, 23, 23,
302 24, 24, 24, 24, 24, 25, 25, 26, 26, 26,
303 27, 27, 27, 28, 28, 28, 28, 28, 28, 28,
304 28, 29, 29, 30, 30, 30, 30, 30, 30, 30,
305 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
309 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
310 static const short yyr2[] =
312 0, 0, 2, 1, 1, 1, 1, 1, 1, 1,
313 2, 4, 4, 6, 6, 1, 2, 1, 1, 2,
314 1, 2, 2, 3, 5, 3, 3, 2, 4, 2,
315 3, 2, 1, 2, 2, 1, 2, 2, 1, 2,
316 2, 1, 2, 2, 1, 2, 2, 1, 2, 2,
320 /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
321 doesn't specify something else to do. Zero means the default is an
323 static const short yydefact[] =
325 1, 0, 20, 41, 18, 44, 15, 47, 0, 38,
326 50, 35, 17, 0, 51, 2, 3, 4, 5, 7,
327 6, 8, 32, 9, 21, 16, 27, 19, 40, 43,
328 46, 37, 49, 34, 22, 39, 42, 10, 45, 29,
329 36, 48, 33, 0, 0, 0, 31, 0, 26, 30,
330 25, 52, 23, 28, 53, 12, 0, 11, 0, 52,
334 static const short yydefgoto[] =
336 1, 15, 16, 17, 18, 19, 20, 21, 22, 23,
340 static const short yypact[] =
342 -32768, 0, 1,-32768,-32768,-32768, 19,-32768, -14,-32768,
343 -32768,-32768, 32, 26, 14,-32768,-32768,-32768,-32768,-32768,
344 -32768,-32768, 27,-32768,-32768,-32768, 22,-32768,-32768,-32768,
345 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -16,
346 -32768,-32768,-32768, 29, 25, 30,-32768, 31,-32768,-32768,
347 -32768, 28, 23,-32768,-32768,-32768, 33,-32768, 34, -7,
348 -32768,-32768,-32768, 50,-32768
351 static const short yypgoto[] =
353 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
361 static const short yytable[] =
363 63, 48, 49, 54, 26, 2, 3, 4, 5, 6,
364 61, 7, 8, 9, 10, 11, 12, 13, 14, 34,
365 35, 24, 36, 25, 37, 38, 39, 40, 41, 42,
366 46, 43, 28, 44, 29, 45, 27, 30, 54, 31,
367 32, 33, 47, 51, 58, 55, 50, 56, 52, 53,
371 static const short yycheck[] =
373 0, 17, 18, 10, 18, 5, 6, 7, 8, 9,
374 17, 11, 12, 13, 14, 15, 16, 17, 18, 5,
375 6, 20, 8, 4, 10, 11, 12, 13, 14, 15,
376 3, 17, 6, 19, 8, 21, 4, 11, 10, 13,
377 14, 15, 20, 18, 21, 17, 17, 19, 18, 18,
382 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
383 #line 3 "/opt/reb/share/bison/bison.simple"
385 /* Skeleton output parser for bison,
386 Copyright 1984, 1989, 1990, 2000, 2001 Free Software Foundation, Inc.
388 This program is free software; you can redistribute it and/or modify
389 it under the terms of the GNU General Public License as published by
390 the Free Software Foundation; either version 2, or (at your option)
393 This program is distributed in the hope that it will be useful,
394 but WITHOUT ANY WARRANTY; without even the implied warranty of
395 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
396 GNU General Public License for more details.
398 You should have received a copy of the GNU General Public License
399 along with this program; if not, write to the Free Software
400 Foundation, Inc., 59 Temple Place - Suite 330,
401 Boston, MA 02111-1307, USA. */
403 /* As a special exception, when this file is copied by Bison into a
404 Bison output file, you may use that output file without restriction.
405 This special exception was added by the Free Software Foundation
406 in version 1.24 of Bison. */
408 /* This is the parser code that is written into each bison parser when
409 the %semantic_parser declaration is not specified in the grammar.
410 It was written by Richard Stallman by simplifying the hairy parser
411 used when %semantic_parser is specified. */
413 #ifndef YYSTACK_USE_ALLOCA
415 # define YYSTACK_USE_ALLOCA 1
416 # else /* alloca not defined */
418 # define YYSTACK_USE_ALLOCA 1
419 # define alloca __builtin_alloca
420 # else /* not GNU C. */
421 # if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
422 # define YYSTACK_USE_ALLOCA 1
424 # else /* not sparc */
425 /* We think this test detects Watcom and Microsoft C. */
426 /* This used to test MSDOS, but that is a bad idea since that
427 symbol is in the user namespace. */
428 # if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
430 /* No need for malloc.h, which pollutes the namespace; instead,
431 just don't use alloca. */
434 # else /* not MSDOS, or __TURBOC__ */
436 /* I don't know what this was needed for, but it pollutes the
437 namespace. So I turned it off. rms, 2 May 1997. */
438 /* #include <malloc.h> */
440 # define YYSTACK_USE_ALLOCA 1
441 # else /* not MSDOS, or __TURBOC__, or _AIX */
443 /* haible@ilog.fr says this works for HPUX 9.05 and up, and on
444 HPUX 10. Eventually we can turn this on. */
446 # define YYSTACK_USE_ALLOCA 1
447 # define alloca __builtin_alloca
450 # endif /* not _AIX */
451 # endif /* not MSDOS, or __TURBOC__ */
452 # endif /* not sparc */
453 # endif /* not GNU C */
454 # endif /* alloca not defined */
455 #endif /* YYSTACK_USE_ALLOCA not defined */
457 #if YYSTACK_USE_ALLOCA
458 # define YYSTACK_ALLOC alloca
460 # define YYSTACK_ALLOC malloc
463 #define yyerrok (yyerrstatus = 0)
464 #define yyclearin (yychar = YYEMPTY)
467 #define YYACCEPT goto yyacceptlab
468 #define YYABORT goto yyabortlab
469 #define YYERROR goto yyerrlab1
470 /* Like YYERROR except do call yyerror. This remains here temporarily
471 to ease the transition to the new meaning of YYERROR, for GCC.
472 Once GCC version 2 has supplanted version 1, this can go. */
473 #define YYFAIL goto yyerrlab
474 #define YYRECOVERING() (!!yyerrstatus)
475 #define YYBACKUP(Token, Value) \
477 if (yychar == YYEMPTY && yylen == 1) \
481 yychar1 = YYTRANSLATE (yychar); \
487 yyerror ("syntax error: cannot back up"); \
493 #define YYERRCODE 256
496 /* YYLLOC_DEFAULT -- Compute the default location (before the actions
499 When YYLLOC_DEFAULT is run, CURRENT is set the location of the
500 first token. By default, to implement support for ranges, extend
501 its range to the last symbol. */
503 #ifndef YYLLOC_DEFAULT
504 # define YYLLOC_DEFAULT(Current, Rhs, N) \
505 Current.last_line = Rhs[N].last_line; \
506 Current.last_column = Rhs[N].last_column;
510 /* YYLEX -- calling `yylex' with the right arguments. */
515 # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
517 # define YYLEX yylex (&yylval, &yylloc)
519 # else /* !YYLSP_NEEDED */
521 # define YYLEX yylex (&yylval, YYLEX_PARAM)
523 # define YYLEX yylex (&yylval)
525 # endif /* !YYLSP_NEEDED */
527 # define YYLEX yylex ()
531 /* Enable debugging if requested. */
533 # define YYDPRINTF(Args) \
538 /* Nonzero means print parse trace. [The following comment makes no
539 sense to me. Could someone clarify it? --akim] Since this is
540 uninitialized, it does not stop multiple parsers from coexisting.
544 # define YYDPRINTF(Args)
545 #endif /* !YYDEBUG */
547 /* YYINITDEPTH -- initial size of the parser's stacks. */
549 # define YYINITDEPTH 200
552 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
553 if the built-in stack extension method is used). */
559 # define YYMAXDEPTH 10000
562 /* Define __yy_memcpy. Note that the size argument
563 should be passed with type unsigned int, because that is what the non-GCC
564 definitions require. With GCC, __builtin_memcpy takes an arg
565 of type size_t, but it can handle unsigned int. */
567 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
568 # define __yy_memcpy(To, From, Count) __builtin_memcpy (To, From, Count)
569 #else /* not GNU C or C++ */
571 /* This is the most reliable way to avoid incompatibilities
572 in available built-in functions on various systems. */
575 __yy_memcpy (to, from, count)
579 # else /* __cplusplus */
580 __yy_memcpy (char *to, const char *from, unsigned int count)
583 register const char *f = from;
584 register char *t = to;
585 register int i = count;
593 #line 212 "/opt/reb/share/bison/bison.simple"
596 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
597 into yyparse. The argument should have type void *.
598 It should actually point to an object.
599 Grammar actions can access the variable by casting it
600 to the proper pointer type. */
604 # define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
605 # define YYPARSE_PARAM_DECL
606 # else /* !__cplusplus */
607 # define YYPARSE_PARAM_ARG YYPARSE_PARAM
608 # define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
609 # endif /* !__cplusplus */
610 #else /* !YYPARSE_PARAM */
611 # define YYPARSE_PARAM_ARG
612 # define YYPARSE_PARAM_DECL
613 #endif /* !YYPARSE_PARAM */
615 /* Prevent warning if -Wstrict-prototypes. */
617 # ifdef YYPARSE_PARAM
618 int yyparse (void *);
624 /* YY_DECL_VARIABLES -- depending whether we use a pure parser,
625 variables are global, or local to YYPARSE. */
627 #define _YY_DECL_VARIABLES \
628 /* The lookahead symbol. */ \
631 /* The semantic value of the lookahead symbol. */ \
634 /* Number of parse errors so far. */ \
638 # define YY_DECL_VARIABLES \
641 /* Location data for the lookahead symbol. */ \
644 # define YY_DECL_VARIABLES \
649 /* If nonreentrant, generate the variables here. */
656 yyparse (YYPARSE_PARAM_ARG)
659 /* If reentrant, generate the variables here. */
664 register int yystate;
666 /* Number of tokens to shift before error messages enabled. */
668 /* Lookahead token as an internal (translated) token number. */
671 /* Three stacks and their tools:
672 `yyss': related to states,
673 `yysv': related to semantic values,
674 `yyls': related to locations.
676 Refer to the stacks thru separate pointers, to allow yyoverflow
677 to reallocate them elsewhere. */
679 /* The state stack. */
680 short yyssa[YYINITDEPTH];
682 register short *yyssp;
684 /* The semantic value stack. */
685 YYSTYPE yyvsa[YYINITDEPTH];
686 YYSTYPE *yyvs = yyvsa;
687 register YYSTYPE *yyvsp;
690 /* The location stack. */
691 YYLTYPE yylsa[YYINITDEPTH];
692 YYLTYPE *yyls = yylsa;
697 # define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
699 # define YYPOPSTACK (yyvsp--, yyssp--)
702 int yystacksize = YYINITDEPTH;
703 int yyfree_stacks = 0;
706 /* The variables used to return semantic value and location from the
713 /* When reducing, the number of symbols on the RHS of the reduced
717 YYDPRINTF ((stderr, "Starting parse\n"));
722 yychar = YYEMPTY; /* Cause a token to be read. */
724 /* Initialize stack pointers.
725 Waste one element of value and location stack
726 so that they stay on the same level as the state stack.
727 The wasted elements are never initialized. */
736 /*------------------------------------------------------------.
737 | yynewstate -- Push a new state, which is found in yystate. |
738 `------------------------------------------------------------*/
740 /* In all cases, when you get here, the value and location stacks
741 have just been pushed. so pushing a state here evens the stacks.
748 if (yyssp >= yyss + yystacksize - 1)
750 /* Give user a chance to reallocate the stack. Use copies of
751 these so that the &'s don't force the real ones into memory.
753 YYSTYPE *yyvs1 = yyvs;
756 YYLTYPE *yyls1 = yyls;
759 /* Get the current used size of the three stacks, in elements. */
760 int size = yyssp - yyss + 1;
763 /* Each stack pointer address is followed by the size of the
764 data in use in that stack, in bytes. */
766 /* This used to be a conditional around just the two extra args,
767 but that might be undefined if yyoverflow is a macro. */
768 yyoverflow ("parser stack overflow",
769 &yyss1, size * sizeof (*yyssp),
770 &yyvs1, size * sizeof (*yyvsp),
771 &yyls1, size * sizeof (*yylsp),
774 yyoverflow ("parser stack overflow",
775 &yyss1, size * sizeof (*yyssp),
776 &yyvs1, size * sizeof (*yyvsp),
780 yyss = yyss1; yyvs = yyvs1;
784 #else /* no yyoverflow */
785 /* Extend the stack our own way. */
786 if (yystacksize >= YYMAXDEPTH)
788 yyerror ("parser stack overflow");
800 if (yystacksize > YYMAXDEPTH)
801 yystacksize = YYMAXDEPTH;
802 # ifndef YYSTACK_USE_ALLOCA
805 yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
806 __yy_memcpy ((char *)yyss, (char *)yyss1,
807 size * (unsigned int) sizeof (*yyssp));
808 yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
809 __yy_memcpy ((char *)yyvs, (char *)yyvs1,
810 size * (unsigned int) sizeof (*yyvsp));
812 yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
813 __yy_memcpy ((char *)yyls, (char *)yyls1,
814 size * (unsigned int) sizeof (*yylsp));
816 #endif /* no yyoverflow */
818 yyssp = yyss + size - 1;
819 yyvsp = yyvs + size - 1;
821 yylsp = yyls + size - 1;
824 YYDPRINTF ((stderr, "Stack size increased to %d\n", yystacksize));
826 if (yyssp >= yyss + yystacksize - 1)
830 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
840 /* Do appropriate processing given the current state. */
841 /* Read a lookahead token if we need one and don't already have one. */
844 /* First try to decide what to do without reference to lookahead token. */
846 yyn = yypact[yystate];
850 /* Not known => get a lookahead token if don't already have one. */
852 /* yychar is either YYEMPTY or YYEOF
853 or a valid token in external form. */
855 if (yychar == YYEMPTY)
857 YYDPRINTF ((stderr, "Reading a token: "));
861 /* Convert token to internal form (in yychar1) for indexing tables with */
863 if (yychar <= 0) /* This means end of input. */
866 yychar = YYEOF; /* Don't call YYLEX any more */
868 YYDPRINTF ((stderr, "Now at end of input.\n"));
872 yychar1 = YYTRANSLATE (yychar);
875 /* We have to keep this `#if YYDEBUG', since we use variables
876 which are defined only if `YYDEBUG' is set. */
879 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
880 /* Give the individual parser a way to print the precise
881 meaning of a token, for further debugging info. */
883 YYPRINT (stderr, yychar, yylval);
885 fprintf (stderr, ")\n");
891 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
896 /* yyn is what to do for this token type in this state.
897 Negative => reduce, -yyn is rule number.
898 Positive => shift, yyn is new state.
899 New state is final state => don't bother to shift,
901 0, or most negative number => error. */
916 /* Shift the lookahead token. */
917 YYDPRINTF ((stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]));
919 /* Discard the token being shifted unless it is eof. */
928 /* Count tokens shifted since error; after three, turn off error
937 /*-----------------------------------------------------------.
938 | yydefault -- do the default action for the current state. |
939 `-----------------------------------------------------------*/
941 yyn = yydefact[yystate];
947 /*-----------------------------.
948 | yyreduce -- Do a reduction. |
949 `-----------------------------*/
951 /* yyn is the number of a rule to reduce with. */
954 /* If YYLEN is nonzero, implement the default value of the action:
957 Otherwise, the following line sets YYVAL to the semantic value of
958 the lookahead token. This behavior is undocumented and Bison
959 users should not rely upon it. Assigning to YYVAL
960 unconditionally makes the parser a bit smaller, and it avoids a
961 GCC warning that YYVAL may be used uninitialized. */
962 yyval = yyvsp[1-yylen];
965 /* Similarly for the default location. Let the user run additional
966 commands if for instance locations are ranges. */
967 yyloc = yylsp[1-yylen];
968 YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
972 /* We have to keep this `#if YYDEBUG', since we use variables which
973 are defined only if `YYDEBUG' is set. */
978 fprintf (stderr, "Reducing via rule %d (line %d), ",
981 /* Print the symbols being reduced, and their result. */
982 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
983 fprintf (stderr, "%s ", yytname[yyrhs[i]]);
984 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
991 #line 196 "getdate.y"
995 #line 198 "getdate.y"
996 { PC.local_zones_seen++; ;
999 #line 200 "getdate.y"
1000 { PC.zones_seen++; ;
1003 #line 202 "getdate.y"
1004 { PC.dates_seen++; ;
1007 #line 204 "getdate.y"
1011 #line 206 "getdate.y"
1015 #line 212 "getdate.y"
1017 PC.hour = yyvsp[-1].textintval.value;
1020 PC.meridian = yyvsp[0].intval;
1024 #line 219 "getdate.y"
1026 PC.hour = yyvsp[-3].textintval.value;
1027 PC.minutes = yyvsp[-1].textintval.value;
1029 PC.meridian = yyvsp[0].intval;
1033 #line 226 "getdate.y"
1035 PC.hour = yyvsp[-3].textintval.value;
1036 PC.minutes = yyvsp[-1].textintval.value;
1037 PC.meridian = MER24;
1039 PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
1043 #line 234 "getdate.y"
1045 PC.hour = yyvsp[-5].textintval.value;
1046 PC.minutes = yyvsp[-3].textintval.value;
1047 PC.seconds = yyvsp[-1].textintval.value;
1048 PC.meridian = yyvsp[0].intval;
1052 #line 241 "getdate.y"
1054 PC.hour = yyvsp[-5].textintval.value;
1055 PC.minutes = yyvsp[-3].textintval.value;
1056 PC.seconds = yyvsp[-1].textintval.value;
1057 PC.meridian = MER24;
1059 PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
1063 #line 253 "getdate.y"
1064 { PC.local_isdst = yyvsp[0].intval; ;
1067 #line 255 "getdate.y"
1068 { PC.local_isdst = yyvsp[-1].intval < 0 ? 1 : yyvsp[-1].intval + 1; ;
1071 #line 260 "getdate.y"
1072 { PC.time_zone = yyvsp[0].intval; ;
1075 #line 262 "getdate.y"
1076 { PC.time_zone = yyvsp[0].intval + 60; ;
1079 #line 264 "getdate.y"
1080 { PC.time_zone = yyvsp[-1].intval + 60; ;
1083 #line 269 "getdate.y"
1086 PC.day_number = yyvsp[0].intval;
1090 #line 274 "getdate.y"
1093 PC.day_number = yyvsp[-1].intval;
1097 #line 279 "getdate.y"
1099 PC.day_ordinal = yyvsp[-1].textintval.value;
1100 PC.day_number = yyvsp[0].intval;
1104 #line 287 "getdate.y"
1106 PC.month = yyvsp[-2].textintval.value;
1107 PC.day = yyvsp[0].textintval.value;
1111 #line 292 "getdate.y"
1113 /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
1114 otherwise as MM/DD/YY.
1115 The goal in recognizing YYYY/MM/DD is solely to support legacy
1116 machine-generated dates like those in an RCS log listing. If
1117 you want portability, use the ISO 8601 format. */
1118 if (4 <= yyvsp[-4].textintval.digits)
1120 PC.year = yyvsp[-4].textintval;
1121 PC.month = yyvsp[-2].textintval.value;
1122 PC.day = yyvsp[0].textintval.value;
1126 PC.month = yyvsp[-4].textintval.value;
1127 PC.day = yyvsp[-2].textintval.value;
1128 PC.year = yyvsp[0].textintval;
1133 #line 312 "getdate.y"
1135 /* ISO 8601 format. YYYY-MM-DD. */
1136 PC.year = yyvsp[-2].textintval;
1137 PC.month = -yyvsp[-1].textintval.value;
1138 PC.day = -yyvsp[0].textintval.value;
1142 #line 319 "getdate.y"
1144 /* e.g. 17-JUN-1992. */
1145 PC.day = yyvsp[-2].textintval.value;
1146 PC.month = yyvsp[-1].intval;
1147 PC.year.value = -yyvsp[0].textintval.value;
1148 PC.year.digits = yyvsp[0].textintval.digits;
1152 #line 327 "getdate.y"
1154 PC.month = yyvsp[-1].intval;
1155 PC.day = yyvsp[0].textintval.value;
1159 #line 332 "getdate.y"
1161 PC.month = yyvsp[-3].intval;
1162 PC.day = yyvsp[-2].textintval.value;
1163 PC.year = yyvsp[0].textintval;
1167 #line 338 "getdate.y"
1169 PC.day = yyvsp[-1].textintval.value;
1170 PC.month = yyvsp[0].intval;
1174 #line 343 "getdate.y"
1176 PC.day = yyvsp[-2].textintval.value;
1177 PC.month = yyvsp[-1].intval;
1178 PC.year = yyvsp[0].textintval;
1182 #line 352 "getdate.y"
1184 PC.rel_seconds = -PC.rel_seconds;
1185 PC.rel_minutes = -PC.rel_minutes;
1186 PC.rel_hour = -PC.rel_hour;
1187 PC.rel_day = -PC.rel_day;
1188 PC.rel_month = -PC.rel_month;
1189 PC.rel_year = -PC.rel_year;
1193 #line 365 "getdate.y"
1194 { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1197 #line 367 "getdate.y"
1198 { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1201 #line 369 "getdate.y"
1202 { PC.rel_year += yyvsp[0].intval; ;
1205 #line 371 "getdate.y"
1206 { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1209 #line 373 "getdate.y"
1210 { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1213 #line 375 "getdate.y"
1214 { PC.rel_month += yyvsp[0].intval; ;
1217 #line 377 "getdate.y"
1218 { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1221 #line 379 "getdate.y"
1222 { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1225 #line 381 "getdate.y"
1226 { PC.rel_day += yyvsp[0].intval ;
1229 #line 383 "getdate.y"
1230 { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1233 #line 385 "getdate.y"
1234 { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1237 #line 387 "getdate.y"
1238 { PC.rel_hour += yyvsp[0].intval ;
1241 #line 389 "getdate.y"
1242 { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1245 #line 391 "getdate.y"
1246 { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1249 #line 393 "getdate.y"
1250 { PC.rel_minutes += yyvsp[0].intval ;
1253 #line 395 "getdate.y"
1254 { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1257 #line 397 "getdate.y"
1258 { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; ;
1261 #line 399 "getdate.y"
1262 { PC.rel_seconds += yyvsp[0].intval; ;
1265 #line 404 "getdate.y"
1268 && ! PC.rels_seen && (PC.times_seen || 2 < yyvsp[0].textintval.digits))
1269 PC.year = yyvsp[0].textintval;
1272 if (4 < yyvsp[0].textintval.digits)
1275 PC.day = yyvsp[0].textintval.value % 100;
1276 PC.month = (yyvsp[0].textintval.value / 100) % 100;
1277 PC.year.value = yyvsp[0].textintval.value / 10000;
1278 PC.year.digits = yyvsp[0].textintval.digits - 4;
1283 if (yyvsp[0].textintval.digits <= 2)
1285 PC.hour = yyvsp[0].textintval.value;
1290 PC.hour = yyvsp[0].textintval.value / 100;
1291 PC.minutes = yyvsp[0].textintval.value % 100;
1294 PC.meridian = MER24;
1300 #line 440 "getdate.y"
1301 { yyval.intval = MER24; ;
1304 #line 442 "getdate.y"
1305 { yyval.intval = yyvsp[0].intval; ;
1309 #line 606 "/opt/reb/share/bison/bison.simple"
1321 short *ssp1 = yyss - 1;
1322 fprintf (stderr, "state stack now");
1323 while (ssp1 != yyssp)
1324 fprintf (stderr, " %d", *++ssp1);
1325 fprintf (stderr, "\n");
1334 /* Now `shift' the result of the reduction. Determine what state
1335 that goes to, based on the state we popped back to and the rule
1336 number reduced by. */
1340 yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1341 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1342 yystate = yytable[yystate];
1344 yystate = yydefgoto[yyn - YYNTBASE];
1349 /*------------------------------------.
1350 | yyerrlab -- here on detecting error |
1351 `------------------------------------*/
1353 /* If not already recovering from an error, report this error. */
1358 #ifdef YYERROR_VERBOSE
1359 yyn = yypact[yystate];
1361 if (yyn > YYFLAG && yyn < YYLAST)
1368 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1369 for (x = (yyn < 0 ? -yyn : 0);
1370 x < (int) (sizeof (yytname) / sizeof (char *)); x++)
1371 if (yycheck[x + yyn] == x)
1372 size += strlen (yytname[x]) + 15, count++;
1373 size += strlen ("parse error, unexpected `") + 1;
1374 size += strlen (yytname[YYTRANSLATE (yychar)]);
1375 msg = (char *) malloc (size);
1378 strcpy (msg, "parse error, unexpected `");
1379 strcat (msg, yytname[YYTRANSLATE (yychar)]);
1385 for (x = (yyn < 0 ? -yyn : 0);
1386 x < (int) (sizeof (yytname) / sizeof (char *)); x++)
1387 if (yycheck[x + yyn] == x)
1389 strcat (msg, count == 0 ? ", expecting `" : " or `");
1390 strcat (msg, yytname[x]);
1399 yyerror ("parse error; also virtual memory exceeded");
1402 #endif /* YYERROR_VERBOSE */
1403 yyerror ("parse error");
1408 /*--------------------------------------------------.
1409 | yyerrlab1 -- error raised explicitly by an action |
1410 `--------------------------------------------------*/
1412 if (yyerrstatus == 3)
1414 /* If just tried and failed to reuse lookahead token after an
1415 error, discard it. */
1417 /* return failure if at end of input */
1418 if (yychar == YYEOF)
1420 YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
1421 yychar, yytname[yychar1]));
1425 /* Else will try to reuse lookahead token after shifting the error
1428 yyerrstatus = 3; /* Each real token shifted decrements this */
1433 /*-------------------------------------------------------------------.
1434 | yyerrdefault -- current state does not do anything special for the |
1436 `-------------------------------------------------------------------*/
1439 /* This is wrong; only states that explicitly want error tokens
1440 should shift them. */
1442 /* If its default is to accept any token, ok. Otherwise pop it. */
1443 yyn = yydefact[yystate];
1449 /*---------------------------------------------------------------.
1450 | yyerrpop -- pop the current state because it cannot handle the |
1452 `---------------------------------------------------------------*/
1465 short *ssp1 = yyss - 1;
1466 fprintf (stderr, "Error: state stack now");
1467 while (ssp1 != yyssp)
1468 fprintf (stderr, " %d", *++ssp1);
1469 fprintf (stderr, "\n");
1477 yyn = yypact[yystate];
1482 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1499 YYDPRINTF ((stderr, "Shifting error token, "));
1510 /*-------------------------------------.
1511 | yyacceptlab -- YYACCEPT comes here. |
1512 `-------------------------------------*/
1525 /*-----------------------------------.
1526 | yyabortlab -- YYABORT comes here. |
1527 `-----------------------------------*/
1539 #line 445 "getdate.y"
1542 /* Include this file down here because bison inserts code above which
1543 may define-away `const'. We want the prototype for get_date to have
1544 the same signature as the function definition. */
1545 #include "getdate.h"
1548 struct tm *gmtime ();
1551 struct tm *localtime ();
1557 static table const meridian_table[] =
1559 { "AM", tMERIDIAN, MERam },
1560 { "A.M.", tMERIDIAN, MERam },
1561 { "PM", tMERIDIAN, MERpm },
1562 { "P.M.", tMERIDIAN, MERpm },
1566 static table const dst_table[] =
1571 static table const month_and_day_table[] =
1573 { "JANUARY", tMONTH, 1 },
1574 { "FEBRUARY", tMONTH, 2 },
1575 { "MARCH", tMONTH, 3 },
1576 { "APRIL", tMONTH, 4 },
1577 { "MAY", tMONTH, 5 },
1578 { "JUNE", tMONTH, 6 },
1579 { "JULY", tMONTH, 7 },
1580 { "AUGUST", tMONTH, 8 },
1581 { "SEPTEMBER",tMONTH, 9 },
1582 { "SEPT", tMONTH, 9 },
1583 { "OCTOBER", tMONTH, 10 },
1584 { "NOVEMBER", tMONTH, 11 },
1585 { "DECEMBER", tMONTH, 12 },
1586 { "SUNDAY", tDAY, 0 },
1587 { "MONDAY", tDAY, 1 },
1588 { "TUESDAY", tDAY, 2 },
1589 { "TUES", tDAY, 2 },
1590 { "WEDNESDAY",tDAY, 3 },
1591 { "WEDNES", tDAY, 3 },
1592 { "THURSDAY", tDAY, 4 },
1593 { "THUR", tDAY, 4 },
1594 { "THURS", tDAY, 4 },
1595 { "FRIDAY", tDAY, 5 },
1596 { "SATURDAY", tDAY, 6 },
1600 static table const time_units_table[] =
1602 { "YEAR", tYEAR_UNIT, 1 },
1603 { "MONTH", tMONTH_UNIT, 1 },
1604 { "FORTNIGHT",tDAY_UNIT, 14 },
1605 { "WEEK", tDAY_UNIT, 7 },
1606 { "DAY", tDAY_UNIT, 1 },
1607 { "HOUR", tHOUR_UNIT, 1 },
1608 { "MINUTE", tMINUTE_UNIT, 1 },
1609 { "MIN", tMINUTE_UNIT, 1 },
1610 { "SECOND", tSEC_UNIT, 1 },
1611 { "SEC", tSEC_UNIT, 1 },
1615 /* Assorted relative-time words. */
1616 static table const relative_time_table[] =
1618 { "TOMORROW", tMINUTE_UNIT, 24 * 60 },
1619 { "YESTERDAY",tMINUTE_UNIT, - (24 * 60) },
1620 { "TODAY", tMINUTE_UNIT, 0 },
1621 { "NOW", tMINUTE_UNIT, 0 },
1622 { "LAST", tUNUMBER, -1 },
1623 { "THIS", tUNUMBER, 0 },
1624 { "NEXT", tUNUMBER, 1 },
1625 { "FIRST", tUNUMBER, 1 },
1626 /*{ "SECOND", tUNUMBER, 2 }, */
1627 { "THIRD", tUNUMBER, 3 },
1628 { "FOURTH", tUNUMBER, 4 },
1629 { "FIFTH", tUNUMBER, 5 },
1630 { "SIXTH", tUNUMBER, 6 },
1631 { "SEVENTH", tUNUMBER, 7 },
1632 { "EIGHTH", tUNUMBER, 8 },
1633 { "NINTH", tUNUMBER, 9 },
1634 { "TENTH", tUNUMBER, 10 },
1635 { "ELEVENTH", tUNUMBER, 11 },
1636 { "TWELFTH", tUNUMBER, 12 },
1641 /* The time zone table. This table is necessarily incomplete, as time
1642 zone abbreviations are ambiguous; e.g. Australians interpret "EST"
1643 as Eastern time in Australia, not as US Eastern Standard Time.
1644 You cannot rely on getdate to handle arbitrary time zone
1645 abbreviations; use numeric abbreviations like `-0500' instead. */
1646 static table const time_zone_table[] =
1648 { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
1649 { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
1650 { "UTC", tZONE, HOUR ( 0) },
1651 { "WET", tZONE, HOUR ( 0) }, /* Western European */
1652 { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
1653 { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
1654 { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
1655 { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
1656 { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
1657 { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
1658 { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
1659 { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
1660 { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
1661 { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
1662 { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
1663 { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
1664 { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
1665 { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
1666 { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
1667 { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
1668 { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
1669 { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
1670 { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
1671 { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
1672 { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
1673 { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
1674 { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
1675 { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
1676 { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
1677 { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
1678 { "CET", tZONE, HOUR ( 1) }, /* Central European */
1679 { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
1680 { "MET", tZONE, HOUR ( 1) }, /* Middle European */
1681 { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
1682 { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
1683 { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
1684 { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
1685 { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
1686 { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
1687 { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
1688 { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
1689 { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
1690 { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
1691 { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
1692 { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
1693 { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
1694 { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
1695 { "GST", tZONE, HOUR (10) }, /* Guam Standard */
1696 { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
1697 { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
1701 /* Military time zone table. */
1702 static table const military_table[] =
1704 { "A", tZONE, -HOUR ( 1) },
1705 { "B", tZONE, -HOUR ( 2) },
1706 { "C", tZONE, -HOUR ( 3) },
1707 { "D", tZONE, -HOUR ( 4) },
1708 { "E", tZONE, -HOUR ( 5) },
1709 { "F", tZONE, -HOUR ( 6) },
1710 { "G", tZONE, -HOUR ( 7) },
1711 { "H", tZONE, -HOUR ( 8) },
1712 { "I", tZONE, -HOUR ( 9) },
1713 { "K", tZONE, -HOUR (10) },
1714 { "L", tZONE, -HOUR (11) },
1715 { "M", tZONE, -HOUR (12) },
1716 { "N", tZONE, HOUR ( 1) },
1717 { "O", tZONE, HOUR ( 2) },
1718 { "P", tZONE, HOUR ( 3) },
1719 { "Q", tZONE, HOUR ( 4) },
1720 { "R", tZONE, HOUR ( 5) },
1721 { "S", tZONE, HOUR ( 6) },
1722 { "T", tZONE, HOUR ( 7) },
1723 { "U", tZONE, HOUR ( 8) },
1724 { "V", tZONE, HOUR ( 9) },
1725 { "W", tZONE, HOUR (10) },
1726 { "X", tZONE, HOUR (11) },
1727 { "Y", tZONE, HOUR (12) },
1728 { "Z", tZONE, HOUR ( 0) },
1735 to_hour (int hours, int meridian)
1740 return 0 <= hours && hours < 24 ? hours : -1;
1742 return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
1744 return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
1752 to_year (textint textyear)
1754 int year = textyear.value;
1759 /* XPG4 suggests that years 00-68 map to 2000-2068, and
1760 years 69-99 map to 1969-1999. */
1761 if (textyear.digits == 2)
1762 year += year < 69 ? 2000 : 1900;
1767 static table const *
1768 lookup_zone (parser_control const *pc, char const *name)
1772 /* Try local zone abbreviations first; they're more likely to be right. */
1773 for (tp = pc->local_time_zone_table; tp->name; tp++)
1774 if (strcmp (name, tp->name) == 0)
1777 for (tp = time_zone_table; tp->name; tp++)
1778 if (strcmp (name, tp->name) == 0)
1784 #if ! HAVE_TM_GMTOFF
1785 /* Yield the difference between *A and *B,
1786 measured in seconds, ignoring leap seconds.
1787 The body of this function is taken directly from the GNU C Library;
1788 see src/strftime.c. */
1790 tm_diff (struct tm const *a, struct tm const *b)
1792 /* Compute intervening leap days correctly even if year is negative.
1793 Take care to avoid int overflow in leap day calculations,
1794 but it's OK to assume that A and B are close to each other. */
1795 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
1796 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
1797 int a100 = a4 / 25 - (a4 % 25 < 0);
1798 int b100 = b4 / 25 - (b4 % 25 < 0);
1799 int a400 = a100 >> 2;
1800 int b400 = b100 >> 2;
1801 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
1802 int years = a->tm_year - b->tm_year;
1803 int days = (365 * years + intervening_leap_days
1804 + (a->tm_yday - b->tm_yday));
1805 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
1806 + (a->tm_min - b->tm_min))
1807 + (a->tm_sec - b->tm_sec));
1809 #endif /* ! HAVE_TM_GMTOFF */
1811 static table const *
1812 lookup_word (parser_control const *pc, char *word)
1821 /* Make it uppercase. */
1822 for (p = word; *p; p++)
1823 if (ISLOWER ((unsigned char) *p))
1824 *p = toupper ((unsigned char) *p);
1826 for (tp = meridian_table; tp->name; tp++)
1827 if (strcmp (word, tp->name) == 0)
1830 /* See if we have an abbreviation for a month. */
1831 wordlen = strlen (word);
1832 abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
1834 for (tp = month_and_day_table; tp->name; tp++)
1835 if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
1838 if ((tp = lookup_zone (pc, word)))
1841 if (strcmp (word, dst_table[0].name) == 0)
1844 for (tp = time_units_table; tp->name; tp++)
1845 if (strcmp (word, tp->name) == 0)
1848 /* Strip off any plural and try the units table again. */
1849 if (word[wordlen - 1] == 'S')
1851 word[wordlen - 1] = '\0';
1852 for (tp = time_units_table; tp->name; tp++)
1853 if (strcmp (word, tp->name) == 0)
1855 word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
1858 for (tp = relative_time_table; tp->name; tp++)
1859 if (strcmp (word, tp->name) == 0)
1862 /* Military time zones. */
1864 for (tp = military_table; tp->name; tp++)
1865 if (word[0] == tp->name[0])
1868 /* Drop out any periods and try the time zone table again. */
1869 for (i = 0, p = q = word; (*p = *q); q++)
1874 if (i && (tp = lookup_zone (pc, word)))
1881 yylex (YYSTYPE *lvalp, parser_control *pc)
1888 while (c = *pc->input, ISSPACE (c))
1891 if (ISDIGIT (c) || c == '-' || c == '+')
1896 if (c == '-' || c == '+')
1898 sign = c == '-' ? -1 : 1;
1901 /* skip the '-' sign */
1910 value = 10 * value + c - '0';
1913 while (ISDIGIT (c));
1914 lvalp->textintval.value = sign < 0 ? -value : value;
1915 lvalp->textintval.digits = p - pc->input;
1917 return sign ? tSNUMBER : tUNUMBER;
1928 if (p < buff + sizeof buff - 1)
1932 while (ISALPHA (c) || c == '.');
1935 tp = lookup_word (pc, buff);
1938 lvalp->intval = tp->value;
1943 return *pc->input++;
1959 /* Do nothing if the parser reports an error. */
1961 yyerror (char *s ATTRIBUTE_UNUSED)
1966 /* Parse a date/time string P. Return the corresponding time_t value,
1967 or (time_t) -1 if there is an error. P can be an incomplete or
1968 relative time specification; if so, use *NOW as the basis for the
1971 get_date (const char *p, const time_t *now)
1973 time_t Start = now ? *now : time (0);
1974 struct tm *tmp = localtime (&Start);
1983 pc.year.value = tmp->tm_year + TM_YEAR_BASE;
1985 pc.month = tmp->tm_mon + 1;
1986 pc.day = tmp->tm_mday;
1987 pc.hour = tmp->tm_hour;
1988 pc.minutes = tmp->tm_min;
1989 pc.seconds = tmp->tm_sec;
1990 tm.tm_isdst = tmp->tm_isdst;
1992 pc.meridian = MER24;
2003 pc.local_zones_seen = 0;
2007 pc.local_time_zone_table[0].name = tmp->tm_zone;
2008 pc.local_time_zone_table[0].type = tLOCAL_ZONE;
2009 pc.local_time_zone_table[0].value = tmp->tm_isdst;
2010 pc.local_time_zone_table[1].name = 0;
2012 /* Probe the names used in the next three calendar quarters, looking
2013 for a tm_isdst different from the one we already have. */
2016 for (quarter = 1; quarter <= 3; quarter++)
2018 time_t probe = Start + quarter * (90 * 24 * 60 * 60);
2019 struct tm *probe_tm = localtime (&probe);
2020 if (probe_tm && probe_tm->tm_zone
2021 && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
2024 pc.local_time_zone_table[1].name = probe_tm->tm_zone;
2025 pc.local_time_zone_table[1].type = tLOCAL_ZONE;
2026 pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
2027 pc.local_time_zone_table[2].name = 0;
2037 extern char *tzname[];
2040 for (i = 0; i < 2; i++)
2042 pc.local_time_zone_table[i].name = tzname[i];
2043 pc.local_time_zone_table[i].type = tLOCAL_ZONE;
2044 pc.local_time_zone_table[i].value = i;
2046 pc.local_time_zone_table[i].name = 0;
2049 pc.local_time_zone_table[0].name = 0;
2053 if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
2054 && ! strcmp (pc.local_time_zone_table[0].name,
2055 pc.local_time_zone_table[1].name))
2057 /* This locale uses the same abbrevation for standard and
2058 daylight times. So if we see that abbreviation, we don't
2059 know whether it's daylight time. */
2060 pc.local_time_zone_table[0].value = -1;
2061 pc.local_time_zone_table[1].name = 0;
2064 if (yyparse (&pc) != 0
2065 || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen
2066 || 1 < (pc.local_zones_seen + pc.zones_seen)
2067 || (pc.local_zones_seen && 1 < pc.local_isdst))
2070 tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year;
2071 tm.tm_mon = pc.month - 1 + pc.rel_month;
2072 tm.tm_mday = pc.day + pc.rel_day;
2073 if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
2075 tm.tm_hour = to_hour (pc.hour, pc.meridian);
2078 tm.tm_min = pc.minutes;
2079 tm.tm_sec = pc.seconds;
2083 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
2086 /* Let mktime deduce tm_isdst if we have an absolute time stamp,
2087 or if the relative time stamp mentions days, months, or years. */
2088 if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day
2089 | pc.rel_month | pc.rel_year)
2092 /* But if the input explicitly specifies local time with or without
2093 DST, give mktime that information. */
2094 if (pc.local_zones_seen)
2095 tm.tm_isdst = pc.local_isdst;
2099 Start = mktime (&tm);
2101 if (Start == (time_t) -1)
2104 /* Guard against falsely reporting errors near the time_t boundaries
2105 when parsing times in other time zones. For example, if the min
2106 time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
2107 of UTC, then the min localtime value is 1970-01-01 08:00:00; if
2108 we apply mktime to 1970-01-01 00:00:00 we will get an error, so
2109 we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
2110 zone by 24 hours to compensate. This algorithm assumes that
2111 there is no DST transition within a day of the time_t boundaries. */
2115 if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)
2118 pc.time_zone += 24 * 60;
2123 pc.time_zone -= 24 * 60;
2125 Start = mktime (&tm);
2128 if (Start == (time_t) -1)
2132 if (pc.days_seen && ! pc.dates_seen)
2134 tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
2135 + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
2137 Start = mktime (&tm);
2138 if (Start == (time_t) -1)
2144 int delta = pc.time_zone * 60;
2145 #ifdef HAVE_TM_GMTOFF
2146 delta -= tm.tm_gmtoff;
2148 struct tm *gmt = gmtime (&Start);
2151 delta -= tm_diff (&tm, gmt);
2153 if ((Start < Start - delta) != (delta < 0))
2154 return -1; /* time_t overflow */
2158 /* Add relative hours, minutes, and seconds. Ignore leap seconds;
2159 i.e. "+ 10 minutes" means 600 seconds, even if one of them is a
2160 leap second. Typically this is not what the user wants, but it's
2161 too hard to do it the other way, because the time zone indicator
2162 must be applied before relative times, and if mktime is applied
2163 again the time zone will be lost. */
2166 long d1 = 60 * 60 * (long) pc.rel_hour;
2167 time_t t1 = t0 + d1;
2168 long d2 = 60 * (long) pc.rel_minutes;
2169 time_t t2 = t1 + d2;
2170 int d3 = pc.rel_seconds;
2171 time_t t3 = t2 + d3;
2172 if ((d1 / (60 * 60) ^ pc.rel_hour)
2173 | (d2 / 60 ^ pc.rel_minutes)
2174 | ((t0 + d1 < t0) ^ (d1 < 0))
2175 | ((t1 + d2 < t1) ^ (d2 < 0))
2176 | ((t2 + d3 < t2) ^ (d3 < 0)))
2189 main (int ac, char **av)
2194 printf ("Enter date, or blank line to exit.\n\t> ");
2197 buff[BUFSIZ - 1] = 0;
2198 while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
2200 d = get_date (buff, 0);
2201 if (d == (time_t) -1)
2202 printf ("Bad format - couldn't convert.\n");
2204 printf ("%s", ctime (&d));
2210 #endif /* defined TEST */