* lib: Convert tabs to spaces for ruby files per

http://redmine.ruby-lang.org/projects/ruby/wiki/DeveloperHowto#coding-style
	  Patch by Steve Klabnik [Ruby 1.9 - Bug #4730]
	  Patch by Jason Dew [Ruby 1.9 - Feature #4718]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31635 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2011-05-18 21:19:18 +00:00
parent 34276148c4
commit 7bbf2f3085
67 changed files with 3823 additions and 3814 deletions

View File

@ -1,3 +1,10 @@
Thu May 19 06:16:41 2011 Eric Hodel <drbrain@segment7.net>
* lib: Convert tabs to spaces for ruby files per
http://redmine.ruby-lang.org/projects/ruby/wiki/DeveloperHowto#coding-style
Patch by Steve Klabnik [Ruby 1.9 - Bug #4730]
Patch by Jason Dew [Ruby 1.9 - Feature #4718]
Thu May 19 06:06:07 2011 Eric Hodel <drbrain@segment7.net> Thu May 19 06:06:07 2011 Eric Hodel <drbrain@segment7.net>
* lib/cgi/util.rb: Improve documentation. Patch by Clinton Nixon. * lib/cgi/util.rb: Improve documentation. Patch by Clinton Nixon.

View File

@ -45,24 +45,24 @@ module Abbrev
seen = Hash.new(0) seen = Hash.new(0)
if pattern.is_a?(String) if pattern.is_a?(String)
pattern = /^#{Regexp.quote(pattern)}/ # regard as a prefix pattern = /^#{Regexp.quote(pattern)}/ # regard as a prefix
end end
words.each do |word| words.each do |word|
next if (abbrev = word).empty? next if (abbrev = word).empty?
while (len = abbrev.rindex(/[\w\W]\z/)) > 0 while (len = abbrev.rindex(/[\w\W]\z/)) > 0
abbrev = word[0,len] abbrev = word[0,len]
next if pattern && pattern !~ abbrev next if pattern && pattern !~ abbrev
case seen[abbrev] += 1 case seen[abbrev] += 1
when 1 when 1
table[abbrev] = word table[abbrev] = word
when 2 when 2
table.delete(abbrev) table.delete(abbrev)
else else
break break
end end
end end
end end

View File

@ -254,9 +254,9 @@ module Benchmark
puts 'Rehearsal '.ljust(width+CAPTION.length,'-') puts 'Rehearsal '.ljust(width+CAPTION.length,'-')
ets = job.list.inject(Tms.new) { |sum,(label,item)| ets = job.list.inject(Tms.new) { |sum,(label,item)|
print label.ljust(width) print label.ljust(width)
res = Benchmark.measure(&item) res = Benchmark.measure(&item)
print res.format print res.format
sum + res sum + res
}.format("total: %tsec") }.format("total: %tsec")
print " #{ets}\n\n".rjust(width+CAPTION.length+2,'-') print " #{ets}\n\n".rjust(width+CAPTION.length+2,'-')
@ -520,14 +520,14 @@ module Benchmark
cutime.__send__(op, x.cutime), cutime.__send__(op, x.cutime),
cstime.__send__(op, x.cstime), cstime.__send__(op, x.cstime),
real.__send__(op, x.real) real.__send__(op, x.real)
) )
else else
Benchmark::Tms.new(utime.__send__(op, x), Benchmark::Tms.new(utime.__send__(op, x),
stime.__send__(op, x), stime.__send__(op, x),
cutime.__send__(op, x), cutime.__send__(op, x),
cstime.__send__(op, x), cstime.__send__(op, x),
real.__send__(op, x) real.__send__(op, x)
) )
end end
end end
end end
@ -548,13 +548,13 @@ if __FILE__ == $0
x.report("for:") {for _ in 1..n; _ = "1"; end} # Benchmark.measure x.report("for:") {for _ in 1..n; _ = "1"; end} # Benchmark.measure
x.report("times:") {n.times do ; _ = "1"; end} x.report("times:") {n.times do ; _ = "1"; end}
x.report("upto:") {1.upto(n) do ; _ = "1"; end} x.report("upto:") {1.upto(n) do ; _ = "1"; end}
end end
benchmark do benchmark do
[ [
measure{for _ in 1..n; _ = "1"; end}, # Benchmark.measure measure{for _ in 1..n; _ = "1"; end}, # Benchmark.measure
measure{n.times do ; _ = "1"; end}, measure{n.times do ; _ = "1"; end},
measure{1.upto(n) do ; _ = "1"; end} measure{1.upto(n) do ; _ = "1"; end}
] ]
end end
end end

View File

@ -55,7 +55,7 @@ module CMath
else else
ere = exp!(z.real) ere = exp!(z.real)
Complex(ere * cos!(z.imag), Complex(ere * cos!(z.imag),
ere * sin!(z.imag)) ere * sin!(z.imag))
end end
end end
@ -71,7 +71,7 @@ module CMath
else else
a = Complex(log!(z.abs), z.arg) a = Complex(log!(z.abs), z.arg)
if b if b
a /= log(b) a /= log(b)
end end
a a
end end
@ -105,18 +105,18 @@ module CMath
def sqrt(z) def sqrt(z)
if z.real? if z.real?
if z < 0 if z < 0
Complex(0, sqrt!(-z)) Complex(0, sqrt!(-z))
else else
sqrt!(z) sqrt!(z)
end end
else else
if z.imag < 0 || if z.imag < 0 ||
(z.imag == 0 && z.imag.to_s[0] == '-') (z.imag == 0 && z.imag.to_s[0] == '-')
sqrt(z.conjugate).conjugate sqrt(z.conjugate).conjugate
else else
r = z.abs r = z.abs
x = z.real x = z.real
Complex(sqrt!((r + x) / 2.0), sqrt!((r - x) / 2.0)) Complex(sqrt!((r + x) / 2.0), sqrt!((r - x) / 2.0))
end end
end end
end end
@ -138,7 +138,7 @@ module CMath
sin!(z) sin!(z)
else else
Complex(sin!(z.real) * cosh!(z.imag), Complex(sin!(z.real) * cosh!(z.imag),
cos!(z.real) * sinh!(z.imag)) cos!(z.real) * sinh!(z.imag))
end end
end end
@ -149,7 +149,7 @@ module CMath
cos!(z) cos!(z)
else else
Complex(cos!(z.real) * cosh!(z.imag), Complex(cos!(z.real) * cosh!(z.imag),
-sin!(z.real) * sinh!(z.imag)) -sin!(z.real) * sinh!(z.imag))
end end
end end
@ -170,7 +170,7 @@ module CMath
sinh!(z) sinh!(z)
else else
Complex(sinh!(z.real) * cos!(z.imag), Complex(sinh!(z.real) * cos!(z.imag),
cosh!(z.real) * sin!(z.imag)) cosh!(z.real) * sin!(z.imag))
end end
end end
@ -181,7 +181,7 @@ module CMath
cosh!(z) cosh!(z)
else else
Complex(cosh!(z.real) * cos!(z.imag), Complex(cosh!(z.real) * cos!(z.imag),
sinh!(z.real) * sin!(z.imag)) sinh!(z.real) * sin!(z.imag))
end end
end end

File diff suppressed because it is too large Load Diff

View File

@ -330,12 +330,12 @@ end
# :stopdoc: # :stopdoc:
def Delegator.delegating_block(mid) def Delegator.delegating_block(mid)
lambda do |*args, &block| lambda do |*args, &block|
target = self.__getobj__ target = self.__getobj__
begin begin
target.__send__(mid, *args, &block) target.__send__(mid, *args, &block)
ensure ensure
$@.delete_if {|t| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}:/o =~ t} if $@ $@.delete_if {|t| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}:/o =~ t} if $@
end end
end end
end end
# :startdoc: # :startdoc:
@ -368,10 +368,10 @@ def DelegateClass(superclass)
end end
end end
klass.define_singleton_method :public_instance_methods do |all=true| klass.define_singleton_method :public_instance_methods do |all=true|
super(all) - superclass.protected_instance_methods super(all) - superclass.protected_instance_methods
end end
klass.define_singleton_method :protected_instance_methods do |all=true| klass.define_singleton_method :protected_instance_methods do |all=true|
super(all) | superclass.protected_instance_methods super(all) | superclass.protected_instance_methods
end end
return klass return klass
end end
@ -405,7 +405,7 @@ if __FILE__ == $0
foo2 = SimpleDelegator.new(foo) foo2 = SimpleDelegator.new(foo)
p foo2 p foo2
foo2.instance_eval{print "foo\n"} foo2.instance_eval{print "foo\n"}
p foo.test == foo2.test # => true p foo.test == foo2.test # => true
p foo2.iter{[55,true]} # => true p foo2.iter{[55,true]} # => true
foo2.error # raise error! foo2.error # raise error!
end end

View File

@ -51,15 +51,15 @@ class ACL
def initialize(str) def initialize(str)
if str == '*' or str == 'all' if str == '*' or str == 'all'
@pat = [:all] @pat = [:all]
elsif str.include?('*') elsif str.include?('*')
@pat = [:name, dot_pat(str)] @pat = [:name, dot_pat(str)]
else else
begin begin
@pat = [:ip, IPAddr.new(str)] @pat = [:ip, IPAddr.new(str)]
rescue ArgumentError rescue ArgumentError
@pat = [:name, dot_pat(str)] @pat = [:name, dot_pat(str)]
end end
end end
end end
@ -70,7 +70,7 @@ class ACL
def dot_pat_str(str) def dot_pat_str(str)
list = str.split('.').collect { |s| list = str.split('.').collect { |s|
(s == '*') ? '.+' : s (s == '*') ? '.+' : s
} }
list.join("\\.") list.join("\\.")
end end
@ -93,19 +93,19 @@ class ACL
def match(addr) def match(addr)
case @pat[0] case @pat[0]
when :all when :all
true true
when :ip when :ip
begin begin
ipaddr = IPAddr.new(addr[3]) ipaddr = IPAddr.new(addr[3])
ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4? ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4?
rescue ArgumentError rescue ArgumentError
return false return false
end end
(@pat[1].include?(ipaddr)) ? true : false (@pat[1].include?(ipaddr)) ? true : false
when :name when :name
(@pat[1] =~ addr[2]) ? true : false (@pat[1] =~ addr[2]) ? true : false
else else
false false
end end
end end
end end
@ -130,7 +130,7 @@ class ACL
def match(addr) def match(addr)
@list.each do |e| @list.each do |e|
return true if e.match(addr) return true if e.match(addr)
end end
false false
end end
@ -219,11 +219,11 @@ class ACL
permission, domain = list.slice(i,2) permission, domain = list.slice(i,2)
case permission.downcase case permission.downcase
when 'allow' when 'allow'
@allow.add(domain) @allow.add(domain)
when 'deny' when 'deny'
@deny.add(domain) @deny.add(domain)
else else
raise "Invalid ACL entry #{list.to_s}" raise "Invalid ACL entry #{list.to_s}"
end end
i += 2 i += 2
end end
@ -234,17 +234,17 @@ end
if __FILE__ == $0 if __FILE__ == $0
# example # example
list = %w(deny all list = %w(deny all
allow 192.168.1.1 allow 192.168.1.1
allow ::ffff:192.168.1.2 allow ::ffff:192.168.1.2
allow 192.168.1.3 allow 192.168.1.3
) )
addr = ["AF_INET", 10, "lc630", "192.168.1.3"] addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
acl = ACL.new acl = ACL.new
p acl.allow_addr?(addr) p acl.allow_addr?(addr)
acl = ACL.new(list, ACL::DENY_ALLOW) acl = ACL.new(list, ACL::DENY_ALLOW)
p acl.allow_addr?(addr) p acl.allow_addr?(addr)
end end

View File

@ -466,11 +466,11 @@ module DRb
def initialize(err, buf) def initialize(err, buf)
case err.to_s case err.to_s
when /uninitialized constant (\S+)/ when /uninitialized constant (\S+)/
@name = $1 @name = $1
when /undefined class\/module (\S+)/ when /undefined class\/module (\S+)/
@name = $1 @name = $1
else else
@name = nil @name = nil
end end
@buf = buf @buf = buf
end end
@ -486,9 +486,9 @@ module DRb
def self._load(s) # :nodoc: def self._load(s) # :nodoc:
begin begin
Marshal::load(s) Marshal::load(s)
rescue NameError, ArgumentError rescue NameError, ArgumentError
DRbUnknown.new($!, s) DRbUnknown.new($!, s)
end end
end end
@ -514,16 +514,16 @@ module DRb
class DRbArray class DRbArray
def initialize(ary) def initialize(ary)
@ary = ary.collect { |obj| @ary = ary.collect { |obj|
if obj.kind_of? DRbUndumped if obj.kind_of? DRbUndumped
DRbObject.new(obj) DRbObject.new(obj)
else else
begin begin
Marshal.dump(obj) Marshal.dump(obj)
obj obj
rescue rescue
DRbObject.new(obj) DRbObject.new(obj)
end end
end end
} }
end end
@ -554,16 +554,16 @@ module DRb
def dump(obj, error=false) # :nodoc: def dump(obj, error=false) # :nodoc:
obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped
begin begin
str = Marshal::dump(obj) str = Marshal::dump(obj)
rescue rescue
str = Marshal::dump(make_proxy(obj, error)) str = Marshal::dump(make_proxy(obj, error))
end end
[str.size].pack('N') + str [str.size].pack('N') + str
end end
def load(soc) # :nodoc: def load(soc) # :nodoc:
begin begin
sz = soc.read(4) # sizeof (N) sz = soc.read(4) # sizeof (N)
rescue rescue
raise(DRbConnError, $!.message, $!.backtrace) raise(DRbConnError, $!.message, $!.backtrace)
end end
@ -600,7 +600,7 @@ module DRb
ary.push(dump(msg_id.id2name)) ary.push(dump(msg_id.id2name))
ary.push(dump(arg.length)) ary.push(dump(arg.length))
arg.each do |e| arg.each do |e|
ary.push(dump(e)) ary.push(dump(e))
end end
ary.push(dump(b)) ary.push(dump(b))
stream.write(ary.join('')) stream.write(ary.join(''))
@ -616,7 +616,7 @@ module DRb
raise(DRbConnError, "too many arguments") if @argc_limit < argc raise(DRbConnError, "too many arguments") if @argc_limit < argc
argv = Array.new(argc, nil) argv = Array.new(argc, nil)
argc.times do |n| argc.times do |n|
argv[n] = load(stream) argv[n] = load(stream)
end end
block = load(stream) block = load(stream)
return ro, msg, argv, block return ro, msg, argv, block
@ -727,18 +727,18 @@ module DRb
# URI, but an error occurs in opening it, a DRbConnError is raised. # URI, but an error occurs in opening it, a DRbConnError is raised.
def open(uri, config, first=true) def open(uri, config, first=true)
@protocol.each do |prot| @protocol.each do |prot|
begin begin
return prot.open(uri, config) return prot.open(uri, config)
rescue DRbBadScheme rescue DRbBadScheme
rescue DRbConnError rescue DRbConnError
raise($!) raise($!)
rescue rescue
raise(DRbConnError, "#{uri} - #{$!.inspect}") raise(DRbConnError, "#{uri} - #{$!.inspect}")
end end
end end
if first && (config[:auto_load] != false) if first && (config[:auto_load] != false)
auto_load(uri, config) auto_load(uri, config)
return open(uri, config, false) return open(uri, config, false)
end end
raise DRbBadURI, 'can\'t parse uri:' + uri raise DRbBadURI, 'can\'t parse uri:' + uri
end end
@ -755,14 +755,14 @@ module DRb
# error is passed on to the caller. # error is passed on to the caller.
def open_server(uri, config, first=true) def open_server(uri, config, first=true)
@protocol.each do |prot| @protocol.each do |prot|
begin begin
return prot.open_server(uri, config) return prot.open_server(uri, config)
rescue DRbBadScheme rescue DRbBadScheme
end end
end end
if first && (config[:auto_load] != false) if first && (config[:auto_load] != false)
auto_load(uri, config) auto_load(uri, config)
return open_server(uri, config, false) return open_server(uri, config, false)
end end
raise DRbBadURI, 'can\'t parse uri:' + uri raise DRbBadURI, 'can\'t parse uri:' + uri
end end
@ -776,15 +776,15 @@ module DRb
# URI, then a DRbBadURI error is raised. # URI, then a DRbBadURI error is raised.
def uri_option(uri, config, first=true) def uri_option(uri, config, first=true)
@protocol.each do |prot| @protocol.each do |prot|
begin begin
uri, opt = prot.uri_option(uri, config) uri, opt = prot.uri_option(uri, config)
# opt = nil if opt == '' # opt = nil if opt == ''
return uri, opt return uri, opt
rescue DRbBadScheme rescue DRbBadScheme
end end
end end
if first && (config[:auto_load] != false) if first && (config[:auto_load] != false)
auto_load(uri, config) auto_load(uri, config)
return uri_option(uri, config, false) return uri_option(uri, config, false)
end end
raise DRbBadURI, 'can\'t parse uri:' + uri raise DRbBadURI, 'can\'t parse uri:' + uri
@ -793,7 +793,7 @@ module DRb
def auto_load(uri, config) # :nodoc: def auto_load(uri, config) # :nodoc:
if uri =~ /^drb([a-z0-9]+):/ if uri =~ /^drb([a-z0-9]+):/
require("drb/#{$1}") rescue nil require("drb/#{$1}") rescue nil
end end
end end
module_function :auto_load module_function :auto_load
@ -806,13 +806,13 @@ module DRb
private private
def self.parse_uri(uri) def self.parse_uri(uri)
if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/ if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/
host = $1 host = $1
port = $2.to_i port = $2.to_i
option = $4 option = $4
[host, port, option] [host, port, option]
else else
raise(DRbBadScheme, uri) unless uri =~ /^druby:/ raise(DRbBadScheme, uri) unless uri =~ /^druby:/
raise(DRbBadURI, 'can\'t parse uri:' + uri) raise(DRbBadURI, 'can\'t parse uri:' + uri)
end end
end end
@ -858,7 +858,7 @@ module DRb
host = getservername host = getservername
soc = open_server_inaddr_any(host, port) soc = open_server_inaddr_any(host, port)
else else
soc = TCPServer.open(host, port) soc = TCPServer.open(host, port)
end end
port = soc.addr[1] if port == 0 port = soc.addr[1] if port == 0
config[:tcp_port] = port config[:tcp_port] = port
@ -928,8 +928,8 @@ module DRb
# client-server session. # client-server session.
def close def close
if @socket if @socket
@socket.close @socket.close
@socket = nil @socket = nil
end end
end end
@ -938,9 +938,9 @@ module DRb
# the server's side of this client-server session. # the server's side of this client-server session.
def accept def accept
while true while true
s = @socket.accept s = @socket.accept
break if (@acl ? @acl.allow_socket?(s) : true) break if (@acl ? @acl.allow_socket?(s) : true)
s.close s.close
end end
if @config[:tcp_original_host].to_s.size == 0 if @config[:tcp_original_host].to_s.size == 0
uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}" uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}"
@ -954,8 +954,8 @@ module DRb
def alive? def alive?
return false unless @socket return false unless @socket
if IO.select([@socket], nil, nil, 0) if IO.select([@socket], nil, nil, 0)
close close
return false return false
end end
true true
end end
@ -1004,7 +1004,7 @@ module DRb
uri, ref = Marshal.load(s) uri, ref = Marshal.load(s)
if DRb.here?(uri) if DRb.here?(uri)
obj = DRb.to_obj(ref) obj = DRb.to_obj(ref)
if ((! obj.tainted?) && Thread.current[:drb_untaint]) if ((! obj.tainted?) && Thread.current[:drb_untaint])
Thread.current[:drb_untaint].push(obj) Thread.current[:drb_untaint].push(obj)
end end
@ -1042,12 +1042,12 @@ module DRb
@uri = nil @uri = nil
@ref = nil @ref = nil
if obj.nil? if obj.nil?
return if uri.nil? return if uri.nil?
@uri, option = DRbProtocol.uri_option(uri, DRb.config) @uri, option = DRbProtocol.uri_option(uri, DRb.config)
@ref = DRbURIOption.new(option) unless option.nil? @ref = DRbURIOption.new(option) unless option.nil?
else else
@uri = uri ? uri : (DRb.uri rescue nil) @uri = uri ? uri : (DRb.uri rescue nil)
@ref = obj ? DRb.to_id(obj) : nil @ref = obj ? DRb.to_id(obj) : nil
end end
end end
@ -1078,9 +1078,9 @@ module DRb
# Routes method calls to the referenced object. # Routes method calls to the referenced object.
def method_missing(msg_id, *a, &b) def method_missing(msg_id, *a, &b)
if DRb.here?(@uri) if DRb.here?(@uri)
obj = DRb.to_obj(@ref) obj = DRb.to_obj(@ref)
DRb.current_server.check_insecure_method(obj, msg_id) DRb.current_server.check_insecure_method(obj, msg_id)
return obj.__send__(msg_id, *a, &b) return obj.__send__(msg_id, *a, &b)
end end
succ, result = self.class.with_friend(@uri) do succ, result = self.class.with_friend(@uri) do
@ -1095,7 +1095,7 @@ module DRb
raise result raise result
else else
bt = self.class.prepare_backtrace(@uri, result) bt = self.class.prepare_backtrace(@uri, result)
result.set_backtrace(bt + caller) result.set_backtrace(bt + caller)
raise result raise result
end end
end end
@ -1117,7 +1117,7 @@ module DRb
result.backtrace.each do |x| result.backtrace.each do |x|
break if /`__send__'$/ =~ x break if /`__send__'$/ =~ x
if /^\(druby:\/\// =~ x if /^\(druby:\/\// =~ x
bt.push(x) bt.push(x)
else else
bt.push(prefix + x) bt.push(prefix + x)
end end
@ -1153,36 +1153,36 @@ module DRb
def self.open(remote_uri) # :nodoc: def self.open(remote_uri) # :nodoc:
begin begin
conn = nil conn = nil
@mutex.synchronize do @mutex.synchronize do
#FIXME #FIXME
new_pool = [] new_pool = []
@pool.each do |c| @pool.each do |c|
if conn.nil? and c.uri == remote_uri if conn.nil? and c.uri == remote_uri
conn = c if c.alive? conn = c if c.alive?
else else
new_pool.push c new_pool.push c
end end
end end
@pool = new_pool @pool = new_pool
end end
conn = self.new(remote_uri) unless conn conn = self.new(remote_uri) unless conn
succ, result = yield(conn) succ, result = yield(conn)
return succ, result return succ, result
ensure ensure
if conn if conn
if succ if succ
@mutex.synchronize do @mutex.synchronize do
@pool.unshift(conn) @pool.unshift(conn)
@pool.pop.close while @pool.size > POOL_SIZE @pool.pop.close while @pool.size > POOL_SIZE
end end
else else
conn.close conn.close
end end
end end
end end
end end
@ -1274,11 +1274,11 @@ module DRb
def self.make_config(hash={}) # :nodoc: def self.make_config(hash={}) # :nodoc:
default_config = { default_config = {
:idconv => @@idconv, :idconv => @@idconv,
:verbose => @@verbose, :verbose => @@verbose,
:tcp_acl => @@acl, :tcp_acl => @@acl,
:load_limit => @@load_limit, :load_limit => @@load_limit,
:argc_limit => @@argc_limit, :argc_limit => @@argc_limit,
:safe_level => @@safe_level :safe_level => @@safe_level
} }
default_config.update(hash) default_config.update(hash)
@ -1329,12 +1329,12 @@ module DRb
# The server will immediately start running in its own thread. # The server will immediately start running in its own thread.
def initialize(uri=nil, front=nil, config_or_acl=nil) def initialize(uri=nil, front=nil, config_or_acl=nil)
if Hash === config_or_acl if Hash === config_or_acl
config = config_or_acl.dup config = config_or_acl.dup
else else
acl = config_or_acl || @@acl acl = config_or_acl || @@acl
config = { config = {
:tcp_acl => acl :tcp_acl => acl
} }
end end
@config = self.class.make_config(config) @config = self.class.make_config(config)
@ -1414,28 +1414,28 @@ module DRb
private private
def kill_sub_thread def kill_sub_thread
Thread.new do Thread.new do
grp = ThreadGroup.new grp = ThreadGroup.new
grp.add(Thread.current) grp.add(Thread.current)
list = @grp.list list = @grp.list
while list.size > 0 while list.size > 0
list.each do |th| list.each do |th|
th.kill if th.alive? th.kill if th.alive?
end end
list = @grp.list list = @grp.list
end end
end end
end end
def run def run
Thread.start do Thread.start do
begin begin
while true while true
main_loop main_loop
end end
ensure ensure
@protocol.close if @protocol @protocol.close if @protocol
kill_sub_thread kill_sub_thread
end end
end end
end end
@ -1473,10 +1473,10 @@ module DRb
raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
if obj.private_methods.include?(msg_id) if obj.private_methods.include?(msg_id)
desc = any_to_s(obj) desc = any_to_s(obj)
raise NoMethodError, "private method `#{msg_id}' called for #{desc}" raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
elsif obj.protected_methods.include?(msg_id) elsif obj.protected_methods.include?(msg_id)
desc = any_to_s(obj) desc = any_to_s(obj)
raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
else else
true true
@ -1486,15 +1486,15 @@ module DRb
class InvokeMethod # :nodoc: class InvokeMethod # :nodoc:
def initialize(drb_server, client) def initialize(drb_server, client)
@drb_server = drb_server @drb_server = drb_server
@safe_level = drb_server.safe_level @safe_level = drb_server.safe_level
@client = client @client = client
end end
def perform def perform
@result = nil @result = nil
@succ = false @succ = false
setup_message setup_message
if $SAFE < @safe_level if $SAFE < @safe_level
info = Thread.current['DRb'] info = Thread.current['DRb']
@ -1518,19 +1518,19 @@ module DRb
@result = perform_without_block @result = perform_without_block
end end
end end
@succ = true @succ = true
if @msg_id == :to_ary && @result.class == Array if @msg_id == :to_ary && @result.class == Array
@result = DRbArray.new(@result) @result = DRbArray.new(@result)
end end
return @succ, @result return @succ, @result
rescue StandardError, ScriptError, Interrupt rescue StandardError, ScriptError, Interrupt
@result = $! @result = $!
return @succ, @result return @succ, @result
end end
private private
def init_with_client def init_with_client
obj, msg, argv, block = @client.recv_request obj, msg, argv, block = @client.recv_request
@obj = obj @obj = obj
@msg_id = msg.intern @msg_id = msg.intern
@argv = argv @argv = argv
@ -1542,21 +1542,21 @@ module DRb
end end
def setup_message def setup_message
init_with_client init_with_client
check_insecure_method check_insecure_method
end end
def perform_without_block def perform_without_block
if Proc === @obj && @msg_id == :__drb_yield if Proc === @obj && @msg_id == :__drb_yield
if @argv.size == 1 if @argv.size == 1
ary = @argv ary = @argv
else else
ary = [@argv] ary = [@argv]
end end
ary.collect(&@obj)[0] ary.collect(&@obj)[0]
else else
@obj.__send__(@msg_id, *@argv) @obj.__send__(@msg_id, *@argv)
end end
end end
end end
@ -1582,29 +1582,29 @@ module DRb
# or a local method call fails. # or a local method call fails.
def main_loop def main_loop
Thread.start(@protocol.accept) do |client| Thread.start(@protocol.accept) do |client|
@grp.add Thread.current @grp.add Thread.current
Thread.current['DRb'] = { 'client' => client , Thread.current['DRb'] = { 'client' => client ,
'server' => self } 'server' => self }
loop do loop do
begin begin
succ = false succ = false
invoke_method = InvokeMethod.new(self, client) invoke_method = InvokeMethod.new(self, client)
succ, result = invoke_method.perform succ, result = invoke_method.perform
if !succ && verbose if !succ && verbose
p result p result
result.backtrace.each do |x| result.backtrace.each do |x|
puts x puts x
end end
end end
client.send_reply(succ, result) rescue nil client.send_reply(succ, result) rescue nil
ensure ensure
client.close unless succ client.close unless succ
if Thread.current['DRb']['stop_service'] if Thread.current['DRb']['stop_service']
Thread.new { stop_service } Thread.new { stop_service }
end end
break unless succ break unless succ
end end
end end
end end
end end
end end

View File

@ -1,6 +1,6 @@
=begin =begin
external service external service
Copyright (c) 2000,2002 Masatoshi SEKI Copyright (c) 2000,2002 Masatoshi SEKI
=end =end
require 'drb/drb' require 'drb/drb'

View File

@ -1,6 +1,6 @@
=begin =begin
external service manager external service manager
Copyright (c) 2000 Masatoshi SEKI Copyright (c) 2000 Masatoshi SEKI
=end =end
require 'drb/drb' require 'drb/drb'
@ -54,17 +54,17 @@ module DRb
def unregist(name) def unregist(name)
synchronize do synchronize do
@servers.delete(name) @servers.delete(name)
end end
end end
private private
def invoke_thread def invoke_thread
Thread.new do Thread.new do
while true while true
name = @queue.pop name = @queue.pop
invoke_service_command(name, @@command[name]) invoke_service_command(name, @@command[name])
end end
end end
end end
@ -75,8 +75,8 @@ module DRb
def invoke_service_command(name, command) def invoke_service_command(name, command)
raise "invalid command. name: #{name}" unless command raise "invalid command. name: #{name}" unless command
synchronize do synchronize do
return if @servers.include?(name) return if @servers.include?(name)
@servers[name] = false @servers[name] = false
end end
uri = @uri || DRb.uri uri = @uri || DRb.uri
Process.detach spawn("#{command} #{uri} #{name}") Process.detach spawn("#{command} #{uri} #{name}")

View File

@ -4,9 +4,9 @@ module DRb
class DRbServer class DRbServer
module InvokeMethod18Mixin module InvokeMethod18Mixin
def block_yield(x) def block_yield(x)
if x.size == 1 && x[0].class == Array if x.size == 1 && x[0].class == Array
x[0] = DRbArray.new(x[0]) x[0] = DRbArray.new(x[0])
end end
@block.call(*x) @block.call(*x)
end end

View File

@ -10,43 +10,43 @@ module DRb
class SSLConfig class SSLConfig
DEFAULT = { DEFAULT = {
:SSLCertificate => nil, :SSLCertificate => nil,
:SSLPrivateKey => nil, :SSLPrivateKey => nil,
:SSLClientCA => nil, :SSLClientCA => nil,
:SSLCACertificatePath => nil, :SSLCACertificatePath => nil,
:SSLCACertificateFile => nil, :SSLCACertificateFile => nil,
:SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE,
:SSLVerifyDepth => nil, :SSLVerifyDepth => nil,
:SSLVerifyCallback => nil, # custom verification :SSLVerifyCallback => nil, # custom verification
:SSLCertificateStore => nil, :SSLCertificateStore => nil,
# Must specify if you use auto generated certificate. # Must specify if you use auto generated certificate.
:SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]]
:SSLCertComment => "Generated by Ruby/OpenSSL" :SSLCertComment => "Generated by Ruby/OpenSSL"
} }
def initialize(config) def initialize(config)
@config = config @config = config
@cert = config[:SSLCertificate] @cert = config[:SSLCertificate]
@pkey = config[:SSLPrivateKey] @pkey = config[:SSLPrivateKey]
@ssl_ctx = nil @ssl_ctx = nil
end end
def [](key); def [](key);
@config[key] || DEFAULT[key] @config[key] || DEFAULT[key]
end end
def connect(tcp) def connect(tcp)
ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
ssl.sync = true ssl.sync = true
ssl.connect ssl.connect
ssl ssl
end end
def accept(tcp) def accept(tcp)
ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
ssl.sync = true ssl.sync = true
ssl.accept ssl.accept
ssl ssl
end end
def setup_certificate def setup_certificate
@ -54,56 +54,56 @@ module DRb
return return
end end
rsa = OpenSSL::PKey::RSA.new(512){|p, n| rsa = OpenSSL::PKey::RSA.new(512){|p, n|
next unless self[:verbose] next unless self[:verbose]
case p case p
when 0; $stderr.putc "." # BN_generate_prime when 0; $stderr.putc "." # BN_generate_prime
when 1; $stderr.putc "+" # BN_generate_prime when 1; $stderr.putc "+" # BN_generate_prime
when 2; $stderr.putc "*" # searching good prime, when 2; $stderr.putc "*" # searching good prime,
# n = #of try, # n = #of try,
# but also data from BN_generate_prime # but also data from BN_generate_prime
when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q, when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
# but also data from BN_generate_prime # but also data from BN_generate_prime
else; $stderr.putc "*" # BN_generate_prime else; $stderr.putc "*" # BN_generate_prime
end end
} }
cert = OpenSSL::X509::Certificate.new cert = OpenSSL::X509::Certificate.new
cert.version = 3 cert.version = 3
cert.serial = 0 cert.serial = 0
name = OpenSSL::X509::Name.new(self[:SSLCertName]) name = OpenSSL::X509::Name.new(self[:SSLCertName])
cert.subject = name cert.subject = name
cert.issuer = name cert.issuer = name
cert.not_before = Time.now cert.not_before = Time.now
cert.not_after = Time.now + (365*24*60*60) cert.not_after = Time.now + (365*24*60*60)
cert.public_key = rsa.public_key cert.public_key = rsa.public_key
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
cert.extensions = [ cert.extensions = [
ef.create_extension("basicConstraints","CA:FALSE"), ef.create_extension("basicConstraints","CA:FALSE"),
ef.create_extension("subjectKeyIdentifier", "hash") ] ef.create_extension("subjectKeyIdentifier", "hash") ]
ef.issuer_certificate = cert ef.issuer_certificate = cert
cert.add_extension(ef.create_extension("authorityKeyIdentifier", cert.add_extension(ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")) "keyid:always,issuer:always"))
if comment = self[:SSLCertComment] if comment = self[:SSLCertComment]
cert.add_extension(ef.create_extension("nsComment", comment)) cert.add_extension(ef.create_extension("nsComment", comment))
end end
cert.sign(rsa, OpenSSL::Digest::SHA1.new) cert.sign(rsa, OpenSSL::Digest::SHA1.new)
@cert = cert @cert = cert
@pkey = rsa @pkey = rsa
end end
def setup_ssl_context def setup_ssl_context
ctx = ::OpenSSL::SSL::SSLContext.new ctx = ::OpenSSL::SSL::SSLContext.new
ctx.cert = @cert ctx.cert = @cert
ctx.key = @pkey ctx.key = @pkey
ctx.client_ca = self[:SSLClientCA] ctx.client_ca = self[:SSLClientCA]
ctx.ca_path = self[:SSLCACertificatePath] ctx.ca_path = self[:SSLCACertificatePath]
ctx.ca_file = self[:SSLCACertificateFile] ctx.ca_file = self[:SSLCACertificateFile]
ctx.verify_mode = self[:SSLVerifyMode] ctx.verify_mode = self[:SSLVerifyMode]
ctx.verify_depth = self[:SSLVerifyDepth] ctx.verify_depth = self[:SSLVerifyDepth]
ctx.verify_callback = self[:SSLVerifyCallback] ctx.verify_callback = self[:SSLVerifyCallback]
ctx.cert_store = self[:SSLCertificateStore] ctx.cert_store = self[:SSLCertificateStore]
@ssl_ctx = ctx @ssl_ctx = ctx
end end
@ -111,13 +111,13 @@ module DRb
def self.parse_uri(uri) def self.parse_uri(uri)
if uri =~ /^drbssl:\/\/(.*?):(\d+)(\?(.*))?$/ if uri =~ /^drbssl:\/\/(.*?):(\d+)(\?(.*))?$/
host = $1 host = $1
port = $2.to_i port = $2.to_i
option = $4 option = $4
[host, port, option] [host, port, option]
else else
raise(DRbBadScheme, uri) unless uri =~ /^drbssl:/ raise(DRbBadScheme, uri) unless uri =~ /^drbssl:/
raise(DRbBadURI, 'can\'t parse uri:' + uri) raise(DRbBadURI, 'can\'t parse uri:' + uri)
end end
end end
@ -139,7 +139,7 @@ module DRb
host = getservername host = getservername
soc = open_server_inaddr_any(host, port) soc = open_server_inaddr_any(host, port)
else else
soc = TCPServer.open(host, port) soc = TCPServer.open(host, port)
end end
port = soc.addr[1] if port == 0 port = soc.addr[1] if port == 0
@uri = "drbssl://#{host}:#{port}" @uri = "drbssl://#{host}:#{port}"
@ -164,24 +164,24 @@ module DRb
def close def close
if @ssl if @ssl
@ssl.close @ssl.close
@ssl = nil @ssl = nil
end end
super super
end end
def accept def accept
begin begin
while true while true
soc = @socket.accept soc = @socket.accept
break if (@acl ? @acl.allow_socket?(soc) : true) break if (@acl ? @acl.allow_socket?(soc) : true)
soc.close soc.close
end end
ssl = @config.accept(soc) ssl = @config.accept(soc)
self.class.new(uri, ssl, @config, true) self.class.new(uri, ssl, @config, true)
rescue OpenSSL::SSL::SSLError rescue OpenSSL::SSL::SSLError
warn("#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})") if @config[:verbose] warn("#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})") if @config[:verbose]
retry retry
end end
end end
end end

View File

@ -9,65 +9,65 @@ module DRb
class InvalidIndexError < RuntimeError; end class InvalidIndexError < RuntimeError; end
def initialize(timeout=600) def initialize(timeout=600)
super() super()
@sentinel = Object.new @sentinel = Object.new
@gc = {} @gc = {}
@curr = {} @curr = {}
@renew = {} @renew = {}
@timeout = timeout @timeout = timeout
@keeper = keeper @keeper = keeper
end end
def add(obj) def add(obj)
synchronize do synchronize do
key = obj.__id__ key = obj.__id__
@curr[key] = obj @curr[key] = obj
return key return key
end end
end end
def fetch(key, dv=@sentinel) def fetch(key, dv=@sentinel)
synchronize do synchronize do
obj = peek(key) obj = peek(key)
if obj == @sentinel if obj == @sentinel
return dv unless dv == @sentinel return dv unless dv == @sentinel
raise InvalidIndexError raise InvalidIndexError
end end
@renew[key] = obj # KeepIt @renew[key] = obj # KeepIt
return obj return obj
end end
end end
def include?(key) def include?(key)
synchronize do synchronize do
obj = peek(key) obj = peek(key)
return false if obj == @sentinel return false if obj == @sentinel
true true
end end
end end
def peek(key) def peek(key)
synchronize do synchronize do
return @curr.fetch(key, @renew.fetch(key, @gc.fetch(key, @sentinel))) return @curr.fetch(key, @renew.fetch(key, @gc.fetch(key, @sentinel)))
end end
end end
private private
def alternate def alternate
synchronize do synchronize do
@gc = @curr # GCed @gc = @curr # GCed
@curr = @renew @curr = @renew
@renew = {} @renew = {}
end end
end end
def keeper def keeper
Thread.new do Thread.new do
loop do loop do
alternate alternate
sleep(@timeout) sleep(@timeout)
end end
end end
end end
end end

View File

@ -9,12 +9,12 @@ module DRb
class DRbUNIXSocket < DRbTCPSocket class DRbUNIXSocket < DRbTCPSocket
def self.parse_uri(uri) def self.parse_uri(uri)
if /^drbunix:(.*?)(\?(.*))?$/ =~ uri if /^drbunix:(.*?)(\?(.*))?$/ =~ uri
filename = $1 filename = $1
option = $3 option = $3
[filename, option] [filename, option]
else else
raise(DRbBadScheme, uri) unless uri =~ /^drbunix:/ raise(DRbBadScheme, uri) unless uri =~ /^drbunix:/
raise(DRbBadURI, 'can\'t parse uri:' + uri) raise(DRbBadURI, 'can\'t parse uri:' + uri)
end end
end end
@ -28,11 +28,11 @@ module DRb
def self.open_server(uri, config) def self.open_server(uri, config)
filename, = parse_uri(uri) filename, = parse_uri(uri)
if filename.size == 0 if filename.size == 0
soc = temp_server soc = temp_server
filename = soc.path filename = soc.path
uri = 'drbunix:' + soc.path uri = 'drbunix:' + soc.path
else else
soc = UNIXServer.open(filename) soc = UNIXServer.open(filename)
end end
owner = config[:UNIXFileOwner] owner = config[:UNIXFileOwner]
group = config[:UNIXFileGroup] group = config[:UNIXFileGroup]
@ -67,18 +67,18 @@ module DRb
tmpdir = Dir::tmpdir tmpdir = Dir::tmpdir
n = 0 n = 0
while true while true
begin begin
tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n) tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n)
lock = tmpname + '.lock' lock = tmpname + '.lock'
unless File.exist?(tmpname) or File.exist?(lock) unless File.exist?(tmpname) or File.exist?(lock)
Dir.mkdir(lock) Dir.mkdir(lock)
break break
end end
rescue rescue
raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try
#sleep(1) #sleep(1)
end end
n += 1 n += 1
end end
soc = UNIXServer.new(tmpname) soc = UNIXServer.new(tmpname)
Dir.rmdir(lock) Dir.rmdir(lock)

View File

@ -1,8 +1,8 @@
# #
# e2mmap.rb - for ruby 1.1 # e2mmap.rb - for ruby 1.1
# $Release Version: 2.0$ # $Release Version: 2.0$
# $Revision: 1.10 $ # $Revision: 1.10 $
# by Keiju ISHITSUKA # by Keiju ISHITSUKA
# #
# -- # --
# Usage: # Usage:
@ -60,19 +60,19 @@ module Exception2MessageMapper
def bind(cl) def bind(cl)
self.module_eval %[ self.module_eval %[
def Raise(err = nil, *rest) def Raise(err = nil, *rest)
Exception2MessageMapper.Raise(self.class, err, *rest) Exception2MessageMapper.Raise(self.class, err, *rest)
end end
alias Fail Raise alias Fail Raise
def self.included(mod) def self.included(mod)
mod.extend Exception2MessageMapper mod.extend Exception2MessageMapper
end end
] ]
end end
# Fail(err, *rest) # Fail(err, *rest)
# err: exception # err: exception
# rest: message arguments # rest: message arguments
# #
def Raise(err = nil, *rest) def Raise(err = nil, *rest)
E2MM.Raise(self, err, *rest) E2MM.Raise(self, err, *rest)
@ -81,19 +81,19 @@ module Exception2MessageMapper
alias fail Raise alias fail Raise
# def_e2message(c, m) # def_e2message(c, m)
# c: exception # c: exception
# m: message_form # m: message_form
# define exception c with message m. # define exception c with message m.
# #
def def_e2message(c, m) def def_e2message(c, m)
E2MM.def_e2message(self, c, m) E2MM.def_e2message(self, c, m)
end end
# def_exception(n, m, s) # def_exception(n, m, s)
# n: exception_name # n: exception_name
# m: message_form # m: message_form
# s: superclass(default: StandardError) # s: superclass(default: StandardError)
# define exception named ``c'' with message m. # define exception named ``c'' with message m.
# #
def def_exception(n, m, s = StandardError) def def_exception(n, m, s = StandardError)
E2MM.def_exception(self, n, m, s) E2MM.def_exception(self, n, m, s)
@ -106,10 +106,10 @@ module Exception2MessageMapper
@MessageMap = {} @MessageMap = {}
# E2MM.def_e2message(k, e, m) # E2MM.def_e2message(k, e, m)
# k: class to define exception under. # k: class to define exception under.
# e: exception # e: exception
# m: message_form # m: message_form
# define exception c with message m. # define exception c with message m.
# #
def E2MM.def_e2message(k, c, m) def E2MM.def_e2message(k, c, m)
E2MM.instance_eval{@MessageMap[[k, c]] = m} E2MM.instance_eval{@MessageMap[[k, c]] = m}
@ -117,11 +117,11 @@ module Exception2MessageMapper
end end
# E2MM.def_exception(k, n, m, s) # E2MM.def_exception(k, n, m, s)
# k: class to define exception under. # k: class to define exception under.
# n: exception_name # n: exception_name
# m: message_form # m: message_form
# s: superclass(default: StandardError) # s: superclass(default: StandardError)
# define exception named ``c'' with message m. # define exception named ``c'' with message m.
# #
def E2MM.def_exception(k, n, m, s = StandardError) def E2MM.def_exception(k, n, m, s = StandardError)
n = n.id2name if n.kind_of?(Fixnum) n = n.id2name if n.kind_of?(Fixnum)
@ -131,9 +131,9 @@ module Exception2MessageMapper
end end
# Fail(klass, err, *rest) # Fail(klass, err, *rest)
# klass: class to define exception under. # klass: class to define exception under.
# err: exception # err: exception
# rest: message arguments # rest: message arguments
# #
def E2MM.Raise(klass = E2MM, err = nil, *rest) def E2MM.Raise(klass = E2MM, err = nil, *rest)
if form = e2mm_message(klass, err) if form = e2mm_message(klass, err)
@ -141,7 +141,7 @@ module Exception2MessageMapper
#p $@ #p $@
#p __FILE__ #p __FILE__
b.shift if b[0] =~ /^#{Regexp.quote(__FILE__)}:/ b.shift if b[0] =~ /^#{Regexp.quote(__FILE__)}:/
raise err, sprintf(form, *rest), b raise err, sprintf(form, *rest), b
else else
E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
end end
@ -153,9 +153,9 @@ module Exception2MessageMapper
def E2MM.e2mm_message(klass, exp) def E2MM.e2mm_message(klass, exp)
for c in klass.ancestors for c in klass.ancestors
if mes = @MessageMap[[c,exp]] if mes = @MessageMap[[c,exp]]
#p mes #p mes
m = klass.instance_eval('"' + mes + '"') m = klass.instance_eval('"' + mes + '"')
return m return m
end end
end end
nil nil
@ -165,8 +165,8 @@ module Exception2MessageMapper
end end
E2MM.def_exception(E2MM, E2MM.def_exception(E2MM,
:ErrNotRegisteredException, :ErrNotRegisteredException,
"not registerd exception(%s)") "not registerd exception(%s)")
end end

View File

@ -254,7 +254,7 @@
# Rails, the web application framework, uses ERB to create views. # Rails, the web application framework, uses ERB to create views.
# #
class ERB class ERB
Revision = '$Date:: $' #' Revision = '$Date:: $' #'
# Returns revision information for the erb.rb module. # Returns revision information for the erb.rb module.
def self.version def self.version
@ -351,21 +351,21 @@ class ERB
class Scanner # :nodoc: class Scanner # :nodoc:
@scanner_map = {} @scanner_map = {}
def self.regist_scanner(klass, trim_mode, percent) def self.regist_scanner(klass, trim_mode, percent)
@scanner_map[[trim_mode, percent]] = klass @scanner_map[[trim_mode, percent]] = klass
end end
def self.default_scanner=(klass) def self.default_scanner=(klass)
@default_scanner = klass @default_scanner = klass
end end
def self.make_scanner(src, trim_mode, percent) def self.make_scanner(src, trim_mode, percent)
klass = @scanner_map.fetch([trim_mode, percent], @default_scanner) klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
klass.new(src, trim_mode, percent) klass.new(src, trim_mode, percent)
end end
def initialize(src, trim_mode, percent) def initialize(src, trim_mode, percent)
@src = src @src = src
@stag = nil @stag = nil
end end
attr_accessor :stag attr_accessor :stag
@ -374,44 +374,44 @@ class ERB
class TrimScanner < Scanner # :nodoc: class TrimScanner < Scanner # :nodoc:
def initialize(src, trim_mode, percent) def initialize(src, trim_mode, percent)
super super
@trim_mode = trim_mode @trim_mode = trim_mode
@percent = percent @percent = percent
if @trim_mode == '>' if @trim_mode == '>'
@scan_line = self.method(:trim_line1) @scan_line = self.method(:trim_line1)
elsif @trim_mode == '<>' elsif @trim_mode == '<>'
@scan_line = self.method(:trim_line2) @scan_line = self.method(:trim_line2)
elsif @trim_mode == '-' elsif @trim_mode == '-'
@scan_line = self.method(:explicit_trim_line) @scan_line = self.method(:explicit_trim_line)
else else
@scan_line = self.method(:scan_line) @scan_line = self.method(:scan_line)
end end
end end
attr_accessor :stag attr_accessor :stag
def scan(&block) def scan(&block)
@stag = nil @stag = nil
if @percent if @percent
@src.each_line do |line| @src.each_line do |line|
percent_line(line, &block) percent_line(line, &block)
end end
else else
@scan_line.call(@src, &block) @scan_line.call(@src, &block)
end end
nil nil
end end
def percent_line(line, &block) def percent_line(line, &block)
if @stag || line[0] != ?% if @stag || line[0] != ?%
return @scan_line.call(line, &block) return @scan_line.call(line, &block)
end end
line[0] = '' line[0] = ''
if line[0] == ?% if line[0] == ?%
@scan_line.call(line, &block) @scan_line.call(line, &block)
else else
yield(PercentLine.new(line.chomp)) yield(PercentLine.new(line.chomp))
end end
end end
def scan_line(line) def scan_line(line)
@ -420,7 +420,7 @@ class ERB
next if token.empty? next if token.empty?
yield(token) yield(token)
end end
end end
end end
def trim_line1(line) def trim_line1(line)
@ -434,11 +434,11 @@ class ERB
yield(token) yield(token)
end end
end end
end end
end end
def trim_line2(line) def trim_line2(line)
head = nil head = nil
line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens| line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
tokens.each do |token| tokens.each do |token|
next if token.empty? next if token.empty?
@ -456,7 +456,7 @@ class ERB
head = nil if token == "\n" head = nil if token == "\n"
end end
end end
end end
end end
def explicit_trim_line(line) def explicit_trim_line(line)
@ -479,7 +479,7 @@ class ERB
ERB_STAG = %w(<%= <%# <%) ERB_STAG = %w(<%= <%# <%)
def is_erb_stag?(s) def is_erb_stag?(s)
ERB_STAG.member?(s) ERB_STAG.member?(s)
end end
end end
@ -492,7 +492,7 @@ class ERB
next if token.empty? next if token.empty?
yield(token) yield(token)
end end
end end
end end
end end
@ -515,23 +515,23 @@ class ERB
Scanner.regist_scanner(SimpleScanner2, nil, false) Scanner.regist_scanner(SimpleScanner2, nil, false)
class ExplicitScanner < Scanner # :nodoc: class ExplicitScanner < Scanner # :nodoc:
def scan def scan
stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m
etag_reg = /(.*?)(%%>|-%>|%>|\z)/m etag_reg = /(.*?)(%%>|-%>|%>|\z)/m
scanner = StringScanner.new(@src) scanner = StringScanner.new(@src)
while ! scanner.eos? while ! scanner.eos?
scanner.scan(@stag ? etag_reg : stag_reg) scanner.scan(@stag ? etag_reg : stag_reg)
yield(scanner[1]) yield(scanner[1])
elem = scanner[2] elem = scanner[2]
if /[ \t]*<%-/ =~ elem if /[ \t]*<%-/ =~ elem
yield('<%') yield('<%')
elsif elem == '-%>' elsif elem == '-%>'
yield('%>') yield('%>')
yield(:cr) if scanner.scan(/(\n|\z)/) yield(:cr) if scanner.scan(/(\n|\z)/)
else else
yield(elem) yield(elem)
end end
end end
end end
end end
@ -542,32 +542,32 @@ class ERB
class Buffer # :nodoc: class Buffer # :nodoc:
def initialize(compiler, enc=nil) def initialize(compiler, enc=nil)
@compiler = compiler @compiler = compiler
@line = [] @line = []
@script = enc ? "#coding:#{enc.to_s}\n" : "" @script = enc ? "#coding:#{enc.to_s}\n" : ""
@compiler.pre_cmd.each do |x| @compiler.pre_cmd.each do |x|
push(x) push(x)
end end
end end
attr_reader :script attr_reader :script
def push(cmd) def push(cmd)
@line << cmd @line << cmd
end end
def cr def cr
@script << (@line.join('; ')) @script << (@line.join('; '))
@line = [] @line = []
@script << "\n" @script << "\n"
end end
def close def close
return unless @line return unless @line
@compiler.post_cmd.each do |x| @compiler.post_cmd.each do |x|
push(x) push(x)
end end
@script << (@line.join('; ')) @script << (@line.join('; '))
@line = nil @line = nil
end end
end end
@ -594,53 +594,53 @@ class ERB
scanner.scan do |token| scanner.scan do |token|
next if token.nil? next if token.nil?
next if token == '' next if token == ''
if scanner.stag.nil? if scanner.stag.nil?
case token case token
when PercentLine when PercentLine
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0 out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
content = '' content = ''
out.push(token.to_s) out.push(token.to_s)
out.cr out.cr
when :cr when :cr
out.cr out.cr
when '<%', '<%=', '<%#' when '<%', '<%=', '<%#'
scanner.stag = token scanner.stag = token
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0 out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
content = '' content = ''
when "\n" when "\n"
content << "\n" content << "\n"
out.push("#{@put_cmd} #{content_dump(content)}") out.push("#{@put_cmd} #{content_dump(content)}")
content = '' content = ''
when '<%%' when '<%%'
content << '<%' content << '<%'
else else
content << token content << token
end end
else else
case token case token
when '%>' when '%>'
case scanner.stag case scanner.stag
when '<%' when '<%'
if content[-1] == ?\n if content[-1] == ?\n
content.chop! content.chop!
out.push(content) out.push(content)
out.cr out.cr
else else
out.push(content) out.push(content)
end end
when '<%=' when '<%='
out.push("#{@insert_cmd}((#{content}).to_s)") out.push("#{@insert_cmd}((#{content}).to_s)")
when '<%#' when '<%#'
# out.push("# #{content_dump(content)}") # out.push("# #{content_dump(content)}")
end end
scanner.stag = nil scanner.stag = nil
content = '' content = ''
when '%%>' when '%%>'
content << '%>' content << '%>'
else else
content << token content << token
end end
end end
end end
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0 out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
out.close out.close
@ -650,24 +650,24 @@ class ERB
def prepare_trim_mode(mode) # :nodoc: def prepare_trim_mode(mode) # :nodoc:
case mode case mode
when 1 when 1
return [false, '>'] return [false, '>']
when 2 when 2
return [false, '<>'] return [false, '<>']
when 0 when 0
return [false, nil] return [false, nil]
when String when String
perc = mode.include?('%') perc = mode.include?('%')
if mode.include?('-') if mode.include?('-')
return [perc, '-'] return [perc, '-']
elsif mode.include?('<>') elsif mode.include?('<>')
return [perc, '<>'] return [perc, '<>']
elsif mode.include?('>') elsif mode.include?('>')
return [perc, '>'] return [perc, '>']
else else
[perc, nil] [perc, nil]
end end
else else
return [false, nil] return [false, nil]
end end
end end
@ -701,12 +701,12 @@ class ERB
private private
def detect_magic_comment(s) def detect_magic_comment(s)
if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s) if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s)
comment = $1 comment = $1
comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/] comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment
enc = $1.sub(/-(?:mac|dos|unix)/i, '') enc = $1.sub(/-(?:mac|dos|unix)/i, '')
enc = Encoding.find(enc) enc = Encoding.find(enc)
end end
end end
end end
end end
@ -726,9 +726,9 @@ class ERB
# If _trim_mode_ is passed a String containing one or more of the following # If _trim_mode_ is passed a String containing one or more of the following
# modifiers, ERB will adjust its code generation as listed: # modifiers, ERB will adjust its code generation as listed:
# #
# % enables Ruby code processing for lines beginning with % # % enables Ruby code processing for lines beginning with %
# <> omit newline for lines starting with <% and ending in %> # <> omit newline for lines starting with <% and ending in %>
# > omit newline for lines ending in %> # > omit newline for lines ending in %>
# #
# _eoutvar_ can be used to set the name of the variable ERB will build up # _eoutvar_ can be used to set the name of the variable ERB will build up
# its output in. This is useful when you need to run multiple ERB # its output in. This is useful when you need to run multiple ERB
@ -831,8 +831,8 @@ class ERB
def result(b=TOPLEVEL_BINDING) def result(b=TOPLEVEL_BINDING)
if @safe_level if @safe_level
proc { proc {
$SAFE = @safe_level $SAFE = @safe_level
eval(@src, b, (@filename || '(erb)'), 0) eval(@src, b, (@filename || '(erb)'), 0)
}.call }.call
else else
eval(@src, b, (@filename || '(erb)'), 0) eval(@src, b, (@filename || '(erb)'), 0)
@ -899,14 +899,14 @@ class ERB
# #
# A utility method for escaping HTML tag characters in _s_. # A utility method for escaping HTML tag characters in _s_.
# #
# require "erb" # require "erb"
# include ERB::Util # include ERB::Util
# #
# puts html_escape("is a > 0 & a < 10?") # puts html_escape("is a > 0 & a < 10?")
# #
# _Generates_ # _Generates_
# #
# is a &gt; 0 &amp; a &lt; 10? # is a &gt; 0 &amp; a &lt; 10?
# #
def html_escape(s) def html_escape(s)
s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;") s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
@ -918,14 +918,14 @@ class ERB
# #
# A utility method for encoding the String _s_ as a URL. # A utility method for encoding the String _s_ as a URL.
# #
# require "erb" # require "erb"
# include ERB::Util # include ERB::Util
# #
# puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide") # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
# #
# _Generates_ # _Generates_
# #
# Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
# #
def url_encode(s) def url_encode(s)
s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) { s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
@ -971,7 +971,7 @@ class ERB
# #
module DefMethod module DefMethod
public public
# define _methodname_ as instance method of current module, using ERB object or eRuby file # define _methodname_ as instance method of current module, using ERB object or eRuby file
def def_erb_method(methodname, erb_or_fname) def def_erb_method(methodname, erb_or_fname)
if erb_or_fname.kind_of? String if erb_or_fname.kind_of? String
fname = erb_or_fname fname = erb_or_fname

View File

@ -38,7 +38,7 @@ module Find
paths.collect!{|d| raise Errno::ENOENT unless File.exist?(d); d.dup} paths.collect!{|d| raise Errno::ENOENT unless File.exist?(d); d.dup}
while file = paths.shift while file = paths.shift
catch(:prune) do catch(:prune) do
yield file.dup.taint yield file.dup.taint
begin begin
s = File.lstat(file) s = File.lstat(file)
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG

View File

@ -1,9 +1,9 @@
# #
# forwardable.rb - # forwardable.rb -
# $Release Version: 1.1$ # $Release Version: 1.1$
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ishitsuka.com) # by Keiju ISHITSUKA(keiju@ishitsuka.com)
# original definition by delegator.rb # original definition by delegator.rb
# Revised by Daniel J. Berger with suggestions from Florian Gross. # Revised by Daniel J. Berger with suggestions from Florian Gross.
# #
# Documentation by James Edward Gray II and Gavin Sinclair # Documentation by James Edward Gray II and Gavin Sinclair
@ -84,7 +84,7 @@
# def_delegator :Implementation, :service # def_delegator :Implementation, :service
# #
# class Implementation # class Implementation
# def service... # def service...
# end # end
# end # end
# #
@ -178,12 +178,12 @@ module Forwardable
def def_instance_delegator(accessor, method, ali = method) def def_instance_delegator(accessor, method, ali = method)
line_no = __LINE__; str = %{ line_no = __LINE__; str = %{
def #{ali}(*args, &block) def #{ali}(*args, &block)
begin begin
#{accessor}.__send__(:#{method}, *args, &block) #{accessor}.__send__(:#{method}, *args, &block)
rescue Exception rescue Exception
$@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
::Kernel::raise ::Kernel::raise
end end
end end
} }
# If it's not a class or module, it's an instance # If it's not a class or module, it's an instance
@ -248,12 +248,12 @@ module SingleForwardable
def def_single_delegator(accessor, method, ali = method) def def_single_delegator(accessor, method, ali = method)
str = %{ str = %{
def #{ali}(*args, &block) def #{ali}(*args, &block)
begin begin
#{accessor}.__send__(:#{method}, *args, &block) #{accessor}.__send__(:#{method}, *args, &block)
rescue Exception rescue Exception
$@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
::Kernel::raise ::Kernel::raise
end end
end end
} }

