Annotation of embedaddon/php/ext/date/lib/parse_date.re, revision 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>