PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - lcov_data/ext/date/lib - parse_date.re (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 906 1032 87.8 %
Date: 2014-04-19 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2013 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$ */
      20             : 
      21             : #include "timelib.h"
      22             : 
      23             : #include <stdio.h>
      24             : #include <ctype.h>
      25             : #include <math.h>
      26             : #include <assert.h>
      27             : 
      28             : #ifdef HAVE_STDLIB_H
      29             : #include <stdlib.h>
      30             : #endif
      31             : #ifdef HAVE_STRING_H
      32             : #include <string.h>
      33             : #else
      34             : #include <strings.h>
      35             : #endif
      36             : 
      37             : #if defined(_MSC_VER)
      38             : # define strtoll(s, f, b) _atoi64(s)
      39             : #elif !defined(HAVE_STRTOLL)
      40             : # if defined(HAVE_ATOLL)
      41             : #  define strtoll(s, f, b) atoll(s)
      42             : # else
      43             : #  define strtoll(s, f, b) strtol(s, f, b)
      44             : # endif
      45             : #endif
      46             : 
      47             : #define TIMELIB_UNSET   -99999
      48             : 
      49             : #define TIMELIB_SECOND  1
      50             : #define TIMELIB_MINUTE  2
      51             : #define TIMELIB_HOUR    3
      52             : #define TIMELIB_DAY     4
      53             : #define TIMELIB_MONTH   5
      54             : #define TIMELIB_YEAR    6
      55             : #define TIMELIB_WEEKDAY 7
      56             : #define TIMELIB_SPECIAL 8
      57             : 
      58             : #define EOI      257
      59             : #define TIME     258
      60             : #define DATE     259
      61             : 
      62             : #define TIMELIB_XMLRPC_SOAP    260
      63             : #define TIMELIB_TIME12         261
      64             : #define TIMELIB_TIME24         262
      65             : #define TIMELIB_GNU_NOCOLON    263
      66             : #define TIMELIB_GNU_NOCOLON_TZ 264
      67             : #define TIMELIB_ISO_NOCOLON    265
      68             : 
      69             : #define TIMELIB_AMERICAN       266
      70             : #define TIMELIB_ISO_DATE       267
      71             : #define TIMELIB_DATE_FULL      268
      72             : #define TIMELIB_DATE_TEXT      269
      73             : #define TIMELIB_DATE_NOCOLON   270
      74             : #define TIMELIB_PG_YEARDAY     271
      75             : #define TIMELIB_PG_TEXT        272
      76             : #define TIMELIB_PG_REVERSE     273
      77             : #define TIMELIB_CLF            274
      78             : #define TIMELIB_DATE_NO_DAY    275
      79             : #define TIMELIB_SHORTDATE_WITH_TIME 276
      80             : #define TIMELIB_DATE_FULL_POINTED 277
      81             : #define TIMELIB_TIME24_WITH_ZONE 278
      82             : #define TIMELIB_ISO_WEEK       279
      83             : #define TIMELIB_LF_DAY_OF_MONTH 280
      84             : #define TIMELIB_WEEK_DAY_OF_MONTH 281
      85             : 
      86             : #define TIMELIB_TIMEZONE       300
      87             : #define TIMELIB_AGO            301
      88             : 
      89             : #define TIMELIB_RELATIVE       310
      90             : 
      91             : #define TIMELIB_ERROR          999
      92             : 
      93             : /* Some compilers like AIX, defines uchar in sys/types.h */
      94             : #undef uchar
      95             : typedef unsigned char uchar;
      96             : 
      97             : #define   BSIZE    8192
      98             : 
      99             : #define   YYCTYPE      uchar
     100             : #define   YYCURSOR     cursor
     101             : #define   YYLIMIT      s->lim
     102             : #define   YYMARKER     s->ptr
     103             : #define   YYFILL(n)    return EOI;
     104             : 
     105             : #define   RET(i)       {s->cur = cursor; return i;}
     106             : 
     107             : #define timelib_string_free free
     108             : 
     109             : #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; } }
     110             : #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; }
     111             : #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; } }
     112             : #define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
     113             : #define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; }
     114             : #define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_weekday_relative = 1; }
     115             : #define TIMELIB_HAVE_SPECIAL_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_special_relative = 1; }
     116             : #define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { s->time->have_zone > 1 ? add_error(s, "Double timezone specification") : add_warning(s, "Double timezone specification"); timelib_string_free(str); s->time->have_zone++; return TIMELIB_ERROR; } else { s->time->have_zone++; } }
     117             : 
     118             : #define TIMELIB_INIT  s->cur = cursor; str = timelib_string(s); ptr = str
     119             : #define TIMELIB_DEINIT timelib_string_free(str)
     120             : #define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
     121             : 
     122             : #define TIMELIB_PROCESS_YEAR(x, l) { \
     123             :         if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
     124             :         /*      (x) = 0; */          \
     125             :         } else if ((x) < 100) {  \
     126             :                 if ((x) < 70) {      \
     127             :                         (x) += 2000;     \
     128             :                 } else {             \
     129             :                         (x) += 1900;     \
     130             :                 }                    \
     131             :         }                        \
     132             : }
     133             : 
     134             : #ifdef DEBUG_PARSER
     135             : #define DEBUG_OUTPUT(s) printf("%s\n", s);
     136             : #define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
     137             : #else
     138             : #define DEBUG_OUTPUT(s)
     139             : #define YYDEBUG(s,c)
     140             : #endif
     141             : 
     142             : #include "timelib_structs.h"
     143             : 
     144             : typedef struct timelib_elems {
     145             :         unsigned int   c; /* Number of elements */
     146             :         char         **v; /* Values */
     147             : } timelib_elems;
     148             : 
     149             : typedef struct Scanner {
     150             :         int           fd;
     151             :         uchar        *lim, *str, *ptr, *cur, *tok, *pos;
     152             :         unsigned int  line, len;
     153             :         struct timelib_error_container *errors;
     154             : 
     155             :         struct timelib_time *time;
     156             :         const timelib_tzdb  *tzdb;
     157             : } Scanner;
     158             : 
     159             : typedef struct _timelib_lookup_table {
     160             :     const char *name;
     161             :     int         type;
     162             :     int         value;
     163             : } timelib_lookup_table;
     164             : 
     165             : typedef struct _timelib_relunit {
     166             :         const char *name;
     167             :         int         unit;
     168             :         int         multiplier;
     169             : } timelib_relunit;
     170             : 
     171             : #define HOUR(a) (int)(a * 60)
     172             : 
     173             : /* The timezone table. */
     174             : const static timelib_tz_lookup_table timelib_timezone_lookup[] = {
     175             : #include "timezonemap.h"
     176             :         { NULL, 0, 0, NULL },
     177             : };
     178             : 
     179             : const static timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
     180             : #include "fallbackmap.h"
     181             :         { NULL, 0, 0, NULL },
     182             : };
     183             : 
     184             : const static timelib_tz_lookup_table timelib_timezone_utc[] = {
     185             :         { "utc", 0, 0, "UTC" },
     186             : };
     187             : 
     188             : static timelib_relunit const timelib_relunit_lookup[] = {
     189             :         { "sec",         TIMELIB_SECOND,  1 },
     190             :         { "secs",        TIMELIB_SECOND,  1 },
     191             :         { "second",      TIMELIB_SECOND,  1 },
     192             :         { "seconds",     TIMELIB_SECOND,  1 },
     193             :         { "min",         TIMELIB_MINUTE,  1 },
     194             :         { "mins",        TIMELIB_MINUTE,  1 },
     195             :         { "minute",      TIMELIB_MINUTE,  1 },
     196             :         { "minutes",     TIMELIB_MINUTE,  1 },
     197             :         { "hour",        TIMELIB_HOUR,    1 },
     198             :         { "hours",       TIMELIB_HOUR,    1 },
     199             :         { "day",         TIMELIB_DAY,     1 },
     200             :         { "days",        TIMELIB_DAY,     1 },
     201             :         { "week",        TIMELIB_DAY,     7 },
     202             :         { "weeks",       TIMELIB_DAY,     7 },
     203             :         { "fortnight",   TIMELIB_DAY,    14 },
     204             :         { "fortnights",  TIMELIB_DAY,    14 },
     205             :         { "forthnight",  TIMELIB_DAY,    14 },
     206             :         { "forthnights", TIMELIB_DAY,    14 },
     207             :         { "month",       TIMELIB_MONTH,   1 },
     208             :         { "months",      TIMELIB_MONTH,   1 },
     209             :         { "year",        TIMELIB_YEAR,    1 },
     210             :         { "years",       TIMELIB_YEAR,    1 },
     211             : 
     212             :         { "monday",      TIMELIB_WEEKDAY, 1 },
     213             :         { "mon",         TIMELIB_WEEKDAY, 1 },
     214             :         { "tuesday",     TIMELIB_WEEKDAY, 2 },
     215             :         { "tue",         TIMELIB_WEEKDAY, 2 },
     216             :         { "wednesday",   TIMELIB_WEEKDAY, 3 },
     217             :         { "wed",         TIMELIB_WEEKDAY, 3 },
     218             :         { "thursday",    TIMELIB_WEEKDAY, 4 },
     219             :         { "thu",         TIMELIB_WEEKDAY, 4 },
     220             :         { "friday",      TIMELIB_WEEKDAY, 5 },
     221             :         { "fri",         TIMELIB_WEEKDAY, 5 },
     222             :         { "saturday",    TIMELIB_WEEKDAY, 6 },
     223             :         { "sat",         TIMELIB_WEEKDAY, 6 },
     224             :         { "sunday",      TIMELIB_WEEKDAY, 0 },
     225             :         { "sun",         TIMELIB_WEEKDAY, 0 },
     226             : 
     227             :         { "weekday",     TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
     228             :         { "weekdays",    TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
     229             :         { NULL,          0,          0 }
     230             : };
     231             : 
     232             : /* The relative text table. */
     233             : static timelib_lookup_table const timelib_reltext_lookup[] = {
     234             :         { "first",    0,  1 },
     235             :         { "next",     0,  1 },
     236             :         { "second",   0,  2 },
     237             :         { "third",    0,  3 },
     238             :         { "fourth",   0,  4 },
     239             :         { "fifth",    0,  5 },
     240             :         { "sixth",    0,  6 },
     241             :         { "seventh",  0,  7 },
     242             :         { "eight",    0,  8 },
     243             :         { "eighth",   0,  8 },
     244             :         { "ninth",    0,  9 },
     245             :         { "tenth",    0, 10 },
     246             :         { "eleventh", 0, 11 },
     247             :         { "twelfth",  0, 12 },
     248             :         { "last",     0, -1 },
     249             :         { "previous", 0, -1 },
     250             :         { "this",     1,  0 },
     251             :         { NULL,       1,  0 }
     252             : };
     253             : 
     254             : /* The month table. */
     255             : static timelib_lookup_table const timelib_month_lookup[] = {
     256             :         { "jan",  0,  1 },
     257             :         { "feb",  0,  2 },
     258             :         { "mar",  0,  3 },
     259             :         { "apr",  0,  4 },
     260             :         { "may",  0,  5 },
     261             :         { "jun",  0,  6 },
     262             :         { "jul",  0,  7 },
     263             :         { "aug",  0,  8 },
     264             :         { "sep",  0,  9 },
     265             :         { "sept", 0,  9 },
     266             :         { "oct",  0, 10 },
     267             :         { "nov",  0, 11 },
     268             :         { "dec",  0, 12 },
     269             :         { "i",    0,  1 },
     270             :         { "ii",   0,  2 },
     271             :         { "iii",  0,  3 },
     272             :         { "iv",   0,  4 },
     273             :         { "v",    0,  5 },
     274             :         { "vi",   0,  6 },
     275             :         { "vii",  0,  7 },
     276             :         { "viii", 0,  8 },
     277             :         { "ix",   0,  9 },
     278             :         { "x",    0, 10 },
     279             :         { "xi",   0, 11 },
     280             :         { "xii",  0, 12 },
     281             : 
     282             :         { "january",   0,  1 },
     283             :         { "february",  0,  2 },
     284             :         { "march",     0,  3 },
     285             :         { "april",     0,  4 },
     286             :         { "may",       0,  5 },
     287             :         { "june",      0,  6 },
     288             :         { "july",      0,  7 },
     289             :         { "august",    0,  8 },
     290             :         { "september", 0,  9 },
     291             :         { "october",   0, 10 },
     292             :         { "november",  0, 11 },
     293             :         { "december",  0, 12 },
     294             :         {  NULL,       0,  0 }
     295             : };
     296             : 
     297             : #if 0
     298             : static char* timelib_ltrim(char *s)
     299             : {
     300             :         char *ptr = s;
     301             :         while (ptr[0] == ' ' || ptr[0] == '\t') {
     302             :                 ptr++;
     303             :         }
     304             :         return ptr;
     305             : }
     306             : #endif
     307             : 
     308             : #if 0
     309             : uchar *fill(Scanner *s, uchar *cursor){
     310             :         if(!s->eof){
     311             :                 unsigned int cnt = s->tok - s->bot;
     312             :                 if(cnt){
     313             :                         memcpy(s->bot, s->tok, s->lim - s->tok);
     314             :                         s->tok = s->bot;
     315             :                         s->ptr -= cnt;
     316             :                         cursor -= cnt;
     317             :                         s->pos -= cnt;
     318             :                         s->lim -= cnt;
     319             :                 }
     320             :                 if((s->top - s->lim) < BSIZE){
     321             :                         uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
     322             :                         memcpy(buf, s->tok, s->lim - s->tok);
     323             :                         s->tok = buf;
     324             :                         s->ptr = &buf[s->ptr - s->bot];
     325             :                         cursor = &buf[cursor - s->bot];
     326             :                         s->pos = &buf[s->pos - s->bot];
     327             :                         s->lim = &buf[s->lim - s->bot];
     328             :                         s->top = &s->lim[BSIZE];
     329             :                         free(s->bot);
     330             :                         s->bot = buf;
     331             :                 }
     332             :                 if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
     333             :                         s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
     334             :                 }
     335             :                 s->lim += cnt;
     336             :         }
     337             :         return cursor;
     338             : }
     339             : #endif
     340             : 
     341         230 : static void add_warning(Scanner *s, char *error)
     342             : {
     343         230 :         s->errors->warning_count++;
     344         230 :         s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
     345         230 :         s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
     346         230 :         s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
     347         230 :         s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
     348         230 : }
     349             : 
     350         178 : static void add_error(Scanner *s, char *error)
     351             : {
     352         178 :         s->errors->error_count++;
     353         178 :         s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
     354         178 :         s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
     355         178 :         s->errors->error_messages[s->errors->error_count - 1].character = s->tok ? *s->tok : 0;
     356         178 :         s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
     357         178 : }
     358             : 
     359           8 : static void add_pbf_warning(Scanner *s, char *error, char *sptr, char *cptr)
     360             : {
     361           8 :         s->errors->warning_count++;
     362           8 :         s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
     363           8 :         s->errors->warning_messages[s->errors->warning_count - 1].position = cptr - sptr;
     364           8 :         s->errors->warning_messages[s->errors->warning_count - 1].character = *cptr;
     365           8 :         s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
     366           8 : }
     367             : 
     368          10 : static void add_pbf_error(Scanner *s, char *error, char *sptr, char *cptr)
     369             : {
     370          10 :         s->errors->error_count++;
     371          10 :         s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
     372          10 :         s->errors->error_messages[s->errors->error_count - 1].position = cptr - sptr;
     373          10 :         s->errors->error_messages[s->errors->error_count - 1].character = *cptr;
     374          10 :         s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
     375          10 : }
     376             : 
     377          27 : static timelib_sll timelib_meridian(char **ptr, timelib_sll h)
     378             : {
     379          27 :         timelib_sll retval = 0;
     380             : 
     381          62 :         while (!strchr("AaPp", **ptr)) {
     382           8 :                 ++*ptr;
     383             :         }
     384          45 :         if (**ptr == 'a' || **ptr == 'A') {
     385          18 :                 if (h == 12) {
     386           4 :                         retval = -12;
     387             :                 }
     388           9 :         } else if (h != 12) {
     389           9 :                 retval = 12;
     390             :         }
     391          27 :         ++*ptr;
     392          27 :         if (**ptr == '.') {
     393           6 :                 *ptr += 3;
     394             :         } else {
     395          21 :                 ++*ptr;
     396             :         }
     397          27 :         return retval;
     398             : }
     399             : 
     400           1 : static timelib_sll timelib_meridian_with_check(char **ptr, timelib_sll h)
     401             : {
     402           1 :         timelib_sll retval = 0;
     403             : 
     404           2 :         while (!strchr("AaPp", **ptr)) {
     405           0 :                 ++*ptr;
     406             :         }
     407           1 :         if (**ptr == 'a' || **ptr == 'A') {
     408           0 :                 if (h == 12) {
     409           0 :                         retval = -12;
     410             :                 }
     411           1 :         } else if (h != 12) {
     412           1 :                 retval = 12;
     413             :         }
     414           1 :         ++*ptr;
     415           1 :         if (**ptr == '.') {
     416           0 :                 ++*ptr;
     417           0 :                 if (**ptr != 'm' && **ptr != 'M') {
     418           0 :                         return TIMELIB_UNSET;
     419             :                 }
     420           0 :                 ++*ptr;
     421           0 :                 if (**ptr != '.' ) {
     422           0 :                         return TIMELIB_UNSET;
     423             :                 }
     424           0 :                 ++*ptr;
     425           2 :         } else if (**ptr == 'm' || **ptr == 'M') {
     426           1 :                 ++*ptr;
     427             :         } else {
     428           0 :                 return TIMELIB_UNSET;
     429             :         }
     430           1 :         return retval;
     431             : }
     432             : 
     433       16134 : static char *timelib_string(Scanner *s)
     434             : {
     435       16134 :         char *tmp = calloc(1, s->cur - s->tok + 1);
     436       16134 :         memcpy(tmp, s->tok, s->cur - s->tok);
     437             : 
     438       16134 :         return tmp;
     439             : }
     440             : 
     441       32620 : static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int *scanned_length)
     442             : {
     443             :         char *begin, *end, *str;
     444       32620 :         timelib_sll tmp_nr = TIMELIB_UNSET;
     445       32620 :         int len = 0;
     446             : 
     447       85532 :         while ((**ptr < '0') || (**ptr > '9')) {
     448       20298 :                 if (**ptr == '\0') {
     449           6 :                         return TIMELIB_UNSET;
     450             :                 }
     451       20292 :                 ++*ptr;
     452             :         }
     453       32614 :         begin = *ptr;
     454      147072 :         while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
     455       81844 :                 ++*ptr;
     456       81844 :                 ++len;
     457             :         }
     458       32614 :         end = *ptr;
     459       32614 :         if (scanned_length) {
     460        1242 :                 *scanned_length = end - begin;
     461             :         }
     462       32614 :         str = calloc(1, end - begin + 1);
     463       32614 :         memcpy(str, begin, end - begin);
     464       32614 :         tmp_nr = strtoll(str, NULL, 10);
     465       32614 :         free(str);
     466       32614 :         return tmp_nr;
     467             : }
     468             : 
     469       31374 : static timelib_sll timelib_get_nr(char **ptr, int max_length)
     470             : {
     471       31374 :         return timelib_get_nr_ex(ptr, max_length, NULL);
     472             : }
     473             : 
     474          86 : static void timelib_skip_day_suffix(char **ptr)
     475             : {
     476          86 :         if (isspace(**ptr)) {
     477          77 :                 return;
     478             :         }
     479           9 :         if (!strncasecmp(*ptr, "nd", 2) || !strncasecmp(*ptr, "rd", 2) ||!strncasecmp(*ptr, "st", 2) || !strncasecmp(*ptr, "th", 2)) {
     480           2 :                 *ptr += 2;
     481             :         }
     482             : }
     483             : 
     484          20 : static double timelib_get_frac_nr(char **ptr, int max_length)
     485             : {
     486             :         char *begin, *end, *str;
     487          20 :         double tmp_nr = TIMELIB_UNSET;
     488          20 :         int len = 0;
     489             : 
     490          40 :         while ((**ptr != '.') && (**ptr != ':') && ((**ptr < '0') || (**ptr > '9'))) {
     491           0 :                 if (**ptr == '\0') {
     492           0 :                         return TIMELIB_UNSET;
     493             :                 }
     494           0 :                 ++*ptr;
     495             :         }
     496          20 :         begin = *ptr;
     497         154 :         while (((**ptr == '.') || (**ptr == ':') || ((**ptr >= '0') && (**ptr <= '9'))) && len < max_length) {
     498         114 :                 ++*ptr;
     499         114 :                 ++len;
     500             :         }
     501          20 :         end = *ptr;
     502          20 :         str = calloc(1, end - begin + 1);
     503          20 :         memcpy(str, begin, end - begin);
     504          20 :         if (str[0] == ':') {
     505           0 :                 str[0] = '.';
     506             :         }
     507          20 :         tmp_nr = strtod(str, NULL);
     508          20 :         free(str);
     509          20 :         return tmp_nr;
     510             : }
     511             : 
     512        5526 : static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
     513             : {
     514        5526 :         timelib_ull dir = 1;
     515             : 
     516       11281 :         while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
     517         229 :                 if (**ptr == '\0') {
     518           0 :                         return TIMELIB_UNSET;
     519             :                 }
     520         229 :                 ++*ptr;
     521             :         }
     522             : 
     523       11313 :         while (**ptr == '+' || **ptr == '-')
     524             :         {
     525         261 :                 if (**ptr == '-') {
     526          84 :                         dir *= -1;
     527             :                 }
     528         261 :                 ++*ptr;
     529             :         }
     530        5526 :         return dir * timelib_get_nr(ptr, max_length);
     531             : }
     532             : 
     533         214 : static long timelib_parse_tz_cor(char **ptr)
     534             : {
     535         214 :         char *begin = *ptr, *end;
     536             :         long  tmp;
     537             : 
     538        1263 :         while (isdigit(**ptr) || **ptr == ':') {
     539         835 :                 ++*ptr;
     540             :         }
     541         214 :         end = *ptr;
     542         214 :         switch (end - begin) {
     543             :                 case 1:
     544             :                 case 2:
     545          28 :                         return HOUR(strtol(begin, NULL, 10));
     546             :                         break;
     547             :                 case 3:
     548             :                 case 4:
     549         144 :                         if (begin[1] == ':') {
     550           1 :                                 tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
     551           1 :                                 return tmp;
     552         143 :                         } else if (begin[2] == ':') {
     553           0 :                                 tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
     554           0 :                                 return tmp;
     555             :                         } else {
     556         143 :                                 tmp = strtol(begin, NULL, 10);
     557         143 :                                 return HOUR(tmp / 100) + tmp % 100;
     558             :                         }
     559             :                 case 5:
     560          42 :                         tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
     561          42 :                         return tmp;
     562             :         }
     563           0 :         return 0;
     564             : }
     565             : 
     566         134 : static timelib_sll timelib_lookup_relative_text(char **ptr, int *behavior)
     567             : {
     568             :         char *word;
     569         134 :         char *begin = *ptr, *end;
     570         134 :         timelib_sll  value = 0;
     571             :         const timelib_lookup_table *tp;
     572             : 
     573         851 :         while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
     574         583 :                 ++*ptr;
     575             :         }
     576         134 :         end = *ptr;
     577         134 :         word = calloc(1, end - begin + 1);
     578         134 :         memcpy(word, begin, end - begin);
     579             : 
     580        2412 :         for (tp = timelib_reltext_lookup; tp->name; tp++) {
     581        2278 :                 if (strcasecmp(word, tp->name) == 0) {
     582         134 :                         value = tp->value;
     583         134 :                         *behavior = tp->type;
     584             :                 }
     585             :         }
     586             : 
     587         134 :         free(word);
     588         134 :         return value;
     589             : }
     590             : 
     591         134 : static timelib_sll timelib_get_relative_text(char **ptr, int *behavior)
     592             : {
     593         268 :         while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '/') {
     594           0 :                 ++*ptr;
     595             :         }
     596         134 :         return timelib_lookup_relative_text(ptr, behavior);
     597             : }
     598             : 
     599         179 : static long timelib_lookup_month(char **ptr)
     600             : {
     601             :         char *word;
     602         179 :         char *begin = *ptr, *end;
     603         179 :         long  value = 0;
     604             :         const timelib_lookup_table *tp;
     605             : 
     606        1018 :         while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
     607         660 :                 ++*ptr;
     608             :         }
     609         179 :         end = *ptr;
     610         179 :         word = calloc(1, end - begin + 1);
     611         179 :         memcpy(word, begin, end - begin);
     612             : 
     613        6802 :         for (tp = timelib_month_lookup; tp->name; tp++) {
     614        6623 :                 if (strcasecmp(word, tp->name) == 0) {
     615         189 :                         value = tp->value;
     616             :                 }
     617             :         }
     618             : 
     619         179 :         free(word);
     620         179 :         return value;
     621             : }
     622             : 
     623         164 : static long timelib_get_month(char **ptr)
     624             : {
     625         415 :         while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '.' || **ptr == '/') {
     626          87 :                 ++*ptr;
     627             :         }
     628         164 :         return timelib_lookup_month(ptr);
     629             : }
     630             : 
     631         505 : static void timelib_eat_spaces(char **ptr)
     632             : {
     633        1509 :         while (**ptr == ' ' || **ptr == '\t') {
     634         499 :                 ++*ptr;
     635             :         }
     636         505 : }
     637             : 
     638           2 : static void timelib_eat_until_separator(char **ptr)
     639             : {
     640           2 :         ++*ptr;
     641           4 :         while (strchr(" \t.,:;/-0123456789", **ptr) == NULL) {
     642           0 :                 ++*ptr;
     643             :         }
     644           2 : }
     645             : 
     646        1507 : static const timelib_relunit* timelib_lookup_relunit(char **ptr)
     647             : {
     648             :         char *word;
     649        1507 :         char *begin = *ptr, *end;
     650        1507 :         const timelib_relunit *tp, *value = NULL;
     651             : 
     652       55132 :         while (**ptr != '\0' && **ptr != ' ' && **ptr != ',' && **ptr != '\t' && **ptr != ';' && **ptr != ':' &&
     653       43432 :            **ptr != '/' && **ptr != '.' && **ptr != '-' && **ptr != '(' && **ptr != ')' ) {
     654        8686 :                 ++*ptr;
     655             :         }
     656        1507 :         end = *ptr;
     657        1507 :         word = calloc(1, end - begin + 1);
     658        1507 :         memcpy(word, begin, end - begin);
     659             : 
     660       32374 :         for (tp = timelib_relunit_lookup; tp->name; tp++) {
     661       32374 :                 if (strcasecmp(word, tp->name) == 0) {
     662        1507 :                         value = tp;
     663        1507 :                         break;
     664             :                 }
     665             :         }
     666             : 
     667        1507 :         free(word);
     668        1507 :         return value;
     669             : }
     670             : 
     671         432 : static void timelib_set_relative(char **ptr, timelib_sll amount, int behavior, Scanner *s)
     672             : {
     673             :         const timelib_relunit* relunit;
     674             : 
     675         432 :         if (!(relunit = timelib_lookup_relunit(ptr))) {
     676           0 :                 return;
     677             :         }
     678             : 
     679         432 :         switch (relunit->unit) {
     680          33 :                 case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
     681          22 :                 case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
     682          56 :                 case TIMELIB_HOUR:   s->time->relative.h += amount * relunit->multiplier; break;
     683         120 :                 case TIMELIB_DAY:    s->time->relative.d += amount * relunit->multiplier; break;
     684          45 :                 case TIMELIB_MONTH:  s->time->relative.m += amount * relunit->multiplier; break;
     685          31 :                 case TIMELIB_YEAR:   s->time->relative.y += amount * relunit->multiplier; break;
     686             : 
     687             :                 case TIMELIB_WEEKDAY:
     688         125 :                         TIMELIB_HAVE_WEEKDAY_RELATIVE();
     689         125 :                         TIMELIB_UNHAVE_TIME();
     690         125 :                         s->time->relative.d += (amount > 0 ? amount - 1 : amount) * 7;
     691         125 :                         s->time->relative.weekday = relunit->multiplier;
     692         125 :                         s->time->relative.weekday_behavior = behavior;
     693         125 :                         break;
     694             : 
     695             :                 case TIMELIB_SPECIAL:
     696           0 :                         TIMELIB_HAVE_SPECIAL_RELATIVE();
     697           0 :                         TIMELIB_UNHAVE_TIME();
     698           0 :                         s->time->relative.special.type = relunit->multiplier;
     699           0 :                         s->time->relative.special.amount = amount;
     700             :         }
     701             : }
     702             : 
     703        3693 : const static timelib_tz_lookup_table* zone_search(const char *word, long gmtoffset, int isdst)
     704             : {
     705        3693 :         int first_found = 0;
     706        3693 :         const timelib_tz_lookup_table  *tp, *first_found_elem = NULL;
     707             :         const timelib_tz_lookup_table  *fmp;
     708             : 
     709        3693 :         if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
     710         105 :                 return timelib_timezone_utc;
     711             :         }
     712             :         
     713     5620418 :         for (tp = timelib_timezone_lookup; tp->name; tp++) {
     714     5618081 :                 if (strcasecmp(word, tp->name) == 0) {
     715        1276 :                         if (!first_found) {
     716        1252 :                                 first_found = 1;
     717        1252 :                                 first_found_elem = tp;
     718        1252 :                                 if (gmtoffset == -1) {
     719        1245 :                                         return tp;
     720             :                                 }
     721             :                         }
     722          31 :                         if (tp->gmtoffset == gmtoffset) {
     723           6 :                                 return tp;
     724             :                         }
     725             :                 }
     726             :         }
     727        2337 :         if (first_found) {
     728           1 :                 return first_found_elem;
     729             :         }
     730             : 
     731     1492525 :         for (tp = timelib_timezone_lookup; tp->name; tp++) {
     732     1492387 :                 if (tp->full_tz_name && strcasecmp(word, tp->full_tz_name) == 0) {
     733        2198 :                         if (!first_found) {
     734        2198 :                                 first_found = 1;
     735        2198 :                                 first_found_elem = tp;
     736        2198 :                                 if (gmtoffset == -1) {
     737        2198 :                                         return tp;
     738             :                                 }
     739             :                         }
     740           0 :                         if (tp->gmtoffset == gmtoffset) {
     741           0 :                                 return tp;
     742             :                         }
     743             :                 }
     744             :         }
     745         138 :         if (first_found) {
     746           0 :                 return first_found_elem;
     747             :         }
     748             : 
     749             : 
     750             :         /* Still didn't find anything, let's find the zone solely based on
     751             :          * offset/isdst then */
     752        5323 :         for (fmp = timelib_timezone_fallbackmap; fmp->name; fmp++) {
     753        5213 :                 if ((fmp->gmtoffset * 60) == gmtoffset && fmp->type == isdst) {
     754          28 :                         return fmp;
     755             :                 }
     756             :         }
     757         110 :         return NULL;
     758             : }
     759             : 
     760        3263 : static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found)
     761             : {
     762             :         char *word;
     763        3263 :         char *begin = *ptr, *end;
     764        3263 :         long  value = 0;
     765             :         const timelib_tz_lookup_table *tp;
     766             : 
     767       36766 :         while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') {
     768       30240 :                 ++*ptr;
     769             :         }
     770        3263 :         end = *ptr;
     771        3263 :         word = calloc(1, end - begin + 1);
     772        3263 :         memcpy(word, begin, end - begin);
     773             : 
     774        3263 :         if ((tp = zone_search(word, -1, 0))) {
     775        3203 :                 value = -tp->gmtoffset / 60;
     776        3203 :                 *dst = tp->type;
     777        3203 :                 value += tp->type * 60;
     778        3203 :                 *found = 1;
     779             :         } else {
     780          60 :                 *found = 0;
     781             :         }
     782             : 
     783        3263 :         *tz_abbr = word;
     784        3263 :         return value;
     785             : }
     786             : 
     787        3477 : static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper)
     788             : {
     789             :         timelib_tzinfo *res;
     790        3477 :         long            retval = 0;
     791             : 
     792        3477 :         *tz_not_found = 0;
     793             : 
     794        6956 :         while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
     795           2 :                 ++*ptr;
     796             :         }
     797        3477 :         if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) {
     798          10 :                 *ptr += 3;
     799             :         }
     800        3477 :         if (**ptr == '+') {
     801         101 :                 ++*ptr;
     802         101 :                 t->is_localtime = 1;
     803         101 :                 t->zone_type = TIMELIB_ZONETYPE_OFFSET;
     804         101 :                 *tz_not_found = 0;
     805         101 :                 t->dst = 0;
     806             : 
     807         101 :                 retval = -1 * timelib_parse_tz_cor(ptr);
     808        3376 :         } else if (**ptr == '-') {
     809         113 :                 ++*ptr;
     810         113 :                 t->is_localtime = 1;
     811         113 :                 t->zone_type = TIMELIB_ZONETYPE_OFFSET;
     812         113 :                 *tz_not_found = 0;
     813         113 :                 t->dst = 0;
     814             : 
     815         113 :                 retval = timelib_parse_tz_cor(ptr);
     816             :         } else {
     817        3263 :                 int found = 0;
     818             :                 long offset;
     819             :                 char *tz_abbr;
     820             : 
     821        3263 :                 t->is_localtime = 1;
     822             : 
     823        3263 :                 offset = timelib_lookup_zone(ptr, dst, &tz_abbr, &found);
     824        3263 :                 if (found) {
     825        3203 :                         t->zone_type = TIMELIB_ZONETYPE_ABBR;
     826             :                 }
     827             : #if 0
     828             :                 /* If we found a TimeZone identifier, use it */
     829             :                 if (tz_name) {
     830             :                         t->tz_info = timelib_parse_tzfile(tz_name);
     831             :                         t->zone_type = TIMELIB_ZONETYPE_ID;
     832             :                 }
     833             : #endif
     834             :                 /* If we have a TimeZone identifier to start with, use it */
     835        3263 :                 if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 0) {
     836        1940 :                         if ((res = tz_wrapper(tz_abbr, tzdb)) != NULL) {
     837        1940 :                                 t->tz_info = res;
     838        1940 :                                 t->zone_type = TIMELIB_ZONETYPE_ID;
     839        1940 :                                 found++;
     840             :                         }
     841             :                 }
     842        3263 :                 if (found && t->zone_type != TIMELIB_ZONETYPE_ID) {
     843        1275 :                         timelib_time_tz_abbr_update(t, tz_abbr);
     844             :                 }
     845        3263 :                 free(tz_abbr);
     846        3263 :                 *tz_not_found = (found == 0);
     847        3263 :                 retval = offset;
     848             :         }
     849        6954 :         while (**ptr == ')') {
     850           0 :                 ++*ptr;
     851             :         }
     852        3477 :         return retval;
     853             : }
     854             : 
     855             : #define timelib_split_free(arg) {       \
     856             :         int i;                         \
     857             :         for (i = 0; i < arg.c; i++) {  \
     858             :                 free(arg.v[i]);            \
     859             :         }                              \
     860             :         if (arg.v) {                   \
     861             :                 free(arg.v);               \
     862             :         }                              \
     863             : }
     864             : 
     865       24085 : static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
     866             : {
     867       24085 :         uchar *cursor = s->cur;
     868       24085 :         char *str, *ptr = NULL;
     869             :                 
     870             : std:
     871       40199 :         s->tok = cursor;
     872       40199 :         s->len = 0;
     873             : /*!re2c
     874             : any = [\000-\377];
     875             : 
     876             : space = [ \t]+;
     877             : frac = "."[0-9]+;
     878             : 
     879             : ago = 'ago';
     880             : 
     881             : hour24 = [01]?[0-9] | "2"[0-4];
     882             : hour24lz = [01][0-9] | "2"[0-4];
     883             : hour12 = "0"?[1-9] | "1"[0-2];
     884             : minute = [0-5]?[0-9];
     885             : minutelz = [0-5][0-9];
     886             : second = minute | "60";
     887             : secondlz = minutelz | "60";
     888             : meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
     889             : tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/-][A-Za-z]+)+;
     890             : tzcorrection = "GMT"? [+-] hour24 ":"? minute?;
     891             : 
     892             : daysuf = "st" | "nd" | "rd" | "th";
     893             : 
     894             : month = "0"? [0-9] | "1"[0-2];
     895             : day   = (([0-2]?[0-9]) | ("3"[01])) daysuf?;
     896             : year  = [0-9]{1,4};
     897             : year2 = [0-9]{2};
     898             : year4 = [0-9]{4};
     899             : year4withsign = [+-]? [0-9]{4};
     900             : 
     901             : dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
     902             : weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
     903             : 
     904             : monthlz = "0" [0-9] | "1" [0-2];
     905             : daylz   = "0" [0-9] | [1-2][0-9] | "3" [01];
     906             : 
     907             : dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
     908             : dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
     909             : dayspecial = 'weekday' | 'weekdays';
     910             : daytext = dayfull | dayabbr | dayspecial;
     911             : 
     912             : monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
     913             : monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
     914             : monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
     915             : monthtext = monthfull | monthabbr | monthroman;
     916             : 
     917             : /* Time formats */
     918             : timetiny12 = hour12 space? meridian;
     919             : timeshort12 = hour12[:.]minutelz space? meridian;
     920             : timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
     921             : 
     922             : timeshort24 = 't'? hour24[:.]minute;
     923             : timelong24 =  't'? hour24[:.]minute[:.]second;
     924             : iso8601long =  't'? hour24 [:.] minute [:.] second frac;
     925             : 
     926             : /* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
     927             : iso8601normtz =  't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
     928             : /* iso8601longtz =  hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
     929             : 
     930             : gnunocolon       = 't'? hour24lz minutelz;
     931             : /* gnunocolontz     = hour24lz minutelz space? (tzcorrection | tz); */
     932             : iso8601nocolon   = 't'? hour24lz minutelz secondlz; 
     933             : /* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
     934             : 
     935             : /* Date formats */
     936             : americanshort    = month "/" day;
     937             : american         = month "/" day "/" year;
     938             : iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
     939             : dateslash        = year4 "/" month "/" day;
     940             : iso8601date4     = year4withsign "-" monthlz "-" daylz;
     941             : iso8601date2     = year2 "-" monthlz "-" daylz;
     942             : gnudateshorter   = year4 "-" month;
     943             : gnudateshort     = year "-" month "-" day;
     944             : pointeddate4     = day [.\t-] month [.-] year4;
     945             : pointeddate2     = day [.\t] month "." year2;
     946             : datefull         = day ([ \t.-])* monthtext ([ \t.-])* year;
     947             : datenoday        = monthtext ([ .\t-])* year4;
     948             : datenodayrev     = year4 ([ .\t-])* monthtext;
     949             : datetextual      = monthtext ([ .\t-])* day [,.stndrh\t ]+ year;
     950             : datenoyear       = monthtext ([ .\t-])* day [,.stndrh\t ]*;
     951             : datenoyearrev    = day ([ .\t-])* monthtext;
     952             : datenocolon      = year4 monthlz daylz;
     953             : 
     954             : /* Special formats */
     955             : soap             = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection?;
     956             : xmlrpc           = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
     957             : xmlrpcnocolon    = year4 monthlz daylz 't' hour24 minutelz secondlz;
     958             : wddx             = year4 "-" month "-" day "T" hour24 ":" minute ":" second;
     959             : pgydotd          = year4 "."? dayofyear;
     960             : pgtextshort      = monthabbr "-" daylz "-" year;
     961             : pgtextreverse    = year "-" monthabbr "-" daylz;
     962             : mssqltime        = hour12 ":" minutelz ":" secondlz [:.] [0-9]+ meridian;
     963             : isoweekday       = year4 "-"? "W" weekofyear "-"? [0-7];
     964             : isoweek          = year4 "-"? "W" weekofyear;
     965             : exif             = year4 ":" monthlz ":" daylz " " hour24lz ":" minutelz ":" secondlz;
     966             : firstdayof       = 'first day of'?;
     967             : lastdayof        = 'last day of'?;
     968             : backof           = 'back of ' hour24 space? meridian?;
     969             : frontof          = 'front of ' hour24 space? meridian?;
     970             : 
     971             : /* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
     972             : clf              = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
     973             : 
     974             : /* Timestamp format: @1126396800 */
     975             : timestamp        = "@" "-"? [0-9]+;
     976             : 
     977             : /* To fix some ambiguities */
     978             : dateshortwithtimeshort12  = datenoyear timeshort12;
     979             : dateshortwithtimelong12   = datenoyear timelong12;
     980             : dateshortwithtimeshort  = datenoyear timeshort24;
     981             : dateshortwithtimelong   = datenoyear timelong24;
     982             : dateshortwithtimelongtz = datenoyear iso8601normtz;
     983             : 
     984             : /*
     985             :  * Relative regexps
     986             :  */
     987             : reltextnumber = 'first'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'eighth'|'ninth'|'tenth'|'eleventh'|'twelfth';
     988             : reltexttext = 'next'|'last'|'previous'|'this';
     989             : reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'fortnight'|'forthnight'|'month'|'year') 's'?) | 'weeks' | daytext;
     990             : 
     991             : relnumber = ([+-]*[ \t]*[0-9]+);
     992             : relative = relnumber space? (reltextunit | 'week' );
     993             : relativetext = (reltextnumber|reltexttext) space reltextunit;
     994             : relativetextweek = reltexttext space 'week';
     995             : 
     996             : weekdayof        = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of';
     997             : 
     998             : */
     999             : 
    1000             : /*!re2c
    1001             :         /* so that vim highlights correctly */
    1002             :         'yesterday'
    1003             :         {
    1004             :                 DEBUG_OUTPUT("yesterday");
    1005           1 :                 TIMELIB_INIT;
    1006           1 :                 TIMELIB_HAVE_RELATIVE();
    1007           1 :                 TIMELIB_UNHAVE_TIME();
    1008             : 
    1009           1 :                 s->time->relative.d = -1;
    1010           1 :                 TIMELIB_DEINIT;
    1011           1 :                 return TIMELIB_RELATIVE;
    1012             :         }
    1013             : 
    1014             :         'now'
    1015             :         {
    1016             :                 DEBUG_OUTPUT("now");
    1017          59 :                 TIMELIB_INIT;
    1018             : 
    1019          59 :                 TIMELIB_DEINIT;
    1020          59 :                 return TIMELIB_RELATIVE;
    1021             :         }
    1022             : 
    1023             :         'noon'
    1024             :         {
    1025             :                 DEBUG_OUTPUT("noon");
    1026           2 :                 TIMELIB_INIT;
    1027           2 :                 TIMELIB_UNHAVE_TIME();
    1028           2 :                 TIMELIB_HAVE_TIME();
    1029           2 :                 s->time->h = 12;
    1030             : 
    1031           2 :                 TIMELIB_DEINIT;
    1032           2 :                 return TIMELIB_RELATIVE;
    1033             :         }
    1034             : 
    1035             :         'midnight' | 'today'
    1036             :         {
    1037             :                 DEBUG_OUTPUT("midnight | today");
    1038           1 :                 TIMELIB_INIT;
    1039           1 :                 TIMELIB_UNHAVE_TIME();
    1040             : 
    1041           1 :                 TIMELIB_DEINIT;
    1042           1 :                 return TIMELIB_RELATIVE;
    1043             :         }
    1044             : 
    1045             :         'tomorrow'
    1046             :         {
    1047             :                 DEBUG_OUTPUT("tomorrow");
    1048           1 :                 TIMELIB_INIT;
    1049           1 :                 TIMELIB_HAVE_RELATIVE();
    1050           1 :                 TIMELIB_UNHAVE_TIME();
    1051             : 
    1052           1 :                 s->time->relative.d = 1;
    1053           1 :                 TIMELIB_DEINIT;
    1054           1 :                 return TIMELIB_RELATIVE;
    1055             :         }
    1056             : 
    1057             :         timestamp
    1058             :         {
    1059             :                 timelib_ull i;
    1060             : 
    1061         212 :                 TIMELIB_INIT;
    1062         212 :                 TIMELIB_HAVE_RELATIVE();
    1063         212 :                 TIMELIB_UNHAVE_DATE();
    1064         212 :                 TIMELIB_UNHAVE_TIME();
    1065         212 :                 TIMELIB_HAVE_TZ();
    1066             : 
    1067         212 :                 i = timelib_get_unsigned_nr((char **) &ptr, 24);
    1068         212 :                 s->time->y = 1970;
    1069         212 :                 s->time->m = 1;
    1070         212 :                 s->time->d = 1;
    1071         212 :                 s->time->h = s->time->i = s->time->s = 0;
    1072         212 :                 s->time->f = 0.0;
    1073         212 :                 s->time->relative.s += i;
    1074         212 :                 s->time->is_localtime = 1;
    1075         212 :                 s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
    1076         212 :                 s->time->z = 0;
    1077         212 :                 s->time->dst = 0;
    1078             : 
    1079         212 :                 TIMELIB_DEINIT;
    1080         212 :                 return TIMELIB_RELATIVE;
    1081             :         }
    1082             : 
    1083             :         firstdayof | lastdayof
    1084             :         {
    1085             :                 DEBUG_OUTPUT("firstdayof | lastdayof");
    1086           7 :                 TIMELIB_INIT;
    1087           7 :                 TIMELIB_HAVE_RELATIVE();
    1088             : 
    1089             :                 /* skip "last day of" or "first day of" */
    1090           7 :                 if (*ptr == 'l') {
    1091           2 :                         s->time->relative.first_last_day_of = 2;
    1092             :                 } else {
    1093           5 :                         s->time->relative.first_last_day_of = 1;
    1094             :                 }
    1095             : 
    1096           7 :                 TIMELIB_DEINIT;
    1097           7 :                 return TIMELIB_LF_DAY_OF_MONTH;
    1098             :         }
    1099             : 
    1100             :         backof | frontof
    1101             :         {
    1102             :                 DEBUG_OUTPUT("backof | frontof");
    1103           5 :                 TIMELIB_INIT;
    1104           5 :                 TIMELIB_UNHAVE_TIME();
    1105           5 :                 TIMELIB_HAVE_TIME();
    1106             : 
    1107           5 :                 if (*ptr == 'b') {
    1108           3 :                         s->time->h = timelib_get_nr((char **) &ptr, 2);
    1109           3 :                         s->time->i = 15;
    1110             :                 } else {
    1111           2 :                         s->time->h = timelib_get_nr((char **) &ptr, 2) - 1;
    1112           2 :                         s->time->i = 45;
    1113             :                 }
    1114           5 :                 if (*ptr != '\0' ) {
    1115           1 :                         timelib_eat_spaces((char **) &ptr);
    1116           1 :                         s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1117             :                 }
    1118             : 
    1119           5 :                 TIMELIB_DEINIT;
    1120           5 :                 return TIMELIB_LF_DAY_OF_MONTH;
    1121             :         }
    1122             : 
    1123             :         weekdayof
    1124             :         {
    1125             :                 timelib_sll i;
    1126           5 :                 int         behavior = 0;
    1127             :                 DEBUG_OUTPUT("weekdayof");
    1128           5 :                 TIMELIB_INIT;
    1129           5 :                 TIMELIB_HAVE_RELATIVE();
    1130           5 :                 TIMELIB_HAVE_SPECIAL_RELATIVE();
    1131             : 
    1132           5 :                 i = timelib_get_relative_text((char **) &ptr, &behavior);
    1133           5 :                 timelib_eat_spaces((char **) &ptr);
    1134           5 :                 if (i > 0) { /* first, second... etc */
    1135           4 :                         s->time->relative.special.type = TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH;
    1136           4 :                         timelib_set_relative((char **) &ptr, i, 1, s);
    1137             :                 } else { /* last */
    1138           1 :                         s->time->relative.special.type = TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH;
    1139           1 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1140             :                 }
    1141           5 :                 TIMELIB_DEINIT;
    1142           5 :                 return TIMELIB_WEEK_DAY_OF_MONTH;
    1143             :         }
    1144             : 
    1145             :         timetiny12 | timeshort12 | timelong12
    1146             :         {
    1147             :                 DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
    1148          22 :                 TIMELIB_INIT;
    1149          22 :                 TIMELIB_HAVE_TIME();
    1150          22 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1151          22 :                 if (*ptr == ':' || *ptr == '.') {
    1152          13 :                         s->time->i = timelib_get_nr((char **) &ptr, 2);
    1153          13 :                         if (*ptr == ':' || *ptr == '.') {
    1154           4 :                                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1155             :                         }
    1156             :                 }
    1157          22 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1158          22 :                 TIMELIB_DEINIT;
    1159          22 :                 return TIMELIB_TIME12;
    1160             :         }
    1161             : 
    1162             :         mssqltime
    1163             :         {
    1164             :                 DEBUG_OUTPUT("mssqltime");
    1165           0 :                 TIMELIB_INIT;
    1166           0 :                 TIMELIB_HAVE_TIME();
    1167           0 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1168           0 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1169           0 :                 if (*ptr == ':' || *ptr == '.') {
    1170           0 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1171             : 
    1172           0 :                         if (*ptr == ':' || *ptr == '.') {
    1173           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1174             :                         }
    1175             :                 }
    1176           0 :                 timelib_eat_spaces((char **) &ptr);
    1177           0 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1178           0 :                 TIMELIB_DEINIT;
    1179           0 :                 return TIMELIB_TIME24_WITH_ZONE;
    1180             :         }
    1181             : 
    1182             :         timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
    1183             :         {
    1184             :                 int tz_not_found;
    1185             :                 DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
    1186        4327 :                 TIMELIB_INIT;
    1187        4327 :                 TIMELIB_HAVE_TIME();
    1188        4324 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1189        4324 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1190        4324 :                 if (*ptr == ':' || *ptr == '.') {
    1191        3287 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1192             : 
    1193        3287 :                         if (*ptr == '.') {
    1194          19 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1195             :                         }
    1196             :                 }
    1197             : 
    1198        4324 :                 if (*ptr != '\0') {
    1199           0 :                         s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1200           0 :                         if (tz_not_found) {
    1201           0 :                                 add_error(s, "The timezone could not be found in the database");
    1202             :                         }
    1203             :                 }
    1204        4324 :                 TIMELIB_DEINIT;
    1205        4324 :                 return TIMELIB_TIME24_WITH_ZONE;
    1206             :         }
    1207             : 
    1208             :         gnunocolon
    1209             :         {
    1210             :                 DEBUG_OUTPUT("gnunocolon");
    1211          22 :                 TIMELIB_INIT;
    1212          22 :                 switch (s->time->have_time) {
    1213             :                         case 0:
    1214          16 :                                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1215          16 :                                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1216          16 :                                 s->time->s = 0;
    1217          16 :                                 break;
    1218             :                         case 1:
    1219           6 :                                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1220           6 :                                 break;
    1221             :                         default:
    1222           0 :                                 TIMELIB_DEINIT;
    1223           0 :                                 add_error(s, "Double time specification");
    1224           0 :                                 return TIMELIB_ERROR;
    1225             :                 }
    1226          22 :                 s->time->have_time++;
    1227          22 :                 TIMELIB_DEINIT;
    1228          22 :                 return TIMELIB_GNU_NOCOLON;
    1229             :         }
    1230             : /*
    1231             :         gnunocolontz
    1232             :         {
    1233             :                 DEBUG_OUTPUT("gnunocolontz");
    1234             :                 TIMELIB_INIT;
    1235             :                 switch (s->time->have_time) {
    1236             :                         case 0:
    1237             :                                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1238             :                                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1239             :                                 s->time->s = 0;
    1240             :                                 s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb, tz_get_wrapper);
    1241             :                                 break;
    1242             :                         case 1:
    1243             :                                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1244             :                                 break;
    1245             :                         default:
    1246             :                                 TIMELIB_DEINIT;
    1247             :                                 return TIMELIB_ERROR;
    1248             :                 }
    1249             :                 s->time->have_time++;
    1250             :                 TIMELIB_DEINIT;
    1251             :                 return TIMELIB_GNU_NOCOLON_TZ;
    1252             :         }
    1253             : */
    1254             :         iso8601nocolon /*| iso8601nocolontz*/
    1255             :         {
    1256             :                 int tz_not_found;
    1257             :                 DEBUG_OUTPUT("iso8601nocolon");
    1258           8 :                 TIMELIB_INIT;
    1259           8 :                 TIMELIB_HAVE_TIME();
    1260           8 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1261           8 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1262           8 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1263             : 
    1264           8 :                 if (*ptr != '\0') {
    1265           0 :                         s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1266           0 :                         if (tz_not_found) {
    1267           0 :                                 add_error(s, "The timezone could not be found in the database");
    1268             :                         }
    1269             :                 }
    1270           8 :                 TIMELIB_DEINIT;
    1271           8 :                 return TIMELIB_ISO_NOCOLON;
    1272             :         }
    1273             : 
    1274             :         americanshort | american
    1275             :         {
    1276           4 :                 int length = 0;
    1277             :                 DEBUG_OUTPUT("americanshort | american");
    1278           4 :                 TIMELIB_INIT;
    1279           4 :                 TIMELIB_HAVE_DATE();
    1280           4 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1281           4 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1282           4 :                 if (*ptr == '/') {
    1283           4 :                         s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1284           4 :                         TIMELIB_PROCESS_YEAR(s->time->y, length);
    1285             :                 }
    1286           4 :                 TIMELIB_DEINIT;
    1287           4 :                 return TIMELIB_AMERICAN;
    1288             :         }
    1289             : 
    1290             :         iso8601date4 | iso8601dateslash | dateslash
    1291             :         {
    1292             :                 DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
    1293        5016 :                 TIMELIB_INIT;
    1294        5016 :                 TIMELIB_HAVE_DATE();
    1295        5016 :                 s->time->y = timelib_get_unsigned_nr((char **) &ptr, 4);
    1296        5016 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1297        5016 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1298        5016 :                 TIMELIB_DEINIT;
    1299        5016 :                 return TIMELIB_ISO_DATE;
    1300             :         }
    1301             : 
    1302             :         iso8601date2
    1303             :         {
    1304           0 :                 int length = 0;
    1305             :                 DEBUG_OUTPUT("iso8601date2");
    1306           0 :                 TIMELIB_INIT;
    1307           0 :                 TIMELIB_HAVE_DATE();
    1308           0 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1309           0 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1310           0 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1311           0 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1312           0 :                 TIMELIB_DEINIT;
    1313           0 :                 return TIMELIB_ISO_DATE;
    1314             :         }
    1315             : 
    1316             :         gnudateshorter
    1317             :         {
    1318           6 :                 int length = 0;
    1319             :                 DEBUG_OUTPUT("gnudateshorter");
    1320           6 :                 TIMELIB_INIT;
    1321           6 :                 TIMELIB_HAVE_DATE();
    1322           6 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1323           6 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1324           6 :                 s->time->d = 1;
    1325           6 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1326           6 :                 TIMELIB_DEINIT;
    1327           6 :                 return TIMELIB_ISO_DATE;
    1328             :         }
    1329             : 
    1330             :         gnudateshort
    1331             :         {
    1332        1022 :                 int length = 0;
    1333             :                 DEBUG_OUTPUT("gnudateshort");
    1334        1022 :                 TIMELIB_INIT;
    1335        1022 :                 TIMELIB_HAVE_DATE();
    1336        1022 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1337        1022 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1338        1022 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1339        1022 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1340        1022 :                 TIMELIB_DEINIT;
    1341        1022 :                 return TIMELIB_ISO_DATE;
    1342             :         }
    1343             : 
    1344             :         datefull
    1345             :         {
    1346          83 :                 int length = 0;
    1347             :                 DEBUG_OUTPUT("datefull");
    1348          83 :                 TIMELIB_INIT;
    1349          83 :                 TIMELIB_HAVE_DATE();
    1350          83 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1351          83 :                 timelib_skip_day_suffix((char **) &ptr);
    1352          83 :                 s->time->m = timelib_get_month((char **) &ptr);
    1353          83 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1354          83 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1355          83 :                 TIMELIB_DEINIT;
    1356          83 :                 return TIMELIB_DATE_FULL;
    1357             :         }
    1358             : 
    1359             :         pointeddate4
    1360             :         {
    1361             :                 DEBUG_OUTPUT("pointed date YYYY");
    1362           5 :                 TIMELIB_INIT;
    1363           5 :                 TIMELIB_HAVE_DATE();
    1364           5 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1365           5 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1366           5 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1367           5 :                 TIMELIB_DEINIT;
    1368           5 :                 return TIMELIB_DATE_FULL_POINTED;
    1369             :         }
    1370             : 
    1371             :         pointeddate2
    1372             :         {
    1373           0 :                 int length = 0;
    1374             :                 DEBUG_OUTPUT("pointed date YY");
    1375           0 :                 TIMELIB_INIT;
    1376           0 :                 TIMELIB_HAVE_DATE();
    1377           0 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1378           0 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1379           0 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
    1380           0 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1381           0 :                 TIMELIB_DEINIT;
    1382           0 :                 return TIMELIB_DATE_FULL_POINTED;
    1383             :         }
    1384             : 
    1385             :         datenoday
    1386             :         {
    1387          28 :                 int length = 0;
    1388             :                 DEBUG_OUTPUT("datenoday");
    1389          28 :                 TIMELIB_INIT;
    1390          28 :                 TIMELIB_HAVE_DATE();
    1391          28 :                 s->time->m = timelib_get_month((char **) &ptr);
    1392          28 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1393          28 :                 s->time->d = 1;
    1394          28 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1395          28 :                 TIMELIB_DEINIT;
    1396          28 :                 return TIMELIB_DATE_NO_DAY;
    1397             :         }
    1398             : 
    1399             :         datenodayrev
    1400             :         {
    1401           1 :                 int length = 0;
    1402             :                 DEBUG_OUTPUT("datenodayrev");
    1403           1 :                 TIMELIB_INIT;
    1404           1 :                 TIMELIB_HAVE_DATE();
    1405           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1406           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1407           1 :                 s->time->d = 1;
    1408           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1409           1 :                 TIMELIB_DEINIT;
    1410           1 :                 return TIMELIB_DATE_NO_DAY;
    1411             :         }
    1412             : 
    1413             :         datetextual | datenoyear
    1414             :         {
    1415          29 :                 int length = 0;
    1416             :                 DEBUG_OUTPUT("datetextual | datenoyear");
    1417          29 :                 TIMELIB_INIT;
    1418          29 :                 TIMELIB_HAVE_DATE();
    1419          29 :                 s->time->m = timelib_get_month((char **) &ptr);
    1420          29 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1421          29 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1422          29 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1423          29 :                 TIMELIB_DEINIT;
    1424          29 :                 return TIMELIB_DATE_TEXT;
    1425             :         }
    1426             : 
    1427             :         datenoyearrev
    1428             :         {
    1429             :                 DEBUG_OUTPUT("datenoyearrev");
    1430           3 :                 TIMELIB_INIT;
    1431           3 :                 TIMELIB_HAVE_DATE();
    1432           3 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1433           3 :                 timelib_skip_day_suffix((char **) &ptr);
    1434           3 :                 s->time->m = timelib_get_month((char **) &ptr);
    1435           3 :                 TIMELIB_DEINIT;
    1436           3 :                 return TIMELIB_DATE_TEXT;
    1437             :         }
    1438             : 
    1439             :         datenocolon
    1440             :         {
    1441             :                 DEBUG_OUTPUT("datenocolon");
    1442           7 :                 TIMELIB_INIT;
    1443           7 :                 TIMELIB_HAVE_DATE();
    1444           7 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1445           7 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1446           7 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1447           7 :                 TIMELIB_DEINIT;
    1448           7 :                 return TIMELIB_DATE_NOCOLON;
    1449             :         }
    1450             : 
    1451             :         xmlrpc | xmlrpcnocolon | soap | wddx | exif
    1452             :         {
    1453             :                 int tz_not_found;
    1454             :                 DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
    1455          55 :                 TIMELIB_INIT;
    1456          55 :                 TIMELIB_HAVE_TIME();
    1457          55 :                 TIMELIB_HAVE_DATE();
    1458          55 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1459          55 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1460          55 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1461          55 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1462          55 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1463          55 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1464          55 :                 if (*ptr == '.') {
    1465           1 :                         s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
    1466           1 :                         if (*ptr) { /* timezone is optional */
    1467           0 :                                 s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1468           0 :                                 if (tz_not_found) {
    1469           0 :                                         add_error(s, "The timezone could not be found in the database");
    1470             :                                 }
    1471             :                         }
    1472             :                 }
    1473          55 :                 TIMELIB_DEINIT;
    1474          55 :                 return TIMELIB_XMLRPC_SOAP;
    1475             :         }
    1476             : 
    1477             :         pgydotd
    1478             :         {
    1479           1 :                 int length = 0;
    1480             :                 DEBUG_OUTPUT("pgydotd");
    1481           1 :                 TIMELIB_INIT;
    1482           1 :                 TIMELIB_HAVE_DATE();
    1483           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1484           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 3);
    1485           1 :                 s->time->m = 1;
    1486           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1487           1 :                 TIMELIB_DEINIT;
    1488           1 :                 return TIMELIB_PG_YEARDAY;
    1489             :         }
    1490             : 
    1491             :         isoweekday
    1492             :         {
    1493             :                 timelib_sll w, d;
    1494             :                 DEBUG_OUTPUT("isoweekday");
    1495           4 :                 TIMELIB_INIT;
    1496           4 :                 TIMELIB_HAVE_DATE();
    1497           4 :                 TIMELIB_HAVE_RELATIVE();
    1498             :                 
    1499           4 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1500           4 :                 w = timelib_get_nr((char **) &ptr, 2);
    1501           4 :                 d = timelib_get_nr((char **) &ptr, 1);
    1502           4 :                 s->time->m = 1;
    1503           4 :                 s->time->d = 1;
    1504           4 :                 s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
    1505             : 
    1506           4 :                 TIMELIB_DEINIT;
    1507           4 :                 return TIMELIB_ISO_WEEK;
    1508             :         }
    1509             : 
    1510             :         isoweek
    1511             :         {
    1512             :                 timelib_sll w, d;
    1513             :                 DEBUG_OUTPUT("isoweek");
    1514           1 :                 TIMELIB_INIT;
    1515           1 :                 TIMELIB_HAVE_DATE();
    1516           1 :                 TIMELIB_HAVE_RELATIVE();
    1517             :                 
    1518           1 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1519           1 :                 w = timelib_get_nr((char **) &ptr, 2);
    1520           1 :                 d = 1;
    1521           1 :                 s->time->m = 1;
    1522           1 :                 s->time->d = 1;
    1523           1 :                 s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
    1524             : 
    1525           1 :                 TIMELIB_DEINIT;
    1526           1 :                 return TIMELIB_ISO_WEEK;
    1527             :         }
    1528             : 
    1529             :         pgtextshort
    1530             :         {
    1531           1 :                 int length = 0;
    1532             :                 DEBUG_OUTPUT("pgtextshort");
    1533           1 :                 TIMELIB_INIT;
    1534           1 :                 TIMELIB_HAVE_DATE();
    1535           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1536           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1537           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1538           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1539           1 :                 TIMELIB_DEINIT;
    1540           1 :                 return TIMELIB_PG_TEXT;
    1541             :         }
    1542             : 
    1543             :         pgtextreverse
    1544             :         {
    1545           1 :                 int length = 0;
    1546             :                 DEBUG_OUTPUT("pgtextreverse");
    1547           1 :                 TIMELIB_INIT;
    1548           1 :                 TIMELIB_HAVE_DATE();
    1549           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1550           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1551           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1552           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1553           1 :                 TIMELIB_DEINIT;
    1554           1 :                 return TIMELIB_PG_TEXT;
    1555             :         }
    1556             : 
    1557             :         clf
    1558             :         {
    1559             :                 int tz_not_found;
    1560             :                 DEBUG_OUTPUT("clf");
    1561           2 :                 TIMELIB_INIT;
    1562           2 :                 TIMELIB_HAVE_TIME();
    1563           2 :                 TIMELIB_HAVE_DATE();
    1564           2 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1565           2 :                 s->time->m = timelib_get_month((char **) &ptr);
    1566           2 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1567           2 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1568           2 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1569           2 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1570           2 :                 s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1571           2 :                 if (tz_not_found) {
    1572           0 :                         add_error(s, "The timezone could not be found in the database");
    1573             :                 }
    1574           2 :                 TIMELIB_DEINIT;
    1575           2 :                 return TIMELIB_CLF;
    1576             :         }
    1577             : 
    1578             :         year4
    1579             :         {
    1580             :                 DEBUG_OUTPUT("year4");
    1581           1 :                 TIMELIB_INIT;
    1582           1 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1583           1 :                 TIMELIB_DEINIT;
    1584           1 :                 return TIMELIB_CLF;
    1585             :         }
    1586             : 
    1587             :         ago
    1588             :         {
    1589             :                 DEBUG_OUTPUT("ago");
    1590           6 :                 TIMELIB_INIT;
    1591           6 :                 s->time->relative.y = 0 - s->time->relative.y;
    1592           6 :                 s->time->relative.m = 0 - s->time->relative.m;
    1593           6 :                 s->time->relative.d = 0 - s->time->relative.d;
    1594           6 :                 s->time->relative.h = 0 - s->time->relative.h;
    1595           6 :                 s->time->relative.i = 0 - s->time->relative.i;
    1596           6 :                 s->time->relative.s = 0 - s->time->relative.s;
    1597           6 :                 s->time->relative.weekday = 0 - s->time->relative.weekday;
    1598           6 :                 if (s->time->relative.weekday == 0) {
    1599           6 :                         s->time->relative.weekday = -7;
    1600             :                 }
    1601           6 :                 if (s->time->relative.have_special_relative && s->time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY) {
    1602           0 :                         s->time->relative.special.amount = 0 - s->time->relative.special.amount;
    1603             :                 }
    1604           6 :                 TIMELIB_DEINIT;
    1605           6 :                 return TIMELIB_AGO;
    1606             :         }
    1607             : 
    1608             :         daytext
    1609             :         {
    1610             :                 const timelib_relunit* relunit;
    1611             :                 DEBUG_OUTPUT("daytext");
    1612        1060 :                 TIMELIB_INIT;
    1613        1060 :                 TIMELIB_HAVE_RELATIVE();
    1614        1060 :                 TIMELIB_HAVE_WEEKDAY_RELATIVE();
    1615        1060 :                 TIMELIB_UNHAVE_TIME();
    1616        1060 :                 relunit = timelib_lookup_relunit((char**) &ptr);
    1617        1060 :                 s->time->relative.weekday = relunit->multiplier;
    1618        1060 :                 if (s->time->relative.weekday_behavior != 2) {
    1619        1058 :                         s->time->relative.weekday_behavior = 1;
    1620             :                 }
    1621             :                 
    1622        1060 :                 TIMELIB_DEINIT;
    1623        1060 :                 return TIMELIB_WEEKDAY;
    1624             :         }
    1625             : 
    1626             :         relativetextweek
    1627             :         {
    1628             :                 timelib_sll i;
    1629           3 :                 int         behavior = 0;
    1630             :                 DEBUG_OUTPUT("relativetextweek");
    1631           3 :                 TIMELIB_INIT;
    1632           3 :                 TIMELIB_HAVE_RELATIVE();
    1633             : 
    1634           9 :                 while(*ptr) {
    1635           3 :                         i = timelib_get_relative_text((char **) &ptr, &behavior);
    1636           3 :                         timelib_eat_spaces((char **) &ptr);
    1637           3 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1638           3 :                         s->time->relative.weekday_behavior = 2;
    1639             : 
    1640             :                         /* to handle the format weekday + last/this/next week */
    1641           3 :                         if (s->time->relative.have_weekday_relative == 0) {
    1642           3 :                                 TIMELIB_HAVE_WEEKDAY_RELATIVE();
    1643           3 :                                 s->time->relative.weekday = 1;
    1644             :                         }
    1645             :                 }
    1646           3 :                 TIMELIB_DEINIT;
    1647           3 :                 return TIMELIB_RELATIVE;
    1648             :         }
    1649             : 
    1650             :         relativetext
    1651             :         {
    1652             :                 timelib_sll i;
    1653         126 :                 int         behavior = 0;
    1654             :                 DEBUG_OUTPUT("relativetext");
    1655         126 :                 TIMELIB_INIT;
    1656         126 :                 TIMELIB_HAVE_RELATIVE();
    1657             : 
    1658         378 :                 while(*ptr) {
    1659         126 :                         i = timelib_get_relative_text((char **) &ptr, &behavior);
    1660         126 :                         timelib_eat_spaces((char **) &ptr);
    1661         126 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1662             :                 }
    1663         126 :                 TIMELIB_DEINIT;
    1664         126 :                 return TIMELIB_RELATIVE;
    1665             :         }
    1666             : 
    1667             :         monthfull | monthabbr
    1668             :         {
    1669             :                 DEBUG_OUTPUT("monthtext");
    1670           2 :                 TIMELIB_INIT;
    1671           2 :                 TIMELIB_HAVE_DATE();
    1672           2 :                 s->time->m = timelib_lookup_month((char **) &ptr);
    1673           2 :                 TIMELIB_DEINIT;
    1674           2 :                 return TIMELIB_DATE_TEXT;
    1675             :         }
    1676             : 
    1677             :         tzcorrection | tz
    1678             :         {
    1679             :                 int tz_not_found;
    1680             :                 DEBUG_OUTPUT("tzcorrection | tz");
    1681        3681 :                 TIMELIB_INIT;
    1682        3681 :                 TIMELIB_HAVE_TZ();
    1683        3443 :                 s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1684        3443 :                 if (tz_not_found) {
    1685          47 :                         add_error(s, "The timezone could not be found in the database");
    1686             :                 }
    1687        3443 :                 TIMELIB_DEINIT;
    1688        3443 :                 return TIMELIB_TIMEZONE;
    1689             :         }
    1690             : 
    1691             :         dateshortwithtimeshort12 | dateshortwithtimelong12
    1692             :         {
    1693             :                 DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
    1694           4 :                 TIMELIB_INIT;
    1695           4 :                 TIMELIB_HAVE_DATE();
    1696           4 :                 s->time->m = timelib_get_month((char **) &ptr);
    1697           4 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1698             : 
    1699           4 :                 TIMELIB_HAVE_TIME();
    1700           4 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1701           4 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1702           4 :                 if (*ptr == ':' || *ptr == '.') {
    1703           0 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1704             : 
    1705           0 :                         if (*ptr == '.') {
    1706           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1707             :                         }
    1708             :                 }
    1709             : 
    1710           4 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1711           4 :                 TIMELIB_DEINIT;
    1712           4 :                 return TIMELIB_SHORTDATE_WITH_TIME;
    1713             :         }
    1714             : 
    1715             :         dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
    1716             :         {
    1717             :                 int tz_not_found;
    1718             :                 DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
    1719          12 :                 TIMELIB_INIT;
    1720          12 :                 TIMELIB_HAVE_DATE();
    1721          12 :                 s->time->m = timelib_get_month((char **) &ptr);
    1722          12 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1723             : 
    1724          12 :                 TIMELIB_HAVE_TIME();
    1725          12 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1726          12 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1727          12 :                 if (*ptr == ':') {
    1728           3 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1729             : 
    1730           3 :                         if (*ptr == '.') {
    1731           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1732             :                         }
    1733             :                 }
    1734             : 
    1735          12 :                 if (*ptr != '\0') {
    1736           0 :                         s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1737           0 :                         if (tz_not_found) {
    1738           0 :                                 add_error(s, "The timezone could not be found in the database");
    1739             :                         }
    1740             :                 }
    1741          12 :                 TIMELIB_DEINIT;
    1742          12 :                 return TIMELIB_SHORTDATE_WITH_TIME;
    1743             :         }
    1744             : 
    1745             :         relative
    1746             :         {
    1747             :                 timelib_ull i;
    1748             :                 DEBUG_OUTPUT("relative");
    1749         298 :                 TIMELIB_INIT;
    1750         298 :                 TIMELIB_HAVE_RELATIVE();
    1751             : 
    1752         894 :                 while(*ptr) {
    1753         298 :                         i = timelib_get_unsigned_nr((char **) &ptr, 24);
    1754         298 :                         timelib_eat_spaces((char **) &ptr);
    1755         298 :                         timelib_set_relative((char **) &ptr, i, 1, s);
    1756             :                 }
    1757         298 :                 TIMELIB_DEINIT;
    1758         298 :                 return TIMELIB_RELATIVE;
    1759             :         }
    1760             : 
    1761             :         [ .,\t]
    1762             :         {
    1763        8101 :                 goto std;
    1764             :         }
    1765             : 
    1766             :         "\000"|"\n"
    1767             :         {
    1768        7930 :                 s->pos = cursor; s->line++;
    1769        7930 :                 goto std;
    1770             :         }
    1771             : 
    1772             :         any
    1773             :         {
    1774          83 :                 add_error(s, "Unexpected character");
    1775          83 :                 goto std;
    1776             :         }
    1777             : */
    1778             : }
    1779             : 
    1780             : /*!max:re2c */
    1781             : 
    1782        7976 : timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
    1783             : {
    1784             :         Scanner in;
    1785             :         int t;
    1786        7976 :         char *e = s + len - 1;
    1787             : 
    1788        7976 :         memset(&in, 0, sizeof(in));
    1789        7976 :         in.errors = malloc(sizeof(struct timelib_error_container));
    1790        7976 :         in.errors->warning_count = 0;
    1791        7976 :         in.errors->warning_messages = NULL;
    1792        7976 :         in.errors->error_count = 0;
    1793        7976 :         in.errors->error_messages = NULL;
    1794             : 
    1795        7976 :         if (len > 0) {
    1796       15911 :                 while (isspace(*s) && s < e) {
    1797           9 :                         s++;
    1798             :                 }
    1799       15912 :                 while (isspace(*e) && e > s) {
    1800          10 :                         e--;
    1801             :                 }
    1802             :         }
    1803        7976 :         if (e - s < 0) {
    1804          25 :                 in.time = timelib_time_ctor();
    1805          25 :                 add_error(&in, "Empty string");
    1806          25 :                 if (errors) {
    1807          25 :                         *errors = in.errors;
    1808             :                 } else {
    1809           0 :                         timelib_error_container_dtor(in.errors);
    1810             :                 }
    1811          25 :                 in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->dst = in.time->z = TIMELIB_UNSET;
    1812          25 :                 in.time->is_localtime = in.time->zone_type = 0;
    1813          25 :                 return in.time;
    1814             :         }
    1815        7951 :         e++;
    1816             : 
    1817        7951 :         in.str = malloc((e - s) + YYMAXFILL);
    1818        7951 :         memset(in.str, 0, (e - s) + YYMAXFILL);
    1819        7951 :         memcpy(in.str, s, (e - s));
    1820        7951 :         in.lim = in.str + (e - s) + YYMAXFILL;
    1821        7951 :         in.cur = in.str;
    1822        7951 :         in.time = timelib_time_ctor();
    1823        7951 :         in.time->y = TIMELIB_UNSET;
    1824        7951 :         in.time->d = TIMELIB_UNSET;
    1825        7951 :         in.time->m = TIMELIB_UNSET;
    1826        7951 :         in.time->h = TIMELIB_UNSET;
    1827        7951 :         in.time->i = TIMELIB_UNSET;
    1828        7951 :         in.time->s = TIMELIB_UNSET;
    1829        7951 :         in.time->f = TIMELIB_UNSET;
    1830        7951 :         in.time->z = TIMELIB_UNSET;
    1831        7951 :         in.time->dst = TIMELIB_UNSET;
    1832        7951 :         in.tzdb = tzdb;
    1833        7951 :         in.time->is_localtime = 0;
    1834        7951 :         in.time->zone_type = 0;
    1835             : 
    1836             :         do {
    1837       24085 :                 t = scan(&in, tz_get_wrapper);
    1838             : #ifdef DEBUG_PARSER
    1839             :                 printf("%d\n", t);
    1840             : #endif
    1841       24085 :         } while(t != EOI);
    1842             : 
    1843             :         /* do funky checking whether the parsed time was valid time */
    1844        7951 :         if (in.time->have_time && !timelib_valid_time( in.time->h, in.time->i, in.time->s)) {
    1845           4 :                 add_warning(&in, "The parsed time was invalid");
    1846             :         }
    1847             :         /* do funky checking whether the parsed date was valid date */
    1848        7951 :         if (in.time->have_date && !timelib_valid_date( in.time->y, in.time->m, in.time->d)) {
    1849           8 :                 add_warning(&in, "The parsed date was invalid");
    1850             :         }
    1851             : 
    1852        7951 :         free(in.str);
    1853        7951 :         if (errors) {
    1854        7762 :                 *errors = in.errors;
    1855             :         } else {
    1856         189 :                 timelib_error_container_dtor(in.errors);
    1857             :         }
    1858        7951 :         return in.time;
    1859             : }
    1860             : 
    1861             : #define TIMELIB_CHECK_NUMBER                                           \
    1862             :                 if (strchr("0123456789", *ptr) == NULL)                        \
    1863             :                 {                                                              \
    1864             :                         add_pbf_error(s, "Unexpected data found.", string, begin); \
    1865             :                 }
    1866             : 
    1867           7 : static void timelib_time_reset_fields(timelib_time *time)
    1868             : {
    1869           7 :         assert(time != NULL);
    1870             : 
    1871           7 :         time->y = 1970;
    1872           7 :         time->m = 1;
    1873           7 :         time->d = 1;
    1874           7 :         time->h = time->i = time->s = 0;
    1875           7 :         time->f = 0.0;
    1876           7 :         time->tz_info = NULL;
    1877           7 : }
    1878             : 
    1879           1 : static void timelib_time_reset_unset_fields(timelib_time *time)
    1880             : {
    1881           1 :         assert(time != NULL);
    1882             : 
    1883           1 :         if (time->y == TIMELIB_UNSET ) time->y = 1970;
    1884           1 :         if (time->m == TIMELIB_UNSET ) time->m = 1;
    1885           1 :         if (time->d == TIMELIB_UNSET ) time->d = 1;
    1886           1 :         if (time->h == TIMELIB_UNSET ) time->h = 0;
    1887           1 :         if (time->i == TIMELIB_UNSET ) time->i = 0;
    1888           1 :         if (time->s == TIMELIB_UNSET ) time->s = 0;
    1889           1 :         if (time->f == TIMELIB_UNSET ) time->f = 0.0;
    1890           1 : }
    1891             : 
    1892        1070 : timelib_time *timelib_parse_from_format(char *format, char *string, int len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
    1893             : {
    1894        1070 :         char       *fptr = format;
    1895        1070 :         char       *ptr = string;
    1896             :         char       *begin;
    1897             :         timelib_sll tmp;
    1898             :         Scanner in;
    1899        1070 :         Scanner *s = &in;
    1900        1070 :         int allow_extra = 0;
    1901             : 
    1902        1070 :         memset(&in, 0, sizeof(in));
    1903        1070 :         in.errors = malloc(sizeof(struct timelib_error_container));
    1904        1070 :         in.errors->warning_count = 0;
    1905        1070 :         in.errors->warning_messages = NULL;
    1906        1070 :         in.errors->error_count = 0;
    1907        1070 :         in.errors->error_messages = NULL;
    1908             : 
    1909        1070 :         in.time = timelib_time_ctor();
    1910        1070 :         in.time->y = TIMELIB_UNSET;
    1911        1070 :         in.time->d = TIMELIB_UNSET;
    1912        1070 :         in.time->m = TIMELIB_UNSET;
    1913        1070 :         in.time->h = TIMELIB_UNSET;
    1914        1070 :         in.time->i = TIMELIB_UNSET;
    1915        1070 :         in.time->s = TIMELIB_UNSET;
    1916        1070 :         in.time->f = TIMELIB_UNSET;
    1917        1070 :         in.time->z = TIMELIB_UNSET;
    1918        1070 :         in.time->dst = TIMELIB_UNSET;
    1919        1070 :         in.tzdb = tzdb;
    1920        1070 :         in.time->is_localtime = 0;
    1921        1070 :         in.time->zone_type = 0;
    1922             : 
    1923             :         /* Loop over the format string */
    1924        3689 :         while (*fptr && *ptr) {
    1925        1549 :                 begin = ptr;
    1926        1549 :                 switch (*fptr) {
    1927             :                         case 'D': /* three letter day */
    1928             :                         case 'l': /* full day */
    1929             :                                 {
    1930          15 :                                         const timelib_relunit* tmprel = 0;
    1931             : 
    1932          15 :                                         tmprel = timelib_lookup_relunit((char **) &ptr);
    1933          15 :                                         if (!tmprel) {
    1934           0 :                                                 add_pbf_error(s, "A textual day could not be found", string, begin);
    1935           0 :                                                 break;
    1936             :                                         } else {
    1937          15 :                                                 in.time->have_relative = 1; 
    1938          15 :                                                 in.time->relative.have_weekday_relative = 1;
    1939          15 :                                                 in.time->relative.weekday = tmprel->multiplier;
    1940          15 :                                                 in.time->relative.weekday_behavior = 1;
    1941             :                                         }
    1942             :                                 }
    1943          15 :                                 break;
    1944             :                         case 'd': /* two digit day, with leading zero */
    1945             :                         case 'j': /* two digit day, without leading zero */
    1946          50 :                                 TIMELIB_CHECK_NUMBER;
    1947          50 :                                 if ((s->time->d = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1948           0 :                                         add_pbf_error(s, "A two digit day could not be found", string, begin);
    1949             :                                 }
    1950          50 :                                 break;
    1951             :                         case 'S': /* day suffix, ignored, nor checked */
    1952           0 :                                 timelib_skip_day_suffix((char **) &ptr);
    1953           0 :                                 break;
    1954             :                         case 'z': /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */
    1955           1 :                                 TIMELIB_CHECK_NUMBER;
    1956           1 :                                 if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) {
    1957           0 :                                         add_pbf_error(s, "A three digit day-of-year could not be found", string, begin);
    1958             :                                 } else {
    1959           1 :                                         s->time->m = 1;
    1960           1 :                                         s->time->d = tmp + 1;
    1961           1 :                                         timelib_do_normalize(s->time);
    1962             :                                 }
    1963           1 :                                 break;
    1964             : 
    1965             :                         case 'm': /* two digit month, with leading zero */
    1966             :                         case 'n': /* two digit month, without leading zero */
    1967          38 :                                 TIMELIB_CHECK_NUMBER;
    1968          38 :                                 if ((s->time->m = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1969           0 :                                         add_pbf_error(s, "A two digit month could not be found", string, begin);
    1970             :                                 }
    1971          38 :                                 break;
    1972             :                         case 'M': /* three letter month */
    1973             :                         case 'F': /* full month */
    1974          13 :                                 tmp = timelib_lookup_month((char **) &ptr);
    1975          13 :                                 if (!tmp) {
    1976           0 :                                         add_pbf_error(s, "A textual month could not be found", string, begin);
    1977             :                                 } else {
    1978          13 :                                         s->time->m = tmp;
    1979             :                                 }
    1980          13 :                                 break;
    1981             :                         case 'y': /* two digit year */
    1982             :                                 {
    1983          18 :                                         int length = 0;
    1984          18 :                                         TIMELIB_CHECK_NUMBER;
    1985          18 :                                         if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == TIMELIB_UNSET) {
    1986           0 :                                                 add_pbf_error(s, "A two digit year could not be found", string, begin);
    1987             :                                         }
    1988          18 :                                         TIMELIB_PROCESS_YEAR(s->time->y, length);
    1989             :                                 }
    1990          18 :                                 break;
    1991             :                         case 'Y': /* four digit year */
    1992          34 :                                 TIMELIB_CHECK_NUMBER;
    1993          34 :                                 if ((s->time->y = timelib_get_nr((char **) &ptr, 4)) == TIMELIB_UNSET) {
    1994           0 :                                         add_pbf_error(s, "A four digit year could not be found", string, begin);
    1995             :                                 }
    1996          34 :                                 break;
    1997             :                         case 'g': /* two digit hour, with leading zero */
    1998             :                         case 'h': /* two digit hour, without leading zero */
    1999           1 :                                 TIMELIB_CHECK_NUMBER;
    2000           1 :                                 if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    2001           0 :                                         add_pbf_error(s, "A two digit hour could not be found", string, begin);
    2002             :                                 }
    2003           1 :                                 if (s->time->h > 12) {
    2004           0 :                                         add_pbf_error(s, "Hour can not be higher than 12", string, begin);
    2005             :                                 }
    2006           1 :                                 break;
    2007             :                         case 'G': /* two digit hour, with leading zero */
    2008             :                         case 'H': /* two digit hour, without leading zero */
    2009          25 :                                 TIMELIB_CHECK_NUMBER;
    2010          25 :                                 if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    2011           0 :                                         add_pbf_error(s, "A two digit hour could not be found", string, begin);
    2012             :                                 }
    2013          25 :                                 break;
    2014             :                         case 'a': /* am/pm/a.m./p.m. */
    2015             :                         case 'A': /* AM/PM/A.M./P.M. */
    2016           1 :                                 if (s->time->h == TIMELIB_UNSET) {
    2017           0 :                                         add_pbf_error(s, "Meridian can only come after an hour has been found", string, begin);
    2018           1 :                                 } else if ((tmp = timelib_meridian_with_check((char **) &ptr, s->time->h)) == TIMELIB_UNSET) {
    2019           0 :                                         add_pbf_error(s, "A meridian could not be found", string, begin);
    2020             :                                 } else {
    2021           1 :                                         s->time->h += tmp;
    2022             :                                 }
    2023           1 :                                 break;
    2024             :                         case 'i': /* two digit minute, with leading zero */
    2025             :                                 {
    2026             :                                         int length;
    2027             :                                         timelib_sll min;
    2028             : 
    2029          26 :                                         TIMELIB_CHECK_NUMBER;
    2030          26 :                                         min = timelib_get_nr_ex((char **) &ptr, 2, &length);
    2031          26 :                                         if (min == TIMELIB_UNSET || length != 2) {
    2032           0 :                                                 add_pbf_error(s, "A two digit minute could not be found", string, begin);
    2033             :                                         } else {
    2034          26 :                                                 s->time->i = min;
    2035             :                                         }
    2036             :                                 }
    2037          26 :                                 break;
    2038             :                         case 's': /* two digit second, with leading zero */
    2039             :                                 {
    2040             :                                         int length;
    2041             :                                         timelib_sll sec;
    2042             : 
    2043          26 :                                         TIMELIB_CHECK_NUMBER;
    2044          26 :                                         sec = timelib_get_nr_ex((char **) &ptr, 2, &length);
    2045          27 :                                         if (sec == TIMELIB_UNSET || length != 2) {
    2046           1 :                                                 add_pbf_error(s, "A two digit second could not be found", string, begin);
    2047             :                                         } else {
    2048          25 :                                                 s->time->s = sec;
    2049             :                                         }
    2050             :                                 }
    2051          26 :                                 break;
    2052             :                         case 'u': /* up to six digit millisecond */
    2053             :                                 {
    2054             :                                         double f;
    2055             :                                         char *tptr;
    2056             : 
    2057        1008 :                                         TIMELIB_CHECK_NUMBER;
    2058        1008 :                                         tptr = ptr;
    2059        1008 :                                         if ((f = timelib_get_nr((char **) &ptr, 6)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
    2060           0 :                                                 add_pbf_error(s, "A six digit millisecond could not be found", string, begin);
    2061             :                                         } else {
    2062        1008 :                                                 s->time->f = (f / pow(10, (ptr - tptr)));
    2063             :                                         }
    2064             :                                 }
    2065        1008 :                                 break;
    2066             :                         case ' ': /* any sort of whitespace (' ' and \t) */
    2067          72 :                                 timelib_eat_spaces((char **) &ptr);
    2068          72 :                                 break;
    2069             :                         case 'U': /* epoch seconds */
    2070           0 :                                 TIMELIB_CHECK_NUMBER;
    2071           0 :                                 TIMELIB_HAVE_RELATIVE();
    2072           0 :                                 tmp = timelib_get_unsigned_nr((char **) &ptr, 24);
    2073           0 :                                 s->time->y = 1970;
    2074           0 :                                 s->time->m = 1;
    2075           0 :                                 s->time->d = 1;
    2076           0 :                                 s->time->h = s->time->i = s->time->s = 0;
    2077           0 :                                 s->time->f = 0.0;
    2078           0 :                                 s->time->relative.s += tmp;
    2079           0 :                                 s->time->is_localtime = 1;
    2080           0 :                                 s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
    2081           0 :                                 s->time->z = 0;
    2082           0 :                                 s->time->dst = 0;
    2083           0 :                                 break;
    2084             : 
    2085             :                         case 'e': /* timezone */
    2086             :                         case 'P': /* timezone */
    2087             :                         case 'T': /* timezone */
    2088             :                         case 'O': /* timezone */
    2089             :                                 {
    2090             :                                         int tz_not_found;
    2091          32 :                                         s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    2092          32 :                                         if (tz_not_found) {
    2093           1 :                                                 add_pbf_error(s, "The timezone could not be found in the database", string, begin);
    2094             :                                         }
    2095             :                                 }
    2096          32 :                                 break;
    2097             : 
    2098             :                         case '#': /* separation symbol */
    2099           2 :                                 if (*ptr == ';' || *ptr == ':' || *ptr == '/' || *ptr == '.' || *ptr == ',' || *ptr == '-' || *ptr == '(' || *ptr == ')') {
    2100           1 :                                         ++ptr;
    2101             :                                 } else {
    2102           0 :                                         add_pbf_error(s, "The separation symbol ([;:/.,-]) could not be found", string, begin);
    2103             :                                 }
    2104           1 :                                 break;
    2105             : 
    2106             :                         case ';':
    2107             :                         case ':':
    2108             :                         case '/':
    2109             :                         case '.':
    2110             :                         case ',':
    2111             :                         case '-':
    2112             :                         case '(':
    2113             :                         case ')':
    2114         148 :                                 if (*ptr == *fptr) {
    2115         148 :                                         ++ptr;
    2116             :                                 } else {
    2117           0 :                                         add_pbf_error(s, "The separation symbol could not be found", string, begin);
    2118             :                                 }
    2119         148 :                                 break;
    2120             : 
    2121             :                         case '!': /* reset all fields to default */
    2122           6 :                                 timelib_time_reset_fields(s->time);
    2123           6 :                                 break; /* break intentionally not missing */
    2124             : 
    2125             :                         case '|': /* reset all fields to default when not set */
    2126           0 :                                 timelib_time_reset_unset_fields(s->time);
    2127           0 :                                 break; /* break intentionally not missing */
    2128             : 
    2129             :                         case '?': /* random char */
    2130           0 :                                 ++ptr;
    2131           0 :                                 break;
    2132             : 
    2133             :                         case '\\': /* escaped char */
    2134           4 :                                 fptr++;
    2135           4 :                                 if (*ptr == *fptr) {
    2136           4 :                                         ++ptr;
    2137             :                                 } else {
    2138           0 :                                         add_pbf_error(s, "The escaped character could not be found", string, begin);
    2139             :                                 }
    2140           4 :                                 break;
    2141             : 
    2142             :                         case '*': /* random chars until a separator or number ([ \t.,:;/-0123456789]) */
    2143           2 :                                 timelib_eat_until_separator((char **) &ptr);
    2144           2 :                                 break;
    2145             : 
    2146             :                         case '+': /* allow extra chars in the format */
    2147          12 :                                 allow_extra = 1;
    2148          12 :                                 break;
    2149             : 
    2150             :                         default:
    2151          16 :                                 if (*fptr != *ptr) {
    2152           0 :                                         add_pbf_error(s, "The format separator does not match", string, begin);
    2153             :                                 }
    2154          16 :                                 ptr++;
    2155             :                 }
    2156        1549 :                 fptr++;
    2157             :         }
    2158        1070 :         if (*ptr) {
    2159          12 :                 if (allow_extra) {
    2160           8 :                         add_pbf_warning(s, "Trailing data", string, ptr);
    2161             :                 } else {
    2162           4 :                         add_pbf_error(s, "Trailing data", string, ptr);
    2163             :                 }
    2164             :         }
    2165             :         /* ignore trailing +'s */
    2166        2144 :         while (*fptr == '+') {
    2167           4 :                 fptr++;
    2168             :         }
    2169        1070 :         if (*fptr) {
    2170             :                 /* Trailing | and ! specifiers are valid. */
    2171           5 :                 int done = 0;
    2172          15 :                 while (*fptr && !done) {
    2173           5 :                         switch (*fptr++) {
    2174             :                                 case '!': /* reset all fields to default */
    2175           1 :                                         timelib_time_reset_fields(s->time);
    2176           1 :                                         break;
    2177             : 
    2178             :                                 case '|': /* reset all fields to default when not set */
    2179           1 :                                         timelib_time_reset_unset_fields(s->time);
    2180           1 :                                         break;
    2181             : 
    2182             :                                 default:
    2183           3 :                                         add_pbf_error(s, "Data missing", string, ptr);
    2184           3 :                                         done = 1;
    2185             :                         }
    2186             :                 }
    2187             :         }
    2188             : 
    2189             :         /* clean up a bit */
    2190        1070 :         if (s->time->h != TIMELIB_UNSET || s->time->i != TIMELIB_UNSET || s->time->s != TIMELIB_UNSET) {
    2191          34 :                 if (s->time->h == TIMELIB_UNSET ) {
    2192           0 :                         s->time->h = 0;
    2193             :                 }
    2194          34 :                 if (s->time->i == TIMELIB_UNSET ) {
    2195           0 :                         s->time->i = 0;
    2196             :                 }
    2197          34 :                 if (s->time->s == TIMELIB_UNSET ) {
    2198           1 :                         s->time->s = 0;
    2199             :                 }
    2200             :         }
    2201             : 
    2202             :         /* do funky checking whether the parsed time was valid time */
    2203        1138 :         if (s->time->h != TIMELIB_UNSET && s->time->i != TIMELIB_UNSET &&
    2204          34 :                 s->time->s != TIMELIB_UNSET && 
    2205          34 :                 !timelib_valid_time( s->time->h, s->time->i, s->time->s)) {
    2206           0 :                 add_pbf_warning(s, "The parsed time was invalid", string, ptr);
    2207             :         }
    2208             :         /* do funky checking whether the parsed date was valid date */
    2209        1173 :         if (s->time->y != TIMELIB_UNSET && s->time->m != TIMELIB_UNSET &&
    2210          52 :                 s->time->d != TIMELIB_UNSET && 
    2211          51 :                 !timelib_valid_date( s->time->y, s->time->m, s->time->d)) {
    2212           0 :                 add_pbf_warning(s, "The parsed date was invalid", string, ptr);
    2213             :         }
    2214             : 
    2215        1070 :         if (errors) {
    2216        1070 :                 *errors = in.errors;
    2217             :         } else {
    2218           0 :                 timelib_error_container_dtor(in.errors);
    2219             :         }
    2220        1070 :         return in.time;
    2221             : }
    2222             : 
    2223        8606 : void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
    2224             : {
    2225        8606 :         if (!(options & TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
    2226        2871 :                 parsed->h = 0;
    2227        2871 :                 parsed->i = 0;
    2228        2871 :                 parsed->s = 0;
    2229        2871 :                 parsed->f = 0;
    2230             :         }
    2231        8606 :         if (parsed->y == TIMELIB_UNSET) parsed->y = now->y != TIMELIB_UNSET ? now->y : 0;
    2232        8606 :         if (parsed->d == TIMELIB_UNSET) parsed->d = now->d != TIMELIB_UNSET ? now->d : 0;
    2233        8606 :         if (parsed->m == TIMELIB_UNSET) parsed->m = now->m != TIMELIB_UNSET ? now->m : 0;
    2234        8606 :         if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0;
    2235        8606 :         if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0;
    2236        8606 :         if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0;
    2237        8606 :         if (parsed->f == TIMELIB_UNSET) parsed->f = now->f != TIMELIB_UNSET ? now->f : 0;
    2238        8606 :         if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0;
    2239        8606 :         if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0;
    2240             : 
    2241        8606 :         if (!parsed->tz_abbr) {
    2242        7339 :                 parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
    2243             :         }
    2244        8606 :         if (!parsed->tz_info) {
    2245        6666 :                 parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL;
    2246             :         }
    2247        8606 :         if (parsed->zone_type == 0 && now->zone_type != 0) {
    2248        5187 :                 parsed->zone_type = now->zone_type;
    2249             : /*              parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
    2250             :                 parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
    2251        5187 : */              parsed->is_localtime = 1;
    2252             :         }
    2253             : /*      timelib_dump_date(parsed, 2);
    2254             :         timelib_dump_date(now, 2);
    2255             : */
    2256        8606 : }
    2257             : 
    2258         430 : char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst)
    2259             : {
    2260             :         const timelib_tz_lookup_table *tp;
    2261             : 
    2262         430 :         tp = zone_search(abbr, gmtoffset, isdst);
    2263         430 :         if (tp) {
    2264         380 :                 return (tp->full_tz_name);
    2265             :         } else {
    2266          50 :                 return NULL;
    2267             :         }
    2268             : }
    2269             : 
    2270           4 : const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
    2271             : {
    2272           4 :         return timelib_timezone_lookup;
    2273             : }
    2274             : 
    2275             : #ifdef DEBUG_PARSER_STUB
    2276             : int main(void)
    2277             : {
    2278             :         timelib_time time = timelib_strtotime("May 12");
    2279             : 
    2280             :         printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
    2281             :                 time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
    2282             :         if (time.have_relative) {
    2283             :                 printf ("%3dY %3dM %3dD / %3dH %3dM %3dS", 
    2284             :                         time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
    2285             :         }
    2286             :         if (time.have_weekday_relative) {
    2287             :                 printf (" / %d", time.relative.weekday);
    2288             :         }
    2289             :         if (time.have_weeknr_day) {
    2290             :                 printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
    2291             :         }
    2292             :         return 0;                               
    2293             : }
    2294             : #endif
    2295             : 
    2296             : /*
    2297             :  * vim: syntax=c
    2298             :  */

Generated by: LCOV version 1.10

Generated at Sun, 20 Apr 2014 03:52:21 +0000 (4 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.