summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog270
-rw-r--r--ToDo4
-rw-r--r--array.c119
-rw-r--r--bignum.c20
-rw-r--r--class.c87
-rw-r--r--defines.h10
-rw-r--r--dir.c15
-rw-r--r--dln.c21
-rw-r--r--dln.h2
-rw-r--r--error.c43
-rw-r--r--eval.c306
-rw-r--r--ext/curses/curses.c4
-rw-r--r--ext/dbm/dbm.c46
-rw-r--r--ext/dbm/extconf.rb35
-rw-r--r--ext/gdbm/MANIFEST1
-rw-r--r--ext/gdbm/gdbm.c337
-rw-r--r--ext/md5/md5init.c11
-rw-r--r--file.c203
-rw-r--r--gc.c38
-rw-r--r--hash.c35
-rw-r--r--intern.h29
-rw-r--r--io.c78
-rw-r--r--marshal.c13
-rw-r--r--node.h16
-rw-r--r--numeric.c20
-rw-r--r--object.c69
-rw-r--r--pack.c70
-rw-r--r--parse.y53
-rw-r--r--process.c83
-rw-r--r--re.c26
-rw-r--r--regex.c12
-rw-r--r--ruby.c22
-rw-r--r--ruby.h53
-rw-r--r--rubyio.h2
-rw-r--r--rubysig.h2
-rw-r--r--signal.c2
-rw-r--r--sprintf.c5
-rw-r--r--st.c9
-rw-r--r--string.c85
-rw-r--r--struct.c2
-rw-r--r--time.c60
-rw-r--r--util.c305
-rw-r--r--variable.c37
-rw-r--r--version.h4
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 <kosako@sofnec.co.jp>
+
+ * eval.c (block_pass): should not downgrade safe level.
+
+Wed May 2 03:07:49 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * string.c (rb_str_insert): new method.
+
+Tue May 1 17:55:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG.
+
+Tue May 1 16:23:03 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_insert): new method.
+
+ * array.c (rb_ary_update): new utility function.
+
Tue May 1 03:24:05 2001 Akinori MUSHA <knu@iDaemons.org>
* 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 <knu@iDaemons.org>
* lib/irb/main.rb: This file is not needed anymore.
+Fri Apr 27 09:27:10 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (set_outfile): should check if closed before assignment.
+
Thu Apr 26 22:36:11 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* configure.in: don't use tzname on cygwin 1.3.1+.
@@ -19,6 +48,36 @@ Thu Apr 26 22:36:11 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* 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 <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): should preserve value of ruby_errinfo.
+
+Thu Apr 26 10:36:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): infinite sleep should not cause
+ dead lock.
+
+Wed Apr 25 16:40:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_flatten_bang): proper recursive detection.
+
+Wed Apr 25 15:36:15 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (yield_under): need not to prohibit at safe level 4.
+
+Wed Apr 25 15:22:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <knu@iDaemons.org>
* 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 <knu@iDaemons.org>
* 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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * marshal.c (w_float): precision changed to "%.16g"
+
+Sat Apr 21 22:07:58 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * eval.c (rb_call0): wrong retry behavior.
+
+Fri Apr 20 19:12:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_aref): a bug on long>int architecture.
+
+Fri Apr 20 14:57:15 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_eval_string_wrap): should restore ruby_wrapper.
+
Sun Apr 22 17:44:37 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* configure.in: add -mieee to CFLAGS on Linux/Alpha
@@ -38,16 +124,145 @@ Wed Apr 18 04:37:51 2001 Wakou Aoyama <wakou@fsinet.or.jp>
* lib/cgi.rb: CGI::Cookie: no use PATH_INFO.
+Wed Apr 18 00:24:40 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): char class at either edge of range
+ should be invalid.
+
+Tue Apr 17 17:33:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <kosako@sofnec.co.jp>
+
+ * eval.c (safe_getter): should use INT2NUM().
+
+Tue Apr 17 15:12:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long.
+
+Sat Apr 14 22:46:43 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * regex.c (calculate_must_string): wrong length calculation.
+
Sat Apr 14 13:37:32 2001 Usaku Nakamura <usa@osb.att.ne.jp>
* win32/config.status.in: no longer use missing/alloca.c.
* win32/Makefile.sub: ditto.
+Fri Apr 13 12:40:48 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_thread_start_0): fixed memory leak.
+
+Fri Apr 13 16:41:18 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (none): should clear cmdarg_stack too.
+
+Fri Apr 13 06:19:29 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+
+ * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on
+ some platforms.
+
+Wed Apr 11 23:36:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <kosako@sofnec.co.jp>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * eval.c (rb_mod_included): new hook called from rb_mod_include().
+
+Tue Apr 10 02:24:40 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * io.c (opt_i_set): should strdup() inplace_edit string.
+
+Mon Apr 9 23:29:54 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (exec_under): need to push cref too.
+
+Mon Apr 9 15:20:21 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * file.c (Init_File): should redifine "new" class method.
+
Mon Apr 9 11:56:52 2001 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb: fix typo.
+Fri Apr 6 01:46:35 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <kosako@sofnec.co.jp>
+
+ * object.c (rb_obj_is_instance_of): nil belongs to false, not true.
+
+Thu Apr 5 02:19:03 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <eban@ruby-lang.org>
* ext/extmk.rb.in (create_makefile): create def file only if
@@ -55,6 +270,26 @@ Tue Apr 3 09:56:20 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* lib/mkmf.rb: ditto.
+Tue Apr 3 00:05:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <shugo@ruby-lang.org>
* lib/monitor.rb (wait): ensure reentrance.
@@ -87,14 +322,49 @@ Mon Apr 2 01:16:24 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* win32/dir.h, dir.c, Makefile: ditto.
+Sun Apr 1 23:26:14 2001 TOYOFUKU Chikanobu <toyofuku@juice.or.jp>
+
+ * numeric.c (flodivmod): a bug in no fmod case.
+
+Sun Apr 1 18:36:14 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * process.c (pst_wifsignaled): should apply WIFSIGNALED for status
+ (int), not st (VALUE).
+
Sat Mar 31 04:47:55 2001 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb: add document and example code.
+Sat Mar 31 03:24:10 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <shugo@ruby-lang.org>
* lib/net/imap.rb: rename ContinueRequest to ContinuationRequest.
+Fri Mar 30 12:51:19 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): freeze check at first.
+
+Thu Mar 29 17:05:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_attr): sprintf() and rb_intern() moved into
+ conditional body.
+
Wed Mar 28 23:43:00 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* 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,13 +583,29 @@ 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
@@ -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; i<RARRAY(ary)->len; i++) {
+ while (i<RARRAY(ary)->len) {
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 (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;
@@ -54,6 +44,47 @@ clone_method(mid, body, tbl)
}
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);
@@ -5526,6 +5547,13 @@ rb_mod_modfunc(argc, argv, 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; i<argc; i++) {
Check_Type(argv[i], T_MODULE);
rb_funcall(argv[i], rb_intern("append_features"), 1, module);
+ rb_funcall(argv[i], rb_intern("included"), 1, module);
}
return module;
}
@@ -5849,6 +5878,7 @@ Init_eval()
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
+ rb_define_private_method(rb_cModule, "included", rb_mod_included, 1);
rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
@@ -5914,6 +5944,9 @@ Init_load()
rb_define_global_function("require", rb_f_require, 1);
rb_define_global_function("autoload", rb_f_autoload, 2);
rb_global_variable(&ruby_wrapper);
+
+ ruby_dln_librefs = rb_ary_new();
+ rb_global_variable(&ruby_dln_librefs);
}
static void
@@ -5982,6 +6015,7 @@ blk_copy_prev(block)
struct BLOCK *block;
{
struct BLOCK *tmp;
+ struct RVarmap* vars;
while (block->prev) {
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
+
+def db_prefix(func)
+ $db_prefix+func
end
-gdbm or have_library("db", "dbm_open") or have_library("dbm", "dbm_open")
+
+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 <fcntl.h>
#include <errno.h>
-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;
}
@@ -249,6 +321,36 @@ fgdbm_indexes(argc, argv, obj)
}
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; i<args->len; 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; i<n; i++) {
switch (TYPE(argv[i])) {
case T_STRING:
- SafeStr(argv[i]);
+ SafeStringValue(argv[i]);
break;
case T_FILE:
break;
@@ -1805,6 +1814,30 @@ rb_f_test(argc, argv)
}
static VALUE
+rb_stat_s_new(klass, fname)
+ VALUE klass, fname;
+{
+ VALUE s;
+ struct stat st;
+
+ Check_SafeStr(fname);
+ if (stat(RSTRING(fname)->ptr, &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;i<RARRAY(rb_load_path)->len;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 <sys/types.h>
#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__)
#include <sys/ioctl.h>
@@ -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; i<sizeof(double);i++) {
hash += c[i] * 971;
@@ -593,8 +595,8 @@ static VALUE
flo_eql(x, y)
VALUE x, y;
{
- if (TYPE(y) == T_FLOAT) {
- if (RFLOAT(x)->value == 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<<i))
+ }
+ if (val & (1L<<i))
return INT2FIX(1);
return INT2FIX(0);
}
diff --git a/object.c b/object.c
index fa08e0ae19..efc1874a27 100644
--- a/object.c
+++ b/object.c
@@ -226,12 +226,10 @@ rb_obj_is_instance_of(obj, c)
return Qfalse;
case T_FALSE:
- if (obj) return Qfalse;
- return Qtrue;
+ return RTEST(obj) ? Qfalse : Qtrue;
case T_TRUE:
- if (obj) return Qtrue;
- return Qfalse;
+ return RTEST(obj) ? Qtrue : Qfalse;
default:
rb_raise(rb_eTypeError, "class or module required");
@@ -380,7 +378,7 @@ nil_plus(x, y)
return y;
default:
rb_raise(rb_eTypeError, "tried to add %s(%s) to nil",
- STR2CSTR(rb_inspect(y)),
+ RSTRING(rb_inspect(y))->ptr,
rb_class2name(CLASS_OF(y)));
}
/* not reached */
@@ -533,36 +531,6 @@ sym_intern(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 : {
$<vars>$ = 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 = $<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();
$<num>$ = ruby_sourceline;
}
@@ -1259,7 +1250,6 @@ primary : literal
$$ = NEW_CLASS($2, $5, $3);
nd_set_line($$, $<num>4);
local_pop();
- cref_pop();
class_nest--;
}
| kCLASS tLSHFT expr
@@ -1272,7 +1262,6 @@ primary : literal
$<num>$ = 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 = $<num>4;
in_single = $<num>6;
@@ -1291,7 +1279,6 @@ primary : literal
if (in_def || in_single)
yyerror("module definition in method body");
class_nest++;
- cref_push();
local_push();
$<num>$ = ruby_sourceline;
}
@@ -1301,7 +1288,6 @@ primary : literal
$$ = NEW_MODULE($2, $4);
nd_set_line($$, $<num>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;
+
+ result = rb_ary_new();
#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;
+ 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; i<argc; i++) {
- SafeStr(argv[i]);
+ SafeStringValue(argv[i]);
args[i] = RSTRING(argv[i])->ptr;
}
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)
+
+VALUE rb_str_to_str _((VALUE));
+#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 SafeStr(v) */
+/* obsolete macro - use SafeStringValue(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 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];
}
@@ -1080,6 +1074,14 @@ rb_str_aset_m(argc, argv, str)
}
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;
VALUE *argv;
@@ -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; i<argc; i++) {
VALUE s = argv[i];
- if (TYPE(s) != T_STRING)
- s = rb_str_to_str(s);
+ StringValue(s);
tr_setup_table(s, squeez, init);
init = 0;
}
@@ -2046,8 +2049,7 @@ rb_str_squeeze_bang(argc, argv, str)
for (i=0; i<argc; i++) {
VALUE s = argv[i];
- if (TYPE(s) != T_STRING)
- s = rb_str_to_str(s);
+ StringValue(s);
tr_setup_table(s, squeez, init);
init = 0;
}
@@ -2118,8 +2120,7 @@ rb_str_count(argc, argv, str)
for (i=0; i<argc; i++) {
VALUE s = argv[i];
- if (TYPE(s) != T_STRING)
- s = rb_str_to_str(s);
+ StringValue(s);
tr_setup_table(s, table, init);
init = 0;
}
@@ -2284,7 +2285,7 @@ rb_str_split(str, sep0)
{
VALUE sep;
- if (TYPE(str) != T_STRING) str = rb_str_to_str(str);
+ StringValue(str);
sep = rb_str_new2(sep0);
return rb_str_split_m(1, &sep, str);
}
@@ -2319,10 +2320,7 @@ rb_str_each_line(argc, argv, str)
rb_yield(str);
return str;
}
- if (TYPE(rs) != T_STRING) {
- rs = rb_str_to_str(rs);
- }
-
+ StringValue(rs);
rslen = RSTRING(rs)->len;
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 */
-
- 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<r; p+=size) if ((*cmp)(p,p+size) > 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<r; p+=size) if ((*cmp)(p,p+size) < 0) goto fail2;
- while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
- goto nxt;
- }
- fail2: mmswap(l,r); goto loopA; /*7-5-3*/
- }
- if (t < 0) {
- if ((*cmp)(l,r) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
- mmrot3(l,m,r); goto loopA; /*7-5-6*/
- }
- mmswap(l,r); goto loopA; /*7-5-5*/
- }
-
- if ((t = (*cmp)(m,r)) < 0) {goto loopA;} /*5-5-7*/
- if (t > 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 */
- }
+ 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<r; p+=size) if ((*cmp)(p,p+size) > 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<r; p+=size) if ((*cmp)(p,p+size) < 0) goto fail2;
+ while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
+ goto nxt;
+ }
+ fail2: mmswap(l,r); goto loopA; /*7-5-3*/
+ }
+ if (t < 0) {
+ if ((*cmp)(l,r) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
+ mmrot3(l,m,r); goto loopA; /*7-5-6*/
+ }
+ mmswap(l,r); goto loopA; /*7-5-5*/
+ }
+
+ if ((t = (*cmp)(m,r)) < 0) {goto loopA;} /*5-5-7*/
+ if (t > 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