summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore27
-rw-r--r--ChangeLog892
-rw-r--r--Makefile.in5
-rw-r--r--README23
-rw-r--r--README.jp16
-rw-r--r--array.c2
-rw-r--r--bignum.c18
-rw-r--r--class.c75
-rw-r--r--configure.in62
-rw-r--r--cygwin/GNUmakefile.in2
-rw-r--r--dir.c76
-rw-r--r--djgpp/config.status77
-rw-r--r--dln.c31
-rw-r--r--dln.h2
-rw-r--r--error.c7
-rw-r--r--eval.c679
-rw-r--r--ext/.cvsignore1
-rw-r--r--ext/Win32API/Win32API.c6
-rw-r--r--ext/Win32API/extconf.rb2
-rw-r--r--ext/curses/.cvsignore1
-rw-r--r--ext/curses/curses.c8
-rw-r--r--ext/curses/extconf.rb4
-rw-r--r--ext/dbm/.cvsignore1
-rw-r--r--ext/etc/.cvsignore1
-rw-r--r--ext/extmk.rb.in34
-rw-r--r--ext/fcntl/.cvsignore1
-rw-r--r--ext/gdbm/.cvsignore1
-rw-r--r--ext/md5/.cvsignore1
-rw-r--r--ext/nkf/.cvsignore1
-rw-r--r--ext/pty/.cvsignore1
-rw-r--r--ext/pty/extconf.rb16
-rw-r--r--ext/readline/.cvsignore1
-rw-r--r--ext/readline/extconf.rb3
-rw-r--r--ext/readline/readline.c9
-rw-r--r--ext/sdbm/.cvsignore1
-rw-r--r--ext/sdbm/_sdbm.c4
-rw-r--r--ext/socket/.cvsignore1
-rw-r--r--ext/tcltklib/.cvsignore1
-rw-r--r--ext/tk/.cvsignore1
-rw-r--r--ext/tk/lib/tk.rb143
-rw-r--r--ext/tk/lib/tkcanvas.rb8
-rw-r--r--ext/tk/lib/tkentry.rb2
-rw-r--r--ext/tk/lib/tktext.rb8
-rw-r--r--ext/tk/lib/tkvirtevent.rb33
-rw-r--r--file.c171
-rw-r--r--gc.c118
-rw-r--r--hash.c9
-rw-r--r--intern.h6
-rw-r--r--io.c39
-rw-r--r--lib/Env.rb14
-rw-r--r--lib/cgi.rb232
-rw-r--r--lib/cgi/session.rb15
-rw-r--r--lib/date.rb38
-rw-r--r--lib/debug.rb210
-rw-r--r--lib/delegate.rb2
-rw-r--r--lib/importenv.rb6
-rw-r--r--lib/irb/ruby-lex.rb2
-rw-r--r--lib/mkmf.rb53
-rw-r--r--lib/monitor.rb96
-rw-r--r--lib/net/http.rb1118
-rw-r--r--lib/net/imap.rb487
-rw-r--r--lib/net/pop.rb13
-rw-r--r--lib/net/protocol.rb309
-rw-r--r--lib/net/smtp.rb29
-rw-r--r--lib/net/telnet.rb217
-rw-r--r--lib/observer.rb2
-rw-r--r--lib/parsedate.rb11
-rw-r--r--lib/ping.rb2
-rw-r--r--lib/thread.rb2
-rw-r--r--marshal.c12
-rw-r--r--math.c5
-rw-r--r--misc/ruby-mode.el2
-rw-r--r--missing/dir.h5
-rw-r--r--missing/flock.c120
-rw-r--r--missing/strftime.c6
-rw-r--r--missing/vsnprintf.c6
-rw-r--r--mkconfig.rb17
-rw-r--r--node.h14
-rw-r--r--numeric.c2
-rw-r--r--object.c41
-rw-r--r--pack.c8
-rw-r--r--parse.y365
-rw-r--r--prec.c2
-rw-r--r--re.c14
-rw-r--r--regex.c15
-rw-r--r--ruby.c29
-rw-r--r--ruby.h37
-rw-r--r--sample/README3
-rw-r--r--signal.c16
-rw-r--r--sprintf.c2
-rw-r--r--string.c39
-rw-r--r--time.c17
-rw-r--r--util.c38
-rw-r--r--variable.c17
-rw-r--r--version.h8
-rw-r--r--win32/Makefile.sub4
-rw-r--r--win32/config.h.in1
-rw-r--r--win32/config.status.in4
-rw-r--r--win32/win32.c91
-rw-r--r--win32/win32.h2
100 files changed, 4207 insertions, 2224 deletions
diff --git a/.cvsignore b/.cvsignore
index 8fcaffddb2..35fff17b58 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,19 +1,20 @@
-parse.c
-newver.rb
-ruby
-miniruby
+*.bak
+*.orig
+*.rej
+*.sav
+*~
+.cvsignore
+Makefile
README.fat-patch
-configure
+archive
config.cache
config.h
config.log
config.status
-Makefile
+configure
+miniruby
+newver.rb
+parse.c
ppack
-archive
-extmk.rb
-*.orig
-*.rej
-*.bak
-*.sav
-*~
+rbconfig.rb
+ruby
diff --git a/ChangeLog b/ChangeLog
index c6cd432b49..ee862e9723 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,854 @@
+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 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:33: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 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 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.
+
+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 SUMMER TIME!
+
+ * 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>
+
+ * class.c (rb_mod_clone): should copy method bodies too.
+
+ * bignum.c (bigdivrem): should trim trailing zero bdigits of
+ remainder, even if dd == 0.
+
+Tue Apr 3 15:29:10 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * Makefile.in: Introduce MAINLIBS.
+
+ * configure.in: Link libc_r against the ruby executable on
+ FreeBSD, which is the first attempt to work around a certain
+ problem regarding pthread on FreeBSD. It should make ruby/libruby
+ happy when it loads an extention to a library compiled and linked
+ with -pthread. Note, however, that libruby is _not_ linked with
+ libc_r so as not to mess up pthread unfriendly stuff including
+ apache+mod_ruby and vim6+ruby_interp.
+
+Tue Apr 3 09:56:20 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/extmk.rb.in (create_makefile): create def file only if
+ it does not yet exist.
+
+ * 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 14:25:49 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/monitor.rb (wait): ensure reentrance.
+
+ * lib/monitor.rb (wait): fix timeout support.
+
+Mon Apr 2 12:44:53 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: backport from ruby-1.7.
+
+Mon Apr 2 01:16:24 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c: use ruby's opendir on mingw32.
+
+ * missing/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 03:24:10 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): module inclusion should be check
+ taints.
+
+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
+ rules for the mswin32 platforms.
+
+Wed Mar 28 19:29:21 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: move C++ rules to the right place.
+
+Wed Mar 28 17:39:04 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_str2cstr): warn if string contains \0 and length
+ value is ignored.
+
+Wed Mar 28 15:00:31 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * class.c (rb_singleton_class_clone): should copy class constant
+ table as well.
+
+Wed Mar 28 15:03:23 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): sometimes cache was mistakenly left
+ uncleared - based on the patch by K.Kosako.
+
+Wed Mar 28 09:52:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/Makefile.sub: disable global optimization.
+
+Tue Mar 27 15:00:54 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_mod_define_method): should have clear method cache.
+
+ * eval.c (rb_mod_define_method): should have raised exception for
+ type error.
+
+Tue Mar 27 14:48:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: changed "extern INLINE" to "static inline".
+
+Mon Mar 26 23:19:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * time.c (rb_strftime): check whether strftime returns empty string.
+
+Mon Mar 26 18:14:47 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (rb_glob_helper): part of 1.7 globber backported to proper
+ following of symlinks.
+
+Mon Mar 26 17:21:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c: remove TMP_PROTECT_END to prevent C_ALLOCA crash.
+
+Mon Mar 26 14:04:41 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/Win32API/Win32API.c: remove Init_win32api().
+
+Sat Mar 24 23:44:50 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_defined): should ignore toplevel cbase (Object).
+
+ * eval.c (ev_const_get): ditto.
+
+Fri Mar 23 12:18:44 2001 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * ext/curses/curses.c: curses on Mac OS X public beta does not
+ have _maxx etc.
+
+Fri Mar 23 10:50:31 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_object): should truncate trailing zero short for
+ bignums.
+
+Thu Mar 22 22:15:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/Win32API/extconf.rb: add -fno-omit-frame-pointer.
+
+Thu Mar 22 17:43:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: better inline function support.
+
+ * configure.in (NO_C_INLINE): check if inline is available for the
+ C compiler.
+
+Wed Mar 21 23:07:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (win32_stat): WinNT/2k "//host/share" support.
+
+Wed Mar 21 01:26:14 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): sometimes confused symbol and reference.
+
+Tue Mar 20 23:09:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (win32_stat): UNC support.
+
+ * dir.c (extract_path): fix "./*" problem.
+
+Mon Mar 19 19:14:47 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * marshal.c (shortlen): shortlen should return number of bytes
+ written.
+
+Mon Mar 19 18:56:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.3 released.
+
+Mon Mar 19 16:52:23 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (ev_const_defined): need not to check if cbase->nd_class
+ is rb_cObject.
+
+ * eval.c (ev_const_get): ditto.
+
+Mon Mar 19 16:27:32 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_ALLOC): flags should be initialized.
+
+ * signal.c (rb_f_kill): should use FIX2INT, not FIX2UINT.
+
+Mon Mar 19 11:03:10 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * marshal.c (r_object): len calculation patch was wrong for
+ machines SIZEOF_BDIGITS == SIZEOF_SHORT.
+
+ * gc.c: alloca prototype reorganized for C_ALLOCA machine.
+
+Sun Mar 18 08:58:18 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/net/cgi.rb: // === '' --> //.match('')
+
+ * lib/net/cgi.rb: cgi#header(): improvement for mod_ruby.
+
+ * lib/net/cgi.rb: cgi#rfc1123date(): improvement.
+ thanks to TADA Tadashi <sho@spc.gr.jp>.
+
+ * lib/net/cgi.rb: cgi#rfc1123date(): document bug fix.
+ thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>.
+
+ * lib/net/cgi.rb: cgi#header(): bug fix.
+ thanks to IWATSUKI Hiroyuki <don@na.rim.or.jp>.
+
+Fri Mar 16 17:21:25 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in: Set SOLIBS properly for all ELF and
+ FreeBSD/NetBSD/OpenBSD a.out platforms so that the shlib
+ dependencies are recorded in the libruby shlib.
+
+Wed Mar 14 16:41:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): raise FATAL just once to
+ THREAD_TO_KILL.
+
+Wed Mar 14 10:41:34 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): 0 (= Qfalse) is a valid value, so that
+ default self should be checked by klass == 0.
+
+ * bignum.c (rb_cstr2inum): should disallow '++1', '+-1', etc.
+
+Tue Mar 13 17:51:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_defined): add new parameter self for special
+ const fallback.
+
+ * eval.c (ev_const_get): ditto.
+
+Tue Mar 13 16:39:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (rb_glob_helper): fix drive letter handling on DOSISH.
+
+Tue Mar 13 15:01:12 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: add HTTPRequest#basic_auth.
+
+ * lib/net/smtp.rb: raise if only account or password is given.
+
+ * lib/net/protocol.rb: WriteAdapter#<< returns self.
+
+Tue Mar 13 14:41:16 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_seek): wrong calling sequence of rb_io_seek().
+
+Mon Mar 12 18:59:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): save/restore $libs and $LIBPATH.
+
+Sun Mar 11 00:55:31 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (install_rb): fix handling of destination path.
+
+Sat Mar 10 02:34:18 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * math.c (math_log, math_log10): use nan() instead of 0.0/0.0 on Cygwin.
+
+Thu Mar 8 17:43:59 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: one write(2) per one line.
+
+Wed Mar 7 14:26:11 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * math.c (math_log, math_log10): should return NaN if x < 0.0
+ on Cygwin.
+
+Thu Mar 7 10:31:26 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (stmt): while/until modifier must work for empty body.
+
+Tue Mar 6 22:53:58 2001 Kazuhiro Yoshida <moriq.kazuhiro@nifty.ne.jp>
+
+ * ruby.c (ruby_set_argv): clear ARGV contents before adding args.
+
+Tue Mar 6 10:50:29 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (primary): rescue and ensure clauses should be allowed
+ to appear in singleton method body.
+
+Mon Mar 5 17:25:13 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_eq): compare Procs using blocktag equality.
+
+ * eval.c (proc_to_s): stringify according to block tag address.
+
+Mon Mar 5 17:19:56 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): use GetLocalTime() instead of ftime()
+ for high-resolution timing.
+
+Sun Mar 4 20:45:20 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: add C++ rules in addition to C
+ rules.
+
+Sun Mar 4 17:01:09 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * string.c (trnext): support backslash escape in String#tr.
+
+Wed Feb 28 11:02:41 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_delete_bang): delete! should take at least 1
+ argument.
+
+Tue Feb 27 16:38:15 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_get): retrieve Object's caonstat if no current
+ class is available (e.g. defining singleton class for Fixnums).
+
+ * eval.c (ev_const_defined): check Object's constant if no current
+ class is available (e.g. defining singleton class for Fixnums).
+
+ * eval.c (proc_call): ignore block to `call' always, despite of
+ being orphan or not.
+
+Wed Feb 27 10:16:32 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (rb_yield_0): should check based on rb_block_given_p()
+ and rb_f_block_given_p().
+
+Mon Feb 26 16:20:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): call ruby_show_version() just once.
+
+Mon Feb 26 00:04:52 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_call): should not modify ruby_block->frame.iter
+ based on ruby_frame->iter altered by PUSH_ITER().
+
+Mon Feb 26 05:27:52 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/net/telnet.rb: #telnetmode(), #binmode(): bug fix.
+ thanks to nobu.nakada@nifty.ne.jp.
+
+Mon Feb 26 04:55:50 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: CGI#form(): bug fix.
+ thanks to MoonWolf <moonwolf@moonwolf.com>.
+
+ * lib/cgi.rb: CGI#rfc1123_date(): improvement.
+ thanks to Tomoyasu Akita <genzo-@dm4lab.to>.
+
+ * lib/cgi.rb: CGI#header(): improvement for mod_ruby.
+ thanks to Shugo Maeda <shugo@ruby-lang.org>.
+
+Sun Feb 25 02:45:30 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * file.c (rb_file_s_rename): avoid Cygwin's bug.
+
+Sat Feb 24 23:32:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_fd_close): should save current context before
+ raising exception.
+
+Sat Feb 24 22:14:00 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (myrename): fix error handling.
+
+Sat Feb 24 15:43:31 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: use net 1.2 for also ruby 1.6 branch.
+
+ * lib/net/smtp.rb: ditto.
+
+ * lib/net/pop.rb: ditto.
+
+ * lib/net/http.rb: ditto.
+
+Fri Feb 23 16:36:09 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: always close connection if body is not exist.
+
+Fri Feb 23 13:27:05 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: keep-alive detection was incomplete.
+
+Fri Feb 23 08:24:53 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: clear read buffer after reopen.
+
+ * lib/net/http.rb: update RD document.
+
+Tue Feb 20 16:37:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2long): should not raise RangeError for Bignum
+ LONG_MIN value.
+
+Mon Feb 19 17:46:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_substr): "a"[1,2] should return ""; need
+ rubicon upgrade.
+
+Mon Feb 19 01:55:43 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (secure_visibility): visibility check for untainted modules.
+
+Mon Feb 19 00:29:29 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * signal.c (sigpipe): sighandler which does nothing.
+
+ * signal.c (trap): set sigpipe function for SIGPIPE.
+
+ * signal.c (Init_signal): default SIGPIPE handler should be
+ sigpipe function.
+
+Sun Feb 18 15:42:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/curses/extconf.rb: add dir_config.
+
+ * missing/flock.c: use fcntl(2) instead of lockf(2).
+
+Sun Feb 18 13:02:03 2001 Yasushi Shoji <yashi@yashi.com>
+
+ * array.c (rb_ary_subseq): wrong boundary check.
+
+Fri Feb 16 01:44:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (set_outfile): f should be the FILE* from the assigning value.
+
+Thu Feb 15 11:33:49 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/cgi/session.rb (close): fixed reversed condition.
+
+Wed Feb 14 17:28:24 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: supports unknown resp_text_code.
+
+Wed Feb 14 00:44:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_s_glob): call rb_yield directly (via push_pattern) if
+ block is given to the method.
+
+ * dir.c (push_pattern): do not call rb_ary_push; yield directly.
+
+Tue Feb 13 23:05:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (lstat): should use rb_sys_stat if lstat(2) is not
+ available.
+
+Tue Feb 13 17:00:18 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: supports HTTP 1.0 server.
+
+Tue Feb 13 01:13:43 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (primary): preserve and clear in_single and in_def using
+ stack to prevent nested method errors in singleton class bodies.
+
+Sun Feb 11 16:00:30 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (stack_length): use __builtin_frame_address() only if
+ GCC and i386 CPU.
+
+ * gc.c (rb_gc, Init_stack): ditto.
+
+ * configure.in: add ac_cv_func_getpgrp_void=yes on DJGPP.
+
+Sat Feb 10 23:43:49 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * hash.c (rb_any_hash): dumped core on machines sizeof(int) != sizeof(long).
+
+Sat Feb 10 23:07:15 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (PREV_IS_A_LETTER): should not treat c>0x7f as a word
+ character if -Kn.
+
+Sat Feb 10 00:06:28 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * win32/win32.c (win32_stat): replace stat for enable when pathname
+ ends with '/' or '\' for mswin32 on Win9X / Win2k.
+
+ * win32/win32.h: ditto.
+
+ * ruby.h: ditto.
+
+ * dir.c (rb_glob_helper): ditto.
+
+ * file.c (rb_stat, rb_file_s_stat, eaccess, check3rdbyte): ditto.
+
+Fri Feb 9 22:54:57 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ruby.c (ruby_init_loadpath): convert '\\' to '/'
+ before finding executable file path.
+
+Fri Feb 9 17:41:53 2001 Triet H. Lai <thlai@mail.usyd.edu.au>
+
+ * dir.c (rb_glob_helper): do not follow symbolic links.
+
+Fri Feb 8 23:53:08 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/config.h.in (inline): add inline definition.
+
+Thu Feb 8 21:27:24 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (install_rb): fix handling of relative path.
+
+ * lib/mkmf.rb (create_makefile): add srcdir.
+
+Wed Feb 7 16:05:22 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (parse_quotedwords): %w should allow parenthesis escape.
+
+Wed Feb 7 00:57:42 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parse_qstring): %q should allow terminator escape.
+
+Wed Feb 7 00:57:42 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_equal): all option flags should be same to be equal.
+
+Tue Feb 6 21:01:29 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: ignore EOFError on only specified case.
+
+ * lib/net/http.rb: take HTTP 1.0 server into account.
+
+Mon Feb 5 00:39:06 2001 KANEKO Naoshi <wbs01621@mail.wbs.ne.jp>
+
+ * dir.c: use ISXXX() instead of isxxx().
+
+ * dln.c (aix_loaderror): ditto.
+
+ * file.c (rb_file_s_expand_path): ditto.
+
+ * string.c (rb_str_upcase_bang): ditto.
+
+ * win32/win32.c (do_spawn): ditto.
+
+ * win32/win32.c (NtMakeCmdVector): ditto.
+
+ * win32/win32.c (opendir): ditto.
+
+Fri Feb 3 00:48:50 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/win32.c (isInternalCmd): ignore case for shell's internal
+ command. (marge from HEAD)
+
+Fri Feb 2 16:14:51 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (POP_VARS): propagate DVAR_DONT_RECYCLE, if
+ SCOPE_DONT_RECYCLE of ruby_scope is set.
+
+Wed Jan 31 22:27:29 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: gcc-2.95.2-7(cygwin) support.
+ add -mwin32 if available.
+
+ * cygwin/GNUmakefile: ditto.
+
+Mon Jan 29 17:36:19 2001 TOYOFUKU Chikanobu <toyofuku@juice.or.jp>
+
+ * eval.c (rb_eval): nd_iter evaluation should be wrapped by
+ BEGIN_CALLARGS and END_CALLARGS.
+
+Mon Jan 29 01:40:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_independent): should not clear str->orig here.
+ it's too early.
+
+Wed Jan 24 01:45:49 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (POP_BLOCK_TAG): call rb_gc_force_recycle() if block has
+ not been objectified.
+
+ * eval.c (rb_callcc): should nail down block->tag history to avoid
+ rb_gc_force_recycle().
+
+Tue Jan 23 18:51:57 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): should finalize objects in
+ deferred_final_list too.
+
+Tue Jan 23 16:10:12 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (os_live_obj): do not list terminated object.
+
+ * gc.c (os_obj_of): ditto.
+
+ * gc.c (rb_gc_mark): support new T_BLKTAG tag.
+
+ * gc.c (obj_free): ditto.
+
+ * eval.c (new_blktag): creation of new block tag, which holds
+ destination of global jump and orphan status.
+
+ * eval.c (block_pass): break from orphan Proc object will raise a
+ LocalJumpError exception.
+
+Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * mkconfig.rb: autoconf 2.49 support.
+
+Sat Jan 20 03:54:00 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): fixed serious syntax misbehavior. do's
+ preceding was too high. a block in `foo bar do .. end' should
+ be passed to `foo', not `bar'.
+
+ * parse.y (block_call): syntax restructure.
+
+Fri Jan 19 04:04:31 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/irb/ruby-lex.rb: Merge from HEAD: rev.1.4
+
+Wed Jan 17 13:28:26 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: remove DEFS definition.
+
+ * mkconfig.rb: ditto.
+
+ * win32/config.status.in: ditto.
+
+Tue Jan 16 16:59:14 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: ignore EOFError for read
+
+Sun Jan 14 21:49:28 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sprintf.c (rb_f_sprintf): simple typo. binary base should be 2,
+ not '2'.
+
+Sun Jan 14 02:49:57 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb (adding): too few "yield" in case of arg is
+ not String/File.
+
+Sat Jan 13 19:18:18 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * re.c (rb_reg_desc): separate RE_OPTION_MULTILINE
+
+ * re.c (rb_reg_options): add RE_OPTION_{POSIXLINE,RE_OPTION_MULTILINE,
+ RE_OPTION_EXTENDED}
+
+Thu Jan 11 06:45:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_dup): should propagate FL_SINGLETON.
+
+ * object.c (inspect_obj): handles the case of no instance variable.
+
+Wed Jan 10 01:50:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_reverse_bang): forgot to call rb_str_modify().
+
+Tue Jan 9 17:41:40 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_obj_taint): check frozen status before modifying
+ taint status.
+
+ * object.c (rb_obj_untaint): ditto.
+
+Mon Jan 8 21:35:10 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * file.c (path_check_1): should restore modified path.
+
+Mon Jan 8 21:24:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * error.c (rb_load_fail): new func to report LoadError.
+
+ * ruby.c (load_file): use rb_load_fail.
+
+Sat Jan 6 00:55:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): template "m2" or "u2" caused inifinite loop.
+
+Fri Jan 5 01:02:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ruby_finalize): should enclosed by PUSH_TAG/POP_TAG.
+
+Sun Dec 31 01:39:16 2000 Guy Decoux <decoux@moulon.inra.fr>
+
+ * eval.c (rb_mod_define_method): wrong comparison for blocks.
+
+Sat Dec 30 19:28:50 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): should handle Symbol too.
+
+ * gc.c (id2ref): should print original ptr value
+
+Sat Dec 30 03:14:22 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_iterate): NODE_CFUNC does not protect its data
+ (nd_tval), so create new node NODE_IFUNC for iteration C
+ function.
+
+ * eval.c (rb_yield_0): use NODE_IFUNC.
+
+ * gc.c (rb_gc_mark): support NODE_IFUNC.
+
+Fri Dec 29 11:41:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (mem_error): prohibit recursive mem_error().
+ (ruby-bugs-ja:PR#36)
+
+Fri Dec 29 11:05:41 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_fd_writable): should not switch context if
+ rb_thread_critical is set.
+
+ * eval.c (rb_thread_wait_fd): ditto.
+
+ * eval.c (rb_thread_wait_for): ditto.
+
+ * eval.c (rb_thread_select): ditto.
+
+ * eval.c (rb_thread_join): join during critical section causes
+ deadlock.
+
+Tue Dec 26 18:46:41 2000 NAKAMURA Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/debug.rb: Avoid thread deadlock in debugging stopped thread.
+
+ * lib/debug.rb: Uncleared 'finish' state.
+
+Tue Dec 26 16:53:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): remove dvar node by rb_gc_force_recycle()
+ more eagerly.
+
+ * eval.c (rb_f_binding): recycling should be stopped for outer
+ scope too.
+
+ * eval.c (proc_new): ditto.
+
+Tue Dec 26 15:45:35 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_inspect): should treat multibyte chracters
+ properly.
+
+Mon Dec 25 17:49:08 2000 K.Kosako <kosako@sofnec.co.jp>
+
+ * string.c (rb_str_replace_m): unexpected string share happens if
+ replace is done for associated (STR_NO_ORIG) string.
+
+Tue Dec 26 15:01:53 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_f_p): should not call rb_io_flush() if rb_defout is not
+ a IO (T_FILE).
+
+Mon Dec 25 15:52:39 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.2 released.
+
Mon Dec 25 05:11:04 2000 Wakou Aoyama <wakou@fsinet.or.jp>
* lib/cgi.rb: version 2.1.2 (some bug fixes).
@@ -21,10 +872,6 @@ Mon Dec 25 00:04:54 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* eval.c (rb_thread_schedule): initial value of `max' changed to -1.
-Fri Dec 22 17:59:30 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
-
- * stable version 1.6.2 released.
-
Mon Dec 25 00:16:14 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (rb_str_replace_m): copy-on-write replace.
@@ -85,7 +932,7 @@ Tue Dec 19 13:44:50 2000 K.Kosako <kosako@sofnec.co.jp>
Tue Dec 19 00:57:10 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
- * time.c (time_minus): usec might overflow (ruby-bugs-ja:#PR#35).
+ * time.c (time_minus): usec might overflow. (ruby-bugs-ja:PR#35)
* eval.c (rb_obj_extend): Object#extend should take at least one
argument.
@@ -837,7 +1684,7 @@ Sat Sep 23 03:06:25 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
Fri Sep 22 15:46:21 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
- * lib/net/http.rb: too early parameter expantion in string.
+ * lib/net/http.rb: too early parameter expansion in string.
Fri Sep 22 13:58:51 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
@@ -894,7 +1741,7 @@ Wed Sep 20 23:21:38 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Sep 20 14:01:45 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
- * eval.c (rb_provided): detect infnite load loop.
+ * eval.c (rb_provided): detect infinite load loop.
* eval.c (rb_provided): too weak filename comparison.
@@ -959,7 +1806,7 @@ Thu Sep 14 02:46:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Sep 13 17:01:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
- * bignum.c (rb_big_eq): imcomplete value compare of bignums.
+ * bignum.c (rb_big_eq): incomplete value comparison of bignums.
Wed Sep 13 06:39:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -1084,7 +1931,7 @@ Fri Sep 1 10:36:29 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (aref_args,opt_call_args): add block_call to allow a
method without parentheses and with block as a last argument.
- * hash.c (rb_hash_sort): should not retrun nil.
+ * hash.c (rb_hash_sort): should not return nil.
* re.c (match_aref): should use rb_reg_nth_match().
@@ -1252,7 +2099,7 @@ Fri Aug 11 15:43:46 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
Thu Aug 10 08:05:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
- * eval.c (rb_callcc): returned current thread instaed of
+ * eval.c (rb_callcc): returned current thread instead of
continuation wrongly.
Thu Aug 10 05:40:28 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
@@ -1425,7 +2272,7 @@ Tue Jul 18 14:58:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
Mon Jul 17 04:29:50 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
- * lib/mkmf.rb: converts extention of $objs into $OBJEXT.
+ * lib/mkmf.rb: converts extension of $objs into $OBJEXT.
Sun Jul 16 03:02:34 2000 Dave Thomas <dave@thomases.com>
@@ -1522,7 +2369,7 @@ Mon Jul 10 09:07:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
Sat Jul 8 23:08:40 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (rb_thread_start_0): should copy previous scopes to
- prevent rb_gc_force_recylce().
+ prevent rb_gc_force_recycle().
Fri Jul 7 23:36:36 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
@@ -1597,7 +2444,7 @@ Wed Jul 5 09:47:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* time.c (time_arg): Time::local, Time::gm now take 7th optional
argument for usec.
- * numeric.c (num_ceil, etc): default ceil, floor, round, trancate
+ * numeric.c (num_ceil, etc): default ceil, floor, round, truncate
implementation for Numeric, using `to_f'.
* io.c (rb_io_reopen): clear fptr->path after free() to prevent
@@ -1688,7 +2535,7 @@ Mon Jul 3 13:15:02 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* bignum.c (rb_big_divmod): ditto.
- * numeric.c (fixdivmod): does not depend C's undifined %
+ * numeric.c (fixdivmod): does not depend C's undefined %
behavior. adopt to fmod(3m) behavior.
* numeric.c (flo_mod): modulo now reserves fmod(3m) behavior.
@@ -1731,7 +2578,7 @@ Sat Jul 1 15:22:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
Sat Jul 1 15:22:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (rb_eval): the value from RTEST() is not valid Ruby
- objct. result should be either true or false.
+ object. result should be either true or false.
Sat Jul 1 09:30:06 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
@@ -2824,6 +3671,13 @@ Sat Mar 25 23:21:10 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* marshal.c (w_object): symbols should be converted to ID before
dumping out.
+Sun Mar 25 16:52:48 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * file.c (rb_file_flock): do not trap EINTR.
+
+ * missing/flock.c (flock): returns the value from lockf(2)
+ directly.
+
Fri Mar 24 18:26:51 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* file.c (test_check): should have checked exact number of arguments.
@@ -3924,7 +4778,7 @@ Thu Oct 21 16:14:19 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* ruby.c (proc_options): use RUBYOPT environment variable to
retrieve the default options.
- * dir.c (fnmatch): use eban's fnmatch; do not depend on systems's
+ * dir.c (fnmatch): use eban's fnmatch; do not depend on system's
fnmatch (which may have portability problem) anymore.
Wed Oct 20 15:14:24 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -6519,7 +7373,7 @@ Sun Nov 1 01:18:52 1998 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
Sat Oct 31 23:18:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* string.c (rb_str_split_method): negative LIMIT means number of
- splitted fields are unlimited, as in perl.
+ split fields are unlimited, as in perl.
* string.c (rb_str_split_method): if LIMIT is unspecified,
trailing null fields are stripped.
@@ -8775,7 +9629,7 @@ Wed Nov 12 13:44:47 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Mon Nov 10 11:24:51 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
- * regex.c (re_compile_pattern): non-resitering parens (?:..).
+ * regex.c (re_compile_pattern): non-registering parens (?:..).
* regex.c (re_compile_pattern): new meta character \< (wordbeg)
and \> (wordend).
@@ -9031,7 +9885,7 @@ Tue Sep 16 17:54:25 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* ruby.c (ruby_prog_init): close stdaux and stdprn for MSDOS.
* ruby.c (ruby_prog_init): should not add path from environment
- variable, if ruby is running under seuid.
+ variable, if ruby is running under setuid.
* process.c (init_ids): check suid check for setuid/seteuid etc.
diff --git a/Makefile.in b/Makefile.in
index b1b0166b89..420bd3985b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -22,6 +22,7 @@ MISSING = @LIBOBJS@ @ALLOCA@
LDSHARED = @LIBRUBY_LDSHARED@
DLDFLAGS = @LIBRUBY_DLDFLAGS@
SOLIBS = @SOLIBS@
+MAINLIBS = @MAINLIBS@
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
RUBY_SO_NAME=@RUBY_SO_NAME@
@@ -91,7 +92,7 @@ miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) dmyext.@OBJEXT@
$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
$(LIBRUBY_A): $(OBJS) dmyext.@OBJEXT@
@AR@ rcu $@ $(OBJS) dmyext.@OBJEXT@
@@ -230,7 +231,7 @@ dl_os2.@OBJEXT@: $(srcdir)/missing/dl_os2.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/dl_os2.c
win32.@OBJEXT@: $(srcdir)/win32/win32.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/win32/win32.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I$(srcdir)/missing -c $(srcdir)/win32/win32.c
# Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT:
diff --git a/README b/README
index 5794f5daf6..83a88e1359 100644
--- a/README
+++ b/README
@@ -26,10 +26,10 @@ The Ruby distribution can be found on:
You can get it by anonymous CVS. How to check out is:
- $ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs login
- (Logging in to anonymous@cvs.netlab.co.jp)
+ $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/home/cvs login
+ (Logging in to anonymous@cvs.ruby-lang.org)
CVS password: guest
- $ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs checkout ruby
+ $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/home/cvs checkout ruby
* Mailing list
@@ -40,17 +40,20 @@ To subscribe this list, please send the following phrase
e.g.
subscribe Joseph Smith
-in the mail body (not subject) to the address <ruby-talk-ctl@netlab.co.jp>.
+in the mail body (not subject) to the address <ruby-talk-ctl@ruby-lang.org>.
* How to compile and install
This is what you need to do to compile and install Ruby:
- 1. Run ./configure, which will generate config.h and Makefile.
+ 1. If ./configure does not exist or is older than configure.in,
+ run autoconf to (re)generate configure.
- 2. Edit defines.h if you need. Probably this step will not need.
+ 2. Run ./configure, which will generate config.h and Makefile.
- 3. Remove comment mark(#) before the module names from ext/Setup (or
+ 3. Edit defines.h if you need. Probably this step will not need.
+
+ 4. Remove comment mark(#) before the module names from ext/Setup (or
add module names if not present), if you want to link modules
statically.
@@ -59,13 +62,13 @@ This is what you need to do to compile and install Ruby:
remove comment mark from the line "#option nodynamic" in
ext/Setup.
- 4. Run make.
+ 5. Run make.
- 5. Optionally, run 'make test' to check whether the compiled Ruby
+ 6. Optionally, run 'make test' to check whether the compiled Ruby
interpreter works well. If you see the message "test succeeded",
your ruby works as it should (hopefully).
- 6. Run 'make install'
+ 7. Run 'make install'
You may have to be a super user to install ruby.
diff --git a/README.jp b/README.jp
index fccedb2f99..566fbcdac4 100644
--- a/README.jp
+++ b/README.jp
@@ -78,13 +78,17 @@ Ruby³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-ext¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
°Ê²¼¤Î¼ê½ç¤Ç¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
- 1. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë
+ 1. ¤â¤·configure¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤é¤Ê¤¤¡¢¤â¤·¤¯¤Ï
+ configure.in¤è¤ê¸Å¤¤¤è¤¦¤Ê¤é¡¢autoconf¤ò¼Â¹Ô¤·¤Æ
+ ¿·¤·¤¯configure¤òÀ¸À®¤¹¤ë
- 2. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë
+ 2. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë
+
+ 3. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë
¿ʬ¡¤É¬Í×̵¤¤¤È»×¤¤¤Þ¤¹¡¥
- 3. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò
+ 4. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò
»ØÄꤹ¤ë
ext/Setup¤Ëµ­½Ò¤·¤¿¥â¥¸¥å¡¼¥ë¤ÏÀÅŪ¤Ë¥ê¥ó¥¯¤µ¤ì¤Þ¤¹¡¥
@@ -95,14 +99,14 @@ Ruby³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-ext¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
³ÈÄ¥¥â¥¸¥å¡¼¥ë¤òÍøÍѤ¹¤ë¤¿¤á¤Ë¤Ï¡¤¤¢¤é¤«¤¸¤áÀÅŪ¤Ë¥ê¥ó
¥¯¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
- 4. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë
+ 5. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë
- 5. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥
+ 6. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥
¡Ötest succeeded¡×¤Èɽ¼¨¤µ¤ì¤ì¤ÐÀ®¸ù¤Ç¤¹¡¥¤¿¤À¤·¥Æ¥¹¥È
¤ËÀ®¸ù¤·¤Æ¤â´°àú¤À¤ÈÊݾڤµ¤ì¤Æ¤¤¤ëÌõ¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥
- 6. make install
+ 7. make install
root¤Çºî¶È¤¹¤ëɬÍפ¬¤¢¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡¥
diff --git a/array.c b/array.c
index 638b392753..3349a81f8f 100644
--- a/array.c
+++ b/array.c
@@ -1171,7 +1171,7 @@ rb_ary_replace_m(ary, ary2)
return ary;
}
-static VALUE
+VALUE
rb_ary_clear(ary)
VALUE ary;
{
diff --git a/bignum.c b/bignum.c
index daf131b042..708d74c155 100644
--- a/bignum.c
+++ b/bignum.c
@@ -209,6 +209,10 @@ rb_cstr2inum(str, base)
str++;
sign = 0;
}
+ if (str[0] == '+' || str[0] == '-') {
+ if (badcheck) goto bad;
+ return INT2FIX(0);
+ }
if (base == 0) {
if (str[0] == '0') {
if (str[1] == 'x' || str[1] == 'X') {
@@ -467,7 +471,7 @@ rb_big2long(x)
{
unsigned long num = big2ulong(x, "int");
- if ((long)num < 0) {
+ 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;
@@ -831,8 +835,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;
}
@@ -911,10 +917,10 @@ bigdivrem(x, y, divp, modp)
}
if (modp) { /* just normalize remainder */
*modp = rb_big_clone(z);
+ zds = BDIGITS(*modp);
+ while (0 < ny && !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 2eedb262dc..b5caf3082a 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;
{
@@ -67,6 +98,9 @@ rb_singleton_class_clone(klass)
clone->super = RCLASS(klass)->super;
clone->iv_tbl = 0;
clone->m_tbl = 0;
+ if (RCLASS(klass)->iv_tbl) {
+ clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
+ }
clone->m_tbl = st_init_numtable();
st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl);
FL_SET(clone, FL_SINGLETON);
@@ -78,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
@@ -217,7 +255,12 @@ rb_include_module(klass, module)
VALUE 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;
@@ -238,16 +281,16 @@ rb_include_module(klass, module)
if (RCLASS(module)->super) {
rb_include_module(p, RCLASS(module)->super);
}
+ if (changed) rb_clear_cache();
return;
}
}
- rb_frozen_class_p(klass);
- RCLASS(klass)->super =
- include_class_new(module, RCLASS(klass)->super);
+ RCLASS(klass)->super = include_class_new(module, RCLASS(klass)->super);
klass = RCLASS(klass)->super;
module = RCLASS(module)->super;
+ changed = 1;
}
- rb_clear_cache();
+ if (changed) rb_clear_cache();
}
VALUE
diff --git a/configure.in b/configure.in
index b24f492665..094098861d 100644
--- a/configure.in
+++ b/configure.in
@@ -90,14 +90,20 @@ AC_CHECK_TOOL(AR, ar)
AC_CHECK_PROGS(AR, ar aal, ar)
case "$target_os" in
- cygwin*|mingw*)
- AC_CHECK_TOOL(NM, nm)
- AC_CHECK_TOOL(DLLWRAP, dllwrap)
- AC_CHECK_TOOL(AS, as)
- AC_CHECK_TOOL(DLLTOOL, dlltool)
- AC_CHECK_TOOL(WINDRES, windres)
- ;;
+cygwin*|mingw*)
+ AC_CHECK_TOOL(NM, nm)
+ AC_CHECK_TOOL(DLLWRAP, dllwrap)
+ AC_CHECK_TOOL(AS, as)
+ AC_CHECK_TOOL(DLLTOOL, dlltool)
+ AC_CHECK_TOOL(WINDRES, windres)
+ echo 'main(){}' > conftest.c
+ if $CC -mwin32 -c conftest.c 2> /dev/null; then
+ MWIN32=-mwin32
+ CFLAGS="$CFLAGS $MWIN32"
+ fi
+ ;;
esac
+AC_SUBST(MWIN32)
AC_PROG_LN_S
AC_PROG_MAKE_SET
@@ -163,6 +169,14 @@ if test "$rb_cv_have_attr_noreturn" = yes; then
AC_DEFINE(HAVE_ATTR_NORETURN)
fi
+dnl wheather link libc_r or not
+AC_ARG_WITH(libc_r,
+ [--with-libc_r link libc_r if possible (FreeBSD only)], [
+ case $withval in
+ yes) with_libc_r=yes;;
+ *) with_libc_r=no;;
+ esac], [with_libc_r=yes])
+
dnl Checks for libraries.
case "$target_os" in
nextstep*) ;;
@@ -184,6 +198,8 @@ mingw*) LIBS="-lwsock32 -lmsvcrt $LIBS"
ac_cv_func_times=yes;;
os2_emx*) LIBS="-lm $LIBS"
ac_cv_lib_dir_opendir=no;;
+msdosdjgpp*) LIBS="-lm $LIBS"
+ ac_cv_func_getpgrp_void=yes;;
freebsd*) LIBS="-lm $LIBS"
AC_CACHE_CHECK([whether -lxpg4 has to be linked],
rb_cv_lib_xpg4_needed,
@@ -200,6 +216,25 @@ freebsd*) LIBS="-lm $LIBS"
if test "$rb_cv_lib_xpg4_needed" = yes; then
AC_CHECK_LIB(xpg4, setlocale)
fi
+ if test "$with_libc_r" = yes; then
+ AC_CACHE_CHECK([whether libc_r is supplementary to libc],
+ rb_cv_supplementary_lib_c_r,
+ [AC_TRY_CPP([
+#include <osreldate.h>
+#if 500016 <= __FreeBSD_version
+#error libc_r is supplementary to libc
+#endif
+ ],
+ rb_cv_supplementary_lib_c_r=no,
+ rb_cv_supplementary_lib_c_r=yes,
+ rb_cv_supplementary_lib_c_r=yes)])
+ if test "$rb_cv_supplementary_lib_c_r" = yes; then
+ MAINLIBS="-lc_r $MAINLIBS"
+ else
+ MAINLIBS="-pthread $MAINLIBS"
+ CFLAGS="-D_THREAD_SAFE $CFLAGS"
+ fi
+ fi
;;
*) LIBS="-lm $LIBS";;
esac
@@ -316,6 +351,7 @@ test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o"
AC_C_BIGENDIAN
AC_C_CONST
AC_C_CHAR_UNSIGNED
+AC_C_INLINE
AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
@@ -380,7 +416,7 @@ AC_ARG_WITH(default-kcode,
esac])
AC_DEFINE_UNQUOTED(DEFAULT_KCODE, $DEFAULT_KCODE)
-dnl wheather use dln_a_out ot not
+dnl wheather use dln_a_out or not
AC_ARG_WITH(dln-a-out,
[--with-dln-a-out use dln_a_out if possible], [
case $withval in
@@ -757,6 +793,9 @@ if test "$enable_shared" = 'yes'; then
LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
CFLAGS="$CFLAGS $CCDLFLAGS"
ENABLE_SHARED=yes
+ if test "$rb_cv_binary_elf" = yes; then
+ SOLIBS='$(LIBS)'
+ fi
case "$target_os" in
sunos4*)
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
@@ -766,6 +805,7 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
;;
freebsd*)
+ SOLIBS='$(LIBS)'
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
if test "$rb_cv_binary_elf" != "yes" ; then
LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
@@ -773,6 +813,7 @@ if test "$enable_shared" = 'yes'; then
fi
;;
netbsd*)
+ SOLIBS='$(LIBS)'
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
if test "$rb_cv_binary_elf" = yes; then # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so'
@@ -780,6 +821,9 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES= # a.out platforms
fi
;;
+ openbsd*)
+ SOLIBS='$(LIBS)'
+ ;;
solaris*)
XLDFLAGS='-R${prefix}/lib'
;;
@@ -893,6 +937,7 @@ AC_SUBST(LIBRUBYARG)
AC_SUBST(SOLIBS)
AC_SUBST(DLDLIBS)
AC_SUBST(ENABLE_SHARED)
+AC_SUBST(MAINLIBS)
ri_prefix=
test "$program_prefix" != NONE &&
@@ -963,5 +1008,6 @@ fi
echo "creating config.h"
tr -d '\015' < confdefs.h > config.h
+: > confdefs.h
AC_OUTPUT($FIRSTMAKEFILE Makefile ext/extmk.rb)
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 76ce832a31..0e89d15dec 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -21,7 +21,7 @@ $(LIBRUBY_SO): $(RUBYDEF) $(LIBRUBY_SO).res.@OBJEXT@
$(LIBRUBY): $(LIBRUBY_SO)
%.res.@OBJEXT@: %.rc
- @WINDRES@ --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
+ @WINDRES@ --preprocessor '$(CC) -E -xc-header -DRC_INVOKE @MWIN32@' --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
$(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(LIBRUBY_SO).rc: rbconfig.rb
@@MINIRUBY@ $(srcdir)/win32/resource.rb \
diff --git a/dir.c b/dir.c
index 37cf332cb5..224965186d 100644
--- a/dir.c
+++ b/dir.c
@@ -26,10 +26,10 @@
#include <unistd.h>
#endif
-#if HAVE_DIRENT_H
+#if defined HAVE_DIRENT_H && !defined NT
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
-#elif HAVE_DIRECT_H
+#elif defined HAVE_DIRECT_H && !defined NT
# include <direct.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
@@ -44,7 +44,7 @@
# if HAVE_NDIR_H
# include <ndir.h>
# endif
-# if defined(NT) && defined(_MSC_VER)
+# if defined(NT)
# include "missing/dir.h"
# endif
#endif
@@ -61,6 +61,10 @@ char *strchr _((char*,char));
#include <ctype.h>
+#ifndef HAVE_LSTAT
+#define lstat rb_sys_stat
+#endif
+
#define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02
#define FNM_PERIOD 0x04
@@ -69,7 +73,7 @@ char *strchr _((char*,char));
#define FNM_NOMATCH 1
#define FNM_ERROR 2
-#define downcase(c) (nocase && isupper(c) ? tolower(c) : (c))
+#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
#if defined DOSISH
#define isdirsep(c) ((c) == '/' || (c) == '\\')
@@ -531,7 +535,11 @@ extract_path(p, pend)
len = pend - p;
alloc = ALLOC_N(char, len+1);
memcpy(alloc, p, len);
- if (len > 1 && pend[-1] == '/') {
+ if (len > 1 && pend[-1] == '/'
+#if defined DOSISH
+ && pend[-2] != ':'
+#endif
+ ) {
alloc[len-1] = 0;
}
else {
@@ -568,7 +576,7 @@ rb_glob_helper(path, flag, func, arg)
char *p, *m;
if (!has_magic(path, 0)) {
- if (stat(path, &st) == 0) {
+ if (rb_sys_stat(path, &st) == 0) {
(*func)(path, arg);
}
return;
@@ -601,12 +609,27 @@ rb_glob_helper(path, flag, func, arg)
rb_glob_helper(buf, flag, func, arg);
free(buf);
}
- dirp = opendir(dir);
- if (dirp == NULL) {
- free(base);
- break;
+ if (rb_sys_stat(dir, &st) < 0) {
+ free(base);
+ break;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ free(base);
+ break;
+ }
+ }
+ else {
+ free(base);
+ break;
}
+
+#if defined DOSISH
+#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3])))
+#else
#define BASE (*base && !(*base == '/' && !base[1]))
+#endif
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (recursive) {
@@ -614,7 +637,15 @@ rb_glob_helper(path, flag, func, arg)
continue;
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
sprintf(buf, "%s%s%s/**%s", base, (BASE)?"/":"", dp->d_name, m);
- rb_glob_helper(buf, flag, func, arg);
+ sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
+ if (lstat(buf, &st) < 0) {
+ continue;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ strcat(buf, "/**");
+ strcat(buf, m);
+ rb_glob_helper(buf, flag, func, arg);
+ }
free(buf);
continue;
}
@@ -679,7 +710,14 @@ push_pattern(path, ary)
char *path;
VALUE ary;
{
- rb_ary_push(ary, rb_tainted_str_new2(path));
+ VALUE str = rb_tainted_str_new2(path);
+
+ if (ary) {
+ rb_ary_push(ary, str);
+ }
+ else {
+ rb_yield(str);
+ }
}
static void
@@ -753,10 +791,12 @@ dir_s_glob(dir, str)
char buffer[MAXPATHLEN], *buf = buffer;
char *t;
int nest;
- VALUE ary;
+ VALUE ary = 0;
Check_SafeStr(str);
- ary = rb_ary_new();
+ if (!rb_block_given_p()) {
+ ary = rb_ary_new();
+ }
if (RSTRING(str)->len >= MAXPATHLEN)
buf = xmalloc(RSTRING(str)->len + 1);
@@ -783,14 +823,6 @@ dir_s_glob(dir, str)
}
if (buf != buffer)
free(buf);
- if (rb_block_given_p()) {
- long len = RARRAY(ary)->len;
- VALUE *ptr = RARRAY(ary)->ptr;
-
- while (len--) {
- rb_yield(*ptr++);
- }
- }
return ary;
}
diff --git a/djgpp/config.status b/djgpp/config.status
deleted file mode 100644
index 7a10754d1d..0000000000
--- a/djgpp/config.status
+++ /dev/null
@@ -1,77 +0,0 @@
-/^SHELL/s,/bin/sh,$(COMPSEC),
-s%@srcdir@%.%g
-s%@top_srcdir@%..%
-s%@CFLAGS@%-O2%g
-s%@CPPFLAGS@%%g
-s%@CXXFLAGS@%%g
-s%@LDFLAGS@%%g
-s%@LIBS@%-lm %g
-s%@exec_prefix@%${prefix}%g
-s%@prefix@%/usr/local%g
-s%@program_transform_name@%s,x,x,%g
-s%@bindir@%${exec_prefix}/bin%g
-s%@sbindir@%${exec_prefix}/sbin%g
-s%@libexecdir@%${exec_prefix}/libexec%g
-s%@datadir@%${prefix}/share%g
-s%@sysconfdir@%${prefix}/etc%g
-s%@sharedstatedir@%${prefix}/com%g
-s%@localstatedir@%${prefix}/var%g
-s%@libdir@%${exec_prefix}/lib%g
-s%@includedir@%${prefix}/include%g
-s%@oldincludedir@%/usr/include%g
-s%@infodir@%${prefix}/info%g
-s%@mandir@%${prefix}/man%g
-s%@host@%i386-pc-msdosdjgpp%g
-s%@host_alias@%i386-msdosdjgpp%g
-s%@host_cpu@%i386%g
-s%@host_vendor@%pc%g
-s%@host_os@%msdosdjgpp%g
-s%@CC@%gcc%g
-s%@CPP@%gcc -E%g
-s%@YACC@%bison -y%g
-s%@RANLIB@%ranlib%g
-s%@AR@%ar%g
-s%@INSTALL_PROGRAM@%${INSTALL}%g
-s%@INSTALL_DATA@%${INSTALL} -m 644%g
-s%@SET_MAKE@%%g
-s%@LIBOBJS@% crypt.o flock.o vsnprintf.o%g
-s%@ALLOCA@%%g
-s%@DEFAULT_KCODE@%%g
-s%@EXEEXT@%.exe%g
-s%@OBJEXT@%o%g
-s%@XLDFLAGS@%%g
-s%@DLDFLAGS@%%g
-s%@STATIC@%%g
-s%@CCDLFLAGS@%%g
-s%@LDSHARED@%ld%g
-s%@DLEXT@%o%g
-s%@STRIP@%strip%g
-s%@EXTSTATIC@%%g
-s%@binsuffix@%.exe%g
-s%@setup@%Setup.dj%g
-s%@LIBRUBY@%libruby.a%g
-s%@LIBRUBY_A@%libruby.a%g
-s%@LIBRUBYARG@%libruby.a%g
-s%@LIBRUBY_SO@%%g
-s%@SOLIBS@%%g
-s%@arch@%i386-msdosdjgpp%g
-;s%/bin/rm%rm%
-s%@DLDLIBS@%-lc%g
-s%@PREP@%%
-s%@RUBY_INSTALL_NAME@%ruby%g
-s%@RUBY_SO_NAME@%%g
-s%@arch@%i386-msdosdjgpp%g
-s%@sitedir@%${prefix}/lib/ruby/site_ruby%g
-s%@MINIRUBY@%./miniruby%
-s%@archlib@%/usr/local/lib/ruby/i386-msdosdjgpp%
-;s%|| true%%
-;/\/dev\/null/ {
-;s,/dev/null 2>&1, nul,
-;s,2> /dev/null,,
-;}
-;/^config.status/ {
-; N;N;N;N;N;d
-;}
-;s%y\.tab\.c%y_tab.c%
-/^,THIS_IS_DUMMY_PATTERN_/i\
-ac_given_srcdir=.
diff --git a/dln.c b/dln.c
index c843bee57b..ae3cbf2fb3 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)
{
@@ -1204,7 +1204,7 @@ aix_loaderror(const char *pathname)
if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
ERRBUF_APPEND(load_errtab[i].errstr);
}
- while (isdigit(*message[i])) message[i]++;
+ while (ISDIGIT(*message[i])) message[i]++;
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
@@ -1214,7 +1214,7 @@ aix_loaderror(const char *pathname)
}
#endif
-void
+void*
dln_load(file)
const char *file;
{
@@ -1234,23 +1234,21 @@ dln_load(file)
/* Load file */
if ((handle =
LoadLibraryExA(winfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) {
- printf("LoadLibraryExA: %s\n", winfile);
goto failed;
}
if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
- printf("GetProcAddress %s\n", buf);
- goto failed;
+ rb_loaderror("%s - %s\n%s", dln_strerror(), buf, 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];
@@ -1276,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 */
@@ -1306,11 +1305,11 @@ dln_load(file)
}
}
(*init_fct)();
- return;
+ return (void*)lib;
}
#endif /* hpux */
-#if defined(_AIX)
+#if defined(_AIX) && ! defined(_IA64)
#define DLN_DEFINED
{
void (*init_fct)();
@@ -1323,7 +1322,7 @@ dln_load(file)
aix_loaderror(file);
}
(*init_fct)();
- return;
+ return (void*)init_fct;
}
#endif /* _AIX */
@@ -1362,7 +1361,7 @@ dln_load(file)
init_fct = (void(*)())init_address;
(*init_fct)();
- return;
+ return (void*)init_address;
}
#else/* OPENSTEP dyld functions */
{
@@ -1392,7 +1391,7 @@ dln_load(file)
init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
(*init_fct)();
- return;
+ return (void*)init_fct;
}
#endif /* rld or dyld */
#endif
@@ -1440,7 +1439,7 @@ dln_load(file)
/* call module initialize function. */
(*init_fct)();
- return;
+ return (void*)img_id;
}
#endif /* __BEOS__*/
@@ -1488,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 7e3ab9fabb..c29d3bd8e9 100644
--- a/dln.h
+++ b/dln.h
@@ -29,5 +29,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 4527128030..6a008cdac5 100644
--- a/error.c
+++ b/error.c
@@ -695,6 +695,13 @@ rb_sys_fail(mesg)
}
void
+rb_load_fail(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 ae2ce62da9..b1f01f958d 100644
--- a/eval.c
+++ b/eval.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Jun 10 14:22:17 JST 1993
- Copyright (C) 1993-2000 Yukihiro Matsumoto
+ Copyright (C) 1993-2001 Yukihiro Matsumoto
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
Copyright (C) 2000 Information-technology Promotion Agency, Japan
@@ -22,6 +22,25 @@
#include "st.h"
#include "dln.h"
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+# ifndef atarist
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# endif /* atarist */
+#else
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif !defined(alloca)
+char *alloca();
+# endif
+#endif /* __GNUC__ */
+
+#ifdef _AIX
+#pragma alloca
+#endif
+
#ifdef HAVE_STDARG_PROTOTYPES
#include <stdarg.h>
#define va_init_list(a,b) va_start(a,b)
@@ -109,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)
@@ -483,9 +477,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));
@@ -527,14 +521,20 @@ static struct SCOPE *top_scope;
ruby_sourceline = _frame.line; \
ruby_frame = _frame.prev; }
+struct BLOCKTAG {
+ struct RBasic super;
+ long dst;
+ long flags;
+};
+
struct BLOCK {
NODE *var;
NODE *body;
VALUE self;
struct FRAME frame;
struct SCOPE *scope;
+ struct BLOCKTAG *tag;
VALUE klass;
- struct tag *tag;
int iter;
int vmode;
int flags;
@@ -545,12 +545,23 @@ struct BLOCK {
#define BLOCK_D_SCOPE 1
#define BLOCK_DYNAMIC 2
+#define BLOCK_ORPHAN 4
static struct BLOCK *ruby_block;
+static struct BLOCKTAG*
+new_blktag()
+{
+ NEWOBJ(blktag, struct BLOCKTAG);
+ OBJSETUP(blktag, 0, T_BLKTAG);
+ blktag->dst = 0;
+ blktag->flags = 0;
+ return blktag;
+}
+
#define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \
- _block.tag = prot_tag; \
+ _block.tag = new_blktag(); \
_block.var = v; \
_block.body = b; \
_block.self = self; \
@@ -566,19 +577,18 @@ static struct BLOCK *ruby_block;
_block.dyna_vars = ruby_dyna_vars; \
ruby_block = &_block;
+#define POP_BLOCK_TAG(tag) do { \
+ if ((tag)->flags & BLOCK_DYNAMIC) \
+ (tag)->flags |= BLOCK_ORPHAN; \
+ else \
+ rb_gc_force_recycle((VALUE)tag); \
+} while (0)
+
#define POP_BLOCK() \
+ POP_BLOCK_TAG(_block.tag); \
ruby_block = _block.prev; \
}
-#define PUSH_BLOCK2(b) { \
- struct BLOCK * volatile _old; \
- _old = ruby_block; \
- ruby_block = b;
-
-#define POP_BLOCK2() \
- ruby_block = _old; \
-}
-
struct RVarmap *ruby_dyna_vars;
#define PUSH_VARS() { \
struct RVarmap * volatile _old; \
@@ -586,6 +596,8 @@ struct RVarmap *ruby_dyna_vars;
ruby_dyna_vars = 0;
#define POP_VARS() \
+ if (_old && (ruby_scope->flag & SCOPE_DONT_RECYCLE)) \
+ FL_SET(_old, DVAR_DONT_RECYCLE); \
ruby_dyna_vars = _old; \
}
@@ -739,7 +751,6 @@ static struct tag *prot_tag;
_tag.frame = ruby_frame; \
_tag.iter = ruby_iter; \
_tag.prev = prot_tag; \
- _tag.retval = Qnil; \
_tag.scope = ruby_scope; \
_tag.tag = ptag; \
_tag.dst = 0; \
@@ -785,6 +796,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; \
@@ -1011,7 +1027,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();
@@ -1051,7 +1069,7 @@ static int
error_handle(ex)
int ex;
{
- switch (ex & 0xf) {
+ switch (ex & TAG_MASK) {
case 0:
ex = 0;
break;
@@ -1122,9 +1140,13 @@ void rb_exec_end_proc _((void));
void
ruby_finalize()
{
- rb_trap_exit();
- rb_exec_end_proc();
- rb_gc_call_finalizer_at_exit();
+ PUSH_TAG(PROT_NONE);
+ if (EXEC_TAG() == 0) {
+ rb_trap_exit();
+ rb_exec_end_proc();
+ rb_gc_call_finalizer_at_exit();
+ }
+ POP_TAG();
}
void
@@ -1255,6 +1277,34 @@ rb_eval_string_wrap(str, state)
return val;
}
+static void
+jump_tag_but_local_jump(state)
+ int state;
+{
+ switch (state) {
+ case 0:
+ break;
+ case TAG_RETURN:
+ rb_raise(rb_eLocalJumpError, "unexpected return");
+ break;
+ case TAG_NEXT:
+ rb_raise(rb_eLocalJumpError, "unexpected next");
+ break;
+ case TAG_BREAK:
+ rb_raise(rb_eLocalJumpError, "unexpected break");
+ break;
+ case TAG_REDO:
+ rb_raise(rb_eLocalJumpError, "unexpected redo");
+ break;
+ case TAG_RETRY:
+ rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
+ break;
+ default:
+ JUMP_TAG(state);
+ break;
+ }
+}
+
VALUE
rb_eval_cmd(cmd, arg)
VALUE cmd, arg;
@@ -1290,28 +1340,7 @@ rb_eval_cmd(cmd, arg)
POP_TAG();
POP_CLASS();
- switch (state) {
- case 0:
- break;
- case TAG_RETURN:
- rb_raise(rb_eLocalJumpError, "unexpected return");
- break;
- case TAG_NEXT:
- rb_raise(rb_eLocalJumpError, "unexpected next");
- break;
- case TAG_BREAK:
- rb_raise(rb_eLocalJumpError, "unexpected break");
- break;
- case TAG_REDO:
- rb_raise(rb_eLocalJumpError, "unexpected redo");
- break;
- case TAG_RETRY:
- rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
- break;
- default:
- JUMP_TAG(state);
- break;
- }
+ jump_tag_but_local_jump(state);
return val;
}
@@ -1373,17 +1402,18 @@ superclass(self, node)
#define ruby_cbase (RNODE(ruby_frame->cbase)->nd_clss)
static VALUE
-ev_const_defined(cref, id)
+ev_const_defined(cref, id, self)
NODE *cref;
ID id;
+ VALUE self;
{
NODE *cbase = cref;
- while (cbase && cbase->nd_clss != rb_cObject) {
+ while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
- if (klass->iv_tbl &&
- st_lookup(klass->iv_tbl, id, 0)) {
+ if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
+ if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, 0)) {
return Qtrue;
}
cbase = cbase->nd_next;
@@ -1392,16 +1422,18 @@ ev_const_defined(cref, id)
}
static VALUE
-ev_const_get(cref, id)
+ev_const_get(cref, id, self)
NODE *cref;
ID id;
+ VALUE self;
{
NODE *cbase = cref;
VALUE result;
- while (cbase && cbase->nd_clss != rb_cObject) {
+ while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
+ if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
return result;
}
@@ -1411,34 +1443,13 @@ ev_const_get(cref, id)
}
static VALUE
-ev_const_set(cref, id, val)
- NODE *cref;
- ID id;
- VALUE val;
-{
- NODE *cbase = cref;
-
- while (cbase && cbase->nd_clss != rb_cObject) {
- struct RClass *klass = RCLASS(cbase->nd_clss);
-
- if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, 0)) {
- st_insert(klass->iv_tbl, id, val);
- return val;
- }
- cbase = cbase->nd_next;
- }
- rb_const_assign(cbase->nd_clss, id, val);
- return val;
-}
-
-static VALUE
rb_mod_nesting()
{
NODE *cbase = RNODE(ruby_frame->cbase);
VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != rb_cObject) {
- rb_ary_push(ary, cbase->nd_clss);
+ while (cbase && cbase->nd_next) {
+ if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss);
cbase = cbase->nd_next;
}
return ary;
@@ -1450,12 +1461,12 @@ rb_mod_s_constants()
NODE *cbase = RNODE(ruby_frame->cbase);
VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != rb_cObject) {
- rb_mod_const_at(cbase->nd_clss, ary);
+ while (cbase) {
+ 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;
}
@@ -1576,22 +1587,32 @@ 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) \
(tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
ALLOC_N(VALUE,n),tmp__protect_tmp,n), \
(void*)tmp__protect_tmp->nd_head)
-# define TMP_PROTECT_END do {\
- if (tmp__protect_tmp) {\
- rb_gc_force_recycle((VALUE)tmp__protect_tmp);\
- alloca(0);\
- }\
-} while (0)
#else
# define TMP_PROTECT typedef int foobazzz
# define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
-# define TMP_PROTECT_END
#endif
#define SETUP_ARGS(anode) {\
@@ -1776,7 +1797,7 @@ is_defined(self, node, buf)
break;
case NODE_CONST:
- if (ev_const_defined(RNODE(ruby_frame->cbase), node->nd_vid)) {
+ if (ev_const_defined(RNODE(ruby_frame->cbase), node->nd_vid, self)) {
return "constant";
}
break;
@@ -2207,15 +2228,14 @@ rb_eval(self, n)
case NODE_FOR:
{
iter_retry:
- PUSH_BLOCK(node->nd_var, node->nd_body);
PUSH_TAG(PROT_FUNC);
+ PUSH_BLOCK(node->nd_var, node->nd_body);
state = EXEC_TAG();
if (state == 0) {
+ PUSH_ITER(ITER_PRE);
if (nd_type(node) == NODE_ITER) {
- PUSH_ITER(ITER_PRE);
result = rb_eval(self, node->nd_iter);
- POP_ITER();
}
else {
VALUE recv;
@@ -2223,13 +2243,14 @@ rb_eval(self, n)
int line = ruby_sourceline;
_block.flags &= ~BLOCK_D_SCOPE;
+ BEGIN_CALLARGS;
recv = rb_eval(self, node->nd_iter);
- PUSH_ITER(ITER_PRE);
+ END_CALLARGS;
ruby_sourcefile = file;
ruby_sourceline = line;
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
- POP_ITER();
}
+ POP_ITER();
}
else if (_block.tag->dst == state) {
state &= TAG_MASK;
@@ -2237,8 +2258,8 @@ rb_eval(self, n)
result = prot_tag->retval;
}
}
- POP_TAG();
POP_BLOCK();
+ POP_TAG();
switch (state) {
case 0:
break;
@@ -2460,7 +2481,6 @@ rb_eval(self, n)
END_CALLARGS;
result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
- TMP_PROTECT_END;
}
break;
@@ -2474,7 +2494,6 @@ rb_eval(self, n)
END_CALLARGS;
result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
- TMP_PROTECT_END;
}
break;
@@ -2507,13 +2526,13 @@ rb_eval(self, n)
ruby_frame->self, ruby_frame->last_func,
argc, argv, 3);
POP_ITER();
- TMP_PROTECT_END;
}
break;
case NODE_SCOPE:
{
struct FRAME frame;
+ NODE *saved_cref = 0;
frame = *ruby_frame;
frame.tmp = ruby_frame;
@@ -2521,7 +2540,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;
@@ -2539,6 +2562,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;
@@ -2569,7 +2594,6 @@ rb_eval(self, n)
argv[argc-1] = val;
val = rb_funcall2(recv, aset, argc, argv);
result = val;
- TMP_PROTECT_END;
}
break;
@@ -2688,7 +2712,7 @@ rb_eval(self, n)
break;
case NODE_CONST:
- result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid);
+ result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid, self);
break;
case NODE_CVAR: /* normal method */
@@ -2878,7 +2902,7 @@ rb_eval(self, n)
case NODE_DEFN:
if (node->nd_defn) {
- NODE *body;
+ NODE *body, *defn;
VALUE origin;
int noex;
@@ -2920,11 +2944,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)) {
@@ -2942,7 +2968,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");
@@ -2964,7 +2990,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));
@@ -3162,16 +3190,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;
@@ -3184,6 +3207,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) {
@@ -3194,6 +3219,7 @@ module_setup(module, n)
result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
+ POP_CREF();
POP_VARS();
POP_SCOPE();
POP_CLASS();
@@ -3203,7 +3229,6 @@ module_setup(module, n)
call_trace_func("end", file, line, 0,
ruby_frame->last_func, ruby_frame->last_class);
}
- TMP_PROTECT_END;
if (state) JUMP_TAG(state);
return result;
@@ -3467,7 +3492,7 @@ rb_yield_0(val, self, klass, acheck)
int state;
static unsigned serial = 1;
- if (!ruby_frame->iter || !ruby_block) {
+ if (!(rb_block_given_p() || rb_f_block_given_p()) || !ruby_block) {
rb_raise(rb_eLocalJumpError, "yield called out of block");
}
@@ -3489,7 +3514,7 @@ rb_yield_0(val, self, klass, acheck)
ruby_dyna_vars = block->dyna_vars;
}
ruby_class = klass?klass:block->klass;
- if (!self) self = block->self;
+ if (!klass) self = block->self;
node = block->body;
if (block->var) {
@@ -3526,7 +3551,7 @@ rb_yield_0(val, self, klass, acheck)
if (!node) {
result = Qnil;
}
- else if (nd_type(node) == NODE_CFUNC) {
+ 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);
}
@@ -3548,7 +3573,7 @@ rb_yield_0(val, self, klass, acheck)
case TAG_RETURN:
state |= (serial++ << 8);
state |= 0x10;
- block->tag->dst = state;
+ block->tag->dst = state;
break;
default:
break;
@@ -3558,26 +3583,56 @@ rb_yield_0(val, self, klass, acheck)
pop_state:
POP_ITER();
POP_CLASS();
- if ((block->flags & BLOCK_D_SCOPE) &&
+#if 0
+ if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
+ (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) ||
+ !(block->tag->flags & BLOCK_DYNAMIC) ||
+ !FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE))) {
+ struct RVarmap *vars, *tmp;
+
+ if (ruby_dyna_vars->id == 0) {
+ vars = ruby_dyna_vars->next;
+ rb_gc_force_recycle((VALUE)ruby_dyna_vars);
+ while (vars && vars->id != 0) {
+ tmp = vars->next;
+ rb_gc_force_recycle((VALUE)vars);
+ vars = tmp;
+ }
+ }
+ }
+#else
+ if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
!FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
struct RVarmap *vars = ruby_dyna_vars;
- while (vars && vars->id != 0) {
- struct RVarmap *tmp = vars->next;
- rb_gc_force_recycle((VALUE)vars);
- vars = tmp;
- }
- if (ruby_dyna_vars && ruby_dyna_vars->id == 0) {
+ if (ruby_dyna_vars->id == 0) {
+ vars = ruby_dyna_vars->next;
rb_gc_force_recycle((VALUE)ruby_dyna_vars);
+ while (vars && vars->id != 0) {
+ struct RVarmap *tmp = vars->next;
+ rb_gc_force_recycle((VALUE)vars);
+ vars = tmp;
+ }
}
}
+#endif
POP_VARS();
ruby_block = block;
ruby_frame = ruby_frame->prev;
if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
scope_dup(old_scope);
ruby_scope = old_scope;
- if (state) JUMP_TAG(state);
+ if (state) {
+ if (!block->tag) {
+ switch (state & TAG_MASK) {
+ case TAG_BREAK:
+ case TAG_RETURN:
+ jump_tag_but_local_jump(state & TAG_MASK);
+ break;
+ }
+ }
+ JUMP_TAG(state);
+ }
return result;
}
@@ -3744,7 +3799,7 @@ rb_iterate(it_proc, data1, bl_proc, data2)
{
int state;
volatile VALUE retval = Qnil;
- NODE *node = NEW_CFUNC(bl_proc, data2);
+ NODE *node = NEW_IFUNC(bl_proc, data2);
VALUE self = ruby_top_self;
iter_retry:
@@ -3809,7 +3864,6 @@ handle_rescue(self, node)
if (rb_obj_is_kind_of(ruby_errinfo, argv[0])) return 1;
argv++;
}
- TMP_PROTECT_END;
return 0;
}
@@ -4053,6 +4107,7 @@ static int STACK_LEVEL_MAX = 65535;
#ifdef __human68k__
extern int _stacksize;
# define STACK_LEVEL_MAX (_stacksize - 4096)
+#undef HAVE_GETRLIMIT
#else
#ifdef HAVE_GETRLIMIT
static int STACK_LEVEL_MAX = 655300;
@@ -4072,7 +4127,7 @@ stack_length(p)
alloca(0);
# define STACK_END (&stack_end)
#else
-# if defined(__GNUC__) && !defined(__alpha__) && !defined(__APPLE__)
+# if defined(__GNUC__) && defined(__i386__)
VALUE *stack_end = __builtin_frame_address(0);
# else
VALUE *stack_end = alloca(1);
@@ -4081,7 +4136,7 @@ stack_length(p)
#endif
if (p) *p = STACK_END;
-#ifdef sparc
+#ifdef __sparc__
return rb_gc_stack_start - STACK_END + 0x80;
#else
return (STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END
@@ -4266,14 +4321,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;
@@ -4366,6 +4426,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;
@@ -4379,27 +4440,24 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
case 0:
break;
- case TAG_NEXT:
- rb_raise(rb_eLocalJumpError, "unexpected next");
- break;
- case TAG_BREAK:
- rb_raise(rb_eLocalJumpError, "unexpected break");
- break;
- case TAG_REDO:
- rb_raise(rb_eLocalJumpError, "unexpected redo");
- break;
case TAG_RETRY:
- if (!rb_block_given_p()) {
- rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
+ if (rb_block_given_p()) {
+ break;
}
+ /* fall through */
default:
- JUMP_TAG(state);
+ jump_tag_but_local_jump(state);
+ break;
}
}
+ break;
+
+ default:
+ rb_bug("unknown node type %d", nd_type(body));
+ break;
}
POP_FRAME();
POP_ITER();
- TMP_PROTECT_END;
return result;
}
@@ -4416,6 +4474,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 object");
+ }
/* is it in the method cache? */
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
@@ -4701,7 +4762,6 @@ eval(self, src, scope, file, line)
}
Data_Get_Struct(scope, struct BLOCK, data);
-
/* PUSH BLOCK from data */
frame = data->frame;
frame.tmp = ruby_frame; /* gc protection */
@@ -4747,14 +4807,33 @@ eval(self, src, scope, file, line)
POP_CLASS();
ruby_in_eval--;
if (!NIL_P(scope)) {
+ int dont_recycle = ruby_scope->flag & SCOPE_DONT_RECYCLE;
+
ruby_frame = frame.tmp;
- if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
- scope_dup(old_scope);
ruby_scope = old_scope;
ruby_block = old_block;
ruby_dyna_vars = old_dyna_vars;
data->vmode = scope_vmode; /* write back visibility mode */
scope_vmode = old_vmode;
+ if (dont_recycle) {
+ struct tag *tag;
+ struct RVarmap *vars;
+
+ scope_dup(ruby_scope);
+ for (tag=prot_tag; tag; tag=tag->prev) {
+ scope_dup(tag->scope);
+ }
+ if (ruby_block) {
+ struct BLOCK *block = ruby_block;
+ while (block) {
+ block->tag->flags |= BLOCK_DYNAMIC;
+ block = block->prev;
+ }
+ }
+ for (vars = ruby_dyna_vars; vars; vars = vars->next) {
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
+ }
}
else {
ruby_frame->iter = iter;
@@ -4849,6 +4928,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);
@@ -4857,6 +4937,7 @@ exec_under(func, under, args)
val = (*func)(args);
}
POP_TAG();
+ POP_CREF();
SCOPE_SET(mode);
POP_FRAME();
POP_CLASS();
@@ -5014,6 +5095,7 @@ 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) {
@@ -5031,6 +5113,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;
@@ -5041,6 +5124,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;
@@ -5083,6 +5167,7 @@ rb_load(fname, wrap)
free(ruby_scope->local_tbl);
}
POP_TAG();
+ ruby_cref = saved_cref;
POP_SCOPE();
POP_FRAME();
POP_CLASS();
@@ -5092,8 +5177,7 @@ rb_load(fname, wrap)
ruby_nerrs = 0;
rb_exc_raise(ruby_errinfo);
}
- TMP_PROTECT_END;
- if (state) JUMP_TAG(state);
+ if (state) jump_tag_but_local_jump(state);
if (!NIL_P(ruby_errinfo)) /* exception during load */
rb_exc_raise(ruby_errinfo);
}
@@ -5126,6 +5210,7 @@ rb_f_load(argc, argv)
return Qtrue;
}
+VALUE ruby_dln_librefs;
static VALUE rb_features;
static st_table *loading_tbl;
@@ -5167,7 +5252,7 @@ rb_feature_p(feature, wait)
while (st_lookup(loading_tbl, f, &th)) {
if (th == curr_thread) {
- rb_raise(rb_eLoadError, "infinite load loop -- %s", f);
+ return Qtrue;
}
CHECK_INTS;
rb_thread_schedule();
@@ -5293,9 +5378,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);
@@ -5333,6 +5421,15 @@ rb_require(fname)
}
static void
+secure_visibility(self)
+ VALUE self;
+{
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't change method visibility");
+ }
+}
+
+static void
set_method_visibility(self, argc, argv, ex)
VALUE self;
int argc;
@@ -5341,6 +5438,7 @@ set_method_visibility(self, argc, argv, ex)
{
int i;
+ secure_visibility(self);
for (i=0; i<argc; i++) {
rb_export_method(self, rb_to_id(argv[i]), ex);
}
@@ -5352,6 +5450,7 @@ rb_mod_public(argc, argv, module)
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PUBLIC);
}
@@ -5367,6 +5466,7 @@ rb_mod_protected(argc, argv, module)
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PROTECTED);
}
@@ -5382,6 +5482,7 @@ rb_mod_private(argc, argv, module)
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PRIVATE);
}
@@ -5441,6 +5542,7 @@ rb_mod_modfunc(argc, argv, module)
rb_raise(rb_eTypeError, "module_function must be called for modules");
}
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_MODFUNC);
return module;
@@ -5849,6 +5951,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
@@ -5883,6 +5988,7 @@ blk_mark(data)
rb_gc_mark(data->self);
rb_gc_mark(data->dyna_vars);
rb_gc_mark(data->klass);
+ rb_gc_mark(data->tag);
data = data->prev;
}
}
@@ -5916,6 +6022,7 @@ blk_copy_prev(block)
struct BLOCK *block;
{
struct BLOCK *tmp;
+ struct RVarmap* vars;
while (block->prev) {
tmp = ALLOC_N(struct BLOCK, 1);
@@ -5925,6 +6032,13 @@ blk_copy_prev(block)
MEMCPY(tmp->frame.argv, block->prev->frame.argv, VALUE, tmp->frame.argc);
}
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;
}
@@ -5980,7 +6094,7 @@ static VALUE
rb_f_binding(self)
VALUE self;
{
- struct BLOCK *data;
+ struct BLOCK *data, *p;
struct RVarmap *vars;
VALUE bind;
@@ -6002,10 +6116,14 @@ rb_f_binding(self)
else {
data->prev = 0;
}
+ data->flags |= BLOCK_DYNAMIC;
+ data->tag->flags |= BLOCK_DYNAMIC;
- for (vars = data->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
+ for (p = data; p; p = p->prev) {
+ for (vars = p->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
}
scope_dup(data->scope);
POP_BLOCK();
@@ -6063,11 +6181,11 @@ proc_new(klass)
VALUE klass;
{
volatile VALUE proc;
- struct BLOCK *data;
+ struct BLOCK *data, *p;
struct RVarmap *vars;
if (!rb_block_given_p() && !rb_f_block_given_p()) {
- rb_raise(rb_eArgError, "tried to create Procedure-Object without a block");
+ rb_raise(rb_eArgError, "tried to create Proc object without a block");
}
proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
@@ -6075,7 +6193,6 @@ proc_new(klass)
data->orig_thread = rb_thread_current();
data->iter = data->prev?Qtrue:Qfalse;
- data->tag = 0; /* should not point into stack */
frame_dup(&data->frame);
if (data->iter) {
blk_copy_prev(data);
@@ -6084,10 +6201,13 @@ proc_new(klass)
data->prev = 0;
}
data->flags |= BLOCK_DYNAMIC;
+ data->tag->flags |= BLOCK_DYNAMIC;
- for (vars = data->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
+ for (p = data; p; p = p->prev) {
+ for (vars = p->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
}
scope_dup(data->scope);
proc_save_safe_level(proc);
@@ -6165,6 +6285,8 @@ proc_call(proc, args)
old_block = ruby_block;
_block = *data;
ruby_block = &_block;
+ ruby_block->frame.iter = ITER_NOT;
+
PUSH_ITER(ITER_CUR);
ruby_frame->iter = ITER_CUR;
@@ -6172,17 +6294,7 @@ proc_call(proc, args)
args = callargs(args);
}
- if (orphan) {/* orphan procedure */
- if (rb_block_given_p()) {
- ruby_block->frame.iter = ITER_CUR;
- }
- else {
- ruby_block->frame.iter = ITER_NOT;
- }
- }
-
PUSH_TAG(PROT_NONE);
- _block.tag = prot_tag;
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(proc);
@@ -6243,6 +6355,39 @@ proc_arity(proc)
}
static VALUE
+proc_eq(self, other)
+ VALUE 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) 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;
+ return Qfalse;
+}
+
+static VALUE
+proc_to_s(self, other)
+ VALUE self, other;
+{
+ struct BLOCK *data;
+ char *cname = rb_class2name(CLASS_OF(self));
+ VALUE str;
+
+ Data_Get_Struct(self, struct BLOCK, data);
+ str = rb_str_new(0, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:eos */
+ sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", cname, data->tag);
+ RSTRING(str)->len = strlen(RSTRING(str)->ptr);
+ if (OBJ_TAINTED(self)) OBJ_TAINT(str);
+
+ return str;
+}
+
+static VALUE
block_pass(self, node)
VALUE self;
NODE *node;
@@ -6278,7 +6423,6 @@ block_pass(self, node)
ruby_frame->iter = ITER_PRE;
PUSH_TAG(PROT_NONE);
- _block.tag = prot_tag;
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(block);
@@ -6300,25 +6444,33 @@ block_pass(self, node)
}
ptr = ptr->prev;
}
+ if (!ptr) {
+ state &= TAG_MASK;
+ }
}
}
ruby_block = old_block;
ruby_safe_level = safe;
- if (state) {
- switch (state) {/* escape from orphan procedure */
- case TAG_BREAK:
+ switch (state) {/* escape from orphan procedure */
+ case 0:
+ break;
+ case TAG_BREAK:
+ if (orphan) {
rb_raise(rb_eLocalJumpError, "break from proc-closure");
- break;
- case TAG_RETRY:
- rb_raise(rb_eLocalJumpError, "retry from proc-closure");
- break;
- case TAG_RETURN:
+ }
+ break;
+ case TAG_RETRY:
+ rb_raise(rb_eLocalJumpError, "retry from proc-closure");
+ break;
+ case TAG_RETURN:
+ if (orphan) {
rb_raise(rb_eLocalJumpError, "return from proc-closure");
- break;
}
+ default:
JUMP_TAG(state);
}
+
return result;
}
@@ -6445,8 +6597,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);
@@ -6611,7 +6763,7 @@ rb_mod_define_method(argc, argv, mod)
VALUE mod;
{
ID id;
- VALUE name, body;
+ VALUE body;
if (argc == 1) {
id = rb_to_id(argv[0]);
@@ -6626,17 +6778,20 @@ rb_mod_define_method(argc, argv, mod)
}
if (TYPE(body) != T_DATA) {
/* type error */
+ rb_raise(rb_eTypeError, "wrong argument type (expected Proc)");
}
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 {
/* type error */
+ rb_raise(rb_eTypeError, "wrong argument type (expected Proc)");
}
+ rb_clear_cache_by_id(id);
return body;
}
@@ -6652,6 +6807,8 @@ Init_Proc()
rb_define_method(rb_cProc, "call", proc_call, -2);
rb_define_method(rb_cProc, "arity", proc_arity, 0);
rb_define_method(rb_cProc, "[]", proc_call, -2);
+ rb_define_method(rb_cProc, "==", proc_eq, 1);
+ rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
rb_define_global_function("proc", rb_f_lambda, 0);
rb_define_global_function("lambda", rb_f_lambda, 0);
rb_define_global_function("binding", rb_f_binding, 0);
@@ -6725,6 +6882,7 @@ struct thread {
struct tag *tag;
VALUE klass;
VALUE wrapper;
+ NODE *cref;
int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
@@ -6758,7 +6916,9 @@ struct thread {
VALUE thread;
};
-#define THREAD_RAISED 0x200
+#define THREAD_RAISED 0x200 /* temporary flag */
+#define THREAD_TERMINATING 0x400 /* persistent flag */
+#define THREAD_FLAGS_MASK 0x400 /* mask for persistent flags */
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -6766,6 +6926,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()
@@ -6791,6 +6982,7 @@ thread_mark(th)
rb_gc_mark(th->klass);
rb_gc_mark(th->wrapper);
+ rb_gc_mark(th->cref);
rb_gc_mark(th->scope);
rb_gc_mark(th->dyna_vars);
@@ -6868,6 +7060,8 @@ rb_thread_check(data)
return (rb_thread_t)RDATA(data)->data;
}
+static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
+
static int th_raise_argc;
static VALUE th_raise_argv[2];
static char *th_raise_file;
@@ -6906,9 +7100,11 @@ 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 = scope_vmode | (rb_trap_immediate<<8);
+ th->flags &= THREAD_FLAGS_MASK;
+ th->flags |= (rb_trap_immediate<<8) | scope_vmode;
th->iter = ruby_iter;
th->tag = prot_tag;
th->tracing = tracing;
@@ -6995,6 +7191,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;
@@ -7055,13 +7252,8 @@ rb_thread_fd_close(fd)
FOREACH_THREAD(th) {
if ((th->wait_for & WAIT_FD) && fd == th->fd) {
- th_raise_argc = 1;
- th_raise_argv[0] = rb_exc_new2(rb_eIOError, "stream closed");
- th_raise_file = ruby_sourcefile;
- th_raise_line = ruby_sourceline;
- curr_thread = th;
- rb_thread_ready(th);
- rb_thread_restore_context(curr_thread, RESTORE_RAISE);
+ VALUE exc = rb_exc_new2(rb_eIOError, "stream closed");
+ rb_thread_raise(1, &exc, th);
}
}
END_FOREACH(th);
@@ -7339,8 +7531,11 @@ rb_thread_schedule()
curr_thread = next;
if (next->status == THREAD_TO_KILL) {
- /* execute ensure-clause if any */
- rb_thread_restore_context(next, RESTORE_FATAL);
+ if (!(next->flags & THREAD_TERMINATING)) {
+ next->flags |= THREAD_TERMINATING;
+ /* terminate; execute ensure-clause if any */
+ rb_thread_restore_context(next, RESTORE_FATAL);
+ }
}
rb_thread_restore_context(next, RESTORE_NORMAL);
}
@@ -7349,6 +7544,7 @@ void
rb_thread_wait_fd(fd)
int fd;
{
+ if (rb_thread_critical) return;
if (curr_thread == curr_thread->next) return;
if (curr_thread->status == THREAD_TO_KILL) return;
@@ -7362,9 +7558,9 @@ int
rb_thread_fd_writable(fd)
int fd;
{
+ if (rb_thread_critical) return Qtrue;
if (curr_thread == curr_thread->next) return Qtrue;
if (curr_thread->status == THREAD_TO_KILL) return Qtrue;
-
curr_thread->status = THREAD_STOPPED;
FD_ZERO(&curr_thread->readfds);
FD_ZERO(&curr_thread->writefds);
@@ -7382,7 +7578,8 @@ rb_thread_wait_for(time)
{
double date;
- if (curr_thread == curr_thread->next ||
+ if (rb_thread_critical ||
+ curr_thread == curr_thread->next ||
curr_thread->status == THREAD_TO_KILL) {
int n;
#ifndef linux
@@ -7394,7 +7591,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();
@@ -7447,7 +7651,8 @@ rb_thread_select(max, read, write, except, timeout)
(double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
}
- if (curr_thread == curr_thread->next ||
+ if (rb_thread_critical ||
+ curr_thread == curr_thread->next ||
curr_thread->status == THREAD_TO_KILL) {
#ifndef linux
struct timeval tv, *tvp = timeout;
@@ -7513,6 +7718,7 @@ rb_thread_join(thread)
rb_thread_t th = rb_thread_check(thread);
enum thread_status last_status = THREAD_RUNNABLE;
+ if (rb_thread_critical) rb_thread_deadlock();
if (!rb_thread_dead(th)) {
if (th == curr_thread)
rb_raise(rb_eThreadError, "thread tried to join itself");
@@ -7612,8 +7818,8 @@ rb_thread_kill(thread)
rb_thread_ready(th);
th->gid = 0;
th->status = THREAD_TO_KILL;
- rb_thread_schedule();
- return Qnil; /* not reached */
+ if (!rb_thread_critical) rb_thread_schedule();
+ return thread;
}
static VALUE
@@ -7780,6 +7986,7 @@ rb_thread_abort_exc_set(thread, val)
\
th->status = THREAD_RUNNABLE;\
th->result = 0;\
+ th->flags = 0;\
\
th->stk_ptr = 0;\
th->stk_len = 0;\
@@ -7795,6 +8002,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;\
@@ -7846,8 +8054,6 @@ catch_timer(sig)
int rb_thread_tick = THREAD_TICK;
#endif
-static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
-
#define SCOPE_SHARED FL_USER1
#if defined(HAVE_SETITIMER)
@@ -7886,6 +8092,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;
@@ -7903,7 +8110,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);
@@ -7930,6 +8141,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)) {
@@ -8018,8 +8239,6 @@ static VALUE
rb_thread_start(klass, args)
VALUE klass, args;
{
- rb_thread_t th;
-
if (!rb_block_given_p()) {
rb_raise(rb_eThreadError, "must be called with a block");
}
@@ -8366,6 +8585,14 @@ rb_callcc(self)
for (tag=prot_tag; tag; tag=tag->prev) {
scope_dup(tag->scope);
}
+ if (ruby_block) {
+ struct BLOCK *block = ruby_block;
+
+ while (block) {
+ block->tag->flags |= BLOCK_DYNAMIC;
+ block = block->prev;
+ }
+ }
th->thread = curr_thread->thread;
for (vars = th->dyna_vars; vars; vars = vars->next) {
diff --git a/ext/.cvsignore b/ext/.cvsignore
new file mode 100644
index 0000000000..d8b8a61d92
--- /dev/null
+++ b/ext/.cvsignore
@@ -0,0 +1 @@
+extmk.rb
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
index dcfdd7caab..0ee28f05ac 100644
--- a/ext/Win32API/Win32API.c
+++ b/ext/Win32API/Win32API.c
@@ -305,9 +305,3 @@ Init_Win32API()
rb_define_method(cWin32API, "call", Win32API_Call, -1);
rb_define_alias(cWin32API, "Call", "call");
}
-
-void
-Init_win32api()
-{
- Init_Win32API();
-}
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
index f8d78e1465..5e42f62558 100644
--- a/ext/Win32API/extconf.rb
+++ b/ext/Win32API/extconf.rb
@@ -1,6 +1,6 @@
case RUBY_PLATFORM
when /cygwin/,/mingw/
- $CFLAGS = "-fno-defer-pop"
+ $CFLAGS = "-fno-defer-pop -fno-omit-frame-pointer"
create_makefile("Win32API")
when /win32/
create_makefile("Win32API")
diff --git a/ext/curses/.cvsignore b/ext/curses/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/curses/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index db620654bd..4a8c46f483 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -16,16 +16,16 @@
# include <curses_colr/curses.h>
# else
# include <curses.h>
-# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxx)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__) ) && !defined(_maxx)
# define _maxx maxx
# endif
-# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxy)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_maxy)
# define _maxy maxy
# endif
-# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begx)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_begx)
# define _begx begx
# endif
-# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begy)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_begy)
# define _begy begy
# endif
# endif
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 5c6881164a..c16ab00f28 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -1,5 +1,9 @@
require 'mkmf'
+dir_config('curses')
+dir_config('ncurses')
+dir_config('termcap')
+
make=false
have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
if have_header("ncurses.h") and have_library("ncurses", "initscr")
diff --git a/ext/dbm/.cvsignore b/ext/dbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/dbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/etc/.cvsignore b/ext/etc/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/etc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index 92d11d0f6e..a369933a14 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -370,13 +370,15 @@ def create_makefile(target)
if $configure_args['--enable-shared'] or "@LIBRUBY@" != "@LIBRUBY_A@"
$libs = "@LIBRUBYARG@ " + $libs
- $LIBPATH |= [$topdir]
+ $LIBPATH.unshift $topdir
end
defflag = ''
if RUBY_PLATFORM =~ /cygwin|mingw/ and not $static
- open(target + '.def', 'wb') do |f|
- f.print "EXPORTS\n", "Init_", target, "\n"
+ if not File.exist? target + '.def'
+ open(target + '.def', 'wb') do |f|
+ f.print "EXPORTS\n", "Init_", target, "\n"
+ end
end
defflag = "--def=" + target + ".def"
end
@@ -492,19 +494,43 @@ EOS
mfile.puts "
.c.@OBJEXT@:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+.cc.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.cpp.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.cxx.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.C.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
"
elsif /nmake/i =~ $make
mfile.print "
{$(srcdir)}.c{}.@OBJEXT@:
$(CC) -I. -I$(<D) $(CFLAGS) $(CPPFLAGS) -c $(<:/=\\)
-
.c.@OBJEXT@:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+
+{$(srcdir)}.cc{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cc.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cpp{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cpp.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cxx{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cxx.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
"
else
mfile.print "
.c.@OBJEXT@:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
+
+.cc.@OBJEXT@ .cpp.@OBJEXT@ .cxx.@OBJEXT@ .C.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
"
end
diff --git a/ext/fcntl/.cvsignore b/ext/fcntl/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/fcntl/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/gdbm/.cvsignore b/ext/gdbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/gdbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/md5/.cvsignore b/ext/md5/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/md5/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/nkf/.cvsignore b/ext/nkf/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/nkf/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/pty/.cvsignore b/ext/pty/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/pty/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index 4df2011eb5..ba2b44c70b 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -1,10 +1,12 @@
require 'mkmf'
-have_header("sys/stropts.h")
-have_func("setresuid")
-$CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === RUBY_PLATFORM
-if have_func("openpty") or
- have_func("_getpty") or
- have_func("ioctl")
- create_makefile('pty')
+if /mswin32|mingw/ !~ RUBY_PLATFORM
+ have_header("sys/stropts.h")
+ have_func("setresuid")
+ $CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === RUBY_PLATFORM
+ if have_func("openpty") or
+ have_func("_getpty") or
+ have_func("ioctl")
+ create_makefile('pty')
+ end
end
diff --git a/ext/readline/.cvsignore b/ext/readline/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/readline/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index 7db62745f3..431ed213bb 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -9,5 +9,8 @@ have_library("ncurses", "tgetnum") or
if have_header("readline/readline.h") and
have_header("readline/history.h") and
have_library("readline", "readline")
+ if have_func("rl_filename_completion_function")
+ $CFLAGS += "-DREADLINE_42_OR_LATER"
+ end
create_makefile("readline")
end
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 02b29796af..b96f818194 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -15,6 +15,11 @@ static VALUE mReadline;
#define COMPLETION_PROC "completion_proc"
#define COMPLETION_CASE_FOLD "completion_case_fold"
+#ifndef READLINE_42_OR_LATER
+# define rl_filename_completion_function filename_completion_function
+# define rl_username_completion_function username_completion_function
+#endif
+
static int
readline_event()
{
@@ -322,7 +327,7 @@ filename_completion_proc_call(self, str)
int i;
matches = completion_matches(STR2CSTR(str),
- filename_completion_function);
+ rl_filename_completion_function);
if (matches) {
result = rb_ary_new();
for (i = 0; matches[i]; i++) {
@@ -349,7 +354,7 @@ username_completion_proc_call(self, str)
int i;
matches = completion_matches(STR2CSTR(str),
- username_completion_function);
+ rl_username_completion_function);
if (matches) {
result = rb_ary_new();
for (i = 0; matches[i]; i++) {
diff --git a/ext/sdbm/.cvsignore b/ext/sdbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/sdbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
index 7a31472930..92c96f26d0 100644
--- a/ext/sdbm/_sdbm.c
+++ b/ext/sdbm/_sdbm.c
@@ -103,11 +103,9 @@ static int duppair proto((char *, datum));
/*
* externals
*/
-#ifndef sun
-#ifndef MSDOS
+#if !defined(sun) && !defined(MSDOS) && !defined(_WIN32)
extern int errno;
#endif
-#endif
/*
* forward
diff --git a/ext/socket/.cvsignore b/ext/socket/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/socket/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/tcltklib/.cvsignore b/ext/tcltklib/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/tcltklib/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/tk/.cvsignore b/ext/tk/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/tk/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index a088d5c493..59d78da5d2 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -351,7 +351,7 @@ module TkComm
end
if context.kind_of? Array
context = context.collect{|ev|
- if context.kind_of? TkVirtualEvent
+ if ev.kind_of? TkVirtualEvent
ev.path
else
ev
@@ -397,8 +397,18 @@ module TkComm
end
}
else
- tk_split_list(tk_call(*what)).collect{|seq|
- seq[1..-2].gsub(/></,',')
+ tk_split_simplelist(tk_call(*what)).collect!{|seq|
+ l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ case (subseq)
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(subseq[1..-2])
+ when /^<[^<>]+>$/
+ subseq[1..-2]
+ else
+ subseq.split('')
+ end
+ }.flatten
+ (l.size == 1) ? l[0] : l
}
end
end
@@ -651,12 +661,76 @@ module TkCore
end
end
+module TkPackage
+ include TkCore
+ extend TkPackage
+
+ def forget(package)
+ tk_call('package', 'forget', package)
+ nil
+ end
+
+ def names
+ tk_split_simplelist(tk_call('package', 'names'))
+ end
+
+ def provide(package, version=nil)
+ if version
+ tk_call('package', 'provide', package, version)
+ nil
+ else
+ tk_call('package', 'provide', package)
+ end
+ end
+
+ def present(package, version=None)
+ tk_call('package', 'present', package, version)
+ end
+
+ def present_exact(package, version)
+ tk_call('package', 'present', '-exact', package, version)
+ end
+
+ def require(package, version=None)
+ tk_call('package', 'require', package, version)
+ end
+
+ def require_exact(package, version)
+ tk_call('package', 'require', '-exact', package, version)
+ end
+
+ def versions(package)
+ tk_split_simplelist(tk_call('package', 'versions', package))
+ end
+
+ def vcompare(version1, version2)
+ Integer(tk_call('package', 'vcompare', version1, version2))
+ end
+
+ def vsatisfies(version1, version2)
+ bool(tk_call('package', 'vsatisfies', version1, version2))
+ end
+end
+
module Tk
include TkCore
extend Tk
TCL_VERSION = INTERP._invoke("info", "tclversion")
TK_VERSION = INTERP._invoke("set", "tk_version")
+
+ TCL_PATCHLEVEL = INTERP._invoke("info", "patchlevel")
+ TK_PATCHLEVEL = INTERP._invoke("set", "tk_patchLevel")
+
+ TCL_LIBRARY = INTERP._invoke("set", "tcl_library")
+ TK_LIBRARY = INTERP._invoke("set", "tk_library")
+ LIBRARY = INTERP._invoke("info", "library")
+
+ TCL_PACKAGE_PATH = INTERP._invoke("set", "tcl_pkgPath")
+ AUTO_PATH = tk_split_simplelist(INTERP._invoke("set", "auto_path"))
+
+ PLATFORM = Hash[*tk_split_simplelist(INTERP._eval('array get tcl_platform'))]
+
JAPANIZED_TK = (INTERP._invoke("info", "commands", "kanji") != "")
def root
@@ -680,6 +754,10 @@ module Tk
tk_tcl2ruby(tk_call('focus', '-lastfor', win))
end
+ def Tk.strictMotif(bool=None)
+ bool(tk_call('set', 'tk_strictMotif', bool))
+ end
+
def Tk.show_kinsoku(mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
@@ -710,11 +788,11 @@ module Tk
end
end
- def toUTF8(str,encoding)
+ def Tk.toUTF8(str,encoding)
INTERP._toUTF8(str,encoding)
end
- def fromUTF8(str,encoding)
+ def Tk.fromUTF8(str,encoding)
INTERP._fromUTF8(str,encoding)
end
@@ -978,6 +1056,12 @@ class TkBindTag
BTagID_TBL[id]? BTagID_TBL[id]: id
end
+ ALL = self.new
+ ALL.instance_eval {
+ @id = 'all'
+ BTagID_TBL[@id] = self
+ }
+
def initialize(*args)
@id = Tk_BINDTAG_ID[0]
Tk_BINDTAG_ID[0] = Tk_BINDTAG_ID[0].succ
@@ -995,20 +1079,11 @@ class TkBindTag
end
class TkBindTagAll<TkBindTag
- BindTagALL = []
def TkBindTagAll.new(*args)
- if BindTagALL[0]
- BindTagALL[0].bind(*args) if args != []
- else
- new = super()
- BindTagALL[0] = new
- end
- BindTagALL[0]
- end
+ $stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n"
- def initialize(*args)
- @id = 'all'
- BindTagALL[0].bind(*args) if args != []
+ TkBindTag::ALL.bind(*args) if args != []
+ TkBindTag::ALL
end
end
@@ -1446,7 +1521,7 @@ module TkXIM
end
def useinputmethods(value=nil)
- TkXIM.useinputmethods(self, value=nil)
+ TkXIM.useinputmethods(self, value)
end
def imconfigure(window, slot, value=None)
@@ -2370,7 +2445,7 @@ class TkWindow<TkObject
def grid_propagate(mode=nil)
if mode
- tk_call('grid', 'propagate', epath, bool)
+ tk_call('grid', 'propagate', epath, mode)
else
bool(tk_call('grid', 'propagate', epath))
end
@@ -2507,7 +2582,7 @@ class TkWindow<TkObject
def bindtags(taglist=nil)
if taglist
- fail unless taglist.kind_of? Array
+ fail ArgumentError unless taglist.kind_of? Array
tk_call('bindtags', path, taglist)
else
list(tk_call('bindtags', path)).collect{|tag|
@@ -2708,8 +2783,16 @@ class TkScale<TkWindow
tk_call 'scale', path
end
- def get
- number(tk_send('get'))
+ def get(x=None, y=None)
+ number(tk_send('get', x, y))
+ end
+
+ def coords(val=None)
+ tk_split_list(tk_send('coords', val))
+ end
+
+ def identify(x, y)
+ tk_send('identify', x, y)
end
def set(val)
@@ -2744,8 +2827,8 @@ class TkScrollbar<TkWindow
number(tk_send('fraction', x, y))
end
- def identify(x=None, y=None)
- tk_send('fraction', x, y)
+ def identify(x, y)
+ tk_send('identify', x, y)
end
def get
@@ -2760,6 +2843,10 @@ class TkScrollbar<TkWindow
def set(first, last)
tk_send "set", first, last
end
+
+ def activate(element=None)
+ tk_send('activate', element)
+ end
end
class TkTextWin<TkWindow
@@ -3033,12 +3120,12 @@ class TkMenu<TkWindow
tk_send 'invoke', index
end
def insert(index, type, keys=nil)
- tk_send 'add', index, type, *hash_kv(keys)
+ tk_send 'insert', index, type, *hash_kv(keys)
end
def delete(index, last=None)
tk_send 'delete', index, last
end
- def popup(x, y, index=nil)
+ def popup(x, y, index=None)
tk_call 'tk_popup', path, x, y, index
end
def post(x, y)
@@ -3128,12 +3215,12 @@ class TkMenu<TkWindow
end
class TkMenuClone<TkMenu
- def initialize(parent, type=nil)
+ def initialize(parent, type=None)
unless parent.kind_of?(TkMenu)
fail ArgumentError, "parent must be TkMenu"
end
@parent = parent
- install_win(@parent)
+ install_win(@parent.path)
tk_call @parent.path, 'clone', @path, type
end
end
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
index ff06e9305a..9b323e9cbb 100644
--- a/ext/tk/lib/tkcanvas.rb
+++ b/ext/tk/lib/tkcanvas.rb
@@ -172,7 +172,7 @@ class TkCanvas<TkWindow
end
def bbox(tagOrId, *tags)
- list(tk_send('bbox', tagid(tagOrId), *tags))
+ list(tk_send('bbox', tagid(tagOrId), *tags.collect{|t| tagid(t)}))
end
def itembind(tag, context, cmd=Proc.new, args=nil)
@@ -207,7 +207,7 @@ class TkCanvas<TkWindow
end
def delete(*args)
- tk_send 'delete', *args
+ tk_send 'delete', *args.collect{|t| tagid(t)}
end
alias remove delete
@@ -375,7 +375,7 @@ class TkCanvas<TkWindow
end
def lower(tag, below=None)
- tk_send 'lower', tagid(tag), below
+ tk_send 'lower', tagid(tag), tagid(below)
end
def move(tag, x, y)
@@ -387,7 +387,7 @@ class TkCanvas<TkWindow
end
def raise(tag, above=None)
- tk_send 'raise', tagid(tag), above
+ tk_send 'raise', tagid(tag), tagid(above)
end
def scale(tag, x, y, xs, ys)
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
index 6b25be376b..7af3f26748 100644
--- a/ext/tk/lib/tkentry.rb
+++ b/ext/tk/lib/tkentry.rb
@@ -136,7 +136,7 @@ class TkEntry<TkLabel
tk_send 'selection', 'from', index
end
def selection_present()
- tk_send('selection', 'present') == 1
+ bool(tk_send('selection', 'present'))
end
def selection_range(s, e)
tk_send 'selection', 'range', s, e
diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb
index bb3d537bc4..51b5d82b60 100644
--- a/ext/tk/lib/tktext.rb
+++ b/ext/tk/lib/tktext.rb
@@ -189,6 +189,14 @@ class TkText<TkTextWin
}
end
+ def mark_next(index)
+ tagid2obj(tk_send('mark', 'next', index))
+ end
+
+ def mark_previous(index)
+ tagid2obj(tk_send('mark', 'previous', index))
+ end
+
def window_names
tk_send('window', 'names').collect{|elt|
tagid2obj(elt)
diff --git a/ext/tk/lib/tkvirtevent.rb b/ext/tk/lib/tkvirtevent.rb
index b31b99062f..d3721e362e 100644
--- a/ext/tk/lib/tkvirtevent.rb
+++ b/ext/tk/lib/tkvirtevent.rb
@@ -7,12 +7,27 @@ require 'tk'
class TkVirtualEvent<TkObject
extend Tk
- TkVirturlEventID = [0]
- TkVirturlEventTBL = {}
+ TkVirtualEventID = [0]
+ TkVirtualEventTBL = {}
+
+ class PreDefVirtEvent<self
+ def initialize(event)
+ @path = @id = event
+ TkVirtualEvent::TkVirtualEventTBL[@id] = self
+ end
+ end
def TkVirtualEvent.getobj(event)
- obj = TkVirturlEventTBL[event]
- obj ? obj : event
+ obj = TkVirtualEventTBL[event]
+ if obj
+ obj
+ else
+ if tk_call('event', 'info').index("<#{event}>")
+ PreDefVirtEvent.new(event)
+ else
+ fail ArgumentError, "undefined virtual event '<#{event}>'"
+ end
+ end
end
def TkVirtualEvent.info
@@ -22,8 +37,8 @@ class TkVirtualEvent<TkObject
end
def initialize(*sequences)
- @path = @id = format("<VirtEvent%.4d>", TkVirturlEventID[0])
- TkVirturlEventID[0] += 1
+ @path = @id = format("<VirtEvent%.4d>", TkVirtualEventID[0])
+ TkVirtualEventID[0] += 1
add(*sequences)
end
@@ -31,7 +46,7 @@ class TkVirtualEvent<TkObject
if sequences != []
tk_call('event', 'add', "<#{@id}>",
*(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
- TkVirturlEventTBL[@id] = self
+ TkVirtualEventTBL[@id] = self
end
self
end
@@ -39,11 +54,11 @@ class TkVirtualEvent<TkObject
def delete(*sequences)
if sequences == []
tk_call('event', 'delete', "<#{@id}>")
- TkVirturlEventTBL[@id] = nil
+ TkVirtualEventTBL[@id] = nil
else
tk_call('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
- TkVirturlEventTBL[@id] = nil if info == []
+ TkVirtualEventTBL[@id] = nil if info == []
end
self
end
diff --git a/file.c b/file.c
index 98098f9047..af18b88fba 100644
--- a/file.c
+++ b/file.c
@@ -67,7 +67,7 @@ char *strrchr _((const char*,const char));
#include <sys/stat.h>
#ifndef HAVE_LSTAT
-#define lstat stat
+#define lstat rb_sys_stat
#endif
VALUE rb_cFile;
@@ -113,7 +113,8 @@ rb_file_path(obj)
#endif
static VALUE
-stat_new(st)
+stat_new_0(klass, st)
+ VALUE klass;
struct stat *st;
{
struct stat *nst;
@@ -121,7 +122,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*
@@ -152,42 +160,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 UINT2NUM(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
@@ -195,7 +203,7 @@ rb_stat_rdev(self)
VALUE self;
{
#ifdef HAVE_ST_RDEV
- return INT2FIX((int)get_stat(self)->st_rdev);
+ return INT2NUM(get_stat(self)->st_rdev);
#else
return INT2FIX(0);
#endif
@@ -205,7 +213,7 @@ static VALUE
rb_stat_size(self)
VALUE self;
{
- return INT2FIX((int)get_stat(self)->st_size);
+ return INT2NUM(get_stat(self)->st_size);
}
static VALUE
@@ -213,7 +221,7 @@ rb_stat_blksize(self)
VALUE self;
{
#ifdef HAVE_ST_BLKSIZE
- return INT2FIX((int)get_stat(self)->st_blksize);
+ return UINT2NUM(get_stat(self)->st_blksize);
#else
return INT2FIX(0);
#endif
@@ -224,7 +232,7 @@ rb_stat_blocks(self)
VALUE self;
{
#ifdef HAVE_ST_BLOCKS
- return INT2FIX((int)get_stat(self)->st_blocks);
+ return UINT2NUM(get_stat(self)->st_blocks);
#else
return INT2FIX(0);
#endif
@@ -314,17 +322,17 @@ rb_stat(file, st)
#if defined DJGPP
if (RSTRING(file)->len == 0) return -1;
#endif
- return stat(RSTRING(file)->ptr, st);
+ return rb_sys_stat(RSTRING(file)->ptr, st);
}
static VALUE
-rb_file_s_stat(obj, fname)
- VALUE obj, fname;
+rb_file_s_stat(klass, fname)
+ VALUE klass, fname;
{
struct stat st;
Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) == -1) {
+ if (rb_sys_stat(RSTRING(fname)->ptr, &st) == -1) {
rb_sys_fail(RSTRING(fname)->ptr);
}
return stat_new(&st);
@@ -345,8 +353,8 @@ 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;
@@ -357,7 +365,7 @@ rb_file_s_lstat(obj, fname)
}
return stat_new(&st);
#else
- return rb_file_s_stat(obj, fname);
+ return rb_file_s_stat(klass, fname);
#endif
}
@@ -420,7 +428,7 @@ eaccess(path, mode)
struct stat st;
static int euid = -1;
- if (stat(path, &st) < 0) return (-1);
+ if (rb_sys_stat(path, &st) < 0) return (-1);
if (euid == -1)
euid = geteuid ();
@@ -722,7 +730,7 @@ check3rdbyte(file, mode)
{
struct stat st;
- if (stat(file, &st) < 0) return Qfalse;
+ if (rb_sys_stat(file, &st) < 0) return Qfalse;
if (st.st_mode & mode) return Qtrue;
return Qfalse;
}
@@ -757,15 +765,16 @@ test_sticky(obj, fname)
VALUE obj, fname;
{
#ifdef S_ISVTX
- return check3rdbyte(STR2CSTR(fname), S_ISVTX);
+ Check_SafeStr(fname);
+ return check3rdbyte(RSTRING(fname)->ptr, 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;
@@ -815,8 +824,8 @@ 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;
@@ -829,8 +838,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;
@@ -854,8 +863,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;
@@ -879,8 +888,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;
@@ -1097,8 +1106,8 @@ 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;
{
Check_SafeStr(from);
Check_SafeStr(to);
@@ -1109,8 +1118,8 @@ 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
Check_SafeStr(from);
@@ -1126,8 +1135,8 @@ 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];
@@ -1154,8 +1163,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;
@@ -1164,14 +1173,19 @@ 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;
{
Check_SafeStr(from);
Check_SafeStr(to);
- if (rename(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0)
+ if (rename(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) {
+#if defined __CYGWIN__
+ extern unsigned long __attribute__((stdcall)) GetLastError();
+ errno = GetLastError(); /* This is a Cygwin bug */
+#endif
rb_sys_fail(RSTRING(from)->ptr);
+ }
return INT2FIX(0);
}
@@ -1253,7 +1267,7 @@ rb_file_s_expand_path(argc, argv)
}
#if defined DOSISH
/* skip drive letter */
- else if (isalpha(s[0]) && s[1] == ':' && isdirsep(s[2])) {
+ else if (ISALPHA(s[0]) && s[1] == ':' && isdirsep(s[2])) {
while (*s && !isdirsep(*s)) {
*p++ = *s++;
}
@@ -1388,8 +1402,8 @@ 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;
@@ -1407,8 +1421,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));
}
@@ -1416,15 +1430,15 @@ 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);
Check_SafeStr(path);
@@ -1509,11 +1523,14 @@ rb_thread_flock(fd, op, fptr)
op |= LOCK_NB;
while (flock(fd, op) < 0) {
switch (errno) {
- case EINTR: /* can be happen? */
+ case EAGAIN:
+ case EACCES:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
+#endif
rb_thread_polling(); /* busy wait */
rb_io_check_closed(fptr);
- break;
+ continue;
default:
return -1;
}
@@ -1542,11 +1559,14 @@ rb_file_flock(obj, operation)
ret = flock(fileno(fptr->f), NUM2INT(operation));
TRAP_END;
if (ret < 0) {
-#ifdef EWOULDBLOCK
- if (errno == EWOULDBLOCK) {
- return Qfalse;
- }
+ switch (errno) {
+ case EAGAIN:
+ case EACCES:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
#endif
+ return Qfalse;
+ }
rb_sys_fail(fptr->path);
}
#endif
@@ -1716,6 +1736,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 (rb_sys_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;
{
@@ -2029,6 +2073,7 @@ path_check_1(path)
}
for (;;) {
if (stat(path, &st) == 0 && (st.st_mode & 002)) {
+ if (p) *p = '/';
return 0;
}
s = strrchr(path, '/');
@@ -2056,7 +2101,10 @@ rb_path_check(path)
if (pend) *pend = '\0';
safe = path_check_1(p);
- if (!safe) return 0;
+ if (!safe) {
+ if (pend) *pend = sep;
+ return 0;
+ }
if (!pend) break;
*pend = sep;
p = pend + 1;
@@ -2159,6 +2207,7 @@ define_filetest_function(name, func, argc)
rb_define_singleton_method(rb_cFile, name, func, argc);
}
+void
Init_File()
{
rb_mFileTest = rb_define_module("FileTest");
@@ -2254,6 +2303,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 a3578aef2f..a0e4ce6404 100644
--- a/gc.c
+++ b/gc.c
@@ -31,10 +31,23 @@ void rb_io_fptr_finalize _((struct OpenFile*));
#endif
#endif
-#ifdef C_ALLOCA
-#ifndef alloca
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+# ifndef atarist
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# endif /* atarist */
+#else
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif !defined(alloca)
void *alloca();
-#endif
+# endif
+#endif /* __GNUC__ */
+
+#ifdef _AIX
+#pragma alloca
#endif
static void run_final();
@@ -53,10 +66,17 @@ static void
mem_error(mesg)
char *mesg;
{
+ static int recurse = 0;
+
if (rb_safe_level() >= 4) {
rb_raise(rb_eNoMemError, mesg);
}
- rb_fatal(mesg);
+ if (recurse == 0) {
+ recurse++;
+ rb_fatal(mesg);
+ }
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ exit(1);
}
void *
@@ -308,10 +328,7 @@ rb_data_object_alloc(klass, datap, dmark, dfree)
extern st_table *rb_class_tbl;
VALUE *rb_gc_stack_start = 0;
-#if defined(__GNUC__) && __GNUC__ >= 2
-__inline__
-#endif
-static int
+static inline int
is_pointer_to_heap(ptr)
void *ptr;
{
@@ -606,6 +623,7 @@ rb_gc_mark(ptr)
case T_REGEXP:
case T_FLOAT:
case T_BIGNUM:
+ case T_BLKTAG:
break;
case T_MATCH:
@@ -712,7 +730,7 @@ gc_sweep()
during_gc = 0;
/* clear finalization list */
- if (need_call_final && final_list) {
+ if (final_list) {
RVALUE *tmp;
if (rb_prohibit_interrupt || ruby_in_compile) {
@@ -822,6 +840,7 @@ obj_free(obj)
case T_FLOAT:
case T_VARMAP:
+ case T_BLKTAG:
break;
case T_BIGNUM:
@@ -924,7 +943,7 @@ rb_gc()
alloca(0);
# define STACK_END (&stack_end)
#else
-# if defined(__GNUC__) && !defined(__alpha__) && !defined(__APPLE__)
+# if defined(__GNUC__) && defined(__i386__)
VALUE *stack_end = __builtin_frame_address(0);
# else
VALUE *stack_end = alloca(1);
@@ -1004,7 +1023,7 @@ Init_stack(addr)
#if defined(__human68k__)
extern void *_SEND;
rb_gc_stack_start = _SEND;
-#elif defined(__GNUC__) && !defined(__alpha__) && !defined(__APPLE__)
+#elif defined(__GNUC__) && defined(__i386__)
rb_gc_stack_start = __builtin_frame_address(2);
#else
VALUE start;
@@ -1044,6 +1063,7 @@ os_live_obj()
case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue;
default:
+ if (!p->as.basic.klass) continue;
rb_yield((VALUE)p);
n++;
}
@@ -1076,6 +1096,7 @@ os_obj_of(of)
case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue;
default:
+ if (!p->as.basic.klass) continue;
if (rb_obj_is_kind_of((VALUE)p, of)) {
rb_yield((VALUE)p);
n++;
@@ -1207,8 +1228,7 @@ run_final(obj)
args[0] = RARRAY(finalizers)->ptr[i];
rb_protect(run_single_final, (VALUE)args, &status);
}
- if (finalizer_table && st_lookup(finalizer_table, obj, &table)) {
- st_delete(finalizer_table, &obj, 0);
+ if (finalizer_table && st_delete(finalizer_table, &obj, &table)) {
for (i=0; i<RARRAY(table)->len; i++) {
args[0] = RARRAY(table)->ptr[i];
rb_protect(run_single_final, (VALUE)args, &status);
@@ -1223,14 +1243,25 @@ rb_gc_call_finalizer_at_exit()
int i;
/* run finalizers */
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i]; pend = p + HEAP_SLOTS;
- while (p < pend) {
- if (FL_TEST(p, FL_FINALIZE)) {
- p->as.free.flag = 0;
- run_final((VALUE)p);
+ if (need_call_final) {
+ if (deferred_final_list) {
+ p = deferred_final_list;
+ while (p) {
+ RVALUE *tmp = p;
+ p = p->as.free.next;
+ run_final((VALUE)tmp);
+ }
+ }
+ for (i = 0; i < heaps_used; i++) {
+ p = heaps[i]; pend = p + HEAP_SLOTS;
+ while (p < pend) {
+ if (FL_TEST(p, FL_FINALIZE)) {
+ FL_UNSET(p, FL_FINALIZE);
+ p->as.basic.klass = 0;
+ run_final((VALUE)p);
+ }
+ p++;
}
- p++;
}
}
/* run data object's finaliers */
@@ -1255,21 +1286,24 @@ static VALUE
id2ref(obj, id)
VALUE obj, id;
{
- unsigned long ptr;
+ unsigned long ptr, p0;
rb_secure(4);
- ptr = NUM2UINT(id);
- if (FIXNUM_P(ptr)) return (VALUE)ptr;
+ p0 = ptr = NUM2UINT(id);
if (ptr == Qtrue) return Qtrue;
if (ptr == Qfalse) return Qfalse;
if (ptr == Qnil) return Qnil;
+ if (FIXNUM_P(ptr)) return (VALUE)ptr;
+ if (SYMBOL_P(ptr) && rb_id2name(SYM2ID((VALUE)ptr)) != 0) {
+ return (VALUE)ptr;
+ }
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;
}
@@ -1303,37 +1337,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 2a5803c96e..eb6e73908c 100644
--- a/hash.c
+++ b/hash.c
@@ -79,16 +79,16 @@ static int
rb_any_hash(a)
VALUE a;
{
- unsigned int hval;
+ VALUE hval;
switch (TYPE(a)) {
case T_FIXNUM:
case T_SYMBOL:
- hval = a;
+ return (int)a;
break;
case T_STRING:
- hval = rb_str_hash(a);
+ return rb_str_hash(a);
break;
default:
@@ -98,9 +98,8 @@ rb_any_hash(a)
hval = rb_funcall(hval, '%', 1, INT2FIX(65439));
}
ENABLE_INTS;
- hval = FIX2LONG(hval);
+ return (int)FIX2LONG(hval);
}
- return hval;
}
static struct st_hash_type objhash = {
diff --git a/intern.h b/intern.h
index 7d8b0de130..147fb605df 100644
--- a/intern.h
+++ b/intern.h
@@ -41,6 +41,7 @@ VALUE rb_ary_sort _((VALUE));
VALUE rb_ary_sort_bang _((VALUE));
VALUE rb_ary_delete _((VALUE, VALUE));
VALUE rb_ary_delete_at _((VALUE, long));
+VALUE rb_ary_clear _((VALUE));
VALUE rb_ary_plus _((VALUE, VALUE));
VALUE rb_ary_concat _((VALUE, VALUE));
VALUE rb_ary_assoc _((VALUE, VALUE));
@@ -77,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));
@@ -107,7 +110,8 @@ 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_load_fail _((char*)) NORETURN;
+void rb_error_frozen _((char*)) NORETURN;
/* eval.c */
void rb_exc_raise _((VALUE)) NORETURN;
void rb_exc_fatal _((VALUE)) NORETURN;
diff --git a/io.c b/io.c
index a422cc0869..79118b073a 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>
@@ -1362,6 +1366,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
@@ -1385,6 +1393,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;
}
@@ -1902,12 +1915,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);
@@ -2156,7 +2175,9 @@ rb_f_p(argc, argv)
for (i=0; i<argc; i++) {
rb_p(argv[i]);
}
+ if (TYPE(rb_defout) == T_FILE) {
rb_io_flush(rb_defout);
+ }
return Qnil;
}
@@ -2238,8 +2259,6 @@ set_outfile(val, var, orig, stdf)
GetOpenFile(val, fptr);
rb_io_check_writable(fptr);
-
- GetOpenFile(*var, fptr);
f = GetWriteFile(fptr);
dup2(fileno(f), fileno(stdf));
@@ -2281,7 +2300,7 @@ prep_stdio(f, mode, klass)
return (VALUE)io;
}
-static VALUE
+static void
prep_path(io, path)
VALUE io;
char *path;
@@ -2771,6 +2790,7 @@ rb_f_select(argc, argv, obj)
return res; /* returns an empty array on interrupt */
}
+#if !defined(MSDOS) && !defined(__human68k__)
static int
io_cntl(fd,cmd,narg,io_p)
int fd, cmd, io_p;
@@ -2796,6 +2816,7 @@ io_cntl(fd,cmd,narg,io_p)
#endif
return retval;
}
+#endif
static VALUE
rb_io_ctl(io, req, arg, io_p)
@@ -3095,8 +3116,9 @@ argf_tell()
}
static VALUE
-argf_seek(self, offset, ptrname)
- VALUE self, offset, ptrname;
+argf_seek(argc, argv)
+ int argc;
+ VALUE *argv;
{
if (!next_argv()) {
rb_raise(rb_eArgError, "no stream to seek");
@@ -3105,7 +3127,7 @@ argf_seek(self, offset, ptrname)
if (TYPE(current_file) != T_FILE) {
return argf_forward();
}
- return rb_io_seek(current_file, offset, ptrname);
+ return rb_io_seek(argc, argv, current_file);
}
static VALUE
@@ -3321,11 +3343,12 @@ 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);
+ ruby_inplace_mode = strdup(STR2CSTR(val));
}
void
@@ -3474,7 +3497,7 @@ Init_IO()
rb_define_singleton_method(argf, "getc", argf_getc, 0);
rb_define_singleton_method(argf, "readchar", argf_readchar, 0);
rb_define_singleton_method(argf, "tell", argf_tell, 0);
- rb_define_singleton_method(argf, "seek", argf_seek, 2);
+ rb_define_singleton_method(argf, "seek", argf_seek, -1);
rb_define_singleton_method(argf, "rewind", argf_rewind, 0);
rb_define_singleton_method(argf, "pos", argf_tell, 0);
rb_define_singleton_method(argf, "pos=", argf_set_pos, 1);
diff --git a/lib/Env.rb b/lib/Env.rb
index 7101b84c91..452a28659e 100644
--- a/lib/Env.rb
+++ b/lib/Env.rb
@@ -6,19 +6,7 @@
# $USER = "matz"
# p ENV["USER"]
-for k,v in ENV
- next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
- eval <<EOS
- $#{k} = %q!#{v}!
- trace_var "$#{k}", proc{|v|
- ENV[%q!#{k}!] = v;
- $#{k} = %q!#{v}!
- if v == nil
- untrace_var "$#{k}"
- end
- }
-EOS
-end
+require 'importenv'
if __FILE__ == $0
p $TERM
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 7d27cecd67..fcf8c006e5 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -4,7 +4,7 @@
cgi.rb - cgi support library
-Version 2.1.2
+Version 2.1.4
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
@@ -185,12 +185,13 @@ class CGI
CR = "\015"
LF = "\012"
EOL = CR + LF
- VERSION = "2.1.2"
- RELEASE_DATE = "2000-12-25"
- VERSION_CODE = 212
- RELEASE_CODE = 20001225
+ VERSION = '2.1.3'
+ RELEASE_DATE = '2001-03-18'
+ VERSION_CODE = 214
+ RELEASE_CODE = 20010318
+ REVISION = '$Id$'
- NEEDS_BINMODE = true if /WIN/ni === RUBY_PLATFORM
+ NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM)
PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
HTTP_STATUS = {
@@ -350,11 +351,11 @@ class CGI
=begin
=== MAKE RFC1123 DATE STRING
CGI::rfc1123_date(Time.now)
- # Sat, 1 Jan 2000 00:00:00 GMT
+ # Sat, 01 Jan 2000 00:00:00 GMT
=end
def CGI::rfc1123_date(time)
t = time.clone.gmtime
- return format("%s, %d %s %d %.2d:%.2d:%.2d GMT",
+ return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
t.hour, t.min, t.sec)
end
@@ -423,7 +424,8 @@ status:
options["type"].concat( options.delete("charset") )
end
- if options.delete("nph") or (/IIS/n === env_table['SERVER_SOFTWARE'])
+ options.delete("nph") if defined?(MOD_RUBY)
+ if options.delete("nph") or /IIS/n.match(env_table['SERVER_SOFTWARE'])
buf.concat( (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " )
buf.concat( (HTTP_STATUS[options["status"]] or
options["status"] or
@@ -446,7 +448,9 @@ status:
end
if options.has_key?("status")
- buf.concat("Status: " + options.delete("status") + EOL)
+ status = (HTTP_STATUS[options["status"]] or options["status"])
+ buf.concat("Status: " + status + EOL)
+ options.delete("status")
end
if options.has_key?("server")
@@ -496,8 +500,21 @@ status:
}
if defined?(MOD_RUBY)
- buf.scan(/([^:]+): (.+)#{EOL}/n){
- Apache::request[$1] = $2
+ table = Apache::request.headers_out
+ buf.scan(/([^:]+): (.+)#{EOL}/n){ |name, value|
+ $stderr.printf("name:%s value:%s\n", name, value) if $DEBUG
+ case name
+ when 'Set-Cookie'
+ table.add($1, $2)
+ when /^status$/ni
+ Apache::request.status_line = value
+ when /^content-type$/ni
+ Apache::request.content_type = value
+ when /^content-encoding$/ni
+ Apache::request.content_encoding = value
+ else
+ Apache::request.headers_out[name] = value
+ end
}
Apache::request.send_http_header
''
@@ -793,9 +810,9 @@ convert string charset, and set language to "ja".
body = Tempfile.new("CGI")
body.binmode
- until head and (/#{boundary}(?:#{EOL}|--)/n === buf)
+ until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
- if (not head) and (/#{EOL}#{EOL}/n === buf)
+ if (not head) and /#{EOL}#{EOL}/n.match(buf)
buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
head = $1.dup
""
@@ -834,14 +851,14 @@ convert string charset, and set language to "ja".
end
END
- /Content-Disposition:.* filename="?([^\";]*)"?/ni === head
+ /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
eval <<-END
def body.original_filename
#{
filename = ($1 or "").dup
- if (/Mac/ni === env_table['HTTP_USER_AGENT']) and
- (/Mozilla/ni === env_table['HTTP_USER_AGENT']) and
- (not /MSIE/ni === env_table['HTTP_USER_AGENT'])
+ if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
+ /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
+ (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
CGI::unescape(filename)
else
filename
@@ -850,14 +867,14 @@ convert string charset, and set language to "ja".
end
END
- /Content-Type: (.*)/ni === head
+ /Content-Type: (.*)/ni.match(head)
eval <<-END
def body.content_type
#{($1 or "").dump.untaint}.taint
end
END
- /Content-Disposition:.* name="?([^\";]*)"?/ni === head
+ /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
name = $1.dup
if params.has_key?(name)
@@ -889,7 +906,7 @@ convert string charset, and set language to "ja".
words = Shellwords.shellwords(string)
- if words.find{|x| /=/n === x }
+ if words.find{|x| /=/n.match(x) }
words.join('&')
else
words.join('+')
@@ -899,8 +916,7 @@ convert string charset, and set language to "ja".
def initialize_query()
if ("POST" == env_table['REQUEST_METHOD']) and
- (%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n ===
- env_table['CONTENT_TYPE'])
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE'])
boundary = $1.dup
@params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
else
@@ -975,8 +991,8 @@ convert string charset, and set language to "ja".
cgi = CGI.new("html3") # add HTML generation methods
cgi.element
cgi.element{ "string" }
- cgi.element({ "ATTRILUTE1" => "value1", "ATTRIBUTE2" => "value2" })
- cgi.element({ "ATTRILUTE1" => "value1", "ATTRIBUTE2" => "value2" }){ "string" }
+ cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" })
+ cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" }){ "string" }
# add HTML generation methods
CGI.new("html3") # html3.2
@@ -1235,8 +1251,10 @@ convert string charset, and set language to "ja".
form("get", "url"){ "string" }
# <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- form({"METHOD" => "post", ENCTYPE => "enctype"}){ "string" }
+ form({"METHOD" => "post", "ENCTYPE" => "enctype"}){ "string" }
# <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
+
+The hash keys are case sensitive. Ask the samples.
=end
def form(method = "post", action = nil, enctype = "application/x-www-form-urlencoded")
attributes = if method.kind_of?(String)
@@ -1244,7 +1262,7 @@ convert string charset, and set language to "ja".
"ENCTYPE" => enctype }
else
unless method.has_key?("METHOD")
- method["METHOD"] = method
+ method["METHOD"] = "post"
end
unless method.has_key?("ENCTYPE")
method["ENCTYPE"] = enctype
@@ -1935,161 +1953,7 @@ end
== HISTORY
-* Mon Dec 25 05:02:27 JST 2000 - wakou
- * version 2.1.2
- * bug fix: CGI::escapeElement(): didn't accept empty element.
- * bug fix: CGI::unescapeElement(): ditto.
- * bug fix: CGI::unescapeHTML(): support for "&copy;, &hearts;, ..."
- thanks to YANAGAWA Kazuhisa <kjana@os.xaxon.ne.jp>
- * bug fix: CGI::unescapeHTML(): support for "&#09;"
- thanks to OHSHIMA Ryunosuke <ryu@jaist.ac.jp>
- * Regexp::last_match[0] --> $&
- * Regexp::last_match[1] --> $1
- * Regexp::last_match[2] --> $2
- * add: CGI#param(): test implement. undocumented.
-
-* Mon Dec 11 00:16:51 JST 2000 - wakou
- * version 2.1.1
- * support -T1 on ruby 1.6.2
- * body.original_filename: eval(str.dump.untaint).taint
- * body.content_type: eval(str.dump.untaint).taint
- * $& --> Regexp::last_match[0]
- * $1 --> Regexp::last_match[1]
- * $2 --> Regexp::last_match[2]
-
-* Thu Oct 12 01:16:59 JST 2000 - wakou
- * version 2.1.0
- * bug fix: CGI::html(): PRETTY option didn't work.
- thanks to akira yamada <akira@ruby-lang.org>
-
-* Wed Sep 13 06:09:26 JST 2000 - wakou
- * version 2.0.1
- * bug fix: CGI::header(): output status header.
- thanks to Yasuhiro Fukuma <yasuf@bsdclub.org>
-
-* Tue Sep 12 06:56:51 JST 2000 - wakou
- * version 2.0.0
- * require ruby1.5.4 or later. (ruby1.4 doesn't have block_given? method.)
- * improvement: CGI::escape(), CGI::unescape().
- thanks to WATANABE Hirofumi <eban@os.rim.or.jp>
- * bug fix: CGI::escapeElement().
- * improvement: CGI::unescapeHTML().
- thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
-
-* 2000/08/09 04:32:22 - matz
- * improvement: CGI::pretty()
-
-* 2000/06/23 07:01:34 - matz
- * change: iterator? --> block_given?
-
-* Sun Jun 18 23:31:44 JST 2000 - wakou
- * version 1.7.0
- * change: version syntax. old: x.yz, now: x.y.z
-
-* 2000/06/13 15:49:27 - wakou
- * version 1.61
- * read_multipart(): if no content body then raise EOFError.
-
-* 2000/06/03 18:16:17 - wakou
- * version 1.60
- * improve: CGI::pretty()
-
-* 2000/05/30 19:04:08 - wakou
- * version 1.50
- * CGI#out(): if "HEAD" == REQUEST_METHOD then output only HTTP header.
-
-* 2000/05/24 06:58:51 - wakou
- * version 1.40
- * typo: CGI::Cookie::new()
- * bug fix: CGI::escape(): bad: " " --> "%2B"; true: " " --> "+";
- thanks to Ryunosuke Ohshima <ryu@jaist.ac.jp>
-
-* 2000/05/08 21:51:30 - wakou
- * version 1.31
- * improvement of time forming new CGI object accompanied with HTML generation methods.
-
-* 2000/05/07 21:51:14 - wakou
- * version 1.30
- * require English.rb
- * improvement of load time.
-
-* 2000/05/02 21:44:12 - wakou
- * version 1.21
- * support for ruby 1.5.3 (2000-05-01) (Array#filter --> Array#collect!)
-
-* 2000/04/03 18:31:42 - wakou
- * version 1.20
- * bug fix: CGI#image_button() can't get Hash option.
- thanks to Takashi Ikeda <ikeda@auc.co.jp>
- * CGI::unescapeHTML(): simple support for "&#12345;"
- * CGI::Cookie::new(): simple support for IE
- * CGI::escape(): ' ' replaced by '+'
-
-* 1999/12/06 20:16:34 - wakou
- * version 1.10
- * can make many CGI objects.
- * if use mod_ruby, then require ruby1.4.3 or later.
-
-* 1999/11/29 21:35:58 - wakou
- * version 1.01
- * support for ruby 1.5.0 (1999-11-20)
-
-* 1999/09/13 23:00:58 - wakou
- * version 1.00
- * COUTION! name change. CGI.rb --> cgi.rb
- * CGI#auth_type, CGI#content_length, CGI#content_type, ...
- if not ENV included it, then return nil.
- * CGI#content_length and CGI#server_port return Integer.
- * if not CGI#params.include?('name'), then CGI#params['name'] return [].
- * if not CGI#cookies.include?('name'), then CGI#cookies['name'] return [].
-
-* 1999/08/05 18:04:59 - wakou
- * version 0.41
- * typo. thanks to MJ Ray <markj@altern.org>
- HTTP_STATUS["NOT_INPLEMENTED"] --> HTTP_STATUS["NOT_IMPLEMENTED"]
-
-* 1999/07/20 20:44:31 - wakou
- * version 0.40
- * COUTION! incompatible change.
- sorry, but probably this change is last big incompatible change.
- * CGI::print --> CGI#out
- cgi = CGI.new
- cgi.out{"string"} # old: CGI::print{"string"}
- * CGI::cookie --> CGI::Cookie::new
- cookie1 = CGI::Cookie::new # old: CGI::cookie
- * CGI::header --> CGI#header
-
-* 1999/06/29 06:50:21 - wakou
- * version 0.30
- * COUTION! incompatible change.
- query = CGI.new
- cookies = query.cookies # old: query.cookie
- values = query.cookies[name] # old: query.cookie[name]
-
-* 1999/06/21 21:05:57 - wakou
- * version 0.24
- * CGI::Cookie::parse() return { name => CGI::Cookie object } pairs.
-
-* 1999/06/20 23:29:12 - wakou
- * version 0.23
- * modified a bit to clear module separation.
-
-* Mon Jun 14 17:49:32 JST 1999 - matz
- * version 0.22
- * Cookies are now CGI::Cookie objects.
- * Cookie modeled after CGI::Cookie.pm.
-
-* Fri Jun 11 11:19:11 JST 1999 - matz
- * version 0.21
- * modified a bit to clear module separation.
-
-* 1999/06/03 06:48:15 - wakou
- * version 0.20
- * support for multipart form.
-
-* 1999/05/24 07:05:41 - wakou
- * version 0.10
- * first release.
-
-$Date$
+delete. see cvs log.
+
+
=end
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index 48f3496939..1120fb50f0 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,23 +16,22 @@ 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
def initialize(request, option={})
session_key = option['session_key'] || '_session_id'
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 +43,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,7 +54,9 @@ class CGI
@output_cookies = [
Cookie::new("name" => session_key,
"value" => id,
- "path" => if ENV["SCRIPT_NAME"] then
+ "path" => if option['session_path'] then
+ option['session_path']
+ elsif ENV["SCRIPT_NAME"] then
File::dirname(ENV["SCRIPT_NAME"])
else
""
@@ -132,6 +134,7 @@ class CGI
end
def close
+ return if @f.closed?
update
@f.close
end
diff --git a/lib/date.rb b/lib/date.rb
index 58179a7153..3422121298 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -1,5 +1,5 @@
-# date.rb: Written by Tadayoshi Funaba 1998-2000
-# $Id: date.rb,v 1.22 2000-07-16 10:23:40+09 tadf Exp $
+# date2.rb: Written by Tadayoshi Funaba 1998-2001
+# $Id: date2.rb,v 1.23 2001-01-18 12:09:47+09 tadf Exp $
class Date
@@ -128,16 +128,15 @@ class Date
end
if d < 0
ny, nm = clfloor(y * 12 + m, 12)
- nm, = clfloor(m + 1, 1)
- la = nil
- 31.downto 1 do |z|
- break if la = exist3?(y, m, z, sg)
- end
- ns = ns?(la, sg)
- d = jd_to_civil(civil_to_jd(ny, nm, 1, ns) + d, ns)[-1]
+ nm, = clfloor(nm + 1, 1)
+ jd = civil_to_jd(ny, nm, d + 1, sg)
+ ns = ns?(jd, sg)
+ return unless [y, m] == jd_to_civil(jd, sg)[0..1]
+ return unless [ny, nm, 1] == jd_to_civil(jd - d, ns)
+ else
+ jd = civil_to_jd(y, m, d, sg)
+ return unless [y, m, d] == jd_to_civil(jd, sg)
end
- jd = civil_to_jd(y, m, d, sg)
- return unless [y, m, d] == jd_to_civil(jd, sg)
jd
end
@@ -154,16 +153,15 @@ class Date
def exist2? (y, d, sg=ITALY)
if d < 0
- ny = y + 1
- la = nil
- 366.downto 1 do |z|
- break if la = exist2?(y, z, sg)
- end
- ns = ns?(la, sg)
- d = jd_to_ordinal(ordinal_to_jd(ny, 1, ns) + d, ns)[-1]
+ ny, = clfloor(y + 1, 1)
+ jd = ordinal_to_jd(ny, d + 1, sg)
+ ns = ns?(jd, sg)
+ return unless [y] == jd_to_ordinal(jd, sg)[0..0]
+ return unless [ny, 1] == jd_to_ordinal(jd - d, ns)
+ else
+ jd = ordinal_to_jd(y, d, sg)
+ return unless [y, d] == jd_to_ordinal(jd, sg)
end
- jd = ordinal_to_jd(y, d, sg)
- return unless [y, d] == jd_to_ordinal(jd, sg)
jd
end
diff --git a/lib/debug.rb b/lib/debug.rb
index b6968cc338..220b68d2c9 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -91,22 +91,70 @@ class DEBUGGER__
@finish_pos = 0
@trace = false
@catch = "StandardError"
+ @suspend_next = false
end
def stop_next(n=1)
@stop_next = n
end
+ def set_suspend
+ @suspend_next = true
+ end
+
+ def clear_suspend
+ @suspend_next = false
+ end
+
+ def suspend_all
+ DEBUGGER__.suspend
+ end
+
+ def resume_all
+ DEBUGGER__.resume
+ end
+
+ def check_suspend
+ while (Thread.critical = true; @suspend_next)
+ DEBUGGER__.waiting.push Thread.current
+ @suspend_next = false
+ Thread.stop
+ end
+ Thread.critical = false
+ end
+
+ def trace?
+ @trace
+ end
+
+ def set_trace(arg)
+ @trace = arg
+ end
+
def stdout
DEBUGGER__.stdout
end
+
def break_points
DEBUGGER__.break_points
end
+
def display
DEBUGGER__.display
end
+ def context(th)
+ DEBUGGER__.context(th)
+ end
+
+ def set_trace_all(arg)
+ DEBUGGER__.set_trace(arg)
+ end
+
+ def set_last_thread(th)
+ DEBUGGER__.set_last_thread(th)
+ end
+
def debug_eval(str, binding)
begin
val = eval(str, binding)
@@ -205,7 +253,7 @@ class DEBUGGER__
def debug_command(file, line, id, binding)
MUTEX.lock
- DEBUGGER__.set_last_thread(Thread.current)
+ set_last_thread(Thread.current)
frame_pos = 0
binding_file = file
binding_line = line
@@ -218,7 +266,8 @@ class DEBUGGER__
end
@frames[0] = [binding, file, line, id]
display_expressions(binding)
- while input = readline("(rdb:%d) "%thnum(), true)
+ prompt = true
+ while prompt and input = readline("(rdb:%d) "%thnum(), true)
catch(:debug_error) do
if input == ""
input = DEBUG_LAST_CMD[0]
@@ -228,18 +277,24 @@ class DEBUGGER__
end
case input
- when /^\s*tr(?:ace)?(?:\s+(on|off))?$/
- if defined?( $1 )
+ when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
+ if defined?( $2 )
if $1 == 'on'
- @trace = true
+ set_trace_all true
else
- @trace = false
+ set_trace_all false
+ end
+ elsif defined?( $1 )
+ if $1 == 'on'
+ set_trace true
+ else
+ set_trace false
end
end
- if @trace
- stdout.print "Trace on\n"
+ if trace?
+ stdout.print "Trace on.\n"
else
- stdout.print "Trace off\n"
+ stdout.print "Trace off.\n"
end
when /^\s*b(?:reak)?\s+((?:.*?+:)?.+)$/
@@ -336,8 +391,7 @@ class DEBUGGER__
end
when /^\s*c(?:ont)?$/
- MUTEX.unlock
- return
+ prompt = false
when /^\s*s(?:tep)?(?:\s+(\d+))?$/
if $1
@@ -346,7 +400,7 @@ class DEBUGGER__
lev = 1
end
@stop_next = lev
- return
+ prompt = false
when /^\s*n(?:ext)?(?:\s+(\d+))?$/
if $1
@@ -356,7 +410,7 @@ class DEBUGGER__
end
@stop_next = lev
@no_step = @frames.size - frame_pos
- return
+ prompt = false
when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
display_frames(frame_pos)
@@ -417,8 +471,7 @@ class DEBUGGER__
else
@finish_pos = @frames.size - frame_pos
frame_pos = 0
- MUTEX.unlock
- return
+ prompt = false
end
when /^\s*cat(?:ch)?(?:\s+(.+))?$/
@@ -440,8 +493,10 @@ class DEBUGGER__
end
when /^\s*q(?:uit)?$/
- input = readline("really quit? (y/n) ", false)
- exit if input == "y"
+ input = readline("Really quit? (y/n) ", false)
+ if input == "y"
+ exit! # exit -> exit!: No graceful way to stop threads...
+ end
when /^\s*v(?:ar)?\s+/
debug_variable_info($', binding)
@@ -451,8 +506,7 @@ class DEBUGGER__
when /^\s*th(?:read)?\s+/
if DEBUGGER__.debug_thread_info($', binding) == :cont
- MUTEX.unlock
- return
+ prompt = false
end
when /^\s*p\s+/
@@ -467,6 +521,8 @@ class DEBUGGER__
end
end
end
+ MUTEX.unlock
+ resume_all
end
def debug_print_help
@@ -492,7 +548,8 @@ Commands
up[ nn] move to higher frame
down[ nn] move to lower frame
fin[ish] return to outer frame
- tr[ace][ (on|off)] set trace mode
+ tr[ace] (on|off) set trace mode of current thread
+ tr[ace] (on|off) all set trace mode of all threads
q[uit] exit from debugger
v[ar] g[lobal] show global variables
v[ar] l[ocal] show local variables
@@ -501,11 +558,10 @@ Commands
m[ethod] i[nstance] <obj> show methods of object
m[ethod] <class|module> show instance methods of class or module
th[read] l[ist] list all threads
- th[read] c[ur[rent]] show current threads
- th[read] <nnn> stop thread nnn
- th[read] stop <nnn> alias for th[read] <nnn>
- th[read] c[ur[rent]] <nnn> alias for th[read] <nnn>
- th[read] resume <nnn> run thread nnn
+ th[read] c[ur[rent]] show current thread
+ th[read] [sw[itch]] <nnn> switch thread context to nnn
+ th[read] stop <nnn> stop thread nnn
+ th[read] resume <nnn> resume thread nnn
p expression evaluate expression and print its value
h[elp] print this help
<everything else> evaluate
@@ -587,7 +643,7 @@ EOHELP
end
def check_break_points(file, pos, binding, id)
- MUTEX.lock # Stop all threads before 'line' and 'call'.
+ return false if break_points.empty?
file = File.basename(file)
n = 1
for b in break_points
@@ -604,7 +660,6 @@ EOHELP
end
n += 1
end
- MUTEX.unlock
return false
end
@@ -616,7 +671,6 @@ EOHELP
end
if @catch and ($!.type.ancestors.find { |e| e.to_s == @catch })
- MUTEX.lock
fs = @frames.size
tb = caller(0)[-fs..-1]
if tb
@@ -624,12 +678,14 @@ EOHELP
stdout.printf "\tfrom %s\n", i
end
end
+ suspend_all
debug_command(file, line, id, binding)
end
end
def trace_func(event, file, line, id, binding, klass)
- Tracer.trace_func(event, file, line, id, binding) if @trace
+ Tracer.trace_func(event, file, line, id, binding, klass) if trace?
+ context(Thread.current).check_suspend
@file = file
@line = line
case event
@@ -647,6 +703,7 @@ EOHELP
@stop_next = 1
else
@no_step = nil
+ suspend_all
debug_command(file, line, id, binding)
@last = [file, line]
end
@@ -656,6 +713,7 @@ EOHELP
@frames.unshift [binding, file, line, id]
if check_break_points(file, id.id2name, binding, id) or
check_break_points(klass.to_s, id.id2name, binding, id)
+ suspend_all
debug_command(file, line, id, binding)
end
@@ -668,6 +726,7 @@ EOHELP
when 'return', 'end'
if @frames.size == @finish_pos
@stop_next = 1
+ @finish_pos = 0
end
@frames.shift
@@ -682,19 +741,20 @@ EOHELP
end
end
- trap("INT") { DEBUGGER__.interrupt }
-# $DEBUG = true
+ trap("INT") { DEBUGGER__.interrupt }
@last_thread = Thread::main
@max_thread = 1
@thread_list = {Thread::main => 1}
@break_points = []
@display = []
+ @waiting = []
@stdout = STDOUT
class <<DEBUGGER__
def stdout
@stdout
end
+
def stdout=(s)
@stdout = s
end
@@ -707,10 +767,51 @@ EOHELP
@break_points
end
+ def waiting
+ @waiting
+ end
+
+ def set_trace( arg )
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ context(th[0]).set_trace arg
+ end
+ Thread.critical = false
+ end
+
def set_last_thread(th)
@last_thread = th
end
+ def suspend
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ next if th[0] == Thread.current
+ context(th[0]).set_suspend
+ end
+ Thread.critical = false
+ # Schedule other threads to suspend as soon as possible.
+ Thread.pass
+ end
+
+ def resume
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ next if th[0] == Thread.current
+ context(th[0]).clear_suspend
+ end
+ waiting.each do |th|
+ th.run
+ end
+ waiting.clear
+ Thread.critical = false
+ # Schedule other threads to restart as soon as possible.
+ Thread.pass
+ end
+
def context(thread=Thread.current)
c = thread[:__debugger_data__]
unless c
@@ -726,7 +827,7 @@ EOHELP
def get_thread(num)
th = @thread_list.index(num)
unless th
- @stdout.print "no thread no.", num, "\n"
+ @stdout.print "No thread ##{num}\n"
throw :debug_error
end
th
@@ -773,31 +874,52 @@ EOHELP
make_thread_list
thread_list_all
- when /^c(?:ur(?:rent)?)?\s+(\d+)/, /^stop\s+(\d+)/, /^(\d+)/
+ when /^c(?:ur(?:rent)?)?$/
+ make_thread_list
+ thread_list(@thread_list[Thread.current])
+
+ when /^(?:sw(?:itch)?\s+)?(\d+)/
make_thread_list
th = get_thread($1.to_i)
- thread_list(@thread_list[th])
- context(th).stop_next
- th.run
- return :cont
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ else
+ thread_list(@thread_list[th])
+ context(th).stop_next
+ th.run
+ return :cont
+ end
- when /^c(?:ur(?:rent)?)?$/
+ when /^stop\s+(\d+)/
make_thread_list
- thread_list(@thread_list[Thread.current])
+ th = get_thread($1.to_i)
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ elsif th.stop?
+ @stdout.print "Already stopped.\n"
+ else
+ thread_list(@thread_list[th])
+ context(th).suspend
+ end
when /^resume\s+(\d+)/
make_thread_list
th = get_thread($1.to_i)
- thread_list(@thread_list[th])
- th.run
- return :cont
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ elsif !th.stop?
+ @stdout.print "Already running."
+ else
+ thread_list(@thread_list[th])
+ th.run
+ end
end
end
end
stdout.printf "Debug.rb\n"
stdout.printf "Emacs support available.\n\n"
- set_trace_func proc{|event, file, line, id, binding,klass,*rest|
- DEBUGGER__.context.trace_func event, file, line, id, binding,klass
+ set_trace_func proc { |event, file, line, id, binding, klass, *rest|
+ DEBUGGER__.context.trace_func event, file, line, id, binding, klass
}
end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 480e1ef6b8..a72ea943ba 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -8,7 +8,7 @@
# Usage:
# foo = Object.new
# foo2 = SimpleDelegator.new(foo)
-# foo.hash == foo2.hash # => true
+# foo.hash == foo2.hash # => false
#
# Foo = DelegateClass(Array)
#
diff --git a/lib/importenv.rb b/lib/importenv.rb
index fcf306a9ab..586f37661b 100644
--- a/lib/importenv.rb
+++ b/lib/importenv.rb
@@ -10,10 +10,10 @@
for k,v in ENV
next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
eval <<EOS
- $#{k} = %q!#{v}!
+ $#{k} = v
trace_var "$#{k}", proc{|v|
- ENV[%q!#{k}!] = v;
- $#{k} = %q!#{v}!
+ ENV[%q!#{k}!] = v
+ $#{k} = v
if v == nil
untrace_var "$#{k}"
end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index 4c7a3b1002..534870e329 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -608,7 +608,7 @@ class RubyLex
identify_quotation
elsif peek(0) == '='
getc
- Token(OP_ASGIN, "%")
+ Token(TkOPASGN, :%)
elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
identify_quotation
else
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 317200ba79..a9ce9b55bb 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -43,7 +43,7 @@ else
$null = open('test.log', 'w')
end
-LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
+LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
CPP = "#{CONFIG['CPP']} -E %s -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s conftest.c"
def rm_f(*files)
@@ -155,7 +155,9 @@ def install_rb(mfile, dest, srcdir = nil)
mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' %s/%s\n", dest, f
end
for f in path
- mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' lib/%s %s/%s\n", f, dest, f
+ d = '/' + File::dirname(f)
+ d = '' if d == '/.'
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' %s/%s %s%s\n", libdir, f, dest, d
end
end
@@ -352,6 +354,8 @@ def dir_config(target, idefault=nil, ldefault=nil)
end
def create_makefile(target, srcdir = File.dirname($0))
+ save_libs = $libs.dup
+ save_libpath = $LIBPATH.dup
print "creating Makefile\n"
rm_f "conftest*"
STDOUT.flush
@@ -370,15 +374,16 @@ def create_makefile(target, srcdir = File.dirname($0))
end
$DLDFLAGS = CONFIG["DLDFLAGS"]
- if $configure_args['--enable-shared'] or CONFIG['LIBRUBY'] != CONFIG['LIBRUBY_A']
- $libs = CONFIG["LIBRUBYARG"] + " " + $libs
- $LIBPATH |= ["$(topdir)", CONFIG["libdir"]]
- end
+ $libs = CONFIG["LIBRUBYARG"] + " " + $libs
+ $configure_args['--enable-shared'] or $LIBPATH |= [$topdir]
+ $LIBPATH |= [CONFIG["libdir"]]
defflag = ''
if RUBY_PLATFORM =~ /cygwin|mingw/
- open(target + '.def', 'wb') do |f|
- f.print "EXPORTS\n", "Init_", target, "\n"
+ if not File.exist? target + '.def'
+ open(target + '.def', 'wb') do |f|
+ f.print "EXPORTS\n", "Init_", target, "\n"
+ end
end
defflag = "--def=" + target + ".def"
end
@@ -474,7 +479,7 @@ $(archdir)/$(DLLIB): $(DLLIB)
@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(archdir)
@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(archdir)/$(DLLIB)
EOMF
- install_rb(mfile, "$(libdir)")
+ install_rb(mfile, "$(libdir)", srcdir)
mfile.printf "\n"
mfile.printf <<EOMF
@@ -482,21 +487,42 @@ $(sitearchdir)/$(DLLIB): $(DLLIB)
@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(sitearchdir)
@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(sitearchdir)/$(DLLIB)
EOMF
- install_rb(mfile, "$(sitelibdir)")
+ install_rb(mfile, "$(sitelibdir)", srcdir)
mfile.printf "\n"
if /mswin32/ !~ RUBY_PLATFORM
mfile.print "
.c.#{$OBJEXT}:
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+.cc.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+.cpp.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+.cxx.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+.C.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
"
elsif /nmake/i =~ $make
mfile.print "
{$(srcdir)}.c.#{$OBJEXT}:
$(CC) $(CFLAGS) -I$(<D) $(CPPFLAGS) -c $(<:/=\\)
-
.c.#{$OBJEXT}:
$(CC) $(CFLAGS) -I$(<D) $(CPPFLAGS) -c $(<:/=\\)
+
+{$(srcdir)}.cc{}.#{$OBJEXT}:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cc.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cpp{}.#{$OBJEXT}:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cpp.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cxx{}.#{$OBJEXT}:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cxx.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
"
else
mfile.print "
@@ -504,6 +530,9 @@ EOMF
.c.#{$OBJEXT}:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
+
+.cc.#{$OBJEXT} .cpp.#{$OBJEXT} .cxx.#{$OBJEXT} .C.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
"
end
@@ -536,6 +565,8 @@ EOMF
dfile.close
end
mfile.close
+ $libs = save_libs
+ $LIBPATH = save_libpath
end
$OBJEXT = CONFIG["OBJEXT"]
diff --git a/lib/monitor.rb b/lib/monitor.rb
index 75d9c35821..721c51a9f5 100644
--- a/lib/monitor.rb
+++ b/lib/monitor.rb
@@ -1,27 +1,44 @@
=begin
-monitor.rb
-Author: Shugo Maeda <shugo@netlab.co.jp>
-Version: 1.2.1
+= monitor.rb
-USAGE:
+Copyright (C) 2001 Shugo Maeda <shugo@ruby-lang.org>
- foo = Foo.new
- foo.extend(MonitorMixin)
- cond = foo.new_cond
+This library is distributed under the terms of the Ruby license.
+You can freely distribute/modify this library.
- thread1:
- foo.synchronize {
- ...
- cond.wait_until { foo.done? }
- ...
- }
+== example
- thread2:
- foo.synchronize {
- foo.do_something
- cond.signal
- }
+This is a simple example.
+
+ require 'monitor.rb'
+
+ buf = []
+ buf.extend(MonitorMixin)
+ empty_cond = buf.new_cond
+
+ # consumer
+ Thread.start do
+ loop do
+ buf.synchronize do
+ empty_cond.wait_while { buf.empty? }
+ print buf.shift
+ end
+ end
+ end
+
+ # producer
+ while line = ARGF.gets
+ buf.synchronize do
+ buf.push(line)
+ empty_cond.signal
+ end
+ end
+
+The consumer thread waits for the producer thread to push a line
+to buf while buf.empty?, and the producer thread (main thread)
+reads a line from ARGF and push it to buf, then call
+empty_cond.signal.
=end
@@ -52,6 +69,15 @@ module MonitorMixin
raise ThreadError, "current thread not owner"
end
+ if timeout
+ ct = Thread.current
+ timeout_thread = Thread.start {
+ Thread.pass
+ sleep(timeout)
+ ct.raise(Timeout.new)
+ }
+ end
+
Thread.critical = true
count = @monitor.mon_count
@monitor.mon_count = 0
@@ -63,34 +89,28 @@ module MonitorMixin
end
t.wakeup if t
@waiters.push(Thread.current)
-
- if timeout
- t = Thread.current
- timeout_thread = Thread.start {
- sleep(timeout)
- t.raise(Timeout.new)
- }
- end
+
begin
Thread.stop
rescue Timeout
- @waiters.delete(Thread.current)
ensure
+ Thread.critical = true
if timeout && timeout_thread.alive?
Thread.kill(timeout_thread)
end
+ if @waiters.include?(Thread.current) # interrupted?
+ @waiters.delete(Thread.current)
+ end
+ while @monitor.mon_owner &&
+ @monitor.mon_owner != Thread.current
+ @monitor.mon_waiting_queue.push(Thread.current)
+ Thread.stop
+ Thread.critical = true
+ end
+ @monitor.mon_owner = Thread.current
+ @monitor.mon_count = count
+ Thread.critical = false
end
-
- Thread.critical = true
- while @monitor.mon_owner &&
- @monitor.mon_owner != Thread.current
- @monitor.mon_waiting_queue.push(Thread.current)
- Thread.stop
- Thread.critical = true
- end
- @monitor.mon_owner = Thread.current
- @monitor.mon_count = count
- Thread.critical = false
end
def wait_while
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 3900ed6c68..26e5285525 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -1,8 +1,9 @@
=begin
-= net/http.rb version 1.1.32
+= net/http.rb version 1.1.34
+
+written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
-maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This file is derived from "http-access.rb".
This program is free software.
@@ -14,9 +15,34 @@ You can get it from RAA
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html).
-= class HTTP
+== http.rb version 1.2 features
+
+You can use 1.2 features by calling HTTP.version_1_2. And
+calling Net::HTTP.version_1_1 allows to use 1.1 features.
+
+ # example
+ HTTP.start {|http1| ...(http1 has 1.1 features)... }
+
+ HTTP.version_1_2
+ HTTP.start {|http2| ...(http2 has 1.2 features)... }
+
+ HTTP.version_1_1
+ HTTP.start {|http3| ...(http3 has 1.1 features)... }
+
+Changes are:
-== Class Methods
+ * HTTP#get, head, post does not raise ProtocolError
+ * HTTP#get, head, post returns only one object, a HTTPResponse object
+ * HTTPResponseReceiver is joined into HTTPResponse
+ * request object: HTTP::Get, Head, Post; and HTTP#request(req)
+
+WARNING: These features are not definite yet.
+They will change without notice!
+
+
+== class HTTP
+
+=== Class Methods
: new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
creates a new Net::HTTP object.
@@ -49,7 +75,7 @@ You can get it from RAA
HTTP default port (80).
-== Methods
+=== Methods
: start
: start {|http| .... }
@@ -72,7 +98,7 @@ You can get it from RAA
get data from "path" on connecting host.
"header" must be a Hash like { 'Accept' => '*/*', ... }.
Data is written to "dest" by using "<<" method.
- This method returns Net::HTTPResponse object, and "dest".
+ This method returns HTTPResponse object, and "dest".
# example
response, body = http.get( '/index.html' )
@@ -95,7 +121,7 @@ You can get it from RAA
: head( path, header = nil )
gets only header from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
- This method returns a Net::HTTPResponse object.
+ This method returns a HTTPResponse object.
You can http header from this object like:
response['content-length'] #-> '2554'
@@ -109,7 +135,7 @@ You can get it from RAA
If the body exists, also gets entity body.
Data is written to "dest" by using "<<" method.
"header" must be a Hash like { 'Accept' => '*/*', ... }.
- This method returns Net::HTTPResponse object and "dest".
+ This method returns HTTPResponse object and "dest".
If called with block, gives a part of entity body string.
@@ -181,21 +207,21 @@ You can get it from RAA
response.body
-= class HTTPResponse
+== class HTTPResponse
HTTP response object.
All "key" is case-insensitive.
-== Methods
+=== Methods
: body
- the entity body. ("dest" argument for HTTP#get, post, put)
+ the entity body (String).
: self[ key ]
returns header field for "key".
for HTTP, value is a string like 'text/plain'(for Content-Type),
- '2045'(for Content-Length), 'bytes 0-1024/10024'(for Content-Range).
- Multiple header had be joined by HTTP1.1 scheme.
+ '2045'(for Content-Length), 'bytes 0-1023/10024'(for Content-Range).
+ If there's some fields which has same name, they are joined with ','.
: self[ key ] = val
set field value for "key".
@@ -204,88 +230,92 @@ All "key" is case-insensitive.
true if key exists
: each {|name,value| .... }
- iterates for each field name and value pair
+ iterates for each field name and value pair.
: code
- HTTP result code string. For example, '302'
+ HTTP result code string. For example, '302'.
: message
- HTTP result message. For example, 'Not Found'
+ HTTP result message. For example, 'Not Found'.
-= class HTTPResponseReceiver
+== class HTTPResponseReceiver
-== Methods
+=== Methods
: header
: response
- Net::HTTPResponse object
+ HTTPResponse object
-: body( dest = '' )
-: entity( dest = '' )
- entity body. A body is written to "dest" using "<<" method.
+: read_body( dest = '' )
+ reads entity body into DEST by calling "<<" method and
+ returns DEST.
-: body {|str| ... }
- gets entity body with block.
- If this method is called twice, block is not executed and
- returns first "dest".
+: read_body {|string| ... }
+ reads entity body little by little and gives it to block
+ until entity ends.
+: body
+: entity
+ entity body. If #read_body is called already, returns its
+ argument DEST. Else returns entity body as String.
-= http.rb version 1.2 features
+ Calling this method any times causes returning same
+ object (does not read entity again).
-You can use 1.2 features by calling HTTP.version_1_2. And
-calling Net::HTTP.version_1_1 allows to use 1.1 features.
+=end
- # example
- HTTP.start {|http1| ...(http1 has 1.1 features)... }
+require 'net/protocol'
- HTTP.version_1_2
- HTTP.start {|http2| ...(http2 has 1.2 features)... }
- HTTP.version_1_1
- HTTP.start {|http3| ...(http3 has 1.1 features)... }
+module Net
-== Method (only diff to 1.1)
+ class HTTPBadResponse < StandardError; end
+ class HTTPHeaderSyntaxError < StandardError; end
-: get( path, u_header = nil )
-: get( path, u_header = nil ) {|str| .... }
- gets document from "path".
- returns HTTPResponse object.
-: head( path, u_header = nil )
- gets only document header from "path".
- returns HTTPResponse object.
+ class HTTP < Protocol
-: post( path, data, u_header = nil )
-: post( path, data, u_header = nil ) {|str| .... }
- posts "data" to "path" entity and gets document.
- returns HTTPResponse object.
+ HTTPVersion = '1.1'
-=end
+ #
+ # connection
+ #
-require 'net/protocol'
+ protocol_param :port, '80'
-module Net
+ def initialize( addr = nil, port = nil )
+ super
- class HTTPBadResponse < StandardError; end
+ @proxy_address = nil
+ @proxy_port = nil
+ @curr_http_version = HTTPVersion
+ @seems_1_0_server = false
+ end
- class HTTP < Protocol
- protocol_param :port, '80'
- protocol_param :command_type, '::Net::NetPrivate::HTTPCommand'
+ private
+ def conn_command( sock )
+ end
+
+ def do_finish
+ end
+
+
+ #
+ # proxy
+ #
+
+ public
- ###
- ### proxy
- ###
class << self
def Proxy( p_addr, p_port = nil )
- ::Net::NetPrivate::HTTPProxy.create_proxy_class(
- p_addr, p_port || self.port )
+ ProxyMod.create_proxy_class( p_addr, p_port || self.port )
end
alias orig_new new
@@ -293,7 +323,7 @@ module Net
def new( address = nil, port = nil, p_addr = nil, p_port = nil )
c = p_addr ? self::Proxy(p_addr, p_port) : self
i = c.orig_new( address, port )
- setimplv i
+ setvar i
i
end
@@ -332,385 +362,230 @@ module Net
end
- ###
- ### 1.2 implementation
- ###
+ module ProxyMod
- @@newimpl = false
+ class << self
- #class << self
+ def create_proxy_class( p_addr, p_port )
+ mod = self
+ klass = Class.new( HTTP )
+ klass.module_eval {
+ include mod
+ @proxy_address = p_addr
+ @proxy_port = p_port
+ }
+ def klass.proxy_class?
+ true
+ end
- def self.version_1_2
- @@newimpl = true
- end
+ def klass.proxy_address
+ @proxy_address
+ end
- def self.version_1_1
- @@newimpl = false
- end
+ def klass.proxy_port
+ @proxy_port
+ end
- #private
+ klass
+ end
- def self.setimplv( obj )
- f = @@newimpl
- obj.instance_eval { @newimpl = f }
end
- #end
-
-
- ###
- ### http operations
- ###
-
- def get( path, u_header = nil, dest = nil, &block )
- resp = get2( path, u_header ) {|f| f.body( dest, &block ) }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+ def initialize( addr, port )
+ super
+ @proxy_address = type.proxy_address
+ @proxy_port = type.proxy_port
end
- end
-
- def get2( path, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.get edit_path(path), uh
- }
- end
+
+ attr_reader :proxy_address, :proxy_port
+ alias proxyaddr proxy_address
+ alias proxyport proxy_port
- def head( path, u_header = nil )
- resp = head2( path, u_header )
- unless @newimpl then
- resp.value
+ def proxy?
+ true
end
- resp
- end
-
- def head2( path, u_header = nil, &block )
- common_oper( u_header, false, block ) {|uh|
- @command.head edit_path(path), uh
- }
- end
-
-
- def post( path, data, u_header = nil, dest = nil, &block )
- resp = post2( path, data, u_header ) {|f| f.body( dest, &block ) }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+
+ private
+
+ def conn_socket( addr, port )
+ super @proxy_address, @proxy_port
end
- end
-
- def post2( path, data, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.post edit_path(path), uh, data
- }
- end
-
- # not tested because I could not setup apache (__;;;
- def put( path, src, u_header = nil )
- resp = put2( path, src, u_header ) {|f| f.body }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+ def edit_path( path )
+ 'http://' + addr_port + path
end
- end
+
+ end # module ProxyMod
- def put2( path, src, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.put path, uh, src
- }
- end
-
-
- private
-
-
- def common_oper( u_header, body_exist, block )
- header = procheader( u_header )
- recv = err = nil
-
- connecting( header ) {
- recv = HTTPResponseReceiver.new( @command, body_exist )
- yield header
- begin
- block.call recv if block
- rescue Exception => err
- ;
- end
- recv.terminate
-
- recv.response
- }
- raise err if err
- recv.response
- end
+ #
+ # for backward compatibility
+ #
- def connecting( header )
- if not @socket then
- header['Connection'] = 'close'
- start
- elsif @socket.closed? then
- @socket.reopen
- end
+ @@newimpl = false
- resp = yield
+ class << self
- unless keep_alive? header, resp then
- @socket.close
+ def version_1_2
+ @@newimpl = true
end
- end
- def keep_alive?( header, resp )
- if resp.key? 'connection' then
- if /keep-alive/i === resp['connection'] then
- return true
- end
- elsif resp.key? 'proxy-connection' then
- if /keep-alive/i === resp['proxy-connection'] then
- return true
- end
- elsif header.key? 'Connection' then
- if /keep-alive/i === header['Connection'] then
- return true
- end
- else
- if @command.http_version == '1.1' then
- return true
- end
+ def version_1_1
+ @@newimpl = false
end
- false
- end
-
- def procheader( h )
- ret = {}
- ret[ 'Host' ] = address +
- ((port == HTTP.port) ? '' : ":#{port}")
- ret[ 'Connection' ] = 'Keep-Alive'
- ret[ 'Accept' ] = '*/*'
+ private
- return ret unless h
- tmp = {}
- h.each do |k,v|
- key = k.split('-').collect {|i| i.capitalize }.join('-')
- if tmp[key] then
- $stderr.puts "'#{key}' http header appered twice" if $VERBOSE
- end
- tmp[key] = v
+ def setvar( obj )
+ f = @@newimpl
+ obj.instance_eval { @newimpl = f }
end
- ret.update tmp
- ret
end
- def do_finish
- end
+ #
+ # http operations
+ #
- end
-
- HTTPSession = HTTP
-
-
- module NetPrivate
-
- module HTTPProxy
-
- class << self
-
- def create_proxy_class( p_addr, p_port )
- klass = Class.new( HTTP )
- klass.module_eval {
- include HTTPProxy
- @proxy_address = p_addr
- @proxy_port = p_port
- }
- def klass.proxy_class?
- true
- end
+ public
- def klass.proxy_address
- @proxy_address
+ def self.def_http_method( nm, hasdest, hasdata )
+ name = nm.id2name.downcase
+ cname = nm.id2name
+ lineno = __LINE__ + 2
+ src = <<" ----"
+
+ def #{name}( path, #{hasdata ? 'data,' : ''}
+ u_header = nil #{hasdest ? ',dest = nil, &block' : ''} )
+ resp = nil
+ request(
+ #{cname}.new( path, u_header ) #{hasdata ? ',data' : ''}
+ ) do |resp|
+ resp.read_body( #{hasdest ? 'dest, &block' : ''} )
+ end
+ if @newimpl then
+ resp
+ else
+ resp.value
+ #{hasdest ? 'return resp, resp.body' : 'resp'}
+ end
end
- def klass.proxy_port
- @proxy_port
+ def #{name}2( path, #{hasdata ? 'data,' : ''}
+ u_header = nil, &block )
+ request( #{cname}.new(path, u_header),
+ #{hasdata ? 'data,' : ''} &block )
end
-
- klass
- end
-
- end
-
-
- def initialize( addr, port )
- super
- @proxy_address = type.proxy_address
- @proxy_port = type.proxy_port
+ ----
+ module_eval src, __FILE__, lineno
end
- attr_reader :proxy_address, :proxy_port
+ def_http_method :Get, true, false
+ def_http_method :Head, false, false
+ def_http_method :Post, true, true
+ def_http_method :Put, false, true
- alias proxyaddr proxy_address
- alias proxyport proxy_port
-
- def proxy?
- true
- end
-
- def connect( addr = nil, port = nil )
- super @proxy_address, @proxy_port
- end
-
- def edit_path( path )
- 'http://' + address + (port == type.port ? '' : ":#{port}") + path
+ def request( req, *args )
+ common_oper( req ) {
+ req.__send__( :exec,
+ @socket, @curr_http_version, edit_path(req.path), *args )
+ yield req.response if block_given?
+ }
+ req.response
end
-
- end
-
- end # net private
+ private
- class HTTPResponseReceiver
-
- def initialize( command, body_exist )
- @command = command
- @body_exist = body_exist
- @header = @body = nil
- end
-
- def inspect
- "#<#{type}>"
- end
- def read_header
- unless @header then
- stream_check
- @header = @command.get_response
+ def common_oper( req )
+ req['connection'] ||= 'keep-alive'
+ if not @socket then
+ start
+ req['connection'] = 'close'
+ elsif @socket.closed? then
+ re_connect
end
- @header
- end
-
- alias header read_header
- alias response read_header
-
- def read_body( dest = nil, &block )
- unless @body then
- read_header
-
- to = procdest( dest, block )
- stream_check
-
- if @body_exist and @header.code_type.body_exist? then
- @command.get_body @header, to
- @header.body = @body = to
- else
- @command.no_body
- @header.body = nil
- @body = 1
- end
+ if not req.body_exist? or @seems_1_0_server then
+ req['connection'] = 'close'
end
- @body == 1 ? nil : @body
- end
-
- alias body read_body
- alias entity read_body
+ req['host'] = addr_port
- def terminate
- read_header
- read_body
- @command = nil
- end
+ yield req
+ req.response.__send__ :terminate
+ @curr_http_version = req.response.http_version
-
- private
-
- def stream_check
- unless @command then
- raise IOError, 'receiver was used out of block'
- end
- end
-
- def procdest( dest, block )
- if dest and block then
- raise ArgumentError,
- 'both of arg and block are given for HTTP method'
- end
- if block then
- NetPrivate::ReadAdapter.new block
+ if not req.response.body then
+ @socket.close
+ elsif keep_alive? req, req.response then
+ D 'Conn keep-alive'
+ if @socket.closed? then # (only) read stream had been closed
+ D 'Conn (but seems 1.0 server)'
+ @seems_1_0_server = true
+ @socket.close
+ end
else
- dest or ''
+ D 'Conn close'
+ @socket.close
end
- end
-
- end
-
- HTTPReadAdapter = HTTPResponseReceiver
-
- class HTTPResponse < Response
-
- def initialize( code_type, code, msg )
- super
- @data = {}
- @body = nil
+ req.response
end
- attr_accessor :body
+ def keep_alive?( req, res )
+ /close/i === req['connection'].to_s and return false
+ @seems_1_0_server and return false
- def inspect
- "#<#{type.name} #{code}>"
- end
+ /keep-alive/i === res['connection'].to_s and return true
+ /close/i === res['connection'].to_s and return false
+ /keep-alive/i === res['proxy-connection'].to_s and return true
+ /close/i === res['proxy-connection'].to_s and return false
- def []( key )
- @data[ key.downcase ]
+ @curr_http_version == '1.1' and return true
+ false
end
- def []=( key, val )
- @data[ key.downcase ] = val
- end
- def each( &block )
- @data.each( &block )
- end
+ #
+ # utils
+ #
- def each_key( &block )
- @data.each_key( &block )
- end
+ public
- def each_value( &block )
- @data.each_value( &block )
+ def self.get( addr, path, port = nil )
+ req = Get.new( path )
+ resp = nil
+ new( addr, port || HTTP.port ).start {|http|
+ resp = http.request( req )
+ }
+ resp.body
end
- def delete( key )
- @data.delete key.downcase
+ def self.get_print( addr, path, port = nil )
+ print get( addr, path, port )
end
- def key?( key )
- @data.key? key.downcase
- end
- def to_hash
- @data.dup
+ private
+
+ def addr_port
+ address + (port == HTTP.port ? '' : ":#{port}")
end
- def value
- unless SuccessCode === self then
- error! self
+ def D( msg )
+ if @dout then
+ @dout << msg
+ @dout << "\n"
end
end
end
+ HTTPSession = HTTP
+
+
class Code
@@ -776,101 +651,246 @@ module Net
HTTPVersionNotSupported = HTTPServerErrorCode.http_mkchild
- module NetPrivate
+ ###
+ ### header
+ ###
- class HTTPCommand < Command
+ net_private {
- HTTPVersion = '1.1'
+ module HTTPHeader
- def initialize( sock )
- @http_version = HTTPVersion
- super sock
+ def size
+ @header.size
end
- attr_reader :http_version
+ alias length size
- def inspect
- "#<Net::HTTPCommand>"
+ def []( key )
+ @header[ key.downcase ]
end
+ def []=( key, val )
+ @header[ key.downcase ] = val
+ end
- ###
- ### request
- ###
+ def each( &block )
+ @header.each( &block )
+ end
- public
+ def each_key( &block )
+ @header.each_key( &block )
+ end
- def get( path, u_header )
- return unless begin_critical
- request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
+ def each_value( &block )
+ @header.each_value( &block )
end
-
- def head( path, u_header )
- return unless begin_critical
- request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
+
+ def delete( key )
+ @header.delete key.downcase
+ end
+
+ def key?( key )
+ @header.key? key.downcase
+ end
+
+ def to_hash
+ @header.dup
end
- def post( path, u_header, data )
- return unless begin_critical
- u_header[ 'Content-Length' ] = data.size.to_s
- request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
- @socket.write data
+ def canonical_each
+ @header.each do |k,v|
+ yield canonical(k), v
+ end
end
- def put( path, u_header, src )
- return unless begin_critical
- request sprintf('PUT %s HTTP/%s', path, HTTPVersion), u_header
- @socket.write_bin src
+ def canonical( k )
+ k.split('-').collect {|i| i.capitalize }.join('-')
end
- # def delete
+ def range
+ s = @header['range']
+ s or return nil
- # def trace
+ arr = []
+ s.split(',').each do |spec|
+ m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match( spec )
+ m or raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
- # def options
+ d1 = m[1].to_i
+ d2 = m[2].to_i
+ if m[1] and m[2] then arr.push (d1 .. d2)
+ elsif m[1] then arr.push (d1 .. -1)
+ elsif m[2] then arr.push (-d2 .. -1)
+ else
+ raise HTTPHeaderSyntaxError, 'range is not specified'
+ end
+ end
- def quit
+ return *arr
end
+ def range=( r, fin = nil )
+ if fin then
+ r = r ... r+fin
+ end
- private
+ case r
+ when Numeric
+ s = r > 0 ? "0-#{r - 1}" : "-#{-r}"
+ when Range
+ first = r.first
+ last = r.last
+ if r.exclude_end? then
+ last -= 1
+ end
- def request( req, u_header )
- @socket.writeline req
- u_header.each do |n,v|
- @socket.writeline n + ': ' + v
+ if last == -1 then
+ s = first > 0 ? "#{first}-" : "-#{-first}"
+ else
+ first >= 0 or raise HTTPHeaderSyntaxError, 'range.first is negative'
+ last > 0 or raise HTTPHeaderSyntaxError, 'range.last is negative'
+ first < last or raise HTTPHeaderSyntaxError, 'must be .first < .last'
+ s = "#{first}-#{last}"
+ end
+ else
+ raise TypeError, 'Range/Integer is required'
end
- @socket.writeline ''
+
+ @header['range'] = "bytes=#{s}"
+ r
end
+ alias set_range range=
- ###
- ### response line & header
- ###
+ def content_length
+ s = @header['content-length']
+ s or return nil
- public
+ m = /\d+/.match(s)
+ m or raise HTTPHeaderSyntaxError, 'wrong Content-Length format'
+ m[0].to_i
+ end
- def get_response
- resp = get_resp0
- resp = get_resp0 while ContinueCode === resp
- resp
+ def chunked?
+ s = @header['transfer-encoding']
+ (s and /(?:\A|[^\-\w])chunked(?:[^\-\w]|\z)/i === s) ? true : false
+ end
+
+ def content_range
+ s = @header['content-range']
+ s or return nil
+
+ m = %r<bytes\s+(\d+)-(\d+)/(?:\d+|\*)>i.match( s )
+ m or raise HTTPHeaderSyntaxError, 'wrong Content-Range format'
+
+ m[1].to_i .. m[2].to_i + 1
+ end
+
+ def range_length
+ r = content_range
+ r and r.length
+ end
+
+ def basic_auth( acc, pass )
+ @header['authorization'] =
+ 'Basic ' + ["#{acc}:#{pass}"].pack('m').gsub(/\s+/, '')
+ end
+
+ end
+
+ }
+
+
+ ###
+ ### request
+ ###
+
+ net_private {
+
+ class HTTPRequest
+
+ include ::Net::NetPrivate::HTTPHeader
+
+ def initialize( path, uhead = nil )
+ @path = path
+ @header = tmp = {}
+ return unless uhead
+ uhead.each do |k,v|
+ key = k.downcase
+ if tmp.key? key then
+ $stderr.puts "WARNING: duplicated HTTP header: #{k}" if $VERBOSE
+ end
+ tmp[ key ] = v.strip
+ end
+ tmp['accept'] ||= '*/*'
+
+ @socket = nil
+ @response = nil
+ end
+
+ attr_reader :path
+ attr_reader :response
+
+ def inspect
+ "\#<#{type}>"
+ end
+
+ def body_exist?
+ type::HAS_BODY
end
private
- def get_resp0
- resp = get_reply
+ #
+ # write
+ #
+
+ def exec( sock, ver, path )
+ ready( sock ) {
+ request ver, path
+ }
+ @response
+ end
+
+ def ready( sock )
+ @response = nil
+ @socket = sock
+ yield
+ @response = get_response
+ @socket = nil
+ end
+
+ def request( ver, path )
+ @socket.writeline sprintf('%s %s HTTP/%s', type::METHOD, path, ver)
+ canonical_each do |k,v|
+ @socket.writeline k + ': ' + v
+ end
+ @socket.writeline ''
+ end
+
+ #
+ # read
+ #
+
+ def get_response
+ begin
+ resp = read_response
+ end while ContinueCode === resp
+ resp
+ end
+
+ def read_response
+ resp = get_resline
while true do
- line = @socket.readline
+ line = @socket.readuntil( "\n", true ) # ignore EOF
+ line.sub!( /\s+\z/, '' ) # don't use chop!
break if line.empty?
m = /\A([^:]+):\s*/.match( line )
- unless m then
- raise HTTPBadResponse, 'wrong header line format'
- end
+ m or raise HTTPBadResponse, 'wrong header line format'
nm = m[1]
line = m.post_match
if resp.key? nm then
@@ -883,23 +903,117 @@ module Net
resp
end
- def get_reply
+ def get_resline
str = @socket.readline
- m = /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i.match( str )
- unless m then
- raise HTTPBadResponse, "wrong status line: #{str}"
- end
- @http_version = m[1]
+ m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/i.match( str )
+ m or raise HTTPBadResponse, "wrong status line: #{str}"
+ httpver = m[1]
status = m[2]
discrip = m[3]
- code = HTTPCODE_TO_OBJ[status] ||
- HTTPCODE_CLASS_TO_OBJ[status[0,1]] ||
- UnknownCode
- HTTPResponse.new( code, status, discrip )
+ ::Net::NetPrivate::HTTPResponse.new(
+ status, discrip, @socket, type::HAS_BODY, httpver )
+ end
+
+ end
+
+
+ class HTTPRequestWithBody < HTTPRequest
+
+ private
+
+ def exec( sock, ver, path, str = nil )
+ check_arg str, block_given?
+
+ if block_given? then
+ ac = Accumulator.new
+ yield ac # must be yield, DO NOT USE block.call
+ data = ac.terminate
+ else
+ data = str
+ end
+ @header['content-length'] = data.size.to_s
+ @header.delete 'transfer-encoding'
+
+ ready( sock ) {
+ request ver, path
+ @socket.write data
+ }
+ @response
+ end
+
+ def check_arg( data, blkp )
+ if data and blkp then
+ raise ArgumentError, 'both of data and block given'
+ end
+ unless data or blkp then
+ raise ArgumentError, 'str or block required'
+ end
+ end
+
+ end
+
+
+ class Accumulator
+
+ def initialize
+ @buf = ''
+ end
+
+ def write( s )
+ @buf.concat s
+ end
+
+ alias << write
+
+ def terminate
+ ret = @buf
+ @buf = nil
+ ret
+ end
+
+ end
+
+ }
+
+
+ class HTTP
+
+ class Get < ::Net::NetPrivate::HTTPRequest
+ HAS_BODY = true
+ METHOD = 'GET'
+ end
+
+ class Head < ::Net::NetPrivate::HTTPRequest
+ HAS_BODY = false
+ METHOD = 'HEAD'
+ end
+
+ class Post < ::Net::NetPrivate::HTTPRequestWithBody
+ HAS_BODY = true
+ METHOD = 'POST'
+ end
+
+ class Put < ::Net::NetPrivate::HTTPRequestWithBody
+ HAS_BODY = true
+ METHOD = 'PUT'
end
- HTTPCODE_CLASS_TO_OBJ = {
+ end
+
+
+
+ ###
+ ### response
+ ###
+
+ net_private {
+
+ class HTTPResponse < Response
+
+ include ::Net::NetPrivate::HTTPHeader
+
+ CODE_CLASS_TO_OBJ = {
'1' => HTTPInformationCode,
'2' => HTTPSuccessCode,
'3' => HTTPRedirectionCode,
@@ -907,7 +1021,7 @@ module Net
'5' => HTTPServerErrorCode
}
- HTTPCODE_TO_OBJ = {
+ CODE_TO_OBJ = {
'100' => ContinueCode,
'101' => HTTPSwitchProtocol,
@@ -951,22 +1065,87 @@ module Net
'505' => HTTPVersionNotSupported
}
+ def initialize( stat, msg, sock, be, hv )
+ code = CODE_TO_OBJ[stat] ||
+ CODE_CLASS_TO_OBJ[stat[0,1]] ||
+ UnknownCode
+ super code, stat, msg
+ @socket = sock
+ @body_exist = be
+ @http_version = hv
- ###
- ### body
- ###
+ @header = {}
+ @body = nil
+ @read = false
+ end
- public
+ attr_reader :http_version
+
+ def inspect
+ "#<#{type} #{code}>"
+ end
+
+ def value
+ SuccessCode === self or error! self
+ end
- def get_body( resp, dest )
- if chunked? resp then
+
+ #
+ # header (for backward compatibility)
+ #
+
+ def read_header
+ self
+ end
+
+ alias header read_header
+ alias response read_header
+
+ #
+ # body
+ #
+
+ def read_body( dest = nil, &block )
+ if @read and (dest or block) then
+ raise IOError, "#{type}\#read_body called twice with argument"
+ end
+
+ unless @read then
+ to = procdest( dest, block )
+ stream_check
+
+ if @body_exist and code_type.body_exist? then
+ read_body_0 to
+ @body = to
+ else
+ @body = nil
+ end
+ @read = true
+ end
+
+ @body
+ end
+
+ alias body read_body
+ alias entity read_body
+
+
+ private
+
+
+ def terminate
+ read_body
+ end
+
+ def read_body_0( dest )
+ if chunked? then
read_chunked dest
else
- clen = content_length( resp )
+ clen = content_length
if clen then
- @socket.read clen, dest
+ @socket.read clen, dest, true # ignore EOF
else
- clen = range_length( resp )
+ clen = range_length
if clen then
@socket.read clen, dest
else
@@ -974,16 +1153,8 @@ module Net
end
end
end
- end_critical
- end
-
- def no_body
- end_critical
end
-
- private
-
def read_chunked( dest )
len = nil
total = 0
@@ -991,9 +1162,7 @@ module Net
while true do
line = @socket.readline
m = /[0-9a-fA-F]+/.match( line )
- unless m then
- raise HTTPBadResponse, "wrong chunk size line: #{line}"
- end
+ m or raise HTTPBadResponse, "wrong chunk size line: #{line}"
len = m[0].hex
break if len == 0
@socket.read( len, dest ); total += len
@@ -1004,44 +1173,27 @@ module Net
end
end
- def content_length( resp )
- if resp.key? 'content-length' then
- m = /\d+/.match( resp['content-length'] )
- unless m then
- raise HTTPBadResponse, 'wrong Content-Length format'
- end
- m[0].to_i
- else
- nil
- end
+ def stream_check
+ @socket.closed? and raise IOError, 'try to read body out of block'
end
- def chunked?( resp )
- tmp = resp['transfer-encoding']
- tmp and /(?:\A|\s+)chunked(?:\s+|\z)/i === tmp
- end
-
- def range_length( resp )
- if resp.key? 'content-range' then
- m = %r<bytes\s+(\d+)-(\d+)/\d+>.match( resp['content-range'] )
- unless m then
- raise HTTPBadResponse, 'wrong Content-Range format'
- end
- l = m[2].to_i
- u = m[1].to_i
- if l > u then
- nil
- else
- u - l
- end
+ def procdest( dest, block )
+ if dest and block then
+ raise ArgumentError, 'both of arg and block are given for HTTP method'
+ end
+ if block then
+ ::Net::NetPrivate::ReadAdapter.new block
else
- nil
+ dest || ''
end
end
end
+ }
+
- end # module Net::NetPrivate
+ HTTPResponse = NetPrivate::HTTPResponse
+ HTTPResponseReceiver = NetPrivate::HTTPResponse
end # module Net
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 34d324ed12..ea064d2552 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -7,9 +7,10 @@ Copyright (C) 2000 Shugo Maeda <shugo@ruby-lang.org>
This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this library.
-== class Net::IMAP
+== Net::IMAP
Net::IMAP implements Internet Message Access Protocol (IMAP) clients.
+(The protocol is described in ((<[IMAP]>)).)
=== Super Class
@@ -102,21 +103,24 @@ Object
: list(refname, mailbox)
Sends a LIST command, and returns a subset of names from
the complete set of all names available to the client.
+ The return value is an array of ((<Net::IMAP::MailboxList>)).
ex).
imap.create("foo/bar")
imap.create("foo/baz")
p imap.list("", "foo/%")
- #=> [#<Net::IMAP::MailboxList attr=[:NoSelect], delim="/", name="foo/">, #<Net::IMAP::MailboxList attr=[:NoInferiors, :Marked], delim="/", name="foo/bar">, #<Net::IMAP::MailboxList attr=[:NoInferiors], delim="/", name="foo/baz">]
+ #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
: lsub(refname, mailbox)
Sends a LSUB command, and returns a subset of names from the set
of names that the user has declared as being "active" or
"subscribed".
+ The return value is an array of ((<Net::IMAP::MailboxList>)).
: status(mailbox, attr)
Sends a STATUS command, and returns the status of the indicated
mailbox.
+ The return value is a hash of attributes.
ex).
p imap.status("inbox", ["MESSAGES", "RECENT"])
@@ -166,6 +170,7 @@ Object
in the mailbox. the set parameter is a number or an array of
numbers or a Range object. the number is a message sequence
number (fetch) or a unique identifier (uid_fetch).
+ The return value is an array of ((<Net::IMAP::FetchData>)).
ex).
p imap.fetch(6..8, "UID")
@@ -188,6 +193,7 @@ Object
in the mailbox. the set parameter is a number or an array of
numbers or a Range object. the number is a message sequence
number (store) or a unique identifier (uid_store).
+ The return value is an array of ((<Net::IMAP::FetchData>)).
ex).
p imap.store(6..8, "+FLAGS", [:Deleted])
@@ -210,6 +216,443 @@ Object
p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
#=> [6, 7, 8, 1]
+== Net::IMAP::ContinuationRequest
+
+Net::IMAP::ContinuationRequest represents command continuation requests.
+
+The command continuation request response is indicated by a "+" token
+instead of a tag. This form of response indicates that the server is
+ready to accept the continuation of a command from the client. The
+remainder of this response is a line of text.
+
+ continue_req ::= "+" SPACE (resp_text / base64)
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: data
+ Returns the data (Net::IMAP::ResponseText).
+
+: raw_data
+ Returns the raw data string.
+
+== Net::IMAP::UntaggedResponse
+
+Net::IMAP::UntaggedResponse represents untagged responses.
+
+Data transmitted by the server to the client and status responses
+that do not indicate command completion are prefixed with the token
+"*", and are called untagged responses.
+
+ response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
+ mailbox_data / message_data / capability_data)
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: name
+ Returns the name such as "FLAGS", "LIST", "FETCH"....
+
+: data
+ Returns the data such as an array of flag symbols,
+ a ((<Net::IMAP::MailboxList>)) object....
+
+: raw_data
+ Returns the raw data string.
+
+== Net::IMAP::TaggedResponse
+
+Net::IMAP::TaggedResponse represents tagged responses.
+
+The server completion result response indicates the success or
+failure of the operation. It is tagged with the same tag as the
+client command which began the operation.
+
+ response_tagged ::= tag SPACE resp_cond_state CRLF
+
+ tag ::= 1*<any ATOM_CHAR except "+">
+
+ resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: tag
+ Returns the tag.
+
+: name
+ Returns the name. the name is one of "OK", "NO", "BAD".
+
+: data
+ Returns the data. See ((<Net::IMAP::ResponseText>)).
+
+: raw_data
+ Returns the raw data string.
+
+== Net::IMAP::ResponseText
+
+Net::IMAP::ResponseText represents texts of responses.
+The text may be prefixed by the response code.
+
+ resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
+ ;; text SHOULD NOT begin with "[" or "="
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: code
+ Returns the response code. See ((<Net::IMAP::ResponseCode>)).
+
+: text
+ Returns the text.
+
+== Net::IMAP::ResponseCode
+
+Net::IMAP::ResponseCode represents response codes.
+
+ resp_text_code ::= "ALERT" / "PARSE" /
+ "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
+ "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
+ "UIDVALIDITY" SPACE nz_number /
+ "UNSEEN" SPACE nz_number /
+ atom [SPACE 1*<any TEXT_CHAR except "]">]
+
+=== SuperClass
+
+Struct
+
+=== Methods
+
+: name
+ Returns the name such as "ALERT", "PERMANENTFLAGS", "UIDVALIDITY"....
+
+: data
+ Returns the data if it exists.
+
+== Net::IMAP::MailboxList
+
+Net::IMAP::MailboxList represents contents of the LIST response.
+
+ mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
+ "\Noselect" / "\Unmarked" / flag_extension) ")"
+ SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: attr
+ Returns the name attributes. Each name attribute is a symbol
+ capitalized by String#capitalize, such as :Noselect (not :NoSelect).
+
+: delim
+ Returns the hierarchy delimiter
+
+: name
+ Returns the mailbox name.
+
+== Net::IMAP::StatusData
+
+Net::IMAP::StatusData represents contents of the STATUS response.
+
+=== Super Class
+
+Object
+
+=== Methods
+
+: mailbox
+ Returns the mailbox name.
+
+: attr
+ Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
+ "UIDVALIDITY", "UNSEEN". Each value is a number.
+
+== Net::IMAP::FetchData
+
+Net::IMAP::FetchData represents contents of the FETCH response.
+
+=== Super Class
+
+Object
+
+=== Methods
+
+: seqno
+ Returns the message sequence number.
+ (Note: not the unique identifier, even for the UID command response.)
+
+: attr
+ Returns a hash. Each key is a data item name, and each value is
+ its value.
+
+ The current data items are:
+
+ : BODY
+ A form of BODYSTRUCTURE without extension data.
+ : BODY[<section>]<<origin_octet>>
+ A string expressing the body contents of the specified section.
+ : BODYSTRUCTURE
+ An object that describes the ((<[MIME-IMB]>)) body structure of a message.
+ See ((<Net::IMAP::BodyTypeBasic>)), ((<Net::IMAP::BodyTypeText>)),
+ ((<Net::IMAP::BodyTypeMessage>)), ((<Net::IMAP::BodyTypeMultipart>)).
+ : ENVELOPE
+ A ((<Net::IMAP::Envelope>)) object that describes the envelope
+ structure of a message.
+ : FLAGS
+ A array of flag symbols that are set for this message. flag symbols
+ are capitalized by String#capitalize.
+ : INTERNALDATE
+ A string representing the internal date of the message.
+ : RFC822
+ Equivalent to BODY[].
+ : RFC822.HEADER
+ Equivalent to BODY.PEEK[HEADER].
+ : RFC822.SIZE
+ A number expressing the ((<[RFC-822]>)) size of the message.
+ : RFC822.TEXT
+ Equivalent to BODY[TEXT].
+ : UID
+ A number expressing the unique identifier of the message.
+
+== Net::IMAP::Envelope
+
+Net::IMAP::Envelope represents envelope structures of messages.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: date
+ Retunns a string that represents the date.
+
+: subject
+ Retunns a string that represents the subject.
+
+: from
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the from.
+
+: sender
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the sender.
+
+: reply_to
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the reply-to.
+
+: to
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the to.
+
+: cc
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the cc.
+
+: bcc
+ Retunns an array of ((<Net::IMAP::Address>)) that represents the bcc.
+
+: in_reply_to
+ Retunns a string that represents the in-reply-to.
+
+: message_id
+ Retunns a string that represents the message-id.
+
+== Net::IMAP::Address
+
+((<Net::IMAP::Address>)) represents electronic mail addresses.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: name
+ Returns the phrase from ((<[RFC-822]>)) mailbox.
+
+: route
+ Returns the route from ((<[RFC-822]>)) route-addr.
+
+: mailbox
+ nil indicates end of ((<[RFC-822]>)) group.
+ If non-nil and host is nil, returns ((<[RFC-822]>)) group name.
+ Otherwise, returns ((<[RFC-822]>)) local-part
+
+: host
+ nil indicates ((<[RFC-822]>)) group syntax.
+ Otherwise, returns ((<[RFC-822]>)) domain name.
+
+== Net::IMAP::ContentDisposition
+
+Net::IMAP::ContentDisposition represents Content-Disposition fields.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: dsp_type
+ Returns the disposition type.
+
+: param
+ Returns a hash that represents parameters of the Content-Disposition
+ field.
+
+== Net::IMAP::BodyTypeBasic
+
+Net::IMAP::BodyTypeBasic represents basic body structures of messages.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: media_type
+ Returns the content media type name as defined in ((<[MIME-IMB]>)).
+
+: subtype
+ Returns the content subtype name as defined in ((<[MIME-IMB]>)).
+
+: param
+ Returns a hash that represents parameters as defined in
+ ((<[MIME-IMB]>)).
+
+: content_id
+ Returns a string giving the content id as defined in ((<[MIME-IMB]>)).
+
+: description
+ Returns a string giving the content description as defined in
+ ((<[MIME-IMB]>)).
+
+: encoding
+ Returns a string giving the content transfer encoding as defined in
+ ((<[MIME-IMB]>)).
+
+: size
+ Returns a number giving the size of the body in octets.
+
+: md5
+ Returns a string giving the body MD5 value as defined in ((<[MD5]>)).
+
+: disposition
+ Returns a ((<Net::IMAP::ContentDisposition>)) object giving
+ the content disposition.
+
+: language
+ Returns a string or an array of strings giving the body
+ language value as defined in [LANGUAGE-TAGS].
+
+: extension
+ Returns extension data.
+
+: multipart?
+ Returns false.
+
+== Net::IMAP::BodyTypeText
+
+Net::IMAP::BodyTypeText represents TEXT body structures of messages.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: lines
+ Returns the size of the body in text lines.
+
+And Net::IMAP::BodyTypeText has all methods of ((<Net::IMAP::BodyTypeBasic>)).
+
+== Net::IMAP::BodyTypeMessage
+
+Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: envelope
+ Returns a ((<Net::IMAP::Envelope>)) giving the envelope structure.
+
+: body
+ Returns an object giving the body structure.
+
+And Net::IMAP::BodyTypeMessage has all methods of ((<Net::IMAP::BodyTypeText>)).
+
+== Net::IMAP::BodyTypeText
+
+=== Super Class
+
+Struct
+
+=== Methods
+
+: media_type
+ Returns the content media type name as defined in ((<[MIME-IMB]>)).
+
+: subtype
+ Returns the content subtype name as defined in ((<[MIME-IMB]>)).
+
+: parts
+ Returns multiple parts.
+
+: param
+ Returns a hash that represents parameters as defined in
+ ((<[MIME-IMB]>)).
+
+: disposition
+ Returns a ((<Net::IMAP::ContentDisposition>)) object giving
+ the content disposition.
+
+: language
+ Returns a string or an array of strings giving the body
+ language value as defined in [LANGUAGE-TAGS].
+
+: extension
+ Returns extension data.
+
+: multipart?
+ Returns true.
+
+== References
+
+: [IMAP]
+ M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
+ RFC 2060, December 1996.
+
+: [LANGUAGE-TAGS]
+ Alvestrand, H., "Tags for the Identification of
+ Languages", RFC 1766, March 1995.
+
+: [MD5]
+ Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC
+ 1864, October 1995.
+
+: [MIME-IMB]
+ Freed, N., and N. Borenstein, "MIME (Multipurpose Internet
+ Mail Extensions) Part One: Format of Internet Message Bodies", RFC
+ 2045, November 1996.
+
+: [RFC-822]
+ Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages", STD 11, RFC 822, University of Delaware, August 1982.
+
=end
require "socket"
@@ -702,7 +1145,7 @@ module Net
Address = Struct.new(:name, :route, :mailbox, :host)
ContentDisposition = Struct.new(:dsp_type, :param)
- class BodyTypeBasic < Struct.new(:media_type, :media_subtype,
+ class BodyTypeBasic < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
:md5, :disposition, :language,
@@ -710,9 +1153,15 @@ module Net
def multipart?
return false
end
+
+ def media_subtype
+ $stderr.printf("warning: media_subtype is obsolete.\n")
+ $stderr.printf(" use subtype instead.\n")
+ return subtype
+ end
end
- class BodyTypeText < Struct.new(:media_type, :media_subtype,
+ class BodyTypeText < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
:lines,
@@ -721,9 +1170,15 @@ module Net
def multipart?
return false
end
+
+ def media_subtype
+ $stderr.printf("warning: media_subtype is obsolete.\n")
+ $stderr.printf(" use subtype instead.\n")
+ return subtype
+ end
end
- class BodyTypeMessage < Struct.new(:media_type, :media_subtype,
+ class BodyTypeMessage < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
:envelope, :body, :lines,
@@ -732,15 +1187,27 @@ module Net
def multipart?
return false
end
+
+ def media_subtype
+ $stderr.printf("warning: media_subtype is obsolete.\n")
+ $stderr.printf(" use subtype instead.\n")
+ return subtype
+ end
end
- class BodyTypeMultipart < Struct.new(:media_type, :media_subtype,
+ class BodyTypeMultipart < Struct.new(:media_type, :subtype,
:parts,
:param, :disposition, :language,
:extension)
def multipart?
return true
end
+
+ def media_subtype
+ $stderr.printf("warning: media_subtype is obsolete.\n")
+ $stderr.printf(" use subtype instead.\n")
+ return subtype
+ end
end
class ResponseParser
@@ -1475,6 +1942,12 @@ module Net
when /\A(?:UIDVALIDITY|UIDNEXT|UNSEEN)\z/n
match(T_SPACE)
result = ResponseCode.new(name, number)
+ else
+ match(T_SPACE)
+ @lex_state = EXPR_CTEXT
+ token = match(T_TEXT)
+ @lex_state = EXPR_BEG
+ result = ResponseCode.new(name, token.value)
end
match(T_RBRA)
@lex_state = EXPR_RTEXT
@@ -1579,7 +2052,7 @@ module Net
if @str.index(/\(([^)]*)\)/ni, @pos)
@pos = $~.end(0)
return $1.scan(FLAG_REGEXP).collect { |flag, atom|
- atom || flag.intern
+ atom || flag.capitalize.intern
}
else
parse_error("invalid flag list")
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 4f6eb930a4..8f3f978e8c 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -1,6 +1,6 @@
=begin
-= net/pop.rb version 1.1.32
+= net/pop.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -184,6 +184,7 @@ module Net
protocol_param :port, '110'
protocol_param :command_type, '::Net::NetPrivate::POP3Command'
+ protocol_param :apop_command_type, '::Net::NetPrivate::APOPCommand'
protocol_param :mail_type, '::Net::POPMail'
@@ -206,9 +207,10 @@ module Net
end
- def initialize( addr = nil, port = nil )
- super
+ def initialize( addr = nil, port = nil, apop = false )
+ super addr, port
@mails = nil
+ @apop = false
end
attr :mails
@@ -238,6 +240,11 @@ module Net
private
+ def conn_command( sock )
+ @command =
+ (@apop ? type.apop_command_type : type.command_type).new(sock)
+ end
+
def do_start( acnt, pwd )
@command.auth( acnt, pwd )
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index 161024cfe2..343721add3 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -1,6 +1,6 @@
=begin
-= net/protocol.rb version 1.1.32
+= net/protocol.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -59,13 +59,22 @@ Object
=end
require 'socket'
+require 'timeout'
module Net
+ module NetPrivate
+ end
+
+ def self.net_private( &block )
+ ::Net::NetPrivate.module_eval( &block )
+ end
+
+
class Protocol
- Version = '1.1.32'
+ Version = '1.1.34'
class << self
@@ -116,8 +125,12 @@ module Net
@command = nil
@socket = nil
- @active = false
- @pipe = nil
+ @active = false
+
+ @open_timeout = nil
+ @read_timeout = nil
+
+ @dout = nil
end
attr_reader :address
@@ -126,10 +139,26 @@ module Net
attr_reader :command
attr_reader :socket
+ attr_accessor :open_timeout
+ attr_accessor :read_timeout
+
+ def active?
+ @active
+ end
+
+ def set_debug_output( arg ) # un-documented
+ @dout = arg
+ end
+
+ alias set_pipe set_debug_output
+
def inspect
"#<#{type} #{address}:#{port} open=#{active?}>"
end
+ #
+ # open session
+ #
def start( *args )
return false if active?
@@ -146,45 +175,59 @@ module Net
end
end
+ private
+
def _start( args )
connect
do_start( *args )
@active = true
end
- private :_start
-
- def finish
- return false unless active?
- do_finish unless @command.critical?
- disconnect
- @active = false
- true
+ def connect
+ conn_socket @address, @port
+ conn_command @socket
+ on_connect
end
- def active?
- @active
+ def re_connect
+ @socket.reopen @open_timeout
+ on_connect
end
- def set_pipe( arg ) # un-documented
- @pipe = arg
+ def conn_socket( addr, port )
+ @socket = type.socket_type.open(
+ addr, port, @open_timeout, @read_timeout, @dout )
end
+ def conn_command( sock )
+ @command = type.command_type.new( sock )
+ end
- private
-
+ def on_connect
+ end
def do_start
end
- def do_finish
- @command.quit
+ #
+ # close session
+ #
+
+ public
+
+ def finish
+ return false unless active?
+
+ do_finish if @command and not @command.critical?
+ disconnect
+ @active = false
+ true
end
+ private
- def connect( addr = @address, port = @port )
- @socket = type.socket_type.open( addr, port, @pipe )
- @command = type.command_type.new( @socket )
+ def do_finish
+ @command.quit
end
def disconnect
@@ -192,7 +235,11 @@ module Net
if @socket and not @socket.closed? then
@socket.close
end
- @socket = nil
+ @socket = nil
+ on_disconnect
+ end
+
+ def on_disconnect
end
end
@@ -200,6 +247,7 @@ module Net
Session = Protocol
+ net_private {
class Response
@@ -223,6 +271,8 @@ module Net
end
+ }
+
class ProtocolError < StandardError; end
class ProtoSyntaxError < ProtocolError; end
@@ -294,8 +344,7 @@ module Net
- module NetPrivate
-
+ net_private {
class WriteAdapter
@@ -311,7 +360,11 @@ module Net
def write( str )
@sock.__send__ @mid, str
end
- alias << write
+
+ def <<( str )
+ @sock.__send__ @mid, str
+ self
+ end
end
@@ -407,6 +460,7 @@ module Net
@critical = false
end
+
private
def critical
@@ -431,22 +485,30 @@ module Net
class Socket
- def initialize( addr, port, pipe = nil )
+ def initialize( addr, port, otime = nil, rtime = nil, dout = nil )
@addr = addr
@port = port
- @pipe = pipe
- @prepipe = nil
- @closed = true
- @ipaddr = ''
+ @read_timeout = rtime
+
+ @debugout = dout
+
+ @socket = nil
@sending = ''
@buffer = ''
- @socket = TCPsocket.new( addr, port )
- @closed = false
- @ipaddr = @socket.addr[3]
+ connect otime
+ D 'opened'
end
+ def connect( otime )
+ D "opening connection to #{@addr}..."
+ timeout( otime ) {
+ @socket = TCPsocket.new( @addr, @port )
+ }
+ end
+ private :connect
+
attr :pipe, true
class << self
@@ -454,27 +516,31 @@ module Net
end
def inspect
- "#<#{type} open=#{!@closed}>"
+ "#<#{type} #{closed? ? 'closed' : 'opened'}>"
end
- def reopen
- unless closed? then
- close
- @buffer = ''
- end
- @socket = TCPsocket.new( @addr, @port )
- @closed = false
+ def reopen( otime = nil )
+ D 'reopening...'
+ close
+ connect otime
+ D 'reopened'
end
attr :socket, true
def close
- @socket.close
- @closed = true
+ if @socket then
+ @socket.close
+ D 'closed'
+ else
+ D 'close call for already closed socket'
+ end
+ @socket = nil
+ @buffer = ''
end
def closed?
- @closed
+ not @socket
end
def address
@@ -486,7 +552,8 @@ module Net
attr_reader :port
def ip_address
- @ipaddr.dup
+ @socket or return ''
+ @socket.addr[3]
end
alias ipaddr ip_address
@@ -494,57 +561,64 @@ module Net
attr_reader :sending
- ###
- ### read
- ###
+ #
+ # read
+ #
+
+ public
CRLF = "\r\n"
- def read( len, dest = '' )
- @pipe << "reading #{len} bytes...\n" if @pipe; pipeoff
+ def read( len, dest = '', ignerr = false )
+ D_off "reading #{len} bytes..."
rsize = 0
- while rsize + @buffer.size < len do
- rsize += writeinto( dest, @buffer.size )
- fill_rbuf
+ begin
+ while rsize + @buffer.size < len do
+ rsize += rbuf_moveto( dest, @buffer.size )
+ rbuf_fill
+ end
+ rbuf_moveto dest, len - rsize
+ rescue EOFError
+ raise unless igneof
end
- writeinto( dest, len - rsize )
- @pipe << "read #{len} bytes\n" if pipeon
+ D_on "read #{len} bytes"
dest
end
-
def read_all( dest = '' )
- @pipe << "reading all...\n" if @pipe; pipeoff
+ D_off 'reading all...'
rsize = 0
begin
while true do
- rsize += writeinto( dest, @buffer.size )
- fill_rbuf
+ rsize += rbuf_moveto( dest, @buffer.size )
+ rbuf_fill
end
rescue EOFError
;
end
- @pipe << "read #{rsize} bytes\n" if pipeon
+ D_on "read #{rsize} bytes"
dest
end
-
- def readuntil( target )
- while true do
- idx = @buffer.index( target )
- break if idx
- fill_rbuf
- end
-
+ def readuntil( target, igneof = false )
dest = ''
- writeinto( dest, idx + target.size )
+ begin
+ while true do
+ idx = @buffer.index( target )
+ break if idx
+ rbuf_fill
+ end
+ rbuf_moveto dest, idx + target.size
+ rescue EOFError
+ raise unless igneof
+ rbuf_moveto dest, @buffer.size
+ end
dest
end
-
def readline
ret = readuntil( "\n" )
@@ -552,9 +626,8 @@ module Net
ret
end
-
def read_pendstr( dest )
- @pipe << "reading text...\n" if @pipe; pipeoff
+ D_off 'reading text...'
rsize = 0
while (str = readuntil("\r\n")) != ".\r\n" do
@@ -563,14 +636,13 @@ module Net
dest << str
end
- @pipe << "read #{rsize} bytes\n" if pipeon
+ D_on "read #{rsize} bytes"
dest
end
-
# private use only (can not handle 'break')
def read_pendlist
- @pipe << "reading list...\n" if @pipe; pipeoff
+ D_off 'reading list...'
str = nil
i = 0
@@ -580,55 +652,59 @@ module Net
yield str
end
- @pipe << "read #{i} items\n" if pipeon
+ D_on "read #{i} items"
end
private
- READ_BLOCK = 1024 * 8
+ READ_SIZE = 1024 * 4
- def fill_rbuf
- @buffer << @socket.sysread( READ_BLOCK )
+ def rbuf_fill
+ unless IO.select [@socket], nil, nil, @read_timeout then
+ on_read_timeout
+ end
+ @buffer << @socket.sysread( READ_SIZE )
end
- def writeinto( dest, len )
+ def on_read_timeout
+ raise TimeoutError, "socket read timeout (#{@read_timeout} sec)"
+ end
+
+ def rbuf_moveto( dest, len )
bsi = @buffer.size
- dest << @buffer[ 0, len ]
+ s = @buffer[ 0, len ]
+ dest << s
@buffer = @buffer[ len, bsi - len ]
- @pipe << %{read "#{Net.quote dest}"\n} if @pipe
+ @debugout << %<read "#{Net.quote s}"\n> if @debugout
len
end
- ###
- ### write
- ###
+ #
+ # write interfece
+ #
public
-
def write( str )
writing {
do_write str
}
end
-
def writeline( str )
writing {
- do_write str
- do_write "\r\n"
+ do_write str + "\r\n"
}
end
-
def write_bin( src, block )
writing {
if block then
- block.call WriteAdapter.new( self, :do_write )
+ block.call ::Net::NetPrivate::WriteAdapter.new( self, :do_write )
else
src.each do |bin|
do_write bin
@@ -637,19 +713,18 @@ module Net
}
end
-
def write_pendstr( src, block )
- @pipe << "writing text from #{src.type}\n" if @pipe; pipeoff
+ D_off "writing text from #{src.type}"
wsize = use_each_crlf_line {
if block then
- block.call WriteAdapter.new( self, :wpend_in )
+ block.call ::Net::NetPrivate::WriteAdapter.new( self, :wpend_in )
else
wpend_in src
end
}
- @pipe << "wrote #{wsize} bytes text\n" if pipeon
+ D_on "wrote #{wsize} bytes text"
wsize
end
@@ -696,17 +771,17 @@ module Net
beg = 0
buf = @wbuf
while buf.index( /\n|\r\n|\r/, beg ) do
- m = $~
+ m = Regexp.last_match
if m.begin(0) == buf.size - 1 and buf[-1] == ?\r then
# "...\r" : can follow "\n..."
break
end
- str = buf[ beg, m.begin(0) - beg ]
+ str = buf[ beg ... m.begin(0) ]
str.concat "\r\n"
yield str
beg = m.end(0)
end
- @wbuf = buf[ beg, buf.size - beg ]
+ @wbuf = buf[ beg ... buf.size ]
end
end
@@ -736,6 +811,7 @@ module Net
yield
end
end
+ yield unless @wbuf.empty?
end
end
@@ -746,17 +822,17 @@ module Net
yield
- if @pipe then
- @pipe << 'write "'
- @pipe << @sending
- @pipe << "\"\n"
+ if @debugout then
+ @debugout << 'write "'
+ @debugout << @sending
+ @debugout << "\"\n"
end
@socket.flush
@writtensize
end
def do_write( arg )
- if @pipe or @sending.size < 128 then
+ if @debugout or @sending.size < 128 then
@sending << Net.quote( arg )
else
@sending << '...' unless @sending[-1] == ?.
@@ -768,22 +844,25 @@ module Net
end
- def pipeoff
- @prepipe = @pipe
- @pipe = nil
- @prepipe
+ def D_off( msg )
+ D msg
+ @savedo, @debugout = @debugout, nil
end
- def pipeon
- @pipe = @prepipe
- @prepipe = nil
- @pipe
+ def D_on( msg )
+ @debugout = @savedo
+ D msg
end
- end
+ def D( msg )
+ @debugout or return
+ @debugout << msg
+ @debugout << "\n"
+ end
+ end
- end # module Net::NetPrivate
+ }
def Net.quote( str )
diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb
index 9679984e2c..befc1adf03 100644
--- a/lib/net/smtp.rb
+++ b/lib/net/smtp.rb
@@ -1,6 +1,6 @@
=begin
-= net/smtp.rb version 1.1.32
+= net/smtp.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -30,10 +30,8 @@ Net::Protocol
=== Methods
-: start( helo_domain = Socket.gethostname, \
- account = nil, password = nil, authtype = nil )
-: start( helo_domain = Socket.gethostname, \
- account = nil, password = nil, authtype = nil ) {|smtp| .... }
+: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil )
+: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil ) {|smtp| .... }
opens TCP connection and starts SMTP session.
If protocol had been started, do nothing and return false.
@@ -53,10 +51,10 @@ Net::Protocol
to_addrs must be a String(s) or an Array of String.
Exceptions which SMTP raises are:
- * Net::ProtoSyntaxError: syntax error (errno.500)
- * Net::ProtoFatalError: fatal error (errno.550)
- * Net::ProtoUnknownError: unknown error
- * Net::ProtoServerBusy: temporary error (errno.420/450)
+ * Net::ProtoSyntaxError: syntax error (errno.500)
+ * Net::ProtoFatalError: fatal error (errno.550)
+ * Net::ProtoUnknownError: unknown error
+ * Net::ProtoServerBusy: temporary error (errno.420/450)
# usage example
@@ -153,12 +151,15 @@ module Net
end
end
- if user and secret then
+ if user or secret then
+ (user and secret) or
+ raise ArgumentError, 'both of account and password are required'
+
mid = 'auth_' + (authtype || 'cram_md5').to_s
- unless @command.respond_to? mid then
- raise ArgumentError, "wrong auth type #{authtype.to_s}"
- end
- @command.send mid, user, secret
+ @command.respond_to? mid or
+ raise ArgumentError, "wrong auth type #{authtype.to_s}"
+
+ @command.__send__ mid, user, secret
end
end
diff --git a/lib/net/telnet.rb b/lib/net/telnet.rb
index 87790c0300..380e834bea 100644
--- a/lib/net/telnet.rb
+++ b/lib/net/telnet.rb
@@ -4,7 +4,7 @@
net/telnet.rb - simple telnet client library
-Version 1.6.2
+Version 1.6.3
Wakou Aoyama <wakou@fsinet.or.jp>
@@ -239,10 +239,11 @@ module Net
CR = "\015"
LF = "\012"
EOL = CR + LF
- VERSION = "1.6.2"
- RELEASE_DATE = "2000-12-25"
- VERSION_CODE = 162
- RELEASE_CODE = 20001225
+ VERSION = '1.6.3'
+ RELEASE_DATE = '2001-02-26'
+ VERSION_CODE = 163
+ RELEASE_CODE = 20010226
+ REVISION = '$Id$'
def initialize(options)
@options = options
@@ -346,14 +347,13 @@ module Net
attr :sock
def telnetmode(mode = nil)
- if mode
- if (true == mode or false == mode)
- @options["Telnetmode"] = mode
- else
- raise ArgumentError, "required true or false"
- end
- else
+ case mode
+ when nil
@options["Telnetmode"]
+ when true, false
+ @options["Telnetmode"] = mode
+ else
+ raise ArgumentError, "required true or false"
end
end
@@ -366,14 +366,13 @@ module Net
end
def binmode(mode = nil)
- if mode
- if (true == mode or false == mode)
- @options["Binmode"] = mode
- else
- raise ArgumentError, "required true or false"
- end
- else
+ case mode
+ when nil
@options["Binmode"]
+ when true, false
+ @options["Binmode"] = mode
+ else
+ raise ArgumentError, "required true or false"
end
end
@@ -599,181 +598,7 @@ end
== HISTORY
-* Mon Dec 25 01:37:43 JST 2000 - wakou
- * version 1.6.2
- * Regexp::last_match[1] --> $1
-
-* Mon Dec 11 00:16:51 JST 2000 - wakou
- * version 1.6.1
- * $1 --> Regexp::last_match[1]
-
-* 2000/09/12 05:37:35 - matz
- * change: iterator? --> block_given?
-
-* Tue Sep 12 06:52:48 JST 2000 - wakou
- * version 1.6.0
- * correct: document.
- thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
- * add: Telnet#puts().
-
-* Sun Jun 18 23:31:44 JST 2000 - wakou
- * version 1.5.0
- * change: version syntax. old: x.yz, now: x.y.z
-
-* 2000/05/24 06:57:38 - wakou
- * version 1.40
- * improve: binmode(), telnetmode() interface.
- thanks to Dave Thomas <Dave@thomases.com>
-
-* 2000/05/09 22:02:56 - wakou
- * version 1.32
- * require English.rb
-
-* 2000/05/02 21:48:39 - wakou
- * version 1.31
- * Proxy option: can receive IO object.
-
-* 2000/04/03 18:27:02 - wakou
- * version 1.30
- * telnet.rb --> net/telnet.rb
-
-* 2000/01/24 17:02:57 - wakou
- * version 1.20
- * respond to "IAC WILL x" with "IAC DONT x"
- * respond to "IAC WONT x" with "IAC DONT x"
- * better dumplog format.
- thanks to WATANABE Hirofumi <Hirofumi.Watanabe@jp.sony.com>
-
-* 2000/01/18 17:47:31 - wakou
- * version 1.10
- * bug fix: write method
- * respond to "IAC WILL BINARY" with "IAC DO BINARY"
-
-* 1999/10/04 22:51:26 - wakou
- * version 1.00
- * bug fix: waitfor(preprocess) method.
- thanks to Shin-ichiro Hara <sinara@blade.nagaokaut.ac.jp>
- * add simple support for AO, DM, IP, NOP, SB, SE
- * COUTION! TimeOut --> TimeoutError
-
-* 1999/09/21 21:24:07 - wakou
- * version 0.50
- * add write method
-
-* 1999/09/17 17:41:41 - wakou
- * version 0.40
- * bug fix: preprocess method
-
-* 1999/09/14 23:09:05 - wakou
- * version 0.30
- * change prompt check order.
- not IO::select([@sock], nil, nil, waittime) and prompt === line
- --> prompt === line and not IO::select([@sock], nil, nil, waittime)
-
-* 1999/09/13 22:28:33 - wakou
- * version 0.24
- * Telnet#login: if ommit password, then not require password prompt.
-
-* 1999/08/10 05:20:21 - wakou
- * version 0.232
- * STATUS OUTPUT sample code typo.
- thanks to Tadayoshi Funaba <tadf@kt.rim.or.jp>
- host = Telnet.new({"Hosh" => "localhost"){|c| print c }
- --> host = Telnet.new({"Host" => "localhost"){|c| print c }
-
-* 1999/07/16 13:39:42 - wakou
- * version 0.231
- * TRUE --> true, FALSE --> false
-
-* 1999/07/15 22:32:09 - wakou
- * version 0.23
- * waitfor: if end of file reached, then return nil.
-
-* 1999/06/29 09:08:51 - wakou
- * version 0.22
- * new, waitfor, cmd: {"Timeout" => false} # ignore timeout
-
-* 1999/06/28 18:18:55 - wakou
- * version 0.21
- * waitfor: not rescue (EOFError)
-
-* 1999/06/04 06:24:58 - wakou
- * version 0.20
- * waitfor: support for divided telnet command
-
-* 1999/05/22 - wakou
- * version 0.181
- * bug fix: print method
-
-* 1999/05/14 - wakou
- * version 0.18
- * respond to "IAC WON'T SGA" with "IAC DON'T SGA"
- * DON'T SGA : end of line --> CR + LF
- * bug fix: preprocess method
-
-* 1999/04/30 - wakou
- * version 0.17
- * bug fix: $! + "\n" --> $!.to_s + "\n"
-
-* 1999/04/11 - wakou
- * version 0.163
- * STDOUT.write(message) --> yield(message) if iterator?
-
-* 1999/03/17 - wakou
- * version 0.162
- * add "Proxy" option
- * required timeout.rb
-
-* 1999/02/03 - wakou
- * version 0.161
- * select --> IO::select
-
-* 1998/10/09 - wakou
- * version 0.16
- * preprocess method change for the better
- * add binmode method.
- * change default Binmode. TRUE --> FALSE
-
-* 1998/10/04 - wakou
- * version 0.15
- * add telnetmode method.
-
-* 1998/09/22 - wakou
- * version 0.141
- * change default prompt. /[$%#>] $/ --> /[$%#>] \Z/
-
-* 1998/09/01 - wakou
- * version 0.14
- * IAC WILL SGA send EOL --> CR+NULL
- * IAC WILL SGA IAC DO BIN send EOL --> CR
- * NONE send EOL --> LF
- * add Dump_log option.
-
-* 1998/08/25 - wakou
- * version 0.13
- * add print method.
-
-* 1998/08/05 - wakou
- * version 0.122
- * support for HP-UX 10.20.
- thanks to WATANABE Tetsuya <tetsu@jpn.hp.com>
- * socket.<< --> socket.write
-
-* 1998/07/15 - wakou
- * version 0.121
- * string.+= --> string.concat
-
-* 1998/06/01 - wakou
- * version 0.12
- * add timeout, waittime.
-
-* 1998/04/21 - wakou
- * version 0.11
- * add realtime output.
-
-* 1998/04/13 - wakou
- * version 0.10
- * first release.
-
-$Date$
+delete. see cvs log.
+
+
=end
diff --git a/lib/observer.rb b/lib/observer.rb
index 08e75f5125..e1b249e885 100644
--- a/lib/observer.rb
+++ b/lib/observer.rb
@@ -5,7 +5,7 @@
module Observable
def add_observer(observer)
@observer_peers = [] unless defined? @observer_peers
- unless defined? observer.update
+ unless observer.respond_to? :update
raise NameError, "observer needs to respond to `update'"
end
@observer_peers.push observer
diff --git a/lib/parsedate.rb b/lib/parsedate.rb
index eee114acb2..7fc75cf0c2 100644
--- a/lib/parsedate.rb
+++ b/lib/parsedate.rb
@@ -1,5 +1,5 @@
-# parsedate.rb: Written by Tadayoshi Funaba 2000
-# $Id: parsedate.rb,v 1.2 2000-04-01 12:16:56+09 tadf Exp $
+# parsedate3.rb: Written by Tadayoshi Funaba 2000, 2001
+# $Id: parsedate3.rb,v 1.3 2001-01-18 12:09:47+09 tadf Exp $
module ParseDate
@@ -46,7 +46,12 @@ module ParseDate
hour = $1.to_i
min = $2.to_i
sec = $3.to_i if $3
- hour += 12 if $4 and $4.downcase == 'p'
+ if $4
+ hour %= 12
+ if $4.downcase == 'p'
+ hour += 12
+ end
+ end
zone = $5
end
diff --git a/lib/ping.rb b/lib/ping.rb
index 48657818cc..d698dd0c52 100644
--- a/lib/ping.rb
+++ b/lib/ping.rb
@@ -47,6 +47,8 @@ module Ping
s = TCPsocket.new(host, service)
s.close
end
+ rescue Errno::ECONNREFUSED
+ return true
rescue
return false
end
diff --git a/lib/thread.rb b/lib/thread.rb
index d4b6ad6ec1..559cd95a8a 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -185,7 +185,7 @@ class Queue
end
end
def shift(non_block=false)
- pop(non_block=false)
+ pop(non_block)
end
alias deq shift
diff --git a/marshal.c b/marshal.c
index cf84e5ed24..1f0efa8843 100644
--- a/marshal.c
+++ b/marshal.c
@@ -14,7 +14,7 @@
#include "rubyio.h"
#include "st.h"
-#ifndef atof
+#if !defined(atof) && !defined(HAVE_STDLIB_H)
double strtod();
#endif
@@ -46,7 +46,7 @@ shortlen(len, ds)
num = SHORTDN(num);
offset++;
}
- return len*sizeof(BDIGIT)/sizeof(short) - offset;
+ return (len - 1)*sizeof(BDIGIT)/sizeof(short) + offset;
}
#define SHORTLEN(x) shortlen((x),d)
#endif
@@ -378,7 +378,7 @@ w_object(obj, arg, limit)
for (i=0; i<SIZEOF_BDIGITS; i+=sizeof(short)) {
w_short(num & SHORTMASK, arg);
num = SHORTDN(num);
- if (num == 0) break;
+ if (len == 0 && num == 0) break;
}
#else
w_short(*d, arg);
@@ -823,7 +823,11 @@ r_object(arg)
OBJSETUP(big, rb_cBignum, T_BIGNUM);
big->sign = (r_byte(arg) == '+');
len = r_long(arg);
+#if SIZEOF_BDIGITS == SIZEOF_SHORT
+ big->len = len;
+#else
big->len = (len + 1) * sizeof(short) / sizeof(BDIGIT);
+#endif
big->digits = digits = ALLOC_N(BDIGIT, big->len);
while (len > 0) {
#if SIZEOF_BDIGITS > SIZEOF_SHORT
@@ -1055,7 +1059,7 @@ marshal_load(argc, argv)
\tformat version %d.%d required; %d.%d given",
MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
}
- if (minor != MARSHAL_MINOR) {
+ if (ruby_verbose && minor != MARSHAL_MINOR) {
rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
diff --git a/math.c b/math.c
index ac87b9c8dc..2cac83e938 100644
--- a/math.c
+++ b/math.c
@@ -64,6 +64,11 @@ math_exp(obj, x)
return rb_float_new(exp(RFLOAT(x)->value));
}
+#if defined __CYGWIN__
+#define log(x) ((x) < 0.0 ? nan() : log(x))
+#define log10(x) ((x) < 0.0 ? nan() : log10(x))
+#endif
+
static VALUE
math_log(obj, x)
VALUE obj, x;
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index c0754efad4..7dd4708176 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -749,7 +749,7 @@ An end of a defun is found by moving forward from the beginning of one."
'("^\\s *def\\s +\\([^( ]+\\)"
1 font-lock-function-name-face)
;; symbols
- '("\\(^\\|[^:]\\)\\(:\\(\\w\\|_\\)+\\??\\)\\b"
+ '("\\(^\\|[^:]\\)\\(:\\([-+/%&|^~`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|\\[\\]\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b\\)\\)\\)"
2 font-lock-reference-face))
"*Additional expressions to highlight in ruby mode."))
diff --git a/missing/dir.h b/missing/dir.h
index 830239b3ea..4fe0e120d5 100644
--- a/missing/dir.h
+++ b/missing/dir.h
@@ -28,7 +28,9 @@
#ifndef __DIR_INCLUDED
#define __DIR_INCLUDED
-#if !defined __MINGW32__
+#if defined __MINGW32__
+#define cdecl
+#endif
/*Directory entry size */
#ifdef DIRSIZ
#undef DIRSIZ
@@ -61,5 +63,4 @@ void seekdir(DIR *dirp,long loc);
void rewinddir(DIR *dirp);
void closedir(DIR *dirp);
-#endif
#endif /* __DIR_INCLUDED */
diff --git a/missing/flock.c b/missing/flock.c
index 78576d438c..c828fcc7ad 100644
--- a/missing/flock.c
+++ b/missing/flock.c
@@ -1,6 +1,55 @@
#include "config.h"
-#if defined(HAVE_LOCKF)
+#if defined HAVE_FCNTL && defined HAVE_FCNTL_H
+
+/* These are the flock() constants. Since this sytems doesn't have
+ flock(), the values of the constants are probably not available.
+*/
+# ifndef LOCK_SH
+# define LOCK_SH 1
+# endif
+# ifndef LOCK_EX
+# define LOCK_EX 2
+# endif
+# ifndef LOCK_NB
+# define LOCK_NB 4
+# endif
+# ifndef LOCK_UN
+# define LOCK_UN 8
+# endif
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+int
+flock(fd, operation)
+ int fd;
+ int operation;
+{
+ struct flock lock;
+
+ switch (operation & ~LOCK_NB) {
+ case LOCK_SH:
+ lock.l_type = F_RDLCK;
+ break;
+ case LOCK_EX:
+ lock.l_type = F_WRLCK;
+ break;
+ case LOCK_UN:
+ lock.l_type = F_UNLCK;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ lock.l_whence = SEEK_SET;
+ lock.l_start = lock.l_len = 0L;
+
+ return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lock);
+}
+
+#elif defined(HAVE_LOCKF)
#include <unistd.h>
#include <errno.h>
@@ -45,86 +94,33 @@ flock(fd, operation)
int fd;
int operation;
{
- int i;
switch (operation) {
/* LOCK_SH - get a shared lock */
case LOCK_SH:
+ rb_notimplement();
+ return -1;
/* LOCK_EX - get an exclusive lock */
case LOCK_EX:
- i = lockf (fd, F_LOCK, 0);
- break;
+ return lockf (fd, F_LOCK, 0);
/* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
case LOCK_SH|LOCK_NB:
+ rb_notimplement();
+ return -1;
/* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
case LOCK_EX|LOCK_NB:
- i = lockf (fd, F_TLOCK, 0);
- if (i == -1)
- if ((errno == EAGAIN) || (errno == EACCES))
- errno = EWOULDBLOCK;
- break;
+ return lockf (fd, F_TLOCK, 0);
/* LOCK_UN - unlock */
case LOCK_UN:
- i = lockf (fd, F_ULOCK, 0);
- break;
+ return lockf (fd, F_ULOCK, 0);
/* Default - can't decipher operation */
default:
- i = -1;
errno = EINVAL;
- break;
+ return -1;
}
- return i;
-}
-#elif defined HAVE_FCNTL && defined HAVE_FCNTL_H
-
-/* These are the flock() constants. Since this sytems doesn't have
- flock(), the values of the constants are probably not available.
-*/
-# ifndef LOCK_SH
-# define LOCK_SH 1
-# endif
-# ifndef LOCK_EX
-# define LOCK_EX 2
-# endif
-# ifndef LOCK_NB
-# define LOCK_NB 4
-# endif
-# ifndef LOCK_UN
-# define LOCK_UN 8
-# endif
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-int
-flock(fd, operation)
- int fd;
- int operation;
-{
- struct flock lock;
-
- switch (operation & ~LOCK_NB) {
- case LOCK_SH:
- lock.l_type = F_RDLCK;
- break;
- case LOCK_EX:
- lock.l_type = F_WRLCK;
- break;
- case LOCK_UN:
- lock.l_type = F_UNLCK;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
-
- return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lock);
}
#elif !defined NT
int
diff --git a/missing/strftime.c b/missing/strftime.c
index 6bce490249..3042649aeb 100644
--- a/missing/strftime.c
+++ b/missing/strftime.c
@@ -113,12 +113,6 @@ extern char *getenv();
extern char *strchr();
#endif
-#ifdef __GNUC__
-#define inline __inline__
-#else
-#define inline /**/
-#endif
-
#define range(low, item, hi) max(low, min(item, hi))
#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
index d297209d06..489bf58361 100644
--- a/missing/vsnprintf.c
+++ b/missing/vsnprintf.c
@@ -108,9 +108,7 @@
#define __const
#endif /* People who don't like const sys_error */
-#if defined NT && !defined __MINGW32__
-typedef long size_t;
-#endif
+#include <stddef.h>
#ifndef NULL
#define NULL 0
@@ -1095,8 +1093,6 @@ vsnprintf(str, n, fmt, ap)
static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <stddef.h>
-
#if defined(__STDC__)
# include <stdarg.h>
#else
diff --git a/mkconfig.rb b/mkconfig.rb
index 175a4c3b15..c190861b5e 100644
--- a/mkconfig.rb
+++ b/mkconfig.rb
@@ -28,11 +28,11 @@ has_srcdir = false
has_version = false
File.foreach "config.status" do |$_|
next if /^#/
- if /^s%@program_transform_name@%s,(.*)%g$/
+ if /^s[%,]@program_transform_name@[%,]s,(.*)[%,]/
next if $install_name
ptn = $1.sub(/\$\$/, '$').split(/,/) #'
v_fast << " CONFIG[\"ruby_install_name\"] = \"" + "ruby".sub(ptn[0],ptn[1]) + "\"\n"
- elsif /^s%@(\w+)@%(.*)%g/
+ elsif /^s[%,]@(\w+)@[%,](.*)[%,]/
name = $1
val = $2 || ""
next if name =~ /^(INSTALL|DEFS|configure_input|srcdir|top_srcdir)$/
@@ -48,19 +48,6 @@ File.foreach "config.status" do |$_|
v_others << v
end
has_version = true if name == "MAJOR"
- if /DEFS/
- val.split(/\s*-D/).each do |i|
- if i =~ /(.*)=(\\")?([^\\]*)(\\")?/
- key, val = $1, $3
- if val == '1'
- val = "TRUE"
- else
- val.sub! /^\s*(.*)\s*$/, '"\1"'
- end
- print " CONFIG[\"#{key}\"] = #{val}\n"
- end
- end
- end
elsif /^ac_given_srcdir=(.*)/
v_fast << " CONFIG[\"srcdir\"] = \"" + File.expand_path($1) + "\"\n"
has_srcdir = true
diff --git a/node.h b/node.h
index 1904a0a072..4788f8bc95 100644
--- a/node.h
+++ b/node.h
@@ -21,6 +21,7 @@ enum node_type {
NODE_METHOD,
NODE_FBODY,
NODE_CFUNC,
+ NODE_IFUNC,
NODE_SCOPE,
NODE_BLOCK,
NODE_IF,
@@ -234,8 +235,9 @@ typedef struct RNode {
#define NEW_DEFN(i,a,d,p) rb_node_newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d))
#define NEW_DEFS(r,i,a,d) rb_node_newnode(NODE_DEFS,r,i,NEW_RFUNC(a,d))
#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)
@@ -307,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)
diff --git a/numeric.c b/numeric.c
index 0dd86f0532..b5cd479a57 100644
--- a/numeric.c
+++ b/numeric.c
@@ -332,7 +332,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;
diff --git a/object.c b/object.c
index 4e3d5dd856..9f3c033a76 100644
--- a/object.c
+++ b/object.c
@@ -162,6 +162,7 @@ inspect_i(id, value, str)
if (!rb_is_instance_id(id)) return ST_CONTINUE;
if (RSTRING(str)->ptr[0] == '-') { /* first element */
RSTRING(str)->ptr[0] = '#';
+ rb_str_cat2(str, " ");
}
else {
rb_str_cat2(str, ", ");
@@ -182,6 +183,7 @@ inspect_obj(obj, str)
{
st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str);
rb_str_cat2(str, ">");
+ RSTRING(str)->ptr[0] = '#';
OBJ_INFECT(str, obj);
return str;
@@ -227,12 +229,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");
@@ -286,6 +286,9 @@ rb_obj_taint(obj)
VALUE obj;
{
rb_secure(4);
+ if (OBJ_FROZEN(obj)) {
+ rb_error_frozen("object");
+ }
OBJ_TAINT(obj);
return obj;
}
@@ -514,33 +517,6 @@ sym_to_s(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(module)
- VALUE module;
-{
- VALUE dup = rb_mod_clone(module);
- OBJSETUP(dup, RBASIC(module)->klass, BUILTIN_TYPE(module));
- return dup;
-}
-
-static VALUE
rb_mod_to_s(klass)
VALUE klass;
{
@@ -1036,6 +1012,9 @@ rb_str2cstr(str, len)
str = rb_str_to_str(str);
}
if (len) *len = RSTRING(str)->len;
+ else if (ruby_verbose && RSTRING(str)->len != strlen(RSTRING(str)->ptr)) {
+ rb_warn("string contains \\0 character");
+ }
return RSTRING(str)->ptr;
}
diff --git a/pack.c b/pack.c
index 5538600449..9e05f46c5a 100644
--- a/pack.c
+++ b/pack.c
@@ -826,7 +826,7 @@ pack_pack(ary, fmt)
case 'm':
ptr = rb_str2cstr(NEXTFROM, &plen);
- if (len <= 1)
+ if (len <= 2)
len = 45;
else
len = len / 3 * 3;
@@ -1026,11 +1026,7 @@ qpencode(str, from, len)
}
}
-#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
-static __inline__ int
-#else
-static int
-#endif
+static inline int
hex2num(c)
char c;
{
diff --git a/parse.y b/parse.y
index d1f1a32321..bf611f7479 100644
--- a/parse.y
+++ b/parse.y
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 28 18:02:42 JST 1993
- Copyright (C) 1993-2000 Yukihiro Matsumoto
+ Copyright (C) 1993-2001 Yukihiro Matsumoto
**********************************************************************/
@@ -49,7 +49,6 @@ static int yyerror();
static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
- EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */
EXPR_ARG, /* newline significant, +/- is a operator. */
EXPR_MID, /* newline significant, +/- is a operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */
@@ -57,8 +56,16 @@ 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;
+#else
+typedef unsigned long stack_type;
+#endif
+
static int cond_nest = 0;
-static unsigned long cond_stack = 0;
+static stack_type cond_stack = 0;
#define COND_PUSH do {\
cond_nest++;\
cond_stack = (cond_stack<<1)|1;\
@@ -67,10 +74,20 @@ static unsigned long cond_stack = 0;
cond_nest--;\
cond_stack >>= 1;\
} while (0)
-#define IN_COND (cond_nest > 0 && (cond_stack&1))
+#define COND_P() (cond_nest > 0 && (cond_stack&1))
+
+static stack_type cmdarg_stack = 0;
+#define CMDARG_PUSH do {\
+ cmdarg_stack = (cmdarg_stack<<1)|1;\
+} while(0)
+#define CMDARG_POP do {\
+ cmdarg_stack >>= 1;\
+} while (0)
+#define CMDARG_P() (cmdarg_stack && (cmdarg_stack&1))
static int class_nest = 0;
static int in_single = 0;
+static int in_def = 0;
static int compile_for_eval = 0;
static ID cur_mid = 0;
@@ -115,10 +132,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();
%}
@@ -155,7 +168,8 @@ static void top_local_setup();
kRETRY
kIN
kDO
- kDO2
+ kDO_COND
+ kDO_BLOCK
kRETURN
kYIELD
kSUPER
@@ -184,11 +198,11 @@ static void top_local_setup();
%type <node> singleton string
%type <val> literal numeric
-%type <node> compstmt stmts stmt expr arg primary command_call method_call
+%type <node> compstmt stmts stmt expr arg primary command command_call method_call
%type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure
-%type <node> opt_call_args call_args ret_args args when_args
-%type <node> aref_args opt_block_arg block_arg stmt_rhs
-%type <node> mrhs mrhs_basic superclass generic_call block_call var_ref
+%type <node> args ret_args when_args call_args paren_args opt_paren_args
+%type <node> command_args aref_args opt_block_arg block_arg var_ref
+%type <node> mrhs mrhs_basic superclass block_call block_command
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> assoc_list assocs assoc undef_list backref
%type <node> block_var opt_block_var brace_block do_block lhs none
@@ -251,7 +265,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;
}
@@ -270,7 +283,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;
}
@@ -295,16 +307,15 @@ stmts : none
$$ = $2;
}
-stmt : block_call
- | kALIAS fitem {lex_state = EXPR_FNAME;} fitem
+stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("alias within method");
$$ = NEW_ALIAS($2, $4);
}
| kALIAS tGVAR tGVAR
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("alias within method");
$$ = NEW_VALIAS($2, $3);
}
@@ -312,7 +323,7 @@ stmt : block_call
{
char buf[3];
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("alias within method");
sprintf(buf, "$%c", $3->nd_nth);
$$ = NEW_VALIAS($2, rb_intern(buf));
@@ -324,7 +335,7 @@ stmt : block_call
}
| kUNDEF undef_list
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("undef within method");
$$ = $2;
}
@@ -343,31 +354,21 @@ stmt : block_call
| stmt kWHILE_MOD expr
{
value_expr($3);
- if ($1) {
- if (nd_type($1) == NODE_BEGIN) {
- $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
- }
- else {
- $$ = NEW_WHILE(cond($3), $1, 1);
- }
+ if ($1 && nd_type($1) == NODE_BEGIN) {
+ $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
}
else {
- $$ = 0;
+ $$ = NEW_WHILE(cond($3), $1, 1);
}
}
| stmt kUNTIL_MOD expr
{
value_expr($3);
- if ($1) {
- if (nd_type($1) == NODE_BEGIN) {
- $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
- }
- else {
- $$ = NEW_UNTIL(cond($3), $1, 1);
- }
+ if ($1 && nd_type($1) == NODE_BEGIN) {
+ $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
}
else {
- $$ = 0;
+ $$ = NEW_UNTIL(cond($3), $1, 1);
}
}
| stmt kRESCUE_MOD stmt
@@ -376,7 +377,7 @@ stmt : block_call
}
| klBEGIN
{
- if (cur_mid || in_single) {
+ if (in_def || in_single) {
yyerror("BEGIN in method");
}
local_push();
@@ -390,18 +391,18 @@ stmt : block_call
}
| klEND '{' compstmt '}'
{
- if (compile_for_eval && (cur_mid || in_single)) {
+ if (compile_for_eval && (in_def || in_single)) {
yyerror("END in method; use at_exit");
}
$$ = NEW_ITER(0, NEW_POSTEXE(), $3);
}
- | lhs '=' stmt_rhs
+ | lhs '=' command_call
{
value_expr($3);
$$ = node_assign($1, $3);
}
- | mlhs '=' stmt_rhs
+ | mlhs '=' command_call
{
value_expr($3);
$1->nd_value = $3;
@@ -421,7 +422,7 @@ expr : mlhs '=' mrhs
}
| kRETURN ret_args
{
- if (!compile_for_eval && !cur_mid && !in_single)
+ if (!compile_for_eval && !in_def && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN($2);
}
@@ -445,26 +446,41 @@ expr : mlhs '=' mrhs
}
| arg
-command_call : operation call_args
+command_call : command
+ | block_command
+
+block_command : block_call
+ | block_call '.' operation2 command_args
+ {
+ value_expr($1);
+ $$ = new_call($1, $3, $4);
+ }
+ | block_call tCOLON2 operation2 command_args
+ {
+ value_expr($1);
+ $$ = new_call($1, $3, $4);
+ }
+
+command : operation command_args
{
$$ = new_fcall($1, $2);
fixpos($$, $2);
}
- | primary '.' operation2 call_args
+ | primary '.' operation2 command_args
{
value_expr($1);
$$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | primary tCOLON2 operation2 call_args
+ | primary tCOLON2 operation2 command_args
{
value_expr($1);
$$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | kSUPER call_args
+ | kSUPER command_args
{
- if (!compile_for_eval && !cur_mid && !in_single)
+ if (!compile_for_eval && !in_def && !in_single)
yyerror("super called outside of method");
$$ = new_super($2);
fixpos($$, $2);
@@ -475,7 +491,6 @@ command_call : operation call_args
fixpos($$, $2);
}
-
mlhs : mlhs_basic
| tLPAREN mlhs_entry ')'
{
@@ -897,14 +912,6 @@ aref_args : none
{
$$ = list_append($1, $3);
}
- | block_call opt_nl
- {
- $$ = NEW_LIST($1);
- }
- | args ',' block_call opt_nl
- {
- $$ = list_append($1, $3);
- }
| args trailer
{
$$ = $1;
@@ -924,22 +931,31 @@ aref_args : none
$$ = NEW_RESTARGS($2);
}
-opt_call_args : none
- | call_args opt_nl
- | block_call opt_nl
+paren_args : '(' none ')'
{
- $$ = NEW_LIST($1);
+ $$ = $2;
}
- | args ',' block_call
+ | '(' call_args opt_nl ')'
{
- $$ = list_append($1, $3);
+ $$ = $2;
+ }
+ | '(' block_call opt_nl ')'
+ {
+ $$ = NEW_LIST($2);
}
+ | '(' args ',' block_call opt_nl ')'
+ {
+ $$ = list_append($2, $4);
+ }
+
+opt_paren_args : none
+ | paren_args
-call_args : command_call
+call_args : command
{
$$ = NEW_LIST($1);
}
- | args ',' command_call
+ | args ',' command
{
$$ = list_append($1, $3);
}
@@ -953,10 +969,6 @@ call_args : command_call
$$ = arg_concat($1, $4);
$$ = arg_blk_pass($$, $5);
}
- | assocs ','
- {
- $$ = NEW_LIST(NEW_HASH($1));
- }
| assocs opt_block_arg
{
$$ = NEW_LIST(NEW_HASH($1));
@@ -973,10 +985,6 @@ 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);
@@ -990,6 +998,12 @@ call_args : command_call
}
| block_arg
+command_args : {CMDARG_PUSH;} call_args
+ {
+ CMDARG_POP;
+ $$ = $2;
+ }
+
block_arg : tAMPER arg
{
value_expr($2);
@@ -1119,20 +1133,20 @@ primary : literal
}
| kRETURN '(' ret_args ')'
{
- if (!compile_for_eval && !cur_mid && !in_single)
+ if (!compile_for_eval && !in_def && !in_single)
yyerror("return appeared outside of method");
value_expr($3);
$$ = NEW_RETURN($3);
}
| kRETURN '(' ')'
{
- if (!compile_for_eval && !cur_mid && !in_single)
+ if (!compile_for_eval && !in_def && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN(0);
}
| kRETURN
{
- if (!compile_for_eval && !cur_mid && !in_single)
+ if (!compile_for_eval && !in_def && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN(0);
}
@@ -1225,11 +1239,9 @@ primary : literal
}
| kCLASS cname superclass
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("class definition in method body");
-
class_nest++;
- cref_push();
local_push();
$<num>$ = ruby_sourceline;
}
@@ -1239,30 +1251,35 @@ primary : literal
$$ = NEW_CLASS($2, $5, $3);
nd_set_line($$, $<num>4);
local_pop();
- cref_pop();
class_nest--;
}
- | kCLASS tLSHFT expr term
+ | kCLASS tLSHFT expr
+ {
+ $<num>$ = in_def;
+ in_def = 0;
+ }
+ term
{
+ $<num>$ = in_single;
+ in_single = 0;
class_nest++;
- cref_push();
local_push();
}
compstmt
kEND
{
- $$ = NEW_SCLASS($3, $6);
+ $$ = NEW_SCLASS($3, $7);
fixpos($$, $3);
local_pop();
- cref_pop();
class_nest--;
+ in_def = $<num>4;
+ in_single = $<num>6;
}
| kMODULE cname
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("module definition in method body");
class_nest++;
- cref_push();
local_push();
$<num>$ = ruby_sourceline;
}
@@ -1272,14 +1289,15 @@ primary : literal
$$ = NEW_MODULE($2, $4);
nd_set_line($$, $<num>3);
local_pop();
- cref_pop();
class_nest--;
}
| kDEF fname
{
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("nested method definition");
+ $<id>$ = cur_mid;
cur_mid = $2;
+ in_def++;
local_push();
}
f_arglist
@@ -1301,7 +1319,8 @@ primary : literal
if (is_attrset_id($2)) $$->nd_noex = NOEX_PUBLIC;
fixpos($$, $4);
local_pop();
- cur_mid = 0;
+ in_def--;
+ cur_mid = $<id>3;
}
| kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
{
@@ -1312,8 +1331,18 @@ primary : literal
}
f_arglist
compstmt
+ rescue
+ opt_else
+ ensure
kEND
{
+ if ($9) $8 = NEW_RESCUE($8, $9, $10);
+ else if ($10) {
+ rb_warn("else without rescue is useless");
+ $8 = block_append($8, $10);
+ }
+ if ($11) $8 = NEW_ENSURE($8, $11);
+
$$ = NEW_DEFS($2, $5, $7, $8);
fixpos($$, $2);
local_pop();
@@ -1341,7 +1370,7 @@ then : term
| term kTHEN
do : term
- | kDO
+ | kDO_COND
if_tail : opt_else
| kELSIF expr then
@@ -1377,7 +1406,7 @@ opt_block_var : none
}
-do_block : kDO
+do_block : kDO_BLOCK
{
$<vars>$ = dyna_push();
}
@@ -1390,47 +1419,7 @@ do_block : kDO
dyna_pop($<vars>2);
}
-brace_block : '{'
- {
- $<vars>$ = dyna_push();
- }
- opt_block_var
- compstmt '}'
- {
- $$ = NEW_ITER($3, 0, $4);
- fixpos($$, $4);
- dyna_pop($<vars>2);
- }
- | kDO2
- {
- $<vars>$ = dyna_push();
- }
- opt_block_var
- compstmt
- kEND
- {
- $$ = NEW_ITER($3, 0, $4);
- fixpos($$, $4);
- dyna_pop($<vars>2);
- }
-
-
-generic_call : tIDENTIFIER
- {
- $$ = NEW_VCALL($1);
- }
- | tCONSTANT
- {
- $$ = NEW_VCALL($1);
- }
- | tFID
- {
- $$ = NEW_VCALL($1);
- }
- | method_call
- | command_call
-
-block_call : generic_call do_block
+block_call : command do_block
{
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
rb_compile_error("both block arg and actual block given");
@@ -1439,28 +1428,32 @@ block_call : generic_call do_block
$$ = $2;
fixpos($$, $2);
}
-
-method_call : operation '(' opt_call_args close_paren
+ | block_call '.' operation2 opt_paren_args
{
- $$ = new_fcall($1, $3);
- fixpos($$, $3);
+ value_expr($1);
+ $$ = new_call($1, $3, $4);
}
- | primary '.' operation2 '(' opt_call_args close_paren
+ | block_call tCOLON2 operation2 opt_paren_args
{
value_expr($1);
- $$ = new_call($1, $3, $5);
- fixpos($$, $1);
+ $$ = new_call($1, $3, $4);
}
- | primary '.' operation2
+
+method_call : operation paren_args
+ {
+ $$ = new_fcall($1, $2);
+ fixpos($$, $2);
+ }
+ | primary '.' operation2 opt_paren_args
{
value_expr($1);
- $$ = new_call($1, $3, 0);
+ $$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | primary tCOLON2 operation2 '(' opt_call_args close_paren
+ | primary tCOLON2 operation2 paren_args
{
value_expr($1);
- $$ = new_call($1, $3, $5);
+ $$ = new_call($1, $3, $4);
fixpos($$, $1);
}
| primary tCOLON2 operation3
@@ -1468,28 +1461,43 @@ method_call : operation '(' opt_call_args close_paren
value_expr($1);
$$ = new_call($1, $3, 0);
}
- | kSUPER '(' opt_call_args close_paren
+ | kSUPER paren_args
{
- if (!compile_for_eval && !cur_mid &&
+ if (!compile_for_eval && !in_def &&
!in_single && !in_defined)
yyerror("super called outside of method");
- $$ = new_super($3);
+ $$ = new_super($2);
}
| kSUPER
{
- if (!compile_for_eval && !cur_mid &&
+ if (!compile_for_eval && !in_def &&
!in_single && !in_defined)
yyerror("super called outside of method");
$$ = NEW_ZSUPER();
}
-close_paren : ')'
+brace_block : '{'
{
- if (!IN_COND) lex_state = EXPR_PAREN;
+ $<vars>$ = dyna_push();
+ }
+ opt_block_var
+ compstmt '}'
+ {
+ $$ = NEW_ITER($3, 0, $4);
+ fixpos($$, $4);
+ dyna_pop($<vars>2);
+ }
+ | kDO
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_block_var
+ compstmt kEND
+ {
+ $$ = NEW_ITER($3, 0, $4);
+ fixpos($$, $4);
+ dyna_pop($<vars>2);
}
-
-stmt_rhs : block_call
- | command_call
case_body : kWHEN when_args then
compstmt
@@ -1965,8 +1973,10 @@ 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;
cur_mid = 0;
if (n == 0) node = ruby_eval_tree;
@@ -2043,10 +2053,7 @@ rb_compile_file(f, file, start)
return yycompile(strdup(f), start);
}
-#if defined(__GNUC__) && __GNUC__ >= 2
-__inline__
-#endif
-static int
+static inline int
nextc()
{
int c;
@@ -2542,13 +2549,12 @@ parse_qstring(term, paren)
c = '\\';
break;
- case '\'':
- if (term == '\'') {
- c = '\'';
- break;
- }
- /* fall through */
default:
+ /* fall through */
+ if (c == term || (paren && c == paren)) {
+ tokadd(c);
+ continue;
+ }
tokadd('\\');
}
}
@@ -2603,7 +2609,7 @@ parse_quotedwords(term, paren)
c = '\\';
break;
default:
- if (c == term) {
+ if (c == term || (paren && c == paren)) {
tokadd(c);
continue;
}
@@ -2794,7 +2800,7 @@ arg_ambiguous()
rb_warning("ambiguous first argument; make sure");
}
-#ifndef strtod
+#if !defined(strtod) && !defined(HAVE_STDLIB_H)
double strtod ();
#endif
@@ -2919,8 +2925,7 @@ yylex()
case '<':
c = nextc();
if (c == '<' &&
- lex_state != EXPR_END && lex_state != EXPR_PAREN &&
- lex_state != EXPR_CLASS &&
+ lex_state != EXPR_END && lex_state != EXPR_CLASS &&
(lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc();
int indent = 0;
@@ -2979,7 +2984,7 @@ yylex()
return parse_qstring(c,0);
case '?':
- if (lex_state == EXPR_END || lex_state == EXPR_PAREN) {
+ if (lex_state == EXPR_END) {
lex_state = EXPR_BEG;
return '?';
}
@@ -3306,7 +3311,7 @@ yylex()
return tCOLON2;
}
pushback(c);
- if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) {
+ if (lex_state == EXPR_END || ISSPACE(c)) {
lex_state = EXPR_BEG;
return ':';
}
@@ -3390,9 +3395,7 @@ yylex()
return c;
case '{':
- if (lex_state != EXPR_END &&
- lex_state != EXPR_PAREN &&
- lex_state != EXPR_ARG)
+ if (lex_state != EXPR_END && lex_state != EXPR_ARG)
c = tLBRACE;
lex_state = EXPR_BEG;
return c;
@@ -3616,10 +3619,10 @@ yylex()
if (state == EXPR_FNAME) {
yylval.id = rb_intern(kw->name);
}
- if (kw->id[0] == kDO &&
- (state == EXPR_PAREN ||
- (!IN_COND && state == EXPR_ARG))) {
- return kDO2;
+ if (kw->id[0] == kDO) {
+ if (COND_P()) return kDO_COND;
+ if (CMDARG_P()) return kDO_BLOCK;
+ return kDO;
}
return kw->id[state != EXPR_BEG];
}
@@ -4121,7 +4124,7 @@ assignable(id, val)
return NEW_IASGN(id, val);
}
else if (is_const_id(id)) {
- if (cur_mid || in_single)
+ if (in_def || in_single)
yyerror("dynamic constant assignment");
return NEW_CDECL(id, val);
}
@@ -4375,6 +4378,9 @@ void_expr(node)
}
}
+
+static NODE *cond2 _((NODE*));
+
static void
void_stmts(node)
NODE *node;
@@ -4390,8 +4396,6 @@ void_stmts(node)
}
}
-static NODE *cond2();
-
static int
assign_in_cond(node)
NODE *node;
@@ -4733,12 +4737,6 @@ dyna_in_block()
return (lvtbl->dlev > 0);
}
-static void
-cref_pop()
-{
- cur_cref = cur_cref->nd_next;
-}
-
void
rb_parser_append_print()
{
@@ -4822,7 +4820,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);
}
diff --git a/prec.c b/prec.c
index 8dcd121bc0..fab5ea3899 100644
--- a/prec.c
+++ b/prec.c
@@ -43,7 +43,7 @@ prec_prec_f(x)
static VALUE
prec_induced_from(module, x)
-
+ VALUE module, x;
{
rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
rb_class2name(CLASS_OF(x)), rb_class2name(module));
diff --git a/re.c b/re.c
index bb9898fdb4..0cf81ef607 100644
--- a/re.c
+++ b/re.c
@@ -288,11 +288,11 @@ rb_reg_desc(s, len, re)
rb_str_cat2(str, "/");
if (re) {
rb_reg_check(re);
- if (RREGEXP(re)->ptr->options & RE_OPTION_MULTILINE)
- rb_str_cat2(str, "m");
/* /p is obsolete; to be removed */
if ((RREGEXP(re)->ptr->options & RE_OPTION_POSIXLINE) == RE_OPTION_POSIXLINE)
rb_str_cat2(str, "p");
+ else if (RREGEXP(re)->ptr->options & RE_OPTION_MULTILINE)
+ rb_str_cat2(str, "m");
if (RREGEXP(re)->ptr->options & RE_OPTION_IGNORECASE)
rb_str_cat2(str, "i");
if (RREGEXP(re)->ptr->options & RE_OPTION_EXTENDED)
@@ -915,8 +915,7 @@ rb_reg_equal(re1, re2)
if (min > RREGEXP(re2)->len) min = RREGEXP(re2)->len;
if (memcmp(RREGEXP(re1)->str, RREGEXP(re2)->str, min) == 0 &&
rb_reg_cur_kcode(re1) == rb_reg_cur_kcode(re2) &&
- !((RREGEXP(re1)->ptr->options & RE_OPTION_IGNORECASE) ^
- (RREGEXP(re2)->ptr->options & RE_OPTION_IGNORECASE))) {
+ RREGEXP(re1)->ptr->options == RREGEXP(re2)->ptr->options) {
return Qtrue;
}
return Qfalse;
@@ -1015,6 +1014,7 @@ rb_reg_initialize_m(argc, argv, self)
p = rb_str2cstr(src, &len);
rb_reg_initialize(self, p, len, flag);
}
+ return self;
}
static VALUE
@@ -1123,6 +1123,12 @@ rb_reg_options(re)
rb_reg_check(re);
if (RREGEXP(re)->ptr->options & RE_OPTION_IGNORECASE)
options |= RE_OPTION_IGNORECASE;
+ if ((RREGEXP(re)->ptr->options & RE_OPTION_POSIXLINE) == RE_OPTION_POSIXLINE)
+ options |= RE_OPTION_POSIXLINE;
+ else if (RREGEXP(re)->ptr->options & RE_OPTION_MULTILINE)
+ options |= RE_OPTION_MULTILINE;
+ if (RREGEXP(re)->ptr->options & RE_OPTION_EXTENDED)
+ options |= RE_OPTION_EXTENDED;
if (FL_TEST(re, KCODE_FIXED)) {
options |= rb_reg_get_kcode(re);
}
diff --git a/regex.c b/regex.c
index d4c1c2a915..9268b31f9b 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,10 @@ 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 a end value of range");
+ goto invalid_pattern;
+ }
PATFETCH(c);
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;
@@ -3461,7 +3471,8 @@ re_search(bufp, string, size, startpos, range, regs)
#define PREV_IS_A_LETTER(d) ((current_mbctype == MBCTYPE_SJIS)? \
IS_A_LETTER((d)-(!AT_STRINGS_BEG((d)-1)&& \
ismbchar((d)[-2])?2:1)): \
- ((d)[-1] >= 0x80 || IS_A_LETTER((d)-1)))
+ ((current_mbctype && ((d)[-1] >= 0x80)) || \
+ IS_A_LETTER((d)-1)))
static void
init_regs(regs, num_regs)
diff --git a/ruby.c b/ruby.c
index 9649b69af4..da1049533d 100644
--- a/ruby.c
+++ b/ruby.c
@@ -214,13 +214,23 @@ ruby_init_loadpath()
#elif defined(DJGPP)
extern char *__dos_argv0;
strncpy(libpath, __dos_argv0, FILENAME_MAX);
+#define CharNext(p) ((p) + mblen(p, MB_CUR_MAX))
#elif defined(__EMX__)
_execname(libpath, FILENAME_MAX);
#endif
- p = strrchr(libpath, '\\');
+
+#ifndef CharNext /* defined as CharNext[AW] on Windows. */
+#define CharNext(p) ((p) + 1)
+#endif
+
+ for (p = libpath; *p; p = CharNext(p))
+ if (*p == '\\')
+ *p = '/';
+
+ p = strrchr(libpath, '/');
if (p) {
*p = 0;
- if (p-libpath > 3 && !strcasecmp(p-4, "\\bin")) {
+ if (p-libpath > 3 && !strcasecmp(p-4, "/bin")) {
p -= 4;
*p = 0;
}
@@ -229,14 +239,6 @@ ruby_init_loadpath()
p = libpath + 1;
}
-#if !defined(__CYGWIN32__)
-#ifndef CharNext /* defined as CharNext[AW] on Windows. */
-#define CharNext(p) ((p) + 1)
-#endif
- for (p = libpath; *p; p = CharNext(p))
- if (*p == '\\')
- *p = '/';
-#endif
rest = FILENAME_MAX - (p - libpath);
#define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
@@ -428,6 +430,10 @@ proc_options(argc, argv)
goto reswitch;
case 'v':
+ if (verbose) {
+ s++;
+ goto reswitch;
+ }
ruby_show_version();
verbose = 1;
case 'w':
@@ -728,7 +734,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);
@@ -983,6 +989,7 @@ ruby_set_argv(argc, argv)
if (origargv) dln_argv0 = origargv[0];
else dln_argv0 = argv[0];
#endif
+ rb_ary_clear(rb_argv);
for (i=0; i < argc; i++) {
rb_ary_push(rb_argv, rb_tainted_str_new2(argv[i]));
}
diff --git a/ruby.h b/ruby.h
index ca97ee2c42..d9e3460684 100644
--- a/ruby.h
+++ b/ruby.h
@@ -164,6 +164,7 @@ VALUE rb_uint2inum _((unsigned long));
#define T_MATCH 0x23
#define T_SYMBOL 0x24
+#define T_BLKTAG 0x3b
#define T_UNDEF 0x3c
#define T_VARMAP 0x3d
#define T_SCOPE 0x3e
@@ -541,13 +542,13 @@ EXTERN VALUE rb_eNameError;
EXTERN VALUE rb_eSyntaxError;
EXTERN VALUE rb_eLoadError;
-#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
-extern __inline__ VALUE rb_class_of _((VALUE));
-extern __inline__ int rb_type _((VALUE));
-extern __inline__ int rb_special_const_p _((VALUE));
-
-extern __inline__ VALUE
+static inline VALUE
+#if defined(__cplusplus)
rb_class_of(VALUE obj)
+#else
+rb_class_of(obj)
+ VALUE obj;
+#endif
{
if (FIXNUM_P(obj)) return rb_cFixnum;
if (obj == Qnil) return rb_cNilClass;
@@ -558,8 +559,13 @@ rb_class_of(VALUE obj)
return RBASIC(obj)->klass;
}
-extern __inline__ int
+static inline int
+#if defined(__cplusplus)
rb_type(VALUE obj)
+#else
+rb_type(obj)
+ VALUE obj;
+#endif
{
if (FIXNUM_P(obj)) return T_FIXNUM;
if (obj == Qnil) return T_NIL;
@@ -570,19 +576,18 @@ rb_type(VALUE obj)
return BUILTIN_TYPE(obj);
}
-extern __inline__ int
+static inline int
+#if defined(__cplusplus)
rb_special_const_p(VALUE obj)
+#else
+rb_special_const_p(obj)
+ VALUE obj;
+#endif
{
if (SPECIAL_CONST_P(obj)) return Qtrue;
return Qfalse;
}
-#else
-VALUE rb_class_of _((VALUE));
-int rb_type _((VALUE));
-int rb_special_const_p _((VALUE));
-#endif
-
#include "intern.h"
#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
@@ -590,6 +595,10 @@ int rb_special_const_p _((VALUE));
static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
#endif
+#ifndef rb_sys_stat
+#define rb_sys_stat stat
+#endif
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/sample/README b/sample/README
index 82db05eec9..bf080c1d51 100644
--- a/sample/README
+++ b/sample/README
@@ -7,7 +7,6 @@ dbmtest.rb test for dbm
dir.rb directory access
dualstack-fetch.rb IPv6 demo
dualstack-httpd.rb IPv6 demo
-dstore.rb object database on dbm
eval.rb simple evaluator
export.rb method access example
exyacc.rb extrace BNF from yacc file
@@ -22,7 +21,6 @@ from.rb scan mail spool
fullpath.rb convert ls -lR to fullpath format
getopts.test test fot getopt.rb
goodfriday.rb print various christian calendar event.
-io.rb io test
irb.rb interactive ruby
less.rb front end for less
list.rb stupid object sample
@@ -41,7 +39,6 @@ pi.rb calculate PI
rcs.awk random character stereogram (AWK)
rcs.rb random character stereogram (Ruby)
rcs.dat data for random character stereogram
-rd2html.rb rd (Ruby Document) to HTML translator
regx.rb regular expression tester
sieve.rb sieve of Eratosthenes
svr.rb socket server
diff --git a/signal.c b/signal.c
index 2bb8bada28..48849a6554 100644
--- a/signal.c
+++ b/signal.c
@@ -252,7 +252,7 @@ rb_f_kill(argc, argv)
else {
for (i=1; i<argc; i++) {
Check_Type(argv[i], T_FIXNUM);
- if (kill(FIX2UINT(argv[i]), sig) < 0)
+ if (kill(FIX2INT(argv[i]), sig) < 0)
rb_sys_fail(0);
}
}
@@ -386,6 +386,16 @@ sigsegv(sig)
}
#endif
+#ifdef SIGPIPE
+static RETSIGTYPE sigpipe _((int));
+static RETSIGTYPE
+sigpipe(sig)
+ int sig;
+{
+ /* do nothing */
+}
+#endif
+
void
rb_trap_exit()
{
@@ -546,7 +556,7 @@ trap(arg)
#endif
#ifdef SIGPIPE
case SIGPIPE:
- func = SIG_IGN;
+ func = sigpipe;
break;
#endif
}
@@ -659,7 +669,7 @@ Init_signal()
ruby_signal(SIGSEGV, sigsegv);
#endif
#ifdef SIGPIPE
- ruby_signal(SIGPIPE, SIG_IGN);
+ ruby_signal(SIGPIPE, sigpipe);
#endif
#endif /* MACOS_UNUSE_SIGNAL */
}
diff --git a/sprintf.c b/sprintf.c
index 756de87ed9..178f81f192 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -573,7 +573,7 @@ rb_f_sprintf(argc, argv)
break;
case 8:
c = '7'; break;
- case '2':
+ case 2:
c = '1'; break;
}
s = &buf[pos];
diff --git a/string.c b/string.c
index ddf50e2eed..8b37a4dccb 100644
--- a/string.c
+++ b/string.c
@@ -174,7 +174,7 @@ rb_str_associate(str, add)
rb_ary_push(RSTRING(str)->orig, add);
}
-static ID to_str;
+static ID id_to_s;
VALUE
rb_obj_as_string(obj)
@@ -185,7 +185,7 @@ rb_obj_as_string(obj)
if (TYPE(obj) == T_STRING) {
return obj;
}
- str = rb_funcall(obj, to_str, 0);
+ str = rb_funcall(obj, id_to_s, 0);
if (TYPE(str) != T_STRING)
return rb_any_to_s(obj);
if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
@@ -339,7 +339,6 @@ rb_str_substr(str, beg, len)
if (len < 0) return Qnil;
if (beg > RSTRING(str)->len) return Qnil;
- if (beg == RSTRING(str)->len && len > 0) return Qnil;
if (beg < 0) {
beg += RSTRING(str)->len;
if (beg < 0) return Qnil;
@@ -367,7 +366,6 @@ str_independent(str)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return 1;
if (TYPE(RSTRING(str)->orig) != T_STRING) rb_bug("non string str->orig");
- RSTRING(str)->orig = 0;
return 0;
}
@@ -384,6 +382,7 @@ rb_str_modify(str)
}
ptr[RSTRING(str)->len] = 0;
RSTRING(str)->ptr = ptr;
+ RSTRING(str)->orig = 0;
}
VALUE
@@ -1127,7 +1126,7 @@ rb_str_sub_bang(argc, argv, str)
iter = 1;
}
else if (argc == 2) {
- repl = rb_obj_as_string(argv[1]);;
+ repl = rb_str_to_str(argv[1]);;
if (OBJ_TAINTED(repl)) tainted = 1;
}
else {
@@ -1200,7 +1199,7 @@ str_gsub(argc, argv, str, bang)
iter = 1;
}
else if (argc == 2) {
- repl = rb_obj_as_string(argv[1]);
+ repl = rb_str_to_str(argv[1]);
if (OBJ_TAINTED(repl)) tainted = 1;
}
else {
@@ -1278,6 +1277,9 @@ str_gsub(argc, argv, str, bang)
if (str_independent(str)) {
free(RSTRING(str)->ptr);
}
+ else {
+ RSTRING(str)->orig = 0;
+ }
}
else {
NEWOBJ(dup, struct RString);
@@ -1316,15 +1318,19 @@ static VALUE
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);
- rb_str_modify(str);
- if (RSTRING(str2)->orig && FL_TEST(str2, STR_NO_ORIG)) {
+ if (RSTRING(str2)->orig && !FL_TEST(str2, STR_NO_ORIG)) {
+ 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;
}
else {
+ rb_str_modify(str);
rb_str_resize(str, RSTRING(str2)->len);
memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
@@ -1395,6 +1401,7 @@ rb_str_reverse_bang(str)
char *s, *e;
char c;
+ rb_str_modify(str);
s = RSTRING(str)->ptr;
e = s + RSTRING(str)->len - 1;
while (s < e) {
@@ -1490,8 +1497,8 @@ rb_str_inspect(str)
char c = *p++;
if (ismbchar(c) && p < pend) {
int len = mbclen(c);
- rb_str_cat(result, p, len);
- p += len;
+ rb_str_cat(result, p - 1, len);
+ p += len - 1;
}
else if (c == '"'|| c == '\\') {
s[0] = '\\'; s[1] = c;
@@ -1644,7 +1651,7 @@ rb_str_upcase_bang(str)
if (ismbchar(*s)) {
s+=mbclen(*s) - 1;
}
- else if (islower(*s)) {
+ else if (ISLOWER(*s)) {
*s = toupper(*s);
modify = 1;
}
@@ -1784,7 +1791,10 @@ trnext(t)
if (!t->gen) {
if (t->p == t->pend) return -1;
t->now = *(USTR)t->p++;
- if (t->p < t->pend - 1 && *t->p == '-') {
+ if (t->p < t->pend - 1 && *t->p == '\\') {
+ t->p++;
+ }
+ else if (t->p < t->pend - 1 && *t->p == '-') {
t->p++;
if (t->p < t->pend) {
if (t->now > *(USTR)t->p) {
@@ -1965,6 +1975,9 @@ rb_str_delete_bang(argc, argv, str)
int init = 1;
int i;
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "wrong # of arguments");
+ }
for (i=0; i<argc; i++) {
VALUE s = argv[i];
@@ -2877,7 +2890,7 @@ Init_String()
rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
- to_str = rb_intern("to_s");
+ id_to_s = rb_intern("to_s");
rb_fs = Qnil;
rb_define_hooked_variable("$;", &rb_fs, 0, rb_str_setter);
diff --git a/time.c b/time.c
index e45e2e854a..c03d7e5424 100644
--- a/time.c
+++ b/time.c
@@ -324,11 +324,6 @@ make_time_t(tptr, utc_or_local)
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
struct tm gt, lt;
long tzsec;
@@ -357,10 +352,14 @@ make_time_t(tptr, utc_or_local)
}
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;
+ }
}
-#endif
if (guess < 0) {
goto out_of_range;
}
@@ -891,7 +890,7 @@ rb_strftime(buf, format, time)
return 0;
}
len = strftime(*buf, SMALLBUF, format, time);
- if (len != 0) return len;
+ if (len != 0 || **buf == '\0') return len;
for (size=1024; ; size*=2) {
*buf = xmalloc(size);
(*buf)[0] = '\0';
diff --git a/util.c b/util.c
index 9cbfb5fc74..8fc543dbc0 100644
--- a/util.c
+++ b/util.c
@@ -16,45 +16,9 @@
#include "missing/file.h"
#endif
-#define RUBY_NO_INLINE
+#define INLINE_DEFINE
#include "ruby.h"
-VALUE
-rb_class_of(obj)
- VALUE obj;
-{
- if (FIXNUM_P(obj)) return rb_cFixnum;
- if (obj == Qnil) return rb_cNilClass;
- if (obj == Qfalse) return rb_cFalseClass;
- if (obj == Qtrue) return rb_cTrueClass;
- if (SYMBOL_P(obj)) return rb_cSymbol;
-
- return RBASIC(obj)->klass;
-}
-
-int
-rb_type(obj)
- VALUE obj;
-{
- if (FIXNUM_P(obj)) return T_FIXNUM;
- if (obj == Qnil) return T_NIL;
- if (obj == Qfalse) return T_FALSE;
- if (obj == Qtrue) return T_TRUE;
- if (obj == Qundef) return T_UNDEF;
- if (SYMBOL_P(obj)) return T_SYMBOL;
-
- return BUILTIN_TYPE(obj);
-}
-
-int
-rb_special_const_p(obj)
- VALUE obj;
-{
- if (SPECIAL_CONST_P(obj)) return Qtrue;
-
- return Qfalse;
-}
-
#include "util.h"
#ifndef HAVE_STRING_H
char *strchr _((char*,char));
diff --git a/variable.c b/variable.c
index 69791ab26d..6e2ef0c875 100644
--- a/variable.c
+++ b/variable.c
@@ -1064,10 +1064,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;
@@ -1075,15 +1076,17 @@ 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));
+ 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));
}
diff --git a/version.h b/version.h
index 71d484b8fd..f90b413a11 100644
--- a/version.h
+++ b/version.h
@@ -1,4 +1,4 @@
-#define RUBY_VERSION "1.6.2"
-#define RUBY_RELEASE_DATE "2000-12-25"
-#define RUBY_VERSION_CODE 162
-#define RUBY_RELEASE_CODE 20001225
+#define RUBY_VERSION "1.6.4"
+#define RUBY_RELEASE_DATE "2001-04-18"
+#define RUBY_VERSION_CODE 164
+#define RUBY_RELEASE_CODE 20010418
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 227ab68b18..42100a5d92 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -30,13 +30,13 @@ AUTOCONF = autoconf
prefix = /usr
-CFLAGS = -nologo -DNT=1 -Zi -MD -O2b2x -G5
+CFLAGS = -nologo -DNT=1 -Zi -MD -O2b2xg- -G5
CPPFLAGS = -I$(srcdir) -I$(srcdir)/missing
LDFLAGS = $(CFLAGS) -Fm
XLDFLAGS =
#EXTLIBS =
LIBS = user32.lib advapi32.lib wsock32.lib $(EXTLIBS)
-MISSING = crypt.obj alloca.obj win32.obj isinf.obj isnan.obj
+MISSING = crypt.obj win32.obj isinf.obj isnan.obj
LDSHARED =
DLDFLAGS =
SOLIBS =
diff --git a/win32/config.h.in b/win32/config.h.in
index a7e28120e6..f1ba8da5c3 100644
--- a/win32/config.h.in
+++ b/win32/config.h.in
@@ -1,6 +1,7 @@
#define HAVE_PROTOTYPES 1
#define HAVE_STDARG_PROTOTYPES 1
/* #define HAVE_ATTR_NORETURN 1 */
+#define inline __inline
/* #define HAVE_DIRENT_H 1 */
/* #define HAVE_UNISTD_H 1 */
#define HAVE_STDLIB_H 1
diff --git a/win32/config.status.in b/win32/config.status.in
index 461877b886..f337d97b35 100644
--- a/win32/config.status.in
+++ b/win32/config.status.in
@@ -3,8 +3,6 @@ s%@CFLAGS@%-nologo -DNT=1 -Zi -MD -O2b2x -G5%g
s%@CPPFLAGS@%%g
s%@CXXFLAGS@%%g
s%@FFLAGS@%%g
-s%@DEFS@%
- -DUSE_THREAD -DSIZEOF_INT=4 -DSIZEOF_SHORT=2 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DSIZEOF_FLOAT=4 -DSIZEOF_DOUBLE=8 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_STDLIB_H=1 -DHAVE_LIMITS_H=1 -DHAVE_FCNTL_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=int -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -DHAVE_FMOD=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_CHSIZE=1 -DHAVE_GETGROUPS=1 -DHAVE_GETLOGIN=1 -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".so\" -DDLEXT2=\".dll\" -DRUBY_PLATFORM=\"i586-mswin32\" %g
s%@LDFLAGS@%-nologo%g
s%@LIBS@%user32.lib advapi32.lib wsock32.lib%g
s%@exec_prefix@%${prefix}%g
@@ -34,7 +32,7 @@ s%@RANLIB@%rem%g
s%@AR@%lib -nologo%g
s%@LN_S@%%g
s%@SET_MAKE@%%g
-s%@LIBOBJS@% crypt.obj alloca.obj win32.obj isinf.obj isnan.obj%g
+s%@LIBOBJS@% crypt.obj win32.obj isinf.obj isnan.obj%g
s%@ALLOCA@%%g
s%@DEFAULT_KCODE@%%g
s%@EXEEXT@%.exe%g
diff --git a/win32/win32.c b/win32/win32.c
index bd07bb644e..9fb120e09d 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -29,6 +29,7 @@
#ifndef index
#define index(x, y) strchr((x), (y))
#endif
+#define isdirsep(x) ((x) == '/' || (x) == '\\')
#ifndef bool
#define bool int
@@ -357,7 +358,7 @@ isInternalCmd(char *cmd)
int vecc = NtMakeCmdVector(cmd, &vec, FALSE);
for( i = 0; szInternalCmds[i] ; i++){
- if(!strcmp(szInternalCmds[i], vec[0])){
+ if(!strcasecmp(szInternalCmds[i], vec[0])){
fRet = 1;
break;
}
@@ -777,10 +778,10 @@ char *cmd;
strcpy(cmd2, cmd);
a = argv;
for (s = cmd2; *s;) {
- while (*s && isspace(*s)) s++;
+ while (*s && ISSPACE(*s)) s++;
if (*s)
*(a++) = s;
- while (*s && !isspace(*s)) s++;
+ while (*s && !ISSPACE(*s)) s++;
if (*s)
*s++ = '\0';
}
@@ -1054,7 +1055,7 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd)
//
ptr = cmdline+(cmdlen - 1);
- while(ptr >= cmdline && isspace(*ptr))
+ while(ptr >= cmdline && ISSPACE(*ptr))
--ptr;
*++ptr = '\0';
@@ -1074,7 +1075,7 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd)
// zap any leading whitespace
//
- while(isspace(*ptr))
+ while(ISSPACE(*ptr))
ptr++;
base = ptr;
@@ -1277,7 +1278,6 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd)
}
-#if !defined __MINGW32__
//
// UNIX compatible directory access functions for NT
//
@@ -1309,9 +1309,9 @@ opendir(char *filename)
// check to see if we\'ve got a directory
//
- if ((stat (filename, &sbuf) < 0 ||
+ if ((win32_stat (filename, &sbuf) < 0 ||
sbuf.st_mode & _S_IFDIR == 0) &&
- (!isalpha(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
+ (!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
((1 << (filename[0] & 0x5f) - 'A') & GetLogicalDrives()) == 0)) {
return NULL;
}
@@ -1466,7 +1466,6 @@ closedir(DIR *dirp)
free(dirp->start);
free(dirp);
}
-#endif
//
@@ -2425,13 +2424,23 @@ waitpid (pid_t pid, int *stat_loc, int options)
int _cdecl
gettimeofday(struct timeval *tv, struct timezone *tz)
{
- struct timeb tb;
+ SYSTEMTIME st;
+ time_t t;
+ struct tm tm;
+
+ GetLocalTime(&st);
+ tm.tm_sec = st.wSecond;
+ tm.tm_min = st.wMinute;
+ tm.tm_hour = st.wHour;
+ tm.tm_mday = st.wDay;
+ tm.tm_mon = st.wMonth - 1;
+ tm.tm_year = st.wYear - 1900;
+ tm.tm_isdst = -1;
+ t = mktime(&tm);
+ tv->tv_sec = t;
+ tv->tv_usec = st.wMilliseconds * 1000;
- ftime(&tb);
- tv->tv_sec = tb.time;
- tv->tv_usec = tb.millitm * 1000;
-
- return 0;
+ return 0;
}
char *
@@ -2545,7 +2554,7 @@ myrename(const char *oldpath, const char *newpath)
newatts = GetFileAttributes(newpath);
if (oldatts == -1) {
- printf("file to move doesn't exist");
+ errno = GetLastError();
return -1;
}
@@ -2583,6 +2592,56 @@ myrename(const char *oldpath, const char *newpath)
return res;
}
+static int
+isUNCRoot(const char *path)
+{
+ if (path[0] == '\\' && path[1] == '\\') {
+ const char *p;
+ for (p = path + 3; *p; p = CharNext(p)) {
+ if (*p == '\\')
+ break;
+ }
+ if (p[0] && p[1]) {
+ for (p++; *p; p = CharNext(p)) {
+ if (*p == '\\')
+ break;
+ }
+ if (!p[0] || !p[1])
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+win32_stat(const char *path, struct stat *st)
+{
+ const char *p;
+ char *buf1 = ALLOCA_N(char, strlen(path) + 1);
+ char *buf2 = ALLOCA_N(char, MAXPATHLEN);
+ char *s;
+ int len;
+
+ for (p = path, s = buf1; *p; p++, s++) {
+ if (*p == '/')
+ *s = '\\';
+ else
+ *s = *p;
+ }
+ *s = '\0';
+ len = strlen(buf1);
+ p = CharPrev(buf1, buf1 + len);
+ if (isUNCRoot(buf1)) {
+ if (*p != '\\')
+ strcat(buf1, "\\");
+ } else if (*p == '\\' || *p == ':')
+ strcat(buf1, ".");
+ if (_fullpath(buf2, buf1, MAXPATHLEN))
+ return stat(buf2, st);
+ else
+ return -1;
+}
+
static long
filetime_to_clock(FILETIME *ft)
{
diff --git a/win32/win32.h b/win32/win32.h
index ebffc5c8ab..ffbe967703 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -162,6 +162,8 @@ extern "C++" {
#define pclose _pclose
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
+#undef rb_sys_stat
+#define rb_sys_stat win32_stat
/* these are defined in nt.c */
#ifdef __MINGW32__