getdate.c

Go to the documentation of this file.
00001 /* A Bison parser, made by GNU Bison 1.875b.  */
00002 
00003 /* Skeleton parser for Yacc-like parsing with Bison,
00004    Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 /* As a special exception, when this file is copied by Bison into a
00022    Bison output file, you may use that output file without restriction.
00023    This special exception was added by the Free Software Foundation
00024    in version 1.24 of Bison.  */
00025 
00026 /* Written by Richard Stallman by simplifying the original so called
00027    ``semantic'' parser.  */
00028 
00029 /* All symbols defined below should begin with yy or YY, to avoid
00030    infringing on user name space.  This should be done even for local
00031    variables, as they might otherwise be expanded by user macros.
00032    There are some unavoidable exceptions within include files to
00033    define necessary library symbols; they are noted "INFRINGES ON
00034    USER NAME SPACE" below.  */
00035 
00036 /* Identify Bison output.  */
00037 #define YYBISON 1
00038 
00039 /* Skeleton name.  */
00040 #define YYSKELETON_NAME "yacc.c"
00041 
00042 /* Pure parsers.  */
00043 #define YYPURE 1
00044 
00045 /* Using locations.  */
00046 #define YYLSP_NEEDED 0
00047 
00048 
00049 
00050 /* Tokens.  */
00051 #ifndef YYTOKENTYPE
00052 # define YYTOKENTYPE
00053    /* Put the tokens into the symbol table, so that GDB and other debuggers
00054       know about them.  */
00055    enum yytokentype {
00056      tAGO = 258,
00057      tDST = 259,
00058      tDAY = 260,
00059      tDAY_UNIT = 261,
00060      tDAYZONE = 262,
00061      tHOUR_UNIT = 263,
00062      tLOCAL_ZONE = 264,
00063      tMERIDIAN = 265,
00064      tMINUTE_UNIT = 266,
00065      tMONTH = 267,
00066      tMONTH_UNIT = 268,
00067      tSEC_UNIT = 269,
00068      tYEAR_UNIT = 270,
00069      tZONE = 271,
00070      tSNUMBER = 272,
00071      tUNUMBER = 273
00072    };
00073 #endif
00074 #define tAGO 258
00075 #define tDST 259
00076 #define tDAY 260
00077 #define tDAY_UNIT 261
00078 #define tDAYZONE 262
00079 #define tHOUR_UNIT 263
00080 #define tLOCAL_ZONE 264
00081 #define tMERIDIAN 265
00082 #define tMINUTE_UNIT 266
00083 #define tMONTH 267
00084 #define tMONTH_UNIT 268
00085 #define tSEC_UNIT 269
00086 #define tYEAR_UNIT 270
00087 #define tZONE 271
00088 #define tSNUMBER 272
00089 #define tUNUMBER 273
00090 
00091 
00092 
00093 
00094 /* Copy the first part of user declarations.  */
00095 #line 1 "getdate.y"
00096 
00097 /* Parse a string into an internal time stamp.
00098    Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
00099 
00100    This program is free software; you can redistribute it and/or modify
00101    it under the terms of the GNU General Public License as published by
00102    the Free Software Foundation; either version 2, or (at your option)
00103    any later version.
00104 
00105    This program is distributed in the hope that it will be useful,
00106    but WITHOUT ANY WARRANTY; without even the implied warranty of
00107    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00108    GNU General Public License for more details.
00109 
00110    You should have received a copy of the GNU General Public License
00111    along with this program; if not, write to the Free Software Foundation,
00112    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00113 
00114 /* Originally written by Steven M. Bellovin <smb@research.att.com> while
00115    at the University of North Carolina at Chapel Hill.  Later tweaked by
00116    a couple of people on Usenet.  Completely overhauled by Rich $alz
00117    <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
00118 
00119    Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
00120    the right thing about local DST.  Unlike previous versions, this
00121    version is reentrant.  */
00122 
00123 #ifdef HAVE_CONFIG_H
00124 # include <config.h>
00125 #endif
00126 
00127 #include <alloca.h>
00128 
00129 /* Since the code of getdate.y is not included in the Emacs executable
00130    itself, there is no need to #define static in this file.  Even if
00131    the code were included in the Emacs executable, it probably
00132    wouldn't do any harm to #undef it here; this will only cause
00133    problems if we try to write to a static variable, which I don't
00134    think this code needs to do.  */
00135 #ifdef emacs
00136 # undef static
00137 #endif
00138 
00139 #include <ctype.h>
00140 
00141 #include <stdlib.h> /* for `free'; used by Bison 1.27 */
00142 
00143 #if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
00144 # define IN_CTYPE_DOMAIN(c) 1
00145 #else
00146 # define IN_CTYPE_DOMAIN(c) isascii (c)
00147 #endif
00148 
00149 #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
00150 #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
00151 #define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
00152 #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
00153 
00154 /* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
00155    - Its arg may be any int or unsigned int; it need not be an unsigned char.
00156    - It's guaranteed to evaluate its argument exactly once.
00157    - It's typically faster.
00158    POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
00159    ISDIGIT_LOCALE unless it's important to use the locale's definition
00160    of `digit' even when the host does not conform to POSIX.  */
00161 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
00162 
00163 #include <string.h>
00164 
00165 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
00166 # define __attribute__(x)
00167 #endif
00168 
00169 #ifndef ATTRIBUTE_UNUSED
00170 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
00171 #endif
00172 
00173 #define EPOCH_YEAR 1970
00174 #define TM_YEAR_BASE 1900
00175 
00176 #define HOUR(x) ((x) * 60)
00177 
00178 /* An integer value, and the number of digits in its textual
00179    representation.  */
00180 typedef struct
00181 {
00182   int value;
00183   int digits;
00184 } textint;
00185 
00186 /* An entry in the lexical lookup table.  */
00187 typedef struct
00188 {
00189   char const *name;
00190   int type;
00191   int value;
00192 } table;
00193 
00194 /* Meridian: am, pm, or 24-hour style.  */
00195 enum { MERam, MERpm, MER24 };
00196 
00197 /* Information passed to and from the parser.  */
00198 typedef struct
00199 {
00200   /* The input string remaining to be parsed. */
00201   const char *input;
00202 
00203   /* N, if this is the Nth Tuesday.  */
00204   int day_ordinal;
00205 
00206   /* Day of week; Sunday is 0.  */
00207   int day_number;
00208 
00209   /* tm_isdst flag for the local zone.  */
00210   int local_isdst;
00211 
00212   /* Time zone, in minutes east of UTC.  */
00213   int time_zone;
00214 
00215   /* Style used for time.  */
00216   int meridian;
00217 
00218   /* Gregorian year, month, day, hour, minutes, and seconds.  */
00219   textint year;
00220   int month;
00221   int day;
00222   int hour;
00223   int minutes;
00224   int seconds;
00225 
00226   /* Relative year, month, day, hour, minutes, and seconds.  */
00227   int rel_year;
00228   int rel_month;
00229   int rel_day;
00230   int rel_hour;
00231   int rel_minutes;
00232   int rel_seconds;
00233 
00234   /* Counts of nonterminals of various flavors parsed so far.  */
00235   int dates_seen;
00236   int days_seen;
00237   int local_zones_seen;
00238   int rels_seen;
00239   int times_seen;
00240   int zones_seen;
00241 
00242   /* Table of local time zone abbrevations, terminated by a null entry.  */
00243   table local_time_zone_table[3];
00244 } parser_control;
00245 
00246 #define PC (* (parser_control *) parm)
00247 #define YYLEX_PARAM parm
00248 #define YYPARSE_PARAM parm
00249 
00250 static int yyerror ();
00251 static int yylex ();
00252 
00253 
00254 
00255 /* Enabling traces.  */
00256 #ifndef YYDEBUG
00257 # define YYDEBUG 0
00258 #endif
00259 
00260 /* Enabling verbose error messages.  */
00261 #ifdef YYERROR_VERBOSE
00262 # undef YYERROR_VERBOSE
00263 # define YYERROR_VERBOSE 1
00264 #else
00265 # define YYERROR_VERBOSE 0
00266 #endif
00267 
00268 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
00269 #line 167 "getdate.y"
00270 typedef union YYSTYPE {
00271   int intval;
00272   textint textintval;
00273 } YYSTYPE;
00274 /* Line 191 of yacc.c.  */
00275 #line 276 "getdate.c"
00276 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
00277 # define YYSTYPE_IS_DECLARED 1
00278 # define YYSTYPE_IS_TRIVIAL 1
00279 #endif
00280 
00281 
00282 
00283 /* Copy the second part of user declarations.  */
00284 
00285 
00286 /* Line 214 of yacc.c.  */
00287 #line 288 "getdate.c"
00288 
00289 #if ! defined (yyoverflow) || YYERROR_VERBOSE
00290 
00291 /* The parser invokes alloca or malloc; define the necessary symbols.  */
00292 
00293 # if YYSTACK_USE_ALLOCA
00294 #  define YYSTACK_ALLOC alloca
00295 # else
00296 #  ifndef YYSTACK_USE_ALLOCA
00297 #   if defined (alloca) || defined (_ALLOCA_H)
00298 #    define YYSTACK_ALLOC alloca
00299 #   else
00300 #    ifdef __GNUC__
00301 #     define YYSTACK_ALLOC __builtin_alloca
00302 #    endif
00303 #   endif
00304 #  endif
00305 # endif
00306 
00307 # ifdef YYSTACK_ALLOC
00308    /* Pacify GCC's `empty if-body' warning. */
00309 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
00310 # else
00311 #  if defined (__STDC__) || defined (__cplusplus)
00312 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
00313 #   define YYSIZE_T size_t
00314 #  endif
00315 #  define YYSTACK_ALLOC malloc
00316 #  define YYSTACK_FREE free
00317 # endif
00318 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
00319 
00320 
00321 #if (! defined (yyoverflow) \
00322      && (! defined (__cplusplus) \
00323          || (YYSTYPE_IS_TRIVIAL)))
00324 
00325 /* A type that is properly aligned for any stack member.  */
00326 union yyalloc
00327 {
00328   short yyss;
00329   YYSTYPE yyvs;
00330   };
00331 
00332 /* The size of the maximum gap between one aligned stack and the next.  */
00333 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
00334 
00335 /* The size of an array large to enough to hold all stacks, each with
00336    N elements.  */
00337 # define YYSTACK_BYTES(N) \
00338      ((N) * (sizeof (short) + sizeof (YYSTYPE))                         \
00339       + YYSTACK_GAP_MAXIMUM)
00340 
00341 /* Copy COUNT objects from FROM to TO.  The source and destination do
00342    not overlap.  */
00343 # ifndef YYCOPY
00344 #  if 1 < __GNUC__
00345 #   define YYCOPY(To, From, Count) \
00346       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
00347 #  else
00348 #   define YYCOPY(To, From, Count)              \
00349       do                                        \
00350         {                                       \
00351           register YYSIZE_T yyi;                \
00352           for (yyi = 0; yyi < (Count); yyi++)   \
00353             (To)[yyi] = (From)[yyi];            \
00354         }                                       \
00355       while (0)
00356 #  endif
00357 # endif
00358 
00359 /* Relocate STACK from its old location to the new one.  The
00360    local variables YYSIZE and YYSTACKSIZE give the old and new number of
00361    elements in the stack, and YYPTR gives the new location of the
00362    stack.  Advance YYPTR to a properly aligned location for the next
00363    stack.  */
00364 # define YYSTACK_RELOCATE(Stack)                                        \
00365     do                                                                  \
00366       {                                                                 \
00367         YYSIZE_T yynewbytes;                                            \
00368         YYCOPY (&yyptr->Stack, Stack, yysize);                          \
00369         Stack = &yyptr->Stack;                                          \
00370         yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
00371         yyptr += yynewbytes / sizeof (*yyptr);                          \
00372       }                                                                 \
00373     while (0)
00374 
00375 #endif
00376 
00377 #if defined (__STDC__) || defined (__cplusplus)
00378    typedef signed char yysigned_char;
00379 #else
00380    typedef short yysigned_char;
00381 #endif
00382 
00383 /* YYFINAL -- State number of the termination state. */
00384 #define YYFINAL  2
00385 /* YYLAST -- Last index in YYTABLE.  */
00386 #define YYLAST   55
00387 
00388 /* YYNTOKENS -- Number of terminals. */
00389 #define YYNTOKENS  22
00390 /* YYNNTS -- Number of nonterminals. */
00391 #define YYNNTS  12
00392 /* YYNRULES -- Number of rules. */
00393 #define YYNRULES  55
00394 /* YYNRULES -- Number of states. */
00395 #define YYNSTATES  66
00396 
00397 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
00398 #define YYUNDEFTOK  2
00399 #define YYMAXUTOK   273
00400 
00401 #define YYTRANSLATE(YYX)                                                \
00402   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
00403 
00404 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
00405 static const unsigned char yytranslate[] =
00406 {
00407        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00408        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00409        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00410        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00411        2,     2,     2,     2,    20,     2,     2,    21,     2,     2,
00412        2,     2,     2,     2,     2,     2,     2,     2,    19,     2,
00413        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00414        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00415        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00416        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00417        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00418        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00419        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00420        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00421        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00422        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00423        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00424        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00425        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00426        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00427        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00428        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00429        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00430        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00431        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
00432        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
00433        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
00434       15,    16,    17,    18
00435 };
00436 
00437 #if YYDEBUG
00438 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
00439    YYRHS.  */
00440 static const unsigned char yyprhs[] =
00441 {
00442        0,     0,     3,     4,     7,     9,    11,    13,    15,    17,
00443       19,    21,    24,    29,    34,    41,    48,    50,    53,    55,
00444       57,    60,    62,    65,    68,    72,    78,    82,    86,    90,
00445       93,    98,   101,   105,   108,   110,   113,   116,   118,   121,
00446      124,   126,   129,   132,   134,   137,   140,   142,   145,   148,
00447      150,   153,   156,   158,   160,   161
00448 };
00449 
00450 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
00451 static const yysigned_char yyrhs[] =
00452 {
00453       23,     0,    -1,    -1,    23,    24,    -1,    25,    -1,    26,
00454       -1,    27,    -1,    29,    -1,    28,    -1,    30,    -1,    32,
00455       -1,    18,    10,    -1,    18,    19,    18,    33,    -1,    18,
00456       19,    18,    17,    -1,    18,    19,    18,    19,    18,    33,
00457       -1,    18,    19,    18,    19,    18,    17,    -1,     9,    -1,
00458        9,     4,    -1,    16,    -1,     7,    -1,    16,     4,    -1,
00459        5,    -1,     5,    20,    -1,    18,     5,    -1,    18,    21,
00460       18,    -1,    18,    21,    18,    21,    18,    -1,    18,    17,
00461       17,    -1,    18,    12,    17,    -1,    12,    17,    17,    -1,
00462       12,    18,    -1,    12,    18,    20,    18,    -1,    18,    12,
00463       -1,    18,    12,    18,    -1,    31,     3,    -1,    31,    -1,
00464       18,    15,    -1,    17,    15,    -1,    15,    -1,    18,    13,
00465       -1,    17,    13,    -1,    13,    -1,    18,     6,    -1,    17,
00466        6,    -1,     6,    -1,    18,     8,    -1,    17,     8,    -1,
00467        8,    -1,    18,    11,    -1,    17,    11,    -1,    11,    -1,
00468       18,    14,    -1,    17,    14,    -1,    14,    -1,    18,    -1,
00469       -1,    10,    -1
00470 };
00471 
00472 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
00473 static const unsigned short yyrline[] =
00474 {
00475        0,   183,   183,   185,   189,   191,   193,   195,   197,   199,
00476      201,   205,   212,   219,   227,   234,   246,   248,   253,   255,
00477      257,   262,   267,   272,   280,   285,   305,   312,   320,   328,
00478      333,   339,   344,   353,   362,   366,   368,   370,   372,   374,
00479      376,   378,   380,   382,   384,   386,   388,   390,   392,   394,
00480      396,   398,   400,   405,   442,   443
00481 };
00482 #endif
00483 
00484 #if YYDEBUG || YYERROR_VERBOSE
00485 /* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
00486    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
00487 static const char *const yytname[] =
00488 {
00489   "$end", "error", "$undefined", "tAGO", "tDST", "tDAY", "tDAY_UNIT", 
00490   "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT", 
00491   "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER", 
00492   "tUNUMBER", "':'", "','", "'/'", "$accept", "spec", "item", "time", 
00493   "local_zone", "zone", "day", "date", "rel", "relunit", "number", 
00494   "o_merid", 0
00495 };
00496 #endif
00497 
00498 # ifdef YYPRINT
00499 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
00500    token YYLEX-NUM.  */
00501 static const unsigned short yytoknum[] =
00502 {
00503        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
00504      265,   266,   267,   268,   269,   270,   271,   272,   273,    58,
00505       44,    47
00506 };
00507 # endif
00508 
00509 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
00510 static const unsigned char yyr1[] =
00511 {
00512        0,    22,    23,    23,    24,    24,    24,    24,    24,    24,
00513       24,    25,    25,    25,    25,    25,    26,    26,    27,    27,
00514       27,    28,    28,    28,    29,    29,    29,    29,    29,    29,
00515       29,    29,    29,    30,    30,    31,    31,    31,    31,    31,
00516       31,    31,    31,    31,    31,    31,    31,    31,    31,    31,
00517       31,    31,    31,    32,    33,    33
00518 };
00519 
00520 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
00521 static const unsigned char yyr2[] =
00522 {
00523        0,     2,     0,     2,     1,     1,     1,     1,     1,     1,
00524        1,     2,     4,     4,     6,     6,     1,     2,     1,     1,
00525        2,     1,     2,     2,     3,     5,     3,     3,     3,     2,
00526        4,     2,     3,     2,     1,     2,     2,     1,     2,     2,
00527        1,     2,     2,     1,     2,     2,     1,     2,     2,     1,
00528        2,     2,     1,     1,     0,     1
00529 };
00530 
00531 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
00532    STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
00533    means the default is an error.  */
00534 static const unsigned char yydefact[] =
00535 {
00536        2,     0,     1,    21,    43,    19,    46,    16,    49,     0,
00537       40,    52,    37,    18,     0,    53,     3,     4,     5,     6,
00538        8,     7,     9,    34,    10,    22,    17,     0,    29,    20,
00539       42,    45,    48,    39,    51,    36,    23,    41,    44,    11,
00540       47,    31,    38,    50,    35,     0,     0,     0,    33,    28,
00541        0,    27,    32,    26,    54,    24,    30,    55,    13,     0,
00542       12,     0,    54,    25,    15,    14
00543 };
00544 
00545 /* YYDEFGOTO[NTERM-NUM]. */
00546 static const yysigned_char yydefgoto[] =
00547 {
00548       -1,     1,    16,    17,    18,    19,    20,    21,    22,    23,
00549       24,    60
00550 };
00551 
00552 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
00553    STATE-NUM.  */
00554 #define YYPACT_NINF -17
00555 static const yysigned_char yypact[] =
00556 {
00557      -17,     0,   -17,     1,   -17,   -17,   -17,    19,   -17,   -16,
00558      -17,   -17,   -17,    32,    26,    14,   -17,   -17,   -17,   -17,
00559      -17,   -17,   -17,    27,   -17,   -17,   -17,   -13,    24,   -17,
00560      -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,
00561      -17,    25,   -17,   -17,   -17,    29,    30,    31,   -17,   -17,
00562       33,   -17,   -17,   -17,    28,    34,   -17,   -17,   -17,    35,
00563      -17,    36,    -7,   -17,   -17,   -17
00564 };
00565 
00566 /* YYPGOTO[NTERM-NUM].  */
00567 static const yysigned_char yypgoto[] =
00568 {
00569      -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,   -17,
00570      -17,   -12
00571 };
00572 
00573 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
00574    positive, shift that token.  If negative, reduce the rule which
00575    number is the opposite.  If zero, do what YYDEFACT says.
00576    If YYTABLE_NINF, syntax error.  */
00577 #define YYTABLE_NINF -1
00578 static const unsigned char yytable[] =
00579 {
00580        2,    27,    28,    57,    49,     3,     4,     5,     6,     7,
00581       64,     8,     9,    10,    11,    12,    13,    14,    15,    36,
00582       37,    25,    38,    26,    39,    40,    41,    42,    43,    44,
00583       48,    45,    30,    46,    31,    47,    29,    32,    57,    33,
00584       34,    35,    51,    52,    50,    58,    53,    59,    54,    55,
00585       65,    56,     0,    62,    63,    61
00586 };
00587 
00588 static const yysigned_char yycheck[] =
00589 {
00590        0,    17,    18,    10,    17,     5,     6,     7,     8,     9,
00591       17,    11,    12,    13,    14,    15,    16,    17,    18,     5,
00592        6,    20,     8,     4,    10,    11,    12,    13,    14,    15,
00593        3,    17,     6,    19,     8,    21,     4,    11,    10,    13,
00594       14,    15,    17,    18,    20,    17,    17,    19,    18,    18,
00595       62,    18,    -1,    18,    18,    21
00596 };
00597 
00598 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
00599    symbol of state STATE-NUM.  */
00600 static const unsigned char yystos[] =
00601 {
00602        0,    23,     0,     5,     6,     7,     8,     9,    11,    12,
00603       13,    14,    15,    16,    17,    18,    24,    25,    26,    27,
00604       28,    29,    30,    31,    32,    20,     4,    17,    18,     4,
00605        6,     8,    11,    13,    14,    15,     5,     6,     8,    10,
00606       11,    12,    13,    14,    15,    17,    19,    21,     3,    17,
00607       20,    17,    18,    17,    18,    18,    18,    10,    17,    19,
00608       33,    21,    18,    18,    17,    33
00609 };
00610 
00611 #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
00612 # define YYSIZE_T __SIZE_TYPE__
00613 #endif
00614 #if ! defined (YYSIZE_T) && defined (size_t)
00615 # define YYSIZE_T size_t
00616 #endif
00617 #if ! defined (YYSIZE_T)
00618 # if defined (__STDC__) || defined (__cplusplus)
00619 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
00620 #  define YYSIZE_T size_t
00621 # endif
00622 #endif
00623 #if ! defined (YYSIZE_T)
00624 # define YYSIZE_T unsigned int
00625 #endif
00626 
00627 #define yyerrok         (yyerrstatus = 0)
00628 #define yyclearin       (yychar = YYEMPTY)
00629 #define YYEMPTY         (-2)
00630 #define YYEOF           0
00631 
00632 #define YYACCEPT        goto yyacceptlab
00633 #define YYABORT         goto yyabortlab
00634 #define YYERROR         goto yyerrlab1
00635 
00636 
00637 /* Like YYERROR except do call yyerror.  This remains here temporarily
00638    to ease the transition to the new meaning of YYERROR, for GCC.
00639    Once GCC version 2 has supplanted version 1, this can go.  */
00640 
00641 #define YYFAIL          goto yyerrlab
00642 
00643 #define YYRECOVERING()  (!!yyerrstatus)
00644 
00645 #define YYBACKUP(Token, Value)                                  \
00646 do                                                              \
00647   if (yychar == YYEMPTY && yylen == 1)                          \
00648     {                                                           \
00649       yychar = (Token);                                         \
00650       yylval = (Value);                                         \
00651       yytoken = YYTRANSLATE (yychar);                           \
00652       YYPOPSTACK;                                               \
00653       goto yybackup;                                            \
00654     }                                                           \
00655   else                                                          \
00656     {                                                           \
00657       yyerror ("syntax error: cannot back up");\
00658       YYERROR;                                                  \
00659     }                                                           \
00660 while (0)
00661 
00662 #define YYTERROR        1
00663 #define YYERRCODE       256
00664 
00665 /* YYLLOC_DEFAULT -- Compute the default location (before the actions
00666    are run).  */
00667 
00668 #ifndef YYLLOC_DEFAULT
00669 # define YYLLOC_DEFAULT(Current, Rhs, N)         \
00670   Current.first_line   = Rhs[1].first_line;      \
00671   Current.first_column = Rhs[1].first_column;    \
00672   Current.last_line    = Rhs[N].last_line;       \
00673   Current.last_column  = Rhs[N].last_column;
00674 #endif
00675 
00676 /* YYLEX -- calling `yylex' with the right arguments.  */
00677 
00678 #ifdef YYLEX_PARAM
00679 # define YYLEX yylex (&yylval, YYLEX_PARAM)
00680 #else
00681 # define YYLEX yylex (&yylval)
00682 #endif
00683 
00684 /* Enable debugging if requested.  */
00685 #if YYDEBUG
00686 
00687 # ifndef YYFPRINTF
00688 #  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
00689 #  define YYFPRINTF fprintf
00690 # endif
00691 
00692 # define YYDPRINTF(Args)                        \
00693 do {                                            \
00694   if (yydebug)                                  \
00695     YYFPRINTF Args;                             \
00696 } while (0)
00697 
00698 # define YYDSYMPRINT(Args)                      \
00699 do {                                            \
00700   if (yydebug)                                  \
00701     yysymprint Args;                            \
00702 } while (0)
00703 
00704 # define YYDSYMPRINTF(Title, Token, Value, Location)            \
00705 do {                                                            \
00706   if (yydebug)                                                  \
00707     {                                                           \
00708       YYFPRINTF (stderr, "%s ", Title);                         \
00709       yysymprint (stderr,                                       \
00710                   Token, Value);        \
00711       YYFPRINTF (stderr, "\n");                                 \
00712     }                                                           \
00713 } while (0)
00714 
00715 /*------------------------------------------------------------------.
00716 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
00717 | TOP (cinluded).                                                   |
00718 `------------------------------------------------------------------*/
00719 
00720 #if defined (__STDC__) || defined (__cplusplus)
00721 static void
00722 yy_stack_print (short *bottom, short *top)
00723 #else
00724 static void
00725 yy_stack_print (bottom, top)
00726     short *bottom;
00727     short *top;
00728 #endif
00729 {
00730   YYFPRINTF (stderr, "Stack now");
00731   for (/* Nothing. */; bottom <= top; ++bottom)
00732     YYFPRINTF (stderr, " %d", *bottom);
00733   YYFPRINTF (stderr, "\n");
00734 }
00735 
00736 # define YY_STACK_PRINT(Bottom, Top)                            \
00737 do {                                                            \
00738   if (yydebug)                                                  \
00739     yy_stack_print ((Bottom), (Top));                           \
00740 } while (0)
00741 
00742 
00743 /*------------------------------------------------.
00744 | Report that the YYRULE is going to be reduced.  |
00745 `------------------------------------------------*/
00746 
00747 #if defined (__STDC__) || defined (__cplusplus)
00748 static void
00749 yy_reduce_print (int yyrule)
00750 #else
00751 static void
00752 yy_reduce_print (yyrule)
00753     int yyrule;
00754 #endif
00755 {
00756   int yyi;
00757   unsigned int yylno = yyrline[yyrule];
00758   YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
00759              yyrule - 1, yylno);
00760   /* Print the symbols being reduced, and their result.  */
00761   for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
00762     YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
00763   YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
00764 }
00765 
00766 # define YY_REDUCE_PRINT(Rule)          \
00767 do {                                    \
00768   if (yydebug)                          \
00769     yy_reduce_print (Rule);             \
00770 } while (0)
00771 
00772 /* Nonzero means print parse trace.  It is left uninitialized so that
00773    multiple parsers can coexist.  */
00774 int yydebug;
00775 #else /* !YYDEBUG */
00776 # define YYDPRINTF(Args)
00777 # define YYDSYMPRINT(Args)
00778 # define YYDSYMPRINTF(Title, Token, Value, Location)
00779 # define YY_STACK_PRINT(Bottom, Top)
00780 # define YY_REDUCE_PRINT(Rule)
00781 #endif /* !YYDEBUG */
00782 
00783 
00784 /* YYINITDEPTH -- initial size of the parser's stacks.  */
00785 #ifndef YYINITDEPTH
00786 # define YYINITDEPTH 200
00787 #endif
00788 
00789 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
00790    if the built-in stack extension method is used).
00791 
00792    Do not make this value too large; the results are undefined if
00793    SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
00794    evaluated with infinite-precision integer arithmetic.  */
00795 
00796 #if YYMAXDEPTH == 0
00797 # undef YYMAXDEPTH
00798 #endif
00799 
00800 #ifndef YYMAXDEPTH
00801 # define YYMAXDEPTH 10000
00802 #endif
00803 
00804 
00805 
00806 #if YYERROR_VERBOSE
00807 
00808 # ifndef yystrlen
00809 #  if defined (__GLIBC__) && defined (_STRING_H)
00810 #   define yystrlen strlen
00811 #  else
00812 /* Return the length of YYSTR.  */
00813 static YYSIZE_T
00814 #   if defined (__STDC__) || defined (__cplusplus)
00815 yystrlen (const char *yystr)
00816 #   else
00817 yystrlen (yystr)
00818      const char *yystr;
00819 #   endif
00820 {
00821   register const char *yys = yystr;
00822 
00823   while (*yys++ != '\0')
00824     continue;
00825 
00826   return yys - yystr - 1;
00827 }
00828 #  endif
00829 # endif
00830 
00831 # ifndef yystpcpy
00832 #  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
00833 #   define yystpcpy stpcpy
00834 #  else
00835 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
00836    YYDEST.  */
00837 static char *
00838 #   if defined (__STDC__) || defined (__cplusplus)
00839 yystpcpy (char *yydest, const char *yysrc)
00840 #   else
00841 yystpcpy (yydest, yysrc)
00842      char *yydest;
00843      const char *yysrc;
00844 #   endif
00845 {
00846   register char *yyd = yydest;
00847   register const char *yys = yysrc;
00848 
00849   while ((*yyd++ = *yys++) != '\0')
00850     continue;
00851 
00852   return yyd - 1;
00853 }
00854 #  endif
00855 # endif
00856 
00857 #endif /* !YYERROR_VERBOSE */
00858 
00859 
00860 
00861 #if YYDEBUG
00862 /*--------------------------------.
00863 | Print this symbol on YYOUTPUT.  |
00864 `--------------------------------*/
00865 
00866 #if defined (__STDC__) || defined (__cplusplus)
00867 static void
00868 yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
00869 #else
00870 static void
00871 yysymprint (yyoutput, yytype, yyvaluep)
00872     FILE *yyoutput;
00873     int yytype;
00874     YYSTYPE *yyvaluep;
00875 #endif
00876 {
00877   /* Pacify ``unused variable'' warnings.  */
00878   (void) yyvaluep;
00879 
00880   if (yytype < YYNTOKENS)
00881     {
00882       YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
00883 # ifdef YYPRINT
00884       YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
00885 # endif
00886     }
00887   else
00888     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
00889 
00890   switch (yytype)
00891     {
00892       default:
00893         break;
00894     }
00895   YYFPRINTF (yyoutput, ")");
00896 }
00897 
00898 #endif /* ! YYDEBUG */
00899 /*-----------------------------------------------.
00900 | Release the memory associated to this symbol.  |
00901 `-----------------------------------------------*/
00902 
00903 #if defined (__STDC__) || defined (__cplusplus)
00904 static void
00905 yydestruct (int yytype, YYSTYPE *yyvaluep)
00906 #else
00907 static void
00908 yydestruct (yytype, yyvaluep)
00909     int yytype;
00910     YYSTYPE *yyvaluep;
00911 #endif
00912 {
00913   /* Pacify ``unused variable'' warnings.  */
00914   (void) yyvaluep;
00915 
00916   switch (yytype)
00917     {
00918 
00919       default:
00920         break;
00921     }
00922 }
00923 
00924 
00925 /* Prevent warnings from -Wmissing-prototypes.  */
00926 
00927 #ifdef YYPARSE_PARAM
00928 # if defined (__STDC__) || defined (__cplusplus)
00929 int yyparse (void *YYPARSE_PARAM);
00930 # else
00931 int yyparse ();
00932 # endif
00933 #else /* ! YYPARSE_PARAM */
00934 #if defined (__STDC__) || defined (__cplusplus)
00935 int yyparse (void);
00936 #else
00937 int yyparse ();
00938 #endif
00939 #endif /* ! YYPARSE_PARAM */
00940 
00941 
00942 
00943 
00944 
00945 
00946 /*----------.
00947 | yyparse.  |
00948 `----------*/
00949 
00950 #ifdef YYPARSE_PARAM
00951 # if defined (__STDC__) || defined (__cplusplus)
00952 int yyparse (void *YYPARSE_PARAM)
00953 # else
00954 int yyparse (YYPARSE_PARAM)
00955   void *YYPARSE_PARAM;
00956 # endif
00957 #else /* ! YYPARSE_PARAM */
00958 #if defined (__STDC__) || defined (__cplusplus)
00959 int
00960 yyparse (void)
00961 #else
00962 int
00963 yyparse ()
00964 
00965 #endif
00966 #endif
00967 {
00968   /* The lookahead symbol.  */
00969 int yychar;
00970 
00971 /* The semantic value of the lookahead symbol.  */
00972 YYSTYPE yylval;
00973 
00974 /* Number of syntax errors so far.  */
00975 int yynerrs;
00976 
00977   register int yystate;
00978   register int yyn;
00979   int yyresult;
00980   /* Number of tokens to shift before error messages enabled.  */
00981   int yyerrstatus;
00982   /* Lookahead token as an internal (translated) token number.  */
00983   int yytoken = 0;
00984 
00985   /* Three stacks and their tools:
00986      `yyss': related to states,
00987      `yyvs': related to semantic values,
00988      `yyls': related to locations.
00989 
00990      Refer to the stacks thru separate pointers, to allow yyoverflow
00991      to reallocate them elsewhere.  */
00992 
00993   /* The state stack.  */
00994   short yyssa[YYINITDEPTH];
00995   short *yyss = yyssa;
00996   register short *yyssp;
00997 
00998   /* The semantic value stack.  */
00999   YYSTYPE yyvsa[YYINITDEPTH];
01000   YYSTYPE *yyvs = yyvsa;
01001   register YYSTYPE *yyvsp;
01002 
01003 
01004 
01005 #define YYPOPSTACK   (yyvsp--, yyssp--)
01006 
01007   YYSIZE_T yystacksize = YYINITDEPTH;
01008 
01009   /* The variables used to return semantic value and location from the
01010      action routines.  */
01011   YYSTYPE yyval;
01012 
01013 
01014   /* When reducing, the number of symbols on the RHS of the reduced
01015      rule.  */
01016   int yylen;
01017 
01018   YYDPRINTF ((stderr, "Starting parse\n"));
01019 
01020   yystate = 0;
01021   yyerrstatus = 0;
01022   yynerrs = 0;
01023   yychar = YYEMPTY;             /* Cause a token to be read.  */
01024 
01025   /* Initialize stack pointers.
01026      Waste one element of value and location stack
01027      so that they stay on the same level as the state stack.
01028      The wasted elements are never initialized.  */
01029 
01030   yyssp = yyss;
01031   yyvsp = yyvs;
01032 
01033   goto yysetstate;
01034 
01035 /*------------------------------------------------------------.
01036 | yynewstate -- Push a new state, which is found in yystate.  |
01037 `------------------------------------------------------------*/
01038  yynewstate:
01039   /* In all cases, when you get here, the value and location stacks
01040      have just been pushed. so pushing a state here evens the stacks.
01041      */
01042   yyssp++;
01043 
01044  yysetstate:
01045   *yyssp = yystate;
01046 
01047   if (yyss + yystacksize - 1 <= yyssp)
01048     {
01049       /* Get the current used size of the three stacks, in elements.  */
01050       YYSIZE_T yysize = yyssp - yyss + 1;
01051 
01052 #ifdef yyoverflow
01053       {
01054         /* Give user a chance to reallocate the stack. Use copies of
01055            these so that the &'s don't force the real ones into
01056            memory.  */
01057         YYSTYPE *yyvs1 = yyvs;
01058         short *yyss1 = yyss;
01059 
01060 
01061         /* Each stack pointer address is followed by the size of the
01062            data in use in that stack, in bytes.  This used to be a
01063            conditional around just the two extra args, but that might
01064            be undefined if yyoverflow is a macro.  */
01065         yyoverflow ("parser stack overflow",
01066                     &yyss1, yysize * sizeof (*yyssp),
01067                     &yyvs1, yysize * sizeof (*yyvsp),
01068 
01069                     &yystacksize);
01070 
01071         yyss = yyss1;
01072         yyvs = yyvs1;
01073       }
01074 #else /* no yyoverflow */
01075 # ifndef YYSTACK_RELOCATE
01076       goto yyoverflowlab;
01077 # else
01078       /* Extend the stack our own way.  */
01079       if (YYMAXDEPTH <= yystacksize)
01080         goto yyoverflowlab;
01081       yystacksize *= 2;
01082       if (YYMAXDEPTH < yystacksize)
01083         yystacksize = YYMAXDEPTH;
01084 
01085       {
01086         short *yyss1 = yyss;
01087         union yyalloc *yyptr =
01088           (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
01089         if (! yyptr)
01090           goto yyoverflowlab;
01091         YYSTACK_RELOCATE (yyss);
01092         YYSTACK_RELOCATE (yyvs);
01093 
01094 #  undef YYSTACK_RELOCATE
01095         if (yyss1 != yyssa)
01096           YYSTACK_FREE (yyss1);
01097       }
01098 # endif
01099 #endif /* no yyoverflow */
01100 
01101       yyssp = yyss + yysize - 1;
01102       yyvsp = yyvs + yysize - 1;
01103 
01104 
01105       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
01106                   (unsigned long int) yystacksize));
01107 
01108       if (yyss + yystacksize - 1 <= yyssp)
01109         YYABORT;
01110     }
01111 
01112   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
01113 
01114   goto yybackup;
01115 
01116 /*-----------.
01117 | yybackup.  |
01118 `-----------*/
01119 yybackup:
01120 
01121 /* Do appropriate processing given the current state.  */
01122 /* Read a lookahead token if we need one and don't already have one.  */
01123 /* yyresume: */
01124 
01125   /* First try to decide what to do without reference to lookahead token.  */
01126 
01127   yyn = yypact[yystate];
01128   if (yyn == YYPACT_NINF)
01129     goto yydefault;
01130 
01131   /* Not known => get a lookahead token if don't already have one.  */
01132 
01133   /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
01134   if (yychar == YYEMPTY)
01135     {
01136       YYDPRINTF ((stderr, "Reading a token: "));
01137       yychar = YYLEX;
01138     }
01139 
01140   if (yychar <= YYEOF)
01141     {
01142       yychar = yytoken = YYEOF;
01143       YYDPRINTF ((stderr, "Now at end of input.\n"));
01144     }
01145   else
01146     {
01147       yytoken = YYTRANSLATE (yychar);
01148       YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
01149     }
01150 
01151   /* If the proper action on seeing token YYTOKEN is to reduce or to
01152      detect an error, take that action.  */
01153   yyn += yytoken;
01154   if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
01155     goto yydefault;
01156   yyn = yytable[yyn];
01157   if (yyn <= 0)
01158     {
01159       if (yyn == 0 || yyn == YYTABLE_NINF)
01160         goto yyerrlab;
01161       yyn = -yyn;
01162       goto yyreduce;
01163     }
01164 
01165   if (yyn == YYFINAL)
01166     YYACCEPT;
01167 
01168   /* Shift the lookahead token.  */
01169   YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
01170 
01171   /* Discard the token being shifted unless it is eof.  */
01172   if (yychar != YYEOF)
01173     yychar = YYEMPTY;
01174 
01175   *++yyvsp = yylval;
01176 
01177 
01178   /* Count tokens shifted since error; after three, turn off error
01179      status.  */
01180   if (yyerrstatus)
01181     yyerrstatus--;
01182 
01183   yystate = yyn;
01184   goto yynewstate;
01185 
01186 
01187 /*-----------------------------------------------------------.
01188 | yydefault -- do the default action for the current state.  |
01189 `-----------------------------------------------------------*/
01190 yydefault:
01191   yyn = yydefact[yystate];
01192   if (yyn == 0)
01193     goto yyerrlab;
01194   goto yyreduce;
01195 
01196 
01197 /*-----------------------------.
01198 | yyreduce -- Do a reduction.  |
01199 `-----------------------------*/
01200 yyreduce:
01201   /* yyn is the number of a rule to reduce with.  */
01202   yylen = yyr2[yyn];
01203 
01204   /* If YYLEN is nonzero, implement the default value of the action:
01205      `$$ = $1'.
01206 
01207      Otherwise, the following line sets YYVAL to garbage.
01208      This behavior is undocumented and Bison
01209      users should not rely upon it.  Assigning to YYVAL
01210      unconditionally makes the parser a bit smaller, and it avoids a
01211      GCC warning that YYVAL may be used uninitialized.  */
01212   yyval = yyvsp[1-yylen];
01213 
01214 
01215   YY_REDUCE_PRINT (yyn);
01216   switch (yyn)
01217     {
01218         case 4:
01219 #line 190 "getdate.y"
01220     { PC.times_seen++; }
01221     break;
01222 
01223   case 5:
01224 #line 192 "getdate.y"
01225     { PC.local_zones_seen++; }
01226     break;
01227 
01228   case 6:
01229 #line 194 "getdate.y"
01230     { PC.zones_seen++; }
01231     break;
01232 
01233   case 7:
01234 #line 196 "getdate.y"
01235     { PC.dates_seen++; }
01236     break;
01237 
01238   case 8:
01239 #line 198 "getdate.y"
01240     { PC.days_seen++; }
01241     break;
01242 
01243   case 9:
01244 #line 200 "getdate.y"
01245     { PC.rels_seen++; }
01246     break;
01247 
01248   case 11:
01249 #line 206 "getdate.y"
01250     {
01251         PC.hour = yyvsp[-1].textintval.value;
01252         PC.minutes = 0;
01253         PC.seconds = 0;
01254         PC.meridian = yyvsp[0].intval;
01255       }
01256     break;
01257 
01258   case 12:
01259 #line 213 "getdate.y"
01260     {
01261         PC.hour = yyvsp[-3].textintval.value;
01262         PC.minutes = yyvsp[-1].textintval.value;
01263         PC.seconds = 0;
01264         PC.meridian = yyvsp[0].intval;
01265       }
01266     break;
01267 
01268   case 13:
01269 #line 220 "getdate.y"
01270     {
01271         PC.hour = yyvsp[-3].textintval.value;
01272         PC.minutes = yyvsp[-1].textintval.value;
01273         PC.meridian = MER24;
01274         PC.zones_seen++;
01275         PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
01276       }
01277     break;
01278 
01279   case 14:
01280 #line 228 "getdate.y"
01281     {
01282         PC.hour = yyvsp[-5].textintval.value;
01283         PC.minutes = yyvsp[-3].textintval.value;
01284         PC.seconds = yyvsp[-1].textintval.value;
01285         PC.meridian = yyvsp[0].intval;
01286       }
01287     break;
01288 
01289   case 15:
01290 #line 235 "getdate.y"
01291     {
01292         PC.hour = yyvsp[-5].textintval.value;
01293         PC.minutes = yyvsp[-3].textintval.value;
01294         PC.seconds = yyvsp[-1].textintval.value;
01295         PC.meridian = MER24;
01296         PC.zones_seen++;
01297         PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
01298       }
01299     break;
01300 
01301   case 16:
01302 #line 247 "getdate.y"
01303     { PC.local_isdst = yyvsp[0].intval; }
01304     break;
01305 
01306   case 17:
01307 #line 249 "getdate.y"
01308     { PC.local_isdst = yyvsp[-1].intval < 0 ? 1 : yyvsp[-1].intval + 1; }
01309     break;
01310 
01311   case 18:
01312 #line 254 "getdate.y"
01313     { PC.time_zone = yyvsp[0].intval; }
01314     break;
01315 
01316   case 19:
01317 #line 256 "getdate.y"
01318     { PC.time_zone = yyvsp[0].intval + 60; }
01319     break;
01320 
01321   case 20:
01322 #line 258 "getdate.y"
01323     { PC.time_zone = yyvsp[-1].intval + 60; }
01324     break;
01325 
01326   case 21:
01327 #line 263 "getdate.y"
01328     {
01329         PC.day_ordinal = 1;
01330         PC.day_number = yyvsp[0].intval;
01331       }
01332     break;
01333 
01334   case 22:
01335 #line 268 "getdate.y"
01336     {
01337         PC.day_ordinal = 1;
01338         PC.day_number = yyvsp[-1].intval;
01339       }
01340     break;
01341 
01342   case 23:
01343 #line 273 "getdate.y"
01344     {
01345         PC.day_ordinal = yyvsp[-1].textintval.value;
01346         PC.day_number = yyvsp[0].intval;
01347       }
01348     break;
01349 
01350   case 24:
01351 #line 281 "getdate.y"
01352     {
01353         PC.month = yyvsp[-2].textintval.value;
01354         PC.day = yyvsp[0].textintval.value;
01355       }
01356     break;
01357 
01358   case 25:
01359 #line 286 "getdate.y"
01360     {
01361         /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
01362            otherwise as MM/DD/YY.
01363            The goal in recognizing YYYY/MM/DD is solely to support legacy
01364            machine-generated dates like those in an RCS log listing.  If
01365            you want portability, use the ISO 8601 format.  */
01366         if (4 <= yyvsp[-4].textintval.digits)
01367           {
01368             PC.year = yyvsp[-4].textintval;
01369             PC.month = yyvsp[-2].textintval.value;
01370             PC.day = yyvsp[0].textintval.value;
01371           }
01372         else
01373           {
01374             PC.month = yyvsp[-4].textintval.value;
01375             PC.day = yyvsp[-2].textintval.value;
01376             PC.year = yyvsp[0].textintval;
01377           }
01378       }
01379     break;
01380 
01381   case 26:
01382 #line 306 "getdate.y"
01383     {
01384         /* ISO 8601 format.  YYYY-MM-DD.  */
01385         PC.year = yyvsp[-2].textintval;
01386         PC.month = -yyvsp[-1].textintval.value;
01387         PC.day = -yyvsp[0].textintval.value;
01388       }
01389     break;
01390 
01391   case 27:
01392 #line 313 "getdate.y"
01393     {
01394         /* e.g. 17-JUN-1992.  */
01395         PC.day = yyvsp[-2].textintval.value;
01396         PC.month = yyvsp[-1].intval;
01397         PC.year.value = -yyvsp[0].textintval.value;
01398         PC.year.digits = yyvsp[0].textintval.digits;
01399       }
01400     break;
01401 
01402   case 28:
01403 #line 321 "getdate.y"
01404     {
01405         /* e.g. JUN-17-1992.  */
01406         PC.month = yyvsp[-2].intval;
01407         PC.day = -yyvsp[-1].textintval.value;
01408         PC.year.value = -yyvsp[0].textintval.value;
01409         PC.year.digits = yyvsp[0].textintval.digits;
01410       }
01411     break;
01412 
01413   case 29:
01414 #line 329 "getdate.y"
01415     {
01416         PC.month = yyvsp[-1].intval;
01417         PC.day = yyvsp[0].textintval.value;
01418       }
01419     break;
01420 
01421   case 30:
01422 #line 334 "getdate.y"
01423     {
01424         PC.month = yyvsp[-3].intval;
01425         PC.day = yyvsp[-2].textintval.value;
01426         PC.year = yyvsp[0].textintval;
01427       }
01428     break;
01429 
01430   case 31:
01431 #line 340 "getdate.y"
01432     {
01433         PC.day = yyvsp[-1].textintval.value;
01434         PC.month = yyvsp[0].intval;
01435       }
01436     break;
01437 
01438   case 32:
01439 #line 345 "getdate.y"
01440     {
01441         PC.day = yyvsp[-2].textintval.value;
01442         PC.month = yyvsp[-1].intval;
01443         PC.year = yyvsp[0].textintval;
01444       }
01445     break;
01446 
01447   case 33:
01448 #line 354 "getdate.y"
01449     {
01450         PC.rel_seconds = -PC.rel_seconds;
01451         PC.rel_minutes = -PC.rel_minutes;
01452         PC.rel_hour = -PC.rel_hour;
01453         PC.rel_day = -PC.rel_day;
01454         PC.rel_month = -PC.rel_month;
01455         PC.rel_year = -PC.rel_year;
01456       }
01457     break;
01458 
01459   case 35:
01460 #line 367 "getdate.y"
01461     { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01462     break;
01463 
01464   case 36:
01465 #line 369 "getdate.y"
01466     { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01467     break;
01468 
01469   case 37:
01470 #line 371 "getdate.y"
01471     { PC.rel_year += yyvsp[0].intval; }
01472     break;
01473 
01474   case 38:
01475 #line 373 "getdate.y"
01476     { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01477     break;
01478 
01479   case 39:
01480 #line 375 "getdate.y"
01481     { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01482     break;
01483 
01484   case 40:
01485 #line 377 "getdate.y"
01486     { PC.rel_month += yyvsp[0].intval; }
01487     break;
01488 
01489   case 41:
01490 #line 379 "getdate.y"
01491     { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01492     break;
01493 
01494   case 42:
01495 #line 381 "getdate.y"
01496     { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01497     break;
01498 
01499   case 43:
01500 #line 383 "getdate.y"
01501     { PC.rel_day += yyvsp[0].intval; }
01502     break;
01503 
01504   case 44:
01505 #line 385 "getdate.y"
01506     { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01507     break;
01508 
01509   case 45:
01510 #line 387 "getdate.y"
01511     { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01512     break;
01513 
01514   case 46:
01515 #line 389 "getdate.y"
01516     { PC.rel_hour += yyvsp[0].intval; }
01517     break;
01518 
01519   case 47:
01520 #line 391 "getdate.y"
01521     { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01522     break;
01523 
01524   case 48:
01525 #line 393 "getdate.y"
01526     { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01527     break;
01528 
01529   case 49:
01530 #line 395 "getdate.y"
01531     { PC.rel_minutes += yyvsp[0].intval; }
01532     break;
01533 
01534   case 50:
01535 #line 397 "getdate.y"
01536     { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01537     break;
01538 
01539   case 51:
01540 #line 399 "getdate.y"
01541     { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; }
01542     break;
01543 
01544   case 52:
01545 #line 401 "getdate.y"
01546     { PC.rel_seconds += yyvsp[0].intval; }
01547     break;
01548 
01549   case 53:
01550 #line 406 "getdate.y"
01551     {
01552         if (PC.dates_seen
01553             && ! PC.rels_seen && (PC.times_seen || 2 < yyvsp[0].textintval.digits))
01554           PC.year = yyvsp[0].textintval;
01555         else
01556           {
01557             if (4 < yyvsp[0].textintval.digits)
01558               {
01559                 PC.dates_seen++;
01560                 PC.day = yyvsp[0].textintval.value % 100;
01561                 PC.month = (yyvsp[0].textintval.value / 100) % 100;
01562                 PC.year.value = yyvsp[0].textintval.value / 10000;
01563                 PC.year.digits = yyvsp[0].textintval.digits - 4;
01564               }
01565             else
01566               {
01567                 PC.times_seen++;
01568                 if (yyvsp[0].textintval.digits <= 2)
01569                   {
01570                     PC.hour = yyvsp[0].textintval.value;
01571                     PC.minutes = 0;
01572                   }
01573                 else
01574                   {
01575                     PC.hour = yyvsp[0].textintval.value / 100;
01576                     PC.minutes = yyvsp[0].textintval.value % 100;
01577                   }
01578                 PC.seconds = 0;
01579                 PC.meridian = MER24;
01580               }
01581           }
01582       }
01583     break;
01584 
01585   case 54:
01586 #line 442 "getdate.y"
01587     { yyval.intval = MER24; }
01588     break;
01589 
01590   case 55:
01591 #line 444 "getdate.y"
01592     { yyval.intval = yyvsp[0].intval; }
01593     break;
01594 
01595 
01596     }
01597 
01598 /* Line 999 of yacc.c.  */
01599 #line 1600 "getdate.c"
01600 
01601   yyvsp -= yylen;
01602   yyssp -= yylen;
01603 
01604 
01605   YY_STACK_PRINT (yyss, yyssp);
01606 
01607   *++yyvsp = yyval;
01608 
01609 
01610   /* Now `shift' the result of the reduction.  Determine what state
01611      that goes to, based on the state we popped back to and the rule
01612      number reduced by.  */
01613 
01614   yyn = yyr1[yyn];
01615 
01616   yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
01617   if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
01618     yystate = yytable[yystate];
01619   else
01620     yystate = yydefgoto[yyn - YYNTOKENS];
01621 
01622   goto yynewstate;
01623 
01624 
01625 /*------------------------------------.
01626 | yyerrlab -- here on detecting error |
01627 `------------------------------------*/
01628 yyerrlab:
01629   /* If not already recovering from an error, report this error.  */
01630   if (!yyerrstatus)
01631     {
01632       ++yynerrs;
01633 #if YYERROR_VERBOSE
01634       yyn = yypact[yystate];
01635 
01636       if (YYPACT_NINF < yyn && yyn < YYLAST)
01637         {
01638           YYSIZE_T yysize = 0;
01639           int yytype = YYTRANSLATE (yychar);
01640           const char* yyprefix;
01641           char *yymsg;
01642           int yyx;
01643 
01644           /* Start YYX at -YYN if negative to avoid negative indexes in
01645              YYCHECK.  */
01646           int yyxbegin = yyn < 0 ? -yyn : 0;
01647 
01648           /* Stay within bounds of both yycheck and yytname.  */
01649           int yychecklim = YYLAST - yyn;
01650           int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
01651           int yycount = 0;
01652 
01653           yyprefix = ", expecting ";
01654           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
01655             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
01656               {
01657                 yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
01658                 yycount += 1;
01659                 if (yycount == 5)
01660                   {
01661                     yysize = 0;
01662                     break;
01663                   }
01664               }
01665           yysize += (sizeof ("syntax error, unexpected ")
01666                      + yystrlen (yytname[yytype]));
01667           yymsg = (char *) YYSTACK_ALLOC (yysize);
01668           if (yymsg != 0)
01669             {
01670               char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
01671               yyp = yystpcpy (yyp, yytname[yytype]);
01672 
01673               if (yycount < 5)
01674                 {
01675                   yyprefix = ", expecting ";
01676                   for (yyx = yyxbegin; yyx < yyxend; ++yyx)
01677                     if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
01678                       {
01679                         yyp = yystpcpy (yyp, yyprefix);
01680                         yyp = yystpcpy (yyp, yytname[yyx]);
01681                         yyprefix = " or ";
01682                       }
01683                 }
01684               yyerror (yymsg);
01685               YYSTACK_FREE (yymsg);
01686             }
01687           else
01688             yyerror ("syntax error; also virtual memory exhausted");
01689         }
01690       else
01691 #endif /* YYERROR_VERBOSE */
01692         yyerror ("syntax error");
01693     }
01694 
01695 
01696 
01697   if (yyerrstatus == 3)
01698     {
01699       /* If just tried and failed to reuse lookahead token after an
01700          error, discard it.  */
01701 
01702       /* Return failure if at end of input.  */
01703       if (yychar == YYEOF)
01704         {
01705           /* Pop the error token.  */
01706           YYPOPSTACK;
01707           /* Pop the rest of the stack.  */
01708           while (yyss < yyssp)
01709             {
01710               YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
01711               yydestruct (yystos[*yyssp], yyvsp);
01712               YYPOPSTACK;
01713             }
01714           YYABORT;
01715         }
01716 
01717       YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
01718       yydestruct (yytoken, &yylval);
01719       yychar = YYEMPTY;
01720 
01721     }
01722 
01723   /* Else will try to reuse lookahead token after shifting the error
01724      token.  */
01725   goto yyerrlab1;
01726 
01727 
01728 /*----------------------------------------------------.
01729 | yyerrlab1 -- error raised explicitly by an action.  |
01730 `----------------------------------------------------*/
01731 yyerrlab1:
01732   yyerrstatus = 3;      /* Each real token shifted decrements this.  */
01733 
01734   for (;;)
01735     {
01736       yyn = yypact[yystate];
01737       if (yyn != YYPACT_NINF)
01738         {
01739           yyn += YYTERROR;
01740           if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
01741             {
01742               yyn = yytable[yyn];
01743               if (0 < yyn)
01744                 break;
01745             }
01746         }
01747 
01748       /* Pop the current state because it cannot handle the error token.  */
01749       if (yyssp == yyss)
01750         YYABORT;
01751 
01752       YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
01753       yydestruct (yystos[yystate], yyvsp);
01754       yyvsp--;
01755       yystate = *--yyssp;
01756 
01757       YY_STACK_PRINT (yyss, yyssp);
01758     }
01759 
01760   if (yyn == YYFINAL)
01761     YYACCEPT;
01762 
01763   YYDPRINTF ((stderr, "Shifting error token, "));
01764 
01765   *++yyvsp = yylval;
01766 
01767 
01768   yystate = yyn;
01769   goto yynewstate;
01770 
01771 
01772 /*-------------------------------------.
01773 | yyacceptlab -- YYACCEPT comes here.  |
01774 `-------------------------------------*/
01775 yyacceptlab:
01776   yyresult = 0;
01777   goto yyreturn;
01778 
01779 /*-----------------------------------.
01780 | yyabortlab -- YYABORT comes here.  |
01781 `-----------------------------------*/
01782 yyabortlab:
01783   yyresult = 1;
01784   goto yyreturn;
01785 
01786 #ifndef yyoverflow
01787 /*----------------------------------------------.
01788 | yyoverflowlab -- parser overflow comes here.  |
01789 `----------------------------------------------*/
01790 yyoverflowlab:
01791   yyerror ("parser stack overflow");
01792   yyresult = 2;
01793   /* Fall through.  */
01794 #endif
01795 
01796 yyreturn:
01797 #ifndef yyoverflow
01798   if (yyss != yyssa)
01799     YYSTACK_FREE (yyss);
01800 #endif
01801   return yyresult;
01802 }
01803 
01804 
01805 #line 447 "getdate.y"
01806 
01807 
01808 /* Include this file down here because bison inserts code above which
01809    may define-away `const'.  We want the prototype for get_date to have
01810    the same signature as the function definition.  */
01811 #include "getdate.h"
01812 //#include "unlocked-io.h"
01813 
01814 #ifndef gmtime
01815 struct tm *gmtime ();
01816 #endif
01817 #ifndef localtime
01818 struct tm *localtime ();
01819 #endif
01820 #ifndef mktime
01821 time_t mktime ();
01822 #endif
01823 
01824 static table const meridian_table[] =
01825 {
01826   { "AM",   tMERIDIAN, MERam },
01827   { "A.M.", tMERIDIAN, MERam },
01828   { "PM",   tMERIDIAN, MERpm },
01829   { "P.M.", tMERIDIAN, MERpm },
01830   { 0, 0, 0 }
01831 };
01832 
01833 static table const dst_table[] =
01834 {
01835   { "DST", tDST, 0 }
01836 };
01837 
01838 static table const month_and_day_table[] =
01839 {
01840   { "JANUARY",  tMONTH,  1 },
01841   { "FEBRUARY", tMONTH,  2 },
01842   { "MARCH",    tMONTH,  3 },
01843   { "APRIL",    tMONTH,  4 },
01844   { "MAY",      tMONTH,  5 },
01845   { "JUNE",     tMONTH,  6 },
01846   { "JULY",     tMONTH,  7 },
01847   { "AUGUST",   tMONTH,  8 },
01848   { "SEPTEMBER",tMONTH,  9 },
01849   { "SEPT",     tMONTH,  9 },
01850   { "OCTOBER",  tMONTH, 10 },
01851   { "NOVEMBER", tMONTH, 11 },
01852   { "DECEMBER", tMONTH, 12 },
01853   { "SUNDAY",   tDAY,    0 },
01854   { "MONDAY",   tDAY,    1 },
01855   { "TUESDAY",  tDAY,    2 },
01856   { "TUES",     tDAY,    2 },
01857   { "WEDNESDAY",tDAY,    3 },
01858   { "WEDNES",   tDAY,    3 },
01859   { "THURSDAY", tDAY,    4 },
01860   { "THUR",     tDAY,    4 },
01861   { "THURS",    tDAY,    4 },
01862   { "FRIDAY",   tDAY,    5 },
01863   { "SATURDAY", tDAY,    6 },
01864   { 0, 0, 0 }
01865 };
01866 
01867 static table const time_units_table[] =
01868 {
01869   { "YEAR",     tYEAR_UNIT,      1 },
01870   { "MONTH",    tMONTH_UNIT,     1 },
01871   { "FORTNIGHT",tDAY_UNIT,      14 },
01872   { "WEEK",     tDAY_UNIT,       7 },
01873   { "DAY",      tDAY_UNIT,       1 },
01874   { "HOUR",     tHOUR_UNIT,      1 },
01875   { "MINUTE",   tMINUTE_UNIT,    1 },
01876   { "MIN",      tMINUTE_UNIT,    1 },
01877   { "SECOND",   tSEC_UNIT,       1 },
01878   { "SEC",      tSEC_UNIT,       1 },
01879   { 0, 0, 0 }
01880 };
01881 
01882 /* Assorted relative-time words. */
01883 static table const relative_time_table[] =
01884 {
01885   { "TOMORROW", tDAY_UNIT,       1 },
01886   { "YESTERDAY",tDAY_UNIT,      -1 },
01887   { "TODAY",    tDAY_UNIT,       0 },
01888   { "NOW",      tDAY_UNIT,       0 },
01889   { "LAST",     tUNUMBER,       -1 },
01890   { "THIS",     tUNUMBER,        0 },
01891   { "NEXT",     tUNUMBER,        1 },
01892   { "FIRST",    tUNUMBER,        1 },
01893 /*{ "SECOND",   tUNUMBER,        2 }, */
01894   { "THIRD",    tUNUMBER,        3 },
01895   { "FOURTH",   tUNUMBER,        4 },
01896   { "FIFTH",    tUNUMBER,        5 },
01897   { "SIXTH",    tUNUMBER,        6 },
01898   { "SEVENTH",  tUNUMBER,        7 },
01899   { "EIGHTH",   tUNUMBER,        8 },
01900   { "NINTH",    tUNUMBER,        9 },
01901   { "TENTH",    tUNUMBER,       10 },
01902   { "ELEVENTH", tUNUMBER,       11 },
01903   { "TWELFTH",  tUNUMBER,       12 },
01904   { "AGO",      tAGO,            1 },
01905   { 0, 0, 0 }
01906 };
01907 
01908 /* The time zone table.  This table is necessarily incomplete, as time
01909    zone abbreviations are ambiguous; e.g. Australians interpret "EST"
01910    as Eastern time in Australia, not as US Eastern Standard Time.
01911    You cannot rely on getdate to handle arbitrary time zone
01912    abbreviations; use numeric abbreviations like `-0500' instead.  */
01913 static table const time_zone_table[] =
01914 {
01915   { "GMT",      tZONE,     HOUR ( 0) }, /* Greenwich Mean */
01916   { "UT",       tZONE,     HOUR ( 0) }, /* Universal (Coordinated) */
01917   { "UTC",      tZONE,     HOUR ( 0) },
01918   { "WET",      tZONE,     HOUR ( 0) }, /* Western European */
01919   { "WEST",     tDAYZONE,  HOUR ( 0) }, /* Western European Summer */
01920   { "BST",      tDAYZONE,  HOUR ( 0) }, /* British Summer */
01921   { "ART",      tZONE,    -HOUR ( 3) }, /* Argentina */
01922   { "BRT",      tZONE,    -HOUR ( 3) }, /* Brazil */
01923   { "BRST",     tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
01924   { "NST",      tZONE,   -(HOUR ( 3) + 30) },   /* Newfoundland Standard */
01925   { "NDT",      tDAYZONE,-(HOUR ( 3) + 30) },   /* Newfoundland Daylight */
01926   { "AST",      tZONE,    -HOUR ( 4) }, /* Atlantic Standard */
01927   { "ADT",      tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
01928   { "CLT",      tZONE,    -HOUR ( 4) }, /* Chile */
01929   { "CLST",     tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
01930   { "EST",      tZONE,    -HOUR ( 5) }, /* Eastern Standard */
01931   { "EDT",      tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
01932   { "CST",      tZONE,    -HOUR ( 6) }, /* Central Standard */
01933   { "CDT",      tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
01934   { "MST",      tZONE,    -HOUR ( 7) }, /* Mountain Standard */
01935   { "MDT",      tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
01936   { "PST",      tZONE,    -HOUR ( 8) }, /* Pacific Standard */
01937   { "PDT",      tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
01938   { "AKST",     tZONE,    -HOUR ( 9) }, /* Alaska Standard */
01939   { "AKDT",     tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
01940   { "HST",      tZONE,    -HOUR (10) }, /* Hawaii Standard */
01941   { "HAST",     tZONE,    -HOUR (10) }, /* Hawaii-Aleutian Standard */
01942   { "HADT",     tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
01943   { "SST",      tZONE,    -HOUR (12) }, /* Samoa Standard */
01944   { "WAT",      tZONE,     HOUR ( 1) }, /* West Africa */
01945   { "CET",      tZONE,     HOUR ( 1) }, /* Central European */
01946   { "CEST",     tDAYZONE,  HOUR ( 1) }, /* Central European Summer */
01947   { "MET",      tZONE,     HOUR ( 1) }, /* Middle European */
01948   { "MEZ",      tZONE,     HOUR ( 1) }, /* Middle European */
01949   { "MEST",     tDAYZONE,  HOUR ( 1) }, /* Middle European Summer */
01950   { "MESZ",     tDAYZONE,  HOUR ( 1) }, /* Middle European Summer */
01951   { "EET",      tZONE,     HOUR ( 2) }, /* Eastern European */
01952   { "EEST",     tDAYZONE,  HOUR ( 2) }, /* Eastern European Summer */
01953   { "CAT",      tZONE,     HOUR ( 2) }, /* Central Africa */
01954   { "SAST",     tZONE,     HOUR ( 2) }, /* South Africa Standard */
01955   { "EAT",      tZONE,     HOUR ( 3) }, /* East Africa */
01956   { "MSK",      tZONE,     HOUR ( 3) }, /* Moscow */
01957   { "MSD",      tDAYZONE,  HOUR ( 3) }, /* Moscow Daylight */
01958   { "IST",      tZONE,    (HOUR ( 5) + 30) },   /* India Standard */
01959   { "SGT",      tZONE,     HOUR ( 8) }, /* Singapore */
01960   { "KST",      tZONE,     HOUR ( 9) }, /* Korea Standard */
01961   { "JST",      tZONE,     HOUR ( 9) }, /* Japan Standard */
01962   { "GST",      tZONE,     HOUR (10) }, /* Guam Standard */
01963   { "NZST",     tZONE,     HOUR (12) }, /* New Zealand Standard */
01964   { "NZDT",     tDAYZONE,  HOUR (12) }, /* New Zealand Daylight */
01965   { 0, 0, 0  }
01966 };
01967 
01968 /* Military time zone table. */
01969 static table const military_table[] =
01970 {
01971   { "A", tZONE, -HOUR ( 1) },
01972   { "B", tZONE, -HOUR ( 2) },
01973   { "C", tZONE, -HOUR ( 3) },
01974   { "D", tZONE, -HOUR ( 4) },
01975   { "E", tZONE, -HOUR ( 5) },
01976   { "F", tZONE, -HOUR ( 6) },
01977   { "G", tZONE, -HOUR ( 7) },
01978   { "H", tZONE, -HOUR ( 8) },
01979   { "I", tZONE, -HOUR ( 9) },
01980   { "K", tZONE, -HOUR (10) },
01981   { "L", tZONE, -HOUR (11) },
01982   { "M", tZONE, -HOUR (12) },
01983   { "N", tZONE,  HOUR ( 1) },
01984   { "O", tZONE,  HOUR ( 2) },
01985   { "P", tZONE,  HOUR ( 3) },
01986   { "Q", tZONE,  HOUR ( 4) },
01987   { "R", tZONE,  HOUR ( 5) },
01988   { "S", tZONE,  HOUR ( 6) },
01989   { "T", tZONE,  HOUR ( 7) },
01990   { "U", tZONE,  HOUR ( 8) },
01991   { "V", tZONE,  HOUR ( 9) },
01992   { "W", tZONE,  HOUR (10) },
01993   { "X", tZONE,  HOUR (11) },
01994   { "Y", tZONE,  HOUR (12) },
01995   { "Z", tZONE,  HOUR ( 0) },
01996   { 0, 0, 0 }
01997 };
01998 
01999 
02000 
02001 static int
02002 to_hour (int hours, int meridian)
02003 {
02004   switch (meridian)
02005     {
02006     case MER24:
02007       return 0 <= hours && hours < 24 ? hours : -1;
02008     case MERam:
02009       return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
02010     case MERpm:
02011       return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
02012     default:
02013       abort ();
02014     }
02015   /* NOTREACHED */
02016 }
02017 
02018 static int
02019 to_year (textint textyear)
02020 {
02021   int year = textyear.value;
02022 
02023   if (year < 0)
02024     year = -year;
02025 
02026   /* XPG4 suggests that years 00-68 map to 2000-2068, and
02027      years 69-99 map to 1969-1999.  */
02028   if (textyear.digits == 2)
02029     year += year < 69 ? 2000 : 1900;
02030 
02031   return year;
02032 }
02033 
02034 static table const *
02035 lookup_zone (parser_control const *pc, char const *name)
02036 {
02037   table const *tp;
02038 
02039   /* Try local zone abbreviations first; they're more likely to be right.  */
02040   for (tp = pc->local_time_zone_table; tp->name; tp++)
02041     if (strcmp (name, tp->name) == 0)
02042       return tp;
02043 
02044   for (tp = time_zone_table; tp->name; tp++)
02045     if (strcmp (name, tp->name) == 0)
02046       return tp;
02047 
02048   return 0;
02049 }
02050 
02051 #if ! HAVE_TM_GMTOFF
02052 /* Yield the difference between *A and *B,
02053    measured in seconds, ignoring leap seconds.
02054    The body of this function is taken directly from the GNU C Library;
02055    see src/strftime.c.  */
02056 static int
02057 tm_diff (struct tm const *a, struct tm const *b)
02058 {
02059   /* Compute intervening leap days correctly even if year is negative.
02060      Take care to avoid int overflow in leap day calculations,
02061      but it's OK to assume that A and B are close to each other.  */
02062   int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
02063   int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
02064   int a100 = a4 / 25 - (a4 % 25 < 0);
02065   int b100 = b4 / 25 - (b4 % 25 < 0);
02066   int a400 = a100 >> 2;
02067   int b400 = b100 >> 2;
02068   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
02069   int years = a->tm_year - b->tm_year;
02070   int days = (365 * years + intervening_leap_days
02071               + (a->tm_yday - b->tm_yday));
02072   return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
02073                 + (a->tm_min - b->tm_min))
02074           + (a->tm_sec - b->tm_sec));
02075 }
02076 #endif /* ! HAVE_TM_GMTOFF */
02077 
02078 static table const *
02079 lookup_word (parser_control const *pc, char *word)
02080 {
02081   char *p;
02082   char *q;
02083   size_t wordlen;
02084   table const *tp;
02085   int i;
02086   int abbrev;
02087 
02088   /* Make it uppercase.  */
02089   for (p = word; *p; p++)
02090     if (ISLOWER ((unsigned char) *p))
02091       *p = toupper ((unsigned char) *p);
02092 
02093   for (tp = meridian_table; tp->name; tp++)
02094     if (strcmp (word, tp->name) == 0)
02095       return tp;
02096 
02097   /* See if we have an abbreviation for a month. */
02098   wordlen = strlen (word);
02099   abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
02100 
02101   for (tp = month_and_day_table; tp->name; tp++)
02102     if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
02103       return tp;
02104 
02105   if ((tp = lookup_zone (pc, word)))
02106     return tp;
02107 
02108   if (strcmp (word, dst_table[0].name) == 0)
02109     return dst_table;
02110 
02111   for (tp = time_units_table; tp->name; tp++)
02112     if (strcmp (word, tp->name) == 0)
02113       return tp;
02114 
02115   /* Strip off any plural and try the units table again. */
02116   if (word[wordlen - 1] == 'S')
02117     {
02118       word[wordlen - 1] = '\0';
02119       for (tp = time_units_table; tp->name; tp++)
02120         if (strcmp (word, tp->name) == 0)
02121           return tp;
02122       word[wordlen - 1] = 'S';  /* For "this" in relative_time_table.  */
02123     }
02124 
02125   for (tp = relative_time_table; tp->name; tp++)
02126     if (strcmp (word, tp->name) == 0)
02127       return tp;
02128 
02129   /* Military time zones. */
02130   if (wordlen == 1)
02131     for (tp = military_table; tp->name; tp++)
02132       if (word[0] == tp->name[0])
02133         return tp;
02134 
02135   /* Drop out any periods and try the time zone table again. */
02136   for (i = 0, p = q = word; (*p = *q); q++)
02137     if (*q == '.')
02138       i = 1;
02139     else
02140       p++;
02141   if (i && (tp = lookup_zone (pc, word)))
02142     return tp;
02143 
02144   return 0;
02145 }
02146 
02147 static int
02148 yylex (YYSTYPE *lvalp, parser_control *pc)
02149 {
02150   unsigned char c;
02151   int count;
02152 
02153   for (;;)
02154     {
02155       while (c = *pc->input, ISSPACE (c))
02156         pc->input++;
02157 
02158       if (ISDIGIT (c) || c == '-' || c == '+')
02159         {
02160           char const *p;
02161           int sign;
02162           int value;
02163           if (c == '-' || c == '+')
02164             {
02165               sign = c == '-' ? -1 : 1;
02166               c = *++pc->input;
02167               if (! ISDIGIT (c))
02168                 /* skip the '-' sign */
02169                 continue;
02170             }
02171           else
02172             sign = 0;
02173           p = pc->input;
02174           value = 0;
02175           do
02176             {
02177               value = 10 * value + c - '0';
02178               c = *++p;
02179             }
02180           while (ISDIGIT (c));
02181           lvalp->textintval.value = sign < 0 ? -value : value;
02182           lvalp->textintval.digits = p - pc->input;
02183           pc->input = p;
02184           return sign ? tSNUMBER : tUNUMBER;
02185         }
02186 
02187       if (ISALPHA (c))
02188         {
02189           char buff[20];
02190           char *p = buff;
02191           table const *tp;
02192 
02193           do
02194             {
02195               if (p < buff + sizeof buff - 1)
02196                 *p++ = c;
02197               c = *++pc->input;
02198             }
02199           while (ISALPHA (c) || c == '.');
02200 
02201           *p = '\0';
02202           tp = lookup_word (pc, buff);
02203           if (! tp)
02204             return '?';
02205           lvalp->intval = tp->value;
02206           return tp->type;
02207         }
02208 
02209       if (c != '(')
02210         return *pc->input++;
02211       count = 0;
02212       do
02213         {
02214           c = *pc->input++;
02215           if (c == '\0')
02216             return c;
02217           if (c == '(')
02218             count++;
02219           else if (c == ')')
02220             count--;
02221         }
02222       while (count > 0);
02223     }
02224 }
02225 
02226 /* Do nothing if the parser reports an error.  */
02227 static int
02228 yyerror (char *s ATTRIBUTE_UNUSED)
02229 {
02230   return 0;
02231 }
02232 
02233 /* Parse a date/time string P.  Return the corresponding time_t value,
02234    or (time_t) -1 if there is an error.  P can be an incomplete or
02235    relative time specification; if so, use *NOW as the basis for the
02236    returned time.  */
02237 time_t
02238 get_date (const char *p, const time_t *now)
02239 {
02240   time_t Start = now ? *now : time (0);
02241   struct tm *tmp = localtime (&Start);
02242   struct tm tm;
02243   struct tm tm0;
02244   parser_control pc;
02245 
02246   if (! tmp)
02247     return -1;
02248 
02249   pc.input = p;
02250   pc.year.value = tmp->tm_year + TM_YEAR_BASE;
02251   pc.year.digits = 4;
02252   pc.month = tmp->tm_mon + 1;
02253   pc.day = tmp->tm_mday;
02254   pc.hour = tmp->tm_hour;
02255   pc.minutes = tmp->tm_min;
02256   pc.seconds = tmp->tm_sec;
02257   tm.tm_isdst = tmp->tm_isdst;
02258 
02259   pc.meridian = MER24;
02260   pc.rel_seconds = 0;
02261   pc.rel_minutes = 0;
02262   pc.rel_hour = 0;
02263   pc.rel_day = 0;
02264   pc.rel_month = 0;
02265   pc.rel_year = 0;
02266   pc.dates_seen = 0;
02267   pc.days_seen = 0;
02268   pc.rels_seen = 0;
02269   pc.times_seen = 0;
02270   pc.local_zones_seen = 0;
02271   pc.zones_seen = 0;
02272 
02273 #if HAVE_STRUCT_TM_TM_ZONE
02274   pc.local_time_zone_table[0].name = tmp->tm_zone;
02275   pc.local_time_zone_table[0].type = tLOCAL_ZONE;
02276   pc.local_time_zone_table[0].value = tmp->tm_isdst;
02277   pc.local_time_zone_table[1].name = 0;
02278 
02279   /* Probe the names used in the next three calendar quarters, looking
02280      for a tm_isdst different from the one we already have.  */
02281   {
02282     int quarter;
02283     for (quarter = 1; quarter <= 3; quarter++)
02284       {
02285         time_t probe = Start + quarter * (90 * 24 * 60 * 60);
02286         struct tm *probe_tm = localtime (&probe);
02287         if (probe_tm && probe_tm->tm_zone
02288             && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
02289           {
02290               {
02291                 pc.local_time_zone_table[1].name = probe_tm->tm_zone;
02292                 pc.local_time_zone_table[1].type = tLOCAL_ZONE;
02293                 pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
02294                 pc.local_time_zone_table[2].name = 0;
02295               }
02296             break;
02297           }
02298       }
02299   }
02300 #else
02301 #if HAVE_TZNAME
02302   {
02303 # ifndef tzname
02304     extern char *tzname[];
02305 # endif
02306     int i;
02307     for (i = 0; i < 2; i++)
02308       {
02309         pc.local_time_zone_table[i].name = tzname[i];
02310         pc.local_time_zone_table[i].type = tLOCAL_ZONE;
02311         pc.local_time_zone_table[i].value = i;
02312       }
02313     pc.local_time_zone_table[i].name = 0;
02314   }
02315 #else
02316   pc.local_time_zone_table[0].name = 0;
02317 #endif
02318 #endif
02319 
02320   if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
02321       && ! strcmp (pc.local_time_zone_table[0].name,
02322                    pc.local_time_zone_table[1].name))
02323     {
02324       /* This locale uses the same abbrevation for standard and
02325          daylight times.  So if we see that abbreviation, we don't
02326          know whether it's daylight time.  */
02327       pc.local_time_zone_table[0].value = -1;
02328       pc.local_time_zone_table[1].name = 0;
02329     }
02330 
02331   if (yyparse (&pc) != 0
02332       || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen
02333       || 1 < (pc.local_zones_seen + pc.zones_seen)
02334       || (pc.local_zones_seen && 1 < pc.local_isdst))
02335     return -1;
02336 
02337   tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year;
02338   tm.tm_mon = pc.month - 1 + pc.rel_month;
02339   tm.tm_mday = pc.day + pc.rel_day;
02340   if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
02341     {
02342       tm.tm_hour = to_hour (pc.hour, pc.meridian);
02343       if (tm.tm_hour < 0)
02344         return -1;
02345       tm.tm_min = pc.minutes;
02346       tm.tm_sec = pc.seconds;
02347     }
02348   else
02349     {
02350       tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
02351     }
02352 
02353   /* Let mktime deduce tm_isdst if we have an absolute time stamp,
02354      or if the relative time stamp mentions days, months, or years.  */
02355   if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day
02356       | pc.rel_month | pc.rel_year)
02357     tm.tm_isdst = -1;
02358 
02359   /* But if the input explicitly specifies local time with or without
02360      DST, give mktime that information.  */
02361   if (pc.local_zones_seen)
02362     tm.tm_isdst = pc.local_isdst;
02363 
02364   tm0 = tm;
02365 
02366   Start = mktime (&tm);
02367 
02368   if (Start == (time_t) -1)
02369     {
02370 
02371       /* Guard against falsely reporting errors near the time_t boundaries
02372          when parsing times in other time zones.  For example, if the min
02373          time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
02374          of UTC, then the min localtime value is 1970-01-01 08:00:00; if
02375          we apply mktime to 1970-01-01 00:00:00 we will get an error, so
02376          we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
02377          zone by 24 hours to compensate.  This algorithm assumes that
02378          there is no DST transition within a day of the time_t boundaries.  */
02379       if (pc.zones_seen)
02380         {
02381           tm = tm0;
02382           if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)
02383             {
02384               tm.tm_mday++;
02385               pc.time_zone += 24 * 60;
02386             }
02387           else
02388             {
02389               tm.tm_mday--;
02390               pc.time_zone -= 24 * 60;
02391             }
02392           Start = mktime (&tm);
02393         }
02394 
02395       if (Start == (time_t) -1)
02396         return Start;
02397     }
02398 
02399   if (pc.days_seen && ! pc.dates_seen)
02400     {
02401       tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
02402                      + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
02403       tm.tm_isdst = -1;
02404       Start = mktime (&tm);
02405       if (Start == (time_t) -1)
02406         return Start;
02407     }
02408 
02409   if (pc.zones_seen)
02410     {
02411       int delta = pc.time_zone * 60;
02412 #ifdef HAVE_TM_GMTOFF
02413       delta -= tm.tm_gmtoff;
02414 #else
02415       struct tm *gmt = gmtime (&Start);
02416       if (! gmt)
02417         return -1;
02418       delta -= tm_diff (&tm, gmt);
02419 #endif
02420       if ((Start < Start - delta) != (delta < 0))
02421         return -1;      /* time_t overflow */
02422       Start -= delta;
02423     }
02424 
02425   /* Add relative hours, minutes, and seconds.  Ignore leap seconds;
02426      i.e. "+ 10 minutes" means 600 seconds, even if one of them is a
02427      leap second.  Typically this is not what the user wants, but it's
02428      too hard to do it the other way, because the time zone indicator
02429      must be applied before relative times, and if mktime is applied
02430      again the time zone will be lost.  */
02431   {
02432     time_t t0 = Start;
02433     long d1 = 60 * 60 * (long) pc.rel_hour;
02434     time_t t1 = t0 + d1;
02435     long d2 = 60 * (long) pc.rel_minutes;
02436     time_t t2 = t1 + d2;
02437     int d3 = pc.rel_seconds;
02438     time_t t3 = t2 + d3;
02439     if ((d1 / (60 * 60) ^ pc.rel_hour)
02440         | (d2 / 60 ^ pc.rel_minutes)
02441         | ((t0 + d1 < t0) ^ (d1 < 0))
02442         | ((t1 + d2 < t1) ^ (d2 < 0))
02443         | ((t2 + d3 < t2) ^ (d3 < 0)))
02444       return -1;
02445     Start = t3;
02446   }
02447 
02448   return Start;
02449 }
02450 
02451 #if TEST
02452 
02453 #include <stdio.h>
02454 
02455 int
02456 main (int ac, char **av)
02457 {
02458   char buff[BUFSIZ];
02459   time_t d;
02460 
02461   printf ("Enter date, or blank line to exit.\n\t> ");
02462   fflush (stdout);
02463 
02464   buff[BUFSIZ - 1] = 0;
02465   while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
02466     {
02467       d = get_date (buff, 0);
02468       if (d == (time_t) -1)
02469         printf ("Bad format - couldn't convert.\n");
02470       else
02471         printf ("%s", ctime (&d));
02472       printf ("\t> ");
02473       fflush (stdout);
02474     }
02475   return 0;
02476 }
02477 #endif /* defined TEST */
02478 
02479 

Generated on Mon May 19 15:36:55 2008 for lpbot by  doxygen 1.5.4