diff options
author | (no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-04-10 06:09:00 +0000 |
---|---|---|
committer | (no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-04-10 06:09:00 +0000 |
commit | e14f4ff4ab9a2af85a1a0e31e03445fc6c5c0c84 (patch) | |
tree | 05852fad6a378aa3c04243244f793964ccb42d7f | |
parent | 99020d6e50702eb371111d73280eb80b4b29ba5b (diff) |
This commit was manufactured by cvs2svn to create tag
'v1_6_4_preview1'.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_6_4_preview1@1317 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
97 files changed, 4024 insertions, 2168 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 @@ -1,3 +1,798 @@ +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 +816,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 +876,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 +1628,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 +1685,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 +1750,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 +1875,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 +2043,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 +2216,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 +2313,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 +2388,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 +2479,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 +2522,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> @@ -3924,7 +4715,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 +7310,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 +9566,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 +9822,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: @@ -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. @@ -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¤Çºî¶È¤¹¤ëɬÍפ¬¤¢¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡¥ @@ -1171,7 +1171,7 @@ rb_ary_replace_m(ary, ary2) return ary; } -static VALUE +VALUE rb_ary_clear(ary) VALUE ary; { @@ -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 && (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]; @@ -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); @@ -217,7 +251,17 @@ 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); + } + + rb_frozen_class_p(klass); + if (!OBJ_TAINTED(klass)) { + rb_secure(4); + } if (NIL_P(module)) return; if (klass == module) return; @@ -238,16 +282,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 \ @@ -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=. @@ -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"); } @@ -1234,13 +1234,11 @@ 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)(); @@ -1310,7 +1308,7 @@ dln_load(file) } #endif /* hpux */ -#if defined(_AIX) +#if defined(_AIX) && ! defined(_IA64) #define DLN_DEFINED { void (*init_fct)(); @@ -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; { @@ -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,33 +1443,12 @@ 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) { + while (cbase && cbase->nd_next) { rb_ary_push(ary, cbase->nd_clss); cbase = cbase->nd_next; } @@ -1450,7 +1461,7 @@ rb_mod_s_constants() NODE *cbase = RNODE(ruby_frame->cbase); VALUE ary = rb_ary_new(); - while (cbase && cbase->nd_clss != rb_cObject) { + while (cbase) { rb_mod_const_at(cbase->nd_clss, ary); cbase = cbase->nd_next; } @@ -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); } @@ -5167,7 +5251,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(); @@ -5333,6 +5417,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 +5434,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 +5446,7 @@ rb_mod_public(argc, argv, module) VALUE *argv; VALUE module; { + secure_visibility(module); if (argc == 0) { SCOPE_SET(SCOPE_PUBLIC); } @@ -5367,6 +5462,7 @@ rb_mod_protected(argc, argv, module) VALUE *argv; VALUE module; { + secure_visibility(module); if (argc == 0) { SCOPE_SET(SCOPE_PROTECTED); } @@ -5382,6 +5478,7 @@ rb_mod_private(argc, argv, module) VALUE *argv; VALUE module; { + secure_visibility(module); if (argc == 0) { SCOPE_SET(SCOPE_PRIVATE); } @@ -5441,6 +5538,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; @@ -5883,6 +5981,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; } } @@ -5925,6 +6024,7 @@ 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; block->prev = tmp; block = tmp; } @@ -5980,7 +6080,7 @@ static VALUE rb_f_binding(self) VALUE self; { - struct BLOCK *data; + struct BLOCK *data, *p; struct RVarmap *vars; VALUE bind; @@ -6002,10 +6102,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 +6167,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 +6179,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 +6187,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 +6271,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 +6280,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 +6341,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 +6409,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 +6430,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 +6583,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 +6749,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 +6764,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 +6793,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 +6868,7 @@ struct thread { struct tag *tag; VALUE klass; VALUE wrapper; + NODE *cref; int flags; /* misc. states (vmode/rb_trap_immediate/raised) */ @@ -6758,7 +6902,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 +6912,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 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; + curr_thread->safe = level; +} + /* Return the current time as a floating-point number */ static double timeofday() @@ -6791,6 +6968,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 +7046,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 +7086,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 +7177,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 +7238,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 +7517,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 +7530,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,6 +7544,7 @@ 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; @@ -7382,7 +7565,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 +7578,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 +7638,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 +7705,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 +7805,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 +7973,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 +7989,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 +8041,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) @@ -8018,8 +8211,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 +8557,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/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 @@ -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* @@ -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); @@ -1716,6 +1730,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 +2067,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 +2095,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; @@ -2254,6 +2296,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); @@ -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); -} @@ -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 = { @@ -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; @@ -2156,7 +2156,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 +2240,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 +2281,7 @@ prep_stdio(f, mode, klass) return (VALUE)io; } -static VALUE +static void prep_path(io, path) VALUE io; char *path; @@ -2771,6 +2771,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 +2797,7 @@ io_cntl(fd,cmd,narg,io_p) #endif return retval; } +#endif static VALUE rb_io_ctl(io, req, arg, io_p) @@ -3095,8 +3097,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 +3108,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 +3324,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 +3478,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 "©, ♥, ..." - thanks to YANAGAWA Kazuhisa <kjana@os.xaxon.ne.jp> - * bug fix: CGI::unescapeHTML(): support for "	" - 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 "〹" - * 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 @@ -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); @@ -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..e293ca0d72 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> @@ -50,6 +99,8 @@ flock(fd, 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); @@ -57,6 +108,8 @@ flock(fd, operation) /* 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); @@ -78,54 +131,6 @@ flock(fd, operation) } 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 flock(fd, operation) 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 @@ -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) @@ -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; @@ -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; } @@ -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; { @@ -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 @@ -1967,6 +1975,7 @@ yycompile(f, line) cond_stack = 0; class_nest = 0; in_single = 0; + in_def = 0; cur_mid = 0; if (n == 0) node = ruby_eval_tree; @@ -2043,10 +2052,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 +2548,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 +2608,7 @@ parse_quotedwords(term, paren) c = '\\'; break; default: - if (c == term) { + if (c == term || (paren && c == paren)) { tokadd(c); continue; } @@ -2794,7 +2799,7 @@ arg_ambiguous() rb_warning("ambiguous first argument; make sure"); } -#ifndef strtod +#if !defined(strtod) && !defined(HAVE_STDLIB_H) double strtod (); #endif @@ -2919,8 +2924,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 +2983,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 +3310,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 +3394,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 +3618,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 +4123,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 +4377,9 @@ void_expr(node) } } + +static NODE *cond2 _((NODE*)); + static void void_stmts(node) NODE *node; @@ -4390,8 +4395,6 @@ void_stmts(node) } } -static NODE *cond2(); - static int assign_in_cond(node) NODE *node; @@ -4733,12 +4736,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 +4819,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); } @@ -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)); @@ -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); } @@ -3461,7 +3461,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) @@ -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])); } @@ -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 @@ -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 */ } @@ -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]; @@ -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); @@ -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'; @@ -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..445f811a18 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,8 +1076,10 @@ 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 */ @@ -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-10" +#define RUBY_VERSION_CODE 164 +#define RUBY_RELEASE_CODE 20010410 diff --git a/win32/Makefile.sub b/win32/Makefile.sub index 227ab68b18..e5ce57f726 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -30,7 +30,7 @@ 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 = 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..01af07f71a 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 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__ |