Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- Add my new timelib and ext/date. For now only strtotime() makes use…

… of this.
  • Loading branch information...
commit 4fb4cac65c735a9253d7b77f17468a5768a7de13 1 parent f14292d
Derick Rethans authored
View
2  NEWS
@@ -2,6 +2,8 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? Jun 2005, PHP 5.1 Beta 2
- Added bindto socket context option. (Ilia)
+- Rewrote strtotime() with support for timezones and tons of new formats.
+ (Derick)
- Fixed PDO shutdown problem (possible inifite loop running rollback on
shutdown). (Wez)
- Fixed PECL bug #3714 (beginTransaction doesn't work if you're in
View
2  ext/date/CREDITS
@@ -0,0 +1,2 @@
+Date/Time Support
+Derick Rethans
View
4 ext/date/TODO
@@ -0,0 +1,4 @@
+- Fix one bug that prevent current testcases from working.
+- Implement INI settings default timezone, for now the env var "TZ" can be
+ used.
+- Port over my 200 test cases to .phpt format.
View
6 ext/date/config.m4
@@ -0,0 +1,6 @@
+dnl $Id$
+dnl config.m4 for date extension
+
+AC_DEFINE(HAVE_DATE, 1, [Whether you want date/time support])
+AC_DEFINE(TIMEZONE_DB_PATH, $libdir/timezonedb, [The path to the timezone database])
+PHP_NEW_EXTENSION(date, php_date.c lib/datetime.c lib/dow.c lib/parse_date.c lib/parse_tz.c lib/tm2unixtime.c lib/unixtime2tm.c, no)
View
5 ext/date/lib/README
@@ -0,0 +1,5 @@
+Regenerating Parser
+===================
+
+Make sure you use re2c 0.97 or higher:
+/dat/dev/sf/re2c/re2c -d -b parse_date.re > ../parse_date.c
View
189 ext/date/lib/datetime.c
@@ -0,0 +1,189 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "timelib_structs.h"
+#include "datetime.h"
+#include <ctype.h>
+
+timelib_time* timelib_time_ctor()
+{
+ timelib_time *t;
+ t = calloc(1, sizeof(timelib_time));
+
+ return t;
+}
+
+void timelib_time_tz_abbr_update(timelib_time* tm, char* tz_abbr)
+{
+ int i;
+
+ if (tm->tz_abbr) {
+ free(tm->tz_abbr);
+ }
+ tm->tz_abbr = strdup(tz_abbr);
+ for (i = 0; i < strlen(tz_abbr); i++) {
+ tm->tz_abbr[i] = toupper(tz_abbr[i]);
+ }
+}
+
+void timelib_time_dtor(timelib_time* t)
+{
+ if (t->tz_abbr) {
+ free(t->tz_abbr);
+ }
+ free(t);
+}
+
+timelib_time_offset* timelib_time_offset_ctor()
+{
+ timelib_time_offset *t;
+ t = calloc(1, sizeof(timelib_time_offset));
+
+ return t;
+}
+
+void timelib_time_offset_dtor(timelib_time_offset* t)
+{
+ if (t->abbr) {
+ free(t->abbr);
+ }
+ free(t);
+}
+
+timelib_tzinfo* timelib_tzinfo_ctor(char *name)
+{
+ timelib_tzinfo *t;
+ t = calloc(1, sizeof(timelib_tzinfo));
+ t->name = strdup(name);
+
+ return t;
+}
+
+timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
+{
+ timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
+ tmp->ttisgmtcnt = tz->ttisgmtcnt;
+ tmp->ttisstdcnt = tz->ttisstdcnt;
+ tmp->leapcnt = tz->leapcnt;
+ tmp->timecnt = tz->timecnt;
+ tmp->typecnt = tz->typecnt;
+ tmp->charcnt = tz->charcnt;
+
+ tmp->trans = (int32_t *) malloc(tz->timecnt * sizeof(int32_t));
+ tmp->trans_idx = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
+ memcpy(tmp->trans, tz->trans, tz->timecnt * sizeof(int32_t));
+ memcpy(tmp->trans_idx, tz->trans_idx, tz->timecnt * sizeof(unsigned char));
+
+ tmp->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
+ memcpy(tmp->type, tz->type, tz->typecnt * sizeof(struct ttinfo));
+
+ tmp->timezone_abbr = (char*) malloc(tz->charcnt);
+ memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->charcnt);
+
+ tmp->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
+ memcpy(tmp->leap_times, tz->leap_times, tz->leapcnt * sizeof(tlinfo));
+
+ return tmp;
+}
+
+void timelib_tzinfo_dtor(timelib_tzinfo *tz)
+{
+ free(tz->name);
+ free(tz->trans);
+ free(tz->trans_idx);
+ free(tz->type);
+ free(tz->timezone_abbr);
+ free(tz->leap_times);
+ free(tz);
+}
+
+char *timelib_get_tz_abbr_ptr(timelib_time *t)
+{
+ if (!t->sse_uptodate) {
+ timelib_update_ts(t, NULL);
+ };
+ return t->tz_abbr;
+}
+
+signed long timelib_date_to_int(timelib_time *d, int *error)
+{
+ timelib_sll ts;
+
+ ts = d->sse;
+
+ if (ts < LONG_MIN || ts > LONG_MAX) {
+ if (error) {
+ *error = 1;
+ }
+ return 0;
+ }
+ if (error) {
+ *error = 0;
+ }
+ return d->sse;
+}
+
+void timelib_dump_date(timelib_time *d, int options)
+{
+ if ((options & 2) == 2) {
+ printf("TYPE: %d ", d->zone_type);
+ }
+ printf("TS: %lld | %04lld-%02lld-%02lld %02lld:%02lld:%02lld",
+ d->sse, d->y, d->m, d->d, d->h, d->i, d->s);
+ if (d->f > +0.0) {
+ printf(" %.5f", d->f);
+ }
+
+ if (d->is_localtime) {
+ switch (d->zone_type) {
+ case TIMELIB_ZONETYPE_OFFSET: /* Only offset */
+ printf(" GMT %05d%s", d->z, d->dst == 1 ? " (DST)" : "");
+ break;
+ case TIMELIB_ZONETYPE_ID: /* Timezone struct */
+ /* Show abbreviation if wanted */
+ if (d->tz_abbr) {
+ printf(" %s", d->tz_abbr);
+ }
+ /* Do we have a TimeZone struct? */
+ if (d->tz_info) {
+ printf(" %s", d->tz_info->name);
+ }
+ break;
+ case TIMELIB_ZONETYPE_ABBR:
+ printf(" %s", d->tz_abbr);
+ printf(" %05d%s", d->z, d->dst == 1 ? " (DST)" : "");
+ break;
+ }
+ } else {
+ printf(" GMT 00000");
+ }
+
+ if ((options & 1) == 1) {
+ if (d->have_relative) {
+ printf("%3lldY %3lldM %3lldD / %3lldH %3lldM %3lldS",
+ d->relative.y, d->relative.m, d->relative.d, d->relative.h, d->relative.i, d->relative.s);
+ }
+ if (d->have_weekday_relative) {
+ printf(" / %d", d->relative.weekday);
+ }
+ }
+ printf("\n");
+}
+
View
63 ext/date/lib/datetime.h
@@ -0,0 +1,63 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "timelib_structs.h"
+
+#define TIMELIB_NONE 0x00
+#define TIMELIB_OVERRIDE_TIME 0x01
+
+/* From dow.c */
+int timelib_day_of_week(int y, int m, int d);
+int timelib_daynr_from_weeknr(int y, int w, int d);
+
+/* From parse_date.re */
+timelib_time *timelib_strtotime(char *s);
+void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);
+
+/* From tm2unixtime.c */
+void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
+
+/* From unixtime2tm.c */
+int timelib_apply_localtime(timelib_time *t, uint localtime);
+void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts);
+void timelib_unixtime2local(timelib_time *tm, timelib_sll ts, timelib_tzinfo* tz);
+void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);
+
+/* From parse_tz.c */
+timelib_tzinfo *timelib_parse_tzfile(char *timezone);
+int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
+timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
+
+/* From datetime.c */
+timelib_tzinfo* timelib_tzinfo_ctor();
+void timelib_time_tz_abbr_update(timelib_time* tm, char* tz_abbr);
+void timelib_time_tz_name_update(timelib_time* tm, char* tz_name);
+void timelib_tzinfo_dtor(timelib_tzinfo *tz);
+timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
+
+timelib_time* timelib_time_ctor();
+void timelib_time_dtor(timelib_time* t);
+
+timelib_time_offset* timelib_time_offset_ctor();
+void timelib_time_offset_dtor(timelib_time_offset* t);
+
+signed long timelib_date_to_int(timelib_time *d, int *error);
+void timelib_dump_date(timelib_time *d, int options);
+
View
67 ext/date/lib/dow.c
@@ -0,0 +1,67 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "timelib_structs.h"
+
+static int m_table_common[13] = { -1, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 }; /* 1 = jan */
+static int m_table_leap[13] = { -1, 6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 }; /* 1 = jan */
+
+static int century_value(int j)
+{
+ int i = j - 17;
+ int c = (4 - i * 2 + (i + 1) / 4) % 7;
+
+ return c < 0 ? c + 7 : c;
+}
+
+int timelib_day_of_week(int y, int m, int d)
+{
+ int c1, y1, m1;
+
+ /* Only valid for Gregorian calendar */
+ if (y < 1753) {
+ return -1;
+ }
+ c1 = century_value(y / 100);
+ y1 = (y % 100);
+ m1 = is_leap(y) ? m_table_leap[m] : m_table_common[m];
+ return (c1 + y1 + m1 + (y1 / 4) + d) % 7;
+}
+
+int timelib_daynr_from_weeknr(int y, int w, int d)
+{
+ int dow, day;
+
+ /* Figure out the dayofweek for y-1-1 */
+ dow = timelib_day_of_week(y, 1, 1);
+ /* then use that to figure out the offset for day 1 of week 1 */
+ day = 0 - (dow > 4 ? dow - 7 : dow);
+
+ /* Add weeks and days */
+ return day + ((w - 1) * 7) + d;
+}
+
+#if 0
+int main(void)
+{
+ printf("dow = %d\n", timelib_day_of_week(1978, 12, 22)); /* 5 */
+ printf("dow = %d\n", timelib_day_of_week(2005, 2, 19)); /* 6 */
+}
+#endif
View
13,245 ext/date/lib/parse_date.c
13,245 additions, 0 deletions not shown
View
1,417 ext/date/lib/parse_date.re
@@ -0,0 +1,1417 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "datetime.h"
+
+#define TIMELIB_SECOND 1
+#define TIMELIB_MINUTE 2
+#define TIMELIB_HOUR 3
+#define TIMELIB_DAY 4
+#define TIMELIB_MONTH 5
+#define TIMELIB_YEAR 6
+#define TIMELIB_WEEKDAY 7
+
+#define EOI 257
+#define TIME 258
+#define DATE 259
+
+#define TIMELIB_XMLRPC_SOAP 260
+#define TIMELIB_TIME12 261
+#define TIMELIB_TIME24 262
+#define TIMELIB_GNU_NOCOLON 263
+#define TIMELIB_GNU_NOCOLON_TZ 264
+#define TIMELIB_ISO_NOCOLON 265
+
+#define TIMELIB_AMERICAN 266
+#define TIMELIB_ISO_DATE 267
+#define TIMELIB_DATE_FULL 268
+#define TIMELIB_DATE_TEXT 269
+#define TIMELIB_DATE_NOCOLON 270
+#define TIMELIB_PG_YEARDAY 271
+#define TIMELIB_PG_TEXT 272
+#define TIMELIB_PG_REVERSE 273
+#define TIMELIB_CLF 274
+#define TIMELIB_DATE_NO_DAY 275
+#define TIMELIB_SHORTDATE_WITH_TIME 276
+#define TIMELIB_DATE_FULL_POINTED 277
+#define TIMELIB_TIME24_WITH_ZONE 278
+#define TIMELIB_ISO_WEEK 279
+
+#define TIMELIB_TIMEZONE 300
+#define TIMELIB_AGO 301
+
+#define TIMELIB_RELATIVE 310
+
+#define ERROR 999
+
+typedef unsigned char uchar;
+
+#define BSIZE 8192
+
+#define YYCTYPE uchar
+#define YYCURSOR cursor
+#define YYLIMIT s->lim
+#define YYMARKER s->ptr
+#define YYFILL(n) return EOI;
+
+#define RET(i) {s->cur = cursor; return i;}
+
+#define timelib_string_free free
+
+#define TIMELIB_HAVE_TIME() { if (s->time->have_time) { return ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
+#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; }
+#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { return ERROR; } else { s->time->have_date = 1; } }
+#define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
+#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; }
+#define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_weekday_relative = 1; }
+#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { return ERROR; } else { s->time.have_zone = 1; } }
+
+#define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
+#define TIMELIB_DEINIT timelib_string_free(str)
+#define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
+
+#define TIMELIB_PROCESS_YEAR(x) { \
+ if ((x) == -1) { \
+ /* (x) = 0; */ \
+ } else if ((x) < 100) { \
+ if ((x) < 70) { \
+ (x) += 2000; \
+ } else { \
+ (x) += 1900; \
+ } \
+ } \
+}
+
+#ifdef DEBUG_PARSER
+#define DEBUG_OUTPUT(s) printf("%s\n", s);
+#define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
+#else
+#define DEBUG_OUTPUT(s)
+#define YYDEBUG(s,c)
+#endif
+
+#include "timelib_structs.h"
+
+typedef struct timelib_elems {
+ uint c; /* Number of elements */
+ char **v; /* Values */
+} timelib_elems;
+
+typedef struct Scanner {
+ int fd;
+ uchar *lim, *str, *ptr, *cur, *tok, *pos;
+ uint line, len;
+
+ struct timelib_time *time;
+} Scanner;
+
+typedef struct _timelib_lookup_table {
+ const char *name;
+ int type;
+ int value;
+} timelib_lookup_table;
+
+typedef struct _timelib_tz_lookup_table {
+ const char *name;
+ int type;
+ int value;
+ char *full_tz_name;
+} timelib_tz_lookup_table;
+
+typedef struct _timelib_relunit {
+ const char *name;
+ int unit;
+ int multiplier;
+} timelib_relunit;
+
+#define HOUR(a) (a * 60)
+
+/* The timezone table. */
+static timelib_tz_lookup_table const timelib_timezone_lookup[] = {
+ { "gmt", 0, HOUR ( 0), "GMT" }, /* Greenwich Mean */
+ { "ut", 0, HOUR ( 0), "UTC" }, /* Universal (Coordinated) */
+ { "utc", 0, HOUR ( 0), "UTC" },
+ { "wet", 0, HOUR ( 0), "Europe/London" }, /* Western European */
+ { "bst", 1, HOUR ( 0), "Europe/London" }, /* British Summer */
+ { "wat", 0, HOUR ( 1), "Africa/Dakar" }, /* West Africa */
+ { "at", 0, HOUR ( 2), "Atlantic/Azores" }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", 0, HOUR ( 3), NULL }, /* Brazil Standard */
+ { "gst", 0, HOUR ( 3), NULL }, /* Greenland Standard */
+#endif
+ { "nft", 0, HOUR (3.5), "America/St_Johns" }, /* Newfoundland */
+ { "nst", 0, HOUR (3.5), "America/St_Johns" }, /* Newfoundland Standard */
+ { "ndt", 1, HOUR (3.5), "America/St_Johns" }, /* Newfoundland Daylight */
+ { "ast", 0, HOUR ( 4), "America/Halifax" }, /* Atlantic Standard */
+ { "adt", 1, HOUR ( 4), "America/Halifax" }, /* Atlantic Daylight */
+ { "est", 0, HOUR ( 5), "America/New_York" }, /* Eastern Standard */
+ { "edt", 1, HOUR ( 5), "America/New_York" }, /* Eastern Daylight */
+ { "cst", 0, HOUR ( 6), "America/Chicago" }, /* Central Standard */
+ { "cdt", 1, HOUR ( 6), "America/Chicago" }, /* Central Daylight */
+ { "mst", 0, HOUR ( 7), "America/Phoenix" }, /* Mountain Standard */
+ { "mdt", 1, HOUR ( 7), "America/Phoenix" }, /* Mountain Daylight */
+ { "pst", 0, HOUR ( 8), "America/Los_Angeles" }, /* Pacific Standard */
+ { "pdt", 1, HOUR ( 8), "America/Los_Angeles" }, /* Pacific Daylight */
+ { "yst", 0, HOUR ( 9), "America/Anchorage" }, /* Yukon Standard */
+ { "ydt", 1, HOUR ( 9), "America/Anchorage" }, /* Yukon Daylight */
+ { "hst", 0, HOUR (10), "Pacific/Honolulu" }, /* Hawaii Standard */
+ { "hdt", 1, HOUR (10), "Pacific/Honolulu" }, /* Hawaii Daylight */
+ { "cat", 0, HOUR (10), "America/Anchorage" }, /* Central Alaska */
+ { "akst", 0, HOUR (10), "America/Anchorage" }, /* Alaska Standard */
+ { "akdt", 0, HOUR (10), "America/Anchorage" }, /* Alaska Daylight */
+ { "ahst", 0, HOUR (10), "America/Anchorage" }, /* Alaska-Hawaii Standard */
+ { "nt", 0, HOUR (11), NULL }, /* Nome */
+ { "idlw", 0, HOUR (12), NULL }, /* International Date Line West */
+ { "cet", 0, -HOUR (1), "Europe/Berlin" }, /* Central European */
+ { "cest", 1, -HOUR (1), "Europe/Berlin" }, /* Central European Summer */
+ { "slt", 0, -HOUR (1), "Europe/Oslo" }, /* Skien Local Time */
+ { "slst", 1, -HOUR (1), "Europe/Oslo" }, /* Skien Local Summer Time */
+ { "met", 0, -HOUR (1), "MET" }, /* Middle European */
+ { "mewt", 0, -HOUR (1), "MET" }, /* Middle European Winter */
+ { "mest", 1, -HOUR (1), "MET" }, /* Middle European Summer */
+ { "mesz", 1, -HOUR (1), "MET" }, /* Middle European Summer */
+ { "swt", 0, -HOUR (1), "Europe/Stockholm" }, /* Swedish Winter */
+ { "sst", 1, -HOUR (1), "Europe/Stockholm" }, /* Swedish Summer */
+ { "fwt", 0, -HOUR (1), "Europe/Paris" }, /* French Winter */
+ { "fst", 1, -HOUR (1), "Europe/Paris" }, /* French Summer */
+ { "eet", 0, -HOUR (2), "Europe/Bucharest" }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", 0, -HOUR (3), "Asia/Baghdad" }, /* Baghdad, USSR Zone 2 */
+ { "it", 0, -HOUR (3.5), "Asia/Tehran" },/* Iran */
+ { "zp4", 0, -HOUR (4), NULL }, /* USSR Zone 3 */
+ { "zp5", 0, -HOUR (5), NULL }, /* USSR Zone 4 */
+ { "ist", 0, -HOUR (5.5), "Asia/Calcutta" },/* Indian Standard */
+ { "zp6", 0, -HOUR (6), NULL }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Standard, and SST is
+ * also Swedish Summer. */
+ { "nst", 0, -HOUR (6.5), NULL },/* North Sumatra */
+ { "sst", 0, -HOUR (7), NULL }, /* South Sumatra, USSR Zone 6 */
+#endif
+ { "wast", 0, -HOUR (7), "Australia/Perth" }, /* West Australian Standard */
+ { "wadt", 1, -HOUR (7), "Australia/Perth" }, /* West Australian Daylight */
+ { "jt", 0, -HOUR (7.5), NULL },/* Java (3pm in Cronusland!) */
+ { "cct", 0, -HOUR (8), "Asia/Shanghai" }, /* China Coast, USSR Zone 7 */
+ { "jst", 0, -HOUR (9), "Asia/Tokyo" }, /* Japan Standard, USSR Zone 8 */
+ { "cast", 0, -HOUR (9.5), "Australia/Adelaide" },/* Central Australian Standard */
+ { "cadt", 1, -HOUR (9.5), "Australia/Adelaide" },/* Central Australian Daylight */
+ { "east", 0, -HOUR (10), "Australia/Sydney" }, /* Eastern Australian Standard */
+ { "eadt", 1, -HOUR (10), "Australia/Sydney" }, /* Eastern Australian Daylight */
+ { "gst", 0, -HOUR (10), "Pacific/Guam" }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", 0, -HOUR (12), "NZ" }, /* New Zealand */
+ { "nzst", 0, -HOUR (12), "NZ" }, /* New Zealand Standard */
+ { "nzdt", 1, -HOUR (12), "NZ" }, /* New Zealand Daylight */
+ { "idle", 0, -HOUR (12), "NZ" }, /* International Date Line East */
+
+ { "a", 0, HOUR (- 1), NULL },
+ { "b", 0, HOUR (- 2), NULL },
+ { "c", 0, HOUR (- 3), NULL },
+ { "d", 0, HOUR (- 4), NULL },
+ { "e", 0, HOUR (- 5), NULL },
+ { "f", 0, HOUR (- 6), NULL },
+ { "g", 0, HOUR (- 7), NULL },
+ { "h", 0, HOUR (- 8), NULL },
+ { "i", 0, HOUR (- 9), NULL },
+ { "k", 0, HOUR (-10), NULL },
+ { "l", 0, HOUR (-11), NULL },
+ { "m", 0, HOUR (-12), NULL },
+ { "n", 0, HOUR ( 1), NULL },
+ { "o", 0, HOUR ( 2), NULL },
+ { "p", 0, HOUR ( 3), NULL },
+ { "q", 0, HOUR ( 4), NULL },
+ { "r", 0, HOUR ( 5), NULL },
+ { "s", 0, HOUR ( 6), NULL },
+ { "t", 0, HOUR ( 7), NULL },
+ { "u", 0, HOUR ( 8), NULL },
+ { "v", 0, HOUR ( 9), NULL },
+ { "w", 0, HOUR ( 10), NULL },
+ { "x", 0, HOUR ( 11), NULL },
+ { "y", 0, HOUR ( 12), NULL },
+ { "z", 0, HOUR ( 0), NULL },
+ { NULL, 0, 0, NULL }
+};
+
+static timelib_relunit const timelib_relunit_lookup[] = {
+ { "sec", TIMELIB_SECOND, 1 },
+ { "secs", TIMELIB_SECOND, 1 },
+ { "second", TIMELIB_SECOND, 1 },
+ { "seconds", TIMELIB_SECOND, 1 },
+ { "min", TIMELIB_MINUTE, 1 },
+ { "mins", TIMELIB_MINUTE, 1 },
+ { "minute", TIMELIB_MINUTE, 1 },
+ { "minutes", TIMELIB_MINUTE, 1 },
+ { "hour", TIMELIB_HOUR, 1 },
+ { "hours", TIMELIB_HOUR, 1 },
+ { "day", TIMELIB_DAY, 1 },
+ { "days", TIMELIB_DAY, 1 },
+ { "week", TIMELIB_DAY, 7 },
+ { "weeks", TIMELIB_DAY, 7 },
+ { "fortnight", TIMELIB_DAY, 14 },
+ { "fortnights", TIMELIB_DAY, 14 },
+ { "forthnight", TIMELIB_DAY, 14 },
+ { "forthnights", TIMELIB_DAY, 14 },
+ { "month", TIMELIB_MONTH, 1 },
+ { "months", TIMELIB_MONTH, 1 },
+ { "year", TIMELIB_YEAR, 1 },
+ { "years", TIMELIB_YEAR, 1 },
+
+ { "monday", TIMELIB_WEEKDAY, 1 },
+ { "tuesday", TIMELIB_WEEKDAY, 2 },
+ { "wednesday", TIMELIB_WEEKDAY, 3 },
+ { "thursday", TIMELIB_WEEKDAY, 4 },
+ { "friday", TIMELIB_WEEKDAY, 5 },
+ { "saturday", TIMELIB_WEEKDAY, 6 },
+ { "sunday", TIMELIB_WEEKDAY, 0 },
+
+ { NULL, 0, 0 }
+};
+
+/* The relative text table. */
+static timelib_lookup_table const timelib_reltext_lookup[] = {
+ { "first", 0, 1 },
+ { "next", 0, 1 },
+ { "second", 0, 2 },
+ { "third", 0, 3 },
+ { "fourth", 0, 4 },
+ { "fifth", 0, 5 },
+ { "sixth", 0, 6 },
+ { "seventh", 0, 7 },
+ { "eight", 0, 8 },
+ { "ninth", 0, 9 },
+ { "tenth", 0, 10 },
+ { "eleventh", 0, 11 },
+ { "twelfth", 0, 12 },
+ { "last", 0, -1 },
+ { "previous", 0, -1 },
+ { "this", 0, 0 },
+ { NULL, 0, 0 }
+};
+
+/* The month table. */
+static timelib_lookup_table const timelib_month_lookup[] = {
+ { "jan", 0, 1 },
+ { "feb", 0, 2 },
+ { "mar", 0, 3 },
+ { "apr", 0, 4 },
+ { "may", 0, 5 },
+ { "jun", 0, 6 },
+ { "jul", 0, 7 },
+ { "aug", 0, 8 },
+ { "sep", 0, 9 },
+ { "sept", 0, 9 },
+ { "oct", 0, 10 },
+ { "nov", 0, 11 },
+ { "dec", 0, 12 },
+ { "i", 0, 1 },
+ { "ii", 0, 2 },
+ { "iii", 0, 3 },
+ { "iv", 0, 4 },
+ { "v", 0, 5 },
+ { "vi", 0, 6 },
+ { "vii", 0, 7 },
+ { "viii", 0, 8 },
+ { "ix", 0, 9 },
+ { "x", 0, 10 },
+ { "xi", 0, 11 },
+ { "xii", 0, 12 },
+
+ { "january", 0, 1 },
+ { "february", 0, 2 },
+ { "march", 0, 3 },
+ { "april", 0, 4 },
+ { "may", 0, 5 },
+ { "june", 0, 6 },
+ { "july", 0, 7 },
+ { "august", 0, 8 },
+ { "september", 0, 9 },
+ { "october", 0, 10 },
+ { "november", 0, 11 },
+ { "december", 0, 12 },
+ { NULL, 0, 0 }
+};
+
+#if 0
+static char* timelib_ltrim(char *s)
+{
+ char *ptr = s;
+ while (ptr[0] == ' ') {
+ ptr++;
+ }
+ return ptr;
+}
+#endif
+
+#if 0
+uchar *fill(Scanner *s, uchar *cursor){
+ if(!s->eof){
+ uint cnt = s->tok - s->bot;
+ if(cnt){
+ memcpy(s->bot, s->tok, s->lim - s->tok);
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ cursor -= cnt;
+ s->pos -= cnt;
+ s->lim -= cnt;
+ }
+ if((s->top - s->lim) < BSIZE){
+ uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
+ memcpy(buf, s->tok, s->lim - s->tok);
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ cursor = &buf[cursor - s->bot];
+ s->pos = &buf[s->pos - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ free(s->bot);
+ s->bot = buf;
+ }
+ if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
+ s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
+ }
+ s->lim += cnt;
+ }
+ return cursor;
+}
+#endif
+
+static int timelib_meridian(char **ptr, int h)
+{
+ int retval = 0;
+
+ while (!strchr("AaPp", **ptr)) {
+ ++*ptr;
+ }
+ if (**ptr == 'a' || **ptr == 'A') {
+ if (h == 12) {
+ retval = -12;
+ }
+ } else if (h != 12) {
+ retval = 12;
+ }
+ ++*ptr;
+ if (**ptr == '.') {
+ *ptr += 3;
+ } else {
+ ++*ptr;
+ }
+ return retval;
+}
+
+static char *timelib_string(Scanner *s)
+{
+ char *tmp = calloc(1, s->cur - s->tok + 1);
+ memcpy(tmp, s->tok, s->cur - s->tok);
+
+ return tmp;
+}
+
+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+ char *begin, *end, *str;
+ timelib_sll tmp_nr = -1;
+ int len = 0;
+
+ while ((**ptr < '0') || (**ptr > '9')) {
+ if (**ptr == '\0') {
+ return -1;
+ }
+ ++*ptr;
+ }
+ begin = *ptr;
+ while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
+ ++*ptr;
+ ++len;
+ }
+ end = *ptr;
+ str = calloc(1, end - begin + 1);
+ memcpy(str, begin, end - begin);
+ tmp_nr = strtoll(str, NULL, 10);
+ free(str);
+ return tmp_nr;
+}
+
+static float timelib_get_frac_nr(char **ptr, int max_length)
+{
+ char *begin, *end, *str;
+ float tmp_nr = -1;
+ int len = 0;
+
+ while ((**ptr != '.') && ((**ptr < '0') || (**ptr > '9'))) {
+ if (**ptr == '\0') {
+ return -1;
+ }
+ ++*ptr;
+ }
+ begin = *ptr;
+ while (((**ptr == '.') || ((**ptr >= '0') && (**ptr <= '9'))) && len < max_length) {
+ ++*ptr;
+ ++len;
+ }
+ end = *ptr;
+ str = calloc(1, end - begin + 1);
+ memcpy(str, begin, end - begin);
+ tmp_nr = strtod(str, NULL);
+ free(str);
+ return tmp_nr;
+}
+
+static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
+{
+ timelib_ull dir = 1;
+
+ while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
+ if (**ptr == '\0') {
+ return -1;
+ }
+ ++*ptr;
+ }
+ if (**ptr == '+') {
+ ++*ptr;
+ } else if (**ptr == '-') {
+ dir = -1;
+ ++*ptr;
+ }
+ return dir * timelib_get_nr(ptr, max_length);
+}
+
+static long timelib_parse_tz_cor(char **ptr)
+{
+ char *begin = *ptr, *end;
+ long tmp;
+
+ while (**ptr != '\0') {
+ ++*ptr;
+ }
+ end = *ptr;
+ switch (end - begin) {
+ case 1:
+ case 2:
+ return HOUR(strtol(begin, NULL, 10));
+ break;
+ case 3:
+ case 4:
+ tmp = strtol(begin, NULL, 10);
+ return HOUR(tmp / 100) + tmp % 100;
+ case 5:
+ tmp = HOUR(strtol(begin, NULL, 10)) +
+ strtol(begin + 3, NULL, 10);
+ return tmp;
+ }
+ return 0;
+}
+
+static long timelib_lookup_relative_text(char **ptr)
+{
+ char *word;
+ char *begin = *ptr, *end;
+ long value = 0;
+ const timelib_lookup_table *tp;
+
+ while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
+ ++*ptr;
+ }
+ end = *ptr;
+ word = calloc(1, end - begin + 1);
+ memcpy(word, begin, end - begin);
+
+ for (tp = timelib_reltext_lookup; tp->name; tp++) {
+ if (strcasecmp(word, tp->name) == 0) {
+ value = tp->value;
+ }
+ }
+
+ free(word);
+ return value;
+}
+
+static long timelib_get_relative_text(char **ptr)
+{
+ while (**ptr == ' ' || **ptr == '-' || **ptr == '/') {
+ ++*ptr;
+ }
+ return timelib_lookup_relative_text(ptr);
+}
+
+static long timelib_lookup_month(char **ptr)
+{
+ char *word;
+ char *begin = *ptr, *end;
+ long value = 0;
+ const timelib_lookup_table *tp;
+
+ while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
+ ++*ptr;
+ }
+ end = *ptr;
+ word = calloc(1, end - begin + 1);
+ memcpy(word, begin, end - begin);
+
+ for (tp = timelib_month_lookup; tp->name; tp++) {
+ if (strcasecmp(word, tp->name) == 0) {
+ value = tp->value;
+ }
+ }
+
+ free(word);
+ return value;
+}
+
+static long timelib_get_month(char **ptr)
+{
+ while (**ptr == ' ' || **ptr == '-' || **ptr == '.' || **ptr == '/') {
+ ++*ptr;
+ }
+ return timelib_lookup_month(ptr);
+}
+
+static void timelib_eat_spaces(char **ptr)
+{
+ while (**ptr == ' ') {
+ ++*ptr;
+ }
+}
+
+static const timelib_relunit* timelib_lookup_relunit(char **ptr)
+{
+ char *word;
+ char *begin = *ptr, *end;
+ const timelib_relunit *tp, *value = NULL;
+
+ while (**ptr != '\0' && **ptr != ' ') {
+ ++*ptr;
+ }
+ end = *ptr;
+ word = calloc(1, end - begin + 1);
+ memcpy(word, begin, end - begin);
+
+ for (tp = timelib_relunit_lookup; tp->name; tp++) {
+ if (strcasecmp(word, tp->name) == 0) {
+ value = tp;
+ break;
+ }
+ }
+
+ free(word);
+ return value;
+}
+
+static void timelib_set_relative(char **ptr, long amount, Scanner *s)
+{
+ const timelib_relunit* relunit;
+
+ relunit = timelib_lookup_relunit(ptr);
+ switch (relunit->unit) {
+ case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
+ case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
+ case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break;
+ case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break;
+ case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break;
+ case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break;
+
+ case TIMELIB_WEEKDAY:
+ TIMELIB_HAVE_WEEKDAY_RELATIVE();
+ TIMELIB_UNHAVE_TIME();
+ s->time->relative.d += (amount > 0 ? amount - 1 : amount) * 7;
+ s->time->relative.weekday = relunit->multiplier;
+ break;
+ }
+}
+
+static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, char **tz_name)
+{
+ char *word;
+ char *begin = *ptr, *end;
+ long value = 0;
+ const timelib_tz_lookup_table *tp;
+
+ while (**ptr != '\0') {
+ ++*ptr;
+ }
+ end = *ptr;
+ word = calloc(1, end - begin + 1);
+ memcpy(word, begin, end - begin);
+ *tz_name = NULL;
+
+ for (tp = timelib_timezone_lookup; tp->name; tp++) {
+ if (strcasecmp(word, tp->name) == 0) {
+ value = tp->value;
+ *dst = tp->type;
+/*
+ if (tp->full_tz_name) {
+ *tz_name = tp->full_tz_name;
+ }
+*/
+ break;
+ }
+ }
+
+ *tz_abbr = word;
+ return value;
+}
+
+static long timelib_get_zone(char **ptr, int *dst, timelib_time *t)
+{
+ timelib_tzinfo *res;
+
+ while (**ptr == ' ') {
+ ++*ptr;
+ }
+ if (**ptr == '+') {
+ ++*ptr;
+ t->is_localtime = 1;
+ t->zone_type = TIMELIB_ZONETYPE_OFFSET;
+
+ return -1 * timelib_parse_tz_cor(ptr);
+ } else if (**ptr == '-') {
+ ++*ptr;
+ t->is_localtime = 1;
+ t->zone_type = TIMELIB_ZONETYPE_OFFSET;
+
+ return timelib_parse_tz_cor(ptr);
+ } else {
+ long offset;
+ char *tz_abbr, *tz_name;
+
+ t->is_localtime = 1;
+ t->zone_type = TIMELIB_ZONETYPE_ABBR;
+ offset = timelib_lookup_zone(ptr, dst, &tz_abbr, &tz_name);
+ /* If we found a TimeZone identifier, use it */
+ if (tz_name) {
+ t->tz_info = timelib_parse_tzfile(tz_name);
+ t->zone_type = TIMELIB_ZONETYPE_ID;
+ }
+ /* If we have a TimeZone identifier to start with, use it */
+ if (strstr(tz_abbr, "/")) {
+ if ((res = timelib_parse_tzfile(tz_abbr)) != NULL) {
+ t->tz_info = res;
+ t->zone_type = TIMELIB_ZONETYPE_ID;
+ }
+ }
+ if (t->zone_type != TIMELIB_ZONETYPE_ID) {
+ timelib_time_tz_abbr_update(t, tz_abbr);
+ }
+ free(tz_abbr);
+ return offset;
+ }
+}
+
+#define timelib_split_free(arg) { \
+ int i; \
+ for (i = 0; i < arg.c; i++) { \
+ free(arg.v[i]); \
+ } \
+ if (arg.v) { \
+ free(arg.v); \
+ } \
+}
+
+static int scan(Scanner *s)
+{
+ uchar *cursor = s->cur;
+ char *str, *ptr = NULL;
+
+std:
+ s->tok = cursor;
+ s->len = 0;
+/*!re2c
+any = [\000-\377];
+
+space = [ ]+;
+frac = "."[0-9]+;
+
+ago = 'ago';
+
+hour24 = [01]?[0-9] | "2"[0-3];
+hour24lz = [01][0-9] | "2"[0-3];
+hour12 = "0"?[1-9] | "1"[0-2];
+minute = [0-5]?[0-9];
+minutelz = [0-5][0-9];
+second = minute | "60";
+secondlz = minutelz | "60";
+meridian = [AaPp] "."? [Mm] "."?;
+tz = [A-Za-z]+ | [A-Z][a-z]+("/"[A-Z][a-z]+)+;
+tzcorrection = [+-] hour24 ":"? minutelz?;
+
+month = "0"? [0-9] | "1"[0-2];
+day = [0-2]?[0-9] | "3"[01];
+year = [0-9]{1,4};
+year2 = [0-9]{2};
+year4 = [0-9]{4};
+
+dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
+weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
+
+monthlz = "0" [1-9] | "1" [0-2];
+daylz = "0" [1-9] | [1-2][0-9] | "3" [01];
+
+dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
+dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
+daytext = dayfull | dayabbr;
+
+monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
+monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
+monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
+monthtext = monthfull | monthabbr | monthroman;
+
+/* Time formats */
+timeshort12 = hour12[:]minutelz space? meridian;
+timelong12 = hour12[:]minute[:]secondlz space? meridian;
+
+timeshort24 = hour24[:]minute;
+timelong24 = hour24[:]minute[:]second;
+iso8601long = hour24 [:] minute [:] second frac;
+
+/* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
+iso8601normtz = hour24 [:] minute [:] secondlz space? (tzcorrection | tz);
+/* iso8601longtz = hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
+
+gnunocolon = hour24lz minutelz;
+/* gnunocolontz = hour24lz minutelz space? (tzcorrection | tz); */
+iso8601nocolon = hour24lz minutelz secondlz;
+/* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
+
+/* Date formats */
+americanshort = month "/" day;
+american = month "/" day "/" year;
+iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
+gnudateshort = year "-" month "-" day;
+iso8601date = year4 "-" monthlz "-" daylz;
+pointeddate = day "." month "." year;
+datefull = day ([ -.])* monthtext ([ -.])* year;
+datenoday = monthtext ([ -.])* year4;
+datenodayrev = year4 ([ -.])* monthtext;
+datetextual = monthtext space? day [,.stndrh ]* year;
+datenoyear = monthtext space? day [,.stndrh ]*;
+datenocolon = year4 monthlz daylz;
+
+/* Special formats */
+soap = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection;
+xmlrpc = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
+xmlrpcnocolon = year4 monthlz daylz 't' hour24 minutelz secondlz;
+wddx = year4 "-" monthlz "-" daylz "T" hour24 ":" minutelz ":" secondlz;
+pgydotd = year4 "."? dayofyear;
+pgtextshort = monthabbr "-" daylz "-" year;
+pgtextreverse = year "-" monthabbr "-" daylz;
+isoweekday = year4 "W" weekofyear [0-7];
+
+/* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
+clf = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
+
+/* Timestamp format: @1126396800 */
+timestamp = "@" [1-9] [0-9]*;
+
+/* To fix some ambiguities */
+dateshortwithtimeshort = datenoyear timeshort24;
+dateshortwithtimelong = datenoyear timelong24;
+dateshortwithtimelongtz = datenoyear iso8601normtz;
+
+/*
+ * Relative regexps
+ */
+reltextnumber = 'first'|'next'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'ninth'|'tenth'|'eleventh'|'twelfth'|'last'|'previous'|'this';
+reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'week'|'fortnight'|'forthnight'|'month'|'year') 's'?) | dayfull;
+
+relnumber = ([+-]?[0-9]+);
+relative = (relnumber space reltextunit)+;
+relativetext = (reltextnumber space reltextunit)+;
+
+*/
+
+/*!re2c
+ /* so that vim highlights correctly */
+ "yesterday"
+ {
+ DEBUG_OUTPUT("yesterday");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+ TIMELIB_UNHAVE_TIME();
+
+ s->time->relative.d = -1;
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ "now"
+ {
+ DEBUG_OUTPUT("now");
+ TIMELIB_INIT;
+
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ "today"
+ {
+ DEBUG_OUTPUT("today");
+ TIMELIB_INIT;
+ TIMELIB_UNHAVE_TIME();
+
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ "tomorrow"
+ {
+ DEBUG_OUTPUT("tomorrow");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+ TIMELIB_UNHAVE_TIME();
+
+ s->time->relative.d = 1;
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ timestamp
+ {
+ timelib_ull i;
+
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+ TIMELIB_UNHAVE_DATE();
+ TIMELIB_UNHAVE_TIME();
+
+ i = timelib_get_unsigned_nr((char **) &ptr, 24);
+ s->time->y = 1970;
+ s->time->m = 1;
+ s->time->d = 1;
+ s->time->h = s->time->i = s->time->s = s->time->f = 0;
+ s->time->relative.s += i;
+ s->time->is_localtime = 1;
+ s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
+ s->time->z = 0;
+
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ timeshort12 | timelong12
+ {
+ DEBUG_OUTPUT("timeshort12 | timelong12");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_TIME();
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ if (*ptr == ':') {
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+ }
+ s->time->h += timelib_meridian((char **) &ptr, s->time->h);
+ TIMELIB_DEINIT;
+ return TIMELIB_TIME12;
+ }
+
+ timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
+ {
+ DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_TIME();
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ if (*ptr == ':') {
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+
+ if (*ptr == '.') {
+ s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
+ }
+ }
+
+ if (*ptr != '\0') {
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_TIME24_WITH_ZONE;
+ }
+
+ gnunocolon
+ {
+ DEBUG_OUTPUT("gnunocolon");
+ TIMELIB_INIT;
+ switch (s->time->have_time) {
+ case 0:
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ s->time->s = 0;
+ break;
+ case 1:
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ break;
+ default:
+ TIMELIB_DEINIT;
+ return ERROR;
+ }
+ s->time->have_time++;
+ TIMELIB_DEINIT;
+ return TIMELIB_GNU_NOCOLON;
+ }
+/*
+ gnunocolontz
+ {
+ DEBUG_OUTPUT("gnunocolontz");
+ TIMELIB_INIT;
+ switch (s->time->have_time) {
+ case 0:
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ s->time->s = 0;
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ break;
+ case 1:
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ break;
+ default:
+ TIMELIB_DEINIT;
+ return ERROR;
+ }
+ s->time->have_time++;
+ TIMELIB_DEINIT;
+ return TIMELIB_GNU_NOCOLON_TZ;
+ }
+*/
+ iso8601nocolon /*| iso8601nocolontz*/
+ {
+ DEBUG_OUTPUT("iso8601nocolon");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_TIME();
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+
+ if (*ptr != '\0') {
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_ISO_NOCOLON;
+ }
+
+ americanshort | american
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ if (*ptr == '/') {
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_AMERICAN;
+ }
+
+ iso8601date | iso8601dateslash
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_DEINIT;
+ return TIMELIB_ISO_DATE;
+ }
+
+ gnudateshort
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_ISO_DATE;
+ }
+
+ datefull
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_FULL;
+ }
+
+ pointeddate
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_FULL_POINTED;
+ }
+
+ datenoday
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->d = 1;
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_NO_DAY;
+ }
+
+ datenodayrev
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->d = 1;
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_NO_DAY;
+ }
+
+ datetextual | datenoyear
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_TEXT;
+ }
+
+ datenocolon
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_NOCOLON;
+ }
+
+ xmlrpc | xmlrpcnocolon | soap | wddx
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_TIME();
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+ if (*ptr == '.') {
+ s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_XMLRPC_SOAP;
+ }
+
+ pgydotd
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->d = timelib_get_nr((char **) &ptr, 3);
+ s->time->m = 1;
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_PG_YEARDAY;
+ }
+
+ isoweekday
+ {
+ int w, d;
+
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ TIMELIB_HAVE_RELATIVE();
+
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ w = timelib_get_nr((char **) &ptr, 2);
+ d = timelib_get_nr((char **) &ptr, 1);
+ s->time->m = 1;
+ s->time->d = 1;
+ s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
+
+ TIMELIB_DEINIT;
+ return TIMELIB_ISO_WEEK;
+ }
+
+ pgtextshort
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_PG_TEXT;
+ }
+
+ pgtextreverse
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_PROCESS_YEAR(s->time->y);
+ TIMELIB_DEINIT;
+ return TIMELIB_PG_TEXT;
+ }
+
+ clf
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_TIME();
+ TIMELIB_HAVE_DATE();
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->y = timelib_get_nr((char **) &ptr, 4);
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ TIMELIB_DEINIT;
+ return TIMELIB_CLF;
+ }
+
+ ago
+ {
+ TIMELIB_INIT;
+ s->time->relative.y = 0 - s->time->relative.y;
+ s->time->relative.m = 0 - s->time->relative.m;
+ s->time->relative.d = 0 - s->time->relative.d;
+ s->time->relative.h = 0 - s->time->relative.h;
+ s->time->relative.i = 0 - s->time->relative.i;
+ s->time->relative.s = 0 - s->time->relative.s;
+ s->time->relative.weekday = 0 - s->time->relative.weekday;
+ TIMELIB_DEINIT;
+ return TIMELIB_AGO;
+ }
+
+ relativetext
+ {
+ long i;
+
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+
+ while(*ptr) {
+ i = timelib_get_relative_text((char **) &ptr);
+ timelib_eat_spaces((char **) &ptr);
+ timelib_set_relative((char **) &ptr, i, s);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ dayfull
+ {
+ const timelib_relunit* relunit;
+
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+ TIMELIB_HAVE_WEEKDAY_RELATIVE();
+ TIMELIB_UNHAVE_TIME();
+
+ relunit = timelib_lookup_relunit((char**) &ptr);
+ s->time->relative.weekday = relunit->multiplier;
+
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ dayabbr
+ {
+ goto std;
+ }
+
+ tzcorrection | tz
+ {
+ TIMELIB_INIT;
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ TIMELIB_DEINIT;
+ return TIMELIB_TIMEZONE;
+ }
+
+ dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
+ {
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->m = timelib_get_month((char **) &ptr);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+
+ TIMELIB_HAVE_TIME();
+ s->time->h = timelib_get_nr((char **) &ptr, 2);
+ s->time->i = timelib_get_nr((char **) &ptr, 2);
+ if (*ptr == ':') {
+ s->time->s = timelib_get_nr((char **) &ptr, 2);
+
+ if (*ptr == '.') {
+ s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
+ }
+ }
+
+ if (*ptr != '\0') {
+ s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_SHORTDATE_WITH_TIME;
+ }
+
+ relative
+ {
+ timelib_ull i;
+
+ TIMELIB_INIT;
+ TIMELIB_HAVE_RELATIVE();
+
+ while(*ptr) {
+ i = timelib_get_unsigned_nr((char **) &ptr, 24);
+ timelib_eat_spaces((char **) &ptr);
+ timelib_set_relative((char **) &ptr, i, s);
+ }
+ TIMELIB_DEINIT;
+ return TIMELIB_RELATIVE;
+ }
+
+ [ .,]
+ {
+ goto std;
+ }
+
+ "\0"|"\n"
+ {
+ s->pos = cursor; s->line++;
+ goto std;
+ }
+
+ any
+ {
+ printf("unexpected character: #%d, %c\n", *s->tok, *s->tok);
+ goto std;
+ }
+*/
+}
+
+/*!max:re2c */
+
+timelib_time* timelib_strtotime(char *s)
+{
+ Scanner in;
+ int t;
+
+ memset(&in, 0, sizeof(in));
+ in.str = malloc(strlen(s) + 25);
+ memset(in.str, 0, strlen(s) + 25);
+ memcpy(in.str, s, strlen(s));
+ in.lim = in.str + strlen(s) + 25;
+ in.cur = in.str;
+ in.time = timelib_time_ctor();
+ in.time->y = -1;
+ in.time->d = -1;
+ in.time->m = -1;
+ in.time->h = -1;
+ in.time->i = -1;
+ in.time->s = -1;
+ in.time->f = -1;
+ in.time->z = -1;
+ in.time->dst = -1;
+
+ do {
+ t = scan(&in);
+/* printf("%d\n", t); */
+ } while(t != EOI);
+
+ free(in.str);
+
+ return in.time;
+}
+
+void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
+{
+ if (!(options && TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
+ parsed->h = 0;
+ parsed->i = 0;
+ parsed->s = 0;
+ parsed->f = 0;
+ }
+ if (parsed->y == -1) parsed->y = now->y != -1 ? now->y : 0;
+ if (parsed->d == -1) parsed->d = now->d != -1 ? now->d : 0;
+ if (parsed->m == -1) parsed->m = now->m != -1 ? now->m : 0;
+ if (parsed->h == -1) parsed->h = now->h != -1 ? now->h : 0;
+ if (parsed->i == -1) parsed->i = now->i != -1 ? now->i : 0;
+ if (parsed->s == -1) parsed->s = now->s != -1 ? now->s : 0;
+ if (parsed->f == -1) parsed->f = now->f != -1 ? now->f : 0;
+ if (parsed->z == -1) parsed->z = now->z != -1 ? now->z : 0;
+ if (parsed->dst == -1) parsed->dst = now->dst != -1 ? now->dst : 0;
+
+ if (!parsed->tz_abbr) {
+ parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
+ }
+ if (!parsed->tz_info) {
+ parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
+ }
+ if (parsed->zone_type == 0 && now->zone_type != 0) {
+ parsed->zone_type = now->zone_type;
+/* parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
+ parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
+*/ parsed->is_localtime = 1;
+ }
+/* timelib_dump_date(parsed, 2);
+ timelib_dump_date(now, 2);
+*/
+}
+
+
+#ifdef DEBUG_PARSER_STUB
+int main(void)
+{
+ timelib_time time = timelib_strtotime("May 12");
+
+ printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
+ time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
+ if (time.have_relative) {
+ printf ("%3dY %3dM %3dD / %3dH %3dM %3dS",
+ time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
+ }
+ if (time.have_weekday_relative) {
+ printf (" / %d", time.relative.weekday);
+ }
+ if (time.have_weeknr_day) {
+ printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
+ }
+ return 0;
+}
+#endif
+
+/*
+ * vim: syntax=c
+ */
View
283 ext/date/lib/parse_tz.c
@@ -0,0 +1,283 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include "datetime.h"
+#include "timezonedb.h"
+
+static void read_header(char **tzf, timelib_tzinfo *tz)
+{
+ uint32_t buffer[6];
+
+ memcpy(&buffer, *tzf, sizeof(buffer));
+ tz->ttisgmtcnt = htonl(buffer[0]);
+ tz->ttisstdcnt = htonl(buffer[1]);
+ tz->leapcnt = htonl(buffer[2]);
+ tz->timecnt = htonl(buffer[3]);
+ tz->typecnt = htonl(buffer[4]);
+ tz->charcnt = htonl(buffer[5]);
+ *tzf += sizeof(buffer);
+}
+
+static void read_transistions(char **tzf, timelib_tzinfo *tz)
+{
+ int32_t *buffer = NULL, i;
+ unsigned char *cbuffer = NULL;
+
+ if (tz->timecnt) {
+ buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
+ if (!buffer) {
+ return;
+ }
+ memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
+ *tzf += (sizeof(int32_t) * tz->timecnt);
+ for (i = 0; i < tz->timecnt; i++) {
+ buffer[i] = htonl(buffer[i]);
+ }
+
+ cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
+ if (!cbuffer) {
+ return;
+ }
+ memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
+ *tzf += sizeof(unsigned char) * tz->timecnt;
+ }
+
+ tz->trans = buffer;
+ tz->trans_idx = cbuffer;
+}
+
+static void read_types(char **tzf, timelib_tzinfo *tz)
+{
+ unsigned char *buffer;
+ int32_t *leap_buffer;
+ unsigned int i, j;
+
+ buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
+ if (!buffer) {
+ return;
+ }
+ memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
+ *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
+
+ tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
+
+ for (i = 0; i < tz->typecnt; i++) {
+ j = i * 6;
+ tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
+ tz->type[i].isdst = buffer[j + 4];
+ tz->type[i].abbr_idx = buffer[j + 5];
+ }
+ free(buffer);
+
+ tz->timezone_abbr = (char*) malloc(tz->charcnt);
+ if (!tz->timezone_abbr) {
+ return;
+ }
+ memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
+ *tzf += sizeof(char) * tz->charcnt;
+
+ leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
+ if (!leap_buffer) {
+ return;
+ }
+ memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
+ *tzf += sizeof(int32_t) * tz->leapcnt * 2;
+
+ tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
+ if (!tz->leap_times) {
+ return;
+ }
+ for (i = 0; i < tz->leapcnt; i++) {
+ tz->leap_times[i].trans = htonl(leap_buffer[i * 2]);
+ tz->leap_times[i].offset = htonl(leap_buffer[i * 2 + 1]);
+ }
+ free(leap_buffer);
+
+ buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
+ if (!buffer) {
+ return;
+ }
+ memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
+ *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
+
+ for (i = 0; i < tz->ttisstdcnt; i++) {
+ tz->type[i].isstdcnt = buffer[i];
+ }
+ free(buffer);
+
+ buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
+ if (!buffer) {
+ return;
+ }
+ memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
+ *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
+
+ for (i = 0; i < tz->ttisgmtcnt; i++) {
+ tz->type[i].isgmtcnt = buffer[i];
+ }
+ free(buffer);
+}
+
+#if 0
+static void dumpinfo(timelib_tzinfo *tz)
+{
+ uint32_t i;
+
+ printf("UTC/Local count: %lu\n", (unsigned long) tz->ttisgmtcnt);
+ printf("Std/Wall count: %lu\n", (unsigned long) tz->ttisstdcnt);
+ printf("Leap.sec. count: %lu\n", (unsigned long) tz->leapcnt);
+ printf("Trans. count: %lu\n", (unsigned long) tz->timecnt);
+ printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
+ printf("Zone Abbr. count: %lu\n", (unsigned long) tz->charcnt);
+
+ for (i = 0; i < tz->timecnt; i++) {
+ printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
+ tz->trans[i], tz->trans[i], tz->trans_idx[i],
+ tz->type[tz->trans_idx[i]].offset,
+ tz->type[tz->trans_idx[i]].isdst,
+ tz->type[tz->trans_idx[i]].abbr_idx,
+ &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
+ tz->type[tz->trans_idx[i]].isstdcnt,
+ tz->type[tz->trans_idx[i]].isgmtcnt
+ );
+ }
+ for (i = 0; i < tz->leapcnt; i++) {
+ printf ("%08X (%12ld) = %d\n",
+ tz->leap_times[i].trans,
+ (long) tz->leap_times[i].trans,
+ tz->leap_times[i].offset);
+ }
+}
+#endif
+
+static int seek_to_tz_position(char **tzf, char *timezone)
+{
+ int found;
+ tzdb_idx *ptr;
+
+ /* Reset Index Position */
+ ptr = timezonedb_idx;
+
+ /* Start scanning the index file for the timezone */
+ found = 0;
+ do {
+ if (strcmp(timezone, ptr->id) == 0) {
+ found = 1;
+ (*tzf) = &php_timezone_db_index[ptr->pos + 20];
+ break;
+ }
+ ptr++;
+ } while (ptr->id != NULL);
+ if (!found) {
+ return 0;
+ }
+ return 1;
+}
+
+timelib_tzinfo *timelib_parse_tzfile(char *timezone)
+{
+ char *tzf;
+ timelib_tzinfo *tmp;
+
+ if (seek_to_tz_position((char**) &tzf, timezone)) {
+ tmp = timelib_tzinfo_ctor(timezone);
+
+ read_header((char**) &tzf, tmp);
+ read_transistions((char**) &tzf, tmp);
+ read_types((char**) &tzf, tmp);
+ } else {
+ tmp = NULL;
+ }
+
+ return tmp;
+}
+
+static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts)
+{
+ int i;
+
+ if (!tz->timecnt || !tz->trans) {
+ return NULL;
+ }
+
+ for (i = 0; i < tz->timecnt; i++) {
+ if (ts < tz->trans[i]) {
+ return &(tz->type[tz->trans_idx[i - 1]]);
+ }
+ }
+ return NULL;
+}
+
+static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
+{
+ int i;
+
+ if (!tz->leapcnt || !tz->leap_times) {
+ return NULL;
+ }
+
+ for (i = tz->leapcnt - 1; i > 0; i--) {
+ if (ts > tz->leap_times[i].trans) {
+ return &(tz->leap_times[i]);
+ }
+ }
+ return NULL;
+}
+
+int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
+{
+ ttinfo *to;
+ if ((to = fetch_timezone_offset(tz, ts))) {
+ return to->isdst;
+ }
+ return -1;
+}
+
+timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
+{
+ ttinfo *to;
+ tlinfo *tl;
+ int32_t offset = 0, leap_secs = 0;
+ char *abbr;
+ timelib_time_offset *tmp = timelib_time_offset_ctor();
+
+ if ((to = fetch_timezone_offset(tz, ts))) {
+ offset = to->offset;
+ abbr = &(tz->timezone_abbr[to->abbr_idx]);
+ tmp->is_dst = to->isdst;
+ } else {
+ abbr = tz->timezone_abbr;
+ tmp->is_dst = 0;
+ }
+
+ if ((tl = fetch_leaptime_offset(tz, ts))) {
+ leap_secs = -tl->offset;
+ }
+
+ tmp->offset = offset;
+ tmp->leap_secs = leap_secs;
+ tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
+
+ return tmp;
+}
View
5 ext/date/lib/resource/README
@@ -0,0 +1,5 @@
+Regenerating Parser
+===================
+
+Make sure you use re2c 0.97 or higher:
+/dat/dev/sf/re2c/re2c -d -b parse_date.re > ../parse_date.c
View
1,417 ext/date/lib/resource/parse_date.re
@@ -0,0 +1,1417 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <dr@ez.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "datetime.h"
+
+#define TIMELIB_SECOND 1
+#define TIMELIB_MINUTE 2
+#define TIMELIB_HOUR 3
+#define TIMELIB_DAY 4
+#define TIMELIB_MONTH 5
+#define TIMELIB_YEAR 6
+#define TIMELIB_WEEKDAY 7
+
+#define EOI 257
+#define TIME 258
+#define DATE 259
+
+#define TIMELIB_XMLRPC_SOAP 260
+#define TIMELIB_TIME12 261
+#define TIMELIB_TIME24 262
+#define TIMELIB_GNU_NOCOLON 263
+#define TIMELIB_GNU_NOCOLON_TZ 264
+#define TIMELIB_ISO_NOCOLON 265
+
+#define TIMELIB_AMERICAN 266
+#define TIMELIB_ISO_DATE 267
+#define TIMELIB_DATE_FULL 268
+#define TIMELIB_DATE_TEXT 269
+#define TIMELIB_DATE_NOCOLON 270
+#define TIMELIB_PG_YEARDAY 271
+#define TIMELIB_PG_TEXT 272
+#define TIMELIB_PG_REVERSE 273
+#define TIMELIB_CLF 274
+#define TIMELIB_DATE_NO_DAY 275
+#define TIMELIB_SHORTDATE_WITH_TIME 276
+#define TIMELIB_DATE_FULL_POINTED 277
+#define TIMELIB_TIME24_WITH_ZONE 278
+#define TIMELIB_ISO_WEEK 279
+
+#define TIMELIB_TIMEZONE 300
+#define TIMELIB_AGO 301
+
+#define TIMELIB_RELATIVE 310
+
+#define ERROR 999
+
+typedef unsigned char uchar;
+
+#define BSIZE 8192
+
+#define YYCTYPE uchar
+#define YYCURSOR cursor
+#define YYLIMIT s->lim
+#define YYMARKER s->ptr
+#define YYFILL(n) return EOI;
+
+#define RET(i) {s->cur = cursor; return i;}
+
+#define timelib_string_free free
+
+#define TIMELIB_HAVE_TIME() { if (s->time->have_time) { return ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
+#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; }
+#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { return ERROR; } else { s->time->have_date = 1; } }
+#define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
+#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; }
+#define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_weekday_relative = 1; }
+#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { return ERROR; } else { s->time.have_zone = 1; } }
+
+#define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
+#define TIMELIB_DEINIT timelib_string_free(str)
+#define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
+
+#define TIMELIB_PROCESS_YEAR(x) { \
+ if ((x) == -1) { \
+ /* (x) = 0; */ \
+ } else if ((x) < 100) { \
+ if ((x) < 70) { \
+ (x) += 2000; \
+ } else { \
+ (x) += 1900; \
+ } \
+ } \
+}
+
+#ifdef DEBUG_PARSER
+#define DEBUG_OUTPUT(s) printf("%s\n", s);
+#define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
+#else
+#define DEBUG_OUTPUT(s)
+#define YYDEBUG(s,c)
+#endif
+
+#include "timelib_structs.h"
+
+typedef struct timelib_elems {
+ uint c; /* Number of elements */
+ char **v; /* Values */
+} timelib_elems;
+
+typedef struct Scanner {
+ int fd;
+ uchar *lim, *str, *ptr, *cur, *tok, *pos;
+ uint line, len;
+
+ struct timelib_time *time;
+} Scanner;
+
+typedef struct _timelib_lookup_table {
+ const char *name;
+ int type;
+ int value;
+} timelib_lookup_table;
+
+typedef struct _timelib_tz_lookup_table {
+ const char *name;
+ int type;
+ int value;
+ char *full_tz_name;
+} timelib_tz_lookup_table;
+
+typedef struct _timelib_relunit {
+ const char *name;
+ int unit;
+ int multiplier;
+} timelib_relunit;
+
+#define HOUR(a) (a * 60)
+
+/* The timezone table. */
+static timelib_tz_lookup_table const timelib_timezone_lookup[] = {
+ { "gmt", 0, HOUR ( 0), "GMT" }, /* Greenwich Mean */
+ { "ut", 0, HOUR ( 0), "UTC" }, /* Universal (Coordinated) */
+ { "utc", 0, HOUR ( 0), "UTC" },
+ { "wet", 0, HOUR ( 0), "Europe/London" }, /* Western European */
+ { "bst", 1, HOUR ( 0), "Europe/London" }, /* British Summer */
+ { "wat", 0, HOUR ( 1), "Africa/Dakar" }, /* West Africa */
+ { "at", 0, HOUR ( 2), "Atlantic/Azores" }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", 0, HOUR ( 3), NULL }, /* Brazil Standard */
+ { "gst", 0, HOUR ( 3), NULL }, /* Greenland Standard */
+#endif
+ { "nft", 0, HOUR (3.5), "America/St_Johns" }, /* Newfoundland */
+ { "nst", 0, HOUR (3.5), "America/St_Johns" }, /* Newfoundland Standard */
+ { "ndt", 1, HOUR (3.5), "America/St_Johns" }, /* Newfoundland Daylight */
+ { "ast", 0, HOUR ( 4), "America/Halifax" }, /* Atlantic Standard */
+ { "adt", 1, HOUR ( 4), "America/Halifax" }, /* Atlantic Daylight */
+ { "est", 0, HOUR ( 5), "America/New_York" }, /* Eastern Standard */
+ { "edt", 1, HOUR ( 5), "America/New_York" }, /* Eastern Daylight */
+ { "cst", 0, HOUR ( 6), "America/Chicago" }, /* Central Standard */
+ { "cdt", 1, HOUR ( 6), "America/Chicago" }, /* Central Daylight */
+ { "mst", 0, HOUR ( 7), "America/Phoenix" }, /* Mountain Standard */
+ { "mdt", 1, HOUR ( 7), "America/Phoenix" }, /* Mountain Daylight */
+ { "pst", 0, HOUR ( 8), "America/Los_Angeles" }, /* Pacific Standard */
+ { "pdt", 1, HOUR ( 8), "America/Los_Angeles" }, /* Pacific Daylight */
+ { "yst", 0, HOUR ( 9), "America/Anchorage" }, /* Yukon Standard */
+ { "ydt", 1, HOUR ( 9), "America/Anchorage" }, /* Yukon Daylight */
+ { "hst", 0, HOUR (10), "Pacific/Honolulu" }, /* Hawaii Standard */
+ { "hdt", 1, HOUR (10), "Pacific/Honolulu" }, /* Hawaii Daylight */
+ { "cat", 0, HOUR (10), "America/Anchorage" }, /* Central Alaska */
+ { "akst", 0, HOUR (10), "America/Anchorage" }, /* Alaska Standard */
+ { "akdt", 0, HOUR (10), "America/Anchorage" }, /* Alaska Daylight */
+ { "ahst", 0, HOUR (10), "America/Anchorage" }, /* Alaska-Hawaii Standard */
+ { "nt", 0, HOUR (11), NULL }, /* Nome */
+ { "idlw", 0, HOUR (12), NULL }, /* International Date Line West */
+ { "cet", 0, -HOUR (1), "Europe/Berlin" }, /* Central European */
+ { "cest", 1, -HOUR (1), "Europe/Berlin" }, /* Central European Summer */
+ { "slt", 0, -HOUR (1), "Europe/Oslo" }, /* Skien Local Time */
+ { "slst", 1, -HOUR (1), "Europe/Oslo" }, /* Skien Local Summer Time */
+ { "met", 0, -HOUR (1), "MET" }, /* Middle European */
+ { "mewt", 0, -HOUR (1), "MET" }, /* Middle European Winter */
+ { "mest", 1, -HOUR (1), "MET" }, /* Middle European Summer */
+ { "mesz", 1, -HOUR (1), "MET" }, /* Middle European Summer */
+ { "swt", 0, -HOUR (1), "Europe/Stockholm" }, /* Swedish Winter */
+ { "sst", 1, -HOUR (1), "Europe/Stockholm" }, /* Swedish Summer */
+ { "fwt", 0, -HOUR (1), "Europe/Paris" }, /* French Winter */
+ { "fst", 1, -HOUR (1), "Europe/Paris" }, /* French Summer */
+ { "eet", 0, -HOUR (2), "Europe/Bucharest" }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", 0, -HOUR (3), "Asia/Baghdad" }, /* Baghdad, USSR Zone 2 */
+ { "it", 0, -HOUR (3.5), "Asia/Tehran" },/* Iran */
+ { "zp4", 0, -HOUR (4), NULL }, /* USSR Zone 3 */
+ { "zp5", 0, -HOUR (5), NULL }, /* USSR Zone 4 */
+ { "ist", 0, -HOUR (5.5), "Asia/Calcutta" },/* Indian Standard */
+ { "zp6", 0, -HOUR (6), NULL }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Standard, and SST is
+ * also Swedish Summer. */
+ { "nst", 0, -HOUR (6.5), NULL },/* North Sumatra */
+ { "sst", 0, -HOUR (7), NULL }, /* South Sumatra, USSR Zone 6 */
+#endif
+ { "wast", 0, -HOUR (7), "Australia/Perth" }, /* West Australian Standard */
+ { "wadt", 1, -HOUR (7), "Australia/Perth" }, /* West Australian Daylight */
+ { "jt", 0, -HOUR (7.5), NULL },/* Java (3pm in Cronusland!) */
+ { "cct", 0, -HOUR (8), "Asia/Shanghai" }, /* China Coast, USSR Zone 7 */
+ { "jst", 0, -HOUR (9), "Asia/Tokyo" }, /* Japan Standard, USSR Zone 8 */
+ { "cast", 0, -HOUR (9.5), "Australia/Adelaide" },/* Central Australian Standard */
+ { "cadt", 1, -HOUR (9.5), "Australia/Adelaide" },/* Central Australian Daylight */
+ { "east", 0, -HOUR (10), "Australia/Sydney" }, /* Eastern Australian Standard */
+ { "eadt", 1, -HOUR (10), "Australia/Sydney" }, /* Eastern Australian Daylight */
+ { "gst", 0, -HOUR (10), "Pacific/Guam" }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", 0, -HOUR (12), "NZ" }, /* New Zealand */
+ { "nzst", 0, -HOUR (12), "NZ" }, /* New Zealand Standard */
+ { "nzdt", 1, -HOUR (12), "NZ" }, /* New Zealand Daylight */
+ { "idle", 0, -HOUR (12), "NZ" }, /* International Date Line East */
+
+ { "a", 0, HOUR (- 1), NULL },
+ { "b", 0, HOUR (- 2), NULL },
+ { "c", 0, HOUR (- 3), NULL },
+ { "d", 0, HOUR (- 4), NULL },
+ { "e", 0, HOUR (- 5), NULL },
+ { "f", 0, HOUR (- 6), NULL },
+ { "g", 0, HOUR (- 7), NULL },
+ { "h", 0, HOUR (- 8), NULL },
+ { "i", 0, HOUR (- 9), NULL },
+ { "k", 0, HOUR (-10), NULL },
+ { "l", 0, HOUR (-11), NULL },
+ { "m", 0, HOUR (-12), NULL },
+ { "n", 0, HOUR ( 1), NULL },
+ { "o", 0, HOUR ( 2), NULL },
+ { "p", 0, HOUR ( 3), NULL },
+ { "q", 0, HOUR ( 4), NULL },
+ { "r", 0, HOUR ( 5), NULL },
+ { "s", 0, HOUR ( 6), NULL },
+ { "t", 0, HOUR ( 7), NULL },
+ { "u", 0, HOUR ( 8), NULL },
+ { "v", 0, HOUR ( 9), NULL },
+ { "w", 0, HOUR ( 10), NULL },
+ { "x", 0, HOUR ( 11), NULL },
+ { "y", 0, HOUR ( 12), NULL },
+ { "z", 0, HOUR ( 0), NULL },
+ { NULL, 0, 0, NULL }
+};
+
+static timelib_relunit const timelib_relunit_lookup[] = {
+ { "sec", TIMELIB_SECOND, 1 },
+ { "secs", TIMELIB_SECOND, 1 },
+ { "second", TIMELIB_SECOND, 1 },
+ { "seconds", TIMELIB_SECOND, 1 },
+ { "min", TIMELIB_MINUTE, 1 },
+ { "mins", TIMELIB_MINUTE, 1 },
+ { "minute", TIMELIB_MINUTE, 1 },
+ { "minutes", TIMELIB_MINUTE, 1 },
+ { "hour", TIMELIB_HOUR, 1 },
+ { "hours", TIMELIB_HOUR, 1 },
+ { "day", TIMELIB_DAY, 1 },
+ { "days", TIMELIB_DAY, 1 },
+ { "week", TIMELIB_DAY, 7 },
+ { "weeks", TIMELIB_DAY, 7 },
+ { "fortnight", TIMELIB_DAY, 14 },
+ { "fortnights", TIMELIB_DAY, 14 },
+ { "forthnight", TIMELIB_DAY, 14 },
+ { "forthnights", TIMELIB_DAY, 14 },
+ { "month", TIMELIB_MONTH, 1 },
+ { "months", TIMELIB_MONTH, 1 },
+ { "year", TIMELIB_YEAR, 1 },
+ { "years", TIMELIB_YEAR, 1 },
+
+ { "monday", TIMELIB_WEEKDAY, 1 },
+ { "tuesday", TIMELIB_WEEKDAY, 2 },
+ { "wednesday", TIMELIB_WEEKDAY, 3 },
+ { "thursday", TIMELIB_WEEKDAY, 4 },
+ { "friday", TIMELIB_WEEKDAY, 5 },
+ { "saturday", TIMELIB_WEEKDAY, 6 },
+ { "sunday", TIMELIB_WEEKDAY, 0 },
+
+ { NULL, 0, 0 }
+};
+
+/* The relative text table. */
+static timelib_lookup_table const timelib_reltext_lookup[] = {
+ { "first", 0, 1 },
+ { "next", 0, 1 },
+ { "second", 0, 2 },
+ { "third", 0, 3 },
+ { "fourth", 0, 4 },
+ { "fifth", 0, 5 },
+ { "sixth", 0, 6 },
+ { "seventh", 0, 7 },
+ { "eight", 0, 8 },
+ { "ninth", 0, 9 },
+ { "tenth", 0, 10 },
+ { "eleventh", 0, 11 },
+ { "twelfth", 0, 12 },
+ { "last", 0, -1 },
+ { "previous", 0, -1 },
+ { "this", 0, 0 },
+ { NULL, 0, 0 }
+};
+
+/* The month table. */
+static timelib_lookup_table const timelib_month_lookup[] = {
+ { "jan", 0, 1 },
+ { "feb", 0, 2 },
+ { "mar", 0, 3 },
+ { "apr", 0, 4 },
+ { "may", 0, 5 },
+ { "jun", 0, 6 },
+ { "jul", 0, 7 },
+ { "aug", 0, 8 },
+ { "sep", 0, 9 },
+ { "sept", 0, 9 },
+ { "oct", 0, 10 },
+ { "nov", 0, 11 },
+ { "dec", 0, 12 },
+ { "i", 0, 1 },
+ { "ii", 0, 2 },
+ { "iii", 0, 3 },
+ { "iv", 0, 4 },
+ { "v", 0, 5 },
+ { "vi", 0, 6 },
+ { "vii", 0, 7 },
+ { "viii", 0, 8 },
+ { "ix", 0, 9 },
+ { "x", 0, 10 },
+ { "xi", 0, 11 },
+ { "xii", 0, 12 },
+
+ { "january", 0, 1 },
+ { "february", 0, 2 },
+ { "march", 0, 3 },
+ { "april", 0, 4 },
+ { "may", 0, 5 },
+ { "june", 0, 6 },
+ { "july", 0, 7 },
+ { "august", 0, 8 },
+ { "september", 0, 9 },
+ { "october", 0, 10 },
+ { "november", 0, 11 },
+ { "december", 0, 12 },
+ { NULL, 0, 0 }
+};
+
+#if 0
+static char* timelib_ltrim(char *s)
+{
+ char *ptr = s;
+ while (ptr[0] == ' ') {
+ ptr++;
+ }
+ return ptr;
+}
+#endif
+
+#if 0
+uchar *fill(Scanner *s, uchar *cursor){
+ if(!s->eof){
+ uint cnt = s->tok - s->bot;
+ if(cnt){
+ memcpy(s->bot, s->tok, s->lim - s->tok);
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ cursor -= cnt;
+ s->pos -= cnt;
+ s->lim -= cnt;
+ }
+ if((s->top - s->lim) < BSIZE){
+ uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
+ memcpy(buf, s->tok, s->lim - s->tok);
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ cursor = &buf[cursor - s->bot];
+ s->pos = &buf[s->pos - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ free(s->bot);
+ s->bot = buf;
+ }
+ if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
+ s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
+ }
+ s->lim += cnt;
+ }
+ return cursor;
+}
+#endif
+
+static int timelib_meridian(char **ptr, int h)
+{
+ int retval = 0;
+
+ while (!strchr("AaPp", **ptr)) {
+ ++*ptr;
+ }
+ if (**ptr == 'a' || **ptr == 'A') {
+ if (h == 12) {
+ retval = -12;
+ }
+ } else if (h != 12) {
+ retval = 12;
+ }
+ ++*ptr;
+ if (**ptr == '.') {
+ *ptr += 3;
+ } else {
+ ++*ptr;
+ }
+ return retval;
+}
+
+static char *timelib_string(Scanner *s)
+{
+ char *tmp = calloc(1, s->cur - s->tok + 1);
+ memcpy(tmp, s->tok, s->cur - s->tok);
+
+ return tmp;
+}
+
+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+ char *begin, *end, *str;
+ timelib_sll tmp_nr = -1;
+ int len = 0;
+
+ while ((**ptr < '0') || (**ptr > '9')) {
+ if (**ptr == '\0') {
+ return -1;
+ }
+ ++*ptr;
+ }
+ begin = *ptr;
+ while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
+ ++*ptr;
+ ++len;
+ }
+ end = *ptr;
+ str = calloc(1, end - begin + 1);
+ memcpy(str, begin, end - begin);
+ tmp_nr = strtoll(str, NULL, 10);
+ free(str);
+ return tmp_nr;
+}
+
+static float timelib_get_frac_nr(char **ptr, int max_length)
+{
+ char *begin, *end, *str;
+ float tmp_nr = -1;
+ int len = 0;
+
+ while ((**ptr != '.') && ((**ptr < '0') || (**ptr > '9'))) {
+ if (**ptr == '\0') {
+ return -1;
+ }
+ ++*ptr;
+ }
+ begin = *ptr;
+ while (((**ptr == '.') || ((**ptr >= '0') && (**ptr <= '9'))) && len < max_length) {
+ ++*ptr;
+ ++len;
+ }
+ end = *ptr;
+ str = calloc(1, end - begin + 1);