View File

@ -241,7 +241,7 @@ class GetoptLong
if @status != STATUS_YET if @status != STATUS_YET
set_error(ArgumentError, "argument error") set_error(ArgumentError, "argument error")
raise RuntimeError, raise RuntimeError,
"invoke ordering=, but option processing has already started" "invoke ordering=, but option processing has already started"
end end
# #
@ -273,7 +273,7 @@ class GetoptLong
# #
if @status != STATUS_YET if @status != STATUS_YET
raise RuntimeError, raise RuntimeError,
"invoke set_options, but option processing has already started" "invoke set_options, but option processing has already started"
end end
# #
@ -284,7 +284,7 @@ class GetoptLong
arguments.each do |arg| arguments.each do |arg|
if !arg.is_a?(Array) if !arg.is_a?(Array)
raise ArgumentError, "the option list contains non-Array argument" raise ArgumentError, "the option list contains non-Array argument"
end end
# #
@ -292,44 +292,44 @@ class GetoptLong
# #
argument_flag = nil argument_flag = nil
arg.each do |i| arg.each do |i|
if ARGUMENT_FLAGS.include?(i) if ARGUMENT_FLAGS.include?(i)
if argument_flag != nil if argument_flag != nil
raise ArgumentError, "too many argument-flags" raise ArgumentError, "too many argument-flags"
end end
argument_flag = i argument_flag = i
end end
end end
raise ArgumentError, "no argument-flag" if argument_flag == nil raise ArgumentError, "no argument-flag" if argument_flag == nil
canonical_name = nil canonical_name = nil
arg.each do |i| arg.each do |i|
# #
# Check an option name. # Check an option name.
# #
next if i == argument_flag next if i == argument_flag
begin begin
if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/ if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
raise ArgumentError, "an invalid option `#{i}'" raise ArgumentError, "an invalid option `#{i}'"
end end
if (@canonical_names.include?(i)) if (@canonical_names.include?(i))
raise ArgumentError, "option redefined `#{i}'" raise ArgumentError, "option redefined `#{i}'"
end end
rescue rescue
@canonical_names.clear @canonical_names.clear
@argument_flags.clear @argument_flags.clear
raise raise
end end
# #
# Register the option (`i') to the `@canonical_names' and # Register the option (`i') to the `@canonical_names' and
# `@canonical_names' Hashes. # `@canonical_names' Hashes.
# #
if canonical_name == nil if canonical_name == nil
canonical_name = i canonical_name = i
end end
@canonical_names[i] = canonical_name @canonical_names[i] = canonical_name
@argument_flags[i] = argument_flag @argument_flags[i] = argument_flag
end end
raise ArgumentError, "no option name" if canonical_name == nil raise ArgumentError, "no option name" if canonical_name == nil
end end
@ -447,17 +447,17 @@ class GetoptLong
return nil return nil
elsif @ordering == PERMUTE elsif @ordering == PERMUTE
while 0 < ARGV.length && ARGV[0] !~ /^-./ while 0 < ARGV.length && ARGV[0] !~ /^-./
@non_option_arguments.push(ARGV.shift) @non_option_arguments.push(ARGV.shift)
end end
if ARGV.length == 0 if ARGV.length == 0
terminate terminate
return nil return nil
end end
argument = ARGV.shift argument = ARGV.shift
elsif @ordering == REQUIRE_ORDER elsif @ordering == REQUIRE_ORDER
if (ARGV[0] !~ /^-./) if (ARGV[0] !~ /^-./)
terminate terminate
return nil return nil
end end
argument = ARGV.shift argument = ARGV.shift
else else
@ -482,49 +482,49 @@ class GetoptLong
# #
pattern = $1 pattern = $1
if @canonical_names.include?(pattern) if @canonical_names.include?(pattern)
option_name = pattern option_name = pattern
else else
# #
# The option `option_name' is not registered in `@canonical_names'. # The option `option_name' is not registered in `@canonical_names'.
# It may be an abbreviated. # It may be an abbreviated.
# #
matches = [] matches = []
@canonical_names.each_key do |key| @canonical_names.each_key do |key|
if key.index(pattern) == 0 if key.index(pattern) == 0
option_name = key option_name = key
matches << key matches << key
end end
end end
if 2 <= matches.length if 2 <= matches.length
set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
elsif matches.length == 0 elsif matches.length == 0
set_error(InvalidOption, "unrecognized option `#{argument}'") set_error(InvalidOption, "unrecognized option `#{argument}'")
end end
end end
# #
# Check an argument to the option. # Check an argument to the option.
# #
if @argument_flags[option_name] == REQUIRED_ARGUMENT if @argument_flags[option_name] == REQUIRED_ARGUMENT
if argument =~ /=(.*)$/ if argument =~ /=(.*)$/
option_argument = $1 option_argument = $1
elsif 0 < ARGV.length elsif 0 < ARGV.length
option_argument = ARGV.shift option_argument = ARGV.shift
else else
set_error(MissingArgument, set_error(MissingArgument,
"option `#{argument}' requires an argument") "option `#{argument}' requires an argument")
end end
elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
if argument =~ /=(.*)$/ if argument =~ /=(.*)$/
option_argument = $1 option_argument = $1
elsif 0 < ARGV.length && ARGV[0] !~ /^-./ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
option_argument = ARGV.shift option_argument = ARGV.shift
else else
option_argument = '' option_argument = ''
end end
elsif argument =~ /=(.*)$/ elsif argument =~ /=(.*)$/
set_error(NeedlessArgument, set_error(NeedlessArgument,
"option `#{option_name}' doesn't allow an argument") "option `#{option_name}' doesn't allow an argument")
end end
elsif argument =~ /^(-(.))(.*)/ elsif argument =~ /^(-(.))(.*)/
@ -536,40 +536,40 @@ class GetoptLong
option_name, ch, @rest_singles = $1, $2, $3 option_name, ch, @rest_singles = $1, $2, $3
if @canonical_names.include?(option_name) if @canonical_names.include?(option_name)
# #
# The option `option_name' is found in `@canonical_names'. # The option `option_name' is found in `@canonical_names'.
# Check its argument. # Check its argument.
# #
if @argument_flags[option_name] == REQUIRED_ARGUMENT if @argument_flags[option_name] == REQUIRED_ARGUMENT
if 0 < @rest_singles.length if 0 < @rest_singles.length
option_argument = @rest_singles option_argument = @rest_singles
@rest_singles = '' @rest_singles = ''
elsif 0 < ARGV.length elsif 0 < ARGV.length
option_argument = ARGV.shift option_argument = ARGV.shift
else else
# 1003.2 specifies the format of this message. # 1003.2 specifies the format of this message.
set_error(MissingArgument, "option requires an argument -- #{ch}") set_error(MissingArgument, "option requires an argument -- #{ch}")
end end
elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
if 0 < @rest_singles.length if 0 < @rest_singles.length
option_argument = @rest_singles option_argument = @rest_singles
@rest_singles = '' @rest_singles = ''
elsif 0 < ARGV.length && ARGV[0] !~ /^-./ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
option_argument = ARGV.shift option_argument = ARGV.shift
else else
option_argument = '' option_argument = ''
end end
end end
else else
# #
# This is an invalid option. # This is an invalid option.
# 1003.2 specifies the format of this message. # 1003.2 specifies the format of this message.
# #
if ENV.include?('POSIXLY_CORRECT') if ENV.include?('POSIXLY_CORRECT')
set_error(InvalidOption, "invalid option -- #{ch}") set_error(InvalidOption, "invalid option -- #{ch}")
else else
set_error(InvalidOption, "invalid option -- #{ch}") set_error(InvalidOption, "invalid option -- #{ch}")
end end
end end
else else
# #

View File

@ -72,17 +72,17 @@ end
# #
# ipaddr1 = IPAddr.new "3ffe:505:2::1" # ipaddr1 = IPAddr.new "3ffe:505:2::1"
# #
# p ipaddr1 #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff> # p ipaddr1 #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
# #
# p ipaddr1.to_s #=> "3ffe:505:2::1" # p ipaddr1.to_s #=> "3ffe:505:2::1"
# #
# ipaddr2 = ipaddr1.mask(48) #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000> # ipaddr2 = ipaddr1.mask(48) #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>
# #
# p ipaddr2.to_s #=> "3ffe:505:2::" # p ipaddr2.to_s #=> "3ffe:505:2::"
# #
# ipaddr3 = IPAddr.new "192.168.2.0/24" # ipaddr3 = IPAddr.new "192.168.2.0/24"
# #
# p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0> # p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
class IPAddr class IPAddr
@ -157,13 +157,13 @@ class IPAddr
# net1 = IPAddr.new("192.168.2.0/24") # net1 = IPAddr.new("192.168.2.0/24")
# net2 = IPAddr.new("192.168.2.100") # net2 = IPAddr.new("192.168.2.100")
# net3 = IPAddr.new("192.168.3.0") # net3 = IPAddr.new("192.168.3.0")
# p net1.include?(net2) #=> true # p net1.include?(net2) #=> true
# p net1.include?(net3) #=> false # p net1.include?(net3) #=> false
def include?(other) def include?(other)
other = coerce_other(other) other = coerce_other(other)
if ipv4_mapped? if ipv4_mapped?
if (@mask_addr >> 32) != 0xffffffffffffffffffffffff if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
return false return false
end end
mask_addr = (@mask_addr & IN4MASK) mask_addr = (@mask_addr & IN4MASK)
addr = (@addr & IN4MASK) addr = (@addr & IN4MASK)
@ -231,7 +231,7 @@ class IPAddr
return [@addr].pack('N') return [@addr].pack('N')
when Socket::AF_INET6 when Socket::AF_INET6
return (0..7).map { |i| return (0..7).map { |i|
(@addr >> (112 - 16 * i)) & 0xffff (@addr >> (112 - 16 * i)) & 0xffff
}.pack('n8') }.pack('n8')
else else
raise "unsupported address family" raise "unsupported address family"
@ -372,7 +372,7 @@ class IPAddr
raise "unsupported address family" raise "unsupported address family"
end end
return sprintf("#<%s: %s:%s/%s>", self.class.name, return sprintf("#<%s: %s:%s/%s>", self.class.name,
af, _to_string(@addr), _to_string(@mask_addr)) af, _to_string(@addr), _to_string(@mask_addr))
end end
protected protected
@ -381,11 +381,11 @@ class IPAddr
case family[0] ? family[0] : @family case family[0] ? family[0] : @family
when Socket::AF_INET when Socket::AF_INET
if addr < 0 || addr > IN4MASK if addr < 0 || addr > IN4MASK
raise ArgumentError, "invalid address" raise ArgumentError, "invalid address"
end end
when Socket::AF_INET6 when Socket::AF_INET6
if addr < 0 || addr > IN6MASK if addr < 0 || addr > IN6MASK
raise ArgumentError, "invalid address" raise ArgumentError, "invalid address"
end end
else else
raise ArgumentError, "unsupported address family" raise ArgumentError, "unsupported address family"
@ -400,15 +400,15 @@ class IPAddr
def mask!(mask) def mask!(mask)
if mask.kind_of?(String) if mask.kind_of?(String)
if mask =~ /^\d+$/ if mask =~ /^\d+$/
prefixlen = mask.to_i prefixlen = mask.to_i
else else
m = IPAddr.new(mask) m = IPAddr.new(mask)
if m.family != @family if m.family != @family
raise ArgumentError, "address family is not same" raise ArgumentError, "address family is not same"
end end
@mask_addr = m.to_i @mask_addr = m.to_i
@addr &= @mask_addr @addr &= @mask_addr
return self return self
end end
else else
prefixlen = mask prefixlen = mask
@ -416,13 +416,13 @@ class IPAddr
case @family case @family
when Socket::AF_INET when Socket::AF_INET
if prefixlen < 0 || prefixlen > 32 if prefixlen < 0 || prefixlen > 32
raise ArgumentError, "invalid length" raise ArgumentError, "invalid length"
end end
masklen = 32 - prefixlen masklen = 32 - prefixlen
@mask_addr = ((IN4MASK >> masklen) << masklen) @mask_addr = ((IN4MASK >> masklen) << masklen)
when Socket::AF_INET6 when Socket::AF_INET6
if prefixlen < 0 || prefixlen > 128 if prefixlen < 0 || prefixlen > 128
raise ArgumentError, "invalid length" raise ArgumentError, "invalid length"
end end
masklen = 128 - prefixlen masklen = 128 - prefixlen
@mask_addr = ((IN6MASK >> masklen) << masklen) @mask_addr = ((IN6MASK >> masklen) << masklen)
@ -461,9 +461,9 @@ class IPAddr
@mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK
return return
when Socket::AF_UNSPEC when Socket::AF_UNSPEC
raise ArgumentError, "address family must be specified" raise ArgumentError, "address family must be specified"
else else
raise ArgumentError, "unsupported address family: #{family}" raise ArgumentError, "unsupported address family: #{family}"
end end
end end
prefix, prefixlen = addr.split('/') prefix, prefixlen = addr.split('/')
@ -473,9 +473,9 @@ class IPAddr
end end
# It seems AI_NUMERICHOST doesn't do the job. # It seems AI_NUMERICHOST doesn't do the job.
#Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil, #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
# Socket::AI_NUMERICHOST) # Socket::AI_NUMERICHOST)
begin begin
IPSocket.getaddress(prefix) # test if address is valid IPSocket.getaddress(prefix) # test if address is valid
rescue rescue
raise ArgumentError, "invalid address" raise ArgumentError, "invalid address"
end end
@ -483,7 +483,7 @@ class IPAddr
if family == Socket::AF_UNSPEC || family == Socket::AF_INET if family == Socket::AF_UNSPEC || family == Socket::AF_INET
@addr = in_addr(prefix) @addr = in_addr(prefix)
if @addr if @addr
@family = Socket::AF_INET @family = Socket::AF_INET
end end
end end
if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6) if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6)
@ -514,8 +514,8 @@ class IPAddr
def in_addr(addr) def in_addr(addr)
if addr =~ /^\d+\.\d+\.\d+\.\d+$/ if addr =~ /^\d+\.\d+\.\d+\.\d+$/
return addr.split('.').inject(0) { |i, s| return addr.split('.').inject(0) { |i, s|
i << 8 | s.to_i i << 8 | s.to_i
} }
end end
return nil return nil
end end
@ -559,7 +559,7 @@ class IPAddr
case @family case @family
when Socket::AF_INET when Socket::AF_INET
return (0..3).map { |i| return (0..3).map { |i|
(@addr >> (8 * i)) & 0xff (@addr >> (8 * i)) & 0xff
}.join('.') }.join('.')
when Socket::AF_INET6 when Socket::AF_INET6
return ("%.32x" % @addr).reverse!.gsub!(/.(?!$)/, '\&.') return ("%.32x" % @addr).reverse!.gsub!(/.(?!$)/, '\&.')
@ -572,7 +572,7 @@ class IPAddr
case @family case @family
when Socket::AF_INET when Socket::AF_INET
return (0..3).map { |i| return (0..3).map { |i|
(addr >> (24 - 8 * i)) & 0xff (addr >> (24 - 8 * i)) & 0xff
}.join('.') }.join('.')
when Socket::AF_INET6 when Socket::AF_INET6
return (("%.32x" % addr).gsub!(/.{4}(?!$)/, '\&:')) return (("%.32x" % addr).gsub!(/.{4}(?!$)/, '\&:'))
@ -659,7 +659,7 @@ class TC_IPAddr < Test::Unit::TestCase
["[192.168.1.2]/120"], ["[192.168.1.2]/120"],
].each { |args| ].each { |args|
assert_raises(ArgumentError) { assert_raises(ArgumentError) {
IPAddr.new(*args) IPAddr.new(*args)
} }
} }
end end
@ -760,7 +760,7 @@ class TC_Operator < Test::Unit::TestCase
assert_equal("3ffe:505:2:1::", a.to_s) assert_equal("3ffe:505:2:1::", a.to_s)
assert_equal("3ffe:505:2::", @a.to_s) assert_equal("3ffe:505:2::", @a.to_s)
assert_equal("3ffe:505:2:1::", assert_equal("3ffe:505:2:1::",
(@a | 0x00000000000000010000000000000000).to_s) (@a | 0x00000000000000010000000000000000).to_s)
end end
def test_and def test_and

