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: 880 1029 85.5 %
Date: 2014-04-18 Functions: 31 32 96.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:39 +0000 (6 days ago)

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