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 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 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 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 1571 yyerror(s) 1572 char *s; 1573 { 1574 return 0; 1575 } 1576 1577 1578 static time_t 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 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 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 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 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 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 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 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 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 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