Annotation of embedaddon/php/ext/date/lib/parse_date.re, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>