diff --git a/ChangeLog b/ChangeLog index 597ff6c33f53d7..c7c504f65d6b7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,41 @@ +Thu Jun 22 17:27:46 2000 Yukihiro Matsumoto + + * string.c (rb_str_substr): str[n,m] now returns nil when n equals + to str.size. + Thu Jun 22 13:49:02 2000 Uechi Yasumasa - * lib/net/ftp.rb: support resume. + * lib/net/ftp.rb: support resuming. Thu Jun 22 13:37:19 2000 WATANABE Hirofumi * eval.c (rb_thread_sleep_forever): merge pause() macro. +Wed Jun 21 08:49:04 2000 Yukihiro Matsumoto + + * eval.c (rb_eval): should not raise exception just by defining + singleton class. + +Wed Jun 21 01:18:03 2000 Yukihiro Matsumoto + + * ruby.h: two macros RUBY_DATA_FUNC and RUBY_METHOD_FUNC are added + to make writing C++ extensions easier. + + * array.c (rb_ary_dup): internal classes should not be shared by dup. + + * hash.c (rb_hash_dup): ditto. + + * object.c (rb_obj_dup): ditto. + + * string.c (rb_str_dup): ditto. + + * error.c (Init_Exception): renamed NotImplementError to + NotImplementedError. + +Tue Jun 20 16:22:38 2000 Yukihiro Matsumoto + + * time.c (make_time_t): bug in DST boundary. + Tue Jun 20 10:54:19 2000 WATANABE Hirofumi * configure.in: add eval sitedir. @@ -16,6 +46,13 @@ Tue Jun 20 06:14:43 2000 Wakou Aoyama * lib/net/telnet.rb: ditto. +Tue Jun 20 00:37:45 2000 Yukihiro Matsumoto + + * re.c (rb_reg_kcode_m): Regexp#kcode returns nil for code unfixed + regexp object. + + * bignum.c (bigdivmod): bignum zero check was wrong. + Mon Jun 19 10:48:28 2000 Yukihiro Matsumoto * variable.c (rb_cvar_set): forgot to add security check for class diff --git a/array.c b/array.c index d8dc37195ca672..f2089996e5fb20 100644 --- a/array.c +++ b/array.c @@ -680,9 +680,13 @@ static VALUE rb_ary_dup(ary) VALUE ary; { + VALUE klass = CLASS_OF(ary); VALUE dup; - dup = rb_ary_s_create(RARRAY(ary)->len, RARRAY(ary)->ptr, CLASS_OF(ary)); + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; + } + dup = rb_ary_s_create(RARRAY(ary)->len, RARRAY(ary)->ptr, klass); if (OBJ_TAINTED(ary)) OBJ_TAINT(dup); return dup; } diff --git a/bignum.c b/bignum.c index dabb96a82e5d4b..ec36a0946c83c5 100644 --- a/bignum.c +++ b/bignum.c @@ -451,8 +451,8 @@ rb_big_to_i(x) return bignorm(x); } -VALUE -rb_dbl2big(d) +static VALUE +dbl2big(d) double d; { unsigned long i = 0; @@ -481,7 +481,14 @@ rb_dbl2big(d) digits[i] = (USHORT)c; } - return bignorm(z); + return z; +} + +VALUE +rb_dbl2big(d) + double d; +{ + return bignorm(dbl2big(d)); } double @@ -521,7 +528,7 @@ rb_big_cmp(x, y) break; case T_FLOAT: - y = rb_dbl2big(RFLOAT(y)->value); + y = dbl2big(RFLOAT(y)->value); break; default: @@ -553,7 +560,7 @@ rb_big_eq(x, y) case T_BIGNUM: break; case T_FLOAT: - y = rb_dbl2big(RFLOAT(y)->value); + y = dbl2big(RFLOAT(y)->value); break; default: return Qfalse; @@ -894,7 +901,7 @@ bigdivmod(x, y, div, mod, modulo) if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) { long len = ny; zds = BDIGITS(*mod); - while (len-- && !zds[len]); + while (len && !zds[len]) len--; if (len > 0) { *mod = bigadd(*mod, y, 1); return; @@ -946,7 +953,7 @@ rb_big_modulo(x, y, modulo) break; case T_FLOAT: - y = rb_dbl2big(RFLOAT(y)->value); + y = dbl2big(RFLOAT(y)->value); break; default: @@ -983,7 +990,7 @@ rb_big_divmod(x, y) break; case T_FLOAT: - y = rb_dbl2big(RFLOAT(y)->value); + y = dbl2big(RFLOAT(y)->value); break; case T_BIGNUM: @@ -994,7 +1001,7 @@ rb_big_divmod(x, y) } bigdivmod(x, y, &div, &mod, 1); - return rb_assoc_new(div, mod);; + return rb_assoc_new(div, mod); } VALUE diff --git a/class.c b/class.c index f92ceda8e4b984..d26269d2c801e4 100644 --- a/class.c +++ b/class.c @@ -540,6 +540,7 @@ rb_singleton_class(obj) else { FL_UNSET(klass, FL_TAINT); } + if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); return klass; } diff --git a/configure.in b/configure.in index 2b64920778cafa..667b43fd97d552 100644 --- a/configure.in +++ b/configure.in @@ -866,7 +866,8 @@ test "$program_suffix" != NONE && RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}" RUBY_LIB_PREFIX="${prefix}/lib/ruby" RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}" -sitedir='${prefix}/lib/ruby/site_ruby' +#sitedir='${prefix}/lib/ruby/site_ruby' +sitedir="${prefix}/lib/ruby/site_ruby" AC_ARG_WITH(sitedir, [--with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]], [sitedir=$withval]) diff --git a/error.c b/error.c index e174ff6c98ac57..c65ad06d67230c 100644 --- a/error.c +++ b/error.c @@ -549,7 +549,9 @@ Init_Exception() rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError); rb_eNameError = rb_define_class("NameError", rb_eScriptError); rb_eLoadError = rb_define_class("LoadError", rb_eScriptError); - rb_eNotImpError = rb_define_class("NotImplementError", rb_eScriptError); + rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError); + /* backward compatibility -- will be removed in the future */ + rb_define_global_const("NotImplementError", rb_eNotImpError); rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError); rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError); diff --git a/eval.c b/eval.c index 88f51ea53c7f8d..c92384fd7cf110 100644 --- a/eval.c +++ b/eval.c @@ -1420,6 +1420,28 @@ rb_mod_s_constants() return ary; } +static void +frozen_class_p(klass) + VALUE klass; +{ + char *desc = "something(?!)"; + + if (OBJ_FROZEN(klass)) { + if (FL_TEST(klass, FL_SINGLETON)) + desc = "object"; + else { + switch (TYPE(klass)) { + case T_MODULE: + case T_ICLASS: + desc = "module"; break; + case T_CLASS: + desc = "class"; break; + } + } + rb_error_frozen(desc); + } +} + void rb_undef(klass, id) VALUE klass; @@ -1434,7 +1456,7 @@ rb_undef(klass, id) if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef"); } - if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); + frozen_class_p(klass); body = search_method(ruby_class, id, &origin); if (!body || !body->nd_body) { char *s0 = " class"; @@ -1476,6 +1498,7 @@ rb_alias(klass, name, def) VALUE origin; NODE *orig, *body; + frozen_class_p(klass); if (name == def) return; if (klass == rb_cObject) { rb_secure(4); @@ -2757,6 +2780,7 @@ rb_eval(self, n) if (ruby_class == rb_cObject && node->nd_mid == init) { rb_warn("re-defining Object#initialize may cause infinite loop"); } + frozen_class_p(ruby_class); body = search_method(ruby_class, node->nd_mid, &origin); if (body){ if (RTEST(ruby_verbose) && ruby_class == origin) { @@ -2975,7 +2999,6 @@ rb_eval(self, n) } if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) rb_raise(rb_eSecurityError, "Insecure: can't extend object"); - if (OBJ_FROZEN(klass)) rb_error_frozen("object"); if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) { rb_clear_cache(); } diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index c97f86a6877ca4..272a508e0ff02f 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -218,28 +218,30 @@ SRC return true end -def have_func(func) +def have_func(func, header=nil) libs = $libs - - if /mswin32|mingw/ =~ RUBY_PLATFORM - r = try_link(<<"SRC", libs) + src = + if /mswin32|mingw/ =~ RUBY_PLATFORM + r = <<"SRC" #include #include +SRC + else + "" + end + unless header.nil? + src << <<"SRC" +#include <#{header}> +SRC + end + r = try_link(src + <<"SRC", libs) int main() { return 0; } int t() { #{func}(); return 0; } SRC - unless r - r = try_link(<<"SRC", libs) -#include -#include + unless r + r = try_link(src + <<"SRC", libs) int main() { return 0; } int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; } -SRC - end - else - r = try_link(<<"SRC", libs) -int main() { return 0; } -int t() { #{func}(); return 0; } SRC end unless r diff --git a/ext/md5/md5.txt b/ext/md5/md5.txt index 0eca7c90253f66..e2b072401b05cf 100644 --- a/ext/md5/md5.txt +++ b/ext/md5/md5.txt @@ -25,6 +25,17 @@ Methods: returns have value of the added strings as a 16 bytes string. + hexdigest + + returns have value of the added strings as an 32 bytes ASCII + string. This method is equal to: + + def hexdigest + ret = '' + digest.each_byte {|i| ret << sprintf('%02x', i) } + ret + end + update(str) Update the MD5 object with the string. Repeated calls are diff --git a/ext/md5/md5.txt.jp b/ext/md5/md5.txt.jp index a1451f1175bb95..04cf32908d3055 100644 --- a/ext/md5/md5.txt.jp +++ b/ext/md5/md5.txt.jp @@ -26,6 +26,18 @@ Methods: 今までに追加した文字列に対するハッシュ値を16バイト長の文字列で 返す. + hexdigest + + 今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って + 16進数の列を示す'fe5c2235f48d2bcc911afabea23cd5aa'のような32文字 + の文字列にエンコードして返す。Rubyで書くと以下と同じ。 + + def hexdigest + ret = '' + digest.each_byte {|i| ret << sprintf('%02x', i) } + ret + end + update(str) MD5オブジェクトに文字列を追加する。複数回updateを呼ぶことは文 diff --git a/hash.c b/hash.c index e66ab126e9db2e..a8251dac7f9c0d 100644 --- a/hash.c +++ b/hash.c @@ -268,8 +268,13 @@ static VALUE rb_hash_dup(hash) VALUE hash; { + VALUE klass = CLASS_OF(hash); + NEWOBJ(dup, struct RHash); - OBJSETUP(dup, CLASS_OF(hash), T_HASH); + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; + } + OBJSETUP(dup, klass, T_HASH); dup->iter_lev = 0; dup->ifnone = RHASH(hash)->ifnone; diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 1ee1d680bcec30..d14f9bd55af6e5 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -210,31 +210,33 @@ def find_library(lib, func, *paths) return true end -def have_func(func) +def have_func(func, header=nil) printf "checking for %s()... ", func STDOUT.flush libs = $libs - - if /mswin32|mingw/ =~ RUBY_PLATFORM - r = try_link(<<"SRC", libs) + src = + if /mswin32|mingw/ =~ RUBY_PLATFORM + r = <<"SRC" #include #include +SRC + else + "" + end + unless header.nil? + src << <<"SRC" +#include <#{header}> +SRC + end + r = try_link(src + <<"SRC", libs) int main() { return 0; } int t() { #{func}(); return 0; } SRC - unless r - r = try_link(<<"SRC", libs) -#include -#include + unless r + r = try_link(src + <<"SRC", libs) int main() { return 0; } int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; } -SRC - end - else - r = try_link(<<"SRC", libs) -int main() { return 0; } -int t() { #{func}(); return 0; } SRC end unless r diff --git a/marshal.c b/marshal.c index 4b385dc117ec20..19a06a99f42c9e 100644 --- a/marshal.c +++ b/marshal.c @@ -397,7 +397,9 @@ w_object(obj, arg, limit) char *path; if (FL_TEST(klass, FL_SINGLETON)) { - rb_raise(rb_eTypeError, "singleton can't be dumped"); + if (RCLASS(klass)->m_tbl->num_entries > 0) { + rb_raise(rb_eTypeError, "singleton can't be dumped"); + } } path = rb_class2name(klass); w_unique(path, arg); diff --git a/object.c b/object.c index 410c964d0eaafc..b9333f75d8e15a 100644 --- a/object.c +++ b/object.c @@ -113,10 +113,14 @@ static VALUE rb_obj_dup(obj) VALUE obj; { - VALUE dup; - if (TYPE(obj) == T_OBJECT) { - dup = rb_obj_alloc(RBASIC(obj)->klass); + VALUE klass = CLASS_OF(obj); + VALUE dup; + + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; + } + dup = rb_obj_alloc(klass); if (ROBJECT(obj)->iv_tbl) { ROBJECT(dup)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); } diff --git a/re.c b/re.c index a28ac4a235521b..a778efca6c4ddb 100644 --- a/re.c +++ b/re.c @@ -373,7 +373,7 @@ static VALUE rb_reg_kcode_m(re) VALUE re; { - char *kcode = "$KCODE"; + char *kcode; if (FL_TEST(re, KCODE_FIXED)) { switch (RBASIC(re)->flags & KCODE_MASK) { @@ -386,11 +386,12 @@ rb_reg_kcode_m(re) case KCODE_UTF8: kcode = "utf8"; break; default: + rb_bug("unknow kcode - should not happen"); break; } + return rb_str_new2(kcode); } - - return rb_str_new2(kcode); + return Qnil; } static Regexp* diff --git a/ruby.h b/ruby.h index e208c7a113281d..40d128086ebcaa 100644 --- a/ruby.h +++ b/ruby.h @@ -290,6 +290,7 @@ struct RData { #define DATA_PTR(dta) (RDATA(dta)->data) +#define RUBY_DATA_FUNC(func) ((void (*)_((void*)))func) VALUE rb_data_object_alloc _((VALUE,void*,void (*) _((void*)),void (*) _((void*)))); #define Data_Make_Struct(klass,type,mark,free,sval) (\ sval = ALLOC(type),\ @@ -406,6 +407,7 @@ 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)); diff --git a/sample/tsvr.rb b/sample/tsvr.rb index d6a5620d1148bd..ebfad4beeb693d 100644 --- a/sample/tsvr.rb +++ b/sample/tsvr.rb @@ -2,7 +2,6 @@ # usage: ruby tsvr.rb require "socket" -require "thread" gs = TCPserver.open(0) addr = gs.addr @@ -10,10 +9,8 @@ printf("server is on %d\n", addr.join(":")) while TRUE - ns = gs.accept - print(ns, " is accepted\n") - Thread.start do - s = ns # save to thread-local variable + Thread.start(gs.accept) do |s| + print(s, " is accepted\n") while s.gets s.write($_) end diff --git a/string.c b/string.c index f547323a58b2e9..f6ae91bdf1cc24 100644 --- a/string.c +++ b/string.c @@ -181,31 +181,34 @@ rb_str_dup(str) VALUE str; { VALUE str2; + VALUE klass; if (TYPE(str) != T_STRING) str = rb_str_to_str(str); - if (OBJ_FROZEN(str)) return rb_str_new3(str); - if (FL_TEST(str, STR_NO_ORIG)) { + klass = CLASS_OF(str); + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; + } + + if (OBJ_FROZEN(str)) str2 = rb_str_new3(str); + else if (FL_TEST(str, STR_NO_ORIG)) { str2 = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len); - OBJ_INFECT(str2, str); - return str2; } - if (RSTRING(str)->orig) { + else if (RSTRING(str)->orig) { str2 = rb_str_new3(RSTRING(str)->orig); - OBJ_INFECT(str2, str); - return str2; } - - str2 = rb_str_new4(str); - { + else { NEWOBJ(dup, struct RString); - OBJSETUP(dup, rb_cString, T_STRING); + OBJSETUP(dup, klass, T_STRING); + + str2 = rb_str_new4(str); dup->len = RSTRING(str2)->len; dup->ptr = RSTRING(str2)->ptr; dup->orig = str2; - OBJ_INFECT(dup, str); - - return (VALUE)dup; + str2 = (VALUE)dup; } + OBJ_INFECT(str2, str); + RBASIC(str2)->klass = klass; + return str2; } @@ -326,7 +329,7 @@ rb_str_substr(str, beg, len) VALUE str2; if (len < 0) return Qnil; - if (beg > RSTRING(str)->len) return Qnil; + if (beg >= RSTRING(str)->len) return Qnil; if (beg < 0) { beg += RSTRING(str)->len; if (beg < 0) return Qnil; diff --git a/time.c b/time.c index 9028b7337d2ace..a165bafe7f8e14 100644 --- a/time.c +++ b/time.c @@ -316,6 +316,11 @@ make_time_t(tptr, utc_or_local) tm = localtime(&guess); if (!tm) goto error; guess -= tm->tm_gmtoff; + tm = localtime(&guess); + if (!tm) goto error; + if (tm->tm_hour != tptr->tm_hour) { + guess += (tptr->tm_hour - tm->tm_hour)*3600; + } #else struct tm gt, lt; long tzsec; @@ -338,18 +343,17 @@ make_time_t(tptr, utc_or_local) else { tzsec += (gt.tm_yday - lt.tm_yday)*24*3600; } - if (lt.tm_isdst) guess += 3600; guess += tzsec; if (guess < 0) { goto out_of_range; } -#endif tm = localtime(&guess); if (!tm) goto error; - if (tm->tm_hour != tptr->tm_hour) { + if (lt.tm_isdst != tm->tm_isdst) { guess -= 3600; } +#endif if (guess < 0) { goto out_of_range; }