Ruby  2.5.0dev(2017-10-22revision60238)
date_parse.c
Go to the documentation of this file.
1 /*
2  date_parse.c: Coded by Tadayoshi Funaba 2011,2012
3 */
4 
5 #include "ruby.h"
6 #include "ruby/encoding.h"
7 #include "ruby/re.h"
8 #include <ctype.h>
9 
10 RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
11 RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
12 
13 /* #define TIGHT_PARSER */
14 
15 #define sizeof_array(o) (sizeof o / sizeof o[0])
16 
17 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
18 #define f_add(x,y) rb_funcall(x, '+', 1, y)
19 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
20 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
21 #define f_div(x,y) rb_funcall(x, '/', 1, y)
22 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
23 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
24 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
25 
26 #define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
27 #define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
28 #define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
29 #define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
30 
31 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
32 
33 #define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
34 #define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
35 #define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
36 #define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
37 #define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
38 #define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
39 #define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
40 #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
41 #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
42 
43 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
44 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
45 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
46 
47 #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
48 #define str2num(s) rb_str_to_inum(s, 10, 0)
49 
50 static const char abbr_days[][4] = {
51  "sun", "mon", "tue", "wed",
52  "thu", "fri", "sat"
53 };
54 
55 static const char abbr_months[][4] = {
56  "jan", "feb", "mar", "apr", "may", "jun",
57  "jul", "aug", "sep", "oct", "nov", "dec"
58 };
59 
60 #define issign(c) ((c) == '-' || (c) == '+')
61 #define asp_string() rb_str_new(" ", 1)
62 #ifdef TIGHT_PARSER
63 #define asuba_string() rb_str_new("\001", 1)
64 #define asubb_string() rb_str_new("\002", 1)
65 #define asubw_string() rb_str_new("\027", 1)
66 #define asubt_string() rb_str_new("\024", 1)
67 #endif
68 
69 #define DECDIGIT "0123456789"
70 
71 static void
72 s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
73 {
74  VALUE vbuf = 0;
75  VALUE c = Qnil;
76 
77  if (!RB_TYPE_P(m, T_STRING))
78  m = f_to_s(m);
79 
80  if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
81  VALUE oy = y;
82  VALUE om = m;
83  VALUE od = d;
84 
85  y = od;
86  m = oy;
87  d = om;
88  }
89 
90  if (NIL_P(y)) {
91  if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
92  y = d;
93  d = Qnil;
94  }
95  if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
96  y = d;
97  d = Qnil;
98  }
99  }
100 
101  if (!NIL_P(y)) {
102  const char *s, *bp, *ep;
103  size_t l;
104 
105  s = RSTRING_PTR(y);
106  while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
107  s++;
108  bp = s;
109  if (issign((unsigned char)*s))
110  s++;
111  l = strspn(s, DECDIGIT);
112  ep = s + l;
113  if (*ep) {
114  y = d;
115  d = rb_str_new(bp, ep - bp);
116  }
117  }
118 
119  if (!NIL_P(m)) {
120  const char *s;
121 
122  s = RSTRING_PTR(m);
123  if (*s == '\'' || RSTRING_LEN(m) > 2) {
124  /* us -> be */
125  VALUE oy = y;
126  VALUE om = m;
127  VALUE od = d;
128 
129  y = om;
130  m = od;
131  d = oy;
132  }
133  }
134 
135  if (!NIL_P(d)) {
136  const char *s;
137 
138  s = RSTRING_PTR(d);
139  if (*s == '\'' || RSTRING_LEN(d) > 2) {
140  VALUE oy = y;
141  VALUE od = d;
142 
143  y = od;
144  d = oy;
145  }
146  }
147 
148  if (!NIL_P(y)) {
149  const char *s, *bp, *ep;
150  int sign = 0;
151  size_t l;
152  VALUE iy;
153 
154  s = RSTRING_PTR(y);
155  while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
156  s++;
157  bp = s;
158  if (issign(*s)) {
159  s++;
160  sign = 1;
161  }
162  if (sign)
163  c = Qfalse;
164  l = strspn(s, DECDIGIT);
165  ep = s + l;
166  if (l > 2)
167  c = Qfalse;
168  {
169  char *buf;
170 
171  buf = ALLOCV_N(char, vbuf, ep - bp + 1);
172  memcpy(buf, bp, ep - bp);
173  buf[ep - bp] = '\0';
174  iy = cstr2num(buf);
175  ALLOCV_END(vbuf);
176  }
177  set_hash("year", iy);
178  }
179 
180  if (bc)
181  set_hash("_bc", Qtrue);
182 
183  if (!NIL_P(m)) {
184  const char *s, *bp, *ep;
185  size_t l;
186  VALUE im;
187 
188  s = RSTRING_PTR(m);
189  while (!isdigit((unsigned char)*s))
190  s++;
191  bp = s;
192  l = strspn(s, DECDIGIT);
193  ep = s + l;
194  {
195  char *buf;
196 
197  buf = ALLOCV_N(char, vbuf, ep - bp + 1);
198  memcpy(buf, bp, ep - bp);
199  buf[ep - bp] = '\0';
200  im = cstr2num(buf);
201  ALLOCV_END(vbuf);
202  }
203  set_hash("mon", im);
204  }
205 
206  if (!NIL_P(d)) {
207  const char *s, *bp, *ep;
208  size_t l;
209  VALUE id;
210 
211  s = RSTRING_PTR(d);
212  while (!isdigit((unsigned char)*s))
213  s++;
214  bp = s;
215  l = strspn(s, DECDIGIT);
216  ep = s + l;
217  {
218  char *buf;
219 
220  buf = ALLOCV_N(char, vbuf, ep - bp + 1);
221  memcpy(buf, bp, ep - bp);
222  buf[ep - bp] = '\0';
223  id = cstr2num(buf);
224  ALLOCV_END(vbuf);
225  }
226  set_hash("mday", id);
227  }
228 
229  if (!NIL_P(c))
230  set_hash("_comp", c);
231 }
232 
233 #define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
234 #define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
235 #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
236 #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
237 
238 #ifdef TIGHT_PARSER
239 #define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
240 #define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
241 #define DOTLESS_VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")"
242 #define BOS "\\A\\s*"
243 #define FPA "\\001"
244 #define FPB "\\002"
245 #define FPW "\\027"
246 #define FPT "\\024"
247 #define FPW_COM "\\s*(?:" FPW "\\s*,?)?\\s*"
248 #define FPT_COM "\\s*(?:" FPT "\\s*,?)?\\s*"
249 #define COM_FPW "\\s*(?:,?\\s*" FPW ")?\\s*"
250 #define COM_FPT "\\s*(?:,?\\s*(?:@|\\b[aA][tT]\\b)?\\s*" FPT ")?\\s*"
251 #define TEE_FPT "\\s*(?:[tT]?" FPT ")?"
252 #define EOS "\\s*\\z"
253 #endif
254 
255 static VALUE
256 regcomp(const char *source, long len, int opt)
257 {
258  VALUE pat;
259 
260  pat = rb_reg_new(source, len, opt);
262  return pat;
263 }
264 
265 #define REGCOMP(pat,opt) \
266 { \
267  if (NIL_P(pat)) \
268  pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
269 }
270 
271 #define REGCOMP_0(pat) REGCOMP(pat, 0)
272 #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
273 
274 #define MATCH(s,p,c) \
275 { \
276  return match(s, p, hash, c); \
277 }
278 
279 static int
280 match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
281 {
282  VALUE m;
283 
284  m = f_match(pat, str);
285 
286  if (NIL_P(m))
287  return 0;
288 
289  (*cb)(m, hash);
290 
291  return 1;
292 }
293 
294 static int
295 subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
296 {
297  VALUE m;
298 
299  m = f_match(pat, str);
300 
301  if (NIL_P(m))
302  return 0;
303 
304  {
305  VALUE be, en;
306 
307  be = f_begin(m, INT2FIX(0));
308  en = f_end(m, INT2FIX(0));
309  f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), rep);
310  (*cb)(m, hash);
311  }
312 
313  return 1;
314 }
315 
316 #define SUBS(s,p,c) \
317 { \
318  return subx(s, asp_string(), p, hash, c); \
319 }
320 
321 #ifdef TIGHT_PARSER
322 #define SUBA(s,p,c) \
323 { \
324  return subx(s, asuba_string(), p, hash, c); \
325 }
326 
327 #define SUBB(s,p,c) \
328 { \
329  return subx(s, asubb_string(), p, hash, c); \
330 }
331 
332 #define SUBW(s,p,c) \
333 { \
334  return subx(s, asubw_string(), p, hash, c); \
335 }
336 
337 #define SUBT(s,p,c) \
338 { \
339  return subx(s, asubt_string(), p, hash, c); \
340 }
341 #endif
342 
343 #include "zonetab.h"
344 
345 static int
346 str_end_with(const char *s, long l, const char *w)
347 {
348  int n = (int)strlen(w);
349  return (l >= n && strncmp(s - n, w, n) == 0);
350 }
351 
352 VALUE
354 {
355  VALUE offset = Qnil;
356  VALUE vbuf = 0;
357 
358  long l, i;
359  char *s, *dest, *d;
360  int sp = 1;
361 
362  l = RSTRING_LEN(str);
363  s = RSTRING_PTR(str);
364 
365  dest = d = ALLOCV_N(char, vbuf, l + 1);
366 
367  for (i = 0; i < l; i++) {
368  if (isspace((unsigned char)s[i]) || s[i] == '\0') {
369  if (!sp)
370  *d++ = ' ';
371  sp = 1;
372  }
373  else {
374  if (isalpha((unsigned char)s[i]))
375  *d++ = tolower((unsigned char)s[i]);
376  else
377  *d++ = s[i];
378  sp = 0;
379  }
380  }
381  if (d > dest) {
382  if (*(d - 1) == ' ')
383  --d;
384  *d = '\0';
385  }
386  l = d - dest;
387  s = dest;
388  {
389  static const char STD[] = " standard time";
390  static const char DST1[] = " daylight time";
391  static const char DST2[] = " dst";
392  int dst = 0;
393 
394  if (str_end_with(d, l, STD)) {
395  l -= sizeof(STD) - 1;
396  }
397  else if (str_end_with(d, l, DST1)) {
398  l -= sizeof(DST1) - 1;
399  dst = 1;
400  }
401  else if (str_end_with(d, l, DST2)) {
402  l -= sizeof(DST2) - 1;
403  dst = 1;
404  }
405  {
406  const struct zone *z = zonetab(s, (unsigned int)l);
407  if (z) {
408  int d = z->offset;
409  if (dst)
410  d += 3600;
411  offset = INT2FIX(d);
412  goto ok;
413  }
414  }
415  {
416  char *p;
417  int sign = 0;
418  long hour = 0, min = 0, sec = 0;
419 
420  if (l > 3 &&
421  (strncmp(s, "gmt", 3) == 0 ||
422  strncmp(s, "utc", 3) == 0)) {
423  s += 3;
424  l -= 3;
425  }
426  if (issign(*s)) {
427  sign = *s == '-';
428  s++;
429  l--;
430 
431  hour = STRTOUL(s, &p, 10);
432  if (*p == ':') {
433  s = ++p;
434  min = STRTOUL(s, &p, 10);
435  if (*p == ':') {
436  s = ++p;
437  sec = STRTOUL(s, &p, 10);
438  }
439  goto num;
440  }
441  if (*p == ',' || *p == '.') {
442  char *e = 0;
443  p++;
444  min = STRTOUL(p, &e, 10) * 3600;
445  if (sign) {
446  hour = -hour;
447  min = -min;
448  }
449  offset = rb_rational_new(INT2FIX(min),
450  rb_int_positive_pow(10, (int)(e - p)));
451  offset = f_add(INT2FIX(hour * 3600), offset);
452  goto ok;
453  }
454  else if (l > 2) {
455  size_t n;
456  int ov;
457 
458  if (l >= 1)
459  hour = ruby_scan_digits(&s[0], 2 - l % 2, 10, &n, &ov);
460  if (l >= 3)
461  min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
462  if (l >= 5)
463  sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
464  goto num;
465  }
466  num:
467  sec += min * 60 + hour * 3600;
468  if (sign) sec = -sec;
469  offset = INT2FIX(sec);
470  }
471  }
472  }
473  RB_GC_GUARD(str);
474  ok:
475  ALLOCV_END(vbuf);
476  return offset;
477 }
478 
479 static int
480 day_num(VALUE s)
481 {
482  int i;
483 
484  for (i = 0; i < (int)sizeof_array(abbr_days); i++)
485  if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
486  break;
487  return i;
488 }
489 
490 static int
491 mon_num(VALUE s)
492 {
493  int i;
494 
495  for (i = 0; i < (int)sizeof_array(abbr_months); i++)
496  if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
497  break;
498  return i + 1;
499 }
500 
501 static int
502 parse_day_cb(VALUE m, VALUE hash)
503 {
504  VALUE s;
505 
506  s = rb_reg_nth_match(1, m);
507  set_hash("wday", INT2FIX(day_num(s)));
508  return 1;
509 }
510 
511 static int
512 parse_day(VALUE str, VALUE hash)
513 {
514  static const char pat_source[] =
515 #ifndef TIGHT_PARSER
516  "\\b(" ABBR_DAYS ")[^-/\\d\\s]*"
517 #else
518  "(" VALID_DAYS ")"
519 #endif
520  ;
521  static VALUE pat = Qnil;
522 
523  REGCOMP_I(pat);
524 #ifndef TIGHT_PARSER
525  SUBS(str, pat, parse_day_cb);
526 #else
527  SUBW(str, pat, parse_day_cb);
528 #endif
529 }
530 
531 static int
532 parse_time2_cb(VALUE m, VALUE hash)
533 {
534  VALUE h, min, s, f, p;
535 
536  h = rb_reg_nth_match(1, m);
537  h = str2num(h);
538 
539  min = rb_reg_nth_match(2, m);
540  if (!NIL_P(min))
541  min = str2num(min);
542 
543  s = rb_reg_nth_match(3, m);
544  if (!NIL_P(s))
545  s = str2num(s);
546 
547  f = rb_reg_nth_match(4, m);
548 
549  if (!NIL_P(f))
550  f = rb_rational_new2(str2num(f),
551  f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
552 
553  p = rb_reg_nth_match(5, m);
554 
555  if (!NIL_P(p)) {
556  int ih = NUM2INT(h);
557  ih %= 12;
558  if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
559  ih += 12;
560  h = INT2FIX(ih);
561  }
562 
563  set_hash("hour", h);
564  if (!NIL_P(min))
565  set_hash("min", min);
566  if (!NIL_P(s))
567  set_hash("sec", s);
568  if (!NIL_P(f))
569  set_hash("sec_fraction", f);
570 
571  return 1;
572 }
573 
574 static int
575 parse_time_cb(VALUE m, VALUE hash)
576 {
577  static const char pat_source[] =
578  "\\A(\\d+)h?"
579  "(?:\\s*:?\\s*(\\d+)m?"
580  "(?:"
581  "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
582  ")?"
583  ")?"
584  "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
585  static VALUE pat = Qnil;
586  VALUE s1, s2;
587 
588  s1 = rb_reg_nth_match(1, m);
589  s2 = rb_reg_nth_match(2, m);
590 
591  if (!NIL_P(s2))
592  set_hash("zone", s2);
593 
594  REGCOMP_I(pat);
595 
596  {
597  VALUE m = f_match(pat, s1);
598 
599  if (NIL_P(m))
600  return 0;
601  parse_time2_cb(m, hash);
602  }
603 
604  return 1;
605 }
606 
607 static int
608 parse_time(VALUE str, VALUE hash)
609 {
610  static const char pat_source[] =
611  "("
612  "(?:"
613  "\\d+\\s*:\\s*\\d+"
614  "(?:"
615 #ifndef TIGHT_PARSER
616  "\\s*:\\s*\\d+(?:[,.]\\d*)?"
617 #else
618  "\\s*:\\s*\\d+(?:[,.]\\d+)?"
619 #endif
620  ")?"
621  "|"
622  "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
623  ")"
624  "(?:"
625  "\\s*"
626  "[ap](?:m\\b|\\.m\\.)"
627  ")?"
628  "|"
629  "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
630  ")"
631  "(?:"
632  "\\s*"
633  "("
634  "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
635  "|"
636  "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
637  "|"
638  "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
639  ")"
640  ")?";
641  static VALUE pat = Qnil;
642 
643  REGCOMP_I(pat);
644 #ifndef TIGHT_PARSER
645  SUBS(str, pat, parse_time_cb);
646 #else
647  SUBT(str, pat, parse_time_cb);
648 #endif
649 }
650 
651 #ifdef TIGHT_PARSER
652 static int
653 parse_era1_cb(VALUE m, VALUE hash)
654 {
655  return 1;
656 }
657 
658 static int
659 parse_era1(VALUE str, VALUE hash)
660 {
661  static const char pat_source[] =
662  "(a(?:d|\\.d\\.))";
663  static VALUE pat = Qnil;
664 
665  REGCOMP_I(pat);
666  SUBA(str, pat, parse_era1_cb);
667 }
668 
669 static int
670 parse_era2_cb(VALUE m, VALUE hash)
671 {
672  VALUE b;
673 
674  b = rb_reg_nth_match(1, m);
675  if (*RSTRING_PTR(b) == 'B' ||
676  *RSTRING_PTR(b) == 'b')
677  set_hash("_bc", Qtrue);
678  return 1;
679 }
680 
681 static int
682 parse_era2(VALUE str, VALUE hash)
683 {
684  static const char pat_source[] =
685  "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
686  static VALUE pat = Qnil;
687 
688  REGCOMP_I(pat);
689  SUBB(str, pat, parse_era2_cb);
690 }
691 
692 static int
693 parse_era(VALUE str, VALUE hash)
694 {
695  if (parse_era1(str, hash)) /* pre */
696  goto ok;
697  if (parse_era2(str, hash)) /* post */
698  goto ok;
699  return 0;
700  ok:
701  return 1;
702 }
703 #endif
704 
705 #ifdef TIGHT_PARSER
706 static int
707 check_year_width(VALUE y)
708 {
709  char *s;
710  size_t l;
711 
712  s = RSTRING_PTR(y);
713  l = strcspn(s, DECDIGIT);
714  s += l;
715  l = strspn(s, DECDIGIT);
716  if (l != 2)
717  return 0;
718  return 1;
719 }
720 
721 static int
722 check_apost(VALUE a, VALUE b, VALUE c)
723 {
724  int f = 0;
725 
726  if (!NIL_P(a) && *RSTRING_PTR(a) == '\'') {
727  if (!check_year_width(a))
728  return 0;
729  f++;
730  }
731  if (!NIL_P(b) && *RSTRING_PTR(b) == '\'') {
732  if (!check_year_width(b))
733  return 0;
734  if (!NIL_P(c))
735  return 0;
736  f++;
737  }
738  if (!NIL_P(c) && *RSTRING_PTR(c) == '\'') {
739  if (!check_year_width(c))
740  return 0;
741  f++;
742  }
743  if (f > 1)
744  return 0;
745  return 1;
746 }
747 #endif
748 
749 static int
750 parse_eu_cb(VALUE m, VALUE hash)
751 {
752 #ifndef TIGHT_PARSER
753  VALUE y, mon, d, b;
754 
755  d = rb_reg_nth_match(1, m);
756  mon = rb_reg_nth_match(2, m);
757  b = rb_reg_nth_match(3, m);
758  y = rb_reg_nth_match(4, m);
759 
760  mon = INT2FIX(mon_num(mon));
761 
762  s3e(hash, y, mon, d, !NIL_P(b) &&
763  (*RSTRING_PTR(b) == 'B' ||
764  *RSTRING_PTR(b) == 'b'));
765 #else
766  VALUE y, mon, d;
767 
768  d = rb_reg_nth_match(1, m);
769  mon = rb_reg_nth_match(2, m);
770  y = rb_reg_nth_match(3, m);
771 
772  if (!check_apost(d, mon, y))
773  return 0;
774 
775  mon = INT2FIX(mon_num(mon));
776 
777  s3e(hash, y, mon, d, 0);
778 #endif
779  return 1;
780 }
781 
782 static int
783 parse_eu(VALUE str, VALUE hash)
784 {
785  static const char pat_source[] =
786 #ifdef TIGHT_PARSER
787  BOS
788  FPW_COM FPT_COM
789 #endif
790 #ifndef TIGHT_PARSER
791  "('?\\d+)[^-\\d\\s]*"
792 #else
793  "(\\d+)(?:(?:st|nd|rd|th)\\b)?"
794 #endif
795  "\\s*"
796 #ifndef TIGHT_PARSER
797  "(" ABBR_MONTHS ")[^-\\d\\s']*"
798 #else
799  "(" VALID_MONTHS ")"
800 #endif
801  "(?:"
802  "\\s*"
803 #ifndef TIGHT_PARSER
804  "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
805  "\\s*"
806  "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
807 #else
808  "(?:" FPA ")?"
809  "\\s*"
810  "([-']?\\d+)"
811  "\\s*"
812  "(?:" FPA "|" FPB ")?"
813 #endif
814  ")?"
815 #ifdef TIGHT_PARSER
816  COM_FPT COM_FPW
817  EOS
818 #endif
819  ;
820  static VALUE pat = Qnil;
821 
822  REGCOMP_I(pat);
823  SUBS(str, pat, parse_eu_cb);
824 }
825 
826 static int
827 parse_us_cb(VALUE m, VALUE hash)
828 {
829 #ifndef TIGHT_PARSER
830  VALUE y, mon, d, b;
831 
832  mon = rb_reg_nth_match(1, m);
833  d = rb_reg_nth_match(2, m);
834 
835  b = rb_reg_nth_match(3, m);
836  y = rb_reg_nth_match(4, m);
837 
838  mon = INT2FIX(mon_num(mon));
839 
840  s3e(hash, y, mon, d, !NIL_P(b) &&
841  (*RSTRING_PTR(b) == 'B' ||
842  *RSTRING_PTR(b) == 'b'));
843 #else
844  VALUE y, mon, d;
845 
846  mon = rb_reg_nth_match(1, m);
847  d = rb_reg_nth_match(2, m);
848  y = rb_reg_nth_match(3, m);
849 
850  if (!check_apost(mon, d, y))
851  return 0;
852 
853  mon = INT2FIX(mon_num(mon));
854 
855  s3e(hash, y, mon, d, 0);
856 #endif
857  return 1;
858 }
859 
860 static int
861 parse_us(VALUE str, VALUE hash)
862 {
863  static const char pat_source[] =
864 #ifdef TIGHT_PARSER
865  BOS
866  FPW_COM FPT_COM
867 #endif
868 #ifndef TIGHT_PARSER
869  "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
870 #else
871  "\\b(" VALID_MONTHS ")"
872 #endif
873  "\\s*"
874 #ifndef TIGHT_PARSER
875  "('?\\d+)[^-\\d\\s']*"
876 #else
877  "('?\\d+)(?:(?:st|nd|rd|th)\\b)?"
878  COM_FPT
879 #endif
880  "(?:"
881  "\\s*,?"
882  "\\s*"
883 #ifndef TIGHT_PARSER
884  "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
885  "\\s*"
886  "('?-?\\d+)"
887 #else
888  "(?:" FPA ")?"
889  "\\s*"
890  "([-']?\\d+)"
891  "\\s*"
892  "(?:" FPA "|" FPB ")?"
893 #endif
894  ")?"
895 #ifdef TIGHT_PARSER
896  COM_FPT COM_FPW
897  EOS
898 #endif
899  ;
900  static VALUE pat = Qnil;
901 
902  REGCOMP_I(pat);
903  SUBS(str, pat, parse_us_cb);
904 }
905 
906 static int
907 parse_iso_cb(VALUE m, VALUE hash)
908 {
909  VALUE y, mon, d;
910 
911  y = rb_reg_nth_match(1, m);
912  mon = rb_reg_nth_match(2, m);
913  d = rb_reg_nth_match(3, m);
914 
915 #ifdef TIGHT_PARSER
916  if (!check_apost(y, mon, d))
917  return 0;
918 #endif
919 
920  s3e(hash, y, mon, d, 0);
921  return 1;
922 }
923 
924 static int
925 parse_iso(VALUE str, VALUE hash)
926 {
927  static const char pat_source[] =
928 #ifndef TIGHT_PARSER
929  "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
930 #else
931  BOS
932  FPW_COM FPT_COM
933  "([-+']?\\d+)-(\\d+)-([-']?\\d+)"
934  TEE_FPT COM_FPW
935  EOS
936 #endif
937  ;
938  static VALUE pat = Qnil;
939 
940  REGCOMP_0(pat);
941  SUBS(str, pat, parse_iso_cb);
942 }
943 
944 static int
945 parse_iso21_cb(VALUE m, VALUE hash)
946 {
947  VALUE y, w, d;
948 
949  y = rb_reg_nth_match(1, m);
950  w = rb_reg_nth_match(2, m);
951  d = rb_reg_nth_match(3, m);
952 
953  if (!NIL_P(y))
954  set_hash("cwyear", str2num(y));
955  set_hash("cweek", str2num(w));
956  if (!NIL_P(d))
957  set_hash("cwday", str2num(d));
958 
959  return 1;
960 }
961 
962 static int
963 parse_iso21(VALUE str, VALUE hash)
964 {
965  static const char pat_source[] =
966 #ifndef TIGHT_PARSER
967  "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"
968 #else
969  BOS
970  FPW_COM FPT_COM
971  "(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?"
972  TEE_FPT COM_FPW
973  EOS
974 #endif
975  ;
976  static VALUE pat = Qnil;
977 
978  REGCOMP_I(pat);
979  SUBS(str, pat, parse_iso21_cb);
980 }
981 
982 static int
983 parse_iso22_cb(VALUE m, VALUE hash)
984 {
985  VALUE d;
986 
987  d = rb_reg_nth_match(1, m);
988  set_hash("cwday", str2num(d));
989  return 1;
990 }
991 
992 static int
993 parse_iso22(VALUE str, VALUE hash)
994 {
995  static const char pat_source[] =
996 #ifndef TIGHT_PARSER
997  "-w-(\\d)\\b"
998 #else
999  BOS
1000  FPW_COM FPT_COM
1001  "-w-(\\d)"
1002  TEE_FPT COM_FPW
1003  EOS
1004 #endif
1005  ;
1006  static VALUE pat = Qnil;
1007 
1008  REGCOMP_I(pat);
1009  SUBS(str, pat, parse_iso22_cb);
1010 }
1011 
1012 static int
1013 parse_iso23_cb(VALUE m, VALUE hash)
1014 {
1015  VALUE mon, d;
1016 
1017  mon = rb_reg_nth_match(1, m);
1018  d = rb_reg_nth_match(2, m);
1019 
1020  if (!NIL_P(mon))
1021  set_hash("mon", str2num(mon));
1022  set_hash("mday", str2num(d));
1023 
1024  return 1;
1025 }
1026 
1027 static int
1028 parse_iso23(VALUE str, VALUE hash)
1029 {
1030  static const char pat_source[] =
1031 #ifndef TIGHT_PARSER
1032  "--(\\d{2})?-(\\d{2})\\b"
1033 #else
1034  BOS
1035  FPW_COM FPT_COM
1036  "--(\\d{2})?-(\\d{2})"
1037  TEE_FPT COM_FPW
1038  EOS
1039 #endif
1040  ;
1041  static VALUE pat = Qnil;
1042 
1043  REGCOMP_0(pat);
1044  SUBS(str, pat, parse_iso23_cb);
1045 }
1046 
1047 static int
1048 parse_iso24_cb(VALUE m, VALUE hash)
1049 {
1050  VALUE mon, d;
1051 
1052  mon = rb_reg_nth_match(1, m);
1053  d = rb_reg_nth_match(2, m);
1054 
1055  set_hash("mon", str2num(mon));
1056  if (!NIL_P(d))
1057  set_hash("mday", str2num(d));
1058 
1059  return 1;
1060 }
1061 
1062 static int
1063 parse_iso24(VALUE str, VALUE hash)
1064 {
1065  static const char pat_source[] =
1066 #ifndef TIGHT_PARSER
1067  "--(\\d{2})(\\d{2})?\\b"
1068 #else
1069  BOS
1070  FPW_COM FPT_COM
1071  "--(\\d{2})(\\d{2})?"
1072  TEE_FPT COM_FPW
1073  EOS
1074 #endif
1075  ;
1076  static VALUE pat = Qnil;
1077 
1078  REGCOMP_0(pat);
1079  SUBS(str, pat, parse_iso24_cb);
1080 }
1081 
1082 static int
1083 parse_iso25_cb(VALUE m, VALUE hash)
1084 {
1085  VALUE y, d;
1086 
1087  y = rb_reg_nth_match(1, m);
1088  d = rb_reg_nth_match(2, m);
1089 
1090  set_hash("year", str2num(y));
1091  set_hash("yday", str2num(d));
1092 
1093  return 1;
1094 }
1095 
1096 static int
1097 parse_iso25(VALUE str, VALUE hash)
1098 {
1099  static const char pat0_source[] =
1100 #ifndef TIGHT_PARSER
1101  "[,.](\\d{2}|\\d{4})-\\d{3}\\b"
1102 #else
1103  BOS
1104  FPW_COM FPT_COM
1105  "[,.](\\d{2}|\\d{4})-\\d{3}"
1106  TEE_FPT COM_FPW
1107  EOS
1108 #endif
1109  ;
1110  static VALUE pat0 = Qnil;
1111  static const char pat_source[] =
1112 #ifndef TIGHT_PARSER
1113  "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"
1114 #else
1115  BOS
1116  FPW_COM FPT_COM
1117  "(\\d{2}|\\d{4})-(\\d{3})"
1118  TEE_FPT COM_FPW
1119  EOS
1120 #endif
1121  ;
1122  static VALUE pat = Qnil;
1123 
1124  REGCOMP_0(pat0);
1125  REGCOMP_0(pat);
1126 
1127  if (!NIL_P(f_match(pat0, str)))
1128  return 0;
1129  SUBS(str, pat, parse_iso25_cb);
1130 }
1131 
1132 static int
1133 parse_iso26_cb(VALUE m, VALUE hash)
1134 {
1135  VALUE d;
1136 
1137  d = rb_reg_nth_match(1, m);
1138  set_hash("yday", str2num(d));
1139 
1140  return 1;
1141 }
1142 static int
1143 parse_iso26(VALUE str, VALUE hash)
1144 {
1145  static const char pat0_source[] =
1146 #ifndef TIGHT_PARSER
1147  "\\d-\\d{3}\\b"
1148 #else
1149  BOS
1150  FPW_COM FPT_COM
1151  "\\d-\\d{3}"
1152  TEE_FPT COM_FPW
1153  EOS
1154 #endif
1155  ;
1156  static VALUE pat0 = Qnil;
1157  static const char pat_source[] =
1158 #ifndef TIGHT_PARSER
1159  "\\b-(\\d{3})\\b"
1160 #else
1161  BOS
1162  FPW_COM FPT_COM
1163  "-(\\d{3})"
1164  TEE_FPT COM_FPW
1165  EOS
1166 #endif
1167  ;
1168  static VALUE pat = Qnil;
1169 
1170  REGCOMP_0(pat0);
1171  REGCOMP_0(pat);
1172 
1173  if (!NIL_P(f_match(pat0, str)))
1174  return 0;
1175  SUBS(str, pat, parse_iso26_cb);
1176 }
1177 
1178 static int
1179 parse_iso2(VALUE str, VALUE hash)
1180 {
1181  if (parse_iso21(str, hash))
1182  goto ok;
1183  if (parse_iso22(str, hash))
1184  goto ok;
1185  if (parse_iso23(str, hash))
1186  goto ok;
1187  if (parse_iso24(str, hash))
1188  goto ok;
1189  if (parse_iso25(str, hash))
1190  goto ok;
1191  if (parse_iso26(str, hash))
1192  goto ok;
1193  return 0;
1194 
1195  ok:
1196  return 1;
1197 }
1198 
1199 static int
1200 gengo(int c)
1201 {
1202  int e;
1203 
1204  switch (c) {
1205  case 'M': case 'm': e = 1867; break;
1206  case 'T': case 't': e = 1911; break;
1207  case 'S': case 's': e = 1925; break;
1208  case 'H': case 'h': e = 1988; break;
1209  default: e = 0; break;
1210  }
1211  return e;
1212 }
1213 
1214 static int
1215 parse_jis_cb(VALUE m, VALUE hash)
1216 {
1217  VALUE e, y, mon, d;
1218  int ep;
1219 
1220  e = rb_reg_nth_match(1, m);
1221  y = rb_reg_nth_match(2, m);
1222  mon = rb_reg_nth_match(3, m);
1223  d = rb_reg_nth_match(4, m);
1224 
1225  ep = gengo(*RSTRING_PTR(e));
1226 
1227  set_hash("year", f_add(str2num(y), INT2FIX(ep)));
1228  set_hash("mon", str2num(mon));
1229  set_hash("mday", str2num(d));
1230 
1231  return 1;
1232 }
1233 
1234 static int
1235 parse_jis(VALUE str, VALUE hash)
1236 {
1237  static const char pat_source[] =
1238 #ifndef TIGHT_PARSER
1239  "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1240 #else
1241  BOS
1242  FPW_COM FPT_COM
1243  "([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1244  TEE_FPT COM_FPW
1245  EOS
1246 #endif
1247  ;
1248  static VALUE pat = Qnil;
1249 
1250  REGCOMP_I(pat);
1251  SUBS(str, pat, parse_jis_cb);
1252 }
1253 
1254 static int
1255 parse_vms11_cb(VALUE m, VALUE hash)
1256 {
1257  VALUE y, mon, d;
1258 
1259  d = rb_reg_nth_match(1, m);
1260  mon = rb_reg_nth_match(2, m);
1261  y = rb_reg_nth_match(3, m);
1262 
1263 #ifdef TIGHT_PARSER
1264  if (!check_apost(d, mon, y))
1265  return 0;
1266 #endif
1267 
1268  mon = INT2FIX(mon_num(mon));
1269 
1270  s3e(hash, y, mon, d, 0);
1271  return 1;
1272 }
1273 
1274 static int
1275 parse_vms11(VALUE str, VALUE hash)
1276 {
1277  static const char pat_source[] =
1278 #ifndef TIGHT_PARSER
1279  "('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
1280  "-('?-?\\d+)"
1281 #else
1282  BOS
1283  FPW_COM FPT_COM
1284  "([-']?\\d+)-(" DOTLESS_VALID_MONTHS ")"
1285  "-([-']?\\d+)"
1286  COM_FPT COM_FPW
1287  EOS
1288 #endif
1289  ;
1290  static VALUE pat = Qnil;
1291 
1292  REGCOMP_I(pat);
1293  SUBS(str, pat, parse_vms11_cb);
1294 }
1295 
1296 static int
1297 parse_vms12_cb(VALUE m, VALUE hash)
1298 {
1299  VALUE y, mon, d;
1300 
1301  mon = rb_reg_nth_match(1, m);
1302  d = rb_reg_nth_match(2, m);
1303  y = rb_reg_nth_match(3, m);
1304 
1305 #ifdef TIGHT_PARSER
1306  if (!check_apost(mon, d, y))
1307  return 0;
1308 #endif
1309 
1310  mon = INT2FIX(mon_num(mon));
1311 
1312  s3e(hash, y, mon, d, 0);
1313  return 1;
1314 }
1315 
1316 static int
1317 parse_vms12(VALUE str, VALUE hash)
1318 {
1319  static const char pat_source[] =
1320 #ifndef TIGHT_PARSER
1321  "\\b(" ABBR_MONTHS ")[^-/.]*"
1322  "-('?-?\\d+)(?:-('?-?\\d+))?"
1323 #else
1324  BOS
1325  FPW_COM FPT_COM
1326  "(" DOTLESS_VALID_MONTHS ")"
1327  "-([-']?\\d+)(?:-([-']?\\d+))?"
1328  COM_FPT COM_FPW
1329  EOS
1330 #endif
1331  ;
1332  static VALUE pat = Qnil;
1333 
1334  REGCOMP_I(pat);
1335  SUBS(str, pat, parse_vms12_cb);
1336 }
1337 
1338 static int
1339 parse_vms(VALUE str, VALUE hash)
1340 {
1341  if (parse_vms11(str, hash))
1342  goto ok;
1343  if (parse_vms12(str, hash))
1344  goto ok;
1345  return 0;
1346 
1347  ok:
1348  return 1;
1349 }
1350 
1351 static int
1352 parse_sla_cb(VALUE m, VALUE hash)
1353 {
1354  VALUE y, mon, d;
1355 
1356  y = rb_reg_nth_match(1, m);
1357  mon = rb_reg_nth_match(2, m);
1358  d = rb_reg_nth_match(3, m);
1359 
1360 #ifdef TIGHT_PARSER
1361  if (!check_apost(y, mon, d))
1362  return 0;
1363 #endif
1364 
1365  s3e(hash, y, mon, d, 0);
1366  return 1;
1367 }
1368 
1369 static int
1370 parse_sla(VALUE str, VALUE hash)
1371 {
1372  static const char pat_source[] =
1373 #ifndef TIGHT_PARSER
1374  "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
1375 #else
1376  BOS
1377  FPW_COM FPT_COM
1378  "([-']?\\d+)/\\s*('?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1379  COM_FPT COM_FPW
1380  EOS
1381 #endif
1382  ;
1383  static VALUE pat = Qnil;
1384 
1385  REGCOMP_I(pat);
1386  SUBS(str, pat, parse_sla_cb);
1387 }
1388 
1389 #ifdef TIGHT_PARSER
1390 static int
1391 parse_sla2_cb(VALUE m, VALUE hash)
1392 {
1393  VALUE y, mon, d;
1394 
1395  d = rb_reg_nth_match(1, m);
1396  mon = rb_reg_nth_match(2, m);
1397  y = rb_reg_nth_match(3, m);
1398 
1399  if (!check_apost(d, mon, y))
1400  return 0;
1401 
1402  mon = INT2FIX(mon_num(mon));
1403 
1404  s3e(hash, y, mon, d, 0);
1405  return 1;
1406 }
1407 
1408 static int
1409 parse_sla2(VALUE str, VALUE hash)
1410 {
1411  static const char pat_source[] =
1412  BOS
1413  FPW_COM FPT_COM
1414  "([-']?\\d+)/\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1415  COM_FPT COM_FPW
1416  EOS
1417  ;
1418  static VALUE pat = Qnil;
1419 
1420  REGCOMP_I(pat);
1421  SUBS(str, pat, parse_sla2_cb);
1422 }
1423 
1424 static int
1425 parse_sla3_cb(VALUE m, VALUE hash)
1426 {
1427  VALUE y, mon, d;
1428 
1429  mon = rb_reg_nth_match(1, m);
1430  d = rb_reg_nth_match(2, m);
1431  y = rb_reg_nth_match(3, m);
1432 
1433  if (!check_apost(mon, d, y))
1434  return 0;
1435 
1436  mon = INT2FIX(mon_num(mon));
1437 
1438  s3e(hash, y, mon, d, 0);
1439  return 1;
1440 }
1441 
1442 static int
1443 parse_sla3(VALUE str, VALUE hash)
1444 {
1445  static const char pat_source[] =
1446  BOS
1447  FPW_COM FPT_COM
1448  "(" DOTLESS_VALID_MONTHS ")/\\s*([-']?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1449  COM_FPT COM_FPW
1450  EOS
1451  ;
1452  static VALUE pat = Qnil;
1453 
1454  REGCOMP_I(pat);
1455  SUBS(str, pat, parse_sla3_cb);
1456 }
1457 #endif
1458 
1459 static int
1460 parse_dot_cb(VALUE m, VALUE hash)
1461 {
1462  VALUE y, mon, d;
1463 
1464  y = rb_reg_nth_match(1, m);
1465  mon = rb_reg_nth_match(2, m);
1466  d = rb_reg_nth_match(3, m);
1467 
1468 #ifdef TIGHT_PARSER
1469  if (!check_apost(y, mon, d))
1470  return 0;
1471 #endif
1472 
1473  s3e(hash, y, mon, d, 0);
1474  return 1;
1475 }
1476 
1477 static int
1478 parse_dot(VALUE str, VALUE hash)
1479 {
1480  static const char pat_source[] =
1481 #ifndef TIGHT_PARSER
1482  "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
1483 #else
1484  BOS
1485  FPW_COM FPT_COM
1486  "([-']?\\d+)\\.\\s*(\\d+)\\.\\s*([-']?\\d+)"
1487  COM_FPT COM_FPW
1488  EOS
1489 #endif
1490  ;
1491  static VALUE pat = Qnil;
1492 
1493  REGCOMP_I(pat);
1494  SUBS(str, pat, parse_dot_cb);
1495 }
1496 
1497 #ifdef TIGHT_PARSER
1498 static int
1499 parse_dot2_cb(VALUE m, VALUE hash)
1500 {
1501  VALUE y, mon, d;
1502 
1503  d = rb_reg_nth_match(1, m);
1504  mon = rb_reg_nth_match(2, m);
1505  y = rb_reg_nth_match(3, m);
1506 
1507  if (!check_apost(d, mon, y))
1508  return 0;
1509 
1510  mon = INT2FIX(mon_num(mon));
1511 
1512  s3e(hash, y, mon, d, 0);
1513  return 1;
1514 }
1515 
1516 static int
1517 parse_dot2(VALUE str, VALUE hash)
1518 {
1519  static const char pat_source[] =
1520  BOS
1521  FPW_COM FPT_COM
1522  "([-']?\\d+)\\.\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[./])\\s*([-']?\\d+))?"
1523  COM_FPT COM_FPW
1524  EOS
1525  ;
1526  static VALUE pat = Qnil;
1527 
1528  REGCOMP_I(pat);
1529  SUBS(str, pat, parse_dot2_cb);
1530 }
1531 
1532 static int
1533 parse_dot3_cb(VALUE m, VALUE hash)
1534 {
1535  VALUE y, mon, d;
1536 
1537  mon = rb_reg_nth_match(1, m);
1538  d = rb_reg_nth_match(2, m);
1539  y = rb_reg_nth_match(3, m);
1540 
1541  if (!check_apost(mon, d, y))
1542  return 0;
1543 
1544  mon = INT2FIX(mon_num(mon));
1545 
1546  s3e(hash, y, mon, d, 0);
1547  return 1;
1548 }
1549 
1550 static int
1551 parse_dot3(VALUE str, VALUE hash)
1552 {
1553  static const char pat_source[] =
1554  BOS
1555  FPW_COM FPT_COM
1556  "(" DOTLESS_VALID_MONTHS ")\\.\\s*([-']?\\d+)(?:(?:[./])\\s*([-']?\\d+))?"
1557  COM_FPT COM_FPW
1558  EOS
1559  ;
1560  static VALUE pat = Qnil;
1561 
1562  REGCOMP_I(pat);
1563  SUBS(str, pat, parse_dot3_cb);
1564 }
1565 #endif
1566 
1567 static int
1568 parse_year_cb(VALUE m, VALUE hash)
1569 {
1570  VALUE y;
1571 
1572  y = rb_reg_nth_match(1, m);
1573  set_hash("year", str2num(y));
1574  return 1;
1575 }
1576 
1577 static int
1578 parse_year(VALUE str, VALUE hash)
1579 {
1580  static const char pat_source[] =
1581 #ifndef TIGHT_PARSER
1582  "'(\\d+)\\b"
1583 #else
1584  BOS
1585  FPW_COM FPT_COM
1586  "'(\\d+)"
1587  COM_FPT COM_FPW
1588  EOS
1589 #endif
1590  ;
1591  static VALUE pat = Qnil;
1592 
1593  REGCOMP_0(pat);
1594  SUBS(str, pat, parse_year_cb);
1595 }
1596 
1597 static int
1598 parse_mon_cb(VALUE m, VALUE hash)
1599 {
1600  VALUE mon;
1601 
1602  mon = rb_reg_nth_match(1, m);
1603  set_hash("mon", INT2FIX(mon_num(mon)));
1604  return 1;
1605 }
1606 
1607 static int
1608 parse_mon(VALUE str, VALUE hash)
1609 {
1610  static const char pat_source[] =
1611 #ifndef TIGHT_PARSER
1612  "\\b(" ABBR_MONTHS ")\\S*"
1613 #else
1614  BOS
1615  FPW_COM FPT_COM
1616  "(" VALID_MONTHS ")"
1617  COM_FPT COM_FPW
1618  EOS
1619 #endif
1620  ;
1621  static VALUE pat = Qnil;
1622 
1623  REGCOMP_I(pat);
1624  SUBS(str, pat, parse_mon_cb);
1625 }
1626 
1627 static int
1628 parse_mday_cb(VALUE m, VALUE hash)
1629 {
1630  VALUE d;
1631 
1632  d = rb_reg_nth_match(1, m);
1633  set_hash("mday", str2num(d));
1634  return 1;
1635 }
1636 
1637 static int
1638 parse_mday(VALUE str, VALUE hash)
1639 {
1640  static const char pat_source[] =
1641 #ifndef TIGHT_PARSER
1642  "(\\d+)(st|nd|rd|th)\\b"
1643 #else
1644  BOS
1645  FPW_COM FPT_COM
1646  "(\\d+)(st|nd|rd|th)"
1647  COM_FPT COM_FPW
1648  EOS
1649 #endif
1650  ;
1651  static VALUE pat = Qnil;
1652 
1653  REGCOMP_I(pat);
1654  SUBS(str, pat, parse_mday_cb);
1655 }
1656 
1657 static int
1658 n2i(const char *s, long f, long w)
1659 {
1660  long e, i;
1661  int v;
1662 
1663  e = f + w;
1664  v = 0;
1665  for (i = f; i < e; i++) {
1666  v *= 10;
1667  v += s[i] - '0';
1668  }
1669  return v;
1670 }
1671 
1672 static int
1673 parse_ddd_cb(VALUE m, VALUE hash)
1674 {
1675  VALUE s1, s2, s3, s4, s5;
1676  const char *cs2, *cs3, *cs5;
1677  long l2, l3, l4, l5;
1678 
1679  s1 = rb_reg_nth_match(1, m);
1680  s2 = rb_reg_nth_match(2, m);
1681  s3 = rb_reg_nth_match(3, m);
1682  s4 = rb_reg_nth_match(4, m);
1683  s5 = rb_reg_nth_match(5, m);
1684 
1685  cs2 = RSTRING_PTR(s2);
1686  l2 = RSTRING_LEN(s2);
1687 
1688  switch (l2) {
1689  case 2:
1690  if (NIL_P(s3) && !NIL_P(s4))
1691  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1692  else
1693  set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
1694  break;
1695  case 4:
1696  if (NIL_P(s3) && !NIL_P(s4)) {
1697  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1698  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1699  }
1700  else {
1701  set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
1702  set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
1703  }
1704  break;
1705  case 6:
1706  if (NIL_P(s3) && !NIL_P(s4)) {
1707  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1708  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1709  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1710  }
1711  else {
1712  int y = n2i(cs2, 0, 2);
1713  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1714  y = -y;
1715  set_hash("year", INT2FIX(y));
1716  set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
1717  set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
1718  }
1719  break;
1720  case 8:
1721  case 10:
1722  case 12:
1723  case 14:
1724  if (NIL_P(s3) && !NIL_P(s4)) {
1725  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1726  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1727  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1728  set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
1729  if (l2 >= 10)
1730  set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
1731  if (l2 == 12) {
1732  int y = n2i(cs2, l2-12, 2);
1733  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1734  y = -y;
1735  set_hash("year", INT2FIX(y));
1736  }
1737  if (l2 == 14) {
1738  int y = n2i(cs2, l2-14, 4);
1739  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1740  y = -y;
1741  set_hash("year", INT2FIX(y));
1742  set_hash("_comp", Qfalse);
1743  }
1744  }
1745  else {
1746  int y = n2i(cs2, 0, 4);
1747  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1748  y = -y;
1749  set_hash("year", INT2FIX(y));
1750  set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
1751  set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
1752  if (l2 >= 10)
1753  set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
1754  if (l2 >= 12)
1755  set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
1756  if (l2 >= 14)
1757  set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
1758  set_hash("_comp", Qfalse);
1759  }
1760  break;
1761  case 3:
1762  if (NIL_P(s3) && !NIL_P(s4)) {
1763  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1764  set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
1765  }
1766  else
1767  set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
1768  break;
1769  case 5:
1770  if (NIL_P(s3) && !NIL_P(s4)) {
1771  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1772  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1773  set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
1774  }
1775  else {
1776  int y = n2i(cs2, 0, 2);
1777  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1778  y = -y;
1779  set_hash("year", INT2FIX(y));
1780  set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
1781  }
1782  break;
1783  case 7:
1784  if (NIL_P(s3) && !NIL_P(s4)) {
1785  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1786  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1787  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1788  set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
1789  }
1790  else {
1791  int y = n2i(cs2, 0, 4);
1792  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1793  y = -y;
1794  set_hash("year", INT2FIX(y));
1795  set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
1796  }
1797  break;
1798  }
1799  RB_GC_GUARD(s2);
1800  if (!NIL_P(s3)) {
1801  cs3 = RSTRING_PTR(s3);
1802  l3 = RSTRING_LEN(s3);
1803 
1804  if (!NIL_P(s4)) {
1805  switch (l3) {
1806  case 2:
1807  case 4:
1808  case 6:
1809  set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
1810  if (l3 >= 4)
1811  set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
1812  if (l3 >= 6)
1813  set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
1814  break;
1815  }
1816  }
1817  else {
1818  switch (l3) {
1819  case 2:
1820  case 4:
1821  case 6:
1822  set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
1823  if (l3 >= 4)
1824  set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
1825  if (l3 >= 6)
1826  set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
1827  break;
1828  }
1829  }
1830  RB_GC_GUARD(s3);
1831  }
1832  if (!NIL_P(s4)) {
1833  l4 = RSTRING_LEN(s4);
1834 
1835  set_hash("sec_fraction",
1837  f_expt(INT2FIX(10), LONG2NUM(l4))));
1838  }
1839  if (!NIL_P(s5)) {
1840  cs5 = RSTRING_PTR(s5);
1841  l5 = RSTRING_LEN(s5);
1842 
1843  set_hash("zone", s5);
1844 
1845  if (*cs5 == '[') {
1846  VALUE vbuf = 0;
1847  char *buf = ALLOCV_N(char, vbuf, l5 + 1);
1848  char *s1, *s2, *s3;
1849  VALUE zone;
1850 
1851  memcpy(buf, cs5, l5);
1852  buf[l5 - 1] = '\0';
1853 
1854  s1 = buf + 1;
1855  s2 = strchr(buf, ':');
1856  if (s2) {
1857  *s2 = '\0';
1858  s2++;
1859  }
1860  if (s2)
1861  s3 = s2;
1862  else
1863  s3 = s1;
1864  zone = rb_str_new2(s3);
1865  set_hash("zone", zone);
1866  if (isdigit((unsigned char)*s1))
1867  *--s1 = '+';
1868  set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
1869  ALLOCV_END(vbuf);
1870  }
1871  RB_GC_GUARD(s5);
1872  }
1873 
1874  return 1;
1875 }
1876 
1877 static int
1878 parse_ddd(VALUE str, VALUE hash)
1879 {
1880  static const char pat_source[] =
1881 #ifdef TIGHT_PARSER
1882  BOS
1883 #endif
1884  "([-+]?)(\\d{2,14})"
1885  "(?:"
1886  "\\s*"
1887  "t?"
1888  "\\s*"
1889  "(\\d{2,6})?(?:[,.](\\d*))?"
1890  ")?"
1891  "(?:"
1892  "\\s*"
1893  "("
1894  "z\\b"
1895  "|"
1896  "[-+]\\d{1,4}\\b"
1897  "|"
1898  "\\[[-+]?\\d[^\\]]*\\]"
1899  ")"
1900  ")?"
1901 #ifdef TIGHT_PARSER
1902  EOS
1903 #endif
1904  ;
1905  static VALUE pat = Qnil;
1906 
1907  REGCOMP_I(pat);
1908  SUBS(str, pat, parse_ddd_cb);
1909 }
1910 
1911 #ifndef TIGHT_PARSER
1912 static int
1913 parse_bc_cb(VALUE m, VALUE hash)
1914 {
1915  set_hash("_bc", Qtrue);
1916  return 1;
1917 }
1918 
1919 static int
1920 parse_bc(VALUE str, VALUE hash)
1921 {
1922  static const char pat_source[] =
1923  "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
1924  static VALUE pat = Qnil;
1925 
1926  REGCOMP_I(pat);
1927  SUBS(str, pat, parse_bc_cb);
1928 }
1929 
1930 static int
1931 parse_frag_cb(VALUE m, VALUE hash)
1932 {
1933  VALUE s, n;
1934 
1935  s = rb_reg_nth_match(1, m);
1936 
1937  if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
1938  n = str2num(s);
1939  if (f_ge_p(n, INT2FIX(1)) &&
1940  f_le_p(n, INT2FIX(31)))
1941  set_hash("mday", n);
1942  }
1943  if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
1944  n = str2num(s);
1945  if (f_ge_p(n, INT2FIX(0)) &&
1946  f_le_p(n, INT2FIX(24)))
1947  set_hash("hour", n);
1948  }
1949 
1950  return 1;
1951 }
1952 
1953 static int
1954 parse_frag(VALUE str, VALUE hash)
1955 {
1956  static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
1957  static VALUE pat = Qnil;
1958 
1959  REGCOMP_I(pat);
1960  SUBS(str, pat, parse_frag_cb);
1961 }
1962 #endif
1963 
1964 #ifdef TIGHT_PARSER
1965 static int
1966 parse_dummy_cb(VALUE m, VALUE hash)
1967 {
1968  return 1;
1969 }
1970 
1971 static int
1972 parse_wday_only(VALUE str, VALUE hash)
1973 {
1974  static const char pat_source[] = "\\A\\s*" FPW "\\s*\\z";
1975  static VALUE pat = Qnil;
1976 
1977  REGCOMP_0(pat);
1978  SUBS(str, pat, parse_dummy_cb);
1979 }
1980 
1981 static int
1982 parse_time_only(VALUE str, VALUE hash)
1983 {
1984  static const char pat_source[] = "\\A\\s*" FPT "\\s*\\z";
1985  static VALUE pat = Qnil;
1986 
1987  REGCOMP_0(pat);
1988  SUBS(str, pat, parse_dummy_cb);
1989 }
1990 
1991 static int
1992 parse_wday_and_time(VALUE str, VALUE hash)
1993 {
1994  static const char pat_source[] = "\\A\\s*(" FPW "\\s+" FPT "|" FPT "\\s+" FPW ")\\s*\\z";
1995  static VALUE pat = Qnil;
1996 
1997  REGCOMP_0(pat);
1998  SUBS(str, pat, parse_dummy_cb);
1999 }
2000 
2001 static unsigned
2002 have_invalid_char_p(VALUE s)
2003 {
2004  long i;
2005 
2006  for (i = 0; i < RSTRING_LEN(s); i++)
2007  if (iscntrl((unsigned char)RSTRING_PTR(s)[i]) &&
2008  !isspace((unsigned char)RSTRING_PTR(s)[i]))
2009  return 1;
2010  return 0;
2011 }
2012 #endif
2013 
2014 #define HAVE_ALPHA (1<<0)
2015 #define HAVE_DIGIT (1<<1)
2016 #define HAVE_DASH (1<<2)
2017 #define HAVE_DOT (1<<3)
2018 #define HAVE_SLASH (1<<4)
2019 
2020 static unsigned
2021 check_class(VALUE s)
2022 {
2023  unsigned flags;
2024  long i;
2025 
2026  flags = 0;
2027  for (i = 0; i < RSTRING_LEN(s); i++) {
2028  if (isalpha((unsigned char)RSTRING_PTR(s)[i]))
2029  flags |= HAVE_ALPHA;
2030  if (isdigit((unsigned char)RSTRING_PTR(s)[i]))
2031  flags |= HAVE_DIGIT;
2032  if (RSTRING_PTR(s)[i] == '-')
2033  flags |= HAVE_DASH;
2034  if (RSTRING_PTR(s)[i] == '.')
2035  flags |= HAVE_DOT;
2036  if (RSTRING_PTR(s)[i] == '/')
2037  flags |= HAVE_SLASH;
2038  }
2039  return flags;
2040 }
2041 
2042 #define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
2043 
2044 #ifdef TIGHT_PARSER
2045 #define PARSER_ERROR return rb_hash_new()
2046 #endif
2047 
2048 VALUE
2050 {
2051  VALUE backref, hash;
2052 
2053 #ifdef TIGHT_PARSER
2054  if (have_invalid_char_p(str))
2055  PARSER_ERROR;
2056 #endif
2057 
2058  backref = rb_backref_get();
2059  rb_match_busy(backref);
2060 
2061  {
2062  static const char pat_source[] =
2063 #ifndef TIGHT_PARSER
2064  "[^-+',./:@[:alnum:]\\[\\]]+"
2065 #else
2066  "[^[:graph:]]+"
2067 #endif
2068  ;
2069  static VALUE pat = Qnil;
2070 
2071  REGCOMP_0(pat);
2072  str = rb_str_dup(str);
2073  f_gsub_bang(str, pat, asp_string());
2074  }
2075 
2076  hash = rb_hash_new();
2077  set_hash("_comp", comp);
2078 
2079  if (HAVE_ELEM_P(HAVE_ALPHA))
2080  parse_day(str, hash);
2081  if (HAVE_ELEM_P(HAVE_DIGIT))
2082  parse_time(str, hash);
2083 
2084 #ifdef TIGHT_PARSER
2085  if (HAVE_ELEM_P(HAVE_ALPHA))
2086  parse_era(str, hash);
2087 #endif
2088 
2090  if (parse_eu(str, hash))
2091  goto ok;
2092  if (parse_us(str, hash))
2093  goto ok;
2094  }
2096  if (parse_iso(str, hash))
2097  goto ok;
2099  if (parse_jis(str, hash))
2100  goto ok;
2102  if (parse_vms(str, hash))
2103  goto ok;
2105  if (parse_sla(str, hash))
2106  goto ok;
2107 #ifdef TIGHT_PARSER
2109  if (parse_sla2(str, hash))
2110  goto ok;
2111  if (parse_sla3(str, hash))
2112  goto ok;
2113  }
2114 #endif
2116  if (parse_dot(str, hash))
2117  goto ok;
2118 #ifdef TIGHT_PARSER
2120  if (parse_dot2(str, hash))
2121  goto ok;
2122  if (parse_dot3(str, hash))
2123  goto ok;
2124  }
2125 #endif
2126  if (HAVE_ELEM_P(HAVE_DIGIT))
2127  if (parse_iso2(str, hash))
2128  goto ok;
2129  if (HAVE_ELEM_P(HAVE_DIGIT))
2130  if (parse_year(str, hash))
2131  goto ok;
2132  if (HAVE_ELEM_P(HAVE_ALPHA))
2133  if (parse_mon(str, hash))
2134  goto ok;
2135  if (HAVE_ELEM_P(HAVE_DIGIT))
2136  if (parse_mday(str, hash))
2137  goto ok;
2138  if (HAVE_ELEM_P(HAVE_DIGIT))
2139  if (parse_ddd(str, hash))
2140  goto ok;
2141 
2142 #ifdef TIGHT_PARSER
2143  if (parse_wday_only(str, hash))
2144  goto ok;
2145  if (parse_time_only(str, hash))
2146  goto ok;
2147  if (parse_wday_and_time(str, hash))
2148  goto ok;
2149 
2150  PARSER_ERROR; /* not found */
2151 #endif
2152 
2153  ok:
2154 #ifndef TIGHT_PARSER
2155  if (HAVE_ELEM_P(HAVE_ALPHA))
2156  parse_bc(str, hash);
2157  if (HAVE_ELEM_P(HAVE_DIGIT))
2158  parse_frag(str, hash);
2159 #endif
2160 
2161  {
2162  if (RTEST(ref_hash("_bc"))) {
2163  VALUE y;
2164 
2165  y = ref_hash("cwyear");
2166  if (!NIL_P(y)) {
2167  y = f_add(f_negate(y), INT2FIX(1));
2168  set_hash("cwyear", y);
2169  }
2170  y = ref_hash("year");
2171  if (!NIL_P(y)) {
2172  y = f_add(f_negate(y), INT2FIX(1));
2173  set_hash("year", y);
2174  }
2175  }
2176 
2177  if (RTEST(ref_hash("_comp"))) {
2178  VALUE y;
2179 
2180  y = ref_hash("cwyear");
2181  if (!NIL_P(y))
2182  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2183  if (f_ge_p(y, INT2FIX(69)))
2184  set_hash("cwyear", f_add(y, INT2FIX(1900)));
2185  else
2186  set_hash("cwyear", f_add(y, INT2FIX(2000)));
2187  }
2188  y = ref_hash("year");
2189  if (!NIL_P(y))
2190  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2191  if (f_ge_p(y, INT2FIX(69)))
2192  set_hash("year", f_add(y, INT2FIX(1900)));
2193  else
2194  set_hash("year", f_add(y, INT2FIX(2000)));
2195  }
2196  }
2197 
2198  }
2199 
2200  del_hash("_bc");
2201  del_hash("_comp");
2202 
2203  {
2204  VALUE zone = ref_hash("zone");
2205  if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
2206  set_hash("offset", date_zone_to_diff(zone));
2207  }
2208 
2209  rb_backref_set(backref);
2210 
2211  return hash;
2212 }
2213 
2214 static VALUE
2215 comp_year69(VALUE y)
2216 {
2217  if (f_ge_p(y, INT2FIX(69)))
2218  return f_add(y, INT2FIX(1900));
2219  return f_add(y, INT2FIX(2000));
2220 }
2221 
2222 static VALUE
2223 comp_year50(VALUE y)
2224 {
2225  if (f_ge_p(y, INT2FIX(50)))
2226  return f_add(y, INT2FIX(1900));
2227  return f_add(y, INT2FIX(2000));
2228 }
2229 
2230 static VALUE
2231 sec_fraction(VALUE f)
2232 {
2233  return rb_rational_new2(str2num(f),
2234  f_expt(INT2FIX(10),
2235  LONG2NUM(RSTRING_LEN(f))));
2236 }
2237 
2238 #define SNUM 14
2239 
2240 static int
2241 iso8601_ext_datetime_cb(VALUE m, VALUE hash)
2242 {
2243  VALUE s[SNUM + 1], y;
2244 
2245  {
2246  int i;
2247  s[0] = Qnil;
2248  for (i = 1; i <= SNUM; i++)
2249  s[i] = rb_reg_nth_match(i, m);
2250  }
2251 
2252  if (!NIL_P(s[3])) {
2253  set_hash("mday", str2num(s[3]));
2254  if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
2255  y = str2num(s[1]);
2256  if (RSTRING_LEN(s[1]) < 4)
2257  y = comp_year69(y);
2258  set_hash("year", y);
2259  }
2260  if (NIL_P(s[2])) {
2261  if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
2262  return 0;
2263  }
2264  else
2265  set_hash("mon", str2num(s[2]));
2266  }
2267  else if (!NIL_P(s[5])) {
2268  set_hash("yday", str2num(s[5]));
2269  if (!NIL_P(s[4])) {
2270  y = str2num(s[4]);
2271  if (RSTRING_LEN(s[4]) < 4)
2272  y = comp_year69(y);
2273  set_hash("year", y);
2274  }
2275  }
2276  else if (!NIL_P(s[8])) {
2277  set_hash("cweek", str2num(s[7]));
2278  set_hash("cwday", str2num(s[8]));
2279  if (!NIL_P(s[6])) {
2280  y = str2num(s[6]);
2281  if (RSTRING_LEN(s[6]) < 4)
2282  y = comp_year69(y);
2283  set_hash("cwyear", y);
2284  }
2285  }
2286  else if (!NIL_P(s[9])) {
2287  set_hash("cwday", str2num(s[9]));
2288  }
2289  if (!NIL_P(s[10])) {
2290  set_hash("hour", str2num(s[10]));
2291  set_hash("min", str2num(s[11]));
2292  if (!NIL_P(s[12]))
2293  set_hash("sec", str2num(s[12]));
2294  }
2295  if (!NIL_P(s[13])) {
2296  set_hash("sec_fraction", sec_fraction(s[13]));
2297  }
2298  if (!NIL_P(s[14])) {
2299  set_hash("zone", s[14]);
2300  set_hash("offset", date_zone_to_diff(s[14]));
2301  }
2302 
2303  return 1;
2304 }
2305 
2306 static int
2307 iso8601_ext_datetime(VALUE str, VALUE hash)
2308 {
2309  static const char pat_source[] =
2310  "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
2311  "([-+]?\\d{2,})?-(\\d{3})|"
2312  "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
2313  "-w-(\\d))"
2314  "(?:t"
2315  "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
2316  "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
2317  static VALUE pat = Qnil;
2318 
2319  REGCOMP_I(pat);
2320  MATCH(str, pat, iso8601_ext_datetime_cb);
2321 }
2322 
2323 #undef SNUM
2324 #define SNUM 17
2325 
2326 static int
2327 iso8601_bas_datetime_cb(VALUE m, VALUE hash)
2328 {
2329  VALUE s[SNUM + 1], y;
2330 
2331  {
2332  int i;
2333  s[0] = Qnil;
2334  for (i = 1; i <= SNUM; i++)
2335  s[i] = rb_reg_nth_match(i, m);
2336  }
2337 
2338  if (!NIL_P(s[3])) {
2339  set_hash("mday", str2num(s[3]));
2340  if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
2341  y = str2num(s[1]);
2342  if (RSTRING_LEN(s[1]) < 4)
2343  y = comp_year69(y);
2344  set_hash("year", y);
2345  }
2346  if (*RSTRING_PTR(s[2]) == '-') {
2347  if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
2348  return 0;
2349  }
2350  else
2351  set_hash("mon", str2num(s[2]));
2352  }
2353  else if (!NIL_P(s[5])) {
2354  set_hash("yday", str2num(s[5]));
2355  y = str2num(s[4]);
2356  if (RSTRING_LEN(s[4]) < 4)
2357  y = comp_year69(y);
2358  set_hash("year", y);
2359  }
2360  else if (!NIL_P(s[6])) {
2361  set_hash("yday", str2num(s[6]));
2362  }
2363  else if (!NIL_P(s[9])) {
2364  set_hash("cweek", str2num(s[8]));
2365  set_hash("cwday", str2num(s[9]));
2366  y = str2num(s[7]);
2367  if (RSTRING_LEN(s[7]) < 4)
2368  y = comp_year69(y);
2369  set_hash("cwyear", y);
2370  }
2371  else if (!NIL_P(s[11])) {
2372  set_hash("cweek", str2num(s[10]));
2373  set_hash("cwday", str2num(s[11]));
2374  }
2375  else if (!NIL_P(s[12])) {
2376  set_hash("cwday", str2num(s[12]));
2377  }
2378  if (!NIL_P(s[13])) {
2379  set_hash("hour", str2num(s[13]));
2380  set_hash("min", str2num(s[14]));
2381  if (!NIL_P(s[15]))
2382  set_hash("sec", str2num(s[15]));
2383  }
2384  if (!NIL_P(s[16])) {
2385  set_hash("sec_fraction", sec_fraction(s[16]));
2386  }
2387  if (!NIL_P(s[17])) {
2388  set_hash("zone", s[17]);
2389  set_hash("offset", date_zone_to_diff(s[17]));
2390  }
2391 
2392  return 1;
2393 }
2394 
2395 static int
2396 iso8601_bas_datetime(VALUE str, VALUE hash)
2397 {
2398  static const char pat_source[] =
2399  "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
2400  "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
2401  "-(\\d{3})|"
2402  "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
2403  "-w(\\d{2})(\\d)|"
2404  "-w-(\\d))"
2405  "(?:t?"
2406  "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
2407  "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
2408  static VALUE pat = Qnil;
2409 
2410  REGCOMP_I(pat);
2411  MATCH(str, pat, iso8601_bas_datetime_cb);
2412 }
2413 
2414 #undef SNUM
2415 #define SNUM 5
2416 
2417 static int
2418 iso8601_ext_time_cb(VALUE m, VALUE hash)
2419 {
2420  VALUE s[SNUM + 1];
2421 
2422  {
2423  int i;
2424  s[0] = Qnil;
2425  for (i = 1; i <= SNUM; i++)
2426  s[i] = rb_reg_nth_match(i, m);
2427  }
2428 
2429  set_hash("hour", str2num(s[1]));
2430  set_hash("min", str2num(s[2]));
2431  if (!NIL_P(s[3]))
2432  set_hash("sec", str2num(s[3]));
2433  if (!NIL_P(s[4]))
2434  set_hash("sec_fraction", sec_fraction(s[4]));
2435  if (!NIL_P(s[5])) {
2436  set_hash("zone", s[5]);
2437  set_hash("offset", date_zone_to_diff(s[5]));
2438  }
2439 
2440  return 1;
2441 }
2442 
2443 #define iso8601_bas_time_cb iso8601_ext_time_cb
2444 
2445 static int
2446 iso8601_ext_time(VALUE str, VALUE hash)
2447 {
2448  static const char pat_source[] =
2449  "\\A\\s*(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?"
2450  "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
2451  static VALUE pat = Qnil;
2452 
2453  REGCOMP_I(pat);
2454  MATCH(str, pat, iso8601_ext_time_cb);
2455 }
2456 
2457 static int
2458 iso8601_bas_time(VALUE str, VALUE hash)
2459 {
2460  static const char pat_source[] =
2461  "\\A\\s*(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?"
2462  "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
2463  static VALUE pat = Qnil;
2464 
2465  REGCOMP_I(pat);
2466  MATCH(str, pat, iso8601_bas_time_cb);
2467 }
2468 
2469 VALUE
2471 {
2472  VALUE backref, hash;
2473 
2474  backref = rb_backref_get();
2475  rb_match_busy(backref);
2476 
2477  hash = rb_hash_new();
2478 
2479  if (iso8601_ext_datetime(str, hash))
2480  goto ok;
2481  if (iso8601_bas_datetime(str, hash))
2482  goto ok;
2483  if (iso8601_ext_time(str, hash))
2484  goto ok;
2485  if (iso8601_bas_time(str, hash))
2486  goto ok;
2487 
2488  ok:
2489  rb_backref_set(backref);
2490 
2491  return hash;
2492 }
2493 
2494 #undef SNUM
2495 #define SNUM 8
2496 
2497 static int
2498 rfc3339_cb(VALUE m, VALUE hash)
2499 {
2500  VALUE s[SNUM + 1];
2501 
2502  {
2503  int i;
2504  s[0] = Qnil;
2505  for (i = 1; i <= SNUM; i++)
2506  s[i] = rb_reg_nth_match(i, m);
2507  }
2508 
2509  set_hash("year", str2num(s[1]));
2510  set_hash("mon", str2num(s[2]));
2511  set_hash("mday", str2num(s[3]));
2512  set_hash("hour", str2num(s[4]));
2513  set_hash("min", str2num(s[5]));
2514  set_hash("sec", str2num(s[6]));
2515  set_hash("zone", s[8]);
2516  set_hash("offset", date_zone_to_diff(s[8]));
2517  if (!NIL_P(s[7]))
2518  set_hash("sec_fraction", sec_fraction(s[7]));
2519 
2520  return 1;
2521 }
2522 
2523 static int
2524 rfc3339(VALUE str, VALUE hash)
2525 {
2526  static const char pat_source[] =
2527  "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
2528  "(?:t|\\s)"
2529  "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2530  "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
2531  static VALUE pat = Qnil;
2532 
2533  REGCOMP_I(pat);
2534  MATCH(str, pat, rfc3339_cb);
2535 }
2536 
2537 VALUE
2539 {
2540  VALUE backref, hash;
2541 
2542  backref = rb_backref_get();
2543  rb_match_busy(backref);
2544 
2545  hash = rb_hash_new();
2546  rfc3339(str, hash);
2547  rb_backref_set(backref);
2548  return hash;
2549 }
2550 
2551 #undef SNUM
2552 #define SNUM 8
2553 
2554 static int
2555 xmlschema_datetime_cb(VALUE m, VALUE hash)
2556 {
2557  VALUE s[SNUM + 1];
2558 
2559  {
2560  int i;
2561  s[0] = Qnil;
2562  for (i = 1; i <= SNUM; i++)
2563  s[i] = rb_reg_nth_match(i, m);
2564  }
2565 
2566  set_hash("year", str2num(s[1]));
2567  if (!NIL_P(s[2]))
2568  set_hash("mon", str2num(s[2]));
2569  if (!NIL_P(s[3]))
2570  set_hash("mday", str2num(s[3]));
2571  if (!NIL_P(s[4]))
2572  set_hash("hour", str2num(s[4]));
2573  if (!NIL_P(s[5]))
2574  set_hash("min", str2num(s[5]));
2575  if (!NIL_P(s[6]))
2576  set_hash("sec", str2num(s[6]));
2577  if (!NIL_P(s[7]))
2578  set_hash("sec_fraction", sec_fraction(s[7]));
2579  if (!NIL_P(s[8])) {
2580  set_hash("zone", s[8]);
2581  set_hash("offset", date_zone_to_diff(s[8]));
2582  }
2583 
2584  return 1;
2585 }
2586 
2587 static int
2588 xmlschema_datetime(VALUE str, VALUE hash)
2589 {
2590  static const char pat_source[] =
2591  "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
2592  "(?:t"
2593  "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
2594  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2595  static VALUE pat = Qnil;
2596 
2597  REGCOMP_I(pat);
2598  MATCH(str, pat, xmlschema_datetime_cb);
2599 }
2600 
2601 #undef SNUM
2602 #define SNUM 5
2603 
2604 static int
2605 xmlschema_time_cb(VALUE m, VALUE hash)
2606 {
2607  VALUE s[SNUM + 1];
2608 
2609  {
2610  int i;
2611  s[0] = Qnil;
2612  for (i = 1; i <= SNUM; i++)
2613  s[i] = rb_reg_nth_match(i, m);
2614  }
2615 
2616  set_hash("hour", str2num(s[1]));
2617  set_hash("min", str2num(s[2]));
2618  if (!NIL_P(s[3]))
2619  set_hash("sec", str2num(s[3]));
2620  if (!NIL_P(s[4]))
2621  set_hash("sec_fraction", sec_fraction(s[4]));
2622  if (!NIL_P(s[5])) {
2623  set_hash("zone", s[5]);
2624  set_hash("offset", date_zone_to_diff(s[5]));
2625  }
2626 
2627  return 1;
2628 }
2629 
2630 static int
2631 xmlschema_time(VALUE str, VALUE hash)
2632 {
2633  static const char pat_source[] =
2634  "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2635  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2636  static VALUE pat = Qnil;
2637 
2638  REGCOMP_I(pat);
2639  MATCH(str, pat, xmlschema_time_cb);
2640 }
2641 
2642 #undef SNUM
2643 #define SNUM 4
2644 
2645 static int
2646 xmlschema_trunc_cb(VALUE m, VALUE hash)
2647 {
2648  VALUE s[SNUM + 1];
2649 
2650  {
2651  int i;
2652  s[0] = Qnil;
2653  for (i = 1; i <= SNUM; i++)
2654  s[i] = rb_reg_nth_match(i, m);
2655  }
2656 
2657  if (!NIL_P(s[1]))
2658  set_hash("mon", str2num(s[1]));
2659  if (!NIL_P(s[2]))
2660  set_hash("mday", str2num(s[2]));
2661  if (!NIL_P(s[3]))
2662  set_hash("mday", str2num(s[3]));
2663  if (!NIL_P(s[4])) {
2664  set_hash("zone", s[4]);
2665  set_hash("offset", date_zone_to_diff(s[4]));
2666  }
2667 
2668  return 1;
2669 }
2670 
2671 static int
2672 xmlschema_trunc(VALUE str, VALUE hash)
2673 {
2674  static const char pat_source[] =
2675  "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
2676  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2677  static VALUE pat = Qnil;
2678 
2679  REGCOMP_I(pat);
2680  MATCH(str, pat, xmlschema_trunc_cb);
2681 }
2682 
2683 VALUE
2685 {
2686  VALUE backref, hash;
2687 
2688  backref = rb_backref_get();
2689  rb_match_busy(backref);
2690 
2691  hash = rb_hash_new();
2692 
2693  if (xmlschema_datetime(str, hash))
2694  goto ok;
2695  if (xmlschema_time(str, hash))
2696  goto ok;
2697  if (xmlschema_trunc(str, hash))
2698  goto ok;
2699 
2700  ok:
2701  rb_backref_set(backref);
2702 
2703  return hash;
2704 }
2705 
2706 #undef SNUM
2707 #define SNUM 8
2708 
2709 static int
2710 rfc2822_cb(VALUE m, VALUE hash)
2711 {
2712  VALUE s[SNUM + 1], y;
2713 
2714  {
2715  int i;
2716  s[0] = Qnil;
2717  for (i = 1; i <= SNUM; i++)
2718  s[i] = rb_reg_nth_match(i, m);
2719  }
2720 
2721  if (!NIL_P(s[1])) {
2722  set_hash("wday", INT2FIX(day_num(s[1])));
2723  }
2724  set_hash("mday", str2num(s[2]));
2725  set_hash("mon", INT2FIX(mon_num(s[3])));
2726  y = str2num(s[4]);
2727  if (RSTRING_LEN(s[4]) < 4)
2728  y = comp_year50(y);
2729  set_hash("year", y);
2730  set_hash("hour", str2num(s[5]));
2731  set_hash("min", str2num(s[6]));
2732  if (!NIL_P(s[7]))
2733  set_hash("sec", str2num(s[7]));
2734  set_hash("zone", s[8]);
2735  set_hash("offset", date_zone_to_diff(s[8]));
2736 
2737  return 1;
2738 }
2739 
2740 static int
2741 rfc2822(VALUE str, VALUE hash)
2742 {
2743  static const char pat_source[] =
2744  "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
2745  "(\\d{1,2})\\s+"
2746  "(" ABBR_MONTHS ")\\s+"
2747  "(-?\\d{2,})\\s+"
2748  "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
2749  "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
2750  static VALUE pat = Qnil;
2751 
2752  REGCOMP_I(pat);
2753  MATCH(str, pat, rfc2822_cb);
2754 }
2755 
2756 VALUE
2758 {
2759  VALUE backref, hash;
2760 
2761  backref = rb_backref_get();
2762  rb_match_busy(backref);
2763 
2764  hash = rb_hash_new();
2765  rfc2822(str, hash);
2766  rb_backref_set(backref);
2767  return hash;
2768 }
2769 
2770 #undef SNUM
2771 #define SNUM 8
2772 
2773 static int
2774 httpdate_type1_cb(VALUE m, VALUE hash)
2775 {
2776  VALUE s[SNUM + 1];
2777 
2778  {
2779  int i;
2780  s[0] = Qnil;
2781  for (i = 1; i <= SNUM; i++)
2782  s[i] = rb_reg_nth_match(i, m);
2783  }
2784 
2785  set_hash("wday", INT2FIX(day_num(s[1])));
2786  set_hash("mday", str2num(s[2]));
2787  set_hash("mon", INT2FIX(mon_num(s[3])));
2788  set_hash("year", str2num(s[4]));
2789  set_hash("hour", str2num(s[5]));
2790  set_hash("min", str2num(s[6]));
2791  set_hash("sec", str2num(s[7]));
2792  set_hash("zone", s[8]);
2793  set_hash("offset", INT2FIX(0));
2794 
2795  return 1;
2796 }
2797 
2798 static int
2799 httpdate_type1(VALUE str, VALUE hash)
2800 {
2801  static const char pat_source[] =
2802  "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
2803  "(\\d{2})\\s+"
2804  "(" ABBR_MONTHS ")\\s+"
2805  "(-?\\d{4})\\s+"
2806  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2807  "(gmt)\\s*\\z";
2808  static VALUE pat = Qnil;
2809 
2810  REGCOMP_I(pat);
2811  MATCH(str, pat, httpdate_type1_cb);
2812 }
2813 
2814 #undef SNUM
2815 #define SNUM 8
2816 
2817 static int
2818 httpdate_type2_cb(VALUE m, VALUE hash)
2819 {
2820  VALUE s[SNUM + 1], y;
2821 
2822  {
2823  int i;
2824  s[0] = Qnil;
2825  for (i = 1; i <= SNUM; i++)
2826  s[i] = rb_reg_nth_match(i, m);
2827  }
2828 
2829  set_hash("wday", INT2FIX(day_num(s[1])));
2830  set_hash("mday", str2num(s[2]));
2831  set_hash("mon", INT2FIX(mon_num(s[3])));
2832  y = str2num(s[4]);
2833  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
2834  y = comp_year69(y);
2835  set_hash("year", y);
2836  set_hash("hour", str2num(s[5]));
2837  set_hash("min", str2num(s[6]));
2838  set_hash("sec", str2num(s[7]));
2839  set_hash("zone", s[8]);
2840  set_hash("offset", INT2FIX(0));
2841 
2842  return 1;
2843 }
2844 
2845 static int
2846 httpdate_type2(VALUE str, VALUE hash)
2847 {
2848  static const char pat_source[] =
2849  "\\A\\s*(" DAYS ")\\s*,\\s+"
2850  "(\\d{2})\\s*-\\s*"
2851  "(" ABBR_MONTHS ")\\s*-\\s*"
2852  "(\\d{2})\\s+"
2853  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2854  "(gmt)\\s*\\z";
2855  static VALUE pat = Qnil;
2856 
2857  REGCOMP_I(pat);
2858  MATCH(str, pat, httpdate_type2_cb);
2859 }
2860 
2861 #undef SNUM
2862 #define SNUM 7
2863 
2864 static int
2865 httpdate_type3_cb(VALUE m, VALUE hash)
2866 {
2867  VALUE s[SNUM + 1];
2868 
2869  {
2870  int i;
2871  s[0] = Qnil;
2872  for (i = 1; i <= SNUM; i++)
2873  s[i] = rb_reg_nth_match(i, m);
2874  }
2875 
2876  set_hash("wday", INT2FIX(day_num(s[1])));
2877  set_hash("mon", INT2FIX(mon_num(s[2])));
2878  set_hash("mday", str2num(s[3]));
2879  set_hash("hour", str2num(s[4]));
2880  set_hash("min", str2num(s[5]));
2881  set_hash("sec", str2num(s[6]));
2882  set_hash("year", str2num(s[7]));
2883 
2884  return 1;
2885 }
2886 
2887 static int
2888 httpdate_type3(VALUE str, VALUE hash)
2889 {
2890  static const char pat_source[] =
2891  "\\A\\s*(" ABBR_DAYS ")\\s+"
2892  "(" ABBR_MONTHS ")\\s+"
2893  "(\\d{1,2})\\s+"
2894  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2895  "(\\d{4})\\s*\\z";
2896  static VALUE pat = Qnil;
2897 
2898  REGCOMP_I(pat);
2899  MATCH(str, pat, httpdate_type3_cb);
2900 }
2901 
2902 VALUE
2904 {
2905  VALUE backref, hash;
2906 
2907  backref = rb_backref_get();
2908  rb_match_busy(backref);
2909 
2910  hash = rb_hash_new();
2911 
2912  if (httpdate_type1(str, hash))
2913  goto ok;
2914  if (httpdate_type2(str, hash))
2915  goto ok;
2916  if (httpdate_type3(str, hash))
2917  goto ok;
2918 
2919  ok:
2920  rb_backref_set(backref);
2921 
2922  return hash;
2923 }
2924 
2925 #undef SNUM
2926 #define SNUM 9
2927 
2928 static int
2929 jisx0301_cb(VALUE m, VALUE hash)
2930 {
2931  VALUE s[SNUM + 1];
2932  int ep;
2933 
2934  {
2935  int i;
2936  s[0] = Qnil;
2937  for (i = 1; i <= SNUM; i++)
2938  s[i] = rb_reg_nth_match(i, m);
2939  }
2940 
2941  ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
2942  set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
2943  set_hash("mon", str2num(s[3]));
2944  set_hash("mday", str2num(s[4]));
2945  if (!NIL_P(s[5])) {
2946  set_hash("hour", str2num(s[5]));
2947  if (!NIL_P(s[6]))
2948  set_hash("min", str2num(s[6]));
2949  if (!NIL_P(s[7]))
2950  set_hash("sec", str2num(s[7]));
2951  }
2952  if (!NIL_P(s[8]))
2953  set_hash("sec_fraction", sec_fraction(s[8]));
2954  if (!NIL_P(s[9])) {
2955  set_hash("zone", s[9]);
2956  set_hash("offset", date_zone_to_diff(s[9]));
2957  }
2958 
2959  return 1;
2960 }
2961 
2962 static int
2963 jisx0301(VALUE str, VALUE hash)
2964 {
2965  static const char pat_source[] =
2966  "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
2967  "(?:t"
2968  "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
2969  "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
2970  static VALUE pat = Qnil;
2971 
2972  REGCOMP_I(pat);
2973  MATCH(str, pat, jisx0301_cb);
2974 }
2975 
2976 VALUE
2978 {
2979  VALUE backref, hash;
2980 
2981  backref = rb_backref_get();
2982  rb_match_busy(backref);
2983 
2984  hash = rb_hash_new();
2985  if (jisx0301(str, hash))
2986  goto ok;
2987  hash = date__iso8601(str);
2988 
2989  ok:
2990  rb_backref_set(backref);
2991  return hash;
2992 }
2993 
2994 /*
2995 Local variables:
2996 c-file-style: "ruby"
2997 End:
2998 */
#define f_begin(o, i)
Definition: date_parse.c:36
#define rb_rational_new2(x, y)
Definition: intern.h:167
#define ref_hash(k)
Definition: date_parse.c:44
size_t strlen(const char *)
void rb_backref_set(VALUE)
Definition: vm.c:1235
#define NUM2INT(x)
Definition: ruby.h:684
#define f_expt(x, y)
Definition: date_parse.c:24
#define f_to_s(x)
Definition: date_parse.c:31
#define Qtrue
Definition: ruby.h:437
const int id
Definition: nkf.c:209
#define sizeof_array(o)
Definition: date_parse.c:15
#define asp_string()
Definition: date_parse.c:61
#define f_match(r, s)
Definition: date_parse.c:33
#define HAVE_DIGIT
Definition: date_parse.c:2015
#define set_hash(k, v)
Definition: date_parse.c:43
VALUE rb_backref_get(void)
Definition: vm.c:1229
#define f_end(o, i)
Definition: date_parse.c:37
#define RB_GC_GUARD(v)
Definition: ruby.h:552
RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Definition: util.c:84
#define HAVE_DASH
Definition: date_parse.c:2016
#define REGCOMP_I(pat)
Definition: date_parse.c:272
#define ABBR_DAYS
Definition: date_parse.c:235
#define strncasecmp
Definition: win32.h:192
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define SUBS(s, p, c)
Definition: date_parse.c:316
VALUE date__xmlschema(VALUE str)
Definition: date_parse.c:2684
#define ABBR_MONTHS
Definition: date_parse.c:236
#define DAYS
Definition: date_parse.c:233
#define STRTOUL(str, endptr, base)
Definition: ruby.h:2162
VALUE date__parse(VALUE str, VALUE comp)
Definition: date_parse.c:2049
#define f_le_p(x, y)
Definition: date_parse.c:28
#define NIL_P(v)
Definition: ruby.h:451
#define f_ge_p(x, y)
Definition: date_parse.c:29
#define f_negate(x)
Definition: date_parse.c:17
VALUE date_zone_to_diff(VALUE str)
Definition: date_parse.c:353
#define MATCH(s, p, c)
Definition: date_parse.c:274
int offset
Definition: zonetab.h:36
VALUE date__rfc2822(VALUE str)
Definition: date_parse.c:2757
VALUE date__jisx0301(VALUE str)
Definition: date_parse.c:2977
#define Qfalse
Definition: ruby.h:436
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1657
VALUE rb_rational_new(VALUE, VALUE)
Definition: rational.c:1973
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:6227
#define HAVE_ELEM_P(x)
Definition: date_parse.c:2042
#define rb_str_new2
Definition: intern.h:835
#define HAVE_DOT
Definition: date_parse.c:2017
#define ALLOCV_END(v)
Definition: ruby.h:1658
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:3942
#define RSTRING_LEN(str)
Definition: ruby.h:971
VALUE rb_reg_new(const char *, long, int)
Definition: re.c:2913
#define RUBY_EXTERN
Definition: missing.h:77
#define f_add(x, y)
Definition: date_parse.c:18
VALUE rb_hash_new(void)
Definition: hash.c:424
#define HAVE_SLASH
Definition: date_parse.c:2018
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
#define HAVE_ALPHA
Definition: date_parse.c:2014
#define Qnil
Definition: ruby.h:438
#define cstr2num(s)
Definition: date_parse.c:47
unsigned long VALUE
Definition: ruby.h:85
char * strchr(char *, char)
void rb_match_busy(VALUE)
Definition: re.c:1252
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
#define LONG2NUM(x)
Definition: ruby.h:1573
register unsigned int len
Definition: zonetab.h:51
#define iso8601_bas_time_cb
Definition: date_parse.c:2443
#define RSTRING_PTR(str)
Definition: ruby.h:975
#define f
#define INT2FIX(i)
Definition: ruby.h:232
#define SNUM
Definition: date_parse.c:2926
#define str2num(s)
Definition: date_parse.c:48
#define f_gsub_bang(s, r, x)
Definition: date_parse.c:41
VALUE date__httpdate(VALUE str)
Definition: date_parse.c:2903
#define f_aset2(o, i, j, v)
Definition: date_parse.c:39
#define RTEST(v)
Definition: ruby.h:450
#define T_STRING
Definition: ruby.h:496
#define FPT
Definition: vsnprintf.c:537
#define del_hash(k)
Definition: date_parse.c:45
Definition: zonetab.h:34
VALUE date__rfc3339(VALUE str)
Definition: date_parse.c:2538
#define REGCOMP_0(pat)
Definition: date_parse.c:271
#define issign(c)
Definition: date_parse.c:60
const struct zone * zonetab(str, len) register const char *str
#define bp()
Definition: vm_debug.h:25
VALUE date__iso8601(VALUE str)
Definition: date_parse.c:2470
#define NUM2LONG(x)
Definition: ruby.h:648
VALUE rb_reg_nth_match(int, VALUE)
Definition: re.c:1679
#define DECDIGIT
Definition: date_parse.c:69
VALUE rb_str_new(const char *, long)
Definition: string.c:737