[macruby-changes] [4114] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon May 17 18:40:53 PDT 2010


Revision: 4114
          http://trac.macosforge.org/projects/ruby/changeset/4114
Author:   martinlagardette at apple.com
Date:     2010-05-17 18:40:51 -0700 (Mon, 17 May 2010)
Log Message:
-----------
Update library and removing working tags

Modified Paths:
--------------
    MacRuby/trunk/lib/English.rb
    MacRuby/trunk/lib/cgi/cookie.rb
    MacRuby/trunk/lib/cgi/core.rb
    MacRuby/trunk/lib/cgi/html.rb
    MacRuby/trunk/lib/cgi/session/pstore.rb
    MacRuby/trunk/lib/cgi/session.rb
    MacRuby/trunk/lib/cgi/util.rb
    MacRuby/trunk/lib/cgi.rb
    MacRuby/trunk/lib/cmath.rb
    MacRuby/trunk/lib/complex.rb
    MacRuby/trunk/lib/csv.rb
    MacRuby/trunk/lib/date/format.rb
    MacRuby/trunk/lib/date.rb
    MacRuby/trunk/lib/drb/drb.rb
    MacRuby/trunk/lib/drb/eq.rb
    MacRuby/trunk/lib/drb/extserv.rb
    MacRuby/trunk/lib/drb/extservm.rb
    MacRuby/trunk/lib/drb/invokemethod.rb
    MacRuby/trunk/lib/drb/observer.rb
    MacRuby/trunk/lib/drb/ssl.rb
    MacRuby/trunk/lib/drb/timeridconv.rb
    MacRuby/trunk/lib/drb/unix.rb
    MacRuby/trunk/lib/e2mmap.rb
    MacRuby/trunk/lib/erb.rb
    MacRuby/trunk/lib/fileutils.rb
    MacRuby/trunk/lib/find.rb
    MacRuby/trunk/lib/forwardable.rb
    MacRuby/trunk/lib/getoptlong.rb
    MacRuby/trunk/lib/gserver.rb
    MacRuby/trunk/lib/ipaddr.rb
    MacRuby/trunk/lib/logger.rb
    MacRuby/trunk/lib/mathn.rb
    MacRuby/trunk/lib/matrix.rb
    MacRuby/trunk/lib/minitest/autorun.rb
    MacRuby/trunk/lib/minitest/mock.rb
    MacRuby/trunk/lib/minitest/spec.rb
    MacRuby/trunk/lib/minitest/unit.rb
    MacRuby/trunk/lib/mkmf.rb
    MacRuby/trunk/lib/monitor.rb
    MacRuby/trunk/lib/mutex_m.rb
    MacRuby/trunk/lib/net/ftp.rb
    MacRuby/trunk/lib/net/http.rb
    MacRuby/trunk/lib/net/https.rb
    MacRuby/trunk/lib/net/imap.rb
    MacRuby/trunk/lib/net/pop.rb
    MacRuby/trunk/lib/net/protocol.rb
    MacRuby/trunk/lib/net/smtp.rb
    MacRuby/trunk/lib/net/telnet.rb
    MacRuby/trunk/lib/observer.rb
    MacRuby/trunk/lib/open-uri.rb
    MacRuby/trunk/lib/open3.rb
    MacRuby/trunk/lib/optparse.rb
    MacRuby/trunk/lib/pathname.rb
    MacRuby/trunk/lib/pp.rb
    MacRuby/trunk/lib/prettyprint.rb
    MacRuby/trunk/lib/pstore.rb
    MacRuby/trunk/lib/rake/clean.rb
    MacRuby/trunk/lib/rake/gempackagetask.rb
    MacRuby/trunk/lib/rake/loaders/makefile.rb
    MacRuby/trunk/lib/rake/packagetask.rb
    MacRuby/trunk/lib/rake/rdoctask.rb
    MacRuby/trunk/lib/rake/runtest.rb
    MacRuby/trunk/lib/rake/tasklib.rb
    MacRuby/trunk/lib/rake/testtask.rb
    MacRuby/trunk/lib/rake/win32.rb
    MacRuby/trunk/lib/rake.rb
    MacRuby/trunk/lib/rational.rb
    MacRuby/trunk/lib/resolv.rb
    MacRuby/trunk/lib/rexml/attlistdecl.rb
    MacRuby/trunk/lib/rexml/attribute.rb
    MacRuby/trunk/lib/rexml/cdata.rb
    MacRuby/trunk/lib/rexml/child.rb
    MacRuby/trunk/lib/rexml/comment.rb
    MacRuby/trunk/lib/rexml/doctype.rb
    MacRuby/trunk/lib/rexml/document.rb
    MacRuby/trunk/lib/rexml/dtd/entitydecl.rb
    MacRuby/trunk/lib/rexml/dtd/notationdecl.rb
    MacRuby/trunk/lib/rexml/element.rb
    MacRuby/trunk/lib/rexml/encoding.rb
    MacRuby/trunk/lib/rexml/encodings/CP-1252.rb
    MacRuby/trunk/lib/rexml/encodings/ISO-8859-15.rb
    MacRuby/trunk/lib/rexml/encodings/UNILE.rb
    MacRuby/trunk/lib/rexml/encodings/UTF-16.rb
    MacRuby/trunk/lib/rexml/entity.rb
    MacRuby/trunk/lib/rexml/formatters/default.rb
    MacRuby/trunk/lib/rexml/formatters/pretty.rb
    MacRuby/trunk/lib/rexml/formatters/transitive.rb
    MacRuby/trunk/lib/rexml/functions.rb
    MacRuby/trunk/lib/rexml/instruction.rb
    MacRuby/trunk/lib/rexml/namespace.rb
    MacRuby/trunk/lib/rexml/node.rb
    MacRuby/trunk/lib/rexml/output.rb
    MacRuby/trunk/lib/rexml/parent.rb
    MacRuby/trunk/lib/rexml/parseexception.rb
    MacRuby/trunk/lib/rexml/parsers/baseparser.rb
    MacRuby/trunk/lib/rexml/parsers/pullparser.rb
    MacRuby/trunk/lib/rexml/parsers/sax2parser.rb
    MacRuby/trunk/lib/rexml/parsers/streamparser.rb
    MacRuby/trunk/lib/rexml/parsers/treeparser.rb
    MacRuby/trunk/lib/rexml/parsers/xpathparser.rb
    MacRuby/trunk/lib/rexml/quickpath.rb
    MacRuby/trunk/lib/rexml/rexml.rb
    MacRuby/trunk/lib/rexml/sax2listener.rb
    MacRuby/trunk/lib/rexml/source.rb
    MacRuby/trunk/lib/rexml/streamlistener.rb
    MacRuby/trunk/lib/rexml/text.rb
    MacRuby/trunk/lib/rexml/validation/relaxng.rb
    MacRuby/trunk/lib/rexml/validation/validation.rb
    MacRuby/trunk/lib/rexml/xmltokens.rb
    MacRuby/trunk/lib/rexml/xpath.rb
    MacRuby/trunk/lib/rexml/xpath_parser.rb
    MacRuby/trunk/lib/rinda/rinda.rb
    MacRuby/trunk/lib/rinda/ring.rb
    MacRuby/trunk/lib/rinda/tuplespace.rb
    MacRuby/trunk/lib/rss/0.9.rb
    MacRuby/trunk/lib/rss/1.0.rb
    MacRuby/trunk/lib/rss/2.0.rb
    MacRuby/trunk/lib/rss/atom.rb
    MacRuby/trunk/lib/rss/content/1.0.rb
    MacRuby/trunk/lib/rss/content/2.0.rb
    MacRuby/trunk/lib/rss/converter.rb
    MacRuby/trunk/lib/rss/dublincore/1.0.rb
    MacRuby/trunk/lib/rss/dublincore/2.0.rb
    MacRuby/trunk/lib/rss/dublincore/atom.rb
    MacRuby/trunk/lib/rss/dublincore.rb
    MacRuby/trunk/lib/rss/image.rb
    MacRuby/trunk/lib/rss/maker/0.9.rb
    MacRuby/trunk/lib/rss/maker/1.0.rb
    MacRuby/trunk/lib/rss/maker/2.0.rb
    MacRuby/trunk/lib/rss/maker/base.rb
    MacRuby/trunk/lib/rss/maker/dublincore.rb
    MacRuby/trunk/lib/rss/maker/entry.rb
    MacRuby/trunk/lib/rss/maker/feed.rb
    MacRuby/trunk/lib/rss/maker/image.rb
    MacRuby/trunk/lib/rss/maker/taxonomy.rb
    MacRuby/trunk/lib/rss/maker/trackback.rb
    MacRuby/trunk/lib/rss/maker.rb
    MacRuby/trunk/lib/rss/parser.rb
    MacRuby/trunk/lib/rss/rexmlparser.rb
    MacRuby/trunk/lib/rss/rss.rb
    MacRuby/trunk/lib/rss/syndication.rb
    MacRuby/trunk/lib/rss/taxonomy.rb
    MacRuby/trunk/lib/rss/trackback.rb
    MacRuby/trunk/lib/rss/utils.rb
    MacRuby/trunk/lib/rss/xml-stylesheet.rb
    MacRuby/trunk/lib/rss/xmlparser.rb
    MacRuby/trunk/lib/rss/xmlscanner.rb
    MacRuby/trunk/lib/securerandom.rb
    MacRuby/trunk/lib/set.rb
    MacRuby/trunk/lib/shell/builtin-command.rb
    MacRuby/trunk/lib/shell/command-processor.rb
    MacRuby/trunk/lib/shell/error.rb
    MacRuby/trunk/lib/shell/filter.rb
    MacRuby/trunk/lib/shell/process-controller.rb
    MacRuby/trunk/lib/shell/system-command.rb
    MacRuby/trunk/lib/shell/version.rb
    MacRuby/trunk/lib/shell.rb
    MacRuby/trunk/lib/sync.rb
    MacRuby/trunk/lib/tempfile.rb
    MacRuby/trunk/lib/test/unit/assertions.rb
    MacRuby/trunk/lib/test/unit/testcase.rb
    MacRuby/trunk/lib/test/unit.rb
    MacRuby/trunk/lib/thread.rb
    MacRuby/trunk/lib/thwait.rb
    MacRuby/trunk/lib/time.rb
    MacRuby/trunk/lib/timeout.rb
    MacRuby/trunk/lib/tmpdir.rb
    MacRuby/trunk/lib/tracer.rb
    MacRuby/trunk/lib/tsort.rb
    MacRuby/trunk/lib/un.rb
    MacRuby/trunk/lib/uri/common.rb
    MacRuby/trunk/lib/uri/ftp.rb
    MacRuby/trunk/lib/uri/generic.rb
    MacRuby/trunk/lib/uri/http.rb
    MacRuby/trunk/lib/uri/https.rb
    MacRuby/trunk/lib/uri/ldap.rb
    MacRuby/trunk/lib/uri/mailto.rb
    MacRuby/trunk/lib/uri.rb
    MacRuby/trunk/lib/xmlrpc/base64.rb
    MacRuby/trunk/lib/xmlrpc/client.rb
    MacRuby/trunk/lib/xmlrpc/config.rb
    MacRuby/trunk/lib/xmlrpc/create.rb
    MacRuby/trunk/lib/xmlrpc/datetime.rb
    MacRuby/trunk/lib/xmlrpc/httpserver.rb
    MacRuby/trunk/lib/xmlrpc/marshal.rb
    MacRuby/trunk/lib/xmlrpc/parser.rb
    MacRuby/trunk/lib/xmlrpc/server.rb
    MacRuby/trunk/lib/xmlrpc/utils.rb
    MacRuby/trunk/numeric.c
    MacRuby/trunk/rakelib/builder/builder.rb
    MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/cookie/value_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/initialize_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/unescape_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/csv/parse_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/date/strptime_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/getoptlong/set_options_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/close_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/write_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/logger/logger/close_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/build_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/collect_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_size_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_vector_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/columns_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conj_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conjugate_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/constructor_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/det_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/determinant_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/divide_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_with_index_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/element_reference_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/empty_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/exponent_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imag_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imaginary_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/inspect_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/map_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minor_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minus_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/multiply_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/plus_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rank_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/real_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rect_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rectangular_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/regular_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/row_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/singular_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/square_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/t_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/tr_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/trace_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/transpose_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/vector/each2_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/library/uri/eql_tags.txt

Modified: MacRuby/trunk/lib/English.rb
===================================================================
--- MacRuby/trunk/lib/English.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/English.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -11,7 +11,7 @@
 #  With English:
 #
 #      require "English"
-#      
+#
 #      $OUTPUT_FIELD_SEPARATOR = ' -- '
 #      "waterbuffalo" =~ /buff/
 #      print $LOADED_FEATURES, $POSTMATCH, $PID, "\n"
@@ -83,7 +83,7 @@
 # of the contents of all the files
 # given as command-line arguments, or <tt>$stdin</tt>
 # (in the case where there are no
-# arguments). <tt>$<</tt> supports methods similar to a 
+# arguments). <tt>$<</tt> supports methods similar to a
 # +File+ object:
 # +inmode+, +close+,
 # <tt>closed?</tt>, +each+,
@@ -91,7 +91,7 @@
 # +eof+, <tt>eof?</tt>, +file+,
 # +filename+, +fileno+,
 # +getc+, +gets+, +lineno+,
-# <tt>lineno=</tt>, +path+, 
+# <tt>lineno=</tt>, +path+,
 # +pos+, <tt>pos=</tt>,
 # +read+, +readchar+,
 # +readline+, +readlines+,
@@ -139,12 +139,12 @@
 alias $MATCH                   $&
 
 # The string preceding the match in the last
-# successful pattern match. This variable is local to 
+# successful pattern match. This variable is local to
 # the current scope. Read only. Thread local.
 alias $PREMATCH                $`
 
 # The string following the match in the last
-# successful pattern match. This variable is local to 
+# successful pattern match. This variable is local to
 # the current scope. Read only. Thread local.
 alias $POSTMATCH               $'
 

Modified: MacRuby/trunk/lib/cgi/cookie.rb
===================================================================
--- MacRuby/trunk/lib/cgi/cookie.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/cookie.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,37 +1,38 @@
-  # Class representing an HTTP cookie.
-  #
-  # In addition to its specific fields and methods, a Cookie instance
-  # is a delegator to the array of its values.
-  #
-  # See RFC 2965.
-  #
-  # == Examples of use
-  #   cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
-  #   cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
-  #   cookie1 = CGI::Cookie::new('name'    => 'name',
-  #                              'value'   => ['value1', 'value2', ...],
-  #                              'path'    => 'path',   # optional
-  #                              'domain'  => 'domain', # optional
-  #                              'expires' => Time.now, # optional
-  #                              'secure'  => true      # optional
-  #                             )
-  # 
-  #   cgi.out("cookie" => [cookie1, cookie2]) { "string" }
-  # 
-  #   name    = cookie1.name
-  #   values  = cookie1.value
-  #   path    = cookie1.path
-  #   domain  = cookie1.domain
-  #   expires = cookie1.expires
-  #   secure  = cookie1.secure
-  # 
-  #   cookie1.name    = 'name'
-  #   cookie1.value   = ['value1', 'value2', ...]
-  #   cookie1.path    = 'path'
-  #   cookie1.domain  = 'domain'
-  #   cookie1.expires = Time.now + 30
-  #   cookie1.secure  = true
+# Class representing an HTTP cookie.
+#
+# In addition to its specific fields and methods, a Cookie instance
+# is a delegator to the array of its values.
+#
+# See RFC 2965.
+#
+# == Examples of use
+#   cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
+#   cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
+#   cookie1 = CGI::Cookie::new('name'    => 'name',
+#                              'value'   => ['value1', 'value2', ...],
+#                              'path'    => 'path',   # optional
+#                              'domain'  => 'domain', # optional
+#                              'expires' => Time.now, # optional
+#                              'secure'  => true      # optional
+#                             )
+#
+#   cgi.out("cookie" => [cookie1, cookie2]) { "string" }
+#
+#   name    = cookie1.name
+#   values  = cookie1.value
+#   path    = cookie1.path
+#   domain  = cookie1.domain
+#   expires = cookie1.expires
+#   secure  = cookie1.secure
+#
+#   cookie1.name    = 'name'
+#   cookie1.value   = ['value1', 'value2', ...]
+#   cookie1.path    = 'path'
+#   cookie1.domain  = 'domain'
+#   cookie1.expires = Time.now + 30
+#   cookie1.secure  = true
 class CGI
+  @@accept_charset="UTF-8" unless defined?(@@accept_charset)
   class Cookie < Array
 
     # Create a new CGI::Cookie object.
@@ -48,18 +49,19 @@
     # domain:: the domain for which this cookie applies.
     # expires:: the time at which this cookie expires, as a +Time+ object.
     # secure:: whether this cookie is a secure cookie or not (default to
-    #          false).  Secure cookies are only transmitted to HTTPS 
+    #          false).  Secure cookies are only transmitted to HTTPS
     #          servers.
     #
     # These keywords correspond to attributes of the cookie object.
     def initialize(name = "", *value)
+      @domain = nil
+      @expires = nil
       if name.kind_of?(String)
         @name = name
-        @value = value
         %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
         @path = ($1 or "")
         @secure = false
-        return super(@value)
+        return super(value)
       end
 
       options = name
@@ -68,7 +70,7 @@
       end
 
       @name = options["name"]
-      @value = Array(options["value"])
+      value = Array(options["value"])
       # simple support for IE
       if options["path"]
         @path = options["path"]
@@ -80,12 +82,20 @@
       @expires = options["expires"]
       @secure = options["secure"] == true ? true : false
 
-      super(@value)
+      super(value)
     end
 
-    attr_accessor("name", "value", "path", "domain", "expires")
+    attr_accessor("name", "path", "domain", "expires")
     attr_reader("secure")
 
+    def value
+      self
+    end
+
+    def value=(val)
+      replace(Array(val))
+    end
+
     # Set whether the Cookie is a secure cookie or not.
     #
     # +val+ must be a boolean.
@@ -96,7 +106,7 @@
 
     # Convert the Cookie to its string representation.
     def to_s
-      val = @value.kind_of?(String) ? CGI::escape(@value) : @value.collect{|v| CGI::escape(v) }.join("&")
+      val = collect{|v| CGI::escape(v) }.join("&")
       buf = "#{@name}=#{val}"
       buf << "; domain=#{@domain}" if @domain
       buf << "; path=#{@path}"     if @path
@@ -123,7 +133,7 @@
       next unless name and values
       name = CGI::unescape(name)
       values ||= ""
-      values = values.split('&').collect{|v| CGI::unescape(v) }
+      values = values.split('&').collect{|v| CGI::unescape(v,@@accept_charset) }
       if cookies.has_key?(name)
         values = cookies[name].value + values
       end

Modified: MacRuby/trunk/lib/cgi/core.rb
===================================================================
--- MacRuby/trunk/lib/cgi/core.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/core.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -11,9 +11,9 @@
   # Standard internet newline sequence
   EOL = CR + LF
 
-  REVISION = '$Id: core.rb 21825 2009-01-28 09:21:49Z yugui $' #:nodoc:
+  REVISION = '$Id: core.rb 27581 2010-05-01 23:54:39Z nobu $' #:nodoc:
 
-  NEEDS_BINMODE = true if /WIN/i.match(RUBY_PLATFORM) 
+  NEEDS_BINMODE = File::BINARY != 0
 
   # Path separators in different environments.
   PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
@@ -33,22 +33,16 @@
     "METHOD_NOT_ALLOWED"  => "405 Method Not Allowed",
     "NOT_ACCEPTABLE"      => "406 Not Acceptable",
     "LENGTH_REQUIRED"     => "411 Length Required",
-    "PRECONDITION_FAILED" => "412 Rrecondition Failed",
+    "PRECONDITION_FAILED" => "412 Precondition Failed",
     "SERVER_ERROR"        => "500 Internal Server Error",
     "NOT_IMPLEMENTED"     => "501 Method Not Implemented",
     "BAD_GATEWAY"         => "502 Bad Gateway",
     "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
   }
 
-  # Abbreviated day-of-week names specified by RFC 822
-  RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
-
-  # Abbreviated month names specified by RFC 822
-  RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
-
   # :startdoc:
 
-  def env_table 
+  def env_table
     ENV
   end
 
@@ -79,7 +73,7 @@
   # status:: the HTTP status code, returned as the Status header.  See the
   #          list of available status codes below.
   # server:: the server software, returned as the Server header.
-  # connection:: the connection type, returned as the Connection header (for 
+  # connection:: the connection type, returned as the Connection header (for
   #              instance, "close".
   # length:: the length of the content that will be sent, returned as the
   #          Content-Length header.
@@ -89,19 +83,19 @@
   #           object, returned as the Expires header.
   # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
   #          The value can be the literal string of the cookie; a CGI::Cookie
-  #          object; an Array of literal cookie strings or Cookie objects; or a 
+  #          object; an Array of literal cookie strings or Cookie objects; or a
   #          hash all of whose values are literal cookie strings or Cookie objects.
   #          These cookies are in addition to the cookies held in the
   #          @output_cookies field.
   #
   # Other header lines can also be set; they are appended as key: value.
-  # 
+  #
   #   header
   #     # Content-Type: text/html
-  # 
+  #
   #   header("text/plain")
   #     # Content-Type: text/plain
-  # 
+  #
   #   header("nph"        => true,
   #          "status"     => "OK",  # == "200 OK"
   #            # "status"     => "200 GOOD",
@@ -116,9 +110,9 @@
   #          "cookie"     => [cookie1, cookie2],
   #          "my_header1" => "my_value"
   #          "my_header2" => "my_value")
-  # 
+  #
   # The status codes are:
-  # 
+  #
   #   "OK"                  --> "200 OK"
   #   "PARTIAL_CONTENT"     --> "206 Partial Content"
   #   "MULTIPLE_CHOICES"    --> "300 Multiple Choices"
@@ -137,8 +131,8 @@
   #   "NOT_IMPLEMENTED"     --> "501 Method Not Implemented"
   #   "BAD_GATEWAY"         --> "502 Bad Gateway"
   #   "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
-  # 
-  # This method does not perform charset conversion. 
+  #
+  # This method does not perform charset conversion.
   def header(options='text/html')
     if options.is_a?(String)
       content_type = options
@@ -277,13 +271,13 @@
   #     # Content-Length: 6
   #     #
   #     # string
-  # 
+  #
   #   cgi.out("text/plain") { "string" }
   #     # Content-Type: text/plain
   #     # Content-Length: 6
   #     #
   #     # string
-  # 
+  #
   #   cgi.out("nph"        => true,
   #           "status"     => "OK",  # == "200 OK"
   #           "server"     => ENV['SERVER_SOFTWARE'],
@@ -296,16 +290,16 @@
   #           "cookie"     => [cookie1, cookie2],
   #           "my_header1" => "my_value",
   #           "my_header2" => "my_value") { "string" }
-  # 
+  #
   # Content-Length is automatically calculated from the size of
   # the String returned by the content block.
   #
   # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
   # is outputted (the content block is still required, but it
   # is ignored).
-  # 
+  #
   # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
-  # the content is converted to this charset, and the language is set 
+  # the content is converted to this charset, and the language is set
   # to "ja".
   def out(options = "text/html") # :yield:
 
@@ -358,7 +352,7 @@
 
   # Mixin module. It provides the follow functionality groups:
   #
-  # 1. Access to CGI environment variables as methods.  See 
+  # 1. Access to CGI environment variables as methods.  See
   #    documentation to the CGI class for a list of these variables.
   #
   # 2. Access to cookies, including the cookies attribute.
@@ -408,7 +402,7 @@
     # values is an Array.
     attr_reader :params
 
-    # Get the uploaed files as a hash of name=>values pairs
+    # Get the uploaded files as a hash of name=>values pairs
     attr_reader :files
 
     # Set all the parameters.
@@ -440,7 +434,13 @@
         ## create body (StringIO or Tempfile)
         body = create_body(bufsize < content_length)
         class << body
-          alias local_path path
+          if method_defined?(:path)
+            alias local_path path
+          else
+            def local_path
+              nil
+            end
+          end
           attr_reader :original_filename, :content_type
         end
         ## find head and boundary
@@ -549,12 +549,17 @@
             %|(offline mode: enter name=value pairs on standard input)\n|
           )
         end
-        readlines.join(' ').gsub(/\n/, '')
-      end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')
+        array = readlines rescue nil
+        if not array.nil?
+            array.join(' ').gsub(/\n/n, '')
+        else
+            ""
+        end
+      end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
 
       words = Shellwords.shellwords(string)
 
-      if words.find{|x| /=/.match(x) }
+      if words.find{|x| /=/n.match(x) }
         words.join('&')
       else
         words.join('+')
@@ -617,7 +622,7 @@
 
     # Get the value for the parameter with a given key.
     #
-    # If the parameter has multiple values, only the first will be 
+    # If the parameter has multiple values, only the first will be
     # retrieved; use #params() to get the array of values.
     def [](key)
       params = @params[key]
@@ -658,7 +663,7 @@
   # This default value default is "UTF-8"
   # If you want to change the default accept character set
   # when create a new CGI instance, set this:
-  # 
+  #
   #   CGI.accept_charset = "EUC-JP"
   #
 
@@ -700,11 +705,11 @@
   #
   # == block
   #
-  # When you use a block, you can write a process 
+  # When you use a block, you can write a process
   # that query encoding is invalid. Example:
   #
   #   encoding_error={}
-  #   cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value| 
+  #   cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
   #     encoding_error[key] = value
   #   end
   #

Modified: MacRuby/trunk/lib/cgi/html.rb
===================================================================
--- MacRuby/trunk/lib/cgi/html.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/html.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -66,7 +66,7 @@
   # Modules Http3, Http4, etc., contain more basic HTML-generation methods
   # (:title, :center, etc.).
   #
-  # See class CGI for a detailed example. 
+  # See class CGI for a detailed example.
   #
   module HtmlExtension
 
@@ -99,7 +99,7 @@
       end
     end
 
-    # Generate a Document Base URI element as a String. 
+    # Generate a Document Base URI element as a String.
     #
     # +href+ can either by a string, giving the base URL for the HREF
     # attribute, or it can be a has of the element's attributes.
@@ -179,10 +179,10 @@
     #
     #   checkbox("name")
     #     # = checkbox("NAME" => "name")
-    # 
+    #
     #   checkbox("name", "value")
     #     # = checkbox("NAME" => "name", "VALUE" => "value")
-    # 
+    #
     #   checkbox("name", "value", true)
     #     # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
     def checkbox(name = "", value = nil, checked = nil)
@@ -220,23 +220,23 @@
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
-    # 
+    #
     #   checkbox_group("name", ["foo"], ["bar", true], "baz")
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
     #     # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
-    # 
+    #
     #   checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
     #     # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
     #     # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
-    # 
+    #
     #   checkbox_group("NAME" => "name",
     #                    "VALUES" => ["foo", "bar", "baz"])
-    # 
+    #
     #   checkbox_group("NAME" => "name",
     #                    "VALUES" => [["foo"], ["bar", true], "baz"])
-    # 
+    #
     #   checkbox_group("NAME" => "name",
     #                    "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
     def checkbox_group(name = "", *values)
@@ -272,13 +272,13 @@
     #
     #   file_field("name")
     #     # <INPUT TYPE="file" NAME="name" SIZE="20">
-    # 
+    #
     #   file_field("name", 40)
     #     # <INPUT TYPE="file" NAME="name" SIZE="40">
-    # 
+    #
     #   file_field("name", 40, 100)
     #     # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
-    # 
+    #
     #   file_field("NAME" => "name", "SIZE" => 40)
     #     # <INPUT TYPE="file" NAME="name" SIZE="40">
     def file_field(name = "", size = 20, maxlength = nil)
@@ -298,7 +298,7 @@
     #
     # +method+ should be either "get" or "post", and defaults to the latter.
     # +action+ defaults to the current CGI script name.  +enctype+
-    # defaults to "application/x-www-form-urlencoded".  
+    # defaults to "application/x-www-form-urlencoded".
     #
     # Alternatively, the attributes can be specified as a hash.
     #
@@ -306,19 +306,19 @@
     #
     #   form{ "string" }
     #     # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
-    # 
+    #
     #   form("get") { "string" }
     #     # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
-    # 
+    #
     #   form("get", "url") { "string" }
     #     # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
-    # 
+    #
     #   form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
     #     # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
     def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
       attributes = if method.kind_of?(String)
                      { "METHOD" => method, "ACTION" => action,
-                       "ENCTYPE" => enctype } 
+                       "ENCTYPE" => enctype }
                    else
                      unless method.has_key?("METHOD")
                        method["METHOD"] = "post"
@@ -350,10 +350,10 @@
     #
     #   hidden("name")
     #     # <INPUT TYPE="hidden" NAME="name">
-    # 
+    #
     #   hidden("name", "value")
     #     # <INPUT TYPE="hidden" NAME="name" VALUE="value">
-    # 
+    #
     #   hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
     #     # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
     def hidden(name = "", value = nil)
@@ -376,36 +376,36 @@
     # should include the entire text of this tag, including angle brackets.
     #
     # The body of the html element is supplied as a block.
-    # 
+    #
     #   html{ "string" }
     #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
-    # 
+    #
     #   html("LANG" => "ja") { "string" }
     #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
-    # 
+    #
     #   html("DOCTYPE" => false) { "string" }
     #     # <HTML>string</HTML>
-    # 
+    #
     #   html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
     #     # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
-    # 
+    #
     #   html("PRETTY" => "  ") { "<BODY></BODY>" }
     #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
     #     # <HTML>
     #     #   <BODY>
     #     #   </BODY>
     #     # </HTML>
-    # 
+    #
     #   html("PRETTY" => "\t") { "<BODY></BODY>" }
     #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
     #     # <HTML>
     #     #         <BODY>
     #     #         </BODY>
     #     # </HTML>
-    # 
+    #
     #   html("PRETTY") { "<BODY></BODY>" }
     #     # = html("PRETTY" => "  ") { "<BODY></BODY>" }
-    # 
+    #
     #   html(if $VERBOSE then "PRETTY" end) { "HTML string" }
     #
     def html(attributes = {}) # :yield:
@@ -444,18 +444,18 @@
 
     # Generate an Image Button Input element as a string.
     #
-    # +src+ is the URL of the image to use for the button.  +name+ 
+    # +src+ is the URL of the image to use for the button.  +name+
     # is the input name.  +alt+ is the alternative text for the image.
     #
     # Alternatively, the attributes can be specified as a hash.
-    # 
+    #
     #   image_button("url")
     #     # <INPUT TYPE="image" SRC="url">
-    # 
+    #
     #   image_button("url", "name", "string")
     #     # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
-    # 
-    #   image_button("SRC" => "url", "ATL" => "strng")
+    #
+    #   image_button("SRC" => "url", "ALT" => "string")
     #     # <INPUT TYPE="image" SRC="url" ALT="string">
     def image_button(src = "", name = nil, alt = nil)
       attributes = if src.kind_of?(String)
@@ -480,7 +480,7 @@
     #
     #   img("src", "alt", 100, 50)
     #     # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
-    # 
+    #
     #   img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
     #     # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
     def img(src = "", alt = "", width = nil, height = nil)
@@ -506,15 +506,15 @@
     #
     #   multipart_form{ "string" }
     #     # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
-    # 
+    #
     #   multipart_form("url") { "string" }
     #     # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
     def multipart_form(action = nil, enctype = "multipart/form-data")
       attributes = if action == nil
-                     { "METHOD" => "post", "ENCTYPE" => enctype } 
+                     { "METHOD" => "post", "ENCTYPE" => enctype }
                    elsif action.kind_of?(String)
                      { "METHOD" => "post", "ACTION" => action,
-                       "ENCTYPE" => enctype } 
+                       "ENCTYPE" => enctype }
                    else
                      unless action.has_key?("METHOD")
                        action["METHOD"] = "post"
@@ -542,13 +542,13 @@
     #
     #   password_field("name")
     #     # <INPUT TYPE="password" NAME="name" SIZE="40">
-    # 
+    #
     #   password_field("name", "value")
     #     # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
-    # 
+    #
     #   password_field("password", "value", 80, 200)
     #     # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
-    # 
+    #
     #   password_field("NAME" => "name", "VALUE" => "value")
     #     # <INPUT TYPE="password" NAME="name" VALUE="value">
     def password_field(name = "", value = nil, size = 40, maxlength = nil)
@@ -584,21 +584,21 @@
     #     #   <OPTION VALUE="bar">bar</OPTION>
     #     #   <OPTION VALUE="baz">baz</OPTION>
     #     # </SELECT>
-    # 
+    #
     #   popup_menu("name", ["foo"], ["bar", true], "baz")
     #     # <SELECT NAME="name">
     #     #   <OPTION VALUE="foo">foo</OPTION>
     #     #   <OPTION VALUE="bar" SELECTED>bar</OPTION>
     #     #   <OPTION VALUE="baz">baz</OPTION>
     #     # </SELECT>
-    # 
+    #
     #   popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
     #     # <SELECT NAME="name">
     #     #   <OPTION VALUE="1">Foo</OPTION>
     #     #   <OPTION SELECTED VALUE="2">Bar</OPTION>
     #     #   <OPTION VALUE="Baz">Baz</OPTION>
     #     # </SELECT>
-    # 
+    #
     #   popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
     #               "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
     #     # <SELECT NAME="name" MULTIPLE SIZE="2">
@@ -649,10 +649,10 @@
     #
     #   radio_button("name", "value")
     #     # <INPUT TYPE="radio" NAME="name" VALUE="value">
-    # 
+    #
     #   radio_button("name", "value", true)
     #     # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
-    # 
+    #
     #   radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
     #     # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
     def radio_button(name = "", value = nil, checked = nil)
@@ -670,28 +670,28 @@
     #
     # This works the same as #checkbox_group().  However, it is not valid
     # to have more than one radiobutton in a group checked.
-    # 
+    #
     #   radio_group("name", "foo", "bar", "baz")
     #     # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
     #     # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
     #     # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
-    # 
+    #
     #   radio_group("name", ["foo"], ["bar", true], "baz")
     #     # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
     #     # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
     #     # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
-    # 
+    #
     #   radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
     #     # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
     #     # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
     #     # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
-    # 
+    #
     #   radio_group("NAME" => "name",
     #                 "VALUES" => ["foo", "bar", "baz"])
-    # 
+    #
     #   radio_group("NAME" => "name",
     #                 "VALUES" => [["foo"], ["bar", true], "baz"])
-    # 
+    #
     #   radio_group("NAME" => "name",
     #                 "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
     def radio_group(name = "", *values)
@@ -723,10 +723,10 @@
     #
     #   reset
     #     # <INPUT TYPE="reset">
-    # 
+    #
     #   reset("reset")
     #     # <INPUT TYPE="reset" VALUE="reset">
-    # 
+    #
     #   reset("VALUE" => "reset", "ID" => "foo")
     #     # <INPUT TYPE="reset" VALUE="reset" ID="foo">
     def reset(value = nil, name = nil)
@@ -750,13 +750,13 @@
     #
     #   submit
     #     # <INPUT TYPE="submit">
-    # 
+    #
     #   submit("ok")
     #     # <INPUT TYPE="submit" VALUE="ok">
-    # 
+    #
     #   submit("ok", "button1")
     #     # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
-    # 
+    #
     #   submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
     #     # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
     def submit(value = nil, name = nil)
@@ -779,16 +779,16 @@
     #
     #   text_field("name")
     #     # <INPUT TYPE="text" NAME="name" SIZE="40">
-    # 
+    #
     #   text_field("name", "value")
     #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
-    # 
+    #
     #   text_field("name", "value", 80)
     #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
-    # 
+    #
     #   text_field("name", "value", 80, 200)
     #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
-    # 
+    #
     #   text_field("NAME" => "name", "VALUE" => "value")
     #     # <INPUT TYPE="text" NAME="name" VALUE="value">
     def text_field(name = "", value = nil, size = 40, maxlength = nil)

Modified: MacRuby/trunk/lib/cgi/session/pstore.rb
===================================================================
--- MacRuby/trunk/lib/cgi/session/pstore.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/session/pstore.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -2,7 +2,7 @@
 # cgi/session/pstore.rb - persistent storage of marshalled session data
 #
 # Documentation: William Webber (william at williamwebber.com)
-# 
+#
 # == Overview
 #
 # This file provides the CGI::Session::PStore class, which builds
@@ -29,7 +29,7 @@
       # created.  The session id must only contain alphanumeric
       # characters; automatically generated session ids observe
       # this requirement.
-      # 
+      #
       # +option+ is a hash of options for the initializer.  The
       # following options are recognised:
       #
@@ -77,7 +77,7 @@
       end
 
       # Save session state to the session's PStore file.
-      def update 
+      def update
         @p.transaction do
           @p['hash'] = @hash
         end

Modified: MacRuby/trunk/lib/cgi/session.rb
===================================================================
--- MacRuby/trunk/lib/cgi/session.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/session.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -13,7 +13,7 @@
 #
 # This file provides the +CGI::Session+ class, which provides session
 # support for CGI scripts.  A session is a sequence of HTTP requests
-# and responses linked together and associated with a single client.  
+# and responses linked together and associated with a single client.
 # Information associated with the session is stored
 # on the server between requests.  A session id is passed between client
 # and server with every request and response, transparently
@@ -28,7 +28,7 @@
 
 class CGI
 
-  # Class representing an HTTP session.  See documentation for the file 
+  # Class representing an HTTP session.  See documentation for the file
   # cgi/session.rb for an introduction to HTTP sessions.
   #
   # == Lifecycle
@@ -47,7 +47,7 @@
   # == Setting and retrieving session data.
   #
   # The Session class associates data with a session as key-value pairs.
-  # This data can be set and retrieved by indexing the Session instance 
+  # This data can be set and retrieved by indexing the Session instance
   # using '[]', much the same as hashes (although other hash methods
   # are not supported).
   #
@@ -60,21 +60,21 @@
   #
   # == Storing session state
   #
-  # The caller can specify what form of storage to use for the session's 
+  # The caller can specify what form of storage to use for the session's
   # data with the +database_manager+ option to CGI::Session::new.  The
   # following storage classes are provided as part of the standard library:
   #
-  # CGI::Session::FileStore:: stores data as plain text in a flat file.  Only 
-  #                           works with String data.  This is the default 
+  # CGI::Session::FileStore:: stores data as plain text in a flat file.  Only
+  #                           works with String data.  This is the default
   #                           storage type.
-  # CGI::Session::MemoryStore:: stores data in an in-memory hash.  The data 
-  #                             only persists for as long as the current ruby 
+  # CGI::Session::MemoryStore:: stores data in an in-memory hash.  The data
+  #                             only persists for as long as the current ruby
   #                             interpreter instance does.
   # CGI::Session::PStore:: stores data in Marshalled format.  Provided by
-  #                        cgi/session/pstore.rb.  Supports data of any type, 
+  #                        cgi/session/pstore.rb.  Supports data of any type,
   #                        and provides file-locking and transaction support.
   #
-  # Custom storage types can also be created by defining a class with 
+  # Custom storage types can also be created by defining a class with
   # the following methods:
   #
   #    new(session, options)
@@ -99,14 +99,14 @@
   # The simplest way to do this is via cookies.  The CGI::Session class
   # provides transparent support for session id communication via cookies
   # if the client has cookies enabled.
-  # 
+  #
   # If the client has cookies disabled, the session id must be included
   # as a parameter of all requests sent by the client to the server.  The
   # CGI::Session class in conjunction with the CGI class will transparently
   # add the session id as a hidden input field to all forms generated
   # using the CGI#form() HTML generation method.  No built-in support is
   # provided for other mechanisms, such as URL re-writing.  The caller is
-  # responsible for extracting the session id from the session_id 
+  # responsible for extracting the session id from the session_id
   # attribute and manually encoding it in URLs and adding it as a hidden
   # input to HTML forms created by other mechanisms.  Also, session expiry
   # is not automatically handled.
@@ -124,10 +124,10 @@
   #   session = CGI::Session.new(cgi,
   #       'database_manager' => CGI::Session::PStore,  # use PStore
   #       'session_key' => '_rb_sess_id',              # custom session key
-  #       'session_expires' => Time.now + 30 * 60,     # 30 minute timeout 
+  #       'session_expires' => Time.now + 30 * 60,     # 30 minute timeout
   #       'prefix' => 'pstore_sid_')                   # PStore option
   #   if cgi.has_key?('user_name') and cgi['user_name'] != ''
-  #       # coerce to String: cgi[] returns the 
+  #       # coerce to String: cgi[] returns the
   #       # string-like CGI::QueryExtension::Value
   #       session['user_name'] = cgi['user_name'].to_s
   #   elsif !session['user_name']
@@ -143,11 +143,11 @@
   #   cgi = CGI.new("html4")
   #
   #   # We make sure to delete an old session if one exists,
-  #   # not just to free resources, but to prevent the session 
+  #   # not just to free resources, but to prevent the session
   #   # from being maliciously hijacked later on.
   #   begin
-  #       session = CGI::Session.new(cgi, 'new_session' => false)      
-  #       session.delete                 
+  #       session = CGI::Session.new(cgi, 'new_session' => false)
+  #       session.delete
   #   rescue ArgumentError  # if no old session
   #   end
   #   session = CGI::Session.new(cgi, 'new_session' => true)
@@ -172,7 +172,7 @@
     # The session id is an MD5 hash based upon the time,
     # a random number, and a constant string.  This routine
     # is used internally for automatically generated
-    # session ids. 
+    # session ids.
     def create_new_id
       require 'securerandom'
       begin
@@ -205,7 +205,7 @@
     #              it is retrieved from the +session_key+ parameter
     #              of the request, or automatically generated for
     #              a new session.
-    # new_session:: if true, force creation of a new session.  If not set, 
+    # new_session:: if true, force creation of a new session.  If not set,
     #               a new session is only created if none currently
     #               exists.  If false, a new session is never created,
     #               and if none currently exists and the +session_id+
@@ -220,7 +220,7 @@
     # The following options are also recognised, but only apply if the
     # session id is stored in a cookie.
     #
-    # session_expires:: the time the current session expires, as a 
+    # session_expires:: the time the current session expires, as a
     #                   +Time+ object.  If not set, the session will terminate
     #                   when the user's browser is closed.
     # session_domain:: the hostname domain for which this session is valid.
@@ -232,10 +232,10 @@
     # +option+ is also passed on to the session storage class initializer; see
     # the documentation for each session storage class for the options
     # they support.
-    #                  
+    #
     # The retrieved or created session is automatically added to +request+
     # as a cookie, and also to its +output_hidden+ table, which is used
-    # to add hidden input elements to forms.  
+    # to add hidden input elements to forms.
     #
     # *WARNING* the +output_hidden+
     # fields are surrounded by a <fieldset> tag in HTML 4 generation, which
@@ -294,7 +294,7 @@
           "expires" => option['session_expires'],
           "domain" => option['session_domain'],
           "secure" => option['session_secure'],
-          "path" => 
+          "path" =>
           if option['session_path']
             option['session_path']
           elsif ENV["SCRIPT_NAME"]
@@ -323,11 +323,11 @@
 
     # Store session data on the server.  For some session storage types,
     # this is a no-op.
-    def update  
+    def update
       @dbman.update
     end
 
-    # Store session data on the server and close the session storage.  
+    # Store session data on the server and close the session storage.
     # For some session storage types, this is a no-op.
     def close
       @dbman.close
@@ -359,7 +359,7 @@
       # created.  The session id must only contain alphanumeric
       # characters; automatically generated session ids observe
       # this requirement.
-      # 
+      #
       # +option+ is a hash of options for the initializer.  The
       # following options are recognised:
       #
@@ -450,7 +450,7 @@
     # In-memory session storage class.
     #
     # Implements session storage as a global in-memory hash.  Session
-    # data will only persist for as long as the ruby interpreter 
+    # data will only persist for as long as the ruby interpreter
     # instance does.
     class MemoryStore
       GLOBAL_HASH_TABLE = {} #:nodoc:

Modified: MacRuby/trunk/lib/cgi/util.rb
===================================================================
--- MacRuby/trunk/lib/cgi/util.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi/util.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +1,5 @@
 class CGI
+  @@accept_charset="UTF-8" unless defined?(@@accept_charset)
   # URL-encode a string.
   #   url_encoded_string = CGI::escape("'Stop!' said Fred")
   #      # => "%27Stop%21%27+said+Fred"
@@ -9,14 +10,14 @@
   end
 
 
-  # URL-decode a string.
+  # URL-decode a string with encoding(optional).
   #   string = CGI::unescape("%27Stop%21%27+said+Fred")
   #      # => "'Stop!' said Fred"
-  def CGI::unescape(string)
-    enc = string.encoding
-    string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
-      [$1.delete('%')].pack('H*').force_encoding(enc)
-    end
+  def CGI::unescape(string,encoding=@@accept_charset)
+    str=string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
+      [$1.delete('%')].pack('H*')
+    end.force_encoding(encoding)
+    str.valid_encoding? ? str : str.force_encoding(string.encoding)
   end
 
   TABLE_FOR_ESCAPE_HTML__ = {
@@ -119,7 +120,7 @@
   #   print CGI::unescapeElement(
   #           CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
   #     # "&lt;BR&gt;<A HREF="url"></A>"
-  # 
+  #
   #   print CGI::unescapeElement(
   #           CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
   #     # "&lt;BR&gt;<A HREF="url"></A>"
@@ -140,6 +141,12 @@
     unescapeElement(str)
   end
 
+  # Abbreviated day-of-week names specified by RFC 822
+  RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
+
+  # Abbreviated month names specified by RFC 822
+  RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
+
   # Format a +Time+ object as a String using the format specified by RFC 1123.
   #
   #   CGI::rfc1123_date(Time.now)
@@ -161,7 +168,7 @@
   #     #   <BODY>
   #     #   </BODY>
   #     # </HTML>
-  # 
+  #
   #   print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
   #     # <HTML>
   #     #         <BODY>
@@ -169,7 +176,7 @@
   #     # </HTML>
   #
   def CGI::pretty(string, shift = "  ")
-    lines = string.gsub(/(?!\A)<(?:.|\n)*?>/, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/, "\\0\n")
+    lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n")
     end_pos = 0
     while end_pos = lines.index(/^<\/(\w+)/, end_pos)
       element = $1.dup

Modified: MacRuby/trunk/lib/cgi.rb
===================================================================
--- MacRuby/trunk/lib/cgi.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cgi.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,14 +1,14 @@
-# 
+#
 # cgi.rb - cgi support library
-# 
+#
 # Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-# 
+#
 # Copyright (C) 2000  Information-technology Promotion Agency, Japan
 #
 # Author: Wakou Aoyama <wakou at ruby-lang.org>
 #
-# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber) 
-# 
+# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
+#
 # == Overview
 #
 # The Common Gateway Interface (CGI) is a simple protocol
@@ -18,7 +18,7 @@
 # parameters of the request passed in either in the
 # environment (GET) or via $stdin (POST), and everything
 # it prints to $stdout is returned to the client.
-# 
+#
 # This file holds the +CGI+ class.  This class provides
 # functionality for retrieving HTTP request parameters,
 # managing cookies, and generating HTML output.  See the
@@ -75,18 +75,18 @@
 #
 #
 # For each of these variables, there is a corresponding attribute with the
-# same name, except all lower case and without a preceding HTTP_.  
+# same name, except all lower case and without a preceding HTTP_.
 # +content_length+ and +server_port+ are integers; the rest are strings.
 #
 # === Parameters
 #
 # The method #params() returns a hash of all parameters in the request as
 # name/value-list pairs, where the value-list is an Array of one or more
-# values.  The CGI object itself also behaves as a hash of parameter names 
-# to values, but only returns a single value (as a String) for each 
+# values.  The CGI object itself also behaves as a hash of parameter names
+# to values, but only returns a single value (as a String) for each
 # parameter name.
 #
-# For instance, suppose the request contains the parameter 
+# For instance, suppose the request contains the parameter
 # "favourite_colours" with the multiple values "blue" and "green".  The
 # following behaviour would occur:
 #
@@ -105,7 +105,7 @@
 #
 # === Multipart requests
 #
-# If a request's method is POST and its content type is multipart/form-data, 
+# If a request's method is POST and its content type is multipart/form-data,
 # then it may contain uploaded files.  These are stored by the QueryExtension
 # module in the parameters of the request.  The parameter name is the name
 # attribute of the file input field, as usual.  However, the value is not
@@ -136,7 +136,7 @@
 #
 # Each HTML element has a corresponding method for generating that
 # element as a String.  The name of this method is the same as that
-# of the element, all lowercase.  The attributes of the element are 
+# of the element, all lowercase.  The attributes of the element are
 # passed in as a hash, and the body as a no-argument block that evaluates
 # to a String.  The HTML generation module knows which elements are
 # always empty, and silently drops any passed-in body.  It also knows
@@ -150,57 +150,57 @@
 # as arguments, rather than via a hash.
 #
 # == Examples of use
-# 
+#
 # === Get form values
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   value = cgi['field_name']   # <== value string for 'field_name'
 #     # if not 'field_name' included, then return "".
 #   fields = cgi.keys            # <== array of field names
-# 
+#
 #   # returns true if form has 'field_name'
 #   cgi.has_key?('field_name')
 #   cgi.has_key?('field_name')
 #   cgi.include?('field_name')
-# 
-# CAUTION! cgi['field_name'] returned an Array with the old 
+#
+# CAUTION! cgi['field_name'] returned an Array with the old
 # cgi.rb(included in ruby 1.6)
-# 
+#
 # === Get form values as hash
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   params = cgi.params
-# 
+#
 # cgi.params is a hash.
-# 
+#
 #   cgi.params['new_field_name'] = ["value"]  # add new param
 #   cgi.params['field_name'] = ["new_value"]  # change value
 #   cgi.params.delete('field_name')           # delete param
 #   cgi.params.clear                          # delete all params
-# 
-# 
+#
+#
 # === Save form values to file
-# 
+#
 #   require "pstore"
 #   db = PStore.new("query.db")
 #   db.transaction do
 #     db["params"] = cgi.params
 #   end
-# 
-# 
+#
+#
 # === Restore form values from file
-# 
+#
 #   require "pstore"
 #   db = PStore.new("query.db")
 #   db.transaction do
 #     cgi.params = db["params"]
 #   end
-# 
-# 
+#
+#
 # === Get multipart form values
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   value = cgi['field_name']   # <== value string for 'field_name'
@@ -208,37 +208,37 @@
 #   value.local_path            # <== path to local file of value
 #   value.original_filename     # <== original filename of value
 #   value.content_type          # <== content_type of value
-# 
+#
 # and value has StringIO or Tempfile class methods.
-# 
+#
 # === Get cookie values
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   values = cgi.cookies['name']  # <== array of 'name'
 #     # if not 'name' included, then return [].
 #   names = cgi.cookies.keys      # <== array of cookie names
-# 
+#
 # and cgi.cookies is a hash.
-# 
+#
 # === Get cookie objects
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   for name, cookie in cgi.cookies
 #     cookie.expires = Time.now + 30
 #   end
 #   cgi.out("cookie" => cgi.cookies) {"string"}
-# 
+#
 #   cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new
 #   cgi.cookies['name'].expires = Time.now + 30
 #   cgi.out("cookie" => cgi.cookies['name']) {"string"}
-# 
+#
 # === Print http header and html string to $DEFAULT_OUTPUT ($>)
-# 
+#
 #   require "cgi"
 #   cgi = CGI.new("html3")  # add HTML generation methods
 #   cgi.out() do
@@ -262,7 +262,7 @@
 #       end
 #     end
 #   end
-# 
+#
 #   # add HTML generation methods
 #   CGI.new("html3")    # html3.2
 #   CGI.new("html4")    # html4.01 (Strict)
@@ -272,3 +272,4 @@
 require 'cgi/core'
 require 'cgi/cookie'
 require 'cgi/util'
+CGI.autoload(:HtmlExtension, 'cgi/html')

Modified: MacRuby/trunk/lib/cmath.rb
===================================================================
--- MacRuby/trunk/lib/cmath.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/cmath.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -4,8 +4,10 @@
 
   alias exp! exp
   alias log! log
+  alias log2! log2
   alias log10! log10
   alias sqrt! sqrt
+  alias cbrt! cbrt
 
   alias sin! sin
   alias cos! cos
@@ -28,8 +30,9 @@
     if z.real?
       exp!(z)
     else
-      Complex(exp!(z.real) * cos!(z.imag),
-	      exp!(z.real) * sin!(z.imag))
+      ere = exp!(z.real)
+      Complex(ere * cos!(z.imag),
+	      ere * sin!(z.imag))
     end
   end
 
@@ -38,8 +41,7 @@
     if z.real? and z >= 0 and (b.nil? or b >= 0)
       log!(*args)
     else
-      r, theta = z.polar
-      a = Complex(log!(r.abs), theta)
+      a = Complex(log!(z.abs), z.arg)
       if b
 	a /= log(b)
       end
@@ -47,8 +49,16 @@
     end
   end
 
+  def log2(z)
+    if z.real? and z >= 0
+      log2!(z)
+    else
+      log(z) / log!(2)
+    end
+  end
+
   def log10(z)
-    if z.real?
+    if z.real? and z >= 0
       log10!(z)
     else
       log(z) / log!(10)
@@ -63,7 +73,8 @@
 	sqrt!(z)
       end
     else
-      if z.imag < 0
+      if z.imag < 0 ||
+	  (z.imag == 0 && z.imag.to_s[0] == '-')
 	sqrt(z.conjugate).conjugate
       else
 	r = z.abs
@@ -73,6 +84,14 @@
     end
   end
 
+  def cbrt(z)
+    if z.real? and z >= 0
+      cbrt!(z)
+    else
+      Complex(z) ** (1.0/3)
+    end
+  end
+
   def sin(z)
     if z.real?
       sin!(z)
@@ -95,7 +114,7 @@
     if z.real?
       tan!(z)
     else
-      sin(z)/cos(z)
+      sin(z) / cos(z)
     end
   end
 
@@ -129,7 +148,7 @@
     if z.real? and z >= -1 and z <= 1
       asin!(z)
     else
-      Complex(0, -1.0) * log(Complex(0, 1.0) * z + sqrt(1.0 - z * z))
+      (-1.0).i * log(1.0.i * z + sqrt(1.0 - z * z))
     end
   end
 
@@ -137,7 +156,7 @@
     if z.real? and z >= -1 and z <= 1
       acos!(z)
     else
-      Complex(0, -1.0) * log(z + Complex(0, 1.0) * sqrt(1.0 - z * z))
+      (-1.0).i * log(z + 1.0.i * sqrt(1.0 - z * z))
     end
   end
 
@@ -145,7 +164,7 @@
     if z.real?
       atan!(z)
     else
-      Complex(0, 1.0) * log((Complex(0, 1.0) + z) / (Complex(0, 1.0) - z)) / 2.0
+      1.0.i * log((1.0.i + z) / (1.0.i - z)) / 2.0
     end
   end
 
@@ -153,10 +172,18 @@
     if y.real? and x.real?
       atan2!(y,x)
     else
-      Complex(0, -1.0) * log((x + Complex(0, 1.0) * y) / sqrt(x * x + y * y))
+      (-1.0).i * log((x + 1.0.i * y) / sqrt(x * x + y * y))
     end
   end
 
+  def asinh(z)
+    if z.real?
+      asinh!(z)
+    else
+      log(z + sqrt(1.0 + z * z))
+    end
+  end
+
   def acosh(z)
     if z.real? and z >= 1
       acosh!(z)
@@ -165,14 +192,6 @@
     end
   end
 
-  def asinh(z)
-    if z.real?
-      asinh!(z)
-    else
-      log(z + sqrt(1.0 + z * z))
-    end
-  end
-
   def atanh(z)
     if z.real? and z >= -1 and z <= 1
       atanh!(z)
@@ -185,10 +204,14 @@
   module_function :exp
   module_function :log!
   module_function :log
+  module_function :log2!
+  module_function :log2
   module_function :log10!
   module_function :log10
   module_function :sqrt!
   module_function :sqrt
+  module_function :cbrt!
+  module_function :cbrt
 
   module_function :sin!
   module_function :sin
@@ -220,8 +243,6 @@
   module_function :atanh!
   module_function :atanh
 
-  module_function :log2
-  module_function :cbrt
   module_function :frexp
   module_function :ldexp
   module_function :hypot

Modified: MacRuby/trunk/lib/complex.rb
===================================================================
--- MacRuby/trunk/lib/complex.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/complex.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +1,7 @@
+# :enddoc:
+
+warn('lib/complex.rb is deprecated') if $VERBOSE
+
 require 'cmath'
 
 unless defined?(Math.exp!)

Modified: MacRuby/trunk/lib/csv.rb
===================================================================
--- MacRuby/trunk/lib/csv.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/csv.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,42 +1,41 @@
-#!/usr/bin/env ruby -w
-# encoding: UTF-8
+# encoding: US-ASCII
 # = csv.rb -- CSV Reading and Writing
 #
 #  Created by James Edward Gray II on 2005-10-31.
 #  Copyright 2005 James Edward Gray II. You can redistribute or modify this code
 #  under the terms of Ruby's license.
-# 
+#
 # See CSV for documentation.
-# 
+#
 # == Description
-# 
+#
 # Welcome to the new and improved CSV.
-# 
+#
 # This version of the CSV library began its life as FasterCSV.  FasterCSV was
 # intended as a replacement to Ruby's then standard CSV library.  It was
 # designed to address concerns users of that library had and it had three
 # primary goals:
-# 
+#
 # 1.  Be significantly faster than CSV while remaining a pure Ruby library.
 # 2.  Use a smaller and easier to maintain code base.  (FasterCSV eventually
 #     grew larger, was also but considerably richer in features.  The parsing
 #     core remains quite small.)
 # 3.  Improve on the CSV interface.
-# 
+#
 # Obviously, the last one is subjective.  I did try to defer to the original
 # interface whenever I didn't have a compelling reason to change it though, so
 # hopefully this won't be too radically different.
-# 
+#
 # We must have met our goals because FasterCSV was renamed to CSV and replaced
 # the original library.
-# 
+#
 # == What's Different From the Old CSV?
-# 
+#
 # I'm sure I'll miss something, but I'll try to mention most of the major
 # differences I am aware of, to help others quickly get up to speed:
-# 
+#
 # === CSV Parsing
-# 
+#
 # * This parser is m17n aware.  See CSV for full details.
 # * This library has a stricter parser and will throw MalformedCSVErrors on
 #   problematic data.
@@ -46,9 +45,9 @@
 # * The old library returned empty lines as <tt>[nil]</tt>.  This library calls
 #   them <tt>[]</tt>.
 # * This library has a much faster parser.
-# 
+#
 # === Interface
-# 
+#
 # * CSV now uses Hash-style parameters to set options.
 # * CSV no longer has generate_row() or parse_row().
 # * The old CSV's Reader and Writer classes have been dropped.
@@ -60,33 +59,33 @@
 # * CSV no longer supports partial reads.  It works line-by-line.
 # * CSV no longer allows the instance methods to override the separators for
 #   performance reasons.  They must be set in the constructor.
-# 
+#
 # If you use this library and find yourself missing any functionality I have
 # trimmed, please {let me know}[mailto:james at grayproductions.net].
-# 
+#
 # == Documentation
-# 
+#
 # See CSV for documentation.
-# 
+#
 # == What is CSV, really?
-# 
+#
 # CSV maintains a pretty strict definition of CSV taken directly from
 # {the RFC}[http://www.ietf.org/rfc/rfc4180.txt].  I relax the rules in only one
 # place and that is to make using this library easier.  CSV will parse all valid
 # CSV.
-# 
+#
 # What you don't want to do is feed CSV invalid data.  Because of the way the
 # CSV format works, it's common for a parser to need to read until the end of
 # the file to be sure a field is invalid.  This eats a lot of time and memory.
-# 
+#
 # Luckily, when working with invalid CSV, Ruby's built-in methods will almost
 # always be superior in every way.  For example, parsing non-quoted fields is as
 # easy as:
-# 
+#
 #   data.split(",")
-# 
+#
 # == Questions and/or Comments
-# 
+#
 # Feel free to email {James Edward Gray II}[mailto:james at grayproductions.net]
 # with any questions.
 
@@ -95,139 +94,139 @@
 require "date"
 require "stringio"
 
-# 
+#
 # This class provides a complete interface to CSV files and data.  It offers
 # tools to enable you to read and write to and from Strings or IO objects, as
 # needed.
-# 
+#
 # == Reading
-# 
+#
 # === From a File
-# 
+#
 # ==== A Line at a Time
-# 
+#
 #   CSV.foreach("path/to/file.csv") do |row|
 #     # use row here...
 #   end
-# 
+#
 # ==== All at Once
-# 
+#
 #   arr_of_arrs = CSV.read("path/to/file.csv")
-# 
+#
 # === From a String
-# 
+#
 # ==== A Line at a Time
-# 
+#
 #   CSV.parse("CSV,data,String") do |row|
 #     # use row here...
 #   end
-# 
+#
 # ==== All at Once
-# 
+#
 #   arr_of_arrs = CSV.parse("CSV,data,String")
-# 
+#
 # == Writing
-# 
+#
 # === To a File
-# 
+#
 #   CSV.open("path/to/file.csv", "wb") do |csv|
 #     csv << ["row", "of", "CSV", "data"]
 #     csv << ["another", "row"]
 #     # ...
 #   end
-# 
+#
 # === To a String
-# 
+#
 #   csv_string = CSV.generate do |csv|
 #     csv << ["row", "of", "CSV", "data"]
 #     csv << ["another", "row"]
 #     # ...
 #   end
-# 
+#
 # == Convert a Single Line
-# 
+#
 #   csv_string = ["CSV", "data"].to_csv   # to CSV
 #   csv_array  = "CSV,String".parse_csv   # from CSV
-# 
+#
 # == Shortcut Interface
-# 
+#
 #   CSV             { |csv_out| csv_out << %w{my data here} }  # to $stdout
 #   CSV(csv = "")   { |csv_str| csv_str << %w{my data here} }  # to a String
 #   CSV($stderr)    { |csv_err| csv_err << %w{my data here} }  # to $stderr
-# 
+#
 # == CSV and Character Encodings (M17n or Multilingualization)
-# 
+#
 # This new CSV parser is m17n savvy.  The parser works in the Encoding of the IO
 # or String object being read from or written to.  Your data is never transcoded
 # (unless you ask Ruby to transcode it for you) and will literally be parsed in
 # the Encoding it is in.  Thus CSV will return Arrays or Rows of Strings in the
 # Encoding of your data.  This is accomplished by transcoding the parser itself
 # into your Encoding.
-# 
+#
 # Some transcoding must take place, of course, to accomplish this multiencoding
 # support.  For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
 # <tt>:quote_char</tt> must be transcoded to match your data.  Hopefully this
 # makes the entire process feel transparent, since CSV's defaults should just
 # magically work for you data.  However, you can set these values manually in
 # the target Encoding to avoid the translation.
-# 
+#
 # It's also important to note that while all of CSV's core parser is now
 # Encoding agnostic, some features are not.  For example, the built-in
 # converters will try to transcode data to UTF-8 before making conversions.
 # Again, you can provide custom converters that are aware of your Encodings to
 # avoid this translation.  It's just too hard for me to support native
 # conversions in all of Ruby's Encodings.
-# 
+#
 # Anyway, the practical side of this is simple:  make sure IO and String objects
 # passed into CSV have the proper Encoding set and everything should just work.
 # CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
 # CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
-# 
+#
 # One minor exception comes when generating CSV into a String with an Encoding
 # that is not ASCII compatible.  There's no existing data for CSV to use to
 # prepare itself and thus you will probably need to manually specify the desired
 # Encoding for most of those cases.  It will try to guess using the fields in a
 # row of output though, when using CSV::generate_line() or Array#to_csv().
-# 
+#
 # I try to point out any other Encoding issues in the documentation of methods
 # as they come up.
-# 
+#
 # This has been tested to the best of my ability with all non-"dummy" Encodings
 # Ruby ships with.  However, it is brave new code and may have some bugs.
 # Please feel free to {report}[mailto:james at grayproductions.net] any issues you
 # find with it.
-# 
+#
 class CSV
   # The version of the installed library.
-  VERSION = "2.4.5".freeze
-  
-  # 
+  VERSION = "2.4.6".freeze
+
+  #
   # A CSV::Row is part Array and part Hash.  It retains an order for the fields
   # and allows duplicates just as an Array would, but also allows you to access
   # fields by name just as you could if they were in a Hash.
-  # 
+  #
   # All rows returned by CSV will be constructed from this class, if header row
   # processing is activated.
-  # 
+  #
   class Row
-    # 
+    #
     # Construct a new CSV::Row from +headers+ and +fields+, which are expected
     # to be Arrays.  If one Array is shorter than the other, it will be padded
     # with +nil+ objects.
-    # 
+    #
     # The optional +header_row+ parameter can be set to +true+ to indicate, via
     # CSV::Row.header_row?() and CSV::Row.field_row?(), that this is a header
     # row.  Otherwise, the row is assumes to be a field row.
-    # 
+    #
     # A CSV::Row object supports the following Array methods through delegation:
-    # 
+    #
     # * empty?()
     # * length()
     # * size()
-    # 
+    #
     def initialize(headers, fields, header_row = false)
       @header_row = header_row
-      
+
       # handle extra headers or fields
       @row = if headers.size > fields.size
         headers.zip(fields)
@@ -235,7 +234,7 @@
         fields.zip(headers).map { |pair| pair.reverse }
       end
     end
-    
+
     # Internal data format used to compare equality.
     attr_reader :row
     protected   :row
@@ -244,35 +243,35 @@
 
     extend Forwardable
     def_delegators :@row, :empty?, :length, :size
-    
+
     # Returns +true+ if this is a header row.
     def header_row?
       @header_row
     end
-    
+
     # Returns +true+ if this is a field row.
     def field_row?
       not header_row?
     end
-    
+
     # Returns the headers of this row.
     def headers
       @row.map { |pair| pair.first }
     end
-    
-    # 
+
+    #
     # :call-seq:
     #   field( header )
     #   field( header, offset )
     #   field( index )
-    # 
+    #
     # This method will fetch the field value by +header+ or +index+.  If a field
     # is not found, +nil+ is returned.
-    # 
+    #
     # When provided, +offset+ ensures that a header match occurrs on or later
-    # than the +offset+ index.  You can use this to find duplicate headers, 
+    # than the +offset+ index.  You can use this to find duplicate headers,
     # without resorting to hard-coding exact indices.
-    # 
+    #
     def field(header_or_index, minimum_index = 0)
       # locate the pair
       finder = header_or_index.is_a?(Integer) ? :[] : :assoc
@@ -282,23 +281,23 @@
       pair.nil? ? nil : pair.last
     end
     alias_method :[], :field
-    
-    # 
+
+    #
     # :call-seq:
     #   []=( header, value )
     #   []=( header, offset, value )
     #   []=( index, value )
-    # 
+    #
     # Looks up the field by the semantics described in CSV::Row.field() and
     # assigns the +value+.
-    # 
+    #
     # Assigning past the end of the row with an index will set all pairs between
     # to <tt>[nil, nil]</tt>.  Assigning to an unused header appends the new
     # pair.
-    # 
+    #
     def []=(*args)
       value = args.pop
-      
+
       if args.first.is_a? Integer
         if @row[args.first].nil?  # extending past the end with index
           @row[args.first] = [nil, value]
@@ -315,20 +314,20 @@
         end
       end
     end
-    
-    # 
+
+    #
     # :call-seq:
     #   <<( field )
     #   <<( header_and_field_array )
     #   <<( header_and_field_hash )
-    # 
+    #
     # If a two-element Array is provided, it is assumed to be a header and field
     # and the pair is appended.  A Hash works the same way with the key being
     # the header and the value being the field.  Anything else is assumed to be
     # a lone field which is appended with a +nil+ header.
-    # 
+    #
     # This method returns the row for chaining.
-    # 
+    #
     def <<(arg)
       if arg.is_a?(Array) and arg.size == 2  # appending a header and name
         @row << arg
@@ -337,62 +336,64 @@
       else                                   # append field value
         @row << [nil, arg]
       end
-      
+
       self  # for chaining
     end
-    
-    # 
+
+    #
     # A shortcut for appending multiple fields.  Equivalent to:
-    # 
+    #
     #   args.each { |arg| csv_row << arg }
-    # 
+    #
     # This method returns the row for chaining.
-    # 
+    #
     def push(*args)
       args.each { |arg| self << arg }
-      
+
       self  # for chaining
     end
-    
-    # 
+
+    #
     # :call-seq:
     #   delete( header )
     #   delete( header, offset )
     #   delete( index )
-    # 
+    #
     # Used to remove a pair from the row by +header+ or +index+.  The pair is
     # located as described in CSV::Row.field().  The deleted pair is returned,
     # or +nil+ if a pair could not be found.
-    # 
+    #
     def delete(header_or_index, minimum_index = 0)
-      if header_or_index.is_a? Integer  # by index
+      if header_or_index.is_a? Integer                 # by index
         @row.delete_at(header_or_index)
-      else                              # by header
-        @row.delete_at(index(header_or_index, minimum_index))
+      elsif i = index(header_or_index, minimum_index)  # by header
+        @row.delete_at(i)
+      else
+        [ ]
       end
     end
-    
-    # 
+
+    #
     # The provided +block+ is passed a header and field for each pair in the row
     # and expected to return +true+ or +false+, depending on whether the pair
     # should be deleted.
-    # 
+    #
     # This method returns the row for chaining.
-    # 
+    #
     def delete_if(&block)
       @row.delete_if(&block)
-      
+
       self  # for chaining
     end
-    
-    # 
+
+    #
     # This method accepts any number of arguments which can be headers, indices,
-    # Ranges of either, or two-element Arrays containing a header and offset.  
+    # Ranges of either, or two-element Arrays containing a header and offset.
     # Each argument will be replaced with a field lookup as described in
     # CSV::Row.field().
-    # 
+    #
     # If called with no arguments, all fields are returned.
-    # 
+    #
     def fields(*headers_and_or_indices)
       if headers_and_or_indices.empty?  # return all fields--no arguments
         @row.map { |pair| pair.last }
@@ -413,80 +414,80 @@
       end
     end
     alias_method :values_at, :fields
-    
-    # 
+
+    #
     # :call-seq:
     #   index( header )
     #   index( header, offset )
-    # 
+    #
     # This method will return the index of a field with the provided +header+.
     # The +offset+ can be used to locate duplicate header names, as described in
     # CSV::Row.field().
-    # 
+    #
     def index(header, minimum_index = 0)
       # find the pair
       index = headers[minimum_index..-1].index(header)
       # return the index at the right offset, if we found one
       index.nil? ? nil : index + minimum_index
     end
-    
+
     # Returns +true+ if +name+ is a header for this row, and +false+ otherwise.
     def header?(name)
       headers.include? name
     end
     alias_method :include?, :header?
-    
-    # 
+
+    #
     # Returns +true+ if +data+ matches a field in this row, and +false+
     # otherwise.
-    # 
+    #
     def field?(data)
       fields.include? data
     end
 
     include Enumerable
-    
-    # 
+
+    #
     # Yields each pair of the row as header and field tuples (much like
     # iterating over a Hash).
-    # 
+    #
     # Support for Enumerable.
-    # 
+    #
     # This method returns the row for chaining.
-    # 
+    #
     def each(&block)
       @row.each(&block)
-      
+
       self  # for chaining
     end
-    
-    # 
-    # Returns +true+ if this row contains the same headers and fields in the 
+
+    #
+    # Returns +true+ if this row contains the same headers and fields in the
     # same order as +other+.
-    # 
+    #
     def ==(other)
       @row == other.row
     end
-    
-    # 
+
+    #
     # Collapses the row into a simple Hash.  Be warning that this discards field
     # order and clobbers duplicate fields.
-    # 
+    #
     def to_hash
       # flatten just one level of the internal Array
       Hash[*@row.inject(Array.new) { |ary, pair| ary.push(*pair) }]
     end
-    
-    # 
+
+    #
     # Returns the row as a CSV String.  Headers are not used.  Equivalent to:
-    # 
+    #
     #   csv_row.fields.to_csv( options )
-    # 
+    #
     def to_csv(options = Hash.new)
       fields.to_csv(options)
     end
     alias_method :to_s, :to_csv
-    
+
     # A summary of fields, by header, in an ASCII compatible String.
     def inspect
       str = ["#<", self.class.to_s]
@@ -505,35 +506,35 @@
       end
     end
   end
-  
-  # 
+
+  #
   # A CSV::Table is a two-dimensional data structure for representing CSV
-  # documents.  Tables allow you to work with the data by row or column, 
+  # documents.  Tables allow you to work with the data by row or column,
   # manipulate the data, and even convert the results back to CSV, if needed.
-  # 
+  #
   # All tables returned by CSV will be constructed from this class, if header
   # row processing is activated.
-  # 
+  #
   class Table
-    # 
+    #
     # Construct a new CSV::Table from +array_of_rows+, which are expected
     # to be CSV::Row objects.  All rows are assumed to have the same headers.
-    # 
+    #
     # A CSV::Table object supports the following Array methods through
     # delegation:
-    # 
+    #
     # * empty?()
     # * length()
     # * size()
-    # 
+    #
     def initialize(array_of_rows)
       @table = array_of_rows
       @mode  = :col_or_row
     end
-    
+
     # The current access mode for indexing and iteration.
     attr_reader :mode
-    
+
     # Internal data format used to compare equality.
     attr_reader :table
     protected   :table
@@ -542,88 +543,88 @@
 
     extend Forwardable
     def_delegators :@table, :empty?, :length, :size
-    
-    # 
-    # Returns a duplicate table object, in column mode.  This is handy for 
-    # chaining in a single call without changing the table mode, but be aware 
+
+    #
+    # Returns a duplicate table object, in column mode.  This is handy for
+    # chaining in a single call without changing the table mode, but be aware
     # that this method can consume a fair amount of memory for bigger data sets.
-    # 
+    #
     # This method returns the duplicate table for chaining.  Don't chain
     # destructive methods (like []=()) this way though, since you are working
     # with a duplicate.
-    # 
+    #
     def by_col
       self.class.new(@table.dup).by_col!
     end
-    
-    # 
+
+    #
     # Switches the mode of this table to column mode.  All calls to indexing and
     # iteration methods will work with columns until the mode is changed again.
-    # 
+    #
     # This method returns the table and is safe to chain.
-    # 
+    #
     def by_col!
       @mode = :col
-      
+
       self
     end
-    
-    # 
-    # Returns a duplicate table object, in mixed mode.  This is handy for 
-    # chaining in a single call without changing the table mode, but be aware 
+
+    #
+    # Returns a duplicate table object, in mixed mode.  This is handy for
+    # chaining in a single call without changing the table mode, but be aware
     # that this method can consume a fair amount of memory for bigger data sets.
-    # 
+    #
     # This method returns the duplicate table for chaining.  Don't chain
     # destructive methods (like []=()) this way though, since you are working
     # with a duplicate.
-    # 
+    #
     def by_col_or_row
       self.class.new(@table.dup).by_col_or_row!
     end
-    
-    # 
+
+    #
     # Switches the mode of this table to mixed mode.  All calls to indexing and
     # iteration methods will use the default intelligent indexing system until
     # the mode is changed again.  In mixed mode an index is assumed to be a row
     # reference while anything else is assumed to be column access by headers.
-    # 
+    #
     # This method returns the table and is safe to chain.
-    # 
+    #
     def by_col_or_row!
       @mode = :col_or_row
-      
+
       self
     end
-    
-    # 
+
+    #
     # Returns a duplicate table object, in row mode.  This is handy for chaining
     # in a single call without changing the table mode, but be aware that this
     # method can consume a fair amount of memory for bigger data sets.
-    # 
+    #
     # This method returns the duplicate table for chaining.  Don't chain
     # destructive methods (like []=()) this way though, since you are working
     # with a duplicate.
-    # 
+    #
     def by_row
       self.class.new(@table.dup).by_row!
     end
-    
-    # 
+
+    #
     # Switches the mode of this table to row mode.  All calls to indexing and
     # iteration methods will work with rows until the mode is changed again.
-    # 
+    #
     # This method returns the table and is safe to chain.
-    # 
+    #
     def by_row!
       @mode = :row
-      
+
       self
     end
-    
-    # 
+
+    #
     # Returns the headers for the first row of this table (assumed to match all
     # other rows).  An empty Array is returned for empty tables.
-    # 
+    #
     def headers
       if @table.empty?
         Array.new
@@ -631,15 +632,15 @@
         @table.first.headers
       end
     end
-    
-    # 
+
+    #
     # In the default mixed mode, this method returns rows for index access and
     # columns for header access.  You can force the index association by first
     # calling by_col!() or by_row!().
-    # 
+    #
     # Columns are returned as an Array of values.  Altering that Array has no
     # effect on the table.
-    # 
+    #
     def [](index_or_header)
       if @mode == :row or  # by index
          (@mode == :col_or_row and index_or_header.is_a? Integer)
@@ -648,23 +649,23 @@
         @table.map { |row| row[index_or_header] }
       end
     end
-    
-    # 
+
+    #
     # In the default mixed mode, this method assigns rows for index access and
     # columns for header access.  You can force the index association by first
     # calling by_col!() or by_row!().
-    # 
+    #
     # Rows may be set to an Array of values (which will inherit the table's
     # headers()) or a CSV::Row.
-    # 
-    # Columns may be set to a single value, which is copied to each row of the 
+    #
+    # Columns may be set to a single value, which is copied to each row of the
     # column, or an Array of values.  Arrays of values are assigned to rows top
     # to bottom in row major order.  Excess values are ignored and if the Array
     # does not have a value for each row the extra rows will receive a +nil+.
-    # 
+    #
     # Assigning to an existing column or row clobbers the data.  Assigning to
     # new columns creates them at the right end of the table.
-    # 
+    #
     def []=(index_or_header, value)
       if @mode == :row or  # by index
          (@mode == :col_or_row and index_or_header.is_a? Integer)
@@ -693,16 +694,16 @@
         end
       end
     end
-    
-    # 
+
+    #
     # The mixed mode default is to treat a list of indices as row access,
     # returning the rows indicated.  Anything else is considered columnar
     # access.  For columnar access, the return set has an Array for each row
     # with the values indicated by the headers in each Array.  You can force
     # column or row mode using by_col!() or by_row!().
-    # 
+    #
     # You cannot mix column and row access.
-    # 
+    #
     def values_at(*indices_or_headers)
       if @mode == :row or  # by indices
          ( @mode == :col_or_row and indices_or_headers.all? do |index|
@@ -717,41 +718,41 @@
       end
     end
 
-    # 
+    #
     # Adds a new row to the bottom end of this table.  You can provide an Array,
     # which will be converted to a CSV::Row (inheriting the table's headers()),
     # or a CSV::Row.
-    # 
+    #
     # This method returns the table for chaining.
-    # 
+    #
     def <<(row_or_array)
       if row_or_array.is_a? Array  # append Array
         @table << Row.new(headers, row_or_array)
       else                         # append Row
         @table << row_or_array
       end
-      
+
       self  # for chaining
     end
-    
-    # 
+
+    #
     # A shortcut for appending multiple rows.  Equivalent to:
-    # 
+    #
     #   rows.each { |row| self << row }
-    # 
+    #
     # This method returns the table for chaining.
-    # 
+    #
     def push(*rows)
       rows.each { |row| self << row }
-      
+
       self  # for chaining
     end
 
-    # 
+    #
     # Removes and returns the indicated column or row.  In the default mixed
     # mode indices refer to rows and everything else is assumed to be a column
     # header.  Use by_col!() or by_row!() to force the lookup.
-    # 
+    #
     def delete(index_or_header)
       if @mode == :row or  # by index
          (@mode == :col_or_row and index_or_header.is_a? Integer)
@@ -760,15 +761,15 @@
         @table.map { |row| row.delete(index_or_header).last }
       end
     end
-    
-    # 
+
+    #
     # Removes any column or row for which the block returns +true+.  In the
     # default mixed mode or row mode, iteration is the standard row major
     # walking of rows.  In column mode, interation will +yield+ two element
     # tuples containing the column name and an Array of values for that column.
-    # 
+    #
     # This method returns the table for chaining.
-    # 
+    #
     def delete_if(&block)
       if @mode == :row or @mode == :col_or_row  # by index
         @table.delete_if(&block)
@@ -779,38 +780,38 @@
         end
         to_delete.map { |header| delete(header) }
       end
-      
+
       self  # for chaining
     end
-    
+
     include Enumerable
-    
-    # 
+
+    #
     # In the default mixed mode or row mode, iteration is the standard row major
     # walking of rows.  In column mode, interation will +yield+ two element
     # tuples containing the column name and an Array of values for that column.
-    # 
+    #
     # This method returns the table for chaining.
-    # 
+    #
     def each(&block)
       if @mode == :col
         headers.each { |header| block[[header, self[header]]] }
       else
         @table.each(&block)
       end
-      
+
       self  # for chaining
     end
-    
+
     # Returns +true+ if all rows of this table ==() +other+'s rows.
     def ==(other)
       @table == other.table
     end
-    
-    # 
+
+    #
     # Returns the table as an Array of Arrays.  Headers will be the first row,
     # then all of the field rows will follow.
-    # 
+    #
     def to_a
       @table.inject([headers]) do |array, row|
         if row.header_row?
@@ -820,13 +821,17 @@
         end
       end
     end
-    
-    # 
+
+    #
     # Returns the table as a complete CSV String.  Headers will be listed first,
     # then all of the field rows.
+    #
+    # This method assumes you want the Table.headers(), unless you explicitly
+    # pass <tt>:write_headers => false</tt>.
     # 
     def to_csv(options = Hash.new)
-      @table.inject([headers.to_csv(options)]) do |rows, row|
+      wh = options.fetch(:write_headers, true)
+      @table.inject(wh ? [headers.to_csv(options)] : [ ]) do |rows, row|
         if row.header_row?
           rows
         else
@@ -835,7 +840,7 @@
       end.join
     end
     alias_method :to_s, :to_csv
-    
+
     # Shows the mode and size of this table in a US-ASCII String.
     def inspect
       "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII")
@@ -844,19 +849,19 @@
 
   # The error thrown when the parser encounters illegal CSV formatting.
   class MalformedCSVError < RuntimeError; end
-  
-  # 
+
+  #
   # A FieldInfo Struct contains details about a field's position in the data
   # source it was read from.  CSV will pass this Struct to some blocks that make
   # decisions based on field structure.  See CSV.convert_fields() for an
   # example.
-  # 
+  #
   # <b><tt>index</tt></b>::  The zero-based index of the field in its row.
   # <b><tt>line</tt></b>::   The line of the data source this row is from.
   # <b><tt>header</tt></b>:: The header for the column, when available.
-  # 
+  #
   FieldInfo = Struct.new(:index, :line, :header)
-  
+
   # A Regexp used to find and convert some common Date formats.
   DateMatcher     = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} |
                             \d{4}-\d{2}-\d{2} )\z /x
@@ -864,34 +869,34 @@
   DateTimeMatcher =
     / \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} |
             \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} )\z /x
-  
+
   # The encoding used by all converters.
   ConverterEncoding = Encoding.find("UTF-8")
-  
-  # 
+
+  #
   # This Hash holds the built-in converters of CSV that can be accessed by name.
   # You can select Converters with CSV.convert() or through the +options+ Hash
   # passed to CSV::new().
-  # 
+  #
   # <b><tt>:integer</tt></b>::    Converts any field Integer() accepts.
   # <b><tt>:float</tt></b>::      Converts any field Float() accepts.
-  # <b><tt>:numeric</tt></b>::    A combination of <tt>:integer</tt> 
+  # <b><tt>:numeric</tt></b>::    A combination of <tt>:integer</tt>
   #                               and <tt>:float</tt>.
   # <b><tt>:date</tt></b>::       Converts any field Date::parse() accepts.
   # <b><tt>:date_time</tt></b>::  Converts any field DateTime::parse() accepts.
-  # <b><tt>:all</tt></b>::        All built-in converters.  A combination of 
+  # <b><tt>:all</tt></b>::        All built-in converters.  A combination of
   #                               <tt>:date_time</tt> and <tt>:numeric</tt>.
-  # 
+  #
   # All built-in converters transcode field data to UTF-8 before attempting a
   # conversion.  If your data cannot be transcoded to UTF-8 the conversion will
   # fail and the field will remain unchanged.
-  # 
+  #
   # This Hash is intentionally left unfrozen and users should feel free to add
   # values to it that can be accessed by all CSV objects.
-  # 
+  #
   # To add a combo field, the value should be an Array of names.  Combo fields
   # can be nested with other combo fields.
-  # 
+  #
   Converters  = { integer:   lambda { |f|
                     Integer(f.encode(ConverterEncoding)) rescue f
                   },
@@ -917,26 +922,26 @@
                   },
                   all:       [:date_time, :numeric] }
 
-  # 
+  #
   # This Hash holds the built-in header converters of CSV that can be accessed
   # by name.  You can select HeaderConverters with CSV.header_convert() or
   # through the +options+ Hash passed to CSV::new().
-  # 
+  #
   # <b><tt>:downcase</tt></b>::  Calls downcase() on the header String.
   # <b><tt>:symbol</tt></b>::    The header String is downcased, spaces are
   #                              replaced with underscores, non-word characters
   #                              are dropped, and finally to_sym() is called.
-  # 
+  #
   # All built-in header converters transcode header data to UTF-8 before
   # attempting a conversion.  If your data cannot be transcoded to UTF-8 the
   # conversion will fail and the header will remain unchanged.
-  # 
+  #
   # This Hash is intetionally left unfrozen and users should feel free to add
   # values to it that can be accessed by all CSV objects.
-  # 
+  #
   # To add a combo field, the value should be an Array of names.  Combo fields
   # can be nested with other combo fields.
-  # 
+  #
   HeaderConverters = {
     downcase: lambda { |h| h.encode(ConverterEncoding).downcase },
     symbol:   lambda { |h|
@@ -944,10 +949,10 @@
                                            gsub(/\W+/, "").to_sym
     }
   }
-  
-  # 
+
+  #
   # The options used when no overrides are given by calling code.  They are:
-  # 
+  #
   # <b><tt>:col_sep</tt></b>::            <tt>","</tt>
   # <b><tt>:row_sep</tt></b>::            <tt>:auto</tt>
   # <b><tt>:quote_char</tt></b>::         <tt>'"'</tt>
@@ -959,10 +964,10 @@
   # <b><tt>:header_converters</tt></b>::  +nil+
   # <b><tt>:skip_blanks</tt></b>::        +false+
   # <b><tt>:force_quotes</tt></b>::       +false+
-  # 
+  #
   DEFAULT_OPTIONS = { col_sep:            ",",
                       row_sep:            :auto,
-                      quote_char:         '"', 
+                      quote_char:         '"',
                       field_size_limit:   nil,
                       converters:         nil,
                       unconverted_fields: nil,
@@ -971,21 +976,21 @@
                       header_converters:  nil,
                       skip_blanks:        false,
                       force_quotes:       false }.freeze
-  
-  # 
+
+  #
   # This method will return a CSV instance, just like CSV::new(), but the
   # instance will be cached and returned for all future calls to this method for
   # the same +data+ object (tested by Object#object_id()) with the same
   # +options+.
-  # 
+  #
   # If a block is given, the instance is passed to the block and the return
   # value becomes the return value of the block.
-  # 
+  #
   def self.instance(data = $stdout, options = Hash.new)
     # create a _signature_ for this method call, data object and options
     sig = [data.object_id] +
           options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
-    
+
     # fetch or create the instance for this signature
     @@instances ||= Hash.new
     instance    =   (@@instances[sig] ||= new(data, options))
@@ -997,25 +1002,25 @@
     end
   end
 
-  # 
+  #
   # This method allows you to serialize an Array of Ruby objects to a String or
   # File of CSV data.  This is not as powerful as Marshal or YAML, but perhaps
   # useful for spreadsheet and database interaction.
-  # 
+  #
   # Out of the box, this method is intended to work with simple data objects or
   # Structs.  It will serialize a list of instance variables and/or
   # Struct.members().
-  # 
+  #
   # If you need need more complicated serialization, you can control the process
   # by adding methods to the class to be serialized.
-  # 
+  #
   # A class method csv_meta() is responsible for returning the first row of the
   # document (as an Array).  This row is considered to be a Hash of the form
   # key_1,value_1,key_2,value_2,...  CSV::load() expects to find a class key
   # with a value of the stringified class name and CSV::dump() will create this,
   # if you do not define this method.  This method is only called on the first
   # object of the Array.
-  # 
+  #
   # The next method you can provide is an instance method called csv_headers().
   # This method is expected to return the second line of the document (again as
   # an Array), which is to be used to give each column a header.  By default,
@@ -1023,20 +1028,20 @@
   # @ character or call send() passing the header as the method name and
   # the field value as an argument.  This method is only called on the first
   # object of the Array.
-  # 
+  #
   # Finally, you can provide an instance method called csv_dump(), which will
   # be passed the headers.  This should return an Array of fields that can be
   # serialized for this object.  This method is called once for every object in
   # the Array.
-  # 
+  #
   # The +io+ parameter can be used to serialize to a File, and +options+ can be
   # anything CSV::new() accepts.
-  # 
+  #
   def self.dump(ary_of_objs, io = "", options = Hash.new)
     obj_template = ary_of_objs.first
-    
+
     csv = new(io, options)
-    
+
     # write meta information
     begin
       csv << obj_template.class.csv_meta
@@ -1054,7 +1059,7 @@
       end
     end
     csv << headers
-    
+
     # serialize each object
     ary_of_objs.each do |obj|
       begin
@@ -1069,39 +1074,39 @@
         end
       end
     end
-    
+
     if io.is_a? String
       csv.string
     else
       csv.close
     end
   end
-  
-  # 
+
+  #
   # This method is the reading counterpart to CSV::dump().  See that method for
   # a detailed description of the process.
-  # 
-  # You can customize loading by adding a class method called csv_load() which 
+  #
+  # You can customize loading by adding a class method called csv_load() which
   # will be passed a Hash of meta information, an Array of headers, and an Array
   # of fields for the object the method is expected to return.
-  # 
+  #
   # Remember that all fields will be Strings after this load.  If you need
   # something else, use +options+ to setup converters or provide a custom
   # csv_load() implementation.
-  # 
+  #
   def self.load(io_or_str, options = Hash.new)
     csv = new(io_or_str, options)
-    
+
     # load meta information
     meta = Hash[*csv.shift]
     cls  = meta["class".encode(csv.encoding)].split("::".encode(csv.encoding)).
                                               inject(Object) do |c, const|
       c.const_get(const)
     end
-    
+
     # load headers
     headers = csv.shift
-    
+
     # unserialize each object stored in the file
     results = csv.inject(Array.new) do |all, row|
       begin
@@ -1118,36 +1123,36 @@
       end
       all << obj
     end
-    
+
     csv.close unless io_or_str.is_a? String
-    
+
     results
   end
-  
-  # 
+
+  #
   # :call-seq:
   #   filter( options = Hash.new ) { |row| ... }
   #   filter( input, options = Hash.new ) { |row| ... }
   #   filter( input, output, options = Hash.new ) { |row| ... }
-  # 
+  #
   # This method is a convenience for building Unix-like filters for CSV data.
-  # Each row is yielded to the provided block which can alter it as needed.  
+  # Each row is yielded to the provided block which can alter it as needed.
   # After the block returns, the row is appended to +output+ altered or not.
-  # 
+  #
   # The +input+ and +output+ arguments can be anything CSV::new() accepts
-  # (generally String or IO objects).  If not given, they default to 
+  # (generally String or IO objects).  If not given, they default to
   # <tt>ARGF</tt> and <tt>$stdout</tt>.
-  # 
+  #
   # The +options+ parameter is also filtered down to CSV::new() after some
-  # clever key parsing.  Any key beginning with <tt>:in_</tt> or 
+  # clever key parsing.  Any key beginning with <tt>:in_</tt> or
   # <tt>:input_</tt> will have that leading identifier stripped and will only
   # be used in the +options+ Hash for the +input+ object.  Keys starting with
-  # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+.  All other keys 
+  # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+.  All other keys
   # are assigned to both objects.
-  # 
+  #
   # The <tt>:output_row_sep</tt> +option+ defaults to
   # <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
-  # 
+  #
   def self.filter(*args)
     # parse options for input, output, or both
     in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
@@ -1167,19 +1172,19 @@
     # build input and output wrappers
     input  = new(args.shift || ARGF,    in_options)
     output = new(args.shift || $stdout, out_options)
-    
+
     # read, yield, write
     input.each do |row|
       yield row
       output << row
     end
   end
-  
-  # 
+
+  #
   # This method is intended as the primary interface for reading CSV files.  You
   # pass a +path+ and any +options+ you wish to set for the read.  Each row of
   # file will be passed to the provided +block+ in turn.
-  # 
+  #
   # The +options+ parameter can be anything CSV::new() understands.  This method
   # also understands an additional <tt>:encoding</tt> parameter that you can use
   # to specify the Encoding of the data in the file to be read. You must provide
@@ -1188,7 +1193,7 @@
   # have the data transcoded as it is read.  For example,
   # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
   # but transcode it to UTF-8 before CSV parses it.
-  # 
+  #
   def self.foreach(path, options = Hash.new, &block)
     encoding =  options.delete(:encoding)
     mode     =  "rb"
@@ -1198,24 +1203,24 @@
     end
   end
 
-  # 
+  #
   # :call-seq:
   #   generate( str, options = Hash.new ) { |csv| ... }
   #   generate( options = Hash.new ) { |csv| ... }
-  # 
-  # This method wraps a String you provide, or an empty default String, in a 
+  #
+  # This method wraps a String you provide, or an empty default String, in a
   # CSV object which is passed to the provided block.  You can use the block to
   # append CSV rows to the String and when the block exits, the final String
   # will be returned.
-  # 
+  #
   # Note that a passed String *is* modfied by this method.  Call dup() before
   # passing if you need a new String.
-  # 
-  # The +options+ parameter can be anthing CSV::new() understands.  This method
+  #
+  # The +options+ parameter can be anything CSV::new() understands.  This method
   # understands an additional <tt>:encoding</tt> parameter when not passed a
   # String to set the base Encoding for the output.  CSV needs this hint if you
   # plan to output non-ASCII compatible data.
-  # 
+  #
   def self.generate(*args)
     # add a default empty String, if none was given
     if args.first.is_a? String
@@ -1233,19 +1238,19 @@
     csv.string        # return final String
   end
 
-  # 
-  # This method is a shortcut for converting a single row (Array) into a CSV 
+  #
+  # This method is a shortcut for converting a single row (Array) into a CSV
   # String.
-  # 
-  # The +options+ parameter can be anthing CSV::new() understands.  This method
-  # understands an additional <tt>:encoding</tt> parameter to set the base 
+  #
+  # The +options+ parameter can be anything CSV::new() understands.  This method
+  # understands an additional <tt>:encoding</tt> parameter to set the base
   # Encoding for the output.  This method will try to guess your Encoding from
   # the first non-+nil+ field in +row+, if possible, but you may need to use
   # this parameter as a backup plan.
-  # 
+  #
   # The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
   # (<tt>$/</tt>) when calling this method.
-  # 
+  #
   def self.generate_line(row, options = Hash.new)
     options  = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
     encoding = options.delete(:encoding)
@@ -1257,27 +1262,27 @@
     end
     (new(str, options) << row).string
   end
-  
-  # 
+
+  #
   # :call-seq:
   #   open( filename, mode = "rb", options = Hash.new ) { |faster_csv| ... }
   #   open( filename, options = Hash.new ) { |faster_csv| ... }
   #   open( filename, mode = "rb", options = Hash.new )
   #   open( filename, options = Hash.new )
-  # 
+  #
   # This method opens an IO object, and wraps that with CSV.  This is intended
   # as the primary interface for writing a CSV file.
-  # 
+  #
   # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
   # open().  You may also pass an optional Hash containing any +options+
   # CSV::new() understands as the final argument.
-  # 
+  #
   # This method works like Ruby's open() call, in that it will pass a CSV object
   # to a provided block and close it when the block terminates, or it will
   # return the CSV object when no block is provided.  (*Note*: This is different
   # from the Ruby 1.8 CSV library which passed rows to the block.  Use
   # CSV::foreach() for that behavior.)
-  # 
+  #
   # You must provide a +mode+ with an embedded Encoding designator unless your
   # data is in Encoding::default_external().  CSV will check the Encoding of the
   # underlying IO object (set by the +mode+ you pass) to deterime how to parse
@@ -1285,10 +1290,10 @@
   # it is read just as you can with a normal call to IO::open().  For example,
   # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
   # transcode it to UTF-8 before CSV parses it.
-  # 
+  #
   # An opened CSV object will delegate to many IO methods for convenience.  You
   # may call:
-  # 
+  #
   # * binmode()
   # * binmode?()
   # * close()
@@ -1320,7 +1325,7 @@
   # * to_io()
   # * truncate()
   # * tty?()
-  # 
+  #
   def self.open(*args)
     # find the +options+ Hash
     options = if args.last.is_a? Hash then args.pop else Hash.new end
@@ -1328,7 +1333,7 @@
     args << "rb" if args.size == 1
     # wrap a File opened with the remaining +args+
     csv     = new(File.open(*args), options)
-    
+
     # handle blocks like Ruby's open(), not like the CSV library
     if block_given?
       begin
@@ -1340,19 +1345,19 @@
       csv
     end
   end
-  
-  # 
+
+  #
   # :call-seq:
   #   parse( str, options = Hash.new ) { |row| ... }
   #   parse( str, options = Hash.new )
-  # 
+  #
   # This method can be used to easily parse CSV out of a String.  You may either
   # provide a +block+ which will be called with each row of the String in turn,
   # or just use the returned Array of Arrays (when no +block+ is given).
-  # 
+  #
   # You pass your +str+ to read from, and an optional +options+ Hash containing
   # anything CSV::new() understands.
-  # 
+  #
   def self.parse(*args, &block)
     csv = new(*args)
     if block.nil?  # slurp contents, if no block is given
@@ -1365,20 +1370,20 @@
       csv.each(&block)
     end
   end
-  
-  # 
-  # This method is a shortcut for converting a single line of a CSV String into 
-  # a into an Array.  Note that if +line+ contains multiple rows, anything 
+
+  #
+  # This method is a shortcut for converting a single line of a CSV String into
+  # a into an Array.  Note that if +line+ contains multiple rows, anything
   # beyond the first row is ignored.
-  # 
-  # The +options+ parameter can be anthing CSV::new() understands.
-  # 
+  #
+  # The +options+ parameter can be anything CSV::new() understands.
+  #
   def self.parse_line(line, options = Hash.new)
     new(line, options).shift
   end
-  
-  # 
-  # Use to slurp a CSV file into an Array of Arrays.  Pass the +path+ to the 
+
+  #
+  # Use to slurp a CSV file into an Array of Arrays.  Pass the +path+ to the
   # file and any +options+ CSV::new() understands.  This method also understands
   # an additional <tt>:encoding</tt> parameter that you can use to specify the
   # Encoding of the data in the file to be read. You must provide this unless
@@ -1387,46 +1392,46 @@
   # transcoded as it is read.  For example,
   # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
   # but transcode it to UTF-8 before CSV parses it.
-  # 
+  #
   def self.read(path, options = Hash.new)
     encoding =  options.delete(:encoding)
     mode     =  "rb"
     mode     << ":#{encoding}" if encoding
     open(path, mode, options) { |csv| csv.read }
   end
-  
+
   # Alias for CSV::read().
   def self.readlines(*args)
     read(*args)
   end
-  
-  # 
+
+  #
   # A shortcut for:
-  # 
+  #
   #   CSV.read( path, { headers:           true,
   #                     converters:        :numeric,
   #                     header_converters: :symbol }.merge(options) )
-  # 
+  #
   def self.table(path, options = Hash.new)
     read( path, { headers:           true,
                   converters:        :numeric,
                   header_converters: :symbol }.merge(options) )
   end
-  
-  # 
+
+  #
   # This constructor will wrap either a String or IO object passed in +data+ for
   # reading and/or writing.  In addition to the CSV instance methods, several IO
   # methods are delegated.  (See CSV::open() for a complete list.)  If you pass
   # a String for +data+, you can later retrieve it (after writing to it, for
   # example) with CSV.string().
-  # 
-  # Note that a wrapped String will be positioned at at the beginning (for 
+  #
+  # Note that a wrapped String will be positioned at at the beginning (for
   # reading).  If you want it at the end (for writing), use CSV::generate().
   # If you want any other positioning, pass a preset StringIO object instead.
-  # 
-  # You may set any reading and/or writing preferences in the +options+ Hash.  
+  #
+  # You may set any reading and/or writing preferences in the +options+ Hash.
   # Available options are:
-  # 
+  #
   # <b><tt>:col_sep</tt></b>::            The String placed between each field.
   #                                       This String will be transcoded into
   #                                       the data's Encoding before parsing.
@@ -1501,7 +1506,7 @@
   #                                       Array or String were not fields of the
   #                                       document and thus will have an empty
   #                                       Array attached.
-  # <b><tt>:headers</tt></b>::            If set to <tt>:first_row</tt> or 
+  # <b><tt>:headers</tt></b>::            If set to <tt>:first_row</tt> or
   #                                       +true+, the initial row of the CSV
   #                                       file will be treated as a row of
   #                                       headers.  If set to an Array, the
@@ -1538,129 +1543,124 @@
   #                                       skip over any rows with no content.
   # <b><tt>:force_quotes</tt></b>::       When set to a +true+ value, CSV will
   #                                       quote all CSV fields it creates.
-  # 
+  #
   # See CSV::DEFAULT_OPTIONS for the default settings.
-  # 
+  #
   # Options cannot be overriden in the instance methods for performance reasons,
   # so be sure to set what you want here.
-  # 
+  #
   def initialize(data, options = Hash.new)
     # build the options for this read/write
     options = DEFAULT_OPTIONS.merge(options)
-    
+
     # create the IO object we will read from
     @io       =   if data.is_a? String then StringIO.new(data) else data end
     # honor the IO encoding if we can, otherwise default to ASCII-8BIT
-    @encoding =   if @io.respond_to? :internal_encoding
-                    @io.internal_encoding || @io.external_encoding
-                  elsif @io.is_a? StringIO
-                    @io.string.encoding
-                  end
-    @encoding ||= Encoding.default_internal || Encoding.default_external
-    # 
+    @encoding = raw_encoding || Encoding.default_internal || Encoding.default_external
+    #
     # prepare for building safe regular expressions in the target encoding,
     # if we can transcode the needed characters
-    # 
+    #
     @re_esc   =   "\\".encode(@encoding) rescue ""
     @re_chars =   %w[ \\ .  [  ]  -  ^  $  ?
                       *  +  {  }  (  )  |  #
                       \  \r \n \t \f \v ].
                   map { |s| s.encode(@encoding) rescue nil }.compact
-   
+
     init_separators(options)
     init_parsers(options)
     init_converters(options)
     init_headers(options)
-    
+
     unless options.empty?
       raise ArgumentError, "Unknown options:  #{options.keys.join(', ')}."
     end
-    
+
     # track our own lineno since IO gets confused about line-ends is CSV fields
     @lineno = 0
   end
-  
-  # 
+
+  #
   # The encoded <tt>:col_sep</tt> used in parsing and writing.  See CSV::new
   # for details.
-  # 
+  #
   attr_reader :col_sep
-  # 
+  #
   # The encoded <tt>:row_sep</tt> used in parsing and writing.  See CSV::new
   # for details.
-  # 
+  #
   attr_reader :row_sep
-  # 
+  #
   # The encoded <tt>:quote_char</tt> used in parsing and writing.  See CSV::new
   # for details.
-  # 
+  #
   attr_reader :quote_char
   # The limit for field size, if any.  See CSV::new for details.
   attr_reader :field_size_limit
-  # 
+  #
   # Returns the current list of converters in effect.  See CSV::new for details.
   # Built-in converters will be returned by name, while others will be returned
   # as is.
-  # 
+  #
   def converters
     @converters.map do |converter|
       name = Converters.rassoc(converter)
       name ? name.first : converter
     end
   end
-  # 
+  #
   # Returns +true+ if unconverted_fields() to parsed results.  See CSV::new
   # for details.
-  # 
+  #
   def unconverted_fields?() @unconverted_fields end
-  # 
+  #
   # Returns +nil+ if headers will not be used, +true+ if they will but have not
   # yet been read, or the actual headers after they have been read.  See
   # CSV::new for details.
-  # 
+  #
   def headers
     @headers || true if @use_headers
   end
-  # 
+  #
   # Returns +true+ if headers will be returned as a row of results.
   # See CSV::new for details.
-  # 
+  #
   def return_headers?()     @return_headers     end
   # Returns +true+ if headers are written in output. See CSV::new for details.
   def write_headers?()      @write_headers      end
-  # 
+  #
   # Returns the current list of converters in effect for headers.  See CSV::new
   # for details.  Built-in converters will be returned by name, while others
   # will be returned as is.
-  # 
+  #
   def header_converters
     @header_converters.map do |converter|
       name = HeaderConverters.rassoc(converter)
       name ? name.first : converter
     end
   end
-  # 
+  #
   # Returns +true+ blank lines are skipped by the parser. See CSV::new
   # for details.
-  # 
+  #
   def skip_blanks?()        @skip_blanks        end
   # Returns +true+ if all output fields are quoted. See CSV::new for details.
   def force_quotes?()       @force_quotes       end
-    
-  # 
+
+  #
   # The Encoding CSV is parsing or writing in.  This will be the Encoding you
   # receive parsed data in and/or the Encoding data will be written in.
-  # 
+  #
   attr_reader :encoding
-  
-  # 
-  # The line number of the last row read from this file.  Fields with nested 
+
+  #
+  # The line number of the last row read from this file.  Fields with nested
   # line-end characters will not affect this count.
-  # 
+  #
   attr_reader :lineno
-  
+
   ### IO and StringIO Delegation ###
-  
+
   extend Forwardable
   def_delegators :@io, :binmode, :binmode?, :close, :close_read, :close_write,
                        :closed?, :eof, :eof?, :external_encoding, :fcntl,
@@ -1668,31 +1668,31 @@
                        :ioctl, :isatty, :path, :pid, :pos, :pos=, :reopen,
                        :seek, :stat, :string, :sync, :sync=, :tell, :to_i,
                        :to_io, :truncate, :tty?
-  
+
   # Rewinds the underlying IO object and resets CSV's lineno() counter.
   def rewind
     @headers = nil
     @lineno  = 0
-    
+
     @io.rewind
   end
 
   ### End Delegation ###
-  
-  # 
+
+  #
   # The primary write method for wrapped Strings and IOs, +row+ (an Array or
   # CSV::Row) is converted to CSV and appended to the data source.  When a
   # CSV::Row is passed, only the row's fields() are appended to the output.
-  # 
+  #
   # The data source must be open for writing.
-  # 
+  #
   def <<(row)
     # make sure headers have been assigned
     if header_row? and [Array, String].include? @use_headers.class
       parse_headers  # won't read data for Array or String
       self << @headers if @write_headers
     end
-    
+
     # handle CSV::Row objects and Hashes
     row = case row
           when self.class::Row then row.fields
@@ -1704,69 +1704,69 @@
     @lineno  += 1
 
     @io << row.map(&@quote).join(@col_sep) + @row_sep  # quote and separate
-    
+
     self  # for chaining
   end
   alias_method :add_row, :<<
   alias_method :puts,    :<<
-  
-  # 
+
+  #
   # :call-seq:
   #   convert( name )
   #   convert { |field| ... }
   #   convert { |field, field_info| ... }
-  # 
+  #
   # You can use this method to install a CSV::Converters built-in, or provide a
   # block that handles a custom conversion.
-  # 
+  #
   # If you provide a block that takes one argument, it will be passed the field
   # and is expected to return the converted value or the field itself.  If your
-  # block takes two arguments, it will also be passed a CSV::FieldInfo Struct, 
-  # containing details about the field.  Again, the block should return a 
+  # block takes two arguments, it will also be passed a CSV::FieldInfo Struct,
+  # containing details about the field.  Again, the block should return a
   # converted field or the field itself.
-  # 
+  #
   def convert(name = nil, &converter)
     add_converter(:converters, self.class::Converters, name, &converter)
   end
 
-  # 
+  #
   # :call-seq:
   #   header_convert( name )
   #   header_convert { |field| ... }
   #   header_convert { |field, field_info| ... }
-  # 
+  #
   # Identical to CSV#convert(), but for header rows.
-  # 
+  #
   # Note that this method must be called before header rows are read to have any
   # effect.
-  # 
+  #
   def header_convert(name = nil, &converter)
     add_converter( :header_converters,
                    self.class::HeaderConverters,
                    name,
                    &converter )
   end
-  
+
   include Enumerable
-  
-  # 
+
+  #
   # Yields each row of the data source in turn.
-  # 
+  #
   # Support for Enumerable.
-  # 
+  #
   # The data source must be open for reading.
-  # 
+  #
   def each
     while row = shift
       yield row
     end
   end
-  
-  # 
+
+  #
   # Slurps the remaining rows and returns an Array of Arrays.
-  # 
+  #
   # The data source must be open for reading.
-  # 
+  #
   def read
     rows = to_a
     if @use_headers
@@ -1776,25 +1776,25 @@
     end
   end
   alias_method :readlines, :read
-  
+
   # Returns +true+ if the next row read will be a header row.
   def header_row?
     @use_headers and @headers.nil?
   end
-  
-  # 
+
+  #
   # The primary read method for wrapped Strings and IOs, a single row is pulled
   # from the data source, parsed and returned as an Array of fields (if header
   # rows are not used) or a CSV::Row (when header rows are used).
-  # 
+  #
   # The data source must be open for reading.
-  # 
+  #
   def shift
     #########################################################################
     ### This method is purposefully kept a bit long as simple conditional ###
     ### checks are faster than numerous (expensive) method calls.         ###
     #########################################################################
-    
+
     # handle headers not based on document content
     if header_row? and @return_headers and
        [Array, String].include? @use_headers.class
@@ -1804,74 +1804,103 @@
         return parse_headers
       end
     end
-    
+
     # begin with a blank line, so we can always add to it
     line = ""
 
-    # 
+    #
     # it can take multiple calls to <tt>@io.gets()</tt> to get a full line,
     # because of \r and/or \n characters embedded in quoted fields
-    # 
+    #
+    in_extended_col = false
+    csv             = Array.new
+
     loop do
       # add another read to the line
-      (line += @io.gets(@row_sep)) rescue return nil
-      # copy the line so we can chop it up in parsing
-      parse =  line.dup
+      unless parse = @io.gets(@row_sep)
+        return nil
+      end
+
       parse.sub!(@parsers[:line_end], "")
-      
-      # 
-      # I believe a blank line should be an <tt>Array.new</tt>, not Ruby 1.8
-      # CSV's <tt>[nil]</tt>
-      # 
-      if parse.empty?
-        @lineno += 1
-        if @skip_blanks
-          line = ""
-          next
-        elsif @unconverted_fields
-          return add_unconverted_fields(Array.new, Array.new)
-        elsif @use_headers
-          return self.class::Row.new(Array.new, Array.new)
-        else
-          return Array.new
+
+      if csv.empty?
+        #
+        # I believe a blank line should be an <tt>Array.new</tt>, not Ruby 1.8
+        # CSV's <tt>[nil]</tt>
+        #
+        if parse.empty?
+          @lineno += 1
+          if @skip_blanks
+            next
+          elsif @unconverted_fields
+            return add_unconverted_fields(Array.new, Array.new)
+          elsif @use_headers
+            return self.class::Row.new(Array.new, Array.new)
+          else
+            return Array.new
+          end
         end
       end
 
-      # 
-      # shave leading empty fields if needed, because the main parser chokes 
-      # on these
-      # 
-      csv = if parse.sub!(@parsers[:leading_fields], "")
-        [nil] * ($&.length / @col_sep.length)
-      else
-        Array.new
-      end
-      # 
-      # then parse the main fields with a hyper-tuned Regexp from 
-      # Mastering Regular Expressions, Second Edition
-      # 
-      parse.gsub!(@parsers[:csv_row]) do
-        csv << if $1.nil?     # we found an unquoted field
-          if $2.empty?        # switch empty unquoted fields to +nil+...
-            nil               # for Ruby 1.8 CSV compatibility
+      parts =  parse.split(@col_sep, -1)
+      csv   << nil if parts.empty?
+
+      # This loop is the hot path of csv parsing. Some things may be non-dry
+      # for a reason. Make sure to benchmark when refactoring.
+      parts.each do |part|
+        if in_extended_col
+          # If we are continuing a previous column
+          if part[-1] == @quote_char && part.count(@quote_char) % 2 != 0
+            # extended column ends
+            csv.last << part[0..-2]
+            raise MalformedCSVError if csv.last =~ @parsers[:stray_quote]
+            csv.last.gsub!(@quote_char * 2, @quote_char)
+            in_extended_col = false
           else
-            # I decided to take a strict approach to CSV parsing...
-            if $2.count(@parsers[:return_newline]).zero?  # verify correctness
-              $2
-            else
-              # or throw an Exception
-              raise MalformedCSVError, "Unquoted fields do not allow " +
-                                       "\\r or \\n (line #{lineno + 1})."
-            end
+            csv.last << part
+            csv.last << @col_sep
           end
-        else                  # we found a quoted field...
-          $1.gsub(@quote_char * 2, @quote_char)  # unescape contents
+        elsif part[0] == @quote_char
+          # If we are staring a new quoted column
+          if part[-1] != @quote_char || part.count(@quote_char) % 2 != 0
+            # start an extended column
+            csv             << part[1..-1]
+            csv.last        << @col_sep
+            in_extended_col =  true
+          else
+            # regular quoted column
+            csv << part[1..-2]
+            raise MalformedCSVError if csv.last =~ @parsers[:stray_quote]
+            csv.last.gsub!(@quote_char * 2, @quote_char)
+          end
+        elsif part =~ @parsers[:quote_or_nl]
+          # Unquoted field with bad characters.
+          if part =~ @parsers[:nl_or_lf]
+            raise MalformedCSVError, "Unquoted fields do not allow " +
+                                     "\\r or \\n (line #{lineno + 1})."
+          else
+            raise MalformedCSVError, "Illegal quoting on line #{lineno + 1}."
+          end
+        else
+          # Regular ole unquoted field.
+          csv << (part.empty? ? nil : part)
         end
-        ""  # gsub!'s replacement, clear the field
       end
 
-      # if parse is empty?(), we found all the fields on the line...
-      if parse.empty?
+      # Replace tacked on @col_sep with @row_sep if we are still in an extended
+      # column.
+      csv[-1][-1] = @row_sep if in_extended_col
+
+      if in_extended_col
+        # if we're at eof?(), a quoted field wasn't closed...
+        if @io.eof?
+          raise MalformedCSVError,
+                "Unclosed quoted field on line #{lineno + 1}."
+        elsif @field_size_limit and csv.last.size >= @field_size_limit
+          raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
+        end
+        # otherwise, we need to loop and pull some more data to complete the row
+      else
         @lineno += 1
 
         # save fields unconverted fields, if needed...
@@ -1890,24 +1919,15 @@
         # return the results
         break csv
       end
-      # if we're not empty?() but at eof?(), a quoted field wasn't closed...
-      if @io.eof?
-        raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}."
-      elsif parse =~ @parsers[:bad_field]
-        raise MalformedCSVError, "Illegal quoting on line #{lineno + 1}."
-      elsif @field_size_limit and parse.length >= @field_size_limit
-        raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
-      end
-      # otherwise, we need to loop and pull some more data to complete the row
     end
   end
   alias_method :gets,     :shift
   alias_method :readline, :shift
-  
-  # 
+
+  #
   # Returns a simplified description of the key FasterCSV attributes in an
   # ASCII compatible String.
-  # 
+  #
   def inspect
     str = ["<#", self.class.to_s, " io_type:"]
     # show type of wrapped IO
@@ -1942,19 +1962,19 @@
       end.join
     end
   end
-  
+
   private
-  
-  # 
+
+  #
   # Stores the indicated separators for later use.
-  # 
+  #
   # If auto-discovery was requested for <tt>@row_sep</tt>, this method will read
   # ahead in the <tt>@io</tt> and try to find one.  +ARGF+, +STDIN+, +STDOUT+,
   # +STDERR+ and any stream open for output only with a default
   # <tt>@row_sep</tt> of <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
-  # 
+  #
   # This method also establishes the quoting rules used for CSV output.
-  # 
+  #
   def init_separators(options)
     # store the selected separators
     @col_sep    = options.delete(:col_sep).to_s.encode(@encoding)
@@ -1964,11 +1984,11 @@
     if @quote_char.length != 1
       raise ArgumentError, ":quote_char has to be a single character String"
     end
-    
-    # 
+
+    #
     # automatically discover row separator when requested
     # (not fully encoding safe)
-    # 
+    #
     if @row_sep == :auto
       if [ARGF, STDIN, STDOUT, STDERR].include?(@io) or
          (defined?(Zlib) and @io.class == Zlib::GzipWriter)
@@ -1977,20 +1997,19 @@
         begin
           saved_pos = @io.pos  # remember where we were
           while @row_sep == :auto
-            # 
-            # if we run out of data, it's probably a single line 
+            #
+            # if we run out of data, it's probably a single line
             # (use a sensible default)
-            # 
+            #
             if @io.eof?
               @row_sep = $INPUT_RECORD_SEPARATOR
               break
             end
-      
+
             # read ahead a bit
             sample =  read_to_char(1024)
             sample += read_to_char(1) if sample[-1..-1] == encode_str("\r") and
                                          not @io.eof?
-      
             # try to find a standard separator
             if sample =~ encode_re("\r\n?|\n")
               @row_sep = $&
@@ -2011,7 +2030,7 @@
       end
     end
     @row_sep = @row_sep.to_s.encode(@encoding)
-    
+
     # establish quoting rules
     @force_quotes = options.delete(:force_quotes)
     do_quote      = lambda do |field|
@@ -2039,72 +2058,50 @@
       end
     end
   end
-  
+
   # Pre-compiles parsers and stores them by name for access during reads.
   def init_parsers(options)
     # store the parser behaviors
     @skip_blanks      = options.delete(:skip_blanks)
     @field_size_limit = options.delete(:field_size_limit)
-    
+
     # prebuild Regexps for faster parsing
     esc_col_sep = escape_re(@col_sep)
     esc_row_sep = escape_re(@row_sep)
     esc_quote   = escape_re(@quote_char)
     @parsers = {
-      # for empty leading fields
-      leading_fields: encode_re("\\A(?:", esc_col_sep, ")+"),
-      # The Primary Parser
-      csv_row:        encode_re(
-        "\\G(?:\\A|", esc_col_sep, ")",                # anchor the match
-        "(?:", esc_quote,                              # find quoted fields
-               "((?>[^", esc_quote, "]*)",             # "unrolling the loop"
-               "(?>", esc_quote * 2,                   # double for escaping
-               "[^", esc_quote, "]*)*)",
-               esc_quote,
-               "|",                                    # ... or ...
-               "([^", esc_quote, esc_col_sep, "]*))",  # unquoted fields
-        "(?=", esc_col_sep, "|\\z)"                    # ensure field is ended
-      ),
-      # a test for unescaped quotes
-      bad_field:      encode_re(
-        "\\A", esc_col_sep, "?",                   # an optional comma
-        "(?:", esc_quote,                          # a quoted field
-               "(?>[^", esc_quote, "]*)",          # "unrolling the loop"
-               "(?>", esc_quote * 2,               # double for escaping
-               "[^", esc_quote, "]*)*",
-               esc_quote,                          # the closing quote
-               "[^", esc_quote, "]",               # an extra character
-               "|",                                # ... or ...
-               "[^", esc_quote, esc_col_sep, "]+", # an unquoted field
-               esc_quote, ")"                      # an extra quote
-      ),
+      # for detecting parse errors
+      quote_or_nl:    encode_re("[", esc_quote, "\r\n]"),
+      nl_or_lf:       encode_re("[\r\n]"),
+      stray_quote:    encode_re( "[^", esc_quote, "]", esc_quote,
+                                 "[^", esc_quote, "]" ),
       # safer than chomp!()
       line_end:       encode_re(esc_row_sep, "\\z"),
       # illegal unquoted characters
       return_newline: encode_str("\r\n")
     }
   end
-  
-  # 
+
+  #
   # Loads any converters requested during construction.
-  # 
+  #
   # If +field_name+ is set <tt>:converters</tt> (the default) field converters
   # are set.  When +field_name+ is <tt>:header_converters</tt> header converters
   # are added instead.
-  # 
-  # The <tt>:unconverted_fields</tt> option is also actived for 
+  #
+  # The <tt>:unconverted_fields</tt> option is also actived for
   # <tt>:converters</tt> calls, if requested.
-  # 
+  #
   def init_converters(options, field_name = :converters)
     if field_name == :converters
       @unconverted_fields = options.delete(:unconverted_fields)
     end
 
     instance_variable_set("@#{field_name}", Array.new)
-    
+
     # find the correct method to add the converters
     convert = method(field_name.to_s.sub(/ers\Z/, ""))
-    
+
     # load converters
     unless options[field_name].nil?
       # allow a single converter not wrapped in an Array
@@ -2120,10 +2117,10 @@
         end
       end
     end
-    
+
     options.delete(field_name)
   end
-  
+
   # Stores header row settings and loads header converters, if needed.
   def init_headers(options)
     @use_headers    = options.delete(:headers)
@@ -2132,18 +2129,18 @@
 
     # headers must be delayed until shift(), in case they need a row of content
     @headers = nil
-    
+
     init_converters(options, :header_converters)
   end
-  
-  # 
+
+  #
   # The actual work method for adding converters, used by both CSV.convert() and
   # CSV.header_convert().
-  # 
+  #
   # This method requires the +var_name+ of the instance variable to place the
   # converters in, the +const+ Hash to lookup named converters in, and the
   # normal parameters of the CSV.convert() and CSV.header_convert() methods.
-  # 
+  #
   def add_converter(var_name, const, name = nil, &converter)
     if name.nil?  # custom converter
       instance_variable_get("@#{var_name}") << converter
@@ -2159,18 +2156,18 @@
       end
     end
   end
-  
-  # 
+
+  #
   # Processes +fields+ with <tt>@converters</tt>, or <tt>@header_converters</tt>
   # if +headers+ is passed as +true+, returning the converted field set.  Any
   # converter that changes the field into something other than a String halts
   # the pipeline of conversion for that field.  This is primarily an efficiency
   # shortcut.
-  # 
+  #
   def convert_fields(fields, headers = false)
     # see if we are converting headers or fields
     converters = headers ? @header_converters : @converters
-    
+
     fields.map.with_index do |field, index|
       converters.each do |converter|
         field = if converter.arity == 1  # straight field converter
@@ -2184,17 +2181,17 @@
       field  # final state of each field, converted or original
     end
   end
-  
-  # 
+
+  #
   # This methods is used to turn a finished +row+ into a CSV::Row.  Header rows
   # are also dealt with here, either by returning a CSV::Row with identical
   # headers and fields (save that the fields do not go through the converters)
   # or by reading past them to return a field row. Headers are also saved in
   # <tt>@headers</tt> for use in future rows.
-  # 
+  #
   # When +nil+, +row+ is assumed to be a header row not based on an actual row
   # of the stream.
-  # 
+  #
   def parse_headers(row = nil)
     if @headers.nil?                # header row
       @headers = case @use_headers  # save headers
@@ -2209,11 +2206,11 @@
                  # first row is headers
                  else            row
                  end
-      
+
       # prepare converted and unconverted copies
       row      = @headers                       if row.nil?
       @headers = convert_fields(@headers, true)
-      
+
       if @return_headers                                     # return headers
         return self.class::Row.new(@headers, row, true)
       elsif not [Array, String].include? @use_headers.class  # skip to field row
@@ -2223,12 +2220,12 @@
 
     self.class::Row.new(@headers, convert_fields(row))  # field row
   end
-  
-  # 
+
+  #
   # Thiw methods injects an instance variable <tt>unconverted_fields</tt> into
   # +row+ and an accessor method for it called unconverted_fields().  The
   # variable is set to the contents of +fields+.
-  # 
+  #
   def add_unconverted_fields(row, fields)
     class << row
       attr_reader :unconverted_fields
@@ -2236,45 +2233,46 @@
     row.instance_eval { @unconverted_fields = fields }
     row
   end
-  
-  # 
-  # This method is an encoding safe version of Regexp::escape().  I will escape
+
+  #
+  # This method is an encoding safe version of Regexp::escape().  It will escape
   # any characters that would change the meaning of a regular expression in the
   # encoding of +str+.  Regular expression characters that cannot be transcoded
-  # to the target encodign will be skipped and no escaping will be performed if
+  # to the target encoding will be skipped and no escaping will be performed if
   # a backslash cannot be transcoded.
-  # 
+  #
   def escape_re(str)
     str.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join
   end
-  
-  # 
+
+  #
   # Builds a regular expression in <tt>@encoding</tt>.  All +chunks+ will be
   # transcoded to that encoding.
-  # 
+  #
   def encode_re(*chunks)
     Regexp.new(encode_str(*chunks))
   end
-  
-  # 
+
+  #
   # Builds a String in <tt>@encoding</tt>.  All +chunks+ will be transcoded to
   # that encoding.
-  # 
+  #
   def encode_str(*chunks)
     chunks.map { |chunk| chunk.encode(@encoding.name) }.join
   end
 
-  # 
+  #
   # Reads at least +bytes+ from <tt>@io</tt>, but will read up 10 bytes ahead if
   # needed to ensure the data read is valid in the ecoding of that data.  This
   # should ensure that it is safe to use regular expressions on the read data,
   # unless it is actually a broken encoding.  The read data will be returned in
   # <tt>@encoding</tt>.
-  # 
+  #
   def read_to_char(bytes)
     return "" if @io.eof?
-    data = @io.read(bytes)
+    data = read_io(bytes)
     begin
+      raise unless data.valid_encoding?
       encoded = encode_str(data)
       raise unless encoded.valid_encoding?
       return encoded
@@ -2282,13 +2280,28 @@
       if @io.eof? or data.size >= bytes + 10
         return data
       else
-        data += @io.read(1) until data.valid_encoding? or
-                                  @io.eof?             or
-                                  data.size >= bytes + 10
+        data += read_io(1)
         retry
       end
     end
   end
+
+  private
+  def raw_encoding
+    if @io.respond_to? :internal_encoding
+      @io.internal_encoding || @io.external_encoding
+    elsif @io.is_a? StringIO
+      @io.string.encoding
+    elsif @io.respond_to? :encoding
+      @io.encoding
+    else
+      Encoding::ASCII_8BIT
+    end
+  end
+
+  def read_io(bytes)
+    @io.read(bytes).force_encoding(raw_encoding)
+  end
 end
 
 # Another name for CSV::instance().

Modified: MacRuby/trunk/lib/date/format.rb
===================================================================
--- MacRuby/trunk/lib/date/format.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/date/format.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +1,4 @@
-# format.rb: Written by Tadayoshi Funaba 1999-2008
+# format.rb: Written by Tadayoshi Funaba 1999-2009
 # $Id: format.rb,v 2.43 2008-01-17 20:16:31+09 tadf Exp $
 
 class Date
@@ -563,8 +563,8 @@
 	end
       else
 	case c
-	when /\A[\s\v]/
-	  str.sub!(/\A[\s\v]+/, '')
+	when /\A\s/
+	  str.sub!(/\A\s+/, '')
 	else
 	  return unless str.sub!(Regexp.new('\\A' + Regexp.quote(a)), '')
 	end

Modified: MacRuby/trunk/lib/date.rb
===================================================================
--- MacRuby/trunk/lib/date.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/date.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,7 +1,7 @@
 #
 # date.rb - date and time library
 #
-# Author: Tadayoshi Funaba 1998-2008
+# Author: Tadayoshi Funaba 1998-2010
 #
 # Documentation: William Webber <william at williamwebber.com>
 #
@@ -927,7 +927,7 @@
 	  elem[e] = d.__send__(e)
 	end
 	elem[:wnum1] ||= 0
-	elem[:wday]  ||= 0
+	elem[:wday]  ||= 1
       end
     end
 
@@ -1371,6 +1371,12 @@
     case other
     when Numeric; return @ajd <=> other
     when Date;    return @ajd <=> other.ajd
+    else
+      begin
+        l, r = other.coerce(self)
+        return l <=> r
+      rescue NoMethodError
+      end
     end
     nil
   end
@@ -1385,6 +1391,9 @@
     case other
     when Numeric; return jd == other
     when Date;    return jd == other.jd
+    else
+      l, r = other.coerce(self)
+      return l === r
     end
     false
   end
@@ -1407,7 +1416,10 @@
     y, m = (year * 12 + (mon - 1) + n).divmod(12)
     m,   = (m + 1)                    .divmod(1)
     d = mday
-    d -= 1 until jd2 = _valid_civil?(y, m, d, @sg)
+    until jd2 = _valid_civil?(y, m, d, @sg)
+      d -= 1
+      raise ArgumentError, 'invalid date' unless d > 0
+    end
     self + (jd2 - jd)
   end
 
@@ -1775,7 +1787,7 @@
   def to_datetime
     jd = DateTime.__send__(:civil_to_jd, year, mon, mday, DateTime::ITALY)
     fr = DateTime.__send__(:time_to_day_fraction, hour, min, [sec, 59].min) +
-      Rational(nsec, 86400_000_000_000)
+      Rational(subsec, 86400)
     of = Rational(utc_offset, 86400)
     DateTime.new!(DateTime.__send__(:jd_to_ajd, jd, fr, of),
 		  of, DateTime::ITALY)
@@ -1805,7 +1817,7 @@
     t = Time.now
     jd = civil_to_jd(t.year, t.mon, t.mday, sg)
     fr = time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
-      Rational(t.nsec, 86400_000_000_000)
+      Rational(t.subsec, 86400)
     of = Rational(t.utc_offset, 86400)
     new!(jd_to_ajd(jd, fr, of), of, sg)
   end

Modified: MacRuby/trunk/lib/drb/drb.rb
===================================================================
--- MacRuby/trunk/lib/drb/drb.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/drb.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -18,7 +18,7 @@
 #
 # The Ruby standard library contains the core classes of the dRuby package.
 # However, the full package also includes access control lists and the
-# Rinda tuple-space distributed task management system, as well as a 
+# Rinda tuple-space distributed task management system, as well as a
 # large number of samples.  The full dRuby package can be downloaded from
 # the dRuby home page (see *References*).
 #
@@ -121,7 +121,7 @@
 # are forwarded to the local object, as described in the discussion of
 # DRbObjects.  This has semantics similar to the normal Ruby
 # pass-by-reference.
-# 
+#
 # The easiest way to signal that we want an otherwise marshallable
 # object to be passed or returned as a DRbObject reference, rather
 # than marshalled and sent as a copy, is to include the
@@ -135,7 +135,7 @@
 # passed back to the remote execution context to be collected, before
 # the collected values are finally returned to the local context as
 # the return value of the method invocation.
-# 
+#
 # == Examples of usage
 #
 # For more dRuby samples, see the +samples+ directory in the full
@@ -148,33 +148,33 @@
 # starting the server code first.
 #
 # ==== Server code
-#    
+#
 #   require 'drb/drb'
-#     
+#
 #   # The URI for the server to connect to
-#   URI="druby://localhost:8787" 
-#     
+#   URI="druby://localhost:8787"
+#
 #   class TimeServer
-#     
+#
 #     def get_current_time
 #       return Time.now
 #     end
-#     
+#
 #   end
-#     
+#
 #   # The object that handles requests on the server
 #   FRONT_OBJECT=TimeServer.new
 #
 #   $SAFE = 1   # disable eval() and friends
-#   
+#
 #   DRb.start_service(URI, FRONT_OBJECT)
 #   # Wait for the drb server thread to finish before exiting.
 #   DRb.thread.join
 #
 # ==== Client code
-#     
+#
 #   require 'drb/drb'
-#   
+#
 #   # The URI to connect to
 #   SERVER_URI="druby://localhost:8787"
 #
@@ -184,43 +184,43 @@
 #   # as soon as we pass a non-marshallable object as an argument
 #   # to a dRuby call.
 #   DRb.start_service
-#   
+#
 #   timeserver = DRbObject.new_with_uri(SERVER_URI)
-#   puts timeserver.get_current_time 
+#   puts timeserver.get_current_time
 #
 # === Remote objects under dRuby
 #
 # This example illustrates returning a reference to an object
 # from a dRuby call.  The Logger instances live in the server
 # process.  References to them are returned to the client process,
-# where methods can be invoked upon them.  These methods are 
+# where methods can be invoked upon them.  These methods are
 # executed in the server process.
 #
 # ==== Server code
-#   
+#
 #   require 'drb/drb'
-#   
+#
 #   URI="druby://localhost:8787"
-#   
+#
 #   class Logger
 #
 #       # Make dRuby send Logger instances as dRuby references,
 #       # not copies.
 #       include DRb::DRbUndumped
-#   
+#
 #       def initialize(n, fname)
 #           @name = n
 #           @filename = fname
 #       end
-#   
+#
 #       def log(message)
 #           File.open(@filename, "a") do |f|
 #               f.puts("#{Time.now}: #{@name}: #{message}")
 #           end
 #       end
-#   
+#
 #   end
-#   
+#
 #   # We have a central object for creating and retrieving loggers.
 #   # This retains a local reference to all loggers created.  This
 #   # is so an existing logger can be looked up by name, but also
@@ -228,12 +228,12 @@
 #   # reference to an object is not sufficient to prevent it being
 #   # garbage collected!
 #   class LoggerFactory
-#   
+#
 #       def initialize(bdir)
 #           @basedir = bdir
 #           @loggers = {}
 #       end
-#   
+#
 #       def get_logger(name)
 #           if !@loggers.has_key? name
 #               # make the filename safe, then declare it to be so
@@ -242,34 +242,34 @@
 #           end
 #           return @loggers[name]
 #       end
-#   
+#
 #   end
-#   
+#
 #   FRONT_OBJECT=LoggerFactory.new("/tmp/dlog")
 #
 #   $SAFE = 1   # disable eval() and friends
-#   
+#
 #   DRb.start_service(URI, FRONT_OBJECT)
 #   DRb.thread.join
 #
 # ==== Client code
 #
 #   require 'drb/drb'
-#   
+#
 #   SERVER_URI="druby://localhost:8787"
 #
 #   DRb.start_service
-#   
+#
 #   log_service=DRbObject.new_with_uri(SERVER_URI)
-#   
+#
 #   ["loga", "logb", "logc"].each do |logname|
-#   
+#
 #       logger=log_service.get_logger(logname)
-#   
+#
 #       logger.log("Hello, world!")
 #       logger.log("Goodbye, world!")
 #       logger.log("=== EOT ===")
-#   
+#
 #   end
 #
 # == Security
@@ -288,9 +288,9 @@
 #    ro.instance_eval("`rm -rf *`")
 #
 # The dangers posed by instance_eval and friends are such that a
-# DRbServer should generally be run with $SAFE set to at least 
-# level 1.  This will disable eval() and related calls on strings 
-# passed across the wire.  The sample usage code given above follows 
+# DRbServer should generally be run with $SAFE set to at least
+# level 1.  This will disable eval() and related calls on strings
+# passed across the wire.  The sample usage code given above follows
 # this practice.
 #
 # A DRbServer can be configured with an access control list to
@@ -360,7 +360,7 @@
   #
   # This, the default implementation, uses an object's local ObjectSpace
   # __id__ as its id.  This means that an object's identification over
-  # drb remains valid only while that object instance remains alive 
+  # drb remains valid only while that object instance remains alive
   # within the server runtime.
   #
   # For alternative mechanisms, see DRb::TimerIdConv in rdb/timeridconv.rb
@@ -374,7 +374,7 @@
     def to_obj(ref)
       ObjectSpace._id2ref(ref)
     end
-    
+
     # Convert an object into a reference id.
     #
     # This implementation returns the object's __id__ in the local
@@ -390,7 +390,7 @@
   # called over drb, then the object remains in the server space
   # and a reference to the object is returned, rather than the
   # object being marshalled and moved into the client space.
-  module DRbUndumped 
+  module DRbUndumped
     def _dump(dummy)  # :nodoc:
       raise TypeError, 'can\'t dump'
     end
@@ -424,7 +424,7 @@
     def self._load(s)  # :nodoc:
       Marshal::load(s)
     end
-    
+
     def _dump(lv) # :nodoc:
       Marshal::dump(@unknown)
     end
@@ -456,11 +456,11 @@
   # +name+ attribute.  The marshalled object is held in the +buf+
   # attribute.
   class DRbUnknown
-    
+
     # Create a new DRbUnknown object.
     #
     # +buf+ is a string containing a marshalled object that could not
-    # be unmarshalled.  +err+ is the error message that was raised 
+    # be unmarshalled.  +err+ is the error message that was raised
     # when the unmarshalling failed.  It is used to determine the
     # name of the unmarshalled object.
     def initialize(err, buf)
@@ -499,7 +499,7 @@
     # Attempt to load the wrapped marshalled object again.
     #
     # If the class of the object is now known locally, the object
-    # will be unmarshalled and returned.  Otherwise, a new 
+    # will be unmarshalled and returned.  Otherwise, a new
     # but identical DRbUnknown object will be returned.
     def reload
       self.class._load(@buf)
@@ -513,7 +513,7 @@
 
   class DRbArray
     def initialize(ary)
-      @ary = ary.collect { |obj| 
+      @ary = ary.collect { |obj|
 	if obj.kind_of? DRbUndumped
 	  DRbObject.new(obj)
 	else
@@ -607,7 +607,7 @@
     rescue
       raise(DRbConnError, $!.message, $!.backtrace)
     end
-    
+
     def recv_request(stream) # :nodoc:
       ref = load(stream)
       ro = DRb.to_obj(ref)
@@ -656,10 +656,10 @@
   #                              using configuration +config+.  Return a
   #                              protocol instance for this listener.
   #   [uri_option(uri, config)] Take a URI, possibly containing an option
-  #                             component (e.g. a trailing '?param=val'), 
+  #                             component (e.g. a trailing '?param=val'),
   #                             and return a [uri, option] tuple.
   #
-  # All of these methods should raise a DRbBadScheme error if the URI 
+  # All of these methods should raise a DRbBadScheme error if the URI
   # does not identify the protocol they support (e.g. "druby:" for
   # the standard Ruby protocol).  This is how the DRbProtocol module,
   # given a URI, determines which protocol implementation serves that
@@ -675,14 +675,14 @@
   #
   # The protocol instance returned by #open must have the following methods:
   #
-  # [send_request (ref, msg_id, arg, b)] 
+  # [send_request (ref, msg_id, arg, b)]
   #      Send a request to +ref+ with the given message id and arguments.
   #      This is most easily implemented by calling DRbMessage.send_request,
   #      providing a stream that sits on top of the current protocol.
   # [recv_reply]
   #      Receive a reply from the server and return it as a [success-boolean,
   #      reply-value] pair.  This is most easily implemented by calling
-  #      DRb.recv_reply, providing a stream that sits on top of the 
+  #      DRb.recv_reply, providing a stream that sits on top of the
   #      current protocol.
   # [alive?]
   #      Is this connection still alive?
@@ -725,7 +725,7 @@
     # URI by raising a DRbBadScheme error.  If no protocol recognises the
     # URI, then a DRbBadURI error is raised.  If a protocol accepts the
     # 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|
 	begin
 	  return prot.open(uri, config)
@@ -744,14 +744,14 @@
     end
     module_function :open
 
-    # Open a server listening for connections at +uri+ with 
+    # Open a server listening for connections at +uri+ with
     # configuration +config+.
     #
     # The DRbProtocol module asks each registered protocol in turn to
-    # try to open a server at the URI.  Each protocol signals that it does 
-    # not handle that URI by raising a DRbBadScheme error.  If no protocol 
-    # recognises the URI, then a DRbBadURI error is raised.  If a protocol 
-    # accepts the URI, but an error occurs in opening it, the underlying 
+    # try to open a server at the URI.  Each protocol signals that it does
+    # not handle that URI by raising a DRbBadScheme error.  If no protocol
+    # recognises the URI, then a DRbBadURI error is raised.  If a protocol
+    # accepts the URI, but an error occurs in opening it, the underlying
     # error is passed on to the caller.
     def open_server(uri, config, first=true)
       @protocol.each do |prot|
@@ -773,7 +773,7 @@
     # The DRbProtocol module asks each registered protocol in turn to
     # try to parse the URI.  Each protocol signals that it does not handle that
     # URI by raising a DRbBadScheme error.  If no protocol recognises the
-    # URI, then a DRbBadURI error is raised.  
+    # URI, then a DRbBadURI error is raised.
     def uri_option(uri, config, first=true)
       @protocol.each do |prot|
 	begin
@@ -837,23 +837,18 @@
     end
 
     def self.open_server_inaddr_any(host, port)
-      infos = Socket::getaddrinfo(host, nil, 
+      infos = Socket::getaddrinfo(host, nil,
                                   Socket::AF_UNSPEC,
-                                  Socket::SOCK_STREAM, 
+                                  Socket::SOCK_STREAM,
                                   0,
                                   Socket::AI_PASSIVE)
-      family = infos.collect { |af, *_| af }.uniq
-      case family
-      when ['AF_INET']
-        return TCPServer.open('0.0.0.0', port)
-      when ['AF_INET6']
-        return TCPServer.open('::', port)
-      else
-        return TCPServer.open(port)
-      end
+      families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
+      return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET')
+      return TCPServer.open('::', port) if families.has_key?('AF_INET6')
+      return TCPServer.open(port)
     end
 
-    # Open a server listening for connections at +uri+ using 
+    # Open a server listening for connections at +uri+ using
     # configuration +config+.
     def self.open_server(uri, config)
       uri = 'druby://:0' unless uri
@@ -899,7 +894,7 @@
     def peeraddr
       @socket.peeraddr
     end
-    
+
     # Get the socket.
     def stream; @socket; end
 
@@ -907,7 +902,7 @@
     def send_request(ref, msg_id, arg, b)
       @msg.send_request(stream, ref, msg_id, arg, b)
     end
-    
+
     # On the server side, receive a request from the client.
     def recv_request
       @msg.recv_request(stream)
@@ -937,14 +932,14 @@
 	@socket = nil
       end
     end
-    
-    # On the server side, for an instance returned by #open_server, 
+
+    # On the server side, for an instance returned by #open_server,
     # accept a client connection and return a new instance to handle
     # the server's side of this client-server session.
     def accept
       while true
 	s = @socket.accept
-	break if (@acl ? @acl.allow_socket?(s) : true) 
+	break if (@acl ? @acl.allow_socket?(s) : true)
 	s.close
       end
       if @config[:tcp_original_host].to_s.size == 0
@@ -981,16 +976,16 @@
     end
     attr :option
     def to_s; @option; end
-    
+
     def ==(other)
       return false unless DRbURIOption === other
       @option == other.option
     end
-    
+
     def hash
       @option.hash
     end
-    
+
     alias eql? ==
   end
 
@@ -1007,7 +1002,7 @@
     # created to act as a stub for the remote referenced object.
     def self._load(s)
       uri, ref = Marshal.load(s)
-      
+
       if DRb.here?(uri)
 	obj = DRb.to_obj(ref)
         if ((! obj.tainted?) && Thread.current[:drb_untaint])
@@ -1057,7 +1052,7 @@
     end
 
     # Get the URI of the remote object.
-    def __drburi 
+    def __drburi
       @uri
     end
 
@@ -1085,7 +1080,7 @@
       if DRb.here?(@uri)
 	obj = DRb.to_obj(@ref)
 	DRb.current_server.check_insecure_method(obj, msg_id)
-	return obj.__send__(msg_id, *a, &b) 
+	return obj.__send__(msg_id, *a, &b)
       end
 
       succ, result = self.class.with_friend(@uri) do
@@ -1108,7 +1103,7 @@
     def self.with_friend(uri)
       friend = DRb.fetch_server(uri)
       return yield() unless friend
-      
+
       save = Thread.current['DRb']
       Thread.current['DRb'] = { 'server' => friend }
       return yield
@@ -1120,7 +1115,7 @@
       prefix = "(#{uri}) "
       bt = []
       result.backtrace.each do |x|
-        break if /`__send__'$/ =~ x 
+        break if /`__send__'$/ =~ x
         if /^\(druby:\/\// =~ x
           bt.push(x)
         else
@@ -1271,14 +1266,14 @@
     def self.verbose=(on)
       @@verbose = on
     end
-    
+
     # Get the default value of the :verbose option.
     def self.verbose
       @@verbose
     end
 
     def self.make_config(hash={})  # :nodoc:
-      default_config = { 
+      default_config = {
 	:idconv => @@idconv,
 	:verbose => @@verbose,
 	:tcp_acl => @@acl,
@@ -1368,7 +1363,7 @@
     attr_reader :thread
 
     # The front object of the DRbServer.
-    # 
+    #
     # This object receives remote method calls made on the server's
     # URI alone, with an object id.
     attr_reader :front
@@ -1399,7 +1394,7 @@
       if  Thread.current['DRb'] && Thread.current['DRb']['server'] == self
         Thread.current['DRb']['stop_service'] = true
       else
-        @thread.kill
+        @thread.kill.join
       end
     end
 
@@ -1461,7 +1456,7 @@
     def any_to_s(obj)
       obj.to_s + ":#{obj.class}"
     rescue
-      sprintf("#<%s:0x%lx>", obj.class, obj.__id__)      
+      sprintf("#<%s:0x%lx>", obj.class, obj.__id__)
     end
 
     # Check that a method is callable via dRuby.
@@ -1469,14 +1464,14 @@
     # +obj+ is the object we want to invoke the method on. +msg_id+ is the
     # method name, as a Symbol.
     #
-    # If the method is an insecure method (see #insecure_method?) a 
+    # If the method is an insecure method (see #insecure_method?) a
     # SecurityError is thrown.  If the method is private or undefined,
     # a NameError is thrown.
     def check_insecure_method(obj, msg_id)
       return true if Proc === obj && msg_id == :__drb_yield
       raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
       raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
-      
+
       if obj.private_methods.include?(msg_id)
 	desc = any_to_s(obj)
         raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
@@ -1488,7 +1483,7 @@
       end
     end
     public :check_insecure_method
-    
+
     class InvokeMethod  # :nodoc:
       def initialize(drb_server, client)
 	@drb_server = drb_server
@@ -1510,7 +1505,7 @@
               perform_with_block
             }.value
           else
-            @result = Thread.new { 
+            @result = Thread.new {
               Thread.current['DRb'] = info
               $SAFE = @safe_level
               perform_without_block
@@ -1525,7 +1520,7 @@
         end
 	@succ = true
 	if @msg_id == :to_ary && @result.class == Array
-	  @result = DRbArray.new(@result) 
+	  @result = DRbArray.new(@result)
 	end
 	return @succ, @result
       rescue StandardError, ScriptError, Interrupt
@@ -1541,7 +1536,7 @@
         @argv = argv
         @block = block
       end
-      
+
       def check_insecure_method
         @drb_server.check_insecure_method(@obj, @msg_id)
       end
@@ -1550,7 +1545,7 @@
 	init_with_client
 	check_insecure_method
       end
-      
+
       def perform_without_block
 	if Proc === @obj && @msg_id == :__drb_yield
           if @argv.size == 1
@@ -1638,7 +1633,7 @@
 
   # The primary local dRuby server.
   #
-  # This is the server created by the #start_service call.  
+  # This is the server created by the #start_service call.
   attr_accessor :primary_server
   module_function :primary_server=, :primary_server
 
@@ -1653,8 +1648,8 @@
   # If the above rule fails to find a server, a DRbServerNotFound
   # error is raised.
   def current_server
-    drb = Thread.current['DRb'] 
-    server = (drb && drb['server']) ? drb['server'] : @primary_server 
+    drb = Thread.current['DRb']
+    server = (drb && drb['server']) ? drb['server'] : @primary_server
     raise DRbServerNotFound unless server
     return server
   end
@@ -1700,7 +1695,7 @@
     DRbServer.make_config
   end
   module_function :config
-  
+
   # Get the front object of the current server.
   #
   # This raises a DRbServerNotFound error if there is no current server.
@@ -1771,7 +1766,7 @@
     @server.delete(server.uri)
   end
   module_function :remove_server
-  
+
   def fetch_server(uri)
     @server[uri]
   end

Modified: MacRuby/trunk/lib/drb/eq.rb
===================================================================
--- MacRuby/trunk/lib/drb/eq.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/eq.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-require 'drb/drb'
-
 module DRb
   class DRbObject
     def ==(other)

Modified: MacRuby/trunk/lib/drb/extserv.rb
===================================================================
--- MacRuby/trunk/lib/drb/extserv.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/extserv.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,6 +1,6 @@
 =begin
  external service
- 	Copyright (c) 2000,2002 Masatoshi SEKI 
+ 	Copyright (c) 2000,2002 Masatoshi SEKI
 =end
 
 require 'drb/drb'

Modified: MacRuby/trunk/lib/drb/extservm.rb
===================================================================
--- MacRuby/trunk/lib/drb/extservm.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/extservm.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,6 +1,6 @@
 =begin
  external service manager
- 	Copyright (c) 2000 Masatoshi SEKI 
+ 	Copyright (c) 2000 Masatoshi SEKI
 =end
 
 require 'drb/drb'
@@ -21,7 +21,7 @@
     def self.command=(cmd)
       @@command = cmd
     end
-      
+
     def initialize
       super()
       @cond = new_cond
@@ -51,7 +51,7 @@
       end
       self
     end
-    
+
     def unregist(name)
       synchronize do
 	@servers.delete(name)
@@ -79,11 +79,7 @@
 	@servers[name] = false
       end
       uri = @uri || DRb.uri
-      if RUBY_PLATFORM =~ /mswin32/ && /NT/ =~ ENV["OS"]
-        system(%Q'cmd /c start "ruby" /b #{command} #{uri} #{name}')
-      else
-	system("#{command} #{uri} #{name} &")
-      end
+      Process.detach spawn("#{command} #{uri} #{name}")
     end
   end
 end

Modified: MacRuby/trunk/lib/drb/invokemethod.rb
===================================================================
--- MacRuby/trunk/lib/drb/invokemethod.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/invokemethod.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,7 +9,7 @@
 	end
         block_value = @block.call(*x)
       end
-      
+
       def perform_with_block
         @obj.__send__(@msg_id, *@argv) do |*x|
           jump_error = nil

Modified: MacRuby/trunk/lib/drb/observer.rb
===================================================================
--- MacRuby/trunk/lib/drb/observer.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/observer.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -6,16 +6,16 @@
 
     def notify_observers(*arg)
       if defined? @observer_state and @observer_state
-	if defined? @observer_peers
-	  for i in @observer_peers.dup
-	    begin
-	      i.update(*arg)
-	    rescue
-	      delete_observer(i)
-	    end
-	  end
-	end
-	@observer_state = false
+        if defined? @observer_peers
+          @observer_peers.each do |observer, method|
+            begin
+              observer.send(method, *arg)
+            rescue
+              delete_observer(observer)
+            end
+          end
+        end
+        @observer_state = false
       end
     end
   end

Modified: MacRuby/trunk/lib/drb/ssl.rb
===================================================================
--- MacRuby/trunk/lib/drb/ssl.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/ssl.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -15,7 +15,7 @@
 	:SSLClientCA          => nil,
 	:SSLCACertificatePath => nil,
 	:SSLCACertificateFile => nil,
-	:SSLVerifyMode        => ::OpenSSL::SSL::VERIFY_NONE, 
+	:SSLVerifyMode        => ::OpenSSL::SSL::VERIFY_NONE,
 	:SSLVerifyDepth       => nil,
 	:SSLVerifyCallback    => nil,   # custom verification
         :SSLCertificateStore  => nil,
@@ -31,7 +31,7 @@
         @ssl_ctx = nil
       end
 
-      def [](key); 
+      def [](key);
 	@config[key] || DEFAULT[key]
       end
 
@@ -41,14 +41,14 @@
 	ssl.connect
 	ssl
       end
-      
+
       def accept(tcp)
 	ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
 	ssl.sync = true
 	ssl.accept
 	ssl
       end
-      
+
       def setup_certificate
         if @cert && @pkey
           return
@@ -77,7 +77,7 @@
 	cert.not_before = Time.now
 	cert.not_after = Time.now + (365*24*60*60)
 	cert.public_key = rsa.public_key
-	
+
 	ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
 	cert.extensions = [
 	  ef.create_extension("basicConstraints","CA:FALSE"),
@@ -89,7 +89,7 @@
 	  cert.add_extension(ef.create_extension("nsComment", comment))
 	end
 	cert.sign(rsa, OpenSSL::Digest::SHA1.new)
-	
+
 	@cert = cert
         @pkey = rsa
       end
@@ -143,7 +143,7 @@
       end
       port = soc.addr[1] if port == 0
       @uri = "drbssl://#{host}:#{port}"
-      
+
       ssl_conf = SSLConfig.new(config)
       ssl_conf.setup_certificate
       ssl_conf.setup_ssl_context
@@ -159,7 +159,7 @@
       @ssl = is_established ? soc : nil
       super(uri, soc.to_io, config)
     end
-    
+
     def stream; @ssl; end
 
     def close
@@ -169,12 +169,12 @@
       end
       super
     end
-      
+
     def accept
       begin
       while true
 	soc = @socket.accept
-	break if (@acl ? @acl.allow_socket?(soc) : true) 
+	break if (@acl ? @acl.allow_socket?(soc) : true)
 	soc.close
       end
       ssl = @config.accept(soc)
@@ -185,6 +185,6 @@
       end
     end
   end
-  
+
   DRbProtocol.add_protocol(DRbSSLSocket)
 end

Modified: MacRuby/trunk/lib/drb/timeridconv.rb
===================================================================
--- MacRuby/trunk/lib/drb/timeridconv.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/timeridconv.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -19,7 +19,7 @@
       end
 
       def add(obj)
-	synchronize do 
+	synchronize do
 	  key = obj.__id__
 	  @curr[key] = obj
 	  return key
@@ -27,7 +27,7 @@
       end
 
       def fetch(key, dv=@sentinel)
-	synchronize do 
+	synchronize do
 	  obj = peek(key)
 	  if obj == @sentinel
 	    return dv unless dv == @sentinel
@@ -39,7 +39,7 @@
       end
 
       def include?(key)
-	synchronize do 
+	synchronize do
 	  obj = peek(key)
 	  return false if obj == @sentinel
 	  true
@@ -47,7 +47,7 @@
       end
 
       def peek(key)
-	synchronize do 
+	synchronize do
 	  return @curr.fetch(key, @renew.fetch(key, @gc.fetch(key, @sentinel)))
 	end
       end

Modified: MacRuby/trunk/lib/drb/unix.rb
===================================================================
--- MacRuby/trunk/lib/drb/unix.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/drb/unix.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,7 +8,7 @@
 
   class DRbUNIXSocket < DRbTCPSocket
     def self.parse_uri(uri)
-      if /^drbunix:(.*?)(\?(.*))?$/ =~ uri 
+      if /^drbunix:(.*?)(\?(.*))?$/ =~ uri
 	filename = $1
 	option = $3
 	[filename, option]
@@ -59,7 +59,7 @@
       @server_mode = server_mode
       @acl = nil
     end
-    
+
     # import from tempfile.rb
     Max_try = 10
     private

Modified: MacRuby/trunk/lib/e2mmap.rb
===================================================================
--- MacRuby/trunk/lib/e2mmap.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/e2mmap.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -56,7 +56,7 @@
     super
     cl.bind(self) unless cl < E2MM
   end
-  
+
   def bind(cl)
     self.module_eval %[
       def Raise(err = nil, *rest)
@@ -88,7 +88,7 @@
   def def_e2message(c, m)
     E2MM.def_e2message(self, c, m)
   end
-  
+
   # def_exception(n, m, s)
   #	    n:  exception_name
   #	    m:  message_form
@@ -115,7 +115,7 @@
     E2MM.instance_eval{@MessageMap[[k, c]] = m}
     c
   end
-  
+
   # E2MM.def_exception(k, n, m, s)
   #	    k:  class to define exception under.
   #	    n:  exception_name
@@ -146,7 +146,7 @@
       E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
     end
   end
-  class <<E2MM
+  class << E2MM
     alias Fail Raise
   end
 
@@ -160,12 +160,12 @@
     end
     nil
   end
-  class <<self
+  class << self
     alias message e2mm_message
   end
 
-  E2MM.def_exception(E2MM, 
-		     :ErrNotRegisteredException, 
+  E2MM.def_exception(E2MM,
+		     :ErrNotRegisteredException,
 		     "not registerd exception(%s)")
 end
 

Modified: MacRuby/trunk/lib/erb.rb
===================================================================
--- MacRuby/trunk/lib/erb.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/erb.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -10,251 +10,251 @@
 #
 # You can redistribute it and/or modify it under the same terms as Ruby.
 
-=begin rdoc
-= ERB -- Ruby Templating
-
-== Introduction
-
-ERB provides an easy to use but powerful templating system for Ruby.  Using
-ERB, actual Ruby code can be added to any plain text document for the
-purposes of generating document information details and/or flow control.
-
-A very simple example is this:
-
-  require 'erb'
-
-  x = 42
-  template = ERB.new <<-EOF
-    The value of x is: <%= x %>
-  EOF
-  puts template.result(binding)
-
-<em>Prints:</em> The value of x is: 42
-
-More complex examples are given below.
-
-
-== Recognized Tags
-
-ERB recognizes certain tags in the provided template and converts them based
-on the rules below:
-
-  <% Ruby code -- inline with output %>
-  <%= Ruby expression -- replace with result %>
-  <%# comment -- ignored -- useful in testing %>
-  % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
-  %% replaced with % if first thing on a line and % processing is used
-  <%% or %%> -- replace with <% or %> respectively
-
-All other text is passed through ERB filtering unchanged.
-
-
-== Options
-
-There are several settings you can change when you use ERB:
-* the nature of the tags that are recognized;
-* the value of <tt>$SAFE</tt> under which the template is run;
-* the binding used to resolve local variables in the template.
-
-See the ERB.new and ERB#result methods for more detail.
-
-== Character encodings
-
-ERB (or ruby code generated by ERB) returns a string in the same
-character encoding as the input string.  When the input string has
-a magic comment, however, it returns a string in the encoding specified
-by the magic comment.
-
-  # -*- coding: UTF-8 -*-
-  require 'erb'
-
-  template = ERB.new <<EOF
-  <%#-*- coding: Big5 -*-%>
-    \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
-  EOF
-  puts template.result
-
-<em>Prints:</em> \_\_ENCODING\_\_ is Big5.
-
-
-== Examples
-
-=== Plain Text
-
-ERB is useful for any generic templating situation.  Note that in this example, we use the
-convenient "% at start of line" tag, and we quote the template literally with
-<tt>%q{...}</tt> to avoid trouble with the backslash.
-
-  require "erb"
-  
-  # Create template.
-  template = %q{
-    From:  James Edward Gray II <james at grayproductions.net>
-    To:  <%= to %>
-    Subject:  Addressing Needs
-  
-    <%= to[/\w+/] %>:
-  
-    Just wanted to send a quick note assuring that your needs are being
-    addressed.
-  
-    I want you to know that my team will keep working on the issues,
-    especially:
-  
-    <%# ignore numerous minor requests -- focus on priorities %>
-    % priorities.each do |priority|
-      * <%= priority %>
-    % end
-  
-    Thanks for your patience.
-  
-    James Edward Gray II
-  }.gsub(/^  /, '')
-  
-  message = ERB.new(template, 0, "%<>")
-  
-  # Set up template data.
-  to = "Community Spokesman <spokesman at ruby_community.org>"
-  priorities = [ "Run Ruby Quiz",
-                 "Document Modules",
-                 "Answer Questions on Ruby Talk" ]
-  
-  # Produce result.
-  email = message.result
-  puts email
-
-<i>Generates:</i>
-
-  From:  James Edward Gray II <james at grayproductions.net>
-  To:  Community Spokesman <spokesman at ruby_community.org>
-  Subject:  Addressing Needs
-  
-  Community:
-  
-  Just wanted to send a quick note assuring that your needs are being addressed.
-  
-  I want you to know that my team will keep working on the issues, especially:
-  
-      * Run Ruby Quiz
-      * Document Modules
-      * Answer Questions on Ruby Talk
-  
-  Thanks for your patience.
-  
-  James Edward Gray II
-
-=== Ruby in HTML
-
-ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby).  Notice the need in
-this example to provide a special binding when the template is run, so that the instance
-variables in the Product object can be resolved.
-
-  require "erb"
-  
-  # Build template data class.
-  class Product
-    def initialize( code, name, desc, cost )
-      @code = code
-      @name = name
-      @desc = desc
-      @cost = cost
-       	
-      @features = [ ]
-    end
-  
-    def add_feature( feature )
-      @features << feature
-    end
-  
-    # Support templating of member data.
-    def get_binding
-      binding
-    end
-  
-    # ...
-  end
-  
-  # Create template.
-  template = %{
-    <html>
-      <head><title>Ruby Toys -- <%= @name %></title></head>
-      <body>
-  
-        <h1><%= @name %> (<%= @code %>)</h1>
-        <p><%= @desc %></p>
-  
-        <ul>
-          <% @features.each do |f| %>
-            <li><b><%= f %></b></li>
-          <% end %>
-        </ul>
-  
-        <p>
-          <% if @cost < 10 %>
-            <b>Only <%= @cost %>!!!</b>
-          <% else %>
-             Call for a price, today!
-          <% end %>
-        </p>
-   
-      </body>
-    </html>
-  }.gsub(/^  /, '')
-  
-  rhtml = ERB.new(template)
-  
-  # Set up template data.
-  toy = Product.new( "TZ-1002",
-                     "Rubysapien",
-                     "Geek's Best Friend!  Responds to Ruby commands...",
-                     999.95 )
-  toy.add_feature("Listens for verbal commands in the Ruby language!")
-  toy.add_feature("Ignores Perl, Java, and all C variants.")
-  toy.add_feature("Karate-Chop Action!!!")
-  toy.add_feature("Matz signature on left leg.")
-  toy.add_feature("Gem studded eyes... Rubies, of course!")
-  
-  # Produce result.
-  rhtml.run(toy.get_binding)
-
-<i>Generates (some blank lines removed):</i>
-
-   <html>
-     <head><title>Ruby Toys -- Rubysapien</title></head>
-     <body>
-   
-       <h1>Rubysapien (TZ-1002)</h1>
-       <p>Geek's Best Friend!  Responds to Ruby commands...</p>
-   
-       <ul>
-           <li><b>Listens for verbal commands in the Ruby language!</b></li>
-           <li><b>Ignores Perl, Java, and all C variants.</b></li>
-           <li><b>Karate-Chop Action!!!</b></li>
-           <li><b>Matz signature on left leg.</b></li>
-           <li><b>Gem studded eyes... Rubies, of course!</b></li>
-       </ul>
-   
-       <p>
-            Call for a price, today!
-       </p>
-   
-     </body>
-   </html>
-
-
-== Notes
-
-There are a variety of templating solutions available in various Ruby projects:
-* ERB's big brother, eRuby, works the same but is written in C for speed;
-* Amrita (smart at producing HTML/XML);
-* cs/Template (written in C for speed);
-* RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
-* and others; search the RAA.
-
-Rails, the web application framework, uses ERB to create views.
-=end
+#
+# = ERB -- Ruby Templating
+#
+# == Introduction
+#
+# ERB provides an easy to use but powerful templating system for Ruby.  Using
+# ERB, actual Ruby code can be added to any plain text document for the
+# purposes of generating document information details and/or flow control.
+#
+# A very simple example is this:
+#
+#   require 'erb'
+#
+#   x = 42
+#   template = ERB.new <<-EOF
+#     The value of x is: <%= x %>
+#   EOF
+#   puts template.result(binding)
+#
+# <em>Prints:</em> The value of x is: 42
+#
+# More complex examples are given below.
+#
+#
+# == Recognized Tags
+#
+# ERB recognizes certain tags in the provided template and converts them based
+# on the rules below:
+#
+#   <% Ruby code -- inline with output %>
+#   <%= Ruby expression -- replace with result %>
+#   <%# comment -- ignored -- useful in testing %>
+#   % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
+#   %% replaced with % if first thing on a line and % processing is used
+#   <%% or %%> -- replace with <% or %> respectively
+#
+# All other text is passed through ERB filtering unchanged.
+#
+#
+# == Options
+#
+# There are several settings you can change when you use ERB:
+# * the nature of the tags that are recognized;
+# * the value of <tt>$SAFE</tt> under which the template is run;
+# * the binding used to resolve local variables in the template.
+#
+# See the ERB.new and ERB#result methods for more detail.
+#
+# == Character encodings
+#
+# ERB (or ruby code generated by ERB) returns a string in the same
+# character encoding as the input string.  When the input string has
+# a magic comment, however, it returns a string in the encoding specified
+# by the magic comment.
+#
+#   # -*- coding: UTF-8 -*-
+#   require 'erb'
+#
+#   template = ERB.new <<EOF
+#   <%#-*- coding: Big5 -*-%>
+#     \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
+#   EOF
+#   puts template.result
+#
+# <em>Prints:</em> \_\_ENCODING\_\_ is Big5.
+#
+#
+# == Examples
+#
+# === Plain Text
+#
+# ERB is useful for any generic templating situation.  Note that in this example, we use the
+# convenient "% at start of line" tag, and we quote the template literally with
+# <tt>%q{...}</tt> to avoid trouble with the backslash.
+#
+#   require "erb"
+#
+#   # Create template.
+#   template = %q{
+#     From:  James Edward Gray II <james at grayproductions.net>
+#     To:  <%= to %>
+#     Subject:  Addressing Needs
+#
+#     <%= to[/\w+/] %>:
+#
+#     Just wanted to send a quick note assuring that your needs are being
+#     addressed.
+#
+#     I want you to know that my team will keep working on the issues,
+#     especially:
+#
+#     <%# ignore numerous minor requests -- focus on priorities %>
+#     % priorities.each do |priority|
+#       * <%= priority %>
+#     % end
+#
+#     Thanks for your patience.
+#
+#     James Edward Gray II
+#   }.gsub(/^  /, '')
+#
+#   message = ERB.new(template, 0, "%<>")
+#
+#   # Set up template data.
+#   to = "Community Spokesman <spokesman at ruby_community.org>"
+#   priorities = [ "Run Ruby Quiz",
+#                  "Document Modules",
+#                  "Answer Questions on Ruby Talk" ]
+#
+#   # Produce result.
+#   email = message.result
+#   puts email
+#
+# <i>Generates:</i>
+#
+#   From:  James Edward Gray II <james at grayproductions.net>
+#   To:  Community Spokesman <spokesman at ruby_community.org>
+#   Subject:  Addressing Needs
+#
+#   Community:
+#
+#   Just wanted to send a quick note assuring that your needs are being addressed.
+#
+#   I want you to know that my team will keep working on the issues, especially:
+#
+#       * Run Ruby Quiz
+#       * Document Modules
+#       * Answer Questions on Ruby Talk
+#
+#   Thanks for your patience.
+#
+#   James Edward Gray II
+#
+# === Ruby in HTML
+#
+# ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby).  Notice the need in
+# this example to provide a special binding when the template is run, so that the instance
+# variables in the Product object can be resolved.
+#
+#   require "erb"
+#
+#   # Build template data class.
+#   class Product
+#     def initialize( code, name, desc, cost )
+#       @code = code
+#       @name = name
+#       @desc = desc
+#       @cost = cost
+#
+#       @features = [ ]
+#     end
+#
+#     def add_feature( feature )
+#       @features << feature
+#     end
+#
+#     # Support templating of member data.
+#     def get_binding
+#       binding
+#     end
+#
+#     # ...
+#   end
+#
+#   # Create template.
+#   template = %{
+#     <html>
+#       <head><title>Ruby Toys -- <%= @name %></title></head>
+#       <body>
+#
+#         <h1><%= @name %> (<%= @code %>)</h1>
+#         <p><%= @desc %></p>
+#
+#         <ul>
+#           <% @features.each do |f| %>
+#             <li><b><%= f %></b></li>
+#           <% end %>
+#         </ul>
+#
+#         <p>
+#           <% if @cost < 10 %>
+#             <b>Only <%= @cost %>!!!</b>
+#           <% else %>
+#              Call for a price, today!
+#           <% end %>
+#         </p>
+#
+#       </body>
+#     </html>
+#   }.gsub(/^  /, '')
+#
+#   rhtml = ERB.new(template)
+#
+#   # Set up template data.
+#   toy = Product.new( "TZ-1002",
+#                      "Rubysapien",
+#                      "Geek's Best Friend!  Responds to Ruby commands...",
+#                      999.95 )
+#   toy.add_feature("Listens for verbal commands in the Ruby language!")
+#   toy.add_feature("Ignores Perl, Java, and all C variants.")
+#   toy.add_feature("Karate-Chop Action!!!")
+#   toy.add_feature("Matz signature on left leg.")
+#   toy.add_feature("Gem studded eyes... Rubies, of course!")
+#
+#   # Produce result.
+#   rhtml.run(toy.get_binding)
+#
+# <i>Generates (some blank lines removed):</i>
+#
+#    <html>
+#      <head><title>Ruby Toys -- Rubysapien</title></head>
+#      <body>
+#
+#        <h1>Rubysapien (TZ-1002)</h1>
+#        <p>Geek's Best Friend!  Responds to Ruby commands...</p>
+#
+#        <ul>
+#            <li><b>Listens for verbal commands in the Ruby language!</b></li>
+#            <li><b>Ignores Perl, Java, and all C variants.</b></li>
+#            <li><b>Karate-Chop Action!!!</b></li>
+#            <li><b>Matz signature on left leg.</b></li>
+#            <li><b>Gem studded eyes... Rubies, of course!</b></li>
+#        </ul>
+#
+#        <p>
+#             Call for a price, today!
+#        </p>
+#
+#      </body>
+#    </html>
+#
+#
+# == Notes
+#
+# There are a variety of templating solutions available in various Ruby projects:
+# * ERB's big brother, eRuby, works the same but is written in C for speed;
+# * Amrita (smart at producing HTML/XML);
+# * cs/Template (written in C for speed);
+# * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
+# * and others; search the RAA.
+#
+# Rails, the web application framework, uses ERB to create views.
+#
 class ERB
-  Revision = '$Date:: 2009-01-17 07:20:08 -0500#$' 	#'
+  Revision = '$Date:: 2009-10-02 05:04:37 -0700#$' 	#'
 
   # Returns revision information for the erb.rb module.
   def self.version
@@ -318,7 +318,7 @@
 	end
       end
       attr_accessor :stag
-      
+
       def scan(&block)
 	@stag = nil
 	if @percent
@@ -425,7 +425,7 @@
 	end
       end
     end
-    
+
     Scanner.regist_scanner(SimpleScanner, nil, false)
 
     begin
@@ -484,13 +484,13 @@
       def push(cmd)
 	@line << cmd
       end
-      
+
       def cr
 	@script << (@line.join('; '))
 	@line = []
 	@script << "\n"
       end
-      
+
       def close
 	return unless @line
 	@compiler.post_cmd.each do |x|
@@ -520,7 +520,7 @@
       content = ''
       scanner = make_scanner(s)
       scanner.scan do |token|
-        next if token.nil? 
+        next if token.nil?
         next if token == ''
 	if scanner.stag.nil?
 	  case token
@@ -632,19 +632,19 @@
 class ERB
   #
   # Constructs a new ERB object with the template specified in _str_.
-  # 
+  #
   # An ERB object works by building a chunk of Ruby code that will output
   # the completed template when run. If _safe_level_ is set to a non-nil value,
   # ERB code will be run in a separate thread with <b>$SAFE</b> set to the
   # provided level.
-  # 
+  #
   # If _trim_mode_ is passed a String containing one or more of the following
   # modifiers, ERB will adjust its code generation as listed:
-  # 
+  #
   # 	%  enables Ruby code processing for lines beginning with %
   # 	<> omit newline for lines starting with <% and ending in %>
   # 	>  omit newline for lines ending in %>
-  # 
+  #
   # _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
   # templates through the same binding and/or when you want to control where
@@ -653,20 +653,20 @@
   # === Example
   #
   #  require "erb"
-  #  
+  #
   #  # build data class
   #  class Listings
   #    PRODUCT = { :name => "Chicken Fried Steak",
   #                :desc => "A well messages pattie, breaded and fried.",
   #                :cost => 9.95 }
-  #  
+  #
   #    attr_reader :product, :price
-  #    
+  #
   #    def initialize( product = "", price = "" )
   #      @product = product
   #      @price = price
   #    end
-  #    
+  #
   #    def build
   #      b = binding
   #      # create and run templates, filling member data variables
@@ -680,21 +680,21 @@
   #      END_PRICE
   #    end
   #  end
-  #  
+  #
   #  # setup template data
   #  listings = Listings.new
   #  listings.build
-  #  
+  #
   #  puts listings.product + "\n" + listings.price
   #
   # _Generates_
   #
   #  Chicken Fried Steak
   #  A well messages pattie, breaded and fried.
-  #  
+  #
   #  Chicken Fried Steak -- 9.95
   #  A well messages pattie, breaded and fried.
-  #  
+  #
   def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
     @safe_level = safe_level
     compiler = ERB::Compiler.new(trim_mode)
@@ -721,7 +721,7 @@
 
     cmd = []
     cmd.push "#{eoutvar} = ''"
-    
+
     compiler.pre_cmd = cmd
 
     cmd = []
@@ -739,13 +739,13 @@
   # Executes the generated ERB code to produce a completed template, returning
   # the results of that code.  (See ERB#new for details on how this process can
   # be affected by _safe_level_.)
-  # 
+  #
   # _b_ accepts a Binding or Proc object which is used to set the context of
   # code evaluation.
   #
   def result(b=TOPLEVEL_BINDING)
     if @safe_level
-      proc { 
+      proc {
 	$SAFE = @safe_level
 	eval(@src, b, (@filename || '(erb)'), 0)
       }.call
@@ -813,14 +813,14 @@
     public
     #
     # A utility method for escaping HTML tag characters in _s_.
-    # 
+    #
     # 	require "erb"
     # 	include ERB::Util
-    # 	
+    #
     # 	puts html_escape("is a > 0 & a < 10?")
-    # 
+    #
     # _Generates_
-    # 
+    #
     # 	is a &gt; 0 &amp; a &lt; 10?
     #
     def html_escape(s)
@@ -829,17 +829,17 @@
     alias h html_escape
     module_function :h
     module_function :html_escape
-    
+
     #
     # A utility method for encoding the String _s_ as a URL.
-    # 
+    #
     # 	require "erb"
     # 	include ERB::Util
-    # 	
+    #
     # 	puts url_encode("Programming Ruby:  The Pragmatic Programmer's Guide")
-    # 
+    #
     # _Generates_
-    # 
+    #
     # 	Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
     #
     def url_encode(s)

Modified: MacRuby/trunk/lib/fileutils.rb
===================================================================
--- MacRuby/trunk/lib/fileutils.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/fileutils.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,17 +1,17 @@
-# 
+#
 # = fileutils.rb
-# 
+#
 # Copyright (c) 2000-2007 Minero Aoki
-# 
+#
 # This program is free software.
 # You can distribute/modify this program under the same terms of ruby.
-# 
+#
 # == module FileUtils
-# 
+#
 # Namespace for several file utility methods for copying, moving, removing, etc.
-# 
+#
 # === Module Functions
-# 
+#
 #   cd(dir, options)
 #   cd(dir, options) {|dir| .... }
 #   pwd()
@@ -64,23 +64,23 @@
 #   uptodate?(file, cmp_list)
 #
 # == module FileUtils::Verbose
-# 
+#
 # This module has all methods of FileUtils module, but it outputs messages
 # before acting.  This equates to passing the <tt>:verbose</tt> flag to methods
 # in FileUtils.
-# 
+#
 # == module FileUtils::NoWrite
-# 
+#
 # This module has all methods of FileUtils module, but never changes
 # files/directories.  This equates to passing the <tt>:noop</tt> flag to methods
 # in FileUtils.
-# 
+#
 # == module FileUtils::DryRun
-# 
+#
 # This module has all methods of FileUtils module, but never changes
 # files/directories.  This equates to passing the <tt>:noop</tt> and
 # <tt>:verbose</tt> flags to methods in FileUtils.
-# 
+#
 
 module FileUtils
 
@@ -107,14 +107,14 @@
 
   #
   # Options: verbose
-  # 
+  #
   # Changes the current directory to the directory +dir+.
-  # 
+  #
   # If this method is called with block, resumes to the old
   # working directory after the block execution finished.
-  # 
+  #
   #   FileUtils.cd('/', :verbose => true)   # chdir and report it
-  # 
+  #
   def cd(dir, options = {}, &block) # :yield: dir
     fu_check_options options, OPT_TABLE['cd']
     fu_output_message "cd #{dir}" if options[:verbose]
@@ -131,13 +131,13 @@
 
   #
   # Options: (none)
-  # 
+  #
   # Returns true if +newer+ is newer than all +old_list+.
   # Non-existent files are older than any file.
-  # 
+  #
   #   FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
   #       system 'make hello.o'
-  # 
+  #
   def uptodate?(new, old_list, options = nil)
     raise ArgumentError, 'uptodate? does not accept any option' if options
 
@@ -154,14 +154,14 @@
 
   #
   # Options: mode noop verbose
-  # 
+  #
   # Creates one or more directories.
-  # 
+  #
   #   FileUtils.mkdir 'test'
   #   FileUtils.mkdir %w( tmp data )
   #   FileUtils.mkdir 'notexist', :noop => true  # Does not really create.
   #   FileUtils.mkdir 'tmp', :mode => 0700
-  # 
+  #
   def mkdir(list, options = {})
     fu_check_options options, OPT_TABLE['mkdir']
     list = fu_list(list)
@@ -178,12 +178,12 @@
 
   #
   # Options: mode noop verbose
-  # 
+  #
   # Creates a directory and all its parent directories.
   # For example,
-  # 
+  #
   #   FileUtils.mkdir_p '/usr/local/lib/ruby'
-  # 
+  #
   # causes to make following directories, if it does not exist.
   #     * /usr
   #     * /usr/local
@@ -191,7 +191,7 @@
   #     * /usr/local/lib/ruby
   #
   # You can pass several directories at a time in a list.
-  # 
+  #
   def mkdir_p(list, options = {})
     fu_check_options options, OPT_TABLE['mkdir_p']
     list = fu_list(list)
@@ -247,14 +247,14 @@
 
   #
   # Options: noop, verbose
-  # 
+  #
   # Removes one or more directories.
-  # 
+  #
   #   FileUtils.rmdir 'somedir'
   #   FileUtils.rmdir %w(somedir anydir otherdir)
   #   # Does not really remove directory; outputs message.
   #   FileUtils.rmdir 'somedir', :verbose => true, :noop => true
-  # 
+  #
   def rmdir(list, options = {})
     fu_check_options options, OPT_TABLE['rmdir']
     list = fu_list(list)
@@ -286,19 +286,19 @@
   # If +new+ already exists and it is a directory, creates a link +new/old+.
   # If +new+ already exists and it is not a directory, raises Errno::EEXIST.
   # But if :force option is set, overwrite +new+.
-  # 
+  #
   #   FileUtils.ln 'gcc', 'cc', :verbose => true
   #   FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'
-  # 
+  #
   # <b><tt>ln(list, destdir, options = {})</tt></b>
-  # 
+  #
   # Creates several hard links in a directory, with each one pointing to the
   # item in +list+.  If +destdir+ is not a directory, raises Errno::ENOTDIR.
-  # 
+  #
   #   include FileUtils
   #   cd '/sbin'
   #   FileUtils.ln %w(cp mv mkdir), '/bin'   # Now /sbin/cp and /bin/cp are linked.
-  # 
+  #
   def ln(src, dest, options = {})
     fu_check_options options, OPT_TABLE['ln']
     fu_output_message "ln#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
@@ -320,24 +320,24 @@
   # Options: force noop verbose
   #
   # <b><tt>ln_s(old, new, options = {})</tt></b>
-  # 
+  #
   # Creates a symbolic link +new+ which points to +old+.  If +new+ already
   # exists and it is a directory, creates a symbolic link +new/old+.  If +new+
   # already exists and it is not a directory, raises Errno::EEXIST.  But if
   # :force option is set, overwrite +new+.
-  # 
+  #
   #   FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
   #   FileUtils.ln_s 'verylongsourcefilename.c', 'c', :force => true
-  # 
+  #
   # <b><tt>ln_s(list, destdir, options = {})</tt></b>
-  # 
+  #
   # Creates several symbolic links in a directory, with each one pointing to the
   # item in +list+.  If +destdir+ is not a directory, raises Errno::ENOTDIR.
   #
   # If +destdir+ is not a directory, raises Errno::ENOTDIR.
-  # 
+  #
   #   FileUtils.ln_s Dir.glob('bin/*.rb'), '/home/aamine/bin'
-  # 
+  #
   def ln_s(src, dest, options = {})
     fu_check_options options, OPT_TABLE['ln_s']
     fu_output_message "ln -s#{options[:force] ? 'f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
@@ -357,10 +357,10 @@
 
   #
   # Options: noop verbose
-  # 
+  #
   # Same as
   #   #ln_s(src, dest, :force)
-  # 
+  #
   def ln_sf(src, dest, options = {})
     fu_check_options options, OPT_TABLE['ln_sf']
     options = options.dup
@@ -383,7 +383,7 @@
   #   FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
   #   FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', :verbose => true
   #   FileUtils.cp 'symlink', 'dest'   # copy content, "dest" is not a symlink
-  # 
+  #
   def cp(src, dest, options = {})
     fu_check_options options, OPT_TABLE['cp']
     fu_output_message "cp#{options[:preserve] ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
@@ -394,6 +394,8 @@
   end
   module_function :cp
 
+  # XXX Will not work on MacRuby:
+  # raises "can't change visibility of non Ruby method `copy' (RuntimeError)"
   #alias copy cp
   #module_function :copy
 
@@ -402,17 +404,17 @@
 
   #
   # Options: preserve noop verbose dereference_root remove_destination
-  # 
+  #
   # Copies +src+ to +dest+. If +src+ is a directory, this method copies
   # all its contents recursively. If +dest+ is a directory, copies
   # +src+ to +dest/src+.
   #
   # +src+ can be a list of files.
-  # 
+  #
   #   # Installing ruby library "mylib" under the site_ruby
   #   FileUtils.rm_r site_ruby + '/mylib', :force
   #   FileUtils.cp_r 'lib/', site_ruby + '/mylib'
-  # 
+  #
   #   # Examples of copying several files to target directory.
   #   FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
   #   FileUtils.cp_r Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true
@@ -422,11 +424,13 @@
   #   # use following code.
   #   FileUtils.cp_r 'src/.', 'dest'     # cp_r('src', 'dest') makes src/dest,
   #                                      # but this doesn't.
-  # 
+  #
   def cp_r(src, dest, options = {})
     fu_check_options options, OPT_TABLE['cp_r']
     fu_output_message "cp -r#{options[:preserve] ? 'p' : ''}#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
     return if options[:noop]
+    options = options.dup
+    options[:dereference_root] = true unless options.key?(:dereference_root)
     fu_each_src_dest(src, dest) do |s, d|
       copy_entry s, d, options[:preserve], options[:dereference_root], options[:remove_destination]
     end
@@ -485,16 +489,16 @@
 
   #
   # Options: force noop verbose
-  # 
+  #
   # Moves file(s) +src+ to +dest+.  If +file+ and +dest+ exist on the different
-  # disk partition, the file is copied instead.
-  # 
+  # disk partition, the file is copied then the original file is removed.
+  #
   #   FileUtils.mv 'badname.rb', 'goodname.rb'
   #   FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true  # no error
-  # 
+  #
   #   FileUtils.mv %w(junk.txt dust.txt), '/home/aamine/.trash/'
   #   FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true
-  # 
+  #
   def mv(src, dest, options = {})
     fu_check_options options, OPT_TABLE['mv']
     fu_output_message "mv#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
@@ -539,14 +543,14 @@
 
   #
   # Options: force noop verbose
-  # 
+  #
   # Remove file(s) specified in +list+.  This method cannot remove directories.
   # All StandardErrors are ignored when the :force option is set.
-  # 
+  #
   #   FileUtils.rm %w( junk.txt dust.txt )
   #   FileUtils.rm Dir.glob('*.so')
   #   FileUtils.rm 'NotExistFile', :force => true   # never raises exception
-  # 
+  #
   def rm(list, options = {})
     fu_check_options options, OPT_TABLE['rm']
     list = fu_list(list)
@@ -567,7 +571,7 @@
 
   #
   # Options: noop verbose
-  # 
+  #
   # Equivalent to
   #
   #   #rm(list, :force => true)
@@ -588,11 +592,11 @@
 
   #
   # Options: force noop verbose secure
-  # 
+  #
   # remove files +list+[0] +list+[1]... If +list+[n] is a directory,
   # removes its all contents recursively. This method ignores
   # StandardError when :force option is set.
-  # 
+  #
   #   FileUtils.rm_r Dir.glob('/tmp/*')
   #   FileUtils.rm_r '/', :force => true          #  :-)
   #
@@ -606,7 +610,7 @@
   #
   # NOTE: This method calls #remove_entry_secure if :secure option is set.
   # See also #remove_entry_secure.
-  # 
+  #
   def rm_r(list, options = {})
     fu_check_options options, OPT_TABLE['rm_r']
     # options[:secure] = true unless options.key?(:secure)
@@ -627,14 +631,14 @@
 
   #
   # Options: noop verbose secure
-  # 
+  #
   # Equivalent to
   #
   #   #rm_r(list, :force => true)
   #
   # WARNING: This method causes local vulnerability.
   # Read the documentation of #rm_r first.
-  # 
+  #
   def rm_rf(list, options = {})
     fu_check_options options, OPT_TABLE['rm_rf']
     options = options.dup
@@ -788,7 +792,7 @@
 
   #
   # Returns true if the contents of a file A and a file B are identical.
-  # 
+  #
   #   FileUtils.compare_file('somefile', 'somefile')  #=> true
   #   FileUtils.compare_file('/bin/cp', '/bin/mv')    #=> maybe false
   #
@@ -828,22 +832,21 @@
 
   #
   # Options: mode preserve noop verbose
-  # 
+  #
   # If +src+ is not same as +dest+, copies it and changes the permission
   # mode to +mode+.  If +dest+ is a directory, destination is +dest+/+src+.
   # This method removes destination before copy.
-  # 
+  #
   #   FileUtils.install 'ruby', '/usr/local/bin/ruby', :mode => 0755, :verbose => true
   #   FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', :verbose => true
-  # 
+  #
   def install(src, dest, options = {})
     fu_check_options options, OPT_TABLE['install']
     fu_output_message "install -c#{options[:preserve] && ' -p'}#{options[:mode] ? (' -m 0%o' % options[:mode]) : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
     return if options[:noop]
-    fu_each_src_dest(src, dest) do |s, d|
+    fu_each_src_dest(src, dest) do |s, d, st|
       unless File.exist?(d) and compare_file(s, d)
         remove_file d, true
-        st = File.stat(s) if options[:preserve]
         copy_file s, d
         File.utime st.atime, st.mtime, d if options[:preserve]
         File.chmod options[:mode], d if options[:mode]
@@ -856,14 +859,14 @@
 
   #
   # Options: noop verbose
-  # 
+  #
   # Changes permission bits on the named files (in +list+) to the bit pattern
   # represented by +mode+.
-  # 
+  #
   #   FileUtils.chmod 0755, 'somecommand'
   #   FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
   #   FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true
-  # 
+  #
   def chmod(mode, list, options = {})
     fu_check_options options, OPT_TABLE['chmod']
     list = fu_list(list)
@@ -879,12 +882,12 @@
 
   #
   # Options: noop verbose force
-  # 
+  #
   # Changes permission bits on the named files (in +list+)
   # to the bit pattern represented by +mode+.
-  # 
+  #
   #   FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
-  # 
+  #
   def chmod_R(mode, list, options = {})
     fu_check_options options, OPT_TABLE['chmod_R']
     list = fu_list(list)
@@ -908,16 +911,16 @@
 
   #
   # Options: noop verbose
-  # 
+  #
   # Changes owner and group on the named files (in +list+)
   # to the user +user+ and the group +group+.  +user+ and +group+
   # may be an ID (Integer/String) or a name (String).
   # If +user+ or +group+ is nil, this method does not change
   # the attribute.
-  # 
+  #
   #   FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
   #   FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), :verbose => true
-  # 
+  #
   def chown(user, group, list, options = {})
     fu_check_options options, OPT_TABLE['chown']
     list = fu_list(list)
@@ -937,16 +940,16 @@
 
   #
   # Options: noop verbose force
-  # 
+  #
   # Changes owner and group on the named files (in +list+)
   # to the user +user+ and the group +group+ recursively.
   # +user+ and +group+ may be an ID (Integer/String) or
   # a name (String).  If +user+ or +group+ is nil, this
   # method does not change the attribute.
-  # 
+  #
   #   FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
   #   FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true
-  # 
+  #
   def chown_R(user, group, list, options = {})
     fu_check_options options, OPT_TABLE['chown_R']
     list = fu_list(list)
@@ -977,19 +980,26 @@
 
     def fu_get_uid(user)   #:nodoc:
       return nil unless user
-      user = user.to_s
-      if /\A\d+\z/ =~ user
-      then user.to_i
-      else Etc.getpwnam(user).uid
+      case user
+      when Integer
+        user
+      when /\A\d+\z/
+        user.to_i
+      else
+        Etc.getpwnam(user).uid
       end
     end
     private_module_function :fu_get_uid
 
     def fu_get_gid(group)   #:nodoc:
       return nil unless group
-      if /\A\d+\z/ =~ group
-      then group.to_i
-      else Etc.getgrnam(group).gid
+      case group
+      when Integer
+        group
+      when /\A\d+\z/
+        group.to_i
+      else
+        Etc.getgrnam(group).gid
       end
     end
     private_module_function :fu_get_gid
@@ -1010,13 +1020,13 @@
 
   #
   # Options: noop verbose
-  # 
+  #
   # Updates modification time (mtime) and access time (atime) of file(s) in
   # +list+.  Files are created if they don't exist.
-  # 
+  #
   #   FileUtils.touch 'timestamp'
   #   FileUtils.touch Dir.glob('*.c');  system 'make'
-  # 
+  #
   def touch(list, options = {})
     fu_check_options options, OPT_TABLE['touch']
     list = fu_list(list)
@@ -1168,7 +1178,9 @@
     end
 
     def entries
-      Dir.entries(path())\
+      opts = {}
+      opts[:encoding] = "UTF-8" if /mswin|mignw/ =~ RUBY_PLATFORM
+      Dir.entries(path(), opts)\
           .reject {|n| n == '.' or n == '..' }\
           .map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) }
     end
@@ -1260,7 +1272,11 @@
     end
 
     def copy_file(dest)
-      IO.copy_stream(path(),  dest)
+      File.open(path()) do |s|
+        File.open(dest, 'wb') do |f|
+          IO.copy_stream(s, f)
+        end
+      end
     end
 
     def copy_metadata(path)
@@ -1390,7 +1406,7 @@
   def fu_each_src_dest(src, dest)   #:nodoc:
     fu_each_src_dest0(src, dest) do |s, d|
       raise ArgumentError, "same file: #{s} and #{d}" if fu_same?(s, d)
-      yield s, d
+      yield s, d, File.stat(s)
     end
   end
   private_module_function :fu_each_src_dest
@@ -1413,23 +1429,10 @@
   private_module_function :fu_each_src_dest0
 
   def fu_same?(a, b)   #:nodoc:
-    if fu_have_st_ino?
-      st1 = File.stat(a)
-      st2 = File.stat(b)
-      st1.dev == st2.dev and st1.ino == st2.ino
-    else
-      File.expand_path(a) == File.expand_path(b)
-    end
-  rescue Errno::ENOENT
-    return false
+    File.identical?(a, b)
   end
   private_module_function :fu_same?
 
-  def fu_have_st_ino?   #:nodoc:
-    not fu_windows?
-  end
-  private_module_function :fu_have_st_ino?
-
   def fu_check_options(options, optdecl)   #:nodoc:
     h = options.dup
     optdecl.each do |opt|
@@ -1510,11 +1513,11 @@
   METHODS = singleton_methods() - [:private_module_function,
       :commands, :options, :have_option?, :options_of, :collect_method]
 
-  # 
+  #
   # This module has all methods of FileUtils module, but it outputs messages
   # before acting.  This equates to passing the <tt>:verbose</tt> flag to
   # methods in FileUtils.
-  # 
+  #
   module Verbose
     include FileUtils
     @fileutils_output  = $stderr
@@ -1535,11 +1538,11 @@
     end
   end
 
-  # 
+  #
   # This module has all methods of FileUtils module, but never changes
   # files/directories.  This equates to passing the <tt>:noop</tt> flag
   # to methods in FileUtils.
-  # 
+  #
   module NoWrite
     include FileUtils
     @fileutils_output  = $stderr
@@ -1560,12 +1563,12 @@
     end
   end
 
-  # 
+  #
   # This module has all methods of FileUtils module, but never changes
   # files/directories, with printing message before acting.
   # This equates to passing the <tt>:noop</tt> and <tt>:verbose</tt> flag
   # to methods in FileUtils.
-  # 
+  #
   module DryRun
     include FileUtils
     @fileutils_output  = $stderr

Modified: MacRuby/trunk/lib/find.rb
===================================================================
--- MacRuby/trunk/lib/find.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/find.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -39,28 +39,24 @@
     while file = paths.shift
       catch(:prune) do
 	yield file.dup.taint
-        next unless File.exist? file
-	begin
-	  if File.lstat(file).directory? then
-	    d = Dir.open(file)
-	    begin
-	      for f in d
-		next if f == "." or f == ".."
-		if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then
-		  f = file + f
-		elsif file == "/" then
-		  f = "/" + f
-		else
-		  f = File.join(file, f)
-		end
-		paths.unshift f.untaint
-	      end
-	    ensure
-	      d.close
-	    end
-	  end
-       rescue Errno::ENOENT, Errno::EACCES
-	end
+        begin
+          s = File.lstat(file)
+        rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
+          next
+        end
+        if s.directory? then
+          begin
+            fs = Dir.entries(file)
+          rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
+            next
+          end
+          fs.sort!
+          fs.reverse_each {|f|
+            next if f == "." or f == ".."
+            f = File.join(file, f)
+            paths.unshift f.untaint
+          }
+        end
       end
     end
   end

Modified: MacRuby/trunk/lib/forwardable.rb
===================================================================
--- MacRuby/trunk/lib/forwardable.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/forwardable.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,7 +1,7 @@
 #
-#   forwardable.rb - 
+#   forwardable.rb -
 #   	$Release Version: 1.1$
-#   	$Revision: 16810 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ishitsuka.com)
 #	original definition by delegator.rb
 #       Revised by Daniel J. Berger with suggestions from Florian Gross.
@@ -33,28 +33,28 @@
 #
 #   class Queue
 #     extend Forwardable
-#     
+#
 #     def initialize
 #       @q = [ ]    # prepare delegate object
 #     end
-#     
+#
 #     # setup preferred interface, enq() and deq()...
 #     def_delegator :@q, :push, :enq
 #     def_delegator :@q, :shift, :deq
-#     
+#
 #     # support some general Array methods that fit Queues well
 #     def_delegators :@q, :clear, :first, :push, :shift, :size
 #   end
-# 
+#
 #   q = Queue.new
 #   q.enq 1, 2, 3, 4, 5
 #   q.push 6
-# 
+#
 #   q.shift    # => 1
 #   while q.size > 0
 #     puts q.deq
 #   end
-# 
+#
 #   q.enq "Ruby", "Perl", "Python"
 #   puts q.first
 #   q.clear
@@ -70,9 +70,30 @@
 #   Ruby
 #   nil
 #
-# Forwardable can be used to setup delegation at the object level as well.
+# SingleForwardable can be used to setup delegation at the object level as well.
 #
 #    printer = String.new
+#    printer.extend SingleForwardable        # prepare object for delegation
+#    printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
+#    printer.puts "Howdy!"
+#
+# Also, SingleForwardable can be use to Class or Module.
+#
+#    module Facade
+#      extend SingleForwardable
+#      def_delegator :Implementation, :service
+#
+#      class Implementation
+#	  def service...
+#      end
+#    end
+#
+# If you want to use both Forwardable and SingleForwardable, you can
+# use methods def_instance_delegator and def_single_delegator, etc.
+#
+# If the object isn't a Module and Class, You can too extend
+# Forwardable module.
+#    printer = String.new
 #    printer.extend Forwardable              # prepare object for delegation
 #    printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
 #    printer.puts "Howdy!"
@@ -111,8 +132,13 @@
 # Also see the example at forwardable.rb.
 
 module Forwardable
-  FORWARDABLE_VERSION = "1.0.0"
-  
+  FORWARDABLE_VERSION = "1.1.0"
+
+  @debug = nil
+  class<<self
+    attr_accessor :debug
+  end
+
   # Takes a hash as its argument.  The key is a symbol or an array of
   # symbols.  These symbols correspond to method names.  The value is
   # the accessor to which the methods will be delegated.
@@ -121,7 +147,7 @@
   #    delegate method => accessor
   #    delegate [method, method, ...] => accessor
   #
-  def delegate(hash)
+  def instance_delegate(hash)
     hash.each{ |methods, accessor|
       methods = methods.to_s unless methods.respond_to?(:each)
       methods.each{ |method|
@@ -144,34 +170,101 @@
   def def_instance_delegators(accessor, *methods)
     methods.delete("__send__")
     methods.delete("__id__")
-    methods.each{ |method|
+    for method in methods
       def_instance_delegator(accessor, method)
-    }
+    end
   end
 
-  #
-  # Defines a method _method_ which delegates to _obj_ (i.e. it calls
-  # the method of the same name in _obj_).  If _new_name_ is
-  # provided, it is used as the name for the delegate method.
-  #
   def def_instance_delegator(accessor, method, ali = method)
-    str = %Q{
+    line_no = __LINE__; str = %{
       def #{ali}(*args, &block)
-        #{accessor}.send(:#{method}, *args, &block)
+	begin
+	  #{accessor}.__send__(:#{method}, *args, &block)
+	rescue Exception
+	  $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
+	  ::Kernel::raise
+	end
       end
     }
-
     # If it's not a class or module, it's an instance
     begin
-      module_eval(str)
+      module_eval(str, __FILE__, line_no)
     rescue
-      instance_eval(str)
+      instance_eval(str, __FILE__, line_no)
     end
+
   end
 
+  alias delegate instance_delegate
   alias def_delegators def_instance_delegators
   alias def_delegator def_instance_delegator
 end
 
-# compatibility
-SingleForwardable = Forwardable
+#
+# Usage of The SingleForwardable is like Fowadable module.
+#
+module SingleForwardable
+  # Takes a hash as its argument.  The key is a symbol or an array of
+  # symbols.  These symbols correspond to method names.  The value is
+  # the accessor to which the methods will be delegated.
+  #
+  # :call-seq:
+  #    delegate method => accessor
+  #    delegate [method, method, ...] => accessor
+  #
+  def single_delegate(hash)
+    hash.each{ |methods, accessor|
+      methods = methods.to_s unless methods.respond_to?(:each)
+      methods.each{ |method|
+        def_single_delegator(accessor, method)
+      }
+    }
+  end
+
+  #
+  # Shortcut for defining multiple delegator methods, but with no
+  # provision for using a different name.  The following two code
+  # samples have the same effect:
+  #
+  #   def_delegators :@records, :size, :<<, :map
+  #
+  #   def_delegator :@records, :size
+  #   def_delegator :@records, :<<
+  #   def_delegator :@records, :map
+  #
+  def def_single_delegators(accessor, *methods)
+    methods.delete("__send__")
+    methods.delete("__id__")
+    for method in methods
+      def_single_delegator(accessor, method)
+    end
+  end
+
+  #
+  # Defines a method _method_ which delegates to _obj_ (i.e. it calls
+  # the method of the same name in _obj_).  If _new_name_ is
+  # provided, it is used as the name for the delegate method.
+  #
+  def def_single_delegator(accessor, method, ali = method)
+    line_no = __LINE__; str = %{
+      def #{ali}(*args, &block)
+	begin
+	  #{accessor}.__send__(:#{method}, *args, &block)
+	rescue Exception
+	  $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
+	  ::Kernel::raise
+	end
+      end
+    }
+
+    instance_eval(str, __FILE__, __LINE__)
+  end
+
+  alias delegate single_delegate
+  alias def_delegators def_single_delegators
+  alias def_delegator def_single_delegator
+end
+
+
+
+

Modified: MacRuby/trunk/lib/getoptlong.rb
===================================================================
--- MacRuby/trunk/lib/getoptlong.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/getoptlong.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -12,10 +12,10 @@
 # found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
 
 # The GetoptLong class allows you to parse command line options similarly to
-# the GNU getopt_long() C library call. Note, however, that GetoptLong is a 
+# the GNU getopt_long() C library call. Note, however, that GetoptLong is a
 # pure Ruby implementation.
 #
-# GetoptLong allows for POSIX-style options like <tt>--file</tt> as well 
+# GetoptLong allows for POSIX-style options like <tt>--file</tt> as well
 # as single letter options like <tt>-f</tt>
 #
 # The empty option <tt>--</tt> (two minus symbols) is used to end option
@@ -25,14 +25,13 @@
 # Here is a simple example of usage:
 #
 #     require 'getoptlong'
-#     require 'rdoc/usage'
-#     
+#
 #     opts = GetoptLong.new(
 #       [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
 #       [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
 #       [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
 #     )
-#     
+#
 #     dir = nil
 #     name = nil
 #     repetitions = 1
@@ -41,16 +40,16 @@
 #         when '--help'
 #           puts <<-EOF
 #     hello [OPTION] ... DIR
-#     
+#
 #     -h, --help:
 #        show help
-#     
+#
 #     --repeat x, -n x:
 #        repeat x times
-#     
+#
 #     --name [name]:
 #        greet user by name, if name not supplied default is John
-#     
+#
 #     DIR: The directory in which to issue the greeting.
 #           EOF
 #         when '--repeat'
@@ -63,12 +62,12 @@
 #           end
 #       end
 #     end
-#     
+#
 #     if ARGV.length != 1
 #       puts "Missing dir argument (try --help)"
 #       exit 0
 #     end
-#     
+#
 #     dir = ARGV.shift
 #
 #     Dir.chdir(dir)
@@ -114,7 +113,7 @@
   # Set up option processing.
   #
   # The options to support are passed to new() as an array of arrays.
-  # Each sub-array contains any number of String option names which carry 
+  # Each sub-array contains any number of String option names which carry
   # the same meaning, and one of the following flags:
   #
   # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
@@ -194,23 +193,23 @@
   # the processing of options as follows:
   #
   # <b>REQUIRE_ORDER</b> :
-  # 
+  #
   # Options are required to occur before non-options.
   #
   # Processing of options ends as soon as a word is encountered that has not
   # been preceded by an appropriate option flag.
   #
   # For example, if -a and -b are options which do not take arguments,
-  # parsing command line arguments of '-a one -b two' would result in 
-  # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being 
+  # parsing command line arguments of '-a one -b two' would result in
+  # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being
   # processed as an option/arg pair.
   #
   # This is the default ordering, if the environment variable
   # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
   #
   # <b>PERMUTE</b> :
-  #  
-  # Options can occur anywhere in the command line parsed. This is the 
+  #
+  # Options can occur anywhere in the command line parsed. This is the
   # default behavior.
   #
   # Every sequence of words which can be interpreted as an option (with or
@@ -227,7 +226,7 @@
   #
   # <b>RETURN_IN_ORDER</b> :
   #
-  # All words on the command line are processed as options. Words not 
+  # All words on the command line are processed as options. Words not
   # preceded by a short or long option flag are passed as arguments
   # with an option of '' (empty string).
   #
@@ -273,7 +272,7 @@
     # The method is failed if option processing has already started.
     #
     if @status != STATUS_YET
-      raise RuntimeError, 
+      raise RuntimeError,
 	"invoke set_options, but option processing has already started"
     end
 
@@ -283,8 +282,11 @@
     @canonical_names.clear
     @argument_flags.clear
 
-    arguments.each do |*arg|
-      arg = arg.first # TODO: YARV Hack
+    arguments.each do |arg|
+      if !arg.is_a?(Array)
+       raise ArgumentError, "the option list contains non-Array argument"
+      end
+
       #
       # Find an argument flag and it set to `argument_flag'.
       #
@@ -320,7 +322,7 @@
 	end
 
 	#
-	# Register the option (`i') to the `@canonical_names' and 
+	# Register the option (`i') to the `@canonical_names' and
 	# `@canonical_names' Hashes.
 	#
 	if canonical_name == nil
@@ -452,7 +454,7 @@
 	return nil
       end
       argument = ARGV.shift
-    elsif @ordering == REQUIRE_ORDER 
+    elsif @ordering == REQUIRE_ORDER
       if (ARGV[0] !~ /^-./)
 	terminate
 	return nil
@@ -589,7 +591,7 @@
   #
   # The block is called repeatedly with two arguments:
   # The first is the option name.
-  # The second is the argument which followed it (if any). 
+  # The second is the argument which followed it (if any).
   # Example: ('--opt', 'value')
   #
   # The option name is always converted to the first (preferred)

Modified: MacRuby/trunk/lib/gserver.rb
===================================================================
--- MacRuby/trunk/lib/gserver.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/gserver.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -13,7 +13,7 @@
 
 #
 # GServer implements a generic server, featuring thread pool management,
-# simple logging, and multi-server management.  See HttpServer in 
+# simple logging, and multi-server management.  See HttpServer in
 # <tt>xmlrpc/httpserver.rb</tt> in the Ruby standard library for an example of
 # GServer in action.
 #
@@ -34,7 +34,7 @@
 #
 #   #
 #   # A server that returns the time in seconds since 1970.
-#   # 
+#   #
 #   class TimeServer < GServer
 #     def initialize(port=10001, *args)
 #       super(port, *args)
@@ -47,17 +47,17 @@
 #   # Run the server with logging enabled (it's a separate thread).
 #   server = TimeServer.new
 #   server.audit = true                  # Turn logging on.
-#   server.start 
+#   server.start
 #
 #   # *** Now point your browser to http://localhost:10001 to see it working ***
 #
-#   # See if it's still running. 
+#   # See if it's still running.
 #   GServer.in_service?(10001)           # -> true
 #   server.stopped?                      # -> false
 #
 #   # Shut the server down gracefully.
 #   server.shutdown
-#   
+#
 #   # Alternatively, stop it immediately.
 #   GServer.stop(10001)
 #   # or, of course, "server.stop".

Modified: MacRuby/trunk/lib/ipaddr.rb
===================================================================
--- MacRuby/trunk/lib/ipaddr.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/ipaddr.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -7,7 +7,7 @@
 #
 # You can redistribute and/or modify it under the same terms as Ruby.
 #
-# $Id: ipaddr.rb 19504 2008-09-23 21:39:21Z ryan $
+# $Id: ipaddr.rb 27000 2010-03-21 12:10:53Z akr $
 #
 # Contact:
 #   - Akinori MUSHA <knu at iDaemons.org> (current maintainer)
@@ -18,7 +18,7 @@
 require 'socket'
 
 unless Socket.const_defined? "AF_INET6"
-  class Socket
+  class Socket < BasicSocket
     AF_INET6 = Object.new
   end
 
@@ -66,19 +66,19 @@
 # == Example
 #
 #   require 'ipaddr'
-#   
+#
 #   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.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>
-#   
+#
 #   p ipaddr2.to_s		#=> "3ffe:505:2::"
-#   
+#
 #   ipaddr3 = IPAddr.new "192.168.2.0/24"
-#   
+#
 #   p ipaddr3			#=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
 
 class IPAddr
@@ -331,6 +331,16 @@
   end
   include Comparable
 
+  # Checks equality used by Hash.
+  def eql?(other)
+    return self.class == other.class && self.hash == other.hash && self == other
+  end
+
+  # Returns a hash value used by Hash, Set, and Array classes
+  def hash
+    return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
+  end
+
   # Creates a Range object for the network address.
   def to_range
     begin_addr = (@addr & @mask_addr)
@@ -425,7 +435,7 @@
   # Creates a new ipaddr object either from a human readable IP
   # address representation in string, or from a packed in_addr value
   # followed by an address family.
-  # 
+  #
   # In the former case, the following are the valid formats that will
   # be recognized: "address", "address/prefixlen" and "address/mask",
   # where IPv6 address may be enclosed in square brackets (`[' and
@@ -433,8 +443,8 @@
   # IP address.  Although the address family is determined
   # automatically from a specified string, you can specify one
   # explicitly by the optional second argument.
-  # 
-  # Otherwise an IP addess is generated from a packed in_addr value
+  #
+  # Otherwise an IP address is generated from a packed in_addr value
   # and an address family.
   #
   # The IPAddr class defines many methods and operators, and some of
@@ -462,7 +472,7 @@
     #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
     #		       Socket::AI_NUMERICHOST)
     begin
-      IPSocket.getaddress(prefix)		# test if address is vaild
+      IPSocket.getaddress(prefix)		# test if address is valid
     rescue
       raise ArgumentError, "invalid address"
     end
@@ -810,4 +820,31 @@
 
   end
 
+  def test_hash
+    a1 = IPAddr.new('192.168.2.0')
+    a2 = IPAddr.new('192.168.2.0')
+    a3 = IPAddr.new('3ffe:505:2::1')
+    a4 = IPAddr.new('3ffe:505:2::1')
+    a5 = IPAddr.new('127.0.0.1')
+    a6 = IPAddr.new('::1')
+    a7 = IPAddr.new('192.168.2.0/25')
+    a8 = IPAddr.new('192.168.2.0/25')
+
+    h = { a1 => 'ipv4', a2 => 'ipv4', a3 => 'ipv6', a4 => 'ipv6', a5 => 'ipv4', a6 => 'ipv6', a7 => 'ipv4', a8 => 'ipv4'}
+    assert_equal(5, h.size)
+    assert_equal('ipv4', h[a1])
+    assert_equal('ipv4', h[a2])
+    assert_equal('ipv6', h[a3])
+    assert_equal('ipv6', h[a4])
+
+    require 'set'
+    s = Set[a1, a2, a3, a4, a5, a6, a7, a8]
+    assert_equal(5, s.size)
+    assert_equal(true, s.include?(a1))
+    assert_equal(true, s.include?(a2))
+    assert_equal(true, s.include?(a3))
+    assert_equal(true, s.include?(a4))
+    assert_equal(true, s.include?(a5))
+    assert_equal(true, s.include?(a6))
+  end
 end

Modified: MacRuby/trunk/lib/logger.rb
===================================================================
--- MacRuby/trunk/lib/logger.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/logger.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,24 +1,19 @@
 # logger.rb - simple logging utility
-# Copyright (C) 2000-2003, 2005  NAKAMURA, Hiroshi <nakahiro at sarion.co.jp>.
-
-require 'monitor'
-
-# = logger.rb
+# Copyright (C) 2000-2003, 2005, 2008  NAKAMURA, Hiroshi <nahi at ruby-lang.org>.
 #
-# Simple logging utility.
-#
 # Author:: NAKAMURA, Hiroshi  <nakahiro at sarion.co.jp>
 # Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair
 # License::
 #   You can redistribute it and/or modify it under the same terms of Ruby's
 #   license; either the dual license version in 2003, or any later version.
-# Revision:: $Id: logger.rb 20321 2008-11-22 14:52:06Z yugui $
+# Revision:: $Id: logger.rb 25413 2009-10-20 15:08:38Z nahi $
 #
 # See Logger for documentation.
-#
 
 
-#
+require 'monitor'
+
+
 # == Description
 #
 # The Logger class provides a simple but sophisticated logging utility that
@@ -180,8 +175,8 @@
 
 
 class Logger
-  VERSION = "1.2.6"
-  id, name, rev = %w$Id: logger.rb 20321 2008-11-22 14:52:06Z yugui $
+  VERSION = "1.2.7"
+  id, name, rev = %w$Id: logger.rb 25413 2009-10-20 15:08:38Z nahi $
   if name
     name = name.chomp(",v")
   else
@@ -191,7 +186,7 @@
   ProgName = "#{name}/#{rev}"
 
   class Error < RuntimeError; end
-  class ShiftingError < Error; end
+  class ShiftingError < Error; end # not used after 1.2.7. just for compat.
 
   # Logging severity.
   module Severity
@@ -334,10 +329,10 @@
     progname ||= @progname
     if message.nil?
       if block_given?
-	message = yield
+        message = yield
       else
-	message = progname
-	progname = @progname
+        message = progname
+        progname = @progname
       end
     end
     @logdev.write(
@@ -499,32 +494,44 @@
       @dev = @filename = @shift_age = @shift_size = nil
       @mutex = LogDeviceMutex.new
       if log.respond_to?(:write) and log.respond_to?(:close)
-	@dev = log
+        @dev = log
       else
-	@dev = open_logfile(log)
-	@dev.sync = true
-	@filename = log
-	@shift_age = opt[:shift_age] || 7
-	@shift_size = opt[:shift_size] || 1048576
+        @dev = open_logfile(log)
+        @dev.sync = true
+        @filename = log
+        @shift_age = opt[:shift_age] || 7
+        @shift_size = opt[:shift_size] || 1048576
       end
     end
 
     def write(message)
-      @mutex.synchronize do
-        if @shift_age and @dev.respond_to?(:stat)
+      begin
+        @mutex.synchronize do
+          if @shift_age and @dev.respond_to?(:stat)
+            begin
+              check_shift_log
+            rescue
+              warn("log shifting failed. #{$!}")
+            end
+          end
           begin
-            check_shift_log
+            @dev.write(message)
           rescue
-            raise Logger::ShiftingError.new("Shifting failed. #{$!}")
+            warn("log writing failed. #{$!}")
           end
         end
-        @dev.write(message)
+      rescue Exception => ignored
+        warn("log writing failed. #{ignored}")
       end
     end
 
     def close
-      @mutex.synchronize do
-        @dev.close
+      begin
+        @mutex.synchronize do
+          @dev.close rescue nil
+        end
+      rescue Exception => ignored
+        @dev.close rescue nil
       end
     end
 
@@ -532,9 +539,9 @@
 
     def open_logfile(filename)
       if (FileTest.exist?(filename))
-     	open(filename, (File::WRONLY | File::APPEND))
+        open(filename, (File::WRONLY | File::APPEND))
       else
-       	create_logfile(filename)
+        create_logfile(filename)
       end
     end
 
@@ -547,8 +554,8 @@
 
     def add_log_header(file)
       file.write(
-     	"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
-    )
+        "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
+      )
     end
 
     SiD = 24 * 60 * 60
@@ -561,8 +568,9 @@
         end
       else
         now = Time.now
-        if @dev.stat.mtime <= previous_period_end(now)
-          shift_log_period(now)
+        period_end = previous_period_end(now)
+        if @dev.stat.mtime <= period_end
+          shift_log_period(period_end)
         end
       end
     end
@@ -573,19 +581,26 @@
           File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
         end
       end
-      @dev.close
+      @dev.close rescue nil
       File.rename("#{@filename}", "#{@filename}.0")
       @dev = create_logfile(@filename)
       return true
     end
 
-    def shift_log_period(now)
-      postfix = previous_period_end(now).strftime("%Y%m%d")	# YYYYMMDD
+    def shift_log_period(period_end)
+      postfix = period_end.strftime("%Y%m%d") # YYYYMMDD
       age_file = "#{@filename}.#{postfix}"
       if FileTest.exist?(age_file)
-        raise RuntimeError.new("'#{ age_file }' already exists.")
+        # try to avoid filename crash caused by Timestamp change.
+        idx = 0
+        # .99 can be overriden; avoid too much file search with 'loop do'
+        while idx < 100
+          idx += 1
+          age_file = "#{@filename}.#{postfix}.#{idx}"
+          break unless FileTest.exist?(age_file)
+        end
       end
-      @dev.close
+      @dev.close rescue nil
       File.rename("#{@filename}", age_file)
       @dev = create_logfile(@filename)
       return true
@@ -672,12 +687,12 @@
     def start
       status = -1
       begin
-	log(INFO, "Start of #{ @appname }.")
-	status = run
+        log(INFO, "Start of #{ @appname }.")
+        status = run
       rescue
-	log(FATAL, "Detected an exception. Stopping ... #{$!} (#{$!.class})\n" << $@.join("\n"))
+        log(FATAL, "Detected an exception. Stopping ... #{$!} (#{$!.class})\n" << $@.join("\n"))
       ensure
-	log(INFO, "End of #{ @appname }. (status: #{ status.to_s })")
+        log(INFO, "End of #{ @appname }. (status: #{ status.to_s })")
       end
       status
     end
@@ -692,6 +707,8 @@
     #
     def logger=(logger)
       @log = logger
+      @log.progname = @appname
+      @log.level = @level
     end
 
     #
@@ -726,6 +743,7 @@
   private
 
     def run
+      # TODO: should be an NotImplementedError
       raise RuntimeError.new('Method run must be defined in the derived class.')
     end
   end

Modified: MacRuby/trunk/lib/mathn.rb
===================================================================
--- MacRuby/trunk/lib/mathn.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/mathn.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,20 +1,20 @@
 #
-#   mathn.rb - 
+#   mathn.rb -
 #   	$Release Version: 0.5 $
 #   	$Revision: 1.1.1.1.4.1 $
 #   	by Keiju ISHITSUKA(SHL Japan Inc.)
 #
 # --
 #
-#   
 #
+#
 
 require "cmath.rb"
 require "matrix.rb"
 require "prime.rb"
 
-#require "mathn/rational"
-#require "mathn/complex"
+# require "mathn/rational"
+# require "mathn/complex"
 
 unless defined?(Math.exp!)
   Object.instance_eval{remove_const :Math}
@@ -25,7 +25,7 @@
   remove_method :/
   alias / quo
 
-  alias power! ** unless defined?(0.power!)
+  alias power! ** unless method_defined? :power!
 
   def ** (other)
     if self < 0 && other.round != other
@@ -41,7 +41,7 @@
   remove_method :/
   alias / quo
 
-  alias power! ** unless defined?(0.power!)
+  alias power! ** unless method_defined? :power!
 
   def ** (other)
     if self < 0 && other.round != other
@@ -54,6 +54,7 @@
 end
 
 class Rational
+  remove_method :**
   def ** (other)
     if other.kind_of?(Rational)
       other2 = other
@@ -66,14 +67,14 @@
       elsif self == 1
 	return Rational(1,1)
       end
-      
+
       npd = numerator.prime_division
       dpd = denominator.prime_division
       if other < 0
 	other = -other
 	npd, dpd = dpd, npd
       end
-      
+
       for elm in npd
 	elm[1] = elm[1] * other
 	if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
@@ -81,7 +82,7 @@
 	end
 	elm[1] = elm[1].to_i
       end
-      
+
       for elm in dpd
 	elm[1] = elm[1] * other
 	if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
@@ -89,12 +90,12 @@
 	end
 	elm[1] = elm[1].to_i
       end
-      
+
       num = Integer.from_prime_division(npd)
       den = Integer.from_prime_division(dpd)
-      
+
       Rational(num,den)
-      
+
     elsif other.kind_of?(Integer)
       if other > 0
 	num = numerator ** other
@@ -129,7 +130,7 @@
 #      if !(x.kind_of?(Rational) and y.kind_of?(Rational))
 #	return a**Rational(1,2)
 #      end
-      if a.imag >= 0 
+      if a.imag >= 0
 	Complex(x, y)
       else
 	Complex(x, -y)
@@ -142,7 +143,7 @@
       Complex(0,rsqrt(-a))
     end
   end
-  
+
   def rsqrt(a)
     if a.kind_of?(Float)
       sqrt!(a)
@@ -156,7 +157,7 @@
       while (src >= max) and (src >>= 32)
 	byte_a.unshift src & 0xffffffff
       end
-      
+
       answer = 0
       main = 0
       side = 0
@@ -166,13 +167,13 @@
 	if answer != 0
 	  if main * 4  < side * side
 	    applo = main.div(side)
-	  else 
+	  else
 	    applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1
 	  end
 	else
 	  applo = sqrt!(main).to_i + 1
 	end
-	
+
 	while (x = (side + applo) * applo) > main
 	  applo -= 1
 	end
@@ -188,6 +189,9 @@
     end
   end
 
+  class << self
+    remove_method(:sqrt)
+  end
   module_function :sqrt
   module_function :rsqrt
 end

Modified: MacRuby/trunk/lib/matrix.rb
===================================================================
--- MacRuby/trunk/lib/matrix.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/matrix.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,22 +1,15 @@
-#!/usr/local/bin/ruby
-#--
-#   matrix.rb - 
-#   	$Release Version: 1.0$
-#   	$Revision: 1.13 $
-#       Original Version from Smalltalk-80 version
-#          on July 23, 1985 at 8:37:17 am
-#       by Keiju ISHITSUKA
-#++
+# encoding: utf-8
 #
 # = matrix.rb
 #
 # An implementation of Matrix and Vector classes.
 #
-# Author:: Keiju ISHITSUKA
-# Documentation:: Gavin Sinclair (sourced from <i>Ruby in a Nutshell</i> (Matsumoto, O'Reilly)) 
+# See classes Matrix and Vector for documentation.
 #
-# See classes Matrix and Vector for documentation. 
-#
+# Current Maintainer:: Marc-André Lafortune
+# Original Author:: Keiju ISHITSUKA
+# Original Documentation:: Gavin Sinclair (sourced from <i>Ruby in a Nutshell</i> (Matsumoto, O'Reilly))
+##
 
 require "e2mmap.rb"
 
@@ -24,24 +17,18 @@
   extend Exception2MessageMapper
   def_e2message(TypeError, "wrong argument type %s (expected %s)")
   def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")
-  
+
   def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
   def_exception("ErrNotRegular", "Not Regular Matrix")
-  def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined")
+  def_exception("ErrOperationNotDefined", "Operation(%s) can\\'t be defined: %s op %s")
+  def_exception("ErrOperationNotImplemented", "Sorry, Operation(%s) not implemented: %s op %s")
 end
 
 #
-# The +Matrix+ class represents a mathematical matrix, and provides methods for creating
-# special-case matrices (zero, identity, diagonal, singular, vector), operating on them
-# arithmetically and algebraically, and determining their mathematical properties (trace, rank,
-# inverse, determinant).
+# The +Matrix+ class represents a mathematical matrix. It provides methods for creating
+# matrices, operating on them arithmetically and algebraically,
+# and determining their mathematical properties (trace, rank, inverse, determinant).
 #
-# Note that although matrices should theoretically be rectangular, this is not
-# enforced by the class.
-#
-# Also note that the determinant of integer matrices may be incorrectly calculated unless you
-# also <tt>require 'mathn'</tt>.  This may be fixed in the future.
-#
 # == Method Catalogue
 #
 # To create a matrix:
@@ -49,9 +36,9 @@
 # * <tt> Matrix.[](*rows)               </tt>
 # * <tt> Matrix.rows(rows, copy = true) </tt>
 # * <tt> Matrix.columns(columns)        </tt>
+# * <tt> Matrix.build(row_size, column_size, &block) </tt>
 # * <tt> Matrix.diagonal(*values)       </tt>
 # * <tt> Matrix.scalar(n, value)        </tt>
-# * <tt> Matrix.scalar(n, value)        </tt>
 # * <tt> Matrix.identity(n)             </tt>
 # * <tt> Matrix.unit(n)                 </tt>
 # * <tt> Matrix.I(n)                    </tt>
@@ -59,7 +46,7 @@
 # * <tt> Matrix.row_vector(row)         </tt>
 # * <tt> Matrix.column_vector(column)   </tt>
 #
-# To access Matrix elements/columns/rows/submatrices/properties: 
+# To access Matrix elements/columns/rows/submatrices/properties:
 # * <tt>  [](i, j)                      </tt>
 # * <tt> #row_size                      </tt>
 # * <tt> #column_size                   </tt>
@@ -67,9 +54,13 @@
 # * <tt> #column(j)                     </tt>
 # * <tt> #collect                       </tt>
 # * <tt> #map                           </tt>
+# * <tt> #each                          </tt>
+# * <tt> #each_with_index               </tt>
 # * <tt> #minor(*param)                 </tt>
 #
 # Properties of a matrix:
+# * <tt> #empty?                        </tt>
+# * <tt> #real?                         </tt>
 # * <tt> #regular?                      </tt>
 # * <tt> #singular?                     </tt>
 # * <tt> #square?                       </tt>
@@ -92,6 +83,15 @@
 # * <tt> #transpose                     </tt>
 # * <tt> #t                             </tt>
 #
+# Complex arithmetic:
+# * <tt> conj                           </tt>
+# * <tt> conjugate                      </tt>
+# * <tt> imag                           </tt>
+# * <tt> imaginary                      </tt>
+# * <tt> real                           </tt>
+# * <tt> rect                           </tt>
+# * <tt> rectangular                    </tt>
+#
 # Conversion to other data types:
 # * <tt> #coerce(other)                 </tt>
 # * <tt> #row_vectors                   </tt>
@@ -103,14 +103,14 @@
 # * <tt> #inspect                       </tt>
 #
 class Matrix
-  @RCS_ID='-$Id: matrix.rb,v 1.13 2001/12/09 14:22:23 keiju Exp keiju $-'
-  
-#  extend Exception2MessageMapper
+  include Enumerable
   include ExceptionForMatrix
-  
+
   # instance creations
   private_class_method :new
-  
+  attr_reader :rows
+  protected :rows
+
   #
   # Creates a matrix where each argument is a row.
   #   Matrix[ [25, 93], [-1, 66] ]
@@ -118,37 +118,64 @@
   #          -1 66
   #
   def Matrix.[](*rows)
-    new(:init_rows, rows, false)
+    Matrix.rows(rows, false)
   end
-  
+
   #
   # Creates a matrix where +rows+ is an array of arrays, each of which is a row
-  # to the matrix.  If the optional argument +copy+ is false, use the given
+  # of the matrix.  If the optional argument +copy+ is false, use the given
   # arrays as the internal structure of the matrix without copying.
   #   Matrix.rows([[25, 93], [-1, 66]])
   #      =>  25 93
   #          -1 66
+  #
   def Matrix.rows(rows, copy = true)
-    new(:init_rows, rows, copy)
+    rows = convert_to_array(rows)
+    rows.map! do |row|
+      convert_to_array(row, copy)
+    end
+    size = (rows[0] || []).size
+    rows.each do |row|
+      Matrix.Raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size
+    end
+    new rows, size
   end
-  
+
   #
   # Creates a matrix using +columns+ as an array of column vectors.
   #   Matrix.columns([[25, 93], [-1, 66]])
   #      =>  25 -1
   #          93 66
   #
-  #
   def Matrix.columns(columns)
-    rows = (0 .. columns[0].size - 1).collect {|i|
-      (0 .. columns.size - 1).collect {|j|
-        columns[j][i]
-      }
-    }
-    Matrix.rows(rows, false)
+    Matrix.rows(columns, false).transpose
   end
-  
+
   #
+  # Creates a matrix of size +row_size+ x +column_size+.
+  # It fills the values by calling the given block,
+  # passing the current row and column.
+  # Returns an enumerator if no block is given.
+  #
+  #   m = Matrix.build(2, 4) {|row, col| col - row }
+  #     => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
+  #   m = Matrix.build(3) { rand }
+  #     => a 3x3 matrix with random elements
+  #
+  def Matrix.build(row_size, column_size = row_size)
+    row_size = CoercionHelper.coerce_to_int(row_size)
+    column_size = CoercionHelper.coerce_to_int(column_size)
+    raise ArgumentError if row_size < 0 || column_size < 0
+    return to_enum :build, row_size, column_size unless block_given?
+    rows = row_size.times.map do |i|
+      column_size.times.map do |j|
+        yield i, j
+      end
+    end
+    new rows, column_size
+  end
+
+  #
   # Creates a matrix where the diagonal elements are composed of +values+.
   #   Matrix.diagonal(9, 5, -3)
   #     =>  9  0  0
@@ -157,14 +184,14 @@
   #
   def Matrix.diagonal(*values)
     size = values.size
-    rows = (0 .. size  - 1).collect {|j|
-      row = Array.new(size).fill(0, 0, size)
+    rows = (0 ... size).collect {|j|
+      row = Array.new(size, 0)
       row[j] = values[j]
       row
     }
-    rows(rows, false)
+    new rows
   end
-  
+
   #
   # Creates an +n+ by +n+ diagonal matrix where each diagonal element is
   # +value+.
@@ -173,7 +200,7 @@
   #        0 5
   #
   def Matrix.scalar(n, value)
-    Matrix.diagonal(*Array.new(n).fill(value, 0, n))
+    Matrix.diagonal(*Array.new(n, value))
   end
 
   #
@@ -185,11 +212,11 @@
   def Matrix.identity(n)
     Matrix.scalar(n, 1)
   end
-  class << Matrix 
+  class << Matrix
     alias unit identity
     alias I identity
   end
-  
+
   #
   # Creates an +n+ by +n+ zero matrix.
   #   Matrix.zero(2)
@@ -199,7 +226,7 @@
   def Matrix.zero(n)
     Matrix.scalar(n, 0)
   end
-  
+
   #
   # Creates a single-row matrix where the values of that row are as given in
   # +row+.
@@ -207,16 +234,10 @@
   #     => 4 5 6
   #
   def Matrix.row_vector(row)
-    case row
-    when Vector
-      Matrix.rows([row.to_a], false)
-    when Array
-      Matrix.rows([row.dup], false)
-    else
-      Matrix.rows([[row]], false)
-    end
+    row = convert_to_array(row)
+    new [row]
   end
-  
+
   #
   # Creates a single-column matrix where the values of that column are as given
   # in +column+.
@@ -226,39 +247,51 @@
   #        6
   #
   def Matrix.column_vector(column)
-    case column
-    when Vector
-      Matrix.columns([column.to_a])
-    when Array
-      Matrix.columns([column])
-    else
-      Matrix.columns([[column]])
-    end
+    column = convert_to_array(column)
+    new [column].transpose, 1
   end
 
   #
-  # This method is used by the other methods that create matrices, and is of no
-  # use to general users.
+  # Creates a empty matrix of +row_size+ x +column_size+.
+  # At least one of +row_size+ or +column_size+ must be 0.
   #
-  def initialize(init_method, *argv)
-    self.send(init_method, *argv)
+  #   m = Matrix.empty(2, 0)
+  #   m == Matrix[ [], [] ]
+  #     => true
+  #   n = Matrix.empty(0, 3)
+  #   n == Matrix.columns([ [], [], [] ])
+  #     => true
+  #   m * n
+  #     => Matrix[[0, 0, 0], [0, 0, 0]]
+  #
+  def Matrix.empty(row_size = 0, column_size = 0)
+    Matrix.Raise ArgumentError, "One size must be 0" if column_size != 0 && row_size != 0
+    Matrix.Raise ArgumentError, "Negative size" if column_size < 0 || row_size < 0
+
+    new([[]]*row_size, column_size)
   end
-  
-  def init_rows(rows, copy)
-    if copy
-      @rows = rows.collect{|row| row.dup}
-    else
-      @rows = rows
-    end
-    self
+
+  #
+  # Matrix.new is private; use Matrix.rows, columns, [], etc... to create.
+  #
+  def initialize(rows, column_size = rows[0].size)
+    # No checking is done at this point. rows must be an Array of Arrays.
+    # column_size must be the size of the first row, if there is one,
+    # otherwise it *must* be specified and can be any integer >= 0
+    @rows = rows
+    @column_size = column_size
   end
-  private :init_rows
-  
+
+  def new_matrix(rows, column_size = rows[0].size) # :nodoc:
+    Matrix.send(:new, rows, column_size) # bypass privacy of Matrix.new
+  end
+  private :new_matrix
+
   #
   # Returns element (+i+,+j+) of the matrix.  That is: row +i+, column +j+.
   #
   def [](i, j)
-    @rows[i][j]
+    @rows.fetch(i){return nil}[j]
   end
   alias element []
   alias component []
@@ -276,28 +309,22 @@
   def row_size
     @rows.size
   end
-  
+
   #
-  # Returns the number of columns.  Note that it is possible to construct a
-  # matrix with uneven columns (e.g. Matrix[ [1,2,3], [4,5] ]), but this is
-  # mathematically unsound.  This method uses the first row to determine the
-  # result.
+  # Returns the number of columns.
   #
-  def column_size
-    @rows[0].size
-  end
+  attr_reader :column_size
 
   #
   # Returns row vector number +i+ of the matrix as a Vector (starting at 0 like
   # an array).  When a block is given, the elements of that vector are iterated.
   #
-  def row(i) # :yield: e
+  def row(i, &block) # :yield: e
     if block_given?
-      for e in @rows[i]
-        yield e
-      end
+      @rows.fetch(i){return self}.each(&block)
+      self
     else
-      Vector.elements(@rows[i])
+      Vector.elements(@rows.fetch(i){return nil})
     end
   end
 
@@ -308,17 +335,20 @@
   #
   def column(j) # :yield: e
     if block_given?
-      0.upto(row_size - 1) do |i|
+      return self if j >= column_size || j < -column_size
+      row_size.times do |i|
         yield @rows[i][j]
       end
+      self
     else
-      col = (0 .. row_size - 1).collect {|i|
+      return nil if j >= column_size || j < -column_size
+      col = (0 ... row_size).collect {|i|
         @rows[i][j]
       }
       Vector.elements(col, false)
     end
   end
-  
+
   #
   # Returns a matrix that is the result of iteration of the given block over all
   # elements of the matrix.
@@ -326,71 +356,135 @@
   #     => 1  4
   #        9 16
   #
-  def collect # :yield: e
-    rows = @rows.collect{|row| row.collect{|e| yield e}}
-    Matrix.rows(rows, false)
+  def collect(&block) # :yield: e
+    return to_enum(:collect) unless block_given?
+    rows = @rows.collect{|row| row.collect(&block)}
+    new_matrix rows, column_size
   end
   alias map collect
-  
+
   #
+  # Yields all elements of the matrix, starting with those of the first row,
+  # or returns an Enumerator is no block given
+  #   Matrix[ [1,2], [3,4] ].each { |e| puts e }
+  #     # => prints the numbers 1 to 4
+  #
+  def each(&block) # :yield: e
+    return to_enum(:each) unless block_given?
+    @rows.each do |row|
+      row.each(&block)
+    end
+    self
+  end
+
+  #
+  # Yields all elements of the matrix, starting with those of the first row,
+  # along with the row index and column index,
+  # or returns an Enumerator is no block given
+  #   Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col|
+  #     puts "#{e} at #{row}, #{col}"
+  #   end
+  #     # => 1 at 0, 0
+  #     # => 2 at 0, 1
+  #     # => 3 at 1, 0
+  #     # => 4 at 1, 1
+  #
+  def each_with_index(&block) # :yield: e, row, column
+    return to_enum(:each_with_index) unless block_given?
+    @rows.each_with_index do |row, row_index|
+      row.each_with_index do |e, col_index|
+        yield e, row_index, col_index
+      end
+    end
+    self
+  end
+
+  #
   # Returns a section of the matrix.  The parameters are either:
   # *  start_row, nrows, start_col, ncols; OR
-  # *  col_range, row_range
+  # *  row_range, col_range
   #
   #   Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
   #     => 9 0 0
   #        0 5 0
   #
+  # Like Array#[], negative indices count backward from the end of the
+  # row or column (-1 is the last element). Returns nil if the starting
+  # row or column is greater than row_size or column_size respectively.
+  #
   def minor(*param)
     case param.size
     when 2
-      from_row = param[0].first
-      size_row = param[0].end - from_row
-      size_row += 1 unless param[0].exclude_end?
-      from_col = param[1].first
-      size_col = param[1].end - from_col
-      size_col += 1 unless param[1].exclude_end?
+      row_range, col_range = param
+      from_row = row_range.first
+      from_row += row_size if from_row < 0
+      to_row = row_range.end
+      to_row += row_size if to_row < 0
+      to_row += 1 unless row_range.exclude_end?
+      size_row = to_row - from_row
+
+      from_col = col_range.first
+      from_col += column_size if from_col < 0
+      to_col = col_range.end
+      to_col += column_size if to_col < 0
+      to_col += 1 unless col_range.exclude_end?
+      size_col = to_col - from_col
     when 4
-      from_row = param[0]
-      size_row = param[1]
-      from_col = param[2]
-      size_col = param[3]
+      from_row, size_row, from_col, size_col = param
+      return nil if size_row < 0 || size_col < 0
+      from_row += row_size if from_row < 0
+      from_col += column_size if from_col < 0
     else
       Matrix.Raise ArgumentError, param.inspect
     end
-    
+
+    return nil if from_row > row_size || from_col > column_size || from_row < 0 || from_col < 0
     rows = @rows[from_row, size_row].collect{|row|
       row[from_col, size_col]
     }
-    Matrix.rows(rows, false)
+    new_matrix rows, column_size - from_col
   end
- 
+
   #--
   # TESTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
 
   #
-  # Returns +true+ if this is a regular matrix.
+  # Returns +true+ if this is an empty matrix, i.e. if the number of rows
+  # or the number of columns is 0.
   #
+  def empty?
+    column_size == 0 || row_size == 0
+  end
+
+  #
+  # Returns +true+ if all entries of the matrix are real.
+  #
+  def real?
+    all?(&:real?)
+  end
+
+  #
+  # Returns +true+ if this is a regular (i.e. non-singular) matrix.
+  #
   def regular?
-    square? and rank == column_size
+    not singular?
   end
-  
+
   #
-  # Returns +true+ is this is a singular (i.e. non-regular) matrix.
+  # Returns +true+ is this is a singular matrix.
   #
   def singular?
-    not regular?
+    determinant == 0
   end
 
   #
-  # Returns +true+ is this is a square matrix.  See note in column_size about this
-  # being unreliable, though.
+  # Returns +true+ is this is a square matrix.
   #
   def square?
     column_size == row_size
   end
-  
+
   #--
   # OBJECT METHODS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
@@ -400,52 +494,34 @@
   #
   def ==(other)
     return false unless Matrix === other
-    
-    other.compare_by_row_vectors(@rows)
+    rows == other.rows
   end
+
   def eql?(other)
     return false unless Matrix === other
-    
-    other.compare_by_row_vectors(@rows, :eql?)
+    rows.eql? other.rows
   end
-  
+
   #
-  # Not really intended for general consumption.
-  #
-  def compare_by_row_vectors(rows, comparison = :==)
-    return false unless @rows.size == rows.size
-    
-    0.upto(@rows.size - 1) do |i|
-      return false unless @rows[i].send(comparison, rows[i])
-    end
-    true
-  end
-  
-  #
   # Returns a clone of the matrix, so that the contents of each do not reference
   # identical objects.
+  # There should be no good reason to do this since Matrices are immutable.
   #
   def clone
-    Matrix.rows(@rows)
+    new_matrix @rows.map(&:dup), column_size
   end
-  
+
   #
   # Returns a hash-code for the matrix.
   #
   def hash
-    value = 0
-    for row in @rows
-      for e in row
-        value ^= e.hash
-      end
-    end
-    return value
+    @rows.hash
   end
-  
+
   #--
   # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
   # Matrix multiplication.
   #   Matrix[[2,4], [6,8]] * Matrix.identity(2)
@@ -460,30 +536,27 @@
           e * m
         }
       }
-      return Matrix.rows(rows, false)
+      return new_matrix rows, column_size
     when Vector
       m = Matrix.column_vector(m)
       r = self * m
       return r.column(0)
     when Matrix
       Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
-    
-      rows = (0 .. row_size - 1).collect {|i|
-        (0 .. m.column_size - 1).collect {|j|
-          vij = 0
-          0.upto(column_size - 1) do |k|
-            vij += self[i, k] * m[k, j]
+
+      rows = (0 ... row_size).collect {|i|
+        (0 ... m.column_size).collect {|j|
+          (0 ... column_size).inject(0) do |vij, k|
+            vij + self[i, k] * m[k, j]
           end
-          vij
         }
       }
-      return Matrix.rows(rows, false)
+      return new_matrix rows, m.column_size
     else
-      x, y = m.coerce(self)
-      return x * y
+      return apply_through_coercion(m, __method__)
     end
   end
-  
+
   #
   # Matrix addition.
   #   Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
@@ -493,23 +566,22 @@
   def +(m)
     case m
     when Numeric
-      Matrix.Raise ErrOperationNotDefined, "+"
+      Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class
     when Vector
       m = Matrix.column_vector(m)
     when Matrix
     else
-      x, y = m.coerce(self)
-      return x + y
+      return apply_through_coercion(m, __method__)
     end
-    
+
     Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
-    
-    rows = (0 .. row_size - 1).collect {|i|
-      (0 .. column_size - 1).collect {|j|
+
+    rows = (0 ... row_size).collect {|i|
+      (0 ... column_size).collect {|j|
         self[i, j] + m[i, j]
       }
     }
-    Matrix.rows(rows, false)
+    new_matrix rows, column_size
   end
 
   #
@@ -521,25 +593,24 @@
   def -(m)
     case m
     when Numeric
-      Matrix.Raise ErrOperationNotDefined, "-"
+      Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class
     when Vector
       m = Matrix.column_vector(m)
     when Matrix
     else
-      x, y = m.coerce(self)
-      return x - y
+      return apply_through_coercion(m, __method__)
     end
-    
+
     Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
-    
-    rows = (0 .. row_size - 1).collect {|i|
-      (0 .. column_size - 1).collect {|j|
+
+    rows = (0 ... row_size).collect {|i|
+      (0 ... column_size).collect {|j|
         self[i, j] - m[i, j]
       }
     }
-    Matrix.rows(rows, false)
+    new_matrix rows, column_size
   end
-  
+
   #
   # Matrix division (multiplication by the inverse).
   #   Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
@@ -554,38 +625,34 @@
           e / other
         }
       }
-      return Matrix.rows(rows, false)
+      return new_matrix rows, column_size
     when Matrix
       return self * other.inverse
     else
-      x, y = other.coerce(self)
-      rerurn x / y
+      return apply_through_coercion(other, __method__)
     end
   end
 
   #
   # Returns the inverse of the matrix.
-  #   Matrix[[1, 2], [2, 1]].inverse
+  #   Matrix[[-1, -1], [0, -1]].inverse
   #     => -1  1
   #         0 -1
   #
   def inverse
     Matrix.Raise ErrDimensionMismatch unless square?
-    Matrix.I(row_size).inverse_from(self)
+    Matrix.I(row_size).send(:inverse_from, self)
   end
   alias inv inverse
 
-  #
-  # Not for public consumption?
-  #
-  def inverse_from(src)
-    size = row_size - 1
+  def inverse_from(src) # :nodoc:
+    last = row_size - 1
     a = src.to_a
-    
-    for k in 0..size
+
+    0.upto(last) do |k|
       i = k
       akk = a[k][k].abs
-      ((k+1)..size).each do |j|
+      (k+1).upto(last) do |j|
         v = a[j][k].abs
         if v > akk
           i = j
@@ -598,258 +665,206 @@
         @rows[i], @rows[k] = @rows[k], @rows[i]
       end
       akk = a[k][k]
-      
-      for i in 0 .. size
-        next if i == k
-        q = a[i][k].quo(akk)
-        a[i][k] = 0
-        
-	for j in (k + 1).. size
-          a[i][j] -= a[k][j] * q
+
+      0.upto(last) do |ii|
+        next if ii == k
+        q = a[ii][k].quo(akk)
+        a[ii][k] = 0
+
+        (k + 1).upto(last) do |j|
+          a[ii][j] -= a[k][j] * q
         end
-        for j in 0..size
-          @rows[i][j] -= @rows[k][j] * q
+        0.upto(last) do |j|
+          @rows[ii][j] -= @rows[k][j] * q
         end
       end
-      
-      for j in (k + 1).. size
+
+      (k+1).upto(last) do |j|
         a[k][j] = a[k][j].quo(akk)
       end
-      for j in 0..size
+      0.upto(last) do |j|
         @rows[k][j] = @rows[k][j].quo(akk)
       end
     end
     self
   end
-  #alias reciprocal inverse
-  
+  private :inverse_from
+
   #
-  # Matrix exponentiation.  Defined for integer powers only.  Equivalent to
-  # multiplying the matrix by itself N times.
+  # Matrix exponentiation.  Currently implemented for integer powers only.
+  # Equivalent to multiplying the matrix by itself N times.
   #   Matrix[[7,6], [3,9]] ** 2
   #     => 67 96
   #        48 99
   #
   def ** (other)
-    if other.kind_of?(Integer)
+    case other
+    when Integer
       x = self
       if other <= 0
         x = self.inverse
         return Matrix.identity(self.column_size) if other == 0
         other = -other
       end
-      z = x
-      n = other  - 1
-      while n != 0
-        while (div, mod = n.divmod(2)
-               mod == 0)
-          x = x * x
-          n = div
-        end
-        z *= x
-        n -= 1
+      z = nil
+      loop do
+        z = z ? z * x : x if other[0] == 1
+        return z if (other >>= 1).zero?
+        x *= x
       end
-      z
-    elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational)
-      Matrix.Raise ErrOperationNotDefined, "**"
+    when Float, Rational
+      Matrix.Raise ErrOperationNotImplemented, "**", self.class, other.class
     else
-      Matrix.Raise ErrOperationNotDefined, "**"
+      Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class
     end
   end
-  
+
   #--
   # MATRIX FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
-  # Returns the determinant of the matrix.  If the matrix is not square, the
-  # result is 0. This method's algorism is Gaussian elimination method
-  # and using Numeric#quo(). Beware that using Float values, with their
-  # usual lack of precision, can affect the value returned by this method.  Use
-  # Rational values or Matrix#det_e instead if this is important to you.
+  # Returns the determinant of the matrix.
   #
+  # Beware that using Float values can yield erroneous results
+  # because of their lack of precision.
+  # Consider using exact types like Rational or BigDecimal instead.
+  #
   #   Matrix[[7,6], [3,9]].determinant
-  #     => 63.0
+  #     => 45
   #
   def determinant
-    return 0 unless square?
-    
-    size = row_size - 1
-    a = to_a
-    
-    det = 1
-    k = 0
-    loop do
-      if (akk = a[k][k]) == 0
-        i = k
-        loop do
-          return 0 if (ii += 1) > size
-          break unless a[i][k] == 0
-        end
-        a[i], a[k] = a[k], a[i]
-        akk = a[k][k]
-        det *= -1
-      end
-
-      for i in k + 1 .. size
-        q = a[i][k].quo(akk)
-        (k + 1).upto(size) do |j|
-          a[i][j] -= a[k][j] * q
-        end
-      end
-      det *= akk
-      break unless (k += 1) <= size
+    Matrix.Raise ErrDimensionMismatch unless square?
+    m = @rows
+    case row_size
+      # Up to 4x4, give result using Laplacian expansion by minors.
+      # This will typically be faster, as well as giving good results
+      # in case of Floats
+    when 0
+      +1
+    when 1
+      + m[0][0]
+    when 2
+      + m[0][0] * m[1][1] - m[0][1] * m[1][0]
+    when 3
+      m0 = m[0]; m1 = m[1]; m2 = m[2]
+      + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \
+      - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \
+      + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0]
+    when 4
+      m0 = m[0]; m1 = m[1]; m2 = m[2]; m3 = m[3]
+      + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \
+      - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \
+      + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \
+      - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \
+      + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \
+      - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \
+      + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \
+      - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \
+      + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \
+      - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \
+      + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \
+      - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0]
+    else
+      # For bigger matrices, use an efficient and general algorithm.
+      # Currently, we use the Gauss-Bareiss algorithm
+      determinant_bareiss
     end
-    det
   end
-  alias det determinant
+  alias_method :det, :determinant
 
   #
-  # Returns the determinant of the matrix.  If the matrix is not square, the
-  # result is 0. This method's algorism is Gaussian elimination method. 
-  # This method uses Euclidean algorism. If all elements are integer,
-  # really exact value. But, if an element is a float, can't return
-  # exact value.   
+  # Private. Use Matrix#determinant
   #
-  #   Matrix[[7,6], [3,9]].determinant
-  #     => 63
+  # Returns the determinant of the matrix, using
+  # Bareiss' multistep integer-preserving gaussian elimination.
+  # It has the same computational cost order O(n^3) as standard Gaussian elimination.
+  # Intermediate results are fraction free and of lower complexity.
+  # A matrix of Integers will have thus intermediate results that are also Integers,
+  # with smaller bignums (if any), while a matrix of Float will usually have
+  # intermediate results with better precision.
   #
-  def determinant_e
-    return 0 unless square?
-    
-    size = row_size - 1
+  def determinant_bareiss
+    size = row_size
+    last = size - 1
     a = to_a
-    
-    det = 1
-    k = 0
-    loop do
-      if a[k][k].zero?
-        i = k
-        loop do
-          return 0 if (i += 1) > size
-          break unless a[i][k].zero?
-        end
-        a[i], a[k] = a[k], a[i]
-        det *= -1
+    no_pivot = Proc.new{ return 0 }
+    sign = +1
+    pivot = 1
+    size.times do |k|
+      previous_pivot = pivot
+      if (pivot = a[k][k]) == 0
+        switch = (k+1 ... size).find(no_pivot) {|row|
+          a[row][k] != 0
+        }
+        a[switch], a[k] = a[k], a[switch]
+        pivot = a[k][k]
+        sign = -sign
       end
-
-      for i in (k + 1)..size
-        q = a[i][k].quo(a[k][k])
-        k.upto(size) do |j|
-          a[i][j] -= a[k][j] * q
+      (k+1).upto(last) do |i|
+        ai = a[i]
+        (k+1).upto(last) do |j|
+          ai[j] =  (pivot * ai[j] - ai[k] * a[k][j]) / previous_pivot
         end
-        unless a[i][k].zero?
-          a[i], a[k] = a[k], a[i]
-          det *= -1
-          redo
-        end
       end
-      det *= a[k][k]
-      break unless (k += 1) <= size
     end
-    det
+    sign * pivot
   end
+  private :determinant_bareiss
+
+  #
+  # deprecated; use Matrix#determinant
+  #
+  def determinant_e
+    warn "#{caller(1)[0]}: warning: Matrix#determinant_e is deprecated; use #determinant"
+    rank
+  end
   alias det_e determinant_e
 
   #
-  # Returns the rank of the matrix. Beware that using Float values,
-  # probably return faild value. Use Rational values or Matrix#rank_e
-  # for getting exact result.
+  # Returns the rank of the matrix.
+  # Beware that using Float values can yield erroneous results
+  # because of their lack of precision.
+  # Consider using exact types like Rational or BigDecimal instead.
   #
   #   Matrix[[7,6], [3,9]].rank
   #     => 2
   #
   def rank
-    if column_size > row_size
-      a = transpose.to_a
-      a_column_size = row_size
-      a_row_size = column_size
-    else
-      a = to_a
-      a_column_size = column_size
-      a_row_size = row_size
-    end
+    # We currently use Bareiss' multistep integer-preserving gaussian elimination
+    # (see comments on determinant)
+    a = to_a
+    last_column = column_size - 1
+    last_row = row_size - 1
     rank = 0
-    k = 0
-    loop do
-      if (akk = a[k][k]) == 0
-        i = k
-        exists = true
-        loop do
-          if (i += 1) > a_column_size - 1
-            exists = false
-            break
-          end
-          break unless a[i][k] == 0
-        end
-        if exists
-          a[i], a[k] = a[k], a[i]
-          akk = a[k][k]
-        else
-          i = k
-          exists = true
-          loop do
-            if (i += 1) > a_row_size - 1
-              exists = false
-              break
-            end
-            break unless a[k][i] == 0
-          end
-          if exists
-            k.upto(a_column_size - 1) do |j|
-              a[j][k], a[j][i] = a[j][i], a[j][k]
-            end
-            akk = a[k][k]
-          else
-            next
-          end
-        end
+    pivot_row = 0
+    previous_pivot = 1
+    0.upto(last_column) do |k|
+      switch_row = (pivot_row .. last_row).find {|row|
+        a[row][k] != 0
+      }
+      if switch_row
+        a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row
+        pivot = a[pivot_row][k]
+        (pivot_row+1).upto(last_row) do |i|
+           ai = a[i]
+           (k+1).upto(last_column) do |j|
+             ai[j] =  (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot
+           end
+         end
+        pivot_row += 1
+        previous_pivot = pivot
       end
-
-      for i in (k + 1)..(a_row_size - 1)
-        q = a[i][k].quo(akk)
-	for j in (k + 1)..(a_column_size - 1)
-          a[i][j] -= a[k][j] * q
-        end
-      end
-      rank += 1
-      break unless (k += 1) <= a_column_size - 1
     end
-    return rank
+    pivot_row
   end
 
   #
-  # Returns the rank of the matrix. This method uses Euclidean
-  # algorism. If all elements are integer, really exact value. But, if
-  # an element is a float, can't return exact value.  
+  # deprecated; use Matrix#rank
   #
-  #   Matrix[[7,6], [3,9]].rank
-  #     => 2
-  #
   def rank_e
-    a = to_a
-    a_column_size = column_size
-    a_row_size = row_size
-    pi = 0
-    (0 ... a_column_size).each do |j|
-      if i = (pi ... a_row_size).find{|i0| !a[i0][j].zero?}
-        if i != pi
-          a[pi], a[i] = a[i], a[pi]
-        end
-        (pi + 1 ... a_row_size).each do |k|
-          q = a[k][j].quo(a[pi][j])
-          (pi ... a_column_size).each do |j0|
-            a[k][j0] -= q * a[pi][j0]
-          end
-          if k > pi && !a[k][j].zero?
-            a[k], a[pi] = a[pi], a[k]
-            redo
-          end
-        end
-        pi += 1
-      end
-    end
-    pi
+    warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank"
+    rank
   end
 
 
@@ -859,14 +874,13 @@
   #     => 16
   #
   def trace
-    tr = 0
-    0.upto(column_size - 1) do |i|
-      tr += @rows[i][i]
+    Matrix.Raise ErrDimensionMismatch unless square?
+    (0...column_size).inject(0) do |tr, i|
+      tr + @rows[i][i]
     end
-    tr
   end
   alias tr trace
-  
+
   #
   # Returns the transpose of the matrix.
   #   Matrix[[1,2], [3,4], [5,6]]
@@ -878,16 +892,77 @@
   #        2 4 6
   #
   def transpose
-    Matrix.columns(@rows)
+    return Matrix.empty(column_size, 0) if row_size.zero?
+    new_matrix @rows.transpose, row_size
   end
   alias t transpose
-  
+
   #--
+  # COMPLEX ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+  #++
+
+  #
+  # Returns the conjugate of the matrix.
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
+  #     => 1+2i   i  0
+  #           1   2  3
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate
+  #     => 1-2i  -i  0
+  #           1   2  3
+  #
+  def conjugate
+    collect(&:conjugate)
+  end
+  alias conj conjugate
+
+  #
+  # Returns the imaginary part of the matrix.
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
+  #     => 1+2i  i  0
+  #           1  2  3
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary
+  #     =>   2i  i  0
+  #           0  0  0
+  #
+  def imaginary
+    collect(&:imaginary)
+  end
+  alias imag imaginary
+
+  #
+  # Returns the real part of the matrix.
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
+  #     => 1+2i  i  0
+  #           1  2  3
+  #   Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real
+  #     =>    1  0  0
+  #           1  2  3
+  #
+  def real
+    collect(&:real)
+  end
+
+  #
+  # Returns an array containing matrices corresponding to the real and imaginary
+  # parts of the matrix
+  #
+  # m.rect == [m.real, m.imag]  # ==> true for all matrices m
+  #
+  def rect
+    [real, imag]
+  end
+  alias rectangular rect
+
+  #--
   # CONVERTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
-  # FIXME: describe #coerce.
+  # The coerce method provides support for Ruby type coercion.
+  # This coercion mechanism is used by Ruby to handle mixed-type
+  # numeric operations: it is intended to find a compatible common
+  # type between the two operands of the operator.
+  # See also Numeric#coerce.
   #
   def coerce(other)
     case other
@@ -902,99 +977,171 @@
   # Returns an array of the row vectors of the matrix.  See Vector.
   #
   def row_vectors
-    rows = (0 .. row_size - 1).collect {|i|
+    (0 ... row_size).collect {|i|
       row(i)
     }
-    rows
   end
-  
+
   #
   # Returns an array of the column vectors of the matrix.  See Vector.
   #
   def column_vectors
-    columns = (0 .. column_size - 1).collect {|i|
+    (0 ... column_size).collect {|i|
       column(i)
     }
-    columns
   end
-  
+
   #
   # Returns an array of arrays that describe the rows of the matrix.
   #
   def to_a
-    @rows.collect{|row| row.collect{|e| e}}
+    @rows.collect{|row| row.dup}
   end
-  
+
   def elements_to_f
-    collect{|e| e.to_f}
+    warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)"
+    map(&:to_f)
   end
-  
+
   def elements_to_i
-    collect{|e| e.to_i}
+    warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)"
+    map(&:to_i)
   end
-  
+
   def elements_to_r
-    collect{|e| e.to_r}
+    warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)"
+    map(&:to_r)
   end
-  
+
   #--
   # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
   # Overrides Object#to_s
   #
   def to_s
-    "Matrix[" + @rows.collect{|row|
-      "[" + row.collect{|e| e.to_s}.join(", ") + "]"
-    }.join(", ")+"]"
+    if empty?
+      "Matrix.empty(#{row_size}, #{column_size})"
+    else
+      "Matrix[" + @rows.collect{|row|
+        "[" + row.collect{|e| e.to_s}.join(", ") + "]"
+      }.join(", ")+"]"
+    end
   end
-  
+
   #
   # Overrides Object#inspect
   #
   def inspect
-    "Matrix"+ at rows.inspect
+    if empty?
+      "Matrix.empty(#{row_size}, #{column_size})"
+    else
+      "Matrix#{@rows.inspect}"
+    end
   end
-  
+
+  # Private helper modules
+
+  module ConversionHelper # :nodoc:
+    #
+    # Converts the obj to an Array. If copy is set to true
+    # a copy of obj will be made if necessary.
+    #
+    def convert_to_array(obj, copy = false) # :nodoc:
+      case obj
+      when Array
+        copy ? obj.dup : obj
+      when Vector
+        obj.to_a
+      else
+        begin
+          converted = obj.to_ary
+        rescue Exception => e
+          raise TypeError, "can't convert #{obj.class} into an Array (#{e.message})"
+        end
+        raise TypeError, "#{obj.class}#to_ary should return an Array" unless converted.is_a? Array
+        converted
+      end
+    end
+    private :convert_to_array
+  end
+
+  extend ConversionHelper
+
+  module CoercionHelper # :nodoc:
+    #
+    # Applies the operator +oper+ with argument +obj+
+    # through coercion of +obj+
+    #
+    def apply_through_coercion(obj, oper)
+      coercion = obj.coerce(self)
+      raise TypeError unless coercion.is_a?(Array) && coercion.length == 2
+      coercion[0].public_send(oper, coercion[1])
+    rescue
+      raise TypeError, "#{obj.inspect} can't be coerced into #{self.class}"
+    end
+    private :apply_through_coercion
+
+    #
+    # Helper method to coerce a value into a specific class.
+    # Raises a TypeError if the coercion fails or the returned value
+    # is not of the right class.
+    # (from Rubinius)
+    #
+    def self.coerce_to(obj, cls, meth) # :nodoc:
+      return obj if obj.kind_of?(cls)
+
+      begin
+        ret = obj.__send__(meth)
+      rescue Exception => e
+        raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \
+                         "(#{e.message})"
+      end
+      raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls
+      ret
+    end
+
+    def self.coerce_to_int(obj)
+      coerce_to(obj, Integer, :to_int)
+    end
+  end
+
+  include CoercionHelper
+
   # Private CLASS
-  
+
   class Scalar < Numeric # :nodoc:
     include ExceptionForMatrix
-    
+    include CoercionHelper
+
     def initialize(value)
       @value = value
     end
-    
+
     # ARITHMETIC
     def +(other)
       case other
       when Numeric
         Scalar.new(@value + other)
       when Vector, Matrix
-        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar"
-      when Scalar
-        Scalar.new(@value + other.value)
+        Scalar.Raise ErrOperationNotDefined, "+", @value.class, other.class
       else
-        x, y = other.coerce(self)
-        x + y
+        apply_through_coercion(other, __method__)
       end
     end
-    
+
     def -(other)
       case other
       when Numeric
         Scalar.new(@value - other)
       when Vector, Matrix
-        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar"
-      when Scalar
-        Scalar.new(@value - other.value)
+        Scalar.Raise ErrOperationNotDefined, "-", @value.class, other.class
       else
-        x, y = other.coerce(self)
-        x - y
+        apply_through_coercion(other, __method__)
       end
     end
-    
+
     def *(other)
       case other
       when Numeric
@@ -1002,39 +1149,38 @@
       when Vector, Matrix
         other.collect{|e| @value * e}
       else
-        x, y = other.coerce(self)
-        x * y
+        apply_through_coercion(other, __method__)
       end
     end
-    
+
     def / (other)
       case other
       when Numeric
         Scalar.new(@value / other)
       when Vector
-        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar or Matrix"
+        Scalar.Raise ErrOperationNotDefined, "/", @value.class, other.class
       when Matrix
-	self * other.inverse
+        self * other.inverse
       else
-        x, y = other.coerce(self)
-        x.quo(y)
+        apply_through_coercion(other, __method__)
       end
     end
-    
+
     def ** (other)
       case other
       when Numeric
         Scalar.new(@value ** other)
       when Vector
-        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar or Matrix"
+        Scalar.Raise ErrOperationNotDefined, "**", @value.class, other.class
       when Matrix
-        other.powered_by(self)
+        #other.powered_by(self)
+        Scalar.Raise ErrOperationNotImplemented, "**", @value.class, other.class
       else
-        x, y = other.coerce(self)
-        x ** y
+        apply_through_coercion(other, __method__)
       end
     end
   end
+
 end
 
 
@@ -1079,47 +1225,41 @@
 #
 class Vector
   include ExceptionForMatrix
-  
+  include Enumerable
+  include Matrix::CoercionHelper
+  extend Matrix::ConversionHelper
   #INSTANCE CREATION
-  
+
   private_class_method :new
+  attr_reader :elements
+  protected :elements
 
   #
   # Creates a Vector from a list of elements.
   #   Vector[7, 4, ...]
   #
   def Vector.[](*array)
-    new(:init_elements, array, copy = false)
+    new convert_to_array(array, copy = false)
   end
-  
+
   #
   # Creates a vector from an Array.  The optional second argument specifies
   # whether the array itself or a copy is used internally.
   #
   def Vector.elements(array, copy = true)
-    new(:init_elements, array, copy)
+    new convert_to_array(array, copy)
   end
-  
+
   #
-  # For internal use.
+  # Vector.new is private; use Vector[] or Vector.elements to create.
   #
-  def initialize(method, array, copy)
-    self.send(method, array, copy)
+  def initialize(array)
+    # No checking is done at this point.
+    @elements = array
   end
-  
-  #
-  # For internal use.
-  #
-  def init_elements(array, copy)
-    if copy
-      @elements = array.dup
-    else
-      @elements = array
-    end
-  end
-  
+
   # ACCESSING
-         
+
   #
   # Returns element number +i+ (starting at zero) of the vector.
   #
@@ -1135,35 +1275,49 @@
   alias set_element []=
   alias set_component []=
   private :[]=, :set_element, :set_component
-  
+
   #
   # Returns the number of elements in the vector.
   #
   def size
     @elements.size
   end
-  
+
   #--
   # ENUMERATIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
 
   #
+  # Iterate over the elements of this vector
+  #
+  def each(&block)
+    return to_enum(:each) unless block_given?
+    @elements.each(&block)
+    self
+  end
+
+  #
   # Iterate over the elements of this vector and +v+ in conjunction.
   #
   def each2(v) # :yield: e1, e2
+    raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer)
     Vector.Raise ErrDimensionMismatch if size != v.size
-    0.upto(size - 1) do |i|
+    return to_enum(:each2, v) unless block_given?
+    size.times do |i|
       yield @elements[i], v[i]
     end
+    self
   end
-  
+
   #
   # Collects (as in Enumerable#collect) over the elements of this vector and +v+
   # in conjunction.
   #
   def collect2(v) # :yield: e1, e2
+    raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer)
     Vector.Raise ErrDimensionMismatch if size != v.size
-    (0 .. size - 1).collect do |i|
+    return to_enum(:collect2, v) unless block_given?
+    size.times.collect do |i|
       yield @elements[i], v[i]
     end
   end
@@ -1177,40 +1331,32 @@
   #
   def ==(other)
     return false unless Vector === other
-    
-    other.compare_by(@elements)
+    @elements == other.elements
   end
+
   def eql?(other)
     return false unless Vector === other
-    
-    other.compare_by(@elements, :eql?)
+    @elements.eql? other.elements
   end
-  
+
   #
-  # For internal use.
-  #
-  def compare_by(elements, comparison = :==)
-    @elements.send(comparison, elements)
-  end
-  
-  #
   # Return a copy of the vector.
   #
   def clone
     Vector.elements(@elements)
   end
-  
+
   #
   # Return a hash-code for the vector.
   #
   def hash
     @elements.hash
   end
-  
+
   #--
   # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
   # Multiplies the vector by +x+, where +x+ is a number or another vector.
   #
@@ -1221,9 +1367,10 @@
       Vector.elements(els, false)
     when Matrix
       Matrix.column_vector(self) * x
+    when Vector
+      Vector.Raise ErrOperationNotDefined, "*", self.class, x.class
     else
-      s, x = x.coerce(self)
-      s * x
+      apply_through_coercion(x, __method__)
     end
   end
 
@@ -1241,8 +1388,7 @@
     when Matrix
       Matrix.column_vector(self) + v
     else
-      s, x = v.coerce(self)
-      s + x
+      apply_through_coercion(v, __method__)
     end
   end
 
@@ -1260,62 +1406,70 @@
     when Matrix
       Matrix.column_vector(self) - v
     else
-      s, x = v.coerce(self)
-      s - x
+      apply_through_coercion(v, __method__)
     end
   end
-  
+
+  #
+  # Vector division.
+  #
+  def /(x)
+    case x
+    when Numeric
+      els = @elements.collect{|e| e / x}
+      Vector.elements(els, false)
+    when Matrix, Vector
+      Vector.Raise ErrOperationNotDefined, "/", self.class, x.class
+    else
+      apply_through_coercion(x, __method__)
+    end
+  end
+
   #--
   # VECTOR FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
   # Returns the inner product of this vector with the other.
   #   Vector[4,7].inner_product Vector[10,1]  => 47
   #
   def inner_product(v)
     Vector.Raise ErrDimensionMismatch if size != v.size
-    
+
     p = 0
     each2(v) {|v1, v2|
       p += v1 * v2
     }
     p
   end
-  
+
   #
   # Like Array#collect.
   #
-  def collect # :yield: e
-    els = @elements.collect {|v|
-      yield v
-    }
+  def collect(&block) # :yield: e
+    return to_enum(:collect) unless block_given?
+    els = @elements.collect(&block)
     Vector.elements(els, false)
   end
   alias map collect
-  
+
   #
   # Like Vector#collect2, but returns a Vector instead of an Array.
   #
-  def map2(v) # :yield: e1, e2
-    els = collect2(v) {|v1, v2|
-      yield v1, v2
-    }
+  def map2(v, &block) # :yield: e1, e2
+    return to_enum(:map2, v) unless block_given?
+    els = collect2(v, &block)
     Vector.elements(els, false)
   end
-  
+
   #
   # Returns the modulus (Pythagorean distance) of the vector.
   #   Vector[5,8,2].r => 9.643650761
   #
   def r
-    v = 0
-    for e in @elements
-      v += e*e
-    end
-    return Math.sqrt(v)
+    Math.sqrt(@elements.inject(0) {|v, e| v + e*e})
   end
-  
+
   #--
   # CONVERTING
   #++
@@ -1326,28 +1480,35 @@
   def covector
     Matrix.row_vector(self)
   end
-  
+
   #
   # Returns the elements of the vector in an array.
   #
   def to_a
     @elements.dup
   end
-  
+
   def elements_to_f
-    collect{|e| e.to_f}
+    warn "#{caller(1)[0]}: warning: Vector#elements_to_f is deprecated"
+    map(&:to_f)
   end
-  
+
   def elements_to_i
-    collect{|e| e.to_i}
+    warn "#{caller(1)[0]}: warning: Vector#elements_to_i is deprecated"
+    map(&:to_i)
   end
-  
+
   def elements_to_r
-    collect{|e| e.to_r}
+    warn "#{caller(1)[0]}: warning: Vector#elements_to_r is deprecated"
+    map(&:to_r)
   end
-  
+
   #
-  # FIXME: describe Vector#coerce.
+  # The coerce method provides support for Ruby type coercion.
+  # This coercion mechanism is used by Ruby to handle mixed-type
+  # numeric operations: it is intended to find a compatible common
+  # type between the two operands of the operator.
+  # See also Numeric#coerce.
   #
   def coerce(other)
     case other
@@ -1357,18 +1518,18 @@
       raise TypeError, "#{self.class} can't be coerced into #{other.class}"
     end
   end
-  
+
   #--
   # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   #++
-  
+
   #
   # Overrides Object#to_s
   #
   def to_s
     "Vector[" + @elements.join(", ") + "]"
   end
-  
+
   #
   # Overrides Object#inspect
   #
@@ -1376,7 +1537,3 @@
     str = "Vector"+ at elements.inspect
   end
 end
-
-
-# Documentation comments:
-#  - Matrix#coerce and Vector#coerce need to be documented

Modified: MacRuby/trunk/lib/minitest/autorun.rb
===================================================================
--- MacRuby/trunk/lib/minitest/autorun.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/minitest/autorun.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -5,5 +5,7 @@
 ############################################################
 
 require 'minitest/unit'
+require 'minitest/spec'
+require 'minitest/mock'
 
 MiniTest::Unit.autorun

Modified: MacRuby/trunk/lib/minitest/mock.rb
===================================================================
--- MacRuby/trunk/lib/minitest/mock.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/minitest/mock.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -16,6 +16,7 @@
     def expect(name, retval, args=[])
       n, r, a = name, retval, args # for the closure below
       @expected_calls[name] = { :retval => retval, :args => args }
+      self.class.__send__ :remove_method, name if respond_to? name
       self.class.__send__(:define_method, name) { |*x|
         raise ArgumentError unless @expected_calls[n][:args].size == x.size
         @actual_calls[n] << { :retval => r, :args => x }

Modified: MacRuby/trunk/lib/minitest/spec.rb
===================================================================
--- MacRuby/trunk/lib/minitest/spec.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/minitest/spec.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,7 +9,23 @@
 require 'minitest/unit'
 
 class Module
-  def infect_with_assertions pos_prefix, neg_prefix, skip_re, map = {}
+  def infect_an_assertion meth, new_name, dont_flip = false
+    # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
+    self.class_eval <<-EOM
+      def #{new_name} *args, &block
+        return MiniTest::Spec.current.#{meth}(*args, &self) if
+          Proc === self
+        return MiniTest::Spec.current.#{meth}(args.first, self) if
+          args.size == 1 unless #{!!dont_flip}
+        return MiniTest::Spec.current.#{meth}(self, *args)
+      end
+    EOM
+  end
+
+  def infect_with_assertions(pos_prefix, neg_prefix,
+                             skip_re,
+                             dont_flip_re = /\c0/,
+                             map = {})
     MiniTest::Assertions.public_instance_methods(false).each do |meth|
       meth = meth.to_s
 
@@ -25,14 +41,7 @@
       regexp, replacement = map.find { |re, _| new_name =~ re }
       new_name.sub! regexp, replacement if replacement
 
-      # warn "%-22p -> %p %p" % [meth, new_name, regexp]
-      self.class_eval <<-EOM
-        def #{new_name} *args, &block
-          return MiniTest::Spec.current.#{meth}(*args, &self)     if Proc === self
-          return MiniTest::Spec.current.#{meth}(args.first, self) if args.size == 1
-          return MiniTest::Spec.current.#{meth}(self, *args)
-        end
-      EOM
+      infect_an_assertion meth, new_name, new_name =~ dont_flip_re
     end
   end
 end
@@ -40,6 +49,7 @@
 Object.infect_with_assertions(:must, :wont,
                               /^(must|wont)$|wont_(throw)|
                                  must_(block|not?_|nothing|raise$)/x,
+                              /(must|wont)_(include|respond_to)/,
                               /(must_throw)s/                 => '\1',
                               /(?!not)_same/                  => '_be_same_as',
                               /_in_/                          => '_be_within_',
@@ -54,36 +64,229 @@
 end
 
 module Kernel
+  ##
+  # Describe a series of expectations for a given target +desc+.
+  #
+  # TODO: find good tutorial url.
+  #
+  # Defines a test class subclassing from either
+  # MiniTest::Unit::TestCase or from the surrounding describe's class.
+
   def describe desc, &block
-    cls = Class.new(MiniTest::Spec)
-    Object.const_set desc.to_s.split(/\W+/).map { |s| s.capitalize }.join, cls
+    stack = MiniTest::Spec.describe_stack
+    name  = desc.to_s.split(/\W+/).map { |s| s.capitalize }.join + "Spec"
+    prev  = stack.last
+    name  = "#{prev == MiniTest::Spec ? nil : prev}::#{name}"
+    cls   = Object.class_eval "class #{name} < #{prev}; end; #{name}"
 
+    cls.nuke_test_methods!
+
+    stack.push cls
     cls.class_eval(&block)
+    stack.pop
   end
   private :describe
 end
 
+class Module
+  def classes type = Object # :nodoc:
+    constants.map { |n| const_get n }.find_all { |c|
+      c.class == Class and type > c
+    } - [self]
+  end
+end
+
 class MiniTest::Spec < MiniTest::Unit::TestCase
-  def self.current
+  @@describe_stack = [MiniTest::Spec]
+  def self.describe_stack # :nodoc:
+    @@describe_stack
+  end
+
+  def self.current # :nodoc:
     @@current_spec
   end
 
-  def initialize name
+  def initialize name # :nodoc:
     super
     @@current_spec = self
   end
 
-  def self.before(type = :each, &block)
+  def self.nuke_test_methods! # :nodoc:
+    self.public_instance_methods.grep(/^test_/).each do |name|
+      self.send :undef_method, name
+    end
+  end
+
+  def self.define_inheritable_method name, &block # :nodoc:
+    super_method = self.superclass.instance_method name
+
+    define_method name do
+      super_method.bind(self).call if super_method # regular super() warns
+      instance_eval(&block)
+    end
+  end
+
+  ##
+  # Define a 'before' action. Inherits the way normal methods should.
+  #
+  # NOTE: +type+ is ignored and is only there to make porting easier.
+  #
+  # Equivalent to MiniTest::Unit::TestCase#setup.
+
+  def self.before type = :each, &block
     raise "unsupported before type: #{type}" unless type == :each
-    define_method :setup, &block
+    define_inheritable_method :setup, &block
   end
 
-  def self.after(type = :each, &block)
+  ##
+  # Define an 'after' action. Inherits the way normal methods should.
+  #
+  # NOTE: +type+ is ignored and is only there to make porting easier.
+  #
+  # Equivalent to MiniTest::Unit::TestCase#teardown.
+
+  def self.after type = :each, &block
     raise "unsupported after type: #{type}" unless type == :each
-    define_method :teardown, &block
+    define_inheritable_method :teardown, &block
   end
 
+  ##
+  # Define an expectation with name +desc+. Name gets morphed to a
+  # proper test method name. For some freakish reason, people who
+  # write specs don't like class inheritence, so this goes way out of
+  # its way to make sure that expectations aren't inherited.
+  #
+  # Hint: If you _do_ want inheritence, use minitest/unit. You can mix
+  # and match between assertions and expectations as much as you want.
+
   def self.it desc, &block
-    define_method "test_#{desc.gsub(/\W+/, '_').downcase}", &block
+    block ||= proc { skip "(no tests defined)" }
+
+    @specs ||= 0
+    @specs += 1
+
+    name = "test_%04d_%s" % [ @specs, desc.gsub(/\W+/, '_').downcase ]
+
+    define_method name, &block
+
+    classes(MiniTest::Spec).each do |mod|
+      mod.send :undef_method, name if mod.respond_to? name
+    end
   end
+
+  ##
+  # :method: must_be
+  # See MiniTest::Assertions#assert
+
+  ##
+  # :method: must_be_close_to
+  # See MiniTest::Assertions#assert_in_delta
+
+  ##
+  # :method: must_be_empty
+  # See MiniTest::Assertions#assert_empty
+
+  ##
+  # :method: must_be_instance_of
+  # See MiniTest::Assertions#assert_instance_of
+
+  ##
+  # :method: must_be_kind_of
+  # See MiniTest::Assertions#assert_kind_of
+
+  ##
+  # :method: must_be_nil
+  # See MiniTest::Assertions#assert_nil
+
+  ##
+  # :method: must_be_same_as
+  # See MiniTest::Assertions#assert_same
+
+  ##
+  # :method: must_be_within_delta
+  # See MiniTest::Assertions#assert_in_delta
+
+  ##
+  # :method: must_be_within_epsilon
+  # See MiniTest::Assertions#assert_in_epsilon
+
+  ##
+  # :method: must_equal
+  # See MiniTest::Assertions#assert_equal
+
+  ##
+  # :method: must_include
+  # See MiniTest::Assertions#assert_includes
+
+  ##
+  # :method: must_match
+  # See MiniTest::Assertions#assert_match
+
+  ##
+  # :method: must_raise
+  # See MiniTest::Assertions#assert_raises
+
+  ##
+  # :method: must_respond_to
+  # See MiniTest::Assertions#assert_respond_to
+
+  ##
+  # :method: must_send
+  # See MiniTest::Assertions#assert_send
+
+  ##
+  # :method: must_throw
+  # See MiniTest::Assertions#assert_throw
+
+  ##
+  # :method: wont_be
+  # See MiniTest::Assertions#refute
+
+  ##
+  # :method: wont_be_close_to
+  # See MiniTest::Assertions#refute_in_delta
+
+  ##
+  # :method: wont_be_empty
+  # See MiniTest::Assertions#refute_empty
+
+  ##
+  # :method: wont_be_instance_of
+  # See MiniTest::Assertions#refute_instance_of
+
+  ##
+  # :method: wont_be_kind_of
+  # See MiniTest::Assertions#refute_kind_of
+
+  ##
+  # :method: wont_be_nil
+  # See MiniTest::Assertions#refute_nil
+
+  ##
+  # :method: wont_be_same_as
+  # See MiniTest::Assertions#refute_same
+
+  ##
+  # :method: wont_be_within_delta
+  # See MiniTest::Assertions#refute_in_delta
+
+  ##
+  # :method: wont_be_within_epsilon
+  # See MiniTest::Assertions#refute_in_epsilon
+
+  ##
+  # :method: wont_equal
+  # See MiniTest::Assertions#refute_equal
+
+  ##
+  # :method: wont_include
+  # See MiniTest::Assertions#refute_includes
+
+  ##
+  # :method: wont_match
+  # See MiniTest::Assertions#refute_match
+
+  ##
+  # :method: wont_respond_to
+  # See MiniTest::Assertions#refute_respond_to
 end

Modified: MacRuby/trunk/lib/minitest/unit.rb
===================================================================
--- MacRuby/trunk/lib/minitest/unit.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/minitest/unit.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -4,14 +4,21 @@
 # File a patch instead and assign it to Ryan Davis
 ############################################################
 
+require 'optparse'
+
 ##
-#
-# Totally minimal drop-in replacement for test-unit
-#
-# TODO: refute -> debunk, prove/rebut, show/deny... lots of possibilities
+# Minimal (mostly drop-in) replacement for test-unit.
 
 module MiniTest
+
+  ##
+  # Assertion base class
+
   class Assertion < Exception; end
+
+  ##
+  # Assertion raised when skipping a test
+
   class Skip < Assertion; end
 
   file = if RUBY_VERSION =~ /^1\.9/ then  # bt's expanded, but __FILE__ isn't :(
@@ -27,9 +34,9 @@
          end
 
   # './lib' in project dir, or '/usr/local/blahblah' if installed
-  MINI_DIR = File.dirname(File.dirname(file))
+  MINI_DIR = File.dirname(File.dirname(file)) # :nodoc:
 
-  def self.filter_backtrace bt
+  def self.filter_backtrace bt # :nodoc:
     return ["No backtrace"] unless bt
 
     new_bt = []
@@ -43,21 +50,33 @@
     new_bt
   end
 
+  ##
+  # MiniTest Assertions.  All assertion methods accept a +msg+ which is
+  # printed if the assertion fails.
+
   module Assertions
-    def mu_pp(obj)
+
+    ##
+    # mu_pp gives a human-readable version of +obj+.  By default #inspect is
+    # called.  You can override this to use #pretty_print if you want.
+
+    def mu_pp obj
       s = obj.inspect
       s = s.force_encoding(Encoding.default_external) if defined? Encoding
       s
     end
 
-    def _assertions= n
+    def _assertions= n # :nodoc:
       @_assertions = n
     end
 
-    def _assertions
+    def _assertions # :nodoc:
       @_assertions ||= 0
     end
 
+    ##
+    # Fails unless +test+ is a true value.
+
     def assert test, msg = nil
       msg ||= "Failed assertion, no message given."
       self._assertions += 1
@@ -68,105 +87,163 @@
       true
     end
 
+    ##
+    # Fails unless the block returns a true value.
+
     def assert_block msg = nil
       msg = message(msg) { "Expected block to return true value" }
       assert yield, msg
     end
 
+    ##
+    # Fails unless +obj+ is empty.
+
     def assert_empty obj, msg = nil
       msg = message(msg) { "Expected #{obj.inspect} to be empty" }
       assert_respond_to obj, :empty?
       assert obj.empty?, msg
     end
 
+    ##
+    # Fails unless <tt>exp == act</tt>.
+    #
+    # For floats use assert_in_delta
+
     def assert_equal exp, act, msg = nil
       msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
       assert(exp == act, msg)
     end
 
+    ##
+    # For comparing Floats.  Fails unless +exp+ and +act+ are within +delta+
+    # of each other.
+    #
+    #   assert_in_delta Math::PI, (22.0 / 7.0), 0.01
+
     def assert_in_delta exp, act, delta = 0.001, msg = nil
       n = (exp - act).abs
       msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
       assert delta >= n, msg
     end
 
+    ##
+    # For comparing Floats.  Fails unless +exp+ and +act+ have a relative
+    # error less than +epsilon+.
+
     def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
       assert_in_delta a, b, [a, b].min * epsilon, msg
     end
 
+    ##
+    # Fails unless +collection+ includes +obj+.
+
     def assert_includes collection, obj, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" }
+      msg = message(msg) {
+        "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}"
+      }
       assert_respond_to collection, :include?
       assert collection.include?(obj), msg
     end
 
+    ##
+    # Fails unless +obj+ is an instace of +cls+.
+
     def assert_instance_of cls, obj, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" }
-      flip = (Module === obj) && ! (Module === cls) # HACK for specs
-      obj, cls = cls, obj if flip
+      msg = message(msg) {
+        "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}"
+      }
+
       assert obj.instance_of?(cls), msg
     end
 
+    ##
+    # Fails unless +obj+ is a kind of +cls+.
+
     def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
       msg = message(msg) {
         "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
-      flip = (Module === obj) && ! (Module === cls) # HACK for specs
-      obj, cls = cls, obj if flip
+
       assert obj.kind_of?(cls), msg
     end
 
+    ##
+    # Fails unless +exp+ is <tt>=~</tt> +act+.
+
     def assert_match exp, act, msg = nil
       msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" }
       assert_respond_to act, :"=~"
-      exp = /#{Regexp.escape(exp)}/ if String === exp && String === act
+      exp = /#{Regexp.escape exp}/ if String === exp && String === act
       assert exp =~ act, msg
     end
 
+    ##
+    # Fails unless +obj+ is nil
+
     def assert_nil obj, msg = nil
       msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
       assert obj.nil?, msg
     end
 
+    ##
+    # For testing equality operators and so-forth.
+    #
+    #   assert_operator 5, :<=, 4
+
     def assert_operator o1, op, o2, msg = nil
       msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
       assert o1.__send__(op, o2), msg
     end
 
+    ##
+    # Fails unless the block raises one of +exp+
+
     def assert_raises *exp
       msg = String === exp.last ? exp.pop : nil
+      msg = msg.to_s + "\n" if msg
       should_raise = false
       begin
         yield
         should_raise = true
       rescue Exception => e
+        details = "#{msg}#{mu_pp(exp)} exception expected, not"
         assert(exp.any? { |ex|
                  ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
-               }, exception_details(e, "#{mu_pp(exp)} exception expected, not"))
+               }, exception_details(e, details))
 
         return e
       end
 
       exp = exp.first if exp.size == 1
-      flunk "#{mu_pp(exp)} expected but nothing was raised." if should_raise
+      flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." if
+        should_raise
     end
 
+    ##
+    # Fails unless +obj+ responds to +meth+.
+
     def assert_respond_to obj, meth, msg = nil
       msg = message(msg) {
           "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
         }
-      flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
-      obj, meth = meth, obj if flip
       assert obj.respond_to?(meth), msg
     end
 
+    ##
+    # Fails unless +exp+ and +act+ are #equal?
+
     def assert_same exp, act, msg = nil
       msg = message(msg) {
         data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
-        "Expected %s (0x%x) to be the same as %s (0x%x)" % data
+        "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data
       }
       assert exp.equal?(act), msg
     end
 
+    ##
+    # +send_ary+ is a receiver, message and arguments.
+    #
+    # Fails unless the call returns a true value
+
     def assert_send send_ary, m = nil
       recv, msg, *args = send_ary
       m = message(m) {
@@ -174,6 +251,9 @@
       assert recv.__send__(msg, *args), m
     end
 
+    ##
+    # Fails unless the block throws +sym+
+
     def assert_throws sym, msg = nil
       default = "Expected #{mu_pp(sym)} to have been thrown"
       caught = true
@@ -191,6 +271,15 @@
       assert caught, message(msg) { default }
     end
 
+    ##
+    # Captures $stdout and $stderr into strings:
+    #
+    #   out, err = capture_io do
+    #     warn "You did a bad thing"
+    #   end
+    #
+    #   assert_match %r%bad%, err
+
     def capture_io
       require 'stringio'
 
@@ -206,15 +295,24 @@
       $stderr = orig_stderr
     end
 
+    ##
+    # Returns details for exception +e+
+
     def exception_details e, msg
       "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{MiniTest::filter_backtrace(e.backtrace).join("\n")}\n---------------"
     end
 
+    ##
+    # Fails with +msg+
+
     def flunk msg = nil
       msg ||= "Epic Fail!"
       assert false, msg
     end
 
+    ##
+    # Returns a proc that will output +msg+ along with the default message.
+
     def message msg = nil, &default
       proc {
         if msg then
@@ -228,86 +326,147 @@
       }
     end
 
+    ##
     # used for counting assertions
+
     def pass msg = nil
       assert true
     end
 
+    ##
+    # Fails if +test+ is a true value
+
     def refute test, msg = nil
       msg ||= "Failed refutation, no message given"
       not assert(! test, msg)
     end
 
+    ##
+    # Fails if +obj+ is empty.
+
     def refute_empty obj, msg = nil
       msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
       assert_respond_to obj, :empty?
       refute obj.empty?, msg
     end
 
+    ##
+    # Fails if <tt>exp == act</tt>.
+    #
+    # For floats use refute_in_delta.
+
     def refute_equal exp, act, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" }
+      msg = message(msg) {
+        "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}"
+      }
       refute exp == act, msg
     end
 
+    ##
+    # For comparing Floats.  Fails if +exp+ is within +delta+ of +act+
+    #
+    #   refute_in_delta Math::PI, (22.0 / 7.0)
+
     def refute_in_delta exp, act, delta = 0.001, msg = nil
       n = (exp - act).abs
-      msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to not be < #{delta}" }
+      msg = message(msg) {
+        "Expected #{exp} - #{act} (#{n}) to not be < #{delta}"
+      }
       refute delta > n, msg
     end
 
+    ##
+    # For comparing Floats.  Fails if +exp+ and +act+ have a relative error
+    # less than +epsilon+.
+
     def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
       refute_in_delta a, b, a * epsilon, msg
     end
 
+    ##
+    # Fails if +collection+ includes +obj+
+
     def refute_includes collection, obj, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" }
+      msg = message(msg) {
+        "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}"
+      }
       assert_respond_to collection, :include?
       refute collection.include?(obj), msg
     end
 
+    ##
+    # Fails if +obj+ is an instance of +cls+
+
     def refute_instance_of cls, obj, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(obj)} to not be an instance of #{cls}" }
-      flip = (Module === obj) && ! (Module === cls) # HACK for specs
-      obj, cls = cls, obj if flip
+      msg = message(msg) {
+        "Expected #{mu_pp(obj)} to not be an instance of #{cls}"
+      }
       refute obj.instance_of?(cls), msg
     end
 
+    ##
+    # Fails if +obj+ is a kind of +cls+
+
     def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
       msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
-      flip = (Module === obj) && ! (Module === cls) # HACK for specs
-      obj, cls = cls, obj if flip
       refute obj.kind_of?(cls), msg
     end
 
+    ##
+    # Fails if +exp+ <tt>=~</tt> +act+
+
     def refute_match exp, act, msg = nil
       msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" }
       assert_respond_to act, :"=~"
-      exp = /#{Regexp.escape(exp)}/ if String === exp && String === act
+      exp = (/#{Regexp.escape exp}/) if String === exp and String === act
       refute exp =~ act, msg
     end
 
+    ##
+    # Fails if +obj+ is nil.
+
     def refute_nil obj, msg = nil
       msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
       refute obj.nil?, msg
     end
 
+    ##
+    # Fails if +o1+ is not +op+ +o2+ nil. eg:
+    #
+    #   refute_operator 1, :>, 2 #=> pass
+    #   refute_operator 1, :<, 2 #=> fail
+
     def refute_operator o1, op, o2, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" }
+      msg = message(msg) {
+        "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"
+      }
       refute o1.__send__(op, o2), msg
     end
 
+    ##
+    # Fails if +obj+ responds to the message +meth+.
+
     def refute_respond_to obj, meth, msg = nil
       msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
-      flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
-      obj, meth = meth, obj if flip
+
       refute obj.respond_to?(meth), msg
     end
 
+    ##
+    # Fails if +exp+ is the same (by object identity) as +act+.
+
     def refute_same exp, act, msg = nil
-      msg = message(msg) { "Expected #{mu_pp(act)} to not be the same as #{mu_pp(exp)}" }
+      msg = message(msg) {
+        data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
+        "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data
+      }
       refute exp.equal?(act), msg
     end
 
+    ##
+    # Skips the current test. Gets listed at the end of the run but
+    # doesn't cause a failure exit code.
+
     def skip msg = nil, bt = caller
       msg ||= "Skipped, no message given"
       raise MiniTest::Skip, msg, bt
@@ -315,14 +474,18 @@
   end
 
   class Unit
-    VERSION = "1.3.1"
+    VERSION = "1.6.0" # :nodoc:
 
-    attr_accessor :report, :failures, :errors, :skips
-    attr_accessor :test_count, :assertion_count
+    attr_accessor :report, :failures, :errors, :skips # :nodoc:
+    attr_accessor :test_count, :assertion_count       # :nodoc:
+    attr_accessor :start_time                         # :nodoc:
 
     @@installed_at_exit ||= false
     @@out = $stdout
 
+    ##
+    # Registers MiniTest::Unit to run tests at process exit
+
     def self.autorun
       at_exit {
         next if $! # don't run if there was an exception
@@ -332,19 +495,27 @@
       @@installed_at_exit = true
     end
 
+    ##
+    # Sets MiniTest::Unit to write output to +stream+.  $stdout is the default
+    # output
+
     def self.output= stream
       @@out = stream
     end
 
-    def location e
+    def location e # :nodoc:
       last_before_assertion = ""
       e.backtrace.reverse_each do |s|
-        break if s =~ /in .(assert|refute|flunk|pass|fail|raise)/
+        break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
         last_before_assertion = s
       end
       last_before_assertion.sub(/:in .*$/, '')
     end
 
+    ##
+    # Writes status for failed test +meth+ in +klass+ which finished with
+    # exception +e+
+
     def puke klass, meth, e
       e = case e
           when MiniTest::Skip then
@@ -362,26 +533,61 @@
       e[0, 1]
     end
 
-    def initialize
+    def initialize # :nodoc:
       @report = []
       @errors = @failures = @skips = 0
       @verbose = false
     end
 
+    def process_args args = []
+      options = {}
+
+      OptionParser.new do |opts|
+        opts.banner  = 'minitest options:'
+        opts.version = MiniTest::Unit::VERSION
+
+        opts.on '-h', '--help', 'Display this help.' do
+          puts opts
+          exit
+        end
+
+        opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
+          options[:seed] = m.to_i
+        end
+
+        opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
+          options[:verbose] = true
+        end
+
+        opts.on '-n', '--name PATTERN', "Filter test names on pattern." do |a|
+          options[:filter] = a
+        end
+
+        opts.parse args
+      end
+
+      options
+    end
+
     ##
     # Top level driver, controls all output and filtering.
 
     def run args = []
-      @verbose = args.delete('-v')
+      options = process_args args
 
-      filter = if args.first =~ /^(-n|--name)$/ then
-                 args.shift
-                 arg = args.shift
-                 arg =~ /\/(.*)\// ? Regexp.new($1) : arg
-               else
-                 /./ # anything - ^test_ already filtered by #tests
-               end
+      @verbose = options[:verbose]
 
+      filter = options[:filter] || '/./'
+      filter = Regexp.new $1 if filter and filter =~ /\/(.*)\//
+
+      seed = options[:seed]
+      unless seed then
+        srand
+        seed = srand % 0xFFFF
+      end
+
+      srand seed
+
       @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
 
       start = Time.now
@@ -396,12 +602,32 @@
 
       @@out.puts
 
-      format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
-      @@out.puts format % [test_count, assertion_count, failures, errors, skips]
+      status
 
+      @@out.puts
+
+      help = ["--seed", seed]
+      help.push "--verbose" if @verbose
+      help.push("--name", options[:filter].inspect) if options[:filter]
+
+      @@out.puts "Test run options: #{help.join(" ")}"
+
       return failures + errors if @test_count > 0 # or return nil...
+    rescue Interrupt
+      abort 'Interrupted'
     end
 
+    ##
+    # Writes status to +io+
+
+    def status io = @@out
+      format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
+      io.puts format % [test_count, assertion_count, failures, errors, skips]
+    end
+
+    ##
+    # Runs test suites matching +filter+
+
     def run_test_suites filter = /./
       @test_count, @assertion_count = 0, 0
       old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
@@ -411,10 +637,10 @@
           inst._assertions = 0
           @@out.print "#{suite}##{test}: " if @verbose
 
-          t = Time.now if @verbose
+          @start_time = Time.now
           result = inst.run(self)
 
-          @@out.print "%.2f s: " % (Time.now - t) if @verbose
+          @@out.print "%.2f s: " % (Time.now - @start_time) if @verbose
           @@out.print result
           @@out.puts if @verbose
           @test_count += 1
@@ -425,73 +651,126 @@
       [@test_count, @assertion_count]
     end
 
+    ##
+    # Subclass TestCase to create your own tests.  Typically you'll want a
+    # TestCase subclass per implementation class.
+
     class TestCase
-      attr_reader :name
+      attr_reader :__name__ # :nodoc:
 
+      PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException,
+                                Interrupt, SystemExit] # :nodoc:
+
+      SUPPORTS_INFO_SIGNAL = Signal.list['INFO'] # :nodoc:
+
+      ##
+      # Runs the tests reporting the status to +runner+
+
       def run runner
+        trap 'INFO' do
+          warn '%s#%s %.2fs' % [self.class, self.__name__,
+            (Time.now - runner.start_time)]
+          runner.status $stderr
+        end if SUPPORTS_INFO_SIGNAL
+
         result = '.'
         begin
           @passed = nil
           self.setup
-          self.__send__ self.name
+          self.__send__ self.__name__
           @passed = true
+        rescue *PASSTHROUGH_EXCEPTIONS
+          raise
         rescue Exception => e
           @passed = false
-          result = runner.puke(self.class, self.name, e)
+          result = runner.puke(self.class, self.__name__, e)
         ensure
           begin
             self.teardown
+          rescue *PASSTHROUGH_EXCEPTIONS
+            raise
           rescue Exception => e
-            result = runner.puke(self.class, self.name, e)
+            result = runner.puke(self.class, self.__name__, e)
           end
+          trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
         end
         result
       end
 
-      def initialize name
-        @name = name
+      def initialize name # :nodoc:
+        @__name__ = name
         @passed = nil
       end
 
-      def self.reset
+      def self.reset # :nodoc:
         @@test_suites = {}
       end
 
       reset
 
-      def self.inherited klass
+      def self.inherited klass # :nodoc:
         @@test_suites[klass] = true
       end
 
+      ##
+      # Defines test order and is subclassable. Defaults to :random
+      # but can be overridden to return :alpha if your tests are order
+      # dependent (read: weak).
+
       def self.test_order
         :random
       end
 
-      def self.test_suites
+      def self.test_suites # :nodoc:
         @@test_suites.keys.sort_by { |ts| ts.name }
       end
 
-      def self.test_methods
-        methods = public_instance_methods(true).grep(/^test/).map { |m|
-          m.to_s
-        }.sort
+      def self.test_methods # :nodoc:
+        methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s }
 
-        if self.test_order == :random then
+        case self.test_order
+        when :random then
           max = methods.size
-          methods = methods.sort_by { rand(max) }
+          methods.sort.sort_by { rand(max) }
+        when :alpha, :sorted then
+          methods.sort
+        else
+          raise "Unknown test_order: #{self.test_order.inspect}"
         end
-
-        methods
       end
 
-      def setup; end
-      def teardown; end
+      ##
+      # Returns true if the test passed.
 
       def passed?
         @passed
       end
 
+      ##
+      # Runs before every test. Use this to refactor test initialization.
+
+      def setup; end
+
+      ##
+      # Runs after every test. Use this to refactor test cleanup.
+
+      def teardown; end
+
       include MiniTest::Assertions
     end # class TestCase
-  end # class Test
-end # module Mini
+  end # class Unit
+end # module MiniTest
+
+if $DEBUG then
+  module Test                # :nodoc:
+    module Unit              # :nodoc:
+      class TestCase         # :nodoc:
+        def self.inherited x # :nodoc:
+          # this helps me ferret out porting issues
+          raise "Using minitest and test/unit in the same process: #{x}"
+        end
+      end
+    end
+  end
+end
+

Modified: MacRuby/trunk/lib/mkmf.rb
===================================================================
--- MacRuby/trunk/lib/mkmf.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/mkmf.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +1,4 @@
+# -*- indent-tabs-mode: t -*-
 # module to create Makefile for extension modules
 # invoke like: ruby -r mkmf extconf.rb
 
@@ -9,10 +10,10 @@
 ORIG_LIBPATH = ENV['LIB']
 
 CXX_EXT = %w[cc cxx cpp]
-if /mswin|bccwin|mingw|os2/ !~ CONFIG['build_os']
+if File::FNM_SYSCASE.zero?
   CXX_EXT.concat(%w[C])
 end
-SRC_EXT = %w[c m] << CXX_EXT
+SRC_EXT = %w[c m].concat(CXX_EXT)
 $static = nil
 $config_h = '$(arch_hdrdir)/ruby/config.h'
 $default_static = $static
@@ -65,6 +66,7 @@
 $beos = /beos/ =~ RUBY_PLATFORM
 $haiku = /haiku/ =~ RUBY_PLATFORM
 $solaris = /solaris/ =~ RUBY_PLATFORM
+$universal = /universal/ =~ RUBY_PLATFORM
 $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
 
 # :stopdoc:
@@ -154,7 +156,9 @@
 topdir = File.dirname(libdir = File.dirname(__FILE__))
 extdir = File.expand_path("ext", topdir)
 path = File.expand_path($0)
-$extmk = path[0, topdir.size+1] == topdir+"/" && %r"\A(ext|enc|tool)\z" =~ File.dirname(path[topdir.size+1..-1])
+$extmk = path[0, topdir.size+1] == topdir+"/"
+$extmk &&= %r"\A(?:ext|enc|tool|test(?:/.+))\z" =~ File.dirname(path[topdir.size+1..-1])
+$extmk &&= true
 if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
   $topdir = $hdrdir
   $top_srcdir = $hdrdir
@@ -191,11 +195,13 @@
 end
 
 def rm_f(*files)
-  FileUtils.rm_f(Dir[*files])
+  opt = (Hash === files.last ? [files.pop] : [])
+  FileUtils.rm_f(Dir[*files.flatten], *opt)
 end
 
 def rm_rf(*files)
-  FileUtils.rm_rf(Dir[*files])
+  opt = (Hash === files.last ? [files.pop] : [])
+  FileUtils.rm_rf(Dir[*files.flatten], *opt)
 end
 
 # Returns time stamp of the +target+ file if it exists and is newer
@@ -264,7 +270,7 @@
       @log = nil
     end
   end
-  
+
   def self::postpone
     tmplog = "mkmftmp#{@postpone += 1}.log"
     open do
@@ -272,9 +278,9 @@
       @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
       begin
         log.print(open {yield})
+      ensure
         @log.close
         File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
-      ensure
         @log, @logfile, @orgout, @orgerr = log, *save
         @postpone -= 1
         rm_f tmplog
@@ -357,15 +363,17 @@
 def try_do(src, command, &b)
   unless have_devel?
     raise <<MSG
-The compiler failed to generate an executable file.
+The complier failed to generate an executable file.
 You have to install development tools first.
 MSG
   end
-  src = create_tmpsrc(src, &b)
-  xsystem(command)
-ensure
-  log_src(src)
-  rm_rf 'conftest.dSYM'
+  begin
+    src = create_tmpsrc(src, &b)
+    xsystem(command)
+  ensure
+    log_src(src)
+    rm_rf 'conftest.dSYM'
+  end
 end
 
 def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
@@ -397,7 +405,7 @@
                                 'arch_hdrdir' => "#$arch_hdrdir",
                                 'top_srcdir' => $top_srcdir.quote)
   RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
-		   conf).gsub(/-arch\s+\w+/,'')
+		   conf)
 end
 
 def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
@@ -412,7 +420,20 @@
 end
 
 def try_link0(src, opt="", &b)
-  try_do(src, link_command("", opt), &b)
+  cmd = link_command("", opt)
+  if $universal
+    require 'tmpdir'
+    Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
+      begin
+        ENV["TMPDIR"] = tmpdir
+        try_do(src, cmd, &b)
+      ensure
+        ENV["TMPDIR"] = oldtmpdir
+      end
+    end
+  else
+    try_do(src, cmd, &b)
+  end
 end
 
 def try_link(src, opt="", &b)
@@ -433,10 +454,14 @@
   rm_f "conftest*"
 end
 
+class Object
+  alias_method :try_header, (config_string('try_header') || :try_cpp)
+end
+
 def cpp_include(header)
   if header
     header = [header] unless header.kind_of? Array
-    header.map {|h| "#include <#{h}>\n"}.join
+    header.map {|h| String === h ? "#include <#{h}>\n" : h}.join
   else
     ""
   end
@@ -599,7 +624,7 @@
 def install_files(mfile, ifiles, map = nil, srcprefix = nil)
   ifiles or return
   ifiles.empty? and return
-  srcprefix ||= '$(srcdir)'
+  srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
   RbConfig::expand(srcdir = srcprefix.dup)
   dirs = []
   path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
@@ -804,13 +829,10 @@
 # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
 # preprocessor macro would be passed to the compiler.
 #
-def have_header(header, &b)
+def have_header(header, preheaders = nil, &b)
   checking_for header do
-    if try_cpp(cpp_include(header), &b)
-      #FIXME: cannot use this in MacRuby yet
-      #$defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
-      str = header.tr("a-z", "A-Z").tr("./\055", "_")
-      $defs.push(format("-DHAVE_%s", str))
+    if try_header(cpp_include(preheaders)+cpp_include(header), &b)
+      $defs.push(format("-DHAVE_%s", header.tr_cpp))
       true
     else
       false
@@ -828,13 +850,13 @@
   message = checking_message(header, paths)
   header = cpp_include(header)
   checking_for message do
-    if try_cpp(header)
+    if try_header(header)
       true
     else
       found = false
       paths.each do |dir|
         opt = "-I#{dir}".quote
-        if try_cpp(header, opt)
+        if try_header(header, opt)
           $INCFLAGS << " " << opt
           found = true
           break
@@ -857,7 +879,7 @@
 # HAVE_STRUCT_FOO_BAR preprocessor macro would be passed to the compiler.
 #
 # HAVE_ST_BAR is also defined for backward compatibility.
-# 
+#
 def have_struct_member(type, member, headers = nil, &b)
   checking_for checking_message("#{type}.#{member}", headers) do
     if try_compile(<<"SRC", &b)
@@ -965,6 +987,11 @@
   end
 end
 
+STRING_OR_FAILED_FORMAT = "%s"
+def STRING_OR_FAILED_FORMAT.%(x)
+  x ? super : "failed"
+end
+
 # Returns the size of the given +type+.  You may optionally specify additional
 # +headers+ to search in for the +type+.
 #
@@ -975,20 +1002,60 @@
 # For example, if check_sizeof('mystruct') returned 12, then the
 # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
 #
-def check_sizeof(type, headers = nil, &b)
-  expr = "sizeof(#{type})"
-  fmt = "%d"
-  def fmt.%(x)
-    x ? super : "failed"
-  end
+def check_sizeof(type, headers = nil, opts = "", &b)
+  typename, member = type.split('.', 2)
+  prelude = cpp_include(headers).split(/$/)
+  prelude << "typedef #{typename} rbcv_typedef_;\n"
+  prelude << "static rbcv_typedef_ *rbcv_ptr_;\n"
+  prelude = [prelude]
+  expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
+  fmt = STRING_OR_FAILED_FORMAT
   checking_for checking_message("size of #{type}", headers), fmt do
-    if size = try_constant(expr, headers, &b)
-      $defs.push(format("-DSIZEOF_%s=%d", type.tr_cpp, size))
+    if UNIVERSAL_INTS.include?(type)
+      type
+    elsif size = UNIVERSAL_INTS.find {|t|
+        try_static_assert("#{expr} == sizeof(#{t})", prelude, opts, &b)
+      }
+      $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", type.tr_cpp, size.tr_cpp))
       size
+    elsif size = try_constant(expr, prelude, opts, &b)
+      $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size))
+      size
     end
   end
 end
 
+# Returns the signedness of the given +type+.  You may optionally
+# specify additional +headers+ to search in for the +type+.
+#
+# If the +type+ is found and is a numeric type, a macro is passed as a
+# preprocessor constant to the compiler using the +type+ name, in
+# uppercase, prepended with 'SIGNEDNESS_OF_', followed by the +type+
+# name, followed by '=X' where 'X' is positive integer if the +type+ is
+# unsigned, or negative integer if the +type+ is signed.
+#
+# For example, if size_t is defined as unsigned, then
+# check_signedness('size_t') would returned +1 and the
+# SIGNEDNESS_OF_SIZE_T=+1 preprocessor macro would be passed to the
+# compiler, and SIGNEDNESS_OF_INT=-1 if check_signedness('int') is
+# done.
+#
+def check_signedness(type, headers = nil)
+  signed = nil
+  checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
+    if try_static_assert("(#{type})-1 < 0")
+      signed = -1
+    elsif try_static_assert("(#{type})-1 > 0")
+      signed = +1
+    else
+      next nil
+    end
+    $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
+    signed < 0 ? "signed" : "unsigned"
+  end
+  signed
+end
+
 # :stopdoc:
 
 # Used internally by the what_type? method to determine if +type+ is a scalar
@@ -1015,35 +1082,74 @@
 SRC
 end
 
+# Used internally by the what_type? method to check if _typeof_ GCC
+# extension is available.
+def have_typeof?
+  return $typeof if defined?($typeof)
+  $typeof = %w[__typeof__ typeof].find do |t|
+    try_compile(<<SRC)
+int rbcv_foo;
+#{t}(rbcv_foo) rbcv_bar;
+SRC
+  end
+end
+
 def what_type?(type, member = nil, headers = nil, &b)
   m = "#{type}"
-  name = type
+  var = val = "*rbcv_var_"
+  func = "rbcv_func_(void)"
   if member
     m << "." << member
-    name = "(((#{type} *)0)->#{member})"
+  else
+    type, member = type.split('.', 2)
   end
-  fmt = "seems %s"
+  if member
+    val = "(#{var}).#{member}"
+  end
+  prelude = [cpp_include(headers).split(/^/)]
+  prelude << ["typedef #{type} rbcv_typedef_;\n",
+              "extern rbcv_typedef_ *#{func};\n",
+              "static rbcv_typedef_ #{var};\n",
+             ]
+  type = "rbcv_typedef_"
+  fmt = member && !(typeof = have_typeof?) ? "seems %s" : "%s"
+  if typeof
+    var = "*rbcv_member_"
+    func = "rbcv_mem_func_(void)"
+    member = nil
+    type = "rbcv_mem_typedef_"
+    prelude[-1] << "typedef #{typeof}(#{val}) #{type};\n"
+    prelude[-1] << "extern #{type} *#{func};\n"
+    prelude[-1] << "static #{type} #{var};\n"
+    val = var
+  end
   def fmt.%(x)
     x ? super : "unknown"
   end
   checking_for checking_message(m, headers), fmt do
-    if scalar_ptr_type?(type, member, headers, &b)
-      if try_static_assert("sizeof(*#{name}) == 1", headers)
-        "string"
+    if scalar_ptr_type?(type, member, prelude, &b)
+      if try_static_assert("sizeof(*#{var}) == 1", prelude)
+        return "string"
       end
-    elsif scalar_type?(type, member, headers, &b)
-      if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
-        "long long"
-      elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
-        "long"
-      elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
-        "int"
-      elsif try_static_assert("sizeof(#{name}) > 1", headers)
-        "short"
-      else
-        "char"
+      ptr = "*"
+    elsif scalar_type?(type, member, prelude, &b)
+      unless member and !typeof or try_static_assert("(#{type})-1 < 0", prelude)
+        unsigned = "unsigned"
       end
+      ptr = ""
+    else
+      next
     end
+    type = UNIVERSAL_INTS.find do |t|
+      pre = prelude
+      unless member
+        pre += [["static #{unsigned} #{t} #{ptr}#{var};\n",
+                 "extern #{unsigned} #{t} #{ptr}*#{func};\n"]]
+      end
+      try_static_assert("sizeof(#{ptr}#{val}) == sizeof(#{unsigned} #{t})", pre)
+    end
+    type or next
+    [unsigned, type, ptr].join(" ").strip
   end
 end
 
@@ -1052,10 +1158,12 @@
 # Internal use only.
 #
 def find_executable0(bin, path = nil)
-  ext = config_string('EXEEXT')
+  exts = config_string('EXECUTABLE_EXTS') {|s| s.split} || config_string('EXEEXT') {|s| [s]}
   if File.expand_path(bin) == bin
     return bin if File.executable?(bin)
-    ext and File.executable?(file = bin + ext) and return file
+    if exts
+      exts.each {|ext| File.executable?(file = bin + ext) and return file}
+    end
     return nil
   end
   if path ||= ENV['PATH']
@@ -1066,7 +1174,9 @@
   file = nil
   path.each do |dir|
     return file if File.executable?(file = File.join(dir, bin))
-    return file if ext and File.executable?(file << ext)
+    if exts
+      exts.each {|ext| File.executable?(ext = file + ext) and return ext}
+    end
   end
   nil
 end
@@ -1166,7 +1276,7 @@
 # 'extconf.h'.
 #
 # For example:
-# 
+#
 #    # extconf.rb
 #    require 'mkmf'
 #    have_func('realpath')
@@ -1188,22 +1298,20 @@
 #
 def create_header(header = "extconf.h")
   message "creating %s\n", header
-    #FIXME: cannot use this in MacRuby yet
-    #sym = header.tr("a-z./\055", "A-Z___")
-    sym = header.tr("a-z", "A-Z").tr("./\055", "_")
+  sym = header.tr_cpp
   hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
-      for line in $defs
-	case line
-	when /^-D([^=]+)(?:=(.*))?/
-      hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n"
-	when /^-U(.*)/
+  for line in $defs
+    case line
+    when /^-D([^=]+)(?:=(.*))?/
+      hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n"
+    when /^-U(.*)/
       hdr << "#undef #$1\n"
-	end
-      end
+    end
+  end
   hdr << "#endif\n"
   hdr = hdr.join
   unless (IO.read(header) == hdr rescue false)
-    open(header, "w") do |hfile|
+    open(header, "wb") do |hfile|
       hfile.write(hdr)
     end
   end
@@ -1232,7 +1340,7 @@
   ldir = with_config(target + "-lib", ldefault)
   $arg_config.last[1] ||= "${#{target}-dir}/lib"
 
-  idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
+  idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : []
   if defaults
     idirs.concat(defaults.collect {|d| d + "/include"})
     idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
@@ -1245,7 +1353,7 @@
     end
   end
 
-  ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
+  ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : []
   if defaults
     ldirs.concat(defaults.collect {|d| d + "/lib"})
     ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
@@ -1263,7 +1371,7 @@
   if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
     # iff package specific config command is given
     get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
-  elsif ($PKGCONFIG ||= 
+  elsif ($PKGCONFIG ||=
          (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
          find_executable0(pkgconfig) && pkgconfig) and
       system("#{$PKGCONFIG} --exists #{pkg}")
@@ -1396,13 +1504,14 @@
 CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
 ldflags  = #{$LDFLAGS}
 dldflags = #{$DLDFLAGS}
-archflag = #{$ARCH_FLAG}
-DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
+ARCH_FLAG = #{$ARCH_FLAG}
+DLDFLAGS = $(ldflags) $(dldflags)
 LDSHARED = #{CONFIG['LDSHARED']}
 LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
 AR = #{CONFIG['AR']}
 EXEEXT = #{CONFIG['EXEEXT']}
 
+RUBY_BASE_NAME = #{CONFIG['RUBY_BASE_NAME']}
 RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
 RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
 arch = #{CONFIG['arch']}
@@ -1442,6 +1551,8 @@
 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
 
 all install static install-so install-rb: Makefile
+.PHONY: all install static install-so install-rb
+.PHONY: clean clean-so clean-rb
 
 RULES
 end
@@ -1526,7 +1637,7 @@
 # Makefile.
 #
 # Setting the +target_prefix+ will, in turn, install the generated binary in
-# a directory under your Config::CONFIG['sitearchdir'] that mimics your local
+# a directory under your RbConfig::CONFIG['sitearchdir'] that mimics your local
 # filesystem when you run 'make install'.
 #
 # For example, given the following file tree:
@@ -1573,26 +1684,27 @@
     target_prefix = ""
   end
 
-  srcprefix ||= '$(srcdir)'
-  RbConfig::expand(srcdir = srcprefix.dup)
+  srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
+  RbConfig.expand(srcdir = srcprefix.dup)
 
+  ext = ".#{$OBJEXT}"
   if not $objs
-    $objs = []
-    srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
-    for f in srcs
-      obj = File.basename(f, ".*") << ".o"
-      $objs.push(obj) unless $objs.index(obj)
+    srcs = $srcs || Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+    objs = srcs.inject(Hash.new {[]}) {|h, f| h[File.basename(f, ".*") << ext] <<= f; h}
+    $objs = objs.keys
+    unless objs.delete_if {|b, f| f.size == 1}.empty?
+      dups = objs.sort.map {|b, f|
+        "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
+      }
+      abort "source files duplication - #{dups.join(", ")}"
     end
-  elsif !(srcs = $srcs)
-    srcs = $objs.collect {|o| o.sub(/\.o\z/, '.c')}
+  else
+    $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
+    srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
   end
   $srcs = srcs
-  for i in $objs
-    i.sub!(/\.o\z/, ".#{$OBJEXT}")
-  end
-  $objs = $objs.join(" ")
 
-  target = nil if $objs == ""
+  target = nil if $objs.empty?
 
   if target and EXPORT_PREFIX
     if File.exist?(File.join(srcdir, target + '.def'))
@@ -1604,7 +1716,7 @@
       makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
     end
     if makedef
-      $distcleanfiles << '$(DEFFILE)'
+      $cleanfiles << '$(DEFFILE)'
       origdef = deffile
       deffile = "$(TARGET)-$(arch).def"
     end
@@ -1625,7 +1737,9 @@
   dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
   staticlib = target ? "$(TARGET).#$LIBEXT" : ""
   mfile = open("Makefile", "wb")
-  mfile.print(*configuration(srcprefix))
+  conf = configuration(srcprefix)
+  conf = yield(conf) if block_given?
+  mfile.puts(conf)
   mfile.print "
 libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
 LIBPATH = #{libpath}
@@ -1635,13 +1749,13 @@
 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
 DISTCLEANDIRS = #{$distcleandirs.join(' ')}
 
-extout = #{$extout}
+extout = #{$extout && $extout.quote}
 extout_prefix = #{$extout_prefix}
 target_prefix = #{target_prefix}
 LOCAL_LIBS = #{$LOCAL_LIBS}
 LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
 SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
-OBJS = #{$objs}
+OBJS = #{$objs.join(" ")}
 TARGET = #{target}
 DLLIB = #{dllib}
 EXTSTATIC = #{$static || ""}
@@ -1654,10 +1768,12 @@
   mfile.print "
 TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
 CLEANLIBS     = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
-CLEANOBJS     = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, '$(TARGET)')}} *.bak
+CLEANOBJS     = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
 
 all:    #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
 static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
+.PHONY: all install static install-so install-rb
+.PHONY: clean clean-so clean-rb
 "
   mfile.print CLEANINGS
   fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
@@ -1685,8 +1801,8 @@
       mfile.print "\t at -$(RM) #{fseprepl[dest]}\n"
       mfile.print "\t at -$(RMDIRS) #{fseprepl[dir]}\n"
     else
-      mfile.print "#{dest}: #{f}\n"
-      mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} #{fseprepl[dir]}\n"
+      mfile.print "#{dest}: #{f}\n\t at -$(MAKEDIRS) $(@D#{sep})\n"
+      mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} $(@D#{sep})\n"
       if defined?($installed_list)
 	mfile.print "\t at echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
       end
@@ -1708,9 +1824,8 @@
       for f in files
 	dest = "#{dir}/#{File.basename(f)}"
 	mfile.print("install-rb#{sfx}: #{dest}\n")
-        mfile.print("#{dest}: #{f}\n")
-        mfile.print("\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
-	mfile.print("#{fseprepl[f]} $(@D#{sep})\n")
+	mfile.print("#{dest}: #{f}\n\t at -$(MAKEDIRS) $(@D#{sep})\n")
+	mfile.print("\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D#{sep})\n")
 	if defined?($installed_list) and !$extout
 	  mfile.print("\t at echo #{dest}>>$(INSTALLED_LIST)\n")
 	end
@@ -1722,10 +1837,9 @@
     end
     if $extout
       dirs.uniq!
-      dirs.reverse!
       unless dirs.empty?
         mfile.print("clean-rb#{sfx}::\n")
-        for dir in dirs
+        for dir in dirs.sort_by {|d| -d.count('/')}
           mfile.print("\t at -$(RMDIRS) #{fseprepl[dir]}\n")
         end
       end
@@ -1744,19 +1858,19 @@
 
   return unless target
 
-  mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
+  mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b
   mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
   mfile.print "\n"
 
-  CXX_EXT.each do |ext|
+  CXX_EXT.each do |e|
     COMPILE_RULES.each do |rule|
-      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf(rule, e, $OBJEXT)
       mfile.printf("\n\t%s\n\n", COMPILE_CXX)
     end
   end
-  %w[c].each do |ext|
+  %w[c].each do |e|
     COMPILE_RULES.each do |rule|
-      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf(rule, e, $OBJEXT)
       mfile.printf("\n\t%s\n\n", COMPILE_C)
     end
   end
@@ -1825,7 +1939,7 @@
   $LIBRUBYARG = ""
   $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
   $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
-  $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
+  $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(libdir)"]
   $DEFLIBPATH.unshift(".")
   $LIBPATH = []
   $INSTALLFILES = []
@@ -1936,8 +2050,10 @@
 RPATHFLAG = config_string('RPATHFLAG') || ''
 LIBARG = config_string('LIBARG') || '-l%s'
 MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || 'int main() {return 0;}'
+UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
+  %w[int short long long\ long]
 
-sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if sep != "/"} || ""
+sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
 CLEANINGS = "
 clean-rb-default::
 clean-rb::

Modified: MacRuby/trunk/lib/monitor.rb
===================================================================
--- MacRuby/trunk/lib/monitor.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/monitor.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -12,11 +12,11 @@
 This is a simple example.
 
   require 'monitor.rb'
-  
+
   buf = []
   buf.extend(MonitorMixin)
   empty_cond = buf.new_cond
-  
+
   # consumer
   Thread.start do
     loop do
@@ -26,7 +26,7 @@
       end
     end
   end
-  
+
   # producer
   while line = ARGF.gets
     buf.synchronize do
@@ -49,11 +49,11 @@
 # +include+.  For example:
 #
 #    require 'monitor'
-#    
+#
 #    buf = []
 #    buf.extend(MonitorMixin)
 #    empty_cond = buf.new_cond
-#    
+#
 #    # consumer
 #    Thread.start do
 #      loop do
@@ -63,7 +63,7 @@
 #        end
 #      end
 #    end
-#    
+#
 #    # producer
 #    while line = ARGF.gets
 #      buf.synchronize do
@@ -71,7 +71,7 @@
 #        empty_cond.signal
 #      end
 #    end
-# 
+#
 # The consumer thread waits for the producer thread to push a line
 # to buf while buf.empty?, and the producer thread (main thread)
 # reads a line from ARGF and push it to buf, then call
@@ -86,47 +86,58 @@
   #
   class ConditionVariable
     class Timeout < Exception; end
-    
+
+    #
+    # Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup.
+    #
+    # If +timeout+ is given, this method returns after +timeout+ seconds passed,
+    # even if no other thread doesn't signal.
+    #
     def wait(timeout = nil)
-      if timeout
-        raise NotImplementedError, "timeout is not implemented yet"
-      end
-      @monitor.send(:mon_check_owner)
-      count = @monitor.send(:mon_exit_for_cond)
+      @monitor.__send__(:mon_check_owner)
+      count = @monitor.__send__(:mon_exit_for_cond)
       begin
-        @cond.wait(@monitor.instance_variable_get("@mon_mutex"))
+        @cond.wait(@monitor.instance_variable_get("@mon_mutex"), timeout)
         return true
       ensure
-        @monitor.send(:mon_enter_for_cond, count)
+        @monitor.__send__(:mon_enter_for_cond, count)
       end
     end
-    
+
+    #
+    # Calls wait repeatedly while the given block yields a truthy value.
+    #
     def wait_while
       while yield
 	wait
       end
     end
-    
+
+    #
+    # Calls wait repeatedly until the given block yields a truthy value.
+    #
     def wait_until
       until yield
 	wait
       end
     end
-    
+
+    #
+    # Wakes up the first thread in line waiting for this lock.
+    #
     def signal
-      @monitor.send(:mon_check_owner)
+      @monitor.__send__(:mon_check_owner)
       @cond.signal
     end
-    
+
+    #
+    # Wakes up all threads waiting for this lock.
+    #
     def broadcast
-      @monitor.send(:mon_check_owner)
+      @monitor.__send__(:mon_check_owner)
       @cond.broadcast
     end
-    
-    def count_waiters
-      raise NotImplementedError
-    end
-    
+
     private
 
     def initialize(monitor)
@@ -134,12 +145,12 @@
       @cond = ::ConditionVariable.new
     end
   end
-  
+
   def self.extend_object(obj)
     super(obj)
-    obj.send(:mon_initialize)
+    obj.__send__(:mon_initialize)
   end
-  
+
   #
   # Attempts to enter exclusive section.  Returns +false+ if lock fails.
   #
@@ -166,7 +177,7 @@
     end
     @mon_count += 1
   end
-  
+
   #
   # Leaves exclusive section.
   #
@@ -193,9 +204,10 @@
     end
   end
   alias synchronize mon_synchronize
-  
+
   #
-  # FIXME: This isn't documented in Nutshell.
+  # Creates a new MonitorMixin::ConditionVariable associated with the
+  # receiver.
   #
   def new_cond
     return ConditionVariable.new(self)

Modified: MacRuby/trunk/lib/mutex_m.rb
===================================================================
--- MacRuby/trunk/lib/mutex_m.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/mutex_m.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,5 @@
 #
-#   mutex_m.rb - 
+#   mutex_m.rb -
 #   	$Release Version: 3.0$
 #   	$Revision: 1.7 $
 #       Original from mutex.rb
@@ -34,13 +34,13 @@
       alias try_lock mu_try_lock
       alias synchronize mu_synchronize
     }
-  end  
+  end
 
   def Mutex_m.append_features(cl)
     super
     define_aliases(cl) unless cl.instance_of?(Module)
   end
-  
+
   def Mutex_m.extend_object(obj)
     super
     obj.mu_extended
@@ -56,30 +56,30 @@
     end
     mu_initialize
   end
-  
-  # locking 
+
+  # locking
   def mu_synchronize(&block)
     @_mutex.synchronize(&block)
   end
-  
+
   def mu_locked?
     @_mutex.locked?
   end
-  
+
   def mu_try_lock
     @_mutex.try_lock
   end
-  
+
   def mu_lock
     @_mutex.lock
   end
-  
+
   def mu_unlock
     @_mutex.unlock
   end
-  
+
   private
-  
+
   def mu_initialize
     @_mutex = Mutex.new
   end

Modified: MacRuby/trunk/lib/net/ftp.rb
===================================================================
--- MacRuby/trunk/lib/net/ftp.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/ftp.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,11 +1,11 @@
-# 
+#
 # = net/ftp.rb - FTP Client Library
-# 
+#
 # Written by Shugo Maeda <shugo at ruby-lang.org>.
 #
 # Documentation by Gavin Sinclair, sourced from "Programming Ruby" (Hunt/Thomas)
 # and "Ruby In a Nutshell" (Matsumoto), used with permission.
-# 
+#
 # This library is distributed under the terms of the Ruby license.
 # You can freely distribute/modify this library.
 #
@@ -22,9 +22,10 @@
   # :stopdoc:
   class FTPError < StandardError; end
   class FTPReplyError < FTPError; end
-  class FTPTempError < FTPError; end 
-  class FTPPermError < FTPError; end 
+  class FTPTempError < FTPError; end
+  class FTPPermError < FTPError; end
   class FTPProtoError < FTPError; end
+  class FTPConnectionError < FTPError; end
   # :startdoc:
 
   #
@@ -34,11 +35,11 @@
   # advantage of Ruby's style and strengths.
   #
   # == Example
-  # 
+  #
   #   require 'net/ftp'
   #
   # === Example 1
-  #  
+  #
   #   ftp = Net::FTP.new('ftp.netlab.co.jp')
   #   ftp.login
   #   files = ftp.chdir('pub/lang/ruby/contrib')
@@ -71,13 +72,13 @@
   #
   class FTP
     include MonitorMixin
-    
+
     # :stopdoc:
     FTP_PORT = 21
     CRLF = "\r\n"
     DEFAULT_BLOCKSIZE = 4096
     # :startdoc:
-    
+
     # When +true+, transfers are performed in binary mode.  Default: +true+.
     attr_reader :binary
 
@@ -101,7 +102,7 @@
 
     # The server's last response.
     attr_reader :last_response
-    
+
     #
     # A synonym for <tt>FTP.new</tt>, but with a mandatory host parameter.
     #
@@ -120,7 +121,7 @@
         new(host, user, passwd, acct)
       end
     end
-    
+
     #
     # Creates and returns a new +FTP+ object. If a +host+ is given, a connection
     # is made. Additionally, if the +user+ is given, the given user name,
@@ -128,10 +129,12 @@
     #
     def initialize(host = nil, user = nil, passwd = nil, acct = nil)
       super()
-      @binary = false
+      @binary = true
       @passive = false
       @debug_mode = false
       @resume = false
+      @sock = NullSocket.new
+      @logged_in = false
       if host
 	connect(host)
 	if user
@@ -143,10 +146,19 @@
     def binary=(newmode)
       if newmode != @binary
         @binary = newmode
-        @binary ? voidcmd("TYPE I") : voidcmd("TYPE A")
+        send_type_command if @logged_in
       end
     end
 
+    def send_type_command
+      if @binary
+        voidcmd("TYPE I")
+      else
+        voidcmd("TYPE A")
+      end
+    end
+    private :send_type_command
+
     def with_binary(newmode)
       oldmode = binary
       self.binary = newmode
@@ -178,7 +190,7 @@
       end
     end
     private :open_socket
-    
+
     #
     # Establishes an FTP connection to host, optionally overriding the default
     # port. If the environment variable +SOCKS_SERVER+ is set, sets up the
@@ -215,7 +227,7 @@
       end
     end
     private :sanitize
-    
+
     def putline(line)
       if @debug_mode
 	print "put: ", sanitize(line), "\n"
@@ -224,7 +236,7 @@
       @sock.write(line)
     end
     private :putline
-    
+
     def getline
       line = @sock.readline # if get EOF, raise EOFError
       line.sub!(/(\r\n|\n|\r)\z/n, "")
@@ -234,7 +246,7 @@
       return line
     end
     private :getline
-    
+
     def getmultiline
       line = getline
       buff = line
@@ -248,7 +260,7 @@
       return buff << "\n"
     end
     private :getmultiline
-    
+
     def getresp
       @last_response = getmultiline
       @last_response_code = @last_response[0, 3]
@@ -264,7 +276,7 @@
       end
     end
     private :getresp
-    
+
     def voidresp
       resp = getresp
       if resp[0] != ?2
@@ -272,7 +284,7 @@
       end
     end
     private :voidresp
-    
+
     #
     # Sends a command and returns the response.
     #
@@ -282,7 +294,7 @@
 	return getresp
       end
     end
-    
+
     #
     # Sends a command and expect a response beginning with '2'.
     #
@@ -292,7 +304,7 @@
 	voidresp
       end
     end
-    
+
     def sendport(host, port)
       af = (@sock.peeraddr)[0]
       if af == "AF_INET"
@@ -305,7 +317,7 @@
       voidcmd(cmd)
     end
     private :sendport
-    
+
     def makeport
       sock = TCPServer.open(@sock.addr[3], 0)
       port = sock.addr[1]
@@ -314,7 +326,7 @@
       return sock
     end
     private :makeport
-    
+
     def makepasv
       if @sock.peeraddr[0] == "AF_INET"
 	host, port = parse227(sendcmd("PASV"))
@@ -325,13 +337,13 @@
       return host, port
     end
     private :makepasv
-    
+
     def transfercmd(cmd, rest_offset = nil)
       if @passive
 	host, port = makepasv
 	conn = open_socket(host, port)
 	if @resume and rest_offset
-	  resp = sendcmd("REST " + rest_offset.to_s) 
+	  resp = sendcmd("REST " + rest_offset.to_s)
 	  if resp[0] != ?3
 	    raise FTPReplyError, resp
 	  end
@@ -345,7 +357,7 @@
       else
 	sock = makeport
 	if @resume and rest_offset
-	  resp = sendcmd("REST " + rest_offset.to_s) 
+	  resp = sendcmd("REST " + rest_offset.to_s)
 	  if resp[0] != ?3
 	    raise FTPReplyError, resp
 	  end
@@ -362,23 +374,7 @@
       return conn
     end
     private :transfercmd
-    
-    def getaddress
-      thishost = Socket.gethostname
-      if not thishost.index(".")
-	thishost = Socket.gethostbyname(thishost)[0]
-      end
-      if ENV.has_key?("LOGNAME")
-	realuser = ENV["LOGNAME"]
-      elsif ENV.has_key?("USER")
-	realuser = ENV["USER"]
-      else
-	realuser = "anonymous"
-      end
-      return realuser + "@" + thishost
-    end
-    private :getaddress
-    
+
     #
     # Logs in to the remote host. The session must have been previously
     # connected.  If +user+ is the string "anonymous" and the +password+ is
@@ -389,9 +385,9 @@
     #
     def login(user = "anonymous", passwd = nil, acct = nil)
       if user == "anonymous" and passwd == nil
-	passwd = getaddress
+	passwd = "anonymous@"
       end
-      
+
       resp = ""
       synchronize do
 	resp = sendcmd('USER ' + user)
@@ -408,9 +404,10 @@
 	raise FTPReplyError, resp
       end
       @welcome = resp
-      self.binary = true
+      send_type_command
+      @logged_in = true
     end
-    
+
     #
     # Puts the connection into binary (image) mode, issues the given command,
     # and fetches the data returned, passing it to the associated block in
@@ -431,7 +428,7 @@
         end
       end
     end
-    
+
     #
     # Puts the connection into ASCII (text) mode, issues the given command, and
     # passes the resulting data, one line at a time, to the associated block. If
@@ -445,19 +442,14 @@
           loop do
             line = conn.gets
             break if line == nil
-            if line[-2, 2] == CRLF
-              line = line[0 .. -3]
-            elsif line[-1] == ?\n
-              line = line[0 .. -2]
-            end
-            yield(line)
+            yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?)
           end
           conn.close
           voidresp
         end
       end
     end
-    
+
     #
     # Puts the connection into binary (image) mode, issues the given server-side
     # command (such as "STOR myfile"), and sends the contents of the file named
@@ -470,7 +462,7 @@
       end
       synchronize do
 	with_binary(true) do
-          conn = transfercmd(cmd, rest_offset)
+          conn = transfercmd(cmd)
           loop do
             buf = file.read(blocksize)
             break if buf == nil
@@ -489,7 +481,7 @@
       getresp
       raise
     end
-    
+
     #
     # Puts the connection into ASCII (text) mode, issues the given server-side
     # command (such as "STOR myfile"), and sends the contents of the file
@@ -544,7 +536,7 @@
       end
       begin
 	f.binmode if localfile
-	retrbinary("RETR " + remotefile, blocksize, rest_offset) do |data|
+	retrbinary("RETR " + remotefile.to_s, blocksize, rest_offset) do |data|
 	  f.write(data) if localfile
 	  yield(data) if block_given?
           result.concat(data) if result
@@ -554,7 +546,7 @@
 	f.close if localfile
       end
     end
-    
+
     #
     # Retrieves +remotefile+ in ASCII (text) mode, storing the result in
     # +localfile+.
@@ -570,10 +562,11 @@
         result = ""
       end
       begin
-	retrlines("RETR " + remotefile) do |line|
-	  f.puts(line) if localfile
-	  yield(line) if block_given?
-          result.concat(line + "\n") if result
+	retrlines("RETR " + remotefile) do |line, newline|
+          l = newline ? line + "\n" : line
+	  f.print(l) if localfile
+	  yield(line, newline) if block_given?
+          result.concat(l) if result
 	end
         return result
       ensure
@@ -593,7 +586,7 @@
 	gettextfile(remotefile, localfile, &block)
       end
     end
-    
+
     #
     # Transfers +localfile+ to the server in binary mode, storing the result in
     # +remotefile+. If a block is supplied, calls it, passing in the transmitted
@@ -613,12 +606,16 @@
       f = open(localfile)
       begin
 	f.binmode
-	storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
+        if rest_offset
+          storbinary("APPE " + remotefile, f, blocksize, rest_offset, &block)
+        else
+          storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
+        end
       ensure
 	f.close
       end
     end
-    
+
     #
     # Transfers +localfile+ to the server in ASCII (text) mode, storing the result
     # in +remotefile+. If callback or an associated block is supplied, calls it,
@@ -653,7 +650,7 @@
       cmd = "ACCT " + account
       voidcmd(cmd)
     end
-    
+
     #
     # Returns an array of filenames in the remote directory.
     #
@@ -668,7 +665,7 @@
       end
       return files
     end
-    
+
     #
     # Returns an array of file information in the directory (the output is like
     # `ls -l`).  If a block is given, it iterates through the listing.
@@ -676,7 +673,7 @@
     def list(*args, &block) # :yield: line
       cmd = "LIST"
       args.each do |arg|
-	cmd = cmd + " " + arg
+	cmd = cmd + " " + arg.to_s
       end
       if block
 	retrlines(cmd, &block)
@@ -690,7 +687,7 @@
     end
     alias ls list
     alias dir list
-    
+
     #
     # Renames a file on the server.
     #
@@ -701,7 +698,7 @@
       end
       voidcmd("RNTO " + toname)
     end
-    
+
     #
     # Deletes a file on the server.
     #
@@ -715,7 +712,7 @@
 	raise FTPReplyError, resp
       end
     end
-    
+
     #
     # Changes the (remote) directory.
     #
@@ -733,22 +730,22 @@
       cmd = "CWD " + dirname
       voidcmd(cmd)
     end
-    
+
     #
     # Returns the size of the given (remote) filename.
     #
     def size(filename)
       with_binary(true) do
         resp = sendcmd("SIZE " + filename)
-        if resp[0, 3] != "213" 
+        if resp[0, 3] != "213"
           raise FTPReplyError, resp
         end
         return resp[3..-1].strip.to_i
       end
     end
-    
+
     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
     # +true+, it is returned as a local time, otherwise it's a UTC time.
@@ -758,7 +755,7 @@
       ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i}
       return local ? Time.local(*ary) : Time.gm(*ary)
     end
-    
+
     #
     # Creates a remote directory.
     #
@@ -766,14 +763,14 @@
       resp = sendcmd("MKD " + dirname)
       return parse257(resp)
     end
-    
+
     #
     # Removes a remote directory.
     #
     def rmdir(dirname)
       voidcmd("RMD " + dirname)
     end
-    
+
     #
     # Returns the current remote directory.
     #
@@ -782,7 +779,7 @@
       return parse257(resp)
     end
     alias getdir pwd
-    
+
     #
     # Returns system information.
     #
@@ -793,7 +790,7 @@
       end
       return resp[4 .. -1]
     end
-    
+
     #
     # Aborts the previous command (ABOR command).
     #
@@ -807,7 +804,7 @@
       end
       return resp
     end
-    
+
     #
     # Returns the status (STAT command).
     #
@@ -817,7 +814,7 @@
       @sock.send(line, Socket::MSG_OOB)
       return getresp
     end
-    
+
     #
     # Issues the MDTM command.  TODO: more info.
     #
@@ -827,7 +824,7 @@
 	return resp[3 .. -1].strip
       end
     end
-    
+
     #
     # Issues the HELP command.
     #
@@ -838,7 +835,7 @@
       end
       sendcmd(cmd)
     end
-    
+
     #
     # Exits the FTP session.
     #
@@ -860,7 +857,7 @@
       cmd = "SITE " + arg
       voidcmd(cmd)
     end
-    
+
     #
     # Closes the connection.  Further operations are impossible until you open
     # a new connection with #connect.
@@ -868,14 +865,14 @@
     def close
       @sock.close if @sock and not @sock.closed?
     end
-    
+
     #
     # Returns +true+ iff the connection is closed.
     #
     def closed?
       @sock == nil or @sock.closed?
     end
-    
+
     def parse227(resp)
       if resp[0, 3] != "227"
 	raise FTPReplyError, resp
@@ -894,7 +891,7 @@
       return host, port
     end
     private :parse227
-    
+
     def parse228(resp)
       if resp[0, 3] != "228"
 	raise FTPReplyError, resp
@@ -922,11 +919,11 @@
 	end
 	host = v6[0, 8].join(":")
 	port = (numbers[19].to_i << 8) + numbers[20].to_i
-      end 
+      end
       return host, port
     end
     private :parse228
-    
+
     def parse229(resp)
       if resp[0, 3] != "229"
 	raise FTPReplyError, resp
@@ -945,7 +942,7 @@
       return host, port
     end
     private :parse229
-    
+
     def parse257(resp)
       if resp[0, 3] != "257"
 	raise FTPReplyError, resp
@@ -970,8 +967,15 @@
       return dirname
     end
     private :parse257
+
+    # :stopdoc:
+    class NullSocket
+      def method_missing(mid, *args)
+        raise FTPConnectionError, "not connected"
+      end
+    end
+    # :startdoc:
   end
-
 end
 
 

Modified: MacRuby/trunk/lib/net/http.rb
===================================================================
--- MacRuby/trunk/lib/net/http.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/http.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -22,7 +22,7 @@
 # http://www.ruby-lang.org/ja/man/html/net_http.html
 #
 #--
-# $Id$
+# $Id: http.rb 27605 2010-05-03 23:42:26Z mame $
 #++
 
 require 'net/protocol'
@@ -285,7 +285,7 @@
   class HTTP < Protocol
 
     # :stopdoc:
-    Revision = %q$Revision$.split[1]
+    Revision = %q$Revision: 27605 $.split[1]
     HTTPVersion = '1.1'
     @newimpl = true
     begin

Modified: MacRuby/trunk/lib/net/https.rb
===================================================================
--- MacRuby/trunk/lib/net/https.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/https.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,6 +1,6 @@
 =begin
 
-= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
+= net/https -- SSL/TLS enhancement for Net::HTTP.
 
 == Info
   'OpenSSL for Ruby 2' project
@@ -11,16 +11,6 @@
   This program is licenced under the same licence as Ruby.
   (See the file 'LICENCE'.)
 
-== Requirements
-  This program requires Net 1.2.0 or higher version.
-  You can get it from RAA or Ruby's CVS repository.
-
-== Version
-  $Id: https.rb 18512 2008-08-12 05:20:09Z aamine $
-  
-  2001-11-06: Contiributed to Ruby/OpenSSL project.
-  2004-03-06: Some code is merged in to net/http.
-
 == Example
 
 Here is a simple HTTP client:
@@ -73,7 +63,7 @@
 
 : ca_file, ca_file=((|path|))
     Sets path of a CA certification file in PEM format.
-    The file can contrain several CA certificats.
+    The file can contrain several CA certificates.
 
 : ca_path, ca_path=((|path|))
     Sets path of a CA certification directory containing certifications
@@ -81,7 +71,7 @@
 
 : verify_mode, verify_mode=((|mode|))
     Sets the flags for server the certification verification at
-    begining of SSL/TLS session.
+    beginning of SSL/TLS session.
     OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
 
 : verify_callback, verify_callback=((|proc|))
@@ -100,37 +90,3 @@
 
 require 'net/http'
 require 'openssl'
-
-module Net
-  class HTTP
-    remove_method :use_ssl?
-    def use_ssl?
-      @use_ssl
-    end
-
-    # Turn on/off SSL.
-    # This flag must be set before starting session.
-    # If you change use_ssl value after session started,
-    # a Net::HTTP object raises IOError.
-    def use_ssl=(flag)
-      flag = (flag ? true : false)
-      if started? and @use_ssl != flag
-        raise IOError, "use_ssl value changed, but session already started"
-      end
-      @use_ssl = flag
-    end
-
-    SSL_ATTRIBUTES = %w(
-      ssl_version key cert ca_file ca_path cert_store ciphers
-      verify_mode verify_callback verify_depth ssl_timeout
-    )
-    attr_accessor(*SSL_ATTRIBUTES)
-
-    def peer_cert
-      if not use_ssl? or not @socket
-        return nil
-      end
-      @socket.io.peer_cert
-    end
-  end
-end

Modified: MacRuby/trunk/lib/net/imap.rb
===================================================================
--- MacRuby/trunk/lib/net/imap.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/imap.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,7 +9,7 @@
 # Documentation: Shugo Maeda, with RDoc conversion and overview by William
 # Webber.
 #
-# See Net::IMAP for documentation. 
+# See Net::IMAP for documentation.
 #
 
 
@@ -18,7 +18,7 @@
 require "digest/md5"
 require "strscan"
 begin
-  require "openssl/ssl"
+  require "openssl"
 rescue LoadError
 end
 
@@ -45,12 +45,12 @@
   # read-only access) #examine().  Once the client has successfully
   # selected a mailbox, they enter _selected_ state, and that
   # mailbox becomes the _current_ mailbox, on which mail-item
-  # related commands implicitly operate.  
+  # related commands implicitly operate.
   #
   # Messages have two sorts of identifiers: message sequence
-  # numbers, and UIDs.  
+  # numbers, and UIDs.
   #
-  # Message sequence numbers number messages within a mail box 
+  # Message sequence numbers number messages within a mail box
   # from 1 up to the number of items in the mail box.  If new
   # message arrives during a session, it receives a sequence
   # number equal to the new size of the mail box.  If messages
@@ -58,7 +58,7 @@
   # sequence numbers "shuffled down" to fill the gaps.
   #
   # UIDs, on the other hand, are permanently guaranteed not to
-  # identify another message within the same mailbox, even if 
+  # identify another message within the same mailbox, even if
   # the existing message is deleted.  UIDs are required to
   # be assigned in ascending (but not necessarily sequential)
   # order within a mailbox; this means that if a non-IMAP client
@@ -91,11 +91,11 @@
   #     imap.store(message_id, "+FLAGS", [:Deleted])
   #   end
   #   imap.expunge
-  # 
+  #
   # == Thread Safety
   #
   # Net::IMAP supports concurrent threads. For example,
-  # 
+  #
   #   imap = Net::IMAP.new("imap.foo.net", "imap2")
   #   imap.authenticate("cram-md5", "bar", "password")
   #   imap.select("inbox")
@@ -103,7 +103,7 @@
   #   search_result = imap.search(["BODY", "hello"])
   #   fetch_result = fetch_thread.value
   #   imap.disconnect
-  # 
+  #
   # This script invokes the FETCH command and the SEARCH command concurrently.
   #
   # == Errors
@@ -113,9 +113,9 @@
   #
   # NO:: the attempted command could not be successfully completed.  For
   #      instance, the username/password used for logging in are incorrect;
-  #      the selected mailbox does not exists; etc.  
+  #      the selected mailbox does not exists; etc.
   #
-  # BAD:: the request from the client does not follow the server's 
+  # BAD:: the request from the client does not follow the server's
   #       understanding of the IMAP protocol.  This includes attempting
   #       commands from the wrong client state; for instance, attempting
   #       to perform a SEARCH command without having SELECTed a current
@@ -147,8 +147,8 @@
   #
   # Finally, a Net::IMAP::DataFormatError is thrown if low-level data
   # is found to be in an incorrect format (for instance, when converting
-  # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is 
-  # thrown if a server response is non-parseable. 
+  # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
+  # thrown if a server response is non-parseable.
   #
   #
   # == References
@@ -270,15 +270,25 @@
       return @@debug = val
     end
 
+    # Returns the max number of flags interned to symbols.
+    def self.max_flag_count
+      return @@max_flag_count
+    end
+
+    # Sets the max number of flags interned to symbols.
+    def self.max_flag_count=(count)
+      @@max_flag_count = count
+    end
+
     # Adds an authenticator for Net::IMAP#authenticate.  +auth_type+
     # is the type of authentication this authenticator supports
     # (for instance, "LOGIN").  The +authenticator+ is an object
     # which defines a process() method to handle authentication with
-    # the server.  See Net::IMAP::LoginAuthenticator, 
+    # the server.  See Net::IMAP::LoginAuthenticator,
     # Net::IMAP::CramMD5Authenticator, and Net::IMAP::DigestMD5Authenticator
     # for examples.
-    # 
     #
+    #
     # If +auth_type+ refers to an existing authenticator, it will be
     # replaced by the new one.
     def self.add_authenticator(auth_type, authenticator)
@@ -297,9 +307,12 @@
         end
       rescue Errno::ENOTCONN
         # ignore `Errno::ENOTCONN: Socket is not connected' on some platforms.
+      rescue Exception => e
+        @receiver_thread.raise(e)
       end
       @receiver_thread.join
       @sock.close
+      raise e if e
     end
 
     # Returns true if disconnected from the server.
@@ -314,7 +327,7 @@
     #
     # Note that the Net::IMAP class does not modify its
     # behaviour according to the capabilities of the server;
-    # it is up to the user of the class to ensure that 
+    # it is up to the user of the class to ensure that
     # a certain capability is supported by a server before
     # using it.
     def capability
@@ -355,7 +368,7 @@
     # the authentication mechanism to be used. Currently Net::IMAP
     # supports authentication mechanisms:
     #
-    #   LOGIN:: login using cleartext user and password. 
+    #   LOGIN:: login using cleartext user and password.
     #   CRAM-MD5:: login with cleartext user and encrypted password
     #              (see [RFC-2195] for a full description).  This
     #              mechanism requires that the server have the user's
@@ -403,7 +416,7 @@
     end
 
     # Sends a SELECT command to select a +mailbox+ so that messages
-    # in the +mailbox+ can be accessed. 
+    # in the +mailbox+ can be accessed.
     #
     # After you have selected a mailbox, you may retrieve the
     # number of items in that mailbox from @responses["EXISTS"][-1],
@@ -454,7 +467,7 @@
     # Sends a RENAME command to change the name of the +mailbox+ to
     # +newname+.
     #
-    # A Net::IMAP::NoResponseError is raised if a mailbox with the 
+    # A Net::IMAP::NoResponseError is raised if a mailbox with the
     # name +mailbox+ cannot be renamed to +newname+ for whatever
     # reason; for instance, because +mailbox+ does not exist, or
     # because there is already a mailbox with the name +newname+.
@@ -501,8 +514,8 @@
     #   imap.create("foo/bar")
     #   imap.create("foo/baz")
     #   p imap.list("", "foo/%")
-    #   #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\ 
-    #        #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\ 
+    #   #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
+    #        #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
     #        #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
     def list(refname, mailbox)
       synchronize do
@@ -555,7 +568,7 @@
     # then that user will be stripped of any rights to that mailbox.
     # The IMAP ACL commands are described in [RFC-2086].
     def setacl(mailbox, user, rights)
-      if rights.nil? 
+      if rights.nil?
         send_command("SETACL", mailbox, user, "")
       else
         send_command("SETACL", mailbox, user, rights)
@@ -574,7 +587,7 @@
 
     # Sends a LSUB command, and returns a subset of names from the set
     # of names that the user has declared as being "active" or
-    # "subscribed".  +refname+ and +mailbox+ are interpreted as 
+    # "subscribed".  +refname+ and +mailbox+ are interpreted as
     # for #list().
     # The return value is an array of +Net::IMAP::MailboxList+.
     def lsub(refname, mailbox)
@@ -597,7 +610,7 @@
     #   p imap.status("inbox", ["MESSAGES", "RECENT"])
     #   #=> {"RECENT"=>0, "MESSAGES"=>44}
     #
-    # A Net::IMAP::NoResponseError is raised if status values 
+    # A Net::IMAP::NoResponseError is raised if status values
     # for +mailbox+ cannot be returned, for instance because it
     # does not exist.
     def status(mailbox, attr)
@@ -608,9 +621,9 @@
     end
 
     # Sends a APPEND command to append the +message+ to the end of
-    # the +mailbox+. The optional +flags+ argument is an array of 
+    # the +mailbox+. The optional +flags+ argument is an array of
     # flags to initially passing to the new message.  The optional
-    # +date_time+ argument specifies the creation time to assign to the 
+    # +date_time+ argument specifies the creation time to assign to the
     # new message; it defaults to the current time.
     # For example:
     #
@@ -618,7 +631,7 @@
     #   Subject: hello
     #   From: shugo at ruby-lang.org
     #   To: shugo at ruby-lang.org
-    #   
+    #
     #   hello world
     #   EOF
     #
@@ -637,7 +650,7 @@
 
     # Sends a CHECK command to request a checkpoint of the currently
     # selected mailbox.  This performs implementation-specific
-    # housekeeping, for instance, reconciling the mailbox's 
+    # housekeeping, for instance, reconciling the mailbox's
     # in-memory and on-disk state.
     def check
       send_command("CHECK")
@@ -661,8 +674,8 @@
 
     # Sends a SEARCH command to search the mailbox for messages that
     # match the given searching criteria, and returns message sequence
-    # numbers.  +keys+ can either be a string holding the entire 
-    # search string, or a single-dimension array of search keywords and 
+    # numbers.  +keys+ can either be a string holding the entire
+    # search string, or a single-dimension array of search keywords and
     # arguments.  The following are some common search criteria;
     # see [IMAP] section 6.4.4 for a full list.
     #
@@ -686,7 +699,7 @@
     #
     # OR <search-key> <search-key>:: "or" two search keys together.
     #
-    # ON <date>:: messages with an internal date exactly equal to <date>, 
+    # ON <date>:: messages with an internal date exactly equal to <date>,
     #             which has a format similar to 8-Aug-2002.
     #
     # SINCE <date>:: messages with an internal date on or after <date>.
@@ -694,7 +707,7 @@
     # SUBJECT <string>:: messages with <string> in their subject.
     #
     # TO <string>:: messages with <string> in their TO field.
-    # 
+    #
     # For example:
     #
     #   p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
@@ -717,8 +730,8 @@
     # The return value is an array of Net::IMAP::FetchData. For example:
     #
     #   p imap.fetch(6..8, "UID")
-    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\ 
-    #        #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\ 
+    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
+    #        #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\
     #        #<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
     #   p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
     #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
@@ -741,9 +754,9 @@
     end
 
     # Sends a STORE command to alter data associated with messages
-    # in the mailbox, in particular their flags. The +set+ parameter 
-    # is a number or an array of numbers or a Range object. Each number 
-    # is a message sequence number.  +attr+ is the name of a data item 
+    # in the mailbox, in particular their flags. The +set+ parameter
+    # is a number or an array of numbers or a Range object. Each number
+    # is a message sequence number.  +attr+ is the name of a data item
     # to store: 'FLAGS' means to replace the message's flag list
     # with the provided one; '+FLAGS' means to add the provided flags;
     # and '-FLAGS' means to remove them.  +flags+ is a list of flags.
@@ -751,8 +764,8 @@
     # The return value is an array of Net::IMAP::FetchData. For example:
     #
     #   p imap.store(6..8, "+FLAGS", [:Deleted])
-    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\ 
-    #        #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\  
+    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
+    #        #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
     #        #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
     def store(set, attr, flags)
       return store_internal("STORE", set, attr, flags)
@@ -794,9 +807,9 @@
       return sort_internal("UID SORT", sort_keys, search_keys, charset)
     end
 
-    # Adds a response handler. For example, to detect when 
+    # Adds a response handler. For example, to detect when
     # the server sends us a new EXISTS response (which normally
-    # indicates new messages being added to the mail box), 
+    # indicates new messages being added to the mail box),
     # you could add the following handler after selecting the
     # mailbox.
     #
@@ -832,12 +845,50 @@
       return thread_internal("THREAD", algorithm, search_keys, charset)
     end
 
-    # As for #thread(), but returns unique identifiers instead of 
+    # As for #thread(), but returns unique identifiers instead of
     # message sequence numbers.
     def uid_thread(algorithm, search_keys, charset)
       return thread_internal("UID THREAD", algorithm, search_keys, charset)
     end
 
+    # Sends an IDLE command that waits for notifications of new or expunged
+    # messages.  Yields responses from the server during the IDLE.
+    #
+    # Use #idle_done() to leave IDLE.
+    def idle(&response_handler)
+      raise LocalJumpError, "no block given" unless response_handler
+
+      response = nil
+
+      synchronize do
+        tag = Thread.current[:net_imap_tag] = generate_tag
+        put_string("#{tag} IDLE#{CRLF}")
+
+        begin
+          add_response_handler(response_handler)
+          @idle_done_cond = new_cond
+          @idle_done_cond.wait
+          @idle_done_cond = nil
+        ensure
+          remove_response_handler(response_handler)
+          put_string("DONE#{CRLF}")
+          response = get_tagged_response(tag, "IDLE")
+        end
+      end
+
+      return response
+    end
+
+    # Leaves IDLE.
+    def idle_done
+      synchronize do
+        if @idle_done_cond.nil?
+          raise Net::IMAP::Error, "not during IDLE"
+        end
+        @idle_done_cond.signal
+      end
+    end
+
     # Decode a string from modified UTF-7 format to UTF-8.
     #
     # UTF-7 is a 7-bit encoding of Unicode [UTF7].  IMAP uses a
@@ -863,7 +914,7 @@
 
     # Encode a string from UTF-8 format to modified UTF-7.
     def self.encode_utf7(s)
-      return s.gsub(/(&)|([^\x20-\x25\x27-\x7e]+)/u) {
+      return s.gsub(/(&)|([^\x20-\x7e]+)/u) {
         if $1
           "&-"
         else
@@ -873,6 +924,16 @@
       }.force_encoding("ASCII-8BIT")
     end
 
+    # Formats +time+ as an IMAP-style date.
+    def self.format_date(time)
+      return time.strftime('%d-%b-%Y')
+    end
+
+    # Formats +time+ as an IMAP-style date-time.
+    def self.format_datetime(time)
+      return time.strftime('%d-%b-%Y %H:%M %z')
+    end
+
     private
 
     CRLF = "\r\n"      # :nodoc:
@@ -881,6 +942,7 @@
 
     @@debug = false
     @@authenticators = {}
+    @@max_flag_count = 10000
 
     # call-seq:
     #    Net::IMAP.new(host, options = {})
@@ -897,7 +959,7 @@
     #         to use SSL (now TLS) to connect to the server.  For this to work
     #         OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] extensions need to
     #         be installed.
-    #         if options[:ssl] is a hash, it's passed to 
+    #         if options[:ssl] is a hash, it's passed to
     #         OpenSSL::SSL::SSLContext#set_params as parameters.
     #
     # The most common errors are:
@@ -908,7 +970,7 @@
     #                    being dropped by an intervening firewall).
     # Errno::ENETUNREACH:: there is no route to that network.
     # SocketError:: hostname not known or other socket error.
-    # Net::IMAP::ByeResponseError:: we connected to the host, but they 
+    # Net::IMAP::ByeResponseError:: we connected to the host, but they
     #                               immediately said goodbye to us.
     def initialize(host, port_or_options = {},
                    usessl = false, certs = nil, verify = true)
@@ -940,6 +1002,7 @@
       @response_handlers = []
       @tagged_response_arrival = new_cond
       @continuation_request_arrival = new_cond
+      @idle_done_cond = nil
       @logout_command_tag = nil
       @debug_output_bol = true
       @exception = nil
@@ -947,17 +1010,21 @@
       @greeting = get_response
       if @greeting.name == "BYE"
         @sock.close
-        raise ByeResponseError, @greeting.raw_data
+        raise ByeResponseError, @greeting
       end
 
       @client_thread = Thread.current
       @receiver_thread = Thread.start {
-        receive_responses
+        begin
+          receive_responses
+        rescue Exception
+        end
       }
     end
 
     def receive_responses
-      while true
+      connection_closed = false
+      until connection_closed
         synchronize do
           @exception = nil
         end
@@ -993,8 +1060,8 @@
               end
               if resp.name == "BYE" && @logout_command_tag.nil?
                 @sock.close
-                @exception = ByeResponseError.new(resp.raw_data)
-                break
+                @exception = ByeResponseError.new(resp)
+                connection_closed = true
               end
             when ContinuationRequest
               @continuation_request_arrival.signal
@@ -1025,9 +1092,9 @@
       resp = @tagged_responses.delete(tag)
       case resp.name
       when /\A(?:NO)\z/ni
-        raise NoResponseError, resp.data.text
+        raise NoResponseError, resp
       when /\A(?:BAD)\z/ni
-        raise BadResponseError, resp.data.text
+        raise BadResponseError, resp
       else
         return resp
       end
@@ -1062,6 +1129,9 @@
 
     def send_command(cmd, *args, &block)
       synchronize do
+        args.each do |i|
+          validate_data(i)
+        end
         tag = generate_tag
         put_string(tag + " " + cmd)
         args.each do |i|
@@ -1089,7 +1159,7 @@
       @tagno += 1
       return format("%s%04d", @tag_prefix, @tagno)
     end
-    
+
     def put_string(str)
       @sock.print(str)
       if @@debug
@@ -1105,6 +1175,25 @@
       end
     end
 
+    def validate_data(data)
+      case data
+      when nil
+      when String
+      when Integer
+        if data < 0 || data >= 4294967296
+          raise DataFormatError, num.to_s
+        end
+      when Array
+        data.each do |i|
+          validate_data(i)
+        end
+      when Time
+      when Symbol
+      else
+        data.validate
+      end
+    end
+
     def send_data(data)
       case data
       when nil
@@ -1138,7 +1227,7 @@
         put_string(str)
       end
     end
-    
+
     def send_quoted_string(str)
       put_string('"' + str.gsub(/["\\]/n, "\\\\\\&") + '"')
     end
@@ -1151,9 +1240,6 @@
     end
 
     def send_number_data(num)
-      if num < 0 || num >= 4294967296
-        raise DataFormatError, num.to_s
-      end
       put_string(num.to_s)
     end
 
@@ -1202,9 +1288,15 @@
     end
 
     def fetch_internal(cmd, set, attr)
-      if attr.instance_of?(String)
+      case attr
+      when String then
         attr = RawData.new(attr)
+      when Array then
+        attr = attr.map { |arg|
+          arg.is_a?(String) ? RawData.new(arg) : arg
+        }
       end
+
       synchronize do
         @responses.delete("FETCH")
         send_command(cmd, MessageSet.new(set), attr)
@@ -1294,7 +1386,7 @@
       context = SSLContext.new
       context.set_params(params)
       if defined?(VerifyCallbackProc)
-        context.verify_callback = VerifyCallbackProc 
+        context.verify_callback = VerifyCallbackProc
       end
       @sock = SSLSocket.new(@sock, context)
       @sock.sync_close = true
@@ -1309,6 +1401,9 @@
         imap.send(:put_string, @data)
       end
 
+      def validate
+      end
+
       private
 
       def initialize(data)
@@ -1321,6 +1416,9 @@
         imap.send(:put_string, @data)
       end
 
+      def validate
+      end
+
       private
 
       def initialize(data)
@@ -1333,6 +1431,9 @@
         imap.send(:send_quoted_string, @data)
       end
 
+      def validate
+      end
+
       private
 
       def initialize(data)
@@ -1345,6 +1446,9 @@
         imap.send(:send_literal, @data)
       end
 
+      def validate
+      end
+
       private
 
       def initialize(data)
@@ -1357,6 +1461,10 @@
         imap.send(:put_string, format_internal(@data))
       end
 
+      def validate
+        validate_internal(@data)
+      end
+
       private
 
       def initialize(data)
@@ -1368,7 +1476,6 @@
         when "*"
           return data
         when Integer
-          ensure_nz_number(data)
           if data == -1
             return "*"
           else
@@ -1382,6 +1489,23 @@
         when ThreadMember
           return data.seqno.to_s +
             ":" + data.children.collect {|i| format_internal(i).join(",")}
+        end
+      end
+
+      def validate_internal(data)
+        case data
+        when "*"
+        when Integer
+          ensure_nz_number(data)
+        when Range
+        when Array
+          data.each do |i|
+            validate_internal(i)
+          end
+        when ThreadMember
+          data.children.each do |i|
+            validate_internal(i)
+          end
         else
           raise DataFormatError, data.inspect
         end
@@ -1397,109 +1521,109 @@
     end
 
     # Net::IMAP::ContinuationRequest represents command continuation requests.
-    # 
+    #
     # The command continuation request response is indicated by a "+" token
     # instead of a tag.  This form of response indicates that the server is
     # ready to accept the continuation of a command from the client.  The
     # remainder of this response is a line of text.
-    # 
+    #
     #   continue_req    ::= "+" SPACE (resp_text / base64)
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # data:: Returns the data (Net::IMAP::ResponseText).
-    # 
+    #
     # raw_data:: Returns the raw data string.
     ContinuationRequest = Struct.new(:data, :raw_data)
 
     # Net::IMAP::UntaggedResponse represents untagged responses.
-    # 
+    #
     # Data transmitted by the server to the client and status responses
     # that do not indicate command completion are prefixed with the token
     # "*", and are called untagged responses.
-    # 
+    #
     #   response_data   ::= "*" SPACE (resp_cond_state / resp_cond_bye /
     #                       mailbox_data / message_data / capability_data)
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # name:: Returns the name such as "FLAGS", "LIST", "FETCH"....
-    # 
+    #
     # data:: Returns the data such as an array of flag symbols,
     #         a ((<Net::IMAP::MailboxList>)) object....
-    # 
+    #
     # raw_data:: Returns the raw data string.
     UntaggedResponse = Struct.new(:name, :data, :raw_data)
-     
+
     # Net::IMAP::TaggedResponse represents tagged responses.
-    # 
+    #
     # The server completion result response indicates the success or
     # failure of the operation.  It is tagged with the same tag as the
     # client command which began the operation.
-    # 
+    #
     #   response_tagged ::= tag SPACE resp_cond_state CRLF
-    #   
+    #
     #   tag             ::= 1*<any ATOM_CHAR except "+">
-    #   
+    #
     #   resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # tag:: Returns the tag.
-    # 
+    #
     # name:: Returns the name. the name is one of "OK", "NO", "BAD".
-    # 
+    #
     # data:: Returns the data. See ((<Net::IMAP::ResponseText>)).
-    # 
+    #
     # raw_data:: Returns the raw data string.
     #
     TaggedResponse = Struct.new(:tag, :name, :data, :raw_data)
-     
+
     # Net::IMAP::ResponseText represents texts of responses.
     # The text may be prefixed by the response code.
-    # 
+    #
     #   resp_text       ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
     #                       ;; text SHOULD NOT begin with "[" or "="
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # code:: Returns the response code. See ((<Net::IMAP::ResponseCode>)).
-    #       
+    #
     # text:: Returns the text.
-    # 
+    #
     ResponseText = Struct.new(:code, :text)
 
-    # 
+    #
     # Net::IMAP::ResponseCode represents response codes.
-    # 
+    #
     #   resp_text_code  ::= "ALERT" / "PARSE" /
     #                       "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
     #                       "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
     #                       "UIDVALIDITY" SPACE nz_number /
     #                       "UNSEEN" SPACE nz_number /
     #                       atom [SPACE 1*<any TEXT_CHAR except "]">]
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # name:: Returns the name such as "ALERT", "PERMANENTFLAGS", "UIDVALIDITY"....
-    # 
+    #
     # data:: Returns the data if it exists.
     #
     ResponseCode = Struct.new(:name, :data)
 
     # Net::IMAP::MailboxList represents contents of the LIST response.
-    # 
+    #
     #   mailbox_list    ::= "(" #("\Marked" / "\Noinferiors" /
     #                       "\Noselect" / "\Unmarked" / flag_extension) ")"
     #                       SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # attr:: Returns the name attributes. Each name attribute is a symbol
     #        capitalized by String#capitalize, such as :Noselect (not :NoSelect).
-    # 
+    #
     # delim:: Returns the hierarchy delimiter
-    # 
+    #
     # name:: Returns the mailbox name.
     #
     MailboxList = Struct.new(:attr, :delim, :name)
@@ -1508,78 +1632,78 @@
     # This object can also be a response to GETQUOTAROOT.  In the syntax
     # specification below, the delimiter used with the "#" construct is a
     # single space (SPACE).
-    # 
+    #
     #    quota_list      ::= "(" #quota_resource ")"
-    # 
+    #
     #    quota_resource  ::= atom SPACE number SPACE number
-    # 
+    #
     #    quota_response  ::= "QUOTA" SPACE astring SPACE quota_list
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # mailbox:: The mailbox with the associated quota.
-    # 
+    #
     # usage:: Current storage usage of mailbox.
-    # 
+    #
     # quota:: Quota limit imposed on mailbox.
     #
     MailboxQuota = Struct.new(:mailbox, :usage, :quota)
 
     # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
     # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
-    # 
+    #
     #    quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # mailbox:: The mailbox with the associated quota.
-    # 
+    #
     # quotaroots:: Zero or more quotaroots that effect the quota on the
     #              specified mailbox.
     #
     MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots)
 
     # Net::IMAP::MailboxACLItem represents response from GETACL.
-    # 
+    #
     #    acl_data        ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights)
-    # 
+    #
     #    identifier      ::= astring
-    # 
+    #
     #    rights          ::= astring
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # user:: Login name that has certain rights to the mailbox
     #        that was specified with the getacl command.
-    # 
+    #
     # rights:: The access rights the indicated user has to the
     #          mailbox.
     #
     MailboxACLItem = Struct.new(:user, :rights)
 
     # Net::IMAP::StatusData represents contents of the STATUS response.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # mailbox:: Returns the mailbox name.
-    # 
+    #
     # attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
     #        "UIDVALIDITY", "UNSEEN". Each value is a number.
-    # 
+    #
     StatusData = Struct.new(:mailbox, :attr)
 
     # Net::IMAP::FetchData represents contents of the FETCH response.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # seqno:: Returns the message sequence number.
     #         (Note: not the unique identifier, even for the UID command response.)
-    # 
+    #
     # attr:: Returns a hash. Each key is a data item name, and each value is
     #        its value.
-    # 
+    #
     #        The current data items are:
-    # 
+    #
     #        [BODY]
     #           A form of BODYSTRUCTURE without extension data.
     #        [BODY[<section>]<<origin_octet>>]
@@ -1606,67 +1730,67 @@
     #           Equivalent to BODY[TEXT].
     #        [UID]
     #           A number expressing the unique identifier of the message.
-    # 
+    #
     FetchData = Struct.new(:seqno, :attr)
 
     # Net::IMAP::Envelope represents envelope structures of messages.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # date:: Returns a string that represents the date.
-    # 
+    #
     # subject:: Returns a string that represents the subject.
-    # 
+    #
     # from:: Returns an array of Net::IMAP::Address that represents the from.
-    # 
+    #
     # sender:: Returns an array of Net::IMAP::Address that represents the sender.
-    # 
+    #
     # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to.
-    # 
+    #
     # to:: Returns an array of Net::IMAP::Address that represents the to.
-    # 
+    #
     # cc:: Returns an array of Net::IMAP::Address that represents the cc.
-    # 
+    #
     # bcc:: Returns an array of Net::IMAP::Address that represents the bcc.
-    # 
+    #
     # in_reply_to:: Returns a string that represents the in-reply-to.
-    # 
+    #
     # message_id:: Returns a string that represents the message-id.
-    # 
+    #
     Envelope = Struct.new(:date, :subject, :from, :sender, :reply_to,
                           :to, :cc, :bcc, :in_reply_to, :message_id)
 
-    # 
+    #
     # Net::IMAP::Address represents electronic mail addresses.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # name:: Returns the phrase from [RFC-822] mailbox.
-    # 
+    #
     # route:: Returns the route from [RFC-822] route-addr.
-    # 
+    #
     # mailbox:: nil indicates end of [RFC-822] group.
     #           If non-nil and host is nil, returns [RFC-822] group name.
     #           Otherwise, returns [RFC-822] local-part
-    # 
+    #
     # host:: nil indicates [RFC-822] group syntax.
     #        Otherwise, returns [RFC-822] domain name.
     #
     Address = Struct.new(:name, :route, :mailbox, :host)
 
-    # 
+    #
     # Net::IMAP::ContentDisposition represents Content-Disposition fields.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # dsp_type:: Returns the disposition type.
-    # 
+    #
     # param:: Returns a hash that represents parameters of the Content-Disposition
     #         field.
-    # 
+    #
     ContentDisposition = Struct.new(:dsp_type, :param)
 
-    # Net::IMAP::ThreadMember represents a thread-node returned 
+    # Net::IMAP::ThreadMember represents a thread-node returned
     # by Net::IMAP#thread
     #
     # ==== Fields:
@@ -1679,37 +1803,37 @@
     ThreadMember = Struct.new(:seqno, :children)
 
     # Net::IMAP::BodyTypeBasic represents basic body structures of messages.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # media_type:: Returns the content media type name as defined in [MIME-IMB].
-    # 
+    #
     # subtype:: Returns the content subtype name as defined in [MIME-IMB].
-    # 
+    #
     # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
-    # 
+    #
     # content_id:: Returns a string giving the content id as defined in [MIME-IMB].
-    # 
+    #
     # description:: Returns a string giving the content description as defined in
     #               [MIME-IMB].
-    # 
+    #
     # encoding:: Returns a string giving the content transfer encoding as defined in
     #            [MIME-IMB].
-    # 
+    #
     # size:: Returns a number giving the size of the body in octets.
-    # 
+    #
     # md5:: Returns a string giving the body MD5 value as defined in [MD5].
-    # 
+    #
     # disposition:: Returns a Net::IMAP::ContentDisposition object giving
     #               the content disposition.
-    # 
+    #
     # language:: Returns a string or an array of strings giving the body
     #            language value as defined in [LANGUAGE-TAGS].
-    # 
+    #
     # extension:: Returns extension data.
-    # 
+    #
     # multipart?:: Returns false.
-    # 
+    #
     class BodyTypeBasic < Struct.new(:media_type, :subtype,
                                      :param, :content_id,
                                      :description, :encoding, :size,
@@ -1720,7 +1844,7 @@
       end
 
       # Obsolete: use +subtype+ instead.  Calling this will
-      # generate a warning message to +stderr+, then return 
+      # generate a warning message to +stderr+, then return
       # the value of +subtype+.
       def media_subtype
         $stderr.printf("warning: media_subtype is obsolete.\n")
@@ -1730,13 +1854,13 @@
     end
 
     # Net::IMAP::BodyTypeText represents TEXT body structures of messages.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # lines:: Returns the size of the body in text lines.
-    # 
+    #
     # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic.
-    # 
+    #
     class BodyTypeText < Struct.new(:media_type, :subtype,
                                     :param, :content_id,
                                     :description, :encoding, :size,
@@ -1748,7 +1872,7 @@
       end
 
       # Obsolete: use +subtype+ instead.  Calling this will
-      # generate a warning message to +stderr+, then return 
+      # generate a warning message to +stderr+, then return
       # the value of +subtype+.
       def media_subtype
         $stderr.printf("warning: media_subtype is obsolete.\n")
@@ -1758,13 +1882,13 @@
     end
 
     # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure.
-    # 
+    #
     # body:: Returns an object giving the body structure.
-    # 
+    #
     # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText.
     #
     class BodyTypeMessage < Struct.new(:media_type, :subtype,
@@ -1778,7 +1902,7 @@
       end
 
       # Obsolete: use +subtype+ instead.  Calling this will
-      # generate a warning message to +stderr+, then return 
+      # generate a warning message to +stderr+, then return
       # the value of +subtype+.
       def media_subtype
         $stderr.printf("warning: media_subtype is obsolete.\n")
@@ -1787,29 +1911,29 @@
       end
     end
 
-    # Net::IMAP::BodyTypeMultipart represents multipart body structures 
+    # Net::IMAP::BodyTypeMultipart represents multipart body structures
     # of messages.
-    # 
+    #
     # ==== Fields:
-    # 
+    #
     # media_type:: Returns the content media type name as defined in [MIME-IMB].
-    # 
+    #
     # subtype:: Returns the content subtype name as defined in [MIME-IMB].
-    # 
+    #
     # parts:: Returns multiple parts.
-    # 
+    #
     # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
-    # 
+    #
     # disposition:: Returns a Net::IMAP::ContentDisposition object giving
     #               the content disposition.
-    # 
+    #
     # language:: Returns a string or an array of strings giving the body
     #            language value as defined in [LANGUAGE-TAGS].
-    # 
+    #
     # extension:: Returns extension data.
-    # 
+    #
     # multipart?:: Returns true.
-    # 
+    #
     class BodyTypeMultipart < Struct.new(:media_type, :subtype,
                                          :parts,
                                          :param, :disposition, :language,
@@ -1819,7 +1943,7 @@
       end
 
       # Obsolete: use +subtype+ instead.  Calling this will
-      # generate a warning message to +stderr+, then return 
+      # generate a warning message to +stderr+, then return
       # the value of +subtype+.
       def media_subtype
         $stderr.printf("warning: media_subtype is obsolete.\n")
@@ -1829,6 +1953,14 @@
     end
 
     class ResponseParser # :nodoc:
+      def initialize
+        @str = nil
+        @pos = nil
+        @lex_state = nil
+        @token = nil
+        @flag_symbols = {}
+      end
+
       def parse(str)
         @str = str
         @pos = 0
@@ -2620,35 +2752,35 @@
       def thread_branch(token)
         rootmember = nil
         lastmember = nil
-        
+
         while true
           shift_token    # ignore first T_LPAR
           token = lookahead
-          
+
           case token.symbol
           when T_NUMBER
             # new member
             newmember = ThreadMember.new(number, [])
             if rootmember.nil?
               rootmember = newmember
-            else    
+            else
               lastmember.children << newmember
-            end     
+            end
             lastmember = newmember
-          when T_SPACE 
-            # do nothing 
+          when T_SPACE
+            # do nothing
           when T_LPAR
             if rootmember.nil?
               # dummy member
               lastmember = rootmember = ThreadMember.new(nil, [])
-            end     
-            
+            end
+
             lastmember.children << thread_branch(token)
           when T_RPAR
-            break   
-          end     
+            break
+          end
         end
-        
+
         return rootmember
       end
 
@@ -2725,11 +2857,16 @@
           match(T_SPACE)
           result = ResponseCode.new(name, number)
         else
-          match(T_SPACE)
-          @lex_state = EXPR_CTEXT
-          token = match(T_TEXT)
-          @lex_state = EXPR_BEG
-          result = ResponseCode.new(name, token.value)
+          token = lookahead
+          if token.symbol == T_SPACE
+            shift_token
+            @lex_state = EXPR_CTEXT
+            token = match(T_TEXT)
+            @lex_state = EXPR_BEG
+            result = ResponseCode.new(name, token.value)
+          else
+            result = ResponseCode.new(name, nil)
+          end
         end
         match(T_RBRA)
         @lex_state = EXPR_RTEXT
@@ -2834,7 +2971,16 @@
         if @str.index(/\(([^)]*)\)/ni, @pos)
           @pos = $~.end(0)
           return $1.scan(FLAG_REGEXP).collect { |flag, atom|
-            atom || flag.capitalize.intern
+            if atom
+              atom
+            else
+              symbol = flag.capitalize.untaint.intern
+              @flag_symbols[symbol] = true
+              if @flag_symbols.length > IMAP.max_flag_count
+                raise FlagCountError, "number of flag symbols exceeded"
+              end
+              symbol
+            end
           }
         else
           parse_error("invalid flag list")
@@ -3125,7 +3271,7 @@
         @user = user
         @password = password
       end
-    end 
+    end
     add_authenticator "PLAIN", PlainAuthenticator
 
     # Authenticator for the "CRAM-MD5" authentication type.  See
@@ -3151,8 +3297,8 @@
         k_ipad = key + "\0" * (64 - key.length)
         k_opad = key + "\0" * (64 - key.length)
         for i in 0..63
-          k_ipad[i] ^= 0x36
-          k_opad[i] ^= 0x5c
+          k_ipad[i] = (k_ipad[i].ord ^ 0x36).chr
+          k_opad[i] = (k_opad[i].ord ^ 0x5c).chr
         end
 
         digest = Digest::MD5.digest(k_ipad + text)
@@ -3277,6 +3423,16 @@
     # Superclass of all errors used to encapsulate "fail" responses
     # from the server.
     class ResponseError < Error
+
+      # The response that caused this error
+      attr_accessor :response
+
+      def initialize(response)
+        @response = response
+
+        super @response.data.text
+      end
+
     end
 
     # Error raised upon a "NO" response from the server, indicating
@@ -3290,11 +3446,15 @@
     class BadResponseError < ResponseError
     end
 
-    # Error raised upon a "BYE" response from the server, indicating 
+    # Error raised upon a "BYE" response from the server, indicating
     # that the client is not being allowed to login, or has been timed
     # out due to inactivity.
     class ByeResponseError < ResponseError
     end
+
+    # Error raised when too many flags are interned to symbols.
+    class FlagCountError < Error
+    end
   end
 end
 
@@ -3375,7 +3535,7 @@
     usage
     exit(1)
   end
-    
+
   imap = Net::IMAP.new($host, :port => $port, :ssl => $ssl)
   begin
     password = get_password

Modified: MacRuby/trunk/lib/net/pop.rb
===================================================================
--- MacRuby/trunk/lib/net/pop.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/pop.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,20 +3,20 @@
 # Copyright (c) 1999-2007 Yukihiro Matsumoto.
 #
 # Copyright (c) 1999-2007 Minero Aoki.
-# 
+#
 # Written & maintained by Minero Aoki <aamine at loveruby.net>.
 #
 # Documented by William Webber and Minero Aoki.
-# 
+#
 # This program is free software. You can re-distribute and/or
 # modify this program under the same terms as Ruby itself,
 # Ruby Distribute License.
-# 
+#
 # NOTE: You can find Japanese version of this document at:
 # http://www.ruby-lang.org/ja/man/html/net_pop.html
-# 
-#   $Id: pop.rb 19776 2008-10-14 02:22:46Z kazu $
-# 
+#
+#   $Id: pop.rb 25189 2009-10-02 12:04:37Z akr $
+#
 # See Net::POP3 for documentation.
 #
 
@@ -25,7 +25,7 @@
 require 'timeout'
 
 begin
-  require "openssl/ssl"
+  require "openssl"
 rescue LoadError
 end
 
@@ -45,25 +45,25 @@
   # = Net::POP3
   #
   # == What is This Library?
-  # 
-  # This library provides functionality for retrieving 
+  #
+  # This library provides functionality for retrieving
   # email via POP3, the Post Office Protocol version 3. For details
   # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt).
-  # 
+  #
   # == Examples
-  # 
-  # === Retrieving Messages 
-  # 
-  # This example retrieves messages from the server and deletes them 
+  #
+  # === Retrieving Messages
+  #
+  # This example retrieves messages from the server and deletes them
   # on the server.
   #
   # Messages are written to files named 'inbox/1', 'inbox/2', ....
   # Replace 'pop.example.com' with your POP3 server address, and
   # 'YourAccount' and 'YourPassword' with the appropriate account
   # details.
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     pop = Net::POP3.new('pop.example.com')
   #     pop.start('YourAccount', 'YourPassword')             # (1)
   #     if pop.mails.empty?
@@ -80,19 +80,19 @@
   #       puts "#{pop.mails.size} mails popped."
   #     end
   #     pop.finish                                           # (3)
-  # 
+  #
   # 1. Call Net::POP3#start and start POP session.
   # 2. Access messages by using POP3#each_mail and/or POP3#mails.
   # 3. Close POP session by calling POP3#finish or use the block form of #start.
-  # 
+  #
   # === Shortened Code
-  # 
+  #
   # The example above is very verbose. You can shorten the code by using
   # some utility methods. First, the block form of Net::POP3.start can
   # be used instead of POP3.new, POP3#start and POP3#finish.
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     Net::POP3.start('pop.example.com', 110,
   #                     'YourAccount', 'YourPassword') do |pop|
   #       if pop.mails.empty?
@@ -109,11 +109,11 @@
   #         puts "#{pop.mails.size} mails popped."
   #       end
   #     end
-  # 
+  #
   # POP3#delete_all is an alternative for #each_mail and #delete.
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     Net::POP3.start('pop.example.com', 110,
   #                     'YourAccount', 'YourPassword') do |pop|
   #       if pop.mails.empty?
@@ -128,11 +128,11 @@
   #         end
   #       end
   #     end
-  # 
+  #
   # And here is an even shorter example.
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     i = 0
   #     Net::POP3.delete_all('pop.example.com', 110,
   #                          'YourAccount', 'YourPassword') do |m|
@@ -141,14 +141,14 @@
   #       end
   #       i += 1
   #     end
-  # 
+  #
   # === Memory Space Issues
-  # 
+  #
   # All the examples above get each message as one big string.
   # This example avoids this.
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     i = 1
   #     Net::POP3.delete_all('pop.example.com', 110,
   #                          'YourAccount', 'YourPassword') do |m|
@@ -159,44 +159,44 @@
   #         i += 1
   #       end
   #     end
-  # 
+  #
   # === Using APOP
-  # 
+  #
   # The net/pop library supports APOP authentication.
   # To use APOP, use the Net::APOP class instead of the Net::POP3 class.
   # You can use the utility method, Net::POP3.APOP(). For example:
-  # 
+  #
   #     require 'net/pop'
-  # 
+  #
   #     # Use APOP authentication if $isapop == true
   #     pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110)
   #     pop.start(YourAccount', 'YourPassword') do |pop|
   #       # Rest of the code is the same.
   #     end
-  # 
+  #
   # === Fetch Only Selected Mail Using 'UIDL' POP Command
-  # 
+  #
   # If your POP server provides UIDL functionality,
   # you can grab only selected mails from the POP server.
   # e.g.
-  # 
+  #
   #     def need_pop?( id )
   #       # determine if we need pop this mail...
   #     end
-  # 
+  #
   #     Net::POP3.start('pop.example.com', 110,
   #                     'Your account', 'Your password') do |pop|
   #       pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
   #         do_something(m.pop)
   #       end
   #     end
-  # 
+  #
   # The POPMail#unique_id() method returns the unique-id of the message as a
   # String. Normally the unique-id is a hash of the message.
-  # 
+  #
   class POP3 < Protocol
 
-    Revision = %q$Revision: 19776 $.split[1]
+    Revision = %q$Revision: 25189 $.split[1]
 
     #
     # Class Parameters
@@ -210,7 +210,7 @@
     def POP3.default_pop3_port
       110
     end
-    
+
     # The default port for POP3S connections, port 995
     def POP3.default_pop3s_port
       995
@@ -375,7 +375,7 @@
     # Session management
     #
 
-    # Creates a new POP3 object and open the connection.  Equivalent to 
+    # Creates a new POP3 object and open the connection.  Equivalent to
     #
     #   Net::POP3.new(address, port, isapop).start(account, password)
     #
@@ -396,7 +396,7 @@
                    isapop = false, &block)   # :yield: pop
       new(address, port, isapop).start(account, password, &block)
     end
-    
+
     # Creates a new POP3 object.
     #
     # +address+ is the hostname or ip address of your POP3 server.
@@ -412,7 +412,7 @@
       @ssl_params = POP3.ssl_params
       @port = port
       @apop = isapop
-      
+
       @command = nil
       @socket = nil
       @started = false
@@ -434,7 +434,7 @@
     def use_ssl?
       return !@ssl_params.nil?
     end
-   
+
     # call-seq:
     #    Net::POP#enable_ssl(params = {})
     #
@@ -451,7 +451,7 @@
         @port = port || @port
       end
     end
-    
+
     def disable_ssl
       @ssl_params = nil
     end
@@ -635,7 +635,7 @@
 
     # Yields each message to the passed-in block in turn.
     # Equivalent to:
-    # 
+    #
     #   pop3.mails.each do |popmail|
     #     ....
     #   end
@@ -742,7 +742,7 @@
     #
     # This method fetches the message.  If called with a block, the
     # message is yielded to the block one chunk at a time.  If called
-    # without a block, the message is returned as a String.  The optional 
+    # without a block, the message is returned as a String.  The optional
     # +dest+ argument will be prepended to the returned String; this
     # argument is essentially obsolete.
     #
@@ -753,7 +753,7 @@
     #       n = 1
     #       pop.mails.each do |popmail|
     #         File.open("inbox/#{n}", 'w') do |f|
-    #           f.write popmail.pop              
+    #           f.write popmail.pop
     #         end
     #         popmail.delete
     #         n += 1
@@ -792,7 +792,7 @@
     alias all pop    #:nodoc: obsolete
     alias mail pop   #:nodoc: obsolete
 
-    # Fetches the message header and +lines+ lines of body. 
+    # Fetches the message header and +lines+ lines of body.
     #
     # The optional +dest+ argument is obsolete.
     #
@@ -804,7 +804,7 @@
       dest
     end
 
-    # Fetches the message header.     
+    # Fetches the message header.
     #
     # The optional +dest+ argument is obsolete.
     #
@@ -933,7 +933,7 @@
         @socket.each_message_chunk(&block)
       }
     end
-    
+
     def dele(num)
       check_response(critical { get_response('DELE %d', num) })
     end

Modified: MacRuby/trunk/lib/net/protocol.rb
===================================================================
--- MacRuby/trunk/lib/net/protocol.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/protocol.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -11,7 +11,7 @@
 # modify this program under the same terms as Ruby itself,
 # Ruby Distribute License or GNU General Public License.
 #
-# $Id: protocol.rb 12091 2007-03-19 02:27:08Z aamine $
+# $Id: protocol.rb 25189 2009-10-02 12:04:37Z akr $
 #++
 #
 # WARNING: This file is going to remove.
@@ -121,7 +121,7 @@
         return rbuf_consume(@rbuf.size)
       end
     end
-        
+
     def readline
       readuntil("\n").chop
     end
@@ -131,9 +131,23 @@
     BUFSIZE = 1024 * 16
 
     def rbuf_fill
-      timeout(@read_timeout) {
-        @rbuf << @io.sysread(BUFSIZE)
-      }
+      begin
+        @rbuf << @io.read_nonblock(BUFSIZE)
+      rescue IO::WaitReadable
+        if IO.select([@io], nil, nil, @read_timeout)
+          retry
+        else
+          raise Timeout::Error
+        end
+      rescue IO::WaitWritable
+        # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable.
+        # http://www.openssl.org/support/faq.html#PROG10
+        if IO.select(nil, [@io], nil, @read_timeout)
+          retry
+        else
+          raise Timeout::Error
+        end
+      end
     end
 
     def rbuf_consume(len)
@@ -222,7 +236,7 @@
       LOG_on()
       LOG "read message (#{read_bytes} bytes)"
     end
-  
+
     # *library private* (cannot handle 'break')
     def each_list_item
       while (str = readuntil("\r\n")) != ".\r\n"

Modified: MacRuby/trunk/lib/net/smtp.rb
===================================================================
--- MacRuby/trunk/lib/net/smtp.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/smtp.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,23 +1,23 @@
 # = net/smtp.rb
-# 
+#
 # Copyright (c) 1999-2007 Yukihiro Matsumoto.
 #
 # Copyright (c) 1999-2007 Minero Aoki.
-# 
+#
 # Written & maintained by Minero Aoki <aamine at loveruby.net>.
 #
 # Documented by William Webber and Minero Aoki.
-# 
+#
 # This program is free software. You can re-distribute and/or
 # modify this program under the same terms as Ruby itself.
-# 
+#
 # NOTE: You can find Japanese version of this document at:
 # http://www.ruby-lang.org/ja/man/html/net_smtp.html
-# 
-# $Id: smtp.rb 18351 2008-08-04 05:46:53Z shyouhei $
 #
-# See Net::SMTP for documentation. 
-# 
+# $Id: smtp.rb 27512 2010-04-27 09:00:52Z nobu $
+#
+# See Net::SMTP for documentation.
+#
 
 require 'net/protocol'
 require 'digest/md5'
@@ -69,110 +69,110 @@
   # = Net::SMTP
   #
   # == What is This Library?
-  # 
+  #
   # This library provides functionality to send internet
   # mail via SMTP, the Simple Mail Transfer Protocol. For details of
   # SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt).
-  # 
+  #
   # == What is This Library NOT?
-  # 
+  #
   # This library does NOT provide functions to compose internet mails.
   # You must create them by yourself. If you want better mail support,
   # try RubyMail or TMail. You can get both libraries from RAA.
   # (http://www.ruby-lang.org/en/raa.html)
-  # 
+  #
   # FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt).
-  # 
+  #
   # == Examples
-  # 
+  #
   # === Sending Messages
-  # 
+  #
   # You must open a connection to an SMTP server before sending messages.
-  # The first argument is the address of your SMTP server, and the second 
-  # argument is the port number. Using SMTP.start with a block is the simplest 
-  # way to do this. This way, the SMTP connection is closed automatically 
+  # The first argument is the address of your SMTP server, and the second
+  # argument is the port number. Using SMTP.start with a block is the simplest
+  # way to do this. This way, the SMTP connection is closed automatically
   # after the block is executed.
-  # 
+  #
   #     require 'net/smtp'
   #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
   #       # Use the SMTP object smtp only in this block.
   #     end
-  # 
+  #
   # Replace 'your.smtp.server' with your SMTP server. Normally
   # your system manager or internet provider supplies a server
   # for you.
-  # 
+  #
   # Then you can send messages.
-  # 
+  #
   #     msgstr = <<END_OF_MESSAGE
   #     From: Your Name <your at mail.address>
   #     To: Destination Address <someone at example.com>
   #     Subject: test message
   #     Date: Sat, 23 Jun 2001 16:26:43 +0900
   #     Message-Id: <unique.message.id.string at example.com>
-  # 
+  #
   #     This is a test message.
   #     END_OF_MESSAGE
-  # 
+  #
   #     require 'net/smtp'
   #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
   #       smtp.send_message msgstr,
   #                         'your at mail.address',
-  #                         'his_addess at example.com'
+  #                         'his_address at example.com'
   #     end
-  # 
+  #
   # === Closing the Session
-  # 
-  # You MUST close the SMTP session after sending messages, by calling 
+  #
+  # You MUST close the SMTP session after sending messages, by calling
   # the #finish method:
-  # 
+  #
   #     # using SMTP#finish
   #     smtp = Net::SMTP.start('your.smtp.server', 25)
   #     smtp.send_message msgstr, 'from at address', 'to at address'
   #     smtp.finish
-  # 
+  #
   # You can also use the block form of SMTP.start/SMTP#start.  This closes
   # the SMTP session automatically:
-  # 
+  #
   #     # using block form of SMTP.start
   #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
   #       smtp.send_message msgstr, 'from at address', 'to at address'
   #     end
-  # 
+  #
   # I strongly recommend this scheme.  This form is simpler and more robust.
-  # 
+  #
   # === HELO domain
-  # 
+  #
   # In almost all situations, you must provide a third argument
   # to SMTP.start/SMTP#start. This is the domain name which you are on
   # (the host to send mail from). It is called the "HELO domain".
   # The SMTP server will judge whether it should send or reject
   # the SMTP session by inspecting the HELO domain.
-  # 
+  #
   #     Net::SMTP.start('your.smtp.server', 25,
   #                     'mail.from.domain') { |smtp| ... }
-  # 
+  #
   # === SMTP Authentication
-  # 
+  #
   # The Net::SMTP class supports three authentication schemes;
   # PLAIN, LOGIN and CRAM MD5.  (SMTP Authentication: [RFC2554])
-  # To use SMTP authentication, pass extra arguments to 
+  # To use SMTP authentication, pass extra arguments to
   # SMTP.start/SMTP#start.
-  # 
+  #
   #     # PLAIN
   #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
   #                     'Your Account', 'Your Password', :plain)
   #     # LOGIN
   #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
   #                     'Your Account', 'Your Password', :login)
-  # 
+  #
   #     # CRAM MD5
   #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
   #                     'Your Account', 'Your Password', :cram_md5)
   #
   class SMTP
 
-    Revision = %q$Revision: 18351 $.split[1]
+    Revision = %q$Revision: 27512 $.split[1]
 
     # The default SMTP port number, 25.
     def SMTP.default_port
@@ -196,7 +196,7 @@
     def SMTP.default_ssl_context
       OpenSSL::SSL::SSLContext.new
     end
-    
+
     #
     # Creates a new Net::SMTP object.
     #
@@ -223,7 +223,7 @@
       @starttls = false
       @ssl_context = nil
     end
-    
+
     # Provide human-readable stringification of class state.
     def inspect
       "#<#{self.class} #{@address}:#{@port} started=#{@started}>"
@@ -235,7 +235,7 @@
     end
 
     #
-    # Set whether to use ESMTP or not.  This should be done before 
+    # Set whether to use ESMTP or not.  This should be done before
     # calling #start.  Note that if #start is called in ESMTP mode,
     # and the connection fails due to a ProtocolError, the SMTP
     # object will automatically switch to plain SMTP mode and
@@ -310,7 +310,7 @@
     end
 
     alias enable_ssl enable_tls
-    
+
     # Disables SMTP/TLS for this object.  Must be called before the
     # connection is established to have any effect.
     def disable_tls
@@ -336,7 +336,7 @@
     def starttls_auto?
       @starttls == :auto
     end
-    
+
     # Enables SMTP/TLS (STARTTLS) for this object.
     # +context+ is a OpenSSL::SSL::SSLContext object.
     def enable_starttls(context = SMTP.default_ssl_context)
@@ -413,7 +413,7 @@
     # Creates a new Net::SMTP object and connects to the server.
     #
     # This method is equivalent to:
-    # 
+    #
     #   Net::SMTP.new(address, port).start(helo_domain, account, password, authtype)
     #
     # === Example
@@ -437,7 +437,7 @@
     # +port+ is the port to connect to; it defaults to port 25.
     #
     # +helo+ is the _HELO_ _domain_ provided by the client to the
-    # server (see overview comments); it defaults to 'localhost'. 
+    # server (see overview comments); it defaults to 'localhost'.
     #
     # The remaining arguments are used for SMTP authentication, if required
     # or desired.  +user+ is the account name; +secret+ is your password
@@ -476,33 +476,33 @@
     # +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see
     # the discussion in the overview notes.
     #
-    # If both of +user+ and +secret+ are given, SMTP authentication 
-    # will be attempted using the AUTH command.  +authtype+ specifies 
+    # If both of +user+ and +secret+ are given, SMTP authentication
+    # will be attempted using the AUTH command.  +authtype+ specifies
     # the type of authentication to attempt; it must be one of
     # :login, :plain, and :cram_md5.  See the notes on SMTP Authentication
-    # in the overview. 
+    # in the overview.
     #
     # === Block Usage
     #
     # When this methods is called with a block, the newly-started SMTP
     # object is yielded to the block, and automatically closed after
-    # the block call finishes.  Otherwise, it is the caller's 
+    # the block call finishes.  Otherwise, it is the caller's
     # responsibility to close the session when finished.
     #
     # === Example
     #
     # This is very similar to the class method SMTP.start.
     #
-    #     require 'net/smtp' 
+    #     require 'net/smtp'
     #     smtp = Net::SMTP.new('smtp.mail.server', 25)
     #     smtp.start(helo_domain, account, password, authtype) do |smtp|
     #       smtp.send_message msgstr, 'from at example.com', ['dest at example.com']
-    #     end 
+    #     end
     #
     # The primary use of this method (as opposed to SMTP.start)
     # is probably to set debugging (#set_debug_output) or ESMTP
     # (#esmtp=), which must be done before the session is
-    # started.  
+    # started.
     #
     # === Errors
     #
@@ -548,7 +548,7 @@
         check_auth_method(authtype || DEFAULT_AUTH_TYPE)
         check_auth_args user, secret
       end
-      s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }   
+      s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
       logging "Connection opened: #{@address}:#{@port}"
       @socket = new_internet_message_io(tls? ? tlsconnect(s) : s)
       check_response critical { recv_response() }
@@ -621,7 +621,7 @@
     #
     # Sends +msgstr+ as a message.  Single CR ("\r") and LF ("\n") found
     # in the +msgstr+, are converted into the CR LF pair.  You cannot send a
-    # binary message with this method. +msgstr+ should include both 
+    # binary message with this method. +msgstr+ should include both
     # the message headers and body.
     #
     # +from_addr+ is a String representing the source mail address.
@@ -651,8 +651,7 @@
     def send_message(msgstr, from_addr, *to_addrs)
       raise IOError, 'closed session' unless @socket
       mailfrom from_addr
-      rcptto_list to_addrs
-      data msgstr
+      rcptto_list(to_addrs) {data msgstr}
     end
 
     alias send_mail send_message
@@ -705,8 +704,7 @@
     def open_message_stream(from_addr, *to_addrs, &block)   # :yield: stream
       raise IOError, 'closed session' unless @socket
       mailfrom from_addr
-      rcptto_list to_addrs
-      data(&block)
+      rcptto_list(to_addrs) {data(&block)}
     end
 
     alias ready open_message_stream   # obsolete
@@ -769,7 +767,7 @@
       "auth_#{type.to_s.downcase}".intern
     end
 
-    def check_auth_args(user, secret)
+    def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE)
       unless user
         raise ArgumentError, 'SMTP-AUTH requested but missing user name'
       end
@@ -830,9 +828,23 @@
 
     def rcptto_list(to_addrs)
       raise ArgumentError, 'mail destination not given' if to_addrs.empty?
+      ok_users = []
+      unknown_users = []
       to_addrs.flatten.each do |addr|
-        rcptto addr
+        begin
+          rcptto addr
+        rescue SMTPAuthenticationError
+          unknown_users << addr.dump
+        else
+          ok_users << addr
+        end
       end
+      raise ArgumentError, 'mail destination not given' if ok_users.empty?
+      ret = yield
+      unless unknown_users.empty?
+        raise SMTPAuthenticationError, "failed to deliver for #{unknown_users.join(', ')}"
+      end
+      ret
     end
 
     def rcptto(to_addr)
@@ -852,7 +864,7 @@
     #   From: john at example.com
     #   To: betty at example.com
     #   Subject: I found a bug
-    #   
+    #
     #   Check vm.c:58879.
     #   EndMessage
     #

Modified: MacRuby/trunk/lib/net/telnet.rb
===================================================================
--- MacRuby/trunk/lib/net/telnet.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/net/telnet.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,7 +1,7 @@
 # = net/telnet.rb - Simple Telnet Client Library
-# 
+#
 # Author:: Wakou Aoyama <wakou at ruby-lang.org>
-# Documentation:: William Webber and Wakou Aoyama 
+# Documentation:: William Webber and Wakou Aoyama
 #
 # This file holds the class Net::Telnet, which provides client-side
 # telnet functionality.
@@ -10,10 +10,9 @@
 #
 
 require "socket"
-require "delegate"
 require "timeout"
 require "English"
- 
+
 module Net
 
   #
@@ -50,11 +49,11 @@
   # have to handle authentication yourself.
   #
   # For some protocols, it will be possible to specify the +Prompt+
-  # option once when you create the Telnet object and use #cmd() calls; 
+  # option once when you create the Telnet object and use #cmd() calls;
   # for others, you will have to specify the response sequence to
   # look for as the Match option to every #cmd() call, or call
-  # #puts() and #waitfor() directly; for yet others, you will have 
-  # to use #sysread() instead of #waitfor() and parse server 
+  # #puts() and #waitfor() directly; for yet others, you will have
+  # to use #sysread() instead of #waitfor() and parse server
   # responses yourself.
   #
   # It is worth noting that when you create a new Net::Telnet object,
@@ -63,21 +62,21 @@
   # to already open sockets, or to any read-write IO object.  This
   # can be useful, for instance, for setting up a test fixture for
   # unit testing.
-  # 
+  #
   # == Examples
-  # 
+  #
   # === Log in and send a command, echoing all output to stdout
-  # 
+  #
   #   localhost = Net::Telnet::new("Host" => "localhost",
   #                                "Timeout" => 10,
   #                                "Prompt" => /[$%#>] \z/n)
   #   localhost.login("username", "password") { |c| print c }
   #   localhost.cmd("command") { |c| print c }
   #   localhost.close
-  # 
-  # 
+  #
+  #
   # === Check a POP server to see if you have mail
-  # 
+  #
   #   pop = Net::Telnet::new("Host" => "your_destination_host_here",
   #                          "Port" => 110,
   #                          "Telnetmode" => false,
@@ -93,78 +92,78 @@
   # of relevant RFCs, see
   # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html
   #
-  class Telnet < SimpleDelegator
+  class Telnet
 
     # :stopdoc:
     IAC   = 255.chr # "\377" # "\xff" # interpret as command
-    DONT  = 254.chr # "\376" # "\xfe" # you are not to use option 
-    DO    = 253.chr # "\375" # "\xfd" # please, you use option 
-    WONT  = 252.chr # "\374" # "\xfc" # I won't use option 
-    WILL  = 251.chr # "\373" # "\xfb" # I will use option 
-    SB    = 250.chr # "\372" # "\xfa" # interpret as subnegotiation 
-    GA    = 249.chr # "\371" # "\xf9" # you may reverse the line 
-    EL    = 248.chr # "\370" # "\xf8" # erase the current line 
-    EC    = 247.chr # "\367" # "\xf7" # erase the current character 
-    AYT   = 246.chr # "\366" # "\xf6" # are you there 
-    AO    = 245.chr # "\365" # "\xf5" # abort output--but let prog finish 
-    IP    = 244.chr # "\364" # "\xf4" # interrupt process--permanently 
-    BREAK = 243.chr # "\363" # "\xf3" # break 
-    DM    = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning 
-    NOP   = 241.chr # "\361" # "\xf1" # nop 
-    SE    = 240.chr # "\360" # "\xf0" # end sub negotiation 
-    EOR   = 239.chr # "\357" # "\xef" # end of record (transparent mode) 
-    ABORT = 238.chr # "\356" # "\xee" # Abort process 
-    SUSP  = 237.chr # "\355" # "\xed" # Suspend process 
-    EOF   = 236.chr # "\354" # "\xec" # End of file 
-    SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls 
+    DONT  = 254.chr # "\376" # "\xfe" # you are not to use option
+    DO    = 253.chr # "\375" # "\xfd" # please, you use option
+    WONT  = 252.chr # "\374" # "\xfc" # I won't use option
+    WILL  = 251.chr # "\373" # "\xfb" # I will use option
+    SB    = 250.chr # "\372" # "\xfa" # interpret as subnegotiation
+    GA    = 249.chr # "\371" # "\xf9" # you may reverse the line
+    EL    = 248.chr # "\370" # "\xf8" # erase the current line
+    EC    = 247.chr # "\367" # "\xf7" # erase the current character
+    AYT   = 246.chr # "\366" # "\xf6" # are you there
+    AO    = 245.chr # "\365" # "\xf5" # abort output--but let prog finish
+    IP    = 244.chr # "\364" # "\xf4" # interrupt process--permanently
+    BREAK = 243.chr # "\363" # "\xf3" # break
+    DM    = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning
+    NOP   = 241.chr # "\361" # "\xf1" # nop
+    SE    = 240.chr # "\360" # "\xf0" # end sub negotiation
+    EOR   = 239.chr # "\357" # "\xef" # end of record (transparent mode)
+    ABORT = 238.chr # "\356" # "\xee" # Abort process
+    SUSP  = 237.chr # "\355" # "\xed" # Suspend process
+    EOF   = 236.chr # "\354" # "\xec" # End of file
+    SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls
 
-    OPT_BINARY         =   0.chr # "\000" # "\x00" # Binary Transmission 
-    OPT_ECHO           =   1.chr # "\001" # "\x01" # Echo 
-    OPT_RCP            =   2.chr # "\002" # "\x02" # Reconnection 
-    OPT_SGA            =   3.chr # "\003" # "\x03" # Suppress Go Ahead 
-    OPT_NAMS           =   4.chr # "\004" # "\x04" # Approx Message Size Negotiation 
-    OPT_STATUS         =   5.chr # "\005" # "\x05" # Status 
-    OPT_TM             =   6.chr # "\006" # "\x06" # Timing Mark 
-    OPT_RCTE           =   7.chr # "\a"   # "\x07" # Remote Controlled Trans and Echo 
-    OPT_NAOL           =   8.chr # "\010" # "\x08" # Output Line Width 
-    OPT_NAOP           =   9.chr # "\t"   # "\x09" # Output Page Size 
-    OPT_NAOCRD         =  10.chr # "\n"   # "\x0a" # Output Carriage-Return Disposition 
-    OPT_NAOHTS         =  11.chr # "\v"   # "\x0b" # Output Horizontal Tab Stops 
-    OPT_NAOHTD         =  12.chr # "\f"   # "\x0c" # Output Horizontal Tab Disposition 
-    OPT_NAOFFD         =  13.chr # "\r"   # "\x0d" # Output Formfeed Disposition 
-    OPT_NAOVTS         =  14.chr # "\016" # "\x0e" # Output Vertical Tabstops 
-    OPT_NAOVTD         =  15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition 
-    OPT_NAOLFD         =  16.chr # "\020" # "\x10" # Output Linefeed Disposition 
-    OPT_XASCII         =  17.chr # "\021" # "\x11" # Extended ASCII 
-    OPT_LOGOUT         =  18.chr # "\022" # "\x12" # Logout 
-    OPT_BM             =  19.chr # "\023" # "\x13" # Byte Macro 
-    OPT_DET            =  20.chr # "\024" # "\x14" # Data Entry Terminal 
-    OPT_SUPDUP         =  21.chr # "\025" # "\x15" # SUPDUP 
-    OPT_SUPDUPOUTPUT   =  22.chr # "\026" # "\x16" # SUPDUP Output 
-    OPT_SNDLOC         =  23.chr # "\027" # "\x17" # Send Location 
-    OPT_TTYPE          =  24.chr # "\030" # "\x18" # Terminal Type 
-    OPT_EOR            =  25.chr # "\031" # "\x19" # End of Record 
-    OPT_TUID           =  26.chr # "\032" # "\x1a" # TACACS User Identification 
-    OPT_OUTMRK         =  27.chr # "\e"   # "\x1b" # Output Marking 
-    OPT_TTYLOC         =  28.chr # "\034" # "\x1c" # Terminal Location Number 
-    OPT_3270REGIME     =  29.chr # "\035" # "\x1d" # Telnet 3270 Regime 
-    OPT_X3PAD          =  30.chr # "\036" # "\x1e" # X.3 PAD 
-    OPT_NAWS           =  31.chr # "\037" # "\x1f" # Negotiate About Window Size 
-    OPT_TSPEED         =  32.chr # " "    # "\x20" # Terminal Speed 
-    OPT_LFLOW          =  33.chr # "!"    # "\x21" # Remote Flow Control 
-    OPT_LINEMODE       =  34.chr # "\""   # "\x22" # Linemode 
-    OPT_XDISPLOC       =  35.chr # "#"    # "\x23" # X Display Location 
-    OPT_OLD_ENVIRON    =  36.chr # "$"    # "\x24" # Environment Option 
-    OPT_AUTHENTICATION =  37.chr # "%"    # "\x25" # Authentication Option 
-    OPT_ENCRYPT        =  38.chr # "&"    # "\x26" # Encryption Option 
-    OPT_NEW_ENVIRON    =  39.chr # "'"    # "\x27" # New Environment Option 
-    OPT_EXOPL          = 255.chr # "\377" # "\xff" # Extended-Options-List 
+    OPT_BINARY         =   0.chr # "\000" # "\x00" # Binary Transmission
+    OPT_ECHO           =   1.chr # "\001" # "\x01" # Echo
+    OPT_RCP            =   2.chr # "\002" # "\x02" # Reconnection
+    OPT_SGA            =   3.chr # "\003" # "\x03" # Suppress Go Ahead
+    OPT_NAMS           =   4.chr # "\004" # "\x04" # Approx Message Size Negotiation
+    OPT_STATUS         =   5.chr # "\005" # "\x05" # Status
+    OPT_TM             =   6.chr # "\006" # "\x06" # Timing Mark
+    OPT_RCTE           =   7.chr # "\a"   # "\x07" # Remote Controlled Trans and Echo
+    OPT_NAOL           =   8.chr # "\010" # "\x08" # Output Line Width
+    OPT_NAOP           =   9.chr # "\t"   # "\x09" # Output Page Size
+    OPT_NAOCRD         =  10.chr # "\n"   # "\x0a" # Output Carriage-Return Disposition
+    OPT_NAOHTS         =  11.chr # "\v"   # "\x0b" # Output Horizontal Tab Stops
+    OPT_NAOHTD         =  12.chr # "\f"   # "\x0c" # Output Horizontal Tab Disposition
+    OPT_NAOFFD         =  13.chr # "\r"   # "\x0d" # Output Formfeed Disposition
+    OPT_NAOVTS         =  14.chr # "\016" # "\x0e" # Output Vertical Tabstops
+    OPT_NAOVTD         =  15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition
+    OPT_NAOLFD         =  16.chr # "\020" # "\x10" # Output Linefeed Disposition
+    OPT_XASCII         =  17.chr # "\021" # "\x11" # Extended ASCII
+    OPT_LOGOUT         =  18.chr # "\022" # "\x12" # Logout
+    OPT_BM             =  19.chr # "\023" # "\x13" # Byte Macro
+    OPT_DET            =  20.chr # "\024" # "\x14" # Data Entry Terminal
+    OPT_SUPDUP         =  21.chr # "\025" # "\x15" # SUPDUP
+    OPT_SUPDUPOUTPUT   =  22.chr # "\026" # "\x16" # SUPDUP Output
+    OPT_SNDLOC         =  23.chr # "\027" # "\x17" # Send Location
+    OPT_TTYPE          =  24.chr # "\030" # "\x18" # Terminal Type
+    OPT_EOR            =  25.chr # "\031" # "\x19" # End of Record
+    OPT_TUID           =  26.chr # "\032" # "\x1a" # TACACS User Identification
+    OPT_OUTMRK         =  27.chr # "\e"   # "\x1b" # Output Marking
+    OPT_TTYLOC         =  28.chr # "\034" # "\x1c" # Terminal Location Number
+    OPT_3270REGIME     =  29.chr # "\035" # "\x1d" # Telnet 3270 Regime
+    OPT_X3PAD          =  30.chr # "\036" # "\x1e" # X.3 PAD
+    OPT_NAWS           =  31.chr # "\037" # "\x1f" # Negotiate About Window Size
+    OPT_TSPEED         =  32.chr # " "    # "\x20" # Terminal Speed
+    OPT_LFLOW          =  33.chr # "!"    # "\x21" # Remote Flow Control
+    OPT_LINEMODE       =  34.chr # "\""   # "\x22" # Linemode
+    OPT_XDISPLOC       =  35.chr # "#"    # "\x23" # X Display Location
+    OPT_OLD_ENVIRON    =  36.chr # "$"    # "\x24" # Environment Option
+    OPT_AUTHENTICATION =  37.chr # "%"    # "\x25" # Authentication Option
+    OPT_ENCRYPT        =  38.chr # "&"    # "\x26" # Encryption Option
+    OPT_NEW_ENVIRON    =  39.chr # "'"    # "\x27" # New Environment Option
+    OPT_EXOPL          = 255.chr # "\377" # "\xff" # Extended-Options-List
 
-    NULL = "\000" 
-    CR   = "\015"   
-    LF   = "\012" 
-    EOL  = CR + LF 
-    REVISION = '$Id: telnet.rb 17387 2008-06-17 14:04:48Z jeg2 $'
+    NULL = "\000"
+    CR   = "\015"
+    LF   = "\012"
+    EOL  = CR + LF
+    REVISION = '$Id: telnet.rb 25733 2009-11-12 14:03:03Z xibbar $'
     # :startdoc:
 
     #
@@ -174,13 +173,13 @@
     # provided: see below).  If a block is provided, it is yielded
     # status messages on the attempt to connect to the server, of
     # the form:
-    # 
+    #
     #   Trying localhost...
     #   Connected to localhost.
     #
     # +options+ is a hash of options.  The following example lists
     # all options and their default values.
-    # 
+    #
     #   host = Net::Telnet::new(
     #            "Host"       => "localhost",  # default: "localhost"
     #            "Port"       => 23,           # default: 23
@@ -198,16 +197,16 @@
     #
     # The options have the following meanings:
     #
-    # Host:: the hostname or IP address of the host to connect to, as a String. 
+    # Host:: the hostname or IP address of the host to connect to, as a String.
     #        Defaults to "localhost".
     #
     # Port:: the port to connect to.  Defaults to 23.
     #
-    # Binmode:: if false (the default), newline substitution is performed.  
+    # Binmode:: if false (the default), newline substitution is performed.
     #           Outgoing LF is
     #           converted to CRLF, and incoming CRLF is converted to LF.  If
     #           true, this substitution is not performed.  This value can
-    #           also be set with the #binmode() method.  The 
+    #           also be set with the #binmode() method.  The
     #           outgoing conversion only applies to the #puts() and #print()
     #           methods, not the #write() method.  The precise nature of
     #           the newline conversion is also affected by the telnet options
@@ -217,13 +216,13 @@
     #              and all received traffic to.  In the case of a proper
     #              Telnet session, this will include the client input as
     #              echoed by the host; otherwise, it only includes server
-    #              responses.  Output is appended verbatim to this file.  
+    #              responses.  Output is appended verbatim to this file.
     #              By default, no output log is kept.
     #
     # Dump_log:: as for Output_log, except that output is written in hexdump
     #            format (16 bytes per line as hex pairs, followed by their
     #            printable equivalent), with connection status messages
-    #            preceded by '#', sent traffic preceded by '>', and 
+    #            preceded by '#', sent traffic preceded by '>', and
     #            received traffic preceded by '<'.  By default, not dump log
     #            is kept.
     #
@@ -233,7 +232,7 @@
     #          ready to receive a new command.  By default, this regular
     #          expression is /[$%#>] \z/n.
     #
-    # Telnetmode:: a boolean value, true by default.  In telnet mode, 
+    # Telnetmode:: a boolean value, true by default.  In telnet mode,
     #              traffic received from the host is parsed for special
     #              command sequences, and these sequences are escaped
     #              in outgoing traffic sent using #puts() or #print()
@@ -255,11 +254,11 @@
     #           minutes), but other attempts to read data from the host
     #           will hand indefinitely if no data is forthcoming.
     #
-    # Waittime:: the amount of time to wait after seeing what looks like a 
+    # Waittime:: the amount of time to wait after seeing what looks like a
     #            prompt (that is, received data that matches the Prompt
     #            option regular expression) to see if more data arrives.
     #            If more data does arrive in this time, Net::Telnet assumes
-    #            that what it saw was not really a prompt.  This is to try to 
+    #            that what it saw was not really a prompt.  This is to try to
     #            avoid false matches, but it can also lead to missing real
     #            prompts (if, for instance, a background process writes to
     #            the terminal soon after the prompt is displayed).  By
@@ -267,12 +266,12 @@
     #
     # Proxy:: a proxy object to used instead of opening a direct connection
     #         to the host.  Must be either another Net::Telnet object or
-    #         an IO object.  If it is another Net::Telnet object, this 
+    #         an IO object.  If it is another Net::Telnet object, this
     #         instance will use that one's socket for communication.  If an
     #         IO object, it is used directly for communication.  Any other
     #         kind of object will cause an error to be raised.
     #
-    def initialize(options) # :yield: mesg 
+    def initialize(options) # :yield: mesg
       @options = options
       @options["Host"]       = "localhost"   unless @options.has_key?("Host")
       @options["Port"]       = 23            unless @options.has_key?("Port")
@@ -280,7 +279,7 @@
       @options["Timeout"]    = 10            unless @options.has_key?("Timeout")
       @options["Waittime"]   = 0             unless @options.has_key?("Waittime")
       unless @options.has_key?("Binmode")
-        @options["Binmode"]    = false         
+        @options["Binmode"]    = false
       else
         unless (true == @options["Binmode"] or false == @options["Binmode"])
           raise ArgumentError, "Binmode option must be true or false"
@@ -288,7 +287,7 @@
       end
 
       unless @options.has_key?("Telnetmode")
-        @options["Telnetmode"] = true          
+        @options["Telnetmode"] = true
       else
         unless (true == @options["Telnetmode"] or false == @options["Telnetmode"])
           raise ArgumentError, "Telnetmode option must be true or false"
@@ -369,13 +368,12 @@
         @dumplog.log_dump('#', message) if @options.has_key?("Dump_log")
       end
 
-      super(@sock)
     end # initialize
 
     # The socket the Telnet object is using.  Note that this object becomes
     # a delegate of the Telnet object, so normally you invoke its methods
     # directly on the Telnet object.
-    attr :sock 
+    attr :sock
 
     # Set telnet command interpretation on (+mode+ == true) or off
     # (+mode+ == false), or return the current value (+mode+ not
@@ -409,7 +407,7 @@
     def binmode(mode = nil)
       case mode
       when nil
-        @options["Binmode"] 
+        @options["Binmode"]
       when true, false
         @options["Binmode"] = mode
       else
@@ -429,7 +427,7 @@
     # Preprocess received data from the host.
     #
     # Performs newline conversion and detects telnet command sequences.
-    # Called automatically by #waitfor().  You should only use this 
+    # Called automatically by #waitfor().  You should only use this
     # method yourself if you have read input directly using sysread()
     # or similar, and even then only if in telnet mode.
     def preprocess(string)
@@ -495,9 +493,9 @@
     # 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 
+    # 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 
+    # 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.
     #
@@ -511,7 +509,7 @@
     #          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, 
+    #           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
@@ -528,7 +526,7 @@
     #           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"]
@@ -623,7 +621,7 @@
     # Sends a string to the host.
     #
     # This does _not_ automatically append a newline to the string.  Embedded
-    # newlines may be converted and telnet command sequences escaped 
+    # newlines may be converted and telnet command sequences escaped
     # depending upon the values of telnetmode, binmode, and telnet options
     # set by the host.
     def print(string)
@@ -658,7 +656,7 @@
     # data until is sees the prompt or other matched sequence.
     #
     # 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 
+    # 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.
     #
@@ -682,20 +680,22 @@
     def cmd(options) # :yield: recvdata
       match    = @options["Prompt"]
       time_out = @options["Timeout"]
+      fail_eof = @options["FailEOF"]
 
       if options.kind_of?(Hash)
         string   = options["String"]
         match    = options["Match"]   if options.has_key?("Match")
         time_out = options["Timeout"] if options.has_key?("Timeout")
+        fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
       else
         string = options
       end
 
       self.puts(string)
       if block_given?
-        waitfor({"Prompt" => match, "Timeout" => time_out}){|c| yield c }
+        waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c }
       else
-        waitfor({"Prompt" => match, "Timeout" => time_out})
+        waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof})
       end
     end
 
@@ -703,7 +703,7 @@
     #
     # The username and password can either be provided as two string
     # arguments in that order, or as a hash with keys "Name" and
-    # "Password".    
+    # "Password".
     #
     # This method looks for the strings "login" and "Password" from the
     # host to determine when to send the username and password.  If the

Modified: MacRuby/trunk/lib/observer.rb
===================================================================
--- MacRuby/trunk/lib/observer.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/observer.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -7,7 +7,7 @@
 #
 # The Observer pattern, also known as Publish/Subscribe, provides a simple
 # mechanism for one object to inform a set of interested third-party objects
-# when its state changes. 
+# when its state changes.
 #
 # == Mechanism
 #
@@ -39,14 +39,14 @@
 # contracts are correct, nothing else can warn you.
 #
 #   require "observer"
-#   
+#
 #   class Ticker          ### Periodically fetch a stock price.
 #     include Observable
-#   
+#
 #     def initialize(symbol)
 #       @symbol = symbol
 #     end
-#   
+#
 #     def run
 #       lastPrice = nil
 #       loop do
@@ -67,14 +67,14 @@
 #       60 + rand(80)
 #     end
 #   end
-#   
+#
 #   class Warner          ### An abstract observer of Ticker objects.
 #     def initialize(ticker, limit)
 #       @limit = limit
 #       ticker.add_observer(self)
 #     end
 #   end
-#   
+#
 #   class WarnLow < Warner
 #     def update(time, price)       # callback for observer
 #       if price < @limit
@@ -82,7 +82,7 @@
 #       end
 #     end
 #   end
-#   
+#
 #   class WarnHigh < Warner
 #     def update(time, price)       # callback for observer
 #       if price > @limit

Modified: MacRuby/trunk/lib/open-uri.rb
===================================================================
--- MacRuby/trunk/lib/open-uri.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/open-uri.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -465,7 +465,9 @@
         subtype = $2.downcase
         parameters = []
         $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
-          val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& } if qval
+          if qval
+            val = qval[1...-1].gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& }
+          end
           parameters << [att.downcase, val]
         }
         ["#{type}/#{subtype}", *parameters]
@@ -603,7 +605,7 @@
     #
     #  If :progress_proc option is specified, the proc is called with one
     #  argument each time when `open' gets content fragment from network.
-    #  The argument `size' `size' is a accumulated transfered size in bytes.
+    #  The argument `size' `size' is a accumulated transferred size in bytes.
     #
     #  If two or more transfer is done by HTTP redirection, the procedure
     #  is called only one for a last transfer.
@@ -778,8 +780,9 @@
       end
       require 'net/ftp'
 
-      directories = self.path.split(%r{/}, -1)
-      directories.shift if directories[0] == '' # strip a field before leading slash
+      path = self.path
+      path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it.
+      directories = path.split(%r{/}, -1)
       directories.each {|d|
         d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
       }
@@ -800,7 +803,8 @@
       end
 
       # The access sequence is defined by RFC 1738
-      ftp = Net::FTP.open(self.host)
+      ftp = Net::FTP.new
+      ftp.connect(self.host, self.port)
       ftp.passive = true if !options[:ftp_active_mode]
       # todo: extract user/passwd from .netrc.
       user = 'anonymous'

Modified: MacRuby/trunk/lib/open3.rb
===================================================================
--- MacRuby/trunk/lib/open3.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/open3.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -11,77 +11,708 @@
 #
 # Open3 grants you access to stdin, stdout, stderr and a thread to wait the
 # child process when running another program.
+# You can specify various attributes, redirections, current directory, etc., of
+# the program as Process.spawn.
 #
-# Example:
+# - Open3.popen3 : pipes for stdin, stdout, stderr
+# - Open3.popen2 : pipes for stdin, stdout
+# - Open3.popen2e : pipes for stdin, merged stdout and stderr
+# - Open3.capture3 : give a string for stdin.  get strings for stdout, stderr
+# - Open3.capture2 : give a string for stdin.  get a string for stdout
+# - Open3.capture2e : give a string for stdin.  get a string for merged stdout and stderr
+# - Open3.pipeline_rw : pipes for first stdin and last stdout of a pipeline
+# - Open3.pipeline_r : pipe for last stdout of a pipeline
+# - Open3.pipeline_w : pipe for first stdin of a pipeline
+# - Open3.pipeline_start : a pipeline
+# - Open3.pipeline : run a pipline and wait
 #
-#   require "open3"
-#   include Open3
-#   
-#   stdin, stdout, stderr, wait_thr = popen3('nroff -man')
-#
-# Open3.popen3 can also take a block which will receive stdin, stdout,
-# stderr and wait_thr as parameters.
-# This ensures stdin, stdout and stderr are closed and
-# the process is terminated once the block exits.
-#
-# Example:
-#
-#   require "open3"
-#
-#   Open3.popen3('nroff -man') { |stdin, stdout, stderr, wait_thr| ... }
-#
 
 module Open3
-  # 
+
   # Open stdin, stdout, and stderr streams and start external executable.
   # In addition, a thread for waiting the started process is noticed.
-  # The thread has a thread variable :pid which is the pid of the started
-  # process.
+  # The thread has a pid method and thread variable :pid which is the pid of
+  # the started process.
   #
+  # Block form:
+  #
+  #   Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr|
+  #     pid = wait_thr.pid # pid of the started process.
+  #     ...
+  #     exit_status = wait_thr.value # Process::Status object returned.
+  #   }
+  #
   # Non-block form:
-  #   
-  #   stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
+  #
+  #   stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts])
   #   pid = wait_thr[:pid]  # pid of the started process.
   #   ...
-  #   stdin.close  # stdin, stdout and stderr should be closed in this form.
+  #   stdin.close  # stdin, stdout and stderr should be closed explicitly in this form.
   #   stdout.close
   #   stderr.close
   #   exit_status = wait_thr.value  # Process::Status object returned.
   #
-  # Block form:
+  # The parameters +cmd...+ is passed to Process.spawn.
+  # So a commandline string and list of argument strings can be accepted as follows.
   #
-  #   Open3.popen3(cmd) { |stdin, stdout, stderr, wait_thr| ... }
+  #   Open3.popen3("echo a") {|i, o, e, t| ... }
+  #   Open3.popen3("echo", "a") {|i, o, e, t| ... }
+  #   Open3.popen3(["echo", "argv0"], "a") {|i, o, e, t| ... }
   #
-  # The parameter +cmd+ is passed directly to Kernel#spawn.
+  # If the last parameter, opts, is a Hash, it is recognized as an option for Process.spawn.
   #
+  #   Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
+  #     p o.read.chomp #=> "/"
+  #   }
+  #
   # wait_thr.value waits the termination of the process.
   # The block form also waits the process when it returns.
   #
   # Closing stdin, stdout and stderr does not wait the process.
   #
-  def popen3(*cmd)
-    pw = IO::pipe   # pipe[0] for read, pipe[1] for write
-    pr = IO::pipe
-    pe = IO::pipe
+  def popen3(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
 
-    pid = spawn(*cmd, STDIN=>pw[0], STDOUT=>pr[1], STDERR=>pe[1])
+    in_r, in_w = IO.pipe
+    opts[:in] = in_r
+    in_w.sync = true
+
+    out_r, out_w = IO.pipe
+    opts[:out] = out_w
+
+    err_r, err_w = IO.pipe
+    opts[:err] = err_w
+
+    popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block)
+  end
+  module_function :popen3
+
+  # Open3.popen2 is similer to Open3.popen3 except it doesn't make a pipe for
+  # the standard error stream.
+  #
+  # Block form:
+  #
+  #   Open3.popen2([env,] cmd... [, opts]) {|stdin, stdout, wait_thr|
+  #     pid = wait_thr.pid # pid of the started process.
+  #     ...
+  #     exit_status = wait_thr.value # Process::Status object returned.
+  #   }
+  #
+  # Non-block form:
+  #
+  #   stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts])
+  #   ...
+  #   stdin.close  # stdin and stdout should be closed explicitly in this form.
+  #   stdout.close
+  #
+  # See Process.spawn for the optional hash arguments _env_ and _opts_.
+  #
+  # Example:
+  #
+  #   Open3.popen2("wc -c") {|i,o,t|
+  #     i.print "answer to life the universe and everything"
+  #     i.close
+  #     p o.gets #=> "42\n"
+  #   }
+  #
+  #   Open3.popen2("bc -q") {|i,o,t|
+  #     i.puts "obase=13"
+  #     i.puts "6 * 9"
+  #     p o.gets #=> "42\n"
+  #   }
+  #
+  #   Open3.popen2("dc") {|i,o,t|
+  #     i.print "42P"
+  #     i.close
+  #     p o.read #=> "*"
+  #   }
+  #
+  def popen2(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
+
+    in_r, in_w = IO.pipe
+    opts[:in] = in_r
+    in_w.sync = true
+
+    out_r, out_w = IO.pipe
+    opts[:out] = out_w
+
+    popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
+  end
+  module_function :popen2
+
+  # Open3.popen2e is similer to Open3.popen3 except it merges
+  # the standard output stream and the standard error stream.
+  #
+  # Block form:
+  #
+  #   Open3.popen2e([env,] cmd... [, opts]) {|stdin, stdout_and_stderr, wait_thr|
+  #     pid = wait_thr.pid # pid of the started process.
+  #     ...
+  #     exit_status = wait_thr.value # Process::Status object returned.
+  #   }
+  #
+  # Non-block form:
+  #
+  #   stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts])
+  #   ...
+  #   stdin.close  # stdin and stdout_and_stderr should be closed explicitly in this form.
+  #   stdout_and_stderr.close
+  #
+  # See Process.spawn for the optional hash arguments _env_ and _opts_.
+  #
+  # Example:
+  #   # check gcc warnings
+  #   source = "foo.c"
+  #   Open3.popen2e("gcc", "-Wall", source) {|i,oe,t|
+  #     oe.each {|line|
+  #       if /warning/ =~ line
+  #         ...
+  #       end
+  #     }
+  #   }
+  #
+  def popen2e(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
+
+    in_r, in_w = IO.pipe
+    opts[:in] = in_r
+    in_w.sync = true
+
+    out_r, out_w = IO.pipe
+    opts[[:out, :err]] = out_w
+
+    popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
+  end
+  module_function :popen2e
+
+  def popen_run(cmd, opts, child_io, parent_io) # :nodoc:
+    pid = spawn(*cmd, opts)
     wait_thr = Process.detach(pid)
-    pw[0].close
-    pr[1].close
-    pe[1].close
-    pi = [pw[1], pr[0], pe[0], wait_thr]
-    pw[1].sync = true
+    child_io.each {|io| io.close }
+    result = [*parent_io, wait_thr]
     if defined? yield
       begin
-	return yield(*pi)
+	return yield(*result)
       ensure
-	[pw[1], pr[0], pe[0]].each{|p| p.close unless p.closed?}
+	parent_io.each{|io| io.close unless io.closed?}
         wait_thr.join
       end
     end
-    pi
+    result
   end
-  module_function :popen3
+  module_function :popen_run
+  class << self
+    private :popen_run
+  end
+
+  # Open3.capture3 captures the standard output and the standard error of a command.
+  #
+  #   stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts])
+  #
+  # The arguments env, cmd and opts are passed to Open3.popen3 except
+  # opts[:stdin_data] and opts[:stdin_data].  See Process.spawn.
+  #
+  # If opts[:stdin_data] is specified, it is sent to the command's standard input.
+  #
+  # If opts[:binmode] is true, internal pipes are set to binary mode.
+  #
+  # Example:
+  #
+  #   # dot is a command of graphviz.
+  #   graph = <<'End'
+  #     digraph g {
+  #       a -> b
+  #     }
+  #   End
+  #   layouted_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph)
+  #
+  #   o, e, s = Open3.capture3("echo a; sort >&2", :stdin_data=>"foo\nbar\nbaz\n")
+  #   p o #=> "a\n"
+  #   p e #=> "bar\nbaz\nfoo\n"
+  #   p s #=> #<Process::Status: pid 32682 exit 0>
+  #
+  #   # generate a thumnail image using the convert command of ImageMagick.
+  #   # However, if the image stored really in a file,
+  #   # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better
+  #   # because memory consumption.
+  #   # But if the image is stored in a DB or generated by gnuplot Open3.capture2 example,
+  #   # Open3.capture3 is considerable.
+  #   #
+  #   image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true)
+  #   thumnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true)
+  #   if s.success?
+  #     STDOUT.binmode; print thumnail
+  #   end
+  #
+  def capture3(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
+
+    stdin_data = opts.delete(:stdin_data) || ''
+    binmode = opts.delete(:binmode)
+
+    popen3(*cmd, opts) {|i, o, e, t|
+      if binmode
+        i.binmode
+        o.binmode
+        e.binmode
+      end
+      out_reader = Thread.new { o.read }
+      err_reader = Thread.new { e.read }
+      i.write stdin_data
+      i.close
+      [out_reader.value, err_reader.value, t.value]
+    }
+  end
+  module_function :capture3
+
+  # Open3.capture2 captures the standard output of a command.
+  #
+  #   stdout_str, status = Open3.capture2([env,] cmd... [, opts])
+  #
+  # The arguments env, cmd and opts are passed to Open3.popen3 except
+  # opts[:stdin_data] and opts[:stdin_data].  See Process.spawn.
+  #
+  # If opts[:stdin_data] is specified, it is sent to the command's standard input.
+  #
+  # If opts[:binmode] is true, internal pipes are set to binary mode.
+  #
+  # Example:
+  #
+  #   # factor is a command for integer factorization.
+  #   o, s = Open3.capture2("factor", :stdin_data=>"42")
+  #   p o #=> "42: 2 3 7\n"
+  #
+  #   # generate x**2 graph in png using gnuplot.
+  #   gnuplot_commands = <<"End"
+  #     set terminal png
+  #     plot x**2, "-" with lines
+  #     1 14
+  #     2 1
+  #     3 8
+  #     4 5
+  #     e
+  #   End
+  #   image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true)
+  #
+  def capture2(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
+
+    stdin_data = opts.delete(:stdin_data) || ''
+    binmode = opts.delete(:binmode)
+
+    popen2(*cmd, opts) {|i, o, t|
+      if binmode
+        i.binmode
+        o.binmode
+      end
+      out_reader = Thread.new { o.read }
+      i.write stdin_data
+      i.close
+      [out_reader.value, t.value]
+    }
+  end
+  module_function :capture2
+
+  # Open3.capture2e captures the standard output and the standard error of a command.
+  #
+  #   stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts])
+  #
+  # The arguments env, cmd and opts are passed to Open3.popen3 except
+  # opts[:stdin_data] and opts[:stdin_data].  See Process.spawn.
+  #
+  # If opts[:stdin_data] is specified, it is sent to the command's standard input.
+  #
+  # If opts[:binmode] is true, internal pipes are set to binary mode.
+  #
+  # Example:
+  #
+  #   # capture make log
+  #   make_log, s = Open3.capture2e("make")
+  #
+  def capture2e(*cmd, &block)
+    if Hash === cmd.last
+      opts = cmd.pop.dup
+    else
+      opts = {}
+    end
+
+    stdin_data = opts.delete(:stdin_data) || ''
+    binmode = opts.delete(:binmode)
+
+    popen2e(*cmd, opts) {|i, oe, t|
+      if binmode
+        i.binmode
+        oe.binmode
+      end
+      outerr_reader = Thread.new { oe.read }
+      i.write stdin_data
+      i.close
+      [outerr_reader.value, t.value]
+    }
+  end
+  module_function :capture2e
+
+  # Open3.pipeline_rw starts a list of commands as a pipeline with pipes
+  # which connects stdin of the first command and stdout of the last command.
+  #
+  #   Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads|
+  #     ...
+  #   }
+  #
+  #   first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts])
+  #   ...
+  #   first_stdin.close
+  #   last_stdout.close
+  #
+  # Each cmd is a string or an array.
+  # If it is an array, the elements are passed to Process.spawn.
+  #
+  #   cmd:
+  #     commandline                              command line string which is passed to a shell
+  #     [env, commandline, opts]                 command line string which is passed to a shell
+  #     [env, cmdname, arg1, ..., opts]          command name and one or more arguments (no shell)
+  #     [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+  #
+  #   Note that env and opts are optional, as Process.spawn.
+  #
+  # The option to pass Process.spawn is constructed by merging
+  # +opts+, the last hash element of the array and
+  # specification for the pipe between each commands.
+  #
+  # Example:
+  #
+  #   Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i,o,ts|
+  #     i.puts "All persons more than a mile high to leave the court."
+  #     i.close
+  #     p o.gets #=> "42\n"
+  #   }
+  #
+  #   Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
+  #     stdin.puts "foo"
+  #     stdin.puts "bar"
+  #     stdin.puts "baz"
+  #     stdin.close     # send EOF to sort.
+  #     p stdout.read   #=> "     1\tbar\n     2\tbaz\n     3\tfoo\n"
+  #   }
+  def pipeline_rw(*cmds, &block)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    in_r, in_w = IO.pipe
+    opts[:in] = in_r
+    in_w.sync = true
+
+    out_r, out_w = IO.pipe
+    opts[:out] = out_w
+
+    pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block)
+  end
+  module_function :pipeline_rw
+
+  # Open3.pipeline_r starts a list of commands as a pipeline with a pipe
+  # which connects stdout of the last command.
+  #
+  #   Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads|
+  #     ...
+  #   }
+  #
+  #   last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts])
+  #   ...
+  #   last_stdout.close
+  #
+  # Each cmd is a string or an array.
+  # If it is an array, the elements are passed to Process.spawn.
+  #
+  #   cmd:
+  #     commandline                              command line string which is passed to a shell
+  #     [env, commandline, opts]                 command line string which is passed to a shell
+  #     [env, cmdname, arg1, ..., opts]          command name and one or more arguments (no shell)
+  #     [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+  #
+  #   Note that env and opts are optional, as Process.spawn.
+  #
+  # Example:
+  #
+  #   Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz",
+  #                    [{"LANG"=>"C"}, "grep", "GET /favicon.ico"],
+  #                    "logresolve") {|o, ts|
+  #     o.each_line {|line|
+  #       ...
+  #     }
+  #   }
+  #
+  #   Open3.pipeline_r("yes", "head -10") {|o, ts|
+  #     p o.read      #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"
+  #     p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)>
+  #     p ts[1].value #=> #<Process::Status: pid 24913 exit 0>
+  #   }
+  #
+  def pipeline_r(*cmds, &block)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    out_r, out_w = IO.pipe
+    opts[:out] = out_w
+
+    pipeline_run(cmds, opts, [out_w], [out_r], &block)
+  end
+  module_function :pipeline_r
+
+  # Open3.pipeline_w starts a list of commands as a pipeline with a pipe
+  # which connects stdin of the first command.
+  #
+  #   Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads|
+  #     ...
+  #   }
+  #
+  #   first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts])
+  #   ...
+  #   first_stdin.close
+  #
+  # Each cmd is a string or an array.
+  # If it is an array, the elements are passed to Process.spawn.
+  #
+  #   cmd:
+  #     commandline                              command line string which is passed to a shell
+  #     [env, commandline, opts]                 command line string which is passed to a shell
+  #     [env, cmdname, arg1, ..., opts]          command name and one or more arguments (no shell)
+  #     [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+  #
+  #   Note that env and opts are optional, as Process.spawn.
+  #
+  # Example:
+  #
+  #   Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts|
+  #     i.puts "hello"
+  #   }
+  #
+  def pipeline_w(*cmds, &block)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    in_r, in_w = IO.pipe
+    opts[:in] = in_r
+    in_w.sync = true
+
+    pipeline_run(cmds, opts, [in_r], [in_w], &block)
+  end
+  module_function :pipeline_w
+
+  # Open3.pipeline_start starts a list of commands as a pipeline.
+  # No pipe made for stdin of the first command and
+  # stdout of the last command.
+  #
+  #   Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads|
+  #     ...
+  #   }
+  #
+  #   wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts])
+  #   ...
+  #
+  # Each cmd is a string or an array.
+  # If it is an array, the elements are passed to Process.spawn.
+  #
+  #   cmd:
+  #     commandline                              command line string which is passed to a shell
+  #     [env, commandline, opts]                 command line string which is passed to a shell
+  #     [env, cmdname, arg1, ..., opts]          command name and one or more arguments (no shell)
+  #     [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+  #
+  #   Note that env and opts are optional, as Process.spawn.
+  #
+  # Example:
+  #
+  #   # run xeyes in 10 seconds.
+  #   Open3.pipeline_start("xeyes") {|ts|
+  #     sleep 10
+  #     t = ts[0]
+  #     Process.kill("TERM", t.pid)
+  #     p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)>
+  #   }
+  #
+  #   # convert pdf to ps and send it to a printer.
+  #   # collect error message of pdftops and lpr.
+  #   pdf_file = "paper.pdf"
+  #   printer = "printer-name"
+  #   err_r, err_w = IO.pipe
+  #   Open3.pipeline_start(["pdftops", pdf_file, "-"],
+  #                        ["lpr", "-P#{printer}"],
+  #                        :err=>err_w) {|ts|
+  #     err_w.close
+  #     p err_r.read # error messages of pdftops and lpr.
+  #   }
+  #
+  def pipeline_start(*cmds, &block)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    if block
+      pipeline_run(cmds, opts, [], [], &block)
+    else
+      ts, = pipeline_run(cmds, opts, [], [])
+      ts
+    end
+  end
+  module_function :pipeline_start
+
+  # Open3.pipeline starts a list of commands as a pipeline.
+  # It waits the finish of the commands.
+  # No pipe made for stdin of the first command and
+  # stdout of the last command.
+  #
+  #   status_list = Open3.pipeline(cmd1, cmd2, ... [, opts])
+  #
+  # Each cmd is a string or an array.
+  # If it is an array, the elements are passed to Process.spawn.
+  #
+  #   cmd:
+  #     commandline                              command line string which is passed to a shell
+  #     [env, commandline, opts]                 command line string which is passed to a shell
+  #     [env, cmdname, arg1, ..., opts]          command name and one or more arguments (no shell)
+  #     [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+  #
+  #   Note that env and opts are optional, as Process.spawn.
+  #
+  # Example:
+  #
+  #   fname = "/usr/share/man/man1/ruby.1.gz"
+  #   p Open3.pipeline(["zcat", fname], "nroff -man", "less")
+  #   #=> [#<Process::Status: pid 11817 exit 0>,
+  #   #    #<Process::Status: pid 11820 exit 0>,
+  #   #    #<Process::Status: pid 11828 exit 0>]
+  #
+  #   fname = "/usr/share/man/man1/ls.1.gz"
+  #   Open3.pipeline(["zcat", fname], "nroff -man", "colcrt")
+  #
+  #   # convert PDF to PS and send to a printer by lpr
+  #   pdf_file = "paper.pdf"
+  #   printer = "printer-name"
+  #   Open3.pipeline(["pdftops", pdf_file, "-"],
+  #                  ["lpr", "-P#{printer}"])
+  #
+  #   # count lines
+  #   Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count")
+  #
+  #   # cyclic pipeline
+  #   r,w = IO.pipe
+  #   w.print "ibase=14\n10\n"
+  #   Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w)
+  #   #=> 14
+  #   #   18
+  #   #   22
+  #   #   30
+  #   #   42
+  #   #   58
+  #   #   78
+  #   #   106
+  #   #   202
+  #
+  def pipeline(*cmds)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    pipeline_run(cmds, opts, [], []) {|ts|
+      ts.map {|t| t.value }
+    }
+  end
+  module_function :pipeline
+
+  def pipeline_run(cmds, pipeline_opts, child_io, parent_io, &block) # :nodoc:
+    if cmds.empty?
+      raise ArgumentError, "no commands"
+    end
+
+    opts_base = pipeline_opts.dup
+    opts_base.delete :in
+    opts_base.delete :out
+
+    wait_thrs = []
+    r = nil
+    cmds.each_with_index {|cmd, i|
+      cmd_opts = opts_base.dup
+      if String === cmd
+        cmd = [cmd]
+      else
+        cmd_opts.update cmd.pop if Hash === cmd.last
+      end
+      if i == 0
+        if !cmd_opts.include?(:in)
+          if pipeline_opts.include?(:in)
+            cmd_opts[:in] = pipeline_opts[:in]
+          end
+        end
+      else
+        cmd_opts[:in] = r
+      end
+      if i != cmds.length - 1
+        r2, w2 = IO.pipe
+        cmd_opts[:out] = w2
+      else
+        if !cmd_opts.include?(:out)
+          if pipeline_opts.include?(:out)
+            cmd_opts[:out] = pipeline_opts[:out]
+          end
+        end
+      end
+      pid = spawn(*cmd, cmd_opts)
+      wait_thrs << Process.detach(pid)
+      r.close if r
+      w2.close if w2
+      r = r2
+    }
+    result = parent_io + [wait_thrs]
+    child_io.each {|io| io.close }
+    if defined? yield
+      begin
+	return yield(*result)
+      ensure
+	parent_io.each{|io| io.close unless io.closed?}
+        wait_thrs.each {|t| t.join }
+      end
+    end
+    result
+  end
+  module_function :pipeline_run
+  class << self
+    private :pipeline_run
+  end
+
 end
 
 if $0 == __FILE__

Modified: MacRuby/trunk/lib/optparse.rb
===================================================================
--- MacRuby/trunk/lib/optparse.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/optparse.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,15 +1,15 @@
 #
 # optparse.rb - command-line option analysis with the OptionParser class.
-# 
+#
 # Author:: Nobu Nakada
 # Documentation:: Nobu Nakada and Gavin Sinclair.
 #
-# See OptionParser for documentation. 
+# See OptionParser for documentation.
 #
 
 
-# == Developer Documentation (not for RDoc output) 
-# 
+# == Developer Documentation (not for RDoc output)
+#
 # === Class tree
 #
 # - OptionParser:: front end
@@ -51,7 +51,7 @@
 # solution.
 #
 # === Features
-# 
+#
 # 1. The argument specification and the code to handle it are written in the
 #    same place.
 # 2. It can output an option summary; you don't need to maintain this string
@@ -88,12 +88,12 @@
 #   require 'optparse/time'
 #   require 'ostruct'
 #   require 'pp'
-#   
+#
 #   class OptparseExample
-#   
+#
 #     CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
 #     CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
-#   
+#
 #     #
 #     # Return a structure describing the options.
 #     #
@@ -106,19 +106,19 @@
 #       options.encoding = "utf8"
 #       options.transfer_type = :auto
 #       options.verbose = false
-#       
+#
 #       opts = OptionParser.new do |opts|
 #         opts.banner = "Usage: example.rb [options]"
-#       
+#
 #         opts.separator ""
 #         opts.separator "Specific options:"
-#       
+#
 #         # Mandatory argument.
 #         opts.on("-r", "--require LIBRARY",
 #                 "Require the LIBRARY before executing your script") do |lib|
 #           options.library << lib
 #         end
-#       
+#
 #         # Optional argument; multi-line description.
 #         opts.on("-i", "--inplace [EXTENSION]",
 #                 "Edit ARGV files in place",
@@ -127,28 +127,28 @@
 #           options.extension = ext || ''
 #           options.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
 #         end
-#       
+#
 #         # Cast 'delay' argument to a Float.
 #         opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
 #           options.delay = n
 #         end
-#       
+#
 #         # Cast 'time' argument to a Time object.
 #         opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
 #           options.time = time
 #         end
-#       
+#
 #         # Cast to octal integer.
 #         opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
 #                 "Specify record separator (default \\0)") do |rs|
 #           options.record_separator = rs
 #         end
-#       
+#
 #         # List of arguments.
 #         opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
 #           options.list = list
 #         end
-#       
+#
 #         # Keyword completion.  We are specifying a specific set of arguments (CODES
 #         # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
 #         # the shortest unambiguous text.
@@ -157,41 +157,41 @@
 #                 "  (#{code_list})") do |encoding|
 #           options.encoding = encoding
 #         end
-#       
+#
 #         # Optional argument with keyword completion.
 #         opts.on("--type [TYPE]", [:text, :binary, :auto],
 #                 "Select transfer type (text, binary, auto)") do |t|
 #           options.transfer_type = t
 #         end
-#       
+#
 #         # Boolean switch.
 #         opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
 #           options.verbose = v
 #         end
-#       
+#
 #         opts.separator ""
 #         opts.separator "Common options:"
-#       
+#
 #         # No argument, shows at tail.  This will print an options summary.
 #         # Try it and see!
 #         opts.on_tail("-h", "--help", "Show this message") do
 #           puts opts
 #           exit
 #         end
-#       
+#
 #         # Another typical switch to print the version.
 #         opts.on_tail("--version", "Show version") do
 #           puts OptionParser::Version.join('.')
 #           exit
 #         end
 #       end
-#       
+#
 #       opts.parse!(args)
 #       options
 #     end  # parse()
-#   
+#
 #   end  # class OptparseExample
-#   
+#
 #   options = OptparseExample.parse(ARGV)
 #   pp options
 #
@@ -203,7 +203,7 @@
 #
 class OptionParser
   # :stopdoc:
-  RCSID = %w$Id: optparse.rb 21070 2008-12-26 11:16:16Z yugui $[1..-1].each {|s| s.freeze}.freeze
+  RCSID = %w$Id: optparse.rb 27089 2010-03-29 09:10:12Z nobu $[1..-1].each {|s| s.freeze}.freeze
   Version = (RCSID[1].split('.').collect {|s| s.to_i}.extend(Comparable).freeze if RCSID[1])
   LastModified = (Time.gm(*RCSID[2, 2].join('-').scan(/\d+/).collect {|s| s.to_i}) if RCSID[2])
   Release = RCSID[2]
@@ -276,7 +276,7 @@
   # Individual switch class.  Not important to the user.
   #
   # Defined within Switch are several Switch-derived classes: NoArgument,
-  # RequiredArgument, etc. 
+  # RequiredArgument, etc.
   #
   class Switch
     attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
@@ -384,10 +384,16 @@
         left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s
       end
 
-      left[0] << arg if arg
+      if arg
+        left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg)
+      end
       mlen = left.collect {|ss| ss.length}.max.to_i
       while mlen > width and l = left.shift
         mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen
+        if l.length < width and (r = right[0]) and !r.empty?
+          l = l.to_s.ljust(width) + ' ' + r
+          right.shift
+        end
         yield(indent + l)
       end
 
@@ -505,13 +511,13 @@
   class List
     # Map from acceptable argument types to pattern and converter pairs.
     attr_reader :atype
-    
+
     # Map from short style option switches to actual switch objects.
     attr_reader :short
-    
+
     # Map from long style option switches to actual switch objects.
     attr_reader :long
-    
+
     # List of all switches and summary string.
     attr_reader :list
 
@@ -528,7 +534,7 @@
     #
     # See OptionParser.accept.
     #
-    def accept(t, pat = /.*/nm, &block)
+    def accept(t, pat = /.*/m, &block)
       if pat
         pat.respond_to?(:match) or
           raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
@@ -568,7 +574,7 @@
     #
     # Inserts +switch+ at the head of the list, and associates short, long
     # and negated long options. Arguments are:
-    # 
+    #
     # +switch+::      OptionParser::Switch instance to be inserted.
     # +short_opts+::  List of short style options.
     # +long_opts+::   List of long style options.
@@ -584,7 +590,7 @@
     #
     # Appends +switch+ at the tail of the list, and associates short, long
     # and negated long options. Arguments are:
-    # 
+    #
     # +switch+::      OptionParser::Switch instance to be inserted.
     # +short_opts+::  List of short style options.
     # +long_opts+::   List of long style options.
@@ -750,7 +756,7 @@
   # Initializes a new instance and evaluates the optional block in context
   # of the instance. Arguments +args+ are passed to #new, see there for
   # description of parameters.
-  # 
+  #
   # This method is *deprecated*, its behavior corresponds to the older #new
   # method.
   #
@@ -1043,7 +1049,7 @@
   #   There is also a special form which matches character range (not full
   #   set of regular expression):
   #     "-[a-z]MANDATORY"
-  #     "-[a-z][OPTIONAL]" 
+  #     "-[a-z][OPTIONAL]"
   #     "-[a-z]"
   #
   # [Argument style and description:]
@@ -1055,7 +1061,7 @@
   # [Description:]
   #   Description string for the option.
   #     "Run verbosely"
-  # 
+  #
   # [Handler:]
   #   Handler for the parsed argument value. Either give a block or pass a
   #   Proc or Method as an argument.
@@ -1259,7 +1265,7 @@
       while arg = argv.shift
         case arg
         # long option
-        when /\A--([^=]*)(?:=(.*))?/nm
+        when /\A--([^=]*)(?:=(.*))?/m
           opt, rest = $1, $2
           begin
             sw, = complete(:long, opt, true)
@@ -1275,7 +1281,7 @@
           end
 
         # short option
-        when /\A-(.)((=).*|.+)?/nm
+        when /\A-(.)((=).*|.+)?/m
           opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
           begin
             sw, = search(:short, opt)
@@ -1298,7 +1304,7 @@
           begin
             opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
             raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
-            argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
+            argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
             val = cb.call(val) if cb
             setter.call(sw.switch_name, val) if setter
           rescue ParseError
@@ -1502,7 +1508,7 @@
   #
   # Any non-empty string, and no conversion.
   #
-  accept(String, /.+/nm) {|s,*|s}
+  accept(String, /.+/m) {|s,*|s}
 
   #
   # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
@@ -1525,9 +1531,16 @@
 
   #
   # Generic numeric format, converts to Integer for integer format, Float
-  # for float format.
+  # for float format, and Rational for rational format.
   #
-  accept(Numeric, %r"\A[-+]?(?:#{octal}|#{float})"io) {|s,| eval(s) if s}
+  real = "[-+]?(?:#{octal}|#{float})"
+  accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n|
+    if n
+      Rational(d, n)
+    elsif s
+      eval(s)
+    end
+  }
 
   #
   # Decimal integer format, to be converted to Integer.
@@ -1557,7 +1570,7 @@
   yesno = CompletingHash.new
   %w[- no false].each {|el| yesno[el] = false}
   %w[+ yes true].each {|el| yesno[el] = true}
-  yesno['nil'] = false          # shoud be nil?
+  yesno['nil'] = false          # should be nil?
   accept(TrueClass, yesno) {|arg, val| val == nil or val}
   #
   # Similar to TrueClass, but defaults to false.

Modified: MacRuby/trunk/lib/pathname.rb
===================================================================
--- MacRuby/trunk/lib/pathname.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/pathname.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -36,27 +36,27 @@
 # === Example 1: Using Pathname
 #
 #   require 'pathname'
-#   p = Pathname.new("/usr/bin/ruby")
-#   size = p.size              # 27662
-#   isdir = p.directory?       # false
-#   dir  = p.dirname           # Pathname:/usr/bin
-#   base = p.basename          # Pathname:ruby
-#   dir, base = p.split        # [Pathname:/usr/bin, Pathname:ruby]
-#   data = p.read
-#   p.open { |f| _ }
-#   p.each_line { |line| _ }
+#   pn = Pathname.new("/usr/bin/ruby")
+#   size = pn.size              # 27662
+#   isdir = pn.directory?       # false
+#   dir  = pn.dirname           # Pathname:/usr/bin
+#   base = pn.basename          # Pathname:ruby
+#   dir, base = pn.split        # [Pathname:/usr/bin, Pathname:ruby]
+#   data = pn.read
+#   pn.open { |f| _ }
+#   pn.each_line { |line| _ }
 #
 # === Example 2: Using standard Ruby
 #
-#   p = "/usr/bin/ruby"
-#   size = File.size(p)        # 27662
-#   isdir = File.directory?(p) # false
-#   dir  = File.dirname(p)     # "/usr/bin"
-#   base = File.basename(p)    # "ruby"
-#   dir, base = File.split(p)  # ["/usr/bin", "ruby"]
-#   data = File.read(p)
-#   File.open(p) { |f| _ }
-#   File.foreach(p) { |line| _ }
+#   pn = "/usr/bin/ruby"
+#   size = File.size(pn)        # 27662
+#   isdir = File.directory?(pn) # false
+#   dir  = File.dirname(pn)     # "/usr/bin"
+#   base = File.basename(pn)    # "ruby"
+#   dir, base = File.split(pn)  # ["/usr/bin", "ruby"]
+#   data = File.read(pn)
+#   File.open(pn) { |f| _ }
+#   File.foreach(pn) { |line| _ }
 #
 # === Example 3: Special features
 #
@@ -76,9 +76,9 @@
 #
 # === Core methods
 #
-# These methods are effectively manipulating a String, because that's all a path
-# is.  Except for #mountpoint?, #children, and #realpath, they don't access the
-# filesystem.
+# These methods are effectively manipulating a String, because that's
+# all a path is.  Except for #mountpoint?, #children, #each_child,
+# #realdirpath and #realpath, they don't access the filesystem.
 #
 # - +
 # - #join
@@ -90,7 +90,9 @@
 # - #each_filename
 # - #cleanpath
 # - #realpath
+# - #realdirpath
 # - #children
+# - #each_child
 # - #mountpoint?
 #
 # === File status predicate methods
@@ -165,6 +167,7 @@
 # These methods are a facade for IO:
 # - #each_line(*args, &block)
 # - #read(*args)
+# - #binread(*args)
 # - #readlines(*args)
 # - #sysopen(*args)
 #
@@ -194,6 +197,13 @@
     # to_path is implemented so Pathname objects are usable with File.open, etc.
     TO_PATH = :to_path
   end
+
+  SAME_PATHS = if File::FNM_SYSCASE.nonzero?
+    proc {|a, b| a.casecmp(b).zero?}
+  else
+    proc {|a, b| a == b}
+  end
+
   # :startdoc:
 
   #
@@ -204,9 +214,7 @@
     path = path.__send__(TO_PATH) if path.respond_to? TO_PATH
     @path = path.dup
 
-    # XXX work around a multibyte oniguruma problem in MacRuby
-    #if /\0/ =~ @path
-    if @path.include?("\0")
+    if /\0/ =~ @path
       raise ArgumentError, "pathname contains \\0: #{@path.inspect}"
     end
 
@@ -253,7 +261,21 @@
 
   # Return a pathname which is substituted by String#sub.
   def sub(pattern, *rest, &block)
-    self.class.new(@path.sub(pattern, *rest, &block))
+    if block
+      path = @path.sub(pattern, *rest) {|*args|
+        begin
+          old = Thread.current[:pathname_sub_matchdata]
+          Thread.current[:pathname_sub_matchdata] = $~
+          eval("$~ = Thread.current[:pathname_sub_matchdata]", block.binding)
+        ensure
+          Thread.current[:pathname_sub_matchdata] = old
+        end
+        yield(*args)
+      }
+    else
+      path = @path.sub(pattern, *rest)
+    end
+    self.class.new(path)
   end
 
   if File::ALT_SEPARATOR
@@ -276,7 +298,7 @@
   # chop_basename(path) -> [pre-basename, basename] or nil
   def chop_basename(path)
     base = File.basename(path)
-    if /\A#{SEPARATOR_PAT}?\z/ =~ base
+    if /\A#{SEPARATOR_PAT}?\z/o =~ base
       return nil
     else
       return path[0, path.rindex(base)], base
@@ -298,7 +320,7 @@
   def prepend_prefix(prefix, relpath)
     if relpath.empty?
       File.dirname(prefix)
-    elsif /#{SEPARATOR_PAT}/ =~ prefix
+    elsif /#{SEPARATOR_PAT}/o =~ prefix
       prefix = File.dirname(prefix)
       prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
       prefix + relpath
@@ -413,58 +435,25 @@
   end
   private :cleanpath_conservative
 
-  def realpath_rec(prefix, unresolved, h)
-    resolved = []
-    until unresolved.empty?
-      n = unresolved.shift
-      if n == '.'
-        next
-      elsif n == '..'
-        resolved.pop
-      else
-        path = prepend_prefix(prefix, File.join(*(resolved + [n])))
-        if h.include? path
-          if h[path] == :resolving
-            raise Errno::ELOOP.new(path)
-          else
-            prefix, *resolved = h[path]
-          end
-        else
-          s = File.lstat(path)
-          if s.symlink?
-            h[path] = :resolving
-            link_prefix, link_names = split_names(File.readlink(path))
-            if link_prefix == ''
-              prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h)
-            else
-              prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h)
-            end
-          else
-            resolved << n
-            h[path] = [prefix, *resolved]
-          end
-        end
-      end
-    end
-    return prefix, *resolved
+  #
+  # Returns the real (absolute) pathname of +self+ in the actual
+  # filesystem not containing symlinks or useless dots.
+  #
+  # All components of the pathname must exist when this method is
+  # called.
+  #
+  def realpath(basedir=nil)
+    self.class.new(File.realpath(@path, basedir))
   end
-  private :realpath_rec
 
   #
-  # Returns a real (absolute) pathname of +self+ in the actual filesystem.
+  # Returns the real (absolute) pathname of +self+ in the actual filesystem.
   # The real pathname doesn't contain symlinks or useless dots.
   #
-  # No arguments should be given; the old behaviour is *obsoleted*.
+  # The last component of the real pathname can be nonexistent.
   #
-  def realpath
-    path = @path
-    prefix, names = split_names(path)
-    if prefix == ''
-      prefix, names2 = split_names(Dir.pwd)
-      names = names2 + names
-    end
-    prefix, *names = realpath_rec(prefix, names, {})
-    self.class.new(prepend_prefix(prefix, File.join(*names)))
+  def realdirpath(basedir=nil)
+    self.class.new(File.realdirpath(@path, basedir))
   end
 
   # #parent returns the parent directory.
@@ -666,12 +655,12 @@
   # filename only.
   #
   # For example:
-  #   p = Pathname("/usr/lib/ruby/1.8")
-  #   p.children
+  #   pn = Pathname("/usr/lib/ruby/1.8")
+  #   pn.children
   #       # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
   #              Pathname:/usr/lib/ruby/1.8/Env.rb,
   #              Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
-  #   p.children(false)
+  #   pn.children(false)
   #       # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
   #
   # Note that the result never contain the entries <tt>.</tt> and <tt>..</tt> in
@@ -693,7 +682,37 @@
     result
   end
 
+  # Iterates over the children of the directory
+  # (files and subdirectories, not recursive).
+  # It yields Pathname object for each child.
+  # By default, the yielded pathnames will have enough information to access the files.
+  # If you set +with_directory+ to +false+, then the returned pathnames will contain the filename only.
   #
+  #   Pathname("/usr/local").each_child {|f| p f }
+  #   #=> #<Pathname:/usr/local/share>
+  #   #   #<Pathname:/usr/local/bin>
+  #   #   #<Pathname:/usr/local/games>
+  #   #   #<Pathname:/usr/local/lib>
+  #   #   #<Pathname:/usr/local/include>
+  #   #   #<Pathname:/usr/local/sbin>
+  #   #   #<Pathname:/usr/local/src>
+  #   #   #<Pathname:/usr/local/man>
+  #
+  #   Pathname("/usr/local").each_child(false) {|f| p f }
+  #   #=> #<Pathname:share>
+  #   #   #<Pathname:bin>
+  #   #   #<Pathname:games>
+  #   #   #<Pathname:lib>
+  #   #   #<Pathname:include>
+  #   #   #<Pathname:sbin>
+  #   #   #<Pathname:src>
+  #   #   #<Pathname:man>
+  #
+  def each_child(with_directory=true, &b)
+    children(with_directory).each(&b)
+  end
+
+  #
   # #relative_path_from returns a relative path from the argument to the
   # receiver.  If +self+ is absolute, the argument must be absolute too.  If
   # +self+ is relative, the argument must be relative too.
@@ -719,12 +738,12 @@
       base_prefix, basename = r
       base_names.unshift basename if basename != '.'
     end
-    if dest_prefix != base_prefix
+    unless SAME_PATHS[dest_prefix, base_prefix]
       raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
     end
     while !dest_names.empty? &&
           !base_names.empty? &&
-          dest_names.first == base_names.first
+          SAME_PATHS[dest_names.first, base_names.first]
       dest_names.shift
       base_names.shift
     end
@@ -752,16 +771,14 @@
     IO.foreach(@path, *args, &block)
   end
 
-  # Pathname#foreachline is *obsoleted* at 1.8.1.  Use #each_line.
-  def foreachline(*args, &block)
-    warn "Pathname#foreachline is obsoleted.  Use Pathname#each_line."
-    each_line(*args, &block)
-  end
-
-  # See <tt>IO.read</tt>.  Returns all the bytes from the file, or the first +N+
+  # See <tt>IO.read</tt>.  Returns all data from the file, or the first +N+ bytes
   # if specified.
   def read(*args) IO.read(@path, *args) end
 
+  # See <tt>IO.binread</tt>.  Returns all the bytes from the file, or the first +N+
+  # if specified.
+  def binread(*args) IO.binread(@path, *args) end
+
   # See <tt>IO.readlines</tt>.  Returns all the lines from the file.
   def readlines(*args) IO.readlines(@path, *args) end
 
@@ -848,20 +865,6 @@
   # See <tt>File.split</tt>.  Returns the #dirname and the #basename in an
   # Array.
   def split() File.split(@path).map {|f| self.class.new(f) } end
-
-  # Pathname#link is confusing and *obsoleted* because the receiver/argument
-  # order is inverted to corresponding system call.
-  def link(old)
-    warn 'Pathname#link is obsoleted.  Use Pathname#make_link.'
-    File.link(old, @path)
-  end
-
-  # Pathname#symlink is confusing and *obsoleted* because the receiver/argument
-  # order is inverted to corresponding system call.
-  def symlink(old)
-    warn 'Pathname#symlink is obsoleted.  Use Pathname#make_symlink.'
-    File.symlink(old, @path)
-  end
 end
 
 
@@ -943,7 +946,7 @@
 
 class Pathname    # * Dir *
   # See <tt>Dir.glob</tt>.  Returns or yields Pathname objects.
-  def Pathname.glob(*args) # :yield: p
+  def Pathname.glob(*args) # :yield: pathname
     if block_given?
       Dir.glob(*args) {|f| yield self.new(f) }
     else
@@ -955,18 +958,6 @@
   def Pathname.getwd() self.new(Dir.getwd) end
   class << self; alias pwd getwd end
 
-  # Pathname#chdir is *obsoleted* at 1.8.1.
-  def chdir(&block)
-    warn "Pathname#chdir is obsoleted.  Use Dir.chdir."
-    Dir.chdir(@path, &block)
-  end
-
-  # Pathname#chroot is *obsoleted* at 1.8.1.
-  def chroot
-    warn "Pathname#chroot is obsoleted.  Use Dir.chroot."
-    Dir.chroot(@path)
-  end
-
   # Return the entries (files and subdirectories) in the directory, each as a
   # Pathname object.
   def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
@@ -975,16 +966,10 @@
   # yields a Pathname object for each entry.
   #
   # This method has existed since 1.8.1.
-  def each_entry(&block) # :yield: p
+  def each_entry(&block) # :yield: pathname
     Dir.foreach(@path) {|f| yield self.class.new(f) }
   end
 
-  # Pathname#dir_foreach is *obsoleted* at 1.8.1.
-  def dir_foreach(*args, &block)
-    warn "Pathname#dir_foreach is obsoleted.  Use Pathname#each_entry."
-    each_entry(*args, &block)
-  end
-
   # See <tt>Dir.mkdir</tt>.  Create the referenced directory.
   def mkdir(*args) Dir.mkdir(@path, *args) end
 
@@ -1009,7 +994,7 @@
   # If +self+ is <tt>.</tt>, yielded pathnames begin with a filename in the
   # current directory, not <tt>./</tt>.
   #
-  def find(&block) # :yield: p
+  def find(&block) # :yield: pathname
     require 'find'
     if @path == '.'
       Find.find(@path) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
@@ -1051,18 +1036,6 @@
     end
   end
   alias delete unlink
-
-  # This method is *obsoleted* at 1.8.1.  Use #each_line or #each_entry.
-  def foreach(*args, &block)
-    warn "Pathname#foreach is obsoleted.  Use each_line or each_entry."
-    if FileTest.directory? @path
-      # For polymorphism between Dir.foreach and IO.foreach,
-      # Pathname#foreach doesn't yield Pathname object.
-      Dir.foreach(@path, *args, &block)
-    else
-      IO.foreach(@path, *args, &block)
-    end
-  end
 end
 
 class Pathname

Modified: MacRuby/trunk/lib/pp.rb
===================================================================
--- MacRuby/trunk/lib/pp.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/pp.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -54,12 +54,12 @@
   private
   # prints arguments in pretty form.
   #
-  # pp returns nil.
+  # pp returns argument(s).
   def pp(*objs) # :doc:
     objs.each {|obj|
       PP.pp(obj)
     }
-    nil
+    objs.size <= 1 ? objs.first : objs
   end
   module_function :pp
 end
@@ -107,17 +107,17 @@
   module PPMethods
     def guard_inspect_key
       if Thread.current[:__recursive_key__] == nil
-        Thread.current[:__recursive_key__] = {}
+        Thread.current[:__recursive_key__] = {}.untrust
       end
 
       if Thread.current[:__recursive_key__][:inspect] == nil
-        Thread.current[:__recursive_key__][:inspect] = {}
+        Thread.current[:__recursive_key__][:inspect] = {}.untrust
       end
 
       save = Thread.current[:__recursive_key__][:inspect]
 
       begin
-        Thread.current[:__recursive_key__][:inspect] = {}
+        Thread.current[:__recursive_key__][:inspect] = {}.untrust
         yield
       ensure
         Thread.current[:__recursive_key__][:inspect] = save
@@ -164,13 +164,7 @@
       group(1, '#<' + obj.class.name, '>', &block)
     end
 
-    if 0x100000000.class == Bignum
-      # 32bit
-      PointerMask = 0xffffffff
-    else
-      # 64bit
-      PointerMask = 0xffffffffffffffff
-    end
+    PointerMask = (1 << ([""].pack("p").size * 8)) - 1
 
     case Object.new.inspect
     when /\A\#<Object:0x([0-9a-f]+)>\z/
@@ -270,7 +264,7 @@
   module ObjectMixin
     # 1. specific pretty_print
     # 2. specific inspect
-    # 3. specific to_s if instance variable is empty
+    # 3. specific to_s
     # 4. generic pretty_print
 
     # A default pretty printing method for general objects.
@@ -283,10 +277,23 @@
     # This module provides predefined #pretty_print methods for some of
     # the most commonly used built-in classes for convenience.
     def pretty_print(q)
-      if /\(Kernel\)#/ !~ Object.instance_method(:method).bind(self).call(:inspect).inspect
+      method_method = Object.instance_method(:method).bind(self)
+      begin
+        inspect_method = method_method.call(:inspect)
+      rescue NameError
+      end
+      begin
+        to_s_method = method_method.call(:to_s)
+      rescue NameError
+      end
+      if inspect_method && /\(Kernel\)#/ !~ inspect_method.inspect
         q.text self.inspect
-      elsif /\(Kernel\)#/ !~ Object.instance_method(:method).bind(self).call(:to_s).inspect && instance_variables.empty?
+      elsif !inspect_method && self.respond_to?(:inspect)
+        q.text self.inspect
+      elsif to_s_method && /\(Kernel\)#/ !~ to_s_method.inspect
         q.text self.to_s
+      elsif !to_s_method && self.respond_to?(:to_s)
+        q.text self.to_s
       else
         q.pp_object(self)
       end
@@ -361,7 +368,7 @@
 
 class Struct
   def pretty_print(q)
-    q.group(1, '#<struct ' + PP.mcall(self, Kernel, :class).name, '>') {
+    q.group(1, sprintf("#<struct %s", PP.mcall(self, Kernel, :class).name), '>') {
       q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
         q.breakable
         q.text member.to_s
@@ -515,186 +522,3 @@
     end
   }
 }
-
-# :enddoc:
-if __FILE__ == $0
-  require 'test/unit'
-
-  class PPTest < Test::Unit::TestCase
-    def test_list0123_12
-      assert_equal("[0, 1, 2, 3]\n", PP.pp([0,1,2,3], '', 12))
-    end
-
-    def test_list0123_11
-      assert_equal("[0,\n 1,\n 2,\n 3]\n", PP.pp([0,1,2,3], '', 11))
-    end
-
-    OverriddenStruct = Struct.new("OverriddenStruct", :members, :class)
-    def test_struct_override_members # [ruby-core:7865]
-      a = OverriddenStruct.new(1,2)
-      assert_equal("#<struct Struct::OverriddenStruct members=1, class=2>\n", PP.pp(a, ''))
-    end
-
-    def test_redefined_method
-      o = ""
-      def o.method
-      end
-      assert_equal(%(""\n), PP.pp(o, ""))
-    end
-  end
-
-  class HasInspect
-    def initialize(a)
-      @a = a
-    end
-
-    def inspect
-      return "<inspect:#{@a.inspect}>"
-    end
-  end
-
-  class HasPrettyPrint
-    def initialize(a)
-      @a = a
-    end
-
-    def pretty_print(q)
-      q.text "<pretty_print:"
-      q.pp @a
-      q.text ">"
-    end
-  end
-
-  class HasBoth
-    def initialize(a)
-      @a = a
-    end
-
-    def inspect
-      return "<inspect:#{@a.inspect}>"
-    end
-
-    def pretty_print(q)
-      q.text "<pretty_print:"
-      q.pp @a
-      q.text ">"
-    end
-  end
-
-  class PrettyPrintInspect < HasPrettyPrint
-    alias inspect pretty_print_inspect
-  end
-
-  class PrettyPrintInspectWithoutPrettyPrint
-    alias inspect pretty_print_inspect
-  end
-
-  class PPInspectTest < Test::Unit::TestCase
-    def test_hasinspect
-      a = HasInspect.new(1)
-      assert_equal("<inspect:1>\n", PP.pp(a, ''))
-    end
-
-    def test_hasprettyprint
-      a = HasPrettyPrint.new(1)
-      assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
-    end
-
-    def test_hasboth
-      a = HasBoth.new(1)
-      assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
-    end
-
-    def test_pretty_print_inspect
-      a = PrettyPrintInspect.new(1)
-      assert_equal("<pretty_print:1>", a.inspect)
-      a = PrettyPrintInspectWithoutPrettyPrint.new
-      assert_raise(RuntimeError) { a.inspect }
-    end
-
-    def test_proc
-      a = proc {1}
-      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
-    end
-
-    def test_to_s_with_iv
-      a = Object.new
-      def a.to_s() "aaa" end
-      a.instance_eval { @a = nil }
-      result = PP.pp(a, '')
-      assert_equal("#{a.inspect}\n", result)
-      assert_match(/\A#<Object.*>\n\z/m, result)
-      a = 1.0
-      a.instance_eval { @a = nil }
-      result = PP.pp(a, '')
-      assert_equal("#{a.inspect}\n", result)
-    end
-
-    def test_to_s_without_iv
-      a = Object.new
-      def a.to_s() "aaa" end
-      result = PP.pp(a, '')
-      assert_equal("#{a.inspect}\n", result)
-      assert_equal("aaa\n", result)
-    end
-  end
-
-  class PPCycleTest < Test::Unit::TestCase
-    def test_array
-      a = []
-      a << a
-      assert_equal("[[...]]\n", PP.pp(a, ''))
-      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
-    end
-
-    def test_hash
-      a = {}
-      a[0] = a
-      assert_equal("{0=>{...}}\n", PP.pp(a, ''))
-      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
-    end
-
-    S = Struct.new("S", :a, :b)
-    def test_struct
-      a = S.new(1,2)
-      a.b = a
-      assert_equal("#<struct Struct::S a=1, b=#<struct Struct::S:...>>\n", PP.pp(a, ''))
-      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
-    end
-
-    def test_object
-      a = Object.new
-      a.instance_eval {@a = a}
-      assert_equal(a.inspect + "\n", PP.pp(a, ''))
-    end
-
-    def test_anonymous
-      a = Class.new.new
-      assert_equal(a.inspect + "\n", PP.pp(a, ''))
-    end
-
-    def test_withinspect
-      a = []
-      a << HasInspect.new(a)
-      assert_equal("[<inspect:[...]>]\n", PP.pp(a, ''))
-      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
-    end
-
-    def test_share_nil
-      begin
-        PP.sharing_detection = true
-        a = [nil, nil]
-        assert_equal("[nil, nil]\n", PP.pp(a, ''))
-      ensure
-        PP.sharing_detection = false
-      end
-    end
-  end
-
-  class PPSingleLineTest < Test::Unit::TestCase
-    def test_hash
-      assert_equal("{1=>1}", PP.singleline_pp({ 1 => 1}, '')) # [ruby-core:02699]
-      assert_equal("[1#{', 1'*99}]", PP.singleline_pp([1]*100, ''))
-    end
-  end
-end

Modified: MacRuby/trunk/lib/prettyprint.rb
===================================================================
--- MacRuby/trunk/lib/prettyprint.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/prettyprint.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-# $Id$
-
 # This class implements a pretty printing algorithm. It finds line breaks and
 # nice indentations for grouped structure.
 #
@@ -377,520 +375,3 @@
     end
   end
 end
-
-if __FILE__ == $0
-  require 'test/unit'
-
-  class WadlerExample < Test::Unit::TestCase # :nodoc:
-    def setup
-      @tree = Tree.new("aaaa", Tree.new("bbbbb", Tree.new("ccc"),
-                                                 Tree.new("dd")),
-                               Tree.new("eee"),
-                               Tree.new("ffff", Tree.new("gg"),
-                                                Tree.new("hhh"),
-                                                Tree.new("ii")))
-    end
-
-    def hello(width)
-      PrettyPrint.format('', width) {|hello|
-        hello.group {
-          hello.group {
-            hello.group {
-              hello.group {
-                hello.text 'hello'
-                hello.breakable; hello.text 'a'
-              }
-              hello.breakable; hello.text 'b'
-            }
-            hello.breakable; hello.text 'c'
-          }
-          hello.breakable; hello.text 'd'
-        }
-      }
-    end
-
-    def test_hello_00_06
-      expected = <<'End'.chomp
-hello
-a
-b
-c
-d
-End
-      assert_equal(expected, hello(0))
-      assert_equal(expected, hello(6))
-    end
-
-    def test_hello_07_08
-      expected = <<'End'.chomp
-hello a
-b
-c
-d
-End
-      assert_equal(expected, hello(7))
-      assert_equal(expected, hello(8))
-    end
-
-    def test_hello_09_10
-      expected = <<'End'.chomp
-hello a b
-c
-d
-End
-      out = hello(9); assert_equal(expected, out)
-      out = hello(10); assert_equal(expected, out)
-    end
-
-    def test_hello_11_12
-      expected = <<'End'.chomp
-hello a b c
-d
-End
-      assert_equal(expected, hello(11))
-      assert_equal(expected, hello(12))
-    end
-
-    def test_hello_13
-      expected = <<'End'.chomp
-hello a b c d
-End
-      assert_equal(expected, hello(13))
-    end
-
-    def tree(width)
-      PrettyPrint.format('', width) {|q| @tree.show(q)}
-    end
-
-    def test_tree_00_19
-      expected = <<'End'.chomp
-aaaa[bbbbb[ccc,
-           dd],
-     eee,
-     ffff[gg,
-          hhh,
-          ii]]
-End
-      assert_equal(expected, tree(0))
-      assert_equal(expected, tree(19))
-    end
-
-    def test_tree_20_22
-      expected = <<'End'.chomp
-aaaa[bbbbb[ccc, dd],
-     eee,
-     ffff[gg,
-          hhh,
-          ii]]
-End
-      assert_equal(expected, tree(20))
-      assert_equal(expected, tree(22))
-    end
-
-    def test_tree_23_43
-      expected = <<'End'.chomp
-aaaa[bbbbb[ccc, dd],
-     eee,
-     ffff[gg, hhh, ii]]
-End
-      assert_equal(expected, tree(23))
-      assert_equal(expected, tree(43))
-    end
-
-    def test_tree_44
-      assert_equal(<<'End'.chomp, tree(44))
-aaaa[bbbbb[ccc, dd], eee, ffff[gg, hhh, ii]]
-End
-    end
-
-    def tree_alt(width)
-      PrettyPrint.format('', width) {|q| @tree.altshow(q)}
-    end
-
-    def test_tree_alt_00_18
-      expected = <<'End'.chomp
-aaaa[
-  bbbbb[
-    ccc,
-    dd
-  ],
-  eee,
-  ffff[
-    gg,
-    hhh,
-    ii
-  ]
-]
-End
-      assert_equal(expected, tree_alt(0))
-      assert_equal(expected, tree_alt(18))
-    end
-
-    def test_tree_alt_19_20
-      expected = <<'End'.chomp
-aaaa[
-  bbbbb[ ccc, dd ],
-  eee,
-  ffff[
-    gg,
-    hhh,
-    ii
-  ]
-]
-End
-      assert_equal(expected, tree_alt(19))
-      assert_equal(expected, tree_alt(20))
-    end
-
-    def test_tree_alt_20_49
-      expected = <<'End'.chomp
-aaaa[
-  bbbbb[ ccc, dd ],
-  eee,
-  ffff[ gg, hhh, ii ]
-]
-End
-      assert_equal(expected, tree_alt(21))
-      assert_equal(expected, tree_alt(49))
-    end
-
-    def test_tree_alt_50
-      expected = <<'End'.chomp
-aaaa[ bbbbb[ ccc, dd ], eee, ffff[ gg, hhh, ii ] ]
-End
-      assert_equal(expected, tree_alt(50))
-    end
-
-    class Tree # :nodoc:
-      def initialize(string, *children)
-        @string = string
-        @children = children
-      end
-
-      def show(q)
-        q.group {
-          q.text @string
-          q.nest(@string.length) {
-            unless @children.empty?
-              q.text '['
-              q.nest(1) {
-                first = true
-                @children.each {|t|
-                  if first
-                    first = false
-                  else
-                    q.text ','
-                    q.breakable
-                  end
-                  t.show(q)
-                }
-              }
-              q.text ']'
-            end
-          }
-        }
-      end
-
-      def altshow(q)
-        q.group {
-          q.text @string
-          unless @children.empty?
-            q.text '['
-            q.nest(2) {
-              q.breakable
-              first = true
-              @children.each {|t|
-                if first
-                  first = false
-                else
-                  q.text ','
-                  q.breakable
-                end
-                t.altshow(q)
-              }
-            }
-            q.breakable
-            q.text ']'
-          end
-        }
-      end
-
-    end
-  end
-
-  class StrictPrettyExample < Test::Unit::TestCase # :nodoc:
-    def prog(width)
-      PrettyPrint.format('', width) {|q|
-        q.group {
-          q.group {q.nest(2) {
-                       q.text "if"; q.breakable;
-                       q.group {
-                         q.nest(2) {
-                           q.group {q.text "a"; q.breakable; q.text "=="}
-                           q.breakable; q.text "b"}}}}
-          q.breakable
-          q.group {q.nest(2) {
-                       q.text "then"; q.breakable;
-                       q.group {
-                         q.nest(2) {
-                           q.group {q.text "a"; q.breakable; q.text "<<"}
-                           q.breakable; q.text "2"}}}}
-          q.breakable
-          q.group {q.nest(2) {
-                       q.text "else"; q.breakable;
-                       q.group {
-                         q.nest(2) {
-                           q.group {q.text "a"; q.breakable; q.text "+"}
-                           q.breakable; q.text "b"}}}}}
-      }
-    end
-
-    def test_00_04
-      expected = <<'End'.chomp
-if
-  a
-    ==
-    b
-then
-  a
-    <<
-    2
-else
-  a
-    +
-    b
-End
-      assert_equal(expected, prog(0))
-      assert_equal(expected, prog(4))
-    end
-
-    def test_05
-      expected = <<'End'.chomp
-if
-  a
-    ==
-    b
-then
-  a
-    <<
-    2
-else
-  a +
-    b
-End
-      assert_equal(expected, prog(5))
-    end
-
-    def test_06
-      expected = <<'End'.chomp
-if
-  a ==
-    b
-then
-  a <<
-    2
-else
-  a +
-    b
-End
-      assert_equal(expected, prog(6))
-    end
-
-    def test_07
-      expected = <<'End'.chomp
-if
-  a ==
-    b
-then
-  a <<
-    2
-else
-  a + b
-End
-      assert_equal(expected, prog(7))
-    end
-
-    def test_08
-      expected = <<'End'.chomp
-if
-  a == b
-then
-  a << 2
-else
-  a + b
-End
-      assert_equal(expected, prog(8))
-    end
-
-    def test_09
-      expected = <<'End'.chomp
-if a == b
-then
-  a << 2
-else
-  a + b
-End
-      assert_equal(expected, prog(9))
-    end
-
-    def test_10
-      expected = <<'End'.chomp
-if a == b
-then
-  a << 2
-else a + b
-End
-      assert_equal(expected, prog(10))
-    end
-
-    def test_11_31
-      expected = <<'End'.chomp
-if a == b
-then a << 2
-else a + b
-End
-      assert_equal(expected, prog(11))
-      assert_equal(expected, prog(15))
-      assert_equal(expected, prog(31))
-    end
-
-    def test_32
-      expected = <<'End'.chomp
-if a == b then a << 2 else a + b
-End
-      assert_equal(expected, prog(32))
-    end
-
-  end
-
-  class TailGroup < Test::Unit::TestCase # :nodoc:
-    def test_1
-      out = PrettyPrint.format('', 10) {|q|
-        q.group {
-          q.group {
-            q.text "abc"
-            q.breakable
-            q.text "def"
-          }
-          q.group {
-            q.text "ghi"
-            q.breakable
-            q.text "jkl"
-          }
-        }
-      }
-      assert_equal("abc defghi\njkl", out)
-    end
-  end
-
-  class NonString < Test::Unit::TestCase # :nodoc:
-    def format(width)
-      PrettyPrint.format([], width, 'newline', lambda {|n| "#{n} spaces"}) {|q|
-        q.text(3, 3)
-        q.breakable(1, 1)
-        q.text(3, 3)
-      }
-    end
-
-    def test_6
-      assert_equal([3, "newline", "0 spaces", 3], format(6))
-    end
-
-    def test_7
-      assert_equal([3, 1, 3], format(7))
-    end
-
-  end
-
-  class Fill < Test::Unit::TestCase # :nodoc:
-    def format(width)
-      PrettyPrint.format('', width) {|q|
-        q.group {
-          q.text 'abc'
-          q.fill_breakable
-          q.text 'def'
-          q.fill_breakable
-          q.text 'ghi'
-          q.fill_breakable
-          q.text 'jkl'
-          q.fill_breakable
-          q.text 'mno'
-          q.fill_breakable
-          q.text 'pqr'
-          q.fill_breakable
-          q.text 'stu'
-        }
-      }
-    end
-
-    def test_00_06
-      expected = <<'End'.chomp
-abc
-def
-ghi
-jkl
-mno
-pqr
-stu
-End
-      assert_equal(expected, format(0))
-      assert_equal(expected, format(6))
-    end
-
-    def test_07_10
-      expected = <<'End'.chomp
-abc def
-ghi jkl
-mno pqr
-stu
-End
-      assert_equal(expected, format(7))
-      assert_equal(expected, format(10))
-    end
-
-    def test_11_14
-      expected = <<'End'.chomp
-abc def ghi
-jkl mno pqr
-stu
-End
-      assert_equal(expected, format(11))
-      assert_equal(expected, format(14))
-    end
-
-    def test_15_18
-      expected = <<'End'.chomp
-abc def ghi jkl
-mno pqr stu
-End
-      assert_equal(expected, format(15))
-      assert_equal(expected, format(18))
-    end
-
-    def test_19_22
-      expected = <<'End'.chomp
-abc def ghi jkl mno
-pqr stu
-End
-      assert_equal(expected, format(19))
-      assert_equal(expected, format(22))
-    end
-
-    def test_23_26
-      expected = <<'End'.chomp
-abc def ghi jkl mno pqr
-stu
-End
-      assert_equal(expected, format(23))
-      assert_equal(expected, format(26))
-    end
-
-    def test_27
-      expected = <<'End'.chomp
-abc def ghi jkl mno pqr stu
-End
-      assert_equal(expected, format(27))
-    end
-
-  end
-end

Modified: MacRuby/trunk/lib/pstore.rb
===================================================================
--- MacRuby/trunk/lib/pstore.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/pstore.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -15,49 +15,49 @@
 #
 # PStore implements a file based persistence mechanism based on a Hash.  User
 # code can store hierarchies of Ruby objects (values) into the data store file
-# by name (keys).  An object hierarchy may be just a single object.  User code 
+# by name (keys).  An object hierarchy may be just a single object.  User code
 # may later read values back from the data store or even update data, as needed.
-# 
+#
 # The transactional behavior ensures that any changes succeed or fail together.
 # This can be used to ensure that the data store is not left in a transitory
 # state, where some values were updated but others were not.
-# 
-# Behind the scenes, Ruby objects are stored to the data store file with 
-# Marshal.  That carries the usual limitations.  Proc objects cannot be 
+#
+# Behind the scenes, Ruby objects are stored to the data store file with
+# Marshal.  That carries the usual limitations.  Proc objects cannot be
 # marshalled, for example.
 #
 # == Usage example:
-# 
+#
 #  require "pstore"
-#  
+#
 #  # a mock wiki object...
 #  class WikiPage
 #    def initialize( page_name, author, contents )
 #      @page_name = page_name
 #      @revisions = Array.new
-#      
+#
 #      add_revision(author, contents)
 #    end
-#    
+#
 #    attr_reader :page_name
-#    
+#
 #    def add_revision( author, contents )
 #      @revisions << { :created  => Time.now,
 #                      :author   => author,
 #                      :contents => contents }
 #    end
-#    
+#
 #    def wiki_page_references
 #      [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
 #    end
-#    
+#
 #    # ...
 #  end
-#  
+#
 #  # create a new page...
 #  home_page = WikiPage.new( "HomePage", "James Edward Gray II",
 #                            "A page about the JoysOfDocumentation..." )
-#  
+#
 #  # then we want to update page data and the index together, or not at all...
 #  wiki = PStore.new("wiki_pages.pstore")
 #  wiki.transaction do  # begin transaction; do all of this or none of it
@@ -68,9 +68,9 @@
 #    # update wiki index...
 #    wiki[:wiki_index].push(*home_page.wiki_page_references)
 #  end                   # commit changes to wiki data store file
-#  
+#
 #  ### Some time later... ###
-#  
+#
 #  # read wiki data...
 #  wiki.transaction(true) do  # begin read-only transaction, no changes allowed
 #    wiki.roots.each do |data_root_name|
@@ -102,7 +102,7 @@
   # The error type thrown by all PStore methods.
   class Error < StandardError
   end
-  
+
   # Whether PStore should do its best to prevent file corruptions, even when under
   # unlikely-to-occur error conditions such as out-of-space conditions and other
   # unusual OS filesystem errors. Setting this flag comes at the price in the form
@@ -112,13 +112,13 @@
   # all POSIX platforms: Linux, MacOS X, FreeBSD, etc). The default value is false.
   attr_accessor :ultra_safe
 
-  # 
-  # To construct a PStore object, pass in the _file_ path where you would like 
+  #
+  # To construct a PStore object, pass in the _file_ path where you would like
   # the data to be stored.
   #
   # PStore objects are always reentrant. But if _thread_safe_ is set to true,
   # then it will become thread-safe at the cost of a minor performance hit.
-  # 
+  #
   def initialize(file, thread_safe = false)
     dir = File::dirname(file)
     unless File::directory? dir
@@ -131,6 +131,7 @@
     @filename = file
     @abort = false
     @ultra_safe = false
+    @thread_safe = thread_safe
     if @thread_safe
       @lock = Mutex.new
     else
@@ -142,10 +143,10 @@
   def in_transaction
     raise PStore::Error, "not in transaction" unless @transaction
   end
-  # 
+  #
   # Raises PStore::Error if the calling code is not in a PStore#transaction or
   # if the code is in a read-only PStore#transaction.
-  # 
+  #
   def in_transaction_wr()
     in_transaction()
     raise PStore::Error, "in read-only transaction" if @rdonly
@@ -153,9 +154,9 @@
   private :in_transaction, :in_transaction_wr
 
   #
-  # Retrieves a value from the PStore file data, by _name_.  The hierarchy of 
+  # Retrieves a value from the PStore file data, by _name_.  The hierarchy of
   # Ruby objects stored under that root _name_ will be returned.
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -164,12 +165,12 @@
     @table[name]
   end
   #
-  # This method is just like PStore#[], save that you may also provide a 
-  # _default_ value for the object.  In the event the specified _name_ is not 
-  # found in the data store, your _default_ will be returned instead.  If you do 
-  # not specify a default, PStore::Error will be raised if the object is not 
+  # This method is just like PStore#[], save that you may also provide a
+  # _default_ value for the object.  In the event the specified _name_ is not
+  # found in the data store, your _default_ will be returned instead.  If you do
+  # not specify a default, PStore::Error will be raised if the object is not
   # found.
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -188,11 +189,11 @@
   # Stores an individual Ruby object or a hierarchy of Ruby objects in the data
   # store file under the root _name_.  Assigning to a _name_ already in the data
   # store clobbers the old data.
-  # 
+  #
   # == Example:
-  # 
+  #
   #  require "pstore"
-  #  
+  #
   #  store = PStore.new("data_file.pstore")
   #  store.transaction do  # begin transaction
   #    # load some data into the store...
@@ -200,7 +201,7 @@
   #    store[:obj_heirarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"],
   #                              "James Gray"  => ["erb.rb", "pstore.rb"] }
   #  end                   # commit changes to data store file
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction and it cannot
   # be read-only.  It will raise PStore::Error if called at any other time.
   #
@@ -210,7 +211,7 @@
   end
   #
   # Removes an object hierarchy from the data store, by _name_.
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction and it cannot
   # be read-only.  It will raise PStore::Error if called at any other time.
   #
@@ -221,7 +222,7 @@
 
   #
   # Returns the names of all object hierarchies currently in the store.
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -231,7 +232,7 @@
   end
   #
   # Returns true if the supplied _name_ is currently in the data store.
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -247,22 +248,22 @@
   #
   # Ends the current PStore#transaction, committing any changes to the data
   # store immediately.
-  # 
+  #
   # == Example:
-  # 
+  #
   #  require "pstore"
-  #   
+  #
   #  store = PStore.new("data_file.pstore")
   #  store.transaction do  # begin transaction
   #    # load some data into the store...
   #    store[:one] = 1
   #    store[:two] = 2
-  #  
+  #
   #    store.commit        # end transaction here, committing changes
-  #  
+  #
   #    store[:three] = 3   # this change is never reached
   #  end
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -274,21 +275,21 @@
   #
   # Ends the current PStore#transaction, discarding any changes to the data
   # store.
-  # 
+  #
   # == Example:
-  # 
+  #
   #  require "pstore"
-  #   
+  #
   #  store = PStore.new("data_file.pstore")
   #  store.transaction do  # begin transaction
   #    store[:one] = 1     # this change is not applied, see below...
   #    store[:two] = 2     # this change is not applied, see below...
-  #  
+  #
   #    store.abort         # end transaction here, discard all changes
-  #  
+  #
   #    store[:three] = 3   # this change is never reached
   #  end
-  # 
+  #
   # *WARNING*:  This method is only valid in a PStore#transaction.  It will
   # raise PStore::Error if called at any other time.
   #
@@ -300,19 +301,19 @@
 
   #
   # Opens a new transaction for the data store.  Code executed inside a block
-  # passed to this method may read and write data to and from the data store 
+  # passed to this method may read and write data to and from the data store
   # file.
-  # 
+  #
   # At the end of the block, changes are committed to the data store
-  # automatically.  You may exit the transaction early with a call to either 
+  # automatically.  You may exit the transaction early with a call to either
   # PStore#commit or PStore#abort.  See those methods for details about how
-  # changes are handled.  Raising an uncaught Exception in the block is 
+  # changes are handled.  Raising an uncaught Exception in the block is
   # equivalent to calling PStore#abort.
-  # 
+  #
   # If _read_only_ is set to +true+, you will only be allowed to read from the
   # data store during the transaction and any attempts to change the data will
   # raise a PStore::Error.
-  # 
+  #
   # Note that PStore does not support nested transactions.
   #
   def transaction(read_only = false, &block)  # :yields:  pstore
@@ -326,11 +327,11 @@
       if file
         begin
           @table, checksum, original_data_size = load_data(file, read_only)
-          
+
           catch(:pstore_abort_transaction) do
             value = yield(self)
           end
-          
+
           if !@abort && !read_only
             save_data(checksum, original_data_size, file)
           end
@@ -349,19 +350,19 @@
   ensure
     @transaction = false
   end
-  
+
   private
   # Constant for relieving Ruby's garbage collector.
   EMPTY_STRING = ""
   EMPTY_MARSHAL_DATA = Marshal.dump({})
   EMPTY_MARSHAL_CHECKSUM = Digest::MD5.digest(EMPTY_MARSHAL_DATA)
-  
+
   class DummyMutex
     def synchronize
       yield
     end
   end
-  
+
   #
   # Open the specified filename (either in read-only mode or in
   # read-write mode) and lock it for reading or writing.
@@ -391,7 +392,7 @@
       return file
     end
   end
-  
+
   # Load the given PStore file.
   # If +read_only+ is true, the unmarshalled Hash will be returned.
   # If +read_only+ is false, a 3-tuple will be returned: the unmarshalled
@@ -427,18 +428,18 @@
       [table, checksum, size]
     end
   end
-  
+
   def on_windows?
     is_windows = RUBY_PLATFORM =~ /mswin/  ||
                  RUBY_PLATFORM =~ /mingw/  ||
-                 RUBY_PLATFORM =~ /bbcwin/ ||
+                 RUBY_PLATFORM =~ /bccwin/ ||
                  RUBY_PLATFORM =~ /wince/
     self.class.__send__(:define_method, :on_windows?) do
       is_windows
     end
     is_windows
   end
-  
+
   # Check whether Marshal.dump supports the 'canonical' option. This option
   # makes sure that Marshal.dump always dumps data structures in the same order.
   # This is important because otherwise, the checksums that we generate may differ.
@@ -454,7 +455,7 @@
     end
     result
   end
-  
+
   def save_data(original_checksum, original_file_size, file)
     # We only want to save the new data if the size or checksum has changed.
     # This results in less filesystem calls, which is good for performance.
@@ -464,7 +465,7 @@
       new_data = dump(@table)
     end
     new_checksum = Digest::MD5.digest(new_data)
-    
+
     if new_data.size != original_file_size || new_checksum != original_checksum
       if @ultra_safe && !on_windows?
         # Windows doesn't support atomic file renames.
@@ -473,10 +474,10 @@
         save_data_with_fast_strategy(new_data, file)
       end
     end
-    
+
     new_data.replace(EMPTY_STRING)
   end
-  
+
   def save_data_with_atomic_file_rename_strategy(data, file)
     temp_filename = "#{@filename}.tmp.#{Process.pid}.#{rand 1000000}"
     temp_file = File.new(temp_filename, WR_ACCESS)
@@ -492,7 +493,7 @@
       temp_file.close
     end
   end
-  
+
   def save_data_with_fast_strategy(data, file)
     file.rewind
     file.truncate(0)

Modified: MacRuby/trunk/lib/rake/clean.rb
===================================================================
--- MacRuby/trunk/lib/rake/clean.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/clean.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 # The 'rake/clean' file defines two file lists (CLEAN and CLOBBER) and
 # two rake tasks (:clean and :clobber).
 #
@@ -16,8 +14,8 @@
 require 'rake'
 
 CLEAN = Rake::FileList["**/*~", "**/*.bak", "**/core"]
-CLEAN.clear_exclude.exclude { |fn| 
-  fn.pathmap("%f") == 'core' && File.directory?(fn) 
+CLEAN.clear_exclude.exclude { |fn|
+  fn.pathmap("%f") == 'core' && File.directory?(fn)
 }
 
 desc "Remove any temporary products."

Modified: MacRuby/trunk/lib/rake/gempackagetask.rb
===================================================================
--- MacRuby/trunk/lib/rake/gempackagetask.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/gempackagetask.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 # Define a package task library to aid in the definition of GEM
 # packages.
 
@@ -35,10 +33,10 @@
   #     s.files = PKG_FILES
   #     s.description = <<EOF
   #   Rake is a Make-like program implemented in Ruby. Tasks
-  #   and dependencies are specified in standard Ruby syntax. 
+  #   and dependencies are specified in standard Ruby syntax.
   #   EOF
   #   end
-  #   
+  #
   #   Rake::GemPackageTask.new(spec) do |pkg|
   #     pkg.need_zip = true
   #     pkg.need_tar = true
@@ -84,7 +82,7 @@
         }
       end
     end
-    
+
     def gem_file
       if @gem_spec.platform == Gem::Platform::RUBY
         "#{package_name}.gem"
@@ -92,6 +90,6 @@
         "#{package_name}-#{@gem_spec.platform}.gem"
       end
     end
-    
+
   end
 end

Modified: MacRuby/trunk/lib/rake/loaders/makefile.rb
===================================================================
--- MacRuby/trunk/lib/rake/loaders/makefile.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/loaders/makefile.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,19 +1,17 @@
-#!/usr/bin/env ruby
-
 module Rake
 
   # Makefile loader to be used with the import file loader.
   class MakefileLoader
+    SPACE_MARK = "\0"
 
     # Load the makefile dependencies in +fn+.
     def load(fn)
-      open(fn) do |mf|
-        lines = mf.read
-        lines.gsub!(/#[^\n]*\n/m, "")
-        lines.gsub!(/\\\n/, ' ')
-        lines.split("\n").each do |line|
-          process_line(line)
-        end
+      lines = open(fn) {|mf| mf.read}
+      lines.gsub!(/\\ /, SPACE_MARK)
+      lines.gsub!(/#[^\n]*\n/m, "")
+      lines.gsub!(/\\\n/, ' ')
+      lines.each_line do |line|
+        process_line(line)
       end
     end
 
@@ -21,13 +19,18 @@
 
     # Process one logical line of makefile data.
     def process_line(line)
-      file_tasks, args = line.split(':')
+      file_tasks, args = line.split(':', 2)
       return if args.nil?
-      dependents = args.split
-      file_tasks.strip.split.each do |file_task|
+      dependents = args.split.map {|arg| respace(arg)}
+      file_tasks.scan(/\S+/) do |file_task|
+        file_task = respace(file_task)
         file file_task => dependents
       end
     end
+
+    def respace(str)
+      str.tr(SPACE_MARK, ' ')
+    end
   end
 
   # Install the handler

Modified: MacRuby/trunk/lib/rake/packagetask.rb
===================================================================
--- MacRuby/trunk/lib/rake/packagetask.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/packagetask.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,6 +1,4 @@
-#!/usr/bin/env ruby
-
-# Define a package task libarary to aid in the definition of
+# Define a package task library to aid in the definition of
 # redistributable package files.
 
 require 'rake'
@@ -25,13 +23,13 @@
   #   of date.
   #
   # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tgz"</b>]
-  #   Create a gzipped tar package (if <em>need_tar</em> is true).  
+  #   Create a gzipped tar package (if <em>need_tar</em> is true).
   #
   # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.gz"</b>]
-  #   Create a gzipped tar package (if <em>need_tar_gz</em> is true).  
+  #   Create a gzipped tar package (if <em>need_tar_gz</em> is true).
   #
   # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.bz2"</b>]
-  #   Create a bzip2'd tar package (if <em>need_tar_bz2</em> is true).  
+  #   Create a bzip2'd tar package (if <em>need_tar_bz2</em> is true).
   #
   # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.zip"</b>]
   #   Create a zip package archive (if <em>need_zip</em> is true).
@@ -44,7 +42,7 @@
   #   end
   #
   class PackageTask < TaskLib
-    # Name of the package.
+    # Name of the package (from the GEM Spec).
     attr_accessor :name
 
     # Version of the package (e.g. '1.3.2').
@@ -74,7 +72,7 @@
     # Zip command for zipped archives.  The default is 'zip'.
     attr_accessor :zip_command
 
-    # Create a Package Task with the given name and version. 
+    # Create a Package Task with the given name and version.
     def initialize(name=nil, version=nil)
       init(name, version)
       yield self if block_given?
@@ -102,11 +100,11 @@
 
       desc "Build all the packages"
       task :package
-      
+
       desc "Force a rebuild of the package files"
       task :repackage => [:clobber_package, :package]
-      
-      desc "Remove package products" 
+
+      desc "Remove package products"
       task :clobber_package do
         rm_r package_dir rescue nil
       end
@@ -122,13 +120,12 @@
           task :package => ["#{package_dir}/#{file}"]
           file "#{package_dir}/#{file}" => [package_dir_path] + package_files do
             chdir(package_dir) do
-              sh %{env}
               sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}}
             end
           end
         end
       end
-      
+
       if need_zip
         task :package => ["#{package_dir}/#{zip_file}"]
         file "#{package_dir}/#{zip_file}" => [package_dir_path] + package_files do
@@ -160,7 +157,7 @@
     def package_name
       @version ? "#{@name}-#{@version}" : @name
     end
-      
+
     def package_dir_path
       "#{package_dir}/#{package_name}"
     end

Modified: MacRuby/trunk/lib/rake/rdoctask.rb
===================================================================
--- MacRuby/trunk/lib/rake/rdoctask.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/rdoctask.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 require 'rake'
 require 'rake/tasklib'
 
@@ -10,8 +8,8 @@
   #
   # The RDocTask will create the following targets:
   #
-  # [<b><em>rdoc</em></b>]
-  #   Main task for this RDOC task.  
+  # [<b>:<em>rdoc</em></b>]
+  #   Main task for this RDOC task.
   #
   # [<b>:clobber_<em>rdoc</em></b>]
   #   Delete all the rdoc files.  This target is automatically
@@ -28,6 +26,11 @@
   #     rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
   #   end
   #
+  # The +rd+ object passed to the block is an RDocTask object. See the
+  # attributes list for the RDocTask class for available customization options.
+  #
+  # == Specifying different task names
+  #
   # You may wish to give the task a different name, such as if you are
   # generating two sets of documentation.  For instance, if you want to have a
   # development set of documentation including private methods:
@@ -41,6 +44,16 @@
   # The tasks would then be named :<em>rdoc_dev</em>, :clobber_<em>rdoc_dev</em>, and
   # :re<em>rdoc_dev</em>.
   #
+  # If you wish to have completely different task names, then pass a Hash as
+  # first argument. With the <tt>:rdoc</tt>, <tt>:clobber_rdoc</tt> and
+  # <tt>:rerdoc</tt> options, you can customize the task names to your liking.
+  # For example:
+  #
+  #   Rake::RDocTask.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", :rerdoc => "rdoc:force")
+  #
+  # This will create the tasks <tt>:rdoc</tt>, <tt>:rdoc_clean</tt> and
+  # <tt>:rdoc:force</tt>.
+  #
   class RDocTask < TaskLib
     # Name of the main, top level task.  (default is :rdoc)
     attr_accessor :name
@@ -48,7 +61,7 @@
     # Name of directory to receive the html output files. (default is "html")
     attr_accessor :rdoc_dir
 
-    # Title of RDoc documentation. (default is none)
+    # Title of RDoc documentation. (defaults to rdoc's default)
     attr_accessor :title
 
     # Name of file to be used as the main, top level file of the
@@ -61,14 +74,24 @@
     # List of files to be included in the rdoc generation. (default is [])
     attr_accessor :rdoc_files
 
-    # List of options to be passed rdoc.  (default is [])
+    # Additional list of options to be passed rdoc.  (default is [])
     attr_accessor :options
 
-    # Run the rdoc process as an external shell (default is false)
+    # Whether to run the rdoc process as an external shell (default is false)
     attr_accessor :external
 
-    # Create an RDoc task named <em>rdoc</em>.  Default task name is +rdoc+.
-    def initialize(name=:rdoc)  # :yield: self
+    attr_accessor :inline_source
+
+    # Create an RDoc task with the given name. See the RDocTask class overview
+    # for documentation.
+    def initialize(name = :rdoc)  # :yield: self
+      if name.is_a?(Hash)
+        invalid_options = name.keys.map { |k| k.to_sym } - [:rdoc, :clobber_rdoc, :rerdoc]
+        if !invalid_options.empty?
+          raise ArgumentError, "Invalid option(s) passed to RDocTask.new: #{invalid_options.join(", ")}"
+        end
+      end
+
       @name = name
       @rdoc_files = Rake::FileList.new
       @rdoc_dir = 'html'
@@ -76,38 +99,40 @@
       @title = nil
       @template = nil
       @external = false
+      @inline_source = true
       @options = []
       yield self if block_given?
       define
     end
-    
+
     # Create the tasks defined by this task lib.
     def define
-      if name.to_s != "rdoc"
+      if rdoc_task_name != "rdoc"
         desc "Build the RDOC HTML Files"
+      else
+        desc "Build the #{rdoc_task_name} HTML Files"
       end
+      task rdoc_task_name
 
-      desc "Build the #{name} HTML Files"
-      task name
-      
       desc "Force a rebuild of the RDOC files"
-      task "re#{name}" => ["clobber_#{name}", name]
-      
-      desc "Remove rdoc products" 
-      task "clobber_#{name}" do
+      task rerdoc_task_name => [clobber_task_name, rdoc_task_name]
+
+      desc "Remove rdoc products"
+      task clobber_task_name do
         rm_r rdoc_dir rescue nil
       end
-      
-      task :clobber => ["clobber_#{name}"]
-      
+
+      task :clobber => [clobber_task_name]
+
       directory @rdoc_dir
-      task name => [rdoc_target]
+      task rdoc_task_name => [rdoc_target]
       file rdoc_target => @rdoc_files + [Rake.application.rakefile] do
         rm_r @rdoc_dir rescue nil
+        @before_running_rdoc.call if @before_running_rdoc
         args = option_list + @rdoc_files
         if @external
           argstring = args.join(' ')
-          sh %{ruby -Ivendor vender/rd #{argstring}}
+          sh %{ruby -Ivendor vendor/rd #{argstring}}
         else
           require 'rdoc/rdoc'
           RDoc::RDoc.new.document(args)
@@ -116,12 +141,14 @@
       self
     end
 
+    # List of options that will be supplied to RDoc
     def option_list
       result = @options.dup
       result << "-o" << @rdoc_dir
       result << "--main" << quote(main) if main
       result << "--title" << quote(title) if title
       result << "-T" << quote(template) if template
+      result << "--inline-source" if inline_source && !@options.include?("--inline-source") && !@options.include?("-S")
       result
     end
 
@@ -137,11 +164,45 @@
       option_list.join(' ')
     end
 
+    # The block passed to this method will be called just before running the
+    # RDoc generator. It is allowed to modify RDocTask attributes inside the
+    # block.
+    def before_running_rdoc(&block)
+      @before_running_rdoc = block
+    end
+
     private
 
     def rdoc_target
       "#{rdoc_dir}/index.html"
     end
 
+    def rdoc_task_name
+      case name
+      when Hash
+        (name[:rdoc] || "rdoc").to_s
+      else
+        name.to_s
+      end
+    end
+
+    def clobber_task_name
+      case name
+      when Hash
+        (name[:clobber_rdoc] || "clobber_rdoc").to_s
+      else
+        "clobber_#{name}"
+      end
+    end
+
+    def rerdoc_task_name
+      case name
+      when Hash
+        (name[:rerdoc] || "rerdoc").to_s
+      else
+        "re#{name}"
+      end
+    end
+
   end
 end

Modified: MacRuby/trunk/lib/rake/runtest.rb
===================================================================
--- MacRuby/trunk/lib/rake/runtest.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/runtest.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 require 'test/unit'
 require 'test/unit/assertions'
 

Modified: MacRuby/trunk/lib/rake/tasklib.rb
===================================================================
--- MacRuby/trunk/lib/rake/tasklib.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/tasklib.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 require 'rake'
 
 module Rake

Modified: MacRuby/trunk/lib/rake/testtask.rb
===================================================================
--- MacRuby/trunk/lib/rake/testtask.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/testtask.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
 # Define a task library for running unit tests.
 
 require 'rake'
@@ -10,7 +8,7 @@
   # Create a task that runs a set of tests.
   #
   # Example:
-  #  
+  #
   #   Rake::TestTask.new do |t|
   #     t.libs << "test"
   #     t.test_files = FileList['test/test*.rb']
@@ -63,7 +61,7 @@
     # * :rake -- Rake provided test loading script (default).
     # * :testrb -- Ruby provided test loading script.
     # * :direct -- Load tests using command line loader.
-    # 
+    #
     attr_accessor :loader
 
     # Array of commandline options to pass to ruby when running test loader.
@@ -105,11 +103,11 @@
             when :direct
               "-e 'ARGV.each{|f| load f}'"
             when :testrb
-              "-S testrb #{fix}"
+              "-S testrb"
             when :rake
               rake_loader
             end
-          @ruby_opts.unshift( "-I#{lib_path}" )
+          @ruby_opts.unshift( "-I\"#{lib_path}\"" )
           @ruby_opts.unshift( "-w" ) if @warning
           ruby @ruby_opts.join(" ") +
             " \"#{run_code}\" " +
@@ -135,15 +133,6 @@
       end
     end
 
-    def fix # :nodoc:
-      case RUBY_VERSION
-      when '1.8.2'
-        find_file 'rake/ruby182_test_unit_fix'
-      else
-        nil
-      end || ''
-    end
-
     def rake_loader # :nodoc:
       find_file('rake/rake_test_loader') or
         fail "unable to find rake test loader"

Modified: MacRuby/trunk/lib/rake/win32.rb
===================================================================
--- MacRuby/trunk/lib/rake/win32.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake/win32.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -5,9 +5,10 @@
   module Win32
     class << self
       # True if running on a windows system.
-      def windows?
-        # assume other DOSish systems are extinct.
-        File::ALT_SEPARATOR == '\\'
+      if File::ALT_SEPARATOR == '\\' # assume other DOSish systems are extinct.
+        def windows?; true end
+      else
+        def windows?; false end
       end
     end
 
@@ -29,6 +30,17 @@
         end
         File.expand_path('Rake', win32_shared_path)
       end
+
+      # Normalize a win32 path so that the slashes are all forward slashes.
+      def normalize(path)
+        path.tr('\\', '/')
+      end
     end if windows?
   end
+
+  if Win32.windows?
+    def standard_system_dir
+      Win32.win32_system_dir
+    end
+  end
 end

Modified: MacRuby/trunk/lib/rake.rb
===================================================================
--- MacRuby/trunk/lib/rake.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rake.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,8 +1,6 @@
-#!/usr/bin/env ruby
-
 #--
 
-# Copyright (c) 2003, 2004, 2005, 2006, 2007  Jim Weirich
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008 by Jim Weirich (jim at weirichhouse.org)
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to
@@ -29,7 +27,7 @@
 # as a library via a require statement, but it can be distributed
 # independently as an application.
 
-RAKEVERSION = '0.8.3'
+RAKEVERSION = '0.8.7'
 
 require 'rbconfig'
 require 'fileutils'
@@ -40,6 +38,8 @@
 
 require 'rake/win32'
 
+$trace = false
+
 ######################################################################
 # Rake extensions to Module.
 #
@@ -74,7 +74,7 @@
 #
 class String
   rake_extension("ext") do
-    # Replace the file extension with +newext+.  If there is no extenson on
+    # Replace the file extension with +newext+.  If there is no extension on
     # the string, append the new extension to the end.  If the new extension
     # is not given, or is the empty string, remove any existing extension.
     #
@@ -115,7 +115,7 @@
       File.join(partial_dirs)
     end
     protected :pathmap_partial
-      
+
     # Preform the pathmap replacement operations on the given path. The
     # patterns take the form 'pat1,rep1;pat2,rep2...'.
     def pathmap_replace(patterns, &block)
@@ -203,7 +203,7 @@
         when '%f'
           result << File.basename(self)
         when '%n'
-          result << File.basename(self, '.*')
+          result << File.basename(self).ext
         when '%d'
           result << File.dirname(self)
         when '%x'
@@ -280,7 +280,7 @@
 
   end
 
-  # ##########################################################################
+  ####################################################################
   # Mixin for creating easily cloned objects.
   #
   module Cloneable
@@ -305,6 +305,27 @@
   end
 
   ####################################################################
+  # Exit status class for times the system just gives us a nil.
+  class PseudoStatus
+    attr_reader :exitstatus
+    def initialize(code=0)
+      @exitstatus = code
+    end
+    def to_i
+      @exitstatus << 8
+    end
+    def >>(n)
+      to_i >> n
+    end
+    def stopped?
+      false
+    end
+    def exited?
+      true
+    end
+  end
+
+  ####################################################################
   # TaskAguments manage the arguments passed to a task.
   #
   class TaskArguments
@@ -362,9 +383,9 @@
     def inspect
       to_s
     end
-    
+
     protected
-    
+
     def lookup(name)
       if @hash.has_key?(name)
         @hash[name]
@@ -434,7 +455,7 @@
 
 module Rake
 
-  # #########################################################################
+  ###########################################################################
   # A Task is the basic unit of work in a Rakefile.  Tasks have associated
   # actions (possibly more than one) and a list of prerequisites.  When
   # invoked, a task will first ensure that all of its prerequisites have an
@@ -734,7 +755,7 @@
   end # class Rake::Task
 
 
-  # #########################################################################
+  ###########################################################################
   # A FileTask is a task that includes time based dependencies.  If any of a
   # FileTask's prerequisites have a timestamp that is later than the file
   # represented by this task, then the file must be rebuilt (using the
@@ -745,9 +766,7 @@
     # Is this file task needed?  Yes if it doesn't exist, or if its time stamp
     # is out of date.
     def needed?
-      return true unless File.exist?(name)
-      return true if out_of_date?(timestamp)
-      false
+      ! File.exist?(name) || out_of_date?(timestamp)
     end
 
     # Time stamp for file task.
@@ -778,7 +797,7 @@
     end
   end # class Rake::FileTask
 
-  # #########################################################################
+  ###########################################################################
   # A FileCreationTask is a file task that when used as a dependency will be
   # needed if and only if the file has not been created.  Once created, it is
   # not re-triggered if any of its dependencies are newer, nor does trigger
@@ -797,7 +816,7 @@
     end
   end
 
-  # #########################################################################
+  ###########################################################################
   # Same as a regular task, but the immediate prerequisites are done in
   # parallel using Ruby threads.
   #
@@ -812,7 +831,7 @@
   end
 end # module Rake
 
-# ###########################################################################
+## ###########################################################################
 # Task Definition Functions ...
 
 # Declare a basic task.
@@ -931,12 +950,18 @@
   end
 end
 
-# ###########################################################################
+#############################################################################
 # This a FileUtils extension that defines several additional commands to be
 # added to the FileUtils utility functions.
 #
 module FileUtils
-  RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).
+  RUBY_EXT = ((RbConfig::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ?
+    "" :
+    RbConfig::CONFIG['EXEEXT'])
+
+  RUBY = File.join(
+    RbConfig::CONFIG['bindir'],
+    RbConfig::CONFIG['ruby_install_name'] + RUBY_EXT).
     sub(/.*\s.*/m, '"\&"')
 
   OPT_TABLE['sh']  = %w(noop verbose)
@@ -962,14 +987,14 @@
     options = (Hash === cmd.last) ? cmd.pop : {}
     unless block_given?
       show_command = cmd.join(" ")
-      show_command = show_command[0,42] + "..."
+      show_command = show_command[0,42] + "..." unless $trace
       # TODO code application logic heref show_command.length > 45
       block = lambda { |ok, status|
         ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
       }
     end
     if RakeFileUtils.verbose_flag == :default
-      options[:verbose] = false
+      options[:verbose] = true
     else
       options[:verbose] ||= RakeFileUtils.verbose_flag
     end
@@ -978,7 +1003,9 @@
     rake_output_message cmd.join(" ") if options[:verbose]
     unless options[:noop]
       res = rake_system(*cmd)
-      block.call(res, $?)
+      status = $?
+      status = PseudoStatus.new(1) if !res && status.nil?
+      block.call(res, status)
     end
   end
 
@@ -1031,7 +1058,7 @@
   end
 end
 
-# ###########################################################################
+#############################################################################
 # RakeFileUtils provides a custom version of the FileUtils methods that
 # respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
 #
@@ -1162,7 +1189,7 @@
   extend self
 end
 
-# ###########################################################################
+#############################################################################
 # Include the FileUtils file manipulation functions in the top level module,
 # but mark them private so that they don't unintentionally define methods on
 # other objects.
@@ -1175,7 +1202,7 @@
 ######################################################################
 module Rake
 
-  # #########################################################################
+  ###########################################################################
   # A FileList is essentially an array with a few helper methods defined to
   # make file manipulation a bit easier.
   #
@@ -1211,7 +1238,7 @@
 
     # List of array methods (that are not in +Object+) that need to be
     # delegated.
-    ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
+    ARRAY_METHODS = (Array.instance_methods - (Object.instance_methods - [:<=>])).map { |n| n.to_s }
 
     # List of additional methods that must be delegated.
     MUST_DEFINE = %w[to_a inspect]
@@ -1229,28 +1256,23 @@
     ]
 
     DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
-    
+
     # Now do the delegation.
     DELEGATING_METHODS.each_with_index do |sym, i|
       if SPECIAL_RETURN.include?(sym)
-        class_eval do
-	        define_method(sym) do |*args, &block|
-            resolve
-            result = @items.send(sym, *args, &block)
-            FileList.new.import(result)
-          end
+        define_method(sym) do |*args, &block|
+          resolve
+          result = @items.send(sym, *args, &block)
+          FileList.new.import(result)
         end
       else
-        class_eval do
-	        define_method(sym) do |*args, &block|
-            resolve
-            result = @items.send(sym, *args, &block)
-            result.object_id == @items.object_id ? self : result
-          end 
+        define_method(sym) do |*args, &block|
+          resolve
+          result = @items.send(sym, *args, &block)
+          result.object_id == @items.object_id ? self : result
         end
       end
     end
-    
 
     # Create a file list from the globbable patterns given.  If you wish to
     # perform multiple includes or excludes at object build time, use the
@@ -1456,8 +1478,8 @@
       collect { |fn| fn.pathmap(spec) }
     end
 
-    # Return a new array with <tt>String#ext</tt> method applied to each
-    # member of the array.
+    # Return a new FileList with <tt>String#ext</tt> method applied
+    # to each member of the array.
     #
     # This method is a shortcut for:
     #
@@ -1474,9 +1496,9 @@
     # name, line number, and the matching line of text.  If no block is given,
     # a standard emac style file:linenumber:line message will be printed to
     # standard out.
-    def egrep(pattern, *opt)
+    def egrep(pattern, *options)
       each do |fn|
-        open(fn, "rb", *opt) do |inf|
+        open(fn, "rb", *options) do |inf|
           count = 0
           inf.each do |line|
             count += 1
@@ -1582,7 +1604,7 @@
 # Alias FileList to be available at the top level.
 FileList = Rake::FileList
 
-# ###########################################################################
+#############################################################################
 module Rake
 
   # Default Rakefile loader used by +import+.
@@ -1609,7 +1631,7 @@
   EARLY = EarlyTime.instance
 end # module Rake
 
-# ###########################################################################
+#############################################################################
 # Extensions to time to allow comparisons with an early time class.
 #
 class Time
@@ -1643,9 +1665,9 @@
       @task_manager.lookup(name, @scope)
     end
 
-    # Return the list of tasks defined in this namespace.
+    # Return the list of tasks defined in this and nested namespaces.
     def tasks
-      @task_manager.tasks
+      @task_manager.tasks_in_scope(@scope)
     end
   end # NameSpace
 
@@ -1734,7 +1756,7 @@
       [task_name, arg_names, []]
     end
     private :resolve_args_without_dependencies
-    
+
     # Resolve task arguments for a task or rule when there are
     # dependencies declared.
     #
@@ -1765,7 +1787,7 @@
       [task_name, arg_names, deps]
     end
     private :resolve_args_with_dependencies
-    
+
     # If a rule can be found that matches the task name, enhance the
     # task with the prerequisites and actions from the rule.  Set the
     # source attribute of the task appropriately for the rule.  Return
@@ -1790,6 +1812,15 @@
       @tasks.values.sort_by { |t| t.name }
     end
 
+    # List of all the tasks defined in the given scope (and its
+    # sub-scopes).
+    def tasks_in_scope(scope)
+      prefix = scope.join(":")
+      tasks.select { |t|
+        /^#{prefix}:/ =~ t.name
+      }
+    end
+
     # Clear all tasks in this application.
     def clear
       @tasks.clear
@@ -1957,18 +1988,17 @@
     # application.  The define any tasks.  Finally, call +top_level+ to run your top
     # level tasks.
     def run
-      standard_exception_handling do
-        init
-        load_rakefile
-        top_level
-      end
+      init
+      load_rakefile
+      top_level
     end
 
     # Initialize the command line parameters and app name.
     def init(app_name='rake')
       standard_exception_handling do
         @name = app_name
-        collect_tasks handle_options
+        handle_options
+        collect_tasks
       end
     end
 
@@ -2035,9 +2065,9 @@
         exit(false)
       rescue Exception => ex
         # Exit with error message
-        $stderr.puts "rake aborted!"
+        $stderr.puts "#{name} aborted!"
         $stderr.puts ex.message
-        if options.trace
+        if options.trace or true
           $stderr.puts ex.backtrace.join("\n")
         else
           $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
@@ -2051,7 +2081,10 @@
     # If a match is found, it is copied into @rakefile.
     def have_rakefile
       @rakefiles.each do |fn|
-        if File.exist?(fn) || fn == ''
+        if File.exist?(fn)
+          others = Dir.glob(fn, File::FNM_CASEFOLD)
+          return others.size == 1 ? others.first : fn
+        elsif fn == ''
           return fn
         end
       end
@@ -2074,14 +2107,14 @@
       tty_output? || ENV['RAKE_COLUMNS']
     end
 
-    # Display the tasks and dependencies.
+    # Display the tasks and comments.
     def display_tasks_and_comments
       displayable_tasks = tasks.select { |t|
         t.comment && t.name =~ options.show_task_pattern
       }
       if options.full_description
         displayable_tasks.each do |t|
-          puts "rake #{t.name_with_args}"
+          puts "#{name} #{t.name_with_args}"
           t.full_comment.split("\n").each do |line|
             puts "    #{line}"
           end
@@ -2108,7 +2141,7 @@
       80
     end
 
-    # Calculate the dynamic width of the 
+    # Calculate the dynamic width of the
     def dynamic_width
       @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
     end
@@ -2124,7 +2157,7 @@
     def unix?
       RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
     end
-    
+
     def windows?
       Win32.windows?
     end
@@ -2140,7 +2173,7 @@
     # Display the tasks and prerequisites
     def display_prerequisites
       tasks.each do |t|
-        puts "rake #{t.name}"
+        puts "#{name} #{t.name}"
         t.prerequisites.each { |pre| puts "    #{pre}" }
       end
     end
@@ -2184,7 +2217,7 @@
         ],
         ['--execute-continue',  '-E CODE',
           "Execute some Ruby code, then continue with normal task processing.",
-          lambda { |value| eval(value) }            
+          lambda { |value| eval(value) }
         ],
         ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
           lambda { |value| $:.push(value) }
@@ -2196,9 +2229,9 @@
           lambda { |value| verbose(false) }
         ],
         ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
-          lambda { |value| 
+          lambda { |value|
             value ||= ''
-            @rakefiles.clear 
+            @rakefiles.clear
             @rakefiles << value
           }
         ],
@@ -2252,7 +2285,7 @@
             verbose(true)
           }
         ],
-        ['--verbose', '-v', "Log message to standard output (default).",
+        ['--verbose', '-v', "Log message to standard output.",
           lambda { |value| verbose(true) }
         ],
         ['--version', '-V', "Display the program version.",
@@ -2268,19 +2301,19 @@
     def handle_options
       options.rakelib = ['rakelib']
 
-      opts = OptionParser.new
-      opts.banner = "rake [-f rakefile] {options} targets..."
-      opts.separator ""
-      opts.separator "Options are ..."
-      
-      opts.on_tail("-h", "--help", "-H", "Display this help message.") do
-        puts opts
-        exit
-      end
-      
-      standard_rake_options.each { |args| opts.on(*args) }
-      parsed_argv = opts.parse(ARGV)
+      OptionParser.new do |opts|
+        opts.banner = "rake [-f rakefile] {options} targets..."
+        opts.separator ""
+        opts.separator "Options are ..."
 
+        opts.on_tail("-h", "--help", "-H", "Display this help message.") do
+          puts opts
+          exit
+        end
+
+        standard_rake_options.each { |args| opts.on(*args) }
+      end.parse!
+
       # If class namespaces are requested, set the global options
       # according to the values in the options structure.
       if options.classic_namespace
@@ -2290,7 +2323,6 @@
         $dryrun = options.dryrun
         $silent = options.silent
       end
-      parsed_argv
     end
 
     # Similar to the regular Ruby +require+ command, but will check
@@ -2356,34 +2388,23 @@
 
     # The directory path containing the system wide rakefiles.
     def system_dir
-      @system_dir ||=
-        begin
-          if ENV['RAKE_SYSTEM']
-            ENV['RAKE_SYSTEM']
-          else
-            standard_system_dir
-          end
-        end
+      @system_dir ||= ENV['RAKE_SYSTEM'] || standard_system_dir
     end
-    
+
     # The standard directory containing system wide rake files.
-    if Win32.windows?
+    unless method_defined?(:standard_system_dir)
       def standard_system_dir #:nodoc:
-        Win32.win32_system_dir
+        File.expand_path('~/.rake')
       end
-    else
-      def standard_system_dir #:nodoc:
-        File.expand_path('.rake', '~')
-      end
     end
     private :standard_system_dir
 
     # Collect the list of tasks on the command line.  If no tasks are
     # given, return a list containing only the default task.
     # Environmental assignments are processed at this time as well.
-    def collect_tasks(argv)
+    def collect_tasks
       @top_level_tasks = []
-      argv.each do |arg|
+      ARGV.each do |arg|
         if arg =~ /^(\w+)=(.*)$/
           ENV[$1] = $2
         else

Modified: MacRuby/trunk/lib/rational.rb
===================================================================
--- MacRuby/trunk/lib/rational.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rational.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +1,7 @@
+# :enddoc:
+
+warn('lib/rational.rb is deprecated') if $VERBOSE
+
 class Fixnum
 
   alias quof fdiv
@@ -3,5 +7,5 @@
   alias rdiv quo
 
-  alias power! ** unless defined?(0.power!)
+  alias power! ** unless method_defined? :power!
   alias rpower **
 
@@ -13,7 +17,7 @@
   alias quof fdiv
   alias rdiv quo
 
-  alias power! ** unless defined?(0.power!)
+  alias power! ** unless method_defined? :power!
   alias rpower **
 
 end

Modified: MacRuby/trunk/lib/resolv.rb
===================================================================
--- MacRuby/trunk/lib/resolv.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/resolv.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,10 +9,10 @@
 end
 
 # Resolv is a thread-aware DNS resolver library written in Ruby.  Resolv can
-# handle multiple DNS requests concurrently without blocking.  The ruby
+# handle multiple DNS requests concurrently without blocking the entire ruby
 # interpreter.
 #
-# See also resolv-replace.rb to replace the libc resolver with # Resolv.
+# See also resolv-replace.rb to replace the libc resolver with Resolv.
 #
 # Resolv can look up various DNS resources using the DNS module directly.
 #
@@ -162,10 +162,10 @@
   class ResolvTimeout < TimeoutError; end
 
   ##
-  # DNS::Hosts is a hostname resolver that uses the system hosts file.
+  # Resolv::Hosts is a hostname resolver that uses the system hosts file.
 
   class Hosts
-    if /mswin32|mingw|bccwin/ =~ RUBY_PLATFORM
+    if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
       require 'win32/resolv'
       DefaultFileName = Win32::Resolv.get_hosts_path
     else
@@ -173,7 +173,7 @@
     end
 
     ##
-    # Creates a new DNS::Hosts, using +filename+ for its data source.
+    # Creates a new Resolv::Hosts, using +filename+ for its data source.
 
     def initialize(filename = DefaultFileName)
       @filename = filename
@@ -313,7 +313,17 @@
     # nil:: Uses /etc/resolv.conf.
     # String:: Path to a file using /etc/resolv.conf's format.
     # Hash:: Must contain :nameserver, :search and :ndots keys.
+    # :nameserver_port can be used to specify port number of nameserver address.
     #
+    # The value of :nameserver should be an address string or
+    # an array of address strings.
+    # - :nameserver => '8.8.8.8'
+    # - :nameserver => ['8.8.8.8', '8.8.4.4']
+    #
+    # The value of :nameserver_port should be an array of
+    # pair of nameserver address and port number.
+    # - :nameserver_port => [['8.8.8.8', 53], ['8.8.4.4', 53]]
+    #
     # Example:
     #
     #   Resolv::DNS.new(:nameserver => ['210.251.121.21'],
@@ -379,9 +389,21 @@
 
     def each_address(name)
       each_resource(name, Resource::IN::A) {|resource| yield resource.address}
-      each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
+      if use_ipv6?
+        each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
+      end
     end
 
+    def use_ipv6?
+      begin
+        list = Socket.ip_address_list
+      rescue NotImplementedError
+        return true
+      end
+      list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
+    end
+    private :use_ipv6?
+
     ##
     # Gets the hostname for +address+ from the DNS resolver.
     #
@@ -473,13 +495,13 @@
       requester = make_requester
       senders = {}
       begin
-        @config.resolv(name) {|candidate, tout, nameserver|
+        @config.resolv(name) {|candidate, tout, nameserver, port|
           msg = Message.new
           msg.rd = 1
           msg.add_question(candidate, typeclass)
-          unless sender = senders[[candidate, nameserver]]
-            sender = senders[[candidate, nameserver]] =
-              requester.sender(msg, candidate, nameserver)
+          unless sender = senders[[candidate, nameserver, port]]
+            sender = senders[[candidate, nameserver, port]] =
+              requester.sender(msg, candidate, nameserver, port)
           end
           reply, reply_name = requester.request(sender, tout)
           case reply.rcode
@@ -498,10 +520,11 @@
     end
 
     def make_requester # :nodoc:
-      if nameserver = @config.single?
-        Requester::ConnectedUDP.new(nameserver)
+      nameserver_port = @config.nameserver_port
+      if nameserver_port.length == 1
+        Requester::ConnectedUDP.new(*nameserver_port[0])
       else
-        Requester::UnconnectedUDP.new
+        Requester::UnconnectedUDP.new(*nameserver_port)
       end
     end
 
@@ -587,10 +610,10 @@
       }
     end
 
-    def self.bind_random_port(udpsock) # :nodoc:
+    def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
       begin
         port = rangerand(1024..65535)
-        udpsock.bind("", port)
+        udpsock.bind(bind_host, port)
       rescue Errno::EADDRINUSE
         retry
       end
@@ -599,18 +622,23 @@
     class Requester # :nodoc:
       def initialize
         @senders = {}
-        @sock = nil
+        @socks = nil
       end
 
       def request(sender, tout)
         timelimit = Time.now + tout
         sender.send
-        while (now = Time.now) < timelimit
+        while true
+          now = Time.now
           timeout = timelimit - now
-          if !IO.select([@sock], nil, nil, timeout)
+          if timeout <= 0
             raise ResolvTimeout
           end
-          reply, from = recv_reply
+          select_result = IO.select(@socks, nil, nil, timeout)
+          if !select_result
+            raise ResolvTimeout
+          end
+          reply, from = recv_reply(select_result[0])
           begin
             msg = Message.decode(reply)
           rescue DecodeError
@@ -626,9 +654,11 @@
       end
 
       def close
-        sock = @sock
-        @sock = nil
-        sock.close if sock
+        socks = @socks
+        @socks = nil
+        if socks
+          socks.each {|sock| sock.close }
+        end
       end
 
       class Sender # :nodoc:
@@ -640,15 +670,31 @@
       end
 
       class UnconnectedUDP < Requester # :nodoc:
-        def initialize
+        def initialize(*nameserver_port)
           super()
-          @sock = UDPSocket.new
-          @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
-          DNS.bind_random_port(@sock)
+          @nameserver_port = nameserver_port
+          @socks_hash = {}
+          @socks = []
+          nameserver_port.each {|host, port|
+            if host.index(':')
+              bind_host = "::"
+              af = Socket::AF_INET6
+            else
+              bind_host = "0.0.0.0"
+              af = Socket::AF_INET
+            end
+            next if @socks_hash[bind_host]
+            sock = UDPSocket.new(af)
+            sock.do_not_reverse_lookup = true
+            sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+            DNS.bind_random_port(sock, bind_host)
+            @socks << sock
+            @socks_hash[bind_host] = sock
+          }
         end
 
-        def recv_reply
-          reply, from = @sock.recvfrom(UDPSize)
+        def recv_reply(readable_socks)
+          reply, from = readable_socks[0].recvfrom(UDPSize)
           return reply, [from[3],from[1]]
         end
 
@@ -657,8 +703,9 @@
           id = DNS.allocate_request_id(host, port)
           request = msg.encode
           request[0,2] = [id].pack('n')
+          sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
           return @senders[[service, id]] =
-            Sender.new(request, data, @sock, host, port)
+            Sender.new(request, data, sock, host, port)
         end
 
         def close
@@ -687,14 +734,17 @@
           super()
           @host = host
           @port = port
-          @sock = UDPSocket.new(host.index(':') ? Socket::AF_INET6 : Socket::AF_INET)
-          DNS.bind_random_port(@sock)
-          @sock.connect(host, port)
-          @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+          is_ipv6 = host.index(':')
+          sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
+          @socks = [sock]
+          sock.do_not_reverse_lookup = true
+          sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+          DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
+          sock.connect(host, port)
         end
 
-        def recv_reply
-          reply = @sock.recv(UDPSize)
+        def recv_reply(readable_socks)
+          reply = readable_socks[0].recv(UDPSize)
           return reply, nil
         end
 
@@ -705,7 +755,7 @@
           id = DNS.allocate_request_id(@host, @port)
           request = msg.encode
           request[0,2] = [id].pack('n')
-          return @senders[[nil,id]] = Sender.new(request, data, @sock)
+          return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
         end
 
         def close
@@ -728,14 +778,15 @@
           super()
           @host = host
           @port = port
-          @sock = TCPSocket.new(@host, @port)
-          @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+          sock = TCPSocket.new(@host, @port)
+          @socks = [sock]
+          sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
           @senders = {}
         end
 
-        def recv_reply
-          len = @sock.read(2).unpack('n')[0]
-          reply = @sock.read(len)
+        def recv_reply(readable_socks)
+          len = readable_socks[0].read(2).unpack('n')[0]
+          reply = @socks[0].read(len)
           return reply, nil
         end
 
@@ -746,7 +797,7 @@
           id = DNS.allocate_request_id(@host, @port)
           request = msg.encode
           request[0,2] = [request.length, id].pack('nn')
-          return @senders[[nil,id]] = Sender.new(request, data, @sock)
+          return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
         end
 
         class Sender < Requester::Sender # :nodoc:
@@ -817,7 +868,7 @@
         if File.exist? filename
           config_hash = Config.parse_resolv_conf(filename)
         else
-          if /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
+          if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
             require 'win32/resolv'
             search, nameserver = Win32::Resolv.get_resolv_info
             config_hash = {}
@@ -825,13 +876,13 @@
             config_hash[:search] = [search].flatten if search
           end
         end
-        config_hash
+        config_hash || {}
       end
 
       def lazy_initialize
         @mutex.synchronize {
           unless @initialized
-            @nameserver = []
+            @nameserver_port = []
             @search = nil
             @ndots = 1
             case @config_info
@@ -850,11 +901,18 @@
             else
               raise ArgumentError.new("invalid resolv configuration: #{@config_info.inspect}")
             end
-            @nameserver = config_hash[:nameserver] if config_hash.include? :nameserver
+            if config_hash.include? :nameserver
+              @nameserver_port = config_hash[:nameserver].map {|ns| [ns, Port] }
+            end
+            if config_hash.include? :nameserver_port
+              @nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] }
+            end
             @search = config_hash[:search] if config_hash.include? :search
             @ndots = config_hash[:ndots] if config_hash.include? :ndots
 
-            @nameserver = ['0.0.0.0'] if @nameserver.empty?
+            if @nameserver_port.empty?
+              @nameserver_port << ['0.0.0.0', Port]
+            end
             if @search
               @search = @search.map {|arg| Label.split(arg) }
             else
@@ -866,9 +924,14 @@
               end
             end
 
-            if !@nameserver.kind_of?(Array) ||
-               !@nameserver.all? {|ns| String === ns }
-              raise ArgumentError.new("invalid nameserver config: #{@nameserver.inspect}")
+            if !@nameserver_port.kind_of?(Array) ||
+               @nameserver_port.any? {|ns_port|
+                  !(Array === ns_port) ||
+                  ns_port.length != 2
+                  !(String === ns_port[0]) ||
+                  !(Integer === ns_port[1])
+               }
+              raise ArgumentError.new("invalid nameserver config: #{@nameserver_port.inspect}")
             end
 
             if !@search.kind_of?(Array) ||
@@ -888,13 +951,17 @@
 
       def single?
         lazy_initialize
-        if @nameserver.length == 1
-          return @nameserver[0]
+        if @nameserver_port.length == 1
+          return @nameserver_port[0]
         else
           return nil
         end
       end
 
+      def nameserver_port
+        @nameserver_port
+      end
+
       def generate_candidates(name)
         candidates = nil
         name = Name.create(name)
@@ -915,7 +982,7 @@
 
       def generate_timeouts
         ts = [InitialTimeout]
-        ts << ts[-1] * 2 / @nameserver.length
+        ts << ts[-1] * 2 / @nameserver_port.length
         ts << ts[-1] * 2
         ts << ts[-1] * 2
         return ts
@@ -928,9 +995,9 @@
           candidates.each {|candidate|
             begin
               timeouts.each {|tout|
-                @nameserver.each {|nameserver|
+                @nameserver_port.each {|nameserver, port|
                   begin
-                    yield candidate, tout, nameserver
+                    yield candidate, tout, nameserver, port
                   rescue ResolvTimeout
                   end
                 }
@@ -1348,6 +1415,10 @@
           yield self
         end
 
+        def inspect
+          "\#<#{self.class}: #{@data[0, @index].inspect} #{@data[@index..-1].inspect}>"
+        end
+
         def get_length16
           len, = self.get_unpack('n')
           save_limit = @limit
@@ -2039,7 +2110,11 @@
     ##
     # Regular expression IPv4 addresses must match.
 
-    Regex = /\A(\d+)\.(\d+)\.(\d+)\.(\d+)\z/
+    Regex256 = /0
+               |1(?:[0-9][0-9]?)?
+               |2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
+               |[3-9][0-9]?/x
+    Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
 
     def self.create(arg)
       case arg
@@ -2060,9 +2135,12 @@
     end
 
     def initialize(address) # :nodoc:
-      unless address.kind_of?(String) && address.length == 4
-        raise ArgumentError.new('IPv4 address must be 4 bytes')
+      unless address.kind_of?(String)
+        raise ArgumentError, 'IPv4 address must be a string'
       end
+      unless address.length == 4
+        raise ArgumentError, "IPv4 address expects 4 bytes but #{address.length} bytes"
+      end
       @address = address
     end
 

Modified: MacRuby/trunk/lib/rexml/attlistdecl.rb
===================================================================
--- MacRuby/trunk/lib/rexml/attlistdecl.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/attlistdecl.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -31,7 +31,7 @@
         @element_name, @pairs, @contents = *source
       end
     end
-  
+
     # Access the attlist attribute/value pairs.
     #  value = attlist_decl[ attribute_name ]
     def [](key)

Modified: MacRuby/trunk/lib/rexml/attribute.rb
===================================================================
--- MacRuby/trunk/lib/rexml/attribute.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/attribute.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -14,7 +14,7 @@
     attr_reader :element
     # The normalized value of this attribute.  That is, the attribute with
     # entities intact.
-    attr_writer :normalized	
+    attr_writer :normalized
     PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
 
     NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
@@ -22,18 +22,18 @@
     # Constructor.
     # FIXME: The parser doesn't catch illegal characters in attributes
     #
-    # first:: 
+    # first::
     #   Either: an Attribute, which this new attribute will become a
     #   clone of; or a String, which is the name of this attribute
     # second::
     #   If +first+ is an Attribute, then this may be an Element, or nil.
     #   If nil, then the Element parent of this attribute is the parent
-    #   of the +first+ Attribute.  If the first argument is a String, 
-    #   then this must also be a String, and is the content of the attribute.  
+    #   of the +first+ Attribute.  If the first argument is a String,
+    #   then this must also be a String, and is the content of the attribute.
     #   If this is the content, it must be fully normalized (contain no
     #   illegal characters).
     # parent::
-    #   Ignored unless +first+ is a String; otherwise, may be the Element 
+    #   Ignored unless +first+ is a String; otherwise, may be the Element
     #   parent of this attribute, or nil.
     #
     #
@@ -61,7 +61,7 @@
     end
 
     # Returns the namespace of the attribute.
-    # 
+    #
     #  e = Element.new( "elns:myelement" )
     #  e.add_attribute( "nsa:a", "aval" )
     #  e.add_attribute( "b", "bval" )
@@ -78,7 +78,7 @@
     end
 
     # Returns the namespace URL, if defined, or nil otherwise
-    # 
+    #
     #  e = Element.new("el")
     #  e.add_attributes({"xmlns:ns", "http://url"})
     #  e.namespace( "ns" )              # -> "http://url"
@@ -157,7 +157,7 @@
     end
 
     # Removes this Attribute from the tree, and returns true if successfull
-    # 
+    #
     # This method is usually not called directly.
     def remove
       @element.attributes.delete self.name unless @element.nil?

Modified: MacRuby/trunk/lib/rexml/cdata.rb
===================================================================
--- MacRuby/trunk/lib/rexml/cdata.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/cdata.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -17,7 +17,7 @@
     end
 
     # Make a copy of this object
-    # 
+    #
     # _Examples_
     #  c = CData.new( "Some text" )
     #  d = c.clone

Modified: MacRuby/trunk/lib/rexml/child.rb
===================================================================
--- MacRuby/trunk/lib/rexml/child.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/child.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -15,8 +15,8 @@
     #   if supplied, the parent of this child will be set to the
     #   supplied value, and self will be added to the parent
     def initialize( parent = nil )
-      @parent = nil  
-      # Declare @parent, but don't define it.  The next line sets the 
+      @parent = nil
+      # Declare @parent, but don't define it.  The next line sets the
       # parent.
       parent.add( self ) if parent
     end
@@ -68,7 +68,7 @@
       parent.insert_after self, other
     end
 
-    # Sets the previous sibling of this child.  This can be used to insert a 
+    # Sets the previous sibling of this child.  This can be used to insert a
     # child before some other child.
     #  a = Element.new("a")
     #  b = a.add_element("b")

Modified: MacRuby/trunk/lib/rexml/comment.rb
===================================================================
--- MacRuby/trunk/lib/rexml/comment.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/comment.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -14,11 +14,11 @@
 
     ##
     # Constructor.  The first argument can be one of three types:
-    # @param first If String, the contents of this comment are set to the 
+    # @param first If String, the contents of this comment are set to the
     # argument.  If Comment, the argument is duplicated.  If
     # Source, the argument is scanned for a comment.
-    # @param second If the first argument is a Source, this argument 
-    # should be nil, not supplied, or a Parent to be set as the parent 
+    # @param second If the first argument is a Source, this argument
+    # should be nil, not supplied, or a Parent to be set as the parent
     # of this object
     def initialize( first, second = nil )
       #puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"

Modified: MacRuby/trunk/lib/rexml/doctype.rb
===================================================================
--- MacRuby/trunk/lib/rexml/doctype.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/doctype.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -15,11 +15,11 @@
     STOP = ">"
     SYSTEM = "SYSTEM"
     PUBLIC = "PUBLIC"
-    DEFAULT_ENTITIES = { 
-      'gt'=>EntityConst::GT, 
-      'lt'=>EntityConst::LT, 
-      'quot'=>EntityConst::QUOT, 
-      "apos"=>EntityConst::APOS 
+    DEFAULT_ENTITIES = {
+      'gt'=>EntityConst::GT,
+      'lt'=>EntityConst::LT,
+      'quot'=>EntityConst::QUOT,
+      "apos"=>EntityConst::APOS
     }
 
     # name is the name of the doctype
@@ -33,7 +33,7 @@
     #   dt = DocType.new( doctype_to_clone )
     #   # Incomplete.  Shallow clone of doctype
     #
-    # +Note+ that the constructor: 
+    # +Note+ that the constructor:
     #
     #  Doctype.new( Source.new( "<!DOCTYPE foo 'bar'>" ) )
     #
@@ -139,8 +139,8 @@
       @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES
       @entities[ child.name ] = child if child.kind_of? Entity
     end
-    
-    # This method retrieves the public identifier identifying the document's 
+
+    # This method retrieves the public identifier identifying the document's
     # DTD.
     #
     # Method contributed by Henrik Martensson
@@ -152,7 +152,7 @@
         strip_quotes(@long_name)
       end
     end
-    
+
     # This method retrieves the system identifier identifying the document's DTD
     #
     # Method contributed by Henrik Martensson
@@ -164,16 +164,16 @@
         @uri.kind_of?(String) ? strip_quotes(@uri) : nil
       end
     end
-    
+
     # This method returns a list of notations that have been declared in the
-    # _internal_ DTD subset. Notations in the external DTD subset are not 
+    # _internal_ DTD subset. Notations in the external DTD subset are not
     # listed.
     #
     # Method contributed by Henrik Martensson
     def notations
       children().select {|node| node.kind_of?(REXML::NotationDecl)}
     end
-    
+
     # Retrieves a named notation. Only notations declared in the internal
     # DTD subset can be retrieved.
     #
@@ -183,9 +183,9 @@
         notation_decl.name == name
       }
     end
-    
+
     private
-    
+
     # Method contributed by Henrik Martensson
     def strip_quotes(quoted_string)
       quoted_string =~ /^[\'\"].*[\'\"]$/ ?
@@ -217,7 +217,7 @@
       output << to_s
     end
   end
-  
+
   public
   class ElementDecl < Declaration
     def initialize( src )
@@ -250,7 +250,7 @@
 
     def to_s
       "<!NOTATION #@name #@middle#{
-        @public ? ' ' + public.inspect : '' 
+        @public ? ' ' + public.inspect : ''
       }#{
         @system ? ' ' + at system.inspect : ''
       }>"
@@ -259,7 +259,7 @@
     def write( output, indent=-1 )
       output << to_s
     end
-    
+
     # This method retrieves the name of the notation.
     #
     # Method contributed by Henrik Martensson

Modified: MacRuby/trunk/lib/rexml/document.rb
===================================================================
--- MacRuby/trunk/lib/rexml/document.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/document.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -25,7 +25,7 @@
     DECLARATION = XMLDecl.default
 
     # Constructor
-    # @param source if supplied, must be a Document, String, or IO. 
+    # @param source if supplied, must be a Document, String, or IO.
     # Documents have their context and Element attributes cloned.
     # Strings are expected to be valid XML documents.  IOs are expected
     # to be sources of valid XML documents.
@@ -66,25 +66,27 @@
     # of the document
     def add( child )
       if child.kind_of? XMLDecl
-        @children.unshift child
+        if @children[0].kind_of? XMLDecl
+          @children[0] = child
+        else
+          @children.unshift child
+        end
         child.parent = self
       elsif child.kind_of? DocType
-        # Find first Element or DocType node and insert the decl right 
+        # Find first Element or DocType node and insert the decl right
         # before it.  If there is no such node, just insert the child at the
         # end.  If there is a child and it is an DocType, then replace it.
-        insert_before_index = 0
-        @children.find { |x| 
-          insert_before_index += 1
+        insert_before_index = @children.find_index { |x|
           x.kind_of?(Element) || x.kind_of?(DocType)
         }
-        if @children[ insert_before_index ] # Not null = not end of list
-          if @children[ insert_before_index ].kind_of DocType
+        if insert_before_index # Not null = not end of list
+          if @children[ insert_before_index ].kind_of? DocType
             @children[ insert_before_index ] = child
           else
-            @children[ index_before_index-1, 0 ] = child
+            @children[ insert_before_index-1, 0 ] = child
           end
         else  # Insert at end of list
-          @children[insert_before_index] = child
+          @children << child
         end
         child.parent = self
       else
@@ -167,7 +169,7 @@
     # indent::
     #   An integer.  If -1, no indenting will be used; otherwise, the
     #   indentation will be twice this number of spaces, and children will be
-    #   indented an additional amount.  For a value of 3, every item will be 
+    #   indented an additional amount.  For a value of 3, every item will be
     #   indented 3 more levels, or 6 more spaces (2 * 3). Defaults to -1
     # transitive::
     #   If transitive is true and indent is >= 0, then the output will be
@@ -178,7 +180,7 @@
     #   Internet Explorer is the worst piece of crap to have ever been
     #   written, with the possible exception of Windows itself.  Since IE is
     #   unable to parse proper XML, we have to provide a hack to generate XML
-    #   that IE's limited abilities can handle.  This hack inserts a space 
+    #   that IE's limited abilities can handle.  This hack inserts a space
     #   before the /> on empty tags.  Defaults to false
     def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
       if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
@@ -197,7 +199,7 @@
       formatter.write( self, output )
     end
 
-    
+
     def Document::parse_stream( source, listener )
       Parsers::StreamParser.new( source, listener ).parse
     end
@@ -215,7 +217,7 @@
     end
 
     attr_reader :entity_expansion_count
-    
+
     def record_entity_expansion
       @entity_expansion_count += 1
       if @entity_expansion_count > @@entity_expansion_limit

Modified: MacRuby/trunk/lib/rexml/dtd/entitydecl.rb
===================================================================
--- MacRuby/trunk/lib/rexml/dtd/entitydecl.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/dtd/entitydecl.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -49,7 +49,7 @@
       def EntityDecl.parse_source source, listener
         md = source.match( PATTERN_RE, true )
         thing = md[0].squeeze(" \t\n\r")
-        listener.send inspect.downcase, thing 
+        listener.send inspect.downcase, thing
       end
     end
   end

Modified: MacRuby/trunk/lib/rexml/dtd/notationdecl.rb
===================================================================
--- MacRuby/trunk/lib/rexml/dtd/notationdecl.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/dtd/notationdecl.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -32,7 +32,7 @@
       def NotationDecl.parse_source source, listener
         md = source.match( PATTERN_RE, true )
         thing = md[0].squeeze(" \t\n\r")
-        listener.send inspect.downcase, thing 
+        listener.send inspect.downcase, thing
       end
     end
   end

Modified: MacRuby/trunk/lib/rexml/element.rb
===================================================================
--- MacRuby/trunk/lib/rexml/element.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/element.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -30,13 +30,13 @@
     attr_accessor :context
 
     # Constructor
-    # arg:: 
+    # arg::
     # 	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 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
     # 	copied.
-    # parent:: 
+    # parent::
     # 	if supplied, must be a Parent, and will be used as
     # 	the parent of this object.
     # context::
@@ -97,7 +97,7 @@
       self.class.new self
     end
 
-    # Evaluates to the root node of the document that this element 
+    # Evaluates to the root node of the document that this element
     # belongs to. If this element doesn't belong to a document, but does
     # belong to another Element, the parent's root will be returned, until the
     # earliest ancestor is found.
@@ -137,8 +137,8 @@
     # is the case if:
     # 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value
     # 2. The context has :+respect_whitespace+ set to :+all+ or
-    #    an array containing the name of this element, and 
-    #    :+compress_whitespace+ isn't set to :+all+ or an array containing the 
+    #    an array containing the name of this element, and
+    #    :+compress_whitespace+ isn't set to :+all+ or an array containing the
     #    name of this element.
     # The evaluation is tested against +expanded_name+, and so is namespace
     # sensitive.
@@ -162,7 +162,7 @@
       @ignore_whitespace_nodes = false
       if @context
         if @context[:ignore_whitespace_nodes]
-          @ignore_whitespace_nodes = 
+          @ignore_whitespace_nodes =
             (@context[:ignore_whitespace_nodes] == :all or
              @context[:ignore_whitespace_nodes].include? expanded_name)
         end
@@ -206,13 +206,13 @@
       return namespaces
     end
 
-    # Evalutas to the URI for a prefix, or the empty string if no such 
+    # Evalutas to the URI for a prefix, or the empty string if no such
     # namespace is declared for this element. Evaluates recursively for
     # ancestors.  Returns the default namespace, if there is one.
-    # prefix:: 
+    # prefix::
     #   the prefix to search for.  If not supplied, returns the default
     #   namespace if one exists
-    # Returns:: 
+    # Returns::
     #   the namespace URI as a String, or nil if no such namespace
     #   exists.  If the namespace is undefined, returns an empty string
     #  doc = Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
@@ -235,10 +235,10 @@
     end
 
     # Adds a namespace to this element.
-    # prefix:: 
+    # prefix::
     #   the prefix string, or the namespace URI if +uri+ is not
     #   supplied
-    # uri::    
+    # uri::
     #   the namespace URI.  May be nil, in which +prefix+ is used as
     #   the URI
     # Evaluates to: this Element
@@ -280,12 +280,12 @@
 
     # Adds a child to this element, optionally setting attributes in
     # the element.
-    # element:: 
+    # element::
     #   optional.  If Element, the element is added.
     #   Otherwise, a new Element is constructed with the argument (see
     #   Element.initialize).
-    # attrs:: 
-    #   If supplied, must be a Hash containing String name,value 
+    # attrs::
+    #   If supplied, must be a Hash containing String name,value
     #   pairs, which will be used to set the attributes of the new Element.
     # Returns:: the Element that was added
     #  el = doc.add_element 'my-tag'
@@ -302,9 +302,9 @@
     end
 
     # Deletes a child element.
-    # element:: 
-    #   Must be an +Element+, +String+, or +Integer+.  If Element, 
-    #   the element is removed.  If String, the element is found (via XPath) 
+    # element::
+    #   Must be an +Element+, +String+, or +Integer+.  If Element,
+    #   the element is removed.  If String, the element is found (via XPath)
     #   and removed.  <em>This means that any parent can remove any
     #   descendant.<em>  If Integer, the Element indexed by that number will be
     #   removed.
@@ -327,14 +327,14 @@
 
     # Iterates through the child elements, yielding for each Element that
     # has a particular attribute set.
-    # key:: 
+    # key::
     #   the name of the attribute to search for
-    # value:: 
+    # value::
     #   the value of the attribute
-    # max:: 
-    #   (optional) causes this method to return after yielding 
+    # max::
+    #   (optional) causes this method to return after yielding
     #   for this number of matching children
-    # name:: 
+    # name::
     #   (optional) if supplied, this is an XPath that filters
     #   the children to check.
     #
@@ -348,7 +348,7 @@
     #  # Yields d
     #  doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e}
     def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
-      each_with_something( proc {|child| 
+      each_with_something( proc {|child|
         if value.nil?
           child.attributes[key] != nil
         else
@@ -359,13 +359,13 @@
 
     # Iterates through the children, yielding for each Element that
     # has a particular text set.
-    # text:: 
+    # text::
     #   the text to search for.  If nil, or not supplied, will iterate
     #   over all +Element+ children that contain at least one +Text+ node.
-    # max:: 
+    # max::
     #   (optional) causes this method to return after yielding
     #   for this number of matching children
-    # name:: 
+    # name::
     #   (optional) if supplied, this is an XPath that filters
     #   the children to check.
     #
@@ -379,7 +379,7 @@
     #  # Yields d
     #  doc.each_element_with_text(nil, 0, 'd'){|e|p e}
     def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
-      each_with_something( proc {|child| 
+      each_with_something( proc {|child|
         if text.nil?
           child.has_text?
         else
@@ -408,7 +408,7 @@
     #  doc.root.elements['c'].next_element          #-> nil
     def next_element
       element = next_sibling
-      element = element.next_sibling until element.nil? or element.kind_of? Element 
+      element = element.next_sibling until element.nil? or element.kind_of? Element
       return element
     end
 
@@ -477,7 +477,7 @@
     # this method with a nil argument.  In this case, the next Text
     # child becomes the first Text child.  In no case is the order of
     # any siblings disturbed.
-    # text:: 
+    # text::
     #   If a String, a new Text child is created and added to
     #   this Element as the first Text child.  If Text, the text is set
     #   as the first Child element.  If nil, then any existing first Text
@@ -492,7 +492,7 @@
     def text=( text )
       if text.kind_of? String
         text = Text.new( text, whitespace(), nil, raw() )
-      elsif text and !text.kind_of? Text
+      elsif !text.nil? and !text.kind_of? Text
         text = Text.new( text.to_s, whitespace(), nil, raw() )
       end
       old_text = get_text
@@ -520,7 +520,7 @@
     # Note that at the end of this example, the branch has <b>3</b> nodes; the 'e'
     # element and <b>2</b> Text node children.
     def add_text( text )
-      if text.kind_of? String 
+      if text.kind_of? String
         if @children[-1].kind_of? Text
           @children[-1] << text
           return
@@ -559,7 +559,7 @@
       end
       prefix = nil if prefix == 'xmlns'
 
-      ret_val = 
+      ret_val =
         attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
 
       return ret_val unless ret_val.nil?
@@ -586,7 +586,7 @@
     #   the attribute is added to the list of Element attributes.  If String,
     #   the argument is used as the name of the new attribute, and the value
     #   parameter must be supplied.
-    # value:: 
+    # value::
     #   Required if +key+ is a String, and ignored if the first argument is
     #   an Attribute.  This is a String, and is used as the value
     #   of the new Attribute.  This should be the unnormalized value of the
@@ -621,7 +621,7 @@
     #   either an Attribute or a String.  In either case, the
     #   attribute is found by matching the attribute name to the argument,
     #   and then removed.  If no attribute is found, no action is taken.
-    # Returns:: 
+    # Returns::
     #   the attribute removed, or nil if this Element did not contain
     #   a matching attribute
     #  e = Element.new('E')
@@ -638,7 +638,7 @@
     # Other Utilities                               #
     #################################################
 
-    # Get an array of all CData children.  
+    # Get an array of all CData children.
     # IMMUTABLE
     def cdatas
       find_all { |child| child.kind_of? CData }.freeze
@@ -681,7 +681,7 @@
     #   Internet Explorer is the worst piece of crap to have ever been
     #   written, with the possible exception of Windows itself.  Since IE is
     #   unable to parse proper XML, we have to provide a hack to generate XML
-    #   that IE's limited abilities can handle.  This hack inserts a space 
+    #   that IE's limited abilities can handle.  This hack inserts a space
     #   before the /> on empty tags.  Defaults to false
     #
     #  out = ''
@@ -707,8 +707,8 @@
     def __to_xpath_helper node
       rv = node.expanded_name.clone
       if node.parent
-        results = node.parent.find_all {|n| 
-          n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name 
+        results = node.parent.find_all {|n|
+          n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
         }
         if results.length > 1
           idx = results.index( node )
@@ -734,7 +734,7 @@
 
   # A class which provides filtering of children for Elements, and
   # XPath search support.  You are expected to only encounter this class as
-  # the <tt>element.elements</tt> object.  Therefore, you are 
+  # the <tt>element.elements</tt> object.  Therefore, you are
   # _not_ expected to instantiate this yourself.
   class Elements
     include Enumerable
@@ -746,7 +746,7 @@
 
     # Fetches a child element.  Filters only Element children, regardless of
     # the XPath match.
-    # index:: 
+    # index::
     #   the search parameter.  This is either an Integer, which
     #   will be used to find the index'th child Element, or an XPath,
     #   which will be used to search for the Element.  <em>Because
@@ -756,7 +756,7 @@
     #   child element is at index 1, not 0, and the +n+th element is at index
     #   +n+, not <tt>n-1</tt>.  This is because XPath indexes element children
     #   starting from 1, not 0, and the indexes should be the same.
-    # name:: 
+    # name::
     #   optional, and only used in the first argument is an
     #   Integer.  In that case, the index'th child Element that has the
     #   supplied name will be returned.  Note again that the indexes start at 1.
@@ -772,12 +772,12 @@
         num = 0
         @element.find { |child|
           child.kind_of? Element and
-          (name.nil? ? true : child.has_name?( name )) and 
+          (name.nil? ? true : child.has_name?( name )) and
           (num += 1) == index
         }
       else
         return XPath::first( @element, index )
-        #{ |element| 
+        #{ |element|
         #	return element if element.kind_of? Element
         #}
         #return nil
@@ -787,7 +787,7 @@
     # Sets an element, replacing any previous matching element.  If no
     # existing element is found ,the element is added.
     # index:: Used to find a matching element to replace.  See []().
-    # element:: 
+    # element::
     #   The element to replace the existing element with
     #   the previous element
     # Returns:: nil if no previous element was found.
@@ -812,12 +812,12 @@
       @element.find{ |child| child.kind_of? Element}.nil?
     end
 
-    # Returns the index of the supplied child (starting at 1), or -1 if 
+    # Returns the index of the supplied child (starting at 1), or -1 if
     # the element is not a child
     # element:: an +Element+ child
     def index element
       rv = 0
-      found = @element.find do |child| 
+      found = @element.find do |child|
         child.kind_of? Element and
         (rv += 1) and
         child == element
@@ -827,7 +827,7 @@
     end
 
     # Deletes a child Element
-    # element:: 
+    # element::
     #   Either an Element, which is removed directly; an
     #   xpath, where the first matching child is removed; or an Integer,
     #   where the n'th Element is removed.
@@ -854,7 +854,7 @@
     #  deleted = doc.elements.delete_all 'a/c' #-> [<c/>, <c/>, <c/>, <c/>]
     def delete_all( xpath )
       rv = []
-      XPath::each( @element, xpath) {|element| 
+      XPath::each( @element, xpath) {|element|
         rv << element if element.kind_of? Element
       }
       rv.each do |element|
@@ -865,7 +865,7 @@
     end
 
     # Adds an element
-    # element:: 
+    # element::
     #   if supplied, is either an Element, String, or
     #   Source (see Element.initialize).  If not supplied or nil, a
     #   new, default Element will be constructed
@@ -890,8 +890,8 @@
 
     # Iterates through all of the child Elements, optionally filtering
     # them by a given XPath
-    # xpath:: 
-    #   optional.  If supplied, this is a String XPath, and is used to 
+    # xpath::
+    #   optional.  If supplied, this is a String XPath, and is used to
     #   filter the children, so that only matching children are yielded.  Note
     #   that XPaths are automatically filtered for Elements, so that
     #   non-Element children will not be yielded
@@ -908,8 +908,8 @@
 
     def collect( xpath=nil, &block )
       collection = []
-      XPath::each( @element, xpath ) {|e| 
-        collection << yield(e)  if e.kind_of?(Element) 
+      XPath::each( @element, xpath ) {|e|
+        collection << yield(e)  if e.kind_of?(Element)
       }
       collection
     end
@@ -944,7 +944,7 @@
     # supplied XPath matches non-Element children.
     #  doc = Document.new '<a>sean<b/>elliott<c/></a>'
     #  doc.root.elements.to_a                  #-> [ <b/>, <c/> ]
-    #  doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ] 
+    #  doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ]
     #  XPath.match(doc.root, "child::node()")  #-> [ sean, <b/>, elliott, <c/> ]
     def to_a( xpath=nil )
       rv = XPath.match( @element, xpath )
@@ -964,7 +964,7 @@
   # ATTRIBUTES                                                           #
   ########################################################################
 
-  # A class that defines the set of Attributes of an Element and provides 
+  # A class that defines the set of Attributes of an Element and provides
   # operations for accessing elements in that set.
   class Attributes < Hash
     # Constructor
@@ -976,11 +976,11 @@
     # Fetches an attribute value.  If you want to get the Attribute itself,
     # use get_attribute()
     # name:: an XPath attribute name.  Namespaces are relevant here.
-    # Returns:: 
+    # Returns::
     #   the String value of the matching attribute, or +nil+ if no
     #   matching attribute was found.  This is the unnormalized value
     #   (with entities expanded).
-    # 
+    #
     #  doc = Document.new "<a foo:att='1' bar:att='2' att='&lt;'/>"
     #  doc.root.attributes['att']         #-> '<'
     #  doc.root.attributes['bar:att']     #-> '2'
@@ -1006,7 +1006,7 @@
 
     # Iterates over the attributes of an Element.  Yields actual Attribute
     # nodes, not String values.
-    # 
+    #
     #  doc = Document.new '<a x="1" y="2"/>'
     #  doc.root.attributes.each_attribute {|attr|
     #    p attr.expanded_name+" => "+attr.value
@@ -1033,7 +1033,7 @@
     end
 
     # Fetches an attribute
-    # name:: 
+    # name::
     #   the name by which to search for the attribute.  Can be a
     #   <tt>prefix:name</tt> namespace name.
     # Returns:: The first matching attribute, or nil if there was none.  This
@@ -1077,10 +1077,10 @@
     # Sets an attribute, overwriting any existing attribute value by the
     # same name.  Namespace is significant.
     # name:: the name of the attribute
-    # value:: 
+    # value::
     #   (optional) If supplied, the value of the attribute.  If
     #   nil, any existing matching attribute is deleted.
-    # Returns:: 
+    # Returns::
     #   Owning element
     #  doc = Document.new "<a x:foo='1' foo='3'/>"
     #  doc.root.attributes['y:foo'] = '2'
@@ -1109,13 +1109,13 @@
         old_attr[value.prefix] = value
       elsif old_attr.prefix != value.prefix
         # Check for conflicting namespaces
-        raise ParseException.new( 
+        raise ParseException.new(
           "Namespace conflict in adding attribute \"#{value.name}\": "+
           "Prefix \"#{old_attr.prefix}\" = "+
           "\"#{@element.namespace(old_attr.prefix)}\" and prefix "+
-          "\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if 
+          "\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if
           value.prefix != "xmlns" and old_attr.prefix != "xmlns" and
-          @element.namespace( old_attr.prefix ) == 
+          @element.namespace( old_attr.prefix ) ==
             @element.namespace( value.prefix )
           store value.name, { old_attr.prefix	=> old_attr,
             value.prefix		=> value }
@@ -1125,7 +1125,7 @@
       return @element
     end
 
-    # Returns an array of Strings containing all of the prefixes declared 
+    # Returns an array of Strings containing all of the prefixes declared
     # by this set of # attributes.  The array does not include the default
     # namespace declaration, if one exists.
     #  doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' "+
@@ -1164,7 +1164,7 @@
     end
 
     # Removes an attribute
-    # attribute:: 
+    # attribute::
     #   either a String, which is the name of the attribute to remove --
     #   namespaces are significant here -- or the attribute to remove.
     # Returns:: the owning element
@@ -1212,12 +1212,12 @@
     alias :<< :add
 
     # Deletes all attributes matching a name.  Namespaces are significant.
-    # name:: 
+    # name::
     #   A String; all attributes that match this path will be removed
     # Returns:: an Array of the Attributes that were removed
     def delete_all( name )
       rv = []
-      each_attribute { |attribute| 
+      each_attribute { |attribute|
         rv << attribute if attribute.expanded_name == name
       }
       rv.each{ |attr| attr.remove }
@@ -1227,7 +1227,7 @@
     # The +get_attribute_ns+ method retrieves a method by its namespace
     # and name. Thus it is possible to reliably identify an attribute
     # even if an XML processor has changed the prefix.
-    # 
+    #
     # Method contributed by Henrik Martensson
     def get_attribute_ns(namespace, name)
       result = nil
@@ -1236,7 +1236,7 @@
           namespace == attribute.namespace() &&
           ( !namespace.empty? || !attribute.fully_expanded_name.index(':') )
           # 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(':')
         end
       }

Modified: MacRuby/trunk/lib/rexml/encoding.rb
===================================================================
--- MacRuby/trunk/lib/rexml/encoding.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/encoding.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -29,7 +29,7 @@
         if enc and enc != UTF_8
           @encoding = enc
           raise ArgumentError, "Bad encoding name #@encoding" unless @encoding =~ /^[\w-]+$/
-          @encoding.untaint 
+          @encoding.untaint
           begin
             require 'rexml/encodings/ICONV.rb'
             Encoding.apply(self, "ICONV")

Modified: MacRuby/trunk/lib/rexml/encodings/CP-1252.rb
===================================================================
--- MacRuby/trunk/lib/rexml/encodings/CP-1252.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/encodings/CP-1252.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -58,7 +58,7 @@
       end
       array_enc.pack('C*')
     end
-    
+
     # Convert to UTF-8
     def decode_cp1252(str)
       array_latin9 = str.unpack('C*')

Modified: MacRuby/trunk/lib/rexml/encodings/ISO-8859-15.rb
===================================================================
--- MacRuby/trunk/lib/rexml/encodings/ISO-8859-15.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/encodings/ISO-8859-15.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -46,7 +46,7 @@
       end
       array_enc.pack('C*')
     end
-    
+
     # Convert to UTF-8
     def from_iso_8859_15(str)
       array_latin9 = str.unpack('C*')

Modified: MacRuby/trunk/lib/rexml/encodings/UNILE.rb
===================================================================
--- MacRuby/trunk/lib/rexml/encodings/UNILE.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/encodings/UNILE.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -18,7 +18,7 @@
     def decode_unile(str)
       array_enc=str.unpack('C*')
       array_utf8 = []
-      0.step(array_enc.size-1, 2){|i| 
+      0.step(array_enc.size-1, 2){|i|
         array_utf8 << (array_enc.at(i) + array_enc.at(i+1)*0x100)
       }
       array_utf8.pack('U*')

Modified: MacRuby/trunk/lib/rexml/encodings/UTF-16.rb
===================================================================
--- MacRuby/trunk/lib/rexml/encodings/UTF-16.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/encodings/UTF-16.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -17,10 +17,11 @@
 
     def decode_utf16(str)
       # XXX macruby cannot compile this regexp
+      # It now compiles it but doesn't match it
       #str = str[2..-1] if /^\376\377/n =~ str
       array_enc=str.unpack('C*')
       array_utf8 = []
-      0.step(array_enc.size-1, 2){|i| 
+      0.step(array_enc.size-1, 2){|i|
         array_utf8 << (array_enc.at(i+1) + array_enc.at(i)*0x100)
       }
       array_utf8.pack('U*')

Modified: MacRuby/trunk/lib/rexml/entity.rb
===================================================================
--- MacRuby/trunk/lib/rexml/entity.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/entity.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -25,12 +25,12 @@
     # Create a new entity.  Simple entities can be constructed by passing a
     # name, value to the constructor; this creates a generic, plain entity
     # reference. For anything more complicated, you have to pass a Source to
-    # the constructor with the entity definiton, or use the accessor methods.
+    # the constructor with the entity definition, or use the accessor methods.
     # +WARNING+: There is no validation of entity state except when the entity
     # is read from a stream.  If you start poking around with the accessors,
     # you can easily create a non-conformant Entity.  The best thing to do is
     # dump the stupid DTDs and use XMLSchema instead.
-    # 
+    #
     #  e = Entity.new( 'amp', '&' )
     def initialize stream, value=nil, parent=nil, reference=false
       super(parent)
@@ -38,7 +38,7 @@
       if stream.kind_of? Array
         @name = stream[1]
         if stream[-1] == '%'
-          @reference = true 
+          @reference = true
           stream.pop
         else
           @reference = false

Modified: MacRuby/trunk/lib/rexml/formatters/default.rb
===================================================================
--- MacRuby/trunk/lib/rexml/formatters/default.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/formatters/default.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -21,7 +21,7 @@
       def write( node, output )
         case node
 
-        when Document 
+        when Document
           if node.xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
             output = Output.new( output, node.xml_decl.encoding )
           end
@@ -63,14 +63,16 @@
       def write_element( node, output )
         output << "<#{node.expanded_name}"
 
-        node.attributes.to_a.sort_by {|attr| attr.name}.each do |attr|
+        node.attributes.to_a.map { |a|
+          Hash === a ? a.values : a
+        }.flatten.sort_by {|attr| attr.name}.each do |attr|
           output << " "
           attr.write( output )
         end unless node.attributes.empty?
 
         if node.children.empty?
           output << " " if @ie_hack
-          output << "/" 
+          output << "/"
         else
           output << ">"
           node.children.each { |child|

Modified: MacRuby/trunk/lib/rexml/formatters/pretty.rb
===================================================================
--- MacRuby/trunk/lib/rexml/formatters/pretty.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/formatters/pretty.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -48,7 +48,7 @@
           if @ie_hack
             output << " "
           end
-          output << "/" 
+          output << "/"
         else
           output << ">"
           # If compact and all children are text, and if the formatted output

Modified: MacRuby/trunk/lib/rexml/formatters/transitive.rb
===================================================================
--- MacRuby/trunk/lib/rexml/formatters/transitive.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/formatters/transitive.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -31,7 +31,7 @@
         output << ' '*@level
         if node.children.empty?
           output << " " if @ie_hack
-          output << "/" 
+          output << "/"
         else
           output << ">"
           # If compact and all children are text, and if the formatted output

Modified: MacRuby/trunk/lib/rexml/functions.rb
===================================================================
--- MacRuby/trunk/lib/rexml/functions.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/functions.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -48,7 +48,7 @@
     # UNTESTED
     def Functions::local_name( node_set=nil )
       get_namespace( node_set ) do |node|
-        return node.local_name 
+        return node.local_name
       end
     end
 
@@ -57,7 +57,7 @@
     end
 
     def Functions::name( node_set=nil )
-      get_namespace( node_set ) do |node| 
+      get_namespace( node_set ) do |node|
         node.expanded_name
       end
     end
@@ -66,7 +66,7 @@
     def Functions::get_namespace( node_set = nil )
       if node_set == nil
         yield @@context[:node] if defined? @@context[:node].namespace
-      else  
+      else
         if node_set.respond_to? :each
           node_set.each { |node| yield node if defined? node.namespace }
         elsif node_set.respond_to? :namespace
@@ -81,15 +81,15 @@
     #
     # A number is converted to a string as follows
     #
-    # NaN is converted to the string NaN 
+    # NaN is converted to the string NaN
     #
-    # positive zero is converted to the string 0 
+    # positive zero is converted to the string 0
     #
-    # negative zero is converted to the string 0 
+    # negative zero is converted to the string 0
     #
-    # positive infinity is converted to the string Infinity 
+    # positive infinity is converted to the string Infinity
     #
-    # negative infinity is converted to the string -Infinity 
+    # negative infinity is converted to the string -Infinity
     #
     # if the number is an integer, the number is represented in decimal form
     # as a Number with no decimal point and no leading zeros, preceded by a
@@ -156,7 +156,7 @@
       string(string).include?(string(test))
     end
 
-    # Kouhei fixed this 
+    # Kouhei fixed this
     def Functions::substring_before( string, test )
       ruby_string = string(string)
       ruby_index = ruby_string.index(string(test))
@@ -166,7 +166,7 @@
         ruby_string[ 0...ruby_index ]
       end
     end
- 
+
     # Kouhei fixed this too
     def Functions::substring_after( string, test )
       ruby_string = string(string)
@@ -175,11 +175,11 @@
       ""
     end
 
-    # Take equal portions of Mike Stok and Sean Russell; mix 
+    # Take equal portions of Mike Stok and Sean Russell; mix
     # vigorously, and pour into a tall, chilled glass.  Serves 10,000.
     def Functions::substring( string, start, length=nil )
       ruby_string = string(string)
-      ruby_length = if length.nil? 
+      ruby_length = if length.nil?
                       ruby_string.length.to_f
                     else
                       number(length)
@@ -188,15 +188,15 @@
 
       # Handle the special cases
       return '' if (
-        ruby_length.nan? or 
+        ruby_length.nan? or
         ruby_start.nan? or
         ruby_start.infinite?
       )
 
       infinite_length = ruby_length.infinite? == 1
       ruby_length = ruby_string.length if infinite_length
-        
-      # Now, get the bounds.  The XPath bounds are 1..length; the ruby bounds 
+
+      # Now, get the bounds.  The XPath bounds are 1..length; the ruby bounds
       # are 0..length.  Therefore, we have to offset the bounds by one.
       ruby_start = ruby_start.round - 1
       ruby_length = ruby_length.round
@@ -247,7 +247,7 @@
       0.upto(from.length - 1) { |pos|
         from_char = from[pos]
         unless map.has_key? from_char
-          map[from_char] = 
+          map[from_char] =
           if pos < to.length
             to[pos]
           else
@@ -359,7 +359,7 @@
       nodes = [nodes] unless nodes.kind_of? Array
       nodes.inject(0) { |r,n| r += number(string(n)) }
     end
-    
+
     def Functions::floor( number )
       number(number).floor
     end

Modified: MacRuby/trunk/lib/rexml/instruction.rb
===================================================================
--- MacRuby/trunk/lib/rexml/instruction.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/instruction.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -13,7 +13,7 @@
     attr_accessor :target, :content
 
     # Constructs a new Instruction
-    # @param target can be one of a number of things.  If String, then 
+    # @param target can be one of a number of things.  If String, then
     # the target of this instruction is set to this.  If an Instruction,
     # then the Instruction is shallowly cloned (target and content are
     # copied).  If a Source, then the source is scanned and parsed for
@@ -37,7 +37,7 @@
     def clone
       Instruction.new self
     end
-    
+
     # == DEPRECATED
     # See the rexml/formatters package
     #

Modified: MacRuby/trunk/lib/rexml/namespace.rb
===================================================================
--- MacRuby/trunk/lib/rexml/namespace.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/namespace.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -40,7 +40,7 @@
     # source file.
     def fully_expanded_name
       ns = prefix
-      return "#{ns}:#@name" if ns.size > 0 
+      return "#{ns}:#@name" if ns.size > 0
       return @name
     end
   end

Modified: MacRuby/trunk/lib/rexml/node.rb
===================================================================
--- MacRuby/trunk/lib/rexml/node.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/node.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -57,7 +57,7 @@
       }
     end
 
-    # Find (and return) first subnode (recursively) for which the block 
+    # Find (and return) first subnode (recursively) for which the block
     # evaluates to true. Returns +nil+ if none was found.
     def find_first_recursive(&block) # :yields: node
       each_recursive {|node|

Modified: MacRuby/trunk/lib/rexml/output.rb
===================================================================
--- MacRuby/trunk/lib/rexml/output.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/output.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 module REXML
   class Output
     include Encoding
-    
+
     attr_reader :encoding
 
     def initialize real_IO, encd="iso-8859-1"

Modified: MacRuby/trunk/lib/rexml/parent.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parent.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parent.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -6,14 +6,14 @@
   # object.
   class Parent < Child
     include Enumerable
-    
+
     # Constructor
     # @param parent if supplied, will be set as the parent of this object
     def initialize parent=nil
       super(parent)
       @children = []
     end
-    
+
     def add( object )
       #puts "PARENT GOTS #{size} CHILDREN"
       object.parent = self
@@ -21,47 +21,48 @@
       #puts "PARENT NOW GOTS #{size} CHILDREN"
       object
     end
-    
+
     alias :push :add
     alias :<< :push
-    
+
     def unshift( object )
       object.parent = self
       @children.unshift object
     end
-    
+
     def delete( object )
       found = false
       @children.delete_if {|c| c.equal?(object) and found = true }
       object.parent = nil if found
+      found ? object : nil
     end
-    
+
     def each(&block)
       @children.each(&block)
     end
-    
+
     def delete_if( &block )
       @children.delete_if(&block)
     end
-    
+
     def delete_at( index )
       @children.delete_at index
     end
-    
+
     def each_index( &block )
       @children.each_index(&block)
     end
-    
+
     # Fetches a child at a given index
     # @param index the Integer index of the child to fetch
     def []( index )
       @children[index]
     end
-    
+
     alias :each_child :each
-    
-    
-    
+
+
+
     # Set an index entry.  See Array.[]=
     # @param index the index of the element to set
     # @param opt either the object to set, or an Integer length
@@ -71,7 +72,7 @@
       args[-1].parent = self
       @children[*args[0..-2]] = args[-1]
     end
-    
+
     # Inserts an child before another child
     # @param child1 this is either an xpath or an Element.  If an Element,
     # child2 will be inserted before child1 in the child list of the parent.
@@ -91,7 +92,7 @@
       end
       self
     end
-    
+
     # Inserts an child after another child
     # @param child1 this is either an xpath or an Element.  If an Element,
     # child2 will be inserted after child1 in the child list of the parent.
@@ -111,11 +112,11 @@
       end
       self
     end
-    
+
     def to_a
       @children.dup
     end
-    
+
     # Fetches the index of a given child
     # @param child the child to get the index of
     # @return the index of the child, or nil if the object is not a child
@@ -125,24 +126,24 @@
       @children.find { |i| count += 1 ; i.hash == child.hash }
       count
     end
-    
+
     # @return the number of children of this parent
     def size
       @children.size
     end
-    
+
     alias :length :size
-    
+
     # Replaces one child with another, making sure the nodelist is correct
     # @param to_replace the child to replace (must be a Child)
-    # @param replacement the child to insert into the nodelist (must be a 
+    # @param replacement the child to insert into the nodelist (must be a
     # Child)
     def replace_child( to_replace, replacement )
       @children.map! {|c| c.equal?( to_replace ) ? replacement : c }
       to_replace.parent = nil
       replacement.parent = self
     end
-    
+
     # Deeply clones this object.  This creates a complete duplicate of this
     # Parent, including all descendants.
     def deep_clone
@@ -156,9 +157,9 @@
       end
       cl
     end
-    
+
     alias :children :to_a
-    
+
     def parent?
       true
     end

Modified: MacRuby/trunk/lib/rexml/parseexception.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parseexception.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parseexception.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -30,7 +30,7 @@
         err << "Last 80 unconsumed characters:\n"
         err << @source.buffer[0..80].gsub(/\n/, ' ')
       end
-      
+
       err
     end
 
@@ -40,12 +40,12 @@
     end
 
     def line
-      @source.current_line[2] if @source and defined? @source.current_line and 
+      @source.current_line[2] if @source and defined? @source.current_line and
       @source.current_line
     end
 
     def context
       @source.current_line
     end
-  end  
+  end
 end

Modified: MacRuby/trunk/lib/rexml/parsers/baseparser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/baseparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/baseparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -25,24 +25,17 @@
     #
     # Nat Price gave me some good ideas for the API.
     class BaseParser
-      if String.method_defined? :encode
-        # Oniguruma / POSIX [understands unicode]
-        LETTER = '[[:alpha:]]'
-        DIGIT = '[[:digit:]]'
-      else
-        # Ruby < 1.9 [doesn't understand unicode]
-        LETTER = 'a-zA-Z'
-        DIGIT = '\d'
-      end
+      LETTER = '[:alpha:]'
+      DIGIT = '[:digit:]'
 
       COMBININGCHAR = '' # TODO
       EXTENDER = ''      # TODO
 
-      NCNAME_STR= "[#{LETTER}_:][-#{LETTER}#{DIGIT}._:#{COMBININGCHAR}#{EXTENDER}]*"
+      NCNAME_STR= "[#{LETTER}_:][-[:alnum:]._:#{COMBININGCHAR}#{EXTENDER}]*"
       NAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})"
       UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
 
-      NAMECHAR = '[\-\w\d\.:]'
+      NAMECHAR = '[\-\w\.:]'
       NAME = "([\\w:]#{NAMECHAR}*)"
       NMTOKEN = "(?:#{NAMECHAR})+"
       NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
@@ -66,7 +59,7 @@
 
       VERSION = /\bversion\s*=\s*["'](.*?)['"]/um
       ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um
-      STANDALONE = /\bstandalone\s*=\s["'](.*?)['"]/um
+      STANDALONE = /\bstandalone\s*=\s*["'](.*?)['"]/um
 
       ENTITY_START = /^\s*<!ENTITY/
       IDENTITY = /^([!\*\w\-]+)(\s+#{NCNAME_STR})?(\s+["'](.*?)['"])?(\s+['"](.*?)["'])?/u
@@ -105,11 +98,11 @@
 
       EREFERENCE = /&(?!#{NAME};)/
 
-      DEFAULT_ENTITIES = { 
-        'gt' => [/&gt;/, '&gt;', '>', />/], 
-        'lt' => [/&lt;/, '&lt;', '<', /</], 
-        'quot' => [/&quot;/, '&quot;', '"', /"/], 
-        "apos" => [/&apos;/, "&apos;", "'", /'/] 
+      DEFAULT_ENTITIES = {
+        'gt' => [/&gt;/, '&gt;', '>', />/],
+        'lt' => [/&lt;/, '&lt;', '<', /</],
+        'quot' => [/&quot;/, '&quot;', '"', /"/],
+        "apos" => [/&apos;/, "&apos;", "'", /'/]
       }
 
 
@@ -180,9 +173,9 @@
       # Peek at the +depth+ event in the stack.  The first element on the stack
       # is at depth 0.  If +depth+ is -1, will parse to the end of the input
       # stream and return the last event, which is always :end_document.
-      # Be aware that this causes the stream to be parsed up to the +depth+ 
-      # event, so you can effectively pre-parse the entire document (pull the 
-      # entire thing into memory) using this method.  
+      # Be aware that this causes the stream to be parsed up to the +depth+
+      # event, so you can effectively pre-parse the entire document (pull the
+      # entire thing into memory) using this method.
       def peek depth=0
         raise %Q[Illegal argument "#{depth}"] if depth < -1
         temp = []
@@ -265,7 +258,7 @@
         if @document_status == :in_doctype
           md = @source.match(/\s*(.*?>)/um)
           case md[1]
-          when SYSTEMENTITY 
+          when SYSTEMENTITY
             match = @source.match( SYSTEMENTITY, true )[1]
             return [ :externalentity, match ]
 
@@ -344,7 +337,7 @@
               #md = @source.match_to_consume( '>', CLOSE_MATCH)
               md = @source.match( CLOSE_MATCH, true )
               raise REXML::ParseException.new( "Missing end tag for "+
-                "'#{last_tag}' (got \"#{md[1]}\")", 
+                "'#{last_tag}' (got \"#{md[1]}\")",
                 @source) unless last_tag == md[1]
               return [ :end_element, last_tag ]
             elsif @source.buffer[1] == ?!
@@ -377,7 +370,7 @@
               unless md
                 # Check for missing attribute quotes
                 raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES )
-                raise REXML::ParseException.new("malformed XML: missing tag start", @source) 
+                raise REXML::ParseException.new("malformed XML: missing tag start", @source)
               end
               attributes = {}
               prefixes = Set.new
@@ -386,7 +379,7 @@
               if md[4].size > 0
                 attrs = md[4].scan( ATTRIBUTE_PATTERN )
                 raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0
-                attrs.each { |a,b,c,d,e| 
+                attrs.each { |a,b,c,d,e|
                   if b == "xmlns"
                     if c == "xml"
                       if d != "http://www.w3.org/XML/1998/namespace"
@@ -409,10 +402,10 @@
                     raise REXML::ParseException.new( msg, @source, self)
                   end
 
-                  attributes[a] = e 
+                  attributes[a] = e
                 }
               end
-        
+
               # Verify that all of the prefixes have been defined
               for prefix in prefixes
                 unless @nsstack.find{|k| k.member?(prefix)}
@@ -466,7 +459,7 @@
         # Doing it like this rather than in a loop improves the speed
         copy.gsub!( EREFERENCE, '&amp;' )
         entities.each do |key, value|
-          copy.gsub!( value, "&#{key};" ) unless entity_filter and 
+          copy.gsub!( value, "&#{key};" ) unless entity_filter and
                                       entity_filter.include?(entity)
         end if entities
         copy.gsub!( EREFERENCE, '&amp;' )

Modified: MacRuby/trunk/lib/rexml/parsers/pullparser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/pullparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/pullparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -68,7 +68,7 @@
         event = @parser.pull
         case event[0]
         when :entitydecl
-          @entities[ event[1] ] = 
+          @entities[ event[1] ] =
             event[2] unless event[2] =~ /PUBLIC|SYSTEM/
         when :text
           unnormalized = @parser.unnormalize( event[1], @entities )

Modified: MacRuby/trunk/lib/rexml/parsers/sax2parser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/sax2parser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/sax2parser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -20,7 +20,7 @@
       def source
         @parser.source
       end
-      
+
       def add_listener( listener )
         @parser.add_listener( listener )
       end
@@ -44,7 +44,7 @@
       # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
       #
       # There is an additional symbol that can be listened for: :progress.
-      # This will be called for every event generated, passing in the current 
+      # This will be called for every event generated, passing in the current
       # stream position.
       #
       # Array contains regular expressions or strings which will be matched
@@ -72,7 +72,7 @@
           add([nil, nil, args[0]])
         end
       end
-      
+
       def deafen( listener=nil, &blok )
         if listener
           @listeners.delete_if {|item| item[-1] == listener }
@@ -81,10 +81,10 @@
           @procs.delete_if {|item| item[-1] == blok }
         end
       end
-      
+
       def parse
         @procs.each { |sym,match,block| block.call if sym == :start_document }
-        @listeners.each { |sym,match,block| 
+        @listeners.each { |sym,match,block|
           block.start_document if sym == :start_document or sym.nil?
         }
         root = context = []
@@ -126,8 +126,8 @@
             listeners = get_listeners( :start_element, event[1] )
             # notify observers
             procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
-            listeners.each { |ob| 
-              ob.start_element( uri, local, event[1], event[2] ) 
+            listeners.each { |ob|
+              ob.start_element( uri, local, event[1], event[2] )
             } if listeners
           when :end_element
             @tag_stack.pop
@@ -140,8 +140,8 @@
             listeners = get_listeners( :end_element, event[1] )
             # notify observers
             procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
-            listeners.each { |ob| 
-              ob.end_element( uri, local, event[1] ) 
+            listeners.each { |ob|
+              ob.end_element( uri, local, event[1] )
             } if listeners
 
             namespace_mapping = @namespace_stack.pop
@@ -160,7 +160,7 @@
             #handle( :characters, normalized )
             copy = event[1].clone
 
-            esub = proc { |match| 
+            esub = proc { |match|
               if @entities.has_key?($1)
                 @entities[$1].gsub(Text::REFERENCE, &esub)
               else
@@ -178,7 +178,7 @@
           when :entitydecl
             @entities[ event[1] ] = event[2] if event.size == 3
             handle( *event )
-          when :processing_instruction, :comment, :attlistdecl, 
+          when :processing_instruction, :comment, :attlistdecl,
             :elementdecl, :cdata, :notationdecl, :xmldecl
             handle( *event )
           end
@@ -193,8 +193,8 @@
         listeners = get_listeners( symbol, tag )
         # notify observers
         procs.each { |ob| ob.call( *arguments ) } if procs
-        listeners.each { |l| 
-          l.send( symbol.to_s, *arguments ) 
+        listeners.each { |l|
+          l.send( symbol.to_s, *arguments )
         } if listeners
       end
 
@@ -205,7 +205,7 @@
         @procs.find_all do |sym, match, block|
           #puts sym.inspect+"=="+symbol.inspect+ "\t"+match.inspect+"=="+name.inspect+ "\t"+( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match)))).to_s
           (
-            (sym.nil? or symbol == sym) and 
+            (sym.nil? or symbol == sym) and
             ((name.nil? and match.nil?) or match.nil? or (
               (name == match) or
               (match.kind_of? Regexp and name =~ match)
@@ -218,7 +218,7 @@
         return nil if @listeners.size == 0
         @listeners.find_all do |sym, match, block|
           (
-            (sym.nil? or symbol == sym) and 
+            (sym.nil? or symbol == sym) and
             ((name.nil? and match.nil?) or match.nil? or (
               (name == match) or
               (match.kind_of? Regexp and name =~ match)
@@ -237,7 +237,7 @@
         end
       end
 
-      def get_namespace( prefix ) 
+      def get_namespace( prefix )
         uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
           (@namespace_stack.find { |ns| not ns[nil].nil? })
         uris[-1][prefix] unless uris.nil? or 0 == uris.size

Modified: MacRuby/trunk/lib/rexml/parsers/streamparser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/streamparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/streamparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -5,11 +5,11 @@
         @listener = listener
         @parser = BaseParser.new( source )
       end
-      
+
       def add_listener( listener )
         @parser.add_listener( listener )
       end
-      
+
       def parse
         # entity string
         while true

Modified: MacRuby/trunk/lib/rexml/parsers/treeparser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/treeparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/treeparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -42,8 +42,8 @@
                 if @build_context[-1].instance_of? Text
                   @build_context[-1] << event[1]
                 else
-                  @build_context.add( 
-                    Text.new(event[1], @build_context.whitespace, nil, true) 
+                  @build_context.add(
+                    Text.new(event[1], @build_context.whitespace, nil, true)
                   ) unless (
                     @build_context.ignore_whitespace_nodes and
                     event[1].strip.size==0

Modified: MacRuby/trunk/lib/rexml/parsers/xpathparser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/parsers/xpathparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/parsers/xpathparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -53,8 +53,8 @@
             string << "*"
           when :text
             string << "text()"
-          when :following, :following_sibling, 
-                :ancestor, :ancestor_or_self, :descendant, 
+          when :following, :following_sibling,
+                :ancestor, :ancestor_or_self, :descendant,
                 :namespace, :preceding, :preceding_sibling
             string << "/" unless string.size == 0
             string << op.to_s.tr("_", "-")
@@ -97,7 +97,7 @@
           case op
           when :node
             string << "node()"
-          when :attribute, :child, :following, :following_sibling, 
+          when :attribute, :child, :following, :following_sibling,
                 :ancestor, :ancestor_or_self, :descendant, :descendant_or_self,
                 :namespace, :preceding, :preceding_sibling, :self, :parent
             string << "/" unless string.size == 0
@@ -249,7 +249,7 @@
 
             parsed.concat(n)
           end
-          
+
           if path.size > 0
             if path[0] == ?/
               if path[1] == ?/
@@ -332,12 +332,12 @@
           predicates << expr[1..-2] if expr
         end
         #puts "PREDICATES = #{predicates.inspect}"
-        predicates.each{ |pred| 
+        predicates.each{ |pred|
           #puts "ORING #{pred}"
           preds = []
           parsed << :predicate
           parsed << preds
-          OrExpr(pred, preds) 
+          OrExpr(pred, preds)
         }
         #puts "PREDICATES = #{predicates.inspect}"
         path
@@ -551,7 +551,7 @@
           end
         end
         #puts "BEFORE WITH '#{rest}'"
-        rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w_*]/
+        rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/
         parsed.concat(n)
         return rest
       end
@@ -600,13 +600,13 @@
           #puts "LITERAL or NUMBER: #$1"
           varname = $1.nil? ? $2 : $1
           path = $'
-          parsed << :literal 
+          parsed << :literal
           parsed << (varname.include?('.') ? varname.to_f : varname.to_i)
         when LITERAL
           #puts "LITERAL or NUMBER: #$1"
           varname = $1.nil? ? $2 : $1
           path = $'
-          parsed << :literal 
+          parsed << :literal
           parsed << varname
         when /^\(/                                               #/
           path, contents = get_group(path)
@@ -649,7 +649,7 @@
         return nil unless depth==0
         [string[ind..-1], string[0..ind-1]]
       end
-      
+
       def parse_args( string )
         arguments = []
         ind = 0
@@ -683,7 +683,7 @@
                   s = string[0,ind].strip
                   arguments << s unless s == ""
                   string = string[ind+1..-1]
-                  ind = -1 
+                  ind = -1
                 end
               end
             end

Modified: MacRuby/trunk/lib/rexml/quickpath.rb
===================================================================
--- MacRuby/trunk/lib/rexml/quickpath.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/quickpath.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -68,7 +68,7 @@
         ns = $1
         rest = $'
         elements.delete_if do |element|
-          !(element.kind_of? Element and 
+          !(element.kind_of? Element and
             (element.expanded_name == name or
              (element.name == name and
               element.namespace == Functions.namespace_context[ns])))
@@ -135,16 +135,17 @@
         matches = filter(elements.collect{|element| element.next_sibling}.uniq,
           rest)
       when "previous-sibling"
-        matches = filter(elements.collect{|element| 
+        matches = filter(elements.collect{|element|
           element.previous_sibling}.uniq, rest )
       end
       return matches.uniq
     end
 
+    OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)'
     # A predicate filters a node-set with respect to an axis to produce a
-    # new node-set. For each node in the node-set to be filtered, the 
-    # PredicateExpr is evaluated with that node as the context node, with 
-    # the number of nodes in the node-set as the context size, and with the 
+    # new node-set. For each node in the node-set to be filtered, the
+    # PredicateExpr is evaluated with that node as the context node, with
+    # the number of nodes in the node-set as the context size, and with the
     # proximity position of the node in the node-set with respect to the
     # axis as the context position; if PredicateExpr evaluates to true for
     # that node, the node is included in the new node-set; otherwise, it is
@@ -157,7 +158,7 @@
     # number, then the result will be converted as if by a call to the
     # boolean function. Thus a location path para[3] is equivalent to
     # para[position()=3].
-    def QuickPath::predicate( elements, path ) 
+    def QuickPath::predicate( elements, path )
       ind = 1
       bcount = 1
       while bcount > 0
@@ -170,18 +171,20 @@
       rest = path[ind+1..-1]
 
       # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
-      predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u,
+      #
+      predicate.gsub!(
+        /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u,
         '\1 \2 \3 and \3 \4 \5' )
       # Let's do some Ruby trickery to avoid some work:
       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!( /\b(\w[-\w.]*\()/u ) {
         fname = $1
         fname.gsub( /-/u, "_" )
       }
-      
+
       Functions.pair = [ 0, elements.size ]
       results = []
       elements.each do |element|

Modified: MacRuby/trunk/lib/rexml/rexml.rb
===================================================================
--- MacRuby/trunk/lib/rexml/rexml.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/rexml.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -5,26 +5,26 @@
 # non-validating[http://www.w3.org/TR/2004/REC-xml-20040204/#sec-conformance]
 # toolkit with an intuitive API.  REXML passes 100% of the non-validating Oasis
 # tests[http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.shtml],
-# and provides tree, stream, SAX2, pull, and lightweight APIs.  REXML also 
-# includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since 
+# and provides tree, stream, SAX2, pull, and lightweight APIs.  REXML also
+# includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since
 # Ruby 1.8, REXML is included in the standard Ruby distribution.
 #
 # Main page:: http://www.germane-software.com/software/rexml
 # Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
 # Date:: 2008/019
 # Version:: 3.1.7.3
-# 
+#
 # This API documentation can be downloaded from the REXML home page, or can
 # be accessed online[http://www.germane-software.com/software/rexml_doc]
 #
 # A tutorial is available in the REXML distribution in docs/tutorial.html,
-# or can be accessed 
+# or can be accessed
 # online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
 module REXML
   COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser at germane-software.com>"
   DATE = "2008/019"
   VERSION = "3.1.7.3"
-  REVISION = "$Revision: 15141 $".gsub(/\$Revision:|\$/,'').strip
+  REVISION = %w$Revision: 26193 $[1] || ''
 
   Copyright = COPYRIGHT
   Version = VERSION

Modified: MacRuby/trunk/lib/rexml/sax2listener.rb
===================================================================
--- MacRuby/trunk/lib/rexml/sax2listener.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/sax2listener.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,11 +1,11 @@
 module REXML
   # A template for stream parser listeners.
   # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
-  # processed; REXML doesn't yet handle doctype entity declarations, so you 
+  # processed; REXML doesn't yet handle doctype entity declarations, so you
   # have to parse them out yourself.
   # === Missing methods from SAX2
   #  ignorable_whitespace
-  # === Methods extending SAX2 
+  # === Methods extending SAX2
   # +WARNING+
   # These methods are certainly going to change, until DTDs are fully
   # supported.  Be aware of this.
@@ -58,7 +58,7 @@
     # The argument passed to this method is an array of the entity
     # declaration.  It can be in a number of formats, but in general it
     # returns (example, result):
-    #  <!ENTITY % YN '"Yes"'>  
+    #  <!ENTITY % YN '"Yes"'>
     #  ["%", "YN", "'\"Yes\"'", "\""]
     #  <!ENTITY % YN 'Yes'>
     #  ["%", "YN", "'Yes'", "s"]
@@ -93,5 +93,5 @@
     end
     def progress position
     end
-  end	
+  end
 end

Modified: MacRuby/trunk/lib/rexml/source.rb
===================================================================
--- MacRuby/trunk/lib/rexml/source.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/source.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -69,9 +69,9 @@
     # usual scan() method.  For one thing, the pattern argument has some
     # requirements; for another, the source can be consumed.  You can easily
     # confuse this method.  Originally, the patterns were easier
-    # to construct and this method more robust, because this method 
-    # generated search regexes on the fly; however, this was 
-    # computationally expensive and slowed down the entire REXML package 
+    # to construct and this method more robust, because this method
+    # generated search regexes on the fly; however, this was
+    # computationally expensive and slowed down the entire REXML package
     # considerably, since this is by far the most commonly called method.
     # @param pattern must be a Regexp, and must be in the form of
     # /^\s*(#{your pattern, with no groups})(.*)/.  The first group
@@ -162,6 +162,15 @@
         @line_break = ">"
       end
       super( @source.eof? ? str : str+ at source.readline( @line_break ) )
+
+      if !@to_utf and
+          @buffer.respond_to?(:force_encoding) and
+          @source.respond_to?(:external_encoding) and
+          @source.external_encoding != ::Encoding::UTF_8
+        @force_utf8 = true
+      else
+        @force_utf8 = false
+      end
     end
 
     def scan(pattern, cons=false)
@@ -174,11 +183,7 @@
       if rv.size == 0
         until @buffer =~ pattern or @source.nil?
           begin
-            # READLINE OPT
-            #str = @source.read(@block_size)
-            str = @source.readline(@line_break)
-            str = decode(str) if @to_utf and str
-            @buffer << str
+            @buffer << readline
           rescue Iconv::IllegalSequence
             raise
           rescue
@@ -193,12 +198,7 @@
 
     def read
       begin
-        str = @source.readline(@line_break)
-        str = decode(str) if @to_utf and str 
-        @buffer << str
-        if not @to_utf and @buffer.respond_to? :force_encoding
-          @buffer.force_encoding Encoding::UTF_8
-        end
+        @buffer << readline
       rescue Exception, NameError
         @source = nil
       end
@@ -213,9 +213,7 @@
       @buffer = $' if cons and rv
       while !rv and @source
         begin
-          str = @source.readline(@line_break)
-          str = decode(str) if @to_utf and str
-          @buffer << str
+          @buffer << readline
           rv = pattern.match(@buffer)
           @buffer = $' if cons and rv
         rescue
@@ -225,7 +223,7 @@
       rv.taint
       rv
     end
-    
+
     def empty?
       super and ( @source.nil? || @source.eof? )
     end
@@ -254,5 +252,18 @@
       end
       [pos, lineno, line]
     end
+
+    private
+    def readline
+      str = @source.readline(@line_break)
+      return nil if str.nil?
+
+      if @to_utf
+        decode(str)
+      else
+        str.force_encoding(::Encoding::UTF_8) if @force_utf8
+        str
+      end
+    end
   end
 end

Modified: MacRuby/trunk/lib/rexml/streamlistener.rb
===================================================================
--- MacRuby/trunk/lib/rexml/streamlistener.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/streamlistener.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,14 +1,14 @@
 module REXML
   # A template for stream parser listeners.
   # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
-  # processed; REXML doesn't yet handle doctype entity declarations, so you 
+  # processed; REXML doesn't yet handle doctype entity declarations, so you
   # have to parse them out yourself.
   module StreamListener
     # Called when a tag is encountered.
     # @p name the tag name
     # @p attrs an array of arrays of attribute/value pairs, suitable for
     # use with assoc or rassoc.  IE, <tag attr1="value1" attr2="value2">
-    # will result in 
+    # will result in
     # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
     def tag_start name, attrs
     end
@@ -56,7 +56,7 @@
     # The argument passed to this method is an array of the entity
     # declaration.  It can be in a number of formats, but in general it
     # returns (example, result):
-    #  <!ENTITY % YN '"Yes"'>  
+    #  <!ENTITY % YN '"Yes"'>
     #  ["%", "YN", "'\"Yes\"'", "\""]
     #  <!ENTITY % YN 'Yes'>
     #  ["%", "YN", "'Yes'", "s"]

Modified: MacRuby/trunk/lib/rexml/text.rb
===================================================================
--- MacRuby/trunk/lib/rexml/text.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/text.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -19,7 +19,7 @@
     attr_accessor :raw
 
     NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
-    NUMERICENTITY = /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/ 
+    NUMERICENTITY = /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/
     VALID_CHAR = [
       0x9, 0xA, 0xD,
       (0x20..0xD7FF),
@@ -50,25 +50,25 @@
          |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
          | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
          |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
-       )*$/nx; 
+       )*$/nx;
     end
 
     # Constructor
     # +arg+ if a String, the content is set to the String.  If a Text,
-    # the object is shallowly cloned.  
+    # the object is shallowly cloned.
     #
     # +respect_whitespace+ (boolean, false) if true, whitespace is
     # respected
     #
     # +parent+ (nil) if this is a Parent object, the parent
-    # will be set to this.  
+    # will be set to this.
     #
     # +raw+ (nil) This argument can be given three values.
-    # If true, then the value of used to construct this object is expected to 
-    # contain no unescaped XML markup, and REXML will not change the text. If 
+    # If true, then the value of used to construct this object is expected to
+    # contain no unescaped XML markup, and REXML will not change the text. If
     # this value is false, the string may contain any characters, and REXML will
     # escape any and all defined entities whose values are contained in the
-    # text.  If this value is nil (the default), then the raw value of the 
+    # text.  If this value is nil (the default), then the raw value of the
     # parent will be used as the raw value for this node.  If there is no raw
     # value for the parent, and no value is supplied, the default is false.
     # Use this field if you have entities defined for some text, and you don't
@@ -88,17 +88,16 @@
     #   Text.new( "sean russell", false, nil, true, ["s"] ) #-> "sean russell"
     # In the last example, the +entity_filter+ argument is ignored.
     #
-    # +pattern+ INTERNAL USE ONLY
-    def initialize(arg, respect_whitespace=false, parent=nil, raw=nil, 
+    # +illegal+ INTERNAL USE ONLY
+    def initialize(arg, respect_whitespace=false, parent=nil, raw=nil,
       entity_filter=nil, illegal=NEEDS_A_SECOND_CHECK )
 
       @raw = false
+      @parent = nil
 
       if parent
         super( parent )
-        @raw = parent.raw 
-      else
-        @parent = nil
+        @raw = parent.raw
       end
 
       @raw = raw unless raw.nil?
@@ -117,7 +116,7 @@
 
       @string.gsub!( /\r\n?/, "\n" )
 
-      Text.check(@string, NEEDS_A_SECOND_CHECK, doctype) if @raw and @parent
+      Text.check(@string, illegal, doctype) if @raw
     end
 
     def parent= parent
@@ -160,10 +159,11 @@
             else
               raise "Illegal character '#{$1}' in raw string \"#{string}\""
             end
-          elsif $3 and !SUBSTITUTES.include?($1)
-            if !doctype or !doctype.entities.has_key?($3)
-              raise "Undeclared entity '#{$1}' in raw string \"#{string}\""
-            end
+          # FIXME: below can't work but this needs API change.
+          # elsif @parent and $3 and !SUBSTITUTES.include?($1)
+          #   if !doctype or !doctype.entities.has_key?($3)
+          #     raise "Undeclared entity '#{$1}' in raw string \"#{string}\""
+          #   end
           end
         end
       end
@@ -208,12 +208,12 @@
     # escaped, meaning that it is a valid XML text node string, and all
     # entities that can be escaped, have been inserted.  This method respects
     # the entity filter set in the constructor.
-    #   
-    #   # Assume that the entity "s" is defined to be "sean", and that the 
+    #
+    #   # Assume that the entity "s" is defined to be "sean", and that the
     #   # entity "r" is defined to be "russell"
-    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] ) 
+    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] )
     #   t.to_s   #-> "&lt; &amp; &s; russell"
-    #   t = Text.new( "< & &s; russell", false, nil, false ) 
+    #   t = Text.new( "< & &s; russell", false, nil, false )
     #   t.to_s   #-> "&lt; &amp; &s; russell"
     #   u = Text.new( "sean russell", false, nil, true )
     #   u.to_s   #-> "sean russell"
@@ -233,9 +233,9 @@
     # console.  This ignores the 'raw' attribute setting, and any
     # entity_filter.
     #
-    #   # Assume that the entity "s" is defined to be "sean", and that the 
+    #   # Assume that the entity "s" is defined to be "sean", and that the
     #   # entity "r" is defined to be "russell"
-    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] ) 
+    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] )
     #   t.value   #-> "< & sean russell"
     #   t = Text.new( "< & &s; russell", false, nil, false )
     #   t.value   #-> "< & sean russell"
@@ -246,7 +246,7 @@
       @unnormalized = Text::unnormalize( @string, doctype )
     end
 
-    # Sets the contents of this text node.  This expects the text to be 
+    # Sets the contents of this text node.  This expects the text to be
     # unnormalized.  It returns self.
     #
     #   e = Element.new( "a" )
@@ -259,7 +259,7 @@
       @normalized = nil
       @raw = false
     end
- 
+
      def wrap(string, width, addnewline=false)
        # Recursively wrap string at width.
        return string if string.length <= width
@@ -274,7 +274,7 @@
     def indent_text(string, level=1, style="\t", indentfirstline=true)
       return string if level < 0
       new_string = ''
-      string.each { |line|
+      string.each_line { |line|
         indent_string = style * level
         new_line = (indent_string + line).sub(/[\s]+$/,'')
         new_string << new_line
@@ -282,11 +282,11 @@
       new_string.strip! unless indentfirstline
       return new_string
     end
- 
+
     # == DEPRECATED
     # See REXML::Formatters
     #
-    def write( writer, indent=-1, transitive=false, ie_hack=false ) 
+    def write( writer, indent=-1, transitive=false, ie_hack=false )
       Kernel.warn("#{self.class.name}.write is deprecated.  See REXML::Formatters")
       formatter = if indent > -1
           REXML::Formatters::Pretty.new( indent )
@@ -337,7 +337,7 @@
       if copy =~ illegal
         raise ParseException.new( "malformed text: Illegal character #$& in \"#{copy}\"" )
       end if illegal
-      
+
       copy.gsub!( /\r\n?/, "\n" )
       if copy.include? ?&
         copy.gsub!( SETUTITSBUS[0], SLAICEPS[0] )
@@ -365,8 +365,8 @@
       if doctype
         # Replace all ampersands that aren't part of an entity
         doctype.entities.each_value do |entity|
-          copy = copy.gsub( entity.value, 
-            "&#{entity.name};" ) if entity.value and 
+          copy = copy.gsub( entity.value,
+            "&#{entity.name};" ) if entity.value and
               not( entity_filter and entity_filter.include?(entity) )
         end
       else

Modified: MacRuby/trunk/lib/rexml/validation/relaxng.rb
===================================================================
--- MacRuby/trunk/lib/rexml/validation/relaxng.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/validation/relaxng.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -79,7 +79,7 @@
             when "mixed"
               states << Interleave.new( self )
               states[-2] << states[-1]
-              states[-1] << TEXT 
+              states[-1] << TEXT
             when "define"
               states << [ event[2]["name"] ]
             when "ref"
@@ -102,7 +102,7 @@
             case event[1]
             when "element", "attribute"
               states[-1] << event
-            when "zeroOrMore", "oneOrMore", "choice", "optional", 
+            when "zeroOrMore", "oneOrMore", "choice", "optional",
               "interleave", "group", "mixed"
               states.pop
             when "define"
@@ -139,7 +139,7 @@
         @events.each {|s| s.reset if s.kind_of? State }
       end
 
-      def previous=( previous ) 
+      def previous=( previous )
         @previous << previous
       end
 
@@ -183,7 +183,7 @@
       end
 
       def inspect
-        "< #{to_s} #{@events.collect{|e| 
+        "< #{to_s} #{@events.collect{|e|
           pre = e == @events[@current] ? '#' : ''
           pre + e.inspect unless self == e
         }.join(', ')} >"
@@ -201,15 +201,15 @@
       protected
       def expand_ref_in( arry, ind )
         new_events = []
-        @references[ arry[ind].to_s ].each{ |evt| 
+        @references[ arry[ind].to_s ].each{ |evt|
           add_event_to_arry(new_events,evt)
         }
         arry[ind,1] = new_events
       end
 
-      def add_event_to_arry( arry, evt ) 
+      def add_event_to_arry( arry, evt )
         evt = generate_event( evt )
-        if evt.kind_of? String 
+        if evt.kind_of? String
           arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value
           @value = false
         else
@@ -272,7 +272,7 @@
       end
 
       def matches?(event)
-        @events[@current].matches?(event) || 
+        @events[@current].matches?(event) ||
         (@current == 0 and @previous[-1].matches?(event))
       end
 
@@ -319,7 +319,7 @@
       end
 
       def reset
-        super 
+        super
         @ord = 0
       end
 
@@ -345,7 +345,7 @@
       end
 
       def matches?( event )
-        @events[@current].matches?(event) || 
+        @events[@current].matches?(event) ||
         (@current == 0 and @ord > 0 and @previous[-1].matches?(event))
       end
 
@@ -412,7 +412,7 @@
         #puts "IN CHOICE EXPECTED"
         #puts "EVENTS = #{@events.inspect}"
         return [@events[@current]] if @events.size > 0
-        return @choices.collect do |x| 
+        return @choices.collect do |x|
           if x[0].kind_of? State
             x[0].expected
           else
@@ -426,12 +426,12 @@
       end
 
       protected
-      def add_event_to_arry( arry, evt ) 
+      def add_event_to_arry( arry, evt )
         if evt.kind_of? State or evt.class == Ref
           arry << [evt]
-        elsif evt[0] == :text 
+        elsif evt[0] == :text
          if arry[-1] and
-            arry[-1][-1].kind_of?( Event ) and 
+            arry[-1][-1].kind_of?( Event ) and
             arry[-1][-1].event_type == :text and @value
 
             arry[-1][-1].event_arg = evt[1]
@@ -478,7 +478,7 @@
           @choices[idx] = old
           @choice += 1
         end
-        
+
        #puts "In next with #{event.inspect}."
        #puts "events is #{@events.inspect}"
         @events = [] unless @events
@@ -490,7 +490,7 @@
         next_current(event) unless @events[@current]
         return nil unless @events[@current]
 
-        expand_ref_in( @events, @current ) if @events[@current].class == Ref 
+        expand_ref_in( @events, @current ) if @events[@current].class == Ref
        #puts "In next with #{event.inspect}."
        #puts "Next (#@current) is #{@events[@current]}"
         if ( @events[@current].kind_of? State )
@@ -530,7 +530,7 @@
         #puts "IN CHOICE EXPECTED"
         #puts "EVENTS = #{@events.inspect}"
         return [@events[@current]] if @events[@current]
-        return @choices[@choice..-1].collect do |x| 
+        return @choices[@choice..-1].collect do |x|
           if x[0].kind_of? State
             x[0].expected
           else

Modified: MacRuby/trunk/lib/rexml/validation/validation.rb
===================================================================
--- MacRuby/trunk/lib/rexml/validation/validation.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/validation/validation.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -14,7 +14,7 @@
       def dump
         puts @root.inspect
       end
-      def validate( event ) 
+      def validate( event )
         #puts "Current: #@current"
         #puts "Event: #{event.inspect}"
         @attr_stack = [] unless defined? @attr_stack
@@ -33,12 +33,12 @@
             sattr = [:start_attribute, nil]
             eattr = [:end_attribute]
             text = [:text, nil]
-            k,v = event[2].find { |key,value| 
+            k,v = event[2].find { |key,value|
               sattr[1] = key
               #puts "Looking for #{sattr.inspect}"
               m = @current.next( sattr )
               #puts "Got #{m.inspect}"
-              if m 
+              if m
                 # If the state has text children...
                 #puts "Looking for #{eattr.inspect}"
                 #puts "Expect #{m.expected}"

Modified: MacRuby/trunk/lib/rexml/xmltokens.rb
===================================================================
--- MacRuby/trunk/lib/rexml/xmltokens.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/xmltokens.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -2,10 +2,10 @@
   # Defines a number of tokens used for parsing XML.  Not for general
   # consumption.
   module XMLTokens
-    NCNAME_STR= '[\w:][\-\w\d.]*'
+    NCNAME_STR= '[\w:][\-\w.]*'
     NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
 
-    NAMECHAR = '[\-\w\d\.:]'
+    NAMECHAR = '[\-\w\.:]'
     NAME = "([\\w:]#{NAMECHAR}*)"
     NMTOKEN = "(?:#{NAMECHAR})+"
     NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"

Modified: MacRuby/trunk/lib/rexml/xpath.rb
===================================================================
--- MacRuby/trunk/lib/rexml/xpath.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/xpath.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -64,7 +64,7 @@
       parser.parse(path, element).each( &block )
     end
 
-    # Returns an array of nodes matching a given XPath.  
+    # Returns an array of nodes matching a given XPath.
     def XPath::match element, path=nil, namespaces=nil, variables={}
       parser = XPathParser.new
       parser.namespaces = namespaces

Modified: MacRuby/trunk/lib/rexml/xpath_parser.rb
===================================================================
--- MacRuby/trunk/lib/rexml/xpath_parser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rexml/xpath_parser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -88,7 +88,7 @@
 
       case path[0]
       when :document
-        # do nothing 
+        # do nothing
         return first( path[1..-1], node )
       when :child
         for c in node.children
@@ -123,7 +123,7 @@
     end
 
 
-    def match( path_stack, nodeset ) 
+    def match( path_stack, nodeset )
       #puts "MATCH: path_stack = #{path_stack.inspect}"
       #puts "MATCH: nodeset = #{nodeset.inspect}"
       r = expr( path_stack, nodeset )
@@ -136,7 +136,7 @@
 
     # Returns a String namespace for a node, given a prefix
     # The rules are:
-    # 
+    #
     #  1. Use the supplied namespace mapping first.
     #  2. If no mapping was supplied, use the context node to look up the namespace
     def get_namespace( node, prefix )
@@ -187,8 +187,8 @@
                 #puts "node.namespace == #{ns.inspect} => #{node.namespace == ns}"
               end
             end
-            !(node.node_type == :element and 
-              node.name == name and 
+            !(node.node_type == :element and
+              node.name == name and
               node.namespace == ns )
           end
           node_types = ELEMENTS
@@ -205,7 +205,7 @@
         when :processing_instruction
           target = path_stack.shift
           nodeset.delete_if do |node|
-            (node.node_type != :processing_instruction) or 
+            (node.node_type != :processing_instruction) or
             ( target!='' and ( node.target != target ) )
           end
 
@@ -231,7 +231,7 @@
 
         when :literal
           return path_stack.shift
-        
+
         when :attribute
           new_nodeset = []
           case path_stack.shift
@@ -481,23 +481,23 @@
         when :function
           func_name = path_stack.shift.tr('-','_')
           arguments = path_stack.shift
-          #puts "FUNCTION 0: #{func_name}(#{arguments.collect{|a|a.inspect}.join(', ')})" 
+          #puts "FUNCTION 0: #{func_name}(#{arguments.collect{|a|a.inspect}.join(', ')})"
           subcontext = context ? nil : { :size => nodeset.size }
 
           res = []
           cont = context
-          nodeset.each_with_index { |n, i| 
+          nodeset.each_with_index { |n, i|
             if subcontext
               subcontext[:node]  = n
               subcontext[:index] = i
               cont = subcontext
             end
             arg_clone = arguments.dclone
-            args = arg_clone.collect { |arg| 
+            args = arg_clone.collect { |arg|
               #puts "FUNCTION 1: Calling expr( #{arg.inspect}, [#{n.inspect}] )"
-              expr( arg, [n], cont ) 
+              expr( arg, [n], cont )
             }
-            #puts "FUNCTION 2: #{func_name}(#{args.collect{|a|a.inspect}.join(', ')})" 
+            #puts "FUNCTION 2: #{func_name}(#{args.collect{|a|a.inspect}.join(', ')})"
             Functions.context = cont
             res << Functions.send( func_name, *args )
             #puts "FUNCTION 3: #{res[-1].inspect}"
@@ -515,10 +515,10 @@
     # FIXME
     # The next two methods are BAD MOJO!
     # This is my achilles heel.  If anybody thinks of a better
-    # way of doing this, be my guest.  This really sucks, but 
+    # way of doing this, be my guest.  This really sucks, but
     # it is a wonder it works at all.
     # ########################################################
-    
+
     def descendant_or_self( path_stack, nodeset )
       rs = []
       #puts "#"*80
@@ -547,7 +547,7 @@
     # Reorders an array of nodes so that they are in document order
     # It tries to do this efficiently.
     #
-    # FIXME: I need to get rid of this, but the issue is that most of the XPath 
+    # FIXME: I need to get rid of this, but the issue is that most of the XPath
     # interpreter functions as a filter, which means that we lose context going
     # in and out of function calls.  If I knew what the index of the nodes was,
     # I wouldn't have to do this.  Maybe add a document IDX for each node?
@@ -555,7 +555,7 @@
     def document_order( array_of_nodes )
       new_arry = []
       array_of_nodes.each { |node|
-        node_idx = [] 
+        node_idx = []
         np = node.node_type == :attribute ? node.element : node
         while np.parent and np.parent.node_type == :element
           node_idx << np.parent.index( np )
@@ -579,7 +579,7 @@
 
     # Builds a nodeset of all of the preceding nodes of the supplied node,
     # in reverse document order
-    # preceding:: includes every element in the document that precedes this node, 
+    # preceding:: includes every element in the document that precedes this node,
     # except for ancestors
     def preceding( node )
       #puts "IN PRECEDING"
@@ -609,9 +609,9 @@
      #puts "NODE: #{node.inspect}"
      #puts "PREVIOUS NODE: #{node.previous_sibling_node.inspect}"
      #puts "PARENT NODE: #{node.parent}"
-      psn = node.previous_sibling_node 
+      psn = node.previous_sibling_node
       if psn.nil?
-        if node.parent.nil? or node.parent.class == Document 
+        if node.parent.nil? or node.parent.class == Document
           return nil
         end
         return node.parent
@@ -647,9 +647,9 @@
     end
 
     def next_sibling_node(node)
-      psn = node.next_sibling_node 
+      psn = node.next_sibling_node
       while psn.nil?
-        if node.parent.nil? or node.parent.class == Document 
+        if node.parent.nil? or node.parent.class == Document
           return nil
         end
         node = node.parent

Modified: MacRuby/trunk/lib/rinda/rinda.rb
===================================================================
--- MacRuby/trunk/lib/rinda/rinda.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rinda/rinda.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -58,7 +58,7 @@
 
     ##
     # The number of elements in the tuple.
-    
+
     def size
       @tuple.size
     end
@@ -162,7 +162,7 @@
       end
       return true
     end
-    
+
     ##
     # Alias for #match.
 
@@ -171,7 +171,7 @@
     end
 
   end
-  
+
   ##
   # <i>Documentation?</i>
 
@@ -184,7 +184,7 @@
       @drb_uri = uri
       @drb_ref = ref
     end
-    
+
     ##
     # This DRbObjectTemplate matches +ro+ if the remote object's drburi and
     # drbref are the same.  +nil+ is used as a wildcard.
@@ -213,14 +213,14 @@
     def initialize(ts)
       @ts = ts
     end
-    
+
     ##
     # Adds +tuple+ to the proxied TupleSpace.  See TupleSpace#write.
 
     def write(tuple, sec=nil)
       @ts.write(tuple, sec)
     end
-    
+
     ##
     # Takes +tuple+ from the proxied TupleSpace.  See TupleSpace#take.
 
@@ -229,14 +229,14 @@
       @ts.move(DRbObject.new(port), tuple, sec, &block)
       port[0]
     end
-    
+
     ##
     # Reads +tuple+ from the proxied TupleSpace.  See TupleSpace#read.
 
     def read(tuple, sec=nil, &block)
       @ts.read(tuple, sec, &block)
     end
-    
+
     ##
     # Reads all tuples matching +tuple+ from the proxied TupleSpace.  See
     # TupleSpace#read_all.
@@ -244,7 +244,7 @@
     def read_all(tuple)
       @ts.read_all(tuple)
     end
-    
+
     ##
     # Registers for notifications of event +ev+ on the proxied TupleSpace.
     # See TupleSpace#notify

Modified: MacRuby/trunk/lib/rinda/ring.rb
===================================================================
--- MacRuby/trunk/lib/rinda/ring.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rinda/ring.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -49,7 +49,7 @@
 	end
       end
     end
-  
+
     ##
     # Extracts the response URI from +msg+ and adds it to TupleSpace where it
     # will be picked up by +reply_service+ for notification.
@@ -74,7 +74,7 @@
 	end
       end
     end
-    
+
     ##
     # Pulls lookup tuples out of the TupleSpace and sends their DRb object the
     # address of the local TupleSpace.
@@ -104,7 +104,7 @@
     # created RingFinger.
 
     def self.finger
-      unless @@finger 
+      unless @@finger
 	@@finger = self.new
 	@@finger.lookup_ring_any
       end
@@ -207,7 +207,7 @@
 	  @rings.push(it)
 	end
       end
-      
+
       @primary = queue.pop
       raise('RingNotFound') if @primary.nil?
       @primary

Modified: MacRuby/trunk/lib/rinda/tuplespace.rb
===================================================================
--- MacRuby/trunk/lib/rinda/tuplespace.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rinda/tuplespace.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -73,14 +73,14 @@
     end
 
     ##
-    # Reset the expiry time according to +sec_or_renewer+.  
+    # Reset the expiry time according to +sec_or_renewer+.
     #
     # +nil+::    it is set to expire in the far future.
     # +false+::  it has expired.
     # Numeric::  it will expire in that many seconds.
     #
     # Otherwise the argument refers to some kind of renewer object
-    # which will reset its expiry time. 
+    # which will reset its expiry time.
 
     def renew(sec_or_renewer)
       sec, @renewer = get_renewer(sec_or_renewer)
@@ -168,7 +168,7 @@
     def match(tuple)
       @tuple.match(tuple)
     end
-    
+
     alias === match
 
     def make_tuple(ary) # :nodoc:
@@ -224,11 +224,11 @@
   #
   #   ts = Rinda::TupleSpace.new
   #   observer = ts.notify 'write', [nil]
-  #   
+  #
   #   Thread.start do
   #     observer.each { |t| p t }
   #   end
-  #   
+  #
   #   3.times { |i| ts.write [i] }
   #
   # Outputs:
@@ -276,7 +276,7 @@
         it = pop
         yield(it)
       end
-    rescue 
+    rescue
     ensure
       cancel
     end
@@ -295,16 +295,16 @@
       def initialize
         @bin = []
       end
-      
+
       def add(tuple)
         @bin.push(tuple)
       end
-      
+
       def delete(tuple)
         idx = @bin.rindex(tuple)
         @bin.delete_at(idx) if idx
       end
-      
+
       def find(&blk)
         @bin.reverse_each do |x|
           return x if yield(x)

Modified: MacRuby/trunk/lib/rss/0.9.rb
===================================================================
--- MacRuby/trunk/lib/rss/0.9.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/0.9.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,7 +8,7 @@
 
     def self.append_features(klass)
       super
-      
+
       klass.install_must_call_validator('', "")
     end
   end
@@ -123,7 +123,7 @@
       def not_need_to_call_setup_maker_variables
         %w(image textInput)
       end
-    
+
       class SkipDays < Element
         include RSS09
 
@@ -146,11 +146,11 @@
               self.content = args[0]
             end
           end
-      
+
         end
-        
+
       end
-      
+
       class SkipHours < Element
         include RSS09
 
@@ -174,13 +174,13 @@
             end
           end
         end
-        
+
       end
-      
+
       class Image < Element
 
         include RSS09
-        
+
         %w(url title link).each do |name|
           install_text_element(name, "", nil)
         end
@@ -239,9 +239,9 @@
           end
         end
       end
-      
+
       class Item < Element
-        
+
         include RSS09
 
         [
@@ -269,7 +269,7 @@
           @enclosure.setup_maker(item) if @enclosure
           @source.setup_maker(item) if @source
         end
-        
+
         class Source < Element
 
           include RSS09
@@ -279,7 +279,7 @@
           ].each do |name, uri, required|
             install_get_attribute(name, uri, required)
           end
-          
+
           content_setup
 
           def initialize(*args)
@@ -341,7 +341,7 @@
         class Category < Element
 
           include RSS09
-          
+
           [
             ["domain", "", false]
           ].each do |name, uri, required|
@@ -369,11 +369,11 @@
             category.domain = domain
             category.content = content
           end
-          
+
         end
 
       end
-      
+
       class TextInput < Element
 
         include RSS09
@@ -399,9 +399,9 @@
           maker.textinput
         end
       end
-      
+
     end
-    
+
   end
 
   RSS09::ELEMENTS.each do |name|
@@ -411,8 +411,8 @@
   module ListenerMixin
     private
     def initial_start_rss(tag_name, prefix, attrs, ns)
-      check_ns(tag_name, prefix, ns, "")
-      
+      check_ns(tag_name, prefix, ns, "", false)
+
       @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
       @rss.do_validate = @do_validate
       @rss.xml_stylesheets = @xml_stylesheets
@@ -422,7 +422,7 @@
       end
       @proc_stack.push(pr)
     end
-    
+
   end
 
 end

Modified: MacRuby/trunk/lib/rss/1.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/1.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/1.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,7 +8,7 @@
 
     def self.append_features(klass)
       super
-      
+
       klass.install_must_call_validator('', ::RSS::URI)
     end
 
@@ -64,13 +64,13 @@
           URI
         end
       end
-      
+
       [
         ["resource", [URI, ""], true]
       ].each do |name, uri, required|
         install_get_attribute(name, uri, required)
       end
-      
+
       def initialize(*args)
         if Utils.element_initialize_arguments?(args)
           super
@@ -98,10 +98,10 @@
       end
 
       @tag_name = 'Seq'
-      
+
       install_have_children_element("li", URI, "*")
       install_must_call_validator('rdf', ::RSS::RDF::URI)
-      
+
       def initialize(*args)
         if Utils.element_initialize_arguments?(args)
           super
@@ -114,7 +114,7 @@
       def full_name
         tag_name_with_prefix(PREFIX)
       end
-      
+
       def setup_maker(target)
         lis.each do |li|
           target << li.resource
@@ -135,10 +135,10 @@
       end
 
       @tag_name = 'Bag'
-      
+
       install_have_children_element("li", URI, "*")
       install_must_call_validator('rdf', URI)
-      
+
       def initialize(*args)
         if Utils.element_initialize_arguments?(args)
           super
@@ -151,7 +151,7 @@
       def full_name
         tag_name_with_prefix(PREFIX)
       end
-      
+
       def setup_maker(target)
         lis.each do |li|
           target << li.resource
@@ -162,7 +162,7 @@
     class Channel < Element
 
       include RSS10
-      
+
       class << self
 
         def required_uri
@@ -202,17 +202,17 @@
       def maker_target(maker)
         maker.channel
       end
-      
+
       def setup_maker_attributes(channel)
         channel.about = about
       end
 
       class Image < Element
-        
+
         include RSS10
 
         class << self
-          
+
           def required_uri
             ::RSS::URI
           end
@@ -225,7 +225,7 @@
           install_get_attribute(name, uri, required, nil, nil,
                                 "#{PREFIX}:#{name}")
         end
-      
+
         def initialize(*args)
           if Utils.element_initialize_arguments?(args)
             super
@@ -237,11 +237,11 @@
       end
 
       class Textinput < Element
-        
+
         include RSS10
 
         class << self
-          
+
           def required_uri
             ::RSS::URI
           end
@@ -254,7 +254,7 @@
           install_get_attribute(name, uri, required, nil, nil,
                                 "#{PREFIX}:#{name}")
         end
-      
+
         def initialize(*args)
           if Utils.element_initialize_arguments?(args)
             super
@@ -264,7 +264,7 @@
           end
         end
       end
-      
+
       class Items < Element
 
         include RSS10
@@ -272,16 +272,16 @@
         Seq = ::RSS::RDF::Seq
 
         class << self
-          
+
           def required_uri
             ::RSS::URI
           end
-          
+
         end
 
         install_have_child_element("Seq", URI, nil)
         install_must_call_validator('rdf', URI)
-        
+
         def initialize(*args)
           if Utils.element_initialize_arguments?(args)
             super
@@ -309,7 +309,7 @@
       include RSS10
 
       class << self
-        
+
         def required_uri
           ::RSS::URI
         end
@@ -351,7 +351,7 @@
         def required_uri
           ::RSS::URI
         end
-        
+
       end
 
 
@@ -436,7 +436,7 @@
   module ListenerMixin
     private
     def initial_start_RDF(tag_name, prefix, attrs, ns)
-      check_ns(tag_name, prefix, ns, RDF::URI)
+      check_ns(tag_name, prefix, ns, RDF::URI, false)
 
       @rss = RDF.new(@version, @encoding, @standalone)
       @rss.do_validate = @do_validate

Modified: MacRuby/trunk/lib/rss/2.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/2.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/2.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -29,7 +29,7 @@
       Category = Item::Category
 
       class Item
-      
+
         [
           ["comments", "?"],
           ["author", "?"],
@@ -57,9 +57,9 @@
           _setup_maker_element(item)
           @guid.setup_maker(item) if @guid
         end
-        
+
         class Guid < Element
-          
+
           include RSS09
 
           [

Modified: MacRuby/trunk/lib/rss/atom.rb
===================================================================
--- MacRuby/trunk/lib/rss/atom.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/atom.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -716,7 +716,7 @@
   module ListenerMixin
     private
     def initial_start_feed(tag_name, prefix, attrs, ns)
-      check_ns(tag_name, prefix, ns, Atom::URI)
+      check_ns(tag_name, prefix, ns, Atom::URI, false)
 
       @rss = Atom::Feed.new(@version, @encoding, @standalone)
       @rss.do_validate = @do_validate
@@ -731,7 +731,7 @@
     end
 
     def initial_start_entry(tag_name, prefix, attrs, ns)
-      check_ns(tag_name, prefix, ns, Atom::URI)
+      check_ns(tag_name, prefix, ns, Atom::URI, false)
 
       @rss = Atom::Entry.new(@version, @encoding, @standalone)
       @rss.do_validate = @do_validate

Modified: MacRuby/trunk/lib/rss/content/1.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/content/1.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/content/1.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,4 @@
 require 'rss/1.0'
-require 'rss/content'
 
 module RSS
   RDF.install_ns(CONTENT_PREFIX, CONTENT_URI)

Modified: MacRuby/trunk/lib/rss/content/2.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/content/2.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/content/2.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,4 @@
 require "rss/2.0"
-require "rss/content"
 
 module RSS
   Rss.install_ns(CONTENT_PREFIX, CONTENT_URI)

Modified: MacRuby/trunk/lib/rss/converter.rb
===================================================================
--- MacRuby/trunk/lib/rss/converter.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/converter.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 module RSS
 
   class Converter
-    
+
     include Utils
 
     def initialize(to_enc, from_enc=nil)
@@ -63,11 +63,11 @@
         raise UnknownConversionMethodError.new(to_enc, from_enc)
       end
     end
-    
+
     def def_else_enc(to_enc, from_enc)
       def_iconv_convert(to_enc, from_enc, 0)
     end
-    
+
     def def_same_enc()
       def_convert do |value|
         value
@@ -101,40 +101,40 @@
     def def_to_euc_jp_from_utf_8
       def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We')
     end
-    
+
     def def_to_utf_8_from_euc_jp
       def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew')
     end
-    
+
     def def_to_shift_jis_from_utf_8
       def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws')
     end
-    
+
     def def_to_utf_8_from_shift_jis
       def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw')
     end
-    
+
     def def_to_euc_jp_from_shift_jis
       require "nkf"
       def_convert do |value|
         "NKF.nkf('-Se', #{value})"
       end
     end
-    
+
     def def_to_shift_jis_from_euc_jp
       require "nkf"
       def_convert do |value|
         "NKF.nkf('-Es', #{value})"
       end
     end
-    
+
     def def_to_euc_jp_from_iso_2022_jp
       require "nkf"
       def_convert do |value|
         "NKF.nkf('-Je', #{value})"
       end
     end
-    
+
     def def_to_iso_2022_jp_from_euc_jp
       require "nkf"
       def_convert do |value|
@@ -147,7 +147,7 @@
         "#{value}.unpack('C*').pack('U*')"
       end
     end
-    
+
     def def_to_iso_8859_1_from_utf_8
       def_convert do |value|
         <<-EOC
@@ -164,7 +164,7 @@
         EOC
       end
     end
-    
+
   end
-  
+
 end

Modified: MacRuby/trunk/lib/rss/dublincore/1.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/dublincore/1.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/dublincore/1.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,4 @@
 require "rss/1.0"
-require "rss/dublincore"
 
 module RSS
   RDF.install_ns(DC_PREFIX, DC_URI)

Modified: MacRuby/trunk/lib/rss/dublincore/2.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/dublincore/2.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/dublincore/2.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,4 @@
 require "rss/2.0"
-require "rss/dublincore"
 
 module RSS
   Rss.install_ns(DC_PREFIX, DC_URI)

Modified: MacRuby/trunk/lib/rss/dublincore/atom.rb
===================================================================
--- MacRuby/trunk/lib/rss/dublincore/atom.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/dublincore/atom.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,4 @@
 require "rss/atom"
-require "rss/dublincore"
 
 module RSS
   module Atom

Modified: MacRuby/trunk/lib/rss/dublincore.rb
===================================================================
--- MacRuby/trunk/lib/rss/dublincore.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/dublincore.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -25,7 +25,7 @@
           def #{full_name}
             @#{full_name}.first and @#{full_name}.first.value
           end
-          
+
           def #{full_name}=(new_value)
             @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value)
           end
@@ -50,7 +50,7 @@
       EOC
     end
   end
-  
+
   module DublinCoreModel
 
     extend BaseModel
@@ -76,26 +76,26 @@
     DATE_ELEMENTS = {
       "date" => "w3cdtf",
     }
-    
+
     ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a
     DublinCoreModel::DATE_ELEMENTS.each do |name, |
       ELEMENT_NAME_INFOS << [name, nil]
     end
-    
+
     ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys
 
     ELEMENTS.each do |name, plural_name|
       module_eval(<<-EOC, *get_file_and_line_from_caller(0))
         class DublinCore#{Utils.to_class_name(name)} < Element
           include RSS10
-          
+
           content_setup
 
           class << self
             def required_prefix
               DC_PREFIX
             end
-        
+
             def required_uri
               DC_URI
             end
@@ -105,7 +105,7 @@
 
           alias_method(:value, :content)
           alias_method(:value=, :content=)
-          
+
           def initialize(*args)
             if Utils.element_initialize_arguments?(args)
               super
@@ -114,7 +114,7 @@
               self.content = args[0]
             end
           end
-      
+
           def full_name
             tag_name_with_prefix(DC_PREFIX)
           end

Modified: MacRuby/trunk/lib/rss/image.rb
===================================================================
--- MacRuby/trunk/lib/rss/image.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/image.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -15,7 +15,7 @@
     BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}")
     IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}"
   end
-  
+
   module ImageModelUtils
     def validate_one_tag_name(ignore_unknown_element, name, tags)
       if !ignore_unknown_element
@@ -25,7 +25,7 @@
       raise TooMuchTagError.new(name, tag_name) if tags.size > 1
     end
   end
-  
+
   module ImageItemModel
     include ImageModelUtils
     extend BaseModel
@@ -43,12 +43,12 @@
       include DublinCoreModel
 
       @tag_name = "item"
-      
+
       class << self
         def required_prefix
           IMAGE_PREFIX
         end
-        
+
         def required_uri
           IMAGE_URI
         end
@@ -102,11 +102,11 @@
       end
     end
   end
-  
+
   module ImageFaviconModel
     include ImageModelUtils
     extend BaseModel
-    
+
     def self.append_features(klass)
       super
 
@@ -122,12 +122,12 @@
       include DublinCoreModel
 
       @tag_name = "favicon"
-      
+
       class << self
         def required_prefix
           IMAGE_PREFIX
         end
-        
+
         def required_uri
           IMAGE_URI
         end
@@ -154,7 +154,7 @@
         end
         set_size(new_value)
       end
-      
+
       alias image_size= size=
       alias image_size size
 

Modified: MacRuby/trunk/lib/rss/maker/0.9.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/0.9.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/0.9.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -4,14 +4,14 @@
 
 module RSS
   module Maker
-    
+
     class RSS09 < RSSBase
-      
-      def initialize(feed_version="0.92")
+
+      def initialize(feed_version)
         super
         @feed_type = "rss"
       end
-      
+
       private
       def make_feed
         Rss.new(@feed_version, @version, @encoding, @standalone)
@@ -38,20 +38,20 @@
             raise NotSetError.new("maker.channel", _not_set_required_variables)
           end
         end
-        
+
         private
         def setup_items(rss)
           @maker.items.to_feed(rss)
         end
-        
+
         def setup_image(rss)
           @maker.image.to_feed(rss)
         end
-        
+
         def setup_textinput(rss)
           @maker.textinput.to_feed(rss)
         end
-        
+
         def variables
           super + ["pubDate"]
         end
@@ -78,7 +78,7 @@
               end
             end
           end
-          
+
           class Day < DayBase
             def to_feed(rss, days)
               day = Rss::Channel::SkipDays::Day.new
@@ -96,7 +96,7 @@
             end
           end
         end
-        
+
         class SkipHours < SkipHoursBase
           def to_feed(rss, channel)
             unless @hours.empty?
@@ -108,7 +108,7 @@
               end
             end
           end
-          
+
           class Hour < HourBase
             def to_feed(rss, hours)
               hour = Rss::Channel::SkipHours::Hour.new
@@ -126,7 +126,7 @@
             end
           end
         end
-        
+
         class Cloud < CloudBase
           def to_feed(*args)
           end
@@ -243,7 +243,7 @@
           true
         end
       end
-      
+
       class Items < ItemsBase
         def to_feed(rss)
           if rss.channel
@@ -253,7 +253,7 @@
             setup_other_elements(rss, rss.items)
           end
         end
-        
+
         class Item < ItemBase
           def to_feed(rss)
             item = Rss::Channel::Item.new
@@ -439,7 +439,7 @@
           end
         end
       end
-      
+
       class Textinput < TextinputBase
         def to_feed(rss)
           textInput = Rss::Channel::TextInput.new
@@ -457,11 +457,52 @@
         end
       end
     end
-    
-    add_maker("0.9", "0.92", RSS09)
-    add_maker("0.91", "0.91", RSS09)
-    add_maker("0.92", "0.92", RSS09)
-    add_maker("rss0.91", "0.91", RSS09)
-    add_maker("rss0.92", "0.92", RSS09)
+
+    class RSS091 < RSS09
+      def initialize(feed_version="0.91")
+        super
+      end
+
+      class Channel < RSS09::Channel
+      end
+
+      class Items < RSS09::Items
+        class Item < RSS09::Items::Item
+        end
+      end
+
+      class Image < RSS09::Image
+      end
+
+      class Textinput < RSS09::Textinput
+      end
+    end
+
+    class RSS092 < RSS09
+      def initialize(feed_version="0.92")
+        super
+      end
+
+      class Channel < RSS09::Channel
+      end
+
+      class Items < RSS09::Items
+        class Item < RSS09::Items::Item
+        end
+      end
+
+      class Image < RSS09::Image
+      end
+
+      class Textinput < RSS09::Textinput
+      end
+    end
+
+    add_maker("0.9", "0.92", RSS092)
+    add_maker("0.91", "0.91", RSS091)
+    add_maker("0.92", "0.92", RSS092)
+    add_maker("rss0.9", "0.92", RSS092)
+    add_maker("rss0.91", "0.91", RSS091)
+    add_maker("rss0.92", "0.92", RSS092)
   end
 end

Modified: MacRuby/trunk/lib/rss/maker/1.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/1.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/1.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -25,6 +25,7 @@
       end
 
       class Channel < ChannelBase
+        include SetupDefaultLanguage
 
         def to_feed(rss)
           set_default_values do
@@ -60,7 +61,7 @@
           rss.channel.items = items
           set_parent(rss.channel, items)
         end
-        
+
         def setup_image(rss)
           if @maker.image.have_required_values?
             image = RDF::Channel::Image.new(@maker.image.url)
@@ -91,11 +92,11 @@
         class SkipDays < SkipDaysBase
           def to_feed(*args)
           end
-          
+
           class Day < DayBase
           end
         end
-        
+
         class SkipHours < SkipHoursBase
           def to_feed(*args)
           end
@@ -103,7 +104,7 @@
           class Hour < HourBase
           end
         end
-        
+
         class Cloud < CloudBase
           def to_feed(*args)
           end
@@ -403,7 +404,7 @@
           end
         end
       end
-      
+
       class Textinput < TextinputBase
         def to_feed(rss)
           if @link

Modified: MacRuby/trunk/lib/rss/maker/2.0.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/2.0.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/2.0.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -4,9 +4,9 @@
 
 module RSS
   module Maker
-    
+
     class RSS20 < RSS09
-      
+
       def initialize(feed_version="2.0")
         super
       end
@@ -17,17 +17,17 @@
         def required_variable_names
           %w(link)
         end
-        
+
         class SkipDays < RSS09::Channel::SkipDays
           class Day < RSS09::Channel::SkipDays::Day
           end
         end
-        
+
         class SkipHours < RSS09::Channel::SkipHours
           class Hour < RSS09::Channel::SkipHours::Hour
           end
         end
-        
+
         class Cloud < RSS09::Channel::Cloud
           def to_feed(rss, channel)
             cloud = Rss::Channel::Cloud.new
@@ -51,7 +51,7 @@
               category.to_feed(rss, channel)
             end
           end
-          
+
           class Category < RSS09::Channel::Categories::Category
             def to_feed(rss, channel)
               category = Rss::Channel::Category.new
@@ -81,14 +81,14 @@
           end
         end
       end
-      
+
       class Image < RSS09::Image
         private
         def required_element?
           false
         end
       end
-      
+
       class Items < RSS09::Items
         class Item < RSS09::Items::Item
           private
@@ -179,7 +179,7 @@
                 category.to_feed(rss, item)
               end
             end
-          
+
             class Category < RSS09::Items::Item::Categories::Category
               def to_feed(rss, item)
                 category = Rss::Channel::Item::Category.new
@@ -212,11 +212,11 @@
           end
         end
       end
-      
+
       class Textinput < RSS09::Textinput
       end
     end
-    
+
     add_maker("2.0", "2.0", RSS20)
     add_maker("rss2.0", "2.0", RSS20)
   end

Modified: MacRuby/trunk/lib/rss/maker/base.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/base.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/base.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -238,7 +238,7 @@
             setter = "#{var}="
             if target.respond_to?(setter)
               value = __send__(var)
-              if value
+              unless value.nil?
                 target.__send__(setter, value)
                 set = true
               end
@@ -358,7 +358,7 @@
           :date => date,
           :dc_dates => dc_dates.to_a.dup,
         }
-        _date = date
+        _date = _parse_date_if_needed(date)
         if _date and !dc_dates.any? {|dc_date| dc_date.value == _date}
           dc_date = self.class::DublinCoreDates::DublinCoreDate.new(self)
           dc_date.value = _date.dup
@@ -370,12 +370,36 @@
         date = keep[:date]
         dc_dates.replace(keep[:dc_dates])
       end
+
+      def _parse_date_if_needed(date_value)
+        date_value = Time.parse(date_value) if date_value.is_a?(String)
+        date_value
+      end
     end
 
+    module SetupDefaultLanguage
+      private
+      def _set_default_values(&block)
+        keep = {
+          :dc_languages => dc_languages.to_a.dup,
+        }
+        _language = language
+        if _language and
+            !dc_languages.any? {|dc_language| dc_language.value == _language}
+          dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self)
+          dc_language.value = _language.dup
+          dc_languages.unshift(dc_language)
+        end
+        super(&block)
+      ensure
+        dc_languages.replace(keep[:dc_languages])
+      end
+    end
+
     class RSSBase < Base
       class << self
-        def make(version, &block)
-          new(version).make(&block)
+        def make(*args, &block)
+          new(*args).make(&block)
         end
       end
 
@@ -384,7 +408,7 @@
         add_need_initialize_variable(element) do |object|
           object.send("make_#{element}")
         end
-        module_eval(<<-EOC, __FILE__, __LINE__)
+        module_eval(<<-EOC, __FILE__, __LINE__ + 1)
           private
           def setup_#{element}(feed)
             @#{element}.to_feed(feed)
@@ -395,7 +419,7 @@
           end
         EOC
       end
-      
+
       attr_reader :feed_version
       alias_method(:rss_version, :feed_version)
       attr_accessor :version, :encoding, :standalone
@@ -409,7 +433,7 @@
         @encoding = "UTF-8"
         @standalone = nil
       end
-      
+
       def make
         yield(self)
         to_feed
@@ -423,7 +447,7 @@
         feed.validate
         feed
       end
-      
+
       private
       remove_method :make_xml_stylesheets
       def make_xml_stylesheets
@@ -440,7 +464,7 @@
           attr_accessor attribute
           add_need_initialize_variable(attribute)
         end
-        
+
         def to_feed(feed)
           xss = ::RSS::XMLStyleSheet.new
           guess_type_if_need(xss)
@@ -463,7 +487,7 @@
         end
       end
     end
-    
+
     class ChannelBase < Base
       include SetupDefaultDate
 
@@ -484,12 +508,24 @@
       end
 
       %w(id about language
-         managingEditor webMaster rating docs date
-         lastBuildDate ttl).each do |element|
+         managingEditor webMaster rating docs ttl).each do |element|
         attr_accessor element
         add_need_initialize_variable(element)
       end
 
+      %w(date lastBuildDate).each do |date_element|
+        attr_reader date_element
+        add_need_initialize_variable(date_element)
+      end
+
+      def date=(_date)
+        @date = _parse_date_if_needed(_date)
+      end
+
+      def lastBuildDate=(_date)
+        @lastBuildDate = _parse_date_if_needed(_date)
+      end
+
       def pubDate
         date
       end
@@ -538,7 +574,7 @@
           end
         end
       end
-      
+
       class SkipHoursBase < Base
         def_array_element("hour")
 
@@ -549,7 +585,7 @@
           end
         end
       end
-      
+
       class CloudBase < Base
         %w(domain port path registerProcedure protocol).each do |element|
           attr_accessor element
@@ -619,7 +655,7 @@
         include AtomTextConstructBase
       end
     end
-    
+
     class ImageBase < Base
       %w(title url width height description).each do |element|
         attr_accessor element
@@ -630,18 +666,18 @@
         @maker.channel.link
       end
     end
-    
+
     class ItemsBase < Base
       def_array_element("item")
 
       attr_accessor :do_sort, :max_size
-      
+
       def initialize(maker)
         super
         @do_sort = false
         @max_size = -1
       end
-      
+
       def normalize
         if @max_size >= 0
           sort_if_need[0... at max_size]
@@ -684,11 +720,20 @@
           def_classed_elements(name, attribute)
 	end
 
-        %w(date comments id published).each do |element|
+        %w(comments id published).each do |element|
           attr_accessor element
           add_need_initialize_variable(element)
         end
 
+        %w(date).each do |date_element|
+          attr_reader date_element
+          add_need_initialize_variable(date_element)
+        end
+
+        def date=(_date)
+          @date = _parse_date_if_needed(_date)
+        end
+
         def pubDate
           date
         end
@@ -727,6 +772,14 @@
             attr_accessor element
             add_need_initialize_variable(element)
           end
+
+          def permanent_link?
+            isPermaLink
+          end
+
+          def permanent_link=(bool)
+            self.isPermaLink = bool
+          end
         end
 
         class EnclosureBase < Base
@@ -737,6 +790,8 @@
         end
 
         class SourceBase < Base
+          include SetupDefaultDate
+
           %w(authors categories contributors generator icon
              logo rights subtitle title).each do |name|
             def_classed_element(name)
@@ -748,7 +803,7 @@
             def_classed_elements(name, attribute)
           end
 
-          %w(id content date).each do |element|
+          %w(id content).each do |element|
             attr_accessor element
             add_need_initialize_variable(element)
           end
@@ -756,6 +811,15 @@
           alias_method(:url, :link)
           alias_method(:url=, :link=)
 
+          %w(date).each do |date_element|
+            attr_reader date_element
+            add_need_initialize_variable(date_element)
+          end
+
+          def date=(_date)
+            @date = _parse_date_if_needed(_date)
+          end
+
           def updated
             date
           end

Modified: MacRuby/trunk/lib/rss/maker/dublincore.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/dublincore.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/dublincore.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -90,7 +90,7 @@
     class ChannelBase
       include DublinCoreModel
     end
-    
+
     class ImageBase; include DublinCoreModel; end
     class ItemsBase
       class ItemBase

Modified: MacRuby/trunk/lib/rss/maker/entry.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/entry.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/entry.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -135,7 +135,7 @@
               self.id = keep[:id]
               @rights = keep[:rights]
               @title = keep[:title]
-              self.updated = keep[:prev_updated]
+              self.updated = keep[:updated]
             end
 
             Guid = Feed::Items::Item::Guid

Modified: MacRuby/trunk/lib/rss/maker/feed.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/feed.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/feed.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -22,6 +22,8 @@
         end
 
         class Channel < ChannelBase
+          include SetupDefaultLanguage
+
           def to_feed(feed)
             set_default_values do
               setup_values(feed)
@@ -71,14 +73,11 @@
           def _set_default_values(&block)
             keep = {
               :id => id,
-              :updated => updated,
             }
             self.id ||= about
-            self.updated ||= dc_date
             super(&block)
           ensure
             self.id = keep[:id]
-            self.updated = keep[:updated]
           end
 
           class SkipDays < SkipDaysBase
@@ -182,6 +181,7 @@
               set_default_values do
                 entry = feed.class::Entry.new
                 set = setup_values(entry)
+                entry.dc_dates.clear
                 setup_other_elements(feed, entry)
                 if set
                   feed.entries << entry
@@ -216,14 +216,11 @@
             def _set_default_values(&block)
               keep = {
                 :id => id,
-                :updated => updated,
               }
               self.id ||= link
-              self.updated ||= dc_date
               super(&block)
             ensure
               self.id = keep[:id]
-              self.updated = keep[:updated]
             end
 
             class Guid < GuidBase

Modified: MacRuby/trunk/lib/rss/maker/image.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/image.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/image.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -89,7 +89,7 @@
     end
 
     class ChannelBase; include Maker::ImageFaviconModel; end
-    
+
     class ItemsBase
       class ItemBase; include Maker::ImageItemModel; end
     end

Modified: MacRuby/trunk/lib/rss/maker/taxonomy.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/taxonomy.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/taxonomy.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -72,12 +72,12 @@
         class TaxonomyTopicBase < Base
           include DublinCoreModel
           include TaxonomyTopicsModel
-          
+
           attr_accessor :value
           add_need_initialize_variable("value")
           alias_method(:taxo_link, :value)
           alias_method(:taxo_link=, :value=)
-          
+
           def have_required_values?
             @value
           end
@@ -88,11 +88,11 @@
     class RSSBase
       include TaxonomyTopicModel
     end
-    
+
     class ChannelBase
       include TaxonomyTopicsModel
     end
-    
+
     class ItemsBase
       class ItemBase
         include TaxonomyTopicsModel

Modified: MacRuby/trunk/lib/rss/maker/trackback.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker/trackback.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker/trackback.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -19,7 +19,7 @@
         class TrackBackAboutBase < Base
           attr_accessor :value
           add_need_initialize_variable("value")
-          
+
           alias_method(:resource, :value)
           alias_method(:resource=, :value=)
           alias_method(:content, :value)

Modified: MacRuby/trunk/lib/rss/maker.rb
===================================================================
--- MacRuby/trunk/lib/rss/maker.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/maker.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -6,13 +6,13 @@
 
     class << self
       def make(version, &block)
-        m = maker(version)
-        raise UnsupportedMakerVersionError.new(version) if m.nil?
-        m[:maker].make(m[:version], &block)
+        self[version].make(&block)
       end
 
-      def maker(version)
-        MAKERS[version]
+      def [](version)
+        maker_info = maker(version)
+        raise UnsupportedMakerVersionError.new(version) if maker_info.nil?
+        maker_info[:maker]
       end
 
       def add_maker(version, normalized_version, maker)
@@ -26,6 +26,16 @@
       def makers
         MAKERS.values.collect {|info| info[:maker]}.uniq
       end
+
+      def supported?(version)
+        versions.include?(version)
+      end
+
+      private
+      # Can I remove this method?
+      def maker(version)
+        MAKERS[version]
+      end
     end
   end
 end

Modified: MacRuby/trunk/lib/rss/parser.rb
===================================================================
--- MacRuby/trunk/lib/rss/parser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/parser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -98,7 +98,7 @@
       return rss if maybe_xml?(rss)
 
       uri = to_uri(rss)
-      
+
       if uri.respond_to?(:read)
         uri.read
       elsif !rss.tainted? and File.readable?(rss)
@@ -133,7 +133,7 @@
         listener.raise_for_undefined_entity?
       end
     end
-    
+
     def initialize(rss)
       @listener = self.class.listener.new
       @rss = rss
@@ -196,13 +196,13 @@
       def available_tags(uri)
         (@@accessor_bases[uri] || {}).keys
       end
-      
+
       # register uri against this name.
       def register_uri(uri, name)
         @@registered_uris[name] ||= {}
         @@registered_uris[name][uri] = nil
       end
-      
+
       # test if this uri is registered against this name
       def uri_registered?(uri, name)
         @@registered_uris[name].has_key?(uri)
@@ -228,11 +228,11 @@
         install_accessor_base(uri, name, accessor_base)
         def_get_text_element(uri, name, *get_file_and_line_from_caller(1))
       end
-      
+
       def raise_for_undefined_entity?
         true
       end
-    
+
       private
       # set the accessor for the uri, tag_name pair
       def install_accessor_base(uri, tag_name, accessor_base)
@@ -279,7 +279,7 @@
       @xml_element = nil
       @last_xml_element = nil
     end
-    
+
     # set instance vars for version, encoding, standalone
     def xmldecl(version, encoding, standalone)
       @version, @encoding, @standalone = version, encoding, standalone
@@ -392,7 +392,7 @@
         start_have_something_element(local, prefix, attrs, ns, next_class)
       else
         if !@do_validate or @ignore_unknown_element
-          @proc_stack.push(nil)
+          @proc_stack.push(setup_next_element_in_unknown_element)
         else
           parent = "ROOT ELEMENT???"
           if current_class.tag_name
@@ -417,19 +417,28 @@
       end
     end
 
-    NAMESPLIT = /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/
+    NAMESPLIT = /^(?:([\w:][-\w.]*):)?([\w:][-\w.]*)/
     def split_name(name)
       name =~ NAMESPLIT
       [$1 || '', $2]
     end
 
-    def check_ns(tag_name, prefix, ns, require_uri)
-      unless _ns(ns, prefix) == require_uri
-        if @do_validate
+    def check_ns(tag_name, prefix, ns, require_uri, ignore_unknown_element=nil)
+      if _ns(ns, prefix) == require_uri
+        true
+      else
+        if ignore_unknown_element.nil?
+          ignore_unknown_element = @ignore_unknown_element
+        end
+
+        if ignore_unknown_element
+          false
+        elsif @do_validate
           raise NSError.new(tag_name, prefix, require_uri)
         else
           # Force bind required URI with prefix
           @ns_stack.last[prefix] = require_uri
+          true
         end
       end
     end
@@ -437,7 +446,7 @@
     def start_get_text_element(tag_name, prefix, ns, required_uri)
       pr = Proc.new do |text, tags|
         setter = self.class.setter(required_uri, tag_name)
-        if @last_element.respond_to?(setter)
+        if setter and @last_element.respond_to?(setter)
           if @do_validate
             getter = self.class.getter(required_uri, tag_name)
             if @last_element.__send__(getter)
@@ -456,9 +465,12 @@
     end
 
     def start_have_something_element(tag_name, prefix, attrs, ns, klass)
-      check_ns(tag_name, prefix, ns, klass.required_uri)
-      attributes = collect_attributes(tag_name, prefix, attrs, ns, klass)
-      @proc_stack.push(setup_next_element(tag_name, klass, attributes))
+      if check_ns(tag_name, prefix, ns, klass.required_uri)
+        attributes = collect_attributes(tag_name, prefix, attrs, ns, klass)
+        @proc_stack.push(setup_next_element(tag_name, klass, attributes))
+      else
+        @proc_stack.push(setup_next_element_in_unknown_element)
+      end
     end
 
     def collect_attributes(tag_name, prefix, attrs, ns, klass)
@@ -525,6 +537,11 @@
         @last_element = previous
       end
     end
+
+    def setup_next_element_in_unknown_element
+      current_element, @last_element = @last_element, nil
+      Proc.new {@last_element = current_element}
+    end
   end
 
   unless const_defined? :AVAILABLE_PARSER_LIBRARIES

Modified: MacRuby/trunk/lib/rss/rexmlparser.rb
===================================================================
--- MacRuby/trunk/lib/rss/rexmlparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/rexmlparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -7,7 +7,7 @@
 end
 
 module RSS
-  
+
   class REXMLParser < BaseParser
 
     class << self
@@ -15,7 +15,7 @@
         REXMLListener
       end
     end
-    
+
     private
     def _parse
       begin
@@ -28,9 +28,9 @@
         raise NotWellFormedError.new(line){e.message}
       end
     end
-    
+
   end
-  
+
   class REXMLListener < BaseListener
 
     include REXML::StreamListener
@@ -41,7 +41,7 @@
         false
       end
     end
-    
+
     def xmldecl(version, encoding, standalone)
       super(version, encoding, standalone == "yes")
       # Encoding is converted to UTF-8 when REXML parse XML.

Modified: MacRuby/trunk/lib/rss/rss.rb
===================================================================
--- MacRuby/trunk/lib/rss/rss.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/rss.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -53,7 +53,7 @@
 
 module RSS
 
-  VERSION = "0.2.5"
+  VERSION = "0.2.7"
 
   URI = "http://purl.org/rss/1.0/"
 
@@ -249,7 +249,7 @@
       # accessor
       convert_attr_reader name
       date_writer(name, type, disp_name)
-      
+
       install_element(name) do |n, elem_name|
         <<-EOC
         if @#{n}
@@ -634,7 +634,7 @@
     include SetupMaker
 
     INDENT = "  "
-    
+
     MUST_CALL_VALIDATORS = {}
     MODELS = []
     GET_ATTRIBUTES = []
@@ -830,7 +830,7 @@
     def full_name
       tag_name
     end
-    
+
     def converter=(converter)
       @converter = converter
       targets = children.dup
@@ -865,7 +865,7 @@
     ensure
       @do_validate = do_validate
     end
-    
+
     def validate_for_stream(tags, ignore_unknown_element=true)
       validate_attribute
       __validate(ignore_unknown_element, tags, false)
@@ -985,7 +985,7 @@
           end_tag = "\n#{indent}</#{full_name}>"
         end
       end
-      
+
       start_tag + content.join("\n") + end_tag
     end
 
@@ -1010,7 +1010,7 @@
       end
       attrs
     end
-    
+
     def tag_name_with_prefix(prefix)
       "#{prefix}:#{tag_name}"
     end
@@ -1210,7 +1210,7 @@
   module RootElementMixin
 
     include XMLStyleSheetMixin
-    
+
     attr_reader :output_encoding
     attr_reader :feed_type, :feed_subtype, :feed_version
     attr_accessor :version, :encoding, :standalone
@@ -1296,7 +1296,7 @@
       rv << "?>\n"
       rv
     end
-    
+
     def ns_declarations
       decls = {}
       self.class::NSPOOL.collect do |prefix, uri|

Modified: MacRuby/trunk/lib/rss/syndication.rb
===================================================================
--- MacRuby/trunk/lib/rss/syndication.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/syndication.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,11 +8,11 @@
   RDF.install_ns(SY_PREFIX, SY_URI)
 
   module SyndicationModel
-    
+
     extend BaseModel
-    
+
     ELEMENTS = []
-    
+
     def self.append_features(klass)
       super
 

Modified: MacRuby/trunk/lib/rss/taxonomy.rb
===================================================================
--- MacRuby/trunk/lib/rss/taxonomy.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/taxonomy.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -24,7 +24,7 @@
 
   module TaxonomyTopicsModel
     extend BaseModel
-    
+
     def self.append_features(klass)
       super
 
@@ -37,21 +37,21 @@
 
     class TaxonomyTopics < Element
       include RSS10
-      
+
       Bag = ::RSS::RDF::Bag
 
       class << self
         def required_prefix
           TAXO_PREFIX
         end
-        
+
         def required_uri
           TAXO_URI
         end
       end
 
       @tag_name = "topics"
-      
+
       install_have_child_element("Bag", RDF::URI, nil)
       install_must_call_validator('rdf', RDF::URI)
 
@@ -84,10 +84,10 @@
       end
     end
   end
-  
+
   module TaxonomyTopicModel
     extend BaseModel
-    
+
     def self.append_features(klass)
       super
       var_name = "#{TAXO_PREFIX}_topic"
@@ -99,12 +99,12 @@
 
       include DublinCoreModel
       include TaxonomyTopicsModel
-      
+
       class << self
         def required_prefix
           TAXO_PREFIX
         end
-        
+
         def required_uri
           TAXO_URI
         end
@@ -115,7 +115,7 @@
       install_get_attribute("about", ::RSS::RDF::URI, true, nil, nil,
                             "#{RDF::PREFIX}:about")
       install_text_element("link", TAXO_URI, "?", "#{TAXO_PREFIX}_link")
-        
+
       def initialize(*args)
         if Utils.element_initialize_arguments?(args)
           super

Modified: MacRuby/trunk/lib/rss/trackback.rb
===================================================================
--- MacRuby/trunk/lib/rss/trackback.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/trackback.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -23,7 +23,7 @@
   module BaseTrackBackModel
 
     ELEMENTS = %w(ping about)
-    
+
     def append_features(klass)
       super
 
@@ -47,7 +47,7 @@
             end
           EOC
         end
-        
+
         [%w(about s)].each do |name, postfix|
           var_name = "#{TRACKBACK_PREFIX}_#{name}"
           klass_name = "TrackBack#{Utils.to_class_name(name)}"
@@ -105,7 +105,7 @@
         def required_prefix
           TRACKBACK_PREFIX
         end
-        
+
         def required_uri
           TRACKBACK_URI
         end
@@ -141,17 +141,17 @@
       include RSS10
 
       class << self
-        
+
         def required_prefix
           TRACKBACK_PREFIX
         end
-        
+
         def required_uri
           TRACKBACK_URI
         end
 
       end
-      
+
       @tag_name = "about"
 
       [
@@ -163,7 +163,7 @@
 
       alias_method(:value, :resource)
       alias_method(:value=, :resource=)
-      
+
       def initialize(*args)
         if Utils.element_initialize_arguments?(args)
           super
@@ -185,7 +185,7 @@
       def setup_maker_attributes(about)
         about.resource = self.resource
       end
-      
+
     end
   end
 
@@ -197,7 +197,7 @@
       include RSS09
 
       @tag_name = "ping"
-      
+
       content_setup
 
       class << self
@@ -205,13 +205,13 @@
         def required_prefix
           TRACKBACK_PREFIX
         end
-        
+
         def required_uri
           TRACKBACK_URI
         end
 
       end
-      
+
       alias_method(:value, :content)
       alias_method(:value=, :content=)
 
@@ -223,26 +223,26 @@
           self.content = args[0]
         end
       end
-      
+
       def full_name
         tag_name_with_prefix(TRACKBACK_PREFIX)
       end
-      
+
     end
 
     class TrackBackAbout < Element
       include RSS09
 
       @tag_name = "about"
-      
+
       content_setup
 
       class << self
-        
+
         def required_prefix
           TRACKBACK_PREFIX
         end
-        
+
         def required_uri
           TRACKBACK_URI
         end
@@ -260,11 +260,11 @@
           self.content = args[0]
         end
       end
-      
+
       def full_name
         tag_name_with_prefix(TRACKBACK_PREFIX)
       end
-      
+
     end
   end
 

Modified: MacRuby/trunk/lib/rss/utils.rb
===================================================================
--- MacRuby/trunk/lib/rss/utils.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/utils.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,11 +8,9 @@
         "#{part[0, 1].upcase}#{part[1..-1]}"
       end.join("")
     end
-    
+
     def get_file_and_line_from_caller(i=0)
-      bt = caller
-      i = bt.size - 1 if i >= bt.size
-      file, line, = bt[i].split(':')
+      file, line, = caller[i].split(':')
       line = line.to_i
       line += 1 if i.zero?
       [file, line]
@@ -23,7 +21,7 @@
       s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
     end
     alias h html_escape
-    
+
     # If +value+ is an instance of class +klass+, return it, else
     # create a new instance of +klass+ with value +value+.
     def new_with_value_if_need(klass, value)

Modified: MacRuby/trunk/lib/rss/xml-stylesheet.rb
===================================================================
--- MacRuby/trunk/lib/rss/xml-stylesheet.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/xml-stylesheet.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -8,7 +8,7 @@
       super
       @xml_stylesheets = []
     end
-    
+
     private
     def xml_stylesheet_pi
       xsss = @xml_stylesheets.collect do |xss|
@@ -94,7 +94,7 @@
         xss.__send__("#{attr}=", __send__(attr))
       end
     end
-    
+
     private
     def guess_type(filename)
       /\.([^.]+)$/ =~ filename

Modified: MacRuby/trunk/lib/rss/xmlparser.rb
===================================================================
--- MacRuby/trunk/lib/rss/xmlparser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/xmlparser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -26,9 +26,9 @@
 end
 
 module RSS
-  
+
   class REXMLLikeXMLParser < ::XML::Parser
-    
+
     include ::XML::Encoding_ja
 
     def listener=(listener)
@@ -38,7 +38,7 @@
     def startElement(name, attrs)
       @listener.tag_start(name, attrs)
     end
-    
+
     def endElement(name)
       @listener.tag_end(name)
     end
@@ -64,7 +64,7 @@
         XMLParserListener
       end
     end
-    
+
     private
     def _parse
       begin
@@ -75,13 +75,13 @@
         raise NotWellFormedError.new(parser.line){e.message}
       end
     end
-    
+
   end
-  
+
   class XMLParserListener < BaseListener
 
     include ListenerMixin
-    
+
     def xmldecl(version, encoding, standalone)
       super
       # Encoding is converted to UTF-8 when XMLParser parses XML.

Modified: MacRuby/trunk/lib/rss/xmlscanner.rb
===================================================================
--- MacRuby/trunk/lib/rss/xmlscanner.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/rss/xmlscanner.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -2,15 +2,15 @@
 require 'stringio'
 
 module RSS
-  
+
   class XMLScanParser < BaseParser
-    
+
     class << self
       def listener
         XMLScanListener
       end
     end
-    
+
     private
     def _parse
       begin
@@ -26,11 +26,11 @@
         raise NotWellFormedError.new(lineno){e.message}
       end
     end
-    
+
   end
 
   class XMLScanListener < BaseListener
-    
+
     include XMLScan::Visitor
     include ListenerMixin
 

Modified: MacRuby/trunk/lib/securerandom.rb
===================================================================
--- MacRuby/trunk/lib/securerandom.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/securerandom.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -46,6 +46,11 @@
   # If n is not specified, 16 is assumed.
   # It may be larger in future.
   #
+  # The result may contain any byte: "\x00" - "\xff".
+  #
+  #   p SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
+  #   p SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
+  #
   # If secure random number generator is not available,
   # NotImplementedError is raised.
   def self.random_bytes(n=nil)
@@ -59,7 +64,6 @@
       flags = File::RDONLY
       flags |= File::NONBLOCK if defined? File::NONBLOCK
       flags |= File::NOCTTY if defined? File::NOCTTY
-      flags |= File::NOFOLLOW if defined? File::NOFOLLOW
       begin
         File.open("/dev/urandom", flags) {|f|
           unless f.stat.chardev?
@@ -99,7 +103,7 @@
       end
     end
     if @has_win32
-      bytes = " " * n
+      bytes = " ".force_encoding("ASCII-8BIT") * n
       if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0
         raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}"
       end
@@ -117,6 +121,11 @@
   # If n is not specified, 16 is assumed.
   # It may be larger in future.
   #
+  # The result may contain 0-9 and a-f.
+  #
+  #   p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
+  #   p SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61"
+  #
   # If secure random number generator is not available,
   # NotImplementedError is raised.
   def self.hex(n=nil)
@@ -131,21 +140,69 @@
   # If n is not specified, 16 is assumed.
   # It may be larger in future.
   #
+  # The result may contain A-Z, a-z, 0-9, "+", "/" and "=".
+  #
+  #   p SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A=="
+  #   p SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ=="
+  #
   # If secure random number generator is not available,
   # NotImplementedError is raised.
+  #
+  # See RFC 3548 for base64.
   def self.base64(n=nil)
     [random_bytes(n)].pack("m*").delete("\n")
   end
 
+  # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string.
+  #
+  # The argument _n_ specifies the length of the random length.
+  # The length of the result string is about 4/3 of _n_.
+  #
+  # If _n_ is not specified, 16 is assumed.
+  # It may be larger in future.
+  #
+  # The boolean argument _padding_ specifies the padding.
+  # If it is false or nil, padding is not generated.
+  # Otherwise padding is generated.
+  # By default, padding is not generated because "=" may be used as a URL delimiter.
+  #
+  # The result may contain A-Z, a-z, 0-9, "-" and "_".
+  # "=" is also used if _padding_ is true.
+  #
+  #   p SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"
+  #   p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
+  #
+  #   p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
+  #   p SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg=="
+  #
+  # If secure random number generator is not available,
+  # NotImplementedError is raised.
+  #
+  # See RFC 3548 for URL-safe base64.
+  def self.urlsafe_base64(n=nil, padding=false)
+    s = [random_bytes(n)].pack("m*")
+    s.delete!("\n")
+    s.tr!("+/", "-_")
+    s.delete!("=") if !padding
+    s
+  end
+
   # SecureRandom.random_number generates a random number.
   #
   # If an positive integer is given as n,
   # SecureRandom.random_number returns an integer:
   # 0 <= SecureRandom.random_number(n) < n.
   #
+  #   p SecureRandom.random_number(100) #=> 15
+  #   p SecureRandom.random_number(100) #=> 88
+  #
   # If 0 is given or an argument is not given,
   # SecureRandom.random_number returns an float:
   # 0.0 <= SecureRandom.random_number() < 1.0.
+  #
+  #   p SecureRandom.random_number #=> 0.596506046187744
+  #   p SecureRandom.random_number #=> 0.350621695741409
+  #
   def self.random_number(n=0)
     if 0 < n
       hex = n.to_s(16)
@@ -167,6 +224,24 @@
     end
   end
 
+  # SecureRandom.uuid generates a v4 random UUID (Universally Unique IDentifier).
+  #
+  #   p SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
+  #   p SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
+  #   p SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b"
+  #
+  # The version 4 UUID is purely random (except the version).
+  # It doesn't contain meaningful information such as MAC address, time, etc.
+  #
+  # See RFC 4122 for details of UUID.
+  #
+  def self.uuid
+    ary = self.random_bytes(16).unpack("NnnnnN")
+    ary[2] = (ary[2] & 0x0fff) | 0x4000
+    ary[3] = (ary[3] & 0x3fff) | 0x8000
+    "%08x-%04x-%04x-%04x-%04x%08x" % ary
+  end
+
   # Following code is based on David Garamond's GUID library for Ruby.
   def self.lastWin32ErrorMessage # :nodoc:
     get_last_error = Win32API.new("kernel32", "GetLastError", '', 'L')

Modified: MacRuby/trunk/lib/set.rb
===================================================================
--- MacRuby/trunk/lib/set.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/set.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,7 +9,7 @@
 # All rights reserved.  You can redistribute and/or modify it under the same
 # terms as Ruby.
 #
-#   $Id: set.rb 25189 2009-10-02 12:04:37Z akr $
+#   $Id: set.rb 26648 2010-02-11 17:38:05Z knu $
 #
 # == Overview
 #
@@ -70,12 +70,23 @@
     enum.nil? and return
 
     if block
-      enum.each { |o| add(block[o]) }
+      do_with_enum(enum) { |o| add(block[o]) }
     else
       merge(enum)
     end
   end
 
+  def do_with_enum(enum, &block)
+    if enum.respond_to?(:each_entry)
+      enum.each_entry(&block)
+    elsif enum.respond_to?(:each)
+      enum.each(&block)
+    else
+      raise ArgumentError, "value must be enumerable"
+    end
+  end
+  private :do_with_enum
+
   # Copy internal hash.
   def initialize_copy(orig)
     @hash = orig.instance_eval{@hash}.dup
@@ -123,7 +134,7 @@
       @hash.replace(enum.instance_eval { @hash })
     else
       clear
-      enum.each { |o| add(o) }
+      merge(enum)
     end
 
     self
@@ -279,7 +290,7 @@
     if enum.instance_of?(self.class)
       @hash.update(enum.instance_variable_get(:@hash))
     else
-      enum.each { |o| add(o) }
+      do_with_enum(enum) { |o| add(o) }
     end
 
     self
@@ -288,7 +299,7 @@
   # Deletes every element that appears in the given enumerable object
   # and returns self.
   def subtract(enum)
-    enum.each { |o| delete(o) }
+    do_with_enum(enum) { |o| delete(o) }
     self
   end
 
@@ -311,7 +322,7 @@
   # given enumerable object.
   def &(enum)
     n = self.class.new
-    enum.each { |o| n.add(o) if include?(o) }
+    do_with_enum(enum) { |o| n.add(o) if include?(o) }
     n
   end
   alias intersection &	##
@@ -509,7 +520,7 @@
 	  end
 	  
 	  def add(o)
-	    o.respond_to?(:<=>) or raise ArgumentError, "value must repond to <=>"
+	    o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
 	    super
 	  end
 	  alias << add
@@ -637,14 +648,16 @@
 # 	end
 #
 # 	def replace(enum)
+# 	  enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
 # 	  clear
-# 	  enum.each { |o| add(o) }
+# 	  enum.each_entry { |o| add(o) }
 #
 # 	  self
 # 	end
 #
 # 	def merge(enum)
-# 	  enum.each { |o| add(o) }
+# 	  enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
+# 	  enum.each_entry { |o| add(o) }
 #
 # 	  self
 # 	end
@@ -711,10 +724,10 @@
       Set.new([1,2])
       Set.new('a'..'c')
     }
-    assert_raises(NoMethodError) {
+    assert_raises(ArgumentError) {
       Set.new(false)
     }
-    assert_raises(NoMethodError) {
+    assert_raises(ArgumentError) {
       Set.new(1)
     }
     assert_raises(ArgumentError) {

Modified: MacRuby/trunk/lib/shell/builtin-command.rb
===================================================================
--- MacRuby/trunk/lib/shell/builtin-command.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/builtin-command.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/builtin-command.rb - 
+#   shell/builtin-command.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 14912 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 require "shell/filter"
 
@@ -25,7 +25,7 @@
     def initialize(sh, *opts)
       super sh
     end
-    
+
     def each(rs = nil)
       # do nothing
     end
@@ -36,7 +36,7 @@
       super sh
       @strings = strings
     end
-    
+
     def each(rs = nil)
       rs =  @shell.record_separator unless rs
       for str  in @strings
@@ -70,7 +70,7 @@
     end
 
     def each(rs = nil)
-      if @pattern[0] == ?/ 
+      if @pattern[0] == ?/
 	@files = Dir[@pattern]
       else
 	prefix = @shell.pwd+"/"

Modified: MacRuby/trunk/lib/shell/command-processor.rb
===================================================================
--- MacRuby/trunk/lib/shell/command-processor.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/command-processor.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/command-controller.rb - 
+#   shell/command-controller.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 20880 $
+#   	$Revision: 26986 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 require "e2mmap"
 require "thread"
@@ -35,11 +35,11 @@
 
       install_builtin_commands
 
-      # define CommandProccessor#methods to Shell#methods and Filter#methods
+      # define CommandProcessor#methods to Shell#methods and Filter#methods
       for m in CommandProcessor.instance_methods(false) - NoDelegateMethods
 	add_delegate_command_to_shell(m)
       end
-      
+
       def self.method_added(id)
 	add_delegate_command_to_shell(id)
       end
@@ -84,7 +84,7 @@
     # Shell#test
     #
     # -
-    #	
+    #
     # CommandProcessor#foreach(path, rs)
     #	  path: String
     #	  rs:	String - record separator
@@ -168,7 +168,7 @@
     #	  sh["e", "foo"]
     #	  sh[:exists?, "foo"]
     #	  sh["exists?", "foo"]
-    #	  
+    #
     alias top_level_test test
     def test(command, file1, file2=nil)
       file1 = expand_path(file1)
@@ -211,11 +211,11 @@
     # CommandProcessor#mkdir(*path)
     #	  path: String
     #	same as Dir.mkdir()
-    #	  
+    #
     def mkdir(*path)
       @shell.check_point
       notify("mkdir #{path.join(' ')}")
-      
+
       perm = nil
       if path.last.kind_of?(Integer)
 	perm = path.pop
@@ -236,7 +236,7 @@
     # CommandProcessor#rmdir(*path)
     #	  path: String
     #	same as Dir.rmdir()
-    #	  
+    #
     def rmdir(*path)
       @shell.check_point
       notify("rmdir #{path.join(' ')}")
@@ -256,7 +256,7 @@
     #	example:
     #	  print sh.system("ls", "-l")
     #	  sh.system("ls", "-l") | sh.head > STDOUT
-    # 
+    #
     def system(command, *opts)
       if opts.empty?
 	if command =~ /\*|\?|\{|\}|\[|\]|<|>|\(|\)|~|&|\||\\|\$|;|'|`|"|\n/
@@ -338,7 +338,7 @@
     def notify(*opts, &block)
       Shell.notify(*opts) {|mes|
 	yield mes if iterator?
-	
+
 	mes.gsub!("%pwd", "#{@cwd}")
 	mes.gsub!("%cwd", "#{@cwd}")
       }
@@ -383,10 +383,10 @@
      	          SystemCommand.new(@shell, '#{path}', *opts)
                end]), nil, __FILE__, __LINE__ - 1)
       rescue SyntaxError
-	Shell.notify "warn: Can't define #{command} path: #{path}." 
+	Shell.notify "warn: Can't define #{command} path: #{path}."
       end
       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)
     end
 
@@ -418,7 +418,7 @@
                           @shell.__send__(:#{command},
                                           *(CommandProcessor.alias_map[:#{ali}].call *opts))
 	                end]), nil, __FILE__, __LINE__ - 1)
-    
+
 	else
            args = opts.collect{|opt| '"' + opt + '"'}.join(",")
            eval((d = %Q[def #{ali}(*opts)
@@ -426,22 +426,22 @@
                         end]), nil, __FILE__, __LINE__ - 1)
 	end
       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)
 	raise
       end
       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)
       self
     end
-   
+
     def self.unalias_command(ali)
       ali = ali.id2name if ali.kind_of?(Symbol)
       @alias_map.delete ali.intern
       undef_system_command(ali)
     end
-   
+
     #
     # CommandProcessor.def_builtin_commands(delegation_class, command_specs)
     #	  delegation_class: Class or Module
@@ -472,7 +472,7 @@
 		    #{delegation_class}.#{meth}(#{call_arg_str})
 		 end]
 	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)
 	eval d
       end
@@ -513,14 +513,14 @@
 
     #----------------------------------------------------------------------
     #
-    #  class initializing methods  - 
+    #  class initializing methods  -
     #
     #----------------------------------------------------------------------
     def self.add_delegate_command_to_shell(id)
       id = id.intern if id.kind_of?(String)
       name = id.id2name
       if Shell.method_defined?(id)
-	Shell.notify "warn: override definnition of Shell##{name}."
+	Shell.notify "warn: override definition of Shell##{name}."
 	Shell.notify "warn: alias Shell##{name} to Shell##{name}_org.\n"
 	Shell.module_eval "alias #{name}_org #{name}"
       end
@@ -536,7 +536,7 @@
                           end], __FILE__, __LINE__)
 
       if Shell::Filter.method_defined?(id)
-	Shell.notify "warn: override definnition of Shell::Filter##{name}."
+	Shell.notify "warn: override definition of Shell::Filter##{name}."
 	Shell.notify "warn: alias Shell##{name} to Shell::Filter##{name}_org."
 	Filter.module_eval "alias #{name}_org #{name}"
       end
@@ -561,7 +561,7 @@
       normal_delegation_file_methods = [
 	["atime", ["FILENAME"]],
 	["basename", ["fn", "*opts"]],
-	["chmod", ["mode", "*FILENAMES"]], 
+	["chmod", ["mode", "*FILENAMES"]],
 	["chown", ["owner", "group", "*FILENAME"]],
 	["ctime", ["FILENAMES"]],
 	["delete", ["*FILENAMES"]],
@@ -584,7 +584,7 @@
       alias_method :rm, :delete
 
       # method related FileTest
-      def_builtin_commands(FileTest, 
+      def_builtin_commands(FileTest,
 		   FileTest.singleton_methods(false).collect{|m| [m, ["FILENAME"]]})
 
     end

Modified: MacRuby/trunk/lib/shell/error.rb
===================================================================
--- MacRuby/trunk/lib/shell/error.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/error.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/error.rb - 
+#   shell/error.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 14912 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 require "e2mmap"
 

Modified: MacRuby/trunk/lib/shell/filter.rb
===================================================================
--- MacRuby/trunk/lib/shell/filter.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/filter.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/filter.rb - 
+#   shell/filter.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 14912 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 class Shell
   #
@@ -28,7 +28,7 @@
     def input=(filter)
       @input = filter
     end
-    
+
     def each(rs = nil)
       rs = @shell.record_separator unless rs
       if @input

Modified: MacRuby/trunk/lib/shell/process-controller.rb
===================================================================
--- MacRuby/trunk/lib/shell/process-controller.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/process-controller.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/process-controller.rb - 
+#   shell/process-controller.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 20880 $
+#   	$Revision: 26986 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 require "forwardable"
 
 require "thread"
@@ -26,7 +26,7 @@
     class<<self
       extend Forwardable
 
-      def_delegator("@ProcessControllersMonitor", 
+      def_delegator("@ProcessControllersMonitor",
 		    "synchronize", "process_controllers_exclusive")
 
       def active_process_controllers
@@ -118,7 +118,7 @@
     def waiting_jobs
       @waiting_jobs
     end
-    
+
     def jobs_exist?
       @jobs_sync.synchronize(:SH) do
 	@active_jobs.empty? or @waiting_jobs.empty?
@@ -158,7 +158,7 @@
 	else
 	  command = @waiting_jobs.shift
 #	  command.notify "job(%id) pre-start.", @shell.debug?
-	  
+
 	  return unless command
 	end
 	@active_jobs.push command
@@ -191,7 +191,7 @@
 	@active_jobs.delete command
 	ProcessController.inactivate(self)
 	if @active_jobs.empty?
-	  command.notify("start_jon in ierminate_jon(%id)", Shell::debug?)
+	  command.notify("start_job in terminate_job(%id)", Shell::debug?)
 	  start_job
 	end
       end
@@ -253,7 +253,7 @@
 	  end
 
 	  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.current == th
 	    end
@@ -261,7 +261,7 @@
 	    STDIN.reopen(pipe_peer_in)
 	    STDOUT.reopen(pipe_peer_out)
 
-	    ObjectSpace.each_object(IO) do |io| 
+	    ObjectSpace.each_object(IO) do |io|
 	      if ![STDIN, STDOUT, STDERR].include?(io)
 		io.close unless io.closed?
 	      end
@@ -281,13 +281,13 @@
 	  command.notify("job(%id) start to waiting finish.", @shell.debug?)
 	  _pid = Process.waitpid(pid, nil)
 	rescue Errno::ECHILD
-	  command.notify "warn: job(%id) was done already waitipd."
+	  command.notify "warn: job(%id) was done already waitpid."
 	  _pid = true
 	  #	rescue
 	  #	  STDERR.puts $!
 	ensure
 	  command.notify("Job(%id): Wait to finish when Process finished.", @shell.debug?)
-	  # when the process ends, wait until the command termintes
+	  # when the process ends, wait until the command terminates
 	  if USING_AT_EXIT_WHEN_PROCESS_EXIT or _pid
 	  else
 	    command.notify("notice: Process finishing...",
@@ -295,9 +295,9 @@
 			   "You can use Shell#transact or Shell#check_point for more safe execution.")
 	    redo
 	  end
-	  
+
 #	  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?
 	    terminate_job(command)
 #	    command.notify "job(%id) pre-finish2.", @shell.debug?

Modified: MacRuby/trunk/lib/shell/system-command.rb
===================================================================
--- MacRuby/trunk/lib/shell/system-command.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/system-command.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell/system-command.rb - 
+#   shell/system-command.rb -
 #   	$Release Version: 0.7 $
-#   	$Revision: 14912 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 require "shell/filter"
 
@@ -20,7 +20,7 @@
       super(sh)
       @command = command
       @opts = opts
-      
+
       @input_queue = Queue.new
       @pid = nil
 
@@ -140,9 +140,9 @@
     end
 
     # ex)
-    #    if you wish to output: 
+    #    if you wish to output:
     #	    "shell: job(#{@command}:#{@pid}) close pipe-out."
-    #	 then 
+    #	 then
     #	    mes: "job(%id) close pipe-out."
     #    yorn: Boolean(@shell.debug? or @shell.verbose?)
     def notify(*opts, &block)

Modified: MacRuby/trunk/lib/shell/version.rb
===================================================================
--- MacRuby/trunk/lib/shell/version.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell/version.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
 #   version.rb - shell version definition file
 #   	$Release Version: 0.7$
-#   	$Revision: 14912 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 class Shell
   @RELEASE_VERSION = "0.7"

Modified: MacRuby/trunk/lib/shell.rb
===================================================================
--- MacRuby/trunk/lib/shell.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/shell.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
-#   shell.rb - 
+#   shell.rb -
 #   	$Release Version: 0.7 $
 #   	$Revision: 1.9 $
 #   	by Keiju ISHITSUKA(keiju at ruby-lang.org)
 #
 # --
 #
-#   
 #
+#
 
 require "e2mmap"
 

Modified: MacRuby/trunk/lib/sync.rb
===================================================================
--- MacRuby/trunk/lib/sync.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/sync.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,7 +1,7 @@
 #
 #   sync.rb - 2 phase lock with counter
 #   	$Release Version: 1.0$
-#   	$Revision: 19280 $
+#   	$Revision: 25189 $
 #   	by Keiju ISHITSUKA(keiju at ishitsuka.com)
 #
 # --
@@ -34,34 +34,34 @@
 #   Sync#lock(mode)     -- mode = :EX, :SH, :UN
 #   Sync#unlock
 #   Sync#synchronize(mode) {...}
-#   
 #
+#
 
 unless defined? Thread
   raise "Thread not available for this ruby interpreter"
 end
 
 module Sync_m
-  RCS_ID='-$Header$-'
-  
+  RCS_ID='-$Id: sync.rb 25189 2009-10-02 12:04:37Z akr $-'
+
   # lock mode
   UN = :UN
   SH = :SH
   EX = :EX
-  
+
   # exceptions
   class Err < StandardError
     def Err.Fail(*opt)
       fail self, sprintf(self::Message, *opt)
     end
-    
+
     class UnknownLocker < Err
       Message = "Thread(%s) not locked."
       def UnknownLocker.Fail(th)
 	super(th.inspect)
       end
     end
-    
+
     class LockModeFailer < Err
       Message = "Unknown lock mode(%s)"
       def LockModeFailer.Fail(mode)
@@ -72,7 +72,7 @@
       end
     end
   end
-  
+
   def Sync_m.define_aliases(cl)
     cl.module_eval %q{
       alias locked? sync_locked?
@@ -84,7 +84,7 @@
       alias synchronize sync_synchronize
     }
   end
-  
+
   def Sync_m.append_features(cl)
     super
     # do nothing for Modules
@@ -92,12 +92,12 @@
     define_aliases(cl) unless cl.instance_of?(Module)
     self
   end
-  
+
   def Sync_m.extend_object(obj)
     super
     obj.sync_extend
   end
-  
+
   def sync_extend
     unless (defined? locked? and
 	    defined? shared? and
@@ -115,15 +115,15 @@
   def sync_locked?
     sync_mode != UN
   end
-  
+
   def sync_shared?
     sync_mode == SH
   end
-  
+
   def sync_exclusive?
     sync_mode == EX
   end
-  
+
   # locking methods.
   def sync_try_lock(mode = EX)
     return unlock if mode == UN
@@ -132,7 +132,7 @@
     end
     ret
   end
-  
+
   def sync_lock(m = EX)
     return unlock if m == UN
 
@@ -153,21 +153,21 @@
     end
     self
   end
-  
+
   def sync_unlock(m = EX)
     wakeup_threads = []
     @sync_mutex.synchronize do
       if sync_mode == UN
 	Err::UnknownLocker.Fail(Thread.current)
       end
-      
+
       m = sync_mode if m == EX and sync_mode == SH
-      
+
       runnable = false
       case m
       when UN
 	Err::UnknownLocker.Fail(Thread.current)
-	
+
       when EX
 	if sync_ex_locker == Thread.current
 	  if (self.sync_ex_count = sync_ex_count - 1) == 0
@@ -182,12 +182,12 @@
 	else
 	  Err::UnknownLocker.Fail(Thread.current)
 	end
-	
+
       when SH
 	if (count = sync_sh_locker[Thread.current]).nil?
 	  Err::UnknownLocker.Fail(Thread.current)
 	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)
 	    if sync_sh_locker.empty? and sync_ex_count == 0
 	      self.sync_mode = UN
@@ -196,7 +196,7 @@
 	  end
 	end
       end
-      
+
       if runnable
 	if sync_upgrade_waiting.size > 0
 	  th, count = sync_upgrade_waiting.shift
@@ -218,7 +218,7 @@
     end
     self
   end
-  
+
   def sync_synchronize(mode = EX)
     sync_lock(mode)
     begin
@@ -229,7 +229,7 @@
   end
 
   attr_accessor :sync_mode
-    
+
   attr_accessor :sync_waiting
   attr_accessor :sync_upgrade_waiting
   attr_accessor :sync_sh_locker
@@ -258,7 +258,7 @@
     super
     sync_initialize
   end
-    
+
   def sync_try_lock_sub(m)
     case m
     when SH
@@ -282,7 +282,7 @@
       end
     when EX
       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_ex_locker = Thread.current
 	self.sync_ex_count = 1

Modified: MacRuby/trunk/lib/tempfile.rb
===================================================================
--- MacRuby/trunk/lib/tempfile.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/tempfile.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,102 +1,166 @@
 #
 # tempfile - manipulates temporary files
 #
-# $Id: tempfile.rb 19833 2008-10-18 10:32:26Z matz $
+# $Id: tempfile.rb 27578 2010-05-01 13:54:01Z nobu $
 #
 
 require 'delegate'
 require 'tmpdir'
 require 'thread'
 
-# A class for managing temporary files.  This library is written to be
-# thread safe.
+# A utility class for managing temporary files. When you create a Tempfile
+# object, it will create a temporary file with a unique filename. A Tempfile
+# objects behaves just like a File object, and you can perform all the usual
+# file operations on it: reading data, writing data, changing its permissions,
+# etc. So although this class does not explicitly document all instance methods
+# supported by File, you can in fact call any File instance method on a
+# Tempfile object.
+#
+# == Synopsis
+#
+#   require 'tempfile'
+#
+#   file = Tempfile.new('foo')
+#   file.path      # => A unique filename in the OS's temp directory,
+#                  #    e.g.: "/tmp/foo.24722.0"
+#                  #    This filename contains 'foo' in its basename.
+#   file.write("hello world")
+#   file.rewind
+#   file.read      # => "hello world"
+#   file.close
+#   file.unlink    # deletes the temp file
+#
+# == Good practices
+#
+# === Explicit close
+#
+# When a Tempfile object is garbage collected, or when the Ruby interpreter
+# exits, its associated temporary file is automatically deleted. This means
+# that's it's unnecessary to explicitly delete a Tempfile after use, though
+# it's good practice to do so: not explicitly deleting unused Tempfiles can
+# potentially leave behind large amounts of tempfiles on the filesystem
+# until they're garbage collected. The existance of these temp files can make
+# it harder to determine a new Tempfile filename.
+#
+# Therefore, one should always call #unlink or close in an ensure block, like
+# this:
+#
+#   file = Tempfile.new('foo')
+#   begin
+#      ...do something with file...
+#   ensure
+#      file.close
+#      file.unlink   # deletes the temp file
+#   end
+#
+# === Unlink after creation
+#
+# On POSIX systems, it's possible to unlink a file right after creating it,
+# and before closing it. This removes the filesystem entry without closing
+# the file handle, so it ensures that only the processes that already had
+# the file handle open can access the file's contents. It's strongly
+# recommended that you do this if you do not want any other processes to
+# be able to read from or write to the Tempfile, and you do not need to
+# know the Tempfile's filename either.
+#
+# For example, a practical use case for unlink-after-creation would be this:
+# you need a large byte buffer that's too large to comfortably fit in RAM,
+# e.g. when you're writing a web server and you want to buffer the client's
+# file upload data.
+#
+# Please refer to #unlink for more information and a code example.
+#
+# == Minor notes
+#
+# Tempfile's filename picking method is both thread-safe and inter-process-safe:
+# it guarantees that no other threads or processes will pick the same filename.
+#
+# Tempfile itself however may not be entirely thread-safe. If you access the
+# same Tempfile object from multiple threads then you should protect it with a
+# mutex.
 class Tempfile < DelegateClass(File)
-  MAX_TRY = 10
-  @@cleanlist = []
-  @@lock = Mutex.new
+  MAX_TRY = 10  # :nodoc:
+  include Dir::Tmpname
 
-  # Creates a temporary file of mode 0600 in the temporary directory,
-  # opens it with mode "w+", and returns a Tempfile object which
-  # represents the created temporary file.  A Tempfile object can be
-  # treated just like a normal File object.
+  # call-seq:
+  #    new(basename, [tmpdir = Dir.tmpdir], [options])
   #
-  # The basename parameter is used to determine the name of a
-  # temporary file.  If an Array is given, the first element is used
-  # as prefix string and the second as suffix string, respectively.
-  # Otherwise it is treated as prefix string.
+  # Creates a temporary file with permissions 0600 (= only readable and
+  # writable by the owner) and opens it with mode "w+".
   #
-  # If tmpdir is omitted, the temporary directory is determined by
-  # Dir::tmpdir provided by 'tmpdir.rb'.
-  # When $SAFE > 0 and the given tmpdir is tainted, it uses
-  # /tmp. (Note that ENV values are tainted by default)
+  # The +basename+ parameter is used to determine the name of the
+  # temporary file. You can either pass a String or an Array with
+  # 2 String elements. In the former form, the temporary file's base
+  # name will begin with the given string. In the latter form,
+  # the temporary file's base name will begin with the array's first
+  # element, and end with the second element. For example:
+  #
+  #   file = Tempfile.new('hello')
+  #   file.path  # => something like: "/tmp/foo2843-8392-92849382--0"
+  #
+  #   # Use the Array form to enforce an extension in the filename:
+  #   file = Tempfile.new(['hello', '.jpg'])
+  #   file.path  # => something like: "/tmp/foo2843-8392-92849382--0.jpg"
+  #
+  # The temporary file will be placed in the directory as specified
+  # by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+.
+  # When $SAFE > 0 and the given +tmpdir+ is tainted, it uses
+  # '/tmp' as the temporary directory. Please note that ENV values
+  # are tainted by default, and +Dir.tmpdir+'s return value might
+  # come from environment variables (e.g. <tt>$TMPDIR</tt>).
+  #
+  #   file = Tempfile.new('hello', '/home/aisaka')
+  #   file.path  # => something like: "/home/aisaka/foo2843-8392-92849382--0"
+  #
+  # You can also pass an options hash. Under the hood, Tempfile creates
+  # the temporary file using +File.open+. These options will be passed to
+  # +File.open+. This is mostly useful for specifying encoding
+  # options, e.g.:
+  #
+  #   Tempfile.new('hello', '/home/aisaka', :encoding => 'ascii-8bit')
+  #
+  #   # You can also omit the 'tmpdir' parameter:
+  #   Tempfile.new('hello', :encoding => 'ascii-8bit')
+  #
+  # === Exceptions
+  #
+  # If Tempfile.new cannot find a unique filename within a limited
+  # number of tries, then it will raise an exception.
   def initialize(basename, *rest)
-    # I wish keyword argument settled soon.
-    if opts = Hash.try_convert(rest[-1])
-      rest.pop
-    end
-    tmpdir = rest[0] || Dir::tmpdir
-    if $SAFE > 0 and tmpdir.tainted?
-      tmpdir = '/tmp'
-    end
+    @data = []
+    @clean_proc = Remover.new(@data)
+    ObjectSpace.define_finalizer(self, @clean_proc)
 
-    lock = tmpname = nil
-    n = failure = 0
-    @@lock.synchronize {
+    create(basename, *rest) do |tmpname, n, opts|
+      lock = tmpname + '.lock'
+      mode = File::RDWR|File::CREAT|File::EXCL
+      perm = 0600
+      if opts
+        mode |= opts.delete(:mode) || 0
+        opts[:perm] = perm
+        perm = nil
+      else
+        opts = perm
+      end
+      self.class.mkdir(lock)
       begin
-        begin
-          tmpname = File.join(tmpdir, make_tmpname(basename, n))
-          lock = tmpname + '.lock'
-          n += 1
-        end while @@cleanlist.include?(tmpname) or
-            File.exist?(lock) or File.exist?(tmpname)
-        Dir.mkdir(lock)
-      rescue
-        failure += 1
-        retry if failure < MAX_TRY
-        raise "cannot generate tempfile `%s'" % tmpname
+        @data[1] = @tmpfile = File.open(tmpname, mode, opts)
+        @data[0] = @tmpname = tmpname
+      ensure
+        self.class.rmdir(lock)
       end
-    }
-
-    @data = [tmpname]
-    @clean_proc = Tempfile.callback(@data)
-    ObjectSpace.define_finalizer(self, @clean_proc)
-
-    if opts.nil?
-      opts = []
-    else
-      opts = [opts]
+      @mode = mode & ~(File::CREAT|File::EXCL)
+      perm or opts.freeze
+      @opts = opts
     end
-    @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600, *opts)
-    @tmpname = tmpname
-    @@cleanlist << @tmpname
-    @data[1] = @tmpfile
-    @data[2] = @@cleanlist
 
     super(@tmpfile)
-
-    # Now we have all the File/IO methods defined, you must not
-    # carelessly put bare puts(), etc. after this.
-
-    Dir.rmdir(lock)
   end
 
-  def make_tmpname(basename, n)
-    case basename
-    when Array
-      prefix, suffix = *basename
-    else
-      prefix, suffix = basename, ''
-    end
- 
-    t = Time.now.strftime("%Y%m%d")
-    path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}"
-  end
-  private :make_tmpname
-
   # Opens or reopens the file with mode "r+".
   def open
     @tmpfile.close if @tmpfile
-    @tmpfile = File.open(@tmpname, 'r+')
+    @tmpfile = File.open(@tmpname, @mode, @opts)
     @data[1] = @tmpfile
     __setobj__(@tmpfile)
   end
@@ -108,8 +172,9 @@
   end
   protected :_close
 
-  #Closes the file.  If the optional flag is true, unlinks the file
-  # after closing.
+  # Closes the file. If +unlink_now+ is true, then the file will be unlinked
+  # (deleted) after closing. Of course, you can choose to later call #unlink
+  # if you do not unlink it now.
   #
   # If you don't explicitly unlink the temporary file, the removal
   # will be delayed until the object is finalized.
@@ -121,25 +186,57 @@
     end
   end
 
-  # Closes and unlinks the file.
+  # Closes and unlinks (deletes) the file. Has the same effect as called
+  # <tt>close(true)</tt>.
   def close!
     _close
-    @clean_proc.call
+    unlink
     ObjectSpace.undefine_finalizer(self)
-    @data = @tmpname = nil
   end
 
-  # Unlinks the file.  On UNIX-like systems, it is often a good idea
-  # to unlink a temporary file immediately after creating and opening
-  # it, because it leaves other programs zero chance to access the
-  # file.
+  # Unlinks (deletes) the file from the filesystem. One should always unlink
+  # the file after using it, as is explained in the "Explicit close" good
+  # practice section in the Tempfile overview:
+  #
+  #   file = Tempfile.new('foo')
+  #   begin
+  #      ...do something with file...
+  #   ensure
+  #      file.close
+  #      file.unlink   # deletes the temp file
+  #   end
+  #
+  # === Unlink-before-close
+  #
+  # On POSIX systems it's possible to unlink a file before closing it. This
+  # practice is explained in detail in the Tempfile overview (section
+  # "Unlink after creation"); please refer there for more information.
+  #
+  # However, unlink-before-close may not be supported on non-POSIX operating
+  # systems. Microsoft Windows is the most notable case: unlinking a non-closed
+  # file will result in an error, which this method will silently ignore. If
+  # you want to practice unlink-before-close whenever possible, then you should
+  # write code like this:
+  #
+  #   file = Tempfile.new('foo')
+  #   file.unlink   # On Windows this silently fails.
+  #   begin
+  #      ... do something with file ...
+  #   ensure
+  #      file.close!   # Closes the file handle. If the file wasn't unlinked
+  #                    # because #unlink failed, then this method will attempt
+  #                    # to do so again.
+  #   end
   def unlink
     # keep this order for thread safeness
+    return unless @tmpname
     begin
-      File.unlink(@tmpname) if File.exist?(@tmpname)
-      @@cleanlist.delete(@tmpname)
+      if File.exist?(@tmpname)
+        File.unlink(@tmpname)
+      end
+      # remove tmpname from remover
+      @data[0] = @data[2] = nil
       @data = @tmpname = nil
-      ObjectSpace.undefine_finalizer(self)
     rescue Errno::EACCES
       # may not be able to unlink on Windows; just ignore
     end
@@ -147,6 +244,7 @@
   alias delete unlink
 
   # Returns the full path name of the temporary file.
+  # This will be nil if #unlink has been called.
   def path
     @tmpname
   end
@@ -157,37 +255,63 @@
     if @tmpfile
       @tmpfile.flush
       @tmpfile.stat.size
+    elsif @tmpname
+      File.size(@tmpname)
     else
       0
     end
   end
   alias length size
 
-  class << self
-    def callback(data)	# :nodoc:
-      pid = $$
-      Proc.new {
-	if pid == $$ 
-	  path, tmpfile, cleanlist = *data
+  # :stopdoc:
+  class Remover
+    def initialize(data)
+      @pid = $$
+      @data = data
+    end
 
-	  print "removing ", path, "..." if $DEBUG
+    def call(*args)
+      if @pid == $$
+        path, tmpfile = *@data
 
-	  tmpfile.close if tmpfile
+        STDERR.print "removing ", path, "..." if $DEBUG
 
-	  # keep this order for thread safeness
-	  File.unlink(path) if File.exist?(path)
-	  cleanlist.delete(path) if cleanlist
+        tmpfile.close if tmpfile
 
-	  print "done\n" if $DEBUG
-	end
-      }
+        # keep this order for thread safeness
+        if path
+          File.unlink(path) if File.exist?(path)
+        end
+
+        STDERR.print "done\n" if $DEBUG
+      end
     end
+  end
+  # :startdoc:
 
-    # If no block is given, this is a synonym for new().
+  class << self
+    # Creates a new Tempfile.
     #
-    # If a block is given, it will be passed tempfile as an argument,
-    # and the tempfile will automatically be closed when the block
-    # terminates.  In this case, open() returns nil.
+    # If no block is given, this is a synonym for Tempfile.new.
+    #
+    # If a block is given, then a Tempfile object will be constructed,
+    # and the block is run with said object as argument. The Tempfile
+    # oject will be automatically closed after the block terminates.
+    # The call returns the value of the block.
+    #
+    # In any case, all arguments (+*args+) will be passed to Tempfile.new.
+    #
+    #   Tempfile.open('foo', '/home/temp') do |f|
+    #      ... do something with f ...
+    #   end
+    #
+    #   # Equivalent:
+    #   f = Tempfile.open('foo', '/home/temp')
+    #   begin
+    #      ... do something with f ...
+    #   ensure
+    #      f.close
+    #   end
     def open(*args)
       tempfile = new(*args)
 
@@ -201,6 +325,13 @@
 	tempfile
       end
     end
+
+    def mkdir(*args)
+      Dir.mkdir(*args)
+    end
+    def rmdir(*args)
+      Dir.rmdir(*args)
+    end
   end
 end
 

Modified: MacRuby/trunk/lib/test/unit/assertions.rb
===================================================================
--- MacRuby/trunk/lib/test/unit/assertions.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/test/unit/assertions.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -10,6 +10,15 @@
         obj.pretty_inspect.chomp
       end
 
+      def assert(test, msg = (nomsg = true; nil))
+        unless nomsg or msg.instance_of?(String) or msg.instance_of?(Proc) or
+            (bt = caller).first.rindex(MiniTest::MINI_DIR, 0)
+          bt.delete_if {|s| s.rindex(MiniTest::MINI_DIR, 0)}
+          raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
+        end
+        super
+      end
+
       def assert_raise(*args, &b)
         assert_raises(*args, &b)
       end
@@ -28,7 +37,7 @@
           as = e.instance_of?(MiniTest::Assertion)
           if as
             ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
-            bt.reject! {|line| ans =~ line}
+            bt.reject! {|ln| ans =~ ln}
           end
           if ((args.empty? && !as) ||
               args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
@@ -67,8 +76,20 @@
               exp_str = "%\#.#{Float::DIG+2}g" % exp
               act_str = "%\#.#{Float::DIG+2}g" % act
             elsif exp.is_a?(Time) && act.is_a?(Time)
-              exp_comment = " (nsec=#{exp.nsec})"
-              act_comment = " (nsec=#{act.nsec})"
+              if exp.subsec * 1000_000_000 == exp.nsec
+                exp_comment = " (#{exp.nsec}[ns])"
+              else
+                exp_comment = " (subsec=#{exp.subsec})"
+              end
+              if act.subsec * 1000_000_000 == act.nsec
+                act_comment = " (#{act.nsec}[ns])"
+              else
+                act_comment = " (subsec=#{act.subsec})"
+              end
+            elsif exp.class != act.class
+              # a subclass of Range, for example.
+              exp_comment = " (#{exp.class})"
+              act_comment = " (#{act.class})"
             end
           elsif !Encoding.compatible?(exp_str, act_str)
             if exp.is_a?(String) && act.is_a?(String)
@@ -113,6 +134,17 @@
         assert(!actual.equal?(expected), msg)
       end
 
+      # get rid of overcounting
+      def assert_respond_to obj, meth, msg = nil
+        super if !caller[0].rindex(MiniTest::MINI_DIR, 0) || !obj.respond_to?(meth)
+      end
+
+      ms = instance_methods(true).map {|sym| sym.to_s }
+      ms.grep(/\Arefute_/) do |m|
+        mname = ('assert_not_' << m.to_s[/.*?_(.*)/, 1])
+        alias_method(mname, m) unless ms.include? mname
+      end
+
       def build_message(head, template=nil, *arguments)
         template &&= template.chomp
         template.gsub(/\?/) { mu_pp(arguments.shift) }

Modified: MacRuby/trunk/lib/test/unit/testcase.rb
===================================================================
--- MacRuby/trunk/lib/test/unit/testcase.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/test/unit/testcase.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -2,6 +2,9 @@
 
 module Test
   module Unit
+    # remove silly TestCase class
+    remove_const(:TestCase) if defined?(self::TestCase)
+
     class TestCase < MiniTest::Unit::TestCase
       include Assertions
       def self.test_order

Modified: MacRuby/trunk/lib/test/unit.rb
===================================================================
--- MacRuby/trunk/lib/test/unit.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/test/unit.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -16,12 +16,12 @@
       while arg = original_argv.shift
         case arg
         when '-v'
-          minitest_argv << '-v'
-        when '-n', '--name'
           minitest_argv << arg
-          minitest_argv << original_argv.shift
-        when '-x'
-          reject << original_argv.shift
+        when /\A(-n)(.+)?/, /\A(--name)=?\b(.+)?/
+          minitest_argv << $1
+          minitest_argv << ($2 || original_argv.shift)
+        when /\A-x(.+)?/
+          reject << ($1 || original_argv.shift)
         else
           files << arg
         end
@@ -32,7 +32,7 @@
       end
 
       files.map! {|f|
-        f = f.gsub(Regexp.compile(Regexp.quote(File::ALT_SEPARATOR)), File::SEPARATOR) if File::ALT_SEPARATOR
+        f = f.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
         if File.directory? f
           Dir["#{f}/**/test_*.rb"]
         elsif File.file? f
@@ -45,14 +45,14 @@
 
       reject_pat = Regexp.union(reject.map {|r| /#{r}/ })
       files.reject! {|f| reject_pat =~ f }
-        
+
       files.each {|f|
-        d = File.dirname(File.expand_path(f))
+        d = File.dirname(path = File.expand_path(f))
         unless $:.include? d
           $: << d
         end
         begin
-          require f
+          require path
         rescue LoadError
           puts "#{f}: #{$!}"
         end

Modified: MacRuby/trunk/lib/thread.rb
===================================================================
--- MacRuby/trunk/lib/thread.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/thread.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -20,7 +20,7 @@
   Thread.abort_on_exception = true
 end
 
-# 
+#
 # ConditionVariable objects augment class Mutex. Using condition variables,
 # it is possible to suspend while in the middle of a critical section until a
 # resource becomes available.
@@ -31,7 +31,7 @@
 #
 #   mutex = Mutex.new
 #   resource = ConditionVariable.new
-#   
+#
 #   a = Thread.new {
 #     mutex.synchronize {
 #       # Thread 'a' now needs the resource
@@ -39,7 +39,7 @@
 #       # 'a' can now have the resource
 #     }
 #   }
-#   
+#
 #   b = Thread.new {
 #     mutex.synchronize {
 #       # Thread 'b' has finished using the resource
@@ -55,20 +55,28 @@
     @waiters = []
     @waiters_mutex = Mutex.new
   end
-  
+
   #
   # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
   #
-  def wait(mutex)
+  # If +timeout+ is given, this method returns after +timeout+ seconds passed,
+  # even if no other thread doesn't signal.
+  #
+  def wait(mutex, timeout=nil)
     begin
       # TODO: mutex should not be used
       @waiters_mutex.synchronize do
         @waiters.push(Thread.current)
       end
-      mutex.sleep
+      mutex.sleep timeout
+    ensure
+      @waiters_mutex.synchronize do
+        @waiters.delete(Thread.current)
+      end
     end
+    self
   end
-  
+
   #
   # Wakes up the first thread in line waiting for this lock.
   #
@@ -79,8 +87,9 @@
     rescue ThreadError
       retry
     end
+    self
   end
-    
+
   #
   # Wakes up all threads waiting for this lock.
   #
@@ -93,10 +102,11 @@
     end
     for t in waiters0
       begin
-	t.run
+        t.run
       rescue ThreadError
       end
     end
+    self
   end
 end
 
@@ -106,9 +116,9 @@
 # Example:
 #
 #   require 'thread'
-#   
+#
 #   queue = Queue.new
-#   
+#
 #   producer = Thread.new do
 #     5.times do |i|
 #       sleep rand(i) # simulate expense
@@ -116,7 +126,7 @@
 #       puts "#{i} produced"
 #     end
 #   end
-#   
+#
 #   consumer = Thread.new do
 #     5.times do |i|
 #       value = queue.pop
@@ -124,7 +134,7 @@
 #       puts "consumed #{value}"
 #     end
 #   end
-#   
+#
 #   consumer.join
 #
 class Queue
@@ -144,7 +154,6 @@
   # Pushes +obj+ to the queue.
   #
   def push(obj)
-    t = nil
     @mutex.synchronize{
       @que.push obj
       begin
@@ -154,10 +163,6 @@
         retry
       end
     }
-    begin
-      t.run if t
-    rescue ThreadError
-    end
   end
 
   #
@@ -176,8 +181,8 @@
   # thread isn't suspended, and an exception is raised.
   #
   def pop(non_block=false)
-    while true
-      @mutex.synchronize{
+    @mutex.synchronize{
+      while true
         if @que.empty?
           raise ThreadError, "queue empty" if non_block
           @waiting.push Thread.current
@@ -185,8 +190,8 @@
         else
           return @que.shift
         end
-      }
-    end
+      end
+    }
   end
 
   #
@@ -289,14 +294,13 @@
   # until space becomes available.
   #
   def push(obj)
-    t = nil
     @mutex.synchronize{
       while true
-        break if @que.length <= @max
+        break if @que.length < @max
         @queue_wait.push Thread.current
         @mutex.sleep
       end
-    
+
       @que.push obj
       begin
         t = @waiting.shift
@@ -305,11 +309,6 @@
         retry
       end
     }
-    
-    begin
-      t.run if t
-    rescue ThreadError
-    end
   end
 
   #
@@ -327,7 +326,6 @@
   #
   def pop(*args)
     retval = super
-    t = nil
     @mutex.synchronize {
       if @que.length < @max
         begin
@@ -338,10 +336,6 @@
         end
       end
     }
-    begin
-      t.run if t
-    rescue ThreadError
-    end
     retval
   end
 

Modified: MacRuby/trunk/lib/thwait.rb
===================================================================
--- MacRuby/trunk/lib/thwait.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/thwait.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -2,38 +2,7 @@
 #   thwait.rb - thread synchronization class
 #   	$Release Version: 0.9 $
 #   	$Revision: 1.3 $
-#   	by Keiju ISHITSUKA(Nihpon Rational Software Co.,Ltd.)
-#
-# --
-#  feature:
-#  provides synchronization for multiple threads.
-#
-#  class methods:
-#  * ThreadsWait.all_waits(thread1,...)
-#    waits until all of specified threads are terminated.
-#    if a block is supplied for the method, evaluates it for
-#    each thread termination.
-#  * th = ThreadsWait.new(thread1,...)
-#    creates synchronization object, specifying thread(s) to wait.
-#  
-#  methods:
-#  * th.threads
-#    list threads to be synchronized
-#  * th.empty?
-#    is there any thread to be synchronized.
-#  * th.finished?
-#    is there already terminated thread.
-#  * th.join(thread1,...) 
-#    wait for specified thread(s).
-#  * th.join_nowait(threa1,...)
-#    specifies thread(s) to wait.  non-blocking.
-#  * th.next_wait
-#    waits until any of specified threads is terminated.
-#  * th.all_waits
-#    waits until all of specified threads are terminated.
-#    if a block is supplied for the method, evaluates it for
-#    each thread termination.
-#
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd.)
 
 require "thread.rb"
 require "e2mmap.rb"
@@ -50,16 +19,21 @@
 #     STDERR.puts "Thread #{t} has terminated."
 #   end
 #
+#   
+#   th = ThreadsWait.new(thread1,...)
+#   th.next_wait # next one to be done
+#    
+#
 class ThreadsWait
   RCS_ID='-$Id: thwait.rb,v 1.3 1998/06/26 03:19:34 keiju Exp keiju $-'
-  
+
   extend Exception2MessageMapper
   def_exception("ErrNoWaitingThread", "No threads for waiting.")
   def_exception("ErrNoFinishedThread", "No finished threads.")
-  
+
   #
   # Waits until all specified threads have terminated.  If a block is provided,
-  # it is executed for each thread termination.
+  # it is executed for each thread as they terminate.
   #
   def ThreadsWait.all_waits(*threads) # :yield: thread
     tw = ThreadsWait.new(*threads)
@@ -71,7 +45,7 @@
       tw.all_waits
     end
   end
-  
+
   #
   # Creates a ThreadsWait object, specifying the threads to wait on.
   # Non-blocking.
@@ -81,32 +55,33 @@
     @wait_queue = Queue.new
     join_nowait(*threads) unless threads.empty?
   end
-  
-  # Returns the array of threads in the wait queue.
+
+  # Returns the array of threads that have not terminated yet.
   attr :threads
-  
+
   #
-  # Returns +true+ if there are no threads to be synchronized.
+  # Returns +true+ if there are no threads in the pool still running.
   #
   def empty?
     @threads.empty?
   end
-  
+
   #
-  # Returns +true+ if any thread has terminated.
+  # Returns +true+ if any thread has terminated and is ready to be collected.
   #
   def finished?
     !@wait_queue.empty?
   end
-  
+
   #
-  # Waits for specified threads to terminate.
+  # Waits for specified threads to terminate, and returns when one of
+  # the threads terminated.
   #
   def join(*threads)
     join_nowait(*threads)
     next_wait
   end
-  
+
   #
   # Specifies the threads that this object will wait for, but does not actually
   # wait.
@@ -124,7 +99,7 @@
       end
     end
   end
-  
+
   #
   # Waits until any of the specified threads has terminated, and returns the one
   # that does.
@@ -141,7 +116,7 @@
       ThreadsWait.fail ErrNoFinishedThread
     end
   end
-  
+
   #
   # Waits until all of the specified threads are terminated.  If a block is
   # supplied for the method, it is executed for each thread termination.

Modified: MacRuby/trunk/lib/time.rb
===================================================================
--- MacRuby/trunk/lib/time.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/time.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -35,10 +35,6 @@
 #   %z is required to generate zone in date-time of RFC 2822
 #   but it is not portable.
 #
-# == Revision Information
-#
-# $Id$
-#
 
 require 'date/format'
 
@@ -102,7 +98,7 @@
       #   In RFC 3339, -00:00 is used for the time in UTC is known,
       #   but the offset to local time is unknown.
       #   They are not appropriate for specific time zone such as
-      #   Europe/London because time zone neutral, 
+      #   Europe/London because time zone neutral,
       #   So -00:00 and -0000 are treated as UTC.
       if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone
         true
@@ -210,7 +206,7 @@
     # If a block is given, the year described in +date+ is converted by the
     # block.  For example:
     #
-    #     Time.parse(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
+    #     Time.parse(...) {|y| 0 <= y && y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
     #
     # If the upper components of the given time are broken or missing, they are
     # supplied with those of +now+.  For the lower components, the minimum
@@ -218,9 +214,11 @@
     #
     #     # Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
     #     # your timezone is GMT:
-    #     Time.parse("16:30")     #=> Thu Nov 29 16:30:00 GMT 2001
-    #     Time.parse("7/23")      #=> Mon Jul 23 00:00:00 GMT 2001
-    #     Time.parse("Aug 31")    #=> Fri Aug 31 00:00:00 GMT 2001
+    #     now = Time.parse("Thu Nov 29 14:33:20 GMT 2001")
+    #     Time.parse("16:30", now)     #=> 2001-11-29 16:30:00 +0900
+    #     Time.parse("7/23", now)      #=> 2001-07-23 00:00:00 +0900
+    #     Time.parse("Aug 31", now)    #=> 2001-08-31 00:00:00 +0900
+    #     Time.parse("Aug 2000", now)  #=> 2000-08-01 00:00:00 +0900
     #
     # Since there are numerous conflicts among locally defined timezone
     # abbreviations all over the world, this method is not made to
@@ -254,10 +252,18 @@
     #
     # A failure for Time.parse should be checked, though.
     #
+    # time library should be required to use this method as follows.
+    #
+    #     require 'time'
+    #
     def parse(date, now=self.now)
-      d = Date._parse(date, false)
+      comp = !block_given?
+      d = Date._parse(date, comp)
+      if !d[:year] && !d[:mon] && !d[:mday] && !d[:hour] && !d[:min] && !d[:sec] && !d[:sec_fraction]
+        raise ArgumentError, "no time information in #{date.inspect}"
+      end
       year = d[:year]
-      year = yield(year) if year && block_given?
+      year = yield(year) if year && !comp
       make_time(year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
     end
 
@@ -291,6 +297,10 @@
     #
     # See #rfc2822 for more information on this format.
     #
+    # time library should be required to use this method as follows.
+    #
+    #     require 'time'
+    #
     def rfc2822(date)
       if /\A\s*
           (?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
@@ -340,6 +350,10 @@
     #
     # See #httpdate for more information on this format.
     #
+    # time library should be required to use this method as follows.
+    #
+    #     require 'time'
+    #
     def httpdate(date)
       if /\A\s*
           (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
@@ -387,6 +401,10 @@
     #
     # See #xmlschema for more information on this format.
     #
+    # time library should be required to use this method as follows.
+    #
+    #     require 'time'
+    #
     def xmlschema(date)
       if /\A\s*
           (-?\d+)-(\d\d)-(\d\d)
@@ -429,10 +447,14 @@
   #
   # If +self+ is a UTC time, -0000 is used as zone.
   #
+  # time library should be required to use this method as follows.
+  #
+  #     require 'time'
+  #
   def rfc2822
-    sprintf('%s, %02d %s %d %02d:%02d:%02d ',
+    sprintf('%s, %02d %s %0*d %02d:%02d:%02d ',
       RFC2822_DAY_NAME[wday],
-      day, RFC2822_MONTH_NAME[mon-1], year,
+      day, RFC2822_MONTH_NAME[mon-1], year < 0 ? 5 : 4, year,
       hour, min, sec) +
     if utc?
       '-0000'
@@ -460,11 +482,15 @@
   #
   # Note that the result is always UTC (GMT).
   #
+  # time library should be required to use this method as follows.
+  #
+  #     require 'time'
+  #
   def httpdate
     t = dup.utc
-    sprintf('%s, %02d %s %d %02d:%02d:%02d GMT',
+    sprintf('%s, %02d %s %0*d %02d:%02d:%02d GMT',
       RFC2822_DAY_NAME[t.wday],
-      t.day, RFC2822_MONTH_NAME[t.mon-1], t.year,
+      t.day, RFC2822_MONTH_NAME[t.mon-1], t.year < 0 ? 5 : 4, t.year,
       t.hour, t.min, t.sec)
   end
 
@@ -482,15 +508,17 @@
   # +fractional_seconds+ specifies a number of digits of fractional seconds.
   # Its default value is 0.
   #
+  # time library should be required to use this method as follows.
+  #
+  #     require 'time'
+  #
   def xmlschema(fraction_digits=0)
-    sprintf('%d-%02d-%02dT%02d:%02d:%02d',
-      year, mon, day, hour, min, sec) +
+    sprintf('%0*d-%02d-%02dT%02d:%02d:%02d',
+      year < 0 ? 5 : 4, year, mon, day, hour, min, sec) +
     if fraction_digits == 0
       ''
-    elsif fraction_digits <= 9
-      '.' + sprintf('%09d', nsec)[0, fraction_digits]
     else
-      '.' + sprintf('%09d', nsec) + '0' * (fraction_digits - 9)
+      '.' + sprintf('%0*d', fraction_digits, (subsec * 10**fraction_digits).floor)
     end +
     if utc?
       'Z'
@@ -503,367 +531,3 @@
   alias iso8601 xmlschema
 end
 
-if __FILE__ == $0
-  require 'test/unit'
-
-  class TimeExtentionTest < Test::Unit::TestCase # :nodoc:
-    def test_rfc822
-      assert_equal(Time.utc(1976, 8, 26, 14, 30) + 4 * 3600,
-                   Time.rfc2822("26 Aug 76 14:30 EDT"))
-      assert_equal(Time.utc(1976, 8, 27, 9, 32) + 7 * 3600,
-                   Time.rfc2822("27 Aug 76 09:32 PDT"))
-    end
-
-    def test_rfc2822
-      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600,
-                   Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600"))
-      assert_equal(Time.utc(2003, 7, 1, 10, 52, 37) - 2 * 3600,
-                   Time.rfc2822("Tue, 1 Jul 2003 10:52:37 +0200"))
-      assert_equal(Time.utc(1997, 11, 21, 10, 1, 10) + 6 * 3600,
-                   Time.rfc2822("Fri, 21 Nov 1997 10:01:10 -0600"))
-      assert_equal(Time.utc(1997, 11, 21, 11, 0, 0) + 6 * 3600,
-                   Time.rfc2822("Fri, 21 Nov 1997 11:00:00 -0600"))
-      assert_equal(Time.utc(1997, 11, 24, 14, 22, 1) + 8 * 3600,
-                   Time.rfc2822("Mon, 24 Nov 1997 14:22:01 -0800"))
-      begin
-        Time.at(-1)
-      rescue ArgumentError
-        # ignore
-      else
-        assert_equal(Time.utc(1969, 2, 13, 23, 32, 54) + 3 * 3600 + 30 * 60,
-                     Time.rfc2822("Thu, 13 Feb 1969 23:32:54 -0330"))
-        assert_equal(Time.utc(1969, 2, 13, 23, 32, 0) + 3 * 3600 + 30 * 60,
-                     Time.rfc2822(" Thu,
-        13
-          Feb
-            1969
-        23:32
-                 -0330 (Newfoundland Time)"))
-      end
-      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6),
-                   Time.rfc2822("21 Nov 97 09:55:06 GMT"))
-      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600,
-                   Time.rfc2822("Fri, 21 Nov 1997 09 :   55  :  06 -0600"))
-      assert_raise(ArgumentError) {
-        # inner comment is not supported.
-        Time.rfc2822("Fri, 21 Nov 1997 09(comment):   55  :  06 -0600")
-      }
-    end
-
-    def test_rfc2616
-      t = Time.utc(1994, 11, 6, 8, 49, 37)
-      assert_equal(t, Time.httpdate("Sun, 06 Nov 1994 08:49:37 GMT"))
-      assert_equal(t, Time.httpdate("Sunday, 06-Nov-94 08:49:37 GMT"))
-      assert_equal(t, Time.httpdate("Sun Nov  6 08:49:37 1994"))
-      assert_equal(Time.utc(1995, 11, 15, 6, 25, 24),
-                   Time.httpdate("Wed, 15 Nov 1995 06:25:24 GMT"))
-      assert_equal(Time.utc(1995, 11, 15, 4, 58, 8),
-                   Time.httpdate("Wed, 15 Nov 1995 04:58:08 GMT"))
-      assert_equal(Time.utc(1994, 11, 15, 8, 12, 31),
-                   Time.httpdate("Tue, 15 Nov 1994 08:12:31 GMT"))
-      assert_equal(Time.utc(1994, 12, 1, 16, 0, 0),
-                   Time.httpdate("Thu, 01 Dec 1994 16:00:00 GMT"))
-      assert_equal(Time.utc(1994, 10, 29, 19, 43, 31),
-                   Time.httpdate("Sat, 29 Oct 1994 19:43:31 GMT"))
-      assert_equal(Time.utc(1994, 11, 15, 12, 45, 26),
-                   Time.httpdate("Tue, 15 Nov 1994 12:45:26 GMT"))
-      assert_equal(Time.utc(1999, 12, 31, 23, 59, 59),
-                   Time.httpdate("Fri, 31 Dec 1999 23:59:59 GMT"))
-
-      assert_equal(Time.utc(2007, 12, 23, 11, 22, 33),
-                   Time.httpdate('Sunday, 23-Dec-07 11:22:33 GMT'))
-    end
-
-    def test_rfc3339
-      t = Time.utc(1985, 4, 12, 23, 20, 50, 520000)
-      s = "1985-04-12T23:20:50.52Z"
-      assert_equal(t, Time.iso8601(s))
-      assert_equal(s, t.iso8601(2))
-
-      t = Time.utc(1996, 12, 20, 0, 39, 57)
-      s = "1996-12-19T16:39:57-08:00"
-      assert_equal(t, Time.iso8601(s))
-      # There is no way to generate time string with arbitrary timezone.
-      s = "1996-12-20T00:39:57Z"
-      assert_equal(t, Time.iso8601(s))
-      assert_equal(s, t.iso8601)
-
-      t = Time.utc(1990, 12, 31, 23, 59, 60)
-      s = "1990-12-31T23:59:60Z"
-      assert_equal(t, Time.iso8601(s))
-      # leap second is representable only if timezone file has it.
-      s = "1990-12-31T15:59:60-08:00"
-      assert_equal(t, Time.iso8601(s))
-
-      begin
-        Time.at(-1)
-      rescue ArgumentError
-        # ignore
-      else
-        t = Time.utc(1937, 1, 1, 11, 40, 27, 870000)
-        s = "1937-01-01T12:00:27.87+00:20"
-        assert_equal(t, Time.iso8601(s))
-      end
-    end
-
-    # http://www.w3.org/TR/xmlschema-2/
-    def test_xmlschema
-      assert_equal(Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600,
-                   Time.xmlschema("1999-05-31T13:20:00-05:00"))
-      assert_equal(Time.local(2000, 1, 20, 12, 0, 0),
-                   Time.xmlschema("2000-01-20T12:00:00"))
-      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0),
-                   Time.xmlschema("2000-01-20T12:00:00Z"))
-      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600,
-                   Time.xmlschema("2000-01-20T12:00:00+12:00"))
-      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600,
-                   Time.xmlschema("2000-01-20T12:00:00-13:00"))
-      assert_equal(Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600,
-                   Time.xmlschema("2000-03-04T23:00:00+03:00"))
-      assert_equal(Time.utc(2000, 3, 4, 20, 0, 0),
-                   Time.xmlschema("2000-03-04T20:00:00Z"))
-      assert_equal(Time.local(2000, 1, 15, 0, 0, 0),
-                   Time.xmlschema("2000-01-15T00:00:00"))
-      assert_equal(Time.local(2000, 2, 15, 0, 0, 0),
-                   Time.xmlschema("2000-02-15T00:00:00"))
-      assert_equal(Time.local(2000, 1, 15, 12, 0, 0),
-                   Time.xmlschema("2000-01-15T12:00:00"))
-      assert_equal(Time.utc(2000, 1, 16, 12, 0, 0),
-                   Time.xmlschema("2000-01-16T12:00:00Z"))
-      assert_equal(Time.local(2000, 1, 1, 12, 0, 0),
-                   Time.xmlschema("2000-01-01T12:00:00"))
-      assert_equal(Time.utc(1999, 12, 31, 23, 0, 0),
-                   Time.xmlschema("1999-12-31T23:00:00Z"))
-      assert_equal(Time.local(2000, 1, 16, 12, 0, 0),
-                   Time.xmlschema("2000-01-16T12:00:00"))
-      assert_equal(Time.local(2000, 1, 16, 0, 0, 0),
-                   Time.xmlschema("2000-01-16T00:00:00"))
-      assert_equal(Time.utc(2000, 1, 12, 12, 13, 14),
-                   Time.xmlschema("2000-01-12T12:13:14Z"))
-      assert_equal(Time.utc(2001, 4, 17, 19, 23, 17, 300000),
-                   Time.xmlschema("2001-04-17T19:23:17.3Z"))
-      assert_raise(ArgumentError) { Time.xmlschema("2000-01-01T00:00:00.+00:00") }
-    end
-
-    def test_encode_xmlschema
-      t = Time.utc(2001, 4, 17, 19, 23, 17, 300000)
-      assert_equal("2001-04-17T19:23:17Z", t.xmlschema)
-      assert_equal("2001-04-17T19:23:17.3Z", t.xmlschema(1))
-      assert_equal("2001-04-17T19:23:17.300000Z", t.xmlschema(6))
-      assert_equal("2001-04-17T19:23:17.3000000Z", t.xmlschema(7))
-
-      t = Time.utc(2001, 4, 17, 19, 23, 17, 123456)
-      assert_equal("2001-04-17T19:23:17.1234560Z", t.xmlschema(7))
-      assert_equal("2001-04-17T19:23:17.123456Z", t.xmlschema(6))
-      assert_equal("2001-04-17T19:23:17.12345Z", t.xmlschema(5))
-      assert_equal("2001-04-17T19:23:17.1Z", t.xmlschema(1))
-
-      begin
-        Time.at(-1)
-      rescue ArgumentError
-        # ignore
-      else
-        t = Time.utc(1960, 12, 31, 23, 0, 0, 123456)
-        assert_equal("1960-12-31T23:00:00.123456Z", t.xmlschema(6))
-      end
-
-      assert_equal(249, Time.xmlschema("2008-06-05T23:49:23.000249+09:00").usec)
-    end
-
-    def test_completion
-      now = Time.local(2001,11,29,21,26,35)
-      assert_equal(Time.local( 2001,11,29,21,12),
-                   Time.parse("2001/11/29 21:12", now))
-      assert_equal(Time.local( 2001,11,29),
-                   Time.parse("2001/11/29", now))
-      assert_equal(Time.local( 2001,11,29),
-                   Time.parse(     "11/29", now))
-      #assert_equal(Time.local(2001,11,1), Time.parse("Nov", now))
-      assert_equal(Time.local( 2001,11,29,10,22),
-                   Time.parse(           "10:22", now))
-    end
-
-    def test_invalid
-      # They were actually used in some web sites.
-      assert_raise(ArgumentError) { Time.httpdate("1 Dec 2001 10:23:57 GMT") }
-      assert_raise(ArgumentError) { Time.httpdate("Sat, 1 Dec 2001 10:25:42 GMT") }
-      assert_raise(ArgumentError) { Time.httpdate("Sat,  1-Dec-2001 10:53:55 GMT") }
-      assert_raise(ArgumentError) { Time.httpdate("Saturday, 01-Dec-2001 10:15:34 GMT") }
-      assert_raise(ArgumentError) { Time.httpdate("Saturday, 01-Dec-101 11:10:07 GMT") }
-      assert_raise(ArgumentError) { Time.httpdate("Fri, 30 Nov 2001 21:30:00 JST") }
-
-      # They were actually used in some mails.
-      assert_raise(ArgumentError) { Time.rfc2822("01-5-20") }
-      assert_raise(ArgumentError) { Time.rfc2822("7/21/00") }
-      assert_raise(ArgumentError) { Time.rfc2822("2001-8-28") }
-      assert_raise(ArgumentError) { Time.rfc2822("00-5-6 1:13:06") }
-      assert_raise(ArgumentError) { Time.rfc2822("2001-9-27 9:36:49") }
-      assert_raise(ArgumentError) { Time.rfc2822("2000-12-13 11:01:11") }
-      assert_raise(ArgumentError) { Time.rfc2822("2001/10/17 04:29:55") }
-      assert_raise(ArgumentError) { Time.rfc2822("9/4/2001 9:23:19 PM") }
-      assert_raise(ArgumentError) { Time.rfc2822("01 Nov 2001 09:04:31") }
-      assert_raise(ArgumentError) { Time.rfc2822("13 Feb 2001 16:4 GMT") }
-      assert_raise(ArgumentError) { Time.rfc2822("01 Oct 00 5:41:19 PM") }
-      assert_raise(ArgumentError) { Time.rfc2822("2 Jul 00 00:51:37 JST") }
-      assert_raise(ArgumentError) { Time.rfc2822("01 11 2001 06:55:57 -0500") }
-      assert_raise(ArgumentError) { Time.rfc2822("18 \343\366\356\341\370 2000") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, Oct 2001  18:53:32") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 2 Nov 2001 03:47:54") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 27 Jul 2001 11.14.14 +0200") }
-      assert_raise(ArgumentError) { Time.rfc2822("Thu, 2 Nov 2000 04:13:53 -600") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wed, 5 Apr 2000 22:57:09 JST") }
-      assert_raise(ArgumentError) { Time.rfc2822("Mon, 11 Sep 2000 19:47:33 00000") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 28 Apr 2000 20:40:47 +-900") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 19 Jan 2001 8:15:36 AM -0500") }
-      assert_raise(ArgumentError) { Time.rfc2822("Thursday, Sep 27 2001 7:42:35 AM EST") }
-      assert_raise(ArgumentError) { Time.rfc2822("3/11/2001 1:31:57 PM Pacific Daylight Time") }
-      assert_raise(ArgumentError) { Time.rfc2822("Mi, 28 Mrz 2001 11:51:36") }
-      assert_raise(ArgumentError) { Time.rfc2822("P, 30 sept 2001 23:03:14") }
-      assert_raise(ArgumentError) { Time.rfc2822("fr, 11 aug 2000 18:39:22") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fr, 21 Sep 2001 17:44:03 -1000") }
-      assert_raise(ArgumentError) { Time.rfc2822("Mo, 18 Jun 2001 19:21:40 -1000") }
-      assert_raise(ArgumentError) { Time.rfc2822("l\366, 12 aug 2000 18:53:20") }
-      assert_raise(ArgumentError) { Time.rfc2822("l\366, 26 maj 2001 00:15:58") }
-      assert_raise(ArgumentError) { Time.rfc2822("Dom, 30 Sep 2001 17:36:30") }
-      assert_raise(ArgumentError) { Time.rfc2822("%&, 31 %2/ 2000 15:44:47 -0500") }
-      assert_raise(ArgumentError) { Time.rfc2822("dom, 26 ago 2001 03:57:07 -0300") }
-      assert_raise(ArgumentError) { Time.rfc2822("ter, 04 set 2001 16:27:58 -0300") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wen, 3 oct 2001 23:17:49 -0400") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wen, 3 oct 2001 23:17:49 -0400") }
-      assert_raise(ArgumentError) { Time.rfc2822("ele, 11 h: 2000 12:42:15 -0500") }
-      assert_raise(ArgumentError) { Time.rfc2822("Tue, 14 Aug 2001 3:55:3 +0200") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 25 Aug 2000 9:3:48 +0800") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 1 Dec 2000 0:57:50 EST") }
-      assert_raise(ArgumentError) { Time.rfc2822("Mon, 7 May 2001 9:39:51 +0200") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wed, 1 Aug 2001 16:9:15 +0200") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wed, 23 Aug 2000 9:17:36 +0800") }
-      assert_raise(ArgumentError) { Time.rfc2822("Fri, 11 Aug 2000 10:4:42 +0800") }
-      assert_raise(ArgumentError) { Time.rfc2822("Sat, 15 Sep 2001 13:22:2 +0300") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wed,16 \276\305\324\302 2001 20:06:25 +0800") }
-      assert_raise(ArgumentError) { Time.rfc2822("Wed,7 \312\256\322\273\324\302 2001 23:47:22 +0800") }
-      assert_raise(ArgumentError) { Time.rfc2822("=?iso-8859-1?Q?(=C5=DA),?= 10   2 2001 23:32:26 +0900 (JST)") }
-      assert_raise(ArgumentError) { Time.rfc2822("\307\341\314\343\332\311, 30 \344\346\335\343\310\321 2001 10:01:06") }
-      assert_raise(ArgumentError) { Time.rfc2822("=?iso-8859-1?Q?(=BF=E5),?= 12  =?iso-8859-1?Q?9=B7=EE?= 2001 14:52:41\n+0900 (JST)") }
-    end
-
-    def test_zone_0000
-      assert_equal(true, Time.parse("2000-01-01T00:00:00Z").utc?)
-      assert_equal(true, Time.parse("2000-01-01T00:00:00-00:00").utc?)
-      assert_equal(false, Time.parse("2000-01-01T00:00:00+00:00").utc?)
-      assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
-      assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
-      assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
-      assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
-      assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
-      assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
-      assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 UTC").utc?)
-    end
-
-    def test_rfc2822_utc_roundtrip_winter
-      t1 = Time.local(2008,12,1)
-      t2 = Time.rfc2822(t1.rfc2822)
-      assert_equal(t1.utc?, t2.utc?, "[ruby-dev:37126]")
-    end
-
-    def test_rfc2822_utc_roundtrip_summer
-      t1 = Time.local(2008,8,1)
-      t2 = Time.rfc2822(t1.rfc2822)
-      assert_equal(t1.utc?, t2.utc?)
-    end
-
-    def test_parse_leap_second
-      t = Time.utc(1998,12,31,23,59,59)
-      assert_equal(t, Time.parse("Thu Dec 31 23:59:59 UTC 1998"))
-      assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998"));t.localtime
-      assert_equal(t, Time.parse("Fri Jan  1 08:59:59 +0900 1999"))
-      assert_equal(t, Time.parse("Fri Jan  1 00:59:59 +0100 1999"))
-      assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998"))
-      assert_equal(t, Time.parse("Fri Dec 31 22:59:59 -0100 1998"));t.utc
-      t += 1
-      assert_equal(t, Time.parse("Thu Dec 31 23:59:60 UTC 1998"))
-      assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998"));t.localtime
-      assert_equal(t, Time.parse("Fri Jan  1 08:59:60 +0900 1999"))
-      assert_equal(t, Time.parse("Fri Jan  1 00:59:60 +0100 1999"))
-      assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998"))
-      assert_equal(t, Time.parse("Fri Dec 31 22:59:60 -0100 1998"));t.utc
-      t += 1 if t.sec == 60
-      assert_equal(t, Time.parse("Thu Jan  1 00:00:00 UTC 1999"))
-      assert_equal(t, Time.parse("Fri Jan  1 00:00:00 -0000 1999"));t.localtime
-      assert_equal(t, Time.parse("Fri Jan  1 09:00:00 +0900 1999"))
-      assert_equal(t, Time.parse("Fri Jan  1 01:00:00 +0100 1999"))
-      assert_equal(t, Time.parse("Fri Jan  1 00:00:00 +0000 1999"))
-      assert_equal(t, Time.parse("Fri Dec 31 23:00:00 -0100 1998"))
-    end
-
-    def test_rfc2822_leap_second
-      t = Time.utc(1998,12,31,23,59,59)
-      assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:59 UTC"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 08:59:59 +0900"))
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:59:59 +0100"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc
-      t += 1
-      assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:60 UTC"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 08:59:60 +0900"))
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:59:60 +0100"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc
-      t += 1 if t.sec == 60
-      assert_equal(t, Time.rfc2822("Thu,  1 Jan 1999 00:00:00 UTC"))
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:00:00 -0000"));t.localtime
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 09:00:00 +0900"))
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 01:00:00 +0100"))
-      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:00:00 +0000"))
-      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:00:00 -0100"))
-    end
-
-    def test_xmlschema_leap_second
-      t = Time.utc(1998,12,31,23,59,59)
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59Z"))
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00"));t.localtime
-      assert_equal(t, Time.xmlschema("1999-01-01T08:59:59+09:00"))
-      assert_equal(t, Time.xmlschema("1999-01-01T00:59:59+01:00"))
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00"))
-      assert_equal(t, Time.xmlschema("1998-12-31T22:59:59-01:00"));t.utc
-      t += 1
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60Z"))
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00"));t.localtime
-      assert_equal(t, Time.xmlschema("1999-01-01T08:59:60+09:00"))
-      assert_equal(t, Time.xmlschema("1999-01-01T00:59:60+01:00"))
-      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00"))
-      assert_equal(t, Time.xmlschema("1998-12-31T22:59:60-01:00"));t.utc
-      t += 1 if t.sec == 60
-      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00Z"))
-      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00"));t.localtime
-      assert_equal(t, Time.xmlschema("1999-01-01T09:00:00+09:00"))
-      assert_equal(t, Time.xmlschema("1999-01-01T01:00:00+01:00"))
-      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00"))
-      assert_equal(t, Time.xmlschema("1998-12-31T23:00:00-01:00"))
-    end
-
-    def test_xmlschema_fraction
-      assert_equal(500000, Time.xmlschema("2000-01-01T00:00:00.5+00:00").tv_usec)
-    end
-
-    def test_ruby_talk_152866
-      t = Time::xmlschema('2005-08-30T22:48:00-07:00')
-      assert_equal(31, t.day)
-      assert_equal(8, t.mon)
-    end
-
-    def test_parse_fraction
-      assert_equal(500000, Time.parse("2000-01-01T00:00:00.5+00:00").tv_usec)
-    end
-
-    def test_strptime
-      assert_equal(Time.utc(2005, 8, 28, 06, 54, 20), Time.strptime("28/Aug/2005:06:54:20 +0000", "%d/%b/%Y:%T %z"))
-    end
-
-    def test_nsec
-      assert_equal(123456789, Time.xmlschema("2000-01-01T00:00:00.123456789+00:00").tv_nsec)
-      assert_equal(123456789, Time.parse("2000-01-01T00:00:00.123456789+00:00").tv_nsec)
-    end
-  end
-end

Modified: MacRuby/trunk/lib/timeout.rb
===================================================================
--- MacRuby/trunk/lib/timeout.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/timeout.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -46,8 +46,13 @@
     begin
       x = Thread.current
       y = Thread.start {
-        sleep sec
-        x.raise exception, "execution expired" if x.alive?
+        begin
+          sleep sec
+        rescue => e
+          x.raise e
+        else
+          x.raise exception, "execution expired" if x.alive?
+        end
       }
       return yield(sec)
     rescue exception => e
@@ -63,7 +68,7 @@
       raise Error, e.message, e.backtrace
     ensure
       if y and y.alive?
-        y.kill 
+        y.kill
         y.join # make sure y is dead.
       end
     end
@@ -85,24 +90,3 @@
 # Another name for Timeout::Error, defined for backwards compatibility with
 # earlier versions of timeout.rb.
 TimeoutError = Timeout::Error
-
-if __FILE__ == $0
-  p timeout(5) {
-    45
-  }
-  p timeout(5, TimeoutError) {
-    45
-  }
-  p timeout(nil) {
-    54
-  }
-  p timeout(0) {
-    54
-  }
-  p timeout(5) {
-    loop {
-      p 10
-      sleep 1
-    }
-  }
-end

Modified: MacRuby/trunk/lib/tmpdir.rb
===================================================================
--- MacRuby/trunk/lib/tmpdir.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/tmpdir.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,38 +1,19 @@
 #
 # tmpdir - retrieve temporary directory path
 #
-# $Id: tmpdir.rb 19513 2008-09-24 05:39:39Z usa $
+# $Id: tmpdir.rb 27667 2010-05-08 03:25:17Z nobu $
 #
 
 require 'fileutils'
+begin
+  require 'etc.so'
+rescue LoadError
+end
 
 class Dir
 
-  @@systmpdir = '/tmp'
+  @@systmpdir ||= defined?(Etc.systmpdir) ? Etc.systmpdir : '/tmp'
 
-  begin
-    require 'Win32API'
-    CSIDL_LOCAL_APPDATA = 0x001c
-    max_pathlen = 260
-    windir = "\0"*(max_pathlen+1)
-    begin
-      getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
-      raise RuntimeError if getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir) != 0
-      windir = File.expand_path(windir.rstrip)
-    rescue RuntimeError
-      begin
-        getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L')
-      rescue RuntimeError
-        getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L')
-      end
-      len = getdir.call(windir, windir.size)
-      windir = File.expand_path(windir[0, len])
-    end
-    temp = File.join(windir.untaint, 'temp')
-    @@systmpdir = temp if File.directory?(temp) and File.writable?(temp)
-  rescue LoadError
-  end
-
   ##
   # Returns the operating system's temporary file path.
 
@@ -41,12 +22,11 @@
     if $SAFE > 0
       tmp = @@systmpdir
     else
-      for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'],
-	          ENV['USERPROFILE'], @@systmpdir, '/tmp']
-	if dir and File.directory?(dir) and File.writable?(dir)
+      for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
+	if dir and stat = File.stat(dir) and stat.directory? and stat.writable?
 	  tmp = dir
 	  break
-	end
+	end rescue nil
       end
       File.expand_path(tmp)
     end
@@ -96,41 +76,67 @@
   #    FileUtils.remove_entry_secure dir
   #  end
   #
-  def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil)
-    case prefix_suffix
-    when nil
-      prefix = "d"
-      suffix = ""
-    when String
-      prefix = prefix_suffix
-      suffix = ""
-    when Array
-      prefix = prefix_suffix[0]
-      suffix = prefix_suffix[1]
+  def Dir.mktmpdir(prefix_suffix=nil, *rest)
+    path = Tmpname.create(prefix_suffix || "d", *rest) {|n| mkdir(n, 0700)}
+    if block_given?
+      begin
+        yield path
+      ensure
+        FileUtils.remove_entry_secure path
+      end
     else
-      raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
+      path
     end
-    tmpdir ||= Dir.tmpdir
-    t = Time.now.strftime("%Y%m%d")
-    n = nil
-    begin
-      path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
+  end
+
+  module Tmpname # :nodoc:
+    module_function
+
+    def tmpdir
+      Dir.tmpdir
+    end
+
+    def make_tmpname(prefix_suffix, n)
+      case prefix_suffix
+      when String
+        prefix = prefix_suffix
+        suffix = ""
+      when Array
+        prefix = prefix_suffix[0]
+        suffix = prefix_suffix[1]
+      else
+        raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
+      end
+      t = Time.now.strftime("%Y%m%d")
+      path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
       path << "-#{n}" if n
       path << suffix
-      Dir.mkdir(path, 0700)
-    rescue Errno::EEXIST
-      n ||= 0
-      n += 1
-      retry
     end
 
-    if block_given?
+    def create(basename, *rest)
+      if opts = Hash.try_convert(rest[-1])
+        opts = opts.dup if rest.pop.equal?(opts)
+        max_try = opts.delete(:max_try)
+        opts = [opts]
+      else
+        opts = []
+      end
+      tmpdir, = *rest
+      if $SAFE > 0 and tmpdir.tainted?
+        tmpdir = '/tmp'
+      else
+        tmpdir ||= tmpdir()
+      end
+      n = nil
       begin
-        yield path
-      ensure
-        FileUtils.remove_entry_secure path
+        path = File.expand_path(make_tmpname(basename, n), tmpdir)
+        yield(path, n, *opts)
+      rescue Errno::EEXIST
+        n ||= 0
+        n += 1
+        retry if !max_try or n < max_try
+        raise "cannot generate temporary name using `#{basename}' under `#{tmpdir}'"
       end
-    else
       path
     end
   end

Modified: MacRuby/trunk/lib/tracer.rb
===================================================================
--- MacRuby/trunk/lib/tracer.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/tracer.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,38 +1,57 @@
-#
 #   tracer.rb - 
-#   	$Release Version: 0.2$
-#   	$Revision: 1.8 $
-#   	by Keiju ISHITSUKA(Nippon Rational Inc.)
+#   	$Release Version: 0.3$
+#   	$Revision: 1.12 $
+#   	by Keiju ISHITSUKA(keiju at ishitsuka.com)
 #
 # --
 #
 #   
 #
+require "thread"
 
 #
 # tracer main class
 #
 class Tracer
-  @RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-'
-
-  @stdout = STDOUT
-  @verbose = false
   class << self
     attr_accessor :verbose
     alias verbose? verbose
+
     attr_accessor :stdout
+    attr_reader :stdout_mutex
+
+    # display process id?
+    attr_accessor :display_process_id
+    alias display_process_id? display_process_id
+
+    # display thread id?
+    attr_accessor :display_thread_id
+    alias display_thread_id? display_thread_id
+
+    # display builtin method call?
+    attr_accessor :display_c_call
+    alias display_c_call? display_c_call
   end
-  
+  Tracer::stdout = STDOUT
+  Tracer::verbose = false
+  Tracer::display_process_id = false
+  Tracer::display_thread_id = true
+  Tracer::display_c_call = false
+
+  @stdout_mutex = Mutex.new
+
   EVENT_SYMBOL = {
     "line" => "-",
     "call" => ">",
     "return" => "<",
     "class" => "C",
     "end" => "E",
-    "c-call" => ">",
-    "c-return" => "<",
+    "raise" => "^",
+    "c-call" => "}",
+    "c-return" => "{",
+    "unknown" => "?"
   }
-  
+
   def initialize
     @threads = Hash.new
     if defined? Thread.main
@@ -45,7 +64,7 @@
 
     @filters = []
   end
-  
+
   def stdout
     Tracer.stdout
   end
@@ -63,7 +82,7 @@
       stdout.print "Trace on\n" if Tracer.verbose?
     end
   end
-  
+
   def off
     set_trace_func nil
     stdout.print "Trace off\n" if Tracer.verbose?
@@ -76,7 +95,7 @@
   def set_get_line_procs(file, p = proc)
     @get_line_procs[file] = p
   end
-  
+
   def get_line(file, line)
     if p = @get_line_procs[file]
       return p.call(line)
@@ -84,8 +103,8 @@
 
     unless list = SCRIPT_LINES__[file]
       begin
-	f = open(file)
-	begin 
+	f = File::open(file)
+	begin
 	  SCRIPT_LINES__[file] = list = f.readlines
 	ensure
 	  f.close
@@ -101,7 +120,7 @@
       "-\n"
     end
   end
-  
+
   def get_thread_no
     if no = @threads[Thread.current.object_id]
       no
@@ -109,24 +128,35 @@
       @threads[Thread.current.object_id] = @threads.size
     end
   end
-  
+
   def trace_func(event, file, line, id, binding, klass, *)
     return if file == __FILE__
-    
+
     for p in @filters
       return unless p.call event, file, line, id, binding, klass
     end
-    
-    # saved_crit = Thread.critical
-    # Thread.critical = true
-    stdout.printf("#%d:%s:%d:%s:%s: %s",
-      get_thread_no,
-      file,
-      line,
-      klass || '',
-      EVENT_SYMBOL[event],
-      get_line(file, line))
-    # Thread.critical = saved_crit
+
+    return unless Tracer::display_c_call? or 
+      event != "c-call" && event != "c-return"
+
+    Tracer::stdout_mutex.synchronize do
+      if EVENT_SYMBOL[event]
+	stdout.printf("<%d>", $$) if Tracer::display_process_id?
+	stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id?
+	if line == 0
+	  source = "?\n"
+	else
+	  source = get_line(file, line)
+	end
+	printf("%s:%d:%s:%s: %s",
+	       file,
+	       line,
+	       klass || '', 
+	       EVENT_SYMBOL[event],
+	       source)
+      end
+    end
+
   end
 
   Single = new
@@ -137,11 +167,11 @@
       Single.on
     end
   end
-  
+
   def Tracer.off
     Single.off
   end
-  
+
   def Tracer.set_get_line_procs(file_name, p = proc)
     Single.set_get_line_procs(file_name, p)
   end
@@ -149,18 +179,17 @@
   def Tracer.add_filter(p = proc)
     Single.add_filter(p)
   end
-  
 end
 
 SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
 
 if $0 == __FILE__
   # direct call
-    
+
   $0 = ARGV[0]
   ARGV.shift
   Tracer.on
   require $0
-elsif caller(0).size == 1
+elsif caller.size <= 1 
   Tracer.on
 end

Modified: MacRuby/trunk/lib/tsort.rb
===================================================================
--- MacRuby/trunk/lib/tsort.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/tsort.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +1,3 @@
-#!/usr/bin/env ruby
 #--
 # tsort.rb - provides a module for topological sorting and strongly connected components.
 #++
@@ -241,50 +240,3 @@
     raise NotImplementedError.new
   end
 end
-
-if __FILE__ == $0
-  require 'test/unit'
-
-  class TSortHash < Hash # :nodoc:
-    include TSort
-    alias tsort_each_node each_key
-    def tsort_each_child(node, &block)
-      fetch(node).each(&block)
-    end
-  end
-
-  class TSortArray < Array # :nodoc:
-    include TSort
-    alias tsort_each_node each_index
-    def tsort_each_child(node, &block)
-      fetch(node).each(&block)
-    end
-  end
-
-  class TSortTest < Test::Unit::TestCase # :nodoc:
-    def test_dag
-      h = TSortHash[{1=>[2, 3], 2=>[3], 3=>[]}]
-      assert_equal([3, 2, 1], h.tsort)
-      assert_equal([[3], [2], [1]], h.strongly_connected_components)
-    end
-
-    def test_cycle
-      h = TSortHash[{1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}]
-      assert_equal([[4], [2, 3], [1]],
-        h.strongly_connected_components.map {|nodes| nodes.sort})
-      assert_raise(TSort::Cyclic) { h.tsort }
-    end
-
-    def test_array
-      a = TSortArray[[1], [0], [0], [2]]
-      assert_equal([[0, 1], [2], [3]],
-        a.strongly_connected_components.map {|nodes| nodes.sort})
-
-      a = TSortArray[[], [0]]
-      assert_equal([[0], [1]],
-        a.strongly_connected_components.map {|nodes| nodes.sort})
-    end
-  end
-
-end
-

Modified: MacRuby/trunk/lib/un.rb
===================================================================
--- MacRuby/trunk/lib/un.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/un.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,11 +1,11 @@
-# 
+#
 # = un.rb
-# 
+#
 # Copyright (c) 2003 WATANABE Hirofumi <eban at ruby-lang.org>
-# 
+#
 # This program is free software.
 # You can distribute/modify this program under the same terms of Ruby.
-# 
+#
 # == Utilities to replace common UNIX commands in Makefiles etc
 #
 # == SYNOPSIS
@@ -21,6 +21,7 @@
 #   ruby -run -e touch -- [OPTION] FILE
 #   ruby -run -e wait_writable -- [OPTION] FILE
 #   ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
+#   ruby -run -e httpd -- [OPTION] DocumentRoot
 #   ruby -run -e help [COMMAND]
 
 require "fileutils"
@@ -43,7 +44,7 @@
     end
     long_options.each do |s|
       opt_name = s[/\A(?:--)?([^\s=]+)/, 1].intern
-      o.on(s.sub(/\A(?!--)/, '--')) do |val|
+      o.on(s.gsub(/([a-z])([A-Z])/){$1+"-"+$2.downcase}.sub(/\A(?!--)/, '--')) do |val|
         opt_hash[opt_name] = val
       end
     end
@@ -283,6 +284,43 @@
 end
 
 ##
+# Run WEBrick HTTP server.
+#
+#   ruby -run -e httpd -- [OPTION] DocumentRoot
+#
+#   --bind-address=ADDR         address to bind
+#   --port=NUM                  listening port number
+#   --max-clients=MAX           max number of simultaneous clients
+#   --temp-dir=DIR              temporary directory
+#   --do-not-reverse-lookup     disable reverse lookup
+#   --request-timeout=SECOND    request timeout in seconds
+#   --http-version=VERSION      HTTP version
+#   -v                          verbose
+#
+
+def httpd
+  setup("", "BindAddress=ADDR", "Port=PORT", "MaxClients=NUM", "TempDir=DIR",
+        "DoNotReverseLookup", "RequestTimeout=SECOND", "HTTPVersion=VERSION") do
+    |argv, options|
+    require 'webrick'
+    opt = options[:RequestTimeout] and options[:RequestTimeout] = opt.to_i
+    opt = options[:Port] and (options[:Port] = Integer(opt)) rescue nil
+    unless argv.empty?
+      options[:DocumentRoot] = argv.shift
+    end
+    s = WEBrick::HTTPServer.new(options)
+    shut = proc {s.shutdown}
+    Signal.trap("TERM", shut)
+    Signal.trap("QUIT", shut)
+    if STDIN.tty?
+      Signal.trap("HUP", shut)
+      Signal.trap("INT", shut)
+    end
+    s.start
+  end
+end
+
+##
 # Display help message.
 #
 #   ruby -run -e help [COMMAND]

Modified: MacRuby/trunk/lib/uri/common.rb
===================================================================
--- MacRuby/trunk/lib/uri/common.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/common.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,8 +1,8 @@
 # = uri/common.rb
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
-# Revision:: $Id: common.rb 19413 2008-09-18 11:05:09Z mame $
-# License:: 
+# Revision:: $Id: common.rb 27285 2010-04-10 22:05:02Z naruse $
+# License::
 #   You can redistribute it and/or modify it under the same term as Ruby.
 #
 
@@ -34,7 +34,7 @@
       UNRESERVED = "-_.!~*'()#{ALNUM}"
       # reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
       #                 "$" | ","
-      # reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | 
+      # reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
       #                 "$" | "," | "[" | "]" (RFC 2732)
       RESERVED = ";/?:@&=+$,\\[\\]"
 
@@ -103,7 +103,7 @@
 	# null uri
 
       when @regexp[:ABS_URI]
-	scheme, opaque, userinfo, host, port, 
+	scheme, opaque, userinfo, host, port,
 	  registry, path, query, fragment = $~[1..-1]
 
 	# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
@@ -119,19 +119,19 @@
 	# server        = [ [ userinfo "@" ] hostport ]
 
 	if !scheme
-	  raise InvalidURIError, 
+	  raise InvalidURIError,
 	    "bad URI(absolute but no scheme): #{uri}"
 	end
 	if !opaque && (!path && (!host && !registry))
 	  raise InvalidURIError,
-	    "bad URI(absolute but no path): #{uri}" 
+	    "bad URI(absolute but no path): #{uri}"
 	end
 
       when @regexp[:REL_URI]
 	scheme = nil
 	opaque = nil
 
-	userinfo, host, port, registry, 
+	userinfo, host, port, registry,
 	  rel_segment, abs_path, query, fragment = $~[1..-1]
 	if rel_segment && abs_path
 	  path = rel_segment + abs_path
@@ -158,7 +158,7 @@
 
       path = '' if !path && !opaque # (see RFC2396 Section 5.2)
       ret = [
-	scheme, 
+	scheme,
 	userinfo, host, port,         # X
 	registry,                     # X
 	path,                         # Y
@@ -170,16 +170,16 @@
     end
 
     def parse(uri)
-      scheme, userinfo, host, port, 
+      scheme, userinfo, host, port,
        	registry, path, opaque, query, fragment = self.split(uri)
 
       if scheme && URI.scheme_list.include?(scheme.upcase)
-	URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port, 
-                                           registry, path, opaque, query, 
+	URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
+                                           registry, path, opaque, query,
                                            fragment, self)
       else
-	Generic.new(scheme, userinfo, host, port, 
-	   	    registry, path, opaque, query, 
+	Generic.new(scheme, userinfo, host, port,
+	   	    registry, path, opaque, query,
 	    	    fragment, self)
       end
     end
@@ -223,11 +223,11 @@
           tmp << sprintf('%%%02X', uc)
         end
         tmp
-      end
+      end.force_encoding(Encoding::US_ASCII)
     end
 
     def unescape(str, escaped = @regexp[:ESCAPED])
-      str.gsub(escaped) { [$&[1, 2].hex].pack('U') }
+      str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(str.encoding)
     end
 
     @@to_s = Kernel.instance_method(:to_s)
@@ -397,8 +397,8 @@
       ret = {}
 
       # for URI::split
-      ret[:ABS_URI] = Regexp.new('^' + pattern[:X_ABS_URI] + '$', Regexp::EXTENDED)
-      ret[:REL_URI] = Regexp.new('^' + pattern[:X_REL_URI] + '$', Regexp::EXTENDED)
+      ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
+      ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
 
       # for URI::extract
       ret[:URI_REF]     = Regexp.new(pattern[:URI_REF])
@@ -457,7 +457,7 @@
           end
         end
       else
-        raise ArgumentError, 
+        raise ArgumentError,
           "expected Array of or Hash of components of #{klass.to_s} (#{klass.component[1..-1].join(', ')})"
       end
       tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase
@@ -501,6 +501,7 @@
     #   # => "@%3F@%21"
     #
     def escape(*arg)
+      warn "#{caller(1)[0]}: warning: URI.escape is obsolete" if $VERBOSE
       DEFAULT_PARSER.escape(*arg)
     end
     alias encode escape
@@ -526,6 +527,7 @@
     #   # => "http://example.com/?a=\t\r"
     #
     def unescape(*arg)
+      warn "#{caller(1)[0]}: warning: URI.unescape is obsolete" if $VERBOSE
       DEFAULT_PARSER.unescape(*arg)
     end
     alias decode unescape
@@ -538,7 +540,7 @@
   def self.scheme_list
     @@schemes
   end
-  
+
   #
   # Base class for all URI exceptions.
   #
@@ -579,7 +581,7 @@
   #   * Opaque
   #   * Query
   #   * Fragment
-  # 
+  #
   # == Usage
   #
   #   require 'uri'
@@ -604,7 +606,7 @@
   # == Description
   #
   # Creates one of the URI's subclasses instance from the string.
-  #  
+  #
   # == Raises
   #
   # URI::InvalidURIError
@@ -617,11 +619,11 @@
   #   uri = URI.parse("http://www.ruby-lang.org/")
   #   p uri
   #   # => #<URI::HTTP:0x202281be URL:http://www.ruby-lang.org/>
-  #   p uri.scheme 
-  #   # => "http" 
-  #   p uri.host 
-  #   # => "www.ruby-lang.org" 
-  # 
+  #   p uri.scheme
+  #   # => "http"
+  #   p uri.host
+  #   # => "www.ruby-lang.org"
+  #
   def self.parse(uri)
     DEFAULT_PARSER.parse(uri)
   end
@@ -658,7 +660,7 @@
   #
   # == Args
   #
-  # +str+:: 
+  # +str+::
   #   String to extract URIs from.
   # +schemes+::
   #   Limit URI matching to a specific schemes.
@@ -686,25 +688,25 @@
   #
   # == Args
   #
-  # +match_schemes+:: 
+  # +match_schemes+::
   #   Array of schemes. If given, resulting regexp matches to URIs
   #   whose scheme is one of the match_schemes.
-  # 
+  #
   # == Description
   # Returns a Regexp object which matches to URI-like strings.
   # The Regexp object returned by this method includes arbitrary
   # number of capture group (parentheses).  Never rely on it's number.
-  # 
+  #
   # == Usage
   #
   #   require 'uri'
   #
   #   # extract first URI from html_string
   #   html_string.slice(URI.regexp)
-  # 
+  #
   #   # remove ftp URIs
   #   html_string.sub(URI.regexp(['ftp'])
-  # 
+  #
   #   # You should not rely on the number of parentheses
   #   html_string.scan(URI.regexp) do |*matches|
   #     p $&
@@ -714,6 +716,124 @@
     DEFAULT_PARSER.make_regexp(schemes)
   end
 
+  TBLENCWWWCOMP_ = {} # :nodoc:
+  TBLDECWWWCOMP_ = {} # :nodoc:
+  HTML5ASCIIINCOMPAT = [Encoding::UTF_16BE, Encoding::UTF_16LE,
+    Encoding::UTF_32BE, Encoding::UTF_32LE] # :nodoc:
+
+  # Encode given +str+ to URL-encoded form data.
+  #
+  # This doesn't convert *, -, ., 0-9, A-Z, _, a-z,
+  # does convert SP to +, and convert others to %XX.
+  #
+  # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+  #
+  # See URI.decode_www_form_component, URI.encode_www_form
+  def self.encode_www_form_component(str)
+    if TBLENCWWWCOMP_.empty?
+      256.times do |i|
+        TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
+      end
+      TBLENCWWWCOMP_[' '] = '+'
+      TBLENCWWWCOMP_.freeze
+    end
+    str = str.to_s
+    if HTML5ASCIIINCOMPAT.include?(str.encoding)
+      str = str.encode(Encoding::UTF_8)
+    else
+      str = str.dup
+    end
+    str.force_encoding(Encoding::ASCII_8BIT)
+    str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
+    str.force_encoding(Encoding::US_ASCII)
+  end
+
+  # Decode given +str+ of URL-encoded form data.
+  #
+  # This decods + to SP.
+  #
+  # See URI.encode_www_form_component, URI.decode_www_form
+  def self.decode_www_form_component(str, enc=Encoding::UTF_8)
+    if TBLDECWWWCOMP_.empty?
+      256.times do |i|
+        h, l = i>>4, i&15
+        TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
+        TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
+        TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
+        TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
+      end
+      TBLDECWWWCOMP_['+'] = ' '
+      TBLDECWWWCOMP_.freeze
+    end
+    raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%\h\h|[^%]+)*\z/ =~ str
+    str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
+  end
+
+  # Generate URL-encoded form data from given +enum+.
+  #
+  # This generates application/x-www-form-urlencoded data defined in HTML5
+  # from given an Enumerable object.
+  #
+  # This internally uses URI.encode_www_form_component(str).
+  #
+  # This doesn't convert encodings of give items, so convert them before call
+  # this method if you want to send data as other than original encoding or
+  # mixed encoding data. (strings which is encoded in HTML5 ASCII incompatible
+  # encoding is converted to UTF-8)
+  #
+  # This doesn't treat files. When you send a file, use multipart/form-data.
+  #
+  # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+  #
+  # See URI.encode_www_form_component, URI.decode_www_form
+  def self.encode_www_form(enum)
+    str = nil
+    enum.each do |k,v|
+      if str
+        str << '&'
+      else
+        str = nil.to_s
+      end
+      str << encode_www_form_component(k)
+      str << '='
+      str << encode_www_form_component(v)
+    end
+    str
+  end
+
+  WFKV_ = '(?:%\h\h|[^%#=;&]+)' # :nodoc:
+
+  # Decode URL-encoded form data from given +str+.
+  #
+  # This decodes application/x-www-form-urlencoded data
+  # and returns array of key-value array.
+  # This internally uses URI.decode_www_form_component.
+  #
+  # _charset_ hack is not supported now because the mapping from given charset
+  # to Ruby's encoding is not clear yet.
+  # see also http://www.w3.org/TR/html5/syntax.html#character-encodings-0
+  #
+  # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+  #
+  # ary = URI.decode_www_form("a=1&a=2&b=3")
+  # p ary                  #=> [['a', '1'], ['a', '2'], ['b', '3']]
+  # p ary.assoc('a').last  #=> '1'
+  # p ary.assoc('b').last  #=> '3'
+  # p ary.rassoc('a').last #=> '2'
+  # p Hash[ary]            # => {"a"=>"2", "b"=>"3"}
+  #
+  # See URI.decode_www_form_component, URI.encode_www_form
+  def self.decode_www_form(str, enc=Encoding::UTF_8)
+    return [] if str.empty?
+    unless /\A#{WFKV_}*=#{WFKV_}*(?:[;&]#{WFKV_}*=#{WFKV_}*)*\z/o =~ str
+      raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
+    end
+    ary = []
+    $&.scan(/([^=;&]+)=([^;&]*)/) do
+      ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
+    end
+    ary
+  end
 end
 
 module Kernel

Modified: MacRuby/trunk/lib/uri/ftp.rb
===================================================================
--- MacRuby/trunk/lib/uri/ftp.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/ftp.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: ftp.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# Revision:: $Id: ftp.rb 27350 2010-04-15 13:41:19Z mame $
 #
 
 require 'uri/generic'
@@ -13,16 +13,21 @@
   #
   # FTP URI syntax is defined by RFC1738 section 3.2.
   #
+  # This class will be redesigned because of difference of implementations;
+  # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
+  # is a good summary about the de facto spec.
+  # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04
+  #
   class FTP < Generic
     DEFAULT_PORT = 21
 
     COMPONENT = [
-      :scheme, 
+      :scheme,
       :userinfo, :host, :port,
       :path, :typecode
     ].freeze
     #
-    # Typecode is "a", "i" or "d". 
+    # Typecode is "a", "i" or "d".
     #
     # * "a" indicates a text file (the FTP command was ASCII)
     # * "i" indicates a binary file (FTP command IMAGE)
@@ -31,7 +36,7 @@
     TYPECODE = ['a', 'i', 'd'].freeze
     TYPECODE_PREFIX = ';type='.freeze
 
-    def self.new2(user, password, host, port, path, 
+    def self.new2(user, password, host, port, path,
                   typecode = nil, arg_check = true)
       typecode = nil if typecode.size == 0
       if typecode && !TYPECODE.include?(typecode)
@@ -42,22 +47,22 @@
       # do escape
 
       self.new('ftp',
-               [user, password], 
-               host, port, nil, 
-               typecode ? path + TYPECODE_PREFIX + typecode : path, 
+               [user, password],
+               host, port, nil,
+               typecode ? path + TYPECODE_PREFIX + typecode : path,
                nil, nil, nil, arg_check)
     end
 
     #
     # == Description
     #
-    # Creates a new URI::FTP object from components, with syntax checking.  
+    # Creates a new URI::FTP object from components, with syntax checking.
     #
-    # The components accepted are +userinfo+, +host+, +port+, +path+ and 
+    # The components accepted are +userinfo+, +host+, +port+, +path+ and
     # +typecode+.
     #
-    # The components should be provided either as an Array, or as a Hash 
-    # with keys formed by preceding the component names with a colon. 
+    # The components should be provided either as an Array, or as a Hash
+    # with keys formed by preceding the component names with a colon.
     #
     # If an Array is used, the components must be passed in the order
     # [userinfo, host, port, path, typecode]
@@ -67,11 +72,11 @@
     #
     #     require 'uri'
     #
-    #     uri = URI::FTP.build(['user:password', 'ftp.example.com', nil, 
+    #     uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
     #       '/path/file.> zip', 'i'])
     #     puts uri.to_s  ->  ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a
     #
-    #     uri2 = URI::FTP.build({:host => 'ftp.example.com', 
+    #     uri2 = URI::FTP.build({:host => 'ftp.example.com',
     #       :path => 'ruby/src'})
     #     puts uri2.to_s  ->  ftp://ftp.example.com/ruby/src
     #
@@ -92,7 +97,7 @@
 
       if tmp[:typecode]
         if tmp[:typecode].size == 1
-          tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] 
+          tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode]
         end
         tmp[:path] << tmp[:typecode]
       end
@@ -109,17 +114,18 @@
     # Unlike build(), this method does not escape the path component as
     # required by RFC1738; instead it is treated as per RFC2396.
     #
-    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, 
+    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
     # +opaque+, +query+ and +fragment+, in that order.
     #
     def initialize(*arg)
+      arg[5] = arg[5].sub(/^\//,'').sub(/^%2F/,'/')
       super(*arg)
       @typecode = nil
       tmp = @path.index(TYPECODE_PREFIX)
       if tmp
         typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
-        self.set_path(@path[0..tmp - 1])
-        
+        @path = @path[0..tmp - 1]
+
         if arg[-1]
           self.typecode = typecode
         else
@@ -164,9 +170,9 @@
     # RFC 1738 specifically states that the path for an FTP URI does not
     # include the / which separates the URI path from the URI host. Example:
     #
-    #     ftp://ftp.example.com/pub/ruby 
+    #     ftp://ftp.example.com/pub/ruby
     #
-    # The above URI indicates that the client should connect to 
+    # The above URI indicates that the client should connect to
     # ftp.example.com then cd pub/ruby from the initial login directory.
     #
     # If you want to cd to an absolute directory, you must include an
@@ -180,6 +186,11 @@
       return @path.sub(/^\//,'').sub(/^%2F/,'/')
     end
 
+    def set_path(v)
+      super("/" + v.sub(/^\//, "%2F"))
+    end
+    protected :set_path
+
     def to_s
       save_path = nil
       if @typecode

Modified: MacRuby/trunk/lib/uri/generic.rb
===================================================================
--- MacRuby/trunk/lib/uri/generic.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/generic.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,13 +3,13 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: generic.rb 20258 2008-11-18 16:46:16Z yugui $
+# Revision:: $Id: generic.rb 27350 2010-04-15 13:41:19Z mame $
 #
 
 require 'uri/common'
 
 module URI
-  
+
   #
   # Base class for all URI classes.
   # Implements generic URI syntax as per RFC 2396.
@@ -31,10 +31,10 @@
     end
 
     COMPONENT = [
-      :scheme, 
-      :userinfo, :host, :port, :registry, 
-      :path, :opaque, 
-      :query, 
+      :scheme,
+      :userinfo, :host, :port, :registry,
+      :path, :opaque,
+      :query,
       :fragment
     ].freeze
 
@@ -62,7 +62,7 @@
     # == Description
     #
     # At first, tries to create a new URI::Generic instance using
-    # URI::Generic::build. But, if exception URI::InvalidComponentError is raised, 
+    # URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
     # then it URI::Escape.escape all URI components and tries again.
     #
     #
@@ -71,9 +71,9 @@
         return self.build(args)
       rescue InvalidComponentError
         if args.kind_of?(Array)
-          return self.build(args.collect{|x| 
+          return self.build(args.collect{|x|
             if x
-              @parser.escape(x)
+              parser.escape(x)
             else
               x
             end
@@ -82,7 +82,7 @@
           tmp = {}
           args.each do |key, value|
             tmp[key] = if value
-                @parser.escape(value)
+                parser.escape(value)
               else
                 value
               end
@@ -117,11 +117,11 @@
           end
         end
       else
-        raise ArgumentError, 
+        raise ArgumentError,
         "expected Array of or Hash of components of #{self.class} (#{self.class.component.join(', ')})"
       end
 
-      tmp << DEFAULT_PARSER
+      tmp << nil
       tmp << true
       return self.new(*tmp)
     end
@@ -155,10 +155,10 @@
     #
     # Creates a new URI::Generic instance from ``generic'' components without check.
     #
-    def initialize(scheme, 
-                   userinfo, host, port, registry, 
-                   path, opaque, 
-                   query, 
+    def initialize(scheme,
+                   userinfo, host, port, registry,
+                   path, opaque,
+                   query,
                    fragment,
 		   parser = DEFAULT_PARSER,
                    arg_check = false)
@@ -172,7 +172,7 @@
       @opaque = nil
       @registry = nil
       @fragment = nil
-      @parser = parser
+      @parser = parser == DEFAULT_PARSER ? nil : parser
 
       if arg_check
         self.scheme = scheme
@@ -196,10 +196,10 @@
         self.set_fragment(fragment)
       end
       if @registry && !self.class.use_registry
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
       end
-      
+
       @scheme.freeze if @scheme
       self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
       self.set_port(self.default_port) if self.default_port && !@port
@@ -212,8 +212,15 @@
     attr_reader :query
     attr_reader :opaque
     attr_reader :fragment
-    attr_reader :parser
 
+    def parser
+      if !defined?(@parser) || !@parser
+        DEFAULT_PARSER
+      else
+        @parser || DEFAULT_PARSER
+      end
+    end
+
     # replace self by other URI object
     def replace!(oth)
       if self.class != oth.class
@@ -231,7 +238,7 @@
     end
 
     def check_scheme(v)
-      if v && @parser.regexp[:SCHEME] !~ v
+      if v && parser.regexp[:SCHEME] !~ v
         raise InvalidComponentError,
           "bad component(expected scheme component): #{v}"
       end
@@ -264,13 +271,13 @@
 
     def check_user(v)
       if @registry || @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set user with registry or opaque"
       end
 
       return v unless v
 
-      if @parser.regexp[:USERINFO] !~ v
+      if parser.regexp[:USERINFO] !~ v
         raise InvalidComponentError,
           "bad component(expected userinfo component or user component): #{v}"
       end
@@ -281,7 +288,7 @@
 
     def check_password(v, user = @user)
       if @registry || @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set password with registry or opaque"
       end
       return v unless v
@@ -291,7 +298,7 @@
           "password component depends user component"
       end
 
-      if @parser.regexp[:USERINFO] !~ v
+      if parser.regexp[:USERINFO] !~ v
         raise InvalidComponentError,
           "bad component(expected user component): #{v}"
       end
@@ -317,7 +324,7 @@
       set_user(user)
       # returns user
     end
-    
+
     def password=(password)
       check_password(password)
       set_password(password)
@@ -325,7 +332,7 @@
     end
 
     def set_userinfo(user, password = nil)
-      unless password 
+      unless password
         user, password = split_userinfo(user)
       end
       @user     = user
@@ -356,7 +363,7 @@
     private :split_userinfo
 
     def escape_userpass(v)
-      v = @parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
+      v = parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
     end
     private :escape_userpass
 
@@ -382,9 +389,9 @@
       return v unless v
 
       if @registry || @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set host with registry or opaque"
-      elsif @parser.regexp[:HOST] !~ v
+      elsif parser.regexp[:HOST] !~ v
         raise InvalidComponentError,
           "bad component(expected host component): #{v}"
       end
@@ -408,9 +415,9 @@
       return v unless v
 
       if @registry || @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set port with registry or opaque"
-      elsif !v.kind_of?(Fixnum) && @parser.regexp[:PORT] !~ v
+      elsif !v.kind_of?(Fixnum) && parser.regexp[:PORT] !~ v
         raise InvalidComponentError,
           "bad component(expected port component): #{v}"
       end
@@ -444,9 +451,9 @@
       # authority     = server | reg_name
       # server        = [ [ userinfo "@" ] hostport ]
       if @host || @port || @user # userinfo = @user + ':' + @password
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set registry with host, port, or userinfo"
-      elsif v && @parser.regexp[:REGISTRY] !~ v
+      elsif v && parser.regexp[:REGISTRY] !~ v
         raise InvalidComponentError,
           "bad component(expected registry component): #{v}"
       end
@@ -471,18 +478,20 @@
       # absoluteURI   = scheme ":" ( hier_part | opaque_part )
       # hier_part     = ( net_path | abs_path ) [ "?" query ]
       if v && @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "path conflicts with opaque"
       end
 
-      if @scheme
-        if v && v != '' && @parser.regexp[:ABS_PATH] !~ v
-          raise InvalidComponentError, 
+      # If scheme is ftp, path may be relative.
+      # See RFC 1738 section 3.2.2, and RFC 2396.
+      if @scheme && @scheme != "ftp"
+        if v && v != '' && parser.regexp[:ABS_PATH] !~ v
+          raise InvalidComponentError,
             "bad component(expected absolute path component): #{v}"
         end
       else
-        if v && v != '' && @parser.regexp[:ABS_PATH] !~ v && @parser.regexp[:REL_PATH] !~ v
-          raise InvalidComponentError, 
+        if v && v != '' && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v
+          raise InvalidComponentError,
             "bad component(expected relative path component): #{v}"
         end
       end
@@ -509,12 +518,12 @@
       # absoluteURI   = scheme ":" ( hier_part | opaque_part )
       # hier_part     = ( net_path | abs_path ) [ "?" query ]
       if @opaque
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "query conflicts with opaque"
       end
 
-      if v && v != '' && @parser.regexp[:QUERY] !~ v
-          raise InvalidComponentError, 
+      if v && v != '' && parser.regexp[:QUERY] !~ v
+          raise InvalidComponentError,
             "bad component(expected query component): #{v}"
       end
 
@@ -540,9 +549,9 @@
       # absoluteURI   = scheme ":" ( hier_part | opaque_part )
       # hier_part     = ( net_path | abs_path ) [ "?" query ]
       if @host || @port || @user || @path  # userinfo = @user + ':' + @password
-        raise InvalidURIError, 
+        raise InvalidURIError,
           "can not set opaque with host, port, userinfo or path"
-      elsif v && @parser.regexp[:OPAQUE] !~ v
+      elsif v && parser.regexp[:OPAQUE] !~ v
         raise InvalidComponentError,
           "bad component(expected opaque component): #{v}"
       end
@@ -565,8 +574,8 @@
     def check_fragment(v)
       return v unless v
 
-      if v && v != '' && @parser.regexp[:FRAGMENT] !~ v
-        raise InvalidComponentError, 
+      if v && v != '' && parser.regexp[:FRAGMENT] !~ v
+        raise InvalidComponentError,
           "bad component(expected fragment component): #{v}"
       end
 
@@ -777,19 +786,19 @@
       case oth
       when Generic
       when String
-        oth = @parser.parse(oth)
+        oth = parser.parse(oth)
       else
         raise ArgumentError,
           "bad argument(expected URI object or URI string)"
       end
 
       if self.relative? && oth.relative?
-        raise BadURIError, 
+        raise BadURIError,
           "both URI are relative"
       end
 
       if self.absolute? && oth.absolute?
-        #raise BadURIError, 
+        #raise BadURIError,
         #  "both URI are absolute"
         # hmm... should return oth for usability?
         return oth, oth
@@ -810,7 +819,7 @@
       src_path = split_path(src)
       dst_path = split_path(dst)
 
-      # hmm... dst has abnormal absolute path, 
+      # hmm... dst has abnormal absolute path,
       # like "/./", "/../", "/x/../", ...
       if dst_path.include?('..') ||
           dst_path.include?('.')
@@ -848,18 +857,18 @@
       case oth
       when Generic
       when String
-        oth = @parser.parse(oth)
+        oth = parser.parse(oth)
       else
         raise ArgumentError,
           "bad argument(expected URI object or URI string)"
       end
 
       if self.relative?
-        raise BadURIError, 
+        raise BadURIError,
           "relative URI: #{self}"
       end
       if oth.relative?
-        raise BadURIError, 
+        raise BadURIError,
           "relative URI: #{oth}"
       end
 
@@ -867,9 +876,9 @@
         return self, self.dup
       end
       rel = URI::Generic.new(nil, # it is relative URI
-                             self.userinfo, self.host, self.port, 
+                             self.userinfo, self.host, self.port,
                              self.registry, self.path, self.opaque,
-                             self.query, self.fragment, @parser)
+                             self.query, self.fragment, parser)
 
       if rel.userinfo != oth.userinfo ||
           rel.host.to_s.downcase != oth.host.to_s.downcase ||
@@ -955,12 +964,12 @@
     #   uri = URI.parse('http://my.example.com')
     #   p uri.route_to('http://my.example.com/main.rbx?page=1')
     #   #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1>
-    #    
+    #
     def route_to(oth)
       case oth
       when Generic
       when String
-        oth = @parser.parse(oth)
+        oth = parser.parse(oth)
       else
         raise ArgumentError,
           "bad argument(expected URI object or URI string)"
@@ -971,7 +980,7 @@
 
     #
     # Returns normalized URI
-    # 
+    #
     def normalize
       uri = dup
       uri.normalize!
@@ -985,9 +994,12 @@
       if path && path == ''
         set_path('/')
       end
+      if scheme && scheme != scheme.downcase
+        set_scheme(self.scheme.downcase)
+      end
       if host && host != host.downcase
         set_host(self.host.downcase)
-      end        
+      end
     end
 
     def path_query
@@ -1001,7 +1013,7 @@
 
     #
     # Constructs String from URI
-    # 
+    #
     def to_s
       str = ''
       if @scheme
@@ -1059,7 +1071,8 @@
     end
 
     def eql?(oth)
-      @parser == oth.parser &&
+      self.class == oth.class &&
+      parser == oth.parser &&
       self.component_ary.eql?(oth.component_ary)
     end
 
@@ -1103,7 +1116,7 @@
         if component.include?(c)
           self.send(c)
         else
-          raise ArgumentError, 
+          raise ArgumentError,
             "expected of components of #{self.class} (#{self.class.component.join(', ')})"
         end
       end
@@ -1117,7 +1130,7 @@
     def coerce(oth)
       case oth
       when String
-        oth = @parser.parse(oth)
+        oth = parser.parse(oth)
       else
         super
       end

Modified: MacRuby/trunk/lib/uri/http.rb
===================================================================
--- MacRuby/trunk/lib/uri/http.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/http.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: http.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# Revision:: $Id: http.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 require 'uri/generic'
@@ -14,18 +14,18 @@
   # The syntax of HTTP URIs is defined in RFC1738 section 3.3.
   #
   # Note that the Ruby URI library allows HTTP URLs containing usernames and
-  # passwords. This is not legal as per the RFC, but used to be 
-  # supported in Internet Explorer 5 and 6, before the MS04-004 security 
+  # passwords. This is not legal as per the RFC, but used to be
+  # supported in Internet Explorer 5 and 6, before the MS04-004 security
   # update. See <URL:http://support.microsoft.com/kb/834489>.
   #
   class HTTP < Generic
     DEFAULT_PORT = 80
 
     COMPONENT = [
-      :scheme, 
-      :userinfo, :host, :port, 
-      :path, 
-      :query, 
+      :scheme,
+      :userinfo, :host, :port,
+      :path,
+      :query,
       :fragment
     ].freeze
 
@@ -37,21 +37,21 @@
     # The components accepted are userinfo, host, port, path, query and
     # fragment.
     #
-    # The components should be provided either as an Array, or as a Hash 
-    # with keys formed by preceding the component names with a colon. 
+    # The components should be provided either as an Array, or as a Hash
+    # with keys formed by preceding the component names with a colon.
     #
     # If an Array is used, the components must be passed in the order
     # [userinfo, host, port, path, query, fragment].
     #
     # Example:
     #
-    #     newuri = URI::HTTP.build({:host => 'www.example.com', 
+    #     newuri = URI::HTTP.build({:host => 'www.example.com',
     #       :path> => '/foo/bar'})
     #
-    #     newuri = URI::HTTP.build([nil, "www.example.com", nil, "/path", 
+    #     newuri = URI::HTTP.build([nil, "www.example.com", nil, "/path",
     #       "query", 'fragment'])
     #
-    # Currently, if passed userinfo components this method generates 
+    # Currently, if passed userinfo components this method generates
     # invalid HTTP URIs as per RFC 1738.
     #
     def self.build(args)
@@ -63,10 +63,10 @@
     # == Description
     #
     # Create a new URI::HTTP object from generic URI components as per
-    # RFC 2396. No HTTP-specific syntax checking (as per RFC 1738) is 
+    # RFC 2396. No HTTP-specific syntax checking (as per RFC 1738) is
     # performed.
     #
-    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, 
+    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
     # +opaque+, +query+ and +fragment+, in that order.
     #
     # Example:

Modified: MacRuby/trunk/lib/uri/https.rb
===================================================================
--- MacRuby/trunk/lib/uri/https.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/https.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: https.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# Revision:: $Id: https.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 require 'uri/http'

Modified: MacRuby/trunk/lib/uri/ldap.rb
===================================================================
--- MacRuby/trunk/lib/uri/ldap.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/ldap.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,13 +1,13 @@
 #
 # = uri/ldap.rb
 #
-# Author:: 
+# Author::
 #  Takaaki Tateishi <ttate at jaist.ac.jp>
 #  Akira Yamada <akira at ruby-lang.org>
-# License:: 
+# License::
 #   URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada.
 #   You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: ldap.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# Revision:: $Id: ldap.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 require 'uri/generic'
@@ -21,7 +21,7 @@
   class LDAP < Generic
 
     DEFAULT_PORT = 389
-    
+
     COMPONENT = [
       :scheme,
       :host, :port,

Modified: MacRuby/trunk/lib/uri/mailto.rb
===================================================================
--- MacRuby/trunk/lib/uri/mailto.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri/mailto.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,7 +3,7 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: mailto.rb 19495 2008-09-23 18:16:08Z drbrain $
+# Revision:: $Id: mailto.rb 27731 2010-05-11 04:49:56Z marcandre $
 #
 
 require 'uri/generic'
@@ -38,7 +38,7 @@
     # hvalue     =  *urlc
     # header     =  hname "=" hvalue
     HEADER_PATTERN = "(?:[^?=&]*=[^?=&]*)".freeze
-    HEADER_REGEXP  = Regexp.new(HEADER_PATTERN, 'N').freeze
+    HEADER_REGEXP  = Regexp.new(HEADER_PATTERN).freeze
     # headers    =  "?" header *( "&" header )
     # to         =  #mailbox
     # mailtoURL  =  "mailto:" [ to ] [ headers ]
@@ -68,20 +68,20 @@
     #
     # If a Hash is used, the keys are the component names preceded by colons.
     #
-    # The headers can be supplied as a pre-encoded string, such as 
+    # The headers can be supplied as a pre-encoded string, such as
     # "subject=subscribe&cc=address", or as an Array of Arrays like
     # [['subject', 'subscribe'], ['cc', 'address']]
     #
     # Examples:
-    # 
+    #
     #    require 'uri'
-    #    
+    #
     #    m1 = URI::MailTo.build(['joe at example.com', 'subject=Ruby'])
     #    puts m1.to_s  ->  mailto:joe at example.com?subject=Ruby
-    #    
+    #
     #    m2 = URI::MailTo.build(['john at example.com', [['Subject', 'Ruby'], ['Cc', 'jack at example.com']]])
     #    puts m2.to_s  ->  mailto:john at example.com?Subject=Ruby&Cc=jack at example.com
-    #    
+    #
     #    m3 = URI::MailTo.build({:to => 'listman at example.com', :headers => [['subject', 'subscribe']]})
     #    puts m3.to_s  ->  mailto:listman at example.com?subject=subscribe
     #
@@ -159,7 +159,7 @@
       return true unless v
       return true if v.size == 0
 
-      if @parser.regexp[:OPAQUE] !~ v || /\A#{MAILBOX_PATTERN}*\z/o !~ v
+      if parser.regexp[:OPAQUE] !~ v || /\A#{MAILBOX_PATTERN}*\z/o !~ v
         raise InvalidComponentError,
           "bad component(expected opaque component): #{v}"
       end
@@ -183,7 +183,7 @@
       return true unless v
       return true if v.size == 0
 
-      if @parser.regexp[:OPAQUE] !~ v || 
+      if parser.regexp[:OPAQUE] !~ v ||
           /\A(#{HEADER_PATTERN}(?:\&#{HEADER_PATTERN})*)\z/o !~ v
         raise InvalidComponentError,
           "bad component(expected opaque component): #{v}"
@@ -210,12 +210,12 @@
     end
 
     def to_s
-      @scheme + ':' + 
-        if @to 
+      @scheme + ':' +
+        if @to
           @to
         else
           ''
-        end + 
+        end +
         if @headers.size > 0
           '?' + @headers.collect{|x| x.join('=')}.join('&')
         else
@@ -227,7 +227,7 @@
           ''
         end
     end
-    
+
     # Returns the RFC822 e-mail text equivalent of the URL, as a String.
     #
     # Example:
@@ -239,18 +239,18 @@
     #   # => "To: ruby-list at ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n"
     #
     def to_mailtext
-      to = @parser.unescape(@to)
+      to = parser.unescape(@to)
       head = ''
       body = ''
       @headers.each do |x|
         case x[0]
         when 'body'
-          body = @parser.unescape(x[1])
+          body = parser.unescape(x[1])
         when 'to'
-          to << ', ' + @parser.unescape(x[1])
+          to << ', ' + parser.unescape(x[1])
         else
-          head << @parser.unescape(x[0]).capitalize + ': ' +
-            @parser.unescape(x[1])  + "\n"
+          head << parser.unescape(x[0]).capitalize + ': ' +
+            parser.unescape(x[1])  + "\n"
         end
       end
 

Modified: MacRuby/trunk/lib/uri.rb
===================================================================
--- MacRuby/trunk/lib/uri.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/uri.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -3,11 +3,11 @@
 #
 # Author:: Akira Yamada <akira at ruby-lang.org>
 # Documentation:: Akira Yamada <akira at ruby-lang.org>, Dmitry V. Sabanin <sdmitry at lrn.ru>
-# License:: 
+# License::
 #  Copyright (c) 2001 akira yamada <akira at ruby-lang.org>
 #  You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id: uri.rb 13772 2007-10-25 00:53:34Z akira $
-# 
+# Revision:: $Id: uri.rb 25189 2009-10-02 12:04:37Z akr $
+#
 # See URI for documentation
 #
 

Modified: MacRuby/trunk/lib/xmlrpc/base64.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/base64.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/base64.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -9,19 +9,19 @@
 
 = XMLRPC::Base64
 == Description
-This class is necessary for (('xmlrpc4r')) to determine that a string should 
-be transmitted base64-encoded and not as a raw-string. 
-You can use (({XMLRPC::Base64})) on the client and server-side as a 
+This class is necessary for (('xmlrpc4r')) to determine that a string should
+be transmitted base64-encoded and not as a raw-string.
+You can use (({XMLRPC::Base64})) on the client and server-side as a
 parameter and/or return-value.
 
 == Class Methods
 --- XMLRPC::Base64.new( str, state = :dec )
     Creates a new (({XMLRPC::Base64})) instance with string ((|str|)) as the
-    internal string. When ((|state|)) is (({:dec})) it assumes that the 
-    string ((|str|)) is not in base64 format (perhaps already decoded), 
-    otherwise if ((|state|)) is (({:enc})) it decodes ((|str|)) 
+    internal string. When ((|state|)) is (({:dec})) it assumes that the
+    string ((|str|)) is not in base64 format (perhaps already decoded),
+    otherwise if ((|state|)) is (({:enc})) it decodes ((|str|))
     and stores it as the internal string.
-    
+
 --- XMLRPC::Base64.decode( str )
     Decodes string ((|str|)) with base64 and returns that value.
 
@@ -40,7 +40,7 @@
 module XMLRPC
 
 class Base64
-  
+
   def initialize(str, state = :dec)
     case state
     when :enc
@@ -51,11 +51,11 @@
       raise ArgumentError, "wrong argument; either :enc or :dec"
     end
   end
-  
+
   def decoded
-    @str  
+    @str
   end
-  
+
   def encoded
     Base64.encode(@str)
   end
@@ -77,5 +77,5 @@
 
 =begin
 = History
-    $Id: base64.rb 11708 2007-02-12 23:01:19Z shyouhei $
+    $Id: base64.rb 25189 2009-10-02 12:04:37Z akr $
 =end

Modified: MacRuby/trunk/lib/xmlrpc/client.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/client.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/client.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -26,7 +26,7 @@
 or
 
     require "xmlrpc/client"
-  
+
     server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
     ok, param = server.call2("michael.add", 4, 5)
     if ok then
@@ -40,14 +40,14 @@
 == Description
 Class (({XMLRPC::Client})) provides remote procedure calls to a XML-RPC server.
 After setting the connection-parameters with ((<XMLRPC::Client.new>)) which
-creates a new (({XMLRPC::Client})) instance, you can execute a remote procedure 
+creates a new (({XMLRPC::Client})) instance, you can execute a remote procedure
 by sending the ((<call|XMLRPC::Client#call>)) or ((<call2|XMLRPC::Client#call2>))
-message to this new instance. The given parameters indicate which method to 
+message to this new instance. The given parameters indicate which method to
 call on the remote-side and of course the parameters for the remote procedure.
 
 == Class Methods
 --- XMLRPC::Client.new( host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, user=nil, password=nil, use_ssl=false, timeout =nil)
-    Creates an object which represents the remote XML-RPC server on the 
+    Creates an object which represents the remote XML-RPC server on the
     given host ((|host|)). If the server is CGI-based, ((|path|)) is the
     path to the CGI-script, which will be called, otherwise (in the
     case of a standalone server) ((|path|)) should be (({"/RPC2"})).
@@ -59,8 +59,8 @@
     Default values for ((|host|)), ((|path|)) and ((|port|)) are 'localhost', '/RPC2' and
     '80' respectively using SSL '443'.
 
-    If ((|user|)) and ((|password|)) are given, each time a request is send, 
-    a Authorization header is send. Currently only Basic Authentification is 
+    If ((|user|)) and ((|password|)) are given, each time a request is send,
+    a Authorization header is send. Currently only Basic Authentification is
     implemented no Digest.
 
     If ((|use_ssl|)) is set to (({true})), comunication over SSL is enabled.
@@ -76,9 +76,9 @@
 
 :   proxy
     Is of the form "host:port".
- 
+
 :   timeout
-    Defaults to 30. 
+    Defaults to 30.
 
 --- XMLRPC::Client.new3( hash={} )
 --- XMLRPC::Client.new_from_hash( hash={} )
@@ -97,10 +97,10 @@
 
 == Instance Methods
 --- XMLRPC::Client#call( method, *args )
-    Invokes the method named ((|method|)) with the parameters given by 
+    Invokes the method named ((|method|)) with the parameters given by
     ((|args|)) on the XML-RPC server.
-    The parameter ((|method|)) is converted into a (({String})) and should 
-    be a valid XML-RPC method-name.  
+    The parameter ((|method|)) is converted into a (({String})) and should
+    be a valid XML-RPC method-name.
     Each parameter of ((|args|)) must be of one of the following types,
     where (({Hash})), (({Struct})) and (({Array})) can contain any of these listed ((:types:)):
     * (({Fixnum})), (({Bignum}))
@@ -110,31 +110,31 @@
     * (({Hash})), (({Struct}))
     * (({Array}))
     * (({Date})), (({Time})), (({XMLRPC::DateTime}))
-    * (({XMLRPC::Base64})) 
-    * A Ruby object which class includes XMLRPC::Marshallable (only if Config::ENABLE_MARSHALLABLE is (({true}))). 
+    * (({XMLRPC::Base64}))
+    * A Ruby object which class includes XMLRPC::Marshallable (only if Config::ENABLE_MARSHALLABLE is (({true}))).
       That object is converted into a hash, with one additional key/value pair "___class___" which contains the class name
       for restoring later that object.
-    
-    The method returns the return-value from the RPC 
-    ((-stands for Remote Procedure Call-)). 
+
+    The method returns the return-value from the RPC
+    ((-stands for Remote Procedure Call-)).
     The type of the return-value is one of the above shown,
     only that a (({Bignum})) is only allowed when it fits in 32-bit and
     that a XML-RPC (('dateTime.iso8601')) type is always returned as
-    a ((<(({XMLRPC::DateTime}))|URL:datetime.html>)) object and 
+    a ((<(({XMLRPC::DateTime}))|URL:datetime.html>)) object and
     a (({Struct})) is never returned, only a (({Hash})), the same for a (({Symbol})), where
-    always a (({String})) is returned. 
+    always a (({String})) is returned.
     A (({XMLRPC::Base64})) is returned as a (({String})) from xmlrpc4r version 1.6.1 on.
-    
-    If the remote procedure returned a fault-structure, then a 
+
+    If the remote procedure returned a fault-structure, then a
     (({XMLRPC::FaultException})) exception is raised, which has two accessor-methods
     (({faultCode})) and (({faultString})) of type (({Integer})) and (({String})).
 
 --- XMLRPC::Client#call2( method, *args )
     The difference between this method and ((<call|XMLRPC::Client#call>)) is, that
     this method do ((*not*)) raise a (({XMLRPC::FaultException})) exception.
-    The method returns an array of two values. The first value indicates if 
+    The method returns an array of two values. The first value indicates if
     the second value is a return-value ((({true}))) or an object of type
-    (({XMLRPC::FaultException})). 
+    (({XMLRPC::FaultException})).
     Both are explained in ((<call|XMLRPC::Client#call>)).
 
     Simple to remember: The "2" in "call2" denotes the number of values it returns.
@@ -151,19 +151,19 @@
       # => [7, -1]
 
 --- XMLRPC::Client#multicall2( *methods )
-    Same as ((<XMLRPC::Client#multicall>)), but returns like ((<XMLRPC::Client#call2>)) two parameters 
+    Same as ((<XMLRPC::Client#multicall>)), but returns like ((<XMLRPC::Client#call2>)) two parameters
     instead of raising an (({XMLRPC::FaultException})).
 
 --- XMLRPC::Client#proxy( prefix, *args )
     Returns an object of class (({XMLRPC::Client::Proxy})), initialized with
     ((|prefix|)) and ((|args|)). A proxy object returned by this method behaves
     like ((<XMLRPC::Client#call>)), i.e. a call on that object will raise a
-    (({XMLRPC::FaultException})) when a fault-structure is returned by that call. 
+    (({XMLRPC::FaultException})) when a fault-structure is returned by that call.
 
 --- XMLRPC::Client#proxy2( prefix, *args )
     Almost the same like ((<XMLRPC::Client#proxy>)) only that a call on the returned
     (({XMLRPC::Client::Proxy})) object behaves like ((<XMLRPC::Client#call2>)), i.e.
-    a call on that object will return two parameters. 
+    a call on that object will return two parameters.
 
 
 
@@ -175,22 +175,22 @@
 --- XMLRPC::Client#proxy_async(...)
 --- XMLRPC::Client#proxy2_async(...)
     In contrast to corresponding methods without "_async", these can be
-    called concurrently and use for each request a new connection, where the 
+    called concurrently and use for each request a new connection, where the
     non-asynchronous counterparts use connection-alive (one connection for all requests)
-    if possible. 
+    if possible.
 
-    Note, that you have to use Threads to call these methods concurrently. 
+    Note, that you have to use Threads to call these methods concurrently.
     The following example calls two methods concurrently:
-    
+
       Thread.new {
         p client.call_async("michael.add", 4, 5)
       }
- 
+
       Thread.new {
         p client.call_async("michael.div", 7, 9)
       }
- 
 
+
 --- XMLRPC::Client#timeout
 --- XMLRPC::Client#user
 --- XMLRPC::Client#password
@@ -200,12 +200,12 @@
 --- XMLRPC::Client#user= (new_user)
 --- XMLRPC::Client#password= (new_password)
     Set the corresponding attributes.
-    
 
+
 --- XMLRPC::Client#set_writer( writer )
     Sets the XML writer to use for generating XML output.
     Should be an instance of a class from module (({XMLRPC::XMLWriter})).
-    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used. 
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used.
 
 --- XMLRPC::Client#set_parser( parser )
     Sets the XML parser to use for parsing XML documents.
@@ -220,7 +220,7 @@
     Set extra HTTP headers that are included in the request.
 
 --- XMLRPC::Client#http_header_extra
-    Access the via ((<XMLRPC::Client#http_header_extra=>)) assigned header. 
+    Access the via ((<XMLRPC::Client#http_header_extra=>)) assigned header.
 
 --- XMLRPC::Client#http_last_response
     Returns the (({Net::HTTPResponse})) object of the last RPC.
@@ -240,35 +240,35 @@
 
 == Description
 Class (({XMLRPC::Client::Proxy})) makes XML-RPC calls look nicer!
-You can call any method onto objects of that class - the object handles 
+You can call any method onto objects of that class - the object handles
 (({method_missing})) and will forward the method call to a XML-RPC server.
 Don't use this class directly, but use instead method ((<XMLRPC::Client#proxy>)) or
 ((<XMLRPC::Client#proxy2>)).
 
 == Class Methods
---- XMLRPC::Client::Proxy.new( server, prefix, args=[], meth=:call, delim="." ) 
+--- XMLRPC::Client::Proxy.new( server, prefix, args=[], meth=:call, delim="." )
     Creates an object which provides (({method_missing})).
 
     ((|server|)) must be of type (({XMLRPC::Client})), which is the XML-RPC server to be used
     for a XML-RPC call. ((|prefix|)) and ((|delim|)) will be prepended to the methodname
-    called onto this object. 
+    called onto this object.
 
     Parameter ((|meth|)) is the method (call, call2, call_async, call2_async) to use for
     a RPC.
 
     ((|args|)) are arguments which are automatically given
     to every XML-RPC call before the arguments provides through (({method_missing})).
-    
+
 == Instance Methods
 Every method call is forwarded to the XML-RPC server defined in ((<new|XMLRPC::Client::Proxy#new>)).
-    
+
 Note: Inherited methods from class (({Object})) cannot be used as XML-RPC names, because they get around
-(({method_missing})). 
-          
+(({method_missing})).
 
 
+
 = History
-    $Id: client.rb 19657 2008-10-01 13:46:53Z mame $
+    $Id: client.rb 25189 2009-10-02 12:04:37Z akr $
 
 =end
 
@@ -283,7 +283,7 @@
 module XMLRPC
 
   class Client
-   
+
     USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})"
 
     include ParserWriterChooseMixin
@@ -292,11 +292,11 @@
 
     # Constructors -------------------------------------------------------------------
 
-    def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, 
+    def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
                    user=nil, password=nil, use_ssl=nil, timeout=nil)
 
       @http_header_extra = nil
-      @http_last_response = nil 
+      @http_last_response = nil
       @cookie = nil
 
       @host       = host || "localhost"
@@ -325,7 +325,7 @@
 
       # HTTP object for synchronous calls
       Net::HTTP.version_1_2
-      @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port) 
+      @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
       @http.use_ssl = @use_ssl if @use_ssl
       @http.read_timeout = @timeout
       @http.open_timeout = @timeout
@@ -341,7 +341,7 @@
       if match = /^([^:]+):\/\/(([^@]+)@)?([^\/]+)(\/.*)?$/.match(uri)
         proto = match[1]
         user, passwd = (match[3] || "").split(":")
-        host, port = match[4].split(":") 
+        host, port = match[4].split(":")
         path = match[5]
 
         if proto != "http" and proto != "https"
@@ -351,7 +351,7 @@
       else
         raise "Wrong URI as parameter!"
       end
- 
+
       proxy_host, proxy_port = (proxy || "").split(":")
 
       self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout)
@@ -384,8 +384,8 @@
 
     # Cookie support
     attr_accessor :cookie
-    
 
+
     attr_reader :timeout, :user, :password
 
     def timeout=(new_timeout)
@@ -407,13 +407,13 @@
     # Call methods --------------------------------------------------------------
 
     def call(method, *args)
-      ok, param = call2(method, *args) 
+      ok, param = call2(method, *args)
       if ok
         param
       else
         raise param
       end
-    end 
+    end
 
     def call2(method, *args)
       request = create().methodCall(method, *args)
@@ -422,13 +422,13 @@
     end
 
     def call_async(method, *args)
-      ok, param = call2_async(method, *args) 
+      ok, param = call2_async(method, *args)
       if ok
         param
       else
         raise param
       end
-    end 
+    end
 
     def call2_async(method, *args)
       request = create().methodCall(method, *args)
@@ -467,7 +467,7 @@
 
 
     # Proxy generating methods ------------------------------------------
-    
+
     def proxy(prefix=nil, *args)
       Proxy.new(self, prefix, args, :call)
     end
@@ -498,10 +498,10 @@
     end
 
     def do_rpc(request, async=false)
-      header = {  
+      header = {
        "User-Agent"     =>  USER_AGENT,
        "Content-Type"   => "text/xml; charset=utf-8",
-       "Content-Length" => request.size.to_s, 
+       "Content-Length" => request.size.to_s,
        "Connection"     => (async ? "close" : "keep-alive")
       }
 
@@ -512,41 +512,41 @@
         # add authorization header
         header["Authorization"] = @auth
       end
- 
+
       resp = nil
       @http_last_response = nil
 
       if async
-        # use a new HTTP object for each call 
+        # use a new HTTP object for each call
         Net::HTTP.version_1_2
-        http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port) 
+        http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
         http.use_ssl = @use_ssl if @use_ssl
         http.read_timeout = @timeout
         http.open_timeout = @timeout
-        
+
         # post request
         http.start {
-          resp = http.post2(@path, request, header) 
+          resp = http.post2(@path, request, header)
         }
       else
         # reuse the HTTP object for each call => connection alive is possible
         # we must start connection explicitely first time so that http.request
         # does not assume that we don't want keepalive
         @http.start if not @http.started?
-        
+
         # post request
-        resp = @http.post2(@path, request, header) 
+        resp = @http.post2(@path, request, header)
       end
-  
+
       @http_last_response = resp
 
       data = resp.body
 
       if resp.code == "401"
         # Authorization Required
-        raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}" 
+        raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}"
       elsif resp.code[0,1] != "2"
-        raise "HTTP-Error: #{resp.code} #{resp.message}" 
+        raise "HTTP-Error: #{resp.code} #{resp.message}"
       end
 
       ct = parse_content_type(resp["Content-Type"]).first
@@ -559,8 +559,8 @@
       end
 
       expected = resp["Content-Length"] || "<unknown>"
-      if data.nil? or data.size == 0 
-        raise "Wrong size. Was #{data.size}, should be #{expected}" 
+      if data.nil? or data.size == 0
+        raise "Wrong size. Was #{data.size}, should be #{expected}"
       elsif expected != "<unknown>" and expected.to_i != data.size and resp["Transfer-Encoding"].nil?
         raise "Wrong size. Was #{data.size}, should be #{expected}"
       end
@@ -581,11 +581,11 @@
       meth = :call2
       meth = :call2_async if async
 
-      ok, params = self.send(meth, "system.multicall", 
+      ok, params = self.send(meth, "system.multicall",
         methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} }
       )
 
-      if ok 
+      if ok
         params = params.collect do |param|
           if param.is_a? Array
             param[0]
@@ -593,7 +593,7 @@
             XMLRPC::FaultException.new(param["faultCode"], param["faultString"])
           else
             raise "Wrong multicall return value"
-          end 
+          end
         end
       end
 
@@ -607,7 +607,7 @@
       def initialize(server, prefix, args=[], meth=:call, delim=".")
         @server = server
         @prefix = prefix ? prefix + delim : ""
-        @args   = args 
+        @args   = args
         @meth   = meth
       end
 

Modified: MacRuby/trunk/lib/xmlrpc/config.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/config.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/config.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +1,5 @@
 #
-# $Id: config.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# $Id: config.rb 25189 2009-10-02 12:04:37Z akr $
 # Configuration file for XML-RPC for Ruby
 #
 
@@ -8,7 +8,7 @@
   module Config
 
     DEFAULT_WRITER = XMLWriter::Simple            # or XMLWriter::XMLParser
-    
+
     # available parser:
     #   * XMLParser::NQXMLTreeParser
     #   * XMLParser::NQXMLStreamParser
@@ -21,16 +21,16 @@
     # enable <nil/> tag
     ENABLE_NIL_CREATE    = false
     ENABLE_NIL_PARSER    = false
-    
+
     # allows integers greater than 32-bit if true
     ENABLE_BIGINT        = false
 
     # enable marshalling ruby objects which include XMLRPC::Marshallable
-    ENABLE_MARSHALLING   = true 
+    ENABLE_MARSHALLING   = true
 
     # enable multiCall extension by default
     ENABLE_MULTICALL     = false
-    
+
     # enable Introspection extension by default
     ENABLE_INTROSPECTION = false
 

Modified: MacRuby/trunk/lib/xmlrpc/create.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/create.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/create.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,9 +1,9 @@
 #
 # Creates XML-RPC call/response documents
-# 
+#
 # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann at ntecs.de)
 #
-# $Id: create.rb 19657 2008-10-01 13:46:53Z mame $
+# $Id: create.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 require "date"
@@ -41,7 +41,7 @@
       def element(name, attrs, *children)
         raise "attributes not yet implemented" unless attrs.nil?
         if children.empty?
-          "<#{name}/>" 
+          "<#{name}/>"
         else
           "<#{name}>" + children.join("") + "</#{name}>"
         end
@@ -69,7 +69,7 @@
       end
 
       def document(*params)
-        XML::SimpleTree::Document.new(*params) 
+        XML::SimpleTree::Document.new(*params)
       end
 
       def pi(name, *params)
@@ -120,9 +120,9 @@
 
       tree = @writer.document(
                @writer.pi("xml", 'version="1.0"'),
-               @writer.ele("methodCall",   
+               @writer.ele("methodCall",
                  @writer.tag("methodName", name),
-                 @writer.ele("params", *parameter)    
+                 @writer.ele("params", *parameter)
                )
              )
 
@@ -137,29 +137,29 @@
     # if is_ret == false then the params array must
     # contain only one element, which is a structure
     # of a fault return-value.
-    # 
-    # if is_ret == true then a normal 
+    #
+    # if is_ret == true then a normal
     # return-value of all the given params is created.
     #
     def methodResponse(is_ret, *params)
 
-      if is_ret 
+      if is_ret
         resp = params.collect do |param|
           @writer.ele("param", conv2value(param))
         end
-     
+
         resp = [@writer.ele("params", *resp)]
       else
-        if params.size != 1 or params[0] === XMLRPC::FaultException 
+        if params.size != 1 or params[0] === XMLRPC::FaultException
           raise ArgumentError, "no valid fault-structure given"
         end
         resp = @writer.ele("fault", conv2value(params[0].to_h))
       end
 
-        
+
       tree = @writer.document(
                @writer.pi("xml", 'version="1.0"'),
-               @writer.ele("methodResponse", resp) 
+               @writer.ele("methodResponse", resp)
              )
 
       @writer.document_to_str(tree) + "\n"
@@ -178,7 +178,7 @@
     def conv2value(param)
 
         val = case param
-        when Fixnum 
+        when Fixnum
           @writer.tag("i4", param.to_s)
 
         when Bignum
@@ -194,10 +194,10 @@
         when TrueClass, FalseClass
           @writer.tag("boolean", param ? "1" : "0")
 
-        when Symbol 
+        when Symbol
           @writer.tag("string", param.to_s)
 
-        when String 
+        when String
           @writer.tag("string", param)
 
         when NilClass
@@ -211,51 +211,51 @@
           @writer.tag("double", param.to_s)
 
         when Struct
-          h = param.members.collect do |key| 
+          h = param.members.collect do |key|
             value = param[key]
-            @writer.ele("member", 
+            @writer.ele("member",
               @writer.tag("name", key.to_s),
-              conv2value(value) 
+              conv2value(value)
             )
           end
 
-          @writer.ele("struct", *h) 
+          @writer.ele("struct", *h)
 
         when Hash
           # TODO: can a Hash be empty?
-          
+
           h = param.collect do |key, value|
-            @writer.ele("member", 
+            @writer.ele("member",
               @writer.tag("name", key.to_s),
-              conv2value(value) 
+              conv2value(value)
             )
           end
 
-          @writer.ele("struct", *h) 
+          @writer.ele("struct", *h)
 
         when Array
           # TODO: can an Array be empty?
           a = param.collect {|v| conv2value(v) }
-          
-          @writer.ele("array", 
+
+          @writer.ele("array",
             @writer.ele("data", *a)
           )
 
         when Time, Date, ::DateTime
-          @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))  
+          @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))
 
         when XMLRPC::DateTime
-          @writer.tag("dateTime.iso8601", 
+          @writer.tag("dateTime.iso8601",
             format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
-   
+
         when XMLRPC::Base64
-          @writer.tag("base64", param.encoded) 
+          @writer.tag("base64", param.encoded)
 
-        else 
+        else
           if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
             # convert Ruby object into Hash
             ret = {"___class___" => param.class.name}
-            param.instance_variables.each {|v| 
+            param.instance_variables.each {|v|
               name = v[1..-1]
               val = param.instance_variable_get(v)
 
@@ -266,16 +266,16 @@
               end
             }
             return conv2value(ret)
-          else 
+          else
             ok, pa = wrong_type(param)
             if ok
               return conv2value(pa)
-            else 
+            else
               raise "Wrong type!"
             end
           end
         end
-         
+
         @writer.ele("value", val)
     end
 
@@ -283,7 +283,7 @@
       false
     end
 
-    
+
   end # class Create
 
 end # module XMLRPC

Modified: MacRuby/trunk/lib/xmlrpc/datetime.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/datetime.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/datetime.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -10,19 +10,19 @@
 = XMLRPC::DateTime
 == Description
 This class is important to handle XMLRPC (('dateTime.iso8601')) values,
-correcly, because normal UNIX-dates (class (({Date}))) only handle dates 
+correcly, because normal UNIX-dates (class (({Date}))) only handle dates
 from year 1970 on, and class (({Time})) handles dates without the time
-component. (({XMLRPC::DateTime})) is able to store a XMLRPC 
+component. (({XMLRPC::DateTime})) is able to store a XMLRPC
 (('dateTime.iso8601')) value correctly.
 
 == Class Methods
 --- XMLRPC::DateTime.new( year, month, day, hour, min, sec )
     Creates a new (({XMLRPC::DateTime})) instance with the
-    parameters ((|year|)), ((|month|)), ((|day|)) as date and 
+    parameters ((|year|)), ((|month|)), ((|day|)) as date and
     ((|hour|)), ((|min|)), ((|sec|)) as time.
     Raises (({ArgumentError})) if a parameter is out of range, or ((|year|)) is not
     of type (({Integer})).
-    
+
 == Instance Methods
 --- XMLRPC::DateTime#year
 --- XMLRPC::DateTime#month
@@ -50,7 +50,7 @@
 
 --- XMLRPC::DateTime#to_time
     Return a (({Time})) object of the date/time which (({self})) represents.
-    If the (('year')) is below 1970, this method returns (({nil})), 
+    If the (('year')) is below 1970, this method returns (({nil})),
     because (({Time})) cannot handle years below 1970.
     The used timezone is GMT.
 
@@ -68,7 +68,7 @@
 module XMLRPC
 
 class DateTime
-  
+
   attr_reader :year, :month, :day, :hour, :min, :sec
 
   def year= (value)
@@ -102,14 +102,14 @@
   end
 
   alias mon  month
-  alias mon= month= 
- 
+  alias mon= month=
 
+
   def initialize(year, month, day, hour, min, sec)
     self.year, self.month, self.day = year, month, day
     self.hour, self.min, self.sec   = hour, min, sec
   end
- 
+
   def to_time
     if @year >= 1970
       Time.gm(*to_a)
@@ -138,5 +138,5 @@
 
 =begin
 = History
-    $Id: datetime.rb 11708 2007-02-12 23:01:19Z shyouhei $
+    $Id: datetime.rb 25189 2009-10-02 12:04:37Z akr $
 =end

Modified: MacRuby/trunk/lib/xmlrpc/httpserver.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/httpserver.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/httpserver.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,10 +1,10 @@
 #
-# Implements a simple HTTP-server by using John W. Small's (jsmall at laser.net) 
+# Implements a simple HTTP-server by using John W. Small's (jsmall at laser.net)
 # ruby-generic-server.
-# 
+#
 # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann at ntecs.de)
 #
-# $Id: httpserver.rb 19657 2008-10-01 13:46:53Z mame $
+# $Id: httpserver.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 
@@ -14,8 +14,8 @@
 
   ##
   # handle_obj specifies the object, that receives calls to request_handler
-  # and ip_auth_handler 
-  def initialize(handle_obj, port = 8080, host = DEFAULT_HOST, maxConnections = 4, 
+  # and ip_auth_handler
+  def initialize(handle_obj, port = 8080, host = DEFAULT_HOST, maxConnections = 4,
                  stdlog = $stdout, audit = true, debug = true)
     @handler = handle_obj
     super(port, host, maxConnections, stdlog, audit, debug)
@@ -24,7 +24,7 @@
 private
 
   # Constants -----------------------------------------------
-  
+
   CRLF        = "\r\n"
   HTTP_PROTO  = "HTTP/1.0"
   SERVER_NAME = "HttpServer (Ruby #{RUBY_VERSION})"
@@ -46,27 +46,27 @@
   }
 
   # Classes -------------------------------------------------
-  
+
   class Request
     attr_reader :data, :header, :method, :path, :proto
-    
+
     def initialize(data, method=nil, path=nil, proto=nil)
       @header, @data = Table.new, data
       @method, @path, @proto = method, path, proto
     end
-    
+
     def content_length
       len = @header['Content-Length']
       return nil if len.nil?
-      return len.to_i 
+      return len.to_i
     end
-    
+
   end
-  
+
   class Response
     attr_reader   :header
     attr_accessor :body, :status, :status_message
-    
+
     def initialize(status=200)
       @status = status
       @status_message = nil
@@ -82,7 +82,7 @@
     include Enumerable
 
     def initialize(hash={})
-      @hash = hash 
+      @hash = hash
       update(hash)
     end
 
@@ -113,7 +113,7 @@
 
   def http_header(header=nil)
     new_header = Table.new(DEFAULT_HEADER)
-    new_header.update(header) unless header.nil? 
+    new_header.update(header) unless header.nil?
 
     new_header["Connection"] = "close"
     new_header["Date"]       = http_date(Time.now)
@@ -127,7 +127,7 @@
 
   def http_resp(status_code, status_message=nil, header=nil, body=nil)
     status_message ||= StatusCodeMapping[status_code]
-    
+
     str = ""
     str << "#{HTTP_PROTO} #{status_code} #{status_message}" << CRLF
     http_header(header).writeTo(str)
@@ -137,8 +137,8 @@
   end
 
   # Main Serve Loop -----------------------------------------
-  
-  def serve(io)  
+
+  def serve(io)
     # perform IP authentification
     unless @handler.ip_auth_handler(io)
       io << http_resp(403, "Forbidden")
@@ -149,10 +149,10 @@
     if io.gets =~ /^(\S+)\s+(\S+)\s+(\S+)/
       request = Request.new(io, $1, $2, $3)
     else
-      io << http_resp(400, "Bad Request") 
+      io << http_resp(400, "Bad Request")
       return
     end
-     
+
     # parse HTTP headers
     while (line=io.gets) !~ /^(\n|\r)/
       if line =~ /^([\w-]+):\s*(.*)$/
@@ -160,15 +160,15 @@
       end
     end
 
-    io.binmode    
+    io.binmode
     response = Response.new
 
     # execute request handler
     @handler.request_handler(request, response)
-   
+
     # write response back to the client
     io << http_resp(response.status, response.status_message,
-                    response.header, response.body) 
+                    response.header, response.body)
 
   rescue Exception => e
     io << http_resp(500, "Internal Server Error")

Modified: MacRuby/trunk/lib/xmlrpc/marshal.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/marshal.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/marshal.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,9 +1,9 @@
 #
 # Marshalling of XML-RPC methodCall and methodResponse
-# 
+#
 # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann at ntecs.de)
 #
-# $Id: marshal.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# $Id: marshal.rb 25189 2009-10-02 12:04:37Z akr $
 #
 
 require "xmlrpc/parser"
@@ -17,7 +17,7 @@
     include ParserWriterChooseMixin
 
     # class methods -------------------------------
-   
+
     class << self
 
       def dump_call( methodName, *params )
@@ -52,7 +52,7 @@
       create.methodCall( methodName, *params )
     end
 
-    def dump_response( param ) 
+    def dump_response( param )
       create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param )
     end
 

Modified: MacRuby/trunk/lib/xmlrpc/parser.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/parser.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/parser.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,9 +1,9 @@
 #
 # Parser for XML-RPC call and response
-# 
+#
 # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann at ntecs.de)
 #
-# $Id: parser.rb 19657 2008-10-01 13:46:53Z mame $
+# $Id: parser.rb 27235 2010-04-06 03:01:52Z naruse $
 #
 
 
@@ -60,7 +60,7 @@
       @faultCode   = faultCode
       @faultString = faultString
     end
-    
+
     # returns a hash
     def to_h
       {"faultCode" => @faultCode, "faultString" => @faultString}
@@ -77,7 +77,7 @@
       when "0" then false
       when "1" then true
       else
-        raise "RPC-value of type boolean is wrong" 
+        raise "RPC-value of type boolean is wrong"
       end
     end
 
@@ -122,7 +122,7 @@
     def self.struct(hash)
       # convert to marhalled object
       klass = hash["___class___"]
-      if klass.nil? or Config::ENABLE_MARSHALLING == false 
+      if klass.nil? or Config::ENABLE_MARSHALLING == false
         hash
       else
         begin
@@ -130,10 +130,10 @@
           klass.split("::").each {|const| mod = mod.const_get(const.strip)}
 
           obj = mod.allocate
-          
+
           hash.delete "___class___"
-          hash.each {|key, value| 
-            obj.instance_variable_set("@#{ key }", value) if key =~ /^([\w_][\w_0-9]*)$/
+          hash.each {|key, value|
+            obj.instance_variable_set("@#{ key }", value) if key =~ /^([a-zA-Z_]\w*)$/
           }
           obj
         rescue
@@ -143,11 +143,11 @@
     end
 
     def self.fault(hash)
-      if hash.kind_of? Hash and hash.size == 2 and 
-        hash.has_key? "faultCode" and hash.has_key? "faultString" and 
+      if hash.kind_of? Hash and hash.size == 2 and
+        hash.has_key? "faultCode" and hash.has_key? "faultString" and
         hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String
 
-        XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) 
+        XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"])
       else
         raise "wrong fault-structure: #{hash.inspect}"
       end
@@ -182,9 +182,9 @@
             # TODO: add nil?
             unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName
 
-               if node.nodeName == "value" 
+               if node.nodeName == "value"
                  if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil?
-                   remove << nd if nd.nodeValue.strip == "" 
+                   remove << nd if nd.nodeValue.strip == ""
                  end
                else
                  remove << nd if nd.nodeValue.strip == ""
@@ -194,7 +194,7 @@
             remove << nd
           else
             removeWhitespacesAndComments(nd)
-          end 
+          end
         end
 
         remove.each { |i| node.removeChild(i) }
@@ -203,13 +203,13 @@
 
       def nodeMustBe(node, name)
         cmp = case name
-        when Array 
+        when Array
           name.include?(node.nodeName)
         when String
           name == node.nodeName
         else
           raise "error"
-        end  
+        end
 
         if not cmp then
           raise "wrong xml-rpc (name)"
@@ -233,7 +233,7 @@
 
       def assert(b)
         if not b then
-          raise "assert-fail" 
+          raise "assert-fail"
         end
       end
 
@@ -249,21 +249,21 @@
           raise "wrong xml-rpc (size)"
         end
       end
-     
 
+
       def integer(node)
         #TODO: check string for float because to_i returnsa
         #      0 when wrong string
-         nodeMustBe(node, %w(i4 int))    
+         nodeMustBe(node, %w(i4 int))
         hasOnlyOneChild(node)
-        
+
         Convert.int(text(node.firstChild))
       end
 
       def boolean(node)
-        nodeMustBe(node, "boolean")    
+        nodeMustBe(node, "boolean")
         hasOnlyOneChild(node)
-        
+
         Convert.boolean(text(node.firstChild))
       end
 
@@ -274,36 +274,36 @@
       end
 
       def string(node)
-        nodeMustBe(node, "string")    
+        nodeMustBe(node, "string")
         text_zero_one(node)
       end
 
       def double(node)
         #TODO: check string for float because to_f returnsa
         #      0.0 when wrong string
-        nodeMustBe(node, "double")    
+        nodeMustBe(node, "double")
         hasOnlyOneChild(node)
-        
+
         Convert.double(text(node.firstChild))
       end
 
       def dateTime(node)
         nodeMustBe(node, "dateTime.iso8601")
         hasOnlyOneChild(node)
-        
+
         Convert.dateTime( text(node.firstChild) )
       end
 
       def base64(node)
         nodeMustBe(node, "base64")
         #hasOnlyOneChild(node)
-         
+
         Convert.base64(text_zero_one(node))
       end
 
       def member(node)
         nodeMustBe(node, "member")
-        assert( node.childNodes.to_a.size == 2 ) 
+        assert( node.childNodes.to_a.size == 2 )
 
         [ name(node[0]), value(node[1]) ]
       end
@@ -311,13 +311,13 @@
       def name(node)
         nodeMustBe(node, "name")
         #hasOnlyOneChild(node)
-        text_zero_one(node) 
+        text_zero_one(node)
       end
 
       def array(node)
         nodeMustBe(node, "array")
-        hasOnlyOneChild(node, "data") 
-        data(node.firstChild)  
+        hasOnlyOneChild(node, "data")
+        data(node.firstChild)
       end
 
       def data(node)
@@ -325,15 +325,15 @@
 
         node.childNodes.to_a.collect do |val|
           value(val)
-        end 
+        end
       end
 
       def param(node)
         nodeMustBe(node, "param")
         hasOnlyOneChild(node, "value")
-        value(node.firstChild) 
+        value(node.firstChild)
       end
- 
+
       def methodResponse(node)
         nodeMustBe(node, "methodResponse")
         hasOnlyOneChild(node, %w(params fault))
@@ -341,7 +341,7 @@
 
         case child.nodeName
         when "params"
-          [ true, params(child,false) ] 
+          [ true, params(child,false) ]
         when "fault"
           [ false, fault(child) ]
         else
@@ -353,13 +353,13 @@
       def methodName(node)
         nodeMustBe(node, "methodName")
         hasOnlyOneChild(node)
-        text(node.firstChild) 
+        text(node.firstChild)
       end
 
       def params(node, call=true)
         nodeMustBe(node, "params")
 
-        if call 
+        if call
           node.childNodes.to_a.collect do |n|
             param(n)
           end
@@ -372,7 +372,7 @@
       def fault(node)
         nodeMustBe(node, "fault")
         hasOnlyOneChild(node, "value")
-        f = value(node.firstChild) 
+        f = value(node.firstChild)
         Convert.fault(f)
       end
 
@@ -388,13 +388,13 @@
       end
 
       def struct(node)
-        nodeMustBe(node, "struct")    
+        nodeMustBe(node, "struct")
 
         hash = {}
         node.childNodes.to_a.each do |me|
-          n, v = member(me)  
+          n, v = member(me)
           hash[n] = v
-        end 
+        end
 
         Convert.struct(hash)
       end
@@ -403,9 +403,9 @@
       def value(node)
         nodeMustBe(node, "value")
         nodes = node.childNodes.to_a.size
-        if nodes == 0 
+        if nodes == 0
           return ""
-        elsif nodes > 1 
+        elsif nodes > 1
           raise "wrong xml-rpc (size)"
         end
 
@@ -423,14 +423,14 @@
           when "dateTime.iso8601" then dateTime(child)
           when "base64"           then base64(child)
           when "struct"           then struct(child)
-          when "array"            then array(child) 
-          when "nil"              
+          when "array"            then array(child)
+          when "nil"
             if Config::ENABLE_NIL_PARSER
               v_nil(child)
             else
               raise "wrong/unknown XML-RPC type 'nil'"
             end
-          else 
+          else
             raise "wrong/unknown XML-RPC type"
           end
         else
@@ -441,7 +441,7 @@
 
       def methodCall(node)
         nodeMustBe(node, "methodCall")
-        assert( (1..2).include?( node.childNodes.to_a.size ) ) 
+        assert( (1..2).include?( node.childNodes.to_a.size ) )
         name = methodName(node[0])
 
         if node.childNodes.to_a.size == 2 then
@@ -461,7 +461,7 @@
         raise "No valid method response!" if parser.method_name != nil
         if parser.fault != nil
           # is a fault structure
-          [false, parser.fault] 
+          [false, parser.fault]
         else
           # is a normal return value
           raise "Missing return value!" if parser.params.size == 0
@@ -508,7 +508,7 @@
           @value = nil
         when "nil"
           raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER
-          @value = :nil 
+          @value = :nil
         when "array"
           @val_stack << @values
           @values = []
@@ -517,7 +517,7 @@
           @name = []
 
           @structs << @struct
-          @struct = {} 
+          @struct = {}
         end
       end
 
@@ -538,7 +538,7 @@
           @value = Convert.base64(@data)
         when "value"
           @value = @data if @value.nil?
-          @values << (@value == :nil ? nil : @value) 
+          @values << (@value == :nil ? nil : @value)
         when "array"
           @value = @values
           @values = @val_stack.pop
@@ -548,9 +548,9 @@
           @name = @names.pop
           @struct = @structs.pop
         when "name"
-          @name[0] = @data 
+          @name[0] = @data
         when "member"
-          @struct[@name[0]] = @values.pop 
+          @struct[@name[0]] = @values.pop
 
         when "param"
           @params << @values[0]
@@ -560,7 +560,7 @@
           @fault = Convert.fault(@values[0])
 
         when "methodName"
-          @method_name = @data 
+          @method_name = @data
         end
 
         @data = nil
@@ -592,7 +592,7 @@
         @parser_class = XMLRPCParser
       end
 
-      class XMLRPCParser 
+      class XMLRPCParser
         include StreamParserMixin
 
         def parse(str)
@@ -620,9 +620,9 @@
       def initialize
         require "xmltreebuilder"
 
-        # The new XMLParser library (0.6.2+) uses a slightly different DOM implementation. 
+        # The new XMLParser library (0.6.2+) uses a slightly different DOM implementation.
         # The following code removes the differences between both versions.
-        if defined? XML::DOM::Builder 
+        if defined? XML::DOM::Builder
           return if defined? XML::DOM::Node::DOCUMENT # code below has been already executed
           klass = XML::DOM::Node
           klass.const_set("DOCUMENT", klass::DOCUMENT_NODE)
@@ -637,8 +637,8 @@
       def _nodeType(node)
         tp = node.nodeType
         if tp == XML::SimpleTree::Node::TEXT then :TEXT
-        elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT 
-        elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT 
+        elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT
+        elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT
         else :ELSE
         end
       end
@@ -647,14 +647,14 @@
       def methodResponse_document(node)
         assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
         hasOnlyOneChild(node, "methodResponse")
-        
+
         methodResponse(node.firstChild)
       end
 
       def methodCall_document(node)
         assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
         hasOnlyOneChild(node, "methodCall")
-        
+
         methodCall(node.firstChild)
       end
 
@@ -688,7 +688,7 @@
       end
 
       def createCleanedTree(str)
-        doc = ::NQXML::TreeParser.new(str).document.rootNode 
+        doc = ::NQXML::TreeParser.new(str).document.rootNode
         removeWhitespacesAndComments(doc)
         doc
       end
@@ -701,7 +701,7 @@
         @parser_class = StreamListener
       end
 
-      class StreamListener 
+      class StreamListener
         include StreamParserMixin
 
         alias :tag_start :startElement
@@ -716,7 +716,7 @@
         def parse(str)
           parser = REXML::Document.parse_stream(str, self)
         end
-      end 
+      end
 
     end
     # ---------------------------------------------------------------------------
@@ -751,7 +751,7 @@
           startElement(name)
           endElement(name)
         end
-       
+
         def on_chardata(str)
           character(str)
         end
@@ -784,7 +784,7 @@
         # valid_name?
         # valid_chardata?
         # valid_char?
-        # parse_error  
+        # parse_error
 
       end
     end
@@ -792,8 +792,8 @@
     XMLParser   = XMLTreeParser
     NQXMLParser = NQXMLTreeParser
 
-    Classes = [XMLStreamParser, XMLTreeParser, 
-               NQXMLStreamParser, NQXMLTreeParser, 
+    Classes = [XMLStreamParser, XMLTreeParser,
+               NQXMLStreamParser, NQXMLTreeParser,
                REXMLStreamParser, XMLScanStreamParser]
 
     # yields an instance of each installed parser

Modified: MacRuby/trunk/lib/xmlrpc/server.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/server.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/server.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -14,23 +14,23 @@
 = XMLRPC::BasicServer
 == Description
 Is the base class for all XML-RPC server-types (CGI, standalone).
-You can add handler and set a default handler. 
+You can add handler and set a default handler.
 Do not use this server, as this is/should be an abstract class.
 
 === How the method to call is found
-The arity (number of accepted arguments) of a handler (method or (({Proc})) object) is 
-compared to the given arguments submitted by the client for a RPC ((-Remote Procedure Call-)). 
-A handler is only called if it accepts the number of arguments, otherwise the search 
-for another handler will go on. When at the end no handler was found, 
+The arity (number of accepted arguments) of a handler (method or (({Proc})) object) is
+compared to the given arguments submitted by the client for a RPC ((-Remote Procedure Call-)).
+A handler is only called if it accepts the number of arguments, otherwise the search
+for another handler will go on. When at the end no handler was found,
 the ((<default_handler|XMLRPC::BasicServer#set_default_handler>)) will be called.
 With this technique it is possible to do overloading by number of parameters, but
 only for (({Proc})) handler, because you cannot define two methods of the same name in
-the same class. 
+the same class.
 
 
 == Class Methods
 --- XMLRPC::BasicServer.new( class_delim="." )
-    Creates a new (({XMLRPC::BasicServer})) instance, which should not be 
+    Creates a new (({XMLRPC::BasicServer})) instance, which should not be
     done, because (({XMLRPC::BasicServer})) is an abstract class. This
     method should be called from a subclass indirectly by a (({super})) call
     in the method (({initialize})). The paramter ((|class_delim|)) is used
@@ -40,24 +40,24 @@
 == Instance Methods
 --- XMLRPC::BasicServer#add_handler( name, signature=nil, help=nil ) { aBlock }
     Adds ((|aBlock|)) to the list of handlers, with ((|name|)) as the name of the method.
-    Parameters ((|signature|)) and ((|help|)) are used by the Introspection method if specified, 
-    where ((|signature|)) is either an Array containing strings each representing a type of it's 
-    signature (the first is the return value) or an Array of Arrays if the method has multiple 
+    Parameters ((|signature|)) and ((|help|)) are used by the Introspection method if specified,
+    where ((|signature|)) is either an Array containing strings each representing a type of it's
+    signature (the first is the return value) or an Array of Arrays if the method has multiple
     signatures. Value type-names are "int, boolean, double, string, dateTime.iso8601, base64, array, struct".
 
     Parameter ((|help|)) is a String with informations about how to call this method etc.
 
     A handler method or code-block can return the types listed at
-    ((<XMLRPC::Client#call|URL:client.html#index:0>)). 
-    When a method fails, it can tell it the client by throwing an 
+    ((<XMLRPC::Client#call|URL:client.html#index:0>)).
+    When a method fails, it can tell it the client by throwing an
     (({XMLRPC::FaultException})) like in this example:
         s.add_handler("michael.div") do |a,b|
           if b == 0
             raise XMLRPC::FaultException.new(1, "division by zero")
           else
-            a / b 
+            a / b
           end
-        end 
+        end
     The client gets in the case of (({b==0})) an object back of type
     (({XMLRPC::FaultException})) that has a ((|faultCode|)) and ((|faultString|))
     field.
@@ -67,10 +67,10 @@
     To add an object write:
         server.add_handler("michael", MyHandlerClass.new)
     All public methods of (({MyHandlerClass})) are accessible to
-    the XML-RPC clients by (('michael."name of method"')). This is 
-    where the ((|class_delim|)) in ((<new|XMLRPC::BasicServer.new>)) 
-    has it's role, a XML-RPC method-name is defined by 
-    ((|prefix|)) + ((|class_delim|)) + (('"name of method"')). 
+    the XML-RPC clients by (('michael."name of method"')). This is
+    where the ((|class_delim|)) in ((<new|XMLRPC::BasicServer.new>))
+    has it's role, a XML-RPC method-name is defined by
+    ((|prefix|)) + ((|class_delim|)) + (('"name of method"')).
 
 --- XMLRPC::BasicServer#add_handler( interface, obj )
     This is the third form of ((<add_handler|XMLRPC::BasicServer#add_handler>)).
@@ -91,11 +91,11 @@
     It is a (({Proc})) object or (({nil})).
 
 --- XMLRPC::BasicServer#set_default_handler ( &handler )
-    Sets ((|handler|)) as the default-handler, which is called when 
+    Sets ((|handler|)) as the default-handler, which is called when
     no handler for a method-name is found. ((|handler|)) is a code-block.
     The default-handler is called with the (XML-RPC) method-name as first argument, and
     the other arguments are the parameters given by the client-call.
-  
+
     If no block is specified the default of (({XMLRPC::BasicServer})) is used, which raises a
     XMLRPC::FaultException saying "method missing".
 
@@ -103,7 +103,7 @@
 --- XMLRPC::BasicServer#set_writer( writer )
     Sets the XML writer to use for generating XML output.
     Should be an instance of a class from module (({XMLRPC::XMLWriter})).
-    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used. 
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used.
 
 --- XMLRPC::BasicServer#set_parser( parser )
     Sets the XML parser to use for parsing XML documents.
@@ -111,7 +111,7 @@
     If this method is not called, then (({XMLRPC::Config::DEFAULT_PARSER})) is used.
 
 --- XMLRPC::BasicServer#add_introspection
-    Adds the introspection handlers "system.listMethods", "system.methodSignature" and "system.methodHelp", 
+    Adds the introspection handlers "system.listMethods", "system.methodSignature" and "system.methodHelp",
     where only the first one works.
 
 --- XMLRPC::BasicServer#add_multicall
@@ -123,7 +123,7 @@
 --- XMLRPC::BasicServer#set_service_hook ( &handler )
     A service-hook is called for each service request (RPC).
     You can use a service-hook for example to wrap existing methods and catch exceptions of them or
-    convert values to values recognized by XMLRPC. You can disable it by passing (({nil})) as parameter  
+    convert values to values recognized by XMLRPC. You can disable it by passing (({nil})) as parameter
     ((|handler|)) .
 
     The service-hook is called with a (({Proc})) object and with the parameters for this (({Proc})).
@@ -132,8 +132,8 @@
        server.set_service_hook {|obj, *args|
          begin
            ret = obj.call(*args)  # call the original service-method
-           # could convert the return value 
-         resuce
+           # could convert the return value
+         rescue
            # rescue exceptions
          end
        }
@@ -157,7 +157,7 @@
   include ParserWriterChooseMixin
   include ParseContentType
 
-  ERR_METHOD_MISSING        = 1 
+  ERR_METHOD_MISSING        = 1
   ERR_UNCAUGHT_EXCEPTION    = 2
   ERR_MC_WRONG_PARAM        = 3
   ERR_MC_MISSING_PARAMS     = 4
@@ -169,7 +169,7 @@
 
   def initialize(class_delim=".")
     @handler = []
-    @default_handler = nil 
+    @default_handler = nil
     @service_hook = nil
 
     @class_delim = class_delim
@@ -183,7 +183,7 @@
   def add_handler(prefix, obj_or_signature=nil, help=nil, &block)
     if block_given?
       # proc-handler
-      @handler << [prefix, block, obj_or_signature, help]   
+      @handler << [prefix, block, obj_or_signature, help]
     else
       if prefix.kind_of? String
         # class-handler
@@ -208,7 +208,7 @@
     @service_hook = handler
     self
   end
- 
+
   def get_default_handler
     @default_handler
   end
@@ -216,18 +216,18 @@
   def set_default_handler (&handler)
     @default_handler = handler
     self
-  end  
+  end
 
   def add_multicall
     add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs|
-      unless arrStructs.is_a? Array 
+      unless arrStructs.is_a? Array
         raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array")
       end
 
       arrStructs.collect {|call|
         if call.is_a? Hash
           methodName = call["methodName"]
-          params     = call["params"]  
+          params     = call["params"]
 
           if params.nil?
             multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params")
@@ -246,16 +246,16 @@
                   [val]
                 else
                   # exception
-                  multicall_fault(val.faultCode, val.faultString) 
+                  multicall_fault(val.faultCode, val.faultString)
                 end
               end
             end
-          end  
-           
+          end
+
         else
           multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct")
         end
-      } 
+      }
     end # end add_handler
     self
   end
@@ -284,7 +284,7 @@
             sig.each {|s| sigs << s}
           else
             # sig is a single signature, e.g. ["array"]
-            sigs << sig 
+            sigs << sig
           end
         end
       end
@@ -292,11 +292,11 @@
     end
 
     add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth|
-      help = nil 
+      help = nil
       @handler.each do |name, obj, sig, hlp|
-        if obj.kind_of? Proc and name == meth 
+        if obj.kind_of? Proc and name == meth
           help = hlp
-          break      
+          break
         end
       end
       help || ""
@@ -306,18 +306,18 @@
   end
 
 
-  
+
   def process(data)
-    method, params = parser().parseMethodCall(data) 
+    method, params = parser().parseMethodCall(data)
     handle(method, *params)
   end
- 
+
   private # --------------------------------------------------------------
 
   def multicall_fault(nr, str)
     {"faultCode" => nr, "faultString" => str}
   end
- 
+
   #
   # method dispatch
   #
@@ -333,17 +333,17 @@
 
       if check_arity(obj, args.size)
         if @service_hook.nil?
-          return obj.call(*args) 
+          return obj.call(*args)
         else
           return @service_hook.call(obj, *args)
         end
       end
-    end 
- 
+    end
+
     if @default_handler.nil?
       raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!")
     else
-      @default_handler.call(methodname, *args) 
+      @default_handler.call(methodname, *args)
     end
   end
 
@@ -357,7 +357,7 @@
     if ary >= 0
       n_args == ary
     else
-      n_args >= (ary+1).abs 
+      n_args >= (ary+1).abs
     end
   end
 
@@ -366,8 +366,8 @@
   def call_method(methodname, *args)
     begin
       [true, dispatch(methodname, *args)]
-    rescue XMLRPC::FaultException => e  
-      [false, e]  
+    rescue XMLRPC::FaultException => e
+      [false, e]
     rescue Exception => e
       [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")]
     end
@@ -388,9 +388,9 @@
 = XMLRPC::CGIServer
 == Synopsis
     require "xmlrpc/server"
- 
-    s = XMLRPC::CGIServer.new     
 
+    s = XMLRPC::CGIServer.new
+
     s.add_handler("michael.add") do |a,b|
       a + b
     end
@@ -399,15 +399,15 @@
       if b == 0
         raise XMLRPC::FaultException.new(1, "division by zero")
       else
-        a / b 
+        a / b
       end
-    end 
+    end
 
     s.set_default_handler do |name, *args|
       raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
                                        " or wrong number of parameters!")
     end
-  
+
     s.serve
 
 == Description
@@ -419,7 +419,7 @@
 == Class Methods
 --- XMLRPC::CGIServer.new( *a )
     Creates a new (({XMLRPC::CGIServer})) instance. All parameters given
-    are by-passed to ((<XMLRPC::BasicServer.new>)). You can only create 
+    are by-passed to ((<XMLRPC::BasicServer.new>)). You can only create
     ((*one*)) (({XMLRPC::CGIServer})) instance, because more than one makes
     no sense.
 
@@ -427,7 +427,7 @@
 --- XMLRPC::CGIServer#serve
     Call this after you have added all you handlers to the server.
     This method processes a XML-RPC methodCall and sends the answer
-    back to the client. 
+    back to the client.
     Make sure that you don't write to standard-output in a handler, or in
     any other part of your program, this would case a CGI-based server to fail!
 =end
@@ -443,14 +443,14 @@
   def initialize(*a)
     super(*a)
   end
-  
+
   def serve
     catch(:exit_serve) {
       length = ENV['CONTENT_LENGTH'].to_i
 
-      http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST" 
+      http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST"
       http_error(400, "Bad Request")        unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml"
-      http_error(411, "Length Required")    unless length > 0 
+      http_error(411, "Length Required")    unless length > 0
 
       # TODO: do we need a call to binmode?
       $stdin.binmode if $stdin.respond_to? :binmode
@@ -467,7 +467,7 @@
 
   def http_error(status, message)
     err = "#{status} #{message}"
-    msg = <<-"MSGEND" 
+    msg = <<-"MSGEND"
       <html>
         <head>
           <title>#{err}</title>
@@ -487,7 +487,7 @@
     h = {}
     header.each {|key, value| h[key.to_s.capitalize] = value}
     h['Status']         ||= "200 OK"
-    h['Content-length'] ||= body.size.to_s 
+    h['Content-length'] ||= body.size.to_s
 
     str = ""
     h.each {|key, value| str << "#{key}: #{value}\r\n"}
@@ -507,7 +507,7 @@
 
 == Superclass
 ((<XMLRPC::BasicServer>))
-=end 
+=end
 
 class ModRubyServer < BasicServer
 
@@ -523,9 +523,9 @@
 
       length = header['Content-length'].to_i
 
-      http_error(405, "Method Not Allowed") unless @ap.request_method  == "POST" 
+      http_error(405, "Method Not Allowed") unless @ap.request_method  == "POST"
       http_error(400, "Bad Request")        unless parse_content_type(header['Content-type']).first == "text/xml"
-      http_error(411, "Length Required")    unless length > 0 
+      http_error(411, "Length Required")    unless length > 0
 
       # TODO: do we need a call to binmode?
       @ap.binmode
@@ -542,7 +542,7 @@
 
   def http_error(status, message)
     err = "#{status} #{message}"
-    msg = <<-"MSGEND" 
+    msg = <<-"MSGEND"
       <html>
         <head>
           <title>#{err}</title>
@@ -562,12 +562,12 @@
     h = {}
     header.each {|key, value| h[key.to_s.capitalize] = value}
     h['Status']         ||= "200 OK"
-    h['Content-length'] ||= body.size.to_s 
+    h['Content-length'] ||= body.size.to_s
 
     h.each {|key, value| @ap.headers_out[key] = value }
-    @ap.content_type = h["Content-type"] 
-    @ap.status = status.to_i 
-    @ap.send_http_header 
+    @ap.content_type = h["Content-type"]
+    @ap.status = status.to_i
+    @ap.send_http_header
 
     @ap.print body
   end
@@ -578,9 +578,9 @@
 = XMLRPC::Server
 == Synopsis
     require "xmlrpc/server"
- 
-    s = XMLRPC::Server.new(8080) 
 
+    s = XMLRPC::Server.new(8080)
+
     s.add_handler("michael.add") do |a,b|
       a + b
     end
@@ -589,15 +589,15 @@
       if b == 0
         raise XMLRPC::FaultException.new(1, "division by zero")
       else
-        a / b 
+        a / b
       end
-    end 
+    end
 
     s.set_default_handler do |name, *args|
       raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
                                        " or wrong number of parameters!")
     end
- 
+
     s.serve
 
 == Description
@@ -610,13 +610,13 @@
 == Class Methods
 --- XMLRPC::Server.new( port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a )
     Creates a new (({XMLRPC::Server})) instance, which is a XML-RPC server listening on
-    port ((|port|)) and accepts requests for the host ((|host|)), which is by default only the localhost. 
+    port ((|port|)) and accepts requests for the host ((|host|)), which is by default only the localhost.
     The server is not started, to start it you have to call ((<serve|XMLRPC::Server#serve>)).
 
     Parameters ((|audit|)) and ((|debug|)) are obsolete!
 
-    All additionally given parameters in ((|*a|)) are by-passed to ((<XMLRPC::BasicServer.new>)). 
-    
+    All additionally given parameters in ((|*a|)) are by-passed to ((<XMLRPC::BasicServer.new>)).
+
 == Instance Methods
 --- XMLRPC::Server#serve
     Call this after you have added all you handlers to the server.
@@ -624,7 +624,7 @@
 
 --- XMLRPC::Server#shutdown
     Stops and shuts the server down.
-    
+
 =end
 
 class WEBrickServlet < BasicServer; end # forward declaration
@@ -634,26 +634,22 @@
   def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a)
     super(*a)
     require 'webrick'
-    @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections, 
+    @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections,
                                       :Logger => WEBrick::Log.new(stdlog))
     @server.mount("/", self)
   end
-  
+
   def serve
-    if RUBY_PLATFORM =~ /mingw|mswin32/
-      signals = [1]
-    else
-      signals = %w[INT TERM HUP]
-    end
+    signals = %w[INT TERM HUP] & Signal.list.keys
     signals.each { |signal| trap(signal) { @server.shutdown } }
 
     @server.start
   end
-  
+
   def shutdown
     @server.shutdown
   end
- 
+
 end
 
 =begin
@@ -672,16 +668,16 @@
       if b == 0
         raise XMLRPC::FaultException.new(1, "division by zero")
       else
-        a / b 
+        a / b
       end
-    end 
+    end
 
     s.set_default_handler do |name, *args|
       raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
                                        " or wrong number of parameters!")
     end
 
-    httpserver = WEBrick::HTTPServer.new(:Port => 8080)    
+    httpserver = WEBrick::HTTPServer.new(:Port => 8080)
     httpserver.mount("/RPC2", s)
     trap("HUP") { httpserver.shutdown }   # use 1 instead of "HUP" on Windows
     httpserver.start
@@ -695,7 +691,7 @@
 --- XMLRPC::WEBrickServlet#get_valid_ip
     Return the via method ((<set_valid_ip|XMLRPC::Server#set_valid_ip>)) specified
     valid IP addresses.
- 
+
 == Description
 Implements a servlet for use with WEBrick, a pure Ruby (HTTP-) server framework.
 
@@ -711,10 +707,10 @@
     @valid_ip = nil
   end
 
-  # deprecated from WEBrick/1.2.2. 
+  # deprecated from WEBrick/1.2.2.
   # but does not break anything.
   def require_path_info?
-    false 
+    false
   end
 
   def get_instance(config, *options)
@@ -736,7 +732,7 @@
 
   def service(request, response)
 
-    if @valid_ip 
+    if @valid_ip
       raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip }
     end
 
@@ -745,9 +741,9 @@
             "unsupported method `#{request.request_method}'."
     end
 
-    if parse_content_type(request['Content-type']).first != "text/xml" 
+    if parse_content_type(request['Content-type']).first != "text/xml"
       raise WEBrick::HTTPStatus::BadRequest
-    end 
+    end
 
     length = (request['Content-length'] || 0).to_i
 
@@ -760,14 +756,14 @@
     end
 
     resp = process(data)
-    if resp.nil? or resp.size <= 0  
+    if resp.nil? or resp.size <= 0
       raise WEBrick::HTTPStatus::InternalServerError
     end
 
     response.status = 200
     response['Content-Length'] = resp.size
     response['Content-Type']   = "text/xml; charset=utf-8"
-    response.body = resp 
+    response.body = resp
   end
 end
 
@@ -777,6 +773,6 @@
 
 =begin
 = History
-    $Id: server.rb 20879 2008-12-19 11:37:33Z yugui $    
+    $Id: server.rb 26986 2010-03-20 03:30:59Z nobu $
 =end
 

Modified: MacRuby/trunk/lib/xmlrpc/utils.rb
===================================================================
--- MacRuby/trunk/lib/xmlrpc/utils.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/lib/xmlrpc/utils.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,12 +1,12 @@
 #
 # Defines ParserWriterChooseMixin, which makes it possible to choose a
 # different XML writer and/or XML parser then the default one.
-# The Mixin is used in client.rb (class Client) and server.rb (class 
+# The Mixin is used in client.rb (class Client) and server.rb (class
 # BasicServer)
-# 
+#
 # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann at ntecs.de)
 #
-# $Id: utils.rb 19657 2008-10-01 13:46:53Z mame $ 
+# $Id: utils.rb 27537 2010-04-28 18:51:35Z jeg2 $
 #
 
 module XMLRPC
@@ -15,7 +15,7 @@
   # This module enables a user-class to be marshalled
   # by XML-RPC for Ruby into a Hash, with one additional
   # key/value pair "___class___" => ClassName
-  # 
+  #
   module Marshallable
   end
 
@@ -72,9 +72,9 @@
       mname = nil
       sig = [sig] if sig.kind_of? String
 
-      sig = sig.collect do |s| 
+      sig = sig.collect do |s|
         name, si = parse_sig(s)
-        raise "Wrong signatures!" if mname != nil and name != mname 
+        raise "Wrong signatures!" if mname != nil and name != mname
         mname = name
         si
       end
@@ -83,12 +83,12 @@
     end
 
     private # ---------------------------------
-  
+
     def parse_sig(sig)
       # sig is a String
       if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/
         params = [$1]
-        name   = $2.strip 
+        name   = $2.strip
         $4.split(",").each {|i| params << i.strip} if $4 != nil
         return name, params
       else
@@ -109,10 +109,10 @@
       instance_eval(&p)
     end
 
-    def get_methods(obj, delim=".") 
+    def get_methods(obj, delim=".")
       prefix = @prefix + delim
-      @methods.collect { |name, meth, sig, help| 
-        [prefix + name, obj.method(meth).to_proc, sig, help] 
+      @methods.collect { |name, meth, sig, help|
+        [prefix + name.to_s, obj.method(meth).to_proc, sig, help]
       }
     end
 
@@ -132,7 +132,7 @@
     def get_methods(obj, delim=".")
       prefix = @prefix + delim
       obj.class.public_instance_methods(false).collect { |name|
-        [prefix + name, obj.method(name).to_proc, nil, nil] 
+        [prefix + name.to_s, obj.method(name).to_proc, nil, nil]
       }
     end
   end
@@ -141,16 +141,16 @@
   end # module Service
 
 
-  # 
+  #
   # short-form to create a Service::Interface
   #
   def self.interface(prefix, &p)
-    Service::Interface.new(prefix, &p)  
+    Service::Interface.new(prefix, &p)
   end
 
   # short-cut for creating a PublicInstanceMethodsInterface
   def self.iPIMethods(prefix)
-    Service::PublicInstanceMethodsInterface.new(prefix) 
+    Service::PublicInstanceMethodsInterface.new(prefix)
   end
 
 

Modified: MacRuby/trunk/numeric.c
===================================================================
--- MacRuby/trunk/numeric.c	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/numeric.c	2010-05-18 01:40:51 UTC (rev 4114)
@@ -265,6 +265,20 @@
 
 /*
  *  call-seq:
+ *     num.i  ->  Complex(0,num)
+ *
+ *  Returns the corresponding imaginary number.
+ *  Not available for complex numbers.
+ */
+
+static VALUE
+num_imaginary(VALUE num, SEL sel)
+{
+    return rb_complex_new(INT2FIX(0), num);
+}
+
+/*
+ *  call-seq:
  *     -num    => numeric
  *
  *  Unary Minus---Returns the receiver's value, negated.
@@ -3380,6 +3394,7 @@
     rb_objc_define_method(rb_cNumeric, "initialize_copy", num_init_copy, 1);
     rb_objc_define_method(rb_cNumeric, "coerce", num_coerce, 1);
 
+    rb_objc_define_method(rb_cNumeric, "i", num_imaginary, 0);
     rb_objc_define_method(rb_cNumeric, "+@", num_uplus, 0);
     rb_objc_define_method(rb_cNumeric, "-@", num_uminus, 0);
     rb_objc_define_method(rb_cNumeric, "<=>", num_cmp, 1);

Modified: MacRuby/trunk/rakelib/builder/builder.rb
===================================================================
--- MacRuby/trunk/rakelib/builder/builder.rb	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/rakelib/builder/builder.rb	2010-05-18 01:40:51 UTC (rev 4114)
@@ -11,7 +11,6 @@
 
 EXTENSIONS = %w{
   ripper digest etc readline libyaml fcntl socket zlib bigdecimal openssl json
-  nkf
 }.sort
 
 class Builder

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/cookie/value_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/cookie/value_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/cookie/value_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:CGI::Cookie#value is in synch with self
-fails:CGI::Cookie#value= automatically converts the passed Object to an Array using #Array
-fails:CGI::Cookie#value= does keep self and the values in sync

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/initialize_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/initialize_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:CGI#initialize when passed no arguments does not extend self with CGI::HtmlExtension
-fails:CGI#initialize when passed no arguments does not extend self with any of the other HTML modules

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/unescape_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/unescape_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/cgi/unescape_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -0,0 +1 @@
+fails:CGI.unescape url-decodes the passed argument

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/csv/parse_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/csv/parse_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/csv/parse_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,7 +0,0 @@
-fails:CSV.parse parses 'foo,bar,baz' into [['foo','bar','baz']]
-fails:CSV.parse parses 'foo,baz' into [[foo,nil,baz]]
-fails:"CSV.parse parses 'foo,bar\nbaz,quz' into [['foo','bar'],['baz','quz']]"
-fails:"CSV.parse parses 'foo,bar'\nbaz' into [['foo','bar'],['baz']]"
-fails:"CSV.parse parses 'foo\nbar,baz' into [['foo'],['bar','baz']]"
-fails:CSV.parse parses 'foo;bar' into [['foo','bar']] with a separator of ;
-fails:"CSV.parse parses 'foo;bar\nbaz;quz' into [['foo','bar'],['baz','quz']] with a separator of ;"

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/date/strptime_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/date/strptime_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/date/strptime_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Date#strptime parses a week number for a week starting on Monday

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/getoptlong/set_options_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/getoptlong/set_options_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/getoptlong/set_options_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:GetoptLong#set_options raises an ArgumentError if one of the given arguments is not an Array

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/close_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/close_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/close_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Logger::LogDevice#close closes the LogDevice's stream

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/write_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/write_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/logger/device/write_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Logger::LogDevice#write fails if the device is already closed

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/logger/logger/close_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/logger/logger/close_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/logger/logger/close_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Logger#close closes the logging device

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/build_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/build_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/build_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,9 +0,0 @@
-fails:Matrix.build returns a Matrix object of the given size
-fails:Matrix.build builds the Matrix using the given block
-fails:Matrix.build iterates through the first row, then the second, ...
-fails:Matrix.build returns an Enumerator is no block is given
-fails:Matrix.build requires integers as parameters
-fails:Matrix.build requires non-negative integers
-fails:Matrix.build returns empty Matrix if one argument is zero
-fails:Matrix.build tries to calls :to_int on arguments
-fails:Matrix.build builds an nxn Matrix when given only one argument

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/collect_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/collect_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/collect_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#collect returns an enumerator if no block is given

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_size_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_size_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_size_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#column_size returns 0 for empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#column returns self when called with a block
-fails:Matrix#column returns nil when out of bounds
-fails:Matrix#column never yields when out of bounds

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_vector_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_vector_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/column_vector_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix.column_vector returns an empty Matrix when called with an empty Array

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/columns_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/columns_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/columns_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix.columns handles empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conj_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conj_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conj_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:Matrix#conj returns a matrix with all entries 'conjugated'
-fails:Matrix#conj returns empty matrices on the same size if empty

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conjugate_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conjugate_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/conjugate_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:Matrix#conjugate returns a matrix with all entries 'conjugated'
-fails:Matrix#conjugate returns empty matrices on the same size if empty

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/constructor_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/constructor_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/constructor_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +0,0 @@
-fails:Matrix.[] requires arrays as parameters
-fails:Matrix.[] creates an empty Matrix with no arguments
-fails:Matrix.[] raises for non-rectangular matrices
-fails:Matrix.[] accepts vector arguments
-fails:Matrix.[] tries to calls :to_ary on arguments

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/det_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/det_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/det_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#det returns 1 for an empty Matrix
-fails:Matrix#det returns the determinant even for Matrices containing 0 as first entry
-fails:Matrix#det raises an error for rectangular matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/determinant_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/determinant_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/determinant_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#determinant returns 1 for an empty Matrix
-fails:Matrix#determinant returns the determinant even for Matrices containing 0 as first entry
-fails:Matrix#determinant raises an error for rectangular matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/divide_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/divide_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/divide_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#/ raises a TypeError if other is of wrong type

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#each returns an Enumerator when called without a block
-fails:Matrix#each returns self
-fails:Matrix#each yields the elements starting with the those of the first row

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_with_index_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_with_index_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/each_with_index_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#each_with_index returns an Enumerator when called without a block
-fails:Matrix#each_with_index returns self
-fails:Matrix#each_with_index yields the elements starting with the those of the first row

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/element_reference_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/element_reference_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/element_reference_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#[] returns nil for an invalid index pair

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/empty_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/empty_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/empty_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,8 +0,0 @@
-fails:Matrix#empty? returns true when the Matrix is empty
-fails:Matrix#empty? returns false when the Matrix has elements
-fails:Matrix#empty? doesn't accept any parameter
-fails:Matrix.empty returns an empty matrix of the requested size
-fails:Matrix.empty has arguments defaulting to 0
-fails:Matrix.empty does not accept more than two parameters
-fails:Matrix.empty raises an error if both dimensions are > 0
-fails:Matrix.empty raises an error if any dimension is < 0

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/exponent_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/exponent_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/exponent_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#** raises a ErrOperationNotImplemented exception for powers that aren't Integers

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imag_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imag_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imag_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:Matrix#imag returns a matrix with the imaginary part of the elements of the receiver
-fails:Matrix#imag returns empty matrices on the same size if empty

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imaginary_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imaginary_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/imaginary_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:Matrix#imaginary returns a matrix with the imaginary part of the elements of the receiver
-fails:Matrix#imaginary returns empty matrices on the same size if empty

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/inspect_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/inspect_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/inspect_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#inspect returns 'Matrix.empty(...)' for empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/map_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/map_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/map_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#map returns an enumerator if no block is given

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minor_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minor_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minor_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +0,0 @@
-fails:Matrix#minor with start_row, nrows, start_col, ncols returns an empty Matrix unless nrows and ncols are greater than 0
-fails:Matrix#minor with start_row, nrows, start_col, ncols returns nil for out-of-bounds start_row/col
-fails:Matrix#minor with start_row, nrows, start_col, ncols returns nil for negative nrows or ncols
-fails:Matrix#minor with col_range, row_range returns nil if col_range or row_range is out of range

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minus_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minus_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/minus_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#- raises a TypeError if other is of wrong type

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/multiply_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/multiply_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/multiply_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +0,0 @@
-fails:Matrix#* returns a zero matrix if (nx0) * (0xn)
-fails:Matrix#* returns an empty matrix if (0xn) * (nx0)
-fails:Matrix#* returns a 0xm matrix if (0xm) * (mxn)
-fails:Matrix#* raises a TypeError if other is of wrong type

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/plus_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/plus_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/plus_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#+ raises a TypeError if other is of wrong type

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rank_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rank_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rank_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +1 @@
 critical:Matrix#rank doesn't loop forever
-fails:Matrix#rank works for some easy rectangular matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/real_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/real_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/real_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,5 +0,0 @@
-fails:Matrix#real? returns true for matrices with all real entries
-fails:Matrix#real? returns true for empty matrices
-fails:Matrix#real? returns false if one element is a Complex
-fails:Matrix#real returns a matrix with the real part of the elements of the receiver
-fails:Matrix#real returns empty matrices on the same size if empty

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rect_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rect_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rect_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#rect returns [receiver.real, receiver.imag]

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rectangular_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rectangular_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/rectangular_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#rectangular returns [receiver.real, receiver.imag]

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/regular_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/regular_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/regular_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,4 +1,2 @@
 critical:Matrix#regular? returns false unless rank(A) != n
 critical:Matrix#regular? returns false for singular matrices
-fails:Matrix#regular? returns true for an empty 0x0 matrix
-fails:Matrix#regular? raises an error for rectangular matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/row_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/row_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/row_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +0,0 @@
-fails:Matrix#row returns self when called with a block
-fails:Matrix#row returns nil when out of bounds
-fails:Matrix#row never yields when out of bounds

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/singular_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/singular_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/singular_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,3 +1 @@
 critical:Matrix#singular? returns true for singular matrices
-fails:Matrix#singular? returns false for an empty 0x0 matrix
-fails:Matrix#singular? raises an error for rectangular matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/square_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/square_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/square_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#square? returns handles empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/t_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/t_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/t_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#transpose can transpose empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/tr_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/tr_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/tr_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#tr returns the sum of diagonal elements in a rectangular Matrix

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/trace_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/trace_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/trace_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#trace returns the sum of diagonal elements in a rectangular Matrix

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/transpose_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/transpose_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/transpose_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:Matrix#transpose can transpose empty matrices

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/vector/each2_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/vector/each2_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/vector/each2_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1,2 +0,0 @@
-fails:Vector.each2 given one argument returns self when given a block
-fails:Vector.each2 given one argument returns an enumerator if no block given

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/uri/eql_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/uri/eql_tags.txt	2010-05-17 21:25:19 UTC (rev 4113)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/uri/eql_tags.txt	2010-05-18 01:40:51 UTC (rev 4114)
@@ -1 +0,0 @@
-fails:URI#eql? returns false for when compared to non-uri objects
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100517/4d0061e8/attachment-0001.html>


More information about the macruby-changes mailing list