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