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

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

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