summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog128
-rw-r--r--ToDo10
-rw-r--r--array.c209
-rw-r--r--class.c3
-rw-r--r--enum.c47
-rw-r--r--error.c4
-rw-r--r--ext/curses/curses.c60
-rw-r--r--gc.c12
-rw-r--r--hash.c41
-rw-r--r--io.c31
-rw-r--r--object.c3
-rw-r--r--parse.y22
-rw-r--r--regex.c2
-rw-r--r--ruby.h17
-rw-r--r--sample/test.rb57
-rw-r--r--string.c225
-rw-r--r--time.c55
-rw-r--r--util.c59
-rw-r--r--version.h4
19 files changed, 653 insertions, 336 deletions
diff --git a/ChangeLog b/ChangeLog
index 64664b74c8..ed890318a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,53 @@
-Sun Dec 9 23:00:54 2001 Keiju Ishitsuka <keiju@ishitsuka.com>
- * matrix.rb: Vector#* bug. reported from Massimiliano Mirra
- <info@chromatic-harp.com>.
-
-Sun Dec 9 22:15:59 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+Mon Dec 10 02:09:28 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
- * enum.c (enum_sort_by): should replace with last elements.
+ * array.c (rb_ary_modify): should copy the internal buffer if the
+ modifying buffer is shared.
+
+ * array.c (ary_make_shared): make an internal buffer of an array
+ to be shared.
+
+ * array.c (rb_ary_shift): avoid sliding an internal buffer by
+ using shared buffer.
+
+ * array.c (rb_ary_subseq): avoid copying the buffer.
+
+Mon Dec 10 01:06:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (gettable): should freeze __LINE__ string.
Sun Dec 9 18:06:26 2001 Minero Aoki <aamine@loveruby.net>
* lib/net/protocol.rb: calls on_connect before conn_command
+Sat Dec 8 23:27:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_puts): old behavoir restored. rationale: a) if you
+ want to call to_s for arrays, you can just call print a, "\n".
+ b) to_s wastes memory if array (and sum of its contents) is
+ huge. c) now any object that has to_ary is treated as an array,
+ using rb_check_convert_type().
+
+Sat Dec 8 22:40:38 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_initialize): now accepts a block to calculate
+ the default value. [new]
+
+ * hash.c (rb_hash_aref): call "default" method to get the value
+ corrensponding to the non existing key.
+
+ * hash.c (rb_hash_default): get the default value based on the
+ block given to 'new'. Now it takes an optinal "key" argument.
+ "default" became the method to get the value for non existing
+ key. Users may override "default" method to change the hash
+ behavior.
+
+ * hash.c (rb_hash_set_default): clear the flag if a block is given
+ to 'new'
+
+Sat Dec 8 02:29:54 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (Init_Object): undef Data.allocate, left Data.new.
+
Fri Dec 7 19:12:14 2001 Minero Aoki <aamine@loveruby.net>
* lib/net/smtp.rb: SMTP.new requires at least one arg.
@@ -27,12 +65,83 @@ Fri Dec 7 15:49:39 2001 Usaku Nakamura <usa@ruby-lang.org>
* ext/extmk.rb.in: ignore adding -Wl,-R to DLDFLAGS when the directory
is $topdir.
+Fri Dec 7 13:58:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/curses/curses.c (window_scrollok): use RTEST().
+
+ * ext/curses/curses.c (window_idlok): ditto.
+
+ * ext/curses/curses.c (window_keypad): ditto.
+
+ * ext/curses/curses.c (window_idlok): idlok() may return void on
+ some platforms; so don't use return value.
+
+ * ext/curses/curses.c (window_scrollok): ditto for consistency.
+
+ * ext/curses/curses.c: replace FIX2INT() by typechecking NUM2INT().
+
+Fri Dec 7 09:51:00 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (str_extend): should not process immature #$x and
+ #@x interpolation, e.g #@#@ etc.
+
+Fri Dec 7 03:21:18 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enum.c (enum_sort_by): sort_by does not have to be stable always.
+
+ * enum.c (enum_sort_by): call qsort directly to gain performance.
+
Thu Dec 6 18:52:28 2001 Usaku Nakamura <usa@ruby-lang.org>
* ext/extmk.rb.in: add -Wl,-R flags to DLDFLAGS on netbsdelf.
* lib/mkmf.rb: ditto.
+Thu Dec 6 09:15:14 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_qsort): ruby_qsort(qs6) is now native thread safe.
+
+ * error.c (rb_sys_fail): it must be a bug if it's called when
+ errno == 0.
+
+Wed Dec 5 23:36:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (WC2MBC1ST): should not pass through > 0x80 number in UTF-8.
+
+Tue Dec 4 17:43:10 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (DUPSETUP): new SETUP macro for duplication.
+
+ * time.c (time_dup): implement in Time class using DUPSETUP.
+
+ * time.c (time_getlocaltime): new method; probably requires
+ better name than getlocaltime. [new,experimental]
+
+ * time.c (time_getgmtime): ditto.
+
+ * array.c (rb_ary_dup): uses DUPSETUP.
+
+ * string.c (rb_str_dup): uses DUPSETUP. now properly copies
+ instance variables too.
+
+Tue Dec 4 03:49:06 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_fread): EAGAIN/EWOULDBLOCK should not terminate and
+ throw away the input.
+
+ * time.c (time_new_internal): underflow adjustment must not use
+ negative div/mod.
+
+ * time.c (time_cmp): should consider tv_usec on non Fixnum number
+ comparison.
+Sun Dec 9 23:00:54 2001 Keiju Ishitsuka <keiju@ishitsuka.com>
+ * matrix.rb: Vector#* bug. reported from Massimiliano Mirra
+ <info@chromatic-harp.com>.
+
+Sun Dec 9 22:15:59 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * enum.c (enum_sort_by): should replace with last elements.
+
Mon Dec 3 16:06:57 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/socket/extconf.rb: remove -L/usr/local/lib.
@@ -43,6 +152,13 @@ Mon Dec 3 16:04:16 2001 Usaku Nakamura <usa@ruby-lang.org>
* configure.in: not use X11BASE, since it's not always set.
+Mon Dec 3 13:53:49 2001 Tanaka Akira <akr@m17n.org>
+
+ * time.c (rb_strftime): buffer length condition was wrong.
+
+ * time.c (time_strftime): should backup buf to the original
+ buffer.
+
Mon Dec 3 09:59:08 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* time.c (time_plus): must detect result overflow.
diff --git a/ToDo b/ToDo
index b43679b8a1..4c826c0528 100644
--- a/ToDo
+++ b/ToDo
@@ -71,9 +71,11 @@ Standard Libraries
- fork_and_kill_other_threads.
- signal list (Signal::trap, Signal::list).
- move NameError under StandardError.
+- Integer#to_s(base)
+- Hash::new{default}
+- hash etc. should handle self referenceing array/hash
* String#scanf(?)
* Object#fmt(?)
-* Integer#{bin,oct,hex,heX}
* Time::strptime
* Integer[num], Float[num]; Fixnum[num]?
* method to retrieve non-number trailer for to_i/to_f.
@@ -86,16 +88,16 @@ Standard Libraries
* Array#&, Array#| to allow duplication. ???
* way to specify immortal (fork endurance) thread;
* or raise ForkException to every thread but fork caller.
-* Hash::new{default} or recommend Hash#fetch?
* new user-defined marshal scheme. _dump(dumper), _load(restorer)
-* hash etc. should handle self referenceing array/hash
* library to load per-user profile seeking .ruby_profile or ruby.ini file.
* warning framework (warn, warning for Ruby level)
-* marshal should not depend on sprintf/strtod (works bad for locale).
+* marshal should not depend on sprintf/strtod (works bad with locale).
* ternary arg pow: a.pow(b,c) == a**b%c
* new caller(), e.g. call_stack; needs better name.
* remove dependency on MAXPATHLEN.
* pointer share mechanism similar to one in String for Array.
+* Array#select(n1,n2...) works like Array#indexes(n1,n2...)
+* deprecate Array#indexes, and Array#indices.
Extension Libraries
diff --git a/array.c b/array.c
index 6a419d800e..0401dd3598 100644
--- a/array.c
+++ b/array.c
@@ -17,7 +17,7 @@
#include "st.h"
VALUE rb_cArray;
-static ID cmp;
+static ID id_cmp;
#define ARY_DEFAULT_SIZE 16
@@ -45,7 +45,7 @@ memfill(mem, size, val)
#define ARY_TMPLOCK FL_USER1
static void
-rb_ary_modify(ary)
+rb_ary_modify_check(ary)
VALUE ary;
{
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
@@ -55,6 +55,21 @@ rb_ary_modify(ary)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
+static void
+rb_ary_modify(ary)
+ VALUE ary;
+{
+ VALUE *ptr;
+
+ rb_ary_modify_check(ary);
+ if (!FL_TEST(ary, ELTS_SHARED)) return;
+ ptr = ALLOC_N(VALUE, RARRAY(ary)->len);
+ FL_UNSET(ary, ELTS_SHARED);
+ RARRAY(ary)->aux.capa = RARRAY(ary)->len;
+ MEMCPY(ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
+ RARRAY(ary)->ptr = ptr;
+}
+
VALUE
rb_ary_freeze(ary)
VALUE ary;
@@ -79,14 +94,14 @@ rb_ary_s_alloc(klass)
OBJSETUP(ary, klass, T_ARRAY);
ary->len = 0;
- ary->capa = 0;
ary->ptr = 0;
+ ary->aux.capa = 0;
return (VALUE)ary;
}
-VALUE
-rb_ary_new0(klass, len)
+static VALUE
+ary_new(klass, len)
VALUE klass;
long len;
{
@@ -100,7 +115,7 @@ rb_ary_new0(klass, len)
}
if (len == 0) len++;
RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
- RARRAY(ary)->capa = len;
+ RARRAY(ary)->aux.capa = len;
return ary;
}
@@ -109,7 +124,7 @@ VALUE
rb_ary_new2(len)
long len;
{
- return rb_ary_new0(rb_cArray, len);
+ return ary_new(rb_cArray, len);
}
@@ -228,9 +243,9 @@ rb_ary_initialize(argc, argv, ary)
if (len > 0 && len*sizeof(VALUE) <= 0) {
rb_raise(rb_eArgError, "array size too big");
}
- if (len > RARRAY(ary)->capa) {
- RARRAY(ary)->capa = len;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (len > RARRAY(ary)->aux.capa) {
+ RARRAY(ary)->aux.capa = len;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
memfill(RARRAY(ary)->ptr, len, val);
RARRAY(ary)->len = len;
@@ -250,7 +265,7 @@ rb_ary_s_create(argc, argv, klass)
RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
}
- RARRAY(ary)->len = RARRAY(ary)->capa = argc;
+ RARRAY(ary)->len = RARRAY(ary)->aux.capa = argc;
return ary;
}
@@ -270,13 +285,13 @@ rb_ary_store(ary, idx, val)
}
}
- if (idx >= RARRAY(ary)->capa) {
- long capa_inc = RARRAY(ary)->capa / 2;
+ if (idx >= RARRAY(ary)->aux.capa) {
+ long capa_inc = RARRAY(ary)->aux.capa / 2;
if (capa_inc < ARY_DEFAULT_SIZE) {
capa_inc = ARY_DEFAULT_SIZE;
}
- RARRAY(ary)->capa = idx + capa_inc;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ RARRAY(ary)->aux.capa = idx + capa_inc;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
if (idx > RARRAY(ary)->len) {
rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,
@@ -319,34 +334,45 @@ VALUE
rb_ary_pop(ary)
VALUE ary;
{
- rb_ary_modify(ary);
+ rb_ary_modify_check(ary);
if (RARRAY(ary)->len == 0) return Qnil;
- if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) {
- RARRAY(ary)->capa = RARRAY(ary)->len * 2;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (RARRAY(ary)->len * 10 < RARRAY(ary)->aux.capa && RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
+ RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
return RARRAY(ary)->ptr[--RARRAY(ary)->len];
}
+static void
+ary_make_shared(ary)
+ VALUE ary;
+{
+ if (FL_TEST(ary, ELTS_SHARED)) return;
+ else {
+ NEWOBJ(shared, struct RArray);
+ OBJSETUP(shared, rb_cArray, T_ARRAY);
+
+ shared->len = RARRAY(ary)->len;
+ shared->ptr = RARRAY(ary)->ptr;
+ shared->aux.capa = RARRAY(ary)->aux.capa;
+ RARRAY(ary)->aux.shared = (VALUE)shared;
+ FL_SET(ary, ELTS_SHARED);
+ }
+}
+
VALUE
rb_ary_shift(ary)
VALUE ary;
{
VALUE top;
- rb_ary_modify(ary);
+ rb_ary_modify_check(ary);
if (RARRAY(ary)->len == 0) return Qnil;
-
top = RARRAY(ary)->ptr[0];
+ ary_make_shared(ary);
+ RARRAY(ary)->ptr++; /* shift ptr */
RARRAY(ary)->len--;
- /* sliding items */
- MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+1, VALUE, RARRAY(ary)->len);
- if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) {
- RARRAY(ary)->capa = RARRAY(ary)->len * 2;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
- }
-
return top;
}
@@ -355,13 +381,13 @@ rb_ary_unshift(ary, item)
VALUE ary, item;
{
rb_ary_modify(ary);
- if (RARRAY(ary)->len >= RARRAY(ary)->capa) {
- long capa_inc = RARRAY(ary)->capa / 2;
+ if (RARRAY(ary)->len >= RARRAY(ary)->aux.capa) {
+ long capa_inc = RARRAY(ary)->aux.capa / 2;
if (capa_inc < ARY_DEFAULT_SIZE) {
capa_inc = ARY_DEFAULT_SIZE;
}
- RARRAY(ary)->capa+=capa_inc;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ RARRAY(ary)->aux.capa+=capa_inc;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
/* sliding items */
@@ -429,11 +455,14 @@ rb_ary_subseq(ary, beg, len)
len = 0;
}
klass = rb_obj_class(ary);
- if (len == 0) return rb_ary_new0(klass,0);
+ if (len == 0) return ary_new(klass,0);
- ary2 = rb_ary_new0(klass, len);
- MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len);
+ ary_make_shared(ary);
+ ary2 = rb_obj_alloc(klass);
+ RARRAY(ary2)->ptr = RARRAY(ary)->ptr+beg;
RARRAY(ary2)->len = len;
+ RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared;
+ FL_SET(ary2, ELTS_SHARED);
return ary2;
}
@@ -609,9 +638,9 @@ rb_ary_update(ary, beg, len, rpl)
rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
len = beg + rlen;
- if (len >= RARRAY(ary)->capa) {
- RARRAY(ary)->capa=len;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (len >= RARRAY(ary)->aux.capa) {
+ RARRAY(ary)->aux.capa=len;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len);
MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, rlen);
@@ -625,9 +654,9 @@ rb_ary_update(ary, beg, len, rpl)
}
alen = RARRAY(ary)->len + rlen - len;
- if (alen >= RARRAY(ary)->capa) {
- RARRAY(ary)->capa = alen;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (alen >= RARRAY(ary)->aux.capa) {
+ RARRAY(ary)->aux.capa = alen;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
if (len != rlen) {
@@ -749,32 +778,51 @@ rb_ary_empty_p(ary)
}
static VALUE
-rb_ary_clone(ary)
+ary_copy(ary, clone)
VALUE ary;
+ int clone;
{
- VALUE clone = rb_ary_new2(RARRAY(ary)->len);
+ VALUE copy;
+
+ ary_make_shared(ary);
+ copy = rb_obj_alloc(rb_cArray);
+ if (clone) CLONESETUP(copy, ary);
+ else DUPSETUP(copy, ary);
+ RARRAY(copy)->ptr = RARRAY(ary)->ptr;
+ RARRAY(copy)->len = RARRAY(ary)->len;
+ RARRAY(copy)->aux.shared = RARRAY(ary)->aux.shared;
+ FL_SET(copy, ELTS_SHARED);
+
+ return copy;
+}
- CLONESETUP(clone, ary);
- MEMCPY(RARRAY(clone)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- RARRAY(clone)->len = RARRAY(ary)->len;
- return clone;
+static VALUE
+rb_ary_clone(ary)
+ VALUE ary;
+{
+ return ary_copy(ary, Qtrue);
}
VALUE
rb_ary_dup(ary)
VALUE ary;
{
+ return ary_copy(ary, Qfalse);
+}
+
+static VALUE
+ary_dup(ary)
+ VALUE ary;
+{
VALUE dup = rb_ary_new2(RARRAY(ary)->len);
- OBJSETUP(dup, rb_obj_class(ary), T_ARRAY);
+ DUPSETUP(dup, ary);
MEMCPY(RARRAY(dup)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
RARRAY(dup)->len = RARRAY(ary)->len;
- OBJ_INFECT(dup, ary);
return dup;
}
extern VALUE rb_output_fs;
-extern VALUE rb_default_rs;
static VALUE
inspect_join(ary, arg)
@@ -861,9 +909,6 @@ rb_ary_to_s(ary)
if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
sep = rb_output_fs;
-#if 1
- if (NIL_P(rb_output_fs)) sep = rb_default_rs; /* newline */
-#endif
str = rb_ary_join(ary, sep);
return str;
}
@@ -1006,7 +1051,7 @@ static VALUE
rb_ary_reverse_m(ary)
VALUE ary;
{
- return rb_ary_reverse(rb_ary_dup(ary));
+ return rb_ary_reverse(ary_dup(ary));
}
int
@@ -1018,8 +1063,8 @@ rb_cmpint(cmp)
if (RBIGNUM(cmp)->sign) return 1;
return -1;
}
- if (rb_funcall(cmp, '>', 1, INT2FIX(0))) return 1;
- if (rb_funcall(cmp, '<', 1, INT2FIX(0))) return -1;
+ if (rb_funcall(id_cmp, '>', 1, INT2FIX(0))) return 1;
+ if (rb_funcall(id_cmp, '<', 1, INT2FIX(0))) return -1;
return 0;
}
@@ -1044,7 +1089,7 @@ sort_2(a, b)
return rb_str_cmp(*a, *b);
}
- retval = rb_funcall(*a, cmp, 1, *b);
+ retval = rb_funcall(*a, id_cmp, 1, *b);
return rb_cmpint(retval);
}
@@ -1081,32 +1126,12 @@ VALUE
rb_ary_sort(ary)
VALUE ary;
{
- ary = rb_ary_dup(ary);
+ ary = ary_dup(ary);
rb_ary_sort_bang(ary);
return ary;
}
static VALUE
-sort_inplace(ary)
- VALUE ary;
-{
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),sort_2);
- return ary;
-}
-
-VALUE
-rb_ary_sort_inplace(ary)
- VALUE ary;
-{
- rb_ary_modify(ary);
- if (RARRAY(ary)->len <= 1) return ary;
-
- FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */
- rb_ensure(sort_inplace, ary, sort_unlock, ary);
- return ary;
-}
-
-static VALUE
rb_ary_collect(ary)
VALUE ary;
{
@@ -1269,7 +1294,7 @@ static VALUE
rb_ary_reject(ary)
VALUE ary;
{
- ary = rb_ary_dup(ary);
+ ary = ary_dup(ary);
rb_ary_reject_bang(ary);
return ary;
}
@@ -1297,9 +1322,9 @@ rb_ary_clear(ary)
{
rb_ary_modify(ary);
RARRAY(ary)->len = 0;
- if (ARY_DEFAULT_SIZE*3 < RARRAY(ary)->capa) {
- RARRAY(ary)->capa = ARY_DEFAULT_SIZE * 2;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (ARY_DEFAULT_SIZE*3 < RARRAY(ary)->aux.capa) {
+ RARRAY(ary)->aux.capa = ARY_DEFAULT_SIZE * 2;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
return ary;
}
@@ -1337,9 +1362,9 @@ rb_ary_fill(argc, argv, ary)
rb_ary_modify(ary);
end = beg + len;
if (end > RARRAY(ary)->len) {
- if (end >= RARRAY(ary)->capa) {
- RARRAY(ary)->capa = end;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ if (end >= RARRAY(ary)->aux.capa) {
+ RARRAY(ary)->aux.capa = end;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
}
if (beg > RARRAY(ary)->len) {
rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,end-RARRAY(ary)->len);
@@ -1397,7 +1422,7 @@ rb_ary_times(ary, times)
}
len *= RARRAY(ary)->len;
- ary2 = rb_ary_new0(rb_obj_class(ary), len);
+ ary2 = ary_new(rb_obj_class(ary), len);
RARRAY(ary2)->len = len;
for (i=0; i<len; i+=RARRAY(ary)->len) {
@@ -1521,7 +1546,7 @@ rb_ary_cmp(ary, ary2)
len = RARRAY(ary2)->len;
}
for (i=0; i<len; i++) {
- VALUE v = rb_funcall(RARRAY(ary)->ptr[i],cmp,1,RARRAY(ary2)->ptr[i]);
+ VALUE v = rb_funcall(RARRAY(ary)->ptr[i],id_cmp,1,RARRAY(ary2)->ptr[i]);
if (v != INT2FIX(0)) {
return v;
}
@@ -1646,7 +1671,7 @@ static VALUE
rb_ary_uniq(ary)
VALUE ary;
{
- ary = rb_ary_dup(ary);
+ ary = ary_dup(ary);
rb_ary_uniq_bang(ary);
return ary;
}
@@ -1667,7 +1692,7 @@ rb_ary_compact_bang(ary)
if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) {
return Qnil;
}
- RARRAY(ary)->len = RARRAY(ary)->capa = (p - RARRAY(ary)->ptr);
+ RARRAY(ary)->len = RARRAY(ary)->aux.capa = (p - RARRAY(ary)->ptr);
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
return ary;
@@ -1677,7 +1702,7 @@ static VALUE
rb_ary_compact(ary)
VALUE ary;
{
- ary = rb_ary_dup(ary);
+ ary = ary_dup(ary);
rb_ary_compact_bang(ary);
return ary;
}
@@ -1755,7 +1780,7 @@ static VALUE
rb_ary_flatten(ary)
VALUE ary;
{
- ary = rb_ary_dup(ary);
+ ary = ary_dup(ary);
rb_ary_flatten_bang(ary);
return ary;
}
@@ -1847,5 +1872,5 @@ Init_Array()
rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
- cmp = rb_intern("<=>");
+ id_cmp = rb_intern("<=>");
}
diff --git a/class.c b/class.c
index 31d72757a0..48577a79ec 100644
--- a/class.c
+++ b/class.c
@@ -87,7 +87,8 @@ rb_mod_dup(mod)
VALUE mod;
{
VALUE dup = rb_mod_clone(mod);
- OBJSETUP(dup, RBASIC(mod)->klass, BUILTIN_TYPE(mod));
+
+ DUPSETUP(dup, mod);
if (FL_TEST(mod, FL_SINGLETON)) {
FL_SET(dup, FL_SINGLETON);
}
diff --git a/enum.c b/enum.c
index 352771fcaa..9e0cf19fc0 100644
--- a/enum.c
+++ b/enum.c
@@ -12,6 +12,7 @@
#include "ruby.h"
#include "node.h"
+#include "util.h"
VALUE rb_mEnumerable;
static ID id_each, id_eqq, id_cmp;
@@ -204,53 +205,41 @@ enum_sort(obj)
}
static VALUE
-sort_by_i(i, memo)
- VALUE i;
- NODE *memo;
+sort_by_i(i, ary)
+ VALUE i, ary;
{
VALUE v, e;
v = rb_yield(i);
- if (TYPE(v) == T_ARRAY) {
- int j, len = RARRAY(v)->len;
-
- e = rb_ary_new2(len+2);
- for (j=0; j<len; j++) {
- RARRAY(e)->ptr[j] = RARRAY(v)->ptr[j];
- }
- RARRAY(e)->ptr[j++] = INT2NUM(memo->u3.cnt);
- RARRAY(e)->ptr[j] = i;
- RARRAY(e)->len = len + 2;
- }
- else {
- e = rb_ary_new3(3, v, INT2NUM(memo->u3.cnt), i);
- }
- rb_ary_push(memo->u1.value, e);
- memo->u3.cnt++;
+ e = rb_assoc_new(v, i);
+ rb_ary_push(ary, e);
return Qnil;
}
-static VALUE
-sort_by_sort_body(a)
- VALUE a;
+static int
+sort_by_cmp(a, b)
+ VALUE *a, *b;
{
- return rb_ary_cmp(RARRAY(a)->ptr[0], RARRAY(a)->ptr[1]);
+ VALUE retval;
+
+ retval = rb_funcall(RARRAY(*a)->ptr[0], id_cmp, 1, RARRAY(*b)->ptr[0]);
+ return rb_cmpint(retval);
}
static VALUE
enum_sort_by(obj)
VALUE obj;
{
- VALUE ary = rb_ary_new2(2000);
- NODE *memo = rb_node_newnode(NODE_MEMO, ary, 0, 0);
+ VALUE ary;
long i;
- rb_iterate(rb_each, obj, sort_by_i, (VALUE)memo);
- rb_gc_force_recycle((VALUE)memo);
- rb_ary_sort_inplace(ary);
+ ary = rb_ary_new2((TYPE(obj) == T_ARRAY) ? RARRAY(obj)->len : 2000);
+ rb_iterate(rb_each, obj, sort_by_i, ary);
+ if (RARRAY(ary)->len <= 1) return ary;
+ qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp);
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE e = RARRAY(ary)->ptr[i];
- RARRAY(ary)->ptr[i] = RARRAY(e)->ptr[RARRAY(e)->len - 1];
+ RARRAY(ary)->ptr[i] = RARRAY(e)->ptr[1];
}
return ary;
diff --git a/error.c b/error.c
index 4d56f80e70..010a27243a 100644
--- a/error.c
+++ b/error.c
@@ -718,6 +718,10 @@ rb_sys_fail(mesg)
int n = errno;
VALUE ee;
+ if (errno == 0) {
+ rb_bug("rb_sys_fail() - errno == 0");
+ }
+
err = strerror(errno);
if (mesg) {
volatile VALUE tmp = rb_str_inspect(rb_str_new2(mesg));
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index c756c47caa..c1523823b6 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -460,18 +460,20 @@ static VALUE
curses_curs_set(VALUE obj, VALUE visibility)
{
int n;
- return (n = curs_set(FIX2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil;
+ return (n = curs_set(NUM2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil;
}
static VALUE
curses_scrl(VALUE obj, VALUE n)
{
+ /* may have to raise exception on ERR */
return (scrl(NUM2INT(n)) == OK) ? Qtrue : Qfalse;
}
static VALUE
curses_setscrreg(VALUE obj, VALUE top, VALUE bottom)
{
+ /* may have to raise exception on ERR */
return (setscrreg(NUM2INT(top), NUM2INT(bottom)) == OK) ? Qtrue : Qfalse;
}
@@ -479,21 +481,21 @@ static VALUE
curses_attroff(VALUE obj, VALUE attrs)
{
return window_attroff(rb_stdscr,attrs);
- /* return INT2FIX(attroff(FIX2INT(attrs))); */
+ /* return INT2FIX(attroff(NUM2INT(attrs))); */
}
static VALUE
curses_attron(VALUE obj, VALUE attrs)
{
return window_attron(rb_stdscr,attrs);
- /* return INT2FIX(attroff(FIX2INT(attrs))); */
+ /* return INT2FIX(attroff(NUM2INT(attrs))); */
}
static VALUE
curses_attrset(VALUE obj, VALUE attrs)
{
return window_attrset(rb_stdscr,attrs);
- /* return INT2FIX(attroff(FIX2INT(attrs))); */
+ /* return INT2FIX(attroff(NUM2INT(attrs))); */
}
static VALUE
@@ -513,20 +515,23 @@ curses_bkgd(VALUE obj, VALUE ch)
static VALUE
curses_start_color(VALUE obj)
{
+ /* may have to raise exception on ERR */
return (start_color() == OK) ? Qtrue : Qfalse;
}
static VALUE
curses_init_pair(VALUE obj, VALUE pair, VALUE f, VALUE b)
{
- return (init_pair(FIX2INT(pair),FIX2INT(f),FIX2INT(b)) == OK) ? Qtrue : Qfalse;
+ /* may have to raise exception on ERR */
+ return (init_pair(NUM2INT(pair),NUM2INT(f),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
}
static VALUE
curses_init_color(VALUE obj, VALUE color, VALUE r, VALUE g, VALUE b)
{
- return (init_color(FIX2INT(color),FIX2INT(r),
- FIX2INT(g),FIX2INT(b)) == OK) ? Qtrue : Qfalse;
+ /* may have to raise exception on ERR */
+ return (init_color(NUM2INT(color),NUM2INT(r),
+ NUM2INT(g),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
}
static VALUE
@@ -546,7 +551,7 @@ curses_color_content(VALUE obj, VALUE color)
{
short r,g,b;
- color_content(FIX2INT(color),&r,&g,&b);
+ color_content(NUM2INT(color),&r,&g,&b);
return rb_ary_new3(3,INT2FIX(r),INT2FIX(g),INT2FIX(b));
}
@@ -555,20 +560,20 @@ curses_pair_content(VALUE obj, VALUE pair)
{
short f,b;
- pair_content(FIX2INT(pair),&f,&b);
+ pair_content(NUM2INT(pair),&f,&b);
return rb_ary_new3(2,INT2FIX(f),INT2FIX(b));
}
static VALUE
curses_color_pair(VALUE obj, VALUE attrs)
{
- return INT2FIX(COLOR_PAIR(FIX2INT(attrs)));
+ return INT2FIX(COLOR_PAIR(NUM2INT(attrs)));
}
static VALUE
curses_pair_number(VALUE obj, VALUE attrs)
{
- return INT2FIX(PAIR_NUMBER(FIX2INT(attrs)));
+ return INT2FIX(PAIR_NUMBER(NUM2INT(attrs)));
}
#endif
@@ -591,7 +596,7 @@ no_mevent()
static void
curses_mousedata_free(struct mousedata *mdata)
{
- if( mdata->mevent )
+ if (mdata->mevent)
free(mdata->mevent);
};
@@ -604,7 +609,7 @@ curses_getmouse(VALUE obj)
val = Data_Make_Struct(cMouseEvent,struct mousedata,
0,curses_mousedata_free,mdata);
mdata->mevent = (MEVENT*)malloc(sizeof(MEVENT));
- return ( getmouse(mdata->mevent) == OK ) ? val : Qnil;
+ return (getmouse(mdata->mevent) == OK) ? val : Qnil;
};
static VALUE
@@ -898,8 +903,8 @@ window_box(argc, argv, self)
c = NUM2CHR(corn);
getyx(winp->window, cur_y, cur_x);
- x = FIX2INT(window_maxx(self)) - 1;
- y = FIX2INT(window_maxy(self)) - 1;
+ x = NUM2INT(window_maxx(self)) - 1;
+ y = NUM2INT(window_maxy(self)) - 1;
wmove(winp->window, 0, 0);
waddch(winp->window, c);
wmove(winp->window, y, 0);
@@ -1062,11 +1067,10 @@ static VALUE
window_scrollok(VALUE obj, VALUE bf)
{
struct windata *winp;
- int res;
GetWINDOW(obj, winp);
- res = scrollok(winp->window, (bf == Qtrue) ? TRUE : FALSE);
- return (res == OK) ? Qtrue : Qfalse;
+ scrollok(winp->window, RTEST(bf) ? TRUE : FALSE);
+ return Qnil;
}
static VALUE
@@ -1076,8 +1080,8 @@ window_idlok(VALUE obj, VALUE bf)
int res;
GetWINDOW(obj, winp);
- res = idlok(winp->window, (bf == Qtrue) ? TRUE : FALSE);
- return (res == OK) ? Qtrue : Qfalse;
+ idlok(winp->window, RTEST(bf) ? TRUE : FALSE);
+ return Qnil;
}
static VALUE
@@ -1088,6 +1092,7 @@ window_setscrreg(VALUE obj, VALUE top, VALUE bottom)
GetWINDOW(obj, winp);
res = wsetscrreg(winp->window, NUM2INT(top), NUM2INT(bottom));
+ /* may have to raise exception on ERR */
return (res == OK) ? Qtrue : Qfalse;
};
@@ -1097,6 +1102,7 @@ window_scroll(VALUE obj)
struct windata *winp;
GetWINDOW(obj, winp);
+ /* may have to raise exception on ERR */
return (scroll(winp->window) == OK) ? Qtrue : Qfalse;
}
@@ -1106,6 +1112,7 @@ window_scrl(VALUE obj, VALUE n)
struct windata *winp;
GetWINDOW(obj, winp);
+ /* may have to raise exception on ERR */
return (wscrl(winp->window,NUM2INT(n)) == OK) ? Qtrue : Qfalse;
}
@@ -1115,7 +1122,7 @@ window_attroff(VALUE obj, VALUE attrs)
struct windata *winp;
GetWINDOW(obj,winp);
- return INT2FIX(wattroff(winp->window,FIX2INT(attrs)));
+ return INT2FIX(wattroff(winp->window,NUM2INT(attrs)));
};
static VALUE
@@ -1125,10 +1132,10 @@ window_attron(VALUE obj, VALUE attrs)
VALUE val;
GetWINDOW(obj,winp);
- val = INT2FIX(wattron(winp->window,FIX2INT(attrs)));
+ val = INT2FIX(wattron(winp->window,NUM2INT(attrs)));
if( rb_block_given_p() ){
rb_yield(val);
- wattroff(winp->window,FIX2INT(attrs));
+ wattroff(winp->window,NUM2INT(attrs));
return val;
}
else{
@@ -1142,7 +1149,7 @@ window_attrset(VALUE obj, VALUE attrs)
struct windata *winp;
GetWINDOW(obj,winp);
- return INT2FIX(wattrset(winp->window,FIX2INT(attrs)));
+ return INT2FIX(wattrset(winp->window,NUM2INT(attrs)));
}
static VALUE
@@ -1182,10 +1189,11 @@ window_keypad(VALUE obj, VALUE val)
GetWINDOW(obj,winp);
/* keypad() of NetBSD's libcurses returns no value */
#if defined(__NetBSD__) && !defined(NCURSES_VERSION)
- keypad(winp->window,(val == Qtrue ? TRUE : FALSE));
+ keypad(winp->window,(RTEST(val) ? TRUE : FALSE));
return Qnil;
#else
- return (keypad(winp->window,(val == Qtrue) ? TRUE : FALSE)) == OK ?
+ /* may have to raise exception on ERR */
+ return (keypad(winp->window,RTEST(val) ? TRUE : FALSE)) == OK ?
Qtrue : Qfalse;
#endif
};
diff --git a/gc.c b/gc.c
index e73fad4089..4b72db951d 100644
--- a/gc.c
+++ b/gc.c
@@ -756,6 +756,8 @@ rb_gc_mark_children(ptr)
for (i=0; i < len; i++)
rb_gc_mark(*ptr++);
}
+ if (FL_TEST(obj, ELTS_SHARED))
+ rb_gc_mark(obj->as.array.aux.shared);
break;
case T_HASH:
@@ -764,8 +766,9 @@ rb_gc_mark_children(ptr)
break;
case T_STRING:
- if (obj->as.string.orig) {
- rb_gc_mark((VALUE)obj->as.string.orig);
+#define STR_ASSOC FL_USER2 /* copied from string.c */
+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) {
+ rb_gc_mark(obj->as.string.aux.shared);
}
break;
@@ -945,13 +948,12 @@ obj_free(obj)
}
break;
case T_STRING:
-#define STR_NO_ORIG FL_USER2 /* copied from string.c */
- if (!RANY(obj)->as.string.orig || FL_TEST(obj, STR_NO_ORIG)) {
+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) {
RUBY_CRITICAL(free(RANY(obj)->as.string.ptr));
}
break;
case T_ARRAY:
- if (RANY(obj)->as.array.ptr) {
+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) {
RUBY_CRITICAL(free(RANY(obj)->as.array.ptr));
}
break;
diff --git a/hash.c b/hash.c
index 9ac14e87d5..94c7e33a33 100644
--- a/hash.c
+++ b/hash.c
@@ -18,6 +18,7 @@
#include "rubysig.h"
#define HASH_DELETED FL_USER1
+#define HASH_PROC_DEFAULT FL_USER2
static void
rb_hash_modify(hash)
@@ -38,13 +39,13 @@ rb_hash_freeze(hash)
VALUE rb_cHash;
static VALUE envtbl;
-static ID hash;
+static ID id_hash, id_yield, id_default;
VALUE
rb_hash(obj)
VALUE obj;
{
- return rb_funcall(obj, hash, 0);
+ return rb_funcall(obj, id_hash, 0);
}
static VALUE
@@ -93,7 +94,7 @@ rb_any_hash(a)
default:
DEFER_INTS;
- hval = rb_funcall(a, hash, 0);
+ hval = rb_funcall(a, id_hash, 0);
if (FIXNUM_P(hval)) {
hval %= 536870917;
}
@@ -198,9 +199,18 @@ rb_hash_initialize(argc, argv, hash)
{
VALUE ifnone;
- rb_scan_args(argc, argv, "01", &ifnone);
rb_hash_modify(hash);
- RHASH(hash)->ifnone = ifnone;
+ if (rb_block_given_p()) {
+ if (argc > 1) {
+ rb_raise(rb_eArgError, "wrong number of arguments", argc);
+ }
+ RHASH(hash)->ifnone = rb_f_lambda();
+ FL_SET(hash, HASH_PROC_DEFAULT);
+ }
+ else {
+ rb_scan_args(argc, argv, "01", &ifnone);
+ RHASH(hash)->ifnone = ifnone;
+ }
return hash;
}
@@ -284,7 +294,7 @@ rb_hash_aref(hash, key)
VALUE val;
if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
- return RHASH(hash)->ifnone;
+ return rb_funcall(hash, id_default, 1, key);
}
return val;
}
@@ -316,9 +326,17 @@ rb_hash_fetch(argc, argv, hash)
}
static VALUE
-rb_hash_default(hash)
+rb_hash_default(argc, argv, hash)
+ int argc;
+ VALUE *argv;
VALUE hash;
{
+ VALUE key;
+
+ rb_scan_args(argc, argv, "01", &key);
+ if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
+ return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
+ }
return RHASH(hash)->ifnone;
}
@@ -328,6 +346,7 @@ rb_hash_set_default(hash, ifnone)
{
rb_hash_modify(hash);
RHASH(hash)->ifnone = ifnone;
+ FL_UNSET(hash, HASH_PROC_DEFAULT);
return hash;
}
@@ -392,7 +411,7 @@ rb_hash_delete(hash, key)
if (rb_block_given_p()) {
return rb_yield(key);
}
- return RHASH(hash)->ifnone;
+ return Qnil;
}
struct shift_var {
@@ -1433,7 +1452,9 @@ env_reject()
void
Init_Hash()
{
- hash = rb_intern("hash");
+ id_hash = rb_intern("hash");
+ id_yield = rb_intern("yield");
+ id_default = rb_intern("default");
rb_cHash = rb_define_class("Hash", rb_cObject);
@@ -1456,7 +1477,7 @@ Init_Hash()
rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
- rb_define_method(rb_cHash,"default", rb_hash_default, 0);
+ rb_define_method(rb_cHash,"default", rb_hash_default, -1);
rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
rb_define_method(rb_cHash,"index", rb_hash_index, 1);
rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
diff --git a/io.c b/io.c
index 3732e0632b..0984fdfe02 100644
--- a/io.c
+++ b/io.c
@@ -513,6 +513,10 @@ io_fread(ptr, len, f)
eof:
if (ferror(f)) {
if (errno == EINTR) continue;
+ if (errno == EAGAIN) return len - n;
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ if (errno == EWOULDBLOCK) return len - n;
+#endif
rb_sys_fail(0);
}
*ptr = '\0';
@@ -2187,6 +2191,25 @@ rb_f_putc(recv, ch)
return rb_io_putc(rb_defout, ch);
}
+static VALUE rb_io_puts _((int, VALUE*, VALUE));
+
+static VALUE
+io_puts_ary(ary, out)
+ VALUE ary, out;
+{
+ VALUE tmp;
+ int i;
+
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ tmp = RARRAY(ary)->ptr[i];
+ if (rb_inspecting_p(tmp)) {
+ tmp = rb_str_new2("[...]");
+ }
+ rb_io_puts(1, &tmp, out);
+ }
+ return Qnil;
+}
+
static VALUE
rb_io_puts(argc, argv, out)
int argc;
@@ -2206,11 +2229,11 @@ rb_io_puts(argc, argv, out)
line = rb_str_new2("nil");
}
else {
-#if 0
- if (TYPE(argv[i]) == T_ARRAY) {
- rb_warn("puts behavior changed for Array");
+ line = rb_check_convert_type(argv[i], T_ARRAY, "Array", "to_ary");
+ if (!NIL_P(line)) {
+ rb_protect_inspect(io_puts_ary, line, out);
+ continue;
}
-#endif
line = rb_obj_as_string(argv[i]);
}
rb_io_write(out, line);
diff --git a/object.c b/object.c
index 4020f54d03..7a4b1e208c 100644
--- a/object.c
+++ b/object.c
@@ -313,7 +313,6 @@ rb_obj_freeze(obj)
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
}
-
OBJ_FREEZE(obj);
}
return obj;
@@ -1292,7 +1291,7 @@ Init_Object()
rb_undef_method(rb_cClass, "append_features");
rb_cData = rb_define_class("Data", rb_cObject);
- rb_undef_method(CLASS_OF(rb_cData), "new");
+ rb_undef_method(CLASS_OF(rb_cData), "allocate");
ruby_top_self = rb_obj_alloc(rb_cObject);
rb_global_variable(&ruby_top_self);
diff --git a/parse.y b/parse.y
index e1c2dd46d1..96a7fd6edd 100644
--- a/parse.y
+++ b/parse.y
@@ -3938,6 +3938,10 @@ str_extend(list, term, paren)
case '-':
tokadd(c);
c = nextc();
+ if (!is_identchar(c)) {
+ pushback();
+ goto invalid_interporate;
+ }
tokadd(c);
goto fetch_id;
@@ -3956,9 +3960,14 @@ str_extend(list, term, paren)
goto refetch;
}
if (!is_identchar(c)) {
- yyerror("bad global variable in string");
- newtok();
- return list;
+ invalid_interporate:
+ {
+ VALUE s = rb_str_new2("#");
+ rb_str_cat(s, tok(), toklen());
+ list_append(list, NEW_STR(s));
+ newtok();
+ return list;
+ }
}
}
@@ -3997,6 +4006,9 @@ str_extend(list, term, paren)
c = nextc();
}
pushback(c);
+ if (toklen() == 1) {
+ goto invalid_interporate;
+ }
break;
case '{':
@@ -4264,7 +4276,9 @@ gettable(id)
return NEW_FALSE();
}
else if (id == k__FILE__) {
- return NEW_STR(rb_str_new2(ruby_sourcefile));
+ VALUE f = rb_str_new2(ruby_sourcefile);
+ OBJ_FREEZE(f);
+ return NEW_STR(f);
}
else if (id == k__LINE__) {
return NEW_LIT(INT2FIX(ruby_sourceline));
diff --git a/regex.c b/regex.c
index ad5d88cc4f..b88bfffa4b 100644
--- a/regex.c
+++ b/regex.c
@@ -477,7 +477,7 @@ re_set_syntax(syntax)
} while(0)
#define WC2MBC1ST(c) \
- ((c<0x100)?(c):((current_mbctype != MBCTYPE_UTF8)?(((c)>>8)&0xff):utf8_firstbyte(c)))
+ ((current_mbctype != MBCTYPE_UTF8) ? ((c<0x100) ? (c) : (((c)>>8)&0xff)) : utf8_firstbyte(c))
static unsigned int
utf8_firstbyte(c)
diff --git a/ruby.h b/ruby.h
index 65b4d3b2ef..d1f48959f5 100644
--- a/ruby.h
+++ b/ruby.h
@@ -247,6 +247,10 @@ VALUE rb_newobj _((void));
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\
} while (0)
+#define DUPSETUP(dup,obj) do {\
+ OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT));\
+ if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)dup,(VALUE)obj);\
+} while (0)
struct RBasic {
unsigned long flags;
@@ -270,16 +274,25 @@ struct RFloat {
double value;
};
+#define ELTS_SHARED FL_USER2
+
struct RString {
struct RBasic basic;
long len;
char *ptr;
- VALUE orig;
+ union {
+ int capa;
+ VALUE shared;
+ } aux;
};
struct RArray {
struct RBasic basic;
- long len, capa;
+ long len;
+ union {
+ int capa;
+ VALUE shared;
+ } aux;
VALUE *ptr;
};
diff --git a/sample/test.rb b/sample/test.rb
index 663a8695e1..a6ab98ca63 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -470,6 +470,18 @@ test_ok(($x * 0).join(":") == '')
test_ok($x.size == 7)
test_ok($x == [1, 2, 3, 4, 5, 6, 7])
+$x = [1,2,3]
+$x[1,0] = $x
+test_ok($x == [1,1,2,3,2,3])
+
+$x = [1,2,3]
+$x[-1,0] = $x
+test_ok($x == [1,2,1,2,3,3])
+
+$x = [1,2,3]
+$x.concat($x)
+test_ok($x == [1,2,3,1,2,3])
+
test_check "hash"
$x = {1=>2, 2=>4, 3=>6}
$y = {1, 2, 2, 4, 3, 6}
@@ -505,17 +517,40 @@ $z = [1,2]
$y[$z] = 256
test_ok($y[$z] == 256)
-$x = [1,2,3]
-$x[1,0] = $x
-test_ok($x == [1,1,2,3,2,3])
-
-$x = [1,2,3]
-$x[-1,0] = $x
-test_ok($x == [1,2,1,2,3,3])
-
-$x = [1,2,3]
-$x.concat($x)
-test_ok($x == [1,2,3,1,2,3])
+$x = Hash.new(0)
+$x[1] = 1
+test_ok($x[1] == 1)
+test_ok($x[2] == 0)
+
+$x = Hash.new([])
+test_ok($x[22] == [])
+test_ok($x[22].equal?($x[22]))
+
+$x = Hash.new{[]}
+test_ok($x[22] == [])
+test_ok(!$x[22].equal?($x[22]))
+
+$x = Hash.new{|h,k| $z = k; h[k] = k*2}
+$z = 0
+test_ok($x[22] == 44)
+test_ok($z == 22)
+$z = 0
+test_ok($x[22] == 44)
+test_ok($z == 0)
+$x.default = 5
+test_ok($x[23] == 5)
+
+$x = Hash.new
+def $x.default(k)
+ $z = k
+ self[k] = k*2
+end
+$z = 0
+test_ok($x[22] == 44)
+test_ok($z == 22)
+$z = 0
+test_ok($x[22] == 44)
+test_ok($z == 0)
test_check "iterator"
diff --git a/string.c b/string.c
index f1dd8b3b35..f3520813a0 100644
--- a/string.c
+++ b/string.c
@@ -27,7 +27,6 @@
VALUE rb_cString;
-#define STR_NO_ORIG FL_USER2
#define STR_ASSOC FL_USER3
VALUE rb_fs;
@@ -41,13 +40,13 @@ rb_str_s_alloc(klass)
str->ptr = 0;
str->len = 0;
- str->orig = 0;
+ str->aux.capa = 0;
return (VALUE)str;
}
-VALUE
-rb_str_new0(klass, ptr, len)
+static VALUE
+str_new(klass, ptr, len)
VALUE klass;
const char *ptr;
long len;
@@ -55,6 +54,7 @@ rb_str_new0(klass, ptr, len)
VALUE str = rb_obj_alloc(klass);
RSTRING(str)->len = len;
+ RSTRING(str)->aux.capa = len;
RSTRING(str)->ptr = ALLOC_N(char,len+1);
if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
@@ -68,7 +68,7 @@ rb_str_new(ptr, len)
const char *ptr;
long len;
{
- return rb_str_new0(rb_cString, ptr, len);
+ return str_new(rb_cString, ptr, len);
}
VALUE
@@ -99,51 +99,52 @@ rb_tainted_str_new2(ptr)
return str;
}
-VALUE
-rb_str_new3(str)
- VALUE str;
+static VALUE
+str_new3(klass, str)
+ VALUE klass, str;
{
- VALUE str2 = rb_obj_alloc(rb_obj_class(str));
+ VALUE str2 = rb_obj_alloc(klass);
RSTRING(str2)->len = RSTRING(str)->len;
RSTRING(str2)->ptr = RSTRING(str)->ptr;
- RSTRING(str2)->orig = str;
+ RSTRING(str2)->aux.shared = str;
+ FL_SET(str2, ELTS_SHARED);
OBJ_INFECT(str2, str);
return str2;
}
VALUE
+rb_str_new3(str)
+ VALUE str;
+{
+ return str_new3(rb_obj_class(str), str);
+}
+
+VALUE
rb_str_new4(orig)
VALUE orig;
{
- VALUE klass;
+ VALUE klass, str;
klass = rb_obj_class(orig);
- if (RSTRING(orig)->orig) {
- VALUE str;
-
- if (FL_TEST(orig, STR_NO_ORIG)) {
- str = rb_str_new0(klass, RSTRING(orig)->ptr, RSTRING(orig)->len);
- }
- else {
- str = rb_str_new3(RSTRING(orig)->orig);
- RBASIC(str)->klass = klass;
- }
- OBJ_FREEZE(str);
- return str;
+ if (FL_TEST(orig, ELTS_SHARED)) {
+ str = str_new3(klass, RSTRING(orig)->aux.shared);
+ }
+ else if (FL_TEST(orig, STR_ASSOC)) {
+ str = str_new(klass, RSTRING(orig)->ptr, RSTRING(orig)->len);
}
else {
- VALUE str = rb_obj_alloc(klass);
+ str = rb_obj_alloc(klass);
RSTRING(str)->len = RSTRING(orig)->len;
RSTRING(str)->ptr = RSTRING(orig)->ptr;
- RSTRING(orig)->orig = str;
- OBJ_INFECT(str, orig);
- OBJ_FREEZE(str);
-
- return str;
+ RSTRING(orig)->aux.shared = str;
+ FL_SET(orig, ELTS_SHARED);
}
+ OBJ_INFECT(str, orig);
+ OBJ_FREEZE(str);
+ return str;
}
VALUE
@@ -152,7 +153,7 @@ rb_str_new5(obj, ptr, len)
const char *ptr;
long len;
{
- return rb_str_new0(rb_obj_class(obj), ptr, len);
+ return str_new(rb_obj_class(obj), ptr, len);
}
#define STR_BUF_MIN_SIZE 128
@@ -163,12 +164,11 @@ rb_str_buf_new(capa)
{
VALUE str = rb_obj_alloc(rb_cString);
- FL_SET(str, STR_NO_ORIG);
if (capa < STR_BUF_MIN_SIZE)
capa = STR_BUF_MIN_SIZE;
RSTRING(str)->ptr = 0;
RSTRING(str)->len = 0;
- RSTRING(str)->orig = LONG2FIX(capa);
+ RSTRING(str)->aux.capa = capa;
RSTRING(str)->ptr = ALLOC_N(char, capa+1);
RSTRING(str)->ptr[0] = '\0';
@@ -210,16 +210,23 @@ rb_str_become(str, str2)
if (NIL_P(str2)) {
RSTRING(str)->ptr = 0;
RSTRING(str)->len = 0;
- RSTRING(str)->orig = 0;
+ RSTRING(str)->aux.capa = 0;
return;
}
- if ((!RSTRING(str)->orig||FL_TEST(str,STR_NO_ORIG))&&RSTRING(str)->ptr)
- free(RSTRING(str)->ptr);
+ if (FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
RSTRING(str)->ptr = RSTRING(str2)->ptr;
RSTRING(str)->len = RSTRING(str2)->len;
- RSTRING(str)->orig = RSTRING(str2)->orig;
+ if (FL_TEST(str2, ELTS_SHARED|STR_ASSOC)) {
+ FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
+ RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
+ }
+ else {
+ RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
+ }
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
+ RSTRING(str2)->aux.capa = 0;
+ FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
@@ -227,22 +234,23 @@ void
rb_str_associate(str, add)
VALUE str, add;
{
- if (FL_TEST(str, STR_NO_ORIG|STR_ASSOC) != (STR_NO_ORIG|STR_ASSOC)) {
- if (FL_TEST(str, STR_NO_ORIG)) {
+ if (FL_TEST(str, STR_ASSOC)) {
+ /* already associated */
+ rb_ary_concat(RSTRING(str)->aux.shared, add);
+ }
+ else {
+ if (FL_TEST(str, ELTS_SHARED)) {
+ rb_str_modify(str);
+ }
+ else if (RSTRING(str)->aux.shared) {
/* str_buf */
- if (FIX2LONG(RSTRING(str)->orig) != RSTRING(str)->len) {
+ if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len + 1);
}
}
- else if (RSTRING(str)->orig) {
- rb_str_modify(str);
- }
- RSTRING(str)->orig = add;
- FL_SET(str, STR_NO_ORIG|STR_ASSOC);
- }
- else {
- /* already associated */
- rb_ary_concat(RSTRING(str)->orig, add);
+ RSTRING(str)->aux.shared = add;
+ FL_UNSET(str, ELTS_SHARED);
+ FL_SET(str, STR_ASSOC);
}
}
@@ -250,10 +258,10 @@ VALUE
rb_str_associated(str)
VALUE str;
{
- if (FL_TEST(str, STR_NO_ORIG|STR_ASSOC) != (STR_NO_ORIG|STR_ASSOC)) {
- return Qfalse;
+ if (FL_TEST(str, STR_ASSOC)) {
+ return RSTRING(str)->aux.shared;
}
- return RSTRING(str)->orig;
+ return Qfalse;
}
static ID id_to_s;
@@ -274,45 +282,53 @@ rb_obj_as_string(obj)
return str;
}
-VALUE
-rb_str_dup(str)
+static VALUE
+str_copy(str, clone)
VALUE str;
+ int clone;
{
VALUE str2;
VALUE klass;
+ int flags;
StringValue(str);
- klass = rb_obj_class(str);
- if (OBJ_FROZEN(str)) str2 = rb_str_new3(str);
- else if (FL_TEST(str, STR_NO_ORIG)) {
- str2 = rb_str_new0(klass, RSTRING(str)->ptr, RSTRING(str)->len);
+ if (FL_TEST(str, ELTS_SHARED)) {
+ str2 = rb_str_new3(RSTRING(str)->aux.shared);
}
- else if (RSTRING(str)->orig) {
- str2 = rb_str_new3(RSTRING(str)->orig);
- RBASIC(str2)->klass = klass;
- FL_UNSET(str2, FL_TAINT);
- OBJ_INFECT(str2, str);
+ else if (FL_TEST(str, STR_ASSOC)) {
+ str2 = str_new(RSTRING(str)->ptr, RSTRING(str)->len);
+ RSTRING(str2)->aux.shared = RSTRING(str)->aux.shared;
+ }
+ else if (OBJ_FROZEN(str)) {
+ str2 = rb_str_new3(str);
}
else {
str2 = rb_str_new3(rb_str_new4(str));
}
- if (FL_TEST(str, FL_EXIVAR))
- rb_copy_generic_ivar(str2, str);
- OBJ_INFECT(str2, str);
+ flags = FL_TEST(str2, ELTS_SHARED|STR_ASSOC);
+ if (clone) {
+ CLONESETUP(str2, str);
+ }
+ else {
+ DUPSETUP(str2, str);
+ }
+ if (flags) FL_SET(str2, flags);
return str2;
}
+VALUE
+rb_str_dup(str)
+ VALUE str;
+{
+ return str_copy(str, Qfalse);
+}
+
static VALUE
rb_str_clone(str)
VALUE str;
{
- VALUE clone = rb_str_dup(str);
- if (FL_TEST(str, STR_NO_ORIG))
- RSTRING(clone)->orig = RSTRING(str)->orig;
- CLONESETUP(clone, str);
-
- return clone;
+ return str_copy(str, Qtrue);
}
static VALUE rb_str_replace _((VALUE, VALUE));
@@ -446,9 +462,7 @@ str_independent(str)
if (OBJ_FROZEN(str)) rb_error_frozen("string");
if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
- if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return 1;
- if (RBASIC(str)->flags == 0) abort();
- if (TYPE(RSTRING(str)->orig) != T_STRING) rb_bug("non string str->orig");
+ if (!FL_TEST(str, ELTS_SHARED)) return 1;
return 0;
}
@@ -465,7 +479,8 @@ rb_str_modify(str)
}
ptr[RSTRING(str)->len] = 0;
RSTRING(str)->ptr = ptr;
- RSTRING(str)->orig = 0;
+ RSTRING(str)->aux.capa = RSTRING(str)->len;
+ FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
}
VALUE
@@ -479,9 +494,9 @@ VALUE
rb_str_dup_frozen(str)
VALUE str;
{
- if (RSTRING(str)->orig && !FL_TEST(str, STR_NO_ORIG)) {
- OBJ_FREEZE(RSTRING(str)->orig);
- return RSTRING(str)->orig;
+ if (FL_TEST(str, ELTS_SHARED)) {
+ OBJ_FREEZE(RSTRING(str)->aux.shared);
+ return RSTRING(str)->aux.shared;
}
if (OBJ_FROZEN(str)) return str;
str = rb_str_dup(str);
@@ -516,21 +531,17 @@ rb_str_buf_cat(str, ptr, len)
{
long i, capa, total;
- if (RSTRING(str)->orig == 0) {
- capa = RSTRING(str)->len;
- FL_SET(str, STR_NO_ORIG);
- }
- else {
- capa = FIX2LONG(RSTRING(str)->orig);
+ if (FL_TEST(str, ELTS_SHARED)) {
+ rb_str_modify(str);
}
-
+ capa = RSTRING(str)->aux.capa;
total = RSTRING(str)->len+len;
if (capa <= total) {
while (total > capa) {
capa = (capa + 1) * 2;
}
REALLOC_N(RSTRING(str)->ptr, char, capa+1);
- RSTRING(str)->orig = LONG2FIX(capa);
+ RSTRING(str)->aux.capa = capa;
}
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
RSTRING(str)->len = total;
@@ -557,8 +568,7 @@ rb_str_cat(str, ptr, len)
rb_str_modify(str);
if (len > 0) {
- if (RSTRING(str)->orig == 0 ||
- (FL_TEST(str, STR_NO_ORIG) && !FL_TEST(str, STR_ASSOC))) {
+ if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
return rb_str_buf_cat(str, ptr, len);
}
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len+1);
@@ -589,13 +599,10 @@ rb_str_buf_append(str, str2)
{
long i, capa, len;
- if (RSTRING(str)->orig == 0) {
- capa = RSTRING(str)->len;
- FL_SET(str, STR_NO_ORIG);
- }
- else {
- capa = FIX2LONG(RSTRING(str)->orig);
+ if (FL_TEST(str, ELTS_SHARED)) {
+ rb_str_modify(str);
}
+ capa = RSTRING(str)->aux.capa;
len = RSTRING(str)->len+RSTRING(str2)->len;
if (capa <= len) {
@@ -603,7 +610,7 @@ rb_str_buf_append(str, str2)
capa = (capa + 1) * 2;
}
REALLOC_N(RSTRING(str)->ptr, char, capa+1);
- RSTRING(str)->orig = LONG2FIX(capa);
+ RSTRING(str)->aux.capa = capa;
}
memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
RSTRING(str2)->ptr, RSTRING(str2)->len);
@@ -623,11 +630,9 @@ rb_str_append(str, str2)
rb_str_modify(str);
if (RSTRING(str2)->len > 0) {
len = RSTRING(str)->len+RSTRING(str2)->len;
- if (RSTRING(str)->orig == 0 ||
- (FL_TEST(str, STR_NO_ORIG) && !FL_TEST(str, STR_ASSOC))) {
+ if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
rb_str_buf_append(str, str2);
OBJ_INFECT(str, str2);
-
return str;
}
REALLOC_N(RSTRING(str)->ptr, char, len+1);
@@ -810,6 +815,13 @@ rb_str_match2(str)
return rb_reg_match2(rb_reg_regcomp(str));
}
+static VALUE
+rb_str_match_m(str, re)
+ VALUE str, re;
+{
+ return rb_funcall(re, rb_intern("match"), 1, str);
+}
+
static long
rb_str_index(str, sub, offset)
VALUE str, sub;
@@ -1529,20 +1541,18 @@ str_gsub(argc, argv, str, bang)
if (str_independent(str)) {
free(RSTRING(str)->ptr);
}
- else {
- RSTRING(str)->orig = 0;
- }
+ FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
}
else {
VALUE dup = rb_obj_alloc(rb_obj_class(str));
OBJ_INFECT(dup, str);
str = dup;
- RSTRING(dup)->orig = 0;
}
RSTRING(str)->ptr = buf;
RSTRING(str)->len = len = bp - buf;
RSTRING(str)->ptr[len] = '\0';
+ RSTRING(str)->aux.capa = len;
if (tainted) OBJ_TAINT(str);
return str;
@@ -1573,13 +1583,19 @@ rb_str_replace(str, str2)
if (str == str2) return str;
StringValue(str2);
- if (RSTRING(str2)->orig && !FL_TEST(str2, STR_NO_ORIG)) {
+ if (FL_TEST(str2, ELTS_SHARED)) {
if (str_independent(str)) {
free(RSTRING(str)->ptr);
}
RSTRING(str)->len = RSTRING(str2)->len;
RSTRING(str)->ptr = RSTRING(str2)->ptr;
- RSTRING(str)->orig = RSTRING(str2)->orig;
+ if (FL_TEST(str2, ELTS_SHARED|STR_ASSOC)) {
+ FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
+ RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
+ }
+ else {
+ RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
+ }
}
else {
rb_str_modify(str);
@@ -3113,6 +3129,7 @@ Init_String()
rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
rb_define_method(rb_cString, "=~", rb_str_match, 1);
rb_define_method(rb_cString, "~", rb_str_match2, 0);
+ rb_define_method(rb_cString, "match", rb_str_match_m, 1);
rb_define_method(rb_cString, "succ", rb_str_succ, 0);
rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
rb_define_method(rb_cString, "next", rb_str_succ, 0);
diff --git a/time.c b/time.c
index 35ef208802..655a49f1fe 100644
--- a/time.c
+++ b/time.c
@@ -72,9 +72,9 @@ time_new_internal(klass, sec, usec)
sec += usec / 1000000;
usec %= 1000000;
}
- if (usec < 0) { /* usec underflow */
- sec -= (-usec) / 1000000;
- usec %= 1000000;
+ while (usec < 0) { /* usec underflow */
+ sec--;
+ usec += 1000000;
}
#ifndef NEGATIVE_TIME_T
if (sec < 0 || (sec == 0 && usec < 0))
@@ -643,7 +643,13 @@ time_cmp(time1, time2)
return INT2FIX(-1);
}
i = NUM2LONG(time2);
- if (tobj1->tv.tv_sec == i) return INT2FIX(0);
+ if (tobj1->tv.tv_sec == i) {
+ if (tobj1->tv.tv_usec == 0)
+ return INT2FIX(0);
+ if (tobj1->tv.tv_usec > 0)
+ return INT2FIX(1);
+ return INT2FIX(-1);
+ }
if (tobj1->tv.tv_sec > i) return INT2FIX(1);
return INT2FIX(-1);
}
@@ -760,6 +766,35 @@ time_gmtime(time)
}
static VALUE
+time_dup(time)
+ VALUE time;
+{
+ VALUE clone;
+ struct time_object *tobj, *tclone;
+
+ GetTimeval(time, tobj);
+ clone = Data_Make_Struct(0, struct time_object, 0, free, tclone);
+ DUPSETUP(clone, time);
+ MEMCPY(tclone, tobj, struct time_object, 1);
+
+ return clone;
+}
+
+static VALUE
+time_getlocaltime(time)
+ VALUE time;
+{
+ return time_localtime(time_dup(time));
+}
+
+static VALUE
+time_getgmtime(time)
+ VALUE time;
+{
+ return time_gmtime(time_dup(time));
+}
+
+static VALUE
time_get_tm(time, gmt)
VALUE time;
int gmt;
@@ -1071,7 +1106,7 @@ rb_strftime(buf, format, time)
* if the buffer is 1024 times bigger than the length of the
* format string, it's not failing for lack of room.
*/
- if (len > 0 || len >= 1024 * flen) return len;
+ if (len > 0 || size >= 1024 * flen) return len;
free(*buf);
}
/* not reached */
@@ -1109,7 +1144,10 @@ time_strftime(time, format)
p += strlen(p) + 1;
if (p <= pe)
rb_str_cat(str, "\0", 1);
- if (len > SMALLBUF) free(buf);
+ if (buf != buffer) {
+ free(buf);
+ buf = buffer;
+ }
}
return str;
}
@@ -1231,10 +1269,15 @@ Init_Time()
rb_define_method(rb_cTime, "eql?", time_eql, 1);
rb_define_method(rb_cTime, "hash", time_hash, 0);
rb_define_method(rb_cTime, "clone", time_clone, 0);
+ rb_define_method(rb_cTime, "dup", time_dup, 0);
rb_define_method(rb_cTime, "localtime", time_localtime, 0);
rb_define_method(rb_cTime, "gmtime", time_gmtime, 0);
rb_define_method(rb_cTime, "utc", time_gmtime, 0);
+ rb_define_method(rb_cTime, "getlocal", time_getlocaltime, 0);
+ rb_define_method(rb_cTime, "getgm", time_getgmtime, 0);
+ rb_define_method(rb_cTime, "getutc", time_getgmtime, 0);
+
rb_define_method(rb_cTime, "ctime", time_asctime, 0);
rb_define_method(rb_cTime, "asctime", time_asctime, 0);
rb_define_method(rb_cTime, "to_s", time_to_s, 0);
diff --git a/util.c b/util.c
index bec54f4237..26a35ed398 100644
--- a/util.c
+++ b/util.c
@@ -384,31 +384,25 @@ __crt0_glob_function(char *path)
/* mm.c */
-static int mmkind, mmsize, high, low;
-
#define A ((int*)a)
#define B ((int*)b)
#define C ((int*)c)
#define D ((int*)d)
-static void mmprepare(base, size) void *base; int size;
-{
-#ifdef DEBUG
- if (sizeof(int) != 4) die("sizeof(int) != 4");
- if (size <= 0) die("mmsize <= 0");
-#endif
+#define mmprepare(base, size) do {\
+ if (((long)base & (0x3)) == 0)\
+ if (size >= 16) mmkind = 1;\
+ else mmkind = 0;\
+ else mmkind = -1;\
+ high = (size & (~0xf));\
+ low = (size & 0x0c);\
+} while (0)\
- if (((long)base & (4-1)) == 0 && ((long)base & (4-1)) == 0)
- if (size >= 16) mmkind = 1;
- else mmkind = 0;
- else mmkind = -1;
-
- mmsize = size;
- high = (size & (-16));
- low = (size & 0x0c);
-}
+#define mmarg mmkind, size, high, low
-static void mmswap(a, b) register char *a, *b;
+static void mmswap_(a, b, mmarg)
+ register char *a, *b;
+ int mmarg;
{
register int s;
if (a == b) return;
@@ -427,12 +421,15 @@ static void mmswap(a, b) register char *a, *b;
if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
}
else {
- register char *t = a + mmsize;
+ register char *t = a + size;
do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
}
}
+#define mmswap(a,b) mmswap_((a),(b),mmarg)
-static void mmrot3(a, b, c) register char *a, *b, *c;
+static void mmrot3_(a, b, c, mmarg)
+ register char *a, *b, *c;
+ int mmarg;
{
register int s;
if (mmkind >= 0) {
@@ -450,10 +447,11 @@ static void mmrot3(a, b, c) register char *a, *b, *c;
if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
}
else {
- register char *t = a + mmsize;
+ register char *t = a + size;
do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
}
}
+#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
/* qs6.c */
/*****************************************************/
@@ -472,14 +470,19 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
((*cmp)(b,c)<0 ? b : ((*cmp)(a,c)<0 ? c : a)) : \
((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c)))
-void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)();
+void ruby_qsort (base, nel, size, cmp)
+ void* base;
+ const int nel;
+ const 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 */
+ 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 */
+ int mmkind, high, low;
if (nel <= 1) return; /* need not to sort */
mmprepare(base, size);
@@ -491,7 +494,9 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
for (;;) {
start:
- if (L + size == R) {if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;}/* 2 elements */
+ if (L + size == R) { /* 2 elements */
+ if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;
+ }
l = L; r = R;
t = (r - l + size) / size; /* number of elements */
@@ -559,7 +564,7 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
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*/
+ /* determining splitting type in case 5-5-5 */ /*5-5-5*/
for (;;) {
if ((l += size) == r) goto nxt; /*5-5-5*/
if (l == m) continue;
diff --git a/version.h b/version.h
index a53780acb2..fb712da798 100644
--- a/version.h
+++ b/version.h
@@ -1,4 +1,4 @@
#define RUBY_VERSION "1.7.2"
-#define RUBY_RELEASE_DATE "2001-12-09"
+#define RUBY_RELEASE_DATE "2001-12-10"
#define RUBY_VERSION_CODE 172
-#define RUBY_RELEASE_CODE 20011209
+#define RUBY_RELEASE_CODE 20011210