aboutsummaryrefslogtreecommitdiff
path: root/src/parse-datetime.y
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-10-14 15:28:51 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2013-10-14 17:54:41 +0300
commitf035194d7d1b6cc0846ad7a5d86e0d6fa9463c67 (patch)
tree494d180cee9a078727c8d4965caa65cb2052f33d /src/parse-datetime.y
parent58f7dbc0658b3d73816a1bc91b75c2bdac733510 (diff)
downloadvmod-binlog-f035194d7d1b6cc0846ad7a5d86e0d6fa9463c67.tar.gz
vmod-binlog-f035194d7d1b6cc0846ad7a5d86e0d6fa9463c67.tar.bz2
New utility binlogsel
* configure.ac: Check for yacc. * src/.gitignore: Update. * src/Makefile.am (libbinlog_a_SOURCES): Add new files. Build binlogsel. * src/binlogcat.c: Use xmalloc. * src/binlogsel.c: New file. * src/parse-datetime.h: New file. * src/parse-datetime.y: New file. * src/xalloc.c: New file. * src/xalloc.h: New file.
Diffstat (limited to 'src/parse-datetime.y')
-rw-r--r--src/parse-datetime.y1598
1 files changed, 1598 insertions, 0 deletions
diff --git a/src/parse-datetime.y b/src/parse-datetime.y
new file mode 100644
index 0000000..2dd5e1c
--- /dev/null
+++ b/src/parse-datetime.y
@@ -0,0 +1,1598 @@
1%{
2/* Parse a string into an internal time stamp.
3
4 Copyright (C) 1999-2000, 2002-2013 Free Software Foundation, Inc.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19/* Originally written by Steven M. Bellovin <smb@research.att.com> while
20 at the University of North Carolina at Chapel Hill. Later tweaked by
21 a couple of people on Usenet. Completely overhauled by Rich $alz
22 <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
23
24 Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
25 the right thing about local DST. Also modified by Paul Eggert
26 <eggert@cs.ucla.edu> in February 2004 to support
27 nanosecond-resolution time stamps, and in October 2004 to support
28 TZ strings in dates. */
29
30/* FIXME: Check for arithmetic overflow in all cases, not just
31 some of them. */
32
33#include <config.h>
34#include <time.h>
35#include <sys/time.h>
36
37/* There's no need to extend the stack, so there's no need to involve
38 alloca. */
39#define YYSTACK_USE_ALLOCA 0
40
41/* Tell Bison how much stack space is needed. 20 should be plenty for
42 this grammar, which is not right recursive. Beware setting it too
43 high, since that might cause problems on machines whose
44 implementations have lame stack-overflow checking. */
45#define YYMAXDEPTH 20
46#define YYINITDEPTH YYMAXDEPTH
47
48/* Since the code of parse-datetime.y is not included in the Emacs executable
49 itself, there is no need to #define static in this file. Even if
50 the code were included in the Emacs executable, it probably
51 wouldn't do any harm to #undef it here; this will only cause
52 problems if we try to write to a static variable, which I don't
53 think this code needs to do. */
54#ifdef emacs
55# undef static
56#endif
57
58#include <ctype.h>
59#include <limits.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include "err.h"
64#include "xalloc.h"
65
66/* ISDIGIT differs from isdigit, as follows:
67 - Its arg may be any int or unsigned int; it need not be an unsigned char
68 or EOF.
69 - It's typically faster.
70 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
71 isdigit unless it's important to use the locale's definition
72 of "digit" even when the host does not conform to POSIX. */
73#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
74
75/* Shift A right by B bits portably, by dividing A by 2**B and
76 truncating towards minus infinity. A and B should be free of side
77 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
78 INT_BITS is the number of useful bits in an int. GNU code can
79 assume that INT_BITS is at least 32.
80
81 ISO C99 says that A >> B is implementation-defined if A < 0. Some
82 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
83 right in the usual way when A < 0, so SHR falls back on division if
84 ordinary A >> B doesn't seem to be the usual signed shift. */
85#define SHR(a, b) \
86 (-1 >> 1 == -1 \
87 ? (a) >> (b) \
88 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
89
90#define EPOCH_YEAR 1970
91#define TM_YEAR_BASE 1900
92
93#define HOUR(x) ((x) * 60)
94
95/* Convert a possibly-signed character to an unsigned character. This is
96 a bit safer than casting to unsigned char, since it catches some type
97 errors that the cast doesn't. */
98static unsigned char to_uchar (char ch) { return ch; }
99
100#define long_time_t time_t
101
102/* An integer value, and the number of digits in its textual
103 representation. */
104typedef struct
105{
106 int negative;
107 long int value;
108 size_t digits;
109} textint;
110
111/* An entry in the lexical lookup table. */
112typedef struct
113{
114 char const *name;
115 int type;
116 int value;
117} table;
118
119/* Meridian: am, pm, or 24-hour style. */
120enum { MERam, MERpm, MER24 };
121
122enum { BILLION = 1000000000, LOG10_BILLION = 9 };
123
124/* Relative times. */
125typedef struct
126{
127 /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
128 long int year;
129 long int month;
130 long int day;
131 long int hour;
132 long int minutes;
133 long_time_t seconds;
134 long int ns;
135} relative_time;
136
137#if HAVE_COMPOUND_LITERALS
138# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
139#else
140static relative_time const RELATIVE_TIME_0;
141#endif
142
143/* Information passed to and from the parser. */
144typedef struct
145{
146 /* The input string remaining to be parsed. */
147 const char *input;
148
149 /* N, if this is the Nth Tuesday. */
150 long int day_ordinal;
151
152 /* Day of week; Sunday is 0. */
153 int day_number;
154
155 /* tm_isdst flag for the local zone. */
156 int local_isdst;
157
158 /* Time zone, in minutes east of UTC. */
159 long int time_zone;
160
161 /* Style used for time. */
162 int meridian;
163
164 /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */
165 textint year;
166 long int month;
167 long int day;
168 long int hour;
169 long int minutes;
170 struct timespec seconds; /* includes nanoseconds */
171
172 /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
173 relative_time rel;
174
175 /* Presence or counts of nonterminals of various flavors parsed so far. */
176 int timespec_seen;
177 int rels_seen;
178 size_t dates_seen;
179 size_t days_seen;
180 size_t local_zones_seen;
181 size_t dsts_seen;
182 size_t times_seen;
183 size_t zones_seen;
184
185 /* Table of local time zone abbreviations, terminated by a null entry. */
186 table local_time_zone_table[3];
187} parser_control;
188
189union YYSTYPE;
190static int yylex (union YYSTYPE *, parser_control *);
191static int yyerror (parser_control const *, char const *);
192static long int time_zone_hhmm (parser_control *, textint, long int);
193
194/* Extract into *PC any date and time info from a string of digits
195 of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
196 YYYY, ...). */
197static void
198digits_to_date_time (parser_control *pc, textint text_int)
199{
200 if (pc->dates_seen && ! pc->year.digits
201 && ! pc->rels_seen && (pc->times_seen || 2 < text_int.digits))
202 pc->year = text_int;
203 else
204 {
205 if (4 < text_int.digits)
206 {
207 pc->dates_seen++;
208 pc->day = text_int.value % 100;
209 pc->month = (text_int.value / 100) % 100;
210 pc->year.value = text_int.value / 10000;
211 pc->year.digits = text_int.digits - 4;
212 }
213 else
214 {
215 pc->times_seen++;
216 if (text_int.digits <= 2)
217 {
218 pc->hour = text_int.value;
219 pc->minutes = 0;
220 }
221 else
222 {
223 pc->hour = text_int.value / 100;
224 pc->minutes = text_int.value % 100;
225 }
226 pc->seconds.tv_sec = 0;