diff --git a/ChangeLog b/ChangeLog index 8a09ecc265..c977f4276b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,71 @@ +Sun Apr 9 20:49:19 2000 Dave Thomas + + * parse.y (str_extend): Allow class variables to be expanded. + +Fri Apr 7 02:03:54 2000 Yukihiro Matsumoto + + * error.c (rb_sys_fail): escape non-printable characters. + +Thu Apr 6 20:10:47 2000 Katsuyuki Komatsu + + * ext/extmk.rb.in (create_makefile): BeOS --program-suffix support. + * lib/mkmf.rb (create_makefile): ditto. + +Thu Apr 6 09:55:26 2000 Katsuyuki Komatsu + + * error.c (rb_sys_fail): need rb_exc_new2() call on BeOS. + +Mon Apr 3 17:22:27 2000 Yukihiro Matsumoto + + * io.c (rb_io_reopen): support tempfile. + + * eval.c (catch_i): should supply argument. + +Sat Apr 1 22:50:28 2000 Yukihiro Matsumoto + + * marshal.c (r_object): wrong symbol restoration. + +Sat Apr 1 21:30:53 2000 WATANABE Hirofumi + + * io.c(rb_io_printf, rb_f_printf): should use rb_io_write. + +Sat Apr 1 00:16:05 2000 Yukihiro Matsumoto + + * gc.c (rb_gc_call_finalizer_at_exit): should be clear flags + before calling finalizers. + + * eval.c (specific_eval): can be called without SecurityError, if + $SAFE >= 4. + + * object.c (sym_inspect): inspect gives ":sym", to_s gives "sym". + +Fri Mar 31 08:56:55 2000 Yukihiro Matsumoto + + * parse.y (yylex): + +Thu Mar 30 12:19:44 2000 Katsuyuki Komatsu + + * enum.c (enum_find): rb_eval_cmd() should be called with array. + +Tue Mar 28 13:57:05 2000 Clemens Hintze + + * ext/dbm/dbm.c (fdbm_invert): should return new hash. + + * ext/gdbm/gdbm.c (fgdbm_invert): ditto. + +Sat Mar 25 23:21:10 2000 Yukihiro Matsumoto + + * marshal.c (w_object): symbols should be converted to ID before + dumping out. + +Fri Mar 24 18:26:51 2000 Yukihiro Matsumoto + + * file.c (test_check): should have checked exact number of arguments. + +Fri Mar 24 21:02:11 2000 Koji Arai + + * signal.c (trap): should treat some symbols as the signal. + Thu Mar 23 02:26:14 2000 Yukihiro Matsumoto * io.c (rb_io_fptr_finalize): fptr may be null. @@ -46,7 +114,7 @@ Sat Mar 18 12:36:09 2000 Nobuyoshi Nakada Sat Mar 18 11:25:10 2000 Yukihiro Matsumoto * parse.y (rescue): allows `rescue Error in foo'. experimental. - which is better this or preparing alias `exception' for `$!'. + which is better this or preparing alias `exception' for `$!'? Fri Mar 17 15:02:45 2000 Yukihiro Matsumoto @@ -205,7 +273,7 @@ Sun Mar 5 18:49:06 2000 Nakada.Nobuyoshi Tue Feb 29 01:08:26 2000 Yukihiro Matsumoto * range.c (range_initialize): initialization done in `initialize'; - `initialize; should not be called more than once. + `initialize' should not be called more than once. * object.c (Init_Object): default `initialize' should take zero argument. @@ -214,7 +282,7 @@ Tue Feb 29 01:08:26 2000 Yukihiro Matsumoto Sat Feb 26 22:39:31 2000 EGUCHI Osamu - * Fix String#* with huge string. + * string.c (rb_str_times): fix String#* with huge string. Sat Feb 26 00:14:59 2000 Yukihiro Matsumoto diff --git a/MANIFEST b/MANIFEST index dcd932a22e..89968edf9e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -76,7 +76,6 @@ variable.c version.c version.h beos/GNUmakefile.in -beos/ruby.def.in cygwin/GNUmakefile.in ext/Setup ext/Setup.dj @@ -90,6 +89,8 @@ lib/Env.rb lib/README lib/base64.rb lib/cgi.rb +lib/cgi/session.rb +lib/cgi-lib.rb lib/complex.rb lib/date.rb lib/date2.rb @@ -125,11 +126,9 @@ lib/matrix.rb lib/mkmf.rb lib/monitor.rb lib/mutex_m.rb -lib/net/http.rb lib/net/ftp.rb -lib/net/http.rb lib/net/pop.rb -lib/net/session.rb +lib/net/protocol.rb lib/net/smtp.rb lib/observer.rb lib/open3.rb @@ -223,7 +222,6 @@ sample/rename.rb sample/rcs.awk sample/rcs.dat sample/rcs.rb -sample/rd2html.rb sample/regx.rb sample/sieve.rb sample/svr.rb diff --git a/ToDo b/ToDo index 3bdc5ab991..9e49c4ba9e 100644 --- a/ToDo +++ b/ToDo @@ -35,11 +35,12 @@ Hacking Interpreter - all object made freezable * non-blocking open (e.g. for named pipe) for thread * avoid blocking with gethostbyname/gethostbyaddr (use fork ???) -* objectify interpreters +* objectify interpreters ??? * remove rb_eval() recursions * syntax tree -> bytecode ??? * scrambled script, or script filter * setuid ruby +* performance tune for in-block (dynamic) local variables. Standard Libraries @@ -61,7 +62,7 @@ Standard Libraries - Struct::new([name,]member,...) - IO#reopen accepts path as well - Kernel#scan -- call initialize for builtin class too (not yet: Regexp, etc) +- call initialize for builtin classes too (not yet: Regexp, Class, Module) - performance tune for String's non-bang methods. * String#scanf(?) * Object#fmt(?) diff --git a/array.c b/array.c index f8c2b2e030..f4c3a33752 100644 --- a/array.c +++ b/array.c @@ -728,8 +728,8 @@ rb_ary_join(ary, sep) default: tmp = rb_obj_as_string(tmp); } - if (!NIL_P(sep)) rb_str_concat(result, sep); - rb_str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len); + if (!NIL_P(sep)) rb_str_append(result, sep); + rb_str_append(result, tmp); if (OBJ_TAINTED(tmp)) taint = 1; } @@ -841,8 +841,8 @@ inspect_ary(ary) for (i=0; ilen; i++) { s = rb_inspect(RARRAY(ary)->ptr[i]); tainted = OBJ_TAINTED(s); - if (i > 0) rb_str_cat(str, ", ", 2); - rb_str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len); + if (i > 0) rb_str_cat2(str, ", "); + rb_str_append(str, s); } rb_str_cat(str, "]", 1); diff --git a/enum.c b/enum.c index 8d842bbd76..f79719f56b 100644 --- a/enum.c +++ b/enum.c @@ -88,7 +88,7 @@ enum_find(argc, argv, obj) return memo->u1.value; } if (!NIL_P(if_none)) { - rb_eval_cmd(if_none, Qnil); + rb_eval_cmd(if_none, rb_ary_new2(0)); } rb_gc_force_recycle((VALUE)memo); return Qnil; diff --git a/error.c b/error.c index ecfc7185fe..76f41a4fe1 100644 --- a/error.c +++ b/error.c @@ -344,9 +344,9 @@ exc_inspect(exc) str = rb_str_new2("#<"); klass = rb_class_path(klass); - rb_str_concat(str, klass); + rb_str_append(str, klass); rb_str_cat(str, ": ", 2); - rb_str_concat(str, exc); + rb_str_append(str, exc); rb_str_cat(str, ">", 1); return str; @@ -631,8 +631,10 @@ rb_sys_fail(mesg) err = strerror(errno); if (mesg) { - buf = ALLOCA_N(char, strlen(err)+strlen(mesg)+4); - sprintf(buf, "%s - %s", err, mesg); + volatile VALUE tmp = rb_str_inspect(rb_str_new2(mesg)); + + buf = ALLOCA_N(char, strlen(err)+RSTRING(tmp)->len+4); + sprintf(buf, "%s - %s", err, RSTRING(tmp)->ptr); } else { buf = ALLOCA_N(char, strlen(err)+1); @@ -658,8 +660,8 @@ rb_sys_fail(mesg) else { ee = syserr_list[n]; } - ee = rb_exc_new2(ee, buf); #endif + ee = rb_exc_new2(ee, buf); rb_iv_set(ee, "errno", INT2FIX(n)); rb_exc_raise(ee); } diff --git a/eval.c b/eval.c index b3a86d1dbe..4cd3d7bf5d 100644 --- a/eval.c +++ b/eval.c @@ -2686,8 +2686,8 @@ rb_eval(self, node) str2 = rb_obj_as_string(str2); break; } - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); - if (OBJ_TAINTED(str2)) OBJ_TAINT(str); + rb_str_append(str, str2); + OBJ_INFECT(str, str2); } list = list->nd_next; } @@ -4524,8 +4524,8 @@ eval(self, src, scope, file, line) if (strcmp(file, "(eval)") == 0) { if (ruby_sourceline > 1) { err = RARRAY(errat)->ptr[0]; - rb_str_cat(err, ": ", 2); - rb_str_concat(err, ruby_errinfo); + rb_str_cat2(err, ": "); + rb_str_append(err, ruby_errinfo); } else { err = rb_str_dup(ruby_errinfo); @@ -4560,7 +4560,7 @@ rb_f_eval(argc, argv, self) line = NUM2INT(vline); } - if (ruby_safe_level >= 3) { + if (ruby_safe_level >= 4) { Check_Type(src, T_STRING); } else { @@ -4697,7 +4697,12 @@ specific_eval(argc, argv, klass, self) int iter = rb_iterator_p(); if (argc > 0) { - Check_SafeStr(argv[0]); + if (ruby_safe_level >= 4) { + Check_Type(argv[0], T_STRING); + } + else { + Check_SafeStr(argv[0]); + } if (argc > 3) { rb_raise(rb_eArgError, "wrong # of arguments: %s(src) or %s{..}", rb_id2name(ruby_frame->last_func), @@ -5708,7 +5713,7 @@ proc_set_safe_level(data) } static VALUE -proc_s_new(klass) +proc_new(klass) VALUE klass; { volatile VALUE proc; @@ -5743,10 +5748,22 @@ proc_s_new(klass) return proc; } +static VALUE +proc_s_new(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; +{ + VALUE proc = proc_new(klass); + + rb_obj_call_init(proc, argc, argv); + return proc; +} + VALUE rb_f_lambda() { - return proc_s_new(rb_cProc); + return proc_new(rb_cProc); } static int @@ -5763,6 +5780,21 @@ blk_orphan(data) return 0; } +static VALUE +callargs(args) + VALUE args; +{ + switch (RARRAY(args)->len) { + case 0: + return Qnil; + break; + case 1: + return RARRAY(args)->ptr[0]; + default: + return args; + } +} + static VALUE proc_call(proc, args) VALUE proc, args; /* OK */ @@ -5786,14 +5818,7 @@ proc_call(proc, args) ruby_frame->iter = ITER_CUR; if (TYPE(args) == T_ARRAY) { - switch (RARRAY(args)->len) { - case 0: - args = Qnil; - break; - case 1: - args = RARRAY(args)->ptr[0]; - break; - } + args = callargs(args); } if (orphan) {/* orphan procedure */ @@ -6087,14 +6112,14 @@ method_inspect(method) Data_Get_Struct(method, struct METHOD, data); str = rb_str_new2("#<"); s = rb_class2name(CLASS_OF(method)); - rb_str_cat(str, s, strlen(s)); - rb_str_cat(str, ": ", 2); + rb_str_cat2(str, s); + rb_str_cat2(str, ": "); s = rb_class2name(data->oklass); - rb_str_cat(str, s, strlen(s)); - rb_str_cat(str, "#", 1); + rb_str_cat2(str, s); + rb_str_cat2(str, "#"); s = rb_id2name(data->oid); - rb_str_cat(str, s, strlen(s)); - rb_str_cat(str, ">", 1); + rb_str_cat2(str, s); + rb_str_cat2(str, ">"); return str; } @@ -6138,7 +6163,7 @@ Init_Proc() rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError); rb_cProc = rb_define_class("Proc", rb_cObject); - rb_define_singleton_method(rb_cProc, "new", proc_s_new, 0); + rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1); rb_define_method(rb_cProc, "call", proc_call, -2); rb_define_method(rb_cProc, "arity", proc_arity, 0); @@ -6333,6 +6358,10 @@ thread_free(th) if (th->stk_ptr) free(th->stk_ptr); th->stk_ptr = 0; if (th->locals) st_free_table(th->locals); + if (th->status != THREAD_KILLED) { + th->prev->next = th->next; + th->next->prev = th->prev; + } if (th != main_thread) free(th); } @@ -7270,12 +7299,11 @@ rb_thread_stop_timer() #endif static VALUE -rb_thread_create_0(fn, arg, klass) +rb_thread_start_0(fn, arg, th) VALUE (*fn)(); void *arg; - VALUE klass; + thread_t th; { - thread_t th = rb_thread_alloc(klass); volatile VALUE thread = th->thread; enum thread_status status; int state; @@ -7339,7 +7367,7 @@ rb_thread_create(fn, arg) VALUE (*fn)(); void *arg; { - return rb_thread_create_0(fn, arg, rb_cThread); + return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread)); } int @@ -7354,7 +7382,37 @@ rb_thread_yield(arg, th) thread_t th; { scope_dup(ruby_block->scope); - return rb_yield_0(arg, 0, 0, Qfalse); + return rb_yield_0(callargs(arg), 0, 0, Qfalse); +} + +static VALUE +rb_thread_s_new(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; +{ + thread_t th = rb_thread_alloc(klass); + volatile VALUE *pos; + + THREAD_SAVE_CONTEXT(th); + pos = th->stk_pos; + rb_obj_call_init(th->thread, argc, argv); + if (th->stk_pos == pos) { + rb_raise(rb_eThreadError, "uninitialized thread - check `initialize' of %s", + rb_class2name(klass)); + } + + return th->thread; +} + +static VALUE +rb_thread_initialize(thread, args) + VALUE thread, args; +{ + if (!rb_iterator_p()) { + rb_raise(rb_eThreadError, "must be called as iterator"); + } + return rb_thread_start_0(rb_thread_yield, args, rb_thread_check(thread)); } static VALUE @@ -7364,7 +7422,7 @@ rb_thread_start(klass, args) if (!rb_iterator_p()) { rb_raise(rb_eThreadError, "must be called as iterator"); } - return rb_thread_create_0(rb_thread_yield, args, klass); + return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass)); } static VALUE @@ -7743,7 +7801,9 @@ struct thgroup { }; static VALUE -thgroup_s_new(klass) +thgroup_s_new(argc, argv, klass) + int argc; + VALUE *argv; VALUE klass; { VALUE group; @@ -7753,6 +7813,7 @@ thgroup_s_new(klass) group = Data_Make_Struct(klass, struct thgroup, 0, free, data); data->gid = serial++; + rb_obj_call_init(group, argc, argv); return group; } @@ -7800,7 +7861,8 @@ Init_Thread() rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError); rb_cThread = rb_define_class("Thread", rb_cObject); - rb_define_singleton_method(rb_cThread, "new", rb_thread_start, -2); + rb_define_singleton_method(rb_cThread, "new", rb_thread_s_new, -1); + rb_define_method(rb_cThread, "initialize", rb_thread_initialize, -2); rb_define_singleton_method(rb_cThread, "start", rb_thread_start, -2); rb_define_singleton_method(rb_cThread, "fork", rb_thread_start, -2); @@ -7851,10 +7913,10 @@ Init_Thread() rb_define_global_function("callcc", rb_callcc, 0); cThGroup = rb_define_class("ThreadGroup", rb_cObject); - rb_define_singleton_method(cThGroup, "new", thgroup_s_new, 0); + rb_define_singleton_method(cThGroup, "new", thgroup_s_new, -1); rb_define_method(cThGroup, "list", thgroup_list, 0); rb_define_method(cThGroup, "add", thgroup_add, 1); - rb_define_const(cThGroup, "Default", thgroup_s_new(cThGroup)); + rb_define_const(cThGroup, "Default", thgroup_s_new(0, 0, cThGroup)); } static VALUE @@ -7884,7 +7946,7 @@ static VALUE catch_i(tag) ID tag; { - return rb_funcall(Qnil, rb_intern("catch"), 0, INT2FIX(tag)); + return rb_funcall(Qnil, rb_intern("catch"), 1, ID2SYM(tag)); } VALUE @@ -7937,7 +7999,7 @@ rb_throw(tag, val) VALUE argv[2]; ID t = rb_intern(tag); - argv[0] = INT2FIX(t); + argv[0] = ID2SYM(t); argv[1] = val; rb_f_throw(2, argv); } diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index 5377b4b6e3..66b41d03c1 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -262,7 +262,7 @@ fdbm_invert(obj) valstr = rb_tainted_str_new(val.dptr, val.dsize); rb_hash_aset(hash, valstr, keystr); } - return obj; + return hash; } static VALUE diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index cae02d576f..4336fdb51f 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -329,8 +329,8 @@ def create_makefile(target) $DLDFLAGS = '@DLDFLAGS@' - if RUBY_PLATFORM =~ /beos/ - $libs = $libs + " -lruby" + if RUBY_PLATFORM =~ /beos/ and not $static + $libs = $libs + " @LIBRUBYARG@" $DLDFLAGS = $DLDFLAGS + " -L" + $topdir end diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c index 3bf9669543..3c1ef88adf 100644 --- a/ext/gdbm/gdbm.c +++ b/ext/gdbm/gdbm.c @@ -260,7 +260,7 @@ fgdbm_invert(obj) valstr = rb_tainted_str_new(val.dptr, val.dsize); rb_hash_aset(hash, valstr, keystr); } - return obj; + return hash; } static VALUE diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb index 9e38db5032..2dea68980c 100644 --- a/ext/tk/lib/tktext.rb +++ b/ext/tk/lib/tktext.rb @@ -427,6 +427,98 @@ class TkTextas.free.flag = 0; run_final((VALUE)p); + } p++; } } diff --git a/hash.c b/hash.c index 7d8668b0c3..a19e298328 100644 --- a/hash.c +++ b/hash.c @@ -639,14 +639,14 @@ inspect_i(key, value, str) if (key == Qundef) return ST_CONTINUE; if (RSTRING(str)->len > 1) { - rb_str_cat(str, ", ", 2); + rb_str_cat2(str, ", "); } str2 = rb_inspect(key); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); + rb_str_append(str, str2); OBJ_INFECT(str, str2); - rb_str_cat(str, "=>", 2); + rb_str_cat2(str, "=>"); str2 = rb_inspect(value); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); + rb_str_append(str, str2); OBJ_INFECT(str, str2); return ST_CONTINUE; @@ -660,7 +660,7 @@ inspect_hash(hash) str = rb_str_new2("{"); st_foreach(RHASH(hash)->tbl, inspect_i, str); - rb_str_cat(str, "}", 1); + rb_str_cat2(str, "}"); OBJ_INFECT(str, hash); return str; diff --git a/intern.h b/intern.h index 56b30a9d26..3c53601317 100644 --- a/intern.h +++ b/intern.h @@ -286,6 +286,8 @@ void rb_str_modify _((VALUE)); VALUE rb_str_freeze _((VALUE)); VALUE rb_str_resize _((VALUE, long)); VALUE rb_str_cat _((VALUE, const char*, long)); +VALUE rb_str_cat2 _((VALUE, const char*)); +VALUE rb_str_append _((VALUE, VALUE)); VALUE rb_str_concat _((VALUE, VALUE)); int rb_str_hash _((VALUE)); int rb_str_cmp _((VALUE, VALUE)); diff --git a/io.c b/io.c index 82b611805a..b249ef839e 100644 --- a/io.c +++ b/io.c @@ -1799,7 +1799,7 @@ rb_io_reopen(argc, argv, file) rb_secure(4); if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) { - if (TYPE(fname) == T_FILE) { /* fname must be IO */ + if (TYPE(fname) != T_STRING) { /* fname must be IO */ return io_reopen(file, fname); } } @@ -1895,7 +1895,7 @@ rb_io_printf(argc, argv, out) VALUE argv[]; VALUE out; { - io_write(out, rb_f_sprintf(argc, argv)); + rb_io_write(out, rb_f_sprintf(argc, argv)); return Qnil; } @@ -1915,7 +1915,7 @@ rb_f_printf(argc, argv) argv++; argc--; } - io_write(out, rb_f_sprintf(argc, argv)); + rb_io_write(out, rb_f_sprintf(argc, argv)); return Qnil; } @@ -2334,8 +2334,7 @@ next_argv() #if defined(MSDOS) || defined(__CYGWIN__) || defined(NT) ruby_add_suffix(str, ruby_inplace_mode); #else - rb_str_cat(str, ruby_inplace_mode, - strlen(ruby_inplace_mode)); + rb_str_cat2(str, ruby_inplace_mode); #endif #if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(NT) || defined(__human68k__) || defined(__EMX__) (void)fclose(fr); @@ -3063,7 +3062,7 @@ argf_read(argc, argv) } if (NIL_P(tmp) || RSTRING(tmp)->len == 0) return str; else if (NIL_P(str)) str = tmp; - else rb_str_cat(str, RSTRING(tmp)->ptr, RSTRING(tmp)->len); + else rb_str_append(str, tmp); if (argc == 0) { goto retry; } diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 5d905a83d7..6a16c54e60 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -327,7 +327,7 @@ def create_makefile(target) $DLDFLAGS = CONFIG["DLDFLAGS"] if RUBY_PLATFORM =~ /beos/ - $libs = $libs + " -lruby" + $libs = $libs + " " + CONFIG["LIBRUBYARG"] $DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib" end diff --git a/lib/observer.rb b/lib/observer.rb index a91c1e38c3..08e75f5125 100644 --- a/lib/observer.rb +++ b/lib/observer.rb @@ -4,20 +4,20 @@ module Observable def add_observer(observer) - @observer_peers = [] unless @observer_peers + @observer_peers = [] unless defined? @observer_peers unless defined? observer.update raise NameError, "observer needs to respond to `update'" end @observer_peers.push observer end def delete_observer(observer) - @observer_peers.delete observer if @observer_peers + @observer_peers.delete observer if defined? @observer_peers end def delete_observers - @observer_peers.clear if @observer_peers + @observer_peers.clear if defined? @observer_peers end def count_observers - if @observer_peers + if defined? @observer_peers @observer_peers.size else 0 @@ -27,11 +27,15 @@ module Observable @observer_state = state end def changed? - @observer_state + if defined? @observer_state and @observer_state + true + else + false + end end def notify_observers(*arg) - if @observer_state - if @observer_peers + if defined? @observer_state and @observer_state + if defined? @observer_peers for i in @observer_peers.dup i.update(*arg) end diff --git a/lib/parsedate.rb b/lib/parsedate.rb index 59a8b4f3b4..7f83888f52 100644 --- a/lib/parsedate.rb +++ b/lib/parsedate.rb @@ -1,589 +1,162 @@ -# parsedate2.ry: Written by Tadayoshi Funaba 1999, 2000 -# $Id: parsedate2.ry,v 1.5 2000/03/20 16:23:46 tadf Exp $ -## Generated by rbison version 0.0.5. +# parsedate3.rb: Written by Tadayoshi Funaba 2000 +# $Id: parsedate3.rb,v 1.2 2000/04/01 03:16:56 tadf Exp $ -class ParseDatePar +module ParseDate - class ParseError < StandardError ; end - class LexError < StandardError ; end - NULL = nil - - attr :yydebug, true - - DAY = 257 - DIGITS = 258 - MON = 259 - LETTERS = 260 - MERID = 261 - - ## Parser declarations begin - ## Parser declarations end - - YYFINAL = 84 - YYFLAG = -32768 - YYNTBASE = 14 - YYTRANSLATE = [ 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 13, 8, 9, 10, 11, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 12, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, - 7 - ] - YYPRHS = [ 0, - 0, 1, 3, 6, 8, 12, 14, 20, 26, 32, - 34, 38, 40, 44, 45, 48, 50, 51, 53, 55, - 57, 60, 63, 65, 67, 69, 71, 73, 80, 88, - 94, 98, 104, 108, 115, 116, 119, 122, 123, 125, - 128, 129, 131, 132, 134, 136, 139, 142, 147, 149 - ] - YYRHS = [ -1, - 17, 0, 16, 15, 0, 19, 0, 19, 18, 22, - 0, 28, 0, 28, 18, 19, 18, 22, 0, 19, - 18, 28, 18, 22, 0, 19, 18, 22, 18, 28, - 0, 23, 0, 23, 18, 28, 0, 30, 0, 30, - 18, 32, 0, 0, 17, 18, 0, 3, 0, 0, - 8, 0, 20, 0, 21, 0, 4, 5, 0, 5, - 4, 0, 4, 0, 24, 0, 25, 0, 26, 0, - 27, 0, 4, 9, 4, 9, 4, 31, 0, 6, - 4, 10, 4, 10, 4, 31, 0, 4, 9, 5, - 9, 4, 0, 4, 11, 4, 0, 4, 11, 4, - 11, 4, 0, 4, 7, 34, 0, 4, 12, 4, - 29, 33, 34, 0, 0, 12, 4, 0, 4, 31, - 0, 0, 6, 0, 4, 34, 0, 0, 7, 0, - 0, 35, 0, 6, 0, 6, 6, 0, 36, 4, - 0, 36, 4, 12, 4, 0, 9, 0, 13, 0 - ] - YYRLINE = [ 0, - 14, 14, 14, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 28, 28, 30, 32, 32, 34, 34, - 36, 38, 40, 42, 42, 42, 42, 44, 58, 72, - 86, 91, 105, 109, 116, 116, 118, 141, 141, 143, - 156, 156, 158, 158, 160, 161, 166, 167, 170, 170 - ] - YYTNAME = [ "$","error","$undefined.","DAY","DIGITS", -"MON","LETTERS","MERID","','","'-'","'.'","'/'","':'","'+'","repr","dat","odaycom", -"day","ocom","woy","eu","us","year","wy","iso","jis","vms","sla","time","osec", -"ddd","otee","ttt","omerid","ozone","zone","sign", NULL - ] - YYR1 = [ 0, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 16, 16, 17, 18, 18, 19, 19, - 20, 21, 22, 23, 23, 23, 23, 24, 25, 26, - 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, - 33, 33, 34, 34, 35, 35, 35, 35, 36, 36 - ] - YYR2 = [ 0, - 0, 1, 2, 1, 3, 1, 5, 5, 5, 1, - 3, 1, 3, 0, 2, 1, 0, 1, 1, 1, - 2, 2, 1, 1, 1, 1, 1, 6, 7, 5, - 3, 5, 3, 6, 0, 2, 2, 0, 1, 2, - 0, 1, 0, 1, 1, 2, 2, 4, 1, 1 - ] - YYDEFACT = [ 14, - 16, 0, 17, 38, 0, 0, 3, 4, 19, 20, - 10, 24, 25, 26, 27, 17, 12, 18, 15, 21, - 39, 43, 0, 0, 0, 37, 22, 0, 0, 0, - 0, 0, 45, 49, 50, 33, 44, 0, 0, 0, - 31, 35, 0, 23, 5, 17, 0, 11, 0, 17, - 43, 13, 46, 47, 0, 0, 0, 0, 41, 0, - 0, 0, 0, 40, 0, 38, 30, 32, 36, 42, - 43, 0, 9, 23, 8, 7, 48, 28, 34, 38, - 29, 0, 0, 0 - ] - YYDEFGOTO = [ 82, - 7, 2, 3, 19, 8, 9, 10, 45, 11, 12, - 13, 14, 15, 16, 59, 17, 26, 52, 71, 36, - 37, 38 - ] - YYPACT = [ 10, --32768, 30, 6, 11, 37, 39,-32768, 23,-32768,-32768, - 23,-32768,-32768,-32768,-32768, 7, 23,-32768,-32768,-32768, --32768, 19, 25, 40, 41,-32768,-32768, 36, 43, 44, - 35, 45, 46,-32768,-32768,-32768,-32768, 47, 48, 49, - 42, 38, 50, 14, 23, 51, 14,-32768, 55, 51, - 19,-32768,-32768, 52, 57, 58, 59, 61, 60, 56, - 44, 64, 64,-32768, 65, 66,-32768,-32768,-32768,-32768, - 19, 67,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 66, --32768, 70, 73,-32768 - ] - YYPGOTO = [ -32768, --32768,-32768,-32768, -8, 24,-32768,-32768, -51,-32768,-32768, --32768,-32768,-32768, -28,-32768,-32768, -61,-32768,-32768, -47, --32768,-32768 - ] - YYLAST = 73 - YYTABLE = [ 29, - 46, 48, 30, 64, 78, -2, -6, 31, 32, -1, - 75, 76, 1, 18, 18, 20, 21, 22, 81, 23, - 22, 24, 25, 79, 33, 25, -17, 34, 39, 40, - 18, 35, 73, 4, 5, 6, 61, 62, 49, 5, - 27, 63, 28, 41, 42, 43, 44, 47, 51, 58, - 54, 53, 57, 60, 50, 0, 55, 56, 18, 20, - 66, 67, 68, 65, 69, 72, 70, 74, 77, 83, - 80, 21, 84 - ] - YYCHECK = [ 8, - 29, 30, 11, 51, 66, 0, 0, 16, 17, 0, - 62, 63, 3, 8, 8, 5, 6, 7, 80, 9, - 7, 11, 12, 71, 6, 12, 4, 9, 4, 5, - 8, 13, 61, 4, 5, 6, 45, 46, 4, 5, - 4, 50, 4, 4, 4, 10, 4, 4, 4, 12, - 4, 6, 11, 4, 31, -1, 9, 9, 8, 5, - 4, 4, 4, 12, 4, 10, 7, 4, 4, 0, - 4, 6, 0 - ] - YYEMPTY = -2 - YYEOF = 0 - YYTERROR = 1 - - def initialize - @yydebug = false - end - - def yyparse(lexer) - yyerrstatus = 0 - yychar = YYEMPTY - yystate = 0 - yyss = [] - yyvs = ["nil"] - yyval = 0 - jump = :YYNEWSTATE - - while true - - case jump - - when :YYNEWSTATE - if @yydebug - printf($stderr, "Entering state %d\n", yystate) - end - yyss.push(yystate) - jump = :YYBACKUP - next - - when :YYBACKUP - yyn = YYPACT[yystate] - if yyn == YYFLAG - jump = :YYDEFAULT - next - end - - ## get a lookahead token if we don't already have one - if yychar == YYEMPTY - if @yydebug - printf($stderr, "Reading a token: ") - end - begin - yychar, yylval = lexer.yylex - rescue LexError - raise ParseError, "lex error" - end - end - - ## if lookahead <= 0, end of input - if yychar <= 0 - yychar1 = 0 - yychar = YYEOF - if @yydebug - printf($stderr, "Now at end of input.\n") - end - else - yychar1 = yychar < 0 || yychar > 261 ? 37 : YYTRANSLATE[yychar] - if @yydebug - printf($stderr, "Next token is %d (%s,%s)\n", yychar, - YYTNAME[yychar1], yylval) - end - end - - ## see if we know what to do with this token in this state - yyn += yychar1 - if yyn < 0 || yyn > YYLAST || YYCHECK[yyn] != yychar1 - jump = :YYDEFAULT - next - end - - ## yyn is what to do for this token type in this state - ## negative -> reduce, - yyn is the rule number - ## positive -> shift, yyn is the new state - ## New state is final state, don't bother to shift, just - ## return success - ## 0, or most negative number -> error - yyn = YYTABLE[yyn] - if yyn < 0 - if yyn == YYFLAG - jump = :YYERRLAB - next - end - yyn = - yyn - jump = :YYREDUCE - next - elsif yyn == 0 - jump = :YYERRLAB - next - end - - if yyn == YYFINAL - return ## accept - end - - ## shift the lookahead token - if @yydebug - printf($stderr, "Shifting token %d (%s), ", yychar, - YYTNAME[yychar1]) - end - - ## discard the token being shifted unless it is eof - if yychar != YYEOF - yychar = YYEMPTY - end - yyvs.push(yylval) - - ## count tokens shifted since error; after, three turn off - ## error status - yyerrstatus -= 1 if yyerrstatus > 0 - - yystate = yyn - jump = :YYNEWSTATE - next - - when :YYDEFAULT - yyn = YYDEFACT[yystate] - if yyn == 0 - jump = :YYERRLAB - next - else - jump = :YYREDUCE - next - end - - ## do a reduction. yyn is the number of the rule to reduce with - when :YYREDUCE - yylen = YYR2[yyn] - if yylen > 0 - yyval = yyvs[yyvs.size - yylen] - end - - if @yydebug - printf($stderr, "Reducing via rule %d (line %d), ", yyn, - YYRLINE[yyn]) - i = YYPRHS[yyn] - while YYRHS[i] > 0 - printf($stderr, "%s ", YYTNAME[YYRHS[i]]) - i += 1 - end - printf($stderr, " -> %s\n", YYTNAME[YYR1[yyn]]) - end - - case yyn - when 16 - store(:wday, yyvs[-1].to_i) - when 21 - store(:mday, yyvs[-2].to_i); store(:mon, yyvs[-1]) - when 22 - store(:mon, yyvs[-2]); store(:mday, yyvs[-1].to_i) - when 23 - store(:year, yyvs[-1].to_i) - when 28 - - if yyvs[-1 + -1].size >= 4 - store(:mday, yyvs[-1 + -5].to_i) - store(:mon, yyvs[-1 + -3].to_i) - store(:year, yyvs[-1 + -1].to_i) - else - store(:year, yyvs[-1 + -5].to_i) - store(:mon, yyvs[-1 + -3].to_i) - store(:mday, yyvs[-1 + -1].to_i) - end - - when 29 - - e = { 'M'=>1867, - 'T'=>1911, - 'S'=>1925, - 'H'=>1988 - }[yyvs[-1 + -6]] - raise ParseError, 'YYERROR' unless e - store(:year, yyvs[-1 + -5].to_i + e) - store(:mon, yyvs[-1 + -3].to_i) - store(:mday, yyvs[-1 + -1].to_i) - - when 30 - - if yyvs[-1 + -4].size >= 4 - store(:year, yyvs[-1 + -4].to_i) - store(:mon, yyvs[-1 + -2]) - store(:mday, yyvs[-1 + 0].to_i) - else - store(:mday, yyvs[-1 + -4].to_i) - store(:mon, yyvs[-1 + -2]) - store(:year, yyvs[-1 + 0].to_i) - end - - when 31 - - store(:mon, yyvs[-1 + -2].to_i) - store(:mday, yyvs[-1 + 0].to_i) - - when 32 - - if yyvs[-1 + -4].size >= 4 - store(:year, yyvs[-1 + -4].to_i) - store(:mon, yyvs[-1 + -2].to_i) - store(:mday, yyvs[-1 + 0].to_i) - else - store(:mon, yyvs[-1 + -4].to_i) - store(:mday, yyvs[-1 + -2].to_i) - store(:year, yyvs[-1 + 0].to_i) - end - - when 33 - - store(:hour, yyvs[-1 + -2].to_i + yyvs[-1 + -1]) - - when 34 - - store(:hour, yyvs[-1 + -5].to_i + yyvs[-1 + -1]) - store(:min, yyvs[-1 + -3].to_i) - - when 36 - store(:sec, yyvs[-1].to_i) - when 37 - - case yyvs[-1 + -1].size - when 4 - store(:mon, yyvs[-1 + -1][ 0, 2].to_i) - store(:mday, yyvs[-1 + -1][ 2, 2].to_i) - when 6 - store(:year, yyvs[-1 + -1][ 0, 2].to_i) - store(:mon, yyvs[-1 + -1][ 2, 2].to_i) - store(:mday, yyvs[-1 + -1][ 4, 2].to_i) - when 8, 10, 12, 14 - store(:year, yyvs[-1 + -1][ 0, 4].to_i) - store(:mon, yyvs[-1 + -1][ 4, 2].to_i) - store(:mday, yyvs[-1 + -1][ 6, 2].to_i) - store(:hour, yyvs[-1 + -1][ 8, 2].to_i) if yyvs[-1 + -1].size >= 10 - store(:min, yyvs[-1 + -1][10, 2].to_i) if yyvs[-1 + -1].size >= 12 - store(:sec, yyvs[-1 + -1][12, 2].to_i) if yyvs[-1 + -1].size >= 14 - else - raise ParseError, 'YYERROR' - end - - when 39 - raise ParseError, 'YYERROR' unless yyvs[-1] == 'T' - when 40 - - case yyvs[-1 + -1].size - when 2, 4, 6 - store(:hour, yyvs[-1 + -1][ 0, 2].to_i) - store(:min, yyvs[-1 + -1][ 2, 2].to_i) if yyvs[-1 + -1].size >= 4 - store(:sec, yyvs[-1 + -1][ 4, 2].to_i) if yyvs[-1 + -1].size >= 6 - else - raise ParseError, 'YYERROR' - end - - when 41 - yyval = 0 - when 45 - store(:zone, yyvs[-1]) - when 46 - - raise ParseError, 'YYERROR' unless yyvs[-1 + 0] == 'DST' - store(:zone, yyvs[-1 + -1] + ' ' + yyvs[-1 + 0]) - - when 47 - store(:zone, yyvs[-2] + yyvs[-1]) - when 48 - store(:zone, yyvs[-4] + yyvs[-3] + yyvs[-2] + yyvs[-1]) - when -65536 ## never used, placeholder for ruby - end - - if yylen > 0 - yyss[(yyss.size - yylen) .. (yyss.size - 1)] = [] - yyvs[(yyvs.size - yylen) .. (yyvs.size - 1)] = [] - end - - yyvs.push(yyval) - - if @yydebug - printf($stderr, "State stack now: %s\n", yyss.join(' ')) - printf($stderr, "Value stack now: %s\n", yyvs.join(' ')) - end - - ## "Shift" the result of the reduction. - yyn = YYR1[yyn] - yystate = YYPGOTO[yyn - YYNTBASE] + yyss[-1] - if yystate >=0 && yystate <= YYLAST && - YYCHECK[yystate] == yyss[-1] - yystate = YYTABLE[yystate] - else - yystate = YYDEFGOTO[yyn - YYNTBASE] - end - jump = :YYNEWSTATE - next - - when :YYERRLAB - if yyerrstatus == 0 && @yydebug - printf($stderr, "Parse error!\n") - end - jump = :YYERRLAB1 - next - - when :YYERRLAB1 - if yyerrstatus == 3 - if yychar == YYEOF - raise ParseError, "parse error" - end - if @yydebug - printf($stderr, "Discarding token %d (%s).\n", yychar, - YYTNAME[yychar1]) - end - yychar = YYEMPTY - end - - yyerrstatus = 3 - jump = :YYERRHANDLE - next - - when :YYERRPOP - if yyvs.empty? - raise ParseError, "parse error" - end - ## don't pop if the state on top of the stack can handle - ## the error token - yystate = yyss[-1] - if YYCHECK[YYPACT[yystate] + YYTERROR] != YYTERROR - yyvs.pop - yyss.pop - if @yydebug - printf($stderr, "Error: state stack now: %s\n", - yyss.join(' ')) - printf($stderr, "Error: Value stack now: %s\n", - yyvs.join(' ')) - end - end - jump = :YYERRHANDLE - next - - when :YYERRHANDLE - yyn = YYPACT[yystate] - if yyn == YYFLAG - jump = :YYERRPOP - next - end - - yyn += YYTERROR - if yyn < 0 || yyn > YYLAST || YYCHECK[yyn] != YYTERROR - jump = :YYERRPOP - next - end - - yyn = YYTABLE[yyn] - if yyn < 0 - if yyn == YYFLAG - jump = :YYERRPOP - next - end - yyn = -yyn - jump = :YYREDUCE - next - elsif yyn == 0 - jump = :YYERRPOP - next - end - - if yyn == YYFINAL - return ## accept - end - - if @yydebug - printf($stderr, "Shifting error token, ") - end - - yyvs.push(yylval) - yystate = yyn - jump = :YYNEWSTATE - next - - end ## case - - end ## while true - - end ## yyparse - -end ## class - -## Additional user code -class ParseDateLex MONTHS = { 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 } - MONTHPAT = MONTHS.keys.sort.reverse.join('|') + MONTHPAT = MONTHS.keys.join('|') + DAYS = { 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3, 'thu' => 4, 'fri' => 5, 'sat' => 6 } - DAYPAT = DAYS.keys.sort.reverse.join('|') - def initialize(str) @str = str end - def reset(str) @str = str end - def yylex - @str = @str.sub(/\A\s+/, '') - return [-1, nil] if @str.size == 0 - if /\A(#{DAYPAT})[a-z]*\.?/i =~ @str - @str = $' - return [ParseDatePar::DAY, DAYS[$1[0, 3].downcase]] + DAYPAT = DAYS.keys.join('|') + + def parsedate(date, cyear=false) + date = date.dup + + # day + if date.sub!(/(#{DAYPAT})\S*/ino, ' ') + wday = DAYS[$1.downcase] end - if /\A(\d+)(?:(?:th|st|nd|rd)\b)?/ =~ @str - @str = $' - return [ParseDatePar::DIGITS, $1] + + # time + if date.sub!( + /(\d+):(\d+)(?::(\d+))? + (?: + \s* + ([ap])\.?m\.? + \b + )? + (?: + \s* + ( + [a-z]+(?:\s+dst)? + | + [-+]\d+(?::?\d+) + ) + \b + )? + /inox, + ' ') + hour = $1.to_i + min = $2.to_i + sec = $3.to_i if $3 + hour += 12 if $4 and $4.downcase == 'p' + zone = $5 end - if /\A(#{MONTHPAT})[a-z]*\.?/i =~ @str - @str = $' - return [ParseDatePar::MON, MONTHS[$1[0, 3].downcase]] + + # eu + if date.sub!( + /(\d+)\S* + \s+ + (#{MONTHPAT})\S* + (?: + \s+ + (\d+) + )? + /inox, + ' ') + mday = $1.to_i + mon = MONTHS[$2.downcase] + year = $3.to_i if $3 + + # us + elsif date.sub!( + /(#{MONTHPAT})\S* + \s+ + (\d+)\S* + (?: + \s+ + (\d+) + )? + /inox, + ' ') + mon = MONTHS[$1.downcase] + mday = $2.to_i + year = $3.to_i if $3 + + # iso + elsif date.sub!(/(\d+)-(\d+)-(\d+)/no, ' ') + year = $1.to_i + mon = $2.to_i + mday = $3.to_i + mday, mon, year = year, mon, mday if $3.size >= 4 + + # jis + elsif date.sub!(/([MTSH])(\d+)\.(\d+)\.(\d+)/no, ' ') + e = { 'M'=>1867, + 'T'=>1911, + 'S'=>1925, + 'H'=>1988 + }[$1] + year, mon, mday = $2.to_i + e, $3.to_i, $4.to_i + + # vms + elsif date.sub!(/(\d+)-(#{MONTHPAT})\S*-(\d+)/ino, ' ') + mday = $1.to_i + mon = MONTHS[$2.downcase] + year = $3.to_i + year, mon, mday = mday, mon, year if $1.size >= 4 + + # sla + elsif date.sub!(%r|(\d+)/(\d+)(?:/(\d+))?|no, ' ') + mon = $1.to_i + mday = $2.to_i + year = $3.to_i if $3 + year, mon, mday = mon, mday, year if $1.size >= 4 + + # ddd + elsif date.sub!( + /(\d{4,14}) + (?: + \s* + T? + \s* + (\d{2,6}) + )? + (?: + \s* + ( + Z + | + [-+]\d{2,4} + ) + \b + )? + /nox, + ' ') + case $1.size + when 4 + mon = $1[ 0, 2].to_i + mday = $1[ 2, 2].to_i + when 6 + year = $1[ 0, 2].to_i + mon = $1[ 2, 2].to_i + mday = $1[ 4, 2].to_i + when 8, 10, 12, 14 + year = $1[ 0, 4].to_i + mon = $1[ 4, 2].to_i + mday = $1[ 6, 2].to_i + hour = $1[ 8, 2].to_i if $1.size >= 10 + min = $1[10, 2].to_i if $1.size >= 12 + sec = $1[12, 2].to_i if $1.size >= 14 + end + if $2 + case $2.size + when 2, 4, 6 + hour = $2[ 0, 2].to_i + min = $2[ 2, 2].to_i if $2.size >= 4 + sec = $2[ 4, 2].to_i if $2.size >= 6 + end + end + zone = $3 end - if /\A([ap]\.?m\.?\b)/i =~ @str - @str = $' - return [ParseDatePar::MERID, - if $1[0, 1].downcase == 'a' then 0 else 12 end] - end - if /\A([a-z]+)/i =~ @str - @str = $' - return [ParseDatePar::LETTERS, $1] - end - if /\A(.)/ =~ @str - @str = $' - return [$1[0], $1] - end - end -end -class ParseDatePar - def clear() @values = {} end - def store(key, val) @values[key] = val end - def values(cyear) - year = @values[:year] + if cyear and year if year < 100 if year >= 69 @@ -593,18 +166,11 @@ class ParseDatePar end end end - @values[:year] = year - @values.indexes(:year, :mon, :mday, - :hour, :min, :sec, :zone, :wday) - end -end -module ParseDate - def parsedate(date, cyear=false) - lex = ParseDateLex.new(date) - par = ParseDatePar.new - par.clear - begin par.yyparse(lex); rescue; end - par.values(cyear) + + return year, mon, mday, hour, min, sec, zone, wday + end + module_function :parsedate + end diff --git a/marshal.c b/marshal.c index 3a6d3bd000..a152010c20 100644 --- a/marshal.c +++ b/marshal.c @@ -254,7 +254,7 @@ w_object(obj, arg, limit) #endif } else if (SYMBOL_P(obj)) { - w_symbol(obj, arg); + w_symbol(SYM2ID(obj), arg); return; } else { @@ -597,20 +597,25 @@ r_bytes0(s, len, arg) } static ID -r_symbol(arg) +r_symlink(arg) + struct load_arg *arg; +{ + ID id; + int num = r_long(arg); + + if (st_lookup(arg->symbol, num, &id)) { + return id; + } + rb_raise(rb_eTypeError, "bad symbol"); +} + +static ID +r_symreal(arg) struct load_arg *arg; { char *buf; ID id; - if (r_byte(arg) == TYPE_SYMLINK) { - int num = r_long(arg); - - if (st_lookup(arg->symbol, num, &id)) { - return id; - } - rb_raise(rb_eTypeError, "bad symbol"); - } r_bytes(buf, arg); id = rb_intern(buf); st_insert(arg->symbol, arg->symbol->num_entries, id); @@ -618,6 +623,16 @@ r_symbol(arg) return id; } +static ID +r_symbol(arg) + struct load_arg *arg; +{ + if (r_byte(arg) == TYPE_SYMLINK) { + return r_symlink(arg); + } + return r_symreal(arg); +} + static char* r_unique(arg) struct load_arg *arg; @@ -881,8 +896,12 @@ r_object(arg) } return r_regist(m, arg); } + case TYPE_SYMBOL: - return ID2SYM(r_symbol(arg)); + return ID2SYM(r_symreal(arg)); + + case TYPE_SYMLINK: + return ID2SYM(r_symlink(arg)); default: rb_raise(rb_eArgError, "dump format error(0x%x)", type); diff --git a/object.c b/object.c index 1f11e96b7f..b2806da171 100644 --- a/object.c +++ b/object.c @@ -159,16 +159,16 @@ inspect_i(id, value, str) if (!rb_is_instance_id(id)) return ST_CONTINUE; if (RSTRING(str)->ptr[0] == '-') { RSTRING(str)->ptr[0] = '#'; - rb_str_cat(str, ": ", 2); + rb_str_cat2(str, ": "); } else { - rb_str_cat(str, ", ", 2); + rb_str_cat2(str, ", "); } ivname = rb_id2name(id); - rb_str_cat(str, ivname, strlen(ivname)); - rb_str_cat(str, "=", 1); + rb_str_cat2(str, ivname); + rb_str_cat2(str, "="); str2 = rb_inspect(value); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); + rb_str_append(str, str2); OBJ_INFECT(str, str2); return ST_CONTINUE; @@ -179,7 +179,7 @@ inspect_obj(obj, str) VALUE obj, str; { st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str); - rb_str_cat(str, ">", 1); + rb_str_cat2(str, ">"); OBJ_INFECT(str, obj); return str; @@ -202,7 +202,7 @@ rb_obj_inspect(obj) return rb_str_new2(buf); } str = rb_str_new2("-<"); - rb_str_cat(str, b, strlen(b)); + rb_str_cat2(str, b); return rb_protect_inspect(inspect_obj, obj, str); } return rb_funcall(obj, rb_intern("to_s"), 0, 0); @@ -494,7 +494,7 @@ sym_to_i(sym) } static VALUE -sym_to_s(sym) +sym_inspect(sym) VALUE sym; { char *name, *buf; @@ -507,7 +507,7 @@ sym_to_s(sym) } static VALUE -sym_id2name(sym) +sym_to_s(sym) VALUE sym; { return rb_str_new2(rb_id2name(SYM2ID(sym))); @@ -1117,8 +1117,9 @@ Init_Object() rb_undef_method(CLASS_OF(rb_cSymbol), "new"); rb_define_method(rb_cSymbol, "type", sym_type, 0); rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0); + rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0); rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0); - rb_define_method(rb_cSymbol, "id2name", sym_id2name, 0); + rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0); rb_define_method(rb_cModule, "===", rb_mod_eqq, 1); rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1); diff --git a/pack.c b/pack.c index bac34154b7..24032b8729 100644 --- a/pack.c +++ b/pack.c @@ -1565,8 +1565,9 @@ pack_unpack(str, fmt) VALUE str = rb_str_new(0, 0); memcpy(&t, s, sizeof(char *)); s += sizeof(char *); - if (t) - rb_str_cat(str, t, strlen(t)); + if (t) { + rb_str_cat2(str, t); + } rb_ary_push(ary, str); } } diff --git a/parse.y b/parse.y index 63cb9f0f21..73494fc3e4 100644 --- a/parse.y +++ b/parse.y @@ -2573,9 +2573,9 @@ here_document(term, indent) switch (parse_string(term, '\n', '\n')) { case tSTRING: case tXSTRING: - rb_str_cat(yylval.val, "\n", 1); + rb_str_cat2(yylval.val, "\n"); if (!list) { - rb_str_cat(str, RSTRING(yylval.val)->ptr, RSTRING(yylval.val)->len); + rb_str_append(str, yylval.val); } else { list_append(list, NEW_STR(yylval.val)); @@ -3167,11 +3167,8 @@ yylex() lex_state = EXPR_BEG; } else { - if (lex_state == EXPR_ARG) { - if (space_seen) { - arg_ambiguous(); - c = tLPAREN; - } + if (lex_state == EXPR_ARG && space_seen) { + rb_warning("%s (...) interpreted as function", tok()); } lex_state = EXPR_BEG; } @@ -3549,6 +3546,10 @@ str_extend(list, term) case '@': tokadd(c); c = nextc(); + if (c == '@') { + tokadd(c); + c = nextc(); + } while (is_identchar(c)) { tokadd(c); if (ismbchar(c)) { diff --git a/range.c b/range.c index bbb24124bf..971c596a26 100644 --- a/range.c +++ b/range.c @@ -256,8 +256,10 @@ range_to_s(range) str = rb_obj_as_string(rb_ivar_get(range, id_beg)); str2 = rb_obj_as_string(rb_ivar_get(range, id_end)); + str = rb_str_dup(str); rb_str_cat(str, "...", EXCL(range)?3:2); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); + rb_str_append(str, str2); + OBJ_INFECT(str, str2); return str; } @@ -270,8 +272,10 @@ range_inspect(range) str = rb_inspect(rb_ivar_get(range, id_beg)); str2 = rb_inspect(rb_ivar_get(range, id_end)); + str = rb_str_dup(str); rb_str_cat(str, "...", EXCL(range)?3:2); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); + rb_str_append(str, str2); + OBJ_INFECT(str, str2); return str; } diff --git a/re.c b/re.c index cc435e2efa..866b9b65d8 100644 --- a/re.c +++ b/re.c @@ -243,27 +243,27 @@ rb_reg_desc(s, len, re) { VALUE str = rb_str_new2("/"); rb_reg_expr_str(str, s, len); - rb_str_cat(str, "/", 1); + rb_str_cat2(str, "/"); if (re) { if (FL_TEST(re, REG_IGNORECASE)) - rb_str_cat(str, "i", 1); + rb_str_cat2(str, "i"); if (FL_TEST(re, REG_EXTENDED)) - rb_str_cat(str, "x", 1); + rb_str_cat2(str, "x"); if (FL_TEST(re, REG_POSIXLINE)) - rb_str_cat(str, "p", 1); + rb_str_cat2(str, "p"); if (FL_TEST(re, KCODE_FIXED)) { switch ((RBASIC(re)->flags & KCODE_MASK)) { case KCODE_NONE: - rb_str_cat(str, "n", 1); + rb_str_cat2(str, "n"); break; case KCODE_EUC: - rb_str_cat(str, "e", 1); + rb_str_cat2(str, "e"); break; case KCODE_SJIS: - rb_str_cat(str, "s", 1); + rb_str_cat2(str, "s"); break; case KCODE_UTF8: - rb_str_cat(str, "u", 1); + rb_str_cat2(str, "u"); break; } } diff --git a/ruby.c b/ruby.c index 2e813e9dcc..8dcd25bee7 100644 --- a/ruby.c +++ b/ruby.c @@ -403,8 +403,8 @@ proc_options(argc, argv) e_script = rb_str_new(0,0); if (script == 0) script = "-e"; } - rb_str_cat(e_script, s, strlen(s)); - rb_str_cat(e_script, "\n", 1); + rb_str_cat2(e_script, s); + rb_str_cat2(e_script, "\n"); break; case 'r': diff --git a/signal.c b/signal.c index d0b0981793..9be0d48ee5 100644 --- a/signal.c +++ b/signal.c @@ -429,6 +429,7 @@ trap(arg) RETSIGTYPE (*func)(); VALUE command, old; int sig; + char *s; func = sighandle; command = arg->cmd; @@ -466,18 +467,27 @@ trap(arg) command = 0; } - if (TYPE(arg->sig) == T_STRING) { - char *s = RSTRING(arg->sig)->ptr; + switch (TYPE(arg->sig)) { + case T_FIXNUM: + sig = NUM2INT(arg->sig); + break; + case T_SYMBOL: + s = rb_id2name(SYM2ID(arg->sig)); + if (!s) rb_raise(rb_eArgError, "bad signal"); + goto str_signal; + + case T_STRING: + s = RSTRING(arg->sig)->ptr; + + str_signal: if (strncmp("SIG", s, 3) == 0) s += 3; sig = signm2signo(s); if (sig == 0 && strcmp(s, "EXIT") != 0) rb_raise(rb_eArgError, "invalid signal SIG%s", s); } - else { - sig = NUM2INT(arg->sig); - } + if (sig < 0 || sig > NSIG) { rb_raise(rb_eArgError, "invalid signal number (%d)", sig); } diff --git a/string.c b/string.c index 7184080b1b..8589b298eb 100644 --- a/string.c +++ b/string.c @@ -413,11 +413,29 @@ rb_str_cat(str, ptr, len) return str; } +VALUE +rb_str_cat2(str, ptr) + VALUE str; + const char *ptr; +{ + return rb_str_cat(str, ptr, strlen(ptr)); +} + +VALUE +rb_str_append(str1, str2) + VALUE str1, str2; +{ + if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); + str1 = rb_str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); + OBJ_INFECT(str1, str2); + + return str1; +} + VALUE rb_str_concat(str1, str2) VALUE str1, str2; { - rb_str_modify(str1); if (FIXNUM_P(str2)) { int i = FIX2INT(str2); if (0 <= i && i <= 0xff) { /* byte */ @@ -425,9 +443,8 @@ rb_str_concat(str1, str2) return rb_str_cat(str1, &c, 1); } } - if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); - str1 = rb_str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); - if (OBJ_TAINTED(str2)) OBJ_TAINT(str1); + str1 = rb_str_append(str1, str2); + return str1; } diff --git a/struct.c b/struct.c index 52063ae77f..1106054ff4 100644 --- a/struct.c +++ b/struct.c @@ -55,7 +55,7 @@ rb_struct_s_members(obj) ary = rb_ary_new2(RARRAY(member)->len); p = RARRAY(member)->ptr; pend = p + RARRAY(member)->len; while (p < pend) { - rb_ary_push(ary, rb_str_new2(rb_id2name(FIX2INT(*p)))); + rb_ary_push(ary, rb_str_new2(rb_id2name(SYM2ID(*p)))); p++; } @@ -135,7 +135,7 @@ rb_struct_set(obj, val) } for (i=0; ilen; i++) { slot = RARRAY(member)->ptr[i]; - if (rb_id_attrset(FIX2INT(slot)) == rb_frame_last_func()) { + if (rb_id_attrset(SYM2ID(slot)) == rb_frame_last_func()) { return RSTRUCT(obj)->ptr[i] = val; } } @@ -169,7 +169,7 @@ make_struct(name, member, klass) rb_define_singleton_method(nstr, "[]", struct_alloc, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0); for (i=0; i< RARRAY(member)->len; i++) { - ID id = FIX2INT(RARRAY(member)->ptr[i]); + ID id = SYM2ID(RARRAY(member)->ptr[i]); if (i<10) { rb_define_method_id(nstr, id, ref_func[i], 0); } @@ -210,7 +210,7 @@ rb_struct_define(name, va_alist) va_init_list(ar, name); while (mem = va_arg(ar, char*)) { ID slot = rb_intern(mem); - rb_ary_push(ary, INT2FIX(slot)); + rb_ary_push(ary, ID2SYM(slot)); } va_end(ar); @@ -231,11 +231,11 @@ rb_struct_s_def(argc, argv, klass) rb_scan_args(argc, argv, "1*", &name, &rest); for (i=0; ilen; i++) { id = rb_to_id(RARRAY(rest)->ptr[i]); - RARRAY(rest)->ptr[i] = INT2FIX(id); + RARRAY(rest)->ptr[i] = ID2SYM(id); } if (TYPE(name) != T_STRING) { id = rb_to_id(name); - rb_ary_unshift(rest, INT2FIX(id)); + rb_ary_unshift(rest, ID2SYM(id)); name = Qnil; } st = make_struct(name, rest, klass); @@ -252,7 +252,7 @@ rb_struct_initialize(self, values) long n; size = iv_get(klass, "__size__"); - n = FIX2INT(size); + n = FIX2LONG(size); if (n < RARRAY(values)->len) { rb_raise(rb_eArgError, "struct size differs"); } @@ -357,24 +357,23 @@ inspect_struct(s) } str = rb_str_new2("#<"); - rb_str_cat(str, cname, strlen(cname)); - rb_str_cat(str, " ", 1); + rb_str_cat2(str, cname); + rb_str_cat2(str, " "); for (i=0; ilen; i++) { VALUE str2, slot; char *p; if (i > 0) { - rb_str_cat(str, ", ", 2); + rb_str_cat2(str, ", "); } slot = RARRAY(member)->ptr[i]; - p = rb_id2name(FIX2LONG(slot)); - rb_str_cat(str, p, strlen(p)); - rb_str_cat(str, "=", 1); + p = rb_id2name(SYM2ID(slot)); + rb_str_cat2(str, p); + rb_str_cat2(str, "="); str2 = rb_inspect(RSTRUCT(s)->ptr[i]); - rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); - OBJ_INFECT(str, str2); + rb_str_append(str, str2); } - rb_str_cat(str, ">", 1); + rb_str_cat2(str, ">"); OBJ_INFECT(str, s); return str; @@ -430,7 +429,7 @@ rb_struct_aref_id(s, id) len = RARRAY(member)->len; for (i=0; iptr[i]) == id) { + if (SYM2ID(RARRAY(member)->ptr[i]) == id) { return RSTRUCT(s)->ptr[i]; } } @@ -475,7 +474,7 @@ rb_struct_aset_id(s, id, val) if (OBJ_FROZEN(s)) rb_error_frozen("Struct"); len = RARRAY(member)->len; for (i=0; iptr[i]) == id) { + if (SYM2ID(RARRAY(member)->ptr[i]) == id) { RSTRUCT(s)->ptr[i] = val; return val; } diff --git a/variable.c b/variable.c index d276fc1e3e..ec2f9bedc6 100644 --- a/variable.c +++ b/variable.c @@ -49,8 +49,8 @@ fc_i(key, value, res) name = rb_id2name(key); if (res->path) { path = rb_str_dup(res->path); - rb_str_cat(path, "::", 2); - rb_str_cat(path, name, strlen(name)); + rb_str_cat2(path, "::"); + rb_str_cat2(path, name); } else { path = rb_str_new2(name); @@ -129,7 +129,7 @@ classname(klass) ID classid = rb_intern("__classid__"); if (st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) { - path = rb_str_new2(rb_id2name(FIX2INT(path))); + path = rb_str_new2(rb_id2name(SYM2ID(path))); st_insert(ROBJECT(klass)->iv_tbl, classpath, path); st_delete(RCLASS(klass)->iv_tbl, &classid, 0); } @@ -185,8 +185,8 @@ rb_set_class_path(klass, under, name) } else { str = rb_str_dup(rb_class_path(under)); - rb_str_cat(str, "::", 2); - rb_str_cat(str, name, strlen(name)); + rb_str_cat2(str, "::"); + rb_str_cat2(str, name); } rb_iv_set(klass, "__classpath__", str); } @@ -216,7 +216,7 @@ rb_name_class(klass, id) VALUE klass; ID id; { - rb_iv_set(klass, "__classid__", INT2FIX(id)); + rb_iv_set(klass, "__classid__", ID2SYM(id)); } static st_table *autoload_tbl = 0; diff --git a/version.h b/version.h index 211d7814f0..6d669589ef 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.5.3" -#define RUBY_RELEASE_DATE "2000-03-23" +#define RUBY_RELEASE_DATE "2000-04-10" #define RUBY_VERSION_CODE 153 -#define RUBY_RELEASE_CODE 20000323 +#define RUBY_RELEASE_CODE 20000410