mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47042 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			3128 lines
		
	
	
	
		
			61 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3128 lines
		
	
	
	
		
			61 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
  date_parse.c: Coded by Tadayoshi Funaba 2011,2012
 | 
						|
*/
 | 
						|
 | 
						|
#include "ruby.h"
 | 
						|
#include "ruby/encoding.h"
 | 
						|
#include "ruby/re.h"
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
/* #define TIGHT_PARSER */
 | 
						|
 | 
						|
#define sizeof_array(o) (sizeof o / sizeof o[0])
 | 
						|
 | 
						|
#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
 | 
						|
#define f_add(x,y) rb_funcall(x, '+', 1, y)
 | 
						|
#define f_sub(x,y) rb_funcall(x, '-', 1, y)
 | 
						|
#define f_mul(x,y) rb_funcall(x, '*', 1, y)
 | 
						|
#define f_div(x,y) rb_funcall(x, '/', 1, y)
 | 
						|
#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
 | 
						|
#define f_mod(x,y) rb_funcall(x, '%', 1, y)
 | 
						|
#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
 | 
						|
 | 
						|
#define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
 | 
						|
#define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
 | 
						|
#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
 | 
						|
#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
 | 
						|
 | 
						|
#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
 | 
						|
 | 
						|
#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
 | 
						|
#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
 | 
						|
#define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
 | 
						|
#define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
 | 
						|
#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
 | 
						|
#define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
 | 
						|
#define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
 | 
						|
#define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
 | 
						|
#define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
 | 
						|
 | 
						|
#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
 | 
						|
#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
 | 
						|
#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
 | 
						|
 | 
						|
#define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
 | 
						|
#define str2num(s) rb_str_to_inum(s, 10, 0)
 | 
						|
 | 
						|
static const char *abbr_days[] = {
 | 
						|
    "sun", "mon", "tue", "wed",
 | 
						|
    "thu", "fri", "sat"
 | 
						|
};
 | 
						|
 | 
						|
static const char *abbr_months[] = {
 | 
						|
    "jan", "feb", "mar", "apr", "may", "jun",
 | 
						|
    "jul", "aug", "sep", "oct", "nov", "dec"
 | 
						|
};
 | 
						|
 | 
						|
#define issign(c) ((c) == '-' || (c) == '+')
 | 
						|
#define asp_string() rb_str_new(" ", 1)
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
#define asuba_string() rb_str_new("\001", 1)
 | 
						|
#define asubb_string() rb_str_new("\002", 1)
 | 
						|
#define asubw_string() rb_str_new("\027", 1)
 | 
						|
#define asubt_string() rb_str_new("\024", 1)
 | 
						|
#endif
 | 
						|
 | 
						|
#define DECDIGIT "0123456789"
 | 
						|
 | 
						|
static void
 | 
						|