View File

@ -1,8 +1,8 @@
# #
# irb.rb - irb main module # irb.rb - irb main module
# $Release Version: 0.9.6 $ # $Release Version: 0.9.6 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -67,12 +67,12 @@ module IRB
begin begin
catch(:IRB_EXIT) do catch(:IRB_EXIT) do
irb.eval_input irb.eval_input
end end
ensure ensure
irb_at_exit irb_at_exit
end end
# print "\n" # print "\n"
end end
def IRB.irb_at_exit def IRB.irb_at_exit
@ -108,99 +108,99 @@ module IRB
def eval_input def eval_input
@scanner.set_prompt do @scanner.set_prompt do
|ltype, indent, continue, line_no| |ltype, indent, continue, line_no|
if ltype if ltype
f = @context.prompt_s f = @context.prompt_s
elsif continue elsif continue
f = @context.prompt_c f = @context.prompt_c
elsif indent > 0 elsif indent > 0
f = @context.prompt_n f = @context.prompt_n
else else
f = @context.prompt_i f = @context.prompt_i
end end
f = "" unless f f = "" unless f
if @context.prompting? if @context.prompting?
@context.io.prompt = p = prompt(f, ltype, indent, line_no) @context.io.prompt = p = prompt(f, ltype, indent, line_no)
else else
@context.io.prompt = p = "" @context.io.prompt = p = ""
end end
if @context.auto_indent_mode if @context.auto_indent_mode
unless ltype unless ltype
ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size + ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
indent * 2 - p.size indent * 2 - p.size
ind += 2 if continue ind += 2 if continue
@context.io.prompt = p + " " * ind if ind > 0 @context.io.prompt = p + " " * ind if ind > 0
end end
end end
end end
@scanner.set_input(@context.io) do @scanner.set_input(@context.io) do
signal_status(:IN_INPUT) do signal_status(:IN_INPUT) do
if l = @context.io.gets if l = @context.io.gets
print l if @context.verbose? print l if @context.verbose?
else else
if @context.ignore_eof? and @context.io.readable_atfer_eof? if @context.ignore_eof? and @context.io.readable_atfer_eof?
l = "\n" l = "\n"
if @context.verbose? if @context.verbose?
printf "Use \"exit\" to leave %s\n", @context.ap_name printf "Use \"exit\" to leave %s\n", @context.ap_name
end end
else else
print "\n" print "\n"
end end
end end
l l
end end
end end
@scanner.each_top_level_statement do |line, line_no| @scanner.each_top_level_statement do |line, line_no|
signal_status(:IN_EVAL) do signal_status(:IN_EVAL) do
begin begin
line.untaint line.untaint
@context.evaluate(line, line_no) @context.evaluate(line, line_no)
output_value if @context.echo? output_value if @context.echo?
exc = nil exc = nil
rescue Interrupt => exc rescue Interrupt => exc
rescue SystemExit, SignalException rescue SystemExit, SignalException
raise raise
rescue Exception => exc rescue Exception => exc
end end
if exc if exc
print exc.class, ": ", exc, "\n" print exc.class, ": ", exc, "\n"
if exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ && if exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
!(SyntaxError === exc) !(SyntaxError === exc)
irb_bug = true irb_bug = true
else else
irb_bug = false irb_bug = false
end end
messages = [] messages = []
lasts = [] lasts = []
levels = 0 levels = 0
for m in exc.backtrace for m in exc.backtrace
m = @context.workspace.filter_backtrace(m) unless irb_bug m = @context.workspace.filter_backtrace(m) unless irb_bug
if m if m
if messages.size < @context.back_trace_limit if messages.size < @context.back_trace_limit
messages.push "\tfrom "+m messages.push "\tfrom "+m
else else
lasts.push "\tfrom "+m lasts.push "\tfrom "+m
if lasts.size > @context.back_trace_limit if lasts.size > @context.back_trace_limit
lasts.shift lasts.shift
levels += 1 levels += 1
end end
end end
end end
end end
print messages.join("\n"), "\n" print messages.join("\n"), "\n"
unless lasts.empty? unless lasts.empty?
printf "... %d levels...\n", levels if levels > 0 printf "... %d levels...\n", levels if levels > 0
print lasts.join("\n") print lasts.join("\n")
end end
print "Maybe IRB bug!\n" if irb_bug print "Maybe IRB bug!\n" if irb_bug
end end
if $SAFE > 2 if $SAFE > 2
abort "Error: irb does not work for $SAFE level higher than 2" abort "Error: irb does not work for $SAFE level higher than 2"
end end
end end
end end
end end
@ -208,19 +208,19 @@ module IRB
@context.irb_path, back_path = path, @context.irb_path if path @context.irb_path, back_path = path, @context.irb_path if path
@context.irb_name, back_name = name, @context.irb_name if name @context.irb_name, back_name = name, @context.irb_name if name
begin begin
yield back_path, back_name yield back_path, back_name
ensure ensure
@context.irb_path = back_path if path @context.irb_path = back_path if path
@context.irb_name = back_name if name @context.irb_name = back_name if name
end end
end end
def suspend_workspace(workspace) def suspend_workspace(workspace)
@context.workspace, back_workspace = workspace, @context.workspace @context.workspace, back_workspace = workspace, @context.workspace
begin begin
yield back_workspace yield back_workspace
ensure ensure
@context.workspace = back_workspace @context.workspace = back_workspace
end end
end end
@ -228,39 +228,39 @@ module IRB
back_io = @context.io back_io = @context.io
@context.instance_eval{@io = input_method} @context.instance_eval{@io = input_method}
begin begin
yield back_io yield back_io
ensure ensure
@context.instance_eval{@io = back_io} @context.instance_eval{@io = back_io}
end end
end end
def suspend_context(context) def suspend_context(context)
@context, back_context = context, @context @context, back_context = context, @context
begin begin
yield back_context yield back_context
ensure ensure
@context = back_context @context = back_context
end end
end end
def signal_handle def signal_handle
unless @context.ignore_sigint? unless @context.ignore_sigint?
print "\nabort!\n" if @context.verbose? print "\nabort!\n" if @context.verbose?
exit exit
end end
case @signal_status case @signal_status
when :IN_INPUT when :IN_INPUT
print "^C\n" print "^C\n"
raise RubyLex::TerminateLineInput raise RubyLex::TerminateLineInput
when :IN_EVAL when :IN_EVAL
IRB.irb_abort(self) IRB.irb_abort(self)
when :IN_LOAD when :IN_LOAD
IRB.irb_abort(self, LoadAbort) IRB.irb_abort(self, LoadAbort)
when :IN_IRB when :IN_IRB
# ignore # ignore
else else
# ignore other cases as well # ignore other cases as well
end end
end end
@ -270,39 +270,39 @@ module IRB
signal_status_back = @signal_status signal_status_back = @signal_status
@signal_status = status @signal_status = status
begin begin
yield yield
ensure ensure
@signal_status = signal_status_back @signal_status = signal_status_back
end end
end end
def prompt(prompt, ltype, indent, line_no) def prompt(prompt, ltype, indent, line_no)
p = prompt.dup p = prompt.dup
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
case $2 case $2
when "N" when "N"
@context.irb_name @context.irb_name
when "m" when "m"
@context.main.to_s @context.main.to_s
when "M" when "M"
@context.main.inspect @context.main.inspect
when "l" when "l"
ltype ltype
when "i" when "i"
if $1 if $1
format("%" + $1 + "d", indent) format("%" + $1 + "d", indent)
else else
indent.to_s indent.to_s
end end
when "n" when "n"
if $1 if $1
format("%" + $1 + "d", line_no) format("%" + $1 + "d", line_no)
else else
line_no.to_s line_no.to_s
end end
when "%" when "%"
"%" "%"
end end
end end
p p
end end
@ -314,14 +314,14 @@ module IRB
def inspect def inspect
ary = [] ary = []
for iv in instance_variables for iv in instance_variables
case (iv = iv.to_s) case (iv = iv.to_s)
when "@signal_status" when "@signal_status"
ary.push format("%s=:%s", iv, @signal_status.id2name) ary.push format("%s=:%s", iv, @signal_status.id2name)
when "@context" when "@context"
ary.push format("%s=%s", iv, eval(iv).__to_s__) ary.push format("%s=%s", iv, eval(iv).__to_s__)
else else
ary.push format("%s=%s", iv, eval(iv)) ary.push format("%s=%s", iv, eval(iv))
end end
end end
format("#<%s: %s>", self.class, ary.join(", ")) format("#<%s: %s>", self.class, ary.join(", "))
end end
@ -335,16 +335,16 @@ module IRB
for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name} for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
case k case k
when :MAIN_CONTEXT, :__TMP__EHV__ when :MAIN_CONTEXT, :__TMP__EHV__
array.push format("CONF[:%s]=...myself...", k.id2name) array.push format("CONF[:%s]=...myself...", k.id2name)
when :PROMPT when :PROMPT
s = v.collect{ s = v.collect{
|kk, vv| |kk, vv|
ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"} ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
format(":%s=>{%s}", kk.id2name, ss.join(", ")) format(":%s=>{%s}", kk.id2name, ss.join(", "))
} }
array.push format("CONF[:%s]={%s}", k.id2name, s.join(", ")) array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
else else
array.push format("CONF[:%s]=%s", k.id2name, v.inspect) array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
end end
end end
array.join("\n") array.join("\n")

View File

@ -263,9 +263,9 @@ class Logger
alias sev_threshold level alias sev_threshold level
alias sev_threshold= level= alias sev_threshold= level=
# Returns +true+ iff the current severity level allows for the printing of # Returns +true+ iff the current severity level allows for the printing of
# +DEBUG+ messages. # +DEBUG+ messages.
def debug?; @level <= DEBUG; end def debug?; @level <= DEBUG; end
# Returns +true+ iff the current severity level allows for the printing of # Returns +true+ iff the current severity level allows for the printing of
# +INFO+ messages. # +INFO+ messages.
@ -312,7 +312,7 @@ class Logger
@logdev = nil @logdev = nil
if logdev if logdev
@logdev = LogDevice.new(logdev, :shift_age => shift_age, @logdev = LogDevice.new(logdev, :shift_age => shift_age,
:shift_size => shift_size) :shift_size => shift_size)
end end
end end
@ -376,7 +376,7 @@ class Logger
end end
@logdev.write( @logdev.write(
format_message(format_severity(severity), Time.now, progname, message)) format_message(format_severity(severity), Time.now, progname, message))
true true
end end
alias log add alias log add
@ -478,7 +478,7 @@ class Logger
@logdev.close if @logdev @logdev.close if @logdev
end end
private private
# Severity label for logging. (max 5 char) # Severity label for logging. (max 5 char)
SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY) SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY)
@ -507,7 +507,7 @@ private
msg2str(msg)] msg2str(msg)]
end end
private private
def format_datetime(time) def format_datetime(time)
if @datetime_format.nil? if @datetime_format.nil?
@ -523,7 +523,7 @@ private
msg msg
when ::Exception when ::Exception
"#{ msg.message } (#{ msg.class })\n" << "#{ msg.message } (#{ msg.class })\n" <<
(msg.backtrace || []).join("\n") (msg.backtrace || []).join("\n")
else else
msg.inspect msg.inspect
end end
@ -585,7 +585,7 @@ private
end end
end end
private private
def open_logfile(filename) def open_logfile(filename)
if (FileTest.exist?(filename)) if (FileTest.exist?(filename))
@ -791,7 +791,7 @@ private
@log.add(severity, message, @appname, &block) if @log @log.add(severity, message, @appname, &block) if @log
end end
private private
def run def run
# TODO: should be an NotImplementedError # TODO: should be an NotImplementedError

View File

@ -299,18 +299,18 @@ end
def xsystem command, opts = nil def xsystem command, opts = nil
varpat = /\$\((\w+)\)|\$\{(\w+)\}/ varpat = /\$\((\w+)\)|\$\{(\w+)\}/
if varpat =~ command if varpat =~ command
vars = Hash.new {|h, k| h[k] = ''; ENV[k]} vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
command = command.dup command = command.dup
nil while command.gsub!(varpat) {vars[$1||$2]} nil while command.gsub!(varpat) {vars[$1||$2]}
end end
Logging::open do Logging::open do
puts command.quote puts command.quote
if opts and opts[:werror] if opts and opts[:werror]
result = nil result = nil
Logging.postpone do |log| Logging.postpone do |log|
result = (system(command) and File.zero?(log.path)) result = (system(command) and File.zero?(log.path))
"" ""
end end
result result
else else
@ -337,12 +337,12 @@ def log_src(src)
Logging::message <<"EOM" Logging::message <<"EOM"
checked program was: checked program was:
/* begin */ /* begin */
EOM EOM
src.each_with_index {|line, no| Logging::message fmt, no+1, line} src.each_with_index {|line, no| Logging::message fmt, no+1, line}
Logging::message <<"EOM" Logging::message <<"EOM"
/* end */ /* end */
EOM EOM
end end
def create_tmpsrc(src) def create_tmpsrc(src)
@ -410,7 +410,7 @@ def cc_command(opt="")
'arch_hdrdir' => "#$arch_hdrdir", 'arch_hdrdir' => "#$arch_hdrdir",
'top_srcdir' => $top_srcdir.quote) 'top_srcdir' => $top_srcdir.quote)
RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}", RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
conf) conf)
end end
def cpp_command(outfile, opt="") def cpp_command(outfile, opt="")
@ -418,7 +418,7 @@ def cpp_command(outfile, opt="")
'arch_hdrdir' => "#$arch_hdrdir", 'arch_hdrdir' => "#$arch_hdrdir",
'top_srcdir' => $top_srcdir.quote) 'top_srcdir' => $top_srcdir.quote)
RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}", RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
conf) conf)
end end
def libpathflag(libpath=$DEFLIBPATH|$LIBPATH) def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
@ -547,7 +547,7 @@ end
def try_static_assert(expr, headers = nil, opt = "", &b) def try_static_assert(expr, headers = nil, opt = "", &b)
headers = cpp_include(headers) headers = cpp_include(headers)
try_compile(<<SRC, opt, &b) try_compile(<<SRC, opt, &b)
#{headers} #{headers}
/*top*/ /*top*/
int conftest_const[(#{expr}) ? 1 : -1]; int conftest_const[(#{expr}) ? 1 : -1];
SRC SRC
@ -616,15 +616,15 @@ def try_func(func, libs, headers = nil, &b)
decltype = proc {|x| "void ((*#{x})())"} decltype = proc {|x| "void ((*#{x})())"}
end end
try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b) or
#{headers} #{headers}
/*top*/ /*top*/
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int t() { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; } int t() { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; }
SRC SRC
call && try_link(<<"SRC", libs, &b) call && try_link(<<"SRC", libs, &b)
#{headers} #{headers}
/*top*/ /*top*/
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int t() { #{func}(); return 0; } int t() { #{func}(); return 0; }
SRC SRC
end end
@ -633,9 +633,9 @@ end
def try_var(var, headers = nil, &b) def try_var(var, headers = nil, &b)
headers = cpp_include(headers) headers = cpp_include(headers)
try_compile(<<"SRC", &b) try_compile(<<"SRC", &b)
#{headers} #{headers}
/*top*/ /*top*/
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; } int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
SRC SRC
end end
@ -659,18 +659,18 @@ def egrep_cpp(pat, src, opt = "", &b)
if Regexp === pat if Regexp === pat
puts(" ruby -ne 'print if #{pat.inspect}'") puts(" ruby -ne 'print if #{pat.inspect}'")
f.grep(pat) {|l| f.grep(pat) {|l|
puts "#{f.lineno}: #{l}" puts "#{f.lineno}: #{l}"
return true return true
} }
false false
else else
puts(" egrep '#{pat}'") puts(" egrep '#{pat}'")
begin begin
stdin = $stdin.dup stdin = $stdin.dup
$stdin.reopen(f) $stdin.reopen(f)
system("egrep", pat) system("egrep", pat)
ensure ensure
$stdin.reopen(stdin) $stdin.reopen(stdin)
end end
end end
end end
@ -867,11 +867,11 @@ def find_library(lib, func, *paths, &b)
libs = append_library($libs, lib) libs = append_library($libs, lib)
begin begin
until r = try_func(func, libs, &b) or paths.empty? until r = try_func(func, libs, &b) or paths.empty?
$LIBPATH = libpath | [paths.shift] $LIBPATH = libpath | [paths.shift]
end end
if r if r
$libs = libs $libs = libs
libpath = nil libpath = nil
end end
ensure ensure
$LIBPATH = libpath if libpath $LIBPATH = libpath if libpath
@ -999,9 +999,9 @@ end
def have_struct_member(type, member, headers = nil, &b) def have_struct_member(type, member, headers = nil, &b)
checking_for checking_message("#{type}.#{member}", headers) do checking_for checking_message("#{type}.#{member}", headers) do
if try_compile(<<"SRC", &b) if try_compile(<<"SRC", &b)
#{cpp_include(headers)} #{cpp_include(headers)}
/*top*/ /*top*/
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int s = (char *)&((#{type}*)0)->#{member} - (char *)0; int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
SRC SRC
$defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp)) $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
@ -1019,7 +1019,7 @@ end
# #
def try_type(type, headers = nil, opt = "", &b) def try_type(type, headers = nil, opt = "", &b)
if try_compile(<<"SRC", opt, &b) if try_compile(<<"SRC", opt, &b)
#{cpp_include(headers)} #{cpp_include(headers)}
/*top*/ /*top*/
typedef #{type} conftest_type; typedef #{type} conftest_type;
int conftestval[sizeof(conftest_type)?1:-1]; int conftestval[sizeof(conftest_type)?1:-1];
@ -1077,7 +1077,7 @@ end
def try_const(const, headers = nil, opt = "", &b) def try_const(const, headers = nil, opt = "", &b)
const, type = *const const, type = *const
if try_compile(<<"SRC", opt, &b) if try_compile(<<"SRC", opt, &b)
#{cpp_include(headers)} #{cpp_include(headers)}
/*top*/ /*top*/
typedef #{type || 'int'} conftest_type; typedef #{type || 'int'} conftest_type;
conftest_type conftestval = #{type ? '' : '(int)'}#{const}; conftest_type conftestval = #{type ? '' : '(int)'}#{const};
@ -1217,18 +1217,18 @@ def convertible_int(type, headers = nil, opts = nil, &b)
u = "unsigned " if signed > 0 u = "unsigned " if signed > 0
prelude << "extern rbcv_typedef_ foo();" prelude << "extern rbcv_typedef_ foo();"
compat = UNIVERSAL_INTS.find {|t| compat = UNIVERSAL_INTS.find {|t|
try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b) try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b)
} }
if compat if compat
macname ||= type.sub(/_(?=t\z)/, '').tr_cpp macname ||= type.sub(/_(?=t\z)/, '').tr_cpp
conv = (compat == "long long" ? "LL" : compat.upcase) conv = (compat == "long long" ? "LL" : compat.upcase)
compat = "#{u}#{compat}" compat = "#{u}#{compat}"
$defs.push(format("-DTYPEOF_%s=%s", type.tr_cpp, compat.quote)) $defs.push(format("-DTYPEOF_%s=%s", type.tr_cpp, compat.quote))
$defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv)) $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv))
conv = (u ? "U" : "") + conv conv = (u ? "U" : "") + conv
$defs.push(format("-D%s2NUM=%s2NUM", macname, conv)) $defs.push(format("-D%s2NUM=%s2NUM", macname, conv))
$defs.push(format("-DNUM2%s=NUM2%s", macname, conv)) $defs.push(format("-DNUM2%s=NUM2%s", macname, conv))
compat compat
end end
end end
end end
@ -1239,10 +1239,10 @@ end
# pointer. # pointer.
def scalar_ptr_type?(type, member = nil, headers = nil, &b) def scalar_ptr_type?(type, member = nil, headers = nil, &b)
try_compile(<<"SRC", &b) # pointer try_compile(<<"SRC", &b) # pointer
#{cpp_include(headers)} #{cpp_include(headers)}
/*top*/ /*top*/
volatile #{type} conftestval; volatile #{type} conftestval;
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));} int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
SRC SRC
end end
@ -1251,10 +1251,10 @@ end
# pointer. # pointer.
def scalar_type?(type, member = nil, headers = nil, &b) def scalar_type?(type, member = nil, headers = nil, &b)
try_compile(<<"SRC", &b) # pointer try_compile(<<"SRC", &b) # pointer
#{cpp_include(headers)} #{cpp_include(headers)}
/*top*/ /*top*/
volatile #{type} conftestval; volatile #{type} conftestval;
#{MAIN_DOES_NOTHING} #{MAIN_DOES_NOTHING}
int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));} int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
SRC SRC
end end
@ -1266,7 +1266,7 @@ def have_typeof?
$typeof = %w[__typeof__ typeof].find do |t| $typeof = %w[__typeof__ typeof].find do |t|
try_compile(<<SRC) try_compile(<<SRC)
int rbcv_foo; int rbcv_foo;
#{t}(rbcv_foo) rbcv_bar; #{t}(rbcv_foo) rbcv_bar;
SRC SRC
end end
end end
@ -1644,7 +1644,7 @@ ECHO1 = $(V:1=@:)
ECHO = $(ECHO1:0=@echo) ECHO = $(ECHO1:0=@echo)
#### Start of system configuration section. #### #### Start of system configuration section. ####
#{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk} #{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk}
srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2])}.quote} srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2])}.quote}
topdir = #{mkintpath($extmk ? CONFIG["topdir"] : $topdir).quote} topdir = #{mkintpath($extmk ? CONFIG["topdir"] : $topdir).quote}
hdrdir = #{mkintpath(CONFIG["hdrdir"]).quote} hdrdir = #{mkintpath(CONFIG["hdrdir"]).quote}
@ -1730,7 +1730,7 @@ preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
"!ifndef " + $1 + "\n" + "!ifndef " + $1 + "\n" +
$& + $& +
"!endif\n" "!endif\n"
end end
end end
end end
@ -2006,7 +2006,7 @@ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
mfile.print "#{dest}: #{f}\n\t@-$(MAKEDIRS) $(@D#{sep})\n" mfile.print "#{dest}: #{f}\n\t@-$(MAKEDIRS) $(@D#{sep})\n"
mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} $(@D#{sep})\n" mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} $(@D#{sep})\n"
if defined?($installed_list) if defined?($installed_list)
mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n" mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
end end
end end
else else
@ -2020,17 +2020,17 @@ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
files = install_files(mfile, i, nil, srcprefix) or next files = install_files(mfile, i, nil, srcprefix) or next
for dir, *files in files for dir, *files in files
unless dirs.include?(dir) unless dirs.include?(dir)
dirs << dir dirs << dir
mfile.print "pre-install-rb#{sfx}: #{dir}\n" mfile.print "pre-install-rb#{sfx}: #{dir}\n"
end end
for f in files for f in files
dest = "#{dir}/#{File.basename(f)}" dest = "#{dir}/#{File.basename(f)}"
mfile.print("install-rb#{sfx}: #{dest} #{dir}\n") mfile.print("install-rb#{sfx}: #{dest} #{dir}\n")
mfile.print("#{dest}: #{f}\n") mfile.print("#{dest}: #{f}\n")
mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D#{sep})\n") mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D#{sep})\n")
if defined?($installed_list) and !$extout if defined?($installed_list) and !$extout
mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n") mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
end end
if $extout if $extout
mfile.print("clean-rb#{sfx}::\n") mfile.print("clean-rb#{sfx}::\n")
mfile.print("\t@-$(RM) #{fseprepl[dest]}\n") mfile.print("\t@-$(RM) #{fseprepl[dest]}\n")

View File

@ -109,7 +109,7 @@ module MonitorMixin
# #
def wait_while def wait_while
while yield while yield
wait wait
end end
end end
@ -118,7 +118,7 @@ module MonitorMixin
# #
def wait_until def wait_until
until yield until yield
wait wait
end end
end end

View File

@ -1,26 +1,26 @@
# #
# mutex_m.rb - # mutex_m.rb -
# $Release Version: 3.0$ # $Release Version: 3.0$
# $Revision: 1.7 $ # $Revision: 1.7 $
# Original from mutex.rb # Original from mutex.rb
# by Keiju ISHITSUKA(keiju@ishitsuka.com) # by Keiju ISHITSUKA(keiju@ishitsuka.com)
# modified by matz # modified by matz
# patched by akira yamada # patched by akira yamada
# #
# -- # --
# Usage: # Usage:
# require "mutex_m.rb" # require "mutex_m.rb"
# obj = Object.new # obj = Object.new
# obj.extend Mutex_m # obj.extend Mutex_m
# ... # ...
# extended object can be handled like Mutex # extended object can be handled like Mutex
# or # or
# class Foo # class Foo
# include Mutex_m # include Mutex_m
# ... # ...
# end # end
# obj = Foo.new # obj = Foo.new
# this obj can be handled like Mutex # this obj can be handled like Mutex
# #
require 'thread' require 'thread'
@ -48,11 +48,11 @@ module Mutex_m
def mu_extended def mu_extended
unless (defined? locked? and unless (defined? locked? and
defined? lock and defined? lock and
defined? unlock and defined? unlock and
defined? try_lock and defined? try_lock and
defined? synchronize) defined? synchronize)
Mutex_m.define_aliases(singleton_class) Mutex_m.define_aliases(singleton_class)
end end
mu_initialize mu_initialize
end end

View File

@ -136,10 +136,10 @@ module Net
@sock = NullSocket.new @sock = NullSocket.new
@logged_in = false @logged_in = false
if host if host
connect(host) connect(host)
if user if user
login(user, passwd, acct) login(user, passwd, acct)
end end
end end
end end
@ -197,10 +197,10 @@ module Net
# else a TCPSocket is returned. # else a TCPSocket is returned.
def open_socket(host, port) def open_socket(host, port)
if defined? SOCKSSocket and ENV["SOCKS_SERVER"] if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
@passive = true @passive = true
return SOCKSSocket.open(host, port) return SOCKSSocket.open(host, port)
else else
return TCPSocket.open(host, port) return TCPSocket.open(host, port)
end end
end end
private :open_socket private :open_socket
@ -213,11 +213,11 @@ module Net
# #
def connect(host, port = FTP_PORT) def connect(host, port = FTP_PORT)
if @debug_mode if @debug_mode
print "connect: ", host, ", ", port, "\n" print "connect: ", host, ", ", port, "\n"
end end
synchronize do synchronize do
@sock = open_socket(host, port) @sock = open_socket(host, port)
voidresp voidresp
end end
end end
@ -226,10 +226,10 @@ module Net
# #
def set_socket(sock, get_greeting = true) def set_socket(sock, get_greeting = true)
synchronize do synchronize do
@sock = sock @sock = sock
if get_greeting if get_greeting
voidresp voidresp
end end
end end
end end
@ -237,9 +237,9 @@ module Net
# then the contents of the password are cleaned from the string using "*" # then the contents of the password are cleaned from the string using "*"
def sanitize(s) def sanitize(s)
if s =~ /^PASS /i if s =~ /^PASS /i
return s[0, 5] + "*" * (s.length - 5) return s[0, 5] + "*" * (s.length - 5)
else else
return s return s
end end
end end
private :sanitize private :sanitize
@ -248,7 +248,7 @@ module Net
# and writes it to the socket. # and writes it to the socket.
def putline(line) def putline(line)
if @debug_mode if @debug_mode
print "put: ", sanitize(line), "\n" print "put: ", sanitize(line), "\n"
end end
line = line + CRLF line = line + CRLF
@sock.write(line) @sock.write(line)
@ -261,7 +261,7 @@ module Net
line = @sock.readline # if get EOF, raise EOFError line = @sock.readline # if get EOF, raise EOFError
line.sub!(/(\r\n|\n|\r)\z/n, "") line.sub!(/(\r\n|\n|\r)\z/n, "")
if @debug_mode if @debug_mode
print "get: ", sanitize(line), "\n" print "get: ", sanitize(line), "\n"
end end
return line return line
end end
@ -272,11 +272,11 @@ module Net
line = getline line = getline
buff = line buff = line
if line[3] == ?- if line[3] == ?-
code = line[0, 3] code = line[0, 3]
begin begin
line = getline line = getline
buff << "\n" << line buff << "\n" << line
end until line[0, 3] == code and line[3] != ?- end until line[0, 3] == code and line[3] != ?-
end end
return buff << "\n" return buff << "\n"
end end
@ -290,13 +290,13 @@ module Net
@last_response_code = @last_response[0, 3] @last_response_code = @last_response[0, 3]
case @last_response_code case @last_response_code
when /\A[123]/ when /\A[123]/
return @last_response return @last_response
when /\A4/ when /\A4/
raise FTPTempError, @last_response raise FTPTempError, @last_response
when /\A5/ when /\A5/
raise FTPPermError, @last_response raise FTPPermError, @last_response
else else
raise FTPProtoError, @last_response raise FTPProtoError, @last_response
end end
end end
private :getresp private :getresp
@ -306,7 +306,7 @@ module Net
def voidresp def voidresp
resp = getresp resp = getresp
if resp[0] != ?2 if resp[0] != ?2
raise FTPReplyError, resp raise FTPReplyError, resp
end end
end end
private :voidresp private :voidresp
@ -316,8 +316,8 @@ module Net
# #
def sendcmd(cmd) def sendcmd(cmd)
synchronize do synchronize do
putline(cmd) putline(cmd)
return getresp return getresp
end end
end end
@ -326,8 +326,8 @@ module Net
# #
def voidcmd(cmd) def voidcmd(cmd)
synchronize do synchronize do
putline(cmd) putline(cmd)
voidresp voidresp
end end
end end
@ -335,11 +335,11 @@ module Net
def sendport(host, port) def sendport(host, port)
af = (@sock.peeraddr)[0] af = (@sock.peeraddr)[0]
if af == "AF_INET" if af == "AF_INET"
cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",") cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",")
elsif af == "AF_INET6" elsif af == "AF_INET6"
cmd = sprintf("EPRT |2|%s|%d|", host, port) cmd = sprintf("EPRT |2|%s|%d|", host, port)
else else
raise FTPProtoError, host raise FTPProtoError, host
end end
voidcmd(cmd) voidcmd(cmd)
end end
@ -360,10 +360,10 @@ module Net
# sends the appropriate command to enable a passive connection # sends the appropriate command to enable a passive connection
def makepasv def makepasv
if @sock.peeraddr[0] == "AF_INET" if @sock.peeraddr[0] == "AF_INET"
host, port = parse227(sendcmd("PASV")) host, port = parse227(sendcmd("PASV"))
else else
host, port = parse229(sendcmd("EPSV")) host, port = parse229(sendcmd("EPSV"))
# host, port = parse228(sendcmd("LPSV")) # host, port = parse228(sendcmd("LPSV"))
end end
return host, port return host, port
end end
@ -372,36 +372,36 @@ module Net
# Constructs a connection for transferring data # Constructs a connection for transferring data
def transfercmd(cmd, rest_offset = nil) def transfercmd(cmd, rest_offset = nil)
if @passive if @passive
host, port = makepasv host, port = makepasv
conn = open_socket(host, port) conn = open_socket(host, port)
if @resume and rest_offset if @resume and rest_offset
resp = sendcmd("REST " + rest_offset.to_s) resp = sendcmd("REST " + rest_offset.to_s)
if resp[0] != ?3 if resp[0] != ?3
raise FTPReplyError, resp raise FTPReplyError, resp
end end
end end
resp = sendcmd(cmd) resp = sendcmd(cmd)
# skip 2XX for some ftp servers # skip 2XX for some ftp servers
resp = getresp if resp[0] == ?2 resp = getresp if resp[0] == ?2
if resp[0] != ?1 if resp[0] != ?1
raise FTPReplyError, resp raise FTPReplyError, resp
end end
else else
sock = makeport sock = makeport
if @resume and rest_offset if @resume and rest_offset
resp = sendcmd("REST " + rest_offset.to_s) resp = sendcmd("REST " + rest_offset.to_s)
if resp[0] != ?3 if resp[0] != ?3
raise FTPReplyError, resp raise FTPReplyError, resp
end end
end end
resp = sendcmd(cmd) resp = sendcmd(cmd)
# skip 2XX for some ftp servers # skip 2XX for some ftp servers
resp = getresp if resp[0] == ?2 resp = getresp if resp[0] == ?2
if resp[0] != ?1 if resp[0] != ?1
raise FTPReplyError, resp raise FTPReplyError, resp
end end
conn = sock.accept conn = sock.accept
sock.close sock.close
end end
return conn return conn
end end
@ -417,23 +417,23 @@ module Net
# #
def login(user = "anonymous", passwd = nil, acct = nil) def login(user = "anonymous", passwd = nil, acct = nil)
if user == "anonymous" and passwd == nil if user == "anonymous" and passwd == nil
passwd = "anonymous@" passwd = "anonymous@"
end end
resp = "" resp = ""
synchronize do synchronize do
resp = sendcmd('USER ' + user) resp = sendcmd('USER ' + user)
if resp[0] == ?3 if resp[0] == ?3
raise FTPReplyError, resp if passwd.nil? raise FTPReplyError, resp if passwd.nil?
resp = sendcmd('PASS ' + passwd) resp = sendcmd('PASS ' + passwd)
end end
if resp[0] == ?3 if resp[0] == ?3
raise FTPReplyError, resp if acct.nil? raise FTPReplyError, resp if acct.nil?
resp = sendcmd('ACCT ' + acct) resp = sendcmd('ACCT ' + acct)
end end
end end
if resp[0] != ?2 if resp[0] != ?2
raise FTPReplyError, resp raise FTPReplyError, resp
end end
@welcome = resp @welcome = resp
send_type_command send_type_command
@ -448,7 +448,7 @@ module Net
# #
def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
synchronize do synchronize do
with_binary(true) do with_binary(true) do
conn = transfercmd(cmd, rest_offset) conn = transfercmd(cmd, rest_offset)
loop do loop do
data = conn.read(blocksize) data = conn.read(blocksize)
@ -469,7 +469,7 @@ module Net
# #
def retrlines(cmd) # :yield: line def retrlines(cmd) # :yield: line
synchronize do synchronize do
with_binary(false) do with_binary(false) do
conn = transfercmd(cmd) conn = transfercmd(cmd)
loop do loop do
line = conn.gets line = conn.gets
@ -493,7 +493,7 @@ module Net
file.seek(rest_offset, IO::SEEK_SET) file.seek(rest_offset, IO::SEEK_SET)
end end
synchronize do synchronize do
with_binary(true) do with_binary(true) do
conn = transfercmd(cmd) conn = transfercmd(cmd)
loop do loop do
buf = file.read(blocksize) buf = file.read(blocksize)
@ -522,7 +522,7 @@ module Net
# #
def storlines(cmd, file, &block) # :yield: line def storlines(cmd, file, &block) # :yield: line
synchronize do synchronize do
with_binary(false) do with_binary(false) do
conn = transfercmd(cmd) conn = transfercmd(cmd)
loop do loop do
buf = file.gets buf = file.gets
@ -553,7 +553,7 @@ module Net
# chunks. # chunks.
# #
def getbinaryfile(remotefile, localfile = File.basename(remotefile), def getbinaryfile(remotefile, localfile = File.basename(remotefile),
blocksize = DEFAULT_BLOCKSIZE) # :yield: data blocksize = DEFAULT_BLOCKSIZE) # :yield: data
result = nil result = nil
if localfile if localfile
if @resume if @resume
@ -567,15 +567,15 @@ module Net
result = "" result = ""
end end
begin begin
f.binmode if localfile f.binmode if localfile
retrbinary("RETR " + remotefile.to_s, blocksize, rest_offset) do |data| retrbinary("RETR " + remotefile.to_s, blocksize, rest_offset) do |data|
f.write(data) if localfile f.write(data) if localfile
yield(data) if block_given? yield(data) if block_given?
result.concat(data) if result result.concat(data) if result
end end
return result return result
ensure ensure
f.close if localfile f.close if localfile
end end
end end
@ -594,15 +594,15 @@ module Net
result = "" result = ""
end end
begin begin
retrlines("RETR " + remotefile) do |line, newline| retrlines("RETR " + remotefile) do |line, newline|
l = newline ? line + "\n" : line l = newline ? line + "\n" : line
f.print(l) if localfile f.print(l) if localfile
yield(line, newline) if block_given? yield(line, newline) if block_given?
result.concat(l) if result result.concat(l) if result
end end
return result return result
ensure ensure
f.close if localfile f.close if localfile
end end
end end
@ -611,11 +611,11 @@ module Net
# binary). See #gettextfile and #getbinaryfile. # binary). See #gettextfile and #getbinaryfile.
# #
def get(remotefile, localfile = File.basename(remotefile), def get(remotefile, localfile = File.basename(remotefile),
blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
if @binary if @binary
getbinaryfile(remotefile, localfile, blocksize, &block) getbinaryfile(remotefile, localfile, blocksize, &block)
else else
gettextfile(remotefile, localfile, &block) gettextfile(remotefile, localfile, &block)
end end
end end
@ -625,7 +625,7 @@ module Net
# data in +blocksize+ chunks. # data in +blocksize+ chunks.
# #
def putbinaryfile(localfile, remotefile = File.basename(localfile), def putbinaryfile(localfile, remotefile = File.basename(localfile),
blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
if @resume if @resume
begin begin
rest_offset = size(remotefile) rest_offset = size(remotefile)
@ -633,18 +633,18 @@ module Net
rest_offset = nil rest_offset = nil
end end
else else
rest_offset = nil rest_offset = nil
end end
f = open(localfile) f = open(localfile)
begin begin
f.binmode f.binmode
if rest_offset if rest_offset
storbinary("APPE " + remotefile, f, blocksize, rest_offset, &block) storbinary("APPE " + remotefile, f, blocksize, rest_offset, &block)
else else
storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block) storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
end end
ensure ensure
f.close f.close
end end
end end
@ -656,9 +656,9 @@ module Net
def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
f = open(localfile) f = open(localfile)
begin begin
storlines("STOR " + remotefile, f, &block) storlines("STOR " + remotefile, f, &block)
ensure ensure
f.close f.close
end end
end end
@ -667,11 +667,11 @@ module Net
# (text or binary). See #puttextfile and #putbinaryfile. # (text or binary). See #puttextfile and #putbinaryfile.
# #
def put(localfile, remotefile = File.basename(localfile), def put(localfile, remotefile = File.basename(localfile),
blocksize = DEFAULT_BLOCKSIZE, &block) blocksize = DEFAULT_BLOCKSIZE, &block)
if @binary if @binary
putbinaryfile(localfile, remotefile, blocksize, &block) putbinaryfile(localfile, remotefile, blocksize, &block)
else else
puttextfile(localfile, remotefile, &block) puttextfile(localfile, remotefile, &block)
end end
end end
@ -692,11 +692,11 @@ module Net
def nlst(dir = nil) def nlst(dir = nil)
cmd = "NLST" cmd = "NLST"
if dir if dir
cmd = cmd + " " + dir cmd = cmd + " " + dir
end end
files = [] files = []
retrlines(cmd) do |line| retrlines(cmd) do |line|
files.push(line) files.push(line)
end end
return files return files
end end
@ -708,16 +708,16 @@ module Net
def list(*args, &block) # :yield: line def list(*args, &block) # :yield: line
cmd = "LIST" cmd = "LIST"
args.each do |arg| args.each do |arg|
cmd = cmd + " " + arg.to_s cmd = cmd + " " + arg.to_s
end end
if block if block
retrlines(cmd, &block) retrlines(cmd, &block)
else else
lines = [] lines = []
retrlines(cmd) do |line| retrlines(cmd) do |line|
lines << line lines << line
end end
return lines return lines
end end
end end
alias ls list alias ls list
@ -729,7 +729,7 @@ module Net
def rename(fromname, toname) def rename(fromname, toname)
resp = sendcmd("RNFR " + fromname) resp = sendcmd("RNFR " + fromname)
if resp[0] != ?3 if resp[0] != ?3
raise FTPReplyError, resp raise FTPReplyError, resp
end end
voidcmd("RNTO " + toname) voidcmd("RNTO " + toname)
end end
@ -740,11 +740,11 @@ module Net
def delete(filename) def delete(filename)
resp = sendcmd("DELE " + filename) resp = sendcmd("DELE " + filename)
if resp[0, 3] == "250" if resp[0, 3] == "250"
return return
elsif resp[0] == ?5 elsif resp[0] == ?5
raise FTPPermError, resp raise FTPPermError, resp
else else
raise FTPReplyError, resp raise FTPReplyError, resp
end end
end end
@ -753,14 +753,14 @@ module Net
# #
def chdir(dirname) def chdir(dirname)
if dirname == ".." if dirname == ".."
begin begin
voidcmd("CDUP") voidcmd("CDUP")
return return
rescue FTPPermError => e rescue FTPPermError => e
if e.message[0, 3] != "500" if e.message[0, 3] != "500"
raise e raise e
end end
end end
end end
cmd = "CWD " + dirname cmd = "CWD " + dirname
voidcmd(cmd) voidcmd(cmd)
@ -781,15 +781,15 @@ module Net
MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ # :nodoc: MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ # :nodoc:
# #
# Returns the last modification time of the (remote) file. If +local+ is # Returns the last modification time of the (remote) file. If +local+ is
# +true+, it is returned as a local time, otherwise it's a UTC time. # +true+, it is returned as a local time, otherwise it's a UTC time.
# #
def mtime(filename, local = false) def mtime(filename, local = false)
str = mdtm(filename) str = mdtm(filename)
ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i} ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i}
return local ? Time.local(*ary) : Time.gm(*ary) return local ? Time.local(*ary) : Time.gm(*ary)
end end
# #
# Creates a remote directory. # Creates a remote directory.
@ -821,7 +821,7 @@ module Net
def system def system
resp = sendcmd("SYST") resp = sendcmd("SYST")
if resp[0, 3] != "215" if resp[0, 3] != "215"
raise FTPReplyError, resp raise FTPReplyError, resp
end end
return resp[4 .. -1] return resp[4 .. -1]
end end
@ -835,7 +835,7 @@ module Net
@sock.send(line, Socket::MSG_OOB) @sock.send(line, Socket::MSG_OOB)
resp = getmultiline resp = getmultiline
unless ["426", "226", "225"].include?(resp[0, 3]) unless ["426", "226", "225"].include?(resp[0, 3])
raise FTPProtoError, resp raise FTPProtoError, resp
end end
return resp return resp
end end
@ -856,7 +856,7 @@ module Net
def mdtm(filename) def mdtm(filename)
resp = sendcmd("MDTM " + filename) resp = sendcmd("MDTM " + filename)
if resp[0, 3] == "213" if resp[0, 3] == "213"
return resp[3 .. -1].strip return resp[3 .. -1].strip
end end
end end
@ -866,7 +866,7 @@ module Net
def help(arg = nil) def help(arg = nil)
cmd = "HELP" cmd = "HELP"
if arg if arg
cmd = cmd + " " + arg cmd = cmd + " " + arg
end end
sendcmd(cmd) sendcmd(cmd)
end end
@ -916,16 +916,16 @@ module Net
# Returns host and port. # Returns host and port.
def parse227(resp) def parse227(resp)
if resp[0, 3] != "227" if resp[0, 3] != "227"
raise FTPReplyError, resp raise FTPReplyError, resp
end end
left = resp.index("(") left = resp.index("(")
right = resp.index(")") right = resp.index(")")
if left == nil or right == nil if left == nil or right == nil
raise FTPProtoError, resp raise FTPProtoError, resp
end end
numbers = resp[left + 1 .. right - 1].split(",") numbers = resp[left + 1 .. right - 1].split(",")
if numbers.length != 6 if numbers.length != 6
raise FTPProtoError, resp raise FTPProtoError, resp
end end
host = numbers[0, 4].join(".") host = numbers[0, 4].join(".")
port = (numbers[4].to_i << 8) + numbers[5].to_i port = (numbers[4].to_i << 8) + numbers[5].to_i
@ -939,31 +939,31 @@ module Net
# Returns host and port. # Returns host and port.
def parse228(resp) def parse228(resp)
if resp[0, 3] != "228" if resp[0, 3] != "228"
raise FTPReplyError, resp raise FTPReplyError, resp
end end
left = resp.index("(") left = resp.index("(")
right = resp.index(")") right = resp.index(")")
if left == nil or right == nil if left == nil or right == nil
raise FTPProtoError, resp raise FTPProtoError, resp
end end
numbers = resp[left + 1 .. right - 1].split(",") numbers = resp[left + 1 .. right - 1].split(",")
if numbers[0] == "4" if numbers[0] == "4"
if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2" if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2"
raise FTPProtoError, resp raise FTPProtoError, resp
end end
host = numbers[2, 4].join(".") host = numbers[2, 4].join(".")
port = (numbers[7].to_i << 8) + numbers[8].to_i port = (numbers[7].to_i << 8) + numbers[8].to_i
elsif numbers[0] == "6" elsif numbers[0] == "6"
if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2" if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2"
raise FTPProtoError, resp raise FTPProtoError, resp
end end
v6 = ["", "", "", "", "", "", "", ""] v6 = ["", "", "", "", "", "", "", ""]
for i in 0 .. 7 for i in 0 .. 7
v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i, v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i,
numbers[(i * 2) + 3].to_i) numbers[(i * 2) + 3].to_i)
end end
host = v6[0, 8].join(":") host = v6[0, 8].join(":")
port = (numbers[19].to_i << 8) + numbers[20].to_i port = (numbers[19].to_i << 8) + numbers[20].to_i
end end
return host, port return host, port
end end
@ -975,16 +975,16 @@ module Net
# Returns host and port. # Returns host and port.
def parse229(resp) def parse229(resp)
if resp[0, 3] != "229" if resp[0, 3] != "229"
raise FTPReplyError, resp raise FTPReplyError, resp
end end
left = resp.index("(") left = resp.index("(")
right = resp.index(")") right = resp.index(")")
if left == nil or right == nil if left == nil or right == nil
raise FTPProtoError, resp raise FTPProtoError, resp
end end
numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1]) numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1])
if numbers.length != 4 if numbers.length != 4
raise FTPProtoError, resp raise FTPProtoError, resp
end end
port = numbers[3].to_i port = numbers[3].to_i
host = (@sock.peeraddr())[3] host = (@sock.peeraddr())[3]
@ -998,24 +998,24 @@ module Net
# Returns host and port. # Returns host and port.
def parse257(resp) def parse257(resp)
if resp[0, 3] != "257" if resp[0, 3] != "257"
raise FTPReplyError, resp raise FTPReplyError, resp
end end
if resp[3, 2] != ' "' if resp[3, 2] != ' "'
return "" return ""
end end
dirname = "" dirname = ""
i = 5 i = 5
n = resp.length n = resp.length
while i < n while i < n
c = resp[i, 1] c = resp[i, 1]
i = i + 1 i = i + 1
if c == '"' if c == '"'
if i > n or resp[i, 1] != '"' if i > n or resp[i, 1] != '"'
break break
end end
i = i + 1 i = i + 1
end end
dirname = dirname + c dirname = dirname + c
end end
return dirname return dirname
end end

