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: 905 1020 88.7 %
Date: 2014-07-21 Functions: 31 31 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:24 +0000 (11 days ago)

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