diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-14 15:28:51 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-14 17:54:41 +0300 |
commit | f035194d7d1b6cc0846ad7a5d86e0d6fa9463c67 (patch) | |
tree | 494d180cee9a078727c8d4965caa65cb2052f33d /src/parse-datetime.y | |
parent | 58f7dbc0658b3d73816a1bc91b75c2bdac733510 (diff) | |
download | vmod-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.y | 1598 |
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. */ | ||
98 | static 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. */ | ||
104 | typedef struct | ||
105 | { | ||
106 | int negative; | ||
107 | long int value; | ||
108 | size_t digits; | ||
109 | } textint; | ||
110 | |||
111 | /* An entry in the lexical lookup table. */ | ||
112 | typedef struct | ||
113 | { | ||
114 | char const *name; | ||
115 | int type; | ||
116 | int value; | ||
117 | } table; | ||
118 | |||
119 | /* Meridian: am, pm, or 24-hour style. */ | ||
120 | enum { MERam, MERpm, MER24 }; | ||
121 | |||
122 | enum { BILLION = 1000000000, LOG10_BILLION = 9 }; | ||
123 | |||
124 | /* Relative times. */ | ||
125 | typedef 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 | ||
140 | static relative_time const RELATIVE_TIME_0; | ||
141 | #endif | ||
142 | |||
143 | /* Information passed to and from the parser. */ | ||
144 | typedef 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 | |||
189 | union YYSTYPE; | ||
190 | static int yylex (union YYSTYPE *, parser_control *); | ||
191 | static int yyerror (parser_control const *, char const *); | ||
192 | static 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, ...). */ | ||
197 | static void | ||
198 | digits_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; | ||