View File

@ -1091,7 +1091,7 @@ module Net
when UntaggedResponse when UntaggedResponse
record_response(resp.name, resp.data) record_response(resp.name, resp.data)
if resp.data.instance_of?(ResponseText) && if resp.data.instance_of?(ResponseText) &&
(code = resp.data.code) (code = resp.data.code)
record_response(code.name, code.data) record_response(code.name, code.data)
end end
if resp.name == "BYE" && @logout_command_tag.nil? if resp.name == "BYE" && @logout_command_tag.nil?
@ -1550,7 +1550,7 @@ module Net
def ensure_nz_number(num) def ensure_nz_number(num)
if num < -1 || num == 0 || num >= 4294967296 if num < -1 || num == 0 || num >= 4294967296
msg = "nz_number must be non-zero unsigned 32-bit integer: " + msg = "nz_number must be non-zero unsigned 32-bit integer: " +
num.inspect num.inspect
raise DataFormatError, msg raise DataFormatError, msg
end end
end end
@ -2032,43 +2032,43 @@ module Net
T_TEXT = :TEXT T_TEXT = :TEXT
BEG_REGEXP = /\G(?:\ BEG_REGEXP = /\G(?:\
(?# 1: SPACE )( +)|\ (?# 1: SPACE )( +)|\
(?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\ (?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\
(?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\ (?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\
(?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+]+)|\ (?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+]+)|\
(?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ (?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\
(?# 6: LPAR )(\()|\ (?# 6: LPAR )(\()|\
(?# 7: RPAR )(\))|\ (?# 7: RPAR )(\))|\
(?# 8: BSLASH )(\\)|\ (?# 8: BSLASH )(\\)|\
(?# 9: STAR )(\*)|\ (?# 9: STAR )(\*)|\
(?# 10: LBRA )(\[)|\ (?# 10: LBRA )(\[)|\
(?# 11: RBRA )(\])|\ (?# 11: RBRA )(\])|\
(?# 12: LITERAL )\{(\d+)\}\r\n|\ (?# 12: LITERAL )\{(\d+)\}\r\n|\
(?# 13: PLUS )(\+)|\ (?# 13: PLUS )(\+)|\
(?# 14: PERCENT )(%)|\ (?# 14: PERCENT )(%)|\
(?# 15: CRLF )(\r\n)|\ (?# 15: CRLF )(\r\n)|\
(?# 16: EOF )(\z))/ni (?# 16: EOF )(\z))/ni
DATA_REGEXP = /\G(?:\ DATA_REGEXP = /\G(?:\
(?# 1: SPACE )( )|\ (?# 1: SPACE )( )|\
(?# 2: NIL )(NIL)|\ (?# 2: NIL )(NIL)|\
(?# 3: NUMBER )(\d+)|\ (?# 3: NUMBER )(\d+)|\
(?# 4: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ (?# 4: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\
(?# 5: LITERAL )\{(\d+)\}\r\n|\ (?# 5: LITERAL )\{(\d+)\}\r\n|\
(?# 6: LPAR )(\()|\ (?# 6: LPAR )(\()|\
(?# 7: RPAR )(\)))/ni (?# 7: RPAR )(\)))/ni
TEXT_REGEXP = /\G(?:\ TEXT_REGEXP = /\G(?:\
(?# 1: TEXT )([^\x00\r\n]*))/ni (?# 1: TEXT )([^\x00\r\n]*))/ni
RTEXT_REGEXP = /\G(?:\ RTEXT_REGEXP = /\G(?:\
(?# 1: LBRA )(\[)|\ (?# 1: LBRA )(\[)|\
(?# 2: TEXT )([^\x00\r\n]*))/ni (?# 2: TEXT )([^\x00\r\n]*))/ni
CTEXT_REGEXP = /\G(?:\ CTEXT_REGEXP = /\G(?:\
(?# 1: TEXT )([^\x00\r\n\]]*))/ni (?# 1: TEXT )([^\x00\r\n\]]*))/ni
Token = Struct.new(:symbol, :value) Token = Struct.new(:symbol, :value)
def response def response
token = lookahead token = lookahead
@ -2932,11 +2932,11 @@ module Net
end end
ADDRESS_REGEXP = /\G\ ADDRESS_REGEXP = /\G\
(?# 1: NAME )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 1: NAME )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
(?# 2: ROUTE )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 2: ROUTE )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
(?# 3: MAILBOX )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 3: MAILBOX )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
(?# 4: HOST )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)")\ (?# 4: HOST )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)")\
\)/ni \)/ni
def address def address
match(T_LPAR) match(T_LPAR)
@ -2965,62 +2965,62 @@ module Net
return Address.new(name, route, mailbox, host) return Address.new(name, route, mailbox, host)
end end
# def flag_list # def flag_list
# result = [] # result = []
# match(T_LPAR) # match(T_LPAR)
# while true # while true
# token = lookahead # token = lookahead
# case token.symbol # case token.symbol
# when T_RPAR # when T_RPAR
# shift_token # shift_token
# break # break
# when T_SPACE # when T_SPACE
# shift_token # shift_token
# end # end
# result.push(flag) # result.push(flag)
# end # end
# return result # return result
# end # end
# def flag # def flag
# token = lookahead # token = lookahead
# if token.symbol == T_BSLASH # if token.symbol == T_BSLASH
# shift_token # shift_token
# token = lookahead # token = lookahead
# if token.symbol == T_STAR # if token.symbol == T_STAR
# shift_token # shift_token
# return token.value.intern # return token.value.intern
# else # else
# return atom.intern # return atom.intern
# end # end
# else # else
# return atom # return atom
# end # end
# end # end
FLAG_REGEXP = /\ FLAG_REGEXP = /\
(?# FLAG )\\([^\x80-\xff(){ \x00-\x1f\x7f%"\\]+)|\ (?# FLAG )\\([^\x80-\xff(){ \x00-\x1f\x7f%"\\]+)|\
(?# ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\]+)/n (?# ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\]+)/n
def flag_list def flag_list
if @str.index(/\(([^)]*)\)/ni, @pos) if @str.index(/\(([^)]*)\)/ni, @pos)
@pos = $~.end(0) @pos = $~.end(0)
return $1.scan(FLAG_REGEXP).collect { |flag, atom| return $1.scan(FLAG_REGEXP).collect { |flag, atom|
if atom if atom
atom atom
else else
symbol = flag.capitalize.untaint.intern symbol = flag.capitalize.untaint.intern
@flag_symbols[symbol] = true @flag_symbols[symbol] = true
if @flag_symbols.length > IMAP.max_flag_count if @flag_symbols.length > IMAP.max_flag_count
raise FlagCountError, "number of flag symbols exceeded" raise FlagCountError, "number of flag symbols exceeded"
end
symbol
end
}
else
parse_error("invalid flag list")
end end
symbol
end end
}
else
parse_error("invalid flag list")
end
end
def nstring def nstring
token = lookahead token = lookahead
@ -3347,73 +3347,73 @@ module Net
# #authenticate(). # #authenticate().
class DigestMD5Authenticator class DigestMD5Authenticator
def process(challenge) def process(challenge)
case @stage case @stage
when STAGE_ONE when STAGE_ONE
@stage = STAGE_TWO @stage = STAGE_TWO
sparams = {} sparams = {}
c = StringScanner.new(challenge) c = StringScanner.new(challenge)
while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/) while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/)
k, v = c[1], c[2] k, v = c[1], c[2]
if v =~ /^"(.*)"$/ if v =~ /^"(.*)"$/
v = $1 v = $1
if v =~ /,/ if v =~ /,/
v = v.split(',') v = v.split(',')
end end
end end
sparams[k] = v sparams[k] = v
end end
raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0 raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0
raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth") raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth")
response = { response = {
:nonce => sparams['nonce'], :nonce => sparams['nonce'],
:username => @user, :username => @user,
:realm => sparams['realm'], :realm => sparams['realm'],
:cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]), :cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]),
:'digest-uri' => 'imap/' + sparams['realm'], :'digest-uri' => 'imap/' + sparams['realm'],
:qop => 'auth', :qop => 'auth',
:maxbuf => 65535, :maxbuf => 65535,
:nc => "%08d" % nc(sparams['nonce']), :nc => "%08d" % nc(sparams['nonce']),
:charset => sparams['charset'], :charset => sparams['charset'],
} }
response[:authzid] = @authname unless @authname.nil? response[:authzid] = @authname unless @authname.nil?
# now, the real thing # now, the real thing
a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') ) a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') )
a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':') a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':')
a1 << ':' + response[:authzid] unless response[:authzid].nil? a1 << ':' + response[:authzid] unless response[:authzid].nil?
a2 = "AUTHENTICATE:" + response[:'digest-uri'] a2 = "AUTHENTICATE:" + response[:'digest-uri']
a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/ a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/
response[:response] = Digest::MD5.hexdigest( response[:response] = Digest::MD5.hexdigest(
[ [
Digest::MD5.hexdigest(a1), Digest::MD5.hexdigest(a1),
response.values_at(:nonce, :nc, :cnonce, :qop), response.values_at(:nonce, :nc, :cnonce, :qop),
Digest::MD5.hexdigest(a2) Digest::MD5.hexdigest(a2)
].join(':') ].join(':')
) )
return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',') return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',')
when STAGE_TWO when STAGE_TWO
@stage = nil @stage = nil
# if at the second stage, return an empty string # if at the second stage, return an empty string
if challenge =~ /rspauth=/ if challenge =~ /rspauth=/
return '' return ''
else else
raise ResponseParseError, challenge raise ResponseParseError, challenge
end end
else else
raise ResponseParseError, challenge raise ResponseParseError, challenge
end end
end end
def initialize(user, password, authname = nil) def initialize(user, password, authname = nil)
@user, @password, @authname = user, password, authname @user, @password, @authname = user, password, authname
@nc, @stage = {}, STAGE_ONE @nc, @stage = {}, STAGE_ONE
end end
private private
@ -3422,23 +3422,23 @@ module Net
STAGE_TWO = :stage_two STAGE_TWO = :stage_two
def nc(nonce) def nc(nonce)
if @nc.has_key? nonce if @nc.has_key? nonce
@nc[nonce] = @nc[nonce] + 1 @nc[nonce] = @nc[nonce] + 1
else else
@nc[nonce] = 1 @nc[nonce] = 1
end end
return @nc[nonce] return @nc[nonce]
end end
# some responses need quoting # some responses need quoting
def qdval(k, v) def qdval(k, v)
return if k.nil? or v.nil? return if k.nil? or v.nil?
if %w"username authzid realm nonce cnonce digest-uri qop".include? k if %w"username authzid realm nonce cnonce digest-uri qop".include? k
v.gsub!(/([\\"])/, "\\\1") v.gsub!(/([\\"])/, "\\\1")
return '%s="%s"' % [k, v] return '%s="%s"' % [k, v]
else else
return '%s=%s' % [k, v] return '%s=%s' % [k, v]
end end
end end
end end
add_authenticator "DIGEST-MD5", DigestMD5Authenticator add_authenticator "DIGEST-MD5", DigestMD5Authenticator
@ -3514,7 +3514,7 @@ usage: #{$0} [options] <host>
--auth=AUTH specifies auth type --auth=AUTH specifies auth type
--starttls use starttls --starttls use starttls
--ssl use ssl --ssl use ssl
EOF EOF
end end
begin begin
@ -3649,7 +3649,7 @@ summary display summary
fetch [msgno] display message fetch [msgno] display message
logout logout logout logout
help, ? display help message help, ? display help message
EOF EOF
else else
print "unknown command: ", cmd, "\n" print "unknown command: ", cmd, "\n"
end end

View File

@ -433,18 +433,18 @@ module Net
# combine CR+NULL into CR # combine CR+NULL into CR
string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"] string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
# combine EOL into "\n" # combine EOL into "\n"
string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"] string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
# remove NULL # remove NULL
string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"] string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"]
string.gsub(/#{IAC}( string.gsub(/#{IAC}(
[#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
[#{DO}#{DONT}#{WILL}#{WONT}] [#{DO}#{DONT}#{WILL}#{WONT}]
[#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]|
#{SB}[^#{IAC}]*#{IAC}#{SE} #{SB}[^#{IAC}]*#{IAC}#{SE}
)/xno) do )/xno) do
if IAC == $1 # handle escaped IAC characters if IAC == $1 # handle escaped IAC characters
IAC IAC
elsif AYT == $1 # respond to "IAC AYT" (are you there) elsif AYT == $1 # respond to "IAC AYT" (are you there)
@ -464,301 +464,301 @@ module Net
elsif WILL[0] == $1[0] # respond to "IAC WILL x" elsif WILL[0] == $1[0] # respond to "IAC WILL x"
if OPT_BINARY[0] == $1[1] if OPT_BINARY[0] == $1[1]
self.write(IAC + DO + OPT_BINARY) self.write(IAC + DO + OPT_BINARY)
elsif OPT_ECHO[0] == $1[1] elsif OPT_ECHO[0] == $1[1]
self.write(IAC + DO + OPT_ECHO) self.write(IAC + DO + OPT_ECHO)
elsif OPT_SGA[0] == $1[1] elsif OPT_SGA[0] == $1[1]
@telnet_option["SGA"] = true @telnet_option["SGA"] = true
self.write(IAC + DO + OPT_SGA) self.write(IAC + DO + OPT_SGA)
else else
self.write(IAC + DONT + $1[1..1]) self.write(IAC + DONT + $1[1..1])
end end
'' ''
elsif WONT[0] == $1[0] # respond to "IAC WON'T x" elsif WONT[0] == $1[0] # respond to "IAC WON'T x"
if OPT_ECHO[0] == $1[1] if OPT_ECHO[0] == $1[1]
self.write(IAC + DONT + OPT_ECHO) self.write(IAC + DONT + OPT_ECHO)
elsif OPT_SGA[0] == $1[1] elsif OPT_SGA[0] == $1[1]
@telnet_option["SGA"] = false @telnet_option["SGA"] = false
self.write(IAC + DONT + OPT_SGA) self.write(IAC + DONT + OPT_SGA)
else else
self.write(IAC + DONT + $1[1..1]) self.write(IAC + DONT + $1[1..1])
end end
'' ''
else else
'' ''
end end
end
end # preprocess
# Read data from the host until a certain sequence is matched.
#
# If a block is given, the received data will be yielded as it
# is read in (not necessarily all in one go), or nil if EOF
# occurs before any data is received. Whether a block is given
# or not, all data read will be returned in a single string, or again
# nil if EOF occurs before any data is received. Note that
# received data includes the matched sequence we were looking for.
#
# +options+ can be either a regular expression or a hash of options.
# If a regular expression, this specifies the data to wait for.
# If a hash, this can specify the following options:
#
# Match:: a regular expression, specifying the data to wait for.
# Prompt:: as for Match; used only if Match is not specified.
# String:: as for Match, except a string that will be converted
# into a regular expression. Used only if Match and
# Prompt are not specified.
# Timeout:: the number of seconds to wait for data from the host
# before raising a TimeoutError. If set to false,
# no timeout will occur. If not specified, the
# Timeout option value specified when this instance
# was created will be used, or, failing that, the
# default value of 10 seconds.
# Waittime:: the number of seconds to wait after matching against
# the input data to see if more data arrives. If more
# data arrives within this time, we will judge ourselves
# not to have matched successfully, and will continue
# trying to match. If not specified, the Waittime option
# value specified when this instance was created will be
# used, or, failing that, the default value of 0 seconds,
# which means not to wait for more input.
# FailEOF:: if true, when the remote end closes the connection then an
# EOFError will be raised. Otherwise, defaults to the old
# behaviour that the function will return whatever data
# has been received already, or nil if nothing was received.
#
def waitfor(options) # :yield: recvdata
time_out = @options["Timeout"]
waittime = @options["Waittime"]
fail_eof = @options["FailEOF"]
if options.kind_of?(Hash)
prompt = if options.has_key?("Match")
options["Match"]
elsif options.has_key?("Prompt")
options["Prompt"]
elsif options.has_key?("String")
Regexp.new( Regexp.quote(options["String"]) )
end
time_out = options["Timeout"] if options.has_key?("Timeout")
waittime = options["Waittime"] if options.has_key?("Waittime")
fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
else
prompt = options
end
if time_out == false
time_out = nil
end
line = ''
buf = ''
rest = ''
until(prompt === line and not IO::select([@sock], nil, nil, waittime))
unless IO::select([@sock], nil, nil, time_out)
raise TimeoutError, "timed out while waiting for more data"
end
begin
c = @sock.readpartial(1024 * 1024)
@dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
if @options["Telnetmode"]
c = rest + c
if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) <
Integer(c.rindex(/#{IAC}#{SB}/no) || 0)
buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)])
rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1]
elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) ||
c.rindex(/\r\z/no)
buf = preprocess(c[0 ... pt])
rest = c[pt .. -1]
else
buf = preprocess(c)
rest = ''
end end
else end # preprocess
# Not Telnetmode.
# # Read data from the host until a certain sequence is matched.
# We cannot use preprocess() on this data, because that #
# method makes some Telnetmode-specific assumptions. # If a block is given, the received data will be yielded as it
buf = rest + c # is read in (not necessarily all in one go), or nil if EOF
rest = '' # occurs before any data is received. Whether a block is given
unless @options["Binmode"] # or not, all data read will be returned in a single string, or again
if pt = buf.rindex(/\r\z/no) # nil if EOF occurs before any data is received. Note that
buf = buf[0 ... pt] # received data includes the matched sequence we were looking for.
rest = buf[pt .. -1] #
end # +options+ can be either a regular expression or a hash of options.
buf.gsub!(/#{EOL}/no, "\n") # If a regular expression, this specifies the data to wait for.
end # If a hash, this can specify the following options:
#
# Match:: a regular expression, specifying the data to wait for.
# Prompt:: as for Match; used only if Match is not specified.
# String:: as for Match, except a string that will be converted
# into a regular expression. Used only if Match and
# Prompt are not specified.
# Timeout:: the number of seconds to wait for data from the host
# before raising a TimeoutError. If set to false,
# no timeout will occur. If not specified, the
# Timeout option value specified when this instance
# was created will be used, or, failing that, the
# default value of 10 seconds.
# Waittime:: the number of seconds to wait after matching against
# the input data to see if more data arrives. If more
# data arrives within this time, we will judge ourselves
# not to have matched successfully, and will continue
# trying to match. If not specified, the Waittime option
# value specified when this instance was created will be
# used, or, failing that, the default value of 0 seconds,
# which means not to wait for more input.
# FailEOF:: if true, when the remote end closes the connection then an
# EOFError will be raised. Otherwise, defaults to the old
# behaviour that the function will return whatever data
# has been received already, or nil if nothing was received.
#
def waitfor(options) # :yield: recvdata
time_out = @options["Timeout"]
waittime = @options["Waittime"]
fail_eof = @options["FailEOF"]
if options.kind_of?(Hash)
prompt = if options.has_key?("Match")
options["Match"]
elsif options.has_key?("Prompt")
options["Prompt"]
elsif options.has_key?("String")
Regexp.new( Regexp.quote(options["String"]) )
end
time_out = options["Timeout"] if options.has_key?("Timeout")
waittime = options["Waittime"] if options.has_key?("Waittime")
fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
else
prompt = options
end
if time_out == false
time_out = nil
end
line = ''
buf = ''
rest = ''
until(prompt === line and not IO::select([@sock], nil, nil, waittime))
unless IO::select([@sock], nil, nil, time_out)
raise TimeoutError, "timed out while waiting for more data"
end
begin
c = @sock.readpartial(1024 * 1024)
@dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
if @options["Telnetmode"]
c = rest + c
if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) <
Integer(c.rindex(/#{IAC}#{SB}/no) || 0)
buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)])
rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1]
elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) ||
c.rindex(/\r\z/no)
buf = preprocess(c[0 ... pt])
rest = c[pt .. -1]
else
buf = preprocess(c)
rest = ''
end
else
# Not Telnetmode.
#
# We cannot use preprocess() on this data, because that
# method makes some Telnetmode-specific assumptions.
buf = rest + c
rest = ''
unless @options["Binmode"]
if pt = buf.rindex(/\r\z/no)
buf = buf[0 ... pt]
rest = buf[pt .. -1]
end
buf.gsub!(/#{EOL}/no, "\n")
end
end
@log.print(buf) if @options.has_key?("Output_log")
line += buf
yield buf if block_given?
rescue EOFError # End of file reached
raise if fail_eof
if line == ''
line = nil
yield nil if block_given?
end
break
end
end
line
end end
@log.print(buf) if @options.has_key?("Output_log")
line += buf # Write +string+ to the host.
yield buf if block_given? #
rescue EOFError # End of file reached # Does not perform any conversions on +string+. Will log +string+ to the
raise if fail_eof # dumplog, if the Dump_log option is set.
if line == '' def write(string)
line = nil length = string.length
yield nil if block_given? while 0 < length
IO::select(nil, [@sock])
@dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log")
length -= @sock.syswrite(string[-length..-1])
end
end end
break
end
end
line
end
# Write +string+ to the host. # Sends a string to the host.
# #
# Does not perform any conversions on +string+. Will log +string+ to the # This does _not_ automatically append a newline to the string. Embedded
# dumplog, if the Dump_log option is set. # newlines may be converted and telnet command sequences escaped
def write(string) # depending upon the values of telnetmode, binmode, and telnet options
length = string.length # set by the host.
while 0 < length def print(string)
IO::select(nil, [@sock]) string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
@dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log")
length -= @sock.syswrite(string[-length..-1])
end
end
# Sends a string to the host. if @options["Binmode"]
# self.write(string)
# This does _not_ automatically append a newline to the string. Embedded else
# newlines may be converted and telnet command sequences escaped if @telnet_option["BINARY"] and @telnet_option["SGA"]
# depending upon the values of telnetmode, binmode, and telnet options # IAC WILL SGA IAC DO BIN send EOL --> CR
# set by the host. self.write(string.gsub(/\n/n, CR))
def print(string) elsif @telnet_option["SGA"]
string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"] # IAC WILL SGA send EOL --> CR+NULL
self.write(string.gsub(/\n/n, CR + NULL))
else
# NONE send EOL --> CR+LF
self.write(string.gsub(/\n/n, EOL))
end
end
end
if @options["Binmode"] # Sends a string to the host.
self.write(string) #
else # Same as #print(), but appends a newline to the string.
if @telnet_option["BINARY"] and @telnet_option["SGA"] def puts(string)
# IAC WILL SGA IAC DO BIN send EOL --> CR self.print(string + "\n")
self.write(string.gsub(/\n/n, CR)) end
elsif @telnet_option["SGA"]
# IAC WILL SGA send EOL --> CR+NULL
self.write(string.gsub(/\n/n, CR + NULL))
else
# NONE send EOL --> CR+LF
self.write(string.gsub(/\n/n, EOL))
end
end
end
# Sends a string to the host. # Send a command to the host.
# #
# Same as #print(), but appends a newline to the string. # More exactly, sends a string to the host, and reads in all received
def puts(string) # data until is sees the prompt or other matched sequence.
self.print(string + "\n") #
end # If a block is given, the received data will be yielded to it as
# it is read in. Whether a block is given or not, the received data
# will be return as a string. Note that the received data includes
# the prompt and in most cases the host's echo of our command.
#
# +options+ is either a String, specified the string or command to
# send to the host; or it is a hash of options. If a hash, the
# following options can be specified:
#
# String:: the command or other string to send to the host.
# Match:: a regular expression, the sequence to look for in
# the received data before returning. If not specified,
# the Prompt option value specified when this instance
# was created will be used, or, failing that, the default
# prompt of /[$%#>] \z/n.
# Timeout:: the seconds to wait for data from the host before raising
# a Timeout error. If not specified, the Timeout option
# value specified when this instance was created will be
# used, or, failing that, the default value of 10 seconds.
#
# The command or other string will have the newline sequence appended
# to it.
def cmd(options) # :yield: recvdata
match = @options["Prompt"]
time_out = @options["Timeout"]
fail_eof = @options["FailEOF"]
# Send a command to the host. if options.kind_of?(Hash)
# string = options["String"]
# More exactly, sends a string to the host, and reads in all received match = options["Match"] if options.has_key?("Match")
# data until is sees the prompt or other matched sequence. time_out = options["Timeout"] if options.has_key?("Timeout")
# fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
# If a block is given, the received data will be yielded to it as else
# it is read in. Whether a block is given or not, the received data string = options
# will be return as a string. Note that the received data includes end
# the prompt and in most cases the host's echo of our command.
#
# +options+ is either a String, specified the string or command to
# send to the host; or it is a hash of options. If a hash, the
# following options can be specified:
#
# String:: the command or other string to send to the host.
# Match:: a regular expression, the sequence to look for in
# the received data before returning. If not specified,
# the Prompt option value specified when this instance
# was created will be used, or, failing that, the default
# prompt of /[$%#>] \z/n.
# Timeout:: the seconds to wait for data from the host before raising
# a Timeout error. If not specified, the Timeout option
# value specified when this instance was created will be
# used, or, failing that, the default value of 10 seconds.
#
# The command or other string will have the newline sequence appended
# to it.
def cmd(options) # :yield: recvdata
match = @options["Prompt"]
time_out = @options["Timeout"]
fail_eof = @options["FailEOF"]
if options.kind_of?(Hash) self.puts(string)
string = options["String"] if block_given?
match = options["Match"] if options.has_key?("Match") waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c }
time_out = options["Timeout"] if options.has_key?("Timeout") else
fail_eof = options["FailEOF"] if options.has_key?("FailEOF") waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof})
else end
string = options end
end
self.puts(string) # Login to the host with a given username and password.
if block_given? #
waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c } # The username and password can either be provided as two string
else # arguments in that order, or as a hash with keys "Name" and
waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}) # "Password".
end #
end # This method looks for the strings "login" and "Password" from the
# host to determine when to send the username and password. If the
# login sequence does not follow this pattern (for instance, you
# are connecting to a service other than telnet), you will need
# to handle login yourself.
#
# The password can be omitted, either by only
# provided one String argument, which will be used as the username,
# or by providing a has that has no "Password" key. In this case,
# the method will not look for the "Password:" prompt; if it is
# sent, it will have to be dealt with by later calls.
#
# The method returns all data received during the login process from
# the host, including the echoed username but not the password (which
# the host should not echo). If a block is passed in, this received
# data is also yielded to the block as it is received.
def login(options, password = nil) # :yield: recvdata
login_prompt = /[Ll]ogin[: ]*\z/n
password_prompt = /[Pp]ass(?:word|phrase)[: ]*\z/n
if options.kind_of?(Hash)
username = options["Name"]
password = options["Password"]
login_prompt = options["LoginPrompt"] if options["LoginPrompt"]
password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"]
else
username = options
end
# Login to the host with a given username and password. if block_given?
# line = waitfor(login_prompt){|c| yield c }
# The username and password can either be provided as two string if password
# arguments in that order, or as a hash with keys "Name" and line += cmd({"String" => username,
# "Password". "Match" => password_prompt}){|c| yield c }
# line += cmd(password){|c| yield c }
# This method looks for the strings "login" and "Password" from the else
# host to determine when to send the username and password. If the line += cmd(username){|c| yield c }
# login sequence does not follow this pattern (for instance, you end
# are connecting to a service other than telnet), you will need else
# to handle login yourself. line = waitfor(login_prompt)
# if password
# The password can be omitted, either by only line += cmd({"String" => username,
# provided one String argument, which will be used as the username, "Match" => password_prompt})
# or by providing a has that has no "Password" key. In this case, line += cmd(password)
# the method will not look for the "Password:" prompt; if it is else
# sent, it will have to be dealt with by later calls. line += cmd(username)
# end
# The method returns all data received during the login process from end
# the host, including the echoed username but not the password (which line
# the host should not echo). If a block is passed in, this received end
# data is also yielded to the block as it is received.
def login(options, password = nil) # :yield: recvdata
login_prompt = /[Ll]ogin[: ]*\z/n
password_prompt = /[Pp]ass(?:word|phrase)[: ]*\z/n
if options.kind_of?(Hash)
username = options["Name"]
password = options["Password"]
login_prompt = options["LoginPrompt"] if options["LoginPrompt"]
password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"]
else
username = options
end
if block_given? # Closes the connection
line = waitfor(login_prompt){|c| yield c } def close
if password @sock.close
line += cmd({"String" => username, end
"Match" => password_prompt}){|c| yield c }
line += cmd(password){|c| yield c }
else
line += cmd(username){|c| yield c }
end
else
line = waitfor(login_prompt)
if password
line += cmd({"String" => username,
"Match" => password_prompt})
line += cmd(password)
else
line += cmd(username)
end
end
line
end
# Closes the connection end # class Telnet
def close end # module Net
@sock.close
end
end # class Telnet
end # module Net

View File

@ -205,9 +205,9 @@ module Open3
result = [*parent_io, wait_thr] result = [*parent_io, wait_thr]
if defined? yield if defined? yield
begin begin
return yield(*result) return yield(*result)
ensure ensure
parent_io.each{|io| io.close unless io.closed?} parent_io.each{|io| io.close unless io.closed?}
wait_thr.join wait_thr.join
end end
end end
@ -700,9 +700,9 @@ module Open3
child_io.each {|io| io.close } child_io.each {|io| io.close }
if defined? yield if defined? yield
begin begin
return yield(*result) return yield(*result)
ensure ensure
parent_io.each{|io| io.close unless io.closed?} parent_io.each{|io| io.close unless io.closed?}
wait_thrs.each {|t| t.join } wait_thrs.each {|t| t.join }
end end
end end

View File

@ -99,397 +99,397 @@ class Prime
def method_added(method) # :nodoc: def method_added(method) # :nodoc:
(class<< self;self;end).def_delegator :instance, method (class<< self;self;end).def_delegator :instance, method
end
end
# Iterates the given block over all prime numbers.
#
# == Parameters
# +ubound+::
# Optional. An arbitrary positive number.
# The upper bound of enumeration. The method enumerates
# prime numbers infinitely if +ubound+ is nil.
# +generator+::
# Optional. An implementation of pseudo-prime generator.
#
# == Return value
# An evaluated value of the given block at the last time.
# Or an enumerator which is compatible to an +Enumerator+
# if no block given.
#
# == Description
# Calls +block+ once for each prime number, passing the prime as
# a parameter.
#
# +ubound+::
# Upper bound of prime numbers. The iterator stops after
# yields all prime numbers p <= +ubound+.
#
# == Note
# +Prime+.+new+ returns a object extended by +Prime+::+OldCompatibility+
# in order to compatibility to Ruby 1.8, and +Prime+#each is overwritten
# by +Prime+::+OldCompatibility+#+each+.
#
# +Prime+.+new+ is now obsolete. Use +Prime+.+instance+.+each+ or simply
# +Prime+.+each+.
def each(ubound = nil, generator = EratosthenesGenerator.new, &block)
generator.upper_bound = ubound
generator.each(&block)
end
# Returns true if +value+ is prime, false for a composite.
#
# == Parameters
# +value+:: an arbitrary integer to be checked.
# +generator+:: optional. A pseudo-prime generator.
def prime?(value, generator = Prime::Generator23.new)
value = -value if value < 0
return false if value < 2
for num in generator
q,r = value.divmod num
return true if q < num
return false if r == 0
end
end
# Re-composes a prime factorization and returns the product.
#
# == Parameters
# +pd+:: Array of pairs of integers. The each internal
# pair consists of a prime number -- a prime factor --
# and a natural number -- an exponent.
#
# == Example
# For [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]], it returns
# p_1**e_1 * p_2**e_2 * .... * p_n**e_n.
#
# Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12
def int_from_prime_division(pd)
pd.inject(1){|value, (prime, index)|
value *= prime**index
}
end
# Returns the factorization of +value+.
#
# == Parameters
# +value+:: An arbitrary integer.
# +generator+:: Optional. A pseudo-prime generator.
# +generator+.succ must return the next
# pseudo-prime number in the ascendent
# order. It must generate all prime numbers,
# but may generate non prime numbers.
#
# === Exceptions
# +ZeroDivisionError+:: when +value+ is zero.
#
# == Example
# For an arbitrary integer
# n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n,
# prime_division(n) returns
# [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]].
#
# Prime.prime_division(12) #=> [[2,2], [3,1]]
#
def prime_division(value, generator= Prime::Generator23.new)
raise ZeroDivisionError if value == 0
if value < 0
value = -value
pv = [[-1, 1]]
else
pv = []
end
for prime in generator
count = 0
while (value1, mod = value.divmod(prime)
mod) == 0
value = value1
count += 1
end end
end if count != 0
pv.push [prime, count]
# Iterates the given block over all prime numbers.
#
# == Parameters
# +ubound+::
# Optional. An arbitrary positive number.
# The upper bound of enumeration. The method enumerates
# prime numbers infinitely if +ubound+ is nil.
# +generator+::
# Optional. An implementation of pseudo-prime generator.
#
# == Return value
# An evaluated value of the given block at the last time.
# Or an enumerator which is compatible to an +Enumerator+
# if no block given.
#
# == Description
# Calls +block+ once for each prime number, passing the prime as
# a parameter.
#
# +ubound+::
# Upper bound of prime numbers. The iterator stops after
# yields all prime numbers p <= +ubound+.
#
# == Note
# +Prime+.+new+ returns a object extended by +Prime+::+OldCompatibility+
# in order to compatibility to Ruby 1.8, and +Prime+#each is overwritten
# by +Prime+::+OldCompatibility+#+each+.
#
# +Prime+.+new+ is now obsolete. Use +Prime+.+instance+.+each+ or simply
# +Prime+.+each+.
def each(ubound = nil, generator = EratosthenesGenerator.new, &block)
generator.upper_bound = ubound
generator.each(&block)
end
# Returns true if +value+ is prime, false for a composite.
#
# == Parameters
# +value+:: an arbitrary integer to be checked.
# +generator+:: optional. A pseudo-prime generator.
def prime?(value, generator = Prime::Generator23.new)
value = -value if value < 0
return false if value < 2
for num in generator
q,r = value.divmod num
return true if q < num
return false if r == 0
end end
break if value1 <= prime
end
if value > 1
pv.push [value, 1]
end
return pv
end
# An abstract class for enumerating pseudo-prime numbers.
#
# Concrete subclasses should override succ, next, rewind.
class PseudoPrimeGenerator
include Enumerable
def initialize(ubound = nil)
@ubound = ubound
end end
# Re-composes a prime factorization and returns the product. def upper_bound=(ubound)
# @ubound = ubound
# == Parameters end
# +pd+:: Array of pairs of integers. The each internal def upper_bound
# pair consists of a prime number -- a prime factor -- @ubound
# and a natural number -- an exponent.
#
# == Example
# For [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]], it returns
# p_1**e_1 * p_2**e_2 * .... * p_n**e_n.
#
# Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12
def int_from_prime_division(pd)
pd.inject(1){|value, (prime, index)|
value *= prime**index
}
end end
# Returns the factorization of +value+. # returns the next pseudo-prime number, and move the internal
# position forward.
# #
# == Parameters # +PseudoPrimeGenerator+#succ raises +NotImplementedError+.
# +value+:: An arbitrary integer. def succ
# +generator+:: Optional. A pseudo-prime generator. raise NotImplementedError, "need to define `succ'"
# +generator+.succ must return the next end
# pseudo-prime number in the ascendent
# order. It must generate all prime numbers, # alias of +succ+.
# but may generate non prime numbers. def next
raise NotImplementedError, "need to define `next'"
end
# Rewinds the internal position for enumeration.
# #
# === Exceptions # See +Enumerator+#rewind.
# +ZeroDivisionError+:: when +value+ is zero. def rewind
# raise NotImplementedError, "need to define `rewind'"
# == Example end
# For an arbitrary integer
# n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n, # Iterates the given block for each prime numbers.
# prime_division(n) returns def each(&block)
# [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]. return self.dup unless block
# if @ubound
# Prime.prime_division(12) #=> [[2,2], [3,1]] last_value = nil
# loop do
def prime_division(value, generator= Prime::Generator23.new) prime = succ
raise ZeroDivisionError if value == 0 break last_value if prime > @ubound
if value < 0 last_value = block.call(prime)
value = -value end
pv = [[-1, 1]]
else else
pv = []
end
for prime in generator
count = 0
while (value1, mod = value.divmod(prime)
mod) == 0
value = value1
count += 1
end
if count != 0
pv.push [prime, count]
end
break if value1 <= prime
end
if value > 1
pv.push [value, 1]
end
return pv
end
# An abstract class for enumerating pseudo-prime numbers.
#
# Concrete subclasses should override succ, next, rewind.
class PseudoPrimeGenerator
include Enumerable
def initialize(ubound = nil)
@ubound = ubound
end
def upper_bound=(ubound)
@ubound = ubound
end
def upper_bound
@ubound
end
# returns the next pseudo-prime number, and move the internal
# position forward.
#
# +PseudoPrimeGenerator+#succ raises +NotImplementedError+.
def succ
raise NotImplementedError, "need to define `succ'"
end
# alias of +succ+.
def next
raise NotImplementedError, "need to define `next'"
end
# Rewinds the internal position for enumeration.
#
# See +Enumerator+#rewind.
def rewind
raise NotImplementedError, "need to define `rewind'"
end
# Iterates the given block for each prime numbers.
def each(&block)
return self.dup unless block
if @ubound
last_value = nil
loop do
prime = succ
break last_value if prime > @ubound
last_value = block.call(prime)
end
else
loop do
block.call(succ)
end
end
end
# see +Enumerator+#with_index.
alias with_index each_with_index
# see +Enumerator+#with_object.
def with_object(obj)
return enum_for(:with_object) unless block_given?
each do |prime|
yield prime, obj
end
end
end
# An implementation of +PseudoPrimeGenerator+.
#
# Uses +EratosthenesSieve+.
class EratosthenesGenerator < PseudoPrimeGenerator
def initialize
@last_prime = nil
super
end
def succ
@last_prime = @last_prime ? EratosthenesSieve.instance.next_to(@last_prime) : 2
end
def rewind
initialize
end
alias next succ
end
# An implementation of +PseudoPrimeGenerator+ which uses
# a prime table generated by trial division.
class TrialDivisionGenerator<PseudoPrimeGenerator
def initialize
@index = -1
super
end
def succ
TrialDivision.instance[@index += 1]
end
def rewind
initialize
end
alias next succ
end
# Generates all integer which are greater than 2 and
# are not divided by 2 nor 3.
#
# This is a pseudo-prime generator, suitable on
# checking primality of a integer by brute force
# method.
class Generator23<PseudoPrimeGenerator
def initialize
@prime = 1
@step = nil
super
end
def succ
loop do loop do
if (@step) block.call(succ)
@prime += @step
@step = 6 - @step
else
case @prime
when 1; @prime = 2
when 2; @prime = 3
when 3; @prime = 5; @step = 2
end
end
return @prime
end end
end end
alias next succ
def rewind
initialize
end
end end
# see +Enumerator+#with_index.
alias with_index each_with_index
# see +Enumerator+#with_object.
def with_object(obj)
# Internal use. An implementation of prime table by trial division method. return enum_for(:with_object) unless block_given?
class TrialDivision each do |prime|
include Singleton yield prime, obj
def initialize # :nodoc:
# These are included as class variables to cache them for later uses. If memory
# usage is a problem, they can be put in Prime#initialize as instance variables.
# There must be no primes between @primes[-1] and @next_to_check.
@primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
# @next_to_check % 6 must be 1.
@next_to_check = 103 # @primes[-1] - @primes[-1] % 6 + 7
@ulticheck_index = 3 # @primes.index(@primes.reverse.find {|n|
# n < Math.sqrt(@@next_to_check) })
@ulticheck_next_squared = 121 # @primes[@ulticheck_index + 1] ** 2
end
# Returns the cached prime numbers.
def cache
return @primes
end
alias primes cache
alias primes_so_far cache
# Returns the +index+th prime number.
#
# +index+ is a 0-based index.
def [](index)
while index >= @primes.length
# Only check for prime factors up to the square root of the potential primes,
# but without the performance hit of an actual square root calculation.
if @next_to_check + 4 > @ulticheck_next_squared
@ulticheck_index += 1
@ulticheck_next_squared = @primes.at(@ulticheck_index + 1) ** 2
end
# Only check numbers congruent to one and five, modulo six. All others
# are divisible by two or three. This also allows us to skip checking against
# two and three.
@primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
@next_to_check += 4
@primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
@next_to_check += 2
end
return @primes[index]
end
end
# Internal use. An implementation of eratosthenes's sieve
class EratosthenesSieve
include Singleton
BITS_PER_ENTRY = 16 # each entry is a set of 16-bits in a Fixnum
NUMS_PER_ENTRY = BITS_PER_ENTRY * 2 # twiced because even numbers are omitted
ENTRIES_PER_TABLE = 8
NUMS_PER_TABLE = NUMS_PER_ENTRY * ENTRIES_PER_TABLE
FILLED_ENTRY = (1 << NUMS_PER_ENTRY) - 1
def initialize # :nodoc:
# bitmap for odd prime numbers less than 256.
# For an arbitrary odd number n, @tables[i][j][k] is
# * 1 if n is prime,
# * 0 if n is composite,
# where i,j,k = indices(n)
@tables = [[0xcb6e, 0x64b4, 0x129a, 0x816d, 0x4c32, 0x864a, 0x820d, 0x2196].freeze]
end
# returns the least odd prime number which is greater than +n+.
def next_to(n)
n = (n-1).div(2)*2+3 # the next odd number to given n
table_index, integer_index, bit_index = indices(n)
loop do
extend_table until @tables.length > table_index
for j in integer_index...ENTRIES_PER_TABLE
if !@tables[table_index][j].zero?
for k in bit_index...BITS_PER_ENTRY
return NUMS_PER_TABLE*table_index + NUMS_PER_ENTRY*j + 2*k+1 if !@tables[table_index][j][k].zero?
end
end
bit_index = 0
end
table_index += 1; integer_index = 0
end
end
private
# for an odd number +n+, returns (i, j, k) such that @tables[i][j][k] represents primarity of the number
def indices(n)
# binary digits of n: |0|1|2|3|4|5|6|7|8|9|10|11|....
# indices: |-| k | j | i
# because of NUMS_PER_ENTRY, NUMS_PER_TABLE
k = (n & 0b00011111) >> 1
j = (n & 0b11100000) >> 5
i = n >> 8
return i, j, k
end
def extend_table
lbound = NUMS_PER_TABLE * @tables.length
ubound = lbound + NUMS_PER_TABLE
new_table = [FILLED_ENTRY] * ENTRIES_PER_TABLE # which represents primarity in lbound...ubound
(3..Integer(Math.sqrt(ubound))).step(2) do |p|
i, j, k = indices(p)
next if @tables[i][j][k].zero?
start = (lbound.div(p)+1)*p # least multiple of p which is >= lbound
start += p if start.even?
(start...ubound).step(2*p) do |n|
_, j, k = indices(n)
new_table[j] &= FILLED_ENTRY^(1<<k)
end
end
@tables << new_table.freeze
end
end
# Provides a +Prime+ object with compatibility to Ruby 1.8 when instantiated via +Prime+.+new+.
module OldCompatibility
# Returns the next prime number and forwards internal pointer.
def succ
@generator.succ
end
alias next succ
# Overwrites Prime#each.
#
# Iterates the given block over all prime numbers. Note that enumeration starts from
# the current position of internal pointer, not rewound.
def each(&block)
return @generator.dup unless block_given?
loop do
yield succ
end
end end
end end
end end
# An implementation of +PseudoPrimeGenerator+.
#
# Uses +EratosthenesSieve+.
class EratosthenesGenerator < PseudoPrimeGenerator
def initialize
@last_prime = nil
super
end
def succ
@last_prime = @last_prime ? EratosthenesSieve.instance.next_to(@last_prime) : 2
end
def rewind
initialize
end
alias next succ
end
# An implementation of +PseudoPrimeGenerator+ which uses
# a prime table generated by trial division.
class TrialDivisionGenerator<PseudoPrimeGenerator
def initialize
@index = -1
super
end
def succ
TrialDivision.instance[@index += 1]
end
def rewind
initialize
end
alias next succ
end
# Generates all integer which are greater than 2 and
# are not divided by 2 nor 3.
#
# This is a pseudo-prime generator, suitable on
# checking primality of a integer by brute force
# method.
class Generator23<PseudoPrimeGenerator
def initialize
@prime = 1
@step = nil
super
end
def succ
loop do
if (@step)
@prime += @step
@step = 6 - @step
else
case @prime
when 1; @prime = 2
when 2; @prime = 3
when 3; @prime = 5; @step = 2
end
end
return @prime
end
end
alias next succ
def rewind
initialize
end
end
# Internal use. An implementation of prime table by trial division method.
class TrialDivision
include Singleton
def initialize # :nodoc:
# These are included as class variables to cache them for later uses. If memory
# usage is a problem, they can be put in Prime#initialize as instance variables.
# There must be no primes between @primes[-1] and @next_to_check.
@primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
# @next_to_check % 6 must be 1.
@next_to_check = 103 # @primes[-1] - @primes[-1] % 6 + 7
@ulticheck_index = 3 # @primes.index(@primes.reverse.find {|n|
# n < Math.sqrt(@@next_to_check) })
@ulticheck_next_squared = 121 # @primes[@ulticheck_index + 1] ** 2
end
# Returns the cached prime numbers.
def cache
return @primes
end
alias primes cache
alias primes_so_far cache
# Returns the +index+th prime number.
#
# +index+ is a 0-based index.
def [](index)
while index >= @primes.length
# Only check for prime factors up to the square root of the potential primes,
# but without the performance hit of an actual square root calculation.
if @next_to_check + 4 > @ulticheck_next_squared
@ulticheck_index += 1
@ulticheck_next_squared = @primes.at(@ulticheck_index + 1) ** 2
end
# Only check numbers congruent to one and five, modulo six. All others
# are divisible by two or three. This also allows us to skip checking against
# two and three.
@primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
@next_to_check += 4
@primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
@next_to_check += 2
end
return @primes[index]
end
end
# Internal use. An implementation of eratosthenes's sieve
class EratosthenesSieve
include Singleton
BITS_PER_ENTRY = 16 # each entry is a set of 16-bits in a Fixnum
NUMS_PER_ENTRY = BITS_PER_ENTRY * 2 # twiced because even numbers are omitted
ENTRIES_PER_TABLE = 8
NUMS_PER_TABLE = NUMS_PER_ENTRY * ENTRIES_PER_TABLE
FILLED_ENTRY = (1 << NUMS_PER_ENTRY) - 1
def initialize # :nodoc:
# bitmap for odd prime numbers less than 256.
# For an arbitrary odd number n, @tables[i][j][k] is
# * 1 if n is prime,
# * 0 if n is composite,
# where i,j,k = indices(n)
@tables = [[0xcb6e, 0x64b4, 0x129a, 0x816d, 0x4c32, 0x864a, 0x820d, 0x2196].freeze]
end
# returns the least odd prime number which is greater than +n+.
def next_to(n)
n = (n-1).div(2)*2+3 # the next odd number to given n
table_index, integer_index, bit_index = indices(n)
loop do
extend_table until @tables.length > table_index
for j in integer_index...ENTRIES_PER_TABLE
if !@tables[table_index][j].zero?
for k in bit_index...BITS_PER_ENTRY
return NUMS_PER_TABLE*table_index + NUMS_PER_ENTRY*j + 2*k+1 if !@tables[table_index][j][k].zero?
end
end
bit_index = 0
end
table_index += 1; integer_index = 0
end
end
private
# for an odd number +n+, returns (i, j, k) such that @tables[i][j][k] represents primarity of the number
def indices(n)
# binary digits of n: |0|1|2|3|4|5|6|7|8|9|10|11|....
# indices: |-| k | j | i
# because of NUMS_PER_ENTRY, NUMS_PER_TABLE
k = (n & 0b00011111) >> 1
j = (n & 0b11100000) >> 5
i = n >> 8
return i, j, k
end
def extend_table
lbound = NUMS_PER_TABLE * @tables.length
ubound = lbound + NUMS_PER_TABLE
new_table = [FILLED_ENTRY] * ENTRIES_PER_TABLE # which represents primarity in lbound...ubound
(3..Integer(Math.sqrt(ubound))).step(2) do |p|
i, j, k = indices(p)
next if @tables[i][j][k].zero?
start = (lbound.div(p)+1)*p # least multiple of p which is >= lbound
start += p if start.even?
(start...ubound).step(2*p) do |n|
_, j, k = indices(n)
new_table[j] &= FILLED_ENTRY^(1<<k)
end
end
@tables << new_table.freeze
end
end
# Provides a +Prime+ object with compatibility to Ruby 1.8 when instantiated via +Prime+.+new+.
module OldCompatibility
# Returns the next prime number and forwards internal pointer.
def succ
@generator.succ
end
alias next succ
# Overwrites Prime#each.
#
# Iterates the given block over all prime numbers. Note that enumeration starts from
# the current position of internal pointer, not rewound.
def each(&block)
return @generator.dup unless block_given?
loop do
yield succ
end
end
end
end

View File

@ -6,15 +6,15 @@ module REXML
STOP = ']]>' STOP = ']]>'
ILLEGAL = /(\]\]>)/ ILLEGAL = /(\]\]>)/
# Constructor. CData is data between <![CDATA[ ... ]]> # Constructor. CData is data between <![CDATA[ ... ]]>
# #
# _Examples_ # _Examples_
# CData.new( source ) # CData.new( source )
# CData.new( "Here is some CDATA" ) # CData.new( "Here is some CDATA" )
# CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element ) # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
def initialize( first, whitespace=true, parent=nil ) def initialize( first, whitespace=true, parent=nil )
super( first, whitespace, parent, false, true, ILLEGAL ) super( first, whitespace, parent, false, true, ILLEGAL )
end end
# Make a copy of this object # Make a copy of this object
# #

View File

@ -7,7 +7,7 @@ module REXML
# class directly. # class directly.
class Child class Child
include Node include Node
attr_reader :parent # The Parent of this object attr_reader :parent # The Parent of this object
# Constructor. Any inheritors of this class should call super to make # Constructor. Any inheritors of this class should call super to make
# sure this method is called. # sure this method is called.

View File

@ -38,15 +38,15 @@ module REXML
# See REXML::Formatters # See REXML::Formatters
# #
# output:: # output::
# Where to write the string # Where to write the string
# indent:: # indent::
# An integer. If -1, no indenting will be used; otherwise, the # An integer. If -1, no indenting will be used; otherwise, the
# indentation will be this number of spaces, and children will be # indentation will be this number of spaces, and children will be
# indented an additional amount. # indented an additional amount.
# transitive:: # transitive::
# Ignored by this class. The contents of comments are never modified. # Ignored by this class. The contents of comments are never modified.
# ie_hack:: # ie_hack::
# Needed for conformity to the child API, but not used by this class. # Needed for conformity to the child API, but not used by this class.
def write( output, indent=-1, transitive=false, ie_hack=false ) def write( output, indent=-1, transitive=false, ie_hack=false )
Kernel.warn("Comment.write is deprecated. See REXML::Formatters") Kernel.warn("Comment.write is deprecated. See REXML::Formatters")
indent( output, indent ) indent( output, indent )

View File

@ -165,7 +165,7 @@ module REXML
# Document.new("<a><b/></a>").serialize( tr ) # Document.new("<a><b/></a>").serialize( tr )
# #
# output:: # output::
# output an object which supports '<< string'; this is where the # output an object which supports '<< string'; this is where the
# document will be written. # document will be written.
# indent:: # indent::
# An integer. If -1, no indenting will be used; otherwise, the # An integer. If -1, no indenting will be used; otherwise, the
@ -188,15 +188,15 @@ module REXML
output = Output.new( output, xml_decl.encoding ) output = Output.new( output, xml_decl.encoding )
end end
formatter = if indent > -1 formatter = if indent > -1
if transitive if transitive
require "rexml/formatters/transitive" require "rexml/formatters/transitive"
REXML::Formatters::Transitive.new( indent, ie_hack ) REXML::Formatters::Transitive.new( indent, ie_hack )
else else
REXML::Formatters::Pretty.new( indent, ie_hack ) REXML::Formatters::Pretty.new( indent, ie_hack )
end end
else else
REXML::Formatters::Default.new( ie_hack ) REXML::Formatters::Default.new( ie_hack )
end end
formatter.write( self, output ) formatter.write( self, output )
end end

View File

@ -20,7 +20,7 @@ module REXML
class Element < Parent class Element < Parent
include Namespace include Namespace
UNDEFINED = "UNDEFINED"; # The default name UNDEFINED = "UNDEFINED"; # The default name
# Mechanisms for accessing attributes and child elements of this # Mechanisms for accessing attributes and child elements of this
# element. # element.
@ -31,17 +31,17 @@ module REXML
# Constructor # Constructor
# arg:: # arg::
# if not supplied, will be set to the default value. # if not supplied, will be set to the default value.
# If a String, the name of this object will be set to the argument. # If a String, the name of this object will be set to the argument.
# If an Element, the object will be shallowly cloned; name, # If an Element, the object will be shallowly cloned; name,
# attributes, and namespaces will be copied. Children will +not+ be # attributes, and namespaces will be copied. Children will +not+ be
# copied. # copied.
# parent:: # parent::
# if supplied, must be a Parent, and will be used as # if supplied, must be a Parent, and will be used as
# the parent of this object. # the parent of this object.
# context:: # context::
# If supplied, must be a hash containing context items. Context items # If supplied, must be a hash containing context items. Context items
# include: # include:
# * <tt>:respect_whitespace</tt> the value of this is :+all+ or an array of # * <tt>:respect_whitespace</tt> the value of this is :+all+ or an array of
# strings being the names of the elements to respect # strings being the names of the elements to respect
# whitespace for. Defaults to :+all+. # whitespace for. Defaults to :+all+.
@ -297,7 +297,7 @@ module REXML
el = @elements.add(element) el = @elements.add(element)
attrs.each do |key, value| attrs.each do |key, value|
el.attributes[key]=value el.attributes[key]=value
end if attrs.kind_of? Hash end if attrs.kind_of? Hash
el el
end end
@ -667,7 +667,7 @@ module REXML
# #
# Writes out this element, and recursively, all children. # Writes out this element, and recursively, all children.
# output:: # output::
# output an object which supports '<< string'; this is where the # output an object which supports '<< string'; this is where the
# document will be written. # document will be written.
# indent:: # indent::
# An integer. If -1, no indenting will be used; otherwise, the # An integer. If -1, no indenting will be used; otherwise, the
@ -690,15 +690,15 @@ module REXML
def write(output=$stdout, indent=-1, transitive=false, ie_hack=false) def write(output=$stdout, indent=-1, transitive=false, ie_hack=false)
Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters") Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters")
formatter = if indent > -1 formatter = if indent > -1
if transitive if transitive
require "rexml/formatters/transitive" require "rexml/formatters/transitive"
REXML::Formatters::Transitive.new( indent, ie_hack ) REXML::Formatters::Transitive.new( indent, ie_hack )
else else
REXML::Formatters::Pretty.new( indent, ie_hack ) REXML::Formatters::Pretty.new( indent, ie_hack )
end end
else else
REXML::Formatters::Default.new( ie_hack ) REXML::Formatters::Default.new( ie_hack )
end end
formatter.write( self, output ) formatter.write( self, output )
end end
@ -778,7 +778,7 @@ module REXML
else else
return XPath::first( @element, index ) return XPath::first( @element, index )
#{ |element| #{ |element|
# return element if element.kind_of? Element # return element if element.kind_of? Element
#} #}
#return nil #return nil
end end
@ -1086,7 +1086,7 @@ module REXML
# doc.root.attributes['foo'] = '4' # doc.root.attributes['foo'] = '4'
# doc.root.attributes['x:foo'] = nil # doc.root.attributes['x:foo'] = nil
def []=( name, value ) def []=( name, value )
if value.nil? # Delete the named attribute if value.nil? # Delete the named attribute
attr = get_attribute(name) attr = get_attribute(name)
delete attr delete attr
return return
@ -1116,8 +1116,8 @@ module REXML
value.prefix != "xmlns" and old_attr.prefix != "xmlns" and value.prefix != "xmlns" and old_attr.prefix != "xmlns" and
@element.namespace( old_attr.prefix ) == @element.namespace( old_attr.prefix ) ==
@element.namespace( value.prefix ) @element.namespace( value.prefix )
store value.name, { old_attr.prefix => old_attr, store value.name, { old_attr.prefix => old_attr,
value.prefix => value } value.prefix => value }
else else
store value.name, value store value.name, value
end end
@ -1236,7 +1236,7 @@ module REXML
( !namespace.empty? || !attribute.fully_expanded_name.index(':') ) ( !namespace.empty? || !attribute.fully_expanded_name.index(':') )
# foo will match xmlns:foo, but only if foo isn't also an attribute # foo will match xmlns:foo, but only if foo isn't also an attribute
result = attribute if !result or !namespace.empty? or result = attribute if !result or !namespace.empty? or
!attribute.fully_expanded_name.index(':') !attribute.fully_expanded_name.index(':')
end end
} }
result result

View File

@ -1,13 +1,13 @@
require 'rexml/xmltokens' require 'rexml/xmltokens'
# [ :element, parent, name, attributes, children* ] # [ :element, parent, name, attributes, children* ]
# a = Node.new # a = Node.new
# a << "B" # => <a>B</a> # a << "B" # => <a>B</a>
# a.b # => <a>B<b/></a> # a.b # => <a>B<b/></a>
# a.b[1] # => <a>B<b/><b/><a> # a.b[1] # => <a>B<b/><b/><a>
# a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a> # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
# a.b[0].c # => <a>B<b><c/></b><b x="y"/></a> # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
# a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a> # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
module REXML module REXML
module Light module Light
# Represents a tagged XML element. Elements are characterized by # Represents a tagged XML element. Elements are characterized by

View File

@ -36,12 +36,12 @@ module REXML
end end
def indent to, ind def indent to, ind
if @parent and @parent.context and not @parent.context[:indentstyle].nil? then if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
indentstyle = @parent.context[:indentstyle] indentstyle = @parent.context[:indentstyle]
else else
indentstyle = ' ' indentstyle = ' '
end end
to << indentstyle*ind unless ind<1 to << indentstyle*ind unless ind<1
end end
def parent? def parent?

View File

@ -44,10 +44,10 @@ module REXML
end end
# An element is an array. The array contains: # An element is an array. The array contains:
# 0 The parent element # 0 The parent element
# 1 The tag name # 1 The tag name
# 2 A hash of attributes # 2 A hash of attributes
# 3..-1 The child elements # 3..-1 The child elements
# An element is an array of size > 3 # An element is an array of size > 3
# Text is a String # Text is a String
# PIs are [ :processing_instruction, target, data ] # PIs are [ :processing_instruction, target, data ]

View File

@ -28,15 +28,15 @@ module REXML
# Listen arguments: # Listen arguments:
# #
# Symbol, Array, Block # Symbol, Array, Block
# Listen to Symbol events on Array elements # Listen to Symbol events on Array elements
# Symbol, Block # Symbol, Block
# Listen to Symbol events # Listen to Symbol events
# Array, Listener # Array, Listener
# Listen to all events on Array elements # Listen to all events on Array elements
# Array, Block # Array, Block
# Listen to :start_element events on Array elements # Listen to :start_element events on Array elements
# Listener # Listener
# Listen to All events # Listen to All events
# #
# Symbol can be one of: :start_element, :end_element, # Symbol can be one of: :start_element, :end_element,
# :start_prefix_mapping, :end_prefix_mapping, :characters, # :start_prefix_mapping, :end_prefix_mapping, :characters,
@ -209,7 +209,7 @@ module REXML
((name.nil? and match.nil?) or match.nil? or ( ((name.nil? and match.nil?) or match.nil? or (
(name == match) or (name == match) or
(match.kind_of? Regexp and name =~ match) (match.kind_of? Regexp and name =~ match)
) )
) )
) )
end.collect{|x| x[-1]} end.collect{|x| x[-1]}
@ -222,7 +222,7 @@ module REXML
((name.nil? and match.nil?) or match.nil? or ( ((name.nil? and match.nil?) or match.nil? or (
(name == match) or (name == match) or
(match.kind_of? Regexp and name =~ match) (match.kind_of? Regexp and name =~ match)
) )
) )
) )
end.collect{|x| x[-1]} end.collect{|x| x[-1]}

View File

@ -42,10 +42,10 @@ module REXML
end end
# An element is an array. The array contains: # An element is an array. The array contains:
# 0 The parent element # 0 The parent element
# 1 The tag name # 1 The tag name
# 2 A hash of attributes # 2 A hash of attributes
# 3..-1 The child elements # 3..-1 The child elements
# An element is an array of size > 3 # An element is an array of size > 3
# Text is a String # Text is a String
# PIs are [ :processing_instruction, target, data ] # PIs are [ :processing_instruction, target, data ]

View File

@ -49,20 +49,20 @@ module REXML
def QuickPath::filter elements, path def QuickPath::filter elements, path
return elements if path.nil? or path == '' or elements.size == 0 return elements if path.nil? or path == '' or elements.size == 0
case path case path
when /^\/\//u # Descendant when /^\/\//u # Descendant
return axe( elements, "descendant-or-self", $' ) return axe( elements, "descendant-or-self", $' )
when /^\/?\b(\w[-\w]*)\b::/u # Axe when /^\/?\b(\w[-\w]*)\b::/u # Axe
return axe( elements, $1, $' ) return axe( elements, $1, $' )
when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
rest = $' rest = $'
results = [] results = []
elements.each do |element| elements.each do |element|
results |= filter( element.to_a, rest ) results |= filter( element.to_a, rest )
end end
return results return results
when /^\/?(\w[-\w]*)\(/u # / Function when /^\/?(\w[-\w]*)\(/u # / Function
return function( elements, $1, $' ) return function( elements, $1, $' )
when Namespace::NAMESPLIT # Element name when Namespace::NAMESPLIT # Element name
name = $2 name = $2
ns = $1 ns = $1
rest = $' rest = $'
@ -79,22 +79,22 @@ module REXML
matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
end end
return matches return matches
when /^\[/u # Predicate when /^\[/u # Predicate
return predicate( elements, path ) return predicate( elements, path )
when /^\/?\.\.\./u # Ancestor when /^\/?\.\.\./u # Ancestor
return axe( elements, "ancestor", $' ) return axe( elements, "ancestor", $' )
when /^\/?\.\./u # Parent when /^\/?\.\./u # Parent
return filter( elements.collect{|e|e.parent}, $' ) return filter( elements.collect{|e|e.parent}, $' )
when /^\/?\./u # Self when /^\/?\./u # Self
return filter( elements, $' ) return filter( elements, $' )
when /^\*/u # Any when /^\*/u # Any
results = [] results = []
elements.each do |element| elements.each do |element|
results |= filter( [element], $' ) if element.kind_of? Element results |= filter( [element], $' ) if element.kind_of? Element
#if element.kind_of? Element #if element.kind_of? Element
# children = element.to_a # children = element.to_a
# children.delete_if { |child| !child.kind_of?(Element) } # children.delete_if { |child| !child.kind_of?(Element) }
# results |= filter( children, $' ) # results |= filter( children, $' )
#end #end
end end
return results return results
@ -132,7 +132,7 @@ module REXML
matches = filter(elements.collect{|element| element.parent}.uniq, rest) matches = filter(elements.collect{|element| element.parent}.uniq, rest)
when "following-sibling" when "following-sibling"
matches = filter(elements.collect{|element| element.next_sibling}.uniq, matches = filter(elements.collect{|element| element.next_sibling}.uniq,
rest) rest)
when "previous-sibling" when "previous-sibling"
matches = filter(elements.collect{|element| matches = filter(elements.collect{|element|
element.previous_sibling}.uniq, rest ) element.previous_sibling}.uniq, rest )
@ -174,32 +174,32 @@ module REXML
predicate.gsub!( predicate.gsub!(
/#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u, /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u,
'\1 \2 \3 and \3 \4 \5' ) '\1 \2 \3 and \3 \4 \5' )
# Let's do some Ruby trickery to avoid some work: # Let's do some Ruby trickery to avoid some work:
predicate.gsub!( /&/u, "&&" ) predicate.gsub!( /&/u, "&&" )
predicate.gsub!( /=/u, "==" ) predicate.gsub!( /=/u, "==" )
predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' ) predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' )
predicate.gsub!( /\bmod\b/u, "%" ) predicate.gsub!( /\bmod\b/u, "%" )
predicate.gsub!( /\b(\w[-\w.]*\()/u ) { predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
fname = $1 fname = $1
fname.gsub( /-/u, "_" ) fname.gsub( /-/u, "_" )
} }
Functions.pair = [ 0, elements.size ] Functions.pair = [ 0, elements.size ]
results = [] results = []
elements.each do |element| elements.each do |element|
Functions.pair[0] += 1 Functions.pair[0] += 1
Functions.node = element Functions.node = element
res = eval( predicate ) res = eval( predicate )
case res case res
when true when true
results << element results << element
when Fixnum when Fixnum
results << element if Functions.pair[0] == res results << element if Functions.pair[0] == res
when String when String
results << element results << element
end
end end
end return filter( results, rest )
return filter( results, rest )
end end
def QuickPath::attribute( name ) def QuickPath::attribute( name )

View File

@ -12,12 +12,12 @@ module REXML
# Finds and returns the first node that matches the supplied xpath. # Finds and returns the first node that matches the supplied xpath.
# element:: # element::
# The context element # The context element
# path:: # path::
# The xpath to search for. If not supplied or nil, returns the first # The xpath to search for. If not supplied or nil, returns the first
# node matching '*'. # node matching '*'.
# namespaces:: # namespaces::
# If supplied, a Hash which defines a namespace mapping. # If supplied, a Hash which defines a namespace mapping.
# variables:: # variables::
# If supplied, a Hash which maps $variables in the query # If supplied, a Hash which maps $variables in the query
# to values. This can be used to avoid XPath injection attacks # to values. This can be used to avoid XPath injection attacks
@ -45,7 +45,7 @@ module REXML
# path:: # path::
# The xpath to search for. If not supplied or nil, defaults to '*' # The xpath to search for. If not supplied or nil, defaults to '*'
# namespaces:: # namespaces::
# If supplied, a Hash which defines a namespace mapping # If supplied, a Hash which defines a namespace mapping
# variables:: # variables::
# If supplied, a Hash which maps $variables in the query # If supplied, a Hash which maps $variables in the query
# to values. This can be used to avoid XPath injection attacks # to values. This can be used to avoid XPath injection attacks

View File

@ -43,10 +43,10 @@ module Rinda
def write_service def write_service
Thread.new do Thread.new do
loop do loop do
msg = @soc.recv(1024) msg = @soc.recv(1024)
do_write(msg) do_write(msg)
end end
end end
end end
@ -56,11 +56,11 @@ module Rinda
def do_write(msg) def do_write(msg)
Thread.new do Thread.new do
begin begin
tuple, sec = Marshal.load(msg) tuple, sec = Marshal.load(msg)
@ts.write(tuple, sec) @ts.write(tuple, sec)
rescue rescue
end end
end end
end end
@ -69,9 +69,9 @@ module Rinda
def reply_service def reply_service
Thread.new do Thread.new do
loop do loop do
do_reply do_reply
end end
end end
end end
@ -105,8 +105,8 @@ module Rinda
def self.finger def self.finger
unless @@finger unless @@finger
@@finger = self.new @@finger = self.new
@@finger.lookup_ring_any @@finger.lookup_ring_any
end end
@@finger @@finger
end end
@ -178,15 +178,15 @@ module Rinda
msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout]) msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout])
@broadcast_list.each do |it| @broadcast_list.each do |it|
soc = UDPSocket.open soc = UDPSocket.open
begin begin
soc.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true) soc.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
soc.send(msg, 0, it, @port) soc.send(msg, 0, it, @port)
rescue rescue
nil nil
ensure ensure
soc.close soc.close
end end
end end
sleep(timeout) sleep(timeout)
end end
@ -199,13 +199,13 @@ module Rinda
queue = Queue.new queue = Queue.new
Thread.new do Thread.new do
self.lookup_ring(timeout) do |ts| self.lookup_ring(timeout) do |ts|
queue.push(ts) queue.push(ts)
end end
queue.push(nil) queue.push(nil)
while it = queue.pop while it = queue.pop
@rings.push(it) @rings.push(it)
end end
end end
@primary = queue.pop @primary = queue.pop

