Annotation of embedaddon/php/ext/date/lib/parse_iso_intervals.re, revision 1.1.1.3

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: 
                     26: #ifdef HAVE_STDLIB_H
                     27: #include <stdlib.h>
                     28: #endif
                     29: #ifdef HAVE_STRING_H
                     30: #include <string.h>
                     31: #else
                     32: #include <strings.h>
                     33: #endif
                     34: 
                     35: #if defined(_MSC_VER)
                     36: # define strtoll(s, f, b) _atoi64(s)
                     37: #elif !defined(HAVE_STRTOLL)
                     38: # if defined(HAVE_ATOLL)
                     39: #  define strtoll(s, f, b) atoll(s)
                     40: # else
                     41: #  define strtoll(s, f, b) strtol(s, f, b)
                     42: # endif
                     43: #endif
                     44: 
                     45: #define TIMELIB_UNSET   -99999
                     46: 
                     47: #define TIMELIB_SECOND  1
                     48: #define TIMELIB_MINUTE  2
                     49: #define TIMELIB_HOUR    3
                     50: #define TIMELIB_DAY     4
                     51: #define TIMELIB_MONTH   5
                     52: #define TIMELIB_YEAR    6
                     53: 
                     54: #define EOI      257
                     55: 
                     56: #define TIMELIB_PERIOD  260
                     57: #define TIMELIB_ISO_DATE 261
                     58: #define TIMELIB_ERROR   999
                     59: 
                     60: typedef unsigned char uchar;
                     61: 
                     62: #define   BSIZE           8192
                     63: 
                     64: #define   YYCTYPE      uchar
                     65: #define   YYCURSOR     cursor
                     66: #define   YYLIMIT      s->lim
                     67: #define   YYMARKER     s->ptr
                     68: #define   YYFILL(n)    return EOI;
                     69: 
                     70: #define   RET(i)       {s->cur = cursor; return i;}
                     71: 
                     72: #define timelib_string_free free
                     73: 
                     74: #define TIMELIB_INIT  s->cur = cursor; str = timelib_string(s); ptr = str
                     75: #define TIMELIB_DEINIT timelib_string_free(str)
                     76: 
                     77: #ifdef DEBUG_PARSER
                     78: #define DEBUG_OUTPUT(s) printf("%s\n", s);
                     79: #define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
                     80: #else
                     81: #define DEBUG_OUTPUT(s)
                     82: #define YYDEBUG(s,c)
                     83: #endif
                     84: 
                     85: #include "timelib_structs.h"
                     86: 
                     87: typedef struct Scanner {
                     88:        int           fd;
                     89:        uchar        *lim, *str, *ptr, *cur, *tok, *pos;
                     90:        unsigned int  line, len;
                     91:        struct timelib_error_container *errors;
                     92: 
                     93:        struct timelib_time     *begin;
                     94:        struct timelib_time     *end;
                     95:        struct timelib_rel_time *period;
                     96:        int                      recurrences;
                     97: 
                     98:        int have_period;
                     99:        int have_recurrences;
                    100:        int have_date;
                    101:        int have_begin_date;
                    102:        int have_end_date;
                    103: } Scanner;
                    104: 
                    105: #define HOUR(a) (int)(a * 60)
                    106: 
                    107: static void add_warning(Scanner *s, char *error)
                    108: {
                    109:        s->errors->warning_count++;
                    110:        s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
                    111:        s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
                    112:        s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
                    113:        s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
                    114: }
                    115: 
                    116: static void add_error(Scanner *s, char *error)
                    117: {
                    118:        s->errors->error_count++;
                    119:        s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
                    120:        s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
                    121:        s->errors->error_messages[s->errors->error_count - 1].character = s->tok ? *s->tok : 0;
                    122:        s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
                    123: }
                    124: 
                    125: static char *timelib_string(Scanner *s)
                    126: {
                    127:        char *tmp = calloc(1, s->cur - s->tok + 1);
                    128:        memcpy(tmp, s->tok, s->cur - s->tok);
                    129: 
                    130:        return tmp;
                    131: }
                    132: 
                    133: static timelib_sll timelib_get_nr(char **ptr, int max_length)
                    134: {
                    135:        char *begin, *end, *str;
                    136:        timelib_sll tmp_nr = TIMELIB_UNSET;
                    137:        int len = 0;
                    138: 
                    139:        while ((**ptr < '0') || (**ptr > '9')) {
                    140:                if (**ptr == '\0') {
                    141:                        return TIMELIB_UNSET;
                    142:                }
                    143:                ++*ptr;
                    144:        }
                    145:        begin = *ptr;
                    146:        while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
                    147:                ++*ptr;
                    148:                ++len;
                    149:        }
                    150:        end = *ptr;
                    151:        str = calloc(1, end - begin + 1);
                    152:        memcpy(str, begin, end - begin);
                    153:        tmp_nr = strtoll(str, NULL, 10);
                    154:        free(str);
                    155:        return tmp_nr;
                    156: }
                    157: 
                    158: static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
                    159: {
                    160:        timelib_ull dir = 1;
                    161: 
                    162:        while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
                    163:                if (**ptr == '\0') {
                    164:                        return TIMELIB_UNSET;
                    165:                }
                    166:                ++*ptr;
                    167:        }
                    168: 
                    169:        while (**ptr == '+' || **ptr == '-')
                    170:        {
                    171:                if (**ptr == '-') {
                    172:                        dir *= -1;
                    173:                }
                    174:                ++*ptr;
                    175:        }
                    176:        return dir * timelib_get_nr(ptr, max_length);
                    177: }
                    178: 
                    179: static long timelib_parse_tz_cor(char **ptr)
                    180: {
                    181:        char *begin = *ptr, *end;
                    182:        long  tmp;
                    183: 
                    184:        while (isdigit(**ptr) || **ptr == ':') {
                    185:                ++*ptr;
                    186:        }
                    187:        end = *ptr;
                    188:        switch (end - begin) {
                    189:                case 1:
                    190:                case 2:
                    191:                        return HOUR(strtol(begin, NULL, 10));
                    192:                        break;
                    193:                case 3:
                    194:                case 4:
                    195:                        if (begin[1] == ':') {
                    196:                                tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
                    197:                                return tmp;
                    198:                        } else if (begin[2] == ':') {
                    199:                                tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
                    200:                                return tmp;
                    201:                        } else {
                    202:                                tmp = strtol(begin, NULL, 10);
                    203:                                return HOUR(tmp / 100) + tmp % 100;
                    204:                        }
                    205:                case 5:
                    206:                        tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
                    207:                        return tmp;
                    208:        }
                    209:        return 0;
                    210: }
                    211: 
                    212: static void timelib_eat_spaces(char **ptr)
                    213: {
                    214:        while (**ptr == ' ' || **ptr == '\t') {
                    215:                ++*ptr;
                    216:        }
                    217: }
                    218: 
                    219: static void timelib_eat_until_separator(char **ptr)
                    220: {
                    221:        while (strchr(" \t.,:;/-0123456789", **ptr) == NULL) {
                    222:                ++*ptr;
                    223:        }
                    224: }
                    225: 
                    226: static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb)
                    227: {
                    228:        long retval = 0;
                    229: 
                    230:        *tz_not_found = 0;
                    231: 
                    232:        while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
                    233:                ++*ptr;
                    234:        }
                    235:        if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) {
                    236:                *ptr += 3;
                    237:        }
                    238:        if (**ptr == '+') {
                    239:                ++*ptr;
                    240:                t->is_localtime = 1;
                    241:                t->zone_type = TIMELIB_ZONETYPE_OFFSET;
                    242:                *tz_not_found = 0;
                    243:                t->dst = 0;
                    244: 
                    245:                retval = -1 * timelib_parse_tz_cor(ptr);
                    246:        } else if (**ptr == '-') {
                    247:                ++*ptr;
                    248:                t->is_localtime = 1;
                    249:                t->zone_type = TIMELIB_ZONETYPE_OFFSET;
                    250:                *tz_not_found = 0;
                    251:                t->dst = 0;
                    252: 
                    253:                retval = timelib_parse_tz_cor(ptr);
                    254:        }
                    255:        while (**ptr == ')') {
                    256:                ++*ptr;
                    257:        }
                    258:        return retval;
                    259: }
                    260: 
                    261: #define timelib_split_free(arg) {       \
                    262:        int i;                         \
                    263:        for (i = 0; i < arg.c; i++) {  \
                    264:                free(arg.v[i]);            \
                    265:        }                              \
                    266:        if (arg.v) {                   \
                    267:                free(arg.v);               \
                    268:        }                              \
                    269: }
                    270: 
                    271: /* date parser's scan function too large for VC6 - VC7.x
                    272:    drop the optimization solves the problem */
                    273: #ifdef PHP_WIN32
                    274: #pragma optimize( "", off )
                    275: #endif
                    276: static int scan(Scanner *s)
                    277: {
                    278:        uchar *cursor = s->cur;
                    279:        char *str, *ptr = NULL;
                    280:                
                    281: std:
                    282:        s->tok = cursor;
                    283:        s->len = 0;
                    284: /*!re2c
                    285: 
                    286: /* */
                    287: any = [\000-\377];
                    288: number = [0-9]+;
                    289: 
                    290: hour24lz = [01][0-9] | "2"[0-4];
                    291: minutelz = [0-5][0-9];
                    292: monthlz = "0" [1-9] | "1" [0-2];
                    293: monthlzz = "0" [0-9] | "1" [0-2];
                    294: daylz   = "0" [1-9] | [1-2][0-9] | "3" [01];
                    295: daylzz  = "0" [0-9] | [1-2][0-9] | "3" [01];
                    296: secondlz = minutelz;
                    297: year4 = [0-9]{4};
                    298: weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
                    299: 
                    300: space = [ \t]+;
                    301: datetimebasic  = year4 monthlz daylz "T" hour24lz minutelz secondlz "Z";
                    302: datetimeextended  = year4 "-" monthlz "-" daylz "T" hour24lz ':' minutelz ':' secondlz "Z";
                    303: period   = "P" (number "Y")? (number "M")? (number "W")? (number "D")? ("T" (number "H")? (number "M")? (number "S")?)?;
                    304: combinedrep = "P" year4 "-" monthlzz "-" daylzz "T" hour24lz ':' minutelz ':' secondlz;
                    305: 
                    306: recurrences = "R" number;
                    307: 
                    308: isoweekday       = year4 "-"? "W" weekofyear "-"? [0-7];
                    309: isoweek          = year4 "-"? "W" weekofyear;
                    310: 
                    311: */
                    312: 
                    313: /*!re2c
                    314:        /* so that vim highlights correctly */
                    315:        recurrences
                    316:        {
                    317:                DEBUG_OUTPUT("recurrences");
                    318:                TIMELIB_INIT;
                    319:                ptr++;
                    320:                s->recurrences = timelib_get_unsigned_nr((char **) &ptr, 9);
                    321:                TIMELIB_DEINIT;
                    322:                s->have_recurrences = 1;
                    323:                return TIMELIB_PERIOD;
                    324:        }
                    325: 
                    326:        datetimebasic| datetimeextended
                    327:        {
                    328:                timelib_time *current;
                    329: 
                    330:                if (s->have_date || s->have_period) {
                    331:                        current = s->end;
                    332:                        s->have_end_date = 1;
                    333:                } else {
                    334:                        current = s->begin;
                    335:                        s->have_begin_date = 1;
                    336:                }
                    337:                DEBUG_OUTPUT("datetimebasic | datetimeextended");
                    338:                TIMELIB_INIT;
                    339:                current->y = timelib_get_nr((char **) &ptr, 4);
                    340:                current->m = timelib_get_nr((char **) &ptr, 2);
                    341:                current->d = timelib_get_nr((char **) &ptr, 2);
                    342:                current->h = timelib_get_nr((char **) &ptr, 2);
                    343:                current->i = timelib_get_nr((char **) &ptr, 2);
                    344:                current->s = timelib_get_nr((char **) &ptr, 2);
                    345:                s->have_date = 1;
                    346:                TIMELIB_DEINIT;
                    347:                return TIMELIB_ISO_DATE;
                    348:        }
                    349: 
                    350:        period
                    351:        {
                    352:                timelib_sll nr;
                    353:                int         in_time = 0;
                    354:                DEBUG_OUTPUT("period");
                    355:                TIMELIB_INIT;
                    356:                ptr++;
                    357:                do {
                    358:                        if ( *ptr == 'T' ) {
                    359:                                in_time = 1;
                    360:                                ptr++;
                    361:                        }
                    362:                        if ( *ptr == '\0' ) {
                    363:                                add_error(s, "Missing expected time part");
                    364:                                break;
                    365:                        }
                    366: 
                    367:                        nr = timelib_get_unsigned_nr((char **) &ptr, 12);
                    368:                        switch (*ptr) {
                    369:                                case 'Y': s->period->y = nr; break;
                    370:                                case 'W': s->period->d = nr * 7; break;
                    371:                                case 'D': s->period->d = nr; break;
                    372:                                case 'H': s->period->h = nr; break;
                    373:                                case 'S': s->period->s = nr; break;
                    374:                                case 'M': 
                    375:                                        if (in_time) {
                    376:                                                s->period->i = nr;
                    377:                                        } else {
                    378:                                                s->period->m = nr; 
                    379:                                        }
                    380:                                        break;
                    381:                                default:
                    382:                                        add_error(s, "Undefined period specifier");
                    383:                                        break;
                    384:                        }
                    385:                        ptr++;
                    386:                } while (*ptr);
                    387:                s->have_period = 1;
                    388:                TIMELIB_DEINIT;
                    389:                return TIMELIB_PERIOD;
                    390:        }
                    391: 
                    392:        combinedrep
                    393:        {
                    394:                DEBUG_OUTPUT("combinedrep");
                    395:                TIMELIB_INIT;
                    396:                s->period->y = timelib_get_unsigned_nr((char **) &ptr, 4);
                    397:                ptr++;
                    398:                s->period->m = timelib_get_unsigned_nr((char **) &ptr, 2);
                    399:                ptr++;
                    400:                s->period->d = timelib_get_unsigned_nr((char **) &ptr, 2);
                    401:                ptr++;
                    402:                s->period->h = timelib_get_unsigned_nr((char **) &ptr, 2);
                    403:                ptr++;
                    404:                s->period->i = timelib_get_unsigned_nr((char **) &ptr, 2);
                    405:                ptr++;
                    406:                s->period->s = timelib_get_unsigned_nr((char **) &ptr, 2);
                    407:                s->have_period = 1;
                    408:                TIMELIB_DEINIT;
                    409:                return TIMELIB_PERIOD;
                    410:        }
                    411: 
                    412:        [ .,\t/]
                    413:        {
                    414:                goto std;
                    415:        }
                    416: 
                    417:        "\000"|"\n"
                    418:        {
                    419:                s->pos = cursor; s->line++;
                    420:                goto std;
                    421:        }
                    422: 
                    423:        any
                    424:        {
                    425:                add_error(s, "Unexpected character");
                    426:                goto std;
                    427:        }
                    428: */
                    429: }
                    430: #ifdef PHP_WIN32
                    431: #pragma optimize( "", on )
                    432: #endif
                    433: 
                    434: /*!max:re2c */
                    435: 
                    436: void timelib_strtointerval(char *s, int len, 
                    437:                            timelib_time **begin, timelib_time **end, 
                    438:                                                   timelib_rel_time **period, int *recurrences, 
                    439:                                                   struct timelib_error_container **errors)
                    440: {
                    441:        Scanner in;
                    442:        int t;
                    443:        char *e = s + len - 1;
                    444: 
                    445:        memset(&in, 0, sizeof(in));
                    446:        in.errors = malloc(sizeof(struct timelib_error_container));
                    447:        in.errors->warning_count = 0;
                    448:        in.errors->warning_messages = NULL;
                    449:        in.errors->error_count = 0;
                    450:        in.errors->error_messages = NULL;
                    451: 
                    452:        if (len > 0) {
                    453:                while (isspace(*s) && s < e) {
                    454:                        s++;
                    455:                }
                    456:                while (isspace(*e) && e > s) {
                    457:                        e--;
                    458:                }
                    459:        }
                    460:        if (e - s < 0) {
                    461:                add_error(&in, "Empty string");
                    462:                if (errors) {
                    463:                        *errors = in.errors;
                    464:                } else {
                    465:                        timelib_error_container_dtor(in.errors);
                    466:                }
                    467:                return;
                    468:        }
                    469:        e++;
                    470: 
                    471:        /* init cursor */
                    472:        in.str = malloc((e - s) + YYMAXFILL);
                    473:        memset(in.str, 0, (e - s) + YYMAXFILL);
                    474:        memcpy(in.str, s, (e - s));
                    475:        in.lim = in.str + (e - s) + YYMAXFILL;
                    476:        in.cur = in.str;
                    477: 
                    478:        /* init value containers */
                    479:        in.begin = timelib_time_ctor();
                    480:        in.begin->y = TIMELIB_UNSET;
                    481:        in.begin->d = TIMELIB_UNSET;
                    482:        in.begin->m = TIMELIB_UNSET;
                    483:        in.begin->h = TIMELIB_UNSET;
                    484:        in.begin->i = TIMELIB_UNSET;
                    485:        in.begin->s = TIMELIB_UNSET;
                    486:        in.begin->f = 0;
                    487:        in.begin->z = 0;
                    488:        in.begin->dst = 0;
                    489:        in.begin->is_localtime = 0;
                    490:        in.begin->zone_type = TIMELIB_ZONETYPE_OFFSET;
                    491: 
                    492:        in.end = timelib_time_ctor();
                    493:        in.end->y = TIMELIB_UNSET;
                    494:        in.end->d = TIMELIB_UNSET;
                    495:        in.end->m = TIMELIB_UNSET;
                    496:        in.end->h = TIMELIB_UNSET;
                    497:        in.end->i = TIMELIB_UNSET;
                    498:        in.end->s = TIMELIB_UNSET;
                    499:        in.end->f = 0;
                    500:        in.end->z = 0;
                    501:        in.end->dst = 0;
                    502:        in.end->is_localtime = 0;
                    503:        in.end->zone_type = TIMELIB_ZONETYPE_OFFSET;
                    504: 
                    505:        in.period = timelib_rel_time_ctor();
                    506:        in.period->y = 0;
                    507:        in.period->d = 0;
                    508:        in.period->m = 0;
                    509:        in.period->h = 0;
                    510:        in.period->i = 0;
                    511:        in.period->s = 0;
                    512:        in.period->weekday = 0;
                    513:        in.period->weekday_behavior = 0;
                    514:        in.period->first_last_day_of = 0;
                    515:        in.period->days = TIMELIB_UNSET;
                    516: 
                    517:        in.recurrences = 1;
                    518: 
                    519:        do {
                    520:                t = scan(&in);
                    521: #ifdef DEBUG_PARSER
                    522:                printf("%d\n", t);
                    523: #endif
                    524:        } while(t != EOI);
                    525: 
                    526:        free(in.str);
                    527:        if (errors) {
                    528:                *errors = in.errors;
                    529:        } else {
                    530:                timelib_error_container_dtor(in.errors);
                    531:        }
                    532:        if (in.have_begin_date) {
                    533:                *begin = in.begin;
                    534:        } else {
                    535:                timelib_time_dtor(in.begin);
                    536:        }
                    537:        if (in.have_end_date) {
                    538:                *end   = in.end;
                    539:        } else {
                    540:                timelib_time_dtor(in.end);
                    541:        }
                    542:        if (in.have_period) {
                    543:                *period = in.period;
                    544:        } else {
                    545:                timelib_rel_time_dtor(in.period);
                    546:        }
                    547:        if (in.have_recurrences) {
                    548:                *recurrences = in.recurrences;
                    549:        }
                    550: }
                    551: 
                    552: 
                    553: /*
                    554:  * vim: syntax=c
                    555:  */

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