From 210367ec889f5910e270d6ea2c7ddb8a8d939e61 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 20 Jan 1999 04:59:39 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r372, which included commits to RCS files with non-trunk default branches. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/base64.rb | 45 +-- lib/cgi-lib.rb | 39 +- lib/complex.rb | 14 +- lib/date.rb | 91 +++-- lib/debug.rb | 12 +- lib/delegate.rb | 100 ++++- lib/e2mmap.rb | 77 +++- lib/eregex.rb | 11 +- lib/finalize.rb | 66 ++-- lib/find.rb | 4 +- lib/ftools.rb | 31 +- lib/ftplib.rb | 1123 ++++++++++++++++++++++++++--------------------------- lib/getopts.rb | 3 +- lib/importenv.rb | 15 +- lib/jcode.rb | 23 +- lib/mailread.rb | 5 +- lib/mathn.rb | 5 +- lib/matrix.rb | 239 +++++++++++- lib/mkmf.rb | 144 +++++-- lib/mutex_m.rb | 60 ++- lib/observer.rb | 8 +- lib/parsearg.rb | 5 +- lib/parsedate.rb | 81 ++-- lib/ping.rb | 33 +- lib/pstore.rb | 39 +- lib/rational.rb | 9 +- lib/shellwords.rb | 16 +- lib/sync.rb | 13 +- lib/thread.rb | 163 ++++++-- lib/thwait.rb | 113 +++--- lib/tracer.rb | 147 +++++-- lib/weakref.rb | 39 +- 32 files changed, 1715 insertions(+), 1058 deletions(-) (limited to 'lib') diff --git a/lib/base64.rb b/lib/base64.rb index 96208a634d..d7461d82e7 100644 --- a/lib/base64.rb +++ b/lib/base64.rb @@ -1,50 +1,25 @@ -def decode64(str) - string = '' - for line in str.split("\n") - line.delete!('^A-Za-z0-9+/') # remove non-base64 chars - line.tr!('A-Za-z0-9+/', ' -_') # convert to uuencoded format - len = ["#{32 + line.length * 3 / 4}"].pack("c") - # compute length byte - string += "#{len}#{line}".unpack("u") # uudecode and concatenate - end - return string -end +require "kconv" -def j2e(str) - while str =~ /\033\$B([^\033]*)\033\(B/ - s = $1 - pre, post = $`, $' - s.gsub!(/./) { |ch| - (ch[0]|0x80).chr - } - str = pre + s + post - end -# str.gsub!(/\033\$B([^\033]*)\033\(B/) { -# $1.gsub!(/./) { |ch| -# (ch[0]|0x80).chr -# } -# } - str +def decode64(str) + str.unpack("m")[0] end def decode_b(str) str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/i) { decode64($1) } + str = Kconv::toeuc(str) + str.gsub!(/=\?SHIFT_JIS\?B\?([!->@-~]+)\?=/i) { + decode64($1) + } + str = Kconv::toeuc(str) str.gsub!(/\n/, ' ') str.gsub!(/\0/, '') - j2e(str) + str end def encode64(bin) - encode = "" - pad = 0 - [bin].pack("u").each do |uu| - len = (2 + (uu[0] - 32)* 4) / 3 - encode << uu[1, len].tr('` -_', 'AA-Za-z0-9+/') - pad += uu.length - 2 - len - end - encode + "=" * (pad % 3) + [bin].pack("m") end def b64encode(bin, len = 60) diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb index 5234e046cc..7033f0f8c1 100644 --- a/lib/cgi-lib.rb +++ b/lib/cgi-lib.rb @@ -1,4 +1,3 @@ -#!/usr/local/bin/ruby # # Get CGI String # @@ -7,26 +6,26 @@ # foo = CGI.new # foo['field'] <== value of 'field' # foo.keys <== array of fields -# foo.inputs <== hash of { => } +# and foo has Hash class methods # if running on Windows(IIS or PWS) then change cwd. if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '') end -require "shellwords.rb" +require "delegate" -class CGI - include Shellwords +class CGI < SimpleDelegator attr("inputs") # original is CGI.pm def read_from_cmdline - words = shellwords(if not ARGV.empty? then + require "shellwords.rb" + words = Shellwords.shellwords(if not ARGV.empty? then ARGV.join(' ') else - print "(offline mode: enter name=value pairs on standard input)\n" + STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty? readlines.join(' ').gsub(/\n/, '') end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')) @@ -47,32 +46,32 @@ class CGI end module_function :escape, :unescape - def initialize - # exception messages should be printed to stdout. - STDERR.reopen(STDOUT) + def initialize(input = $stdin) @inputs = {} case ENV['REQUEST_METHOD'] when "GET" + # exception messages should be printed to stdout. + STDERR.reopen(STDOUT) ENV['QUERY_STRING'] or "" when "POST" - $stdin.read ENV['CONTENT_LENGTH'].to_i + # exception messages should be printed to stdout. + STDERR.reopen(STDOUT) + input.read Integer(ENV['CONTENT_LENGTH']) else read_from_cmdline end.split(/&/).each do |x| key, val = x.split(/=/,2).collect{|x|unescape(x)} - @inputs[key] += ("\0" if @inputs[key]) + (val or "") + if @inputs.include?(key) + @inputs[key] += "\0" + (val or "") + else + @inputs[key] = (val or "") + end end - end - def keys - @inputs.keys + super(@inputs) end - def [](key) - @inputs[key] - end - def CGI.message(msg, title = "") print "Content-type: text/html\n\n" print "" @@ -84,7 +83,7 @@ class CGI end def CGI.error - m = $!.dup + m = $!.to_s.dup m.gsub!(/&/, '&') m.gsub!(/</, '<') m.gsub!(/>/, '>') diff --git a/lib/complex.rb b/lib/complex.rb index aa5d219d2f..59caad6ebc 100644 --- a/lib/complex.rb +++ b/lib/complex.rb @@ -1,8 +1,8 @@ # # complex.rb - # $Release Version: 0.5 $ -# $Revision: 1.1 $ -# $Date: 1996/11/11 04:25:19 $ +# $Revision: 1.3 $ +# $Date: 1998/07/08 10:05:28 $ # by Keiju ISHITSUKA(SHL Japan Inc.) # # -- @@ -59,6 +59,7 @@ def Complex(a, b = 0) end class Complex < Numeric + @RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-' def Complex.generic?(other) other.kind_of?(Integer) or @@ -284,6 +285,11 @@ class Complex < Numeric @real ^ @image end + def inspect + sprintf("Complex(%s, %s)", @real.inspect, @image.inspect) + end + + I = Complex(0,1) attr :real @@ -396,7 +402,7 @@ module Math cos!(z) else Complex(cos!(z.real)*cosh!(z.image), - sin!(z.real)*sinh!(z.image)) + -sin!(z.real)*sinh!(z.image)) end end @@ -405,7 +411,7 @@ module Math sin!(z) else Complex(sin!(z.real)*cosh!(z.image), - -cos!(z.real)*sinh!(z.image)) + cos!(z.real)*sinh!(z.image)) end end diff --git a/lib/date.rb b/lib/date.rb index 998c2e8152..9de49bcbc7 100644 --- a/lib/date.rb +++ b/lib/date.rb @@ -1,8 +1,8 @@ # # Date.rb - # $Release Version: $ -# $Revision: 1.2 $ -# $Date: 1997/02/14 11:05:29 $ +# $Revision: 1.1.1.1.4.5 $ +# $Date: 1998/03/03 02:39:34 $ # by Yasuo OHBA(SHL Japan Inc. Technology Dept.) # # -- @@ -17,15 +17,34 @@ class Date include Comparable + Weektag = [ + "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" + ] + + Monthtag = [ + "January","February","March","April", "May", "June","July", + "August", "September", "October", "November", "December" + ] + + Monthtab = { + "jan"=>1, "feb"=>2, "mar"=>3, "apr"=>4, "may"=>5, "jun"=>6, + "jul"=>7, "aug"=>8, "sep"=>9, "oct"=>10, "nov"=>11, "dec"=>12 + } + def initialize(y = 1, m = 1, d = 1) - if y.kind_of?(String) && y.size == 8 - @year = y[0,4].to_i - @month = y[4,2].to_i - @day = y[6,2].to_i + if y.kind_of?(String) + case y + when /(\d\d\d\d)-?(?:(\d\d)-?(\d\d)?)?/ + @year = $1.to_i + @month = if $2 then $2.to_i else 1 end + @day = if $3 then $3.to_i else 1 end + else + require 'parsedate' + @year, @month, @day = ParseDate.parsedate(y) + end else if m.kind_of?(String) - ml = {"jan"=>1, "feb"=>2, "mar"=>3, "apr"=>4, "may"=>5, "jun"=>6, "jul"=>7, "aug"=>8, "sep"=>9, "oct"=>10, "nov"=>11, "dec"=>12} - m = ml[m.downcase] + m = Monthtab[m.downcase] if m.nil? raise ArgumentError, "Wrong argument. (month)" end @@ -53,25 +72,35 @@ class Date def period return Date.period!(@year, @month, @day) end - + + def jd + return period + 1721423 + end + + def mjd + return jd - 2400000.5 + end + + def to_s + format("%.3s, %.3s %2d %4d", name_of_week, name_of_month, @day, @year) + end + + def inspect + to_s + end + def day_of_week - dl = Date.daylist(@year) - d = Date.jan1!(@year) - for m in 1..(@month - 1) - d += dl[m] - end - d += @day - 1 - if @year == 1752 && @month == 9 && @day >= 14 - d -= (14 - 3) - end - return (d % 7) + return (period + 5) % 7 end - Weektag = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] def name_of_week return Weektag[self.day_of_week] end + def name_of_month + return Monthtag[@month-1] + end + def +(o) if o.kind_of?(Numeric) d = Integer(self.period + o) @@ -80,6 +109,9 @@ class Date else raise TypeError, "Illegal type. (Integer or Date)" end + if d <= 0 + raise ArgumentError, "argument out of range. (self > other)" + end return Date.at(d) end @@ -117,14 +149,13 @@ class Date end def leapyear? - if Date.leapyear(@year) == 1 - return FALSE - else - return TRUE - end + Date.leapyear(@year) != 1 end def _check_date + if @year == nil or @month == nil or @day == nil + raise ArgumentError, "argument contains nil" + end m = Date.daylist(@year) if @month < 1 || @month > 12 raise ArgumentError, "argument(month) out of range." @@ -151,7 +182,7 @@ end def Date.at(d) if d.kind_of? Time - return Date.new(1900+d.year, d.mon+1, d.mday) + return Date.new(d.year, d.mon, d.mday) end if d.kind_of? Date return Date.at(d.period) @@ -189,10 +220,10 @@ def Date.period!(y, m, d) p += dl[mm] end p += (y - 1) * 365 + ((y - 1) / 4.0).to_i - if (y - 1) > 1752 - p -= ((y - 1 - 1752) / 100.0).to_i - p += ((y - 1 - 1752) / 400.0).to_i - p -= (14 - 3) + if y > 1752 + p -= ((y - 1) / 100.0).to_i + p += ((y - 1) / 400.0).to_i + p += 2 elsif y == 1752 && m == 9 && d >= 14 && d <= 30 p -= (14 - 3) end diff --git a/lib/debug.rb b/lib/debug.rb index 432c7b4d19..90270a3fe7 100644 --- a/lib/debug.rb +++ b/lib/debug.rb @@ -11,6 +11,8 @@ class DEBUGGER__ @scripts = {} end + DEBUG_LAST_CMD = [] + def interrupt @stop_next = 1 end @@ -40,6 +42,11 @@ class DEBUGGER__ STDOUT.flush while input = STDIN.gets input.chop! + if input == "" + input = DEBUG_LAST_CMD[0] + else + DEBUG_LAST_CMD[0] = input + end case input when /^b(reak)?\s+(([^:\n]+:)?.+)/ pos = $2 @@ -169,7 +176,7 @@ class DEBUGGER__ printf "no sourcefile available for %s\n", file end when /^p\s+/ - p debug_eval($', binding) + p debug_eval($', binding) #' else v = debug_eval(input, binding) p v unless v == nil @@ -187,10 +194,13 @@ class DEBUGGER__ return "\n" unless line return line end + save = $DEBUG begin + $DEBUG = FALSE f = open(file) lines = @scripts[file] = f.readlines rescue + $DEBUG = save @scripts[file] = TRUE return "\n" end diff --git a/lib/delegate.rb b/lib/delegate.rb index e5943cead8..0771f2feeb 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -1,26 +1,51 @@ # Delegation class that delegates even methods defined in super class, # which can not be covered with normal method_missing hack. # -# Delegater is the abstract delegation class. Need to redefine -# `__getobj__' method in the subclass. SimpleDelegater is the +# Delegator is the abstract delegation class. Need to redefine +# `__getobj__' method in the subclass. SimpleDelegator is the # concrete subclass for simple delegation. # # Usage: # foo = Object.new -# foo = SimpleDelegater.new(foo) -# foo.type # => Object +# foo2 = SimpleDelegator.new(foo) +# foo.hash == foo2.hash # => true +# +# Foo = DelegateClass(Array) +# +# class ExtArray<DelegateClass(Array) +# ... +# end -class Delegater +class Delegator def initialize(obj) - preserved = ["id", "equal?", "__getobj__"] + preserved = ::Kernel.instance_methods + preserved -= ["to_s","to_a","inspect","==","=~","==="] for t in self.type.ancestors preserved |= t.instance_methods - break if t == Delegater + preserved |= t.private_instance_methods + preserved |= t.protected_instance_methods + break if t == Delegator end for method in obj.methods next if preserved.include? method - eval "def self.#{method}(*args); __getobj__.send :#{method}, *args; end" + eval <<-EOS + def self.#{method}(*args, &block) + begin + __getobj__.__send__(:#{method}, *args, &block) + rescue Exception + c = -caller(0).size + if /:in `__getobj__'$/ =~ $@[c-1] #` + n = 1 + else + c -= 1 + n = 2 + end + $@[c,n] = nil + raise + end + end + EOS end end @@ -30,7 +55,7 @@ class Delegater end -class SimpleDelegater<Delegater +class SimpleDelegator<Delegator def initialize(obj) super @@ -41,4 +66,61 @@ class SimpleDelegater<Delegater @obj end + def __setobj__(obj) + @obj = obj + end +end + +# backward compatibility ^_^;;; +Delegater = Delegator +SimpleDelegater = SimpleDelegator + +# +def DelegateClass(superclass) + klass = Class.new + methods = superclass.instance_methods + methods -= ::Kernel.instance_methods + methods |= ["to_s","to_a","inspect","==","=~","==="] + klass.module_eval <<-EOS + def initialize(obj) + @obj = obj + end + EOS + for method in methods + klass.module_eval <<-EOS + def #{method}(*args, &block) + begin + @obj.__send__(:#{method}, *args, &block) + rescue + $@[0,2] = nil + raise + end + end + EOS + end + return klass; + end + +if __FILE__ == $0 + class ExtArray<DelegateClass(Array) + def initialize() + super([]) + end + end + + ary = ExtArray.new + p ary.type + ary.push 25 + p ary + + foo = Object.new + def foo.test + 25 + end + def foo.error + raise 'this is OK' + end + foo2 = SimpleDelegator.new(foo) + p foo.test == foo2.test # => true + foo2.error # raise error! end diff --git a/lib/e2mmap.rb b/lib/e2mmap.rb index d10657bbad..bf860dc5c1 100644 --- a/lib/e2mmap.rb +++ b/lib/e2mmap.rb @@ -1,11 +1,22 @@ # # e2mmap.rb - for ruby 1.1 -# $Release Version: 1.1$ -# $Revision: 1.4 $ -# $Date: 1997/08/18 07:12:12 $ +# $Release Version: 1.2$ +# $Revision: 1.8 $ +# $Date: 1998/08/19 15:22:22 $ # by Keiju ISHITSUKA # # -- +# Usage: +# +# class Foo +# extend Exception2MassageMapper +# def_exception :NewExceptionClass, "message..."[, superclass] +# def_e2meggage ExistingExceptionClass, "message..." +# ... +# end +# +# Foo.Fail NewExceptionClass, arg... +# Foo.Fail ExistingExceptionClass, arg... # # if VERSION < "1.1" @@ -13,40 +24,60 @@ if VERSION < "1.1" else module Exception2MessageMapper - RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/e2mmap.rb,v 1.4 1997/08/18 07:12:12 keiju Exp keiju $-' + @RCS_ID='-$Id: e2mmap.rb,v 1.8 1998/08/19 15:22:22 keiju Exp keiju $-' E2MM = Exception2MessageMapper - + def E2MM.extend_object(cl) super cl.bind(self) end - # 以前との互換性のために残してある. + # backward compatibility def E2MM.extend_to(b) c = eval("self", b) c.extend(self) end -# public :fail - # alias e2mm_fail fail + # public :fail + alias fail! fail + + #def fail(err = nil, *rest) + # super + #end - def fail(err = nil, *rest) - Exception2MessageMapper.fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s + def Fail(err = nil, *rest) + Exception2MessageMapper.Fail Exception2MessageMapper::ErrNotRegisteredException, err.inspect end def bind(cl) self.module_eval %q^ - E2MM_ErrorMSG = {} + E2MM_ErrorMSG = {} unless self.const_defined?(:E2MM_ErrorMSG) # fail(err, *rest) - # err: 例外 - # rest: メッセージに渡すパラメータ + # err: Exception + # rest: Parameter accompanied with the exception # + def self.Fail(err = nil, *rest) + if form = E2MM_ErrorMSG[err] + $! = err.new(sprintf(form, *rest)) + $@ = caller(0) if $@.nil? + $@.shift + # e2mm_fail() + raise() +# elsif self == Exception2MessageMapper +# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s + else +# print "super\n" + super + end + end + + # 過去の互換性のため def self.fail(err = nil, *rest) - $@ = caller(0) if $@.nil? - $@.shift if form = E2MM_ErrorMSG[err] $! = err.new(sprintf(form, *rest)) + $@ = caller(0) if $@.nil? + $@.shift # e2mm_fail() raise() # elsif self == Exception2MessageMapper @@ -63,7 +94,6 @@ else # def_exception(c, m) # c: exception # m: message_form - # 例外cのメッセージをmとする. # def self.def_e2message(c, m) E2MM_ErrorMSG[c] = m @@ -72,13 +102,21 @@ else # def_exception(c, m) # n: exception_name # m: message_form - # s: 例外スーパークラス(デフォルト: Exception) - # 例外名``c''をもつ例外を定義し, そのメッセージをmとする. + # s: superclass_of_exception (default: Exception) + # defines excaption named ``c'', whose message is ``m''. # #def def_exception(n, m) - def self.def_exception(n, m, s = Exception) + def self.def_exception(n, m, s = nil) n = n.id2name if n.kind_of?(Fixnum) + unless s + if defined?(StandardError) + s = StandardError + else + s = Exception + end + end e = Class.new(s) + const_set(n, e) E2MM_ErrorMSG[e] = m # const_get(:E2MM_ErrorMSG)[e] = m @@ -91,4 +129,3 @@ else def_exception(:ErrNotRegisteredException, "not registerd exception(%s)") end end - diff --git a/lib/eregex.rb b/lib/eregex.rb index f214f6a2d4..384d531e0f 100644 --- a/lib/eregex.rb +++ b/lib/eregex.rb @@ -30,10 +30,7 @@ class Regexp end end -p "abc" =~ /b/|/c/ -p "abc" =~ /b/&/c/ - - - - - +if __FILE__ == $0 + p "abc" =~ /b/|/c/ + p "abc" =~ /b/&/c/ +end diff --git a/lib/finalize.rb b/lib/finalize.rb index 9b2ffefcf5..a07e67d093 100644 --- a/lib/finalize.rb +++ b/lib/finalize.rb @@ -1,8 +1,8 @@ # # finalizer.rb - -# $Release Version: 0.2$ -# $Revision: 1.3 $ -# $Date: 1998/01/09 08:09:49 $ +# $Release Version: 0.3$ +# $Revision: 1.4 $ +# $Date: 1998/02/27 05:34:33 $ # by Keiju ISHITSUKA # # -- @@ -11,44 +11,42 @@ # # add(obj, dependant, method = :finalize, *opt) # add_dependency(obj, dependant, method = :finalize, *opt) -# 依存関係 R_method(obj, dependant) の追加 +# add dependency R_method(obj, dependant) # # delete(obj_or_id, dependant, method = :finalize) # delete_dependency(obj_or_id, dependant, method = :finalize) -# 依存関係 R_method(obj, dependant) の削除 +# delete dependency R_method(obj, dependant) # delete_all_dependency(obj_or_id, dependant) -# 依存関係 R_*(obj, dependant) の削除 +# delete dependency R_*(obj, dependant) # delete_by_dependant(dependant, method = :finalize) -# 依存関係 R_method(*, dependant) の削除 +# delete dependency R_method(*, dependant) # delete_all_by_dependant(dependant) -# 依存関係 R_*(*, dependant) の削除 +# delete dependency R_*(*, dependant) # delete_all -# 全ての依存関係の削除. +# delete all dependency R_*(*, *) # # finalize(obj_or_id, dependant, method = :finalize) # finalize_dependency(obj_or_id, dependant, method = :finalize) -# 依存関連 R_method(obj, dependtant) で結ばれるdependantを -# finalizeする. +# finalize the dependant connected by dependency R_method(obj, dependtant). # finalize_all_dependency(obj_or_id, dependant) -# 依存関連 R_*(obj, dependtant) で結ばれるdependantをfinalizeする. +# finalize all dependants connected by dependency R_*(obj, dependtant). # finalize_by_dependant(dependant, method = :finalize) -# 依存関連 R_method(*, dependtant) で結ばれるdependantをfinalizeする. +# finalize the dependant connected by dependency R_method(*, dependtant). # fainalize_all_by_dependant(dependant) -# 依存関連 R_*(*, dependtant) で結ばれるdependantをfinalizeする. +# finalize all dependants connected by dependency R_*(*, dependant). # finalize_all -# Finalizerに登録される全てのdependantをfinalizeする +# finalize all dependency registered to the Finalizer. # # safe{..} -# gc時にFinalizerが起動するのを止める. -# +# stop invoking Finalizer on GC. # module Finalizer - RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.3 1998/01/09 08:09:49 keiju Exp keiju $-' + RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-' # @dependency: {id => [[dependant, method, *opt], ...], ...} - # 依存関係 R_method(obj, dependant) の追加 + # add dependency R_method(obj, dependant) def add_dependency(obj, dependant, method = :finalize, *opt) ObjectSpace.call_finalizer(obj) method = method.intern unless method.kind_of?(Integer) @@ -61,7 +59,7 @@ module Finalizer end alias add add_dependency - # 依存関係 R_method(obj, dependant) の削除 + # delete dependency R_method(obj, dependant) def delete_dependency(id, dependant, method = :finalize) id = id.id unless id.kind_of?(Integer) method = method.intern unless method.kind_of?(Integer) @@ -75,7 +73,7 @@ module Finalizer end alias delete delete_dependency - # 依存関係 R_*(obj, dependant) の削除 + # delete dependency R_*(obj, dependant) def delete_all_dependency(id, dependant) id = id.id unless id.kind_of?(Integer) method = method.intern unless method.kind_of?(Integer) @@ -88,30 +86,29 @@ module Finalizer end end - # 依存関係 R_method(*, dependant) の削除 + # delete dependency R_method(*, dependant) def delete_by_dependant(dependant, method = :finalize) method = method.intern unless method.kind_of?(Integer) - for id in Dependency.keys + for id in @dependency.keys delete(id, dependant, method) end end - # 依存関係 R_*(*, dependant) の削除 + # delete dependency R_*(*, dependant) def delete_all_by_dependant(dependant) for id in @dependency.keys delete_all_dependency(id, dependant) end end - # 依存関連 R_method(obj, dependtant) で結ばれるdependantをfinalizeす - # る. + # finalize the depandant connected by dependency R_method(obj, dependtant) def finalize_dependency(id, dependant, method = :finalize) id = id.id unless id.kind_of?(Integer) method = method.intern unless method.kind_of?(Integer) for assocs in @dependency[id] assocs.delete_if do |d, m, *o| - d.send(m, *o) if ret = d == dependant && m == method + d.send(m, id, *o) if ret = d == dependant && m == method ret end @dependency.delete(id) if assoc.empty? @@ -119,20 +116,20 @@ module Finalizer end alias finalize finalize_dependency - # 依存関連 R_*(obj, dependtant) で結ばれるdependantをfinalizeする. + # finalize all dependants connected by dependency R_*(obj, dependtant) def finalize_all_dependency(id, dependant) id = id.id unless id.kind_of?(Integer) method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| - d.send(m, *o) if ret = d == dependant + d.send(m, id, *o) if ret = d == dependant end @dependency.delete(id) if assoc.empty? end end - # 依存関連 R_method(*, dependtant) で結ばれるdependantをfinalizeする. + # finalize the dependant connected by dependency R_method(*, dependtant) def finalize_by_dependant(dependant, method = :finalize) method = method.intern unless method.kind_of?(Integer) for id in @dependency.keys @@ -140,14 +137,14 @@ module Finalizer end end - # 依存関連 R_*(*, dependtant) で結ばれるdependantをfinalizeする. + # finalize all dependants connected by dependency R_*(*, dependtant) def fainalize_all_by_dependant(dependant) for id in @dependency.keys finalize_all_dependency(id, dependant) end end - # Finalizerに登録されている全てのdependantをfinalizeする + # finalize all dependants registered to the Finalizer. def finalize_all for id, assocs in @dependency for dependant, method, *opt in assocs @@ -157,7 +154,7 @@ module Finalizer end end - # finalize_* を安全に呼び出すためのイテレータ + # method to call finalize_* safely. def safe old_status = Thread.critical Thread.critical = TRUE @@ -167,7 +164,7 @@ module Finalizer Thread.critical = old_status end - # ObjectSpace#add_finalizerへの登録関数 + # registering function to ObjectSpace#add_finalizer def final_of(id) if assocs = @dependency.delete(id) for dependant, method, *opt in assocs @@ -202,4 +199,3 @@ module Finalizer private_class_method :final_of end - diff --git a/lib/find.rb b/lib/find.rb index 5ecc54329c..3f1b82d2b3 100644 --- a/lib/find.rb +++ b/lib/find.rb @@ -1,5 +1,5 @@ # Usage: -# require "find.rb" +# require "find" # # Find.find('/foo','/bar') {|f| ...} # or @@ -12,7 +12,7 @@ module Find while file = path.shift catch(:prune) { yield file - if File.directory? file and not File.symlink? file then + if File.directory? file then d = Dir.open(file) begin for f in d diff --git a/lib/ftools.rb b/lib/ftools.rb index 59bc81b365..7ccc7a4468 100644 --- a/lib/ftools.rb +++ b/lib/ftools.rb @@ -30,7 +30,7 @@ class << File to.binmode begin - while TRUE + while true r = from.sysread(fsize) rsize = r.size w = 0 @@ -40,9 +40,9 @@ class << File end end rescue EOFError - ret = TRUE + ret = true rescue - ret = FALSE + ret = false ensure to.close from.close @@ -50,7 +50,7 @@ class << File ret end - def copy from, to, verbose = FALSE + def copy from, to, verbose = false $stderr.print from, " -> ", catname(from, to), "\n" if verbose syscopy from, to end @@ -59,11 +59,11 @@ class << File # move file - def move from, to, verbose = FALSE + def move from, to, verbose = false to = catname(from, to) $stderr.print from, " -> ", to, "\n" if verbose - if PLATFORM =~ /djgpp|cygwin32|mswin32/ and FileTest.file? to + if PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to unlink to end begin @@ -76,10 +76,10 @@ class << File alias mv move # compare two files -# TRUE: identical -# FALSE: not identical +# true: identical +# false: not identical - def compare from, to, verbose = FALSE + def compare from, to, verbose = false $stderr.print from, " <=> ", to, "\n" if verbose fsize = size(from) fsize = 1024 if fsize < 512 @@ -90,7 +90,7 @@ class << File to = open(to, "r") to.binmode - ret = FALSE + ret = false fr = tr = '' begin @@ -103,7 +103,7 @@ class << File end end rescue - ret = FALSE + ret = false ensure to.close from.close @@ -116,7 +116,7 @@ class << File # unlink files safely def safe_unlink(*files) - verbose = if files[-1].is_a? String then FALSE else files.pop end + verbose = if files[-1].is_a? String then false else files.pop end begin $stderr.print files.join(" "), "\n" if verbose chmod 0777, *files @@ -129,7 +129,7 @@ class << File alias rm_f safe_unlink def makedirs(*dirs) - verbose = if dirs[-1].is_a? String then FALSE else dirs.pop end + verbose = if dirs[-1].is_a? String then false else dirs.pop end # mode = if dirs[-1].is_a? Fixnum then dirs.pop else 0755 end mode = 0755 for dir in dirs @@ -146,14 +146,15 @@ class << File alias o_chmod chmod def chmod(mode, *files) - verbose = if files[-1].is_a? String then FALSE else files.pop end + verbose = if files[-1].is_a? String then false else files.pop end $stderr.printf "chmod %04o %s\n", mode, files.join(" ") if verbose o_chmod mode, *files end - def install(from, to, mode, verbose) + def install(from, to, mode = nil, verbose = false) to = catname(from, to) unless FileTest.exist? to and cmp from, to + unlink to if FileTest.exist? to cp from, to, verbose chmod mode, to, verbose if mode end diff --git a/lib/ftplib.rb b/lib/ftplib.rb index 34ee2f8d62..617d85899b 100644 --- a/lib/ftplib.rb +++ b/lib/ftplib.rb @@ -1,617 +1,574 @@ -### ftplib.rb -*- Mode: ruby; tab-width: 8; -*- +## ftplib.rb -## $Revision: 1.5 $ -## $Date: 1997/09/16 08:03:31 $ -## by maeda shugo <shugo@po.aianet.ne.jp> +# Author: Shugo Maeda <shugo@po.aianet.ne.jp> +# Version: $Revision: 1.7 $ -### Code: +## Code: require "socket" -require "sync" if defined? Thread +require "monitor" -class FTPError < Exception; end +class FTPError < StandardError; end class FTPReplyError < FTPError; end class FTPTempError < FTPError; end class FTPPermError < FTPError; end class FTPProtoError < FTPError; end class FTP - - RCS_ID = '$Id: ftplib.rb,v 1.5 1997/09/16 08:03:31 shugo Exp $' - - FTP_PORT = 21 - CRLF = "\r\n" - - attr :passive, TRUE - attr :return_code, TRUE - attr :debug_mode, TRUE - attr :welcome - attr :lastresp - - THREAD_SAFE = defined?(Thread) != FALSE - - if THREAD_SAFE - def synchronize(mode = :EX) - if @sync - @sync.synchronize(mode) do - yield - end - end - end - - def sock_synchronize(mode = :EX) - if @sock - @sock.synchronize(mode) do - yield - end - end - end - else - def synchronize(mode = :EX) - yield - end - - def sock_synchronize(mode = :EX) - yield - end - end - private :sock_synchronize - - def FTP.open(host, user = nil, passwd = nil, acct = nil) - new(host, user, passwd, acct) - end + + RCS_ID = %q$Id: ftplib.rb,v 1.7 1998/04/13 12:34:24 shugo Exp shugo $ + + include MonitorMixin + + FTP_PORT = 21 + CRLF = "\r\n" + + attr_accessor :passive, :return_code, :debug_mode + attr_reader :welcome, :lastresp + + def FTP.open(host, user = nil, passwd = nil, acct = nil) + new(host, user, passwd, acct) + end - def initialize(host = nil, user = nil, - passwd = nil, acct = nil) - if THREAD_SAFE - @sync = Sync.new - end - @passive = FALSE - @return_code = "\n" - @debug_mode = FALSE - if host - connect(host) - if user - login(user, passwd, acct) - end - end - end - - def open_socket(host, port) - if defined? SOCKSsocket and ENV["SOCKS_SERVER"] - @passive = TRUE - SOCKSsocket.open(host, port) - else - TCPsocket.open(host, port) - end - end - private :open_socket - - def connect(host, port = FTP_PORT) - if @debug_mode - print "connect: ", host, ", ", port, "\n" - end - synchronize do - @sock = open_socket(host, port) - if THREAD_SAFE - @sock.extend Sync_m - end - voidresp - end - end - - def sanitize(s) - if s =~ /^PASS /i - s[0, 5] + "*" * (s.length - 5) - else - s - end - end - private :sanitize - - def putline(line) - if @debug_mode - print "put: ", sanitize(line), "\n" - end - line = line + CRLF - @sock.write(line) - end - private :putline - - def getline - line = @sock.readline # if get EOF, raise EOFError - if line[-2, 2] == CRLF - line = line[0 .. -3] - elsif line[-1] == ?\r or - line[-1] == ?\n - line = line[0 .. -2] - end - if @debug_mode - print "get: ", sanitize(line), "\n" - end - line - end - private :getline - - def getmultiline - line = getline - buff = line - if line[3] == ?- - code = line[0, 3] - begin - line = getline - buff << "\n" << line - end until line[0, 3] == code and line[3] != ?- - end - buff << "\n" - end - private :getmultiline - - def getresp - resp = getmultiline - @lastresp = resp[0, 3] - c = resp[0] - case c - when ?1, ?2, ?3 - return resp - when ?4 - raise FTPTempError, resp - when ?5 - raise FTPPermError, resp - else - raise FTPProtoError, resp - end - end - private :getresp - - def voidresp - resp = getresp - if resp[0] != ?2 - raise FTPReplyError, resp - end - end - private :voidresp - - def sendcmd(cmd) - synchronize do - sock_synchronize do - putline(cmd) - getresp - end - end - end - - def voidcmd(cmd) - synchronize do - sock_synchronize do - putline(cmd) - voidresp - end - end - nil - end - - def sendport(host, port) - hbytes = host.split(".") - pbytes = [port / 256, port % 256] - bytes = hbytes + pbytes - cmd = "PORT " + bytes.join(",") - voidcmd(cmd) - end - private :sendport - - def makeport - sock = TCPserver.open(0) - port = sock.addr[1] - host = TCPsocket.getaddress(@sock.addr[2]) - resp = sendport(host, port) - sock - end - private :makeport - - def transfercmd(cmd) - if @passive - host, port = parse227(sendcmd("PASV")) - conn = open_socket(host, port) - resp = sendcmd(cmd) - if resp[0] != ?1 - raise FTPReplyError, resp - end - else - sock = makeport - resp = sendcmd(cmd) - if resp[0] != ?1 - raise FTPReplyError, resp - end - conn = sock.accept - end - conn - end - private :transfercmd - - def getaddress - thishost = Socket.gethostname - if not thishost.index(".") - thishost = Socket.gethostbyname(thishost)[0] - end - if ENV.has_key?("LOGNAME") - realuser = ENV["LOGNAME"] - elsif ENV.has_key?("USER") - realuser = ENV["USER"] - else - realuser = "anonymous" - end - realuser + "@" + thishost - end - private :getaddress - - def login(user = "anonymous", passwd = nil, acct = nil) - if user == "anonymous" and passwd == nil - passwd = getaddress - end - - resp = "" - synchronize do - resp = sendcmd('USER ' + user) - if resp[0] == ?3 - resp = sendcmd('PASS ' + passwd) - end - if resp[0] == ?3 - resp = sendcmd('ACCT ' + acct) - end - end - if resp[0] != ?2 - raise FTPReplyError, resp - end - @welcome = resp - end + def initialize(host = nil, user = nil, passwd = nil, acct = nil) + super + @passive = false + @return_code = "\n" + @debug_mode = false + if host + connect(host) + if user + login(user, passwd, acct) + end + end + end + + def open_socket(host, port) + if defined? SOCKSsocket and ENV["SOCKS_SERVER"] + @passive = true + return SOCKSsocket.open(host, port) + else + return TCPsocket.open(host, port) + end + end + private :open_socket + + def connect(host, port = FTP_PORT) + if @debug_mode + print "connect: ", host, ", ", port, "\n" + end + synchronize do + @sock = open_socket(host, port) + voidresp + end + end + + def sanitize(s) + if s =~ /^PASS /i + return s[0, 5] + "*" * (s.length - 5) + else + return s + end + end + private :sanitize + + def putline(line) + if @debug_mode + print "put: ", sanitize(line), "\n" + end + line = line + CRLF + @sock.write(line) + end + private :putline + + def getline + line = @sock.readline # if get EOF, raise EOFError + if line[-2, 2] == CRLF + line = line[0 .. -3] + elsif line[-1] == ?\r or + line[-1] == ?\n + line = line[0 .. -2] + end + if @debug_mode + print "get: ", sanitize(line), "\n" + end + return line + end + private :getline + + def getmultiline + line = getline + buff = line + if line[3] == ?- + code = line[0, 3] + begin + line = getline + buff << "\n" << line + end until line[0, 3] == code and line[3] != ?- + end + return buff << "\n" + end + private :getmultiline + + def getresp + resp = getmultiline + @lastresp = resp[0, 3] + c = resp[0] + case c + when ?1, ?2, ?3 + return resp + when ?4 + raise FTPTempError, resp + when ?5 + raise FTPPermError, resp + else + raise FTPProtoError, resp + end + end + private :getresp + + def voidresp + resp = getresp + if resp[0] != ?2 + raise FTPReplyError, resp + end + end + private :voidresp + + def sendcmd(cmd) + synchronize do + putline(cmd) + return getresp + end + end - def retrbinary(cmd, blocksize, callback = Proc.new) - synchronize do - voidcmd("TYPE I") - conn = transfercmd(cmd) - while TRUE - data = conn.read(blocksize) - break if data == nil - callback.call(data) - end - conn.close - voidresp - end - end + def voidcmd(cmd) + synchronize do + putline(cmd) + voidresp + end + end - def retrlines(cmd, callback = nil) - if iterator? - callback = Proc.new - elsif not callback.is_a?(Proc) - callback = Proc.new {|line| print line, "\n"} - end - synchronize do - voidcmd("TYPE A") - conn = transfercmd(cmd) - while TRUE - line = conn.gets - break if line == nil - if line[-2, 2] == CRLF - line = line[0 .. -3] - elsif line[-1] == ?\n - line = line[0 .. -2] - end - callback.call(line) - end - conn.close - voidresp - end - end + def sendport(host, port) + hbytes = host.split(".") + pbytes = [port / 256, port % 256] + bytes = hbytes + pbytes + cmd = "PORT " + bytes.join(",") + voidcmd(cmd) + end + private :sendport + + def makeport + sock = TCPserver.open(0) + port = sock.addr[1] + host = TCPsocket.getaddress(@sock.addr[2]) + resp = sendport(host, port) + return sock + end + private :makeport + + def transfercmd(cmd) + if @passive + host, port = parse227(sendcmd("PASV")) + conn = open_socket(host, port) + resp = sendcmd(cmd) + if resp[0] != ?1 + raise FTPReplyError, resp + end + else + sock = makeport + resp = sendcmd(cmd) + if resp[0] != ?1 + raise FTPReplyError, resp + end + conn = sock.accept + end + return conn + end + private :transfercmd + + def getaddress + thishost = Socket.gethostname + if not thishost.index(".") + thishost = Socket.gethostbyname(thishost)[0] + end + if ENV.has_key?("LOGNAME") + realuser = ENV["LOGNAME"] + elsif ENV.has_key?("USER") + realuser = ENV["USER"] + else + realuser = "anonymous" + end + return realuser + "@" + thishost + end + private :getaddress - def storbinary(cmd, file, blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - synchronize do - voidcmd("TYPE I") - conn = transfercmd(cmd) - while TRUE - buf = file.read(blocksize) - break if buf == nil - conn.write(buf) - if use_callback - callback.call(buf) - end - end - conn.close - voidresp - end - end + def login(user = "anonymous", passwd = nil, acct = nil) + if user == "anonymous" and passwd == nil + passwd = getaddress + end + + resp = "" + synchronize do + resp = sendcmd('USER ' + user) + if resp[0] == ?3 + resp = sendcmd('PASS ' + passwd) + end + if resp[0] == ?3 + resp = sendcmd('ACCT ' + acct) + end + end + if resp[0] != ?2 + raise FTPReplyError, resp + end + @welcome = resp + end + + def retrbinary(cmd, blocksize, callback = Proc.new) + synchronize do + voidcmd("TYPE I") + conn = transfercmd(cmd) + loop do + data = conn.read(blocksize) + break if data == nil + callback.call(data) + end + conn.close + voidresp + end + end - def storlines(cmd, file, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - synchronize do - voidcmd("TYPE A") - conn = transfercmd(cmd) - while TRUE - buf = file.gets - break if buf == nil - if buf[-2, 2] != CRLF - if buf[-1] == ?\r or - buf[-1] == ?\n - buf = buf[0 .. -2] - end - buf = buf + CRLF - end - conn.write(buf) - if use_callback - callback.call(buf) - end - end - conn.close - voidresp - end - end + def retrlines(cmd, callback = nil) + if iterator? + callback = Proc.new + elsif not callback.is_a?(Proc) + callback = Proc.new {|line| print line, "\n"} + end + synchronize do + voidcmd("TYPE A") + conn = transfercmd(cmd) + loop do + line = conn.gets + break if line == nil + if line[-2, 2] == CRLF + line = line[0 .. -3] + elsif line[-1] == ?\n + line = line[0 .. -2] + end + callback.call(line) + end + conn.close + voidresp + end + end + + def storbinary(cmd, file, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + synchronize do + voidcmd("TYPE I") + conn = transfercmd(cmd) + loop do + buf = file.read(blocksize) + break if buf == nil + conn.write(buf) + callback.call(buf) if use_callback + end + conn.close + voidresp + end + end - def getbinaryfile(remotefile, localfile, - blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile, "w") - begin + def storlines(cmd, file, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + synchronize do + voidcmd("TYPE A") + conn = transfercmd(cmd) + loop do + buf = file.gets + break if buf == nil + if buf[-2, 2] != CRLF + if buf[-1] == ?\r or + buf[-1] == ?\n + buf = buf[0 .. -2] + end + buf = buf + CRLF + end + conn.write(buf) + callback.call(buf) if use_callback + end + conn.close + voidresp + end + end + + def getbinaryfile(remotefile, localfile, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile, "w") + begin f.binmode - retrbinary("RETR " + remotefile, blocksize) do |data| - f.write(data) - if use_callback - callback.call(data) - end - end - ensure - f.close + retrbinary("RETR " + remotefile, blocksize) do |data| + f.write(data) + callback.call(data) if use_callback end - end + ensure + f.close + end + end - def gettextfile(remotefile, localfile, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile, "w") - begin - retrlines("RETR " + remotefile) do |line| - line = line + @return_code - f.write(line) - if use_callback - callback.call(line) - end - end - ensure - f.close - end - end + def gettextfile(remotefile, localfile, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile, "w") + begin + retrlines("RETR " + remotefile) do |line| + line = line + @return_code + f.write(line) + callback.call(line) if use_callback + end + ensure + f.close + end + end - def putbinaryfile(localfile, remotefile, - blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile) - begin + def putbinaryfile(localfile, remotefile, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile) + begin f.binmode - storbinary("STOR " + remotefile, f, blocksize) do |data| - if use_callback - callback.call(data) - end - end - ensure - f.close + storbinary("STOR " + remotefile, f, blocksize) do |data| + callback.call(data) if use_callback end - end - - def puttextfile(localfile, remotefile, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile) - begin - storlines("STOR " + remotefile, f) do |line| - if use_callback - callback.call(line) - end - end - ensure - f.close - end - end - - def acct(account) - cmd = "ACCT " + account - voidcmd(cmd) - end + ensure + f.close + end + end + + def puttextfile(localfile, remotefile, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile) + begin + storlines("STOR " + remotefile, f) do |line| + callback.call(line) if use_callback + end + ensure + f.close + end + end - def nlst(dir = nil) - cmd = "NLST" - if dir - cmd = cmd + " " + dir - end - files = [] + def acct(account) + cmd = "ACCT " + account + voidcmd(cmd) + end + + def nlst(dir = nil) + cmd = "NLST" + if dir + cmd = cmd + " " + dir + end + files = [] + retrlines(cmd) do |line| + files.push(line) + end + return files + end + + def list(*args, &block) + cmd = "LIST" + args.each do |arg| + cmd = cmd + " " + arg + end + if block + retrlines(cmd, &block) + else + lines = [] retrlines(cmd) do |line| - files.push(line) + lines << line end - files - end - - def list(*args) - cmd = "LIST" - if iterator? - callback = Proc.new - elsif args[-1].is_a?(Proc) - callback = args.pop - else - callback = nil - end - args.each do |arg| - cmd = cmd + " " + arg - end - retrlines(cmd, callback) - end - alias ls list - alias dir list - - def rename(fromname, toname) - resp = sendcmd("RNFR " + fromname) - if resp[0] != ?3 - raise FTPReplyError, resp - end - voidcmd("RNTO " + toname) - end - - def delete(filename) - resp = sendcmd("DELE " + filename) - if resp[0, 3] == "250" - return - elsif resp[0] == ?5 - raise FTPPermError, resp - else - raise FTPReplyError, resp - end - end - - def chdir(dirname) - if dirname == ".." - begin - voidcmd("CDUP") - return - rescue FTPPermError - if $![0, 3] != "500" - raise FTPPermError, $! - end - end - end - cmd = "CWD " + dirname - voidcmd(cmd) - end - - def size(filename) - resp = sendcmd("SIZE " + filename) - if resp[0, 3] == "213" - return Integer(resp[3 .. -1].strip) - end - end - - def mkdir(dirname) - resp = sendcmd("MKD " + dirname) - return parse257(resp) - end - - def rmdir(dirname) - voidcmd("RMD " + dirname) - end + return lines + end + end + alias ls list + alias dir list + + def rename(fromname, toname) + resp = sendcmd("RNFR " + fromname) + if resp[0] != ?3 + raise FTPReplyError, resp + end + voidcmd("RNTO " + toname) + end + + def delete(filename) + resp = sendcmd("DELE " + filename) + if resp[0, 3] == "250" + return + elsif resp[0] == ?5 + raise FTPPermError, resp + else + raise FTPReplyError, resp + end + end + + def chdir(dirname) + if dirname == ".." + begin + voidcmd("CDUP") + return + rescue FTPPermError + if $![0, 3] != "500" + raise FTPPermError, $! + end + end + end + cmd = "CWD " + dirname + voidcmd(cmd) + end - def pwd - resp = sendcmd("PWD") + def size(filename) + voidcmd("TYPE I") + resp = sendcmd("SIZE " + filename) + if resp[0, 3] != "213" + raise FTPReplyError, resp + end + return resp[3..-1].strip + end + + MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/ + + def mtime(filename, local = false) + str = mdtm(filename) + ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i} + return local ? Time.local(*ary) : Time.gm(*ary) + end + + def mkdir(dirname) + resp = sendcmd("MKD " + dirname) + return parse257(resp) + end + + def rmdir(dirname) + voidcmd("RMD " + dirname) + end + + def pwd + resp = sendcmd("PWD") return parse257(resp) - end - alias getdir pwd - - def system - resp = sendcmd("SYST") - if resp[0, 3] != "215" - raise FTPReplyError, resp - end - return resp[4 .. -1] - end - - def abort - line = "ABOR" + CRLF - resp = "" - sock_synchronize do - print "put: ABOR\n" if @debug_mode - @sock.send(line, Socket::MSG_OOB) - resp = getmultiline - end - unless ["426", "226", "225"].include?(resp[0, 3]) - raise FTPProtoError, resp - end - resp - end - - def status - line = "STAT" + CRLF - resp = "" - sock_synchronize do - print "put: STAT\n" if @debug_mode - @sock.send(line, Socket::MSG_OOB) - resp = getresp - end - resp - end - - def help(arg = nil) - cmd = "HELP" - if arg - cmd = cmd + " " + arg - end - sendcmd(cmd) - end - - def quit - voidcmd("QUIT") - end - - def close - @sock.close if @sock and not @sock.closed? - end + end + alias getdir pwd + + def system + resp = sendcmd("SYST") + if resp[0, 3] != "215" + raise FTPReplyError, resp + end + return resp[4 .. -1] + end + + def abort + line = "ABOR" + CRLF + print "put: ABOR\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + resp = getmultiline + unless ["426", "226", "225"].include?(resp[0, 3]) + raise FTPProtoError, resp + end + return resp + end + def status + line = "STAT" + CRLF + print "put: STAT\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + return getresp + end + + def mdtm(filename) + resp = sendcmd("MDTM " + filename) + if resp[0, 3] == "213" + return resp[3 .. -1].strip + end + end + + def help(arg = nil) + cmd = "HELP" + if arg + cmd = cmd + " " + arg + end + sendcmd(cmd) + end + + def quit + voidcmd("QUIT") + end + + def close + @sock.close if @sock and not @sock.closed? + end + def closed? @sock == nil or @sock.closed? end - def parse227(resp) - if resp[0, 3] != "227" - raise FTPReplyError, resp - end - left = resp.index("(") - right = resp.index(")") - if left == nil or right == nil - raise FTPProtoError, resp - end - numbers = resp[left + 1 .. right - 1].split(",") - if numbers.length != 6 - raise FTPProtoError, resp - end - host = numbers[0, 4].join(".") - port = (Integer(numbers[4]) << 8) + Integer(numbers[5]) - return host, port - end - private :parse227 - - def parse257(resp) - if resp[0, 3] != "257" - raise FTPReplyError, resp - end - if resp[3, 2] != ' "' - return "" - end - dirname = "" - i = 5 - n = resp.length - while i < n - c = resp[i, 1] - i = i + 1 - if c == '"' - if i > n or resp[i, 1] != '"' - break - end - i = i + 1 - end - dirname = dirname + c - end - return dirname - end - private :parse257 + def parse227(resp) + if resp[0, 3] != "227" + raise FTPReplyError, resp + end + left = resp.index("(") + right = resp.index(")") + if left == nil or right == nil + raise FTPProtoError, resp + end + numbers = resp[left + 1 .. right - 1].split(",") + if numbers.length != 6 + raise FTPProtoError, resp + end + host = numbers[0, 4].join(".") + port = (numbers[4].to_i << 8) + numbers[5].to_i + return host, port + end + private :parse227 + + def parse257(resp) + if resp[0, 3] != "257" + raise FTPReplyError, resp + end + if resp[3, 2] != ' "' + return "" + end + dirname = "" + i = 5 + n = resp.length + while i < n + c = resp[i, 1] + i = i + 1 + if c == '"' + if i > n or resp[i, 1] != '"' + break + end + i = i + 1 + end + dirname = dirname + c + end + return dirname + end + private :parse257 end + +## ftplib.rb ends here diff --git a/lib/getopts.rb b/lib/getopts.rb index 6929f7e4fd..9e1e8a2cf6 100644 --- a/lib/getopts.rb +++ b/lib/getopts.rb @@ -1,4 +1,3 @@ -#!/usr/local/bin/ruby # # getopts.rb - # $Release Version: $ @@ -11,7 +10,7 @@ # # -$RCS_ID="$Header$" +$RCS_ID=%q$Header$ def isSingle(lopt) if lopt.index(":") diff --git a/lib/importenv.rb b/lib/importenv.rb index 41253765ea..10b289199c 100644 --- a/lib/importenv.rb +++ b/lib/importenv.rb @@ -21,9 +21,12 @@ for k,v in ENV EOS end -p $TERM -$TERM = nil -p $TERM -p ENV["TERM"] -$TERM = "foo" -p ENV["TERM"] +if __FILE__ == $0 + p $TERM + $TERM = nil + p $TERM + p ENV["TERM"] + $TERM = "foo" + p ENV["TERM"] +end + diff --git a/lib/jcode.rb b/lib/jcode.rb index 40ab48ddac..50b7beee9d 100644 --- a/lib/jcode.rb +++ b/lib/jcode.rb @@ -11,13 +11,13 @@ class String alias original_succ succ private :original_succ - def mbchar?(c) + def mbchar? if $KCODE =~ /^s/i - c =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n + self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n elsif $KCODE =~ /^e/i - c =~ /[\xa1-\xfe][\xa1-\xfe]/n + self =~ /[\xa1-\xfe][\xa1-\xfe]/n else - FALSE + false end end @@ -25,12 +25,13 @@ class String if self[-2] && self[-2] & 0x80 != 0 s = self.dup s[-1] += 1 - s[-1] += 1 if !mbchar?(s) + s[-1] += 1 if !s.mbchar? return s else original_succ end end + alias next succ def upto(to) return if self > to @@ -41,7 +42,7 @@ class String if self[0..-2] == to[0..-2] first = self[-2].chr for c in self[-1] .. to[-1] - if mbchar?(first+c.chr) + if (first+c.chr).mbchar? yield self[0..-2]+c.chr end end @@ -103,7 +104,7 @@ class String end def tr(from, to) - self.dup.tr!(from, to) + (str = self.dup).tr!(from, to) or str end def delete!(del) @@ -126,7 +127,7 @@ class String end def delete(del) - self.dup.delete!(del) + (str = self.dup).delete!(del) or str end def squeeze!(del=nil) @@ -154,7 +155,7 @@ class String end def squeeze(del=nil) - self.dup.squeeze!(del) + (str = self.dup).squeeze!(del) or str end def tr_s!(from, to) @@ -187,7 +188,7 @@ class String end def tr_s(from, to) - self.dup.tr_s!(from,to) + (str = self.dup).tr_s!(from,to) or str end alias original_chop! chop! @@ -201,7 +202,7 @@ class String end def chop - self.dup.chop! + (str = self.dup).chop! or str end end $VERBOSE = $vsave diff --git a/lib/mailread.rb b/lib/mailread.rb index a5d60c84b4..5e46606c09 100644 --- a/lib/mailread.rb +++ b/lib/mailread.rb @@ -1,7 +1,7 @@ class Mail def initialize(f) - unless f.kind_of?(IO) + unless defined? f.gets f = open(f, "r") opened = true end @@ -15,7 +15,8 @@ class Mail break if /^$/ # end of header if /^(\S+):\s*(.*)/ - @header[attr = $1.capitalize!] = $2 + (attr = $1).capitalize! + @header[attr] = $2 elsif attr sub!(/^\s*/, '') @header[attr] += "\n" + $_ diff --git a/lib/mathn.rb b/lib/mathn.rb index fdf27f6771..265ef1337f 100644 --- a/lib/mathn.rb +++ b/lib/mathn.rb @@ -1,8 +1,8 @@ # # mathn.rb - # $Release Version: 0.5 $ -# $Revision: 1.1 $ -# $Date: 1997/07/03 04:43:47 $ +# $Revision: 1.1.1.1.4.1 $ +# $Date: 1998/01/16 12:36:05 $ # by Keiju ISHITSUKA(SHL Japan Inc.) # # -- @@ -96,6 +96,7 @@ class Prime @counts.push @seed + @seed return @seed end + alias next succ def each loop do diff --git a/lib/matrix.rb b/lib/matrix.rb index 394c66f098..64b0738e1b 100644 --- a/lib/matrix.rb +++ b/lib/matrix.rb @@ -1,9 +1,8 @@ -#!/usr/local/bin/ruby # # matrix.rb - # $Release Version: 1.0$ -# $Revision: 1.0 $ -# $Date: 97/05/23 11:35:28 $ +# $Revision: 1.6 $ +# $Date: 1998/07/31 03:39:49 $ # Original Version from Smalltalk-80 version # on July 23, 1985 at 8:37:17 am # by Keiju ISHITSUKA @@ -18,9 +17,158 @@ # : # rown] # -# column: 列 -# row: 行 # +# module ExceptionForMatrix:: +# Exceptions: +# ErrDimensionMismatch +# number of column/row do not match +# ErrNotRegular +# not a regular matrix +# ErrOperationNotDefined +# specified operator is not defined (yet) +# +# class Matrix +# include ExceptionForMatrix +# +# Methods: +# class methods: +# Matrix.[](*rows) +# creates a matrix where `rows' indicates rows. +# `rows' is an array of arrays, +# e.g, Matrix[[11, 12], [21, 22]] +# Matrix.rows(rows, copy = TRUE) +# creates a matrix where `rows' indicates rows. +# if optional argument `copy' is false, use the array as +# internal structure of the metrix without copying. +# Matrix.columns(columns) +# creates a new matrix using `columns` as set of colums vectors. +# Matrix.diagonal(*values) +# creates a matrix where `columns' indicates columns. +# Matrix.scalar(n, value) +# creates a diagonal matrix such that the diagal compornents is +# given by `values'. +# Matrix.scalar(n, value) +# creates an n-by-n scalar matrix such that the diagal compornent is +# given by `value'. +# Matrix.identity(n) +# Matrix.unit(n) +# Matrix.I(n) +# creates an n-by-n unit matrix. +# Matrix.zero(n) +# creates an n-by-n zero matrix. +# Matrix.row_vector(row) +# creates a 1-by-n matrix such the row vector is `row'. +# `row' is specifed as a Vector or an Array. +# Matrix.column_vector(column) +# creates a 1-by-n matrix such that column vector is `column'. +# `column' is specifed as a Vector or an Array. +# accessing: +# [](i, j) +# returns (i,j) compornent +# row_size +# returns the number of rows +# column_size +# returns the number of columns +# row(i) +# returns the i-th row vector. +# when the block is supplied for the method, the block is iterated +# over all row vectors. +# column(j) +# returns the jth column vector. +# when the block is supplied for the method, the block is iterated +# over all column vectors. +# collect +# map +# creates a matrix which is the result of iteration of given +# block over all compornents. +# minor(*param) +# returns sub matrix. parameter is specified as the following: +# 1. from_row, row_size, from_col, size_col +# 2. from_row..to_row, from_col..to_col +# TESTING: +# regular? +# Is regular? +# singular? +# Is singular? i.e. Is non-regular? +# square? +# Is square? +# ARITHMETIC: +# *(m) +# times +# +(m) +# plus +# -(m) +# minus +# /(m) +# self * m.inv +# inverse +# inv +# inverse +# ** +# power +# Matrix functions: +# determinant +# det +# returns the determinant +# rank +# returns the rank +# trace +# tr +# returns the trace +# transpose +# t +# returns the transposed +# CONVERTING: +# coerce(other) +# row_vectors +# array of row vectors +# column_vectors +# array of column vectors +# to_a +# converts each element to Array +# to_f +# converts each element to Float +# to_i +# converts each element to Integer +# to_r +# converts each element to Rational +# PRINTING: +# to_s +# returns string representation +# inspect +# +# class Vector +# include ExceptionForMatrix +# +# INSTANCE CREATION: +# Vector.[](*array) +# Vector.elements(array, copy = TRUE) +# ACCSESSING: +# [](i) +# size +# ENUMRATIONS: +# each2(v) +# collect2(v) +# ARITHMETIC: +# *(x) "is matrix or number" +# +(v) +# -(v) +# VECTOR FUNCTIONS: +# inner_product(v) +# collect +# map +# map2(v) +# r +# CONVERTING: +# covector +# to_a +# to_f +# to_i +# to_r +# coerce(other) +# PRINTING: +# to_s +# inspect require "e2mmap.rb" @@ -36,8 +184,8 @@ module ExceptionForMatrix end class Matrix - RCS_ID='-$Header: ruby-mode,v 1.2 91/04/20 17:24:57 keiju Locked $-' - + @RCS_ID='-$Id: matrix.rb,v 1.6 1998/07/31 03:39:49 keiju Exp keiju $-' + include ExceptionForMatrix # instance creations @@ -144,6 +292,7 @@ class Matrix if iterator? for e in @rows[i] yield e + end else Vector.elements(@rows[i]) @@ -211,6 +360,38 @@ class Matrix column_size == row_size end + # COMPARING + def ==(other) + return FALSE unless Matrix === other + + other.compare_by_row_vectors(@rows) + end + alias eql? == + + def compare_by_row_vectors(rows) + return FALSE unless @rows.size == rows.size + + 0.upto(@rows.size - 1) do + |i| + return FALSE unless @rows[i] == rows[i] + end + TRUE + end + + def clone + Matrix.rows(@rows) + end + + def hash + value = 0 + for row in @rows + for e in row + value ^= e.hash + end + end + return value + end + # ARITHMETIC def *(m) #is matrix or vector or number" @@ -297,6 +478,25 @@ class Matrix } Matrix.rows(rows, FALSE) end + + def /(other) + case other + when Numeric + rows = @rows.collect { + |row| + row.collect { + |e| + e / other + } + } + return Matrix.rows(rows, FALSE) + when Matrix + return self * other.inverse + else + x, y = other.coerce(self) + rerurn x / y + end + end def inverse Matrix.fail ErrDimensionMismatch unless square? @@ -597,13 +797,12 @@ end #---------------------------------------------------------------------- class Vector include ExceptionForMatrix - #INSTANCE CREATION private_class_method :new def Vector.[](*array) - new(:init_elements, array, copy = FALSE) + new(:init_elements, array, FALSE) end def Vector.elements(array, copy = TRUE) @@ -649,6 +848,26 @@ class Vector end end + # COMPARING + def ==(other) + return FALSE unless Vector === other + + other.compare_by(@elements) + end + alias eqn? == + + def compare_by(elements) + @elements == elements + end + + def clone + Vector.elements(@elements) + end + + def hash + @elements.hash + end + # ARITHMETIC def *(x) "is matrix or number" @@ -733,7 +952,7 @@ class Vector for e in @elements v += e*e end - return v.sqrt + return Math.sqrt(v) end # CONVERTING diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 2bf3684920..7e131fe890 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -1,7 +1,8 @@ -# module to create Makefile for extention modules +# module to create Makefile for extension modules # invoke like: ruby -r mkmf extconf.rb require 'rbconfig' +require 'find' include Config @@ -36,6 +37,7 @@ $install = CONFIG["INSTALL_PROGRAM"] $install_data = CONFIG["INSTALL_DATA"] if $install !~ /^\// then $install = CONFIG["srcdir"]+"/"+$install + $install_data = CONFIG["srcdir"]+"/"+$install_data end if File.exist? $archdir + "/ruby.h" @@ -47,28 +49,60 @@ else exit 1 end -nul = "> /dev/null" - CFLAGS = CONFIG["CFLAGS"] if PLATFORM == "m68k-human" - nul = "> nul" CFLAGS.gsub!(/-c..-stack=[0-9]+ */, '') end -if $DEBUG - nul = "" +if /win32|djgpp|mingw32|m68k-human/i =~ PLATFORM + $null = open("nul", "w") +else + $null = open("/dev/null", "w") +end +LINK = "#{CONFIG['CC']} -o conftest -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s #{CONFIG['LDFLAGS']} %s conftest.c #{CONFIG['LIBS']} %s" +CPP = "#{CONFIG['CPP']} -E -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s conftest.c" + +$orgerr = $stderr.dup +$orgout = $stdout.dup +def xsystem command + if $DEBUG + print command, "\n" + return system(command) + end + $stderr.reopen($null) + $stdout.reopen($null) + r = system(command) + $stderr.reopen($orgerr) + $stdout.reopen($orgout) + return r end -LINK = CONFIG["CC"]+" -o conftest -I#{$srcdir} " + CFLAGS + " %s " + CONFIG["LDFLAGS"] + " %s conftest.c " + CONFIG["LIBS"] + "%s " + nul + " 2>&1" -CPP = CONFIG["CPP"] + " -E -I#{$srcdir} " + CFLAGS + " %s conftest.c " + nul + " 2>&1" def try_link(libs) - system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs)) end def try_cpp - system(format(CPP, $CFLAGS)) + xsystem(format(CPP, $CFLAGS)) +end + +def install_rb(mfile) + path = [] + dir = [] + Find.find("lib") do |f| + next unless /\.rb$/ =~ f + f = f[4..-1] + path.push f + dir |= File.dirname(f) + end + for f in dir + next if f == "." + mfile.printf "\t@test -d $(libdir)/%s || mkdir $(libdir)/%s\n", f, f + end + for f in path + mfile.printf "\t$(INSTALL_DATA) lib/%s $(libdir)/%s\n", f, f + end end -def have_library(lib, func) +def have_library(lib, func="main") printf "checking for %s() in -l%s... ", func, lib STDOUT.flush if $lib_cache[lib] @@ -86,32 +120,40 @@ def have_library(lib, func) end end - cfile = open("conftest.c", "w") - cfile.printf "\ + if func && func != "" + cfile = open("conftest.c", "w") + cfile.printf "\ int main() { return 0; } int t() { %s(); return 0; } ", func - cfile.close + cfile.close - begin + begin + if $libs + libs = "-l" + lib + " " + $libs + else + libs = "-l" + lib + end + unless try_link(libs) + $lib_cache[lib] = 'no' + $cache_mod = TRUE + print "no\n" + return FALSE + end + ensure + system "rm -f conftest*" + end + else if $libs libs = "-l" + lib + " " + $libs else libs = "-l" + lib end - unless try_link(libs) - $lib_found[lib] = 'no' - $found = TRUE - print "no\n" - return FALSE - end - ensure - system "rm -f conftest*" end $libs = libs - $lib_found[lib] = 'yes' - $found = TRUE + $lib_cache[lib] = 'yes' + $cache_mod = TRUE print "yes\n" return TRUE end @@ -221,9 +263,15 @@ def create_makefile(target) $defs.push(format("-DEXTLIB='%s'", libs.join(","))) end $libs = "" unless $libs + $DLDFLAGS = CONFIG["DLDFLAGS"] + + if PLATFORM =~ /beos/ + $libs = $libs + " -lruby" + $DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib" + end - if !$objs then - $objs = Dir["*.c"] + unless $objs then + $objs = Dir["*.{c,cc}"] for f in $objs f.sub!(/\.(c|cc)$/, ".o") end @@ -239,15 +287,18 @@ SHELL = /bin/sh srcdir = #{$srcdir} hdrdir = #{$hdrdir} -CC = gcc +CC = #{CONFIG["CC"]} -CFLAGS = #{CONFIG["CCDLFLAGS"]} -I#{$hdrdir} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")} -DLDFLAGS = #{CONFIG["DLDFLAGS"]} #{$LDFLAGS} +prefix = #{CONFIG["prefix"]} +CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) -I#{CONFIG["includedir"]} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")} +CXXFLAGS = $(CFLAGS) +DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS} LDSHARED = #{CONFIG["LDSHARED"]} prefix = #{CONFIG["prefix"]} exec_prefix = #{CONFIG["exec_prefix"]} -libdir = #{$archdir} +libdir = #{$libdir} +archdir = #{$archdir} #### End of system configuration section. #### @@ -258,6 +309,7 @@ OBJS = #{$objs} TARGET = #{target}.#{CONFIG["DLEXT"]} INSTALL = #{$install} +INSTALL_DATA = #{$install_data} binsuffix = #{CONFIG["binsuffix"]} @@ -269,21 +321,20 @@ clean:; @rm -f *.o *.so *.sl realclean: clean -install: $(libdir)/$(TARGET) +install: $(archdir)/$(TARGET) -$(libdir)/$(TARGET): $(TARGET) +$(archdir)/$(TARGET): $(TARGET) @test -d $(libdir) || mkdir $(libdir) - $(INSTALL) $(TARGET) $(libdir)/$(TARGET) + @test -d $(archdir) || mkdir $(archdir) + $(INSTALL) $(TARGET) $(archdir)/$(TARGET) EOMF - for rb in Dir["lib/*.rb"] - mfile.printf "\t$(INSTALL) %s %s\n", rb, $libdir - end + install_rb(mfile) mfile.printf "\n" if CONFIG["DLEXT"] != "o" mfile.printf <<EOMF $(TARGET): $(OBJS) - $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS) + $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS) EOMF elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") or mfile.print "$(TARGET): $(OBJS)\n" @@ -332,12 +383,19 @@ EOMF rescue end end + + if PLATFORM =~ /beos/ + print "creating ruby.def\n" + open("ruby.def", "w") do |file| + file.print("EXPORTS\n") if PLATFORM =~ /^i/ + file.print("Init_#{target}\n") + end + end end -$local_libs = nil -$libs = nil +$libs = PLATFORM =~ /cygwin32|beos/ ? nil : "-lc" $objs = nil -$CFLAGS = nil -$LDFLAGS = nil +$local_libs = "" +$CFLAGS = "" +$LDFLAGS = "" $defs = [] - diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb index 823888e72f..4b8d64438e 100644 --- a/lib/mutex_m.rb +++ b/lib/mutex_m.rb @@ -1,8 +1,8 @@ # # mutex_m.rb - # $Release Version: 2.0$ -# $Revision: 1.2 $ -# $Date: 1997/07/25 02:43:21 $ +# $Revision: 1.7 $ +# $Date: 1998/02/27 04:28:57 $ # Original from mutex.rb # by Keiju ISHITSUKA(SHL Japan Inc.) # @@ -18,21 +18,50 @@ require "finalize" module Mutex_m - def Mutex_m.extend_object(obj) + def Mutex_m.extendable_module(obj) if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj raise TypeError, "Mutex_m can't extend to this class(#{obj.type})" else begin - eval "class << obj - @mu_locked - end" - obj.extend(For_primitive_object) + obj.instance_eval "@mu_locked" + For_general_object rescue TypeError - obj.extend(For_general_object) + For_primitive_object end end end + def Mutex_m.includable_module(cl) + begin + dummy = cl.new + Mutex_m.extendable_module(dummy) + rescue NameError + # newが定義されていない時は, DATAとみなす. + For_primitive_object + end + end + + def Mutex_m.extend_class(cl) + return super if cl.instance_of?(Module) + + # モジュールの時は何もしない. クラスの場合, 適切なモジュールの決定 + # とaliasを行う. + real = includable_module(cl) + cl.module_eval %q{ + include real + + alias locked? mu_locked? + alias lock mu_lock + alias unlock mu_unlock + alias try_lock mu_try_lock + alias synchronize mu_synchronize + } + end + + def Mutex_m.extend_object(obj) + obj.extend(Mutex_m.extendable_module(obj)) + end + def mu_extended unless (defined? locked? and defined? lock and @@ -40,7 +69,7 @@ module Mutex_m defined? try_lock and defined? synchronize) eval "class << self - alias locked mu_locked? + alias locked? mu_locked? alias lock mu_lock alias unlock mu_unlock alias try_lock mu_try_lock @@ -49,6 +78,7 @@ module Mutex_m end end + # locking def mu_synchronize begin mu_lock @@ -58,6 +88,7 @@ module Mutex_m end end + # internal class module For_general_object include Mutex_m @@ -118,10 +149,16 @@ module Mutex_m def For_primitive_object.extend_object(obj) super + obj.mu_extended Finalizer.add(obj, For_primitive_object, :mu_finalize) end + def mu_extended + super + initialize + end + def For_primitive_object.mu_finalize(id) Thread.critical = TRUE if wait = Mu_Locked.delete(id) @@ -146,7 +183,7 @@ module Mutex_m ret = FALSE else Mu_Locked[self.id] = [] - Finalizer.set(self, For_primitive_object, :mu_delete_Locked) + Finalizer.add(self, For_primitive_object, :mu_finalize) ret = TRUE end Thread.critical = FALSE @@ -159,7 +196,7 @@ module Mutex_m Thread.stop end Mu_Locked[self.id] = [] - Finalizer.add(self, For_primitive_object, :mu_delete_Locked) + Finalizer.add(self, For_primitive_object, :mu_finalize) Thread.critical = FALSE self end @@ -180,4 +217,3 @@ module Mutex_m end end - diff --git a/lib/observer.rb b/lib/observer.rb index b802dac633..5928367a7d 100644 --- a/lib/observer.rb +++ b/lib/observer.rb @@ -30,9 +30,11 @@ module Observable @observer_state end def notify_observers(*arg) - if @observer_peers and @observer_state - for i in @observer_peers - i.update(*arg) + if @observer_state + if @observer_peers + for i in @observer_peers + i.update(*arg) + end end @observer_state = FALSE end diff --git a/lib/parsearg.rb b/lib/parsearg.rb index a0ef90f018..b9f41d5e5f 100644 --- a/lib/parsearg.rb +++ b/lib/parsearg.rb @@ -1,4 +1,3 @@ -#!/usr/local/bin/ruby # # parsearg.rb - parse arguments # $Release Version: $ @@ -11,9 +10,9 @@ # # -$RCS_ID="$Header$" +$RCS_ID=%q$Header$ -load("getopts.rb") +require "getopts" def printUsageAndExit() if $USAGE diff --git a/lib/parsedate.rb b/lib/parsedate.rb index 1c1dda76bc..68550c6505 100644 --- a/lib/parsedate.rb +++ b/lib/parsedate.rb @@ -4,39 +4,68 @@ module ParseDate 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 } MONTHPAT = MONTHS.keys.join('|') - DAYPAT = 'mon|tue|wed|thu|fri|sat|sun' + DAYS = { + 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3, + 'thu' => 4, 'fri' => 5, 'sat' => 6 } + DAYPAT = DAYS.keys.join('|') def parsedate(date) - if date.sub!(/(#{DAYPAT})/i, ' ') - dayofweek = $1 + # part of ISO 8601 + # yyyy-mm-dd | yyyy-mm | yyyy + # date hh:mm:ss | date Thh:mm:ss + if date =~ /^(\d\d\d\d)-?(?:(\d\d)-?(\d\d)?)? *T?(?:(\d\d):?(\d\d):?(\d\d)?)?$/ + return $1.to_i, + if $2 then $2.to_i else 1 end, + if $3 then $3.to_i else 1 end, + if $4 then $4.to_i end, + if $5 then $5.to_i end, + if $6 then $6.to_i end, + nil, + nil end - if date.sub!(/\s+(\d+:\d+(:\d+)?)/, ' ') - time = $1 + date = date.dup + if date.sub!(/(#{DAYPAT})[a-z]*,?/i, ' ') + wday = DAYS[$1.downcase] end - if date =~ /19(\d\d)/ - year = Integer($1) + if date.sub!(/(\d+):(\d+)(?::(\d+))?\s*(am|pm)?\s*(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4})?|[-+]\d{4}))?/i, ' ') + hour = $1.to_i + min = $2.to_i + if $3 + sec = $3.to_i + end + if $4 == 'pm' + hour += 12 + end + if $5 + zone = $5 + end end - if date.sub!(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ') - dayofmonth = $1.to_i - monthname = $2 - elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ') - monthname = $1 - dayofmonth = $2.to_i - elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ') - monthname = $1 - dayofmonth = $2.to_i - elsif date.sub!(/\s*(\d\d?)\/(\d\d?)/, ' ') - month = $1 - dayofmonth = $2.to_i + if date.sub!(/(\d+)\S*\s+(#{MONTHPAT})\S*(?:\s+(\d+))?/i, ' ') + mday = $1.to_i + mon = MONTHS[$2.downcase] + if $3 + year = $3.to_i + end + elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*\s*,?(?:\s+(\d+))?/i, ' ') + mon = MONTHS[$1.downcase] + mday = $2.to_i + if $3 + year = $3.to_i + end + elsif date.sub!(/(\d+)\/(\d+)(?:\/(\d+))/, ' ') + mon = $1.to_i + mday = $2.to_i + if $3 + year = $3.to_i + end end - if monthname - month = MONTHS[monthname.downcase] - end - if ! year && date =~ /\d\d/ - year = Integer($&) - end - return year, month, dayofmonth + return year, mon, mday, hour, min, sec, zone, wday end module_function :parsedate end + +if __FILE__ == $0 + p Time.now.asctime + p ParseDate.parsedate(Time.now.asctime) +end diff --git a/lib/ping.rb b/lib/ping.rb index d742a50f99..065b1d2303 100644 --- a/lib/ping.rb +++ b/lib/ping.rb @@ -26,6 +26,10 @@ # # The timeout in seconds. If not specified it will default to 5 seconds. # +# : service +# +# The service port to connect. The default is "echo". +# #= WARNING # # pingecho() uses user-level thread to implement the timeout, so it may block @@ -33,23 +37,26 @@ # #=end +require 'timeout' + module Ping require "socket" - def pingecho(host, timeout=5) + def pingecho(host, timeout=5, service="echo") begin - x = Thread.current - y = Thread.start { - sleep timeout - x.raise RuntimeError if x.status - } - s = TCPsocket.new(host, "echo") - s.close - return TRUE + timeout(timeout) do + s = TCPsocket.new(host, service) + s.close + end rescue - return FALSE; - ensure - Thread.kill y if y.status + return false end + return true end - module_function "pingecho" + module_function :pingecho +end + +if $0 == __FILE__ + host = ARGV[0] + host ||= "localhost" + printf("%s alive? - %s\n", host, Ping::pingecho(host, 5)) end diff --git a/lib/pstore.rb b/lib/pstore.rb index 86f086d226..2aa9864b58 100644 --- a/lib/pstore.rb +++ b/lib/pstore.rb @@ -1,5 +1,4 @@ -#!/usr/local/bin/ruby - +# # How to use: # # db = PStore.new("/tmp/foo") @@ -16,7 +15,8 @@ require "marshal" class PStore - Exception(:Error) + class Error < StandardError + end def initialize(file) dir = File::dirname(file) @@ -89,33 +89,46 @@ class PStore catch(:pstore_abort_transaction) do value = yield(self) end + rescue Exception + @abort = true + raise ensure unless @abort - File::rename @filename, @filename+"~" + begin + File::rename @filename, @filename+"~" + rescue Errno::ENOENT + no_orig = true + end begin File::open(@filename, "w") do |file| Marshal::dump(@table, file) end rescue - File::rename @filename+"~", @filename + File::rename @filename+"~", @filename unless no_orig end end @abort = false end ensure + @table = nil @transaction = false end value end end -db = PStore.new("/tmp/foo") -db.transaction do - p db.roots - ary = db["root"] = [1,2,3,4] - ary[0] = [1,1.5] -end +if __FILE__ == $0 + db = PStore.new("/tmp/foo") + db.transaction do + p db.roots + ary = db["root"] = [1,2,3,4] + ary[1] = [1,1.5] + end -db.transaction do - p db["root"] + 1000.times do + db.transaction do + db["root"][0] += 1 + p db["root"][0] + end + end end diff --git a/lib/rational.rb b/lib/rational.rb index d4112c2956..1282f56410 100644 --- a/lib/rational.rb +++ b/lib/rational.rb @@ -1,8 +1,8 @@ # # rational.rb - # $Release Version: 0.5 $ -# $Revision: 1.1 $ -# $Date: 1996/11/11 04:25:14 $ +# $Revision: 1.3 $ +# $Date: 1998/03/11 14:09:03 $ # by Keiju ISHITSUKA(SHL Japan Inc.) # # -- @@ -44,7 +44,11 @@ def Rational(a, b = 1) end class Rational < Numeric + @RCS_ID='-$Id: rational.rb,v 1.3 1998/03/11 14:09:03 keiju Exp keiju $-' + def Rational.reduce(num, den = 1) + raise ZeroDivisionError, "denometor is 0" if den == 0 + if den < 0 num = -num den = -den @@ -128,6 +132,7 @@ class Rational < Numeric den = @denominator * a.numerator Rational(num, den) elsif a.kind_of?(Integer) + raise ZeroDivisionError, "devided by 0" if a == 0 self / Rational.new!(a, 1) elsif a.kind_of?(Float) Float(self) / a diff --git a/lib/shellwords.rb b/lib/shellwords.rb index 9632f1222a..9154cd84c1 100644 --- a/lib/shellwords.rb +++ b/lib/shellwords.rb @@ -18,21 +18,19 @@ module Shellwords while line != '' field = '' while TRUE - if line.sub! /^"(([^"\\]|\\.)*)"/, '' then + if line.sub! /^"(([^"\\]|\\.)*)"/, '' then #" snippet = $1 snippet.gsub! /\\(.)/, '\1' - elsif line =~ /^"/ then - STDOUT.print "Unmatched double quote: $_\n" - exit - elsif line.sub! /^'(([^'\\]|\\.)*)'/, '' then + elsif line =~ /^"/ then #" + raise ArgError, "Unmatched double quote: #{line}" + elsif line.sub! /^'(([^'\\]|\\.)*)'/, '' then #' snippet = $1 snippet.gsub! /\\(.)/, '\1' - elsif line =~ /^'/ then - STDOUT.print "Unmatched single quote: $_\n" - exit + elsif line =~ /^'/ then #' + raise ArgError, "Unmatched single quote: #{line}" elsif line.sub! /^\\(.)/, '' then snippet = $1 - elsif line.sub! /^([^\s\\'"]+)/, '' then + elsif line.sub! /^([^\s\\'"]+)/, '' then #' snippet = $1 else line.sub! /^\s+/, '' diff --git a/lib/sync.rb b/lib/sync.rb index b5a3fc32b3..9f9706d9ee 100644 --- a/lib/sync.rb +++ b/lib/sync.rb @@ -4,6 +4,7 @@ # $Revision$ # $Date$ # by Keiju ISHITSUKA +# modified by matz # # -- # Sync_m, Synchronizer_m @@ -43,7 +44,7 @@ unless defined? Thread fail "Thread not available for this ruby interpreter" end -require "finalize" +require "final" module Sync_m RCS_ID='-$Header$-' @@ -54,7 +55,7 @@ module Sync_m EX = :EX # 例外定義 - class Err < Exception + class Err < StandardError def Err.Fail(*opt) fail self, sprintf(self::Message, *opt) end @@ -296,8 +297,8 @@ module Sync_m private :sync_try_lock_sub def sync_synchronize(mode = EX) + sync_lock(mode) begin - sync_lock(mode) yield ensure sync_unlock @@ -321,7 +322,11 @@ module Sync_m def For_primitive_object.extend_object(obj) super obj.sync_extended - Finalizer.add(obj, For_primitive_object, :sync_finalize) + # Changed to use `final.rb'. + # Finalizer.add(obj, For_primitive_object, :sync_finalize) + ObjectSpace.define_finalizer(obj) do |id| + For_primitive_object.sync_finalize(id) + end end def initialize diff --git a/lib/thread.rb b/lib/thread.rb index 4f294cc9a3..ec75144374 100644 --- a/lib/thread.rb +++ b/lib/thread.rb @@ -9,14 +9,20 @@ unless defined? Thread end unless defined? ThreadError - class ThreadError<Exception + class ThreadError<StandardError end end +if $DEBUG + Thread.abort_on_exception = true +end + class Mutex def initialize @waiting = [] - @locked = FALSE; + @locked = false; + @waiting.taint # enable tainted comunication + self.taint end def locked? @@ -24,42 +30,39 @@ class Mutex end def try_lock - result = FALSE - Thread.critical = TRUE + result = false + Thread.critical = true unless @locked - @locked = TRUE - result = TRUE + @locked = true + result = true end - Thread.critical = FALSE + Thread.critical = false result end def lock - while (Thread.critical = TRUE; @locked) + while (Thread.critical = true; @locked) @waiting.push Thread.current Thread.stop end - @locked = TRUE - Thread.critical = FALSE + @locked = true + Thread.critical = false self end def unlock return unless @locked Thread.critical = TRUE - wait = @waiting - @waiting = [] + t = @waiting.shift @locked = FALSE Thread.critical = FALSE - for w in wait - w.run - end + t.run if t self end def synchronize + lock begin - lock yield ensure unlock @@ -67,37 +70,74 @@ class Mutex end end +class ConditionVariable + def initialize + @waiters = [] + @waiters_mutex = Mutex.new + @waiters.taint # enable tainted comunication + self.taint + end + + def wait(mutex) + mutex.unlock + @waiters_mutex.synchronize { + @waiters.push(Thread.current) + } + Thread.stop + mutex.lock + end + + def signal + @waiters_mutex.synchronize { + t = @waiters.shift + t.run if t + } + end + + def broadcast + @waiters_mutex.synchronize { + for t in @waiters + t.run + end + @waiters.clear + } + end +end + class Queue def initialize @que = [] @waiting = [] + @que.taint # enable tainted comunication + @waiting.taint + self.taint end def push(obj) - Thread.critical = TRUE + Thread.critical = true @que.push obj t = @waiting.shift - Thread.critical = FALSE + Thread.critical = false t.run if t end - def pop non_block=FALSE - item = nil - until item - Thread.critical = TRUE - if @que.length == 0 - if non_block - Thread.critical = FALSE - raise ThreadError, "queue empty" + def pop non_block=false + Thread.critical = true + begin + loop do + if @que.length == 0 + if non_block + raise ThreadError, "queue empty" + end + @waiting.push Thread.current + Thread.stop + else + return @que.shift end - @waiting.push Thread.current - Thread.stop - else - item = @que.shift end + ensure + Thread.critical = false end - Thread.critical = FALSE - item end def empty? @@ -107,4 +147,63 @@ class Queue def length @que.length end + alias size length + + + def num_waiting + @waiting.size + end +end + +class SizedQueue<Queue + def initialize(max) + @max = max + @queue_wait = [] + @queue_wait.taint # enable tainted comunication + super() + end + + def max + @max + end + + def max=(max) + Thread.critical = TRUE + if @max >= max + @max = max + Thread.critical = FALSE + else + diff = max - @max + @max = max + Thread.critical = FALSE + diff.times do + t = @queue_wait.shift + t.run if t + end + end + max + end + + def push(obj) + Thread.critical = true + while @que.length >= @max + @queue_wait.push Thread.current + Thread.stop + Thread.critical = true + end + super + end + + def pop(*args) + Thread.critical = true + if @que.length < @max + t = @queue_wait.shift + t.run if t + end + super + end + + def num_waiting + @waiting.size + @queue_wait.size + end end diff --git a/lib/thwait.rb b/lib/thwait.rb index c638335f5d..958163edef 100644 --- a/lib/thwait.rb +++ b/lib/thwait.rb @@ -1,34 +1,53 @@ # -# thwait.rb - -# $Release Version: $ -# $Revision: 1.1 $ -# $Date: 1997/08/18 03:13:14 $ -# by Keiju ISHITSUKA(Nippon Rational Inc.) +# thwait.rb - thread synchronization class +# $Release Version: 0.9 $ +# $Revision: 1.3 $ +# $Date: 1998/06/26 03:19:34 $ +# by Keiju ISHITSUKA(Nihpon Rational Software Co.,Ltd.) # # -- +# feature: +# provides synchronization for multiple threads. # -# +# class methods: +# * ThreadsWait.all_waits(thread1,...) +# waits until all of specified threads are terminated. +# if a block is supplied for the method, evaluates it for +# each thread termination. +# * th = ThreadsWait.new(thread1,...) +# creates synchronization object, specifying thread(s) to wait. +# +# methods: +# * th.threads +# list threads to be synchronized +# * th.empty? +# is there any thread to be synchronized. +# * th.finished? +# is there already terminated thread. +# * th.join(thread1,...) +# wait for specified thread(s). +# * th.join_nowait(threa1,...) +# specifies thread(s) to wait. non-blocking. +# * th.next_wait +# waits until any of specified threads is terminated. +# * th.all_waits +# waits until all of specified threads are terminated. +# if a block is supplied for the method, evaluates it for +# each thread termination. # require "thread.rb" require "e2mmap.rb" class ThreadsWait - RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/thwait.rb,v 1.1 1997/08/18 03:13:14 keiju Exp keiju $-' + RCS_ID='-$Id: thwait.rb,v 1.3 1998/06/26 03:19:34 keiju Exp keiju $-' Exception2MessageMapper.extend_to(binding) - def_exception("ErrWaitThreadsNothing", "Wait threads nothing.") - def_exception("FinshedThreadsNothing", "finished thread nothing.") + def_exception("ErrNoWaitingThread", "No threads for waiting.") + def_exception("ErrNoFinshedThread", "No finished threads.") - # class mthods - # all_waits - - # - # 指定したスレッドが全て終了するまで待つ. イテレータとして呼ばれると - # 指定したスレッドが終了するとイテレータを呼び出す. - # def ThreadsWait.all_waits(*threads) - tw = ThreadsWait.new(th1, th2, th3, th4, th5) + tw = ThreadsWait.new(*threads) if iterator? tw.all_waits do |th| @@ -39,12 +58,6 @@ class ThreadsWait end end - # initialize and terminating: - # initialize - - # - # 初期化. 待つスレッドの指定ができる. - # def initialize(*threads) @threads = [] @wait_queue = Queue.new @@ -52,24 +65,19 @@ class ThreadsWait end # accessing - # threads - - # 待ちスレッドの一覧を返す. + # threads - list threads to be synchronized attr :threads # testing # empty? # finished? - # - - # - # 待ちスレッドが存在するかどうかを返す. + + # is there any thread to be synchronized. def empty? @threads.empty? end - # - # すでに終了したスレッドがあるかどうか返す + # is there already terminated thread. def finished? !@wait_queue.empty? end @@ -80,45 +88,40 @@ class ThreadsWait # next_wait # all_wait - # - # 待っているスレッドを追加し待ちにはいる. - # + # adds thread(s) to join, waits for any of waiting threads to terminate. def join(*threads) join_nowait(*threads) next_wait end - # - # 待っているスレッドを追加する. 待ちには入らない. - # + # adds thread(s) to join, no wait. def join_nowait(*threads) @threads.concat threads for th in threads Thread.start do - th = Thread.join(th) + th = th.join @wait_queue.push th end end end - # - # 次の待ちにはいる. - # 待つべきスレッドがなければ, 例外ErrWaitThreadsNothing を返す. - # nonnlockが真の時には, nonblockingで調べる. 存在しなければ, 例外 - # FinishedThreadNothingを返す. - # + # waits for any of waiting threads to terminate + # if there is no thread to wait, raises ErrNoWaitingThread. + # if `nonblock' is true, and there is no terminated thread, + # raises ErrNoFinishedThread. def next_wait(nonblock = nil) - Threads.Wait.fail ErrWaitThreadsNothing if @threads.empty? - - th = @wait_queue.pop(nonblock) - @threads.delete th - th + ThreadsWait.fail ErrNoWaitingThread if @threads.empty? + begin + @threads.delete(th = @wait_queue.pop(nonblock)) + th + rescue ThreadError + ThreadsWait.fail ErrNoFinshedThread + end end - # - # 全てのスレッドが終了するまで待つ. イテレータとして呼ばれた時は, ス - # レッドが終了する度に, イテレータを呼び出す. - # + # waits until all of specified threads are terminated. + # if a block is supplied for the method, evaluates it for + # each thread termination. def all_waits until @threads.empty? th = next_wait @@ -126,3 +129,5 @@ class ThreadsWait end end end + +ThWait = ThreadsWait diff --git a/lib/tracer.rb b/lib/tracer.rb index d37339fd62..fbfca24fe5 100644 --- a/lib/tracer.rb +++ b/lib/tracer.rb @@ -1,7 +1,28 @@ +# +# tracer.rb - +# $Release Version: 0.2$ +# $Revision: 1.8 $ +# $Date: 1998/05/19 03:42:49 $ +# by Keiju ISHITSUKA(Nippon Rational Inc.) +# +# -- +# +# +# + +# +# tracer main class +# class Tracer - MY_FILE_NAME_PATTERN = /^tracer\.(rb)?/ - Threads = Hash.new - Sources = Hash.new + @RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-' + + class << self + attr :verbose, TRUE + alias verbose? verbose + end + verbose = TRUE + + MY_FILE_NAME = caller(0)[0].scan(/^(.*):[0-9]+$/)[0][0] EVENT_SYMBOL = { "line" => "-", @@ -10,39 +31,89 @@ class Tracer "class" => "C", "end" => "E"} + def initialize + @threads = Hash.new + if defined? Thread.main + @threads[Thread.main.id] = 0 + else + @threads[Thread.current.id] = 0 + end + + @get_line_procs = {} + @sources = {} + + @filters = [] + end + def on - set_trace_func proc{|event, file, line, id, binding| - trace_func event, file, line, id, binding - } - print "Trace on\n" + if iterator? + on + begin + yield + ensure + off + end + else + set_trace_func proc{|event, file, line, id, binding| + trace_func event, file, line, id, binding + } + print "Trace on\n" if Tracer.verbose? + end end def off set_trace_func nil - print "Trace off\n" + print "Trace off\n" if Tracer.verbose? end - - def get_thread_no - unless no = Threads[Thread.current.id] - Threads[Thread.current.id] = no = Threads.size - end - no + + def add_filter(p = proc) + @filters.push p + end + + def set_get_line_procs(file, p = proc) + @get_line_procs[file] = p end def get_line(file, line) - unless list = Sources[file] - f =open(file) - begin - Sources[file] = list = f.readlines - ensure - f.close + if p = @get_line_procs[file] + return p.call line + end + + unless list = @sources[file] +# print file if $DEBUG + begin + f = open(file) + begin + @sources[file] = list = f.readlines + ensure + f.close + end + rescue + @sources[file] = list = [] end end - list[line - 1] + if l = list[line - 1] + l + else + "-\n" + end + end + + def get_thread_no + if no = @threads[Thread.current.id] + no + else + @threads[Thread.current.id] = @threads.size + end end def trace_func(event, file, line, id, binding) - return if File.basename(file) =~ MY_FILE_NAME_PATTERN + return if file == MY_FILE_NAME + #printf "Th: %s\n", Thread.current.inspect + + for p in @filters + return unless p.call event, file, line, id, binding + end Thread.critical = TRUE printf("#%d:%s:%d:%s: %s", @@ -56,20 +127,36 @@ class Tracer Single = new def Tracer.on - Single.on + if iterator? + Single.on{yield} + else + Single.on + end end def Tracer.off Single.off end -end + def Tracer.set_get_line_procs(file_name, p = proc) + Single.set_get_line_procs(file_name, p) + end -if File.basename($0) =~ Tracer::MY_FILE_NAME_PATTERN - $0 = ARGV.shift + def Tracer.add_filter(p = proc) + Single.add_filter(p) + end - Tracer.on - load $0 -else - Tracer.on +end + +if caller(0).size == 1 + if $0 == Tracer::MY_FILE_NAME + # direct call + + $0 = ARGV[0] + ARGV.shift + Tracer.on + require $0 + else + Tracer.on + end end diff --git a/lib/weakref.rb b/lib/weakref.rb index 93b2c65ecd..c31e959e74 100644 --- a/lib/weakref.rb +++ b/lib/weakref.rb @@ -10,9 +10,10 @@ require "delegate" -class WeakRef<Delegater +class WeakRef<Delegator - Exception :RefError + class RefError<StandardError + end ID_MAP = {} ID_REV_MAP = {} @@ -31,26 +32,22 @@ class WeakRef<Delegater def initialize(orig) super - @id = orig.id + @__id = orig.__id__ ObjectSpace.call_finalizer orig - ID_MAP[@id] = self.id - ID_REV_MAP[self.id] = @id + ObjectSpace.call_finalizer self + ID_MAP[@__id] = self.__id__ + ID_REV_MAP[self.id] = @__id end def __getobj__ - unless ID_MAP[@id] - $@ = caller(1) - $! = RefError.new("Illegal Reference - probably recycled") - raise + unless ID_MAP[@__id] + raise RefError, "Illegal Reference - probably recycled", caller(2) end - ObjectSpace.id2ref(@id) -# ObjectSpace.each_object do |obj| -# return obj if obj.id == @id -# end + ObjectSpace._id2ref(@__id) end def weakref_alive? - if ID_MAP[@id] + if ID_MAP[@__id] true else false @@ -62,9 +59,11 @@ class WeakRef<Delegater end end -foo = Object.new -p foo.hash -foo = WeakRef.new(foo) -p foo.hash -ObjectSpace.garbage_collect -p foo.hash +if __FILE__ == $0 + foo = Object.new + p foo.hash # original's hash value + foo = WeakRef.new(foo) + p foo.hash # should be same hash value + ObjectSpace.garbage_collect + p foo.hash # should raise exception (recycled) +end -- cgit v1.2.3