View File

@ -51,7 +51,7 @@ module RSS
module_eval(<<-EOC, __FILE__, __LINE__ + 1) module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def new_#{name} def new_#{name}
#{name} = self.class::#{klass_name}.new(@maker) #{name} = self.class::#{klass_name}.new(@maker)
@#{plural} << #{name} @#{plural} << #{name}
if block_given? if block_given?
yield #{name} yield #{name}
@ -63,14 +63,14 @@ module RSS
def to_feed(*args) def to_feed(*args)
@#{plural}.each do |#{name}| @#{plural}.each do |#{name}|
#{name}.to_feed(*args) #{name}.to_feed(*args)
end end
end end
def replace(elements) def replace(elements)
@#{plural}.replace(elements.to_a) @#{plural}.replace(elements.to_a)
end end
EOC EOC
end end
def def_classed_element_without_accessor(name, class_name=nil) def def_classed_element_without_accessor(name, class_name=nil)
@ -88,7 +88,7 @@ module RSS
def make_#{name} def make_#{name}
self.class::#{class_name}.new(@maker) self.class::#{class_name}.new(@maker)
end end
EOC EOC
end end
def def_classed_element(name, class_name=nil, attribute_name=nil) def def_classed_element(name, class_name=nil, attribute_name=nil)
@ -106,7 +106,7 @@ module RSS
def #{name}=(new_value) def #{name}=(new_value)
@#{name}.#{attribute_name} = new_value @#{name}.#{attribute_name} = new_value
end end
EOC EOC
else else
attr_reader name attr_reader name
end end
@ -126,17 +126,17 @@ module RSS
end end
module_eval(<<-EOC, __FILE__, __LINE__ + 1) module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name} def #{name}
#{local_variable_name} = #{plural_name}.first #{local_variable_name} = #{plural_name}.first
#{local_variable_name} ? #{local_variable_name}.#{attribute} : nil #{local_variable_name} ? #{local_variable_name}.#{attribute} : nil
end end
def #{name}=(#{new_value_variable_name}) def #{name}=(#{new_value_variable_name})
#{local_variable_name} = #{local_variable_name} =
#{plural_name}.first || #{plural_name}.new_#{new_name} #{plural_name}.first || #{plural_name}.new_#{new_name}
#{additional_setup_code} #{additional_setup_code}
#{local_variable_name}.#{attribute} = #{new_value_variable_name} #{local_variable_name}.#{attribute} = #{new_value_variable_name}
end end
EOC EOC
end end
def def_other_element(name) def def_other_element(name)
@ -153,7 +153,7 @@ module RSS
current.#{name} = @#{name} current.#{name} = @#{name}
end end
end end
EOC EOC
end end
def def_csv_element(name, type=nil) def def_csv_element(name, type=nil)
@ -167,7 +167,7 @@ module RSS
def #{name}=(value) def #{name}=(value)
@#{name} = Utils::CSV.parse(value)#{converter} @#{name} = Utils::CSV.parse(value)#{converter}
end end
EOC EOC
end end
end end
@ -308,7 +308,7 @@ module RSS
def ensure_xml_content(content) def ensure_xml_content(content)
xhtml_uri = ::RSS::Atom::XHTML_URI xhtml_uri = ::RSS::Atom::XHTML_URI
unless content.is_a?(RSS::XML::Element) and unless content.is_a?(RSS::XML::Element) and
["div", xhtml_uri] == [content.name, content.uri] ["div", xhtml_uri] == [content.name, content.uri]
children = content children = content
children = [children] unless content.is_a?(Array) children = [children] unless content.is_a?(Array)
children = set_xhtml_uri_as_default_uri(children) children = set_xhtml_uri_as_default_uri(children)
@ -331,7 +331,7 @@ module RSS
def set_xhtml_uri_as_default_uri(children) def set_xhtml_uri_as_default_uri(children)
children.collect do |child| children.collect do |child|
if child.is_a?(RSS::XML::Element) and if child.is_a?(RSS::XML::Element) and
child.prefix.nil? and child.uri.nil? child.prefix.nil? and child.uri.nil?
RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI, RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI,
child.attributes.dup, child.attributes.dup,
set_xhtml_uri_as_default_uri(child.children)) set_xhtml_uri_as_default_uri(child.children))
@ -385,7 +385,7 @@ module RSS
} }
_language = language _language = language
if _language and if _language and
!dc_languages.any? {|dc_language| dc_language.value == _language} !dc_languages.any? {|dc_language| dc_language.value == _language}
dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self) dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self)
dc_language.value = _language.dup dc_language.value = _language.dup
dc_languages.unshift(dc_language) dc_languages.unshift(dc_language)
@ -417,7 +417,7 @@ module RSS
def make_#{element} def make_#{element}
self.class::#{Utils.to_class_name(element)}.new(self) self.class::#{Utils.to_class_name(element)}.new(self)
end end
EOC EOC
end end
attr_reader :feed_version attr_reader :feed_version
@ -500,9 +500,9 @@ module RSS
end end
[ [
["link", "href", Proc.new {|target,| "#{target}.href = 'self'"}], ["link", "href", Proc.new {|target,| "#{target}.href = 'self'"}],
["author", "name"], ["author", "name"],
["contributor", "name"], ["contributor", "name"],
].each do |name, attribute, additional_setup_maker| ].each do |name, attribute, additional_setup_maker|
def_classed_elements(name, attribute, &additional_setup_maker) def_classed_elements(name, attribute, &additional_setup_maker)
end end
@ -511,7 +511,7 @@ module RSS
managingEditor webMaster rating docs ttl).each do |element| managingEditor webMaster rating docs ttl).each do |element|
attr_accessor element attr_accessor element
add_need_initialize_variable(element) add_need_initialize_variable(element)
end end
%w(date lastBuildDate).each do |date_element| %w(date lastBuildDate).each do |date_element|
attr_reader date_element attr_reader date_element
@ -713,12 +713,12 @@ module RSS
end end
[ [
["author", "name"], ["author", "name"],
["link", "href", Proc.new {|target,| "#{target}.href = 'alternate'"}], ["link", "href", Proc.new {|target,| "#{target}.href = 'alternate'"}],
["contributor", "name"], ["contributor", "name"],
].each do |name, attribute| ].each do |name, attribute|
def_classed_elements(name, attribute) def_classed_elements(name, attribute)
end end
%w(comments id published).each do |element| %w(comments id published).each do |element|
attr_accessor element attr_accessor element
@ -795,10 +795,10 @@ module RSS
%w(authors categories contributors generator icon %w(authors categories contributors generator icon
logo rights subtitle title).each do |name| logo rights subtitle title).each do |name|
def_classed_element(name) def_classed_element(name)
end end
[ [
["link", "href"], ["link", "href"],
].each do |name, attribute| ].each do |name, attribute|
def_classed_elements(name, attribute) def_classed_elements(name, attribute)
end end

