2 /* A Bison parser, made from parsedate.y with Bison version GNU Bison version 1.22
5 #define YYBISON 1 /* Identify Bison output. */
11 #define tMONTH_UNIT 262
21 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
22 ** at the University of North Carolina at Chapel Hill. Later tweaked by
23 ** a couple of people on Usenet. Completely overhauled by Rich $alz
24 ** <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
25 ** Further revised (removed obsolete constructs and cleaned up timezone
26 ** names) in August, 1991, by Rich. Paul Eggert <eggert@twinsun.com>
27 ** helped in September, 1992.
29 ** This grammar has six shift/reduce conflicts.
31 ** This code is in the public domain and has no copyright.
33 /* SUPPRESS 530 *//* Empty body for statement */
34 /* SUPPRESS 593 on yyerrlab *//* Label was not used */
35 /* SUPPRESS 593 on yynewstate *//* Label was not used */
36 /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
38 #include <sys/types.h>
44 #define yyparse date_parse
45 #define yylex date_lex
46 #define yyerror date_error
49 /* See the LeapYears table in Convert. */
51 #define END_OF_TIME 2038
52 /* Constants for general time calculations. */
54 #define SECSPERDAY (24L * 60L * 60L)
55 /* Readability for TABLE stuff. */
56 #define HOUR(x) (x * 60)
60 #define IS7BIT(x) ((unsigned int)(x) < 0200)
62 #define SIZEOF(array) ((int)(sizeof array / sizeof array[0]))
63 #define ENDOF(array) (&array[SIZEOF(array)])
67 ** An entry in the lexical lookup table.
69 typedef struct _TABLE {
76 ** Daylight-savings mode: on, off, or not yet known.
78 typedef enum _DSTMODE {
79 DSTon, DSToff, DSTmaybe
83 ** Meridian: am, pm, or 24-hour style.
85 typedef enum _MERIDIAN {
91 ** Global variables. We could get rid of most of them by using a yacc
92 ** union, but this is more efficient. (This routine predates the
93 ** yacc %union construct.)
96 static DSTMODE yyDSTmode;
97 static int yyHaveDate;
99 static int yyHaveTime;
100 static time_t yyTimezone;
102 static time_t yyHour;
103 static time_t yyMinutes;
104 static time_t yyMonth;
105 static time_t yySeconds;
106 static time_t yyYear;
107 static MERIDIAN yyMeridian;
108 static time_t yyRelMonth;
109 static time_t yyRelSeconds;
112 extern struct tm *localtime();
114 static void date_error();
116 #line 100 "parsedate.y"
119 enum _MERIDIAN Meridian;
135 #define YYLTYPE yyltype
149 #define YYFLAG -32768
152 #define YYTRANSLATE(x) ((unsigned)(x) <= 266 ? yytranslate[x] : 23)
154 static const char yytranslate[] = { 0,
155 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
156 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
157 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
158 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
159 2, 2, 2, 14, 2, 2, 13, 2, 2, 2,
160 2, 2, 2, 2, 2, 2, 2, 12, 2, 2,
161 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
164 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
165 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
166 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
167 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
168 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
169 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
170 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
171 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
172 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
173 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
174 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
175 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
176 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
177 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
178 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
179 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
180 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
185 static const short yyprhs[] = { 0,
186 0, 1, 4, 6, 9, 11, 13, 16, 21, 26,
187 33, 40, 42, 44, 47, 49, 51, 55, 61, 64,
188 69, 72, 76, 82, 85, 88, 91, 94, 95
191 static const short yyrhs[] = { -1,
192 15, 16, 0, 17, 0, 17, 18, 0, 20, 0,
193 21, 0, 10, 22, 0, 10, 12, 10, 22, 0,
194 10, 12, 10, 19, 0, 10, 12, 10, 12, 10,
195 22, 0, 10, 12, 10, 12, 10, 19, 0, 11,
196 0, 4, 0, 11, 19, 0, 19, 0, 9, 0,
197 10, 13, 10, 0, 10, 13, 10, 13, 10, 0,
198 6, 10, 0, 6, 10, 14, 10, 0, 10, 6,
199 0, 10, 6, 10, 0, 3, 14, 10, 6, 10,
200 0, 9, 8, 0, 10, 8, 0, 9, 7, 0,
207 static const short yyrline[] = { 0,
208 114, 115, 118, 127, 131, 134, 139, 151, 157, 164,
209 170, 180, 184, 188, 196, 202, 223, 227, 239, 243,
210 248, 252, 257, 264, 267, 270, 273, 278, 281
213 static const char * const yytname[] = { "$","error","$illegal.","tDAY","tDAYZONE",
214 "tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
215 "':'","'/'","','","spec","item","time","zone","numzone","date","rel","o_merid",
220 static const short yyr1[] = { 0,
221 15, 15, 16, 16, 16, 16, 17, 17, 17, 17,
222 17, 18, 18, 18, 18, 19, 20, 20, 20, 20,
223 20, 20, 20, 21, 21, 21, 21, 22, 22
226 static const short yyr2[] = { 0,
227 0, 2, 1, 2, 1, 1, 2, 4, 4, 6,
228 6, 1, 1, 2, 1, 1, 3, 5, 2, 4,
229 2, 3, 5, 2, 2, 2, 2, 0, 1
232 static const short yydefact[] = { 1,
233 0, 0, 0, 0, 28, 2, 3, 5, 6, 0,
234 19, 26, 24, 29, 21, 27, 25, 0, 0, 7,
235 13, 16, 12, 4, 15, 0, 0, 22, 28, 17,
236 14, 0, 20, 0, 9, 8, 0, 23, 28, 18,
240 static const short yydefgoto[] = { 1,
241 6, 7, 24, 25, 8, 9, 20
244 static const short yypact[] = {-32768,
245 1, -11, 11, 20, 12,-32768, 4,-32768,-32768, 13,
246 16,-32768,-32768,-32768, 21,-32768,-32768, 22, 23,-32768,
247 -32768,-32768, 5,-32768,-32768, 28, 25,-32768, 17, 24,
248 -32768, 26,-32768, 29,-32768,-32768, 30,-32768, 0,-32768,
249 -32768,-32768, 38,-32768
252 static const short yypgoto[] = {-32768,
253 -32768,-32768,-32768, -23,-32768,-32768, -27
260 static const short yytable[] = { 31,
261 43, 36, 10, 2, 14, 35, 3, 21, 22, 4,
262 5, 42, 22, 22, 23, 41, 14, 15, 16, 17,
263 11, 14, 26, 18, 19, 22, 12, 13, 34, 27,
264 28, 29, 30, 32, 33, 38, 37, 44, 39, 40
267 static const short yycheck[] = { 23,
268 0, 29, 14, 3, 5, 29, 6, 4, 9, 9,
269 10, 39, 9, 9, 11, 39, 5, 6, 7, 8,
270 10, 5, 10, 12, 13, 9, 7, 8, 12, 14,
271 10, 10, 10, 6, 10, 10, 13, 0, 10, 10
273 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
274 #line 3 "/usr/lib/bison.simple"
276 /* Skeleton output parser for bison,
277 Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
279 This program is free software; you can redistribute it and/or modify
280 it under the terms of the GNU General Public License as published by
281 the Free Software Foundation; either version 1, or (at your option)
284 This program is distributed in the hope that it will be useful,
285 but WITHOUT ANY WARRANTY; without even the implied warranty of
286 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287 GNU General Public License for more details.
289 You should have received a copy of the GNU General Public License
290 along with this program; if not, write to the Free Software
291 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
296 #define alloca __builtin_alloca
297 #else /* not GNU C. */
298 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
300 #else /* not sparc */
301 #if defined (MSDOS) && !defined (__TURBOC__)
303 #else /* not MSDOS, or __TURBOC__ */
307 #else /* not MSDOS, __TURBOC__, or _AIX */
311 void *alloca (unsigned int);
313 #else /* not __cplusplus */
315 #endif /* not __cplusplus */
317 #endif /* not _AIX */
318 #endif /* not MSDOS, or __TURBOC__ */
319 #endif /* not sparc. */
320 #endif /* not GNU C. */
321 #endif /* alloca not defined. */
323 /* This is the parser code that is written into each bison parser
324 when the %semantic_parser declaration is not specified in the grammar.
325 It was written by Richard Stallman by simplifying the hairy parser
326 used when %semantic_parser is specified. */
328 /* Note: there must be only one dollar sign in this file.
329 It is replaced by the list of actions, each action
330 as one case of the switch. */
332 #define yyerrok (yyerrstatus = 0)
333 #define yyclearin (yychar = YYEMPTY)
336 #define YYACCEPT return(0)
337 #define YYABORT return(1)
338 #define YYERROR goto yyerrlab1
339 /* Like YYERROR except do call yyerror.
340 This remains here temporarily to ease the
341 transition to the new meaning of YYERROR, for GCC.
342 Once GCC version 2 has supplanted version 1, this can go. */
343 #define YYFAIL goto yyerrlab
344 #define YYRECOVERING() (!!yyerrstatus)
345 #define YYBACKUP(token, value) \
347 if (yychar == YYEMPTY && yylen == 1) \
348 { yychar = (token), yylval = (value); \
349 yychar1 = YYTRANSLATE (yychar); \
354 { yyerror ("syntax error: cannot back up"); YYERROR; } \
358 #define YYERRCODE 256
361 #define YYLEX yylex()
366 #define YYLEX yylex(&yylval, &yylloc)
368 #define YYLEX yylex(&yylval)
372 /* If nonreentrant, generate the variables here */
376 int yychar; /* the lookahead symbol */
377 YYSTYPE yylval; /* the semantic value of the */
378 /* lookahead symbol */
381 YYLTYPE yylloc; /* location data for the lookahead */
385 int yynerrs; /* number of parse errors so far */
386 #endif /* not YYPURE */
389 int yydebug; /* nonzero means print parse trace */
390 /* Since this is uninitialized, it does not stop multiple parsers
394 /* YYINITDEPTH indicates the initial size of the parser's stacks */
397 #define YYINITDEPTH 200
400 /* YYMAXDEPTH is the maximum size the stacks can grow to
401 (effective only if the built-in stack extension method is used). */
408 #define YYMAXDEPTH 10000
411 /* Prevent warning if -Wstrict-prototypes. */
416 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
417 #define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
418 #else /* not GNU C or C++ */
421 /* This is the most reliable way to avoid incompatibilities
422 in available built-in functions on various systems. */
424 __yy_bcopy (from, to, count)
429 register char *f = from;
430 register char *t = to;
431 register int i = count;
437 #else /* __cplusplus */
439 /* This is the most reliable way to avoid incompatibilities
440 in available built-in functions on various systems. */
442 __yy_bcopy (char *from, char *to, int count)
444 register char *f = from;
445 register char *t = to;
446 register int i = count;
455 #line 184 "/usr/lib/bison.simple"
459 register int yystate;
461 register short *yyssp;
462 register YYSTYPE *yyvsp;
463 int yyerrstatus; /* number of tokens to shift before error messages enabled */
464 int yychar1 = 0; /* lookahead token as an internal (translated) token number */
466 short yyssa[YYINITDEPTH]; /* the state stack */
467 YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
469 short *yyss = yyssa; /* refer to the stacks thru separate pointers */
470 YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
473 YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
474 YYLTYPE *yyls = yylsa;
477 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
479 #define YYPOPSTACK (yyvsp--, yyssp--)
482 int yystacksize = YYINITDEPTH;
493 YYSTYPE yyval; /* the variable used to return */
494 /* semantic values from the action */
501 fprintf(stderr, "Starting parse\n");
507 yychar = YYEMPTY; /* Cause a token to be read. */
509 /* Initialize stack pointers.
510 Waste one element of value and location stack
511 so that they stay on the same level as the state stack.
512 The wasted elements are never initialized. */
520 /* Push a new state, which is found in yystate . */
521 /* In all cases, when you get here, the value and location stacks
522 have just been pushed. so pushing a state here evens the stacks. */
527 if (yyssp >= yyss + yystacksize - 1)
529 /* Give user a chance to reallocate the stack */
530 /* Use copies of these so that the &'s don't force the real ones into memory. */
531 YYSTYPE *yyvs1 = yyvs;
534 YYLTYPE *yyls1 = yyls;
537 /* Get the current used size of the three stacks, in elements. */
538 int size = yyssp - yyss + 1;
541 /* Each stack pointer address is followed by the size of
542 the data in use in that stack, in bytes. */
544 /* This used to be a conditional around just the two extra args,
545 but that might be undefined if yyoverflow is a macro. */
546 yyoverflow("parser stack overflow",
547 &yyss1, size * sizeof (*yyssp),
548 &yyvs1, size * sizeof (*yyvsp),
549 &yyls1, size * sizeof (*yylsp),
552 yyoverflow("parser stack overflow",
553 &yyss1, size * sizeof (*yyssp),
554 &yyvs1, size * sizeof (*yyvsp),
558 yyss = yyss1; yyvs = yyvs1;
562 #else /* no yyoverflow */
563 /* Extend the stack our own way. */
564 if (yystacksize >= YYMAXDEPTH)
566 yyerror("parser stack overflow");
570 if (yystacksize > YYMAXDEPTH)
571 yystacksize = YYMAXDEPTH;
572 yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
573 __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
574 yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
575 __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
577 yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
578 __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
580 #endif /* no yyoverflow */
582 yyssp = yyss + size - 1;
583 yyvsp = yyvs + size - 1;
585 yylsp = yyls + size - 1;
590 fprintf(stderr, "Stack size increased to %d\n", yystacksize);
593 if (yyssp >= yyss + yystacksize - 1)
599 fprintf(stderr, "Entering state %d\n", yystate);
605 /* Do appropriate processing given the current state. */
606 /* Read a lookahead token if we need one and don't already have one. */
609 /* First try to decide what to do without reference to lookahead token. */
611 yyn = yypact[yystate];
615 /* Not known => get a lookahead token if don't already have one. */
617 /* yychar is either YYEMPTY or YYEOF
618 or a valid token in external form. */
620 if (yychar == YYEMPTY)
624 fprintf(stderr, "Reading a token: ");
629 /* Convert token to internal form (in yychar1) for indexing tables with */
631 if (yychar <= 0) /* This means end of input. */
634 yychar = YYEOF; /* Don't call YYLEX any more */
638 fprintf(stderr, "Now at end of input.\n");
643 yychar1 = YYTRANSLATE(yychar);
648 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
649 /* Give the individual parser a way to print the precise meaning
650 of a token, for further debugging info. */
652 YYPRINT (stderr, yychar, yylval);
654 fprintf (stderr, ")\n");
660 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
665 /* yyn is what to do for this token type in this state.
666 Negative => reduce, -yyn is rule number.
667 Positive => shift, yyn is new state.
668 New state is final state => don't bother to shift,
670 0, or most negative number => error. */
685 /* Shift the lookahead token. */
689 fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
692 /* Discard the token being shifted unless it is eof. */
701 /* count tokens shifted since error; after three, turn off error status. */
702 if (yyerrstatus) yyerrstatus--;
707 /* Do the default action for the current state. */
710 yyn = yydefact[yystate];
714 /* Do a reduction. yyn is the number of a rule to reduce with. */
718 yyval = yyvsp[1-yylen]; /* implement default value of the action */
725 fprintf (stderr, "Reducing via rule %d (line %d), ",
728 /* Print the symbols being reduced, and their result. */
729 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
730 fprintf (stderr, "%s ", yytname[yyrhs[i]]);
731 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
739 #line 118 "parsedate.y"
743 /* I am compulsive about lint natterings... */
744 if (yyHaveTime == -1) {
751 #line 127 "parsedate.y"
754 yyTimezone = yyvsp[0].Number;
758 #line 131 "parsedate.y"
764 #line 134 "parsedate.y"
770 #line 139 "parsedate.y"
772 if (yyvsp[-1].Number < 100) {
773 yyHour = yyvsp[-1].Number;
777 yyHour = yyvsp[-1].Number / 100;
778 yyMinutes = yyvsp[-1].Number % 100;
781 yyMeridian = yyvsp[0].Meridian;
785 #line 151 "parsedate.y"
787 yyHour = yyvsp[-3].Number;
788 yyMinutes = yyvsp[-1].Number;
790 yyMeridian = yyvsp[0].Meridian;
794 #line 157 "parsedate.y"
796 yyHour = yyvsp[-3].Number;
797 yyMinutes = yyvsp[-1].Number;
798 yyTimezone = yyvsp[0].Number;
804 #line 164 "parsedate.y"
806 yyHour = yyvsp[-5].Number;
807 yyMinutes = yyvsp[-3].Number;
808 yySeconds = yyvsp[-1].Number;
809 yyMeridian = yyvsp[0].Meridian;
813 #line 170 "parsedate.y"
815 yyHour = yyvsp[-5].Number;
816 yyMinutes = yyvsp[-3].Number;
817 yySeconds = yyvsp[-1].Number;
818 yyTimezone = yyvsp[0].Number;
824 #line 180 "parsedate.y"
826 yyval.Number = yyvsp[0].Number;
831 #line 184 "parsedate.y"
833 yyval.Number = yyvsp[0].Number;
838 #line 188 "parsedate.y"
840 /* Only allow "GMT+300" and "GMT-0800" */
841 if (yyvsp[-1].Number != 0) {
844 yyval.Number = yyvsp[0].Number;
849 #line 196 "parsedate.y"
851 yyval.Number = yyvsp[0].Number;
856 #line 202 "parsedate.y"
860 /* Unix and GMT and numeric timezones -- a little confusing. */
861 if (yyvsp[0].Number < 0) {
862 /* Don't work with negative modulus. */
863 yyvsp[0].Number = -yyvsp[0].Number;
864 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
867 yyval.Number = (yyvsp[0].Number / 100) * 60 + i;
870 if (yyvsp[0].Number > 9999 || (i = yyvsp[0].Number % 100) >= 60) {
873 yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
878 #line 223 "parsedate.y"
880 yyMonth = yyvsp[-2].Number;
881 yyDay = yyvsp[0].Number;
885 #line 227 "parsedate.y"
887 if (yyvsp[-4].Number > 100) {
888 yyYear = yyvsp[-4].Number;
889 yyMonth = yyvsp[-2].Number;
890 yyDay = yyvsp[0].Number;
893 yyMonth = yyvsp[-4].Number;
894 yyDay = yyvsp[-2].Number;
895 yyYear = yyvsp[0].Number;
900 #line 239 "parsedate.y"
902 yyMonth = yyvsp[-1].Number;
903 yyDay = yyvsp[0].Number;
907 #line 243 "parsedate.y"
909 yyMonth = yyvsp[-3].Number;
910 yyDay = yyvsp[-2].Number;
911 yyYear = yyvsp[0].Number;
915 #line 248 "parsedate.y"
917 yyDay = yyvsp[-1].Number;
918 yyMonth = yyvsp[0].Number;
922 #line 252 "parsedate.y"
924 yyDay = yyvsp[-2].Number;
925 yyMonth = yyvsp[-1].Number;
926 yyYear = yyvsp[0].Number;
930 #line 257 "parsedate.y"
932 yyDay = yyvsp[-2].Number;
933 yyMonth = yyvsp[-1].Number;
934 yyYear = yyvsp[0].Number;
938 #line 264 "parsedate.y"
940 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
944 #line 267 "parsedate.y"
946 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
950 #line 270 "parsedate.y"
952 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
956 #line 273 "parsedate.y"
958 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
962 #line 278 "parsedate.y"
964 yyval.Meridian = MER24;
968 #line 281 "parsedate.y"
970 yyval.Meridian = yyvsp[0].Meridian;
974 /* the action file gets copied in in place of this dollarsign */
975 #line 465 "/usr/lib/bison.simple"
986 short *ssp1 = yyss - 1;
987 fprintf (stderr, "state stack now");
988 while (ssp1 != yyssp)
989 fprintf (stderr, " %d", *++ssp1);
990 fprintf (stderr, "\n");
1000 yylsp->first_line = yylloc.first_line;
1001 yylsp->first_column = yylloc.first_column;
1002 yylsp->last_line = (yylsp-1)->last_line;
1003 yylsp->last_column = (yylsp-1)->last_column;
1008 yylsp->last_line = (yylsp+yylen-1)->last_line;
1009 yylsp->last_column = (yylsp+yylen-1)->last_column;
1013 /* Now "shift" the result of the reduction.
1014 Determine what state that goes to,
1015 based on the state we popped back to
1016 and the rule number reduced by. */
1020 yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1021 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1022 yystate = yytable[yystate];
1024 yystate = yydefgoto[yyn - YYNTBASE];
1028 yyerrlab: /* here on detecting error */
1031 /* If not already recovering from an error, report this error. */
1035 #ifdef YYERROR_VERBOSE
1036 yyn = yypact[yystate];
1038 if (yyn > YYFLAG && yyn < YYLAST)
1045 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1046 for (x = (yyn < 0 ? -yyn : 0);
1047 x < (sizeof(yytname) / sizeof(char *)); x++)
1048 if (yycheck[x + yyn] == x)
1049 size += strlen(yytname[x]) + 15, count++;
1050 msg = (char *) malloc(size + 15);
1053 strcpy(msg, "parse error");
1058 for (x = (yyn < 0 ? -yyn : 0);
1059 x < (sizeof(yytname) / sizeof(char *)); x++)
1060 if (yycheck[x + yyn] == x)
1062 strcat(msg, count == 0 ? ", expecting `" : " or `");
1063 strcat(msg, yytname[x]);
1072 yyerror ("parse error; also virtual memory exceeded");
1075 #endif /* YYERROR_VERBOSE */
1076 yyerror("parse error");
1080 yyerrlab1: /* here on error raised explicitly by an action */
1082 if (yyerrstatus == 3)
1084 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1086 /* return failure if at end of input */
1087 if (yychar == YYEOF)
1092 fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1098 /* Else will try to reuse lookahead token
1099 after shifting the error token. */
1101 yyerrstatus = 3; /* Each real token shifted decrements this */
1105 yyerrdefault: /* current state does not do anything special for the error token. */
1108 /* This is wrong; only states that explicitly want error tokens
1109 should shift them. */
1110 yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1111 if (yyn) goto yydefault;
1114 yyerrpop: /* pop the current state because it cannot handle the error token */
1116 if (yyssp == yyss) YYABORT;
1126 short *ssp1 = yyss - 1;
1127 fprintf (stderr, "Error: state stack now");
1128 while (ssp1 != yyssp)
1129 fprintf (stderr, " %d", *++ssp1);
1130 fprintf (stderr, "\n");
1136 yyn = yypact[yystate];
1141 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1160 fprintf(stderr, "Shifting error token, ");
1171 #line 286 "parsedate.y"
1174 /* Month and day table. */
1175 static TABLE MonthDayTable[] = {
1176 { "january", tMONTH, 1 },
1177 { "february", tMONTH, 2 },
1178 { "march", tMONTH, 3 },
1179 { "april", tMONTH, 4 },
1180 { "may", tMONTH, 5 },
1181 { "june", tMONTH, 6 },
1182 { "july", tMONTH, 7 },
1183 { "august", tMONTH, 8 },
1184 { "september", tMONTH, 9 },
1185 { "october", tMONTH, 10 },
1186 { "november", tMONTH, 11 },
1187 { "december", tMONTH, 12 },
1188 /* The value of the day isn't used... */
1189 { "sunday", tDAY, 0 },
1190 { "monday", tDAY, 0 },
1191 { "tuesday", tDAY, 0 },
1192 { "wednesday", tDAY, 0 },
1193 { "thursday", tDAY, 0 },
1194 { "friday", tDAY, 0 },
1195 { "saturday", tDAY, 0 },
1198 /* Time units table. */
1199 static TABLE UnitsTable[] = {
1200 { "year", tMONTH_UNIT, 12 },
1201 { "month", tMONTH_UNIT, 1 },
1202 { "week", tSEC_UNIT, 7L * 24 * 60 * 60 },
1203 { "day", tSEC_UNIT, 1L * 24 * 60 * 60 },
1204 { "hour", tSEC_UNIT, 60 * 60 },
1205 { "minute", tSEC_UNIT, 60 },
1206 { "min", tSEC_UNIT, 60 },
1207 { "second", tSEC_UNIT, 1 },
1208 { "sec", tSEC_UNIT, 1 },
1211 /* Timezone table. */
1212 static TABLE TimezoneTable[] = {
1213 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
1214 { "ut", tZONE, HOUR( 0) }, /* Universal */
1215 { "utc", tZONE, HOUR( 0) }, /* Universal Coordinated */
1216 { "cut", tZONE, HOUR( 0) }, /* Coordinated Universal */
1217 { "z", tZONE, HOUR( 0) }, /* Greenwich Mean */
1218 { "wet", tZONE, HOUR( 0) }, /* Western European */
1219 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
1220 { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
1221 { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
1222 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
1223 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
1224 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
1225 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
1226 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
1227 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
1228 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
1229 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
1230 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
1231 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
1232 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
1233 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
1234 { "akst", tZONE, HOUR( 9) }, /* Alaska Standard */
1235 { "akdt", tDAYZONE, HOUR( 9) }, /* Alaska Daylight */
1236 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
1237 { "hast", tZONE, HOUR(10) }, /* Hawaii-Aleutian Standard */
1238 { "hadt", tDAYZONE, HOUR(10) }, /* Hawaii-Aleutian Daylight */
1239 { "ces", tDAYZONE, -HOUR(1) }, /* Central European Summer */
1240 { "cest", tDAYZONE, -HOUR(1) }, /* Central European Summer */
1241 { "mez", tZONE, -HOUR(1) }, /* Middle European */
1242 { "mezt", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
1243 { "cet", tZONE, -HOUR(1) }, /* Central European */
1244 { "met", tZONE, -HOUR(1) }, /* Middle European */
1245 { "eet", tZONE, -HOUR(2) }, /* Eastern Europe */
1246 { "msk", tZONE, -HOUR(3) }, /* Moscow Winter */
1247 { "msd", tDAYZONE, -HOUR(3) }, /* Moscow Summer */
1248 { "wast", tZONE, -HOUR(8) }, /* West Australian Standard */
1249 { "wadt", tDAYZONE, -HOUR(8) }, /* West Australian Daylight */
1250 { "hkt", tZONE, -HOUR(8) }, /* Hong Kong */
1251 { "cct", tZONE, -HOUR(8) }, /* China Coast */
1252 { "jst", tZONE, -HOUR(9) }, /* Japan Standard */
1253 { "kst", tZONE, -HOUR(9) }, /* Korean Standard */
1254 { "kdt", tZONE, -HOUR(9) }, /* Korean Daylight */
1255 { "cast", tZONE, -(HOUR(9)+30) }, /* Central Australian Standard */
1256 { "cadt", tDAYZONE, -(HOUR(9)+30) }, /* Central Australian Daylight */
1257 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
1258 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
1259 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
1260 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
1262 /* For completeness we include the following entries. */
1265 /* Duplicate names. Either they conflict with a zone listed above
1266 * (which is either more likely to be seen or just been in circulation
1267 * longer), or they conflict with another zone in this section and
1268 * we could not reasonably choose one over the other. */
1269 { "fst", tZONE, HOUR( 2) }, /* Fernando De Noronha Standard */
1270 { "fdt", tDAYZONE, HOUR( 2) }, /* Fernando De Noronha Daylight */
1271 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
1272 { "est", tZONE, HOUR( 3) }, /* Eastern Standard (Brazil) */
1273 { "edt", tDAYZONE, HOUR( 3) }, /* Eastern Daylight (Brazil) */
1274 { "wst", tZONE, HOUR( 4) }, /* Western Standard (Brazil) */
1275 { "wdt", tDAYZONE, HOUR( 4) }, /* Western Daylight (Brazil) */
1276 { "cst", tZONE, HOUR( 5) }, /* Chile Standard */
1277 { "cdt", tDAYZONE, HOUR( 5) }, /* Chile Daylight */
1278 { "ast", tZONE, HOUR( 5) }, /* Acre Standard */
1279 { "adt", tDAYZONE, HOUR( 5) }, /* Acre Daylight */
1280 { "cst", tZONE, HOUR( 5) }, /* Cuba Standard */
1281 { "cdt", tDAYZONE, HOUR( 5) }, /* Cuba Daylight */
1282 { "est", tZONE, HOUR( 6) }, /* Easter Island Standard */
1283 { "edt", tDAYZONE, HOUR( 6) }, /* Easter Island Daylight */
1284 { "sst", tZONE, HOUR(11) }, /* Samoa Standard */
1285 { "ist", tZONE, -HOUR(2) }, /* Israel Standard */
1286 { "idt", tDAYZONE, -HOUR(2) }, /* Israel Daylight */
1287 { "idt", tDAYZONE, -(HOUR(3)+30) }, /* Iran Daylight */
1288 { "ist", tZONE, -(HOUR(3)+30) }, /* Iran Standard */
1289 { "cst", tZONE, -HOUR(8) }, /* China Standard */
1290 { "cdt", tDAYZONE, -HOUR(8) }, /* China Daylight */
1291 { "sst", tZONE, -HOUR(8) }, /* Singapore Standard */
1293 /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
1294 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
1295 { "wat", tZONE, -HOUR(1) }, /* West Africa */
1296 { "at", tZONE, HOUR( 2) }, /* Azores */
1297 { "gst", tZONE, -HOUR(10) }, /* Guam Standard */
1298 { "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
1299 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
1300 { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
1301 { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
1302 { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
1303 { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
1304 { "fwt", tZONE, -HOUR(1) }, /* French Winter */
1305 { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
1306 { "bt", tZONE, -HOUR(3) }, /* Baghdad */
1307 { "it", tZONE, -(HOUR(3)+30) }, /* Iran */
1308 { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
1309 { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
1310 { "ist", tZONE, -(HOUR(5)+30) }, /* Indian Standard */
1311 { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
1312 { "nst", tZONE, -HOUR(7) }, /* North Sumatra */
1313 { "sst", tZONE, -HOUR(7) }, /* South Sumatra */
1314 { "jt", tZONE, -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
1315 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
1316 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
1317 { "cat", tZONE, HOUR(10) }, /* -- expired 1967 */
1318 { "nt", tZONE, HOUR(11) }, /* -- expired 1967 */
1319 { "ahst", tZONE, HOUR(10) }, /* -- expired 1983 */
1320 { "hdt", tDAYZONE, HOUR(10) }, /* -- expired 1986 */
1335 ToSeconds(Hours, Minutes, Seconds, Meridian)
1341 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
1343 if (Meridian == MER24) {
1344 if (Hours < 0 || Hours > 23)
1348 if (Hours < 1 || Hours > 12)
1352 if (Meridian == MERpm)
1355 return (Hours * 60L + Minutes) * 60L + Seconds;
1360 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
1370 static int DaysNormal[13] = {
1371 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1373 static int DaysLeap[13] = {
1374 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1376 static int LeapYears[] = {
1377 1972, 1976, 1980, 1984, 1988, 1992, 1996,
1378 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
1382 register time_t Julian;
1392 for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
1397 if (Year < EPOCH || Year > END_OF_TIME
1398 || Month < 1 || Month > 12
1399 /* NOSTRICT *//* conversion from long may lose accuracy */
1400 || Day < 1 || Day > mp[(int)Month])
1403 Julian = Day - 1 + (Year - EPOCH) * 365;
1404 for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
1407 for (i = 1; i < Month; i++)
1409 Julian *= SECSPERDAY;
1410 Julian += yyTimezone * 60L;
1411 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
1415 if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
1416 Julian -= DST_OFFSET * 60L * 60L;
1422 DSTcorrect(Start, Future)
1429 StartDay = (localtime(&Start)->tm_hour + 1) % 24;
1430 FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
1431 return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
1436 RelativeMonth(Start, RelMonth)
1444 tm = localtime(&Start);
1445 Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
1447 Month = Month % 12 + 1;
1448 return DSTcorrect(Start,
1449 Convert(Month, (time_t)tm->tm_mday, Year,
1450 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
1456 LookupWord(buff, length)
1458 register int length;
1468 /* See if we have an abbreviation for a month. */
1469 if (length == 3 || (length == 4 && p[3] == '.'))
1470 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
1472 if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
1473 yylval.Number = tp->value;
1478 for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
1479 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1480 yylval.Number = tp->value;
1484 /* Try for a timezone. */
1485 for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1486 if (c == tp->name[0] && p[1] == tp->name[1]
1487 && strcmp(p, tp->name) == 0) {
1488 yylval.Number = tp->value;
1492 /* Try the units table. */
1493 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1494 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1495 yylval.Number = tp->value;
1499 /* Strip off any plural and try the units table again. */
1500 if (--length > 0 && p[length] == 's') {
1502 for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
1503 if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
1505 yylval.Number = tp->value;
1512 /* Drop out any periods. */
1513 for (p = buff, q = (char*)buff; *q; q++)
1518 /* Try the meridians. */
1519 if (buff[1] == 'm' && buff[2] == '\0') {
1520 if (buff[0] == 'a') {
1521 yylval.Meridian = MERam;
1524 if (buff[0] == 'p') {
1525 yylval.Meridian = MERpm;
1530 /* If we saw any periods, try the timezones again. */
1531 if (p - buff != length) {
1533 for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
1534 if (c == tp->name[0] && p[1] == tp->name[1]
1535 && strcmp(p, tp->name) == 0) {
1536 yylval.Number = tp->value;
1541 /* Unknown word -- assume GMT timezone. */
1555 register int nesting;
1558 /* Get first character after the whitespace. */
1560 while (isspace(*yyInput))
1564 /* Ignore RFC 822 comments, typically time zone names. */
1567 for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
1570 else if (!IS7BIT(c) || c == '\0' || c == '\r'
1571 || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
1572 /* Lexical error: bad comment. */
1578 if (isdigit(c) || c == '-' || c == '+') {
1579 if (c == '-' || c == '+') {
1580 sign = c == '-' ? -1 : 1;
1582 if (!isdigit(*yyInput))
1583 /* Skip the plus or minus sign. */
1588 for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
1589 i = 10 * i + c - '0';
1591 yylval.Number = sign < 0 ? -i : i;
1592 return sign ? tSNUMBER : tUNUMBER;
1597 for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
1598 if (p < &buff[sizeof buff - 1])
1599 *p++ = isupper(c) ? tolower(c) : c;
1602 return LookupWord(buff, p - buff);
1614 extern int date_parse();
1623 yyDSTmode = DSTmaybe;
1634 if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
1637 if (yyHaveDate || yyHaveTime) {
1638 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1639 yyMeridian, yyDSTmode);
1646 Start += yyRelSeconds;
1648 Start += RelativeMonth(Start, yyRelMonth);
1650 /* Have to do *something* with a legitimate -1 so it's distinguishable
1651 * from the error return value. (Alternately could set errno on error.) */
1652 return Start == -1 ? 0 : Start;
1660 #endif /* YYDEBUG */
1673 #endif /* YYDEBUG */
1675 (void)printf("Enter date, or blank line to exit.\n\t> ");
1677 (void)printf("\t> ");
1678 (void)fflush(stdout);
1679 if (gets(buff) == NULL || buff[0] == '\n')
1682 if (strcmp(buff, "yydebug") == 0) {
1684 printf("yydebug = %s\n", yydebug ? "on" : "off");
1687 #endif /* YYDEBUG */
1688 d = parsedate(buff);
1690 (void)printf("Bad format - couldn't convert.\n");
1692 (void)printf("%s", ctime(&d));