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: 897 1009 88.9 %
Date: 2014-09-19 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         234 : static void add_warning(Scanner *s, char *error)
     340             : {
     341         234 :         s->errors->warning_count++;
     342         234 :         s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
     343         234 :         s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
     344         234 :         s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
     345         234 :         s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
     346         234 : }
     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       16731 : static char *timelib_string(Scanner *s)
     435             : {
     436       16731 :         char *tmp = calloc(1, s->cur - s->tok + 1);
     437       16731 :         memcpy(tmp, s->tok, s->cur - s->tok);
     438             : 
     439       16731 :         return tmp;
     440             : }
     441             : 
     442       33836 : static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int *scanned_length)
     443             : {
     444             :         char *begin, *end, *str;
     445       33836 :         timelib_sll tmp_nr = TIMELIB_UNSET;
     446       33836 :         int len = 0;
     447             : 
     448       88642 :         while ((**ptr < '0') || (**ptr > '9')) {
     449       20976 :                 if (**ptr == '\0') {
     450           6 :                         return TIMELIB_UNSET;
     451             :                 }
     452       20970 :                 ++*ptr;
     453             :         }
     454       33830 :         begin = *ptr;
     455      152327 :         while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
     456       84667 :                 ++*ptr;
     457       84667 :                 ++len;
     458             :         }
     459       33830 :         end = *ptr;
     460       33830 :         if (scanned_length) {
     461        1245 :                 *scanned_length = end - begin;
     462             :         }
     463       33830 :         str = calloc(1, end - begin + 1);
     464       33830 :         memcpy(str, begin, end - begin);
     465       33830 :         tmp_nr = strtoll(str, NULL, 10);
     466       33830 :         free(str);
     467       33830 :         return tmp_nr;
     468             : }
     469             : 
     470       32587 : static timelib_sll timelib_get_nr(char **ptr, int max_length)
     471             : {
     472       32587 :         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        5988 : static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
     514             : {
     515        5988 :         timelib_ull dir = 1;
     516             : 
     517       12206 :         while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
     518         230 :                 if (**ptr == '\0') {
     519           0 :                         return TIMELIB_UNSET;
     520             :                 }
     521         230 :                 ++*ptr;
     522             :         }
     523             : 
     524       12329 :         while (**ptr == '+' || **ptr == '-')
     525             :         {
     526         353 :                 if (**ptr == '-') {
     527         174 :                         dir *= -1;
     528             :                 }
     529         353 :                 ++*ptr;
     530             :         }
     531        5988 :         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         186 : static timelib_long timelib_lookup_month(char **ptr)
     568             : {
     569             :         char *word;
     570         186 :         char *begin = *ptr, *end;
     571         186 :         timelib_long  value = 0;
     572             :         const timelib_lookup_table *tp;
     573             : 
     574        1060 :         while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
     575         688 :                 ++*ptr;
     576             :         }
     577         186 :         end = *ptr;
     578         186 :         word = calloc(1, end - begin + 1);
     579         186 :         memcpy(word, begin, end - begin);
     580             : 
     581        7068 :         for (tp = timelib_month_lookup; tp->name; tp++) {
     582        6882 :                 if (strcasecmp(word, tp->name) == 0) {
     583         196 :                         value = tp->value;
     584             :                 }
     585             :         }
     586             : 
     587         186 :         free(word);
     588         186 :         return value;
     589             : }
     590             : 
     591         167 : static timelib_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       64730 :         while (**ptr != '\0' && **ptr != ' ' && **ptr != ',' && **ptr != '\t' && **ptr != ';' && **ptr != ':' &&
     621       51107 :            **ptr != '/' && **ptr != '.' && **ptr != '-' && **ptr != '(' && **ptr != ')' ) {
     622       10221 :                 ++*ptr;
     623             :         }
     624        1701 :         end = *ptr;
     625        1701 :         word = calloc(1, end - begin + 1);
     626        1701 :         memcpy(word, begin, end - begin);
     627             : 
     628       39557 :         for (tp = timelib_relunit_lookup; tp->name; tp++) {
     629       39557 :                 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        3751 : const static timelib_tz_lookup_table* abbr_search(const char *word, timelib_long gmtoffset, int isdst)
     672             : {
     673        3751 :         int first_found = 0;
     674        3751 :         const timelib_tz_lookup_table  *tp, *first_found_elem = NULL;
     675             :         const timelib_tz_lookup_table  *fmp;
     676             : 
     677        3751 :         if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
     678         114 :                 return timelib_timezone_utc;
     679             :         }
     680             :         
     681     5710656 :         for (tp = timelib_timezone_lookup; tp->name; tp++) {
     682     5708280 :                 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        2376 :         if (first_found) {
     696           1 :                 return first_found_elem;
     697             :         }
     698             : 
     699             :         /* Still didn't find anything, let's find the zone solely based on
     700             :          * offset/isdst then */
     701      101514 :         for (fmp = timelib_timezone_fallbackmap; fmp->name; fmp++) {
     702       99167 :                 if ((fmp->gmtoffset * 60) == gmtoffset && fmp->type == isdst) {
     703          28 :                         return fmp;
     704             :                 }
     705             :         }
     706        2347 :         return NULL;
     707             : }
     708             : 
     709        3679 : static timelib_long timelib_lookup_abbr(char **ptr, int *dst, char **tz_abbr, int *found)
     710             : {
     711             :         char *word;
     712        3679 :         char *begin = *ptr, *end;
     713        3679 :         timelib_long  value = 0;
     714             :         const timelib_tz_lookup_table *tp;
     715             : 
     716       42789 :         while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') {
     717       35431 :                 ++*ptr;
     718             :         }
     719        3679 :         end = *ptr;
     720        3679 :         word = calloc(1, end - begin + 1);
     721        3679 :         memcpy(word, begin, end - begin);
     722             : 
     723        3679 :         if ((tp = abbr_search(word, -1, 0))) {
     724        1336 :                 value = -tp->gmtoffset / 60;
     725        1336 :                 *dst = tp->type;
     726        1336 :                 value += tp->type * 60;
     727        1336 :                 *found = 1;
     728             :         } else {
     729        2343 :                 *found = 0;
     730             :         }
     731             : 
     732        3679 :         *tz_abbr = word;
     733        3679 :         return value;
     734             : }
     735             : 
     736        3921 : timelib_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)
     737             : {
     738             :         timelib_tzinfo *res;
     739        3921 :         timelib_long            retval = 0;
     740             : 
     741        3921 :         *tz_not_found = 0;
     742             : 
     743        7844 :         while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
     744           2 :                 ++*ptr;
     745             :         }
     746        3921 :         if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) {
     747          11 :                 *ptr += 3;
     748             :         }
     749        3921 :         if (**ptr == '+') {
     750         127 :                 ++*ptr;
     751         127 :                 t->is_localtime = 1;
     752         127 :                 t->zone_type = TIMELIB_ZONETYPE_OFFSET;
     753         127 :                 *tz_not_found = 0;
     754         127 :                 t->dst = 0;
     755             : 
     756         127 :                 retval = -1 * timelib_parse_tz_cor(ptr);
     757        3794 :         } else if (**ptr == '-') {
     758         115 :                 ++*ptr;
     759         115 :                 t->is_localtime = 1;
     760         115 :                 t->zone_type = TIMELIB_ZONETYPE_OFFSET;
     761         115 :                 *tz_not_found = 0;
     762         115 :                 t->dst = 0;
     763             : 
     764         115 :                 retval = timelib_parse_tz_cor(ptr);
     765             :         } else {
     766        3679 :                 int found = 0;
     767        3679 :                 timelib_long offset = 0;
     768             :                 char *tz_abbr;
     769             : 
     770        3679 :                 t->is_localtime = 1;
     771             : 
     772             :                 /* First, we lookup by abbreviation only */
     773        3679 :                 offset = timelib_lookup_abbr(ptr, dst, &tz_abbr, &found);
     774        3679 :                 if (found) {
     775        1336 :                         t->zone_type = TIMELIB_ZONETYPE_ABBR;
     776        1336 :                         timelib_time_tz_abbr_update(t, tz_abbr);
     777             :                 }
     778             : 
     779             :                 /* Otherwise, we look if we have a TimeZone identifier */
     780        3679 :                 if (!found || strcmp("UTC", tz_abbr) == 0) {
     781        2388 :                         if ((res = tz_wrapper(tz_abbr, tzdb)) != NULL) {
     782        2294 :                                 t->tz_info = res;
     783        2294 :                                 t->zone_type = TIMELIB_ZONETYPE_ID;
     784        2294 :                                 found++;
     785             :                         }
     786             :                 }
     787        3679 :                 free(tz_abbr);
     788        3679 :                 *tz_not_found = (found == 0);
     789        3679 :                 retval = offset;
     790             :         }
     791        7842 :         while (**ptr == ')') {
     792           0 :                 ++*ptr;
     793             :         }
     794        3921 :         return retval;
     795             : }
     796             : 
     797             : #define timelib_split_free(arg) {       \
     798             :         int i;                         \
     799             :         for (i = 0; i < arg.c; i++) {  \
     800             :                 free(arg.v[i]);            \
     801             :         }                              \
     802             :         if (arg.v) {                   \
     803             :                 free(arg.v);               \
     804             :         }                              \
     805             : }
     806             : 
     807       25158 : static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
     808             : {
     809       25158 :         uchar *cursor = s->cur;
     810       25158 :         char *str, *ptr = NULL;
     811             :                 
     812             : std:
     813       41864 :         s->tok = cursor;
     814       41864 :         s->len = 0;
     815             : /*!re2c
     816             : any = [\000-\377];
     817             : 
     818             : space = [ \t]+;
     819             : frac = "."[0-9]+;
     820             : 
     821             : ago = 'ago';
     822             : 
     823             : hour24 = [01]?[0-9] | "2"[0-4];
     824             : hour24lz = [01][0-9] | "2"[0-4];
     825             : hour12 = "0"?[1-9] | "1"[0-2];
     826             : minute = [0-5]?[0-9];
     827             : minutelz = [0-5][0-9];
     828             : second = minute | "60";
     829             : secondlz = minutelz | "60";
     830             : meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
     831             : tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/-][A-Za-z]+)+;
     832             : tzcorrection = "GMT"? [+-] hour24 ":"? minute?;
     833             : 
     834             : daysuf = "st" | "nd" | "rd" | "th";
     835             : 
     836             : month = "0"? [0-9] | "1"[0-2];
     837             : day   = (([0-2]?[0-9]) | ("3"[01])) daysuf?;
     838             : year  = [0-9]{1,4};
     839             : year2 = [0-9]{2};
     840             : year4 = [0-9]{4};
     841             : year4withsign = [+-]? [0-9]{4};
     842             : 
     843             : dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
     844             : weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
     845             : 
     846             : monthlz = "0" [0-9] | "1" [0-2];
     847             : daylz   = "0" [0-9] | [1-2][0-9] | "3" [01];
     848             : 
     849             : dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
     850             : dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
     851             : dayspecial = 'weekday' | 'weekdays';
     852             : daytext = dayfull | dayabbr | dayspecial;
     853             : 
     854             : monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
     855             : monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
     856             : monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
     857             : monthtext = monthfull | monthabbr | monthroman;
     858             : 
     859             : /* Time formats */
     860             : timetiny12 = hour12 space? meridian;
     861             : timeshort12 = hour12[:.]minutelz space? meridian;
     862             : timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
     863             : 
     864             : timeshort24 = 't'? hour24[:.]minute;
     865             : timelong24 =  't'? hour24[:.]minute[:.]second;
     866             : iso8601long =  't'? hour24 [:.] minute [:.] second frac;
     867             : 
     868             : /* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
     869             : iso8601normtz =  't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
     870             : /* iso8601longtz =  hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
     871             : 
     872             : gnunocolon       = 't'? hour24lz minutelz;
     873             : /* gnunocolontz     = hour24lz minutelz space? (tzcorrection | tz); */
     874             : iso8601nocolon   = 't'? hour24lz minutelz secondlz; 
     875             : /* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
     876             : 
     877             : /* Date formats */
     878             : americanshort    = month "/" day;
     879             : american         = month "/" day "/" year;
     880             : iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
     881             : dateslash        = year4 "/" month "/" day;
     882             : iso8601date4     = year4withsign "-" monthlz "-" daylz;
     883             : iso8601date2     = year2 "-" monthlz "-" daylz;
     884             : gnudateshorter   = year4 "-" month;
     885             : gnudateshort     = year "-" month "-" day;
     886             : pointeddate4     = day [.\t-] month [.-] year4;
     887             : pointeddate2     = day [.\t] month "." year2;
     888             : datefull         = day ([ \t.-])* monthtext ([ \t.-])* year;
     889             : datenoday        = monthtext ([ .\t-])* year4;
     890             : datenodayrev     = year4 ([ .\t-])* monthtext;
     891             : datetextual      = monthtext ([ .\t-])* day [,.stndrh\t ]+ year;
     892             : datenoyear       = monthtext ([ .\t-])* day [,.stndrh\t ]*;
     893             : datenoyearrev    = day ([ .\t-])* monthtext;
     894             : datenocolon      = year4 monthlz daylz;
     895             : 
     896             : /* Special formats */
     897             : soap             = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection?;
     898             : xmlrpc           = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
     899             : xmlrpcnocolon    = year4 monthlz daylz 't' hour24 minutelz secondlz;
     900             : wddx             = year4 "-" month "-" day "T" hour24 ":" minute ":" second;
     901             : pgydotd          = year4 "."? dayofyear;
     902             : pgtextshort      = monthabbr "-" daylz "-" year;
     903             : pgtextreverse    = year "-" monthabbr "-" daylz;
     904             : mssqltime        = hour12 ":" minutelz ":" secondlz [:.] [0-9]+ meridian;
     905             : isoweekday       = year4 "-"? "W" weekofyear "-"? [0-7];
     906             : isoweek          = year4 "-"? "W" weekofyear;
     907             : exif             = year4 ":" monthlz ":" daylz " " hour24lz ":" minutelz ":" secondlz;
     908             : firstdayof       = 'first day of';
     909             : lastdayof        = 'last day of';
     910             : backof           = 'back of ' hour24 space? meridian?;
     911             : frontof          = 'front of ' hour24 space? meridian?;
     912             : 
     913             : /* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
     914             : clf              = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
     915             : 
     916             : /* Timestamp format: @1126396800 */
     917             : timestamp        = "@" "-"? [0-9]+;
     918             : 
     919             : /* To fix some ambiguities */
     920             : dateshortwithtimeshort12  = datenoyear timeshort12;
     921             : dateshortwithtimelong12   = datenoyear timelong12;
     922             : dateshortwithtimeshort  = datenoyear timeshort24;
     923             : dateshortwithtimelong   = datenoyear timelong24;
     924             : dateshortwithtimelongtz = datenoyear iso8601normtz;
     925             : 
     926             : /*
     927             :  * Relative regexps
     928             :  */
     929             : reltextnumber = 'first'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'eighth'|'ninth'|'tenth'|'eleventh'|'twelfth';
     930             : reltexttext = 'next'|'last'|'previous'|'this';
     931             : reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'fortnight'|'forthnight'|'month'|'year') 's'?) | 'weeks' | daytext;
     932             : 
     933             : relnumber = ([+-]*[ \t]*[0-9]+);
     934             : relative = relnumber space? (reltextunit | 'week' );
     935             : relativetext = (reltextnumber|reltexttext) space reltextunit;
     936             : relativetextweek = reltexttext space 'week';
     937             : 
     938             : weekdayof        = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of';
     939             : 
     940             : */
     941             : 
     942             : /*!re2c
     943             :         /* so that vim highlights correctly */
     944             :         'yesterday'
     945             :         {
     946             :                 DEBUG_OUTPUT("yesterday");
     947           1 :                 TIMELIB_INIT;
     948           1 :                 TIMELIB_HAVE_RELATIVE();
     949           1 :                 TIMELIB_UNHAVE_TIME();
     950             : 
     951           1 :                 s->time->relative.d = -1;
     952           1 :                 TIMELIB_DEINIT;
     953           1 :                 return TIMELIB_RELATIVE;
     954             :         }
     955             : 
     956             :         'now'
     957             :         {
     958             :                 DEBUG_OUTPUT("now");
     959          60 :                 TIMELIB_INIT;
     960             : 
     961          60 :                 TIMELIB_DEINIT;
     962          60 :                 return TIMELIB_RELATIVE;
     963             :         }
     964             : 
     965             :         'noon'
     966             :         {
     967             :                 DEBUG_OUTPUT("noon");
     968           2 :                 TIMELIB_INIT;
     969           2 :                 TIMELIB_UNHAVE_TIME();
     970           2 :                 TIMELIB_HAVE_TIME();
     971           2 :                 s->time->h = 12;
     972             : 
     973           2 :                 TIMELIB_DEINIT;
     974           2 :                 return TIMELIB_RELATIVE;
     975             :         }
     976             : 
     977             :         'midnight' | 'today'
     978             :         {
     979             :                 DEBUG_OUTPUT("midnight | today");
     980           3 :                 TIMELIB_INIT;
     981           3 :                 TIMELIB_UNHAVE_TIME();
     982             : 
     983           3 :                 TIMELIB_DEINIT;
     984           3 :                 return TIMELIB_RELATIVE;
     985             :         }
     986             : 
     987             :         'tomorrow'
     988             :         {
     989             :                 DEBUG_OUTPUT("tomorrow");
     990           3 :                 TIMELIB_INIT;
     991           3 :                 TIMELIB_HAVE_RELATIVE();
     992           3 :                 TIMELIB_UNHAVE_TIME();
     993             : 
     994           3 :                 s->time->relative.d = 1;
     995           3 :                 TIMELIB_DEINIT;
     996           3 :                 return TIMELIB_RELATIVE;
     997             :         }
     998             : 
     999             :         timestamp
    1000             :         {
    1001             :                 timelib_ull i;
    1002             : 
    1003         213 :                 TIMELIB_INIT;
    1004         213 :                 TIMELIB_HAVE_RELATIVE();
    1005         213 :                 TIMELIB_UNHAVE_DATE();
    1006         213 :                 TIMELIB_UNHAVE_TIME();
    1007         213 :                 TIMELIB_HAVE_TZ();
    1008             : 
    1009         213 :                 i = timelib_get_unsigned_nr((char **) &ptr, 24);
    1010         213 :                 s->time->y = 1970;
    1011         213 :                 s->time->m = 1;
    1012         213 :                 s->time->d = 1;
    1013         213 :                 s->time->h = s->time->i = s->time->s = 0;
    1014         213 :                 s->time->f = 0.0;
    1015         213 :                 s->time->relative.s += i;
    1016         213 :                 s->time->is_localtime = 1;
    1017         213 :                 s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
    1018         213 :                 s->time->z = 0;
    1019         213 :                 s->time->dst = 0;
    1020             : 
    1021         213 :                 TIMELIB_DEINIT;
    1022         213 :                 return TIMELIB_RELATIVE;
    1023             :         }
    1024             : 
    1025             :         firstdayof | lastdayof
    1026             :         {
    1027             :                 DEBUG_OUTPUT("firstdayof | lastdayof");
    1028          11 :                 TIMELIB_INIT;
    1029          11 :                 TIMELIB_HAVE_RELATIVE();
    1030             : 
    1031             :                 /* skip "last day of" or "first day of" */
    1032          16 :                 if (*ptr == 'l' || *ptr == 'L') {
    1033           5 :                         s->time->relative.first_last_day_of = 2;
    1034             :                 } else {
    1035           6 :                         s->time->relative.first_last_day_of = 1;
    1036             :                 }
    1037             : 
    1038          11 :                 TIMELIB_DEINIT;
    1039          11 :                 return TIMELIB_LF_DAY_OF_MONTH;
    1040             :         }
    1041             : 
    1042             :         backof | frontof
    1043             :         {
    1044             :                 DEBUG_OUTPUT("backof | frontof");
    1045           5 :                 TIMELIB_INIT;
    1046           5 :                 TIMELIB_UNHAVE_TIME();
    1047           5 :                 TIMELIB_HAVE_TIME();
    1048             : 
    1049           5 :                 if (*ptr == 'b') {
    1050           3 :                         s->time->h = timelib_get_nr((char **) &ptr, 2);
    1051           3 :                         s->time->i = 15;
    1052             :                 } else {
    1053           2 :                         s->time->h = timelib_get_nr((char **) &ptr, 2) - 1;
    1054           2 :                         s->time->i = 45;
    1055             :                 }
    1056           5 :                 if (*ptr != '\0' ) {
    1057           1 :                         timelib_eat_spaces((char **) &ptr);
    1058           1 :                         s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1059             :                 }
    1060             : 
    1061           5 :                 TIMELIB_DEINIT;
    1062           5 :                 return TIMELIB_LF_DAY_OF_MONTH;
    1063             :         }
    1064             : 
    1065             :         weekdayof
    1066             :         {
    1067             :                 timelib_sll i;
    1068           5 :                 int         behavior = 0;
    1069             :                 DEBUG_OUTPUT("weekdayof");
    1070           5 :                 TIMELIB_INIT;
    1071           5 :                 TIMELIB_HAVE_RELATIVE();
    1072           5 :                 TIMELIB_HAVE_SPECIAL_RELATIVE();
    1073             : 
    1074           5 :                 i = timelib_get_relative_text((char **) &ptr, &behavior);
    1075           5 :                 timelib_eat_spaces((char **) &ptr);
    1076           5 :                 if (i > 0) { /* first, second... etc */
    1077           4 :                         s->time->relative.special.type = TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH;
    1078           4 :                         timelib_set_relative((char **) &ptr, i, 1, s);
    1079             :                 } else { /* last */
    1080           1 :                         s->time->relative.special.type = TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH;
    1081           1 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1082             :                 }
    1083           5 :                 TIMELIB_DEINIT;
    1084           5 :                 return TIMELIB_WEEK_DAY_OF_MONTH;
    1085             :         }
    1086             : 
    1087             :         timetiny12 | timeshort12 | timelong12
    1088             :         {
    1089             :                 DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
    1090          22 :                 TIMELIB_INIT;
    1091          22 :                 TIMELIB_HAVE_TIME();
    1092          22 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1093          22 :                 if (*ptr == ':' || *ptr == '.') {
    1094          13 :                         s->time->i = timelib_get_nr((char **) &ptr, 2);
    1095          13 :                         if (*ptr == ':' || *ptr == '.') {
    1096           4 :                                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1097             :                         }
    1098             :                 }
    1099          22 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1100          22 :                 TIMELIB_DEINIT;
    1101          22 :                 return TIMELIB_TIME12;
    1102             :         }
    1103             : 
    1104             :         mssqltime
    1105             :         {
    1106             :                 DEBUG_OUTPUT("mssqltime");
    1107           0 :                 TIMELIB_INIT;
    1108           0 :                 TIMELIB_HAVE_TIME();
    1109           0 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1110           0 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1111           0 :                 if (*ptr == ':' || *ptr == '.') {
    1112           0 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1113             : 
    1114           0 :                         if (*ptr == ':' || *ptr == '.') {
    1115           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1116             :                         }
    1117             :                 }
    1118           0 :                 timelib_eat_spaces((char **) &ptr);
    1119           0 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1120           0 :                 TIMELIB_DEINIT;
    1121           0 :                 return TIMELIB_TIME24_WITH_ZONE;
    1122             :         }
    1123             : 
    1124             :         timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
    1125             :         {
    1126             :                 int tz_not_found;
    1127             :                 DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
    1128        4397 :                 TIMELIB_INIT;
    1129        4397 :                 TIMELIB_HAVE_TIME();
    1130        4394 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1131        4394 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1132        4394 :                 if (*ptr == ':' || *ptr == '.') {
    1133        3356 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1134             : 
    1135        3356 :                         if (*ptr == '.') {
    1136          24 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1137             :                         }
    1138             :                 }
    1139             : 
    1140        4394 :                 if (*ptr != '\0') {
    1141           0 :                         s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1142           0 :                         if (tz_not_found) {
    1143           0 :                                 add_error(s, "The timezone could not be found in the database");
    1144             :                         }
    1145             :                 }
    1146        4394 :                 TIMELIB_DEINIT;
    1147        4394 :                 return TIMELIB_TIME24_WITH_ZONE;
    1148             :         }
    1149             : 
    1150             :         gnunocolon
    1151             :         {
    1152             :                 DEBUG_OUTPUT("gnunocolon");
    1153          22 :                 TIMELIB_INIT;
    1154          22 :                 switch (s->time->have_time) {
    1155             :                         case 0:
    1156          16 :                                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1157          16 :                                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1158          16 :                                 s->time->s = 0;
    1159          16 :                                 break;
    1160             :                         case 1:
    1161           6 :                                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1162           6 :                                 break;
    1163             :                         default:
    1164           0 :                                 TIMELIB_DEINIT;
    1165           0 :                                 add_error(s, "Double time specification");
    1166           0 :                                 return TIMELIB_ERROR;
    1167             :                 }
    1168          22 :                 s->time->have_time++;
    1169          22 :                 TIMELIB_DEINIT;
    1170          22 :                 return TIMELIB_GNU_NOCOLON;
    1171             :         }
    1172             : /*
    1173             :         gnunocolontz
    1174             :         {
    1175             :                 DEBUG_OUTPUT("gnunocolontz");
    1176             :                 TIMELIB_INIT;
    1177             :                 switch (s->time->have_time) {
    1178             :                         case 0:
    1179             :                                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1180             :                                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1181             :                                 s->time->s = 0;
    1182             :                                 s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb, tz_get_wrapper);
    1183             :                                 break;
    1184             :                         case 1:
    1185             :                                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1186             :                                 break;
    1187             :                         default:
    1188             :                                 TIMELIB_DEINIT;
    1189             :                                 return TIMELIB_ERROR;
    1190             :                 }
    1191             :                 s->time->have_time++;
    1192             :                 TIMELIB_DEINIT;
    1193             :                 return TIMELIB_GNU_NOCOLON_TZ;
    1194             :         }
    1195             : */
    1196             :         iso8601nocolon /*| iso8601nocolontz*/
    1197             :         {
    1198             :                 int tz_not_found;
    1199             :                 DEBUG_OUTPUT("iso8601nocolon");
    1200           8 :                 TIMELIB_INIT;
    1201           8 :                 TIMELIB_HAVE_TIME();
    1202           8 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1203           8 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1204           8 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1205             : 
    1206           8 :                 if (*ptr != '\0') {
    1207           0 :                         s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1208           0 :                         if (tz_not_found) {
    1209           0 :                                 add_error(s, "The timezone could not be found in the database");
    1210             :                         }
    1211             :                 }
    1212           8 :                 TIMELIB_DEINIT;
    1213           8 :                 return TIMELIB_ISO_NOCOLON;
    1214             :         }
    1215             : 
    1216             :         americanshort | american
    1217             :         {
    1218           4 :                 int length = 0;
    1219             :                 DEBUG_OUTPUT("americanshort | american");
    1220           4 :                 TIMELIB_INIT;
    1221           4 :                 TIMELIB_HAVE_DATE();
    1222           4 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1223           4 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1224           4 :                 if (*ptr == '/') {
    1225           4 :                         s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1226           4 :                         TIMELIB_PROCESS_YEAR(s->time->y, length);
    1227             :                 }
    1228           4 :                 TIMELIB_DEINIT;
    1229           4 :                 return TIMELIB_AMERICAN;
    1230             :         }
    1231             : 
    1232             :         iso8601date4 | iso8601dateslash | dateslash
    1233             :         {
    1234             :                 DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
    1235        5284 :                 TIMELIB_INIT;
    1236        5284 :                 TIMELIB_HAVE_DATE();
    1237        5284 :                 s->time->y = timelib_get_unsigned_nr((char **) &ptr, 4);
    1238        5284 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1239        5284 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1240        5284 :                 TIMELIB_DEINIT;
    1241        5284 :                 return TIMELIB_ISO_DATE;
    1242             :         }
    1243             : 
    1244             :         iso8601date2
    1245             :         {
    1246           0 :                 int length = 0;
    1247             :                 DEBUG_OUTPUT("iso8601date2");
    1248           0 :                 TIMELIB_INIT;
    1249           0 :                 TIMELIB_HAVE_DATE();
    1250           0 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1251           0 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1252           0 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1253           0 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1254           0 :                 TIMELIB_DEINIT;
    1255           0 :                 return TIMELIB_ISO_DATE;
    1256             :         }
    1257             : 
    1258             :         gnudateshorter
    1259             :         {
    1260           6 :                 int length = 0;
    1261             :                 DEBUG_OUTPUT("gnudateshorter");
    1262           6 :                 TIMELIB_INIT;
    1263           6 :                 TIMELIB_HAVE_DATE();
    1264           6 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1265           6 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1266           6 :                 s->time->d = 1;
    1267           6 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1268           6 :                 TIMELIB_DEINIT;
    1269           6 :                 return TIMELIB_ISO_DATE;
    1270             :         }
    1271             : 
    1272             :         gnudateshort
    1273             :         {
    1274        1022 :                 int length = 0;
    1275             :                 DEBUG_OUTPUT("gnudateshort");
    1276        1022 :                 TIMELIB_INIT;
    1277        1022 :                 TIMELIB_HAVE_DATE();
    1278        1022 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1279        1022 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1280        1022 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1281        1022 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1282        1022 :                 TIMELIB_DEINIT;
    1283        1022 :                 return TIMELIB_ISO_DATE;
    1284             :         }
    1285             : 
    1286             :         datefull
    1287             :         {
    1288          86 :                 int length = 0;
    1289             :                 DEBUG_OUTPUT("datefull");
    1290          86 :                 TIMELIB_INIT;
    1291          86 :                 TIMELIB_HAVE_DATE();
    1292          86 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1293          86 :                 timelib_skip_day_suffix((char **) &ptr);
    1294          86 :                 s->time->m = timelib_get_month((char **) &ptr);
    1295          86 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1296          86 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1297          86 :                 TIMELIB_DEINIT;
    1298          86 :                 return TIMELIB_DATE_FULL;
    1299             :         }
    1300             : 
    1301             :         pointeddate4
    1302             :         {
    1303             :                 DEBUG_OUTPUT("pointed date YYYY");
    1304           5 :                 TIMELIB_INIT;
    1305           5 :                 TIMELIB_HAVE_DATE();
    1306           5 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1307           5 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1308           5 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1309           5 :                 TIMELIB_DEINIT;
    1310           5 :                 return TIMELIB_DATE_FULL_POINTED;
    1311             :         }
    1312             : 
    1313             :         pointeddate2
    1314             :         {
    1315           0 :                 int length = 0;
    1316             :                 DEBUG_OUTPUT("pointed date YY");
    1317           0 :                 TIMELIB_INIT;
    1318           0 :                 TIMELIB_HAVE_DATE();
    1319           0 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1320           0 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1321           0 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
    1322           0 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1323           0 :                 TIMELIB_DEINIT;
    1324           0 :                 return TIMELIB_DATE_FULL_POINTED;
    1325             :         }
    1326             : 
    1327             :         datenoday
    1328             :         {
    1329          28 :                 int length = 0;
    1330             :                 DEBUG_OUTPUT("datenoday");
    1331          28 :                 TIMELIB_INIT;
    1332          28 :                 TIMELIB_HAVE_DATE();
    1333          28 :                 s->time->m = timelib_get_month((char **) &ptr);
    1334          28 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1335          28 :                 s->time->d = 1;
    1336          28 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1337          28 :                 TIMELIB_DEINIT;
    1338          28 :                 return TIMELIB_DATE_NO_DAY;
    1339             :         }
    1340             : 
    1341             :         datenodayrev
    1342             :         {
    1343           1 :                 int length = 0;
    1344             :                 DEBUG_OUTPUT("datenodayrev");
    1345           1 :                 TIMELIB_INIT;
    1346           1 :                 TIMELIB_HAVE_DATE();
    1347           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1348           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1349           1 :                 s->time->d = 1;
    1350           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1351           1 :                 TIMELIB_DEINIT;
    1352           1 :                 return TIMELIB_DATE_NO_DAY;
    1353             :         }
    1354             : 
    1355             :         datetextual | datenoyear
    1356             :         {
    1357          29 :                 int length = 0;
    1358             :                 DEBUG_OUTPUT("datetextual | datenoyear");
    1359          29 :                 TIMELIB_INIT;
    1360          29 :                 TIMELIB_HAVE_DATE();
    1361          29 :                 s->time->m = timelib_get_month((char **) &ptr);
    1362          29 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1363          29 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1364          29 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1365          29 :                 TIMELIB_DEINIT;
    1366          29 :                 return TIMELIB_DATE_TEXT;
    1367             :         }
    1368             : 
    1369             :         datenoyearrev
    1370             :         {
    1371             :                 DEBUG_OUTPUT("datenoyearrev");
    1372           3 :                 TIMELIB_INIT;
    1373           3 :                 TIMELIB_HAVE_DATE();
    1374           3 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1375           3 :                 timelib_skip_day_suffix((char **) &ptr);
    1376           3 :                 s->time->m = timelib_get_month((char **) &ptr);
    1377           3 :                 TIMELIB_DEINIT;
    1378           3 :                 return TIMELIB_DATE_TEXT;
    1379             :         }
    1380             : 
    1381             :         datenocolon
    1382             :         {
    1383             :                 DEBUG_OUTPUT("datenocolon");
    1384           7 :                 TIMELIB_INIT;
    1385           7 :                 TIMELIB_HAVE_DATE();
    1386           7 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1387           7 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1388           7 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1389           7 :                 TIMELIB_DEINIT;
    1390           7 :                 return TIMELIB_DATE_NOCOLON;
    1391             :         }
    1392             : 
    1393             :         xmlrpc | xmlrpcnocolon | soap | wddx | exif
    1394             :         {
    1395             :                 int tz_not_found;
    1396             :                 DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
    1397          55 :                 TIMELIB_INIT;
    1398          55 :                 TIMELIB_HAVE_TIME();
    1399          55 :                 TIMELIB_HAVE_DATE();
    1400          55 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1401          55 :                 s->time->m = timelib_get_nr((char **) &ptr, 2);
    1402          55 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1403          55 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1404          55 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1405          55 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1406          55 :                 if (*ptr == '.') {
    1407           1 :                         s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
    1408           1 :                         if (*ptr) { /* timezone is optional */
    1409           0 :                                 s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1410           0 :                                 if (tz_not_found) {
    1411           0 :                                         add_error(s, "The timezone could not be found in the database");
    1412             :                                 }
    1413             :                         }
    1414             :                 }
    1415          55 :                 TIMELIB_DEINIT;
    1416          55 :                 return TIMELIB_XMLRPC_SOAP;
    1417             :         }
    1418             : 
    1419             :         pgydotd
    1420             :         {
    1421           1 :                 int length = 0;
    1422             :                 DEBUG_OUTPUT("pgydotd");
    1423           1 :                 TIMELIB_INIT;
    1424           1 :                 TIMELIB_HAVE_DATE();
    1425           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1426           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 3);
    1427           1 :                 s->time->m = 1;
    1428           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1429           1 :                 TIMELIB_DEINIT;
    1430           1 :                 return TIMELIB_PG_YEARDAY;
    1431             :         }
    1432             : 
    1433             :         isoweekday
    1434             :         {
    1435             :                 timelib_sll w, d;
    1436             :                 DEBUG_OUTPUT("isoweekday");
    1437           4 :                 TIMELIB_INIT;
    1438           4 :                 TIMELIB_HAVE_DATE();
    1439           4 :                 TIMELIB_HAVE_RELATIVE();
    1440             :                 
    1441           4 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1442           4 :                 w = timelib_get_nr((char **) &ptr, 2);
    1443           4 :                 d = timelib_get_nr((char **) &ptr, 1);
    1444           4 :                 s->time->m = 1;
    1445           4 :                 s->time->d = 1;
    1446           4 :                 s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
    1447             : 
    1448           4 :                 TIMELIB_DEINIT;
    1449           4 :                 return TIMELIB_ISO_WEEK;
    1450             :         }
    1451             : 
    1452             :         isoweek
    1453             :         {
    1454             :                 timelib_sll w, d;
    1455             :                 DEBUG_OUTPUT("isoweek");
    1456           1 :                 TIMELIB_INIT;
    1457           1 :                 TIMELIB_HAVE_DATE();
    1458           1 :                 TIMELIB_HAVE_RELATIVE();
    1459             :                 
    1460           1 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1461           1 :                 w = timelib_get_nr((char **) &ptr, 2);
    1462           1 :                 d = 1;
    1463           1 :                 s->time->m = 1;
    1464           1 :                 s->time->d = 1;
    1465           1 :                 s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
    1466             : 
    1467           1 :                 TIMELIB_DEINIT;
    1468           1 :                 return TIMELIB_ISO_WEEK;
    1469             :         }
    1470             : 
    1471             :         pgtextshort
    1472             :         {
    1473           1 :                 int length = 0;
    1474             :                 DEBUG_OUTPUT("pgtextshort");
    1475           1 :                 TIMELIB_INIT;
    1476           1 :                 TIMELIB_HAVE_DATE();
    1477           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1478           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1479           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1480           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1481           1 :                 TIMELIB_DEINIT;
    1482           1 :                 return TIMELIB_PG_TEXT;
    1483             :         }
    1484             : 
    1485             :         pgtextreverse
    1486             :         {
    1487           1 :                 int length = 0;
    1488             :                 DEBUG_OUTPUT("pgtextreverse");
    1489           1 :                 TIMELIB_INIT;
    1490           1 :                 TIMELIB_HAVE_DATE();
    1491           1 :                 s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
    1492           1 :                 s->time->m = timelib_get_month((char **) &ptr);
    1493           1 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1494           1 :                 TIMELIB_PROCESS_YEAR(s->time->y, length);
    1495           1 :                 TIMELIB_DEINIT;
    1496           1 :                 return TIMELIB_PG_TEXT;
    1497             :         }
    1498             : 
    1499             :         clf
    1500             :         {
    1501             :                 int tz_not_found;
    1502             :                 DEBUG_OUTPUT("clf");
    1503           2 :                 TIMELIB_INIT;
    1504           2 :                 TIMELIB_HAVE_TIME();
    1505           2 :                 TIMELIB_HAVE_DATE();
    1506           2 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1507           2 :                 s->time->m = timelib_get_month((char **) &ptr);
    1508           2 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1509           2 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1510           2 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1511           2 :                 s->time->s = timelib_get_nr((char **) &ptr, 2);
    1512           2 :                 s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1513           2 :                 if (tz_not_found) {
    1514           0 :                         add_error(s, "The timezone could not be found in the database");
    1515             :                 }
    1516           2 :                 TIMELIB_DEINIT;
    1517           2 :                 return TIMELIB_CLF;
    1518             :         }
    1519             : 
    1520             :         year4
    1521             :         {
    1522             :                 DEBUG_OUTPUT("year4");
    1523           1 :                 TIMELIB_INIT;
    1524           1 :                 s->time->y = timelib_get_nr((char **) &ptr, 4);
    1525           1 :                 TIMELIB_DEINIT;
    1526           1 :                 return TIMELIB_CLF;
    1527             :         }
    1528             : 
    1529             :         ago
    1530             :         {
    1531             :                 DEBUG_OUTPUT("ago");
    1532           6 :                 TIMELIB_INIT;
    1533           6 :                 s->time->relative.y = 0 - s->time->relative.y;
    1534           6 :                 s->time->relative.m = 0 - s->time->relative.m;
    1535           6 :                 s->time->relative.d = 0 - s->time->relative.d;
    1536           6 :                 s->time->relative.h = 0 - s->time->relative.h;
    1537           6 :                 s->time->relative.i = 0 - s->time->relative.i;
    1538           6 :                 s->time->relative.s = 0 - s->time->relative.s;
    1539           6 :                 s->time->relative.weekday = 0 - s->time->relative.weekday;
    1540           6 :                 if (s->time->relative.weekday == 0) {
    1541           6 :                         s->time->relative.weekday = -7;
    1542             :                 }
    1543           6 :                 if (s->time->relative.have_special_relative && s->time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY) {
    1544           0 :                         s->time->relative.special.amount = 0 - s->time->relative.special.amount;
    1545             :                 }
    1546           6 :                 TIMELIB_DEINIT;
    1547           6 :                 return TIMELIB_AGO;
    1548             :         }
    1549             : 
    1550             :         daytext
    1551             :         {
    1552             :                 const timelib_relunit* relunit;
    1553             :                 DEBUG_OUTPUT("daytext");
    1554        1060 :                 TIMELIB_INIT;
    1555        1060 :                 TIMELIB_HAVE_RELATIVE();
    1556        1060 :                 TIMELIB_HAVE_WEEKDAY_RELATIVE();
    1557        1060 :                 TIMELIB_UNHAVE_TIME();
    1558        1060 :                 relunit = timelib_lookup_relunit((char**) &ptr);
    1559        1060 :                 s->time->relative.weekday = relunit->multiplier;
    1560        1060 :                 if (s->time->relative.weekday_behavior != 2) {
    1561        1058 :                         s->time->relative.weekday_behavior = 1;
    1562             :                 }
    1563             :                 
    1564        1060 :                 TIMELIB_DEINIT;
    1565        1060 :                 return TIMELIB_WEEKDAY;
    1566             :         }
    1567             : 
    1568             :         relativetextweek
    1569             :         {
    1570             :                 timelib_sll i;
    1571           3 :                 int         behavior = 0;
    1572             :                 DEBUG_OUTPUT("relativetextweek");
    1573           3 :                 TIMELIB_INIT;
    1574           3 :                 TIMELIB_HAVE_RELATIVE();
    1575             : 
    1576           9 :                 while(*ptr) {
    1577           3 :                         i = timelib_get_relative_text((char **) &ptr, &behavior);
    1578           3 :                         timelib_eat_spaces((char **) &ptr);
    1579           3 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1580           3 :                         s->time->relative.weekday_behavior = 2;
    1581             : 
    1582             :                         /* to handle the format weekday + last/this/next week */
    1583           3 :                         if (s->time->relative.have_weekday_relative == 0) {
    1584           3 :                                 TIMELIB_HAVE_WEEKDAY_RELATIVE();
    1585           3 :                                 s->time->relative.weekday = 1;
    1586             :                         }
    1587             :                 }
    1588           3 :                 TIMELIB_DEINIT;
    1589           3 :                 return TIMELIB_RELATIVE;
    1590             :         }
    1591             : 
    1592             :         relativetext
    1593             :         {
    1594             :                 timelib_sll i;
    1595         127 :                 int         behavior = 0;
    1596             :                 DEBUG_OUTPUT("relativetext");
    1597         127 :                 TIMELIB_INIT;
    1598         127 :                 TIMELIB_HAVE_RELATIVE();
    1599             : 
    1600         381 :                 while(*ptr) {
    1601         127 :                         i = timelib_get_relative_text((char **) &ptr, &behavior);
    1602         127 :                         timelib_eat_spaces((char **) &ptr);
    1603         127 :                         timelib_set_relative((char **) &ptr, i, behavior, s);
    1604             :                 }
    1605         127 :                 TIMELIB_DEINIT;
    1606         127 :                 return TIMELIB_RELATIVE;
    1607             :         }
    1608             : 
    1609             :         monthfull | monthabbr
    1610             :         {
    1611             :                 DEBUG_OUTPUT("monthtext");
    1612           5 :                 TIMELIB_INIT;
    1613           5 :                 TIMELIB_HAVE_DATE();
    1614           5 :                 s->time->m = timelib_lookup_month((char **) &ptr);
    1615           5 :                 TIMELIB_DEINIT;
    1616           5 :                 return TIMELIB_DATE_TEXT;
    1617             :         }
    1618             : 
    1619             :         tzcorrection | tz
    1620             :         {
    1621             :                 int tz_not_found;
    1622             :                 DEBUG_OUTPUT("tzcorrection | tz");
    1623        3730 :                 TIMELIB_INIT;
    1624        3730 :                 TIMELIB_HAVE_TZ();
    1625        3484 :                 s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1626        3484 :                 if (tz_not_found) {
    1627          50 :                         add_error(s, "The timezone could not be found in the database");
    1628             :                 }
    1629        3484 :                 TIMELIB_DEINIT;
    1630        3484 :                 return TIMELIB_TIMEZONE;
    1631             :         }
    1632             : 
    1633             :         dateshortwithtimeshort12 | dateshortwithtimelong12
    1634             :         {
    1635             :                 DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
    1636           4 :                 TIMELIB_INIT;
    1637           4 :                 TIMELIB_HAVE_DATE();
    1638           4 :                 s->time->m = timelib_get_month((char **) &ptr);
    1639           4 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1640             : 
    1641           4 :                 TIMELIB_HAVE_TIME();
    1642           4 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1643           4 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1644           4 :                 if (*ptr == ':' || *ptr == '.') {
    1645           0 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1646             : 
    1647           0 :                         if (*ptr == '.') {
    1648           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1649             :                         }
    1650             :                 }
    1651             : 
    1652           4 :                 s->time->h += timelib_meridian((char **) &ptr, s->time->h);
    1653           4 :                 TIMELIB_DEINIT;
    1654           4 :                 return TIMELIB_SHORTDATE_WITH_TIME;
    1655             :         }
    1656             : 
    1657             :         dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
    1658             :         {
    1659             :                 int tz_not_found;
    1660             :                 DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
    1661          12 :                 TIMELIB_INIT;
    1662          12 :                 TIMELIB_HAVE_DATE();
    1663          12 :                 s->time->m = timelib_get_month((char **) &ptr);
    1664          12 :                 s->time->d = timelib_get_nr((char **) &ptr, 2);
    1665             : 
    1666          12 :                 TIMELIB_HAVE_TIME();
    1667          12 :                 s->time->h = timelib_get_nr((char **) &ptr, 2);
    1668          12 :                 s->time->i = timelib_get_nr((char **) &ptr, 2);
    1669          12 :                 if (*ptr == ':') {
    1670           3 :                         s->time->s = timelib_get_nr((char **) &ptr, 2);
    1671             : 
    1672           3 :                         if (*ptr == '.') {
    1673           0 :                                 s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
    1674             :                         }
    1675             :                 }
    1676             : 
    1677          12 :                 if (*ptr != '\0') {
    1678           0 :                         s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    1679           0 :                         if (tz_not_found) {
    1680           0 :                                 add_error(s, "The timezone could not be found in the database");
    1681             :                         }
    1682             :                 }
    1683          12 :                 TIMELIB_DEINIT;
    1684          12 :                 return TIMELIB_SHORTDATE_WITH_TIME;
    1685             :         }
    1686             : 
    1687             :         relative
    1688             :         {
    1689             :                 timelib_ull i;
    1690             :                 DEBUG_OUTPUT("relative");
    1691         491 :                 TIMELIB_INIT;
    1692         491 :                 TIMELIB_HAVE_RELATIVE();
    1693             : 
    1694        1473 :                 while(*ptr) {
    1695         491 :                         i = timelib_get_unsigned_nr((char **) &ptr, 24);
    1696         491 :                         timelib_eat_spaces((char **) &ptr);
    1697         491 :                         timelib_set_relative((char **) &ptr, i, 1, s);
    1698             :                 }
    1699         491 :                 TIMELIB_DEINIT;
    1700         491 :                 return TIMELIB_RELATIVE;
    1701             :         }
    1702             : 
    1703             :         [ .,\t]
    1704             :         {
    1705        8215 :                 goto std;
    1706             :         }
    1707             : 
    1708             :         "\000"|"\n"
    1709             :         {
    1710        8406 :                 s->pos = cursor; s->line++;
    1711        8406 :                 goto std;
    1712             :         }
    1713             : 
    1714             :         any
    1715             :         {
    1716          85 :                 add_error(s, "Unexpected character");
    1717          85 :                 goto std;
    1718             :         }
    1719             : */
    1720             : }
    1721             : 
    1722             : /*!max:re2c */
    1723             : 
    1724        8452 : timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
    1725             : {
    1726             :         Scanner in;
    1727             :         int t;
    1728        8452 :         char *e = s + len - 1;
    1729             : 
    1730        8452 :         memset(&in, 0, sizeof(in));
    1731        8452 :         in.errors = malloc(sizeof(struct timelib_error_container));
    1732        8452 :         in.errors->warning_count = 0;
    1733        8452 :         in.errors->warning_messages = NULL;
    1734        8452 :         in.errors->error_count = 0;
    1735        8452 :         in.errors->error_messages = NULL;
    1736             : 
    1737        8452 :         if (len > 0) {
    1738       16863 :                 while (isspace(*s) && s < e) {
    1739           9 :                         s++;
    1740             :                 }
    1741       16864 :                 while (isspace(*e) && e > s) {
    1742          10 :                         e--;
    1743             :                 }
    1744             :         }
    1745        8452 :         if (e - s < 0) {
    1746          25 :                 in.time = timelib_time_ctor();
    1747          25 :                 add_error(&in, "Empty string");
    1748          25 :                 if (errors) {
    1749          25 :                         *errors = in.errors;
    1750             :                 } else {
    1751           0 :                         timelib_error_container_dtor(in.errors);
    1752             :                 }
    1753          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;
    1754          25 :                 in.time->is_localtime = in.time->zone_type = 0;
    1755          25 :                 return in.time;
    1756             :         }
    1757        8427 :         e++;
    1758             : 
    1759        8427 :         in.str = malloc((e - s) + YYMAXFILL);
    1760        8427 :         memset(in.str, 0, (e - s) + YYMAXFILL);
    1761        8427 :         memcpy(in.str, s, (e - s));
    1762        8427 :         in.lim = in.str + (e - s) + YYMAXFILL;
    1763        8427 :         in.cur = in.str;
    1764        8427 :         in.time = timelib_time_ctor();
    1765        8427 :         in.time->y = TIMELIB_UNSET;
    1766        8427 :         in.time->d = TIMELIB_UNSET;
    1767        8427 :         in.time->m = TIMELIB_UNSET;
    1768        8427 :         in.time->h = TIMELIB_UNSET;
    1769        8427 :         in.time->i = TIMELIB_UNSET;
    1770        8427 :         in.time->s = TIMELIB_UNSET;
    1771        8427 :         in.time->f = TIMELIB_UNSET;
    1772        8427 :         in.time->z = TIMELIB_UNSET;
    1773        8427 :         in.time->dst = TIMELIB_UNSET;
    1774        8427 :         in.tzdb = tzdb;
    1775        8427 :         in.time->is_localtime = 0;
    1776        8427 :         in.time->zone_type = 0;
    1777        8427 :         in.time->relative.days = TIMELIB_UNSET;
    1778             : 
    1779             :         do {
    1780       25158 :                 t = scan(&in, tz_get_wrapper);
    1781             : #ifdef DEBUG_PARSER
    1782             :                 printf("%d\n", t);
    1783             : #endif
    1784       25158 :         } while(t != EOI);
    1785             : 
    1786             :         /* do funky checking whether the parsed time was valid time */
    1787        8427 :         if (in.time->have_time && !timelib_valid_time( in.time->h, in.time->i, in.time->s)) {
    1788           4 :                 add_warning(&in, "The parsed time was invalid");
    1789             :         }
    1790             :         /* do funky checking whether the parsed date was valid date */
    1791        8427 :         if (in.time->have_date && !timelib_valid_date( in.time->y, in.time->m, in.time->d)) {
    1792          11 :                 add_warning(&in, "The parsed date was invalid");
    1793             :         }
    1794             : 
    1795        8427 :         free(in.str);
    1796        8427 :         if (errors) {
    1797        8238 :                 *errors = in.errors;
    1798             :         } else {
    1799         189 :                 timelib_error_container_dtor(in.errors);
    1800             :         }
    1801        8427 :         return in.time;
    1802             : }
    1803             : 
    1804             : #define TIMELIB_CHECK_NUMBER                                           \
    1805             :                 if (strchr("0123456789", *ptr) == NULL)                        \
    1806             :                 {                                                              \
    1807             :                         add_pbf_error(s, "Unexpected data found.", string, begin); \
    1808             :                 }
    1809             : 
    1810           7 : static void timelib_time_reset_fields(timelib_time *time)
    1811             : {
    1812           7 :         assert(time != NULL);
    1813             : 
    1814           7 :         time->y = 1970;
    1815           7 :         time->m = 1;
    1816           7 :         time->d = 1;
    1817           7 :         time->h = time->i = time->s = 0;
    1818           7 :         time->f = 0.0;
    1819           7 :         time->tz_info = NULL;
    1820           7 : }
    1821             : 
    1822           1 : static void timelib_time_reset_unset_fields(timelib_time *time)
    1823             : {
    1824           1 :         assert(time != NULL);
    1825             : 
    1826           1 :         if (time->y == TIMELIB_UNSET ) time->y = 1970;
    1827           1 :         if (time->m == TIMELIB_UNSET ) time->m = 1;
    1828           1 :         if (time->d == TIMELIB_UNSET ) time->d = 1;
    1829           1 :         if (time->h == TIMELIB_UNSET ) time->h = 0;
    1830           1 :         if (time->i == TIMELIB_UNSET ) time->i = 0;
    1831           1 :         if (time->s == TIMELIB_UNSET ) time->s = 0;
    1832           1 :         if (time->f == TIMELIB_UNSET ) time->f = 0.0;
    1833           1 : }
    1834             : 
    1835        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)
    1836             : {
    1837        1073 :         char       *fptr = format;
    1838        1073 :         char       *ptr = string;
    1839             :         char       *begin;
    1840             :         timelib_sll tmp;
    1841             :         Scanner in;
    1842        1073 :         Scanner *s = &in;
    1843        1073 :         int allow_extra = 0;
    1844             : 
    1845        1073 :         memset(&in, 0, sizeof(in));
    1846        1073 :         in.errors = malloc(sizeof(struct timelib_error_container));
    1847        1073 :         in.errors->warning_count = 0;
    1848        1073 :         in.errors->warning_messages = NULL;
    1849        1073 :         in.errors->error_count = 0;
    1850        1073 :         in.errors->error_messages = NULL;
    1851             : 
    1852        1073 :         in.time = timelib_time_ctor();
    1853        1073 :         in.time->y = TIMELIB_UNSET;
    1854        1073 :         in.time->d = TIMELIB_UNSET;
    1855        1073 :         in.time->m = TIMELIB_UNSET;
    1856        1073 :         in.time->h = TIMELIB_UNSET;
    1857        1073 :         in.time->i = TIMELIB_UNSET;
    1858        1073 :         in.time->s = TIMELIB_UNSET;
    1859        1073 :         in.time->f = TIMELIB_UNSET;
    1860        1073 :         in.time->z = TIMELIB_UNSET;
    1861        1073 :         in.time->dst = TIMELIB_UNSET;
    1862        1073 :         in.tzdb = tzdb;
    1863        1073 :         in.time->is_localtime = 0;
    1864        1073 :         in.time->zone_type = 0;
    1865             : 
    1866             :         /* Loop over the format string */
    1867        3704 :         while (*fptr && *ptr) {
    1868        1558 :                 begin = ptr;
    1869        1558 :                 switch (*fptr) {
    1870             :                         case 'D': /* three letter day */
    1871             :                         case 'l': /* full day */
    1872             :                                 {
    1873          15 :                                         const timelib_relunit* tmprel = 0;
    1874             : 
    1875          15 :                                         tmprel = timelib_lookup_relunit((char **) &ptr);
    1876          15 :                                         if (!tmprel) {
    1877           0 :                                                 add_pbf_error(s, "A textual day could not be found", string, begin);
    1878           0 :                                                 break;
    1879             :                                         } else {
    1880          15 :                                                 in.time->have_relative = 1; 
    1881          15 :                                                 in.time->relative.have_weekday_relative = 1;
    1882          15 :                                                 in.time->relative.weekday = tmprel->multiplier;
    1883          15 :                                                 in.time->relative.weekday_behavior = 1;
    1884             :                                         }
    1885             :                                 }
    1886          15 :                                 break;
    1887             :                         case 'd': /* two digit day, with leading zero */
    1888             :                         case 'j': /* two digit day, without leading zero */
    1889          51 :                                 TIMELIB_CHECK_NUMBER;
    1890          51 :                                 if ((s->time->d = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1891           0 :                                         add_pbf_error(s, "A two digit day could not be found", string, begin);
    1892             :                                 }
    1893          51 :                                 break;
    1894             :                         case 'S': /* day suffix, ignored, nor checked */
    1895           0 :                                 timelib_skip_day_suffix((char **) &ptr);
    1896           0 :                                 break;
    1897             :                         case 'z': /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */
    1898           1 :                                 TIMELIB_CHECK_NUMBER;
    1899           1 :                                 if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) {
    1900           0 :                                         add_pbf_error(s, "A three digit day-of-year could not be found", string, begin);
    1901             :                                 } else {
    1902           1 :                                         s->time->m = 1;
    1903           1 :                                         s->time->d = tmp + 1;
    1904           1 :                                         timelib_do_normalize(s->time);
    1905             :                                 }
    1906           1 :                                 break;
    1907             : 
    1908             :                         case 'm': /* two digit month, with leading zero */
    1909             :                         case 'n': /* two digit month, without leading zero */
    1910          38 :                                 TIMELIB_CHECK_NUMBER;
    1911          38 :                                 if ((s->time->m = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1912           0 :                                         add_pbf_error(s, "A two digit month could not be found", string, begin);
    1913             :                                 }
    1914          38 :                                 break;
    1915             :                         case 'M': /* three letter month */
    1916             :                         case 'F': /* full month */
    1917          14 :                                 tmp = timelib_lookup_month((char **) &ptr);
    1918          14 :                                 if (!tmp) {
    1919           0 :                                         add_pbf_error(s, "A textual month could not be found", string, begin);
    1920             :                                 } else {
    1921          14 :                                         s->time->m = tmp;
    1922             :                                 }
    1923          14 :                                 break;
    1924             :                         case 'y': /* two digit year */
    1925             :                                 {
    1926          18 :                                         int length = 0;
    1927          18 :                                         TIMELIB_CHECK_NUMBER;
    1928          18 :                                         if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == TIMELIB_UNSET) {
    1929           0 :                                                 add_pbf_error(s, "A two digit year could not be found", string, begin);
    1930             :                                         }
    1931          18 :                                         TIMELIB_PROCESS_YEAR(s->time->y, length);
    1932             :                                 }
    1933          18 :                                 break;
    1934             :                         case 'Y': /* four digit year */
    1935          35 :                                 TIMELIB_CHECK_NUMBER;
    1936          35 :                                 if ((s->time->y = timelib_get_nr((char **) &ptr, 4)) == TIMELIB_UNSET) {
    1937           0 :                                         add_pbf_error(s, "A four digit year could not be found", string, begin);
    1938             :                                 }
    1939          35 :                                 break;
    1940             :                         case 'g': /* two digit hour, with leading zero */
    1941             :                         case 'h': /* two digit hour, without leading zero */
    1942           1 :                                 TIMELIB_CHECK_NUMBER;
    1943           1 :                                 if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1944           0 :                                         add_pbf_error(s, "A two digit hour could not be found", string, begin);
    1945             :                                 }
    1946           1 :                                 if (s->time->h > 12) {
    1947           0 :                                         add_pbf_error(s, "Hour can not be higher than 12", string, begin);
    1948             :                                 }
    1949           1 :                                 break;
    1950             :                         case 'G': /* two digit hour, with leading zero */
    1951             :                         case 'H': /* two digit hour, without leading zero */
    1952          26 :                                 TIMELIB_CHECK_NUMBER;
    1953          26 :                                 if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
    1954           0 :                                         add_pbf_error(s, "A two digit hour could not be found", string, begin);
    1955             :                                 }
    1956          26 :                                 break;
    1957             :                         case 'a': /* am/pm/a.m./p.m. */
    1958             :                         case 'A': /* AM/PM/A.M./P.M. */
    1959           3 :                                 if (s->time->h == TIMELIB_UNSET) {
    1960           1 :                                         add_pbf_error(s, "Meridian can only come after an hour has been found", string, begin);
    1961           2 :                                 } else if ((tmp = timelib_meridian_with_check((char **) &ptr, s->time->h)) == TIMELIB_UNSET) {
    1962           1 :                                         add_pbf_error(s, "A meridian could not be found", string, begin);
    1963             :                                 } else {
    1964           1 :                                         s->time->h += tmp;
    1965             :                                 }
    1966           3 :                                 break;
    1967             :                         case 'i': /* two digit minute, with leading zero */
    1968             :                                 {
    1969             :                                         int length;
    1970             :                                         timelib_sll min;
    1971             : 
    1972          26 :                                         TIMELIB_CHECK_NUMBER;
    1973          26 :                                         min = timelib_get_nr_ex((char **) &ptr, 2, &length);
    1974          26 :                                         if (min == TIMELIB_UNSET || length != 2) {
    1975           0 :                                                 add_pbf_error(s, "A two digit minute could not be found", string, begin);
    1976             :                                         } else {
    1977          26 :                                                 s->time->i = min;
    1978             :                                         }
    1979             :                                 }
    1980          26 :                                 break;
    1981             :                         case 's': /* two digit second, with leading zero */
    1982             :                                 {
    1983             :                                         int length;
    1984             :                                         timelib_sll sec;
    1985             : 
    1986          26 :                                         TIMELIB_CHECK_NUMBER;
    1987          26 :                                         sec = timelib_get_nr_ex((char **) &ptr, 2, &length);
    1988          27 :                                         if (sec == TIMELIB_UNSET || length != 2) {
    1989           1 :                                                 add_pbf_error(s, "A two digit second could not be found", string, begin);
    1990             :                                         } else {
    1991          25 :                                                 s->time->s = sec;
    1992             :                                         }
    1993             :                                 }
    1994          26 :                                 break;
    1995             :                         case 'u': /* up to six digit millisecond */
    1996             :                                 {
    1997             :                                         double f;
    1998             :                                         char *tptr;
    1999             : 
    2000        1008 :                                         TIMELIB_CHECK_NUMBER;
    2001        1008 :                                         tptr = ptr;
    2002        1008 :                                         if ((f = timelib_get_nr((char **) &ptr, 6)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
    2003           0 :                                                 add_pbf_error(s, "A six digit millisecond could not be found", string, begin);
    2004             :                                         } else {
    2005        1008 :                                                 s->time->f = (f / pow(10, (ptr - tptr)));
    2006             :                                         }
    2007             :                                 }
    2008        1008 :                                 break;
    2009             :                         case ' ': /* any sort of whitespace (' ' and \t) */
    2010          72 :                                 timelib_eat_spaces((char **) &ptr);
    2011          72 :                                 break;
    2012             :                         case 'U': /* epoch seconds */
    2013           0 :                                 TIMELIB_CHECK_NUMBER;
    2014           0 :                                 TIMELIB_HAVE_RELATIVE();
    2015           0 :                                 tmp = timelib_get_unsigned_nr((char **) &ptr, 24);
    2016           0 :                                 s->time->y = 1970;
    2017           0 :                                 s->time->m = 1;
    2018           0 :                                 s->time->d = 1;
    2019           0 :                                 s->time->h = s->time->i = s->time->s = 0;
    2020           0 :                                 s->time->f = 0.0;
    2021           0 :                                 s->time->relative.s += tmp;
    2022           0 :                                 s->time->is_localtime = 1;
    2023           0 :                                 s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
    2024           0 :                                 s->time->z = 0;
    2025           0 :                                 s->time->dst = 0;
    2026           0 :                                 break;
    2027             : 
    2028             :                         case 'e': /* timezone */
    2029             :                         case 'P': /* timezone */
    2030             :                         case 'T': /* timezone */
    2031             :                         case 'O': /* timezone */
    2032             :                                 {
    2033             :                                         int tz_not_found;
    2034          32 :                                         s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
    2035          32 :                                         if (tz_not_found) {
    2036           1 :                                                 add_pbf_error(s, "The timezone could not be found in the database", string, begin);
    2037             :                                         }
    2038             :                                 }
    2039          32 :                                 break;
    2040             : 
    2041             :                         case '#': /* separation symbol */
    2042           2 :                                 if (*ptr == ';' || *ptr == ':' || *ptr == '/' || *ptr == '.' || *ptr == ',' || *ptr == '-' || *ptr == '(' || *ptr == ')') {
    2043           1 :                                         ++ptr;
    2044             :                                 } else {
    2045           0 :                                         add_pbf_error(s, "The separation symbol ([;:/.,-]) could not be found", string, begin);
    2046             :                                 }
    2047           1 :                                 break;
    2048             : 
    2049             :                         case ';':
    2050             :                         case ':':
    2051             :                         case '/':
    2052             :                         case '.':
    2053             :                         case ',':
    2054             :                         case '-':
    2055             :                         case '(':
    2056             :                         case ')':
    2057         150 :                                 if (*ptr == *fptr) {
    2058         150 :                                         ++ptr;
    2059             :                                 } else {
    2060           0 :                                         add_pbf_error(s, "The separation symbol could not be found", string, begin);
    2061             :                                 }
    2062         150 :                                 break;
    2063             : 
    2064             :                         case '!': /* reset all fields to default */
    2065           6 :                                 timelib_time_reset_fields(s->time);
    2066           6 :                                 break; /* break intentionally not missing */
    2067             : 
    2068             :                         case '|': /* reset all fields to default when not set */
    2069           0 :                                 timelib_time_reset_unset_fields(s->time);
    2070           0 :                                 break; /* break intentionally not missing */
    2071             : 
    2072             :                         case '?': /* random char */
    2073           0 :                                 ++ptr;
    2074           0 :                                 break;
    2075             : 
    2076             :                         case '\\': /* escaped char */
    2077           5 :                                 if(!fptr[1]) {
    2078           1 :                                         add_pbf_error(s, "Escaped character expected", string, begin);
    2079           1 :                                         break;
    2080             :                                 }
    2081           4 :                                 fptr++;
    2082           4 :                                 if (*ptr == *fptr) {
    2083           4 :                                         ++ptr;
    2084             :                                 } else {
    2085           0 :                                         add_pbf_error(s, "The escaped character could not be found", string, begin);
    2086             :                                 }
    2087           4 :                                 break;
    2088             : 
    2089             :                         case '*': /* random chars until a separator or number ([ \t.,:;/-0123456789]) */
    2090           2 :                                 timelib_eat_until_separator((char **) &ptr);
    2091           2 :                                 break;
    2092             : 
    2093             :                         case '+': /* allow extra chars in the format */
    2094          12 :                                 allow_extra = 1;
    2095          12 :                                 break;
    2096             : 
    2097             :                         default:
    2098          16 :                                 if (*fptr != *ptr) {
    2099           0 :                                         add_pbf_error(s, "The format separator does not match", string, begin);
    2100             :                                 }
    2101          16 :                                 ptr++;
    2102             :                 }
    2103        1558 :                 fptr++;
    2104             :         }
    2105        1073 :         if (*ptr) {
    2106          13 :                 if (allow_extra) {
    2107           8 :                         add_pbf_warning(s, "Trailing data", string, ptr);
    2108             :                 } else {
    2109           5 :                         add_pbf_error(s, "Trailing data", string, ptr);
    2110             :                 }
    2111             :         }
    2112             :         /* ignore trailing +'s */
    2113        2150 :         while (*fptr == '+') {
    2114           4 :                 fptr++;
    2115             :         }
    2116        1073 :         if (*fptr) {
    2117             :                 /* Trailing | and ! specifiers are valid. */
    2118           6 :                 int done = 0;
    2119          18 :                 while (*fptr && !done) {
    2120           6 :                         switch (*fptr++) {
    2121             :                                 case '!': /* reset all fields to default */
    2122           1 :                                         timelib_time_reset_fields(s->time);
    2123           1 :                                         break;
    2124             : 
    2125             :                                 case '|': /* reset all fields to default when not set */
    2126           1 :                                         timelib_time_reset_unset_fields(s->time);
    2127           1 :                                         break;
    2128             : 
    2129             :                                 default:
    2130           4 :                                         add_pbf_error(s, "Data missing", string, ptr);
    2131           4 :                                         done = 1;
    2132             :                         }
    2133             :                 }
    2134             :         }
    2135             : 
    2136             :         /* clean up a bit */
    2137        1073 :         if (s->time->h != TIMELIB_UNSET || s->time->i != TIMELIB_UNSET || s->time->s != TIMELIB_UNSET) {
    2138          35 :                 if (s->time->h == TIMELIB_UNSET ) {
    2139           0 :                         s->time->h = 0;
    2140             :                 }
    2141          35 :                 if (s->time->i == TIMELIB_UNSET ) {
    2142           1 :                         s->time->i = 0;
    2143             :                 }
    2144          35 :                 if (s->time->s == TIMELIB_UNSET ) {
    2145           2 :                         s->time->s = 0;
    2146             :                 }
    2147             :         }
    2148             : 
    2149             :         /* do funky checking whether the parsed time was valid time */
    2150        1143 :         if (s->time->h != TIMELIB_UNSET && s->time->i != TIMELIB_UNSET &&
    2151          35 :                 s->time->s != TIMELIB_UNSET && 
    2152          35 :                 !timelib_valid_time( s->time->h, s->time->i, s->time->s)) {
    2153           0 :                 add_pbf_warning(s, "The parsed time was invalid", string, ptr);
    2154             :         }
    2155             :         /* do funky checking whether the parsed date was valid date */
    2156        1178 :         if (s->time->y != TIMELIB_UNSET && s->time->m != TIMELIB_UNSET &&
    2157          53 :                 s->time->d != TIMELIB_UNSET && 
    2158          52 :                 !timelib_valid_date( s->time->y, s->time->m, s->time->d)) {
    2159           0 :                 add_pbf_warning(s, "The parsed date was invalid", string, ptr);
    2160             :         }
    2161             : 
    2162        1073 :         if (errors) {
    2163        1073 :                 *errors = in.errors;
    2164             :         } else {
    2165           0 :                 timelib_error_container_dtor(in.errors);
    2166             :         }
    2167        1073 :         return in.time;
    2168             : }
    2169             : 
    2170        8886 : void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
    2171             : {
    2172        8886 :         if (!(options & TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
    2173        3075 :                 parsed->h = 0;
    2174        3075 :                 parsed->i = 0;
    2175        3075 :                 parsed->s = 0;
    2176        3075 :                 parsed->f = 0;
    2177             :         }
    2178        8886 :         if (parsed->y == TIMELIB_UNSET) parsed->y = now->y != TIMELIB_UNSET ? now->y : 0;
    2179        8886 :         if (parsed->d == TIMELIB_UNSET) parsed->d = now->d != TIMELIB_UNSET ? now->d : 0;
    2180        8886 :         if (parsed->m == TIMELIB_UNSET) parsed->m = now->m != TIMELIB_UNSET ? now->m : 0;
    2181        8886 :         if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0;
    2182        8886 :         if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0;
    2183        8886 :         if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0;
    2184        8886 :         if (parsed->f == TIMELIB_UNSET) parsed->f = now->f != TIMELIB_UNSET ? now->f : 0;
    2185        8886 :         if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0;
    2186        8886 :         if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0;
    2187             : 
    2188        8886 :         if (!parsed->tz_abbr) {
    2189        7584 :                 parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
    2190             :         }
    2191        8886 :         if (!parsed->tz_info) {
    2192        6935 :                 parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL;
    2193             :         }
    2194        8886 :         if (parsed->zone_type == 0 && now->zone_type != 0) {
    2195        5428 :                 parsed->zone_type = now->zone_type;
    2196             : /*              parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
    2197             :                 parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
    2198        5428 : */              parsed->is_localtime = 1;
    2199             :         }
    2200             : /*      timelib_dump_date(parsed, 2);
    2201             :         timelib_dump_date(now, 2);
    2202             : */
    2203        8886 : }
    2204             : 
    2205          72 : char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst)
    2206             : {
    2207             :         const timelib_tz_lookup_table *tp;
    2208             : 
    2209          72 :         tp = abbr_search(abbr, gmtoffset, isdst);
    2210          72 :         if (tp) {
    2211          68 :                 return (tp->full_tz_name);
    2212             :         } else {
    2213           4 :                 return NULL;
    2214             :         }
    2215             : }
    2216             : 
    2217           4 : const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
    2218             : {
    2219           4 :         return timelib_timezone_lookup;
    2220             : }
    2221             : 
    2222             : #ifdef DEBUG_PARSER_STUB
    2223             : int main(void)
    2224             : {
    2225             :         timelib_time time = timelib_strtotime("May 12");
    2226             : 
    2227             :         printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
    2228             :                 time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
    2229             :         if (time.have_relative) {
    2230             :                 printf ("%3dY %3dM %3dD / %3dH %3dM %3dS", 
    2231             :                         time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
    2232             :         }
    2233             :         if (time.have_weekday_relative) {
    2234             :                 printf (" / %d", time.relative.weekday);
    2235             :         }
    2236             :         if (time.have_weeknr_day) {
    2237             :                 printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
    2238             :         }
    2239             :         return 0;                               
    2240             : }
    2241             : #endif
    2242             : 
    2243             : /*
    2244             :  * vim: syntax=c
    2245             :  */

Generated by: LCOV version 1.10

Generated at Fri, 19 Sep 2014 17:11:21 +0000 (2 days ago)

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