View File

@ -13,11 +13,11 @@ module RSS
end end
def self.install_image_item(klass) def self.install_image_item(klass)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageItem < ImageItemBase class ImageItem < ImageItemBase
DublinCoreModel.install_dublin_core(self) DublinCoreModel.install_dublin_core(self)
end end
EOC EOC
end end
class ImageItemBase < Base class ImageItemBase < Base
@ -29,9 +29,9 @@ EOC
add_need_initialize_variable("image_width") add_need_initialize_variable("image_width")
add_need_initialize_variable("image_height") add_need_initialize_variable("image_height")
alias width= image_width= alias width= image_width=
alias width image_width alias width image_width
alias height= image_height= alias height= image_height=
alias height image_height alias height image_height
def have_required_values? def have_required_values?
@about @about
@ -57,7 +57,7 @@ EOC
end end
def self.install_image_favicon(klass) def self.install_image_favicon(klass)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageFavicon < ImageFaviconBase class ImageFavicon < ImageFaviconBase
DublinCoreModel.install_dublin_core(self) DublinCoreModel.install_dublin_core(self)
end end
@ -73,9 +73,9 @@ EOC
alias size image_size alias size image_size
alias size= image_size= alias size= image_size=
def have_required_values? def have_required_values?
@about and @image_size @about and @image_size
end end
def to_feed(feed, current) def to_feed(feed, current)
if current.respond_to?(:image_favicon=) and have_required_values? if current.respond_to?(:image_favicon=) and have_required_values?

View File

