1 Return-Path: <jani@nikula.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id A79F6429E32
\r
6 for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:24:12 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
8 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"
\r
12 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5
\r
13 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
14 Received: from olra.theworths.org ([127.0.0.1])
\r
15 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
16 with ESMTP id xnBI7q+EKNjw for <notmuch@notmuchmail.org>;
\r
17 Wed, 10 Aug 2011 03:23:38 -0700 (PDT)
\r
18 Received: from mail-qw0-f53.google.com (mail-qw0-f53.google.com
\r
19 [209.85.216.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))
\r
20 (No client certificate requested)
\r
21 by olra.theworths.org (Postfix) with ESMTPS id C5CA4429E30
\r
22 for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:23:35 -0700 (PDT)
\r
23 Received: by mail-qw0-f53.google.com with SMTP id 7so539114qwb.26
\r
24 for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:22:16 -0700 (PDT)
\r
25 Received: by 10.229.66.222 with SMTP id o30mr6166147qci.189.1312971735811;
\r
26 Wed, 10 Aug 2011 03:22:15 -0700 (PDT)
\r
27 Received: from localhost (nikula.org [92.243.24.172])
\r
28 by mx.google.com with ESMTPS id m7sm714311qct.17.2011.08.10.03.22.12
\r
29 (version=TLSv1/SSLv3 cipher=OTHER);
\r
30 Wed, 10 Aug 2011 03:22:14 -0700 (PDT)
\r
31 From: Jani Nikula <jani@nikula.org>
\r
32 To: notmuch@notmuchmail.org
\r
33 Subject: [RFC PATCH 1/3] Import date/time parser from GNU coreutils
\r
34 Date: Wed, 10 Aug 2011 10:22:05 +0000
\r
36 <92e838734a58ff6d89c8ce47a32aa1c33e31cc3e.1312964528.git.jani@nikula.org>
\r
37 X-Mailer: git-send-email 1.7.1
\r
38 In-Reply-To: <cover.1312964528.git.jani@nikula.org>
\r
39 References: <cover.1312964528.git.jani@nikula.org>
\r
40 In-Reply-To: <cover.1312964528.git.jani@nikula.org>
\r
41 References: <cover.1312964528.git.jani@nikula.org>
\r
42 X-Mailman-Approved-At: Wed, 24 Aug 2011 16:29:30 -0700
\r
43 Cc: amdragon@mit.edu
\r
44 X-BeenThere: notmuch@notmuchmail.org
\r
45 X-Mailman-Version: 2.1.13
\r
47 List-Id: "Use and development of the notmuch mail system."
\r
48 <notmuch.notmuchmail.org>
\r
49 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
50 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
51 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
52 List-Post: <mailto:notmuch@notmuchmail.org>
\r
53 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
54 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
55 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
56 X-List-Received-Date: Wed, 10 Aug 2011 10:24:13 -0000
\r
58 From: Michal Sojka <sojkam1@fel.cvut.cz>
\r
60 This function have quite a lot dependencies. We may reduce them later it
\r
63 lib/c-ctype.c | 398 +++++++
\r
64 lib/c-ctype.h | 297 +++++
\r
65 lib/getdate.c | 3497 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\r
66 lib/getdate.h | 22 +
\r
67 lib/getdate.y | 1572 +++++++++++++++++++++++++
\r
68 lib/gettime.c | 48 +
\r
69 lib/intprops.h | 83 ++
\r
70 lib/timespec.h | 39 +
\r
71 lib/verify.h | 140 +++
\r
72 9 files changed, 6096 insertions(+), 0 deletions(-)
\r
73 create mode 100644 lib/c-ctype.c
\r
74 create mode 100644 lib/c-ctype.h
\r
75 create mode 100644 lib/getdate.c
\r
76 create mode 100644 lib/getdate.h
\r
77 create mode 100644 lib/getdate.y
\r
78 create mode 100644 lib/gettime.c
\r
79 create mode 100644 lib/gettime.h
\r
80 create mode 100644 lib/intprops.h
\r
81 create mode 100644 lib/timespec.h
\r
82 create mode 100644 lib/verify.h
\r
84 diff --git a/lib/c-ctype.c b/lib/c-ctype.c
\r
85 new file mode 100644
\r
86 index 0000000..48baa72
\r
90 +/* -*- buffer-read-only: t -*- vi: set ro: */
\r
91 +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
\r
92 +/* Character handling in C locale.
\r
94 + Copyright 2000-2003, 2006, 2009-2010 Free Software Foundation, Inc.
\r
96 +This program is free software; you can redistribute it and/or modify
\r
97 +it under the terms of the GNU General Public License as published by
\r
98 +the Free Software Foundation; either version 3 of the License, or
\r
99 +(at your option) any later version.
\r
101 +This program is distributed in the hope that it will be useful,
\r
102 +but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
103 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
104 +GNU General Public License for more details.
\r
106 +You should have received a copy of the GNU General Public License
\r
107 +along with this program; if not, write to the Free Software Foundation,
\r
108 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
\r
110 +#include <config.h>
\r
112 +/* Specification. */
\r
113 +#define NO_C_CTYPE_MACROS
\r
114 +#include "c-ctype.h"
\r
116 +/* The function isascii is not locale dependent. Its use in EBCDIC is
\r
121 + return (c >= 0x00 && c <= 0x7f);
\r
127 +#if C_CTYPE_CONSECUTIVE_DIGITS \
\r
128 + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
130 + return ((c >= '0' && c <= '9')
\r
131 + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'));
\r
133 + return ((c >= '0' && c <= '9')
\r
134 + || (c >= 'A' && c <= 'Z')
\r
135 + || (c >= 'a' && c <= 'z'));
\r
140 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
141 + case '6': case '7': case '8': case '9':
\r
142 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
143 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
144 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
145 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
146 + case 'Y': case 'Z':
\r
147 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
148 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
149 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
150 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
151 + case 'y': case 'z':
\r
162 +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
164 + return ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z');
\r
166 + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
\r
171 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
172 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
173 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
174 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
175 + case 'Y': case 'Z':
\r
176 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
177 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
178 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
179 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
180 + case 'y': case 'z':
\r
191 + return (c == ' ' || c == '\t');
\r
198 + return ((c & ~0x1f) == 0 || c == 0x7f);
\r
202 + case ' ': case '!': case '"': case '#': case '$': case '%':
\r
203 + case '&': case '\'': case '(': case ')': case '*': case '+':
\r
204 + case ',': case '-': case '.': case '/':
\r
205 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
206 + case '6': case '7': case '8': case '9':
\r
207 + case ':': case ';': case '<': case '=': case '>': case '?':
\r
209 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
210 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
211 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
212 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
213 + case 'Y': case 'Z':
\r
214 + case '[': case '\\': case ']': case '^': case '_': case '`':
\r
215 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
216 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
217 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
218 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
219 + case 'y': case 'z':
\r
220 + case '{': case '|': case '}': case '~':
\r
231 +#if C_CTYPE_CONSECUTIVE_DIGITS
\r
232 + return (c >= '0' && c <= '9');
\r
236 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
237 + case '6': case '7': case '8': case '9':
\r
248 +#if C_CTYPE_CONSECUTIVE_LOWERCASE
\r
249 + return (c >= 'a' && c <= 'z');
\r
253 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
254 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
255 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
256 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
257 + case 'y': case 'z':
\r
269 + return (c >= '!' && c <= '~');
\r
273 + case '!': case '"': case '#': case '$': case '%': case '&':
\r
274 + case '\'': case '(': case ')': case '*': case '+': case ',':
\r
275 + case '-': case '.': case '/':
\r
276 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
277 + case '6': case '7': case '8': case '9':
\r
278 + case ':': case ';': case '<': case '=': case '>': case '?':
\r
280 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
281 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
282 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
283 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
284 + case 'Y': case 'Z':
\r
285 + case '[': case '\\': case ']': case '^': case '_': case '`':
\r
286 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
287 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
288 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
289 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
290 + case 'y': case 'z':
\r
291 + case '{': case '|': case '}': case '~':
\r
303 + return (c >= ' ' && c <= '~');
\r
307 + case ' ': case '!': case '"': case '#': case '$': case '%':
\r
308 + case '&': case '\'': case '(': case ')': case '*': case '+':
\r
309 + case ',': case '-': case '.': case '/':
\r
310 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
311 + case '6': case '7': case '8': case '9':
\r
312 + case ':': case ';': case '<': case '=': case '>': case '?':
\r
314 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
315 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
316 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
317 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
318 + case 'Y': case 'Z':
\r
319 + case '[': case '\\': case ']': case '^': case '_': case '`':
\r
320 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
321 + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
\r
322 + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
\r
323 + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
\r
324 + case 'y': case 'z':
\r
325 + case '{': case '|': case '}': case '~':
\r
337 + return ((c >= '!' && c <= '~')
\r
338 + && !((c >= '0' && c <= '9')
\r
339 + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')));
\r
343 + case '!': case '"': case '#': case '$': case '%': case '&':
\r
344 + case '\'': case '(': case ')': case '*': case '+': case ',':
\r
345 + case '-': case '.': case '/':
\r
346 + case ':': case ';': case '<': case '=': case '>': case '?':
\r
348 + case '[': case '\\': case ']': case '^': case '_': case '`':
\r
349 + case '{': case '|': case '}': case '~':
\r
360 + return (c == ' ' || c == '\t'
\r
361 + || c == '\n' || c == '\v' || c == '\f' || c == '\r');
\r
367 +#if C_CTYPE_CONSECUTIVE_UPPERCASE
\r
368 + return (c >= 'A' && c <= 'Z');
\r
372 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
373 + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
\r
374 + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
\r
375 + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
\r
376 + case 'Y': case 'Z':
\r
385 +c_isxdigit (int c)
\r
387 +#if C_CTYPE_CONSECUTIVE_DIGITS \
\r
388 + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
390 + return ((c >= '0' && c <= '9')
\r
391 + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F'));
\r
393 + return ((c >= '0' && c <= '9')
\r
394 + || (c >= 'A' && c <= 'F')
\r
395 + || (c >= 'a' && c <= 'f'));
\r
400 + case '0': case '1': case '2': case '3': case '4': case '5':
\r
401 + case '6': case '7': case '8': case '9':
\r
402 + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
\r
403 + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
\r
414 +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
415 + return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
\r
419 + case 'A': return 'a';
\r
420 + case 'B': return 'b';
\r
421 + case 'C': return 'c';
\r
422 + case 'D': return 'd';
\r
423 + case 'E': return 'e';
\r
424 + case 'F': return 'f';
\r
425 + case 'G': return 'g';
\r
426 + case 'H': return 'h';
\r
427 + case 'I': return 'i';
\r
428 + case 'J': return 'j';
\r
429 + case 'K': return 'k';
\r
430 + case 'L': return 'l';
\r
431 + case 'M': return 'm';
\r
432 + case 'N': return 'n';
\r
433 + case 'O': return 'o';
\r
434 + case 'P': return 'p';
\r
435 + case 'Q': return 'q';
\r
436 + case 'R': return 'r';
\r
437 + case 'S': return 's';
\r
438 + case 'T': return 't';
\r
439 + case 'U': return 'u';
\r
440 + case 'V': return 'v';
\r
441 + case 'W': return 'w';
\r
442 + case 'X': return 'x';
\r
443 + case 'Y': return 'y';
\r
444 + case 'Z': return 'z';
\r
445 + default: return c;
\r
453 +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
454 + return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
\r
458 + case 'a': return 'A';
\r
459 + case 'b': return 'B';
\r
460 + case 'c': return 'C';
\r
461 + case 'd': return 'D';
\r
462 + case 'e': return 'E';
\r
463 + case 'f': return 'F';
\r
464 + case 'g': return 'G';
\r
465 + case 'h': return 'H';
\r
466 + case 'i': return 'I';
\r
467 + case 'j': return 'J';
\r
468 + case 'k': return 'K';
\r
469 + case 'l': return 'L';
\r
470 + case 'm': return 'M';
\r
471 + case 'n': return 'N';
\r
472 + case 'o': return 'O';
\r
473 + case 'p': return 'P';
\r
474 + case 'q': return 'Q';
\r
475 + case 'r': return 'R';
\r
476 + case 's': return 'S';
\r
477 + case 't': return 'T';
\r
478 + case 'u': return 'U';
\r
479 + case 'v': return 'V';
\r
480 + case 'w': return 'W';
\r
481 + case 'x': return 'X';
\r
482 + case 'y': return 'Y';
\r
483 + case 'z': return 'Z';
\r
484 + default: return c;
\r
488 diff --git a/lib/c-ctype.h b/lib/c-ctype.h
\r
489 new file mode 100644
\r
490 index 0000000..26c89b8
\r
492 +++ b/lib/c-ctype.h
\r
494 +/* -*- buffer-read-only: t -*- vi: set ro: */
\r
495 +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
\r
496 +/* Character handling in C locale.
\r
498 + These functions work like the corresponding functions in <ctype.h>,
\r
499 + except that they have the C (POSIX) locale hardwired, whereas the
\r
500 + <ctype.h> functions' behaviour depends on the current locale set via
\r
503 + Copyright (C) 2000-2003, 2006, 2008-2010 Free Software Foundation, Inc.
\r
505 +This program is free software; you can redistribute it and/or modify
\r
506 +it under the terms of the GNU General Public License as published by
\r
507 +the Free Software Foundation; either version 3 of the License, or
\r
508 +(at your option) any later version.
\r
510 +This program is distributed in the hope that it will be useful,
\r
511 +but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
512 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
513 +GNU General Public License for more details.
\r
515 +You should have received a copy of the GNU General Public License
\r
516 +along with this program; if not, write to the Free Software Foundation,
\r
517 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
\r
522 +#include <stdbool.h>
\r
525 +#ifdef __cplusplus
\r
530 +/* The functions defined in this file assume the "C" locale and a character
\r
531 + set without diacritics (ASCII-US or EBCDIC-US or something like that).
\r
532 + Even if the "C" locale on a particular system is an extension of the ASCII
\r
533 + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
\r
534 + is ISO-8859-1), the functions in this file recognize only the ASCII
\r
538 +/* Check whether the ASCII optimizations apply. */
\r
540 +/* ANSI C89 (and ISO C99 5.2.1.3 too) already guarantees that
\r
541 + '0', '1', ..., '9' have consecutive integer values. */
\r
542 +#define C_CTYPE_CONSECUTIVE_DIGITS 1
\r
544 +#if ('A' <= 'Z') \
\r
545 + && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \
\r
546 + && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \
\r
547 + && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \
\r
548 + && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \
\r
549 + && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \
\r
550 + && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \
\r
551 + && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \
\r
552 + && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \
\r
553 + && ('Y' + 1 == 'Z')
\r
554 +#define C_CTYPE_CONSECUTIVE_UPPERCASE 1
\r
557 +#if ('a' <= 'z') \
\r
558 + && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \
\r
559 + && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \
\r
560 + && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \
\r
561 + && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \
\r
562 + && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \
\r
563 + && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \
\r
564 + && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \
\r
565 + && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \
\r
566 + && ('y' + 1 == 'z')
\r
567 +#define C_CTYPE_CONSECUTIVE_LOWERCASE 1
\r
570 +#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
\r
571 + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
\r
572 + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
\r
573 + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
\r
574 + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
\r
575 + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
\r
576 + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
\r
577 + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
\r
578 + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
\r
579 + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
\r
580 + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
\r
581 + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
\r
582 + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
\r
583 + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
\r
584 + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
\r
585 + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
\r
586 + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
\r
587 + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
\r
588 + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
\r
589 + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
\r
590 + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
\r
591 + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
\r
592 + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
\r
593 +/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
\r
594 + Testing the value of '\n' and '\r' is not relevant. */
\r
595 +#define C_CTYPE_ASCII 1
\r
599 +/* Function declarations. */
\r
601 +/* Unlike the functions in <ctype.h>, which require an argument in the range
\r
602 + of the 'unsigned char' type, the functions here operate on values that are
\r
603 + in the 'unsigned char' range or in the 'char' range. In other words,
\r
604 + when you have a 'char' value, you need to cast it before using it as
\r
605 + argument to a <ctype.h> function:
\r
607 + const char *s = ...;
\r
608 + if (isalpha ((unsigned char) *s)) ...
\r
610 + but you don't need to cast it for the functions defined in this file:
\r
612 + const char *s = ...;
\r
613 + if (c_isalpha (*s)) ...
\r
616 +extern bool c_isascii (int c); /* not locale dependent */
\r
618 +extern bool c_isalnum (int c);
\r
619 +extern bool c_isalpha (int c);
\r
620 +extern bool c_isblank (int c);
\r
621 +extern bool c_iscntrl (int c);
\r
622 +extern bool c_isdigit (int c);
\r
623 +extern bool c_islower (int c);
\r
624 +extern bool c_isgraph (int c);
\r
625 +extern bool c_isprint (int c);
\r
626 +extern bool c_ispunct (int c);
\r
627 +extern bool c_isspace (int c);
\r
628 +extern bool c_isupper (int c);
\r
629 +extern bool c_isxdigit (int c);
\r
631 +extern int c_tolower (int c);
\r
632 +extern int c_toupper (int c);
\r
635 +#if defined __GNUC__ && defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ && !defined NO_C_CTYPE_MACROS
\r
637 +/* ASCII optimizations. */
\r
640 +#define c_isascii(c) \
\r
641 + ({ int __c = (c); \
\r
642 + (__c >= 0x00 && __c <= 0x7f); \
\r
645 +#if C_CTYPE_CONSECUTIVE_DIGITS \
\r
646 + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
649 +#define c_isalnum(c) \
\r
650 + ({ int __c = (c); \
\r
651 + ((__c >= '0' && __c <= '9') \
\r
652 + || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z')); \
\r
656 +#define c_isalnum(c) \
\r
657 + ({ int __c = (c); \
\r
658 + ((__c >= '0' && __c <= '9') \
\r
659 + || (__c >= 'A' && __c <= 'Z') \
\r
660 + || (__c >= 'a' && __c <= 'z')); \
\r
665 +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
668 +#define c_isalpha(c) \
\r
669 + ({ int __c = (c); \
\r
670 + ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z'); \
\r
674 +#define c_isalpha(c) \
\r
675 + ({ int __c = (c); \
\r
676 + ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \
\r
682 +#define c_isblank(c) \
\r
683 + ({ int __c = (c); \
\r
684 + (__c == ' ' || __c == '\t'); \
\r
689 +#define c_iscntrl(c) \
\r
690 + ({ int __c = (c); \
\r
691 + ((__c & ~0x1f) == 0 || __c == 0x7f); \
\r
695 +#if C_CTYPE_CONSECUTIVE_DIGITS
\r
697 +#define c_isdigit(c) \
\r
698 + ({ int __c = (c); \
\r
699 + (__c >= '0' && __c <= '9'); \
\r
703 +#if C_CTYPE_CONSECUTIVE_LOWERCASE
\r
705 +#define c_islower(c) \
\r
706 + ({ int __c = (c); \
\r
707 + (__c >= 'a' && __c <= 'z'); \
\r
713 +#define c_isgraph(c) \
\r
714 + ({ int __c = (c); \
\r
715 + (__c >= '!' && __c <= '~'); \
\r
721 +#define c_isprint(c) \
\r
722 + ({ int __c = (c); \
\r
723 + (__c >= ' ' && __c <= '~'); \
\r
729 +#define c_ispunct(c) \
\r
730 + ({ int _c = (c); \
\r
731 + (c_isgraph (_c) && ! c_isalnum (_c)); \
\r
736 +#define c_isspace(c) \
\r
737 + ({ int __c = (c); \
\r
738 + (__c == ' ' || __c == '\t' \
\r
739 + || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \
\r
742 +#if C_CTYPE_CONSECUTIVE_UPPERCASE
\r
744 +#define c_isupper(c) \
\r
745 + ({ int __c = (c); \
\r
746 + (__c >= 'A' && __c <= 'Z'); \
\r
750 +#if C_CTYPE_CONSECUTIVE_DIGITS \
\r
751 + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
754 +#define c_isxdigit(c) \
\r
755 + ({ int __c = (c); \
\r
756 + ((__c >= '0' && __c <= '9') \
\r
757 + || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'F')); \
\r
761 +#define c_isxdigit(c) \
\r
762 + ({ int __c = (c); \
\r
763 + ((__c >= '0' && __c <= '9') \
\r
764 + || (__c >= 'A' && __c <= 'F') \
\r
765 + || (__c >= 'a' && __c <= 'f')); \
\r
770 +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
\r
772 +#define c_tolower(c) \
\r
773 + ({ int __c = (c); \
\r
774 + (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \
\r
777 +#define c_toupper(c) \
\r
778 + ({ int __c = (c); \
\r
779 + (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \
\r
783 +#endif /* optimizing for speed */
\r
786 +#ifdef __cplusplus
\r
790 +#endif /* C_CTYPE_H */
\r
791 diff --git a/lib/getdate.c b/lib/getdate.c
\r
792 new file mode 100644
\r
793 index 0000000..5b20eeb
\r
795 +++ b/lib/getdate.c
\r
798 +/* A Bison parser, made by GNU Bison 2.4.1. */
\r
800 +/* Skeleton implementation for Bison's Yacc-like parsers in C
\r
802 + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
\r
803 + Free Software Foundation, Inc.
\r
805 + This program is free software: you can redistribute it and/or modify
\r
806 + it under the terms of the GNU General Public License as published by
\r
807 + the Free Software Foundation, either version 3 of the License, or
\r
808 + (at your option) any later version.
\r
810 + This program is distributed in the hope that it will be useful,
\r
811 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
812 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
813 + GNU General Public License for more details.
\r
815 + You should have received a copy of the GNU General Public License
\r
816 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
818 +/* As a special exception, you may create a larger work that contains
\r
819 + part or all of the Bison parser skeleton and distribute that work
\r
820 + under terms of your choice, so long as that work isn't itself a
\r
821 + parser generator using the skeleton or a modified version thereof
\r
822 + as a parser skeleton. Alternatively, if you modify or redistribute
\r
823 + the parser skeleton itself, you may (at your option) remove this
\r
824 + special exception, which will cause the skeleton and the resulting
\r
825 + Bison output files to be licensed under the GNU General Public
\r
826 + License without this special exception.
\r
828 + This special exception was added by the Free Software Foundation in
\r
829 + version 2.2 of Bison. */
\r
831 +/* C LALR(1) parser skeleton written by Richard Stallman, by
\r
832 + simplifying the original so-called "semantic" parser. */
\r
834 +/* All symbols defined below should begin with yy or YY, to avoid
\r
835 + infringing on user name space. This should be done even for local
\r
836 + variables, as they might otherwise be expanded by user macros.
\r
837 + There are some unavoidable exceptions within include files to
\r
838 + define necessary library symbols; they are noted "INFRINGES ON
\r
839 + USER NAME SPACE" below. */
\r
841 +/* Identify Bison output. */
\r
844 +/* Bison version. */
\r
845 +#define YYBISON_VERSION "2.4.1"
\r
847 +/* Skeleton name. */
\r
848 +#define YYSKELETON_NAME "yacc.c"
\r
850 +/* Pure parsers. */
\r
853 +/* Push parsers. */
\r
856 +/* Pull parsers. */
\r
859 +/* Using locations. */
\r
860 +#define YYLSP_NEEDED 0
\r
864 +/* Copy the first part of user declarations. */
\r
866 +/* Line 189 of yacc.c */
\r
867 +#line 1 "getdate.y"
\r
869 +/* Parse a string into an internal time stamp.
\r
871 + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
\r
872 + 2010 Free Software Foundation, Inc.
\r
874 + This program is free software: you can redistribute it and/or modify
\r
875 + it under the terms of the GNU General Public License as published by
\r
876 + the Free Software Foundation; either version 3 of the License, or
\r
877 + (at your option) any later version.
\r
879 + This program is distributed in the hope that it will be useful,
\r
880 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
881 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
882 + GNU General Public License for more details.
\r
884 + You should have received a copy of the GNU General Public License
\r
885 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
887 +/* Originally written by Steven M. Bellovin <smb@research.att.com> while
\r
888 + at the University of North Carolina at Chapel Hill. Later tweaked by
\r
889 + a couple of people on Usenet. Completely overhauled by Rich $alz
\r
890 + <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
\r
892 + Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
\r
893 + the right thing about local DST. Also modified by Paul Eggert
\r
894 + <eggert@cs.ucla.edu> in February 2004 to support
\r
895 + nanosecond-resolution time stamps, and in October 2004 to support
\r
896 + TZ strings in dates. */
\r
898 +/* FIXME: Check for arithmetic overflow in all cases, not just
\r
901 +#include <config.h>
\r
903 +#include "getdate.h"
\r
905 +#include "intprops.h"
\r
906 +#include "timespec.h"
\r
907 +#include "verify.h"
\r
909 +/* There's no need to extend the stack, so there's no need to involve
\r
911 +#define YYSTACK_USE_ALLOCA 0
\r
913 +/* Tell Bison how much stack space is needed. 20 should be plenty for
\r
914 + this grammar, which is not right recursive. Beware setting it too
\r
915 + high, since that might cause problems on machines whose
\r
916 + implementations have lame stack-overflow checking. */
\r
917 +#define YYMAXDEPTH 20
\r
918 +#define YYINITDEPTH YYMAXDEPTH
\r
920 +/* Since the code of getdate.y is not included in the Emacs executable
\r
921 + itself, there is no need to #define static in this file. Even if
\r
922 + the code were included in the Emacs executable, it probably
\r
923 + wouldn't do any harm to #undef it here; this will only cause
\r
924 + problems if we try to write to a static variable, which I don't
\r
925 + think this code needs to do. */
\r
930 +#include <c-ctype.h>
\r
931 +#include <limits.h>
\r
932 +#include <stdio.h>
\r
933 +#include <stdlib.h>
\r
934 +#include <string.h>
\r
936 +#include "xalloc.h"
\r
939 +/* ISDIGIT differs from isdigit, as follows:
\r
940 + - Its arg may be any int or unsigned int; it need not be an unsigned char
\r
942 + - It's typically faster.
\r
943 + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
\r
944 + isdigit unless it's important to use the locale's definition
\r
945 + of `digit' even when the host does not conform to POSIX. */
\r
946 +#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
\r
948 +/* Shift A right by B bits portably, by dividing A by 2**B and
\r
949 + truncating towards minus infinity. A and B should be free of side
\r
950 + effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
\r
951 + INT_BITS is the number of useful bits in an int. GNU code can
\r
952 + assume that INT_BITS is at least 32.
\r
954 + ISO C99 says that A >> B is implementation-defined if A < 0. Some
\r
955 + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
\r
956 + right in the usual way when A < 0, so SHR falls back on division if
\r
957 + ordinary A >> B doesn't seem to be the usual signed shift. */
\r
958 +#define SHR(a, b) \
\r
961 + : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
\r
963 +#define EPOCH_YEAR 1970
\r
964 +#define TM_YEAR_BASE 1900
\r
966 +#define HOUR(x) ((x) * 60)
\r
968 +/* long_time_t is a signed integer type that contains all time_t values. */
\r
969 +verify (TYPE_IS_INTEGER (time_t));
\r
970 +#if TIME_T_FITS_IN_LONG_INT
\r
971 +typedef long int long_time_t;
\r
973 +typedef time_t long_time_t;
\r
976 +/* Lots of this code assumes time_t and time_t-like values fit into
\r
978 +verify (TYPE_MINIMUM (long_time_t) <= TYPE_MINIMUM (time_t)
\r
979 + && TYPE_MAXIMUM (time_t) <= TYPE_MAXIMUM (long_time_t));
\r
981 +/* FIXME: It also assumes that signed integer overflow silently wraps around,
\r
982 + but this is not true any more with recent versions of GCC 4. */
\r
984 +/* An integer value, and the number of digits in its textual
\r
985 + representation. */
\r
993 +/* An entry in the lexical lookup table. */
\r
996 + char const *name;
\r
1001 +/* Meridian: am, pm, or 24-hour style. */
\r
1002 +enum { MERam, MERpm, MER24 };
\r
1004 +enum { BILLION = 1000000000, LOG10_BILLION = 9 };
\r
1006 +/* Relative times. */
\r
1009 + /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
1014 + long int minutes;
\r
1015 + long_time_t seconds;
\r
1019 +#if HAVE_COMPOUND_LITERALS
\r
1020 +# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
\r
1022 +static relative_time const RELATIVE_TIME_0;
\r
1025 +/* Information passed to and from the parser. */
\r
1028 + /* The input string remaining to be parsed. */
\r
1029 + const char *input;
\r
1031 + /* N, if this is the Nth Tuesday. */
\r
1032 + long int day_ordinal;
\r
1034 + /* Day of week; Sunday is 0. */
\r
1037 + /* tm_isdst flag for the local zone. */
\r
1038 + int local_isdst;
\r
1040 + /* Time zone, in minutes east of UTC. */
\r
1041 + long int time_zone;
\r
1043 + /* Style used for time. */
\r
1046 + /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
1051 + long int minutes;
\r
1052 + struct timespec seconds; /* includes nanoseconds */
\r
1054 + /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
1055 + relative_time rel;
\r
1057 + /* Presence or counts of nonterminals of various flavors parsed so far. */
\r
1058 + bool timespec_seen;
\r
1060 + size_t dates_seen;
\r
1061 + size_t days_seen;
\r
1062 + size_t local_zones_seen;
\r
1063 + size_t dsts_seen;
\r
1064 + size_t times_seen;
\r
1065 + size_t zones_seen;
\r
1067 + /* Table of local time zone abbrevations, terminated by a null entry. */
\r
1068 + table local_time_zone_table[3];
\r
1069 +} parser_control;
\r
1072 +static int yylex (union YYSTYPE *, parser_control *);
\r
1073 +static int yyerror (parser_control const *, char const *);
\r
1074 +static long int time_zone_hhmm (parser_control *, textint, long int);
\r
1076 +/* Extract into *PC any date and time info from a string of digits
\r
1077 + of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
\r
1080 +digits_to_date_time (parser_control *pc, textint text_int)
\r
1082 + if (pc->dates_seen && ! pc->year.digits
\r
1083 + && ! pc->rels_seen && (pc->times_seen || 2 < text_int.digits))
\r
1084 + pc->year = text_int;
\r
1087 + if (4 < text_int.digits)
\r
1089 + pc->dates_seen++;
\r
1090 + pc->day = text_int.value % 100;
\r
1091 + pc->month = (text_int.value / 100) % 100;
\r
1092 + pc->year.value = text_int.value / 10000;
\r
1093 + pc->year.digits = text_int.digits - 4;
\r
1097 + pc->times_seen++;
\r
1098 + if (text_int.digits <= 2)
\r
1100 + pc->hour = text_int.value;
\r
1101 + pc->minutes = 0;
\r
1105 + pc->hour = text_int.value / 100;
\r
1106 + pc->minutes = text_int.value % 100;
\r
1108 + pc->seconds.tv_sec = 0;
\r
1109 + pc->seconds.tv_nsec = 0;
\r
1110 + pc->meridian = MER24;
\r
1115 +/* Increment PC->rel by FACTOR * REL (FACTOR is 1 or -1). */
\r
1117 +apply_relative_time (parser_control *pc, relative_time rel, int factor)
\r
1119 + pc->rel.ns += factor * rel.ns;
\r
1120 + pc->rel.seconds += factor * rel.seconds;
\r
1121 + pc->rel.minutes += factor * rel.minutes;
\r
1122 + pc->rel.hour += factor * rel.hour;
\r
1123 + pc->rel.day += factor * rel.day;
\r
1124 + pc->rel.month += factor * rel.month;
\r
1125 + pc->rel.year += factor * rel.year;
\r
1126 + pc->rels_seen = true;
\r
1129 +/* Set PC-> hour, minutes, seconds and nanoseconds members from arguments. */
\r
1131 +set_hhmmss (parser_control *pc, long int hour, long int minutes,
\r
1132 + time_t sec, long int nsec)
\r
1134 + pc->hour = hour;
\r
1135 + pc->minutes = minutes;
\r
1136 + pc->seconds.tv_sec = sec;
\r
1137 + pc->seconds.tv_nsec = nsec;
\r
1142 +/* Line 189 of yacc.c */
\r
1143 +#line 348 "getdate.c"
\r
1145 +/* Enabling traces. */
\r
1147 +# define YYDEBUG 0
\r
1150 +/* Enabling verbose error messages. */
\r
1151 +#ifdef YYERROR_VERBOSE
\r
1152 +# undef YYERROR_VERBOSE
\r
1153 +# define YYERROR_VERBOSE 1
\r
1155 +# define YYERROR_VERBOSE 0
\r
1158 +/* Enabling the token table. */
\r
1159 +#ifndef YYTOKEN_TABLE
\r
1160 +# define YYTOKEN_TABLE 0
\r
1165 +#ifndef YYTOKENTYPE
\r
1166 +# define YYTOKENTYPE
\r
1167 + /* Put the tokens into the symbol table, so that GDB and other debuggers
\r
1168 + know about them. */
\r
1169 + enum yytokentype {
\r
1172 + tYEAR_UNIT = 260,
\r
1173 + tMONTH_UNIT = 261,
\r
1174 + tHOUR_UNIT = 262,
\r
1175 + tMINUTE_UNIT = 263,
\r
1176 + tSEC_UNIT = 264,
\r
1177 + tDAY_UNIT = 265,
\r
1178 + tDAY_SHIFT = 266,
\r
1181 + tLOCAL_ZONE = 269,
\r
1182 + tMERIDIAN = 270,
\r
1188 + tSDECIMAL_NUMBER = 276,
\r
1189 + tUDECIMAL_NUMBER = 277
\r
1195 +#define tYEAR_UNIT 260
\r
1196 +#define tMONTH_UNIT 261
\r
1197 +#define tHOUR_UNIT 262
\r
1198 +#define tMINUTE_UNIT 263
\r
1199 +#define tSEC_UNIT 264
\r
1200 +#define tDAY_UNIT 265
\r
1201 +#define tDAY_SHIFT 266
\r
1203 +#define tDAYZONE 268
\r
1204 +#define tLOCAL_ZONE 269
\r
1205 +#define tMERIDIAN 270
\r
1206 +#define tMONTH 271
\r
1207 +#define tORDINAL 272
\r
1208 +#define tZONE 273
\r
1209 +#define tSNUMBER 274
\r
1210 +#define tUNUMBER 275
\r
1211 +#define tSDECIMAL_NUMBER 276
\r
1212 +#define tUDECIMAL_NUMBER 277
\r
1217 +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
\r
1218 +typedef union YYSTYPE
\r
1221 +/* Line 214 of yacc.c */
\r
1222 +#line 285 "getdate.y"
\r
1224 + long int intval;
\r
1225 + textint textintval;
\r
1226 + struct timespec timespec;
\r
1227 + relative_time rel;
\r
1231 +/* Line 214 of yacc.c */
\r
1232 +#line 437 "getdate.c"
\r
1234 +# define YYSTYPE_IS_TRIVIAL 1
\r
1235 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */
\r
1236 +# define YYSTYPE_IS_DECLARED 1
\r
1240 +/* Copy the second part of user declarations. */
\r
1243 +/* Line 264 of yacc.c */
\r
1244 +#line 449 "getdate.c"
\r
1250 +#ifdef YYTYPE_UINT8
\r
1251 +typedef YYTYPE_UINT8 yytype_uint8;
\r
1253 +typedef unsigned char yytype_uint8;
\r
1256 +#ifdef YYTYPE_INT8
\r
1257 +typedef YYTYPE_INT8 yytype_int8;
\r
1258 +#elif (defined __STDC__ || defined __C99__FUNC__ \
\r
1259 + || defined __cplusplus || defined _MSC_VER)
\r
1260 +typedef signed char yytype_int8;
\r
1262 +typedef short int yytype_int8;
\r
1265 +#ifdef YYTYPE_UINT16
\r
1266 +typedef YYTYPE_UINT16 yytype_uint16;
\r
1268 +typedef unsigned short int yytype_uint16;
\r
1271 +#ifdef YYTYPE_INT16
\r
1272 +typedef YYTYPE_INT16 yytype_int16;
\r
1274 +typedef short int yytype_int16;
\r
1278 +# ifdef __SIZE_TYPE__
\r
1279 +# define YYSIZE_T __SIZE_TYPE__
\r
1280 +# elif defined size_t
\r
1281 +# define YYSIZE_T size_t
\r
1282 +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
\r
1283 + || defined __cplusplus || defined _MSC_VER)
\r
1284 +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
\r
1285 +# define YYSIZE_T size_t
\r
1287 +# define YYSIZE_T unsigned int
\r
1291 +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
\r
1294 +# if YYENABLE_NLS
\r
1296 +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
\r
1297 +# define YY_(msgid) dgettext ("bison-runtime", msgid)
\r
1301 +# define YY_(msgid) msgid
\r
1305 +/* Suppress unused-variable warnings by "using" E. */
\r
1306 +#if ! defined lint || defined __GNUC__
\r
1307 +# define YYUSE(e) ((void) (e))
\r
1309 +# define YYUSE(e) /* empty */
\r
1312 +/* Identity function, used to suppress warnings about constant conditions. */
\r
1314 +# define YYID(n) (n)
\r
1316 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
1317 + || defined __cplusplus || defined _MSC_VER)
\r
1330 +#if ! defined yyoverflow || YYERROR_VERBOSE
\r
1332 +/* The parser invokes alloca or malloc; define the necessary symbols. */
\r
1334 +# ifdef YYSTACK_USE_ALLOCA
\r
1335 +# if YYSTACK_USE_ALLOCA
\r
1337 +# define YYSTACK_ALLOC __builtin_alloca
\r
1338 +# elif defined __BUILTIN_VA_ARG_INCR
\r
1339 +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
\r
1340 +# elif defined _AIX
\r
1341 +# define YYSTACK_ALLOC __alloca
\r
1342 +# elif defined _MSC_VER
\r
1343 +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
\r
1344 +# define alloca _alloca
\r
1346 +# define YYSTACK_ALLOC alloca
\r
1347 +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
\r
1348 + || defined __cplusplus || defined _MSC_VER)
\r
1349 +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
\r
1350 +# ifndef _STDLIB_H
\r
1351 +# define _STDLIB_H 1
\r
1358 +# ifdef YYSTACK_ALLOC
\r
1359 + /* Pacify GCC's `empty if-body' warning. */
\r
1360 +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
\r
1361 +# ifndef YYSTACK_ALLOC_MAXIMUM
\r
1362 + /* The OS might guarantee only one guard page at the bottom of the stack,
\r
1363 + and a page size can be as small as 4096 bytes. So we cannot safely
\r
1364 + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
\r
1365 + to allow for a few compiler-allocated temporary stack slots. */
\r
1366 +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
\r
1369 +# define YYSTACK_ALLOC YYMALLOC
\r
1370 +# define YYSTACK_FREE YYFREE
\r
1371 +# ifndef YYSTACK_ALLOC_MAXIMUM
\r
1372 +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
\r
1374 +# if (defined __cplusplus && ! defined _STDLIB_H \
\r
1375 + && ! ((defined YYMALLOC || defined malloc) \
\r
1376 + && (defined YYFREE || defined free)))
\r
1377 +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
\r
1378 +# ifndef _STDLIB_H
\r
1379 +# define _STDLIB_H 1
\r
1382 +# ifndef YYMALLOC
\r
1383 +# define YYMALLOC malloc
\r
1384 +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
\r
1385 + || defined __cplusplus || defined _MSC_VER)
\r
1386 +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
\r
1390 +# define YYFREE free
\r
1391 +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
\r
1392 + || defined __cplusplus || defined _MSC_VER)
\r
1393 +void free (void *); /* INFRINGES ON USER NAME SPACE */
\r
1397 +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
\r
1400 +#if (! defined yyoverflow \
\r
1401 + && (! defined __cplusplus \
\r
1402 + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
\r
1404 +/* A type that is properly aligned for any stack member. */
\r
1407 + yytype_int16 yyss_alloc;
\r
1408 + YYSTYPE yyvs_alloc;
\r
1411 +/* The size of the maximum gap between one aligned stack and the next. */
\r
1412 +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
\r
1414 +/* The size of an array large to enough to hold all stacks, each with
\r
1416 +# define YYSTACK_BYTES(N) \
\r
1417 + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
\r
1418 + + YYSTACK_GAP_MAXIMUM)
\r
1420 +/* Copy COUNT objects from FROM to TO. The source and destination do
\r
1423 +# if defined __GNUC__ && 1 < __GNUC__
\r
1424 +# define YYCOPY(To, From, Count) \
\r
1425 + __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
\r
1427 +# define YYCOPY(To, From, Count) \
\r
1431 + for (yyi = 0; yyi < (Count); yyi++) \
\r
1432 + (To)[yyi] = (From)[yyi]; \
\r
1434 + while (YYID (0))
\r
1438 +/* Relocate STACK from its old location to the new one. The
\r
1439 + local variables YYSIZE and YYSTACKSIZE give the old and new number of
\r
1440 + elements in the stack, and YYPTR gives the new location of the
\r
1441 + stack. Advance YYPTR to a properly aligned location for the next
\r
1443 +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
\r
1446 + YYSIZE_T yynewbytes; \
\r
1447 + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
\r
1448 + Stack = &yyptr->Stack_alloc; \
\r
1449 + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
\r
1450 + yyptr += yynewbytes / sizeof (*yyptr); \
\r
1452 + while (YYID (0))
\r
1456 +/* YYFINAL -- State number of the termination state. */
\r
1457 +#define YYFINAL 12
\r
1458 +/* YYLAST -- Last index in YYTABLE. */
\r
1459 +#define YYLAST 98
\r
1461 +/* YYNTOKENS -- Number of terminals. */
\r
1462 +#define YYNTOKENS 27
\r
1463 +/* YYNNTS -- Number of nonterminals. */
\r
1464 +#define YYNNTS 21
\r
1465 +/* YYNRULES -- Number of rules. */
\r
1466 +#define YYNRULES 82
\r
1467 +/* YYNRULES -- Number of states. */
\r
1468 +#define YYNSTATES 100
\r
1470 +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
\r
1471 +#define YYUNDEFTOK 2
\r
1472 +#define YYMAXUTOK 277
\r
1474 +#define YYTRANSLATE(YYX) \
\r
1475 + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
\r
1477 +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
\r
1478 +static const yytype_uint8 yytranslate[] =
\r
1480 + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1481 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1482 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1483 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1484 + 2, 2, 2, 2, 25, 2, 2, 26, 2, 2,
\r
1485 + 2, 2, 2, 2, 2, 2, 2, 2, 24, 2,
\r
1486 + 2, 2, 2, 2, 23, 2, 2, 2, 2, 2,
\r
1487 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1488 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1489 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1490 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1491 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1492 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1493 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1494 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1495 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1496 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1497 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1498 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1499 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1500 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1501 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1502 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1503 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1504 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
1505 + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
\r
1506 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
\r
1507 + 15, 16, 17, 18, 19, 20, 21, 22
\r
1511 +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
\r
1513 +static const yytype_uint8 yyprhs[] =
\r
1515 + 0, 0, 3, 5, 7, 10, 11, 14, 16, 18,
\r
1516 + 20, 22, 24, 26, 28, 30, 33, 38, 44, 51,
\r
1517 + 59, 61, 64, 66, 69, 73, 75, 78, 80, 83,
\r
1518 + 86, 89, 93, 99, 103, 107, 111, 114, 119, 122,
\r
1519 + 126, 129, 131, 133, 136, 139, 141, 144, 147, 149,
\r
1520 + 152, 155, 157, 160, 163, 165, 168, 171, 173, 176,
\r
1521 + 179, 182, 185, 187, 189, 192, 195, 198, 201, 204,
\r
1522 + 207, 209, 211, 213, 215, 217, 219, 221, 223, 226,
\r
1526 +/* YYRHS -- A `-1'-separated list of the rules' RHS. */
\r
1527 +static const yytype_int8 yyrhs[] =
\r
1529 + 28, 0, -1, 29, -1, 30, -1, 23, 41, -1,
\r
1530 + -1, 30, 31, -1, 32, -1, 33, -1, 34, -1,
\r
1531 + 36, -1, 35, -1, 37, -1, 44, -1, 45, -1,
\r
1532 + 20, 15, -1, 20, 24, 20, 47, -1, 20, 24,
\r
1533 + 20, 19, 46, -1, 20, 24, 20, 24, 43, 47,
\r
1534 + -1, 20, 24, 20, 24, 43, 19, 46, -1, 14,
\r
1535 + -1, 14, 4, -1, 18, -1, 18, 39, -1, 18,
\r
1536 + 19, 46, -1, 13, -1, 18, 4, -1, 12, -1,
\r
1537 + 12, 25, -1, 17, 12, -1, 20, 12, -1, 20,
\r
1538 + 26, 20, -1, 20, 26, 20, 26, 20, -1, 20,
\r
1539 + 19, 19, -1, 20, 16, 19, -1, 16, 19, 19,
\r
1540 + -1, 16, 20, -1, 16, 20, 25, 20, -1, 20,
\r
1541 + 16, -1, 20, 16, 20, -1, 38, 3, -1, 38,
\r
1542 + -1, 40, -1, 17, 5, -1, 20, 5, -1, 5,
\r
1543 + -1, 17, 6, -1, 20, 6, -1, 6, -1, 17,
\r
1544 + 10, -1, 20, 10, -1, 10, -1, 17, 7, -1,
\r
1545 + 20, 7, -1, 7, -1, 17, 8, -1, 20, 8,
\r
1546 + -1, 8, -1, 17, 9, -1, 20, 9, -1, 21,
\r
1547 + 9, -1, 22, 9, -1, 9, -1, 39, -1, 19,
\r
1548 + 5, -1, 19, 6, -1, 19, 10, -1, 19, 7,
\r
1549 + -1, 19, 8, -1, 19, 9, -1, 11, -1, 42,
\r
1550 + -1, 43, -1, 21, -1, 19, -1, 22, -1, 20,
\r
1551 + -1, 20, -1, 20, 39, -1, -1, 24, 20, -1,
\r
1555 +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
\r
1556 +static const yytype_uint16 yyrline[] =
\r
1558 + 0, 311, 311, 312, 316, 323, 325, 329, 331, 333,
\r
1559 + 335, 337, 339, 340, 341, 345, 350, 355, 362, 367,
\r
1560 + 377, 382, 390, 392, 395, 397, 399, 404, 409, 414,
\r
1561 + 419, 427, 432, 452, 459, 467, 475, 480, 486, 491,
\r
1562 + 500, 502, 504, 509, 511, 513, 515, 517, 519, 521,
\r
1563 + 523, 525, 527, 529, 531, 533, 535, 537, 539, 541,
\r
1564 + 543, 545, 547, 549, 553, 555, 557, 559, 561, 563,
\r
1565 + 568, 572, 572, 575, 576, 581, 582, 587, 592, 603,
\r
1570 +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
\r
1571 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
\r
1572 + First, the terminals, then, starting at YYNTOKENS, nonterminals. */
\r
1573 +static const char *const yytname[] =
\r
1575 + "$end", "error", "$undefined", "tAGO", "tDST", "tYEAR_UNIT",
\r
1576 + "tMONTH_UNIT", "tHOUR_UNIT", "tMINUTE_UNIT", "tSEC_UNIT", "tDAY_UNIT",
\r
1577 + "tDAY_SHIFT", "tDAY", "tDAYZONE", "tLOCAL_ZONE", "tMERIDIAN", "tMONTH",
\r
1578 + "tORDINAL", "tZONE", "tSNUMBER", "tUNUMBER", "tSDECIMAL_NUMBER",
\r
1579 + "tUDECIMAL_NUMBER", "'@'", "':'", "','", "'/'", "$accept", "spec",
\r
1580 + "timespec", "items", "item", "time", "local_zone", "zone", "day", "date",
\r
1581 + "rel", "relunit", "relunit_snumber", "dayshift", "seconds",
\r
1582 + "signed_seconds", "unsigned_seconds", "number", "hybrid",
\r
1583 + "o_colon_minutes", "o_merid", 0
\r
1588 +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
\r
1589 + token YYLEX-NUM. */
\r
1590 +static const yytype_uint16 yytoknum[] =
\r
1592 + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
\r
1593 + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
\r
1594 + 275, 276, 277, 64, 58, 44, 47
\r
1598 +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
\r
1599 +static const yytype_uint8 yyr1[] =
\r
1601 + 0, 27, 28, 28, 29, 30, 30, 31, 31, 31,
\r
1602 + 31, 31, 31, 31, 31, 32, 32, 32, 32, 32,
\r
1603 + 33, 33, 34, 34, 34, 34, 34, 35, 35, 35,
\r
1604 + 35, 36, 36, 36, 36, 36, 36, 36, 36, 36,
\r
1605 + 37, 37, 37, 38, 38, 38, 38, 38, 38, 38,
\r
1606 + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
\r
1607 + 38, 38, 38, 38, 39, 39, 39, 39, 39, 39,
\r
1608 + 40, 41, 41, 42, 42, 43, 43, 44, 45, 46,
\r
1612 +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
\r
1613 +static const yytype_uint8 yyr2[] =
\r
1615 + 0, 2, 1, 1, 2, 0, 2, 1, 1, 1,
\r
1616 + 1, 1, 1, 1, 1, 2, 4, 5, 6, 7,
\r
1617 + 1, 2, 1, 2, 3, 1, 2, 1, 2, 2,
\r
1618 + 2, 3, 5, 3, 3, 3, 2, 4, 2, 3,
\r
1619 + 2, 1, 1, 2, 2, 1, 2, 2, 1, 2,
\r
1620 + 2, 1, 2, 2, 1, 2, 2, 1, 2, 2,
\r
1621 + 2, 2, 1, 1, 2, 2, 2, 2, 2, 2,
\r
1622 + 1, 1, 1, 1, 1, 1, 1, 1, 2, 0,
\r
1626 +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
\r
1627 + STATE-NUM when YYTABLE doesn't specify something else to do. Zero
\r
1628 + means the default is an error. */
\r
1629 +static const yytype_uint8 yydefact[] =
\r
1631 + 5, 0, 0, 2, 3, 74, 76, 73, 75, 4,
\r
1632 + 71, 72, 1, 45, 48, 54, 57, 62, 51, 70,
\r
1633 + 27, 25, 20, 0, 0, 22, 0, 77, 0, 0,
\r
1634 + 6, 7, 8, 9, 11, 10, 12, 41, 63, 42,
\r
1635 + 13, 14, 28, 21, 0, 36, 43, 46, 52, 55,
\r
1636 + 58, 49, 29, 26, 79, 23, 64, 65, 67, 68,
\r
1637 + 69, 66, 44, 47, 53, 56, 59, 50, 30, 15,
\r
1638 + 38, 0, 0, 0, 78, 60, 61, 40, 35, 0,
\r
1639 + 0, 24, 34, 39, 33, 81, 31, 37, 80, 82,
\r
1640 + 79, 0, 16, 0, 17, 81, 32, 79, 18, 19
\r
1643 +/* YYDEFGOTO[NTERM-NUM]. */
\r
1644 +static const yytype_int8 yydefgoto[] =
\r
1646 + -1, 2, 3, 4, 30, 31, 32, 33, 34, 35,
\r
1647 + 36, 37, 38, 39, 9, 10, 11, 40, 41, 81,
\r
1651 +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
\r
1653 +#define YYPACT_NINF -82
\r
1654 +static const yytype_int8 yypact[] =
\r
1656 + -17, 56, 15, -82, 26, -82, -82, -82, -82, -82,
\r
1657 + -82, -82, -82, -82, -82, -82, -82, -82, -82, -82,
\r
1658 + 36, -82, 68, 10, 50, 9, 59, -5, 72, 73,
\r
1659 + -82, -82, -82, -82, -82, -82, -82, 80, -82, -82,
\r
1660 + -82, -82, -82, -82, 65, 61, -82, -82, -82, -82,
\r
1661 + -82, -82, -82, -82, 17, -82, -82, -82, -82, -82,
\r
1662 + -82, -82, -82, -82, -82, -82, -82, -82, -82, -82,
\r
1663 + 60, 44, 67, 69, -82, -82, -82, -82, -82, 70,
\r
1664 + 71, -82, -82, -82, -82, -7, 62, -82, -82, -82,
\r
1665 + 74, -2, -82, 75, -82, 55, -82, 74, -82, -82
\r
1668 +/* YYPGOTO[NTERM-NUM]. */
\r
1669 +static const yytype_int8 yypgoto[] =
\r
1671 + -82, -82, -82, -82, -82, -82, -82, -82, -82, -82,
\r
1672 + -82, -82, 46, -82, -82, -82, -6, -82, -82, -81,
\r
1676 +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
\r
1677 + positive, shift that token. If negative, reduce the rule which
\r
1678 + number is the opposite. If zero, do what YYDEFACT says.
\r
1679 + If YYTABLE_NINF, syntax error. */
\r
1680 +#define YYTABLE_NINF -1
\r
1681 +static const yytype_uint8 yytable[] =
\r
1683 + 62, 63, 64, 65, 66, 67, 1, 68, 89, 94,
\r
1684 + 69, 70, 90, 53, 71, 12, 99, 91, 6, 72,
\r
1685 + 8, 73, 56, 57, 58, 59, 60, 61, 54, 44,
\r
1686 + 45, 13, 14, 15, 16, 17, 18, 19, 20, 21,
\r
1687 + 22, 80, 23, 24, 25, 26, 27, 28, 29, 56,
\r
1688 + 57, 58, 59, 60, 61, 46, 47, 48, 49, 50,
\r
1689 + 51, 42, 52, 84, 56, 57, 58, 59, 60, 61,
\r
1690 + 89, 55, 43, 74, 97, 5, 6, 7, 8, 82,
\r
1691 + 83, 75, 76, 77, 78, 95, 79, 85, 93, 86,
\r
1692 + 87, 88, 98, 0, 0, 96, 0, 0, 80
\r
1695 +static const yytype_int8 yycheck[] =
\r
1697 + 5, 6, 7, 8, 9, 10, 23, 12, 15, 90,
\r
1698 + 15, 16, 19, 4, 19, 0, 97, 24, 20, 24,
\r
1699 + 22, 26, 5, 6, 7, 8, 9, 10, 19, 19,
\r
1700 + 20, 5, 6, 7, 8, 9, 10, 11, 12, 13,
\r
1701 + 14, 24, 16, 17, 18, 19, 20, 21, 22, 5,
\r
1702 + 6, 7, 8, 9, 10, 5, 6, 7, 8, 9,
\r
1703 + 10, 25, 12, 19, 5, 6, 7, 8, 9, 10,
\r
1704 + 15, 25, 4, 27, 19, 19, 20, 21, 22, 19,
\r
1705 + 20, 9, 9, 3, 19, 91, 25, 20, 26, 20,
\r
1706 + 20, 20, 95, -1, -1, 20, -1, -1, 24
\r
1709 +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
\r
1710 + symbol of state STATE-NUM. */
\r
1711 +static const yytype_uint8 yystos[] =
\r
1713 + 0, 23, 28, 29, 30, 19, 20, 21, 22, 41,
\r
1714 + 42, 43, 0, 5, 6, 7, 8, 9, 10, 11,
\r
1715 + 12, 13, 14, 16, 17, 18, 19, 20, 21, 22,
\r
1716 + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
\r
1717 + 44, 45, 25, 4, 19, 20, 5, 6, 7, 8,
\r
1718 + 9, 10, 12, 4, 19, 39, 5, 6, 7, 8,
\r
1719 + 9, 10, 5, 6, 7, 8, 9, 10, 12, 15,
\r
1720 + 16, 19, 24, 26, 39, 9, 9, 3, 19, 25,
\r
1721 + 24, 46, 19, 20, 19, 20, 20, 20, 20, 15,
\r
1722 + 19, 24, 47, 26, 46, 43, 20, 19, 47, 46
\r
1725 +#define yyerrok (yyerrstatus = 0)
\r
1726 +#define yyclearin (yychar = YYEMPTY)
\r
1727 +#define YYEMPTY (-2)
\r
1730 +#define YYACCEPT goto yyacceptlab
\r
1731 +#define YYABORT goto yyabortlab
\r
1732 +#define YYERROR goto yyerrorlab
\r
1735 +/* Like YYERROR except do call yyerror. This remains here temporarily
\r
1736 + to ease the transition to the new meaning of YYERROR, for GCC.
\r
1737 + Once GCC version 2 has supplanted version 1, this can go. */
\r
1739 +#define YYFAIL goto yyerrlab
\r
1741 +#define YYRECOVERING() (!!yyerrstatus)
\r
1743 +#define YYBACKUP(Token, Value) \
\r
1745 + if (yychar == YYEMPTY && yylen == 1) \
\r
1747 + yychar = (Token); \
\r
1748 + yylval = (Value); \
\r
1749 + yytoken = YYTRANSLATE (yychar); \
\r
1750 + YYPOPSTACK (1); \
\r
1751 + goto yybackup; \
\r
1755 + yyerror (pc, YY_("syntax error: cannot back up")); \
\r
1761 +#define YYTERROR 1
\r
1762 +#define YYERRCODE 256
\r
1765 +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
\r
1766 + If N is 0, then set CURRENT to the empty location which ends
\r
1767 + the previous symbol: RHS[0] (always defined). */
\r
1769 +#define YYRHSLOC(Rhs, K) ((Rhs)[K])
\r
1770 +#ifndef YYLLOC_DEFAULT
\r
1771 +# define YYLLOC_DEFAULT(Current, Rhs, N) \
\r
1775 + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
\r
1776 + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
\r
1777 + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
\r
1778 + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
\r
1782 + (Current).first_line = (Current).last_line = \
\r
1783 + YYRHSLOC (Rhs, 0).last_line; \
\r
1784 + (Current).first_column = (Current).last_column = \
\r
1785 + YYRHSLOC (Rhs, 0).last_column; \
\r
1787 + while (YYID (0))
\r
1791 +/* YY_LOCATION_PRINT -- Print the location on the stream.
\r
1792 + This macro was not mandated originally: define only if we know
\r
1793 + we won't break user code: when these are the locations we know. */
\r
1795 +#ifndef YY_LOCATION_PRINT
\r
1796 +# if YYLTYPE_IS_TRIVIAL
\r
1797 +# define YY_LOCATION_PRINT(File, Loc) \
\r
1798 + fprintf (File, "%d.%d-%d.%d", \
\r
1799 + (Loc).first_line, (Loc).first_column, \
\r
1800 + (Loc).last_line, (Loc).last_column)
\r
1802 +# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
\r
1807 +/* YYLEX -- calling `yylex' with the right arguments. */
\r
1809 +#ifdef YYLEX_PARAM
\r
1810 +# define YYLEX yylex (&yylval, YYLEX_PARAM)
\r
1812 +# define YYLEX yylex (&yylval, pc)
\r
1815 +/* Enable debugging if requested. */
\r
1818 +# ifndef YYFPRINTF
\r
1819 +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
\r
1820 +# define YYFPRINTF fprintf
\r
1823 +# define YYDPRINTF(Args) \
\r
1826 + YYFPRINTF Args; \
\r
1827 +} while (YYID (0))
\r
1829 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
\r
1833 + YYFPRINTF (stderr, "%s ", Title); \
\r
1834 + yy_symbol_print (stderr, \
\r
1835 + Type, Value, pc); \
\r
1836 + YYFPRINTF (stderr, "\n"); \
\r
1838 +} while (YYID (0))
\r
1841 +/*--------------------------------.
\r
1842 +| Print this symbol on YYOUTPUT. |
\r
1843 +`--------------------------------*/
\r
1846 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
1847 + || defined __cplusplus || defined _MSC_VER)
\r
1849 +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_control *pc)
\r
1852 +yy_symbol_value_print (yyoutput, yytype, yyvaluep, pc)
\r
1855 + YYSTYPE const * const yyvaluep;
\r
1856 + parser_control *pc;
\r
1863 + if (yytype < YYNTOKENS)
\r
1864 + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
\r
1866 + YYUSE (yyoutput);
\r
1876 +/*--------------------------------.
\r
1877 +| Print this symbol on YYOUTPUT. |
\r
1878 +`--------------------------------*/
\r
1880 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
1881 + || defined __cplusplus || defined _MSC_VER)
\r
1883 +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_control *pc)
\r
1886 +yy_symbol_print (yyoutput, yytype, yyvaluep, pc)
\r
1889 + YYSTYPE const * const yyvaluep;
\r
1890 + parser_control *pc;
\r
1893 + if (yytype < YYNTOKENS)
\r
1894 + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
\r
1896 + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
\r
1898 + yy_symbol_value_print (yyoutput, yytype, yyvaluep, pc);
\r
1899 + YYFPRINTF (yyoutput, ")");
\r
1902 +/*------------------------------------------------------------------.
\r
1903 +| yy_stack_print -- Print the state stack from its BOTTOM up to its |
\r
1904 +| TOP (included). |
\r
1905 +`------------------------------------------------------------------*/
\r
1907 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
1908 + || defined __cplusplus || defined _MSC_VER)
\r
1910 +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
\r
1913 +yy_stack_print (yybottom, yytop)
\r
1914 + yytype_int16 *yybottom;
\r
1915 + yytype_int16 *yytop;
\r
1918 + YYFPRINTF (stderr, "Stack now");
\r
1919 + for (; yybottom <= yytop; yybottom++)
\r
1921 + int yybot = *yybottom;
\r
1922 + YYFPRINTF (stderr, " %d", yybot);
\r
1924 + YYFPRINTF (stderr, "\n");
\r
1927 +# define YY_STACK_PRINT(Bottom, Top) \
\r
1930 + yy_stack_print ((Bottom), (Top)); \
\r
1931 +} while (YYID (0))
\r
1934 +/*------------------------------------------------.
\r
1935 +| Report that the YYRULE is going to be reduced. |
\r
1936 +`------------------------------------------------*/
\r
1938 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
1939 + || defined __cplusplus || defined _MSC_VER)
\r
1941 +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, parser_control *pc)
\r
1944 +yy_reduce_print (yyvsp, yyrule, pc)
\r
1947 + parser_control *pc;
\r
1950 + int yynrhs = yyr2[yyrule];
\r
1952 + unsigned long int yylno = yyrline[yyrule];
\r
1953 + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
\r
1954 + yyrule - 1, yylno);
\r
1955 + /* The symbols being reduced. */
\r
1956 + for (yyi = 0; yyi < yynrhs; yyi++)
\r
1958 + YYFPRINTF (stderr, " $%d = ", yyi + 1);
\r
1959 + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
\r
1960 + &(yyvsp[(yyi + 1) - (yynrhs)])
\r
1962 + YYFPRINTF (stderr, "\n");
\r
1966 +# define YY_REDUCE_PRINT(Rule) \
\r
1969 + yy_reduce_print (yyvsp, Rule, pc); \
\r
1970 +} while (YYID (0))
\r
1972 +/* Nonzero means print parse trace. It is left uninitialized so that
\r
1973 + multiple parsers can coexist. */
\r
1975 +#else /* !YYDEBUG */
\r
1976 +# define YYDPRINTF(Args)
\r
1977 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
\r
1978 +# define YY_STACK_PRINT(Bottom, Top)
\r
1979 +# define YY_REDUCE_PRINT(Rule)
\r
1980 +#endif /* !YYDEBUG */
\r
1983 +/* YYINITDEPTH -- initial size of the parser's stacks. */
\r
1984 +#ifndef YYINITDEPTH
\r
1985 +# define YYINITDEPTH 200
\r
1988 +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
\r
1989 + if the built-in stack extension method is used).
\r
1991 + Do not make this value too large; the results are undefined if
\r
1992 + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
\r
1993 + evaluated with infinite-precision integer arithmetic. */
\r
1995 +#ifndef YYMAXDEPTH
\r
1996 +# define YYMAXDEPTH 10000
\r
2002 +#if YYERROR_VERBOSE
\r
2004 +# ifndef yystrlen
\r
2005 +# if defined __GLIBC__ && defined _STRING_H
\r
2006 +# define yystrlen strlen
\r
2008 +/* Return the length of YYSTR. */
\r
2009 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
2010 + || defined __cplusplus || defined _MSC_VER)
\r
2012 +yystrlen (const char *yystr)
\r
2016 + const char *yystr;
\r
2020 + for (yylen = 0; yystr[yylen]; yylen++)
\r
2027 +# ifndef yystpcpy
\r
2028 +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
\r
2029 +# define yystpcpy stpcpy
\r
2031 +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
\r
2033 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
2034 + || defined __cplusplus || defined _MSC_VER)
\r
2036 +yystpcpy (char *yydest, const char *yysrc)
\r
2039 +yystpcpy (yydest, yysrc)
\r
2041 + const char *yysrc;
\r
2044 + char *yyd = yydest;
\r
2045 + const char *yys = yysrc;
\r
2047 + while ((*yyd++ = *yys++) != '\0')
\r
2055 +# ifndef yytnamerr
\r
2056 +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
\r
2057 + quotes and backslashes, so that it's suitable for yyerror. The
\r
2058 + heuristic is that double-quoting is unnecessary unless the string
\r
2059 + contains an apostrophe, a comma, or backslash (other than
\r
2060 + backslash-backslash). YYSTR is taken from yytname. If YYRES is
\r
2061 + null, do not copy; instead, return the length of what the result
\r
2062 + would have been. */
\r
2064 +yytnamerr (char *yyres, const char *yystr)
\r
2066 + if (*yystr == '"')
\r
2068 + YYSIZE_T yyn = 0;
\r
2069 + char const *yyp = yystr;
\r
2076 + goto do_not_strip_quotes;
\r
2079 + if (*++yyp != '\\')
\r
2080 + goto do_not_strip_quotes;
\r
2081 + /* Fall through. */
\r
2084 + yyres[yyn] = *yyp;
\r
2090 + yyres[yyn] = '\0';
\r
2093 + do_not_strip_quotes: ;
\r
2097 + return yystrlen (yystr);
\r
2099 + return yystpcpy (yyres, yystr) - yyres;
\r
2103 +/* Copy into YYRESULT an error message about the unexpected token
\r
2104 + YYCHAR while in state YYSTATE. Return the number of bytes copied,
\r
2105 + including the terminating null byte. If YYRESULT is null, do not
\r
2106 + copy anything; just return the number of bytes that would be
\r
2107 + copied. As a special case, return 0 if an ordinary "syntax error"
\r
2108 + message will do. Return YYSIZE_MAXIMUM if overflow occurs during
\r
2109 + size calculation. */
\r
2111 +yysyntax_error (char *yyresult, int yystate, int yychar)
\r
2113 + int yyn = yypact[yystate];
\r
2115 + if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
\r
2119 + int yytype = YYTRANSLATE (yychar);
\r
2120 + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
\r
2121 + YYSIZE_T yysize = yysize0;
\r
2122 + YYSIZE_T yysize1;
\r
2123 + int yysize_overflow = 0;
\r
2124 + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
\r
2125 + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
\r
2129 + /* This is so xgettext sees the translatable formats that are
\r
2130 + constructed on the fly. */
\r
2131 + YY_("syntax error, unexpected %s");
\r
2132 + YY_("syntax error, unexpected %s, expecting %s");
\r
2133 + YY_("syntax error, unexpected %s, expecting %s or %s");
\r
2134 + YY_("syntax error, unexpected %s, expecting %s or %s or %s");
\r
2135 + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
\r
2138 + char const *yyf;
\r
2139 + static char const yyunexpected[] = "syntax error, unexpected %s";
\r
2140 + static char const yyexpecting[] = ", expecting %s";
\r
2141 + static char const yyor[] = " or %s";
\r
2142 + char yyformat[sizeof yyunexpected
\r
2143 + + sizeof yyexpecting - 1
\r
2144 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
\r
2145 + * (sizeof yyor - 1))];
\r
2146 + char const *yyprefix = yyexpecting;
\r
2148 + /* Start YYX at -YYN if negative to avoid negative indexes in
\r
2150 + int yyxbegin = yyn < 0 ? -yyn : 0;
\r
2152 + /* Stay within bounds of both yycheck and yytname. */
\r
2153 + int yychecklim = YYLAST - yyn + 1;
\r
2154 + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
\r
2155 + int yycount = 1;
\r
2157 + yyarg[0] = yytname[yytype];
\r
2158 + yyfmt = yystpcpy (yyformat, yyunexpected);
\r
2160 + for (yyx = yyxbegin; yyx < yyxend; ++yyx)
\r
2161 + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
\r
2163 + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
\r
2166 + yysize = yysize0;
\r
2167 + yyformat[sizeof yyunexpected - 1] = '\0';
\r
2170 + yyarg[yycount++] = yytname[yyx];
\r
2171 + yysize1 = yysize + yytnamerr (0, yytname[yyx]);
\r
2172 + yysize_overflow |= (yysize1 < yysize);
\r
2173 + yysize = yysize1;
\r
2174 + yyfmt = yystpcpy (yyfmt, yyprefix);
\r
2175 + yyprefix = yyor;
\r
2178 + yyf = YY_(yyformat);
\r
2179 + yysize1 = yysize + yystrlen (yyf);
\r
2180 + yysize_overflow |= (yysize1 < yysize);
\r
2181 + yysize = yysize1;
\r
2183 + if (yysize_overflow)
\r
2184 + return YYSIZE_MAXIMUM;
\r
2188 + /* Avoid sprintf, as that infringes on the user's name space.
\r
2189 + Don't have undefined behavior even if the translation
\r
2190 + produced a string with the wrong number of "%s"s. */
\r
2191 + char *yyp = yyresult;
\r
2193 + while ((*yyp = *yyf) != '\0')
\r
2195 + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
\r
2197 + yyp += yytnamerr (yyp, yyarg[yyi++]);
\r
2210 +#endif /* YYERROR_VERBOSE */
\r
2214 +/*-----------------------------------------------.
\r
2215 +| Release the memory associated to this symbol. |
\r
2216 +`-----------------------------------------------*/
\r
2219 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
2220 + || defined __cplusplus || defined _MSC_VER)
\r
2222 +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_control *pc)
\r
2225 +yydestruct (yymsg, yytype, yyvaluep, pc)
\r
2226 + const char *yymsg;
\r
2228 + YYSTYPE *yyvaluep;
\r
2229 + parser_control *pc;
\r
2232 + YYUSE (yyvaluep);
\r
2236 + yymsg = "Deleting";
\r
2237 + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
\r
2247 +/* Prevent warnings from -Wmissing-prototypes. */
\r
2248 +#ifdef YYPARSE_PARAM
\r
2249 +#if defined __STDC__ || defined __cplusplus
\r
2250 +int yyparse (void *YYPARSE_PARAM);
\r
2254 +#else /* ! YYPARSE_PARAM */
\r
2255 +#if defined __STDC__ || defined __cplusplus
\r
2256 +int yyparse (parser_control *pc);
\r
2260 +#endif /* ! YYPARSE_PARAM */
\r
2266 +/*-------------------------.
\r
2267 +| yyparse or yypush_parse. |
\r
2268 +`-------------------------*/
\r
2270 +#ifdef YYPARSE_PARAM
\r
2271 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
2272 + || defined __cplusplus || defined _MSC_VER)
\r
2274 +yyparse (void *YYPARSE_PARAM)
\r
2277 +yyparse (YYPARSE_PARAM)
\r
2278 + void *YYPARSE_PARAM;
\r
2280 +#else /* ! YYPARSE_PARAM */
\r
2281 +#if (defined __STDC__ || defined __C99__FUNC__ \
\r
2282 + || defined __cplusplus || defined _MSC_VER)
\r
2284 +yyparse (parser_control *pc)
\r
2288 + parser_control *pc;
\r
2292 +/* The lookahead symbol. */
\r
2295 +/* The semantic value of the lookahead symbol. */
\r
2298 + /* Number of syntax errors so far. */
\r
2302 + /* Number of tokens to shift before error messages enabled. */
\r
2303 + int yyerrstatus;
\r
2305 + /* The stacks and their tools:
\r
2306 + `yyss': related to states.
\r
2307 + `yyvs': related to semantic values.
\r
2309 + Refer to the stacks thru separate pointers, to allow yyoverflow
\r
2310 + to reallocate them elsewhere. */
\r
2312 + /* The state stack. */
\r
2313 + yytype_int16 yyssa[YYINITDEPTH];
\r
2314 + yytype_int16 *yyss;
\r
2315 + yytype_int16 *yyssp;
\r
2317 + /* The semantic value stack. */
\r
2318 + YYSTYPE yyvsa[YYINITDEPTH];
\r
2322 + YYSIZE_T yystacksize;
\r
2326 + /* Lookahead token as an internal (translated) token number. */
\r
2328 + /* The variables used to return semantic value and location from the
\r
2329 + action routines. */
\r
2332 +#if YYERROR_VERBOSE
\r
2333 + /* Buffer for error messages, and its allocated size. */
\r
2334 + char yymsgbuf[128];
\r
2335 + char *yymsg = yymsgbuf;
\r
2336 + YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
\r
2339 +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
\r
2341 + /* The number of symbols on the RHS of the reduced rule.
\r
2342 + Keep to zero when no symbol should be popped. */
\r
2348 + yystacksize = YYINITDEPTH;
\r
2350 + YYDPRINTF ((stderr, "Starting parse\n"));
\r
2353 + yyerrstatus = 0;
\r
2355 + yychar = YYEMPTY; /* Cause a token to be read. */
\r
2357 + /* Initialize stack pointers.
\r
2358 + Waste one element of value and location stack
\r
2359 + so that they stay on the same level as the state stack.
\r
2360 + The wasted elements are never initialized. */
\r
2364 + goto yysetstate;
\r
2366 +/*------------------------------------------------------------.
\r
2367 +| yynewstate -- Push a new state, which is found in yystate. |
\r
2368 +`------------------------------------------------------------*/
\r
2370 + /* In all cases, when you get here, the value and location stacks
\r
2371 + have just been pushed. So pushing a state here evens the stacks. */
\r
2375 + *yyssp = yystate;
\r
2377 + if (yyss + yystacksize - 1 <= yyssp)
\r
2379 + /* Get the current used size of the three stacks, in elements. */
\r
2380 + YYSIZE_T yysize = yyssp - yyss + 1;
\r
2382 +#ifdef yyoverflow
\r
2384 + /* Give user a chance to reallocate the stack. Use copies of
\r
2385 + these so that the &'s don't force the real ones into
\r
2387 + YYSTYPE *yyvs1 = yyvs;
\r
2388 + yytype_int16 *yyss1 = yyss;
\r
2390 + /* Each stack pointer address is followed by the size of the
\r
2391 + data in use in that stack, in bytes. This used to be a
\r
2392 + conditional around just the two extra args, but that might
\r
2393 + be undefined if yyoverflow is a macro. */
\r
2394 + yyoverflow (YY_("memory exhausted"),
\r
2395 + &yyss1, yysize * sizeof (*yyssp),
\r
2396 + &yyvs1, yysize * sizeof (*yyvsp),
\r
2402 +#else /* no yyoverflow */
\r
2403 +# ifndef YYSTACK_RELOCATE
\r
2404 + goto yyexhaustedlab;
\r
2406 + /* Extend the stack our own way. */
\r
2407 + if (YYMAXDEPTH <= yystacksize)
\r
2408 + goto yyexhaustedlab;
\r
2409 + yystacksize *= 2;
\r
2410 + if (YYMAXDEPTH < yystacksize)
\r
2411 + yystacksize = YYMAXDEPTH;
\r
2414 + yytype_int16 *yyss1 = yyss;
\r
2415 + union yyalloc *yyptr =
\r
2416 + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
\r
2418 + goto yyexhaustedlab;
\r
2419 + YYSTACK_RELOCATE (yyss_alloc, yyss);
\r
2420 + YYSTACK_RELOCATE (yyvs_alloc, yyvs);
\r
2421 +# undef YYSTACK_RELOCATE
\r
2422 + if (yyss1 != yyssa)
\r
2423 + YYSTACK_FREE (yyss1);
\r
2426 +#endif /* no yyoverflow */
\r
2428 + yyssp = yyss + yysize - 1;
\r
2429 + yyvsp = yyvs + yysize - 1;
\r
2431 + YYDPRINTF ((stderr, "Stack size increased to %lu\n",
\r
2432 + (unsigned long int) yystacksize));
\r
2434 + if (yyss + yystacksize - 1 <= yyssp)
\r
2438 + YYDPRINTF ((stderr, "Entering state %d\n", yystate));
\r
2440 + if (yystate == YYFINAL)
\r
2450 + /* Do appropriate processing given the current state. Read a
\r
2451 + lookahead token if we need one and don't already have one. */
\r
2453 + /* First try to decide what to do without reference to lookahead token. */
\r
2454 + yyn = yypact[yystate];
\r
2455 + if (yyn == YYPACT_NINF)
\r
2458 + /* Not known => get a lookahead token if don't already have one. */
\r
2460 + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
\r
2461 + if (yychar == YYEMPTY)
\r
2463 + YYDPRINTF ((stderr, "Reading a token: "));
\r
2467 + if (yychar <= YYEOF)
\r
2469 + yychar = yytoken = YYEOF;
\r
2470 + YYDPRINTF ((stderr, "Now at end of input.\n"));
\r
2474 + yytoken = YYTRANSLATE (yychar);
\r
2475 + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
\r
2478 + /* If the proper action on seeing token YYTOKEN is to reduce or to
\r
2479 + detect an error, take that action. */
\r
2481 + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
\r
2483 + yyn = yytable[yyn];
\r
2486 + if (yyn == 0 || yyn == YYTABLE_NINF)
\r
2492 + /* Count tokens shifted since error; after three, turn off error
\r
2494 + if (yyerrstatus)
\r
2497 + /* Shift the lookahead token. */
\r
2498 + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
\r
2500 + /* Discard the shifted token. */
\r
2501 + yychar = YYEMPTY;
\r
2504 + *++yyvsp = yylval;
\r
2506 + goto yynewstate;
\r
2509 +/*-----------------------------------------------------------.
\r
2510 +| yydefault -- do the default action for the current state. |
\r
2511 +`-----------------------------------------------------------*/
\r
2513 + yyn = yydefact[yystate];
\r
2519 +/*-----------------------------.
\r
2520 +| yyreduce -- Do a reduction. |
\r
2521 +`-----------------------------*/
\r
2523 + /* yyn is the number of a rule to reduce with. */
\r
2524 + yylen = yyr2[yyn];
\r
2526 + /* If YYLEN is nonzero, implement the default value of the action:
\r
2529 + Otherwise, the following line sets YYVAL to garbage.
\r
2530 + This behavior is undocumented and Bison
\r
2531 + users should not rely upon it. Assigning to YYVAL
\r
2532 + unconditionally makes the parser a bit smaller, and it avoids a
\r
2533 + GCC warning that YYVAL may be used uninitialized. */
\r
2534 + yyval = yyvsp[1-yylen];
\r
2537 + YY_REDUCE_PRINT (yyn);
\r
2542 +/* Line 1455 of yacc.c */
\r
2543 +#line 317 "getdate.y"
\r
2545 + pc->seconds = (yyvsp[(2) - (2)].timespec);
\r
2546 + pc->timespec_seen = true;
\r
2552 +/* Line 1455 of yacc.c */
\r
2553 +#line 330 "getdate.y"
\r
2554 + { pc->times_seen++; }
\r
2559 +/* Line 1455 of yacc.c */
\r
2560 +#line 332 "getdate.y"
\r
2561 + { pc->local_zones_seen++; }
\r
2566 +/* Line 1455 of yacc.c */
\r
2567 +#line 334 "getdate.y"
\r
2568 + { pc->zones_seen++; }
\r
2573 +/* Line 1455 of yacc.c */
\r
2574 +#line 336 "getdate.y"
\r
2575 + { pc->dates_seen++; }
\r
2580 +/* Line 1455 of yacc.c */
\r
2581 +#line 338 "getdate.y"
\r
2582 + { pc->days_seen++; }
\r
2587 +/* Line 1455 of yacc.c */
\r
2588 +#line 346 "getdate.y"
\r
2590 + set_hhmmss (pc, (yyvsp[(1) - (2)].textintval).value, 0, 0, 0);
\r
2591 + pc->meridian = (yyvsp[(2) - (2)].intval);
\r
2597 +/* Line 1455 of yacc.c */
\r
2598 +#line 351 "getdate.y"
\r
2600 + set_hhmmss (pc, (yyvsp[(1) - (4)].textintval).value, (yyvsp[(3) - (4)].textintval).value, 0, 0);
\r
2601 + pc->meridian = (yyvsp[(4) - (4)].intval);
\r
2607 +/* Line 1455 of yacc.c */
\r
2608 +#line 356 "getdate.y"
\r
2610 + set_hhmmss (pc, (yyvsp[(1) - (5)].textintval).value, (yyvsp[(3) - (5)].textintval).value, 0, 0);
\r
2611 + pc->meridian = MER24;
\r
2612 + pc->zones_seen++;
\r
2613 + pc->time_zone = time_zone_hhmm (pc, (yyvsp[(4) - (5)].textintval), (yyvsp[(5) - (5)].intval));
\r
2619 +/* Line 1455 of yacc.c */
\r
2620 +#line 363 "getdate.y"
\r
2622 + set_hhmmss (pc, (yyvsp[(1) - (6)].textintval).value, (yyvsp[(3) - (6)].textintval).value, (yyvsp[(5) - (6)].timespec).tv_sec, (yyvsp[(5) - (6)].timespec).tv_nsec);
\r
2623 + pc->meridian = (yyvsp[(6) - (6)].intval);
\r
2629 +/* Line 1455 of yacc.c */
\r
2630 +#line 368 "getdate.y"
\r
2632 + set_hhmmss (pc, (yyvsp[(1) - (7)].textintval).value, (yyvsp[(3) - (7)].textintval).value, (yyvsp[(5) - (7)].timespec).tv_sec, (yyvsp[(5) - (7)].timespec).tv_nsec);
\r
2633 + pc->meridian = MER24;
\r
2634 + pc->zones_seen++;
\r
2635 + pc->time_zone = time_zone_hhmm (pc, (yyvsp[(6) - (7)].textintval), (yyvsp[(7) - (7)].intval));
\r
2641 +/* Line 1455 of yacc.c */
\r
2642 +#line 378 "getdate.y"
\r
2644 + pc->local_isdst = (yyvsp[(1) - (1)].intval);
\r
2645 + pc->dsts_seen += (0 < (yyvsp[(1) - (1)].intval));
\r
2651 +/* Line 1455 of yacc.c */
\r
2652 +#line 383 "getdate.y"
\r
2654 + pc->local_isdst = 1;
\r
2655 + pc->dsts_seen += (0 < (yyvsp[(1) - (2)].intval)) + 1;
\r
2661 +/* Line 1455 of yacc.c */
\r
2662 +#line 391 "getdate.y"
\r
2663 + { pc->time_zone = (yyvsp[(1) - (1)].intval); }
\r
2668 +/* Line 1455 of yacc.c */
\r
2669 +#line 393 "getdate.y"
\r
2670 + { pc->time_zone = (yyvsp[(1) - (2)].intval);
\r
2671 + apply_relative_time (pc, (yyvsp[(2) - (2)].rel), 1); }
\r
2676 +/* Line 1455 of yacc.c */
\r
2677 +#line 396 "getdate.y"
\r
2678 + { pc->time_zone = (yyvsp[(1) - (3)].intval) + time_zone_hhmm (pc, (yyvsp[(2) - (3)].textintval), (yyvsp[(3) - (3)].intval)); }
\r
2683 +/* Line 1455 of yacc.c */
\r
2684 +#line 398 "getdate.y"
\r
2685 + { pc->time_zone = (yyvsp[(1) - (1)].intval) + 60; }
\r
2690 +/* Line 1455 of yacc.c */
\r
2691 +#line 400 "getdate.y"
\r
2692 + { pc->time_zone = (yyvsp[(1) - (2)].intval) + 60; }
\r
2697 +/* Line 1455 of yacc.c */
\r
2698 +#line 405 "getdate.y"
\r
2700 + pc->day_ordinal = 0;
\r
2701 + pc->day_number = (yyvsp[(1) - (1)].intval);
\r
2707 +/* Line 1455 of yacc.c */
\r
2708 +#line 410 "getdate.y"
\r
2710 + pc->day_ordinal = 0;
\r
2711 + pc->day_number = (yyvsp[(1) - (2)].intval);
\r
2717 +/* Line 1455 of yacc.c */
\r
2718 +#line 415 "getdate.y"
\r
2720 + pc->day_ordinal = (yyvsp[(1) - (2)].intval);
\r
2721 + pc->day_number = (yyvsp[(2) - (2)].intval);
\r
2727 +/* Line 1455 of yacc.c */
\r
2728 +#line 420 "getdate.y"
\r
2730 + pc->day_ordinal = (yyvsp[(1) - (2)].textintval).value;
\r
2731 + pc->day_number = (yyvsp[(2) - (2)].intval);
\r
2737 +/* Line 1455 of yacc.c */
\r
2738 +#line 428 "getdate.y"
\r
2740 + pc->month = (yyvsp[(1) - (3)].textintval).value;
\r
2741 + pc->day = (yyvsp[(3) - (3)].textintval).value;
\r
2747 +/* Line 1455 of yacc.c */
\r
2748 +#line 433 "getdate.y"
\r
2750 + /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
\r
2751 + otherwise as MM/DD/YY.
\r
2752 + The goal in recognizing YYYY/MM/DD is solely to support legacy
\r
2753 + machine-generated dates like those in an RCS log listing. If
\r
2754 + you want portability, use the ISO 8601 format. */
\r
2755 + if (4 <= (yyvsp[(1) - (5)].textintval).digits)
\r
2757 + pc->year = (yyvsp[(1) - (5)].textintval);
\r
2758 + pc->month = (yyvsp[(3) - (5)].textintval).value;
\r
2759 + pc->day = (yyvsp[(5) - (5)].textintval).value;
\r
2763 + pc->month = (yyvsp[(1) - (5)].textintval).value;
\r
2764 + pc->day = (yyvsp[(3) - (5)].textintval).value;
\r
2765 + pc->year = (yyvsp[(5) - (5)].textintval);
\r
2772 +/* Line 1455 of yacc.c */
\r
2773 +#line 453 "getdate.y"
\r
2775 + /* ISO 8601 format. YYYY-MM-DD. */
\r
2776 + pc->year = (yyvsp[(1) - (3)].textintval);
\r
2777 + pc->month = -(yyvsp[(2) - (3)].textintval).value;
\r
2778 + pc->day = -(yyvsp[(3) - (3)].textintval).value;
\r
2784 +/* Line 1455 of yacc.c */
\r
2785 +#line 460 "getdate.y"
\r
2787 + /* e.g. 17-JUN-1992. */
\r
2788 + pc->day = (yyvsp[(1) - (3)].textintval).value;
\r
2789 + pc->month = (yyvsp[(2) - (3)].intval);
\r
2790 + pc->year.value = -(yyvsp[(3) - (3)].textintval).value;
\r
2791 + pc->year.digits = (yyvsp[(3) - (3)].textintval).digits;
\r
2797 +/* Line 1455 of yacc.c */
\r
2798 +#line 468 "getdate.y"
\r
2800 + /* e.g. JUN-17-1992. */
\r
2801 + pc->month = (yyvsp[(1) - (3)].intval);
\r
2802 + pc->day = -(yyvsp[(2) - (3)].textintval).value;
\r
2803 + pc->year.value = -(yyvsp[(3) - (3)].textintval).value;
\r
2804 + pc->year.digits = (yyvsp[(3) - (3)].textintval).digits;
\r
2810 +/* Line 1455 of yacc.c */
\r
2811 +#line 476 "getdate.y"
\r
2813 + pc->month = (yyvsp[(1) - (2)].intval);
\r
2814 + pc->day = (yyvsp[(2) - (2)].textintval).value;
\r
2820 +/* Line 1455 of yacc.c */
\r
2821 +#line 481 "getdate.y"
\r
2823 + pc->month = (yyvsp[(1) - (4)].intval);
\r
2824 + pc->day = (yyvsp[(2) - (4)].textintval).value;
\r
2825 + pc->year = (yyvsp[(4) - (4)].textintval);
\r
2831 +/* Line 1455 of yacc.c */
\r
2832 +#line 487 "getdate.y"
\r
2834 + pc->day = (yyvsp[(1) - (2)].textintval).value;
\r
2835 + pc->month = (yyvsp[(2) - (2)].intval);
\r
2841 +/* Line 1455 of yacc.c */
\r
2842 +#line 492 "getdate.y"
\r
2844 + pc->day = (yyvsp[(1) - (3)].textintval).value;
\r
2845 + pc->month = (yyvsp[(2) - (3)].intval);
\r
2846 + pc->year = (yyvsp[(3) - (3)].textintval);
\r
2852 +/* Line 1455 of yacc.c */
\r
2853 +#line 501 "getdate.y"
\r
2854 + { apply_relative_time (pc, (yyvsp[(1) - (2)].rel), -1); }
\r
2859 +/* Line 1455 of yacc.c */
\r
2860 +#line 503 "getdate.y"
\r
2861 + { apply_relative_time (pc, (yyvsp[(1) - (1)].rel), 1); }
\r
2866 +/* Line 1455 of yacc.c */
\r
2867 +#line 505 "getdate.y"
\r
2868 + { apply_relative_time (pc, (yyvsp[(1) - (1)].rel), 1); }
\r
2873 +/* Line 1455 of yacc.c */
\r
2874 +#line 510 "getdate.y"
\r
2875 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].intval); }
\r
2880 +/* Line 1455 of yacc.c */
\r
2881 +#line 512 "getdate.y"
\r
2882 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }
\r
2887 +/* Line 1455 of yacc.c */
\r
2888 +#line 514 "getdate.y"
\r
2889 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = 1; }
\r
2894 +/* Line 1455 of yacc.c */
\r
2895 +#line 516 "getdate.y"
\r
2896 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].intval); }
\r
2901 +/* Line 1455 of yacc.c */
\r
2902 +#line 518 "getdate.y"
\r
2903 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }
\r
2908 +/* Line 1455 of yacc.c */
\r
2909 +#line 520 "getdate.y"
\r
2910 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = 1; }
\r
2915 +/* Line 1455 of yacc.c */
\r
2916 +#line 522 "getdate.y"
\r
2917 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].intval) * (yyvsp[(2) - (2)].intval); }
\r
2922 +/* Line 1455 of yacc.c */
\r
2923 +#line 524 "getdate.y"
\r
2924 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }
\r
2929 +/* Line 1455 of yacc.c */
\r
2930 +#line 526 "getdate.y"
\r
2931 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (1)].intval); }
\r
2936 +/* Line 1455 of yacc.c */
\r
2937 +#line 528 "getdate.y"
\r
2938 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].intval); }
\r
2943 +/* Line 1455 of yacc.c */
\r
2944 +#line 530 "getdate.y"
\r
2945 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }
\r
2950 +/* Line 1455 of yacc.c */
\r
2951 +#line 532 "getdate.y"
\r
2952 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = 1; }
\r
2957 +/* Line 1455 of yacc.c */
\r
2958 +#line 534 "getdate.y"
\r
2959 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].intval); }
\r
2964 +/* Line 1455 of yacc.c */
\r
2965 +#line 536 "getdate.y"
\r
2966 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }
\r
2971 +/* Line 1455 of yacc.c */
\r
2972 +#line 538 "getdate.y"
\r
2973 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = 1; }
\r
2978 +/* Line 1455 of yacc.c */
\r
2979 +#line 540 "getdate.y"
\r
2980 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].intval); }
\r
2985 +/* Line 1455 of yacc.c */
\r
2986 +#line 542 "getdate.y"
\r
2987 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }
\r
2992 +/* Line 1455 of yacc.c */
\r
2993 +#line 544 "getdate.y"
\r
2994 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }
\r
2999 +/* Line 1455 of yacc.c */
\r
3000 +#line 546 "getdate.y"
\r
3001 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }
\r
3006 +/* Line 1455 of yacc.c */
\r
3007 +#line 548 "getdate.y"
\r
3008 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = 1; }
\r
3013 +/* Line 1455 of yacc.c */
\r
3014 +#line 554 "getdate.y"
\r
3015 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }
\r
3020 +/* Line 1455 of yacc.c */
\r
3021 +#line 556 "getdate.y"
\r
3022 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }
\r
3027 +/* Line 1455 of yacc.c */
\r
3028 +#line 558 "getdate.y"
\r
3029 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }
\r
3034 +/* Line 1455 of yacc.c */
\r
3035 +#line 560 "getdate.y"
\r
3036 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }
\r
3041 +/* Line 1455 of yacc.c */
\r
3042 +#line 562 "getdate.y"
\r
3043 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }
\r
3048 +/* Line 1455 of yacc.c */
\r
3049 +#line 564 "getdate.y"
\r
3050 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }
\r
3055 +/* Line 1455 of yacc.c */
\r
3056 +#line 569 "getdate.y"
\r
3057 + { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (1)].intval); }
\r
3062 +/* Line 1455 of yacc.c */
\r
3063 +#line 577 "getdate.y"
\r
3064 + { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }
\r
3069 +/* Line 1455 of yacc.c */
\r
3070 +#line 583 "getdate.y"
\r
3071 + { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }
\r
3076 +/* Line 1455 of yacc.c */
\r
3077 +#line 588 "getdate.y"
\r
3078 + { digits_to_date_time (pc, (yyvsp[(1) - (1)].textintval)); }
\r
3083 +/* Line 1455 of yacc.c */
\r
3084 +#line 593 "getdate.y"
\r
3086 + /* Hybrid all-digit and relative offset, so that we accept e.g.,
\r
3087 + "YYYYMMDD +N days" as well as "YYYYMMDD N days". */
\r
3088 + digits_to_date_time (pc, (yyvsp[(1) - (2)].textintval));
\r
3089 + apply_relative_time (pc, (yyvsp[(2) - (2)].rel), 1);
\r
3095 +/* Line 1455 of yacc.c */
\r
3096 +#line 603 "getdate.y"
\r
3097 + { (yyval.intval) = -1; }
\r
3102 +/* Line 1455 of yacc.c */
\r
3103 +#line 605 "getdate.y"
\r
3104 + { (yyval.intval) = (yyvsp[(2) - (2)].textintval).value; }
\r
3109 +/* Line 1455 of yacc.c */
\r
3110 +#line 610 "getdate.y"
\r
3111 + { (yyval.intval) = MER24; }
\r
3116 +/* Line 1455 of yacc.c */
\r
3117 +#line 612 "getdate.y"
\r
3118 + { (yyval.intval) = (yyvsp[(1) - (1)].intval); }
\r
3123 +/* Line 1455 of yacc.c */
\r
3124 +#line 2327 "getdate.c"
\r
3127 + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
\r
3129 + YYPOPSTACK (yylen);
\r
3131 + YY_STACK_PRINT (yyss, yyssp);
\r
3133 + *++yyvsp = yyval;
\r
3135 + /* Now `shift' the result of the reduction. Determine what state
\r
3136 + that goes to, based on the state we popped back to and the rule
\r
3137 + number reduced by. */
\r
3139 + yyn = yyr1[yyn];
\r
3141 + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
\r
3142 + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
\r
3143 + yystate = yytable[yystate];
\r
3145 + yystate = yydefgoto[yyn - YYNTOKENS];
\r
3147 + goto yynewstate;
\r
3150 +/*------------------------------------.
\r
3151 +| yyerrlab -- here on detecting error |
\r
3152 +`------------------------------------*/
\r
3154 + /* If not already recovering from an error, report this error. */
\r
3155 + if (!yyerrstatus)
\r
3158 +#if ! YYERROR_VERBOSE
\r
3159 + yyerror (pc, YY_("syntax error"));
\r
3162 + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
\r
3163 + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
\r
3165 + YYSIZE_T yyalloc = 2 * yysize;
\r
3166 + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
\r
3167 + yyalloc = YYSTACK_ALLOC_MAXIMUM;
\r
3168 + if (yymsg != yymsgbuf)
\r
3169 + YYSTACK_FREE (yymsg);
\r
3170 + yymsg = (char *) YYSTACK_ALLOC (yyalloc);
\r
3172 + yymsg_alloc = yyalloc;
\r
3175 + yymsg = yymsgbuf;
\r
3176 + yymsg_alloc = sizeof yymsgbuf;
\r
3180 + if (0 < yysize && yysize <= yymsg_alloc)
\r
3182 + (void) yysyntax_error (yymsg, yystate, yychar);
\r
3183 + yyerror (pc, yymsg);
\r
3187 + yyerror (pc, YY_("syntax error"));
\r
3188 + if (yysize != 0)
\r
3189 + goto yyexhaustedlab;
\r
3197 + if (yyerrstatus == 3)
\r
3199 + /* If just tried and failed to reuse lookahead token after an
\r
3200 + error, discard it. */
\r
3202 + if (yychar <= YYEOF)
\r
3204 + /* Return failure if at end of input. */
\r
3205 + if (yychar == YYEOF)
\r
3210 + yydestruct ("Error: discarding",
\r
3211 + yytoken, &yylval, pc);
\r
3212 + yychar = YYEMPTY;
\r
3216 + /* Else will try to reuse lookahead token after shifting the error
\r
3221 +/*---------------------------------------------------.
\r
3222 +| yyerrorlab -- error raised explicitly by YYERROR. |
\r
3223 +`---------------------------------------------------*/
\r
3226 + /* Pacify compilers like GCC when the user code never invokes
\r
3227 + YYERROR and the label yyerrorlab therefore never appears in user
\r
3229 + if (/*CONSTCOND*/ 0)
\r
3230 + goto yyerrorlab;
\r
3232 + /* Do not reclaim the symbols of the rule which action triggered
\r
3233 + this YYERROR. */
\r
3234 + YYPOPSTACK (yylen);
\r
3236 + YY_STACK_PRINT (yyss, yyssp);
\r
3237 + yystate = *yyssp;
\r
3241 +/*-------------------------------------------------------------.
\r
3242 +| yyerrlab1 -- common code for both syntax error and YYERROR. |
\r
3243 +`-------------------------------------------------------------*/
\r
3245 + yyerrstatus = 3; /* Each real token shifted decrements this. */
\r
3249 + yyn = yypact[yystate];
\r
3250 + if (yyn != YYPACT_NINF)
\r
3252 + yyn += YYTERROR;
\r
3253 + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
\r
3255 + yyn = yytable[yyn];
\r
3261 + /* Pop the current state because it cannot handle the error token. */
\r
3262 + if (yyssp == yyss)
\r
3266 + yydestruct ("Error: popping",
\r
3267 + yystos[yystate], yyvsp, pc);
\r
3269 + yystate = *yyssp;
\r
3270 + YY_STACK_PRINT (yyss, yyssp);
\r
3273 + *++yyvsp = yylval;
\r
3276 + /* Shift the error token. */
\r
3277 + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
\r
3280 + goto yynewstate;
\r
3283 +/*-------------------------------------.
\r
3284 +| yyacceptlab -- YYACCEPT comes here. |
\r
3285 +`-------------------------------------*/
\r
3290 +/*-----------------------------------.
\r
3291 +| yyabortlab -- YYABORT comes here. |
\r
3292 +`-----------------------------------*/
\r
3297 +#if !defined(yyoverflow) || YYERROR_VERBOSE
\r
3298 +/*-------------------------------------------------.
\r
3299 +| yyexhaustedlab -- memory exhaustion comes here. |
\r
3300 +`-------------------------------------------------*/
\r
3302 + yyerror (pc, YY_("memory exhausted"));
\r
3304 + /* Fall through. */
\r
3308 + if (yychar != YYEMPTY)
\r
3309 + yydestruct ("Cleanup: discarding lookahead",
\r
3310 + yytoken, &yylval, pc);
\r
3311 + /* Do not reclaim the symbols of the rule which action triggered
\r
3312 + this YYABORT or YYACCEPT. */
\r
3313 + YYPOPSTACK (yylen);
\r
3314 + YY_STACK_PRINT (yyss, yyssp);
\r
3315 + while (yyssp != yyss)
\r
3317 + yydestruct ("Cleanup: popping",
\r
3318 + yystos[*yyssp], yyvsp, pc);
\r
3321 +#ifndef yyoverflow
\r
3322 + if (yyss != yyssa)
\r
3323 + YYSTACK_FREE (yyss);
\r
3325 +#if YYERROR_VERBOSE
\r
3326 + if (yymsg != yymsgbuf)
\r
3327 + YYSTACK_FREE (yymsg);
\r
3329 + /* Make sure YYID is used. */
\r
3330 + return YYID (yyresult);
\r
3335 +/* Line 1675 of yacc.c */
\r
3336 +#line 615 "getdate.y"
\r
3339 +static table const meridian_table[] =
\r
3341 + { "AM", tMERIDIAN, MERam },
\r
3342 + { "A.M.", tMERIDIAN, MERam },
\r
3343 + { "PM", tMERIDIAN, MERpm },
\r
3344 + { "P.M.", tMERIDIAN, MERpm },
\r
3348 +static table const dst_table[] =
\r
3350 + { "DST", tDST, 0 }
\r
3353 +static table const month_and_day_table[] =
\r
3355 + { "JANUARY", tMONTH, 1 },
\r
3356 + { "FEBRUARY", tMONTH, 2 },
\r
3357 + { "MARCH", tMONTH, 3 },
\r
3358 + { "APRIL", tMONTH, 4 },
\r
3359 + { "MAY", tMONTH, 5 },
\r
3360 + { "JUNE", tMONTH, 6 },
\r
3361 + { "JULY", tMONTH, 7 },
\r
3362 + { "AUGUST", tMONTH, 8 },
\r
3363 + { "SEPTEMBER",tMONTH, 9 },
\r
3364 + { "SEPT", tMONTH, 9 },
\r
3365 + { "OCTOBER", tMONTH, 10 },
\r
3366 + { "NOVEMBER", tMONTH, 11 },
\r
3367 + { "DECEMBER", tMONTH, 12 },
\r
3368 + { "SUNDAY", tDAY, 0 },
\r
3369 + { "MONDAY", tDAY, 1 },
\r
3370 + { "TUESDAY", tDAY, 2 },
\r
3371 + { "TUES", tDAY, 2 },
\r
3372 + { "WEDNESDAY",tDAY, 3 },
\r
3373 + { "WEDNES", tDAY, 3 },
\r
3374 + { "THURSDAY", tDAY, 4 },
\r
3375 + { "THUR", tDAY, 4 },
\r
3376 + { "THURS", tDAY, 4 },
\r
3377 + { "FRIDAY", tDAY, 5 },
\r
3378 + { "SATURDAY", tDAY, 6 },
\r
3382 +static table const time_units_table[] =
\r
3384 + { "YEAR", tYEAR_UNIT, 1 },
\r
3385 + { "MONTH", tMONTH_UNIT, 1 },
\r
3386 + { "FORTNIGHT",tDAY_UNIT, 14 },
\r
3387 + { "WEEK", tDAY_UNIT, 7 },
\r
3388 + { "DAY", tDAY_UNIT, 1 },
\r
3389 + { "HOUR", tHOUR_UNIT, 1 },
\r
3390 + { "MINUTE", tMINUTE_UNIT, 1 },
\r
3391 + { "MIN", tMINUTE_UNIT, 1 },
\r
3392 + { "SECOND", tSEC_UNIT, 1 },
\r
3393 + { "SEC", tSEC_UNIT, 1 },
\r
3397 +/* Assorted relative-time words. */
\r
3398 +static table const relative_time_table[] =
\r
3400 + { "TOMORROW", tDAY_SHIFT, 1 },
\r
3401 + { "YESTERDAY",tDAY_SHIFT, -1 },
\r
3402 + { "TODAY", tDAY_SHIFT, 0 },
\r
3403 + { "NOW", tDAY_SHIFT, 0 },
\r
3404 + { "LAST", tORDINAL, -1 },
\r
3405 + { "THIS", tORDINAL, 0 },
\r
3406 + { "NEXT", tORDINAL, 1 },
\r
3407 + { "FIRST", tORDINAL, 1 },
\r
3408 +/*{ "SECOND", tORDINAL, 2 }, */
\r
3409 + { "THIRD", tORDINAL, 3 },
\r
3410 + { "FOURTH", tORDINAL, 4 },
\r
3411 + { "FIFTH", tORDINAL, 5 },
\r
3412 + { "SIXTH", tORDINAL, 6 },
\r
3413 + { "SEVENTH", tORDINAL, 7 },
\r
3414 + { "EIGHTH", tORDINAL, 8 },
\r
3415 + { "NINTH", tORDINAL, 9 },
\r
3416 + { "TENTH", tORDINAL, 10 },
\r
3417 + { "ELEVENTH", tORDINAL, 11 },
\r
3418 + { "TWELFTH", tORDINAL, 12 },
\r
3419 + { "AGO", tAGO, 1 },
\r
3423 +/* The universal time zone table. These labels can be used even for
\r
3424 + time stamps that would not otherwise be valid, e.g., GMT time
\r
3425 + stamps in London during summer. */
\r
3426 +static table const universal_time_zone_table[] =
\r
3428 + { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
\r
3429 + { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
\r
3430 + { "UTC", tZONE, HOUR ( 0) },
\r
3434 +/* The time zone table. This table is necessarily incomplete, as time
\r
3435 + zone abbreviations are ambiguous; e.g. Australians interpret "EST"
\r
3436 + as Eastern time in Australia, not as US Eastern Standard Time.
\r
3437 + You cannot rely on getdate to handle arbitrary time zone
\r
3438 + abbreviations; use numeric abbreviations like `-0500' instead. */
\r
3439 +static table const time_zone_table[] =
\r
3441 + { "WET", tZONE, HOUR ( 0) }, /* Western European */
\r
3442 + { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
\r
3443 + { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
\r
3444 + { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
\r
3445 + { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
\r
3446 + { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
\r
3447 + { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
\r
3448 + { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
\r
3449 + { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
\r
3450 + { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
\r
3451 + { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
\r
3452 + { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
\r
3453 + { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
\r
3454 + { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
\r
3455 + { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
\r
3456 + { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
\r
3457 + { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
\r
3458 + { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
\r
3459 + { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
\r
3460 + { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
\r
3461 + { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
\r
3462 + { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
\r
3463 + { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
\r
3464 + { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
\r
3465 + { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
\r
3466 + { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
\r
3467 + { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
\r
3468 + { "CET", tZONE, HOUR ( 1) }, /* Central European */
\r
3469 + { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
\r
3470 + { "MET", tZONE, HOUR ( 1) }, /* Middle European */
\r
3471 + { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
\r
3472 + { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
\r
3473 + { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
\r
3474 + { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
\r
3475 + { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
\r
3476 + { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
\r
3477 + { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
\r
3478 + { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
\r
3479 + { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
\r
3480 + { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
\r
3481 + { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
\r
3482 + { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
\r
3483 + { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
\r
3484 + { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
\r
3485 + { "GST", tZONE, HOUR (10) }, /* Guam Standard */
\r
3486 + { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
\r
3487 + { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
\r
3491 +/* Military time zone table. */
\r
3492 +static table const military_table[] =
\r
3494 + { "A", tZONE, -HOUR ( 1) },
\r
3495 + { "B", tZONE, -HOUR ( 2) },
\r
3496 + { "C", tZONE, -HOUR ( 3) },
\r
3497 + { "D", tZONE, -HOUR ( 4) },
\r
3498 + { "E", tZONE, -HOUR ( 5) },
\r
3499 + { "F", tZONE, -HOUR ( 6) },
\r
3500 + { "G", tZONE, -HOUR ( 7) },
\r
3501 + { "H", tZONE, -HOUR ( 8) },
\r
3502 + { "I", tZONE, -HOUR ( 9) },
\r
3503 + { "K", tZONE, -HOUR (10) },
\r
3504 + { "L", tZONE, -HOUR (11) },
\r
3505 + { "M", tZONE, -HOUR (12) },
\r
3506 + { "N", tZONE, HOUR ( 1) },
\r
3507 + { "O", tZONE, HOUR ( 2) },
\r
3508 + { "P", tZONE, HOUR ( 3) },
\r
3509 + { "Q", tZONE, HOUR ( 4) },
\r
3510 + { "R", tZONE, HOUR ( 5) },
\r
3511 + { "S", tZONE, HOUR ( 6) },
\r
3512 + { "T", tZONE, HOUR ( 7) },
\r
3513 + { "U", tZONE, HOUR ( 8) },
\r
3514 + { "V", tZONE, HOUR ( 9) },
\r
3515 + { "W", tZONE, HOUR (10) },
\r
3516 + { "X", tZONE, HOUR (11) },
\r
3517 + { "Y", tZONE, HOUR (12) },
\r
3518 + { "Z", tZONE, HOUR ( 0) },
\r
3525 +/* Convert a time zone expressed as HH:MM into an integer count of
\r
3526 + minutes. If MM is negative, then S is of the form HHMM and needs
\r
3527 + to be picked apart; otherwise, S is of the form HH. As specified in
\r
3528 + http://www.opengroup.org/susv3xbd/xbd_chap08.html#tag_08_03, allow
\r
3529 + only valid TZ range, and consider first two digits as hours, if no
\r
3530 + minutes specified. */
\r
3533 +time_zone_hhmm (parser_control *pc, textint s, long int mm)
\r
3535 + long int n_minutes;
\r
3537 + /* If the length of S is 1 or 2 and no minutes are specified,
\r
3538 + interpret it as a number of hours. */
\r
3539 + if (s.digits <= 2 && mm < 0)
\r
3543 + n_minutes = (s.value / 100) * 60 + s.value % 100;
\r
3545 + n_minutes = s.value * 60 + (s.negative ? -mm : mm);
\r
3547 + /* If the absolute number of minutes is larger than 24 hours,
\r
3548 + arrange to reject it by incrementing pc->zones_seen. Thus,
\r
3549 + we allow only values in the range UTC-24:00 to UTC+24:00. */
\r
3550 + if (24 * 60 < abs (n_minutes))
\r
3551 + pc->zones_seen++;
\r
3553 + return n_minutes;
\r
3557 +to_hour (long int hours, int meridian)
\r
3559 + switch (meridian)
\r
3561 + default: /* Pacify GCC. */
\r
3563 + return 0 <= hours && hours < 24 ? hours : -1;
\r
3565 + return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
\r
3567 + return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
\r
3572 +to_year (textint textyear)
\r
3574 + long int year = textyear.value;
\r
3579 + /* XPG4 suggests that years 00-68 map to 2000-2068, and
\r
3580 + years 69-99 map to 1969-1999. */
\r
3581 + else if (textyear.digits == 2)
\r
3582 + year += year < 69 ? 2000 : 1900;
\r
3587 +static table const *
\r
3588 +lookup_zone (parser_control const *pc, char const *name)
\r
3590 + table const *tp;
\r
3592 + for (tp = universal_time_zone_table; tp->name; tp++)
\r
3593 + if (strcmp (name, tp->name) == 0)
\r
3596 + /* Try local zone abbreviations before those in time_zone_table, as
\r
3597 + the local ones are more likely to be right. */
\r
3598 + for (tp = pc->local_time_zone_table; tp->name; tp++)
\r
3599 + if (strcmp (name, tp->name) == 0)
\r
3602 + for (tp = time_zone_table; tp->name; tp++)
\r
3603 + if (strcmp (name, tp->name) == 0)
\r
3609 +#if ! HAVE_TM_GMTOFF
\r
3610 +/* Yield the difference between *A and *B,
\r
3611 + measured in seconds, ignoring leap seconds.
\r
3612 + The body of this function is taken directly from the GNU C Library;
\r
3613 + see src/strftime.c. */
\r
3615 +tm_diff (struct tm const *a, struct tm const *b)
\r
3617 + /* Compute intervening leap days correctly even if year is negative.
\r
3618 + Take care to avoid int overflow in leap day calculations. */
\r
3619 + int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
\r
3620 + int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
\r
3621 + int a100 = a4 / 25 - (a4 % 25 < 0);
\r
3622 + int b100 = b4 / 25 - (b4 % 25 < 0);
\r
3623 + int a400 = SHR (a100, 2);
\r
3624 + int b400 = SHR (b100, 2);
\r
3625 + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
\r
3626 + long int ayear = a->tm_year;
\r
3627 + long int years = ayear - b->tm_year;
\r
3628 + long int days = (365 * years + intervening_leap_days
\r
3629 + + (a->tm_yday - b->tm_yday));
\r
3630 + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
\r
3631 + + (a->tm_min - b->tm_min))
\r
3632 + + (a->tm_sec - b->tm_sec));
\r
3634 +#endif /* ! HAVE_TM_GMTOFF */
\r
3636 +static table const *
\r
3637 +lookup_word (parser_control const *pc, char *word)
\r
3642 + table const *tp;
\r
3643 + bool period_found;
\r
3646 + /* Make it uppercase. */
\r
3647 + for (p = word; *p; p++)
\r
3649 + unsigned char ch = *p;
\r
3650 + *p = c_toupper (ch);
\r
3653 + for (tp = meridian_table; tp->name; tp++)
\r
3654 + if (strcmp (word, tp->name) == 0)
\r
3657 + /* See if we have an abbreviation for a month. */
\r
3658 + wordlen = strlen (word);
\r
3659 + abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
\r
3661 + for (tp = month_and_day_table; tp->name; tp++)
\r
3662 + if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
\r
3665 + if ((tp = lookup_zone (pc, word)))
\r
3668 + if (strcmp (word, dst_table[0].name) == 0)
\r
3669 + return dst_table;
\r
3671 + for (tp = time_units_table; tp->name; tp++)
\r
3672 + if (strcmp (word, tp->name) == 0)
\r
3675 + /* Strip off any plural and try the units table again. */
\r
3676 + if (word[wordlen - 1] == 'S')
\r
3678 + word[wordlen - 1] = '\0';
\r
3679 + for (tp = time_units_table; tp->name; tp++)
\r
3680 + if (strcmp (word, tp->name) == 0)
\r
3682 + word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
\r
3685 + for (tp = relative_time_table; tp->name; tp++)
\r
3686 + if (strcmp (word, tp->name) == 0)
\r
3689 + /* Military time zones. */
\r
3690 + if (wordlen == 1)
\r
3691 + for (tp = military_table; tp->name; tp++)
\r
3692 + if (word[0] == tp->name[0])
\r
3695 + /* Drop out any periods and try the time zone table again. */
\r
3696 + for (period_found = false, p = q = word; (*p = *q); q++)
\r
3698 + period_found = true;
\r
3701 + if (period_found && (tp = lookup_zone (pc, word)))
\r
3708 +yylex (YYSTYPE *lvalp, parser_control *pc)
\r
3710 + unsigned char c;
\r
3715 + while (c = *pc->input, c_isspace (c))
\r
3718 + if (ISDIGIT (c) || c == '-' || c == '+')
\r
3722 + unsigned long int value;
\r
3723 + if (c == '-' || c == '+')
\r
3725 + sign = c == '-' ? -1 : 1;
\r
3726 + while (c = *++pc->input, c_isspace (c))
\r
3728 + if (! ISDIGIT (c))
\r
3729 + /* skip the '-' sign */
\r
3735 + for (value = 0; ; value *= 10)
\r
3737 + unsigned long int value1 = value + (c - '0');
\r
3738 + if (value1 < value)
\r
3742 + if (! ISDIGIT (c))
\r
3744 + if (ULONG_MAX / 10 < value)
\r
3747 + if ((c == '.' || c == ',') && ISDIGIT (p[1]))
\r
3752 + unsigned long int value1;
\r
3754 + /* Check for overflow when converting value to time_t. */
\r
3769 + if (value != value1)
\r
3772 + /* Accumulate fraction, to ns precision. */
\r
3774 + ns = *p++ - '0';
\r
3775 + for (digits = 2; digits <= LOG10_BILLION; digits++)
\r
3778 + if (ISDIGIT (*p))
\r
3779 + ns += *p++ - '0';
\r
3782 + /* Skip excess digits, truncating toward -Infinity. */
\r
3784 + for (; ISDIGIT (*p); p++)
\r
3790 + while (ISDIGIT (*p))
\r
3793 + /* Adjust to the timespec convention, which is that
\r
3794 + tv_nsec is always a positive offset even if tv_sec is
\r
3796 + if (sign < 0 && ns)
\r
3801 + ns = BILLION - ns;
\r
3804 + lvalp->timespec.tv_sec = s;
\r
3805 + lvalp->timespec.tv_nsec = ns;
\r
3807 + return sign ? tSDECIMAL_NUMBER : tUDECIMAL_NUMBER;
\r
3811 + lvalp->textintval.negative = sign < 0;
\r
3814 + lvalp->textintval.value = - value;
\r
3815 + if (0 < lvalp->textintval.value)
\r
3820 + lvalp->textintval.value = value;
\r
3821 + if (lvalp->textintval.value < 0)
\r
3824 + lvalp->textintval.digits = p - pc->input;
\r
3826 + return sign ? tSNUMBER : tUNUMBER;
\r
3830 + if (c_isalpha (c))
\r
3834 + table const *tp;
\r
3838 + if (p < buff + sizeof buff - 1)
\r
3840 + c = *++pc->input;
\r
3842 + while (c_isalpha (c) || c == '.');
\r
3845 + tp = lookup_word (pc, buff);
\r
3848 + lvalp->intval = tp->value;
\r
3849 + return tp->type;
\r
3853 + return *pc->input++;
\r
3857 + c = *pc->input++;
\r
3862 + else if (c == ')')
\r
3865 + while (count != 0);
\r
3869 +/* Do nothing if the parser reports an error. */
\r
3871 +yyerror (parser_control const *pc _GL_UNUSED,
\r
3872 + char const *s _GL_UNUSED)
\r
3877 +/* If *TM0 is the old and *TM1 is the new value of a struct tm after
\r
3878 + passing it to mktime, return true if it's OK that mktime returned T.
\r
3879 + It's not OK if *TM0 has out-of-range members. */
\r
3882 +mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)
\r
3884 + if (t == (time_t) -1)
\r
3886 + /* Guard against falsely reporting an error when parsing a time
\r
3887 + stamp that happens to equal (time_t) -1, on a host that
\r
3888 + supports such a time stamp. */
\r
3889 + tm1 = localtime (&t);
\r
3894 + return ! ((tm0->tm_sec ^ tm1->tm_sec)
\r
3895 + | (tm0->tm_min ^ tm1->tm_min)
\r
3896 + | (tm0->tm_hour ^ tm1->tm_hour)
\r
3897 + | (tm0->tm_mday ^ tm1->tm_mday)
\r
3898 + | (tm0->tm_mon ^ tm1->tm_mon)
\r
3899 + | (tm0->tm_year ^ tm1->tm_year));
\r
3902 +/* A reasonable upper bound for the size of ordinary TZ strings.
\r
3903 + Use heap allocation if TZ's length exceeds this. */
\r
3904 +enum { TZBUFSIZE = 100 };
\r
3906 +/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated
\r
3909 +get_tz (char tzbuf[TZBUFSIZE])
\r
3911 + char *tz = getenv ("TZ");
\r
3914 + size_t tzsize = strlen (tz) + 1;
\r
3915 + tz = (tzsize <= TZBUFSIZE
\r
3916 + ? memcpy (tzbuf, tz, tzsize)
\r
3917 + : xmemdup (tz, tzsize));
\r
3922 +/* Parse a date/time string, storing the resulting time value into *RESULT.
\r
3923 + The string itself is pointed to by P. Return true if successful.
\r
3924 + P can be an incomplete or relative time specification; if so, use
\r
3925 + *NOW as the basis for the returned time. */
\r
3927 +get_date (struct timespec *result, char const *p, struct timespec const *now)
\r
3930 + long int Start_ns;
\r
3931 + struct tm const *tmp;
\r
3934 + parser_control pc;
\r
3935 + struct timespec gettime_buffer;
\r
3936 + unsigned char c;
\r
3937 + bool tz_was_altered = false;
\r
3938 + char *tz0 = NULL;
\r
3939 + char tz0buf[TZBUFSIZE];
\r
3944 + gettime (&gettime_buffer);
\r
3945 + now = &gettime_buffer;
\r
3948 + Start = now->tv_sec;
\r
3949 + Start_ns = now->tv_nsec;
\r
3951 + tmp = localtime (&now->tv_sec);
\r
3955 + while (c = *p, c_isspace (c))
\r
3958 + if (strncmp (p, "TZ=\"", 4) == 0)
\r
3960 + char const *tzbase = p + 4;
\r
3961 + size_t tzsize = 1;
\r
3964 + for (s = tzbase; *s; s++, tzsize++)
\r
3968 + if (! (*s == '\\' || *s == '"'))
\r
3971 + else if (*s == '"')
\r
3975 + char tz1buf[TZBUFSIZE];
\r
3976 + bool large_tz = TZBUFSIZE < tzsize;
\r
3978 + /* Free tz0, in case this is the 2nd or subsequent time through. */
\r
3980 + tz0 = get_tz (tz0buf);
\r
3981 + z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
\r
3982 + for (s = tzbase; *s != '"'; s++)
\r
3983 + *z++ = *(s += *s == '\\');
\r
3985 + setenv_ok = setenv ("TZ", tz1, 1) == 0;
\r
3990 + tz_was_altered = true;
\r
3995 + /* As documented, be careful to treat the empty string just like
\r
3996 + a date string of "0". Without this, an empty string would be
\r
3997 + declared invalid when parsed during a DST transition. */
\r
4002 + pc.year.value = tmp->tm_year;
\r
4003 + pc.year.value += TM_YEAR_BASE;
\r
4004 + pc.year.digits = 0;
\r
4005 + pc.month = tmp->tm_mon + 1;
\r
4006 + pc.day = tmp->tm_mday;
\r
4007 + pc.hour = tmp->tm_hour;
\r
4008 + pc.minutes = tmp->tm_min;
\r
4009 + pc.seconds.tv_sec = tmp->tm_sec;
\r
4010 + pc.seconds.tv_nsec = Start_ns;
\r
4011 + tm.tm_isdst = tmp->tm_isdst;
\r
4013 + pc.meridian = MER24;
\r
4014 + pc.rel = RELATIVE_TIME_0;
\r
4015 + pc.timespec_seen = false;
\r
4016 + pc.rels_seen = false;
\r
4017 + pc.dates_seen = 0;
\r
4018 + pc.days_seen = 0;
\r
4019 + pc.times_seen = 0;
\r
4020 + pc.local_zones_seen = 0;
\r
4021 + pc.dsts_seen = 0;
\r
4022 + pc.zones_seen = 0;
\r
4024 +#if HAVE_STRUCT_TM_TM_ZONE
\r
4025 + pc.local_time_zone_table[0].name = tmp->tm_zone;
\r
4026 + pc.local_time_zone_table[0].type = tLOCAL_ZONE;
\r
4027 + pc.local_time_zone_table[0].value = tmp->tm_isdst;
\r
4028 + pc.local_time_zone_table[1].name = NULL;
\r
4030 + /* Probe the names used in the next three calendar quarters, looking
\r
4031 + for a tm_isdst different from the one we already have. */
\r
4034 + for (quarter = 1; quarter <= 3; quarter++)
\r
4036 + time_t probe = Start + quarter * (90 * 24 * 60 * 60);
\r
4037 + struct tm const *probe_tm = localtime (&probe);
\r
4038 + if (probe_tm && probe_tm->tm_zone
\r
4039 + && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
\r
4042 + pc.local_time_zone_table[1].name = probe_tm->tm_zone;
\r
4043 + pc.local_time_zone_table[1].type = tLOCAL_ZONE;
\r
4044 + pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
\r
4045 + pc.local_time_zone_table[2].name = NULL;
\r
4054 +# if !HAVE_DECL_TZNAME
\r
4055 + extern char *tzname[];
\r
4058 + for (i = 0; i < 2; i++)
\r
4060 + pc.local_time_zone_table[i].name = tzname[i];
\r
4061 + pc.local_time_zone_table[i].type = tLOCAL_ZONE;
\r
4062 + pc.local_time_zone_table[i].value = i;
\r
4064 + pc.local_time_zone_table[i].name = NULL;
\r
4067 + pc.local_time_zone_table[0].name = NULL;
\r
4071 + if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
\r
4072 + && ! strcmp (pc.local_time_zone_table[0].name,
\r
4073 + pc.local_time_zone_table[1].name))
\r
4075 + /* This locale uses the same abbrevation for standard and
\r
4076 + daylight times. So if we see that abbreviation, we don't
\r
4077 + know whether it's daylight time. */
\r
4078 + pc.local_time_zone_table[0].value = -1;
\r
4079 + pc.local_time_zone_table[1].name = NULL;
\r
4082 + if (yyparse (&pc) != 0)
\r
4085 + if (pc.timespec_seen)
\r
4086 + *result = pc.seconds;
\r
4089 + if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
\r
4090 + | (pc.local_zones_seen + pc.zones_seen)))
\r
4093 + tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;
\r
4094 + tm.tm_mon = pc.month - 1;
\r
4095 + tm.tm_mday = pc.day;
\r
4096 + if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
\r
4098 + tm.tm_hour = to_hour (pc.hour, pc.meridian);
\r
4099 + if (tm.tm_hour < 0)
\r
4101 + tm.tm_min = pc.minutes;
\r
4102 + tm.tm_sec = pc.seconds.tv_sec;
\r
4106 + tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
\r
4107 + pc.seconds.tv_nsec = 0;
\r
4110 + /* Let mktime deduce tm_isdst if we have an absolute time stamp. */
\r
4111 + if (pc.dates_seen | pc.days_seen | pc.times_seen)
\r
4112 + tm.tm_isdst = -1;
\r
4114 + /* But if the input explicitly specifies local time with or without
\r
4115 + DST, give mktime that information. */
\r
4116 + if (pc.local_zones_seen)
\r
4117 + tm.tm_isdst = pc.local_isdst;
\r
4121 + Start = mktime (&tm);
\r
4123 + if (! mktime_ok (&tm0, &tm, Start))
\r
4125 + if (! pc.zones_seen)
\r
4129 + /* Guard against falsely reporting errors near the time_t
\r
4130 + boundaries when parsing times in other time zones. For
\r
4131 + example, suppose the input string "1969-12-31 23:00:00 -0100",
\r
4132 + the current time zone is 8 hours ahead of UTC, and the min
\r
4133 + time_t value is 1970-01-01 00:00:00 UTC. Then the min
\r
4134 + localtime value is 1970-01-01 08:00:00, and mktime will
\r
4135 + therefore fail on 1969-12-31 23:00:00. To work around the
\r
4136 + problem, set the time zone to 1 hour behind UTC temporarily
\r
4137 + by setting TZ="XXX1:00" and try mktime again. */
\r
4139 + long int time_zone = pc.time_zone;
\r
4140 + long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
\r
4141 + long int abs_time_zone_hour = abs_time_zone / 60;
\r
4142 + int abs_time_zone_min = abs_time_zone % 60;
\r
4143 + char tz1buf[sizeof "XXX+0:00"
\r
4144 + + sizeof pc.time_zone * CHAR_BIT / 3];
\r
4145 + if (!tz_was_altered)
\r
4146 + tz0 = get_tz (tz0buf);
\r
4147 + sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
\r
4148 + abs_time_zone_hour, abs_time_zone_min);
\r
4149 + if (setenv ("TZ", tz1buf, 1) != 0)
\r
4151 + tz_was_altered = true;
\r
4153 + Start = mktime (&tm);
\r
4154 + if (! mktime_ok (&tm0, &tm, Start))
\r
4159 + if (pc.days_seen && ! pc.dates_seen)
\r
4161 + tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
\r
4162 + + 7 * (pc.day_ordinal
\r
4163 + - (0 < pc.day_ordinal
\r
4164 + && tm.tm_wday != pc.day_number)));
\r
4165 + tm.tm_isdst = -1;
\r
4166 + Start = mktime (&tm);
\r
4167 + if (Start == (time_t) -1)
\r
4171 + /* Add relative date. */
\r
4172 + if (pc.rel.year | pc.rel.month | pc.rel.day)
\r
4174 + int year = tm.tm_year + pc.rel.year;
\r
4175 + int month = tm.tm_mon + pc.rel.month;
\r
4176 + int day = tm.tm_mday + pc.rel.day;
\r
4177 + if (((year < tm.tm_year) ^ (pc.rel.year < 0))
\r
4178 + | ((month < tm.tm_mon) ^ (pc.rel.month < 0))
\r
4179 + | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))
\r
4181 + tm.tm_year = year;
\r
4182 + tm.tm_mon = month;
\r
4183 + tm.tm_mday = day;
\r
4184 + tm.tm_hour = tm0.tm_hour;
\r
4185 + tm.tm_min = tm0.tm_min;
\r
4186 + tm.tm_sec = tm0.tm_sec;
\r
4187 + tm.tm_isdst = tm0.tm_isdst;
\r
4188 + Start = mktime (&tm);
\r
4189 + if (Start == (time_t) -1)
\r
4193 + /* The only "output" of this if-block is an updated Start value,
\r
4194 + so this block must follow others that clobber Start. */
\r
4195 + if (pc.zones_seen)
\r
4197 + long int delta = pc.time_zone * 60;
\r
4199 +#ifdef HAVE_TM_GMTOFF
\r
4200 + delta -= tm.tm_gmtoff;
\r
4202 + time_t t = Start;
\r
4203 + struct tm const *gmt = gmtime (&t);
\r
4206 + delta -= tm_diff (&tm, gmt);
\r
4208 + t1 = Start - delta;
\r
4209 + if ((Start < t1) != (delta < 0))
\r
4210 + goto fail; /* time_t overflow */
\r
4214 + /* Add relative hours, minutes, and seconds. On hosts that support
\r
4215 + leap seconds, ignore the possibility of leap seconds; e.g.,
\r
4216 + "+ 10 minutes" adds 600 seconds, even if one of them is a
\r
4217 + leap second. Typically this is not what the user wants, but it's
\r
4218 + too hard to do it the other way, because the time zone indicator
\r
4219 + must be applied before relative times, and if mktime is applied
\r
4220 + again the time zone will be lost. */
\r
4222 + long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
\r
4223 + long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
\r
4224 + time_t t0 = Start;
\r
4225 + long int d1 = 60 * 60 * pc.rel.hour;
\r
4226 + time_t t1 = t0 + d1;
\r
4227 + long int d2 = 60 * pc.rel.minutes;
\r
4228 + time_t t2 = t1 + d2;
\r
4229 + long_time_t d3 = pc.rel.seconds;
\r
4230 + long_time_t t3 = t2 + d3;
\r
4231 + long int d4 = (sum_ns - normalized_ns) / BILLION;
\r
4232 + long_time_t t4 = t3 + d4;
\r
4235 + if ((d1 / (60 * 60) ^ pc.rel.hour)
\r
4236 + | (d2 / 60 ^ pc.rel.minutes)
\r
4237 + | ((t1 < t0) ^ (d1 < 0))
\r
4238 + | ((t2 < t1) ^ (d2 < 0))
\r
4239 + | ((t3 < t2) ^ (d3 < 0))
\r
4240 + | ((t4 < t3) ^ (d4 < 0))
\r
4244 + result->tv_sec = t5;
\r
4245 + result->tv_nsec = normalized_ns;
\r
4254 + if (tz_was_altered)
\r
4255 + ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;
\r
4256 + if (tz0 != tz0buf)
\r
4264 +main (int ac, char **av)
\r
4266 + char buff[BUFSIZ];
\r
4268 + printf ("Enter date, or blank line to exit.\n\t> ");
\r
4269 + fflush (stdout);
\r
4271 + buff[BUFSIZ - 1] = '\0';
\r
4272 + while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
\r
4274 + struct timespec d;
\r
4275 + struct tm const *tm;
\r
4276 + if (! get_date (&d, buff, NULL))
\r
4277 + printf ("Bad format - couldn't convert.\n");
\r
4278 + else if (! (tm = localtime (&d.tv_sec)))
\r
4280 + long int sec = d.tv_sec;
\r
4281 + printf ("localtime (%ld) failed\n", sec);
\r
4285 + int ns = d.tv_nsec;
\r
4286 + printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
\r
4287 + tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
\r
4288 + tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
\r
4290 + printf ("\t> ");
\r
4291 + fflush (stdout);
\r
4295 +#endif /* TEST */
\r
4297 diff --git a/lib/getdate.h b/lib/getdate.h
\r
4298 new file mode 100644
\r
4299 index 0000000..22cc2c0
\r
4301 +++ b/lib/getdate.h
\r
4303 +/* Parse a string into an internal time stamp.
\r
4305 + Copyright (C) 1995, 1997, 1998, 2003, 2004, 2007, 2009, 2010 Free Software
\r
4306 + Foundation, Inc.
\r
4308 + This program is free software: you can redistribute it and/or modify
\r
4309 + it under the terms of the GNU General Public License as published by
\r
4310 + the Free Software Foundation; either version 3 of the License, or
\r
4311 + (at your option) any later version.
\r
4313 + This program is distributed in the hope that it will be useful,
\r
4314 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
4315 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
4316 + GNU General Public License for more details.
\r
4318 + You should have received a copy of the GNU General Public License
\r
4319 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
4321 +#include <stdbool.h>
\r
4322 +#include <time.h>
\r
4324 +bool get_date (struct timespec *, char const *, struct timespec const *);
\r
4325 diff --git a/lib/getdate.y b/lib/getdate.y
\r
4326 new file mode 100644
\r
4327 index 0000000..445865b
\r
4329 +++ b/lib/getdate.y
\r
4330 @@ -0,0 +1,1572 @@
\r
4332 +/* Parse a string into an internal time stamp.
\r
4334 + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
\r
4335 + 2010 Free Software Foundation, Inc.
\r
4337 + This program is free software: you can redistribute it and/or modify
\r
4338 + it under the terms of the GNU General Public License as published by
\r
4339 + the Free Software Foundation; either version 3 of the License, or
\r
4340 + (at your option) any later version.
\r
4342 + This program is distributed in the hope that it will be useful,
\r
4343 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
4344 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
4345 + GNU General Public License for more details.
\r
4347 + You should have received a copy of the GNU General Public License
\r
4348 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
4350 +/* Originally written by Steven M. Bellovin <smb@research.att.com> while
\r
4351 + at the University of North Carolina at Chapel Hill. Later tweaked by
\r
4352 + a couple of people on Usenet. Completely overhauled by Rich $alz
\r
4353 + <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
\r
4355 + Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
\r
4356 + the right thing about local DST. Also modified by Paul Eggert
\r
4357 + <eggert@cs.ucla.edu> in February 2004 to support
\r
4358 + nanosecond-resolution time stamps, and in October 2004 to support
\r
4359 + TZ strings in dates. */
\r
4361 +/* FIXME: Check for arithmetic overflow in all cases, not just
\r
4362 + some of them. */
\r
4364 +#include <config.h>
\r
4366 +#include "getdate.h"
\r
4368 +#include "intprops.h"
\r
4369 +#include "timespec.h"
\r
4370 +#include "verify.h"
\r
4372 +/* There's no need to extend the stack, so there's no need to involve
\r
4374 +#define YYSTACK_USE_ALLOCA 0
\r
4376 +/* Tell Bison how much stack space is needed. 20 should be plenty for
\r
4377 + this grammar, which is not right recursive. Beware setting it too
\r
4378 + high, since that might cause problems on machines whose
\r
4379 + implementations have lame stack-overflow checking. */
\r
4380 +#define YYMAXDEPTH 20
\r
4381 +#define YYINITDEPTH YYMAXDEPTH
\r
4383 +/* Since the code of getdate.y is not included in the Emacs executable
\r
4384 + itself, there is no need to #define static in this file. Even if
\r
4385 + the code were included in the Emacs executable, it probably
\r
4386 + wouldn't do any harm to #undef it here; this will only cause
\r
4387 + problems if we try to write to a static variable, which I don't
\r
4388 + think this code needs to do. */
\r
4393 +#include <c-ctype.h>
\r
4394 +#include <limits.h>
\r
4395 +#include <stdio.h>
\r
4396 +#include <stdlib.h>
\r
4397 +#include <string.h>
\r
4399 +#include "xalloc.h"
\r
4402 +/* ISDIGIT differs from isdigit, as follows:
\r
4403 + - Its arg may be any int or unsigned int; it need not be an unsigned char
\r
4405 + - It's typically faster.
\r
4406 + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
\r
4407 + isdigit unless it's important to use the locale's definition
\r
4408 + of `digit' even when the host does not conform to POSIX. */
\r
4409 +#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
\r
4411 +/* Shift A right by B bits portably, by dividing A by 2**B and
\r
4412 + truncating towards minus infinity. A and B should be free of side
\r
4413 + effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
\r
4414 + INT_BITS is the number of useful bits in an int. GNU code can
\r
4415 + assume that INT_BITS is at least 32.
\r
4417 + ISO C99 says that A >> B is implementation-defined if A < 0. Some
\r
4418 + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
\r
4419 + right in the usual way when A < 0, so SHR falls back on division if
\r
4420 + ordinary A >> B doesn't seem to be the usual signed shift. */
\r
4421 +#define SHR(a, b) \
\r
4422 + (-1 >> 1 == -1 \
\r
4424 + : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
\r
4426 +#define EPOCH_YEAR 1970
\r
4427 +#define TM_YEAR_BASE 1900
\r
4429 +#define HOUR(x) ((x) * 60)
\r
4431 +/* long_time_t is a signed integer type that contains all time_t values. */
\r
4432 +verify (TYPE_IS_INTEGER (time_t));
\r
4433 +#if TIME_T_FITS_IN_LONG_INT
\r
4434 +typedef long int long_time_t;
\r
4436 +typedef time_t long_time_t;
\r
4439 +/* Lots of this code assumes time_t and time_t-like values fit into
\r
4441 +verify (TYPE_MINIMUM (long_time_t) <= TYPE_MINIMUM (time_t)
\r
4442 + && TYPE_MAXIMUM (time_t) <= TYPE_MAXIMUM (long_time_t));
\r
4444 +/* FIXME: It also assumes that signed integer overflow silently wraps around,
\r
4445 + but this is not true any more with recent versions of GCC 4. */
\r
4447 +/* An integer value, and the number of digits in its textual
\r
4448 + representation. */
\r
4456 +/* An entry in the lexical lookup table. */
\r
4459 + char const *name;
\r
4464 +/* Meridian: am, pm, or 24-hour style. */
\r
4465 +enum { MERam, MERpm, MER24 };
\r
4467 +enum { BILLION = 1000000000, LOG10_BILLION = 9 };
\r
4469 +/* Relative times. */
\r
4472 + /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
4477 + long int minutes;
\r
4478 + long_time_t seconds;
\r
4482 +#if HAVE_COMPOUND_LITERALS
\r
4483 +# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
\r
4485 +static relative_time const RELATIVE_TIME_0;
\r
4488 +/* Information passed to and from the parser. */
\r
4491 + /* The input string remaining to be parsed. */
\r
4492 + const char *input;
\r
4494 + /* N, if this is the Nth Tuesday. */
\r
4495 + long int day_ordinal;
\r
4497 + /* Day of week; Sunday is 0. */
\r
4500 + /* tm_isdst flag for the local zone. */
\r
4501 + int local_isdst;
\r
4503 + /* Time zone, in minutes east of UTC. */
\r
4504 + long int time_zone;
\r
4506 + /* Style used for time. */
\r
4509 + /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
4514 + long int minutes;
\r
4515 + struct timespec seconds; /* includes nanoseconds */
\r
4517 + /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
\r
4518 + relative_time rel;
\r
4520 + /* Presence or counts of nonterminals of various flavors parsed so far. */
\r
4521 + bool timespec_seen;
\r
4523 + size_t dates_seen;
\r
4524 + size_t days_seen;
\r
4525 + size_t local_zones_seen;
\r
4526 + size_t dsts_seen;
\r
4527 + size_t times_seen;
\r
4528 + size_t zones_seen;
\r
4530 + /* Table of local time zone abbrevations, terminated by a null entry. */
\r
4531 + table local_time_zone_table[3];
\r
4532 +} parser_control;
\r
4535 +static int yylex (union YYSTYPE *, parser_control *);
\r
4536 +static int yyerror (parser_control const *, char const *);
\r
4537 +static long int time_zone_hhmm (parser_control *, textint, long int);
\r
4539 +/* Extract into *PC any date and time info from a string of digits
\r
4540 + of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
\r
4543 +digits_to_date_time (parser_control *pc, textint text_int)
\r
4545 + if (pc->dates_seen && ! pc->year.digits
\r
4546 + && ! pc->rels_seen && (pc->times_seen || 2 < text_int.digits))
\r
4547 + pc->year = text_int;
\r
4550 + if (4 < text_int.digits)
\r
4552 + pc->dates_seen++;
\r
4553 + pc->day = text_int.value % 100;
\r
4554 + pc->month = (text_int.value / 100) % 100;
\r
4555 + pc->year.value = text_int.value / 10000;
\r
4556 + pc->year.digits = text_int.digits - 4;
\r
4560 + pc->times_seen++;
\r
4561 + if (text_int.digits <= 2)
\r
4563 + pc->hour = text_int.value;
\r
4564 + pc->minutes = 0;
\r
4568 + pc->hour = text_int.value / 100;
\r
4569 + pc->minutes = text_int.value % 100;
\r
4571 + pc->seconds.tv_sec = 0;
\r
4572 + pc->seconds.tv_nsec = 0;
\r
4573 + pc->meridian = MER24;
\r
4578 +/* Increment PC->rel by FACTOR * REL (FACTOR is 1 or -1). */
\r
4580 +apply_relative_time (parser_control *pc, relative_time rel, int factor)
\r
4582 + pc->rel.ns += factor * rel.ns;
\r
4583 + pc->rel.seconds += factor * rel.seconds;
\r
4584 + pc->rel.minutes += factor * rel.minutes;
\r
4585 + pc->rel.hour += factor * rel.hour;
\r
4586 + pc->rel.day += factor * rel.day;
\r
4587 + pc->rel.month += factor * rel.month;
\r
4588 + pc->rel.year += factor * rel.year;
\r
4589 + pc->rels_seen = true;
\r
4592 +/* Set PC-> hour, minutes, seconds and nanoseconds members from arguments. */
\r
4594 +set_hhmmss (parser_control *pc, long int hour, long int minutes,
\r
4595 + time_t sec, long int nsec)
\r
4597 + pc->hour = hour;
\r
4598 + pc->minutes = minutes;
\r
4599 + pc->seconds.tv_sec = sec;
\r
4600 + pc->seconds.tv_nsec = nsec;
\r
4605 +/* We want a reentrant parser, even if the TZ manipulation and the calls to
\r
4606 + localtime and gmtime are not reentrant. */
\r
4608 +%parse-param { parser_control *pc }
\r
4609 +%lex-param { parser_control *pc }
\r
4611 +/* This grammar has 20 shift/reduce conflicts. */
\r
4616 + long int intval;
\r
4617 + textint textintval;
\r
4618 + struct timespec timespec;
\r
4619 + relative_time rel;
\r
4624 +%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT
\r
4625 +%token <intval> tDAY_UNIT tDAY_SHIFT
\r
4627 +%token <intval> tDAY tDAYZONE tLOCAL_ZONE tMERIDIAN
\r
4628 +%token <intval> tMONTH tORDINAL tZONE
\r
4630 +%token <textintval> tSNUMBER tUNUMBER
\r
4631 +%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER
\r
4633 +%type <intval> o_colon_minutes o_merid
\r
4634 +%type <timespec> seconds signed_seconds unsigned_seconds
\r
4636 +%type <rel> relunit relunit_snumber dayshift
\r
4648 + pc->seconds = $2;
\r
4649 + pc->timespec_seen = true;
\r
4660 + { pc->times_seen++; }
\r
4662 + { pc->local_zones_seen++; }
\r
4664 + { pc->zones_seen++; }
\r
4666 + { pc->dates_seen++; }
\r
4668 + { pc->days_seen++; }
\r
4675 + tUNUMBER tMERIDIAN
\r
4677 + set_hhmmss (pc, $1.value, 0, 0, 0);
\r
4678 + pc->meridian = $2;
\r
4680 + | tUNUMBER ':' tUNUMBER o_merid
\r
4682 + set_hhmmss (pc, $1.value, $3.value, 0, 0);
\r
4683 + pc->meridian = $4;
\r
4685 + | tUNUMBER ':' tUNUMBER tSNUMBER o_colon_minutes
\r
4687 + set_hhmmss (pc, $1.value, $3.value, 0, 0);
\r
4688 + pc->meridian = MER24;
\r
4689 + pc->zones_seen++;
\r
4690 + pc->time_zone = time_zone_hhmm (pc, $4, $5);
\r
4692 + | tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid
\r
4694 + set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
\r
4695 + pc->meridian = $6;
\r
4697 + | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER o_colon_minutes
\r
4699 + set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
\r
4700 + pc->meridian = MER24;
\r
4701 + pc->zones_seen++;
\r
4702 + pc->time_zone = time_zone_hhmm (pc, $6, $7);
\r
4709 + pc->local_isdst = $1;
\r
4710 + pc->dsts_seen += (0 < $1);
\r
4712 + | tLOCAL_ZONE tDST
\r
4714 + pc->local_isdst = 1;
\r
4715 + pc->dsts_seen += (0 < $1) + 1;
\r
4721 + { pc->time_zone = $1; }
\r
4722 + | tZONE relunit_snumber
\r
4723 + { pc->time_zone = $1;
\r
4724 + apply_relative_time (pc, $2, 1); }
\r
4725 + | tZONE tSNUMBER o_colon_minutes
\r
4726 + { pc->time_zone = $1 + time_zone_hhmm (pc, $2, $3); }
\r
4728 + { pc->time_zone = $1 + 60; }
\r
4730 + { pc->time_zone = $1 + 60; }
\r
4736 + pc->day_ordinal = 0;
\r
4737 + pc->day_number = $1;
\r
4741 + pc->day_ordinal = 0;
\r
4742 + pc->day_number = $1;
\r
4746 + pc->day_ordinal = $1;
\r
4747 + pc->day_number = $2;
\r
4751 + pc->day_ordinal = $1.value;
\r
4752 + pc->day_number = $2;
\r
4757 + tUNUMBER '/' tUNUMBER
\r
4759 + pc->month = $1.value;
\r
4760 + pc->day = $3.value;
\r
4762 + | tUNUMBER '/' tUNUMBER '/' tUNUMBER
\r
4764 + /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
\r
4765 + otherwise as MM/DD/YY.
\r
4766 + The goal in recognizing YYYY/MM/DD is solely to support legacy
\r
4767 + machine-generated dates like those in an RCS log listing. If
\r
4768 + you want portability, use the ISO 8601 format. */
\r
4769 + if (4 <= $1.digits)
\r
4772 + pc->month = $3.value;
\r
4773 + pc->day = $5.value;
\r
4777 + pc->month = $1.value;
\r
4778 + pc->day = $3.value;
\r
4782 + | tUNUMBER tSNUMBER tSNUMBER
\r
4784 + /* ISO 8601 format. YYYY-MM-DD. */
\r
4786 + pc->month = -$2.value;
\r
4787 + pc->day = -$3.value;
\r
4789 + | tUNUMBER tMONTH tSNUMBER
\r
4791 + /* e.g. 17-JUN-1992. */
\r
4792 + pc->day = $1.value;
\r
4794 + pc->year.value = -$3.value;
\r
4795 + pc->year.digits = $3.digits;
\r
4797 + | tMONTH tSNUMBER tSNUMBER
\r
4799 + /* e.g. JUN-17-1992. */
\r
4801 + pc->day = -$2.value;
\r
4802 + pc->year.value = -$3.value;
\r
4803 + pc->year.digits = $3.digits;
\r
4805 + | tMONTH tUNUMBER
\r
4808 + pc->day = $2.value;
\r
4810 + | tMONTH tUNUMBER ',' tUNUMBER
\r
4813 + pc->day = $2.value;
\r
4816 + | tUNUMBER tMONTH
\r
4818 + pc->day = $1.value;
\r
4821 + | tUNUMBER tMONTH tUNUMBER
\r
4823 + pc->day = $1.value;
\r
4831 + { apply_relative_time (pc, $1, -1); }
\r
4833 + { apply_relative_time (pc, $1, 1); }
\r
4835 + { apply_relative_time (pc, $1, 1); }
\r
4839 + tORDINAL tYEAR_UNIT
\r
4840 + { $$ = RELATIVE_TIME_0; $$.year = $1; }
\r
4841 + | tUNUMBER tYEAR_UNIT
\r
4842 + { $$ = RELATIVE_TIME_0; $$.year = $1.value; }
\r
4844 + { $$ = RELATIVE_TIME_0; $$.year = 1; }
\r
4845 + | tORDINAL tMONTH_UNIT
\r
4846 + { $$ = RELATIVE_TIME_0; $$.month = $1; }
\r
4847 + | tUNUMBER tMONTH_UNIT
\r
4848 + { $$ = RELATIVE_TIME_0; $$.month = $1.value; }
\r
4850 + { $$ = RELATIVE_TIME_0; $$.month = 1; }
\r
4851 + | tORDINAL tDAY_UNIT
\r
4852 + { $$ = RELATIVE_TIME_0; $$.day = $1 * $2; }
\r
4853 + | tUNUMBER tDAY_UNIT
\r
4854 + { $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; }
\r
4856 + { $$ = RELATIVE_TIME_0; $$.day = $1; }
\r
4857 + | tORDINAL tHOUR_UNIT
\r
4858 + { $$ = RELATIVE_TIME_0; $$.hour = $1; }
\r
4859 + | tUNUMBER tHOUR_UNIT
\r
4860 + { $$ = RELATIVE_TIME_0; $$.hour = $1.value; }
\r
4862 + { $$ = RELATIVE_TIME_0; $$.hour = 1; }
\r
4863 + | tORDINAL tMINUTE_UNIT
\r
4864 + { $$ = RELATIVE_TIME_0; $$.minutes = $1; }
\r
4865 + | tUNUMBER tMINUTE_UNIT
\r
4866 + { $$ = RELATIVE_TIME_0; $$.minutes = $1.value; }
\r
4868 + { $$ = RELATIVE_TIME_0; $$.minutes = 1; }
\r
4869 + | tORDINAL tSEC_UNIT
\r
4870 + { $$ = RELATIVE_TIME_0; $$.seconds = $1; }
\r
4871 + | tUNUMBER tSEC_UNIT
\r
4872 + { $$ = RELATIVE_TIME_0; $$.seconds = $1.value; }
\r
4873 + | tSDECIMAL_NUMBER tSEC_UNIT
\r
4874 + { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }
\r
4875 + | tUDECIMAL_NUMBER tSEC_UNIT
\r
4876 + { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }
\r
4878 + { $$ = RELATIVE_TIME_0; $$.seconds = 1; }
\r
4879 + | relunit_snumber
\r
4883 + tSNUMBER tYEAR_UNIT
\r
4884 + { $$ = RELATIVE_TIME_0; $$.year = $1.value; }
\r
4885 + | tSNUMBER tMONTH_UNIT
\r
4886 + { $$ = RELATIVE_TIME_0; $$.month = $1.value; }
\r
4887 + | tSNUMBER tDAY_UNIT
\r
4888 + { $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; }
\r
4889 + | tSNUMBER tHOUR_UNIT
\r
4890 + { $$ = RELATIVE_TIME_0; $$.hour = $1.value; }
\r
4891 + | tSNUMBER tMINUTE_UNIT
\r
4892 + { $$ = RELATIVE_TIME_0; $$.minutes = $1.value; }
\r
4893 + | tSNUMBER tSEC_UNIT
\r
4894 + { $$ = RELATIVE_TIME_0; $$.seconds = $1.value; }
\r
4899 + { $$ = RELATIVE_TIME_0; $$.day = $1; }
\r
4902 +seconds: signed_seconds | unsigned_seconds;
\r
4905 + tSDECIMAL_NUMBER
\r
4907 + { $$.tv_sec = $1.value; $$.tv_nsec = 0; }
\r
4910 +unsigned_seconds:
\r
4911 + tUDECIMAL_NUMBER
\r
4913 + { $$.tv_sec = $1.value; $$.tv_nsec = 0; }
\r
4918 + { digits_to_date_time (pc, $1); }
\r
4922 + tUNUMBER relunit_snumber
\r
4924 + /* Hybrid all-digit and relative offset, so that we accept e.g.,
\r
4925 + "YYYYMMDD +N days" as well as "YYYYMMDD N days". */
\r
4926 + digits_to_date_time (pc, $1);
\r
4927 + apply_relative_time (pc, $2, 1);
\r
4935 + { $$ = $2.value; }
\r
4947 +static table const meridian_table[] =
\r
4949 + { "AM", tMERIDIAN, MERam },
\r
4950 + { "A.M.", tMERIDIAN, MERam },
\r
4951 + { "PM", tMERIDIAN, MERpm },
\r
4952 + { "P.M.", tMERIDIAN, MERpm },
\r
4956 +static table const dst_table[] =
\r
4958 + { "DST", tDST, 0 }
\r
4961 +static table const month_and_day_table[] =
\r
4963 + { "JANUARY", tMONTH, 1 },
\r
4964 + { "FEBRUARY", tMONTH, 2 },
\r
4965 + { "MARCH", tMONTH, 3 },
\r
4966 + { "APRIL", tMONTH, 4 },
\r
4967 + { "MAY", tMONTH, 5 },
\r
4968 + { "JUNE", tMONTH, 6 },
\r
4969 + { "JULY", tMONTH, 7 },
\r
4970 + { "AUGUST", tMONTH, 8 },
\r
4971 + { "SEPTEMBER",tMONTH, 9 },
\r
4972 + { "SEPT", tMONTH, 9 },
\r
4973 + { "OCTOBER", tMONTH, 10 },
\r
4974 + { "NOVEMBER", tMONTH, 11 },
\r
4975 + { "DECEMBER", tMONTH, 12 },
\r
4976 + { "SUNDAY", tDAY, 0 },
\r
4977 + { "MONDAY", tDAY, 1 },
\r
4978 + { "TUESDAY", tDAY, 2 },
\r
4979 + { "TUES", tDAY, 2 },
\r
4980 + { "WEDNESDAY",tDAY, 3 },
\r
4981 + { "WEDNES", tDAY, 3 },
\r
4982 + { "THURSDAY", tDAY, 4 },
\r
4983 + { "THUR", tDAY, 4 },
\r
4984 + { "THURS", tDAY, 4 },
\r
4985 + { "FRIDAY", tDAY, 5 },
\r
4986 + { "SATURDAY", tDAY, 6 },
\r
4990 +static table const time_units_table[] =
\r
4992 + { "YEAR", tYEAR_UNIT, 1 },
\r
4993 + { "MONTH", tMONTH_UNIT, 1 },
\r
4994 + { "FORTNIGHT",tDAY_UNIT, 14 },
\r
4995 + { "WEEK", tDAY_UNIT, 7 },
\r
4996 + { "DAY", tDAY_UNIT, 1 },
\r
4997 + { "HOUR", tHOUR_UNIT, 1 },
\r
4998 + { "MINUTE", tMINUTE_UNIT, 1 },
\r
4999 + { "MIN", tMINUTE_UNIT, 1 },
\r
5000 + { "SECOND", tSEC_UNIT, 1 },
\r
5001 + { "SEC", tSEC_UNIT, 1 },
\r
5005 +/* Assorted relative-time words. */
\r
5006 +static table const relative_time_table[] =
\r
5008 + { "TOMORROW", tDAY_SHIFT, 1 },
\r
5009 + { "YESTERDAY",tDAY_SHIFT, -1 },
\r
5010 + { "TODAY", tDAY_SHIFT, 0 },
\r
5011 + { "NOW", tDAY_SHIFT, 0 },
\r
5012 + { "LAST", tORDINAL, -1 },
\r
5013 + { "THIS", tORDINAL, 0 },
\r
5014 + { "NEXT", tORDINAL, 1 },
\r
5015 + { "FIRST", tORDINAL, 1 },
\r
5016 +/*{ "SECOND", tORDINAL, 2 }, */
\r
5017 + { "THIRD", tORDINAL, 3 },
\r
5018 + { "FOURTH", tORDINAL, 4 },
\r
5019 + { "FIFTH", tORDINAL, 5 },
\r
5020 + { "SIXTH", tORDINAL, 6 },
\r
5021 + { "SEVENTH", tORDINAL, 7 },
\r
5022 + { "EIGHTH", tORDINAL, 8 },
\r
5023 + { "NINTH", tORDINAL, 9 },
\r
5024 + { "TENTH", tORDINAL, 10 },
\r
5025 + { "ELEVENTH", tORDINAL, 11 },
\r
5026 + { "TWELFTH", tORDINAL, 12 },
\r
5027 + { "AGO", tAGO, 1 },
\r
5031 +/* The universal time zone table. These labels can be used even for
\r
5032 + time stamps that would not otherwise be valid, e.g., GMT time
\r
5033 + stamps in London during summer. */
\r
5034 +static table const universal_time_zone_table[] =
\r
5036 + { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
\r
5037 + { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
\r
5038 + { "UTC", tZONE, HOUR ( 0) },
\r
5042 +/* The time zone table. This table is necessarily incomplete, as time
\r
5043 + zone abbreviations are ambiguous; e.g. Australians interpret "EST"
\r
5044 + as Eastern time in Australia, not as US Eastern Standard Time.
\r
5045 + You cannot rely on getdate to handle arbitrary time zone
\r
5046 + abbreviations; use numeric abbreviations like `-0500' instead. */
\r
5047 +static table const time_zone_table[] =
\r
5049 + { "WET", tZONE, HOUR ( 0) }, /* Western European */
\r
5050 + { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
\r
5051 + { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
\r
5052 + { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
\r
5053 + { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
\r
5054 + { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
\r
5055 + { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
\r
5056 + { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
\r
5057 + { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
\r
5058 + { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
\r
5059 + { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
\r
5060 + { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
\r
5061 + { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
\r
5062 + { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
\r
5063 + { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
\r
5064 + { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
\r
5065 + { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
\r
5066 + { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
\r
5067 + { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
\r
5068 + { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
\r
5069 + { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
\r
5070 + { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
\r
5071 + { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
\r
5072 + { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
\r
5073 + { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
\r
5074 + { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
\r
5075 + { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
\r
5076 + { "CET", tZONE, HOUR ( 1) }, /* Central European */
\r
5077 + { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
\r
5078 + { "MET", tZONE, HOUR ( 1) }, /* Middle European */
\r
5079 + { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
\r
5080 + { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
\r
5081 + { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
\r
5082 + { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
\r
5083 + { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
\r
5084 + { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
\r
5085 + { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
\r
5086 + { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
\r
5087 + { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
\r
5088 + { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
\r
5089 + { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
\r
5090 + { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
\r
5091 + { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
\r
5092 + { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
\r
5093 + { "GST", tZONE, HOUR (10) }, /* Guam Standard */
\r
5094 + { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
\r
5095 + { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
\r
5099 +/* Military time zone table. */
\r
5100 +static table const military_table[] =
\r
5102 + { "A", tZONE, -HOUR ( 1) },
\r
5103 + { "B", tZONE, -HOUR ( 2) },
\r
5104 + { "C", tZONE, -HOUR ( 3) },
\r
5105 + { "D", tZONE, -HOUR ( 4) },
\r
5106 + { "E", tZONE, -HOUR ( 5) },
\r
5107 + { "F", tZONE, -HOUR ( 6) },
\r
5108 + { "G", tZONE, -HOUR ( 7) },
\r
5109 + { "H", tZONE, -HOUR ( 8) },
\r
5110 + { "I", tZONE, -HOUR ( 9) },
\r
5111 + { "K", tZONE, -HOUR (10) },
\r
5112 + { "L", tZONE, -HOUR (11) },
\r
5113 + { "M", tZONE, -HOUR (12) },
\r
5114 + { "N", tZONE, HOUR ( 1) },
\r
5115 + { "O", tZONE, HOUR ( 2) },
\r
5116 + { "P", tZONE, HOUR ( 3) },
\r
5117 + { "Q", tZONE, HOUR ( 4) },
\r
5118 + { "R", tZONE, HOUR ( 5) },
\r
5119 + { "S", tZONE, HOUR ( 6) },
\r
5120 + { "T", tZONE, HOUR ( 7) },
\r
5121 + { "U", tZONE, HOUR ( 8) },
\r
5122 + { "V", tZONE, HOUR ( 9) },
\r
5123 + { "W", tZONE, HOUR (10) },
\r
5124 + { "X", tZONE, HOUR (11) },
\r
5125 + { "Y", tZONE, HOUR (12) },
\r
5126 + { "Z", tZONE, HOUR ( 0) },
\r
5133 +/* Convert a time zone expressed as HH:MM into an integer count of
\r
5134 + minutes. If MM is negative, then S is of the form HHMM and needs
\r
5135 + to be picked apart; otherwise, S is of the form HH. As specified in
\r
5136 + http://www.opengroup.org/susv3xbd/xbd_chap08.html#tag_08_03, allow
\r
5137 + only valid TZ range, and consider first two digits as hours, if no
\r
5138 + minutes specified. */
\r
5141 +time_zone_hhmm (parser_control *pc, textint s, long int mm)
\r
5143 + long int n_minutes;
\r
5145 + /* If the length of S is 1 or 2 and no minutes are specified,
\r
5146 + interpret it as a number of hours. */
\r
5147 + if (s.digits <= 2 && mm < 0)
\r
5151 + n_minutes = (s.value / 100) * 60 + s.value % 100;
\r
5153 + n_minutes = s.value * 60 + (s.negative ? -mm : mm);
\r
5155 + /* If the absolute number of minutes is larger than 24 hours,
\r
5156 + arrange to reject it by incrementing pc->zones_seen. Thus,
\r
5157 + we allow only values in the range UTC-24:00 to UTC+24:00. */
\r
5158 + if (24 * 60 < abs (n_minutes))
\r
5159 + pc->zones_seen++;
\r
5161 + return n_minutes;
\r
5165 +to_hour (long int hours, int meridian)
\r
5167 + switch (meridian)
\r
5169 + default: /* Pacify GCC. */
\r
5171 + return 0 <= hours && hours < 24 ? hours : -1;
\r
5173 + return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
\r
5175 + return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
\r
5180 +to_year (textint textyear)
\r
5182 + long int year = textyear.value;
\r
5187 + /* XPG4 suggests that years 00-68 map to 2000-2068, and
\r
5188 + years 69-99 map to 1969-1999. */
\r
5189 + else if (textyear.digits == 2)
\r
5190 + year += year < 69 ? 2000 : 1900;
\r
5195 +static table const *
\r
5196 +lookup_zone (parser_control const *pc, char const *name)
\r
5198 + table const *tp;
\r
5200 + for (tp = universal_time_zone_table; tp->name; tp++)
\r
5201 + if (strcmp (name, tp->name) == 0)
\r
5204 + /* Try local zone abbreviations before those in time_zone_table, as
\r
5205 + the local ones are more likely to be right. */
\r
5206 + for (tp = pc->local_time_zone_table; tp->name; tp++)
\r
5207 + if (strcmp (name, tp->name) == 0)
\r
5210 + for (tp = time_zone_table; tp->name; tp++)
\r
5211 + if (strcmp (name, tp->name) == 0)
\r
5217 +#if ! HAVE_TM_GMTOFF
\r
5218 +/* Yield the difference between *A and *B,
\r
5219 + measured in seconds, ignoring leap seconds.
\r
5220 + The body of this function is taken directly from the GNU C Library;
\r
5221 + see src/strftime.c. */
\r
5223 +tm_diff (struct tm const *a, struct tm const *b)
\r
5225 + /* Compute intervening leap days correctly even if year is negative.
\r
5226 + Take care to avoid int overflow in leap day calculations. */
\r
5227 + int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
\r
5228 + int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
\r
5229 + int a100 = a4 / 25 - (a4 % 25 < 0);
\r
5230 + int b100 = b4 / 25 - (b4 % 25 < 0);
\r
5231 + int a400 = SHR (a100, 2);
\r
5232 + int b400 = SHR (b100, 2);
\r
5233 + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
\r
5234 + long int ayear = a->tm_year;
\r
5235 + long int years = ayear - b->tm_year;
\r
5236 + long int days = (365 * years + intervening_leap_days
\r
5237 + + (a->tm_yday - b->tm_yday));
\r
5238 + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
\r
5239 + + (a->tm_min - b->tm_min))
\r
5240 + + (a->tm_sec - b->tm_sec));
\r
5242 +#endif /* ! HAVE_TM_GMTOFF */
\r
5244 +static table const *
\r
5245 +lookup_word (parser_control const *pc, char *word)
\r
5250 + table const *tp;
\r
5251 + bool period_found;
\r
5254 + /* Make it uppercase. */
\r
5255 + for (p = word; *p; p++)
\r
5257 + unsigned char ch = *p;
\r
5258 + *p = c_toupper (ch);
\r
5261 + for (tp = meridian_table; tp->name; tp++)
\r
5262 + if (strcmp (word, tp->name) == 0)
\r
5265 + /* See if we have an abbreviation for a month. */
\r
5266 + wordlen = strlen (word);
\r
5267 + abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
\r
5269 + for (tp = month_and_day_table; tp->name; tp++)
\r
5270 + if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
\r
5273 + if ((tp = lookup_zone (pc, word)))
\r
5276 + if (strcmp (word, dst_table[0].name) == 0)
\r
5277 + return dst_table;
\r
5279 + for (tp = time_units_table; tp->name; tp++)
\r
5280 + if (strcmp (word, tp->name) == 0)
\r
5283 + /* Strip off any plural and try the units table again. */
\r
5284 + if (word[wordlen - 1] == 'S')
\r
5286 + word[wordlen - 1] = '\0';
\r
5287 + for (tp = time_units_table; tp->name; tp++)
\r
5288 + if (strcmp (word, tp->name) == 0)
\r
5290 + word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
\r
5293 + for (tp = relative_time_table; tp->name; tp++)
\r
5294 + if (strcmp (word, tp->name) == 0)
\r
5297 + /* Military time zones. */
\r
5298 + if (wordlen == 1)
\r
5299 + for (tp = military_table; tp->name; tp++)
\r
5300 + if (word[0] == tp->name[0])
\r
5303 + /* Drop out any periods and try the time zone table again. */
\r
5304 + for (period_found = false, p = q = word; (*p = *q); q++)
\r
5306 + period_found = true;
\r
5309 + if (period_found && (tp = lookup_zone (pc, word)))
\r
5316 +yylex (YYSTYPE *lvalp, parser_control *pc)
\r
5318 + unsigned char c;
\r
5323 + while (c = *pc->input, c_isspace (c))
\r
5326 + if (ISDIGIT (c) || c == '-' || c == '+')
\r
5330 + unsigned long int value;
\r
5331 + if (c == '-' || c == '+')
\r
5333 + sign = c == '-' ? -1 : 1;
\r
5334 + while (c = *++pc->input, c_isspace (c))
\r
5336 + if (! ISDIGIT (c))
\r
5337 + /* skip the '-' sign */
\r
5343 + for (value = 0; ; value *= 10)
\r
5345 + unsigned long int value1 = value + (c - '0');
\r
5346 + if (value1 < value)
\r
5350 + if (! ISDIGIT (c))
\r
5352 + if (ULONG_MAX / 10 < value)
\r
5355 + if ((c == '.' || c == ',') && ISDIGIT (p[1]))
\r
5360 + unsigned long int value1;
\r
5362 + /* Check for overflow when converting value to time_t. */
\r
5377 + if (value != value1)
\r
5380 + /* Accumulate fraction, to ns precision. */
\r
5382 + ns = *p++ - '0';
\r
5383 + for (digits = 2; digits <= LOG10_BILLION; digits++)
\r
5386 + if (ISDIGIT (*p))
\r
5387 + ns += *p++ - '0';
\r
5390 + /* Skip excess digits, truncating toward -Infinity. */
\r
5392 + for (; ISDIGIT (*p); p++)
\r
5398 + while (ISDIGIT (*p))
\r
5401 + /* Adjust to the timespec convention, which is that
\r
5402 + tv_nsec is always a positive offset even if tv_sec is
\r
5404 + if (sign < 0 && ns)
\r
5409 + ns = BILLION - ns;
\r
5412 + lvalp->timespec.tv_sec = s;
\r
5413 + lvalp->timespec.tv_nsec = ns;
\r
5415 + return sign ? tSDECIMAL_NUMBER : tUDECIMAL_NUMBER;
\r
5419 + lvalp->textintval.negative = sign < 0;
\r
5422 + lvalp->textintval.value = - value;
\r
5423 + if (0 < lvalp->textintval.value)
\r
5428 + lvalp->textintval.value = value;
\r
5429 + if (lvalp->textintval.value < 0)
\r
5432 + lvalp->textintval.digits = p - pc->input;
\r
5434 + return sign ? tSNUMBER : tUNUMBER;
\r
5438 + if (c_isalpha (c))
\r
5442 + table const *tp;
\r
5446 + if (p < buff + sizeof buff - 1)
\r
5448 + c = *++pc->input;
\r
5450 + while (c_isalpha (c) || c == '.');
\r
5453 + tp = lookup_word (pc, buff);
\r
5456 + lvalp->intval = tp->value;
\r
5457 + return tp->type;
\r
5461 + return *pc->input++;
\r
5465 + c = *pc->input++;
\r
5470 + else if (c == ')')
\r
5473 + while (count != 0);
\r
5477 +/* Do nothing if the parser reports an error. */
\r
5479 +yyerror (parser_control const *pc _GL_UNUSED,
\r
5480 + char const *s _GL_UNUSED)
\r
5485 +/* If *TM0 is the old and *TM1 is the new value of a struct tm after
\r
5486 + passing it to mktime, return true if it's OK that mktime returned T.
\r
5487 + It's not OK if *TM0 has out-of-range members. */
\r
5490 +mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)
\r
5492 + if (t == (time_t) -1)
\r
5494 + /* Guard against falsely reporting an error when parsing a time
\r
5495 + stamp that happens to equal (time_t) -1, on a host that
\r
5496 + supports such a time stamp. */
\r
5497 + tm1 = localtime (&t);
\r
5502 + return ! ((tm0->tm_sec ^ tm1->tm_sec)
\r
5503 + | (tm0->tm_min ^ tm1->tm_min)
\r
5504 + | (tm0->tm_hour ^ tm1->tm_hour)
\r
5505 + | (tm0->tm_mday ^ tm1->tm_mday)
\r
5506 + | (tm0->tm_mon ^ tm1->tm_mon)
\r
5507 + | (tm0->tm_year ^ tm1->tm_year));
\r
5510 +/* A reasonable upper bound for the size of ordinary TZ strings.
\r
5511 + Use heap allocation if TZ's length exceeds this. */
\r
5512 +enum { TZBUFSIZE = 100 };
\r
5514 +/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated
\r
5517 +get_tz (char tzbuf[TZBUFSIZE])
\r
5519 + char *tz = getenv ("TZ");
\r
5522 + size_t tzsize = strlen (tz) + 1;
\r
5523 + tz = (tzsize <= TZBUFSIZE
\r
5524 + ? memcpy (tzbuf, tz, tzsize)
\r
5525 + : xmemdup (tz, tzsize));
\r
5530 +/* Parse a date/time string, storing the resulting time value into *RESULT.
\r
5531 + The string itself is pointed to by P. Return true if successful.
\r
5532 + P can be an incomplete or relative time specification; if so, use
\r
5533 + *NOW as the basis for the returned time. */
\r
5535 +get_date (struct timespec *result, char const *p, struct timespec const *now)
\r
5538 + long int Start_ns;
\r
5539 + struct tm const *tmp;
\r
5542 + parser_control pc;
\r
5543 + struct timespec gettime_buffer;
\r
5544 + unsigned char c;
\r
5545 + bool tz_was_altered = false;
\r
5546 + char *tz0 = NULL;
\r
5547 + char tz0buf[TZBUFSIZE];
\r
5552 + gettime (&gettime_buffer);
\r
5553 + now = &gettime_buffer;
\r
5556 + Start = now->tv_sec;
\r
5557 + Start_ns = now->tv_nsec;
\r
5559 + tmp = localtime (&now->tv_sec);
\r
5563 + while (c = *p, c_isspace (c))
\r
5566 + if (strncmp (p, "TZ=\"", 4) == 0)
\r
5568 + char const *tzbase = p + 4;
\r
5569 + size_t tzsize = 1;
\r
5572 + for (s = tzbase; *s; s++, tzsize++)
\r
5576 + if (! (*s == '\\' || *s == '"'))
\r
5579 + else if (*s == '"')
\r
5583 + char tz1buf[TZBUFSIZE];
\r
5584 + bool large_tz = TZBUFSIZE < tzsize;
\r
5586 + /* Free tz0, in case this is the 2nd or subsequent time through. */
\r
5588 + tz0 = get_tz (tz0buf);
\r
5589 + z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
\r
5590 + for (s = tzbase; *s != '"'; s++)
\r
5591 + *z++ = *(s += *s == '\\');
\r
5593 + setenv_ok = setenv ("TZ", tz1, 1) == 0;
\r
5598 + tz_was_altered = true;
\r
5603 + /* As documented, be careful to treat the empty string just like
\r
5604 + a date string of "0". Without this, an empty string would be
\r
5605 + declared invalid when parsed during a DST transition. */
\r
5610 + pc.year.value = tmp->tm_year;
\r
5611 + pc.year.value += TM_YEAR_BASE;
\r
5612 + pc.year.digits = 0;
\r
5613 + pc.month = tmp->tm_mon + 1;
\r
5614 + pc.day = tmp->tm_mday;
\r
5615 + pc.hour = tmp->tm_hour;
\r
5616 + pc.minutes = tmp->tm_min;
\r
5617 + pc.seconds.tv_sec = tmp->tm_sec;
\r
5618 + pc.seconds.tv_nsec = Start_ns;
\r
5619 + tm.tm_isdst = tmp->tm_isdst;
\r
5621 + pc.meridian = MER24;
\r
5622 + pc.rel = RELATIVE_TIME_0;
\r
5623 + pc.timespec_seen = false;
\r
5624 + pc.rels_seen = false;
\r
5625 + pc.dates_seen = 0;
\r
5626 + pc.days_seen = 0;
\r
5627 + pc.times_seen = 0;
\r
5628 + pc.local_zones_seen = 0;
\r
5629 + pc.dsts_seen = 0;
\r
5630 + pc.zones_seen = 0;
\r
5632 +#if HAVE_STRUCT_TM_TM_ZONE
\r
5633 + pc.local_time_zone_table[0].name = tmp->tm_zone;
\r
5634 + pc.local_time_zone_table[0].type = tLOCAL_ZONE;
\r
5635 + pc.local_time_zone_table[0].value = tmp->tm_isdst;
\r
5636 + pc.local_time_zone_table[1].name = NULL;
\r
5638 + /* Probe the names used in the next three calendar quarters, looking
\r
5639 + for a tm_isdst different from the one we already have. */
\r
5642 + for (quarter = 1; quarter <= 3; quarter++)
\r
5644 + time_t probe = Start + quarter * (90 * 24 * 60 * 60);
\r
5645 + struct tm const *probe_tm = localtime (&probe);
\r
5646 + if (probe_tm && probe_tm->tm_zone
\r
5647 + && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
\r
5650 + pc.local_time_zone_table[1].name = probe_tm->tm_zone;
\r
5651 + pc.local_time_zone_table[1].type = tLOCAL_ZONE;
\r
5652 + pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
\r
5653 + pc.local_time_zone_table[2].name = NULL;
\r
5662 +# if !HAVE_DECL_TZNAME
\r
5663 + extern char *tzname[];
\r
5666 + for (i = 0; i < 2; i++)
\r
5668 + pc.local_time_zone_table[i].name = tzname[i];
\r
5669 + pc.local_time_zone_table[i].type = tLOCAL_ZONE;
\r
5670 + pc.local_time_zone_table[i].value = i;
\r
5672 + pc.local_time_zone_table[i].name = NULL;
\r
5675 + pc.local_time_zone_table[0].name = NULL;
\r
5679 + if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
\r
5680 + && ! strcmp (pc.local_time_zone_table[0].name,
\r
5681 + pc.local_time_zone_table[1].name))
\r
5683 + /* This locale uses the same abbrevation for standard and
\r
5684 + daylight times. So if we see that abbreviation, we don't
\r
5685 + know whether it's daylight time. */
\r
5686 + pc.local_time_zone_table[0].value = -1;
\r
5687 + pc.local_time_zone_table[1].name = NULL;
\r
5690 + if (yyparse (&pc) != 0)
\r
5693 + if (pc.timespec_seen)
\r
5694 + *result = pc.seconds;
\r
5697 + if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
\r
5698 + | (pc.local_zones_seen + pc.zones_seen)))
\r
5701 + tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;
\r
5702 + tm.tm_mon = pc.month - 1;
\r
5703 + tm.tm_mday = pc.day;
\r
5704 + if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
\r
5706 + tm.tm_hour = to_hour (pc.hour, pc.meridian);
\r
5707 + if (tm.tm_hour < 0)
\r
5709 + tm.tm_min = pc.minutes;
\r
5710 + tm.tm_sec = pc.seconds.tv_sec;
\r
5714 + tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
\r
5715 + pc.seconds.tv_nsec = 0;
\r
5718 + /* Let mktime deduce tm_isdst if we have an absolute time stamp. */
\r
5719 + if (pc.dates_seen | pc.days_seen | pc.times_seen)
\r
5720 + tm.tm_isdst = -1;
\r
5722 + /* But if the input explicitly specifies local time with or without
\r
5723 + DST, give mktime that information. */
\r
5724 + if (pc.local_zones_seen)
\r
5725 + tm.tm_isdst = pc.local_isdst;
\r
5729 + Start = mktime (&tm);
\r
5731 + if (! mktime_ok (&tm0, &tm, Start))
\r
5733 + if (! pc.zones_seen)
\r
5737 + /* Guard against falsely reporting errors near the time_t
\r
5738 + boundaries when parsing times in other time zones. For
\r
5739 + example, suppose the input string "1969-12-31 23:00:00 -0100",
\r
5740 + the current time zone is 8 hours ahead of UTC, and the min
\r
5741 + time_t value is 1970-01-01 00:00:00 UTC. Then the min
\r
5742 + localtime value is 1970-01-01 08:00:00, and mktime will
\r
5743 + therefore fail on 1969-12-31 23:00:00. To work around the
\r
5744 + problem, set the time zone to 1 hour behind UTC temporarily
\r
5745 + by setting TZ="XXX1:00" and try mktime again. */
\r
5747 + long int time_zone = pc.time_zone;
\r
5748 + long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
\r
5749 + long int abs_time_zone_hour = abs_time_zone / 60;
\r
5750 + int abs_time_zone_min = abs_time_zone % 60;
\r
5751 + char tz1buf[sizeof "XXX+0:00"
\r
5752 + + sizeof pc.time_zone * CHAR_BIT / 3];
\r
5753 + if (!tz_was_altered)
\r
5754 + tz0 = get_tz (tz0buf);
\r
5755 + sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
\r
5756 + abs_time_zone_hour, abs_time_zone_min);
\r
5757 + if (setenv ("TZ", tz1buf, 1) != 0)
\r
5759 + tz_was_altered = true;
\r
5761 + Start = mktime (&tm);
\r
5762 + if (! mktime_ok (&tm0, &tm, Start))
\r
5767 + if (pc.days_seen && ! pc.dates_seen)
\r
5769 + tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
\r
5770 + + 7 * (pc.day_ordinal
\r
5771 + - (0 < pc.day_ordinal
\r
5772 + && tm.tm_wday != pc.day_number)));
\r
5773 + tm.tm_isdst = -1;
\r
5774 + Start = mktime (&tm);
\r
5775 + if (Start == (time_t) -1)
\r
5779 + /* Add relative date. */
\r
5780 + if (pc.rel.year | pc.rel.month | pc.rel.day)
\r
5782 + int year = tm.tm_year + pc.rel.year;
\r
5783 + int month = tm.tm_mon + pc.rel.month;
\r
5784 + int day = tm.tm_mday + pc.rel.day;
\r
5785 + if (((year < tm.tm_year) ^ (pc.rel.year < 0))
\r
5786 + | ((month < tm.tm_mon) ^ (pc.rel.month < 0))
\r
5787 + | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))
\r
5789 + tm.tm_year = year;
\r
5790 + tm.tm_mon = month;
\r
5791 + tm.tm_mday = day;
\r
5792 + tm.tm_hour = tm0.tm_hour;
\r
5793 + tm.tm_min = tm0.tm_min;
\r
5794 + tm.tm_sec = tm0.tm_sec;
\r
5795 + tm.tm_isdst = tm0.tm_isdst;
\r
5796 + Start = mktime (&tm);
\r
5797 + if (Start == (time_t) -1)
\r
5801 + /* The only "output" of this if-block is an updated Start value,
\r
5802 + so this block must follow others that clobber Start. */
\r
5803 + if (pc.zones_seen)
\r
5805 + long int delta = pc.time_zone * 60;
\r
5807 +#ifdef HAVE_TM_GMTOFF
\r
5808 + delta -= tm.tm_gmtoff;
\r
5810 + time_t t = Start;
\r
5811 + struct tm const *gmt = gmtime (&t);
\r
5814 + delta -= tm_diff (&tm, gmt);
\r
5816 + t1 = Start - delta;
\r
5817 + if ((Start < t1) != (delta < 0))
\r
5818 + goto fail; /* time_t overflow */
\r
5822 + /* Add relative hours, minutes, and seconds. On hosts that support
\r
5823 + leap seconds, ignore the possibility of leap seconds; e.g.,
\r
5824 + "+ 10 minutes" adds 600 seconds, even if one of them is a
\r
5825 + leap second. Typically this is not what the user wants, but it's
\r
5826 + too hard to do it the other way, because the time zone indicator
\r
5827 + must be applied before relative times, and if mktime is applied
\r
5828 + again the time zone will be lost. */
\r
5830 + long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
\r
5831 + long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
\r
5832 + time_t t0 = Start;
\r
5833 + long int d1 = 60 * 60 * pc.rel.hour;
\r
5834 + time_t t1 = t0 + d1;
\r
5835 + long int d2 = 60 * pc.rel.minutes;
\r
5836 + time_t t2 = t1 + d2;
\r
5837 + long_time_t d3 = pc.rel.seconds;
\r
5838 + long_time_t t3 = t2 + d3;
\r
5839 + long int d4 = (sum_ns - normalized_ns) / BILLION;
\r
5840 + long_time_t t4 = t3 + d4;
\r
5843 + if ((d1 / (60 * 60) ^ pc.rel.hour)
\r
5844 + | (d2 / 60 ^ pc.rel.minutes)
\r
5845 + | ((t1 < t0) ^ (d1 < 0))
\r
5846 + | ((t2 < t1) ^ (d2 < 0))
\r
5847 + | ((t3 < t2) ^ (d3 < 0))
\r
5848 + | ((t4 < t3) ^ (d4 < 0))
\r
5852 + result->tv_sec = t5;
\r
5853 + result->tv_nsec = normalized_ns;
\r
5862 + if (tz_was_altered)
\r
5863 + ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;
\r
5864 + if (tz0 != tz0buf)
\r
5872 +main (int ac, char **av)
\r
5874 + char buff[BUFSIZ];
\r
5876 + printf ("Enter date, or blank line to exit.\n\t> ");
\r
5877 + fflush (stdout);
\r
5879 + buff[BUFSIZ - 1] = '\0';
\r
5880 + while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
\r
5882 + struct timespec d;
\r
5883 + struct tm const *tm;
\r
5884 + if (! get_date (&d, buff, NULL))
\r
5885 + printf ("Bad format - couldn't convert.\n");
\r
5886 + else if (! (tm = localtime (&d.tv_sec)))
\r
5888 + long int sec = d.tv_sec;
\r
5889 + printf ("localtime (%ld) failed\n", sec);
\r
5893 + int ns = d.tv_nsec;
\r
5894 + printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
\r
5895 + tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
\r
5896 + tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
\r
5898 + printf ("\t> ");
\r
5899 + fflush (stdout);
\r
5903 +#endif /* TEST */
\r
5904 diff --git a/lib/gettime.c b/lib/gettime.c
\r
5905 new file mode 100644
\r
5906 index 0000000..044b26f
\r
5908 +++ b/lib/gettime.c
\r
5910 +/* gettime -- get the system clock
\r
5912 + Copyright (C) 2002, 2004-2007, 2009-2010 Free Software Foundation, Inc.
\r
5914 + This program is free software: you can redistribute it and/or modify
\r
5915 + it under the terms of the GNU General Public License as published by
\r
5916 + the Free Software Foundation; either version 3 of the License, or
\r
5917 + (at your option) any later version.
\r
5919 + This program is distributed in the hope that it will be useful,
\r
5920 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
5921 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
5922 + GNU General Public License for more details.
\r
5924 + You should have received a copy of the GNU General Public License
\r
5925 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
5927 +/* Written by Paul Eggert. */
\r
5929 +#include <config.h>
\r
5931 +#include "timespec.h"
\r
5933 +#include <sys/time.h>
\r
5935 +/* Get the system time into *TS. */
\r
5938 +gettime (struct timespec *ts)
\r
5940 +#if HAVE_NANOTIME
\r
5944 +# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
\r
5945 + if (clock_gettime (CLOCK_REALTIME, ts) == 0)
\r
5950 + struct timeval tv;
\r
5951 + gettimeofday (&tv, NULL);
\r
5952 + ts->tv_sec = tv.tv_sec;
\r
5953 + ts->tv_nsec = tv.tv_usec * 1000;
\r
5958 diff --git a/lib/gettime.h b/lib/gettime.h
\r
5959 new file mode 100644
\r
5960 index 0000000..e69de29
\r
5961 diff --git a/lib/intprops.h b/lib/intprops.h
\r
5962 new file mode 100644
\r
5963 index 0000000..46f4d47
\r
5965 +++ b/lib/intprops.h
\r
5967 +/* intprops.h -- properties of integer types
\r
5969 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010 Free Software
\r
5970 + Foundation, Inc.
\r
5972 + This program is free software: you can redistribute it and/or modify
\r
5973 + it under the terms of the GNU General Public License as published by
\r
5974 + the Free Software Foundation; either version 3 of the License, or
\r
5975 + (at your option) any later version.
\r
5977 + This program is distributed in the hope that it will be useful,
\r
5978 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
5979 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
5980 + GNU General Public License for more details.
\r
5982 + You should have received a copy of the GNU General Public License
\r
5983 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
5985 +/* Written by Paul Eggert. */
\r
5987 +#ifndef GL_INTPROPS_H
\r
5988 +# define GL_INTPROPS_H
\r
5990 +# include <limits.h>
\r
5992 +/* The extra casts in the following macros work around compiler bugs,
\r
5993 + e.g., in Cray C 5.0.3.0. */
\r
5995 +/* True if the arithmetic type T is an integer type. bool counts as
\r
5997 +# define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
\r
5999 +/* True if negative values of the signed integer type T use two's
\r
6000 + complement, ones' complement, or signed magnitude representation,
\r
6001 + respectively. Much GNU code assumes two's complement, but some
\r
6002 + people like to be portable to all possible C hosts. */
\r
6003 +# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
\r
6004 +# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
\r
6005 +# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
\r
6007 +/* True if the arithmetic type T is signed. */
\r
6008 +# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
\r
6010 +/* The maximum and minimum values for the integer type T. These
\r
6011 + macros have undefined behavior if T is signed and has padding bits.
\r
6012 + If this is a problem for you, please let us know how to fix it for
\r
6014 +# define TYPE_MINIMUM(t) \
\r
6015 + ((t) (! TYPE_SIGNED (t) \
\r
6017 + : TYPE_SIGNED_MAGNITUDE (t) \
\r
6019 + : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
\r
6020 +# define TYPE_MAXIMUM(t) \
\r
6021 + ((t) (! TYPE_SIGNED (t) \
\r
6023 + : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
\r
6025 +/* Return zero if T can be determined to be an unsigned type.
\r
6026 + Otherwise, return 1.
\r
6027 + When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
\r
6028 + tighter bound. Otherwise, it overestimates the true bound by one byte
\r
6029 + when applied to unsigned types of size 2, 4, 16, ... bytes.
\r
6030 + The symbol signed_type_or_expr__ is private to this header file. */
\r
6031 +# if __GNUC__ >= 2
\r
6032 +# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
\r
6034 +# define signed_type_or_expr__(t) 1
\r
6037 +/* Bound on length of the string representing an integer type or expression T.
\r
6038 + Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
\r
6039 + add 1 for integer division truncation; add 1 more for a minus sign
\r
6041 +# define INT_STRLEN_BOUND(t) \
\r
6042 + ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
\r
6043 + + signed_type_or_expr__ (t) + 1)
\r
6045 +/* Bound on buffer size needed to represent an integer type or expression T,
\r
6046 + including the terminating null. */
\r
6047 +# define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
\r
6049 +#endif /* GL_INTPROPS_H */
\r
6050 diff --git a/lib/timespec.h b/lib/timespec.h
\r
6051 new file mode 100644
\r
6052 index 0000000..81b3423
\r
6054 +++ b/lib/timespec.h
\r
6056 +/* timespec -- System time interface
\r
6058 + Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2010 Free Software
\r
6059 + Foundation, Inc.
\r
6061 + This program is free software: you can redistribute it and/or modify
\r
6062 + it under the terms of the GNU General Public License as published by
\r
6063 + the Free Software Foundation; either version 3 of the License, or
\r
6064 + (at your option) any later version.
\r
6066 + This program is distributed in the hope that it will be useful,
\r
6067 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
6068 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
6069 + GNU General Public License for more details.
\r
6071 + You should have received a copy of the GNU General Public License
\r
6072 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
6074 +#if ! defined TIMESPEC_H
\r
6075 +# define TIMESPEC_H
\r
6077 +# include <time.h>
\r
6079 +/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
\r
6080 + Assume the nanosecond components are in range, or close to it. */
\r
6081 +static inline int
\r
6082 +timespec_cmp (struct timespec a, struct timespec b)
\r
6084 + return (a.tv_sec < b.tv_sec ? -1
\r
6085 + : a.tv_sec > b.tv_sec ? 1
\r
6086 + : a.tv_nsec < b.tv_nsec ? -1
\r
6087 + : a.tv_nsec > b.tv_nsec ? 1
\r
6091 +void gettime (struct timespec *);
\r
6092 +int settime (struct timespec const *);
\r
6095 diff --git a/lib/verify.h b/lib/verify.h
\r
6096 new file mode 100644
\r
6097 index 0000000..bcd3f5a
\r
6099 +++ b/lib/verify.h
\r
6101 +/* Compile-time assert-like macros.
\r
6103 + Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, Inc.
\r
6105 + This program is free software: you can redistribute it and/or modify
\r
6106 + it under the terms of the GNU General Public License as published by
\r
6107 + the Free Software Foundation; either version 3 of the License, or
\r
6108 + (at your option) any later version.
\r
6110 + This program is distributed in the hope that it will be useful,
\r
6111 + but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
6112 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
6113 + GNU General Public License for more details.
\r
6115 + You should have received a copy of the GNU General Public License
\r
6116 + along with this program. If not, see <http://www.gnu.org/licenses/>. */
\r
6118 +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
\r
6121 +# define VERIFY_H 1
\r
6123 +/* Each of these macros verifies that its argument R is nonzero. To
\r
6124 + be portable, R should be an integer constant expression. Unlike
\r
6125 + assert (R), there is no run-time overhead.
\r
6127 + There are two macros, since no single macro can be used in all
\r
6128 + contexts in C. verify_true (R) is for scalar contexts, including
\r
6129 + integer constant expression contexts. verify (R) is for declaration
\r
6130 + contexts, e.g., the top level.
\r
6132 + Symbols ending in "__" are private to this header.
\r
6134 + The code below uses several ideas.
\r
6136 + * The first step is ((R) ? 1 : -1). Given an expression R, of
\r
6137 + integral or boolean or floating-point type, this yields an
\r
6138 + expression of integral type, whose value is later verified to be
\r
6139 + constant and nonnegative.
\r
6141 + * Next this expression W is wrapped in a type
\r
6142 + struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }.
\r
6143 + If W is negative, this yields a compile-time error. No compiler can
\r
6144 + deal with a bit-field of negative size.
\r
6146 + One might think that an array size check would have the same
\r
6147 + effect, that is, that the type struct { unsigned int dummy[W]; }
\r
6148 + would work as well. However, inside a function, some compilers
\r
6149 + (such as C++ compilers and GNU C) allow local parameters and
\r
6150 + variables inside array size expressions. With these compilers,
\r
6151 + an array size check would not properly diagnose this misuse of
\r
6152 + the verify macro:
\r
6154 + void function (int n) { verify (n < 0); }
\r
6156 + * For the verify macro, the struct verify_type__ will need to
\r
6157 + somehow be embedded into a declaration. To be portable, this
\r
6158 + declaration must declare an object, a constant, a function, or a
\r
6159 + typedef name. If the declared entity uses the type directly,
\r
6162 + struct dummy {...};
\r
6163 + typedef struct {...} dummy;
\r
6164 + extern struct {...} *dummy;
\r
6165 + extern void dummy (struct {...} *);
\r
6166 + extern struct {...} *dummy (void);
\r
6168 + two uses of the verify macro would yield colliding declarations
\r
6169 + if the entity names are not disambiguated. A workaround is to
\r
6170 + attach the current line number to the entity name:
\r
6172 + #define GL_CONCAT0(x, y) x##y
\r
6173 + #define GL_CONCAT(x, y) GL_CONCAT0 (x, y)
\r
6174 + extern struct {...} * GL_CONCAT(dummy,__LINE__);
\r
6176 + But this has the problem that two invocations of verify from
\r
6177 + within the same macro would collide, since the __LINE__ value
\r
6178 + would be the same for both invocations.
\r
6180 + A solution is to use the sizeof operator. It yields a number,
\r
6181 + getting rid of the identity of the type. Declarations like
\r
6183 + extern int dummy [sizeof (struct {...})];
\r
6184 + extern void dummy (int [sizeof (struct {...})]);
\r
6185 + extern int (*dummy (void)) [sizeof (struct {...})];
\r
6187 + can be repeated.
\r
6189 + * Should the implementation use a named struct or an unnamed struct?
\r
6190 + Which of the following alternatives can be used?
\r
6192 + extern int dummy [sizeof (struct {...})];
\r
6193 + extern int dummy [sizeof (struct verify_type__ {...})];
\r
6194 + extern void dummy (int [sizeof (struct {...})]);
\r
6195 + extern void dummy (int [sizeof (struct verify_type__ {...})]);
\r
6196 + extern int (*dummy (void)) [sizeof (struct {...})];
\r
6197 + extern int (*dummy (void)) [sizeof (struct verify_type__ {...})];
\r
6199 + In the second and sixth case, the struct type is exported to the
\r
6200 + outer scope; two such declarations therefore collide. GCC warns
\r
6201 + about the first, third, and fourth cases. So the only remaining
\r
6202 + possibility is the fifth case:
\r
6204 + extern int (*dummy (void)) [sizeof (struct {...})];
\r
6206 + * This implementation exploits the fact that GCC does not warn about
\r
6207 + the last declaration mentioned above. If a future version of GCC
\r
6208 + introduces a warning for this, the problem could be worked around
\r
6209 + by using code specialized to GCC, e.g.,:
\r
6211 + #if 4 <= __GNUC__
\r
6212 + # define verify(R) \
\r
6213 + extern int (* verify_function__ (void)) \
\r
6214 + [__builtin_constant_p (R) && (R) ? 1 : -1]
\r
6217 + * In C++, any struct definition inside sizeof is invalid.
\r
6218 + Use a template type to work around the problem. */
\r
6221 +/* Verify requirement R at compile-time, as an integer constant expression.
\r
6224 +# ifdef __cplusplus
\r
6226 + struct verify_type__ { unsigned int verify_error_if_negative_size__: w; };
\r
6227 +# define verify_true(R) \
\r
6228 + (!!sizeof (verify_type__<(R) ? 1 : -1>))
\r
6230 +# define verify_true(R) \
\r
6232 + (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; }))
\r
6235 +/* Verify requirement R at compile-time, as a declaration without a
\r
6236 + trailing ';'. */
\r
6238 +# define verify(R) extern int (* verify_function__ (void)) [verify_true (R)]
\r