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: 896 1015 88.3 %
Date: 2014-04-16 Functions: 31 31 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 16 Apr 2014 12:48:02 +0000 (3 days ago)

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