1
2 /* A Bison parser, made from getdate.y
3 by GNU Bison version 1.28 */
4
5 #define YYBISON 1 /* Identify Bison output. */
6
7 #define tAGO 257
8 #define tDAY 258
9 #define tDAYZONE 259
10 #define tID 260
11 #define tMERIDIAN 261
12 #define tMINUTE_UNIT 262
13 #define tMONTH 263
14 #define tMONTH_UNIT 264
15 #define tSEC_UNIT 265
16 #define tSNUMBER 266
17 #define tUNUMBER 267
18 #define tZONE 268
19 #define tDST 269
20
21 #line 1 "getdate.y"
22
23 /*
24 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
25 ** at the University of North Carolina at Chapel Hill. Later tweaked by
26 ** a couple of people on Usenet. Completely overhauled by Rich $alz
27 ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
28 **
29 ** This grammar has 10 shift/reduce conflicts.
30 **
31 ** This code is in the public domain and has no copyright.
32 */
33 /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
34 /* SUPPRESS 288 on yyerrlab *//* Label unused */
35
36 #ifdef HAVE_CONFIG_H
37 #if defined (emacs) || defined (CONFIG_BROKETS)
38 #include <config.h>
39 #else
40 #include "config.h"
41 #endif
42 #endif
43
44 /* Since the code of getdate.y is not included in the Emacs executable
45 itself, there is no need to #define static in this file. Even if
46 the code were included in the Emacs executable, it probably
47 wouldn't do any harm to #undef it here; this will only cause
48 problems if we try to write to a static variable, which I don't
49 think this code needs to do. */
50 #ifdef emacs
51 #undef static
52 #endif
53
54 #include <stdio.h>
55 #include <ctype.h>
56
57 /* The code at the top of get_date which figures out the offset of the
58 current time zone checks various CPP symbols to see if special
59 tricks are need, but defaults to using the gettimeofday system call.
60 Include <sys/time.h> if that will be used. */
61
62 #if defined(vms)
63 # include <types.h>
64 #else /* defined(vms) */
65 # include <sys/types.h>
66 # include "xtime.h"
67 #endif /* !defined(vms) */
68
69 #if defined (STDC_HEADERS) || defined (USG)
70 #include <string.h>
71 #endif
72
73 /* Some old versions of bison generate parsers that use bcopy.
74 That loses on systems that don't provide the function, so we have
75 to redefine it here. */
76 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
77 #define bcopy(from, to, len) memcpy ((to), (from), (len))
78 #endif
79
80 #if defined (STDC_HEADERS)
81 #include <stdlib.h>
82 #endif
83
84 /* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
85 releases):
86
87 We don't want to mess with all the portability hassles of alloca.
88 In particular, most (all?) versions of bison will use alloca in
89 their parser. If bison works on your system (e.g. it should work
90 with gcc), then go ahead and use it, but the more general solution
91 is to use byacc instead of bison, which should generate a portable
92 parser. I played with adding "#define alloca dont_use_alloca", to
93 give an error if the parser generator uses alloca (and thus detect
94 unportable getdate.c's), but that seems to cause as many problems
95 as it solves. */
96
97 extern struct tm *gmtime();
98 extern struct tm *localtime();
99
100 #define yyparse getdate_yyparse
101 #define yylex getdate_yylex
102 #define yyerror getdate_yyerror
103
104 static int yyparse ();
105 static int yylex ();
106 static int yyerror ();
107
108 #define EPOCH 1970
109 #define HOUR(x) ((time_t)(x) * 60)
110 #define SECSPERDAY (24L * 60L * 60L)
111
112
113 /*
114 ** An entry in the lexical lookup table.
115 */
116 typedef struct _TABLE {
117 char *name;
118 int type;
119 time_t value;
120 } TABLE;
121
122
123 /*
124 ** Daylight-savings mode: on, off, or not yet known.
125 */
126 typedef enum _DSTMODE {
127 DSTon, DSToff, DSTmaybe
128 } DSTMODE;
129
130 /*
131 ** Meridian: am, pm, or 24-hour style.
132 */
133 typedef enum _MERIDIAN {
134 MERam, MERpm, MER24
135 } MERIDIAN;
136
137
138 /*
139 ** Global variables. We could get rid of most of these by using a good
140 ** union as the yacc stack. (This routine was originally written before
141 ** yacc had the %union construct.) Maybe someday; right now we only use
142 ** the %union very rarely.
143 */
144 static char *yyInput;
145 static DSTMODE yyDSTmode;
146 static time_t yyDayOrdinal;
147 static time_t yyDayNumber;
148 static int yyHaveDate;
149 static int yyHaveDay;
150 static int yyHaveRel;
151 static int yyHaveTime;
152 static int yyHaveZone;
153 static time_t yyTimezone;
154 static time_t yyDay;
155 static time_t yyHour;
156 static time_t yyMinutes;
157 static time_t yyMonth;
158 static time_t yySeconds;
159 static time_t yyYear;
160 static MERIDIAN yyMeridian;
161 static time_t yyRelMonth;
162 static time_t yyRelSeconds;
163
164
165 #line 145 "getdate.y"
166 typedef union {
167 time_t Number;
168 enum _MERIDIAN Meridian;
169 } YYSTYPE;
170 #include <stdio.h>
171
172 #ifndef __cplusplus
173 #ifndef __STDC__
174 #define const
175 #endif
176 #endif
177
178
179
180 #define YYFINAL 52
181 #define YYFLAG -32768
182 #define YYNTBASE 19
183
184 #define YYTRANSLATE(x) ((unsigned)(x) <= 269 ? yytranslate[x] : 29)
185
186 static const char yytranslate[] = { 0,
187 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
188 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
189 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
190 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
191 2, 2, 2, 17, 2, 2, 18, 2, 2, 2,
192 2, 2, 2, 2, 2, 2, 2, 16, 2, 2,
193 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
194 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
195 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
196 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
197 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
198 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
199 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
200 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
201 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
202 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
203 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
204 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
205 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
206 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
207 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
208 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
209 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
210 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
211 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
212 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
213 7, 8, 9, 10, 11, 12, 13, 14, 15
214 };
215
216 #if YYDEBUG != 0
217 static const short yyprhs[] = { 0,
218 0, 1, 4, 6, 8, 10, 12, 14, 16, 19,
219 24, 29, 36, 43, 45, 47, 50, 52, 55, 58,
220 62, 68, 72, 76, 79, 84, 87, 91, 94, 96,
221 99, 102, 104, 107, 110, 112, 115, 118, 120, 122,
222 123
223 };
224
225 static const short yyrhs[] = { -1,
226 19, 20, 0, 21, 0, 22, 0, 24, 0, 23,
227 0, 25, 0, 27, 0, 13, 7, 0, 13, 16,
228 13, 28, 0, 13, 16, 13, 12, 0, 13, 16,
229 13, 16, 13, 28, 0, 13, 16, 13, 16, 13,
230 12, 0, 14, 0, 5, 0, 14, 15, 0, 4,
231 0, 4, 17, 0, 13, 4, 0, 13, 18, 13,
232 0, 13, 18, 13, 18, 13, 0, 13, 12, 12,
233 0, 13, 9, 12, 0, 9, 13, 0, 9, 13,
234 17, 13, 0, 13, 9, 0, 13, 9, 13, 0,
235 26, 3, 0, 26, 0, 13, 8, 0, 12, 8,
236 0, 8, 0, 12, 11, 0, 13, 11, 0, 11,
237 0, 12, 10, 0, 13, 10, 0, 10, 0, 13,
238 0, 0, 7, 0
239 };
240
241 #endif
242
243 #if YYDEBUG != 0
244 static const short yyrline[] = { 0,
245 159, 160, 163, 166, 169, 172, 175, 178, 181, 187,
246 193, 200, 206, 216, 220, 224, 231, 235, 239, 245,
247 249, 260, 266, 272, 276, 281, 285, 292, 296, 299,
248 302, 305, 308, 311, 314, 317, 320, 323, 328, 355,
249 358
250 };
251 #endif
252
253
254 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
255
256 static const char * const yytname[] = { "$","error","$undefined.","tAGO","tDAY",
257 "tDAYZONE","tID","tMERIDIAN","tMINUTE_UNIT","tMONTH","tMONTH_UNIT","tSEC_UNIT",
258 "tSNUMBER","tUNUMBER","tZONE","tDST","':'","','","'/'","spec","item","time",
259 "zone","day","date","rel","relunit","number","o_merid", NULL
260 };
261 #endif
262
263 static const short yyr1[] = { 0,
264 19, 19, 20, 20, 20, 20, 20, 20, 21, 21,
265 21, 21, 21, 22, 22, 22, 23, 23, 23, 24,
266 24, 24, 24, 24, 24, 24, 24, 25, 25, 26,
267 26, 26, 26, 26, 26, 26, 26, 26, 27, 28,
268 28
269 };
270
271 static const short yyr2[] = { 0,
272 0, 2, 1, 1, 1, 1, 1, 1, 2, 4,
273 4, 6, 6, 1, 1, 2, 1, 2, 2, 3,
274 5, 3, 3, 2, 4, 2, 3, 2, 1, 2,
275 2, 1, 2, 2, 1, 2, 2, 1, 1, 0,
276 1
277 };
278
279 static const short yydefact[] = { 1,
280 0, 17, 15, 32, 0, 38, 35, 0, 39, 14,
281 2, 3, 4, 6, 5, 7, 29, 8, 18, 24,
282 31, 36, 33, 19, 9, 30, 26, 37, 34, 0,
283 0, 0, 16, 28, 0, 23, 27, 22, 40, 20,
284 25, 41, 11, 0, 10, 0, 40, 21, 13, 12,
285 0, 0
286 };
287
288 static const short yydefgoto[] = { 1,
289 11, 12, 13, 14, 15, 16, 17, 18, 45
290 };
291
292 static const short yypact[] = {-32768,
293 0, -1,-32768,-32768, 4,-32768,-32768, 25, 11, -8,
294 -32768,-32768,-32768,-32768,-32768,-32768, 21,-32768,-32768, 9,
295 -32768,-32768,-32768,-32768,-32768,-32768, -10,-32768,-32768, 16,
296 19, 24,-32768,-32768, 26,-32768,-32768,-32768, 18, 13,
297 -32768,-32768,-32768, 27,-32768, 28, -6,-32768,-32768,-32768,
298 38,-32768
299 };
300
301 static const short yypgoto[] = {-32768,
302 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -5
303 };
304
305
306 #define YYLAST 42
307
308
309 static const short yytable[] = { 51,
310 42, 36, 37, 2, 3, 49, 33, 4, 5, 6,
311 7, 8, 9, 10, 24, 19, 20, 25, 26, 27,
312 28, 29, 30, 34, 42, 35, 31, 38, 32, 43,
313 46, 39, 21, 44, 22, 23, 40, 52, 41, 47,
314 48, 50
315 };
316
317 static const short yycheck[] = { 0,
318 7, 12, 13, 4, 5, 12, 15, 8, 9, 10,
319 11, 12, 13, 14, 4, 17, 13, 7, 8, 9,
320 10, 11, 12, 3, 7, 17, 16, 12, 18, 12,
321 18, 13, 8, 16, 10, 11, 13, 0, 13, 13,
322 13, 47
323 };
324 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
325 #line 3 "/usr/lib/bison.simple"
326 /* This file comes from bison-1.28. */
327
328 /* Skeleton output parser for bison,
329 Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
330
331 This program is free software; you can redistribute it and/or modify
332 it under the terms of the GNU General Public License as published by
333 the Free Software Foundation; either version 2, or (at your option)
334 any later version.
335
336 This program is distributed in the hope that it will be useful,
337 but WITHOUT ANY WARRANTY; without even the implied warranty of
338 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
339 GNU General Public License for more details.
340
341 You should have received a copy of the GNU General Public License
342 along with this program; if not, write to the Free Software
343 Foundation, Inc., 59 Temple Place - Suite 330,
344 Boston, MA 02111-1307, USA. */
345
346 /* As a special exception, when this file is copied by Bison into a
347 Bison output file, you may use that output file without restriction.
348 This special exception was added by the Free Software Foundation
349 in version 1.24 of Bison. */
350
351 /* This is the parser code that is written into each bison parser
352 when the %semantic_parser declaration is not specified in the grammar.
353 It was written by Richard Stallman by simplifying the hairy parser
354 used when %semantic_parser is specified. */
355
356 #ifndef YYSTACK_USE_ALLOCA
357 #ifdef alloca
358 #define YYSTACK_USE_ALLOCA
359 #else /* alloca not defined */
360 #ifdef __GNUC__
361 #define YYSTACK_USE_ALLOCA
362 #define alloca __builtin_alloca
363 #else /* not GNU C. */
364 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
365 #define YYSTACK_USE_ALLOCA
366 #include <alloca.h>
367 #else /* not sparc */
368 /* We think this test detects Watcom and Microsoft C. */
369 /* This used to test MSDOS, but that is a bad idea
370 since that symbol is in the user namespace. */
371 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
372 #if 0 /* No need for malloc.h, which pollutes the namespace;
373 instead, just don't use alloca. */
374 #include <malloc.h>
375 #endif
376 #else /* not MSDOS, or __TURBOC__ */
377 #if defined(_AIX)
378 /* I don't know what this was needed for, but it pollutes the namespace.
379 So I turned it off. rms, 2 May 1997. */
380 /* #include <malloc.h> */
381 #pragma alloca
382 #define YYSTACK_USE_ALLOCA
383 #else /* not MSDOS, or __TURBOC__, or _AIX */
384 #if 0
385 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
386 and on HPUX 10. Eventually we can turn this on. */
387 #define YYSTACK_USE_ALLOCA
388 #define alloca __builtin_alloca
389 #endif /* __hpux */
390 #endif
391 #endif /* not _AIX */
392 #endif /* not MSDOS, or __TURBOC__ */
393 #endif /* not sparc */
394 #endif /* not GNU C */
395 #endif /* alloca not defined */
396 #endif /* YYSTACK_USE_ALLOCA not defined */
397
398 #ifdef YYSTACK_USE_ALLOCA
399 #define YYSTACK_ALLOC alloca
400 #else
401 #define YYSTACK_ALLOC malloc
402 #endif
403
404 /* Note: there must be only one dollar sign in this file.
405 It is replaced by the list of actions, each action
406 as one case of the switch. */
407
408 #define yyerrok (yyerrstatus = 0)
409 #define yyclearin (yychar = YYEMPTY)
410 #define YYEMPTY -2
411 #define YYEOF 0
412 #define YYACCEPT goto yyacceptlab
413 #define YYABORT goto yyabortlab
414 #define YYERROR goto yyerrlab1
415 /* Like YYERROR except do call yyerror.
416 This remains here temporarily to ease the
417 transition to the new meaning of YYERROR, for GCC.
418 Once GCC version 2 has supplanted version 1, this can go. */
419 #define YYFAIL goto yyerrlab
420 #define YYRECOVERING() (!!yyerrstatus)
421 #define YYBACKUP(token, value) \
422 do \
423 if (yychar == YYEMPTY && yylen == 1) \
424 { yychar = (token), yylval = (value); \
425 yychar1 = YYTRANSLATE (yychar); \
426 YYPOPSTACK; \
427 goto yybackup; \
428 } \
429 else \
430 { yyerror ("syntax error: cannot back up"); YYERROR; } \
431 while (0)
432
433 #define YYTERROR 1
434 #define YYERRCODE 256
435
436 #ifndef YYPURE
437 #define YYLEX yylex()
438 #endif
439
440 #ifdef YYPURE
441 #ifdef YYLSP_NEEDED
442 #ifdef YYLEX_PARAM
443 #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
444 #else
445 #define YYLEX yylex(&yylval, &yylloc)
446 #endif
447 #else /* not YYLSP_NEEDED */
448 #ifdef YYLEX_PARAM
449 #define YYLEX yylex(&yylval, YYLEX_PARAM)
450 #else
451 #define YYLEX yylex(&yylval)
452 #endif
453 #endif /* not YYLSP_NEEDED */
454 #endif
455
456 /* If nonreentrant, generate the variables here */
457
458 #ifndef YYPURE
459
460 int yychar; /* the lookahead symbol */
461 YYSTYPE yylval; /* the semantic value of the */
462 /* lookahead symbol */
463
464 #ifdef YYLSP_NEEDED
465 YYLTYPE yylloc; /* location data for the lookahead */
466 /* symbol */
467 #endif
468
469 int yynerrs; /* number of parse errors so far */
470 #endif /* not YYPURE */
471
472 #if YYDEBUG != 0
473 int yydebug; /* nonzero means print parse trace */
474 /* Since this is uninitialized, it does not stop multiple parsers
475 from coexisting. */
476 #endif
477
478 /* YYINITDEPTH indicates the initial size of the parser's stacks */
479
480 #ifndef YYINITDEPTH
481 #define YYINITDEPTH 200
482 #endif
483
484 /* YYMAXDEPTH is the maximum size the stacks can grow to
485 (effective only if the built-in stack extension method is used). */
486
487 #if YYMAXDEPTH == 0
488 #undef YYMAXDEPTH
489 #endif
490
491 #ifndef YYMAXDEPTH
492 #define YYMAXDEPTH 10000
493 #endif
494
495 /* Define __yy_memcpy. Note that the size argument
496 should be passed with type unsigned int, because that is what the non-GCC
497 definitions require. With GCC, __builtin_memcpy takes an arg
498 of type size_t, but it can handle unsigned int. */
499
500 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
501 #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
502 #else /* not GNU C or C++ */
503 #ifndef __cplusplus
504
505 /* This is the most reliable way to avoid incompatibilities
506 in available built-in functions on various systems. */
507 static void
__yy_memcpy(to,from,count)508 __yy_memcpy (to, from, count)
509 char *to;
510 char *from;
511 unsigned int count;
512 {
513 register char *f = from;
514 register char *t = to;
515 register int i = count;
516
517 while (i-- > 0)
518 *t++ = *f++;
519 }
520
521 #else /* __cplusplus */
522
523 /* This is the most reliable way to avoid incompatibilities
524 in available built-in functions on various systems. */
525 static void
__yy_memcpy(char * to,char * from,unsigned int count)526 __yy_memcpy (char *to, char *from, unsigned int count)
527 {
528 register char *t = to;
529 register char *f = from;
530 register int i = count;
531
532 while (i-- > 0)
533 *t++ = *f++;
534 }
535
536 #endif
537 #endif
538
539 #line 217 "/usr/lib/bison.simple"
540
541 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
542 into yyparse. The argument should have type void *.
543 It should actually point to an object.
544 Grammar actions can access the variable by casting it
545 to the proper pointer type. */
546
547 #ifdef YYPARSE_PARAM
548 #ifdef __cplusplus
549 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
550 #define YYPARSE_PARAM_DECL
551 #else /* not __cplusplus */
552 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
553 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
554 #endif /* not __cplusplus */
555 #else /* not YYPARSE_PARAM */
556 #define YYPARSE_PARAM_ARG
557 #define YYPARSE_PARAM_DECL
558 #endif /* not YYPARSE_PARAM */
559
560 /* Prevent warning if -Wstrict-prototypes. */
561 #ifdef __GNUC__
562 #ifdef YYPARSE_PARAM
563 int yyparse (void *);
564 #else
565 int yyparse (void);
566 #endif
567 #endif
568
569 int
yyparse(YYPARSE_PARAM_ARG)570 yyparse(YYPARSE_PARAM_ARG)
571 YYPARSE_PARAM_DECL
572 {
573 register int yystate;
574 register int yyn;
575 register short *yyssp;
576 register YYSTYPE *yyvsp;
577 int yyerrstatus; /* number of tokens to shift before error messages enabled */
578 int yychar1 = 0; /* lookahead token as an internal (translated) token number */
579
580 short yyssa[YYINITDEPTH]; /* the state stack */
581 YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
582
583 short *yyss = yyssa; /* refer to the stacks thru separate pointers */
584 YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
585
586 #ifdef YYLSP_NEEDED
587 YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
588 YYLTYPE *yyls = yylsa;
589 YYLTYPE *yylsp;
590
591 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
592 #else
593 #define YYPOPSTACK (yyvsp--, yyssp--)
594 #endif
595
596 int yystacksize = YYINITDEPTH;
597 int yyfree_stacks = 0;
598
599 #ifdef YYPURE
600 int yychar;
601 YYSTYPE yylval;
602 int yynerrs;
603 #ifdef YYLSP_NEEDED
604 YYLTYPE yylloc;
605 #endif
606 #endif
607
608 YYSTYPE yyval; /* the variable used to return */
609 /* semantic values from the action */
610 /* routines */
611
612 int yylen;
613
614 #if YYDEBUG != 0
615 if (yydebug)
616 fprintf(stderr, "Starting parse\n");
617 #endif
618
619 yystate = 0;
620 yyerrstatus = 0;
621 yynerrs = 0;
622 yychar = YYEMPTY; /* Cause a token to be read. */
623
624 /* Initialize stack pointers.
625 Waste one element of value and location stack
626 so that they stay on the same level as the state stack.
627 The wasted elements are never initialized. */
628
629 yyssp = yyss - 1;
630 yyvsp = yyvs;
631 #ifdef YYLSP_NEEDED
632 yylsp = yyls;
633 #endif
634
635 /* Push a new state, which is found in yystate . */
636 /* In all cases, when you get here, the value and location stacks
637 have just been pushed. so pushing a state here evens the stacks. */
638 yynewstate:
639
640 *++yyssp = yystate;
641
642 if (yyssp >= yyss + yystacksize - 1)
643 {
644 /* Give user a chance to reallocate the stack */
645 /* Use copies of these so that the &'s don't force the real ones into memory. */
646 YYSTYPE *yyvs1 = yyvs;
647 short *yyss1 = yyss;
648 #ifdef YYLSP_NEEDED
649 YYLTYPE *yyls1 = yyls;
650 #endif
651
652 /* Get the current used size of the three stacks, in elements. */
653 int size = yyssp - yyss + 1;
654
655 #ifdef yyoverflow
656 /* Each stack pointer address is followed by the size of
657 the data in use in that stack, in bytes. */
658 #ifdef YYLSP_NEEDED
659 /* This used to be a conditional around just the two extra args,
660 but that might be undefined if yyoverflow is a macro. */
661 yyoverflow("parser stack overflow",
662 &yyss1, size * sizeof (*yyssp),
663 &yyvs1, size * sizeof (*yyvsp),
664 &yyls1, size * sizeof (*yylsp),
665 &yystacksize);
666 #else
667 yyoverflow("parser stack overflow",
668 &yyss1, size * sizeof (*yyssp),
669 &yyvs1, size * sizeof (*yyvsp),
670 &yystacksize);
671 #endif
672
673 yyss = yyss1; yyvs = yyvs1;
674 #ifdef YYLSP_NEEDED
675 yyls = yyls1;
676 #endif
677 #else /* no yyoverflow */
678 /* Extend the stack our own way. */
679 if (yystacksize >= YYMAXDEPTH)
680 {
681 yyerror("parser stack overflow");
682 if (yyfree_stacks)
683 {
684 free (yyss);
685 free (yyvs);
686 #ifdef YYLSP_NEEDED
687 free (yyls);
688 #endif
689 }
690 return 2;
691 }
692 yystacksize *= 2;
693 if (yystacksize > YYMAXDEPTH)
694 yystacksize = YYMAXDEPTH;
695 #ifndef YYSTACK_USE_ALLOCA
696 yyfree_stacks = 1;
697 #endif
698 yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
699 __yy_memcpy ((char *)yyss, (char *)yyss1,
700 size * (unsigned int) sizeof (*yyssp));
701 yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
702 __yy_memcpy ((char *)yyvs, (char *)yyvs1,
703 size * (unsigned int) sizeof (*yyvsp));
704 #ifdef YYLSP_NEEDED
705 yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
706 __yy_memcpy ((char *)yyls, (char *)yyls1,
707 size * (unsigned int) sizeof (*yylsp));
708 #endif
709 #endif /* no yyoverflow */
710
711 yyssp = yyss + size - 1;
712 yyvsp = yyvs + size - 1;
713 #ifdef YYLSP_NEEDED
714 yylsp = yyls + size - 1;
715 #endif
716
717 #if YYDEBUG != 0
718 if (yydebug)
719 fprintf(stderr, "Stack size increased to %d\n", yystacksize);
720 #endif
721
722 if (yyssp >= yyss + yystacksize - 1)
723 YYABORT;
724 }
725
726 #if YYDEBUG != 0
727 if (yydebug)
728 fprintf(stderr, "Entering state %d\n", yystate);
729 #endif
730
731 goto yybackup;
732 yybackup:
733
734 /* Do appropriate processing given the current state. */
735 /* Read a lookahead token if we need one and don't already have one. */
736 /* yyresume: */
737
738 /* First try to decide what to do without reference to lookahead token. */
739
740 yyn = yypact[yystate];
741 if (yyn == YYFLAG)
742 goto yydefault;
743
744 /* Not known => get a lookahead token if don't already have one. */
745
746 /* yychar is either YYEMPTY or YYEOF
747 or a valid token in external form. */
748
749 if (yychar == YYEMPTY)
750 {
751 #if YYDEBUG != 0
752 if (yydebug)
753 fprintf(stderr, "Reading a token: ");
754 #endif
755 yychar = YYLEX;
756 }
757
758 /* Convert token to internal form (in yychar1) for indexing tables with */
759
760 if (yychar <= 0) /* This means end of input. */
761 {
762 yychar1 = 0;
763 yychar = YYEOF; /* Don't call YYLEX any more */
764
765 #if YYDEBUG != 0
766 if (yydebug)
767 fprintf(stderr, "Now at end of input.\n");
768 #endif
769 }
770 else
771 {
772 yychar1 = YYTRANSLATE(yychar);
773
774 #if YYDEBUG != 0
775 if (yydebug)
776 {
777 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
778 /* Give the individual parser a way to print the precise meaning
779 of a token, for further debugging info. */
780 #ifdef YYPRINT
781 YYPRINT (stderr, yychar, yylval);
782 #endif
783 fprintf (stderr, ")\n");
784 }
785 #endif
786 }
787
788 yyn += yychar1;
789 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
790 goto yydefault;
791
792 yyn = yytable[yyn];
793
794 /* yyn is what to do for this token type in this state.
795 Negative => reduce, -yyn is rule number.
796 Positive => shift, yyn is new state.
797 New state is final state => don't bother to shift,
798 just return success.
799 0, or most negative number => error. */
800
801 if (yyn < 0)
802 {
803 if (yyn == YYFLAG)
804 goto yyerrlab;
805 yyn = -yyn;
806 goto yyreduce;
807 }
808 else if (yyn == 0)
809 goto yyerrlab;
810
811 if (yyn == YYFINAL)
812 YYACCEPT;
813
814 /* Shift the lookahead token. */
815
816 #if YYDEBUG != 0
817 if (yydebug)
818 fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
819 #endif
820
821 /* Discard the token being shifted unless it is eof. */
822 if (yychar != YYEOF)
823 yychar = YYEMPTY;
824
825 *++yyvsp = yylval;
826 #ifdef YYLSP_NEEDED
827 *++yylsp = yylloc;
828 #endif
829
830 /* count tokens shifted since error; after three, turn off error status. */
831 if (yyerrstatus) yyerrstatus--;
832
833 yystate = yyn;
834 goto yynewstate;
835
836 /* Do the default action for the current state. */
837 yydefault:
838
839 yyn = yydefact[yystate];
840 if (yyn == 0)
841 goto yyerrlab;
842
843 /* Do a reduction. yyn is the number of a rule to reduce with. */
844 yyreduce:
845 yylen = yyr2[yyn];
846 if (yylen > 0)
847 yyval = yyvsp[1-yylen]; /* implement default value of the action */
848
849 #if YYDEBUG != 0
850 if (yydebug)
851 {
852 int i;
853
854 fprintf (stderr, "Reducing via rule %d (line %d), ",
855 yyn, yyrline[yyn]);
856
857 /* Print the symbols being reduced, and their result. */
858 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
859 fprintf (stderr, "%s ", yytname[yyrhs[i]]);
860 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
861 }
862 #endif
863
864
865 switch (yyn) {
866
867 case 3:
868 #line 163 "getdate.y"
869 {
870 yyHaveTime++;
871 ;
872 break;}
873 case 4:
874 #line 166 "getdate.y"
875 {
876 yyHaveZone++;
877 ;
878 break;}
879 case 5:
880 #line 169 "getdate.y"
881 {
882 yyHaveDate++;
883 ;
884 break;}
885 case 6:
886 #line 172 "getdate.y"
887 {
888 yyHaveDay++;
889 ;
890 break;}
891 case 7:
892 #line 175 "getdate.y"
893 {
894 yyHaveRel++;
895 ;
896 break;}
897 case 9:
898 #line 181 "getdate.y"
899 {
900 yyHour = yyvsp[-1].Number;
901 yyMinutes = 0;
902 yySeconds = 0;
903 yyMeridian = yyvsp[0].Meridian;
904 ;
905 break;}
906 case 10:
907 #line 187 "getdate.y"
908 {
909 yyHour = yyvsp[-3].Number;
910 yyMinutes = yyvsp[-1].Number;
911 yySeconds = 0;
912 yyMeridian = yyvsp[0].Meridian;
913 ;
914 break;}
915 case 11:
916 #line 193 "getdate.y"
917 {
918 yyHour = yyvsp[-3].Number;
919 yyMinutes = yyvsp[-1].Number;
920 yyMeridian = MER24;
921 yyDSTmode = DSToff;
922 yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
923 ;
924 break;}
925 case 12:
926 #line 200 "getdate.y"
927 {
928 yyHour = yyvsp[-5].Number;
929 yyMinutes = yyvsp[-3].Number;
930 yySeconds = yyvsp[-1].Number;
931 yyMeridian = yyvsp[0].Meridian;
932 ;
933 break;}
934 case 13:
935 #line 206 "getdate.y"
936 {
937 yyHour = yyvsp[-5].Number;
938 yyMinutes = yyvsp[-3].Number;
939 yySeconds = yyvsp[-1].Number;
940 yyMeridian = MER24;
941 yyDSTmode = DSToff;
942 yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
943 ;
944 break;}
945 case 14:
946 #line 216 "getdate.y"
947 {
948 yyTimezone = yyvsp[0].Number;
949 yyDSTmode = DSToff;
950 ;
951 break;}
952 case 15:
953 #line 220 "getdate.y"
954 {
955 yyTimezone = yyvsp[0].Number;
956 yyDSTmode = DSTon;
957 ;
958 break;}
959 case 16:
960 #line 225 "getdate.y"
961 {
962 yyTimezone = yyvsp[-1].Number;
963 yyDSTmode = DSTon;
964 ;
965 break;}
966 case 17:
967 #line 231 "getdate.y"
968 {
969 yyDayOrdinal = 1;
970 yyDayNumber = yyvsp[0].Number;
971 ;
972 break;}
973 case 18:
974 #line 235 "getdate.y"
975 {
976 yyDayOrdinal = 1;
977 yyDayNumber = yyvsp[-1].Number;
978 ;
979 break;}
980 case 19:
981 #line 239 "getdate.y"
982 {
983 yyDayOrdinal = yyvsp[-1].Number;
984 yyDayNumber = yyvsp[0].Number;
985 ;
986 break;}
987 case 20:
988 #line 245 "getdate.y"
989 {
990 yyMonth = yyvsp[-2].Number;
991 yyDay = yyvsp[0].Number;
992 ;
993 break;}
994 case 21:
995 #line 249 "getdate.y"
996 {
997 if (yyvsp[-4].Number >= 100) {
998 yyYear = yyvsp[-4].Number;
999 yyMonth = yyvsp[-2].Number;
1000 yyDay = yyvsp[0].Number;
1001 } else {
1002 yyMonth = yyvsp[-4].Number;
1003 yyDay = yyvsp[-2].Number;
1004 yyYear = yyvsp[0].Number;
1005 }
1006 ;
1007 break;}
1008 case 22:
1009 #line 260 "getdate.y"
1010 {
1011 /* ISO 8601 format. yyyy-mm-dd. */
1012 yyYear = yyvsp[-2].Number;
1013 yyMonth = -yyvsp[-1].Number;
1014 yyDay = -yyvsp[0].Number;
1015 ;
1016 break;}
1017 case 23:
1018 #line 266 "getdate.y"
1019 {
1020 /* e.g. 17-JUN-1992. */
1021 yyDay = yyvsp[-2].Number;
1022 yyMonth = yyvsp[-1].Number;
1023 yyYear = -yyvsp[0].Number;
1024 ;
1025 break;}
1026 case 24:
1027 #line 272 "getdate.y"
1028 {
1029 yyMonth = yyvsp[-1].Number;
1030 yyDay = yyvsp[0].Number;
1031 ;
1032 break;}
1033 case 25:
1034 #line 276 "getdate.y"
1035 {
1036 yyMonth = yyvsp[-3].Number;
1037 yyDay = yyvsp[-2].Number;
1038 yyYear = yyvsp[0].Number;
1039 ;
1040 break;}
1041 case 26:
1042 #line 281 "getdate.y"
1043 {
1044 yyMonth = yyvsp[0].Number;
1045 yyDay = yyvsp[-1].Number;
1046 ;
1047 break;}
1048 case 27:
1049 #line 285 "getdate.y"
1050 {
1051 yyMonth = yyvsp[-1].Number;
1052 yyDay = yyvsp[-2].Number;
1053 yyYear = yyvsp[0].Number;
1054 ;
1055 break;}
1056 case 28:
1057 #line 292 "getdate.y"
1058 {
1059 yyRelSeconds = -yyRelSeconds;
1060 yyRelMonth = -yyRelMonth;
1061 ;
1062 break;}
1063 case 30:
1064 #line 299 "getdate.y"
1065 {
1066 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1067 ;
1068 break;}
1069 case 31:
1070 #line 302 "getdate.y"
1071 {
1072 yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1073 ;
1074 break;}
1075 case 32:
1076 #line 305 "getdate.y"
1077 {
1078 yyRelSeconds += yyvsp[0].Number * 60L;
1079 ;
1080 break;}
1081 case 33:
1082 #line 308 "getdate.y"
1083 {
1084 yyRelSeconds += yyvsp[-1].Number;
1085 ;
1086 break;}
1087 case 34:
1088 #line 311 "getdate.y"
1089 {
1090 yyRelSeconds += yyvsp[-1].Number;
1091 ;
1092 break;}
1093 case 35:
1094 #line 314 "getdate.y"
1095 {
1096 yyRelSeconds++;
1097 ;
1098 break;}
1099 case 36:
1100 #line 317 "getdate.y"
1101 {
1102 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1103 ;
1104 break;}
1105 case 37:
1106 #line 320 "getdate.y"
1107 {
1108 yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1109 ;
1110 break;}
1111 case 38:
1112 #line 323 "getdate.y"
1113 {
1114 yyRelMonth += yyvsp[0].Number;
1115 ;
1116 break;}
1117 case 39:
1118 #line 328 "getdate.y"
1119 {
1120 if (yyHaveTime && yyHaveDate && !yyHaveRel)
1121 yyYear = yyvsp[0].Number;
1122 else {
1123 if(yyvsp[0].Number>10000) {
1124 yyHaveDate++;
1125 yyDay= (yyvsp[0].Number)%100;
1126 yyMonth= (yyvsp[0].Number/100)%100;
1127 yyYear = yyvsp[0].Number/10000;
1128 }
1129 else {
1130 yyHaveTime++;
1131 if (yyvsp[0].Number < 100) {
1132 yyHour = yyvsp[0].Number;
1133 yyMinutes = 0;
1134 }
1135 else {
1136 yyHour = yyvsp[0].Number / 100;
1137 yyMinutes = yyvsp[0].Number % 100;
1138 }
1139 yySeconds = 0;
1140 yyMeridian = MER24;
1141 }
1142 }
1143 ;
1144 break;}
1145 case 40:
1146 #line 355 "getdate.y"
1147 {
1148 yyval.Meridian = MER24;
1149 ;
1150 break;}
1151 case 41:
1152 #line 358 "getdate.y"
1153 {
1154 yyval.Meridian = yyvsp[0].Meridian;
1155 ;
1156 break;}
1157 }
1158 /* the action file gets copied in in place of this dollarsign */
1159 #line 543 "/usr/lib/bison.simple"
1160
1161 yyvsp -= yylen;
1162 yyssp -= yylen;
1163 #ifdef YYLSP_NEEDED
1164 yylsp -= yylen;
1165 #endif
1166
1167 #if YYDEBUG != 0
1168 if (yydebug)
1169 {
1170 short *ssp1 = yyss - 1;
1171 fprintf (stderr, "state stack now");
1172 while (ssp1 != yyssp)
1173 fprintf (stderr, " %d", *++ssp1);
1174 fprintf (stderr, "\n");
1175 }
1176 #endif
1177
1178 *++yyvsp = yyval;
1179
1180 #ifdef YYLSP_NEEDED
1181 yylsp++;
1182 if (yylen == 0)
1183 {
1184 yylsp->first_line = yylloc.first_line;
1185 yylsp->first_column = yylloc.first_column;
1186 yylsp->last_line = (yylsp-1)->last_line;
1187 yylsp->last_column = (yylsp-1)->last_column;
1188 yylsp->text = 0;
1189 }
1190 else
1191 {
1192 yylsp->last_line = (yylsp+yylen-1)->last_line;
1193 yylsp->last_column = (yylsp+yylen-1)->last_column;
1194 }
1195 #endif
1196
1197 /* Now "shift" the result of the reduction.
1198 Determine what state that goes to,
1199 based on the state we popped back to
1200 and the rule number reduced by. */
1201
1202 yyn = yyr1[yyn];
1203
1204 yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1205 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1206 yystate = yytable[yystate];
1207 else
1208 yystate = yydefgoto[yyn - YYNTBASE];
1209
1210 goto yynewstate;
1211
1212 yyerrlab: /* here on detecting error */
1213
1214 if (! yyerrstatus)
1215 /* If not already recovering from an error, report this error. */
1216 {
1217 ++yynerrs;
1218
1219 #ifdef YYERROR_VERBOSE
1220 yyn = yypact[yystate];
1221
1222 if (yyn > YYFLAG && yyn < YYLAST)
1223 {
1224 int size = 0;
1225 char *msg;
1226 int x, count;
1227
1228 count = 0;
1229 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1230 for (x = (yyn < 0 ? -yyn : 0);
1231 x < (sizeof(yytname) / sizeof(char *)); x++)
1232 if (yycheck[x + yyn] == x)
1233 size += strlen(yytname[x]) + 15, count++;
1234 msg = (char *) malloc(size + 15);
1235 if (msg != 0)
1236 {
1237 strcpy(msg, "parse error");
1238
1239 if (count < 5)
1240 {
1241 count = 0;
1242 for (x = (yyn < 0 ? -yyn : 0);
1243 x < (sizeof(yytname) / sizeof(char *)); x++)
1244 if (yycheck[x + yyn] == x)
1245 {
1246 strcat(msg, count == 0 ? ", expecting `" : " or `");
1247 strcat(msg, yytname[x]);
1248 strcat(msg, "'");
1249 count++;
1250 }
1251 }
1252 yyerror(msg);
1253 free(msg);
1254 }
1255 else
1256 yyerror ("parse error; also virtual memory exceeded");
1257 }
1258 else
1259 #endif /* YYERROR_VERBOSE */
1260 yyerror("parse error");
1261 }
1262
1263 goto yyerrlab1;
1264 yyerrlab1: /* here on error raised explicitly by an action */
1265
1266 if (yyerrstatus == 3)
1267 {
1268 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1269
1270 /* return failure if at end of input */
1271 if (yychar == YYEOF)
1272 YYABORT;
1273
1274 #if YYDEBUG != 0
1275 if (yydebug)
1276 fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1277 #endif
1278
1279 yychar = YYEMPTY;
1280 }
1281
1282 /* Else will try to reuse lookahead token
1283 after shifting the error token. */
1284
1285 yyerrstatus = 3; /* Each real token shifted decrements this */
1286
1287 goto yyerrhandle;
1288
1289 yyerrdefault: /* current state does not do anything special for the error token. */
1290
1291 #if 0
1292 /* This is wrong; only states that explicitly want error tokens
1293 should shift them. */
1294 yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1295 if (yyn) goto yydefault;
1296 #endif
1297
1298 yyerrpop: /* pop the current state because it cannot handle the error token */
1299
1300 if (yyssp == yyss) YYABORT;
1301 yyvsp--;
1302 yystate = *--yyssp;
1303 #ifdef YYLSP_NEEDED
1304 yylsp--;
1305 #endif
1306
1307 #if YYDEBUG != 0
1308 if (yydebug)
1309 {
1310 short *ssp1 = yyss - 1;
1311 fprintf (stderr, "Error: state stack now");
1312 while (ssp1 != yyssp)
1313 fprintf (stderr, " %d", *++ssp1);
1314 fprintf (stderr, "\n");
1315 }
1316 #endif
1317
1318 yyerrhandle:
1319
1320 yyn = yypact[yystate];
1321 if (yyn == YYFLAG)
1322 goto yyerrdefault;
1323
1324 yyn += YYTERROR;
1325 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1326 goto yyerrdefault;
1327
1328 yyn = yytable[yyn];
1329 if (yyn < 0)
1330 {
1331 if (yyn == YYFLAG)
1332 goto yyerrpop;
1333 yyn = -yyn;
1334 goto yyreduce;
1335 }
1336 else if (yyn == 0)
1337 goto yyerrpop;
1338
1339 if (yyn == YYFINAL)
1340 YYACCEPT;
1341
1342 #if YYDEBUG != 0
1343 if (yydebug)
1344 fprintf(stderr, "Shifting error token, ");
1345 #endif
1346
1347 *++yyvsp = yylval;
1348 #ifdef YYLSP_NEEDED
1349 *++yylsp = yylloc;
1350 #endif
1351
1352 yystate = yyn;
1353 goto yynewstate;
1354
1355 yyacceptlab:
1356 /* YYACCEPT comes here. */
1357 if (yyfree_stacks)
1358 {
1359 free (yyss);
1360 free (yyvs);
1361 #ifdef YYLSP_NEEDED
1362 free (yyls);
1363 #endif
1364 }
1365 return 0;
1366
1367 yyabortlab:
1368 /* YYABORT comes here. */
1369 if (yyfree_stacks)
1370 {
1371 free (yyss);
1372 free (yyvs);
1373 #ifdef YYLSP_NEEDED
1374 free (yyls);
1375 #endif
1376 }
1377 return 1;
1378 }
1379 #line 363 "getdate.y"
1380
1381
1382 /* Month and day table. */
1383 static TABLE const MonthDayTable[] = {
1384 { "january", tMONTH, 1 },
1385 { "february", tMONTH, 2 },
1386 { "march", tMONTH, 3 },
1387 { "april", tMONTH, 4 },
1388 { "may", tMONTH, 5 },
1389 { "june", tMONTH, 6 },
1390 { "july", tMONTH, 7 },
1391 { "august", tMONTH, 8 },
1392 { "september", tMONTH, 9 },
1393 { "sept", tMONTH, 9 },
1394 { "october", tMONTH, 10 },
1395 { "november", tMONTH, 11 },
1396 { "december", tMONTH, 12 },
1397 { "sunday", tDAY, 0 },
1398 { "monday", tDAY, 1 },
1399 { "tuesday", tDAY, 2 },
1400 { "tues", tDAY, 2 },
1401 { "wednesday", tDAY, 3 },
1402 { "wednes", tDAY, 3 },
1403 { "thursday", tDAY, 4 },
1404 { "thur", tDAY, 4 },
1405 { "thurs", tDAY, 4 },
1406 { "friday", tDAY, 5 },
1407 { "saturday", tDAY, 6 },
1408 { NULL }
1409 };
1410
1411 /* Time units table. */
1412 static TABLE const UnitsTable[] = {
1413 { "year", tMONTH_UNIT, 12 },
1414 { "month", tMONTH_UNIT, 1 },
1415 { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
1416 { "week", tMINUTE_UNIT, 7 * 24 * 60 },
1417 { "day", tMINUTE_UNIT, 1 * 24 * 60 },
1418 { "hour", tMINUTE_UNIT, 60 },
1419 { "minute", tMINUTE_UNIT, 1 },
1420 { "min", tMINUTE_UNIT, 1 },
1421 { "second", tSEC_UNIT, 1 },
1422 { "sec", tSEC_UNIT, 1 },
1423 { NULL }
1424 };
1425
1426 /* Assorted relative-time words. */
1427 static TABLE const OtherTable[] = {
1428 { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
1429 { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
1430 { "today", tMINUTE_UNIT, 0 },
1431 { "now", tMINUTE_UNIT, 0 },
1432 { "last", tUNUMBER, -1 },
1433 { "this", tMINUTE_UNIT, 0 },
1434 { "next", tUNUMBER, 2 },
1435 { "first", tUNUMBER, 1 },
1436 /* { "second", tUNUMBER, 2 }, */
1437 { "third", tUNUMBER, 3 },
1438 { "fourth", tUNUMBER, 4 },
1439 { "fifth", tUNUMBER, 5 },
1440 { "sixth", tUNUMBER, 6 },
1441 { "seventh", tUNUMBER, 7 },
1442 { "eighth", tUNUMBER, 8 },
1443 { "ninth", tUNUMBER, 9 },
1444 { "tenth", tUNUMBER, 10 },
1445 { "eleventh", tUNUMBER, 11 },
1446 { "twelfth", tUNUMBER, 12 },
1447 { "ago", tAGO, 1 },
1448 { NULL }
1449 };
1450
1451 /* The timezone table. */
1452 /* Some of these are commented out because a time_t can't store a float. */
1453 static TABLE const TimezoneTable[] = {
1454 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
1455 { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
1456 { "utc", tZONE, HOUR( 0) },
1457 { "wet", tZONE, HOUR( 0) }, /* Western European */
1458 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
1459 { "wat", tZONE, HOUR( 1) }, /* West Africa */
1460 { "at", tZONE, HOUR( 2) }, /* Azores */
1461 #if 0
1462 /* For completeness. BST is also British Summer, and GST is
1463 * also Guam Standard. */
1464 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
1465 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
1466 #endif
1467 #if 0
1468 { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
1469 { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
1470 { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
1471 #endif
1472 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
1473 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
1474 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
1475 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
1476 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
1477 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
1478 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
1479 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
1480 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
1481 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
1482 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
1483 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
1484 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
1485 { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
1486 { "cat", tZONE, HOUR(10) }, /* Central Alaska */
1487 { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
1488 { "nt", tZONE, HOUR(11) }, /* Nome */
1489 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
1490 { "cet", tZONE, -HOUR(1) }, /* Central European */
1491 { "met", tZONE, -HOUR(1) }, /* Middle European */
1492 { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
1493 { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
1494 { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
1495 { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
1496 { "fwt", tZONE, -HOUR(1) }, /* French Winter */
1497 { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
1498 { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
1499 { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
1500 #if 0
1501 { "it", tZONE, -HOUR(3.5) },/* Iran */
1502 #endif
1503 { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
1504 { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
1505 #if 0
1506 { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
1507 #endif
1508 { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
1509 #if 0
1510 /* For completeness. NST is also Newfoundland Stanard, and SST is
1511 * also Swedish Summer. */
1512 { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
1513 { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
1514 #endif /* 0 */
1515 { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
1516 { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
1517 #if 0
1518 { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
1519 #endif
1520 { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
1521 { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
1522 #if 0
1523 { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
1524 { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
1525 #endif
1526 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
1527 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
1528 { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
1529 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
1530 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
1531 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
1532 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
1533 { NULL }
1534 };
1535
1536 /* Military timezone table. */
1537 static TABLE const MilitaryTable[] = {
1538 { "a", tZONE, HOUR( 1) },
1539 { "b", tZONE, HOUR( 2) },
1540 { "c", tZONE, HOUR( 3) },
1541 { "d", tZONE, HOUR( 4) },
1542 { "e", tZONE, HOUR( 5) },
1543 { "f", tZONE, HOUR( 6) },
1544 { "g", tZONE, HOUR( 7) },
1545 { "h", tZONE, HOUR( 8) },
1546 { "i", tZONE, HOUR( 9) },
1547 { "k", tZONE, HOUR( 10) },
1548 { "l", tZONE, HOUR( 11) },
1549 { "m", tZONE, HOUR( 12) },
1550 { "n", tZONE, HOUR(- 1) },
1551 { "o", tZONE, HOUR(- 2) },
1552 { "p", tZONE, HOUR(- 3) },
1553 { "q", tZONE, HOUR(- 4) },
1554 { "r", tZONE, HOUR(- 5) },
1555 { "s", tZONE, HOUR(- 6) },
1556 { "t", tZONE, HOUR(- 7) },
1557 { "u", tZONE, HOUR(- 8) },
1558 { "v", tZONE, HOUR(- 9) },
1559 { "w", tZONE, HOUR(-10) },
1560 { "x", tZONE, HOUR(-11) },
1561 { "y", tZONE, HOUR(-12) },
1562 { "z", tZONE, HOUR( 0) },
1563 { NULL }
1564 };
1565
1566
1567
1568
1569 /* ARGSUSED */
1570 static int
yyerror(s)1571 yyerror(s)
1572 char *s;
1573 {
1574 return 0;
1575 }
1576
1577
1578 static time_t
ToSeconds(Hours,Minutes,Seconds,Meridian)1579 ToSeconds(Hours, Minutes, Seconds, Meridian)
1580 time_t Hours;
1581 time_t Minutes;
1582 time_t Seconds;
1583 MERIDIAN Meridian;
1584 {
1585 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
1586 return -1;
1587 switch (Meridian) {
1588 case MER24:
1589 if (Hours < 0 || Hours > 23)
1590 return -1;
1591 return (Hours * 60L + Minutes) * 60L + Seconds;
1592 case MERam:
1593 if (Hours < 1 || Hours > 12)
1594 return -1;
1595 if (Hours == 12)
1596 Hours = 0;
1597 return (Hours * 60L + Minutes) * 60L + Seconds;
1598 case MERpm:
1599 if (Hours < 1 || Hours > 12)
1600 return -1;
1601 if (Hours == 12)
1602 Hours = 0;
1603 return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
1604 default:
1605 abort ();
1606 }
1607 /* NOTREACHED */
1608 }
1609
1610
1611 /* Year is either
1612 * A negative number, which means to use its absolute value (why?)
1613 * A number from 0 to 99, which means a year from 1900 to 1999, or
1614 * The actual year (>=100). */
1615 static time_t
Convert(Month,Day,Year,Hours,Minutes,Seconds,Meridian,DSTmode)1616 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
1617 time_t Month;
1618 time_t Day;
1619 time_t Year;
1620 time_t Hours;
1621 time_t Minutes;
1622 time_t Seconds;
1623 MERIDIAN Meridian;
1624 DSTMODE DSTmode;
1625 {
1626 static int DaysInMonth[12] = {
1627 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1628 };
1629 time_t tod;
1630 time_t Julian;
1631 int i;
1632
1633 if (Year < 0)
1634 Year = -Year;
1635 if (Year < 69)
1636 Year += 2000;
1637 else if (Year < 100)
1638 Year += 1900;
1639 DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
1640 ? 29 : 28;
1641 /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
1642 I'm too lazy to try to check for time_t overflow in another way. */
1643 if (Year < EPOCH || Year > 2038
1644 || Month < 1 || Month > 12
1645 /* Lint fluff: "conversion from long may lose accuracy" */
1646 || Day < 1 || Day > DaysInMonth[(int)--Month])
1647 return -1;
1648
1649 for (Julian = Day - 1, i = 0; i < Month; i++)
1650 Julian += DaysInMonth[i];
1651 for (i = EPOCH; i < Year; i++)
1652 Julian += 365 + (i % 4 == 0);
1653 Julian *= SECSPERDAY;
1654 Julian += yyTimezone * 60L;
1655 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
1656 return -1;
1657 Julian += tod;
1658 if (DSTmode == DSTon
1659 || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
1660 Julian -= 60 * 60;
1661 return Julian;
1662 }
1663
1664
1665 static time_t
DSTcorrect(Start,Future)1666 DSTcorrect(Start, Future)
1667 time_t Start;
1668 time_t Future;
1669 {
1670 time_t StartDay;
1671 time_t FutureDay;
1672
1673 StartDay = (localtime(&Start)->tm_hour + 1) % 24;
1674 FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
1675 return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
1676 }
1677
1678
1679 static time_t
RelativeDate(Start,DayOrdinal,DayNumber)1680 RelativeDate(Start, DayOrdinal, DayNumber)
1681 time_t Start;
1682 time_t DayOrdinal;
1683 time_t DayNumber;
1684 {
1685 struct tm *tm;
1686 time_t now;
1687
1688 now = Start;
1689 tm = localtime(&now);
1690 now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
1691 now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
1692 return DSTcorrect(Start, now);
1693 }
1694
1695
1696 static time_t
RelativeMonth(Start,RelMonth)1697 RelativeMonth(Start, RelMonth)
1698 time_t Start;
1699 time_t RelMonth;
1700 {
1701 struct tm *tm;
1702 time_t Month;
1703 time_t Year;
1704
1705 if (RelMonth == 0)
1706 return 0;
1707 tm = localtime(&Start);
1708 Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
1709 Year = Month / 12;
1710 Month = Month % 12 + 1;
1711 return DSTcorrect(Start,
1712 Convert(Month, (time_t)tm->tm_mday, Year,
1713 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
1714 MER24, DSTmaybe));
1715 }
1716
1717
1718 static int
LookupWord(buff)1719 LookupWord(buff)
1720 char *buff;
1721 {
1722 register char *p;
1723 register char *q;
1724 register const TABLE *tp;
1725 int i;
1726 int abbrev;
1727
1728 /* Make it lowercase. */
1729 for (p = buff; *p; p++)
1730 if (isupper(*p))
1731 *p = tolower(*p);
1732
1733 if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
1734 yylval.Meridian = MERam;
1735 return tMERIDIAN;
1736 }
1737 if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
1738 yylval.Meridian = MERpm;
1739 return tMERIDIAN;
1740 }
1741
1742 /* See if we have an abbreviation for a month. */
1743 if (strlen(buff) == 3)
1744 abbrev = 1;
1745 else if (strlen(buff) == 4 && buff[3] == '.') {
1746 abbrev = 1;
1747 buff[3] = '\0';
1748 }
1749 else
1750 abbrev = 0;
1751
1752 for (tp = MonthDayTable; tp->name; tp++) {
1753 if (abbrev) {
1754 if (strncmp(buff, tp->name, 3) == 0) {
1755 yylval.Number = tp->value;
1756 return tp->type;
1757 }
1758 }
1759 else if (strcmp(buff, tp->name) == 0) {
1760 yylval.Number = tp->value;
1761 return tp->type;
1762 }
1763 }
1764
1765 for (tp = TimezoneTable; tp->name; tp++)
1766 if (strcmp(buff, tp->name) == 0) {
1767 yylval.Number = tp->value;
1768 return tp->type;
1769 }
1770
1771 if (strcmp(buff, "dst") == 0)
1772 return tDST;
1773
1774 for (tp = UnitsTable; tp->name; tp++)
1775 if (strcmp(buff, tp->name) == 0) {
1776 yylval.Number = tp->value;
1777 return tp->type;
1778 }
1779
1780 /* Strip off any plural and try the units table again. */
1781 i = strlen(buff) - 1;
1782 if (buff[i] == 's') {
1783 buff[i] = '\0';
1784 for (tp = UnitsTable; tp->name; tp++)
1785 if (strcmp(buff, tp->name) == 0) {
1786 yylval.Number = tp->value;
1787 return tp->type;
1788 }
1789 buff[i] = 's'; /* Put back for "this" in OtherTable. */
1790 }
1791
1792 for (tp = OtherTable; tp->name; tp++)
1793 if (strcmp(buff, tp->name) == 0) {
1794 yylval.Number = tp->value;
1795 return tp->type;
1796 }
1797
1798 /* Military timezones. */
1799 if (buff[1] == '\0' && isalpha(*buff)) {
1800 for (tp = MilitaryTable; tp->name; tp++)
1801 if (strcmp(buff, tp->name) == 0) {
1802 yylval.Number = tp->value;
1803 return tp->type;
1804 }
1805 }
1806
1807 /* Drop out any periods and try the timezone table again. */
1808 for (i = 0, p = q = buff; *q; q++)
1809 if (*q != '.')
1810 *p++ = *q;
1811 else
1812 i++;
1813 *p = '\0';
1814 if (i)
1815 for (tp = TimezoneTable; tp->name; tp++)
1816 if (strcmp(buff, tp->name) == 0) {
1817 yylval.Number = tp->value;
1818 return tp->type;
1819 }
1820
1821 return tID;
1822 }
1823
1824
1825 static int
yylex()1826 yylex()
1827 {
1828 register char c;
1829 register char *p;
1830 char buff[20];
1831 int Count;
1832 int sign;
1833
1834 for ( ; ; ) {
1835 while (isspace(*yyInput))
1836 yyInput++;
1837
1838 if (isdigit(c = *yyInput) || c == '-' || c == '+') {
1839 if (c == '-' || c == '+') {
1840 sign = c == '-' ? -1 : 1;
1841 if (!isdigit(*++yyInput))
1842 /* skip the '-' sign */
1843 continue;
1844 }
1845 else
1846 sign = 0;
1847 for (yylval.Number = 0; isdigit(c = *yyInput++); )
1848 yylval.Number = 10 * yylval.Number + c - '0';
1849 yyInput--;
1850 if (sign < 0)
1851 yylval.Number = -yylval.Number;
1852 return sign ? tSNUMBER : tUNUMBER;
1853 }
1854 if (isalpha(c)) {
1855 for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
1856 if (p < &buff[sizeof buff - 1])
1857 *p++ = c;
1858 *p = '\0';
1859 yyInput--;
1860 return LookupWord(buff);
1861 }
1862 if (c != '(')
1863 return *yyInput++;
1864 Count = 0;
1865 do {
1866 c = *yyInput++;
1867 if (c == '\0')
1868 return c;
1869 if (c == '(')
1870 Count++;
1871 else if (c == ')')
1872 Count--;
1873 } while (Count > 0);
1874 }
1875 }
1876
1877 #define TM_YEAR_ORIGIN 1900
1878
1879 /* Yield A - B, measured in seconds. */
1880 static long
difftm(a,b)1881 difftm (a, b)
1882 struct tm *a, *b;
1883 {
1884 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
1885 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
1886 int days = (
1887 /* difference in day of year */
1888 a->tm_yday - b->tm_yday
1889 /* + intervening leap days */
1890 + ((ay >> 2) - (by >> 2))
1891 - (ay/100 - by/100)
1892 + ((ay/100 >> 2) - (by/100 >> 2))
1893 /* + difference in years * 365 */
1894 + (long)(ay-by) * 365
1895 );
1896 return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
1897 + (a->tm_min - b->tm_min))
1898 + (a->tm_sec - b->tm_sec));
1899 }
1900
1901 time_t
get_date(p)1902 get_date(p)
1903 char *p;
1904 {
1905 struct tm *tm, *gmt, gmtbuf;
1906 time_t Start;
1907 time_t tod;
1908 time_t now;
1909 time_t timezone;
1910
1911 yyInput = p;
1912 (void)time (&now);
1913
1914 gmt = gmtime (&now);
1915 if (gmt != NULL)
1916 {
1917 /* Make a copy, in case localtime modifies *tm (I think
1918 that comment now applies to *gmt, but I am too
1919 lazy to dig into how gmtime and locatime allocate the
1920 structures they return pointers to). */
1921 gmtbuf = *gmt;
1922 gmt = &gmtbuf;
1923 }
1924
1925 if (! (tm = localtime (&now)))
1926 return -1;
1927
1928 if (gmt != NULL)
1929 timezone = difftm (gmt, tm) / 60;
1930 else
1931 /* We are on a system like VMS, where the system clock is
1932 in local time and the system has no concept of timezones.
1933 Hopefully we can fake this out (for the case in which the
1934 user specifies no timezone) by just saying the timezone
1935 is zero. */
1936 timezone = 0;
1937
1938 if(tm->tm_isdst)
1939 timezone += 60;
1940
1941 tm = localtime(&now);
1942 yyYear = tm->tm_year + 1900;
1943 yyMonth = tm->tm_mon + 1;
1944 yyDay = tm->tm_mday;
1945 yyTimezone = timezone;
1946 yyDSTmode = DSTmaybe;
1947 yyHour = 0;
1948 yyMinutes = 0;
1949 yySeconds = 0;
1950 yyMeridian = MER24;
1951 yyRelSeconds = 0;
1952 yyRelMonth = 0;
1953 yyHaveDate = 0;
1954 yyHaveDay = 0;
1955 yyHaveRel = 0;
1956 yyHaveTime = 0;
1957 yyHaveZone = 0;
1958
1959 if (yyparse()
1960 || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
1961 return -1;
1962
1963 if (yyHaveDate || yyHaveTime || yyHaveDay) {
1964 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1965 yyMeridian, yyDSTmode);
1966 if (Start < 0)
1967 return -1;
1968 }
1969 else {
1970 Start = now;
1971 if (!yyHaveRel)
1972 Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
1973 }
1974
1975 Start += yyRelSeconds;
1976 Start += RelativeMonth(Start, yyRelMonth);
1977
1978 if (yyHaveDay && !yyHaveDate) {
1979 tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
1980 Start += tod;
1981 }
1982
1983 /* Have to do *something* with a legitimate -1 so it's distinguishable
1984 * from the error return value. (Alternately could set errno on error.) */
1985 return Start == -1 ? 0 : Start;
1986 }
1987
1988
1989 #if defined(TEST)
1990
1991 /* ARGSUSED */
1992 int
main(ac,av)1993 main(ac, av)
1994 int ac;
1995 char *av[];
1996 {
1997 char buff[128];
1998 time_t d;
1999
2000 (void)printf("Enter date, or blank line to exit.\n\t> ");
2001 (void)fflush(stdout);
2002 while (gets(buff) && buff[0]) {
2003 d = get_date(buff);
2004 if (d == -1)
2005 (void)printf("Bad format - couldn't convert.\n");
2006 else
2007 (void)printf("%s", ctime(&d));
2008 (void)printf("\t> ");
2009 (void)fflush(stdout);
2010 }
2011 exit(0);
2012 /* NOTREACHED */
2013 }
2014 #endif /* defined(TEST) */
2015