source: branches/samba-3.0/source/modules/getdate.c@ 315

Last change on this file since 315 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 63.9 KB
Line 
1/* A Bison parser, made by GNU Bison 1.875a. */
2
3/* Skeleton parser for Yacc-like parsing with Bison,
4 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21/* As a special exception, when this file is copied by Bison into a
22 Bison output file, you may use that output file without restriction.
23 This special exception was added by the Free Software Foundation
24 in version 1.24 of Bison. */
25
26/* Written by Richard Stallman by simplifying the original so called
27 ``semantic'' parser. */
28
29/* All symbols defined below should begin with yy or YY, to avoid
30 infringing on user name space. This should be done even for local
31 variables, as they might otherwise be expanded by user macros.
32 There are some unavoidable exceptions within include files to
33 define necessary library symbols; they are noted "INFRINGES ON
34 USER NAME SPACE" below. */
35
36/* Identify Bison output. */
37#define YYBISON 1
38
39/* Skeleton name. */
40#define YYSKELETON_NAME "yacc.c"
41
42/* Pure parsers. */
43#define YYPURE 1
44
45/* Using locations. */
46#define YYLSP_NEEDED 0
47
48
49
50/* Tokens. */
51#ifndef YYTOKENTYPE
52# define YYTOKENTYPE
53 /* Put the tokens into the symbol table, so that GDB and other debuggers
54 know about them. */
55 enum yytokentype {
56 tAGO = 258,
57 tDST = 259,
58 tDAY = 260,
59 tDAY_UNIT = 261,
60 tDAYZONE = 262,
61 tHOUR_UNIT = 263,
62 tLOCAL_ZONE = 264,
63 tMERIDIAN = 265,
64 tMINUTE_UNIT = 266,
65 tMONTH = 267,
66 tMONTH_UNIT = 268,
67 tSEC_UNIT = 269,
68 tYEAR_UNIT = 270,
69 tZONE = 271,
70 tSNUMBER = 272,
71 tUNUMBER = 273
72 };
73#endif
74#define tAGO 258
75#define tDST 259
76#define tDAY 260
77#define tDAY_UNIT 261
78#define tDAYZONE 262
79#define tHOUR_UNIT 263
80#define tLOCAL_ZONE 264
81#define tMERIDIAN 265
82#define tMINUTE_UNIT 266
83#define tMONTH 267
84#define tMONTH_UNIT 268
85#define tSEC_UNIT 269
86#define tYEAR_UNIT 270
87#define tZONE 271
88#define tSNUMBER 272
89#define tUNUMBER 273
90
91
92
93
94/* Copy the first part of user declarations. */
95#line 1 "getdate.y"
96
97/* Parse a string into an internal time stamp.
98 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
99
100 This program is free software; you can redistribute it and/or modify
101 it under the terms of the GNU General Public License as published by
102 the Free Software Foundation; either version 2, or (at your option)
103 any later version.
104
105 This program is distributed in the hope that it will be useful,
106 but WITHOUT ANY WARRANTY; without even the implied warranty of
107 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
108 GNU General Public License for more details.
109
110 You should have received a copy of the GNU General Public License
111 along with this program; if not, write to the Free Software Foundation,
112 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
113
114/* Originally written by Steven M. Bellovin <smb@research.att.com> while
115 at the University of North Carolina at Chapel Hill. Later tweaked by
116 a couple of people on Usenet. Completely overhauled by Rich $alz
117 <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
118
119 Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
120 the right thing about local DST. Unlike previous versions, this
121 version is reentrant. */
122
123#ifdef HAVE_CONFIG_H
124# include <config.h>
125# ifdef HAVE_ALLOCA_H
126# include <alloca.h>
127# endif
128#endif
129
130/* Since the code of getdate.y is not included in the Emacs executable
131 itself, there is no need to #define static in this file. Even if
132 the code were included in the Emacs executable, it probably
133 wouldn't do any harm to #undef it here; this will only cause
134 problems if we try to write to a static variable, which I don't
135 think this code needs to do. */
136#ifdef emacs
137# undef static
138#endif
139
140#include <ctype.h>
141#include <string.h>
142
143#if HAVE_STDLIB_H
144# include <stdlib.h> /* for `free'; used by Bison 1.27 */
145#endif
146
147#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
148# define IN_CTYPE_DOMAIN(c) 1
149#else
150# define IN_CTYPE_DOMAIN(c) isascii (c)
151#endif
152
153#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
154#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
155#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
156#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
157
158/* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
159 - Its arg may be any int or unsigned int; it need not be an unsigned char.
160 - It's guaranteed to evaluate its argument exactly once.
161 - It's typically faster.
162 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
163 ISDIGIT_LOCALE unless it's important to use the locale's definition
164 of `digit' even when the host does not conform to POSIX. */
165#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
166
167#if STDC_HEADERS || HAVE_STRING_H
168# include <string.h>
169#endif
170
171#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
172# define __attribute__(x)
173#endif
174
175#ifndef ATTRIBUTE_UNUSED
176# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
177#endif
178
179#define EPOCH_YEAR 1970
180#define TM_YEAR_BASE 1900
181
182#define HOUR(x) ((x) * 60)
183
184/* An integer value, and the number of digits in its textual
185 representation. */
186typedef struct
187{
188 int value;
189 int digits;
190} textint;
191
192/* An entry in the lexical lookup table. */
193typedef struct
194{
195 char const *name;
196 int type;
197 int value;
198} table;
199
200/* Meridian: am, pm, or 24-hour style. */
201enum { MERam, MERpm, MER24 };
202
203/* Information passed to and from the parser. */
204typedef struct
205{
206 /* The input string remaining to be parsed. */
207 const char *input;
208
209 /* N, if this is the Nth Tuesday. */
210 int day_ordinal;
211
212 /* Day of week; Sunday is 0. */
213 int day_number;
214
215 /* tm_isdst flag for the local zone. */
216 int local_isdst;
217
218 /* Time zone, in minutes east of UTC. */
219 int time_zone;
220
221 /* Style used for time. */
222 int meridian;
223
224 /* Gregorian year, month, day, hour, minutes, and seconds. */
225 textint year;
226 int month;
227 int day;
228 int hour;
229 int minutes;
230 int seconds;
231
232 /* Relative year, month, day, hour, minutes, and seconds. */
233 int rel_year;
234 int rel_month;
235 int rel_day;
236 int rel_hour;
237 int rel_minutes;
238 int rel_seconds;
239
240 /* Counts of nonterminals of various flavors parsed so far. */
241 int dates_seen;
242 int days_seen;
243 int local_zones_seen;
244 int rels_seen;
245 int times_seen;
246 int zones_seen;
247
248 /* Table of local time zone abbrevations, terminated by a null entry. */
249 table local_time_zone_table[3];
250} parser_control;
251
252#define PC (* (parser_control *) parm)
253#define YYLEX_PARAM parm
254#define YYPARSE_PARAM parm
255
256static int yyerror ();
257static int yylex ();
258
259
260
261/* Enabling traces. */
262#ifndef YYDEBUG
263# define YYDEBUG 0
264#endif
265
266/* Enabling verbose error messages. */
267#ifdef YYERROR_VERBOSE
268# undef YYERROR_VERBOSE
269# define YYERROR_VERBOSE 1
270#else
271# define YYERROR_VERBOSE 0
272#endif
273
274#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
275#line 172 "getdate.y"
276typedef union YYSTYPE {
277 int intval;
278 textint textintval;
279} YYSTYPE;
280/* Line 191 of yacc.c. */
281#line 281 "getdate.c"
282# define yystype YYSTYPE /* obsolescent; will be withdrawn */
283# define YYSTYPE_IS_DECLARED 1
284# define YYSTYPE_IS_TRIVIAL 1
285#endif
286
287
288
289/* Copy the second part of user declarations. */
290
291
292/* Line 214 of yacc.c. */
293#line 293 "getdate.c"
294
295#if ! defined (yyoverflow) || YYERROR_VERBOSE
296
297/* The parser invokes alloca or malloc; define the necessary symbols. */
298
299# if YYSTACK_USE_ALLOCA
300# define YYSTACK_ALLOC alloca
301# else
302# ifndef YYSTACK_USE_ALLOCA
303# if defined (alloca) || defined (_ALLOCA_H)
304# define YYSTACK_ALLOC alloca
305# else
306# ifdef __GNUC__
307# define YYSTACK_ALLOC __builtin_alloca
308# endif
309# endif
310# endif
311# endif
312
313# ifdef YYSTACK_ALLOC
314 /* Pacify GCC's `empty if-body' warning. */
315# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
316# else
317# if defined (__STDC__) || defined (__cplusplus)
318# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
319# define YYSIZE_T size_t
320# endif
321# define YYSTACK_ALLOC malloc
322# define YYSTACK_FREE free
323# endif
324#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
325
326
327#if (! defined (yyoverflow) \
328 && (! defined (__cplusplus) \
329 || (YYSTYPE_IS_TRIVIAL)))
330
331/* A type that is properly aligned for any stack member. */
332union yyalloc
333{
334 short yyss;
335 YYSTYPE yyvs;
336 };
337
338/* The size of the maximum gap between one aligned stack and the next. */
339# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
340
341/* The size of an array large to enough to hold all stacks, each with
342 N elements. */
343# define YYSTACK_BYTES(N) \
344 ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
345 + YYSTACK_GAP_MAXIMUM)
346
347/* Copy COUNT objects from FROM to TO. The source and destination do
348 not overlap. */
349# ifndef YYCOPY
350# if 1 < __GNUC__
351# define YYCOPY(To, From, Count) \
352 __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
353# else
354# define YYCOPY(To, From, Count) \
355 do \
356 { \
357 register YYSIZE_T yyi; \
358 for (yyi = 0; yyi < (Count); yyi++) \
359 (To)[yyi] = (From)[yyi]; \
360 } \
361 while (0)
362# endif
363# endif
364
365/* Relocate STACK from its old location to the new one. The
366 local variables YYSIZE and YYSTACKSIZE give the old and new number of
367 elements in the stack, and YYPTR gives the new location of the
368 stack. Advance YYPTR to a properly aligned location for the next
369 stack. */
370# define YYSTACK_RELOCATE(Stack) \
371 do \
372 { \
373 YYSIZE_T yynewbytes; \
374 YYCOPY (&yyptr->Stack, Stack, yysize); \
375 Stack = &yyptr->Stack; \
376 yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
377 yyptr += yynewbytes / sizeof (*yyptr); \
378 } \
379 while (0)
380
381#endif
382
383#if defined (__STDC__) || defined (__cplusplus)
384 typedef signed char yysigned_char;
385#else
386 typedef short yysigned_char;
387#endif
388
389/* YYFINAL -- State number of the termination state. */
390#define YYFINAL 2
391/* YYLAST -- Last index in YYTABLE. */
392#define YYLAST 52
393
394/* YYNTOKENS -- Number of terminals. */
395#define YYNTOKENS 22
396/* YYNNTS -- Number of nonterminals. */
397#define YYNNTS 12
398/* YYNRULES -- Number of rules. */
399#define YYNRULES 54
400/* YYNRULES -- Number of states. */
401#define YYNSTATES 64
402
403/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
404#define YYUNDEFTOK 2
405#define YYMAXUTOK 273
406
407#define YYTRANSLATE(YYX) \
408 ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
409
410/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
411static const unsigned char yytranslate[] =
412{
413 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
414 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
415 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
416 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
417 2, 2, 2, 2, 20, 2, 2, 21, 2, 2,
418 2, 2, 2, 2, 2, 2, 2, 2, 19, 2,
419 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
420 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
421 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
422 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
423 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
424 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
425 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
426 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
427 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
428 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
429 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
430 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
431 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
432 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
433 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
434 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
435 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
436 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
437 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
438 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
439 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
440 15, 16, 17, 18
441};
442
443#if YYDEBUG
444/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
445 YYRHS. */
446static const unsigned char yyprhs[] =
447{
448 0, 0, 3, 4, 7, 9, 11, 13, 15, 17,
449 19, 21, 24, 29, 34, 41, 48, 50, 53, 55,
450 57, 60, 62, 65, 68, 72, 78, 82, 86, 89,
451 94, 97, 101, 104, 106, 109, 112, 114, 117, 120,
452 122, 125, 128, 130, 133, 136, 138, 141, 144, 146,
453 149, 152, 154, 156, 157
454};
455
456/* YYRHS -- A `-1'-separated list of the rules' RHS. */
457static const yysigned_char yyrhs[] =
458{
459 23, 0, -1, -1, 23, 24, -1, 25, -1, 26,
460 -1, 27, -1, 29, -1, 28, -1, 30, -1, 32,
461 -1, 18, 10, -1, 18, 19, 18, 33, -1, 18,
462 19, 18, 17, -1, 18, 19, 18, 19, 18, 33,
463 -1, 18, 19, 18, 19, 18, 17, -1, 9, -1,
464 9, 4, -1, 16, -1, 7, -1, 16, 4, -1,
465 5, -1, 5, 20, -1, 18, 5, -1, 18, 21,
466 18, -1, 18, 21, 18, 21, 18, -1, 18, 17,
467 17, -1, 18, 12, 17, -1, 12, 18, -1, 12,
468 18, 20, 18, -1, 18, 12, -1, 18, 12, 18,
469 -1, 31, 3, -1, 31, -1, 18, 15, -1, 17,
470 15, -1, 15, -1, 18, 13, -1, 17, 13, -1,
471 13, -1, 18, 6, -1, 17, 6, -1, 6, -1,
472 18, 8, -1, 17, 8, -1, 8, -1, 18, 11,
473 -1, 17, 11, -1, 11, -1, 18, 14, -1, 17,
474 14, -1, 14, -1, 18, -1, -1, 10, -1
475};
476
477/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
478static const unsigned short yyrline[] =
479{
480 0, 188, 188, 190, 194, 196, 198, 200, 202, 204,
481 206, 210, 217, 224, 232, 239, 251, 253, 258, 260,
482 262, 267, 272, 277, 285, 290, 310, 317, 325, 330,
483 336, 341, 350, 359, 363, 365, 367, 369, 371, 373,
484 375, 377, 379, 381, 383, 385, 387, 389, 391, 393,
485 395, 397, 402, 439, 440
486};
487#endif
488
489#if YYDEBUG || YYERROR_VERBOSE
490/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
491 First, the terminals, then, starting at YYNTOKENS, nonterminals. */
492static const char *const yytname[] =
493{
494 "$end", "error", "$undefined", "tAGO", "tDST", "tDAY", "tDAY_UNIT",
495 "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT",
496 "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER",
497 "tUNUMBER", "':'", "','", "'/'", "$accept", "spec", "item", "time",
498 "local_zone", "zone", "day", "date", "rel", "relunit", "number",
499 "o_merid", 0
500};
501#endif
502
503# ifdef YYPRINT
504/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
505 token YYLEX-NUM. */
506static const unsigned short yytoknum[] =
507{
508 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
509 265, 266, 267, 268, 269, 270, 271, 272, 273, 58,
510 44, 47
511};
512# endif
513
514/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
515static const unsigned char yyr1[] =
516{
517 0, 22, 23, 23, 24, 24, 24, 24, 24, 24,
518 24, 25, 25, 25, 25, 25, 26, 26, 27, 27,
519 27, 28, 28, 28, 29, 29, 29, 29, 29, 29,
520 29, 29, 30, 30, 31, 31, 31, 31, 31, 31,
521 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
522 31, 31, 32, 33, 33
523};
524
525/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
526static const unsigned char yyr2[] =
527{
528 0, 2, 0, 2, 1, 1, 1, 1, 1, 1,
529 1, 2, 4, 4, 6, 6, 1, 2, 1, 1,
530 2, 1, 2, 2, 3, 5, 3, 3, 2, 4,
531 2, 3, 2, 1, 2, 2, 1, 2, 2, 1,
532 2, 2, 1, 2, 2, 1, 2, 2, 1, 2,
533 2, 1, 1, 0, 1
534};
535
536/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
537 STATE-NUM when YYTABLE doesn't specify something else to do. Zero
538 means the default is an error. */
539static const unsigned char yydefact[] =
540{
541 2, 0, 1, 21, 42, 19, 45, 16, 48, 0,
542 39, 51, 36, 18, 0, 52, 3, 4, 5, 6,
543 8, 7, 9, 33, 10, 22, 17, 28, 20, 41,
544 44, 47, 38, 50, 35, 23, 40, 43, 11, 46,
545 30, 37, 49, 34, 0, 0, 0, 32, 0, 27,
546 31, 26, 53, 24, 29, 54, 13, 0, 12, 0,
547 53, 25, 15, 14
548};
549
550/* YYDEFGOTO[NTERM-NUM]. */
551static const yysigned_char yydefgoto[] =
552{
553 -1, 1, 16, 17, 18, 19, 20, 21, 22, 23,
554 24, 58
555};
556
557/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
558 STATE-NUM. */
559#define YYPACT_NINF -17
560static const yysigned_char yypact[] =
561{
562 -17, 0, -17, 1, -17, -17, -17, 19, -17, -14,
563 -17, -17, -17, 32, 26, 14, -17, -17, -17, -17,
564 -17, -17, -17, 27, -17, -17, -17, 22, -17, -17,
565 -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
566 -16, -17, -17, -17, 29, 25, 30, -17, 31, -17,
567 -17, -17, 28, 23, -17, -17, -17, 33, -17, 34,
568 -7, -17, -17, -17
569};
570
571/* YYPGOTO[NTERM-NUM]. */
572static const yysigned_char yypgoto[] =
573{
574 -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
575 -17, -10
576};
577
578/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
579 positive, shift that token. If negative, reduce the rule which
580 number is the opposite. If zero, do what YYDEFACT says.
581 If YYTABLE_NINF, syntax error. */
582#define YYTABLE_NINF -1
583static const unsigned char yytable[] =
584{
585 2, 49, 50, 55, 27, 3, 4, 5, 6, 7,
586 62, 8, 9, 10, 11, 12, 13, 14, 15, 35,
587 36, 25, 37, 26, 38, 39, 40, 41, 42, 43,
588 47, 44, 29, 45, 30, 46, 28, 31, 55, 32,
589 33, 34, 48, 52, 59, 56, 51, 57, 53, 54,
590 63, 60, 61
591};
592
593static const unsigned char yycheck[] =
594{
595 0, 17, 18, 10, 18, 5, 6, 7, 8, 9,
596 17, 11, 12, 13, 14, 15, 16, 17, 18, 5,
597 6, 20, 8, 4, 10, 11, 12, 13, 14, 15,
598 3, 17, 6, 19, 8, 21, 4, 11, 10, 13,
599 14, 15, 20, 18, 21, 17, 17, 19, 18, 18,
600 60, 18, 18
601};
602
603/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
604 symbol of state STATE-NUM. */
605static const unsigned char yystos[] =
606{
607 0, 23, 0, 5, 6, 7, 8, 9, 11, 12,
608 13, 14, 15, 16, 17, 18, 24, 25, 26, 27,
609 28, 29, 30, 31, 32, 20, 4, 18, 4, 6,
610 8, 11, 13, 14, 15, 5, 6, 8, 10, 11,
611 12, 13, 14, 15, 17, 19, 21, 3, 20, 17,
612 18, 17, 18, 18, 18, 10, 17, 19, 33, 21,
613 18, 18, 17, 33
614};
615
616#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
617# define YYSIZE_T __SIZE_TYPE__
618#endif
619#if ! defined (YYSIZE_T) && defined (size_t)
620# define YYSIZE_T size_t
621#endif
622#if ! defined (YYSIZE_T)
623# if defined (__STDC__) || defined (__cplusplus)
624# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
625# define YYSIZE_T size_t
626# endif
627#endif
628#if ! defined (YYSIZE_T)
629# define YYSIZE_T unsigned int
630#endif
631
632#define yyerrok (yyerrstatus = 0)
633#define yyclearin (yychar = YYEMPTY)
634#define YYEMPTY (-2)
635#define YYEOF 0
636
637#define YYACCEPT goto yyacceptlab
638#define YYABORT goto yyabortlab
639#define YYERROR goto yyerrlab1
640
641
642/* Like YYERROR except do call yyerror. This remains here temporarily
643 to ease the transition to the new meaning of YYERROR, for GCC.
644 Once GCC version 2 has supplanted version 1, this can go. */
645
646#define YYFAIL goto yyerrlab
647
648#define YYRECOVERING() (!!yyerrstatus)
649
650#define YYBACKUP(Token, Value) \
651do \
652 if (yychar == YYEMPTY && yylen == 1) \
653 { \
654 yychar = (Token); \
655 yylval = (Value); \
656 yytoken = YYTRANSLATE (yychar); \
657 YYPOPSTACK; \
658 goto yybackup; \
659 } \
660 else \
661 { \
662 yyerror ("syntax error: cannot back up");\
663 YYERROR; \
664 } \
665while (0)
666
667#define YYTERROR 1
668#define YYERRCODE 256
669
670/* YYLLOC_DEFAULT -- Compute the default location (before the actions
671 are run). */
672
673#ifndef YYLLOC_DEFAULT
674# define YYLLOC_DEFAULT(Current, Rhs, N) \
675 Current.first_line = Rhs[1].first_line; \
676 Current.first_column = Rhs[1].first_column; \
677 Current.last_line = Rhs[N].last_line; \
678 Current.last_column = Rhs[N].last_column;
679#endif
680
681/* YYLEX -- calling `yylex' with the right arguments. */
682
683#ifdef YYLEX_PARAM
684# define YYLEX yylex (&yylval, YYLEX_PARAM)
685#else
686# define YYLEX yylex (&yylval)
687#endif
688
689/* Enable debugging if requested. */
690#if YYDEBUG
691
692# ifndef YYFPRINTF
693# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
694# define YYFPRINTF fprintf
695# endif
696
697# define YYDPRINTF(Args) \
698do { \
699 if (yydebug) \
700 YYFPRINTF Args; \
701} while (0)
702
703# define YYDSYMPRINT(Args) \
704do { \
705 if (yydebug) \
706 yysymprint Args; \
707} while (0)
708
709# define YYDSYMPRINTF(Title, Token, Value, Location) \
710do { \
711 if (yydebug) \
712 { \
713 YYFPRINTF (stderr, "%s ", Title); \
714 yysymprint (stderr, \
715 Token, Value); \
716 YYFPRINTF (stderr, "\n"); \
717 } \
718} while (0)
719
720/*------------------------------------------------------------------.
721| yy_stack_print -- Print the state stack from its BOTTOM up to its |
722| TOP (cinluded). |
723`------------------------------------------------------------------*/
724
725#if defined (__STDC__) || defined (__cplusplus)
726static void
727yy_stack_print (short *bottom, short *top)
728#else
729static void
730yy_stack_print (bottom, top)
731 short *bottom;
732 short *top;
733#endif
734{
735 YYFPRINTF (stderr, "Stack now");
736 for (/* Nothing. */; bottom <= top; ++bottom)
737 YYFPRINTF (stderr, " %d", *bottom);
738 YYFPRINTF (stderr, "\n");
739}
740
741# define YY_STACK_PRINT(Bottom, Top) \
742do { \
743 if (yydebug) \
744 yy_stack_print ((Bottom), (Top)); \
745} while (0)
746
747
748/*------------------------------------------------.
749| Report that the YYRULE is going to be reduced. |
750`------------------------------------------------*/
751
752#if defined (__STDC__) || defined (__cplusplus)
753static void
754yy_reduce_print (int yyrule)
755#else
756static void
757yy_reduce_print (yyrule)
758 int yyrule;
759#endif
760{
761 int yyi;
762 unsigned int yylineno = yyrline[yyrule];
763 YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
764 yyrule - 1, yylineno);
765 /* Print the symbols being reduced, and their result. */
766 for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
767 YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
768 YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
769}
770
771# define YY_REDUCE_PRINT(Rule) \
772do { \
773 if (yydebug) \
774 yy_reduce_print (Rule); \
775} while (0)
776
777/* Nonzero means print parse trace. It is left uninitialized so that
778 multiple parsers can coexist. */
779int yydebug;
780#else /* !YYDEBUG */
781# define YYDPRINTF(Args)
782# define YYDSYMPRINT(Args)
783# define YYDSYMPRINTF(Title, Token, Value, Location)
784# define YY_STACK_PRINT(Bottom, Top)
785# define YY_REDUCE_PRINT(Rule)
786#endif /* !YYDEBUG */
787
788
789/* YYINITDEPTH -- initial size of the parser's stacks. */
790#ifndef YYINITDEPTH
791# define YYINITDEPTH 200
792#endif
793
794/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
795 if the built-in stack extension method is used).
796
797 Do not make this value too large; the results are undefined if
798 SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
799 evaluated with infinite-precision integer arithmetic. */
800
801#if YYMAXDEPTH == 0
802# undef YYMAXDEPTH
803#endif
804
805#ifndef YYMAXDEPTH
806# define YYMAXDEPTH 10000
807#endif
808
809
810
811
812#if YYERROR_VERBOSE
813
814# ifndef yystrlen
815# if defined (__GLIBC__) && defined (_STRING_H)
816# define yystrlen strlen
817# else
818/* Return the length of YYSTR. */
819static YYSIZE_T
820# if defined (__STDC__) || defined (__cplusplus)
821yystrlen (const char *yystr)
822# else
823yystrlen (yystr)
824 const char *yystr;
825# endif
826{
827 register const char *yys = yystr;
828
829 while (*yys++ != '\0')
830 continue;
831
832 return yys - yystr - 1;
833}
834# endif
835# endif
836
837# ifndef yystpcpy
838# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
839# define yystpcpy stpcpy
840# else
841/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
842 YYDEST. */
843static char *
844# if defined (__STDC__) || defined (__cplusplus)
845yystpcpy (char *yydest, const char *yysrc)
846# else
847yystpcpy (yydest, yysrc)
848 char *yydest;
849 const char *yysrc;
850# endif
851{
852 register char *yyd = yydest;
853 register const char *yys = yysrc;
854
855 while ((*yyd++ = *yys++) != '\0')
856 continue;
857
858 return yyd - 1;
859}
860# endif
861# endif
862
863#endif /* !YYERROR_VERBOSE */
864
865
866
867
868#if YYDEBUG
869/*--------------------------------.
870| Print this symbol on YYOUTPUT. |
871`--------------------------------*/
872
873#if defined (__STDC__) || defined (__cplusplus)
874static void
875yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
876#else
877static void
878yysymprint (yyoutput, yytype, yyvaluep)
879 FILE *yyoutput;
880 int yytype;
881 YYSTYPE *yyvaluep;
882#endif
883{
884 /* Pacify ``unused variable'' warnings. */
885 (void) yyvaluep;
886
887 if (yytype < YYNTOKENS)
888 {
889 YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
890# ifdef YYPRINT
891 YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
892# endif
893 }
894 else
895 YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
896
897 switch (yytype)
898 {
899 default:
900 break;
901 }
902 YYFPRINTF (yyoutput, ")");
903}
904
905#endif /* ! YYDEBUG */
906/*-----------------------------------------------.
907| Release the memory associated to this symbol. |
908`-----------------------------------------------*/
909
910#if defined (__STDC__) || defined (__cplusplus)
911static void
912yydestruct (int yytype, YYSTYPE *yyvaluep)
913#else
914static void
915yydestruct (yytype, yyvaluep)
916 int yytype;
917 YYSTYPE *yyvaluep;
918#endif
919{
920 /* Pacify ``unused variable'' warnings. */
921 (void) yyvaluep;
922
923 switch (yytype)
924 {
925
926 default:
927 break;
928 }
929}
930
931
932
933/* Prevent warnings from -Wmissing-prototypes. */
934
935#ifdef YYPARSE_PARAM
936# if defined (__STDC__) || defined (__cplusplus)
937int yyparse (void *YYPARSE_PARAM);
938# else
939int yyparse ();
940# endif
941#else /* ! YYPARSE_PARAM */
942#if defined (__STDC__) || defined (__cplusplus)
943int yyparse (void);
944#else
945int yyparse ();
946#endif
947#endif /* ! YYPARSE_PARAM */
948
949
950
951
952
953
954/*----------.
955| yyparse. |
956`----------*/
957
958#ifdef YYPARSE_PARAM
959# if defined (__STDC__) || defined (__cplusplus)
960int yyparse (void *YYPARSE_PARAM)
961# else
962int yyparse (YYPARSE_PARAM)
963 void *YYPARSE_PARAM;
964# endif
965#else /* ! YYPARSE_PARAM */
966#if defined (__STDC__) || defined (__cplusplus)
967int
968yyparse (void)
969#else
970int
971yyparse ()
972
973#endif
974#endif
975{
976 /* The lookahead symbol. */
977int yychar;
978
979/* The semantic value of the lookahead symbol. */
980YYSTYPE yylval;
981
982/* Number of syntax errors so far. */
983int yynerrs;
984
985 register int yystate;
986 register int yyn;
987 int yyresult;
988 /* Number of tokens to shift before error messages enabled. */
989 int yyerrstatus;
990 /* Lookahead token as an internal (translated) token number. */
991 int yytoken = 0;
992
993 /* Three stacks and their tools:
994 `yyss': related to states,
995 `yyvs': related to semantic values,
996 `yyls': related to locations.
997
998 Refer to the stacks thru separate pointers, to allow yyoverflow
999 to reallocate them elsewhere. */
1000
1001 /* The state stack. */
1002 short yyssa[YYINITDEPTH];
1003 short *yyss = yyssa;
1004 register short *yyssp;
1005
1006 /* The semantic value stack. */
1007 YYSTYPE yyvsa[YYINITDEPTH];
1008 YYSTYPE *yyvs = yyvsa;
1009 register YYSTYPE *yyvsp;
1010
1011
1012
1013#define YYPOPSTACK (yyvsp--, yyssp--)
1014
1015 YYSIZE_T yystacksize = YYINITDEPTH;
1016
1017 /* The variables used to return semantic value and location from the
1018 action routines. */
1019 YYSTYPE yyval;
1020
1021
1022 /* When reducing, the number of symbols on the RHS of the reduced
1023 rule. */
1024 int yylen;
1025
1026 YYDPRINTF ((stderr, "Starting parse\n"));
1027
1028 yystate = 0;
1029 yyerrstatus = 0;
1030 yynerrs = 0;
1031 yychar = YYEMPTY; /* Cause a token to be read. */
1032
1033 /* Initialize stack pointers.
1034 Waste one element of value and location stack
1035 so that they stay on the same level as the state stack.
1036 The wasted elements are never initialized. */
1037
1038 yyssp = yyss;
1039 yyvsp = yyvs;
1040
1041 goto yysetstate;
1042
1043/*------------------------------------------------------------.
1044| yynewstate -- Push a new state, which is found in yystate. |
1045`------------------------------------------------------------*/
1046 yynewstate:
1047 /* In all cases, when you get here, the value and location stacks
1048 have just been pushed. so pushing a state here evens the stacks.
1049 */
1050 yyssp++;
1051
1052 yysetstate:
1053 *yyssp = yystate;
1054
1055 if (yyss + yystacksize - 1 <= yyssp)
1056 {
1057 /* Get the current used size of the three stacks, in elements. */
1058 YYSIZE_T yysize = yyssp - yyss + 1;
1059
1060#ifdef yyoverflow
1061 {
1062 /* Give user a chance to reallocate the stack. Use copies of
1063 these so that the &'s don't force the real ones into
1064 memory. */
1065 YYSTYPE *yyvs1 = yyvs;
1066 short *yyss1 = yyss;
1067
1068
1069 /* Each stack pointer address is followed by the size of the
1070 data in use in that stack, in bytes. This used to be a
1071 conditional around just the two extra args, but that might
1072 be undefined if yyoverflow is a macro. */
1073 yyoverflow ("parser stack overflow",
1074 &yyss1, yysize * sizeof (*yyssp),
1075 &yyvs1, yysize * sizeof (*yyvsp),
1076
1077 &yystacksize);
1078
1079 yyss = yyss1;
1080 yyvs = yyvs1;
1081 }
1082#else /* no yyoverflow */
1083# ifndef YYSTACK_RELOCATE
1084 goto yyoverflowlab;
1085# else
1086 /* Extend the stack our own way. */
1087 if (YYMAXDEPTH <= yystacksize)
1088 goto yyoverflowlab;
1089 yystacksize *= 2;
1090 if (YYMAXDEPTH < yystacksize)
1091 yystacksize = YYMAXDEPTH;
1092
1093 {
1094 short *yyss1 = yyss;
1095 union yyalloc *yyptr =
1096 (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1097 if (! yyptr)
1098 goto yyoverflowlab;
1099 YYSTACK_RELOCATE (yyss);
1100 YYSTACK_RELOCATE (yyvs);
1101
1102# undef YYSTACK_RELOCATE
1103 if (yyss1 != yyssa)
1104 YYSTACK_FREE (yyss1);
1105 }
1106# endif
1107#endif /* no yyoverflow */
1108
1109 yyssp = yyss + yysize - 1;
1110 yyvsp = yyvs + yysize - 1;
1111
1112
1113 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1114 (unsigned long int) yystacksize));
1115
1116 if (yyss + yystacksize - 1 <= yyssp)
1117 YYABORT;
1118 }
1119
1120 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1121
1122 goto yybackup;
1123
1124/*-----------.
1125| yybackup. |
1126`-----------*/
1127yybackup:
1128
1129/* Do appropriate processing given the current state. */
1130/* Read a lookahead token if we need one and don't already have one. */
1131/* yyresume: */
1132
1133 /* First try to decide what to do without reference to lookahead token. */
1134
1135 yyn = yypact[yystate];
1136 if (yyn == YYPACT_NINF)
1137 goto yydefault;
1138
1139 /* Not known => get a lookahead token if don't already have one. */
1140
1141 /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
1142 if (yychar == YYEMPTY)
1143 {
1144 YYDPRINTF ((stderr, "Reading a token: "));
1145 yychar = YYLEX;
1146 }
1147
1148 if (yychar <= YYEOF)
1149 {
1150 yychar = yytoken = YYEOF;
1151 YYDPRINTF ((stderr, "Now at end of input.\n"));
1152 }
1153 else
1154 {
1155 yytoken = YYTRANSLATE (yychar);
1156 YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
1157 }
1158
1159 /* If the proper action on seeing token YYTOKEN is to reduce or to
1160 detect an error, take that action. */
1161 yyn += yytoken;
1162 if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1163 goto yydefault;
1164 yyn = yytable[yyn];
1165 if (yyn <= 0)
1166 {
1167 if (yyn == 0 || yyn == YYTABLE_NINF)
1168 goto yyerrlab;
1169 yyn = -yyn;
1170 goto yyreduce;
1171 }
1172
1173 if (yyn == YYFINAL)
1174 YYACCEPT;
1175
1176 /* Shift the lookahead token. */
1177 YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
1178
1179 /* Discard the token being shifted unless it is eof. */
1180 if (yychar != YYEOF)
1181 yychar = YYEMPTY;
1182
1183 *++yyvsp = yylval;
1184
1185
1186 /* Count tokens shifted since error; after three, turn off error
1187 status. */
1188 if (yyerrstatus)
1189 yyerrstatus--;
1190
1191 yystate = yyn;
1192 goto yynewstate;
1193
1194
1195/*-----------------------------------------------------------.
1196| yydefault -- do the default action for the current state. |
1197`-----------------------------------------------------------*/
1198yydefault:
1199 yyn = yydefact[yystate];
1200 if (yyn == 0)
1201 goto yyerrlab;
1202 goto yyreduce;
1203
1204
1205/*-----------------------------.
1206| yyreduce -- Do a reduction. |
1207`-----------------------------*/
1208yyreduce:
1209 /* yyn is the number of a rule to reduce with. */
1210 yylen = yyr2[yyn];
1211
1212 /* If YYLEN is nonzero, implement the default value of the action:
1213 `$$ = $1'.
1214
1215 Otherwise, the following line sets YYVAL to garbage.
1216 This behavior is undocumented and Bison
1217 users should not rely upon it. Assigning to YYVAL
1218 unconditionally makes the parser a bit smaller, and it avoids a
1219 GCC warning that YYVAL may be used uninitialized. */
1220 yyval = yyvsp[1-yylen];
1221
1222
1223 YY_REDUCE_PRINT (yyn);
1224 switch (yyn)
1225 {
1226 case 4:
1227#line 195 "getdate.y"
1228 { PC.times_seen++; }
1229 break;
1230
1231 case 5:
1232#line 197 "getdate.y"
1233 { PC.local_zones_seen++; }
1234 break;
1235
1236 case 6:
1237#line 199 "getdate.y"
1238 { PC.zones_seen++; }
1239 break;
1240
1241 case 7:
1242#line 201 "getdate.y"
1243 { PC.dates_seen++; }
1244 break;
1245
1246 case 8:
1247#line 203 "getdate.y"
1248 { PC.days_seen++; }
1249 break;
1250
1251 case 9:
1252#line 205 "getdate.y"
1253 { PC.rels_seen++; }
1254 break;
1255
1256 case 11:
1257#line 211 "getdate.y"
1258 {
1259 PC.hour = yyvsp[-1].textintval.value;
1260 PC.minutes = 0;
1261 PC.seconds = 0;
1262 PC.meridian = yyvsp[0].intval;
1263 }
1264 break;
1265
1266 case 12:
1267#line 218 "getdate.y"
1268 {
1269 PC.hour = yyvsp[-3].textintval.value;
1270 PC.minutes = yyvsp[-1].textintval.value;
1271 PC.seconds = 0;
1272 PC.meridian = yyvsp[0].intval;
1273 }
1274 break;
1275
1276 case 13:
1277#line 225 "getdate.y"
1278 {
1279 PC.hour = yyvsp[-3].textintval.value;
1280 PC.minutes = yyvsp[-1].textintval.value;
1281 PC.meridian = MER24;
1282 PC.zones_seen++;
1283 PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
1284 }
1285 break;
1286
1287 case 14:
1288#line 233 "getdate.y"
1289 {
1290 PC.hour = yyvsp[-5].textintval.value;
1291 PC.minutes = yyvsp[-3].textintval.value;
1292 PC.seconds = yyvsp[-1].textintval.value;
1293 PC.meridian = yyvsp[0].intval;
1294 }
1295 break;
1296
1297 case 15:
1298#line 240 "getdate.y"
1299 {
1300 PC.hour = yyvsp[-5].textintval.value;
1301 PC.minutes = yyvsp[-3].textintval.value;
1302 PC.seconds = yyvsp[-1].textintval.value;
1303 PC.meridian = MER24;
1304 PC.zones_seen++;
1305 PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60;
1306 }
1307 break;
1308
1309 case 16:
1310#line 252 "getdate.y"
1311 { PC.local_isdst = yyvsp[0].intval; }
1312 break;
1313
1314 case 17:
1315#line 254 "getdate.y"
1316 { PC.local_isdst = yyvsp[-1].intval < 0 ? 1 : yyvsp[-1].intval + 1; }
1317 break;
1318
1319 case 18:
1320#line 259 "getdate.y"
1321 { PC.time_zone = yyvsp[0].intval; }
1322 break;
1323
1324 case 19:
1325#line 261 "getdate.y"
1326 { PC.time_zone = yyvsp[0].intval + 60; }
1327 break;
1328
1329 case 20:
1330#line 263 "getdate.y"
1331 { PC.time_zone = yyvsp[-1].intval + 60; }
1332 break;
1333
1334 case 21:
1335#line 268 "getdate.y"
1336 {
1337 PC.day_ordinal = 1;
1338 PC.day_number = yyvsp[0].intval;
1339 }
1340 break;
1341
1342 case 22:
1343#line 273 "getdate.y"
1344 {
1345 PC.day_ordinal = 1;
1346 PC.day_number = yyvsp[-1].intval;
1347 }
1348 break;
1349
1350 case 23:
1351#line 278 "getdate.y"
1352 {
1353 PC.day_ordinal = yyvsp[-1].textintval.value;
1354 PC.day_number = yyvsp[0].intval;
1355 }
1356 break;
1357
1358 case 24:
1359#line 286 "getdate.y"
1360 {
1361 PC.month = yyvsp[-2].textintval.value;
1362 PC.day = yyvsp[0].textintval.value;
1363 }
1364 break;
1365
1366 case 25:
1367#line 291 "getdate.y"
1368 {
1369 /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
1370 otherwise as MM/DD/YY.
1371 The goal in recognizing YYYY/MM/DD is solely to support legacy
1372 machine-generated dates like those in an RCS log listing. If
1373 you want portability, use the ISO 8601 format. */
1374 if (4 <= yyvsp[-4].textintval.digits)
1375 {
1376 PC.year = yyvsp[-4].textintval;
1377 PC.month = yyvsp[-2].textintval.value;
1378 PC.day = yyvsp[0].textintval.value;
1379 }
1380 else
1381 {
1382 PC.month = yyvsp[-4].textintval.value;
1383 PC.day = yyvsp[-2].textintval.value;
1384 PC.year = yyvsp[0].textintval;
1385 }
1386 }
1387 break;
1388
1389 case 26:
1390#line 311 "getdate.y"
1391 {
1392 /* ISO 8601 format. YYYY-MM-DD. */
1393 PC.year = yyvsp[-2].textintval;
1394 PC.month = -yyvsp[-1].textintval.value;
1395 PC.day = -yyvsp[0].textintval.value;
1396 }
1397 break;
1398
1399 case 27:
1400#line 318 "getdate.y"
1401 {
1402 /* e.g. 17-JUN-1992. */
1403 PC.day = yyvsp[-2].textintval.value;
1404 PC.month = yyvsp[-1].intval;
1405 PC.year.value = -yyvsp[0].textintval.value;
1406 PC.year.digits = yyvsp[0].textintval.digits;
1407 }
1408 break;
1409
1410 case 28:
1411#line 326 "getdate.y"
1412 {
1413 PC.month = yyvsp[-1].intval;
1414 PC.day = yyvsp[0].textintval.value;
1415 }
1416 break;
1417
1418 case 29:
1419#line 331 "getdate.y"
1420 {
1421 PC.month = yyvsp[-3].intval;
1422 PC.day = yyvsp[-2].textintval.value;
1423 PC.year = yyvsp[0].textintval;
1424 }
1425 break;
1426
1427 case 30:
1428#line 337 "getdate.y"
1429 {
1430 PC.day = yyvsp[-1].textintval.value;
1431 PC.month = yyvsp[0].intval;
1432 }
1433 break;
1434
1435 case 31:
1436#line 342 "getdate.y"
1437 {
1438 PC.day = yyvsp[-2].textintval.value;
1439 PC.month = yyvsp[-1].intval;
1440 PC.year = yyvsp[0].textintval;
1441 }
1442 break;
1443
1444 case 32:
1445#line 351 "getdate.y"
1446 {
1447 PC.rel_seconds = -PC.rel_seconds;
1448 PC.rel_minutes = -PC.rel_minutes;
1449 PC.rel_hour = -PC.rel_hour;
1450 PC.rel_day = -PC.rel_day;
1451 PC.rel_month = -PC.rel_month;
1452 PC.rel_year = -PC.rel_year;
1453 }
1454 break;
1455
1456 case 34:
1457#line 364 "getdate.y"
1458 { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1459 break;
1460
1461 case 35:
1462#line 366 "getdate.y"
1463 { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1464 break;
1465
1466 case 36:
1467#line 368 "getdate.y"
1468 { PC.rel_year += yyvsp[0].intval; }
1469 break;
1470
1471 case 37:
1472#line 370 "getdate.y"
1473 { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1474 break;
1475
1476 case 38:
1477#line 372 "getdate.y"
1478 { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1479 break;
1480
1481 case 39:
1482#line 374 "getdate.y"
1483 { PC.rel_month += yyvsp[0].intval; }
1484 break;
1485
1486 case 40:
1487#line 376 "getdate.y"
1488 { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1489 break;
1490
1491 case 41:
1492#line 378 "getdate.y"
1493 { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1494 break;
1495
1496 case 42:
1497#line 380 "getdate.y"
1498 { PC.rel_day += yyvsp[0].intval; }
1499 break;
1500
1501 case 43:
1502#line 382 "getdate.y"
1503 { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1504 break;
1505
1506 case 44:
1507#line 384 "getdate.y"
1508 { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1509 break;
1510
1511 case 45:
1512#line 386 "getdate.y"
1513 { PC.rel_hour += yyvsp[0].intval; }
1514 break;
1515
1516 case 46:
1517#line 388 "getdate.y"
1518 { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1519 break;
1520
1521 case 47:
1522#line 390 "getdate.y"
1523 { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1524 break;
1525
1526 case 48:
1527#line 392 "getdate.y"
1528 { PC.rel_minutes += yyvsp[0].intval; }
1529 break;
1530
1531 case 49:
1532#line 394 "getdate.y"
1533 { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1534 break;
1535
1536 case 50:
1537#line 396 "getdate.y"
1538 { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; }
1539 break;
1540
1541 case 51:
1542#line 398 "getdate.y"
1543 { PC.rel_seconds += yyvsp[0].intval; }
1544 break;
1545
1546 case 52:
1547#line 403 "getdate.y"
1548 {
1549 if (PC.dates_seen
1550 && ! PC.rels_seen && (PC.times_seen || 2 < yyvsp[0].textintval.digits))
1551 PC.year = yyvsp[0].textintval;
1552 else
1553 {
1554 if (4 < yyvsp[0].textintval.digits)
1555 {
1556 PC.dates_seen++;
1557 PC.day = yyvsp[0].textintval.value % 100;
1558 PC.month = (yyvsp[0].textintval.value / 100) % 100;
1559 PC.year.value = yyvsp[0].textintval.value / 10000;
1560 PC.year.digits = yyvsp[0].textintval.digits - 4;
1561 }
1562 else
1563 {
1564 PC.times_seen++;
1565 if (yyvsp[0].textintval.digits <= 2)
1566 {
1567 PC.hour = yyvsp[0].textintval.value;
1568 PC.minutes = 0;
1569 }
1570 else
1571 {
1572 PC.hour = yyvsp[0].textintval.value / 100;
1573 PC.minutes = yyvsp[0].textintval.value % 100;
1574 }
1575 PC.seconds = 0;
1576 PC.meridian = MER24;
1577 }
1578 }
1579 }
1580 break;
1581
1582 case 53:
1583#line 439 "getdate.y"
1584 { yyval.intval = MER24; }
1585 break;
1586
1587 case 54:
1588#line 441 "getdate.y"
1589 { yyval.intval = yyvsp[0].intval; }
1590 break;
1591
1592
1593 }
1594
1595/* Line 999 of yacc.c. */
1596#line 1593 "getdate.c"
1597
1598
1599 yyvsp -= yylen;
1600 yyssp -= yylen;
1601
1602
1603 YY_STACK_PRINT (yyss, yyssp);
1604
1605 *++yyvsp = yyval;
1606
1607
1608 /* Now `shift' the result of the reduction. Determine what state
1609 that goes to, based on the state we popped back to and the rule
1610 number reduced by. */
1611
1612 yyn = yyr1[yyn];
1613
1614 yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1615 if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1616 yystate = yytable[yystate];
1617 else
1618 yystate = yydefgoto[yyn - YYNTOKENS];
1619
1620 goto yynewstate;
1621
1622
1623/*------------------------------------.
1624| yyerrlab -- here on detecting error |
1625`------------------------------------*/
1626yyerrlab:
1627 /* If not already recovering from an error, report this error. */
1628 if (!yyerrstatus)
1629 {
1630 ++yynerrs;
1631#if YYERROR_VERBOSE
1632 yyn = yypact[yystate];
1633
1634 if (YYPACT_NINF < yyn && yyn < YYLAST)
1635 {
1636 YYSIZE_T yysize = 0;
1637 int yytype = YYTRANSLATE (yychar);
1638 char *yymsg;
1639 int yyx, yycount;
1640
1641 yycount = 0;
1642 /* Start YYX at -YYN if negative to avoid negative indexes in
1643 YYCHECK. */
1644 for (yyx = yyn < 0 ? -yyn : 0;
1645 yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
1646 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1647 yysize += yystrlen (yytname[yyx]) + 15, yycount++;
1648 yysize += yystrlen ("syntax error, unexpected ") + 1;
1649 yysize += yystrlen (yytname[yytype]);
1650 yymsg = (char *) YYSTACK_ALLOC (yysize);
1651 if (yymsg != 0)
1652 {
1653 char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
1654 yyp = yystpcpy (yyp, yytname[yytype]);
1655
1656 if (yycount < 5)
1657 {
1658 yycount = 0;
1659 for (yyx = yyn < 0 ? -yyn : 0;
1660 yyx < (int) (sizeof (yytname) / sizeof (char *));
1661 yyx++)
1662 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1663 {
1664 const char *yyq = ! yycount ? ", expecting " : " or ";
1665 yyp = yystpcpy (yyp, yyq);
1666 yyp = yystpcpy (yyp, yytname[yyx]);
1667 yycount++;
1668 }
1669 }
1670 yyerror (yymsg);
1671 YYSTACK_FREE (yymsg);
1672 }
1673 else
1674 yyerror ("syntax error; also virtual memory exhausted");
1675 }
1676 else
1677#endif /* YYERROR_VERBOSE */
1678 yyerror ("syntax error");
1679 }
1680
1681
1682
1683 if (yyerrstatus == 3)
1684 {
1685 /* If just tried and failed to reuse lookahead token after an
1686 error, discard it. */
1687
1688 /* Return failure if at end of input. */
1689 if (yychar == YYEOF)
1690 {
1691 /* Pop the error token. */
1692 YYPOPSTACK;
1693 /* Pop the rest of the stack. */
1694 while (yyss < yyssp)
1695 {
1696 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
1697 yydestruct (yystos[*yyssp], yyvsp);
1698 YYPOPSTACK;
1699 }
1700 YYABORT;
1701 }
1702
1703 YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
1704 yydestruct (yytoken, &yylval);
1705 yychar = YYEMPTY;
1706
1707 }
1708
1709 /* Else will try to reuse lookahead token after shifting the error
1710 token. */
1711 goto yyerrlab1;
1712
1713
1714/*----------------------------------------------------.
1715| yyerrlab1 -- error raised explicitly by an action. |
1716`----------------------------------------------------*/
1717yyerrlab1:
1718 yyerrstatus = 3; /* Each real token shifted decrements this. */
1719
1720 for (;;)
1721 {
1722 yyn = yypact[yystate];
1723 if (yyn != YYPACT_NINF)
1724 {
1725 yyn += YYTERROR;
1726 if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1727 {
1728 yyn = yytable[yyn];
1729 if (0 < yyn)
1730 break;
1731 }
1732 }
1733
1734 /* Pop the current state because it cannot handle the error token. */
1735 if (yyssp == yyss)
1736 YYABORT;
1737
1738 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
1739 yydestruct (yystos[yystate], yyvsp);
1740 yyvsp--;
1741 yystate = *--yyssp;
1742
1743 YY_STACK_PRINT (yyss, yyssp);
1744 }
1745
1746 if (yyn == YYFINAL)
1747 YYACCEPT;
1748
1749 YYDPRINTF ((stderr, "Shifting error token, "));
1750
1751 *++yyvsp = yylval;
1752
1753
1754 yystate = yyn;
1755 goto yynewstate;
1756
1757
1758/*-------------------------------------.
1759| yyacceptlab -- YYACCEPT comes here. |
1760`-------------------------------------*/
1761yyacceptlab:
1762 yyresult = 0;
1763 goto yyreturn;
1764
1765/*-----------------------------------.
1766| yyabortlab -- YYABORT comes here. |
1767`-----------------------------------*/
1768yyabortlab:
1769 yyresult = 1;
1770 goto yyreturn;
1771
1772#ifndef yyoverflow
1773/*----------------------------------------------.
1774| yyoverflowlab -- parser overflow comes here. |
1775`----------------------------------------------*/
1776yyoverflowlab:
1777 yyerror ("parser stack overflow");
1778 yyresult = 2;
1779 /* Fall through. */
1780#endif
1781
1782yyreturn:
1783#ifndef yyoverflow
1784 if (yyss != yyssa)
1785 YYSTACK_FREE (yyss);
1786#endif
1787 return yyresult;
1788}
1789
1790
1791#line 444 "getdate.y"
1792
1793
1794/* Include this file down here because bison inserts code above which
1795 may define-away `const'. We want the prototype for get_date to have
1796 the same signature as the function definition. */
1797#include "modules/getdate.h"
1798
1799#ifndef gmtime
1800struct tm *gmtime ();
1801#endif
1802#ifndef localtime
1803struct tm *localtime ();
1804#endif
1805#ifndef mktime
1806time_t mktime ();
1807#endif
1808
1809static table const meridian_table[] =
1810{
1811 { "AM", tMERIDIAN, MERam },
1812 { "A.M.", tMERIDIAN, MERam },
1813 { "PM", tMERIDIAN, MERpm },
1814 { "P.M.", tMERIDIAN, MERpm },
1815 { 0, 0, 0 }
1816};
1817
1818static table const dst_table[] =
1819{
1820 { "DST", tDST, 0 }
1821};
1822
1823static table const month_and_day_table[] =
1824{
1825 { "JANUARY", tMONTH, 1 },
1826 { "FEBRUARY", tMONTH, 2 },
1827 { "MARCH", tMONTH, 3 },
1828 { "APRIL", tMONTH, 4 },
1829 { "MAY", tMONTH, 5 },
1830 { "JUNE", tMONTH, 6 },
1831 { "JULY", tMONTH, 7 },
1832 { "AUGUST", tMONTH, 8 },
1833 { "SEPTEMBER",tMONTH, 9 },
1834 { "SEPT", tMONTH, 9 },
1835 { "OCTOBER", tMONTH, 10 },
1836 { "NOVEMBER", tMONTH, 11 },
1837 { "DECEMBER", tMONTH, 12 },
1838 { "SUNDAY", tDAY, 0 },
1839 { "MONDAY", tDAY, 1 },
1840 { "TUESDAY", tDAY, 2 },
1841 { "TUES", tDAY, 2 },
1842 { "WEDNESDAY",tDAY, 3 },
1843 { "WEDNES", tDAY, 3 },
1844 { "THURSDAY", tDAY, 4 },
1845 { "THUR", tDAY, 4 },
1846 { "THURS", tDAY, 4 },
1847 { "FRIDAY", tDAY, 5 },
1848 { "SATURDAY", tDAY, 6 },
1849 { 0, 0, 0 }
1850};
1851
1852static table const time_units_table[] =
1853{
1854 { "YEAR", tYEAR_UNIT, 1 },
1855 { "MONTH", tMONTH_UNIT, 1 },
1856 { "FORTNIGHT",tDAY_UNIT, 14 },
1857 { "WEEK", tDAY_UNIT, 7 },
1858 { "DAY", tDAY_UNIT, 1 },
1859 { "HOUR", tHOUR_UNIT, 1 },
1860 { "MINUTE", tMINUTE_UNIT, 1 },
1861 { "MIN", tMINUTE_UNIT, 1 },
1862 { "SECOND", tSEC_UNIT, 1 },
1863 { "SEC", tSEC_UNIT, 1 },
1864 { 0, 0, 0 }
1865};
1866
1867/* Assorted relative-time words. */
1868static table const relative_time_table[] =
1869{
1870 { "TOMORROW", tMINUTE_UNIT, 24 * 60 },
1871 { "YESTERDAY",tMINUTE_UNIT, - (24 * 60) },
1872 { "TODAY", tMINUTE_UNIT, 0 },
1873 { "NOW", tMINUTE_UNIT, 0 },
1874 { "LAST", tUNUMBER, -1 },
1875 { "THIS", tUNUMBER, 0 },
1876 { "NEXT", tUNUMBER, 1 },
1877 { "FIRST", tUNUMBER, 1 },
1878/*{ "SECOND", tUNUMBER, 2 }, */
1879 { "THIRD", tUNUMBER, 3 },
1880 { "FOURTH", tUNUMBER, 4 },
1881 { "FIFTH", tUNUMBER, 5 },
1882 { "SIXTH", tUNUMBER, 6 },
1883 { "SEVENTH", tUNUMBER, 7 },
1884 { "EIGHTH", tUNUMBER, 8 },
1885 { "NINTH", tUNUMBER, 9 },
1886 { "TENTH", tUNUMBER, 10 },
1887 { "ELEVENTH", tUNUMBER, 11 },
1888 { "TWELFTH", tUNUMBER, 12 },
1889 { "AGO", tAGO, 1 },
1890 { 0, 0, 0 }
1891};
1892
1893/* The time zone table. This table is necessarily incomplete, as time
1894 zone abbreviations are ambiguous; e.g. Australians interpret "EST"
1895 as Eastern time in Australia, not as US Eastern Standard Time.
1896 You cannot rely on getdate to handle arbitrary time zone
1897 abbreviations; use numeric abbreviations like `-0500' instead. */
1898static table const time_zone_table[] =
1899{
1900 { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
1901 { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
1902 { "UTC", tZONE, HOUR ( 0) },
1903 { "WET", tZONE, HOUR ( 0) }, /* Western European */
1904 { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
1905 { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
1906 { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
1907 { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
1908 { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
1909 { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
1910 { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
1911 { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
1912 { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
1913 { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
1914 { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
1915 { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
1916 { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
1917 { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
1918 { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
1919 { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
1920 { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
1921 { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
1922 { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
1923 { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
1924 { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
1925 { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
1926 { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
1927 { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
1928 { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
1929 { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
1930 { "CET", tZONE, HOUR ( 1) }, /* Central European */
1931 { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
1932 { "MET", tZONE, HOUR ( 1) }, /* Middle European */
1933 { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
1934 { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
1935 { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
1936 { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
1937 { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
1938 { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
1939 { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
1940 { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
1941 { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
1942 { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
1943 { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
1944 { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
1945 { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
1946 { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
1947 { "GST", tZONE, HOUR (10) }, /* Guam Standard */
1948 { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
1949 { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
1950 { 0, 0, 0 }
1951};
1952
1953/* Military time zone table. */
1954static table const military_table[] =
1955{
1956 { "A", tZONE, -HOUR ( 1) },
1957 { "B", tZONE, -HOUR ( 2) },
1958 { "C", tZONE, -HOUR ( 3) },
1959 { "D", tZONE, -HOUR ( 4) },
1960 { "E", tZONE, -HOUR ( 5) },
1961 { "F", tZONE, -HOUR ( 6) },
1962 { "G", tZONE, -HOUR ( 7) },
1963 { "H", tZONE, -HOUR ( 8) },
1964 { "I", tZONE, -HOUR ( 9) },
1965 { "K", tZONE, -HOUR (10) },
1966 { "L", tZONE, -HOUR (11) },
1967 { "M", tZONE, -HOUR (12) },
1968 { "N", tZONE, HOUR ( 1) },
1969 { "O", tZONE, HOUR ( 2) },
1970 { "P", tZONE, HOUR ( 3) },
1971 { "Q", tZONE, HOUR ( 4) },
1972 { "R", tZONE, HOUR ( 5) },
1973 { "S", tZONE, HOUR ( 6) },
1974 { "T", tZONE, HOUR ( 7) },
1975 { "U", tZONE, HOUR ( 8) },
1976 { "V", tZONE, HOUR ( 9) },
1977 { "W", tZONE, HOUR (10) },
1978 { "X", tZONE, HOUR (11) },
1979 { "Y", tZONE, HOUR (12) },
1980 { "Z", tZONE, HOUR ( 0) },
1981 { 0, 0, 0 }
1982};
1983
1984
1985
1986
1987static int
1988to_hour (int hours, int meridian)
1989{
1990 switch (meridian)
1991 {
1992 case MER24:
1993 return 0 <= hours && hours < 24 ? hours : -1;
1994 case MERam:
1995 return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
1996 case MERpm:
1997 return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
1998 default:
1999 abort ();
2000 }
2001 /* NOTREACHED */
2002 return 0;
2003}
2004
2005static int
2006to_year (textint textyear)
2007{
2008 int year = textyear.value;
2009
2010 if (year < 0)
2011 year = -year;
2012
2013 /* XPG4 suggests that years 00-68 map to 2000-2068, and
2014 years 69-99 map to 1969-1999. */
2015 if (textyear.digits == 2)
2016 year += year < 69 ? 2000 : 1900;
2017
2018 return year;
2019}
2020
2021static table const *
2022lookup_zone (parser_control const *pc, char const *name)
2023{
2024 table const *tp;
2025
2026 /* Try local zone abbreviations first; they're more likely to be right. */
2027 for (tp = pc->local_time_zone_table; tp->name; tp++)
2028 if (strcmp (name, tp->name) == 0)
2029 return tp;
2030
2031 for (tp = time_zone_table; tp->name; tp++)
2032 if (strcmp (name, tp->name) == 0)
2033 return tp;
2034
2035 return 0;
2036}
2037
2038#if ! HAVE_TM_GMTOFF
2039/* Yield the difference between *A and *B,
2040 measured in seconds, ignoring leap seconds.
2041 The body of this function is taken directly from the GNU C Library;
2042 see src/strftime.c. */
2043static int
2044tm_diff (struct tm const *a, struct tm const *b)
2045{
2046 /* Compute intervening leap days correctly even if year is negative.
2047 Take care to avoid int overflow in leap day calculations,
2048 but it's OK to assume that A and B are close to each other. */
2049 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
2050 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
2051 int a100 = a4 / 25 - (a4 % 25 < 0);
2052 int b100 = b4 / 25 - (b4 % 25 < 0);
2053 int a400 = a100 >> 2;
2054 int b400 = b100 >> 2;
2055 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
2056 int years = a->tm_year - b->tm_year;
2057 int days = (365 * years + intervening_leap_days
2058 + (a->tm_yday - b->tm_yday));
2059 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
2060 + (a->tm_min - b->tm_min))
2061 + (a->tm_sec - b->tm_sec));
2062}
2063#endif /* ! HAVE_TM_GMTOFF */
2064
2065static table const *
2066lookup_word (parser_control const *pc, char *word)
2067{
2068 char *p;
2069 char *q;
2070 size_t wordlen;
2071 table const *tp;
2072 int i;
2073 int abbrev;
2074
2075 /* Make it uppercase. */
2076 for (p = word; *p; p++)
2077 if (ISLOWER ((unsigned char) *p))
2078 *p = toupper ((unsigned char) *p);
2079
2080 for (tp = meridian_table; tp->name; tp++)
2081 if (strcmp (word, tp->name) == 0)
2082 return tp;
2083
2084 /* See if we have an abbreviation for a month. */
2085 wordlen = strlen (word);
2086 abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
2087
2088 for (tp = month_and_day_table; tp->name; tp++)
2089 if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
2090 return tp;
2091
2092 if ((tp = lookup_zone (pc, word)))
2093 return tp;
2094
2095 if (strcmp (word, dst_table[0].name) == 0)
2096 return dst_table;
2097
2098 for (tp = time_units_table; tp->name; tp++)
2099 if (strcmp (word, tp->name) == 0)
2100 return tp;
2101
2102 /* Strip off any plural and try the units table again. */
2103 if (word[wordlen - 1] == 'S')
2104 {
2105 word[wordlen - 1] = '\0';
2106 for (tp = time_units_table; tp->name; tp++)
2107 if (strcmp (word, tp->name) == 0)
2108 return tp;
2109 word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
2110 }
2111
2112 for (tp = relative_time_table; tp->name; tp++)
2113 if (strcmp (word, tp->name) == 0)
2114 return tp;
2115
2116 /* Military time zones. */
2117 if (wordlen == 1)
2118 for (tp = military_table; tp->name; tp++)
2119 if (word[0] == tp->name[0])
2120 return tp;
2121
2122 /* Drop out any periods and try the time zone table again. */
2123 for (i = 0, p = q = word; (*p = *q); q++)
2124 if (*q == '.')
2125 i = 1;
2126 else
2127 p++;
2128 if (i && (tp = lookup_zone (pc, word)))
2129 return tp;
2130
2131 return 0;
2132}
2133
2134static int
2135yylex (YYSTYPE *lvalp, parser_control *pc)
2136{
2137 unsigned char c;
2138 int count;
2139
2140 for (;;)
2141 {
2142 while (c = *pc->input, ISSPACE (c))
2143 pc->input++;
2144
2145 if (ISDIGIT (c) || c == '-' || c == '+')
2146 {
2147 char const *p;
2148 int sign;
2149 int value;
2150 if (c == '-' || c == '+')
2151 {
2152 sign = c == '-' ? -1 : 1;
2153 c = *++pc->input;
2154 if (! ISDIGIT (c))
2155 /* skip the '-' sign */
2156 continue;
2157 }
2158 else
2159 sign = 0;
2160 p = pc->input;
2161 value = 0;
2162 do
2163 {
2164 value = 10 * value + c - '0';
2165 c = *++p;
2166 }
2167 while (ISDIGIT (c));
2168 lvalp->textintval.value = sign < 0 ? -value : value;
2169 lvalp->textintval.digits = p - pc->input;
2170 pc->input = p;
2171 return sign ? tSNUMBER : tUNUMBER;
2172 }
2173
2174 if (ISALPHA (c))
2175 {
2176 char buff[20];
2177 char *p = buff;
2178 table const *tp;
2179
2180 do
2181 {
2182 if (p < buff + sizeof buff - 1)
2183 *p++ = c;
2184 c = *++pc->input;
2185 }
2186 while (ISALPHA (c) || c == '.');
2187
2188 *p = '\0';
2189 tp = lookup_word (pc, buff);
2190 if (! tp)
2191 return '?';
2192 lvalp->intval = tp->value;
2193 return tp->type;
2194 }
2195
2196 if (c != '(')
2197 return *pc->input++;
2198 count = 0;
2199 do
2200 {
2201 c = *pc->input++;
2202 if (c == '\0')
2203 return c;
2204 if (c == '(')
2205 count++;
2206 else if (c == ')')
2207 count--;
2208 }
2209 while (count > 0);
2210 }
2211}
2212
2213/* Do nothing if the parser reports an error. */
2214static int
2215yyerror (char *s ATTRIBUTE_UNUSED)
2216{
2217 return 0;
2218}
2219
2220/* Parse a date/time string P. Return the corresponding time_t value,
2221 or (time_t) -1 if there is an error. P can be an incomplete or
2222 relative time specification; if so, use *NOW as the basis for the
2223 returned time. */
2224time_t
2225get_date (const char *p, const time_t *now)
2226{
2227 time_t Start = now ? *now : time (0);
2228 struct tm *tmp = localtime (&Start);
2229 struct tm tm;
2230 struct tm tm0;
2231 parser_control pc;
2232
2233 if (! tmp)
2234 return -1;
2235
2236 pc.input = p;
2237 pc.year.value = tmp->tm_year + TM_YEAR_BASE;
2238 pc.year.digits = 4;
2239 pc.month = tmp->tm_mon + 1;
2240 pc.day = tmp->tm_mday;
2241 pc.hour = tmp->tm_hour;
2242 pc.minutes = tmp->tm_min;
2243 pc.seconds = tmp->tm_sec;
2244 tm.tm_isdst = tmp->tm_isdst;
2245
2246 pc.meridian = MER24;
2247 pc.rel_seconds = 0;
2248 pc.rel_minutes = 0;
2249 pc.rel_hour = 0;
2250 pc.rel_day = 0;
2251 pc.rel_month = 0;
2252 pc.rel_year = 0;
2253 pc.dates_seen = 0;
2254 pc.days_seen = 0;
2255 pc.rels_seen = 0;
2256 pc.times_seen = 0;
2257 pc.local_zones_seen = 0;
2258 pc.zones_seen = 0;
2259
2260#if HAVE_STRUCT_TM_TM_ZONE
2261 pc.local_time_zone_table[0].name = tmp->tm_zone;
2262 pc.local_time_zone_table[0].type = tLOCAL_ZONE;
2263 pc.local_time_zone_table[0].value = tmp->tm_isdst;
2264 pc.local_time_zone_table[1].name = 0;
2265
2266 /* Probe the names used in the next three calendar quarters, looking
2267 for a tm_isdst different from the one we already have. */
2268 {
2269 int quarter;
2270 for (quarter = 1; quarter <= 3; quarter++)
2271 {
2272 time_t probe = Start + quarter * (90 * 24 * 60 * 60);
2273 struct tm *probe_tm = localtime (&probe);
2274 if (probe_tm && probe_tm->tm_zone
2275 && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
2276 {
2277 {
2278 pc.local_time_zone_table[1].name = probe_tm->tm_zone;
2279 pc.local_time_zone_table[1].type = tLOCAL_ZONE;
2280 pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
2281 pc.local_time_zone_table[2].name = 0;
2282 }
2283 break;
2284 }
2285 }
2286 }
2287#else
2288#if HAVE_TZNAME
2289 {
2290# ifndef tzname
2291 extern char *tzname[];
2292# endif
2293 int i;
2294 for (i = 0; i < 2; i++)
2295 {
2296 pc.local_time_zone_table[i].name = tzname[i];
2297 pc.local_time_zone_table[i].type = tLOCAL_ZONE;
2298 pc.local_time_zone_table[i].value = i;
2299 }
2300 pc.local_time_zone_table[i].name = 0;
2301 }
2302#else
2303 pc.local_time_zone_table[0].name = 0;
2304#endif
2305#endif
2306
2307 if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
2308 && ! strcmp (pc.local_time_zone_table[0].name,
2309 pc.local_time_zone_table[1].name))
2310 {
2311 /* This locale uses the same abbrevation for standard and
2312 daylight times. So if we see that abbreviation, we don't
2313 know whether it's daylight time. */
2314 pc.local_time_zone_table[0].value = -1;
2315 pc.local_time_zone_table[1].name = 0;
2316 }
2317
2318 if (yyparse (&pc) != 0
2319 || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen
2320 || 1 < (pc.local_zones_seen + pc.zones_seen)
2321 || (pc.local_zones_seen && 1 < pc.local_isdst))
2322 return -1;
2323
2324 tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year;
2325 tm.tm_mon = pc.month - 1 + pc.rel_month;
2326 tm.tm_mday = pc.day + pc.rel_day;
2327 if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
2328 {
2329 tm.tm_hour = to_hour (pc.hour, pc.meridian);
2330 if (tm.tm_hour < 0)
2331 return -1;
2332 tm.tm_min = pc.minutes;
2333 tm.tm_sec = pc.seconds;
2334 }
2335 else
2336 {
2337 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
2338 }
2339
2340 /* Let mktime deduce tm_isdst if we have an absolute time stamp,
2341 or if the relative time stamp mentions days, months, or years. */
2342 if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day
2343 | pc.rel_month | pc.rel_year)
2344 tm.tm_isdst = -1;
2345
2346 /* But if the input explicitly specifies local time with or without
2347 DST, give mktime that information. */
2348 if (pc.local_zones_seen)
2349 tm.tm_isdst = pc.local_isdst;
2350
2351 tm0 = tm;
2352
2353 Start = mktime (&tm);
2354
2355 if (Start == (time_t) -1)
2356 {
2357
2358 /* Guard against falsely reporting errors near the time_t boundaries
2359 when parsing times in other time zones. For example, if the min
2360 time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
2361 of UTC, then the min localtime value is 1970-01-01 08:00:00; if
2362 we apply mktime to 1970-01-01 00:00:00 we will get an error, so
2363 we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
2364 zone by 24 hours to compensate. This algorithm assumes that
2365 there is no DST transition within a day of the time_t boundaries. */
2366 if (pc.zones_seen)
2367 {
2368 tm = tm0;
2369 if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)
2370 {
2371 tm.tm_mday++;
2372 pc.time_zone += 24 * 60;
2373 }
2374 else
2375 {
2376 tm.tm_mday--;
2377 pc.time_zone -= 24 * 60;
2378 }
2379 Start = mktime (&tm);
2380 }
2381
2382 if (Start == (time_t) -1)
2383 return Start;
2384 }
2385
2386 if (pc.days_seen && ! pc.dates_seen)
2387 {
2388 tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
2389 + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
2390 tm.tm_isdst = -1;
2391 Start = mktime (&tm);
2392 if (Start == (time_t) -1)
2393 return Start;
2394 }
2395
2396 if (pc.zones_seen)
2397 {
2398 int delta = pc.time_zone * 60;
2399#ifdef HAVE_TM_GMTOFF
2400 delta -= tm.tm_gmtoff;
2401#else
2402 struct tm *gmt = gmtime (&Start);
2403 if (! gmt)
2404 return -1;
2405 delta -= tm_diff (&tm, gmt);
2406#endif
2407 if ((Start < Start - delta) != (delta < 0))
2408 return -1; /* time_t overflow */
2409 Start -= delta;
2410 }
2411
2412 /* Add relative hours, minutes, and seconds. Ignore leap seconds;
2413 i.e. "+ 10 minutes" means 600 seconds, even if one of them is a
2414 leap second. Typically this is not what the user wants, but it's
2415 too hard to do it the other way, because the time zone indicator
2416 must be applied before relative times, and if mktime is applied
2417 again the time zone will be lost. */
2418 {
2419 time_t t0 = Start;
2420 long d1 = 60 * 60 * (long) pc.rel_hour;
2421 time_t t1 = t0 + d1;
2422 long d2 = 60 * (long) pc.rel_minutes;
2423 time_t t2 = t1 + d2;
2424 int d3 = pc.rel_seconds;
2425 time_t t3 = t2 + d3;
2426 if ((d1 / (60 * 60) ^ pc.rel_hour)
2427 | (d2 / 60 ^ pc.rel_minutes)
2428 | ((t0 + d1 < t0) ^ (d1 < 0))
2429 | ((t1 + d2 < t1) ^ (d2 < 0))
2430 | ((t2 + d3 < t2) ^ (d3 < 0)))
2431 return -1;
2432 Start = t3;
2433 }
2434
2435 return Start;
2436}
2437
2438#if TEST
2439
2440#include <stdio.h>
2441
2442int
2443main (int ac, char **av)
2444{
2445 char buff[BUFSIZ];
2446 time_t d;
2447
2448 printf ("Enter date, or blank line to exit.\n\t> ");
2449 fflush (stdout);
2450
2451 buff[BUFSIZ - 1] = 0;
2452 while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
2453 {
2454 d = get_date (buff, 0);
2455 if (d == (time_t) -1)
2456 printf ("Bad format - couldn't convert.\n");
2457 else
2458 printf ("%s", ctime (&d));
2459 printf ("\t> ");
2460 fflush (stdout);
2461 }
2462 return 0;
2463}
2464#endif /* defined TEST */
2465
2466
Note: See TracBrowser for help on using the repository browser.