diff --git a/ChangeLog b/ChangeLog index 46aaa622a8..c41b0e22a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,51 @@ +Tue Jan 9 16:22:14 2001 Yukihiro Matsumoto + + * enum.c (enum_inject): new method. + +Tue Jan 9 02:16:42 2001 Yukihiro Matsumoto + + * gc.c (rb_gc_call_finalizer_at_exit): clear klass member of + terminating object. + + * eval.c (rb_call): raise exception for terminated object. + +Mon Jan 8 21:24:37 2001 Yukihiro Matsumoto + + * bignum.c (bigdivrem): t2 might be too big for signed long; do + not use rb_int2big(), but rb_uint2big(). + +Mon Jan 8 03:09:58 2001 Yukihiro Matsumoto + + * error.c (rb_load_fail): new func to report LoadError. + + * ruby.c (load_file): use rb_load_fail. + Sat Jan 6 00:17:18 2001 WATANABE Hirofumi * pack.c (pack_pack): avoid infinite loop(pack 'm2'). +Fri Jan 5 01:02:17 2001 Yukihiro Matsumoto + + * eval.c (ruby_finalize): should enclosed by PUSH_TAG/POP_TAG. + + * gc.c (rb_gc_mark): link 2 of NODE_IFUNC should not be explicitly + marked. it may contain non object pointer. + +Tue Jan 2 00:20:06 2001 Yukihiro Matsumoto + + * re.c (reg_s_last_match): Regexp::last_match(nth) returns nth + substring of the match (alternative for $& and $). + +Sun Dec 31 01:39:16 2000 Guy Decoux + + * eval.c (rb_mod_define_method): wrong comparison for blocks. + +Sat Dec 30 19:28:50 2000 Yukihiro Matsumoto + + * gc.c (id2ref): should handle Symbol too. + + * gc.c (id2ref): should print original ptr value + Sat Dec 30 03:14:22 2000 Yukihiro Matsumoto * eval.c (rb_iterate): NODE_CFUNC does not protect its data diff --git a/Makefile.in b/Makefile.in index b1b0166b89..af29b78daa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -111,12 +111,13 @@ clean:; @rm -f $(OBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY_ALIASES) $(MAINOBJ) @-@MINIRUBY@ -Cext extmk.rb clean 2> /dev/null || true @rm -f $(PROGRAM) miniruby$(EXEEXT) -distclean: clean +distclean:; @-@MINIRUBY@ -Cext extmk.rb distclean 2> /dev/null || true + $(MAKE) clean @rm -f Makefile ext/extmk.rb config.h @rm -f ext/config.cache config.cache config.log config.status @rm -f *~ core *.core gmon.out y.tab.c y.output ruby.imp -realclean: distclean +realclean: distclean @rm -f parse.c @rm -f lex.c @@ -142,7 +143,7 @@ fake.rb: miniruby$(EXEEXT) config.status: $(srcdir)/configure $(SHELL) ./config.status --recheck -$(srcdir)/configure: $(srcdir)/configure.in + $(srcdir)/configure: $(srcdir)/configure.in cd $(srcdir) && $(AUTOCONF) .c.@OBJEXT@: diff --git a/ToDo b/ToDo index 4062103d29..1d12e5869a 100644 --- a/ToDo +++ b/ToDo @@ -1,12 +1,5 @@ Language Spec. -- def foo; .. rescue .. end -- compile time string concatenation, "hello" "world" => "helloworld" -- rescue modifier; a rescue b => begin a rescue; b end -- %w(a\ b\ c abc) => ["a b c", "abc"] -- objectify symbols -- class variable (prefix @@) -- rescue RuntimeError => err * operator !! for rescue. ??? * objectify characters * ../... outside condition invokes operator method too. @@ -31,15 +24,11 @@ Language Spec. * a +1 to be a+1, not a(+1). * unify == and eql? again * to_i returns nil if str contains no digit. +* raise exception by `` Hacking Interpreter -- use eban's fnmatch -- RUBYOPT environment variable -- alias $defout $> -- retrieve STACK_LEVEL_MAX from users' limit. -- remove end_proc registered out of require only -- all object made freezable +- generational GC * non-blocking open (e.g. for named pipe) for thread * avoid blocking with gethostbyname/gethostbyaddr (use fork ???) * objectify interpreters ??? @@ -48,41 +37,16 @@ Hacking Interpreter * scrambled script, or script filter * setuid ruby * performance tune for in-block (dynamic) local variables. -* generational GC * give warnings to assign magic variables. * export rb_io_{addstr,printf,puts,print} * autoload should work with threads [ruby-talk:4589] * remove stdio dependency from IOs. * warn for inconsistent local variable usage (lv m and method m at the same time). +* MicroRuby Standard Libraries -- hash[key] = nil does not remove entry; hashes may have nil as the value. -- hash.fetch(key) raises exception if key is not found. -- Array#{first,last,at} -- Dir.glob(pat){|f|...} -- sprintf/printf's $ to specify argument order -- Dir.glob("**/*.c") ala zsh -- Remove Enumerable#{size,length} -- Array#slice, Array#slice! -- String#slice, String#slice! -- Marshal should handle generic instance variables. -- debugger for thread programming -- SyntaxError, NameError, LoadError and NotImplementedError are subclasses of - ScriptError..), \G -- Struct::new([name,]member,...) -- IO#reopen accepts path as well -- Kernel#scan -- call initialize for builtin classes too -- performance tune for String's non-bang methods. -- 'w' template for pack/unpack -- alternative for interator? => block_given? -- regex - /p (made obsolete), /m (new) -- consistent /, %, divmod -- unbound method object -- integrate final.rb into the core. +- Module#define_method which takes a name and a body (block, proc or method). * Enumerable#sort_by for Schwartzian transformation * String#scanf(?) * Object#fmt(?) @@ -98,31 +62,29 @@ Standard Libraries * Process::waitall [ruby-talk:4557] * synchronized method - synchronized{...}, synchronized :foo, :bar * move Time::times to Process. -- Module#define_method which takes a name and a body (block, proc or method). * IO#for_fd in general * Array#&, Array#| to allow duplication. ??? -- fork_and_kill_other_threads. +* fork_and_kill_other_threads. * way to specify immortal (fork endurance) thread; * or raise ForkException to every thread but fork caller. * Array#fetch +* Hash::new{default} or recommend Hash#fetch? +* Enume#inject Extension Libraries -- FastCGI ruby * ptk.rb pTk wrapper that is compatible to tk.rb * Berkeley DB extension * BitVector Ruby Libraries -- net/http.rb * add uri.rb * urllib.rb, nttplib.rb, etc. * format like perl's Tools -- extension library maker using SWIG * freeze or undump to bundle everything Misc diff --git a/bignum.c b/bignum.c index daf131b042..e342989da8 100644 --- a/bignum.c +++ b/bignum.c @@ -831,8 +831,10 @@ bigdivrem(x, y, divp, modp) t2 %= dd; } RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign; - if (!RBIGNUM(x)->sign) t2 = -(long)t2; - if (modp) *modp = rb_int2big((long)t2); + if (modp) { + *modp = rb_uint2big((unsigned long)t2); + RBIGNUM(*modp)->sign = RBIGNUM(x)->sign; + } if (divp) *divp = z; return; } diff --git a/dln.c b/dln.c index c843bee57b..8046b158b3 100644 --- a/dln.c +++ b/dln.c @@ -1166,7 +1166,7 @@ dln_strerror() } -#if defined(_AIX) +#if defined(_AIX) && ! defined(_IA64) static void aix_loaderror(const char *pathname) { @@ -1310,7 +1310,7 @@ dln_load(file) } #endif /* hpux */ -#if defined(_AIX) +#if defined(_AIX) && ! defined(_IA64) #define DLN_DEFINED { void (*init_fct)(); diff --git a/enum.c b/enum.c index 4a97811384..11f42c48d7 100644 --- a/enum.c +++ b/enum.c @@ -178,6 +178,24 @@ enum_collect(obj) return tmp; } +static VALUE +inject_i(i, np) + VALUE i; + VALUE *np; +{ + *np = rb_yield(rb_assoc_new(*np, i)); + return Qnil; +} + +static VALUE +enum_inject(obj, n) + VALUE obj, n; +{ + rb_iterate(rb_each, obj, inject_i, (VALUE)&n); + + return n; +} + static VALUE enum_sort(obj) VALUE obj; @@ -339,6 +357,7 @@ Init_Enumerable() rb_define_method(rb_mEnumerable,"reject", enum_reject, 0); rb_define_method(rb_mEnumerable,"collect", enum_collect, 0); rb_define_method(rb_mEnumerable,"map", enum_collect, 0); + rb_define_method(rb_mEnumerable,"inject", enum_inject, 1); rb_define_method(rb_mEnumerable,"min", enum_min, 0); rb_define_method(rb_mEnumerable,"max", enum_max, 0); rb_define_method(rb_mEnumerable,"member?", enum_member, 1); diff --git a/error.c b/error.c index 4527128030..ef74ff5af0 100644 --- a/error.c +++ b/error.c @@ -569,8 +569,6 @@ Init_Exception() rb_eNameError = rb_define_class("NameError", rb_eScriptError); rb_eLoadError = rb_define_class("LoadError", 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); @@ -694,6 +692,13 @@ rb_sys_fail(mesg) rb_exc_raise(ee); } +void +rb_load_failed(path) + char *path; +{ + rb_loaderror("%s -- %s", strerror(errno), path); +} + void rb_error_frozen(what) char *what; diff --git a/eval.c b/eval.c index 21cff9bcd0..4ad82d1053 100644 --- a/eval.c +++ b/eval.c @@ -1122,9 +1122,15 @@ void rb_exec_end_proc _((void)); void ruby_finalize() { - rb_trap_exit(); - rb_exec_end_proc(); - rb_gc_call_finalizer_at_exit(); + int state; + + PUSH_TAG(PROT_NONE); + if ((state = EXEC_TAG()) == 0) { + rb_trap_exit(); + rb_exec_end_proc(); + rb_gc_call_finalizer_at_exit(); + } + POP_TAG(); } void @@ -3526,7 +3532,7 @@ rb_yield_0(val, self, klass, acheck) if (!node) { result = Qnil; } - else if (nd_type(node) == NODE_IFUNC) { + else if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) { if (val == Qundef) val = rb_ary_new2(0); result = (*node->nd_cfnc)(val, node->nd_tval, self); } @@ -4417,6 +4423,9 @@ rb_call(klass, recv, mid, argc, argv, scope) ID id = mid; struct cache_entry *ent; + if (!klass) { + rb_raise(rb_eNotImpError, "method call on terminated obejct"); + } /* is it in the method cache? */ ent = cache + EXPR1(klass, mid); if (ent->mid == mid && ent->klass == klass) { @@ -6635,7 +6644,7 @@ rb_mod_define_method(argc, argv, mod) if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) { rb_add_method(mod, id, NEW_DMETHOD(method_unbind(body)), NOEX_PUBLIC); } - else if (RDATA(body)->dmark != (RUBY_DATA_FUNC)blk_mark) { + else if (RDATA(body)->dmark == (RUBY_DATA_FUNC)blk_mark) { rb_add_method(mod, id, NEW_BMETHOD(body), NOEX_PUBLIC); } else { diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 52debd47cc..8dd457fc98 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -12,7 +12,13 @@ elsif ARGV[0] == 'install' $destdir = ARGV[1] || '' ARGV.shift elsif ARGV[0] == 'clean' - $clean = true + $clean = "clean" + ARGV.shift +elsif ARGV[0] == 'distclean' + $clean = "distclean" + ARGV.shift +elsif ARGV[0] == 'realclean' + $clean = "realclean" ARGV.shift end @@ -625,7 +631,7 @@ def extmake(target) if $install system "#{$make} install DESTDIR=#{$destdir}" elsif $clean - system "#{$make} clean" + system "#{$make} #{$clean}" else unless system "#{$make} all" if ENV["MAKEFLAGS"] != "k" and ENV["MFLAGS"] != "-k" diff --git a/gc.c b/gc.c index 65803a3860..e4320e0a4f 100644 --- a/gc.c +++ b/gc.c @@ -480,7 +480,6 @@ rb_gc_mark(ptr) case NODE_OP_ASGN_AND: rb_gc_mark(obj->as.node.u1.node); /* fall through */ - case NODE_IFUNC: case NODE_METHOD: /* 2 */ case NODE_NOT: case NODE_GASGN: @@ -1232,7 +1231,8 @@ rb_gc_call_finalizer_at_exit() p = heaps[i]; pend = p + HEAP_SLOTS; while (p < pend) { if (FL_TEST(p, FL_FINALIZE)) { - p->as.free.flag = 0; + FL_UNSET(p, FL_FINALIZE); + p->as.basic.klass = 0; run_final((VALUE)p); } p++; @@ -1260,21 +1260,22 @@ static VALUE id2ref(obj, id) VALUE obj, id; { - unsigned long ptr; + unsigned long ptr, p0; rb_secure(4); - ptr = NUM2UINT(id); + p0 = ptr = NUM2UINT(id); if (FIXNUM_P(ptr)) return (VALUE)ptr; + if (SYMBOL_P(ptr)) return (VALUE)ptr; if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; ptr = id ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ if (!is_pointer_to_heap(ptr)) { - rb_raise(rb_eRangeError, "0x%x is not id value", ptr); + rb_raise(rb_eRangeError, "0x%x is not id value", p0); } if (BUILTIN_TYPE(ptr) == 0) { - rb_raise(rb_eRangeError, "0x%x is recycled object", ptr); + rb_raise(rb_eRangeError, "0x%x is recycled object", p0); } return (VALUE)ptr; } diff --git a/intern.h b/intern.h index 7d8b0de130..640fb5d836 100644 --- a/intern.h +++ b/intern.h @@ -107,7 +107,7 @@ VALUE rb_exc_new3 _((VALUE, VALUE)); void rb_loaderror __((const char*, ...)) NORETURN; void rb_compile_error __((const char*, ...)); void rb_compile_error_append __((const char*, ...)); -void rb_error_frozen _((char*)); +void rb_error_frozen _((char*)) NORETURN; /* eval.c */ void rb_exc_raise _((VALUE)) NORETURN; void rb_exc_fatal _((VALUE)) NORETURN; diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb index 30fc8582cb..8c4417c490 100644 --- a/lib/cgi/session.rb +++ b/lib/cgi/session.rb @@ -1,3 +1,4 @@ +# Copyright (C) 2001 Yukihiro "Matz" Matsumoto # Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Information-technology Promotion Agency, Japan @@ -15,14 +16,14 @@ class CGI } end - def create_new_id + def Session::create_new_id require 'md5' md5 = MD5::new md5.update(String(Time::now)) md5.update(String(rand(0))) md5.update(String($$)) md5.update('foobar') - @session_id = md5.hexdigest[0,16] + md5.hexdigest[0,16] end private :create_new_id @@ -31,7 +32,7 @@ class CGI id, = option['session_id'] unless id if option['new_session'] - id = create_new_id + id = Session::create_new_id end end unless id @@ -43,7 +44,7 @@ class CGI if option.key?('new_session') and not option['new_session'] raise ArgumentError, "session_key `%s' should be supplied"%session_key end - id = create_new_id + id = Session::create_new_id end end @session_id = id @@ -54,9 +55,9 @@ class CGI @output_cookies = [ Cookie::new("name" => session_key, "value" => id, - "path" => if ENV["PATH_INFO"] then - File::dirname(ENV["PATH_INFO"]) - elsif ENV["SCRIPT_NAME"] then + "path" => if option['session_path'] then + option['session_path'] + elsif ENV["SCRIPT_NAME"] then File::dirname(ENV["SCRIPT_NAME"]) else "" @@ -134,12 +135,14 @@ class CGI end def close + return unless @f.closed? update @f.close end def delete path = @f.path + return unless @f.closed? @f.close File::unlink path end diff --git a/node.h b/node.h index 19e95cd4f2..658941a723 100644 --- a/node.h +++ b/node.h @@ -21,7 +21,6 @@ enum node_type { NODE_METHOD, NODE_FBODY, NODE_CFUNC, - NODE_IFUNC, NODE_SCOPE, NODE_BLOCK, NODE_IF, @@ -121,6 +120,7 @@ enum node_type { NODE_DMETHOD, NODE_BMETHOD, NODE_MEMO, + NODE_IFUNC, NODE_LAST }; diff --git a/parse.y b/parse.y index 7149818668..0f0db252fc 100644 --- a/parse.y +++ b/parse.y @@ -938,7 +938,11 @@ opt_call_args : none call_args : command_call { $$ = NEW_LIST($1); - } + } /* + | args ',' + { + $$ = $1; + } */ | args ',' command_call { $$ = list_append($1, $3); @@ -952,11 +956,11 @@ call_args : command_call value_expr($4); $$ = arg_concat($1, $4); $$ = arg_blk_pass($$, $5); - } + } /* | assocs ',' { $$ = NEW_LIST(NEW_HASH($1)); - } + } */ | assocs opt_block_arg { $$ = NEW_LIST(NEW_HASH($1)); @@ -972,11 +976,11 @@ call_args : command_call { $$ = list_append($1, NEW_HASH($3)); $$ = arg_blk_pass($$, $4); - } + } /* | args ',' assocs ',' { $$ = list_append($1, NEW_HASH($3)); - } + } */ | args ',' assocs ',' tSTAR arg opt_block_arg { value_expr($6); @@ -1842,8 +1846,6 @@ none : /* none */ $$ = 0; } %% -#include -#include #include "regex.h" #include "util.h" diff --git a/re.c b/re.c index bb9898fdb4..9d1a282dee 100644 --- a/re.c +++ b/re.c @@ -726,6 +726,19 @@ last_match_getter() return rb_reg_last_match(rb_backref_get()); } +static VALUE +rb_reg_s_last_match(argc, argv) + int argc; + VALUE *argv; +{ + VALUE nth; + + if (rb_scan_args(argc, argv, "01", &nth) == 1) { + rb_reg_nth_match(NUM2INT(nth), rb_backref_get()); + } + return rb_reg_last_match(rb_backref_get()); +} + static VALUE prematch_getter() { @@ -1347,7 +1360,7 @@ Init_Regexp() rb_define_singleton_method(rb_cRegexp, "compile", rb_reg_s_new, -1); rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, -1); rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, -1); - rb_define_singleton_method(rb_cRegexp, "last_match", match_getter, 0); + rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, 0); rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1); rb_define_method(rb_cRegexp, "clone", rb_reg_clone, 0); diff --git a/ruby.c b/ruby.c index 9649b69af4..6910ff7c2b 100644 --- a/ruby.c +++ b/ruby.c @@ -728,7 +728,7 @@ load_file(fname, script) FILE *fp = fopen(fname, "r"); if (fp == NULL) { - rb_raise(rb_eLoadError, "No such file to load -- %s", fname); + rb_load_fail(fname); } fclose(fp); diff --git a/version.h b/version.h index 2b892a328a..9e30579bbe 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.0" -#define RUBY_RELEASE_DATE "2000-12-29" +#define RUBY_RELEASE_DATE "2000-12-30" #define RUBY_VERSION_CODE 170 -#define RUBY_RELEASE_CODE 20001229 +#define RUBY_RELEASE_CODE 20001230