@ -5,27 +5,27 @@ class Time
unless respond_to?(:w3cdtf) unless respond_to?(:w3cdtf)
def w3cdtf(date) def w3cdtf(date)
if /\A\s* if /\A\s*
(-?\d+)-(\d\d)-(\d\d) (-?\d+)-(\d\d)-(\d\d)
(?:T (?:T
(\d\d):(\d\d)(?::(\d\d))? (\d\d):(\d\d)(?::(\d\d))?
(\.\d+)? (\.\d+)?
(Z|[+-]\d\d:\d\d)?)? (Z|[+-]\d\d:\d\d)?)?
\s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8)) \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8))
datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i] datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i]
usec = 0 usec = 0
usec = $7.to_f * 1000000 if $7 usec = $7.to_f * 1000000 if $7
zone = $8 zone = $8
if zone if zone
off = zone_offset(zone, datetime[0]) off = zone_offset(zone, datetime[0])
datetime = apply_offset(*(datetime + [off])) datetime = apply_offset(*(datetime + [off]))
datetime << usec datetime << usec
time = Time.utc(*datetime) time = Time.utc(*datetime)
time.localtime unless zone_utc?(zone) time.localtime unless zone_utc?(zone)
time time
else else
datetime << usec datetime << usec
Time.local(*datetime) Time.local(*datetime)
end end
else else
raise ArgumentError.new("invalid date: #{date.inspect}") raise ArgumentError.new("invalid date: #{date.inspect}")
end end
@ -209,7 +209,7 @@ module RSS
else else
'' ''
end end
EOC EOC
end end
end end
alias_method(:install_have_attribute_element, :install_have_child_element) alias_method(:install_have_attribute_element, :install_have_child_element)
@ -230,7 +230,7 @@ EOC
rv << value if /\\A\\s*\\z/ !~ value rv << value if /\\A\\s*\\z/ !~ value
end end
rv.join("\n") rv.join("\n")
EOC EOC
end end
end end
@ -259,12 +259,12 @@ EOC
else else
rv << value rv << value
end end
rv << "</#{elem_name}>" rv << "</#{elem_name}>"
rv rv
else else
'' ''
end end
EOC EOC
end end
end end
@ -290,12 +290,12 @@ EOC
else else
rv << value rv << value
end end
rv << "</#{elem_name}>" rv << "</#{elem_name}>"
rv rv
else else
'' ''
end end
EOC EOC
end end
end end
@ -307,10 +307,10 @@ EOC
add_to_element_method(method_name) add_to_element_method(method_name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2)) module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{method_name}(need_convert=true, indent='') def #{method_name}(need_convert=true, indent='')
#{yield(name, elem_name)} #{yield(name, elem_name)}
end end
private :#{method_name} private :#{method_name}
EOC EOC
end end
def inherit_convert_attr_reader(*attrs) def inherit_convert_attr_reader(*attrs)
@ -323,14 +323,14 @@ EOC
def #{attr} def #{attr}
if @#{attr} if @#{attr}
#{attr}_without_inherit #{attr}_without_inherit
elsif @parent elsif @parent
@parent.#{attr} @parent.#{attr}
else else
nil nil
end end
end end
EOC EOC
end end
end end
@ -351,7 +351,7 @@ EOC
"\#{base}\#{value}" "\#{base}\#{value}"
end end
end end
EOC EOC
end end
end end
@ -362,7 +362,7 @@ EOC
def #{attr} def #{attr}
convert(@#{attr}) convert(@#{attr})
end end
EOC EOC
end end
end end
@ -408,7 +408,7 @@ EOC
@#{attr}.join(#{separator.dump}) @#{attr}.join(#{separator.dump})
end end
end end
EOC EOC
end end
end end
@ -448,7 +448,7 @@ EOC
end end
end end
EOC EOC
end end
def integer_writer(name, disp_name=name) def integer_writer(name, disp_name=name)
@ -468,7 +468,7 @@ EOC
end end
end end
end end
EOC EOC
end end
def positive_integer_writer(name, disp_name=name) def positive_integer_writer(name, disp_name=name)
@ -490,7 +490,7 @@ EOC
end end
end end
end end
EOC EOC
end end
def boolean_writer(name, disp_name=name) def boolean_writer(name, disp_name=name)
@ -510,7 +510,7 @@ EOC
end end
end end
end end
EOC EOC
end end
def text_type_writer(name, disp_name=name) def text_type_writer(name, disp_name=name)
@ -522,7 +522,7 @@ EOC
end end
@#{name} = new_value @#{name} = new_value
end end
EOC EOC
end end
def content_writer(name, disp_name=name) def content_writer(name, disp_name=name)
@ -536,7 +536,7 @@ EOC
@#{name}.content = new_value @#{name}.content = new_value
end end
end end
EOC EOC
end end
def yes_clean_other_writer(name, disp_name=name) def yes_clean_other_writer(name, disp_name=name)
@ -603,7 +603,7 @@ EOC
end end
end end
alias_method(:set_#{accessor_name}, :#{accessor_name}=) alias_method(:set_#{accessor_name}, :#{accessor_name}=)
EOC EOC
end end
end end
@ -630,7 +630,7 @@ EOC
value = __send__(var) value = __send__(var)
next if value.nil? next if value.nil?
if value.respond_to?("setup_maker") and if value.respond_to?("setup_maker") and
!not_need_to_call_setup_maker_variables.include?(var) !not_need_to_call_setup_maker_variables.include?(var)
value.setup_maker(target) value.setup_maker(target)
else else
setter = "#{var}=" setter = "#{var}="
@ -1173,7 +1173,7 @@ EOC
else else
if name == tag if name == tag
if models[i+1] and models[i+1][0] != name and if models[i+1] and models[i+1][0] != name and
tags and tags.first == name tags and tags.first == name
raise TooMuchTagError.new(name, tag_name) raise TooMuchTagError.new(name, tag_name)
end end
else else

View File

@ -506,28 +506,28 @@ module Scanf
class FormatString class FormatString
attr_reader :string_left, :last_spec_tried, attr_reader :string_left, :last_spec_tried,
:last_match_tried, :matched_count, :space :last_match_tried, :matched_count, :space
SPECIFIERS = 'diuXxofFeEgGscaA' SPECIFIERS = 'diuXxofFeEgGscaA'
REGEX = / REGEX = /
# possible space, followed by... # possible space, followed by...
(?:\s* (?:\s*
# percent sign, followed by... # percent sign, followed by...
% %
# another percent sign, or... # another percent sign, or...
(?:%| (?:%|
# optional assignment suppression flag # optional assignment suppression flag
\*? \*?
# optional maximum field width # optional maximum field width
\d* \d*
# named character class, ... # named character class, ...
(?:\[\[:\w+:\]\]| (?:\[\[:\w+:\]\]|
# traditional character class, or... # traditional character class, or...
\[[^\]]*\]| \[[^\]]*\]|
# specifier letter. # specifier letter.
[#{SPECIFIERS}])))| [#{SPECIFIERS}])))|
# or miscellaneous characters # or miscellaneous characters
[^%\s]+/ix [^%\s]+/ix
def initialize(str) def initialize(str)
@specs = [] @specs = []
@ -578,33 +578,33 @@ end
class IO class IO
# The trick here is doing a match where you grab one *line* # The trick here is doing a match where you grab one *line*
# of input at a time. The linebreak may or may not occur # of input at a time. The linebreak may or may not occur
# at the boundary where the string matches a format specifier. # at the boundary where the string matches a format specifier.
# And if it does, some rule about whitespace may or may not # And if it does, some rule about whitespace may or may not
# be in effect... # be in effect...
# #
# That's why this is much more elaborate than the string # That's why this is much more elaborate than the string
# version. # version.
# #
# For each line: # For each line:
# Match succeeds (non-emptily) # Match succeeds (non-emptily)
# and the last attempted spec/string sub-match succeeded: # and the last attempted spec/string sub-match succeeded:
# #
# could the last spec keep matching? # could the last spec keep matching?
# yes: save interim results and continue (next line) # yes: save interim results and continue (next line)
# #
# The last attempted spec/string did not match: # The last attempted spec/string did not match:
# #
# are we on the next-to-last spec in the string? # are we on the next-to-last spec in the string?
# yes: # yes:
# is fmt_string.string_left all spaces? # is fmt_string.string_left all spaces?
# yes: does current spec care about input space? # yes: does current spec care about input space?
# yes: fatal failure # yes: fatal failure
# no: save interim results and continue # no: save interim results and continue
# no: continue [this state could be analyzed further] # no: continue [this state could be analyzed further]
# #
# #
def scanf(str,&b) def scanf(str,&b)
return block_scanf(str,&b) if b return block_scanf(str,&b) if b
@ -671,8 +671,8 @@ class IO
def block_scanf(str) def block_scanf(str)
final = [] final = []
# Sub-ideal, since another FS gets created in scanf. # Sub-ideal, since another FS gets created in scanf.
# But used here to determine the number of specifiers. # But used here to determine the number of specifiers.
fstr = Scanf::FormatString.new(str) fstr = Scanf::FormatString.new(str)
last_spec = fstr.last_spec last_spec = fstr.last_spec
begin begin

View File

@ -92,19 +92,19 @@ class Set
@hash = orig.instance_eval{@hash}.dup @hash = orig.instance_eval{@hash}.dup
end end
def freeze # :nodoc: def freeze # :nodoc:
super super
@hash.freeze @hash.freeze
self self
end end
def taint # :nodoc: def taint # :nodoc:
super super
@hash.taint @hash.taint
self self
end end
def untaint # :nodoc: def untaint # :nodoc:
super super
@hash.untaint @hash.untaint
self self
@ -148,15 +148,15 @@ class Set
def flatten_merge(set, seen = Set.new) # :nodoc: def flatten_merge(set, seen = Set.new) # :nodoc:
set.each { |e| set.each { |e|
if e.is_a?(Set) if e.is_a?(Set)
if seen.include?(e_id = e.object_id) if seen.include?(e_id = e.object_id)
raise ArgumentError, "tried to flatten recursive Set" raise ArgumentError, "tried to flatten recursive Set"
end end
seen.add(e_id) seen.add(e_id)
flatten_merge(e, seen) flatten_merge(e, seen)
seen.delete(e_id) seen.delete(e_id)
else else
add(e) add(e)
end end
} }
@ -325,163 +325,163 @@ class Set
def |(enum) def |(enum)
dup.merge(enum) dup.merge(enum)
end end
alias + | ## alias + | ##
alias union | ## alias union | ##
# Returns a new set built by duplicating the set, removing every # Returns a new set built by duplicating the set, removing every
# element that appears in the given enumerable object. # element that appears in the given enumerable object.
def -(enum) def -(enum)
dup.subtract(enum) dup.subtract(enum)
end
alias difference - ##
# Returns a new set containing elements common to the set and the
# given enumerable object.
def &(enum)
n = self.class.new
do_with_enum(enum) { |o| n.add(o) if include?(o) }
n
end
alias intersection & ##
# Returns a new set containing elements exclusive between the set
# and the given enumerable object. (set ^ enum) is equivalent to
# ((set | enum) - (set & enum)).
def ^(enum)
n = Set.new(enum)
each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
n
end
# Returns true if two sets are equal. The equality of each couple
# of elements is defined according to Object#eql?.
def ==(other)
if self.equal?(other)
true
elsif other.instance_of?(self.class)
@hash == other.instance_variable_get(:@hash)
elsif other.is_a?(Set) && self.size == other.size
other.all? { |o| @hash.include?(o) }
else
false
end end
alias difference - ##
# Returns a new set containing elements common to the set and the
# given enumerable object.
def &(enum)
n = self.class.new
do_with_enum(enum) { |o| n.add(o) if include?(o) }
n
end
alias intersection & ##
# Returns a new set containing elements exclusive between the set
# and the given enumerable object. (set ^ enum) is equivalent to
# ((set | enum) - (set & enum)).
def ^(enum)
n = Set.new(enum)
each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
n
end
# Returns true if two sets are equal. The equality of each couple
# of elements is defined according to Object#eql?.
def ==(other)
if self.equal?(other)
true
elsif other.instance_of?(self.class)
@hash == other.instance_variable_get(:@hash)
elsif other.is_a?(Set) && self.size == other.size
other.all? { |o| @hash.include?(o) }
else
false
end end
end
def hash # :nodoc: def hash # :nodoc:
@hash.hash @hash.hash
end end
def eql?(o) # :nodoc: def eql?(o) # :nodoc:
return false unless o.is_a?(Set) return false unless o.is_a?(Set)
@hash.eql?(o.instance_eval{@hash}) @hash.eql?(o.instance_eval{@hash})
end end
# Classifies the set by the return value of the given block and # Classifies the set by the return value of the given block and
# returns a hash of {value => set of elements} pairs. The block is # returns a hash of {value => set of elements} pairs. The block is
# called once for each element of the set, passing the element as # called once for each element of the set, passing the element as
# parameter. # parameter.
# #
# e.g.: # e.g.:
# #
# require 'set' # require 'set'
# files = Set.new(Dir.glob("*.rb")) # files = Set.new(Dir.glob("*.rb"))
# hash = files.classify { |f| File.mtime(f).year } # hash = files.classify { |f| File.mtime(f).year }
# p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>, # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
# # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>, # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
# # 2002=>#<Set: {"f.rb"}>} # # 2002=>#<Set: {"f.rb"}>}
def classify # :yields: o def classify # :yields: o
block_given? or return enum_for(__method__) block_given? or return enum_for(__method__)
h = {} h = {}
each { |i| each { |i|
x = yield(i) x = yield(i)
(h[x] ||= self.class.new).add(i) (h[x] ||= self.class.new).add(i)
} }
h h
end end
# Divides the set into a set of subsets according to the commonality # Divides the set into a set of subsets according to the commonality
# defined by the given block. # defined by the given block.
# #
# If the arity of the block is 2, elements o1 and o2 are in common # If the arity of the block is 2, elements o1 and o2 are in common
# if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
# in common if block.call(o1) == block.call(o2). # in common if block.call(o1) == block.call(o2).
# #
# e.g.: # e.g.:
# #
# require 'set' # require 'set'
# numbers = Set[1, 3, 4, 6, 9, 10, 11] # numbers = Set[1, 3, 4, 6, 9, 10, 11]
# set = numbers.divide { |i,j| (i - j).abs == 1 } # set = numbers.divide { |i,j| (i - j).abs == 1 }
# p set # => #<Set: {#<Set: {1}>, # p set # => #<Set: {#<Set: {1}>,
# # #<Set: {11, 9, 10}>, # # #<Set: {11, 9, 10}>,
# # #<Set: {3, 4}>, # # #<Set: {3, 4}>,
# # #<Set: {6}>}> # # #<Set: {6}>}>
def divide(&func) def divide(&func)
func or return enum_for(__method__) func or return enum_for(__method__)
if func.arity == 2 if func.arity == 2
require 'tsort' require 'tsort'
class << dig = {} # :nodoc: class << dig = {} # :nodoc:
include TSort include TSort
alias tsort_each_node each_key alias tsort_each_node each_key
def tsort_each_child(node, &block) def tsort_each_child(node, &block)
fetch(node).each(&block) fetch(node).each(&block)
end
end end
each { |u|
dig[u] = a = []
each{ |v| func.call(u, v) and a << v }
}
set = Set.new()
dig.each_strongly_connected_component { |css|
set.add(self.class.new(css))
}
set
else
Set.new(classify(&func).values)
end
end
InspectKey = :__inspect_key__ # :nodoc:
# Returns a string containing a human-readable representation of the
# set. ("#<Set: {element1, element2, ...}>")
def inspect
ids = (Thread.current[InspectKey] ||= [])
if ids.include?(object_id)
return sprintf('#<%s: {...}>', self.class.name)
end end
begin each { |u|
ids << object_id dig[u] = a = []
return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2]) each{ |v| func.call(u, v) and a << v }
ensure
ids.pop
end
end
def pretty_print(pp) # :nodoc:
pp.text sprintf('#<%s: {', self.class.name)
pp.nest(1) {
pp.seplist(self) { |o|
pp.pp o
}
} }
pp.text "}>"
set = Set.new()
dig.each_strongly_connected_component { |css|
set.add(self.class.new(css))
}
set
else
Set.new(classify(&func).values)
end
end
InspectKey = :__inspect_key__ # :nodoc:
# Returns a string containing a human-readable representation of the
# set. ("#<Set: {element1, element2, ...}>")
def inspect
ids = (Thread.current[InspectKey] ||= [])
if ids.include?(object_id)
return sprintf('#<%s: {...}>', self.class.name)
end end
def pretty_print_cycle(pp) # :nodoc: begin
pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...') ids << object_id
return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
ensure
ids.pop
end end
end end
def pretty_print(pp) # :nodoc:
pp.text sprintf('#<%s: {', self.class.name)
pp.nest(1) {
pp.seplist(self) { |o|
pp.pp o
}
}
pp.text "}>"
end
def pretty_print_cycle(pp) # :nodoc:
pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
end
end
# #
# SortedSet implements a Set that guarantees that it's element are # SortedSet implements a Set that guarantees that it's element are
# yielded in sorted order (according to the return values of their # yielded in sorted order (according to the return values of their
@ -515,11 +515,11 @@ class SortedSet < Set
@@setup = false @@setup = false
class << self class << self
def [](*ary) # :nodoc: def [](*ary) # :nodoc:
new(ary) new(ary)
end end
def setup # :nodoc: def setup # :nodoc:
@@setup and return @@setup and return
module_eval { module_eval {
@ -528,89 +528,89 @@ class SortedSet < Set
remove_method :old_init remove_method :old_init
} }
begin begin
require 'rbtree' require 'rbtree'
module_eval %{ module_eval %{
def initialize(*args, &block) def initialize(*args, &block)
@hash = RBTree.new @hash = RBTree.new
super super
end end
def add(o) def add(o)
o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
super super
end end
alias << add alias << add
} }
rescue LoadError rescue LoadError
module_eval %{ module_eval %{
def initialize(*args, &block) def initialize(*args, &block)
@keys = nil @keys = nil
super super
end end
def clear def clear
@keys = nil @keys = nil
super super
end end
def replace(enum) def replace(enum)
@keys = nil @keys = nil
super super
end end
def add(o) def add(o)
o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
@keys = nil @keys = nil
super super
end end
alias << add alias << add
def delete(o) def delete(o)
@keys = nil @keys = nil
@hash.delete(o) @hash.delete(o)
self self
end end
def delete_if def delete_if
block_given? or return enum_for(__method__) block_given? or return enum_for(__method__)
n = @hash.size n = @hash.size
super super
@keys = nil if @hash.size != n @keys = nil if @hash.size != n
self self
end end
def keep_if def keep_if
block_given? or return enum_for(__method__) block_given? or return enum_for(__method__)
n = @hash.size n = @hash.size
super super
@keys = nil if @hash.size != n @keys = nil if @hash.size != n
self self
end end
def merge(enum) def merge(enum)
@keys = nil @keys = nil
super super
end end
def each def each
block_given? or return enum_for(__method__) block_given? or return enum_for(__method__)
to_a.each { |o| yield(o) } to_a.each { |o| yield(o) }
self self
end end
def to_a def to_a
(@keys = @hash.keys).sort! unless @keys (@keys = @hash.keys).sort! unless @keys
@keys @keys
end end
} }
end end
@@setup = true @@setup = true
end end
end end
def initialize(*args, &block) # :nodoc: def initialize(*args, &block) # :nodoc:
SortedSet.setup SortedSet.setup
initialize(*args, &block) initialize(*args, &block)
end end
@ -657,54 +657,54 @@ end
# #
# if @proc.arity == 2 # if @proc.arity == 2
# instance_eval %{ # instance_eval %{
# def add(o) # def add(o)
# @hash[o] = true if @proc.call(self, o) # @hash[o] = true if @proc.call(self, o)
# self # self
# end # end
# alias << add # alias << add
# #
# def add?(o) # def add?(o)
# if include?(o) || !@proc.call(self, o) # if include?(o) || !@proc.call(self, o)
# nil # nil
# else # else
# @hash[o] = true # @hash[o] = true
# self # self
# end # end
# end # end
# #
# def replace(enum) # def replace(enum)
# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
# clear # clear
# enum.each_entry { |o| add(o) } # enum.each_entry { |o| add(o) }
# #
# self # self
# end # end
# #
# def merge(enum) # def merge(enum)
# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
# enum.each_entry { |o| add(o) } # enum.each_entry { |o| add(o) }
# #
# self # self
# end # end
# } # }
# else # else
# instance_eval %{ # instance_eval %{
# def add(o) # def add(o)
# if @proc.call(o) # if @proc.call(o)
# @hash[o] = true # @hash[o] = true
# end # end
# self # self
# end # end
# alias << add # alias << add
# #
# def add?(o) # def add?(o)
# if include?(o) || !@proc.call(o) # if include?(o) || !@proc.call(o)
# nil # nil
# else # else
# @hash[o] = true # @hash[o] = true
# self # self
# end # end
# end # end
# } # }
# end # end
# #
@ -835,13 +835,13 @@ class TC_Set < Test::Unit::TestCase
set1 = Set[ set1 = Set[
1, 1,
Set[ Set[
5, 5,
Set[7, Set[7,
Set[0] Set[0]
], ],
Set[6,2], Set[6,2],
1 1
], ],
3, 3,
Set[3,4] Set[3,4]
] ]
@ -1020,8 +1020,8 @@ class TC_Set < Test::Unit::TestCase
assert_nothing_raised { assert_nothing_raised {
set.each { |o| set.each { |o|
ary.delete(o) or raise "unexpected element: #{o}" ary.delete(o) or raise "unexpected element: #{o}"
} }
ary.empty? or raise "forgotten elements: #{ary.join(', ')}" ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
} }
@ -1085,11 +1085,11 @@ class TC_Set < Test::Unit::TestCase
ret = set.collect! { |i| ret = set.collect! { |i|
case i case i
when Numeric when Numeric
i * 2 i * 2
when String when String
i.upcase i.upcase
else else
nil nil
end end
} }
@ -1168,8 +1168,8 @@ class TC_Set < Test::Unit::TestCase
set2 = Set["a", "b", set1] set2 = Set["a", "b", set1]
set1 = set1.add(set1.clone) set1 = set1.add(set1.clone)
# assert_equal(set1, set2) # assert_equal(set1, set2)
# assert_equal(set2, set1) # assert_equal(set2, set1)
assert_equal(set2, set2.clone) assert_equal(set2, set2.clone)
assert_equal(set1.clone, set1) assert_equal(set1.clone, set1)
@ -1214,15 +1214,15 @@ class TC_Set < Test::Unit::TestCase
assert_equal(set, ret.flatten) assert_equal(set, ret.flatten)
ret.each { |s| ret.each { |s|
if s.include?(0) if s.include?(0)
assert_equal(Set[0,1], s) assert_equal(Set[0,1], s)
elsif s.include?(3) elsif s.include?(3)
assert_equal(Set[3,4,5], s) assert_equal(Set[3,4,5], s)
elsif s.include?(7) elsif s.include?(7)
assert_equal(Set[7], s) assert_equal(Set[7], s)
elsif s.include?(9) elsif s.include?(9)
assert_equal(Set[9,10,11], s) assert_equal(Set[9,10,11], s)
else else
raise "unexpected group: #{s.inspect}" raise "unexpected group: #{s.inspect}"
end end
} }
end end

View File

@ -1,8 +1,8 @@
# #
# shell.rb - # shell.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision: 1.9 $ # $Revision: 1.9 $
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -25,7 +25,7 @@ class Shell
include Error include Error
extend Exception2MessageMapper extend Exception2MessageMapper
# @cascade = true # @cascade = true
# debug: true -> normal debug # debug: true -> normal debug
# debug: 1 -> eval definition debug # debug: 1 -> eval definition debug
# debug: 2 -> detail inspect debug # debug: 2 -> detail inspect debug
@ -41,7 +41,7 @@ class Shell
attr_accessor :cascade, :debug, :verbose attr_accessor :cascade, :debug, :verbose
# alias cascade? cascade # alias cascade? cascade
alias debug? debug alias debug? debug
alias verbose? verbose alias verbose? verbose
@verbose = true @verbose = true
@ -57,9 +57,9 @@ class Shell
def default_system_path def default_system_path
if @default_system_path if @default_system_path
@default_system_path @default_system_path
else else
ENV["PATH"].split(":") ENV["PATH"].split(":")
end end
end end
@ -69,9 +69,9 @@ class Shell
def default_record_separator def default_record_separator
if @default_record_separator if @default_record_separator
@default_record_separator @default_record_separator
else else
$/ $/
end end
end end
@ -156,10 +156,10 @@ class Shell
notify("chdir(with block) #{path}") if verbose notify("chdir(with block) #{path}") if verbose
cwd_old = @cwd cwd_old = @cwd
begin begin
chdir(path, nil) chdir(path, nil)
yield yield
ensure ensure
chdir(cwd_old, nil) chdir(cwd_old, nil)
end end
else else
notify("chdir #{path}") if verbose notify("chdir #{path}") if verbose
@ -179,9 +179,9 @@ class Shell
notify("pushdir(with block) #{path}") if verbose notify("pushdir(with block) #{path}") if verbose
pushdir(path, nil) pushdir(path, nil)
begin begin
yield yield
ensure ensure
popdir popdir
end end
elsif path elsif path
notify("pushdir #{path}") if verbose notify("pushdir #{path}") if verbose
@ -192,12 +192,12 @@ class Shell
else else
notify("pushdir") if verbose notify("pushdir") if verbose
if pop = @dir_stack.pop if pop = @dir_stack.pop
@dir_stack.push @cwd @dir_stack.push @cwd
chdir pop chdir pop
notify "dir stack: [#{@dir_stack.join ', '}]" notify "dir stack: [#{@dir_stack.join ', '}]"
self self
else else
Shell.Fail DirStackEmpty Shell.Fail DirStackEmpty
end end
end end
Void.new(self) Void.new(self)
@ -265,32 +265,32 @@ class Shell
def self.notify(*opts, &block) def self.notify(*opts, &block)
Shell::debug_output_synchronize do Shell::debug_output_synchronize do
if opts[-1].kind_of?(String) if opts[-1].kind_of?(String)
yorn = verbose? yorn = verbose?
else else
yorn = opts.pop yorn = opts.pop
end end
return unless yorn return unless yorn
if @debug_display_thread_id if @debug_display_thread_id
if @debug_display_process_id if @debug_display_process_id
prefix = "shell(##{Process.pid}:#{Thread.current.to_s.sub("Thread", "Th")}): " prefix = "shell(##{Process.pid}:#{Thread.current.to_s.sub("Thread", "Th")}): "
else else
prefix = "shell(#{Thread.current.to_s.sub("Thread", "Th")}): " prefix = "shell(#{Thread.current.to_s.sub("Thread", "Th")}): "
end end
else else
prefix = "shell: " prefix = "shell: "
end end
_head = true _head = true
STDERR.print opts.collect{|mes| STDERR.print opts.collect{|mes|
mes = mes.dup mes = mes.dup
yield mes if iterator? yield mes if iterator?
if _head if _head
_head = false _head = false
# "shell" " + mes # "shell" " + mes
prefix + mes prefix + mes
else else
" "* prefix.size + mes " "* prefix.size + mes
end end
}.join("\n")+"\n" }.join("\n")+"\n"
end end
end end

View File

@ -1,8 +1,8 @@
# #
# shell/builtin-command.rb - # shell/builtin-command.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -40,7 +40,7 @@ class Shell
def each(rs = nil) def each(rs = nil)
rs = @shell.record_separator unless rs rs = @shell.record_separator unless rs
for str in @strings for str in @strings
yield str + rs yield str + rs
end end
end end
end end
@ -53,11 +53,11 @@ class Shell
def each(rs = nil) def each(rs = nil)
if @cat_files.empty? if @cat_files.empty?
super super
else else
for src in @cat_files for src in @cat_files
@shell.foreach(src, rs){|l| yield l} @shell.foreach(src, rs){|l| yield l}
end end
end end
end end
end end
@ -71,31 +71,31 @@ class Shell
def each(rs = nil) def each(rs = nil)
if @pattern[0] == ?/ if @pattern[0] == ?/
@files = Dir[@pattern] @files = Dir[@pattern]
else else
prefix = @shell.pwd+"/" prefix = @shell.pwd+"/"
@files = Dir[prefix+@pattern].collect{|p| p.sub(prefix, "")} @files = Dir[prefix+@pattern].collect{|p| p.sub(prefix, "")}
end end
rs = @shell.record_separator unless rs rs = @shell.record_separator unless rs
for f in @files for f in @files
yield f+rs yield f+rs
end end
end end
end end
# class Sort < Cat # class Sort < Cat
# def initialize(sh, *filenames) # def initialize(sh, *filenames)
# super # super
# end # end
# #
# def each(rs = nil) # def each(rs = nil)
# ary = [] # ary = []
# super{|l| ary.push l} # super{|l| ary.push l}
# for l in ary.sort! # for l in ary.sort!
# yield l # yield l
# end # end
# end # end
# end # end
class AppendIO < BuiltInCommand class AppendIO < BuiltInCommand
def initialize(sh, io, filter) def initialize(sh, io, filter)
@ -107,7 +107,7 @@ class Shell
def input=(filter) def input=(filter)
@input.input=filter @input.input=filter
for l in @input for l in @input
@io << l @io << l
end end
end end
@ -122,9 +122,9 @@ class Shell
def input=(filter) def input=(filter)
begin begin
super super
ensure ensure
@io.close @io.close
end end
end end
end end
@ -138,9 +138,9 @@ class Shell
def each(rs = nil) def each(rs = nil)
to = @shell.open(@to_filename, "w") to = @shell.open(@to_filename, "w")
begin begin
super{|l| to << l; yield l} super{|l| to << l; yield l}
ensure ensure
to.close to.close
end end
end end
end end
@ -153,7 +153,7 @@ class Shell
def each(rs = nil) def each(rs = nil)
while job = @jobs.shift while job = @jobs.shift
job.each{|l| yield l} job.each{|l| yield l}
end end
end end
end end

View File

@ -1,8 +1,8 @@
# #
# shell/command-controller.rb - # shell/command-controller.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -19,7 +19,7 @@ require "shell/builtin-command"
class Shell class Shell
class CommandProcessor class CommandProcessor
# include Error # include Error
# #
# initialize of Shell and related classes. # initialize of Shell and related classes.
@ -37,11 +37,11 @@ class Shell
# define CommandProcessor#methods to Shell#methods and Filter#methods # define CommandProcessor#methods to Shell#methods and Filter#methods
for m in CommandProcessor.instance_methods(false) - NoDelegateMethods for m in CommandProcessor.instance_methods(false) - NoDelegateMethods
add_delegate_command_to_shell(m) add_delegate_command_to_shell(m)
end end
def self.method_added(id) def self.method_added(id)
add_delegate_command_to_shell(id) add_delegate_command_to_shell(id)
end end
end end
@ -50,14 +50,14 @@ class Shell
# #
def self.run_config def self.run_config
begin begin
load File.expand_path("~/.rb_shell") if ENV.key?("HOME") load File.expand_path("~/.rb_shell") if ENV.key?("HOME")
rescue LoadError, Errno::ENOENT rescue LoadError, Errno::ENOENT
rescue rescue
print "load error: #{rc}\n" print "load error: #{rc}\n"
print $!.class, ": ", $!, "\n" print $!.class, ": ", $!, "\n"
for err in $@[0, $@.size - 2] for err in $@[0, $@.size - 2]
print "\t", err, "\n" print "\t", err, "\n"
end end
end end
end end
@ -68,9 +68,9 @@ class Shell
# #
# CommandProcessor#expand_path(path) # CommandProcessor#expand_path(path)
# path: String # path: String
# return: String # return: String
# returns the absolute path for <path> # returns the absolute path for <path>
# #
def expand_path(path) def expand_path(path)
@shell.expand_path(path) @shell.expand_path(path)
@ -86,68 +86,68 @@ class Shell
# - # -
# #
# CommandProcessor#foreach(path, rs) # CommandProcessor#foreach(path, rs)
# path: String # path: String
# rs: String - record separator # rs: String - record separator
# iterator # iterator
# Same as: # Same as:
# File#foreach (when path is file) # File#foreach (when path is file)
# Dir#foreach (when path is directory) # Dir#foreach (when path is directory)
# path is relative to pwd # path is relative to pwd
# #
def foreach(path = nil, *rs) def foreach(path = nil, *rs)
path = "." unless path path = "." unless path
path = expand_path(path) path = expand_path(path)
if File.directory?(path) if File.directory?(path)
Dir.foreach(path){|fn| yield fn} Dir.foreach(path){|fn| yield fn}
else else
IO.foreach(path, *rs){|l| yield l} IO.foreach(path, *rs){|l| yield l}
end end
end end
# #
# CommandProcessor#open(path, mode) # CommandProcessor#open(path, mode)
# path: String # path: String
# mode: String # mode: String
# return: File or Dir # return: File or Dir
# Same as: # Same as:
# File#open (when path is file) # File#open (when path is file)
# Dir#open (when path is directory) # Dir#open (when path is directory)
# mode has an effect only when path is a file # mode has an effect only when path is a file
# #
def open(path, mode = nil, perm = 0666, &b) def open(path, mode = nil, perm = 0666, &b)
path = expand_path(path) path = expand_path(path)
if File.directory?(path) if File.directory?(path)
Dir.open(path, &b) Dir.open(path, &b)
else else
if @shell.umask if @shell.umask
f = File.open(path, mode, perm) f = File.open(path, mode, perm)
File.chmod(perm & ~@shell.umask, path) File.chmod(perm & ~@shell.umask, path)
if block_given? if block_given?
f.each(&b) f.each(&b)
end end
f f
else else
f = File.open(path, mode, perm, &b) f = File.open(path, mode, perm, &b)
end end
end end
end end
# public :open # public :open
# #
# CommandProcessor#unlink(path) # CommandProcessor#unlink(path)
# same as: # same as:
# Dir#unlink (when path is directory) # Dir#unlink (when path is directory)
# File#unlink (when path is file) # File#unlink (when path is file)
# #
def unlink(path) def unlink(path)
@shell.check_point @shell.check_point
path = expand_path(path) path = expand_path(path)
if File.directory?(path) if File.directory?(path)
Dir.unlink(path) Dir.unlink(path)
else else
IO.unlink(path) IO.unlink(path)
end end
Void.new(@shell) Void.new(@shell)
end end
@ -155,19 +155,19 @@ class Shell
# #
# CommandProcessor#test(command, file1, file2) # CommandProcessor#test(command, file1, file2)
# CommandProcessor#[command, file1, file2] # CommandProcessor#[command, file1, file2]
# command: char or String or Symbol # command: char or String or Symbol
# file1: String # file1: String
# file2: String(optional) # file2: String(optional)
# return: Boolean # return: Boolean
# same as: # same as:
# test() (when command is char or length 1 string or symbol) # test() (when command is char or length 1 string or symbol)
# FileTest.command (others) # FileTest.command (others)
# example: # example:
# sh[?e, "foo"] # sh[?e, "foo"]
# sh[:e, "foo"] # sh[:e, "foo"]
# sh["e", "foo"] # sh["e", "foo"]
# sh[:exists?, "foo"] # sh[:exists?, "foo"]
# sh["exists?", "foo"] # sh["exists?", "foo"]
# #
alias top_level_test test alias top_level_test test
def test(command, file1, file2=nil) def test(command, file1, file2=nil)
@ -177,25 +177,25 @@ class Shell
case command case command
when Integer when Integer
if file2 if file2
top_level_test(command, file1, file2) top_level_test(command, file1, file2)
else else
top_level_test(command, file1) top_level_test(command, file1)
end end
when String when String
if command.size == 1 if command.size == 1
if file2 if file2
top_level_test(command, file1, file2) top_level_test(command, file1, file2)
else else
top_level_test(command, file1) top_level_test(command, file1)
end end
else else
if file2 if file2
FileTest.send(command, file1, file2) FileTest.send(command, file1, file2)
else else
FileTest.send(command, file1) FileTest.send(command, file1)
end end
end end
end end
end end
alias [] test alias [] test
@ -209,8 +209,8 @@ class Shell
#-- #--
# #
# CommandProcessor#mkdir(*path) # CommandProcessor#mkdir(*path)
# path: String # path: String
# same as Dir.mkdir() # same as Dir.mkdir()
# #
def mkdir(*path) def mkdir(*path)
@shell.check_point @shell.check_point
@ -218,59 +218,59 @@ class Shell
perm = nil perm = nil
if path.last.kind_of?(Integer) if path.last.kind_of?(Integer)
perm = path.pop perm = path.pop
end end
for dir in path for dir in path
d = expand_path(dir) d = expand_path(dir)
if perm if perm
Dir.mkdir(d, perm) Dir.mkdir(d, perm)
else else
Dir.mkdir(d) Dir.mkdir(d)
end end
File.chmod(d, 0666 & ~@shell.umask) if @shell.umask File.chmod(d, 0666 & ~@shell.umask) if @shell.umask
end end
Void.new(@shell) Void.new(@shell)
end end
# #
# CommandProcessor#rmdir(*path) # CommandProcessor#rmdir(*path)
# path: String # path: String
# same as Dir.rmdir() # same as Dir.rmdir()
# #
def rmdir(*path) def rmdir(*path)
@shell.check_point @shell.check_point
notify("rmdir #{path.join(' ')}") notify("rmdir #{path.join(' ')}")
for dir in path for dir in path
Dir.rmdir(expand_path(dir)) Dir.rmdir(expand_path(dir))
end end
Void.new(@shell) Void.new(@shell)
end end
# #
# CommandProcessor#system(command, *opts) # CommandProcessor#system(command, *opts)
# command: String # command: String
# opts: String # opts: String
# return: SystemCommand # return: SystemCommand
# Same as system() function # Same as system() function
# example: # example:
# print sh.system("ls", "-l") # print sh.system("ls", "-l")
# sh.system("ls", "-l") | sh.head > STDOUT # sh.system("ls", "-l") | sh.head > STDOUT
# #
def system(command, *opts) def system(command, *opts)
if opts.empty? if opts.empty?
if command =~ /\*|\?|\{|\}|\[|\]|<|>|\(|\)|~|&|\||\\|\$|;|'|`|"|\n/ if command =~ /\*|\?|\{|\}|\[|\]|<|>|\(|\)|~|&|\||\\|\$|;|'|`|"|\n/
return SystemCommand.new(@shell, find_system_command("sh"), "-c", command) return SystemCommand.new(@shell, find_system_command("sh"), "-c", command)
else else
command, *opts = command.split(/\s+/) command, *opts = command.split(/\s+/)
end end
end end
SystemCommand.new(@shell, find_system_command(command), *opts) SystemCommand.new(@shell, find_system_command(command), *opts)
end end
# #
# ProcessCommand#rehash # ProcessCommand#rehash
# clear command hash table. # clear command hash table.
# #
def rehash def rehash
@system_commands = {} @system_commands = {}
@ -286,9 +286,9 @@ class Shell
def transact(&block) def transact(&block)
begin begin
@shell.instance_eval(&block) @shell.instance_eval(&block)
ensure ensure
check_point check_point
end end
end end
@ -318,11 +318,11 @@ class Shell
def append(to, filter) def append(to, filter)
case to case to
when String when String
AppendFile.new(@shell, to, filter) AppendFile.new(@shell, to, filter)
when IO when IO
AppendIO.new(@shell, to, filter) AppendIO.new(@shell, to, filter)
else else
Shell.Fail Error::CantApplyMethod, "append", to.class Shell.Fail Error::CantApplyMethod, "append", to.class
end end
end end
@ -337,10 +337,10 @@ class Shell
# %pwd, %cwd -> @pwd # %pwd, %cwd -> @pwd
def notify(*opts, &block) def notify(*opts, &block)
Shell.notify(*opts) {|mes| Shell.notify(*opts) {|mes|
yield mes if iterator? yield mes if iterator?
mes.gsub!("%pwd", "#{@cwd}") mes.gsub!("%pwd", "#{@cwd}")
mes.gsub!("%cwd", "#{@cwd}") mes.gsub!("%cwd", "#{@cwd}")
} }
end end
@ -351,21 +351,21 @@ class Shell
return command if /^\// =~ command return command if /^\// =~ command
case path = @system_commands[command] case path = @system_commands[command]
when String when String
if exists?(path) if exists?(path)
return path return path
else else
Shell.Fail Error::CommandNotFound, command Shell.Fail Error::CommandNotFound, command
end end
when false when false
Shell.Fail Error::CommandNotFound, command Shell.Fail Error::CommandNotFound, command
end end
for p in @shell.system_path for p in @shell.system_path
path = join(p, command) path = join(p, command)
if FileTest.exist?(path) if FileTest.exist?(path)
@system_commands[command] = path @system_commands[command] = path
return path return path
end end
end end
@system_commands[command] = false @system_commands[command] = false
Shell.Fail Error::CommandNotFound, command Shell.Fail Error::CommandNotFound, command
@ -373,21 +373,21 @@ class Shell
# #
# CommandProcessor.def_system_command(command, path) # CommandProcessor.def_system_command(command, path)
# command: String # command: String
# path: String # path: String
# define 'command()' method as method. # define 'command()' method as method.
# #
def self.def_system_command(command, path = command) def self.def_system_command(command, path = command)
begin begin
eval((d = %Q[def #{command}(*opts) eval((d = %Q[def #{command}(*opts)
SystemCommand.new(@shell, '#{path}', *opts) SystemCommand.new(@shell, '#{path}', *opts)
end]), nil, __FILE__, __LINE__ - 1) end]), nil, __FILE__, __LINE__ - 1)
rescue SyntaxError rescue SyntaxError
Shell.notify "warn: Can't define #{command} path: #{path}." Shell.notify "warn: Can't define #{command} path: #{path}."
end end
Shell.notify "Define #{command} path: #{path}.", Shell.debug? Shell.notify "Define #{command} path: #{path}.", Shell.debug?
Shell.notify("Definition of #{command}: ", d, Shell.notify("Definition of #{command}: ", d,
Shell.debug.kind_of?(Integer) && Shell.debug > 1) Shell.debug.kind_of?(Integer) && Shell.debug > 1)
end end
def self.undef_system_command(command) def self.undef_system_command(command)
@ -411,28 +411,28 @@ class Shell
ali = ali.id2name if ali.kind_of?(Symbol) ali = ali.id2name if ali.kind_of?(Symbol)
command = command.id2name if command.kind_of?(Symbol) command = command.id2name if command.kind_of?(Symbol)
begin begin
if iterator? if iterator?
@alias_map[ali.intern] = proc @alias_map[ali.intern] = proc
eval((d = %Q[def #{ali}(*opts) eval((d = %Q[def #{ali}(*opts)
@shell.__send__(:#{command}, @shell.__send__(:#{command},
*(CommandProcessor.alias_map[:#{ali}].call *opts)) *(CommandProcessor.alias_map[:#{ali}].call *opts))
end]), nil, __FILE__, __LINE__ - 1) end]), nil, __FILE__, __LINE__ - 1)
else else
args = opts.collect{|opt| '"' + opt + '"'}.join(",") args = opts.collect{|opt| '"' + opt + '"'}.join(",")
eval((d = %Q[def #{ali}(*opts) eval((d = %Q[def #{ali}(*opts)
@shell.__send__(:#{command}, #{args}, *opts) @shell.__send__(:#{command}, #{args}, *opts)
end]), nil, __FILE__, __LINE__ - 1) end]), nil, __FILE__, __LINE__ - 1)
end end
rescue SyntaxError rescue SyntaxError
Shell.notify "warn: Can't alias #{ali} command: #{command}." Shell.notify "warn: Can't alias #{ali} command: #{command}."
Shell.notify("Definition of #{ali}: ", d) Shell.notify("Definition of #{ali}: ", d)
raise raise
end end
Shell.notify "Define #{ali} command: #{command}.", Shell.debug? Shell.notify "Define #{ali} command: #{command}.", Shell.debug?
Shell.notify("Definition of #{ali}: ", d, Shell.notify("Definition of #{ali}: ", d,
Shell.debug.kind_of?(Integer) && Shell.debug > 1) Shell.debug.kind_of?(Integer) && Shell.debug > 1)
self self
end end
@ -444,43 +444,43 @@ class Shell
# #
# CommandProcessor.def_builtin_commands(delegation_class, command_specs) # CommandProcessor.def_builtin_commands(delegation_class, command_specs)
# delegation_class: Class or Module # delegation_class: Class or Module
# command_specs: [[command_name, [argument,...]],...] # command_specs: [[command_name, [argument,...]],...]
# command_name: String # command_name: String
# arguments: String # arguments: String
# FILENAME?? -> expand_path(filename??) # FILENAME?? -> expand_path(filename??)
# *FILENAME?? -> filename??.collect{|f|expand_path(f)}.join(", ") # *FILENAME?? -> filename??.collect{|f|expand_path(f)}.join(", ")
# define command_name(argument,...) as # define command_name(argument,...) as
# delegation_class.command_name(argument,...) # delegation_class.command_name(argument,...)
# #
def self.def_builtin_commands(delegation_class, command_specs) def self.def_builtin_commands(delegation_class, command_specs)
for meth, args in command_specs for meth, args in command_specs
arg_str = args.collect{|arg| arg.downcase}.join(", ") arg_str = args.collect{|arg| arg.downcase}.join(", ")
call_arg_str = args.collect{ call_arg_str = args.collect{
|arg| |arg|
case arg case arg
when /^(FILENAME.*)$/ when /^(FILENAME.*)$/
format("expand_path(%s)", $1.downcase) format("expand_path(%s)", $1.downcase)
when /^(\*FILENAME.*)$/ when /^(\*FILENAME.*)$/
# \*FILENAME* -> filenames.collect{|fn| expand_path(fn)}.join(", ") # \*FILENAME* -> filenames.collect{|fn| expand_path(fn)}.join(", ")
$1.downcase + '.collect{|fn| expand_path(fn)}' $1.downcase + '.collect{|fn| expand_path(fn)}'
else else
arg arg
end end
}.join(", ") }.join(", ")
d = %Q[def #{meth}(#{arg_str}) d = %Q[def #{meth}(#{arg_str})
#{delegation_class}.#{meth}(#{call_arg_str}) #{delegation_class}.#{meth}(#{call_arg_str})
end] end]
Shell.notify "Define #{meth}(#{arg_str})", Shell.debug? Shell.notify "Define #{meth}(#{arg_str})", Shell.debug?
Shell.notify("Definition of #{meth}: ", d, Shell.notify("Definition of #{meth}: ", d,
Shell.debug.kind_of?(Integer) && Shell.debug > 1) Shell.debug.kind_of?(Integer) && Shell.debug > 1)
eval d eval d
end end
end end
# #
# CommandProcessor.install_system_commands(pre) # CommandProcessor.install_system_commands(pre)
# pre: String - command name prefix # pre: String - command name prefix
# defines every command which belongs in default_system_path via # defines every command which belongs in default_system_path via
# CommandProcessor.command(). It doesn't define already defined # CommandProcessor.command(). It doesn't define already defined
# methods twice. By default, "pre_" is prefixes to each method # methods twice. By default, "pre_" is prefixes to each method
@ -490,24 +490,24 @@ class Shell
def self.install_system_commands(pre = "sys_") def self.install_system_commands(pre = "sys_")
defined_meth = {} defined_meth = {}
for m in Shell.methods for m in Shell.methods
defined_meth[m] = true defined_meth[m] = true
end end
sh = Shell.new sh = Shell.new
for path in Shell.default_system_path for path in Shell.default_system_path
next unless sh.directory? path next unless sh.directory? path
sh.cd path sh.cd path
sh.foreach do sh.foreach do
|cn| |cn|
if !defined_meth[pre + cn] && sh.file?(cn) && sh.executable?(cn) if !defined_meth[pre + cn] && sh.file?(cn) && sh.executable?(cn)
command = (pre + cn).gsub(/\W/, "_").sub(/^([0-9])/, '_\1') command = (pre + cn).gsub(/\W/, "_").sub(/^([0-9])/, '_\1')
begin begin
def_system_command(command, sh.expand_path(cn)) def_system_command(command, sh.expand_path(cn))
rescue rescue
Shell.notify "warn: Can't define #{command} path: #{cn}" Shell.notify "warn: Can't define #{command} path: #{cn}"
end end
defined_meth[command] = command defined_meth[command] = command
end end
end end
end end
end end
@ -520,35 +520,35 @@ class Shell
id = id.intern if id.kind_of?(String) id = id.intern if id.kind_of?(String)
name = id.id2name name = id.id2name
if Shell.method_defined?(id) if Shell.method_defined?(id)
Shell.notify "warn: override definition of Shell##{name}." Shell.notify "warn: override definition of Shell##{name}."
Shell.notify "warn: alias Shell##{name} to Shell##{name}_org.\n" Shell.notify "warn: alias Shell##{name} to Shell##{name}_org.\n"
Shell.module_eval "alias #{name}_org #{name}" Shell.module_eval "alias #{name}_org #{name}"
end end
Shell.notify "method added: Shell##{name}.", Shell.debug? Shell.notify "method added: Shell##{name}.", Shell.debug?
Shell.module_eval(%Q[def #{name}(*args, &block) Shell.module_eval(%Q[def #{name}(*args, &block)
begin begin
@command_processor.__send__(:#{name}, *args, &block) @command_processor.__send__(:#{name}, *args, &block)
rescue Exception rescue Exception
$@.delete_if{|s| /:in `__getobj__'$/ =~ s} #` $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
$@.delete_if{|s| /^\\(eval\\):/ =~ s} $@.delete_if{|s| /^\\(eval\\):/ =~ s}
raise raise
end end
end], __FILE__, __LINE__) end], __FILE__, __LINE__)
if Shell::Filter.method_defined?(id) if Shell::Filter.method_defined?(id)
Shell.notify "warn: override definition of Shell::Filter##{name}." Shell.notify "warn: override definition of Shell::Filter##{name}."
Shell.notify "warn: alias Shell##{name} to Shell::Filter##{name}_org." Shell.notify "warn: alias Shell##{name} to Shell::Filter##{name}_org."
Filter.module_eval "alias #{name}_org #{name}" Filter.module_eval "alias #{name}_org #{name}"
end end
Shell.notify "method added: Shell::Filter##{name}.", Shell.debug? Shell.notify "method added: Shell::Filter##{name}.", Shell.debug?
Filter.module_eval(%Q[def #{name}(*args, &block) Filter.module_eval(%Q[def #{name}(*args, &block)
begin begin
self | @shell.__send__(:#{name}, *args, &block) self | @shell.__send__(:#{name}, *args, &block)
rescue Exception rescue Exception
$@.delete_if{|s| /:in `__getobj__'$/ =~ s} #` $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
$@.delete_if{|s| /^\\(eval\\):/ =~ s} $@.delete_if{|s| /^\\(eval\\):/ =~ s}
raise raise
end end
end], __FILE__, __LINE__) end], __FILE__, __LINE__)
end end
@ -557,35 +557,35 @@ class Shell
# #
def self.install_builtin_commands def self.install_builtin_commands
# method related File. # method related File.
# (exclude open/foreach/unlink) # (exclude open/foreach/unlink)
normal_delegation_file_methods = [ normal_delegation_file_methods = [
["atime", ["FILENAME"]], ["atime", ["FILENAME"]],
["basename", ["fn", "*opts"]], ["basename", ["fn", "*opts"]],
["chmod", ["mode", "*FILENAMES"]], ["chmod", ["mode", "*FILENAMES"]],
["chown", ["owner", "group", "*FILENAME"]], ["chown", ["owner", "group", "*FILENAME"]],
["ctime", ["FILENAMES"]], ["ctime", ["FILENAMES"]],
["delete", ["*FILENAMES"]], ["delete", ["*FILENAMES"]],
["dirname", ["FILENAME"]], ["dirname", ["FILENAME"]],
["ftype", ["FILENAME"]], ["ftype", ["FILENAME"]],
["join", ["*items"]], ["join", ["*items"]],
["link", ["FILENAME_O", "FILENAME_N"]], ["link", ["FILENAME_O", "FILENAME_N"]],
["lstat", ["FILENAME"]], ["lstat", ["FILENAME"]],
["mtime", ["FILENAME"]], ["mtime", ["FILENAME"]],
["readlink", ["FILENAME"]], ["readlink", ["FILENAME"]],
["rename", ["FILENAME_FROM", "FILENAME_TO"]], ["rename", ["FILENAME_FROM", "FILENAME_TO"]],
# ["size", ["FILENAME"]], # ["size", ["FILENAME"]],
["split", ["pathname"]], ["split", ["pathname"]],
["stat", ["FILENAME"]], ["stat", ["FILENAME"]],
["symlink", ["FILENAME_O", "FILENAME_N"]], ["symlink", ["FILENAME_O", "FILENAME_N"]],
["truncate", ["FILENAME", "length"]], ["truncate", ["FILENAME", "length"]],
["utime", ["atime", "mtime", "*FILENAMES"]]] ["utime", ["atime", "mtime", "*FILENAMES"]]]
def_builtin_commands(File, normal_delegation_file_methods) def_builtin_commands(File, normal_delegation_file_methods)
alias_method :rm, :delete alias_method :rm, :delete
# method related FileTest # method related FileTest
def_builtin_commands(FileTest, def_builtin_commands(FileTest,
FileTest.singleton_methods(false).collect{|m| [m, ["FILENAME"]]}) FileTest.singleton_methods(false).collect{|m| [m, ["FILENAME"]]})
end end

View File

@ -1,8 +1,8 @@
# #
# shell/error.rb - # shell/error.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #

View File

@ -1,8 +1,8 @@
# #
# shell/filter.rb - # shell/filter.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -19,8 +19,8 @@ class Shell
include Enumerable include Enumerable
def initialize(sh) def initialize(sh)
@shell = sh # parent shell @shell = sh # parent shell
@input = nil # input filter @input = nil # input filter
end end
attr_reader :input attr_reader :input
@ -32,52 +32,52 @@ class Shell
def each(rs = nil) def each(rs = nil)
rs = @shell.record_separator unless rs rs = @shell.record_separator unless rs
if @input if @input
@input.each(rs){|l| yield l} @input.each(rs){|l| yield l}
end end
end end
def < (src) def < (src)
case src case src
when String when String
cat = Cat.new(@shell, src) cat = Cat.new(@shell, src)
cat | self cat | self
when IO when IO
self.input = src self.input = src
self self
else else
Shell.Fail Error::CantApplyMethod, "<", to.class Shell.Fail Error::CantApplyMethod, "<", to.class
end end
end end
def > (to) def > (to)
case to case to
when String when String
dst = @shell.open(to, "w") dst = @shell.open(to, "w")
begin begin
each(){|l| dst << l} each(){|l| dst << l}
ensure ensure
dst.close dst.close
end end
when IO when IO
each(){|l| to << l} each(){|l| to << l}
else else
Shell.Fail Error::CantApplyMethod, ">", to.class Shell.Fail Error::CantApplyMethod, ">", to.class
end end
self self
end end
def >> (to) def >> (to)
begin begin
Shell.cd(@shell.pwd).append(to, self) Shell.cd(@shell.pwd).append(to, self)
rescue CantApplyMethod rescue CantApplyMethod
Shell.Fail Error::CantApplyMethod, ">>", to.class Shell.Fail Error::CantApplyMethod, ">>", to.class
end end
end end
def | (filter) def | (filter)
filter.input = self filter.input = self
if active? if active?
@shell.process_controller.start_job filter @shell.process_controller.start_job filter
end end
filter filter
end end
@ -100,9 +100,9 @@ class Shell
def inspect def inspect
if @shell.debug.kind_of?(Integer) && @shell.debug > 2 if @shell.debug.kind_of?(Integer) && @shell.debug > 2
super super
else else
to_s to_s
end end
end end
end end

View File

@ -1,8 +1,8 @@
# #
# shell/process-controller.rb - # shell/process-controller.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -27,60 +27,60 @@ class Shell
extend Forwardable extend Forwardable
def_delegator("@ProcessControllersMonitor", def_delegator("@ProcessControllersMonitor",
"synchronize", "process_controllers_exclusive") "synchronize", "process_controllers_exclusive")
def active_process_controllers def active_process_controllers
process_controllers_exclusive do process_controllers_exclusive do
@ProcessControllers.dup @ProcessControllers.dup
end end
end end
def activate(pc) def activate(pc)
process_controllers_exclusive do process_controllers_exclusive do
@ProcessControllers[pc] ||= 0 @ProcessControllers[pc] ||= 0
@ProcessControllers[pc] += 1 @ProcessControllers[pc] += 1
end end
end end
def inactivate(pc) def inactivate(pc)
process_controllers_exclusive do process_controllers_exclusive do
if @ProcessControllers[pc] if @ProcessControllers[pc]
if (@ProcessControllers[pc] -= 1) == 0 if (@ProcessControllers[pc] -= 1) == 0
@ProcessControllers.delete(pc) @ProcessControllers.delete(pc)
@ProcessControllersCV.signal @ProcessControllersCV.signal
end end
end end
end end
end end
def each_active_object def each_active_object
process_controllers_exclusive do process_controllers_exclusive do
for ref in @ProcessControllers.keys for ref in @ProcessControllers.keys
yield ref yield ref
end end
end end
end end
def block_output_synchronize(&b) def block_output_synchronize(&b)
@BlockOutputMonitor.synchronize(&b) @BlockOutputMonitor.synchronize(&b)
end end
def wait_to_finish_all_process_controllers def wait_to_finish_all_process_controllers
process_controllers_exclusive do process_controllers_exclusive do
while !@ProcessControllers.empty? while !@ProcessControllers.empty?
Shell::notify("Process finishing, but active shell exists", Shell::notify("Process finishing, but active shell exists",
"You can use Shell#transact or Shell#check_point for more safe execution.") "You can use Shell#transact or Shell#check_point for more safe execution.")
if Shell.debug? if Shell.debug?
for pc in @ProcessControllers.keys for pc in @ProcessControllers.keys
Shell::notify(" Not finished jobs in "+pc.shell.to_s) Shell::notify(" Not finished jobs in "+pc.shell.to_s)
for com in pc.jobs for com in pc.jobs
com.notify(" Jobs: %id") com.notify(" Jobs: %id")
end end
end end
end end
@ProcessControllersCV.wait(@ProcessControllersMonitor) @ProcessControllersCV.wait(@ProcessControllersMonitor)
end end
end end
end end
end end
@ -105,8 +105,8 @@ class Shell
def jobs def jobs
jobs = [] jobs = []
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
jobs.concat @waiting_jobs jobs.concat @waiting_jobs
jobs.concat @active_jobs jobs.concat @active_jobs
end end
jobs jobs
end end
@ -121,115 +121,115 @@ class Shell
def jobs_exist? def jobs_exist?
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
@active_jobs.empty? or @waiting_jobs.empty? @active_jobs.empty? or @waiting_jobs.empty?
end end
end end
def active_jobs_exist? def active_jobs_exist?
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
@active_jobs.empty? @active_jobs.empty?
end end
end end
def waiting_jobs_exist? def waiting_jobs_exist?
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
@waiting_jobs.empty? @waiting_jobs.empty?
end end
end end
# schedule a command # schedule a command
def add_schedule(command) def add_schedule(command)
@jobs_sync.synchronize(:EX) do @jobs_sync.synchronize(:EX) do
ProcessController.activate(self) ProcessController.activate(self)
if @active_jobs.empty? if @active_jobs.empty?
start_job command start_job command
else else
@waiting_jobs.push(command) @waiting_jobs.push(command)
end end
end end
end end
# start a job # start a job
def start_job(command = nil) def start_job(command = nil)
@jobs_sync.synchronize(:EX) do @jobs_sync.synchronize(:EX) do
if command if command
return if command.active? return if command.active?
@waiting_jobs.delete command @waiting_jobs.delete command
else else
command = @waiting_jobs.shift command = @waiting_jobs.shift
# command.notify "job(%id) pre-start.", @shell.debug? # command.notify "job(%id) pre-start.", @shell.debug?
return unless command return unless command
end end
@active_jobs.push command @active_jobs.push command
command.start command.start
# command.notify "job(%id) post-start.", @shell.debug? # command.notify "job(%id) post-start.", @shell.debug?
# start all jobs that input from the job # start all jobs that input from the job
for job in @waiting_jobs.dup for job in @waiting_jobs.dup
start_job(job) if job.input == command start_job(job) if job.input == command
end end
# command.notify "job(%id) post2-start.", @shell.debug? # command.notify "job(%id) post2-start.", @shell.debug?
end end
end end
def waiting_job?(job) def waiting_job?(job)
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
@waiting_jobs.include?(job) @waiting_jobs.include?(job)
end end
end end
def active_job?(job) def active_job?(job)
@jobs_sync.synchronize(:SH) do @jobs_sync.synchronize(:SH) do
@active_jobs.include?(job) @active_jobs.include?(job)
end end
end end
# terminate a job # terminate a job
def terminate_job(command) def terminate_job(command)
@jobs_sync.synchronize(:EX) do @jobs_sync.synchronize(:EX) do
@active_jobs.delete command @active_jobs.delete command
ProcessController.inactivate(self) ProcessController.inactivate(self)
if @active_jobs.empty? if @active_jobs.empty?
command.notify("start_job in terminate_job(%id)", Shell::debug?) command.notify("start_job in terminate_job(%id)", Shell::debug?)
start_job start_job
end end
end end
end end
# kill a job # kill a job
def kill_job(sig, command) def kill_job(sig, command)
@jobs_sync.synchronize(:EX) do @jobs_sync.synchronize(:EX) do
if @waiting_jobs.delete command if @waiting_jobs.delete command
ProcessController.inactivate(self) ProcessController.inactivate(self)
return return
elsif @active_jobs.include?(command) elsif @active_jobs.include?(command)
begin begin
r = command.kill(sig) r = command.kill(sig)
ProcessController.inactivate(self) ProcessController.inactivate(self)
rescue rescue
print "Shell: Warn: $!\n" if @shell.verbose? print "Shell: Warn: $!\n" if @shell.verbose?
return nil return nil
end end
@active_jobs.delete command @active_jobs.delete command
r r
end end
end end
end end
# wait for all jobs to terminate # wait for all jobs to terminate
def wait_all_jobs_execution def wait_all_jobs_execution
@job_monitor.synchronize do @job_monitor.synchronize do
begin begin
while !jobs.empty? while !jobs.empty?
@job_condition.wait(@job_monitor) @job_condition.wait(@job_monitor)
for job in jobs for job in jobs
job.notify("waiting job(%id)", Shell::debug?) job.notify("waiting job(%id)", Shell::debug?)
end end
end end
ensure ensure
redo unless jobs.empty? redo unless jobs.empty?
end end
end end
end end
@ -244,73 +244,73 @@ class Shell
pid_cv = ConditionVariable.new pid_cv = ConditionVariable.new
Thread.start do Thread.start do
ProcessController.block_output_synchronize do ProcessController.block_output_synchronize do
STDOUT.flush STDOUT.flush
ProcessController.each_active_object do |pc| ProcessController.each_active_object do |pc|
for jobs in pc.active_jobs for jobs in pc.active_jobs
jobs.flush jobs.flush
end end
end end
pid = fork { pid = fork {
Thread.list.each do |th| Thread.list.each do |th|
# th.kill unless [Thread.main, Thread.current].include?(th) # th.kill unless [Thread.main, Thread.current].include?(th)
th.kill unless Thread.current == th th.kill unless Thread.current == th
end end
STDIN.reopen(pipe_peer_in) STDIN.reopen(pipe_peer_in)
STDOUT.reopen(pipe_peer_out) STDOUT.reopen(pipe_peer_out)
ObjectSpace.each_object(IO) do |io| ObjectSpace.each_object(IO) do |io|
if ![STDIN, STDOUT, STDERR].include?(io) if ![STDIN, STDOUT, STDERR].include?(io)
io.close unless io.closed? io.close unless io.closed?
end end
end end
yield yield
} }
end end
pid_cv.signal pid_cv.signal
pipe_peer_in.close pipe_peer_in.close
pipe_peer_out.close pipe_peer_out.close
command.notify "job(%name:##{pid}) start", @shell.debug? command.notify "job(%name:##{pid}) start", @shell.debug?
begin begin
_pid = nil _pid = nil
command.notify("job(%id) start to waiting finish.", @shell.debug?) command.notify("job(%id) start to waiting finish.", @shell.debug?)
_pid = Process.waitpid(pid, nil) _pid = Process.waitpid(pid, nil)
rescue Errno::ECHILD rescue Errno::ECHILD
command.notify "warn: job(%id) was done already waitpid." command.notify "warn: job(%id) was done already waitpid."
_pid = true _pid = true
# rescue # rescue
# STDERR.puts $! # STDERR.puts $!
ensure ensure
command.notify("Job(%id): Wait to finish when Process finished.", @shell.debug?) command.notify("Job(%id): Wait to finish when Process finished.", @shell.debug?)
# when the process ends, wait until the command terminates # when the process ends, wait until the command terminates
if USING_AT_EXIT_WHEN_PROCESS_EXIT or _pid if USING_AT_EXIT_WHEN_PROCESS_EXIT or _pid
else else
command.notify("notice: Process finishing...", command.notify("notice: Process finishing...",
"wait for Job[%id] to finish.", "wait for Job[%id] to finish.",
"You can use Shell#transact or Shell#check_point for more safe execution.") "You can use Shell#transact or Shell#check_point for more safe execution.")
redo redo
end end
# command.notify "job(%id) pre-pre-finish.", @shell.debug? # command.notify "job(%id) pre-pre-finish.", @shell.debug?
@job_monitor.synchronize do @job_monitor.synchronize do
# command.notify "job(%id) pre-finish.", @shell.debug? # command.notify "job(%id) pre-finish.", @shell.debug?
terminate_job(command) terminate_job(command)
# command.notify "job(%id) pre-finish2.", @shell.debug? # command.notify "job(%id) pre-finish2.", @shell.debug?
@job_condition.signal @job_condition.signal
command.notify "job(%id) finish.", @shell.debug? command.notify "job(%id) finish.", @shell.debug?
end end
end end
end end
pid_mutex.synchronize do pid_mutex.synchronize do
while !pid while !pid
pid_cv.wait(pid_mutex) pid_cv.wait(pid_mutex)
end end
end end
return pid, pipe_me_in, pipe_me_out return pid, pipe_me_in, pipe_me_out

View File

@ -1,8 +1,8 @@
# #
# shell/system-command.rb - # shell/system-command.rb -
# $Release Version: 0.7 $ # $Release Version: 0.7 $
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #
@ -15,7 +15,7 @@ class Shell
class SystemCommand < Filter class SystemCommand < Filter
def initialize(sh, command, *opts) def initialize(sh, command, *opts)
if t = opts.find{|opt| !opt.kind_of?(String) && opt.class} if t = opts.find{|opt| !opt.kind_of?(String) && opt.class}
Shell.Fail Error::TypeError, t.class, "String" Shell.Fail Error::TypeError, t.class, "String"
end end
super(sh) super(sh)
@command = command @command = command
@ -41,7 +41,7 @@ class Shell
def input=(inp) def input=(inp)
super super
if active? if active?
start_export start_export
end end
end end
@ -49,12 +49,12 @@ class Shell
notify([@command, *@opts].join(" ")) notify([@command, *@opts].join(" "))
@pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) { @pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) {
Dir.chdir @shell.pwd Dir.chdir @shell.pwd
$0 = @command $0 = @command
exec(@command, *@opts) exec(@command, *@opts)
} }
if @input if @input
start_export start_export
end end
start_import start_import
end end
@ -65,18 +65,18 @@ class Shell
def terminate def terminate
begin begin
@pipe_in.close @pipe_in.close
rescue IOError rescue IOError
end end
begin begin
@pipe_out.close @pipe_out.close
rescue IOError rescue IOError
end end
end end
def kill(sig) def kill(sig)
if @pid if @pid
Process.kill(sig, @pid) Process.kill(sig, @pid)
end end
end end
@ -85,24 +85,24 @@ class Shell
rs = @shell.record_separator unless rs rs = @shell.record_separator unless rs
_eop = true _eop = true
Thread.start { Thread.start {
begin begin
while l = @pipe_in.gets while l = @pipe_in.gets
@input_queue.push l @input_queue.push l
end end
_eop = false _eop = false
rescue Errno::EPIPE rescue Errno::EPIPE
_eop = false _eop = false
ensure ensure
if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop
notify("warn: Process finishing...", notify("warn: Process finishing...",
"wait for Job[%id] to finish pipe importing.", "wait for Job[%id] to finish pipe importing.",
"You can use Shell#transact or Shell#check_point for more safe execution.") "You can use Shell#transact or Shell#check_point for more safe execution.")
redo redo
end end
notify "job(%id}) close imp-pipe.", @shell.debug? notify "job(%id}) close imp-pipe.", @shell.debug?
@input_queue.push :EOF @input_queue.push :EOF
@pipe_in.close @pipe_in.close
end end
} }
end end
@ -110,49 +110,49 @@ class Shell
notify "job(%id) start exp-pipe.", @shell.debug? notify "job(%id) start exp-pipe.", @shell.debug?
_eop = true _eop = true
Thread.start{ Thread.start{
begin begin
@input.each do |l| @input.each do |l|
ProcessController::block_output_synchronize do ProcessController::block_output_synchronize do
@pipe_out.print l @pipe_out.print l
end end
end end
_eop = false _eop = false
rescue Errno::EPIPE, Errno::EIO rescue Errno::EPIPE, Errno::EIO
_eop = false _eop = false
ensure ensure
if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop
notify("shell: warn: Process finishing...", notify("shell: warn: Process finishing...",
"wait for Job(%id) to finish pipe exporting.", "wait for Job(%id) to finish pipe exporting.",
"You can use Shell#transact or Shell#check_point for more safe execution.") "You can use Shell#transact or Shell#check_point for more safe execution.")
redo redo
end end
notify "job(%id) close exp-pipe.", @shell.debug? notify "job(%id) close exp-pipe.", @shell.debug?
@pipe_out.close @pipe_out.close
end end
} }
end end
alias super_each each alias super_each each
def each(rs = nil) def each(rs = nil)
while (l = @input_queue.pop) != :EOF while (l = @input_queue.pop) != :EOF
yield l yield l
end end
end end
# ex) # ex)
# if you wish to output: # if you wish to output:
# "shell: job(#{@command}:#{@pid}) close pipe-out." # "shell: job(#{@command}:#{@pid}) close pipe-out."
# then # then
# mes: "job(%id) close pipe-out." # mes: "job(%id) close pipe-out."
# yorn: Boolean(@shell.debug? or @shell.verbose?) # yorn: Boolean(@shell.debug? or @shell.verbose?)
def notify(*opts, &block) def notify(*opts, &block)
@shell.notify(*opts) do |mes| @shell.notify(*opts) do |mes|
yield mes if iterator? yield mes if iterator?
mes.gsub!("%id", "#{@command}:##{@pid}") mes.gsub!("%id", "#{@command}:##{@pid}")
mes.gsub!("%name", "#{@command}") mes.gsub!("%name", "#{@command}")
mes.gsub!("%pid", "#{@pid}") mes.gsub!("%pid", "#{@pid}")
mes mes
end end
end end
end end

