From fd06a2a7fbcaf995b662575f894a0f6ecd1be175 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 2 May 2001 04:22:21 +0000 Subject: [PATCH] * eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 270 +++++++++++++++++++++++++++++++++++ ToDo | 4 + array.c | 119 ++++++++++------ bignum.c | 20 +-- class.c | 87 ++++++++++-- defines.h | 10 ++ dir.c | 15 +- dln.c | 21 +-- dln.h | 2 +- error.c | 43 ++++-- eval.c | 306 +++++++++++++++++++++++++++------------- ext/curses/curses.c | 4 +- ext/dbm/dbm.c | 46 ++++-- ext/dbm/extconf.rb | 35 ++++- ext/gdbm/MANIFEST | 1 + ext/gdbm/gdbm.c | 337 +++++++++++++++++++++++++++++--------------- ext/md5/md5init.c | 11 +- file.c | 203 +++++++++++++++----------- gc.c | 38 +---- hash.c | 35 +++-- intern.h | 29 ++-- io.c | 78 ++++++---- marshal.c | 13 +- node.h | 16 +-- numeric.c | 20 +-- object.c | 69 ++++----- pack.c | 70 ++++++--- parse.y | 53 +++---- process.c | 83 ++++------- re.c | 26 ++-- regex.c | 12 +- ruby.c | 22 +-- ruby.h | 55 +++++--- rubyio.h | 2 +- rubysig.h | 2 +- signal.c | 2 +- sprintf.c | 5 +- st.c | 9 +- string.c | 85 ++++++----- struct.c | 2 +- time.c | 60 ++++---- util.c | 303 ++++++++++++++++++++------------------- variable.c | 37 +++-- version.h | 4 +- 44 files changed, 1712 insertions(+), 952 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17bfd878a3..98057975be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +Wed May 2 11:46:13 2001 K.Kosako + + * eval.c (block_pass): should not downgrade safe level. + +Wed May 2 03:07:49 2001 Yukihiro Matsumoto + + * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. + + * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks + memory, whereas gdbm.so doesn't. potential incompatibility. + +Wed May 2 02:02:18 2001 Yukihiro Matsumoto + + * string.c (rb_str_insert): new method. + +Tue May 1 17:55:58 2001 Yukihiro Matsumoto + + * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. + +Tue May 1 16:23:03 2001 Yukihiro Matsumoto + + * array.c (rb_ary_insert): new method. + + * array.c (rb_ary_update): new utility function. + Tue May 1 03:24:05 2001 Akinori MUSHA * lib/irb/completion.rb, lib/irb/frame.rb, lib/irb/xmp.rb, @@ -12,6 +37,10 @@ Tue May 1 03:07:17 2001 Akinori MUSHA * lib/irb/main.rb: This file is not needed anymore. +Fri Apr 27 09:27:10 2001 Yukihiro Matsumoto + + * io.c (set_outfile): should check if closed before assignment. + Thu Apr 26 22:36:11 2001 WATANABE Hirofumi * configure.in: don't use tzname on cygwin 1.3.1+. @@ -19,6 +48,36 @@ Thu Apr 26 22:36:11 2001 WATANABE Hirofumi * configure.in: add -mieee/-ieee to CFLAGS on OSF1/Alpha to disable "DIVISION BY ZERO" exception. +Thu Apr 26 22:30:43 2001 Yukihiro Matsumoto + + * eval.c (rb_eval): should preserve value of ruby_errinfo. + +Thu Apr 26 10:36:09 2001 Yukihiro Matsumoto + + * eval.c (rb_thread_schedule): infinite sleep should not cause + dead lock. + +Wed Apr 25 16:40:44 2001 Yukihiro Matsumoto + + * array.c (rb_ary_flatten_bang): proper recursive detection. + +Wed Apr 25 15:36:15 2001 K.Kosako + + * eval.c (yield_under): need not to prohibit at safe level 4. + +Wed Apr 25 15:22:20 2001 Yukihiro Matsumoto + + * pack.c (pack_pack): p/P packs nil into NULL. + + * pack.c (pack_unpack): p/P unpacks NULL into nil. + +Tue Apr 24 15:35:32 2001 Yukihiro Matsumoto + + * pack.c (pack_pack): size check for P template. + + * ruby.c (set_arg0): wrong predicate when new $0 value is bigger + than original space. + Tue Apr 24 15:18:49 2001 Akinori MUSHA * ext/extmk.rb.in, lib/mkmf.rb: (dir_config) do not add the @@ -27,6 +86,33 @@ Tue Apr 24 15:18:49 2001 Akinori MUSHA * ext/extmk.rb.in, lib/mkmf.rb: (dir_config) return a more useful value, [include_dir, lib_dir]. +Mon Apr 23 14:43:59 2001 Yukihiro Matsumoto + + * gc.c (id2ref): should use NUM2ULONG() + + * object.c (rb_mod_const_get): check whether name is a class + variable name. + + * object.c (rb_mod_const_set): ditto. + + * object.c (rb_mod_const_defined): ditto. + +Sat Apr 21 22:33:26 2001 Yukihiro Matsumoto + + * marshal.c (w_float): precision changed to "%.16g" + +Sat Apr 21 22:07:58 2001 Guy Decoux + + * eval.c (rb_call0): wrong retry behavior. + +Fri Apr 20 19:12:20 2001 Yukihiro Matsumoto + + * numeric.c (fix_aref): a bug on long>int architecture. + +Fri Apr 20 14:57:15 2001 K.Kosako + + * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. + Sun Apr 22 17:44:37 2001 WATANABE Hirofumi * configure.in: add -mieee to CFLAGS on Linux/Alpha @@ -38,16 +124,145 @@ Wed Apr 18 04:37:51 2001 Wakou Aoyama * lib/cgi.rb: CGI::Cookie: no use PATH_INFO. +Wed Apr 18 00:24:40 2001 Yukihiro Matsumoto + + * regex.c (re_compile_pattern): char class at either edge of range + should be invalid. + +Tue Apr 17 17:33:55 2001 Yukihiro Matsumoto + + * eval.c (handle_rescue): use === to compare exception match. + + * error.c (syserr_eqq): comparison between SytemCallErrors should + based on their error numbers. + +Tue Apr 17 16:54:39 2001 K.Kosako + + * eval.c (safe_getter): should use INT2NUM(). + +Tue Apr 17 15:12:56 2001 Yukihiro Matsumoto + + * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. + +Sat Apr 14 22:46:43 2001 Guy Decoux + + * regex.c (calculate_must_string): wrong length calculation. + Sat Apr 14 13:37:32 2001 Usaku Nakamura * win32/config.status.in: no longer use missing/alloca.c. * win32/Makefile.sub: ditto. +Fri Apr 13 12:40:48 2001 K.Kosako + + * eval.c (rb_thread_start_0): fixed memory leak. + +Fri Apr 13 16:41:18 2001 Yukihiro Matsumoto + + * parse.y (none): should clear cmdarg_stack too. + +Fri Apr 13 06:19:29 2001 GOTOU YUUZOU + + * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on + some platforms. + +Wed Apr 11 23:36:26 2001 Yukihiro Matsumoto + + * file.c (rb_stat_dev): device functions should honor stat field + types (except long long such as dev_t). + +Wed Apr 11 18:07:53 2001 K.Kosako + + * eval.c (rb_mod_nesting): should not push nil for nesting array. + + * eval.c (rb_mod_s_constants): should not search array by + rb_mod_const_at() for nil (happens for singleton class). + +Wed Apr 11 13:29:26 2001 Yukihiro Matsumoto + + * class.c (rb_singleton_class_attached): should modify iv_tbl by + itself, no longer use rb_iv_set() to avoid freeze check error. + + * variable.c (rb_const_get): error message "uninitialized constant + Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". + +Tue Apr 10 17:52:10 2001 Yukihiro Matsumoto + + * eval.c (rb_mod_included): new hook called from rb_mod_include(). + +Tue Apr 10 02:24:40 2001 Nobuyoshi Nakada + + * io.c (opt_i_set): should strdup() inplace_edit string. + +Mon Apr 9 23:29:54 2001 Yukihiro Matsumoto + + * eval.c (exec_under): need to push cref too. + +Mon Apr 9 15:20:21 2001 Yukihiro Matsumoto + + * eval.c (rb_f_missing): raise NameError for "undefined local + variable or method". + + * error.c (Init_Exception): new exception NoMethodError. + NameError moved under ScriptError again. + + * eval.c (rb_f_missing): use NoMethodError instead of NameError. + +Mon Apr 9 12:05:44 2001 Yukihiro Matsumoto + + * file.c (Init_File): should redifine "new" class method. + Mon Apr 9 11:56:52 2001 Shugo Maeda * lib/net/imap.rb: fix typo. +Fri Apr 6 01:46:35 2001 Yukihiro Matsumoto + + * eval.c (PUSH_CREF): sharing cref node was problematic. maintain + runtime cref list instead. + + * eval.c (rb_eval): copy defn node before registering. + + * eval.c (rb_load): clear ruby_cref before loading. + +Thu Apr 5 22:40:12 2001 Yukihiro Matsumoto + + * variable.c (rb_const_get): no recursion to show full class path + for modules. + + * eval.c (rb_set_safe_level): should set safe level in curr_thread + as well. + + * eval.c (safe_setter): ditto. + +Thu Apr 5 13:46:06 2001 K.Kosako + + * object.c (rb_obj_is_instance_of): nil belongs to false, not true. + +Thu Apr 5 02:19:03 2001 Yukihiro Matsumoto + + * time.c (make_time_t): proper (I hope) daylight saving time + handling for both US and Europe. I HATE DST! + + * eval.c (rb_thread_wait_for): non blocked signal interrupt should + stop the interval. + +Wed Apr 4 03:47:03 2001 Yukihiro Matsumoto + + * eval.c (proc_eq): class check aded. + + * eval.c (proc_eq): typo fixed ("return" was ommitted). + + * error.c (Init_Exception): move NameError under StandardError. + + * class.c (rb_mod_clone): should copy method bodies too. + + * bignum.c (bigdivrem): should trim trailing zero bdigits of + remainder, even if dd == 0. + + * file.c (check3rdbyte): safe string check moved here. + Tue Apr 3 09:56:20 2001 WATANABE Hirofumi * ext/extmk.rb.in (create_makefile): create def file only if @@ -55,6 +270,26 @@ Tue Apr 3 09:56:20 2001 WATANABE Hirofumi * lib/mkmf.rb: ditto. +Tue Apr 3 00:05:07 2001 Yukihiro Matsumoto + + * time.c (make_time_t): remove HAVE_TM_ZONE code since it + sometimes reports wrong time. + + * time.c (make_time_t): remove unnecessary range check for + platforms where negative time_t is available. + +Mon Apr 2 16:52:48 2001 Yukihiro Matsumoto + + * process.c (proc_waitall): should push Process::Status instead of + Finuxm status. + + * process.c (waitall_each): should add all entries in pid_tbl. + these changes are inspired by Koji Arai. Thanks. + + * process.c (proc_wait): should not iterate if pid_tbl is 0. + + * process.c (proc_waitall): ditto. + Mon Apr 2 14:25:49 2001 Shugo Maeda * lib/monitor.rb (wait): ensure reentrance. @@ -87,14 +322,49 @@ Mon Apr 2 01:16:24 2001 WATANABE Hirofumi * win32/dir.h, dir.c, Makefile: ditto. +Sun Apr 1 23:26:14 2001 TOYOFUKU Chikanobu + + * numeric.c (flodivmod): a bug in no fmod case. + +Sun Apr 1 18:36:14 2001 Koji Arai + + * process.c (pst_wifsignaled): should apply WIFSIGNALED for status + (int), not st (VALUE). + Sat Mar 31 04:47:55 2001 Shugo Maeda * lib/net/imap.rb: add document and example code. +Sat Mar 31 03:24:10 2001 Yukihiro Matsumoto + + * io.c (Init_IO): value of $/ and $\ are no longer restricted to + strings. type checks are done on demand. + + * class.c (rb_include_module): module inclusion should be check + taints. + + * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). + + * ruby.h (rb_str2cstr): ditto. + +Fri Mar 30 23:37:49 2001 Yukihiro Matsumoto + + * eval.c (rb_load): should not copy topleve local variables. It + cause variable/method ambiguity. Thanks to L. Peter Deutsch. + Fri Mar 30 22:56:56 2001 Shugo Maeda * lib/net/imap.rb: rename ContinueRequest to ContinuationRequest. +Fri Mar 30 12:51:19 2001 Yukihiro Matsumoto + + * class.c (rb_include_module): freeze check at first. + +Thu Mar 29 17:05:09 2001 Yukihiro Matsumoto + + * eval.c (rb_attr): sprintf() and rb_intern() moved into + conditional body. + Wed Mar 28 23:43:00 2001 Nobuyoshi Nakada * ext/extmk.rb.in, lib/mkmf.rb: add C++ rules in addition to C diff --git a/ToDo b/ToDo index 4972fcdafb..78b710047b 100644 --- a/ToDo +++ b/ToDo @@ -46,6 +46,9 @@ Hacking Interpreter * MicroRuby * Built-in Interactive Ruby. * trap every method invocation, which can be enabled by e.g. trap_call :method. +* unify Errno exceptions of same errno, or new exception comparison scheme. +* signal list (Signal::trap, Signal::list??). +* 2.times{|i| if i==0 then a = 15 else puts eval("a") end} should print nil. Standard Libraries @@ -78,6 +81,7 @@ Standard Libraries * new user-defined marshal scheme. _dump(dumper), _load(restorer) * warn, warning for Ruby level * hash etc. should handle self referenceing array/hash +* move NameError under StandardError. Extension Libraries diff --git a/array.c b/array.c index 4d3cd04a1c..f92f2073f8 100644 --- a/array.c +++ b/array.c @@ -541,12 +541,12 @@ rb_ary_indexes(argc, argv, ary) } static void -rb_ary_replace(ary, beg, len, rpl) - VALUE ary, rpl; +rb_ary_update(ary, beg, len, rpl, rlen) + VALUE ary; long beg, len; -{ + VALUE *rpl; long rlen; - +{ if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len); if (beg < 0) { beg += RARRAY(ary)->len; @@ -559,14 +559,6 @@ rb_ary_replace(ary, beg, len, rpl) len = RARRAY(ary)->len - beg; } - if (NIL_P(rpl)) { - rpl = rb_ary_new2(0); - } - else if (TYPE(rpl) != T_ARRAY) { - rpl = rb_ary_new3(1, rpl); - } - rlen = RARRAY(rpl)->len; - rb_ary_modify(ary); if (beg >= RARRAY(ary)->len) { len = beg + rlen; @@ -575,7 +567,7 @@ rb_ary_replace(ary, beg, len, rpl) REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len); - MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, rlen); + MEMCPY(RARRAY(ary)->ptr+beg, rpl, VALUE, rlen); RARRAY(ary)->len = len; } else { @@ -591,15 +583,31 @@ rb_ary_replace(ary, beg, len, rpl) REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - if (len != RARRAY(rpl)->len) { + if (len != rlen) { MEMMOVE(RARRAY(ary)->ptr+beg+rlen, RARRAY(ary)->ptr+beg+len, VALUE, RARRAY(ary)->len-(beg+len)); RARRAY(ary)->len = alen; } - MEMMOVE(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, rlen); + MEMMOVE(RARRAY(ary)->ptr+beg, rpl, VALUE, rlen); } } +static void +rb_ary_replace(ary, beg, len, rpl) + VALUE ary, rpl; + long beg, len; +{ + long rlen; + + if (NIL_P(rpl)) { + rpl = rb_ary_new2(0); + } + else if (TYPE(rpl) != T_ARRAY) { + rpl = rb_ary_new3(1, rpl); + } + rb_ary_update(ary, beg, len, RARRAY(rpl)->ptr, RARRAY(rpl)->len); +} + static VALUE rb_ary_aset(argc, argv, ary) int argc; @@ -634,6 +642,19 @@ rb_ary_aset(argc, argv, ary) return argv[1]; } +static VALUE +rb_ary_insert(argc, argv, ary) + int argc; + VALUE *argv; + VALUE ary; +{ + if (argc < 2) { + rb_raise(rb_eArgError, "wrong # of arguments(at least 2)"); + } + rb_ary_update(ary, NUM2LONG(argv[0]), 0, argv+1, argc-1); + return ary; +} + VALUE rb_ary_each(ary) VALUE ary; @@ -1233,7 +1254,7 @@ rb_ary_fill(argc, argv, ary) end = beg + len; if (end > RARRAY(ary)->len) { if (end >= RARRAY(ary)->capa) { - RARRAY(ary)->capa=end; + RARRAY(ary)->capa = end; REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } if (beg > RARRAY(ary)->len) { @@ -1267,19 +1288,11 @@ VALUE rb_ary_concat(x, y) VALUE x, y; { - long xlen = RARRAY(x)->len; long ylen; y = to_ary(y); - ylen = RARRAY(y)->len; - if (ylen > 0) { - rb_ary_modify(x); - if (xlen + ylen > RARRAY(x)->capa) { - RARRAY(x)->capa = xlen + ylen; - REALLOC_N(RARRAY(x)->ptr, VALUE, RARRAY(x)->capa); - } - MEMCPY(RARRAY(x)->ptr+xlen, RARRAY(y)->ptr, VALUE, ylen); - RARRAY(x)->len = xlen + ylen; + if (RARRAY(y)->len > 0) { + rb_ary_replace(x, RARRAY(x)->len, 0, y); } return x; } @@ -1598,35 +1611,54 @@ rb_ary_nitems(ary) return INT2NUM(n); } +static int +flatten(ary, idx, ary2, memo) + VALUE ary; + long idx; + VALUE ary2, memo; +{ + VALUE id; + long i = idx; + long n, lim = idx + RARRAY(ary2)->len; + + id = rb_obj_id(ary2); + if (rb_ary_includes(memo, id)) { + rb_raise(rb_eArgError, "tried to flatten recursive array"); + } + rb_ary_push(memo, id); + rb_ary_replace(ary, idx, 1, ary2); + while (i < lim) { + if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) { + n = flatten(ary, i, RARRAY(ary)->ptr[i], memo); + i += n; lim += n; + } + i++; + } + rb_ary_pop(memo); + + return lim - idx - 1; /* returns number of increased items */ +} + static VALUE rb_ary_flatten_bang(ary) VALUE ary; { - long i; + long i = 0; int mod = 0; - VALUE flattening = Qnil; + VALUE memo = Qnil; rb_ary_modify(ary); - for (i=0; ilen; i++) { + while (ilen) { VALUE ary2 = RARRAY(ary)->ptr[i]; - if (TYPE(ary2) == T_ARRAY) { - if (ary == ary2) { - ary2 = Qnil; - } else { - VALUE id; - if (NIL_P(flattening)) { - flattening = rb_ary_new(); - } - id = rb_obj_id(ary2); - if (rb_ary_includes(flattening, id)) { - rb_raise(rb_eArgError, "tried to flatten recursive array"); - } - rb_ary_push(flattening, id); + if (TYPE(ary2) == T_ARRAY) { + if (NIL_P(memo)) { + memo = rb_ary_new(); } - rb_ary_replace(ary, i--, 1, ary2); + i += flatten(ary, i, ary2, memo); mod = 1; } + i++; } if (mod == 0) return Qnil; return ary; @@ -1673,6 +1705,7 @@ Init_Array() rb_define_method(rb_cArray, "pop", rb_ary_pop, 0); rb_define_method(rb_cArray, "shift", rb_ary_shift, 0); rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1); + rb_define_method(rb_cArray, "insert", rb_ary_insert, -1); rb_define_method(rb_cArray, "each", rb_ary_each, 0); rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0); rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0); diff --git a/bignum.c b/bignum.c index 63384f7ab2..14efc7d75b 100644 --- a/bignum.c +++ b/bignum.c @@ -22,12 +22,12 @@ VALUE rb_cBignum; #if SIZEOF_INT*2 <= SIZEOF_LONG_LONG typedef unsigned int BDIGIT; -typedef unsigned long long BDIGIT_DBL; +typedef unsigned LONG_LONG BDIGIT_DBL; typedef long long BDIGIT_DBL_SIGNED; -#elif SIZEOF_INT*2 <= SIZEOF___INT64 +#elif SIZEOF_ING*2 <= SIZEOF_LONG typedef unsigned int BDIGIT; -typedef unsigned __int64 BDIGIT_DBL; -typedef __int64 BDIGIT_DBL_SIGNED; +typedef unsigned long BDIGIT_DBL; +typedef long long BDIGIT_DBL_SIGNED; #else typedef unsigned short BDIGIT; typedef unsigned long BDIGIT_DBL; @@ -343,7 +343,9 @@ rb_str2inum(str, base) char *s; int len; - s = rb_str2cstr(str, &len); + StringValue(str); + s = RSTRING(str)->ptr; + len = RSTRING(str)->len; if (s[len]) { /* no sentinel somehow */ char *p = ALLOCA_N(char, len+1); @@ -471,7 +473,7 @@ rb_big2long(x) { unsigned long num = big2ulong(x, "int"); - if ((long)num < 0 && (long)num != LONG_MIN) { + if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) { rb_raise(rb_eRangeError, "bignum too big to convert into `int'"); } if (!RBIGNUM(x)->sign) return -(long)num; @@ -917,10 +919,10 @@ bigdivrem(x, y, divp, modp) } if (modp) { /* just normalize remainder */ *modp = rb_big_clone(z); + zds = BDIGITS(*modp); + while (!zds[ny-1]) ny--; if (dd) { - zds = BDIGITS(*modp); - while (ny-- && !zds[ny]) ; - t2 = 0; i = ++ny; + t2 = 0; i = ny; while(i--) { t2 = (t2 | zds[i]) >> dd; q = zds[i]; diff --git a/class.c b/class.c index 5e9cc0e5d9..b1cc94c3c1 100644 --- a/class.c +++ b/class.c @@ -33,16 +33,6 @@ rb_class_new(super) return (VALUE)klass; } -VALUE -rb_singleton_class_new(super) - VALUE super; -{ - VALUE klass = rb_class_new(super); - - FL_SET(klass, FL_SINGLETON); - return klass; -} - static int clone_method(mid, body, tbl) ID mid; @@ -53,6 +43,47 @@ clone_method(mid, body, tbl) return ST_CONTINUE; } +VALUE +rb_mod_clone(module) + VALUE module; +{ + NEWOBJ(clone, struct RClass); + CLONESETUP(clone, module); + + clone->super = RCLASS(module)->super; + if (RCLASS(module)->iv_tbl) { + clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl); + } + if (RCLASS(module)->m_tbl) { + clone->m_tbl = st_init_numtable(); + st_foreach(RCLASS(module)->m_tbl, clone_method, clone->m_tbl); + } + + return (VALUE)clone; +} + +VALUE +rb_mod_dup(mod) + VALUE mod; +{ + VALUE dup = rb_mod_clone(mod); + OBJSETUP(dup, RBASIC(mod)->klass, BUILTIN_TYPE(mod)); + if (FL_TEST(mod, FL_SINGLETON)) { + FL_SET(dup, FL_SINGLETON); + } + return dup; +} + +VALUE +rb_singleton_class_new(super) + VALUE super; +{ + VALUE klass = rb_class_new(super); + + FL_SET(klass, FL_SINGLETON); + return klass; +} + VALUE rb_singleton_class_clone(klass) VALUE klass; @@ -81,8 +112,12 @@ void rb_singleton_class_attached(klass, obj) VALUE klass, obj; { - if (FL_TEST(klass, FL_SINGLETON)) - rb_iv_set(klass, "__attached__", obj); + if (FL_TEST(klass, FL_SINGLETON)) { + if (!RCLASS(klass)->iv_tbl) { + RCLASS(klass)->iv_tbl = st_init_numtable(); + } + st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj); + } } VALUE @@ -112,8 +147,11 @@ rb_define_class(name, super) ID id; id = rb_intern(name); + if (rb_const_defined(rb_cObject, id)) { + klass = rb_const_get(rb_cObject, id); + rb_raise(rb_eNameError, "%s is already defined", name); + } klass = rb_define_class_id(id, super); - st_add_direct(rb_class_tbl, id, klass); return klass; @@ -129,6 +167,10 @@ rb_define_class_under(outer, name, super) ID id; id = rb_intern(name); + if (rb_const_defined_at(outer, id)) { + klass = rb_const_get(outer, id); + rb_raise(rb_eNameError, "%s is already defined", name); + } klass = rb_define_class_id(id, super); rb_const_set(outer, id, klass); rb_set_class_path(klass, outer, name); @@ -170,6 +212,12 @@ rb_define_module(name) ID id; id = rb_intern(name); + if (rb_const_defined(rb_cObject, id)) { + module = rb_const_get(rb_cObject, id); + if (TYPE(module) == T_MODULE) + return module; + rb_raise(rb_eTypeError, "%s is not a module", rb_class2name(CLASS_OF(module))); + } module = rb_define_module_id(id); st_add_direct(rb_class_tbl, id, module); @@ -185,6 +233,13 @@ rb_define_module_under(outer, name) ID id; id = rb_intern(name); + if (rb_const_defined(outer, id)) { + module = rb_const_get(rb_cObject, id); + if (TYPE(module) == T_MODULE) + return module; + rb_raise(rb_eTypeError, "%s::%s is not a module", + rb_class2name(outer), rb_class2name(CLASS_OF(module))); + } module = rb_define_module_id(id); rb_const_set(outer, id, module); rb_set_class_path(module, outer, name); @@ -222,6 +277,11 @@ rb_include_module(klass, module) VALUE p; int changed = 0; + rb_frozen_class_p(klass); + if (!OBJ_TAINTED(klass)) { + rb_secure(4); + } + if (NIL_P(module)) return; if (klass == module) return; @@ -246,7 +306,6 @@ rb_include_module(klass, module) return; } } - rb_frozen_class_p(klass); RCLASS(klass)->super = include_class_new(module, RCLASS(klass)->super); klass = RCLASS(klass)->super; module = RCLASS(module)->super; diff --git a/defines.h b/defines.h index fefddee23b..1e3280a305 100644 --- a/defines.h +++ b/defines.h @@ -12,6 +12,16 @@ #define RUBY +#if SIZEOF_LONG_LONG > 0 +# define HAVE_LONG_LONG +# define LONG_LONG long long +#elif SIZEOF___INT64 > 0 +# define HAVE_LONG_LONG +# define LONG_LONG __int64 +# undef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG SIZEOF___INT64 +#endif + /* define RUBY_USE_EUC/SJIS for default kanji-code */ #ifndef DEFAULT_KCODE #if defined(MSDOS) || defined(__CYGWIN__) || defined(__human68k__) || defined(__MACOS__) || defined(__EMX__) || defined(OS2) || defined(NT) diff --git a/dir.c b/dir.c index a4299ebdbb..4a96e488ca 100644 --- a/dir.c +++ b/dir.c @@ -254,7 +254,7 @@ dir_initialize(dir, dirname) { DIR *dirp; - SafeStr(dirname); + SafeStringValue(dirname); if (DATA_PTR(dir)) closedir(DATA_PTR(dir)); DATA_PTR(dir) = NULL; dirp = opendir(RSTRING(dirname)->ptr); @@ -425,7 +425,7 @@ dir_s_chdir(argc, argv, obj) rb_secure(2); if (rb_scan_args(argc, argv, "01", &path) == 1) { - SafeStr(path); + SafeStringValue(path); dist = RSTRING(path)->ptr; } else { @@ -467,7 +467,7 @@ dir_s_chroot(dir, path) { #if defined(HAVE_CHROOT) && !defined(__CHECKER__) rb_secure(2); - SafeStr(path); + SafeStringValue(path); if (chroot(RSTRING(path)->ptr) == -1) rb_sys_fail(RSTRING(path)->ptr); @@ -495,7 +495,7 @@ dir_s_mkdir(argc, argv, obj) mode = 0777; } - SafeStr(path); + SafeStringValue(path); rb_secure(2); #if !defined(NT) if (mkdir(RSTRING(path)->ptr, mode) == -1) @@ -512,7 +512,7 @@ static VALUE dir_s_rmdir(obj, dir) VALUE obj, dir; { - SafeStr(dir); + SafeStringValue(dir); rb_secure(2); if (rmdir(RSTRING(dir)->ptr) < 0) rb_sys_fail(RSTRING(dir)->ptr); @@ -853,12 +853,13 @@ dir_s_glob(dir, str) int nest; VALUE ary = 0; - SafeStr(str); + SafeStringValue(str); if (!rb_block_given_p()) { ary = rb_ary_new(); } - if (RSTRING(str)->len >= MAXPATHLEN) + if (RSTRING(str)->len >= MAXPATHLEN) { buf = xmalloc(RSTRING(str)->len + 1); + } p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len; diff --git a/dln.c b/dln.c index 127ceabada..d9bacb78c4 100644 --- a/dln.c +++ b/dln.c @@ -1214,7 +1214,7 @@ aix_loaderror(const char *pathname) } #endif -void +void* dln_load(file) const char *file; { @@ -1242,13 +1242,13 @@ dln_load(file) } /* Call the init code */ (*init_fct)(); - return; + return handle; #else #ifdef USE_DLN_A_OUT if (load(file) == -1) { goto failed; } - return; + return 0; #else char buf[MAXPATHLEN]; @@ -1274,11 +1274,12 @@ dln_load(file) } if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) { + dlclose(handle); goto failed; } /* Call the init code */ (*init_fct)(); - return; + return handle; } #endif /* USE_DLN_DLOPEN */ @@ -1304,7 +1305,7 @@ dln_load(file) } } (*init_fct)(); - return; + return (void*)lib; } #endif /* hpux */ @@ -1321,7 +1322,7 @@ dln_load(file) aix_loaderror(file); } (*init_fct)(); - return; + return (void*)init_fct; } #endif /* _AIX */ @@ -1360,7 +1361,7 @@ dln_load(file) init_fct = (void(*)())init_address; (*init_fct)(); - return; + return (void*)init_address; } #else/* OPENSTEP dyld functions */ { @@ -1390,7 +1391,7 @@ dln_load(file) init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf)); (*init_fct)(); - return; + return (void*)init_fct; } #endif /* rld or dyld */ #endif @@ -1438,7 +1439,7 @@ dln_load(file) /* call module initialize function. */ (*init_fct)(); - return; + return (void*)img_id; } #endif /* __BEOS__*/ @@ -1486,7 +1487,7 @@ dln_load(file) init_fct = (void (*)())symAddr; (*init_fct)(); - return; + return (void*)init_fct; } #endif /* __MACOS__ */ diff --git a/dln.h b/dln.h index d3707b38c1..1a7e002551 100644 --- a/dln.h +++ b/dln.h @@ -27,5 +27,5 @@ char *dln_find_file _((const char*,const char*)); extern char *dln_argv0; #endif -void dln_load _((const char*)); +void *dln_load _((const char*)); #endif diff --git a/error.c b/error.c index 7411e957a8..ac5e1e5ba8 100644 --- a/error.c +++ b/error.c @@ -262,6 +262,7 @@ VALUE rb_eRangeError; VALUE rb_eSecurityError; VALUE rb_eNotImpError; VALUE rb_eNoMemError; +VALUE rb_eNoMethodError; VALUE rb_eScriptError; VALUE rb_eNameError; @@ -295,11 +296,8 @@ VALUE rb_exc_new3(etype, str) VALUE etype, str; { - char *s; - int len; - - s = rb_str2cstr(str, &len); - return rb_exc_new(etype, s, len); + StringValue(str); + return rb_exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len); } static VALUE @@ -311,7 +309,7 @@ exc_initialize(argc, argv, exc) VALUE mesg; if (rb_scan_args(argc, argv, "01", &mesg) == 1) { - STR2CSTR(mesg); /* ensure mesg can be converted to String */ + StringValue(mesg); /* ensure mesg can be converted to String */ } rb_iv_set(exc, "mesg", mesg); @@ -522,6 +520,29 @@ syserr_errno(self) return rb_iv_get(self, "errno"); } +static VALUE +syserr_eqq(self, exc) + VALUE self, exc; +{ + VALUE num; + + if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) return Qfalse; + if (self == rb_eSystemCallError) return Qtrue; + + num = rb_iv_get(exc, "errno"); + if (NIL_P(num)) { + VALUE klass = CLASS_OF(exc); + + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; + } + num = rb_const_get(klass, rb_intern("Errno")); + } + if (rb_const_get(self, rb_intern("Errno")) == num) + return Qtrue; + return Qfalse; +} + #ifdef __BEOS__ static VALUE get_syserr(int i) @@ -568,10 +589,11 @@ Init_Exception() rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal); rb_eStandardError = rb_define_class("StandardError", rb_eException); - rb_eTypeError = rb_define_class("TypeError", rb_eStandardError); - rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError); - rb_eIndexError = rb_define_class("IndexError", rb_eStandardError); - rb_eRangeError = rb_define_class("RangeError", rb_eStandardError); + rb_eTypeError = rb_define_class("TypeError", rb_eStandardError); + rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError); + rb_eIndexError = rb_define_class("IndexError", rb_eStandardError); + rb_eRangeError = rb_define_class("RangeError", rb_eStandardError); + rb_eNoMethodError = rb_define_class("NoMethodError", rb_eStandardError); rb_eScriptError = rb_define_class("ScriptError", rb_eException); rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError); @@ -749,6 +771,7 @@ init_syserr() #endif rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError); rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0); + rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1); rb_mErrno = rb_define_module("Errno"); #ifdef __BEOS__ diff --git a/eval.c b/eval.c index 80eabdac7c..031dd4de05 100644 --- a/eval.c +++ b/eval.c @@ -128,33 +128,8 @@ int ruby_safe_level = 0; 4 - no global (non-tainted) variable modification/no direct output */ -void -rb_set_safe_level(level) - int level; -{ - if (level > ruby_safe_level) { - ruby_safe_level = level; - } -} - -static VALUE -safe_getter() -{ - return INT2FIX(ruby_safe_level); -} - -static void -safe_setter(val) - VALUE val; -{ - int level = NUM2INT(val); - - if (level < ruby_safe_level) { - rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d", - ruby_safe_level, level); - } - ruby_safe_level = level; -} +static VALUE safe_getter _((void)); +static void safe_setter _((VALUE val)); void rb_secure(level) @@ -501,9 +476,9 @@ rb_attr(klass, id, read, write, ex) rb_clear_cache_by_id(id); rb_funcall(klass, added, 1, ID2SYM(id)); } - sprintf(buf, "%s=", name); - id = rb_intern(buf); if (write) { + sprintf(buf, "%s=", name); + id = rb_intern(buf); rb_add_method(klass, id, NEW_ATTRSET(attriv), noex); rb_clear_cache_by_id(id); rb_funcall(klass, added, 1, ID2SYM(id)); @@ -820,6 +795,11 @@ static VALUE ruby_wrapper; /* security wrapper */ #define POP_CLASS() ruby_class = _class; } +static NODE *ruby_cref = 0; +static NODE *top_cref; +#define PUSH_CREF(c) ruby_cref = rb_node_newnode(NODE_CREF,(c),0,ruby_cref) +#define POP_CREF() ruby_cref = ruby_cref->nd_next + #define PUSH_SCOPE() { \ volatile int _vmode = scope_vmode; \ struct SCOPE * volatile _old; \ @@ -937,7 +917,9 @@ error_print() eclass = CLASS_OF(ruby_errinfo); PUSH_TAG(PROT_NONE); if (EXEC_TAG() == 0) { - einfo = str2cstr(rb_obj_as_string(ruby_errinfo), &elen); + VALUE e = rb_obj_as_string(ruby_errinfo); + einfo = RSTRING(e)->ptr; + elen = RSTRING(e)->len; } else { einfo = ""; @@ -1046,7 +1028,9 @@ ruby_init() rb_call_inits(); ruby_class = rb_cObject; ruby_frame->self = ruby_top_self; - ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,rb_cObject,0,0); + top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0); + ruby_cref = top_cref; + ruby_frame->cbase = (VALUE)ruby_cref; rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self)); #ifdef __MACOS__ _macruby_init(); @@ -1276,6 +1260,7 @@ rb_eval_string_wrap(str, state) { int status; VALUE self = ruby_top_self; + VALUE wrapper = ruby_wrapper; VALUE val; PUSH_CLASS(); @@ -1287,6 +1272,7 @@ rb_eval_string_wrap(str, state) ruby_top_self = self; POP_CLASS(); + ruby_wrapper = wrapper; if (state) { *state = status; } @@ -1468,7 +1454,7 @@ rb_mod_nesting() VALUE ary = rb_ary_new(); while (cbase && cbase->nd_next) { - rb_ary_push(ary, cbase->nd_clss); + if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss); cbase = cbase->nd_next; } return ary; @@ -1481,11 +1467,11 @@ rb_mod_s_constants() VALUE ary = rb_ary_new(); while (cbase) { - rb_mod_const_at(cbase->nd_clss, ary); + if (!NIL_P(cbase->nd_clss)) rb_mod_const_at(cbase->nd_clss, ary); cbase = cbase->nd_next; } - rb_mod_const_of(ruby_cbase, ary); + if (!NIL_P(ruby_cbase)) rb_mod_const_of(ruby_cbase, ary); return ary; } @@ -1606,6 +1592,23 @@ rb_mod_alias_method(mod, newname, oldname) return mod; } +static NODE* +copy_node_scope(node, rval) + NODE *node; + VALUE rval; +{ + NODE *copy = rb_node_newnode(NODE_SCOPE,0,rval,node->nd_next); + + if (node->nd_tbl) { + copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1); + MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1); + } + else { + copy->nd_tbl = 0; + } + return copy; +} + #ifdef C_ALLOCA # define TMP_PROTECT NODE * volatile tmp__protect_tmp=0 # define TMP_ALLOC(n) \ @@ -2371,9 +2374,11 @@ rb_eval(self, n) POP_TAG(); if (node->nd_ensr) { VALUE retval = prot_tag->retval; /* save retval */ + VALUE errinfo = ruby_errinfo; rb_eval(self, node->nd_ensr); return_value(retval); + ruby_errinfo = errinfo; } if (state) JUMP_TAG(state); break; @@ -2534,6 +2539,7 @@ rb_eval(self, n) case NODE_SCOPE: { struct FRAME frame; + NODE *saved_cref = 0; frame = *ruby_frame; frame.tmp = ruby_frame; @@ -2541,7 +2547,11 @@ rb_eval(self, n) PUSH_SCOPE(); PUSH_TAG(PROT_NONE); - if (node->nd_rval) ruby_frame->cbase = node->nd_rval; + if (node->nd_rval) { + saved_cref = ruby_cref; + ruby_cref = (NODE*)node->nd_rval; + ruby_frame->cbase = node->nd_rval; + } if (node->nd_tbl) { VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1); *vars++ = (VALUE)node; @@ -2559,6 +2569,8 @@ rb_eval(self, n) POP_TAG(); POP_SCOPE(); ruby_frame = frame.tmp; + if (saved_cref) + ruby_cref = saved_cref; if (state) JUMP_TAG(state); } break; @@ -2897,7 +2909,7 @@ rb_eval(self, n) case NODE_DEFN: if (node->nd_defn) { - NODE *body; + NODE *body, *defn; VALUE origin; int noex; @@ -2911,11 +2923,6 @@ rb_eval(self, n) rb_warn("redefining `%s' may cause serious problem", rb_id2name(node->nd_mid)); } - if (node->nd_defn->nd_rval && - ((NODE*)node->nd_defn->nd_rval)->nd_clss != ruby_class) { - node->nd_defn->nd_rval = - (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0, node->nd_defn->nd_rval); - } rb_frozen_class_p(ruby_class); body = search_method(ruby_class, node->nd_mid, &origin); if (body){ @@ -2944,11 +2951,13 @@ rb_eval(self, n) if (body && origin == ruby_class && body->nd_noex & NOEX_UNDEF) { noex |= NOEX_UNDEF; } - rb_add_method(ruby_class, node->nd_mid, node->nd_defn, noex); + + defn = copy_node_scope(node->nd_defn, ruby_cref); + rb_add_method(ruby_class, node->nd_mid, defn, noex); rb_clear_cache_by_id(node->nd_mid); if (scope_vmode == SCOPE_MODFUNC) { rb_add_method(rb_singleton_class(ruby_class), - node->nd_mid, node->nd_defn, NOEX_PUBLIC); + node->nd_mid, defn, NOEX_PUBLIC); rb_funcall(ruby_class, singleton_added, 1, ID2SYM(node->nd_mid)); } if (FL_TEST(ruby_class, FL_SINGLETON)) { @@ -2966,7 +2975,7 @@ rb_eval(self, n) if (node->nd_defn) { VALUE recv = rb_eval(self, node->nd_recv); VALUE klass; - NODE *body = 0; + NODE *body = 0, *defn; if (rb_safe_level() >= 4 && !OBJ_TAINTED(recv)) { rb_raise(rb_eSecurityError, "Insecure; can't define singleton method"); @@ -2978,11 +2987,6 @@ rb_eval(self, n) rb_class2name(CLASS_OF(recv))); } - if (node->nd_defn->nd_rval && - ((NODE*)node->nd_defn->nd_rval)->nd_clss != ruby_class) { - node->nd_defn->nd_rval = - (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0, node->nd_defn->nd_rval); - } if (OBJ_FROZEN(recv)) rb_error_frozen("object"); klass = rb_singleton_class(recv); if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) { @@ -2993,7 +2997,9 @@ rb_eval(self, n) rb_warning("redefine %s", rb_id2name(node->nd_mid)); } } - rb_add_method(klass, node->nd_mid, node->nd_defn, + defn = copy_node_scope(node->nd_defn, ruby_cref); + defn->nd_rval = (VALUE)ruby_cref; + rb_add_method(klass, node->nd_mid, defn, NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0)); rb_clear_cache_by_id(node->nd_mid); rb_funcall(recv, singleton_added, 1, ID2SYM(node->nd_mid)); @@ -3191,16 +3197,11 @@ module_setup(module, n) frame.tmp = ruby_frame; ruby_frame = &frame; - /* fill c-ref */ - node->nd_clss = module; - node = node->nd_body; - PUSH_CLASS(); ruby_class = module; PUSH_SCOPE(); PUSH_VARS(); - if (node->nd_rval) ruby_frame->cbase = node->nd_rval; if (node->nd_tbl) { VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1); *vars++ = (VALUE)node; @@ -3213,6 +3214,8 @@ module_setup(module, n) ruby_scope->local_tbl = 0; } + PUSH_CREF(module); + ruby_frame->cbase = (VALUE)ruby_cref; PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { if (trace_func) { @@ -3223,6 +3226,7 @@ module_setup(module, n) result = rb_eval(ruby_class, node->nd_next); } POP_TAG(); + POP_CREF(); POP_VARS(); POP_SCOPE(); POP_CLASS(); @@ -3362,10 +3366,13 @@ rb_longjmp(tag, mesg) if (RTEST(ruby_debug) && !NIL_P(ruby_errinfo) && !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) { + VALUE e = ruby_errinfo; + + StringValue(e); fprintf(stderr, "Exception `%s' at %s:%d - %s\n", rb_class2name(CLASS_OF(ruby_errinfo)), ruby_sourcefile, ruby_sourceline, - STR2CSTR(ruby_errinfo)); + RSTRING(e)->ptr); } rb_trap_restore_mask(); @@ -3845,7 +3852,7 @@ handle_rescue(self, node) if (!rb_obj_is_kind_of(argv[0], rb_cModule)) { rb_raise(rb_eTypeError, "class or module required for rescue clause"); } - if (rb_obj_is_kind_of(ruby_errinfo, argv[0])) return 1; + if (rb_funcall(*argv, eqq, 1, ruby_errinfo)) return 1; argv++; } return 0; @@ -3999,7 +4006,8 @@ rb_f_missing(argc, argv, obj) VALUE *argv; VALUE obj; { - ID id; + ID id; + VALUE exc = rb_eNoMethodError; volatile VALUE d = 0; char *format = 0; char *desc = ""; @@ -4042,6 +4050,7 @@ rb_f_missing(argc, argv, obj) if (('a' <= mname[0] && mname[0] <= 'z') || mname[0] == '_') { format = "undefined local variable or method `%s' for %s%s%s"; + exc = rb_eNameError; } } if (!format) { @@ -4058,7 +4067,7 @@ rb_f_missing(argc, argv, obj) PUSH_FRAME(); /* fake frame */ *ruby_frame = *_frame.prev->prev; - rb_raise(rb_eNameError, format, rb_id2name(id), + rb_raise(exc, format, rb_id2name(id), desc, desc[0]=='#'?"":":", desc[0]=='#'?"":rb_class2name(CLASS_OF(obj))); POP_FRAME(); @@ -4305,14 +4314,19 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper) result = proc_call(body->nd_cval, rb_ary_new4(argc, argv)); break; - default: + case NODE_SCOPE: { int state; VALUE *local_vars; /* OK */ + NODE *saved_cref = 0; PUSH_SCOPE(); - if (body->nd_rval) ruby_frame->cbase = body->nd_rval; + if (body->nd_rval) { + saved_cref = ruby_cref; + ruby_cref = (NODE*)body->nd_rval; + ruby_frame->cbase = body->nd_rval; + } if (body->nd_tbl) { local_vars = TMP_ALLOC(body->nd_tbl[0]+1); *local_vars++ = (VALUE)body; @@ -4405,6 +4419,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper) POP_TAG(); POP_VARS(); POP_SCOPE(); + ruby_cref = saved_cref; if (trace_func) { char *file = ruby_frame->prev->file; int line = ruby_frame->prev->line; @@ -4420,7 +4435,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper) case TAG_RETRY: if (rb_block_given_p()) { - break; + JUMP_TAG(state); } /* fall through */ default: @@ -4428,6 +4443,11 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper) break; } } + break; + + default: + rb_bug("unknown node type %d", nd_type(body)); + break; } POP_FRAME(); POP_ITER(); @@ -4851,17 +4871,17 @@ rb_f_eval(argc, argv, self) rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline); if (argc >= 3) { - file = STR2CSTR(vfile); + file = StringValuePtr(vfile); } if (argc >= 4) { line = NUM2INT(vline); } if (ruby_safe_level >= 4) { - src = rb_str_to_str(src); + StringValue(src); } else { - SafeStr(src); + SafeStringValue(src); } if (NIL_P(scope) && ruby_frame->prev) { struct FRAME *prev; @@ -4900,6 +4920,7 @@ exec_under(func, under, args) if (ruby_cbase != under) { ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,under,0,ruby_frame->cbase); } + PUSH_CREF(under); mode = scope_vmode; SCOPE_SET(SCOPE_PUBLIC); @@ -4908,6 +4929,7 @@ exec_under(func, under, args) val = (*func)(args); } POP_TAG(); + POP_CREF(); SCOPE_SET(mode); POP_FRAME(); POP_CLASS(); @@ -4933,10 +4955,10 @@ eval_under(under, self, src, file, line) VALUE args[4]; if (ruby_safe_level >= 4) { - src = rb_str_to_str(src); + StringValue(src); } else { - SafeStr(src); + SafeStringValue(src); } args[0] = self; args[1] = src; @@ -4983,8 +5005,6 @@ static VALUE yield_under(under, self) VALUE under, self; { - if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) - rb_raise(rb_eSecurityError, "Insecure: can't eval"); return exec_under(yield_under_i, under, self); } @@ -5010,17 +5030,20 @@ specific_eval(argc, argv, klass, self) } else { if (ruby_safe_level >= 4) { - src = rb_str_to_str(src); + StringValue(src); } else { - SafeStr(src); + SafeStringValue(src); } if (argc > 3) { rb_raise(rb_eArgError, "wrong # of arguments: %s(src) or %s{..}", rb_id2name(ruby_frame->last_func), rb_id2name(ruby_frame->last_func)); } - if (argc > 1) file = STR2CSTR(argv[1]); + if (argc > 1) { + src = argv[1]; + file = StringValuePtr(src); + } if (argc > 2) line = NUM2INT(argv[2]); } return eval_under(klass, self, argv[0], file, line); @@ -5066,13 +5089,14 @@ rb_load(fname, wrap) volatile ID last_func; volatile VALUE wrapper = 0; volatile VALUE self = ruby_top_self; + NODE *saved_cref = ruby_cref; TMP_PROTECT; if (wrap) { - fname = rb_str_to_str(fname); + StringValue(fname); } else { - SafeStr(fname); + SafeStringValue(fname); } file = rb_find_file(RSTRING(fname)->ptr); if (!file) { @@ -5083,6 +5107,7 @@ rb_load(fname, wrap) PUSH_VARS(); PUSH_CLASS(); wrapper = ruby_wrapper; + ruby_cref = top_cref; if (!wrap) { rb_secure(4); /* should alter global state */ ruby_class = rb_cObject; @@ -5093,6 +5118,7 @@ rb_load(fname, wrap) ruby_class = ruby_wrapper = rb_module_new(); self = rb_obj_clone(ruby_top_self); rb_extend_object(self, ruby_class); + PUSH_CREF(ruby_wrapper); } PUSH_FRAME(); ruby_frame->last_func = 0; @@ -5100,19 +5126,8 @@ rb_load(fname, wrap) ruby_frame->self = self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0); PUSH_SCOPE(); - if (ruby_class == rb_cObject && top_scope->local_tbl) { - int len = top_scope->local_tbl[0]+1; - ID *tbl = ALLOC_N(ID, len); - VALUE *vars = TMP_ALLOC(len); - *vars++ = 0; - MEMCPY(tbl, top_scope->local_tbl, ID, len); - MEMCPY(vars, top_scope->local_vars, VALUE, len-1); - ruby_scope->local_tbl = tbl; /* copy toplevel scope */ - ruby_scope->local_vars = vars; /* will not alter toplevel variables */ - } /* default visibility is private at loading toplevel */ SCOPE_SET(SCOPE_PRIVATE); - PUSH_TAG(PROT_NONE); state = EXEC_TAG(); last_func = ruby_frame->last_func; @@ -5135,6 +5150,7 @@ rb_load(fname, wrap) free(ruby_scope->local_tbl); } POP_TAG(); + ruby_cref = saved_cref; POP_SCOPE(); POP_FRAME(); POP_CLASS(); @@ -5177,6 +5193,7 @@ rb_f_load(argc, argv) return Qtrue; } +VALUE ruby_dln_librefs; static VALUE rb_features; static st_table *loading_tbl; @@ -5192,7 +5209,8 @@ rb_feature_p(feature, wait) p = RARRAY(rb_features)->ptr; pend = p + RARRAY(rb_features)->len; while (p < pend) { - f = STR2CSTR(*p); + VALUE v = *p; + f = StringValuePtr(v); if (strcmp(f, feature) == 0) { goto load_wait; } @@ -5266,7 +5284,7 @@ rb_f_require(obj, fname) int state; volatile int safe = ruby_safe_level; - SafeStr(fname); + SafeStringValue(fname); if (rb_feature_p(RSTRING(fname)->ptr, Qtrue)) return Qfalse; ext = strrchr(RSTRING(fname)->ptr, '.'); @@ -5344,9 +5362,12 @@ rb_f_require(obj, fname) PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { + void *handle; + load = rb_str_new2(file); file = RSTRING(load)->ptr; - dln_load(file); + handle = dln_load(file); + rb_ary_push(ruby_dln_librefs, INT2NUM((long)handle)); } POP_TAG(); if (state) JUMP_TAG(state); @@ -5525,6 +5546,13 @@ rb_mod_modfunc(argc, argv, module) return module; } +static VALUE +rb_mod_included(module, include) + VALUE module, include; +{ + return Qnil; +} + static VALUE rb_mod_append_features(module, include) VALUE module, include; @@ -5553,6 +5581,7 @@ rb_mod_include(argc, argv, module) for (i=0; iprev) { tmp = ALLOC_N(struct BLOCK, 1); @@ -5993,6 +6027,12 @@ blk_copy_prev(block) } scope_dup(tmp->scope); tmp->tag->flags |= BLOCK_DYNAMIC; + + for (vars = tmp->dyna_vars; vars; vars = vars->next) { + if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; + FL_SET(vars, DVAR_DONT_RECYCLE); + } + block->prev = tmp; block = tmp; } @@ -6316,8 +6356,10 @@ proc_eq(self, other) { struct BLOCK *data, *data2; + if (self == other) return Qtrue; if (TYPE(other) != T_DATA) return Qfalse; - if (RDATA(other)->dmark != (RUBY_DATA_FUNC)blk_mark) Qfalse; + if (RDATA(other)->dmark != (RUBY_DATA_FUNC)blk_mark) return Qfalse; + if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse; Data_Get_Struct(self, struct BLOCK, data); Data_Get_Struct(other, struct BLOCK, data2); if (data->tag == data2->tag) return Qtrue; @@ -6380,6 +6422,8 @@ block_pass(self, node) state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(block); + if (safe > ruby_safe_level) + ruby_safe_level = safe; result = rb_eval(self, node->nd_iter); } POP_TAG(); @@ -6551,8 +6595,8 @@ method_call(argc, argv, method) Data_Get_Struct(method, struct METHOD, data); PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); PUSH_TAG(PROT_NONE); - if (OBJ_TAINTED(method)) { - if (ruby_safe_level < 4) ruby_safe_level = 4; + if (OBJ_TAINTED(method) && ruby_safe_level < 4) { + ruby_safe_level = 4; } if ((state = EXEC_TAG()) == 0) { result = rb_call0(data->klass,data->recv,data->id,argc,argv,data->body,0); @@ -6836,6 +6880,7 @@ struct thread { struct tag *tag; VALUE klass; VALUE wrapper; + NODE *cref; int flags; /* misc. states (vmode/rb_trap_immediate/raised) */ @@ -6879,6 +6924,37 @@ struct thread { #define FOREACH_THREAD(x) FOREACH_THREAD_FROM(curr_thread,x) #define END_FOREACH(x) END_FOREACH_FROM(curr_thread,x) +/* $SAFE accessor */ +void +rb_set_safe_level(level) + int level; +{ + if (level > ruby_safe_level) { + ruby_safe_level = level; + curr_thread->safe = level; + } +} + +static VALUE +safe_getter() +{ + return INT2NUM(ruby_safe_level); +} + +static void +safe_setter(val) + VALUE val; +{ + int level = NUM2INT(val); + + if (level < ruby_safe_level) { + rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d", + ruby_safe_level, level); + } + ruby_safe_level = level; + curr_thread->safe = level; +} + /* Return the current time as a floating-point number */ static double timeofday() @@ -6904,6 +6980,7 @@ thread_mark(th) rb_gc_mark(th->klass); rb_gc_mark(th->wrapper); + rb_gc_mark((VALUE)th->cref); rb_gc_mark((VALUE)th->scope); rb_gc_mark((VALUE)th->dyna_vars); @@ -7021,6 +7098,7 @@ rb_thread_save_context(th) th->scope = ruby_scope; th->klass = ruby_class; th->wrapper = ruby_wrapper; + th->cref = ruby_cref; th->dyna_vars = ruby_dyna_vars; th->block = ruby_block; th->flags &= THREAD_FLAGS_MASK; @@ -7111,6 +7189,7 @@ rb_thread_restore_context(th, exit) ruby_scope = th->scope; ruby_class = th->klass; ruby_wrapper = th->wrapper; + ruby_cref = th->cref; ruby_dyna_vars = th->dyna_vars; ruby_block = th->block; scope_vmode = th->flags&SCOPE_MASK; @@ -7327,10 +7406,14 @@ rb_thread_schedule() if (th_delay <= 0.0) { th->status = THREAD_RUNNABLE; found = 1; - } else if (th_delay < delay) { + } + else if (th_delay < delay) { delay = th_delay; need_select = 1; } + else if (th->delay == DELAY_INFTY) { + need_select = 1; + } } } END_FOREACH_FROM(curr, th); @@ -7511,7 +7594,14 @@ rb_thread_wait_for(time) n = select(0, 0, 0, 0, &time); TRAP_END; if (n == 0) return; - + if (n < 0) { + switch (errno) { + case EINTR: + return; + default: + rb_sys_fail("sleep"); + } + } #ifndef linux d = limit - timeofday(); @@ -7915,6 +8005,7 @@ rb_thread_abort_exc_set(thread, val) th->scope = 0;\ th->klass = 0;\ th->wrapper = 0;\ + th->cref = ruby_cref;\ th->dyna_vars = ruby_dyna_vars;\ th->block = 0;\ th->iter = 0;\ @@ -8004,6 +8095,7 @@ rb_thread_start_0(fn, arg, th_arg) { volatile rb_thread_t th = th_arg; volatile VALUE thread = th->thread; + struct BLOCK* saved_block = 0; enum thread_status status; int state; @@ -8021,7 +8113,11 @@ rb_thread_start_0(fn, arg, th_arg) #endif if (ruby_block) { /* should nail down higher scopes */ - blk_copy_prev(ruby_block); + struct BLOCK dummy; + + dummy.prev = ruby_block; + blk_copy_prev(&dummy); + saved_block = ruby_block = dummy.prev; } scope_dup(ruby_scope); FL_SET(ruby_scope, SCOPE_SHARED); @@ -8048,6 +8144,16 @@ rb_thread_start_0(fn, arg, th_arg) } POP_TAG(); status = th->status; + + while (saved_block) { + struct BLOCK *tmp = saved_block; + + if (tmp->frame.argc > 0) + free(tmp->frame.argv); + saved_block = tmp->prev; + free(tmp); + } + if (th == main_thread) ruby_stop(state); rb_thread_remove(th); if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) { @@ -8059,11 +8165,15 @@ rb_thread_start_0(fn, arg, th_arg) } else if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) { if (th->safe >= 4) { - rb_raise(rb_eSecurityError, "Insecure exit at level %d", - ruby_safe_level); + char buf[32]; + + sprintf(buf, "Insecure exit at level %d", th->safe); + th->errinfo = rb_exc_new2(rb_eSecurityError, buf); + } + else { + /* delegate exception to main_thread */ + rb_thread_raise(1, &ruby_errinfo, main_thread); } - /* delegate exception to main_thread */ - rb_thread_raise(1, &ruby_errinfo, main_thread); } else if (th->safe < 4 && (thread_abort || th->abort || RTEST(ruby_debug))) { diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 4a8c46f483..b6dfbb0039 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -347,7 +347,7 @@ curses_addstr(obj, str) VALUE str; { if (!NIL_P(str)) { - addstr(STR2CSTR(str)); + addstr(StringValuePtr(str)); } return Qnil; } @@ -711,7 +711,7 @@ window_addstr(obj, str) struct windata *winp; GetWINDOW(obj, winp); - waddstr(winp->window, STR2CSTR(str)); + waddstr(winp->window, StringValuePtr(str)); } return Qnil; } diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index 7196c18149..062ae692ab 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -84,7 +84,7 @@ fdbm_initialize(argc, argv, obj) else { mode = NUM2INT(vmode); } - Check_SafeStr(file); + SafeStringValue(file); dbm = 0; if (mode >= 0) { @@ -150,7 +150,7 @@ fdbm_fetch(obj, keystr, ifnone) struct dbmdata *dbmp; DBM *dbm; - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; @@ -196,7 +196,7 @@ fdbm_index(obj, valstr) struct dbmdata *dbmp; DBM *dbm; - Check_Type(valstr, T_STRING); + StringValue(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; @@ -238,7 +238,7 @@ fdbm_delete(obj, keystr) DBM *dbm; rb_secure(4); - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; @@ -273,14 +273,15 @@ fdbm_shift(obj) rb_secure(4); GetDBM(obj, dbmp); dbm = dbmp->di_dbm; + dbmp->di_size = -1; key = dbm_firstkey(dbm); if (!key.dptr) return Qnil; val = dbm_fetch(dbm, key); - dbm_delete(dbm, key); - keystr = rb_tainted_str_new(key.dptr, key.dsize); valstr = rb_tainted_str_new(val.dptr, val.dsize); + dbm_delete(dbm, key); + return rb_assoc_new(keystr, valstr); } @@ -292,20 +293,35 @@ fdbm_delete_if(obj) struct dbmdata *dbmp; DBM *dbm; VALUE keystr, valstr; + VALUE ret, ary = rb_ary_new(); + int i, status = 0, n; rb_secure(4); GetDBM(obj, dbmp); dbm = dbmp->di_dbm; + n = dbmp->di_size; + dbmp->di_size = -1; + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); keystr = rb_tainted_str_new(key.dptr, key.dsize); valstr = rb_tainted_str_new(val.dptr, val.dsize); - if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) { - if (dbm_delete(dbm, key)) { - rb_raise(rb_eDBMError, "dbm_delete failed"); - } + ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); + if (status != 0) break; + if (RTEST(ret)) rb_ary_push(ary, keystr); + } + + for (i = 0; i < RARRAY(ary)->len; i++) { + keystr = RARRAY(ary)->ptr[i]; + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + if (dbm_delete(dbm, key)) { + rb_raise(rb_eDBMError, "dbm_delete failed"); } } + if (status) rb_jump_tag(status); + if (n > 0) dbmp->di_size = n - RARRAY(ary)->len; + return obj; } @@ -321,11 +337,13 @@ fdbm_clear(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; dbmp->di_size = -1; - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + while (key = dbm_firstkey(dbm), key.dptr) { if (dbm_delete(dbm, key)) { rb_raise(rb_eDBMError, "dbm_delete failed"); } } + dbmp->di_size = 0; + return obj; } @@ -569,7 +587,7 @@ fdbm_has_key(obj, keystr) struct dbmdata *dbmp; DBM *dbm; - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; @@ -588,7 +606,7 @@ fdbm_has_value(obj, valstr) struct dbmdata *dbmp; DBM *dbm; - Check_Type(valstr, T_STRING); + StringValue(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; @@ -682,7 +700,7 @@ Init_dbm() rb_define_method(cDBM, "each_pair", fdbm_each_pair, 0); rb_define_method(cDBM, "keys", fdbm_keys, 0); rb_define_method(cDBM, "values", fdbm_values, 0); - rb_define_method(cDBM, "shift", fdbm_shift, 1); + rb_define_method(cDBM, "shift", fdbm_shift, 0); rb_define_method(cDBM, "delete", fdbm_delete, 1); rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); rb_define_method(cDBM, "reject!", fdbm_delete_if, 0); diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb index 9ce235a2b5..7afa7d92d4 100644 --- a/ext/dbm/extconf.rb +++ b/ext/dbm/extconf.rb @@ -1,13 +1,38 @@ require 'mkmf' dir_config("dbm") -if have_library("gdbm", "dbm_open") - gdbm = true + +$db_hdr = "ndbm.h" +$db_prefix = "" +dblib = with_config("dbm-type", nil) + +def db_check(db) + if /^db2?$/ =~ db + $db_prefix = "__db_n" + $db_hdr = db+".h" + end + r = have_library(db, db_prefix("dbm_open")) + if db == "gdbm" + $have_gdbm = true + end + return r end -gdbm or have_library("db", "dbm_open") or have_library("dbm", "dbm_open") + +def db_prefix(func) + $db_prefix+func +end + +if dblib + db_check(dblib) +else + for dblib in %w(db db2 db1 dbm gdbm) + db_check(dblib) and break + end +end + have_header("cdefs.h") have_header("sys/cdefs.h") -if have_header("ndbm.h") and have_func("dbm_open") - have_func("dbm_clearerr") unless gdbm +if have_header($db_hdr) and have_func(db_prefix("dbm_open")) + have_func(db_prefix("dbm_clearerr")) unless $have_gdbm create_makefile("dbm") end diff --git a/ext/gdbm/MANIFEST b/ext/gdbm/MANIFEST index f4a8796d18..1359b4fdaf 100644 --- a/ext/gdbm/MANIFEST +++ b/ext/gdbm/MANIFEST @@ -3,3 +3,4 @@ README depend extconf.rb gdbm.c +testgdbm.rb diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c index 86ee68678b..ccfaeade6d 100644 --- a/ext/gdbm/gdbm.c +++ b/ext/gdbm/gdbm.c @@ -14,7 +14,7 @@ #include #include -VALUE cGDBM, rb_eGDBMError; +static VALUE cGDBM, rb_eGDBMError; #define MY_BLOCK_SIZE (2048) #define MY_FATAL_FUNC (0) @@ -83,7 +83,7 @@ fgdbm_initialize(argc, argv, obj) if (!NIL_P(vflags)) flags = NUM2INT(vflags); - Check_SafeStr(file); + SafeStringValue(file); dbm = 0; if (mode >= 0) @@ -147,42 +147,112 @@ fgdbm_close(obj) return Qnil; } -static datum -gdbm_fetch_1(dbm, key) +static VALUE +rb_gdbm_fetch(dbm, key) GDBM_FILE dbm; datum key; { - static char *ptr; datum val; + NEWOBJ(str, struct RString); + OBJSETUP(str, rb_cString, T_STRING); val = gdbm_fetch(dbm, key); - if (ptr) free(ptr); - ptr = val.dptr; + if (val.dptr == 0) + return Qnil; - return val; + str->ptr = 0; + str->len = val.dsize; + str->orig = 0; + str->ptr = REALLOC_N(val.dptr,char,val.dsize+1); + str->ptr[str->len] = '\0'; + + OBJ_TAINT(str); + return (VALUE)str; +} + +static VALUE +rb_gdbm_fetch2(dbm, keystr) + GDBM_FILE dbm; + VALUE keystr; +{ + datum key; + + StringValue(keystr); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + return rb_gdbm_fetch(dbm, key); +} + +static VALUE +rb_gdbm_firstkey(dbm) + GDBM_FILE dbm; +{ + datum key; + NEWOBJ(str, struct RString); + OBJSETUP(str, rb_cString, T_STRING); + + key = gdbm_firstkey(dbm); + if (key.dptr == 0) + return Qnil; + + str->ptr = 0; + str->len = key.dsize; + str->orig = 0; + str->ptr = REALLOC_N(key.dptr,char,key.dsize+1); + str->ptr[str->len] = '\0'; + + OBJ_TAINT(str); + return (VALUE)str; +} + +static VALUE +rb_gdbm_nextkey(dbm, keystr) + GDBM_FILE dbm; + VALUE keystr; +{ + datum key, key2; + NEWOBJ(str, struct RString); + OBJSETUP(str, rb_cString, T_STRING); + + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + key2 = gdbm_nextkey(dbm, key); + if (key2.dptr == 0) + return Qnil; + + str->ptr = 0; + str->len = key2.dsize; + str->orig = 0; + str->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1); + str->ptr[str->len] = '\0'; + + OBJ_TAINT(str); + return (VALUE)str; } static VALUE fgdbm_fetch(obj, keystr, ifnone) VALUE obj, keystr, ifnone; { - datum key, value; + datum key; struct dbmdata *dbmp; GDBM_FILE dbm; + VALUE valstr; - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - value = gdbm_fetch_1(dbm, key); - if (value.dptr == 0) { + valstr = rb_gdbm_fetch(dbm, key); + if (NIL_P(valstr)) { if (ifnone == Qnil && rb_block_given_p()) return rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); return ifnone; } - return rb_tainted_str_new(value.dptr, value.dsize); + return valstr; } static VALUE @@ -212,21 +282,23 @@ static VALUE fgdbm_index(obj, valstr) VALUE obj, valstr; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; + VALUE keystr, valstr2; - Check_Type(valstr, T_STRING); - val.dptr = RSTRING(valstr)->ptr; - val.dsize = RSTRING(valstr)->len; - + StringValue(valstr); GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - if (val.dsize == RSTRING(valstr)->len && - memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) - return rb_tainted_str_new(key.dptr, key.dsize); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + valstr2 = rb_gdbm_fetch2(dbm, keystr); + if (!NIL_P(valstr2) && + RSTRING(valstr)->len == RSTRING(valstr2)->len && + memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr, + RSTRING(valstr)->len) == 0) { + return keystr; + } } return Qnil; } @@ -248,6 +320,36 @@ fgdbm_indexes(argc, argv, obj) return new; } +static VALUE +rb_gdbm_delete(obj, keystr) + VALUE obj, keystr; +{ + datum key; + struct dbmdata *dbmp; + GDBM_FILE dbm; + + rb_secure(4); + StringValue(keystr); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + + if (!gdbm_exists(dbm, key)) { + return Qnil; + } + + if (gdbm_delete(dbm, key)) { + dbmp->di_size = -1; + rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); + } + else if (dbmp->di_size >= 0) { + dbmp->di_size--; + } + return obj; +} + static VALUE fgdbm_delete(obj, keystr) VALUE obj, keystr; @@ -257,7 +359,7 @@ fgdbm_delete(obj, keystr) GDBM_FILE dbm; rb_secure(4); - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; @@ -283,7 +385,6 @@ static VALUE fgdbm_shift(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; VALUE keystr, valstr; @@ -292,13 +393,11 @@ fgdbm_shift(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - key = gdbm_firstkey(dbm); - if (!key.dptr) return Qnil; - val = gdbm_fetch_1(dbm, key); - gdbm_delete(dbm, key); + keystr = rb_gdbm_firstkey(dbm); + if (NIL_P(keystr)) return Qnil; + valstr = rb_gdbm_fetch2(dbm, keystr); + rb_gdbm_delete(obj, keystr); - keystr = rb_tainted_str_new(key.dptr, key.dsize); - valstr = rb_tainted_str_new(val.dptr, val.dsize); return rb_assoc_new(keystr, valstr); } @@ -306,24 +405,32 @@ static VALUE fgdbm_delete_if(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; VALUE keystr, valstr; + VALUE ret, ary = rb_ary_new(); + int i, status = 0, n; rb_secure(4); GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - keystr = rb_tainted_str_new(key.dptr, key.dsize); - valstr = rb_tainted_str_new(val.dptr, val.dsize); - if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) { - if (gdbm_delete(dbm, key)) { - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - } + n = dbmp->di_size; + dbmp->di_size = -1; + + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + valstr = rb_gdbm_fetch2(dbm, keystr); + ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); + if (status != 0) break; + if (RTEST(ret)) rb_ary_push(ary, keystr); } + + for (i = 0; i < RARRAY(ary)->len; i++) + rb_gdbm_delete(obj, RARRAY(ary)->ptr[i]); + if (status) rb_jump_tag(status); + if (n > 0) dbmp->di_size = n - RARRAY(ary)->len; + return obj; } @@ -331,7 +438,7 @@ static VALUE fgdbm_clear(obj) VALUE obj; { - datum key, nextkey; + datum key; struct dbmdata *dbmp; GDBM_FILE dbm; @@ -339,12 +446,16 @@ fgdbm_clear(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; dbmp->di_size = -1; - for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { - nextkey = gdbm_nextkey(dbm, key); + + while (key = gdbm_firstkey(dbm), key.dptr) { if (gdbm_delete(dbm, key)) { + free(key.dptr); rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); } + free(key.dptr); } + dbmp->di_size = 0; + return obj; } @@ -352,7 +463,6 @@ static VALUE fgdbm_invert(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; VALUE keystr, valstr; @@ -360,10 +470,10 @@ fgdbm_invert(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - keystr = rb_tainted_str_new(key.dptr, key.dsize); - valstr = rb_tainted_str_new(val.dptr, val.dsize); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + valstr = rb_gdbm_fetch2(dbm, keystr); + rb_hash_aset(hash, valstr, keystr); } return hash; @@ -416,12 +526,11 @@ fgdbm_store(obj, keystr, valstr) GDBM_FILE dbm; rb_secure(4); - keystr = rb_obj_as_string(keystr); - + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - valstr = rb_obj_as_string(valstr); + StringValue(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; @@ -440,7 +549,7 @@ static VALUE fgdbm_length(obj) VALUE obj; { - datum key; + datum key, nextkey; struct dbmdata *dbmp; GDBM_FILE dbm; int i = 0; @@ -449,7 +558,9 @@ fgdbm_length(obj) if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { + for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { + nextkey = gdbm_nextkey(dbm, key); + free(key.dptr); i++; } dbmp->di_size = i; @@ -464,20 +575,20 @@ fgdbm_empty_p(obj) datum key; struct dbmdata *dbmp; GDBM_FILE dbm; - int i = 0; GetDBM(obj, dbmp); if (dbmp->di_size < 0) { dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - i++; + key = gdbm_firstkey(dbm); + if (key.dptr) { + free(key.dptr); + return Qfalse; } + return Qtrue; } - else { - i = dbmp->di_size; - } - if (i == 0) return Qtrue; + + if (dbmp->di_size == 0) return Qtrue; return Qfalse; } @@ -485,15 +596,17 @@ static VALUE fgdbm_each_value(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; + VALUE keystr; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - rb_yield(rb_tainted_str_new(val.dptr, val.dsize)); + + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_yield(rb_gdbm_fetch2(dbm, keystr)); } return obj; } @@ -502,14 +615,17 @@ static VALUE fgdbm_each_key(obj) VALUE obj; { - datum key; struct dbmdata *dbmp; GDBM_FILE dbm; + VALUE keystr; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); + + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_yield(rb_str_dup(keystr)); } return obj; } @@ -518,19 +634,18 @@ static VALUE fgdbm_each_pair(obj) VALUE obj; { - datum key, val; GDBM_FILE dbm; struct dbmdata *dbmp; - VALUE keystr, valstr; + VALUE keystr; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - keystr = rb_tainted_str_new(key.dptr, key.dsize); - valstr = rb_tainted_str_new(val.dptr, val.dsize); - rb_yield(rb_assoc_new(keystr, valstr)); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_yield(rb_assoc_new(rb_str_dup(keystr), + rb_gdbm_fetch2(dbm, keystr))); } return obj; @@ -540,17 +655,18 @@ static VALUE fgdbm_keys(obj) VALUE obj; { - datum key; struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE ary; + VALUE keystr, ary; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; ary = rb_ary_new(); - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize)); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_ary_push(ary, keystr); } return ary; @@ -560,18 +676,20 @@ static VALUE fgdbm_values(obj) VALUE obj; { - datum key, val; + datum key, nextkey; struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE ary; + VALUE valstr, ary; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; ary = rb_ary_new(); - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize)); + for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { + nextkey = gdbm_nextkey(dbm, key); + valstr = rb_gdbm_fetch(dbm, key); + free(key.dptr); + rb_ary_push(ary, valstr); } return ary; @@ -585,7 +703,7 @@ fgdbm_has_key(obj, keystr) struct dbmdata *dbmp; GDBM_FILE dbm; - Check_Type(keystr, T_STRING); + StringValue(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; @@ -600,21 +718,24 @@ static VALUE fgdbm_has_value(obj, valstr) VALUE obj, valstr; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; + VALUE keystr, valstr2; - Check_Type(valstr, T_STRING); - val.dptr = RSTRING(valstr)->ptr; - val.dsize = RSTRING(valstr)->len; - + StringValue(valstr); GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - if (val.dsize == RSTRING(valstr)->len && - memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + valstr2 = rb_gdbm_fetch2(dbm, keystr); + + if (!NIL_P(valstr2) && + RSTRING(valstr)->len == RSTRING(valstr2)->len && + memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr, + RSTRING(valstr)->len) == 0) { return Qtrue; + } } return Qfalse; } @@ -623,19 +744,19 @@ static VALUE fgdbm_to_a(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE ary; + VALUE keystr, ary; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; ary = rb_ary_new(); - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize), - rb_tainted_str_new(val.dptr, val.dsize))); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_ary_push(ary, rb_assoc_new(rb_str_dup(keystr), + rb_gdbm_fetch2(dbm, keystr))); } return ary; @@ -675,7 +796,6 @@ fgdbm_set_cachesize(obj, val) { struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE hash; int optval; GetDBM(obj, dbmp); @@ -694,7 +814,6 @@ fgdbm_set_fastmode(obj, val) { struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE hash; int optval; GetDBM(obj, dbmp); @@ -720,7 +839,6 @@ fgdbm_set_syncmode(obj, val) #else struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE hash; int optval; GetDBM(obj, dbmp); @@ -741,19 +859,18 @@ static VALUE fgdbm_to_hash(obj) VALUE obj; { - datum key, val; struct dbmdata *dbmp; GDBM_FILE dbm; - VALUE hash; + VALUE keystr, hash; GetDBM(obj, dbmp); dbm = dbmp->di_dbm; hash = rb_hash_new(); - for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) { - val = gdbm_fetch_1(dbm, key); - rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize), - rb_tainted_str_new(val.dptr, val.dsize)); + for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); + keystr = rb_gdbm_nextkey(dbm, keystr)) { + + rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr)); } return hash; @@ -794,7 +911,7 @@ Init_gdbm() rb_define_method(cGDBM, "each_pair", fgdbm_each_pair, 0); rb_define_method(cGDBM, "keys", fgdbm_keys, 0); rb_define_method(cGDBM, "values", fgdbm_values, 0); - rb_define_method(cGDBM, "shift", fgdbm_shift, 1); + rb_define_method(cGDBM, "shift", fgdbm_shift, 0); rb_define_method(cGDBM, "delete", fgdbm_delete, 1); rb_define_method(cGDBM, "delete_if", fgdbm_delete_if, 0); rb_define_method(cGDBM, "reject!", fgdbm_delete_if, 0); diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c index 9827b784cf..64bba9dab3 100644 --- a/ext/md5/md5init.c +++ b/ext/md5/md5init.c @@ -21,12 +21,10 @@ md5i_update(obj, str) VALUE obj, str; { md5_state_t *md5; - char *p; - int len; - p = rb_str2cstr(str, &len); + StringValue(str); Data_Get_Struct(obj, md5_state_t, md5); - md5_append(md5, p, len); + md5_append(md5, RSTRING(str)->ptr, RSTRING(str)->len); return obj; } @@ -83,13 +81,14 @@ md5i_new(argc, argv, class) VALUE* argv; VALUE class; { - VALUE obj; + VALUE obj, str; md5_state_t *md5; obj = Data_Make_Struct(class, md5_state_t, 0, free, md5); md5_init(md5); + rb_scan_args(argc, argv, "01", &str); if (argc == 1) { - md5i_update(obj, argv[0]); + md5i_update(obj, str); } return obj; diff --git a/file.c b/file.c index 9f10a0faf8..c8f27acf08 100644 --- a/file.c +++ b/file.c @@ -86,7 +86,7 @@ apply2files(func, vargs, arg) for (i=0; ilen; i++) { path = args->ptr[i]; - SafeStr(path); + SafeStringValue(path); if ((*func)(RSTRING(path)->ptr, arg) < 0) rb_sys_fail(RSTRING(path)->ptr); } @@ -110,7 +110,8 @@ rb_file_path(obj) #endif static VALUE -stat_new(st) +stat_new_0(klass, st) + VALUE klass; struct stat *st; { struct stat *nst; @@ -118,7 +119,14 @@ stat_new(st) nst = ALLOC(struct stat); *nst = *st; - return Data_Wrap_Struct(rb_cStat, NULL, free, nst); + return Data_Wrap_Struct(klass, NULL, free, nst); +} + +static VALUE +stat_new(st) + struct stat *st; +{ + return stat_new_0(rb_cStat, st); } static struct stat* @@ -149,42 +157,42 @@ static VALUE rb_stat_dev(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_dev); + return INT2NUM(get_stat(self)->st_dev); } static VALUE rb_stat_ino(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_ino); + return ULONG2NUM(get_stat(self)->st_ino); } static VALUE rb_stat_mode(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_mode); + return UINT2NUM(get_stat(self)->st_mode); } static VALUE rb_stat_nlink(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_nlink); + return UINT2NUM(get_stat(self)->st_nlink); } static VALUE rb_stat_uid(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_uid); + return UINT2NUM(get_stat(self)->st_uid); } static VALUE rb_stat_gid(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_gid); + return UINT2NUM(get_stat(self)->st_gid); } static VALUE @@ -192,7 +200,7 @@ rb_stat_rdev(self) VALUE self; { #ifdef HAVE_ST_RDEV - return INT2FIX((int)get_stat(self)->st_rdev); + return ULONG2NUM(get_stat(self)->st_rdev); #else return INT2FIX(0); #endif @@ -202,7 +210,7 @@ static VALUE rb_stat_size(self) VALUE self; { - return INT2FIX((int)get_stat(self)->st_size); + return LONG2NUM(get_stat(self)->st_size); } static VALUE @@ -210,7 +218,7 @@ rb_stat_blksize(self) VALUE self; { #ifdef HAVE_ST_BLKSIZE - return INT2FIX((int)get_stat(self)->st_blksize); + return ULONG2NUM(get_stat(self)->st_blksize); #else return INT2FIX(0); #endif @@ -221,7 +229,7 @@ rb_stat_blocks(self) VALUE self; { #ifdef HAVE_ST_BLOCKS - return INT2FIX((int)get_stat(self)->st_blocks); + return ULONG2NUM(get_stat(self)->st_blocks); #else return INT2FIX(0); #endif @@ -306,7 +314,7 @@ rb_stat(file, st) GetOpenFile(file, fptr); return fstat(fileno(fptr->f), st); } - SafeStr(file); + SafeStringValue(file); #if defined DJGPP if (RSTRING(file)->len == 0) return -1; #endif @@ -314,12 +322,12 @@ rb_stat(file, st) } static VALUE -rb_file_s_stat(obj, fname) - VALUE obj, fname; +rb_file_s_stat(klass, fname) + VALUE klass, fname; { struct stat st; - SafeStr(fname); + SafeStringValue(fname); if (stat(RSTRING(fname)->ptr, &st) == -1) { rb_sys_fail(RSTRING(fname)->ptr); } @@ -341,19 +349,19 @@ rb_io_stat(obj) } static VALUE -rb_file_s_lstat(obj, fname) - VALUE obj, fname; +rb_file_s_lstat(klass, fname) + VALUE klass, fname; { #ifdef HAVE_LSTAT struct stat st; - SafeStr(fname); + SafeStringValue(fname); if (lstat(RSTRING(fname)->ptr, &st) == -1) { rb_sys_fail(RSTRING(fname)->ptr); } return stat_new(&st); #else - return rb_file_s_stat(obj, fname); + return rb_file_s_stat(klass, fname); #endif } @@ -500,7 +508,7 @@ test_l(obj, fname) #ifdef S_ISLNK struct stat st; - SafeStr(fname); + SafeStringValue(fname); if (lstat(RSTRING(fname)->ptr, &st) < 0) return Qfalse; if (S_ISLNK(st.st_mode)) return Qtrue; #endif @@ -588,7 +596,7 @@ static VALUE test_r(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (eaccess(RSTRING(fname)->ptr, R_OK) < 0) return Qfalse; return Qtrue; } @@ -597,7 +605,7 @@ static VALUE test_R(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (access(RSTRING(fname)->ptr, R_OK) < 0) return Qfalse; return Qtrue; } @@ -606,7 +614,7 @@ static VALUE test_w(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (eaccess(RSTRING(fname)->ptr, W_OK) < 0) return Qfalse; return Qtrue; } @@ -615,7 +623,7 @@ static VALUE test_W(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (access(RSTRING(fname)->ptr, W_OK) < 0) return Qfalse; return Qtrue; } @@ -624,7 +632,7 @@ static VALUE test_x(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (eaccess(RSTRING(fname)->ptr, X_OK) < 0) return Qfalse; return Qtrue; } @@ -633,7 +641,7 @@ static VALUE test_X(obj, fname) VALUE obj, fname; { - SafeStr(fname); + SafeStringValue(fname); if (access(RSTRING(fname)->ptr, X_OK) < 0) return Qfalse; return Qtrue; } @@ -712,13 +720,14 @@ test_grpowned(obj, fname) #if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX) static VALUE -check3rdbyte(file, mode) - const char *file; +check3rdbyte(fname, mode) + VALUE fname; int mode; { struct stat st; - if (stat(file, &st) < 0) return Qfalse; + SafeStringValue(fname); + if (stat(RSTRING(fname)->ptr, &st) < 0) return Qfalse; if (st.st_mode & mode) return Qtrue; return Qfalse; } @@ -729,8 +738,7 @@ test_suid(obj, fname) VALUE obj, fname; { #ifdef S_ISUID - SafeStr(fname); - return check3rdbyte(RSTRING(fname)->ptr, S_ISUID); + return check3rdbyte(fname, S_ISUID); #else return Qfalse; #endif @@ -741,8 +749,7 @@ test_sgid(obj, fname) VALUE obj, fname; { #ifdef S_ISGID - SafeStr(fname); - return check3rdbyte(RSTRING(fname)->ptr, S_ISGID); + return check3rdbyte(fname, S_ISGID); #else return Qfalse; #endif @@ -753,15 +760,15 @@ test_sticky(obj, fname) VALUE obj, fname; { #ifdef S_ISVTX - return check3rdbyte(STR2CSTR(fname), S_ISVTX); + return check3rdbyte(fname, S_ISVTX); #else return Qnil; #endif } static VALUE -rb_file_s_size(obj, fname) - VALUE obj, fname; +rb_file_s_size(klass, fname) + VALUE klass, fname; { struct stat st; @@ -778,9 +785,11 @@ rb_file_ftype(st) if (S_ISREG(st->st_mode)) { t = "file"; - } else if (S_ISDIR(st->st_mode)) { + } + else if (S_ISDIR(st->st_mode)) { t = "directory"; - } else if (S_ISCHR(st->st_mode)) { + } + else if (S_ISCHR(st->st_mode)) { t = "characterSpecial"; } #ifdef S_ISBLK @@ -811,12 +820,12 @@ rb_file_ftype(st) } static VALUE -rb_file_s_ftype(obj, fname) - VALUE obj, fname; +rb_file_s_ftype(klass, fname) + VALUE klass, fname; { struct stat st; - SafeStr(fname); + SafeStringValue(fname); if (lstat(RSTRING(fname)->ptr, &st) == -1) { rb_sys_fail(RSTRING(fname)->ptr); } @@ -825,8 +834,8 @@ rb_file_s_ftype(obj, fname) } static VALUE -rb_file_s_atime(obj, fname) - VALUE obj, fname; +rb_file_s_atime(klass, fname) + VALUE klass, fname; { struct stat st; @@ -850,8 +859,8 @@ rb_file_atime(obj) } static VALUE -rb_file_s_mtime(obj, fname) - VALUE obj, fname; +rb_file_s_mtime(klass, fname) + VALUE klass, fname; { struct stat st; @@ -875,8 +884,8 @@ rb_file_mtime(obj) } static VALUE -rb_file_s_ctime(obj, fname) - VALUE obj, fname; +rb_file_s_ctime(klass, fname) + VALUE klass, fname; { struct stat st; @@ -1045,7 +1054,7 @@ rb_file_chown(obj, owner, group) return INT2FIX(0); } -#if defined(HAVE_LCHOWN) +#if defined(HAVE_LCHOWN) && !defined(__CHECKER__) static void lchown_internal(path, args) const char *path; @@ -1176,11 +1185,11 @@ rb_file_s_utime(argc, argv) #endif static VALUE -rb_file_s_link(obj, from, to) - VALUE obj, from, to; +rb_file_s_link(klass, from, to) + VALUE klass, from, to; { - SafeStr(from); - SafeStr(to); + SafeStringValue(from); + SafeStringValue(to); if (link(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) rb_sys_fail(RSTRING(from)->ptr); @@ -1188,12 +1197,12 @@ rb_file_s_link(obj, from, to) } static VALUE -rb_file_s_symlink(obj, from, to) - VALUE obj, from, to; +rb_file_s_symlink(klass, from, to) + VALUE klass, from, to; { #ifdef HAVE_SYMLINK - SafeStr(from); - SafeStr(to); + SafeStringValue(from); + SafeStringValue(to); if (symlink(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) rb_sys_fail(RSTRING(from)->ptr); @@ -1205,14 +1214,14 @@ rb_file_s_symlink(obj, from, to) } static VALUE -rb_file_s_readlink(obj, path) - VALUE obj, path; +rb_file_s_readlink(klass, path) + VALUE klass, path; { #ifdef HAVE_READLINK char buf[MAXPATHLEN]; int cc; - SafeStr(path); + SafeStringValue(path); if ((cc = readlink(RSTRING(path)->ptr, buf, MAXPATHLEN)) < 0) rb_sys_fail(RSTRING(path)->ptr); @@ -1232,8 +1241,8 @@ unlink_internal(path) } static VALUE -rb_file_s_unlink(obj, args) - VALUE obj, args; +rb_file_s_unlink(klass, args) + VALUE klass, args; { int n; @@ -1242,11 +1251,11 @@ rb_file_s_unlink(obj, args) } static VALUE -rb_file_s_rename(obj, from, to) - VALUE obj, from, to; +rb_file_s_rename(klass, from, to) + VALUE klass, from, to; { - SafeStr(from); - SafeStr(to); + SafeStringValue(from); + SafeStringValue(to); if (rename(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) { #if defined __CYGWIN__ @@ -1299,7 +1308,7 @@ rb_file_s_expand_path(argc, argv) rb_scan_args(argc, argv, "11", &fname, &dname); tainted = OBJ_TAINTED(fname); - s = STR2CSTR(fname); + s = StringValuePtr(fname); p = buf; if (s[0] == '~') { if (isdirsep(s[1]) || s[1] == '\0') { @@ -1448,9 +1457,9 @@ rb_file_s_basename(argc, argv) int f; if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) { - ext = STR2CSTR(fext); + ext = StringValuePtr(fext); } - name = STR2CSTR(fname); + name = StringValuePtr(fname); p = strrchr(name, '/'); if (!p) { if (NIL_P(fext) || !(f = rmext(name, ext))) @@ -1471,13 +1480,13 @@ rb_file_s_basename(argc, argv) } static VALUE -rb_file_s_dirname(obj, fname) - VALUE obj, fname; +rb_file_s_dirname(klass, fname) + VALUE klass, fname; { char *name, *p; VALUE dirname; - name = STR2CSTR(fname); + name = StringValuePtr(fname); p = strrchr(name, '/'); if (!p) { return rb_str_new2("."); @@ -1490,8 +1499,8 @@ rb_file_s_dirname(obj, fname) } static VALUE -rb_file_s_split(obj, path) - VALUE obj, path; +rb_file_s_split(klass, path) + VALUE klass, path; { return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path)); } @@ -1499,18 +1508,18 @@ rb_file_s_split(obj, path) static VALUE separator; static VALUE -rb_file_s_join(obj, args) - VALUE obj, args; +rb_file_s_join(klass, args) + VALUE klass, args; { return rb_ary_join(args, separator); } static VALUE -rb_file_s_truncate(obj, path, len) - VALUE obj, path, len; +rb_file_s_truncate(klass, path, len) + VALUE klass, path, len; { rb_secure(2); - SafeStr(path); + SafeStringValue(path); #ifdef HAVE_TRUNCATE if (truncate(RSTRING(path)->ptr, NUM2INT(len)) < 0) @@ -1655,7 +1664,7 @@ test_check(n, argc, argv) for (i=1; iptr, &st) == -1) { + rb_sys_fail(RSTRING(fname)->ptr); + } + s = stat_new_0(klass, &st); + rb_obj_call_init(s, 1, &fname); + return s; +} + +static VALUE +rb_stat_init(klass, fname) + VALUE klass, fname; +{ + /* do nothing */ + return Qnil; +} + static VALUE rb_stat_ftype(obj) VALUE obj; @@ -2210,7 +2243,7 @@ rb_find_file(file) if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) { rb_raise(rb_eSecurityError, "loading from unsafe file %s", file); } - file = STR2CSTR(fname); + file = StringValuePtr(fname); } if (rb_load_path) { @@ -2220,13 +2253,13 @@ rb_find_file(file) vpath = rb_ary_new(); for (i=0;ilen;i++) { VALUE str = RARRAY(rb_load_path)->ptr[i]; - SafeStr(str); + SafeStringValue(str); if (RSTRING(str)->len > 0) { rb_ary_push(vpath, str); } } vpath = rb_ary_join(vpath, rb_str_new2(PATH_SEP)); - path = STR2CSTR(vpath); + path = StringValuePtr(vpath); if (rb_safe_level() >= 2 && !rb_path_check(path)) { rb_raise(rb_eSecurityError, "loading from unsafe path %s", path); } @@ -2350,6 +2383,8 @@ Init_File() rb_define_global_function("test", rb_f_test, -1); rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject); + rb_define_singleton_method(rb_cStat, "new", rb_stat_s_new, 1); + rb_define_method(rb_cStat, "initialize", rb_stat_init, 1); rb_include_module(rb_cStat, rb_mComparable); diff --git a/gc.c b/gc.c index 091138ee04..5f72bdc51e 100644 --- a/gc.c +++ b/gc.c @@ -1147,7 +1147,7 @@ rm_final(os, proc) static VALUE finals() { - rb_warn("ObjectSpace::finals is deprecated"); + rb_warn("ObjectSpace::finalizers is deprecated"); return finalizers; } @@ -1283,7 +1283,7 @@ id2ref(obj, id) unsigned long ptr, p0; rb_secure(4); - p0 = ptr = NUM2UINT(id); + p0 = ptr = NUM2ULONG(id); if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; @@ -1331,37 +1331,3 @@ Init_GC() rb_gc_unregister_address(&rb_mObSpace); finalizers = rb_ary_new(); } - -#undef xmalloc -#undef xcalloc -#undef xrealloc -#undef xfree - -void* -xmalloc(size) - long size; -{ - return ruby_xmalloc(size); -} - -void* -xcalloc(n,size) - long n,size; -{ - return ruby_xcalloc(n, size); -} - -void* -xrealloc(ptr,size) - void *ptr; - long size; -{ - return ruby_xrealloc(ptr, size); -} - -void -xfree(ptr) - void *ptr; -{ - ruby_xfree(ptr); -} diff --git a/hash.c b/hash.c index 57debb7c51..bb7cf77d11 100644 --- a/hash.c +++ b/hash.c @@ -858,12 +858,12 @@ static VALUE env_delete(obj, name) VALUE obj, name; { - int len; char *nam, *val; rb_secure(4); - nam = rb_str2cstr(name, &len); - if (strlen(nam) != len) { + StringValue(name); + nam = RSTRING(name)->ptr; + if (strlen(nam) != RSTRING(name)->len) { rb_raise(rb_eArgError, "bad environment variable name"); } val = getenv(nam); @@ -895,8 +895,9 @@ rb_f_getenv(obj, name) char *nam, *env; int len; - nam = rb_str2cstr(name, &len); - if (strlen(nam) != len) { + StringValue(name); + nam = RSTRING(name)->ptr; + if (strlen(nam) != RSTRING(name)->len) { rb_raise(rb_eArgError, "bad environment variable name"); } env = getenv(nam); @@ -915,11 +916,11 @@ env_fetch(argc, argv) { VALUE key, if_none; char *nam, *env; - int len; rb_scan_args(argc, argv, "11", &key, &if_none); - nam = rb_str2cstr(key, &len); - if (strlen(nam) != len) { + StringValue(key); + nam = RSTRING(key)->ptr; + if (strlen(nam) != RSTRING(key)->len) { rb_raise(rb_eArgError, "bad environment variable name"); } env = getenv(nam); @@ -1115,11 +1116,13 @@ rb_f_setenv(obj, nm, val) return Qnil; } - name = rb_str2cstr(nm, &nlen); - value = rb_str2cstr(val, &vlen); - if (strlen(name) != nlen) + StringValue(nm); + StringValue(val); + name = RSTRING(nm)->ptr; + value = RSTRING(val)->ptr; + if (strlen(name) != RSTRING(nm)->len) rb_raise(rb_eArgError, "bad environment variable name"); - if (strlen(value) != vlen) + if (strlen(value) != RSTRING(val)->len) rb_raise(rb_eArgError, "bad environment variable value"); ruby_setenv(name, value); @@ -1335,8 +1338,12 @@ static VALUE env_has_key(env, key) VALUE env, key; { - if (TYPE(key) != T_STRING) return Qfalse; - if (getenv(STR2CSTR(key))) return Qtrue; + char *s; + + s = StringValuePtr(key); + if (strlen(s) != RSTRING(key)->len) + rb_raise(rb_eArgError, "bad environment variable name"); + if (getenv(s)) return Qtrue; return Qfalse; } diff --git a/intern.h b/intern.h index 9e89ae9f2b..7594b8a362 100644 --- a/intern.h +++ b/intern.h @@ -47,7 +47,7 @@ VALUE rb_ary_concat _((VALUE, VALUE)); VALUE rb_ary_assoc _((VALUE, VALUE)); VALUE rb_ary_rassoc _((VALUE, VALUE)); VALUE rb_ary_includes _((VALUE, VALUE)); -VALUE rb_protect_inspect _((VALUE(*)(),VALUE,VALUE)); +VALUE rb_protect_inspect _((VALUE(*)(VALUE,VALUE),VALUE,VALUE)); VALUE rb_inspecting_p _((VALUE)); /* bignum.c */ VALUE rb_big_clone _((VALUE)); @@ -78,6 +78,8 @@ VALUE rb_big_lshift _((VALUE, VALUE)); VALUE rb_big_rand _((VALUE, double)); /* class.c */ VALUE rb_class_new _((VALUE)); +VALUE rb_mod_clone _((VALUE)); +VALUE rb_mod_dup _((VALUE)); VALUE rb_singleton_class_new _((VALUE)); VALUE rb_singleton_class_clone _((VALUE)); void rb_singleton_class_attached _((VALUE,VALUE)); @@ -90,13 +92,13 @@ VALUE rb_class_instance_methods _((int, VALUE*, VALUE)); VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE)); VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE)); VALUE rb_obj_singleton_methods _((VALUE)); -void rb_define_method_id _((VALUE, ID, VALUE (*)(), int)); +void rb_define_method_id _((VALUE, ID, VALUE (*)(ANYARGS), int)); void rb_frozen_class_p _((VALUE)); void rb_undef _((VALUE, ID)); -void rb_define_protected_method _((VALUE, const char*, VALUE (*)(), int)); -void rb_define_private_method _((VALUE, const char*, VALUE (*)(), int)); -void rb_define_singleton_method _((VALUE,const char*,VALUE(*)(),int)); -void rb_define_private_method _((VALUE,const char*,VALUE(*)(),int)); +void rb_define_protected_method _((VALUE, const char*, VALUE (*)(ANYARGS), int)); +void rb_define_private_method _((VALUE, const char*, VALUE (*)(ANYARGS), int)); +void rb_define_singleton_method _((VALUE, const char*, VALUE(*)(ANYARGS), int)); +void rb_define_private_method _((VALUE, const char*, VALUE(*)(ANYARGS), int)); VALUE rb_singleton_class _((VALUE)); /* enum.c */ VALUE rb_enum_length _((VALUE)); @@ -141,8 +143,8 @@ VALUE rb_f_require _((VALUE, VALUE)); void rb_obj_call_init _((VALUE, int, VALUE*)); VALUE rb_class_new_instance _((int, VALUE*, VALUE)); VALUE rb_f_lambda _((void)); -VALUE rb_protect _((VALUE (*)(), VALUE, int*)); -void rb_set_end_proc _((void (*)(), VALUE)); +VALUE rb_protect _((VALUE (*)(VALUE), VALUE, int*)); +void rb_set_end_proc _((void (*)(void), VALUE)); void rb_mark_end_proc _((void)); void rb_exec_end_proc _((void)); void ruby_finalize _((void)); @@ -161,13 +163,13 @@ void rb_thread_sleep_forever _((void)); VALUE rb_thread_stop _((void)); VALUE rb_thread_wakeup _((VALUE)); VALUE rb_thread_run _((VALUE)); -VALUE rb_thread_create _((VALUE (*)(), void*)); +VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*)); int rb_thread_scope_shared_p _((void)); void rb_thread_interrupt _((void)); void rb_thread_trap_eval _((VALUE, int)); void rb_thread_signal_raise _((char*)); -int rb_thread_select(); -void rb_thread_wait_for(); +int rb_thread_select(ANYARGS); +void rb_thread_wait_for(ANYARGS); VALUE rb_thread_current _((void)); VALUE rb_thread_main _((void)); VALUE rb_thread_local_aref _((VALUE, ID)); @@ -258,6 +260,7 @@ VALUE rb_backref_get _((void)); void rb_backref_set _((VALUE)); VALUE rb_lastline_get _((void)); void rb_lastline_set _((VALUE)); +VALUE rb_sym_all_symbols _((void)); /* process.c */ int rb_proc_exec _((const char*)); void rb_syswait _((int)); @@ -296,7 +299,7 @@ VALUE rb_f_kill _((int, VALUE*)); void rb_gc_mark_trap_list _((void)); #ifdef POSIX_SIGNAL #define posix_signal ruby_posix_signal -void posix_signal _((int, void (*)())); +void posix_signal _((int, RETSIGTYPE (*)(int))); #endif void rb_trap_exit _((void)); void rb_trap_exec _((void)); @@ -337,7 +340,7 @@ VALUE rb_struct_aref _((VALUE, VALUE)); VALUE rb_struct_aset _((VALUE, VALUE, VALUE)); VALUE rb_struct_getmember _((VALUE, ID)); /* time.c */ -VALUE rb_time_new(); +VALUE rb_time_new(ANYARGS); /* variable.c */ VALUE rb_mod_name _((VALUE)); VALUE rb_class_path _((VALUE)); diff --git a/io.c b/io.c index 237f9d55fd..08e8fd6e7a 100644 --- a/io.c +++ b/io.c @@ -27,6 +27,10 @@ # define NO_LONG_FNAME #endif +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(sun) +# define USE_SETVBUF +#endif + #include #if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) #include @@ -606,11 +610,10 @@ rb_io_gets_internal(argc, argv, io) VALUE rs; if (argc == 0) { - rs = rb_str_to_str(rb_rs); + rs = rb_default_rs; } else { rb_scan_args(argc, argv, "1", &rs); - if (!NIL_P(rs)) rs = rb_str_to_str(rs); } if (NIL_P(rs)) { @@ -621,6 +624,7 @@ rb_io_gets_internal(argc, argv, io) return rb_io_gets(io); } else { + StringValue(rs); rslen = RSTRING(rs)->len; if (rslen == 0) { rsptr = "\n\n"; @@ -1379,6 +1383,10 @@ rb_fopen(fname, mode) rb_sys_fail(fname); } } +#ifdef USE_SETVBUF + if (setvbuf(file, NULL, _IOFBF, 0) != 0) + rb_warn("setvbuf() can't be honered for %s", fname); +#endif #ifdef __human68k__ fmode(file, _IOTEXT); #endif @@ -1402,6 +1410,11 @@ rb_fdopen(fd, mode) rb_sys_fail(0); } } + +#ifdef USE_SETVBUF + if (setvbuf(file, NULL, _IOFBF, 0) != 0) + rb_warn("setvbuf() can't be honered (fd=%d)", fd); +#endif return file; } @@ -1685,9 +1698,9 @@ rb_io_popen(str, argc, argv, klass) mode = "r"; } else { - mode = STR2CSTR(pmode); + mode = StringValuePtr(pmode); } - SafeStr(pname); + SafeStringValue(pname); port = pipe_open(str, mode); if (NIL_P(port)) { /* child */ @@ -1715,7 +1728,7 @@ rb_io_s_popen(argc, argv, klass) char *str = 0; if (argc >= 1) { - str = STR2CSTR(argv[0]); + str = StringValuePtr(argv[0]); } return rb_io_popen(str, argc, argv, klass); } @@ -1732,7 +1745,7 @@ rb_file_s_open(argc, argv, klass) NEWOBJ(io, struct RFile); OBJSETUP(io, klass, T_FILE); rb_scan_args(argc, argv, "12", &fname, &vmode, &perm); - SafeStr(fname); + SafeStringValue(fname); path = RSTRING(fname)->ptr; RFILE(io)->fptr = 0; @@ -1743,7 +1756,7 @@ rb_file_s_open(argc, argv, klass) file = rb_file_sysopen_internal((VALUE)io, path, flags, fmode); } else { - mode = NIL_P(vmode) ? "r" : STR2CSTR(vmode); + mode = NIL_P(vmode) ? "r" : StringValuePtr(vmode); file = rb_file_open_internal((VALUE)io, RSTRING(fname)->ptr, mode); } @@ -1760,7 +1773,7 @@ rb_f_open(argc, argv) VALUE *argv; { if (argc >= 1) { - char *str = STR2CSTR(argv[0]); + char *str = StringValuePtr(argv[0]); if (str[0] == '|') { return rb_io_popen(str+1, argc, argv, rb_cIO); @@ -1897,9 +1910,9 @@ rb_io_reopen(argc, argv, file) } } - SafeStr(fname); + SafeStringValue(fname); if (!NIL_P(nmode)) { - mode = STR2CSTR(nmode); + mode = StringValuePtr(nmode); } else { mode = "r"; @@ -1919,12 +1932,18 @@ rb_io_reopen(argc, argv, file) fclose(fptr->f2); fptr->f2 = 0; } + return file; } if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == 0) { rb_sys_fail(fptr->path); } +#ifdef USE_SETVBUF + if (setvbuf(fptr->f, NULL, _IOFBF, 0) != 0) + rb_warn("setvbuf() can't be honered for %s", RSTRING(fname)->ptr); +#endif + if (fptr->f2) { if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == 0) { rb_sys_fail(fptr->path); @@ -2255,7 +2274,7 @@ set_outfile(val, var, orig, stdf) if (val == *var) return; - if (TYPE(*var) == T_FILE) { + if (TYPE(*var) == T_FILE && !rb_io_closed(*var)) { rb_io_flush(*var); } if (TYPE(val) != T_FILE) { @@ -2361,7 +2380,7 @@ rb_io_initialize(argc, argv, io) RFILE(io)->fptr = 0; } if (rb_scan_args(argc, argv, "11", &fnum, &mode) == 2) { - SafeStr(mode); + SafeStringValue(mode); m = RSTRING(mode)->ptr; } MakeOpenFile(io, fp); @@ -2381,7 +2400,7 @@ rb_file_initialize(argc, argv, io) char *path, *mode; rb_scan_args(argc, argv, "12", &fname, &vmode, &perm); - SafeStr(fname); + SafeStringValue(fname); path = RSTRING(fname)->ptr; if (RFILE(io)->fptr) { @@ -2400,7 +2419,7 @@ rb_file_initialize(argc, argv, io) mode = "r"; } else { - mode = STR2CSTR(vmode); + mode = StringValuePtr(vmode); } file = rb_file_open_internal(io, RSTRING(fname)->ptr, mode); } @@ -2424,7 +2443,7 @@ rb_io_s_for_fd(argc, argv, klass) OBJSETUP(io, klass, T_FILE); if (rb_scan_args(argc, argv, "11", &fnum, &mode) == 2) { - SafeStr(mode); + SafeStringValue(mode); m = RSTRING(mode)->ptr; } MakeOpenFile(io, fp); @@ -2482,7 +2501,7 @@ next_argv() next_p = 0; if (RARRAY(rb_argv)->len > 0) { filename = rb_ary_shift(rb_argv); - fn = STR2CSTR(filename); + fn = StringValuePtr(filename); if (strlen(fn) == 1 && fn[0] == '-') { current_file = rb_stdin; if (ruby_inplace_mode) { @@ -2681,7 +2700,7 @@ rb_f_backquote(obj, str) { VALUE port, result; - SafeStr(str); + SafeStringValue(str); port = pipe_open(RSTRING(str)->ptr, "r"); if (NIL_P(port)) return rb_str_new(0,0); result = read_all(port); @@ -2885,7 +2904,7 @@ rb_io_ctl(io, req, arg, io_p) narg = 1; } else { - arg = rb_str_to_str(arg); + StringValue(arg); #ifdef IOCPARM_MASK #ifndef IOCPARM_LEN @@ -2984,10 +3003,11 @@ rb_f_syscall(argc, argv) arg[i] = (unsigned long)NUM2INT(*argv); } else { - VALUE v = rb_str_to_str(*argv); + VALUE v = *argv; + StringValue(v); rb_str_modify(v); - arg[i] = (unsigned long)RSTRING(*argv)->ptr; + arg[i] = (unsigned long)RSTRING(v)->ptr; } argv++; i++; @@ -3107,7 +3127,7 @@ rb_io_s_foreach(argc, argv, io) struct foreach_arg arg; rb_scan_args(argc, argv, "11", &fname, &arg.sep); - SafeStr(fname); + SafeStringValue(fname); arg.argc = argc - 1; arg.io = rb_io_open(RSTRING(fname)->ptr, "r"); @@ -3132,7 +3152,7 @@ rb_io_s_readlines(argc, argv, io) struct foreach_arg arg; rb_scan_args(argc, argv, "11", &fname, &arg.sep); - SafeStr(fname); + SafeStringValue(fname); arg.argc = argc - 1; arg.io = rb_io_open(RSTRING(fname)->ptr, "r"); @@ -3157,7 +3177,7 @@ rb_io_s_read(argc, argv, io) struct foreach_arg arg; rb_scan_args(argc, argv, "12", &fname, &arg.sep, &offset); - SafeStr(fname); + SafeStringValue(fname); arg.argc = argc ? 1 : 0; arg.io = rb_io_open(RSTRING(fname)->ptr, "r"); @@ -3256,7 +3276,7 @@ argf_read(argc, argv) if (!next_argv()) return str; if (TYPE(current_file) != T_FILE) { tmp = argf_forward(); - STR2CSTR(tmp); + StringValue(tmp); } else { tmp = io_read(argc, argv, current_file); @@ -3410,11 +3430,13 @@ static void opt_i_set(val) VALUE val; { + if (ruby_inplace_mode) free(ruby_inplace_mode); if (!RTEST(val)) { ruby_inplace_mode = 0; return; } - ruby_inplace_mode = STR2CSTR(val); + StringValue(val); + ruby_inplace_mode = strdup(RSTRING(val)->ptr); } void @@ -3463,9 +3485,9 @@ Init_IO() rb_rs = rb_default_rs = rb_str_new2("\n"); rb_output_rs = Qnil; rb_global_variable(&rb_default_rs); OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */ - rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter); - rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter); - rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter); + rb_define_variable("$/", &rb_rs); + rb_define_variable("$-0", &rb_rs); + rb_define_variable("$\\", &rb_output_rs); rb_define_hooked_variable("$.", &lineno, 0, lineno_setter); rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set); diff --git a/marshal.c b/marshal.c index a1ff9e2b0e..108379da41 100644 --- a/marshal.c +++ b/marshal.c @@ -18,7 +18,7 @@ double strtod(); #endif -#if SIZEOF_INT*2 <= SIZEOF_LONG_LONG || SIZEOF_INT*2 <= SIZEOF___INT64 +#if SIZEOF_INT*2 <= SIZEOF_LONG_LONG || SIZEOF_ING*2 <= SIZEOF_LONG typedef unsigned int BDIGIT; #define SIZEOF_BDIGITS SIZEOF_INT #else @@ -188,7 +188,7 @@ w_float(d, arg) { char buf[100]; - sprintf(buf, "%.12g", d); + sprintf(buf, "%.16g", d); w_bytes(buf, strlen(buf), arg); } @@ -1042,12 +1042,11 @@ marshal_load(argc, argv) arg.taint = Qtrue; } else if (rb_respond_to(port, rb_intern("to_str"))) { - int len; - + arg.taint = OBJ_TAINTED(port); /* original taintedness */ + StringValue(port); /* possible conversion */ arg.fp = 0; - arg.ptr = rb_str2cstr(port, &len); - arg.end = arg.ptr + len; - arg.taint = OBJ_TAINTED(port); + arg.ptr = RSTRING(port)->ptr; + arg.end = arg.ptr + RSTRING(port)->len; } else { rb_raise(rb_eTypeError, "instance of IO needed"); diff --git a/node.h b/node.h index c906aa7c4e..f64e368ad5 100644 --- a/node.h +++ b/node.h @@ -131,7 +131,7 @@ typedef struct RNode { struct RNode *node; ID id; VALUE value; - VALUE (*cfunc)(); + VALUE (*cfunc)(ANYARGS); ID *tbl; } u1; union { @@ -237,7 +237,7 @@ typedef struct RNode { #define NEW_CFUNC(f,c) rb_node_newnode(NODE_CFUNC,f,c,0) #define NEW_IFUNC(f,c) rb_node_newnode(NODE_IFUNC,f,c,0) #define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2)) -#define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),cur_cref,(b)) +#define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),0,(b)) #define NEW_BLOCK(a) rb_node_newnode(NODE_BLOCK,a,0,0) #define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e) #define NEW_UNLESS(c,t,e) NEW_IF(c,e,t) @@ -309,14 +309,12 @@ typedef struct RNode { #define NEW_ALIAS(n,o) rb_node_newnode(NODE_ALIAS,o,n,0) #define NEW_VALIAS(n,o) rb_node_newnode(NODE_VALIAS,o,n,0) #define NEW_UNDEF(i) rb_node_newnode(NODE_UNDEF,0,i,0) -#define NEW_CLASS(n,b,s) rb_node_newnode(NODE_CLASS,n,NEW_CBODY(b),(s)) -#define NEW_SCLASS(r,b) rb_node_newnode(NODE_SCLASS,r,NEW_CBODY(b),0) -#define NEW_MODULE(n,b) rb_node_newnode(NODE_MODULE,n,NEW_CBODY(b),0) +#define NEW_CLASS(n,b,s) rb_node_newnode(NODE_CLASS,n,NEW_SCOPE(b),(s)) +#define NEW_SCLASS(r,b) rb_node_newnode(NODE_SCLASS,r,NEW_SCOPE(b),0) +#define NEW_MODULE(n,b) rb_node_newnode(NODE_MODULE,n,NEW_SCOPE(b),0) #define NEW_COLON2(c,i) rb_node_newnode(NODE_COLON2,c,i,0) #define NEW_COLON3(i) rb_node_newnode(NODE_COLON3,0,i,0) -#define NEW_CREF0() (cur_cref=RNODE(ruby_frame->cbase)) -#define NEW_CREF() (cur_cref=rb_node_newnode(NODE_CREF,0,0,cur_cref)) -#define NEW_CBODY(b) (cur_cref->nd_body=NEW_SCOPE(b),cur_cref) +#define NEW_CREF(c) (rb_node_newnode(NODE_CREF,0,0,c)) #define NEW_DOT2(b,e) rb_node_newnode(NODE_DOT2,b,e,0) #define NEW_DOT3(b,e) rb_node_newnode(NODE_DOT3,b,e,0) #define NEW_ATTRSET(a) rb_node_newnode(NODE_ATTRSET,a,0,0) @@ -342,7 +340,7 @@ NODE *rb_compile_string _((const char*, VALUE, int)); NODE *rb_compile_file _((const char*, VALUE, int)); void rb_add_method _((VALUE, ID, NODE *, int)); -NODE *rb_node_newnode(); +NODE *rb_node_newnode(ANYARGS); struct global_entry *rb_global_entry _((ID)); VALUE rb_gvar_get _((struct global_entry *)); diff --git a/numeric.c b/numeric.c index dc8a788bfc..66ac5645b5 100644 --- a/numeric.c +++ b/numeric.c @@ -56,7 +56,7 @@ coerce_rescue(x) { rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_special_const_p(x[1])? - STR2CSTR(rb_inspect(x[1])): + RSTRING(rb_inspect(x[1]))->ptr: rb_class2name(CLASS_OF(x[1])), rb_class2name(CLASS_OF(x[0]))); return Qnil; /* dummy */ @@ -227,7 +227,8 @@ flo_to_s(flt) memmove(ind+2, ind, len-(ind-buf)+1); ind[0] = '.'; ind[1] = '0'; - } else { + } + else { strcat(buf, ".0"); } } @@ -332,7 +333,7 @@ flodivmod(x, y, divp, modp) double z; modf(x/y, &z); - mod = x - z * x; + mod = x - z * y; } #endif div = (x - mod) / y; @@ -448,6 +449,7 @@ flo_hash(num) int i, hash; d = RFLOAT(num)->value; + if (d == 0) d = fabs(d); c = (char*)&d; for (hash=0, i=0; ivalue == RFLOAT(y)->value) return Qtrue; + if (TYPE(y) == T_FLOAT && RFLOAT(x)->value == RFLOAT(y)->value) { + return Qtrue; } return Qfalse; } @@ -1295,12 +1297,14 @@ static VALUE fix_aref(fix, idx) VALUE fix, idx; { - unsigned long val = FIX2LONG(fix); + long val = FIX2LONG(fix); int i = NUM2INT(idx); - if (i < 0 || sizeof(VALUE)*CHAR_BIT-1 < i) + if (i < 0 || sizeof(VALUE)*CHAR_BIT-1 < i) { + if (val < 0) return INT2FIX(1); return INT2FIX(0); - if (val & (1<ptr, rb_class2name(CLASS_OF(y))); } /* not reached */ @@ -532,36 +530,6 @@ sym_intern(sym) return sym; } -static VALUE -rb_mod_clone(module) - VALUE module; -{ - NEWOBJ(clone, struct RClass); - CLONESETUP(clone, module); - - clone->super = RCLASS(module)->super; - if (RCLASS(module)->iv_tbl) { - clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl); - } - if (RCLASS(module)->m_tbl) { - clone->m_tbl = st_copy(RCLASS(module)->m_tbl); - } - - return (VALUE)clone; -} - -static VALUE -rb_mod_dup(mod) - VALUE mod; -{ - VALUE dup = rb_mod_clone(mod); - OBJSETUP(dup, RBASIC(mod)->klass, BUILTIN_TYPE(mod)); - if (FL_TEST(mod, FL_SINGLETON)) { - FL_SET(dup, FL_SINGLETON); - } - return dup; -} - static VALUE rb_mod_to_s(klass) VALUE klass; @@ -734,7 +702,7 @@ rb_to_id(name) id = SYM2ID(name); break; default: - rb_raise(rb_eTypeError, "%s is not a symbol", STR2CSTR(rb_inspect(name))); + rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING(rb_inspect(name))->ptr); } return id; } @@ -798,14 +766,24 @@ static VALUE rb_mod_const_get(mod, name) VALUE mod, name; { - return rb_const_get(mod, rb_to_id(name)); + ID id = rb_to_id(name); + + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "wrong constant name %s", name); + } + return rb_const_get(mod, id); } static VALUE rb_mod_const_set(mod, name, value) VALUE mod, name, value; { - rb_const_set(mod, rb_to_id(name), value); + ID id = rb_to_id(name); + + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "wrong constant name %s", name); + } + rb_const_set(mod, id, value); return value; } @@ -813,7 +791,12 @@ static VALUE rb_mod_const_defined(mod, name) VALUE mod, name; { - return rb_const_defined_at(mod, rb_to_id(name)); + ID id = rb_to_id(name); + + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "wrong constant name %s", name); + } + return rb_const_defined_at(mod, id); } static VALUE @@ -974,7 +957,7 @@ rb_Float(val) char *q, *p, *end; double d; - q = p = STR2CSTR(val); + q = p = StringValuePtr(val); while (*p && ISSPACE(*p)) p++; again: d = strtod(p, &end); @@ -1054,9 +1037,7 @@ rb_str2cstr(str, len) VALUE str; int *len; { - if (TYPE(str) != T_STRING) { - str = rb_str_to_str(str); - } + StringValue(str); if (len) *len = RSTRING(str)->len; else if (ruby_verbose && RSTRING(str)->len != strlen(RSTRING(str)->ptr)) { rb_warn("string contains \\0 character"); @@ -1232,6 +1213,8 @@ Init_Object() rb_cSymbol = rb_define_class("Symbol", rb_cObject); rb_undef_method(CLASS_OF(rb_cSymbol), "new"); + rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); + 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, "to_int", sym_to_i, 0); diff --git a/pack.c b/pack.c index 8e343c8e22..256fa62eae 100644 --- a/pack.c +++ b/pack.c @@ -339,14 +339,16 @@ pack_pack(ary, fmt) #ifdef NATINT_PACK int natint; /* native integer */ #endif - - p = rb_str2cstr(fmt, &plen); - pend = p + plen; + + StringValue(fmt); + p = RSTRING(fmt)->ptr; + pend = p + RSTRING(fmt)->len; res = rb_str_new(0, 0); items = RARRAY(ary)->len; idx = 0; +#define THISFROM RARRAY(ary)->ptr[idx] #define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (rb_raise(rb_eArgError, toofew),0)) while (p < pend) { @@ -390,7 +392,9 @@ pack_pack(ary, fmt) plen = 0; } else { - ptr = rb_str2cstr(from, &plen); + StringValue(from); + ptr = RSTRING(from)->ptr; + plen = RSTRING(from)->len; } if (p[-1] == '*') @@ -824,7 +828,10 @@ pack_pack(ary, fmt) case 'u': case 'm': - ptr = rb_str2cstr(NEXTFROM, &plen); + from = NEXTFROM; + StringValue(from); + ptr = RSTRING(from)->ptr; + plen = RSTRING(from)->len; if (len <= 2) len = 45; @@ -851,6 +858,14 @@ pack_pack(ary, fmt) break; case 'P': + from = THISFROM; + if (!NIL_P(from)) { + StringValue(from); + if (RSTRING(from)->len < len) { + rb_raise(rb_eArgError, "too short buffer for P(%d for %d)", + RSTRING(from)->len, len); + } + } len = 1; /* FALL THROUGH */ case 'p': @@ -858,9 +873,12 @@ pack_pack(ary, fmt) char *t; from = NEXTFROM; if (NIL_P(from)) { - from = rb_str_new(0, 0); + t = 0; + } + else { + StringValue(from); + t = RSTRING(from)->ptr; } - t = STR2CSTR(from); rb_str_associate(res, from); rb_str_cat(res, (char*)&t, sizeof(char*)); } @@ -1084,10 +1102,12 @@ pack_unpack(str, fmt) int natint; /* native integer */ #endif - s = rb_str2cstr(str, &len); - send = s + len; - p = rb_str2cstr(fmt, &len); - pend = p + len; + StringValue(str); + s = RSTRING(str)->ptr; + send = s + RSTRING(str)->len; + StringValue(fmt); + p = RSTRING(fmt)->ptr; + pend = p + RSTRING(fmt)->len; ary = rb_ary_new(); while (p < pend) { @@ -1611,17 +1631,17 @@ pack_unpack(str, fmt) case 'P': if (sizeof(char *) <= send - s) { char *t; - VALUE a, tmp; + VALUE tmp; - if (!(a = rb_str_associated(str))) { - rb_raise(rb_eArgError, "no associated pointer"); - } memcpy(&t, s, sizeof(char *)); s += sizeof(char *); if (t) { - VALUE *p, *pend; + VALUE a, *p, *pend; + if (!(a = rb_str_associated(str))) { + rb_raise(rb_eArgError, "no associated pointer"); + } p = RARRAY(a)->ptr; pend = p + RARRAY(a)->len; while (p < pend) { @@ -1639,7 +1659,7 @@ pack_unpack(str, fmt) tmp = rb_tainted_str_new(t, len); } else { - tmp = rb_str_new(0, 0); + tmp = Qnil; } rb_ary_push(ary, tmp); } @@ -1652,19 +1672,20 @@ pack_unpack(str, fmt) if (send - s < sizeof(char *)) break; else { + VALUE tmp; char *t; - VALUE a, tmp; - VALUE *p, *pend; - - if (!(a = rb_str_associated(str))) { - rb_raise(rb_eArgError, "no associated pointer"); - } memcpy(&t, s, sizeof(char *)); s += sizeof(char *); if (t) { + VALUE a, tmp; + VALUE *p, *pend; + p = RARRAY(a)->ptr; + if (!(a = rb_str_associated(str))) { + rb_raise(rb_eArgError, "no associated pointer"); + } pend = p + RARRAY(a)->len; while (p < pend) { if (TYPE(*p) == T_STRING && RSTRING(*p)->ptr == t) { @@ -1677,6 +1698,9 @@ pack_unpack(str, fmt) } tmp = rb_str_new2(t); } + else { + tmp = Qnil; + } rb_ary_push(ary, tmp); } } diff --git a/parse.y b/parse.y index 1e7ad8c6b2..f57c942ee6 100644 --- a/parse.y +++ b/parse.y @@ -56,10 +56,8 @@ static enum lex_state { EXPR_CLASS, /* immediate after `class', no here document. */ } lex_state; -#if SIZEOF_LONG_LONG > 0 -typedef unsigned long long stack_type; -#elif SIZEOF___INT64 > 0 -typedef unsigned __int64 stack_type; +#ifdef HAVE_LONG_LONG +typedef unsigned LONG_LONG stack_type; #else typedef unsigned long stack_type; #endif @@ -132,10 +130,6 @@ static struct RVarmap *dyna_push(); static void dyna_pop(); static int dyna_in_block(); -#define cref_push() NEW_CREF() -static void cref_pop(); -static NODE *cur_cref; - static void top_local_init(); static void top_local_setup(); %} @@ -270,7 +264,6 @@ program : { $$ = ruby_dyna_vars; lex_state = EXPR_BEG; top_local_init(); - NEW_CREF0(); /* initialize constant c-ref */ if ((VALUE)ruby_class == rb_cObject) class_nest = 0; else class_nest = 1; } @@ -289,7 +282,6 @@ program : { } ruby_eval_tree = block_append(ruby_eval_tree, $2); top_local_setup(); - cur_cref = 0; class_nest = 0; ruby_dyna_vars = $1; } @@ -1249,7 +1241,6 @@ primary : literal if (in_def || in_single) yyerror("class definition in method body"); class_nest++; - cref_push(); local_push(); $$ = ruby_sourceline; } @@ -1259,7 +1250,6 @@ primary : literal $$ = NEW_CLASS($2, $5, $3); nd_set_line($$, $4); local_pop(); - cref_pop(); class_nest--; } | kCLASS tLSHFT expr @@ -1272,7 +1262,6 @@ primary : literal $$ = in_single; in_single = 0; class_nest++; - cref_push(); local_push(); } compstmt @@ -1281,7 +1270,6 @@ primary : literal $$ = NEW_SCLASS($3, $7); fixpos($$, $3); local_pop(); - cref_pop(); class_nest--; in_def = $4; in_single = $6; @@ -1291,7 +1279,6 @@ primary : literal if (in_def || in_single) yyerror("module definition in method body"); class_nest++; - cref_push(); local_push(); $$ = ruby_sourceline; } @@ -1301,7 +1288,6 @@ primary : literal $$ = NEW_MODULE($2, $4); nd_set_line($$, $3); local_pop(); - cref_pop(); class_nest--; } | kDEF fname @@ -1984,6 +1970,7 @@ yycompile(f, line) ruby_in_compile = 0; cond_nest = 0; cond_stack = 0; + cmdarg_stack = 0; class_nest = 0; in_single = 0; in_def = 0; @@ -3634,7 +3621,13 @@ yylex() if (CMDARG_P()) return kDO_BLOCK; return kDO; } - return kw->id[state != EXPR_BEG]; + if (state == EXPR_BEG) + return kw->id[0]; + else { + if (kw->id[0] != kw->id[1]) + lex_state = EXPR_BEG; + return kw->id[1]; + } } } @@ -4785,12 +4778,6 @@ dyna_in_block() return (lvtbl->dlev > 0); } -static void -cref_pop() -{ - cur_cref = cur_cref->nd_next; -} - void rb_parser_append_print() { @@ -4874,7 +4861,6 @@ Init_sym() { sym_tbl = st_init_strtable_with_size(200); sym_rev_tbl = st_init_numtable_with_size(200); - rb_global_variable((VALUE*)&cur_cref); rb_global_variable((VALUE*)&lex_lastline); } @@ -4983,6 +4969,25 @@ rb_id2name(id) return 0; } +static int +symbols_i(key, value, ary) + char *key; + ID value; + VALUE ary; +{ + rb_ary_push(ary, ID2SYM(value)); + return ST_CONTINUE; +} + +VALUE +rb_sym_all_symbols() +{ + VALUE ary = rb_ary_new2(sym_tbl->num_entries); + + st_foreach(sym_tbl, symbols_i, ary); + return ary; +} + int rb_is_const_id(id) ID id; diff --git a/process.c b/process.c index 101a4d0c89..f8d715f66d 100644 --- a/process.c +++ b/process.c @@ -170,7 +170,7 @@ pst_wifsignaled(st) { int status = NUM2INT(st); - if (WIFSIGNALED(st)) + if (WIFSIGNALED(status)) return Qtrue; else return Qfalse; @@ -314,27 +314,13 @@ wait_each(key, value, data) return ST_DELETE; } -struct waitall_data { - int pid; - int status; - VALUE ary; -}; - static int waitall_each(key, value, data) int key, value; - struct waitall_data *data; + VALUE data; { - VALUE pid_status_member; - - if (data->status != -1) return ST_STOP; - - data->pid = key; - data->status = value; - pid_status_member = rb_ary_new2(2); - rb_ary_push(pid_status_member, INT2NUM(key)); - rb_ary_push(pid_status_member, INT2NUM(value)); - rb_ary_push(data->ary, pid_status_member); + last_status_set(value); + rb_ary_push(data, rb_assoc_new(INT2NUM(key), rb_last_status)); return ST_DELETE; } #endif @@ -346,11 +332,13 @@ proc_wait() #ifdef NO_WAITPID struct wait_data data; - data.status = -1; - st_foreach(pid_tbl, wait_each, &data); - if (data.status != -1) { - last_status_set(data.status); - return INT2FIX(data.pid); + if (pid_tbl) { + data.status = -1; + st_foreach(pid_tbl, wait_each, &data); + if (data.status != -1) { + last_status_set(data.status); + return INT2FIX(data.pid); + } } while (1) { @@ -416,17 +404,13 @@ proc_waitpid2(argc, argv) static VALUE proc_waitall() { - VALUE pid_status_ary, pid_status_member; + VALUE result; int pid, status; -#ifdef NO_WAITPID - struct waitall_data data; - data.ary = pid_status_ary = rb_ary_new(); - data.status = -1; - st_foreach(pid_tbl, waitall_each, &data); - if (data.status != -1) { - last_status_set(data.status); - return pid_status_ary; + result = rb_ary_new(); +#ifdef NO_WAITPID + if (pid_tbl) { + st_foreach(pid_tbl, waitall_each, result); } for (pid = -1;;) { @@ -440,15 +424,11 @@ proc_waitall() } rb_sys_fail(0); } - pid_status_member = rb_ary_new2(2); - rb_ary_push(pid_status_member, INT2NUM(pid)); - rb_ary_push(pid_status_member, INT2NUM(status)); - rb_ary_push(pid_status_ary, pid_status_member); - } - if (RARRAY(pid_status_ary)->len != 0) last_status_set(status); + rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status)); + } #else - pid_status_ary = rb_ary_new(); + rb_last_status = Qnil; for (pid = -1;;) { pid = rb_waitpid(-1, 0, &status); if (pid == -1) { @@ -456,13 +436,10 @@ proc_waitall() break; rb_sys_fail(0); } - pid_status_member = rb_ary_new2(2); - rb_ary_push(pid_status_member, INT2NUM(pid)); - rb_ary_push(pid_status_member, INT2NUM(status)); - rb_ary_push(pid_status_ary, pid_status_member); + rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status)); } #endif - return pid_status_ary; + return result; } #ifndef HAVE_STRING_H @@ -564,7 +541,7 @@ proc_exec_n(argc, argv, progv) } args = ALLOCA_N(char*, argc+1); for (i=0; iptr; } args[i] = 0; @@ -694,7 +671,7 @@ proc_spawn_n(argc, argv, prog) SafeStr(argv[i]); args[i] = RSTRING(argv[i])->ptr; } - SafeStr(prog); + SafeStringValue(prog); args[i] = (char*) 0; if (args[0]) return proc_spawn_v(args, RSTRING(prog)->ptr); @@ -710,7 +687,7 @@ proc_spawn(sv) char **argv, **a; int status; - SafeStr(sv); + SafeStringValue(sv); str = s = RSTRING(sv)->ptr; for (s = str; *s; s++) { if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) { @@ -753,12 +730,12 @@ rb_f_exec(argc, argv) argv[0] = RARRAY(argv[0])->ptr[1]; } if (prog) { - SafeStr(prog); + SafeStringValue(prog); } if (argc == 1 && prog == 0) { VALUE cmd = argv[0]; - SafeStr(cmd); + SafeStringValue(cmd); rb_proc_exec(RSTRING(cmd)->ptr); } else { @@ -876,7 +853,7 @@ rb_f_system(argc, argv) } cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" ")); - SafeStr(cmd); + SafeStringValue(cmd); status = do_spawn(RSTRING(cmd)->ptr); last_status_set(status); @@ -900,7 +877,7 @@ rb_f_system(argc, argv) } cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" ")); - SafeStr(cmd); + SafeStringValue(cmd); status = system(RSTRING(cmd)->ptr); last_status_set((status & 0xff) << 8); @@ -957,10 +934,10 @@ rb_f_system(argc, argv) } if (prog) { - SafeStr(prog); + SafeStringValue(prog); } for (i = 0; i < argc; i++) { - SafeStr(argv[i]); + SafeStringValue(argv[i]); } retry: switch (pid = vfork()) { diff --git a/re.c b/re.c index 2a92b982d7..aa9f1b4cdc 100644 --- a/re.c +++ b/re.c @@ -936,7 +936,7 @@ rb_reg_match(re, str) int start; if (NIL_P(str)) return Qnil; - str = rb_str_to_str(str); + StringValue(str); start = rb_reg_search(re, str, 0, 0); if (start < 0) { return Qnil; @@ -990,7 +990,7 @@ rb_reg_initialize_m(argc, argv, self) else if (RTEST(argv[1])) flags = RE_OPTION_IGNORECASE; } if (argc == 3) { - char *kcode = STR2CSTR(argv[2]); + char *kcode = StringValuePtr(argv[2]); switch (kcode[0]) { case 'n': case 'N': @@ -1016,11 +1016,8 @@ rb_reg_initialize_m(argc, argv, self) rb_reg_initialize(self, RREGEXP(src)->str, RREGEXP(src)->len, flags); } else { - char *p; - int len; - - p = rb_str2cstr(src, &len); - rb_reg_initialize(self, p, len, flags); + StringValue(src); + rb_reg_initialize(self, RSTRING(src)->ptr, RSTRING(src)->len, flags); } return self; } @@ -1047,17 +1044,17 @@ rb_reg_s_quote(argc, argv) int kcode_saved = reg_kcode; char *s, *send, *t; VALUE tmp; - int len; rb_scan_args(argc, argv, "11", &str, &kcode); if (!NIL_P(kcode)) { - rb_set_kcode(STR2CSTR(kcode)); + rb_set_kcode(StringValuePtr(kcode)); curr_kcode = reg_kcode; reg_kcode = kcode_saved; } - s = rb_str2cstr(str, &len); - send = s + len; - tmp = rb_str_new(0, len*2); + StringValue(str); + s = RSTRING(str)->ptr; + send = s + RSTRING(str)->len; + tmp = rb_str_new(0, RSTRING(str)->len*2); t = RSTRING(tmp)->ptr; for (; s < send; s++) { @@ -1288,10 +1285,10 @@ rb_set_kcode(code) static void kcode_setter(val) - struct RString *val; + VALUE val; { may_need_recompile = 1; - rb_set_kcode(STR2CSTR(val)); + rb_set_kcode(StringValuePtr(val)); } static VALUE @@ -1406,6 +1403,7 @@ Init_Regexp() rb_define_method(rb_cMatch, "begin", match_begin, 1); rb_define_method(rb_cMatch, "end", match_end, 1); rb_define_method(rb_cMatch, "to_a", match_to_a, 0); + rb_define_method(rb_cMatch, "to_ary", match_to_a, 0); rb_define_method(rb_cMatch, "[]", match_aref, -1); rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0); rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0); diff --git a/regex.c b/regex.c index 07963b5d1d..eb4c530bad 100644 --- a/regex.c +++ b/regex.c @@ -1049,7 +1049,7 @@ calculate_must_string(start, end) EXTRACT_NUMBER_AND_INCR(mcnt, p); if (mcnt > 0) p += mcnt; if ((enum regexpcode)p[-3] == jump) { - p -= 3; + p -= 2; EXTRACT_NUMBER_AND_INCR(mcnt, p); if (mcnt > 0) p += mcnt; } @@ -1438,6 +1438,9 @@ re_compile_pattern(pattern, size, bufp) EXTEND_BUFFER; } range_retry: + if (range && had_char_class) { + FREE_AND_RETURN(stackb, "invalid regular expression; can't use character class as an end value of range"); + } PATFETCH(c); if (c == ']') { @@ -1459,6 +1462,7 @@ re_compile_pattern(pattern, size, bufp) PATFETCH_MBC(c); had_mbchar++; } + had_char_class = 0; /* \ escapes characters when inside [...]. */ if (c == '\\') { @@ -1473,6 +1477,7 @@ re_compile_pattern(pattern, size, bufp) if (current_mbctype) { set_list_bits(0x80, 0xffffffff, b); } + had_char_class = 1; last = -1; continue; @@ -1483,6 +1488,7 @@ re_compile_pattern(pattern, size, bufp) !current_mbctype && SYNTAX(c) != Sword2)) SET_LIST_BIT(c); } + had_char_class = 1; last = -1; continue; @@ -1490,6 +1496,7 @@ re_compile_pattern(pattern, size, bufp) for (c = 0; c < 256; c++) if (ISSPACE(c)) SET_LIST_BIT(c); + had_char_class = 1; last = -1; continue; @@ -1499,12 +1506,14 @@ re_compile_pattern(pattern, size, bufp) SET_LIST_BIT(c); if (current_mbctype) set_list_bits(0x80, 0xffffffff, b); + had_char_class = 1; last = -1; continue; case 'd': for (c = '0'; c <= '9'; c++) SET_LIST_BIT(c); + had_char_class = 1; last = -1; continue; @@ -1514,6 +1523,7 @@ re_compile_pattern(pattern, size, bufp) SET_LIST_BIT(c); if (current_mbctype) set_list_bits(0x80, 0xffffffff, b); + had_char_class = 1; last = -1; continue; diff --git a/ruby.c b/ruby.c index 55bef5d534..5fa1954cad 100644 --- a/ruby.c +++ b/ruby.c @@ -138,7 +138,8 @@ rubylib_mangle(s, l) if (*s == '\\') *s = '/'; s++; } - } else { + } + else { notfound = 1; } } @@ -234,7 +235,8 @@ ruby_init_loadpath() p -= 4; *p = 0; } - } else { + } + else { strcpy(libpath, "."); p = libpath + 1; } @@ -334,7 +336,8 @@ process_sflag() n = RARRAY(rb_argv)->len; args = RARRAY(rb_argv)->ptr; while (n > 0) { - char *s = STR2CSTR(*args++); + VALUE v = *args++; + char *s = StringValuePtr(v); char *p; if (s[0] != '-') break; @@ -876,11 +879,13 @@ set_arg0(val, id) len = s - origargv[0]; } #endif - s = rb_str2cstr(val, &i); + StringValue(val); + s = RSTRING(val)->ptr; + i = RSTRING(val)->len; #ifndef __hpux - if (i > len) { - memcpy(origargv[0], s, len); - origargv[0][len] = '\0'; + if (i < len) { + memcpy(origargv[0], s, i); + origargv[0][i] = '\0'; } else { memcpy(origargv[0], s, i); @@ -898,7 +903,8 @@ set_arg0(val, id) RSTRING(val)->len = i; *(s + i) = '\0'; pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0); - } else { + } + else { union pstun j; j.pst_command = s; pstat(PSTAT_SETCMD, j, i, 0, 0); diff --git a/ruby.h b/ruby.h index 839bbb5e52..166bc6e7d9 100644 --- a/ruby.h +++ b/ruby.h @@ -63,6 +63,12 @@ extern "C" { # define __(args) () #endif +#ifdef __cplusplus +#define ANYARGS ... +#else +#define ANYARGS +#endif + #ifndef NORETURN # define NORETURN(x) x #endif @@ -108,9 +114,11 @@ typedef unsigned long ID; #define rb_fix_new(v) INT2FIX(v) VALUE rb_int2inum _((long)); #define INT2NUM(v) rb_int2inum(v) +#define LONG2NUM(v) INT2NUM(v) #define rb_int_new(v) rb_int2inum(v) VALUE rb_uint2inum _((unsigned long)); #define UINT2NUM(v) rb_uint2inum(v) +#define ULONG2NUM(v) UINT2NUM(v) #define rb_uint_new(v) rb_uint2inum(v) #define FIX2LONG(x) RSHIFT((long)x,1) @@ -176,15 +184,22 @@ VALUE rb_uint2inum _((unsigned long)); void rb_check_type _((VALUE,int)); #define Check_Type(v,t) rb_check_type((VALUE)(v),t) -void rb_check_safe_str _((VALUE)); -/* obsolete macro - use SafeStr(v) */ -#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) + VALUE rb_str_to_str _((VALUE)); -#define SafeStr(v) do {\ - v = rb_str_to_str(v);\ +#define StringValue(v) do {\ + if (TYPE(v) != T_STRING) v = rb_str_to_str(v);\ +} while (0) +void rb_check_safe_str _((VALUE)); +/* obsolete macro - use SafeStringValue(v) */ +#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) +#define SafeStringValue(v) do {\ + if (TYPE(v) != T_STRING) v = rb_str_to_str(v);\ rb_check_safe_str(v);\ } while (0) +#define StringValuePtr(v) \ + (((TYPE(v) != T_STRING) ? v = rb_str_to_str(v) : (v)), RSTRING(v)->ptr) + void rb_secure _((int)); EXTERN int ruby_safe_level; @@ -212,8 +227,9 @@ int rb_fix2int _((VALUE)); double rb_num2dbl _((VALUE)); #define NUM2DBL(x) rb_num2dbl((VALUE)(x)) +/* obsolete API - use StringValue() */ char *rb_str2cstr _((VALUE,int*)); -#define str2cstr(x,l) rb_str2cstr((VALUE)(x),(l)) +/* obsolete API - use StringValuePtr() */ #define STR2CSTR(x) rb_str2cstr((VALUE)(x),0) #define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\ @@ -402,8 +418,8 @@ void xfree _((void*)); #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n)) #define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n)) -void rb_glob _((char*,void(*)(),VALUE)); -void rb_iglob _((char*,void(*)(),VALUE)); +void rb_glob _((char*,void(*)(const char*,VALUE),VALUE)); +void rb_iglob _((char*,void(*)(const char*,VALUE),VALUE)); VALUE rb_define_class _((const char*,VALUE)); VALUE rb_define_module _((const char*)); @@ -414,16 +430,16 @@ void rb_include_module _((VALUE,VALUE)); void rb_extend_object _((VALUE,VALUE)); void rb_define_variable _((const char*,VALUE*)); -void rb_define_virtual_variable _((const char*,VALUE(*)(),void(*)())); -void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)())); +void rb_define_virtual_variable _((const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS))); +void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(ANYARGS),void(*)(ANYARGS))); void rb_define_readonly_variable _((const char*,VALUE*)); void rb_define_const _((VALUE,const char*,VALUE)); void rb_define_global_const _((const char*,VALUE)); -#define RUBY_METHOD_FUNC(func) ((VALUE (*)__((...)))func) -void rb_define_method _((VALUE,const char*,VALUE(*)(),int)); -void rb_define_module_function _((VALUE,const char*,VALUE(*)(),int)); -void rb_define_global_function _((const char*,VALUE(*)(),int)); +#define RUBY_METHOD_FUNC(func) ((VALUE (*)(ANYARGS))func) +void rb_define_method _((VALUE,const char*,VALUE(*)(ANYARGS),int)); +void rb_define_module_function _((VALUE,const char*,VALUE(*)(ANYARGS),int)); +void rb_define_global_function _((const char*,VALUE(*)(ANYARGS),int)); void rb_undef_method _((VALUE,const char*)); void rb_define_alias _((VALUE,const char*,const char*)); @@ -474,11 +490,11 @@ void rb_warn __((const char*, ...)); /* reports always */ VALUE rb_each _((VALUE)); VALUE rb_yield _((VALUE)); int rb_block_given_p _((void)); -VALUE rb_iterate _((VALUE(*)(),VALUE,VALUE(*)(),VALUE)); -VALUE rb_rescue _((VALUE(*)(),VALUE,VALUE(*)(),VALUE)); -VALUE rb_rescue2 __((VALUE(*)(),VALUE,VALUE(*)(),VALUE,...)); -VALUE rb_ensure _((VALUE(*)(),VALUE,VALUE(*)(),VALUE)); -VALUE rb_catch _((const char*,VALUE(*)(),VALUE)); +VALUE rb_iterate _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE)); +VALUE rb_rescue _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE)); +VALUE rb_rescue2 __((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...)); +VALUE rb_ensure _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE)); +VALUE rb_catch _((const char*,VALUE(*)(ANYARGS),VALUE)); NORETURN(void rb_throw _((const char*,VALUE))); VALUE rb_require _((const char*)); @@ -541,6 +557,7 @@ EXTERN VALUE rb_eTypeError; EXTERN VALUE rb_eZeroDivError; EXTERN VALUE rb_eNotImpError; EXTERN VALUE rb_eNoMemError; +EXTERN VALUE rb_eNoMethodError; EXTERN VALUE rb_eFloatDomainError; EXTERN VALUE rb_eScriptError; diff --git a/rubyio.h b/rubyio.h index 6509e3e7c1..d3d93ef6b7 100644 --- a/rubyio.h +++ b/rubyio.h @@ -23,7 +23,7 @@ typedef struct OpenFile { int pid; /* child's pid (for pipes) */ int lineno; /* number of lines read */ char *path; /* pathname for file */ - void (*finalize)(); /* finalize proc */ + void (*finalize) _((struct OpenFile*)); /* finalize proc */ } OpenFile; #define FMODE_READABLE 1 diff --git a/rubysig.h b/rubysig.h index d6de009c18..7b8e71a62e 100644 --- a/rubysig.h +++ b/rubysig.h @@ -59,7 +59,7 @@ EXTERN int rb_prohibit_interrupt; #define ALLOW_INTS {rb_prohibit_interrupt--; CHECK_INTS;} #define ENABLE_INTS {rb_prohibit_interrupt--;} -VALUE rb_with_disable_interrupt _((VALUE(*)(),VALUE)); +VALUE rb_with_disable_interrupt _((VALUE(*)(ANYARGS),VALUE)); EXTERN rb_atomic_t rb_trap_pending; void rb_trap_restore_mask _((void)); diff --git a/signal.c b/signal.c index a2221aca50..0582da3b73 100644 --- a/signal.c +++ b/signal.c @@ -465,7 +465,7 @@ trap(arg) func = SIG_IGN; } else if (TYPE(command) == T_STRING) { - SafeStr(command); /* taint check */ + SafeStringValue(command); /* taint check */ if (RSTRING(command)->len == 0) { func = SIG_IGN; } diff --git a/sprintf.c b/sprintf.c index 2dd7812254..5552befe20 100644 --- a/sprintf.c +++ b/sprintf.c @@ -174,8 +174,9 @@ rb_f_sprintf(argc, argv) fmt = GETARG(); if (OBJ_TAINTED(fmt)) tainted = 1; - p = rb_str2cstr(fmt, &blen); - end = p + blen; + StringValue(fmt); + p = RSTRING(fmt)->ptr; + end = p + RSTRING(fmt)->len; blen = 0; bsiz = 120; buf = ALLOC_N(char, bsiz); diff --git a/st.c b/st.c index e40c6e1017..86d569717b 100644 --- a/st.c +++ b/st.c @@ -255,7 +255,8 @@ st_lookup(table, key, value) if (ptr == 0) { return 0; - } else { + } + else { if (value != 0) *value = ptr->record; return 1; } @@ -294,7 +295,8 @@ st_insert(table, key, value) if (ptr == 0) { ADD_DIRECT(table, key, value, hash_val, bin_pos); return 0; - } else { + } + else { ptr->record = value; return 1; } @@ -498,7 +500,8 @@ st_foreach(table, func, arg) tmp = ptr; if (last == 0) { table->bins[i] = ptr->next; - } else { + } + else { last->next = ptr->next; } ptr = ptr->next; diff --git a/string.c b/string.c index 4705f992d9..0d549237aa 100644 --- a/string.c +++ b/string.c @@ -209,7 +209,7 @@ rb_str_dup(str) VALUE str2; VALUE klass; - if (TYPE(str) != T_STRING) str = rb_str_to_str(str); + StringValue(str); klass = CLASS_OF(str); while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { klass = (VALUE)RCLASS(klass)->super; @@ -278,7 +278,7 @@ rb_str_plus(str1, str2) { VALUE str3; - if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); + StringValue(str2); str3 = rb_str_new(0, RSTRING(str1)->len+RSTRING(str2)->len); memcpy(RSTRING(str3)->ptr, RSTRING(str1)->ptr, RSTRING(str1)->len); memcpy(RSTRING(str3)->ptr + RSTRING(str1)->len, @@ -470,7 +470,7 @@ VALUE rb_str_append(str1, str2) VALUE str1, str2; { - if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); + StringValue(str2); str1 = rb_str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); OBJ_INFECT(str1, str2); @@ -590,7 +590,7 @@ rb_str_cmp_m(str1, str2) { int result; - if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); + StringValue(str2); result = rb_str_cmp(str1, str2); return INT2FIX(result); } @@ -865,8 +865,7 @@ rb_str_upto(beg, end, excl) VALUE current; ID succ = rb_intern("succ"); - if (TYPE(end) != T_STRING) end = rb_str_to_str(end); - + StringValue(end); current = beg; while (rb_str_cmp(current, end) <= 0) { rb_yield(current); @@ -952,14 +951,26 @@ rb_str_aref_m(argc, argv, str) static void rb_str_replace(str, beg, len, val) - VALUE str, val; + VALUE str; long beg; long len; + VALUE val; { + if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len); + if (beg < 0) { + beg += RSTRING(str)->len; + } + if (beg < 0 || RSTRING(str)->len < beg) { + if (beg < 0) { + beg -= RSTRING(str)->len; + } + rb_raise(rb_eIndexError, "index %d out of string", beg); + } if (RSTRING(str)->len < beg + len) { len = RSTRING(str)->len - beg; } + StringValue(val); if (len < RSTRING(val)->len) { /* expand string */ REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+RSTRING(val)->len-len+1); @@ -1007,7 +1018,6 @@ rb_str_aset(str, indx, val) RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff; } else { - if (TYPE(val) != T_STRING) val = rb_str_to_str(val); rb_str_replace(str, idx, 1, val); } return val; @@ -1024,7 +1034,6 @@ rb_str_aset(str, indx, val) case T_STRING: beg = rb_str_index(str, indx, 0); if (beg != -1) { - if (TYPE(val) != T_STRING) val = rb_str_to_str(val); rb_str_replace(str, beg, RSTRING(indx)->len, val); } return val; @@ -1034,7 +1043,6 @@ rb_str_aset(str, indx, val) { long beg, len; if (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 2)) { - if (TYPE(val) != T_STRING) val = rb_str_to_str(val); rb_str_replace(str, beg, len, val); return val; } @@ -1054,22 +1062,8 @@ rb_str_aset_m(argc, argv, str) if (argc == 3) { long beg, len; - if (TYPE(argv[2]) != T_STRING) argv[2] = rb_str_to_str(argv[2]); beg = NUM2INT(argv[0]); len = NUM2INT(argv[1]); - if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len); - if (beg < 0) { - beg += RSTRING(str)->len; - } - if (beg < 0 || RSTRING(str)->len < beg) { - if (beg < 0) { - beg -= RSTRING(str)->len; - } - rb_raise(rb_eIndexError, "index %d out of string", beg); - } - if (beg + len > RSTRING(str)->len) { - len = RSTRING(str)->len - beg; - } rb_str_replace(str, beg, len, argv[2]); return argv[2]; } @@ -1079,6 +1073,14 @@ rb_str_aset_m(argc, argv, str) return rb_str_aset(str, argv[0], argv[1]); } +static VALUE +rb_str_insert(str, idx, str2) + VALUE str, idx, str2; +{ + rb_str_replace(str, NUM2LONG(idx), 0, str2); + return str; +} + static VALUE rb_str_slice_bang(argc, argv, str) int argc; @@ -1136,7 +1138,8 @@ rb_str_sub_bang(argc, argv, str) iter = 1; } else if (argc == 2) { - repl = rb_str_to_str(argv[1]);; + repl = argv[1]; + StringValue(repl); if (OBJ_TAINTED(repl)) tainted = 1; } else { @@ -1209,7 +1212,8 @@ str_gsub(argc, argv, str, bang) iter = 1; } else if (argc == 2) { - repl = rb_str_to_str(argv[1]); + repl = argv[1]; + StringValue(repl); if (OBJ_TAINTED(repl)) tainted = 1; } else { @@ -1329,8 +1333,8 @@ rb_str_replace_m(str, str2) VALUE str, str2; { if (str == str2) return str; - if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2); + StringValue(str2); if (RSTRING(str2)->orig && !FL_TEST(str2, STR_NO_ORIG)) { if (str_independent(str)) { free(RSTRING(str)->ptr); @@ -1462,7 +1466,7 @@ rb_str_include(str, arg) return Qfalse; } - if (TYPE(arg) != T_STRING) arg = rb_str_to_str(arg); + StringValue(arg); i = rb_str_index(str, arg, 0); if (i == -1) return Qfalse; @@ -1841,13 +1845,13 @@ tr_trans(str, src, repl, sflag) char *s, *send; rb_str_modify(str); - if (TYPE(src) != T_STRING) src = rb_str_to_str(src); + StringValue(src); + StringValue(repl); trsrc.p = RSTRING(src)->ptr; trsrc.pend = trsrc.p + RSTRING(src)->len; if (RSTRING(src)->len >= 2 && RSTRING(src)->ptr[0] == '^') { cflag++; trsrc.p++; } - if (TYPE(repl) != T_STRING) repl = rb_str_to_str(repl); if (RSTRING(repl)->len == 0) { return rb_str_delete_bang(1, &src, str); } @@ -1991,8 +1995,7 @@ rb_str_delete_bang(argc, argv, str) for (i=0; ilen; if (rslen == 0) { newline = '\n'; @@ -2434,7 +2432,7 @@ rb_str_chomp_bang(argc, argv, str) } if (NIL_P(rs)) return Qnil; - if (TYPE(rs) != T_STRING) rs = rb_str_to_str(rs); + StringValue(rs); rslen = RSTRING(rs)->len; if (rslen == 0) { while (len>0 && p[len-1] == '\n') { @@ -2645,7 +2643,7 @@ rb_str_crypt(str, salt) { extern char *crypt(); - if (TYPE(salt) != T_STRING) salt = rb_str_to_str(salt); + StringValue(salt); if (RSTRING(salt)->len < 2) rb_raise(rb_eArgError, "salt too short(need >=2 bytes)"); return rb_str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr)); @@ -2804,6 +2802,7 @@ Init_String() rb_define_method(rb_cString, "%", rb_str_format, 1); rb_define_method(rb_cString, "[]", rb_str_aref_m, -1); rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1); + rb_define_method(rb_cString, "insert", rb_str_insert, 2); rb_define_method(rb_cString, "length", rb_str_length, 0); rb_define_method(rb_cString, "size", rb_str_length, 0); rb_define_method(rb_cString, "empty?", rb_str_empty, 0); diff --git a/struct.c b/struct.c index 9de9915493..82b69964a8 100644 --- a/struct.c +++ b/struct.c @@ -157,7 +157,7 @@ make_struct(name, member, klass) nstr = rb_class_new(klass); } else { - char *cname = STR2CSTR(name); + char *cname = StringValuePtr(name); id = rb_intern(cname); if (!rb_is_const_id(id)) { rb_raise(rb_eNameError, "identifier %s needs to be constant", cname); diff --git a/time.c b/time.c index 150df2da2f..8e79080380 100644 --- a/time.c +++ b/time.c @@ -270,8 +270,11 @@ time_arg(argc, argv, tm, usec) tm->tm_sec = NIL_P(v[5])?0:obj2long(v[5]); /* value validation */ - if ( tm->tm_year < 69 - || tm->tm_mon < 0 || tm->tm_mon > 11 + if ( +#ifndef NEGATIVE_TIME_T + tm->tm_year < 69 || +#endif + tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_mday < 1 || tm->tm_mday > 31 || tm->tm_hour < 0 || tm->tm_hour > 23 || tm->tm_min < 0 || tm->tm_min > 59 @@ -284,14 +287,14 @@ static VALUE time_localtime _((VALUE)); static VALUE time_get_tm _((VALUE, int)); static time_t -make_time_t(tptr, utc_or_local) +make_time_t(tptr, utc_p) struct tm *tptr; - int utc_or_local; + int utc_p; { struct timeval tv; time_t oguess, guess; struct tm *tm; - long t, diff; + long t, diff, i; if (gettimeofday(&tv, 0) < 0) { rb_sys_fail("gettimeofday"); @@ -301,11 +304,13 @@ make_time_t(tptr, utc_or_local) tm = gmtime(&guess); if (!tm) goto error; t = tptr->tm_year; +#ifndef NEGATIVE_TIME_T if (t < 69) goto out_of_range; +#endif + i = 0; while (diff = t - tm->tm_year) { - oguess = guess; guess += diff * 363 * 24 * 3600; - if (diff > 0 && guess <= oguess) goto out_of_range; + if (i++ > 255) goto out_of_range; tm = gmtime(&guess); if (!tm) goto error; } @@ -316,18 +321,18 @@ make_time_t(tptr, utc_or_local) if (!tm) goto error; if (tptr->tm_year != tm->tm_year) goto out_of_range; } + oguess = guess; guess += (tptr->tm_mday - tm->tm_mday) * 24 * 3600; guess += (tptr->tm_hour - tm->tm_hour) * 3600; guess += (tptr->tm_min - tm->tm_min) * 60; guess += (tptr->tm_sec - tm->tm_sec); +#ifndef NEGATIVE_TIME_T if (guess < 0) goto out_of_range; - - if (!utc_or_local) { /* localtime zone adjust */ -#if defined(HAVE_TM_ZONE) - tm = localtime(&guess); - if (!tm) goto error; - guess -= tm->tm_gmtoff; #else + if (oguess > 365 * 24 * 3600 && guess < 0) goto out_of_range; +#endif + + if (!utc_p) { /* localtime zone adjust */ struct tm gt, lt; long tzsec; @@ -351,18 +356,22 @@ make_time_t(tptr, utc_or_local) } if (lt.tm_isdst) guess += 3600; guess += tzsec; - if (guess < 0) { - goto out_of_range; - } +#ifndef NEGATIVE_TIME_T + if (guess < 0) goto out_of_range; +#endif tm = localtime(&guess); if (!tm) goto error; - if (lt.tm_isdst != tm->tm_isdst) { - guess -= 3600; + if (lt.tm_isdst != tm->tm_isdst || tptr->tm_hour != tm->tm_hour) { + oguess = guess - 3600; + tm = localtime(&oguess); + if (!tm) goto error; + if (tptr->tm_hour == tm->tm_hour) { + guess = oguess; + } } +#ifndef NEGATIVE_TIME_T + if (guess < 0) goto out_of_range; #endif - if (guess < 0) { - goto out_of_range; - } } return guess; @@ -926,7 +935,9 @@ time_strftime(time, format) if (tobj->tm_got == 0) { time_get_tm(time, tobj->gmt); } - fmt = rb_str2cstr(format, &len); + StringValue(format); + fmt = RSTRING(format)->ptr; + len = RSTRING(format)->len; if (len == 0) { rb_warning("strftime called with empty format string"); } @@ -1010,8 +1021,9 @@ time_load(klass, str) struct tm tm; int i; - buf = rb_str2cstr(str, &i); - if (i != 8) { + StringValue(str); + buf = RSTRING(str)->ptr; + if (RSTRING(str)->len != 8) { rb_raise(rb_eTypeError, "marshaled time format differ"); } diff --git a/util.c b/util.c index 5bb9c87f13..ddc919584c 100644 --- a/util.c +++ b/util.c @@ -201,19 +201,25 @@ ruby_add_suffix(str, suffix) if (*suffix == '.') { /* Style 1 */ if (strEQ(ext, suffix)) goto fallback; strcpy(p, suffix); - } else if (suffix[1] == '\0') { /* Style 2 */ + } + else if (suffix[1] == '\0') { /* Style 2 */ if (extlen < 4) { ext[extlen] = *suffix; ext[++extlen] = '\0'; - } else if (baselen < 8) { + } + else if (baselen < 8) { *p++ = *suffix; - } else if (ext[3] != *suffix) { + } + else if (ext[3] != *suffix) { ext[3] = *suffix; - } else if (buf[7] != *suffix) { + } + else if (buf[7] != *suffix) { buf[7] = *suffix; - } else goto fallback; + } + else goto fallback; strcpy(p, ext); - } else { /* Style 3: Panic */ + } + else { /* Style 3: Panic */ fallback: (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5); } @@ -418,7 +424,8 @@ static void mmswap(a, b) register char *a, *b; if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s; if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s; if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}} - }else{ + } + else { register char *t = a + mmsize; do {s = *a; *a++ = *b; *b++ = s;} while (a < t); } @@ -435,12 +442,13 @@ static void mmrot3(a, b, c) register char *a, *b, *c; s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s; s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s; s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16; - }while (a < t); + } while (a < t); } if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s; if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s; if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}} - }else{ + } + else { register char *t = a + mmsize; do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t); } @@ -465,145 +473,146 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)(); { - register char *l, *r, *m; /* l,r:left,right group m:median point */ - register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */ - char *L = base; /* left end of curren region */ - char *R = (char*)base + size*(nel-1); /* right end of current region */ - int chklim = 63; /* threshold of ordering element check */ - stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */ + register char *l, *r, *m; /* l,r:left,right group m:median point */ + register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */ + char *L = base; /* left end of curren region */ + char *R = (char*)base + size*(nel-1); /* right end of current region */ + int chklim = 63; /* threshold of ordering element check */ + stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */ - if (nel <= 1) return; /* need not to sort */ - mmprepare(base, size); - goto start; - - nxt: - if (stack == top) return; /* return if stack is empty */ - POP(L,R); - - for (;;) { - start: - if (L + size == R) {if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;}/* 2 elements */ - - l = L; r = R; - t = (r - l + size) / size; /* number of elements */ - m = l + size * (t >> 1); /* calculate median value */ - - if (t >= 60) { - register char *m1; - register char *m3; - if (t >= 200) { - t = size*(t>>3); /* number of bytes in splitting 8 */ - { - register char *p1 = l + t; - register char *p2 = p1 + t; - register char *p3 = p2 + t; - m1 = med3(p1, p2, p3); - p1 = m + t; - p2 = p1 + t; - p3 = p2 + t; - m3 = med3(p1, p2, p3); - } - }else{ - t = size*(t>>2); /* number of bytes in splitting 4 */ - m1 = l + t; - m3 = m + t; - } - m = med3(m1, m, m3); - } - - if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/ - if ((t = (*cmp)(m,r)) < 0) { /*3-5-7*/ - if (chklim && nel >= chklim) { /* check if already ascending order */ - char *p; - chklim = 0; - for (p=l; p 0) goto fail; - goto nxt; - } - fail: goto loopA; /*3-5-7*/ - } - if (t > 0) { - if ((*cmp)(l,r) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ - mmrot3(r,m,l); goto loopA; /*3-5-2*/ - } - goto loopB; /*3-5-5*/ - } - - if (t > 0) { /*7-5-?*/ - if ((t = (*cmp)(m,r)) > 0) { /*7-5-3*/ - if (chklim && nel >= chklim) { /* check if already ascending order */ - char *p; - chklim = 0; - for (p=l; p 0) {mmswap(l,r); goto loopB;} /*5-5-3*/ - - /* deteming splitting type in case 5-5-5 */ /*5-5-5*/ - for (;;) { - if ((l += size) == r) goto nxt; /*5-5-5*/ - if (l == m) continue; - if ((t = (*cmp)(l,m)) > 0) {mmswap(l,r); l = L; goto loopA;} /*575-5*/ - if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/ - } - - loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */ - for (;;) { - for (;;) { - if ((l += size) == r) - {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} - if (l == m) continue; - if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} - if (t < 0) eq_l = 0; - } - for (;;) { - if (l == (r -= size)) - {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} - if (r == m) {m = l; break;} - if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} - if (t == 0) break; - } - mmswap(l,r); /* swap left and right */ - } - - loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */ - for (;;) { - for (;;) { - if (l == (r -= size)) - {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} - if (r == m) continue; - if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} - if (t > 0) eq_r = 0; - } - for (;;) { - if ((l += size) == r) - {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} - if (l == m) {m = r; break;} - if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} - if (t == 0) break; - } - mmswap(l,r); /* swap left and right */ - } - - fin: - if (eq_l == 0) /* need to sort left side */ - if (eq_r == 0) /* need to sort right side */ - if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */ - else {PUSH(L,l); L = r;} /* sort right side first */ - else R = l; /* need to sort left side only */ - else if (eq_r == 0) L = r; /* need to sort right side only */ - else goto nxt; /* need not to sort both sides */ - } + if (nel <= 1) return; /* need not to sort */ + mmprepare(base, size); + goto start; + + nxt: + if (stack == top) return; /* return if stack is empty */ + POP(L,R); + + for (;;) { + start: + if (L + size == R) {if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;}/* 2 elements */ + + l = L; r = R; + t = (r - l + size) / size; /* number of elements */ + m = l + size * (t >> 1); /* calculate median value */ + + if (t >= 60) { + register char *m1; + register char *m3; + if (t >= 200) { + t = size*(t>>3); /* number of bytes in splitting 8 */ + { + register char *p1 = l + t; + register char *p2 = p1 + t; + register char *p3 = p2 + t; + m1 = med3(p1, p2, p3); + p1 = m + t; + p2 = p1 + t; + p3 = p2 + t; + m3 = med3(p1, p2, p3); + } + } + else { + t = size*(t>>2); /* number of bytes in splitting 4 */ + m1 = l + t; + m3 = m + t; + } + m = med3(m1, m, m3); + } + + if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/ + if ((t = (*cmp)(m,r)) < 0) { /*3-5-7*/ + if (chklim && nel >= chklim) { /* check if already ascending order */ + char *p; + chklim = 0; + for (p=l; p 0) goto fail; + goto nxt; + } + fail: goto loopA; /*3-5-7*/ + } + if (t > 0) { + if ((*cmp)(l,r) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ + mmrot3(r,m,l); goto loopA; /*3-5-2*/ + } + goto loopB; /*3-5-5*/ + } + + if (t > 0) { /*7-5-?*/ + if ((t = (*cmp)(m,r)) > 0) { /*7-5-3*/ + if (chklim && nel >= chklim) { /* check if already ascending order */ + char *p; + chklim = 0; + for (p=l; p 0) {mmswap(l,r); goto loopB;} /*5-5-3*/ + + /* deteming splitting type in case 5-5-5 */ /*5-5-5*/ + for (;;) { + if ((l += size) == r) goto nxt; /*5-5-5*/ + if (l == m) continue; + if ((t = (*cmp)(l,m)) > 0) {mmswap(l,r); l = L; goto loopA;} /*575-5*/ + if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/ + } + + loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */ + for (;;) { + for (;;) { + if ((l += size) == r) + {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} + if (l == m) continue; + if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} + if (t < 0) eq_l = 0; + } + for (;;) { + if (l == (r -= size)) + {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} + if (r == m) {m = l; break;} + if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} + if (t == 0) break; + } + mmswap(l,r); /* swap left and right */ + } + + loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */ + for (;;) { + for (;;) { + if (l == (r -= size)) + {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} + if (r == m) continue; + if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} + if (t > 0) eq_r = 0; + } + for (;;) { + if ((l += size) == r) + {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} + if (l == m) {m = r; break;} + if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} + if (t == 0) break; + } + mmswap(l,r); /* swap left and right */ + } + + fin: + if (eq_l == 0) /* need to sort left side */ + if (eq_r == 0) /* need to sort right side */ + if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */ + else {PUSH(L,l); L = r;} /* sort right side first */ + else R = l; /* need to sort left side only */ + else if (eq_r == 0) L = r; /* need to sort right side only */ + else goto nxt; /* need not to sort both sides */ + } } char * diff --git a/variable.c b/variable.c index 4f8ed302b7..156a36f757 100644 --- a/variable.c +++ b/variable.c @@ -249,7 +249,7 @@ VALUE rb_f_autoload(obj, klass, file) VALUE obj, klass, file; { - rb_autoload_id(rb_to_id(klass), STR2CSTR(file)); + rb_autoload_id(rb_to_id(klass), StringValuePtr(file)); return Qnil; } @@ -1062,10 +1062,11 @@ rb_const_get(klass, id) VALUE klass; ID id; { - VALUE value; - VALUE tmp; + VALUE value, tmp; + int mod_retry = 0; tmp = klass; + retry: while (tmp) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { return value; @@ -1073,15 +1074,18 @@ rb_const_get(klass, id) if (tmp == rb_cObject && top_const_get(id, &value)) return value; tmp = RCLASS(tmp)->super; } - if (BUILTIN_TYPE(klass) == T_MODULE) { - return rb_const_get(rb_cObject, id); + if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) { + mod_retry = 1; + tmp = rb_cObject; + goto retry; } /* Uninitialized constant */ - if (klass && klass != rb_cObject) - rb_raise(rb_eNameError, "uninitialized constant %s::%s", - RSTRING(rb_class_path(klass))->ptr, - rb_id2name(id)); + if (klass && klass != rb_cObject) { + rb_raise(rb_eNameError, "uninitialized constant %s at %s", + rb_id2name(id), + RSTRING(rb_class_path(klass))->ptr); + } else { rb_raise(rb_eNameError, "uninitialized constant %s",rb_id2name(id)); } @@ -1306,9 +1310,6 @@ rb_define_const(klass, name, val) if (klass == rb_cObject) { rb_secure(4); } - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "wrong constant name %s", name); - } rb_const_set(klass, id, val); } @@ -1424,7 +1425,11 @@ rb_cv_set(klass, name, val) const char *name; VALUE val; { - rb_cvar_set(klass, rb_intern(name), val); + ID id = rb_intern(name); + if (!rb_is_class_id(id)) { + rb_raise(rb_eNameError, "wrong class variable name %s", name); + } + rb_cvar_set(klass, id, val); } VALUE @@ -1432,7 +1437,11 @@ rb_cv_get(klass, name) VALUE klass; const char *name; { - return rb_cvar_get(klass, rb_intern(name)); + ID id = rb_intern(name); + if (!rb_is_class_id(id)) { + rb_raise(rb_eNameError, "wrong class variable name %s", name); + } + return rb_cvar_get(klass, id); } void diff --git a/version.h b/version.h index 29d506b8a2..3af2f30396 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.0" -#define RUBY_RELEASE_DATE "2001-04-02" +#define RUBY_RELEASE_DATE "2001-05-02" #define RUBY_VERSION_CODE 170 -#define RUBY_RELEASE_CODE 20010402 +#define RUBY_RELEASE_CODE 20010502