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: 915 1037 88.2 %
Date: 2014-09-21 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 21 Sep 2014 15:27:49 +0000 (22 hours ago)

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