View File

@ -1,8 +1,8 @@
# #
# version.rb - shell version definition file # version.rb - shell version definition file
# $Release Version: 0.7$ # $Release Version: 0.7$
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org) # by Keiju ISHITSUKA(keiju@ruby-lang.org)
# #
# -- # --
# #

View File

@ -1,8 +1,8 @@
# #
# sync.rb - 2 phase lock with counter # sync.rb - 2 phase lock with counter
# $Release Version: 1.0$ # $Release Version: 1.0$
# $Revision$ # $Revision$
# by Keiju ISHITSUKA(keiju@ishitsuka.com) # by Keiju ISHITSUKA(keiju@ishitsuka.com)
# #
# -- # --
# Sync_m, Synchronizer_m # Sync_m, Synchronizer_m
@ -10,8 +10,8 @@
# obj.extend(Sync_m) # obj.extend(Sync_m)
# or # or
# class Foo # class Foo
# include Sync_m # include Sync_m
# : # :
# end # end
# #
# Sync_m#sync_mode # Sync_m#sync_mode
@ -58,17 +58,17 @@ module Sync_m
class UnknownLocker < Err class UnknownLocker < Err
Message = "Thread(%s) not locked." Message = "Thread(%s) not locked."
def UnknownLocker.Fail(th) def UnknownLocker.Fail(th)
super(th.inspect) super(th.inspect)
end end
end end
class LockModeFailer < Err class LockModeFailer < Err
Message = "Unknown lock mode(%s)" Message = "Unknown lock mode(%s)"
def LockModeFailer.Fail(mode) def LockModeFailer.Fail(mode)
if mode.id2name if mode.id2name
mode = id2name mode = id2name
end end
super(mode) super(mode)
end end
end end
end end
@ -100,12 +100,12 @@ module Sync_m
def sync_extend def sync_extend
unless (defined? locked? and unless (defined? locked? and
defined? shared? and defined? shared? and
defined? exclusive? and defined? exclusive? and
defined? lock and defined? lock and
defined? unlock and defined? unlock and
defined? try_lock and defined? try_lock and
defined? synchronize) defined? synchronize)
Sync_m.define_aliases(singleton_class) Sync_m.define_aliases(singleton_class)
end end
sync_initialize sync_initialize
@ -137,17 +137,17 @@ module Sync_m
while true while true
@sync_mutex.synchronize do @sync_mutex.synchronize do
if sync_try_lock_sub(m) if sync_try_lock_sub(m)
return self return self
else else
if sync_sh_locker[Thread.current] if sync_sh_locker[Thread.current]
sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]] sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
sync_sh_locker.delete(Thread.current) sync_sh_locker.delete(Thread.current)
else else
sync_waiting.push Thread.current sync_waiting.push Thread.current
end end
@sync_mutex.sleep @sync_mutex.sleep
end end
end end
end end
self self
@ -157,7 +157,7 @@ module Sync_m
wakeup_threads = [] wakeup_threads = []
@sync_mutex.synchronize do @sync_mutex.synchronize do
if sync_mode == UN if sync_mode == UN
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
end end
m = sync_mode if m == EX and sync_mode == SH m = sync_mode if m == EX and sync_mode == SH
@ -165,51 +165,51 @@ module Sync_m
runnable = false runnable = false
case m case m
when UN when UN
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
when EX when EX
if sync_ex_locker == Thread.current if sync_ex_locker == Thread.current
if (self.sync_ex_count = sync_ex_count - 1) == 0 if (self.sync_ex_count = sync_ex_count - 1) == 0
self.sync_ex_locker = nil self.sync_ex_locker = nil
if sync_sh_locker.include?(Thread.current) if sync_sh_locker.include?(Thread.current)
self.sync_mode = SH self.sync_mode = SH
else else
self.sync_mode = UN self.sync_mode = UN
end end
runnable = true runnable = true
end end
else else
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
end end
when SH when SH
if (count = sync_sh_locker[Thread.current]).nil? if (count = sync_sh_locker[Thread.current]).nil?
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
else else
if (sync_sh_locker[Thread.current] = count - 1) == 0 if (sync_sh_locker[Thread.current] = count - 1) == 0
sync_sh_locker.delete(Thread.current) sync_sh_locker.delete(Thread.current)
if sync_sh_locker.empty? and sync_ex_count == 0 if sync_sh_locker.empty? and sync_ex_count == 0
self.sync_mode = UN self.sync_mode = UN
runnable = true runnable = true
end end
end end
end end
end end
if runnable if runnable
if sync_upgrade_waiting.size > 0 if sync_upgrade_waiting.size > 0
th, count = sync_upgrade_waiting.shift th, count = sync_upgrade_waiting.shift
sync_sh_locker[th] = count sync_sh_locker[th] = count
th.wakeup th.wakeup
wakeup_threads.push th wakeup_threads.push th
else else
wait = sync_waiting wait = sync_waiting
self.sync_waiting = [] self.sync_waiting = []
for th in wait for th in wait
th.wakeup th.wakeup
wakeup_threads.push th wakeup_threads.push th
end end
end end
end end
end end
for th in wakeup_threads for th in wakeup_threads
@ -263,34 +263,34 @@ module Sync_m
when SH when SH
case sync_mode case sync_mode
when UN when UN
self.sync_mode = m self.sync_mode = m
sync_sh_locker[Thread.current] = 1 sync_sh_locker[Thread.current] = 1
ret = true ret = true
when SH when SH
count = 0 unless count = sync_sh_locker[Thread.current] count = 0 unless count = sync_sh_locker[Thread.current]
sync_sh_locker[Thread.current] = count + 1 sync_sh_locker[Thread.current] = count + 1
ret = true ret = true
when EX when EX
# in EX mode, lock will upgrade to EX lock # in EX mode, lock will upgrade to EX lock
if sync_ex_locker == Thread.current if sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1 self.sync_ex_count = sync_ex_count + 1
ret = true ret = true
else else
ret = false ret = false
end end
end end
when EX when EX
if sync_mode == UN or if sync_mode == UN or
sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
self.sync_mode = m self.sync_mode = m
self.sync_ex_locker = Thread.current self.sync_ex_locker = Thread.current
self.sync_ex_count = 1 self.sync_ex_count = 1
ret = true ret = true
elsif sync_mode == EX && sync_ex_locker == Thread.current elsif sync_mode == EX && sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1 self.sync_ex_count = sync_ex_count + 1
ret = true ret = true
else else
ret = false ret = false
end end
else else
Err::LockModeFailer.Fail mode Err::LockModeFailer.Fail mode

View File

@ -165,7 +165,7 @@ class Tempfile < DelegateClass(File)
__setobj__(@tmpfile) __setobj__(@tmpfile)
end end
def _close # :nodoc: def _close # :nodoc:
@tmpfile.close if @tmpfile @tmpfile.close if @tmpfile
@tmpfile = nil @tmpfile = nil
@data[1] = nil if @data @data[1] = nil if @data
@ -316,13 +316,13 @@ class Tempfile < DelegateClass(File)
tempfile = new(*args) tempfile = new(*args)
if block_given? if block_given?
begin begin
yield(tempfile) yield(tempfile)
ensure ensure
tempfile.close tempfile.close
end end
else else
tempfile tempfile
end end
end end

View File

@ -1,6 +1,6 @@
# #
# thread.rb - thread support classes # thread.rb - thread support classes
# by Yukihiro Matsumoto <matz@netlab.co.jp> # by Yukihiro Matsumoto <matz@netlab.co.jp>
# #
# Copyright (C) 2001 Yukihiro Matsumoto # Copyright (C) 2001 Yukihiro Matsumoto
# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
@ -144,7 +144,7 @@ class Queue
def initialize def initialize
@que = [] @que = []
@waiting = [] @waiting = []
@que.taint # enable tainted comunication @que.taint # enable tainted comunication
@waiting.taint @waiting.taint
self.taint self.taint
@mutex = Mutex.new @mutex = Mutex.new
@ -252,7 +252,7 @@ class SizedQueue < Queue
raise ArgumentError, "queue size must be positive" unless max > 0 raise ArgumentError, "queue size must be positive" unless max > 0
@max = max @max = max
@queue_wait = [] @queue_wait = []
@queue_wait.taint # enable tainted comunication @queue_wait.taint # enable tainted comunication
super() super()
end end
@ -278,12 +278,12 @@ class SizedQueue < Queue
} }
if diff if diff
diff.times do diff.times do
begin begin
t = @queue_wait.shift t = @queue_wait.shift
t.run if t t.run if t
rescue ThreadError rescue ThreadError
retry retry
end end
end end
end end
max max

View File

@ -1,8 +1,8 @@
# #
# thwait.rb - thread synchronization class # thwait.rb - thread synchronization class
# $Release Version: 0.9 $ # $Release Version: 0.9 $
# $Revision: 1.3 $ # $Revision: 1.3 $
# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd.) # by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd.)
require "thread.rb" require "thread.rb"
require "e2mmap.rb" require "e2mmap.rb"
@ -39,7 +39,7 @@ class ThreadsWait
tw = ThreadsWait.new(*threads) tw = ThreadsWait.new(*threads)
if block_given? if block_given?
tw.all_waits do |th| tw.all_waits do |th|
yield th yield th
end end
else else
tw.all_waits tw.all_waits
@ -91,11 +91,11 @@ class ThreadsWait
@threads.concat threads @threads.concat threads
for th in threads for th in threads
Thread.start(th) do |t| Thread.start(th) do |t|
begin begin
t.join t.join
ensure ensure
@wait_queue.push t @wait_queue.push t
end end
end end
end end
end end

View File

@ -23,10 +23,10 @@ class Dir
tmp = @@systmpdir tmp = @@systmpdir
else else
for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp'] for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
if dir and stat = File.stat(dir) and stat.directory? and stat.writable? if dir and stat = File.stat(dir) and stat.directory? and stat.writable?
tmp = dir tmp = dir
break break
end rescue nil end rescue nil
end end
File.expand_path(tmp) File.expand_path(tmp)
end end

View File

@ -130,9 +130,9 @@ class Tracer
if block_given? if block_given?
on on
begin begin
yield yield
ensure ensure
off off
end end
else else
set_trace_func method(:trace_func).to_proc set_trace_func method(:trace_func).to_proc
@ -160,14 +160,14 @@ class Tracer
unless list = SCRIPT_LINES__[file] unless list = SCRIPT_LINES__[file]
begin begin
f = File::open(file) f = File::open(file)
begin begin
SCRIPT_LINES__[file] = list = f.readlines SCRIPT_LINES__[file] = list = f.readlines
ensure ensure
f.close f.close
end end
rescue rescue
SCRIPT_LINES__[file] = list = [] SCRIPT_LINES__[file] = list = []
end end
end end
@ -198,19 +198,19 @@ class Tracer
Tracer::stdout_mutex.synchronize do Tracer::stdout_mutex.synchronize do
if EVENT_SYMBOL[event] if EVENT_SYMBOL[event]
stdout.printf("<%d>", $$) if Tracer::display_process_id? stdout.printf("<%d>", $$) if Tracer::display_process_id?
stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id? stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id?
if line == 0 if line == 0
source = "?\n" source = "?\n"
else else
source = get_line(file, line) source = get_line(file, line)
end end
printf("%s:%d:%s:%s: %s", printf("%s:%d:%s:%s: %s",
file, file,
line, line,
klass || '', klass || '',
EVENT_SYMBOL[event], EVENT_SYMBOL[event],
source) source)
end end
end end

View File

@ -69,9 +69,9 @@ end
# #
# ruby -run -e cp -- [OPTION] SOURCE DEST # ruby -run -e cp -- [OPTION] SOURCE DEST
# #
# -p preserve file attributes if possible # -p preserve file attributes if possible
# -r copy recursively # -r copy recursively
# -v verbose # -v verbose
# #
def cp def cp
@ -90,9 +90,9 @@ end
# #
# ruby -run -e ln -- [OPTION] TARGET LINK_NAME # ruby -run -e ln -- [OPTION] TARGET LINK_NAME
# #
# -s make symbolic links instead of hard links # -s make symbolic links instead of hard links
# -f remove existing destination files # -f remove existing destination files
# -v verbose # -v verbose
# #
def ln def ln
@ -111,7 +111,7 @@ end
# #
# ruby -run -e mv -- [OPTION] SOURCE DEST # ruby -run -e mv -- [OPTION] SOURCE DEST
# #
# -v verbose # -v verbose
# #
def mv def mv
@ -127,9 +127,9 @@ end
# #
# ruby -run -e rm -- [OPTION] FILE # ruby -run -e rm -- [OPTION] FILE
# #
# -f ignore nonexistent files # -f ignore nonexistent files
# -r remove the contents of directories recursively # -r remove the contents of directories recursively
# -v verbose # -v verbose
# #
def rm def rm
@ -146,8 +146,8 @@ end
# #
# ruby -run -e mkdir -- [OPTION] DIR # ruby -run -e mkdir -- [OPTION] DIR
# #
# -p no error if existing, make parent directories as needed # -p no error if existing, make parent directories as needed
# -v verbose # -v verbose
# #
def mkdir def mkdir
@ -163,8 +163,8 @@ end
# #
# ruby -run -e rmdir -- [OPTION] DIR # ruby -run -e rmdir -- [OPTION] DIR
# #
# -p remove DIRECTORY and its ancestors. # -p remove DIRECTORY and its ancestors.
# -v verbose # -v verbose
# #
def rmdir def rmdir
@ -179,10 +179,10 @@ end
# #
# ruby -run -e install -- [OPTION] SOURCE DEST # ruby -run -e install -- [OPTION] SOURCE DEST
# #
# -p apply access/modification times of SOURCE files to # -p apply access/modification times of SOURCE files to
# corresponding destination files # corresponding destination files
# -m set permission mode (as in chmod), instead of 0755 # -m set permission mode (as in chmod), instead of 0755
# -v verbose # -v verbose
# #
def install def install
@ -200,7 +200,7 @@ end
# #
# ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE # ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE
# #
# -v verbose # -v verbose
# #
def chmod def chmod
@ -215,7 +215,7 @@ end
# #
# ruby -run -e touch -- [OPTION] FILE # ruby -run -e touch -- [OPTION] FILE
# #
# -v verbose # -v verbose
# #
def touch def touch
@ -229,9 +229,9 @@ end
# #
# ruby -run -e wait_writable -- [OPTION] FILE # ruby -run -e wait_writable -- [OPTION] FILE
# #
# -n RETRY count to retry # -n RETRY count to retry
# -w SEC each wait time in seconds # -w SEC each wait time in seconds
# -v verbose # -v verbose
# #
def wait_writable def wait_writable
@ -260,15 +260,15 @@ end
# #
# ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION] # ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
# #
# -d ARGS run dir_config # -d ARGS run dir_config
# -h ARGS run have_header # -h ARGS run have_header
# -l ARGS run have_library # -l ARGS run have_library
# -f ARGS run have_func # -f ARGS run have_func
# -v ARGS run have_var # -v ARGS run have_var
# -t ARGS run have_type # -t ARGS run have_type
# -m ARGS run have_macro # -m ARGS run have_macro
# -c ARGS run have_const # -c ARGS run have_const
# --vendor install to vendor_ruby # --vendor install to vendor_ruby
# #
def mkmf def mkmf
@ -337,11 +337,11 @@ def help
all = argv.empty? all = argv.empty?
open(__FILE__) do |me| open(__FILE__) do |me|
while me.gets("##\n") while me.gets("##\n")
if help = me.gets("\n\n") if help = me.gets("\n\n")
if all or argv.delete help[/-e \w+/].sub(/-e /, "") if all or argv.delete help[/-e \w+/].sub(/-e /, "")
print help.gsub(/^# ?/, "") print help.gsub(/^# ?/, "")
end end
end end
end end
end end
end end

View File

@ -120,71 +120,71 @@ module URI
def split(uri) def split(uri)
case uri case uri
when '' when ''
# null uri # null uri
when @regexp[:ABS_URI] when @regexp[:ABS_URI]
scheme, opaque, userinfo, host, port, scheme, opaque, userinfo, host, port,
registry, path, query, fragment = $~[1..-1] registry, path, query, fragment = $~[1..-1]
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
# absoluteURI = scheme ":" ( hier_part | opaque_part ) # absoluteURI = scheme ":" ( hier_part | opaque_part )
# hier_part = ( net_path | abs_path ) [ "?" query ] # hier_part = ( net_path | abs_path ) [ "?" query ]
# opaque_part = uric_no_slash *uric # opaque_part = uric_no_slash *uric
# abs_path = "/" path_segments # abs_path = "/" path_segments
# net_path = "//" authority [ abs_path ] # net_path = "//" authority [ abs_path ]
# authority = server | reg_name # authority = server | reg_name
# server = [ [ userinfo "@" ] hostport ] # server = [ [ userinfo "@" ] hostport ]
if !scheme if !scheme
raise InvalidURIError, raise InvalidURIError,
"bad URI(absolute but no scheme): #{uri}" "bad URI(absolute but no scheme): #{uri}"
end end
if !opaque && (!path && (!host && !registry)) if !opaque && (!path && (!host && !registry))
raise InvalidURIError, raise InvalidURIError,
"bad URI(absolute but no path): #{uri}" "bad URI(absolute but no path): #{uri}"
end end
when @regexp[:REL_URI] when @regexp[:REL_URI]
scheme = nil scheme = nil
opaque = nil opaque = nil
userinfo, host, port, registry, userinfo, host, port, registry,
rel_segment, abs_path, query, fragment = $~[1..-1] rel_segment, abs_path, query, fragment = $~[1..-1]
if rel_segment && abs_path if rel_segment && abs_path
path = rel_segment + abs_path path = rel_segment + abs_path
elsif rel_segment elsif rel_segment
path = rel_segment path = rel_segment
elsif abs_path elsif abs_path
path = abs_path path = abs_path
end end
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
# relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
# net_path = "//" authority [ abs_path ] # net_path = "//" authority [ abs_path ]
# abs_path = "/" path_segments # abs_path = "/" path_segments
# rel_path = rel_segment [ abs_path ] # rel_path = rel_segment [ abs_path ]
# authority = server | reg_name # authority = server | reg_name
# server = [ [ userinfo "@" ] hostport ] # server = [ [ userinfo "@" ] hostport ]
else else
raise InvalidURIError, "bad URI(is not URI?): #{uri}" raise InvalidURIError, "bad URI(is not URI?): #{uri}"
end end
path = '' if !path && !opaque # (see RFC2396 Section 5.2) path = '' if !path && !opaque # (see RFC2396 Section 5.2)
ret = [ ret = [
scheme, scheme,
userinfo, host, port, # X userinfo, host, port, # X
registry, # X registry, # X
path, # Y path, # Y
opaque, # Y opaque, # Y
query, query,
fragment fragment
] ]
return ret return ret
end end
@ -202,22 +202,22 @@ module URI
# #
# == Usage # == Usage
# #
# p = URI::Parser.new # p = URI::Parser.new
# p.parse("ldap://ldap.example.com/dc=example?user=john") # p.parse("ldap://ldap.example.com/dc=example?user=john")
# #=> #<URI::LDAP:0x00000000b9e7e8 URL:ldap://ldap.example.com/dc=example?user=john> # #=> #<URI::LDAP:0x00000000b9e7e8 URL:ldap://ldap.example.com/dc=example?user=john>
# #
def parse(uri) def parse(uri)
scheme, userinfo, host, port, scheme, userinfo, host, port,
registry, path, opaque, query, fragment = self.split(uri) registry, path, opaque, query, fragment = self.split(uri)
if scheme && URI.scheme_list.include?(scheme.upcase) if scheme && URI.scheme_list.include?(scheme.upcase)
URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port, URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
registry, path, opaque, query, registry, path, opaque, query,
fragment, self) fragment, self)
else else
Generic.new(scheme, userinfo, host, port, Generic.new(scheme, userinfo, host, port,
registry, path, opaque, query, registry, path, opaque, query,
fragment, self) fragment, self)
end end
end end
@ -239,9 +239,9 @@ module URI
# #
# :call-seq: # :call-seq:
# extract( str ) # extract( str )
# extract( str, schemes ) # extract( str, schemes )
# extract( str, schemes ) {|item| block } # extract( str, schemes ) {|item| block }
# #
# == Args # == Args
# #
@ -260,12 +260,12 @@ module URI
# #
def extract(str, schemes = nil, &block) def extract(str, schemes = nil, &block)
if block_given? if block_given?
str.scan(make_regexp(schemes)) { yield $& } str.scan(make_regexp(schemes)) { yield $& }
nil nil
else else
result = [] result = []
str.scan(make_regexp(schemes)) { result.push $& } str.scan(make_regexp(schemes)) { result.push $& }
result result
end end
end end
@ -273,16 +273,16 @@ module URI
# unless +schemes+ is provided. Then it is a Regexp.union with self.pattern[:X_ABS_URI] # unless +schemes+ is provided. Then it is a Regexp.union with self.pattern[:X_ABS_URI]
def make_regexp(schemes = nil) def make_regexp(schemes = nil)
unless schemes unless schemes
@regexp[:ABS_URI_REF] @regexp[:ABS_URI_REF]
else else
/(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
end end
end end
# #
# :call-seq: # :call-seq:
# escape( str ) # escape( str )
# escape( str, unsafe ) # escape( str, unsafe )
# #
# == Args # == Args
# #
@ -313,8 +313,8 @@ module URI
# #
# :call-seq: # :call-seq:
# unescape( str ) # unescape( str )
# unescape( str, unsafe ) # unescape( str, unsafe )
# #
# == Args # == Args
# #
@ -365,7 +365,7 @@ module URI
# hostname = *( domainlabel "." ) toplabel [ "." ] # hostname = *( domainlabel "." ) toplabel [ "." ]
# reg-name = *( unreserved / pct-encoded / sub-delims ) # RFC3986 # reg-name = *( unreserved / pct-encoded / sub-delims ) # RFC3986
unless hostname unless hostname
ret[:HOSTNAME] = hostname = "(?:[a-zA-Z0-9\\-.]|%\\h\\h)+" ret[:HOSTNAME] = hostname = "(?:[a-zA-Z0-9\\-.]|%\\h\\h)+"
end end
# RFC 2373, APPENDIX B: # RFC 2373, APPENDIX B:

View File

@ -174,7 +174,7 @@ module URI
path, opaque, path, opaque,
query, query,
fragment, fragment,
parser = DEFAULT_PARSER, parser = DEFAULT_PARSER,
arg_check = false) arg_check = false)
@scheme = nil @scheme = nil
@user = nil @user = nil
@ -1321,11 +1321,13 @@ module URI
self.query, self.fragment, parser) self.query, self.fragment, parser)
if rel.userinfo != oth.userinfo || if rel.userinfo != oth.userinfo ||
rel.host.to_s.downcase != oth.host.to_s.downcase || rel.host.to_s.downcase != oth.host.to_s.downcase ||
rel.port != oth.port rel.port != oth.port
if self.userinfo.nil? && self.host.nil?
return self, self.dup if self.userinfo.nil? && self.host.nil?
end return self, self.dup
end
rel.set_port(nil) if rel.port == oth.default_port rel.set_port(nil) if rel.port == oth.default_port
return rel, rel return rel, rel
end end

View File

@ -3,11 +3,11 @@
# Usage: # Usage:
# foo = Object.new # foo = Object.new
# foo = Object.new # foo = Object.new
# p foo.to_s # original's class # p foo.to_s # original's class
# foo = WeakRef.new(foo) # foo = WeakRef.new(foo)
# p foo.to_s # should be same class # p foo.to_s # should be same class
# ObjectSpace.garbage_collect # ObjectSpace.garbage_collect
# p foo.to_s # should raise exception (recycled) # p foo.to_s # should raise exception (recycled)
require "delegate" require "delegate"
require 'thread' require 'thread'
@ -24,16 +24,16 @@ class WeakRef < Delegator
@@mutex.synchronize { @@mutex.synchronize {
rids = @@id_map[id] rids = @@id_map[id]
if rids if rids
for rid in rids for rid in rids
@@id_rev_map.delete(rid) @@id_rev_map.delete(rid)
end end
@@id_map.delete(id) @@id_map.delete(id)
end end
rid = @@id_rev_map[id] rid = @@id_rev_map[id]
if rid if rid
@@id_rev_map.delete(id) @@id_rev_map.delete(id)
@@id_map[rid].delete(id) @@id_map[rid].delete(id)
@@id_map.delete(rid) if @@id_map[rid].empty? @@id_map.delete(rid) if @@id_map[rid].empty?
end end
} }
} }
@ -71,10 +71,10 @@ end
if __FILE__ == $0 if __FILE__ == $0
# require 'thread' # require 'thread'
foo = Object.new foo = Object.new
p foo.to_s # original's class p foo.to_s # original's class
foo = WeakRef.new(foo) foo = WeakRef.new(foo)
p foo.to_s # should be same class p foo.to_s # should be same class
ObjectSpace.garbage_collect ObjectSpace.garbage_collect
ObjectSpace.garbage_collect ObjectSpace.garbage_collect
p foo.to_s # should raise exception (recycled) p foo.to_s # should raise exception (recycled)
end end

View File

@ -743,7 +743,7 @@ module XMLRPC
end end
alias :on_stag :startElement alias :on_stag :startElement
alias :on_etag :endElement alias :on_etag :endElement
def on_stag_end(name); end def on_stag_end(name); end