1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2006 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Derick Rethans <derick@derickrethans.nl> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: parse_date.re,v 1.26.2.27.2.9 2007/03/21 09:40:33 derick Exp $ */
20 :
21 : #include "timelib.h"
22 :
23 : #include <stdio.h>
24 : #include <ctype.h>
25 :
26 : #ifdef HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif
29 : #ifdef HAVE_STRING_H
30 : #include <string.h>
31 : #else
32 : #include <strings.h>
33 : #endif
34 :
35 : #if defined(_MSC_VER)
36 : # define strtoll(s, f, b) _atoi64(s)
37 : #elif !defined(HAVE_STRTOLL)
38 : # if defined(HAVE_ATOLL)
39 : # define strtoll(s, f, b) atoll(s)
40 : # else
41 : # define strtoll(s, f, b) strtol(s, f, b)
42 : # endif
43 : #endif
44 :
45 : #define TIMELIB_SECOND 1
46 : #define TIMELIB_MINUTE 2
47 : #define TIMELIB_HOUR 3
48 : #define TIMELIB_DAY 4
49 : #define TIMELIB_MONTH 5
50 : #define TIMELIB_YEAR 6
51 : #define TIMELIB_WEEKDAY 7
52 : #define TIMELIB_SPECIAL 8
53 :
54 : #define EOI 257
55 : #define TIME 258
56 : #define DATE 259
57 :
58 : #define TIMELIB_XMLRPC_SOAP 260
59 : #define TIMELIB_TIME12 261
60 : #define TIMELIB_TIME24 262
61 : #define TIMELIB_GNU_NOCOLON 263
62 : #define TIMELIB_GNU_NOCOLON_TZ 264
63 : #define TIMELIB_ISO_NOCOLON 265
64 :
65 : #define TIMELIB_AMERICAN 266
66 : #define TIMELIB_ISO_DATE 267
67 : #define TIMELIB_DATE_FULL 268
68 : #define TIMELIB_DATE_TEXT 269
69 : #define TIMELIB_DATE_NOCOLON 270
70 : #define TIMELIB_PG_YEARDAY 271
71 : #define TIMELIB_PG_TEXT 272
72 : #define TIMELIB_PG_REVERSE 273
73 : #define TIMELIB_CLF 274
74 : #define TIMELIB_DATE_NO_DAY 275
75 : #define TIMELIB_SHORTDATE_WITH_TIME 276
76 : #define TIMELIB_DATE_FULL_POINTED 277
77 : #define TIMELIB_TIME24_WITH_ZONE 278
78 : #define TIMELIB_ISO_WEEK 279
79 :
80 : #define TIMELIB_TIMEZONE 300
81 : #define TIMELIB_AGO 301
82 :
83 : #define TIMELIB_RELATIVE 310
84 :
85 : #define TIMELIB_ERROR 999
86 :
87 : typedef unsigned char uchar;
88 :
89 : #define BSIZE 8192
90 :
91 : #define YYCTYPE uchar
92 : #define YYCURSOR cursor
93 : #define YYLIMIT s->lim
94 : #define YYMARKER s->ptr
95 : #define YYFILL(n) return EOI;
96 :
97 : #define RET(i) {s->cur = cursor; return i;}
98 :
99 : #define timelib_string_free free
100 :
101 : #define TIMELIB_HAVE_TIME() { if (s->time->have_time) { add_error(s, "Double time specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
102 : #define TIMELIB_UNHAVE_TIME() { s->time->have_time = 0; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; }
103 : #define TIMELIB_HAVE_DATE() { if (s->time->have_date) { add_error(s, "Double date specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
104 : #define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
105 : #define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; s->time->relative.weekday_behavior = 1; }
106 : #define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_weekday_relative = 1; }
107 : #define TIMELIB_HAVE_SPECIAL_RELATIVE() { s->time->have_special_relative = 1; }
108 : #define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { add_warning(s, "Double timezone specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_zone = 1; } }
109 :
110 : #define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
111 : #define TIMELIB_DEINIT timelib_string_free(str)
112 : #define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
113 :
114 : #define TIMELIB_PROCESS_YEAR(x) { \
115 : if ((x) == -1) { \
116 : /* (x) = 0; */ \
117 : } else if ((x) < 100) { \
118 : if ((x) < 70) { \
119 : (x) += 2000; \
120 : } else { \
121 : (x) += 1900; \
122 : } \
123 : } \
124 : }
125 :
126 : #ifdef DEBUG_PARSER
127 : #define DEBUG_OUTPUT(s) printf("%s\n", s);
128 : #define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
129 : #else
130 : #define DEBUG_OUTPUT(s)
131 : #define YYDEBUG(s,c)
132 : #endif
133 :
134 : #include "timelib_structs.h"
135 :
136 : typedef struct timelib_elems {
137 : unsigned int c; /* Number of elements */
138 : char **v; /* Values */
139 : } timelib_elems;
140 :
141 : typedef struct Scanner {
142 : int fd;
143 : uchar *lim, *str, *ptr, *cur, *tok, *pos;
144 : unsigned int line, len;
145 : struct timelib_error_container *errors;
146 :
147 : struct timelib_time *time;
148 : const timelib_tzdb *tzdb;
149 : } Scanner;
150 :
151 : typedef struct _timelib_lookup_table {
152 : const char *name;
153 : int type;
154 : int value;
155 : } timelib_lookup_table;
156 :
157 : typedef struct _timelib_relunit {
158 : const char *name;
159 : int unit;
160 : int multiplier;
161 : } timelib_relunit;
162 :
163 : #define HOUR(a) (int)(a * 60)
164 :
165 : /* The timezone table. */
166 : const static timelib_tz_lookup_table timelib_timezone_lookup[] = {
167 : #include "timezonemap.h"
168 : { NULL, 0, 0, NULL },
169 : };
170 :
171 : const static timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
172 : #include "fallbackmap.h"
173 : { NULL, 0, 0, NULL },
174 : };
175 :
176 : const static timelib_tz_lookup_table timelib_timezone_utc[] = {
177 : { "utc", 0, 0, "UTC" },
178 : };
179 :
180 : static timelib_relunit const timelib_relunit_lookup[] = {
181 : { "sec", TIMELIB_SECOND, 1 },
182 : { "secs", TIMELIB_SECOND, 1 },
183 : { "second", TIMELIB_SECOND, 1 },
184 : { "seconds", TIMELIB_SECOND, 1 },
185 : { "min", TIMELIB_MINUTE, 1 },
186 : { "mins", TIMELIB_MINUTE, 1 },
187 : { "minute", TIMELIB_MINUTE, 1 },
188 : { "minutes", TIMELIB_MINUTE, 1 },
189 : { "hour", TIMELIB_HOUR, 1 },
190 : { "hours", TIMELIB_HOUR, 1 },
191 : { "day", TIMELIB_DAY, 1 },
192 : { "days", TIMELIB_DAY, 1 },
193 : { "week", TIMELIB_DAY, 7 },
194 : { "weeks", TIMELIB_DAY, 7 },
195 : { "fortnight", TIMELIB_DAY, 14 },
196 : { "fortnights", TIMELIB_DAY, 14 },
197 : { "forthnight", TIMELIB_DAY, 14 },
198 : { "forthnights", TIMELIB_DAY, 14 },
199 : { "month", TIMELIB_MONTH, 1 },
200 : { "months", TIMELIB_MONTH, 1 },
201 : { "year", TIMELIB_YEAR, 1 },
202 : { "years", TIMELIB_YEAR, 1 },
203 :
204 : { "monday", TIMELIB_WEEKDAY, 1 },
205 : { "mon", TIMELIB_WEEKDAY, 1 },
206 : { "tuesday", TIMELIB_WEEKDAY, 2 },
207 : { "tue", TIMELIB_WEEKDAY, 2 },
208 : { "wednesday", TIMELIB_WEEKDAY, 3 },
209 : { "wed", TIMELIB_WEEKDAY, 3 },
210 : { "thursday", TIMELIB_WEEKDAY, 4 },
211 : { "thu", TIMELIB_WEEKDAY, 4 },
212 : { "friday", TIMELIB_WEEKDAY, 5 },
213 : { "fri", TIMELIB_WEEKDAY, 5 },
214 : { "saturday", TIMELIB_WEEKDAY, 6 },
215 : { "sat", TIMELIB_WEEKDAY, 6 },
216 : { "sunday", TIMELIB_WEEKDAY, 0 },
217 : { "sun", TIMELIB_WEEKDAY, 0 },
218 :
219 : { "weekday", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
220 : { "weekdays", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
221 : { NULL, 0, 0 }
222 : };
223 :
224 : /* The relative text table. */
225 : static timelib_lookup_table const timelib_reltext_lookup[] = {
226 : { "first", 0, 1 },
227 : { "next", 0, 1 },
228 : { "second", 0, 2 },
229 : { "third", 0, 3 },
230 : { "fourth", 0, 4 },
231 : { "fifth", 0, 5 },
232 : { "sixth", 0, 6 },
233 : { "seventh", 0, 7 },
234 : { "eight", 0, 8 },
235 : { "ninth", 0, 9 },
236 : { "tenth", 0, 10 },
237 : { "eleventh", 0, 11 },
238 : { "twelfth", 0, 12 },
239 : { "last", 0, -1 },
240 : { "previous", 0, -1 },
241 : { "this", 1, 0 },
242 : { NULL, 1, 0 }
243 : };
244 :
245 : /* The month table. */
246 : static timelib_lookup_table const timelib_month_lookup[] = {
247 : { "jan", 0, 1 },
248 : { "feb", 0, 2 },
249 : { "mar", 0, 3 },
250 : { "apr", 0, 4 },
251 : { "may", 0, 5 },
252 : { "jun", 0, 6 },
253 : { "jul", 0, 7 },
254 : { "aug", 0, 8 },
255 : { "sep", 0, 9 },
256 : { "sept", 0, 9 },
257 : { "oct", 0, 10 },
258 : { "nov", 0, 11 },
259 : { "dec", 0, 12 },
260 : { "i", 0, 1 },
261 : { "ii", 0, 2 },
262 : { "iii", 0, 3 },
263 : { "iv", 0, 4 },
264 : { "v", 0, 5 },
265 : { "vi", 0, 6 },
266 : { "vii", 0, 7 },
267 : { "viii", 0, 8 },
268 : { "ix", 0, 9 },
269 : { "x", 0, 10 },
270 : { "xi", 0, 11 },
271 : { "xii", 0, 12 },
272 :
273 : { "january", 0, 1 },
274 : { "february", 0, 2 },
275 : { "march", 0, 3 },
276 : { "april", 0, 4 },
277 : { "may", 0, 5 },
278 : { "june", 0, 6 },
279 : { "july", 0, 7 },
280 : { "august", 0, 8 },
281 : { "september", 0, 9 },
282 : { "october", 0, 10 },
283 : { "november", 0, 11 },
284 : { "december", 0, 12 },
285 : { NULL, 0, 0 }
286 : };
287 :
288 : #if 0
289 : static char* timelib_ltrim(char *s)
290 : {
291 : char *ptr = s;
292 : while (ptr[0] == ' ' || ptr[0] == '\t') {
293 : ptr++;
294 : }
295 : return ptr;
296 : }
297 : #endif
298 :
299 : #if 0
300 : uchar *fill(Scanner *s, uchar *cursor){
301 : if(!s->eof){
302 : unsigned int cnt = s->tok - s->bot;
303 : if(cnt){
304 : memcpy(s->bot, s->tok, s->lim - s->tok);
305 : s->tok = s->bot;
306 : s->ptr -= cnt;
307 : cursor -= cnt;
308 : s->pos -= cnt;
309 : s->lim -= cnt;
310 : }
311 : if((s->top - s->lim) < BSIZE){
312 : uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
313 : memcpy(buf, s->tok, s->lim - s->tok);
314 : s->tok = buf;
315 : s->ptr = &buf[s->ptr - s->bot];
316 : cursor = &buf[cursor - s->bot];
317 : s->pos = &buf[s->pos - s->bot];
318 : s->lim = &buf[s->lim - s->bot];
319 : s->top = &s->lim[BSIZE];
320 : free(s->bot);
321 : s->bot = buf;
322 : }
323 : if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
324 : s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
325 : }
326 : s->lim += cnt;
327 : }
328 : return cursor;
329 : }
330 : #endif
331 :
332 : static void add_warning(Scanner *s, char *error)
333 0 : {
334 0 : s->errors->warning_count++;
335 0 : s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
336 0 : s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
337 0 : s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
338 0 : s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
339 0 : }
340 :
341 : static void add_error(Scanner *s, char *error)
342 0 : {
343 0 : s->errors->error_count++;
344 0 : s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
345 0 : s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
346 0 : s->errors->error_messages[s->errors->error_count - 1].character = s->tok ? *s->tok : 0;
347 0 : s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
348 0 : }
349 :
350 : static timelib_sll timelib_meridian(char **ptr, timelib_sll h)
351 0 : {
352 0 : timelib_sll retval = 0;
353 :
354 0 : while (!strchr("AaPp", **ptr)) {
355 0 : ++*ptr;
356 : }
357 0 : if (**ptr == 'a' || **ptr == 'A') {
358 0 : if (h == 12) {
359 0 : retval = -12;
360 : }
361 0 : } else if (h != 12) {
362 0 : retval = 12;
363 : }
364 0 : ++*ptr;
365 0 : if (**ptr == '.') {
366 0 : *ptr += 3;
367 : } else {
368 0 : ++*ptr;
369 : }
370 0 : return retval;
371 : }
372 :
373 : static char *timelib_string(Scanner *s)
374 4 : {
375 4 : char *tmp = calloc(1, s->cur - s->tok + 1);
376 4 : memcpy(tmp, s->tok, s->cur - s->tok);
377 :
378 4 : return tmp;
379 : }
380 :
381 : static timelib_sll timelib_get_nr(char **ptr, int max_length)
382 5 : {
383 : char *begin, *end, *str;
384 5 : timelib_sll tmp_nr = -1;
385 5 : int len = 0;
386 :
387 13 : while ((**ptr < '0') || (**ptr > '9')) {
388 3 : if (**ptr == '\0') {
389 0 : return -1;
390 : }
391 3 : ++*ptr;
392 : }
393 5 : begin = *ptr;
394 22 : while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
395 12 : ++*ptr;
396 12 : ++len;
397 : }
398 5 : end = *ptr;
399 5 : str = calloc(1, end - begin + 1);
400 5 : memcpy(str, begin, end - begin);
401 5 : tmp_nr = strtoll(str, NULL, 10);
402 5 : free(str);
403 5 : return tmp_nr;
404 : }
405 :
406 : static void timelib_skip_day_suffix(char **ptr)
407 1 : {
408 1 : if (isspace(**ptr)) {
409 1 : return;
410 : }
411 0 : if (!strncasecmp(*ptr, "nd", 2) || !strncasecmp(*ptr, "rd", 2) ||!strncasecmp(*ptr, "st", 2) || !strncasecmp(*ptr, "th", 2)) {
412 0 : *ptr += 2;
413 : }
414 : }
415 :
416 : static double timelib_get_frac_nr(char **ptr, int max_length)
417 0 : {
418 : char *begin, *end, *str;
419 0 : double tmp_nr = -1;
420 0 : int len = 0;
421 :
422 0 : while ((**ptr != '.') && ((**ptr < '0') || (**ptr > '9'))) {
423 0 : if (**ptr == '\0') {
424 0 : return -1;
425 : }
426 0 : ++*ptr;
427 : }
428 0 : begin = *ptr;
429 0 : while (((**ptr == '.') || ((**ptr >= '0') && (**ptr <= '9'))) && len < max_length) {
430 0 : ++*ptr;
431 0 : ++len;
432 : }
433 0 : end = *ptr;
434 0 : str = calloc(1, end - begin + 1);
435 0 : memcpy(str, begin, end - begin);
436 0 : tmp_nr = strtod(str, NULL);
437 0 : free(str);
438 0 : return tmp_nr;
439 : }
440 :
441 : static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
442 0 : {
443 0 : timelib_ull dir = 1;
444 :
445 0 : while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
446 0 : if (**ptr == '\0') {
447 0 : return -1;
448 : }
449 0 : ++*ptr;
450 : }
451 0 : if (**ptr == '+') {
452 0 : ++*ptr;
453 0 : } else if (**ptr == '-') {
454 0 : dir = -1;
455 0 : ++*ptr;
456 : }
457 0 : return dir * timelib_get_nr(ptr, max_length);
458 : }
459 :
460 : static long timelib_parse_tz_cor(char **ptr)
461 0 : {
462 0 : char *begin = *ptr, *end;
463 : long tmp;
464 :
465 0 : while (**ptr != '\0') {
466 0 : ++*ptr;
467 : }
468 0 : end = *ptr;
469 0 : switch (end - begin) {
470 : case 1:
471 : case 2:
472 0 : return HOUR(strtol(begin, NULL, 10));
473 : break;
474 : case 3:
475 : case 4:
476 0 : if (begin[1] == ':') {
477 0 : tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
478 0 : return tmp;
479 0 : } else if (begin[2] == ':') {
480 0 : tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
481 0 : return tmp;
482 : } else {
483 0 : tmp = strtol(begin, NULL, 10);
484 0 : return HOUR(tmp / 100) + tmp % 100;
485 : }
486 : case 5:
487 0 : tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
488 0 : return tmp;
489 : }
490 0 : return 0;
491 : }
492 :
493 : static timelib_sll timelib_lookup_relative_text(char **ptr, int *behavior)
494 0 : {
495 : char *word;
496 0 : char *begin = *ptr, *end;
497 0 : timelib_sll value = 0;
498 : const timelib_lookup_table *tp;
499 :
500 0 : while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
501 0 : ++*ptr;
502 : }
503 0 : end = *ptr;
504 0 : word = calloc(1, end - begin + 1);
505 0 : memcpy(word, begin, end - begin);
506 :
507 0 : for (tp = timelib_reltext_lookup; tp->name; tp++) {
508 0 : if (strcasecmp(word, tp->name) == 0) {
509 0 : value = tp->value;
510 0 : *behavior = tp->type;
511 : }
512 : }
513 :
514 0 : free(word);
515 0 : return value;
516 : }
517 :
518 : static timelib_sll timelib_get_relative_text(char **ptr, int *behavior)
519 0 : {
520 0 : while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '/') {
521 0 : ++*ptr;
522 : }
523 0 : return timelib_lookup_relative_text(ptr, behavior);
524 : }
525 :
526 : static long timelib_lookup_month(char **ptr)
527 1 : {
528 : char *word;
529 1 : char *begin = *ptr, *end;
530 1 : long value = 0;
531 : const timelib_lookup_table *tp;
532 :
533 5 : while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
534 3 : ++*ptr;
535 : }
536 1 : end = *ptr;
537 1 : word = calloc(1, end - begin + 1);
538 1 : memcpy(word, begin, end - begin);
539 :
540 38 : for (tp = timelib_month_lookup; tp->name; tp++) {
541 37 : if (strcasecmp(word, tp->name) == 0) {
542 1 : value = tp->value;
543 : }
544 : }
545 :
546 1 : free(word);
547 1 : return value;
548 : }
549 :
550 : static long timelib_get_month(char **ptr)
551 1 : {
552 3 : while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '.' || **ptr == '/') {
553 1 : ++*ptr;
554 : }
555 1 : return timelib_lookup_month(ptr);
556 : }
557 :
558 : static void timelib_eat_spaces(char **ptr)
559 0 : {
560 0 : while (**ptr == ' ' || **ptr == '\t') {
561 0 : ++*ptr;
562 : }
563 0 : }
564 :
565 : static const timelib_relunit* timelib_lookup_relunit(char **ptr)
566 1 : {
567 : char *word;
568 1 : char *begin = *ptr, *end;
569 1 : const timelib_relunit *tp, *value = NULL;
570 :
571 5 : while (**ptr != '\0' && **ptr != ' ' && **ptr != '\t') {
572 3 : ++*ptr;
573 : }
574 1 : end = *ptr;
575 1 : word = calloc(1, end - begin + 1);
576 1 : memcpy(word, begin, end - begin);
577 :
578 26 : for (tp = timelib_relunit_lookup; tp->name; tp++) {
579 26 : if (strcasecmp(word, tp->name) == 0) {
580 1 : value = tp;
581 1 : break;
582 : }
583 : }
584 :
585 1 : free(word);
586 1 : return value;
587 : }
588 :
589 : static void timelib_set_relative(char **ptr, timelib_sll amount, int behavior, Scanner *s)
590 0 : {
591 : const timelib_relunit* relunit;
592 :
593 0 : if (!(relunit = timelib_lookup_relunit(ptr))) {
594 0 : return;
595 : }
596 :
597 0 : switch (relunit->unit) {
598 0 : case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
599 0 : case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
600 0 : case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break;
601 0 : case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break;
602 0 : case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break;
603 0 : case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break;
604 :
605 : case TIMELIB_WEEKDAY:
606 0 : TIMELIB_HAVE_WEEKDAY_RELATIVE();
607 0 : TIMELIB_UNHAVE_TIME();
608 0 : s->time->relative.d += (amount > 0 ? amount - 1 : amount) * 7;
609 0 : s->time->relative.weekday = relunit->multiplier;
610 0 : s->time->relative.weekday_behavior = behavior;
611 0 : break;
612 :
613 : case TIMELIB_SPECIAL:
614 0 : TIMELIB_HAVE_SPECIAL_RELATIVE();
615 0 : TIMELIB_UNHAVE_TIME();
616 0 : s->time->special.type = relunit->multiplier;
617 0 : s->time->special.amount = amount;
618 : }
619 : }
620 :
621 : const static timelib_tz_lookup_table* zone_search(const char *word, long gmtoffset, int isdst)
622 2 : {
623 2 : int first_found = 0;
624 2 : const timelib_tz_lookup_table *tp, *first_found_elem = NULL;
625 : const timelib_tz_lookup_table *fmp;
626 :
627 2 : if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
628 1 : return timelib_timezone_utc;
629 : }
630 :
631 373 : for (tp = timelib_timezone_lookup; tp->name; tp++) {
632 373 : if (strcasecmp(word, tp->name) == 0) {
633 1 : if (!first_found) {
634 1 : first_found = 1;
635 1 : first_found_elem = tp;
636 1 : if (gmtoffset == -1) {
637 0 : return tp;
638 : }
639 : }
640 1 : if (tp->gmtoffset == gmtoffset) {
641 1 : return tp;
642 : }
643 : }
644 : }
645 0 : if (first_found) {
646 0 : return first_found_elem;
647 : }
648 :
649 : /* Still didn't find anything, let's find the zone solely based on
650 : * offset/isdst then */
651 0 : for (fmp = timelib_timezone_fallbackmap; fmp->name; fmp++) {
652 0 : if ((fmp->gmtoffset * 3600) == gmtoffset && fmp->type == isdst) {
653 0 : return fmp;
654 : }
655 : }
656 0 : return NULL;
657 : }
658 :
659 : static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found)
660 1 : {
661 : char *word;
662 1 : char *begin = *ptr, *end;
663 1 : long value = 0;
664 : const timelib_tz_lookup_table *tp;
665 :
666 5 : while (**ptr != '\0' && **ptr != ')') {
667 3 : ++*ptr;
668 : }
669 1 : end = *ptr;
670 1 : word = calloc(1, end - begin + 1);
671 1 : memcpy(word, begin, end - begin);
672 :
673 1 : if ((tp = zone_search(word, -1, 0))) {
674 1 : value = -tp->gmtoffset / 60;
675 1 : *dst = tp->type;
676 1 : value += tp->type * 60;
677 1 : *found = 1;
678 : } else {
679 0 : *found = 0;
680 : }
681 :
682 1 : *tz_abbr = word;
683 1 : return value;
684 : }
685 :
686 : static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb)
687 1 : {
688 : timelib_tzinfo *res;
689 1 : long retval = 0;
690 :
691 1 : *tz_not_found = 0;
692 :
693 2 : while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
694 0 : ++*ptr;
695 : }
696 1 : if (**ptr == '+') {
697 0 : ++*ptr;
698 0 : t->is_localtime = 1;
699 0 : t->zone_type = TIMELIB_ZONETYPE_OFFSET;
700 0 : *tz_not_found = 0;
701 0 : t->dst = 0;
702 :
703 0 : retval = -1 * timelib_parse_tz_cor(ptr);
704 1 : } else if (**ptr == '-') {
705 0 : ++*ptr;
706 0 : t->is_localtime = 1;
707 0 : t->zone_type = TIMELIB_ZONETYPE_OFFSET;
708 0 : *tz_not_found = 0;
709 0 : t->dst = 0;
710 :
711 0 : retval = timelib_parse_tz_cor(ptr);
712 : } else {
713 1 : int found = 0;
714 : long offset;
715 : char *tz_abbr;
716 :
717 1 : t->is_localtime = 1;
718 :
719 1 : offset = timelib_lookup_zone(ptr, dst, &tz_abbr, &found);
720 1 : if (found) {
721 1 : t->zone_type = TIMELIB_ZONETYPE_ABBR;
722 : }
723 : #if 0
724 : /* If we found a TimeZone identifier, use it */
725 : if (tz_name) {
726 : t->tz_info = timelib_parse_tzfile(tz_name);
727 : t->zone_type = TIMELIB_ZONETYPE_ID;
728 : }
729 : #endif
730 : /* If we have a TimeZone identifier to start with, use it */
731 1 : if (strstr(tz_abbr, "/")) {
732 0 : if ((res = timelib_parse_tzfile(tz_abbr, tzdb)) != NULL) {
733 0 : t->tz_info = res;
734 0 : t->zone_type = TIMELIB_ZONETYPE_ID;
735 0 : found++;
736 : }
737 : }
738 1 : if (found && t->zone_type != TIMELIB_ZONETYPE_ID) {
739 1 : timelib_time_tz_abbr_update(t, tz_abbr);
740 : }
741 1 : free(tz_abbr);
742 1 : *tz_not_found = (found == 0);
743 1 : retval = offset;
744 : }
745 2 : while (**ptr == ')') {
746 0 : ++*ptr;
747 : }
748 1 : return retval;
749 : }
750 :
751 : #define timelib_split_free(arg) { \
752 : int i; \
753 : for (i = 0; i < arg.c; i++) { \
754 : free(arg.v[i]); \
755 : } \
756 : if (arg.v) { \
757 : free(arg.v); \
758 : } \
759 : }
760 :
761 : static int scan(Scanner *s)
762 5 : {
763 5 : uchar *cursor = s->cur;
764 5 : char *str, *ptr = NULL;
765 :
766 10 : std:
767 10 : s->tok = cursor;
768 10 : s->len = 0;
769 : /*!re2c
770 : any = [\000-\377];
771 :
772 : space = [ \t]+;
773 : frac = "."[0-9]+;
774 :
775 : ago = 'ago';
776 :
777 : hour24 = [01]?[0-9] | "2"[0-3];
778 : hour24lz = [01][0-9] | "2"[0-3];
779 : hour12 = "0"?[1-9] | "1"[0-2];
780 : minute = [0-5]?[0-9];
781 : minutelz = [0-5][0-9];
782 : second = minute | "60";
783 : secondlz = minutelz | "60";
784 : meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
785 : tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+;
786 : tzcorrection = [+-] hour24 ":"? minute?;
787 :
788 : daysuf = "st" | "nd" | "rd" | "th";
789 :
790 : month = "0"? [0-9] | "1"[0-2];
791 : day = ([0-2]?[0-9] | "3"[01]) daysuf?;
792 : year = [0-9]{1,4};
793 : year2 = [0-9]{2};
794 : year4 = [0-9]{4};
795 :
796 : dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
797 : weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
798 :
799 : monthlz = "0" [1-9] | "1" [0-2];
800 : daylz = "0" [1-9] | [1-2][0-9] | "3" [01];
801 :
802 : dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
803 : dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
804 : dayspecial = 'weekday' | 'weekdays';
805 : daytext = dayfull | dayabbr | dayspecial;
806 :
807 : monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
808 : monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
809 : monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
810 : monthtext = monthfull | monthabbr | monthroman;
811 :
812 : /* Time formats */
813 : timetiny12 = hour12 space? meridian;
814 : timeshort12 = hour12[:.]minutelz space? meridian;
815 : timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
816 :
817 : timeshort24 = 't'? hour24[:.]minute;
818 : timelong24 = 't'? hour24[:.]minute[:.]second;
819 : iso8601long = 't'? hour24 [:.] minute [:.] second frac;
820 :
821 : /* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
822 : iso8601normtz = 't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
823 : /* iso8601longtz = hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
824 :
825 : gnunocolon = 't'? hour24lz minutelz;
826 : /* gnunocolontz = hour24lz minutelz space? (tzcorrection | tz); */
827 : iso8601nocolon = 't'? hour24lz minutelz secondlz;
828 : /* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
829 :
830 : /* Date formats */
831 : americanshort = month "/" day;
832 : american = month "/" day "/" year;
833 : iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
834 : dateslash = year4 "/" month "/" day;
835 : gnudateshorter = year4 "-" month;
836 : gnudateshort = year "-" month "-" day;
837 : iso8601date = year4 "-" monthlz "-" daylz;
838 : pointeddate = day [.\t-] month [.-] year;
839 : datefull = day ([ \t.-])* monthtext ([ \t.-])* year;
840 : datenoday = monthtext ([ .\t-])* year4;
841 : datenodayrev = year4 ([ .\t-])* monthtext;
842 : datetextual = monthtext ([ .\t-])* day [,.stndrh\t ]* year;
843 : datenoyear = monthtext ([ .\t-])* day [,.stndrh\t ]*;
844 : datenoyearrev = day ([ .\t-])* monthtext;
845 : datenocolon = year4 monthlz daylz;
846 :
847 : /* Special formats */
848 : soap = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection?;
849 : xmlrpc = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
850 : xmlrpcnocolon = year4 monthlz daylz 't' hour24 minutelz secondlz;
851 : wddx = year4 "-" month "-" day "T" hour24 ":" minute ":" second;
852 : pgydotd = year4 "."? dayofyear;
853 : pgtextshort = monthabbr "-" daylz "-" year;
854 : pgtextreverse = year "-" monthabbr "-" daylz;
855 : isoweekday = year4 "-"? "W" weekofyear "-"? [0-7];
856 : isoweek = year4 "-"? "W" weekofyear;
857 : exif = year4 ":" monthlz ":" daylz " " hour24lz ":" minutelz ":" secondlz;
858 :
859 : /* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
860 : clf = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
861 :
862 : /* Timestamp format: @1126396800 */
863 : timestamp = "@" "-"? [0-9]+;
864 :
865 : /* To fix some ambiguities */
866 : dateshortwithtimeshort12 = datenoyear timeshort12;
867 : dateshortwithtimelong12 = datenoyear timelong12;
868 : dateshortwithtimeshort = datenoyear timeshort24;
869 : dateshortwithtimelong = datenoyear timelong24;
870 : dateshortwithtimelongtz = datenoyear iso8601normtz;
871 :
872 : /*
873 : * Relative regexps
874 : */
875 : reltextnumber = 'first'|'next'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'ninth'|'tenth'|'eleventh'|'twelfth'|'last'|'previous'|'this';
876 : reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'week'|'fortnight'|'forthnight'|'month'|'year') 's'?) | daytext;
877 :
878 : relnumber = ([+-]?[ \t]*[0-9]+);
879 : relative = relnumber space? reltextunit;
880 : relativetext = reltextnumber space reltextunit;
881 :
882 : */
883 :
884 : /*!re2c
885 : /* so that vim highlights correctly */
886 : 'yesterday'
887 : {
888 : DEBUG_OUTPUT("yesterday");
889 0 : TIMELIB_INIT;
890 0 : TIMELIB_HAVE_RELATIVE();
891 0 : TIMELIB_UNHAVE_TIME();
892 :
893 0 : s->time->relative.d = -1;
894 0 : TIMELIB_DEINIT;
895 0 : return TIMELIB_RELATIVE;
896 : }
897 :
898 : 'now'
899 : {
900 : DEBUG_OUTPUT("now");
901 0 : TIMELIB_INIT;
902 :
903 0 : TIMELIB_DEINIT;
904 0 : return TIMELIB_RELATIVE;
905 : }
906 :
907 : 'noon'
908 : {
909 : DEBUG_OUTPUT("noon");
910 0 : TIMELIB_INIT;
911 0 : TIMELIB_UNHAVE_TIME();
912 0 : TIMELIB_HAVE_TIME();
913 0 : s->time->h = 12;
914 :
915 0 : TIMELIB_DEINIT;
916 0 : return TIMELIB_RELATIVE;
917 : }
918 :
919 : 'midnight' | 'today'
920 : {
921 : DEBUG_OUTPUT("midnight | today");
922 0 : TIMELIB_INIT;
923 0 : TIMELIB_UNHAVE_TIME();
924 :
925 0 : TIMELIB_DEINIT;
926 0 : return TIMELIB_RELATIVE;
927 : }
928 :
929 : 'tomorrow'
930 : {
931 : DEBUG_OUTPUT("tomorrow");
932 0 : TIMELIB_INIT;
933 0 : TIMELIB_HAVE_RELATIVE();
934 0 : TIMELIB_UNHAVE_TIME();
935 :
936 0 : s->time->relative.d = 1;
937 0 : TIMELIB_DEINIT;
938 0 : return TIMELIB_RELATIVE;
939 : }
940 :
941 : timestamp
942 : {
943 : timelib_ull i;
944 :
945 0 : TIMELIB_INIT;
946 0 : TIMELIB_HAVE_RELATIVE();
947 0 : TIMELIB_UNHAVE_DATE();
948 0 : TIMELIB_UNHAVE_TIME();
949 :
950 0 : i = timelib_get_unsigned_nr((char **) &ptr, 24);
951 0 : s->time->y = 1970;
952 0 : s->time->m = 1;
953 0 : s->time->d = 1;
954 0 : s->time->h = s->time->i = s->time->s = 0;
955 0 : s->time->f = 0.0;
956 0 : s->time->relative.s += i;
957 0 : s->time->is_localtime = 1;
958 0 : s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
959 0 : s->time->z = 0;
960 :
961 0 : TIMELIB_DEINIT;
962 0 : return TIMELIB_RELATIVE;
963 : }
964 :
965 : timetiny12 | timeshort12 | timelong12
966 : {
967 : DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
968 0 : TIMELIB_INIT;
969 0 : TIMELIB_HAVE_TIME();
970 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
971 0 : if (*ptr == ':' || *ptr == '.') {
972 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
973 0 : if (*ptr == ':' || *ptr == '.') {
974 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
975 : }
976 : }
977 0 : s->time->h += timelib_meridian((char **) &ptr, s->time->h);
978 0 : TIMELIB_DEINIT;
979 0 : return TIMELIB_TIME12;
980 : }
981 :
982 : timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
983 : {
984 : int tz_not_found;
985 : DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
986 1 : TIMELIB_INIT;
987 1 : TIMELIB_HAVE_TIME();
988 1 : s->time->h = timelib_get_nr((char **) &ptr, 2);
989 1 : s->time->i = timelib_get_nr((char **) &ptr, 2);
990 1 : if (*ptr == ':' || *ptr == '.') {
991 1 : s->time->s = timelib_get_nr((char **) &ptr, 2);
992 :
993 1 : if (*ptr == '.') {
994 0 : s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
995 : }
996 : }
997 :
998 1 : if (*ptr != '\0') {
999 0 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1000 0 : if (tz_not_found) {
1001 0 : add_error(s, "The timezone could not be found in the database");
1002 : }
1003 : }
1004 1 : TIMELIB_DEINIT;
1005 1 : return TIMELIB_TIME24_WITH_ZONE;
1006 : }
1007 :
1008 : gnunocolon
1009 : {
1010 : DEBUG_OUTPUT("gnunocolon");
1011 0 : TIMELIB_INIT;
1012 0 : switch (s->time->have_time) {
1013 : case 0:
1014 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1015 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1016 0 : s->time->s = 0;
1017 0 : break;
1018 : case 1:
1019 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1020 0 : break;
1021 : default:
1022 0 : TIMELIB_DEINIT;
1023 0 : add_error(s, "Double time specification");
1024 0 : return TIMELIB_ERROR;
1025 : }
1026 0 : s->time->have_time++;
1027 0 : TIMELIB_DEINIT;
1028 0 : return TIMELIB_GNU_NOCOLON;
1029 : }
1030 : /*
1031 : gnunocolontz
1032 : {
1033 : DEBUG_OUTPUT("gnunocolontz");
1034 : TIMELIB_INIT;
1035 : switch (s->time->have_time) {
1036 : case 0:
1037 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1038 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1039 : s->time->s = 0;
1040 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb);
1041 : break;
1042 : case 1:
1043 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1044 : break;
1045 : default:
1046 : TIMELIB_DEINIT;
1047 : return TIMELIB_ERROR;
1048 : }
1049 : s->time->have_time++;
1050 : TIMELIB_DEINIT;
1051 : return TIMELIB_GNU_NOCOLON_TZ;
1052 : }
1053 : */
1054 : iso8601nocolon /*| iso8601nocolontz*/
1055 : {
1056 : int tz_not_found;
1057 : DEBUG_OUTPUT("iso8601nocolon");
1058 0 : TIMELIB_INIT;
1059 0 : TIMELIB_HAVE_TIME();
1060 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1061 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1062 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
1063 :
1064 0 : if (*ptr != '\0') {
1065 0 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1066 0 : if (tz_not_found) {
1067 0 : add_error(s, "The timezone could not be found in the database");
1068 : }
1069 : }
1070 0 : TIMELIB_DEINIT;
1071 0 : return TIMELIB_ISO_NOCOLON;
1072 : }
1073 :
1074 : americanshort | american
1075 : {
1076 : DEBUG_OUTPUT("americanshort | american");
1077 0 : TIMELIB_INIT;
1078 0 : TIMELIB_HAVE_DATE();
1079 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1080 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1081 0 : if (*ptr == '/') {
1082 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1083 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1084 : }
1085 0 : TIMELIB_DEINIT;
1086 0 : return TIMELIB_AMERICAN;
1087 : }
1088 :
1089 : iso8601date | iso8601dateslash | dateslash
1090 : {
1091 : DEBUG_OUTPUT("iso8601date | iso8601dateslash | dateslash");
1092 0 : TIMELIB_INIT;
1093 0 : TIMELIB_HAVE_DATE();
1094 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1095 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1096 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1097 0 : TIMELIB_DEINIT;
1098 0 : return TIMELIB_ISO_DATE;
1099 : }
1100 :
1101 : gnudateshorter
1102 : {
1103 : DEBUG_OUTPUT("gnudateshorter");
1104 0 : TIMELIB_INIT;
1105 0 : TIMELIB_HAVE_DATE();
1106 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1107 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1108 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1109 0 : TIMELIB_DEINIT;
1110 0 : return TIMELIB_ISO_DATE;
1111 : }
1112 :
1113 : gnudateshort
1114 : {
1115 : DEBUG_OUTPUT("gnudateshort");
1116 0 : TIMELIB_INIT;
1117 0 : TIMELIB_HAVE_DATE();
1118 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1119 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1120 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1121 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1122 0 : TIMELIB_DEINIT;
1123 0 : return TIMELIB_ISO_DATE;
1124 : }
1125 :
1126 : datefull
1127 : {
1128 : DEBUG_OUTPUT("datefull");
1129 1 : TIMELIB_INIT;
1130 1 : TIMELIB_HAVE_DATE();
1131 1 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1132 1 : timelib_skip_day_suffix((char **) &ptr);
1133 1 : s->time->m = timelib_get_month((char **) &ptr);
1134 1 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1135 1 : TIMELIB_PROCESS_YEAR(s->time->y);
1136 1 : TIMELIB_DEINIT;
1137 1 : return TIMELIB_DATE_FULL;
1138 : }
1139 :
1140 : pointeddate
1141 : {
1142 : DEBUG_OUTPUT("pointed date");
1143 0 : TIMELIB_INIT;
1144 0 : TIMELIB_HAVE_DATE();
1145 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1146 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1147 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1148 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1149 0 : TIMELIB_DEINIT;
1150 0 : return TIMELIB_DATE_FULL_POINTED;
1151 : }
1152 :
1153 : datenoday
1154 : {
1155 : DEBUG_OUTPUT("datenoday");
1156 0 : TIMELIB_INIT;
1157 0 : TIMELIB_HAVE_DATE();
1158 0 : s->time->m = timelib_get_month((char **) &ptr);
1159 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1160 0 : s->time->d = 1;
1161 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1162 0 : TIMELIB_DEINIT;
1163 0 : return TIMELIB_DATE_NO_DAY;
1164 : }
1165 :
1166 : datenodayrev
1167 : {
1168 : DEBUG_OUTPUT("datenodayrev");
1169 0 : TIMELIB_INIT;
1170 0 : TIMELIB_HAVE_DATE();
1171 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1172 0 : s->time->m = timelib_get_month((char **) &ptr);
1173 0 : s->time->d = 1;
1174 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1175 0 : TIMELIB_DEINIT;
1176 0 : return TIMELIB_DATE_NO_DAY;
1177 : }
1178 :
1179 : datetextual | datenoyear
1180 : {
1181 : DEBUG_OUTPUT("datetextual | datenoyear");
1182 0 : TIMELIB_INIT;
1183 0 : TIMELIB_HAVE_DATE();
1184 0 : s->time->m = timelib_get_month((char **) &ptr);
1185 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1186 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1187 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1188 0 : TIMELIB_DEINIT;
1189 0 : return TIMELIB_DATE_TEXT;
1190 : }
1191 :
1192 : datenoyearrev
1193 : {
1194 : DEBUG_OUTPUT("datenoyearrev");
1195 0 : TIMELIB_INIT;
1196 0 : TIMELIB_HAVE_DATE();
1197 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1198 0 : timelib_skip_day_suffix((char **) &ptr);
1199 0 : s->time->m = timelib_get_month((char **) &ptr);
1200 0 : TIMELIB_DEINIT;
1201 0 : return TIMELIB_DATE_TEXT;
1202 : }
1203 :
1204 : datenocolon
1205 : {
1206 : DEBUG_OUTPUT("datenocolon");
1207 0 : TIMELIB_INIT;
1208 0 : TIMELIB_HAVE_DATE();
1209 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1210 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1211 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1212 0 : TIMELIB_DEINIT;
1213 0 : return TIMELIB_DATE_NOCOLON;
1214 : }
1215 :
1216 : xmlrpc | xmlrpcnocolon | soap | wddx | exif
1217 : {
1218 : int tz_not_found;
1219 : DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
1220 0 : TIMELIB_INIT;
1221 0 : TIMELIB_HAVE_TIME();
1222 0 : TIMELIB_HAVE_DATE();
1223 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1224 0 : s->time->m = timelib_get_nr((char **) &ptr, 2);
1225 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1226 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1227 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1228 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
1229 0 : if (*ptr == '.') {
1230 0 : s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
1231 0 : if (*ptr) { /* timezone is optional */
1232 0 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1233 0 : if (tz_not_found) {
1234 0 : add_error(s, "The timezone could not be found in the database");
1235 : }
1236 : }
1237 : }
1238 0 : TIMELIB_DEINIT;
1239 0 : return TIMELIB_XMLRPC_SOAP;
1240 : }
1241 :
1242 : pgydotd
1243 : {
1244 : DEBUG_OUTPUT("pgydotd");
1245 0 : TIMELIB_INIT;
1246 0 : TIMELIB_HAVE_DATE();
1247 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1248 0 : s->time->d = timelib_get_nr((char **) &ptr, 3);
1249 0 : s->time->m = 1;
1250 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1251 0 : TIMELIB_DEINIT;
1252 0 : return TIMELIB_PG_YEARDAY;
1253 : }
1254 :
1255 : isoweekday
1256 : {
1257 : timelib_sll w, d;
1258 : DEBUG_OUTPUT("isoweekday");
1259 0 : TIMELIB_INIT;
1260 0 : TIMELIB_HAVE_DATE();
1261 0 : TIMELIB_HAVE_RELATIVE();
1262 :
1263 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1264 0 : w = timelib_get_nr((char **) &ptr, 2);
1265 0 : d = timelib_get_nr((char **) &ptr, 1);
1266 0 : s->time->m = 1;
1267 0 : s->time->d = 1;
1268 0 : s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
1269 :
1270 0 : TIMELIB_DEINIT;
1271 0 : return TIMELIB_ISO_WEEK;
1272 : }
1273 :
1274 : isoweek
1275 : {
1276 : timelib_sll w, d;
1277 : DEBUG_OUTPUT("isoweek");
1278 0 : TIMELIB_INIT;
1279 0 : TIMELIB_HAVE_DATE();
1280 0 : TIMELIB_HAVE_RELATIVE();
1281 :
1282 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1283 0 : w = timelib_get_nr((char **) &ptr, 2);
1284 0 : d = 1;
1285 0 : s->time->m = 1;
1286 0 : s->time->d = 1;
1287 0 : s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
1288 :
1289 0 : TIMELIB_DEINIT;
1290 0 : return TIMELIB_ISO_WEEK;
1291 : }
1292 :
1293 : pgtextshort
1294 : {
1295 : DEBUG_OUTPUT("pgtextshort");
1296 0 : TIMELIB_INIT;
1297 0 : TIMELIB_HAVE_DATE();
1298 0 : s->time->m = timelib_get_month((char **) &ptr);
1299 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1300 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1301 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1302 0 : TIMELIB_DEINIT;
1303 0 : return TIMELIB_PG_TEXT;
1304 : }
1305 :
1306 : pgtextreverse
1307 : {
1308 : DEBUG_OUTPUT("pgtextreverse");
1309 0 : TIMELIB_INIT;
1310 0 : TIMELIB_HAVE_DATE();
1311 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1312 0 : s->time->m = timelib_get_month((char **) &ptr);
1313 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1314 0 : TIMELIB_PROCESS_YEAR(s->time->y);
1315 0 : TIMELIB_DEINIT;
1316 0 : return TIMELIB_PG_TEXT;
1317 : }
1318 :
1319 : clf
1320 : {
1321 : int tz_not_found;
1322 : DEBUG_OUTPUT("clf");
1323 0 : TIMELIB_INIT;
1324 0 : TIMELIB_HAVE_TIME();
1325 0 : TIMELIB_HAVE_DATE();
1326 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1327 0 : s->time->m = timelib_get_month((char **) &ptr);
1328 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1329 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1330 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1331 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
1332 0 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1333 0 : if (tz_not_found) {
1334 0 : add_error(s, "The timezone could not be found in the database");
1335 : }
1336 0 : TIMELIB_DEINIT;
1337 0 : return TIMELIB_CLF;
1338 : }
1339 :
1340 : year4
1341 : {
1342 : DEBUG_OUTPUT("year4");
1343 0 : TIMELIB_INIT;
1344 0 : s->time->y = timelib_get_nr((char **) &ptr, 4);
1345 0 : TIMELIB_DEINIT;
1346 0 : return TIMELIB_CLF;
1347 : }
1348 :
1349 : ago
1350 : {
1351 : DEBUG_OUTPUT("ago");
1352 0 : TIMELIB_INIT;
1353 0 : s->time->relative.y = 0 - s->time->relative.y;
1354 0 : s->time->relative.m = 0 - s->time->relative.m;
1355 0 : s->time->relative.d = 0 - s->time->relative.d;
1356 0 : s->time->relative.h = 0 - s->time->relative.h;
1357 0 : s->time->relative.i = 0 - s->time->relative.i;
1358 0 : s->time->relative.s = 0 - s->time->relative.s;
1359 0 : s->time->relative.weekday = 0 - s->time->relative.weekday;
1360 0 : if (s->time->have_special_relative && s->time->special.type == TIMELIB_SPECIAL_WEEKDAY) {
1361 0 : s->time->special.amount = 0 - s->time->special.amount;
1362 : }
1363 0 : TIMELIB_DEINIT;
1364 0 : return TIMELIB_AGO;
1365 : }
1366 :
1367 : daytext
1368 : {
1369 : const timelib_relunit* relunit;
1370 : DEBUG_OUTPUT("daytext");
1371 1 : TIMELIB_INIT;
1372 1 : TIMELIB_HAVE_RELATIVE();
1373 1 : TIMELIB_HAVE_WEEKDAY_RELATIVE();
1374 1 : TIMELIB_UNHAVE_TIME();
1375 1 : relunit = timelib_lookup_relunit((char**) &ptr);
1376 1 : s->time->relative.weekday = relunit->multiplier;
1377 1 : s->time->relative.weekday_behavior = 1;
1378 :
1379 1 : TIMELIB_DEINIT;
1380 1 : return TIMELIB_WEEKDAY;
1381 : }
1382 :
1383 : relativetext
1384 : {
1385 : timelib_sll i;
1386 0 : int behavior = 0;
1387 : DEBUG_OUTPUT("relativetext");
1388 0 : TIMELIB_INIT;
1389 0 : TIMELIB_HAVE_RELATIVE();
1390 :
1391 0 : while(*ptr) {
1392 0 : i = timelib_get_relative_text((char **) &ptr, &behavior);
1393 0 : timelib_eat_spaces((char **) &ptr);
1394 0 : timelib_set_relative((char **) &ptr, i, behavior, s);
1395 : }
1396 0 : TIMELIB_DEINIT;
1397 0 : return TIMELIB_RELATIVE;
1398 : }
1399 :
1400 : monthfull | monthabbr
1401 : {
1402 : DEBUG_OUTPUT("monthtext");
1403 0 : TIMELIB_INIT;
1404 0 : TIMELIB_HAVE_DATE();
1405 0 : s->time->m = timelib_lookup_month((char **) &ptr);
1406 0 : TIMELIB_DEINIT;
1407 0 : return TIMELIB_DATE_TEXT;
1408 : }
1409 :
1410 : tzcorrection | tz
1411 : {
1412 : int tz_not_found;
1413 : DEBUG_OUTPUT("tzcorrection | tz");
1414 1 : TIMELIB_INIT;
1415 1 : TIMELIB_HAVE_TZ();
1416 1 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1417 1 : if (tz_not_found) {
1418 0 : add_error(s, "The timezone could not be found in the database");
1419 : }
1420 1 : TIMELIB_DEINIT;
1421 1 : return TIMELIB_TIMEZONE;
1422 : }
1423 :
1424 : dateshortwithtimeshort12 | dateshortwithtimelong12
1425 : {
1426 : DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
1427 0 : TIMELIB_INIT;
1428 0 : TIMELIB_HAVE_DATE();
1429 0 : s->time->m = timelib_get_month((char **) &ptr);
1430 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1431 :
1432 0 : TIMELIB_HAVE_TIME();
1433 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1434 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1435 0 : if (*ptr == ':' || *ptr == '.') {
1436 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
1437 :
1438 0 : if (*ptr == '.') {
1439 0 : s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
1440 : }
1441 : }
1442 :
1443 0 : s->time->h += timelib_meridian((char **) &ptr, s->time->h);
1444 0 : TIMELIB_DEINIT;
1445 0 : return TIMELIB_SHORTDATE_WITH_TIME;
1446 : }
1447 :
1448 : dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
1449 : {
1450 : int tz_not_found;
1451 : DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
1452 0 : TIMELIB_INIT;
1453 0 : TIMELIB_HAVE_DATE();
1454 0 : s->time->m = timelib_get_month((char **) &ptr);
1455 0 : s->time->d = timelib_get_nr((char **) &ptr, 2);
1456 :
1457 0 : TIMELIB_HAVE_TIME();
1458 0 : s->time->h = timelib_get_nr((char **) &ptr, 2);
1459 0 : s->time->i = timelib_get_nr((char **) &ptr, 2);
1460 0 : if (*ptr == ':') {
1461 0 : s->time->s = timelib_get_nr((char **) &ptr, 2);
1462 :
1463 0 : if (*ptr == '.') {
1464 0 : s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
1465 : }
1466 : }
1467 :
1468 0 : if (*ptr != '\0') {
1469 0 : s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
1470 0 : if (tz_not_found) {
1471 0 : add_error(s, "The timezone could not be found in the database");
1472 : }
1473 : }
1474 0 : TIMELIB_DEINIT;
1475 0 : return TIMELIB_SHORTDATE_WITH_TIME;
1476 : }
1477 :
1478 : relative
1479 : {
1480 : timelib_ull i;
1481 : DEBUG_OUTPUT("relative");
1482 0 : TIMELIB_INIT;
1483 0 : TIMELIB_HAVE_RELATIVE();
1484 :
1485 0 : while(*ptr) {
1486 0 : i = timelib_get_unsigned_nr((char **) &ptr, 24);
1487 0 : timelib_eat_spaces((char **) &ptr);
1488 0 : timelib_set_relative((char **) &ptr, i, 0, s);
1489 : }
1490 0 : TIMELIB_DEINIT;
1491 0 : return TIMELIB_RELATIVE;
1492 : }
1493 :
1494 : [ .,\t]
1495 : {
1496 4 : goto std;
1497 : }
1498 :
1499 : "\000"|"\n"
1500 : {
1501 1 : s->pos = cursor; s->line++;
1502 1 : goto std;
1503 : }
1504 :
1505 : any
1506 : {
1507 0 : add_error(s, "Unexpected character");
1508 0 : goto std;
1509 : }
1510 : */
1511 : }
1512 :
1513 : /*!max:re2c */
1514 :
1515 : timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb)
1516 1 : {
1517 : Scanner in;
1518 : int t;
1519 1 : char *e = s + len - 1;
1520 :
1521 1 : memset(&in, 0, sizeof(in));
1522 1 : in.errors = malloc(sizeof(struct timelib_error_container));
1523 1 : in.errors->warning_count = 0;
1524 1 : in.errors->warning_messages = NULL;
1525 1 : in.errors->error_count = 0;
1526 1 : in.errors->error_messages = NULL;
1527 :
1528 1 : if (len > 0) {
1529 2 : while (isspace(*s) && s < e) {
1530 0 : s++;
1531 : }
1532 2 : while (isspace(*e) && e > s) {
1533 0 : e--;
1534 : }
1535 : }
1536 1 : if (e - s < 1) {
1537 0 : in.time = timelib_time_ctor();
1538 0 : add_error(&in, "Empty string");
1539 0 : if (errors) {
1540 0 : *errors = in.errors;
1541 : } else {
1542 0 : timelib_error_container_dtor(in.errors);
1543 : }
1544 0 : in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->z = in.time->dst = -1;
1545 0 : in.time->is_localtime = in.time->zone_type = 0;
1546 0 : return in.time;
1547 : }
1548 1 : e++;
1549 :
1550 1 : in.str = malloc((e - s) + YYMAXFILL);
1551 1 : memset(in.str, 0, (e - s) + YYMAXFILL);
1552 1 : memcpy(in.str, s, (e - s));
1553 1 : in.lim = in.str + (e - s) + YYMAXFILL;
1554 1 : in.cur = in.str;
1555 1 : in.time = timelib_time_ctor();
1556 1 : in.time->y = -1;
1557 1 : in.time->d = -1;
1558 1 : in.time->m = -1;
1559 1 : in.time->h = -1;
1560 1 : in.time->i = -1;
1561 1 : in.time->s = -1;
1562 1 : in.time->f = -1;
1563 1 : in.time->z = -1;
1564 1 : in.time->dst = -1;
1565 1 : in.tzdb = tzdb;
1566 1 : in.time->is_localtime = 0;
1567 1 : in.time->zone_type = 0;
1568 :
1569 : do {
1570 5 : t = scan(&in);
1571 : #ifdef DEBUG_PARSER
1572 : printf("%d\n", t);
1573 : #endif
1574 5 : } while(t != EOI);
1575 :
1576 1 : free(in.str);
1577 1 : if (errors) {
1578 1 : *errors = in.errors;
1579 : } else {
1580 0 : timelib_error_container_dtor(in.errors);
1581 : }
1582 1 : return in.time;
1583 : }
1584 :
1585 : void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
1586 1 : {
1587 1 : if (!(options && TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
1588 0 : parsed->h = 0;
1589 0 : parsed->i = 0;
1590 0 : parsed->s = 0;
1591 0 : parsed->f = 0;
1592 : }
1593 1 : if (parsed->y == -1) parsed->y = now->y != -1 ? now->y : 0;
1594 1 : if (parsed->d == -1) parsed->d = now->d != -1 ? now->d : 0;
1595 1 : if (parsed->m == -1) parsed->m = now->m != -1 ? now->m : 0;
1596 1 : if (parsed->h == -1) parsed->h = now->h != -1 ? now->h : 0;
1597 1 : if (parsed->i == -1) parsed->i = now->i != -1 ? now->i : 0;
1598 1 : if (parsed->s == -1) parsed->s = now->s != -1 ? now->s : 0;
1599 1 : if (parsed->f == -1) parsed->f = now->f != -1 ? now->f : 0;
1600 1 : if (parsed->z == -1) parsed->z = now->z != -1 ? now->z : 0;
1601 1 : if (parsed->dst == -1) parsed->dst = now->dst != -1 ? now->dst : 0;
1602 :
1603 1 : if (!parsed->tz_abbr) {
1604 0 : parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
1605 : }
1606 1 : if (!parsed->tz_info) {
1607 1 : parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
1608 : }
1609 1 : if (parsed->zone_type == 0 && now->zone_type != 0) {
1610 0 : parsed->zone_type = now->zone_type;
1611 : /* parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
1612 : parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
1613 0 : */ parsed->is_localtime = 1;
1614 : }
1615 : /* timelib_dump_date(parsed, 2);
1616 : timelib_dump_date(now, 2);
1617 : */
1618 1 : }
1619 :
1620 : char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst)
1621 1 : {
1622 : const timelib_tz_lookup_table *tp;
1623 :
1624 1 : tp = zone_search(abbr, gmtoffset, isdst);
1625 1 : if (tp) {
1626 1 : return (tp->full_tz_name);
1627 : } else {
1628 0 : return NULL;
1629 : }
1630 : }
1631 :
1632 : const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
1633 0 : {
1634 0 : return timelib_timezone_lookup;
1635 : }
1636 :
1637 : #ifdef DEBUG_PARSER_STUB
1638 : int main(void)
1639 : {
1640 : timelib_time time = timelib_strtotime("May 12");
1641 :
1642 : printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
1643 : time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
1644 : if (time.have_relative) {
1645 : printf ("%3dY %3dM %3dD / %3dH %3dM %3dS",
1646 : time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
1647 : }
1648 : if (time.have_weekday_relative) {
1649 : printf (" / %d", time.relative.weekday);
1650 : }
1651 : if (time.have_weeknr_day) {
1652 : printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
1653 : }
1654 : return 0;
1655 : }
1656 : #endif
1657 :
1658 : /*
1659 : * vim: syntax=c
1660 : */
|