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