* New parsedate
authorArt Cancro <ajc@citadel.org>
Tue, 14 Dec 1999 20:20:47 +0000 (20:20 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 14 Dec 1999 20:20:47 +0000 (20:20 +0000)
citadel/parsedate.c

index 4682759888f2c954fcdc3a1bb622c8fb4aebe50e..f813214de39051f768c0a594dcf4188e8122b195 100644 (file)
@@ -1,21 +1,14 @@
-
-/*  A Bison parser, made from parsedate.y with Bison version GNU Bison version 1.22
-  */
-
-#define YYBISON 1  /* Identify Bison output.  */
-
-#define        tDAY    258
-#define        tDAYZONE        259
-#define        tMERIDIAN       260
-#define        tMONTH  261
-#define        tMONTH_UNIT     262
-#define        tSEC_UNIT       263
-#define        tSNUMBER        264
-#define        tUNUMBER        265
-#define        tZONE   266
-
-#line 1 "parsedate.y"
-
+#ifndef lint
+static char yysccsid[] = "@(#)yaccpar  1.9 (Berkeley) 02/21/93";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+#line 2 "parsedate.y"
 /* $Revision$
 **
 **  Originally written by Steven M. Bellovin <smb@research.att.com> while
@@ -112,629 +105,863 @@ static time_t   yyRelSeconds;
 extern struct tm       *localtime();
 
 static void            date_error();
-
 #line 100 "parsedate.y"
 typedef union {
     time_t             Number;
     enum _MERIDIAN     Meridian;
 } YYSTYPE;
-
-#ifndef YYLTYPE
-typedef
-  struct yyltype
-    {
-      int timestamp;
-      int first_line;
-      int first_column;
-      int last_line;
-      int last_column;
-      char *text;
-   }
-  yyltype;
-
-#define YYLTYPE yyltype
-#endif
-
-#include <stdio.h>
-
-#ifndef __cplusplus
-#ifndef __STDC__
-#define const
-#endif
-#endif
-
-
-
-#define        YYFINAL         44
-#define        YYFLAG          -32768
-#define        YYNTBASE        15
-
-#define YYTRANSLATE(x) ((unsigned)(x) <= 266 ? yytranslate[x] : 23)
-
-static const char yytranslate[] = {     0,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,    14,     2,     2,    13,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,    12,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     1,     2,     3,     4,     5,
-     6,     7,     8,     9,    10,    11
-};
-
-#if YYDEBUG != 0
-static const short yyprhs[] = {     0,
-     0,     1,     4,     6,     9,    11,    13,    16,    21,    26,
-    33,    40,    42,    44,    47,    49,    51,    55,    61,    64,
-    69,    72,    76,    82,    85,    88,    91,    94,    95
-};
-
-static const short yyrhs[] = {    -1,
-    15,    16,     0,    17,     0,    17,    18,     0,    20,     0,
-    21,     0,    10,    22,     0,    10,    12,    10,    22,     0,
-    10,    12,    10,    19,     0,    10,    12,    10,    12,    10,
-    22,     0,    10,    12,    10,    12,    10,    19,     0,    11,
-     0,     4,     0,    11,    19,     0,    19,     0,     9,     0,
-    10,    13,    10,     0,    10,    13,    10,    13,    10,     0,
-     6,    10,     0,     6,    10,    14,    10,     0,    10,     6,
-     0,    10,     6,    10,     0,     3,    14,    10,     6,    10,
-     0,     9,     8,     0,    10,     8,     0,     9,     7,     0,
-    10,     7,     0,     0,     5,     0
-};
-
-#endif
-
-#if YYDEBUG != 0
-static const short yyrline[] = { 0,
-   114,   115,   118,   127,   131,   134,   139,   151,   157,   164,
-   170,   180,   184,   188,   196,   202,   223,   227,   239,   243,
-   248,   252,   257,   264,   267,   270,   273,   278,   281
+#line 114 "y.tab.c"
+#define tDAY 257
+#define tDAYZONE 258
+#define tMERIDIAN 259
+#define tMONTH 260
+#define tMONTH_UNIT 261
+#define tSEC_UNIT 262
+#define tSNUMBER 263
+#define tUNUMBER 264
+#define tZONE 265
+#define YYERRCODE 256
+short yylhs[] = {                                        -1,
+    0,    0,    4,    4,    4,    4,    5,    5,    5,    5,
+    5,    2,    2,    2,    2,    1,    6,    6,    6,    6,
+    6,    6,    6,    7,    7,    7,    7,    3,    3,
 };
-
-static const char * const yytname[] = {   "$","error","$illegal.","tDAY","tDAYZONE",
-"tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
-"':'","'/'","','","spec","item","time","zone","numzone","date","rel","o_merid",
-""
+short yylen[] = {                                         2,
+    0,    2,    1,    2,    1,    1,    2,    4,    4,    6,
+    6,    1,    1,    2,    1,    1,    3,    5,    2,    4,
+    2,    3,    5,    2,    2,    2,    2,    0,    1,
 };
-#endif
-
-static const short yyr1[] = {     0,
-    15,    15,    16,    16,    16,    16,    17,    17,    17,    17,
-    17,    18,    18,    18,    18,    19,    20,    20,    20,    20,
-    20,    20,    20,    21,    21,    21,    21,    22,    22
+short yydefred[] = {                                      1,
+    0,    0,    0,    0,    0,    2,    0,    5,    6,    0,
+    0,   26,   24,   29,    0,   27,   25,    0,    0,    7,
+   13,   16,    0,   15,    4,    0,    0,   22,    0,    0,
+   14,    0,   20,    0,    9,    8,    0,   23,    0,   18,
+   11,   10,
 };
-
-static const short yyr2[] = {     0,
-     0,     2,     1,     2,     1,     1,     2,     4,     4,     6,
-     6,     1,     1,     2,     1,     1,     3,     5,     2,     4,
-     2,     3,     5,     2,     2,     2,     2,     0,     1
+short yydgoto[] = {                                       1,
+   24,   25,   20,    6,    7,    8,    9,
 };
-
-static const short yydefact[] = {     1,
-     0,     0,     0,     0,    28,     2,     3,     5,     6,     0,
-    19,    26,    24,    29,    21,    27,    25,     0,     0,     7,
-    13,    16,    12,     4,    15,     0,     0,    22,    28,    17,
-    14,     0,    20,     0,     9,     8,     0,    23,    28,    18,
-    11,    10,     0,     0
+short yysindex[] = {                                      0,
+ -239,  -36, -248, -255,  -47,    0, -232,    0,    0, -247,
+  -25,    0,    0,    0, -237,    0,    0, -235, -234,    0,
+    0,    0, -231,    0,    0, -226, -229,    0,  -56,  -11,
+    0, -227,    0, -225,    0,    0, -224,    0, -250,    0,
+    0,    0,
 };
-
-static const short yydefgoto[] = {     1,
-     6,     7,    24,    25,     8,     9,    20
+short yyrindex[] = {                                      0,
+    0,    0,    0,    0,    1,    0,   22,    0,    0,    0,
+   12,    0,    0,    0,   28,    0,    0,    0,    0,    0,
+    0,    0,   23,    0,    0,    0,    0,    0,    3,   14,
+    0,    0,    0,    0,    0,    0,    0,    0,    3,    0,
+    0,    0,
 };
-
-static const short yypact[] = {-32768,
-     1,   -11,    11,    20,    12,-32768,     4,-32768,-32768,    13,
-    16,-32768,-32768,-32768,    21,-32768,-32768,    22,    23,-32768,
--32768,-32768,     5,-32768,-32768,    28,    25,-32768,    17,    24,
--32768,    26,-32768,    29,-32768,-32768,    30,-32768,     0,-32768,
--32768,-32768,    38,-32768
+short yygindex[] = {                                      0,
+  -19,    0,  -24,    0,    0,    0,    0,
 };
-
-static const short yypgoto[] = {-32768,
--32768,-32768,-32768,   -23,-32768,-32768,   -27
+#define YYTABLESIZE 291
+short yytable[] = {                                      19,
+   28,   34,   28,   31,   36,   12,   13,   10,   14,   35,
+   18,   19,   22,   17,   42,   11,   26,    2,   27,   41,
+    3,    3,   12,    4,    5,   21,   28,   21,   29,   30,
+   22,   22,   23,   32,   33,   37,   38,    0,   39,   40,
+    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,
+    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,
+    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,
+    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,
+    0,    0,   14,    0,    0,    0,   22,    0,    0,    0,
+    0,   14,   15,   16,   17,    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,    0,    0,   28,   28,   28,
+   28,    0,   28,   28,   28,   28,   28,   28,   19,    0,
+   17,   19,    0,   17,   19,   19,   17,   17,    3,   12,
+    0,    3,   12,    0,   21,    3,   12,   21,    0,    0,
+   21,
 };
-
-
-#define        YYLAST          40
-
-
-static const short yytable[] = {    31,
-    43,    36,    10,     2,    14,    35,     3,    21,    22,     4,
-     5,    42,    22,    22,    23,    41,    14,    15,    16,    17,
-    11,    14,    26,    18,    19,    22,    12,    13,    34,    27,
-    28,    29,    30,    32,    33,    38,    37,    44,    39,    40
+short yycheck[] = {                                      47,
+    0,   58,    0,   23,   29,  261,  262,   44,  259,   29,
+   58,    0,  263,    0,   39,  264,  264,  257,   44,   39,
+  260,    0,    0,  263,  264,  258,  264,    0,  264,  264,
+  263,  263,  265,  260,  264,   47,  264,   -1,  264,  264,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  259,   -1,   -1,   -1,  263,   -1,   -1,   -1,
+   -1,  259,  260,  261,  262,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,  257,  258,  257,
+  258,   -1,  260,  263,  264,  265,  264,  265,  257,   -1,
+  257,  260,   -1,  260,  263,  264,  263,  264,  257,  257,
+   -1,  260,  260,   -1,  257,  264,  264,  260,   -1,   -1,
+  263,
 };
-
-static const short yycheck[] = {    23,
-     0,    29,    14,     3,     5,    29,     6,     4,     9,     9,
-    10,    39,     9,     9,    11,    39,     5,     6,     7,     8,
-    10,     5,    10,    12,    13,     9,     7,     8,    12,    14,
-    10,    10,    10,     6,    10,    10,    13,     0,    10,    10
+#define YYFINAL 1
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 265
+#if YYDEBUG
+char *yyname[] = {
+"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,
+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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tDAY","tDAYZONE",
+"tMERIDIAN","tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE",
 };
-/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
-#line 3 "/usr/lib/bison.simple"
-
-/* Skeleton output parser for bison,
-   Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 1, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-
-#ifndef alloca
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not GNU C.  */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
-#include <alloca.h>
-#else /* not sparc */
-#if defined (MSDOS) && !defined (__TURBOC__)
-#include <malloc.h>
-#else /* not MSDOS, or __TURBOC__ */
-#if defined(_AIX)
-#include <malloc.h>
- #pragma alloca
-#else /* not MSDOS, __TURBOC__, or _AIX */
-#ifdef __hpux
-#ifdef __cplusplus
-extern "C" {
-void *alloca (unsigned int);
+char *yyrule[] = {
+"$accept : spec",
+"spec :",
+"spec : spec item",
+"item : time",
+"item : time zone",
+"item : date",
+"item : rel",
+"time : tUNUMBER o_merid",
+"time : tUNUMBER ':' tUNUMBER o_merid",
+"time : tUNUMBER ':' tUNUMBER numzone",
+"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
+"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone",
+"zone : tZONE",
+"zone : tDAYZONE",
+"zone : tZONE numzone",
+"zone : numzone",
+"numzone : tSNUMBER",
+"date : tUNUMBER '/' tUNUMBER",
+"date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
+"date : tMONTH tUNUMBER",
+"date : tMONTH tUNUMBER ',' tUNUMBER",
+"date : tUNUMBER tMONTH",
+"date : tUNUMBER tMONTH tUNUMBER",
+"date : tDAY ',' tUNUMBER tMONTH tUNUMBER",
+"rel : tSNUMBER tSEC_UNIT",
+"rel : tUNUMBER tSEC_UNIT",
+"rel : tSNUMBER tMONTH_UNIT",
+"rel : tUNUMBER tMONTH_UNIT",
+"o_merid :",
+"o_merid : tMERIDIAN",
 };
-#else /* not __cplusplus */
-void *alloca ();
-#endif /* not __cplusplus */
-#endif /* __hpux */
-#endif /* not _AIX */
-#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc.  */
-#endif /* not GNU C.  */
-#endif /* alloca not defined.  */
-
-/* This is the parser code that is written into each bison parser
-  when the %semantic_parser declaration is not specified in the grammar.
-  It was written by Richard Stallman by simplifying the hairy parser
-  used when %semantic_parser is specified.  */
-
-/* Note: there must be only one dollar sign in this file.
-   It is replaced by the list of actions, each action
-   as one case of the switch.  */
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                -2
-#define YYEOF          0
-#define YYACCEPT       return(0)
-#define YYABORT        return(1)
-#define YYERROR                goto yyerrlab1
-/* Like YYERROR except do call yyerror.
-   This remains here temporarily to ease the
-   transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-#define YYFAIL         goto yyerrlab
-#define YYRECOVERING()  (!!yyerrstatus)
-#define YYBACKUP(token, value) \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    { yychar = (token), yylval = (value);                      \
-      yychar1 = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK;                                              \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    { yyerror ("syntax error: cannot back up"); YYERROR; }     \
-while (0)
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-#ifndef YYPURE
-#define YYLEX          yylex()
 #endif
-
-#ifdef YYPURE
-#ifdef YYLSP_NEEDED
-#define YYLEX          yylex(&yylval, &yylloc)
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
 #else
-#define YYLEX          yylex(&yylval)
-#endif
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
 #endif
-
-/* If nonreentrant, generate the variables here */
-
-#ifndef YYPURE
-
-int    yychar;                 /*  the lookahead symbol                */
-YYSTYPE        yylval;                 /*  the semantic value of the           */
-                               /*  lookahead symbol                    */
-
-#ifdef YYLSP_NEEDED
-YYLTYPE yylloc;                        /*  location data for the lookahead     */
-                               /*  symbol                              */
 #endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+#line 287 "parsedate.y"
 
-int yynerrs;                   /*  number of parse errors so far       */
-#endif  /* not YYPURE */
+/* Month and day table. */
+static TABLE   MonthDayTable[] = {
+    { "january",       tMONTH,  1 },
+    { "february",      tMONTH,  2 },
+    { "march",         tMONTH,  3 },
+    { "april",         tMONTH,  4 },
+    { "may",           tMONTH,  5 },
+    { "june",          tMONTH,  6 },
+    { "july",          tMONTH,  7 },
+    { "august",                tMONTH,  8 },
+    { "september",     tMONTH,  9 },
+    { "october",       tMONTH, 10 },
+    { "november",      tMONTH, 11 },
+    { "december",      tMONTH, 12 },
+       /* The value of the day isn't used... */
+    { "sunday",                tDAY, 0 },
+    { "monday",                tDAY, 0 },
+    { "tuesday",       tDAY, 0 },
+    { "wednesday",     tDAY, 0 },
+    { "thursday",      tDAY, 0 },
+    { "friday",                tDAY, 0 },
+    { "saturday",      tDAY, 0 },
+};
 
-#if YYDEBUG != 0
-int yydebug;                   /*  nonzero means print parse trace     */
-/* Since this is uninitialized, it does not stop multiple parsers
-   from coexisting.  */
-#endif
+/* Time units table. */
+static TABLE   UnitsTable[] = {
+    { "year",          tMONTH_UNIT,    12 },
+    { "month",         tMONTH_UNIT,    1 },
+    { "week",          tSEC_UNIT,      7L * 24 * 60 * 60 },
+    { "day",           tSEC_UNIT,      1L * 24 * 60 * 60 },
+    { "hour",          tSEC_UNIT,      60 * 60 },
+    { "minute",                tSEC_UNIT,      60 },
+    { "min",           tSEC_UNIT,      60 },
+    { "second",                tSEC_UNIT,      1 },
+    { "sec",           tSEC_UNIT,      1 },
+};
 
-/*  YYINITDEPTH indicates the initial size of the parser's stacks      */
+/* Timezone table. */
+static TABLE   TimezoneTable[] = {
+    { "gmt",   tZONE,     HOUR( 0) },  /* Greenwich Mean */
+    { "ut",    tZONE,     HOUR( 0) },  /* Universal */
+    { "utc",   tZONE,     HOUR( 0) },  /* Universal Coordinated */
+    { "cut",   tZONE,     HOUR( 0) },  /* Coordinated Universal */
+    { "z",     tZONE,     HOUR( 0) },  /* Greenwich Mean */
+    { "wet",   tZONE,     HOUR( 0) },  /* Western European */
+    { "bst",   tDAYZONE,  HOUR( 0) },  /* British Summer */
+    { "nst",   tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
+    { "ndt",   tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
+    { "ast",   tZONE,     HOUR( 4) },  /* Atlantic Standard */
+    { "adt",   tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
+    { "est",   tZONE,     HOUR( 5) },  /* Eastern Standard */
+    { "edt",   tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
+    { "cst",   tZONE,     HOUR( 6) },  /* Central Standard */
+    { "cdt",   tDAYZONE,  HOUR( 6) },  /* Central Daylight */
+    { "mst",   tZONE,     HOUR( 7) },  /* Mountain Standard */
+    { "mdt",   tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
+    { "pst",   tZONE,     HOUR( 8) },  /* Pacific Standard */
+    { "pdt",   tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
+    { "yst",   tZONE,     HOUR( 9) },  /* Yukon Standard */
+    { "ydt",   tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
+    { "akst",  tZONE,     HOUR( 9) },  /* Alaska Standard */
+    { "akdt",  tDAYZONE,  HOUR( 9) },  /* Alaska Daylight */
+    { "hst",   tZONE,     HOUR(10) },  /* Hawaii Standard */
+    { "hast",  tZONE,     HOUR(10) },  /* Hawaii-Aleutian Standard */
+    { "hadt",  tDAYZONE,  HOUR(10) },  /* Hawaii-Aleutian Daylight */
+    { "ces",   tDAYZONE,  -HOUR(1) },  /* Central European Summer */
+    { "cest",  tDAYZONE,  -HOUR(1) },  /* Central European Summer */
+    { "mez",   tZONE,     -HOUR(1) },  /* Middle European */
+    { "mezt",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
+    { "cet",   tZONE,     -HOUR(1) },  /* Central European */
+    { "met",   tZONE,     -HOUR(1) },  /* Middle European */
+    { "eet",   tZONE,     -HOUR(2) },  /* Eastern Europe */
+    { "msk",   tZONE,     -HOUR(3) },  /* Moscow Winter */
+    { "msd",   tDAYZONE,  -HOUR(3) },  /* Moscow Summer */
+    { "wast",  tZONE,     -HOUR(8) },  /* West Australian Standard */
+    { "wadt",  tDAYZONE,  -HOUR(8) },  /* West Australian Daylight */
+    { "hkt",   tZONE,     -HOUR(8) },  /* Hong Kong */
+    { "cct",   tZONE,     -HOUR(8) },  /* China Coast */
+    { "jst",   tZONE,     -HOUR(9) },  /* Japan Standard */
+    { "kst",   tZONE,     -HOUR(9) },  /* Korean Standard */
+    { "kdt",   tZONE,     -HOUR(9) },  /* Korean Daylight */
+    { "cast",  tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
+    { "cadt",  tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
+    { "east",  tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
+    { "eadt",  tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
+    { "nzst",  tZONE,     -HOUR(12) }, /* New Zealand Standard */
+    { "nzdt",  tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
 
-#ifndef        YYINITDEPTH
-#define YYINITDEPTH 200
-#endif
+    /* For completeness we include the following entries. */
+#if 0
 
-/*  YYMAXDEPTH is the maximum size the stacks can grow to
-    (effective only if the built-in stack extension method is used).  */
+    /* Duplicate names.  Either they conflict with a zone listed above
+     * (which is either more likely to be seen or just been in circulation
+     * longer), or they conflict with another zone in this section and
+     * we could not reasonably choose one over the other. */
+    { "fst",   tZONE,     HOUR( 2) },  /* Fernando De Noronha Standard */
+    { "fdt",   tDAYZONE,  HOUR( 2) },  /* Fernando De Noronha Daylight */
+    { "bst",   tZONE,     HOUR( 3) },  /* Brazil Standard */
+    { "est",   tZONE,     HOUR( 3) },  /* Eastern Standard (Brazil) */
+    { "edt",   tDAYZONE,  HOUR( 3) },  /* Eastern Daylight (Brazil) */
+    { "wst",   tZONE,     HOUR( 4) },  /* Western Standard (Brazil) */
+    { "wdt",   tDAYZONE,  HOUR( 4) },  /* Western Daylight (Brazil) */
+    { "cst",   tZONE,     HOUR( 5) },  /* Chile Standard */
+    { "cdt",   tDAYZONE,  HOUR( 5) },  /* Chile Daylight */
+    { "ast",   tZONE,     HOUR( 5) },  /* Acre Standard */
+    { "adt",   tDAYZONE,  HOUR( 5) },  /* Acre Daylight */
+    { "cst",   tZONE,     HOUR( 5) },  /* Cuba Standard */
+    { "cdt",   tDAYZONE,  HOUR( 5) },  /* Cuba Daylight */
+    { "est",   tZONE,     HOUR( 6) },  /* Easter Island Standard */
+    { "edt",   tDAYZONE,  HOUR( 6) },  /* Easter Island Daylight */
+    { "sst",   tZONE,     HOUR(11) },  /* Samoa Standard */
+    { "ist",   tZONE,     -HOUR(2) },  /* Israel Standard */
+    { "idt",   tDAYZONE,  -HOUR(2) },  /* Israel Daylight */
+    { "idt",   tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
+    { "ist",   tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
+    { "cst",    tZONE,     -HOUR(8) }, /* China Standard */
+    { "cdt",    tDAYZONE,  -HOUR(8) }, /* China Daylight */
+    { "sst",    tZONE,     -HOUR(8) }, /* Singapore Standard */
 
-#if YYMAXDEPTH == 0
-#undef YYMAXDEPTH
-#endif
+    /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
+    { "gst",   tZONE,     HOUR( 3) },  /* Greenland Standard */
+    { "wat",   tZONE,     -HOUR(1) },  /* West Africa */
+    { "at",    tZONE,     HOUR( 2) },  /* Azores */
+    { "gst",   tZONE,     -HOUR(10) }, /* Guam Standard */
+    { "nft",   tZONE,     HOUR(3)+30 }, /* Newfoundland */
+    { "idlw",  tZONE,     HOUR(12) },  /* International Date Line West */
+    { "mewt",  tZONE,     -HOUR(1) },  /* Middle European Winter */
+    { "mest",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
+    { "swt",   tZONE,     -HOUR(1) },  /* Swedish Winter */
+    { "sst",   tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
+    { "fwt",   tZONE,     -HOUR(1) },  /* French Winter */
+    { "fst",   tDAYZONE,  -HOUR(1) },  /* French Summer */
+    { "bt",    tZONE,     -HOUR(3) },  /* Baghdad */
+    { "it",    tZONE,     -(HOUR(3)+30) }, /* Iran */
+    { "zp4",   tZONE,     -HOUR(4) },  /* USSR Zone 3 */
+    { "zp5",   tZONE,     -HOUR(5) },  /* USSR Zone 4 */
+    { "ist",   tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
+    { "zp6",   tZONE,     -HOUR(6) },  /* USSR Zone 5 */
+    { "nst",   tZONE,     -HOUR(7) },  /* North Sumatra */
+    { "sst",   tZONE,     -HOUR(7) },  /* South Sumatra */
+    { "jt",    tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
+    { "nzt",   tZONE,     -HOUR(12) }, /* New Zealand */
+    { "idle",  tZONE,     -HOUR(12) }, /* International Date Line East */
+    { "cat",   tZONE,     HOUR(10) },  /* -- expired 1967 */
+    { "nt",    tZONE,     HOUR(11) },  /* -- expired 1967 */
+    { "ahst",  tZONE,     HOUR(10) },  /* -- expired 1983 */
+    { "hdt",   tDAYZONE,  HOUR(10) },  /* -- expired 1986 */
+#endif /* 0 */
+};
 
-#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
-#endif
 
-/* Prevent warning if -Wstrict-prototypes.  */
-#ifdef __GNUC__
-int yyparse (void);
-#endif
-\f
-#if __GNUC__ > 1               /* GNU C and GNU C++ define this.  */
-#define __yy_bcopy(FROM,TO,COUNT)      __builtin_memcpy(TO,FROM,COUNT)
-#else                          /* not GNU C or C++ */
-#ifndef __cplusplus
-
-/* This is the most reliable way to avoid incompatibilities
-   in available built-in functions on various systems.  */
+/* ARGSUSED */
 static void
-__yy_bcopy (from, to, count)
-     char *from;
-     char *to;
-     int count;
+date_error(s)
+    char       *s;
 {
-  register char *f = from;
-  register char *t = to;
-  register int i = count;
-
-  while (i-- > 0)
-    *t++ = *f++;
+    /* NOTREACHED */
 }
 
-#else /* __cplusplus */
 
-/* This is the most reliable way to avoid incompatibilities
-   in available built-in functions on various systems.  */
-static void
-__yy_bcopy (char *from, char *to, int count)
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+    time_t     Hours;
+    time_t     Minutes;
+    time_t     Seconds;
+    MERIDIAN   Meridian;
 {
-  register char *f = from;
-  register char *t = to;
-  register int i = count;
-
-  while (i-- > 0)
-    *t++ = *f++;
+    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
+       return -1;
+    if (Meridian == MER24) {
+       if (Hours < 0 || Hours > 23)
+           return -1;
+    }
+    else {
+       if (Hours < 1 || Hours > 12)
+           return -1;
+       if (Hours == 12)
+           Hours = 0;
+       if (Meridian == MERpm)
+           Hours += 12;
+    }
+    return (Hours * 60L + Minutes) * 60L + Seconds;
 }
 
-#endif
-#endif
-\f
-#line 184 "/usr/lib/bison.simple"
-int
-yyparse()
-{
-  register int yystate;
-  register int yyn;
-  register short *yyssp;
-  register YYSTYPE *yyvsp;
-  int yyerrstatus;     /*  number of tokens to shift before error messages enabled */
-  int yychar1 = 0;             /*  lookahead token as an internal (translated) token number */
-
-  short        yyssa[YYINITDEPTH];     /*  the state stack                     */
-  YYSTYPE yyvsa[YYINITDEPTH];  /*  the semantic value stack            */
-
-  short *yyss = yyssa;         /*  refer to the stacks thru separate pointers */
-  YYSTYPE *yyvs = yyvsa;       /*  to allow yyoverflow to reallocate them elsewhere */
-
-#ifdef YYLSP_NEEDED
-  YYLTYPE yylsa[YYINITDEPTH];  /*  the location stack                  */
-  YYLTYPE *yyls = yylsa;
-  YYLTYPE *yylsp;
-
-#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
-#else
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-#endif
-
-  int yystacksize = YYINITDEPTH;
-
-#ifdef YYPURE
-  int yychar;
-  YYSTYPE yylval;
-  int yynerrs;
-#ifdef YYLSP_NEEDED
-  YYLTYPE yylloc;
-#endif
-#endif
-
-  YYSTYPE yyval;               /*  the variable used to return         */
-                               /*  semantic values from the action     */
-                               /*  routines                            */
-
-  int yylen;
-
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Starting parse\n");
-#endif
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss - 1;
-  yyvsp = yyvs;
-#ifdef YYLSP_NEEDED
-  yylsp = yyls;
-#endif
-
-/* Push a new state, which is found in  yystate  .  */
-/* In all cases, when you get here, the value and location stacks
-   have just been pushed. so pushing a state here evens the stacks.  */
-yynewstate:
-
-  *++yyssp = yystate;
 
-  if (yyssp >= yyss + yystacksize - 1)
-    {
-      /* Give user a chance to reallocate the stack */
-      /* Use copies of these so that the &'s don't force the real ones into memory. */
-      YYSTYPE *yyvs1 = yyvs;
-      short *yyss1 = yyss;
-#ifdef YYLSP_NEEDED
-      YYLTYPE *yyls1 = yyls;
-#endif
-
-      /* Get the current used size of the three stacks, in elements.  */
-      int size = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      /* Each stack pointer address is followed by the size of
-        the data in use in that stack, in bytes.  */
-#ifdef YYLSP_NEEDED
-      /* This used to be a conditional around just the two extra args,
-        but that might be undefined if yyoverflow is a macro.  */
-      yyoverflow("parser stack overflow",
-                &yyss1, size * sizeof (*yyssp),
-                &yyvs1, size * sizeof (*yyvsp),
-                &yyls1, size * sizeof (*yylsp),
-                &yystacksize);
-#else
-      yyoverflow("parser stack overflow",
-                &yyss1, size * sizeof (*yyssp),
-                &yyvs1, size * sizeof (*yyvsp),
-                &yystacksize);
-#endif
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
+    time_t     Month;
+    time_t     Day;
+    time_t     Year;
+    time_t     Hours;
+    time_t     Minutes;
+    time_t     Seconds;
+    MERIDIAN   Meridian;
+    DSTMODE    dst;
+{
+    static int DaysNormal[13] = {
+       0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    static int DaysLeap[13] = {
+       0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    static int LeapYears[] = {
+       1972, 1976, 1980, 1984, 1988, 1992, 1996,
+       2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
+    };
+    register int       *yp;
+    register int       *mp;
+    register time_t    Julian;
+    register int       i;
+    time_t             tod;
 
-      yyss = yyss1; yyvs = yyvs1;
-#ifdef YYLSP_NEEDED
-      yyls = yyls1;
-#endif
-#else /* no yyoverflow */
-      /* Extend the stack our own way.  */
-      if (yystacksize >= YYMAXDEPTH)
-       {
-         yyerror("parser stack overflow");
-         return 2;
+    if (Year < 0)
+       Year = -Year;
+    if (Year < 100)
+       Year += 1900;
+    if (Year < EPOCH)
+       Year += 100;
+    for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
+       if (Year == *yp) {
+           mp = DaysLeap;
+           break;
        }
-      yystacksize *= 2;
-      if (yystacksize > YYMAXDEPTH)
-       yystacksize = YYMAXDEPTH;
-      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
-      __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
-      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
-      __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
-#ifdef YYLSP_NEEDED
-      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
-      __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
-#endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + size - 1;
-      yyvsp = yyvs + size - 1;
-#ifdef YYLSP_NEEDED
-      yylsp = yyls + size - 1;
-#endif
-
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Stack size increased to %d\n", yystacksize);
-#endif
+    if (Year < EPOCH || Year > END_OF_TIME
+     || Month < 1 || Month > 12
+     /* NOSTRICT *//* conversion from long may lose accuracy */
+     || Day < 1 || Day > mp[(int)Month])
+       return -1;
 
-      if (yyssp >= yyss + yystacksize - 1)
-       YYABORT;
-    }
+    Julian = Day - 1 + (Year - EPOCH) * 365;
+    for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
+       if (Year <= *yp)
+           break;
+    for (i = 1; i < Month; i++)
+       Julian += *++mp;
+    Julian *= SECSPERDAY;
+    Julian += yyTimezone * 60L;
+    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+       return -1;
+    Julian += tod;
+    tod = Julian;
+    if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
+       Julian -= DST_OFFSET * 60L * 60L;
+    return Julian;
+}
 
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Entering state %d\n", yystate);
-#endif
 
-  goto yybackup;
- yybackup:
+static time_t
+DSTcorrect(Start, Future)
+    time_t     Start;
+    time_t     Future;
+{
+    time_t     StartDay;
+    time_t     FutureDay;
 
-/* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
-/* yyresume: */
+    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+    return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
+}
 
-  /* First try to decide what to do without reference to lookahead token.  */
 
-  yyn = yypact[yystate];
-  if (yyn == YYFLAG)
-    goto yydefault;
+static time_t
+RelativeMonth(Start, RelMonth)
+    time_t     Start;
+    time_t     RelMonth;
+{
+    struct tm  *tm;
+    time_t     Month;
+    time_t     Year;
 
-  /* Not known => get a lookahead token if don't already have one.  */
+    tm = localtime(&Start);
+    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+    Year = Month / 12;
+    Month = Month % 12 + 1;
+    return DSTcorrect(Start,
+           Convert(Month, (time_t)tm->tm_mday, Year,
+               (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+               MER24, DSTmaybe));
+}
 
-  /* yychar is either YYEMPTY or YYEOF
-     or a valid token in external form.  */
 
-  if (yychar == YYEMPTY)
-    {
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Reading a token: ");
-#endif
-      yychar = YYLEX;
-    }
+static int
+LookupWord(buff, length)
+    char               *buff;
+    register int       length;
+{
+    register char      *p;
+    register char      *q;
+    register TABLE     *tp;
+    register int       c;
 
-  /* Convert token to internal form (in yychar1) for indexing tables with */
+    p = buff;
+    c = p[0];
 
-  if (yychar <= 0)             /* This means end of input. */
-    {
-      yychar1 = 0;
-      yychar = YYEOF;          /* Don't call YYLEX any more */
+    /* See if we have an abbreviation for a month. */
+    if (length == 3 || (length == 4 && p[3] == '.'))
+       for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
+           q = tp->name;
+           if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       }
+    else
+       for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
+           if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
 
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Now at end of input.\n");
-#endif
-    }
-  else
-    {
-      yychar1 = YYTRANSLATE(yychar);
-
-#if YYDEBUG != 0
-      if (yydebug)
-       {
-         fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
-         /* Give the individual parser a way to print the precise meaning
-            of a token, for further debugging info.  */
-#ifdef YYPRINT
-         YYPRINT (stderr, yychar, yylval);
-#endif
-         fprintf (stderr, ")\n");
+    /* Try for a timezone. */
+    for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
+       if (c == tp->name[0] && p[1] == tp->name[1]
+        && strcmp(p, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
        }
-#endif
-    }
 
-  yyn += yychar1;
-  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
-    goto yydefault;
+    /* Try the units table. */
+    for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
+       if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
 
-  yyn = yytable[yyn];
+    /* Strip off any plural and try the units table again. */
+    if (--length > 0 && p[length] == 's') {
+       p[length] = '\0';
+       for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
+           if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+               p[length] = 's';
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       p[length] = 's';
+    }
+    length++;
 
-  /* yyn is what to do for this token type in this state.
-     Negative => reduce, -yyn is rule number.
-     Positive => shift, yyn is new state.
-       New state is final state => don't bother to shift,
-       just return success.
-     0, or most negative number => error.  */
+    /* Drop out any periods. */
+    for (p = buff, q = (char*)buff; *q; q++)
+       if (*q != '.')
+           *p++ = *q;
+    *p = '\0';
 
-  if (yyn < 0)
-    {
-      if (yyn == YYFLAG)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
+    /* Try the meridians. */
+    if (buff[1] == 'm' && buff[2] == '\0') {
+       if (buff[0] == 'a') {
+           yylval.Meridian = MERam;
+           return tMERIDIAN;
+       }
+       if (buff[0] == 'p') {
+           yylval.Meridian = MERpm;
+           return tMERIDIAN;
+       }
     }
-  else if (yyn == 0)
-    goto yyerrlab;
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
+    /* If we saw any periods, try the timezones again. */
+    if (p - buff != length) {
+       c = buff[0];
+       for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
+           if (c == tp->name[0] && p[1] == tp->name[1]
+           && strcmp(p, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+    }
 
-  /* Shift the lookahead token.  */
+    /* Unknown word -- assume GMT timezone. */
+    yylval.Number = 0;
+    return tZONE;
+}
 
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
-#endif
 
-  /* Discard the token being shifted unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+int
+date_lex()
+{
+    register char      c;
+    register char      *p;
+    char               buff[20];
+    register int       sign;
+    register int       i;
+    register int       nesting;
 
-  *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
-  *++yylsp = yylloc;
-#endif
+    for ( ; ; ) {
+       /* Get first character after the whitespace. */
+       for ( ; ; ) {
+           while (isspace(*yyInput))
+               yyInput++;
+           c = *yyInput;
 
-  /* count tokens shifted since error; after three, turn off error status.  */
-  if (yyerrstatus) yyerrstatus--;
+           /* Ignore RFC 822 comments, typically time zone names. */
+           if (c != LPAREN)
+               break;
+           for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
+               if (c == LPAREN)
+                   nesting++;
+               else if (!IS7BIT(c) || c == '\0' || c == '\r'
+                    || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
+                   /* Lexical error: bad comment. */
+                   return '?';
+           yyInput++;
+       }
 
-  yystate = yyn;
-  goto yynewstate;
+       /* A number? */
+       if (isdigit(c) || c == '-' || c == '+') {
+           if (c == '-' || c == '+') {
+               sign = c == '-' ? -1 : 1;
+               yyInput++;
+               if (!isdigit(*yyInput))
+                   /* Skip the plus or minus sign. */
+                   continue;
+           }
+           else
+               sign = 0;
+           for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
+               i = 10 * i + c - '0';
+           yyInput--;
+           yylval.Number = sign < 0 ? -i : i;
+           return sign ? tSNUMBER : tUNUMBER;
+       }
 
-/* Do the default action for the current state.  */
-yydefault:
+       /* A word? */
+       if (isalpha(c)) {
+           for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
+               if (p < &buff[sizeof buff - 1])
+                   *p++ = isupper(c) ? tolower(c) : c;
+           *p = '\0';
+           yyInput--;
+           return LookupWord(buff, p - buff);
+       }
 
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
+       return *yyInput++;
+    }
+}
 
-/* Do a reduction.  yyn is the number of a rule to reduce with.  */
-yyreduce:
-  yylen = yyr2[yyn];
-  if (yylen > 0)
-    yyval = yyvsp[1-yylen]; /* implement default value of the action */
 
-#if YYDEBUG != 0
-  if (yydebug)
-    {
-      int i;
+time_t
+parsedate(p)
+    char               *p;
+{
+    extern int         date_parse();
+    time_t             Start;
 
-      fprintf (stderr, "Reducing via rule %d (line %d), ",
-              yyn, yyrline[yyn]);
+    yyInput = p;
 
-      /* Print the symbols being reduced, and their result.  */
-      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
-       fprintf (stderr, "%s ", yytname[yyrhs[i]]);
-      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
-    }
+    yyYear = 0;
+    yyMonth = 0;
+    yyDay = 0;
+    yyTimezone = 0;
+    yyDSTmode = DSTmaybe;
+    yyHour = 0;
+    yyMinutes = 0;
+    yySeconds = 0;
+    yyMeridian = MER24;
+    yyRelSeconds = 0;
+    yyRelMonth = 0;
+    yyHaveDate = 0;
+    yyHaveRel = 0;
+    yyHaveTime = 0;
+
+    if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
+       return -1;
+
+    if (yyHaveDate || yyHaveTime) {
+       Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+                   yyMeridian, yyDSTmode);
+       if (Start < 0)
+           return -1;
+    }
+    else
+       return -1;
+
+    Start += yyRelSeconds;
+    if (yyRelMonth)
+       Start += RelativeMonth(Start, yyRelMonth);
+
+    /* Have to do *something* with a legitimate -1 so it's distinguishable
+     * from the error return value.  (Alternately could set errno on error.) */
+    return Start == -1 ? 0 : Start;
+}
+
+
+#ifdef TEST
+
+#if YYDEBUG
+extern int     yydebug;
+#endif /* YYDEBUG */
+
+/* ARGSUSED */
+int
+main(ac, av)
+    int                ac;
+    char       *av[];
+{
+    char       buff[128];
+    time_t     d;
+
+#if YYDEBUG
+    yydebug = 1;
+#endif /* YYDEBUG */
+
+    (void)printf("Enter date, or blank line to exit.\n\t> ");
+    for ( ; ; ) {
+       (void)printf("\t> ");
+       (void)fflush(stdout);
+       if (gets(buff) == NULL || buff[0] == '\n')
+           break;
+#if YYDEBUG
+       if (strcmp(buff, "yydebug") == 0) {
+           yydebug = !yydebug;
+           printf("yydebug = %s\n", yydebug ? "on" : "off");
+           continue;
+       }
+#endif /* YYDEBUG */
+       d = parsedate(buff, (TIMEINFO *)NULL);
+       if (d == -1)
+           (void)printf("Bad format - couldn't convert.\n");
+       else
+           (void)printf("%s", ctime(&d));
+    }
+
+    exit(0);
+    /* NOTREACHED */
+}
+#endif /* TEST */
+#line 825 "y.tab.c"
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+yyparse()
+{
+    register int yym, yyn, yystate;
+#if YYDEBUG
+    register char *yys;
+    extern char *getenv();
+
+    if (yys = getenv("YYDEBUG"))
+    {
+        yyn = *yys;
+        if (yyn >= '0' && yyn <= '9')
+            yydebug = yyn - '0';
+    }
 #endif
 
+    yynerrs = 0;
+    yyerrflag = 0;
+    yychar = (-1);
 
-  switch (yyn) {
+    yyssp = yyss;
+    yyvsp = yyvs;
+    *yyssp = yystate = 0;
 
+yyloop:
+    if (yyn = yydefred[yystate]) goto yyreduce;
+    if (yychar < 0)
+    {
+        if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, reading %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+    }
+    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: state %d, shifting to state %d\n",
+                    YYPREFIX, yystate, yytable[yyn]);
+#endif
+        if (yyssp >= yyss + yystacksize - 1)
+        {
+            goto yyoverflow;
+        }
+        *++yyssp = yystate = yytable[yyn];
+        *++yyvsp = yylval;
+        yychar = (-1);
+        if (yyerrflag > 0)  --yyerrflag;
+        goto yyloop;
+    }
+    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+        yyn = yytable[yyn];
+        goto yyreduce;
+    }
+    if (yyerrflag) goto yyinrecovery;
+#ifdef lint
+    goto yynewerror;
+#endif
+yynewerror:
+    yyerror("syntax error");
+#ifdef lint
+    goto yyerrlab;
+#endif
+yyerrlab:
+    ++yynerrs;
+yyinrecovery:
+    if (yyerrflag < 3)
+    {
+        yyerrflag = 3;
+        for (;;)
+        {
+            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+                if (yyssp >= yyss + yystacksize - 1)
+                {
+                    goto yyoverflow;
+                }
+                *++yyssp = yystate = yytable[yyn];
+                *++yyvsp = yylval;
+                goto yyloop;
+            }
+            else
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: error recovery discarding state %d\n",
+                            YYPREFIX, *yyssp);
+#endif
+                if (yyssp <= yyss) goto yyabort;
+                --yyssp;
+                --yyvsp;
+            }
+        }
+    }
+    else
+    {
+        if (yychar == 0) goto yyabort;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+        yychar = (-1);
+        goto yyloop;
+    }
+yyreduce:
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+                YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+    yym = yylen[yyn];
+    yyval = yyvsp[1-yym];
+    switch (yyn)
+    {
 case 3:
 #line 118 "parsedate.y"
 {
@@ -745,27 +972,27 @@ case 3:
                YYERROR;
            }
 #endif /* lint */
-       ;
-    break;}
+       }
+break;
 case 4:
 #line 127 "parsedate.y"
 {
            yyHaveTime++;
            yyTimezone = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 5:
 #line 131 "parsedate.y"
 {
            yyHaveDate++;
-       ;
-    break;}
+       }
+break;
 case 6:
 #line 134 "parsedate.y"
 {
            yyHaveRel = 1;
-       ;
-    break;}
+       }
+break;
 case 7:
 #line 139 "parsedate.y"
 {
@@ -779,8 +1006,8 @@ case 7:
            }
            yySeconds = 0;
            yyMeridian = yyvsp[0].Meridian;
-       ;
-    break;}
+       }
+break;
 case 8:
 #line 151 "parsedate.y"
 {
@@ -788,8 +1015,8 @@ case 8:
            yyMinutes = yyvsp[-1].Number;
            yySeconds = 0;
            yyMeridian = yyvsp[0].Meridian;
-       ;
-    break;}
+       }
+break;
 case 9:
 #line 157 "parsedate.y"
 {
@@ -798,8 +1025,8 @@ case 9:
            yyTimezone = yyvsp[0].Number;
            yyMeridian = MER24;
            yyDSTmode = DSToff;
-       ;
-    break;}
+       }
+break;
 case 10:
 #line 164 "parsedate.y"
 {
@@ -807,8 +1034,8 @@ case 10:
            yyMinutes = yyvsp[-3].Number;
            yySeconds = yyvsp[-1].Number;
            yyMeridian = yyvsp[0].Meridian;
-       ;
-    break;}
+       }
+break;
 case 11:
 #line 170 "parsedate.y"
 {
@@ -818,22 +1045,22 @@ case 11:
            yyTimezone = yyvsp[0].Number;
            yyMeridian = MER24;
            yyDSTmode = DSToff;
-       ;
-    break;}
+       }
+break;
 case 12:
 #line 180 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSToff;
-       ;
-    break;}
+       }
+break;
 case 13:
 #line 184 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSTon;
-       ;
-    break;}
+       }
+break;
 case 14:
 #line 188 "parsedate.y"
 {
@@ -843,15 +1070,15 @@ case 14:
            }
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSToff;
-       ;
-    break;}
+       }
+break;
 case 15:
 #line 196 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSToff;
-       ;
-    break;}
+       }
+break;
 case 16:
 #line 202 "parsedate.y"
 {
@@ -872,15 +1099,15 @@ case 16:
                }
                yyval.Number = -((yyvsp[0].Number / 100) * 60 + i);
            }
-       ;
-    break;}
+       }
+break;
 case 17:
 #line 223 "parsedate.y"
 {
            yyMonth = yyvsp[-2].Number;
            yyDay = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 18:
 #line 227 "parsedate.y"
 {
@@ -894,805 +1121,136 @@ case 18:
                yyDay = yyvsp[-2].Number;
                yyYear = yyvsp[0].Number;
            }
-       ;
-    break;}
+       }
+break;
 case 19:
 #line 239 "parsedate.y"
 {
            yyMonth = yyvsp[-1].Number;
            yyDay = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 20:
 #line 243 "parsedate.y"
 {
            yyMonth = yyvsp[-3].Number;
            yyDay = yyvsp[-2].Number;
            yyYear = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 21:
 #line 248 "parsedate.y"
 {
            yyDay = yyvsp[-1].Number;
            yyMonth = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 22:
 #line 252 "parsedate.y"
 {
            yyDay = yyvsp[-2].Number;
            yyMonth = yyvsp[-1].Number;
            yyYear = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 23:
 #line 257 "parsedate.y"
 {
            yyDay = yyvsp[-2].Number;
            yyMonth = yyvsp[-1].Number;
            yyYear = yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 24:
 #line 264 "parsedate.y"
 {
            yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 25:
 #line 267 "parsedate.y"
 {
            yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 26:
 #line 270 "parsedate.y"
 {
            yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 27:
 #line 273 "parsedate.y"
 {
            yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
-       ;
-    break;}
+       }
+break;
 case 28:
 #line 278 "parsedate.y"
 {
            yyval.Meridian = MER24;
-       ;
-    break;}
+       }
+break;
 case 29:
 #line 281 "parsedate.y"
 {
            yyval.Meridian = yyvsp[0].Meridian;
-       ;
-    break;}
-}
-   /* the action file gets copied in in place of this dollarsign */
-#line 465 "/usr/lib/bison.simple"
-\f
-  yyvsp -= yylen;
-  yyssp -= yylen;
-#ifdef YYLSP_NEEDED
-  yylsp -= yylen;
-#endif
-
-#if YYDEBUG != 0
-  if (yydebug)
-    {
-      short *ssp1 = yyss - 1;
-      fprintf (stderr, "state stack now");
-      while (ssp1 != yyssp)
-       fprintf (stderr, " %d", *++ssp1);
-      fprintf (stderr, "\n");
-    }
-#endif
-
-  *++yyvsp = yyval;
-
-#ifdef YYLSP_NEEDED
-  yylsp++;
-  if (yylen == 0)
-    {
-      yylsp->first_line = yylloc.first_line;
-      yylsp->first_column = yylloc.first_column;
-      yylsp->last_line = (yylsp-1)->last_line;
-      yylsp->last_column = (yylsp-1)->last_column;
-      yylsp->text = 0;
-    }
-  else
-    {
-      yylsp->last_line = (yylsp+yylen-1)->last_line;
-      yylsp->last_column = (yylsp+yylen-1)->last_column;
-    }
-#endif
-
-  /* Now "shift" the result of the reduction.
-     Determine what state that goes to,
-     based on the state we popped back to
-     and the rule number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
-  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTBASE];
-
-  goto yynewstate;
-
-yyerrlab:   /* here on detecting error */
-
-  if (! yyerrstatus)
-    /* If not already recovering from an error, report this error.  */
-    {
-      ++yynerrs;
-
-#ifdef YYERROR_VERBOSE
-      yyn = yypact[yystate];
-
-      if (yyn > YYFLAG && yyn < YYLAST)
-       {
-         int size = 0;
-         char *msg;
-         int x, count;
-
-         count = 0;
-         /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
-         for (x = (yyn < 0 ? -yyn : 0);
-              x < (sizeof(yytname) / sizeof(char *)); x++)
-           if (yycheck[x + yyn] == x)
-             size += strlen(yytname[x]) + 15, count++;
-         msg = (char *) malloc(size + 15);
-         if (msg != 0)
-           {
-             strcpy(msg, "parse error");
-
-             if (count < 5)
-               {
-                 count = 0;
-                 for (x = (yyn < 0 ? -yyn : 0);
-                      x < (sizeof(yytname) / sizeof(char *)); x++)
-                   if (yycheck[x + yyn] == x)
-                     {
-                       strcat(msg, count == 0 ? ", expecting `" : " or `");
-                       strcat(msg, yytname[x]);
-                       strcat(msg, "'");
-                       count++;
-                     }
-               }
-             yyerror(msg);
-             free(msg);
-           }
-         else
-           yyerror ("parse error; also virtual memory exceeded");
        }
-      else
-#endif /* YYERROR_VERBOSE */
-       yyerror("parse error");
+break;
+#line 1201 "y.tab.c"
     }
-
-  goto yyerrlab1;
-yyerrlab1:   /* here on error raised explicitly by an action */
-
-  if (yyerrstatus == 3)
+    yyssp -= yym;
+    yystate = *yyssp;
+    yyvsp -= yym;
+    yym = yylhs[yyn];
+    if (yystate == 0 && yym == 0)
     {
-      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
-
-      /* return failure if at end of input */
-      if (yychar == YYEOF)
-       YYABORT;
-
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
-#endif
-
-      yychar = YYEMPTY;
-    }
-
-  /* Else will try to reuse lookahead token
-     after shifting the error token.  */
-
-  yyerrstatus = 3;             /* Each real token shifted decrements this */
-
-  goto yyerrhandle;
-
-yyerrdefault:  /* current state does not do anything special for the error token. */
-
-#if 0
-  /* This is wrong; only states that explicitly want error tokens
-     should shift them.  */
-  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
-  if (yyn) goto yydefault;
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
 #endif
-
-yyerrpop:   /* pop the current state because it cannot handle the error token */
-
-  if (yyssp == yyss) YYABORT;
-  yyvsp--;
-  yystate = *--yyssp;
-#ifdef YYLSP_NEEDED
-  yylsp--;
+        yystate = YYFINAL;
+        *++yyssp = YYFINAL;
+        *++yyvsp = yyval;
+        if (yychar < 0)
+        {
+            if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+            if (yydebug)
+            {
+                yys = 0;
+                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+                if (!yys) yys = "illegal-symbol";
+                printf("%sdebug: state %d, reading %d (%s)\n",
+                        YYPREFIX, YYFINAL, yychar, yys);
+            }
 #endif
-
-#if YYDEBUG != 0
-  if (yydebug)
-    {
-      short *ssp1 = yyss - 1;
-      fprintf (stderr, "Error: state stack now");
-      while (ssp1 != yyssp)
-       fprintf (stderr, " %d", *++ssp1);
-      fprintf (stderr, "\n");
+        }
+        if (yychar == 0) goto yyaccept;
+        goto yyloop;
     }
+    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+        yystate = yytable[yyn];
+    else
+        yystate = yydgoto[yym];
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
 #endif
-
-yyerrhandle:
-
-  yyn = yypact[yystate];
-  if (yyn == YYFLAG)
-    goto yyerrdefault;
-
-  yyn += YYTERROR;
-  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
-    goto yyerrdefault;
-
-  yyn = yytable[yyn];
-  if (yyn < 0)
+    if (yyssp >= yyss + yystacksize - 1)
     {
-      if (yyn == YYFLAG)
-       goto yyerrpop;
-      yyn = -yyn;
-      goto yyreduce;
+        goto yyoverflow;
     }
-  else if (yyn == 0)
-    goto yyerrpop;
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Shifting error token, ");
-#endif
-
-  *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
-  *++yylsp = yylloc;
-#endif
-
-  yystate = yyn;
-  goto yynewstate;
+    *++yyssp = yystate;
+    *++yyvsp = yyval;
+    goto yyloop;
+yyoverflow:
+    yyerror("yacc stack overflow");
+yyabort:
+    return (1);
+yyaccept:
+    return (0);
 }
-#line 286 "parsedate.y"
-
-
-/* Month and day table. */
-static TABLE   MonthDayTable[] = {
-    { "january",       tMONTH,  1 },
-    { "february",      tMONTH,  2 },
-    { "march",         tMONTH,  3 },
-    { "april",         tMONTH,  4 },
-    { "may",           tMONTH,  5 },
-    { "june",          tMONTH,  6 },
-    { "july",          tMONTH,  7 },
-    { "august",                tMONTH,  8 },
-    { "september",     tMONTH,  9 },
-    { "october",       tMONTH, 10 },
-    { "november",      tMONTH, 11 },
-    { "december",      tMONTH, 12 },
-       /* The value of the day isn't used... */
-    { "sunday",                tDAY, 0 },
-    { "monday",                tDAY, 0 },
-    { "tuesday",       tDAY, 0 },
-    { "wednesday",     tDAY, 0 },
-    { "thursday",      tDAY, 0 },
-    { "friday",                tDAY, 0 },
-    { "saturday",      tDAY, 0 },
-};
-
-/* Time units table. */
-static TABLE   UnitsTable[] = {
-    { "year",          tMONTH_UNIT,    12 },
-    { "month",         tMONTH_UNIT,    1 },
-    { "week",          tSEC_UNIT,      7L * 24 * 60 * 60 },
-    { "day",           tSEC_UNIT,      1L * 24 * 60 * 60 },
-    { "hour",          tSEC_UNIT,      60 * 60 },
-    { "minute",                tSEC_UNIT,      60 },
-    { "min",           tSEC_UNIT,      60 },
-    { "second",                tSEC_UNIT,      1 },
-    { "sec",           tSEC_UNIT,      1 },
-};
-
-/* Timezone table. */
-static TABLE   TimezoneTable[] = {
-    { "gmt",   tZONE,     HOUR( 0) },  /* Greenwich Mean */
-    { "ut",    tZONE,     HOUR( 0) },  /* Universal */
-    { "utc",   tZONE,     HOUR( 0) },  /* Universal Coordinated */
-    { "cut",   tZONE,     HOUR( 0) },  /* Coordinated Universal */
-    { "z",     tZONE,     HOUR( 0) },  /* Greenwich Mean */
-    { "wet",   tZONE,     HOUR( 0) },  /* Western European */
-    { "bst",   tDAYZONE,  HOUR( 0) },  /* British Summer */
-    { "nst",   tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
-    { "ndt",   tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
-    { "ast",   tZONE,     HOUR( 4) },  /* Atlantic Standard */
-    { "adt",   tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
-    { "est",   tZONE,     HOUR( 5) },  /* Eastern Standard */
-    { "edt",   tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
-    { "cst",   tZONE,     HOUR( 6) },  /* Central Standard */
-    { "cdt",   tDAYZONE,  HOUR( 6) },  /* Central Daylight */
-    { "mst",   tZONE,     HOUR( 7) },  /* Mountain Standard */
-    { "mdt",   tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
-    { "pst",   tZONE,     HOUR( 8) },  /* Pacific Standard */
-    { "pdt",   tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
-    { "yst",   tZONE,     HOUR( 9) },  /* Yukon Standard */
-    { "ydt",   tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
-    { "akst",  tZONE,     HOUR( 9) },  /* Alaska Standard */
-    { "akdt",  tDAYZONE,  HOUR( 9) },  /* Alaska Daylight */
-    { "hst",   tZONE,     HOUR(10) },  /* Hawaii Standard */
-    { "hast",  tZONE,     HOUR(10) },  /* Hawaii-Aleutian Standard */
-    { "hadt",  tDAYZONE,  HOUR(10) },  /* Hawaii-Aleutian Daylight */
-    { "ces",   tDAYZONE,  -HOUR(1) },  /* Central European Summer */
-    { "cest",  tDAYZONE,  -HOUR(1) },  /* Central European Summer */
-    { "mez",   tZONE,     -HOUR(1) },  /* Middle European */
-    { "mezt",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
-    { "cet",   tZONE,     -HOUR(1) },  /* Central European */
-    { "met",   tZONE,     -HOUR(1) },  /* Middle European */
-    { "eet",   tZONE,     -HOUR(2) },  /* Eastern Europe */
-    { "msk",   tZONE,     -HOUR(3) },  /* Moscow Winter */
-    { "msd",   tDAYZONE,  -HOUR(3) },  /* Moscow Summer */
-    { "wast",  tZONE,     -HOUR(8) },  /* West Australian Standard */
-    { "wadt",  tDAYZONE,  -HOUR(8) },  /* West Australian Daylight */
-    { "hkt",   tZONE,     -HOUR(8) },  /* Hong Kong */
-    { "cct",   tZONE,     -HOUR(8) },  /* China Coast */
-    { "jst",   tZONE,     -HOUR(9) },  /* Japan Standard */
-    { "kst",   tZONE,     -HOUR(9) },  /* Korean Standard */
-    { "kdt",   tZONE,     -HOUR(9) },  /* Korean Daylight */
-    { "cast",  tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
-    { "cadt",  tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
-    { "east",  tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
-    { "eadt",  tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
-    { "nzst",  tZONE,     -HOUR(12) }, /* New Zealand Standard */
-    { "nzdt",  tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
-
-    /* For completeness we include the following entries. */
-#if 0
-
-    /* Duplicate names.  Either they conflict with a zone listed above
-     * (which is either more likely to be seen or just been in circulation
-     * longer), or they conflict with another zone in this section and
-     * we could not reasonably choose one over the other. */
-    { "fst",   tZONE,     HOUR( 2) },  /* Fernando De Noronha Standard */
-    { "fdt",   tDAYZONE,  HOUR( 2) },  /* Fernando De Noronha Daylight */
-    { "bst",   tZONE,     HOUR( 3) },  /* Brazil Standard */
-    { "est",   tZONE,     HOUR( 3) },  /* Eastern Standard (Brazil) */
-    { "edt",   tDAYZONE,  HOUR( 3) },  /* Eastern Daylight (Brazil) */
-    { "wst",   tZONE,     HOUR( 4) },  /* Western Standard (Brazil) */
-    { "wdt",   tDAYZONE,  HOUR( 4) },  /* Western Daylight (Brazil) */
-    { "cst",   tZONE,     HOUR( 5) },  /* Chile Standard */
-    { "cdt",   tDAYZONE,  HOUR( 5) },  /* Chile Daylight */
-    { "ast",   tZONE,     HOUR( 5) },  /* Acre Standard */
-    { "adt",   tDAYZONE,  HOUR( 5) },  /* Acre Daylight */
-    { "cst",   tZONE,     HOUR( 5) },  /* Cuba Standard */
-    { "cdt",   tDAYZONE,  HOUR( 5) },  /* Cuba Daylight */
-    { "est",   tZONE,     HOUR( 6) },  /* Easter Island Standard */
-    { "edt",   tDAYZONE,  HOUR( 6) },  /* Easter Island Daylight */
-    { "sst",   tZONE,     HOUR(11) },  /* Samoa Standard */
-    { "ist",   tZONE,     -HOUR(2) },  /* Israel Standard */
-    { "idt",   tDAYZONE,  -HOUR(2) },  /* Israel Daylight */
-    { "idt",   tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
-    { "ist",   tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
-    { "cst",    tZONE,     -HOUR(8) }, /* China Standard */
-    { "cdt",    tDAYZONE,  -HOUR(8) }, /* China Daylight */
-    { "sst",    tZONE,     -HOUR(8) }, /* Singapore Standard */
-
-    /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
-    { "gst",   tZONE,     HOUR( 3) },  /* Greenland Standard */
-    { "wat",   tZONE,     -HOUR(1) },  /* West Africa */
-    { "at",    tZONE,     HOUR( 2) },  /* Azores */
-    { "gst",   tZONE,     -HOUR(10) }, /* Guam Standard */
-    { "nft",   tZONE,     HOUR(3)+30 }, /* Newfoundland */
-    { "idlw",  tZONE,     HOUR(12) },  /* International Date Line West */
-    { "mewt",  tZONE,     -HOUR(1) },  /* Middle European Winter */
-    { "mest",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
-    { "swt",   tZONE,     -HOUR(1) },  /* Swedish Winter */
-    { "sst",   tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
-    { "fwt",   tZONE,     -HOUR(1) },  /* French Winter */
-    { "fst",   tDAYZONE,  -HOUR(1) },  /* French Summer */
-    { "bt",    tZONE,     -HOUR(3) },  /* Baghdad */
-    { "it",    tZONE,     -(HOUR(3)+30) }, /* Iran */
-    { "zp4",   tZONE,     -HOUR(4) },  /* USSR Zone 3 */
-    { "zp5",   tZONE,     -HOUR(5) },  /* USSR Zone 4 */
-    { "ist",   tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
-    { "zp6",   tZONE,     -HOUR(6) },  /* USSR Zone 5 */
-    { "nst",   tZONE,     -HOUR(7) },  /* North Sumatra */
-    { "sst",   tZONE,     -HOUR(7) },  /* South Sumatra */
-    { "jt",    tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
-    { "nzt",   tZONE,     -HOUR(12) }, /* New Zealand */
-    { "idle",  tZONE,     -HOUR(12) }, /* International Date Line East */
-    { "cat",   tZONE,     HOUR(10) },  /* -- expired 1967 */
-    { "nt",    tZONE,     HOUR(11) },  /* -- expired 1967 */
-    { "ahst",  tZONE,     HOUR(10) },  /* -- expired 1983 */
-    { "hdt",   tDAYZONE,  HOUR(10) },  /* -- expired 1986 */
-#endif /* 0 */
-};
-
-
-/* ARGSUSED */
-static void
-date_error(s)
-    char       *s;
-{
-    /* NOTREACHED */
-}
-
-
-static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-{
-    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
-       return -1;
-    if (Meridian == MER24) {
-       if (Hours < 0 || Hours > 23)
-           return -1;
-    }
-    else {
-       if (Hours < 1 || Hours > 12)
-           return -1;
-       if (Hours == 12)
-           Hours = 0;
-       if (Meridian == MERpm)
-           Hours += 12;
-    }
-    return (Hours * 60L + Minutes) * 60L + Seconds;
-}
-
-
-static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
-    time_t     Month;
-    time_t     Day;
-    time_t     Year;
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-    DSTMODE    dst;
-{
-    static int DaysNormal[13] = {
-       0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-    };
-    static int DaysLeap[13] = {
-       0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-    };
-    static int LeapYears[] = {
-       1972, 1976, 1980, 1984, 1988, 1992, 1996,
-       2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
-    };
-    register int       *yp;
-    register int       *mp;
-    register time_t    Julian;
-    register int       i;
-    time_t             tod;
-
-    if (Year < 0)
-       Year = -Year;
-    if (Year < 100)
-       Year += 1900;
-    if (Year < EPOCH)
-       Year += 100;
-    for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
-       if (Year == *yp) {
-           mp = DaysLeap;
-           break;
-       }
-    if (Year < EPOCH || Year > END_OF_TIME
-     || Month < 1 || Month > 12
-     /* NOSTRICT *//* conversion from long may lose accuracy */
-     || Day < 1 || Day > mp[(int)Month])
-       return -1;
-
-    Julian = Day - 1 + (Year - EPOCH) * 365;
-    for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
-       if (Year <= *yp)
-           break;
-    for (i = 1; i < Month; i++)
-       Julian += *++mp;
-    Julian *= SECSPERDAY;
-    Julian += yyTimezone * 60L;
-    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
-       return -1;
-    Julian += tod;
-    tod = Julian;
-    if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
-       Julian -= DST_OFFSET * 60L * 60L;
-    return Julian;
-}
-
-
-static time_t
-DSTcorrect(Start, Future)
-    time_t     Start;
-    time_t     Future;
-{
-    time_t     StartDay;
-    time_t     FutureDay;
-
-    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
-    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
-    return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
-}
-
-
-static time_t
-RelativeMonth(Start, RelMonth)
-    time_t     Start;
-    time_t     RelMonth;
-{
-    struct tm  *tm;
-    time_t     Month;
-    time_t     Year;
-
-    tm = localtime(&Start);
-    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
-    Year = Month / 12;
-    Month = Month % 12 + 1;
-    return DSTcorrect(Start,
-           Convert(Month, (time_t)tm->tm_mday, Year,
-               (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
-               MER24, DSTmaybe));
-}
-
-
-static int
-LookupWord(buff, length)
-    char               *buff;
-    register int       length;
-{
-    register char      *p;
-    register char      *q;
-    register TABLE     *tp;
-    register int       c;
-
-    p = buff;
-    c = p[0];
-
-    /* See if we have an abbreviation for a month. */
-    if (length == 3 || (length == 4 && p[3] == '.'))
-       for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
-           q = tp->name;
-           if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-       }
-    else
-       for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
-           if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-
-    /* Try for a timezone. */
-    for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
-       if (c == tp->name[0] && p[1] == tp->name[1]
-        && strcmp(p, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-
-    /* Try the units table. */
-    for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
-       if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-
-    /* Strip off any plural and try the units table again. */
-    if (--length > 0 && p[length] == 's') {
-       p[length] = '\0';
-       for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
-           if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
-               p[length] = 's';
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-       p[length] = 's';
-    }
-    length++;
-
-    /* Drop out any periods. */
-    for (p = buff, q = (char*)buff; *q; q++)
-       if (*q != '.')
-           *p++ = *q;
-    *p = '\0';
-
-    /* Try the meridians. */
-    if (buff[1] == 'm' && buff[2] == '\0') {
-       if (buff[0] == 'a') {
-           yylval.Meridian = MERam;
-           return tMERIDIAN;
-       }
-       if (buff[0] == 'p') {
-           yylval.Meridian = MERpm;
-           return tMERIDIAN;
-       }
-    }
-
-    /* If we saw any periods, try the timezones again. */
-    if (p - buff != length) {
-       c = buff[0];
-       for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
-           if (c == tp->name[0] && p[1] == tp->name[1]
-           && strcmp(p, tp->name) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-    }
-
-    /* Unknown word -- assume GMT timezone. */
-    yylval.Number = 0;
-    return tZONE;
-}
-
-
-int
-date_lex()
-{
-    register char      c;
-    register char      *p;
-    char               buff[20];
-    register int       sign;
-    register int       i;
-    register int       nesting;
-
-    for ( ; ; ) {
-       /* Get first character after the whitespace. */
-       for ( ; ; ) {
-           while (isspace(*yyInput))
-               yyInput++;
-           c = *yyInput;
-
-           /* Ignore RFC 822 comments, typically time zone names. */
-           if (c != LPAREN)
-               break;
-           for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
-               if (c == LPAREN)
-                   nesting++;
-               else if (!IS7BIT(c) || c == '\0' || c == '\r'
-                    || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
-                   /* Lexical error: bad comment. */
-                   return '?';
-           yyInput++;
-       }
-
-       /* A number? */
-       if (isdigit(c) || c == '-' || c == '+') {
-           if (c == '-' || c == '+') {
-               sign = c == '-' ? -1 : 1;
-               yyInput++;
-               if (!isdigit(*yyInput))
-                   /* Skip the plus or minus sign. */
-                   continue;
-           }
-           else
-               sign = 0;
-           for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
-               i = 10 * i + c - '0';
-           yyInput--;
-           yylval.Number = sign < 0 ? -i : i;
-           return sign ? tSNUMBER : tUNUMBER;
-       }
-
-       /* A word? */
-       if (isalpha(c)) {
-           for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
-               if (p < &buff[sizeof buff - 1])
-                   *p++ = isupper(c) ? tolower(c) : c;
-           *p = '\0';
-           yyInput--;
-           return LookupWord(buff, p - buff);
-       }
-
-       return *yyInput++;
-    }
-}
-
-
-time_t
-parsedate(p)
-    char               *p;
-{
-    extern int         date_parse();
-    time_t             Start;
-
-    yyInput = p;
-
-    yyYear = 0;
-    yyMonth = 0;
-    yyDay = 0;
-    yyTimezone = 0;
-    yyDSTmode = DSTmaybe;
-    yyHour = 0;
-    yyMinutes = 0;
-    yySeconds = 0;
-    yyMeridian = MER24;
-    yyRelSeconds = 0;
-    yyRelMonth = 0;
-    yyHaveDate = 0;
-    yyHaveRel = 0;
-    yyHaveTime = 0;
-
-    if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
-       return -1;
-
-    if (yyHaveDate || yyHaveTime) {
-       Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
-                   yyMeridian, yyDSTmode);
-       if (Start < 0)
-           return -1;
-    }
-    else
-       return -1;
-
-    Start += yyRelSeconds;
-    if (yyRelMonth)
-       Start += RelativeMonth(Start, yyRelMonth);
-
-    /* Have to do *something* with a legitimate -1 so it's distinguishable
-     * from the error return value.  (Alternately could set errno on error.) */
-    return Start == -1 ? 0 : Start;
-}
-
-
-#ifdef TEST
-
-#if YYDEBUG
-extern int     yydebug;
-#endif /* YYDEBUG */
-
-/* ARGSUSED */
-int
-main(ac, av)
-    int                ac;
-    char       *av[];
-{
-    char       buff[128];
-    time_t     d;
-
-#if YYDEBUG
-    yydebug = 1;
-#endif /* YYDEBUG */
-
-    (void)printf("Enter date, or blank line to exit.\n\t> ");
-    for ( ; ; ) {
-       (void)printf("\t> ");
-       (void)fflush(stdout);
-       if (gets(buff) == NULL || buff[0] == '\n')
-           break;
-#if YYDEBUG
-       if (strcmp(buff, "yydebug") == 0) {
-           yydebug = !yydebug;
-           printf("yydebug = %s\n", yydebug ? "on" : "off");
-           continue;
-       }
-#endif /* YYDEBUG */
-       d = parsedate(buff);
-       if (d == -1)
-           (void)printf("Bad format - couldn't convert.\n");
-       else
-           (void)printf("%s", ctime(&d));
-    }
-
-    exit(0);
-    /* NOTREACHED */
-}
-#endif /* TEST */