s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 | 
						|
{
 | 
						|
    VALUE c = Qnil;
 | 
						|
 | 
						|
    if (!RB_TYPE_P(m, T_STRING))
 | 
						|
	m = f_to_s(m);
 | 
						|
 | 
						|
    if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
 | 
						|
	VALUE oy = y;
 | 
						|
	VALUE om = m;
 | 
						|
	VALUE od = d;
 | 
						|
 | 
						|
	y = od;
 | 
						|
	m = oy;
 | 
						|
	d = om;
 | 
						|
    }
 | 
						|
 | 
						|
    if (NIL_P(y)) {
 | 
						|
	if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
 | 
						|
	    y = d;
 | 
						|
	    d = Qnil;
 | 
						|
	}
 | 
						|
	if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
 | 
						|
	    y = d;
 | 
						|
	    d = Qnil;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(y)) {
 | 
						|
	const char *s, *bp, *ep;
 | 
						|
	size_t l;
 | 
						|
 | 
						|
	s = RSTRING_PTR(y);
 | 
						|
	while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
 | 
						|
	    s++;
 | 
						|
	bp = s;
 | 
						|
	if (issign((unsigned char)*s))
 | 
						|
	    s++;
 | 
						|
	l = strspn(s, DECDIGIT);
 | 
						|
	ep = s + l;
 | 
						|
	if (*ep) {
 | 
						|
	    y = d;
 | 
						|
	    d = rb_str_new(bp, ep - bp);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(m)) {
 | 
						|
	const char *s;
 | 
						|
 | 
						|
	s = RSTRING_PTR(m);
 | 
						|
	if (*s == '\'' || RSTRING_LEN(m) > 2) {
 | 
						|
	    /* us -> be */
 | 
						|
	    VALUE oy = y;
 | 
						|
	    VALUE om = m;
 | 
						|
	    VALUE od = d;
 | 
						|
 | 
						|
	    y = om;
 | 
						|
	    m = od;
 | 
						|
	    d = oy;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(d)) {
 | 
						|
	const char *s;
 | 
						|
 | 
						|
	s = RSTRING_PTR(d);
 | 
						|
	if (*s == '\'' || RSTRING_LEN(d) > 2) {
 | 
						|
	    VALUE oy = y;
 | 
						|
	    VALUE od = d;
 | 
						|
 | 
						|
	    y = od;
 | 
						|
	    d = oy;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(y)) {
 | 
						|
	const char *s, *bp, *ep;
 | 
						|
	int sign = 0;
 | 
						|
	size_t l;
 | 
						|
	VALUE iy;
 | 
						|
 | 
						|
	s = RSTRING_PTR(y);
 | 
						|
	while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
 | 
						|
	    s++;
 | 
						|
	bp = s;
 | 
						|
	if (issign(*s)) {
 | 
						|
	    s++;
 | 
						|
	    sign = 1;
 | 
						|
	}
 | 
						|
	if (sign)
 | 
						|
	    c = Qfalse;
 | 
						|
	l = strspn(s, DECDIGIT);
 | 
						|
	ep = s + l;
 | 
						|
	if (l > 2)
 | 
						|
	    c = Qfalse;
 | 
						|
	{
 | 
						|
	    char *buf;
 | 
						|
 | 
						|
	    buf = ALLOCA_N(char, ep - bp + 1);
 | 
						|
	    memcpy(buf, bp, ep - bp);
 | 
						|
	    buf[ep - bp] = '\0';
 | 
						|
	    iy = cstr2num(buf);
 | 
						|
	}
 | 
						|
	set_hash("year", iy);
 | 
						|
    }
 | 
						|
 | 
						|
    if (bc)
 | 
						|
	set_hash("_bc", Qtrue);
 | 
						|
 | 
						|
    if (!NIL_P(m)) {
 | 
						|
	const char *s, *bp, *ep;
 | 
						|
	size_t l;
 | 
						|
	VALUE im;
 | 
						|
 | 
						|
	s = RSTRING_PTR(m);
 | 
						|
	while (!isdigit((unsigned char)*s))
 | 
						|
	    s++;
 | 
						|
	bp = s;
 | 
						|
	l = strspn(s, DECDIGIT);
 | 
						|
	ep = s + l;
 | 
						|
	{
 | 
						|
	    char *buf;
 | 
						|
 | 
						|
	    buf = ALLOCA_N(char, ep - bp + 1);
 | 
						|
	    memcpy(buf, bp, ep - bp);
 | 
						|
	    buf[ep - bp] = '\0';
 | 
						|
	    im = cstr2num(buf);
 | 
						|
	}
 | 
						|
	set_hash("mon", im);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(d)) {
 | 
						|
	const char *s, *bp, *ep;
 | 
						|
	size_t l;
 | 
						|
	VALUE id;
 | 
						|
 | 
						|
	s = RSTRING_PTR(d);
 | 
						|
	while (!isdigit((unsigned char)*s))
 | 
						|
	    s++;
 | 
						|
	bp = s;
 | 
						|
	l = strspn(s, DECDIGIT);
 | 
						|
	ep = s + l;
 | 
						|
	{
 | 
						|
	    char *buf;
 | 
						|
 | 
						|
	    buf = ALLOCA_N(char, ep - bp + 1);
 | 
						|
	    memcpy(buf, bp, ep - bp);
 | 
						|
	    buf[ep - bp] = '\0';
 | 
						|
	    id = cstr2num(buf);
 | 
						|
	}
 | 
						|
	set_hash("mday", id);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(c))
 | 
						|
	set_hash("_comp", c);
 | 
						|
}
 | 
						|
 | 
						|
#define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
 | 
						|
#define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
 | 
						|
#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
 | 
						|
#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
#define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
 | 
						|
#define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
 | 
						|
#define DOTLESS_VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")"
 | 
						|
#define BOS "\\A\\s*"
 | 
						|
#define FPA "\\001"
 | 
						|
#define FPB "\\002"
 | 
						|
#define FPW "\\027"
 | 
						|
#define FPT "\\024"
 | 
						|
#define FPW_COM "\\s*(?:" FPW "\\s*,?)?\\s*"
 | 
						|
#define FPT_COM "\\s*(?:" FPT "\\s*,?)?\\s*"
 | 
						|
#define COM_FPW "\\s*(?:,?\\s*" FPW ")?\\s*"
 | 
						|
#define COM_FPT "\\s*(?:,?\\s*(?:@|\\b[aA][tT]\\b)?\\s*" FPT ")?\\s*"
 | 
						|
#define TEE_FPT "\\s*(?:[tT]?" FPT ")?"
 | 
						|
#define EOS "\\s*\\z"
 | 
						|
#endif
 | 
						|
 | 
						|
static VALUE
 | 
						|
regcomp(const char *source, long len, int opt)
 | 
						|
{
 | 
						|
    VALUE pat;
 | 
						|
 | 
						|
    pat = rb_reg_new(source, len, opt);
 | 
						|
    rb_gc_register_mark_object(pat);
 | 
						|
    return pat;
 | 
						|
}
 | 
						|
 | 
						|
#define REGCOMP(pat,opt) \
 | 
						|
{ \
 | 
						|
    if (NIL_P(pat)) \
 | 
						|
	pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
 | 
						|
}
 | 
						|
 | 
						|
#define REGCOMP_0(pat) REGCOMP(pat, 0)
 | 
						|
#define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
 | 
						|
 | 
						|
#define MATCH(s,p,c) \
 | 
						|
{ \
 | 
						|
    return match(s, p, hash, c); \
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
 | 
						|
{
 | 
						|
    VALUE m;
 | 
						|
 | 
						|
    m = f_match(pat, str);
 | 
						|
 | 
						|
    if (NIL_P(m))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    (*cb)(m, hash);
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
 | 
						|
{
 | 
						|
    VALUE m;
 | 
						|
 | 
						|
    m = f_match(pat, str);
 | 
						|
 | 
						|
    if (NIL_P(m))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    {
 | 
						|
	VALUE be, en;
 | 
						|
 | 
						|
	be = f_begin(m, INT2FIX(0));
 | 
						|
	en = f_end(m, INT2FIX(0));
 | 
						|
	f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), rep);
 | 
						|
	(*cb)(m, hash);
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
#define SUBS(s,p,c) \
 | 
						|
{ \
 | 
						|
    return subx(s, asp_string(), p, hash, c); \
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
#define SUBA(s,p,c) \
 | 
						|
{ \
 | 
						|
    return subx(s, asuba_string(), p, hash, c); \
 | 
						|
}
 | 
						|
 | 
						|
#define SUBB(s,p,c) \
 | 
						|
{ \
 | 
						|
    return subx(s, asubb_string(), p, hash, c); \
 | 
						|
}
 | 
						|
 | 
						|
#define SUBW(s,p,c) \
 | 
						|
{ \
 | 
						|
    return subx(s, asubw_string(), p, hash, c); \
 | 
						|
}
 | 
						|
 | 
						|
#define SUBT(s,p,c) \
 | 
						|
{ \
 | 
						|
    return subx(s, asubt_string(), p, hash, c); \
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
struct zone {
 | 
						|
    const char *name;
 | 
						|
    int offset;
 | 
						|
};
 | 
						|
 | 
						|
static struct zone zones_source[] = {
 | 
						|
    {"ut",   0*3600}, {"gmt",  0*3600}, {"est", -5*3600}, {"edt", -4*3600},
 | 
						|
    {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600},
 | 
						|
    {"pst", -8*3600}, {"pdt", -7*3600},
 | 
						|
    {"a",    1*3600}, {"b",    2*3600}, {"c",    3*3600}, {"d",    4*3600},
 | 
						|
    {"e",    5*3600}, {"f",    6*3600}, {"g",    7*3600}, {"h",    8*3600},
 | 
						|
    {"i",    9*3600}, {"k",   10*3600}, {"l",   11*3600}, {"m",   12*3600},
 | 
						|
    {"n",   -1*3600}, {"o",   -2*3600}, {"p",   -3*3600}, {"q",   -4*3600},
 | 
						|
    {"r",   -5*3600}, {"s",   -6*3600}, {"t",   -7*3600}, {"u",   -8*3600},
 | 
						|
    {"v",   -9*3600}, {"w",  -10*3600}, {"x",  -11*3600}, {"y",  -12*3600},
 | 
						|
    {"z",    0*3600},
 | 
						|
 | 
						|
    {"utc",  0*3600}, {"wet",  0*3600},
 | 
						|
    {"at",  -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)},
 | 
						|
    {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600},
 | 
						|
    {"nst", -(3*3600+1800)},
 | 
						|
    {"ast", -4*3600}, {"clt", -4*3600},
 | 
						|
    {"akdt",-8*3600}, {"ydt", -8*3600},
 | 
						|
    {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600},
 | 
						|
    {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600},
 | 
						|
    {"nt",  -11*3600},
 | 
						|
    {"idlw",-12*3600},
 | 
						|
    {"bst",  1*3600}, {"cet",  1*3600}, {"fwt",  1*3600}, {"met",  1*3600},
 | 
						|
    {"mewt", 1*3600}, {"mez",  1*3600}, {"swt",  1*3600}, {"wat",  1*3600},
 | 
						|
    {"west", 1*3600},
 | 
						|
    {"cest", 2*3600}, {"eet",  2*3600}, {"fst",  2*3600}, {"mest", 2*3600},
 | 
						|
    {"mesz", 2*3600}, {"sast", 2*3600}, {"sst",  2*3600},
 | 
						|
    {"bt",   3*3600}, {"eat",  3*3600}, {"eest", 3*3600}, {"msk",  3*3600},
 | 
						|
    {"msd",  4*3600}, {"zp4",  4*3600},
 | 
						|
    {"zp5",  5*3600}, {"ist",  (5*3600+1800)},
 | 
						|
    {"zp6",  6*3600},
 | 
						|
    {"wast", 7*3600},
 | 
						|
    {"cct",  8*3600}, {"sgt",  8*3600}, {"wadt", 8*3600},
 | 
						|
    {"jst",  9*3600}, {"kst",  9*3600},
 | 
						|
    {"east",10*3600}, {"gst", 10*3600},
 | 
						|
    {"eadt",11*3600},
 | 
						|
    {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600},
 | 
						|
    {"nzdt",13*3600},
 | 
						|
 | 
						|
    {"afghanistan",             16200}, {"alaskan",                -32400},
 | 
						|
    {"arab",                    10800}, {"arabian",                 14400},
 | 
						|
    {"arabic",                  10800}, {"atlantic",               -14400},
 | 
						|
    {"aus central",             34200}, {"aus eastern",             36000},
 | 
						|
    {"azores",                  -3600}, {"canada central",         -21600},
 | 
						|
    {"cape verde",              -3600}, {"caucasus",                14400},
 | 
						|
    {"cen. australia",          34200}, {"central america",        -21600},
 | 
						|
    {"central asia",            21600}, {"central europe",           3600},
 | 
						|
    {"central european",         3600}, {"central pacific",         39600},
 | 
						|
    {"central",                -21600}, {"china",                   28800},
 | 
						|
    {"dateline",               -43200}, {"e. africa",               10800},
 | 
						|
    {"e. australia",            36000}, {"e. europe",                7200},
 | 
						|
    {"e. south america",       -10800}, {"eastern",                -18000},
 | 
						|
    {"egypt",                    7200}, {"ekaterinburg",            18000},
 | 
						|
    {"fiji",                    43200}, {"fle",                      7200},
 | 
						|
    {"greenland",              -10800}, {"greenwich",                   0},
 | 
						|
    {"gtb",                      7200}, {"hawaiian",               -36000},
 | 
						|
    {"india",                   19800}, {"iran",                    12600},
 | 
						|
    {"jerusalem",                7200}, {"korea",                   32400},
 | 
						|
    {"mexico",                 -21600}, {"mid-atlantic",            -7200},
 | 
						|
    {"mountain",               -25200}, {"myanmar",                 23400},
 | 
						|
    {"n. central asia",         21600}, {"nepal",                   20700},
 | 
						|
    {"new zealand",             43200}, {"newfoundland",           -12600},
 | 
						|
    {"north asia east",         28800}, {"north asia",              25200},
 | 
						|
    {"pacific sa",             -14400}, {"pacific",                -28800},
 | 
						|
    {"romance",                  3600}, {"russian",                 10800},
 | 
						|
    {"sa eastern",             -10800}, {"sa pacific",             -18000},
 | 
						|
    {"sa western",             -14400}, {"samoa",                  -39600},
 | 
						|
    {"se asia",                 25200}, {"malay peninsula",         28800},
 | 
						|
    {"south africa",             7200}, {"sri lanka",               21600},
 | 
						|
    {"taipei",                  28800}, {"tasmania",                36000},
 | 
						|
    {"tokyo",                   32400}, {"tonga",                   46800},
 | 
						|
    {"us eastern",             -18000}, {"us mountain",            -25200},
 | 
						|
    {"vladivostok",             36000}, {"w. australia",            28800},
 | 
						|
    {"w. central africa",        3600}, {"w. europe",                3600},
 | 
						|
    {"west asia",               18000}, {"west pacific",            36000},
 | 
						|
    {"yakutsk",                 32400}
 | 
						|
};
 | 
						|
 | 
						|
VALUE
 | 
						|
date_zone_to_diff(VALUE str)
 | 
						|
{
 | 
						|
    VALUE offset = Qnil;
 | 
						|
 | 
						|
    long l, i;
 | 
						|
    char *s, *dest, *d;
 | 
						|
    int sp = 1;
 | 
						|
 | 
						|
    l = RSTRING_LEN(str);
 | 
						|
    s = RSTRING_PTR(str);
 | 
						|
 | 
						|
    dest = d = ALLOCA_N(char, l + 1);
 | 
						|
 | 
						|
    for (i = 0; i < l; i++) {
 | 
						|
	if (isspace((unsigned char)s[i]) || s[i] == '\0') {
 | 
						|
	    if (!sp)
 | 
						|
		*d++ = ' ';
 | 
						|
	    sp = 1;
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (isalpha((unsigned char)s[i]))
 | 
						|
		*d++ = tolower((unsigned char)s[i]);
 | 
						|
	    else
 | 
						|
		*d++ = s[i];
 | 
						|
	    sp = 0;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (d > dest) {
 | 
						|
	if (*(d - 1) == ' ')
 | 
						|
	    --d;
 | 
						|
	*d = '\0';
 | 
						|
    }
 | 
						|
    str = rb_str_new2(dest);
 | 
						|
    {
 | 
						|
#define STD " standard time"
 | 
						|
#define DST " daylight time"
 | 
						|
	char *ss, *ds;
 | 
						|
	long sl, dl;
 | 
						|
	int dst = 0;
 | 
						|
 | 
						|
	sl = RSTRING_LEN(str) - (sizeof STD - 1);
 | 
						|
	ss = RSTRING_PTR(str) + sl;
 | 
						|
	dl = RSTRING_LEN(str) - (sizeof DST - 1);
 | 
						|
	ds = RSTRING_PTR(str) + dl;
 | 
						|
 | 
						|
	if (sl >= 0 && strcmp(ss, STD) == 0) {
 | 
						|
	    str = rb_str_new(RSTRING_PTR(str), sl);
 | 
						|
	}
 | 
						|
	else if (dl >= 0 && strcmp(ds, DST) == 0) {
 | 
						|
	    str = rb_str_new(RSTRING_PTR(str), dl);
 | 
						|
	    dst = 1;
 | 
						|
	}
 | 
						|
#undef STD
 | 
						|
#undef DST
 | 
						|
	else {
 | 
						|
#define DST " dst"
 | 
						|
	    char *ds;
 | 
						|
	    long dl;
 | 
						|
 | 
						|
	    dl = RSTRING_LEN(str) - (sizeof DST - 1);
 | 
						|
	    ds = RSTRING_PTR(str) + dl;
 | 
						|
 | 
						|
	    if (dl >= 0 && strcmp(ds, DST) == 0) {
 | 
						|
		str = rb_str_new(RSTRING_PTR(str), dl);
 | 
						|
		dst = 1;
 | 
						|
	    }
 | 
						|
#undef DST
 | 
						|
	}
 | 
						|
	{
 | 
						|
	    static VALUE zones = Qnil;
 | 
						|
 | 
						|
	    if (NIL_P(zones)) {
 | 
						|
		int i;
 | 
						|
 | 
						|
		zones = rb_hash_new();
 | 
						|
		rb_gc_register_mark_object(zones);
 | 
						|
		for (i = 0; i < (int)sizeof_array(zones_source); i++) {
 | 
						|
		    VALUE name = rb_str_new2(zones_source[i].name);
 | 
						|
		    VALUE offset = INT2FIX(zones_source[i].offset);
 | 
						|
		    rb_hash_aset(zones, name, offset);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	    offset = f_aref(zones, str);
 | 
						|
	    if (!NIL_P(offset)) {
 | 
						|
		if (dst)
 | 
						|
		    offset = f_add(offset, INT2FIX(3600));
 | 
						|
		goto ok;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	{
 | 
						|
	    char *s, *p;
 | 
						|
	    VALUE sign;
 | 
						|
	    VALUE hour = Qnil, min = Qnil, sec = Qnil;
 | 
						|
	    VALUE str_orig;
 | 
						|
 | 
						|
	    s = RSTRING_PTR(str);
 | 
						|
	    str_orig = str;
 | 
						|
 | 
						|
	    if (strncmp(s, "gmt", 3) == 0 ||
 | 
						|
		strncmp(s, "utc", 3) == 0)
 | 
						|
		s += 3;
 | 
						|
	    if (issign(*s)) {
 | 
						|
		sign = rb_str_new(s, 1);
 | 
						|
		s++;
 | 
						|
 | 
						|
		str = rb_str_new2(s);
 | 
						|
 | 
						|
		if (p = strchr(s, ':')) {
 | 
						|
		    hour = rb_str_new(s, p - s);
 | 
						|
		    s = ++p;
 | 
						|
		    if (p = strchr(s, ':')) {
 | 
						|
			min = rb_str_new(s, p - s);
 | 
						|
			s = ++p;
 | 
						|
			if (p = strchr(s, ':')) {
 | 
						|
			    sec = rb_str_new(s, p - s);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			    sec = rb_str_new2(s);
 | 
						|
		    }
 | 
						|
		    else
 | 
						|
			min = rb_str_new2(s);
 | 
						|
		    RB_GC_GUARD(str_orig);
 | 
						|
		    goto num;
 | 
						|
		}
 | 
						|
		if (strpbrk(RSTRING_PTR(str), ",.")) {
 | 
						|
		    char *a, *b;
 | 
						|
 | 
						|
		    a = ALLOCA_N(char, RSTRING_LEN(str) + 1);
 | 
						|
		    strcpy(a, RSTRING_PTR(str));
 | 
						|
		    b = strpbrk(a, ",.");
 | 
						|
		    *b = '\0';
 | 
						|
		    b++;
 | 
						|
 | 
						|
		    hour = cstr2num(a);
 | 
						|
		    min = f_mul(rb_rational_new2
 | 
						|
				(cstr2num(b),
 | 
						|
				 f_expt(INT2FIX(10),
 | 
						|
					LONG2NUM((long)strlen(b)))),
 | 
						|
				INT2FIX(60));
 | 
						|
		    goto num;
 | 
						|
		}
 | 
						|
		{
 | 
						|
		    const char *cs = RSTRING_PTR(str);
 | 
						|
		    long cl = RSTRING_LEN(str);
 | 
						|
 | 
						|
		    if (cl % 2) {
 | 
						|
			if (cl >= 1)
 | 
						|
			    hour = rb_str_new(&cs[0], 1);
 | 
						|
			if (cl >= 3)
 | 
						|
			    min  = rb_str_new(&cs[1], 2);
 | 
						|
			if (cl >= 5)
 | 
						|
			    sec  = rb_str_new(&cs[3], 2);
 | 
						|
		    }
 | 
						|
		    else {
 | 
						|
			if (cl >= 2)
 | 
						|
			    hour = rb_str_new(&cs[0], 2);
 | 
						|
			if (cl >= 4)
 | 
						|
			    min  = rb_str_new(&cs[2], 2);
 | 
						|
			if (cl >= 6)
 | 
						|
			    sec  = rb_str_new(&cs[4], 2);
 | 
						|
		    }
 | 
						|
		    goto num;
 | 
						|
		}
 | 
						|
	      num:
 | 
						|
		if (NIL_P(hour))
 | 
						|
		    offset = INT2FIX(0);
 | 
						|
		else {
 | 
						|
		    if (RB_TYPE_P(hour, T_STRING))
 | 
						|
			hour = str2num(hour);
 | 
						|
		    offset = f_mul(hour, INT2FIX(3600));
 | 
						|
		}
 | 
						|
		if (!NIL_P(min)) {
 | 
						|
		    if (RB_TYPE_P(min, T_STRING))
 | 
						|
			min = str2num(min);
 | 
						|
		    offset = f_add(offset, f_mul(min, INT2FIX(60)));
 | 
						|
		}
 | 
						|
		if (!NIL_P(sec))
 | 
						|
		    offset = f_add(offset, str2num(sec));
 | 
						|
		if (!NIL_P(sign) &&
 | 
						|
		    RSTRING_LEN(sign) == 1 &&
 | 
						|
		    *RSTRING_PTR(sign) == '-')
 | 
						|
		    offset = f_negate(offset);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    RB_GC_GUARD(str);
 | 
						|
  ok:
 | 
						|
    return offset;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
day_num(VALUE s)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < (int)sizeof_array(abbr_days); i++)
 | 
						|
	if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
 | 
						|
	    break;
 | 
						|
    return i;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
mon_num(VALUE s)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < (int)sizeof_array(abbr_months); i++)
 | 
						|
	if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
 | 
						|
	    break;
 | 
						|
    return i + 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_day_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s;
 | 
						|
 | 
						|
    s = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("wday", INT2FIX(day_num(s)));
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_day(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b(" ABBR_DAYS ")[^-/\\d\\s]*"
 | 
						|
#else
 | 
						|
	"(" VALID_DAYS ")"
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
    SUBS(str, pat, parse_day_cb);
 | 
						|
#else
 | 
						|
    SUBW(str, pat, parse_day_cb);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_time2_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE h, min, s, f, p;
 | 
						|
 | 
						|
    h = rb_reg_nth_match(1, m);
 | 
						|
    h = str2num(h);
 | 
						|
 | 
						|
    min = rb_reg_nth_match(2, m);
 | 
						|
    if (!NIL_P(min))
 | 
						|
	min = str2num(min);
 | 
						|
 | 
						|
    s = rb_reg_nth_match(3, m);
 | 
						|
    if (!NIL_P(s))
 | 
						|
	s = str2num(s);
 | 
						|
 | 
						|
    f = rb_reg_nth_match(4, m);
 | 
						|
 | 
						|
    if (!NIL_P(f))
 | 
						|
	f = rb_rational_new2(str2num(f),
 | 
						|
			     f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
 | 
						|
 | 
						|
    p = rb_reg_nth_match(5, m);
 | 
						|
 | 
						|
    if (!NIL_P(p)) {
 | 
						|
	int ih = NUM2INT(h);
 | 
						|
	ih %= 12;
 | 
						|
	if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
 | 
						|
	    ih += 12;
 | 
						|
	h = INT2FIX(ih);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("hour", h);
 | 
						|
    if (!NIL_P(min))
 | 
						|
	set_hash("min", min);
 | 
						|
    if (!NIL_P(s))
 | 
						|
	set_hash("sec", s);
 | 
						|
    if (!NIL_P(f))
 | 
						|
	set_hash("sec_fraction", f);
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_time_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	    "\\A(\\d+)h?"
 | 
						|
	      "(?:\\s*:?\\s*(\\d+)m?"
 | 
						|
		"(?:"
 | 
						|
		  "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
 | 
						|
		")?"
 | 
						|
	      ")?"
 | 
						|
	    "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
    VALUE s1, s2;
 | 
						|
 | 
						|
    s1 = rb_reg_nth_match(1, m);
 | 
						|
    s2 = rb_reg_nth_match(2, m);
 | 
						|
 | 
						|
    if (!NIL_P(s2))
 | 
						|
	set_hash("zone", s2);
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
 | 
						|
    {
 | 
						|
	VALUE m = f_match(pat, s1);
 | 
						|
 | 
						|
	if (NIL_P(m))
 | 
						|
	    return 0;
 | 
						|
	parse_time2_cb(m, hash);
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_time(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
		"("
 | 
						|
		   "(?:"
 | 
						|
		     "\\d+\\s*:\\s*\\d+"
 | 
						|
		     "(?:"
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		       "\\s*:\\s*\\d+(?:[,.]\\d*)?"
 | 
						|
#else
 | 
						|
		       "\\s*:\\s*\\d+(?:[,.]\\d+)?"
 | 
						|
#endif
 | 
						|
		     ")?"
 | 
						|
		   "|"
 | 
						|
		     "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
 | 
						|
		   ")"
 | 
						|
		   "(?:"
 | 
						|
		     "\\s*"
 | 
						|
		     "[ap](?:m\\b|\\.m\\.)"
 | 
						|
		   ")?"
 | 
						|
		 "|"
 | 
						|
		   "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
 | 
						|
		 ")"
 | 
						|
		 "(?:"
 | 
						|
		   "\\s*"
 | 
						|
		   "("
 | 
						|
		     "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
 | 
						|
		   "|"
 | 
						|
		     "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
 | 
						|
		   "|"
 | 
						|
		     "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
 | 
						|
		   ")"
 | 
						|
		")?";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
    SUBS(str, pat, parse_time_cb);
 | 
						|
#else
 | 
						|
    SUBT(str, pat, parse_time_cb);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
static int
 | 
						|
parse_era1_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_era1(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"(a(?:d|\\.d\\.))";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBA(str, pat, parse_era1_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_era2_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE b;
 | 
						|
 | 
						|
    b = rb_reg_nth_match(1, m);
 | 
						|
    if (*RSTRING_PTR(b) == 'B' ||
 | 
						|
	*RSTRING_PTR(b) == 'b')
 | 
						|
	set_hash("_bc", Qtrue);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_era2(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBB(str, pat, parse_era2_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_era(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    if (parse_era1(str, hash)) /* pre */
 | 
						|
	goto ok;
 | 
						|
    if (parse_era2(str, hash)) /* post */
 | 
						|
	goto ok;
 | 
						|
    return 0;
 | 
						|
  ok:
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
static int
 | 
						|
check_year_width(VALUE y)
 | 
						|
{
 | 
						|
    char *s;
 | 
						|
    size_t l;
 | 
						|
 | 
						|
    s = RSTRING_PTR(y);
 | 
						|
    l = strcspn(s, DECDIGIT);
 | 
						|
    s += l;
 | 
						|
    l = strspn(s, DECDIGIT);
 | 
						|
    if (l != 2)
 | 
						|
	return 0;
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
check_apost(VALUE a, VALUE b, VALUE c)
 | 
						|
{
 | 
						|
    int f = 0;
 | 
						|
 | 
						|
    if (!NIL_P(a) && *RSTRING_PTR(a) == '\'') {
 | 
						|
	if (!check_year_width(a))
 | 
						|
	    return 0;
 | 
						|
	f++;
 | 
						|
    }
 | 
						|
    if (!NIL_P(b) && *RSTRING_PTR(b) == '\'') {
 | 
						|
	if (!check_year_width(b))
 | 
						|
	    return 0;
 | 
						|
	if (!NIL_P(c))
 | 
						|
	    return 0;
 | 
						|
	f++;
 | 
						|
    }
 | 
						|
    if (!NIL_P(c) && *RSTRING_PTR(c) == '\'') {
 | 
						|
	if (!check_year_width(c))
 | 
						|
	    return 0;
 | 
						|
	f++;
 | 
						|
    }
 | 
						|
    if (f > 1)
 | 
						|
	return 0;
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
parse_eu_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
    VALUE y, mon, d, b;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    b = rb_reg_nth_match(3, m);
 | 
						|
    y = rb_reg_nth_match(4, m);
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, !NIL_P(b) &&
 | 
						|
	(*RSTRING_PTR(b) == 'B' ||
 | 
						|
	 *RSTRING_PTR(b) == 'b'));
 | 
						|
#else
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(d, mon, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
#endif
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_eu(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		BOS
 | 
						|
		FPW_COM FPT_COM
 | 
						|
#endif
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		"('?\\d+)[^-\\d\\s]*"
 | 
						|
#else
 | 
						|
		"(\\d+)(?:(?:st|nd|rd|th)\\b)?"
 | 
						|
#endif
 | 
						|
		 "\\s*"
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		 "(" ABBR_MONTHS ")[^-\\d\\s']*"
 | 
						|
#else
 | 
						|
		 "(" VALID_MONTHS ")"
 | 
						|
#endif
 | 
						|
		 "(?:"
 | 
						|
		   "\\s*"
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		   "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
 | 
						|
		   "\\s*"
 | 
						|
		   "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
 | 
						|
#else
 | 
						|
		   "(?:" FPA ")?"
 | 
						|
		   "\\s*"
 | 
						|
		   "([-']?\\d+)"
 | 
						|
		   "\\s*"
 | 
						|
		   "(?:" FPA "|" FPB ")?"
 | 
						|
#endif
 | 
						|
		")?"
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		COM_FPT COM_FPW
 | 
						|
		EOS
 | 
						|
#endif
 | 
						|
		;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_eu_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_us_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
    VALUE y, mon, d, b;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
 | 
						|
    b = rb_reg_nth_match(3, m);
 | 
						|
    y = rb_reg_nth_match(4, m);
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, !NIL_P(b) &&
 | 
						|
	(*RSTRING_PTR(b) == 'B' ||
 | 
						|
	 *RSTRING_PTR(b) == 'b'));
 | 
						|
#else
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(mon, d, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
#endif
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_us(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		BOS
 | 
						|
		FPW_COM FPT_COM
 | 
						|
#endif
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		"\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
 | 
						|
#else
 | 
						|
		"\\b(" VALID_MONTHS ")"
 | 
						|
#endif
 | 
						|
		 "\\s*"
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		 "('?\\d+)[^-\\d\\s']*"
 | 
						|
#else
 | 
						|
		 "('?\\d+)(?:(?:st|nd|rd|th)\\b)?"
 | 
						|
		COM_FPT
 | 
						|
#endif
 | 
						|
		 "(?:"
 | 
						|
		   "\\s*,?"
 | 
						|
		   "\\s*"
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
		   "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
 | 
						|
		   "\\s*"
 | 
						|
		   "('?-?\\d+)"
 | 
						|
#else
 | 
						|
		   "(?:" FPA ")?"
 | 
						|
		   "\\s*"
 | 
						|
		   "([-']?\\d+)"
 | 
						|
		   "\\s*"
 | 
						|
		   "(?:" FPA "|" FPB ")?"
 | 
						|
#endif
 | 
						|
		")?"
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		COM_FPT COM_FPW
 | 
						|
		EOS
 | 
						|
#endif
 | 
						|
		;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_us_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    d = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (!check_apost(y, mon, d))
 | 
						|
	return 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-+']?\\d+)-(\\d+)-([-']?\\d+)"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_iso_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso21_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, w, d;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    w = rb_reg_nth_match(2, m);
 | 
						|
    d = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!NIL_P(y))
 | 
						|
	set_hash("cwyear", str2num(y));
 | 
						|
    set_hash("cweek", str2num(w));
 | 
						|
    if (!NIL_P(d))
 | 
						|
	set_hash("cwday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso21(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_iso21_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso22_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("cwday", str2num(d));
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso22(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"-w-(\\d)\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"-w-(\\d)"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_iso22_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso23_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
 | 
						|
    if (!NIL_P(mon))
 | 
						|
	set_hash("mon", str2num(mon));
 | 
						|
    set_hash("mday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso23(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"--(\\d{2})?-(\\d{2})\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"--(\\d{2})?-(\\d{2})"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_iso23_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso24_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
 | 
						|
    set_hash("mon", str2num(mon));
 | 
						|
    if (!NIL_P(d))
 | 
						|
	set_hash("mday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso24(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"--(\\d{2})(\\d{2})?\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"--(\\d{2})(\\d{2})?"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_iso24_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso25_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, d;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
 | 
						|
    set_hash("year", str2num(y));
 | 
						|
    set_hash("yday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso25(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat0_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"[,.](\\d{2}|\\d{4})-\\d{3}\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"[,.](\\d{2}|\\d{4})-\\d{3}"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat0 = Qnil;
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b(\\d{2}|\\d{4})-(\\d{3})\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(\\d{2}|\\d{4})-(\\d{3})"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat0);
 | 
						|
    REGCOMP_0(pat);
 | 
						|
 | 
						|
    if (!NIL_P(f_match(pat0, str)))
 | 
						|
	return 0;
 | 
						|
    SUBS(str, pat, parse_iso25_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso26_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("yday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
static int
 | 
						|
parse_iso26(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat0_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\d-\\d{3}\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"\\d-\\d{3}"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat0 = Qnil;
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b-(\\d{3})\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"-(\\d{3})"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat0);
 | 
						|
    REGCOMP_0(pat);
 | 
						|
 | 
						|
    if (!NIL_P(f_match(pat0, str)))
 | 
						|
	return 0;
 | 
						|
    SUBS(str, pat, parse_iso26_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_iso2(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    if (parse_iso21(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_iso22(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_iso23(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_iso24(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_iso25(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_iso26(str, hash))
 | 
						|
	goto ok;
 | 
						|
    return 0;
 | 
						|
 | 
						|
  ok:
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
gengo(int c)
 | 
						|
{
 | 
						|
    int e;
 | 
						|
 | 
						|
    switch (c) {
 | 
						|
      case 'M': case 'm': e = 1867; break;
 | 
						|
      case 'T': case 't': e = 1911; break;
 | 
						|
      case 'S': case 's': e = 1925; break;
 | 
						|
      case 'H': case 'h': e = 1988; break;
 | 
						|
      default:  e = 0; break;
 | 
						|
    }
 | 
						|
    return e;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_jis_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE e, y, mon, d;
 | 
						|
    int ep;
 | 
						|
 | 
						|
    e = rb_reg_nth_match(1, m);
 | 
						|
    y = rb_reg_nth_match(2, m);
 | 
						|
    mon = rb_reg_nth_match(3, m);
 | 
						|
    d = rb_reg_nth_match(4, m);
 | 
						|
 | 
						|
    ep = gengo(*RSTRING_PTR(e));
 | 
						|
 | 
						|
    set_hash("year", f_add(str2num(y), INT2FIX(ep)));
 | 
						|
    set_hash("mon", str2num(mon));
 | 
						|
    set_hash("mday", str2num(d));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_jis(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
 | 
						|
	TEE_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_jis_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_vms11_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (!check_apost(d, mon, y))
 | 
						|
	return 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_vms11(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
 | 
						|
	"-('?-?\\d+)"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-']?\\d+)-(" DOTLESS_VALID_MONTHS ")"
 | 
						|
	"-([-']?\\d+)"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_vms11_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_vms12_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (!check_apost(mon, d, y))
 | 
						|
	return 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_vms12(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b(" ABBR_MONTHS ")[^-/.]*"
 | 
						|
	"-('?-?\\d+)(?:-('?-?\\d+))?"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(" DOTLESS_VALID_MONTHS ")"
 | 
						|
	"-([-']?\\d+)(?:-([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_vms12_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_vms(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    if (parse_vms11(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_vms12(str, hash))
 | 
						|
	goto ok;
 | 
						|
    return 0;
 | 
						|
 | 
						|
  ok:
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_sla_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    d = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (!check_apost(y, mon, d))
 | 
						|
	return 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_sla(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-']?\\d+)/\\s*('?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_sla_cb);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
static int
 | 
						|
parse_sla2_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(d, mon, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_sla2(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-']?\\d+)/\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_sla2_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_sla3_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(mon, d, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_sla3(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(" DOTLESS_VALID_MONTHS ")/\\s*([-']?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_sla3_cb);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
parse_dot_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    d = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (!check_apost(y, mon, d))
 | 
						|
	return 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_dot(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-']?\\d+)\\.\\s*(\\d+)\\.\\s*([-']?\\d+)"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_dot_cb);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
static int
 | 
						|
parse_dot2_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    mon = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(d, mon, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_dot2(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"([-']?\\d+)\\.\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[./])\\s*([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_dot2_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_dot3_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y, mon, d;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    d = rb_reg_nth_match(2, m);
 | 
						|
    y = rb_reg_nth_match(3, m);
 | 
						|
 | 
						|
    if (!check_apost(mon, d, y))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    mon = INT2FIX(mon_num(mon));
 | 
						|
 | 
						|
    s3e(hash, y, mon, d, 0);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_dot3(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(" DOTLESS_VALID_MONTHS ")\\.\\s*([-']?\\d+)(?:(?:[./])\\s*([-']?\\d+))?"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_dot3_cb);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
parse_year_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE y;
 | 
						|
 | 
						|
    y = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("year", str2num(y));
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_year(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"'(\\d+)\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"'(\\d+)"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_year_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_mon_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE mon;
 | 
						|
 | 
						|
    mon = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("mon", INT2FIX(mon_num(mon)));
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_mon(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"\\b(" ABBR_MONTHS ")\\S*"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(" VALID_MONTHS ")"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_mon_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_mday_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE d;
 | 
						|
 | 
						|
    d = rb_reg_nth_match(1, m);
 | 
						|
    set_hash("mday", str2num(d));
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_mday(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	"(\\d+)(st|nd|rd|th)\\b"
 | 
						|
#else
 | 
						|
	BOS
 | 
						|
	FPW_COM FPT_COM
 | 
						|
	"(\\d+)(st|nd|rd|th)"
 | 
						|
	COM_FPT COM_FPW
 | 
						|
	EOS
 | 
						|
#endif
 | 
						|
	;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_mday_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
n2i(const char *s, long f, long w)
 | 
						|
{
 | 
						|
    long e, i;
 | 
						|
    int v;
 | 
						|
 | 
						|
    e = f + w;
 | 
						|
    v = 0;
 | 
						|
    for (i = f; i < e; i++) {
 | 
						|
	v *= 10;
 | 
						|
	v += s[i] - '0';
 | 
						|
    }
 | 
						|
    return v;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_ddd_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s1, s2, s3, s4, s5;
 | 
						|
    const char *cs2, *cs3, *cs5;
 | 
						|
    long l2, l3, l4, l5;
 | 
						|
 | 
						|
    s1 = rb_reg_nth_match(1, m);
 | 
						|
    s2 = rb_reg_nth_match(2, m);
 | 
						|
    s3 = rb_reg_nth_match(3, m);
 | 
						|
    s4 = rb_reg_nth_match(4, m);
 | 
						|
    s5 = rb_reg_nth_match(5, m);
 | 
						|
 | 
						|
    cs2 = RSTRING_PTR(s2);
 | 
						|
    l2 = RSTRING_LEN(s2);
 | 
						|
 | 
						|
    switch (l2) {
 | 
						|
      case 2:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4))
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	else
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2,    0, 2)));
 | 
						|
	break;
 | 
						|
      case 4:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    set_hash("mon",  INT2FIX(n2i(cs2,    0, 2)));
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2,    2, 2)));
 | 
						|
	}
 | 
						|
	break;
 | 
						|
      case 6:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 | 
						|
	    set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    int                  y = n2i(cs2,    0, 2);
 | 
						|
	    if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		y = -y;
 | 
						|
	    set_hash("year", INT2FIX(y));
 | 
						|
	    set_hash("mon",  INT2FIX(n2i(cs2,    2, 2)));
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2,    4, 2)));
 | 
						|
	}
 | 
						|
	break;
 | 
						|
      case 8:
 | 
						|
      case 10:
 | 
						|
      case 12:
 | 
						|
      case 14:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 | 
						|
	    set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
 | 
						|
	    if (l2 >= 10)
 | 
						|
		set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
 | 
						|
	    if (l2 == 12) {
 | 
						|
		int y = n2i(cs2, l2-12, 2);
 | 
						|
		if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		    y = -y;
 | 
						|
		set_hash("year", INT2FIX(y));
 | 
						|
	    }
 | 
						|
	    if (l2 == 14) {
 | 
						|
		int y = n2i(cs2, l2-14, 4);
 | 
						|
		if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		    y = -y;
 | 
						|
		set_hash("year", INT2FIX(y));
 | 
						|
		set_hash("_comp", Qfalse);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    int                  y = n2i(cs2,    0, 4);
 | 
						|
	    if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		y = -y;
 | 
						|
	    set_hash("year", INT2FIX(y));
 | 
						|
	    set_hash("mon",  INT2FIX(n2i(cs2,    4, 2)));
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2,    6, 2)));
 | 
						|
	    if (l2 >= 10)
 | 
						|
		set_hash("hour", INT2FIX(n2i(cs2,    8, 2)));
 | 
						|
	    if (l2 >= 12)
 | 
						|
		set_hash("min",  INT2FIX(n2i(cs2,   10, 2)));
 | 
						|
	    if (l2 >= 14)
 | 
						|
		set_hash("sec",  INT2FIX(n2i(cs2,   12, 2)));
 | 
						|
	    set_hash("_comp", Qfalse);
 | 
						|
	}
 | 
						|
	break;
 | 
						|
      case 3:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-3, 1)));
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    set_hash("yday", INT2FIX(n2i(cs2,    0, 3)));
 | 
						|
	break;
 | 
						|
      case 5:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 | 
						|
	    set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    int                  y = n2i(cs2,    0, 2);
 | 
						|
	    if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		y = -y;
 | 
						|
	    set_hash("year", INT2FIX(y));
 | 
						|
	    set_hash("yday", INT2FIX(n2i(cs2,    2, 3)));
 | 
						|
	}
 | 
						|
	break;
 | 
						|
      case 7:
 | 
						|
	if (NIL_P(s3) && !NIL_P(s4)) {
 | 
						|
	    set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 | 
						|
	    set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 | 
						|
	    set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 | 
						|
	    set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    int                  y = n2i(cs2,    0, 4);
 | 
						|
	    if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 | 
						|
		y = -y;
 | 
						|
	    set_hash("year", INT2FIX(y));
 | 
						|
	    set_hash("yday", INT2FIX(n2i(cs2,    4, 3)));
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    RB_GC_GUARD(s2);
 | 
						|
    if (!NIL_P(s3)) {
 | 
						|
	cs3 = RSTRING_PTR(s3);
 | 
						|
	l3 = RSTRING_LEN(s3);
 | 
						|
 | 
						|
	if (!NIL_P(s4)) {
 | 
						|
	    switch (l3) {
 | 
						|
	      case 2:
 | 
						|
	      case 4:
 | 
						|
	      case 6:
 | 
						|
		set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
 | 
						|
		if (l3 >= 4)
 | 
						|
		    set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
 | 
						|
		if (l3 >= 6)
 | 
						|
		    set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    switch (l3) {
 | 
						|
	      case 2:
 | 
						|
	      case 4:
 | 
						|
	      case 6:
 | 
						|
		set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
 | 
						|
		if (l3 >= 4)
 | 
						|
		    set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
 | 
						|
		if (l3 >= 6)
 | 
						|
		    set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	RB_GC_GUARD(s3);
 | 
						|
    }
 | 
						|
    if (!NIL_P(s4)) {
 | 
						|
	l4 = RSTRING_LEN(s4);
 | 
						|
 | 
						|
	set_hash("sec_fraction",
 | 
						|
		 rb_rational_new2(str2num(s4),
 | 
						|
				  f_expt(INT2FIX(10), LONG2NUM(l4))));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s5)) {
 | 
						|
	cs5 = RSTRING_PTR(s5);
 | 
						|
	l5 = RSTRING_LEN(s5);
 | 
						|
 | 
						|
	set_hash("zone", s5);
 | 
						|
 | 
						|
	if (*cs5 == '[') {
 | 
						|
	    char *buf = ALLOCA_N(char, l5 + 1);
 | 
						|
	    char *s1, *s2, *s3;
 | 
						|
	    VALUE zone;
 | 
						|
 | 
						|
	    memcpy(buf, cs5, l5);
 | 
						|
	    buf[l5 - 1] = '\0';
 | 
						|
 | 
						|
	    s1 = buf + 1;
 | 
						|
	    s2 = strchr(buf, ':');
 | 
						|
	    if (s2) {
 | 
						|
		*s2 = '\0';
 | 
						|
		s2++;
 | 
						|
	    }
 | 
						|
	    if (s2)
 | 
						|
		s3 = s2;
 | 
						|
	    else
 | 
						|
		s3 = s1;
 | 
						|
	    zone = rb_str_new2(s3);
 | 
						|
	    set_hash("zone", zone);
 | 
						|
	    if (isdigit((unsigned char)*s1))
 | 
						|
		*--s1 = '+';
 | 
						|
	    set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
 | 
						|
	}
 | 
						|
	RB_GC_GUARD(s5);
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_ddd(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		BOS
 | 
						|
#endif
 | 
						|
		"([-+]?)(\\d{2,14})"
 | 
						|
		  "(?:"
 | 
						|
		    "\\s*"
 | 
						|
		    "t?"
 | 
						|
		    "\\s*"
 | 
						|
		    "(\\d{2,6})?(?:[,.](\\d*))?"
 | 
						|
		  ")?"
 | 
						|
		  "(?:"
 | 
						|
		    "\\s*"
 | 
						|
		    "("
 | 
						|
		      "z\\b"
 | 
						|
		    "|"
 | 
						|
		      "[-+]\\d{1,4}\\b"
 | 
						|
		    "|"
 | 
						|
		      "\\[[-+]?\\d[^\\]]*\\]"
 | 
						|
		    ")"
 | 
						|
		")?"
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
		EOS
 | 
						|
#endif
 | 
						|
		;
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_ddd_cb);
 | 
						|
}
 | 
						|
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
static int
 | 
						|
parse_bc_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    set_hash("_bc", Qtrue);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_bc(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_bc_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_frag_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s, n;
 | 
						|
 | 
						|
    s = rb_reg_nth_match(1, m);
 | 
						|
 | 
						|
    if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
 | 
						|
	n = str2num(s);
 | 
						|
	if (f_ge_p(n, INT2FIX(1)) &&
 | 
						|
	    f_le_p(n, INT2FIX(31)))
 | 
						|
	    set_hash("mday", n);
 | 
						|
    }
 | 
						|
    if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
 | 
						|
	n = str2num(s);
 | 
						|
	if (f_ge_p(n, INT2FIX(0)) &&
 | 
						|
	    f_le_p(n, INT2FIX(24)))
 | 
						|
	    set_hash("hour", n);
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_frag(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    SUBS(str, pat, parse_frag_cb);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
static int
 | 
						|
parse_dummy_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_wday_only(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] = "\\A\\s*" FPW "\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_dummy_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_time_only(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] = "\\A\\s*" FPT "\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_dummy_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
parse_wday_and_time(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] = "\\A\\s*(" FPW "\\s+" FPT "|" FPT "\\s+" FPW ")\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_0(pat);
 | 
						|
    SUBS(str, pat, parse_dummy_cb);
 | 
						|
}
 | 
						|
 | 
						|
static unsigned
 | 
						|
have_invalid_char_p(VALUE s)
 | 
						|
{
 | 
						|
    long i;
 | 
						|
 | 
						|
    for (i = 0; i < RSTRING_LEN(s); i++)
 | 
						|
	if (iscntrl((unsigned char)RSTRING_PTR(s)[i]) &&
 | 
						|
	    !isspace((unsigned char)RSTRING_PTR(s)[i]))
 | 
						|
	    return 1;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#define HAVE_ALPHA (1<<0)
 | 
						|
#define HAVE_DIGIT (1<<1)
 | 
						|
#define HAVE_DASH (1<<2)
 | 
						|
#define HAVE_DOT (1<<3)
 | 
						|
#define HAVE_SLASH (1<<4)
 | 
						|
 | 
						|
static unsigned
 | 
						|
check_class(VALUE s)
 | 
						|
{
 | 
						|
    unsigned flags;
 | 
						|
    long i;
 | 
						|
 | 
						|
    flags = 0;
 | 
						|
    for (i = 0; i < RSTRING_LEN(s); i++) {
 | 
						|
	if (isalpha((unsigned char)RSTRING_PTR(s)[i]))
 | 
						|
	    flags |= HAVE_ALPHA;
 | 
						|
	if (isdigit((unsigned char)RSTRING_PTR(s)[i]))
 | 
						|
	    flags |= HAVE_DIGIT;
 | 
						|
	if (RSTRING_PTR(s)[i] == '-')
 | 
						|
	    flags |= HAVE_DASH;
 | 
						|
	if (RSTRING_PTR(s)[i] == '.')
 | 
						|
	    flags |= HAVE_DOT;
 | 
						|
	if (RSTRING_PTR(s)[i] == '/')
 | 
						|
	    flags |= HAVE_SLASH;
 | 
						|
    }
 | 
						|
    return flags;
 | 
						|
}
 | 
						|
 | 
						|
#define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
#define PARSER_ERROR return rb_hash_new()
 | 
						|
#endif
 | 
						|
 | 
						|
VALUE
 | 
						|
date__parse(VALUE str, VALUE comp)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (have_invalid_char_p(str))
 | 
						|
	PARSER_ERROR;
 | 
						|
#endif
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    {
 | 
						|
	static const char pat_source[] =
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
	    "[^-+',./:@[:alnum:]\\[\\]]+"
 | 
						|
#else
 | 
						|
	    "[^[:graph:]]+"
 | 
						|
#endif
 | 
						|
	    ;
 | 
						|
	static VALUE pat = Qnil;
 | 
						|
 | 
						|
	REGCOMP_0(pat);
 | 
						|
	str = rb_str_dup(str);
 | 
						|
	f_gsub_bang(str, pat, asp_string());
 | 
						|
    }
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
    set_hash("_comp", comp);
 | 
						|
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA))
 | 
						|
	parse_day(str, hash);
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	parse_time(str, hash);
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA))
 | 
						|
	parse_era(str, hash);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) {
 | 
						|
	if (parse_eu(str, hash))
 | 
						|
	    goto ok;
 | 
						|
	if (parse_us(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    }
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
 | 
						|
	if (parse_iso(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
 | 
						|
	if (parse_jis(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
 | 
						|
	if (parse_vms(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
 | 
						|
	if (parse_sla(str, hash))
 | 
						|
	    goto ok;
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_SLASH)) {
 | 
						|
	if (parse_sla2(str, hash))
 | 
						|
	    goto ok;
 | 
						|
	if (parse_sla3(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
 | 
						|
	if (parse_dot(str, hash))
 | 
						|
	    goto ok;
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DOT)) {
 | 
						|
	if (parse_dot2(str, hash))
 | 
						|
	    goto ok;
 | 
						|
	if (parse_dot3(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	if (parse_iso2(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	if (parse_year(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA))
 | 
						|
	if (parse_mon(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	if (parse_mday(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	if (parse_ddd(str, hash))
 | 
						|
	    goto ok;
 | 
						|
 | 
						|
#ifdef TIGHT_PARSER
 | 
						|
    if (parse_wday_only(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (parse_time_only(str, hash))
 | 
						|
	    goto ok;
 | 
						|
    if (parse_wday_and_time(str, hash))
 | 
						|
	goto ok;
 | 
						|
 | 
						|
    PARSER_ERROR; /* not found */
 | 
						|
#endif
 | 
						|
 | 
						|
  ok:
 | 
						|
#ifndef TIGHT_PARSER
 | 
						|
    if (HAVE_ELEM_P(HAVE_ALPHA))
 | 
						|
	parse_bc(str, hash);
 | 
						|
    if (HAVE_ELEM_P(HAVE_DIGIT))
 | 
						|
	parse_frag(str, hash);
 | 
						|
#endif
 | 
						|
 | 
						|
    {
 | 
						|
	if (RTEST(ref_hash("_bc"))) {
 | 
						|
	    VALUE y;
 | 
						|
 | 
						|
	    y = ref_hash("cwyear");
 | 
						|
	    if (!NIL_P(y)) {
 | 
						|
		y = f_add(f_negate(y), INT2FIX(1));
 | 
						|
		set_hash("cwyear", y);
 | 
						|
	    }
 | 
						|
	    y = ref_hash("year");
 | 
						|
	    if (!NIL_P(y)) {
 | 
						|
		y = f_add(f_negate(y), INT2FIX(1));
 | 
						|
		set_hash("year", y);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	if (RTEST(ref_hash("_comp"))) {
 | 
						|
	    VALUE y;
 | 
						|
 | 
						|
	    y = ref_hash("cwyear");
 | 
						|
	    if (!NIL_P(y))
 | 
						|
		if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
 | 
						|
		    if (f_ge_p(y, INT2FIX(69)))
 | 
						|
			set_hash("cwyear", f_add(y, INT2FIX(1900)));
 | 
						|
		    else
 | 
						|
			set_hash("cwyear", f_add(y, INT2FIX(2000)));
 | 
						|
		}
 | 
						|
	    y = ref_hash("year");
 | 
						|
	    if (!NIL_P(y))
 | 
						|
		if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
 | 
						|
		    if (f_ge_p(y, INT2FIX(69)))
 | 
						|
			set_hash("year", f_add(y, INT2FIX(1900)));
 | 
						|
		    else
 | 
						|
			set_hash("year", f_add(y, INT2FIX(2000)));
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    del_hash("_bc");
 | 
						|
    del_hash("_comp");
 | 
						|
 | 
						|
    {
 | 
						|
	VALUE zone = ref_hash("zone");
 | 
						|
	if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
 | 
						|
	    set_hash("offset", date_zone_to_diff(zone));
 | 
						|
    }
 | 
						|
 | 
						|
    rb_backref_set(backref);
 | 
						|
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
static VALUE
 | 
						|
comp_year69(VALUE y)
 | 
						|
{
 | 
						|
    if (f_ge_p(y, INT2FIX(69)))
 | 
						|
	return f_add(y, INT2FIX(1900));
 | 
						|
    return f_add(y, INT2FIX(2000));
 | 
						|
}
 | 
						|
 | 
						|
static VALUE
 | 
						|
comp_year50(VALUE y)
 | 
						|
{
 | 
						|
    if (f_ge_p(y, INT2FIX(50)))
 | 
						|
	return f_add(y, INT2FIX(1900));
 | 
						|
    return f_add(y, INT2FIX(2000));
 | 
						|
}
 | 
						|
 | 
						|
static VALUE
 | 
						|
sec_fraction(VALUE f)
 | 
						|
{
 | 
						|
    return rb_rational_new2(str2num(f),
 | 
						|
			    f_expt(INT2FIX(10),
 | 
						|
				   LONG2NUM(RSTRING_LEN(f))));
 | 
						|
}
 | 
						|
 | 
						|
#define SNUM 14
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_ext_datetime_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1], y;
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(s[3])) {
 | 
						|
	set_hash("mday", str2num(s[3]));
 | 
						|
	if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
 | 
						|
	    y = str2num(s[1]);
 | 
						|
	    if (RSTRING_LEN(s[1]) < 4)
 | 
						|
		y = comp_year69(y);
 | 
						|
	    set_hash("year", y);
 | 
						|
	}
 | 
						|
	if (NIL_P(s[2])) {
 | 
						|
	    if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    set_hash("mon", str2num(s[2]));
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[5])) {
 | 
						|
	set_hash("yday", str2num(s[5]));
 | 
						|
	if (!NIL_P(s[4])) {
 | 
						|
	    y = str2num(s[4]);
 | 
						|
	    if (RSTRING_LEN(s[4]) < 4)
 | 
						|
		y = comp_year69(y);
 | 
						|
	    set_hash("year", y);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[8])) {
 | 
						|
	set_hash("cweek", str2num(s[7]));
 | 
						|
	set_hash("cwday", str2num(s[8]));
 | 
						|
	if (!NIL_P(s[6])) {
 | 
						|
	    y = str2num(s[6]);
 | 
						|
	    if (RSTRING_LEN(s[6]) < 4)
 | 
						|
		y = comp_year69(y);
 | 
						|
	    set_hash("cwyear", y);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[9])) {
 | 
						|
	set_hash("cwday", str2num(s[9]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[10])) {
 | 
						|
	set_hash("hour", str2num(s[10]));
 | 
						|
	set_hash("min", str2num(s[11]));
 | 
						|
	if (!NIL_P(s[12]))
 | 
						|
	    set_hash("sec", str2num(s[12]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[13])) {
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[13]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[14])) {
 | 
						|
	set_hash("zone", s[14]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[14]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_ext_datetime(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
 | 
						|
		"([-+]?\\d{2,})?-(\\d{3})|"
 | 
						|
		"(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
 | 
						|
		"-w-(\\d))"
 | 
						|
	"(?:t"
 | 
						|
	"(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
 | 
						|
	"(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, iso8601_ext_datetime_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 17
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_bas_datetime_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1], y;
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(s[3])) {
 | 
						|
	set_hash("mday", str2num(s[3]));
 | 
						|
	if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
 | 
						|
	    y = str2num(s[1]);
 | 
						|
	    if (RSTRING_LEN(s[1]) < 4)
 | 
						|
		y = comp_year69(y);
 | 
						|
	    set_hash("year", y);
 | 
						|
	}
 | 
						|
	if (*RSTRING_PTR(s[2]) == '-') {
 | 
						|
	    if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    set_hash("mon", str2num(s[2]));
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[5])) {
 | 
						|
	set_hash("yday", str2num(s[5]));
 | 
						|
	y = str2num(s[4]);
 | 
						|
	if (RSTRING_LEN(s[4]) < 4)
 | 
						|
	    y = comp_year69(y);
 | 
						|
	set_hash("year", y);
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[6])) {
 | 
						|
	set_hash("yday", str2num(s[6]));
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[9])) {
 | 
						|
	set_hash("cweek", str2num(s[8]));
 | 
						|
	set_hash("cwday", str2num(s[9]));
 | 
						|
	y = str2num(s[7]);
 | 
						|
	if (RSTRING_LEN(s[7]) < 4)
 | 
						|
	    y = comp_year69(y);
 | 
						|
	set_hash("cwyear", y);
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[11])) {
 | 
						|
	set_hash("cweek", str2num(s[10]));
 | 
						|
	set_hash("cwday", str2num(s[11]));
 | 
						|
    }
 | 
						|
    else if (!NIL_P(s[12])) {
 | 
						|
	set_hash("cwday", str2num(s[12]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[13])) {
 | 
						|
	set_hash("hour", str2num(s[13]));
 | 
						|
	set_hash("min", str2num(s[14]));
 | 
						|
	if (!NIL_P(s[15]))
 | 
						|
	    set_hash("sec", str2num(s[15]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[16])) {
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[16]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[17])) {
 | 
						|
	set_hash("zone", s[17]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[17]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_bas_datetime(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
 | 
						|
		   "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
 | 
						|
		   "-(\\d{3})|"
 | 
						|
		   "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
 | 
						|
		   "-w(\\d{2})(\\d)|"
 | 
						|
		   "-w-(\\d))"
 | 
						|
	"(?:t?"
 | 
						|
	"(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
 | 
						|
	"(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, iso8601_bas_datetime_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 5
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_ext_time_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("hour", str2num(s[1]));
 | 
						|
    set_hash("min", str2num(s[2]));
 | 
						|
    if (!NIL_P(s[3]))
 | 
						|
	set_hash("sec", str2num(s[3]));
 | 
						|
    if (!NIL_P(s[4]))
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[4]));
 | 
						|
    if (!NIL_P(s[5])) {
 | 
						|
	set_hash("zone", s[5]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[5]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
#define iso8601_bas_time_cb iso8601_ext_time_cb
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_ext_time(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?"
 | 
						|
	"(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, iso8601_ext_time_cb);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
iso8601_bas_time(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?"
 | 
						|
	"(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, iso8601_bas_time_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__iso8601(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
 | 
						|
    if (iso8601_ext_datetime(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (iso8601_bas_datetime(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (iso8601_ext_time(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (iso8601_bas_time(str, hash))
 | 
						|
	goto ok;
 | 
						|
 | 
						|
  ok:
 | 
						|
    rb_backref_set(backref);
 | 
						|
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 8
 | 
						|
 | 
						|
static int
 | 
						|
rfc3339_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("year", str2num(s[1]));
 | 
						|
    set_hash("mon", str2num(s[2]));
 | 
						|
    set_hash("mday", str2num(s[3]));
 | 
						|
    set_hash("hour", str2num(s[4]));
 | 
						|
    set_hash("min", str2num(s[5]));
 | 
						|
    set_hash("sec", str2num(s[6]));
 | 
						|
    set_hash("zone", s[8]);
 | 
						|
    set_hash("offset", date_zone_to_diff(s[8]));
 | 
						|
    if (!NIL_P(s[7]))
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[7]));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
rfc3339(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
 | 
						|
	"(?:t|\\s)"
 | 
						|
	"(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
 | 
						|
	"(z|[-+]\\d{2}:\\d{2})\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, rfc3339_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__rfc3339(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
    rfc3339(str, hash);
 | 
						|
    rb_backref_set(backref);
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 8
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_datetime_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("year", str2num(s[1]));
 | 
						|
    if (!NIL_P(s[2]))
 | 
						|
	set_hash("mon", str2num(s[2]));
 | 
						|
    if (!NIL_P(s[3]))
 | 
						|
	set_hash("mday", str2num(s[3]));
 | 
						|
    if (!NIL_P(s[4]))
 | 
						|
	set_hash("hour", str2num(s[4]));
 | 
						|
    if (!NIL_P(s[5]))
 | 
						|
	set_hash("min", str2num(s[5]));
 | 
						|
    if (!NIL_P(s[6]))
 | 
						|
	set_hash("sec", str2num(s[6]));
 | 
						|
    if (!NIL_P(s[7]))
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[7]));
 | 
						|
    if (!NIL_P(s[8])) {
 | 
						|
	set_hash("zone", s[8]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[8]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_datetime(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
 | 
						|
	"(?:t"
 | 
						|
	  "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
 | 
						|
	"(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, xmlschema_datetime_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 5
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_time_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("hour", str2num(s[1]));
 | 
						|
    set_hash("min", str2num(s[2]));
 | 
						|
    if (!NIL_P(s[3]))
 | 
						|
	set_hash("sec", str2num(s[3]));
 | 
						|
    if (!NIL_P(s[4]))
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[4]));
 | 
						|
    if (!NIL_P(s[5])) {
 | 
						|
	set_hash("zone", s[5]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[5]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_time(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
 | 
						|
	"(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, xmlschema_time_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 4
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_trunc_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(s[1]))
 | 
						|
	set_hash("mon", str2num(s[1]));
 | 
						|
    if (!NIL_P(s[2]))
 | 
						|
	set_hash("mday", str2num(s[2]));
 | 
						|
    if (!NIL_P(s[3]))
 | 
						|
	set_hash("mday", str2num(s[3]));
 | 
						|
    if (!NIL_P(s[4])) {
 | 
						|
	set_hash("zone", s[4]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[4]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
xmlschema_trunc(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
 | 
						|
	"(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, xmlschema_trunc_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__xmlschema(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
 | 
						|
    if (xmlschema_datetime(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (xmlschema_time(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (xmlschema_trunc(str, hash))
 | 
						|
	goto ok;
 | 
						|
 | 
						|
  ok:
 | 
						|
    rb_backref_set(backref);
 | 
						|
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 8
 | 
						|
 | 
						|
static int
 | 
						|
rfc2822_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1], y;
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!NIL_P(s[1])) {
 | 
						|
	set_hash("wday", INT2FIX(day_num(s[1])));
 | 
						|
    }
 | 
						|
    set_hash("mday", str2num(s[2]));
 | 
						|
    set_hash("mon", INT2FIX(mon_num(s[3])));
 | 
						|
    y = str2num(s[4]);
 | 
						|
    if (RSTRING_LEN(s[4]) < 4)
 | 
						|
	y = comp_year50(y);
 | 
						|
    set_hash("year", y);
 | 
						|
    set_hash("hour", str2num(s[5]));
 | 
						|
    set_hash("min", str2num(s[6]));
 | 
						|
    if (!NIL_P(s[7]))
 | 
						|
	set_hash("sec", str2num(s[7]));
 | 
						|
    set_hash("zone", s[8]);
 | 
						|
    set_hash("offset", date_zone_to_diff(s[8]));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
rfc2822(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
 | 
						|
	"(\\d{1,2})\\s+"
 | 
						|
	"(" ABBR_MONTHS ")\\s+"
 | 
						|
	"(-?\\d{2,})\\s+"
 | 
						|
	"(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
 | 
						|
	"([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, rfc2822_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__rfc2822(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
    rfc2822(str, hash);
 | 
						|
    rb_backref_set(backref);
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 8
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type1_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("wday", INT2FIX(day_num(s[1])));
 | 
						|
    set_hash("mday", str2num(s[2]));
 | 
						|
    set_hash("mon", INT2FIX(mon_num(s[3])));
 | 
						|
    set_hash("year", str2num(s[4]));
 | 
						|
    set_hash("hour", str2num(s[5]));
 | 
						|
    set_hash("min", str2num(s[6]));
 | 
						|
    set_hash("sec", str2num(s[7]));
 | 
						|
    set_hash("zone", s[8]);
 | 
						|
    set_hash("offset", INT2FIX(0));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type1(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
 | 
						|
	"(\\d{2})\\s+"
 | 
						|
	"(" ABBR_MONTHS ")\\s+"
 | 
						|
	"(-?\\d{4})\\s+"
 | 
						|
	"(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 | 
						|
	"(gmt)\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, httpdate_type1_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 8
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type2_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1], y;
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("wday", INT2FIX(day_num(s[1])));
 | 
						|
    set_hash("mday", str2num(s[2]));
 | 
						|
    set_hash("mon", INT2FIX(mon_num(s[3])));
 | 
						|
    y = str2num(s[4]);
 | 
						|
    if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
 | 
						|
	y = comp_year69(y);
 | 
						|
    set_hash("year", y);
 | 
						|
    set_hash("hour", str2num(s[5]));
 | 
						|
    set_hash("min", str2num(s[6]));
 | 
						|
    set_hash("sec", str2num(s[7]));
 | 
						|
    set_hash("zone", s[8]);
 | 
						|
    set_hash("offset", INT2FIX(0));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type2(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(" DAYS ")\\s*,\\s+"
 | 
						|
	"(\\d{2})\\s*-\\s*"
 | 
						|
	"(" ABBR_MONTHS ")\\s*-\\s*"
 | 
						|
	"(\\d{2})\\s+"
 | 
						|
	"(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 | 
						|
	"(gmt)\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, httpdate_type2_cb);
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 7
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type3_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    set_hash("wday", INT2FIX(day_num(s[1])));
 | 
						|
    set_hash("mon", INT2FIX(mon_num(s[2])));
 | 
						|
    set_hash("mday", str2num(s[3]));
 | 
						|
    set_hash("hour", str2num(s[4]));
 | 
						|
    set_hash("min", str2num(s[5]));
 | 
						|
    set_hash("sec", str2num(s[6]));
 | 
						|
    set_hash("year", str2num(s[7]));
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
httpdate_type3(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*(" ABBR_DAYS ")\\s+"
 | 
						|
	"(" ABBR_MONTHS ")\\s+"
 | 
						|
	"(\\d{1,2})\\s+"
 | 
						|
	"(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 | 
						|
	"(\\d{4})\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, httpdate_type3_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__httpdate(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
 | 
						|
    if (httpdate_type1(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (httpdate_type2(str, hash))
 | 
						|
	goto ok;
 | 
						|
    if (httpdate_type3(str, hash))
 | 
						|
	goto ok;
 | 
						|
 | 
						|
  ok:
 | 
						|
    rb_backref_set(backref);
 | 
						|
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
#undef SNUM
 | 
						|
#define SNUM 9
 | 
						|
 | 
						|
static int
 | 
						|
jisx0301_cb(VALUE m, VALUE hash)
 | 
						|
{
 | 
						|
    VALUE s[SNUM + 1];
 | 
						|
    int ep;
 | 
						|
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	s[0] = Qnil;
 | 
						|
	for (i = 1; i <= SNUM; i++)
 | 
						|
	    s[i] = rb_reg_nth_match(i, m);
 | 
						|
    }
 | 
						|
 | 
						|
    ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
 | 
						|
    set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
 | 
						|
    set_hash("mon", str2num(s[3]));
 | 
						|
    set_hash("mday", str2num(s[4]));
 | 
						|
    if (!NIL_P(s[5])) {
 | 
						|
	set_hash("hour", str2num(s[5]));
 | 
						|
	if (!NIL_P(s[6]))
 | 
						|
	    set_hash("min", str2num(s[6]));
 | 
						|
	if (!NIL_P(s[7]))
 | 
						|
	    set_hash("sec", str2num(s[7]));
 | 
						|
    }
 | 
						|
    if (!NIL_P(s[8]))
 | 
						|
	set_hash("sec_fraction", sec_fraction(s[8]));
 | 
						|
    if (!NIL_P(s[9])) {
 | 
						|
	set_hash("zone", s[9]);
 | 
						|
	set_hash("offset", date_zone_to_diff(s[9]));
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
jisx0301(VALUE str, VALUE hash)
 | 
						|
{
 | 
						|
    static const char pat_source[] =
 | 
						|
	"\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
 | 
						|
	"(?:t"
 | 
						|
	"(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
 | 
						|
	"(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
 | 
						|
    static VALUE pat = Qnil;
 | 
						|
 | 
						|
    REGCOMP_I(pat);
 | 
						|
    MATCH(str, pat, jisx0301_cb);
 | 
						|
}
 | 
						|
 | 
						|
VALUE
 | 
						|
date__jisx0301(VALUE str)
 | 
						|
{
 | 
						|
    VALUE backref, hash;
 | 
						|
 | 
						|
    backref = rb_backref_get();
 | 
						|
    rb_match_busy(backref);
 | 
						|
 | 
						|
    hash = rb_hash_new();
 | 
						|
    if (jisx0301(str, hash))
 | 
						|
	goto ok;
 | 
						|
    hash = date__iso8601(str);
 | 
						|
 | 
						|
  ok:
 | 
						|
    rb_backref_set(backref);
 | 
						|
    return hash;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
Local variables:
 | 
						|
c-file-style: "ruby"
 | 
						|
End:
 | 
						|
*/
 |