Annotation of embedaddon/php/ext/date/lib/parse_iso_intervals.re, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2010 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Derick Rethans <derick@derickrethans.nl> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: parse_iso_intervals.re 320478 2011-12-06 06:04:24Z derick $ */
! 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>