[macruby-changes] [5310] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Mar 28 13:06:57 PDT 2011


Revision: 5310
          http://trac.macosforge.org/projects/ruby/changeset/5310
Author:   lsansonetti at apple.com
Date:     2011-03-28 13:06:57 -0700 (Mon, 28 Mar 2011)
Log Message:
-----------
moved to github

Added Paths:
-----------
    MacRuby/trunk/MOVED_TO_GITHUB

Removed Paths:
-------------
    MacRuby/trunk/COPYING
    MacRuby/trunk/GPL
    MacRuby/trunk/HACKING.rdoc
    MacRuby/trunk/LEGAL
    MacRuby/trunk/LGPL
    MacRuby/trunk/MacRuby.m
    MacRuby/trunk/MacRubyDebuggerConnector.h
    MacRuby/trunk/MacRubyDebuggerConnector.m
    MacRuby/trunk/NSArray.m
    MacRuby/trunk/NSDictionary.m
    MacRuby/trunk/NSString.m
    MacRuby/trunk/README.rdoc
    MacRuby/trunk/Rakefile
    MacRuby/trunk/TODO
    MacRuby/trunk/array.c
    MacRuby/trunk/array.h
    MacRuby/trunk/auto_zone_1060.h
    MacRuby/trunk/b.rb
    MacRuby/trunk/bignum.c
    MacRuby/trunk/bin/
    MacRuby/trunk/bridgesupport.cpp
    MacRuby/trunk/bridgesupport.h
    MacRuby/trunk/bs.c
    MacRuby/trunk/bs.h
    MacRuby/trunk/bs_lex.h
    MacRuby/trunk/bs_struct_readers.c
    MacRuby/trunk/class.c
    MacRuby/trunk/class.h
    MacRuby/trunk/compar.c
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/complex.c
    MacRuby/trunk/cont.c
    MacRuby/trunk/debugger.cpp
    MacRuby/trunk/debugger.h
    MacRuby/trunk/dir.c
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/distruby.rb
    MacRuby/trunk/dln.c
    MacRuby/trunk/dln.h
    MacRuby/trunk/dmydln.c
    MacRuby/trunk/dmyencoding.c
    MacRuby/trunk/dmyext.c
    MacRuby/trunk/dmytranscode.c
    MacRuby/trunk/dtrace.d
    MacRuby/trunk/encoding.c
    MacRuby/trunk/encoding.h
    MacRuby/trunk/encoding_ucnv.h
    MacRuby/trunk/enum.c
    MacRuby/trunk/enumerator.c
    MacRuby/trunk/env.c
    MacRuby/trunk/error.c
    MacRuby/trunk/eval.c
    MacRuby/trunk/eval_error.c
    MacRuby/trunk/eval_jump.c
    MacRuby/trunk/eval_safe.c
    MacRuby/trunk/exported_symbols_list
    MacRuby/trunk/ext/
    MacRuby/trunk/file.c
    MacRuby/trunk/framework/
    MacRuby/trunk/gc-stub.m
    MacRuby/trunk/gc.c
    MacRuby/trunk/gcd.c
    MacRuby/trunk/gcd.h
    MacRuby/trunk/gem_prelude.rb
    MacRuby/trunk/gen_bs_struct_readers.rb
    MacRuby/trunk/golf_prelude.rb
    MacRuby/trunk/hash.c
    MacRuby/trunk/hash.h
    MacRuby/trunk/icu-1060/
    MacRuby/trunk/id.c
    MacRuby/trunk/id.h
    MacRuby/trunk/include/
    MacRuby/trunk/inits.c
    MacRuby/trunk/instruby.rb
    MacRuby/trunk/interpreter.cpp
    MacRuby/trunk/interpreter.h
    MacRuby/trunk/io.c
    MacRuby/trunk/irb.1
    MacRuby/trunk/kernel.c
    MacRuby/trunk/keywords
    MacRuby/trunk/lex.c.blt
    MacRuby/trunk/lex.c.src
    MacRuby/trunk/lgamma_r.c
    MacRuby/trunk/lib/
    MacRuby/trunk/llvm.h
    MacRuby/trunk/load.c
    MacRuby/trunk/macruby_internal.h
    MacRuby/trunk/main.cpp
    MacRuby/trunk/markgc.c
    MacRuby/trunk/marshal.c
    MacRuby/trunk/math.c
    MacRuby/trunk/misc/
    MacRuby/trunk/mspec/
    MacRuby/trunk/mt.c
    MacRuby/trunk/numeric.c
    MacRuby/trunk/objc.h
    MacRuby/trunk/objc.m
    MacRuby/trunk/object.c
    MacRuby/trunk/pack.c
    MacRuby/trunk/parse.y
    MacRuby/trunk/perf/
    MacRuby/trunk/prec.c
    MacRuby/trunk/proc.c
    MacRuby/trunk/process.c
    MacRuby/trunk/rakelib/
    MacRuby/trunk/random.c
    MacRuby/trunk/range.c
    MacRuby/trunk/rational.c
    MacRuby/trunk/re.c
    MacRuby/trunk/re.h
    MacRuby/trunk/ruby.1
    MacRuby/trunk/ruby.c
    MacRuby/trunk/ruby_deploy.1
    MacRuby/trunk/rubyc.1
    MacRuby/trunk/rubyd.1
    MacRuby/trunk/rubytest.rb
    MacRuby/trunk/runruby.rb
    MacRuby/trunk/sample/
    MacRuby/trunk/sample-macruby/
    MacRuby/trunk/sandbox.c
    MacRuby/trunk/signal.c
    MacRuby/trunk/spec/
    MacRuby/trunk/sprintf.c
    MacRuby/trunk/st.c
    MacRuby/trunk/string.c
    MacRuby/trunk/struct.c
    MacRuby/trunk/symbol.c
    MacRuby/trunk/symbol.h
    MacRuby/trunk/test/
    MacRuby/trunk/test-macruby/
    MacRuby/trunk/test_vm/
    MacRuby/trunk/test_vm.rb
    MacRuby/trunk/thread.c
    MacRuby/trunk/time.c
    MacRuby/trunk/tool/
    MacRuby/trunk/transcode.c
    MacRuby/trunk/ucnv.c
    MacRuby/trunk/util.c
    MacRuby/trunk/variable.c
    MacRuby/trunk/version.c
    MacRuby/trunk/version.h
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h
    MacRuby/trunk/vm_eval.c
    MacRuby/trunk/vm_method.c

Deleted: MacRuby/trunk/COPYING
===================================================================
--- MacRuby/trunk/COPYING	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/COPYING	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,59 +0,0 @@
-MacRuby is copyrighted free software by Apple Inc.
-MacRuby contains code from the Ruby project, copyrighted free software by
-Yukihiro Matsumoto <matz at netlab.jp>.
-
-You can redistribute it and/or modify it under either the terms of the GPL
-version 2 (see the file GPL), or the conditions below:
-
-  1. You may make and give away verbatim copies of the source form of the
-     software without restriction, provided that you duplicate all of the
-     original copyright notices and associated disclaimers.
-
-  2. You may modify your copy of the software in any way, provided that
-     you do at least ONE of the following:
-
-       a) place your modifications in the Public Domain or otherwise
-          make them Freely Available, such as by posting said
-	  modifications to Usenet or an equivalent medium, or by allowing
-	  the author to include your modifications in the software.
-
-       b) use the modified software only within your corporation or
-          organization.
-
-       c) give non-standard binaries non-standard names, with
-          instructions on where to get the original software distribution.
-
-       d) make other distribution arrangements with the author.
-
-  3. You may distribute the software in object code or binary form,
-     provided that you do at least ONE of the following:
-
-       a) distribute the binaries and library files of the software,
-	  together with instructions (in the manual page or equivalent)
-	  on where to get the original distribution.
-
-       b) accompany the distribution with the machine-readable source of
-	  the software.
-
-       c) give non-standard binaries non-standard names, with
-          instructions on where to get the original software distribution.
-
-       d) make other distribution arrangements with the author.
-
-  4. You may modify and include the part of the software into any other
-     software (possibly commercial).  But some files in the distribution
-     are not written by the author, so that they are not under these terms.
-
-     For the list of those files and their copying conditions, see the
-     file LEGAL.
-
-  5. The scripts and library files supplied as input to or produced as 
-     output from the software do not automatically fall under the
-     copyright of the software, but belong to whomever generated them, 
-     and may be sold commercially, and may be aggregated with this
-     software.
-
-  6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
-     IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-     PURPOSE.

Deleted: MacRuby/trunk/GPL
===================================================================
--- MacRuby/trunk/GPL	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/GPL	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,340 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.

Deleted: MacRuby/trunk/HACKING.rdoc
===================================================================
--- MacRuby/trunk/HACKING.rdoc	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/HACKING.rdoc	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,165 +0,0 @@
-== Hacking MacRuby
-
-Please read this file if you are considering hacking MacRuby. It provides
-tips in order to better hack MacRuby and also suggestions on how to submit a
-patch.
-
-=== Coding Style
-
-You need to conform to the following coding style in order to get a patch
-accepted:
-
-* Indentation starts with 4 space characters, then 1 tabulation (hard), then
-  1 tabulation (hard) followed by 4 space characters, then 2 tabulations
-  (hard), etc.
-
-  This is the indentation style that was inherited from the original Ruby source
-  code, so we are preserving it.
-
-* Insert a new line between the type and the name of a function during its
-  definition and start the opening brace on a new line too.
-
-    static void
-    do_something(void)
-    {
-        ...
-    }
-
-* A space must be inserted between keywords and their operand and branches must
-  be written so that an ending brace is always at the end of a line.
-
-    if (some_boolean) {
-        ...
-    }
-    else {
-        ...
-    }
-
-* Branches with only one expression must still be covered by braces, even
-  if it's not mandatory in the C language. Also, do not write one-liner
-  branches.
-
-    if (some_boolean)
-        do_something(); /* bad */
-    if (some_boolean) do_something(); /* bad */
-
-    if (some_boolean) {
-        /* good */
-        do_something();
-    }
-
-* A space must be inserted between operators operands.
-
-    int i, x = 40 + 2;
-    for (i = 0; i < x; i++) {
-        ...
-    }
-
-* Do not insert a space between a function call and its first brace.
-
-    do_something();
-
-* A space must be inserted after every argument in a function call.
-
-    do_something(x, y, z);
-
-* Never pass a non-boolean value as it is to a conditional expression.
-
-    void *ptr = do_something();
-    if (!ptr) {
-        /* bad */
-    }
-
-    if (ptr != NULL) {
-        /* good */
-    }
-
-* Respect the 80 columns rule when possible. You can violate this rule in case
-  the line contains a long string.
-
-* In case you need to split multiple conditional expressions into multiple
-  lines, make sure there is a new line before the operator(s).
-
-    if (do_something ||
-        do_something2()) {
-        /* bad */
-        do_something3();
-    }
-
-    if (do_something()
-        || do_something2()) {
-        /* good */
-        do_something3();
-    }
-
-=== Code Design
-
-* Please declare variables as you use them. The whole project is built under the
-  C99 mode so newer constructs are also recommended (such as the definition of
-  iterator variables in 'for' loops).
-
-* Please use the 'const' qualifier for scalar variables that are not supposed to
-  change.
-
-* Use 'assert' or 'abort' for situations that should never happen. It is not a
-  problem if you abuse of this, just be clever.
-
-* Do not use 'alloca' unless you know what you are doing.
-
-=== Debugging
-
-==== Environment variables
-
-The following environment variables might help you debug easy bugs.
-
-* GC_DISABLE: set it to any value to disable the GC.
-
-* GC_DEBUG: set it to any value to enable GC debugging on $stderr.
-
-* VM_DISABLE_RBO: set it to any value to disable the load of .rbo files.
-
-* VM_DISABLE_INTERPRETER: set it to any value to disable the use of the
-  builtin interpreter (generally used on cold paths).
-
-* VM_DUMP_IR: set it to any value to dump the LLVM IR on $stderr before the
-  interpreter quits.
-
-* VM_VERIFY_IR: set it to any value to force a LLVM module verification before
-  the interpreter quits.
-
-* VM_OPT_LEVEL: set it either to 0, 1, 2 or 3 to change the optimization level
-  of the LLVM code generator.
-
-* VM_KERNEL_PATH: specify a path to a kernel bitcode file to be used instead of
-  the hardcoded one, when deserializing the main module. This is useful when
-  cross-compiling Ruby code to a different architecture.
-
-* DYLD_LIBRARY_PATH: in case you are debugging a Cocoa application, set this 
-  variable to "." before starting gdb, and you won't have to re-install MacRuby
-  every time you re-compile it.
-
-* AUTO_USE_TLC: set this variable to 0 to disable the thread local collector.
-
-==== GDB tricks
-
-* Break on rb_exc_raise to intercept pure Ruby exceptions. You can use a
-  conditional break point in case you only want to break if a specific
-  exception class is being raised:
-  (gdb) b rb_exc_raise
-  Breakpoint 1 at 0x20c49ba5453254: file eval.c, line 312.
-  (gdb) cond 1 *(void **)mesg == rb_eArgError
-
-* To dump the LLVM IR:
-  (gdb) p RoxorCompiler::shared->module->dump()
-
-* To print the list of current active blocks:
-  (gdb) p (char *)RoxorVM::current->debug_blocks()
-
-* To print the list of current active exceptions:
-  (gdb) p (char *)RoxorVM::current->debug_exceptions()
-
-* To determine if a given object is thread-local:
-  (gdb) p (int)gdb_is_local(<address>)
-
-* To symbolize a Ruby address (named as ??) in the backtrace:
-  (gdb) p (void)rb_symbolicate(<address>)

Deleted: MacRuby/trunk/LEGAL
===================================================================
--- MacRuby/trunk/LEGAL	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/LEGAL	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,318 +0,0 @@
-LEGAL NOTICE INFORMATION
-------------------------
-
-All the files in this distribution are covered under either the Ruby's
-license (see the file COPYING) under specific copyright holders (see their
-header comment) or public-domain except some files mentioned below.
-
-parse.c:
-
-  As long as you distribute these files with the file configure, they
-  are covered under the Ruby's license.
-
-      Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
-      Free Software Foundation, Inc.
-
-    This file is free software; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-    As a special exception to the GNU General Public License, if you
-    distribute this file as part of a program that contains a
-    configuration script generated by Autoconf, you may include it under
-    the same distribution terms that you use for the rest of that program.
-
-util.c (partly):
-
-    Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
-
-    Permission to use, copy, modify, and distribute this software for any
-    purpose without fee is hereby granted, provided that this entire notice
-    is included in all copies of any software which is or includes a copy
-    or modification of this software and in all copies of the supporting
-    documentation for such software.
-
-    THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
-    WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
-    REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
-    OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
-
-util.c (partly):
-
-  You can apply the Artistic License to these files. (or GPL,
-  alternatively)
-
-    Copyright (c) 1993, Intergraph Corporation
-
-    You may distribute under the terms of either the GNU General Public
-    License or the Artistic License, as specified in the perl README file.
-
-random.c
-
-  This file is under the new-style BSD license.
-
-    A C-program for MT19937, with initialization improved 2002/2/10.
-    Coded by Takuji Nishimura and Makoto Matsumoto.
-    This is a faster version by taking Shawn Cokus's optimization,
-    Matthe Bellew's simplification, Isaku Wada's real version.
-
-    Before using, initialize the state by using init_genrand(seed) 
-    or init_by_array(init_key, key_length).
-
-    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
-    All rights reserved.                          
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-      1. Redistributions of source code must retain the above copyright
-	 notice, this list of conditions and the following disclaimer.
-
-      2. Redistributions in binary form must reproduce the above copyright
-	 notice, this list of conditions and the following disclaimer in the
-	 documentation and/or other materials provided with the distribution.
-
-      3. The names of its contributors may not be used to endorse or promote 
-	 products derived from this software without specific prior written 
-	 permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-    Any feedback is very welcome.
-    http://www.math.keio.ac.jp/matumoto/emt.html
-    email: matumoto at math.keio.ac.jp
-
-st.[ch]:
-ext/digest/sha1/sha1.[ch]:
-
-  These files are all under public domain.
-
-ext/digest/md5/md5.[ch]:
-
-  These files are under the following license.  Ruby uses modified
-  versions of them.
-
-    Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
-
-    This software is provided 'as-is', without any express or implied
-    warranty.  In no event will the authors be held liable for any damages
-    arising from the use of this software.
-
-    Permission is granted to anyone to use this software for any purpose,
-    including commercial applications, and to alter it and redistribute it
-    freely, subject to the following restrictions:
-
-    1. The origin of this software must not be misrepresented; you must not
-       claim that you wrote the original software. If you use this software
-       in a product, an acknowledgment in the product documentation would be
-       appreciated but is not required.
-    2. Altered source versions must be plainly marked as such, and must not be
-       misrepresented as being the original software.
-    3. This notice may not be removed or altered from any source distribution.
-
-    L. Peter Deutsch
-    ghost at aladdin.com
-
-ext/digest/rmd160/rmd160.[ch]:
-
-  These files have the following copyright information, and by the
-  author we are allowed to use it under the new-style BSD license.
-
-    AUTHOR:   Antoon Bosselaers, ESAT-COSIC
-              (Arranged for libc by Todd C. Miller)
-    DATE:     1 March 1996
-
-    Copyright (c) Katholieke Universiteit Leuven
-    1996, All Rights Reserved
-
-ext/digest/rmd160/rmd160hl.c:
-ext/digest/sha1/sha1hl.c:
-
-  These files are under the beer-ware license.
-
-    "THE BEER-WARE LICENSE" (Revision 42):
-    <phk at login.dkuug.dk> wrote this file.  As long as you retain this notice you
-    can do whatever you want with this stuff. If we meet some day, and you think
-    this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
-
-ext/digest/sha2/sha2.[ch]:
-ext/digest/sha2/sha2hl.c:
-
-  These files are under the new-style BSD license.
-
-    Copyright 2000 Aaron D. Gifford.  All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-    3. Neither the name of the copyright holder nor the names of contributors
-       may be used to endorse or promote products derived from this software
-       without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-ext/nkf/nkf-utf8/config.h:
-ext/nkf/nkf-utf8/nkf.c:
-ext/nkf/nkf-utf8/utf8tbl.c:
-
-  These files are under the following license.  So to speak, it is
-  copyrighted semi-public-domain software.
-
-    Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-       Everyone is permitted to do anything on this program 
-       including copying, modifying, improving,
-       as long as you don't try to pretend that you wrote it.
-       i.e., the above copyright notice has to appear in all copies.
-       Binary distribution requires original version messages.
-       You don't have to ask before copying, redistribution or publishing.
-       THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-
-ext/socket/addrinfo.h:
-ext/socket/getaddrinfo.c:
-ext/socket/getnameinfo.c:
-
-  These files are under the new-style BSD license.
-
-    Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-    3. Neither the name of the project nor the names of its contributors
-       may be used to endorse or promote products derived from this software
-       without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-bs.[ch]:
-
-  These files are under the new-style BSD license.
-
-    Copyright (c) 2008, Apple Inc. All rights reserved.
-  
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1.  Redistributions of source code must retain the above copyright
-        notice, this list of conditions and the following disclaimer.
-    2.  Redistributions in binary form must reproduce the above copyright
-        notice, this list of conditions and the following disclaimer in the
-        documentation and/or other materials provided with the distribution.
-    3.  Neither the name of Apple Inc. ("Apple") nor the names of
-        its contributors may be used to endorse or promote products derived
-        from this software without specific prior written permission.
-  
-    THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
-    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGE.
-
-auto_zone_*.h:
-
-  This file is under the Apache License, version 2.0.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-    
-        http://www.apache.org/licenses/LICENSE-2.0
-    
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-icu-*/**/*.h:
-
-  These files are under the ICU license.
-
-  COPYRIGHT AND PERMISSION NOTICE
-  
-  Copyright (c) 1995-2010 International Business Machines Corporation and
-  others
-  
-  All rights reserved.
-  
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, and/or sell copies of the
-  Software, and to permit persons to whom the Software is furnished to do so,
-  provided that the above copyright notice(s) and this permission notice appear
-  in all copies of the Software and that both the above copyright notice(s) and
-  this permission notice appear in supporting documentation.
-  
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE
-  LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR
-  ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-  OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-  
-  Except as contained in this notice, the name of a copyright holder shall not
-  be used in advertising or otherwise to promote the sale, use or other
-  dealings in this Software without prior written authorization of the
-  copyright holder.

Deleted: MacRuby/trunk/LGPL
===================================================================
--- MacRuby/trunk/LGPL	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/LGPL	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,504 +0,0 @@
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-

Added: MacRuby/trunk/MOVED_TO_GITHUB
===================================================================
--- MacRuby/trunk/MOVED_TO_GITHUB	                        (rev 0)
+++ MacRuby/trunk/MOVED_TO_GITHUB	2011-03-28 20:06:57 UTC (rev 5310)
@@ -0,0 +1 @@
+See you there: https://github.com/MacRuby/MacRuby

Deleted: MacRuby/trunk/MacRuby.m
===================================================================
--- MacRuby/trunk/MacRuby.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/MacRuby.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,130 +0,0 @@
-/*
- * MacRuby Objective-C API.
- * 
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/objc.h"
-#include "vm.h"
-#include "objc.h"
-
- at implementation MacRuby
-
-extern bool ruby_initialized;
-
-+ (MacRuby *)sharedRuntime
-{
-    static MacRuby *runtime = nil;
-    if (runtime == nil) {
-	runtime = [[MacRuby alloc] init];
-	if (!ruby_initialized) {
-	    int argc = 0;
-	    char **argv = NULL;
-	    ruby_sysinit(&argc, &argv);
-	    ruby_init();
-	    ruby_init_loadpath();
-	    rb_vm_init_compiler();
-	    rb_vm_init_jit();
-	    rb_objc_fix_relocatable_load_path();
-	    rb_objc_load_loaded_frameworks_bridgesupport();
-	}
-    }
-    return runtime;
-}
-
-- (id)evaluateString:(NSString *)expression
-{
-    return RB2OC(rb_eval_string([(NSString *)expression UTF8String]));
-}
-
-- (id)evaluateFileAtPath:(NSString *)path
-{
-    return RB2OC(rb_f_require(Qnil, (VALUE)path));
-}
-
-- (id)evaluateFileAtURL:(NSURL *)URL
-{
-    if (![URL isFileURL]) {
-	[NSException raise:NSInvalidArgumentException format:
-	    @"given URL is not a file URL"];
-    }
-    return [self evaluateFileAtPath:[URL relativePath]];
-}
-
-- (void)loadBridgeSupportFileAtPath:(NSString *)path
-{
-#if MACRUBY_STATIC
-    printf("loadBridgeSupportFileAtPath: not supported in MacRuby static\n");
-    abort();
-#else
-    rb_vm_load_bridge_support([path fileSystemRepresentation], NULL, 0);
-#endif
-}
-
-- (void)loadBridgeSupportFileAtURL:(NSURL *)URL
-{
-    if (![URL isFileURL]) {
-	[NSException raise:NSInvalidArgumentException format:
-	    @"given URL is not a file URL"];
-    }
-    [self loadBridgeSupportFileAtPath:[URL relativePath]];
-}
-
- at end
-
- at implementation NSObject (MacRubyAdditions)
-
-- (id)performRubySelector:(SEL)sel
-{
-    return [self performRubySelector:sel withArguments:NULL];
-}
-
-- (id)performRubySelector:(SEL)sel withArguments:(id *)argv count:(int)argc
-{
-    VALUE *rargv = NULL;
-    if (argc > 0) {
-	rargv = (VALUE *)xmalloc(sizeof(VALUE) * argc);
-	for (int i = 0; i < argc; i++) {
-	    rargv[i] = OC2RB(argv[i]);
-	}
-    }
-
-    return RB2OC(rb_vm_call(OC2RB(self), sel, argc, rargv));
-}
-
-- (id)performRubySelector:(SEL)sel withArguments:firstArg, ...
-{
-    va_list args;
-    int argc;
-    id *argv;
-
-    if (firstArg != nil) {
-	argc = 1;
-	va_start(args, firstArg);
-	while (va_arg(args, id) != NULL) {
-	    argc++;
-	}
-	va_end(args);
-	argv = xmalloc(sizeof(id) * argc);
-	va_start(args, firstArg);
-	argv[0] = firstArg;
-	for (int i = 1; i < argc; i++) {
-	    argv[i] = va_arg(args, id);
-	}
-	va_end(args);
-    }
-    else {
-	argc = 0;
-	argv = NULL;
-    }
-
-    return [self performRubySelector:sel withArguments:argv count:argc];
-}
-
- at end

Deleted: MacRuby/trunk/MacRubyDebuggerConnector.h
===================================================================
--- MacRuby/trunk/MacRubyDebuggerConnector.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/MacRubyDebuggerConnector.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,60 +0,0 @@
-/*
- * MacRuby Debugger Connector.
- *
- * This is an interface to the MacRuby runtime when running in debug mode.
- * It is used by MacRuby debugger clients, such as macrubyd or Xcode.
- * This file when compiled separately must be compiled with garbage collection
- * enabled.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-
-typedef unsigned int breakpoint_t;
-
- at interface MacRubyDebuggerConnector : NSObject
-{
-    NSString *_interpreterPath;
-    NSMutableArray *_arguments;
-    NSString *_socketPath;
-    NSTask *_task;
-    NSFileHandle *_socket;
-    NSString *_location;
-}
-
-- (id)initWithInterpreterPath:(NSString *)path arguments:(NSArray *)arguments;
-
-// Execution control.
-
-- (void)startExecution;
-- (void)continueExecution;
-- (void)stepExecution;
-- (void)stopExecution;
-
-// Current state.
-
-- (NSString *)location;
-- (NSArray *)localVariables;
-- (NSArray *)backtrace;
-- (void)setFrame:(unsigned int)frame;
-
-// Breakpoints.
-
-- (breakpoint_t)addBreakPointAtPath:(NSString *)path line:(unsigned int)line
-    condition:(NSString *)condition;
-
-- (void)enableBreakPoint:(breakpoint_t)bp;
-- (void)disableBreakPoint:(breakpoint_t)bp;
-- (void)deleteBreakPoint:(breakpoint_t)bp;
-- (void)setCondition:(NSString *)condition forBreakPoint:(breakpoint_t)bp;
-
-- (NSArray *)allBreakPoints;
-
-// Context evaluation.
-
-- (NSString *)evaluateExpression:(NSString *)expression;
-
- at end

Deleted: MacRuby/trunk/MacRubyDebuggerConnector.m
===================================================================
--- MacRuby/trunk/MacRubyDebuggerConnector.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/MacRubyDebuggerConnector.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,272 +0,0 @@
-/*
- * MacRuby Debugger Connector.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#import "MacRubyDebuggerConnector.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
- at implementation MacRubyDebuggerConnector
-
-- (NSData *)_recv
-{
-    assert(_socket != nil);
-    return [_socket availableData];
-}
-
-- (const char *)_recvCString
-{
-    return (const char *)[[self _recv] bytes];
-}
-
-- (NSString *)_recvString
-{
-    return [[NSString alloc] initWithData:[self _recv]
-	encoding:NSASCIIStringEncoding];
-}
-
-- (void)_send:(NSData *)data
-{
-    assert(_socket != nil);
-    [_socket writeData:data]; 
-}
-
-- (void)_sendCString:(const char *)str
-{
-    [self _send:[NSData dataWithBytes:str length:strlen(str)]];
-}
-
--(void)_readLocation
-{
-    _location = [self _recvString];
-    if ([_location length] == 0) {
-	_location = nil;
-    }
-}
-
-- (id)initWithInterpreterPath:(NSString *)ipath arguments:(NSArray *)arguments
-{
-    self = [super init];
-    if (self != nil) {
-	// Generate the socket path.
-	NSString *tmpdir = NSTemporaryDirectory();
-	assert(tmpdir != nil);
-	char path[PATH_MAX];
-	snprintf(path, sizeof path, "%s/macrubyd-XXXXXX",
-		[tmpdir fileSystemRepresentation]);
-	assert(mktemp(path) != NULL);
-	_socketPath = [[NSFileManager defaultManager]
-	    stringWithFileSystemRepresentation:path length:strlen(path)];
-
-	// Setup arguments.
-	_arguments = [NSMutableArray new];
-	[_arguments addObject:@"--debug-mode"];
-	[_arguments addObject:_socketPath];
-	[_arguments addObjectsFromArray:arguments];
-
-	_interpreterPath = ipath;
-	_task = nil;
-	_socket = nil;
-	_location = nil;
-    }
-    return self;
-}
-
-- (void)finalize
-{
-    [super finalize];
-    [self stopExecution];
-}
-
-- (void)startExecution
-{
-    if (_task == nil || ![_task isRunning]) {
-	// Create task.
-	_task = [NSTask new];
-	[_task setLaunchPath:_interpreterPath];
-	[_task setArguments:_arguments];
-
-	// Launch the remote process.
-	[[NSFileManager defaultManager] removeItemAtPath:_socketPath error:nil];
-	[_task launch];
-
-	// Wait until the socket file is available.
-	while (true) {
-	    if ([[NSFileManager defaultManager] fileExistsAtPath:_socketPath]) {
-		break;
-	    }
-	    if (![_task isRunning]) {
-		// Something wrong happened at the very beginning, most likely
-		// a command-line argument error.
-		_task = nil;
-		return;
-	    }
-	    assert([_task isRunning]); // XXX raise exception
-	    usleep(500000);
-	}
-
-	// Create the socket.
-	const int fd = socket(PF_LOCAL, SOCK_STREAM, 0);
-	if (fd == -1) {
-	    // XXX should raise exception.
-	    perror("socket()");
-	    exit(1);
-	}
-
-	// Prepare the name.
-	struct sockaddr_un name;
-	name.sun_family = PF_LOCAL;
-	strncpy(name.sun_path, [_socketPath fileSystemRepresentation],
-		sizeof(name.sun_path));
-
-	// Connect.
-	if (connect(fd, (struct sockaddr *)&name, SUN_LEN(&name)) == -1) {
-	    // XXX should raise exception.
-	    perror("connect()");
-	    exit(1);
-	}
-
-	// Good!
-	_socket = [[NSFileHandle alloc] initWithFileDescriptor:fd];
-	[self _readLocation];
-    }
-}
-
-- (void)continueExecution
-{
-    [self _sendCString:"continue"];
-    [self _readLocation];
-}
-
-- (void)stepExecution
-{
-    [self _sendCString:"next"];
-    [self _readLocation];
-}
-
-- (void)stopExecution
-{
-    if (_task != nil) {
-	[_task terminate];
-	_task = nil;
-    }
-    _location = nil;
-    [[NSFileManager defaultManager] removeItemAtPath:_socketPath error:nil];
-}
-
-- (NSString *)location
-{
-    return _location;
-}
-
-- (NSArray *)localVariables
-{
-    return nil;
-}
-
-- (NSArray *)backtrace
-{
-    [self _sendCString:"backtrace"];
-    return [[self _recvString] componentsSeparatedByString:@"\n"];
-}
-
-- (void)setFrame:(unsigned int)frame
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "frame %d", frame);
-    [self _sendCString:buf];
-}
-
-- (breakpoint_t)addBreakPointAtPath:(NSString *)path line:(unsigned int)line
-	condition:(NSString *)condition
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "break %s:%d", [path fileSystemRepresentation],
-	    line);
-    [self _sendCString:buf];
-    return [[self _recvString] integerValue];
-}
-
-- (void)enableBreakPoint:(breakpoint_t)bp
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "enable %d", bp);
-    [self _sendCString:buf];
-}
-
-- (void)disableBreakPoint:(breakpoint_t)bp
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "disable %d", bp);
-    [self _sendCString:buf];
-}
-
-- (void)deleteBreakPoint:(breakpoint_t)bp
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "delete %d", bp);
-    [self _sendCString:buf];
-}
-
-- (void)setCondition:(NSString *)condition forBreakPoint:(breakpoint_t)bp
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "condition %d %s", bp, [condition UTF8String]);
-    [self _sendCString:buf];
-}
-
-- (NSDictionary *)_parseBreakPointDescription:(NSString *)desc
-{
-    NSArray *ary = [desc componentsSeparatedByString:@","];
-    if ([ary count] == 0) {
-	return nil;
-    }
-    NSMutableDictionary *dict = [NSMutableDictionary new];
-    unsigned i, count;
-    for (i = 0, count = [ary count]; i < count; i++) {
-	NSArray *fields = [[ary objectAtIndex:i]
-	    componentsSeparatedByString:@"="];
-	if ([fields count] == 2) {
-	    NSString *key = [fields objectAtIndex:0];
-	    NSString *val = [fields objectAtIndex:1];
-	    [dict setObject:val forKey:key];
-	}
-    }
-    if ([dict count] == 0) {
-	return nil;
-    }
-    return dict; 
-}
-
-
-- (NSArray *)allBreakPoints
-{
-    [self _sendCString:"info breakpoints"];
-    NSArray *ary = [[self _recvString] componentsSeparatedByString:@"\n"];
-    NSMutableArray *ary2 = [NSMutableArray new];
-    unsigned i, count;
-    for (i = 0, count = [ary count]; i < count; i++) {
-	NSString *desc = [ary objectAtIndex:i];
-	NSDictionary *dict = [self _parseBreakPointDescription:desc];
-	if (dict != nil) {
-	    [ary2 addObject:dict];
-	}
-    }
-    return ary2;
-}
-
-- (NSString *)evaluateExpression:(NSString *)expression
-{
-    char buf[512];
-    snprintf(buf, sizeof buf, "eval %s", [expression UTF8String]);
-    [self _sendCString:buf];
-    return [self _recvString];
-}
-
- at end

Deleted: MacRuby/trunk/NSArray.m
===================================================================
--- MacRuby/trunk/NSArray.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/NSArray.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1500 +0,0 @@
-/*
- * MacRuby extensions to NSArray.
- * 
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "objc.h"
-#include "vm.h"
-#include "array.h"
-#include "hash.h"
-
-VALUE rb_cArray;
-VALUE rb_cNSArray;
-VALUE rb_cNSMutableArray;
-
-// Some NSArray instances actually do not even respond to mutable methods.
-// So one way to know is to check if the addObject: method exists.
-#define CHECK_MUTABLE(obj) \
-    do { \
-        if (![obj respondsToSelector:@selector(addObject:)]) { \
-	    rb_raise(rb_eRuntimeError, \
-		    "can't modify frozen/immutable array"); \
-        } \
-    } \
-    while (0)
-
-// If a given mutable operation raises an NSException error,
-// it is likely that the object is not mutable.
-#define TRY_MOP(code) \
-    @try { \
-	code; \
-    } \
-    @catch(NSException *exc) { \
-	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array"); \
-    }
-
-static id
-nsary_dup(id rcv, SEL sel)
-{
-    id dup = [rcv mutableCopy];
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(dup);
-    }
-    return dup;
-}
-
-static id
-nsary_clone(id rcv, SEL sel)
-{
-    id clone = nsary_dup(rcv, 0);
-    if (OBJ_FROZEN(rcv)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-static id
-nsary_clear(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv removeAllObjects]);
-    return rcv;
-}
-
-static id
-nsary_inspect(id rcv, SEL sel)
-{
-    NSMutableString *str = [NSMutableString new];
-    [str appendString:@"["];
-    for (id item in rcv) {
-	if ([str length] > 1) {
-	    [str appendString:@", "];
-	}
-	[str appendString:(NSString *)rb_inspect(OC2RB(item))];
-    }
-    [str appendString:@"]"];
-    return str;
-}
-
-static id
-nsary_to_a(id rcv, SEL sel)
-{
-    return rcv;
-}
-
-static VALUE
-nsary_equal(id rcv, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_ARRAY) {
-	return Qfalse;
-    }
-    return [rcv isEqualToArray:(id)other] ? Qtrue : Qfalse;
-}
-
-static VALUE
-nsary_subseq(id rcv, long beg, long len)
-{
-    if (beg < 0 || len < 0) {
-	return Qnil;
-    }
-    const long n = [rcv count];
-    if (beg > n) {
-	return Qnil;
-    }
-    if (n < len || n < beg + len) {
-	len = n - beg;
-    }
-    return (VALUE)[[rcv subarrayWithRange:NSMakeRange(beg, len)] mutableCopy];
-}
-
-static VALUE
-nsary_entry(id rcv, long offset)
-{
-    const long n = [rcv count];
-    if (n == 0) {
-	return Qnil;
-    }
-    if (offset < 0) {
-	offset += n;
-    }
-    if (offset < 0 || n <= offset) {
-	return Qnil;
-    }
-    return OC2RB([rcv objectAtIndex:offset]);
-}
-
-static VALUE
-nsary_aref(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    long beg, len;
-    if (argc == 2) {
-	beg = NUM2LONG(argv[0]);
-	len = NUM2LONG(argv[1]);
-	if (beg < 0) {
-	    beg += [rcv count];
-	}
-	return nsary_subseq(rcv, beg, len);
-    }
-    if (argc != 1) {
-	rb_scan_args(argc, argv, "11", 0, 0);
-    }
-    VALUE arg = argv[0];
-    if (FIXNUM_P(arg)) {
-	return nsary_entry(rcv, FIX2LONG(arg));
-    }
-    // Check if Range.
-    switch (rb_range_beg_len(arg, &beg, &len, [rcv count], 0)) {
-	case Qfalse:
-	    break;
-	case Qnil:
-	    return Qnil;
-	default:
-	    return nsary_subseq(rcv, beg, len);
-    }
-    return nsary_entry(rcv, NUM2LONG(arg));
-}
-
-static void
-nsary_splice(id ary, long beg, long len, VALUE rpl)
-{
-    const long n = [ary count];
-    if (len < 0) {
-	rb_raise(rb_eIndexError, "negative length (%ld)", len);
-    }
-    if (beg < 0) {
-	beg += n;
-	if (beg < 0) {
-	    beg -= n;
-	    rb_raise(rb_eIndexError, "index %ld out of array", beg);
-	}
-    }
-    if (n < len || n < beg + len) {
-	len = n - beg;
-    }
-
-    long rlen = 0;
-    if (rpl != Qundef) {
-	rpl = rb_ary_to_ary(rpl);
-	rlen = RARRAY_LEN(rpl);
-    }
-
-    CHECK_MUTABLE(ary);
-
-    if (beg >= n) {
-	for (long i = n; i < beg; i++) {
-	    TRY_MOP([ary addObject:[NSNull null]]);
-	}
-	if (rlen > 0 && rpl != Qundef) {
-	    TRY_MOP([ary addObjectsFromArray:(id)rpl]);
-	}
-    }
-    else {
-	if (rlen > 0 && rpl != Qundef) {
-	    TRY_MOP([ary replaceObjectsInRange:NSMakeRange(beg, len)
-		withObjectsFromArray:(id)rpl]);
-	}
-	else {
-	    TRY_MOP([ary removeObjectsInRange:NSMakeRange(beg, len)]);
-	}
-    }
-}
-
-static void
-nsary_store(id ary, long idx, VALUE val)
-{
-    const long len = [ary count];
-    if (idx < 0) {
-	idx += len;
-	if (idx < 0) {
-	    rb_raise(rb_eIndexError, "index %ld out of array",
-		    idx - len);
-	}
-    }
-    else if (idx >= ARY_MAX_SIZE) {
-	rb_raise(rb_eIndexError, "index %ld too big", idx);
-    }
-
-    CHECK_MUTABLE(ary);
-
-    if (len <= idx) {
-	for (long i = len; i <= idx; i++) {
-	    TRY_MOP([ary addObject:[NSNull null]]);
-	} 
-    }	
-    TRY_MOP([ary replaceObjectAtIndex:idx withObject:RB2OC(val)]);
-}
-
-static VALUE
-nsary_aset(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 3) {
-	nsary_splice(rcv, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
-	return argv[2];
-    }
-    if (argc != 2) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-
-    long offset;
-    if (FIXNUM_P(argv[0])) {
-	offset = FIX2LONG(argv[0]);
-    }
-    else {
-	long beg, len;
-	if (rb_range_beg_len(argv[0], &beg, &len, [rcv count], 1)) {
-	    // Check if Range.
-	    nsary_splice(rcv, beg, len, argv[1]);
-	    return argv[1];
-	}
-	offset = NUM2LONG(argv[0]);
-    }
-    nsary_store(rcv, offset, argv[1]);
-    return argv[1];
-}
-
-static VALUE
-nsary_at(id rcv, SEL sel, VALUE pos)
-{
-    return nsary_entry(rcv, NUM2LONG(pos));
-}
-
-static VALUE
-nsary_fetch(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE pos, ifnone;
-    rb_scan_args(argc, argv, "11", &pos, &ifnone);
-
-    const bool block_given = rb_block_given_p();
-    if (block_given && argc == 2) {
-	rb_warn("block supersedes default value argument");
-    }
-
-    const long len = [rcv count];
-    long idx = NUM2LONG(pos);
-    if (idx < 0) {
-	idx += len;
-    }
-    if (idx < 0 || len <= idx) {
-	if (block_given) {
-	    return rb_yield(pos);
-	}
-	if (argc == 1) {
-	    rb_raise(rb_eIndexError, "index %ld out of array", idx);
-	}
-	return ifnone;
-    }
-    return OC2RB([rcv objectAtIndex:idx]);
-}
-
-static VALUE
-nsary_shared_first(int argc, VALUE *argv, id ary, bool last, bool remove)
-{
-    VALUE nv;
-    rb_scan_args(argc, argv, "1", &nv);
-    long n = NUM2LONG(nv);
-
-    const long ary_len = [ary count];
-    if (n > ary_len) {
-	n = ary_len;
-    }
-    else if (n < 0) {
-	rb_raise(rb_eArgError, "negative array size");
-    }
-
-    long offset = 0;
-    if (last) {
-	offset = ary_len - n;
-    }
-    id result = [NSMutableArray new];
-
-    for (long i = 0; i < n; i++) {
-	id item = [ary objectAtIndex:i + offset];
-	[result addObject:item];
-    }
-
-    if (remove) {
-	CHECK_MUTABLE(ary);
-	for (long i = 0; i < n; i++) {
-	    TRY_MOP([ary removeObjectAtIndex:offset]);
-	}
-    }
-
-    return (VALUE)result;
-}
-
-static VALUE
-nsary_first(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	return [rcv count] == 0 ? Qnil : OC2RB([rcv objectAtIndex:0]);
-    }
-    return nsary_shared_first(argc, argv, rcv, false, false);
-
-}
-
-static VALUE
-nsary_last(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	const long len = [rcv count];
-	return len == 0 ? Qnil : OC2RB([rcv objectAtIndex:len - 1]);
-    }
-    return nsary_shared_first(argc, argv, rcv, true, false);
-}
-
-static id
-nsary_concat(id rcv, SEL sel, VALUE ary)
-{
-    ary = to_ary(ary);
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv addObjectsFromArray:(id)ary]);
-    return rcv;
-}
-
-static id
-nsary_push(id rcv, SEL sel, VALUE elem)
-{
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv addObject:RB2OC(elem)]);
-    return rcv;
-}
-
-static id
-nsary_push_m(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	nsary_push(rcv, 0, argv[i]);
-    }
-    return rcv;
-}
-
-static VALUE
-nsary_pop(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    CHECK_MUTABLE(rcv);
-    if (argc == 0) {
-	const long len = [rcv count];
-	if (len > 0) {
-	    id elem = [rcv objectAtIndex:len - 1];
-	    TRY_MOP([rcv removeObjectAtIndex:len - 1]);
-	    return OC2RB(elem);
-	}
-	return Qnil;
-    }
-    return nsary_shared_first(argc, argv, rcv, true, true);
-}
-
-static VALUE
-nsary_shift(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    CHECK_MUTABLE(rcv);
-    if (argc == 0) {
-	const long len = [rcv count];
-	if (len > 0) {
-	    id elem = [rcv objectAtIndex:0];
-	    TRY_MOP([rcv removeObjectAtIndex:0]);
-	    return OC2RB(elem);
-	}
-	return Qnil;
-    }
-    return nsary_shared_first(argc, argv, rcv, false, true);
-}
-
-static id
-nsary_unshift(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    CHECK_MUTABLE(rcv);
-    for (int i = argc - 1; i >= 0; i--) {
-	TRY_MOP([rcv insertObject:RB2OC(argv[i]) atIndex:0]);
-    }
-    return rcv;
-}
-
-static void
-nsary_insert(id rcv, long idx, VALUE elem)
-{
-    CHECK_MUTABLE(rcv);
-    const long len = [rcv count];
-    if (idx < 0) {
-	idx += len;
-	if (idx < 0) {
-	    rb_raise(rb_eIndexError, "index %ld out of array", idx - len);
-	}
-    }
-    if (idx > len) {
-	for (long i = len; i < idx; i++) {
-	    TRY_MOP([rcv addObject:[NSNull null]]);
-	} 	
-    }
-    TRY_MOP([rcv insertObject:RB2OC(elem) atIndex:idx]);
-}
-
-static id
-nsary_insert_m(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    CHECK_MUTABLE(rcv);
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
-    }
-    if (argc > 1) {
-	long pos = NUM2LONG(argv[0]);
-	if (pos == -1) {
-	    pos = [rcv count];
-	}
-	if (pos < 0) {
-	    pos++;
-	}
-	if (argc == 2) {
-	    nsary_insert(rcv, pos, argv[1]);
-	}
-	else {
-	    argc--;
-	    argv++;
-	    NSMutableArray *rpl = [NSMutableArray new];
-	    for (int i = 0; i < argc; i++) {
-		[rpl addObject:RB2OC(argv[i])];
-	    }
-	    nsary_splice(rcv, pos, 0, (VALUE)rpl);
-	}
-    }
-    return rcv;
-}
-
-static VALUE
-nsary_each(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    for (id item in rcv) {
-	rb_yield(OC2RB(item));
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)rcv;
-}
-
-static VALUE
-nsary_each_index(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    for (long i = 0, count = [rcv count]; i < count; i++) {
-	rb_yield(LONG2NUM(i));
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)rcv;
-}
-
-static VALUE
-nsary_reverse_each(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    long len = [rcv count];
-    while (len--) {
-	rb_yield(OC2RB([rcv objectAtIndex:len]));
-	RETURN_IF_BROKEN();
-	const long n = [rcv count];
-	if (n < len) {
-	    // Array was modified.
-	    len = n;
-	}
-    }
-    return (VALUE)rcv;
-
-}
-
-static VALUE
-nsary_length(id rcv, SEL sel)
-{
-     return LONG2NUM([rcv count]);
-}
-
-static VALUE
-nsary_empty(id rcv, SEL sel)
-{
-    return [rcv count] == 0 ? Qtrue : Qfalse;
-}
-
-static VALUE
-nsary_index(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    const long len = [rcv count];
-
-    if (argc == 0) {
-	RETURN_ENUMERATOR(rcv, 0, 0);
-	for (long i = 0; i < len; i++) {
-	    VALUE test = rb_yield(OC2RB([rcv objectAtIndex:i]));
-	    RETURN_IF_BROKEN();
-	    if (RTEST(test)) {
-		return LONG2NUM(i);
-	    }
-	}
-    }
-    else {
-	VALUE val;
-	rb_scan_args(argc, argv, "01", &val);
-	if (len > 0) {
-	    NSUInteger index = [rcv indexOfObject:RB2OC(val)
-		inRange:NSMakeRange(0, len)];
-	    if (index != NSNotFound) {
-		return LONG2NUM(index);
-	    }
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-nsary_rindex(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    const long len = [rcv count];
-
-    if (argc == 0) {
-	RETURN_ENUMERATOR(rcv, 0, 0);
-	long i = len;
-	while (i-- >= 0) {
-	    VALUE test = rb_yield(OC2RB([rcv objectAtIndex:i]));
-	    RETURN_IF_BROKEN();
-	    if (RTEST(test)) {
-		return LONG2NUM(i);
-	    }
-	}
-    }
-    else {
-	VALUE val;
- 	rb_scan_args(argc, argv, "01", &val);
-	id ocval = RB2OC(val);
-	for (long i = len - 1; i >= 0; i--) {
-	    id item = [rcv objectAtIndex:i];
-	    if ([ocval isEqual:item]) {
-		return LONG2NUM(i);
-	    }
-	}
-    }
-    return Qnil;
-}
-
-static id
-nsary_reverse_bang(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    for (long i = 0, count = [rcv count]; i < (count / 2); i++) {
-	TRY_MOP([rcv exchangeObjectAtIndex:i withObjectAtIndex:count - i - 1]);
-    }
-    return rcv;
-}
-
-static id
-nsary_reverse(id rcv, SEL sel)
-{
-    NSMutableArray *result = [NSMutableArray arrayWithArray:rcv];
-    return nsary_reverse_bang(result, 0);
-}
-
-static NSInteger
-sort_block(id x, id y, void *context)
-{
-    VALUE rbx = OC2RB(x);
-    VALUE rby = OC2RB(y);
-    VALUE ret = rb_yield_values(2, rbx, rby);
-    return rb_cmpint(ret, rbx, rby);
-}
-
-static id
-nsary_sort_bang(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    if ([rcv count] > 1) {
-	if (rb_block_given_p()) {
-	    TRY_MOP([rcv sortUsingFunction:sort_block context:NULL]);
-	}
-	else {
-	    TRY_MOP([rcv sortUsingSelector:@selector(compare:)]);
-	}
-    }
-    return rcv;
-}
-
-static id
-nsary_sort(id rcv, SEL sel)
-{
-    NSMutableArray *result = [NSMutableArray arrayWithArray:rcv];
-    return nsary_sort_bang(result, 0);
-}
-
-static VALUE
-collect(id rcv)
-{
-    CHECK_MUTABLE(rcv);
-    for (long i = 0, count = [rcv count]; i < count; i++) {
-	id elem = [rcv objectAtIndex:i];
-	id newval = RB2OC(rb_yield(OC2RB(elem)));
-	RETURN_IF_BROKEN();
-	TRY_MOP([rcv replaceObjectAtIndex:i withObject:newval]);
-    }
-    return (VALUE)rcv;
-}
-
-static VALUE
-nsary_collect_bang(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    return collect(rcv);
-}
-
-static VALUE
-nsary_collect(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    NSMutableArray *result = [NSMutableArray arrayWithArray:rcv];
-    return collect(result);
-}
-
-static VALUE
-nsary_select(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    NSMutableArray *result = [NSMutableArray new];
-    for (id elem in rcv) {
-	VALUE test = rb_yield(OC2RB(elem));
-	RETURN_IF_BROKEN();
-	if (RTEST(test)) {
-	    [result addObject:elem];
-	}
-    }
-    return (VALUE)result;
-}
-
-static id
-nsary_values_at(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    const long rcvlen = [rcv count];
-    NSMutableArray *result = [NSMutableArray new];
-    for (long i = 0; i < argc; i++) {
-	long beg, len;
-	switch (rb_range_beg_len(argv[i], &beg, &len, rcvlen, 0)) {
-	    // Check if Range.
-	    case Qfalse:
-		break;
-	    case Qnil:
-		continue;
-	    default:
-		for (long j = 0; j < len; j++) {
-		    [result addObject:[rcv objectAtIndex:j + beg]];
-		}
-		continue;
-	}
-	[result addObject:[rcv objectAtIndex:NUM2LONG(argv[i])]];
-    }
-    return result;
-}
-
-static bool
-nsary_delete_element(id rcv, VALUE elem)
-{
-    id ocelem = RB2OC(elem);
-    long len = [rcv count];
-    NSRange range = NSMakeRange(0, len);
-    NSUInteger index;
-    bool changed = false;
-    CHECK_MUTABLE(rcv);
-    while ((index = [rcv indexOfObject:ocelem inRange:range]) != NSNotFound) {
-	TRY_MOP([rcv removeObjectAtIndex:index]);
-	range.location = index;
-	range.length = --len - index;
-	changed = true;
-    }
-    return changed;
-}
-
-static VALUE
-nsary_delete(id rcv, SEL sel, VALUE elem)
-{
-    if (!nsary_delete_element(rcv, elem)) {
-	if (rb_block_given_p()) {
-	    return rb_yield(elem);
-	}
-	return Qnil;
-    }
-    return elem;
-}
-
-static VALUE
-nsary_delete_at(id rcv, SEL sel, VALUE pos)
-{
-    CHECK_MUTABLE(rcv);
-    long index = NUM2LONG(pos);
-    const long len = [rcv count];
-    if (index >= len) {
-	return Qnil;
-    }
-    if (index < 0) {
-	index += len;
-	if (index < 0) {
-	    return Qnil;
-	}
-    }
-    VALUE elem = OC2RB([rcv objectAtIndex:index]);
-    TRY_MOP([rcv removeObjectAtIndex:index]); 
-    return elem;
-}
-
-static VALUE
-reject(id rcv)
-{
-    CHECK_MUTABLE(rcv);
-    bool changed = false;
-    for (long i = 0, n = [rcv count]; i < n; i++) {
-	VALUE elem = OC2RB([rcv objectAtIndex:i]);
-	VALUE test = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (RTEST(test)) {
-	    TRY_MOP([rcv removeObjectAtIndex:i]);
-	    n--;
-	    i--;
-	    changed = true;
-	}
-    }
-    return changed ? (VALUE)rcv : Qnil;
-}
-
-static VALUE
-nsary_delete_if(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    return reject(rcv);
-}
-
-static VALUE
-nsary_reject(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    NSMutableArray *result = [NSMutableArray arrayWithArray:rcv];
-    reject(result);
-    return (VALUE)rcv;
-}
-
-static VALUE
-nsary_reject_bang(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    return reject(rcv);
-}
-
-static id
-nsary_replace(id rcv, SEL sel, VALUE other)
-{
-    other = to_ary(other);
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv setArray:(id)other]);
-    return rcv;
-}
-
-static VALUE
-nsary_includes(id rcv, SEL sel, VALUE obj)
-{
-    id elem = RB2OC(obj);
-    return [rcv containsObject:elem] ? Qtrue : Qfalse;
-}
-
-static VALUE
-nsary_slice_bang(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    const long rcvlen = [rcv count];
-    VALUE arg1, arg2;
-    long pos, len;
-
-    if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
-	pos = NUM2LONG(arg1);
-	len = NUM2LONG(arg2);
-delete_pos_len:
-	if (pos < 0) {
-	    pos = rcvlen + pos;
-	    if (pos < 0) {
-		return Qnil;
-	    }
-	}
-	if (rcvlen < len || rcvlen < pos + len) {
-	    len = rcvlen - pos;
-	}
-	VALUE result = nsary_subseq(rcv, pos, len);
-	nsary_splice(rcv, pos, len, Qundef);
-	return result;
-    }
-
-    if (!FIXNUM_P(arg1)) {
-	switch (rb_range_beg_len(arg1, &pos, &len, rcvlen, 0)) {
-	    case Qtrue:
-		// Valid range.
-		goto delete_pos_len;
-	    case Qnil:
-		// invalid range.
-		return Qnil;
-	    default:
-		// Not a range.
-		break;
-	}
-    }
-
-    return nsary_delete_at(rcv, 0, arg1);
-}
-
-static id
-nsary_plus(id rcv, SEL sel, VALUE other)
-{
-    other = to_ary(other);
-    NSMutableArray *ary = [NSMutableArray new];
-    [ary addObjectsFromArray:rcv];
-    [ary addObjectsFromArray:(id)other];
-    return ary;
-}
-
-static id
-nsary_times(id rcv, SEL sel, VALUE times)
-{
-    VALUE tmp = rb_check_string_type(times);
-    if (!NIL_P(tmp)) {
-	return (id)rb_ary_join((VALUE)rcv, tmp);
-    }
-
-    const long len = NUM2LONG(times);
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative argument");
-    }
-
-    NSMutableArray *result = [NSMutableArray new];
-    if (len > 0) {
-	const long n = [rcv count];
-	if (LONG_MAX/len < n) {
-	    rb_raise(rb_eArgError, "argument too big");
-	}
-	for (long i = 0; i < len; i++) {
-	    [result addObjectsFromArray:rcv];
-	}
-    }
-    return result;
-}
-
-static VALUE
-nsary_uniq_bang(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    long len = [rcv count];
-    bool changed = false;
-    for (long i = 0; i < len; i++) {
-	id elem = [rcv objectAtIndex:i];
-	NSRange range = NSMakeRange(i + 1, len - i - 1);
-	NSUInteger index;
-	while ((index = [rcv indexOfObject:elem inRange:range]) != NSNotFound) {
-	    TRY_MOP([rcv removeObjectAtIndex:index]);
-	    range.location = index;
-	    range.length = --len - index;
-	    changed = true;
-	}
-    }
-    return changed ? (VALUE)rcv : Qnil;
-}
-
-static id 
-nsary_uniq(id rcv, SEL sel)
-{
-    id result = [NSMutableArray arrayWithArray:rcv];
-    nsary_uniq_bang(result, 0);
-    return result;
-}
-
-static VALUE
-nsary_compact_bang(id rcv, SEL sel)
-{
-    return nsary_delete_element(rcv, Qnil) ? (VALUE)rcv : Qnil;
-}
-
-static id
-nsary_compact(id rcv, SEL sel)
-{
-    id result = [NSMutableArray arrayWithArray:rcv];
-    nsary_compact_bang(result, 0);
-    return result;
-}
-
-static VALUE
-nsary_drop(id rcv, SEL sel, VALUE n)
-{
-    const long pos = NUM2LONG(n);
-    if (pos < 0) {
-	rb_raise(rb_eArgError, "attempt to drop negative size");
-    }
-    return nsary_subseq(rcv, pos, [rcv count]);
-}
-
-static VALUE
-nsary_drop_while(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    long i = 0;
-    for (long count = [rcv count]; i < count; i++) {
-	VALUE v = rb_yield(OC2RB([rcv objectAtIndex:i]));
-	RETURN_IF_BROKEN();
-	if (!RTEST(v)) {
-	    break;
-	}
-    }
-    return nsary_drop(rcv, 0, LONG2FIX(i));
-}
-
-static VALUE
-nsary_take(id rcv, SEL sel, VALUE n)
-{
-    const long len = NUM2LONG(n);
-    if (len < 0) {
-	rb_raise(rb_eArgError, "attempt to take negative size");
-    }
-    return nsary_subseq(rcv, 0, len);
-}
-
-static VALUE
-nsary_take_while(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    long i = 0;
-    for (long count = [rcv count]; i < count; i++) {
-	VALUE v = rb_yield(OC2RB([rcv objectAtIndex:i]));
-	RETURN_IF_BROKEN();
-	if (!RTEST(v)) {
-	    break;
-	}
-    }
-    return nsary_take(rcv, 0, LONG2FIX(i));
-}
-
-static id
-nsary_shuffle_bang(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    long i = [rcv count];
-    while (i > 0) {
-	const long j = rb_genrand_real() * i--;
-	TRY_MOP([rcv exchangeObjectAtIndex:i withObjectAtIndex:j]);
-    }
-    return rcv;
-}
-
-static id
-nsary_shuffle(id rcv, SEL sel)
-{
-    id result = [NSMutableArray arrayWithArray:rcv];
-    nsary_shuffle_bang(result, 0);
-    return result;
-}
-
-void
-Init_NSArray(void)
-{
-    rb_cArray = rb_cNSArray;
-    rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
-    assert(rb_cNSMutableArray != 0);
-
-    rb_include_module(rb_cArray, rb_mEnumerable);
-
-    rb_objc_define_method(rb_cArray, "dup", nsary_dup, 0);
-    rb_objc_define_method(rb_cArray, "clone", nsary_clone, 0);
-    rb_objc_define_method(rb_cArray, "clear", nsary_clear, 0);
-    rb_objc_define_method(rb_cArray, "to_s", nsary_inspect, 0);
-    rb_objc_define_method(rb_cArray, "inspect", nsary_inspect, 0);
-    rb_objc_define_method(rb_cArray, "to_a", nsary_to_a, 0);
-    rb_objc_define_method(rb_cArray, "to_ary", nsary_to_a, 0);
-    rb_objc_define_method(rb_cArray, "==", nsary_equal, 1);
-    rb_objc_define_method(rb_cArray, "eql?", nsary_equal, 1);
-    rb_objc_define_method(rb_cArray, "[]", nsary_aref, -1);
-    rb_objc_define_method(rb_cArray, "[]=", nsary_aset, -1);
-    rb_objc_define_method(rb_cArray, "at", nsary_at, 1);
-    rb_objc_define_method(rb_cArray, "fetch", nsary_fetch, -1);
-    rb_objc_define_method(rb_cArray, "first", nsary_first, -1);
-    rb_objc_define_method(rb_cArray, "last", nsary_last, -1);
-    rb_objc_define_method(rb_cArray, "concat", nsary_concat, 1);
-    rb_objc_define_method(rb_cArray, "<<", nsary_push, 1);
-    rb_objc_define_method(rb_cArray, "push", nsary_push_m, -1);
-    rb_objc_define_method(rb_cArray, "pop", nsary_pop, -1);
-    rb_objc_define_method(rb_cArray, "shift", nsary_shift, -1);
-    rb_objc_define_method(rb_cArray, "unshift", nsary_unshift, -1);
-    rb_objc_define_method(rb_cArray, "insert", nsary_insert_m, -1);
-    rb_objc_define_method(rb_cArray, "each", nsary_each, 0);
-    rb_objc_define_method(rb_cArray, "each_index", nsary_each_index, 0);
-    rb_objc_define_method(rb_cArray, "reverse_each", nsary_reverse_each, 0);
-    rb_objc_define_method(rb_cArray, "length", nsary_length, 0);
-    rb_objc_define_method(rb_cArray, "size", nsary_length, 0);
-    rb_objc_define_method(rb_cArray, "empty?", nsary_empty, 0);
-    rb_objc_define_method(rb_cArray, "find_index", nsary_index, -1);
-    rb_objc_define_method(rb_cArray, "index", nsary_index, -1);
-    rb_objc_define_method(rb_cArray, "rindex", nsary_rindex, -1);
-    rb_objc_define_method(rb_cArray, "reverse", nsary_reverse, 0);
-    rb_objc_define_method(rb_cArray, "reverse!", nsary_reverse_bang, 0);
-    rb_objc_define_method(rb_cArray, "sort", nsary_sort, 0);
-    rb_objc_define_method(rb_cArray, "sort!", nsary_sort_bang, 0);
-    rb_objc_define_method(rb_cArray, "collect", nsary_collect, 0);
-    rb_objc_define_method(rb_cArray, "collect!", nsary_collect_bang, 0);
-    rb_objc_define_method(rb_cArray, "map", nsary_collect, 0);
-    rb_objc_define_method(rb_cArray, "map!", nsary_collect_bang, 0);
-    rb_objc_define_method(rb_cArray, "select", nsary_select, 0);
-    rb_objc_define_method(rb_cArray, "values_at", nsary_values_at, -1);
-    rb_objc_define_method(rb_cArray, "delete", nsary_delete, 1);
-    rb_objc_define_method(rb_cArray, "delete_at", nsary_delete_at, 1);
-    rb_objc_define_method(rb_cArray, "delete_if", nsary_delete_if, 0);
-    rb_objc_define_method(rb_cArray, "reject", nsary_reject, 0);
-    rb_objc_define_method(rb_cArray, "reject!", nsary_reject_bang, 0);
-    rb_objc_define_method(rb_cArray, "replace", nsary_replace, 1);
-    rb_objc_define_method(rb_cArray, "include?", nsary_includes, 1);
-    rb_objc_define_method(rb_cArray, "slice", nsary_aref, -1);
-    rb_objc_define_method(rb_cArray, "slice!", nsary_slice_bang, -1);
-    rb_objc_define_method(rb_cArray, "+", nsary_plus, 1);
-    rb_objc_define_method(rb_cArray, "*", nsary_times, 1);
-    rb_objc_define_method(rb_cArray, "uniq", nsary_uniq, 0);
-    rb_objc_define_method(rb_cArray, "uniq!", nsary_uniq_bang, 0);
-    rb_objc_define_method(rb_cArray, "compact", nsary_compact, 0);
-    rb_objc_define_method(rb_cArray, "compact!", nsary_compact_bang, 0);
-    rb_objc_define_method(rb_cArray, "shuffle!", nsary_shuffle_bang, 0);
-    rb_objc_define_method(rb_cArray, "shuffle", nsary_shuffle, 0);
-    rb_objc_define_method(rb_cArray, "take", nsary_take, 1);
-    rb_objc_define_method(rb_cArray, "take_while", nsary_take_while, 0);
-    rb_objc_define_method(rb_cArray, "drop", nsary_drop, 1);
-    rb_objc_define_method(rb_cArray, "drop_while", nsary_drop_while, 0);
-
-    // Implementation shared with RubyArray (and defined in array.c).
-    rb_objc_define_method(rb_cArray, "-", rary_diff, 1);
-    rb_objc_define_method(rb_cArray, "&", rary_and, 1);
-    rb_objc_define_method(rb_cArray, "|", rary_or, 1);
-    rb_objc_define_method(rb_cArray, "join", rary_join, -1);
-    rb_objc_define_method(rb_cArray, "zip", rary_zip, -1);
-    rb_objc_define_method(rb_cArray, "transpose", rary_transpose, 0);
-    rb_objc_define_method(rb_cArray, "fill", rary_fill, -1);
-    rb_objc_define_method(rb_cArray, "<=>", rary_cmp, 1);
-    rb_objc_define_method(rb_cArray, "assoc", rary_assoc, 1);
-    rb_objc_define_method(rb_cArray, "rassoc", rary_rassoc, 1);
-    rb_objc_define_method(rb_cArray, "flatten", rary_flatten, -1);
-    rb_objc_define_method(rb_cArray, "flatten!", rary_flatten_bang, -1);
-    rb_objc_define_method(rb_cArray, "product", rary_product, -1);
-    rb_objc_define_method(rb_cArray, "combination", rary_combination, 1);
-    rb_objc_define_method(rb_cArray, "permutation", rary_permutation, -1);
-    rb_objc_define_method(rb_cArray, "cycle", rary_cycle, -1);
-    rb_objc_define_method(rb_cArray, "sample", rary_sample, -1);
-}
-
-// MRI compatibility API.
-
-VALUE
-rb_ary_freeze(VALUE ary)
-{
-    return OBJ_FREEZE(ary);
-}
-
-VALUE
-rb_ary_frozen_p(VALUE ary)
-{
-    return OBJ_FROZEN(ary) ? Qtrue : Qfalse;
-}
-
-long
-rb_ary_len(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return RARY(ary)->len;
-    }
-    else {
-	return [(id)ary count];
-    }
-}
-
-VALUE
-rb_ary_elt(VALUE ary, long offset)
-{
-    if (offset >= 0) {
-	if (IS_RARY(ary)) {
-	    if (offset < RARY(ary)->len) {
-		return rary_elt(ary, offset);
-	    }
-	}
-	else {
-	    if (offset < [(id)ary count]) {
-		return OC2RB([(id)ary objectAtIndex:offset]);
-	    }
-	}
-    }
-    return Qnil;
-}
-
-VALUE
-rb_ary_replace(VALUE rcv, VALUE other)
-{
-    other = to_ary(other);
-    rb_ary_clear(rcv);
-    for (long i = 0, count = RARRAY_LEN(other); i < count; i++) {
-	rb_ary_push(rcv, RARRAY_AT(other, i));
-    }
-    return rcv;
-}
-
-VALUE
-rb_ary_clear(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_clear(ary, 0);
-    }
-    else {
-	return (VALUE)nsary_clear((id)ary, 0);
-    }
-}
-
-static VALUE
-recursive_join(VALUE ary, VALUE argp, int recur)
-{
-    VALUE *arg = (VALUE *)argp;
-    if (recur) {
-	rb_raise(rb_eArgError, "recursive array join");
-    }
-    return rb_ary_join(arg[0], arg[1]);
-}
-
-// TODO: Make it faster.
-// rdoc spends a lot of time resizing strings concatenated by rb_ary_join.
-// Resizing the string buffer using str_resize_bytes with something close
-// to the final size before starting the concatenations would probably
-// make it much faster.
-VALUE
-rb_ary_join(VALUE ary, VALUE sep)
-{
-    if (RARRAY_LEN(ary) == 0) {
-	return rb_str_new(0, 0);
-    }
-
-    if (!NIL_P(sep)) {
-	StringValue(sep);
-    }
-
-    bool taint = false;
-    if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) {
-	taint = true;
-    }
-    bool untrust = false;
-    if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) {
-        untrust = true;
-    }
-
-    VALUE result = rb_str_new(0, 0);
-
-    for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	VALUE elem = RARRAY_AT(ary, i);
-	switch (TYPE(elem)) {
-	    case T_STRING:
-		break;
-	    case T_ARRAY:
-		{
-		    VALUE args[2] = {elem, sep};
-		    elem = rb_exec_recursive(recursive_join, ary, (VALUE)args);
-		}
-		break;
-	    default:
-		{
-		    VALUE tmp = rb_check_string_type(elem);
-		    if (!NIL_P(tmp)) {
-			elem = tmp;
-			break;
-		    }
-		    tmp = rb_check_convert_type(elem, T_ARRAY, "Array", "to_ary");
-		    if (!NIL_P(tmp)) {
-			VALUE args[2] = {tmp, sep};
-			elem = rb_exec_recursive(recursive_join, elem, (VALUE)args);
-			break;
-		    }
-		    elem = rb_obj_as_string(elem);
-		}
-		break;
-	}
-	if (i > 0 && !NIL_P(sep)) {
-	    rb_str_buf_append(result, sep);
-	}
-	rb_str_buf_append(result, elem);
-
-	if (OBJ_TAINTED(elem)) {
-	    taint = true;
-	}
-	if (OBJ_UNTRUSTED(elem)) {
-	    untrust = true;
-	}
-    }
-
-    if (taint) {
-	OBJ_TAINT(result);
-    }
-    if (untrust) {
-        OBJ_UNTRUST(result);
-    }
-    return result;
-}
-
-VALUE
-rb_ary_dup(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_dup(ary, 0);
-    }
-    else {
-	return (VALUE)nsary_dup((id)ary, 0);
-    }
-}
-
-VALUE
-rb_ary_reverse(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_reverse_bang(ary, 0);
-    }
-    else {
-	return (VALUE)nsary_reverse_bang((id)ary, 0);
-    }
-}
-
-VALUE
-rb_ary_includes(VALUE ary, VALUE item)
-{
-    if (IS_RARY(ary)) {
-	return rary_includes(ary, 0, item);
-    }
-    else {
-	return nsary_includes((id)ary, 0, item);
-    }
-}
-
-VALUE
-rb_ary_delete(VALUE ary, VALUE item)
-{
-    if (IS_RARY(ary)) {
-	return rary_delete(ary, 0, item);
-    }
-    else {
-	return nsary_delete((id)ary, 0, item);
-    }
-}
-
-VALUE
-rb_ary_delete_at(VALUE ary, long pos)
-{
-    if (IS_RARY(ary)) {
-	return rary_delete_at(ary, 0, LONG2NUM(pos));
-    }
-    else {
-	return nsary_delete_at((id)ary, 0, LONG2NUM(pos));
-    }
-}
-
-VALUE
-rb_ary_pop(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_pop(ary, 0, 0, NULL);
-    }
-    else {
-	return nsary_pop((id)ary, 0, 0, NULL);
-    }
-}
-
-VALUE
-rb_ary_shift(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_shift(ary, 0, 0, NULL);
-    }
-    else {
-	return nsary_shift((id)ary, 0, 0, NULL);
-    }
-}
-
-VALUE
-rb_ary_subseq(VALUE ary, long beg, long len)
-{
-   if (IS_RARY(ary)) {
-	return rary_subseq(ary, beg, len);
-   }
-   else {
-	return nsary_subseq((id)ary, beg, len);
-   }
-}
-
-VALUE
-rb_ary_entry(VALUE ary, long offset)
-{
-    if (IS_RARY(ary)) {
-	return rary_entry(ary, offset);
-    }
-    else {
-	return nsary_entry((id)ary, offset);
-    }
-}
-
-VALUE
-rb_ary_aref(int argc, VALUE *argv, VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_aref(ary, 0, argc, argv);
-    }
-    else {
-	return nsary_aref((id)ary, 0, argc, argv);
-    }
-}
-
-void
-rb_ary_store(VALUE ary, long idx, VALUE val)
-{
-    if (IS_RARY(ary)) {
-	rary_store(ary, idx, val);
-    }
-    else {
-	nsary_store((id)ary, idx, val);
-    }
-}
-
-void
-rb_ary_insert(VALUE ary, long idx, VALUE val)
-{
-    if (IS_RARY(ary)) {
-	rary_insert(ary, idx, val);
-    }
-    else {
-	nsary_insert((id)ary, idx, val);
-    }
-}
-
-VALUE
-rb_ary_concat(VALUE x, VALUE y)
-{
-    if (IS_RARY(x)) {
-	return rary_concat_m(x, 0, y);
-    }
-    else {
-	return (VALUE)nsary_concat((id)x, 0, y);
-    }
-}
-
-VALUE
-rb_ary_push(VALUE ary, VALUE item) 
-{
-    if (IS_RARY(ary)) {
-	return rary_push_m(ary, 0, item);
-    }
-    else {
-	return (VALUE)nsary_push((id)ary, 0, item);
-    }
-}
-
-VALUE
-rb_ary_plus(VALUE x, VALUE y)
-{
-    if (IS_RARY(x)) {
-	return rary_plus(x, 0, y);
-    }
-    else {
-	return (VALUE)nsary_plus((id)x, 0, y);
-    }
-}
-
-VALUE
-rb_ary_unshift(VALUE ary, VALUE item)
-{
-    if (IS_RARY(ary)) {
-	return rary_unshift(ary, 0, 1, &item);
-    }
-    else {
-	return (VALUE)nsary_unshift((id)ary, 0, 1, &item);
-    }
-}
-
-VALUE
-rb_ary_each(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_each(ary, 0);
-    }
-    else {
-	return nsary_each((id)ary, 0);
-    }
-}
-
-VALUE
-rb_ary_sort(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_sort(ary, 0);
-    }
-    else {
-	return (VALUE)nsary_sort((id)ary, 0);
-    }
-}
-
-VALUE
-rb_ary_sort_bang(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_sort_bang(ary, 0);
-    }
-    else {
-	return (VALUE)nsary_sort_bang((id)ary, 0);
-    }
-}
-
-static void *nsary_cptr_key = NULL;
-
-const VALUE *
-rb_ary_ptr(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	return rary_ptr(ary);
-    }
-
-    id nsary = (id)ary;
-    const long len = [nsary count];
-    if (len == 0) {
-	return NULL;
-    }
-
-    VALUE *values = (VALUE *)xmalloc(sizeof(VALUE) * len);
-    for (long i = 0; i < len; i++) {
-	values[i] = OC2RB([nsary objectAtIndex:i]);	
-    }
-
-    rb_objc_set_associative_ref((void *)nsary, &nsary_cptr_key, values);
-
-    return values;
-}
-
-// A very naive hashing function for arrays, which hashes the array's length,
-// then first and last elements (in case the array has more than 4 elements).
-// We cannot rely on the CoreFoundation hashing function for arrays as it's
-// simply returning the number of elements, and can trigger huge performance
-// problems when using same-sized arrays as keys in Hash objects.
-unsigned long
-rb_ary_hash(VALUE ary)
-{
-    const long len = RARRAY_LEN(ary);
-    unsigned long hash = 0;
-    if (len > 0) {
-	VALUE elem = RARRAY_AT(ary, 0);
-	if (elem == ary) {
-	    // recursive array
-	    return (unsigned long)rb_cRubyArray;
-	}
-	hash += rb_hash_code(elem);
-	if (len > 4) {
-	    elem = RARRAY_AT(ary, len - 1);
-	    if (elem == ary) {
-		// recursive array
-		return (unsigned long)rb_cRubyArray;
-	    }
-	    hash = (hash >> 3) ^ rb_hash_code(elem);
-	}
-	hash += len;
-    }
-    return hash;
-}

Deleted: MacRuby/trunk/NSDictionary.m
===================================================================
--- MacRuby/trunk/NSDictionary.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/NSDictionary.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,666 +0,0 @@
-/*
- * MacRuby extensions to NSDictionary.
- * 
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "objc.h"
-#include "vm.h"
-#include "hash.h"
-
-VALUE rb_cHash;
-VALUE rb_cNSHash;
-VALUE rb_cNSMutableHash;
-
-// Some NSDictionary instances actually do not even respond to mutable methods.
-// So one way to know is to check if the setObject:forKey: method exists.
-#define CHECK_MUTABLE(obj) \
-    do { \
-        if (![obj respondsToSelector:@selector(setObject:forKey:)]) { \
-	    rb_raise(rb_eRuntimeError, \
-		    "can't modify frozen/immutable hash"); \
-        } \
-    } \
-    while (0)
-
-// If a given mutable operation raises an NSException error,
-// it is likely that the object is not mutable.
-#define TRY_MOP(code) \
-    @try { \
-	code; \
-    } \
-    @catch(NSException *exc) { \
-	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable hash"); \
-    }
-
-static id
-to_hash(id hash)
-{
-    return (id)rb_convert_type((VALUE)hash, T_HASH, "Hash", "to_hash");
-}
-
-static id
-nshash_dup(id rcv, SEL sel)
-{
-    id dup = [rcv mutableCopy];
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(dup);
-    }
-    return dup;
-}
-
-static id
-nshash_clone(id rcv, SEL sel)
-{
-    id clone = nshash_dup(rcv, 0);
-    if (OBJ_FROZEN(rcv)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-static id
-nshash_rehash(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    NSArray *keys = [rcv allKeys];
-    NSArray *values = [rcv allValues];
-    assert([keys count] == [values count]);
-    TRY_MOP([rcv removeAllObjects]);
-    for (unsigned i = 0, count = [keys count]; i < count; i++) {
-	TRY_MOP([rcv setObject:[values objectAtIndex:i]
-		forKey:[keys objectAtIndex:i]]);
-    }
-    return rcv;
-}
-
-static id
-nshash_to_hash(id rcv, SEL sel)
-{
-    return rcv;
-}
-
-static id
-nshash_to_a(id rcv, SEL sel)
-{
-    NSMutableArray *ary = [NSMutableArray new];
-    for (id key in rcv) {
-	id value = [rcv objectForKey:key];
-	[ary addObject:[NSArray arrayWithObjects:key, value, nil]];
-    }
-    return ary;
-}
-
-static id
-nshash_inspect(id rcv, SEL sel)
-{
-    NSMutableString *str = [NSMutableString new];
-    [str appendString:@"{"];
-    for (id key in rcv) {
-	if ([str length] > 1) {
-	    [str appendString:@", "];
-	}
-	id value = [rcv objectForKey:key];
-	[str appendString:(NSString *)rb_inspect(OC2RB(key))];
-	[str appendString:@"=>"];
-	[str appendString:(NSString *)rb_inspect(OC2RB(value))];
-    }
-    [str appendString:@"}"];
-    return str;
-}
-
-static VALUE
-nshash_equal(id rcv, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_HASH) {
-	return Qfalse;
-    }
-    return [rcv isEqualToDictionary:(id)other] ? Qtrue : Qfalse;
-}
-
-static inline VALUE
-nshash_lookup(id rcv, VALUE key)
-{
-    return OC2RB([rcv objectForKey:RB2OC(key)]);
-}
-
-static VALUE
-nshash_aref(id rcv, SEL sel, VALUE key)
-{
-    return nshash_lookup(rcv, key);
-}
-
-static VALUE
-nshash_aset(id rcv, SEL sel, VALUE key, VALUE val)
-{
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv setObject:RB2OC(val) forKey:RB2OC(key)]);
-    return val;
-}
-
-static VALUE
-nshash_fetch(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE key, if_none;
-    rb_scan_args(argc, argv, "11", &key, &if_none);
-
-    const bool block_given = rb_block_given_p();
-    if (block_given && argc == 2) {
-	rb_warn("block supersedes default value argument");
-    }
-
-    id value = [rcv objectForKey:RB2OC(key)];
-    if (value != nil) {
-	return OC2RB(value);
-    }
-    if (block_given) {
-	return rb_yield(key);
-    }
-    if (argc == 1) {
-	rb_raise(rb_eKeyError, "key not found");
-    }
-    return if_none;
-}
-
-static VALUE
-nshash_default(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    // TODO
-    return Qnil;
-}
-
-static VALUE
-nshash_set_default(id rcv, SEL sel, VALUE default_value)
-{
-    // TODO
-    return Qnil;
-}
-
-static VALUE
-nshash_default_proc(id rcv, SEL sel)
-{
-    // Default procs are never possible with NSDictionaries.
-    return Qnil;
-}
-
-static VALUE
-nshash_key(id rcv, SEL sel, VALUE value)
-{
-    NSArray *keys = [rcv allKeysForObject:RB2OC(value)];
-    if ([keys count] > 0) {
-	return OC2RB([keys objectAtIndex:0]);
-    }
-    return Qnil;
-}
-
-static VALUE
-nshash_index(id rcv, SEL sel, VALUE value)
-{
-    rb_warn("Hash#index is deprecated; use Hash#key");
-    return nshash_key(rcv, 0, value);
-}
-
-static VALUE
-nshash_size(id rcv, SEL sel)
-{
-    return LONG2FIX([rcv count]);
-}
-
-static VALUE
-nshash_empty(id rcv, SEL sel)
-{
-    return [rcv count] == 0 ? Qtrue : Qfalse;
-}
-
-static VALUE
-nshash_each_value(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    for (id key in rcv) {
-	rb_yield(OC2RB([rcv objectForKey:key]));
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)rcv;
-}
-
-static VALUE
-nshash_each_key(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    for (id key in rcv) {
-	rb_yield(OC2RB(key));
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)rcv;
-}
-
-static VALUE
-nshash_each_pair(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    for (id key in rcv) {
-	id value = [rcv objectForKey:key];
-	rb_yield(rb_assoc_new(OC2RB(key), OC2RB(value)));
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)rcv;
-}
-
-static id
-nshash_keys(id rcv, SEL sel)
-{
-    return [[rcv allKeys] mutableCopy];
-}
-
-static id
-nshash_values(id rcv, SEL sel)
-{
-    return [[rcv allValues] mutableCopy];
-}
-
-static id
-nshash_values_at(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    NSMutableArray *ary = [NSMutableArray new];
-    for (int i = 0; i < argc; i++) {
-	id value = [rcv objectForKey:RB2OC(argv[i])];
-	[ary addObject:value];
-    }
-    return ary;
-}
-
-static VALUE
-nshash_shift(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    if ([rcv count] > 0) {
-	id key = [[rcv keyEnumerator] nextObject];
-	assert(key != NULL);
-	id value = [rcv objectForKey:key];
-	TRY_MOP([rcv removeObjectForKey:key]);
-	return rb_assoc_new(OC2RB(key), OC2RB(value));
-    }
-    return nshash_default(rcv, 0, 0, NULL);
-}
-
-static VALUE
-nshash_delete(id rcv, SEL sel, VALUE key)
-{
-    CHECK_MUTABLE(rcv);
-    id ockey = RB2OC(key);
-    id value = [rcv objectForKey:ockey];
-    if (value != nil) {
-	TRY_MOP([rcv removeObjectForKey:ockey]);
-	return OC2RB(value);
-    }
-    if (rb_block_given_p()) {
-	return rb_yield(key);
-    }
-    return Qnil;
-}
-
-static VALUE
-nshash_delete_if(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    NSMutableArray *ary = [NSMutableArray new];
-    for (id key in rcv) {
-	id value = [rcv objectForKey:key];
-	if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
-	    [ary addObject:key];
-	}
-	RETURN_IF_BROKEN();
-    }
-    TRY_MOP([rcv removeObjectsForKeys:ary]);
-    return (VALUE)rcv;
-}
-
-static VALUE
-nshash_select(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    NSMutableDictionary *dict = [NSMutableDictionary new];
-    for (id key in rcv) {
-	id value = [rcv objectForKey:key];
-	if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
-	    TRY_MOP([dict setObject:value forKey:key]);
-	}
-	RETURN_IF_BROKEN();
-    }
-    return (VALUE)dict;
-}
-
-static VALUE
-nshash_reject(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    return nshash_delete_if([rcv mutableCopy], 0); 
-}
-
-static VALUE
-nshash_reject_bang(id rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    unsigned size = [rcv count];
-    nshash_delete_if(rcv, 0);
-    return size != [rcv count] ? (VALUE)rcv : Qnil;
-}
-
-static id
-nshash_clear(id rcv, SEL sel)
-{
-    [rcv removeAllObjects];
-    return rcv;
-}
-
-static id
-nshash_update(id rcv, SEL sel, id hash)
-{
-    hash = to_hash(hash);
-    CHECK_MUTABLE(rcv);
-    if (rb_block_given_p()) {
-	for (id key in hash) {
-	    id value = [hash objectForKey:key];
-	    id old_value = [rcv objectForKey:key];
-	    if (old_value != nil) {
-		value = RB2OC(rb_yield_values(3, OC2RB(key), OC2RB(old_value),
-			    OC2RB(value)));
-	    }
-	    TRY_MOP([rcv setObject:value forKey:key]);
-	}
-    }
-    else {
-	for (id key in hash) {
-	    id value = [hash objectForKey:key];
-	    TRY_MOP([rcv setObject:value forKey:key]);
-	}
-    }    
-    return rcv;
-}
-
-static id
-nshash_merge(id rcv, SEL sel, id hash)
-{
-    return nshash_update([rcv mutableCopy], 0, hash);
-}
-
-static id
-nshash_replace(id rcv, SEL sel, id hash)
-{
-    hash = to_hash(hash);
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv setDictionary:hash]);
-    return rcv;
-}
-
-static VALUE
-nshash_assoc(id rcv, SEL sel, VALUE obj)
-{
-    for (id key in rcv) {
-	if (rb_equal(OC2RB(key), obj)) {
-	    id value = [rcv objectForKey:key];
-	    return rb_assoc_new(obj, OC2RB(value));
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-nshash_rassoc(id rcv, SEL sel, VALUE obj)
-{
-    for (id key in rcv) {
-	id value = [rcv objectForKey:key];
-	if (rb_equal(OC2RB(value), obj)) {
-	    return rb_assoc_new(OC2RB(key), obj);
-	}
-    }
-    return Qnil;
-}
-
-static id
-nshash_flatten(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    id ary = nshash_to_a(rcv, 0);
-    VALUE tmp;
-    if (argc == 0) {
-	argc = 1;
-	tmp = INT2FIX(1);
-	argv = &tmp;
-    }
-    rb_vm_call((VALUE)ary, sel_registerName("flatten!:"), argc, argv);
-    return ary;
-}
-
-static VALUE
-nshash_has_key(id rcv, SEL sel, VALUE key)
-{
-    return [rcv objectForKey:RB2OC(key)] == nil ? Qfalse : Qtrue;
-}
-
-static VALUE
-nshash_has_value(id rcv, SEL sel, VALUE value)
-{
-    return [[rcv allKeysForObject:RB2OC(value)] count] == 0 ? Qfalse : Qtrue;
-}
-
-static id
-nshash_compare_by_id(id rcv, SEL sel)
-{
-    // Not implemented.
-    return rcv;
-}
-
-static VALUE
-nshash_compare_by_id_p(id rcv, SEL sel)
-{
-    // Not implemented.
-    return Qfalse;
-}
-
-void
-Init_NSDictionary(void)
-{
-    rb_cHash = rb_cNSHash;
-    rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
-    assert(rb_cNSMutableHash != 0);
-
-    rb_include_module(rb_cHash, rb_mEnumerable);
-
-    rb_objc_define_method(rb_cHash, "dup", nshash_dup, 0);
-    rb_objc_define_method(rb_cHash, "clone", nshash_clone, 0);
-    rb_objc_define_method(rb_cHash, "rehash", nshash_rehash, 0);
-    rb_objc_define_method(rb_cHash, "to_hash", nshash_to_hash, 0);
-    rb_objc_define_method(rb_cHash, "to_a", nshash_to_a, 0);
-    rb_objc_define_method(rb_cHash, "to_s", nshash_inspect, 0);
-    rb_objc_define_method(rb_cHash, "inspect", nshash_inspect, 0);
-    rb_objc_define_method(rb_cHash, "==", nshash_equal, 1);
-    rb_objc_define_method(rb_cHash, "eql?", nshash_equal, 1);
-    rb_objc_define_method(rb_cHash, "[]", nshash_aref, 1);
-    rb_objc_define_method(rb_cHash, "[]=", nshash_aset, 2);
-    rb_objc_define_method(rb_cHash, "fetch", nshash_fetch, -1);
-    rb_objc_define_method(rb_cHash, "store", nshash_aset, 2);
-    rb_objc_define_method(rb_cHash, "default", nshash_default, -1);
-    rb_objc_define_method(rb_cHash, "default=", nshash_set_default, 1);
-    rb_objc_define_method(rb_cHash, "default_proc", nshash_default_proc, 0);
-    rb_objc_define_method(rb_cHash, "key", nshash_key, 1);
-    rb_objc_define_method(rb_cHash, "index", nshash_index, 1);
-    rb_objc_define_method(rb_cHash, "size", nshash_size, 0);
-    rb_objc_define_method(rb_cHash, "length", nshash_size, 0);
-    rb_objc_define_method(rb_cHash, "empty?", nshash_empty, 0);
-    rb_objc_define_method(rb_cHash, "each_value", nshash_each_value, 0);
-    rb_objc_define_method(rb_cHash, "each_key", nshash_each_key, 0);
-    rb_objc_define_method(rb_cHash, "each_pair", nshash_each_pair, 0);
-    rb_objc_define_method(rb_cHash, "each", nshash_each_pair, 0);
-    rb_objc_define_method(rb_cHash, "keys", nshash_keys, 0);
-    rb_objc_define_method(rb_cHash, "values", nshash_values, 0);
-    rb_objc_define_method(rb_cHash, "values_at", nshash_values_at, -1);
-    rb_objc_define_method(rb_cHash, "shift", nshash_shift, 0);
-    rb_objc_define_method(rb_cHash, "delete", nshash_delete, 1);
-    rb_objc_define_method(rb_cHash, "delete_if", nshash_delete_if, 0);
-    rb_objc_define_method(rb_cHash, "select", nshash_select, 0);
-    rb_objc_define_method(rb_cHash, "reject", nshash_reject, 0);
-    rb_objc_define_method(rb_cHash, "reject!", nshash_reject_bang, 0);
-    rb_objc_define_method(rb_cHash, "clear", nshash_clear, 0);
-    // XXX: #invert is a private method on NSMutableDictionary, so to not
-    // break things we do not implement it.
-    rb_objc_define_method(rb_cHash, "update", nshash_update, 1);
-    rb_objc_define_method(rb_cHash, "merge!", nshash_update, 1);
-    rb_objc_define_method(rb_cHash, "merge", nshash_merge, 1);
-    rb_objc_define_method(rb_cHash, "replace", nshash_replace, 1);
-    rb_objc_define_method(rb_cHash, "assoc", nshash_assoc, 1);
-    rb_objc_define_method(rb_cHash, "rassoc", nshash_rassoc, 1);
-    rb_objc_define_method(rb_cHash, "flatten", nshash_flatten, -1);
-    rb_objc_define_method(rb_cHash, "include?", nshash_has_key, 1);
-    rb_objc_define_method(rb_cHash, "member?", nshash_has_key, 1);
-    rb_objc_define_method(rb_cHash, "key?", nshash_has_key, 1);
-    rb_objc_define_method(rb_cHash, "has_key?", nshash_has_key, 1);
-    rb_objc_define_method(rb_cHash, "value?", nshash_has_value, 1);
-    rb_objc_define_method(rb_cHash, "has_value?", nshash_has_value, 1);
-    rb_objc_define_method(rb_cHash, "compare_by_identity",
-	    nshash_compare_by_id, 0);
-    rb_objc_define_method(rb_cHash, "compare_by_identity?",
-	    nshash_compare_by_id_p, 0);
-}
-
-// MRI compatibility API.
-
-VALUE
-rb_hash_dup(VALUE rcv)
-{
-    if (IS_RHASH(rcv)) {
-	return rhash_dup(rcv, 0);
-    }
-    else {
-	return (VALUE)nshash_dup((id)rcv, 0);
-    }
-}
-
-void
-rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
-{
-    if (IS_RHASH(hash)) {
-	rhash_foreach(hash, func, farg);
-    }
-    else {
-	for (id key in (id)hash) {
-	    id value = [(id)hash objectForKey:key];
-	    if ((*func)(OC2RB(key), OC2RB(value), farg) == ST_STOP) {
-		break;
-	    }
-	}
-    }
-}
-
-VALUE
-rb_hash_lookup(VALUE hash, VALUE key)
-{
-    if (IS_RHASH(hash)) {
-	VALUE val = rhash_lookup(hash, key);
-	return val == Qundef ? Qnil : val;
-    }
-    else {
-	return nshash_lookup((id)hash, key);
-    }
-}
-
-VALUE
-rb_hash_aref(VALUE hash, VALUE key)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_aref(hash, 0, key);
-    }
-    else {
-	return nshash_lookup((id)hash, key);
-    }
-}
-
-VALUE
-rb_hash_delete_key(VALUE hash, VALUE key)
-{
-    if (IS_RHASH(hash)) {
-	rhash_modify(hash);
-	return rhash_delete_key(hash, key);
-    }
-    else {
-	id ockey = RB2OC(key);
-	id value = [(id)hash objectForKey:ockey];
-	if (value != nil) {
-	    [(id)hash removeObjectForKey:ockey];
-	    return OC2RB(value);
-	}
-	return Qundef;
-    }
-}
-
-VALUE
-rb_hash_delete(VALUE hash, VALUE key)
-{
-    VALUE val = rb_hash_delete_key(hash, key);
-    if (val != Qundef) {
-	return val;
-    }
-    return Qnil;
-}
-
-VALUE
-rb_hash_aset(VALUE hash, VALUE key, VALUE val)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_aset(hash, 0, key, val);
-    }
-    else {
-	return nshash_aset((id)hash, 0, key, val);
-    }
-}
-
-long
-rb_hash_size(VALUE hash)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_len(hash);
-    }
-    else {
-	return [(id)hash count];
-    }
-}
-
-VALUE
-rb_hash_keys(VALUE hash)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_keys(hash, 0);
-    }
-    else {
-	return (VALUE)nshash_keys((id)hash, 0);
-    }
-}
-
-VALUE
-rb_hash_has_key(VALUE hash, VALUE key)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_has_key(hash, 0, key);
-    }
-    else {
-	return nshash_has_key((id)hash, 0, key);
-    }
-}
-
-VALUE
-rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
-{
-    if (IS_RHASH(hash)) {
-	return rhash_set_default(hash, 0, ifnone);
-    }
-    else {
-	return nshash_set_default((id)hash, 0, ifnone);
-    }
-}

Deleted: MacRuby/trunk/NSString.m
===================================================================
--- MacRuby/trunk/NSString.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/NSString.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,441 +0,0 @@
-/*
- * MacRuby extensions to NSString.
- * 
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "objc.h"
-#include "vm.h"
-#include "encoding.h"
-
-VALUE rb_cString;
-VALUE rb_cNSString;
-VALUE rb_cNSMutableString;
-
-// Some NSString instances actually do not even respond to mutable methods.
-// So one way to know is to check if the setString: method exists.
-#define CHECK_MUTABLE(obj) \
-    do { \
-        if (![obj respondsToSelector:@selector(setString:)]) { \
-	    rb_raise(rb_eRuntimeError, \
-		    "can't modify frozen/immutable string"); \
-        } \
-    } \
-    while (0)
-
-// If a given mutable operation raises an NSException error,
-// it is likely that the object is not mutable.
-#define TRY_MOP(code) \
-    @try { \
-	code; \
-    } \
-    @catch(NSException *exc) { \
-	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable string"); \
-    }
-
-static inline VALUE
-to_str(VALUE str)
-{
-    switch (TYPE(str)) {
-	case T_STRING:
-	    return str;
-	case T_SYMBOL:
-	    return rb_sym_to_s(str);
-    }
-    return rb_convert_type(str, T_STRING, "String", "to_str");
-}
-
-static id
-nsstr_dup(id rcv, SEL sel)
-{
-    id dup = [rcv mutableCopy];
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(dup);
-    }
-    return dup;
-}
-
-static id
-nsstr_clone(id rcv, SEL sel)
-{
-    id clone = nsstr_dup(rcv, 0);
-    if (OBJ_FROZEN(rcv)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-static id
-nsstr_to_s(id rcv, SEL sel)
-{
-    return rcv;
-}
-
-static id
-nsstr_replace(id rcv, SEL sel, VALUE other)
-{
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv setString:(id)to_str(other)]);
-    return rcv;
-}
-
-static id
-nsstr_clear(id rcv, SEL sel)
-{
-    CHECK_MUTABLE(rcv);
-    const long len = [rcv length];
-    if (len > 0) {
-	TRY_MOP([rcv deleteCharactersInRange:NSMakeRange(0, len)]);
-    }
-    return rcv;
-}
-
-static VALUE
-nsstr_encoding(id rcv, SEL sel)
-{
-    // All NSStrings are Unicode, so let's return UTF-8.
-    return (VALUE)rb_encodings[ENCODING_UTF8];
-}
-
-static VALUE
-nsstr_length(id rcv, SEL sel)
-{
-    return LONG2NUM([rcv length]);
-}
-
-static VALUE
-nsstr_empty(id rcv, SEL sel)
-{
-    return [rcv length] == 0 ? Qtrue : Qfalse;
-}
-
-static id
-nsstr_concat(id rcv, SEL sel, VALUE other)
-{
-    CHECK_MUTABLE(rcv);
-    TRY_MOP([rcv appendString:(id)to_str(other)]);
-    return rcv;
-}
-
-static id
-nsstr_plus(id rcv, SEL sel, VALUE other)
-{
-    id newstr = [NSMutableString new];
-    [newstr appendString:rcv];
-    [newstr appendString:(id)to_str(other)];
-    return newstr;
-}
-
-static VALUE
-nsstr_equal(id rcv, SEL sel, VALUE other)
-{
-    if (rcv == (id)other) {
-        return Qtrue;
-    }
-    if (TYPE(other) != T_STRING) {
-        if (!rb_respond_to(other, rb_intern("to_str"))) {
-            return Qfalse;
-        }
-        return rb_equal(other, (VALUE)rcv);
-    }
-    return [rcv isEqualToString:(id)to_str(other)] ? Qtrue : Qfalse;
-}
-
-static VALUE
-nsstr_cmp(id rcv, SEL sel, VALUE other)
-{
-    int ret = [rcv compare:(id)to_str(other)];
-    if (ret > 0) {
-	ret = 1;
-    }
-    else if (ret < 0) {
-	ret = -1;
-    }
-    return INT2FIX(ret);
-}
-
-static VALUE
-nsstr_casecmp(id rcv, SEL sel, VALUE other)
-{
-    int ret = [rcv compare:(id)to_str(other) options:NSCaseInsensitiveSearch];
-    if (ret > 0) {
-	ret = 1;
-    }
-    else if (ret < 0) {
-	ret = -1;
-    }
-    return INT2FIX(ret);
-}
-
-static VALUE
-nsstr_include(id rcv, SEL sel, VALUE other)
-{
-    NSRange range = [rcv rangeOfString:(id)to_str(other)];
-    return range.location == NSNotFound ? Qfalse : Qtrue;
-}
-
-static id
-rstr_only(id rcv, SEL sel)
-{
-    rb_raise(rb_eArgError, "method `%s' does not work on NSStrings",
-	    sel_getName(sel));
-    return rcv; // never reached
-}
-
-static VALUE
-nsstr_to_rstr(id nsstr)
-{
-    const long len = [nsstr length];
-    if (len == 0) {
-	return rb_str_new(NULL, 0);
-    }
-
-    unichar *buf = (unichar *)malloc(sizeof(unichar) * len);
-    [nsstr getCharacters:buf range:NSMakeRange(0, len)];
-    VALUE rstr = rb_unicode_str_new(buf, len);
-    free(buf);
-    return rstr;
-}
-
-static VALUE
-nsstr_forward_m1(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_vm_call2(rb_vm_current_block(), nsstr_to_rstr(rcv), 0, sel, argc, argv);
-}
-
-static VALUE
-nsstr_forward_0(id rcv, SEL sel)
-{
-    return nsstr_forward_m1(rcv, sel, 0, NULL);
-}
-
-static VALUE
-nsstr_forward_1(id rcv, SEL sel, VALUE arg1)
-{
-    return nsstr_forward_m1(rcv, sel, 1, &arg1);
-}
-
-static VALUE
-nsstr_forward_2(id rcv, SEL sel, VALUE arg1, VALUE arg2)
-{
-    VALUE args[2] = {arg1, arg2};
-    return nsstr_forward_m1(rcv, sel, 2, args);
-}
-
-static VALUE
-nsstr_forward_3(id rcv, SEL sel, VALUE arg1, VALUE arg2, VALUE arg3)
-{
-    VALUE args[3] = {arg1, arg2, arg3};
-    return nsstr_forward_m1(rcv, sel, 3, args);
-}
-
-static VALUE
-nsstr_forward_bang_m1(id rcv, SEL sel, int argc, VALUE *argv)
-{
-    CHECK_MUTABLE(rcv);
-    VALUE rcv_rstr = nsstr_to_rstr(rcv);
-    VALUE ret = rb_vm_call2(rb_vm_current_block(), rcv_rstr, 0, sel, argc, argv);
-    TRY_MOP([rcv setString:(id)rcv_rstr]);
-    return ret;
-}
-
-static VALUE
-nsstr_forward_bang_0(id rcv, SEL sel)
-{
-    return nsstr_forward_bang_m1(rcv, sel, 0, NULL);
-}
-
-static VALUE
-nsstr_forward_bang_1(id rcv, SEL sel, VALUE arg1)
-{
-    return nsstr_forward_bang_m1(rcv, sel, 1, &arg1);    
-}
-
-static VALUE
-nsstr_forward_bang_2(id rcv, SEL sel, VALUE arg1, VALUE arg2)
-{
-    VALUE args[2] = {arg1, arg2};
-    return nsstr_forward_bang_m1(rcv, sel, 2, args);
-}
-
-static VALUE
-nsstr_forward_bang_3(id rcv, SEL sel, VALUE arg1, VALUE arg2, VALUE arg3)
-{
-    VALUE args[3] = {arg1, arg2, arg3};
-    return nsstr_forward_bang_m1(rcv, sel, 3, args);
-}
-
-void
-rb_str_NSCoder_encode(void *coder, VALUE str, const char *key)
-{
-    NSString *nskey = [NSString stringWithUTF8String:key];
-    [(NSCoder *)coder encodeObject:(NSString *)str forKey:nskey];
-}
-
-VALUE
-rb_str_NSCoder_decode(void *coder, const char *key)
-{
-    NSString *nskey = [NSString stringWithUTF8String:key];
-    return OC2RB([(NSCoder *)coder decodeObjectForKey:nskey]);
-}
-
-void
-Init_NSString(void)
-{
-    rb_cString = rb_cNSString;
-    rb_include_module(rb_cString, rb_mComparable);
-    rb_cNSMutableString = (VALUE)objc_getClass("NSMutableString");
-    assert(rb_cNSMutableString != 0);
-
-    rb_objc_define_method(rb_cString, "dup", nsstr_dup, 0);
-    rb_objc_define_method(rb_cString, "clone", nsstr_clone, 0);
-    rb_objc_define_method(rb_cString, "to_s", nsstr_to_s, 0);
-    rb_objc_define_method(rb_cString, "to_str", nsstr_to_s, 0);
-    rb_objc_define_method(rb_cString, "replace", nsstr_replace, 1);
-    rb_objc_define_method(rb_cString, "clear", nsstr_clear, 0);
-    rb_objc_define_method(rb_cString, "encoding", nsstr_encoding, 0);
-    rb_objc_define_method(rb_cString, "size", nsstr_length, 0);
-    rb_objc_define_method(rb_cString, "empty?", nsstr_empty, 0);
-    rb_objc_define_method(rb_cString, "<<", nsstr_concat, 1);
-    rb_objc_define_method(rb_cString, "concat", nsstr_concat, 1);
-    rb_objc_define_method(rb_cString, "+", nsstr_plus, 1);
-    rb_objc_define_method(rb_cString, "==", nsstr_equal, 1);
-    rb_objc_define_method(rb_cString, "eql?", nsstr_equal, 1);
-    rb_objc_define_method(rb_cString, "<=>", nsstr_cmp, 1);
-    rb_objc_define_method(rb_cString, "casecmp", nsstr_casecmp, 1);
-    rb_objc_define_method(rb_cString, "include?", nsstr_include, 1);
-
-#define pick_forwarder(arity, bang) \
-    (arity == -1 \
-	? (bang \
-	    ? (void *)nsstr_forward_bang_m1 : (void *)nsstr_forward_m1)  \
-     : (arity == 0) \
-	? (bang \
-	    ? (void *)nsstr_forward_bang_0 : (void *)nsstr_forward_0) \
-     : (arity == 1) \
-	? (bang \
-	    ? (void *)nsstr_forward_bang_1 : (void *)nsstr_forward_1) \
-     : (arity == 2) \
-	? (bang \
-	    ? (void *)nsstr_forward_bang_2 : (void *)nsstr_forward_2) \
-     : (arity == 3) \
-	? (bang \
-	    ? (void *)nsstr_forward_bang_3 : (void *)nsstr_forward_3) \
-     : (abort(),NULL))
-
-#define forward(msg, arity) \
-    rb_objc_define_method(rb_cString, msg, pick_forwarder(arity, false), arity)
-
-#define forward_bang(msg, arity) \
-    rb_objc_define_method(rb_cString, msg, pick_forwarder(arity, true), arity)
-    
-    // These methods are implemented as forwarders.
-    forward("[]", -1);
-    forward_bang("[]=", -1);
-    forward("slice", -1);
-    forward_bang("slice!", -1);
-    forward_bang("insert", 2);
-    forward("index", -1);
-    forward("rindex", -1);
-    forward("+", 1);
-    forward("*", 1);
-    forward("%", 1);
-    forward("start_with?", -1);
-    forward("end_with?", -1);
-    forward("to_sym", 0);
-    forward("intern", 0);
-    forward("inspect", 0);
-    forward("dump", 0);
-    forward("match", -1);
-    forward("=~", 1);
-    forward("scan", 1);
-    forward("split", -1);
-    forward("to_i", -1);
-    forward("hex", 0);
-    forward("oct", 0);
-    forward("ord", 0);
-    forward("chr", 0);
-    forward("to_f", 0);
-    forward("chomp", -1);
-    forward_bang("chomp!", -1);
-    forward("chop", -1);
-    forward_bang("chop!", -1);
-    forward("sub", -1);
-    forward_bang("sub!", -1);
-    forward("gsub", -1);
-    forward_bang("gsub!", -1);
-    forward("downcase", 0);
-    forward_bang("downcase!", 0);
-    forward("upcase", 0);
-    forward_bang("upcase!", 0);
-    forward("swapcase", 0);
-    forward_bang("swapcase!", 0);
-    forward("capitalize", 0);
-    forward_bang("capitalize!", 0);
-    forward("ljust", -1);
-    forward("rjust", -1);
-    forward("center", -1);
-    forward("strip", 0);
-    forward("lstrip", 0);
-    forward("rstrip", 0);
-    forward_bang("strip!", 0);
-    forward_bang("lstrip!", 0);
-    forward_bang("rstrip!", 0);
-    forward("lines", -1);
-    forward("each_line", -1);
-    forward("chars", 0);
-    forward("each_char", 0);
-    forward("succ", 0);
-    forward_bang("succ!", 0);
-    forward("next", 0);
-    forward_bang("next!", 0);
-    forward("upto", -1);
-    forward("reverse", 0);
-    forward_bang("reverse!", 0);
-    forward("count", -1);
-    forward("delete", -1);
-    forward_bang("delete!", -1);
-    forward("squeeze", -1);
-    forward_bang("squeeze!", -1);
-    forward("tr", 2);
-    forward_bang("tr!", 2);
-    forward("tr_s", 2);
-    forward_bang("tr_s!", 2);
-    forward("sum", -1);
-    forward("partition", 1);
-    forward("rpartition", 1);
-    forward("crypt", 1);
-
-#undef forward
-#undef forward_bang
-
-    // These methods will not work on NSStrings.
-    rb_objc_define_method(rb_cString, "bytesize", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "getbyte", rstr_only, 1);
-    rb_objc_define_method(rb_cString, "setbyte", rstr_only, 2);
-    rb_objc_define_method(rb_cString, "force_encoding", rstr_only, 1);
-    rb_objc_define_method(rb_cString, "valid_encoding?", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "ascii_only?", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "bytes", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "each_byte", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "to_data", rstr_only, 0);
-    rb_objc_define_method(rb_cString, "pointer", rstr_only, 0);
-}
-
-const char *
-nsstr_cstr(VALUE str)
-{
-    return [(NSString *)str UTF8String];
-}
-
-long
-nsstr_clen(VALUE str)
-{
-    return [(NSString *)str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-}

Deleted: MacRuby/trunk/README.rdoc
===================================================================
--- MacRuby/trunk/README.rdoc	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/README.rdoc	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,73 +0,0 @@
-== MacRuby
-
-MacRuby is a Ruby implementation based on Mac OS X technologies, such as the 
-Objective-C runtime and garbage collector, the CoreFoundation framework and the
-LLVM compiler infrastructure.
-
-It is the goal of MacRuby to enable the creation of full-fledged Mac OS X
-applications which do not sacrifice performance in order to enjoy the benefits
-of using Ruby.
-
-MacRuby is copyrighted free software by Apple Inc and covered by the terms of
-the Ruby license. Please refer to the COPYING file for more information.
-
-The project website contains more documentation, such as tutorials and guides:
-http://macruby.org
-
-=== Requirements
-
-* An Intel 64-bit machine. PowerPC and Intel 32-bit machines are not supported
-  anymore, but may still work.
-
-* Mac OS X 10.6 or later.
-
-* LLVM ToT, compiled for x86_64.
-
-  LLVM is a moving target and breaks periodically. We recommend to install
-  revision 127367 of branch 2.9, being sure to specify the correct C and
-  C++ compilers through environment variables. 
-
-    $ svn co https://llvm.org/svn/llvm-project/llvm/branches/release_29@127367 llvm-2.9
-    $ cd llvm-2.9
-    $ env CC=/usr/bin/gcc CXX=/usr/bin/g++ ./configure --enable-bindings=none --enable-optimized --with-llvmgccdir=/tmp
-    $ env CC=/usr/bin/gcc CXX=/usr/bin/g++ make
-    $ sudo env CC=/usr/bin/gcc CXX=/usr/bin/g++ make install
-
-  Note that compiling LLVM can take quite a while. If you have a machine with
-  multiple cores, which is quite likely, you might want to speed up the process
-  by using all/more cores. However, doing this can make your machine
-  unresponsive during compilation. To use multiple cores pass the `-j N'
-  option, where `N' stands for the number of cores you'd like to use. So for a
-  Core Duo the command would look like:
-
-    $ env CC=/usr/bin/gcc CXX=/usr/bin/g++ make -j2
-
-  If you would prefer to update an existing LLVM Subversion working copy you 
-  need to be careful to remove any previous build files before you compile:
-
-    $ svn status --no-ignore | awk '{print $2}' | xargs rm -rf
-    $ svn revert -R .
-    $ svn switch <repository-URL>
-
-=== Build Instructions
-
-You can build MacRuby by doing the following command:
-
-  $ rake
-
-Or, as with LLVM, you can specify the amount of jobs to run simultaneously:
-
-  $ rake jobs=2
-
-Once done, you can run the RubySpec-based regression tests as well as the
-performance suite:
-
-  $ rake spec:ci
-  $ rake bench:ci
-
-To install MacRuby on your machine:
-
-  $ sudo rake install
-
-Then you should be all set! Please report us any problem you will find (the
-http://macruby.org website has pointers). Thanks!

Deleted: MacRuby/trunk/Rakefile
===================================================================
--- MacRuby/trunk/Rakefile	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/Rakefile	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,55 +0,0 @@
-# encoding: utf-8
-
-# See ./rakelib/*.rake for all tasks.
-
-ENV['RUBYOPT'] = '' # no RUBYOPT for spawned MacRuby processes
-
-desc "Same as all"
-task :default => :all
-
-desc "Same as framework:install"
-task :install => 'framework:install'
-
-desc "Same as macruby:build"
-task :macruby => 'macruby:build'
-
-# The old test tasks are now commented since we are switching to RubySpec
-# for regression testing. We still add a task to run the VM regression test
-# suite, though.
-desc "Run the VM regression test suite"
-task :test_vm do
-  sh "/usr/bin/ruby test_vm.rb"
-end
-=begin
-desc "Run the sample tests"
-task :sample_test do
-  sh "./miniruby rubytest.rb"
-end
-
-desc "Run the unit tests"
-task :unit_tests do
-  sh "./miniruby test/macruby_runner.rb"
-end
-
-desc "Run all tests"
-task :test => [:sample_test, :unit_tests]
-=end
-
-desc "Clean local and extension build files"
-task :clean => ['clean:local', 'clean:rbo', 'clean:ext', 'clean:doc']
-
-desc "Build everything"
-task :all => [:macruby, 'stdlib:build', :extensions, :doc]
-
-desc "Create an archive (GIT only)"
-task :git_archive do
-  sh "git archive --format=tar --prefix=MacRuby-HEAD/ HEAD | gzip >MacRuby-HEAD.tar.gz"
-end
-
-desc "Run all 'known good' specs (task alias for spec:ci)"
-task :spec => 'spec:ci'
-
-desc "Run IRB"
-task :irb do
-  exec './miniruby -I./lib ./bin/irb'
-end

Deleted: MacRuby/trunk/TODO
===================================================================
--- MacRuby/trunk/TODO	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/TODO	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,109 +0,0 @@
-For 0.6:
-
-[X] new Hash class, insertion ordering support, optimized for immediate types
-[X] new String and Symbol classes, support for 1.9 encoding semantics
-[X] new Regexp class, thread-safe, ICU-based
-[X] refactor Foundation bridging models
-  [X] NSDictionary
-  [X] NSArray
-  [X] NSString
-  [X] NSNumber
-[X] debugger
-  [X] command-line tool
-[/] MRI C extensions support
-  [X] implement missing API (use nokogiri as test bed)
-  [/] cleanup public headers
-  [ ] define an export file for the linker
-  [ ] GC support
-[/] rails
-  [X] project creation should work
-  [/] development web server
-  [/] hello world should work
-[ ] support Mocha
-[ ] support RSpec
-[/] 90% (min.) of rubyspecs should pass
-
-Historical:
-
-[ ] `macgem build' doesn't seem to work
-[ ] Hash subclass for immediates
-[ ] honor BridgeSupport printf_format attribute
-[/] support for bigdecimal
-    (implemented but some specs are failing, need to sync with upstream)
-[/] support for json
-    (implemented, do we have specs?)
-[/] support for yaml
-  [ ] pass remaining specs
-[/] support for openssl
-  [ ] finish porting to the new runtime APIs
-  [ ] check every RSTRING_PTR call to see if they are not f*cking up the data
-  [ ] pass specs (do we have some?)
-[/] support for zlib
-[ ] merge stdlib from 1.9.2 trunk
-[/] most language/core/library specs should run (modulo a very few exceptions)
-[/] port all rb_funcall() calls to rb_vm_call()
-[/] port all rb_num_coerce_bin() calls to rb_objc_num_coerce_bin()
-[/] port all rb_obj_respond_to() calls to rb_vm_respond_to()
-[/] ri should work
-  [ ] pager problem (apparent bug of IO.popen)
-  [ ] some annotations are not available (`macri -T Array' misses a lot), maybe
-      a YAML merging bug
-[ ] leaks
-  [ ] fix exception leak
-[/] thread issues
-  [ ] method cache is not thread safe
-  [ ] blocks are not reentrant
-      ex: b=Proc.new{}; 100.times{Thread.new{100.times{b.call}}}; sleep 1
-  [ ] exceptions not properly handled by the default EH in GCD blocks called
-      from a different thread
-      ex: g=Dispatch::Group.new; g.dispatch(Dispatch::Queue.concurrent) { raise('hey') }; g.wait
-[ ] implement Enumerable::Enumerator
-[ ] write a pass manager to eliminate unnecessary arrays generated by massigns
-[ ] vectorize bignums
-[ ] block inlining
-[ ] fast regexp =~
-[ ] rakefile-ize instruby.rb
-[ ] multithreaded JIT
-[ ] debugger interface
-[ ] fully implement FFI API
-[ ] add support for encodings in strings
-
-Porting from rb_define_method() to rb_objc_define_method():
-
-  Replace calls to rb_define_method() with a call to
-  rb_objc_define_method() and rewrite the function to 
-  conform to the following signatures:
-
-  // if arity -2
-  VALUE foo(VALUE recv, SEL sel, VALUE args);
-
-  // if arity -1
-  VALUE foo(VALUE recv, SEL sel, int argc, VALUE *argv);
-
-  // if arity 0
-  VALUE foo(VALUE recv, SEL sel);
-
-  // if arity 1
-  VALUE foo(VALUE recv, SEL sel, VALUE arg1);
-
-  // if arity 2
-  VALUE foo(VALUE recv, SEL sel, VALUE arg1, VALUE arg2);
-
-  // etc.
-
-  In the case of rb_define_global_function(), replace it with
-  rb_objc_define_method(rb_mKernel, ...)
-
-  In the case of rb_define_singleton_method() for defining class
-  functions and module-level functions, replace it with
-  rb_objc_define_method(*(VALUE *)klass, ...)
-
-  In the case of rb_define_singleton_method() for defining methods on 
-  individual instances of objects, replace it with
-  rb_objc_define_method(rb_singleton_class(obj), ...)
-
-  In the case of rb_define_module_function(), replace it with
-  rb_objc_define_module_function()
-
-  In the case of rb_define_alloc_func(), replace it with
-  rb_objc_define_method(*(VALUE *)klass, "alloc", ..., 0)

Deleted: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/array.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,3814 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's array.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/util.h"
-#include "ruby/st.h"
-#include "id.h"
-#include "objc.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "class.h"
-#include "array.h"
-
-VALUE rb_cRubyArray;
-
-#define ARY_DEFAULT_SIZE 16
-
-// RubyArray primitives.
-
-void
-rary_reserve(VALUE ary, size_t newlen)
-{
-    rb_ary_t *rary = RARY(ary); 
-    if (rary->beg + newlen > rary->cap) {
-	if (rary->beg > 0) {
-	    if (rary->beg > newlen) {
-		newlen = 0;
-	    }
-	    else {
-		newlen -= rary->beg;
-	    }
-	    for (size_t i = 0; i < rary->len; i++) {
-		GC_WB(&rary->elements[i], rary->elements[rary->beg + i]);
-	    }
-	    rary->beg = 0;
-	}
-	if (newlen > rary->cap) {
-	    if (rary->cap > 0) {
-		newlen *= 2;
-	    }
-	    if (rary->elements == NULL) {
-		GC_WB(&rary->elements, xmalloc_ptrs(sizeof(VALUE) * newlen));
-	    }
-	    else {
-		VALUE *new_elements = xrealloc(rary->elements,
-			sizeof(VALUE) * newlen);
-		if (new_elements != rary->elements) {
-		    GC_WB(&rary->elements, new_elements);
-		}
-	    }
-	    rary->cap = newlen;
-	}
-    }
-}
-
-static VALUE
-rary_erase(VALUE ary, size_t idx, size_t len)
-{
-    assert(idx + len <= RARY(ary)->len);
-    VALUE item = rary_elt(ary, idx);
-    if (idx == 0) {
-	for (size_t i = 0; i < len; i++) {
-	    rary_elt_set(ary, i, Qnil);
-	}
-	if (len < RARY(ary)->len) {
-	    RARY(ary)->beg += len;
-	}
-	else {
-	    RARY(ary)->beg = 0;
-	}
-    }
-    else {
-	for (size_t i = idx; i < RARY(ary)->len - len; i++) {
-	    rary_elt_set(ary, i, rary_elt(ary, i + len));
-	}
-	for (size_t i = 0; i < len; i++) {
-	    rary_elt_set(ary, RARY(ary)->len - i - 1, Qnil);
-	}
-    }
-    RARY(ary)->len -= len;
-    return item;
-}
-
-static void
-rary_resize(VALUE ary, size_t newlen)
-{
-    if (newlen > RARY(ary)->cap) {
-	rary_reserve(ary, newlen);
-    }
-    for (size_t i = RARY(ary)->len; i < newlen; i++) {
-	rary_elt_set(ary, i, Qnil);
-    }
-    RARY(ary)->len = newlen;
-}
-
-static void
-rary_concat(VALUE ary, VALUE other, size_t beg, size_t len)
-{
-    rary_reserve(ary, RARY(ary)->len + len);
-    if (IS_RARY(other)) {
-	for (size_t i = 0; i < len; i++) {
-	    rary_elt_set(ary, i + RARY(ary)->len,
-		    rary_elt(other, beg + i));
-	}
-    }
-    else {
-	for (size_t i = 0; i < len; i++) {
-	    rary_elt_set(ary, i + RARY(ary)->len,
-		    rb_ary_elt(other, beg + i));
-	}
-    }
-    RARY(ary)->len += len;
-}
-
-static void
-rary_remove_all(rb_ary_t *ary)
-{
-    memset(ary->elements, 0, sizeof(VALUE) * ary->len);
-    ary->len = 0;
-}
-
-static VALUE
-rb_equal_fast(VALUE x, VALUE y)
-{
-    if (x == y) {
-	return Qtrue;
-    }
-    if (SYMBOL_P(x)) {
-	return x == y ? Qtrue : Qfalse;
-    }
-    return rb_equal(x, y);
-}
-
-void
-rb_mem_clear(register VALUE *mem, register long size)
-{
-    while (size--) {
-	*mem++ = Qnil;
-    }
-}
-
-static inline VALUE
-rary_alloc(VALUE klass, SEL sel)
-{
-    assert(klass != 0);
-    assert(rb_klass_is_rary(klass));
-
-    NEWOBJ(ary, rb_ary_t);
-    ary->basic.flags = 0;
-    ary->basic.klass = klass;
-    ary->beg = ary->len = ary->cap = 0;
-    ary->elements = NULL;
-    return (VALUE)ary;
-}
-
-static inline void
-assert_ary_len(const long len)
-{
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative array size (or size too big)");
-    }
-    if ((unsigned long)len > ARY_MAX_SIZE) {
-	rb_raise(rb_eArgError, "array size too big");
-    }
-}
-
-VALUE
-rb_ary_new2(long len)
-{
-    assert_ary_len(len);
-
-    VALUE ary;
-    if (rb_cRubyArray != 0) {
-	ary = rary_alloc(rb_cRubyArray, 0);
-	rary_reserve(ary, len);
-    }
-    else {
-	// RubyArray does not exist yet... fallback on an CFArray.
-	ary = (VALUE)CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-	CFMakeCollectable((void *)ary);
-    }
-    return ary;
-}
-
-VALUE
-rb_ary_new(void)
-{
-    return rb_ary_new2(ARY_DEFAULT_SIZE);
-}
-
-VALUE
-rb_ary_new3(long n, ...)
-{
-    VALUE ary = rb_ary_new2(n);
-
-    if (n > 0) {
-	va_list ar;
-	va_start(ar, n);
-	rary_reserve(ary, n);
-	for (long i = 0; i < n; i++) {
-	    rary_push(ary, va_arg(ar, VALUE));
-	}
-	va_end(ar);
-    }
-
-    return ary;
-}
-
-VALUE
-rb_ary_new4(long n, const VALUE *elts)
-{
-    VALUE ary = rb_ary_new2(n);
-    if (n > 0 && elts != NULL) {
-	for (long i = 0; i < n; i++) {
-	    rary_push(ary, elts[i]);
-	}
-    }
-    return ary;
-}
-
-VALUE
-rb_assoc_new(VALUE car, VALUE cdr)
-{
-    VALUE elems[] = { car, cdr };
-    return rb_ary_new4(2, elems);
-}
-
-VALUE
-rb_check_array_type(VALUE ary)
-{
-    return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
-}
-
-/*
- *  call-seq:
- *     Array.try_convert(obj) -> array or nil
- *
- *  Try to convert <i>obj</i> into an array, using to_ary method.
- *  Returns converted array or nil if <i>obj</i> cannot be converted
- *  for any reason.  This method is to check if an argument is an
- *  array.  
- *
- *     Array.try_convert([1])   # => [1]
- *     Array.try_convert("1")   # => nil
- *     
- *     if tmp = Array.try_convert(arg)
- *       # the argument is an array
- *     elsif tmp = String.try_convert(arg)
- *       # the argument is a string
- *     end
- *
- */
-
-static VALUE
-rary_s_try_convert(VALUE dummy, SEL sel, VALUE ary)
-{
-    return rb_check_array_type(ary);
-}
-
-/*
- *  call-seq:
- *     Array.new(size=0, obj=nil)
- *     Array.new(array)
- *     Array.new(size) {|index| block }
- *
- *  Returns a new array. In the first form, the new array is
- *  empty. In the second it is created with _size_ copies of _obj_
- *  (that is, _size_ references to the same
- *  _obj_). The third form creates a copy of the array
- *  passed as a parameter (the array is generated by calling
- *  to_ary  on the parameter). In the last form, an array
- *  of the given size is created. Each element in this array is
- *  calculated by passing the element's index to the given block and
- *  storing the return value.
- *
- *     Array.new
- *     Array.new(2)
- *     Array.new(5, "A")
- * 
- *     # only one copy of the object is created
- *     a = Array.new(2, Hash.new)
- *     a[0]['cat'] = 'feline'
- *     a
- *     a[1]['cat'] = 'Felix'
- *     a
- * 
- *     # here multiple copies are created
- *     a = Array.new(2) { Hash.new }
- *     a[0]['cat'] = 'feline'
- *     a
- * 
- *     squares = Array.new(5) {|i| i*i}
- *     squares
- * 
- *     copy = Array.new(squares)
- */
-
-static VALUE rary_replace(VALUE rcv, SEL sel, VALUE other);
-
-static VALUE
-rary_initialize(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    rary_modify(ary);
-
-    if (argc ==  0) {
-	if (rb_block_given_p()) {
-	    rb_warning("given block not used");
-	}
-	rary_remove_all(RARY(ary));
-	return ary;
-    }
-
-    VALUE size, val;
-    rb_scan_args(argc, argv, "02", &size, &val);
-    if (argc == 1 && !FIXNUM_P(size)) {
-	val = rb_check_array_type(size);
-	if (!NIL_P(val)) {
-	    rary_replace(ary, 0, val);
-	    return ary;
-	}
-    }
-
-    const long len = NUM2LONG(size);
-    assert_ary_len(len);
-    if (rb_block_given_p()) {
-	if (argc == 2) {
-	    rb_warn("block supersedes default value argument");
-	}
-	rary_remove_all(RARY(ary));
-	for (long i = 0; i < len; i++) {
-	    VALUE v = rb_yield(LONG2NUM(i));
-	    RETURN_IF_BROKEN();
-	    rary_push(ary, v);
-	}
-    }
-    else {
-	rary_resize(ary, len);
-	for (long i = 0; i < len; i++) {
-	    rary_store(ary, i, val);
-	}
-    }
-    return ary;
-}
-
-/* 
-* Returns a new array populated with the given objects. 
-*
-*   Array.[]( 1, 'a', /^A/ )
-*   Array[ 1, 'a', /^A/ ]
-*   [ 1, 'a', /^A/ ]
-*/
-
-static VALUE
-rary_s_create(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE ary = rary_alloc(klass, 0);
-    if (argc < 0) {
-	rb_raise(rb_eArgError, "negative array size");
-    }
-    rary_reserve(ary, argc);
-    for (int i = 0; i < argc; i++) {
-	rary_push(ary, argv[i]);
-    }
-    return ary;
-}
-
-void
-rary_insert(VALUE ary, long idx, VALUE val)
-{
-    if (idx < 0) {
-	idx += RARY(ary)->len;
-	if (idx < 0) {
-	    rb_raise(rb_eIndexError, "index %ld out of array",
-		    idx - RARY(ary)->len);
-	}
-    }
-    if (idx > RARY(ary)->len) {
-	rary_resize(ary, idx + 1);
-	rary_store(ary, idx, val);
-    }
-    else if (idx < RARY(ary)->len) {
-	rary_reserve(ary, RARY(ary)->len + 1);
-	for (size_t i = RARY(ary)->len; i > idx; i--) {
-	    rary_elt_set(ary, i, rary_elt(ary, i - 1));
-	}
-	rary_elt_set(ary, idx, val);
-	RARY(ary)->len++;
-    }
-    else {
-	rary_push(ary, val);
-    }
-}
-
-static VALUE
-ary_shared_first(int argc, VALUE *argv, VALUE ary, bool last, bool remove)
-{
-    VALUE nv;
-    rb_scan_args(argc, argv, "1", &nv);
-    long n = NUM2LONG(nv);
-
-    const long ary_len = RARY(ary)->len;
-    if (n > ary_len) {
-	n = ary_len;
-    }
-    else if (n < 0) {
-	rb_raise(rb_eArgError, "negative array size");
-    }
-
-    long offset = 0;
-    if (last) {
-	offset = ary_len - n;
-    }
-
-    VALUE result = rb_ary_new();
-    for (long i = 0; i < n; i++) {
-	VALUE item = rary_elt(ary, i + offset);
-	rary_push(result, item);
-    }
-    if (remove) {
-	for (long i = 0; i < n; i++) {
-	    rary_erase(ary, offset, 1);
-	}
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     array << obj            -> array
- *  
- *  Append---Pushes the given object on to the end of this array. This
- *  expression returns the array itself, so several appends
- *  may be chained together.
- *
- *     [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
- *             #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
- *
- */
-
-VALUE
-rary_push_m(VALUE ary, SEL sel, VALUE item)
-{
-    rary_modify(ary);
-    rary_push(ary, item);
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array.push(obj, ... )   -> array
- *  
- *  Append---Pushes the given object(s) on to the end of this array. This
- *  expression returns the array itself, so several appends
- *  may be chained together.
- *
- *     a = [ "a", "b", "c" ]
- *     a.push("d", "e", "f")  
- *             #=> ["a", "b", "c", "d", "e", "f"]
- */
-
-static VALUE
-rary_push_m2(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    rary_modify(ary);
-    while (argc-- > 0) {
-	rary_push(ary, *argv++);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.pop    -> obj or nil
- *     array.pop(n) -> array
- *  
- *  Removes the last element from <i>self</i> and returns it, or
- *  <code>nil</code> if the array is empty.
- *     
- *  If a number _n_ is given, returns an array of the last n elements
- *  (or less) just like <code>array.slice!(-n, n)</code> does.
- *     
- *     a = [ "a", "b", "c", "d" ]
- *     a.pop     #=> "d"
- *     a.pop(2)  #=> ["b", "c"]
- *     a         #=> ["a"]
- */
-
-VALUE
-rary_pop(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    rary_modify(ary);
-    if (argc == 0) {
-	const long n = RARY(ary)->len;
-	if (n == 0) {
-	    return Qnil;
-	}
-	return rary_erase(ary, n - 1, 1);
-    }
-    return ary_shared_first(argc, argv, ary, true, true);
-}
-
-/*
- *  call-seq:
- *     array.shift    -> obj or nil
- *     array.shift(n) -> array
- *  
- *  Returns the first element of <i>self</i> and removes it (shifting all
- *  other elements down by one). Returns <code>nil</code> if the array
- *  is empty.
- *     
- *  If a number _n_ is given, returns an array of the first n elements
- *  (or less) just like <code>array.slice!(0, n)</code> does.
- *     
- *     args = [ "-m", "-q", "filename" ]
- *     args.shift     #=> "-m"
- *     args           #=> ["-q", "filename"]
- *
- *     args = [ "-m", "-q", "filename" ]
- *     args.shift(2)  #=> ["-m", "-q"]
- *     args           #=> ["filename"]
- */
-
-VALUE
-rary_shift(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    rary_modify(ary);
-    if (argc == 0) {
-	if (RARY(ary)->len == 0) {
-	    return Qnil;
-	}
-	return rary_erase(ary, 0, 1);
-    }
-    return ary_shared_first(argc, argv, ary, false, true);
-}
-
-/*
- *  call-seq:
- *     array.unshift(obj, ...)  -> array
- *  
- *  Prepends objects to the front of <i>array</i>.
- *  other elements up one.
- *     
- *     a = [ "b", "c", "d" ]
- *     a.unshift("a")   #=> ["a", "b", "c", "d"]
- *     a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
- */
-
-VALUE
-rary_unshift(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    rary_modify(ary);
-    for (int i = argc - 1; i >= 0; i--) {
-	rary_insert(ary, 0, argv[i]);
-    }
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array[index]                -> obj      or nil
- *     array[start, length]        -> an_array or nil
- *     array[range]                -> an_array or nil
- *     array.slice(index)          -> obj      or nil
- *     array.slice(start, length)  -> an_array or nil
- *     array.slice(range)          -> an_array or nil
- *
- *  Element Reference---Returns the element at _index_,
- *  or returns a subarray starting at _start_ and
- *  continuing for _length_ elements, or returns a subarray
- *  specified by _range_.
- *  Negative indices count backward from the end of the
- *  array (-1 is the last element). Returns nil if the index
- *  (or starting index) are out of range.
- *
- *     a = [ "a", "b", "c", "d", "e" ]
- *     a[2] +  a[0] + a[1]    #=> "cab"
- *     a[6]                   #=> nil
- *     a[1, 2]                #=> [ "b", "c" ]
- *     a[1..3]                #=> [ "b", "c", "d" ]
- *     a[4..7]                #=> [ "e" ]
- *     a[6..10]               #=> nil
- *     a[-3, 3]               #=> [ "c", "d", "e" ]
- *     # special cases
- *     a[5]                   #=> nil
- *     a[5, 1]                #=> []
- *     a[5..10]               #=> []
- *
- */
-
-VALUE
-rary_subseq(VALUE ary, long beg, long len)
-{
-    if (beg < 0 || len < 0) {
-	return Qnil;
-    }
-    const long n = RARY(ary)->len;
-    if (beg > n) {
-	return Qnil;
-    }
-    if (n < len || n < beg + len) {
-	len = n - beg;
-    }
-    VALUE newary = rary_alloc(rb_obj_class(ary), 0);
-    if (len > 0) {
-	rary_concat(newary, ary, beg, len);
-    }	
-    return newary;
-}
-
-VALUE
-rary_aref(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    long beg, len;
-
-    if (argc == 2) {
-	beg = NUM2LONG(argv[0]);
-	len = NUM2LONG(argv[1]);
-	if (beg < 0) {
-	    beg += RARRAY_LEN(ary);
-	}
-	return rary_subseq(ary, beg, len);
-    }
-    if (argc != 1) {
-	rb_scan_args(argc, argv, "11", 0, 0);
-    }
-    VALUE arg = argv[0];
-    /* special case - speeding up */
-    if (FIXNUM_P(arg)) {
-	return rary_entry(ary, FIX2LONG(arg));
-    }
-    /* check if idx is Range */
-    switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
-	case Qfalse:
-	    break;
-	case Qnil:
-	    return Qnil;
-	default:
-	    return rary_subseq(ary, beg, len);
-    }
-    return rary_entry(ary, NUM2LONG(arg));
-}
-
-/* 
- *  call-seq:
- *     array.at(index)   ->   obj  or nil
- *
- *  Returns the element at _index_. A
- *  negative index counts from the end of _self_.  Returns +nil+
- *  if the index is out of range. See also <code>Array#[]</code>.
- *
- *     a = [ "a", "b", "c", "d", "e" ]
- *     a.at(0)     #=> "a"
- *     a.at(-1)    #=> "e"
- */
-
-static VALUE
-rary_at(VALUE ary, SEL sel, VALUE pos)
-{
-    return rary_entry(ary, NUM2LONG(pos));
-}
-
-/*
- *  call-seq:
- *     array.first     ->   obj or nil
- *     array.first(n)  ->   an_array
- *  
- *  Returns the first element, or the first +n+ elements, of the array.
- *  If the array is empty, the first form returns <code>nil</code>, and the
- *  second form returns an empty array.
- *     
- *     a = [ "q", "r", "s", "t" ]
- *     a.first     #=> "q"
- *     a.first(2)  #=> ["q", "r"]
- */
-
-static VALUE
-rary_first(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	if (RARY(ary)->len == 0) {
-	    return Qnil;
-	}
-	return rary_elt(ary, 0);
-    }
-    return ary_shared_first(argc, argv, ary, false, false);
-}
-
-/*
- *  call-seq:
- *     array.last     ->  obj or nil
- *     array.last(n)  ->  an_array
- *  
- *  Returns the last element(s) of <i>self</i>. If the array is empty,
- *  the first form returns <code>nil</code>.
- *     
- *     a = [ "w", "x", "y", "z" ]
- *     a.last     #=> "z"
- *     a.last(2)  #=> ["y", "z"]
- */
-
-VALUE
-rary_last(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	const long n = RARY(ary)->len;
-	if (n == 0) {
-	    return Qnil;
-	}
-	return rary_elt(ary, n - 1);
-    }
-    return ary_shared_first(argc, argv, ary, true, false);
-}
-
-/*
- *  call-seq:
- *     array.fetch(index)                    -> obj
- *     array.fetch(index, default )          -> obj
- *     array.fetch(index) {|index| block }   -> obj
- *  
- *  Tries to return the element at position <i>index</i>. If the index
- *  lies outside the array, the first form throws an
- *  <code>IndexError</code> exception, the second form returns
- *  <i>default</i>, and the third form returns the value of invoking
- *  the block, passing in the index. Negative values of <i>index</i>
- *  count from the end of the array.
- *     
- *     a = [ 11, 22, 33, 44 ]
- *     a.fetch(1)               #=> 22
- *     a.fetch(-1)              #=> 44
- *     a.fetch(4, 'cat')        #=> "cat"
- *     a.fetch(4) { |i| i*i }   #=> 16
- */
-
-static VALUE
-rary_fetch(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE pos, ifnone;
-
-    rb_scan_args(argc, argv, "11", &pos, &ifnone);
-    const bool block_given = rb_block_given_p();
-    if (block_given && argc == 2) {
-	rb_warn("block supersedes default value argument");
-    }
-
-    long idx = NUM2LONG(pos);
-    if (idx < 0) {
-	idx += RARY(ary)->len;
-    }
-    if (idx < 0 || RARY(ary)->len <= idx) {
-	if (block_given) {
-	    return rb_yield(pos);
-	}
-	if (argc == 1) {
-	    rb_raise(rb_eIndexError, "index %ld out of array", idx);
-	}
-	return ifnone;
-    }
-    return rary_elt(ary, idx);
-}
-
-/*
- *  call-seq:
- *     array.index(obj)           ->  int or nil
- *     array.index {|item| block} ->  int or nil
- *  
- *  Returns the index of the first object in <i>self</i> such that is
- *  <code>==</code> to <i>obj</i>. If a block is given instead of an
- *  argument, returns first object for which <em>block</em> is true.
- *  Returns <code>nil</code> if no match is found.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.index("b")        #=> 1
- *     a.index("z")        #=> nil
- *     a.index{|x|x=="b"}  #=> 1
- *
- *  This is an alias of <code>#find_index</code>.
- */
-
-#define NOT_FOUND LONG_MAX
-
-static size_t
-rary_index_of_item(VALUE ary, size_t origin, VALUE item)
-{
-    assert(RARY(ary)->len == 0 || origin < RARY(ary)->len);
-    for (size_t i = origin; i < RARY(ary)->len; i++) {
-	VALUE item2 = rary_elt(ary, i);
-	if (rb_equal_fast(item2, item) == Qtrue) {
-	    return i;
-	}
-    }
-    return NOT_FOUND;
-}
-
-static VALUE
-rary_index(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE val;
-    if (rb_scan_args(argc, argv, "01", &val) == 0) {
-	RETURN_ENUMERATOR(ary, 0, 0);
-	for (long i = 0; i < RARY(ary)->len; i++) {
-	    VALUE elem = rary_elt(ary, i);
-	    VALUE test = rb_yield(elem);
-	    RETURN_IF_BROKEN();
-	    if (RTEST(test)) {
-		return LONG2NUM(i);
-	    }
-	}
-    }
-    else if (RARY(ary)->len > 0) {
-	size_t pos = rary_index_of_item(ary, 0, val);
-	if (pos != NOT_FOUND) {
-	    return LONG2NUM(pos);
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     array.rindex(obj)    ->  int or nil
- *  
- *  Returns the index of the last object in <i>array</i>
- *  <code>==</code> to <i>obj</i>. If a block is given instead of an
- *  argument, returns first object for which <em>block</em> is
- *  true. Returns <code>nil</code> if no match is found.
- *     
- *     a = [ "a", "b", "b", "b", "c" ]
- *     a.rindex("b")        #=> 3
- *     a.rindex("z")        #=> nil
- *     a.rindex{|x|x=="b"}  #=> 3
- */
-
-static size_t
-rary_rindex_of_item(VALUE ary, long origin, VALUE item)
-{
-    assert(RARY(ary)->len == 0 || origin < RARY(ary)->len);
-    for (long i = origin; i >= 0; i--) {
-	VALUE item2 = rary_elt(ary, i);
-	if (rb_equal_fast(item, item2) == Qtrue) {
-	    return i;
-	}
-    }
-    return NOT_FOUND;
-}
-
-static VALUE
-rary_rindex(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	RETURN_ENUMERATOR(ary, 0, 0);
-	long i = RARY(ary)->len;
-	while (i-- > 0) {
-	    VALUE elem = rary_elt(ary, i);
-	    VALUE test = rb_yield(elem);
-	    RETURN_IF_BROKEN();
-	    if (RTEST(test)) {
-		return LONG2NUM(i);
-	    }
-	    if (i > RARY(ary)->len) {
-		i = RARY(ary)->len;
-	    }
-	}
-    }
-    else {
-	VALUE val;
- 	rb_scan_args(argc, argv, "01", &val);
-
-	if (RARY(ary)->len > 0) {
-	    size_t pos = rary_rindex_of_item(ary, RARY(ary)->len - 1, val);
-	    if (pos != NOT_FOUND) {
-		return LONG2NUM(pos);
-	    }
-	}
-    }
-    return Qnil;
-}
-
-VALUE
-rb_ary_to_ary(VALUE obj)
-{
-    if (TYPE(obj) == T_ARRAY) {
-	return obj;
-    }
-    if (rb_respond_to(obj, rb_intern("to_ary"))) {
-	return to_ary(obj);
-    }
-    return rb_ary_new4(1, &obj);
-}
-
-static void
-rary_splice(VALUE ary, long beg, long len, VALUE rpl)
-{
-    const long n = RARRAY_LEN(ary);
-    if (len < 0) {
-	rb_raise(rb_eIndexError, "negative length (%ld)", len);
-    }
-    if (beg < 0) {
-	beg += n;
-	if (beg < 0) {
-	    beg -= n;
-	    rb_raise(rb_eIndexError, "index %ld out of array", beg);
-	}
-    }
-    if (n < len || n < beg + len) {
-	len = n - beg;
-    }
-
-    long rlen;
-    if (rpl == Qundef) {
-	rlen = 0;
-    }
-    else {
-	rpl = rb_ary_to_ary(rpl);
-	rlen = RARRAY_LEN(rpl);
-    }
-
-    rary_modify(ary);
-
-    if (ary == rpl) {
-	rpl = rb_ary_dup(rpl);
-    }
-    if (beg >= n) {
-	if (beg > ARY_MAX_SIZE - rlen) {
-	    rb_raise(rb_eIndexError, "index %ld too big", beg);
-	}
-	for (long i = n; i < beg; i++) {
-	    rary_push(ary, Qnil);
-	}
-	if (rlen > 0) {
-	    rary_concat(ary, rpl, 0, rlen);
-	}
-    }
-    else if (len == rlen) {
-	for (long i = 0; i < len; i++) {
-	    rary_elt_set(ary, beg + i, rb_ary_elt(rpl, i));
-	}	
-    }
-    else {
-	rary_erase(ary, beg, len);
-	for (long i = 0; i < rlen; i++) {
-	    rary_insert(ary, beg + i, rb_ary_elt(rpl, i));
-	}
-    }
-}
-
-/* 
- *  call-seq:
- *     array[index]         = obj                     ->  obj
- *     array[start, length] = obj or an_array or nil  ->  obj or an_array or nil
- *     array[range]         = obj or an_array or nil  ->  obj or an_array or nil
- *
- *  Element Assignment---Sets the element at _index_,
- *  or replaces a subarray starting at _start_ and
- *  continuing for _length_ elements, or replaces a subarray
- *  specified by _range_.  If indices are greater than
- *  the current capacity of the array, the array grows
- *  automatically. A negative indices will count backward
- *  from the end of the array. Inserts elements if _length_ is
- *  zero. An +IndexError+ is raised if a negative index points
- *  past the beginning of the array. See also
- *  <code>Array#push</code>, and <code>Array#unshift</code>.
- * 
- *     a = Array.new
- *     a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
- *     a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
- *     a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
- *     a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
- *     a[0..2] = "A"               #=> ["A", "4"]
- *     a[-1]   = "Z"               #=> ["A", "Z"]
- *     a[1..-1] = nil              #=> ["A", nil]
- *     a[1..-1] = []               #=> ["A"]
- */
-
-static VALUE
-rary_aset(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    long offset, beg, len;
-
-    if (argc == 3) {
-	rary_modify(ary);
-	rary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
-	return argv[2];
-    }
-    if (argc != 2) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-    rary_modify(ary);
-    if (FIXNUM_P(argv[0])) {
-	offset = FIX2LONG(argv[0]);
-    }
-    else {
-	if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
-	    // Check if Range.
-	    rary_splice(ary, beg, len, argv[1]);
-	    return argv[1];
-	}
-	offset = NUM2LONG(argv[0]);
-    }
-    rary_store(ary, offset, argv[1]);
-    return argv[1];
-}
-
-/*
- *  call-seq:
- *     array.insert(index, obj...)  -> array
- *  
- *  Inserts the given values before the element with the given index
- *  (which may be negative).
- *     
- *     a = %w{ a b c d }
- *     a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
- *     a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
- */
-
-static VALUE
-rary_insert_m(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
-    }
-    rary_modify(ary);
-    if (argc == 1) {
-	return ary;
-    }
-    long pos = NUM2LONG(argv[0]);
-    if (pos == -1) {
-	pos = RARRAY_LEN(ary);
-    }
-    if (pos < 0) {
-	pos++;
-    }
-    if (argc == 2) {
-	rary_insert(ary, pos, argv[1]);
-    }
-    else {
-	rary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.each {|item| block }   ->   array
- *  
- *  Calls <i>block</i> once for each element in <i>self</i>, passing that
- *  element as a parameter.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.each {|x| print x, " -- " }
- *     
- *  produces:
- *     
- *     a -- b -- c --
- */
-
-VALUE
-rary_each(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    for (long i = 0; i < RARY(ary)->len; i++) {
-	VALUE elem = rary_elt(ary, i);
-	rb_yield(elem);
-	RETURN_IF_BROKEN();
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.each_index {|index| block }  ->  array
- *  
- *  Same as <code>Array#each</code>, but passes the index of the element
- *  instead of the element itself.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.each_index {|x| print x, " -- " }
- *     
- *  produces:
- *     
- *     0 -- 1 -- 2 --
- */
-
-static VALUE
-rary_each_index(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    for (long i = 0; i < RARY(ary)->len; i++) {
-	rb_yield(LONG2NUM(i));
-	RETURN_IF_BROKEN();
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.reverse_each {|item| block } 
- *  
- *  Same as <code>Array#each</code>, but traverses <i>self</i> in reverse
- *  order.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.reverse_each {|x| print x, " " }
- *     
- *  produces:
- *     
- *     c b a
- */
-
-static VALUE
-rary_reverse_each(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    long len = RARY(ary)->len;
-    while (len-- > 0) {
-	VALUE elem = rary_elt(ary, len);
-	rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (len > RARY(ary)->len) {
-	    len = RARY(ary)->len;
-	}
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.length -> int
- *  
- *  Returns the number of elements in <i>self</i>. May be zero.
- *     
- *     [ 1, 2, 3, 4, 5 ].length   #=> 5
- */
-
-static VALUE
-rary_length(VALUE ary, SEL sel)
-{
-    return LONG2NUM(RARY(ary)->len);
-}
-
-/*
- *  call-seq:
- *     array.empty?   -> true or false
- *  
- *  Returns <code>true</code> if <i>self</i> array contains no elements.
- *     
- *     [].empty?   #=> true
- */
-
-static VALUE
-rary_empty(VALUE ary, SEL sel)
-{
-    return RARY(ary)->len == 0 ? Qtrue : Qfalse;
-}
-
-static VALUE
-rary_copy(VALUE rcv, VALUE klass)
-{
-    VALUE dup = rary_alloc(klass, 0);
-    rary_concat(dup, rcv, 0, RARY(rcv)->len);
-    return dup;
-}
-
-VALUE
-rary_dup(VALUE ary, SEL sel)
-{
-    VALUE klass = CLASS_OF(ary);
-    while (RCLASS_SINGLETON(klass)) {
-	klass = RCLASS_SUPER(klass);
-    }
-    assert(rb_klass_is_rary(klass));
-
-    VALUE dup = rary_copy(ary, klass);
-
-    if (OBJ_TAINTED(ary)) {
-	OBJ_TAINT(dup);
-    }
-    if (OBJ_UNTRUSTED(ary)) {
-	OBJ_UNTRUST(dup);
-    }
-    return dup;
-}
-
-static VALUE
-rary_clone(VALUE ary, SEL sel)
-{
-    VALUE clone = rary_copy(ary, CLASS_OF(ary));
-
-    if (OBJ_TAINTED(ary)) {
-	OBJ_TAINT(clone);
-    }
-    if (OBJ_UNTRUSTED(ary)) {
-	OBJ_UNTRUST(clone);
-    }
-    if (OBJ_FROZEN(ary)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-/*
- *  call-seq:
- *     array.join(sep=$,)    -> str
- *  
- *  Returns a string created by converting each element of the array to
- *  a string, separated by <i>sep</i>.
- *     
- *     [ "a", "b", "c" ].join        #=> "abc"
- *     [ "a", "b", "c" ].join("-")   #=> "a-b-c"
- */
-
-// Defined on NSArray.
-VALUE
-rary_join(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE sep;
-    rb_scan_args(argc, argv, "01", &sep);
-    if (NIL_P(sep)) {
-	sep = rb_output_fs;
-    }
-    return rb_ary_join(ary, sep);
-}
-
-/*
- *  call-seq:
- *     array.to_s -> string
- *     array.inspect  -> string
- *
- *  Create a printable version of <i>array</i>.
- */
-
-static VALUE
-inspect_ary(VALUE ary, VALUE dummy, int recur)
-{
-    if (recur) {
-	return rb_tainted_str_new2("[...]");
-    }
-
-    bool tainted = OBJ_TAINTED(ary);
-    bool untrusted = OBJ_UNTRUSTED(ary);
-    VALUE str = rb_str_buf_new2("[");
-    for (long i = 0; i < RARRAY_LEN(ary); i++) {
-	VALUE s = rb_inspect(RARRAY_AT(ary, i));
-	if (OBJ_TAINTED(s)) {
-	    tainted = true;
-	}
-	if (OBJ_UNTRUSTED(s)) {
-	    untrusted = true;
-	}
-	if (i > 0) {
-	    rb_str_buf_cat2(str, ", ");
-	}
-	rb_str_buf_append(str, s);
-    }
-    rb_str_buf_cat2(str, "]");
-
-    if (tainted) {
-	OBJ_TAINT(str);
-    }
-    if (untrusted) {
-	OBJ_UNTRUST(str);
-    }
-    return str;
-}
-
-static VALUE
-rary_inspect(VALUE ary, SEL sel)
-{
-    if (RARRAY_LEN(ary) == 0) {
-	return rb_usascii_str_new2("[]");
-    }
-    return rb_exec_recursive(inspect_ary, ary, 0);
-}
-
-/*
- *  call-seq:
- *     array.reverse!   -> array 
- *  
- *  Reverses _self_ in place.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.reverse!       #=> ["c", "b", "a"]
- *     a                #=> ["c", "b", "a"]
- */
-
-VALUE
-rary_reverse_bang(VALUE ary, SEL sel)
-{
-    rary_modify(ary);
-    if (RARY(ary)->len > 1) {
-	for (size_t i = 0; i < RARY(ary)->len / 2; i++) {
-	    const size_t j = RARY(ary)->len - i - 1;
-	    VALUE elem = rary_elt(ary, i);
-	    rary_elt_set(ary, i, rary_elt(ary, j));
-	    rary_elt_set(ary, j, elem);
-	}
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.reverse -> an_array
- *  
- *  Returns a new array containing <i>self</i>'s elements in reverse order.
- *     
- *     [ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
- *     [ 1 ].reverse               #=> [1]
- */
-
-static VALUE
-rary_reverse(VALUE ary, SEL sel)
-{
-    VALUE dup = rary_dup(ary, 0);
-
-    if (RARY(dup)->len > 1) {
-	for (size_t i = 0; i < RARY(dup)->len / 2; i++) {
-	    const size_t j = RARY(dup)->len - i - 1;
-	    VALUE elem = rary_elt(dup, i);
-	    rary_elt_set(dup, i, rary_elt(dup, j));
-	    rary_elt_set(dup, j, elem);
-	}
-    }
-    return dup;
-}
-
-static inline long
-rotate_count(long cnt, long len)
-{
-    return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
-}
-
-static void
-ary_reverse(VALUE ary, long pos1, long pos2)
-{
-    while (pos1 < pos2) {
-	VALUE elem = rary_elt(ary, pos1);
-	rary_elt_set(ary, pos1, rary_elt(ary, pos2));
-	rary_elt_set(ary, pos2, elem);
-	pos1++;
-	pos2--;
-    }
-}
-
-VALUE
-ary_rotate(VALUE ary, long cnt)
-{
-    if (cnt != 0) {
-	long len = RARY(ary)->len;
-	if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
-	    --len;
-	    if (cnt < len) {
-		ary_reverse(ary, cnt, len);
-	    }
-	    if (--cnt > 0) {
-		ary_reverse(ary, 0, cnt);
-	    }
-	    if (len > 0) {
-		ary_reverse(ary, 0, len);
-	    }
-	    return ary;
-	}
-    }
-
-    return Qnil;
-}
-    
-/*
- *  call-seq:
- *     array.rotate!([cnt = 1]) -> array
- *
- *  Rotates _self_ in place so that the element at +cnt+ comes first,
- *  and returns _self_.  If +cnt+ is negative then it rotates in
- *  counter direction.
- *
- *     a = [ "a", "b", "c", "d" ]
- *     a.rotate!        #=> ["b", "c", "d", "a"]
- *     a                #=> ["b", "c", "d", "a"]
- *     a.rotate!(2)     #=> ["d", "a", "b", "c"]
- *     a.rotate!(-3)    #=> ["a", "b", "c", "d"]
- */
-
-static VALUE
-rary_rotate_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE n;
-    long cnt = 1;
-
-    rb_scan_args(argc, argv, "01", &n);
-    if (!NIL_P(n)) {
-	cnt = NUM2LONG(n);
-    }
-    rb_ary_modify(ary);
-    ary_rotate(ary, cnt);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.rotate([n = 1]) -> an_array
- *
- *  Returns new array by rotating _self_, whose first element is the
- *  element at +cnt+ in _self_.  If +cnt+ is negative then it rotates
- *  in counter direction.
- *
- *     a = [ "a", "b", "c", "d" ]
- *     a.rotate         #=> ["b", "c", "d", "a"]
- *     a                #=> ["a", "b", "c", "d"]
- *     a.rotate(2)      #=> ["c", "d", "a", "b"]
- *     a.rotate(-3)     #=> ["b", "c", "d", "a"]
- */
-
-static VALUE
-rary_rotate(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rotated;
-    VALUE n;
-    long cnt = 1;
-
-    rb_scan_args(argc, argv, "01", &n);
-    if (!NIL_P(n)) {
-	cnt = NUM2LONG(n);
-    }
-
-    rotated = rary_dup(ary, 0);
-    if (RARY(ary)->len > 0) {
-	ary_rotate(rotated, cnt);
-    }
-    return rotated;
-}
-
-static int
-sort_1(void *dummy, const void *ap, const void *bp)
-{
-    if (*(VALUE *)dummy == 0) {
-	VALUE a = *(VALUE *)ap;
-	VALUE b = *(VALUE *)bp;
-	VALUE retval = rb_yield_values(2, a, b);
-
-	VALUE v = rb_vm_pop_broken_value();
-	if (v != Qundef) {
-	    // break was performed, we marked the dummy variable with its
-	    // value and we will make sure further calls are ignored.
-	    *(VALUE *)dummy = v;
-	    return 0;
-	}
-	return rb_cmpint(retval, a, b);
-    }
-    else {
-	return 0;
-    }
-}
-
-static int
-sort_2(void *dummy, const void *ap, const void *bp)
-{
-    VALUE a = *(VALUE *)ap;
-    VALUE b = *(VALUE *)bp;
-
-    if (FIXNUM_P(a) && FIXNUM_P(b)) {
-	if ((long)a > (long)b) {
-	    return 1;
-	}
-	if ((long)a < (long)b) {
-	    return -1;
-	}
-	return 0;
-    }
-    else if (FIXFLOAT_P(a) && FIXFLOAT_P(b)) {
-	const double fa = FIXFLOAT2DBL(a);
-	const double fb = FIXFLOAT2DBL(b);
-	if (fa > fb) {
-	    return 1;
-	}
-	if (fa < fb) {
-	    return -1;
-	}
-	return 0;
-    }
-
-#if 0 // TODO
-    /* FIXME optimize!!! */
-    if (TYPE(a) == T_STRING) {
-	if (TYPE(b) == T_STRING) {
-	    return rb_str_cmp(a, b);
-	}
-    }
-#endif
-
-    VALUE retval = rb_objs_cmp(a, b);
-    return rb_cmpint(retval, a, b);
-}
-
-/*
- *  call-seq:
- *     array.sort!                   -> array
- *     array.sort! {| a,b | block }  -> array 
- *  
- *  Sorts _self_. Comparisons for
- *  the sort will be done using the <code><=></code> operator or using
- *  an optional code block. The block implements a comparison between
- *  <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
- *  <code>Enumerable#sort_by</code>.
- *     
- *     a = [ "d", "a", "e", "c", "b" ]
- *     a.sort                    #=> ["a", "b", "c", "d", "e"]
- *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
- */
-
-static VALUE
-sort_bang(VALUE ary, bool is_dup)
-{
-    if (RARY(ary)->len > 1) {
-	if (rb_block_given_p()) {
-	    VALUE tmp = is_dup ? ary : rb_ary_dup(ary);
-	    VALUE break_val = 0;
-
-	    qsort_r(rary_ptr(tmp), RARY(ary)->len, sizeof(VALUE), &break_val,
-		    sort_1);
-
-	    if (break_val != 0) {
-		return break_val;
-	    }
-	    if (!is_dup) {
-		rb_ary_replace(ary, tmp);
-	    }
-	}
-	else {
-	    qsort_r(rary_ptr(ary), RARY(ary)->len, sizeof(VALUE), NULL,
-		    sort_2);
-	}
-    }
-    return ary;
-}
-
-VALUE
-rary_sort_bang(VALUE ary, SEL sel)
-{
-    rary_modify(ary);
-    return sort_bang(ary, false);
-}
-
-/*
- *  call-seq:
- *     array.sort                   -> an_array 
- *     array.sort {| a,b | block }  -> an_array 
- *  
- *  Returns a new array created by sorting <i>self</i>. Comparisons for
- *  the sort will be done using the <code><=></code> operator or using
- *  an optional code block. The block implements a comparison between
- *  <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
- *  <code>Enumerable#sort_by</code>.
- *     
- *     a = [ "d", "a", "e", "c", "b" ]
- *     a.sort                    #=> ["a", "b", "c", "d", "e"]
- *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
- */
-
-VALUE
-rary_sort(VALUE ary, SEL sel)
-{
-    ary = rary_dup(ary, 0);
-    return sort_bang(ary, true);
-}
-
-static VALUE
-sort_by_i(VALUE i)
-{
-    return rb_yield(i);
-}
-
-/*
- *  call-seq:
- *     array.sort_by! {| obj | block }    -> array
- *
- *  Sorts <i>array</i> in place using a set of keys generated by mapping the
- *  values in <i>array</i> through the given block.
- */
-
-static VALUE
-rary_sort_by_bang(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_modify(ary);
-    VALUE sorted = rb_objc_block_call(ary, sel_registerName("sort_by"), 0, 0,
-	    sort_by_i, 0);
-    rb_ary_replace(ary, sorted);
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array.collect! {|item| block }   ->   array
- *     array.map!     {|item| block }   ->   array
- *
- *  Invokes the block once for each element of _self_, replacing the
- *  element with the value returned by _block_.
- *  See also <code>Enumerable#collect</code>.
- *   
- *     a = [ "a", "b", "c", "d" ]
- *     a.collect! {|x| x + "!" }
- *     a             #=>  [ "a!", "b!", "c!", "d!" ]
- */
-
-static VALUE
-collect_bang(VALUE source, VALUE dest)
-{
-    for (long i = 0; i < RARY(source)->len; i++) {
-	VALUE elem = rary_elt(source, i);
-	VALUE new_elem = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	rary_store(dest, i, new_elem);
-    }
-    return dest;
-}
-
-static VALUE
-rary_collect_bang(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    rary_modify(ary);
-    return collect_bang(ary, ary);
-}
-
-/*
- *  call-seq:
- *     array.collect {|item| block }  -> an_array
- *     array.map     {|item| block }  -> an_array
- *  
- *  Invokes <i>block</i> once for each element of <i>self</i>. Creates a 
- *  new array containing the values returned by the block.
- *  See also <code>Enumerable#collect</code>.
- *     
- *     a = [ "a", "b", "c", "d" ]
- *     a.collect {|x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
- *     a                          #=> ["a", "b", "c", "d"]
- */
-
-static VALUE
-rary_collect(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    VALUE result = rb_ary_new2(RARY(ary)->len);
-    return collect_bang(ary, result);
-}
-
-/* 
- *  call-seq:
- *     array.values_at(selector,... )  -> an_array
- *
- *  Returns an array containing the elements in
- *  _self_ corresponding to the given selector(s). The selectors
- *  may be either integer indices or ranges. 
- *  See also <code>Array#select</code>.
- * 
- *     a = %w{ a b c d e f }
- *     a.values_at(1, 3, 5)
- *     a.values_at(1, 3, 5, 7)
- *     a.values_at(-1, -3, -5, -7)
- *     a.values_at(1..3, 2...5)
- */
-
-VALUE
-rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, 
-	VALUE (*func) (VALUE, long))
-{
-    VALUE result = rb_ary_new2(argc);
-    for (long i = 0; i < argc; i++) {
-	if (FIXNUM_P(argv[i])) {
-	    rary_push(result, (*func)(obj, FIX2LONG(argv[i])));
-	    continue;
-	}
-	// Check if Range.
-	long beg, len;
-	switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
-	    case Qfalse:
-		break;
-	    case Qnil:
-		continue;
-	    default:
-		for (long j = 0; j < len; j++) {
-		    rary_push(result, (*func)(obj, j+beg));
-		}
-		continue;
-	}
-	rary_push(result, (*func)(obj, NUM2LONG(argv[i])));
-    }
-    return result;
-}
-
-static VALUE
-rary_values_at(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    return rb_get_values_at(ary, RARY(ary)->len, argc, argv, rary_entry);
-}
-
-/*
- *  call-seq:
- *     array.select {|item| block } -> an_array
- *  
- *  Invokes the block passing in successive elements from <i>array</i>,
- *  returning an array containing those elements for which the block
- *  returns a true value (equivalent to <code>Enumerable#select</code>).
- *     
- *     a = %w{ a b c d e f }
- *     a.select {|v| v =~ /[aeiou]/}   #=> ["a", "e"]
- */
-
-static VALUE
-rary_select(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    VALUE result = rb_ary_new2(RARY(ary)->len);
-    for (long i = 0; i < RARY(ary)->len; i++) {
-	VALUE elem = rary_elt(ary, i);
-	VALUE test = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (RTEST(test)) {
-	    rary_push(result, elem);
-	}
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     array.select! {|item| block } -> an_array
- *
- *  Invokes the block passing in successive elements from
- *  <i>array</i>, deleting elements for which the block returns a
- *  false value.  but returns <code>nil</code> if no changes were
- *  made.  Also see <code>Array#keep_if</code>
- */
-
-static VALUE
-rary_select_bang(VALUE ary, SEL sel)
-{
-    long i1, i2;
-
-    RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_modify(ary);
-    for (i1 = i2 = 0; i1 < RARY(ary)->len; i1++) {
-	VALUE v = rary_elt(ary, i1);
-	VALUE test = RTEST(rb_yield(v));
-	RETURN_IF_BROKEN();
-	if (!RTEST(test)) {
-	    continue;
-	}
-	if (i1 != i2) {
-	    rb_ary_store(ary, i2, v);
-	}
-	i2++;
-    }
-
-    if (RARY(ary)->len == i2) {
-	return Qnil;
-    }
-    if (i2 < RARY(ary)->len) {
-	RARY(ary)->len = i2;
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.keep_if {|item| block } -> an_array
- *
- *  Deletes every element of <i>self</i> for which <i>block</i> evaluates
- *  to <code>false</code>.
- *
- *     a = %w{ a b c d e f }
- *     a.keep_if {|v| v =~ /[aeiou]/}   #=> ["a", "e"]
- */
-
-static VALUE
-rary_keep_if(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    rary_select_bang(ary, 0);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.delete(obj)            -> obj or nil 
- *     array.delete(obj) { block }  -> obj or nil
- *  
- *  Deletes items from <i>self</i> that are equal to <i>obj</i>. If
- *  the item is not found, returns <code>nil</code>. If the optional
- *  code block is given, returns the result of <i>block</i> if the item
- *  is not found.
- *     
- *     a = [ "a", "b", "b", "b", "c" ]
- *     a.delete("b")                   #=> "b"
- *     a                               #=> ["a", "c"]
- *     a.delete("z")                   #=> nil
- *     a.delete("z") { "not found" }   #=> "not found"
- */
-
-static bool
-rary_delete_element(VALUE ary, VALUE item, bool use_equal, bool check_modify)
-{
-    VALUE *p = rary_ptr(ary);
-    VALUE *t = p;
-    VALUE *end = p + RARY(ary)->len;
-
-    if (use_equal) {
-	while (t < end) {
-	    if (RTEST(rb_equal_fast(*t, item))) {
-		if (check_modify) {
-		    rary_modify(ary);
-		    check_modify = false;
-		}
-		t++;
-	    }
-	    else {
-		GC_WB(p, *t);
-		p++;
-		t++;
-	    }
-	}
-    }
-    else {
-	while (t < end) {
-	    if (*t == item) {
-		if (check_modify) {
-		    rary_modify(ary);
-		    check_modify = false;
-		}
-		t++;
-	    }
-	    else {
-		GC_WB(p, *t);
-		p++;
-		t++;
-	    }
-	}
-    }
-
-    const size_t n = p - rary_ptr(ary);
-    if (RARY(ary)->len == n) {
-	// Nothing changed.
-	return false;
-    }
-    RARY(ary)->len = n;
-    return true;
-}
-
-VALUE
-rary_delete(VALUE ary, SEL sel, VALUE item)
-{
-    const bool changed = rary_delete_element(ary, item, true, true);
-    if (!changed) {
-	if (rb_block_given_p()) {
-	    return rb_yield(item);
-	}
-	return Qnil;
-    }
-    return item;
-}
-
-/*
- *  call-seq:
- *     array.delete_at(index)  -> obj or nil
- *  
- *  Deletes the element at the specified index, returning that element,
- *  or <code>nil</code> if the index is out of range. See also
- *  <code>Array#slice!</code>.
- *     
- *     a = %w( ant bat cat dog )
- *     a.delete_at(2)    #=> "cat"
- *     a                 #=> ["ant", "bat", "dog"]
- *     a.delete_at(99)   #=> nil
- */
-
-VALUE
-rary_delete_at(VALUE ary, SEL sel, VALUE pos)
-{
-    long index = NUM2LONG(pos);
-    if (index < 0) {
-	index += RARY(ary)->len;
-	if (index < 0) {
-	    return Qnil;
-	}
-    }
-    if (index >= RARY(ary)->len) {
-	return Qnil;
-    }
-    rary_modify(ary);
-    return rary_erase(ary, index, 1);
-}
-
-/*
- *  call-seq:
- *     array.slice!(index)         -> obj or nil
- *     array.slice!(start, length) -> sub_array or nil
- *     array.slice!(range)         -> sub_array or nil 
- *  
- *  Deletes the element(s) given by an index (optionally with a length)
- *  or by a range. Returns the deleted object, subarray, or
- *  <code>nil</code> if the index is out of range.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.slice!(1)     #=> "b"
- *     a               #=> ["a", "c"]
- *     a.slice!(-1)    #=> "c"
- *     a               #=> ["a"]
- *     a.slice!(100)   #=> nil
- *     a               #=> ["a"]
- */
-
-static VALUE
-rary_slice_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    const long alen = RARY(ary)->len;
-    long pos, len;
-
-    rary_modify(ary);
-    VALUE arg1, arg2;
-    if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
-	pos = NUM2LONG(arg1);
-	len = NUM2LONG(arg2);
-delete_pos_len:
-	if (len < 0) {
-	    return Qnil;
-	}
-	if (pos < 0) {
-	    pos = alen + pos;
-	    if (pos < 0) {
-		return Qnil;
-	    }
-	}
-	else if (alen < pos) {
-	    return Qnil;
-	}
-	if (alen < len || alen < pos + len) {
-	    len = alen - pos;
-	}
-	if (len == 0) {
-	    return rb_ary_new2(0);
-	}
-	arg2 = rary_subseq(ary, pos, len);
-	rary_splice(ary, pos, len, Qundef);
-	return arg2;
-    }
-
-    if (!FIXNUM_P(arg1)) {
-	switch (rb_range_beg_len(arg1, &pos, &len, alen, 0)) {
-	    case Qtrue:
-		// Valid range.
-		goto delete_pos_len;
-	    case Qnil:
-		// Invalid range.
-		return Qnil;
-	    default:
-		// Not a range.
-		break;
-	}
-    }
-    return rary_delete_at(ary, 0, arg1);
-}
-
-/*
- *  call-seq:
- *     array.reject! {|item| block }  -> array or nil
- *  
- *  Equivalent to <code>Array#delete_if</code>, deleting elements from
- *  _self_ for which the block evaluates to true, but returns
- *  <code>nil</code> if no changes were made. Also see
- *  <code>Enumerable#reject</code>.
- */
-
-static VALUE
-rary_reject_bang(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    rary_modify(ary);
-    bool changed = false;
-    for (long i = 0, n = RARY(ary)->len; i < n; i++) {
-	VALUE elem = rary_elt(ary, i);
-	VALUE test = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (RTEST(test)) {
-	    rary_erase(ary, i, 1);	
-	    n--;
-	    i--;
-	    changed = true;
-	}
-    }
-    return changed ? ary : Qnil;
-}
-
-/*
- *  call-seq:
- *     array.reject {|item| block }  -> an_array
- *  
- *  Returns a new array containing the items in _self_
- *  for which the block is not true.
- */
-
-static VALUE
-rary_reject(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    ary = rary_dup(ary, 0);
-    rary_reject_bang(ary, 0);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.delete_if {|item| block }  -> array
- *  
- *  Deletes every element of <i>self</i> for which <i>block</i> evaluates
- *  to <code>true</code>.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.delete_if {|x| x >= "b" }   #=> ["a"]
- */
-
-static VALUE
-rary_delete_if(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-    rary_reject_bang(ary, 0);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.zip(arg, ...)                   -> an_array
- *     array.zip(arg, ...) {| arr | block }  -> nil
- *  
- *  Converts any arguments to arrays, then merges elements of
- *  <i>self</i> with corresponding elements from each argument. This
- *  generates a sequence of <code>self.size</code> <em>n</em>-element
- *  arrays, where <em>n</em> is one more that the count of arguments. If
- *  the size of any argument is less than <code>enumObj.size</code>,
- *  <code>nil</code> values are supplied. If a block given, it is
- *  invoked for each output array, otherwise an array of arrays is
- *  returned.
- *     
- *     a = [ 4, 5, 6 ]
- *     b = [ 7, 8, 9 ]
- *     [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- *     [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
- *     a.zip([1,2],[8])       #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
- */
-
-static VALUE
-take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
-{
-    if (args[1]-- == 0) {
-	rb_iter_break();
-    }
-    if (argc > 1) {
-	val = rb_ary_new4(argc, argv);
-    }
-    rb_ary_push(args[0], val);
-    return Qnil;
-}
-
-static VALUE
-take_items(VALUE obj, long n)
-{
-    VALUE result = rb_check_array_type(obj);
-    VALUE args[2];
-
-    if (!NIL_P(result)) {
-	return rb_ary_subseq(result, 0, n);
-    }
-    result = rb_ary_new2(n);
-    args[0] = result;
-    args[1] = (VALUE)n;
-    
-    rb_objc_block_call(obj, selEach, 0, 0, (VALUE(*)(ANYARGS))take_i,
-	    (VALUE)args);
-
-    return result;
-}
-
-// Defined on NSArray.
-VALUE
-rary_zip(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    const long len = RARRAY_LEN(ary);
-    for (int i = 0; i < argc; i++) {
-	argv[i] = take_items(argv[i], len);
-    }
-    VALUE result = Qnil;
-    if (!rb_block_given_p()) {
-	result = rb_ary_new2(len);
-    }
-
-    for (int i = 0; i < RARRAY_LEN(ary); i++) {
-	VALUE tmp = rb_ary_new2(argc + 1);
-
-	rb_ary_push(tmp, rb_ary_elt(ary, i));
-	for (int j = 0; j < argc; j++) {
-	    VALUE item = rb_ary_elt(argv[j], i);
-	    rb_ary_push(tmp, item);
-	}
-	if (NIL_P(result)) {
-	    rb_yield(tmp);
-	    RETURN_IF_BROKEN();
-	}
-	else {
-	    rb_ary_push(result, tmp);
-	}
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     array.transpose -> an_array
- *  
- *  Assumes that <i>self</i> is an array of arrays and transposes the
- *  rows and columns.
- *     
- *     a = [[1,2], [3,4], [5,6]]
- *     a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
- */
-
-// Defined on NSArray.
-VALUE
-rary_transpose(VALUE ary, SEL sel)
-{
-    const long alen = RARRAY_LEN(ary);
-    if (alen == 0) {
-	return rb_ary_dup(ary);
-    }
-
-    long elen = -1;
-    VALUE result = Qnil;
-    for (long i = 0; i < alen; i++) {
-	VALUE tmp = to_ary(rb_ary_elt(ary, i));
-	if (elen < 0) {		/* first element */
-	    elen = RARRAY_LEN(tmp);
-	    result = rb_ary_new2(elen);
-	    for (long j = 0; j < elen; j++) {
-		rb_ary_store(result, j, rb_ary_new2(alen));
-	    }
-	}
-	else if (elen != RARRAY_LEN(tmp)) {
-	    rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
-		     RARRAY_LEN(tmp), elen);
-	}
-	for (long j = 0; j < elen; j++) {
-	    rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
-	}
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     array.replace(other_array)  -> array
- *  
- *  Replaces the contents of <i>self</i> with the contents of
- *  <i>other_array</i>, truncating or expanding if necessary.
- *     
- *     a = [ "a", "b", "c", "d", "e" ]
- *     a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
- *     a                              #=> ["x", "y", "z"]
- */
-
-static VALUE
-rary_replace(VALUE rcv, SEL sel, VALUE other)
-{
-    rary_modify(rcv);
-    other = to_ary(other);
-    rary_remove_all(RARY(rcv));
-    rary_concat(rcv, other, 0, RARRAY_LEN(other));
-    return rcv;
-}
-
-/*
- *  call-seq:
- *     array.to_a     -> array
- *
- *  Returns _self_. If called on a subclass of Array, converts
- *  the receiver to an Array object.
- */
-
-static VALUE
-rary_to_a(VALUE ary, SEL sel)
-{
-    if (rb_obj_class(ary) != rb_cRubyArray) {
-        VALUE dup = rb_ary_new();
-        rary_replace(dup, 0, ary);
-        return dup;
-    }
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array.clear    ->  array
- *
- *  Removes all elements from _self_.
- *
- *     a = [ "a", "b", "c", "d", "e" ]
- *     a.clear    #=> [ ]
- */
-
-VALUE
-rary_clear(VALUE ary, SEL sel)
-{
-    rary_modify(ary);
-    rary_remove_all(RARY(ary));
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.fill(obj)                                -> array
- *     array.fill(obj, start [, length])              -> array
- *     array.fill(obj, range )                        -> array
- *     array.fill {|index| block }                    -> array
- *     array.fill(start [, length] ) {|index| block } -> array
- *     array.fill(range) {|index| block }             -> array
- *  
- *  The first three forms set the selected elements of <i>self</i> (which
- *  may be the entire array) to <i>obj</i>. A <i>start</i> of
- *  <code>nil</code> is equivalent to zero. A <i>length</i> of
- *  <code>nil</code> is equivalent to <i>self.length</i>. The last three
- *  forms fill the array with the value of the block. The block is
- *  passed the absolute index of each element to be filled.
- *     
- *     a = [ "a", "b", "c", "d" ]
- *     a.fill("x")              #=> ["x", "x", "x", "x"]
- *     a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
- *     a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
- *     a.fill {|i| i*i}         #=> [0, 1, 4, 9]
- *     a.fill(-2) {|i| i*i*i}   #=> [0, 1, 8, 27]
- */
-
-// Defined on NSArray.
-VALUE
-rary_fill(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE item, arg1, arg2;
-    const long n = RARRAY_LEN(ary);
-    bool block_p = false;
-    if (rb_block_given_p()) {
-	block_p = true;
-	rb_scan_args(argc, argv, "02", &arg1, &arg2);
-	argc += 1;		/* hackish */
-    }
-    else {
-	rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
-    }
-
-    long beg = 0, end = 0, len = 0;
-    switch (argc) {
-	case 1:
-	    beg = 0;
-	    len = n;
-	    break;
-	case 2:
-	    if (rb_range_beg_len(arg1, &beg, &len, n, 1)) {
-		break;
-	    }
-	    /* fall through */
-	case 3:
-	    beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
-	    if (beg < 0) {
-		beg = n + beg;
-		if (beg < 0) {
-		    beg = 0;
-		}
-	    }
-	    len = NIL_P(arg2) ? n - beg : NUM2LONG(arg2);
-	    break;
-    }
-
-    rb_ary_modify(ary);
-    if (len < 0) {
-	return ary;
-    }
-    end = beg + len;
-    if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
-	rb_raise(rb_eArgError, "argument too big");
-    }
-
-    if (block_p) {
-	for (long i = beg; i < end; i++) {
-	    VALUE v = rb_yield(LONG2NUM(i));
-	    RETURN_IF_BROKEN();
-	    rb_ary_store(ary, i, v);
-	}
-    }
-    else {
-	for (long i = beg; i < end; i++) {
-	    rb_ary_store(ary, i, item);
-	}
-    }
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array.concat(other_array)   ->  array
- *
- *  Appends the elements in other_array to _self_.
- *  
- *     [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
- */
-
-VALUE
-rary_concat_m(VALUE x, SEL sel, VALUE y)
-{
-    rary_modify(x);
-    y = to_ary(y);
-    rary_concat(x, y, 0, RARRAY_LEN(y));
-    return x;
-}
-
-/* 
- *  call-seq:
- *     array + other_array   -> an_array
- *
- *  Concatenation---Returns a new array built by concatenating the
- *  two arrays together to produce a third array.
- * 
- *     [ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
- */
-
-VALUE
-rary_plus(VALUE x, SEL sel, VALUE y)
-{
-    y = to_ary(y);
-    VALUE z = rb_ary_new2(0);
-    rary_reserve(z, RARY(x)->len + RARRAY_LEN(y));
-    rary_concat_m(z, 0, x);
-    rary_concat_m(z, 0, y);
-    return z;
-}
-
-/* 
- *  call-seq:
- *     array * int     ->    an_array
- *     array * str     ->    a_string
- *
- *  Repetition---With a String argument, equivalent to
- *  self.join(str). Otherwise, returns a new array
- *  built by concatenating the _int_ copies of _self_.
- *
- *
- *     [ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
- *     [ 1, 2, 3 ] * ","  #=> "1,2,3"
- *
- */
-
-static VALUE
-rary_times(VALUE ary, SEL sel, VALUE times)
-{
-    VALUE tmp = rb_check_string_type(times);
-    if (!NIL_P(tmp)) {
-	return rb_ary_join(ary, tmp);
-    }
-
-    const long len = NUM2LONG(times);
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative argument");
-    }
-    VALUE ary2 = rary_alloc(rb_obj_class(ary), 0);
-    if (len > 0) {
-	const long n = RARY(ary)->len;
-	if (ARY_MAX_SIZE/len < n) {
-	    rb_raise(rb_eArgError, "argument too big");
-	}
-	rary_reserve(ary2, n * len);
-	for (long i = 0; i < len; i++) {
-	    rary_concat(ary2, ary, 0, n);
-	}
-    }
-
-    OBJ_INFECT(ary2, ary);
-    return ary2;
-}
-
-/* 
- *  call-seq:
- *     array.assoc(obj)   ->  an_array  or  nil
- *
- *  Searches through an array whose elements are also arrays
- *  comparing _obj_ with the first element of each contained array
- *  using obj.==.
- *  Returns the first contained array that matches (that
- *  is, the first associated array),
- *  or +nil+ if no match is found.
- *  See also <code>Array#rassoc</code>.
- *
- *     s1 = [ "colors", "red", "blue", "green" ]
- *     s2 = [ "letters", "a", "b", "c" ]
- *     s3 = "foo"
- *     a  = [ s1, s2, s3 ]
- *     a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
- *     a.assoc("foo")      #=> nil
- */
-
-// Defined on NSArray.
-VALUE
-rary_assoc(VALUE ary, SEL sel, VALUE key)
-{
-    for (long i = 0; i < RARRAY_LEN(ary); ++i) {
-	VALUE v = rb_check_array_type(RARRAY_AT(ary, i));
-	if (!NIL_P(v) && RARRAY_LEN(v) > 0 && rb_equal(RARRAY_AT(v, 0), key)) {
-	    return v;
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     array.rassoc(obj) -> an_array or nil
- *  
- *  Searches through the array whose elements are also arrays. Compares
- *  _obj_ with the second element of each contained array using
- *  <code>==</code>. Returns the first contained array that matches. See
- *  also <code>Array#assoc</code>.
- *     
- *     a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
- *     a.rassoc("two")    #=> [2, "two"]
- *     a.rassoc("four")   #=> nil
- */
-
-// Defined on NSArray.
-VALUE
-rary_rassoc(VALUE ary, SEL sel, VALUE value)
-{
-    for (long i = 0; i < RARRAY_LEN(ary); ++i) {
-	VALUE v = RARRAY_AT(ary, i);
-	if (TYPE(v) == T_ARRAY && RARRAY_LEN(v) > 1
-	    && rb_equal(RARRAY_AT(v, 1), value)) {
-	    return v;
-	}
-    }
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *     array == other_array   ->   bool
- *
- *  Equality---Two arrays are equal if they contain the same number
- *  of elements and if each element is equal to (according to
- *  Object.==) the corresponding element in the other array.
- *
- *     [ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
- *     [ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
- *     [ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
- *
- */
-
-static VALUE
-recursive_equal(VALUE ary1, VALUE ary2, int recur)
-{
-    if (recur) {
-	return Qtrue; // like Ruby 1.9...
-    }
-    if (IS_RARY(ary1) && IS_RARY(ary2)) {
-	if (RARY(ary1)->len != RARY(ary2)->len) {
-	    return Qfalse;
-	}
-	for (size_t i = 0; i < RARY(ary1)->len; i++) {
-	    VALUE item1 = rary_elt(ary1, i);
-	    VALUE item2 = rary_elt(ary2, i);
-
-	    if ((FIXFLOAT_P(item1) && isnan(FIXFLOAT2DBL(item1)))
-		    || (FIXFLOAT_P(item2) && isnan(FIXFLOAT2DBL(item2)))) {
-		return Qfalse;
-	    }
-
-	    if (rb_equal_fast(item1, item2) == Qfalse) {
-		return Qfalse;
-	    }
-	}
-	return Qtrue;
-    }
-    return CFEqual((CFTypeRef)ary1, (CFTypeRef)ary2) ? Qtrue : Qfalse;
-}
-
-VALUE
-rb_ary_equal(VALUE ary1, VALUE ary2)
-{
-    return rb_exec_recursive(recursive_equal, ary1, ary2);
-}
-
-static VALUE
-rary_equal(VALUE ary1, SEL sel, VALUE ary2)
-{
-    if (ary1 == ary2) {
-	return Qtrue;
-    }
-    if (TYPE(ary2) != T_ARRAY) {
-	if (!rb_vm_respond_to(ary2, selToAry, true)) {
-	    return Qfalse;
-	}
-	return rb_equal(ary2, ary1);
-    }
-    return rb_ary_equal(ary1, ary2);
-}
-
-/*
- *  call-seq:
- *     array.eql?(other)  -> true or false
- *
- *  Returns <code>true</code> if _array_ and _other_ are the same object,
- *  or are both arrays with the same content.
- */
-
-static VALUE
-recursive_eql(VALUE ary1, VALUE ary2, int recur)
-{
-    if (recur) {
-	return Qfalse;
-    }
-    for (long i = 0; i < RARY(ary1)->len; i++) {
-	if (!rb_eql(rary_elt(ary1, i), rb_ary_elt(ary2, i))) {
-	    return Qfalse;
-	}
-    }
-    return Qtrue;
-}
-
-static VALUE
-rary_eql(VALUE ary1, SEL sel, VALUE ary2)
-{
-    if (ary1 == ary2) {
-	return Qtrue;
-    }
-    if (TYPE(ary2) != T_ARRAY) {
-	return Qfalse;
-    }
-    if (RARY(ary1)->len != RARRAY_LEN(ary2)) {
-	return Qfalse;
-    }
-    return rb_exec_recursive(recursive_eql, ary1, ary2);
-}
-
-static VALUE
-recursive_eql_fast(VALUE ary1, VALUE ary2, int recur)
-{
-    if (recur) {
-	return Qfalse;
-    }
-    for (long i = 0; i < RARY(ary1)->len; i++) {
-	if (!rb_eql(rary_elt(ary1, i), rary_elt(ary2, i))) {
-	    return Qfalse;
-	}
-    }
-    return Qtrue;
-}
-
-bool
-rary_eql_fast(rb_ary_t *ary1, rb_ary_t *ary2)
-{
-    if (ary1 == ary2) {
-	return true;
-    }
-    if (ary1->len != ary2->len) {
-	return false;
-    }
-    return rb_exec_recursive(recursive_eql_fast, (VALUE)ary1, (VALUE)ary2);
-}
-
-/*
- *  call-seq:
- *     array.include?(obj)   -> true or false
- *  
- *  Returns <code>true</code> if the given object is present in
- *  <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>),
- *  <code>false</code> otherwise.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.include?("b")   #=> true
- *     a.include?("z")   #=> false
- */
-
-VALUE
-rary_includes(VALUE ary, SEL sel, VALUE item)
-{
-    if (RARY(ary)->len == 0) {
-	return Qfalse;
-    }
-    return rary_index_of_item(ary, 0, item) != NOT_FOUND
-	? Qtrue : Qfalse;
-}
-
-/* 
- *  call-seq:
- *     array <=> other_array   ->  -1, 0, +1
- *
- *  Comparison---Returns an integer (-1, 0,
- *  or +1) if this array is less than, equal to, or greater than
- *  other_array.  Each object in each array is compared
- *  (using <=>). If any value isn't
- *  equal, then that inequality is the return value. If all the
- *  values found are equal, then the return is based on a
- *  comparison of the array lengths.  Thus, two arrays are
- *  ``equal'' according to <code>Array#<=></code> if and only if they have
- *  the same length and the value of each element is equal to the
- *  value of the corresponding element in the other array.
- *  
- *     [ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
- *     [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
- *
- */
-
-static VALUE
-recursive_cmp(VALUE ary1, VALUE ary2, int recur)
-{
-    if (recur) {
-	return Qnil;
-    }
-
-    long len = RARRAY_LEN(ary1);
-    if (len > RARRAY_LEN(ary2)) {
-	len = RARRAY_LEN(ary2);
-    }
-
-    for (long i = 0; i < len; i++) {
-	VALUE v = rb_objs_cmp(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i));
-	if (v != INT2FIX(0)) {
-	    return v;
-	}
-    }
-    return Qundef;
-}
-
-// Defined on NSArray.
-VALUE
-rary_cmp(VALUE ary1, SEL sel, VALUE ary2)
-{
-    ary2 = rb_check_array_type(ary2);
-    if (NIL_P(ary2)) {
-	return Qnil;
-    }
-    if (ary1 == ary2) {
-	return INT2FIX(0);
-    }
-
-    VALUE v = rb_exec_recursive(recursive_cmp, ary1, ary2);
-    if (v != Qundef) {
-	return v;
-    }
-    
-    const long len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
-    return len == 0 ? INT2FIX(0) : len > 0 ? INT2FIX(1) : INT2FIX(-1);
-}
-
-/* 
- *  call-seq:
- *     array - other_array    -> an_array
- *
- *  Array Difference---Returns a new array that is a copy of
- *  the original array, removing any items that also appear in
- *  other_array. (If you need set-like behavior, see the
- *  library class Set.)
- *
- *     [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
- */
-
-static VALUE
-ary_make_hash(VALUE ary1, VALUE ary2)
-{
-    VALUE hash = rb_hash_new();
-    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
-	rb_hash_aset(hash, RARRAY_AT(ary1, i), Qtrue);
-    }
-    if (ary2) {
-	for (long i = 0; i < RARRAY_LEN(ary2); i++) {
-	    rb_hash_aset(hash, RARRAY_AT(ary2, i), Qtrue);
-	}
-    }
-    return hash;
-}
-
-// Defined on NSArray.
-VALUE
-rary_diff(VALUE ary1, SEL sel, VALUE ary2)
-{
-    ary2 = to_ary(ary2);
-    const long ary1_len = RARRAY_LEN(ary1);
-    const long ary2_len = RARRAY_LEN(ary2);
-
-    VALUE ary3 = rb_ary_new();
-
-    if (ary2_len == 0) {
-	rb_ary_concat(ary3, ary1);	
-	return ary3;
-    }
-
-    VALUE hash = ary_make_hash(ary2, 0);
-    for (long i = 0; i < ary1_len; i++) {
-	VALUE v = RARRAY_AT(ary1, i);
-	if (rb_hash_has_key(hash, v) == Qfalse) {
-	    rb_ary_push(ary3, rb_ary_elt(ary1, i));
-	}
-    }
-    return ary3;
-}
-
-/* 
- *  call-seq:
- *     array & other_array
- *
- *  Set Intersection---Returns a new array
- *  containing elements common to the two arrays, with no duplicates.
- *
- *     [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
- */
-
-static void
-filter_diff(VALUE ary1, VALUE ary3, VALUE hash)
-{
-    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
-	VALUE v = RARRAY_AT(ary1, i);
-	if (rb_hash_delete_key(hash, v) != Qundef) {
-	    rb_ary_push(ary3, v);
-	}
-    }
-}
-
-// Defined on NSArray.
-VALUE
-rary_and(VALUE ary1, SEL sel, VALUE ary2)
-{
-    ary2 = to_ary(ary2);
-    VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
-	    RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
-    VALUE hash = ary_make_hash(ary2, 0);
-    if (RHASH_EMPTY_P(hash)) {
-        return ary3;
-    }
-    filter_diff(ary1, ary3, hash);
-    return ary3;
-}
-
-/* 
- *  call-seq:
- *     array | other_array     ->  an_array
- *
- *  Set Union---Returns a new array by joining this array with
- *  other_array, removing duplicates.
- *
- *     [ "a", "b", "c" ] | [ "c", "d", "a" ]
- *            #=> [ "a", "b", "c", "d" ]
- */
-
-// Defined on NSArray.
-VALUE
-rary_or(VALUE ary1, SEL sel, VALUE ary2)
-{
-    ary2 = to_ary(ary2);
-    VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) + RARRAY_LEN(ary2));
-    VALUE hash = ary_make_hash(ary1, ary2);
-    filter_diff(ary1, ary3, hash);
-    filter_diff(ary2, ary3, hash);
-    return ary3;
-}
-
-/*
- *  call-seq:
- *     array.uniq! -> array or nil
- *  
- *  Removes duplicate elements from _self_.
- *  Returns <code>nil</code> if no changes are made (that is, no
- *  duplicates are found).
- *     
- *     a = [ "a", "a", "b", "b", "c" ]
- *     a.uniq!   #=> ["a", "b", "c"]
- *     b = [ "a", "b", "c" ]
- *     b.uniq!   #=> nil
- */
-
-static VALUE
-rary_uniq_bang(VALUE ary, SEL sel)
-{
-    VALUE hash, v;
-    long i, j;
-
-    rary_modify(ary);
-    if (RARRAY_LEN(ary) <= 1) {
-        return Qnil;
-    }
-    if (rb_block_given_p()) {
-	// TODO
-	return Qnil;
-    }
-    else {
-	hash = ary_make_hash(rb_ary_new(), ary);
-	if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
-	    return Qnil;
-	}
-	for (i=j=0; i<RARRAY_LEN(ary); i++) {
-	    st_data_t vv = (st_data_t)(v = rary_elt(ary, i));
-	    if (st_delete(RHASH_TBL(hash), &vv, 0)) {
-		rary_store(ary, j++, v);
-	    }
-	}
-	rary_resize(ary, j);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.uniq   -> an_array
- *  
- *  Returns a new array by removing duplicate values in <i>self</i>.
- *     
- *     a = [ "a", "a", "b", "b", "c" ]
- *     a.uniq   #=> ["a", "b", "c"]
- */
-
-static VALUE
-rary_uniq(VALUE ary, SEL sel)
-{
-    ary = rary_dup(ary, 0);
-    rary_uniq_bang(ary, 0);
-    return ary;
-}
-
-/* 
- *  call-seq:
- *     array.compact!    ->   array  or  nil
- *
- *  Removes +nil+ elements from array.
- *  Returns +nil+ if no changes were made.
- *
- *     [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
- *     [ "a", "b", "c" ].compact!           #=> nil
- */
-
-static VALUE
-rary_compact_bang(VALUE ary, SEL sel)
-{
-    rary_modify(ary);
-    return rary_delete_element(ary, Qnil, false, false) ? ary : Qnil;
-}
-
-/*
- *  call-seq:
- *     array.compact     ->  an_array
- *
- *  Returns a copy of _self_ with all +nil+ elements removed.
- *
- *     [ "a", nil, "b", nil, "c", nil ].compact
- *                       #=> [ "a", "b", "c" ]
- */
-
-static VALUE
-rary_compact(VALUE ary, SEL sel)
-{
-    ary = rary_dup(ary, 0);
-    rary_compact_bang(ary, 0);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.count      -> int
- *     array.count(obj) -> int
- *     array.count { |item| block }  -> int
- *  
- *  Returns the number of elements.  If an argument is given, counts
- *  the number of elements which equals to <i>obj</i>.  If a block is
- *  given, counts the number of elements yielding a true value.
- *
- *     ary = [1, 2, 4, 2]
- *     ary.count             # => 4
- *     ary.count(2)          # => 2
- *     ary.count{|x|x%2==0}  # => 3
- *
- */
-
-static VALUE
-rary_count(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    long n = 0;
- 
-    if (argc == 0) {
-	if (!rb_block_given_p())
-	    return LONG2NUM(RARY(ary)->len);
-
-	for (long i = 0; i < RARY(ary)->len; i++) {
-	    VALUE elem = rary_elt(ary, i);
-	    VALUE test = rb_yield(elem); 
-	    RETURN_IF_BROKEN();
-	    if (RTEST(test)) {
-		n++;
-	    }
-	}
-    }
-    else {
-	VALUE obj;
-	rb_scan_args(argc, argv, "1", &obj);
-	if (rb_block_given_p()) {
-	    rb_warn("given block not used");
-	}
-
-	size_t pos = 0;
-	while ((pos = rary_index_of_item(ary, pos, obj))
-		!= NOT_FOUND) {
-	    n++;
-	    if (++pos == RARY(ary)->len) {
-		break;
-	    }
-	}
-    }
-
-    return LONG2NUM(n);
-}
-
-/*
- *  call-seq:
- *     array.flatten! -> array or nil
- *     array.flatten!(level) -> array or nil
- *  
- *  Flattens _self_ in place.
- *  Returns <code>nil</code> if no modifications were made (i.e.,
- *  <i>array</i> contains no subarrays.)  If the optional <i>level</i>
- *  argument determines the level of recursion to flatten.
- *     
- *     a = [ 1, 2, [3, [4, 5] ] ]
- *     a.flatten!   #=> [1, 2, 3, 4, 5]
- *     a.flatten!   #=> nil
- *     a            #=> [1, 2, 3, 4, 5]
- *     a = [ 1, 2, [3, [4, 5] ] ]
- *     a.flatten!(1) #=> [1, 2, 3, [4, 5]]
- */
-
-static VALUE
-flatten(VALUE ary, int level, int *modified)
-{
-    long i = 0;
-    VALUE stack, result, tmp, elt;
-    st_table *memo;
-    st_data_t id;
-
-    stack = rb_ary_new();
-    VALUE klass = rb_class_of(ary);
-    if (!rb_klass_is_rary(klass)) {
-	klass = rb_cRubyArray;
-    }
-    result = rary_alloc(klass, 0);
-    rary_reserve(result, RARRAY_LEN(ary));
-    memo = st_init_numtable();
-    st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
-    *modified = 0;
-
-    while (true) {
-	while (i < RARRAY_LEN(ary)) {
-	    elt = RARRAY_AT(ary, i++);
-	    tmp = rb_check_array_type(elt);
-	    if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
-		rb_ary_push(result, elt);
-	    }
-	    else {
-		*modified = 1;
-		id = (st_data_t)tmp;
-		if (st_lookup(memo, id, 0)) {
-		    st_free_table(memo);
-		    rb_raise(rb_eArgError, "tried to flatten recursive array");
-		}
-		st_insert(memo, id, (st_data_t)Qtrue);
-		rb_ary_push(stack, ary);
-		rb_ary_push(stack, LONG2NUM(i));
-		ary = tmp;
-		i = 0;
-	    }
-	}
-	if (RARRAY_LEN(stack) == 0) {
-	    break;
-	}
-	id = (st_data_t)ary;
-	st_delete(memo, &id, 0);
-	tmp = rb_ary_pop(stack);
-	i = NUM2LONG(tmp);
-	ary = rb_ary_pop(stack);
-    }
-
-    st_free_table(memo);
-
-    return result;
-}
-
-// Defined on NSArray.
-VALUE
-rary_flatten_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    int mod = 0, level = -1;
-    VALUE result, lv;
-
-    rb_scan_args(argc, argv, "01", &lv);
-    rb_ary_modify(ary);
-    if (!NIL_P(lv)) {
-	level = NUM2INT(lv);
-    }
-    if (level == 0) {
-	return Qnil;
-    }
-
-    result = flatten(ary, level, &mod);
-    if (mod == 0) {
-	return Qnil;
-    }
-    rb_ary_replace(ary, result);
-
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.flatten -> an_array
- *     array.flatten(level) -> an_array
- *  
- *  Returns a new array that is a one-dimensional flattening of this
- *  array (recursively). That is, for every element that is an array,
- *  extract its elements into the new array.  If the optional
- *  <i>level</i> argument determines the level of recursion to flatten.
- *     
- *     s = [ 1, 2, 3 ]           #=> [1, 2, 3]
- *     t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
- *     a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
- *     a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- *     a = [ 1, 2, [3, [4, 5] ] ]
- *     a.flatten(1)              #=> [1, 2, 3, [4, 5]]
- */
-
-// Defined on NSArray.
-VALUE
-rary_flatten(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    int mod = 0, level = -1;
-    VALUE result, lv;
-
-    rb_scan_args(argc, argv, "01", &lv);
-    if (!NIL_P(lv)) {
-	level = NUM2INT(lv);
-    }
-    if (level == 0) {
-	return rary_dup(ary, 0);
-    }
-
-    result = flatten(ary, level, &mod);
-    if (OBJ_TAINTED(ary)) {
-	OBJ_TAINT(result);
-    }
-    if (OBJ_UNTRUSTED(ary)) {
-	OBJ_UNTRUST(result);
-    }
-
-    return result;
-}
-
-/*
- *  call-seq:
- *     array.shuffle!        -> array or nil
- *  
- *  Shuffles elements in _self_ in place.
- */
-
-static VALUE
-rary_shuffle_bang(VALUE ary, SEL sel)
-{
-    rary_modify(ary);
-
-    long i = RARY(ary)->len;
-    while (i > 0) {
-	const long j = rb_genrand_real() * i;
-	VALUE elem = rb_ary_elt(ary, --i);
-	rary_store(ary, i, rb_ary_elt(ary, j));
-	rary_store(ary, j, elem);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.shuffle -> an_array
- *  
- *  Returns a new array with elements of this array shuffled.
- *     
- *     a = [ 1, 2, 3 ]           #=> [1, 2, 3]
- *     a.shuffle                 #=> [2, 3, 1]
- */
-
-static VALUE
-rary_shuffle(VALUE ary, SEL sel)
-{
-    ary = rary_dup(ary, 0);
-    rary_shuffle_bang(ary, 0);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     array.sample        -> obj
- *     array.sample(n)     -> an_array
- *  
- *  Choose a random element, or the random +n+ elements, from the array.
- *  If the array is empty, the first form returns <code>nil</code>, and the
- *  second form returns an empty array.
- */
-
-// Defined on NSArray.
-VALUE
-rary_sample(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE nv, result;
-    long n, len, i, j, k, idx[10];
-
-    len = RARRAY_LEN(ary); 
-    if (argc == 0) {
-	if (len == 0) {
-	    return Qnil;
-	}
-	i = len == 1 ? 0 : rb_genrand_real() * len;
-	return RARRAY_AT(ary, i);
-    }
-    rb_scan_args(argc, argv, "1", &nv);
-    n = NUM2LONG(nv);
-    if (n < 0) {
-	rb_raise(rb_eArgError, "negative count");
-    }
-    len = RARRAY_LEN(ary); 
-    if (n > len) {
-	n = len;
-    }
-    switch (n) {
-	case 0:
-	    return rb_ary_new2(0);
-
-	case 1:
-	    nv = RARRAY_AT(ary, (long)(rb_genrand_real() * len));
-	    return rb_ary_new4(1, &nv);
-
-	case 2:
-	    i = rb_genrand_real() * len;
-	    j = rb_genrand_real() * (len - 1);
-	    if (j >= i) {
-		j++;
-	    }
-	    {
-		VALUE elems[] = { RARRAY_AT(ary, i), RARRAY_AT(ary, j) };
-		return rb_ary_new4(2, elems);
-	    }
-
-	case 3:
-	    i = rb_genrand_real() * len;
-	    j = rb_genrand_real() * (len - 1);
-	    k = rb_genrand_real() * (len - 2);
-	    {
-		long l = j, g = i;
-		if (j >= i) {
-		    l = i;
-		    g = ++j;
-		}
-		if (k >= l && (++k >= g)) {
-		    ++k;
-		}
-		VALUE elems[] = { RARRAY_AT(ary, i), RARRAY_AT(ary, j),
-		    RARRAY_AT(ary, k) };
-		return rb_ary_new4(3, elems);
-	    }
-    }
-    if ((unsigned long)n < sizeof(idx) / sizeof(idx[0])) {
-	long sorted[sizeof(idx) / sizeof(idx[0])];
-	sorted[0] = idx[0] = rb_genrand_real()*len;
-	for (i = 1; i < n; i++) {
-	    k = rb_genrand_real() * --len;
-	    for (j = 0; j < i; ++j) {
-		if (k < sorted[j]) {
-		    break;
-		}
-		++k;
-	    }
-	    memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
-	    sorted[j] = idx[i] = k;
-	}
-	VALUE *elems = (VALUE *)malloc(sizeof(VALUE) * n);
-	for (i = 0; i < n; i++) {
-	    elems[i] = RARRAY_AT(ary, idx[i]);
-	}
-	result = rb_ary_new4(n, elems);
-	free(elems);
-    }
-    else {
-	VALUE *elems = (VALUE *)malloc(sizeof(VALUE) * n);
-	for (i = 0; i < n; i++) {
-	    j = (long)(rb_genrand_real() * (len - i)) + i;
-	    nv = RARRAY_AT(ary, j);
-	    elems[i] = nv;
-	}
-	result = rb_ary_new4(n, elems);
-	free(elems);
-    }
-
-    return result;
-}
-
-/*
- *  call-seq:
- *     ary.cycle {|obj| block }
- *     ary.cycle(n) {|obj| block }
- *  
- *  Calls <i>block</i> for each element repeatedly _n_ times or
- *  forever if none or nil is given.  If a non-positive number is
- *  given or the array is empty, does nothing.  Returns nil if the
- *  loop has finished without getting interrupted.
- *     
- *     a = ["a", "b", "c"]
- *     a.cycle {|x| puts x }  # print, a, b, c, a, b, c,.. forever.
- *     a.cycle(2) {|x| puts x }  # print, a, b, c, a, b, c.
- *     
- */
-
-// Defined on NSArray.
-VALUE
-rary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE nv = Qnil;
-    rb_scan_args(argc, argv, "01", &nv);
-
-    RETURN_ENUMERATOR(ary, argc, argv);
-
-    long n;
-    if (NIL_P(nv)) {
-        n = -1;
-    }
-    else {
-        n = NUM2LONG(nv);
-        if (n <= 0) {
-	    return Qnil;
-	}
-    }
-
-    while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
-        for (long i = 0; i < RARRAY_LEN(ary); i++) {
-            rb_yield(RARRAY_AT(ary, i));
-	    RETURN_IF_BROKEN();
-        }
-    }
-    return Qnil;
-}
-
-/*
- * Recursively compute permutations of r elements of the set [0..n-1].
- * When we have a complete permutation of array indexes, copy the values
- * at those indexes into a new array and yield that array. 
- *
- * n: the size of the set 
- * r: the number of elements in each permutation
- * p: the array (of size r) that we're filling in
- * index: what index we're filling in now
- * used: an array of booleans: whether a given index is already used
- * values: the Ruby array that holds the actual values to permute
- */
-static void
-permute0(long n, long r, long *p, long index, int *used, VALUE values)
-{
-    long i,j;
-    for (i = 0; i < n; i++) {
-	if (used[i] == 0) {
-	    p[index] = i;
-	    if (index < r-1) {             /* if not done yet */
-		used[i] = 1;               /* mark index used */
-		permute0(n, r, p, index+1, /* recurse */
-			 used, values);  
-		used[i] = 0;               /* index unused */
-	    }
-	    else {
-		/* We have a complete permutation of array indexes */
-		/* Build a ruby array of the corresponding values */
-		/* And yield it to the associated block */
-		VALUE result = rb_ary_new2(r);
-		for (j = 0; j < r; j++) {
-		    rb_ary_store(result, j, RARRAY_AT(values, p[j]));
-		}
-		rb_yield(result);
-	    }
-	}
-    }
-}
-
-/*
- *  call-seq:
- *     ary.permutation { |p| block }          -> array
- *     ary.permutation                        -> enumerator
- *     ary.permutation(n) { |p| block }       -> array
- *     ary.permutation(n)                     -> enumerator
- *  
- * When invoked with a block, yield all permutations of length <i>n</i>
- * of the elements of <i>ary</i>, then return the array itself.
- * If <i>n</i> is not specified, yield all permutations of all elements.
- * The implementation makes no guarantees about the order in which 
- * the permutations are yielded.
- *
- * When invoked without a block, return an enumerator object instead.
- * 
- * Examples:
- *
- *     a = [1, 2, 3]
- *     a.permutation.to_a     #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
- *     a.permutation(1).to_a  #=> [[1],[2],[3]]
- *     a.permutation(2).to_a  #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
- *     a.permutation(3).to_a  #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
- *     a.permutation(0).to_a  #=> [[]] # one permutation of length 0
- *     a.permutation(4).to_a  #=> []   # no permutations of length 4
- */
-
-// Defined on NSArray.
-VALUE
-rary_permutation(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    VALUE num;
-    long r, n, i;
-
-    RETURN_ENUMERATOR(ary, argc, argv);   /* Return enumerator if no block */
-    rb_scan_args(argc, argv, "01", &num);
-    n = RARRAY_LEN(ary);                  /* Array length */
-    r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */
-
-    if (r < 0 || n < r) { 
-	/* no permutations: yield nothing */
-    }
-    else if (r == 0) { /* exactly one permutation: the zero-length array */
-	rb_yield(rb_ary_new2(0));
-    }
-    else if (r == 1) { /* this is a special, easy case */
-	for (i = 0; i < n; i++) {
-	    VALUE elem = RARRAY_AT(ary, i);
-	    rb_yield(rb_ary_new4(1, &elem));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {             /* this is the general case */
-	long *p = (long *)alloca(n * sizeof(long));
-	int *used = (int *)alloca(n * sizeof(int));
-	VALUE ary0 = rb_ary_dup(ary);
-
-	for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
-
-	permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
-    }
-    return ary;
-}
-
-static long
-combi_len(long n, long k)
-{
-    long i, val = 1;
-
-    if (k*2 > n) k = n-k;
-    if (k == 0) return 1;
-    if (k < 0) return 0;
-    val = 1;
-    for (i=1; i <= k; i++,n--) {
-	long m = val;
-	val *= n;
-	if (val < m) {
-	    rb_raise(rb_eRangeError, "too big for combination");
-	}
-	val /= i;
-    }
-    return val;
-}
-
-/*
- *  call-seq:
- *     ary.combination(n) { |c| block }    -> ary
- *     ary.combination(n)                  -> enumerator
- *  
- * When invoked with a block, yields all combinations of length <i>n</i> 
- * of elements from <i>ary</i> and then returns <i>ary</i> itself.
- * The implementation makes no guarantees about the order in which 
- * the combinations are yielded.
-  *
- * When invoked without a block, returns an enumerator object instead.
- *     
- * Examples:
- *
- *     a = [1, 2, 3, 4]
- *     a.combination(1).to_a  #=> [[1],[2],[3],[4]]
- *     a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
- *     a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
- *     a.combination(4).to_a  #=> [[1,2,3,4]]
- *     a.combination(0).to_a  #=> [[]] # one combination of length 0
- *     a.combination(5).to_a  #=> []   # no combinations of length 5
- *     
- */
-
-// Defined on NSArray.
-VALUE
-rary_combination(VALUE ary, SEL sel, VALUE num)
-{
-    long n, i, len;
-
-    n = NUM2LONG(num);
-    RETURN_ENUMERATOR(ary, 1, &num);
-    len = RARRAY_LEN(ary);
-    if (n < 0 || len < n) {
-	/* yield nothing */
-    }
-    else if (n == 0) {
-	rb_yield(rb_ary_new2(0));
-    }
-    else if (n == 1) {
-	for (i = 0; i < len; i++) {
-	    VALUE elem = RARRAY_AT(ary, i);
-	    rb_yield(rb_ary_new4(1, &elem));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {
-	long *stack = (long *)alloca((n + 1) * sizeof(long));
-	long nlen = combi_len(len, n);
-	volatile VALUE cc = rb_ary_new2(n);
-	long lev = 0;
-
-	MEMZERO(stack, long, n);
-	stack[0] = -1;
-	for (i = 0; i < nlen; i++) {
-	    rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1]));
-	    for (lev++; lev < n; lev++) {
-		stack[lev+1] = stack[lev]+1;
-		rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1]));
-	    }
-	    rb_yield(rb_ary_dup(cc));
-	    RETURN_IF_BROKEN();
-	    do {
-		stack[lev--]++;
-	    } while (lev && (stack[lev+1]+n == len+lev+1));
-	}
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     ary.product(other_ary, ...)
- *  
- *  Returns an array of all combinations of elements from all arrays.
- *  The length of the returned array is the product of the length
- *  of ary and the argument arrays
- *     
- *     [1,2,3].product([4,5])     # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
- *     [1,2].product([1,2])       # => [[1,1],[1,2],[2,1],[2,2]]
- *     [1,2].product([3,4],[5,6]) # => [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
- *                                #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
- *     [1,2].product()            # => [[1],[2]]
- *     [1,2].product([])          # => []
- */
-
-// Defined on NSArray.
-VALUE
-rary_product(VALUE ary, SEL sel, int argc, VALUE *argv)
-{
-    int n = argc+1;    /* How many arrays we're operating on */
-    VALUE *arrays = (VALUE *)alloca(n * sizeof(VALUE));; /* The arrays we're computing the product of */
-    int *counters = (int *)alloca(n * sizeof(int)); /* The current position in each one */
-    VALUE result = Qnil; /* The array we'll be returning */
-    long i,j;
-    long resultlen = 1;
-
-    /* initialize the arrays of arrays */
-    arrays[0] = ary;
-    for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
-    
-    /* initialize the counters for the arrays */
-    for (i = 0; i < n; i++) counters[i] = 0;
-
-    /* Compute the length of the result array; return [] if any is empty */
-    for (i = 0; i < n; i++) {
-	long k = RARRAY_LEN(arrays[i]), l = resultlen;
-	if (k == 0) {
-	    if (rb_block_given_p()) {
-		return ary;
-	    }
-	    return rb_ary_new2(0);
-	}
-	resultlen *= k;
-	if (resultlen < k || resultlen < l || resultlen / k != l) {
-	    rb_raise(rb_eRangeError, "too big to product");
-	}
-    }
-
-    if (!rb_block_given_p()) {
-	/* Otherwise, allocate and fill in an array of results */
-	result = rb_ary_new2(resultlen);
-    }
-    for (i = 0; i < resultlen; i++) {
-	int m;
-	/* fill in one subarray */
-	VALUE subarray = rb_ary_new2(n);
-	for (j = 0; j < n; j++) {
-	    rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
-	}
-
-	if (NIL_P(result)) {
-	    rb_yield(subarray);
-	}
-	else {
-	    /* put it on the result array */
-	    rb_ary_push(result, subarray);
-	}
-
-	/*
-	 * Increment the last counter.  If it overflows, reset to 0
-	 * and increment the one before it.
-	 */
-	m = n-1;
-	counters[m]++;
-	while (m > 0 && counters[m] == RARRAY_LEN(arrays[m])) {
-	    counters[m] = 0;
-	    m--;
-	    counters[m]++;
-	}
-    }
-
-    return NIL_P(result) ? ary : result;
-}
-
-/*
- *  call-seq:
- *     ary.take(n)               => array
- *  
- *  Returns first n elements from <i>ary</i>.
- *     
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.take(3)             # => [1, 2, 3]
- *     
- */
-
-static VALUE
-rary_take(VALUE obj, SEL sel, VALUE n)
-{
-    const long len = NUM2LONG(n);
-    if (len < 0) {
-	rb_raise(rb_eArgError, "attempt to take negative size");
-    }
-    return rary_subseq(obj, 0, len);
-}
-
-/*
- *  call-seq:
- *     ary.take_while {|arr| block }   => array
- *  
- *  Passes elements to the block until the block returns nil or false,
- *  then stops iterating and returns an array of all prior elements.
- *     
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.take_while {|i| i < 3 }   # => [1, 2]
- *     
- */
-
-static VALUE
-rary_take_while(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    long i = 0;
-    while (i < RARY(ary)->len) {
-	VALUE elem = rary_elt(ary, i);
-	VALUE test = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (!RTEST(test)) {
-	    break;
-	}
-	i++;
-    }
-    return rary_take(ary, 0, LONG2FIX(i));
-}
-
-/*
- *  call-seq:
- *     ary.drop(n)               => array
- *  
- *  Drops first n elements from <i>ary</i>, and returns rest elements
- *  in an array.
- *     
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.drop(3)             # => [4, 5, 0]
- *     
- */
-
-static VALUE
-rary_drop(VALUE ary, SEL sel, VALUE n)
-{
-    const long pos = NUM2LONG(n);
-    if (pos < 0) {
-	rb_raise(rb_eArgError, "attempt to drop negative size");
-    }
-
-    VALUE result = rary_subseq(ary, pos, RARY(ary)->len);
-    if (result == Qnil) {
-	result = rb_ary_new();
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     ary.drop_while {|arr| block }   => array
- *  
- *  Drops elements up to, but not including, the first element for
- *  which the block returns nil or false and returns an array
- *  containing the remaining elements.
- *     
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.drop_while {|i| i < 3 }   # => [3, 4, 5, 0]
- *     
- */
-
-static VALUE
-rary_drop_while(VALUE ary, SEL sel)
-{
-    RETURN_ENUMERATOR(ary, 0, 0);
-
-    long i = 0;
-    while (i < RARY(ary)->len) {
-	VALUE elem = rary_elt(ary, i);
-	VALUE test = rb_yield(elem);
-	RETURN_IF_BROKEN();
-	if (!RTEST(test)) {
-	    break;
-	}
-	i++;
-    }
-    return rary_drop(ary, 0, LONG2FIX(i));
-}
-
-static CFIndex
-imp_rary_count(void *rcv, SEL sel)
-{
-    return RARY(rcv)->len;
-}
-
-static const void *
-imp_rary_objectAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
-    assert(idx < RARY(rcv)->len);
-    return RB2OC(rary_elt((VALUE)rcv, idx));
-}
-
-static void
-imp_rary_insertObjectAtIndex(void *rcv, SEL sel, void *obj, CFIndex idx)
-{
-    rary_insert((VALUE)rcv, idx, OC2RB(obj));
-}
-
-static void
-imp_rary_removeObjectAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
-    rary_erase((VALUE)rcv, idx, 1);
-}
-
-static void
-imp_rary_replaceObjectAtIndexWithObject(void *rcv, SEL sel, CFIndex idx, 
-	void *obj)
-{
-    rary_store((VALUE)rcv, idx, OC2RB(obj));
-}
-
-static void
-imp_rary_addObject(void *rcv, SEL sel, void *obj)
-{
-    rary_push((VALUE)rcv, OC2RB(obj));
-}
-
-bool
-rb_objc_ary_is_pure(VALUE ary)
-{
-    VALUE k = *(VALUE *)ary;
-    while (RCLASS_SINGLETON(k)) {
-        k = RCLASS_SUPER(k);
-    }
-    if (k == rb_cRubyArray) {
-	return true;
-    }
-    while (k != 0) {
-	if (k == rb_cRubyArray) {
-	    return false;
-	}
-	k = RCLASS_SUPER(k);
-    }
-    return true;
-}
-
-/* Arrays are ordered, integer-indexed collections of any object. 
- * Array indexing starts at 0, as in C or Java.  A negative index is 
- * assumed to be relative to the end of the array---that is, an index of -1 
- * indicates the last element of the array, -2 is the next to last 
- * element in the array, and so on. 
- */
-
-void Init_NSArray(void);
-
-void
-Init_Array(void)
-{
-    Init_NSArray();
-
-    rb_cRubyArray = rb_define_class("Array", rb_cNSMutableArray);
-    rb_objc_install_NSObject_special_methods((Class)rb_cRubyArray);
-
-    rb_objc_define_method(*(VALUE *)rb_cRubyArray, "new",
-	    rb_class_new_instance_imp, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRubyArray, "alloc", rary_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cRubyArray, "[]", rary_s_create, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRubyArray, "try_convert",
-	    rary_s_try_convert, 1);
-    rb_objc_define_method(rb_cRubyArray, "initialize", rary_initialize, -1);
-    rb_objc_define_method(rb_cRubyArray, "initialize_copy", rary_replace, 1);
-    rb_objc_define_method(rb_cRubyArray, "to_a", rary_to_a, 0);
-    rb_objc_define_method(rb_cRubyArray, "dup", rary_dup, 0);
-    rb_objc_define_method(rb_cRubyArray, "clone", rary_clone, 0);
-    rb_objc_define_method(rb_cRubyArray, "to_s", rary_inspect, 0);
-    rb_objc_define_method(rb_cRubyArray, "inspect", rary_inspect, 0);
-    rb_objc_define_method(rb_cRubyArray, "==", rary_equal, 1);
-    rb_objc_define_method(rb_cRubyArray, "eql?", rary_eql, 1);
-    rb_objc_define_method(rb_cRubyArray, "[]", rary_aref, -1);
-    rb_objc_define_method(rb_cRubyArray, "[]=", rary_aset, -1);
-    rb_objc_define_method(rb_cRubyArray, "at", rary_at, 1);
-    rb_objc_define_method(rb_cRubyArray, "fetch", rary_fetch, -1);
-    rb_objc_define_method(rb_cRubyArray, "first", rary_first, -1);
-    rb_objc_define_method(rb_cRubyArray, "last", rary_last, -1);
-    rb_objc_define_method(rb_cRubyArray, "concat", rary_concat_m, 1);
-    rb_objc_define_method(rb_cRubyArray, "<<", rary_push_m, 1);
-    rb_objc_define_method(rb_cRubyArray, "push", rary_push_m2, -1);
-    rb_objc_define_method(rb_cRubyArray, "pop", rary_pop, -1);
-    rb_objc_define_method(rb_cRubyArray, "shift", rary_shift, -1);
-    rb_objc_define_method(rb_cRubyArray, "unshift", rary_unshift, -1);
-    rb_objc_define_method(rb_cRubyArray, "insert", rary_insert_m, -1);
-    rb_objc_define_method(rb_cRubyArray, "each", rary_each, 0);
-    rb_objc_define_method(rb_cRubyArray, "each_index", rary_each_index, 0);
-    rb_objc_define_method(rb_cRubyArray, "reverse_each", rary_reverse_each, 0);
-    rb_objc_define_method(rb_cRubyArray, "length", rary_length, 0);
-    rb_objc_define_method(rb_cRubyArray, "size", rary_length, 0);
-    rb_objc_define_method(rb_cRubyArray, "empty?", rary_empty, 0);
-    rb_objc_define_method(rb_cRubyArray, "find_index", rary_index, -1);
-    rb_objc_define_method(rb_cRubyArray, "index", rary_index, -1);
-    rb_objc_define_method(rb_cRubyArray, "rindex", rary_rindex, -1);
-    rb_objc_define_method(rb_cRubyArray, "reverse", rary_reverse, 0);
-    rb_objc_define_method(rb_cRubyArray, "reverse!", rary_reverse_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "rotate", rary_rotate, -1);
-    rb_objc_define_method(rb_cRubyArray, "rotate!", rary_rotate_bang, -1);
-    rb_objc_define_method(rb_cRubyArray, "sort", rary_sort, 0);
-    rb_objc_define_method(rb_cRubyArray, "sort!", rary_sort_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "sort_by!", rary_sort_by_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "collect", rary_collect, 0);
-    rb_objc_define_method(rb_cRubyArray, "collect!", rary_collect_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "map", rary_collect, 0);
-    rb_objc_define_method(rb_cRubyArray, "map!", rary_collect_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "select", rary_select, 0);
-    rb_objc_define_method(rb_cRubyArray, "select!", rary_select_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "keep_if", rary_keep_if, 0);
-    rb_objc_define_method(rb_cRubyArray, "values_at", rary_values_at, -1);
-    rb_objc_define_method(rb_cRubyArray, "delete", rary_delete, 1);
-    rb_objc_define_method(rb_cRubyArray, "delete_at", rary_delete_at, 1);
-    rb_objc_define_method(rb_cRubyArray, "delete_if", rary_delete_if, 0);
-    rb_objc_define_method(rb_cRubyArray, "reject", rary_reject, 0);
-    rb_objc_define_method(rb_cRubyArray, "reject!", rary_reject_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "replace", rary_replace, 1);
-    rb_objc_define_method(rb_cRubyArray, "clear", rary_clear, 0);
-    rb_objc_define_method(rb_cRubyArray, "include?", rary_includes, 1);
-    rb_objc_define_method(rb_cRubyArray, "slice", rary_aref, -1);
-    rb_objc_define_method(rb_cRubyArray, "slice!", rary_slice_bang, -1);
-    rb_objc_define_method(rb_cRubyArray, "+", rary_plus, 1);
-    rb_objc_define_method(rb_cRubyArray, "*", rary_times, 1);
-    rb_objc_define_method(rb_cRubyArray, "uniq", rary_uniq, 0);
-    rb_objc_define_method(rb_cRubyArray, "uniq!", rary_uniq_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "compact", rary_compact, 0);
-    rb_objc_define_method(rb_cRubyArray, "compact!", rary_compact_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "count", rary_count, -1);
-    rb_objc_define_method(rb_cRubyArray, "shuffle!", rary_shuffle_bang, 0);
-    rb_objc_define_method(rb_cRubyArray, "shuffle", rary_shuffle, 0);
-    rb_objc_define_method(rb_cRubyArray, "take", rary_take, 1);
-    rb_objc_define_method(rb_cRubyArray, "take_while", rary_take_while, 0);
-    rb_objc_define_method(rb_cRubyArray, "drop", rary_drop, 1);
-    rb_objc_define_method(rb_cRubyArray, "drop_while", rary_drop_while, 0);
-
-    rb_objc_install_method2((Class)rb_cRubyArray, "count", (IMP)imp_rary_count);
-    rb_objc_install_method2((Class)rb_cRubyArray, "objectAtIndex:",
-	    (IMP)imp_rary_objectAtIndex);
-
-    rb_objc_install_method2((Class)rb_cRubyArray, "insertObject:atIndex:",
-	    (IMP)imp_rary_insertObjectAtIndex);
-    rb_objc_install_method2((Class)rb_cRubyArray, "removeObjectAtIndex:",
-	    (IMP)imp_rary_removeObjectAtIndex);
-    rb_objc_install_method2((Class)rb_cRubyArray,
-	    "replaceObjectAtIndex:withObject:", 
-	    (IMP)imp_rary_replaceObjectAtIndexWithObject);
-    rb_objc_install_method2((Class)rb_cRubyArray, "addObject:",
-	    (IMP)imp_rary_addObject);
-}

Deleted: MacRuby/trunk/array.h
===================================================================
--- MacRuby/trunk/array.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/array.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,193 +0,0 @@
-/*
- * MacRuby Array.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __ARRAY_H_
-#define __ARRAY_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef struct {
-    struct RBasic basic;
-    size_t beg;
-    size_t len;
-    size_t cap;
-    VALUE *elements;
-} rb_ary_t;
-
-#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
-#define RARY(x) ((rb_ary_t *)x)
-
-static inline bool
-rb_klass_is_rary(VALUE klass)
-{
-    do {
-	if (klass == rb_cRubyArray) {
-	    return true;
-	}
-	if (klass == rb_cNSArray) {
-	    return false;
-	}
-	klass = RCLASS_SUPER(klass);
-    }
-    while (klass != 0);
-    return false;
-}
-
-#define IS_RARY(x) (rb_klass_is_rary(*(VALUE *)x))
-
-static inline void
-rary_modify(VALUE ary)
-{
-    const long mask = RBASIC(ary)->flags;
-    if ((mask & FL_FREEZE) == FL_FREEZE) {
-        rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array");
-    }
-    if ((mask & FL_UNTRUSTED) != FL_UNTRUSTED) {
-        if (rb_safe_level() >= 4) {
-            rb_raise(rb_eSecurityError, "Insecure: can't modify array");
-        }
-    }
-}
-
-static inline VALUE
-rary_elt(VALUE ary, size_t idx)
-{
-    //assert(idx < RARY(ary)->len);
-    return RARY(ary)->elements[RARY(ary)->beg + idx];	
-}
-
-static inline void
-rary_elt_set(VALUE ary, size_t idx, VALUE item)
-{
-    //assert(idx < ary->len);
-    GC_WB(&RARY(ary)->elements[RARY(ary)->beg + idx], item);
-}
-
-static inline VALUE *
-rary_ptr(VALUE ary)
-{
-    return &RARY(ary)->elements[RARY(ary)->beg];
-}
-
-static inline VALUE
-rary_entry(VALUE ary, long offset)
-{
-    const long n = RARY(ary)->len;
-    if (n == 0) {
-	return Qnil;
-    }
-    if (offset < 0) {
-	offset += n;
-    }
-    if (offset < 0 || n <= offset) {
-	return Qnil;
-    }
-    return rary_elt(ary, offset);
-}
-
-void rary_reserve(VALUE ary, size_t newlen);
-
-static inline void
-rary_store(VALUE ary, long idx, VALUE item)
-{
-    if (idx < 0) {
-        const long len = RARY(ary)->len;
-        idx += len;
-        if (idx < 0) {
-            rb_raise(rb_eIndexError, "index %ld out of array",
-                    idx - len);
-        }
-    }
-    else if (idx >= ARY_MAX_SIZE) {
-	rb_raise(rb_eIndexError, "index %ld too big", idx);
-    }
-
-    rary_modify(ary);
-    size_t uidx = (size_t)idx;
-    if (uidx >= RARY(ary)->len) {
-        rary_reserve(ary, uidx + 1);
-	size_t i;
-        for (i = RARY(ary)->len; i < uidx + 1; i++) {
-            rary_elt_set(ary, i, Qnil);
-        }
-        RARY(ary)->len = uidx + 1;
-    }
-    rary_elt_set(ary, uidx, item);
-}
-
-static inline void
-rary_push(VALUE ary, VALUE item)
-{
-    rary_reserve(ary, RARY(ary)->len + 1);
-    rary_elt_set(ary, RARY(ary)->len, item);
-    RARY(ary)->len++;
-}
-
-static inline void
-rb_ary_modify(VALUE ary)
-{
-    if (IS_RARY(ary)) {
-	rary_modify(ary);
-    }
-}
-
-static inline VALUE
-to_ary(VALUE ary)
-{
-    return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
-}
-
-VALUE rary_dup(VALUE ary, SEL sel);
-VALUE rary_clear(VALUE ary, SEL sel);
-VALUE rary_reverse_bang(VALUE ary, SEL sel);
-VALUE rary_includes(VALUE ary, SEL sel, VALUE item);
-VALUE rary_delete(VALUE ary, SEL sel, VALUE item);
-VALUE rary_delete_at(VALUE ary, SEL sel, VALUE pos);
-VALUE rary_pop(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_shift(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_plus(VALUE x, SEL sel, VALUE y);
-VALUE rary_push_m(VALUE ary, SEL sel, VALUE item);
-VALUE rary_concat_m(VALUE x, SEL sel, VALUE y);
-VALUE rary_last(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_unshift(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_each(VALUE ary, SEL sel);
-VALUE rary_sort(VALUE ary, SEL sel);
-VALUE rary_sort_bang(VALUE ary, SEL sel);
-VALUE rary_subseq(VALUE ary, long beg, long len);
-void rary_insert(VALUE ary, long idx, VALUE val);
-bool rary_eql_fast(rb_ary_t *ary1, rb_ary_t *ary2);
-
-// Shared implementations.
-VALUE rary_join(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_zip(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_transpose(VALUE ary, SEL sel);
-VALUE rary_fill(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_cmp(VALUE ary1, SEL sel, VALUE ary2);
-VALUE rary_assoc(VALUE ary, SEL sel, VALUE key);
-VALUE rary_rassoc(VALUE ary, SEL sel, VALUE value);
-VALUE rary_flatten(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_flatten_bang(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_product(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_combination(VALUE ary, SEL sel, VALUE num);
-VALUE rary_permutation(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_sample(VALUE ary, SEL sel, int argc, VALUE *argv);
-VALUE rary_diff(VALUE ary1, SEL sel, VALUE ary2);
-VALUE rary_and(VALUE ary1, SEL sel, VALUE ary2);
-VALUE rary_or(VALUE ary1, SEL sel, VALUE ary2);
-
-unsigned long rb_ary_hash(VALUE ary);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __ARRAY_H_

Deleted: MacRuby/trunk/auto_zone_1060.h
===================================================================
--- MacRuby/trunk/auto_zone_1060.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/auto_zone_1060.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,377 +0,0 @@
-/*
-    auto_zone.h
-    Automatic Garbage Collection.
-    Copyright (c) 2002-2010 Apple Inc. All rights reserved.
- */
-
-#ifndef __AUTO_ZONE__
-#define __AUTO_ZONE__
-
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <malloc/malloc.h>
-
-__BEGIN_DECLS
-
-typedef malloc_zone_t auto_zone_t;
-    // an auto zone carries a little more state but can be cast into a malloc_zone_t
-
-extern auto_zone_t *auto_zone_create(const char *name);
-    // create an garbage collected zone.  Can be (theoretically) done more than once.
-    // memory can be allocated by malloc_zone_malloc(result, size)
-    // by default, this memory must be malloc_zone_free(result, ptr) as well (or generic free())
-
-extern struct malloc_introspection_t auto_zone_introspection();
-    // access the zone introspection functions independent of any particular auto zone instance.
-    // this is used by tools to be able to introspect a zone in another process.
-    // the introspection functions returned are required to do version checking on the zone.
-
-#define AUTO_RETAINED_BLOCK_TYPE 0x100  /* zone enumerator returns only blocks with nonzero retain count */
-
-/*********  External (Global) Use counting  ************/
-
-extern void auto_zone_retain(auto_zone_t *zone, void *ptr);
-extern unsigned int auto_zone_release(auto_zone_t *zone, void *ptr);
-extern unsigned int auto_zone_retain_count(auto_zone_t *zone, const void *ptr);
-    // All pointer in the auto zone have an explicit retain count
-    // Objects will not be collected when the retain count is non-zero
-
-/*********  Object information  ************/
-
-extern const void *auto_zone_base_pointer(auto_zone_t *zone, const void *ptr);
-    // return base of interior pointer  (or NULL).
-extern boolean_t auto_zone_is_valid_pointer(auto_zone_t *zone, const void *ptr);
-    // is this a pointer to the base of an allocated block?
-extern size_t auto_zone_size(auto_zone_t *zone, const void *ptr);
-
-/*********  Write-barrier   ************/
-
-extern boolean_t auto_zone_set_write_barrier(auto_zone_t *zone, const void *dest, const void *new_value);
-    // must be used when an object field/slot in the auto zone is set to another object in the auto zone
-    // returns true if the dest was a valid target whose write-barrier was set
-
-boolean_t auto_zone_atomicCompareAndSwap(auto_zone_t *zone, void *existingValue, void *newValue, void *volatile *location, boolean_t isGlobal, boolean_t issueBarrier);
-    // Atomically update a location with a new GC value.  These use OSAtomicCompareAndSwapPtr{Barrier} with appropriate write-barrier interlocking logic.
-
-boolean_t auto_zone_atomicCompareAndSwapPtr(auto_zone_t *zone, void *existingValue, void *newValue, void *volatile *location, boolean_t issueBarrier);
-    // Atomically update a location with a new GC value.  These use OSAtomicCompareAndSwapPtr{Barrier} with appropriate write-barrier interlocking logic.
-    // This version checks location, and if it points into global storage, registers a root.
-
-extern void *auto_zone_write_barrier_memmove(auto_zone_t *zone, void *dst, const void *src, size_t size);
-    // copy content from an arbitrary source area to an arbitrary destination area
-    // marking write barrier if necessary
-
-/*********  Statistics  ************/
-
-typedef uint64_t auto_date_t;
-
-typedef struct {
-    auto_date_t     total_duration;
-    auto_date_t     scan_duration;
-    auto_date_t     enlivening_duration;
-    auto_date_t     finalize_duration;
-    auto_date_t     reclaim_duration;
-} auto_collection_durations_t;
-
-typedef struct {
-    /* Memory usage */
-    malloc_statistics_t malloc_statistics;
-    /* GC stats */
-    // version 0
-    uint32_t            version;            // set to 1 before calling
-    /* When there is an array, 0 stands for full collection, 1 for generational */
-    size_t              num_collections[2];
-    boolean_t           last_collection_was_generational;
-    size_t              bytes_in_use_after_last_collection[2];
-    size_t              bytes_allocated_after_last_collection[2];
-    size_t              bytes_freed_during_last_collection[2];
-    // durations
-    auto_collection_durations_t total[2];   // running total of each field
-    auto_collection_durations_t last[2];    // most recent result
-    auto_collection_durations_t maximum[2]; // on a per item basis, the max.  Thus, total != scan + finalize ...
-    // version 1 additions
-    size_t              thread_collections_total;
-    size_t              thread_blocks_recovered_total;
-    size_t              thread_bytes_recovered_total;
-} auto_statistics_t;
-
-extern void auto_zone_statistics(auto_zone_t *zone, auto_statistics_t *stats);  // set version to 0
-
-/*********  Garbage Collection   ************/
-
-enum {
-    AUTO_COLLECT_RATIO_COLLECTION        = (0 << 0), // run generational or full depending on applying AUTO_COLLECTION_RATIO
-    AUTO_COLLECT_GENERATIONAL_COLLECTION = (1 << 0), // collect young objects. Internal only.
-    AUTO_COLLECT_FULL_COLLECTION         = (2 << 0), // collect entire heap. Internal only.
-    AUTO_COLLECT_EXHAUSTIVE_COLLECTION   = (3 << 0), // run full collections until object count stabilizes.
-    AUTO_COLLECT_SYNCHRONOUS             = (1 << 2), // block caller until scanning is finished.
-    AUTO_COLLECT_IF_NEEDED               = (1 << 3), // only collect if AUTO_COLLECTION_THRESHOLD exceeded.
-};
-typedef uint32_t auto_collection_mode_t;
-
-enum {
-    AUTO_LOG_COLLECTIONS = (1 << 1),        // log whenever a collection occurs
-    AUTO_LOG_REGIONS = (1 << 4),            // log whenever a new region is allocated
-    AUTO_LOG_UNUSUAL = (1 << 5),            // log unusual circumstances
-    AUTO_LOG_WEAK = (1 << 6),               // log weak reference manipulation
-    AUTO_LOG_ALL = (~0u),
-    AUTO_LOG_NONE = 0
-};
-typedef uint32_t auto_log_mask_t;
-
-enum {
-    AUTO_HEAP_HOLES_SHRINKING       = 1,        // total size of holes is approaching zero
-    AUTO_HEAP_HOLES_EXHAUSTED       = 2,        // all holes exhausted, will use hitherto unused memory in "subzone"
-    AUTO_HEAP_SUBZONE_EXHAUSTED     = 3,        // will add subzone
-    AUTO_HEAP_REGION_EXHAUSTED      = 4,        // no more subzones available, need to add region
-    AUTO_HEAP_ARENA_EXHAUSTED       = 5,        // arena exhausted.  (64-bit only)
-};
-typedef uint32_t auto_heap_growth_info_t;
-
-typedef struct auto_zone_cursor *auto_zone_cursor_t;
-typedef void (*auto_zone_foreach_object_t) (auto_zone_cursor_t cursor, void (*op) (void *ptr, void *data), void* data);
-
-typedef struct {
-    uint32_t        version;                // reserved - 0 for now
-    void            (*batch_invalidate) (auto_zone_t *zone, auto_zone_foreach_object_t foreach, auto_zone_cursor_t cursor, size_t cursor_size);
-        // After unreached objects are found, collector calls this routine with internal context.
-        // Typically, one enters a try block to call back into the collector with a function pointer to be used to
-        // invalidate each object.  This amortizes the cost of the try block as well as allows the collector to use
-        // efficient contexts.
-    void            (*resurrect) (auto_zone_t *zone, void *ptr);
-        // Objects on the garbage list may be assigned into live objects in an attempted resurrection.  This is not allowed.
-        // This function, if supplied, is called for these objects to turn them into zombies.  The zombies may well hold
-        // pointers to other objects on the garbage list.  No attempt is made to preserved these objects beyond this collection.
-    const unsigned char* (*layout_for_address)(auto_zone_t *zone, void *ptr);
-        // The collector assumes that the first word of every "object" is a class pointer.
-        // For each class pointer discovered this function is called to return a layout, or NULL
-        // if the object should be scanned conservatively.
-        // The layout format is nibble pairs {skipcount, scancount}  XXX
-    const unsigned char* (*weak_layout_for_address)(auto_zone_t *zone, void *ptr);
-        // called once for each allocation encountered for which we don't know the weak layout
-        // the callee returns a weak layout for the allocation or NULL if the allocation has no weak references.
-    char*           (*name_for_address) (auto_zone_t *zone, vm_address_t base, vm_address_t offset);
-        // if supplied, is used during logging for errors such as resurrections
-    auto_log_mask_t log;
-        // set to auto_log_mask_t bits as desired
-    boolean_t       disable_generational;
-        // if true, ignores requests to do generational GC.
-    boolean_t       malloc_stack_logging;
-        // if true, logs allocations for malloc stack logging.  Automatically set if MallocStackLogging{NoCompact} is set
-    void            (*scan_external_callout)(void *context, void (*scanner)(void *context, void *start, void *end));
-        // an external function that is passed a memory scanner entry point
-        // if set, the function will be called during scanning so that the
-        // function the collector supplies will be called on all external memory that might
-        // have references.  Useful, for example, for green thread systems.
-        
-    void            (*will_grow)(auto_zone_t *zone, auto_heap_growth_info_t);
-        // collector calls this when it is about to grow the heap.  Advise if memory was returned to the collector, or not.
-        // if memory was returned, return 0 and the allocation will be attempted again, otherwise the heap will be grown.
-    size_t          collection_threshold;
-        // if_needed threshold: collector will initiate a collection after this number of bytes is allocated.
-    size_t          full_vs_gen_frequency;
-        // after full_vs_gen_frequency generational collections, a full collection will occur, if the if_needed threshold exceeded
-} auto_collection_control_t;
-
-extern auto_collection_control_t *auto_collection_parameters(auto_zone_t *zone);
-    // FIXME: API is to get the control struct and slam it
-    // sets a parameter that decides when callback gets called
-
-extern void auto_collector_disable(auto_zone_t *zone);
-extern void auto_collector_reenable(auto_zone_t *zone);
-    // these two functions turn off/on the collector
-    // default is on
-    // use with great care.
-
-extern boolean_t auto_zone_is_enabled(auto_zone_t *zone);
-extern boolean_t auto_zone_is_collecting(auto_zone_t *zone);
-
-extern void auto_collect(auto_zone_t *zone, auto_collection_mode_t mode, void *collection_context);
-    // request a collection.  By default, the collection will occur only on the main thread.
-
-extern void auto_collect_multithreaded(auto_zone_t *zone);
-    // start a dedicated thread to do collections. The invalidate callback will subsequently be called from this new thread.
-
-/*********  Object layout for compaction    ************/
-
-// For compaction of the zone, we need to know for sure where are the pointers
-// each object is assumed to have a class pointer as word 0 (the "isa")
-// This layout information is also used for collection (for "tracing" pointers)
-
-// Exact layout knowledge is also important for ignoring weak references
-
-enum {
-    AUTO_TYPE_UNKNOWN = -1,                                 // this is an error value
-    AUTO_UNSCANNED = 1,
-    AUTO_OBJECT = 2,
-    AUTO_MEMORY_SCANNED = 0,                                // holds conservatively scanned pointers
-    AUTO_MEMORY_UNSCANNED = AUTO_UNSCANNED,                 // holds unscanned memory (bits)
-    AUTO_OBJECT_SCANNED = AUTO_OBJECT,                      // first word is 'isa', may have 'exact' layout info elsewhere
-    AUTO_OBJECT_UNSCANNED = AUTO_OBJECT | AUTO_UNSCANNED,   // first word is 'isa', good for bits or auto_zone_retain'ed items
-};
-typedef int auto_memory_type_t;
-
-extern auto_memory_type_t auto_zone_get_layout_type(auto_zone_t *zone, void *ptr);
-
-
-extern void* auto_zone_allocate_object(auto_zone_t *zone, size_t size, auto_memory_type_t type, boolean_t initial_refcount_to_one, boolean_t clear);
-
-// Create copy of AUTO_MEMORY object preserving "scanned" attribute
-// If not auto memory then create unscanned memory copy
-void *auto_zone_create_copy(auto_zone_t *zone, void *ptr);
-
-
-extern void auto_zone_register_thread(auto_zone_t *zone);
-
-extern void auto_zone_unregister_thread(auto_zone_t *zone);
-
-extern void auto_zone_assert_thread_registered(auto_zone_t *zone);
-
-extern void auto_zone_register_datasegment(auto_zone_t *zone, void *address, size_t size);
-extern void auto_zone_unregister_datasegment(auto_zone_t *zone, void *address, size_t size);
-
-
-// Weak references
-
-// The collector maintains a weak reference system.
-// Essentially, locations in which references are stored are registered along with the reference itself.
-// The location should not be within scanned GC memory.
-// After a collection, before finalization, all registered locations are examined and any containing references to
-// newly discovered garbage will be "zeroed" and the registration cancelled.
-//
-// Reading values from locations must be done through the weak read function because there is a race with such
-// reads and the collector having just determined that that value read is in fact otherwise garbage.
-//
-// The address of a callback block may be supplied optionally.  If supplied, if the location is zeroed, the callback
-// block is queued to be called later with the arguments supplied in the callback block.  The same callback block both
-// can and should be used as an aggregation point.  A table of weak locations could supply each registration with the
-// same pointer to a callback block that will call that table if items are zerod.  The callbacks are made before
-// finalization.  Note that only thread-safe operations may be performed by this callback.
-//
-// It is important to cancel all registrations before deallocating the memory containing locations or callback blocks.
-// Cancellation is done by calling the registration function with a NULL "reference" parameter for that location.
-
-typedef struct auto_weak_callback_block {
-    struct auto_weak_callback_block *next;              // must be set to zero before first use
-    void (*callback_function)(void *arg1, void *arg2);
-    void *arg1;
-    void *arg2;
-} auto_weak_callback_block_t;
-
-extern void auto_assign_weak_reference(auto_zone_t *zone, const void *value, const void **location, auto_weak_callback_block_t *block);
-
-// Read a weak-reference, informing the collector that it is now strongly referenced.
-extern void* auto_read_weak_reference(auto_zone_t *zone, void **referrer);
-
-extern void auto_zone_add_root(auto_zone_t *zone, void *address_of_root_ptr, void *value);
-extern void auto_zone_remove_root(auto_zone_t *zone, void *address_of_root_ptr);
-
-extern void auto_zone_root_write_barrier(auto_zone_t *zone, void *address_of_possible_root_ptr, void *value);
-
-
-// Associative references.
-
-// This informs the collector that an object A wishes to associate one or more secondary objects with object A's lifetime.
-// This can be used to implement GC-safe associations that will neither cause uncollectable cycles, nor suffer the limitations
-// of weak references.
-
-extern void auto_zone_set_associative_ref(auto_zone_t *zone, void *object, void *key, void *value);
-extern void *auto_zone_get_associative_ref(auto_zone_t *zone, void *object,  void *key);
-extern void auto_zone_erase_associative_refs(auto_zone_t *zone, void *object);
-
-/***** SPI ******/
-    
-
-
-extern void auto_zone_start_monitor(boolean_t force);
-extern void auto_zone_set_class_list(int (*get_class_list)(void **buffer, int count));
-extern boolean_t auto_zone_is_finalized(auto_zone_t *zone, const void *ptr);
-extern void auto_zone_stats(void); // write stats to stdout
-extern void auto_zone_write_stats(FILE *f); // write stats to the given stream
-extern char *auto_zone_stats_string(); // return a char * containing the stats string, which should be free()'d
-extern void auto_zone_set_nofinalize(auto_zone_t *zone, void *ptr);
-extern void auto_zone_set_unscanned(auto_zone_t *zone, void *ptr);
-extern void auto_zone_clear_stack(auto_zone_t *zone, unsigned long options);
-
-// Reference count logging support for ObjectAlloc et. al.
-
-enum {
-    AUTO_RETAIN_EVENT = 14,
-    AUTO_RELEASE_EVENT = 15
-};
-extern void (*__auto_reference_logger)(uint32_t eventtype, void *ptr, uintptr_t data);
-
-
-// Reference tracing
-
-// referrer_base[referrer_offset]  ->  referent
-typedef struct 
-{
-    vm_address_t referent;
-    vm_address_t referrer_base;
-    intptr_t     referrer_offset;
-} auto_reference_t;
-
-typedef void (*auto_reference_recorder_t)(auto_zone_t *zone, void *ctx, 
-                                          auto_reference_t reference);
-
-extern void auto_enumerate_references(auto_zone_t *zone, void *referent, 
-                                      auto_reference_recorder_t callback, 
-                                      void *stack_bottom, void *ctx);
-
-
-void **auto_weak_find_first_referrer(auto_zone_t *zone, void **location, unsigned long count);
-
-
-/************ DEPRECATED ***********/
-    
-extern auto_zone_t *auto_zone(void);
-    // returns a pointer to the first garbage collected zone created.
-extern unsigned auto_zone_touched_size(auto_zone_t *zone);
-    // conservative (upper bound) on memory touched by the allocator itself.
-
-extern double auto_zone_utilization(auto_zone_t *zone);
-    // conservative measure of utilization of allocator touched memory.
-    
-
-/************* EXPERIMENTAL *********/
-#ifdef __BLOCKS__
-
-typedef void (^auto_zone_stack_dump)(const void *base, unsigned long byte_size);
-typedef void (^auto_zone_register_dump)(const void *base, unsigned long byte_size);
-typedef void (^auto_zone_node_dump)(const void *address, unsigned long size, unsigned int layout, unsigned long refcount);
-typedef void (^auto_zone_root_dump)(const void **address);
-typedef void (^auto_zone_weak_dump)(const void **address, const void *item);
-
-// Instruments.app utility; causes significant disruption.
-// This is SPI for Apple's use only.  Can and likely will change without regard to 3rd party use.
-void auto_zone_dump(auto_zone_t *zone,
-            auto_zone_stack_dump stack_dump,
-            auto_zone_register_dump register_dump,
-            auto_zone_node_dump thread_local_node_dump, // unsupported
-            auto_zone_root_dump root_dump,
-            auto_zone_node_dump global_node_dump,
-            auto_zone_weak_dump weak_dump
-);
-
-#endif
-
-enum {
-    auto_is_not_auto  =    0,
-    auto_is_auto      =    (1 << 1),   // always on for a start of a node
-    auto_is_local     =    (1 << 2),   // is/was node local
-};
-
-typedef int auto_probe_results_t;
-
-// Instruments.app utility; causes significant disruption.
-// This is SPI for Apple's use only.  Can and likely will change without regard to 3rd party use.
-auto_probe_results_t auto_zone_probe_unlocked(auto_zone_t *zone, void *address);
-#ifdef __BLOCKS__
-void auto_zone_scan_exact(auto_zone_t *zone, void *address, void (^callback)(void *base, unsigned long byte_offset, void *candidate));
-#endif
-
-__END_DECLS
-
-#endif /* __AUTO_ZONE__ */

Deleted: MacRuby/trunk/b.rb
===================================================================
--- MacRuby/trunk/b.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/b.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,21 +0,0 @@
-def bench(e, options)
-  puts e
-  ['./miniruby', 'ruby1.9'].each do |r|
-    puts `#{r} -v`.strip
-    line = File.exist?(e) ? "#{r} \"#{e}\"" : "#{r} -e \"#{e}\""
-    n = options.include?('--no-rehearsal') ? 1 : 3
-    n.times do 
-      t = Time.now
-      v = system(line) ? Time.now - t : nil
-      puts '    ' + v.to_s
-    end
-  end
-end
-options = []
-expressions = []
-while e = ARGV.shift
-  a = /^-/.match(e) ? options : expressions
-  a << e
-end
-expressions.map! { |e| e.gsub(/"/, '\"') }
-expressions.each { |e| bench(e, options) }

Deleted: MacRuby/trunk/bignum.c
===================================================================
--- MacRuby/trunk/bignum.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bignum.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2876 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-
-#include "objc.h"
-#include "encoding.h"
-
-#include <math.h>
-#include <float.h>
-#include <ctype.h>
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-VALUE rb_cBignum;
-
-#if defined __MINGW32__
-#define USHORT _USHORT
-#endif
-
-#define BDIGITS(x) (RBIGNUM_DIGITS(x))
-#define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
-#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
-#define DIGSPERLONG ((unsigned int)(SIZEOF_LONG/SIZEOF_BDIGITS))
-#if HAVE_LONG_LONG
-# define DIGSPERLL ((unsigned int)(SIZEOF_LONG_LONG/SIZEOF_BDIGITS))
-#endif
-#define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
-#define BIGDN(x) RSHIFT(x,BITSPERDIG)
-#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
-#define BDIGMAX ((BDIGIT)-1)
-
-#define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
-		     (BDIGITS(x)[0] == 0 && \
-		      (RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
-
-static int
-bigzero_p(VALUE x)
-{
-    long i;
-    for (i = RBIGNUM_LEN(x) - 1; 0 <= i; i--) {
-	if (BDIGITS(x)[i]) return 0;
-    }
-    return 1;
-}
-
-int
-rb_bigzero_p(VALUE x)
-{
-    return BIGZEROP(x);
-}
-
-int
-rb_cmpint(VALUE val, VALUE a, VALUE b)
-{
-    if (NIL_P(val)) {
-	rb_cmperr(a, b);
-    }
-    if (FIXNUM_P(val)) return FIX2INT(val);
-    if (TYPE(val) == T_BIGNUM) {
-	if (BIGZEROP(val)) return 0;
-	if (RBIGNUM_SIGN(val)) return 1;
-	return -1;
-    }
-    if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
-    if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
-    return 0;
-}
-
-#define RBIGNUM_SET_LEN(b,l) \
-  ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
-   (RBASIC(b)->flags = (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
-      ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
-   (RBIGNUM(b)->as.heap.len = (l)))
-
-static void
-rb_big_realloc(VALUE big, long len)
-{
-    BDIGIT *ds;
-    if (RBASIC(big)->flags & RBIGNUM_EMBED_FLAG) {
-	if (RBIGNUM_EMBED_LEN_MAX < len) {
-	    ds = ALLOC_N(BDIGIT, len);
-	    MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
-	    RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
-	    GC_WB(&RBIGNUM(big)->as.heap.digits, ds);
-	    RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
-	}
-    }
-    else {
-	if (len <= RBIGNUM_EMBED_LEN_MAX) {
-	    ds = RBIGNUM(big)->as.heap.digits;
-	    RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
-	    RBIGNUM_SET_LEN(big, len);
-	    if (ds) {
-		MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
-		xfree(ds);
-	    }
-	}
-	else {
-	    if (RBIGNUM_LEN(big) == 0) {
-		GC_WB(&RBIGNUM(big)->as.heap.digits, ALLOC_N(BDIGIT, len));
-	    }
-	    else {
-		void *tmp = ruby_xrealloc(RBIGNUM(big)->as.heap.digits, sizeof(BDIGIT) * len);
-		if (tmp != RBIGNUM(big)->as.heap.digits) {
-		    GC_WB(&RBIGNUM(big)->as.heap.digits, tmp);
-		}
-	    }
-	}
-    }
-}
-
-void
-rb_big_resize(VALUE big, long len)
-{
-    rb_big_realloc(big, len);
-    RBIGNUM_SET_LEN(big, len);
-}
-
-static VALUE
-bignew_1(VALUE klass, long len, int sign)
-{
-    NEWOBJ(big, struct RBignum);
-    OBJSETUP(big, klass, T_BIGNUM);
-    RBIGNUM_SET_SIGN(big, sign?1:0);
-    if (len <= RBIGNUM_EMBED_LEN_MAX) {
-	RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
-	RBIGNUM_SET_LEN(big, len);
-    }
-    else {
-	rb_big_resize((VALUE)big, len);
-    }
-
-    return (VALUE)big;
-}
-
-#define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
-
-VALUE
-rb_big_clone(VALUE x)
-{
-    VALUE z = bignew_1(CLASS_OF(x), RBIGNUM_LEN(x), RBIGNUM_SIGN(x));
-
-    MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM_LEN(x));
-    return z;
-}
-
-/* modify a bignum by 2's complement */
-static void
-get2comp(VALUE x)
-{
-    long i = RBIGNUM_LEN(x);
-    BDIGIT *ds = BDIGITS(x);
-    BDIGIT_DBL num;
-
-    if (!i) return;
-    while (i--) ds[i] = ~ds[i];
-    i = 0; num = 1;
-    do {
-	num += ds[i];
-	ds[i++] = BIGLO(num);
-	num = BIGDN(num);
-    } while (i < RBIGNUM_LEN(x));
-    if (num != 0) {
-	rb_big_resize(x, RBIGNUM_LEN(x)+1);
-	ds = BDIGITS(x);
-	ds[RBIGNUM_LEN(x)-1] = 1;
-    }
-}
-
-void
-rb_big_2comp(VALUE x)			/* get 2's complement */
-{
-    get2comp(x);
-}
-
-static VALUE
-bigtrunc(VALUE x)
-{
-    long len = RBIGNUM_LEN(x);
-    BDIGIT *ds = BDIGITS(x);
-
-    if (len == 0) return x;
-    while (--len && !ds[len]);
-    rb_big_resize(x, len+1);
-    return x;
-}
-
-static VALUE
-bigfixize(VALUE x)
-{
-    long len = RBIGNUM_LEN(x);
-    BDIGIT *ds = BDIGITS(x);
-
-    if (len*SIZEOF_BDIGITS <= sizeof(long)) {
-	long num = 0;
-	while (len--) {
-	    num = BIGUP(num) + ds[len];
-	}
-	if (num >= 0) {
-	    if (RBIGNUM_SIGN(x)) {
-		if (POSFIXABLE(num)) return LONG2FIX(num);
-	    }
-	    else {
-		if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
-	    }
-	}
-    }
-    return x;
-}
-
-static VALUE
-bignorm(VALUE x)
-{
-    if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
-	x = bigfixize(bigtrunc(x));
-    }
-    return x;
-}
-
-VALUE
-rb_big_norm(VALUE x)
-{
-    return bignorm(x);
-}
-
-VALUE
-rb_uint2big(VALUE n)
-{
-    BDIGIT_DBL num = n;
-    long i = 0;
-    BDIGIT *digits;
-    VALUE big;
-
-    big = bignew(DIGSPERLONG, 1);
-    digits = BDIGITS(big);
-    while (i < DIGSPERLONG) {
-	digits[i++] = BIGLO(num);
-	num = BIGDN(num);
-    }
-
-    i = DIGSPERLONG;
-    while (--i && !digits[i]) ;
-    RBIGNUM_SET_LEN(big, i+1);
-    return big;
-}
-
-VALUE
-rb_int2big(SIGNED_VALUE n)
-{
-    long neg = 0;
-    VALUE big;
-
-    if (n < 0) {
-	n = -n;
-	neg = 1;
-    }
-    big = rb_uint2big(n);
-    if (neg) {
-	RBIGNUM_SET_SIGN(big, 0);
-    }
-    return big;
-}
-
-#ifdef HAVE_LONG_LONG
-
-void
-rb_quad_pack(char *buf, VALUE val)
-{
-    LONG_LONG q;
-
-    val = rb_to_int(val);
-    if (FIXNUM_P(val)) {
-	q = FIX2LONG(val);
-    }
-    else {
-	long len = RBIGNUM_LEN(val);
-	BDIGIT *ds;
-
-	if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
-	    len = SIZEOF_LONG_LONG/SIZEOF_BDIGITS;
-	}
-	ds = BDIGITS(val);
-	q = 0;
-	while (len--) {
-	    q = BIGUP(q);
-	    q += ds[len];
-	}
-	if (!RBIGNUM_SIGN(val)) q = -q;
-    }
-    memcpy(buf, (char*)&q, SIZEOF_LONG_LONG);
-}
-
-VALUE
-rb_quad_unpack(const char *buf, int sign)
-{
-    BDIGIT_DBL q;
-    long neg = 0;
-    long i;
-    BDIGIT *digits;
-    VALUE big;
-
-    memcpy(&q, buf, SIZEOF_LONG_LONG);
-    if (sign) {
-	if (FIXABLE((LONG_LONG)q)) return LONG2FIX((LONG_LONG)q);
-	if ((LONG_LONG)q < 0) {
-	    q = -(LONG_LONG)q;
-	    neg = 1;
-	}
-    }
-    else {
-	if (POSFIXABLE(q)) return LONG2FIX(q);
-    }
-
-    i = 0;
-    big = bignew(DIGSPERLL, 1);
-    digits = BDIGITS(big);
-    while (i < DIGSPERLL) {
-	digits[i++] = BIGLO(q);
-	q = BIGDN(q);
-    }
-
-    i = DIGSPERLL;
-    while (i-- && !digits[i]) ;
-    RBIGNUM_SET_LEN(big, i+1);
-
-    if (neg) {
-	RBIGNUM_SET_SIGN(big, 0);
-    }
-    return bignorm(big);
-}
-
-#else
-
-#define QUAD_SIZE 8
-
-void
-rb_quad_pack(char *buf, VALUE val)
-{
-    long len;
-
-    memset(buf, 0, QUAD_SIZE);
-    val = rb_to_int(val);
-    if (FIXNUM_P(val)) {
-	val = rb_int2big(FIX2LONG(val));
-    }
-    len = RBIGNUM_LEN(val) * SIZEOF_BDIGITS;
-    if (len > QUAD_SIZE) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
-    }
-    memcpy(buf, (char*)BDIGITS(val), len);
-    if (!RBIGNUM_SIGN(val)) {
-	len = QUAD_SIZE;
-	while (len--) {
-	    *buf = ~*buf;
-	    buf++;
-	}
-    }
-}
-
-#define BNEG(b) (RSHIFT(((BDIGIT*)b)[QUAD_SIZE/SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
-
-VALUE
-rb_quad_unpack(const char *buf, int sign)
-{
-    VALUE big = bignew(QUAD_SIZE/SIZEOF_BDIGITS, 1);
-
-    memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
-    if (sign && BNEG(buf)) {
-	long len = QUAD_SIZE;
-	char *tmp = (char*)BDIGITS(big);
-
-	RBIGNUM_SET_SIGN(big, 0);
-	while (len--) {
-	    *tmp = ~*tmp;
-	    tmp++;
-	}
-    }
-
-    return bignorm(big);
-}
-
-#endif
-
-VALUE
-rb_cstr_to_inum(const char *str, int base, int badcheck)
-{
-    const char *s = str;
-    char *end;
-    char sign = 1, nondigit = 0;
-    int c;
-    BDIGIT_DBL num;
-    long len, blen = 1;
-    long i;
-    VALUE z;
-    BDIGIT *zds;
-
-#define conv_digit(c) \
-    (!ISASCII(c) ? -1 : \
-     ISDIGIT(c) ? ((c) - '0') : \
-     ISLOWER(c) ? ((c) - 'a' + 10) : \
-     ISUPPER(c) ? ((c) - 'A' + 10) : \
-     -1)
-
-    if (!str) {
-	if (badcheck) goto bad;
-	return INT2FIX(0);
-    }
-    while (ISSPACE(*str)) str++;
-
-    if (str[0] == '+') {
-	str++;
-    }
-    else if (str[0] == '-') {
-	str++;
-	sign = 0;
-    }
-    if (str[0] == '+' || str[0] == '-') {
-	if (badcheck) goto bad;
-	return INT2FIX(0);
-    }
-    if (base <= 0) {
-	if (str[0] == '0') {
-	    switch (str[1]) {
-	      case 'x': case 'X':
-		base = 16;
-		break;
-	      case 'b': case 'B':
-		base = 2;
-		break;
-	      case 'o': case 'O':
-		base = 8;
-		break;
-	      case 'd': case 'D':
-		base = 10;
-		break;
-	      default:
-		base = 8;
-	    }
-	}
-	else if (base < -1) {
-	    base = -base;
-	}
-	else {
-	    base = 10;
-	}
-    }
-    switch (base) {
-      case 2:
-	len = 1;
-	if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
-	    str += 2;
-	}
-	break;
-      case 3:
-	len = 2;
-	break;
-      case 8:
-	if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
-	    str += 2;
-	}
-      case 4: case 5: case 6: case 7:
-	len = 3;
-	break;
-      case 10:
-	if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
-	    str += 2;
-	}
-      case 9: case 11: case 12: case 13: case 14: case 15:
-	len = 4;
-	break;
-      case 16:
-	len = 4;
-	if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
-	    str += 2;
-	}
-	break;
-      default:
-	if (base < 2 || 36 < base) {
-	    rb_raise(rb_eArgError, "invalid radix %d", base);
-	}
-	if (base <= 32) {
-	    len = 5;
-	}
-	else {
-	    len = 6;
-	}
-	break;
-    }
-    if (*str == '0') {		/* squeeze preceding 0s */
-	int us = 0;
-	while ((c = *++str) == '0' || c == '_') {
-	    if (c == '_') {
-		if (++us >= 2)
-		    break;
-	    } else
-		us = 0;
-	}
-	if (!(c = *str) || ISSPACE(c)) --str;
-    }
-    c = *str;
-    c = conv_digit(c);
-    if (c < 0 || c >= base) {
-	if (badcheck) goto bad;
-	return INT2FIX(0);
-    }
-    len *= strlen(str)*sizeof(char);
-
-    if (len <= (sizeof(long)*CHAR_BIT)) {
-	unsigned long val = STRTOUL(str, &end, base);
-
-	if (str < end && *end == '_') goto bigparse;
-	if (badcheck) {
-	    if (end == str) goto bad; /* no number */
-	    while (*end && ISSPACE(*end)) end++;
-	    if (*end) goto bad;	      /* trailing garbage */
-	}
-
-	if (POSFIXABLE(val)) {
-	    if (sign) return LONG2FIX(val);
-	    else {
-		long result = -(long)val;
-		return LONG2FIX(result);
-	    }
-	}
-	else {
-	    VALUE big = rb_uint2big(val);
-	    RBIGNUM_SET_SIGN(big, sign);
-	    return bignorm(big);
-	}
-    }
-  bigparse:
-    len = (len/BITSPERDIG)+1;
-    if (badcheck && *str == '_') goto bad;
-
-    z = bignew(len, sign);
-    zds = BDIGITS(z);
-    for (i=len;i--;) zds[i]=0;
-    while ((c = *str++) != 0) {
-	if (c == '_') {
-	    if (nondigit) {
-		if (badcheck) goto bad;
-		break;
-	    }
-	    nondigit = c;
-	    continue;
-	}
-	else if ((c = conv_digit(c)) < 0) {
-	    break;
-	}
-	if (c >= base) break;
-	nondigit = 0;
-	i = 0;
-	num = c;
-	for (;;) {
-	    while (i<blen) {
-		num += (BDIGIT_DBL)zds[i]*base;
-		zds[i++] = BIGLO(num);
-		num = BIGDN(num);
-	    }
-	    if (num) {
-		blen++;
-		continue;
-	    }
-	    break;
-	}
-    }
-    if (badcheck) {
-	str--;
-	if (s+1 < str && str[-1] == '_') goto bad;
-	while (*str && ISSPACE(*str)) str++;
-	if (*str) {
-	  bad:
-	    rb_invalid_str(s, "Integer");
-	}
-    }
-
-    return bignorm(z);
-}
-
-VALUE
-rb_str_to_inum(VALUE str, int base, int badcheck)
-{
-    const char *s;
-    long len;
-
-    StringValue(str);
-    str_check_ascii_compatible(str);
-    if (badcheck) {
-	s = StringValueCStr(str);
-    }
-    else {
-	s = RSTRING_PTR(str);
-    }
-    if (s) {
-	len = RSTRING_LEN(str);
-	if (s[len]) {		/* no sentinel somehow */
-	    char *p = ALLOCA_N(char, len+1);
-
-	    MEMCPY(p, s, char, len);
-	    p[len] = '\0';
-	    s = p;
-	}
-    }
-    return rb_cstr_to_inum(s, base, badcheck);
-}
-
-#if HAVE_LONG_LONG
-
-VALUE
-rb_ull2big(unsigned long long n)
-{
-    BDIGIT_DBL num = n;
-    long i = 0;
-    BDIGIT *digits;
-    VALUE big;
-
-    big = bignew(DIGSPERLL, 1);
-    digits = BDIGITS(big);
-    while (i < DIGSPERLL) {
-	digits[i++] = BIGLO(num);
-	num = BIGDN(num);
-    }
-
-    i = DIGSPERLL;
-    while (i-- && !digits[i]) ;
-    RBIGNUM_SET_LEN(big, i+1);
-    return big;
-}
-
-VALUE
-rb_ll2big(long long n)
-{
-    long neg = 0;
-    VALUE big;
-
-    if (n < 0) {
-	n = -n;
-	neg = 1;
-    }
-    big = rb_ull2big(n);
-    if (neg) {
-	RBIGNUM_SET_SIGN(big, 0);
-    }
-    return big;
-}
-
-#endif  /* HAVE_LONG_LONG */
-
-VALUE
-rb_cstr2inum(const char *str, int base)
-{
-    return rb_cstr_to_inum(str, base, base==0);
-}
-
-VALUE
-rb_str2inum(VALUE str, int base)
-{
-    return rb_str_to_inum(str, base, base==0);
-}
-
-VALUE
-rb_bignum_new_retained(const char *str)
-{
-    VALUE v = rb_cstr2inum(str, 10);
-    GC_RETAIN(v);
-    return v;
-}
-
-VALUE
-rb_big_new(long len, int sign)
-{
-    return bignew(len, sign != 0);
-}
-
-const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-
-static VALUE bigsqr(VALUE x);
-static void bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp);
-
-#define POW2_P(x) (((x)&((x)-1))==0)
-
-static inline int
-ones(register unsigned long x)
-{
-#if SIZEOF_LONG == 8
-# define MASK_55 0x5555555555555555UL
-# define MASK_33 0x3333333333333333UL
-# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
-#else
-# define MASK_55 0x55555555UL
-# define MASK_33 0x33333333UL
-# define MASK_0f 0x0f0f0f0fUL
-#endif
-    x -= (x >> 1) & MASK_55;
-    x = ((x >> 2) & MASK_33) + (x & MASK_33);
-    x = ((x >> 4) + x) & MASK_0f;
-    x += (x >> 8);
-    x += (x >> 16);
-#if SIZEOF_LONG == 8
-    x += (x >> 32);
-#endif
-    return (int)(x & 0x7f);
-#undef MASK_0f
-#undef MASK_33
-#undef MASK_55
-}
-
-static inline unsigned long
-next_pow2(register unsigned long x)
-{
-    x |= x >> 1;
-    x |= x >> 2;
-    x |= x >> 4;
-    x |= x >> 8;
-    x |= x >> 16;
-#if SIZEOF_LONG == 8
-    x |= x >> 32;
-#endif
-    return x + 1;
-}
-
-static inline int
-floor_log2(register unsigned long x)
-{
-    x |= x >> 1;
-    x |= x >> 2;
-    x |= x >> 4;
-    x |= x >> 8;
-    x |= x >> 16;
-#if SIZEOF_LONG == 8
-    x |= x >> 32;
-#endif
-    return (int)ones(x) - 1;
-}
-
-static inline int
-ceil_log2(register unsigned long x)
-{
-    return floor_log2(x) + !POW2_P(x);
-}
-
-#define LOG2_KARATSUBA_DIGITS 7
-#define KARATSUBA_DIGITS (1L<<LOG2_KARATSUBA_DIGITS)
-#define MAX_BIG2STR_TABLE_ENTRIES 64
-
-static VALUE big2str_power_cache[35][MAX_BIG2STR_TABLE_ENTRIES];
-
-static void
-power_cache_init(void)
-{
-    int i, j;
-    for (i = 0; i < 35; ++i) {
-	for (j = 0; j < MAX_BIG2STR_TABLE_ENTRIES; ++j) {
-	    big2str_power_cache[i][j] = Qnil;
-	}
-    }
-}
-
-static inline VALUE
-power_cache_get_power0(int base, int i)
-{
-    if (NIL_P(big2str_power_cache[base - 2][i])) {
-	big2str_power_cache[base - 2][i] =
-	    i == 0 ? rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS))
-		   : bigsqr(power_cache_get_power0(base, i - 1));
-	GC_RETAIN(big2str_power_cache[base - 2][i]);
-    }
-    return big2str_power_cache[base - 2][i];
-}
-
-static VALUE
-power_cache_get_power(int base, long n1, long* m1)
-{
-    long i, j, m;
-    VALUE t;
-
-    if (n1 <= KARATSUBA_DIGITS)
-	rb_bug("n1 > KARATSUBA_DIGITS");
-
-    m = ceil_log2(n1);
-    if (m1) *m1 = 1 << m;
-    i = m - LOG2_KARATSUBA_DIGITS;
-    if (i >= MAX_BIG2STR_TABLE_ENTRIES)
-	i = MAX_BIG2STR_TABLE_ENTRIES - 1;
-    t = power_cache_get_power0(base, i);
-
-    j = KARATSUBA_DIGITS*(1 << i);
-    while (n1 > j) {
-	t = bigsqr(t);
-	j *= 2;
-    }
-    return t;
-}
-
-/* big2str_muraken_find_n1
- *
- * Let a natural number x is given by:
- * x = 2^0 * x_0 + 2^1 * x_1 + ... + 2^(B*n_0 - 1) * x_{B*n_0 - 1},
- * where B is BITSPERDIG (i.e. BDIGITS*CHAR_BIT) and n_0 is
- * RBIGNUM_LEN(x).
- *
- * Now, we assume n_1 = min_n \{ n | 2^(B*n_0/2) <= b_1^(n_1) \}, so
- * it is realized that 2^(B*n_0) <= {b_1}^{2*n_1}, where b_1 is a
- * given radix number. And then, we have n_1 <= (B*n_0) /
- * (2*log_2(b_1)), therefore n_1 is given by ceil((B*n_0) /
- * (2*log_2(b_1))).
- */
-static long
-big2str_find_n1(VALUE x, int base)
-{
-    static const double log_2[] = {
-	1.0,              1.58496250072116, 2.0,
-	2.32192809488736, 2.58496250072116, 2.8073549220576,
-	3.0,              3.16992500144231, 3.32192809488736,
-	3.4594316186373,  3.58496250072116, 3.70043971814109,
-	3.8073549220576,  3.90689059560852, 4.0,
-	4.08746284125034, 4.16992500144231, 4.24792751344359,
-	4.32192809488736, 4.39231742277876, 4.4594316186373,
-	4.52356195605701, 4.58496250072116, 4.64385618977472,
-	4.70043971814109, 4.75488750216347, 4.8073549220576,
-	4.85798099512757, 4.90689059560852, 4.95419631038688,
-	5.0,              5.04439411935845, 5.08746284125034,
-	5.12928301694497, 5.16992500144231
-    };
-    long bits;
-
-    if (base < 2 || 36 < base)
-	rb_bug("invalid radix %d", base);
-
-    if (FIXNUM_P(x)) {
-	bits = (SIZEOF_LONG*CHAR_BIT - 1)/2 + 1;
-    }
-    else if (BIGZEROP(x)) {
-	return 0;
-    }
-    else if (RBIGNUM_LEN(x) >= LONG_MAX/BITSPERDIG) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
-    }
-    else {
-	bits = BITSPERDIG*RBIGNUM_LEN(x);
-    }
-
-    return (long)ceil(bits/log_2[base - 2]);
-}
-
-static long
-big2str_orig(VALUE x, int base, char* ptr, long len, long hbase, int trim)
-{
-    long i = RBIGNUM_LEN(x), j = len;
-    BDIGIT* ds = BDIGITS(x);
-
-    while (i && j > 0) {
-	long k = i;
-	BDIGIT_DBL num = 0;
-
-	while (k--) {               /* x / hbase */
-	    num = BIGUP(num) + ds[k];
-	    ds[k] = (BDIGIT)(num / hbase);
-	    num %= hbase;
-	}
-	if (trim && ds[i-1] == 0) i--;
-#if defined(__LP64__) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
-	k = SIZEOF_BDIGITS/2;
-#else
-	k = SIZEOF_BDIGITS;
-#endif
-	while (k--) {
-	    ptr[--j] = ruby_digitmap[num % base];
-	    num /= base;
-	    if (j <= 0) break;
-	    if (trim && i == 0 && num == 0) break;
-	}
-    }
-    if (trim) {
-	while (j < len && ptr[j] == '0') j++;
-	MEMMOVE(ptr, ptr + j, char, len - j);
-	len -= j;
-    }
-    return len;
-}
-
-static long
-big2str_karatsuba(VALUE x, int base, char* ptr,
-		  long n1, long len, long hbase, int trim)
-{
-    long lh, ll, m1;
-    VALUE b, q, r;
-
-    if (FIXNUM_P(x)) {
-        VALUE str = rb_fix2str(x, base);
-        const char* str_ptr = RSTRING_PTR(str);
-        long str_len = RSTRING_LEN(str);
-        if (trim) {
-            if (FIX2INT(x) == 0) return 0;
-            MEMCPY(ptr, str_ptr, char, str_len);
-            return str_len;
-        }
-        else {
-            memset(ptr, '0', len - str_len);
-            MEMCPY(ptr + len - str_len, str_ptr, char, str_len);
-            return len;
-        }
-    }
-    if (BIGZEROP(x)) {
-	if (trim) return 0;
-	else {
-	    memset(ptr, '0', len);
-	    return len;
-	}
-    }
-
-    if (n1 <= KARATSUBA_DIGITS) {
-	return big2str_orig(x, base, ptr, len, hbase, trim);
-    }
-
-    b = power_cache_get_power(base, n1, &m1);
-    bigdivmod(x, b, &q, &r);
-    lh = big2str_karatsuba(q, base, ptr,      (len - m1)/2,
-			   len - m1, hbase, trim);
-    ll = big2str_karatsuba(r, base, ptr + lh, m1/2,
-			   m1,       hbase, !lh && trim);
-
-    return lh + ll;
-}
-
-VALUE
-rb_big2str0(VALUE x, int base, int trim)
-{
-    int off;
-    VALUE xx;
-    long n1, n2, len, hbase;
-    char* ptr;
-
-    if (FIXNUM_P(x)) {
-	return rb_fix2str(x, base);
-    }
-    if (BIGZEROP(x)) {
-	return rb_usascii_str_new2("0");
-    }
-
-    if (base < 2 || 36 < base)
-	rb_raise(rb_eArgError, "invalid radix %d", base);
-
-    n2 = big2str_find_n1(x, base);
-    n1 = (n2 + 1) / 2;
-    ptr = (char *)alloca(n2 + 1); /* plus one for sign */
-    ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-';
-
-    hbase = base*base;
-#if SIZEOF_BDIGITS > 2
-    hbase *= hbase;
-#endif
-    off = !(trim && RBIGNUM_SIGN(x)); /* erase plus sign if trim */
-    xx = rb_big_clone(x);
-    RBIGNUM_SET_SIGN(xx, 1);
-    if (n1 <= KARATSUBA_DIGITS) {
-	len = off + big2str_orig(xx, base, ptr + off, n2, hbase, trim);
-    }
-    else {
-	len = off + big2str_karatsuba(xx, base, ptr + off, n1,
-				      n2, hbase, trim);
-    }
-
-    ptr[len] = '\0';
-
-    return rb_str_new2(ptr);
-}
-
-VALUE
-rb_big2str(VALUE x, int base)
-{
-    return rb_big2str0(x, base, 1);
-}
-
-/*
- *  call-seq:
- *     big.to_s(base=10)   =>  string
- *
- *  Returns a string containing the representation of <i>big</i> radix
- *  <i>base</i> (2 through 36).
- *
- *     12345654321.to_s         #=> "12345654321"
- *     12345654321.to_s(2)      #=> "1011011111110110111011110000110001"
- *     12345654321.to_s(8)      #=> "133766736061"
- *     12345654321.to_s(16)     #=> "2dfdbbc31"
- *     78546939656932.to_s(36)  #=> "rubyrules"
- */
-
-static VALUE
-rb_big_to_s(VALUE x, SEL sel, int argc, VALUE *argv)
-{
-    int base;
-
-    if (argc == 0) base = 10;
-    else {
-	VALUE b;
-
-	rb_scan_args(argc, argv, "01", &b);
-	base = NUM2INT(b);
-    }
-    return rb_big2str(x, base);
-}
-
-static unsigned long
-big2ulong(VALUE x, const char *type, int check)
-{
-    long len = RBIGNUM_LEN(x);
-    BDIGIT_DBL num;
-    BDIGIT *ds;
-
-    if (len > DIGSPERLONG) {
-	if (check)
-	    rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
-	len = DIGSPERLONG;
-    }
-    ds = BDIGITS(x);
-    num = 0;
-    while (len--) {
-	num = BIGUP(num);
-	num += ds[len];
-    }
-    return (unsigned long)num;
-}
-
-unsigned long
-rb_big2ulong_pack(VALUE x)
-{
-    unsigned long num = big2ulong(x, "unsigned long", Qfalse);
-    if (!RBIGNUM_SIGN(x)) {
-	return -num;
-    }
-    return num;
-}
-
-unsigned long
-rb_big2ulong(VALUE x)
-{
-    VALUE num = big2ulong(x, "unsigned long", Qtrue);
-
-    if (!RBIGNUM_SIGN(x)) {
-	if ((long)num < 0) {
-	    rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
-	}
-	return -num;
-    }
-    return num;
-}
-
-long
-rb_big2long(VALUE x)
-{
-    VALUE num = big2ulong(x, "long", Qtrue);
-
-    if ((SIGNED_VALUE)num < 0 &&
-	(RBIGNUM_SIGN(x) || (SIGNED_VALUE)num != LONG_MIN)) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
-    }
-    if (!RBIGNUM_SIGN(x)) return -(long)num;
-    return num;
-}
-
-#if HAVE_LONG_LONG
-
-static unsigned LONG_LONG
-big2ull(VALUE x, const char *type)
-{
-    long len = RBIGNUM_LEN(x);
-    BDIGIT_DBL num;
-    BDIGIT *ds;
-
-    if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
-	rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
-    ds = BDIGITS(x);
-    num = 0;
-    while (len--) {
-	num = BIGUP(num);
-	num += ds[len];
-    }
-    return num;
-}
-
-unsigned LONG_LONG
-rb_big2ull(VALUE x)
-{
-    unsigned LONG_LONG num = big2ull(x, "unsigned long long");
-
-    if (!RBIGNUM_SIGN(x)) return -num;
-    return num;
-}
-
-LONG_LONG
-rb_big2ll(VALUE x)
-{
-    unsigned LONG_LONG num = big2ull(x, "long long");
-
-    // This check is disabled because this function might be called from
-    // compiler stubs which will pass negative values as long long times
-    // for certain Cocoa APIs (generally fixed values like -1 or -2).
-#if 0
-    if ((LONG_LONG)num < 0 && (RBIGNUM_SIGN(x)
-			       || (LONG_LONG)num != LLONG_MIN)) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
-    }
-#endif
-    if (!RBIGNUM_SIGN(x)) return -(LONG_LONG)num;
-    return num;
-}
-
-#endif  /* HAVE_LONG_LONG */
-
-static VALUE
-dbl2big(double d)
-{
-    long i = 0;
-    BDIGIT c;
-    BDIGIT *digits;
-    VALUE z;
-    double u = (d < 0)?-d:d;
-
-    if (isinf(d)) {
-	rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
-    }
-    if (isnan(d)) {
-	rb_raise(rb_eFloatDomainError, "NaN");
-    }
-
-    while (!POSFIXABLE(u) || 0 != (long)u) {
-	u /= (double)(BIGRAD);
-	i++;
-    }
-    z = bignew(i, d>=0);
-    digits = BDIGITS(z);
-    while (i--) {
-	u *= BIGRAD;
-	c = (BDIGIT)u;
-	u -= c;
-	digits[i] = c;
-    }
-
-    return z;
-}
-
-VALUE
-rb_dbl2big(double d)
-{
-    return bignorm(dbl2big(d));
-}
-
-static int
-nlz(BDIGIT x)
-{
-    BDIGIT y;
-    int n = BITSPERDIG;
-#if BITSPERDIG > 64
-    y = x >> 64; if (y) {n -= 64; x = y;}
-#endif
-#if BITSPERDIG > 32
-    y = x >> 32; if (y) {n -= 32; x = y;}
-#endif
-#if BITSPERDIG > 16
-    y = x >> 16; if (y) {n -= 16; x = y;}
-#endif
-    y = x >>  8; if (y) {n -=  8; x = y;}
-    y = x >>  4; if (y) {n -=  4; x = y;}
-    y = x >>  2; if (y) {n -=  2; x = y;}
-    y = x >>  1; if (y) {return n - 2;}
-    return n - x;
-}
-
-static double
-big2dbl(VALUE x)
-{
-    double d = 0.0;
-    long i = RBIGNUM_LEN(x), lo = 0, bits;
-    BDIGIT *ds = BDIGITS(x), dl;
-
-    if (i) {
-	bits = i * BITSPERDIG - nlz(ds[i-1]);
-	if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
-	    d = HUGE_VAL;
-	}
-	else {
-	    if (bits > DBL_MANT_DIG+1)
-		lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
-	    else
-		bits = 0;
-	    while (--i > lo) {
-		d = ds[i] + BIGRAD*d;
-	    }
-	    dl = ds[i];
-	    if (bits && (dl & (1UL << (bits %= BITSPERDIG)))) {
-		int carry = dl & ~(~0UL << bits);
-		if (!carry) {
-		    while (i-- > 0) {
-			if ((carry = ds[i]) != 0) break;
-		    }
-		}
-		if (carry) {
-		    dl &= ~0UL << bits;
-		    dl += 1UL << bits;
-		    if (!dl) d += 1;
-		}
-	    }
-	    d = dl + BIGRAD*d;
-	    if (lo) d = ldexp(d, lo * BITSPERDIG);
-	}
-    }
-    if (!RBIGNUM_SIGN(x)) d = -d;
-    return d;
-}
-
-double
-rb_big2dbl(VALUE x)
-{
-    double d = big2dbl(x);
-
-    if (isinf(d)) {
-	rb_warning("Bignum out of Float range");
-	d = HUGE_VAL;
-    }
-    return d;
-}
-
-/*
- *  call-seq:
- *     big.to_f -> float
- *
- *  Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
- *  fit in a <code>Float</code>, the result is infinity.
- *
- */
-
-static VALUE
-rb_big_to_f(VALUE x, SEL sel)
-{
-    return DOUBLE2NUM(rb_big2dbl(x));
-}
-
-/*
- *  call-seq:
- *     big <=> numeric   => -1, 0, +1
- *
- *  Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
- *  less than, equal to, or greater than <i>numeric</i>. This is the
- *  basis for the tests in <code>Comparable</code>.
- *
- */
-
-VALUE
-rb_big_cmp(VALUE x, VALUE y)
-{
-    long xlen = RBIGNUM_LEN(x);
-    BDIGIT *xds, *yds;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      case T_FLOAT:
-	{
-	    double a = RFLOAT_VALUE(y);
-
-	    if (isinf(a)) {
-		if (a > 0.0) return INT2FIX(-1);
-		else return INT2FIX(1);
-	    }
-	    return rb_dbl_cmp(rb_big2dbl(x), a);
-	}
-
-      default:
-	return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
-    }
-
-    if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
-    if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
-    if (xlen < RBIGNUM_LEN(y))
-	return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
-    if (xlen > RBIGNUM_LEN(y))
-	return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);
-
-    xds = BDIGITS(x);
-    yds = BDIGITS(y);
-
-    while(xlen-- && (xds[xlen]==yds[xlen]));
-    if (-1 == xlen) return INT2FIX(0);
-    return (xds[xlen] > yds[xlen]) ?
-	(RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
-	    (RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
-}
-
-static VALUE
-rb_big_cmp_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_cmp(x, y);
-}
-
-/*
- *  call-seq:
- *     big == obj  => true or false
- *
- *  Returns <code>true</code> only if <i>obj</i> has the same value
- *  as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
- *  requires <i>obj</i> to be a <code>Bignum</code>.
- *
- *     68719476736 == 68719476736.0   #=> true
- */
-
-VALUE
-rb_big_eq_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_eq(x, y);
-}
-
-VALUE
-rb_big_eq(VALUE x, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-      case T_BIGNUM:
-	break;
-      case T_FLOAT:
-	{
-	    volatile double a, b;
-
-	    a = RFLOAT_VALUE(y);
-	    if (isnan(a)) return Qfalse;
-	    b = rb_big2dbl(x);
-	    return (a == b)?Qtrue:Qfalse;
-	}
-      default:
-	return rb_equal(y, x);
-    }
-    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
-    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
-    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     big.eql?(obj)   => true or false
- *
- *  Returns <code>true</code> only if <i>obj</i> is a
- *  <code>Bignum</code> with the same value as <i>big</i>. Contrast this
- *  with <code>Bignum#==</code>, which performs type conversions.
- *
- *     68719476736.eql?(68719476736.0)   #=> false
- */
-
-static VALUE
-rb_big_eql(VALUE x, SEL sel, VALUE y)
-{
-    if (TYPE(y) != T_BIGNUM) return Qfalse;
-    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
-    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
-    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    -big   =>  other_big
- *
- * Unary minus (returns a new Bignum whose value is 0-big)
- */
-
-VALUE
-rb_big_uminus(VALUE x)
-{
-    VALUE z = rb_big_clone(x);
-
-    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
-
-    return bignorm(z);
-}
-
-static VALUE
-rb_big_uminus_imp(VALUE x, SEL sel)
-{
-    return rb_big_uminus(x);
-}
-
-/*
- * call-seq:
- *     ~big  =>  integer
- *
- * Inverts the bits in big. As Bignums are conceptually infinite
- * length, the result acts as if it had an infinite number of one
- * bits to the left. In hex representations, this is displayed
- * as two periods to the left of the digits.
- *
- *   sprintf("%X", ~0x1122334455)    #=> "..FEEDDCCBBAA"
- */
-
-static VALUE
-rb_big_neg(VALUE x, SEL sel)
-{
-    VALUE z = rb_big_clone(x);
-    BDIGIT *ds;
-    long i;
-
-    if (!RBIGNUM_SIGN(x)) get2comp(z);
-    ds = BDIGITS(z);
-    i = RBIGNUM_LEN(x);
-    if (!i) return INT2FIX(~(SIGNED_VALUE)0);
-    while (i--) {
-	ds[i] = ~ds[i];
-    }
-    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(z));
-    if (RBIGNUM_SIGN(x)) get2comp(z);
-
-    return bignorm(z);
-}
-
-static VALUE
-bigsub(VALUE x, VALUE y)
-{
-    VALUE z = 0;
-    BDIGIT *zds;
-    BDIGIT_DBL_SIGNED num;
-    long i = RBIGNUM_LEN(x);
-
-    /* if x is larger than y, swap */
-    if (RBIGNUM_LEN(x) < RBIGNUM_LEN(y)) {
-	z = x; x = y; y = z;	/* swap x y */
-    }
-    else if (RBIGNUM_LEN(x) == RBIGNUM_LEN(y)) {
-	while (i > 0) {
-	    i--;
-	    if (BDIGITS(x)[i] > BDIGITS(y)[i]) {
-		break;
-	    }
-	    if (BDIGITS(x)[i] < BDIGITS(y)[i]) {
-		z = x; x = y; y = z;	/* swap x y */
-		break;
-	    }
-	}
-    }
-
-    z = bignew(RBIGNUM_LEN(x), z==0);
-    zds = BDIGITS(z);
-
-    for (i = 0, num = 0; i < RBIGNUM_LEN(y); i++) {
-	num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
-	zds[i] = BIGLO(num);
-	num = BIGDN(num);
-    }
-    while (num && i < RBIGNUM_LEN(x)) {
-	num += BDIGITS(x)[i];
-	zds[i++] = BIGLO(num);
-	num = BIGDN(num);
-    }
-    while (i < RBIGNUM_LEN(x)) {
-	zds[i] = BDIGITS(x)[i];
-	i++;
-    }
-
-    return z;
-}
-
-static VALUE
-bigadd(VALUE x, VALUE y, int sign)
-{
-    VALUE z;
-    BDIGIT_DBL num;
-    long i, len;
-
-    sign = (sign == RBIGNUM_SIGN(y));
-    if (RBIGNUM_SIGN(x) != sign) {
-	if (sign) return bigsub(y, x);
-	return bigsub(x, y);
-    }
-
-    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
-	len = RBIGNUM_LEN(x) + 1;
-	z = x; x = y; y = z;
-    }
-    else {
-	len = RBIGNUM_LEN(y) + 1;
-    }
-    z = bignew(len, sign);
-
-    len = RBIGNUM_LEN(x);
-    for (i = 0, num = 0; i < len; i++) {
-	num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
-	BDIGITS(z)[i] = BIGLO(num);
-	num = BIGDN(num);
-    }
-    len = RBIGNUM_LEN(y);
-    while (num && i < len) {
-	num += BDIGITS(y)[i];
-	BDIGITS(z)[i++] = BIGLO(num);
-	num = BIGDN(num);
-    }
-    while (i < len) {
-	BDIGITS(z)[i] = BDIGITS(y)[i];
-	i++;
-    }
-    BDIGITS(z)[i] = (BDIGIT)num;
-
-    return z;
-}
-
-/*
- *  call-seq:
- *     big + other  => Numeric
- *
- *  Adds big and other, returning the result.
- */
-
-static VALUE
-rb_big_plus_imp(VALUE x, SEL sel, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	/* fall through */
-      case T_BIGNUM:
-	return bignorm(bigadd(x, y, 1));
-
-      case T_FLOAT:
-	return DOUBLE2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
-
-      default:
-	return rb_num_coerce_bin(x, y, '+');
-    }
-}
-
-VALUE
-rb_big_plus(VALUE x, VALUE y)
-{
-    return rb_big_plus_imp(x, 0, y);
-}
-
-/*
- *  call-seq:
- *     big - other  => Numeric
- *
- *  Subtracts other from big, returning the result.
- */
-
-VALUE
-rb_big_minus(VALUE x, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	/* fall through */
-      case T_BIGNUM:
-	return bignorm(bigadd(x, y, 0));
-
-      case T_FLOAT:
-	return DOUBLE2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
-
-      default:
-	return rb_num_coerce_bin(x, y, '-');
-    }
-}
-
-static VALUE
-rb_big_minus_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_minus(x, y);
-}
-
-struct big_mul_struct {
-    VALUE x, y, z, stop;
-};
-
-static inline VALUE
-bigmul1(void *ptr)
-{
-    struct big_mul_struct *bms = (struct big_mul_struct*)ptr;
-    long i, j;
-    BDIGIT_DBL n = 0;
-    VALUE x = bms->x, y = bms->y, z = bms->z;
-    BDIGIT *xds;
-    BDIGIT *yds;
-    BDIGIT *zds;
-    const int x_len = RBIGNUM_LEN(x);
-    const int y_len = RBIGNUM_LEN(y);
-
-    j = x_len + y_len + 1;
-    xds = BDIGITS(x);
-    yds = BDIGITS(y);
-    zds = BDIGITS(z);
-    while (j--) zds[j] = 0;
-    for (i = 0; i < x_len; i++) {
-	BDIGIT_DBL dd;
-//	if (bms->stop) return Qnil;
-	dd = xds[i];
-	if (dd == 0) continue;
-	n = 0;
-	for (j = 0; j < y_len; j++) {
-	    BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * yds[j];
-	    n = zds[i + j] + ee;
-	    if (ee) zds[i + j] = BIGLO(n);
-	    n = BIGDN(n);
-	}
-	if (n) {
-	    zds[i + j] = n;
-	}
-    }
-    return z;
-}
-
-static VALUE
-rb_big_mul0(VALUE x, VALUE y)
-{
-    struct big_mul_struct bms;
-    volatile VALUE z;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      case T_FLOAT:
-	return DOUBLE2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
-
-      default:
-	return rb_num_coerce_bin(x, y, '*');
-    }
-
-    bms.x = x;
-    bms.y = y;
-    bms.z = bignew(RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
-    bms.stop = Qfalse;
-
-//    if (RBIGNUM_LEN(x) + RBIGNUM_LEN(y) > 10000) {
-//	z = rb_thread_blocking_region(bigmul1, &bms, rb_big_stop, &bms.stop);
-//    }
-//    else {
-	z = bigmul1(&bms);
-//    }
-
-    return z;
-}
-
-/*
- *  call-seq:
- *     big * other  => Numeric
- *
- *  Multiplies big and other, returning the result.
- */
-
-VALUE
-rb_big_mul(VALUE x, VALUE y)
-{
-    return bignorm(rb_big_mul0(x, y));
-}
-
-static VALUE
-rb_big_mul_imp(VALUE x, SEL sel, VALUE y)
-{
-    return bignorm(rb_big_mul0(x, y));
-}
-
-struct big_div_struct {
-    long nx, ny;
-    BDIGIT *yds, *zds;
-    VALUE stop;
-};
-
-static VALUE
-bigdivrem1(void *ptr)
-{
-    struct big_div_struct *bds = (struct big_div_struct*)ptr;
-    long nx = bds->nx, ny = bds->ny;
-    long i, j;
-    BDIGIT *yds = bds->yds, *zds = bds->zds;
-    BDIGIT_DBL t2;
-    BDIGIT_DBL_SIGNED num;
-    BDIGIT q;
-
-    j = nx==ny?nx+1:nx;
-    do {
-	if (bds->stop) return Qnil;
-	if (zds[j] ==  yds[ny-1]) q = BIGRAD-1;
-	else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
-	if (q) {
-	    i = 0; num = 0; t2 = 0;
-	    do {			/* multiply and subtract */
-		BDIGIT_DBL ee;
-		t2 += (BDIGIT_DBL)yds[i] * q;
-		ee = num - BIGLO(t2);
-		num = (BDIGIT_DBL)zds[j - ny + i] + ee;
-		if (ee) zds[j - ny + i] = BIGLO(num);
-		num = BIGDN(num);
-		t2 = BIGDN(t2);
-	    } while (++i < ny);
-	    num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */
-	    while (num) {		/* "add back" required */
-		i = 0; num = 0; q--;
-		do {
-		    BDIGIT_DBL ee = num + yds[i];
-		    num = (BDIGIT_DBL)zds[j - ny + i] + ee;
-		    if (ee) zds[j - ny + i] = BIGLO(num);
-		    num = BIGDN(num);
-		} while (++i < ny);
-		num--;
-	    }
-	}
-	zds[j] = q;
-    } while (--j >= ny);
-    return Qnil;
-}
-
-static VALUE
-bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
-{
-    struct big_div_struct bds;
-    long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y);
-    long i, j;
-    volatile VALUE yy, z;
-    BDIGIT *xds, *yds, *zds, *tds;
-    BDIGIT_DBL t2;
-    BDIGIT dd, q;
-
-    if (BIGZEROP(y)) rb_num_zerodiv();
-    yds = BDIGITS(y);
-    if (nx < ny || (nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1])) {
-	if (divp) *divp = rb_int2big(0);
-	if (modp) *modp = x;
-	return Qnil;
-    }
-    xds = BDIGITS(x);
-    if (ny == 1) {
-	dd = yds[0];
-	z = rb_big_clone(x);
-	zds = BDIGITS(z);
-	t2 = 0; i = nx;
-	while (i--) {
-	    t2 = BIGUP(t2) + zds[i];
-	    zds[i] = (BDIGIT)(t2 / dd);
-	    t2 %= dd;
-	}
-	RBIGNUM_SET_SIGN(z, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
-	if (modp) {
-	    *modp = rb_uint2big((VALUE)t2);
-	    RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
-	}
-	if (divp) *divp = z;
-	return Qnil;
-    }
-    z = bignew(nx==ny?nx+2:nx+1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
-    zds = BDIGITS(z);
-    if (nx==ny) zds[nx+1] = 0;
-    while (!yds[ny-1]) ny--;
-
-    dd = 0;
-    q = yds[ny-1];
-    while ((q & (1UL<<(BITSPERDIG-1))) == 0) {
-	q <<= 1UL;
-	dd++;
-    }
-    if (dd) {
-	yy = rb_big_clone(y);
-	tds = BDIGITS(yy);
-	j = 0;
-	t2 = 0;
-	while (j<ny) {
-	    t2 += (BDIGIT_DBL)yds[j]<<dd;
-	    tds[j++] = BIGLO(t2);
-	    t2 = BIGDN(t2);
-	}
-	yds = tds;
-	j = 0;
-	t2 = 0;
-	while (j<nx) {
-	    t2 += (BDIGIT_DBL)xds[j]<<dd;
-	    zds[j++] = BIGLO(t2);
-	    t2 = BIGDN(t2);
-	}
-	zds[j] = (BDIGIT)t2;
-    }
-    else {
-	zds[nx] = 0;
-	j = nx;
-	while (j--) zds[j] = xds[j];
-    }
-
-    bds.nx = nx;
-    bds.ny = ny;
-    bds.zds = zds;
-    bds.yds = yds;
-    bds.stop = Qfalse;
-//    if (RBIGNUM_LEN(x) > 10000 || RBIGNUM_LEN(y) > 10000) {
-//	rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop);
-//    }
-//    else {
-	bigdivrem1(&bds);
-//    }
-
-    if (divp) {			/* move quotient down in z */
-	*divp = rb_big_clone(z);
-	zds = BDIGITS(*divp);
-	j = (nx==ny ? nx+2 : nx+1) - ny;
-	for (i = 0;i < j;i++) zds[i] = zds[i+ny];
-	RBIGNUM_SET_LEN(*divp, i);
-    }
-    if (modp) {			/* normalize remainder */
-	*modp = rb_big_clone(z);
-	zds = BDIGITS(*modp);
-	while (--ny && !zds[ny]); ++ny;
-	if (dd) {
-	    t2 = 0; i = ny;
-	    while(i--) {
-		t2 = (t2 | zds[i]) >> dd;
-		q = zds[i];
-		zds[i] = BIGLO(t2);
-		t2 = BIGUP(q);
-	    }
-	}
-	RBIGNUM_SET_LEN(*modp, ny);
-	RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
-    }
-    return z;
-}
-
-static void
-bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
-{
-    VALUE mod;
-
-    bigdivrem(x, y, divp, &mod);
-    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y) && !BIGZEROP(mod)) {
-	if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
-	if (modp) *modp = bigadd(mod, y, 1);
-    }
-    else {
-	if (divp) *divp = *divp;
-	if (modp) *modp = mod;
-    }
-}
-
-
-static VALUE
-rb_big_divide(VALUE x, VALUE y, ID op)
-{
-    VALUE z;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      case T_FLOAT:
-	{
-	    double div = rb_big2dbl(x) / RFLOAT_VALUE(y);
-	    if (op == '/') {
-		return DOUBLE2NUM(div);
-	    }
-	    else {
-		return rb_dbl2big(div);
-	    }
-	}
-
-      default:
-	return rb_num_coerce_bin(x, y, op);
-    }
-    bigdivmod(x, y, &z, 0);
-
-    return bignorm(z);
-}
-
-/*
- *  call-seq:
- *     big / other     => Numeric
- *
- *  Divides big by other, returning the result.
- */
-
-VALUE 
-rb_big_div_imp(VALUE x, SEL sel, VALUE y)
-{
-  return rb_big_divide(x, y, '/');
-}
-
-VALUE
-rb_big_div(VALUE x, VALUE y)
-{
-  return rb_big_divide(x, y, '/');
-}
-
-VALUE
-rb_big_idiv_imp(VALUE x, SEL sel, VALUE y)
-{
-  return rb_big_divide(x, y, rb_intern("div"));
-}
-
-VALUE
-rb_big_idiv(VALUE x, VALUE y)
-{
-  return rb_big_divide(x, y, rb_intern("div"));
-}
-
-/*
- *  call-seq:
- *     big % other         => Numeric
- *     big.modulo(other)   => Numeric
- *
- *  Returns big modulo other. See Numeric.divmod for more
- *  information.
- */
-
-VALUE
-rb_big_modulo(VALUE x, VALUE y)
-{
-    VALUE z;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      default:
-	return rb_num_coerce_bin(x, y, '%');
-    }
-    bigdivmod(x, y, 0, &z);
-
-    return bignorm(z);
-}
-
-static VALUE
-rb_big_modulo_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_modulo(x, y);
-}
-
-/*
- *  call-seq:
- *     big.remainder(numeric)    => number
- *
- *  Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
- *
- *     -1234567890987654321.remainder(13731)      #=> -6966
- *     -1234567890987654321.remainder(13731.24)   #=> -9906.22531493148
- */
-static VALUE
-rb_big_remainder(VALUE x, SEL sel, VALUE y)
-{
-    VALUE z;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      default:
-	return rb_num_coerce_bin(x, y, rb_intern("remainder"));
-    }
-    bigdivrem(x, y, 0, &z);
-
-    return bignorm(z);
-}
-
-/*
- *  call-seq:
- *     big.divmod(numeric)   => array
- *
- *  See <code>Numeric#divmod</code>.
- *
- */
-VALUE
-rb_big_divmod(VALUE x, VALUE y)
-{
-    VALUE div, mod;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      default:
-	return rb_num_coerce_bin(x, y, rb_intern("divmod"));
-    }
-    bigdivmod(x, y, &div, &mod);
-
-    return rb_assoc_new(bignorm(div), bignorm(mod));
-}
-
-static VALUE
-rb_big_divmod_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_divmod(x, y);
-}
-
-static int
-bdigbitsize(BDIGIT x)
-{
-    int size = 1;
-    int nb = BITSPERDIG / 2;
-    BDIGIT bits = (~0 << nb);
-
-    if (!x) return 0;
-    while (x > 1) {
-	if (x & bits) {
-	    size += nb;
-	    x >>= nb;
-	}
-	x &= ~bits;
-	nb /= 2;
-	bits >>= nb;
-    }
-
-    return size;
-}
-
-static VALUE big_lshift(VALUE, unsigned long);
-static VALUE big_rshift(VALUE, unsigned long);
-
-static VALUE big_shift(VALUE x, int n)
-{
-    if (n < 0)
-	return big_lshift(x, (unsigned int)-n);
-    else if (n > 0)
-	return big_rshift(x, (unsigned int)n);
-    return x;
-}
-
-/*
- *  call-seq:
-  *     big.fdiv(numeric) -> float
- *
- *  Returns the floating point result of dividing <i>big</i> by
- *  <i>numeric</i>.
- *
- *     -1234567890987654321.fdiv(13731)      #=> -89910996357705.5
- *     -1234567890987654321.fdiv(13731.24)   #=> -89909424858035.7
- *
- */
-
-static VALUE
-rb_big_fdiv(VALUE x, SEL sel, VALUE y)
-{
-    double dx = big2dbl(x);
-    double dy;
-
-    if (isinf(dx)) {
-#define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
-	VALUE z;
-	int ex, ey;
-
-	ex = (RBIGNUM_LEN(bigtrunc(x)) - 1) * BITSPERDIG;
-	ex += bdigbitsize(BDIGITS(x)[RBIGNUM_LEN(x) - 1]);
-	ex -= 2 * DBL_BIGDIG * BITSPERDIG;
-	if (ex) x = big_shift(x, ex);
-
-	switch (TYPE(y)) {
-	  case T_FIXNUM:
-	    y = rb_int2big(FIX2LONG(y));
-	  case T_BIGNUM: {
-	    ey = (RBIGNUM_LEN(bigtrunc(y)) - 1) * BITSPERDIG;
-	    ey += bdigbitsize(BDIGITS(y)[RBIGNUM_LEN(y) - 1]);
-	    ey -= DBL_BIGDIG * BITSPERDIG;
-	    if (ey) y = big_shift(y, ey);
-	  bignum:
-	    bigdivrem(x, y, &z, 0);
-	    return DOUBLE2NUM(ldexp(big2dbl(z), ex - ey));
-	  }
-	  case T_FLOAT:
-	    if (isnan(RFLOAT_VALUE(y))) return y;
-	    y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &ey), DBL_MANT_DIG));
-	    ey -= DBL_MANT_DIG;
-	    goto bignum;
-	}
-    }
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	dy = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	dy = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	dy = RFLOAT_VALUE(y);
-	break;
-
-      default:
-	return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
-    }
-    return DOUBLE2NUM(dx / dy);
-}
-
-static VALUE
-bigsqr(VALUE x)
-{
-    long len = RBIGNUM_LEN(x), k = len / 2, i;
-    VALUE a, b, a2, z;
-    BDIGIT_DBL num;
-
-    if (len < 4000 / BITSPERDIG) {
-	return bigtrunc(rb_big_mul0(x, x));
-    }
-
-    a = bignew(len - k, 1);
-    MEMCPY(BDIGITS(a), BDIGITS(x) + k, BDIGIT, len - k);
-    b = bignew(k, 1);
-    MEMCPY(BDIGITS(b), BDIGITS(x), BDIGIT, k);
-
-    a2 = bigtrunc(bigsqr(a));
-    z = bigsqr(b);
-    rb_big_realloc(z, (len = 2 * k + RBIGNUM_LEN(a2)) + 1);
-    while (RBIGNUM_LEN(z) < 2 * k) {
-	BDIGITS(z)[RBIGNUM_LEN(z)] = 0;
-	RBIGNUM_SET_LEN(z, RBIGNUM_LEN(z)+1);
-    }
-    MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM_LEN(a2));
-    RBIGNUM_SET_LEN(z, len);
-    a2 = bigtrunc(rb_big_mul0(a, b));
-    len = RBIGNUM_LEN(a2);
-    for (i = 0, num = 0; i < len; i++) {
-	num += (BDIGIT_DBL)BDIGITS(z)[i + k] + ((BDIGIT_DBL)BDIGITS(a2)[i] << 1);
-	BDIGITS(z)[i + k] = BIGLO(num);
-	num = BIGDN(num);
-    }
-    if (num) {
-	len = RBIGNUM_LEN(z);
-	for (i += k; i < len && num; ++i) {
-	    num += (BDIGIT_DBL)BDIGITS(z)[i];
-	    BDIGITS(z)[i] = BIGLO(num);
-	    num = BIGDN(num);
-	}
-	if (num) {
-	    BDIGITS(z)[RBIGNUM_LEN(z)] = BIGLO(num);
-	    RBIGNUM_SET_LEN(z, RBIGNUM_LEN(z)+1);
-	}
-    }
-    return bigtrunc(z);
-}
-
-/*
- *  call-seq:
- *     big ** exponent   => numeric
- *
- *  Raises _big_ to the _exponent_ power (which may be an integer, float,
- *  or anything that will coerce to a number). The result may be
- *  a Fixnum, Bignum, or Float
- *
- *    123456789 ** 2      #=> 15241578750190521
- *    123456789 ** 1.2    #=> 5126464716.09932
- *    123456789 ** -2     #=> 6.5610001194102e-17
- */
-
-VALUE
-rb_big_pow(VALUE x, VALUE y)
-{
-    double d;
-    SIGNED_VALUE yy;
-
-    if (y == INT2FIX(0)) return INT2FIX(1);
-    switch (TYPE(y)) {
-      case T_FLOAT:
-	d = RFLOAT_VALUE(y);
-	break;
-
-      case T_BIGNUM:
-	if (rb_funcall(y, '<', 1, INT2FIX(0)))
-	  return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
-
-	rb_warn("in a**b, b may be too big");
-	d = rb_big2dbl(y);
-	break;
-
-      case T_FIXNUM:
-	yy = FIX2LONG(y);
-
-	if (yy < 0)
-	  return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
-	else {
-	    VALUE z = 0;
-	    SIGNED_VALUE mask;
-	    const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
-
-	    if ((RBIGNUM_LEN(x) > BIGLEN_LIMIT) ||
-		(RBIGNUM_LEN(x) > BIGLEN_LIMIT / yy)) {
-		rb_warn("in a**b, b may be too big");
-		d = (double)yy;
-		break;
-	    }
-	    for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
-		if (z) z = bigtrunc(bigsqr(z));
-		if (yy & mask) {
-		    z = z ? bigtrunc(rb_big_mul0(z, x)) : x;
-		}
-	    }
-	    return bignorm(z);
-	}
-	/* NOTREACHED */
-	break;
-
-      default:
-	return rb_num_coerce_bin(x, y, rb_intern("**"));
-    }
-    return DOUBLE2NUM(pow(rb_big2dbl(x), d));
-}
-
-static VALUE
-rb_big_pow_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_pow(x, y);
-}
-
-static VALUE
-bit_coerce(VALUE x)
-{
-    while (!FIXNUM_P(x) && TYPE(x) != T_BIGNUM) {
-	if (TYPE(x) == T_FLOAT) {
-	    rb_raise(rb_eTypeError, "can't convert Float into Integer");
-	}
-	x = rb_to_int(x);
-    }
-    return x;
-}
-
-/*
- * call-seq:
- *     big & numeric   =>  integer
- *
- * Performs bitwise +and+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_and(VALUE xx, VALUE yy)
-{
-    volatile VALUE x, y, z;
-    BDIGIT *ds1, *ds2, *zds;
-    long i, l1, l2;
-    char sign;
-
-    x = xx;
-    y = bit_coerce(yy);
-    if (FIXNUM_P(y)) {
-	y = rb_int2big(FIX2LONG(y));
-    }
-    if (!RBIGNUM_SIGN(y)) {
-	y = rb_big_clone(y);
-	get2comp(y);
-    }
-    if (!RBIGNUM_SIGN(x)) {
-	x = rb_big_clone(x);
-	get2comp(x);
-    }
-    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
-	l1 = RBIGNUM_LEN(y);
-	l2 = RBIGNUM_LEN(x);
-	ds1 = BDIGITS(y);
-	ds2 = BDIGITS(x);
-	sign = RBIGNUM_SIGN(y);
-    }
-    else {
-	l1 = RBIGNUM_LEN(x);
-	l2 = RBIGNUM_LEN(y);
-	ds1 = BDIGITS(x);
-	ds2 = BDIGITS(y);
-	sign = RBIGNUM_SIGN(x);
-    }
-    z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
-    zds = BDIGITS(z);
-
-    for (i=0; i<l1; i++) {
-	zds[i] = ds1[i] & ds2[i];
-    }
-    for (; i<l2; i++) {
-	zds[i] = sign?0:ds2[i];
-    }
-    if (!RBIGNUM_SIGN(z)) get2comp(z);
-    return bignorm(z);
-}
-
-static VALUE
-rb_big_and_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_and(x, y);
-}
-
-/*
- * call-seq:
- *     big | numeric   =>  integer
- *
- * Performs bitwise +or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_or(VALUE xx, VALUE yy)
-{
-    volatile VALUE x, y, z;
-    BDIGIT *ds1, *ds2, *zds;
-    long i, l1, l2;
-    char sign;
-
-    x = xx;
-    y = bit_coerce(yy);
-    if (FIXNUM_P(y)) {
-	y = rb_int2big(FIX2LONG(y));
-    }
-
-    if (!RBIGNUM_SIGN(y)) {
-	y = rb_big_clone(y);
-	get2comp(y);
-    }
-    if (!RBIGNUM_SIGN(x)) {
-	x = rb_big_clone(x);
-	get2comp(x);
-    }
-    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
-	l1 = RBIGNUM_LEN(y);
-	l2 = RBIGNUM_LEN(x);
-	ds1 = BDIGITS(y);
-	ds2 = BDIGITS(x);
-	sign = RBIGNUM_SIGN(y);
-    }
-    else {
-	l1 = RBIGNUM_LEN(x);
-	l2 = RBIGNUM_LEN(y);
-	ds1 = BDIGITS(x);
-	ds2 = BDIGITS(y);
-	sign = RBIGNUM_SIGN(x);
-    }
-    z = bignew(l2, RBIGNUM_SIGN(x) && RBIGNUM_SIGN(y));
-    zds = BDIGITS(z);
-
-    for (i=0; i<l1; i++) {
-	zds[i] = ds1[i] | ds2[i];
-    }
-    for (; i<l2; i++) {
-	zds[i] = sign?ds2[i]:(BIGRAD-1);
-    }
-    if (!RBIGNUM_SIGN(z)) get2comp(z);
-
-    return bignorm(z);
-}
-
-static VALUE
-rb_big_or_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_or(x, y);
-}
-
-/*
- * call-seq:
- *     big ^ numeric   =>  integer
- *
- * Performs bitwise +exclusive or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_xor(VALUE xx, VALUE yy)
-{
-    volatile VALUE x, y;
-    VALUE z;
-    BDIGIT *ds1, *ds2, *zds;
-    long i, l1, l2;
-    char sign;
-
-    x = xx;
-    y = bit_coerce(yy);
-    if (FIXNUM_P(y)) {
-	y = rb_int2big(FIX2LONG(y));
-    }
-
-    if (!RBIGNUM_SIGN(y)) {
-	y = rb_big_clone(y);
-	get2comp(y);
-    }
-    if (!RBIGNUM_SIGN(x)) {
-	x = rb_big_clone(x);
-	get2comp(x);
-    }
-    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
-	l1 = RBIGNUM_LEN(y);
-	l2 = RBIGNUM_LEN(x);
-	ds1 = BDIGITS(y);
-	ds2 = BDIGITS(x);
-	sign = RBIGNUM_SIGN(y);
-    }
-    else {
-	l1 = RBIGNUM_LEN(x);
-	l2 = RBIGNUM_LEN(y);
-	ds1 = BDIGITS(x);
-	ds2 = BDIGITS(y);
-	sign = RBIGNUM_SIGN(x);
-    }
-    RBIGNUM_SET_SIGN(x, RBIGNUM_SIGN(x)?1:0);
-    RBIGNUM_SET_SIGN(y, RBIGNUM_SIGN(y)?1:0);
-    z = bignew(l2, !(RBIGNUM_SIGN(x) ^ RBIGNUM_SIGN(y)));
-    zds = BDIGITS(z);
-
-    for (i=0; i<l1; i++) {
-	zds[i] = ds1[i] ^ ds2[i];
-    }
-    for (; i<l2; i++) {
-	zds[i] = sign?ds2[i]:~ds2[i];
-    }
-    if (!RBIGNUM_SIGN(z)) get2comp(z);
-
-    return bignorm(z);
-}
-
-static VALUE
-rb_big_xor_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_xor(x, y);
-}
-
-static VALUE
-check_shiftdown(VALUE y, VALUE x)
-{
-    if (!RBIGNUM_LEN(x)) return INT2FIX(0);
-    if (RBIGNUM_LEN(y) > SIZEOF_LONG / SIZEOF_BDIGITS) {
-	return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(-1);
-    }
-    return Qnil;
-}
-
-/*
- * call-seq:
- *     big << numeric   =>  integer
- *
- * Shifts big left _numeric_ positions (right if _numeric_ is negative).
- */
-
-VALUE
-rb_big_lshift(VALUE x, VALUE y)
-{
-    long shift;
-    int neg = 0;
-
-    for (;;) {
-	if (FIXNUM_P(y)) {
-	    shift = FIX2LONG(y);
-	    if (shift < 0) {
-		neg = 1;
-		shift = -shift;
-	    }
-	    break;
-	}
-	else if (TYPE(y) == T_BIGNUM) {
-	    if (!RBIGNUM_SIGN(y)) {
-		VALUE t = check_shiftdown(y, x);
-		if (!NIL_P(t)) return t;
-		neg = 1;
-	    }
-	    shift = big2ulong(y, "long", Qtrue);
-	    break;
-	}
-	y = rb_to_int(y);
-    }
-
-    if (neg) return big_rshift(x, shift);
-    return big_lshift(x, shift);
-}
-
-static VALUE
-rb_big_lshift_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_lshift(x, y);
-}
-
-static VALUE
-big_lshift(VALUE x, unsigned long shift)
-{
-    BDIGIT *xds, *zds;
-    long s1 = shift/BITSPERDIG;
-    int s2 = shift%BITSPERDIG;
-    VALUE z;
-    BDIGIT_DBL num = 0;
-    long len, i;
-
-    len = RBIGNUM_LEN(x);
-    z = bignew(len+s1+1, RBIGNUM_SIGN(x));
-    zds = BDIGITS(z);
-    for (i=0; i<s1; i++) {
-	*zds++ = 0;
-    }
-    xds = BDIGITS(x);
-    for (i=0; i<len; i++) {
-	num = num | (BDIGIT_DBL)*xds++<<s2;
-	*zds++ = BIGLO(num);
-	num = BIGDN(num);
-    }
-    *zds = BIGLO(num);
-    return bignorm(z);
-}
-
-/*
- * call-seq:
- *     big >> numeric   =>  integer
- *
- * Shifts big right _numeric_ positions (left if _numeric_ is negative).
- */
-
-VALUE
-rb_big_rshift(VALUE x, VALUE y)
-{
-    long shift;
-    int neg = 0;
-
-    for (;;) {
-	if (FIXNUM_P(y)) {
-	    shift = FIX2LONG(y);
-	    if (shift < 0) {
-		neg = 1;
-		shift = -shift;
-	    }
-	    break;
-	}
-	else if (TYPE(y) == T_BIGNUM) {
-	    if (RBIGNUM_SIGN(y)) {
-		VALUE t = check_shiftdown(y, x);
-		if (!NIL_P(t)) return t;
-	    }
-	    else {
-		neg = 1;
-	    }
-	    shift = big2ulong(y, "long", Qtrue);
-	    break;
-	}
-	y = rb_to_int(y);
-    }
-
-    if (neg) return big_lshift(x, shift);
-    return big_rshift(x, shift);
-}
-
-static VALUE
-rb_big_rshift_imp(VALUE x, SEL sel, VALUE y)
-{
-    return rb_big_rshift(x, y);
-}
-
-static VALUE
-big_rshift(VALUE x, unsigned long shift)
-{
-    BDIGIT *xds, *zds;
-    long s1 = shift/BITSPERDIG;
-    int s2 = shift%BITSPERDIG;
-    VALUE z;
-    BDIGIT_DBL num = 0;
-    long i, j;
-    volatile VALUE save_x;
-
-    if (s1 > RBIGNUM_LEN(x)) {
-	if (RBIGNUM_SIGN(x))
-	    return INT2FIX(0);
-	else
-	    return INT2FIX(-1);
-    }
-    if (!RBIGNUM_SIGN(x)) {
-	save_x = x = rb_big_clone(x);
-	get2comp(x);
-    }
-    xds = BDIGITS(x);
-    i = RBIGNUM_LEN(x); j = i - s1;
-    if (j == 0) {
-	if (RBIGNUM_SIGN(x)) return INT2FIX(0);
-	else return INT2FIX(-1);
-    }
-    z = bignew(j, RBIGNUM_SIGN(x));
-    if (!RBIGNUM_SIGN(x)) {
-	num = ((BDIGIT_DBL)~0) << BITSPERDIG;
-    }
-    zds = BDIGITS(z);
-    while (i--, j--) {
-	num = (num | xds[i]) >> s2;
-	zds[j] = BIGLO(num);
-	num = BIGUP(xds[i]);
-    }
-    if (!RBIGNUM_SIGN(x)) {
-	get2comp(z);
-    }
-    return bignorm(z);
-}
-
-/*
- *  call-seq:
- *     big[n] -> 0, 1
- *
- *  Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
- *  representation of <i>big</i>, where <i>big</i>[0] is the least
- *  significant bit.
- *
- *     a = 9**15
- *     50.downto(0) do |n|
- *       print a[n]
- *     end
- *
- *  <em>produces:</em>
- *
- *     000101110110100000111000011110010100111100010111001
- *
- */
-
-static VALUE
-rb_big_aref(VALUE x, SEL sel, VALUE y)
-{
-    BDIGIT *xds;
-    BDIGIT_DBL num;
-    VALUE shift;
-    long i, s1, s2;
-
-    if (TYPE(y) == T_BIGNUM) {
-	if (!RBIGNUM_SIGN(y))
-	    return INT2FIX(0);
-	if (RBIGNUM_LEN(bigtrunc(y)) > DIGSPERLONG) {
-	  out_of_range:
-	    return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
-	}
-	shift = big2ulong(y, "long", Qfalse);
-    }
-    else {
-	i = NUM2LONG(y);
-	if (i < 0) return INT2FIX(0);
-	shift = (VALUE)i;
-    }
-    s1 = shift/BITSPERDIG;
-    s2 = shift%BITSPERDIG;
-
-    if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
-    if (!RBIGNUM_SIGN(x)) {
-	xds = BDIGITS(x);
-	i = 0; num = 1;
-	while (num += ~xds[i], ++i <= s1) {
-	    num = BIGDN(num);
-	}
-    }
-    else {
-	num = BDIGITS(x)[s1];
-    }
-    if (num & ((BDIGIT_DBL)1<<s2))
-	return INT2FIX(1);
-    return INT2FIX(0);
-}
-
-/*
- * call-seq:
- *   big.hash   => fixnum
- *
- * Compute a hash based on the value of _big_.
- */
-
-static VALUE
-rb_big_hash(VALUE x, SEL sel)
-{
-    int hash;
-
-    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
-    return INT2FIX(hash);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_big_coerce(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
-    }
-    else if (TYPE(y) == T_BIGNUM) {
-       return rb_assoc_new(y, x);
-    }
-    else {
-	rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
-		 rb_obj_classname(y));
-    }
-    /* not reached */
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     big.abs -> aBignum
- *
- *  Returns the absolute value of <i>big</i>.
- *
- *     -1234567890987654321.abs   #=> 1234567890987654321
- */
-
-static VALUE
-rb_big_abs(VALUE x, SEL sel)
-{
-    if (!RBIGNUM_SIGN(x)) {
-	x = rb_big_clone(x);
-	RBIGNUM_SET_SIGN(x, 1);
-    }
-    return x;
-}
-
-/*
- *  call-seq:
- *     big.size -> integer
- *
- *  Returns the number of bytes in the machine representation of
- *  <i>big</i>.
- *
- *     (256**10 - 1).size   #=> 12
- *     (256**20 - 1).size   #=> 20
- *     (256**40 - 1).size   #=> 40
- */
-
-static VALUE
-rb_big_size(VALUE big, SEL sel)
-{
-    return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
-}
-
-/*
- *  call-seq:
- *     big.odd? -> true or false
- *
- *  Returns <code>true</code> if <i>big</i> is an odd number.
- */
-
-static VALUE
-rb_big_odd_p(VALUE num, SEL sel)
-{
-    if (BDIGITS(num)[0] & 1) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     big.even? -> true or false
- *
- *  Returns <code>true</code> if <i>big</i> is an even number.
- */
-
-static VALUE
-rb_big_even_p(VALUE num, SEL sel)
-{
-    if (BDIGITS(num)[0] & 1) {
-	return Qfalse;
-    }
-    return Qtrue;
-}
-
-#if WITH_OBJC
-static const char *
-imp_rb_bignum_objCType(void *rcv, SEL sel)
-{
-    return "q";
-}
-    
-static void
-imp_rb_bignum_getValue(void *rcv, SEL sel, void *buffer)
-{
-    long long v = NUM2LL(rcv);
-    *(long long *)buffer = v;
-}
-
-static long long
-imp_rb_bignum_longLongValue(void *rcv, SEL sel)
-{
-    return NUM2LL(rcv);
-}
-
-static bool
-imp_rb_bignum_isEqual(void *rcv, SEL sel, void *other)
-{
-    if (other == NULL)
-	return false;
-    if (*(Class *)other != (Class)rb_cBignum)
-	return false;
-    return rb_big_eq((VALUE)rcv, (VALUE)other) == Qtrue;
-}
-
-static void
-rb_install_nsnumber_primitives(void)
-{
-    Class klass = (Class)rb_cBignum;
-    rb_objc_install_method2(klass, "objCType",
-	    (IMP)imp_rb_bignum_objCType);
-    rb_objc_install_method2(klass, "getValue:",
-	    (IMP)imp_rb_bignum_getValue);
-    rb_objc_install_method2(klass, "longLongValue",
-	    (IMP)imp_rb_bignum_longLongValue);
-    rb_objc_install_method2(klass, "isEqual:",
-	    (IMP)imp_rb_bignum_isEqual);
-}
-#endif
-
-/*
- *  Bignum objects hold integers outside the range of
- *  Fixnum. Bignum objects are created
- *  automatically when integer calculations would otherwise overflow a
- *  Fixnum. When a calculation involving
- *  Bignum objects returns a result that will fit in a
- *  Fixnum, the result is automatically converted.
- *
- *  For the purposes of the bitwise operations and <code>[]</code>, a
- *  Bignum is treated as if it were an infinite-length
- *  bitstring with 2's complement representation.
- *
- *  While Fixnum values are immediate, Bignum
- *  objects are not---assignment and parameter passing work with
- *  references to objects, not the objects themselves.
- *
- */
-
-void
-Init_Bignum(void)
-{
-    rb_cBignum = rb_define_class("Bignum", rb_cInteger);
-
-    rb_objc_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
-    rb_objc_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
-    rb_objc_define_method(rb_cBignum, "-@", rb_big_uminus_imp, 0);
-    rb_objc_define_method(rb_cBignum, "+", rb_big_plus_imp, 1);
-    rb_objc_define_method(rb_cBignum, "-", rb_big_minus_imp, 1);
-    rb_objc_define_method(rb_cBignum, "*", rb_big_mul_imp, 1);
-    rb_objc_define_method(rb_cBignum, "/", rb_big_div_imp, 1);
-    rb_objc_define_method(rb_cBignum, "%", rb_big_modulo_imp, 1);
-    rb_objc_define_method(rb_cBignum, "div", rb_big_idiv_imp, 1);
-    rb_objc_define_method(rb_cBignum, "divmod", rb_big_divmod_imp, 1);
-    rb_objc_define_method(rb_cBignum, "modulo", rb_big_modulo_imp, 1);
-    rb_objc_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
-    rb_objc_define_method(rb_cBignum, "fdiv", rb_big_fdiv, 1);
-    rb_objc_define_method(rb_cBignum, "**", rb_big_pow_imp, 1);
-    rb_objc_define_method(rb_cBignum, "&", rb_big_and_imp, 1);
-    rb_objc_define_method(rb_cBignum, "|", rb_big_or_imp, 1);
-    rb_objc_define_method(rb_cBignum, "^", rb_big_xor_imp, 1);
-    rb_objc_define_method(rb_cBignum, "~", rb_big_neg, 0);
-    rb_objc_define_method(rb_cBignum, "<<", rb_big_lshift_imp, 1);
-    rb_objc_define_method(rb_cBignum, ">>", rb_big_rshift_imp, 1);
-    rb_objc_define_method(rb_cBignum, "[]", rb_big_aref, 1);
-
-    rb_objc_define_method(rb_cBignum, "<=>", rb_big_cmp_imp, 1);
-    rb_objc_define_method(rb_cBignum, "==", rb_big_eq_imp, 1);
-    rb_objc_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
-    rb_objc_define_method(rb_cBignum, "hash", rb_big_hash, 0);
-    rb_objc_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
-    rb_objc_define_method(rb_cBignum, "abs", rb_big_abs, 0);
-    rb_objc_define_method(rb_cBignum, "size", rb_big_size, 0);
-    rb_objc_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0);
-    rb_objc_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
-
-    power_cache_init();
-
-#if WITH_OBJC
-    rb_install_nsnumber_primitives();
-#endif
-}

Deleted: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bridgesupport.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1682 +0,0 @@
-/*
- * MacRuby BridgeSupport implementation.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- */
-
-#if MACRUBY_STATIC
-# include <vector>
-# include <map>
-# include <string>
-#else
-# include <llvm/Module.h>
-# include <llvm/DerivedTypes.h>
-# include <llvm/Constants.h>
-# include <llvm/CallingConv.h>
-# include <llvm/Instructions.h>
-# include <llvm/Intrinsics.h>
-# include <llvm/Analysis/DebugInfo.h>
-# if !defined(LLVM_TOT)
-#  include <llvm/Analysis/DIBuilder.h>
-# endif
-# include <llvm/ExecutionEngine/JIT.h>
-# include <llvm/PassManager.h>
-# include <llvm/Target/TargetData.h>
-using namespace llvm;
-#endif
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "compiler.h"
-#include "bridgesupport.h"
-#include "objc.h"
-#include "class.h"
-
-#include <execinfo.h>
-#include <dlfcn.h>
-#include <sys/stat.h>
-
-static bool bridgesupport_tot = false;
-static ID boxed_ivar_type = 0;
-static VALUE bs_const_magic_cookie = Qnil;
-
-VALUE rb_cBoxed;
-VALUE rb_cPointer;
-
-typedef struct rb_vm_pointer {
-    VALUE type;
-    size_t type_size;
-    VALUE (*convert_to_rval)(void *);
-    void (*convert_to_ocval)(VALUE rval, void *);
-    void *val;
-    size_t len; // if 0, we don't know...
-} rb_vm_pointer_t;
-
-static inline ID
-generate_const_name(char *name)
-{
-    ID id;
-    if (islower(name[0])) {
-	name[0] = toupper(name[0]);
-	id = rb_intern(name);
-	name[0] = tolower(name[0]);
-	return id;
-    }
-    else {
-	return rb_intern(name);
-    }
-}
-extern "C"
-VALUE
-rb_vm_resolve_const_value(VALUE v, VALUE klass, ID id)
-{
-    if (v == bs_const_magic_cookie) {
-	bs_element_constant_t *bs_const = GET_CORE()->find_bs_const(id);
-	if (bs_const == NULL) {
-	    rb_bug("unresolved BridgeSupport constant `%s'",
-		    rb_id2name(id));
-	}
-
-	void *sym = dlsym(RTLD_DEFAULT, bs_const->name);
-	if (sym == NULL) {
-	    // The symbol can't be located, it's probably because the current
-	    // program links against a different version of the framework.
-	    rb_raise(rb_eRuntimeError, "can't locate symbol for constant %s",
-		rb_id2name(id));
-	}
-
-	if (bs_const->magic_cookie) {
-	    // Constant is a magic cookie. We don't support these yet.
-	    rb_raise(rb_eRuntimeError,
-		    "magic-cookie constant %s is not supported yet",
-		    rb_id2name(id));
-	}
-
-	void *convertor = GET_CORE()->gen_to_rval_convertor(bs_const->type);
-	v = ((VALUE (*)(void *))convertor)(sym);
-
-	CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
-	assert(iv_dict != NULL);
-	CFDictionarySetValue(iv_dict, (const void *)id, (const void *)v);
-    }
-    return v;
-}
-
-bs_element_constant_t *
-RoxorCore::find_bs_const(ID name)
-{
-    std::map<ID, bs_element_constant_t *>::iterator iter =
-	bs_consts.find(name);
-
-    return iter == bs_consts.end() ? NULL : iter->second;
-}
-
-bs_element_method_t *
-RoxorCore::find_bs_method(Class klass, SEL sel)
-{
-    std::map<std::string, std::map<SEL, bs_element_method_t *> *> &map =
-	class_isMetaClass(klass) ? bs_classes_class_methods
-	: bs_classes_instance_methods;
-
-    do {
-	std::map<std::string,
-		 std::map<SEL, bs_element_method_t *> *>::iterator iter =
-		     map.find(class_getName(klass));
-
-	if (iter != map.end()) {
-	    std::map<SEL, bs_element_method_t *> *map2 = iter->second;
-	    std::map<SEL, bs_element_method_t *>::iterator iter2 =
-		map2->find(sel);
-
-	    if (iter2 != map2->end()) {
-		return iter2->second;
-	    }
-	}
-
-	klass = class_getSuperclass(klass);
-    }
-    while (klass != NULL);
-
-    return NULL;
-}
-
-rb_vm_bs_boxed_t *
-RoxorCore::find_bs_boxed(std::string type)
-{
-    std::map<std::string, rb_vm_bs_boxed_t *>::iterator iter =
-	bs_boxed.find(type);
-
-    if (iter == bs_boxed.end()) {
-	return NULL;
-    }
-
-    return iter->second;
-}
-
-rb_vm_bs_boxed_t *
-RoxorCore::find_bs_struct(std::string type)
-{
-    rb_vm_bs_boxed_t *boxed = find_bs_boxed(type);
-    if (boxed != NULL) {
-	if (boxed->is_struct()) {
-	    return boxed;
-	}
-	return NULL;
-    }
-
-#if MACRUBY_STATIC
-    return NULL;
-#else
-    // Given structure type does not exist... but it may be an anonymous
-    // type (like {?=qq}) which is sometimes present in BridgeSupport files...
-    return register_anonymous_bs_struct(type.c_str());
-#endif
-}
-
-rb_vm_bs_boxed_t *
-RoxorCore::find_bs_opaque(std::string type)
-{
-    rb_vm_bs_boxed_t *boxed = find_bs_boxed(type);
-    return boxed == NULL ? NULL : boxed->is_struct() ? NULL : boxed;
-}
-
-bs_element_cftype_t *
-RoxorCore::find_bs_cftype(std::string type)
-{
-    std::map<std::string, bs_element_cftype_t *>::iterator iter =
-	bs_cftypes.find(type);
-
-    return iter == bs_cftypes.end() ? NULL : iter->second;
-}
-
-std::string *
-RoxorCore::find_bs_informal_protocol_method(SEL sel, bool class_method)
-{
-    std::map<SEL, std::string *> &map = class_method
-	? bs_informal_protocol_cmethods : bs_informal_protocol_imethods;
-
-    std::map<SEL, std::string *>::iterator iter = map.find(sel);
-
-    return iter == map.end() ? NULL : iter->second;
-}
-
-bs_element_function_t *
-RoxorCore::find_bs_function(std::string &name)
-{
-    std::map<std::string, bs_element_function_t *>::iterator iter =
-	bs_funcs.find(name);
-
-    return iter == bs_funcs.end() ? NULL : iter->second;
-}
-
-static rb_vm_bs_boxed_t *
-locate_bs_boxed(VALUE klass, const bool struct_only=false)
-{
-    VALUE type = rb_attr_get(klass, boxed_ivar_type);
-    assert(type != Qnil);
-    rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_boxed(RSTRING_PTR(type));
-    assert(bs_boxed != NULL);
-    if (struct_only) {
-	assert(bs_boxed->is_struct());
-    }
-    return bs_boxed;
-}
-
-#if !defined(MACRUBY_STATIC)
-extern "C"
-void
-rb_vm_check_arity(int given, int requested)
-{
-    if (given != requested) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		given, requested);
-    }
-}
-
-void
-RoxorCompiler::compile_check_arity(Value *given, Value *requested)
-{
-    if (checkArityFunc == NULL) {
-	// void rb_vm_check_arity(int given, int requested);
-	checkArityFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_check_arity",
-		    VoidTy, Int32Ty, Int32Ty, NULL));
-    }
-
-    Value *args[] = {
-	given,
-	requested
-    };
-    compile_protected_call(checkArityFunc, args, args + 2);
-}
-
-extern "C"
-void
-rb_vm_set_struct(VALUE rcv, int field, VALUE val)
-{
-    VALUE *data;
-    Data_Get_Struct(rcv, VALUE, data);
-    GC_WB(&data[field], val);    
-}
-
-void
-RoxorCompiler::compile_set_struct(Value *rcv, int field, Value *val)
-{
-    if (setStructFunc == NULL) {
-	// void rb_vm_set_struct(VALUE rcv, int field, VALUE val);
-	setStructFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_set_struct",
-		    VoidTy, RubyObjTy, Int32Ty, RubyObjTy, NULL));
-    }
-
-    Value *args[] = {
-	rcv,
-	ConstantInt::get(Int32Ty, field),
-	val
-    };
-    CallInst::Create(setStructFunc, args, args + 3, "", bb);
-}
-
-Function *
-RoxorCompiler::compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed, int field)
-{
-    // VALUE foo(VALUE self, SEL sel, VALUE val);
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy, RubyObjTy, PtrTy, RubyObjTy, NULL));
-    Function::arg_iterator arg = f->arg_begin();
-    Value *self = arg++; 	// self
-    arg++;			// sel
-    Value *val = arg++; 	// val
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    assert((unsigned)field < bs_boxed->as.s->fields_count);
-    const char *ftype = bs_boxed->as.s->fields[field].type;
-    const Type *llvm_type = convert_type(ftype);
-
-    Value *fval = new AllocaInst(llvm_type, "", bb);
-    val = compile_conversion_to_c(ftype, val, fval);
-    val = compile_conversion_to_ruby(ftype, llvm_type, val);
-
-    compile_set_struct(self, field, val);
-
-    ReturnInst::Create(context, val, bb);
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_bs_struct_new(rb_vm_bs_boxed_t *bs_boxed)
-{
-    // VALUE foo(VALUE self, SEL sel, int argc, VALUE *argv);
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy,
-		NULL));
-    Function::arg_iterator arg = f->arg_begin();
-    Value *klass = arg++; 	// self
-    arg++;			// sel
-    Value *argc = arg++; 	// argc
-    Value *argv = arg++; 	// argv
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    BasicBlock *no_args_bb = BasicBlock::Create(context, "no_args", f);
-    BasicBlock *args_bb  = BasicBlock::Create(context, "args", f);
-    Value *has_args = new ICmpInst(*bb, ICmpInst::ICMP_EQ, argc,
-	    ConstantInt::get(Int32Ty, 0));
-
-    BranchInst::Create(no_args_bb, args_bb, has_args, bb);
-
-    // No arguments are given, let's create Ruby field objects based on a
-    // zero-filled memory slot.
-    bb = no_args_bb;
-    std::vector<Value *> fields;
-
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	const char *ftype = bs_boxed->as.s->fields[i].type;
-	const Type *llvm_type = convert_type(ftype);
-	Value *fval = new AllocaInst(llvm_type, "", bb);
-
-	const size_t type_size = GET_CORE()->get_sizeof(llvm_type);
-
-	Value *args[] = {
-	    new BitCastInst(fval, PtrTy, "", bb),  	// start
-	    ConstantInt::get(Int8Ty, 0),		// value
-	    ConstantInt::get(IntTy, type_size),		// size
-	    ConstantInt::get(Int32Ty, 0),		// align
-	    ConstantInt::get(Int1Ty, 0)			// volatile
-	};
-	const Type *Tys[] = { args[0]->getType(), args[2]->getType() };
-	Function *memset_func = Intrinsic::getDeclaration(module,
-		Intrinsic::memset, Tys, 2);
-	assert(memset_func != NULL);
-	CallInst::Create(memset_func, args, args + 5, "", bb);
-
-	fval = new LoadInst(fval, "", bb);
-	fval = compile_conversion_to_ruby(ftype, llvm_type, fval);
-
-	fields.push_back(fval);
-    }
-
-    ReturnInst::Create(context, compile_new_struct(klass, fields), bb);
-
-    // Arguments are given. Need to check given arity, then convert the given
-    // Ruby values into the requested struct field types.
-    bb = args_bb;
-    fields.clear();
-
-    compile_check_arity(argc,
-	    ConstantInt::get(Int32Ty, bs_boxed->as.s->fields_count));
-
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	const char *ftype = bs_boxed->as.s->fields[i].type;
-	const Type *llvm_type = convert_type(ftype);
-	Value *fval = new AllocaInst(llvm_type, "", bb);
-
-	Value *index = ConstantInt::get(Int32Ty, i);
-	Value *arg = GetElementPtrInst::Create(argv, index, "", bb);
-	arg = new LoadInst(arg, "", bb);
-	compile_conversion_to_c(ftype, arg, fval);
-	arg = new LoadInst(fval, "", bb);
-	arg = compile_conversion_to_ruby(ftype, llvm_type, arg);
-
-	fields.push_back(arg);
-    }
-
-    ReturnInst::Create(context, compile_new_struct(klass, fields), bb);
-
-    return f;
-}
-
-static VALUE
-rb_vm_struct_fake_new(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    // Generate the real #new method.
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(rcv, true);
-    GET_CORE()->lock();
-    Function *f = RoxorCompiler::shared->compile_bs_struct_new(bs_boxed);
-    IMP imp = GET_CORE()->compile(f);
-    GET_CORE()->unlock();
-
-    // Replace the fake method with the new one in the runtime.
-    rb_objc_define_method(*(VALUE *)rcv, "new", (void *)imp, -1); 
-
-    // Call the new method.
-    return ((VALUE (*)(VALUE, SEL, int, VALUE *))imp)(rcv, sel, argc, argv);
-}
-
-static VALUE
-rb_vm_struct_fake_set(VALUE rcv, SEL sel, VALUE val)
-{
-    // Locate the given field.
-    char buf[100];
-    const char *selname = sel_getName(sel);
-    size_t s = strlcpy(buf, selname, sizeof buf);
-    if (buf[s - 1] == ':') {
-	s--;
-    }
-    assert(buf[s - 1] == '=');
-    buf[s - 1] = '\0';
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(CLASS_OF(rcv), true);
-    int field = -1;
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	const char *fname = bs_boxed->as.s->fields[i].name;
-	if (strcmp(fname, buf) == 0) {
-	    field = i;
-	    break;
-	}
-    }
-    assert(field != -1); 
-
-    // Generate the new setter method.
-    GET_CORE()->lock();
-    Function *f = RoxorCompiler::shared->compile_bs_struct_writer(
-	    bs_boxed, field);
-    IMP imp = GET_CORE()->compile(f);
-    GET_CORE()->unlock();
-
-    // Replace the fake method with the new one in the runtime.
-    buf[s - 1] = '=';
-    buf[s] = '\0';
-    rb_objc_define_method(*(VALUE *)rcv, buf, (void *)imp, 1); 
-
-    // Call the new method.
-    return ((VALUE (*)(VALUE, SEL, VALUE))imp)(rcv, sel, val);
-}
-
-// Readers are statically generated.
-#include "bs_struct_readers.c"
-
-static VALUE
-rb_vm_boxed_equal(VALUE rcv, SEL sel, VALUE val)
-{
-    if (rcv == val) {
-	return Qtrue;
-    }
-    VALUE klass = CLASS_OF(rcv);
-    if (!rb_obj_is_kind_of(val, klass)) {
-	return Qfalse;
-    }
-
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(klass);
-
-    VALUE *rcv_data; Data_Get_Struct(rcv, VALUE, rcv_data);
-    VALUE *val_data; Data_Get_Struct(val, VALUE, val_data);
-
-    if (bs_boxed->bs_type == BS_ELEMENT_STRUCT) {
-	for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	    if (!rb_equal(rcv_data[i], val_data[i])) {
-		return Qfalse;
-	    }
-	}
-	return Qtrue;
-    }
-
-    return rcv_data == val_data ? Qtrue : Qfalse;
-}
-
-static VALUE
-rb_vm_struct_inspect(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_str_new2("#<");
-    rb_str_cat2(str, rb_obj_classname(rcv));
-
-    VALUE *rcv_data;
-    Data_Get_Struct(rcv, VALUE, rcv_data);
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(CLASS_OF(rcv), true);
-
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	rb_str_cat2(str, " ");
-	rb_str_cat2(str, bs_boxed->as.s->fields[i].name);
-	rb_str_cat2(str, "=");
-	rb_str_append(str, rb_inspect(rcv_data[i]));
-    }
-
-    rb_str_cat2(str, ">");
-
-    return str;
-}
-
-static VALUE
-rb_vm_struct_to_a(VALUE rcv, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-
-    VALUE *rcv_data;
-    Data_Get_Struct(rcv, VALUE, rcv_data);
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(CLASS_OF(rcv), true);
-
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	rb_ary_push(ary, rcv_data[i]);
-    }
-
-    return ary;
-}
-
-static VALUE
-rb_vm_struct_aref(VALUE rcv, SEL sel, VALUE index)
-{
-    const long idx = NUM2LONG(index);
-
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(CLASS_OF(rcv), true);
-    if (idx < 0 || (unsigned long)idx >= bs_boxed->as.s->fields_count) {
-	rb_raise(rb_eArgError, "given index %ld out of bounds", idx);
-    }
-
-    VALUE *rcv_data;
-    Data_Get_Struct(rcv, VALUE, rcv_data);
-
-    return rcv_data[idx];
-}
-
-static VALUE
-rb_vm_struct_aset(VALUE rcv, SEL sel, VALUE index, VALUE val)
-{
-    const long idx = NUM2LONG(index);
-
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(CLASS_OF(rcv), true);
-    if (idx < 0 || (unsigned long)idx >= bs_boxed->as.s->fields_count) {
-	rb_raise(rb_eArgError, "given index %ld out of bounds", idx);
-    }
-
-    char buf[100];
-    snprintf(buf, sizeof buf, "%s=:", bs_boxed->as.s->fields[idx].name);
-
-    return rb_vm_call(rcv, sel_registerName(buf), 1, &val);
-}
-
-static VALUE
-rb_vm_struct_dup(VALUE rcv, SEL sel)
-{
-    VALUE klass = CLASS_OF(rcv);
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(klass, true);
-
-    VALUE *rcv_data;
-    Data_Get_Struct(rcv, VALUE, rcv_data);
-    VALUE *new_data = (VALUE *)xmalloc(
-	    bs_boxed->as.s->fields_count * sizeof(VALUE));
-    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	VALUE field = rcv_data[i];
-	// Numeric values cannot be duplicated.
-	if (!rb_obj_is_kind_of(field, rb_cNumeric)) {
-	    field = rb_send_dup(field);
-	}
-	GC_WB(&new_data[i], field);
-    }
-
-    return Data_Wrap_Struct(klass, NULL, NULL, new_data);
-}
-
-static VALUE
-rb_boxed_fields(VALUE rcv, SEL sel)
-{
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(rcv);
-    VALUE ary = rb_ary_new();
-    if (bs_boxed->bs_type == BS_ELEMENT_STRUCT) {
-	for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	    VALUE field = ID2SYM(rb_intern(bs_boxed->as.s->fields[i].name));
-	    rb_ary_push(ary, field);
-	}
-    }
-    return ary;
-}
-
-static VALUE
-rb_boxed_size(VALUE rcv, SEL sel)
-{
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(rcv);
-    if (bs_boxed->bs_type == BS_ELEMENT_STRUCT) {
-	return LONG2NUM(GET_CORE()->get_sizeof(bs_boxed->as.s->type));
-    }
-    return Qnil;
-}
-
-static VALUE
-rb_vm_opaque_new(VALUE rcv, SEL sel)
-{
-    // XXX instead of doing this, we should perhaps simply delete the new
-    // method on the class...
-    rb_raise(rb_eRuntimeError, "can't allocate opaque type `%s'",
-	    rb_class2name(rcv)); 
-}
-
-bool
-RoxorCore::register_bs_boxed(bs_element_type_t type, void *value)
-{
-    std::string octype(((bs_element_opaque_t *)value)->type);
-
-    std::map<std::string, rb_vm_bs_boxed_t *>::iterator iter =
-	bs_boxed.find(octype);
-
-    if (iter != bs_boxed.end()) {
-	// A boxed class of this type already exists, so let's create an
-	// alias to it.
-	rb_vm_bs_boxed_t *boxed = iter->second;
-	const ID name = rb_intern(((bs_element_opaque_t *)value)->name);
-	rb_const_set(rb_cObject, name, boxed->klass);
-	return false;
-    }
-
-    rb_vm_bs_boxed_t *boxed = (rb_vm_bs_boxed_t *)malloc(
-	    sizeof(rb_vm_bs_boxed_t));
-
-    boxed->bs_type = type;
-    boxed->as.v = value;
-    boxed->type = NULL; // lazy
-    boxed->klass = rb_define_class(((bs_element_opaque_t *)value)->name,
-	    rb_cBoxed);
-
-    rb_ivar_set(boxed->klass, boxed_ivar_type, rb_str_new2(octype.c_str()));
-
-    if (type == BS_ELEMENT_STRUCT && !boxed->as.s->opaque) {
-	// Define the fake #new method.
-	rb_objc_define_method(*(VALUE *)boxed->klass, "new",
-		(void *)rb_vm_struct_fake_new, -1);
-
-	// Define accessors.
-	assert(boxed->as.s->fields_count <= BS_STRUCT_MAX_FIELDS);
-	for (unsigned i = 0; i < boxed->as.s->fields_count; i++) {
-	    // Readers.
-	    rb_objc_define_method(boxed->klass, boxed->as.s->fields[i].name,
-		    (void *)struct_readers[i], 0);
-	    // Writers.
-	    char buf[100];
-	    snprintf(buf, sizeof buf, "%s=", boxed->as.s->fields[i].name);
-	    rb_objc_define_method(boxed->klass, buf,
-		    (void *)rb_vm_struct_fake_set, 1);
-	}
-
-	// Define other utility methods.
-	rb_objc_define_method(*(VALUE *)boxed->klass, "fields",
-		(void *)rb_boxed_fields, 0);
-	rb_objc_define_method(*(VALUE *)boxed->klass, "size",
-		(void *)rb_boxed_size, 0);
-	rb_objc_define_method(boxed->klass, "dup",
-		(void *)rb_vm_struct_dup, 0);
-	rb_objc_define_method(boxed->klass, "clone",
-		(void *)rb_vm_struct_dup, 0);
-	rb_objc_define_method(boxed->klass, "inspect",
-		(void *)rb_vm_struct_inspect, 0);
-	rb_objc_define_method(boxed->klass, "to_a",
-		(void *)rb_vm_struct_to_a, 0);
-	rb_objc_define_method(boxed->klass, "[]",
-		(void *)rb_vm_struct_aref, 1);
-	rb_objc_define_method(boxed->klass, "[]=",
-		(void *)rb_vm_struct_aset, 2);
-    }
-    else {
-	// Opaque methods.
-	rb_objc_define_method(*(VALUE *)boxed->klass, "new",
-		(void *)rb_vm_opaque_new, -1);
-    }
-    // Common methods.
-    rb_objc_define_method(boxed->klass, "==", (void *)rb_vm_boxed_equal, 1);
-
-    bs_boxed[octype] = boxed;
-
-    return true;
-}
-
-rb_vm_bs_boxed_t *
-RoxorCore::register_anonymous_bs_struct(const char *type)
-{
-    const size_t type_len = strlen(type);
-    assert(type_len > 0);
-
-    if (type_len < 3 || type[0] != _C_STRUCT_B || type[1] != '?'
-	    || type[2] != '=') {
-	// Does not look like an anonymous struct...
-	return NULL;
-    }
-
-    // Prepare the list of field types.
-    const size_t buf_len = type_len + 1;
-    char *buf = (char *)malloc(buf_len);
-    std::vector<std::string> s_types;
-    const char *p = &type[3];
-    while (*p != _C_STRUCT_E) {
-	p = GetFirstType(p, buf, buf_len);
-	assert(*p != '\0');
-	s_types.push_back(buf);
-    }
-    free(buf);
-
-    // Prepare the BridgeSupport structure.
-    bs_element_struct_t *bs_struct = (bs_element_struct_t *)
-	malloc(sizeof(bs_element_struct_t));
-    bs_struct->name = (char *)"?";
-    bs_struct->type = strdup(type);
-    bs_struct->fields_count = s_types.size();
-    assert(bs_struct->fields_count > 0);
-    bs_struct->fields = (bs_element_struct_field_t *)
-	malloc(sizeof(bs_element_struct_field_t) * bs_struct->fields_count);
-    for (unsigned i = 0; i < bs_struct->fields_count; i++) {
-	bs_element_struct_field_t *field = &bs_struct->fields[i];
-	field->name = (char *)"?";
-	field->type = strdup(s_types.at(i).c_str());
-    }
-    bs_struct->opaque = false;
-
-    // Prepare the boxed structure.
-    rb_vm_bs_boxed_t *boxed = (rb_vm_bs_boxed_t *)
-	malloc(sizeof(rb_vm_bs_boxed_t));
-    boxed->bs_type = BS_ELEMENT_STRUCT;
-    boxed->as.s = bs_struct;
-    boxed->type = NULL; // Lazy
-    boxed->klass = rb_cBoxed; // This type has no class
-
-    // Register it to the runtime.
-    bs_boxed[type] = boxed;
-    return boxed;
-}
-
-static inline long
-rebuild_new_struct_ary(const StructType *type, VALUE orig, VALUE new_ary)
-{
-    long n = 0;
-    for (StructType::element_iterator iter = type->element_begin();
-	    iter != type->element_end();
-	    ++iter) {
-	const Type *ftype = *iter;
-	if (ftype->getTypeID() == Type::StructTyID) {
-            const long n2 = rebuild_new_struct_ary(cast<StructType>(ftype), orig, new_ary);
-            VALUE tmp = rb_ary_new();
-            for (long i = 0; i < n2; i++) {
-                if (RARRAY_LEN(orig) == 0) {
-                    return 0;
-		}
-                rb_ary_push(tmp, rb_ary_shift(orig));
-            }
-            rb_ary_push(new_ary, tmp);
-        }
-        n++;
-    }
-    return n;
-}
-
-extern "C"
-void
-rb_vm_get_struct_fields(VALUE rval, VALUE *buf, rb_vm_bs_boxed_t *bs_boxed)
-{
-    if (TYPE(rval) == T_ARRAY) {
-	unsigned n = RARRAY_LEN(rval);
-	if (n < bs_boxed->as.s->fields_count) {
-	    rb_raise(rb_eArgError,
-		    "not enough elements in array `%s' to create " \
-		    "structure `%s' (%d for %d)",
-		    RSTRING_PTR(rb_inspect(rval)), bs_boxed->as.s->name, n,
-		    bs_boxed->as.s->fields_count);
-	}
-
-	if (n > bs_boxed->as.s->fields_count) {
-	    VALUE new_rval = rb_ary_new();
-	    VALUE orig = rval;
-	    rval = rb_ary_dup(rval);
-	    rebuild_new_struct_ary(cast<StructType>(bs_boxed->type), rval,
-		    new_rval);
-	    n = RARRAY_LEN(new_rval);
-	    if (RARRAY_LEN(rval) != 0 || n != bs_boxed->as.s->fields_count) {
-		rb_raise(rb_eArgError,
-			"too much elements in array `%s' to create " \
-			"structure `%s' (%ld for %d)",
-			RSTRING_PTR(rb_inspect(orig)),
-			bs_boxed->as.s->name, RARRAY_LEN(orig),
-			bs_boxed->as.s->fields_count);
-	    }
-	    rval = new_rval;
-	}
-
-	for (unsigned i = 0; i < n; i++) {
-	    buf[i] = RARRAY_AT(rval, i);
-	}
-    }
-    else {
-	if (!rb_obj_is_kind_of(rval, bs_boxed->klass)) {
-	    rb_raise(rb_eTypeError, 
-		    "expected instance of `%s', got `%s' (%s)",
-		    rb_class2name(bs_boxed->klass),
-		    RSTRING_PTR(rb_inspect(rval)),
-		    rb_obj_classname(rval));
-	}
-
-	if (bs_boxed->klass == rb_cBoxed) {
-	    // An anonymous type...
-	    // Let's check that the given boxed object matches the types.
-	    rb_vm_bs_boxed_t *rval_bs_boxed =
-		locate_bs_boxed(CLASS_OF(rval), true);
-	    assert(rval_bs_boxed != NULL);
-
-	    if (rval_bs_boxed->as.s->fields_count
-		    != bs_boxed->as.s->fields_count) {
-		rb_raise(rb_eTypeError,
-			"expected instance of Boxed with %d fields, got %d",
-			bs_boxed->as.s->fields_count, 
-			rval_bs_boxed->as.s->fields_count);
-	    }
-
-	    for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-		if (strcmp(bs_boxed->as.s->fields[i].type,
-			    rval_bs_boxed->as.s->fields[i].type) != 0) {
-		    rb_raise(rb_eTypeError,
-			"field %d of given instance of `%s' does not match " \
-			"the type expected (%s, got %s)",
-			i,
-			rb_class2name(bs_boxed->klass),
-			bs_boxed->as.s->fields[i].type,
-			rval_bs_boxed->as.s->fields[i].type);	
-		}
-	    }
-	}
-
-	VALUE *data;
-	Data_Get_Struct(rval, VALUE, data);
-
-	for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
-	    buf[i] = data[i];
-	}	
-    }
-}
-
-static const char *convert_ffi_type(VALUE type,
-	bool raise_exception_if_unknown);
-
-static void
-rb_pointer_init_type(rb_vm_pointer_t *ptr, VALUE type)
-{
-    const char *type_str = StringValuePtr(type);
-    // LLVM doesn't allow to get a pointer to Type::VoidTy, and for convenience
-    // reasons we map a pointer to void as a pointer to unsigned char.
-    if (*type_str == 'v') {
-        type_str = "C";
-        type = rb_str_new2(type_str);
-    }
-    GC_WB(&ptr->type, type);
-
-    RoxorCore *core = GET_CORE();
-
-    ptr->convert_to_rval =
-	(VALUE (*)(void *))core->gen_to_rval_convertor(type_str);
-    ptr->convert_to_ocval =
-	(void (*)(VALUE, void *))core->gen_to_ocval_convertor(type_str);
-
-    ptr->type_size = core->get_sizeof(type_str);
-    assert(ptr->type_size > 0);
-}
-
-extern "C"
-VALUE
-rb_pointer_new(const char *type_str, void *val, size_t len)
-{
-    rb_vm_pointer_t *ptr = (rb_vm_pointer_t *)xmalloc(sizeof(rb_vm_pointer_t));
-
-    rb_pointer_init_type(ptr, rb_str_new2(type_str));
-
-    GC_WB(&ptr->val, val);
-    ptr->len = len;
-
-    return Data_Wrap_Struct(rb_cPointer, NULL, NULL, ptr);
-}
-
-static VALUE
-rb_pointer_s_new(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE type, len;
-
-    rb_scan_args(argc, argv, "11", &type, &len);
-
-    size_t rlen = 1;
-    if (!NIL_P(len)) {
-	const long n = FIX2LONG(len);
-	if (n <= 0) {
-	    rb_raise(rb_eArgError, "given len must be greater than 0");
-	}
-	rlen = (size_t)n;
-    }
-
-    const char *type_str = convert_ffi_type(type, false);
-    // There's no such thing as void type in ruby
-    if (*type_str == 'v') {
-	rb_raise(rb_eTypeError, "Void pointer is not allowed");
-    }
-
-    return rb_pointer_new(type_str,
-	    xmalloc(GET_CORE()->get_sizeof(type_str) * rlen), rlen);
-}
-
-static VALUE
-rb_pointer_s_magic_cookie(VALUE rcv, SEL sel, VALUE val)
-{
-    long magic_cookie = NUM2LONG(val);
-
-    rb_vm_pointer_t *ptr = (rb_vm_pointer_t *)xmalloc(sizeof(rb_vm_pointer_t));
-    ptr->type = rb_str_new2("^v");
-    ptr->type_size = sizeof(void *);
-    ptr->convert_to_rval = NULL;
-    ptr->convert_to_ocval = NULL;
-    ptr->val = (void *)magic_cookie;
-    ptr->len = 1;
-
-    return Data_Wrap_Struct(rb_cPointer, NULL, NULL, ptr);
-}
-
-static void
-check_no_magic_cookie(rb_vm_pointer_t *ptr)
-{
-    if (ptr->convert_to_rval == NULL || ptr->convert_to_ocval == NULL) {
-	rb_raise(rb_eArgError, "cannot access magic cookie pointers");
-    }
-}
-
-static inline void *
-pointer_val(rb_vm_pointer_t *ptr, VALUE idx)
-{
-    const long i = NUM2LONG(idx);
-    if (i < 0) {
-	rb_raise(rb_eArgError, "index must not be negative");
-    }
-    if (ptr->len > 0 && (size_t)i >= ptr->len) {
-	rb_raise(rb_eArgError, "index %ld out of bounds (%ld)", i, ptr->len);
-    }
-    return (void *)((char *)ptr->val + (i * ptr->type_size));
-}
-
-static VALUE
-rb_pointer_aref(VALUE rcv, SEL sel, VALUE idx)
-{
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-
-    check_no_magic_cookie(ptr);
-    return ptr->convert_to_rval(pointer_val(ptr, idx));
-}
-
-static VALUE
-rb_pointer_aset(VALUE rcv, SEL sel, VALUE idx, VALUE val)
-{
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-
-    check_no_magic_cookie(ptr);
-    ptr->convert_to_ocval(val, pointer_val(ptr, idx));
-    return val;
-}
-
-static VALUE
-rb_pointer_assign(VALUE rcv, SEL sel, VALUE val)
-{
-    return rb_pointer_aset(rcv, 0, INT2FIX(0), val);
-}
-
-static VALUE
-rb_pointer_type(VALUE rcv, SEL sel)
-{
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-
-    return ptr->type;
-}
-
-static VALUE
-rb_pointer_cast(VALUE rcv, SEL sel, VALUE type)
-{
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-
-    check_no_magic_cookie(ptr);
-    rb_pointer_init_type(ptr, type);
-    return rcv;
-}
-
-static VALUE
-rb_pointer_offset(VALUE rcv, long off)
-{
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-
-    check_no_magic_cookie(ptr);
-
-    size_t new_len = 0;
-    if (ptr->len > 0) {
-	if (off > 0 && (size_t)off >= ptr->len) {
-	    rb_raise(rb_eArgError, "offset %ld out of bounds (%ld)", off,
-		    ptr->len);
-	}
-	new_len = ptr->len - off;
-    }
-
-    const char *type_str = StringValuePtr(ptr->type);
-    const size_t delta = off * ptr->type_size;
-    return rb_pointer_new(type_str, (char *)ptr->val + delta, new_len);
-}
-
-static VALUE
-rb_pointer_plus(VALUE rcv, SEL sel, VALUE offset)
-{
-    return rb_pointer_offset(rcv, NUM2LONG(offset));
-}
-
-static VALUE
-rb_pointer_minus(VALUE rcv, SEL sel, VALUE offset)
-{
-    return rb_pointer_offset(rcv, -NUM2LONG(offset));
-}
-
-static void
-index_bs_class_methods(const char *name,
-	std::map<std::string, std::map<SEL, bs_element_method_t *> *> &map,
-	bs_element_method_t *methods,
-	unsigned method_count)
-{
-    std::map<std::string, std::map<SEL, bs_element_method_t *> *>::iterator
-	iter = map.find(name);
-
-    std::map<SEL, bs_element_method_t *> *methods_map = NULL;	
-    if (iter == map.end()) {
-	methods_map = new std::map<SEL, bs_element_method_t *>();
-	map[name] = methods_map;
-    }
-    else {
-	methods_map = iter->second;
-    }
-
-    for (unsigned i = 0; i < method_count; i++) {
-	bs_element_method_t *m = &methods[i];
-	methods_map->insert(std::make_pair(m->name, m));
-    }
-} 
-
-void
-RoxorCore::register_bs_class(bs_element_class_t *bs_class)
-{
-    if (bs_class->class_methods_count > 0) {
-	index_bs_class_methods(bs_class->name,
-		bs_classes_class_methods,
-		bs_class->class_methods,
-		bs_class->class_methods_count);
-    }
-    if (bs_class->instance_methods_count > 0) {
-	index_bs_class_methods(bs_class->name,
-		bs_classes_instance_methods,
-		bs_class->instance_methods,
-		bs_class->instance_methods_count);
-    }
-}
-
-static void
-__bs_parse_cb(bs_parser_t *parser, const char *path, bs_element_type_t type, 
-	void *value, void *ctx)
-{
-    GET_CORE()->bs_parse_cb(type, value, ctx);
-}
-
-void
-RoxorCore::bs_parse_cb(bs_element_type_t type, void *value, void *ctx)
-{
-    bool do_not_free = false;
-    CFMutableDictionaryRef rb_cObject_dict = (CFMutableDictionaryRef)ctx;
-
-    switch (type) {
-	case BS_ELEMENT_ENUM:
-	{
-	    bs_element_enum_t *bs_enum = (bs_element_enum_t *)value;
-	    ID name = generate_const_name(bs_enum->name);
-	    if (!CFDictionaryGetValueIfPresent(rb_cObject_dict,
-			(const void *)name, NULL)) {
-
-		VALUE val = strchr(bs_enum->value, '.') != NULL
-		    ? rb_float_new(rb_cstr_to_dbl(bs_enum->value, 0))
-		    : rb_cstr_to_inum(bs_enum->value, 10, 0);
-		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
-			(const void *)val);
-	    }
-	    break;
-	}
-
-	case BS_ELEMENT_CONSTANT:
-	{
-	    bs_element_constant_t *bs_const = (bs_element_constant_t *)value;
-	    ID name = generate_const_name(bs_const->name);
-	    if (!CFDictionaryGetValueIfPresent(rb_cObject_dict,
-			(const void *)name, NULL)) {
-
-		bs_consts[name] = bs_const;
-		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
-			(const void *)bs_const_magic_cookie);
-		do_not_free = true;
-	    }
-	    break;
-	}
-
-	case BS_ELEMENT_STRING_CONSTANT:
-	{
-	    bs_element_string_constant_t *bs_strconst = 
-		(bs_element_string_constant_t *)value;
-	    ID name = generate_const_name(bs_strconst->name);
-	    if (!CFDictionaryGetValueIfPresent(rb_cObject_dict,
-			(const void *)name, NULL)) {
-
-		VALUE val = rb_str_new2(bs_strconst->value);
-		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
-			(const void *)val);
-	    }
-	    break;
-	}
-
-	case BS_ELEMENT_FUNCTION:
-	{
-	    bs_element_function_t *bs_func = (bs_element_function_t *)value;
-	    std::string name(bs_func->name);
-
-	    std::map<std::string, bs_element_function_t *>::iterator iter =
-		bs_funcs.find(name);
-	    if (iter == bs_funcs.end()) {
-		bs_funcs[name] = bs_func;
-		do_not_free = true;
-	    }
-	    break;
-	}
-
-	case BS_ELEMENT_FUNCTION_ALIAS:
-	{
-#if 0 // TODO
-	    bs_element_function_alias_t *bs_func_alias = 
-		(bs_element_function_alias_t *)value;
-	    bs_element_function_t *bs_func_original;
-	    if (st_lookup(bs_functions, 
-			(st_data_t)rb_intern(bs_func_alias->original), 
-			(st_data_t *)&bs_func_original)) {
-		st_insert(bs_functions, 
-			(st_data_t)rb_intern(bs_func_alias->name), 
-			(st_data_t)bs_func_original);
-	    }
-	    else {
-		rb_raise(rb_eRuntimeError, 
-			"cannot alias '%s' to '%s' because it doesn't exist", 
-			bs_func_alias->name, bs_func_alias->original);
-	    }
-#endif
-	    break;
-	}
-
-	case BS_ELEMENT_OPAQUE:
-	case BS_ELEMENT_STRUCT:
-	{
-	    if (register_bs_boxed(type, value)) {
-		do_not_free = true;
-	    }
-	    break;
-	}
-
-	case BS_ELEMENT_CLASS:
-	{
-	    bs_element_class_t *bs_class = (bs_element_class_t *)value;
-	    register_bs_class(bs_class);
-	    free(bs_class);
-	    do_not_free = true;
-	    break;
-	}
-
-	case BS_ELEMENT_INFORMAL_PROTOCOL_METHOD:
-	{
-	    bs_element_informal_protocol_method_t *bs_inf_prot_method = 
-		(bs_element_informal_protocol_method_t *)value;
-
-	    std::map<SEL, std::string *> &map =
-		bs_inf_prot_method->class_method
-		? bs_informal_protocol_cmethods
-		: bs_informal_protocol_imethods;
-
-	    char *type;
-	    if (bridgesupport_tot) {
-		type = bs_inf_prot_method->type;
-	    }
-	    else {
-#if __LP64__
-		// XXX workaround <rdar://problem/7318177> 64-bit informal protocol annotations are missing
-		// Manually converting some 32-bit types to 64-bit...
-		const size_t typelen = strlen(bs_inf_prot_method->type) + 1;
-		type = (char *)alloca(typelen);
-		*type = '\0';
-		const char *p = bs_inf_prot_method->type;
-		do {
-		    const char *p2 = (char *)SkipFirstType(p);
-		    size_t len = p2 - p;
-		    if (*p == _C_PTR && len > 1) {
-			strlcat(type, "^", typelen);
-			p++;
-			len--;
-		    }
-		    if (len == 1 && *p == _C_FLT) {
-			// float -> double
-			strlcat(type, "d", typelen);
-		    }
-		    else if (strncmp(p, "{_NSPoint=", 10) == 0) {
-			strlcat(type, "{CGPoint=dd}", typelen);
-		    }
-		    else if (strncmp(p, "{_NSSize=", 9) == 0) {
-			strlcat(type, "{CGSize=dd}", typelen);
-		    }
-		    else if (strncmp(p, "{_NSRect=", 9) == 0) {
-			strlcat(type, "{CGRect={CGPoint=dd}{CGSize=dd}}", typelen);
-		    }
-		    else if (strncmp(p, "{_NSRange=", 10) == 0) {
-			strlcat(type, "{_NSRange=QQ}", typelen);
-		    } 
-		    else {
-			char buf[100];
-			strncpy(buf, p, len);
-			buf[len] = '\0';
-			strlcat(type, buf, typelen);
-		    }
-		    p = SkipStackSize(p2);
-		}
-		while (*p != '\0');
-#else
-		type = bs_inf_prot_method->type;
-#endif
-	    }
-	    map[bs_inf_prot_method->name] = new std::string(type);
-	    break;
-	}
-
-	case BS_ELEMENT_CFTYPE:
-	{
-	    bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
-	    assert(bs_cftype->type[0] == _C_PTR);
-	    if (bs_cftype->type[1] == _C_VOID) {
-		// Do not register ^v as a valid CFType.
-		break;
-	    }
-	    std::map<std::string, bs_element_cftype_t *>::iterator
-		iter = bs_cftypes.find(bs_cftype->type);
-	    if (iter == bs_cftypes.end()) {
-		std::string s(bs_cftype->type);
-		bs_cftypes[s] = bs_cftype;
-		if (s.compare(s.size() - 2, 2, "=}") == 0) {
-		    // For ^{__CFError=}, also registering ^{__CFError}.
-		    // This is because functions or methods returning CF types
-		    // by reference strangely omit the '=' character as part
-		    // of their BridgeSupport signature.
-		    s.replace(s.size() - 2, 2, "}");
-		    bs_cftypes[s] = bs_cftype;
-		}
-		do_not_free = true;
-	    }
-	    break;
-	}
-    }
-
-    if (!do_not_free) {
-	bs_element_free(type, value);
-    }
-}
-
-extern "C"
-void
-rb_vm_load_bridge_support(const char *path, const char *framework_path,
-	int options)
-{
-    GET_CORE()->load_bridge_support(path, framework_path, options);
-}
-
-void
-RoxorCore::load_bridge_support(const char *path, const char *framework_path,
-	int options)
-{
-    CFMutableDictionaryRef rb_cObject_dict;  
-
-    if (bs_parser == NULL) {
-	bs_parser = bs_parser_new();
-    }
-
-    rb_cObject_dict = rb_class_ivar_dict(rb_cObject);
-    assert(rb_cObject_dict != NULL);
-
-    char *error = NULL;
-    const bool ok = bs_parser_parse(bs_parser, path, framework_path,
-	    (bs_parse_options_t)options, __bs_parse_cb, rb_cObject_dict,
-	    &error);
-    if (!ok) {
-	rb_raise(rb_eRuntimeError, "%s", error);
-    }
-    if (!bridgesupport_tot) {
-#if defined(__LP64__)
-	static bool R6399046_fixed = false;
-	// XXX work around for
-	// <rdar://problem/6399046> NSNotFound 64-bit value is incorrect
-	if (!R6399046_fixed) {
-	    const void *key = (const void *)rb_intern("NSNotFound");
-	    const void *real_val = (const void *)ULL2NUM(LONG_MAX);
-
-	    const void *val = CFDictionaryGetValue(rb_cObject_dict, key);
-	    if (val != real_val) {
-		CFDictionarySetValue(rb_cObject_dict, key, real_val);
-		R6399046_fixed = true;
-	    }
-	}
-#endif
-	static bool R7281806fixed = false;
-	// XXX work around for
-	// <rdar://problem/7281806> -[NSObject performSelector:] has wrong sel_of_type attributes
-	if (!R7281806fixed) {
-	    bs_element_method_t *bs_method = GET_CORE()->find_bs_method((Class)rb_cNSObject,
-		    sel_registerName("performSelector:"));
-	    if (bs_method != NULL) {
-		bs_element_arg_t *arg = bs_method->args;
-		while (arg != NULL) {
-		    if (arg->index == 0 
-			    && arg->sel_of_type != NULL
-			    && arg->sel_of_type[0] != '@') {
-			arg->sel_of_type[0] = '@';
-			R7281806fixed = true;
-			break;
-		    }
-		    arg++;
-		}
-	    }	
-	}
-    }
-}
-
-// FFI
-
-static std::map<ID, std::string> ffi_type_shortcuts;
-
-static void
-init_ffi_type_shortcuts(void)
-{
-#define SHORTCUT(name, type) \
-    ffi_type_shortcuts.insert(std::make_pair(rb_intern(name), type))
-
-    // Ruby-FFI types.
-    SHORTCUT("char", "c");
-    SHORTCUT("uchar", "C");
-    SHORTCUT("short", "s");
-    SHORTCUT("ushort", "S");
-    SHORTCUT("int", "i");
-    SHORTCUT("uint", "I");
-    SHORTCUT("long", "l");
-    SHORTCUT("ulong", "L");
-    SHORTCUT("long_long", "q");
-    SHORTCUT("ulong_long", "Q");
-    SHORTCUT("float", "f");
-    SHORTCUT("double", "d");
-    SHORTCUT("string", "*");
-    SHORTCUT("pointer", "^");
-
-    // MacRuby extensions.
-    SHORTCUT("object", "@");
-    SHORTCUT("id", "@");
-    SHORTCUT("class", "#");
-    SHORTCUT("boolean", "B");
-    SHORTCUT("bool", "B");
-    SHORTCUT("selector", ":");
-    SHORTCUT("sel", ":");
-
-#undef SHORTCUT
-}
-
-static const char *
-convert_ffi_type(VALUE type, bool raise_exception_if_unknown)
-{
-    // Only accept symbols as type shortcuts.
-    if (TYPE(type) != T_SYMBOL) {
-	return StringValueCStr(type);
-    }
-
-    std::map<ID, std::string>::iterator iter =
-	ffi_type_shortcuts.find(SYM2ID(type));
-
-    if (iter == ffi_type_shortcuts.end()) {
-	rb_raise(rb_eTypeError, "unrecognized symbol :%s given as FFI type",
-		rb_id2name(SYM2ID(type)));
-    }
-
-    return iter->second.c_str();
-}
-
-Function *
-RoxorCompiler::compile_ffi_function(void *stub, void *imp, int argc)
-{
-    // VALUE func(VALUE rcv, SEL sel, VALUE arg1, VALUE arg2, ...) {
-    //     VALUE *argv = alloca(...);
-    //     return stub(imp, argc, argv);
-    // }
-    std::vector<const Type *> f_types;
-    f_types.push_back(RubyObjTy);
-    f_types.push_back(PtrTy);
-    for (int i = 0; i < argc; i++) {
-	f_types.push_back(RubyObjTy);
-    }
-    FunctionType *ft = FunctionType::get(RubyObjTy, f_types, false);
-    Function *f = cast<Function>(module->getOrInsertFunction("", ft));
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    Function::arg_iterator arg = f->arg_begin();
-    arg++; // skip self
-    arg++; // skip sel
-
-    std::vector<Value *> params;
-    std::vector<const Type *> stub_types;
-
-    // First argument is the function implementation. 
-    params.push_back(compile_const_pointer(imp));
-    stub_types.push_back(PtrTy);
-
-    // Second argument is arity;
-    params.push_back(ConstantInt::get(Int32Ty, argc));
-    stub_types.push_back(Int32Ty);
-
-    // Third is an array of arguments.
-    Value *argv;
-    if (argc == 0) {
-	argv = new BitCastInst(compile_const_pointer(NULL), RubyObjPtrTy,
-		"", bb);
-    }
-    else {
-	argv = new AllocaInst(RubyObjTy, ConstantInt::get(Int32Ty, argc),
-		"", bb);
-	for (int i = 0; i < argc; i++) {
-	    Value *index = ConstantInt::get(Int32Ty, i);
-	    Value *slot = GetElementPtrInst::Create(argv, index, "", bb);
-	    new StoreInst(arg++, slot, "", bb);
-	}
-    }
-    params.push_back(argv);
-    stub_types.push_back(RubyObjPtrTy);
-
-    // Cast the given stub using the correct function signature.
-    FunctionType *stub_ft = FunctionType::get(RubyObjTy, stub_types, false);
-    Value *stub_val = new BitCastInst(compile_const_pointer(stub),
-	    PointerType::getUnqual(stub_ft), "", bb);
-
-    // Call the stub and return its return value.
-    CallInst *stub_call = CallInst::Create(stub_val, params.begin(),
-	    params.end(), "", bb); 
-    ReturnInst::Create(context, stub_call, bb);
-
-    return f;
-}
-
-static VALUE
-rb_ffi_attach_function(VALUE rcv, SEL sel, VALUE name, VALUE args, VALUE ret)
-{
-    const char *symname;
-    if (TYPE(name) == T_SYMBOL) {
-	symname = rb_id2name(SYM2ID(name));
-    }
-    else {
-	StringValue(name);
-	symname = RSTRING_PTR(name);
-    }
-    void *sym = dlsym(RTLD_DEFAULT, symname);
-    if (sym == NULL) {
-	rb_raise(rb_eArgError, "given function `%s' could not be located",
-		symname);
-    }
-
-    std::string types;
-    types.append(convert_ffi_type(ret, true));
-
-    Check_Type(args, T_ARRAY);
-    const int argc = RARRAY_LEN(args);
-    for (int i = 0; i < argc; i++) {
-	types.append(convert_ffi_type(RARRAY_AT(args, i), true));
-    } 
-
-    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
-	    false, argc, false);
-    Function *f = RoxorCompiler::shared->compile_ffi_function((void *)stub,
-	    sym, argc);
-    IMP imp = GET_CORE()->compile(f);
-
-    VALUE klass = rb_singleton_class(rcv);
-    rb_objc_define_method(klass, symname, (void *)imp, argc);
-
-    return Qnil;
-}
-
-#endif // !MACRUBY_STATIC
-
-static VALUE
-rb_boxed_objc_type(VALUE rcv, SEL sel)
-{
-    return rb_attr_get(rcv, boxed_ivar_type);
-}
-
-static VALUE
-rb_boxed_is_opaque(VALUE rcv, SEL sel)
-{
-    rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(rcv);
-    return bs_boxed->bs_type == BS_ELEMENT_OPAQUE ? Qtrue : Qfalse;
-}
-
-extern "C"
-void
-Init_BridgeSupport(void)
-{
-    struct stat s;
-    bridgesupport_tot =
-	stat("/System/Library/BridgeSupport/ruby-1.8/bridgesupportparser.bundle",
-		&s) == 0;
-
-    // Boxed
-    rb_cBoxed = rb_define_class("Boxed", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cBoxed, "type",
-	    (void *)rb_boxed_objc_type, 0);
-    rb_objc_define_method(*(VALUE *)rb_cBoxed, "opaque?",
-	    (void *)rb_boxed_is_opaque, 0);
-    boxed_ivar_type = rb_intern("__octype__");
-
-    // Pointer
-    rb_cPointer = rb_define_class("Pointer", rb_cObject);
-#if !defined(MACRUBY_STATIC)
-    rb_objc_define_method(*(VALUE *)rb_cPointer, "new",
-	    (void *)rb_pointer_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cPointer, "new_with_type",
-	    (void *)rb_pointer_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cPointer, "magic_cookie",
-	    (void *)rb_pointer_s_magic_cookie, 1);
-    rb_objc_define_method(rb_cPointer, "[]", (void *)rb_pointer_aref, 1);
-    rb_objc_define_method(rb_cPointer, "[]=", (void *)rb_pointer_aset, 2);
-    rb_objc_define_method(rb_cPointer, "assign", (void *)rb_pointer_assign, 1);
-    rb_objc_define_method(rb_cPointer, "type", (void *)rb_pointer_type, 0);
-    rb_objc_define_method(rb_cPointer, "cast!", (void *)rb_pointer_cast, 1);
-    rb_objc_define_method(rb_cPointer, "+", (void *)rb_pointer_plus, 1);
-    rb_objc_define_method(rb_cPointer, "-", (void *)rb_pointer_minus, 1);
-#endif
-
-    bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie");
-    GC_RETAIN(bs_const_magic_cookie);
-}
-
-extern "C"
-void
-Init_FFI(void)
-{
-#if !defined(MACRUBY_STATIC)
-    VALUE mFFI = rb_define_module("FFI");
-    VALUE mFFILib = rb_define_module_under(mFFI, "Library");
-    rb_objc_define_method(mFFILib, "attach_function",
-	    (void *)rb_ffi_attach_function, 3);
-
-    init_ffi_type_shortcuts();
-#endif
-}
-
-// Comparing types by making sure '=' characters are ignored, since these
-// may be sometimes present, sometimes not present in signatures returned by
-// the runtime or BridgeSupport files.
-static bool
-compare_types(const char *t1, const char *t2)
-{
-    while (true) {
-	if (*t1 == '=') {
-	    t1++;
-	}
-	if (*t2 == '=') {
-	    t2++;
-	}
-	if (*t1 != *t2) {
-	    return false;
-	}
-	if (*t1 == '\0') {
-	    break;
-	}
-	t1++;
-	t2++;
-    }
-    return true;
-}
-
-// Called by the kernel:
-
-extern "C"
-void *
-rb_pointer_get_data(VALUE rcv, const char *type)
-{
-    if (!rb_obj_is_kind_of(rcv, rb_cPointer)) {
-	rb_raise(rb_eTypeError,
-		"expected instance of Pointer, got `%s' (%s)",
-		RSTRING_PTR(rb_inspect(rcv)),
-		rb_obj_classname(rcv));
-    }
-
-    rb_vm_pointer_t *ptr;
-    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
-    const char *ptr_type = RSTRING_PTR(ptr->type);
-
-    assert(type[0] == _C_PTR);
-    // Sanity pointer type comparison check, unless the given pointer type
-    // is 'C' (which means converted from void*) or the target argument pointer
-    // type is void*.
-    const char *p = &type[1];
-    while (*p == _C_PTR) {
-	p++;
-    }
-    if (*p != _C_VOID && ptr_type[0] != _C_UCHR
-	    && !compare_types(ptr_type, &type[1])) {
-	rb_raise(rb_eTypeError,
-		"expected instance of Pointer of type `%s', got `%s'",
-		type + 1,
-		ptr_type);
-    }
-
-    return ptr->val;
-}
-
-extern "C"
-bool
-rb_boxed_is_type(VALUE klass, const char *type)
-{
-    VALUE rtype = rb_boxed_objc_type(klass, 0);
-    if (rtype == Qnil) {
-	return false;
-    }
-    if (strcmp(RSTRING_PTR(rtype), type) != 0) {
-	rb_raise(rb_eTypeError,
-		"expected instance of Boxed class of type `%s', "\
-		"got `%s' of type `%s'",
-		type,
-		rb_class2name(klass),
-		RSTRING_PTR(rtype));
-    }
-    return true;
-}
-
-extern "C"
-VALUE
-rb_pointer_new2(const char *type_str, VALUE rval)
-{
-#if MACRUBY_STATIC
-    abort(); // TODO
-#else
-    VALUE p;
-
-    if (TYPE(rval) == T_ARRAY) {
-	const long len = RARRAY_LEN(rval);
-	if (len == 0) {
-	    rb_raise(rb_eArgError,
-		    "can't convert an empty array to a `%s' pointer",
-		    type_str);
-	}
-	p = rb_pointer_new(type_str,
-		xmalloc(GET_CORE()->get_sizeof(type_str) * len), len);
-	for (int i = 0; i < len; i++) {
-	    rb_pointer_aset(p, 0, INT2FIX(i), RARRAY_AT(rval, i));
-	}
-    }
-    else {
-	p = rb_pointer_new(type_str,
-		xmalloc(GET_CORE()->get_sizeof(type_str)), 1);
-	rb_pointer_aset(p, 0, INT2FIX(0), rval);
-    }
-
-    return p;
-#endif
-}
-

Deleted: MacRuby/trunk/bridgesupport.h
===================================================================
--- MacRuby/trunk/bridgesupport.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bridgesupport.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,42 +0,0 @@
-/*
- * MacRuby BridgeSupport implementation.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __BRIDGESUPPORT_H_
-#define __BRIDGESUPPORT_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include "bs.h"
-
-void *rb_pointer_get_data(VALUE rcv, const char *type);
-VALUE rb_pointer_new(const char *type_str, void *val, size_t len);
-VALUE rb_pointer_new2(const char *type_str, VALUE val);
-bool rb_boxed_is_type(VALUE klass, const char *type);
-
-#if defined(__cplusplus)
-} // extern "C"
-
-typedef struct rb_vm_bs_boxed {
-    bs_element_type_t bs_type;
-    bool is_struct(void) { return bs_type == BS_ELEMENT_STRUCT; }
-    union {
-	bs_element_struct_t *s;
-	bs_element_opaque_t *o;
-	void *v;
-    } as;
-#if !defined(MACRUBY_STATIC)
-    Type *type;
-#endif
-    VALUE klass;
-} rb_vm_bs_boxed_t;
-
-#endif /* __cplusplus */
-
-#endif /* __BRIDGESUPPORT_H_ */

Deleted: MacRuby/trunk/bs.c
===================================================================
--- MacRuby/trunk/bs.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bs.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1465 +0,0 @@
-/*  
- *  Copyright (c) 2008-2011, Apple Inc. All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *  1.  Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *  2.  Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *  3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *      its contributors may be used to endorse or promote products derived
- *      from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
- *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- *  ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
- *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- *  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if !defined(MACRUBY_STATIC)
-
-#include "bs.h"
-
-#include <libxml/xmlreader.h>
-#include <dlfcn.h>
-#include <libgen.h>
-#include <unistd.h>
-
-#include "bs_lex.h"
-
-#define ASSERT_ALLOC(ptr) (assert(ptr != NULL))
-
-static inline char *
-get_framework_name(const char *path)
-{
-  char *base;
-  char *name;
-  char *p;
-  
-  base = basename((char *)path);
-  if (base == NULL)
-    return NULL;
-    
-  p = strrchr(base, '.');
-  if (p == NULL)
-    return NULL;
-
-  if (strcmp(p + 1, "framework") != 0)
-    return NULL;
-  
-  assert(p - base > 0);
-  
-  name = (char *)malloc(p - base + 1);
-  ASSERT_ALLOC(name);
-  strncpy(name, base, p - base);
-  name[p - base] = '\0';
-
-  return name;
-}
-
-static inline const char *
-_bs_main_bundle_bs_path(void)
-{
-  static bool done = false;
-  static char *path = NULL;
-  /* XXX not thread-safe */
-  if (!done) {
-    CFBundleRef bundle;
-
-    done = true;
-    bundle = CFBundleGetMainBundle();
-    if (bundle != NULL) {
-      CFURLRef url;
-
-      url = CFBundleCopyResourceURL(bundle, CFSTR("BridgeSupport"), 
-                                    NULL, NULL);
-      if (url != NULL) {
-        CFStringRef str = CFURLCopyPath(url);
-        path = (char *)malloc(sizeof(char) * PATH_MAX);
-        CFStringGetFileSystemRepresentation(str, path, PATH_MAX);
-        CFRelease(str);
-        CFRelease(url);
-      }
-    }
-  }
-  return path;
-}
-
-static bool
-_bs_find_path(const char *framework_path, char *path, const size_t path_len,
-              const char *ext)
-{
-  const char *main_bundle_bs_path;
-  char *framework_name;
-  char *home;
-
-  if (framework_path == NULL || *framework_path == '\0' 
-      || path == NULL || path_len == 0)
-    return false;
-
-#define CHECK_IF_EXISTS()           \
-  do {                              \
-    if (access(path, R_OK) == 0) {  \
-      free(framework_name);         \
-      return true;                  \
-    }                               \
-  }                                 \
-  while (0)
-
-  framework_name = get_framework_name(framework_path);
-  if (framework_name == NULL)
-    return false;
-
-  main_bundle_bs_path = _bs_main_bundle_bs_path();
-  if (main_bundle_bs_path != NULL) {
-    snprintf(path, path_len, "%s/%s.%s", main_bundle_bs_path,
-             framework_name, ext);
-    CHECK_IF_EXISTS();
-  }
-
-  snprintf(path, path_len, "%s/Resources/BridgeSupport/%s.%s",
-           framework_path, framework_name, ext);
-  CHECK_IF_EXISTS();
-
-  home = getenv("HOME");
-  if (home != NULL) {
-    snprintf(path, path_len, "%s/Library/BridgeSupport/%s.%s",
-      home, framework_name, ext);
-    CHECK_IF_EXISTS();
-  }
-  
-  snprintf(path, path_len, "/Library/BridgeSupport/%s.%s",
-    framework_name, ext);
-  CHECK_IF_EXISTS();
-
-  snprintf(path, path_len, "/System/Library/BridgeSupport/%s.%s",
-    framework_name, ext);
-  CHECK_IF_EXISTS();
-
-#undef CHECK_IF_EXISTS
-
-  free(framework_name);
-  return false;  
-}
-
-bool 
-bs_find_path(const char *framework_path, char *path, const size_t path_len)
-{
-  return _bs_find_path(framework_path, path, path_len, "bridgesupport");
-}
-
-static inline char *
-get_attribute(xmlTextReaderPtr reader, const char *name)
-{
-  return (char *)xmlTextReaderGetAttribute(reader, (const xmlChar *)name);
-}
-
-static inline char *
-get_type64_attribute(xmlTextReaderPtr reader)
-{
-  return (char *)xmlTextReaderGetAttribute(reader, (xmlChar *)"type64");
-}
-
-static inline char *
-get_type_attribute(xmlTextReaderPtr reader)
-{
-#if __LP64__
-  char *value = get_type64_attribute(reader);
-  if (value != NULL)
-    return value;
-#endif
-  return (char *)xmlTextReaderGetAttribute(reader, (xmlChar *)"type");
-}
-
-static void
-get_c_ary_type_attribute(xmlTextReaderPtr reader, bs_carray_arg_type_t *type, 
-                         int *value)
-{
-  char *c_ary_type;
-
-  if ((c_ary_type = get_attribute(reader, "c_array_length_in_arg")) != NULL) {
-    *type = BS_CARRAY_ARG_LENGTH_IN_ARG;
-    *value = atoi(c_ary_type);
-  }
-  else if ((c_ary_type = get_attribute(reader, "c_array_of_fixed_length")) 
-           != NULL) {
-    *type = BS_CARRAY_ARG_FIXED_LENGTH;
-    *value = atoi(c_ary_type);
-  }
-  else if ((c_ary_type = get_attribute(reader, "c_array_of_variable_length")) 
-           != NULL && strcmp(c_ary_type, "true") == 0) {
-    *type = BS_CARRAY_ARG_VARIABLE_LENGTH;
-    *value = -1;
-  }
-  else if ((c_ary_type = get_attribute(reader, "c_array_delimited_by_null")) 
-           != NULL && strcmp(c_ary_type, "true") == 0) {
-    *type = BS_CARRAY_ARG_DELIMITED_BY_NULL;
-    *value = -1;
-  }
-  else {
-    *type = BS_CARRAY_ARG_UNDEFINED;
-    *value = -1;
-  }
-
-  if (c_ary_type != NULL)
-    free(c_ary_type);
-}
-
-static void
-get_type_modifier_attribute(xmlTextReaderPtr reader, bs_type_modifier_t *type)
-{
-  char *type_modifier = get_attribute(reader, "type_modifier");
-  
-  *type = BS_TYPE_MODIFIER_UNDEFINED;
-  
-  if (type_modifier != NULL && strlen(type_modifier) == 1) {
-    switch (*type_modifier) {
-      case 'n':
-        *type = BS_TYPE_MODIFIER_IN;
-        break;
-      case 'o':
-        *type = BS_TYPE_MODIFIER_OUT;
-        break;
-      case 'N':
-        *type = BS_TYPE_MODIFIER_INOUT;
-        break;
-    }
-  }
-  free(type_modifier);
-} 
-
-static inline bool
-get_boolean_attribute(xmlTextReaderPtr reader, const char *name, 
-                      bool default_value)
-{
-  char *value;
-  bool ret;
-
-  value = get_attribute(reader, name);
-  if (value == NULL)
-    return default_value;
-  ret = strcmp(value, "true") == 0;
-  free(value);
-  return ret;
-}
-
-#define MAX_ENCODE_LEN 4096
-
-#ifndef MIN
-# define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
-static bool 
-undecorate_struct_type(const char *src, char *dest, size_t dest_len, 
-                       bs_element_struct_field_t *fields, 
-                       size_t fields_count, int *out_fields_count)
-{
-  const char *p_src;
-  char *p_dst;
-  char *pos;
-  size_t src_len;
-  unsigned field_idx;
-  unsigned i;
-
-  p_src = src;
-  p_dst = dest;
-  src_len = strlen(src);
-  field_idx = 0;
-  if (out_fields_count != NULL)
-    *out_fields_count = 0;
-
-  for (;;) {
-    bs_element_struct_field_t *field;
-    size_t len;
-
-    field = field_idx < fields_count ? &fields[field_idx] : NULL;
-
-    /* Locate the first field, if any. */
-    pos = strchr(p_src, '"');
-
-    /* Copy what's before the first field, or the rest of the source. */
-    len = MIN(pos == NULL ? src_len - (p_src - src) + 1 : pos - p_src, dest_len - (p_dst - dest));
-    strncpy(p_dst, p_src, len);
-    p_dst += len;
-
-    /* We can break if there wasn't any field. */
-    if (pos == NULL)
-      break;
-
-    /* Jump to the end of the field, saving the field name if necessary. */
-    p_src = pos + 1;
-    pos = strchr(p_src, '"');
-    if (pos == NULL) {
-      fprintf(stderr, "Can't find the end of field delimiter starting at %d\n", (int)(p_src - src));
-      goto bails; 
-    }
-    if (field != NULL) {
-      field->name = (char *)malloc((sizeof(char) * (pos - p_src)) + 1);
-      ASSERT_ALLOC(field->name);
-      strncpy(field->name, p_src, pos - p_src);
-      field->name[pos - p_src] = '\0';
-      field_idx++; 
-    }
-    p_src = pos + 1; 
-    pos = NULL;
-
-    /* Save the field encoding if necessary. */
-    if (field != NULL) {
-      char opposite;
-      bool ok;
-      int nested;
-
-      opposite = 
-	  *p_src == '{' ? '}' :
-	  *p_src == '(' ? ')' :
-	  *p_src == '[' ? ']' : 0;
-
-      for (i = 0, ok = false, nested = 0;
-           i < src_len - (p_src - src) && !ok; 
-           i++) {
-
-        char c = p_src[i];
-
-        if (opposite != 0) {
-          /* Encoding is a structure, we need to match the closing '}',
-           * taking into account that other structures can be nested in it.
-           */
-          if (c == opposite) {
-            if (nested == 0)
-              ok = true;
-            else
-              nested--;  
-          }
-          else if (c == *p_src && i > 0)
-            nested++;
-        }
-        else {
-          /* Easy case, just match another field delimiter, or the end
-           * of the encoding.
-           */
-          if (c == '"' || c == '}') {
-            i--;
-            ok = true;
-          } 
-        }
-      }
-
-      if (ok == false) {
-        fprintf(stderr, "Can't find the field encoding starting at %d\n", (int)(p_src - src));
-        goto bails;
-      }
-
-      if (opposite == '}' || opposite == ')') {
-        char buf[MAX_ENCODE_LEN];
-        char buf2[MAX_ENCODE_LEN];
- 
-        strncpy(buf, p_src, MIN(sizeof buf, i));
-        buf[MIN(sizeof buf, i)] = '\0';        
-     
-        if (!undecorate_struct_type(buf, buf2, sizeof buf2, NULL, 0, NULL)) {
-          fprintf(stderr, "Can't un-decode the field encoding '%s'\n", buf);
-          goto bails;
-        }
-
-        len = strlen(buf2); 
-        field->type = (char *)malloc((sizeof(char) * len) + 1);
-        ASSERT_ALLOC(field->type);
-        strncpy(field->type, buf2, len);
-        field->type[len] = '\0';
-      }
-      else {
-        field->type = (char *)malloc((sizeof(char) * i) + 1);
-        ASSERT_ALLOC(field->type);
-        strncpy(field->type, p_src, i);
-        field->type[i] = '\0';
-        len = i;
-      }
-
-      strncpy(p_dst, field->type, len);
-
-      p_src += i;
-      p_dst += len;
-    }
-  }
-
-  *p_dst = '\0';
-  if (out_fields_count != NULL)
-    *out_fields_count = field_idx;
-  return true;
-
-bails:
-  /* Free what we allocated! */
-  for (i = 0; i < field_idx; i++) {
-    free(fields[i].name);
-    free(fields[i].type);
-  }
-  return false;
-}
-
-struct _bs_parser {
-  CFMutableArrayRef loaded_paths; 
-};
-
-bs_parser_t *
-bs_parser_new(void)
-{
-  struct _bs_parser *parser;
-
-  parser = (struct _bs_parser *)malloc(sizeof(struct _bs_parser));
-  parser->loaded_paths = 
-    CFArrayCreateMutable(kCFAllocatorMalloc, 0, &kCFTypeArrayCallBacks);
-
-  return parser;
-}
-
-void
-bs_parser_free(bs_parser_t *parser)
-{
-  CFRelease(parser->loaded_paths);
-  free(parser);
-}
-
-bool 
-bs_parser_parse(bs_parser_t *parser, const char *path, 
-                const char *framework_path, bs_parse_options_t options, 
-                bs_parse_callback_t callback, void *context, char **error)
-{
-  xmlTextReaderPtr reader;
-  bs_element_function_t *func;
-  bs_element_class_t *klass;
-  bs_element_method_t *method;
-  unsigned int i;
-#define MAX_ARGS 128
-  bs_element_arg_t args[MAX_ARGS];
-  bs_element_arg_t fptr_args[MAX_ARGS];
-  char *protocol_name = NULL;
-  int func_ptr_arg_depth;
-  bs_element_function_pointer_t *func_ptr;
-  bool success;
-  CFStringRef cf_path;
-  bool nested_func_ptr;
-
-  if (callback == NULL)
-    return false;
-
-  /* check if the given framework path has not been loaded already */
-  cf_path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorMalloc, 
-    path);
-  CFMakeCollectable(cf_path);
-  for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths);
-       i < count; i++) {
-    CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i);
-    if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive)
-        == kCFCompareEqualTo) {
-      /* already loaded */
-      return true;
-    }
-  }
-
-  CFArrayAppendValue(parser->loaded_paths, cf_path);
-
-  //printf("parsing %s\n", path);
-
-#define BAIL(fmt, args...)                      \
-  do {                                          \
-    if (error != NULL) {                        \
-      char buf[1024];                           \
-      snprintf(buf, sizeof buf,                 \
-               "%s:%ld - "fmt, path,            \
-               xmlGetLineNo(xmlTextReaderCurrentNode(reader)), \
-               ##args);                         \
-      *error = strdup(buf);                     \
-    }                                           \
-    success = false;                            \
-    goto bails;                                 \
-  }                                             \
-  while (0)
-
-#if __LP64__
-# define CHECK_TYPE_ATTRIBUTE(var) CHECK_ATTRIBUTE(var, "type")
-#else
-# define CHECK_TYPE_ATTRIBUTE(var) \
-    if (var == NULL && get_type64_attribute(reader) != NULL) { \
-	break; \
-    } \
-    CHECK_ATTRIBUTE(var, "type")
-#endif
-
-#define CHECK_ATTRIBUTE_CAN_BE_EMPTY(a, name) \
-  CHECK_ATTRIBUTE0(a, name, true)
-
-#define CHECK_ATTRIBUTE(a, name) \
-  CHECK_ATTRIBUTE0(a, name, false)
-
-#define CHECK_ATTRIBUTE0(a, name, can_be_empty)         \
-  do {                                                  \
-    if (a == NULL)                                      \
-      BAIL("expected attribute `%s' for element `%s'",  \
-           name, xmlTextReaderConstName(reader));       \
-    if (!can_be_empty && *a == '\0') {                  \
-      free(a);                                          \
-      BAIL("empty attribute `%s' for element `%s'",     \
-           name, xmlTextReaderConstName(reader));       \
-    }                                                   \
-  } while (0)                                           \
-
-  reader = xmlNewTextReaderFilename(path);
-  if (reader == NULL)
-    BAIL("cannot create XML text reader for file at path `%s'", path);
-
-  func = NULL;
-  func_ptr = NULL;
-  func_ptr_arg_depth = -1;
-  nested_func_ptr = false;
-  klass = NULL;
-  method = NULL;
-  protocol_name = NULL;
-
-  while (true) {
-    const char *name;
-    unsigned int namelen;
-    int node_type = -1;
-    bool eof = false;
-    struct bs_xml_atom *atom;
-    void *bs_element;
-    bs_element_type_t bs_element_type = 0;
-
-    do {
-      int retval = xmlTextReaderRead(reader);
-      if (retval == 0) {
-        eof = true;
-        break;
-      }
-      else if (retval < 0)
-        BAIL("parsing error: %d", retval);
-
-      node_type = xmlTextReaderNodeType(reader);
-    }
-    while (node_type != XML_READER_TYPE_ELEMENT 
-           && node_type != XML_READER_TYPE_END_ELEMENT);    
-    
-    if (eof)
-      break;
-
-    name = (const char *)xmlTextReaderConstName(reader);
-    namelen = strlen(name); 
-
-    bs_element = NULL;
-
-    atom = bs_xml_element(name, namelen);
-    if (atom == NULL)
-      continue;
-
-    if (nested_func_ptr) {
-      // FIXME: elements nesting function_pointers aren't supported yet by the
-      // parser, so we just ignore them.
-      if (node_type == XML_READER_TYPE_END_ELEMENT
-          && (atom->val == BS_XML_FUNCTION || atom->val == BS_XML_METHOD)) {
-        nested_func_ptr = false;
-      }
-      continue;
-    }
-
-    if (node_type == XML_READER_TYPE_ELEMENT) {
-      switch (atom->val) {
-        case BS_XML_DEPENDS_ON:
-        {
-          char *depends_on_path;
-          char bs_path[PATH_MAX];
-          bool bs_path_found;
-          
-          depends_on_path = get_attribute(reader, "path");
-          CHECK_ATTRIBUTE(depends_on_path, "path");
-
-//printf("depends of %s\n", depends_on_path);
-          
-          bs_path_found = bs_find_path(depends_on_path, bs_path, 
-                                       sizeof bs_path);
-          if (bs_path_found) {
-            if (!bs_parser_parse(parser, bs_path, depends_on_path, options, 
-                                 callback, context, error)) {
-              free(depends_on_path);
-              return false;
-	    }
-          }
-          free(depends_on_path);
-          break;
-        }
-
-        case BS_XML_CONSTANT: 
-        { 
-          bs_element_constant_t *bs_const;
-          char *const_name;
-          char *const_type;
-
-          const_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(const_name, "name");
-          const_type = get_type_attribute(reader);
-          CHECK_TYPE_ATTRIBUTE(const_type);
-
-          bs_const = (bs_element_constant_t *)
-            malloc(sizeof(bs_element_constant_t));
-          ASSERT_ALLOC(bs_const);
-
-          bs_const->name = const_name;
-          bs_const->type = const_type;
-          bs_const->ignore = false;
-          bs_const->suggestion = NULL;
-          bs_const->magic_cookie = get_boolean_attribute(reader,
-            "magic_cookie", false);
-
-          bs_element = bs_const;
-          bs_element_type = BS_ELEMENT_CONSTANT;
-          break;
-        }
-
-        case BS_XML_STRING_CONSTANT:
-        {
-          bs_element_string_constant_t *bs_strconst;
-          char *strconst_name;
-          char *strconst_value;
-
-          strconst_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(strconst_name, "name");
-          strconst_value = get_attribute(reader, "value");
-          CHECK_ATTRIBUTE_CAN_BE_EMPTY(strconst_value, "value");
-
-          bs_strconst = (bs_element_string_constant_t *)
-            malloc(sizeof(bs_element_string_constant_t));
-          ASSERT_ALLOC(bs_strconst);
-
-          bs_strconst->name = strconst_name;
-          bs_strconst->value = strconst_value;
-          bs_strconst->nsstring = get_boolean_attribute(reader, "nsstring", 
-            false);
-
-          bs_element = bs_strconst;
-          bs_element_type = BS_ELEMENT_STRING_CONSTANT;
-          break;
-        }
-
-        case BS_XML_ENUM: 
-        { 
-          char *enum_name;
-          char *enum_value;        
-
-          enum_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(enum_name, "name");
-
-#if __LP64__
-	  enum_value = get_attribute(reader, "value64");
-	  if (enum_value == NULL)
-#endif
-	    enum_value = get_attribute(reader, "value");
-
-#if BYTE_ORDER == BIG_ENDIAN
-# define BYTE_ORDER_VALUE_ATTR_NAME "be_value"
-#else
-# define BYTE_ORDER_VALUE_ATTR_NAME "le_value"
-#endif
-
-          if (enum_value == NULL)
-            enum_value = get_attribute(reader, BYTE_ORDER_VALUE_ATTR_NAME); 
-          
-          if (enum_value != NULL) {
-            bs_element_enum_t *bs_enum;
-   
-            bs_enum = (bs_element_enum_t *)malloc(sizeof(bs_element_enum_t));
-            ASSERT_ALLOC(bs_enum);
-
-            bs_enum->name = enum_name;
-            bs_enum->value = enum_value;
-            bs_enum->ignore = get_boolean_attribute(reader, "ignore", false);
-            bs_enum->suggestion = get_attribute(reader, "suggestion");
-            
-            bs_element = bs_enum;
-            bs_element_type = BS_ELEMENT_ENUM;
-          }
-          break;
-        }
-
-        case BS_XML_STRUCT: 
-        {
-          bs_element_struct_t *bs_struct;
-          char *struct_decorated_type;
-          char *struct_name;
-          char type[MAX_ENCODE_LEN];
-          bs_element_struct_field_t fields[128];
-          int field_count;
-
-          struct_decorated_type = get_type_attribute(reader);
-          CHECK_TYPE_ATTRIBUTE(struct_decorated_type);
-          struct_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(struct_name, "name");
-
-          if (!undecorate_struct_type(struct_decorated_type, type, 
-                                      sizeof type, fields, 128, 
-                                      &field_count)) {
-            BAIL("Can't handle structure '%s' with type '%s'", 
-                 struct_name, struct_decorated_type);
-          }
-
-          free(struct_decorated_type);
-
-          bs_struct = 
-            (bs_element_struct_t *)malloc(sizeof(bs_element_struct_t));
-          ASSERT_ALLOC(bs_struct);
-
-          bs_struct->name = struct_name;
-          bs_struct->type = strdup(type);
-          
-          bs_struct->fields = (bs_element_struct_field_t *)malloc(
-            sizeof(bs_element_struct_field_t) * field_count);
-          ASSERT_ALLOC(bs_struct->fields);
-          memcpy(bs_struct->fields, fields, 
-                 sizeof(bs_element_struct_field_t) * field_count); 
-          
-          bs_struct->fields_count = field_count;
-          bs_struct->opaque = get_boolean_attribute(reader, "opaque", false);
-
-          bs_element = bs_struct;
-          bs_element_type = BS_ELEMENT_STRUCT;
-          break;
-        }
-
-        case BS_XML_OPAQUE:
-        {
-          bs_element_opaque_t *bs_opaque;
-          char *opaque_name;
-          char *opaque_type;
-
-          opaque_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(opaque_name, "name");
-          opaque_type = get_type_attribute(reader);
-          CHECK_TYPE_ATTRIBUTE(opaque_type);
-
-          bs_opaque = 
-            (bs_element_opaque_t *)malloc(sizeof(bs_element_opaque_t));
-          ASSERT_ALLOC(bs_opaque);
-          
-          bs_opaque->name = opaque_name;
-          bs_opaque->type = opaque_type;
-          
-          bs_element = bs_opaque;
-          bs_element_type = BS_ELEMENT_OPAQUE;
-          break;
-        }
-        
-        case BS_XML_CFTYPE:
-        {
-          bs_element_cftype_t *bs_cftype;
-          char *cftype_name;
-          char *cftype_type;
-
-          cftype_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(cftype_name, "name");
-          cftype_type = get_type_attribute(reader);
-          CHECK_TYPE_ATTRIBUTE(cftype_type);
-
-          bs_cftype = 
-            (bs_element_cftype_t *)malloc(sizeof(bs_element_cftype_t));
-          ASSERT_ALLOC(bs_cftype);
-
-          bs_cftype->name = cftype_name;
-          bs_cftype->type = cftype_type;
-
-#if 1
-          /* the type_id field isn't used in MacRuby */
-          bs_cftype->type_id = 0;
-#else
-          char *cftype_gettypeid_func_name;
-          cftype_gettypeid_func_name = get_attribute(reader, "gettypeid_func");
-          if (cftype_gettypeid_func_name != NULL) {
-            void *sym;
-
-            sym = dlsym(RTLD_DEFAULT, cftype_gettypeid_func_name);
-            if (sym == NULL) {
-              BAIL("cannot locate gettypeid_func function `%s'",
-                   cftype_gettypeid_func_name);
-            }
-            else {
-              CFTypeID (*cb)(void) = sym;
-              bs_cftype->type_id = (*cb)();
-            }
-          }
-          else {
-            bs_cftype->type_id = 0;
-          }
-#endif
-
-          bs_cftype->tollfree = get_attribute(reader, "tollfree");
-
-          bs_element = bs_cftype;
-          bs_element_type = BS_ELEMENT_CFTYPE;
-          break;
-        }
-        
-        case BS_XML_INFORMAL_PROTOCOL: 
-        {
-	  if (protocol_name != NULL)
-	    free(protocol_name);
-          protocol_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(protocol_name, "name");
-          break;
-        }
-
-        case BS_XML_FUNCTION: 
-        {
-          char *func_name;
-          
-          func_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(func_name, "name");
-
-          func = 
-            (bs_element_function_t *)malloc(sizeof(bs_element_function_t));
-          ASSERT_ALLOC(func);
-
-          func->name = func_name;
-          func->variadic = get_boolean_attribute(reader, "variadic", false);
-          func->args_count = 0;
-          func->args = NULL;
-          func->retval = NULL;
-
-          if (xmlTextReaderIsEmptyElement(reader)) {
-            bs_element = func;
-            bs_element_type = BS_ELEMENT_FUNCTION;
-            func = NULL;
-          }
-          break;
-        }
-
-        case BS_XML_FUNCTION_ALIAS: 
-        {
-          bs_element_function_alias_t *bs_func_alias;
-          char *alias_name;
-          char *alias_original;
-
-          alias_name = get_attribute(reader, "name"); 
-          CHECK_ATTRIBUTE(alias_name, "name");
-          alias_original = get_attribute(reader, "original");
-          CHECK_ATTRIBUTE(alias_original, "original");
-
-          bs_func_alias = (bs_element_function_alias_t *)malloc(
-            sizeof(bs_element_function_alias_t));
-          ASSERT_ALLOC(bs_func_alias);
-          
-          bs_func_alias->name = alias_name;
-          bs_func_alias->original = alias_original;
-
-          bs_element = bs_func_alias;
-          bs_element_type = BS_ELEMENT_FUNCTION_ALIAS;
-          break;
-        }
-
-        case BS_XML_CLASS: 
-        {
-          char *class_name;
-          
-          class_name = get_attribute(reader, "name");
-          CHECK_ATTRIBUTE(class_name, "name");
-        
-          klass = (bs_element_class_t *)malloc(sizeof(bs_element_class_t));
-          ASSERT_ALLOC(klass);
-            
-          klass->name = class_name;
-          klass->class_methods = klass->instance_methods = NULL;
-          klass->class_methods_count = klass->instance_methods_count = 0;
-          break;
-        }
-
-        case BS_XML_ARG:
-        {
-          if (func != NULL || method != NULL || func_ptr != NULL) {
-            bs_element_arg_t *bs_arg; 
-            unsigned *argc;
-
-            argc = func_ptr != NULL
-              ? &func_ptr->args_count
-              : func != NULL 
-                ? &func->args_count 
-                : &method->args_count;
-
-            if (*argc >= MAX_ARGS) {
-              if (func_ptr != NULL)
-                BAIL("maximum number of arguments (%d) reached " \
-                     "for function pointer", MAX_ARGS);
-              else if (func != NULL)
-                BAIL("maximum number of arguments (%d) reached " \
-                     "for function '%s'", MAX_ARGS, func->name);
-              else
-                BAIL("maximum number of arguments (%d) reached " \
-                     "for method '%s'", MAX_ARGS, (char *)method->name);
-            } 
-
-	    bs_element_arg_t *args_from =
-		(func_ptr == NULL ? args : fptr_args);
-	    bs_arg = &args_from[(*argc)++];
-
-            if (method != NULL && func_ptr == NULL) {
-              char *index = get_attribute(reader, "index");
-              CHECK_ATTRIBUTE(index, "index");
-              bs_arg->index = strtol(index, NULL, 10);
-              free(index);
-            }
-            else {
-              bs_arg->index = -1;
-            }
-            
-            get_type_modifier_attribute(reader, &bs_arg->type_modifier);
-
-#if __LP64__
-            bs_arg->sel_of_type = get_attribute(reader, "sel_of_type64");
-            if (bs_arg->sel_of_type == NULL)
-#endif
-              bs_arg->sel_of_type = get_attribute(reader, "sel_of_type");
-
-            bs_arg->printf_format = get_boolean_attribute(reader, 
-                "printf_format", false); 
-            bs_arg->null_accepted = get_boolean_attribute(reader, 
-                "null_accepted", true);
-            get_c_ary_type_attribute(reader, 
-                &bs_arg->carray_type, &bs_arg->carray_type_value); 
-  
-            bs_arg->type = get_type_attribute(reader);
-
-            if (get_boolean_attribute(reader, "function_pointer", false)) {
-              if (func_ptr != NULL) {
-                func_ptr = NULL; 
-		nested_func_ptr = true;
-		break;
-	      }
-              bs_arg->function_pointer = (bs_element_function_pointer_t *)
-                calloc(1, sizeof(bs_element_function_pointer_t));
-              ASSERT_ALLOC(bs_arg->function_pointer);
-              func_ptr = bs_arg->function_pointer;
-              func_ptr_arg_depth = xmlTextReaderDepth(reader);
-            }
-	    else {
-              bs_arg->function_pointer = NULL;
-	    }
-          }
-          else {
-            BAIL("argument defined outside of a " \
-                 "function/method/function_pointer");
-          }
-          break;
-        }
-
-        case BS_XML_RETVAL: 
-        {
-          if (func != NULL || method != NULL || func_ptr != NULL) {
-            bs_element_retval_t *bs_retval;  
-
-            if (func_ptr != NULL) {
-              if (func_ptr->retval != NULL)
-                BAIL("function pointer return value defined more than once");
-            }
-            else if (func != NULL) {
-              if (func->retval != NULL)
-                BAIL("function '%s' return value defined more than once", 
-                     func->name);
-            }
-            else if (method != NULL) {
-              if (method->retval != NULL)
-                BAIL("method '%s' return value defined more than once", 
-                     (char *)method->name);
-            }
-    
-            bs_retval = 
-              (bs_element_retval_t *)malloc(sizeof(bs_element_retval_t));
-            ASSERT_ALLOC(bs_retval);
-
-            get_c_ary_type_attribute(reader, &bs_retval->carray_type, 
-              &bs_retval->carray_type_value);
-
-            bs_retval->type = get_type_attribute(reader);
-            if (bs_retval->type != NULL)
-              bs_retval->already_retained = 
-                get_boolean_attribute(reader, "already_retained", false);
-
-            if (func_ptr != NULL) {
-              if (bs_retval->type != NULL) {
-                func_ptr->retval = bs_retval;
-              }
-              else {
-                free(bs_retval);
-                BAIL("function pointer return value defined without type"); 
-              }
-            }
-            else if (func != NULL) {
-              if (bs_retval->type != NULL) {
-                func->retval = bs_retval;
-              }
-              else {
-                free(bs_retval);
-#if !defined(__LP64__)
-		if (get_type64_attribute(reader) != NULL) {
-		    // The function has no 32-bit return value type and we
-		    // run in 32-bit mode. We just ignore it.
-		    func = NULL;
-		    break;
-		}
-#endif
-                BAIL("function '%s' return value defined without type", 
-                     func->name);
-              }
-            }
-            else {
-              method->retval = bs_retval;
-            }
-
-            if (get_boolean_attribute(reader, "function_pointer", false)) {
-              if (func_ptr != NULL) {
-                func_ptr = NULL; 
-		nested_func_ptr = true;
-		break;
-              }
-              bs_retval->function_pointer = (bs_element_function_pointer_t *)
-                calloc(1, sizeof(bs_element_function_pointer_t));
-              ASSERT_ALLOC(bs_retval->function_pointer);
-              func_ptr = bs_retval->function_pointer;
-              func_ptr_arg_depth = xmlTextReaderDepth(reader);
-            }
-	    else {
-              bs_retval->function_pointer = NULL;
-	    }
-          }
-          else {
-            BAIL("return value defined outside a function/method");
-          }
-          break;
-        }
-
-        case BS_XML_METHOD: 
-        {
-          if (protocol_name != NULL) {
-            bs_element_informal_protocol_method_t *bs_informal_method;
-            char *selector;
-            char *method_type;
-
-            selector = get_attribute(reader, "selector");
-            CHECK_ATTRIBUTE(selector, "selector");
-            
-            method_type = get_type_attribute(reader);
-            CHECK_TYPE_ATTRIBUTE(method_type);
-
-            bs_informal_method = (bs_element_informal_protocol_method_t *)
-              malloc(sizeof(bs_element_informal_protocol_method_t));
-            ASSERT_ALLOC(bs_informal_method);
-
-            bs_informal_method->name = sel_registerName(selector);
-	    free(selector);
-            bs_informal_method->class_method = 
-              get_boolean_attribute(reader, "class_method", false);
-            bs_informal_method->type = method_type;
-            bs_informal_method->protocol_name = strdup(protocol_name);
-
-            bs_element = bs_informal_method;
-            bs_element_type = BS_ELEMENT_INFORMAL_PROTOCOL_METHOD;
-          }
-          else if (klass != NULL) {  
-            char *selector;
-
-            selector = get_attribute(reader, "selector");
-            CHECK_ATTRIBUTE(selector, "selector");
-
-            method = 
-              (bs_element_method_t *)malloc(sizeof(bs_element_method_t));
-            ASSERT_ALLOC(method);
-
-            method->name = sel_registerName(selector);
-	    free(selector);
-            method->class_method = 
-              get_boolean_attribute(reader, "class_method", false);
-            method->variadic = 
-              get_boolean_attribute(reader, "variadic", false);
-            method->ignore = 
-              get_boolean_attribute(reader, "ignore", false);
-            method->suggestion = get_attribute(reader, "suggestion");
-            method->args_count = 0;
-            method->args = NULL;
-            method->retval = NULL;
-
-            if (xmlTextReaderIsEmptyElement(reader)) {
-              goto index_method;
-            }
-          }
-          else {
-            BAIL("method defined outside a class or informal protocol");
-          }
-          break;
-        }
-      }
-    }
-    else if (node_type == XML_READER_TYPE_END_ELEMENT) {
-      switch (atom->val) {
-        case BS_XML_INFORMAL_PROTOCOL: 
-        {
-          protocol_name = NULL;
-          break;
-        }
-
-        case BS_XML_RETVAL:
-        case BS_XML_ARG: 
-        {
-          if (func_ptr != NULL 
-              && func_ptr_arg_depth == xmlTextReaderDepth(reader)) {
-
-	      bs_element_retval_t *retval = NULL;
-	      bs_element_arg_t *arg = NULL;
-	      unsigned args_count;
-
-	      if (atom->val == BS_XML_RETVAL) {
-		  retval = func != NULL ? func->retval : method->retval;
-	      }
-	      else {
-		  args_count = func != NULL ? func->args_count
-		      : method->args_count;
-		  arg = &args[args_count - 1];
-	      }
-
-              // Determine if we deal with a block or a function pointer.
-	      const char *old_type = (retval ? retval->type : arg->type);
-              const char lambda_type = *old_type == '@'
-		? _MR_C_LAMBDA_BLOCK
-		: _MR_C_LAMBDA_FUNCPTR;
-
-	      char tmp_type[1025]; // 3 less to fit <, type and >
-	      char new_type[1028];
-
-	      // Function ptr return type
-	      strlcpy(tmp_type, func_ptr->retval->type, sizeof(tmp_type));
-	      // Function ptr args
-	      for (i = 0; i < func_ptr->args_count; i++) {
-		  strlcat(tmp_type, fptr_args[i].type, sizeof(tmp_type));
-	      }
-	      // Clear the final type string
-	      memset(new_type, 0, sizeof(new_type));
-	      // Append the function pointer type
-	      snprintf(new_type, sizeof(new_type), "%c%c%s%c",
-		      _MR_C_LAMBDA_B, lambda_type, tmp_type, _MR_C_LAMBDA_E);
-
-	      // Free the old values
-	      if (retval) {
-		  free(retval->type);
-		  retval->type = strdup(new_type);
-	      }
-	      else {
-		  free(arg->type);
-		  arg->type = strdup(new_type);
-	      }
-            
-	      if (func_ptr->args_count > 0) {
-		  size_t len;
-      
-		  len = sizeof(bs_element_arg_t) * func_ptr->args_count;
-		  func_ptr->args = (bs_element_arg_t *)malloc(len);
-		  ASSERT_ALLOC(func_ptr->args);
-		  memcpy(func_ptr->args, fptr_args, len);
-	      }
-	      else {
-		  func_ptr->args = NULL;
-	      }
-                        
-	      func_ptr = NULL;
-	      func_ptr_arg_depth = -1;
-          }
-          break;
-        }
- 
-        case BS_XML_FUNCTION: 
-        {
-          if (func == NULL) {
-            break;
-          }
-          for (i = 0; i < func->args_count; i++) {
-            if (args[i].type == NULL)
-              BAIL("function '%s' argument #%d type not provided", 
-                   func->name, i);
-          }
-    
-          if (func->args_count > 0) {
-            size_t len;
-    
-            len = sizeof(bs_element_arg_t) * func->args_count;
-            func->args = (bs_element_arg_t *)malloc(len);
-            ASSERT_ALLOC(func->args);
-            memcpy(func->args, args, len);
-          }
-
-          bs_element = func;
-          bs_element_type = BS_ELEMENT_FUNCTION;
-          func = NULL;
-          break;
-        }
-
-        case BS_XML_METHOD: 
-        {
-          bs_element_method_t *methods;
-          unsigned *methods_count;
-          
-          if (method->args_count > 0) {
-            size_t len;
-      
-            len = sizeof(bs_element_arg_t) * method->args_count;
-            method->args = (bs_element_arg_t *)malloc(len);
-            ASSERT_ALLOC(method->args);
-            memcpy(method->args, args, len);
-          }
-
-index_method:
-          methods = method->class_method 
-            ? klass->class_methods : klass->instance_methods;
-
-          methods_count = method->class_method
-            ? &klass->class_methods_count : &klass->instance_methods_count;
-
-          if (methods == NULL) {
-            methods = (bs_element_method_t *)malloc(
-              sizeof(bs_element_method_t) * (*methods_count + 1));
-          }
-          else {
-            methods = (bs_element_method_t *)realloc(methods, 
-              sizeof(bs_element_method_t) * (*methods_count + 1));
-          }
-          ASSERT_ALLOC(methods);
-
-    //      methods[*methods_count] = method;
-    // FIXME this is inefficient
-          memcpy(&methods[*methods_count], method, 
-            sizeof(bs_element_method_t));
-
-          (*methods_count)++;
-          
-          if (method->class_method)
-            klass->class_methods = methods;
-          else
-            klass->instance_methods = methods;
-         
-          free(method);
-          method = NULL;
-          break;
-        }
-
-        case BS_XML_CLASS: 
-        {
-          bs_element = klass;
-          bs_element_type = BS_ELEMENT_CLASS;
-          klass = NULL;
-          break;
-        }
-      }
-    }
-
-    if (bs_element != NULL)
-      (*callback)(parser, path, bs_element_type, bs_element, context);
-  }
-  
-  success = true;
-
-bails:
-  if (protocol_name != NULL)
-    free(protocol_name);
-
-  xmlFreeTextReader(reader);
-
-  if (!success) {
-      for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths);
-	      i < count; i++) {
-	  CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i);
-	  if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive)
-		  == kCFCompareEqualTo) {
-	      CFArrayRemoveValueAtIndex(parser->loaded_paths, i);
-	      break;
-	  }
-      }
-  }
-
-  if (success && options == BS_PARSE_OPTIONS_LOAD_DYLIBS && framework_path != NULL) {
-    char buf[PATH_MAX];
-
-    if (_bs_find_path(framework_path, buf, sizeof buf, "dylib")) {
-      if (dlopen(buf, RTLD_LAZY) == NULL) {
-        if (error != NULL) {
-          *error = dlerror();
-        }
-        success = false;
-      }
-    }
-  }
-
-  return success;
-}
-
-#define SAFE_FREE(x) do { if ((x) != NULL) free(x); } while (0)
-
-static void bs_free_retval(bs_element_retval_t *bs_retval);
-static void bs_free_arg(bs_element_arg_t *bs_arg);
-
-static void
-bs_free_function_pointer(bs_element_function_pointer_t *bs_func_ptr)
-{
-  if (bs_func_ptr != NULL) {
-    unsigned i;
-    for (i = 0; i < bs_func_ptr->args_count; i++)
-      bs_free_arg(&bs_func_ptr->args[i]);
-    SAFE_FREE(bs_func_ptr->args);
-    bs_free_retval(bs_func_ptr->retval);
-    SAFE_FREE(bs_func_ptr);
-  }
-}
-
-static void
-bs_free_retval(bs_element_retval_t *bs_retval)
-{
-  if (bs_retval == NULL)
-    return;
-  SAFE_FREE(bs_retval->type);
-  bs_free_function_pointer(bs_retval->function_pointer);
-}
-
-static void
-bs_free_arg(bs_element_arg_t *bs_arg)
-{
-  SAFE_FREE(bs_arg->type);
-  SAFE_FREE(bs_arg->sel_of_type);
-  bs_free_function_pointer(bs_arg->function_pointer);
-}
-
-static void 
-bs_free_method(bs_element_method_t *bs_method)
-{
-  unsigned i;
-  for (i = 0; i < bs_method->args_count; i++)
-    bs_free_arg(&bs_method->args[i]);
-  SAFE_FREE(bs_method->args);
-  bs_free_retval(bs_method->retval);
-  SAFE_FREE(bs_method->suggestion); 
-}
-
-void 
-bs_element_free(bs_element_type_t type, void *value)
-{
-  assert(value != NULL);
-
-  switch (type) {
-    case BS_ELEMENT_STRUCT:
-    {
-      bs_element_struct_t *bs_struct = (bs_element_struct_t *)value;
-      unsigned i;
-      SAFE_FREE(bs_struct->name);
-      SAFE_FREE(bs_struct->type);
-      for (i = 0; i < bs_struct->fields_count; i++) {
-        SAFE_FREE(bs_struct->fields[i].name);
-        SAFE_FREE(bs_struct->fields[i].type);
-      }
-      SAFE_FREE(bs_struct->fields);
-      break;
-    }
-
-    case BS_ELEMENT_CFTYPE:
-    {
-      bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
-      SAFE_FREE(bs_cftype->name);
-      SAFE_FREE(bs_cftype->type);
-      SAFE_FREE(bs_cftype->tollfree);
-      break;
-    }
-
-    case BS_ELEMENT_OPAQUE:
-    {
-      bs_element_opaque_t *bs_opaque = (bs_element_opaque_t *)value;
-      SAFE_FREE(bs_opaque->name);
-      SAFE_FREE(bs_opaque->type);
-      break;    
-    }
-
-    case BS_ELEMENT_CONSTANT:
-    {
-      bs_element_constant_t *bs_const = (bs_element_constant_t *)value;
-      SAFE_FREE(bs_const->name);
-      SAFE_FREE(bs_const->type);
-      SAFE_FREE(bs_const->suggestion);
-      break;
-    }
-
-    case BS_ELEMENT_STRING_CONSTANT:
-    {
-      bs_element_string_constant_t *bs_str_const = 
-        (bs_element_string_constant_t *)value;
-      SAFE_FREE(bs_str_const->name);
-      SAFE_FREE(bs_str_const->value);
-      break;
-    }
-
-    case BS_ELEMENT_ENUM:
-    {
-      bs_element_enum_t *bs_enum = (bs_element_enum_t *)value;
-      SAFE_FREE(bs_enum->name);
-      SAFE_FREE(bs_enum->value);
-      SAFE_FREE(bs_enum->suggestion);
-      break;
-    }
-
-    case BS_ELEMENT_FUNCTION:
-    {
-      unsigned i;
-      bs_element_function_t *bs_func = (bs_element_function_t *)value;
-      free(bs_func->name);
-      for (i = 0; i < bs_func->args_count; i++)
-        bs_free_arg(&bs_func->args[i]);
-      SAFE_FREE(bs_func->args);
-      bs_free_retval(bs_func->retval);
-      break;
-    }
-
-    case BS_ELEMENT_FUNCTION_ALIAS:
-    {
-      bs_element_function_alias_t *bs_func_alias = 
-        (bs_element_function_alias_t *)value;
-      SAFE_FREE(bs_func_alias->name);
-      SAFE_FREE(bs_func_alias->original);
-      break;
-    }
-
-    case BS_ELEMENT_CLASS:
-    {
-      bs_element_class_t *bs_class = (bs_element_class_t *)value;
-      unsigned i;
-      free(bs_class->name);
-      for (i = 0; i < bs_class->class_methods_count; i++)
-        bs_free_method(&bs_class->class_methods[i]);
-      SAFE_FREE(bs_class->class_methods);
-      for (i = 0; i < bs_class->instance_methods_count; i++)
-        bs_free_method(&bs_class->instance_methods[i]);
-      SAFE_FREE(bs_class->instance_methods);
-      break;
-    }
-
-    case BS_ELEMENT_INFORMAL_PROTOCOL_METHOD:
-    {
-      bs_element_informal_protocol_method_t *bs_iprotm = 
-        (bs_element_informal_protocol_method_t *)value;
-      SAFE_FREE(bs_iprotm->protocol_name);
-      SAFE_FREE(bs_iprotm->type);
-      break;
-    }
-
-    default:
-      fprintf(stderr, "unknown value %p of type %d passed to bs_free()", 
-	      value, type);
-  }
-  free(value);
-}
-
-#endif // !MACRUBY_STATIC

Deleted: MacRuby/trunk/bs.h
===================================================================
--- MacRuby/trunk/bs.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bs.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,280 +0,0 @@
-/*  
- *  Copyright (c) 2008-2011, Apple Inc. All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *  1.  Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *  2.  Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *  3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *      its contributors may be used to endorse or promote products derived
- *      from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
- *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- *  ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
- *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- *  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __BS_H_
-#define __BS_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <objc/runtime.h>
-
-/* Extend objc/runtime.h and add function pointers and blocks tokens.
- * A pointer to `void foo (int, char)' will be encoded as <^vic>.
- * A `void (^)(int, char)' block will be encoded as <@vic>.
- */
-
-#define _MR_C_LAMBDA_B		'<'
-#define _MR_C_LAMBDA_FUNCPTR  	'^'
-#define _MR_C_LAMBDA_BLOCK	'@'
-#define _MR_C_LAMBDA_E		'>'
-
-/* Attribute and element representations.
- * See BridgeSupport(5) for more information.
- */
-
-typedef enum {
-  BS_CARRAY_ARG_UNDEFINED = 0,
-  BS_CARRAY_ARG_LENGTH_IN_ARG,
-  BS_CARRAY_ARG_FIXED_LENGTH,
-  BS_CARRAY_ARG_VARIABLE_LENGTH,
-  BS_CARRAY_ARG_DELIMITED_BY_NULL
-} bs_carray_arg_type_t;
-
-typedef enum {
-  BS_TYPE_MODIFIER_UNDEFINED = 0,
-  BS_TYPE_MODIFIER_IN,
-  BS_TYPE_MODIFIER_OUT,
-  BS_TYPE_MODIFIER_INOUT
-} bs_type_modifier_t;
-
-typedef struct {
-  char *name;
-  char *type;
-} bs_element_struct_field_t;
-
-typedef struct {
-  char *name;
-  char *type;
-  bs_element_struct_field_t *fields;
-  unsigned fields_count;
-  bool opaque;
-} bs_element_struct_t;
-
-typedef struct {
-  char *name;
-  char *type;
-  char *tollfree;
-  CFTypeID type_id; /* 0 if unknown */
-} bs_element_cftype_t;
-
-typedef struct {
-  char *name;
-  char *type;
-} bs_element_opaque_t;
-
-typedef struct {
-  char *name;
-  char *type;
-  bool magic_cookie;
-  bool ignore;
-  char *suggestion;
-} bs_element_constant_t;
-
-typedef struct {
-  char *name;
-  char *value;
-  bool nsstring;
-} bs_element_string_constant_t;
-
-typedef struct {
-  char *name;
-  char *value;
-  bool ignore;
-  char *suggestion;  
-} bs_element_enum_t;
-
-struct __bs_element_arg;
-struct __bs_element_retval;
-typedef struct __bs_element_arg bs_element_arg_t;
-typedef struct __bs_element_retval bs_element_retval_t;
-
-typedef struct {
-  bs_element_arg_t *args;
-  unsigned args_count;
-  bs_element_retval_t *retval;
-} bs_element_function_pointer_t;
-
-struct __bs_element_arg {
-  int index; /* if -1, not used */
-  char *type;
-  bs_type_modifier_t type_modifier;
-  bs_carray_arg_type_t carray_type;
-  bs_element_function_pointer_t *function_pointer; /* can be NULL */
-  int carray_type_value;
-  bool null_accepted;
-  bool printf_format;
-  char *sel_of_type;
-};
-
-struct __bs_element_retval {
-  char *type;
-  bs_carray_arg_type_t carray_type;
-  bs_element_function_pointer_t *function_pointer; /* can be NULL */
-  int carray_type_value;
-  bool already_retained;
-};
-
-typedef struct {
-  char *name;
-  bs_element_arg_t *args;
-  unsigned args_count;
-  bs_element_retval_t *retval;
-  bool variadic;
-} bs_element_function_t;
-
-typedef struct {
-  char *name;
-  char *original;
-} bs_element_function_alias_t;
-
-typedef struct {
-  SEL name;
-  bs_element_arg_t *args;
-  unsigned args_count;
-  bs_element_retval_t *retval;
-  bool class_method;
-  bool variadic;
-  bool ignore;
-  char *suggestion;
-} bs_element_method_t;
-
-typedef struct {
-  char *name;
-  bs_element_method_t *class_methods;
-  unsigned class_methods_count;
-  bs_element_method_t *instance_methods;
-  unsigned instance_methods_count;
-} bs_element_class_t;
-
-typedef struct {
-  SEL name;
-  char *type;
-  char *protocol_name;
-  bool class_method;
-} bs_element_informal_protocol_method_t;
-
-typedef enum {
-  BS_ELEMENT_STRUCT,            /* bs_element_struct_t */
-  BS_ELEMENT_CFTYPE,            /* bs_element_cftype_t */
-  BS_ELEMENT_OPAQUE,            /* bs_element_opaque_t */
-  BS_ELEMENT_CONSTANT,          /* bs_element_constant_t */
-  BS_ELEMENT_STRING_CONSTANT,   /* bs_element_string_constant_t */
-  BS_ELEMENT_ENUM,              /* bs_element_enum_t */
-  BS_ELEMENT_FUNCTION,          /* bs_element_function_t */
-  BS_ELEMENT_FUNCTION_ALIAS,    /* bs_element_function_alias_t */
-  BS_ELEMENT_CLASS,             /* bs_element_class_t */
-  BS_ELEMENT_INFORMAL_PROTOCOL_METHOD  
-                                /* bs_element_informal_protocol_method_t */
-} bs_element_type_t;
-
-/* bs_find_path()
- *
- * Finds the path of a framework's bridge support file, by looking at the
- * following locations, in order of priority:
- *  - inside the main executable bundle (if any), in the Resources/BridgeSupport directory ;
- *  - inside the framework bundle, in the Resources/BridgeSupport directory ;
- *  - in ~/Library/BridgeSupport ;
- *  - in /Library/BridgeSupport ;
- *  - in /System/Library/BridgeSupport.
- * Returns true on success, false otherwise.
- *
- * framework_path: the full path of the framework.
- * path: a pointer to a pre-allocated string that will contain the bridge
- * support path on success.
- * path_len: the size of the path argument.
- */
-bool bs_find_path(const char *framework_path, char *path, const size_t path_len);
-
-/* bs_parser_new()
- * 
- * Creates and returns a parser object, required for bs_parser_parse().
- * Use bs_parser_free() when you're done.
- */
-typedef struct _bs_parser bs_parser_t;
-bs_parser_t *bs_parser_new(void);
-
-/* bs_parser_free()
- *
- * Frees a previously-created parser object.
- */
-void bs_parser_free(bs_parser_t *parser);
-
-typedef void (*bs_parse_callback_t)
-  (bs_parser_t *parser, const char *path, bs_element_type_t type, void *value, 
-   void *context);
-
-typedef enum {
-  /* Default option: parse bridge support files. */
-  BS_PARSE_OPTIONS_DEFAULT = 0,
-  /* Parse bridge support files and dlopen(3) the dylib files, if any. */
-  BS_PARSE_OPTIONS_LOAD_DYLIBS
-} bs_parse_options_t;
-
-/* bs_parse() 
- *
- * Parses a given bridge support file, calling back a given function pointer 
- * for every parsed element. You are responsible to free every element passed 
- * to the callback function, using bs_element_free().
- * Returns true on success, otherwise false.
- *
- * parser: the parser object.
- * path: the full path of the bridge support file to parse.
- * framework_path: the full path of the framework this bridge support file 
- * comes from. This is only required if options is BS_PARSE_OPTIONS_LOAD_DYLIBS
- * in order to locate the dylib files. Pass NULL if you are passing the 
- * default BS_PARSE_OPTIONS_DEFAULT option.
- * options: parsing options.
- * callback: a callback function pointer.
- * context: a contextual data pointer that will be passed to the callback 
- * function.
- * error: in case this function returns false, this variable is set to a newly 
- * allocated error message. You are responsible to free it. Pass NULL if you 
- * don't need it.  
- */
-bool bs_parser_parse(bs_parser_t *parser, const char *path, 
-  const char *framework_path, bs_parse_options_t options, 
-  bs_parse_callback_t callback, void *context, char **error);
-
-/* bs_element_free()
- *
- * Frees a bridge support element that was returned by bs_parse() through the 
- * callback method.
- *
- * type: the type of the bridge support element.
- * value: a pointer to the bridge support element.
- */
-void bs_element_free(bs_element_type_t type, void *value);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __BS_H_ */

Deleted: MacRuby/trunk/bs_lex.h
===================================================================
--- MacRuby/trunk/bs_lex.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bs_lex.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,202 +0,0 @@
-/* ANSI-C code produced by gperf version 3.0.1 */
-/* Command-line: gperf --switch=1 --language=ANSI-C --struct-type -N bs_xml_element bs.gperf  */
-/* Computed positions: -k'1' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf at gnu.org>."
-#endif
-
-#line 1 "bs.gperf"
-struct bs_xml_atom { char *name; int val; };
-
-#define TOTAL_KEYWORDS 14
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 17
-#define MIN_HASH_VALUE 3
-#define MAX_HASH_VALUE 25
-/* maximum key range = 23, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (register const char *str, register unsigned int len)
-{
-  static unsigned char asso_values[] =
-    {
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26,  0, 26,  5,
-      15,  0,  0, 26, 26,  0, 26, 26, 26, 14,
-      26, 15, 26, 26, 10,  0, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-      26, 26, 26, 26, 26, 26
-    };
-  return len + asso_values[(unsigned char)str[0]];
-}
-
-#ifdef __GNUC__
-static __inline
-#endif
-struct bs_xml_atom *
-bs_xml_element (register const char *str, register unsigned int len)
-{
-  static struct bs_xml_atom wordlist[] =
-    {
-#line 7 "bs.gperf"
-      {"arg", 5 },
-#line 4 "bs.gperf"
-      {"enum", 2 },
-#line 5 "bs.gperf"
-      {"struct", 3 },
-#line 9 "bs.gperf"
-      {"function", 7},
-#line 10 "bs.gperf"
-      {"class", 8},
-#line 12 "bs.gperf"
-      {"cftype", 10},
-#line 3 "bs.gperf"
-      {"constant", 1},
-#line 14 "bs.gperf"
-      {"function_alias", 12},
-#line 15 "bs.gperf"
-      {"string_constant", 13},
-#line 8 "bs.gperf"
-      {"retval", 6},
-#line 6 "bs.gperf"
-      {"informal_protocol", 4},
-#line 11 "bs.gperf"
-      {"method", 9 },
-#line 13 "bs.gperf"
-      {"opaque", 11},
-#line 16 "bs.gperf"
-      {"depends_on", 14}
-    };
-
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
-        {
-          register struct bs_xml_atom *resword;
-
-          switch (key - 3)
-            {
-              case 0:
-                resword = &wordlist[0];
-                goto compare;
-              case 1:
-                resword = &wordlist[1];
-                goto compare;
-              case 3:
-                resword = &wordlist[2];
-                goto compare;
-              case 5:
-                resword = &wordlist[3];
-                goto compare;
-              case 7:
-                resword = &wordlist[4];
-                goto compare;
-              case 8:
-                resword = &wordlist[5];
-                goto compare;
-              case 10:
-                resword = &wordlist[6];
-                goto compare;
-              case 11:
-                resword = &wordlist[7];
-                goto compare;
-              case 12:
-                resword = &wordlist[8];
-                goto compare;
-              case 13:
-                resword = &wordlist[9];
-                goto compare;
-              case 14:
-                resword = &wordlist[10];
-                goto compare;
-              case 17:
-                resword = &wordlist[11];
-                goto compare;
-              case 18:
-                resword = &wordlist[12];
-                goto compare;
-              case 22:
-                resword = &wordlist[13];
-                goto compare;
-            }
-          return 0;
-        compare:
-          {
-            register const char *s = resword->name;
-
-            if (*str == *s && !strcmp (str + 1, s + 1))
-              return resword;
-          }
-        }
-    }
-  return 0;
-}
-#line 17 "bs.gperf"
-
-#define BS_XML_CONSTANT           1
-#define BS_XML_ENUM               2
-#define BS_XML_STRUCT             3
-#define BS_XML_INFORMAL_PROTOCOL  4
-#define BS_XML_ARG                5 
-#define BS_XML_RETVAL             6
-#define BS_XML_FUNCTION           7
-#define BS_XML_CLASS              8
-#define BS_XML_METHOD             9
-#define BS_XML_CFTYPE             10
-#define BS_XML_OPAQUE             11
-#define BS_XML_FUNCTION_ALIAS     12
-#define BS_XML_STRING_CONSTANT    13
-#define BS_XML_DEPENDS_ON         14

Deleted: MacRuby/trunk/bs_struct_readers.c
===================================================================
--- MacRuby/trunk/bs_struct_readers.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/bs_struct_readers.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,644 +0,0 @@
-// This file was generated by gen_bs_struct_readers.rb, do not modify it manually.
-static VALUE rb_vm_struct_reader_0 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[0];
-}
-static VALUE rb_vm_struct_reader_1 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[1];
-}
-static VALUE rb_vm_struct_reader_2 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[2];
-}
-static VALUE rb_vm_struct_reader_3 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[3];
-}
-static VALUE rb_vm_struct_reader_4 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[4];
-}
-static VALUE rb_vm_struct_reader_5 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[5];
-}
-static VALUE rb_vm_struct_reader_6 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[6];
-}
-static VALUE rb_vm_struct_reader_7 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[7];
-}
-static VALUE rb_vm_struct_reader_8 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[8];
-}
-static VALUE rb_vm_struct_reader_9 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[9];
-}
-static VALUE rb_vm_struct_reader_10 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[10];
-}
-static VALUE rb_vm_struct_reader_11 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[11];
-}
-static VALUE rb_vm_struct_reader_12 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[12];
-}
-static VALUE rb_vm_struct_reader_13 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[13];
-}
-static VALUE rb_vm_struct_reader_14 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[14];
-}
-static VALUE rb_vm_struct_reader_15 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[15];
-}
-static VALUE rb_vm_struct_reader_16 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[16];
-}
-static VALUE rb_vm_struct_reader_17 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[17];
-}
-static VALUE rb_vm_struct_reader_18 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[18];
-}
-static VALUE rb_vm_struct_reader_19 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[19];
-}
-static VALUE rb_vm_struct_reader_20 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[20];
-}
-static VALUE rb_vm_struct_reader_21 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[21];
-}
-static VALUE rb_vm_struct_reader_22 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[22];
-}
-static VALUE rb_vm_struct_reader_23 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[23];
-}
-static VALUE rb_vm_struct_reader_24 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[24];
-}
-static VALUE rb_vm_struct_reader_25 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[25];
-}
-static VALUE rb_vm_struct_reader_26 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[26];
-}
-static VALUE rb_vm_struct_reader_27 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[27];
-}
-static VALUE rb_vm_struct_reader_28 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[28];
-}
-static VALUE rb_vm_struct_reader_29 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[29];
-}
-static VALUE rb_vm_struct_reader_30 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[30];
-}
-static VALUE rb_vm_struct_reader_31 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[31];
-}
-static VALUE rb_vm_struct_reader_32 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[32];
-}
-static VALUE rb_vm_struct_reader_33 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[33];
-}
-static VALUE rb_vm_struct_reader_34 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[34];
-}
-static VALUE rb_vm_struct_reader_35 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[35];
-}
-static VALUE rb_vm_struct_reader_36 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[36];
-}
-static VALUE rb_vm_struct_reader_37 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[37];
-}
-static VALUE rb_vm_struct_reader_38 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[38];
-}
-static VALUE rb_vm_struct_reader_39 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[39];
-}
-static VALUE rb_vm_struct_reader_40 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[40];
-}
-static VALUE rb_vm_struct_reader_41 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[41];
-}
-static VALUE rb_vm_struct_reader_42 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[42];
-}
-static VALUE rb_vm_struct_reader_43 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[43];
-}
-static VALUE rb_vm_struct_reader_44 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[44];
-}
-static VALUE rb_vm_struct_reader_45 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[45];
-}
-static VALUE rb_vm_struct_reader_46 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[46];
-}
-static VALUE rb_vm_struct_reader_47 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[47];
-}
-static VALUE rb_vm_struct_reader_48 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[48];
-}
-static VALUE rb_vm_struct_reader_49 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[49];
-}
-static VALUE rb_vm_struct_reader_50 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[50];
-}
-static VALUE rb_vm_struct_reader_51 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[51];
-}
-static VALUE rb_vm_struct_reader_52 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[52];
-}
-static VALUE rb_vm_struct_reader_53 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[53];
-}
-static VALUE rb_vm_struct_reader_54 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[54];
-}
-static VALUE rb_vm_struct_reader_55 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[55];
-}
-static VALUE rb_vm_struct_reader_56 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[56];
-}
-static VALUE rb_vm_struct_reader_57 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[57];
-}
-static VALUE rb_vm_struct_reader_58 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[58];
-}
-static VALUE rb_vm_struct_reader_59 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[59];
-}
-static VALUE rb_vm_struct_reader_60 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[60];
-}
-static VALUE rb_vm_struct_reader_61 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[61];
-}
-static VALUE rb_vm_struct_reader_62 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[62];
-}
-static VALUE rb_vm_struct_reader_63 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[63];
-}
-static VALUE rb_vm_struct_reader_64 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[64];
-}
-static VALUE rb_vm_struct_reader_65 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[65];
-}
-static VALUE rb_vm_struct_reader_66 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[66];
-}
-static VALUE rb_vm_struct_reader_67 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[67];
-}
-static VALUE rb_vm_struct_reader_68 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[68];
-}
-static VALUE rb_vm_struct_reader_69 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[69];
-}
-static VALUE rb_vm_struct_reader_70 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[70];
-}
-static VALUE rb_vm_struct_reader_71 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[71];
-}
-static VALUE rb_vm_struct_reader_72 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[72];
-}
-static VALUE rb_vm_struct_reader_73 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[73];
-}
-static VALUE rb_vm_struct_reader_74 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[74];
-}
-static VALUE rb_vm_struct_reader_75 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[75];
-}
-static VALUE rb_vm_struct_reader_76 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[76];
-}
-static VALUE rb_vm_struct_reader_77 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[77];
-}
-static VALUE rb_vm_struct_reader_78 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[78];
-}
-static VALUE rb_vm_struct_reader_79 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[79];
-}
-static VALUE rb_vm_struct_reader_80 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[80];
-}
-static VALUE rb_vm_struct_reader_81 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[81];
-}
-static VALUE rb_vm_struct_reader_82 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[82];
-}
-static VALUE rb_vm_struct_reader_83 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[83];
-}
-static VALUE rb_vm_struct_reader_84 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[84];
-}
-static VALUE rb_vm_struct_reader_85 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[85];
-}
-static VALUE rb_vm_struct_reader_86 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[86];
-}
-static VALUE rb_vm_struct_reader_87 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[87];
-}
-static VALUE rb_vm_struct_reader_88 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[88];
-}
-static VALUE rb_vm_struct_reader_89 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[89];
-}
-static VALUE rb_vm_struct_reader_90 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[90];
-}
-static VALUE rb_vm_struct_reader_91 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[91];
-}
-static VALUE rb_vm_struct_reader_92 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[92];
-}
-static VALUE rb_vm_struct_reader_93 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[93];
-}
-static VALUE rb_vm_struct_reader_94 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[94];
-}
-static VALUE rb_vm_struct_reader_95 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[95];
-}
-static VALUE rb_vm_struct_reader_96 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[96];
-}
-static VALUE rb_vm_struct_reader_97 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[97];
-}
-static VALUE rb_vm_struct_reader_98 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[98];
-}
-static VALUE rb_vm_struct_reader_99 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[99];
-}
-static VALUE rb_vm_struct_reader_100 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[100];
-}
-static VALUE rb_vm_struct_reader_101 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[101];
-}
-static VALUE rb_vm_struct_reader_102 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[102];
-}
-static VALUE rb_vm_struct_reader_103 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[103];
-}
-static VALUE rb_vm_struct_reader_104 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[104];
-}
-static VALUE rb_vm_struct_reader_105 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[105];
-}
-static VALUE rb_vm_struct_reader_106 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[106];
-}
-static VALUE rb_vm_struct_reader_107 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[107];
-}
-static VALUE rb_vm_struct_reader_108 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[108];
-}
-static VALUE rb_vm_struct_reader_109 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[109];
-}
-static VALUE rb_vm_struct_reader_110 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[110];
-}
-static VALUE rb_vm_struct_reader_111 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[111];
-}
-static VALUE rb_vm_struct_reader_112 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[112];
-}
-static VALUE rb_vm_struct_reader_113 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[113];
-}
-static VALUE rb_vm_struct_reader_114 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[114];
-}
-static VALUE rb_vm_struct_reader_115 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[115];
-}
-static VALUE rb_vm_struct_reader_116 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[116];
-}
-static VALUE rb_vm_struct_reader_117 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[117];
-}
-static VALUE rb_vm_struct_reader_118 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[118];
-}
-static VALUE rb_vm_struct_reader_119 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[119];
-}
-static VALUE rb_vm_struct_reader_120 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[120];
-}
-static VALUE rb_vm_struct_reader_121 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[121];
-}
-static VALUE rb_vm_struct_reader_122 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[122];
-}
-static VALUE rb_vm_struct_reader_123 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[123];
-}
-static VALUE rb_vm_struct_reader_124 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[124];
-}
-static VALUE rb_vm_struct_reader_125 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[125];
-}
-static VALUE rb_vm_struct_reader_126 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[126];
-}
-static VALUE rb_vm_struct_reader_127 (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[127];
-}
-#define BS_STRUCT_MAX_FIELDS 128
-typedef VALUE rb_vm_struct_reader_t(VALUE, SEL);
-static rb_vm_struct_reader_t *struct_readers[] = { rb_vm_struct_reader_0, rb_vm_struct_reader_1, rb_vm_struct_reader_2, rb_vm_struct_reader_3, rb_vm_struct_reader_4, rb_vm_struct_reader_5, rb_vm_struct_reader_6, rb_vm_struct_reader_7, rb_vm_struct_reader_8, rb_vm_struct_reader_9, rb_vm_struct_reader_10, rb_vm_struct_reader_11, rb_vm_struct_reader_12, rb_vm_struct_reader_13, rb_vm_struct_reader_14, rb_vm_struct_reader_15, rb_vm_struct_reader_16, rb_vm_struct_reader_17, rb_vm_struct_reader_18, rb_vm_struct_reader_19, rb_vm_struct_reader_20, rb_vm_struct_reader_21, rb_vm_struct_reader_22, rb_vm_struct_reader_23, rb_vm_struct_reader_24, rb_vm_struct_reader_25, rb_vm_struct_reader_26, rb_vm_struct_reader_27, rb_vm_struct_reader_28, rb_vm_struct_reader_29, rb_vm_struct_reader_30, rb_vm_struct_reader_31, rb_vm_struct_reader_32, rb_vm_struct_reader_33, rb_vm_struct_reader_34, rb_vm_struct_reader_35, rb_vm_struct_reader_36, rb_vm_struct_reader_37, rb_vm_struct_reader_38, rb_vm_struct_reader_39, rb_vm_struct_reader_40, rb_vm_struct_reader_41, rb_vm_struct_reader_42, rb_vm_struct_reader_43, rb_vm_struct_reader_44, rb_vm_struct_reader_45, rb_vm_struct_reader_46, rb_vm_struct_reader_47, rb_vm_struct_reader_48, rb_vm_struct_reader_49, rb_vm_struct_reader_50, rb_vm_struct_reader_51, rb_vm_struct_reader_52, rb_vm_struct_reader_53, rb_vm_struct_reader_54, rb_vm_struct_reader_55, rb_vm_struct_reader_56, rb_vm_struct_reader_57, rb_vm_struct_reader_58, rb_vm_struct_reader_59, rb_vm_struct_reader_60, rb_vm_struct_reader_61, rb_vm_struct_reader_62, rb_vm_struct_reader_63, rb_vm_struct_reader_64, rb_vm_struct_reader_65, rb_vm_struct_reader_66, rb_vm_struct_reader_67, rb_vm_struct_reader_68, rb_vm_struct_reader_69, rb_vm_struct_reader_70, rb_vm_struct_reader_71, rb_vm_struct_reader_72, rb_vm_struct_reader_73, rb_vm_struct_reader_74, rb_vm_struct_reader_75, rb_vm_struct_reader_76, rb_vm_struct_reader_77, rb_vm_struct_reader_78, rb_vm_struct_reader_79, rb_vm_struct_reader_80, rb_vm_struct_reader_81, rb_vm_struct_reader_82, rb_vm_struct_reader_83, rb_vm_struct_reader_84, rb_vm_struct_reader_85, rb_vm_struct_reader_86, rb_vm_struct_reader_87, rb_vm_struct_reader_88, rb_vm_struct_reader_89, rb_vm_struct_reader_90, rb_vm_struct_reader_91, rb_vm_struct_reader_92, rb_vm_struct_reader_93, rb_vm_struct_reader_94, rb_vm_struct_reader_95, rb_vm_struct_reader_96, rb_vm_struct_reader_97, rb_vm_struct_reader_98, rb_vm_struct_reader_99, rb_vm_struct_reader_100, rb_vm_struct_reader_101, rb_vm_struct_reader_102, rb_vm_struct_reader_103, rb_vm_struct_reader_104, rb_vm_struct_reader_105, rb_vm_struct_reader_106, rb_vm_struct_reader_107, rb_vm_struct_reader_108, rb_vm_struct_reader_109, rb_vm_struct_reader_110, rb_vm_struct_reader_111, rb_vm_struct_reader_112, rb_vm_struct_reader_113, rb_vm_struct_reader_114, rb_vm_struct_reader_115, rb_vm_struct_reader_116, rb_vm_struct_reader_117, rb_vm_struct_reader_118, rb_vm_struct_reader_119, rb_vm_struct_reader_120, rb_vm_struct_reader_121, rb_vm_struct_reader_122, rb_vm_struct_reader_123, rb_vm_struct_reader_124, rb_vm_struct_reader_125, rb_vm_struct_reader_126, rb_vm_struct_reader_127 };

Deleted: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/class.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1366 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's class.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/signal.h"
-#include "ruby/node.h"
-#include "ruby/st.h"
-#include <ctype.h>
-#include <stdarg.h>
-#include "id.h"
-#include "vm.h"
-#include "objc.h"
-#include "class.h"
-
-extern st_table *rb_class_tbl;
-extern VALUE rb_cRubyObject;
-
-void
-rb_objc_class_sync_version(Class ocklass, Class ocsuper)
-{
-    const long super_version = RCLASS_VERSION(ocsuper);
-    long klass_version = RCLASS_VERSION(ocklass);
-
-    if (ocsuper == (Class)rb_cRubyObject
-	|| (super_version & RCLASS_IS_OBJECT_SUBCLASS)
-	    == RCLASS_IS_OBJECT_SUBCLASS) {
-	klass_version |= RCLASS_IS_OBJECT_SUBCLASS;
-    }
-
-    RCLASS_SET_VERSION(ocklass, klass_version);
-}
-
-static void *
-rb_obj_imp_allocWithZone(void *rcv, SEL sel, void *zone)
-{
-    // XXX honor zone?
-    return (void *)rb_vm_new_rb_object((VALUE)rcv);
-}
-
-static void *
-rb_obj_imp_copyWithZone(void *rcv, SEL sel, void *zone)
-{
-    // XXX honor zone?
-    // for now let rb_obj_dup allocate an instance, since we don't honor the
-    // zone yet anyways
-    return (void *)rb_obj_dup((VALUE)rcv);
-}
-
-static BOOL
-rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj)
-{
-    if (obj == NULL) {
-	return false;
-    }
-    VALUE arg = OC2RB(obj);
-    return rb_vm_call((VALUE)rcv, selEq, 1, &arg) == Qtrue;
-}
-
-static void *
-rb_obj_imp_init(void *rcv, SEL sel)
-{
-    rb_vm_call((VALUE)rcv, selInitialize, 0, NULL);
-    return rcv;
-}
-
-VALUE rb_any_to_string(VALUE obj, SEL sel);
-
-static void *
-rb_obj_imp_description(void *rcv, SEL sel)
-{
-    // If #description and #to_s are the same method (ex. when aliased)
-    Class rcv_class = (Class)CLASS_OF(rcv);
-    IMP desc_imp = class_getMethodImplementation(rcv_class, selDescription);
-    IMP to_s_imp = class_getMethodImplementation(rcv_class, selToS);
-    if (desc_imp == to_s_imp) {
-	return (void *)rb_any_to_string((VALUE)rcv, sel);
-    }
-    return (void *)rb_vm_call(OC2RB(rcv), selToS, 0, NULL);
-}
-
-static VALUE
-rb_objc_init(VALUE rcv, SEL sel)
-{
-    IMP imp = NULL;
-    rb_vm_method_node_t *node = NULL;
-    if (rb_vm_lookup_method((Class)CLASS_OF(rcv), sel, &imp, &node)
-	    && imp != NULL && node == NULL && imp != (IMP)rb_obj_imp_init) {
-	return (VALUE)((void *(*)(void *, SEL))*imp)((void *)rcv, selInit);
-    }
-    return rcv;
-}
-
-static VALUE
-rb_obj_superclass(VALUE klass, SEL sel)
-{
-    VALUE cl = RCLASS_SUPER(klass);
-    while (RCLASS_SINGLETON(cl)) {
-	cl = RCLASS_SUPER(cl);
-    }
-    return rb_class_real(cl, true);
-}
-
-VALUE rb_obj_init_copy(VALUE, SEL, VALUE);
-
-void
-rb_define_object_special_methods(VALUE klass)
-{
-    RCLASS_SET_VERSION(*(VALUE *)klass,
-	    (RCLASS_VERSION(*(VALUE *)klass) | RCLASS_HAS_ROBJECT_ALLOC));
-
-    rb_objc_define_method(*(VALUE *)klass, "new",
-	    rb_class_new_instance_imp, -1);
-    rb_objc_define_method(klass, "dup", rb_obj_dup, 0);
-    rb_objc_define_private_method(klass, "initialize", rb_objc_init, 0);
-    rb_objc_define_private_method(klass, "initialize_copy",
-	    rb_obj_init_copy, 1);
-    rb_objc_define_method(klass, "hash", rb_obj_id, 0);
-
-    // To make sure singleton classes will be filtered.
-    rb_objc_define_method(*(VALUE *)klass, "superclass", rb_obj_superclass, 0);
-    rb_objc_define_method(klass, "class", rb_obj_class, 0);
-
-    rb_objc_install_method(*(Class *)klass, selAllocWithZone,
-	    (IMP)rb_obj_imp_allocWithZone);
-    rb_objc_install_method((Class)klass, selIsEqual,
-	    (IMP)rb_obj_imp_isEqual);
-    rb_objc_install_method((Class)klass, selInit, (IMP)rb_obj_imp_init);
-    rb_objc_install_method((Class)klass, selDescription,
-	    (IMP)rb_obj_imp_description);
-
-    // Create -copyWithZone:, since the method doesn't exist yet we need to
-    // find the type encoding somewhere, here we check Symbol since it's
-    // created very early. 
-    Method m = class_getInstanceMethod((Class)rb_cSymbol, selCopyWithZone);
-    assert(m != NULL);
-    class_replaceMethod((Class)klass, selCopyWithZone, 
-	    (IMP)rb_obj_imp_copyWithZone, method_getTypeEncoding(m));
-}
-
-static VALUE
-rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
-{
-    char ocname[512] = { '\0' };
-    if (!rb_vm_generate_objc_class_name(name, ocname, sizeof ocname)) {
-	goto no_more_classes;
-    }
-
-    if (super == 0) {
-	super = rb_cObject;
-    }
-
-    Class ocklass = objc_allocateClassPair((Class)super, ocname, sizeof(id));
-    if (ocklass == NULL) {
-	goto no_more_classes;
-    }
-
-    long version_flag = RCLASS_IS_RUBY_CLASS;
-    if (flags == T_MODULE) {
-	version_flag |= RCLASS_IS_MODULE;
-    }
-    RCLASS_SET_VERSION(ocklass, version_flag);
-
-    objc_registerClassPair(ocklass);
-
-    if (klass != 0) {
-	rb_objc_class_sync_version(ocklass, (Class)super);
-    }
-
-    return (VALUE)ocklass;
-
-no_more_classes:
-    rb_raise(rb_eRuntimeError, "can't create new classes");
-}
-
-VALUE
-rb_objc_create_class(const char *name, VALUE super)
-{
-    VALUE klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
-   
-    if (super != rb_cNSObject && super != 0
-	    && ((RCLASS_VERSION(*(VALUE *)super) & RCLASS_HAS_ROBJECT_ALLOC)
-		== RCLASS_HAS_ROBJECT_ALLOC)) {
-	RCLASS_SET_VERSION(*(VALUE *)klass,
-		(RCLASS_VERSION(*(VALUE *)klass) | RCLASS_HAS_ROBJECT_ALLOC));
-    }
-
-    if (name != NULL && rb_class_tbl != NULL) {
-	st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
-    }
-
-    return klass;
-}
-
-static VALUE
-rb_class_boot2(VALUE super, const char *name)
-{
-    if (super == rb_cObject && rb_cRubyObject != 0) {
-	super = rb_cRubyObject;
-    }	
-    return rb_objc_create_class(name, super);
-}
-
-VALUE
-rb_class_boot(VALUE super)
-{
-    return rb_class_boot2(super, NULL);
-}
-
-void
-rb_check_inheritable(VALUE super)
-{
-    if (TYPE(super) != T_CLASS) {
-	rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
-		 rb_obj_classname(super));
-    }
-    if (RCLASS_SINGLETON(super)) {
-	rb_raise(rb_eTypeError, "can't make subclass of singleton class");
-    }
-}
-
-VALUE
-rb_class_new(VALUE super)
-{
-    Check_Type(super, T_CLASS);
-    rb_check_inheritable(super);
-    if (super == rb_cClass) {
-	rb_raise(rb_eTypeError, "can't make subclass of Class");
-    }
-    return rb_class_boot(super);
-}
-
-/* :nodoc: */
-VALUE
-rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
-{
-    static ID classpath = 0;
-    static ID classid = 0;
-
-    rb_obj_init_copy(clone, 0, orig);
-    {
-	VALUE super;
-	unsigned long version_flag;
-
-	if (!RCLASS_RUBY(orig)) {
-	    super = orig;
-	    rb_warn("cloning class `%s' is not supported, creating a " \
-		    "subclass instead", rb_class2name(orig));
-	}
-	else {
-	    super = RCLASS_SUPER(orig);
-	}
-	RCLASS_SET_SUPER(clone, super);
-
-	version_flag = RCLASS_IS_RUBY_CLASS;
-	if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
-	    version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
-	}
-
-	RCLASS_SET_VERSION(clone, version_flag);
-
-	rb_vm_copy_methods((Class)orig, (Class)clone);
-	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig);
-	if (ivar_dict != NULL) {
-	    CFMutableDictionaryRef cloned_ivar_dict;
-
-	    if (classpath == 0) {
-		classpath = rb_intern("__classpath__");
-	    }
-	    if (classid == 0) {
-		classid = rb_intern("__classid__");
-	    }
-	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0,
-		(CFDictionaryRef)ivar_dict);
-	    // Remove the classpath & classid (name) so that they are not
-	    // copied over the new module / class
-	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath);
-	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid);
-	    CFMakeCollectable(cloned_ivar_dict);
-	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
-	}
-    }
-
-    return clone;
-}
-
-/* :nodoc: */
-VALUE
-rb_class_init_copy(VALUE clone, SEL sel, VALUE orig)
-{
-    if (orig == rb_cBasicObject || orig == rb_cObject) {
-	rb_raise(rb_eTypeError, "can't copy the root class");
-    }
-    if (/* RCLASS_SUPER(clone) ||  FIXME: comment out because Singleton.clone raises a rb_eTypeError */
-	(clone == rb_cBasicObject || clone == rb_cObject)) {
-	rb_raise(rb_eTypeError, "already initialized class");
-    }
-    if (RCLASS_SINGLETON(orig)) {
-	rb_raise(rb_eTypeError, "can't copy singleton class");
-    }
-    clone =  rb_mod_init_copy(clone, 0, orig);
-    rb_objc_class_sync_version((Class)clone, (Class)orig);
-    return clone;
-}
-
-VALUE
-rb_singleton_class_clone(VALUE obj)
-{
-    VALUE klass = RBASIC(obj)->klass;
-    if (!RCLASS_SINGLETON(klass)) {
-	return klass;
-    }
-    else {
-	/* copy singleton(unnamed) class */
-	VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass));
-
-	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass);
-	if (ivar_dict != NULL) {
-	    CFMutableDictionaryRef cloned_ivar_dict;
-
-	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict);
-	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
-	    CFMakeCollectable(cloned_ivar_dict);
-	}
-
-	Method *methods;
-	unsigned i, methods_count;
-	methods = class_copyMethodList((Class)klass, &methods_count);
-	if (methods != NULL) {
-	    for (i = 0; i < methods_count; i++) {
-		Method method = methods[i], method2;
-		method2 = class_getInstanceMethod((Class)clone, method_getName(method));
-		if (method2 != class_getInstanceMethod((Class)RCLASS_SUPER(clone), method_getName(method))) {
-		    method_setImplementation(method2, method_getImplementation(method));
-		}
-		else {
-		    assert(class_addMethod((Class)clone, 
-				method_getName(method), 
-				method_getImplementation(method), 
-				method_getTypeEncoding(method)));
-		}
-	    }
-	    free(methods);
-	}
-
-	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-	if (RCLASS_SUPER(clone) == rb_cRubyObject) {
-	    long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS;
-	    RCLASS_SET_VERSION(clone, v);
-	}
-	RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON);
-
-	return clone;
-    }
-}
-
-void
-rb_singleton_class_attached(VALUE klass, VALUE obj)
-{
-    if (RCLASS_SINGLETON(klass)) {
-	static ID attachedId = 0;
-	if (attachedId == 0) {
-	    attachedId = rb_intern("__attached__");
-	}
-	rb_ivar_set(klass, attachedId, obj);
-    }
-}
-
-VALUE
-rb_make_singleton_class(VALUE super)
-{
-    VALUE klass = rb_objc_create_class(NULL, super);
-    long v = RCLASS_VERSION(klass);
-    if (super == rb_cRubyObject) {
-	v ^= RCLASS_IS_OBJECT_SUBCLASS;
-    }
-    v |= RCLASS_IS_RUBY_CLASS;
-    v |= RCLASS_IS_SINGLETON;
-    RCLASS_SET_VERSION(klass, v);
-    return klass;
-}
-
-VALUE
-rb_make_metaclass(VALUE obj, VALUE super)
-{
-    if (TYPE(obj) == T_CLASS && RCLASS_SINGLETON(obj)) {
-	RBASIC(obj)->klass = rb_cClass;
-	return rb_cClass;
-    }
-    else {
-	VALUE klass = rb_make_singleton_class(super);
-	VALUE outer = rb_vm_get_outer(super);
-	if (outer != Qundef) {
-	    rb_vm_set_outer(klass, outer);
-	}
-	RBASIC(obj)->klass = klass;
-	rb_singleton_class_attached(klass, obj);
-	return klass;
-    }
-}
-
-VALUE
-rb_define_class_id(ID id, VALUE super)
-{
-    if (super == 0) {
-	super = rb_cObject;
-    }
-    return rb_class_boot2(super, rb_id2name(id));
-}
-
-VALUE
-rb_class_inherited(VALUE super, VALUE klass)
-{
-    if (rb_vm_running()) {
-	if (super == 0) {
-	    super = rb_cObject;
-	}
-	return rb_vm_call(super, selInherited, 1, &klass);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_define_class(const char *name, VALUE super)
-{
-    VALUE klass;
-    ID id;
-
-    id = rb_intern(name);
-    if (rb_const_defined(rb_cObject, id)) {
-	klass = rb_const_get(rb_cObject, id);
-	if (TYPE(klass) != T_CLASS) {
-	    rb_raise(rb_eTypeError, "%s is not a class", name);
-	}
-	if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
-	    rb_name_error(id, "%s is already defined", name);
-	}
-	return klass;
-    }
-    if (!super) {
-	rb_warn("no super class for `%s', Object assumed", name);
-    }
-    klass = rb_define_class_id(id, super);
-    st_add_direct(rb_class_tbl, id, klass);
-    rb_name_class(klass, id);
-    rb_const_set(rb_cObject, id, klass);
-    rb_vm_set_outer(klass, rb_cObject);
-    rb_class_inherited(super, klass);
-
-    return klass;
-}
-
-VALUE
-rb_define_class_under(VALUE outer, const char *name, VALUE super)
-{
-    VALUE klass;
-    ID id;
-
-    id = rb_intern(name);
-    if (rb_const_defined_at(outer, id)) {
-	klass = rb_const_get_at(outer, id);
-	if (TYPE(klass) != T_CLASS) {
-	    rb_raise(rb_eTypeError, "%s is not a class", name);
-	}
-	if (RCLASS_RUBY(klass)) {
-	    // Only for pure Ruby classes, as Objective-C classes
-	    // might be returned from the dynamic resolver.
-	    if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
-		rb_name_error(id, "%s is already defined", name);
-	    }
-	    return klass;
-	}
-    }
-    if (!super) {
-	rb_warn("no super class for `%s::%s', Object assumed",
-		rb_class2name(outer), name);
-    }
-    klass = rb_define_class_id(id, super);
-    rb_set_class_path(klass, outer, name);
-    rb_const_set(outer, id, klass);
-    rb_class_inherited(super, klass);
-
-    return klass;
-}
-
-VALUE
-rb_module_new(void)
-{
-    return rb_define_module_id(0);
-}
-
-VALUE rb_mod_initialize(VALUE, SEL);
-
-VALUE
-rb_define_module_id(ID id)
-{
-    VALUE mdl = rb_objc_alloc_class(id == 0 ? NULL : rb_id2name(id),
-	    rb_cObject, T_MODULE, rb_cModule);
-
-    if ((rb_mKernel != 0) && (id == 0)) {
-	/* because Module#initialize can accept a block */
-	rb_objc_define_method(*(VALUE *)mdl, "initialize", rb_mod_initialize, 0);
-    }
-
-    return mdl;
-}
-
-VALUE
-rb_define_module(const char *name)
-{
-    VALUE module;
-    ID id;
-
-    id = rb_intern(name);
-    if (rb_const_defined(rb_cObject, id)) {
-	module = rb_const_get(rb_cObject, id);
-	if (TYPE(module) == T_MODULE)
-	    return module;
-	rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
-    }
-    module = rb_define_module_id(id);
-    st_add_direct(rb_class_tbl, id, module);
-    rb_const_set(rb_cObject, id, module);
-    rb_vm_set_outer(module, rb_cObject);
-
-    return module;
-}
-
-VALUE
-rb_define_module_under(VALUE outer, const char *name)
-{
-    VALUE module;
-    ID id;
-
-    id = rb_intern(name);
-    if (rb_const_defined_at(outer, id)) {
-	module = rb_const_get_at(outer, id);
-	if (TYPE(module) == T_MODULE)
-	    return module;
-	rb_raise(rb_eTypeError, "%s::%s is not a module",
-		 rb_class2name(outer), rb_obj_classname(module));
-    }
-    module = rb_define_module_id(id);
-    rb_const_set(outer, id, module);
-    rb_set_class_path(module, outer, name);
-
-    return module;
-}
-
-void
-rb_include_module2(VALUE klass, VALUE orig_klass, VALUE module, bool check,
-	bool add_methods)
-{
-    if (check) {
-	rb_frozen_class_p(klass);
-	if (!OBJ_TAINTED(klass)) {
-	    rb_secure(4);
-	}
-	Check_Type(module, T_MODULE);
-    }
-
-    // Register the module as included in the class.
-    VALUE ary = rb_attr_get(klass, idIncludedModules);
-    if (ary == Qnil) {
-	ary = rb_ary_new();
-	rb_ivar_set(klass, idIncludedModules, ary);
-    }
-    else {
-	if (rb_ary_includes(ary, module)) {
-	    return;
-	}
-    }
-    rb_ary_insert(ary, 0, module);
-
-    // Mark the module as included somewhere.
-    const long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
-    RCLASS_SET_VERSION(module, v);
-
-    // Register the class as included in the module.
-    ary = rb_attr_get(module, idIncludedInClasses);
-    if (ary == Qnil) {
-	ary = rb_ary_new();
-	rb_ivar_set(module, idIncludedInClasses, ary);
-    }
-    rb_ary_push(ary, klass);
-
-    // Delete the ancestors array if it exists, since we just changed it.
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
-    if (iv_dict != NULL) {
-	CFDictionaryRemoveValue(iv_dict, (const void *)idAncestors);
-    }
-
-    if (add_methods) {
-	// Copy methods. If original class has the basic -initialize and if the
-	// module has a customized -initialize, we must copy the customized
-	// version to the original class too.
-	rb_vm_copy_methods((Class)module, (Class)klass);
-
-	if (orig_klass != 0 && orig_klass != klass) {
-	    Method m = class_getInstanceMethod((Class)orig_klass,
-		    selInitialize);
-	    Method m2 = class_getInstanceMethod((Class)klass, selInitialize);
-	    if (m != NULL && m2 != NULL
-		&& method_getImplementation(m) == (IMP)rb_objc_init
-		&& method_getImplementation(m2) != (IMP)rb_objc_init) {
-		rb_vm_copy_method((Class)orig_klass, m2);
-	    }
-	}
-    }
-}
-
-void
-rb_include_module(VALUE klass, VALUE module)
-{
-    rb_include_module2(klass, 0, module, true, true);
-}
-
-/*
- *  call-seq:
- *     mod.included_modules -> array
- *  
- *  Returns the list of modules included in <i>mod</i>.
- *     
- *     module Mixin
- *     end
- *     
- *     module Outer
- *       include Mixin
- *     end
- *     
- *     Mixin.included_modules   #=> []
- *     Outer.included_modules   #=> [Mixin]
- */
-
-static void
-rb_mod_included_modules_nosuper(VALUE mod, VALUE ary)
-{
-    VALUE inc_mods = rb_attr_get(mod, idIncludedModules);
-    if (inc_mods != Qnil) {
-	int i, count = RARRAY_LEN(inc_mods);
-	for (i = 0; i < count; i++) {
-	    VALUE imod = RARRAY_AT(inc_mods, i);
-	    rb_ary_push(ary, imod);
-	    rb_ary_concat(ary, rb_mod_included_modules(imod));
-	}
-    }
-}
-
-VALUE
-rb_mod_included_modules(VALUE mod)
-{
-    VALUE ary = rb_ary_new();
-    bool mod_detected = false;
-
-    for (VALUE p = mod; p != 0; p = RCLASS_SUPER(p)) {
-	if (!mod_detected) {
-	    if (RCLASS_MODULE(p)) {
-		mod_detected = true;
-	    }
-	}
-	else {
-	    if (!RCLASS_SINGLETON(p)) {
-		break;
-	    }
-	}
-	rb_mod_included_modules_nosuper(p, ary);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     mod.include?(module)    => true or false
- *  
- *  Returns <code>true</code> if <i>module</i> is included in
- *  <i>mod</i> or one of <i>mod</i>'s ancestors.
- *     
- *     module A
- *     end
- *     class B
- *       include A
- *     end
- *     class C < B
- *     end
- *     B.include?(A)   #=> true
- *     C.include?(A)   #=> true
- *     A.include?(A)   #=> false
- */
-
-VALUE
-rb_mod_include_p(VALUE mod, SEL sel, VALUE mod2)
-{
-    return rb_ary_includes(rb_mod_included_modules(mod), mod2);
-}
-
-/*
- *  call-seq:
- *     mod.ancestors -> array
- *  
- *  Returns a list of modules included in <i>mod</i> (including
- *  <i>mod</i> itself).
- *     
- *     module Mod
- *       include Math
- *       include Comparable
- *     end
- *     
- *     Mod.ancestors    #=> [Mod, Comparable, Math]
- *     Math.ancestors   #=> [Math]
- */
-
-VALUE
-rb_mod_ancestors_nocopy(VALUE mod)
-{
-    VALUE ary = rb_attr_get(mod, idAncestors);
-    if (NIL_P(ary)) {
-	ary = rb_ary_new();
-	for (VALUE p = mod; p != 0; p = RCLASS_SUPER(p)) {
-	    rb_ary_push(ary, p);
-	    rb_mod_included_modules_nosuper(p, ary);
-	}
-	rb_ivar_set(mod, idAncestors, ary);	
-    }
-    return ary;
-}
-
-VALUE
-rb_mod_ancestors(VALUE mod)
-{
-    // This method should return a new array without singleton classes.
-    VALUE ary = rb_mod_ancestors_nocopy(mod);
-    VALUE filtered = rb_ary_new();
-    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	VALUE p = RARRAY_AT(ary, i);
-	if (!RCLASS_SINGLETON(p)) {
-	    rb_ary_push(filtered, p);
-	}
-    }
-    return filtered;
-}
-
-static int
-ins_methods_push(VALUE name, long type, VALUE ary, long visi)
-{
-    if (type != -1) {
-	bool visible;
-	switch (visi) {
-	    case NOEX_PRIVATE:
-	    case NOEX_PROTECTED:
-	    case NOEX_PUBLIC:
-		visible = (type == visi);
-		break;
-	    default:
-		visible = (type != NOEX_PRIVATE);
-		break;
-	}
-	if (visible) {
-	    rb_ary_push(ary, name);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static int
-ins_methods_i(VALUE name, ID type, VALUE ary)
-{
-    return ins_methods_push(name, type, ary, -1); /* everything but private */
-}
-
-static int
-ins_methods_prot_i(VALUE name, ID type, VALUE ary)
-{
-    return ins_methods_push(name, type, ary, NOEX_PROTECTED);
-}
-
-static int
-ins_methods_priv_i(VALUE name, ID type, VALUE ary)
-{
-    return ins_methods_push(name, type, ary, NOEX_PRIVATE);
-}
-
-static int
-ins_methods_pub_i(VALUE name, ID type, VALUE ary)
-{
-    return ins_methods_push(name, type, ary, NOEX_PUBLIC);
-}
-
-static VALUE
-class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (VALUE, ID, VALUE))
-{
-    VALUE ary;
-    VALUE recur, objc_methods;
-
-    ary = rb_ary_new();
-
-    if (argc == 0) {
-	recur = Qtrue;
-	objc_methods = Qfalse;
-    }
-    else {
-	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
-	if (NIL_P(recur)) {
-	    recur = Qtrue;
-	}
-	if (NIL_P(objc_methods)) {
-	    objc_methods = Qfalse;
-	}
-    }
-
-    while (mod != 0) {
-	rb_vm_push_methods(ary, mod, RTEST(objc_methods), func);
-	if (recur == Qfalse) {
-	   break;	   
-	}
-	mod = (VALUE)class_getSuperclass((Class)mod); 
-    } 
-
-    return ary;
-}
-
-/*
- *  call-seq:
- *     mod.instance_methods(include_super=true)   => array
- *  
- *  Returns an array containing the names of public instance methods in
- *  the receiver. For a module, these are the public methods; for a
- *  class, they are the instance (not singleton) methods. With no
- *  argument, or with an argument that is <code>false</code>, the
- *  instance methods in <i>mod</i> are returned, otherwise the methods
- *  in <i>mod</i> and <i>mod</i>'s superclasses are returned.
- *     
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       def method2()  end
- *     end
- *     class C < B
- *       def method3()  end
- *     end
- *     
- *     A.instance_methods                #=> [:method1]
- *     B.instance_methods(false)         #=> [:method2]
- *     C.instance_methods(false)         #=> [:method3]
- *     C.instance_methods(true).length   #=> 43
- */
-
-VALUE
-rb_class_instance_methods(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return class_instance_method_list(argc, argv, mod, ins_methods_i);
-}
-
-/*
- *  call-seq:
- *     mod.protected_instance_methods(include_super=true)   => array
- *  
- *  Returns a list of the protected instance methods defined in
- *  <i>mod</i>. If the optional parameter is not <code>false</code>, the
- *  methods of any ancestors are included.
- */
-
-VALUE
-rb_class_protected_instance_methods(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return class_instance_method_list(argc, argv, mod, ins_methods_prot_i);
-}
-
-/*
- *  call-seq:
- *     mod.private_instance_methods(include_super=true)    => array
- *  
- *  Returns a list of the private instance methods defined in
- *  <i>mod</i>. If the optional parameter is not <code>false</code>, the
- *  methods of any ancestors are included.
- *     
- *     module Mod
- *       def method1()  end
- *       private :method1
- *       def method2()  end
- *     end
- *     Mod.instance_methods           #=> [:method2]
- *     Mod.private_instance_methods   #=> [:method1]
- */
-
-VALUE
-rb_class_private_instance_methods(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return class_instance_method_list(argc, argv, mod, ins_methods_priv_i);
-}
-
-/*
- *  call-seq:
- *     mod.public_instance_methods(include_super=true)   => array
- *  
- *  Returns a list of the public instance methods defined in <i>mod</i>.
- *  If the optional parameter is not <code>false</code>, the methods of
- *  any ancestors are included.
- */
-
-VALUE
-rb_class_public_instance_methods(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return class_instance_method_list(argc, argv, mod, ins_methods_pub_i);
-}
-
-/*
- *  call-seq:
- *     obj.singleton_methods(all=true)    => array
- *  
- *  Returns an array of the names of singleton methods for <i>obj</i>.
- *  If the optional <i>all</i> parameter is true, the list will include
- *  methods in modules included in <i>obj</i>.
- *     
- *     module Other
- *       def three() end
- *     end
- *     
- *     class Single
- *       def Single.four() end
- *     end
- *     
- *     a = Single.new
- *     
- *     def a.one()
- *     end
- *     
- *     class << a
- *       include Other
- *       def two()
- *       end
- *     end
- *     
- *     Single.singleton_methods    #=> [:four]
- *     a.singleton_methods(false)  #=> [:two, :one]
- *     a.singleton_methods         #=> [:two, :one, :three]
- */
-
-VALUE 
-rb_obj_singleton_methods(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE recur, objc_methods, klass, ary;
-
-    if (argc == 0) {
-	recur = Qtrue;
-	objc_methods = Qfalse;
-    }
-    else {
-	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
-    }
-
-    klass = CLASS_OF(obj);
-    ary = rb_ary_new();
-
-    do {
-	if (RCLASS_SINGLETON(klass)) {
-	    rb_vm_push_methods(ary, klass, RTEST(objc_methods), ins_methods_i);
-	}
-	klass = RCLASS_SUPER(klass);
-    }
-    while (recur == Qtrue && klass != 0);
-
-    return ary;
-}
-
-static void
-rb_objc_add_method(VALUE klass, const char *name, void *imp, const int arity,
-		   const int noex, bool direct)
-{
-    if (!direct) {
-	assert(name[strlen(name) - 1] != ':');
-    }
-
-    NODE *body = rb_vm_cfunc_node_from_imp((Class)klass, arity, (IMP)imp, noex);
-    GC_RETAIN(body);
-
-    rb_vm_define_method((Class)klass, rb_vm_name_to_sel(name, arity), (IMP)imp,
-	    body, direct);
-}
-
-void *rb_vm_generate_mri_stub(void *imp, const int arity);
-
-static void
-rb_add_mri_method(VALUE klass, const char *name, void *imp, const int arity,
-	const int noex)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "MRI methods are not supported in MacRuby static");
-#else
-    imp = rb_vm_generate_mri_stub(imp, arity);
-    rb_objc_add_method(klass, name, imp, arity, noex, false);
-#endif
-}
-
-void
-rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
-{
-    Check_Type(klass, T_CLASS);
-    rb_add_mri_method(rb_singleton_class(klass), "alloc", func, 0,
-	    NOEX_PUBLIC);
-}
-
-void
-rb_objc_define_direct_method(VALUE klass, const char *name, void *imp,
-			     const int arity)
-{
-    rb_objc_add_method(klass, name, imp, arity, NOEX_PUBLIC, true);
-}
-
-void
-rb_objc_define_method(VALUE klass, const char *name, void *imp, const int arity)
-{
-    rb_objc_add_method(klass, name, imp, arity, NOEX_PUBLIC, false);
-}
-
-void
-rb_objc_define_private_method(VALUE klass, const char *name, void *imp,
-			      const int arity)
-{
-    rb_objc_add_method(klass, name, imp, arity, NOEX_PRIVATE, false);
-}
-
-void
-rb_objc_define_module_function(VALUE module, const char *name, void *imp,
-			       const int arity)
-{
-    rb_objc_define_private_method(module, name, imp, arity);
-    rb_objc_define_method(*(VALUE *)module, name, imp, arity);
-}
-
-void
-rb_undef_alloc_func(VALUE klass)
-{
-    // TODO
-#if 0
-    Check_Type(klass, T_CLASS);
-    rb_add_mri_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
-#endif
-}
-
-void
-rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc)
-{
-    rb_add_mri_method(klass, rb_id2name(name), func, argc, NOEX_PUBLIC);
-}
-
-void
-rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS),
-	int argc)
-{
-    rb_add_mri_method(klass, name, func, argc, NOEX_PUBLIC);
-}
-
-void
-rb_define_protected_method(VALUE klass, const char *name,
-	VALUE (*func)(ANYARGS), int argc)
-{
-    rb_add_mri_method(klass, name, func, argc, NOEX_PROTECTED);
-}
-
-void
-rb_define_private_method(VALUE klass, const char *name,
-	VALUE (*func)(ANYARGS), int argc)
-{
-    rb_add_mri_method(klass, name, func, argc, NOEX_PRIVATE);
-}
-
-void
-rb_undef_method(VALUE klass, const char *name)
-{
-    rb_vm_undef_method((Class)klass, rb_intern(name), false);
-}
-
-#define SPECIAL_SINGLETON(x,c) do {\
-    if (obj == (x)) {\
-	return c;\
-    }\
-} while (0)
-
-VALUE
-rb_singleton_class(VALUE obj)
-{
-    VALUE klass;
-
-    if (FIXNUM_P(obj) || SYMBOL_P(obj) || FIXFLOAT_P(obj)) {
-	rb_raise(rb_eTypeError, "can't define singleton");
-    }
-    if (rb_special_const_p(obj)) {
-	SPECIAL_SINGLETON(Qnil, rb_cNilClass);
-	SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
-	SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
-	rb_bug("unknown immediate %ld", obj);
-    }
-
-#if 0
-    DEFER_INTS;
-    if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
-	rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
-	klass = RBASIC(obj)->klass;
-    }
-    else
-#endif	
-    {
-	switch (TYPE(obj)) {
-	    case T_CLASS:
-	    case T_MODULE:
-		klass = *(VALUE *)obj;
-		rb_vm_set_outer(klass, obj);
-		break;
-
-	    default:
-		if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
-		    rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
-		    klass = RBASIC(obj)->klass;
-		}
-		else {
-		    klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
-		}
-		break;
-	}
-    }
-#if 0
-    if (OBJ_TAINTED(obj)) {
-	OBJ_TAINT(klass);
-    }
-    else {
-	OBJ_UNTAINT(klass);
-    }
-    if (OBJ_FROZEN(obj)) {
-	OBJ_FREEZE(klass);
-    }
-#endif
-//    ALLOW_INTS;
-
-    return klass;
-}
-
-void
-rb_define_singleton_method(VALUE obj, const char *name,
-	VALUE (*func)(ANYARGS), int argc)
-{
-    rb_define_method(rb_singleton_class(obj), name, func, argc);
-}
-
-void
-rb_define_module_function(VALUE module, const char *name,
-	VALUE (*func)(ANYARGS), int argc)
-{
-    rb_define_private_method(module, name, func, argc);
-    rb_define_singleton_method(module, name, func, argc);
-}
-
-void
-rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
-{
-    rb_define_module_function(rb_mKernel, name, func, argc);
-}
-
-void
-rb_define_alias(VALUE klass, const char *name1, const char *name2)
-{
-    rb_alias(klass, rb_intern(name1), rb_intern(name2));
-}
-
-void
-rb_define_attr(VALUE klass, const char *name, int read, int write)
-{
-    rb_attr(klass, rb_intern(name), read, write, Qfalse);
-}
-
-int
-rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
-{
-    int n, i = 0;
-    const char *p = fmt;
-    VALUE *var;
-    va_list vargs;
-
-    va_start(vargs, fmt);
-
-    if (*p == '*') goto rest_arg;
-
-    if (ISDIGIT(*p)) {
-	n = *p - '0';
-	if (n > argc)
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
-	for (i=0; i<n; i++) {
-	    var = va_arg(vargs, VALUE*);
-	    if (var) *var = argv[i];
-	}
-	p++;
-    }
-    else {
-	goto error;
-    }
-
-    if (ISDIGIT(*p)) {
-	n = i + *p - '0';
-	for (; i<n; i++) {
-	    var = va_arg(vargs, VALUE*);
-	    if (argc > i) {
-		if (var) *var = argv[i];
-	    }
-	    else {
-		if (var) *var = Qnil;
-	    }
-	}
-	p++;
-    }
-
-    if (*p == '*') {
-      rest_arg:
-	var = va_arg(vargs, VALUE*);
-	if (argc > i) {
-	    if (var) *var = rb_ary_new4(argc-i, argv+i);
-	    i = argc;
-	}
-	else {
-	    if (var) *var = rb_ary_new();
-	}
-	p++;
-    }
-
-    if (*p == '&') {
-	var = va_arg(vargs, VALUE*);
-	if (rb_block_given_p()) {
-	    *var = rb_block_proc();
-	}
-	else {
-	    *var = Qnil;
-	}
-	p++;
-    }
-    va_end(vargs);
-
-    if (*p != '\0') {
-	goto error;
-    }
-
-    if (argc > i) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
-    }
-
-    return argc;
-
-  error:
-    rb_fatal("bad scan arg format: %s", fmt);
-    return 0;
-}
-
-rb_class_flags_cache_t *rb_class_flags;
-
-void
-Init_PreClass(void)
-{
-    rb_class_flags = (rb_class_flags_cache_t *)calloc(
-	    CLASS_FLAGS_CACHE_SIZE, sizeof(rb_class_flags_cache_t));
-    assert(rb_class_flags != NULL);
-}
-
-static int
-foundation_type(Class k)
-{
-    Class tmp = k;
-    do {
-	if (tmp == (Class)rb_cNSString) {
-	    return T_STRING;
-	}
-	if (tmp == (Class)rb_cNSArray) {
-	    return T_ARRAY;
-	}
-	if (tmp == (Class)rb_cNSHash) {
-	    return T_HASH;
-	}
-	tmp = class_getSuperclass(tmp);
-    }
-    while (tmp != NULL);
-    return 0;
-}
-
-int
-rb_objc_type(VALUE obj)
-{
-    Class k = *(Class *)obj;
-
-    if (k != NULL) {
-	unsigned long mask = rb_class_get_mask(k);
-	int type = mask & 0xff;
-	if (type == 0) {
-	    // Type is not available, let's compute it. 	    
-	    if (k == (Class)rb_cSymbol) {
-		type = T_SYMBOL;
-		goto done;
-	    }
-	    if ((type = foundation_type(k)) != 0) {
-		goto done;
-	    }
-	    if (RCLASS_META(k)) {
-		if (RCLASS_MODULE(obj)) {
-		    type = T_MODULE;
-		    goto done;
-		}
-		else {
-		    type = T_CLASS;
-		    goto done;
-		}
-	    }
-	    const unsigned long flags = mask >> RCLASS_MASK_TYPE_SHIFT;
-	    if ((flags & RCLASS_IS_OBJECT_SUBCLASS)
-		    != RCLASS_IS_OBJECT_SUBCLASS) {
-		type = T_NATIVE;
-		goto done;
-	    }
-	    type = BUILTIN_TYPE(obj);
-
-done:
-	    assert(type != 0);
-	    mask |= type;
-	    rb_class_set_mask(k, mask); 
-	}	
-	return type;
-    }
-    return BUILTIN_TYPE(obj);
-}
-
-// Note: not returning 'bool' because the function is exported in ruby.h
-// and MRI does not include stdbool.
-int
-rb_obj_is_native(VALUE obj)
-{
-    Class k = *(Class *)obj;
-    return k != NULL && (RCLASS_VERSION(k) & RCLASS_IS_OBJECT_SUBCLASS)
-	!= RCLASS_IS_OBJECT_SUBCLASS;
-}
-
-VALUE
-rb_class_real(VALUE cl, bool hide_builtin_foundation_classes)
-{
-    if (cl == 0) {
-        return 0;
-    }
-    if (RCLASS_META(cl)) {
-	return RCLASS_MODULE(cl) ? rb_cModule : rb_cClass;
-    }
-    while (RCLASS_SINGLETON(cl)) {
-	cl = RCLASS_SUPER(cl);
-    }
-    if (hide_builtin_foundation_classes && !RCLASS_RUBY(cl)) {
-	switch (foundation_type((Class)cl)) {
-	    case T_STRING:
-		return rb_cRubyString;
-	    case T_ARRAY:
-		return rb_cRubyArray;
-	    case T_HASH:
-		return rb_cRubyHash;
-	}
-    }
-    return cl;
-}

Deleted: MacRuby/trunk/class.h
===================================================================
--- MacRuby/trunk/class.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/class.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,183 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __CLASS_H_
-#define __CLASS_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-bool rb_objc_hash_is_pure(VALUE);
-bool rb_objc_str_is_pure(VALUE);
-bool rb_objc_ary_is_pure(VALUE);
-
-VALUE rb_objc_create_class(const char *name, VALUE super);
-void rb_objc_class_sync_version(Class klass, Class super_class);
-void rb_define_object_special_methods(VALUE klass);
-VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *);
-VALUE rb_make_singleton_class(VALUE super);
-
-#define RCLASS_IS_OBJECT_SUBCLASS    (1<<1)  /* class is a true RubyObject subclass */
-#define RCLASS_IS_RUBY_CLASS         (1<<2)  /* class was created from Ruby */
-#define RCLASS_IS_MODULE             (1<<3)  /* class represents a Ruby Module */
-#define RCLASS_IS_SINGLETON	     (1<<4)  /* class represents a singleton */
-#define RCLASS_IS_FROZEN	     (1<<5)  /* class is frozen */
-#define RCLASS_IS_TAINTED	     (1<<6)  /* class is tainted */
-#define RCLASS_IS_INCLUDED           (1<<10)  /* module is included */
-#define RCLASS_HAS_ROBJECT_ALLOC     (1<<11)  /* class uses the default RObject alloc */
-#define RCLASS_SCOPE_PRIVATE	     (1<<12)  /* class opened for private methods */
-#define RCLASS_SCOPE_PROTECTED	     (1<<13)  /* class opened for protected methods */
-#define RCLASS_SCOPE_MOD_FUNC	     (1<<14)  /* class opened for module_function methods */
-#define RCLASS_KVO_CHECK_DONE	     (1<<15)  /* class created by KVO and flags merged */
-
-typedef struct rb_class_flags_cache {
-    Class klass;
-    unsigned long value;
-    struct rb_class_flags_cache *next;
-} rb_class_flags_cache_t;
-
-#define CLASS_FLAGS_CACHE_SIZE 0x1000
-
-extern rb_class_flags_cache_t *rb_class_flags;
-
-static unsigned int
-rb_class_flags_hash(Class k)
-{
-    return ((unsigned long)k >> 2) & (CLASS_FLAGS_CACHE_SIZE - 1);
-}
-
-static inline unsigned long
-rb_class_get_mask(Class k)
-{
-    rb_class_flags_cache_t *e = &rb_class_flags[rb_class_flags_hash(k)];
-    while (e != NULL) {
-	if (e->klass == k) {
-	    return e->value;
-	}
-	e = e->next;
-    }
-    return 0;
-}
-
-static inline void
-rb_class_set_mask(Class k, unsigned long mask)
-{
-    rb_class_flags_cache_t *e = &rb_class_flags[rb_class_flags_hash(k)];
-again:
-    if (e->klass == k) {
-set_value:
-	e->value = mask;
-	return;
-    }
-    if (e->klass == 0) {
-	e->klass = k;
-	goto set_value;
-    }
-    if (e->next != NULL) {
-	e = e->next;
-	goto again;
-    }
-    rb_class_flags_cache_t *ne = (rb_class_flags_cache_t *)malloc(
-	    sizeof(rb_class_flags_cache_t));
-    ne->klass = k;
-    ne->value = mask;
-    ne->next = NULL;
-    e->next = ne;
-}
-
-#define RCLASS_MASK_TYPE_SHIFT 16
-
-static inline unsigned long
-rb_class_get_flags(Class k)
-{
-    return rb_class_get_mask(k) >> RCLASS_MASK_TYPE_SHIFT;
-}
-
-static inline void
-rb_class_set_flags(Class k, unsigned long flags)
-{
-    rb_class_set_mask(k, flags << RCLASS_MASK_TYPE_SHIFT);
-}
-
-#define RCLASS_VERSION(m) (rb_class_get_flags((Class)m))
-#define RCLASS_SET_VERSION(m,f) (rb_class_set_flags((Class)m, (unsigned long)f))
-#define RCLASS_SET_VERSION_FLAG(m,f) (RCLASS_SET_VERSION((Class)m, (RCLASS_VERSION(m) | f)))
-
-#define RCLASS_RUBY(m) ((RCLASS_VERSION(m) & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS)
-#define RCLASS_MODULE(m) ((RCLASS_VERSION(m) & RCLASS_IS_MODULE) == RCLASS_IS_MODULE)
-#define RCLASS_SINGLETON(m) ((RCLASS_VERSION(m) & RCLASS_IS_SINGLETON) == RCLASS_IS_SINGLETON)
-
-CFMutableDictionaryRef rb_class_ivar_dict(VALUE);
-CFMutableDictionaryRef rb_class_ivar_dict_or_create(VALUE);
-void rb_class_ivar_set_dict(VALUE, CFMutableDictionaryRef);
-
-typedef enum {
-    SCOPE_DEFAULT = 0,  // public for everything but Object
-    SCOPE_PUBLIC,
-    SCOPE_PRIVATE,
-    SCOPE_PROTECTED,
-    SCOPE_MODULE_FUNC,
-} rb_vm_scope_t;
-
-static inline void
-rb_vm_check_if_module(VALUE mod)
-{
-    switch (TYPE(mod)) {
-	case T_CLASS:
-	case T_MODULE:
-	    break;
-
-	default:
-	    rb_raise(rb_eTypeError, "%s is not a class/module",
-		    RSTRING_PTR(rb_inspect(mod)));
-    }
-}
-
-static inline void
-rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope)
-{
-    if (scope == SCOPE_DEFAULT) {
-	scope = mod == rb_cObject ? SCOPE_PRIVATE : SCOPE_PUBLIC;
-    }
-    long v = RCLASS_VERSION(mod);
-    switch (scope) {
-	case SCOPE_PUBLIC:
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_PRIVATE:
-	    v |= RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_PROTECTED:
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v |= RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_MODULE_FUNC:
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v |= RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_DEFAULT:
-	    abort(); // handled earlier
-    }
-
-    RCLASS_SET_VERSION(mod, v);
-}
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __CLASS_H_

Deleted: MacRuby/trunk/compar.c
===================================================================
--- MacRuby/trunk/compar.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/compar.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,221 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-
-VALUE rb_mComparable;
-
-static SEL cmp = 0;
-
-void
-rb_cmperr(VALUE x, VALUE y)
-{
-    const char *classname;
-
-    if (SPECIAL_CONST_P(y)) {
-	y = rb_inspect(y);
-	classname = StringValuePtr(y);
-    }
-    else {
-	classname = rb_obj_classname(y);
-    }
-    rb_raise(rb_eArgError, "comparison of %s with %s failed",
-	     rb_obj_classname(x), classname);
-}
-
-VALUE
-rb_objs_cmp(VALUE x, VALUE y)
-{
-    return rb_vm_call(x, cmp, 1, &y);
-}
-
-static VALUE
-cmp_eq(VALUE *a)
-{
-    VALUE c = rb_vm_call(a[0], cmp, 1, &a[1]);
-    if (NIL_P(c)) {
-	return Qfalse;
-    }
-    if (rb_cmpint(c, a[0], a[1]) == 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-static VALUE
-cmp_failed(void)
-{
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj == other    => true or false
- *  
- *  Compares two objects based on the receiver's <code><=></code>
- *  method, returning true if it returns 0. Also returns true if
- *  _obj_ and _other_ are the same object.
- */
-
-static VALUE
-cmp_equal(VALUE x, SEL sel, VALUE y)
-{
-    VALUE a[2];
-
-    if (x == y) return Qtrue;
-
-    a[0] = x; a[1] = y;
-    return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
-}
-
-/*
- *  call-seq:
- *     obj > other    => true or false
- *  
- *  Compares two objects based on the receiver's <code><=></code>
- *  method, returning true if it returns 1.
- */
-
-static VALUE
-cmp_gt(VALUE x, SEL sel, VALUE y)
-{
-    VALUE c = rb_vm_call(x, cmp, 1, &y);
-    if (rb_cmpint(c, x, y) > 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj >= other    => true or false
- *  
- *  Compares two objects based on the receiver's <code><=></code>
- *  method, returning true if it returns 0 or 1.
- */
-
-static VALUE
-cmp_ge(VALUE x, SEL sel, VALUE y)
-{
-    VALUE c = rb_vm_call(x, cmp, 1, &y);
-    if (rb_cmpint(c, x, y) >= 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj < other    => true or false
- *  
- *  Compares two objects based on the receiver's <code><=></code>
- *  method, returning true if it returns -1.
- */
-
-static VALUE
-cmp_lt(VALUE x, SEL sel, VALUE y)
-{
-    VALUE c = rb_vm_call(x, cmp, 1, &y);
-    if (rb_cmpint(c, x, y) < 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj <= other    => true or false
- *  
- *  Compares two objects based on the receiver's <code><=></code>
- *  method, returning true if it returns -1 or 0.
- */
-
-static VALUE
-cmp_le(VALUE x, SEL sel, VALUE y)
-{
-    VALUE c = rb_vm_call(x, cmp, 1, &y);
-    if (rb_cmpint(c, x, y) <= 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj.between?(min, max)    => true or false
- *  
- *  Returns <code>false</code> if <i>obj</i> <code><=></code>
- *  <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
- *  <i>max</i> is greater than zero, <code>true</code> otherwise.
- *     
- *     3.between?(1, 5)               #=> true
- *     6.between?(1, 5)               #=> false
- *     'cat'.between?('ant', 'dog')   #=> true
- *     'gnu'.between?('ant', 'dog')   #=> false
- *     
- */
-
-static VALUE
-cmp_between(VALUE x, SEL sel, VALUE min, VALUE max)
-{
-    if (RTEST(cmp_lt(x, 0, min))) return Qfalse;
-    if (RTEST(cmp_gt(x, 0, max))) return Qfalse;
-    return Qtrue;
-}
-
-/*
- *  The <code>Comparable</code> mixin is used by classes whose objects
- *  may be ordered. The class must define the <code><=></code> operator,
- *  which compares the receiver against another object, returning -1, 0,
- *  or +1 depending on whether the receiver is less than, equal to, or
- *  greater than the other object. <code>Comparable</code> uses
- *  <code><=></code> to implement the conventional comparison operators
- *  (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
- *  and <code>></code>) and the method <code>between?</code>.
- *     
- *     class SizeMatters
- *       include Comparable
- *       attr :str
- *       def <=>(anOther)
- *         str.size <=> anOther.str.size
- *       end
- *       def initialize(str)
- *         @str = str
- *       end
- *       def inspect
- *         @str
- *       end
- *     end
- *     
- *     s1 = SizeMatters.new("Z")
- *     s2 = SizeMatters.new("YY")
- *     s3 = SizeMatters.new("XXX")
- *     s4 = SizeMatters.new("WWWW")
- *     s5 = SizeMatters.new("VVVVV")
- *     
- *     s1 < s2                       #=> true
- *     s4.between?(s1, s3)           #=> false
- *     s4.between?(s3, s5)           #=> true
- *     [ s3, s2, s5, s4, s1 ].sort   #=> [Z, YY, XXX, WWWW, VVVVV]
- *     
- */
-
-void
-Init_Comparable(void)
-{
-    rb_mComparable = rb_define_module("Comparable");
-    rb_objc_define_method(rb_mComparable, "==", cmp_equal, 1);
-    rb_objc_define_method(rb_mComparable, ">", cmp_gt, 1);
-    rb_objc_define_method(rb_mComparable, ">=", cmp_ge, 1);
-    rb_objc_define_method(rb_mComparable, "<", cmp_lt, 1);
-    rb_objc_define_method(rb_mComparable, "<=", cmp_le, 1);
-    rb_objc_define_method(rb_mComparable, "between?", cmp_between, 2);
-
-    cmp = sel_registerName("<=>:");
-}

Deleted: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/compiler.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,7129 +0,0 @@
-/*
- * MacRuby Compiler.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#if !defined(MACRUBY_STATIC)
-
-#define ROXOR_COMPILER_DEBUG 	0
-
-#if !defined(DW_LANG_Ruby)
-# define DW_LANG_Ruby 0x15 // TODO: Python is 0x14, request a real number
-#endif
-
-#include <llvm/LLVMContext.h>
-#include <llvm/Transforms/Utils/Cloning.h>
-
-#include "llvm.h"
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "ruby/node.h"
-#include "id.h"
-#include "vm.h"
-#include "compiler.h"
-#include "objc.h"
-#include "version.h"
-#include "encoding.h"
-#include "re.h"
-#include "bs.h"
-#include "class.h"
-
-extern "C" const char *ruby_node_name(int node);
-
-// Will be set later, in vm.cpp.
-llvm::Module *RoxorCompiler::module = NULL;
-RoxorCompiler *RoxorCompiler::shared = NULL;
-
-#define __save_state(type, var) \
-    type __old__##var = var
-
-#define __restore_state(var) \
-    var = __old__##var
-
-#define save_compiler_state() \
-    __save_state(unsigned int, current_line);\
-    __save_state(BasicBlock *, bb);\
-    __save_state(BasicBlock *, entry_bb);\
-    __save_state(ID, current_mid);\
-    __save_state(rb_vm_arity_t, current_arity);\
-    __save_state(ID, self_id);\
-    __save_state(Value *, current_self);\
-    __save_state(bool, current_block);\
-    __save_state(bool, current_block_chain);\
-    __save_state(Value *, current_var_uses);\
-    __save_state(Value *, running_block);\
-    __save_state(Value *, current_block_arg);\
-    __save_state(BasicBlock *, begin_bb);\
-    __save_state(BasicBlock *, rescue_invoke_bb);\
-    __save_state(BasicBlock *, rescue_rethrow_bb);\
-    __save_state(BasicBlock *, ensure_bb);\
-    __save_state(bool, current_rescue);\
-    __save_state(NODE *, current_block_node);\
-    __save_state(Function *, current_block_func);\
-    __save_state(Function *, current_non_block_func);\
-    __save_state(GlobalVariable *, current_opened_class);\
-    __save_state(bool, dynamic_class);\
-    __save_state(BasicBlock *, current_loop_begin_bb);\
-    __save_state(BasicBlock *, current_loop_body_bb);\
-    __save_state(BasicBlock *, current_loop_end_bb);\
-    __save_state(PHINode *, current_loop_exit_val);\
-    __save_state(int, return_from_block);\
-    __save_state(int, return_from_block_ids);\
-    __save_state(PHINode *, ensure_pn);\
-    __save_state(NODE *, ensure_node);\
-    __save_state(bool, block_declaration);\
-    __save_state(AllocaInst *, dispatch_argv);\
-    __save_state(uint64_t, outer_mask);
-
-#define restore_compiler_state() \
-    __restore_state(current_line);\
-    __restore_state(bb);\
-    __restore_state(entry_bb);\
-    __restore_state(current_mid);\
-    __restore_state(current_arity);\
-    __restore_state(self_id);\
-    __restore_state(current_self);\
-    __restore_state(current_block);\
-    __restore_state(current_block_chain);\
-    __restore_state(current_var_uses);\
-    __restore_state(running_block);\
-    __restore_state(current_block_arg);\
-    __restore_state(begin_bb);\
-    __restore_state(rescue_invoke_bb);\
-    __restore_state(rescue_rethrow_bb);\
-    __restore_state(ensure_bb);\
-    __restore_state(current_rescue);\
-    __restore_state(current_block_node);\
-    __restore_state(current_block_func);\
-    __restore_state(current_non_block_func);\
-    __restore_state(current_opened_class);\
-    __restore_state(dynamic_class);\
-    __restore_state(current_loop_begin_bb);\
-    __restore_state(current_loop_body_bb);\
-    __restore_state(current_loop_end_bb);\
-    __restore_state(current_loop_exit_val);\
-    __restore_state(return_from_block);\
-    __restore_state(return_from_block_ids);\
-    __restore_state(ensure_pn);\
-    __restore_state(ensure_node);\
-    __restore_state(block_declaration);\
-    __restore_state(dispatch_argv);\
-    __restore_state(outer_mask);
-
-#define reset_compiler_state() \
-    bb = NULL;\
-    entry_bb = NULL;\
-    begin_bb = NULL;\
-    rescue_invoke_bb = NULL;\
-    rescue_rethrow_bb = NULL;\
-    ensure_bb = NULL;\
-    current_mid = 0;\
-    current_arity = rb_vm_arity(-1);\
-    self_id = rb_intern("self");\
-    current_self = NULL;\
-    current_var_uses = NULL;\
-    running_block = NULL;\
-    current_block_arg = NULL;\
-    current_block = false;\
-    current_block_chain = false;\
-    current_block_node = NULL;\
-    current_block_func = NULL;\
-    current_non_block_func = NULL;\
-    current_opened_class = NULL;\
-    dynamic_class = false;\
-    current_loop_begin_bb = NULL;\
-    current_loop_body_bb = NULL;\
-    current_loop_end_bb = NULL;\
-    current_loop_exit_val = NULL;\
-    current_rescue = false;\
-    return_from_block = -1;\
-    return_from_block_ids = 0;\
-    ensure_pn = NULL;\
-    ensure_node = NULL;\
-    block_declaration = false;\
-    dispatch_argv = NULL;\
-    outer_mask = 0;
-
-RoxorCompiler::RoxorCompiler(bool _debug_mode)
-{
-    assert(RoxorCompiler::module != NULL);
-#if !defined(LLVM_TOT)
-    debug_info = new DIBuilder(*RoxorCompiler::module);
-#else
-    debug_info = new DIFactory(*RoxorCompiler::module);
-#endif
-
-    can_interpret = false;
-    debug_mode = _debug_mode;
-    fname = "";
-    inside_eval = false;
-    current_line = 0;
-
-    reset_compiler_state();
-
-    writeBarrierFunc = get_function("vm_gc_wb");
-    dispatchFunc = get_function("vm_dispatch");
-    fastPlusFunc = get_function("vm_fast_plus");
-    fastMinusFunc = get_function("vm_fast_minus");
-    fastMultFunc = get_function("vm_fast_mult");
-    fastDivFunc = get_function("vm_fast_div");
-    fastLtFunc = get_function("vm_fast_lt");
-    fastLeFunc = get_function("vm_fast_le");
-    fastGtFunc = get_function("vm_fast_gt");
-    fastGeFunc = get_function("vm_fast_ge");
-    fastEqFunc = get_function("vm_fast_eq");
-    fastNeqFunc = get_function("vm_fast_neq");
-    fastEqqFunc = get_function("vm_fast_eqq");
-    fastArefFunc = get_function("vm_fast_aref");
-    fastAsetFunc = get_function("vm_fast_aset");
-    fastShiftFunc = get_function("vm_fast_shift");
-    whenSplatFunc = get_function("vm_when_splat");
-    prepareBlockFunc = NULL;
-    pushBindingFunc = NULL;
-    getBlockFunc = get_function("vm_get_block");
-    currentBlockObjectFunc = NULL;
-    getConstFunc = get_function("vm_get_const");
-    setConstFunc = get_function("vm_set_const");
-    prepareMethodFunc = NULL;
-    singletonClassFunc = NULL;
-    defineClassFunc = NULL;
-    getIvarFunc = get_function("vm_ivar_get");
-    setIvarFunc = get_function("vm_ivar_set");
-    willChangeValueFunc = NULL;
-    didChangeValueFunc = NULL;
-    definedFunc = NULL;
-    undefFunc = NULL;
-    aliasFunc = NULL;
-    valiasFunc = NULL;
-    newHashFunc = get_function("vm_rhash_new");
-    storeHashFunc = get_function("vm_rhash_store");
-    toAFunc = get_function("vm_to_a");
-    toAryFunc = get_function("vm_to_ary");
-    catArrayFunc = get_function("vm_ary_cat");
-    dupArrayFunc = get_function("vm_ary_dup");
-    newArrayFunc = get_function("vm_rary_new");
-    asetArrayFunc = get_function("vm_rary_aset");
-    entryArrayFunc = get_function("vm_ary_entry");
-    checkArrayFunc = get_function("vm_ary_check");
-    lengthArrayFunc = get_function("vm_ary_length");
-    ptrArrayFunc = get_function("vm_ary_ptr");
-    newStructFunc = NULL;
-    newOpaqueFunc = NULL;
-    newPointerFunc = NULL;
-    getStructFieldsFunc = NULL;
-    getOpaqueDataFunc = NULL;
-    getPointerPtrFunc = get_function("vm_rval_to_cptr");
-    xmallocFunc = NULL;
-    checkArityFunc = NULL;
-    setStructFunc = NULL;
-    newRangeFunc = NULL;
-    newRegexpFunc = NULL;
-    strInternFunc = NULL;
-    selToSymFunc = NULL;
-    keepVarsFunc = NULL;
-    masgnGetElemBeforeSplatFunc =
-	get_function("vm_masgn_get_elem_before_splat");
-    masgnGetElemAfterSplatFunc = get_function("vm_masgn_get_elem_after_splat");
-    masgnGetSplatFunc = get_function("vm_masgn_get_splat");
-    newStringFunc = NULL;
-    newString2Func = NULL;
-    newString3Func = NULL;
-    yieldFunc = get_function("vm_yield_args");
-    getBrokenFunc = get_function("vm_get_broken_value");
-    blockEvalFunc = NULL;
-    gvarSetFunc = NULL;
-    gvarGetFunc = NULL;
-    cvarSetFunc = get_function("vm_cvar_set");
-    cvarGetFunc = get_function("vm_cvar_get");
-    currentExceptionFunc = NULL;
-    popExceptionFunc = NULL;
-    getSpecialFunc = get_function("vm_get_special");
-    breakFunc = NULL;
-    returnFromBlockFunc = NULL;
-    returnedFromBlockFunc = get_function("vm_returned_from_block");
-    checkReturnFromBlockFunc = NULL;
-    setHasEnsureFunc = NULL;
-    setScopeFunc = get_function("vm_set_current_scope");
-    setCurrentClassFunc = NULL;
-    debugTrapFunc = NULL;
-    getFFStateFunc = NULL;
-    setFFStateFunc = NULL;
-    releaseOwnershipFunc = get_function("vm_release_ownership");
-    ocvalToRvalFunc = get_function("vm_ocval_to_rval");
-    charToRvalFunc = get_function("vm_char_to_rval");
-    ucharToRvalFunc = get_function("vm_uchar_to_rval");
-    shortToRvalFunc = get_function("vm_short_to_rval");
-    ushortToRvalFunc = get_function("vm_ushort_to_rval");
-    intToRvalFunc = get_function("vm_int_to_rval");
-    uintToRvalFunc = get_function("vm_uint_to_rval");
-    longToRvalFunc = get_function("vm_long_to_rval");
-    ulongToRvalFunc = get_function("vm_ulong_to_rval");
-    longLongToRvalFunc = get_function("vm_long_long_to_rval");
-    ulongLongToRvalFunc = get_function("vm_ulong_long_to_rval");
-    floatToRvalFunc = get_function("vm_float_to_rval");
-    doubleToRvalFunc = get_function("vm_double_to_rval");
-    selToRvalFunc = get_function("vm_sel_to_rval");
-    charPtrToRvalFunc = get_function("vm_charptr_to_rval");
-    rvalToOcvalFunc = get_function("vm_rval_to_ocval");
-    rvalToBoolFunc = get_function("vm_rval_to_bool");
-    rvalToCharFunc = get_function("vm_rval_to_char");
-    rvalToUcharFunc = get_function("vm_rval_to_uchar");
-    rvalToShortFunc = get_function("vm_rval_to_short");
-    rvalToUshortFunc = get_function("vm_rval_to_ushort");
-    rvalToIntFunc = get_function("vm_rval_to_int");
-    rvalToUintFunc = get_function("vm_rval_to_uint");
-    rvalToLongFunc = get_function("vm_rval_to_long");
-    rvalToUlongFunc = get_function("vm_rval_to_ulong");
-    rvalToLongLongFunc = get_function("vm_rval_to_long_long");
-    rvalToUlongLongFunc = get_function("vm_rval_to_ulong_long");
-    rvalToFloatFunc = get_function("vm_rval_to_float");
-    rvalToDoubleFunc = get_function("vm_rval_to_double");
-    rvalToSelFunc = get_function("vm_rval_to_sel");
-    rvalToCharPtrFunc = get_function("vm_rval_to_charptr");
-    initBlockFunc = get_function("vm_init_c_block");
-    blockProcFunc = get_function("vm_ruby_block_literal_proc");
-    setCurrentMRIMethodContext = NULL;
-
-    VoidTy = Type::getVoidTy(context);
-    Int1Ty = Type::getInt1Ty(context);
-    Int8Ty = Type::getInt8Ty(context);
-    Int16Ty = Type::getInt16Ty(context);
-    Int32Ty = Type::getInt32Ty(context);
-    Int64Ty = Type::getInt64Ty(context);
-    FloatTy = Type::getFloatTy(context);
-    DoubleTy = Type::getDoubleTy(context);
-
-#if __LP64__
-    RubyObjTy = IntTy = Int64Ty;
-#else
-    RubyObjTy = IntTy = Int32Ty;
-#endif
-
-    zeroVal = ConstantInt::get(IntTy, 0);
-    oneVal = ConstantInt::get(IntTy, 1);
-    twoVal = ConstantInt::get(IntTy, 2);
-    threeVal = ConstantInt::get(IntTy, 3);
-
-    defaultScope = ConstantInt::get(Int32Ty, SCOPE_DEFAULT);
-    publicScope = ConstantInt::get(Int32Ty, SCOPE_PUBLIC);
-
-    RubyObjPtrTy = PointerType::getUnqual(RubyObjTy);
-    RubyObjPtrPtrTy = PointerType::getUnqual(RubyObjPtrTy);
-    nilVal = ConstantInt::get(RubyObjTy, Qnil);
-    trueVal = ConstantInt::get(RubyObjTy, Qtrue);
-    falseVal = ConstantInt::get(RubyObjTy, Qfalse);
-    undefVal = ConstantInt::get(RubyObjTy, Qundef);
-    splatArgFollowsVal = ConstantInt::get(RubyObjTy, SPLAT_ARG_FOLLOWS);
-    PtrTy = PointerType::getUnqual(Int8Ty);
-    PtrPtrTy = PointerType::getUnqual(PtrTy);
-    Int32PtrTy = PointerType::getUnqual(Int32Ty);
-    BitTy = Type::getInt1Ty(context);
-
-    BlockLiteralTy = module->getTypeByName("struct.ruby_block_literal");
-    assert(BlockLiteralTy != NULL);
-
-#if ROXOR_COMPILER_DEBUG
-    level = 0;
-#endif
-
-#if LLVM_TOT
-    dbg_mdkind = context.getMDKindID("dbg");
-    assert(dbg_mdkind != 0);
-#else
-    dbg_mdkind = LLVMContext::MD_dbg;
-#endif
-}
-
-RoxorAOTCompiler::RoxorAOTCompiler(void)
-: RoxorCompiler(false)
-{
-    cObject_gvar = NULL;
-    cStandardError_gvar = NULL;
-}
-
-SEL
-RoxorCompiler::mid_to_sel(ID mid, int arity)
-{
-    SEL sel = rb_vm_id_to_sel(mid, arity);
-    if (rb_objc_ignored_sel(sel)) {
-	char buf[100];
-	snprintf(buf, sizeof buf, "__hidden__%s", rb_id2name(mid));
-	sel = sel_registerName(buf);
-    }
-    return sel;
-}
-
-Instruction *
-RoxorCompiler::compile_protected_call(Value *imp, Value **args_begin,
-	Value **args_end)
-{
-    if (rescue_invoke_bb == NULL) {
-	return CallInst::Create(imp, args_begin, args_end, "", bb);
-    }
-    else {
-	BasicBlock *normal_bb = BasicBlock::Create(context, "normal",
-		bb->getParent());
-	InvokeInst *dispatch = InvokeInst::Create(imp, normal_bb,
-		rescue_invoke_bb, args_begin, args_end, "", bb);
-	bb = normal_bb;
-	return dispatch;
-    }
-}
-
-Instruction *
-RoxorCompiler::compile_protected_call(Value *imp, std::vector<Value *> &params)
-{
-    if (rescue_invoke_bb == NULL) {
-	return CallInst::Create(imp, params.begin(), params.end(), "", bb);
-    }
-    else {
-	BasicBlock *normal_bb = BasicBlock::Create(context, "normal",
-		bb->getParent());
-	InvokeInst *dispatch = InvokeInst::Create(imp, normal_bb,
-		rescue_invoke_bb, params.begin(), params.end(), "", bb);
-	bb = normal_bb;
-	return dispatch;
-    }
-}
-
-void
-RoxorCompiler::compile_single_when_argument(NODE *arg, Value *comparedToVal,
-	BasicBlock *thenBB)
-{
-    Value *subnodeVal = compile_node(arg);
-    Value *condVal;
-    if (comparedToVal != NULL) {
-	std::vector<Value *> params;
-	params.push_back(current_self);
-	params.push_back(subnodeVal);
-	params.push_back(compile_sel(selEqq));
-	params.push_back(compile_const_pointer(NULL));
-	params.push_back(ConstantInt::get(Int8Ty, 0));
-	params.push_back(ConstantInt::get(Int32Ty, 1));
-	params.push_back(comparedToVal);
-
-	condVal = compile_optimized_dispatch_call(selEqq, 1, params);
-	if (condVal == NULL) {
-	    condVal = compile_dispatch_call(params);
-	}
-    }
-    else {
-	condVal = subnodeVal;
-    }
-
-    Function *f = bb->getParent();
-    BasicBlock *nextTestBB = BasicBlock::Create(context, "next_test", f);
-
-    compile_boolean_test(condVal, thenBB, nextTestBB);
-
-    bb = nextTestBB;
-}
-
-void
-RoxorCompiler::compile_boolean_test(Value *condVal, BasicBlock *ifTrueBB,
-	BasicBlock *ifFalseBB)
-{
-    Function *f = bb->getParent();
-    BasicBlock *notFalseBB = BasicBlock::Create(context, "not_false", f);
-
-    Value *notFalseCond = new ICmpInst(*bb, ICmpInst::ICMP_NE, condVal,
-	    falseVal);
-    BranchInst::Create(notFalseBB, ifFalseBB, notFalseCond, bb);
-    Value *notNilCond = new ICmpInst(*notFalseBB, ICmpInst::ICMP_NE, condVal,
-	    nilVal);
-    BranchInst::Create(ifTrueBB, ifFalseBB, notNilCond, notFalseBB);
-}
-
-void
-RoxorCompiler::compile_when_arguments(NODE *args, Value *comparedToVal,
-	BasicBlock *thenBB)
-{
-    switch (nd_type(args)) {
-	case NODE_ARRAY:
-	    while (args != NULL) {
-		compile_single_when_argument(args->nd_head, comparedToVal,
-			thenBB);
-		args = args->nd_next;
-	    }
-	    break;
-
-	case NODE_SPLAT:
-	    {
-		Value *condVal = compile_when_splat(comparedToVal,
-			compile_node(args->nd_head));
-
-		BasicBlock *nextTestBB = BasicBlock::Create(context,
-			"next_test", bb->getParent());
-		compile_boolean_test(condVal, thenBB, nextTestBB);
-
-		bb = nextTestBB;
-	    }
-	    break;
-
-	case NODE_ARGSPUSH:
-	case NODE_ARGSCAT:
-	    compile_when_arguments(args->nd_head, comparedToVal, thenBB);
-	    compile_single_when_argument(args->nd_body, comparedToVal, thenBB);
-	    break;
-
-	default:
-	    compile_node_error("unrecognized when arg node", args);
-    }
-}
-
-Function::ArgumentListType::iterator
-RoxorCompiler::compile_optional_arguments(
-	Function::ArgumentListType::iterator iter, NODE *node)
-{
-    assert(nd_type(node) == NODE_OPT_ARG);
-
-    do {
-	assert(node->nd_value != NULL);
-
-	Value *isUndefInst = new ICmpInst(*bb, ICmpInst::ICMP_EQ, iter,
-		undefVal);
-
-	Function *f = bb->getParent();
-	BasicBlock *arg_undef = BasicBlock::Create(context, "arg_undef", f);
-	BasicBlock *next_bb = BasicBlock::Create(context, "", f);
-
-	BranchInst::Create(arg_undef, next_bb, isUndefInst, bb);
-
-	bb = arg_undef;
-	compile_node(node->nd_value);
-	BranchInst::Create(next_bb, bb);
-
-	bb = next_bb;
-	++iter;
-    }
-    while ((node = node->nd_next) != NULL);
-
-    return iter;
-}
-
-void
-RoxorCompiler::compile_dispatch_arguments(NODE *args,
-	std::vector<Value *> &arguments, int *pargc)
-{
-    int argc = 0;
-
-    switch (nd_type(args)) {
-	case NODE_ARRAY:
-	    for (NODE *n = args; n != NULL; n = n->nd_next) {
-		arguments.push_back(compile_node(n->nd_head));
-		argc++;
-	    }
-	    break;
-
-	case NODE_SPLAT:
-	    assert(args->nd_head != NULL);
-	    arguments.push_back(splatArgFollowsVal);
-	    arguments.push_back(compile_node(args->nd_head));
-	    argc++;
-	    break;
-
-	case NODE_ARGSCAT:
-	    assert(args->nd_head != NULL);
-	    compile_dispatch_arguments(args->nd_head, arguments, &argc);
-	    assert(args->nd_body != NULL);
-	    arguments.push_back(splatArgFollowsVal);
-	    arguments.push_back(compile_node(args->nd_body));
-	    argc++;
-	    break;
-
-	case NODE_ARGSPUSH:
-	    assert(args->nd_head != NULL);
-	    compile_dispatch_arguments(args->nd_head, arguments, &argc);
-	    assert(args->nd_body != NULL);
-	    arguments.push_back(compile_node(args->nd_body));
-	    argc++;
-	    break;
-
-	default:
-	    compile_node_error("unrecognized dispatch arg node", args);
-    }
-    *pargc = argc;
-}
-
-Value *
-RoxorCompiler::compile_when_splat(Value *comparedToVal, Value *splatVal)
-{
-    if (comparedToVal == NULL) {
-	return splatVal;
-    }
-    GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(selEqq, true);
-    Value *args[] = {
-	new LoadInst(is_redefined, "", bb),
-	comparedToVal,
-	splatVal
-    };
-    return compile_protected_call(whenSplatFunc, args, args + 3);
-}
-
-Instruction *
-RoxorCompiler::compile_const_global_ustring(const UniChar *str,
-	const size_t len)
-{
-    assert(len > 0);
-
-    const unsigned long hash = rb_str_hash_uchars(str, len);
-
-    std::map<CFHashCode, GlobalVariable *>::iterator iter =
-	static_ustrings.find(hash);
-
-    GlobalVariable *gvar;
-    if (iter == static_ustrings.end()) {
-	const ArrayType *str_type = ArrayType::get(Int16Ty, len);
-
-	std::vector<Constant *> ary_elements;
-	for (unsigned int i = 0; i < len; i++) {
-	    ary_elements.push_back(ConstantInt::get(Int16Ty, str[i]));
-	}
-
-	gvar = new GlobalVariable(*RoxorCompiler::module, str_type, true,
-		GlobalValue::InternalLinkage,
-		ConstantArray::get(str_type, ary_elements), "");
-
-	static_ustrings[hash] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-
-    Value *idxs[] = {
-	ConstantInt::get(Int32Ty, 0),
-	ConstantInt::get(Int32Ty, 0)
-    };
-    return GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb);
-}
-
-Instruction *
-RoxorCompiler::compile_const_global_string(const char *str,
-	const size_t len)
-{
-    assert(len > 0);
-
-    std::string s(str, len);
-    std::map<std::string, GlobalVariable *>::iterator iter =
-	static_strings.find(s);
-
-    GlobalVariable *gvar;
-    if (iter == static_strings.end()) {
-	const ArrayType *str_type = ArrayType::get(Int8Ty, len + 1);
-
-	std::vector<Constant *> ary_elements;
-	for (unsigned int i = 0; i < len; i++) {
-	    ary_elements.push_back(ConstantInt::get(Int8Ty, str[i]));
-	}
-	ary_elements.push_back(ConstantInt::get(Int8Ty, 0));
-	
-	gvar = new GlobalVariable(*RoxorCompiler::module, str_type, true,
-		GlobalValue::InternalLinkage,
-		ConstantArray::get(str_type, ary_elements), "");
-
-	static_strings[s] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-
-    Value *idxs[] = {
-	ConstantInt::get(Int32Ty, 0),
-	ConstantInt::get(Int32Ty, 0)
-    };
-    return GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_ccache(ID name)
-{
-    struct ccache *cache = GET_CORE()->constant_cache_get(name);
-    return compile_const_pointer(cache);
-}
-
-Value *
-RoxorAOTCompiler::compile_ccache(ID name)
-{
-    std::map<ID, GlobalVariable *>::iterator iter =
-	ccaches.find(name);
-    GlobalVariable *gvar;
-    if (iter == ccaches.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module, PtrTy, false,
-		GlobalValue::InternalLinkage, Constant::getNullValue(PtrTy),
-		"");
-	assert(gvar != NULL);
-	ccaches[name] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-    return new LoadInst(gvar, "", bb);
-}
-
-static void
-discover_stubs(std::map<SEL, std::vector<std::string> *> &map,
-	std::vector<std::string> &dest, SEL sel)
-{
-    std::map<SEL, std::vector<std::string> *>::iterator iter;
-    iter = map.find(sel);
-    if (iter != map.end()) {
-	std::vector<std::string> *v = iter->second;
-	for (std::vector<std::string>::iterator i = v->begin();
-		i != v->end(); ++i) {
-	    std::string s = *i;
-	    if (std::find(dest.begin(), dest.end(), s) == dest.end()) {
-		dest.push_back(s);
-	    }		
-	}
-    }
-}
-
-Value *
-RoxorAOTCompiler::compile_sel(SEL sel, bool add_to_bb)
-{
-    std::map<SEL, GlobalVariable *>::iterator iter = sels.find(sel);
-    GlobalVariable *gvar;
-    if (iter == sels.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module, PtrTy, false,
-		GlobalValue::InternalLinkage, Constant::getNullValue(PtrTy),
-		"");
-	assert(gvar != NULL);
-	sels[sel] = gvar;
-
-	discover_stubs(bs_c_stubs_types, c_stubs, sel);
-	discover_stubs(bs_objc_stubs_types, objc_stubs, sel);
-    }
-    else {
-	gvar = iter->second;
-    }
-    return add_to_bb
-	? new LoadInst(gvar, "", bb)
-	: new LoadInst(gvar, "");
-}
-
-Value *
-RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
-{
-    uint64_t v;
-    assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
-    memcpy(&v, &arity, sizeof(rb_vm_arity_t));
-    return ConstantInt::get(Int64Ty, v);
-}
-
-void
-RoxorCompiler::compile_method_definition(NODE *node)
-{
-    ID mid = node->nd_mid;
-    assert(mid > 0);
-
-    NODE *body = node->nd_defn;
-    assert(body != NULL);
-
-    const bool singleton_method = nd_type(node) == NODE_DEFS;
-
-    const ID old_current_mid = current_mid;
-    current_mid = mid;
-    const bool old_current_block_chain = current_block_chain;
-    current_block_chain = false;
-    const bool old_block_declaration = block_declaration;
-    block_declaration = false;
-    const bool old_should_interpret = should_interpret;
-
-    DEBUG_LEVEL_INC();
-    Value *val = compile_node(body);
-    assert(Function::classof(val));
-    Function *func = cast<Function>(val);
-    DEBUG_LEVEL_DEC();
-
-    should_interpret = old_should_interpret;
-    block_declaration = old_block_declaration;
-    current_block_chain = old_current_block_chain;
-    current_mid = old_current_mid;
-
-    Value *classVal;
-    if (singleton_method) {
-	assert(node->nd_recv != NULL);
-	classVal = compile_singleton_class(compile_node(node->nd_recv));
-    }
-    else {
-	classVal = compile_current_class();
-    }
-
-    rb_vm_arity_t arity = rb_vm_node_arity(body);
-    const SEL sel = mid_to_sel(mid, arity.real);
-
-    compile_prepare_method(classVal, compile_sel(sel), singleton_method,
-	    func, arity, body);
-
-    can_interpret = true;
-}
-
-void
-RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
-	bool singleton, Function *new_function, rb_vm_arity_t &arity,
-	NODE *body)
-{
-    if (prepareMethodFunc == NULL) {
-	// void rb_vm_prepare_method(Class klass, unsigned char dynamic_class,
-	//	SEL sel, Function *func, rb_vm_arity_t arity, int flags)
-	prepareMethodFunc = 
-	    cast<Function>(module->getOrInsertFunction(
-			"rb_vm_prepare_method",
-			VoidTy, RubyObjTy, Int8Ty, PtrTy, PtrTy, Int64Ty,
-			Int32Ty, NULL));
-    }
-
-    Value *args[] = {
-	classVal,
-	ConstantInt::get(Int8Ty, !singleton && dynamic_class ? 1 : 0),
-	sel,
-	compile_const_pointer(new_function),
-	compile_arity(arity),
-	ConstantInt::get(Int32Ty, rb_vm_node_flags(body))
-    }; 
-    CallInst::Create(prepareMethodFunc, args, args + 6, "", bb);
-}
-
-void
-RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
-	bool singleton, Function *func, rb_vm_arity_t &arity, NODE *body)
-{
-    if (prepareMethodFunc == NULL) {
-	// void rb_vm_prepare_method2(Class klass, unsigned char dynamic_class,
-	//	SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags, ...)
-	std::vector<const Type *> types;
-	types.push_back(RubyObjTy);
-	types.push_back(Int8Ty);
-	types.push_back(PtrTy);
-	types.push_back(PtrTy);
-	types.push_back(Int64Ty);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(VoidTy, types, true);
-	prepareMethodFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_prepare_method2", ft));
-    }
-
-    const unsigned char dyn_class = !singleton && dynamic_class ? 1 : 0;
-
-    std::vector<Value *> params;
-    params.push_back(classVal);
-    params.push_back(ConstantInt::get(Int8Ty, dyn_class));
-    params.push_back(sel);
-    params.push_back(new BitCastInst(func, PtrTy, "", bb));
-    params.push_back(compile_arity(arity));
-    params.push_back(ConstantInt::get(Int32Ty, rb_vm_node_flags(body)));
-
-    // Pre-compile a generic Objective-C stub, where all arguments and return
-    // value are Ruby types.
-    char types[100];
-    types[0] = '@';
-    types[1] = '@';
-    types[2] = ':';
-    assert(arity.real < (int)sizeof(types) - 3);
-    for (int i = 0; i < arity.real; i++) {
-	types[3 + i] = '@';
-    }
-    types[arity.real + 3] = '\0';
-    params.push_back(compile_const_global_string(types));
-    Function *stub = compile_objc_stub(func, NULL, arity, types);
-    params.push_back(new BitCastInst(stub, PtrTy, "", bb));
-    params.push_back(compile_const_pointer(NULL));
-
-    CallInst::Create(prepareMethodFunc, params.begin(), params.end(), "", bb);
-}
-
-void
-RoxorCompiler::attach_current_line_metadata(Instruction *insn)
-{
-    if (fname != NULL) {
-#if !defined(LLVM_TOT)
-	Value *args[] = {
-	    ConstantInt::get(Int32Ty, current_line),
-	    ConstantInt::get(Int32Ty, 0),
-	    debug_compile_unit,
-	    DILocation(NULL) 
-	};
-	DILocation loc = DILocation(MDNode::get(context, args, 4));
-#else
-	DILocation loc = debug_info->CreateLocation(current_line, 0,
-		debug_compile_unit, DILocation(NULL));
-#endif
-	insn->setMetadata(dbg_mdkind, loc);
-    }
-}
-
-void
-RoxorCompiler::generate_location_path(std::string &path, DILocation loc)
-{
-    if (loc.getFilename() == "-e") {
-	path.append(loc.getFilename());
-    }
-    else {
-	path.append(loc.getDirectory());
-	path.append("/");
-	path.append(loc.getFilename());
-    }
-}
-
-Value *
-RoxorCompiler::recompile_dispatch_argv(std::vector<Value *> &params, int offset)
-{
-    const long argc = params.size() - offset;
-
-    if (argc == 0) {
-	return compile_const_pointer(NULL, RubyObjPtrTy);
-    }
-
-    assert(argc > 0);
-
-    Instruction *first = bb->getParent()->getEntryBlock().getFirstNonPHI();
-    if (dispatch_argv == NULL) {
-	dispatch_argv = new AllocaInst(RubyObjTy,
-		ConstantInt::get(Int32Ty, argc), "argv", first);
-    }
-    else {
-	Value *size = dispatch_argv->getArraySize();
-	if (argc > cast<ConstantInt>(size)->getSExtValue()) {
-	    AllocaInst *new_argv = new AllocaInst(RubyObjTy,
-		    ConstantInt::get(Int32Ty, argc), "argv", first);
-	    dispatch_argv->replaceAllUsesWith(new_argv);
-	    dispatch_argv->eraseFromParent();
-	    dispatch_argv = new_argv;
-	}
-    }
-
-    for (int i = 0; i < argc; i++) {
-	Value *idx = ConstantInt::get(Int32Ty, i);
-	Value *slot = GetElementPtrInst::Create(dispatch_argv, idx, "", bb);
-	new StoreInst(params[offset + i], slot, bb);
-    }
-
-    return dispatch_argv;
-}
-
-Value *
-RoxorCompiler::compile_dispatch_call(std::vector<Value *> &params)
-{
-    Value *argv = recompile_dispatch_argv(params, 6);
-    params.erase(params.begin() + 6, params.end());
-    params.push_back(argv);
-
-    Instruction *insn = compile_protected_call(dispatchFunc, params);
-    attach_current_line_metadata(insn);
-    return insn;
-}
-
-Value *
-RoxorCompiler::compile_attribute_assign(NODE *node, Value *extra_val)
-{
-    Value *recv = node->nd_recv == (NODE *)1
-	? current_self
-	: compile_node(node->nd_recv);
-
-    ID mid = node->nd_mid;
-    assert(mid > 0);
-
-    std::vector<Value *> args;
-    NODE *n = node->nd_args;
-    int argc = 0;
-    if (n != NULL) {
-	compile_dispatch_arguments(n, args, &argc);
-    }
-    if (extra_val != NULL) {
-	args.push_back(extra_val);
-	argc++;
-    }
-
-    if (mid != idASET) {
-	// A regular attribute assignment (obj.foo = 42)
-	assert(argc == 1);
-    }
-
-    std::vector<Value *> params;
-    const SEL sel = mid_to_sel(mid, argc);
-    params.push_back(current_self);
-    params.push_back(recv);
-    params.push_back(compile_sel(sel));
-    params.push_back(compile_const_pointer(NULL));
-    unsigned char opt = 0;
-    if (recv == current_self) {
-	opt = DISPATCH_FCALL;
-    }
-    if (argc < (int)args.size()) {
-	opt |= DISPATCH_SPLAT;
-    }
-    params.push_back(ConstantInt::get(Int8Ty, opt));
-    params.push_back(ConstantInt::get(Int32Ty, argc));
-    for (std::vector<Value *>::iterator i = args.begin();
-	 i != args.end();
-	 ++i) {
-	params.push_back(*i);
-    }
-
-    // The return value of these assignments is always the new value.
-    Value *retval = params.back();
-
-    if (compile_optimized_dispatch_call(sel, argc, params) == NULL) {
-	compile_dispatch_call(params);
-    }
-    return retval;
-}
-
-void
-RoxorCompiler::compile_multiple_assignment_element(NODE *node, Value *val)
-{
-    switch (nd_type(node)) {
-	case NODE_LASGN:
-	case NODE_DASGN:
-	case NODE_DASGN_CURR:
-	    new StoreInst(val, compile_lvar_slot(node->nd_vid), bb);
-	    break;
-
-	case NODE_IASGN:
-	case NODE_IASGN2:
-	    compile_ivar_assignment(node->nd_vid, val);
-	    break;
-
-	case NODE_CVASGN:
-	    compile_cvar_assignment(node->nd_vid, val);
-	    break;
-
-	case NODE_GASGN:
-	    compile_gvar_assignment(node, val);
-	    break;
-
-	case NODE_ATTRASGN:
-	    compile_attribute_assign(node, val);
-	    break;
-
-	case NODE_MASGN:
-	    compile_multiple_assignment(node, val);
-	    break;
-
-	case NODE_CDECL:
-	    compile_constant_declaration(node, val);
-	    break;
-
-	default:
-	    compile_node_error("unimplemented MASGN subnode",
-			       node);
-    }
-}
-
-Value *
-RoxorCompiler::compile_multiple_assignment(NODE *node, Value *val)
-{
-    assert(nd_type(node) == NODE_MASGN);
-
-    NODE *before_splat = node->nd_head, *after_splat = NULL, *splat = NULL;
-
-    assert((before_splat == NULL) || (nd_type(before_splat) == NODE_ARRAY));
-
-    // if the splat has no name (a, *, b = 1, 2, 3), its node value is -1
-    if ((node->nd_next == (NODE *)-1) || (node->nd_next == NULL)
-	    || (nd_type(node->nd_next) != NODE_POSTARG)) {
-	splat = node->nd_next;
-    }
-    else {
-	NODE *post_arg = node->nd_next;
-	splat = post_arg->nd_1st;
-	after_splat = post_arg->nd_2nd;
-    }
-
-    assert((after_splat == NULL) || (nd_type(after_splat) == NODE_ARRAY));
-
-    int before_splat_count = 0, after_splat_count = 0;
-    for (NODE *l = before_splat; l != NULL; l = l->nd_next) {
-	++before_splat_count;
-    }
-    for (NODE *l = after_splat; l != NULL; l = l->nd_next) {
-	++after_splat_count;
-    }
-
-    val = CallInst::Create(toAryFunc, val, "", bb);
-
-    NODE *l = before_splat;
-    for (int i = 0; l != NULL; ++i) {
-	Value *args[] = {
-	    val,
-	    ConstantInt::get(Int32Ty, i)
-	};
-	Value *elt = CallInst::Create(masgnGetElemBeforeSplatFunc,
-		args, args + 2, "", bb);
-
-	compile_multiple_assignment_element(l->nd_head, elt);
-
-	l = l->nd_next;
-    }
-
-    if (splat != NULL && splat != (NODE *)-1) {
-	Value *args[] = {
-	    val,
-	    ConstantInt::get(Int32Ty, before_splat_count),
-	    ConstantInt::get(Int32Ty, after_splat_count)
-	};
-	Value *elt = CallInst::Create(masgnGetSplatFunc, args, args + 3,
-		"", bb);
-
-	compile_multiple_assignment_element(splat, elt);
-    }
-
-    l = after_splat;
-    for (int i = 0; l != NULL; ++i) {
-	Value *args[] = {
-	    val,
-	    ConstantInt::get(Int32Ty, before_splat_count),
-	    ConstantInt::get(Int32Ty, after_splat_count),
-	    ConstantInt::get(Int32Ty, i)
-	};
-	Value *elt = CallInst::Create(masgnGetElemAfterSplatFunc,
-		args, args + 4, "", bb);
-
-	compile_multiple_assignment_element(l->nd_head, elt);
-
-	l = l->nd_next;
-    }
-
-    return val;
-}
-
-Value *
-RoxorCompiler::compile_multiple_assignment(NODE *node)
-{
-    assert(node->nd_value != NULL);
-
-    if (node->nd_next == NULL
-	    && node->nd_head != NULL
-	    && nd_type(node->nd_head) == NODE_ARRAY
-	    && nd_type(node->nd_value) == NODE_ARRAY
-	    && node->nd_head->nd_alen == node->nd_value->nd_alen) {
-
-	// Symetric multiple-assignment optimization.
-	// Grab all left operands in separate Allocas.
-	Instruction *first = bb->getParent()->getEntryBlock().getFirstNonPHI();
-	std::vector<Value *> tmp_rights;
-	NODE *right = node->nd_value;
-	for (int i = 0; i < node->nd_head->nd_alen; i++) {
-	    Value *slot = new AllocaInst(RubyObjTy, "", first);
-	    assert(right->nd_head != NULL);
-	    new StoreInst(compile_node(right->nd_head), slot, bb);
-	    tmp_rights.push_back(new LoadInst(slot, "", bb));
-	    right = right->nd_next;
-	}
-
-	// Compile assignments.
-	NODE *left = node->nd_head;
-	for (std::vector<Value *>::iterator i = tmp_rights.begin();
-		i != tmp_rights.end(); ++i) {
-	    assert(left->nd_head != NULL);
-	    compile_multiple_assignment_element(left->nd_head, *i);
-	    left = left->nd_next;
-	}
-
-	// Compile return value (a new Array) which is eliminated later if
-	// never used.
-	CallInst *ary = CallInst::Create(newArrayFunc,
-		ConstantInt::get(Int32Ty, tmp_rights.size()), "", bb);
-	RoxorCompiler::MAsgnValue val;
-	val.ary = ary;
-	for (unsigned int i = 0; i < tmp_rights.size(); i++) {
-	    Value *args[] = {
-		ary,
-		ConstantInt::get(Int32Ty, i),
-		tmp_rights[i]
-	    };
-	    CallInst *insn = CallInst::Create(asetArrayFunc, args, args + 3,
-		    "", bb);
-	    val.sets.push_back(insn);
-	}
-	masgn_values.push_back(val);
-	return ary;
-    }
-    return compile_multiple_assignment(node, compile_node(node->nd_value));
-}
-
-Value *
-RoxorCompiler::compile_prepare_block_args(Function *func, int *flags)
-{
-    return compile_const_pointer(func);    
-}
-
-Value *
-RoxorAOTCompiler::compile_prepare_block_args(Function *func, int *flags)
-{
-    *flags |= VM_BLOCK_AOT;
-    return new BitCastInst(func, PtrTy, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_block_get(Value *block_object)
-{
-    Value *args[] = { block_object };
-    return compile_protected_call(getBlockFunc, args, args + 1);
-}
-
-Value *
-RoxorCompiler::compile_prepare_block(void)
-{
-    assert(current_block_func != NULL && current_block_node != NULL);
-
-    if (prepareBlockFunc == NULL) {
-	// void *rb_vm_prepare_block(Function *func, int flags, VALUE self,
-	//	rb_vm_arity_t arity,
-	//	rb_vm_var_uses **parent_var_uses,
-	//	rb_vm_block_t *parent_block,
-	//	int dvars_size, ...);
-	std::vector<const Type *> types;
-	types.push_back(PtrTy);
-	types.push_back(Int32Ty);
-	types.push_back(RubyObjTy);
-	types.push_back(Int64Ty);
-	types.push_back(PtrPtrTy);
-	types.push_back(PtrTy);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(PtrTy, types, true);
-	prepareBlockFunc = cast<Function>
-	    (module->getOrInsertFunction("rb_vm_prepare_block", ft));
-    }
-
-    std::vector<Value *> params;
-    int flags = 0;
-    params.push_back(compile_prepare_block_args(current_block_func, &flags));
-    if (nd_type(current_block_node) == NODE_SCOPE
-	    && current_block_node->nd_body == NULL) {
-	flags |= VM_BLOCK_EMPTY;
-    }
-    params.push_back(ConstantInt::get(Int32Ty, flags));
-    params.push_back(current_self);
-    rb_vm_arity_t arity = rb_vm_node_arity(current_block_node);
-    params.push_back(compile_arity(arity));
-    params.push_back(current_var_uses == NULL
-	    ? compile_const_pointer_to_pointer(NULL) : current_var_uses);
-    params.push_back(running_block == NULL
-	    ? compile_const_pointer(NULL) : running_block);
-
-    // Dvars.
-    params.push_back(ConstantInt::get(Int32Ty, (int)dvars.size()));
-    for (std::vector<ID>::iterator iter = dvars.begin();
-	 iter != dvars.end(); ++iter) {
-	params.push_back(compile_lvar_slot(*iter));
-    }
-
-    // Lvars.
-    params.push_back(ConstantInt::get(Int32Ty, (int)lvars.size()));
-    for (std::map<ID, Value *>::iterator iter = lvars.begin();
-	 iter != lvars.end(); ++iter) {
-	ID name = iter->first;
-	Value *slot = iter->second;
-	params.push_back(compile_id((long)name));
-	params.push_back(slot);
-    }
-
-    return CallInst::Create(prepareBlockFunc, params.begin(), params.end(),
-	    "", bb);
-}
-
-Value *
-RoxorCompiler::compile_block(NODE *node)
-{
-    std::vector<ID> old_dvars = dvars;
-
-    BasicBlock *old_current_loop_begin_bb = current_loop_begin_bb;
-    BasicBlock *old_current_loop_body_bb = current_loop_body_bb;
-    BasicBlock *old_current_loop_end_bb = current_loop_end_bb;
-    current_loop_begin_bb = current_loop_end_bb = NULL;
-    Function *old_current_block_func = current_block_func;
-    NODE *old_current_block_node = current_block_node;
-    bool old_current_block = current_block;
-    bool old_current_block_chain = current_block_chain;
-    int old_return_from_block = return_from_block;
-    bool old_dynamic_class = dynamic_class;
-    bool old_block_declaration = block_declaration;
-
-    current_block = true;
-    current_block_chain = true;
-    dynamic_class = true;
-    block_declaration = true;
-
-    assert(node->nd_body != NULL);
-    Value *block = compile_node(node->nd_body);	
-    assert(Function::classof(block));
-
-    block_declaration = old_block_declaration;
-    dynamic_class = old_dynamic_class;
-
-    BasicBlock *return_from_block_bb = NULL;
-    if (!old_current_block_chain && return_from_block != -1) {
-	// The block we just compiled contains one or more return expressions!
-	// We need to enclose further dispatcher calls inside an exception
-	// handler, since return-from-block may use a C++ exception.
-	Function *f = bb->getParent();
-	rescue_invoke_bb = return_from_block_bb =
-	    BasicBlock::Create(context, "return-from-block", f);
-    }
-
-    current_loop_begin_bb = old_current_loop_begin_bb;
-    current_loop_body_bb = old_current_loop_body_bb;
-    current_loop_end_bb = old_current_loop_end_bb;
-    current_block = old_current_block;
-    current_block_chain = old_current_block_chain;
-
-    current_block_func = cast<Function>(block);
-    current_block_node = node->nd_body;
-
-    const int node_type = nd_type(node);
-    const bool is_lambda = node_type == NODE_LAMBDA;
-    Value *caller;
-
-    if (!is_lambda) {
-	assert(node->nd_iter != NULL);
-    }
-
-    if (node_type == NODE_ITER) {
-	caller = compile_node(node->nd_iter);
-    }
-    else {
-	// Dispatch #each on the receiver.
-	std::vector<Value *> params;
-
-	params.push_back(current_self);
-
-	if (!is_lambda) {
-	    // The block must not be passed to the code that generates the
-	    // values we loop on.
-	    current_block_func = NULL;
-	    current_block_node = NULL;
-	    params.push_back(compile_node(node->nd_iter));
-	    current_block_func = cast<Function>(block);
-	    current_block_node = node->nd_body;
-	}
-	else {
-	    params.push_back(current_self);
-	}
-
-	params.push_back(compile_sel((is_lambda ? selLambda : selEach)));
-	params.push_back(compile_prepare_block());
-	int opt = 0;
-	if (is_lambda) {
-	    opt = DISPATCH_FCALL;
-	}
-	params.push_back(ConstantInt::get(Int8Ty, opt));
-	params.push_back(ConstantInt::get(Int32Ty, 0));
-
-	caller = compile_dispatch_call(params);
-    }
-
-    const int block_id = return_from_block_bb != NULL
-	? return_from_block : -1;
-
-    Value *retval_block = CallInst::Create(returnedFromBlockFunc,
-	    ConstantInt::get(Int32Ty, block_id), "", bb);
-
-    Value *is_returned = new ICmpInst(*bb, ICmpInst::ICMP_NE, retval_block,
-	    undefVal);
-
-    Function *f = bb->getParent();
-    BasicBlock *return_bb = BasicBlock::Create(context, "", f);
-    BasicBlock *next_bb = BasicBlock::Create(context, "", f);
-
-    BranchInst::Create(return_bb, next_bb, is_returned, bb);
-
-    bb = return_bb;
-    ReturnInst::Create(context, retval_block, bb);
-
-    bb = next_bb;
-
-    if (return_from_block_bb != NULL) {
-	BasicBlock *old_bb = bb;
-	bb = return_from_block_bb;
-	compile_return_from_block_handler(return_from_block);
-	bb = old_bb;
-	return_from_block = old_return_from_block;
-    }
-
-    current_block_func = old_current_block_func;
-    current_block_node = old_current_block_node;
-    dvars = old_dvars;
-
-    return caller;
-}
-
-Value *
-RoxorCompiler::compile_binding(void)
-{
-    if (pushBindingFunc == NULL) {
-	// void rb_vm_push_binding(VALUE self, rb_vm_block_t *current_block,
-	// 	rb_vm_binding_t *top_binding, rb_vm_var_uses **parent_var_uses,
-	//	int lvars_size, ...);
-	std::vector<const Type *> types;
-	types.push_back(RubyObjTy);
-	types.push_back(PtrTy);
-	types.push_back(PtrTy);
-	types.push_back(PtrPtrTy);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(VoidTy, types, true);
-	pushBindingFunc = cast<Function>
-	    (module->getOrInsertFunction("rb_vm_push_binding", ft));
-    }
-
-    std::vector<Value *> params;
-    params.push_back(current_self);
-    params.push_back(running_block == NULL
-	    ? compile_const_pointer(NULL) : running_block);
-    params.push_back(compile_const_pointer(rb_vm_current_binding()));
-    if (current_var_uses == NULL) {
-	// there is no local variables in this scope
-	params.push_back(compile_const_pointer_to_pointer(NULL));
-    }
-    else {
-	params.push_back(current_var_uses);
-    }
-
-    // Lvars.
-    params.push_back(ConstantInt::get(Int32Ty, (int)lvars.size()));
-    for (std::map<ID, Value *>::iterator iter = lvars.begin();
-	 iter != lvars.end(); ++iter) {
-
-	ID lvar = iter->first;
-	params.push_back(compile_id(lvar));
-	params.push_back(iter->second);
-    }
-
-    return CallInst::Create(pushBindingFunc, params.begin(), params.end(),
-	    "", bb);
-}
-
-Value *
-RoxorCompiler::compile_slot_cache(ID id)
-{
-    std::map<ID, void *>::iterator iter = ivars_slots_cache.find(id);
-    void *cache = NULL;
-    if (iter == ivars_slots_cache.end()) {
-	cache = rb_vm_ivar_slot_allocate();
-	ivars_slots_cache[id] = cache;
-    }
-    else {
-	cache = iter->second;
-    }
-    return compile_const_pointer(cache);
-}
-
-Value *
-RoxorAOTCompiler::compile_slot_cache(ID id)
-{
-    std::map<ID, void *>::iterator iter = ivars_slots_cache.find(id);
-    GlobalVariable *gvar = NULL;
-    if (iter == ivars_slots_cache.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module,
-		PtrTy, false, GlobalValue::InternalLinkage,
-		compile_const_pointer(NULL), "");
-	ivar_slots.push_back(gvar);
-	ivars_slots_cache[id] = gvar;
-    }
-    else {
-	gvar = (GlobalVariable *)iter->second;
-    }
-    return new LoadInst(gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_ivar_get(ID vid)
-{
-    Value *args[] = {
-	current_self,
-	compile_id(vid),
-	compile_slot_cache(vid)
-    };
-    return CallInst::Create(getIvarFunc, args, args + 3, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_ivar_assignment(ID vid, Value *val)
-{
-    Value *args[] = {
-	current_self,
-	compile_id(vid),
-	val,
-	compile_slot_cache(vid)
-    };
-    CallInst::Create(setIvarFunc, args, args + 4, "", bb);
-
-    return val;
-}
-
-Value *
-RoxorCompiler::compile_cvar_get(ID id, bool check)
-{
-    Value *args[] = {
-	compile_current_class(),
-	compile_id(id),
-	ConstantInt::get(Int8Ty, check ? 1 : 0),
-	ConstantInt::get(Int8Ty, dynamic_class ? 1 : 0)
-    };
-    return compile_protected_call(cvarGetFunc, args, args + 4);
-}
-
-Value *
-RoxorCompiler::compile_cvar_assignment(ID name, Value *val)
-{
-    Value *args[] = {
-	compile_current_class(),
-	compile_id(name),
-	val,
-	ConstantInt::get(Int8Ty, dynamic_class ? 1 : 0)
-    };
-    return CallInst::Create(cvarSetFunc, args, args + 4, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_gvar_assignment(NODE *node, Value *val)
-{
-    assert(node->nd_vid > 0);
-    assert(node->nd_entry != NULL);
-
-    if (gvarSetFunc == NULL) {
-	// VALUE rb_gvar_set(struct global_entry *entry, VALUE val);
-	gvarSetFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_gvar_set",
-		    RubyObjTy, PtrTy, RubyObjTy, NULL));
-    }
-
-    Value *args[] = {
-	compile_global_entry(node),
-	val
-    };
-    return compile_protected_call(gvarSetFunc, args, args + 2);
-}
-
-Value *
-RoxorCompiler::compile_gvar_get(NODE *node)
-{
-    assert(node->nd_vid > 0);
-    assert(node->nd_entry != NULL);
-
-    if (gvarGetFunc == NULL) {
-	// VALUE rb_gvar_get(struct global_entry *entry);
-	gvarGetFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_gvar_get", RubyObjTy, PtrTy, NULL));
-    }
-
-    return CallInst::Create(gvarGetFunc, compile_global_entry(node),
-	    "", bb);
-}
-
-Value *
-RoxorCompiler::compile_constant_declaration(NODE *node, Value *val)
-{
-    int flags = 0;
-
-    Value *args[4];
-
-    if (node->nd_vid > 0) {
-	args[0] = compile_current_class();
-	args[1] = compile_id(node->nd_vid);
-    }
-    else {
-	assert(node->nd_else != NULL);
-	args[0] = compile_class_path(node->nd_else, &flags, NULL);
-	assert(node->nd_else->nd_mid > 0);
-	args[1] = compile_id(node->nd_else->nd_mid);
-    }
-    args[2] = val;
-    args[3] = ConstantInt::get(Int8Ty,
-	    dynamic_class && (flags & DEFINE_OUTER) ? 1 : 0);
-
-    CallInst::Create(setConstFunc, args, args + 4, "", bb);
-
-    return val;
-}
-
-Value *
-RoxorCompiler::compile_current_class(void)
-{
-    if (current_opened_class == NULL) {
-	VALUE current_class = (VALUE)GET_VM()->get_current_class();
-	return current_class == 0
-	    ? compile_nsobject() : compile_literal(current_class);
-    }
-    return new LoadInst(current_opened_class, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_nsobject(void)
-{
-    return ConstantInt::get(RubyObjTy, rb_cObject);
-}
-
-Value *
-RoxorAOTCompiler::compile_nsobject(void)
-{
-    if (cObject_gvar == NULL) {
-	cObject_gvar = new GlobalVariable(*RoxorCompiler::module, RubyObjTy,
-		false, GlobalValue::InternalLinkage, zeroVal, "NSObject");
-	class_gvars.push_back(cObject_gvar);
-    }
-    return new LoadInst(cObject_gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_standarderror(void)
-{
-    return ConstantInt::get(RubyObjTy, rb_eStandardError);
-}
-
-Value *
-RoxorAOTCompiler::compile_standarderror(void)
-{
-    if (cStandardError_gvar == NULL) {
-	cStandardError_gvar = new GlobalVariable(*RoxorCompiler::module,
-		RubyObjTy, false, GlobalValue::InternalLinkage, zeroVal,
-		"StandardError");
-	class_gvars.push_back(cStandardError_gvar);
-    }
-    return new LoadInst(cStandardError_gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_id(ID id)
-{
-    return ConstantInt::get(IntTy, (long)id);
-}
-
-Value *
-RoxorAOTCompiler::compile_id(ID id)
-{
-    std::map<ID, GlobalVariable *>::iterator iter = ids.find(id);
-
-    GlobalVariable *gvar;
-    if (iter == ids.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module, IntTy, false,
-		GlobalValue::InternalLinkage, ConstantInt::get(IntTy, 0), "");
-	ids[id] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-
-    return new LoadInst(gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_const(ID id, Value *outer)
-{
-    bool outer_given = true;
-    if (outer == NULL) {
-	outer = compile_current_class();
-	outer_given = false;
-    }
-
-    int flags = 0;
-    if (!outer_given) {
-	flags |= CONST_LOOKUP_LEXICAL;
-    }
-    if (dynamic_class) {
-	flags |= CONST_LOOKUP_DYNAMIC_CLASS;
-    }
-
-    Value *args[] = {
-	outer,
-	ConstantInt::get(Int64Ty, outer_mask),
-	compile_ccache(id),
-	compile_id(id),
-	ConstantInt::get(Int32Ty, flags)
-    };
-    Instruction *insn = compile_protected_call(getConstFunc, args, args + 5);
-    attach_current_line_metadata(insn);
-    return insn;
-}
-
-Value *
-RoxorCompiler::compile_singleton_class(Value *obj)
-{
-    if (singletonClassFunc == NULL) {
-	// VALUE rb_singleton_class(VALUE klass);
-	singletonClassFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_singleton_class",
-		    RubyObjTy, RubyObjTy, NULL));
-    }
-
-    Value *args[] = { obj };
-    return compile_protected_call(singletonClassFunc, args, args + 1);
-}
-
-Value *
-RoxorCompiler::compile_defined_expression(NODE *node)
-{
-    // Easy cases first.
-    VALUE str = 0;
-    switch (nd_type(node)) {
-	case NODE_NIL:
-	    str = (VALUE)CFSTR("nil");
-	    break;
-
-	case NODE_SELF:
-	    str = (VALUE)CFSTR("self");
-	    break;
-
-	case NODE_TRUE:
-	    str = (VALUE)CFSTR("true");
-	    break;
-
-	case NODE_FALSE:
-	    str = (VALUE)CFSTR("false");
-	    break;
-
-	case NODE_ARRAY:
-	case NODE_ZARRAY:
-	case NODE_STR:
-	case NODE_LIT:
-	    str = (VALUE)CFSTR("expression");
-	    break;
-
-	case NODE_LVAR:
-	case NODE_DVAR:
-	    str = (VALUE)CFSTR("local-variable");
-	    break;
-
-	case NODE_OP_ASGN1:
-	case NODE_OP_ASGN2:
-	case NODE_OP_ASGN_OR:
-	case NODE_OP_ASGN_AND:
-	case NODE_MASGN:
-	case NODE_LASGN:
-	case NODE_DASGN:
-	case NODE_DASGN_CURR:
-	case NODE_GASGN:
-	case NODE_IASGN:
-	case NODE_CDECL:
-	case NODE_CVDECL:
-	case NODE_CVASGN:
-	    str = (VALUE)CFSTR("assignment");
-	    break;
-    }
-    if (str != 0) {
-	return ConstantInt::get(RubyObjTy, (long)str);
-    }
-
-    // Now the less easy ones... let's set up an exception handler first
-    // because we might need to evalute things that will result in an
-    // exception.
-    Function *f = bb->getParent(); 
-    BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-    BasicBlock *new_rescue_invoke_bb = BasicBlock::Create(context, "rescue", f);
-    BasicBlock *merge_bb = BasicBlock::Create(context, "merge", f);
-    rescue_invoke_bb = new_rescue_invoke_bb;
-
-    // Prepare arguments for the runtime.
-    Value *self = current_self;
-    Value *what1 = NULL;
-    Value *what2 = NULL;
-    int type = 0;
-    bool expression = false;
-
-    switch (nd_type(node)) {
-	case NODE_IVAR:
-	    type = DEFINED_IVAR;
-	    what1 = compile_id(node->nd_vid);
-	    break;
-
-	case NODE_GVAR:
-	    type = DEFINED_GVAR;
-	    // TODO AOT compiler
-	    what1 = ConstantInt::get(RubyObjTy, (VALUE)node->nd_entry);
-	    break;
-
-	case NODE_CVAR:
-	    type = DEFINED_CVAR;
-	    what1 = compile_id(node->nd_vid);
-	    break;
-
-	case NODE_CONST:
-	    type = DEFINED_LCONST;
-	    what1 = compile_id(node->nd_vid);
-	    what2 = compile_current_class();
-	    break;
-
-	case NODE_SUPER:
-	case NODE_ZSUPER:
-	    type = DEFINED_SUPER;
-	    what1 = compile_id(current_mid);
-	    break;
-
-	case NODE_COLON2:
-	case NODE_COLON3:
-	    what2 = nd_type(node) == NODE_COLON2
-		? compile_node(node->nd_head)
-		: compile_nsobject();
-	    if (rb_is_const_id(node->nd_mid)) {
-		type = DEFINED_CONST;
-		what1 = compile_id(node->nd_mid);
-	    }
-	    else {
-		type = DEFINED_METHOD;
-		what1 = compile_id(node->nd_mid);
-	    }
-	    break;
-
-      case NODE_CALL:
-      case NODE_VCALL:
-      case NODE_FCALL:
-      case NODE_ATTRASGN:
-	    if (nd_type(node) == NODE_CALL
-		|| (nd_type(node) == NODE_ATTRASGN
-		    && node->nd_recv != (NODE *)1)) {
-		self = compile_node(node->nd_recv);
-	    }
-	    type = DEFINED_METHOD;
-	    what1 = compile_id(node->nd_mid);
-	    break;
-
-	default:
-	    // Unhandled node type, probably an expression. Let's compile
-	    // it and it case everything goes okay we just return 'expression'.
-	    compile_node(node);
-	    expression = true;
-	    break;
-    }
-
-    if (definedFunc == NULL) {
-	// VALUE rb_vm_defined(VALUE self, int type, VALUE what, VALUE what2);
-	definedFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_defined",
-		    RubyObjTy, RubyObjTy, Int32Ty, RubyObjTy, RubyObjTy,
-		    NULL));
-    }
-
-    Value *val = NULL;
-    if (!expression) {
-	// Call the runtime.
-	Value *args[] = {
-	    self,
-	    ConstantInt::get(Int32Ty, type),
-	    what1 == NULL ? nilVal : what1,
-	    what2 == NULL ? nilVal : what2
-	};
-	val = compile_protected_call(definedFunc, args, args + 4);
-    }
-    else {
-	val = ConstantInt::get(RubyObjTy, (long)CFSTR("expression"));
-    }
-    BasicBlock *normal_bb = bb;
-    BranchInst::Create(merge_bb, bb);
-
-    // The rescue block - here we simply do nothing.
-    bb = new_rescue_invoke_bb;
-    compile_landing_pad_header();
-    compile_landing_pad_footer();
-    BranchInst::Create(merge_bb, bb);
-
-    // Now merging.
-    bb = merge_bb;
-    PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-    pn->addIncoming(val, normal_bb);
-    pn->addIncoming(nilVal, new_rescue_invoke_bb);
-
-    rescue_invoke_bb = old_rescue_invoke_bb;
-
-    return pn;
-}
-
-Value *
-RoxorCompiler::compile_dstr(NODE *node)
-{
-    std::vector<Value *> params;
-
-    if (node->nd_lit != 0) {
-	params.push_back(compile_literal(node->nd_lit));
-    }
-
-    NODE *n = node->nd_next;
-    assert(n != NULL);
-    while (n != NULL) {
-	params.push_back(compile_node(n->nd_head));
-	n = n->nd_next;
-    }
-
-    const int count = params.size();
-
-    params.insert(params.begin(), ConstantInt::get(Int32Ty, count));
-
-    if (newStringFunc == NULL) {
-	// VALUE rb_str_new_fast(int argc, ...)
-	std::vector<const Type *> types;
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
-	newStringFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_str_new_fast", ft));
-    }
-
-    return CallInst::Create(newStringFunc, params.begin(), params.end(), "",
-	    bb);
-}
-
-Value *
-RoxorCompiler::compile_dvar_slot(ID name)
-{
-    // TODO we should cache this
-    int i = 0, idx = -1;
-    for (std::vector<ID>::iterator iter = dvars.begin();
-	 iter != dvars.end(); ++iter) {
-	if (*iter == name) {
-	    idx = i;
-	    break;
-	}
-	i++;
-    }
-    if (idx == -1) {
-	return NULL;
-    }
-
-    Function::ArgumentListType::iterator fargs_i =
-	bb->getParent()->getArgumentList().begin();
-    ++fargs_i; // skip self
-    ++fargs_i; // skip sel
-    Value *dvars_ary = fargs_i;
-
-    Value *index = ConstantInt::get(Int32Ty, idx);
-    Value *slot = GetElementPtrInst::Create(dvars_ary, index, rb_id2name(name),
-	    bb);
-    return new LoadInst(slot, "", bb);
-}
-
-void
-RoxorCompiler::compile_break_val(Value *val)
-{
-    if (breakFunc == NULL) {
-	// void rb_vm_break(VALUE val);
-	breakFunc = cast<Function>(
-		module->getOrInsertFunction("rb_vm_break", 
-		    VoidTy, RubyObjTy, NULL));
-    }
-
-    CallInst::Create(breakFunc, val, "", bb);
-}
-
-void
-RoxorCompiler::compile_return_from_block(Value *val, int id)
-{
-    if (returnFromBlockFunc == NULL) {
-	// void rb_vm_return_from_block(VALUE val, int id,
-	//	rb_vm_block_t *current_block);
-	returnFromBlockFunc = cast<Function>(
-		module->getOrInsertFunction("rb_vm_return_from_block", 
-		    VoidTy, RubyObjTy, Int32Ty, PtrTy, NULL));
-    }
-
-    Value *args[] = {
-	val,
-	ConstantInt::get(Int32Ty, id),
-	running_block
-    };
-    compile_protected_call(returnFromBlockFunc, args, args + 3);
-}
-
-void
-RoxorCompiler::compile_return_from_block_handler(int id)
-{
-    Value *exception = compile_landing_pad_header();
-
-    if (checkReturnFromBlockFunc == NULL) {
-	// VALUE rb_vm_check_return_from_block_exc(void *exc, int id);
-	checkReturnFromBlockFunc = cast<Function>(
-		module->getOrInsertFunction(
-		    "rb_vm_check_return_from_block_exc", 
-		    RubyObjTy, PtrTy, Int32Ty, NULL));
-    }
-
-    Value *args[] = {
-	exception,
-	ConstantInt::get(Int32Ty, id)
-    };
-    Value *val = CallInst::Create(checkReturnFromBlockFunc, args, args + 2,
-	    "", bb);
-
-    Function *f = bb->getParent();
-    BasicBlock *ret_bb = BasicBlock::Create(context, "ret", f);
-    BasicBlock *rethrow_bb  = BasicBlock::Create(context, "rethrow", f);
-    Value *need_ret = new ICmpInst(*bb, ICmpInst::ICMP_NE, val,
-	    ConstantInt::get(RubyObjTy, Qundef));
-    BranchInst::Create(ret_bb, rethrow_bb, need_ret, bb);
-
-    bb = ret_bb;
-    compile_landing_pad_footer(false);
-    ReturnInst::Create(context, val, bb);	
-
-    bb = rethrow_bb;
-    compile_rethrow_exception();
-}
-
-Value *
-RoxorCompiler::compile_jump(NODE *node)
-{
-    const bool within_loop = current_loop_begin_bb != NULL
-	&& current_loop_body_bb != NULL
-	&& current_loop_end_bb != NULL;
-
-    const bool within_block = block_declaration;
-
-    Value *val = nd_type(node) == NODE_RETRY
-	? nilVal
-	: node->nd_head != NULL
-	    ? compile_node(node->nd_head) : nilVal;
-
-    switch (nd_type(node)) {
-	case NODE_RETRY:
-	    // Simply jump to the nearest begin label, after poping the
-	    // current exception.
-	    compile_pop_exception();
-	    if (begin_bb == NULL) {
-		rb_raise(rb_eSyntaxError, "unexpected retry");
-	    }
-	    // TODO raise a SyntaxError if called outside of a "rescue"
-	    // block.
-	    BranchInst::Create(begin_bb, bb);
-	    break;
-
-	case NODE_BREAK:
-	    if (current_rescue) {
-		compile_landing_pad_footer();
-	    }
-	    if (within_loop) {
-		BranchInst::Create(current_loop_end_bb, bb);
-		current_loop_exit_val->addIncoming(val, bb);
-	    }
-	    else if (within_block) {
-		compile_break_val(val);
-		ReturnInst::Create(context, val, bb);
-	    }
-	    else {
-		rb_raise(rb_eLocalJumpError, "unexpected break");
-	    }
-	    break;
-
-	case NODE_NEXT:
-	    if (current_rescue) {
-		compile_landing_pad_footer();
-	    }
-	    if (within_loop) {
-		if (ensure_node != NULL) {
-		    compile_node(ensure_node);
-		}
-		BranchInst::Create(current_loop_begin_bb, bb);
-	    }
-	    else if (within_block) {
-		compile_simple_return(val);
-	    }
-	    else {
-		rb_raise(rb_eLocalJumpError, "unexpected next");
-	    }
-	    break;
-
-	case NODE_REDO:
-	    if (current_rescue) {
-		compile_landing_pad_footer();
-	    }
-	    if (within_loop) {
-		BranchInst::Create(current_loop_body_bb, bb);
-	    }
-	    else if (within_block) {
-		assert(entry_bb != NULL);
-		BranchInst::Create(entry_bb, bb);
-	    }
-	    else {
-		rb_raise(rb_eLocalJumpError, "unexpected redo");
-	    }
-	    break;
-
-	case NODE_RETURN:
-	    if (current_rescue) {
-		compile_pop_exception();
-	    }
-	    if (within_block) {
-		if (return_from_block == -1) {
-		    return_from_block = return_from_block_ids++;
-		}
-		compile_return_from_block(val, return_from_block);
-		ReturnInst::Create(context, val, bb);
-	    }
-	    else {
-		compile_simple_return(val);
-	    }
-	    break;
-    }
-
-    // To not complicate the compiler even more, let's be very lazy here and
-    // continue on a dead branch. Hopefully LLVM is smart enough to eliminate
-    // it at compilation time.
-    bb = BasicBlock::Create(context, "DEAD", bb->getParent());
-
-    return val;
-}
-
-void
-RoxorCompiler::compile_simple_return(Value *val)
-{
-    if (ensure_bb != NULL) {
-	BranchInst::Create(ensure_bb, bb);
-	ensure_pn->addIncoming(val, bb);
-    }
-    else {
-	ReturnInst::Create(context, val, bb);
-    }
-}
-
-Value *
-RoxorCompiler::compile_set_has_ensure(Value *val)
-{
-    if (setHasEnsureFunc == NULL) {
-	setHasEnsureFunc = cast<Function>(
-		module->getOrInsertFunction(
-		    "rb_vm_set_has_ensure", Int8Ty, Int8Ty, NULL));
-    }
-
-    return CallInst::Create(setHasEnsureFunc, val, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_class_path(NODE *node, int *flags, int *outer_level)
-{
-    if (nd_type(node) == NODE_COLON3) {
-	// ::Foo
-	if (flags != NULL) {
-	    *flags = 0;
-	}
-	if (outer_level != NULL) {
-	    *outer_level = 0;
-	}
-	return compile_nsobject();
-    }
-    else if (node->nd_head != NULL) {
-	// Bar::Foo
-	if (flags != NULL) {
-	    *flags = DEFINE_SUB_OUTER;
-	}
-	if (outer_level != NULL) {
-	    // Count the number of outers.
-	    int level = 0;
-	    NODE *n = node;
-	    while (n != NULL && nd_type(n) == NODE_COLON2) {
-		n = n->nd_head;
-		level++;
-	    }
-	    *outer_level = level;
-	}
-	return compile_node(node->nd_head);
-    }
-    else {
-	if (flags != NULL) {
-	    *flags = DEFINE_OUTER;
-	}
-	if (outer_level != NULL) {
-	    *outer_level = 0;
-	}
-	return compile_current_class();
-    }
-}
-
-Value *
-RoxorCompiler::compile_landing_pad_header(void)
-{
-    Function *eh_exception_f = Intrinsic::getDeclaration(module,
-	    Intrinsic::eh_exception);
-    Value *eh_ptr = CallInst::Create(eh_exception_f, "", bb);
-
-    Function *eh_selector_f = Intrinsic::getDeclaration(module,
-	    Intrinsic::eh_selector);
-
-    std::vector<Value *> params;
-    params.push_back(eh_ptr);
-    Function *__gxx_personality_v0_func = NULL;
-    if (__gxx_personality_v0_func == NULL) {
-	__gxx_personality_v0_func = cast<Function>(
-		module->getOrInsertFunction("__gxx_personality_v0",
-		    PtrTy, NULL));
-    }
-    params.push_back(ConstantExpr::getBitCast(__gxx_personality_v0_func, PtrTy));
-
-    // catch (...)
-    params.push_back(compile_const_pointer(NULL));
-
-    CallInst::Create(eh_selector_f, params.begin(), params.end(), "", bb);
-
-    Function *beginCatchFunc = NULL;
-    if (beginCatchFunc == NULL) {
-	// void *__cxa_begin_catch(void *);
-	beginCatchFunc = cast<Function>(
-		module->getOrInsertFunction("__cxa_begin_catch",
-		    PtrTy, PtrTy, NULL));
-    }
-    params.clear();
-    params.push_back(eh_ptr);
-    return CallInst::Create(beginCatchFunc, params.begin(), params.end(),
-	    "", bb);
-}
-
-void
-RoxorCompiler::compile_pop_exception(int pos)
-{
-    if (popExceptionFunc == NULL) {
-	// void rb_vm_pop_exception(int pos);
-	popExceptionFunc = cast<Function>(
-		module->getOrInsertFunction("rb_vm_pop_exception", 
-		    VoidTy, Int32Ty, NULL));
-    }
-
-    CallInst::Create(popExceptionFunc, ConstantInt::get(Int32Ty, pos), "", bb);
-}
-
-void
-RoxorCompiler::compile_landing_pad_footer(bool pop_exception)
-{
-    if (pop_exception) {
-	compile_pop_exception();
-    }
-
-    Function *endCatchFunc = NULL;
-    if (endCatchFunc == NULL) {
-	// void __cxa_end_catch(void);
-	endCatchFunc = cast<Function>(
-		module->getOrInsertFunction("__cxa_end_catch",
-		    VoidTy, NULL));
-    }
-    CallInst::Create(endCatchFunc, "", bb);
-}
-
-void
-RoxorCompiler::compile_rethrow_exception(void)
-{
-    if (rescue_rethrow_bb == NULL) {
-	Function *rethrowFunc = NULL;
-	if (rethrowFunc == NULL) {
-	    // void __cxa_rethrow(void);
-	    rethrowFunc = cast<Function>(
-		    module->getOrInsertFunction("__cxa_rethrow", VoidTy, NULL));
-	}
-	CallInst::Create(rethrowFunc, "", bb);
-	new UnreachableInst(context, bb);
-    }
-    else {
-	BranchInst::Create(rescue_rethrow_bb, bb);
-    }
-}
-
-Value *
-RoxorCompiler::compile_current_exception(void)
-{
-    if (currentExceptionFunc == NULL) {
-	// VALUE rb_vm_current_exception(void);
-	currentExceptionFunc = cast<Function>(
-		module->getOrInsertFunction(
-		    "rb_vm_current_exception", 
-		    RubyObjTy, NULL));
-    }
-    return CallInst::Create(currentExceptionFunc, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
-	std::vector<Value *> &params)
-{
-    // The not operator (!).
-    if (sel == selNot) {
-	
-	if (current_block_func != NULL || argc != 0) {
-	    return NULL;
-	}
-	
-	Value *val = params[1]; // self
-
-	Function *f = bb->getParent();
-
-	BasicBlock *falseBB = BasicBlock::Create(context, "", f);
-	BasicBlock *trueBB = BasicBlock::Create(context, "", f);
-	BasicBlock *mergeBB = BasicBlock::Create(context, "", f);
-
-	compile_boolean_test(val, trueBB, falseBB);
-
-	BranchInst::Create(mergeBB, falseBB);
-	BranchInst::Create(mergeBB, trueBB);
-
-	bb = mergeBB;	
-
-	PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-	pn->addIncoming(trueVal, falseBB);
-	pn->addIncoming(falseVal, trueBB);
-
-	return pn;
-    }
-    // Pure arithmetic operations.
-    else if (sel == selPLUS || sel == selMINUS || sel == selDIV 
-	     || sel == selMULT || sel == selLT || sel == selLE 
-	     || sel == selGT || sel == selGE || sel == selEq
-	     || sel == selNeq || sel == selEqq) {
-
-	if (current_block_func != NULL || argc != 1) {
-	    return NULL;
-	}
-
-	Value *leftVal = params[1]; // self
-	Value *rightVal = params.back();
-
-	Function *func = NULL;
-	if (sel == selPLUS) {
-	    func = fastPlusFunc;
-	}
-	else if (sel == selMINUS) {
-	    func = fastMinusFunc;
-	}
-	else if (sel == selDIV) {
-	    func = fastDivFunc;
-	}
-	else if (sel == selMULT) {
-	    func = fastMultFunc;
-	}
-	else if (sel == selLT) {
-	    func = fastLtFunc;
-	}
-	else if (sel == selLE) {
-	    func = fastLeFunc;
-	}
-	else if (sel == selGT) {
-	    func = fastGtFunc;
-	}
-	else if (sel == selGE) {
-	    func = fastGeFunc;
-	}
-	else if (sel == selEq) {
-	    func = fastEqFunc;
-	}
-	else if (sel == selNeq) {
-	    func = fastNeqFunc;
-	}
-	else if (sel == selEqq) {
-	    func = fastEqqFunc;
-	}
-	assert(func != NULL);
-
-	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
-
-	Value *args[] = {
-	    leftVal,
-	    rightVal,
-	    new LoadInst(is_redefined, "", bb)
-	};
-	return compile_protected_call(func, args, args + 3);
-    }
-    // Other operators (#<< or #[] or #[]=)
-    else if (sel == selLTLT || sel == selAREF || sel == selASET) {
-
-	const int expected_argc = sel == selASET ? 2 : 1;
-	if (current_block_func != NULL || argc != expected_argc) {
-	    return NULL;
-	}
-
-	if (params.size() - argc > 6) {
-	    // Looks like there is a splat argument there, we can't handle this
-	    // in the primitives.
-	    return NULL;
-	}
-
-	Function *func = NULL;
-	if (sel == selLTLT) {
-	    func = fastShiftFunc;
-	}
-	else if (sel == selAREF) {
-	    func = fastArefFunc;
-	}
-	else if (sel == selASET) {
-	    func = fastAsetFunc;
-	}
-	assert(func != NULL);
-
-	std::vector<Value *> new_params;
-	new_params.push_back(params[1]);		// self
-	if (argc == 1) {
-	    new_params.push_back(params.back());	// other
-	}
-	else {
-	    new_params.insert(new_params.end(), params.end() - 2, params.end());
-	}
-
-	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
-	new_params.push_back(new LoadInst(is_redefined, "", bb));
-
-	return compile_protected_call(func, new_params);
-    }
-    // #send or #__send__
-    else if (sel == selSend || sel == sel__send__) {
-
-	if (current_block_func != NULL || argc == 0) {
-	    return NULL;
-	}
-	Value *symVal = params[params.size() - argc];
-	if (!ConstantInt::classof(symVal)) {
-	    return NULL;
-	}
-	VALUE sym = cast<ConstantInt>(symVal)->getZExtValue();
-	if (!SYMBOL_P(sym)) {
-	    return NULL;
-	}
-	SEL new_sel = mid_to_sel(SYM2ID(sym), argc - 1);
-
-	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
-
-	Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-	Value *isOpRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-		is_redefined_val, ConstantInt::get(Int8Ty, 0));
-
-	Function *f = bb->getParent();
-
-	BasicBlock *thenBB = BasicBlock::Create(context, "op_not_redefined", f);
-	BasicBlock *elseBB = BasicBlock::Create(context, "op_dispatch", f);
-	BasicBlock *mergeBB = BasicBlock::Create(context, "op_merge", f);
-
-	BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
-
-	bb = thenBB;
-	std::vector<Value *> new_params;
-	// Compile a null top reference, to ignore protected visibility.
-	new_params.push_back(ConstantInt::get(RubyObjTy, 0));
-	new_params.push_back(params[1]);
-	new_params.push_back(compile_sel(new_sel));
-	new_params.push_back(params[3]);
-	new_params.push_back(ConstantInt::get(Int8Ty, DISPATCH_FCALL));
-	new_params.push_back(ConstantInt::get(Int32Ty, argc - 1));
-	for (int i = 0; i < argc - 1; i++) {
-	    new_params.push_back(params[7 + i]);
-	}
-	Value *thenVal = compile_dispatch_call(new_params);
-	thenBB = bb;
-	BranchInst::Create(mergeBB, thenBB);
-
-	bb = elseBB;
-	Value *elseVal = compile_dispatch_call(params);
-	elseBB = bb;
-	BranchInst::Create(mergeBB, elseBB);
-
-	bb = mergeBB;
-	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
-	pn->addIncoming(thenVal, thenBB);
-	pn->addIncoming(elseVal, elseBB);
-
-	return pn;
-    }
-    // __method__ or __callee__
-    else if (sel == sel__method__ || sel == sel__callee__) {
-
-	if (current_block_func != NULL || argc != 0) {
-	    return NULL;
-	}
-
-	Function *f = bb->getParent();
-	Function::arg_iterator arg = f->arg_begin();
-	arg++; // skip self
-	Value *callee_sel = arg;
-
-	if (selToSymFunc == NULL) {
-	    // VALUE rb_sel_to_sym(SEL sel);
-	    selToSymFunc = cast<Function>(
-		    module->getOrInsertFunction("rb_sel_to_sym",
-			RubyObjTy, PtrTy, NULL));
-	}
-	return CallInst::Create(selToSymFunc, callee_sel, "", bb);
-    }
-    return NULL;
-}
-
-Instruction *
-RoxorCompiler::compile_range(Value *beg, Value *end, bool exclude_end,
-	bool retain)
-{
-    if (newRangeFunc == NULL) {
-	// VALUE rb_range_new2(VALUE beg, VALUE end, int exclude_end,
-	//	int retain);
-	newRangeFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_range_new2",
-		    RubyObjTy, RubyObjTy, RubyObjTy, Int32Ty, Int32Ty,
-		    NULL));
-    }
-
-    Value *args[] = {
-	beg,
-	end,
-	ConstantInt::get(Int32Ty, exclude_end ? 1 : 0),
-	ConstantInt::get(Int32Ty, retain ? 1 : 0)
-    };
-    return compile_protected_call(newRangeFunc, args, args + 4);
-}
-
-Value *
-RoxorCompiler::compile_literal(VALUE val)
-{
-    if (TYPE(val) == T_STRING) {
-	// We must compile a new string creation because strings are
-	// mutable, we can't simply compile a reference to a master
-	// copy.
-	//
-	//	10.times { s = 'foo'; s << 'bar' }
-	//
-	if (rb_str_chars_len(val) == 0) {
-	    if (newString3Func == NULL) {	
-		newString3Func = cast<Function>(
-			module->getOrInsertFunction(
-			    "rb_str_new_empty", RubyObjTy, NULL));
-	    }
-	    return CallInst::Create(newString3Func, "", bb);
-	}
-	else {
-	    const char *cstr = RSTRING_PTR(val);
-	    const int cstr_len = RSTRING_LEN(val);
-
-	    assert(cstr_len > 0);
-
-	    if (newString2Func == NULL) {	
-		newString2Func = cast<Function>(
-			module->getOrInsertFunction(
-			    "rb_str_new",
-			    RubyObjTy, PtrTy, Int32Ty, NULL));
-	    }
-
-	    Value *args[] = {
-		compile_const_global_string(cstr, cstr_len),
-		ConstantInt::get(Int32Ty, cstr_len)
-	    };
-	    return CallInst::Create(newString2Func, args, args + 2, "", bb);
-	}
-    }
-
-    return compile_immutable_literal(val);
-}
-
-Value *
-RoxorCompiler::compile_immutable_literal(VALUE val)
-{
-    GC_RETAIN(val);
-    return ConstantInt::get(RubyObjTy, (long)val); 
-}
-
-Value *
-RoxorAOTCompiler::compile_immutable_literal(VALUE val)
-{
-    if (SPECIAL_CONST_P(val)) {
-	return RoxorCompiler::compile_immutable_literal(val);
-    }
-    if (rb_obj_is_kind_of(val, rb_cEncoding)) {
-	// This is the __ENCODING__ keyword.
-	// TODO: compile the real encoding...
-	return nilVal;
-    }
-
-    std::map<VALUE, GlobalVariable *>::iterator iter = literals.find(val);
-    GlobalVariable *gvar = NULL;
-
-    if (iter == literals.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module, RubyObjTy, false,
-		GlobalValue::InternalLinkage, nilVal, "");
-	literals[val] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-
-    return new LoadInst(gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_global_entry(NODE *node)
-{
-    return compile_const_pointer(node->nd_entry);
-}
-
-Value *
-RoxorAOTCompiler::compile_global_entry(NODE *node)
-{
-    const ID name = node->nd_vid;
-    assert(name > 0);
-    
-    std::map<ID, GlobalVariable *>::iterator iter = global_entries.find(name);
-    GlobalVariable *gvar = NULL;
-    if (iter == global_entries.end()) {
-	gvar = new GlobalVariable(*RoxorCompiler::module, PtrTy, false,
-		GlobalValue::InternalLinkage, Constant::getNullValue(PtrTy),
-		"");
-	global_entries[name] = gvar;
-    }
-    else {
-	gvar = iter->second;
-    }
-
-    return new LoadInst(gvar, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_set_current_class(Value *klass)
-{
-    if (setCurrentClassFunc == NULL) {
-	// Class rb_vm_set_current_class(Class klass)
-	setCurrentClassFunc = cast<Function>(
-		module->getOrInsertFunction("rb_vm_set_current_class",
-		    RubyObjTy, RubyObjTy, NULL));
-    }
-
-    return CallInst::Create(setCurrentClassFunc, klass, "", bb);
-}
-
-void
-RoxorCompiler::compile_set_current_scope(Value *klass, Value *scope)
-{
-    Value *args[] = {
-	klass,
-	scope
-    };
-    CallInst::Create(setScopeFunc, args, args + 2, "", bb);
-}
-
-void
-RoxorCompiler::compile_node_error(const char *msg, NODE *node)
-{
-    int t = nd_type(node);
-    printf("%s: %d (%s)", msg, t, ruby_node_name(t));
-    abort();
-}
-
-void
-RoxorCompiler::compile_keep_vars(BasicBlock *startBB, BasicBlock *mergeBB)
-{
-    if (keepVarsFunc == NULL) {
-	// void rb_vm_keep_vars(rb_vm_var_uses *uses, int lvars_size, ...)
-	std::vector<const Type *> types;
-	types.push_back(PtrTy);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(VoidTy, types, true);
-	keepVarsFunc = cast<Function>
-	    (module->getOrInsertFunction("rb_vm_keep_vars", ft));
-    }
-
-    BasicBlock *notNullBB = BasicBlock::Create(context, "not_null",
-	    startBB->getParent());
-
-    bb = startBB;
-    Value *usesVal = new LoadInst(current_var_uses, "", bb);
-    Value *notNullCond = new ICmpInst(*bb, ICmpInst::ICMP_NE, usesVal,
-	    compile_const_pointer(NULL));
-    // we only need to call keepVarsFunc if current_var_uses is not NULL
-    BranchInst::Create(notNullBB, mergeBB, notNullCond, bb);
-
-    bb = notNullBB;
-
-    // params must be filled each time because in AOT mode it contains
-    // instructions
-    std::vector<Value *> params;
-    params.push_back(new LoadInst(current_var_uses, "", bb));
-    params.push_back(NULL);
-    int vars_count = 0;
-    for (std::map<ID, Value *>::iterator iter = lvars.begin();
-	    iter != lvars.end(); ++iter) {
-	ID name = iter->first;
-	Value *slot = iter->second;
-	if (std::find(dvars.begin(), dvars.end(), name) == dvars.end()) {
-	    Value *id_val = compile_id(name);
-	    params.push_back(id_val);
-	    params.push_back(slot);
-	    vars_count++;
-	}
-    }
-    params[1] = ConstantInt::get(Int32Ty, vars_count);
-
-    CallInst::Create(keepVarsFunc, params.begin(), params.end(), "", bb);
-
-    BranchInst::Create(mergeBB, bb);
-}
-
-bool
-RoxorCompiler::should_inline_function(Function *f)
-{
-    return f->getName().startswith("vm_");
-}
-
-void
-RoxorCompiler::inline_function_calls(Function *f)
-{
-    std::vector<CallInst *> insns;
-
-    for (Function::iterator fi = f->begin(); fi != f->end(); ++fi) {
-	for (BasicBlock::iterator bi = fi->begin(); bi != fi->end(); ++bi) {
-	    CallInst *insn = dyn_cast<CallInst>(bi);
-	    if (insn != NULL) {
-		Function *called = insn->getCalledFunction();
-		if (called != NULL && should_inline_function(called)) {
-		    insns.push_back(insn);
-		}
-	    }
-	}
-    }
-
-    InlineFunctionInfo IFI;
-    for (std::vector<CallInst *>::iterator i = insns.begin();
-	    i != insns.end(); ++i) {
-	InlineFunction(*i, IFI);
-    }
-}
-
-Function *
-RoxorCompiler::compile_scope(NODE *node)
-{
-    rb_vm_arity_t arity = rb_vm_node_arity(node);
-    const int nargs = bb == NULL ? 0 : arity.real;
-    const bool has_dvars = block_declaration;
-
-    // Get dynamic vars.
-    if (has_dvars && node->nd_tbl != NULL) {
-	const int args_count = (int)node->nd_tbl[0];
-	const int lvar_count = (int)node->nd_tbl[args_count + 1];
-	for (int i = 0; i < lvar_count; i++) {
-	    ID id = node->nd_tbl[i + args_count + 2];
-	    if (lvars.find(id) != lvars.end()) {
-		std::vector<ID>::iterator iter = std::find(dvars.begin(),
-			dvars.end(), id);
-		if (iter == dvars.end()) {
-#if ROXOR_COMPILER_DEBUG
-		    printf("dvar %s\n", rb_id2name(id));
-#endif
-		    dvars.push_back(id);
-		}
-	    }
-	}
-    }
-
-    // Create function type.
-    std::vector<const Type *> types;
-    types.push_back(RubyObjTy);	// self
-    types.push_back(PtrTy);	// sel
-    if (has_dvars) {
-	types.push_back(RubyObjPtrPtrTy); // dvars array
-	types.push_back(PtrTy); // rb_vm_block_t of the currently running block
-    }
-    for (int i = 0; i < nargs; ++i) {
-	types.push_back(RubyObjTy);
-    }
-    FunctionType *ft = FunctionType::get(RubyObjTy, types, false);
-
-    Function *f = Function::Create(ft, GlobalValue::InternalLinkage,
-	    "ruby_scope", module);
-
-    NODE *old_ensure_node = ensure_node;
-    BasicBlock *old_ensure_bb = ensure_bb;
-    ensure_node = NULL;
-    ensure_bb = NULL;
-
-    AllocaInst *old_dispatch_argv = dispatch_argv;
-    BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-    BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
-    BasicBlock *old_entry_bb = entry_bb;
-    BasicBlock *old_bb = bb;
-    BasicBlock *new_rescue_invoke_bb = NULL;
-    BasicBlock *new_rescue_rethrow_bb = NULL;
-    dispatch_argv = NULL;
-    rescue_invoke_bb = NULL;
-    rescue_rethrow_bb = NULL;
-    bb = BasicBlock::Create(context, "MainBlock", f);
-
-    DISubprogram old_debug_subprogram = debug_subprogram;
-#if 0
-    // This is not the right way to emit subprogram DWARF entries,
-    // llc emits some assembly that doesn't compile because some
-    // symbols are duplicated.
-    debug_subprogram = debug_info->CreateSubprogram(
-	    debug_compile_unit, f->getName(), f->getName(),
-	    f->getName(), debug_compile_unit, nd_line(node),
-	    DIType(), f->hasInternalLinkage(), true);
-    debug_info->InsertSubprogramStart(debug_subprogram, bb);
-#endif
-
-    std::map<ID, Value *> old_lvars = lvars;
-    lvars.clear();
-    std::vector<MAsgnValue> old_masgn_values = masgn_values;
-    masgn_values.clear();
-
-    Value *old_self = current_self;
-
-    Function::arg_iterator arg;
-
-    arg = f->arg_begin();
-    Value *self = arg++;
-    self->setName("self");
-    current_self = self;
-
-    Value *sel = arg++;
-    sel->setName("sel");
-
-    Value *old_running_block = running_block;
-    Value *old_current_var_uses = current_var_uses;
-    current_var_uses = NULL;
-
-    if (has_dvars) {
-	Value *dvars_arg = arg++;
-	dvars_arg->setName("dvars");
-	running_block = arg++;
-	running_block->setName("running_block");
-    }
-    else {
-	running_block = NULL;
-    }
-
-    Value *old_current_block_arg = current_block_arg;
-    current_block_arg = NULL;
-    if (node->nd_tbl != NULL) {
-	bool has_vars_to_save = false;
-	int i, args_count = (int)node->nd_tbl[0];
-	assert(args_count == nargs
-		|| args_count == nargs + 1 /* optional block */
-		|| args_count == nargs - 1 /* unnamed param (|x,|) */);
-	for (i = 0; i < args_count; i++) {
-	    ID id = node->nd_tbl[i + 1];
-#if ROXOR_COMPILER_DEBUG
-	    printf("arg %s\n", rb_id2name(id));
-#endif
-
-	    Value *val = NULL;
-	    if (i < nargs) {
-		val = arg++;
-		val->setName(rb_id2name(id));
-	    }
-	    else {
-		// Optional block.
-		if (currentBlockObjectFunc == NULL) {
-		    // VALUE rb_vm_current_block_object(void);
-		    currentBlockObjectFunc = cast<Function>(
-			    module->getOrInsertFunction(
-				"rb_vm_current_block_object", RubyObjTy, NULL));
-		}
-		val = CallInst::Create(currentBlockObjectFunc, "", bb);
-		current_block_arg = val;
-	    }
-	    Value *slot = new AllocaInst(RubyObjTy, "", bb);
-	    new StoreInst(val, slot, bb);
-	    lvars[id] = slot;
-	    has_vars_to_save = true;
-	}
-
-	// Local vars must be created before the optional arguments
-	// because they can be used in them, for instance with def f(a=b=c=1).
-	if (compile_lvars(&node->nd_tbl[args_count + 1])) {
-	    has_vars_to_save = true;
-	}
-
-	if (has_vars_to_save) {
-	    current_var_uses = new AllocaInst(PtrTy, "", bb);
-	    new StoreInst(compile_const_pointer(NULL),
-		    current_var_uses, bb);
-
-	    new_rescue_invoke_bb = BasicBlock::Create(context,
-		    "rescue_save_vars", f);
-	    new_rescue_rethrow_bb = BasicBlock::Create(context,
-		    "rescue_save_vars.rethrow", f);
-	    rescue_invoke_bb = new_rescue_invoke_bb;
-	    rescue_rethrow_bb = new_rescue_rethrow_bb;
-	}
-
-	NODE *args_node = node->nd_args;
-	if (args_node != NULL) {
-	    // Compile multiple assignment arguments (def f((a, b, v))).
-	    // This must also be done after the creation of local variables.
-	    NODE *rest_node = args_node->nd_next;
-	    if (rest_node != NULL) {
-		NODE *right_req_node = rest_node->nd_next;
-		if (right_req_node != NULL) {
-		    NODE *last_node = right_req_node->nd_next;
-		    if (last_node != NULL) {
-			assert(nd_type(last_node) == NODE_AND);
-			// Multiple assignment for the left-side required
-			// arguments.
-			if (last_node->nd_1st != NULL) {
-			    compile_node(last_node->nd_1st);
-			}
-			// Multiple assignment for the right-side required
-			// arguments.
-			if (last_node->nd_2nd != NULL) {
-			    compile_node(last_node->nd_2nd);
-			}
-		    }
-		}
-	    }
-
-	    // Compile optional arguments.
-	    Function::ArgumentListType::iterator iter = f->arg_begin();
-	    ++iter; // skip self
-	    ++iter; // skip sel
-	    NODE *opt_node = args_node->nd_opt;
-	    if (opt_node != NULL) {
-		int to_skip = args_node->nd_frml;
-		if (has_dvars) {
-		    to_skip += 2; // dvars array and currently running block
-		}
-		for (i = 0; i < to_skip; i++) {
-		    ++iter; // skip dvars and args required on the left-side
-		}
-		iter = compile_optional_arguments(iter, opt_node);
-	    }
-	}
-    }
-
-    Value *val = NULL;
-    if (node->nd_body != NULL) {
-	entry_bb = BasicBlock::Create(context, "entry_point", f); 
-	BranchInst::Create(entry_bb, bb);
-	bb = entry_bb;
-
-	rb_vm_arity_t old_current_arity = current_arity;
-	Function *old_current_non_block_func = current_non_block_func;
-	if (!block_declaration) {
-	    current_non_block_func = f;
-	    current_arity = arity;
-	}
-
-	DEBUG_LEVEL_INC();
-	val = compile_node(node->nd_body);
-	DEBUG_LEVEL_DEC();
-
-	current_non_block_func = old_current_non_block_func;
-	current_arity = old_current_arity;
-    }
-    if (val == NULL) {
-	val = nilVal;
-    }
-
-    ReturnInst::Create(context, val, bb);
-
-    // The rethrows after the save of variables must be real rethrows.
-    rescue_rethrow_bb = NULL;
-    rescue_invoke_bb = NULL;
-
-    // Current_lvar_uses has 2 uses or more if it is really used.
-    // (there is always a StoreInst in which we assign it NULL)
-    if (current_var_uses != NULL && current_var_uses->hasNUsesOrMore(2)) {
-	// Searches all ReturnInst in the function we just created and add
-	// before a call to the function to save the local variables if
-	// necessary (we can't do this before finishing compiling the whole
-	// function because we can't be sure if the function contains a block
-	// or not before).
-	std::vector<ReturnInst *> to_fix;
-	for (Function::iterator block_it = f->begin();
-		block_it != f->end();
-		++block_it) {
-	    for (BasicBlock::iterator inst_it = block_it->begin();
-		    inst_it != block_it->end();
-		    ++inst_it) {
-		ReturnInst *inst = dyn_cast<ReturnInst>(inst_it);
-		if (inst != NULL) {
-		    to_fix.push_back(inst);
-		}
-	    }
-	}
-	// We have to process the blocks in a second loop because
-	// we can't modify the blocks while iterating on them.
-	for (std::vector<ReturnInst *>::iterator inst_it = to_fix.begin();
-		inst_it != to_fix.end();
-		++inst_it) {
-
-	    ReturnInst *inst = *inst_it;
-	    BasicBlock *startBB = inst->getParent();
-	    BasicBlock *mergeBB = startBB->splitBasicBlock(inst, "merge");
-	    // We do not want the BranchInst added by splitBasicBlock.
-	    startBB->getInstList().pop_back();
-	    compile_keep_vars(startBB, mergeBB);
-	}
-
-	if (new_rescue_invoke_bb->use_empty()
-		&& new_rescue_rethrow_bb->use_empty()) {
-	    new_rescue_invoke_bb->eraseFromParent();
-	    new_rescue_rethrow_bb->eraseFromParent();
-	}
-	else {
-	    if (new_rescue_invoke_bb->use_empty()) {
-		new_rescue_invoke_bb->eraseFromParent();
-	    }
-	    else {
-		bb = new_rescue_invoke_bb;
-		compile_landing_pad_header();
-		BranchInst::Create(new_rescue_rethrow_bb, bb);
-	    }
-
-	    bb = new_rescue_rethrow_bb;
-	    BasicBlock *mergeBB = BasicBlock::Create(context,
-		    "merge", f);
-	    compile_keep_vars(bb, mergeBB);
-
-	    bb = mergeBB;
-	    compile_rethrow_exception();
-	}
-    }
-    else if (current_var_uses != NULL) {
-	for (BasicBlock::use_iterator rescue_use_it =
-		new_rescue_invoke_bb->use_begin();
-		rescue_use_it != new_rescue_invoke_bb->use_end();
-		rescue_use_it = new_rescue_invoke_bb->use_begin()) {
-#if LLVM_TOT
-	    InvokeInst *invoke = dyn_cast<InvokeInst>(rescue_use_it);
-#else
-	    InvokeInst *invoke = dyn_cast<InvokeInst>(*rescue_use_it);
-#endif
-	    assert(invoke != NULL);
-
-	    // Transform the InvokeInst in CallInst.
-	    std::vector<Value *> params;
-	    for (unsigned i = 0; i < invoke->getNumOperands() - 3; i++) {
-		params.push_back(invoke->getOperand(i));
-	    }
-	    CallInst *call_inst = CallInst::Create(
-		    invoke->getCalledValue(),
-		    params.begin(), params.end(),
-		    "",
-		    invoke);
-
-	    // Transfer the debugging metadata if any.
-	    MDNode *node = invoke->getMetadata(dbg_mdkind);
-	    if (node !=NULL) {
-		call_inst->setMetadata(dbg_mdkind, node);
-	    }
-
-	    invoke->replaceAllUsesWith(call_inst);
-	    BasicBlock *normal_bb = dyn_cast<BasicBlock>(invoke->getNormalDest());
-	    assert(normal_bb != NULL);
-	    BranchInst::Create(normal_bb, invoke);
-	    invoke->eraseFromParent();
-	}
-	new_rescue_invoke_bb->eraseFromParent();
-
-	if (new_rescue_rethrow_bb->use_empty()) {
-	    new_rescue_rethrow_bb->eraseFromParent();
-	}
-	else {
-	    bb = new_rescue_rethrow_bb;
-	    compile_rethrow_exception();
-	}
-    }
-
-    for (std::vector<MAsgnValue>::iterator i = masgn_values.begin();
-	    i != masgn_values.end(); ++i) {
-	MAsgnValue &v = *i;
-	if (v.ary->hasNUses(v.sets.size())) {
-	    for (std::vector<CallInst *>::iterator j = v.sets.begin();
-		    j != v.sets.end(); ++j) {
-		CallInst *insn = *j;
-		insn->eraseFromParent();
-	    }
-	    v.ary->eraseFromParent();
-	}
-    }
-
-    current_block_arg = old_current_block_arg;
-
-    rescue_rethrow_bb = old_rescue_rethrow_bb;
-    rescue_invoke_bb = old_rescue_invoke_bb;
-
-    ensure_node = old_ensure_node;
-    ensure_bb = old_ensure_bb;
-    dispatch_argv = old_dispatch_argv;
-    bb = old_bb;
-    entry_bb = old_entry_bb;
-    lvars = old_lvars;
-    masgn_values = old_masgn_values;
-    current_self = old_self;
-    current_var_uses = old_current_var_uses;
-    running_block = old_running_block;
-    debug_subprogram = old_debug_subprogram;
-
-    return f;
-}
-
-Value *
-RoxorCompiler::compile_call(NODE *node, bool use_tco)
-{
-    NODE *recv = node->nd_recv;
-    NODE *args = node->nd_args;
-    ID mid = node->nd_mid;
-
-    if (nd_type(node) == NODE_CALL) {
-	assert(recv != NULL);
-    }
-    else {
-	assert(recv == NULL);
-    }
-
-    const bool block_given = current_block_func != NULL
-	&& current_block_node != NULL;
-    const bool super_call = nd_type(node) == NODE_SUPER
-	|| nd_type(node) == NODE_ZSUPER;
-
-    if (super_call) {
-	mid = current_mid;
-    }
-    else {
-	assert(mid > 0);
-    }
-
-    bool splat_args = false;
-    bool positive_arity = false;
-    if (nd_type(node) == NODE_ZSUPER) {
-	assert(args == NULL);
-	assert(current_non_block_func != NULL);
-	const long s = current_non_block_func->getArgumentList().size();
-	positive_arity = s - 2 > 0; /* skip self and sel */
-    }
-    else {
-	NODE *n = args;
-rescan_args:
-	if (n != NULL) {
-	    switch (nd_type(n)) {
-		case NODE_ARRAY:
-		    positive_arity = n->nd_alen > 0;
-		    break;
-
-		case NODE_SPLAT:
-		case NODE_ARGSPUSH:
-		case NODE_ARGSCAT:
-		    splat_args = true;
-		    positive_arity = true;
-		    break;
-
-		case NODE_BLOCK_PASS:
-		    n = n->nd_head;
-		    if (n != NULL) {
-			goto rescan_args;
-		    }
-		    positive_arity = false;
-		    break;
-
-		default:
-		    compile_node_error("invalid call args", n);
-	    }
-	}
-    }
-
-    // Recursive method call optimization. Not for everyone.
-    if (use_tco && !block_given && !super_call && !splat_args
-	    && !block_declaration && positive_arity && mid == current_mid
-	    && recv == NULL) {
-
-	Function *f = bb->getParent();
-	const unsigned long argc = args == NULL ? 0 : args->nd_alen;
-
-	if (f->arg_size() - 2 == argc) {
-	    // We check a global variable that we initialize to 0 in order
-	    // to verify that the current method did not overwrite itself.
-	    // This can happen. In this case, we do a normal dispatch.
-	    SEL sel = mid_to_sel(mid, positive_arity ? 1 : 0);
-	    GlobalVariable *gvar = GET_CORE()->redefined_op_gvar(sel, true);
-	    new StoreInst(ConstantInt::get(Type::getInt8Ty(context), 0), gvar,
-		    f->getEntryBlock().getFirstNonPHI());
-	    Value *isNotRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-		    new LoadInst(gvar, "", bb), ConstantInt::get(Int8Ty, 0));
-
-	    BasicBlock *thenBB = BasicBlock::Create(context, "op_not_redef", f);
-	    BasicBlock *elseBB = BasicBlock::Create(context, "op_dispatch", f);
-	    BasicBlock *mergeBB = BasicBlock::Create(context, "op_merge", f);
-
-	    BranchInst::Create(thenBB, elseBB, isNotRedefined, bb);
-
-	    // Compile optimized recursive call.
-	    bb = thenBB;
-	    std::vector<Value *> params;
-	    Function::arg_iterator arg = f->arg_begin();
-	    params.push_back(arg++); // self
-	    params.push_back(arg++); // sel 
-	    for (NODE *n = args; n != NULL; n = n->nd_next) {
-		params.push_back(compile_node(n->nd_head));
-	    }
-	    CallInst *inst = CallInst::Create(f, params.begin(), params.end(),
-		    "", bb);
-	    inst->setTailCall(true); // Promote for tail call elimitation.
-	    Value *optz_value = cast<Value>(inst);
-	    thenBB = bb;
-	    BranchInst::Create(mergeBB, bb);
-
-	    // Compile regular dispatch call.
-	    bb = elseBB;
-	    Value *unoptz_value = compile_call(node, false);
-	    elseBB = bb;
-	    BranchInst::Create(mergeBB, bb);
-
-	    bb = mergeBB;
-	    PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-	    pn->addIncoming(optz_value, thenBB);
-	    pn->addIncoming(unoptz_value, elseBB);
-	    return pn;
-	}
-    }
-
-    // Let's set the block state as NULL temporarily, when we
-    // compile the receiver and the arguments. 
-    Function *old_current_block_func = current_block_func;
-    NODE *old_current_block_node = current_block_node;
-    current_block_func = NULL;
-    current_block_node = NULL;
-
-    // Prepare the dispatcher parameters.
-    std::vector<Value *> params;
-
-    // Prepare the selector.
-    Value *sel_val;
-    SEL sel;
-    if (mid != 0) {
-	sel = mid_to_sel(mid, positive_arity ? 1 : 0);
-	sel_val = compile_sel(sel);
-	if (block_declaration && super_call) {
-	    // A super call inside a block. The selector cannot
-	    // be determined at compilation time, but at runtime:
-	    //
-	    //  VALUE my_block(VALUE rcv, SEL sel, ...)
-	    //	// ...
-	    //	SEL super_sel = sel;
-	    //  if (super_sel == 0)
-	    //	    super_sel = <hardcoded-mid>;
-	    //	rb_vm_dispatch(..., super_sel, ...);
-	    Function *f = bb->getParent();
-	    Function::arg_iterator arg = f->arg_begin();
-	    arg++; // skip self
-	    Value *dyn_sel = arg;
-	    Value *is_null = new ICmpInst(*bb, ICmpInst::ICMP_EQ, dyn_sel,
-		    compile_const_pointer(NULL));
-	    sel_val = SelectInst::Create(is_null, sel_val, dyn_sel, "", bb);
-	}
-    }	
-    else {
-	assert(super_call);
-	// A super call outside a method definition. Compile a
-	// null selector, the runtime will raise an exception.
-	sel = 0;
-	sel_val = compile_const_pointer(NULL);
-    }
-
-    // Top.
-    params.push_back(current_self);
-
-    // Self.
-    params.push_back(recv == NULL ? current_self : compile_node(recv));
-
-    // Selector.
-    params.push_back(sel_val);
-
-    // RubySpec requires that we compile the block *after* the arguments, so we
-    // do pass NULL as the block for the moment.
-    params.push_back(compile_const_pointer(NULL));
-    NODE *real_args = args;
-    if (real_args != NULL && nd_type(real_args) == NODE_BLOCK_PASS) {
-	real_args = args->nd_head;
-    }
-
-    // Call option.
-    unsigned char call_opt = 0;
-    if (super_call) {
-	call_opt |= DISPATCH_SUPER; 
-    }
-    else if (nd_type(node) == NODE_VCALL) {
-	call_opt |= DISPATCH_VCALL;
-    }
-    else if (nd_type(node) == NODE_FCALL) {
-	call_opt |= DISPATCH_FCALL;
-    }
-    params.push_back(ConstantInt::get(Int8Ty, call_opt));
-
-    // Arguments.
-    int argc = 0;
-    if (nd_type(node) == NODE_ZSUPER) {
-	Function::ArgumentListType &fargs =
-	    current_non_block_func->getArgumentList();
-	const int fargs_arity = fargs.size() - 2;
-	params.push_back(ConstantInt::get(Int32Ty, fargs_arity));
-	Function::ArgumentListType::iterator iter = fargs.begin();
-	iter++; // skip self
-	iter++; // skip sel
-	const int rest_pos = current_arity.max == -1
-	    ? (current_arity.left_req
-		    + (current_arity.real - current_arity.min - 1))
-	    : -1;
-	int i = 0;
-	while (iter != fargs.end()) {
-	    if (i == rest_pos) {
-		params.push_back(splatArgFollowsVal);
-		splat_args = true;
-	    }
-
-	    // We can't simply push the direct argument address
-	    // because if may have a default value.
-	    ID argid = rb_intern(iter->getName().data());
-	    Value *argslot;
-	    if (block_declaration) {
-		if (std::find(dvars.begin(), dvars.end(), argid)
-			== dvars.end()) {
-		    // Dvar does not exist yet, so we create it
-		    // on demand!
-		    dvars.push_back(argid);
-		}
-		argslot = compile_dvar_slot(argid);			
-	    }
-	    else {
-		argslot = compile_lvar_slot(argid);
-	    }
-
-	    params.push_back(new LoadInst(argslot, "", bb));
-
-	    ++i;
-	    ++iter;
-	}
-	argc = fargs_arity;
-    }
-    else if (real_args != NULL) {
-	std::vector<Value *> arguments;
-	compile_dispatch_arguments(real_args, arguments, &argc);
-	params.push_back(ConstantInt::get(Int32Ty, argc));
-	for (std::vector<Value *>::iterator i = arguments.begin();
-		i != arguments.end(); ++i) {
-	    params.push_back(*i);
-	}
-    }
-    else {
-	params.push_back(ConstantInt::get(Int32Ty, 0));
-    }
-
-    // In case we have splat args, modify the call option.
-    if (splat_args) {
-	call_opt |= DISPATCH_SPLAT;
-	params[4] = ConstantInt::get(Int8Ty, call_opt);
-    }
-
-    // Restore the block state.
-    current_block_func = old_current_block_func;
-    current_block_node = old_current_block_node;
-
-    // Now compile the block and insert it in the params list!
-    Value *blockVal;
-    if (args != NULL && nd_type(args) == NODE_BLOCK_PASS) {
-	assert(!block_given);
-	assert(args->nd_body != NULL);
-	blockVal = compile_block_get(compile_node(args->nd_body));
-    }
-    else {
-	if (block_given) {
-	    blockVal = compile_prepare_block();
-	}
-	else if (nd_type(node) == NODE_ZSUPER && current_block_arg != NULL) {
-	    blockVal = compile_block_get(current_block_arg);	
-	}
-	else {
-	    blockVal = compile_const_pointer(NULL);
-	}
-    }
-    params[3] = blockVal;
-
-    // If we are calling a method that needs a top-level binding object, let's
-    // create it. (Note: this won't work if the method is aliased, but we can
-    // live with that for now)
-    if (debug_mode
-	    || (!super_call
-		&& (sel == selEval
-		    || sel == selInstanceEval
-		    || sel == selClassEval
-		    || sel == selModuleEval
-		    || sel == selLocalVariables
-		    || sel == selBinding))) {
-	compile_binding();
-    }
-    else {
-	can_interpret = true;
-    }
-
-    // Can we optimize the call?
-    if (!super_call && !splat_args) {
-	Value *opt_call = compile_optimized_dispatch_call(sel, argc, params);
-	if (opt_call != NULL) {
-	    can_interpret = false;
-	    return opt_call;
-	}
-    }
-
-    // Looks like we can't, just do a regular dispatch then.
-    return compile_dispatch_call(params);
-}
-
-Value *
-RoxorCompiler::compile_yield(NODE *node)
-{
-    std::vector<Value *> args;
-    int argc = 0;
-    if (node->nd_head != NULL) {
-	compile_dispatch_arguments(node->nd_head, args, &argc);
-    }
-    Value *argv = recompile_dispatch_argv(args, 0);
-
-    std::vector<Value *> params;
-    params.push_back(ConstantInt::get(Int32Ty, argc));
-    unsigned char opt = 0;
-    if (argc < (int)args.size()) {
-	opt |= DISPATCH_SPLAT;
-    }
-    params.push_back(ConstantInt::get(Int8Ty, opt));
-    params.push_back(argv);    
-
-    Instruction *val = compile_protected_call(yieldFunc, params);
-    attach_current_line_metadata(val);
-
-    Value *broken = CallInst::Create(getBrokenFunc, "", bb);
-    Value *is_broken = new ICmpInst(*bb, ICmpInst::ICMP_NE, broken, undefVal);
-
-    Function *f = bb->getParent();
-    BasicBlock *broken_bb = BasicBlock::Create(context, "broken", f);
-    BasicBlock *next_bb = BasicBlock::Create(context, "next", f);
-
-    BranchInst::Create(broken_bb, next_bb, is_broken, bb);
-
-    bb = broken_bb;
-    ReturnInst::Create(context, broken, bb);
-
-    bb = next_bb;
-    return val;
-}
-
-inline Value *
-RoxorCompiler::compile_node0(NODE *node)
-{
-    switch (nd_type(node)) {
-	case NODE_SCOPE:
-	    can_interpret = true;
-	    return cast<Value>(compile_scope(node));
-
-	case NODE_DVAR:
-	case NODE_LVAR:
-	    assert(node->nd_vid > 0);
-	    return new LoadInst(compile_lvar_slot(node->nd_vid), "", bb);
-
-	case NODE_GVAR:
-	    return compile_gvar_get(node);
-
-	case NODE_GASGN:
-	    assert(node->nd_value != NULL);
-	    return compile_gvar_assignment(node, compile_node(node->nd_value));
-
-	case NODE_CVAR:
-	    assert(node->nd_vid > 0);
-	    return compile_cvar_get(node->nd_vid, true);
-
-	case NODE_CVASGN:
-	    assert(node->nd_vid > 0);
-	    assert(node->nd_value != NULL);
-	    return compile_cvar_assignment(node->nd_vid,
-		    compile_node(node->nd_value));
-
-	case NODE_MASGN:
-	    return compile_multiple_assignment(node);
-
-	case NODE_DASGN:
-	case NODE_DASGN_CURR:
-	    assert(node->nd_vid > 0);
-	    assert(node->nd_value != NULL);
-	    return compile_dvar_assignment(node->nd_vid,
-		    compile_node(node->nd_value));
-
-	case NODE_LASGN:
-	    assert(node->nd_vid > 0);
-	    assert(node->nd_value != NULL);
-	    return compile_lvar_assignment(node->nd_vid,
-		    compile_node(node->nd_value));
-
-	case NODE_OP_ASGN_OR:
-	    {
-		assert(node->nd_recv != NULL);
-		assert(node->nd_value != NULL);
-
-		Value *recvVal;
-		if (nd_type(node->nd_recv) == NODE_CVAR) {
-		    // @@foo ||= 42
-		    // We need to compile the class variable retrieve to not
-		    // raise an exception in case the variable has never been
-		    // defined yet.
-		    assert(node->nd_recv->nd_vid > 0);
-		    recvVal = compile_cvar_get(node->nd_recv->nd_vid, false);
-		}
-		else {
-		    recvVal = compile_node(node->nd_recv);
-		}
-
-
-		Value *falseCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			recvVal, falseVal);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *falseBB = BasicBlock::Create(context, "", f);
-		BasicBlock *elseBB  = BasicBlock::Create(context, "", f);
-		BasicBlock *trueBB = BasicBlock::Create(context, "", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "", f);
-
-		BranchInst::Create(falseBB, trueBB, falseCond, bb);
-
-		bb = trueBB;
-		Value *nilCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ, recvVal,
-			nilVal);
-		BranchInst::Create(falseBB, elseBB, nilCond, bb);
-
-		bb = falseBB;
-		Value *newRecvVal = compile_node(node->nd_value);
-		falseBB = bb;
-		BranchInst::Create(mergeBB, bb);
-
-		BranchInst::Create(mergeBB, elseBB);
-
-		bb = mergeBB;	
-		PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-		pn->addIncoming(newRecvVal, falseBB);
-		pn->addIncoming(recvVal, elseBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_OP_ASGN_AND:
-	    {
-		assert(node->nd_recv != NULL);
-		assert(node->nd_value != NULL);
-		
-		Value *recvVal = compile_node(node->nd_recv);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *notNilBB = BasicBlock::Create(context, "", f);
-		BasicBlock *elseBB  = BasicBlock::Create(context, "", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "", f);
-
-		compile_boolean_test(recvVal, notNilBB, elseBB);
-
-		bb = notNilBB;
-		Value *newRecvVal = compile_node(node->nd_value);
-		notNilBB = bb;
-		BranchInst::Create(mergeBB, bb);
-
-		BranchInst::Create(mergeBB, elseBB);
-
-		bb = mergeBB;	
-		PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-		pn->addIncoming(newRecvVal, notNilBB);
-		pn->addIncoming(recvVal, elseBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_OP_ASGN1:
-	case NODE_OP_ASGN2:
-	    {
-		assert(node->nd_recv != NULL);
-		Value *recv = compile_node(node->nd_recv);
-
-		long type = nd_type(node) == NODE_OP_ASGN1
-		    ? node->nd_mid : node->nd_next->nd_mid;
-
-		// a=[0] += 42
-		//
-		// tmp = a.send(:[], 0)
-		// tmp = tmp + 42
-		// a.send(:[]=, 0, tmp)
-
-		assert(node->nd_args != NULL);
-		assert(node->nd_args->nd_head != NULL);
-
-		// tmp = a.send(:[], 0)
-
-		std::vector<Value *> params;
-		SEL sel;
-		if (nd_type(node) == NODE_OP_ASGN1) {
-		    sel = selAREF;
-		}
-		else {
-		    assert(node->nd_next->nd_vid > 0);
-		    sel = mid_to_sel(node->nd_next->nd_vid, 0);
-		}
-		params.push_back(current_self);
-		params.push_back(recv);
-		params.push_back(compile_sel(sel));
-		params.push_back(compile_const_pointer(NULL));
-
-		int argc = 0;
-		std::vector<Value *> arguments;
-		if (nd_type(node) == NODE_OP_ASGN1) {
-		    assert(node->nd_args->nd_body != NULL);
-		    compile_dispatch_arguments(node->nd_args->nd_body,
-			    arguments,
-			    &argc);
-		}
-
-		unsigned char opt = 0;
-		if (argc < (int)arguments.size()) {
-		    opt |= DISPATCH_SPLAT;
-		}
-		params.push_back(ConstantInt::get(Int8Ty, opt));
-
-		params.push_back(ConstantInt::get(Int32Ty, argc));
-		for (std::vector<Value *>::iterator i = arguments.begin();
-			i != arguments.end(); ++i) {
-		    params.push_back(*i);
-		}
-
-		Value *tmp = compile_optimized_dispatch_call(sel, argc, params);
-		if (tmp == NULL) {
-		    tmp = compile_dispatch_call(params);
-		}
-
-		// tmp = tmp + 42
-
-		BasicBlock *mergeBB = NULL;
-		BasicBlock *touchedBB = NULL;
-		BasicBlock *untouchedBB = NULL;
-		Value *tmp2;
-		NODE *value = nd_type(node) == NODE_OP_ASGN1
-		    ? node->nd_args->nd_head : node->nd_value;
-		assert(value != NULL);
-		if (type == 0 || type == 1) {
-		    // 0 means OR, 1 means AND
-		    Function *f = bb->getParent();
-
-		    touchedBB = BasicBlock::Create(context, "", f);
-		    untouchedBB  = BasicBlock::Create(context, "", f);
-		    mergeBB = BasicBlock::Create(context, "merge", f);
-
-		    if (type == 0) {
-			compile_boolean_test(tmp, untouchedBB, touchedBB);
-		    }
-		    else {
-			compile_boolean_test(tmp, touchedBB, untouchedBB);
-		    }
-
-		    BranchInst::Create(mergeBB, untouchedBB);
-
-		    bb = touchedBB;
-		    tmp2 = compile_node(value);
-		}
-		else {
-		    ID mid = nd_type(node) == NODE_OP_ASGN1
-			? node->nd_mid : node->nd_next->nd_mid;
-		    sel = mid_to_sel(mid, 1);
-		    params.clear();
-		    params.push_back(current_self);
-		    params.push_back(tmp);
-		    params.push_back(compile_sel(sel));
-		    params.push_back(compile_const_pointer(NULL));
-		    params.push_back(ConstantInt::get(Int8Ty, 0));
-		    params.push_back(ConstantInt::get(Int32Ty, 1));
-		    params.push_back(compile_node(value));
-
-		    tmp2 = compile_optimized_dispatch_call(sel, 1, params);
-		    if (tmp2 == NULL) {
-			tmp2 = compile_dispatch_call(params);
-		    }
-		}
-
-		// a.send(:[]=, 0, tmp)
- 
-		if (nd_type(node) == NODE_OP_ASGN1) {
-		    sel = selASET;
-		}
-		else {
-		    assert(node->nd_next->nd_aid > 0);
-		    sel = mid_to_sel(node->nd_next->nd_aid, 1);
-		}
-		params.clear();
-		params.push_back(current_self);
-		params.push_back(recv);
-		params.push_back(compile_sel(sel));
-		params.push_back(compile_const_pointer(NULL));
-		params.push_back(ConstantInt::get(Int8Ty, 0));
-		argc++;
-		params.push_back(ConstantInt::get(Int32Ty, argc));
-		for (std::vector<Value *>::iterator i = arguments.begin();
-		     i != arguments.end(); ++i) {
-		    params.push_back(*i);
-		}
-		params.push_back(tmp2);
-
-		Value *ret = compile_optimized_dispatch_call(sel, argc, params);
-		if (ret == NULL) {
-		    ret = compile_dispatch_call(params);
-		}
-
-		if (mergeBB == NULL) {
-		    return ret;
-		}
-
-		// compile_dispatch_call can create a new BasicBlock
-		// so we have to get bb just after
-		touchedBB = bb;
-
-		BranchInst::Create(mergeBB, touchedBB);
-
-		bb = mergeBB;	
-
-		PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
-		pn->addIncoming(tmp, untouchedBB);
-		pn->addIncoming(ret, touchedBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_XSTR:
-	case NODE_DXSTR:
-	    {
-		Value *str;
-		if (nd_type(node) == NODE_DXSTR) {
-		    str = compile_dstr(node);
-		}
-		else {
-		    assert(node->nd_lit != 0);
-		    str = compile_literal(node->nd_lit);
-		}
-
-		std::vector<Value *> params;
-		params.push_back(current_self);
-		params.push_back(current_self);
-		params.push_back(compile_sel(selBackquote));
-		params.push_back(compile_const_pointer(NULL));
-		params.push_back(ConstantInt::get(Int8Ty, DISPATCH_FCALL));
-		params.push_back(ConstantInt::get(Int32Ty, 1));
-		params.push_back(str);
-
-		return compile_dispatch_call(params);
-	    }
-	    break;
-
-	case NODE_DSTR:
-	    return compile_dstr(node);
-
-	case NODE_DREGX:
-	case NODE_DREGX_ONCE: // TODO optimize NODE_DREGX_ONCE
-	    {
-		Value *val  = compile_dstr(node);
-		const int flag = node->nd_cflag;
-
-		if (newRegexpFunc == NULL) {
-		    newRegexpFunc = cast<Function>(module->getOrInsertFunction(
-				"rb_reg_new_str",
-				RubyObjTy, RubyObjTy, Int32Ty, NULL));
-		}
-
-		Value *args[] = {
-		    val,
-		    ConstantInt::get(Int32Ty, flag)
-		};
-		return compile_protected_call(newRegexpFunc, args, args + 2);
-	    }
-	    break;
-
-	case NODE_DSYM:
-	    {
-		Value *val = compile_dstr(node);
-
-		if (strInternFunc == NULL) {
-		    strInternFunc = cast<Function>(module->getOrInsertFunction(
-				"rb_str_intern_fast",
-				RubyObjTy, RubyObjTy, NULL));
-		}
-
-		Value *args[] = { val };
-		return compile_protected_call(strInternFunc, args, args + 1);
-	    }
-	    break;
-
-	case NODE_EVSTR:
-	    {
-		assert(node->nd_body != NULL);
-		return compile_node(node->nd_body);
-	    }
-	    break;
-
-	case NODE_OR:
-	    {
-		NODE *left = node->nd_1st;
-		assert(left != NULL);
-
-		NODE *right = node->nd_2nd;
-		assert(right != NULL);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *leftNotFalseBB = BasicBlock::Create(context,
-			"left_not_false", f);
-		BasicBlock *leftNotTrueBB = BasicBlock::Create(context,
-			"left_not_true", f);
-		BasicBlock *leftTrueBB = BasicBlock::Create(context,
-			"left_is_true", f);
-		BasicBlock *rightNotFalseBB = BasicBlock::Create(context,
-			"right_not_false", f);
-		BasicBlock *rightTrueBB = BasicBlock::Create(context,
-			"right_is_true", f);
-		BasicBlock *failBB = BasicBlock::Create(context, "fail", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "merge", f);
-
-		Value *leftVal = compile_node(left);
-		Value *leftNotFalseCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			leftVal, falseVal);
-		BranchInst::Create(leftNotFalseBB, leftNotTrueBB,
-			leftNotFalseCond, bb);
-
-		bb = leftNotFalseBB;
-		Value *leftNotNilCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			leftVal, nilVal);
-		BranchInst::Create(leftTrueBB, leftNotTrueBB, leftNotNilCond,
-			bb);
-
-		bb = leftNotTrueBB;
-		Value *rightVal = compile_node(right);
-		Value *rightNotFalseCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			rightVal, falseVal);
-		BranchInst::Create(rightNotFalseBB, failBB, rightNotFalseCond,
-			bb);
-
-		bb = rightNotFalseBB;
-		Value *rightNotNilCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			rightVal, nilVal);
-		BranchInst::Create(rightTrueBB, failBB, rightNotNilCond, bb);
-
-		BranchInst::Create(mergeBB, leftTrueBB);
-		BranchInst::Create(mergeBB, rightTrueBB);
-		BranchInst::Create(mergeBB, failBB);
-
-		bb = mergeBB;
-		PHINode *pn = PHINode::Create(RubyObjTy, "", mergeBB);
-		pn->addIncoming(leftVal, leftTrueBB);
-		pn->addIncoming(rightVal, rightTrueBB);
-		pn->addIncoming(rightVal, failBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_AND:
-	    {
-		NODE *left = node->nd_1st;
-		assert(left != NULL);
-
-		NODE *right = node->nd_2nd;
-		assert(right != NULL);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *leftNotFalseBB = BasicBlock::Create(context,
-			"left_not_false", f);
-		BasicBlock *leftTrueBB = BasicBlock::Create(context,
-			"left_is_true", f);
-		BasicBlock *rightNotFalseBB = BasicBlock::Create(context,
-			"right_not_false", f);
-		BasicBlock *leftFailBB = BasicBlock::Create(context,
-			"left_fail", f);
-		BasicBlock *rightFailBB = BasicBlock::Create(context,
-			"right_fail", f);
-		BasicBlock *successBB = BasicBlock::Create(context, "success",
-			f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "merge", f);
-
-		Value *leftVal = compile_node(left);
-		Value *leftNotFalseCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			leftVal, falseVal);
-		BranchInst::Create(leftNotFalseBB, leftFailBB,
-			leftNotFalseCond, bb);
-
-		bb = leftNotFalseBB;
-		Value *leftNotNilCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			leftVal, nilVal);
-		BranchInst::Create(leftTrueBB, leftFailBB, leftNotNilCond, bb);
-
-		bb = leftTrueBB;
-		Value *rightVal = compile_node(right);
-		Value *rightNotFalseCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			rightVal, falseVal);
-
-		BranchInst::Create(rightNotFalseBB, rightFailBB, rightNotFalseCond, bb);
-
-		bb = rightNotFalseBB;
-		Value *rightNotNilCond = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			rightVal, nilVal);
-		BranchInst::Create(successBB, rightFailBB, rightNotNilCond, bb);
-
-		BranchInst::Create(mergeBB, successBB);
-		BranchInst::Create(mergeBB, leftFailBB);
-		BranchInst::Create(mergeBB, rightFailBB);
-
-		bb = mergeBB;
-		PHINode *pn = PHINode::Create(RubyObjTy, "", mergeBB);
-		pn->addIncoming(leftVal, leftFailBB);
-		pn->addIncoming(rightVal, rightFailBB);
-		pn->addIncoming(rightVal, successBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_IF:
-	    {
-		Value *condVal = compile_node(node->nd_cond);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *thenBB = BasicBlock::Create(context, "then", f);
-		BasicBlock *elseBB  = BasicBlock::Create(context, "else", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "merge", f);
-
-		compile_boolean_test(condVal, thenBB, elseBB);
-
-		bb = thenBB;
-		DEBUG_LEVEL_INC();
-		Value *thenVal = node->nd_body != NULL ? compile_node(node->nd_body) : nilVal;
-		DEBUG_LEVEL_DEC();
-		thenBB = bb;
-		BranchInst::Create(mergeBB, thenBB);
-
-		bb = elseBB;
-		DEBUG_LEVEL_INC();
-		Value *elseVal = node->nd_else != NULL ? compile_node(node->nd_else) : nilVal;
-		DEBUG_LEVEL_DEC();
-		elseBB = bb;
-		BranchInst::Create(mergeBB, elseBB);
-		
-		bb = mergeBB;
-		PHINode *pn = PHINode::Create(RubyObjTy, "iftmp", mergeBB);
-		pn->addIncoming(thenVal, thenBB);
-		pn->addIncoming(elseVal, elseBB);
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_CLASS:
-	case NODE_SCLASS:
-	case NODE_MODULE:
-	    {
-		assert(node->nd_cpath != NULL);
-
-		Value *classVal = NULL;
-		int current_outer_level = 0;
-		if (nd_type(node) == NODE_SCLASS) {
-		    classVal =
-			compile_singleton_class(compile_node(node->nd_recv));
-		}
-		else {
-		    assert(node->nd_cpath->nd_mid > 0);
-		    ID path = node->nd_cpath->nd_mid;
-
-		    NODE *super = node->nd_super;
-
-		    if (defineClassFunc == NULL) {
-			// VALUE rb_vm_define_class(ID path, VALUE outer,
-			//	VALUE super, int flags,
-			//	unsigned char dynamic_class);
-			defineClassFunc = cast<Function>(
-				module->getOrInsertFunction(
-				    "rb_vm_define_class",
-				    RubyObjTy, IntTy, RubyObjTy, RubyObjTy,
-				    Int32Ty, Int8Ty, NULL));
-		    }
-
-		    int flags = 0;
-		    Value *cpath = compile_class_path(node->nd_cpath, &flags,
-			&current_outer_level);
-		    if (nd_type(node) == NODE_MODULE) {
-			flags |= DEFINE_MODULE;
-		    }
-
-		    Value *args[] = {
-			compile_id(path),
-			cpath,
-			super == NULL ? zeroVal : compile_node(super),
-			ConstantInt::get(Int32Ty, flags),
-			ConstantInt::get(Int8Ty,
-				(flags & DEFINE_OUTER) && dynamic_class
-				? 1 : 0)
-		    };
-		    Instruction *insn = compile_protected_call(defineClassFunc,
-			args, args + 5);
-		    attach_current_line_metadata(insn);
-		    classVal = insn;
-		}
-
-		NODE *body = node->nd_body;
-		if (body != NULL) {
-		    assert(nd_type(body) == NODE_SCOPE);
-		    if (body->nd_body != NULL) {	
-			Value *old_self = current_self;
-			current_self = classVal;
-
-			GlobalVariable *old_class = current_opened_class;
-			current_opened_class = new GlobalVariable(
-				*RoxorCompiler::module, RubyObjTy, false,
-				GlobalValue::InternalLinkage, nilVal, "");
-
-			bool old_current_block_chain = current_block_chain;
-			bool old_dynamic_class = dynamic_class;
-
-			current_block_chain = false;
-			dynamic_class = false;
-
-			new StoreInst(classVal, current_opened_class, bb);
-
-			compile_set_current_scope(classVal, publicScope);
-
-			bool old_block_declaration = block_declaration;
-			block_declaration = false;
-
-			std::map<ID, void *> old_ivars_slots_cache
-			    = ivars_slots_cache;
-			old_ivars_slots_cache.clear();
-
-			// Increase the outer mask.
-			int old_outer_mask = outer_mask;
-			outer_mask <<= current_outer_level + 1;
-			for (int i = 0; i < current_outer_level; i++) {
-			    outer_mask |= (1 << (i + 1));
-			} 
-
-			DEBUG_LEVEL_INC();
-			Value *val = compile_node(body);
-			assert(Function::classof(val));
-			Function *f = cast<Function>(val);
-			GET_CORE()->optimize(f);
-			DEBUG_LEVEL_DEC();
-
-			outer_mask = old_outer_mask;
-
-			ivars_slots_cache = old_ivars_slots_cache;
-
-			block_declaration = old_block_declaration;
-
-			std::vector<Value *> params;
-			params.push_back(classVal);
-			params.push_back(compile_const_pointer(NULL));
-			val = compile_protected_call(f, params);
-
-			dynamic_class = old_dynamic_class;
-			compile_set_current_scope(classVal, defaultScope);
-
-			current_self = old_self;
-			current_opened_class = old_class;
-			current_block_chain = old_current_block_chain;
-
-			return val;
-		    }
-		}
-
-		return nilVal;
-	    }
-	    break;
-
-	case NODE_SUPER:
-	case NODE_ZSUPER:
-	case NODE_CALL:
-	case NODE_FCALL:
-	case NODE_VCALL:
-	    return compile_call(node);
-
-	case NODE_ATTRASGN:
-	    return compile_attribute_assign(node, NULL);
-
-	case NODE_BREAK:
-	case NODE_NEXT:
-	case NODE_REDO:
-	case NODE_RETURN:
-	case NODE_RETRY:
-	    return compile_jump(node);
-
-	case NODE_CONST:
-	    assert(node->nd_vid > 0);
-	    return compile_const(node->nd_vid, NULL);
-
-	case NODE_CDECL:
-	    assert(node->nd_value != NULL);
-	    return compile_constant_declaration(node,
-		    compile_node(node->nd_value));
-
-	case NODE_IASGN:
-	case NODE_IASGN2:
-	    assert(node->nd_vid > 0);
-	    assert(node->nd_value != NULL);
-	    return compile_ivar_assignment(node->nd_vid,
-		    compile_node(node->nd_value));
-
-	case NODE_IVAR:
-	    assert(node->nd_vid > 0);
-	    return compile_ivar_get(node->nd_vid);
-
-	case NODE_LIT:
-	    can_interpret = true;
-	case NODE_STR:
-	    assert(node->nd_lit != 0);
-	    return compile_literal(node->nd_lit);
-
-	case NODE_ARGSCAT:
-	case NODE_ARGSPUSH:
-	    {
-		assert(node->nd_head != NULL);
-		Value *ary = compile_node(node->nd_head);
-		Value *args1[] = { ary };
-		ary = compile_protected_call(dupArrayFunc, args1, args1 + 1);
-
-		assert(node->nd_body != NULL);
-		Value *other = compile_node(node->nd_body);
-		Value *args2[] = { ary, other };
-		return compile_protected_call(catArrayFunc, args2, args2 + 2);
-	    }
-	    break;
-
-	case NODE_SPLAT:
-	    {
-		assert(node->nd_head != NULL);
-		Value *val = compile_node(node->nd_head);
-
-		if (nd_type(node->nd_head) != NODE_ARRAY) {
-		    Value *args[] = { val };
-		    val = compile_protected_call(toAFunc, args, args + 1);
-		}
-
-		return val;
-	    }
-	    break;
-
-	case NODE_ARRAY:
-	case NODE_ZARRAY:
-	case NODE_VALUES:
-	    {
-		Value *ary;
-
-		if (nd_type(node) == NODE_ZARRAY) {
-		    ary = CallInst::Create(newArrayFunc,
-			    ConstantInt::get(Int32Ty, 0), "", bb);
-		}
-		else {
-		    const int count = node->nd_alen;
-		    ary = CallInst::Create(newArrayFunc,
-			    ConstantInt::get(Int32Ty, count), "", bb);
-
-		    NODE *n = node;
-		    for (int i = 0; i < count; i++) {
-			assert(n->nd_head != NULL);
-			Value *elem = compile_node(n->nd_head);
-
-			Value *args[] = {
-			    ary,
-			    ConstantInt::get(Int32Ty, i),
-			    elem
-			};
-			CallInst::Create(asetArrayFunc, args, args + 3, "", bb);
-
-			n = n->nd_next;
-		    }
-		}
-
-		return ary;
-	    }
-	    break;
-
-	case NODE_HASH:
-	    {
-		Value *hash = CallInst::Create(newHashFunc, "", bb);
-
-		if (node->nd_head != NULL) {
-		    assert(nd_type(node->nd_head) == NODE_ARRAY);
-		    const int count = node->nd_head->nd_alen;
-		    assert(count % 2 == 0);
-		    NODE *n = node->nd_head;
-
-		    for (int i = 0; i < count; i += 2) {
-			Value *key = compile_node(n->nd_head);
-			n = n->nd_next;
-			Value *val = compile_node(n->nd_head);
-			n = n->nd_next;
-
-			Value *args[] = {
-			    hash,
-			    key,
-			    val
-			};
-			CallInst::Create(storeHashFunc, args, args + 3, "", bb);
-		    }
-		}
-
-		return hash;
-	    }
-	    break;
-
-	case NODE_DOT2:
-	case NODE_DOT3:
-	    assert(node->nd_beg != NULL);
-	    assert(node->nd_end != NULL);
-	    return compile_range(compile_node(node->nd_beg),
-		    compile_node(node->nd_end), nd_type(node) == NODE_DOT3);
-
-	case NODE_FLIP2:
-	case NODE_FLIP3:
-	    assert(node->nd_beg != NULL);
-	    assert(node->nd_end != NULL);
-
-	    if (nd_type(node) == NODE_FLIP2) {
-		return compile_ff2(node);
-	    }
-	    return compile_ff3(node);
-
-	case NODE_BLOCK:
-	    {
-		can_interpret = true;
-		NODE *n = node;
-		Value *val = NULL;
-
-		DEBUG_LEVEL_INC();
-		while (n != NULL && nd_type(n) == NODE_BLOCK) {
-		    val = n->nd_head == NULL
-			? nilVal : compile_node(n->nd_head);
-		    n = n->nd_next;
-		}
-		DEBUG_LEVEL_DEC();
-
-		return val;
-	    }
-	    break;
-
-	case NODE_MATCH:
-	case NODE_MATCH2:
-	case NODE_MATCH3:
-	    {
-		Value *reTarget;
-		Value *reSource;
-
-		if (nd_type(node) == NODE_MATCH) {
-		    assert(node->nd_lit != 0);
-		    reTarget = ConstantInt::get(RubyObjTy, node->nd_lit);
-		    reSource = nilVal; // TODO this should get $_
-		}
-		else {
-		    assert(node->nd_recv);
-		    assert(node->nd_value);
-		    if (nd_type(node) == NODE_MATCH2) {
-			reTarget = compile_node(node->nd_recv);
-			reSource = compile_node(node->nd_value);
-		    }
-		    else {
-			reTarget = compile_node(node->nd_value);
-			reSource = compile_node(node->nd_recv);
-		    }
-		}
-
-		std::vector<Value *> params;
-		params.push_back(current_self);
-		params.push_back(reTarget);
-		params.push_back(compile_sel(selEqTilde));
-		params.push_back(compile_const_pointer(NULL));
-		params.push_back(ConstantInt::get(Int8Ty, 0));
-		params.push_back(ConstantInt::get(Int32Ty, 1));
-		params.push_back(reSource);
-
-		return compile_dispatch_call(params);
-	    }
-	    break;
-
-#if 0 // TODO
-	case NODE_CFUNC:
-	    {
-	    }
-#endif
-
-	case NODE_VALIAS:
-	    {
-		if (valiasFunc == NULL) {
-		    // void rb_alias_variable(ID from, ID to);
-		    valiasFunc = cast<Function>(module->getOrInsertFunction(
-				"rb_alias_variable",
-				VoidTy, IntTy, IntTy, NULL));
-		}
-
-		assert(node->u1.id > 0 && node->u2.id > 0);
-
-		Value *args[] = {
-		    compile_id(node->u1.id),
-		    compile_id(node->u2.id)
-		};
-		CallInst::Create(valiasFunc, args, args + 2, "", bb);
-
-		return nilVal;
-	    }
-	    break;
-
-	case NODE_ALIAS:
-	    {
-		if (aliasFunc == NULL) {
-		    // void rb_vm_alias2(VALUE outer, VALUE from_sym,
-		    //		VALUE to_sym, unsigned char dynamic_class);
-		    aliasFunc = cast<Function>(module->getOrInsertFunction(
-				"rb_vm_alias2",
-				VoidTy, RubyObjTy, IntTy, IntTy, Int8Ty,
-				NULL));
-		}
-
-		assert(node->u1.node != NULL);
-		assert(node->u2.node != NULL);
-
-		Value *args[] = {
-		    compile_current_class(),
-		    compile_node(node->u1.node),
-		    compile_node(node->u2.node),
-		    ConstantInt::get(Int8Ty, dynamic_class ? 1 : 0)
-		};
-		compile_protected_call(aliasFunc, args, args + 4);
-
-		return nilVal;
-	    }
-	    break;
-
-	case NODE_DEFINED:
-	    assert(node->nd_head != NULL);
-	    return compile_defined_expression(node->nd_head);
-
-	case NODE_DEFN:
-	case NODE_DEFS:
-	    compile_method_definition(node);
-	    return nilVal;
-
-	case NODE_UNDEF:
-	    {
-		if (undefFunc == NULL) {
-		    // VALUE rb_vm_undef2(VALUE klass, VALUE sym,
-		    //	unsigned char dynamic_class);
-		    undefFunc =
-			cast<Function>(module->getOrInsertFunction(
-				"rb_vm_undef2",
-				VoidTy, RubyObjTy, RubyObjTy, Int8Ty, NULL));
-		}
-
-		assert(node->u2.node != NULL);
-		Value *args[] = {
-		    compile_current_class(),
-		    compile_node(node->u2.node),
-		    ConstantInt::get(Int8Ty, dynamic_class ? 1 : 0)
-		};
-		compile_protected_call(undefFunc, args, args + 3);
-
-		return nilVal;
-	    }
-	    break;
-
-	case NODE_TRUE:
-	    can_interpret = true;
-	    return trueVal;
-
-	case NODE_FALSE:
-	    can_interpret = true;
-	    return falseVal;
-
-	case NODE_NIL:
-	    can_interpret = true;
-	    return nilVal;
-
-	case NODE_SELF:
-	    return current_self;
-
-	case NODE_NTH_REF:
-	case NODE_BACK_REF:
-	    return CallInst::Create(getSpecialFunc,
-		    ConstantInt::get(Int8Ty, (char)node->nd_nth), "", bb);
-
-	case NODE_BEGIN:
-	    can_interpret = true;
-	    return node->nd_body == NULL
-		? nilVal : compile_node(node->nd_body);
-
-	case NODE_RESCUE:
-	    {
-		assert(node->nd_head != NULL);
-		assert(node->nd_resq != NULL);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *old_begin_bb = begin_bb;
-		begin_bb = BasicBlock::Create(context, "begin", f);
-
-		BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-		BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
-		BasicBlock *new_rescue_invoke_bb =
-		    BasicBlock::Create(context, "rescue", f);
-		BasicBlock *new_rescue_rethrow_bb =
-		    BasicBlock::Create(context, "rescue.rethrow", f);
-		BasicBlock *merge_bb = BasicBlock::Create(context, "merge", f);
-
-		// Begin code.
-		BranchInst::Create(begin_bb, bb);
-		bb = begin_bb;
-		rescue_invoke_bb = new_rescue_invoke_bb;
-		rescue_rethrow_bb = new_rescue_rethrow_bb;
-		Value *not_rescued_val = compile_node(node->nd_head);
-		rescue_rethrow_bb = old_rescue_rethrow_bb;
-		rescue_invoke_bb = old_rescue_invoke_bb;
-
-		if (node->nd_else != NULL) {
-		    BasicBlock *else_bb = BasicBlock::Create(context, "else",
-			    f);
-		    BranchInst::Create(else_bb, bb);
-		    bb = else_bb;
-		    not_rescued_val = compile_node(node->nd_else);
-		}
-
-		BasicBlock *not_rescued_bb = bb;
-		BranchInst::Create(merge_bb, not_rescued_bb);
-
-		PHINode *pn = PHINode::Create(RubyObjTy, "rescue_result",
-			merge_bb);
-		pn->addIncoming(not_rescued_val, not_rescued_bb);
-
-		if (new_rescue_invoke_bb->use_empty()
-			&& new_rescue_rethrow_bb->use_empty()) {
-		    new_rescue_invoke_bb->eraseFromParent();
-		    new_rescue_rethrow_bb->eraseFromParent();
-		}
-		else {
-		    if (new_rescue_invoke_bb->use_empty()) {
-			new_rescue_invoke_bb->eraseFromParent();
-		    }
-		    else {
-			// Landing pad header.
-			bb = new_rescue_invoke_bb;
-			compile_landing_pad_header();
-			BranchInst::Create(new_rescue_rethrow_bb, bb);
-		    }
-
-		    bb = new_rescue_rethrow_bb;
-
-		    // Landing pad code.
-		    bool old_current_rescue = current_rescue;
-		    current_rescue = true;
-		    Value *rescue_val = compile_node(node->nd_resq);
-		    current_rescue = old_current_rescue;
-		    new_rescue_invoke_bb = bb;
-
-		    // Landing pad footer.
-		    compile_landing_pad_footer();
-
-		    BranchInst::Create(merge_bb, bb);
-		    pn->addIncoming(rescue_val, new_rescue_invoke_bb);
-		}
-
-		bb = merge_bb;
-		begin_bb = old_begin_bb;
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_RESBODY:
-	    {
-		NODE *n = node;
-
-		Function *f = bb->getParent();
-		BasicBlock *merge_bb = BasicBlock::Create(context, "merge", f);
-		BasicBlock *handler_bb = NULL;
-
-		std::vector<std::pair<Value *, BasicBlock *> > handlers;
-
-		while (n != NULL) {
-		    std::vector<Value *> exceptions_to_catch;
-
-		    if (n->nd_args == NULL) {
-			// catch StandardError exceptions by default
-			exceptions_to_catch.push_back(compile_standarderror());
-		    }
-		    else {
-			NODE *n2 = n->nd_args;
-			if (nd_type(n2) == NODE_ARRAY) {
-			    while (n2 != NULL) {
-				exceptions_to_catch.push_back(compile_node(
-					    n2->nd_head));
-				n2 = n2->nd_next;
-			    }
-			}
-			else {
-			    exceptions_to_catch.push_back(compile_node(n2));
-			}
-		    }
-
-		    Function *isEHActiveFunc = NULL;
-		    if (isEHActiveFunc == NULL) {
-			// bool rb_vm_is_eh_active(int argc, ...);
-			std::vector<const Type *> types;
-			types.push_back(Int32Ty);
-			FunctionType *ft = FunctionType::get(Int8Ty,
-				types, true);
-			isEHActiveFunc = cast<Function>(
-				module->getOrInsertFunction(
-				    "rb_vm_is_eh_active", ft));
-		    }
-
-		    const int size = exceptions_to_catch.size();
-		    exceptions_to_catch.insert(exceptions_to_catch.begin(), 
-			    ConstantInt::get(Int32Ty, size));
-
-		    Value *handler_active = CallInst::Create(isEHActiveFunc, 
-			    exceptions_to_catch.begin(), 
-			    exceptions_to_catch.end(), "", bb);
-
-		    Value *is_handler_active = new ICmpInst(*bb,
-			    ICmpInst::ICMP_EQ, handler_active,
-			    ConstantInt::get(Int8Ty, 1));
-		    
-		    handler_bb = BasicBlock::Create(context, "handler", f);
-		    BasicBlock *next_handler_bb =
-			BasicBlock::Create(context, "handler", f);
-
-		    BranchInst::Create(handler_bb, next_handler_bb,
-			    is_handler_active, bb);
-
-		    bb = handler_bb;
-		    assert(n->nd_body != NULL);
-
-		    // Compile the rescue handler within another exception
-		    // handler.
-		    BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-		    BasicBlock *new_rescue_invoke_bb =
-			BasicBlock::Create(context, "rescue", f);
-		    rescue_invoke_bb = new_rescue_invoke_bb;
-
-		    Value *header_val = compile_node(n->nd_body);
-		    handler_bb = bb;
-		    BranchInst::Create(merge_bb, bb);
-		    handlers.push_back(std::pair<Value *, BasicBlock *>
-			    (header_val, handler_bb));
-
-		    // If the handler raised an exception, pop the previous
-		    // one from the VM stack and rethrow.
-		    bb = new_rescue_invoke_bb;
-		    compile_landing_pad_header();
-		    compile_pop_exception(1);
-		    compile_rethrow_exception();
-		    rescue_invoke_bb = old_rescue_invoke_bb;
-
-		    bb = handler_bb = next_handler_bb;
-
-		    n = n->nd_head;
-		}
-
-		bb = handler_bb;
-		compile_rethrow_exception();
-
-		bb = merge_bb;
-		assert(handlers.size() > 0);
-		if (handlers.size() == 1) {
-		    return handlers.front().first;
-		}
-		else {
-		    PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", bb);
-		    std::vector<std::pair<Value *, BasicBlock *> >::iterator
-			iter = handlers.begin();
-		    while (iter != handlers.end()) {
-			pn->addIncoming(iter->first, iter->second);
-			++iter;
-		    }
-		    return pn;
-		}
-	    }
-	    break;
-
-	case NODE_ERRINFO:
-	    return compile_current_exception();
-
-	case NODE_ENSURE:
-	    {
-		assert(node->nd_ensr != NULL);
-		if (node->nd_head == NULL) {
-		    compile_node(node->nd_ensr);
-		    return nilVal;
-		}
-
-		Function *f = bb->getParent();
-		BasicBlock *old_ensure_bb = ensure_bb;
-		PHINode *old_ensure_pn = ensure_pn;
-		// the ensure for when the block is left with a return
-		BasicBlock *ensure_return_bb = BasicBlock::Create(context,
-			"ensure.for.return", f);
-		// the ensure for when the block is left without using return
-		BasicBlock *ensure_normal_bb = BasicBlock::Create(context,
-			"ensure.no.return", f);
-		PHINode *new_ensure_pn = PHINode::Create(RubyObjTy,
-			"ensure.phi", ensure_return_bb);
-		ensure_pn = new_ensure_pn;
-
-		ensure_bb = ensure_return_bb;
-
-		BasicBlock *new_rescue_invoke_bb = BasicBlock::Create(context,
-			"rescue", f);
-		BasicBlock *new_rescue_rethrow_bb = BasicBlock::Create(context,
-			"rescue.rethrow", f);
-		BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-		BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
-
-		Value *old_has_ensure =
-		    compile_set_has_ensure(ConstantInt::get(Int8Ty, 1));
-
-		NODE *old_ensure_node = ensure_node;
-		ensure_node = node->nd_ensr;
-
-		rescue_invoke_bb = new_rescue_invoke_bb;
-		rescue_rethrow_bb = new_rescue_rethrow_bb;
-		DEBUG_LEVEL_INC();
-		Value *val = compile_node(node->nd_head);
-		DEBUG_LEVEL_DEC();
-		rescue_rethrow_bb = old_rescue_rethrow_bb;
-		rescue_invoke_bb = old_rescue_invoke_bb;
-		BranchInst::Create(ensure_normal_bb, bb);
-
-		ensure_node = old_ensure_node;
-
-		if (new_rescue_invoke_bb->use_empty()
-			&& new_rescue_rethrow_bb->use_empty()) {
-		    new_rescue_invoke_bb->eraseFromParent();
-		    new_rescue_rethrow_bb->eraseFromParent();
-		}
-		else {
-		    if (new_rescue_invoke_bb->use_empty()) {
-			new_rescue_invoke_bb->eraseFromParent();
-		    }
-		    else {
-			bb = new_rescue_invoke_bb;
-			compile_landing_pad_header();
-			BranchInst::Create(new_rescue_rethrow_bb, bb);
-		    }
-		    bb = new_rescue_rethrow_bb;
-		    compile_set_has_ensure(old_has_ensure);
-		    compile_node(node->nd_ensr);
-		    compile_rethrow_exception();
-		}
-
-		ensure_bb = old_ensure_bb;
-		ensure_pn = old_ensure_pn;
-
-		if (new_ensure_pn->getNumIncomingValues() == 0) {
-		    // there was no return in the block so we do not need
-		    // to have an ensure block to return the value
-		    new_ensure_pn->eraseFromParent();
-		    ensure_return_bb->eraseFromParent();
-		}
-		else {
-		    // some value was returned in the block so we have to
-		    // make a version of the ensure that returns this value
-		    bb = ensure_return_bb;
-		    compile_set_has_ensure(old_has_ensure);
-		    compile_node(node->nd_ensr);
-		    // the return value is the PHINode from all the return
-		    compile_simple_return(new_ensure_pn);
-		}
-
-		// we also have to compile the ensure
-		// for when the block was left without return
-		bb = ensure_normal_bb;
-		compile_set_has_ensure(old_has_ensure);
-		compile_node(node->nd_ensr);
-
-		return val;
-	    }
-	    break;
-
-	case NODE_WHILE:
-	case NODE_UNTIL:
-	    {
-		assert(node->nd_cond != NULL);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *loopBB = BasicBlock::Create(context, "loop", f);
-		BasicBlock *bodyBB = BasicBlock::Create(context, "body", f);
-		BasicBlock *exitBB = BasicBlock::Create(context, "loop_exit",
-			f);
-		BasicBlock *afterBB = BasicBlock::Create(context, "after", f);
-
-		const bool first_pass_free = node->nd_state == 0;
-
-		BranchInst::Create(first_pass_free ? bodyBB : loopBB, bb);
-
-		bb = loopBB;
-		Value *condVal = compile_node(node->nd_cond);
-
-		if (nd_type(node) == NODE_WHILE) {
-		    compile_boolean_test(condVal, bodyBB, exitBB);
-		}
-		else {
-		    compile_boolean_test(condVal, exitBB, bodyBB);
-		}
-		BranchInst::Create(afterBB, exitBB);
-
-		BasicBlock *old_current_loop_begin_bb = current_loop_begin_bb;
-		BasicBlock *old_current_loop_body_bb = current_loop_body_bb;
-		BasicBlock *old_current_loop_end_bb = current_loop_end_bb;
-		PHINode *old_current_loop_exit_val = current_loop_exit_val;
-		NODE *old_ensure_node = ensure_node;
-		BasicBlock *old_ensure_bb = ensure_bb;
-		ensure_node = NULL;
-		ensure_bb = NULL;
-
-		current_loop_begin_bb = loopBB;
-		current_loop_body_bb = bodyBB;
-		current_loop_end_bb = afterBB;
-		current_loop_exit_val = PHINode::Create(RubyObjTy,
-			"loop_exit", afterBB);
-		current_loop_exit_val->addIncoming(nilVal, exitBB);
-
-		bb = bodyBB;
-		if (node->nd_body != NULL) {
-		    compile_node(node->nd_body);
-		}
-		bodyBB = bb;
-
-		BranchInst::Create(loopBB, bb);
-
-		bb = afterBB;
-
-		Value *retval = current_loop_exit_val;
-
-		ensure_bb = old_ensure_bb;
-		ensure_node = old_ensure_node;
-		current_loop_begin_bb = old_current_loop_begin_bb;
-		current_loop_body_bb = old_current_loop_body_bb;
-		current_loop_end_bb = old_current_loop_end_bb;
-		current_loop_exit_val = old_current_loop_exit_val;
-
-		return retval;
-	    }
-	    break;
-
-	case NODE_FOR:
-	case NODE_ITER:
-	case NODE_LAMBDA:
-	    return compile_block(node);
-
-	case NODE_YIELD:
-	    return compile_yield(node);
-
-	case NODE_COLON2:
-	    {
-		assert(node->nd_mid > 0);
-		if (rb_is_const_id(node->nd_mid)) {
-		    // Constant.
-		    assert(node->nd_head != NULL);
-		    return compile_const(node->nd_mid,
-			    compile_node(node->nd_head));
-		}
-		else {
-		    // Method call.
-		    abort(); // TODO
-		}
-	    }
-	    break;
-
-	case NODE_COLON3:
-	    assert(node->nd_mid > 0);
-	    return compile_const(node->nd_mid, compile_nsobject());
-
-	case NODE_CASE:
-	    {
-		Function *f = bb->getParent();
-		BasicBlock *caseMergeBB = BasicBlock::Create(context,
-			"case_merge", f);
-
-		PHINode *pn = PHINode::Create(RubyObjTy, "case_tmp",
-			caseMergeBB);
-
-		Value *comparedToVal = NULL;
-
-		if (node->nd_head != NULL) {
-		    comparedToVal = compile_node(node->nd_head);
-                }
-
-		NODE *subnode = node->nd_body;
-
-		assert(subnode != NULL);
-		assert(nd_type(subnode) == NODE_WHEN);
-		while (subnode != NULL && nd_type(subnode) == NODE_WHEN) {
-		    NODE *valueNode = subnode->nd_head;
-		    assert(valueNode != NULL);
-
-		    BasicBlock *thenBB = BasicBlock::Create(context, "then", f);
-
-		    compile_when_arguments(valueNode, comparedToVal, thenBB);
-		    BasicBlock *nextWhenBB = bb;
-
-		    bb = thenBB;
-		    Value *thenVal = subnode->nd_body != NULL
-			? compile_node(subnode->nd_body) : nilVal;
-		    thenBB = bb;
-
-		    BranchInst::Create(caseMergeBB, thenBB);
-		    pn->addIncoming(thenVal, thenBB);
-
-		    bb = nextWhenBB;
-
-		    subnode = subnode->nd_next;
-		}
-
-		Value *elseVal = nilVal;
-		if (subnode != NULL) { // else
-		    elseVal = compile_node(subnode);
-		}
-		BranchInst::Create(caseMergeBB, bb);
-		pn->addIncoming(elseVal, bb);
-
-		bb = caseMergeBB;
-
-		return pn;
-	    }
-	    break;
-
-	case NODE_PRELUDE:
-	    {
-		assert(node->nd_head != NULL);
-		compile_node(node->nd_head);
-
-		if (node->nd_body != NULL) {
-		    compile_node(node->nd_body);
-		}
-
-		return nilVal;
-	    }
-
-	case NODE_POSTEXE:
-	    {
-		assert(node->nd_body != NULL);
-
-		Value *body = compile_node(node->nd_body);
-		assert(Function::classof(body));
-
-		Function *old_current_block_func = current_block_func;
-		NODE *old_current_block_node = current_block_node;
-		current_block_func = cast<Function>(body);
-		current_block_node = node->nd_body;
-
-		std::vector<Value *> params;
-		SEL sel = sel_registerName("at_exit");
-		params.push_back(current_self);
-		params.push_back(compile_nsobject());
-		params.push_back(compile_sel(sel));
-		params.push_back(compile_prepare_block());
-		params.push_back(ConstantInt::get(Int8Ty, DISPATCH_FCALL));
-		params.push_back(ConstantInt::get(Int32Ty, 0));
-
-		current_block_func = old_current_block_func;
-		current_block_node = old_current_block_node;
-
-		return compile_dispatch_call(params);
-	    }
-	    break;
-
-	default:
-	    compile_node_error("not implemented", node);
-    }
-
-    return NULL;
-}
-
-Value *
-RoxorCompiler::compile_node(NODE *node)
-{
-#if ROXOR_COMPILER_DEBUG
-    printf("%s:%ld ", fname, nd_line(node));
-    for (int i = 0; i < level; i++) {
-	printf("...");
-    }
-    printf("... %s\n", ruby_node_name(nd_type(node)));
-#endif
-    if (current_line != nd_line(node)) {
-	current_line = nd_line(node);
-	if (debug_mode) {
-	    compile_debug_trap();
-	}
-    }
-
-    bool old_can_interpret = can_interpret;
-    can_interpret = false;
-
-    Value *val = compile_node0(node);
-
-    if (!can_interpret) {
-#if ROXOR_COMPILER_DEBUG
-	printf("node %s can't be interpreted!\n",
-		ruby_node_name(nd_type(node)));
-#endif
-	should_interpret = false;
-    }
-    can_interpret = old_can_interpret;
-
-    return val;
-}
-
-#include <libgen.h>
-
-void
-RoxorCompiler::set_fname(const char *_fname)
-{
-    if (fname != _fname
-	    && (fname == NULL || _fname == NULL
-		|| strcmp(fname, _fname) != 0)) {
-	fname = _fname;
-	if (fname != NULL) {
-	    // Compute complete path.
-	    char path[PATH_MAX];
-	    if (*_fname == '/') {
-		strncpy(path, _fname, sizeof path);
-	    }
-	    else {
-		char cwd[PATH_MAX];
-		getcwd(cwd, sizeof cwd);
-		snprintf(path, sizeof path, "%s/%s", cwd, _fname);
-	    }
-
-	    // Split the path into 2 parts: the directory and the base.
-	    char *dir = dirname(path);
-	    char *base = basename(path);
-
-	    // LLVM (llc) really doesn't like when you pass empty strings for
-	    // these values and might later throw a cryptic C++ exception that
-	    // will take hours to investigate. How fun.
-	    assert(strlen(dir) > 0);
-	    assert(strlen(base) > 0);
-
-#if !defined(LLVM_TOT)
-	    debug_info->createCompileUnit(DW_LANG_Ruby, base, dir,
-		    RUBY_DESCRIPTION, true, "", 1);
-	    debug_compile_unit = DICompileUnit(debug_info->getCU());
-#else
-	    debug_compile_unit = debug_info->CreateCompileUnit(DW_LANG_Ruby,
-		    base, dir, RUBY_DESCRIPTION, false, false, "");
-#endif
-	}
-    }
-}
-
-Function *
-RoxorCompiler::compile_main_function(NODE *node, bool *can_interpret_p)
-{
-    save_compiler_state();
-    reset_compiler_state();
-
-    should_interpret = true;
-    can_interpret = false;
-
-    Value *val = compile_node(node);
-    assert(Function::classof(val));
-    Function *func =  cast<Function>(val);
-
-    if (can_interpret_p != NULL) {
-	*can_interpret_p = should_interpret;
-    }
-    restore_compiler_state();
-    return func;
-}
-
-Function *
-RoxorAOTCompiler::compile_main_function(NODE *node, bool *can_be_interpreted)
-{
-    Value *val = compile_node(node);
-    assert(Function::classof(val));
-    Function *func = cast<Function>(val);
-    func->setLinkage(GlobalValue::ExternalLinkage);
-
-    Function *init_func = compile_init_function(); 
-    BasicBlock::InstListType &list = func->getEntryBlock().getInstList();
-    list.insert(list.begin(), CallInst::Create(init_func, ""));
-
-    return func;
-}
-
-Function *
-RoxorAOTCompiler::compile_init_function(void)
-{
-    reset_compiler_state();
-
-    FunctionType *ft = FunctionType::get(VoidTy, false);
-    Function *f = Function::Create(ft, GlobalValue::InternalLinkage,
-	    "init_func", module);
-
-    bb = BasicBlock::Create(context, "MainBlock", f);
-
-    // Compile constant caches.
-
-    Function *getConstCacheFunc = cast<Function>(module->getOrInsertFunction(
-		"rb_vm_get_constant_cache",
-		PtrTy, PtrTy, NULL));
-
-    for (std::map<ID, GlobalVariable *>::iterator i = ccaches.begin();
-	    i != ccaches.end();
-	    ++i) {
-
-	ID name = i->first;
-	GlobalVariable *gvar = i->second;
-
-	Value *val = CallInst::Create(getConstCacheFunc,
-		compile_const_global_string(rb_id2name(name)), "", bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Compile selectors.
-
-    Function *registerSelFunc = get_function("sel_registerName");
-
-    for (std::map<SEL, GlobalVariable *>::iterator i = sels.begin();
-	    i != sels.end();
-	    ++i) {
-
-	SEL sel = i->first;
-	GlobalVariable *gvar = i->second;
-
-	Value *val = CallInst::Create(registerSelFunc,
-		compile_const_global_string(sel_getName(sel)), "", bb);
-	val = new BitCastInst(val, PtrTy, "", bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Compile literals.
-
-    Function *name2symFunc =
-	cast<Function>(module->getOrInsertFunction("rb_name2sym",
-		    RubyObjTy, PtrTy, NULL));
-
-    Function *newRegexp2Func =
-	cast<Function>(module->getOrInsertFunction(
-		    "rb_unicode_regex_new_retained",
-		    RubyObjTy, PointerType::getUnqual(Int16Ty), Int32Ty,
-		    Int32Ty, NULL));
-
-    Function *newBignumFunc =
-	cast<Function>(module->getOrInsertFunction("rb_bignum_new_retained",
-		    RubyObjTy, PtrTy, NULL));
-
-    Function *getClassFunc =
-	cast<Function>(module->getOrInsertFunction("objc_getClass",
-		    RubyObjTy, PtrTy, NULL));
-
-    for (std::map<VALUE, GlobalVariable *>::iterator i = literals.begin();
-	 i != literals.end();
-	 ++i) {
-
-	VALUE val = i->first;
-	GlobalVariable *gvar = i->second;
-	Value *lit_val = NULL;
-
-	switch (TYPE(val)) {
-	    case T_CLASS:
-		{
-		    // This strange literal seems to be only emitted for 
-		    // `for' loops.
-		    const char *cname = class_getName((Class)val);
-		    lit_val = CallInst::Create(getClassFunc,
-			    compile_const_global_string(cname), "", bb);
-		}
-		break;
-
-	    case T_REGEXP:
-		{
-		    const UChar *chars = NULL;
-		    int32_t chars_len = 0;
-
-		    regexp_get_uchars(val, &chars, &chars_len);
-
-		    Value *re_str;
-		    if (chars_len == 0) {
-			re_str = ConstantPointerNull::get(
-				PointerType::getUnqual(Int16Ty));
-		    }
-		    else {
-			re_str = compile_const_global_ustring(chars,
-				chars_len);
-		    }
-
-		    Value *args[] = {
-			re_str,
-			ConstantInt::get(Int32Ty, chars_len),
-			ConstantInt::get(Int32Ty, rb_reg_options(val))
-		    };
-		    lit_val = CallInst::Create(newRegexp2Func, args, args + 3,
-			    "", bb);
-		}
-		break;
-
-	    case T_SYMBOL:
-		{
-		    const char *symname = rb_id2name(SYM2ID(val));
-		    lit_val = CallInst::Create(name2symFunc,
-			    compile_const_global_string(symname), "", bb);
-		}
-		break;
-
-	    case T_BIGNUM:
-		{
-		    const char *bigstr = RSTRING_PTR(rb_big2str(val, 10));
-		    lit_val = CallInst::Create(newBignumFunc,
-			    compile_const_global_string(bigstr), "", bb);
-		}
-		break;
-
-	    default:
-		if (rb_obj_is_kind_of(val, rb_cRange)) {
-		    VALUE beg = 0, end = 0;
-		    bool exclude_end = false;
-		    rb_range_extract(val, &beg, &end, &exclude_end);
-
-		    lit_val = compile_range(ConstantInt::get(RubyObjTy, beg),
-			    ConstantInt::get(RubyObjTy, end),
-			    exclude_end, true);	
-		}
-		else {
-		    printf("unrecognized literal `%s' (class `%s' type %d)\n",
-			    RSTRING_PTR(rb_inspect(val)),
-			    rb_obj_classname(val),
-			    TYPE(val));
-		    abort();
-		}
-		break;
-	}
-
-	assert(lit_val != NULL);
-	new StoreInst(lit_val, gvar, bb);
-    }
-
-    // Compile IDs.
-
-    Function *rbInternFunc = cast<Function>(module->getOrInsertFunction(
-		"rb_intern",
-		IntTy, PtrTy, NULL));
-
-    for (std::map<ID, GlobalVariable *>::iterator i = ids.begin();
-	    i != ids.end();
-	    ++i) {
-
-	ID name = i->first;
-	GlobalVariable *gvar = i->second;
-
-	Value *val = CallInst::Create(rbInternFunc,
-		compile_const_global_string(rb_id2name(name)), "", bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Compile global entries.
-
-    Function *globalEntryFunc = cast<Function>(module->getOrInsertFunction(
-		"rb_global_entry",
-		PtrTy, IntTy, NULL));
-
-    for (std::map<ID, GlobalVariable *>::iterator i = global_entries.begin();
-	    i != global_entries.end();
-	    ++i) {
-
-	ID name = i->first;
-	GlobalVariable *gvar = i->second;
-
-	Value *val = CallInst::Create(rbInternFunc,
-		compile_const_global_string(rb_id2name(name)), "", bb);
-	val = CallInst::Create(globalEntryFunc, val, "", bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Compile constant class references.
-
-    for (std::vector<GlobalVariable *>::iterator i = class_gvars.begin();
-	    i != class_gvars.end();
-	    ++i) {
-
-	GlobalVariable *gvar = *i;
-	Value *val = CallInst::Create(getClassFunc,
-		compile_const_global_string(gvar->getName().str().c_str()),
-		"",bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Instance variable slots.
-
-    Function *ivarSlotAlloc = cast<Function>(module->getOrInsertFunction(
-		"rb_vm_ivar_slot_allocate",
-		PtrTy, NULL));
-
-    for (std::vector<GlobalVariable *>::iterator i = ivar_slots.begin();
-	    i != ivar_slots.end();
-	    ++i) {
-
-	GlobalVariable *gvar = *i;
-	Value *val = CallInst::Create(ivarSlotAlloc, "", bb);
-	new StoreInst(val, gvar, bb);
-    }
-
-    // Stubs.
-
-    Function *addStub = cast<Function>(module->getOrInsertFunction(
-		"rb_vm_add_stub", VoidTy, PtrTy, PtrTy, Int8Ty, NULL));
-
-    for (std::vector<std::string>::iterator i = c_stubs.begin();
-	    i != c_stubs.end();
-	    ++i) {
-
-	const char *types = i->c_str();
-	try {
-	    Value *args[] = {
-		compile_const_global_string(types),
-		new BitCastInst(compile_stub(types, false, TypeArity(types),
-			    false), PtrTy, "", bb),
-		ConstantInt::get(Int8Ty, 0)
-	    };
-	    CallInst::Create(addStub, args, args + 3, "", bb);
-	}
-	catch (...) {}
-    }
-
-    for (std::vector<std::string>::iterator i = objc_stubs.begin();
-	    i != objc_stubs.end();
-	    ++i) {
-
-	const char *types = i->c_str();
-	try {
-	    Value *args[] = {
-		compile_const_global_string(types),
-		new BitCastInst(compile_stub(types, false,
-			    TypeArity(types) - 2, true), PtrTy, "", bb),
-		ConstantInt::get(Int8Ty, 1)
-	    };
-	    CallInst::Create(addStub, args, args + 3, "", bb);
-	}
-	catch (...) {}
-    }
-
-    ReturnInst::Create(context, bb);
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_read_attr(ID name)
-{
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy, RubyObjTy, PtrTy, NULL));
-
-    Function::arg_iterator arg = f->arg_begin();
-    current_self = arg++;
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    ReturnInst::Create(context, compile_ivar_get(name), bb);
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_write_attr(ID name)
-{
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-	RubyObjTy, RubyObjTy, PtrTy, RubyObjTy, NULL));
-
-    Function::arg_iterator arg = f->arg_begin();
-    current_self = arg++;
-    arg++; // sel
-    Value *new_val = arg++; // 1st argument
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    Value *val;
-    if (rb_objc_enable_ivar_set_kvo_notifications) {
-	VALUE tmp = rb_id2str(name);
- 	VALUE str = rb_str_substr(tmp, 1, rb_str_chars_len(tmp) - 1);
-
-	Value *args[] = {
-	    current_self,
-	    compile_immutable_literal(str)
-	};
-
-	if (willChangeValueFunc == NULL) {
-	    willChangeValueFunc =
-		cast<Function>(module->getOrInsertFunction(
-			    "rb_objc_willChangeValueForKey",
-			    VoidTy, RubyObjTy, RubyObjTy, NULL));
-	}
-	CallInst::Create(willChangeValueFunc, args, args + 2, "", bb);
-
-	val = compile_ivar_assignment(name, new_val);
-
-	if (didChangeValueFunc == NULL) {
-	    didChangeValueFunc =
-		cast<Function>(module->getOrInsertFunction(
-			    "rb_objc_didChangeValueForKey",
-			    VoidTy, RubyObjTy, RubyObjTy, NULL));
-	}
-	CallInst::Create(didChangeValueFunc, args, args + 2, "", bb);
-    }
-    else {
-	val = compile_ivar_assignment(name, new_val);
-    }
-
-    ReturnInst::Create(context, val, bb);
-
-    return f;
-}
-
-static inline void
-convert_error(const char type, VALUE val)
-{
-    rb_raise(rb_eTypeError,
-	     "cannot convert object `%s' (%s) to Objective-C type `%c'",
-	     RSTRING_PTR(rb_inspect(val)),
-	     rb_obj_classname(val),
-	     type); 
-}
-
-void
-RoxorCompiler::compile_get_struct_fields(Value *val, Value *buf,
-					 rb_vm_bs_boxed_t *bs_boxed)
-{
-    if (getStructFieldsFunc == NULL) {
-	getStructFieldsFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_get_struct_fields",
-		    VoidTy, RubyObjTy, RubyObjPtrTy, PtrTy, NULL));
-    }
-
-    Value *args[] = {
-	val,
-	buf,
-	compile_const_pointer(bs_boxed)
-    };
-    CallInst::Create(getStructFieldsFunc, args, args + 3, "", bb);
-}
-
-extern "C"
-void *
-rb_vm_get_opaque_data(VALUE rval, rb_vm_bs_boxed_t *bs_boxed, void **ocval)
-{
-    void *data = NULL;
-    if (rval != Qnil) {
-	if (!rb_obj_is_kind_of(rval, bs_boxed->klass)) {
-	    rb_raise(rb_eTypeError,
-		    "cannot convert `%s' (%s) to opaque type %s",
-		    RSTRING_PTR(rb_inspect(rval)),
-		    rb_obj_classname(rval),
-		    rb_class2name(bs_boxed->klass));
-	}
-	Data_Get_Struct(rval, VALUE, data);
-    }
-    if (ocval != NULL) {
-	*ocval = data;
-    }
-    return data;
-}
-
-Value *
-RoxorCompiler::compile_get_opaque_data(Value *val, rb_vm_bs_boxed_t *bs_boxed,
-	Value *slot)
-{
-    if (getOpaqueDataFunc == NULL) {
-	// void *rb_vm_get_opaque_data(VALUE rval, rb_vm_bs_boxed_t *bs_boxed,
-	//	void **ocval)
-	getOpaqueDataFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_get_opaque_data",
-		    PtrTy, RubyObjTy, PtrTy, PtrPtrTy, NULL));
-    }
-
-    Value *args[] = {
-	val,
-	compile_const_pointer(bs_boxed),
-	slot
-    };
-    return compile_protected_call(getOpaqueDataFunc, args, args + 3);
-}
-
-Value *
-RoxorCompiler::compile_get_cptr(Value *val, const char *type, Value *slot)
-{
-    Value *args[] = {
-	val,
-	compile_const_global_string(type),
-	new BitCastInst(slot, PtrPtrTy, "", bb)
-    };
-    return compile_protected_call(getPointerPtrFunc, args, args + 3);
-}
-
-Value *
-RoxorCompiler::compile_lambda_to_funcptr(const char *type,
-	Value *val, Value *slot, bool is_block)
-{
-    GlobalVariable *proc_gvar = NULL;
-    if (!is_block) {
-	// When compiling a function pointer closure, the Proc object we
-	// want to call must be preserved as a global variable.
-	// This isn't needed for C blocks because we can retrieve the Proc
-	// object from the block literal argument.
-	proc_gvar = new GlobalVariable(*RoxorCompiler::module,
-		RubyObjTy, false, GlobalValue::InternalLinkage,
-		nilVal, "");
-	new StoreInst(val, proc_gvar, bb);
-    }
-
-    const size_t buf_len = strlen(type + 1) + 1;
-    assert(buf_len > 1);
-    char *buf = (char *)malloc(buf_len);
-
-    const char *p = GetFirstType(type + 1, buf, buf_len);
-    const Type *ret_type = convert_type(buf);
-    int argc = 0;
-
-    std::vector<std::string> arg_ctypes;
-    std::vector<const Type *> arg_types;
-
-    if (is_block) {
-	// The block literal argument.
-	arg_types.push_back(PtrTy);	
-    }
-
-    while (*p != _MR_C_LAMBDA_E) {
-	p = GetFirstType(p, buf, buf_len);
-	arg_ctypes.push_back(std::string(buf));
-	arg_types.push_back(convert_type(buf));
-	argc++;
-    }
-    FunctionType *ft = FunctionType::get(ret_type, arg_types,
-	    false);
-
-    // ret_type stub(arg1, arg2, ...)
-    // {
-    //     VALUE *argv = alloc(argc);
-    //     argv[0] = arg1;
-    //     argv[1] = arg2;
-    //     return rb_proc_check_and_call(procval, argc, argv);
-    // }
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		ft));
-
-    BasicBlock *oldbb = bb;
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    Function::arg_iterator arg = f->arg_begin();
-    Value *block_lit = NULL;
-    if (is_block) {
-	block_lit = arg++;
-    }
-
-    Value *argv;
-    if (argc == 0) {
-	argv = new BitCastInst(compile_const_pointer(NULL),
-		RubyObjPtrTy, "", bb);
-    }
-    else {
-	argv = new AllocaInst(RubyObjTy, ConstantInt::get(Int32Ty, argc),
-		"", bb);
-	const int off = is_block ? 1 : 0;
-	for (int i = 0; i < argc; i++) {
-	    Value *index = ConstantInt::get(Int32Ty, i);
-	    Value *aslot = GetElementPtrInst::Create(argv, index, "", bb);
-	    Value *rval = compile_conversion_to_ruby(arg_ctypes[i].c_str(),
-		    arg_types[i + off], arg++);
-	    new StoreInst(rval, aslot, bb);
-	}
-    }
-
-    Value *proc;
-    if (is_block) {
-	block_lit = new BitCastInst(block_lit,
-		PointerType::getUnqual(BlockLiteralTy), "", bb);
-	proc = CallInst::Create(blockProcFunc, block_lit, "", bb);
-    }
-    else {
-	proc = new LoadInst(proc_gvar, "", bb);
-    }
-
-    // VALUE rb_proc_check_and_call(
-    //	VALUE self, int argc, VALUE *argv
-    // )
-    Function *proc_call_f =
-	cast<Function>(module->getOrInsertFunction(
-		    "rb_proc_check_and_call",
-		    RubyObjTy,
-		    RubyObjTy, Int32Ty, RubyObjPtrTy, NULL));
-
-    Value *args[] = {
-	proc,
-	ConstantInt::get(Int32Ty, argc),
-	argv
-    };
-    Value *ret_val = compile_protected_call(proc_call_f, args,
-	    args + 3);
-
-    if (ret_type != VoidTy) {
-	GetFirstType(type + 1, buf, buf_len);
-	ret_val = compile_conversion_to_c(buf, ret_val,
-		new AllocaInst(ret_type, "", bb));
-	ReturnInst::Create(context, ret_val, bb);
-    }
-    else {
-	ReturnInst::Create(context, bb);
-    }
-
-    bb = oldbb;
-    free(buf);
-    return new BitCastInst(f, PtrTy, "", bb);
-}
-
-static void
-decompose_ary_type(const char *type, long *size_p, char *elem_type_p, 
-	const size_t elem_type_len)
-{
-    // Syntax is [8S] for `short foo[8]'.
-    // First, let's grab the size.
-    char buf[100];
-    unsigned int n = 0;
-    const char *p = type + 1;
-    while (isdigit(*p)) {
-	assert(n < (sizeof buf) - 1);
-	buf[n++] = *p;
-	p++;
-    }
-    assert(n > 0);
-    buf[n] = '\0';
-    const long size = atol(buf);
-    assert(size > 0);
-    if (size_p != NULL) {
-	*size_p = size;
-    }
-
-    // Second, the element type.
-    n = 0;
-    while (*p != _C_ARY_E) {
-	assert(n < (sizeof buf) - 1);
-	buf[n++] = *p;
-	p++;
-    }
-    assert(n > 0);
-    buf[n] = '\0';
-    if (elem_type_p != NULL) {
-	strlcpy(elem_type_p, buf, elem_type_len);
-    }
-}
-
-Value *
-RoxorCompiler::compile_conversion_to_c(const char *type, Value *val,
-	Value *slot)
-{
-    type = SkipTypeModifiers(type);
-
-    if (type[0] == _C_PTR && type[1] != _C_VOID
-	    && GET_CORE()->find_bs_cftype(type) != NULL) {
-	type = "@";
-    }
-
-    Function *func = NULL;
-
-    switch (*type) {
-	case _C_ID:
-	case _C_CLASS:
-	    func = rvalToOcvalFunc;
-	    break;
-
-	case _C_BOOL:
-	    func = rvalToBoolFunc;
-	    break;
-
-	case _C_CHR:
-	    func = rvalToCharFunc;
-	    break;
-
-	case _C_UCHR:
-	    func = rvalToUcharFunc;
-	    break;
-
-	case _C_SHT:
-	    func = rvalToShortFunc;
-	    break;
-
-	case _C_USHT:
-	    func = rvalToUshortFunc;
-	    break;
-
-	case _C_INT:
-	    func = rvalToIntFunc;
-	    break;
-
-	case _C_UINT:
-	    func = rvalToUintFunc;
-	    break;
-
-	case _C_LNG:
-	    func = rvalToLongFunc;
-	    break;
-
-	case _C_ULNG:
-	    func = rvalToUlongFunc;
-	    break;
-
-	case _C_LNG_LNG:
-	    func = rvalToLongLongFunc;
-	    break;
-
-	case _C_ULNG_LNG:
-	    func = rvalToUlongLongFunc;
-	    break;
-
-	case _C_FLT:
-	    func = rvalToFloatFunc;
-	    break;
-
-	case _C_DBL:
-	    func = rvalToDoubleFunc;
-	    break;
-
-	case _C_SEL:
-	    func = rvalToSelFunc;
-	    break;
-
-	case _C_CHARPTR:
-	    func = rvalToCharPtrFunc;
-	    break;
-
-	case _C_STRUCT_B:
-	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
-		if (bs_boxed != NULL) {
-		    if (bs_boxed->as.s->opaque) {
-			// Structure is opaque, we just copy the data from
-			// the opaque object into the slot.
-			Value *data = compile_get_opaque_data(val, bs_boxed,
-				ConstantPointerNull::get(PtrPtrTy));
-			data = new BitCastInst(data,
-				PointerType::getUnqual(convert_type(type)), 
-				"", bb);
-			new StoreInst(new LoadInst(data, "", bb), slot, bb);
-		    }
-		    else {
-			// Retrieve all fields (as Ruby objects).
-			Value *fields = new AllocaInst(RubyObjTy,
-				ConstantInt::get(Int32Ty,
-				    bs_boxed->as.s->fields_count), "", bb);
-			compile_get_struct_fields(val, fields, bs_boxed);
-
-			// Convert each field to C inside the slot memory.
-			for (unsigned i = 0; i < bs_boxed->as.s->fields_count;
-				i++) {
-
-			    const char *ftype = bs_boxed->as.s->fields[i].type;
-
-			    // Load field VALUE.
-			    Value *fval = GetElementPtrInst::Create(fields,
-				    ConstantInt::get(Int32Ty, i), "", bb);
-			    fval = new LoadInst(fval, "", bb);
-
-			    // Get a pointer to the struct field. The extra 0
-			    // is needed because we are dealing with a pointer
-			    // to the structure.
-			    Value *slot_idx[] = {
-				ConstantInt::get(Int32Ty, 0),
-				ConstantInt::get(Int32Ty, i)
-			    };
-			    Value *fslot = GetElementPtrInst::Create(slot,
-				    slot_idx, slot_idx + 2, "", bb);
-
-			    RoxorCompiler::compile_conversion_to_c(ftype, fval,
-				    fslot);
-			}
-		    }
-
-		    if (GET_CORE()->is_large_struct_type(bs_boxed->type)) {
-			// If this structure is too large, we need to pass its
-			// address and not its value, to conform to the ABI.
-			return slot;
-		    }
-		    return new LoadInst(slot, "", bb);
-		}
-	    }
-	    break;
-
-        case _MR_C_LAMBDA_B:
-	    {
-		type++;
-		const bool is_block = *type == _MR_C_LAMBDA_BLOCK;
-
-		Value *funcptr = compile_lambda_to_funcptr(type, val, slot,
-			is_block);
-		if (!is_block) {
-		    // A pure function pointer, let's pass it.
-		    return funcptr;
-		}
-
-		// A C-level block. We allocate on the auto heap the literal
-		// structure following the ABI, initialize it then pass
-		// a pointer to it.
-		Value *block_lit =
-		    compile_xmalloc(GET_CORE()->get_sizeof(BlockLiteralTy));
-		Value *args[] = {
-		    new BitCastInst(block_lit,
-			    PointerType::getUnqual(BlockLiteralTy), "", bb),
-		    funcptr,
-		    val
-		};
-		CallInst::Create(initBlockFunc, args, args + 3, "", bb);
-		return new BitCastInst(block_lit, PtrTy, "", bb);
-	    }
-	    break;
-
-	case _C_PTR:
-	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_opaque(type);
-		if (bs_boxed != NULL) {
-		    return compile_get_opaque_data(val, bs_boxed, slot);
-		}
-		return compile_get_cptr(val, type, slot);
-	    }
-	    break;
-
-	case _C_ARY_B:
-	    {
-		const ArrayType *ary_type = cast<ArrayType>(convert_type(type));
-		const Type *elem_type = ary_type->getElementType();
-		const unsigned elem_count = ary_type->getNumElements();
-
-		char elem_c_type[100];
-		decompose_ary_type(type, NULL, elem_c_type,
-			sizeof elem_c_type);
-
-		Value *elem_count_val = ConstantInt::get(Int32Ty, elem_count);
-		Value *args[] = {
-		    val,
-		    elem_count_val	
-		};
-		val = CallInst::Create(checkArrayFunc, args, args + 2, "", bb);
-
-		slot = new BitCastInst(slot, PointerType::getUnqual(elem_type),
-			"", bb);
-
-		for (unsigned i = 0; i < elem_count; i++) {
-		    Value *idx = ConstantInt::get(Int32Ty, i);
-		    Value *args[] = {
-			val,
-			idx	
-		    };
-		    Value *elem = CallInst::Create(entryArrayFunc,
-			    args, args + 2, "", bb);
-		    Value *elem_slot = GetElementPtrInst::Create(slot, idx,
-			    "", bb);
-		    compile_conversion_to_c(elem_c_type, elem, elem_slot);
-		}
-
-		return new BitCastInst(slot, PointerType::getUnqual(ary_type),
-			"", bb);
-	    }
-	    break;
-    }
-
-    if (func == NULL) {
-	rb_raise(rb_eTypeError, "unrecognized compile type `%s' to C", type);
-    }
-
-    Value *args[] = {
-	val,
-	slot
-    };
-    CallInst::Create(func, args, args + 2, "", bb);
-    return new LoadInst(slot, "", bb);
-}
-
-extern "C"
-VALUE
-rb_vm_new_struct(VALUE klass, int argc, ...)
-{
-    assert(argc > 0);
-
-    va_list ar;
-    va_start(ar, argc);
-    VALUE *data = (VALUE *)xmalloc_ptrs(argc * sizeof(VALUE));
-    for (int i = 0; i < argc; ++i) {
-	VALUE field = va_arg(ar, VALUE);
-	GC_WB(&data[i], field);
-    }
-    va_end(ar);
-
-    return Data_Wrap_Struct(klass, NULL, NULL, data);
-}
-
-extern "C"
-VALUE
-rb_vm_new_opaque(VALUE klass, void *val)
-{
-    if (val == NULL) {
-	return Qnil;
-    }
-    return Data_Wrap_Struct(klass, NULL, NULL, val);
-}
-
-extern "C"
-VALUE
-rb_vm_new_pointer(const char *type, void *val)
-{
-    return val == NULL ? Qnil : rb_pointer_new(type, val, 0);
-}
-
-Value *
-RoxorCompiler::compile_new_struct(Value *klass, std::vector<Value *> &fields)
-{
-    if (newStructFunc == NULL) {
-	// VALUE rb_vm_new_struct(VALUE klass, int argc, ...)
-	std::vector<const Type *> types;
-	types.push_back(RubyObjTy);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
-
-	newStructFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_new_struct", ft));
-    }
-
-    Value *argc = ConstantInt::get(Int32Ty, fields.size());
-    fields.insert(fields.begin(), argc);
-    fields.insert(fields.begin(), klass);
-
-    return CallInst::Create(newStructFunc, fields.begin(), fields.end(),
-	    "", bb); 
-}
-
-Value *
-RoxorCompiler::compile_new_opaque(Value *klass, Value *val)
-{
-    if (newOpaqueFunc == NULL) {
-	// VALUE rb_vm_new_opaque(VALUE klass, void *val)
-	newOpaqueFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_new_opaque", RubyObjTy, RubyObjTy, PtrTy, NULL));
-    }
-
-    Value *args[] = {
-	klass,
-	val
-    };
-    return CallInst::Create(newOpaqueFunc, args, args + 2, "", bb); 
-}
-
-Value *
-RoxorCompiler::compile_new_pointer(const char *type, Value *val)
-{
-    if (newPointerFunc == NULL) {
-	newPointerFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_new_pointer", RubyObjTy, PtrTy, PtrTy, NULL));
-    }
-
-    Value *args[] = {
-	compile_const_global_string(type),
-	val
-    };
-    return CallInst::Create(newPointerFunc, args, args + 2, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_xmalloc(size_t len)
-{
-    if (xmallocFunc == NULL) {
-	// void *ruby_xmalloc(size_t len);
-	xmallocFunc = cast<Function>(module->getOrInsertFunction(
-		    "ruby_xmalloc", PtrTy, Int64Ty, NULL));
-    }
-
-    return CallInst::Create(xmallocFunc, ConstantInt::get(Int64Ty, len),
-	    "", bb);
-}
-
-Value *
-RoxorCompiler::compile_conversion_to_ruby(const char *type,
-	const Type *llvm_type, Value *val)
-{
-    type = SkipTypeModifiers(type);
-
-    if (type[0] == _C_PTR && type[1] != _C_VOID
-	    && GET_CORE()->find_bs_cftype(type) != NULL) {
-	type = "@";
-    }
-
-    Function *func = NULL;
-
-    switch (*type) {
-	case _C_VOID:
-	    return nilVal;
-
-	case _C_BOOL:
-	    val = new ICmpInst(*bb, ICmpInst::ICMP_EQ, val,
-		    ConstantInt::get(Int8Ty, 1));
-	    return SelectInst::Create(val, trueVal, falseVal, "", bb);
-
-	case _C_ID:
-	case _C_CLASS:
-	    func = ocvalToRvalFunc;
-	    break;
-
-	case _C_CHR:
-	    func = charToRvalFunc;
-	    break;
-
-	case _C_UCHR:
-	    func = ucharToRvalFunc;
-	    break;
-
-	case _C_SHT:
-	    func = shortToRvalFunc;
-	    break;
-
-	case _C_USHT:
-	    func = ushortToRvalFunc;
-	    break;
-
-	case _C_INT:
-	    func = intToRvalFunc;
-	    break;
-
-	case _C_UINT:
-	    func = uintToRvalFunc;
-	    break;
-
-	case _C_LNG:
-	    func = longToRvalFunc;
-	    break;
-
-	case _C_ULNG:
-	    func = ulongToRvalFunc;
-	    break;
-
-	case _C_LNG_LNG:
-	    func = longLongToRvalFunc;
-	    break;
-
-	case _C_ULNG_LNG:
-	    func = ulongLongToRvalFunc;
-	    break;
-
-	case _C_FLT:
-	    func = floatToRvalFunc;
-	    break;
-
-	case _C_DBL:
-	    func = doubleToRvalFunc;
-	    break;
-
-	case _C_SEL:
-	    func = selToRvalFunc;
-	    break;
-
-	case _C_CHARPTR:
-	    func = charPtrToRvalFunc;
-	    break;
-
-	case _C_STRUCT_B:
-	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
-		if (bs_boxed != NULL) {
-		    Value *klass = ConstantInt::get(RubyObjTy, bs_boxed->klass);
-		    if (bs_boxed->as.s->opaque) {
-			// Structure is opaque, we make a copy.
-			const size_t s = GET_CORE()->get_sizeof(llvm_type);
-			Value *slot = compile_xmalloc(s);
-			slot = new BitCastInst(slot,
-				PointerType::getUnqual(llvm_type), "", bb);
-			new StoreInst(val, slot, bb);
-			slot = new BitCastInst(slot, PtrTy, "", bb);
-			return compile_new_opaque(klass, slot);
-		    }
-		    else {
-			// Convert every field into a Ruby type, then box them.
-			std::vector<Value *> params;
-			for (unsigned i = 0; i < bs_boxed->as.s->fields_count;
-				i++) {
-
-			    const char *ftype = bs_boxed->as.s->fields[i].type;
-			    const Type *llvm_ftype = convert_type(ftype);
-			    Value *fval = ExtractValueInst::Create(val, i, "",
-				    bb);
-			    params.push_back(compile_conversion_to_ruby(ftype,
-					llvm_ftype, fval));
-			}
-			return compile_new_struct(klass, params);
-		    }
-		}
-	    }
-	    break;
-
-	case _C_PTR:
-	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_opaque(type);
-		if (bs_boxed != NULL) {
-		    Value *klass = ConstantInt::get(RubyObjTy, bs_boxed->klass);
-		    return compile_new_opaque(klass, val);
-		}
-
-		return compile_new_pointer(type + 1, val);
-	    }
-	    break;
-
-	case _C_ARY_B:
-	    {
-		long elem_count = 0;
-		char elem_c_type[100];
-		decompose_ary_type(type, &elem_count, elem_c_type,
-			sizeof elem_c_type);
-		const Type *elem_type = convert_type(elem_c_type);
-
-		const bool is_ary = ArrayType::classof(val->getType());
-		if (!is_ary) {
-		    val = new BitCastInst(val,
-			    PointerType::getUnqual(elem_type), "", bb);
-		}
-
-		Value *ary = CallInst::Create(newArrayFunc,
-			ConstantInt::get(Int32Ty, elem_count), "", bb);
-		for (long i = 0; i < elem_count; i++) {
-		    Value *idx = ConstantInt::get(Int32Ty, i);
-		    Value *elem;
-		    if (is_ary) {
-			elem = ExtractValueInst::Create(val, i, "", bb);
-		    }
-		    else {
-			Value *slot = GetElementPtrInst::Create(val, idx, "",
-				bb);
-			elem = new LoadInst(slot, "", bb);
-		    }
-		    Value *args[] = {
-			ary,
-			idx,
-			compile_conversion_to_ruby(elem_c_type, elem_type, elem)
-		    };
-		    CallInst::Create(asetArrayFunc, args, args + 3, "", bb);
-		}
-		return ary;
-	    }
-	    break;
-    }
-
-    if (func == NULL) {
-	rb_raise(rb_eTypeError, "unrecognized compile type `%s' to Ruby", type);
-	abort();
-    }
- 
-    return CallInst::Create(func, val, "", bb);
-}
-
-const Type *
-RoxorCompiler::convert_type(const char *type)
-{
-    type = SkipTypeModifiers(type);
-
-    switch (*type) {
-	case _C_VOID:
-	    return VoidTy;
-
-	case _C_ID:
-	case _C_CLASS:
-	    return PtrTy;
-
-	case _C_SEL:
-	case _C_CHARPTR:
-	case _C_PTR:
-	    return PtrTy;
-
-	case _C_BOOL:
-	case _C_UCHR:
-	case _C_CHR:
-	    return Int8Ty;
-
-	case _C_SHT:
-	case _C_USHT:
-	    return Int16Ty;
-
-	case _C_INT:
-	case _C_UINT:
-	    return Int32Ty;
-
-	case _C_LNG:
-	case _C_ULNG:
-#if __LP64__
-	    return Int64Ty;
-#else
-	    return Int32Ty;
-#endif
-
-	case _C_FLT:
-	    return FloatTy;
-
-	case _C_DBL:
-	    return DoubleTy;
-
-	case _C_LNG_LNG:
-	case _C_ULNG_LNG:
-	    return Int64Ty;
-
-	case _C_BFLD:
-	    {
-		// Syntax is `b3' for `unsigned foo:3'. 
-		const long size = atol(type + 1);
-		if (size <= 0) {
-		    rb_raise(rb_eTypeError, "invalid bitfield type: %s",
-			    type);	
-		}
-		return ArrayType::get(BitTy, size);
-	    }
-	    break;
-
-	case _C_ARY_B:
-	    {
-		char buf[100];
-		long size = 0;
-		decompose_ary_type(type, &size, buf, sizeof buf);
-		const Type *type = convert_type(buf);
-		// Now, we can return the array type.
-		return ArrayType::get(type, size);
-	    }
-	    break;
-
-	case _MR_C_LAMBDA_B:
-	    return PtrTy;
-
-	case _C_STRUCT_B:
-	    rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
-	    if (bs_boxed != NULL) {
-		if (bs_boxed->type == NULL) {
-		    std::vector<const Type *> s_types;
-		    for (unsigned i = 0; i < bs_boxed->as.s->fields_count;
-			 i++) {
-
-			const char *ftype = bs_boxed->as.s->fields[i].type;
-			s_types.push_back(convert_type(ftype));
-		    }
-		    bs_boxed->type = StructType::get(context, s_types);
-		    assert(bs_boxed->type != NULL);
-		}
-		return bs_boxed->type;
-	    }
-	    break;
-    }
-
-    rb_raise(rb_eTypeError, "unrecognized runtime type `%s'", type);
-}
-
-Function *
-RoxorCompiler::compile_stub(const char *types, bool variadic, int min_argc,
-	bool is_objc)
-{
-    save_compiler_state();
-    reset_compiler_state();
-
-    Function *f = NULL;
-    try {
-
-    if (is_objc) {
-	// VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
-	// {
-	//     return (*imp)(self, sel, argv[0], argv[1], ...);
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		    RubyObjTy,
-		    PtrTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
-    }
-    else {
-	// VALUE stub(IMP imp, int argc, VALUE *argv)
-	// {
-	//     return (*imp)(argv[0], argv[1], ...);
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		    RubyObjTy,
-		    PtrTy, Int32Ty, RubyObjPtrTy,
-		    NULL));
-    }
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    Function::arg_iterator arg = f->arg_begin();
-    Value *imp_arg = arg++;
-
-    std::vector<const Type *> f_types;
-    std::vector<Value *> params;
-
-    const size_t buf_len = strlen(types) + 1;
-    assert(buf_len > 1);
-    char *buf = (char *)malloc(buf_len);
-
-    // retval
-    const char *p = GetFirstType(types, buf, buf_len);
-    const Type *ret_type = convert_type(buf);
-
-    Value *sret = NULL;
-    if (GET_CORE()->is_large_struct_type(ret_type)) {
-	// We are returning a large struct, we need to pass a pointer as the
-	// first argument to the structure data and return void to conform to
-	// the ABI.
-	f_types.push_back(PointerType::getUnqual(ret_type));
-	sret = new AllocaInst(ret_type, "", bb);
-	params.push_back(sret);
-	ret_type = VoidTy;
-    }
-
-#if !defined(__LP64__)
-    const Type *small_struct_type = NULL;
-    if (ret_type->getTypeID() == Type::StructTyID
-	    && GET_CORE()->get_sizeof(ret_type) == 8) {
-	// We are returning a small struct that can fit inside a 64-bit
-	// integer (such as NSPoint).
-	// TODO: we should probably make this more generic.
-	small_struct_type = ret_type;
-	ret_type = Int64Ty;
-    }
-#endif
-
-    Value *self_arg = NULL;
-    if (is_objc) {
-	// self
-	p = SkipFirstType(p);
-	p = SkipStackSize(p);
-	f_types.push_back(RubyObjTy);
-	self_arg = arg++;
-	params.push_back(self_arg);
-
-	// sel
-	p = SkipFirstType(p);
-	p = SkipStackSize(p);
-	f_types.push_back(PtrTy);
-	Value *sel_arg = arg++;
-	params.push_back(sel_arg);
-    }
-
-    /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
-    Value *argv_arg = arg++;
-
-    // Arguments.
-    std::vector<unsigned int> byval_args;
-    int given_argc = 0;
-    bool stop_arg_type = false;
-    while ((p = GetFirstType(p, buf, buf_len)) != NULL && buf[0] != '\0') {
-	if (variadic && given_argc == min_argc) {
-	    stop_arg_type = true;
-	}
-
-	const Type *llvm_type = convert_type(buf);
-	const Type *f_type = llvm_type;
-	if (GET_CORE()->is_large_struct_type(llvm_type)) {
-	    // We are passing a large struct, we need to mark this argument
-	    // with the byval attribute and configure the internal stub
-	    // call to pass a pointer to the structure, to conform to the
-	    // ABI.
-	    f_type = PointerType::getUnqual(llvm_type);
-	    byval_args.push_back(f_types.size() + 1 /* retval */);
-	}
-	else if (ArrayType::classof(llvm_type)) {
-	    // Vectors are passed by reference.
-	    f_type = PointerType::getUnqual(llvm_type);
-	}
-
-	if (!stop_arg_type) {
-	    // In order to conform to the ABI, we must stop providing types
-	    // once we start dealing with variable arguments and instead mark
-	    // the function as variadic.
-	    f_types.push_back(f_type);
-	}
-
-	Value *index = ConstantInt::get(Int32Ty, given_argc);
-	Value *slot = GetElementPtrInst::Create(argv_arg, index, "", bb);
-	Value *arg_val = new LoadInst(slot, "", bb);
-	Value *new_val_slot = new AllocaInst(llvm_type, "", bb);
-
-	params.push_back(compile_conversion_to_c(buf, arg_val, new_val_slot));
-
-	given_argc++;
-    }
-
-    // Appropriately cast the IMP argument.
-    FunctionType *ft = FunctionType::get(ret_type, f_types, variadic);
-    Value *imp = new BitCastInst(imp_arg, PointerType::getUnqual(ft), "", bb);
-
-    // Compile call.
-    CallInst *imp_call = CallInst::Create(imp, params.begin(), params.end(),
-	    "", bb); 
-
-    for (std::vector<unsigned int>::iterator iter = byval_args.begin();
-	 iter != byval_args.end(); ++iter) {
-	imp_call->addAttribute(*iter, Attribute::ByVal);
-    }
-
-    // Compile retval.
-    Value *retval;
-    if (sret != NULL) {
-	imp_call->addAttribute(1, Attribute::StructRet);
-	retval = new LoadInst(sret, "", bb);
-    }
-    else {
-	retval = imp_call;
-    }
-
-    GetFirstType(types, buf, buf_len);
-    ret_type = convert_type(buf);
-    if (self_arg != NULL && ret_type == VoidTy) {
-	// If we are calling an Objective-C method that returns void, let's
-	// return the receiver instead of nil, for convenience purposes.
-	retval = self_arg;
-    }
-    else {
-#if !defined(__LP64__)
-	if (small_struct_type != NULL) {
-	    Value *slot = new AllocaInst(small_struct_type, "", bb);
-	    new StoreInst(retval,
-		    new BitCastInst(slot, PointerType::getUnqual(Int64Ty),
-			"", bb),
-		    bb);
-	    retval = new LoadInst(slot, "", bb);
-	    ret_type = small_struct_type;
-	}
-#endif
-	retval = compile_conversion_to_ruby(buf, ret_type, retval);
-    }
-    ReturnInst::Create(context, retval, bb);
-
-    free(buf);
-
-    } // try
-    catch (...) {
-	if (f != NULL) {
-	    f->eraseFromParent();
-	}
-	restore_compiler_state();
-	throw;
-    }
-
-    restore_compiler_state();
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_long_arity_stub(int argc, bool is_block)
-{
-    Function *f;
-
-    if (is_block) {
-	// VALUE stubX(IMP imp, VALUE self, SEL sel,
-	//	       VALUE dvars, rb_vm_block_t *b, int argc, VALUE *argv)
-	// {
-	//	return (*imp)(self, sel, dvars, b, argv[0], ..., argv[X - 1]);
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy,
-		PtrTy, RubyObjTy, PtrTy,
-		RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
-    }
-    else {
-	// VALUE stubX(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
-	// {
-	//     return (*imp)(self, sel, argv[0], argv[1], ..., argv[X - 1]);
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy,
-		PtrTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
-    }
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    Function::arg_iterator arg = f->arg_begin();
-
-    Value *imp_arg = arg++;
-    Value *self_arg = arg++;
-    Value *sel_arg = arg++;
-    Value *dvars_arg;
-    Value *block_arg;
-    if (is_block) {
-	dvars_arg = arg++;
-	block_arg = arg++;
-    }
-    /*Value *argc_arg = */arg++;
-    Value *argv_arg = arg++;
-
-    std::vector<const Type *> f_types;
-    std::vector<Value *> params;
-
-    // Return type
-    const Type *ret_type = RubyObjTy;
-
-    // self
-    f_types.push_back(RubyObjTy);
-    params.push_back(self_arg);
-
-    // sel
-    f_types.push_back(PtrTy);
-    params.push_back(sel_arg);
-
-    if (is_block) {
-	// dvars
-	f_types.push_back(RubyObjTy);
-	params.push_back(dvars_arg);
-
-	// block
-	f_types.push_back(PtrTy);
-	params.push_back(block_arg);
-    }
-
-    for (int i = 0; i < argc; i++) {
-	f_types.push_back(RubyObjTy);
-
-	// Get an int
-	Value *index = ConstantInt::get(Int32Ty, i);
-	// Get the slot (aka argv[index])
-	Value *slot = GetElementPtrInst::Create(argv_arg, index, "", bb);
-	// Load the slot into memory and add it as an argument
-	Value *arg_val = new LoadInst(slot, "", bb);
-	params.push_back(arg_val);
-    }
-
-    // Get the function type, aka:    VALUE (*)(VALUE, SEL, ...)
-    FunctionType *ft = FunctionType::get(ret_type, f_types, false);
-    // Cast imp as the function type
-    Value *imp = new BitCastInst(imp_arg, PointerType::getUnqual(ft), "", bb);
-
-    // Compile call to the function
-    CallInst *imp_call = CallInst::Create(imp, params.begin(), params.end(),
-	"", bb);
-
-    // Compile return value
-    Value *retval = imp_call;
-    ReturnInst::Create(context, retval, bb);
-
-    return f;
-}
-
-bool
-RoxorCompiler::compile_lvars(ID *tbl)
-{
-    int lvar_count = (int)tbl[0];
-    int has_real_lvars = false;
-    for (int i = 0; i < lvar_count; i++) {
-	ID id = tbl[i + 1];
-	if (lvars.find(id) != lvars.end()) {
-	    continue;
-	}
-	if (std::find(dvars.begin(), dvars.end(), id) == dvars.end()) {
-#if ROXOR_COMPILER_DEBUG
-	    printf("lvar %s\n", rb_id2name(id));
-#endif
-	    Value *store = new AllocaInst(RubyObjTy, "", bb);
-	    new StoreInst(nilVal, store, bb);
-	    lvars[id] = store;
-	    has_real_lvars = true;
-	}
-    }
-    return has_real_lvars;
-}
-
-Value *
-RoxorCompiler::compile_lvar_slot(ID name, bool *need_wb)
-{
-    std::map<ID, Value *>::iterator iter = lvars.find(name);
-    if (iter != lvars.end()) {
-#if ROXOR_COMPILER_DEBUG
-	printf("get_lvar %s\n", rb_id2name(name));
-#endif
-	return iter->second;
-    }
-    if (current_block) {
-	Value *slot = compile_dvar_slot(name);
-	if (slot != NULL) {	
-#if ROXOR_COMPILER_DEBUG
-	    printf("get_dvar %s\n", rb_id2name(name));
-#endif
-	    return slot;
-	}
-    }
-    VALUE *var = GET_VM()->get_binding_lvar(name, false);
-    if (var != NULL) {
-#if ROXOR_COMPILER_DEBUG
-	printf("get_binding_lvar %s (%p)\n", rb_id2name(name), *(void **)var);
-#endif
-	Value *int_val = ConstantInt::get(IntTy, (long)var);
-	if (need_wb != NULL) {
-	    *need_wb = true;
-	}
-	return new IntToPtrInst(int_val, RubyObjPtrTy, "", bb);
-    }
-    fprintf(stderr, "can't find slot for variable %s\n", rb_id2name(name));
-    abort();
-}
-
-Value *
-RoxorCompiler::compile_lvar_slot(ID name)
-{
-    return compile_lvar_slot(name, NULL);
-}
-
-Value *
-RoxorCompiler::compile_dvar_assignment(ID vid, Value *val)
-{
-    if (running_block != NULL) {
-	// Dynamic variables assignments inside a block are a little bit
-	// complicated: if we are creating new objects we do need to defeat
-	// the thread-local collector by releasing ownership of the objects,
-	// otherwise the TLC might prematurely collect them. This is because
-	// the assignment is done into another thread's stack, which is not
-	// honored by the TLC.
-	Value *flag = new BitCastInst(running_block, Int32PtrTy, "", bb);
-	flag = new LoadInst(flag, "", bb);
-	Value *flagv = ConstantInt::get(Int32Ty, VM_BLOCK_THREAD);
-	flag = BinaryOperator::CreateAnd(flag, flagv, "", bb);
-	Value *is_thread = new ICmpInst(*bb, ICmpInst::ICMP_EQ, flag, flagv);
-
-	Function *f = bb->getParent();
-	BasicBlock *is_thread_bb = BasicBlock::Create(context, "", f);
-	BasicBlock *merge_bb = BasicBlock::Create(context, "", f);
-
-	BranchInst::Create(is_thread_bb, merge_bb, is_thread, bb);
-
-	bb = is_thread_bb;
-	CallInst::Create(releaseOwnershipFunc, val, "", bb);
-	BranchInst::Create(merge_bb, bb);
-
-	bb = merge_bb;
-    }
-    return compile_lvar_assignment(vid, val);
-}
-
-Value *
-RoxorCompiler::compile_lvar_assignment(ID vid, Value *val)
-{
-    bool need_wb = false;
-    Value *slot = compile_lvar_slot(vid, &need_wb);
-    if (need_wb) {
-	Value *args[] = { 
-	    new BitCastInst(slot, RubyObjPtrTy, "", bb),
-	    new BitCastInst(val, RubyObjTy, "", bb)
-	};
-	return CallInst::Create(writeBarrierFunc, args, args + 2, "", bb);
-    }
-    else {
-	new StoreInst(val, slot, bb);
-    }
-    return val;
-}
-
-#if __LP64__
-# define MAX_GPR_REGS 6
-# define MAX_SSE_REGS 8
-// The x86-64 ABI requires us to pass by reference arguments when there isn't
-// enough registers anymore. We need to count both GPR and SEE registers usage.
-// For more info: http://www.x86-64.org/documentation/abi.pdf
-static void
-examine(const Type *t, int *ngpr, int *nsse)
-{
-    switch (t->getTypeID()) {
-	case Type::IntegerTyID:
-	case Type::PointerTyID:
-	    (*ngpr)++;
-	    break;
-
-	case Type::FloatTyID:
-	case Type::DoubleTyID:
-	    (*nsse)++;
-	    break;
-
-	case Type::StructTyID:
-	    {
-		const StructType *st = cast<StructType>(t);
-		for (unsigned i = 0; i < st->getNumElements(); i++) {
-		    examine(st->getElementType(i), ngpr, nsse);
-		}
-	    }
-	    break;
-
-	default:
-	    // oops
-	    break;
-    }
-}
-#endif
-
-Function *
-RoxorCompiler::compile_objc_stub(Function *ruby_func, IMP ruby_imp,
-	const rb_vm_arity_t &arity, const char *types)
-{
-    assert(ruby_func != NULL || ruby_imp != NULL);
-
-    save_compiler_state();
-    reset_compiler_state();
-
-    const size_t buf_len = strlen(types) + 1;
-    assert(buf_len > 1);
-    char *buf = (char *)malloc(buf_len);
-
-    const char *p = types;
-    std::vector<const Type *> f_types;
-
-#if __LP64__
-    int gprcount = 0, ssecount = 0;
-#endif
-
-    // Return value.
-    p = GetFirstType(p, buf, buf_len);
-    std::string ret_type(buf);
-    const Type *f_ret_type = convert_type(buf);
-    const Type *f_sret_type = NULL;
-    if (GET_CORE()->is_large_struct_type(f_ret_type)) {
-	// We are returning a large struct, we need to pass a pointer as the
-	// first argument to the structure data and return void to conform to
-	// the ABI.
-	f_types.push_back(PointerType::getUnqual(f_ret_type));
-	f_sret_type = f_ret_type;
-	f_ret_type = VoidTy;
-#if __LP64__
-	gprcount++;
-#endif
-    }
-
-    // self
-    f_types.push_back(RubyObjTy);
-    p = SkipFirstType(p);
-    p = SkipStackSize(p);
-    // sel
-    f_types.push_back(PtrTy);
-    p = SkipFirstType(p);
-    p = SkipStackSize(p);
-#if __LP64__
-    gprcount += 2;
-#endif
-    // Arguments.
-    std::vector<std::string> arg_types;
-    std::vector<unsigned int> byval_args;
-    for (int i = 0; i < arity.real; i++) {
-	p = GetFirstType(p, buf, buf_len);
-	const Type *t = convert_type(buf);
-	bool enough_registers = true;
-#if __LP64__
-	int ngpr = 0, nsse = 0;
-	examine(t, &ngpr, &nsse);
-	if (gprcount + ngpr > MAX_GPR_REGS || ssecount + nsse > MAX_SSE_REGS) {
-	    enough_registers = false;
-	}
-	else {
-	    gprcount += ngpr;
-	    ssecount += nsse;
-	}
-	//printf("arg[%d] is using %d gpr %d sse\n", i, ngpr, nsse);
-#endif
-	if (!enough_registers || GET_CORE()->is_large_struct_type(t)) {
-	    // We are passing a large struct, we need to mark this argument
-	    // with the byval attribute and configure the internal stub
-	    // call to pass a pointer to the structure, to conform to the ABI.
-	    t = PointerType::getUnqual(t);
-	    byval_args.push_back(f_types.size() + 1 /* retval */);
-	}
-	else if (ArrayType::classof(t)) {
-	    // Vectors are passed by reference.
-	    t = PointerType::getUnqual(t);
-	}
-	f_types.push_back(t);
-	arg_types.push_back(buf);
-    }
-
-    free(buf);
-    buf = NULL;
-
-    // Create the function.
-    FunctionType *ft = FunctionType::get(f_ret_type, f_types, false);
-    Function *f = cast<Function>(module->getOrInsertFunction("", ft));
-    Function::arg_iterator arg = f->arg_begin();
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-#if !__LP64__
-    // Prepare exception handler (see below).
-    BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-    rescue_invoke_bb = BasicBlock::Create(context, "rescue", f);
-#endif
-
-    Value *sret = NULL;
-    int sret_i = 0;
-    if (f_sret_type != NULL) {
-	sret = arg++;
-	sret_i = 1;
-	f->addAttribute(1, Attribute::StructRet);
-    }
-    for (std::vector<unsigned int>::iterator iter = byval_args.begin();
-	 iter != byval_args.end(); ++iter) {
-	f->addAttribute(*iter, Attribute::ByVal);
-    }
-
-    std::vector<Value *> params;
-    params.push_back(arg++); // self
-    params.push_back(arg++); // sel
-
-    // Convert every incoming argument into Ruby type.
-    for (int i = 0; i < arity.real; i++) {
-	Value *a = arg++;
-	const Type *t = f_types[i + 2 + sret_i];
-	if (std::find(byval_args.begin(), byval_args.end(),
-		    (unsigned int)i + 3 + sret_i) != byval_args.end()) {
-	    a = new LoadInst(a, "", bb);
-	    t = cast<PointerType>(t)->getElementType();
-	}
-	Value *ruby_arg = compile_conversion_to_ruby(arg_types[i].c_str(),
-		t, a);
-	params.push_back(ruby_arg);
-    }
-
-    // Create the Ruby implementation type (unless it's already provided).
-    Value *imp;
-    if (ruby_func == NULL) {
-	std::vector<const Type *> ruby_func_types;
-	ruby_func_types.push_back(RubyObjTy);
-	ruby_func_types.push_back(PtrTy);
-	for (int i = 0; i < arity.real; i++) {
-	    ruby_func_types.push_back(RubyObjTy);
-	}
-	FunctionType *ft = FunctionType::get(RubyObjTy, ruby_func_types, false);
-	imp = new BitCastInst(compile_const_pointer((void *)ruby_imp),
-		PointerType::getUnqual(ft), "", bb);
-    }
-    else {
-	imp = ruby_func;
-    }
-
-    // Call the Ruby implementation.
-    Instruction *ruby_call_insn = compile_protected_call(imp, params);
-
-    // Convert the return value into Objective-C type (if any).
-    Value *ret_val = ruby_call_insn;
-    if (f_ret_type != VoidTy) {
-	ret_val = compile_conversion_to_c(ret_type.c_str(), ret_val,
-		new AllocaInst(f_ret_type, "", bb));
-	ReturnInst::Create(context, ret_val, bb);
-    }
-    else if (sret != NULL) {
-	compile_conversion_to_c(ret_type.c_str(), ret_val, sret);
-	ReturnInst::Create(context, bb);
-    }
-    else {
-	ReturnInst::Create(context, bb);
-    }
-
-#if !__LP64__
-    // The 32-bit Objective-C runtime doesn't use C++ exceptions, therefore
-    // we must convert Ruby exceptions to Objective-C ones.
-    bb = rescue_invoke_bb;
-    compile_landing_pad_header();
-
-    Function *ruby2ocExcHandlerFunc = NULL;
-    if (ruby2ocExcHandlerFunc == NULL) {
-	// void rb_rb2oc_exc_handler(void);
-	ruby2ocExcHandlerFunc = cast<Function>(
-		module->getOrInsertFunction("rb_rb2oc_exc_handler", VoidTy,
-		    NULL));
-    }
-    CallInst::Create(ruby2ocExcHandlerFunc, "", bb);
-
-    compile_landing_pad_footer();
-    new UnreachableInst(context, bb);
-
-    rescue_invoke_bb = old_rescue_invoke_bb;
-#endif
-
-    restore_compiler_state();
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
-{
-    if (blockEvalFunc == NULL) {
-	// VALUE rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel,
-	//	int argc, const VALUE *argv)
-	blockEvalFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_block_eval2",
-		    RubyObjTy, PtrTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy,
-		    NULL));
-    }
-
-    Function *f;
-    Value *rcv;
-    Value *sel;
-    Value *argc;
-    Value *argv;
-
-    const int arity = rb_vm_arity_n(block->arity);
-    if (arity == -1) {
-	// VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
-	// {
-	//     return rb_vm_block_eval2(block, rcv, sel, argc, argv);
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		    RubyObjTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
-	Function::arg_iterator arg = f->arg_begin();
-	rcv = arg++;
-	sel = arg++;
-	argc = arg++;
-	argv = arg++;
-
-	bb = BasicBlock::Create(context, "EntryBlock", f);
-    }
-    else if (arity < -1) {
-	// VALUE foo(VALUE rcv, SEL sel, VALUE argv)
-	// {
-	//	return rb_block_eval2(block, rcv, sel, RARRAY_LEN(argv),
-	//		RARRAY_PTR(argv));
-	// }
-	f = cast<Function>(module->getOrInsertFunction("",
-		    RubyObjTy, RubyObjTy, PtrTy, RubyObjTy, NULL));
-	Function::arg_iterator arg = f->arg_begin();
-	rcv = arg++;
-	sel = arg++;
-	Value *argv_ary = arg++;
-
-	bb = BasicBlock::Create(context, "EntryBlock", f);
-
-	argc = CallInst::Create(lengthArrayFunc, argv_ary, "", bb);
-	argc = new TruncInst(argc, Int32Ty, "", bb);
-	argv = CallInst::Create(ptrArrayFunc, argv_ary, "", bb);
-    }
-    else {
-	assert(arity >= 0);
-	// VALUE foo(VALUE rcv, SEL sel, VALUE arg1, ...)
-	// {
-	//     VALUE argv[n] = {arg1, ...};
-	//     return rb_vm_block_eval2(block, rcv, sel, n, argv);
-	// }
-	std::vector<const Type *> stub_types;
-	stub_types.push_back(RubyObjTy);
-	stub_types.push_back(PtrTy);
-	for (int i = 0; i < arity; i++) {
-	    stub_types.push_back(RubyObjTy);
-	}
-	FunctionType *ft = FunctionType::get(RubyObjTy, stub_types, false);
-	f = cast<Function>(module->getOrInsertFunction("", ft));
-
-	Function::arg_iterator arg = f->arg_begin();
-	rcv = arg++;
-	sel = arg++;
-	argc = ConstantInt::get(Int32Ty, arity);
-
-	bb = BasicBlock::Create(context, "EntryBlock", f);
-
-	argv = new AllocaInst(RubyObjTy, argc, "", bb);
-	for (int i = 0; i < arity; i++) {
-	    Value *index = ConstantInt::get(Int32Ty, i);
-	    Value *slot = GetElementPtrInst::Create(argv, index, "", bb);
-	    new StoreInst(arg++, slot, bb);
-	}
-    }
-
-    Value *args[] = {
-	compile_const_pointer(block),
-	rcv,
-	sel,
-	argc,
-	argv
-    };
-    Value *retval = compile_protected_call(blockEvalFunc, args, args + 5);
-    ReturnInst::Create(context, retval, bb);	
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_mri_stub(void *imp, const int arity)
-{
-    if (arity == 0) {
-	// ABI matches if arity is 0.
-	// MacRuby:	VALUE foo(VALUE rcv, SEL sel);
-	// MRI:		VALUE foo(VALUE rcv);
-	return NULL;
-    }
-
-    // Prepare function type for the stub.
-    std::vector<const Type *> stub_types;
-    stub_types.push_back(RubyObjTy); 		// self
-    stub_types.push_back(PtrTy);		// SEL
-    if (arity == -2) {
-	stub_types.push_back(RubyObjTy); 	// ary
-    }
-    else if (arity == -1) {
-	stub_types.push_back(Int32Ty); 		// argc
-	stub_types.push_back(RubyObjPtrTy); 	// argv
-    }
-    else {
-	assert(arity > 0);
-	for (int i = 0; i < arity; i++) {
-	    stub_types.push_back(RubyObjTy); 	// arg...
-	}
-    }
-
-    // Create the stub.
-    FunctionType *ft = FunctionType::get(RubyObjTy, stub_types, false);
-    Function *f = cast<Function>(module->getOrInsertFunction("", ft));
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-    Function::arg_iterator arg = f->arg_begin();
-    Value *rcv = arg++;
-    Value *sel = arg++;
-
-    // Register the receiver and selector to the VM (for rb_call_super()).
-    if (setCurrentMRIMethodContext == NULL) {
-	// void rb_vm_set_current_mri_method_context(VALUE self, SEL sel)
-	setCurrentMRIMethodContext = 
-	    cast<Function>(module->getOrInsertFunction(
-			"rb_vm_set_current_mri_method_context",
-			VoidTy, RubyObjTy, PtrTy, NULL));
-    }
-    Value *args[2] = { rcv, sel };
-    CallInst::Create(setCurrentMRIMethodContext, args, args + 2, "", bb);
-
-    // Prepare function types for the MRI implementation and arguments.
-    std::vector<const Type *> imp_types;
-    std::vector<Value *> params;
-    if (arity == -2) {
-	imp_types.push_back(RubyObjTy); 	// self
-	imp_types.push_back(RubyObjTy); 	// ary
-	params.push_back(rcv);
-	params.push_back(arg++);
-    }
-    else if (arity == -1) {
-	imp_types.push_back(Int32Ty);		// argc
-	imp_types.push_back(RubyObjPtrTy);	// argv
-	imp_types.push_back(RubyObjTy); 	// self
-	params.push_back(arg++);
-	params.push_back(arg++);
-	params.push_back(rcv);
-    }
-    else {
-	assert(arity > 0);
-	imp_types.push_back(RubyObjTy); 	// self
-	params.push_back(rcv);
-	for (int i = 0; i < arity; i++) {
-	    imp_types.push_back(RubyObjTy); 	// arg...
-	    params.push_back(arg++);
-	}
-    }
-
-    // Cast the given MRI implementation.
-    FunctionType *imp_ft = FunctionType::get(RubyObjTy, imp_types, false);
-    Value *imp_val = new BitCastInst(compile_const_pointer(imp),
-	    PointerType::getUnqual(imp_ft), "", bb);
-
-    // Call the MRI implementation and return its value.
-    CallInst *imp_call = CallInst::Create(imp_val, params.begin(),
-	    params.end(), "", bb); 
-    ReturnInst::Create(context, imp_call, bb);
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_to_rval_convertor(const char *type)
-{
-    // VALUE foo(void *ocval);
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy, PtrTy, NULL));
-    Function::arg_iterator arg = f->arg_begin();
-    Value *ocval = arg++;
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    const Type *llvm_type = convert_type(type); 
-    ocval = new BitCastInst(ocval, PointerType::getUnqual(llvm_type), "", bb);
-    ocval = new LoadInst(ocval, "", bb);
-
-    Value *rval = compile_conversion_to_ruby(type, llvm_type, ocval);
-
-    ReturnInst::Create(context, rval, bb);
-
-    return f;
-}
-
-Function *
-RoxorCompiler::compile_to_ocval_convertor(const char *type)
-{
-    // void foo(VALUE rval, void **ocval);
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		VoidTy, RubyObjTy, PtrTy, NULL));
-    Function::arg_iterator arg = f->arg_begin();
-    Value *rval = arg++;
-    Value *ocval = arg++;
-
-    bb = BasicBlock::Create(context, "EntryBlock", f);
-
-    const Type *llvm_type = convert_type(type);
-    ocval = new BitCastInst(ocval, PointerType::getUnqual(llvm_type), "", bb);
-    compile_conversion_to_c(type, rval, ocval);
-
-    ReturnInst::Create(context, bb);
-
-    return f;
-}
-
-Value *
-RoxorCompiler::compile_get_ffstate(GlobalVariable *ffstate)
-{
-    return new LoadInst(ffstate, "", bb);
-}
-
-Value *
-RoxorCompiler::compile_set_ffstate(Value *val, Value *expected,
-				   GlobalVariable *ffstate, BasicBlock *mergeBB, Function *f)
-{
-    BasicBlock *valEqExpectedBB = BasicBlock::Create(context,
-	"value_equal_expected", f);
-    BasicBlock *valNotEqExpectedBB = BasicBlock::Create(context,
-	"value_not_equal_expected", f);
-
-    Value *valueEqExpectedCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ, val,
-	expected);
-    BranchInst::Create(valEqExpectedBB, valNotEqExpectedBB,
-	valueEqExpectedCond, bb);
-
-    new StoreInst(trueVal,  ffstate, valEqExpectedBB);
-    new StoreInst(falseVal, ffstate, valNotEqExpectedBB);
-
-    BranchInst::Create(mergeBB, valEqExpectedBB);
-    BranchInst::Create(mergeBB, valNotEqExpectedBB);
-
-    PHINode *pn = PHINode::Create(RubyObjTy, "", mergeBB);
-    pn->addIncoming(trueVal, valEqExpectedBB);
-    pn->addIncoming(falseVal, valNotEqExpectedBB);
-
-    return pn;
-}
-
-Value *
-RoxorCompiler::compile_ff2(NODE *node)
-{
-    /*
-     * if ($state == true || nd_beg == true)
-     *   $state = (nd_end == false)
-     *   return true
-     * else
-     *   return false
-     * end
-     */
-
-    GlobalVariable *ffstate = new GlobalVariable(*RoxorCompiler::module,
-	RubyObjTy, false, GlobalValue::InternalLinkage, falseVal, "");
-
-    Function *f = bb->getParent();
-
-    BasicBlock *stateNotTrueBB = BasicBlock::Create(context,
-	"state_not_true", f);
-    BasicBlock *stateOrBegIsTrueBB = BasicBlock::Create(context,
-	"state_or_beg_is_true", f);
-    BasicBlock *returnTrueBB = BasicBlock::Create(context, "return_true", f);
-    BasicBlock *returnFalseBB = BasicBlock::Create(context, "return_false", f);
-    BasicBlock *mergeBB = BasicBlock::Create(context, "merge", f);
-
-    // `if $state == true`
-    Value *stateVal = compile_get_ffstate(ffstate);
-    Value *stateIsTrueCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ, stateVal,
-	trueVal);
-    BranchInst::Create(stateOrBegIsTrueBB, stateNotTrueBB, stateIsTrueCond,
-	bb);
-
-    // `or if nd_beg == true`
-    bb = stateNotTrueBB;
-    Value *beginValue = compile_node(node->nd_beg);
-    stateNotTrueBB = bb;
-    Value *begIsTrueCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-	beginValue, trueVal);
-    BranchInst::Create(stateOrBegIsTrueBB, returnFalseBB, begIsTrueCond, bb);
-
-    // `$state = (nd_end == false)`
-    bb = stateOrBegIsTrueBB;
-    Value *endValue = compile_node(node->nd_end);
-    stateOrBegIsTrueBB = bb;
-    compile_set_ffstate(endValue, falseVal, ffstate, returnTrueBB, f);
-
-    BranchInst::Create(mergeBB, returnTrueBB);
-    BranchInst::Create(mergeBB, returnFalseBB);
-
-    bb = mergeBB;
-    PHINode *pn = PHINode::Create(RubyObjTy, "", mergeBB);
-    pn->addIncoming(trueVal, returnTrueBB);
-    pn->addIncoming(falseVal, returnFalseBB);
-
-    return pn;
-}
-
-Value *
-RoxorCompiler::compile_ff3(NODE *node)
-{
-    /*
-     * if ($state == true)
-     *   $state = (nd_end == false)
-     *   return true
-     * else
-     *   $state = (nd_beg == true)
-     *   return $state
-     * end
-     */
-
-    GlobalVariable *ffstate = new GlobalVariable(*RoxorCompiler::module,
-	RubyObjTy, false, GlobalValue::InternalLinkage, falseVal, "");
-
-    Function *f = bb->getParent();
-
-    BasicBlock *stateIsTrueBB = BasicBlock::Create(context, "state_is_true",
-	f);
-    BasicBlock *stateIsFalseBB = BasicBlock::Create(context, "state_is_false",
-	f);
-    BasicBlock *returnTrueBB = BasicBlock::Create(context, "return_true", f);
-    BasicBlock *returnStateBB = BasicBlock::Create(context, "return_state", f);
-    BasicBlock *mergeBB = BasicBlock::Create(context, "merge", f);
-
-    
-    // `if $state == true`
-    Value *stateVal = compile_get_ffstate(ffstate);
-    Value *stateIsTrueCond = new ICmpInst(*bb, ICmpInst::ICMP_EQ, stateVal,
-	trueVal);
-    BranchInst::Create(stateIsTrueBB, stateIsFalseBB, stateIsTrueCond, bb);
-
-    // `$state = (nd_end == false)`
-    bb = stateIsTrueBB;
-    Value *endValue = compile_node(node->nd_end);
-    stateIsTrueBB = bb;
-    compile_set_ffstate(endValue, falseVal, ffstate, returnTrueBB, f);
-
-    // `$state = (nd_beg == true)`
-    bb = stateIsFalseBB;
-    Value *beginValue = compile_node(node->nd_beg);
-    stateIsFalseBB = bb;
-    stateVal = compile_set_ffstate(beginValue, trueVal, ffstate, returnStateBB, f);
-
-    BranchInst::Create(mergeBB, returnTrueBB);
-    BranchInst::Create(mergeBB, returnStateBB);
-
-    bb = mergeBB;
-    PHINode *pn = PHINode::Create(RubyObjTy, "", mergeBB);
-    pn->addIncoming(trueVal, returnTrueBB);
-    pn->addIncoming(stateVal, returnStateBB);
-
-    return pn;
-}
-
-static void
-add_stub_types_cb(SEL sel, const char *types, bool is_objc, void *ctx)
-{
-    RoxorAOTCompiler *compiler = (RoxorAOTCompiler *)ctx;
-
-    std::map<SEL, std::vector<std::string> *> &map =
-	is_objc ? compiler->bs_objc_stubs_types : compiler->bs_c_stubs_types;
-
-    std::map<SEL, std::vector<std::string> *>::iterator iter = map.find(sel);
-    std::vector<std::string> *v;
-    if (iter == map.end()) {
-	v = new std::vector<std::string>();
-	map[sel] = v;
-    }
-    else {
-	v = iter->second;
-    }
-    v->push_back(types);
-}
-
-extern "C"
-void
-rb_vm_parse_bs_full_file(const char *path,
-	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
-	void *ctx);
-
-void
-RoxorAOTCompiler::load_bs_full_file(const char *path)
-{
-    rb_vm_parse_bs_full_file(path, add_stub_types_cb, (void *)this);
-}
-
-#endif // !MACRUBY_STATIC

Deleted: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/compiler.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,522 +0,0 @@
-/*
- * MacRuby Compiler.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __COMPILER_H_
-#define __COMPILER_H_
-
-// For the dispatcher.
-#define DISPATCH_VCALL		0x1  // no receiver, no argument
-#define DISPATCH_FCALL		0x2  // no receiver, one or more arguments
-#define DISPATCH_SUPER		0x4  // super call
-#define DISPATCH_SPLAT		0x8  // has splat
-#define SPLAT_ARG_FOLLOWS	0xdeadbeef
-
-// For const lookup.
-#define CONST_LOOKUP_LEXICAL		1
-#define CONST_LOOKUP_DYNAMIC_CLASS	2
-
-// For defined?
-#define DEFINED_IVAR 	1
-#define DEFINED_GVAR 	2
-#define DEFINED_CVAR 	3
-#define DEFINED_CONST	4
-#define DEFINED_LCONST	5
-#define DEFINED_SUPER	6
-#define DEFINED_METHOD	7
-
-#if defined(__cplusplus)
-
-#if !defined(MACRUBY_STATIC)
-
-class RoxorInterpreter;
-
-class RoxorCompiler {
-    friend class RoxorInterpreter;
-
-    public:
-	static llvm::Module *module;
-	static RoxorCompiler *shared;
-
-	RoxorCompiler(bool debug_mode);
-	virtual ~RoxorCompiler(void) { }
-
-	void set_fname(const char *_fname);
-
-	Value *compile_node(NODE *node);
-
-	virtual Function *compile_main_function(NODE *node,
-		bool *can_be_interpreted);
-	Function *compile_read_attr(ID name);
-	Function *compile_write_attr(ID name);
-	Function *compile_stub(const char *types, bool variadic, int min_argc,
-		bool is_objc);
-	Function *compile_long_arity_stub(int argc, bool is_block);
-	Function *compile_bs_struct_new(rb_vm_bs_boxed_t *bs_boxed);
-	Function *compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed,
-		int field);
-	Function *compile_ffi_function(void *stub, void *imp, int argc);
-	Function *compile_to_rval_convertor(const char *type);
-	Function *compile_to_ocval_convertor(const char *type);
-	Function *compile_objc_stub(Function *ruby_func, IMP ruby_imp,
-		const rb_vm_arity_t &arity, const char *types);
-	Function *compile_block_caller(rb_vm_block_t *block);
-	Function *compile_mri_stub(void *imp, const int arity);
-
-	void inline_function_calls(Function *f);
-
-	const Type *convert_type(const char *type);
-
-	bool is_inside_eval(void) { return inside_eval; }
-	void set_inside_eval(bool flag) { inside_eval = flag; }
-	bool is_dynamic_class(void) { return dynamic_class; }
-	void set_dynamic_class(bool flag) { dynamic_class = flag; }
-
-	void generate_location_path(std::string &path, DILocation loc);
-
-    protected:
-#if !defined(LLVM_TOT)
-	DIBuilder *debug_info;
-#else
-	DIFactory *debug_info;
-#endif
-	DICompileUnit debug_compile_unit;
-	DISubprogram debug_subprogram;
-
-	bool debug_mode;
-	const char *fname;
-	bool inside_eval;
-	bool should_interpret;
-	bool can_interpret;
-
-	std::map<ID, Value *> lvars;
-	std::vector<ID> dvars;
-	std::map<ID, void *> ivars_slots_cache;
-	std::map<std::string, GlobalVariable *> static_strings;
-	std::map<CFHashCode, GlobalVariable *> static_ustrings;
-
-	class MAsgnValue {
-	    public:
-		CallInst *ary;
-		std::vector<CallInst *> sets;
-	};
-	std::vector<MAsgnValue> masgn_values;
-
-#if ROXOR_COMPILER_DEBUG
-	int level;
-# define DEBUG_LEVEL_INC() (level++)
-# define DEBUG_LEVEL_DEC() (level--)
-#else
-# define DEBUG_LEVEL_INC()
-# define DEBUG_LEVEL_DEC()
-#endif
-
-	unsigned int current_line;
-	BasicBlock *bb;
-	BasicBlock *entry_bb;
-	ID current_mid;
-	rb_vm_arity_t current_arity;
-	ID self_id;
-	Value *current_self;
-	bool current_block;
-	bool current_block_chain;
-	Value *current_var_uses;
-	Value *running_block;
-	Value *current_block_arg;
-	BasicBlock *begin_bb;
-	BasicBlock *rescue_invoke_bb;
-	BasicBlock *rescue_rethrow_bb;
-	BasicBlock *ensure_bb;
-	PHINode *ensure_pn;
-	NODE *ensure_node;
-	bool current_rescue;
-	NODE *current_block_node;
-	Function *current_block_func;
-	Function *current_non_block_func;
-	GlobalVariable *current_opened_class;
-	bool dynamic_class;
-	BasicBlock *current_loop_begin_bb;
-	BasicBlock *current_loop_body_bb;
-	BasicBlock *current_loop_end_bb;
-	PHINode *current_loop_exit_val;
-	int return_from_block;
-	int return_from_block_ids;
-	bool block_declaration;
-	AllocaInst *dispatch_argv;
-	long outer_mask;
-
-	Function *writeBarrierFunc;
-	Function *dispatchFunc;
-	Function *fastPlusFunc;
-	Function *fastMinusFunc;
-	Function *fastMultFunc;
-	Function *fastDivFunc;
-	Function *fastLtFunc;
-	Function *fastLeFunc;
-	Function *fastGtFunc;
-	Function *fastGeFunc;
-	Function *fastEqFunc;
-	Function *fastNeqFunc;
-	Function *fastEqqFunc;
-	Function *fastArefFunc;
-	Function *fastAsetFunc;
-	Function *fastShiftFunc;
-	Function *whenSplatFunc;
-	Function *prepareBlockFunc;
-	Function *pushBindingFunc;
-	Function *getBlockFunc;
-	Function *currentBlockObjectFunc;
-	Function *getConstFunc;
-	Function *setConstFunc;
-	Function *prepareMethodFunc;
-	Function *singletonClassFunc;
-	Function *defineClassFunc;
-	Function *prepareIvarSlotFunc;
-	Function *getIvarFunc;
-	Function *setIvarFunc;
-	Function *willChangeValueFunc;
-	Function *didChangeValueFunc;
-	Function *definedFunc;
-	Function *undefFunc;
-	Function *aliasFunc;
-	Function *valiasFunc;
-	Function *newHashFunc;
-	Function *storeHashFunc;
-	Function *toAFunc;
-	Function *toAryFunc;
-	Function *catArrayFunc;
-	Function *dupArrayFunc;
-	Function *newArrayFunc;
-	Function *asetArrayFunc;
-	Function *entryArrayFunc;
-	Function *checkArrayFunc;
-	Function *lengthArrayFunc;
-	Function *ptrArrayFunc;
-	Function *newStructFunc;
-	Function *newOpaqueFunc;
-	Function *newPointerFunc;
-	Function *getStructFieldsFunc;
-	Function *getOpaqueDataFunc;
-	Function *getPointerPtrFunc;
-	Function *xmallocFunc;
-	Function *checkArityFunc;
-	Function *setStructFunc;
-	Function *newRangeFunc;
-	Function *newRegexpFunc;
-	Function *strInternFunc;
-	Function *selToSymFunc;
-	Function *keepVarsFunc;
-	Function *masgnGetElemBeforeSplatFunc;
-	Function *masgnGetElemAfterSplatFunc;
-	Function *masgnGetSplatFunc;
-	Function *newStringFunc;
-	Function *newString2Func;
-	Function *newString3Func;
-	Function *yieldFunc;
-	Function *getBrokenFunc;
-	Function *blockEvalFunc;
-	Function *gvarSetFunc;
-	Function *gvarGetFunc;
-	Function *cvarSetFunc;
-	Function *cvarGetFunc;
-	Function *currentExceptionFunc;
-	Function *popExceptionFunc;
-	Function *getSpecialFunc;
-	Function *breakFunc;
-	Function *returnFromBlockFunc;
-	Function *returnedFromBlockFunc;
-	Function *checkReturnFromBlockFunc;
-	Function *setHasEnsureFunc;
-	Function *setScopeFunc;
-	Function *setCurrentClassFunc;
-	Function *debugTrapFunc;
-	Function *getFFStateFunc;
-	Function *setFFStateFunc;
-	Function *releaseOwnershipFunc;
-	Function *ocvalToRvalFunc;
-	Function *charToRvalFunc;
-	Function *ucharToRvalFunc;
-	Function *shortToRvalFunc;
-	Function *ushortToRvalFunc;
-	Function *intToRvalFunc;
-	Function *uintToRvalFunc;
-	Function *longToRvalFunc;
-	Function *ulongToRvalFunc;
-	Function *longLongToRvalFunc;
-	Function *ulongLongToRvalFunc;
-	Function *floatToRvalFunc;
-	Function *doubleToRvalFunc;
-	Function *selToRvalFunc;
-	Function *charPtrToRvalFunc;
-	Function *rvalToOcvalFunc;
-	Function *rvalToBoolFunc;
-	Function *rvalToCharFunc;
-	Function *rvalToUcharFunc;
-	Function *rvalToShortFunc;
-	Function *rvalToUshortFunc;
-	Function *rvalToIntFunc;
-	Function *rvalToUintFunc;
-	Function *rvalToLongFunc;
-	Function *rvalToUlongFunc;
-	Function *rvalToLongLongFunc;
-	Function *rvalToUlongLongFunc;
-	Function *rvalToFloatFunc;
-	Function *rvalToDoubleFunc;
-	Function *rvalToSelFunc;
-	Function *rvalToCharPtrFunc;
-	Function *initBlockFunc;
-	Function *blockProcFunc;
-	Function *setCurrentMRIMethodContext;
-
-	Constant *zeroVal;
-	Constant *oneVal;
-	Constant *twoVal;
-	Constant *threeVal;
-	Constant *nilVal;
-	Constant *trueVal;
-	Constant *falseVal;
-	Constant *undefVal;
-	Constant *splatArgFollowsVal;
-	Constant *defaultScope;
-	Constant *publicScope;
-
-	const Type *VoidTy;
-	const Type *Int1Ty;
-	const Type *Int8Ty;
-	const Type *Int16Ty;
-	const Type *Int32Ty;
-	const Type *Int64Ty;
-	const Type *FloatTy;
-	const Type *DoubleTy;
-	const Type *RubyObjTy; 
-	const PointerType *RubyObjPtrTy;
-	const PointerType *RubyObjPtrPtrTy;
-	const PointerType *PtrTy;
-	const PointerType *PtrPtrTy;
-	const Type *IntTy;
-	const PointerType *Int32PtrTy;
-	const Type *BitTy;
-	const Type *BlockLiteralTy;
-
-	unsigned dbg_mdkind;
-
-	void compile_node_error(const char *msg, NODE *node);
-
-	Function *
-	get_function(const char *name) {
-	    Function *f = module->getFunction(name);
-	    if (f == NULL) {
-		printf("function %s cannot be found!\n", name);
-		abort();
-	    }
-	    return f;
-	}
-
-	virtual Constant *
-	compile_const_pointer(void *ptr, const PointerType *type=NULL) {
-	    if (type == NULL) {
-		type = PtrTy;
-	    }
-	    if (ptr == NULL) {
-		return ConstantPointerNull::get(type);
-	    }
-	    else {
-		Constant *ptrint = ConstantInt::get(IntTy, (long)ptr);
-		return ConstantExpr::getIntToPtr(ptrint, type);
-	    }
-	}
-
-	Constant *
-	compile_const_pointer_to_pointer(void *ptr) {
-	    return compile_const_pointer(ptr, PtrPtrTy);
-	}
-
-	bool should_inline_function(Function *f);
-
-	Value *compile_node0(NODE *node);
-	Function *compile_scope(NODE *node);
-	Value *compile_call(NODE *node, bool use_tco=true);
-	Value *compile_yield(NODE *node);
-	Instruction *compile_protected_call(Value *imp, Value **args_begin,
-		Value **args_end);
-	Instruction *compile_protected_call(Value *imp, std::vector<Value *>
-		&params);
-	Value *recompile_dispatch_argv(std::vector<Value *> &params, int idx);
-	void compile_dispatch_arguments(NODE *args,
-		std::vector<Value *> &arguments, int *pargc);
-	Function::ArgumentListType::iterator compile_optional_arguments(
-		Function::ArgumentListType::iterator iter, NODE *node);
-	void compile_boolean_test(Value *condVal, BasicBlock *ifTrueBB,
-		BasicBlock *ifFalseBB);
-	void compile_when_arguments(NODE *args, Value *comparedToVal,
-		BasicBlock *thenBB);
-	void compile_single_when_argument(NODE *arg, Value *comparedToVal,
-		BasicBlock *thenBB);
-	void compile_method_definition(NODE *node);
-	virtual void compile_prepare_method(Value *classVal, Value *sel,
-		bool singleton, Function *new_function, rb_vm_arity_t &arity,
-		NODE *body);
-	Value *compile_dispatch_call(std::vector<Value *> &params);
-	Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
-	Value *compile_attribute_assign(NODE *node, Value *extra_val);
-	virtual Value *compile_prepare_block_args(Function *func, int *flags);
-	Value *compile_prepare_block(void);
-	Value *compile_block(NODE *node);
-	Value *compile_block_get(Value *block_object);
-	Value *compile_binding(void);
-	Value *compile_optimized_dispatch_call(SEL sel, int argc,
-		std::vector<Value *> &params);
-	Value *compile_lvar_assignment(ID vid, Value *val);
-	Value *compile_dvar_assignment(ID vid, Value *val);
-	Value *compile_lvar_get(ID vid);
-	Value *compile_ivar_assignment(ID vid, Value *val);
-	Value *compile_ivar_get(ID vid);
-	Value *compile_cvar_assignment(ID vid, Value *val);
-	Value *compile_cvar_get(ID vid, bool check);
-	Value *compile_gvar_assignment(NODE *node, Value *val);
-	Value *compile_gvar_get(NODE *node);
-	Value *compile_constant_declaration(NODE *node, Value *val);
-	Value *compile_multiple_assignment(NODE *node);
-	Value *compile_multiple_assignment(NODE *node, Value *val);
-	void compile_multiple_assignment_element(NODE *node, Value *val);
-	Value *compile_current_class(void);
-	virtual Value *compile_nsobject(void);
-	virtual Value *compile_standarderror(void);
-	Value *compile_class_path(NODE *node, int *flags, int *outer_level);
-	Value *compile_const(ID id, Value *outer);
-	Value *compile_singleton_class(Value *obj);
-	Value *compile_defined_expression(NODE *node);
-	Value *compile_dstr(NODE *node);
-	Value *compile_dvar_slot(ID name);
-	void compile_break_val(Value *val);
-	void compile_simple_return(Value *val);
-	Value *compile_set_has_ensure(Value *val);
-	void compile_return_from_block(Value *val, int id);
-	void compile_return_from_block_handler(int id);
-	Value *compile_jump(NODE *node);
-	virtual Value *compile_ccache(ID id);
-	virtual Value *compile_sel(SEL sel, bool add_to_bb=true) {
-	    return compile_const_pointer(sel, PtrTy);
-	}
-	virtual Value *compile_id(ID id);
-	Instruction *compile_const_global_string(const char *str,
-		const size_t str_len);
-	Instruction *compile_const_global_string(const char *str) {
-	    return compile_const_global_string(str, strlen(str));
-	}
-	Instruction *compile_const_global_ustring(const UniChar *str,
-		const size_t str_len);
-
-	Value *compile_arity(rb_vm_arity_t &arity);
-	Instruction *compile_range(Value *beg, Value *end, bool exclude_end,
-		bool retain=false);
-	Value *compile_literal(VALUE val);
-	virtual Value *compile_immutable_literal(VALUE val);
-	virtual Value *compile_global_entry(NODE *node);
-
-	void compile_set_current_scope(Value *klass, Value *scope);
-	Value *compile_set_current_class(Value *klass);
-
-	Value *compile_landing_pad_header(void);
-	void compile_landing_pad_footer(bool pop_exception=true);
-	Value *compile_current_exception(void);
-	void compile_rethrow_exception(void);
-	void compile_pop_exception(int pos=0);
-	Value *compile_lvar_slot(ID name);
-	Value *compile_lvar_slot(ID name, bool *need_wb);
-	bool compile_lvars(ID *tbl);
-	Value *compile_new_struct(Value *klass, std::vector<Value *> &fields);
-	Value *compile_new_opaque(Value *klass, Value *val);
-	Value *compile_new_pointer(const char *type, Value *val);
-	void compile_get_struct_fields(Value *val, Value *buf,
-		rb_vm_bs_boxed_t *bs_boxed);
-	Value *compile_get_opaque_data(Value *val, rb_vm_bs_boxed_t *bs_boxed,
-		Value *slot);
-	Value *compile_get_cptr(Value *val, const char *type, Value *slot);
-	void compile_check_arity(Value *given, Value *requested);
-	void compile_set_struct(Value *rcv, int field, Value *val);
-	Value *compile_xmalloc(size_t len);
-
-	Value *compile_lambda_to_funcptr(const char *type, Value *val,
-		Value *slot, bool is_block);
-	Value *compile_conversion_to_c(const char *type, Value *val,
-		Value *slot);
-	Value *compile_conversion_to_ruby(const char *type,
-		const Type *llvm_type, Value *val);
-	void compile_debug_trap(void);
-
-	virtual Value *compile_slot_cache(ID id);
-	void compile_keep_vars(BasicBlock *startBB, BasicBlock *mergeBB);
-
-	SEL mid_to_sel(ID mid, int arity);
-
-	Value *compile_get_ffstate(GlobalVariable *ffstate);
-	Value *compile_set_ffstate(Value *val, Value *expected,
-		GlobalVariable *ffstate, BasicBlock *mergeBB, Function *f);
-	Value *compile_ff2(NODE *current_node);
-	Value *compile_ff3(NODE *current_node);
-
-	void attach_current_line_metadata(Instruction *insn);
-};
-
-#define context (RoxorCompiler::module->getContext())
-
-class RoxorAOTCompiler : public RoxorCompiler {
-    public:
-	RoxorAOTCompiler(void);
-
-	Function *compile_main_function(NODE *node, bool *can_be_interpreted);
-
-	// BridgeSupport metadata needed for AOT compilation.
-	std::map<SEL, std::vector<std::string> *> bs_c_stubs_types,
-	    bs_objc_stubs_types;
-
-	void load_bs_full_file(const char *path);
-
-    private:
-	std::map<ID, GlobalVariable *> ccaches;
-	std::map<SEL, GlobalVariable *> sels;
-	std::map<ID, GlobalVariable *> ids;
-	std::map<ID, GlobalVariable *> global_entries;
-	std::vector<GlobalVariable *> ivar_slots;
-	std::map<VALUE, GlobalVariable *> literals;
-	std::vector<std::string> c_stubs, objc_stubs;
-
-	GlobalVariable *cObject_gvar;
-	GlobalVariable *cStandardError_gvar;
-	std::vector<GlobalVariable *> class_gvars;
-
-	Function *compile_init_function(void);
-	Value *compile_ccache(ID id);
-	Value *compile_sel(SEL sel, bool add_to_bb=true);
-	void compile_prepare_method(Value *classVal, Value *sel,
-		bool singleton, Function *new_function, rb_vm_arity_t &arity,
-		NODE *body);
-	Value *compile_prepare_block_args(Function *func, int *flags);
-	Value *compile_nsobject(void);
-	Value *compile_standarderror(void);
-	Value *compile_id(ID id);
-	Value *compile_immutable_literal(VALUE val);
-	Value *compile_global_entry(NODE *node);
-	Value *compile_slot_cache(ID id);
-
-	Constant *
-	compile_const_pointer(void *ptr, const PointerType *type=NULL) {
-	    if (ptr == NULL) {
-		return RoxorCompiler::compile_const_pointer(ptr, type);
-	    }
-	    printf("compile_const_pointer() called with a non-NULL pointer " \
-		   "on the AOT compiler - leaving the ship!\n");
-	    abort();
-	}
-};
-
-#endif // !MACRUBY_STATIC
-
-#endif /* __cplusplus */
-
-#endif /* __COMPILER_H_ */

Deleted: MacRuby/trunk/complex.c
===================================================================
--- MacRuby/trunk/complex.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/complex.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2046 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2008-2009, Tadayoshi Funaba
- */
-
-#include "macruby_internal.h"
-#include <math.h>
-#include "ruby/node.h"
-#include "vm.h"
-#include "id.h"
-
-#define NDEBUG
-#include <assert.h>
-
-#define ZERO INT2FIX(0)
-#define ONE INT2FIX(1)
-#define TWO INT2FIX(2)
-
-VALUE rb_cComplex;
-
-static SEL sel_abs, sel_abs2, sel_arg, sel_cmp, sel_conj, sel_convert,
-    sel_denominator, sel_divmod, sel_expt, sel_fdiv,  sel_floor,
-    sel_idiv, sel_imag, sel_inspect, sel_negate, sel_numerator, sel_quo,
-    sel_real, sel_real_p, sel_to_f, sel_to_i, sel_to_r, sel_to_s;
-
-#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
-
-#define binop(n,op) \
-inline static VALUE \
-f_##n(VALUE x, VALUE y)\
-{\
-    return rb_vm_call(x, op, 1, &y);\
-}
-
-#define fun1(n) \
-inline static VALUE \
-f_##n(VALUE x)\
-{\
-    return rb_vm_call(x, sel_##n, 0, NULL);\
-}
-
-#define fun2(n) \
-inline static VALUE \
-f_##n(VALUE x, VALUE y)\
-{\
-    return rb_vm_call(x, sel_##n, 1, &y);\
-}
-
-#define math1(n) \
-inline static VALUE \
-m_##n(VALUE x)\
-{\
-    return rb_vm_call(rb_mMath, sel_##n, 1, &x);\
-}
-
-#define math2(n) \
-inline static VALUE \
-m_##n(VALUE x, VALUE y)\
-{\
-    VALUE args[2]; args[0] = x; args[1] = y;\
-    return rb_vm_call(rb_mMath, sel_##n, 2, args);\
-}
-
-#define PRESERVE_SIGNEDZERO
-
-inline static VALUE
-f_add(VALUE x, VALUE y)
-{
-#ifndef PRESERVE_SIGNEDZERO
-    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
-	return x;
-    else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
-	return y;
-#endif
-    return rb_vm_call(x, selPLUS, 1, &y);
-}
-
-inline static VALUE
-f_cmp(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y)) {
-	long c = FIX2LONG(x) - FIX2LONG(y);
-	if (c > 0) {
-	    c = 1;
-	}
-	else if (c < 0) {
-	    c = -1;
-	}
-	return INT2FIX(c);
-    }
-    return rb_vm_call(x, selCmp, 1, &y);
-}
-
-inline static VALUE
-f_div(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y) && FIX2LONG(y) == 1) {
-	return x;
-    }
-    return rb_vm_call(x, selDIV, 1, &y);
-}
-
-inline static VALUE
-f_gt_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y)) {
-	return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
-    }
-    return rb_vm_call(x, selGT, 1, &y);
-}
-
-inline static VALUE
-f_lt_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y)) {
-	return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
-    }
-    return rb_vm_call(x, selLT, 1, &y);
-}
-
-binop(mod, selMOD)
-
-inline static VALUE
-f_mul(VALUE x, VALUE y)
-{
-#ifndef PRESERVE_SIGNEDZERO
-    if (FIXNUM_P(y)) {
-	long iy = FIX2LONG(y);
-	if (iy == 0) {
-	    if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM)
-		return ZERO;
-	}
-	else if (iy == 1)
-	    return x;
-    }
-    else if (FIXNUM_P(x)) {
-	long ix = FIX2LONG(x);
-	if (ix == 0) {
-	    if (FIXNUM_P(y) || TYPE(y) == T_BIGNUM)
-		return ZERO;
-	}
-	else if (ix == 1)
-	    return y;
-    }
-#endif
-    return rb_vm_call(x, selMULT, 1, &y);
-}
-
-inline static VALUE
-f_sub(VALUE x, VALUE y)
-{
-#ifndef PRESERVE_SIGNEDZERO
-    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
-	return x;
-#endif
-    return rb_vm_call(x, selMINUS, 1, &y);
-}
-
-fun1(abs)
-fun1(abs2)
-fun1(arg)
-fun1(conj)
-fun1(denominator)
-fun1(floor)
-fun1(imag)
-fun1(inspect)
-fun1(negate)
-fun1(numerator)
-fun1(real)
-fun1(real_p)
-
-fun1(to_f)
-fun1(to_i)
-fun1(to_r)
-fun1(to_s)
-
-fun2(divmod)
-
-inline static VALUE
-f_eqeq_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y)) {
-	return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
-    }
-    return rb_vm_call(x, selEq, 1, &y);
-}
-
-fun2(expt)
-fun2(fdiv)
-fun2(idiv)
-fun2(quo)
-
-inline static VALUE
-f_negative_p(VALUE x)
-{
-    if (FIXNUM_P(x)) {
-	return f_boolcast(FIX2LONG(x) < 0);
-    }
-    VALUE v = ZERO;
-    return rb_vm_call(x, selLT, 1, &v);
-}
-
-#define f_positive_p(x) (!f_negative_p(x))
-
-inline static VALUE
-f_zero_p(VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-	return f_boolcast(FIX2LONG(x) == 0);
-      case T_BIGNUM:
-	return Qfalse;
-      case T_RATIONAL:
-      {
-	  VALUE num = RRATIONAL(x)->num;
-
-	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
-      }
-    }
-    VALUE v = ZERO;
-    return rb_vm_call(x, selEq, 1, &v);
-}
-
-#define f_nonzero_p(x) (!f_zero_p(x))
-
-inline static VALUE
-f_one_p(VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-	return f_boolcast(FIX2LONG(x) == 1);
-      case T_BIGNUM:
-	return Qfalse;
-      case T_RATIONAL:
-      {
-	  VALUE num = RRATIONAL(x)->num;
-	  VALUE den = RRATIONAL(x)->den;
-
-	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
-			    FIXNUM_P(den) && FIX2LONG(den) == 1);
-      }
-    }
-    VALUE v = ONE;
-    return rb_vm_call(x, selEq, 1, &v);
-}
-
-inline static VALUE
-f_kind_of_p(VALUE x, VALUE c)
-{
-    return rb_obj_is_kind_of(x, c);
-}
-
-inline static VALUE
-k_numeric_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cNumeric);
-}
-
-inline static VALUE
-k_integer_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cInteger);
-}
-
-inline static VALUE
-k_fixnum_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cFixnum);
-}
-
-inline static VALUE
-k_bignum_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cBignum);
-}
-
-inline static VALUE
-k_float_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cFloat);
-}
-
-inline static VALUE
-k_rational_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cRational);
-}
-
-inline static VALUE
-k_complex_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cComplex);
-}
-
-#define k_exact_p(x) (!k_float_p(x))
-#define k_inexact_p(x) k_float_p(x)
-
-#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
-#define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
-
-#define get_dat1(x) \
-    struct RComplex *dat;\
-    dat = ((struct RComplex *)(x))
-
-#define get_dat2(x,y) \
-    struct RComplex *adat, *bdat;\
-    adat = ((struct RComplex *)(x));\
-    bdat = ((struct RComplex *)(y))
-
-inline static VALUE
-nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
-{
-    NEWOBJ(obj, struct RComplex);
-    OBJSETUP(obj, klass, T_COMPLEX);
-
-    GC_WB(&obj->real, real);
-    GC_WB(&obj->imag, imag);
-
-    return (VALUE)obj;
-}
-
-static VALUE
-nucomp_s_alloc(VALUE klass, SEL sel)
-{
-    return nucomp_s_new_internal(klass, ZERO, ZERO);
-}
-
-#if 0
-static VALUE
-nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass)
-{
-    VALUE real, imag;
-
-    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
-      case 1:
-	if (!k_numeric_p(real))
-	    real = f_to_i(real);
-	imag = ZERO;
-	break;
-      default:
-	if (!k_numeric_p(real))
-	    real = f_to_i(real);
-	if (!k_numeric_p(imag))
-	    imag = f_to_i(imag);
-	break;
-    }
-
-    return nucomp_s_new_internal(klass, real, imag);
-}
-#endif
-
-inline static VALUE
-f_complex_new_bang1(VALUE klass, VALUE x)
-{
-    assert(!k_complex_p(x));
-    return nucomp_s_new_internal(klass, x, ZERO);
-}
-
-inline static VALUE
-f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
-{
-    assert(!k_complex_p(x));
-    assert(!k_complex_p(y));
-    return nucomp_s_new_internal(klass, x, y);
-}
-
-#ifdef CANONICALIZATION_FOR_MATHN
-#define CANON
-#endif
-
-#ifdef CANON
-static int canonicalization = 0;
-
-void
-nucomp_canonicalization(int f)
-{
-    canonicalization = f;
-}
-#endif
-
-inline static void
-nucomp_real_check(VALUE num)
-{
-    switch (TYPE(num)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-      case T_FLOAT:
-      case T_RATIONAL:
-	break;
-      default:
-	if (!k_numeric_p(num) || !f_real_p(num))
-	    rb_raise(rb_eArgError, "not a real");
-    }
-}
-
-inline static VALUE
-nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
-{
-#ifdef CANON
-#define CL_CANON
-#ifdef CL_CANON
-    if (k_exact_zero_p(imag) && canonicalization)
-	return real;
-#else
-    if (f_zero_p(imag) && canonicalization)
-	return real;
-#endif
-#endif
-    if (f_real_p(real) && f_real_p(imag))
-	return nucomp_s_new_internal(klass, real, imag);
-    else if (f_real_p(real)) {
-	get_dat1(imag);
-
-	return nucomp_s_new_internal(klass,
-				     f_sub(real, dat->imag),
-				     f_add(ZERO, dat->real));
-    }
-    else if (f_real_p(imag)) {
-	get_dat1(real);
-
-	return nucomp_s_new_internal(klass,
-				     dat->real,
-				     f_add(dat->imag, imag));
-    }
-    else {
-	get_dat2(real, imag);
-
-	return nucomp_s_new_internal(klass,
-				     f_sub(adat->real, bdat->imag),
-				     f_add(adat->imag, bdat->real));
-    }
-}
-
-/*
- * call-seq:
- *    Complex.rect(real[, imag])         ->  complex
- *    Complex.rectangular(real[, imag])  ->  complex
- *
- * Returns a complex object which denotes the given rectangular form.
- */
-static VALUE
-nucomp_s_new(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE real, imag;
-
-    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
-      case 1:
-	nucomp_real_check(real);
-	imag = ZERO;
-	break;
-      default:
-	nucomp_real_check(real);
-	nucomp_real_check(imag);
-	break;
-    }
-
-    return nucomp_s_canonicalize_internal(klass, real, imag);
-}
-
-inline static VALUE
-f_complex_new1(VALUE klass, VALUE x)
-{
-    assert(!k_complex_p(x));
-    return nucomp_s_canonicalize_internal(klass, x, ZERO);
-}
-
-inline static VALUE
-f_complex_new2(VALUE klass, VALUE x, VALUE y)
-{
-    assert(!k_complex_p(x));
-    return nucomp_s_canonicalize_internal(klass, x, y);
-}
-
-/*
- * call-seq:
- *    Complex(x[, y])  ->  numeric
- *
- * Returns x+i*y;
- */
-static VALUE
-nucomp_f_complex(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    return rb_vm_call(rb_cComplex, sel_convert, argc, argv);
-}
-
-#define imp1(n) \
-extern VALUE math_##n(VALUE obj, SEL sel, VALUE x);\
-inline static VALUE \
-m_##n##_bang(VALUE x)\
-{\
-    return math_##n(Qnil, 0, x);\
-}
-
-#define imp2(n) \
-extern VALUE math_##n(VALUE obj, SEL sel, VALUE x, VALUE y);\
-inline static VALUE \
-m_##n##_bang(VALUE x, VALUE y)\
-{\
-    return math_##n(Qnil, 0, x, y);\
-}
-
-imp2(atan2)
-imp1(cos)
-imp1(cosh)
-imp1(exp)
-imp2(hypot)
-
-#define m_hypot(x,y) m_hypot_bang(x,y)
-
-extern VALUE math_log(VALUE rcv, SEL sel, int argc, VALUE *argv);
-
-static VALUE
-m_log_bang(VALUE x)
-{
-    return math_log(0, 0, 1, &x);
-}
-
-imp1(sin)
-imp1(sinh)
-imp1(sqrt)
-
-static VALUE
-m_cos(VALUE x)
-{
-    if (f_real_p(x))
-	return m_cos_bang(x);
-    {
-	get_dat1(x);
-	return f_complex_new2(rb_cComplex,
-			      f_mul(m_cos_bang(dat->real),
-				    m_cosh_bang(dat->imag)),
-			      f_mul(f_negate(m_sin_bang(dat->real)),
-				    m_sinh_bang(dat->imag)));
-    }
-}
-
-static VALUE
-m_sin(VALUE x)
-{
-    if (f_real_p(x))
-	return m_sin_bang(x);
-    {
-	get_dat1(x);
-	return f_complex_new2(rb_cComplex,
-			      f_mul(m_sin_bang(dat->real),
-				    m_cosh_bang(dat->imag)),
-			      f_mul(m_cos_bang(dat->real),
-				    m_sinh_bang(dat->imag)));
-    }
-}
-
-#if 0
-static VALUE
-m_sqrt(VALUE x)
-{
-    if (f_real_p(x)) {
-	if (f_positive_p(x))
-	    return m_sqrt_bang(x);
-	return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
-    }
-    else {
-	get_dat1(x);
-
-	if (f_negative_p(dat->imag))
-	    return f_conj(m_sqrt(f_conj(x)));
-	else {
-	    VALUE a = f_abs(x);
-	    return f_complex_new2(rb_cComplex,
-				  m_sqrt_bang(f_div(f_add(a, dat->real), TWO)),
-				  m_sqrt_bang(f_div(f_sub(a, dat->real), TWO)));
-	}
-    }
-}
-#endif
-
-inline static VALUE
-f_complex_polar(VALUE klass, VALUE x, VALUE y)
-{
-    assert(!k_complex_p(x));
-    assert(!k_complex_p(y));
-    return nucomp_s_canonicalize_internal(klass,
-					  f_mul(x, m_cos(y)),
-					  f_mul(x, m_sin(y)));
-}
-
-/*
- * call-seq:
- *    Complex.polar(abs[, arg])  ->  complex
- *
- * Returns a complex object which denotes the given polar form.
- */
-static VALUE
-nucomp_s_polar(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE abs, arg;
-
-    switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
-      case 1:
-	nucomp_real_check(abs);
-	arg = ZERO;
-	break;
-      default:
-	nucomp_real_check(abs);
-	nucomp_real_check(arg);
-	break;
-    }
-    return f_complex_polar(klass, abs, arg);
-}
-
-/*
- * call-seq:
- *    cmp.real  ->  real
- *
- * Returns the real part.
- */
-static VALUE
-nucomp_real(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return dat->real;
-}
-
-/*
- * call-seq:
- *    cmp.imag       ->  real
- *    cmp.imaginary  ->  real
- *
- * Returns the imaginary part.
- */
-static VALUE
-nucomp_imag(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return dat->imag;
-}
-
-/*
- * call-seq:
- *    -cmp  ->  complex
- *
- * Returns negation of the value.
- */
-static VALUE
-nucomp_negate(VALUE self, SEL sel)
-{
-  get_dat1(self);
-  return f_complex_new2(CLASS_OF(self),
-			f_negate(dat->real), f_negate(dat->imag));
-}
-
-inline static VALUE
-f_addsub(VALUE self, VALUE other,
-	 VALUE (*func)(VALUE, VALUE), SEL op)
-{
-    if (k_complex_p(other)) {
-	VALUE real, imag;
-
-	get_dat2(self, other);
-
-	real = (*func)(adat->real, bdat->real);
-	imag = (*func)(adat->imag, bdat->imag);
-
-	return f_complex_new2(CLASS_OF(self), real, imag);
-    }
-    if (k_numeric_p(other) && f_real_p(other)) {
-	get_dat1(self);
-
-	return f_complex_new2(CLASS_OF(self),
-			      (*func)(dat->real, other), dat->imag);
-    }
-    return rb_objc_num_coerce_bin(self, other, op);
-}
-
-/*
- * call-seq:
- *    cmp + numeric  ->  complex
- *
- * Performs addition.
- */
-static VALUE
-nucomp_add(VALUE self, SEL sel, VALUE other)
-{
-    return f_addsub(self, other, f_add, selPLUS);
-}
-
-VALUE
-rb_nu_plus(VALUE x, VALUE y)
-{
-    return f_addsub(x, y, f_add, selPLUS);
-}
-
-/*
- * call-seq:
- *    cmp - numeric  ->  complex
- *
- * Performs subtraction.
- */
-static VALUE
-nucomp_sub(VALUE self, SEL sel, VALUE other)
-{
-    return f_addsub(self, other, f_sub, selMINUS);
-}
-
-VALUE
-rb_nu_minus(VALUE x, VALUE y)
-{
-    return f_addsub(x, y, f_sub, selMINUS);
-}
-
-/*
- * call-seq:
- *    cmp * numeric  ->  complex
- *
- * Performs multiplication.
- */
-static VALUE
-nucomp_mul(VALUE self, SEL sel, VALUE other)
-{
-    if (k_complex_p(other)) {
-	VALUE real, imag;
-
-	get_dat2(self, other);
-
-	real = f_sub(f_mul(adat->real, bdat->real),
-		     f_mul(adat->imag, bdat->imag));
-	imag = f_add(f_mul(adat->real, bdat->imag),
-		     f_mul(adat->imag, bdat->real));
-
-	return f_complex_new2(CLASS_OF(self), real, imag);
-    }
-    if (k_numeric_p(other) && f_real_p(other)) {
-	get_dat1(self);
-
-	return f_complex_new2(CLASS_OF(self),
-			      f_mul(dat->real, other),
-			      f_mul(dat->imag, other));
-    }
-    return rb_objc_num_coerce_bin(self, other, selMULT);
-}
-
-VALUE
-rb_nu_mul(VALUE x, VALUE y)
-{
-    return nucomp_mul(x, 0, y);
-}
-
-inline static VALUE
-f_divide(VALUE self, VALUE other,
-	 VALUE (*func)(VALUE, VALUE), SEL op)
-{
-    if (k_complex_p(other)) {
-	int flo;
-	get_dat2(self, other);
-
-	flo = (k_float_p(adat->real) || k_float_p(adat->imag) ||
-	       k_float_p(bdat->real) || k_float_p(bdat->imag));
-
-	if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
-	    VALUE r, n;
-
-	    r = (*func)(bdat->imag, bdat->real);
-	    n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
-	    if (flo)
-		return f_complex_new2(CLASS_OF(self),
-				      (*func)(self, n),
-				      (*func)(f_negate(f_mul(self, r)), n));
-	    return f_complex_new2(CLASS_OF(self),
-				  (*func)(f_add(adat->real,
-						f_mul(adat->imag, r)), n),
-				  (*func)(f_sub(adat->imag,
-						f_mul(adat->real, r)), n));
-	}
-	else {
-	    VALUE r, n;
-
-	    r = (*func)(bdat->real, bdat->imag);
-	    n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
-	    if (flo)
-		return f_complex_new2(CLASS_OF(self),
-				      (*func)(f_mul(self, r), n),
-				      (*func)(f_negate(self), n));
-	    return f_complex_new2(CLASS_OF(self),
-				  (*func)(f_add(f_mul(adat->real, r),
-						adat->imag), n),
-				  (*func)(f_sub(f_mul(adat->imag, r),
-						adat->real), n));
-	}
-    }
-    if (k_numeric_p(other) && f_real_p(other)) {
-	get_dat1(self);
-
-	return f_complex_new2(CLASS_OF(self),
-			      (*func)(dat->real, other),
-			      (*func)(dat->imag, other));
-    }
-    return rb_objc_num_coerce_bin(self, other, op);
-}
-
-#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
-
-/*
- * call-seq:
- *    cmp / numeric     ->  complex
- *    cmp.quo(numeric)  ->  complex
- *
- * Performs division.
- *
- * For example:
- *
- *     Complex(10.0) / 3  #=> (3.3333333333333335+(0/1)*i)
- *     Complex(10)   / 3  #=> ((10/3)+(0/1)*i)  # not (3+0i)
- */
-static VALUE
-nucomp_div(VALUE self, SEL sel, VALUE other)
-{
-    if (f_zero_p(other)) {
-	rb_raise_zerodiv();
-    }
-    return f_divide(self, other, f_quo, sel_quo);
-}
-
-VALUE
-rb_nu_div(VALUE x, VALUE y)
-{
-    return nucomp_div(x, 0, y);
-}
-
-#define nucomp_quo nucomp_div
-
-/*
- * call-seq:
- *    cmp.fdiv(numeric)  ->  complex
- *
- * Performs division as each part is a float, never returns a float.
- *
- * For example:
- *
- *     Complex(11,22).fdiv(3)  #=> (3.6666666666666665+7.333333333333333i)
- */
-static VALUE
-nucomp_fdiv(VALUE self, SEL sel, VALUE other)
-{
-    return f_divide(self, other, f_fdiv, sel_fdiv);
-}
-
-static VALUE
-m_log(VALUE x)
-{
-    if (f_real_p(x) && f_positive_p(x))
-	return m_log_bang(x);
-    return rb_complex_new2(m_log_bang(f_abs(x)), f_arg(x));
-}
-
-static VALUE
-m_exp(VALUE x)
-{
-    VALUE ere, im;
-
-    if (f_real_p(x))
-	return m_exp_bang(x);
-    ere = m_exp_bang(f_real(x));
-    im = f_imag(x);
-    return rb_complex_new2(f_mul(ere, m_cos_bang(im)),
-			   f_mul(ere, m_sin_bang(im)));
-}
-
-VALUE
-rb_fexpt(VALUE x, VALUE y)
-{
-    if (f_zero_p(x) || (!k_float_p(x) && !k_float_p(y)))
-	return f_expt(x, y);
-    return m_exp(f_mul(m_log(x), y));
-}
-
-inline static VALUE
-f_reciprocal(VALUE x)
-{
-    return f_quo(ONE, x);
-}
-
-/*
- * call-seq:
- *    cmp ** numeric  ->  complex
- *
- * Performs exponentiation.
- *
- * For example:
- *
- *     Complex('i') ** 2             #=> (-1+0i)
- *     Complex(-8) ** Rational(1,3)  #=> (1.0000000000000002+1.7320508075688772i)
- */
-static VALUE
-nucomp_expt(VALUE self, SEL sel, VALUE other)
-{
-    if (k_exact_zero_p(other))
-	return f_complex_new_bang1(CLASS_OF(self), ONE);
-
-    if (k_rational_p(other) && f_one_p(f_denominator(other)))
-	other = f_numerator(other); /* c14n */
-
-    if (k_complex_p(other)) {
-	get_dat1(other);
-
-	if (k_exact_zero_p(dat->imag))
-	    other = dat->real; /* c14n */
-    }
-
-    if (k_complex_p(other)) {
-	VALUE r, theta, nr, ntheta;
-
-	get_dat1(other);
-
-	r = f_abs(self);
-	theta = f_arg(self);
-
-	nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
-			      f_mul(dat->imag, theta)));
-	ntheta = f_add(f_mul(theta, dat->real),
-		       f_mul(dat->imag, m_log_bang(r)));
-	return f_complex_polar(CLASS_OF(self), nr, ntheta);
-    }
-    if (k_fixnum_p(other)) {
-	if (f_gt_p(other, ZERO)) {
-	    VALUE x, z;
-	    long n;
-
-	    x = self;
-	    z = x;
-	    n = FIX2LONG(other) - 1;
-
-	    while (n) {
-		long q, r;
-
-		while (1) {
-		    get_dat1(x);
-
-		    q = n / 2;
-		    r = n % 2;
-
-		    if (r)
-			break;
-
-		    x = f_complex_new2(CLASS_OF(self),
-				       f_sub(f_mul(dat->real, dat->real),
-					     f_mul(dat->imag, dat->imag)),
-				       f_mul(f_mul(TWO, dat->real), dat->imag));
-		    n = q;
-		}
-		z = f_mul(z, x);
-		n--;
-	    }
-	    return z;
-	}
-	return f_expt(f_reciprocal(self), f_negate(other));
-    }
-    if (k_numeric_p(other) && f_real_p(other)) {
-	VALUE r, theta;
-
-	if (k_bignum_p(other))
-	    rb_warn("in a**b, b may be too big");
-
-	r = f_abs(self);
-	theta = f_arg(self);
-
-	return f_complex_polar(CLASS_OF(self), f_expt(r, other),
-			       f_mul(theta, other));
-    }
-    return rb_objc_num_coerce_bin(self, other, sel_expt);
-}
-
-/*
- * call-seq:
- *    cmp == object  ->  true or false
- *
- * Returns true if cmp equals object numerically.
- */
-static VALUE
-nucomp_eqeq_p(VALUE self, SEL sel, VALUE other)
-{
-    if (k_complex_p(other)) {
-	get_dat2(self, other);
-
-	return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
-			  f_eqeq_p(adat->imag, bdat->imag));
-    }
-    if (k_numeric_p(other) && f_real_p(other)) {
-	get_dat1(self);
-
-	return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
-    }
-    return f_eqeq_p(other, self);
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_coerce(VALUE self, SEL sel, VALUE other)
-{
-    if (k_numeric_p(other) && f_real_p(other))
-	return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
-    if (TYPE(other) == T_COMPLEX)
-	return rb_assoc_new(other, self);
-
-    rb_raise(rb_eTypeError, "%s can't be coerced into %s",
-	     rb_obj_classname(other), rb_obj_classname(self));
-    return Qnil;
-}
-
-/*
- * call-seq:
- *    cmp.abs        ->  real
- *    cmp.magnitude  ->  real
- *
- * Returns the absolute part of its polar form.
- */
-static VALUE
-nucomp_abs(VALUE self, SEL sel)
-{
-    get_dat1(self);
-
-    if (f_zero_p(dat->real)) {
-	VALUE a = f_abs(dat->imag);
-	if (k_float_p(dat->real) && !k_float_p(dat->imag))
-	    a = f_to_f(a);
-	return a;
-    }
-    if (f_zero_p(dat->imag)) {
-	VALUE a = f_abs(dat->real);
-	if (!k_float_p(dat->real) && k_float_p(dat->imag))
-	    a = f_to_f(a);
-	return a;
-    }
-    return m_hypot(dat->real, dat->imag);
-}
-
-/*
- * call-seq:
- *    cmp.abs2  ->  real
- *
- * Returns square of the absolute value.
- */
-static VALUE
-nucomp_abs2(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return f_add(f_mul(dat->real, dat->real),
-		 f_mul(dat->imag, dat->imag));
-}
-
-/*
- * call-seq:
- *    cmp.arg    ->  float
- *    cmp.angle  ->  float
- *    cmp.phase  ->  float
- *
- * Returns the angle part of its polar form.
- */
-static VALUE
-nucomp_arg(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return m_atan2_bang(dat->imag, dat->real);
-}
-
-/*
- * call-seq:
- *    cmp.rect         ->  array
- *    cmp.rectangular  ->  array
- *
- * Returns an array; [cmp.real, cmp.imag].
- */
-static VALUE
-nucomp_rect(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return rb_assoc_new(dat->real, dat->imag);
-}
-
-/*
- * call-seq:
- *    cmp.polar  ->  array
- *
- * Returns an array; [cmp.abs, cmp.arg].
- */
-static VALUE
-nucomp_polar(VALUE self, SEL sel)
-{
-    return rb_assoc_new(f_abs(self), f_arg(self));
-}
-
-/*
- * call-seq:
- *    cmp.conj       ->  complex
- *    cmp.conjucate  ->  complex
- *
- * Returns the complex conjucate.
- */
-static VALUE
-nucomp_conj(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
-}
-
-#if 0
-/* :nodoc: */
-static VALUE
-nucomp_true(VALUE self)
-{
-    return Qtrue;
-}
-#endif
-
-/*
- * call-seq:
- *    cmp.real?  ->  false
- *
- * Returns false.
- */
-static VALUE
-nucomp_false(VALUE self, SEL sel)
-{
-    return Qfalse;
-}
-
-#if 0
-/* :nodoc: */
-static VALUE
-nucomp_exact_p(VALUE self)
-{
-    get_dat1(self);
-    return f_boolcast(k_exact_p(dat->real) && k_exact_p(dat->imag));
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_inexact_p(VALUE self)
-{
-    return f_boolcast(!nucomp_exact_p(self));
-}
-#endif
-
-extern VALUE rb_lcm(VALUE x, SEL sel, VALUE y);
-
-/*
- * call-seq:
- *    cmp.denominator  ->  integer
- *
- * Returns the denominator (lcm of both denominator, real and imag).
- *
- * See numerator.
- */
-static VALUE
-nucomp_denominator(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return rb_lcm(f_denominator(dat->real), 0, f_denominator(dat->imag));
-}
-
-/*
- * call-seq:
- *    cmp.numerator  ->  numeric
- *
- * Returns the numerator.
- *
- * For example:
- *
- *        1   2       3+4i  <-  numerator
- *        - + -i  ->  ----
- *        2   3        6    <-  denominator
- *
- *    c = Complex('1/2+2/3i')  #=> ((1/2)+(2/3)*i)
- *    n = c.numerator          #=> (3+4i)
- *    d = c.denominator        #=> 6
- *    n / d                    #=> ((1/2)+(2/3)*i)
- *    Complex(Rational(n.real, d), Rational(n.imag, d))
- *                             #=> ((1/2)+(2/3)*i)
- * See denominator.
- */
-static VALUE
-nucomp_numerator(VALUE self, SEL sel)
-{
-    VALUE cd;
-
-    get_dat1(self);
-
-    cd = f_denominator(self);
-    return f_complex_new2(CLASS_OF(self),
-			  f_mul(f_numerator(dat->real),
-				f_div(cd, f_denominator(dat->real))),
-			  f_mul(f_numerator(dat->imag),
-				f_div(cd, f_denominator(dat->imag))));
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_hash(VALUE self, SEL sel)
-{
-    long v, h[2];
-    VALUE n;
-
-    get_dat1(self);
-    n = rb_hash(dat->real);
-    h[0] = NUM2LONG(n);
-    n = rb_hash(dat->imag);
-    h[1] = NUM2LONG(n);
-    v = rb_memhash(h, sizeof(h));
-    return LONG2FIX(v);
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_eql_p(VALUE self, SEL sel, VALUE other)
-{
-    if (k_complex_p(other)) {
-	get_dat2(self, other);
-
-	return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
-			  (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
-			  f_eqeq_p(self, other));
-
-    }
-    return Qfalse;
-}
-
-#ifndef HAVE_SIGNBIT
-#ifdef signbit
-#define HAVE_SIGNBIT 1
-#endif
-#endif
-
-inline static VALUE
-f_signbit(VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FLOAT: {
-#ifdef HAVE_SIGNBIT
-	double f = RFLOAT_VALUE(x);
-	return f_boolcast(!isnan(f) && signbit(f));
-#else
-	char s[2];
-	double f = RFLOAT_VALUE(x);
-
-	if (isnan(f)) return Qfalse;
-	(void)snprintf(s, sizeof s, "%.0f", f);
-	return f_boolcast(s[0] == '-');
-#endif
-      }
-    }
-    return f_negative_p(x);
-}
-
-inline static VALUE
-f_tpositive_p(VALUE x)
-{
-    return f_boolcast(!f_signbit(x));
-}
-
-static VALUE
-f_format(VALUE self, VALUE (*func)(VALUE))
-{
-    VALUE s, impos;
-
-    get_dat1(self);
-
-    impos = f_tpositive_p(dat->imag);
-
-    s = (*func)(dat->real);
-    rb_str_cat2(s, !impos ? "-" : "+");
-
-    rb_str_concat(s, (*func)(f_abs(dat->imag)));
-    if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
-	rb_str_cat2(s, "*");
-    rb_str_cat2(s, "i");
-
-    return s;
-}
-
-/*
- * call-seq:
- *    cmp.to_s  ->  string
- *
- * Returns the value as a string.
- */
-static VALUE
-nucomp_to_s(VALUE self, SEL sel)
-{
-    return f_format(self, f_to_s);
-}
-
-/*
- * call-seq:
- *    cmp.inspect  ->  string
- *
- * Returns the value as a string for inspection.
- */
-static VALUE
-nucomp_inspect(VALUE self, SEL sel)
-{
-    VALUE s;
-
-    s = rb_usascii_str_new2("(");
-    rb_str_concat(s, f_format(self, f_inspect));
-    rb_str_cat2(s, ")");
-
-    return s;
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_marshal_dump(VALUE self, SEL sel)
-{
-    VALUE a;
-    get_dat1(self);
-
-    a = rb_assoc_new(dat->real, dat->imag);
-    rb_copy_generic_ivar(a, self);
-    return a;
-}
-
-/* :nodoc: */
-static VALUE
-nucomp_marshal_load(VALUE self, SEL sel, VALUE a)
-{
-    get_dat1(self);
-    VALUE ary = rb_convert_type(a, T_ARRAY, "Array", "to_ary");
-    GC_WB(&dat->real, RARRAY_AT(ary, 0));
-    GC_WB(&dat->imag, RARRAY_AT(ary, 1));
-    rb_copy_generic_ivar(self, ary);
-    return self;
-}
-
-/* --- */
-
-VALUE
-rb_complex_raw(VALUE x, VALUE y)
-{
-    return nucomp_s_new_internal(rb_cComplex, x, y);
-}
-
-VALUE
-rb_complex_new(VALUE x, VALUE y)
-{
-    return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
-}
-
-VALUE
-rb_complex_polar(VALUE x, VALUE y)
-{
-    return f_complex_polar(rb_cComplex, x, y);
-}
-
-static VALUE nucomp_s_convert(VALUE klass, SEL sel, int argc, VALUE *argv);
-
-VALUE
-rb_Complex(VALUE x, VALUE y)
-{
-    VALUE a[2];
-    a[0] = x;
-    a[1] = y;
-    return nucomp_s_convert(rb_cComplex, NULL, 2, a);
-}
-
-/*
- * call-seq:
- *    cmp.to_i  ->  integer
- *
- * Returns the value as an integer if possible.
- */
-static VALUE
-nucomp_to_i(VALUE self, SEL sel)
-{
-    get_dat1(self);
-
-    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
-	VALUE s = f_to_s(self);
-	rb_raise(rb_eRangeError, "can't convert %s into Integer",
-		 StringValuePtr(s));
-    }
-    return f_to_i(dat->real);
-}
-
-/*
- * call-seq:
- *    cmp.to_f  ->  float
- *
- * Returns the value as a float if possible.
- */
-static VALUE
-nucomp_to_f(VALUE self, SEL sel)
-{
-    get_dat1(self);
-
-    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
-	VALUE s = f_to_s(self);
-	rb_raise(rb_eRangeError, "can't convert %s into Float",
-		 StringValuePtr(s));
-    }
-    return f_to_f(dat->real);
-}
-
-/*
- * call-seq:
- *    cmp.to_r  ->  rational
- *
- * Returns the value as a rational if possible.
- */
-static VALUE
-nucomp_to_r(VALUE self, SEL sel)
-{
-    get_dat1(self);
-
-    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
-	VALUE s = f_to_s(self);
-	rb_raise(rb_eRangeError, "can't convert %s into Rational",
-		 StringValuePtr(s));
-    }
-    return f_to_r(dat->real);
-}
-
-/*
- * call-seq:
- *    nil.to_c  ->  (0+0i)
- *
- * Returns zero as a complex.
- */
-static VALUE
-nilclass_to_c(VALUE self, SEL sel)
-{
-    return rb_complex_new1(INT2FIX(0));
-}
-
-/*
- * call-seq:
- *    num.to_c  ->  complex
- *
- * Returns the value as a complex.
- */
-static VALUE
-numeric_to_c(VALUE self, SEL sel)
-{
-    return rb_complex_new1(self);
-}
-
-static VALUE comp_pat0, comp_pat1, comp_pat2, a_slash, a_dot_and_an_e,
-    null_string, underscores_pat, an_underscore;
-
-#define WS "\\s*"
-#define DIGITS "(?:[0-9](?:_[0-9]|[0-9])*)"
-#define NUMERATOR "(?:" DIGITS "?\\.)?" DIGITS "(?:[eE][-+]?" DIGITS ")?"
-#define DENOMINATOR DIGITS
-#define NUMBER "[-+]?" NUMERATOR "(?:\\/" DENOMINATOR ")?"
-#define NUMBERNOS NUMERATOR "(?:\\/" DENOMINATOR ")?"
-#define PATTERN0 "\\A" WS "(" NUMBER ")@(" NUMBER ")" WS
-#define PATTERN1 "\\A" WS "([-+])?(" NUMBER ")?[iIjJ]" WS
-#define PATTERN2 "\\A" WS "(" NUMBER ")(([-+])(" NUMBERNOS ")?[iIjJ])?" WS
-
-static void
-make_patterns(void)
-{
-    static const char comp_pat0_source[] = PATTERN0;
-    static const char comp_pat1_source[] = PATTERN1;
-    static const char comp_pat2_source[] = PATTERN2;
-    static const char underscores_pat_source[] = "_+";
-
-    if (comp_pat0) return;
-
-    comp_pat0 = rb_reg_new(comp_pat0_source, sizeof comp_pat0_source - 1, 0);
-    rb_register_mark_object(comp_pat0);
-
-    comp_pat1 = rb_reg_new(comp_pat1_source, sizeof comp_pat1_source - 1, 0);
-    rb_register_mark_object(comp_pat1);
-
-    comp_pat2 = rb_reg_new(comp_pat2_source, sizeof comp_pat2_source - 1, 0);
-    rb_register_mark_object(comp_pat2);
-
-    a_slash = rb_usascii_str_new2("/");
-    rb_register_mark_object(a_slash);
-
-    a_dot_and_an_e = rb_usascii_str_new2(".eE");
-    rb_register_mark_object(a_dot_and_an_e);
-
-    null_string = rb_usascii_str_new2("");
-    rb_register_mark_object(null_string);
-
-    underscores_pat = rb_reg_new(underscores_pat_source,
-				 sizeof underscores_pat_source - 1, 0);
-    rb_register_mark_object(underscores_pat);
-
-    an_underscore = rb_usascii_str_new2("_");
-    rb_register_mark_object(an_underscore);
-}
-
-#define id_match rb_intern("match")
-#define f_match(x,y) rb_funcall(x, id_match, 1, y)
-
-#define id_aref rb_intern("[]")
-#define f_aref(x,y) rb_funcall(x, id_aref, 1, y)
-
-#define id_post_match rb_intern("post_match")
-#define f_post_match(x) rb_funcall(x, id_post_match, 0)
-
-#define id_split rb_intern("split")
-#define f_split(x,y) rb_funcall(x, id_split, 1, y)
-
-#define id_include_p rb_intern("include?")
-#define f_include_p(x,y) rb_funcall(x, id_include_p, 1, y)
-
-#define id_count rb_intern("count")
-#define f_count(x,y) rb_funcall(x, id_count, 1, y)
-
-#define id_gsub_bang rb_intern("gsub!")
-#define f_gsub_bang(x,y,z) rb_funcall(x, id_gsub_bang, 2, y, z)
-
-static VALUE
-string_to_c_internal(VALUE self)
-{
-    VALUE s;
-
-    s = self;
-
-    if (RSTRING_LEN(s) == 0)
-	return rb_assoc_new(Qnil, self);
-
-    {
-	VALUE m, sr, si, re, r, i;
-	int po;
-
-	m = f_match(comp_pat0, s);
-	if (!NIL_P(m)) {
-	  sr = f_aref(m, INT2FIX(1));
-	  si = f_aref(m, INT2FIX(2));
-	  re = f_post_match(m);
-	  po = 1;
-	}
-	if (NIL_P(m)) {
-	    m = f_match(comp_pat1, s);
-	    if (!NIL_P(m)) {
-		sr = Qnil;
-		si = f_aref(m, INT2FIX(1));
-		if (NIL_P(si))
-		    si = rb_usascii_str_new2("");
-		{
-		    VALUE t;
-
-		    t = f_aref(m, INT2FIX(2));
-		    if (NIL_P(t))
-			t = rb_usascii_str_new2("1");
-		    rb_str_concat(si, t);
-		}
-		re = f_post_match(m);
-		po = 0;
-	    }
-	}
-	if (NIL_P(m)) {
-	    m = f_match(comp_pat2, s);
-	    if (NIL_P(m))
-		return rb_assoc_new(Qnil, self);
-	    sr = f_aref(m, INT2FIX(1));
-	    if (NIL_P(f_aref(m, INT2FIX(2))))
-		si = Qnil;
-	    else {
-		VALUE t;
-
-		si = f_aref(m, INT2FIX(3));
-		t = f_aref(m, INT2FIX(4));
-		if (NIL_P(t))
-		    t = rb_usascii_str_new2("1");
-		rb_str_concat(si, t);
-	    }
-	    re = f_post_match(m);
-	    po = 0;
-	}
-	r = INT2FIX(0);
-	i = INT2FIX(0);
-	if (!NIL_P(sr)) {
-	    if (f_include_p(sr, a_slash))
-		r = f_to_r(sr);
-	    else if (f_gt_p(f_count(sr, a_dot_and_an_e), INT2FIX(0)))
-		r = f_to_f(sr);
-	    else
-		r = f_to_i(sr);
-	}
-	if (!NIL_P(si)) {
-	    if (f_include_p(si, a_slash))
-		i = f_to_r(si);
-	    else if (f_gt_p(f_count(si, a_dot_and_an_e), INT2FIX(0)))
-		i = f_to_f(si);
-	    else
-		i = f_to_i(si);
-	}
-	if (po)
-	    return rb_assoc_new(rb_complex_polar(r, i), re);
-	else
-	    return rb_assoc_new(rb_complex_new2(r, i), re);
-    }
-}
-
-static VALUE
-string_to_c_strict(VALUE self)
-{
-    VALUE a = string_to_c_internal(self);
-    if (NIL_P(RARRAY_PTR(a)[0]) || RSTRING_LEN(RARRAY_PTR(a)[1]) > 0) {
-	VALUE s = f_inspect(self);
-	rb_raise(rb_eArgError, "invalid value for convert(): %s",
-		 StringValuePtr(s));
-    }
-    return RARRAY_PTR(a)[0];
-}
-
-#define id_gsub rb_intern("gsub")
-#define f_gsub(x,y,z) rb_funcall(x, id_gsub, 2, y, z)
-
-/*
- * call-seq:
- *    str.to_c  ->  complex
- *
- * Returns a complex which denotes the string form.  The parser
- * ignores leading whitespaces and trailing garbage.  Any digit
- * sequences can be separeted by an underscore.  Returns zero for null
- * or garbage string.
- *
- * For example:
- *
- *    '9'.to_c           #=> (9+0i)
- *    '2.5'.to_c         #=> (2.5+0i)
- *    '2.5/1'.to_c       #=> ((5/2)+0i)
- *    '-3/2'.to_c        #=> ((-3/2)+0i)
- *    '-i'.to_c          #=> (0-1i)
- *    '45i'.to_c         #=> (0+45i)
- *    '3-4i'.to_c        #=> (3-4i)
- *    '-4e2-4e-2i'.to_c  #=> (-400.0-0.04i)
- *    '-0.0-0.0i'.to_c   #=> (-0.0-0.0i)
- *    '1/2+3/4i'.to_c    #=> ((1/2)+(3/4)*i)
- *    'ruby'.to_c        #=> (0+0i)
- */
-static VALUE
-string_to_c(VALUE self, SEL sel)
-{
-    VALUE s, a, backref;
-
-    backref = rb_backref_get();
-    rb_match_busy(backref);
-
-    s = f_gsub(self, underscores_pat, an_underscore);
-    a = string_to_c_internal(s);
-
-    rb_backref_set(backref);
-
-    if (!NIL_P(RARRAY_PTR(a)[0]))
-	return RARRAY_PTR(a)[0];
-    return rb_complex_new1(INT2FIX(0));
-}
-
-static VALUE
-nucomp_s_convert(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE a1, a2, backref;
-
-    rb_scan_args(argc, argv, "11", &a1, &a2);
-
-    if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
-	rb_raise(rb_eTypeError, "can't convert nil into Complex");
-
-    backref = rb_backref_get();
-    rb_match_busy(backref);
-
-    switch (TYPE(a1)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-      case T_FLOAT:
-	break;
-      case T_STRING:
-	a1 = string_to_c_strict(a1);
-	break;
-    }
-
-    switch (TYPE(a2)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-      case T_FLOAT:
-	break;
-      case T_STRING:
-	a2 = string_to_c_strict(a2);
-	break;
-    }
-
-    rb_backref_set(backref);
-
-    switch (TYPE(a1)) {
-      case T_COMPLEX:
-	{
-	    get_dat1(a1);
-
-	    if (k_exact_zero_p(dat->imag))
-		a1 = dat->real;
-	}
-    }
-
-    switch (TYPE(a2)) {
-      case T_COMPLEX:
-	{
-	    get_dat1(a2);
-
-	    if (k_exact_zero_p(dat->imag))
-		a2 = dat->real;
-	}
-    }
-
-    switch (TYPE(a1)) {
-      case T_COMPLEX:
-	if (argc == 1 || (k_exact_zero_p(a2)))
-	    return a1;
-    }
-
-    if (argc == 1) {
-	if (k_numeric_p(a1) && !f_real_p(a1))
-	    return a1;
-	/* expect raise exception for consistency */
-	if (!k_numeric_p(a1))
-	    return rb_convert_type(a1, T_COMPLEX, "Complex", "to_c");
-    }
-    else {
-	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
-	    (!f_real_p(a1) || !f_real_p(a2)))
-	    return f_add(a1,
-			 f_mul(a2,
-			       f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
-    }
-
-    {
-	VALUE argv2[2];
-	argv2[0] = a1;
-	argv2[1] = a2;
-	return nucomp_s_new(klass, NULL, argc, argv2);
-    }
-}
-
-/* --- */
-
-/*
- * call-seq:
- *    num.real  ->  self
- *
- * Returns self.
- */
-static VALUE
-numeric_real(VALUE self, SEL sel)
-{
-    return self;
-}
-
-/*
- * call-seq:
- *    num.imag       ->  0
- *    num.imaginary  ->  0
- *
- * Returns zero.
- */
-static VALUE
-numeric_imag(VALUE self, SEL sel)
-{
-    return INT2FIX(0);
-}
-
-/*
- * call-seq:
- *    num.abs2  ->  real
- *
- * Returns square of self.
- */
-static VALUE
-numeric_abs2(VALUE self, SEL sel)
-{
-    return f_mul(self, self);
-}
-
-#define id_PI rb_intern("PI")
-
-/*
- * call-seq:
- *    num.arg    ->  0 or float
- *    num.angle  ->  0 or float
- *    num.phase  ->  0 or float
- *
- * Returns 0 if the value is positive, pi otherwise.
- */
-static VALUE
-numeric_arg(VALUE self, SEL sel)
-{
-    if (f_positive_p(self))
-	return INT2FIX(0);
-    return rb_const_get(rb_mMath, id_PI);
-}
-
-/*
- * call-seq:
- *    num.rect  ->  array
- *
- * Returns an array; [num, 0].
- */
-static VALUE
-numeric_rect(VALUE self, SEL sel)
-{
-    return rb_assoc_new(self, INT2FIX(0));
-}
-
-/*
- * call-seq:
- *    num.polar  ->  array
- *
- * Returns an array; [num.abs, num.arg].
- */
-static VALUE
-numeric_polar(VALUE self, SEL sel)
-{
-    return rb_assoc_new(f_abs(self), f_arg(self));
-}
-
-/*
- * call-seq:
- *    num.conj       ->  self
- *    num.conjucate  ->  self
- *
- * Returns self.
- */
-static VALUE
-numeric_conj(VALUE self, SEL sel)
-{
-    return self;
-}
-
-/*
- * call-seq:
- *    flo.arg    ->  0 or float
- *    flo.angle  ->  0 or float
- *    flo.phase  ->  0 or float
- *
- * Returns 0 if the value is positive, pi otherwise.
- */
-static VALUE
-float_arg(VALUE self, SEL sel)
-{
-    if (isnan(RFLOAT_VALUE(self)))
-	return self;
-    if (f_tpositive_p(self))
-	return INT2FIX(0);
-    return rb_const_get(rb_mMath, id_PI);
-}
-
-/*
- * A complex number can be represented as a paired real number with
- * imaginary unit; a+bi.  Where a is real part, b is imaginary part
- * and i is imaginary unit.  Real a equals complex a+0i
- * mathematically.
- *
- * In ruby, you can create complex object with Complex, Complex::rect,
- * Complex::polar or to_c method.
- *
- *    Complex(1)           #=> (1+0i)
- *    Complex(2, 3)        #=> (2+3i)
- *    Complex.polar(2, 3)  #=> (-1.9799849932008908+0.2822400161197344i)
- *    3.to_c               #=> (3+0i)
- *
- * You can also create complex object from floating-point numbers or
- * strings.
- *
- *    Complex(0.3)         #=> (0.3+0i)
- *    Complex('0.3-0.5i')  #=> (0.3-0.5i)
- *    Complex('2/3+3/4i')  #=> ((2/3)+(3/4)*i)
- *    Complex('1 at 2')       #=> (-0.4161468365471424+0.9092974268256817i)
- *
- *    0.3.to_c             #=> (0.3+0i)
- *    '0.3-0.5i'.to_c      #=> (0.3-0.5i)
- *    '2/3+3/4i'.to_c      #=> ((2/3)+(3/4)*i)
- *    '1 at 2'.to_c           #=> (-0.4161468365471424+0.9092974268256817i)
- *
- * A complex object is either an exact or an inexact number.
- *
- *    Complex(1, 1) / 2    #=> ((1/2)+(1/2)*i)
- *    Complex(1, 1) / 2.0  #=> (0.5+0.5i)
- */
-void
-Init_Complex(void)
-{
-    assert(fprintf(stderr, "assert() is now active\n"));
-
-    sel_abs = sel_registerName("abs");
-    sel_abs2 = sel_registerName("abs2");
-    sel_arg = sel_registerName("arg");
-    sel_cmp = sel_registerName("<=>");
-    sel_conj = sel_registerName("conj");
-    sel_convert = sel_registerName("convert");
-    sel_denominator = sel_registerName("denominator");
-    sel_divmod = sel_registerName("divmod:");
-    sel_expt = sel_registerName("**:");
-    sel_fdiv = sel_registerName("fdiv:");
-    sel_floor = sel_registerName("floor");
-    sel_idiv = sel_registerName("div:");
-    sel_imag = sel_registerName("imag");
-    sel_inspect = sel_registerName("inspect");
-    sel_negate = sel_registerName("-@");
-    sel_numerator = sel_registerName("numerator");
-    sel_quo = sel_registerName("quo:");
-    sel_real = sel_registerName("real");
-    sel_real_p = sel_registerName("real?");
-    sel_to_f = sel_registerName("to_f");
-    sel_to_i = sel_registerName("to_i");
-    sel_to_r = sel_registerName("to_r");
-    sel_to_s = sel_registerName("to_s");
-
-    rb_cComplex = rb_define_class("Complex", rb_cNumeric);
-
-    rb_objc_define_method(*(VALUE *)rb_cComplex, "alloc", nucomp_s_alloc, 0);
-    rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
-
-#if 0
-    rb_define_private_method(CLASS_OF(rb_cComplex), "new!", nucomp_s_new_bang, -1);
-    rb_define_private_method(CLASS_OF(rb_cComplex), "new", nucomp_s_new, -1);
-#else
-    rb_undef_method(CLASS_OF(rb_cComplex), "new");
-#endif
-
-    rb_objc_define_method(*(VALUE *)rb_cComplex, "rectangular", nucomp_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cComplex, "rect", nucomp_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cComplex, "polar", nucomp_s_polar, -1);
-
-    rb_objc_define_method(rb_mKernel, "Complex", nucomp_f_complex, -1);
-
-    rb_undef_method(rb_cComplex, "%");
-    rb_undef_method(rb_cComplex, "<");
-    rb_undef_method(rb_cComplex, "<=");
-    rb_undef_method(rb_cComplex, "<=>");
-    rb_undef_method(rb_cComplex, ">");
-    rb_undef_method(rb_cComplex, ">=");
-    rb_undef_method(rb_cComplex, "between?");
-    rb_undef_method(rb_cComplex, "div");
-    rb_undef_method(rb_cComplex, "divmod");
-    rb_undef_method(rb_cComplex, "floor");
-    rb_undef_method(rb_cComplex, "ceil");
-    rb_undef_method(rb_cComplex, "modulo");
-    rb_undef_method(rb_cComplex, "remainder");
-    rb_undef_method(rb_cComplex, "round");
-    rb_undef_method(rb_cComplex, "step");
-    rb_undef_method(rb_cComplex, "truncate");
-
-#if 0 /* NUBY */
-    rb_undef_method(rb_cComplex, "//");
-#endif
-
-    rb_objc_define_method(rb_cComplex, "real", nucomp_real, 0);
-    rb_objc_define_method(rb_cComplex, "imaginary", nucomp_imag, 0);
-    rb_objc_define_method(rb_cComplex, "imag", nucomp_imag, 0);
-
-    rb_objc_define_method(rb_cComplex, "-@", nucomp_negate, 0);
-    rb_objc_define_method(rb_cComplex, "+", nucomp_add, 1);
-    rb_objc_define_method(rb_cComplex, "-", nucomp_sub, 1);
-    rb_objc_define_method(rb_cComplex, "*", nucomp_mul, 1);
-    rb_objc_define_method(rb_cComplex, "/", nucomp_div, 1);
-    rb_objc_define_method(rb_cComplex, "quo", nucomp_quo, 1);
-    rb_objc_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 1);
-    rb_objc_define_method(rb_cComplex, "**", nucomp_expt, 1);
-
-    rb_objc_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
-    rb_objc_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
-
-    rb_objc_define_method(rb_cComplex, "abs", nucomp_abs, 0);
-    rb_objc_define_method(rb_cComplex, "magnitude", nucomp_abs, 0);
-    rb_objc_define_method(rb_cComplex, "abs2", nucomp_abs2, 0);
-    rb_objc_define_method(rb_cComplex, "arg", nucomp_arg, 0);
-    rb_objc_define_method(rb_cComplex, "angle", nucomp_arg, 0);
-    rb_objc_define_method(rb_cComplex, "phase", nucomp_arg, 0);
-    rb_objc_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
-    rb_objc_define_method(rb_cComplex, "rect", nucomp_rect, 0);
-    rb_objc_define_method(rb_cComplex, "polar", nucomp_polar, 0);
-    rb_objc_define_method(rb_cComplex, "conjugate", nucomp_conj, 0);
-    rb_objc_define_method(rb_cComplex, "conj", nucomp_conj, 0);
-#if 0
-    rb_define_method(rb_cComplex, "~", nucomp_conj, 0); /* gcc */
-#endif
-
-    rb_objc_define_method(rb_cComplex, "real?", nucomp_false, 0);
-#if 0
-    rb_define_method(rb_cComplex, "complex?", nucomp_true, 0);
-    rb_define_method(rb_cComplex, "exact?", nucomp_exact_p, 0);
-    rb_define_method(rb_cComplex, "inexact?", nucomp_inexact_p, 0);
-#endif
-
-    rb_objc_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
-    rb_objc_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
-
-    rb_objc_define_method(rb_cComplex, "hash", nucomp_hash, 0);
-    rb_objc_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
-
-    rb_objc_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
-    rb_objc_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
-
-    rb_objc_define_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
-    rb_objc_define_method(rb_cComplex, "marshal_load", nucomp_marshal_load, 1);
-
-    /* objc_--- */
-
-    rb_objc_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
-    rb_objc_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
-    rb_objc_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
-    rb_objc_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
-    rb_objc_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
-
-    make_patterns();
-
-    rb_objc_define_method(rb_cString, "to_c", string_to_c, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_cComplex, "convert", nucomp_s_convert, -1);
-//    rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
-
-    /* --- */
-
-    rb_objc_define_method(rb_cNumeric, "real", numeric_real, 0);
-    rb_objc_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
-    rb_objc_define_method(rb_cNumeric, "imag", numeric_imag, 0);
-    rb_objc_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
-    rb_objc_define_method(rb_cNumeric, "arg", numeric_arg, 0);
-    rb_objc_define_method(rb_cNumeric, "angle", numeric_arg, 0);
-    rb_objc_define_method(rb_cNumeric, "phase", numeric_arg, 0);
-    rb_objc_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
-    rb_objc_define_method(rb_cNumeric, "rect", numeric_rect, 0);
-    rb_objc_define_method(rb_cNumeric, "polar", numeric_polar, 0);
-    rb_objc_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
-    rb_objc_define_method(rb_cNumeric, "conj", numeric_conj, 0);
-
-    rb_objc_define_method(rb_cFloat, "arg", float_arg, 0);
-    rb_objc_define_method(rb_cFloat, "angle", float_arg, 0);
-    rb_objc_define_method(rb_cFloat, "phase", float_arg, 0);
-
-    rb_define_const(rb_cComplex, "I",
-		    f_complex_new_bang2(rb_cComplex, ZERO, ONE));
-
-    // TODO: insert NSNumber primitives
-}
-
-/*
-Local variables:
-c-file-style: "ruby"
-End:
-*/

Deleted: MacRuby/trunk/cont.c
===================================================================
--- MacRuby/trunk/cont.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/cont.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,786 +0,0 @@
-/**********************************************************************
-
-  cont.c - 
-
-  $Author: matz $
-  created at: Thu May 23 09:03:43 2007
-
-  Copyright (C) 2007 Koichi Sasada
-
-**********************************************************************/
-
-#include "macruby_internal.h"
-
-enum context_type {
-    CONTINUATION_CONTEXT = 0,
-    FIBER_CONTEXT = 1,
-    ROOT_FIBER_CONTEXT = 2,
-};
-
-typedef struct rb_context_struct {
-    VALUE self;
-    VALUE value;
-    VALUE *vm_stack;
-    VALUE *machine_stack;
-    VALUE *machine_stack_src;
-#ifdef __ia64
-    VALUE *machine_register_stack;
-    VALUE *machine_register_stack_src;
-    int machine_register_stack_size;
-#endif
-    rb_thread_t saved_thread;
-    rb_jmpbuf_t jmpbuf;
-    int machine_stack_size;
-    VALUE prev;
-    int alive;
-    enum context_type type;
-} rb_context_t;
-
-static VALUE rb_cContinuation;
-static VALUE rb_cFiber;
-static VALUE rb_eFiberError;
-
-#define GetContPtr(obj, ptr)  \
-  Data_Get_Struct(obj, rb_context_t, ptr)
-
-NOINLINE(static VALUE cont_capture(volatile int *stat));
-
-#if !WITH_OBJC
-void rb_thread_mark(rb_thread_t *th);
-
-static void
-cont_mark(void *ptr)
-{
-    RUBY_MARK_ENTER("cont");
-    if (ptr) {
-	rb_context_t *cont = ptr;
-	rb_gc_mark(cont->value);
-	rb_gc_mark(cont->prev);
-	rb_thread_mark(&cont->saved_thread);
-
-	if (cont->vm_stack) {
-	    rb_gc_mark_locations(cont->vm_stack,
-				 cont->vm_stack + cont->saved_thread.stack_size);
-	}
-
-	if (cont->machine_stack) {
-	    rb_gc_mark_locations(cont->machine_stack,
-				 cont->machine_stack + cont->machine_stack_size);
-	}
-#ifdef __ia64
-	if (cont->machine_register_stack) {
-	    rb_gc_mark_locations(cont->machine_register_stack,
-				 cont->machine_register_stack + cont->machine_register_stack_size);
-	}
-#endif
-    }
-    RUBY_MARK_LEAVE("cont");
-}
-#else /* !WITH_OBJC */
-# define cont_mark (NULL)
-#endif
-
-static void
-cont_free(void *ptr)
-{
-    RUBY_FREE_ENTER("cont");
-    if (ptr) {
-	rb_context_t *cont = ptr;
-	RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack);
-	RUBY_FREE_UNLESS_NULL(cont->machine_stack);
-#ifdef __ia64
-	RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
-#endif
-	RUBY_FREE_UNLESS_NULL(cont->vm_stack);
-
-	if (cont->type == FIBER_CONTEXT) {
-	    st_free_table(cont->saved_thread.local_storage);
-	}
-
-	ruby_xfree(ptr);
-    }
-    RUBY_FREE_LEAVE("cont");
-}
-
-static void
-cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
-{
-#if !WITH_OBJC
-    int size;
-    rb_thread_t *sth = &cont->saved_thread;
-
-    SET_MACHINE_STACK_END(&th->machine_stack_end);
-#ifdef __ia64
-    th->machine_register_stack_end = rb_ia64_bsp();
-#endif
-
-    if (th->machine_stack_start > th->machine_stack_end) {
-	size = cont->machine_stack_size = th->machine_stack_start - th->machine_stack_end;
-	cont->machine_stack_src = th->machine_stack_end;
-    }
-    else {
-	size = cont->machine_stack_size = th->machine_stack_end - th->machine_stack_start;
-	cont->machine_stack_src = th->machine_stack_start;
-    }
-
-    if (cont->machine_stack) {
-	REALLOC_N(cont->machine_stack, VALUE, size);
-    }
-    else {
-	GC_WB(&cont->machine_stack, ALLOC_N(VALUE, size));
-    }
-
-    FLUSH_REGISTER_WINDOWS;
-    MEMCPY(cont->machine_stack, cont->machine_stack_src, VALUE, size);
-
-#ifdef __ia64
-    rb_ia64_flushrs();
-    size = cont->machine_register_stack_size = th->machine_register_stack_end - th->machine_register_stack_start;
-    cont->machine_register_stack_src = th->machine_register_stack_start;
-    if (cont->machine_register_stack) {
-	REALLOC_N(cont->machine_register_stack, VALUE, size);
-    }
-    else {
-	GC_WB(&cont->machine_register_stack, ALLOC_N(VALUE, size));
-    }
-
-    MEMCPY(cont->machine_register_stack, cont->machine_register_stack_src, VALUE, size);
-#endif
-
-    sth->machine_stack_start = sth->machine_stack_end = 0;
-#ifdef __ia64
-    sth->machine_register_stack_start = sth->machine_register_stack_end = 0;
-#endif
-#endif
-}
-
-static rb_context_t *
-cont_new(VALUE klass)
-{
-    rb_context_t *cont;
-    volatile VALUE contval;
-    rb_thread_t *th = GET_THREAD();
-
-    contval = Data_Make_Struct(klass, rb_context_t,
-			       cont_mark, cont_free, cont);
-
-    cont->self = contval;
-    cont->alive = Qtrue;
-
-    /* save thread context */
-    cont->saved_thread = *th;
-
-    return cont;
-}
-
-void vm_stack_to_heap(rb_thread_t *th);
-
-static VALUE
-cont_capture(volatile int *stat)
-{
-    rb_context_t *cont;
-    rb_thread_t *th = GET_THREAD(), *sth;
-    volatile VALUE contval;
-
-    vm_stack_to_heap(th);
-    cont = cont_new(rb_cContinuation);
-    contval = cont->self;
-    sth = &cont->saved_thread;
-
-    GC_WB(&cont->vm_stack, ALLOC_N(VALUE, th->stack_size));
-    MEMCPY(cont->vm_stack, th->stack, VALUE, th->stack_size);
-    sth->stack = 0;
-
-    cont_save_machine_stack(th, cont);
-
-    if (ruby_setjmp(cont->jmpbuf)) {
-	VALUE value;
-
-	value = cont->value;
-	cont->value = Qnil;
-	*stat = 1;
-	return value;
-    }
-    else {
-	*stat = 0;
-	return cont->self;
-    }
-}
-
-NORETURN(static void cont_restore_1(rb_context_t *));
-
-static void
-cont_restore_1(rb_context_t *cont)
-{
-    rb_thread_t *th = GET_THREAD(), *sth = &cont->saved_thread;
-
-    /* restore thread context */
-    if (cont->type == CONTINUATION_CONTEXT) {
-	/* continuation */
-	VALUE fib;
-
-	th->fiber = sth->fiber;
-	fib = th->fiber ? th->fiber : th->root_fiber;
-
-	if (fib) {
-	    rb_context_t *fcont;
-	    GetContPtr(fib, fcont);
-	    th->stack_size = fcont->saved_thread.stack_size;
-	    th->stack = fcont->saved_thread.stack;
-	}
-	MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size);
-    }
-    else {
-	/* fiber */
-	th->stack = sth->stack;
-	th->stack_size = sth->stack_size;
-	th->local_storage = sth->local_storage;
-	th->fiber = cont->self;
-    }
-
-    th->cfp = sth->cfp;
-    th->safe_level = sth->safe_level;
-    th->raised_flag = sth->raised_flag;
-    th->state = sth->state;
-    th->status = sth->status;
-    th->tag = sth->tag;
-    th->trap_tag = sth->trap_tag;
-    th->errinfo = sth->errinfo;
-    th->first_proc = sth->first_proc;
-
-    /* restore machine stack */
-#ifdef _M_AMD64
-    {
-	/* workaround for x64 SEH */
-	jmp_buf buf;
-	setjmp(buf);
-	((_JUMP_BUFFER*)(&cont->jmpbuf))->Frame =
-	    ((_JUMP_BUFFER*)(&buf))->Frame;
-    }
-#endif
-    if (cont->machine_stack_src) {
-	FLUSH_REGISTER_WINDOWS;
-	MEMCPY(cont->machine_stack_src, cont->machine_stack,
-	       VALUE, cont->machine_stack_size);
-    }
-
-#ifdef __ia64
-    if (cont->machine_register_stack_src) {
-	MEMCPY(cont->machine_register_stack_src, cont->machine_register_stack,
-	       VALUE, cont->machine_register_stack_size);
-    }
-#endif
-
-    ruby_longjmp(cont->jmpbuf, 1);
-}
-
-NORETURN(NOINLINE(static void cont_restore_0(rb_context_t *, VALUE *)));
-
-#ifdef __ia64
-#define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
-#define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
-static volatile int C(a), C(b), C(c), C(d), C(e);
-static volatile int C(f), C(g), C(h), C(i), C(j);
-static volatile int C(k), C(l), C(m), C(n), C(o);
-static volatile int C(p), C(q), C(r), C(s), C(t);
-int rb_dummy_false = 0;
-NORETURN(NOINLINE(static void register_stack_extend(rb_context_t *, VALUE *)));
-static void
-register_stack_extend(rb_context_t *cont, VALUE *curr_bsp)
-{
-    if (rb_dummy_false) {
-        /* use registers as much as possible */
-        E(a) = E(b) = E(c) = E(d) = E(e) =
-        E(f) = E(g) = E(h) = E(i) = E(j) =
-        E(k) = E(l) = E(m) = E(n) = E(o) =
-        E(p) = E(q) = E(r) = E(s) = E(t) = 0;
-        E(a) = E(b) = E(c) = E(d) = E(e) =
-        E(f) = E(g) = E(h) = E(i) = E(j) =
-        E(k) = E(l) = E(m) = E(n) = E(o) =
-        E(p) = E(q) = E(r) = E(s) = E(t) = 0;
-    }
-    if (curr_bsp < cont->machine_register_stack_src+cont->machine_register_stack_size) {
-        register_stack_extend(cont, (VALUE*)rb_ia64_bsp());
-    }
-    cont_restore_1(cont);
-}
-#undef C
-#undef E
-#endif
-
-static void
-cont_restore_0(rb_context_t *cont, VALUE *addr_in_prev_frame)
-{
-    if (cont->machine_stack_src) {
-#define STACK_PAD_SIZE 1024
-	VALUE space[STACK_PAD_SIZE];
-
-#if STACK_GROW_DIRECTION < 0 /* downward */
-	if (addr_in_prev_frame > cont->machine_stack_src) {
-	    cont_restore_0(cont, &space[0]);
-	}
-#elif STACK_GROW_DIRECTION > 0 /* upward */
-	if (addr_in_prev_frame < cont->machine_stack_src + cont->machine_stack_size) {
-	    cont_restore_0(cont, &space[STACK_PAD_SIZE-1]);
-	}
-#else
-	if (addr_in_prev_frame > &space[0]) {
-	    /* Stack grows downward */
-	    if (addr_in_prev_frame > cont->machine_stack_src) {
-		cont_restore_0(cont, &space[0]);
-	    }
-	}
-	else {
-	    /* Stack grows upward */
-	    if (addr_in_prev_frame < cont->machine_stack_src + cont->machine_stack_size) {
-		cont_restore_0(cont, &space[STACK_PAD_SIZE-1]);
-	    }
-	}
-#endif
-    }
-#ifdef __ia64
-    register_stack_extend(cont, (VALUE*)rb_ia64_bsp());
-#else
-    cont_restore_1(cont);
-#endif
-}
-
-/*
- *  Document-class: Continuation
- *
- *  Continuation objects are generated by
- *  <code>Kernel#callcc</code>. They hold a return address and execution
- *  context, allowing a nonlocal return to the end of the
- *  <code>callcc</code> block from anywhere within a program.
- *  Continuations are somewhat analogous to a structured version of C's
- *  <code>setjmp/longjmp</code> (although they contain more state, so
- *  you might consider them closer to threads).
- *     
- *  For instance:
- *     
- *     arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
- *     callcc{|$cc|}
- *     puts(message = arr.shift)
- *     $cc.call unless message =~ /Max/
- *     
- *  <em>produces:</em>
- *     
- *     Freddie
- *     Herbie
- *     Ron
- *     Max
- *     
- *  This (somewhat contrived) example allows the inner loop to abandon
- *  processing early:
- *     
- *     callcc {|cont|
- *       for i in 0..4
- *         print "\n#{i}: "
- *         for j in i*5...(i+1)*5
- *           cont.call() if j == 17
- *           printf "%3d", j
- *         end
- *       end
- *     }
- *     print "\n"
- *     
- *  <em>produces:</em>
- *     
- *     0:   0  1  2  3  4
- *     1:   5  6  7  8  9
- *     2:  10 11 12 13 14
- *     3:  15 16
- */
-
-/*
- *  call-seq:
- *     callcc {|cont| block }   =>  obj
- *  
- *  Generates a <code>Continuation</code> object, which it passes to the
- *  associated block. Performing a <em>cont</em><code>.call</code> will
- *  cause the <code>callcc</code> to return (as will falling through the
- *  end of the block). The value returned by the <code>callcc</code> is
- *  the value of the block, or the value passed to
- *  <em>cont</em><code>.call</code>. See class <code>Continuation</code>
- *  for more details. Also see <code>Kernel::throw</code> for
- *  an alternative mechanism for unwinding a call stack.
- */
-
-static VALUE
-rb_callcc(VALUE self)
-{
-    volatile int called;
-    volatile VALUE val = cont_capture(&called);
-
-    if (called) {
-	return val;
-    }
-    else {
-	return rb_yield(val);
-    }
-}
-
-static VALUE
-make_passing_arg(int argc, VALUE *argv)
-{
-    switch(argc) {
-      case 0:
-	return Qnil;
-      case 1:
-	return argv[0];
-      default:
-	return rb_ary_new4(argc, argv);
-    }
-}
-
-/*
- *  call-seq:
- *     cont.call(args, ...)
- *     cont[args, ...]
- *  
- *  Invokes the continuation. The program continues from the end of the
- *  <code>callcc</code> block. If no arguments are given, the original
- *  <code>callcc</code> returns <code>nil</code>. If one argument is
- *  given, <code>callcc</code> returns it. Otherwise, an array
- *  containing <i>args</i> is returned.
- *     
- *     callcc {|cont|  cont.call }           #=> nil
- *     callcc {|cont|  cont.call 1 }         #=> 1
- *     callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]
- */
-
-static VALUE
-rb_cont_call(int argc, VALUE *argv, VALUE contval)
-{
-    rb_context_t *cont;
-    rb_thread_t *th = GET_THREAD();
-    GetContPtr(contval, cont);
-
-    if (cont->saved_thread.self != th->self) {
-	rb_raise(rb_eRuntimeError, "continuation called across threads");
-    }
-    if (cont->saved_thread.trap_tag != th->trap_tag) {
-	rb_raise(rb_eRuntimeError, "continuation called across trap");
-    }
-    if (cont->saved_thread.fiber) {
-	rb_context_t *fcont;
-	GetContPtr(cont->saved_thread.fiber, fcont);
-
-	if (th->fiber != cont->saved_thread.fiber) {
-	    rb_raise(rb_eRuntimeError, "continuation called across fiber");
-	}
-	
-	if (!fcont->alive) {
-	    rb_raise(rb_eRuntimeError, "continuation called dead fiber");
-	}
-    }
-
-    cont->value = make_passing_arg(argc, argv);
-
-    cont_restore_0(cont, &contval);
-    return Qnil; /* unreachable */
-}
-
-/*********/
-/* fiber */
-/*********/
-
-#define FIBER_VM_STACK_SIZE (4 * 1024)
-
-static rb_context_t *
-fiber_alloc(VALUE klass)
-{
-    rb_context_t *cont = cont_new(klass);
-
-    cont->type = FIBER_CONTEXT;
-    cont->prev = Qnil;
-
-    return cont;
-}
-
-static VALUE
-fiber_new(VALUE klass, VALUE proc)
-{
-    rb_context_t *cont = fiber_alloc(klass);
-    VALUE contval = cont->self;
-    rb_thread_t *th = &cont->saved_thread;
-
-    /* initialize */
-    cont->vm_stack = 0;
-
-    th->stack = 0;
-    th->stack_size = FIBER_VM_STACK_SIZE;
-    GC_WB(&th->stack, ALLOC_N(VALUE, th->stack_size));
-
-    th->cfp = (void *)(th->stack + th->stack_size);
-    th->cfp--;
-    th->cfp->pc = 0;
-    th->cfp->sp = th->stack + 1;
-    th->cfp->bp = 0;
-    th->cfp->lfp = th->stack;
-    *th->cfp->lfp = 0;
-    th->cfp->dfp = th->stack;
-    th->cfp->self = Qnil;
-    th->cfp->flag = 0;
-    th->cfp->iseq = 0;
-    th->cfp->proc = 0;
-    th->cfp->block_iseq = 0;
-    th->tag = 0;
-    GC_WB(&th->local_storage, st_init_numtable());
-
-    GC_WB(&th->first_proc, proc);
-
-    MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1);
-
-    return contval;
-}
-
-VALUE
-rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj)
-{
-    return fiber_new(rb_cFiber, rb_proc_new(func, obj));
-}
-
-static VALUE
-rb_fiber_s_new(VALUE self)
-{
-    return fiber_new(self, rb_block_proc());
-}
-
-static VALUE
-return_fiber(void)
-{
-    rb_context_t *cont;
-    VALUE curr = rb_fiber_current();
-    GetContPtr(curr, cont);
-
-    if (cont->prev == Qnil) {
-	rb_thread_t *th = GET_THREAD();
-
-	if (th->root_fiber != curr) {
-	    return th->root_fiber;
-	}
-	else {
-	    rb_raise(rb_eFiberError, "can't yield from root fiber");
-	}
-    }
-    else {
-	VALUE prev = cont->prev;
-	cont->prev = Qnil;
-	return prev;
-    }
-}
-
-VALUE rb_fiber_transfer(VALUE fib, int argc, VALUE *argv);
-
-static void
-rb_fiber_terminate(rb_context_t *cont)
-{
-    VALUE value = cont->value;
-    cont->alive = Qfalse;
-    rb_fiber_transfer(return_fiber(), 1, &value);
-}
-
-void
-rb_fiber_start(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_context_t *cont;
-//    rb_proc_t *proc;
-//    VALUE args;
-    int state;
-
-    GetContPtr(th->fiber, cont);
-    TH_PUSH_TAG(th);
-    if ((state = EXEC_TAG()) == 0) {
-#if 0 // TODO
-	GetProcPtr(cont->saved_thread.first_proc, proc);
-	args = cont->value;
-	cont->value = Qnil;
-	th->errinfo = Qnil;
-	GC_WB(&th->local_lfp, proc->block.lfp);
-	th->local_svar = Qnil;
-
-	cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args, 0);
-#endif
-    }
-    TH_POP_TAG();
-
-    if (state) {
-	if (TAG_RAISE) {
-	    th->thrown_errinfo = th->errinfo;
-	}
-	else {
-	    th->thrown_errinfo =
-	      vm_make_jump_tag_but_local_jump(state, th->errinfo);
-	}
-	RUBY_VM_SET_INTERRUPT(th);
-    }
-
-    rb_fiber_terminate(cont);
-    rb_bug("rb_fiber_start: unreachable");
-}
-
-VALUE
-rb_fiber_current()
-{
-    rb_thread_t *th = GET_THREAD();
-    if (th->fiber == 0) {
-	/* save root */
-	rb_context_t *cont = fiber_alloc(rb_cFiber);
-	cont->type = ROOT_FIBER_CONTEXT;
-	th->root_fiber = th->fiber = cont->self;
-    }
-    return th->fiber;
-}
-
-static VALUE
-fiber_store(rb_context_t *next_cont)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_context_t *cont;
-
-    if (th->fiber) {
-	GetContPtr(th->fiber, cont);
-	cont->saved_thread = *th;
-    }
-    else {
-	/* create current fiber */
-	cont = fiber_alloc(rb_cFiber); /* no need to allocate vm stack */
-	cont->type = ROOT_FIBER_CONTEXT;
-	th->root_fiber = th->fiber = cont->self;
-    }
-
-    cont_save_machine_stack(th, cont);
-
-    if (ruby_setjmp(cont->jmpbuf)) {
-	/* restored */
-	GetContPtr(th->fiber, cont);
-	return cont->value;
-    }
-    else {
-	return Qundef;
-    }
-}
-
-static inline VALUE
-fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
-{
-    VALUE value;
-    rb_context_t *cont;
-    rb_thread_t *th = GET_THREAD();
-
-    GetContPtr(fib, cont);
-
-    if (cont->saved_thread.self != th->self) {
-	rb_raise(rb_eFiberError, "fiber called across threads");
-    }
-    else if (cont->saved_thread.trap_tag != th->trap_tag) {
-	rb_raise(rb_eFiberError, "fiber called across trap");
-    }
-    else if (!cont->alive) {
-	rb_raise(rb_eFiberError, "dead fiber called");
-    }
-
-    if (is_resume) {
-	cont->prev = rb_fiber_current();
-    }
-
-    cont->value = make_passing_arg(argc, argv);
-
-    if ((value = fiber_store(cont)) == Qundef) {
-	cont_restore_0(cont, &value);
-	rb_bug("rb_fiber_resume: unreachable");
-    }
-
-    RUBY_VM_CHECK_INTS();
-
-    return value;
-}
-
-VALUE
-rb_fiber_transfer(VALUE fib, int argc, VALUE *argv)
-{
-    return fiber_switch(fib, argc, argv, 0);
-}
-
-VALUE
-rb_fiber_resume(VALUE fib, int argc, VALUE *argv)
-{
-    rb_context_t *cont;
-    GetContPtr(fib, cont);
-
-    if (cont->prev != Qnil) {
-	rb_raise(rb_eFiberError, "double resume");
-    }
-
-    return fiber_switch(fib, argc, argv, 1);
-}
-
-VALUE
-rb_fiber_yield(int argc, VALUE *argv)
-{
-    return rb_fiber_transfer(return_fiber(), argc, argv);
-}
-
-VALUE
-rb_fiber_alive_p(VALUE fib)
-{
-    rb_context_t *cont;
-    GetContPtr(fib, cont);
-    return cont->alive;
-}
-
-static VALUE
-rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
-{
-    return rb_fiber_resume(fib, argc, argv);
-}
-
-static VALUE
-rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fib)
-{
-    return rb_fiber_transfer(fib, argc, argv);
-}
-
-static VALUE
-rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
-{
-    return rb_fiber_yield(argc, argv);
-}
-
-static VALUE
-rb_fiber_s_current(VALUE klass)
-{
-    return rb_fiber_current();
-}
-
-void
-Init_Cont(void)
-{
-    rb_cFiber = rb_define_class("Fiber", rb_cObject);
-    rb_undef_alloc_func(rb_cFiber);
-    rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
-    rb_define_singleton_method(rb_cFiber, "new", rb_fiber_s_new, 0);
-    rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
-    rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
-}
-
-void
-Init_Continuation_body(void)
-{
-    rb_cContinuation = rb_define_class("Continuation", rb_cObject);
-    rb_undef_alloc_func(rb_cContinuation);
-    rb_undef_method(CLASS_OF(rb_cContinuation), "new");
-    rb_define_method(rb_cContinuation, "call", rb_cont_call, -1);
-    rb_define_method(rb_cContinuation, "[]", rb_cont_call, -1);
-    rb_define_global_function("callcc", rb_callcc, 0);
-}
-
-void
-Init_Fiber_as_Coroutine(void)
-{
-    rb_define_method(rb_cFiber, "transfer", rb_fiber_m_transfer, -1);
-    rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0);
-    rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
-}

Deleted: MacRuby/trunk/debugger.cpp
===================================================================
--- MacRuby/trunk/debugger.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/debugger.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,428 +0,0 @@
-/*
- * MacRuby debugger.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#if !defined(MACRUBY_STATIC)
-
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/Constants.h>
-#include <llvm/CallingConv.h>
-#include <llvm/Instructions.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/Analysis/DebugInfo.h>
-#if !defined(LLVM_TOT)
-# include <llvm/Analysis/DIBuilder.h>
-#endif
-#include <llvm/ExecutionEngine/JIT.h>
-#include <llvm/PassManager.h>
-#include <llvm/Target/TargetData.h>
-using namespace llvm;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "compiler.h"
-#include "debugger.h"
-
-void
-RoxorCompiler::compile_debug_trap(void)
-{
-    if (bb == NULL || inside_eval) {
-	return;
-    }
-
-    if (debugTrapFunc == NULL) {
-	// void rb_vm_debug_trap(const char *file, int line,
-	//	VALUE self, rb_vm_block_t *current_block, int lvars_size, ...);
-	std::vector<const Type *> types;
-	types.push_back(PtrTy);
-	types.push_back(Int32Ty);
-	types.push_back(RubyObjTy);
-	types.push_back(PtrTy);
-	types.push_back(Int32Ty);
-	FunctionType *ft = FunctionType::get(VoidTy, types, true);
-	debugTrapFunc = cast<Function>
-	    (module->getOrInsertFunction( "rb_vm_debug_trap", ft));
-    }
-
-    std::vector<Value *> params;
-    params.push_back(compile_const_pointer((void *)fname));
-    params.push_back(ConstantInt::get(Int32Ty, current_line));
-    params.push_back(current_self);
-    params.push_back(running_block == NULL
-	    ? compile_const_pointer(NULL) : running_block);
-
-    // Lvars.
-    params.push_back(ConstantInt::get(Int32Ty, (int)lvars.size()));
-    for (std::map<ID, Value *>::iterator iter = lvars.begin();
-	 iter != lvars.end(); ++iter) {
-
-	ID lvar = iter->first;
-	params.push_back(compile_id(lvar));
-	params.push_back(iter->second);
-    }
-
-    CallInst::Create(debugTrapFunc, params.begin(), params.end(), "", bb);
-}
-
-extern "C"
-void
-rb_vm_debug_trap(const char *file, const int line, VALUE self,
-	rb_vm_block_t *current_block, int lvars_size, ...)
-{
-    if (RoxorDebugger::shared == NULL) {
-	RoxorDebugger::shared = RoxorDebugger::unix_server();
-    }
-
-    va_list args;
-    va_start(args, lvars_size);
-    RoxorDebugger::shared->trap(file, line, self, current_block,
-	    lvars_size, args);
-    va_end(args);
-}
-
-unsigned int RoxorBreakPoint::IDs = 0;
-RoxorDebugger *RoxorDebugger::shared = NULL;
-
-RoxorDebugger *
-RoxorDebugger::unix_server(void)
-{
-    // Create the socket.
-    const int fd = socket(PF_LOCAL, SOCK_STREAM, 0);
-    if (fd < 0) {
-	perror("socket()");
-	exit(1);
-    }
-
-    // Bind it to the given path.
-    assert(ruby_debug_socket_path != Qfalse);
-    const char *path = RSTRING_PTR(ruby_debug_socket_path);
-    struct sockaddr_un name;
-    name.sun_family = PF_LOCAL;
-    strncpy(name.sun_path, path, sizeof(name.sun_path));
-    if (bind(fd, (struct sockaddr *)&name, SUN_LEN(&name)) != 0) {
-	perror("bind()");
-	exit(1);
-    }
-
-    // Prepare for listening, backlog of 1 connection.
-    if (listen(fd, 1) != 0) {
-	perror("listen()");
-	exit(1);
-    }
-
-    // Accept first connection.
-    struct sockaddr_un remote;
-    socklen_t remotelen = sizeof(remote);
-    const int pipe = accept(fd, (struct sockaddr *)&remote, &remotelen);
-    if (socket < 0) {
-	perror("accept()");
-	exit(1);
-    }
-
-//printf("DBG: connected with fd %d\n", pipe);
-
-    return new RoxorDebugger(pipe);
-}
-
-RoxorDebugger::RoxorDebugger(int _pipe)
-{
-    pipe = _pipe;
-    binding = NULL;
-    breakpoint = NULL;
-    frame = 0;
-
-    // We want to break at the very first line.
-    break_at_next = true;
-}
-
-RoxorDebugger::~RoxorDebugger()
-{
-    close(pipe);
-}
-
-bool
-RoxorDebugger::send(std::string &data)
-{
-//printf("DBG: send %s\n", data.c_str());
-    const ssize_t len = ::send(pipe, data.c_str(), data.length(), 0);
-    if (len != (ssize_t)data.length()) {
-	if (len == -1) {
-	    perror("send()");
-	}
-	else {
-	    fprintf(stderr, "expected to send %ld bytes instead of %ld\n",
-		    data.length(), len);
-	}
-	return false;	
-    }
-    return true;
-}
-
-bool
-RoxorDebugger::recv(std::string &data)
-{
-    char buf[512];
-    const ssize_t len = ::recv(pipe, buf, sizeof buf, 0);
-    if (len == -1) {
-	perror("recv()");
-	return false;
-    }
-    data.clear();
-    data.append(buf, len);
-//printf("DBG: recv %s\n", data.c_str());
-    return true;
-}
-
-void 
-RoxorDebugger::trap(const char *file, const int line, VALUE self,
-	rb_vm_block_t *block, int lvars_size, va_list lvars)
-{
-    // Compute location.
-    char buf[100];
-    snprintf(buf, sizeof buf, "%s:%d", file, line);
-    std::string loc(buf);
-
-    // Should we break here?
-    bool should_break = false;
-    RoxorBreakPoint *bp = NULL;
-    if (break_at_next) {
-	should_break = true;
-	break_at_next = false;
-    }
-    else {
-	std::map<std::string, RoxorBreakPoint *>::iterator iter =
-	    breakpoints.find(loc);
-	if (iter != breakpoints.end()) {
-	    bp = iter->second;
-	    if (bp->enabled) {
-		if (bp->condition.length() > 0) {
-		    VALUE obj = evaluate_expression(self, block, lvars_size,
-			    lvars, bp->condition);
-		    if (obj != Qnil && obj != Qfalse) {
-			should_break = true;
-		    }
-		}
-		else {
-		    should_break = true;
-		}
-	    }
-	}
-    }
-
-    if (!should_break) {
-	return;
-    }
-
-    // Send the current location to the client.
-    if (!send(loc)) {
-	return;
-    }
-
-    // Invalidate latest binding.
-    if (binding != NULL) {
-	GC_RELEASE(binding);
-	binding = NULL;
-    }
-    frame = 0;
-
-    // Enter the main loop.
-    std::string data;
-    while (true) {
-	// Receive command.
-	if (!recv(data)) {
-	    return;
-	}
-	const char *cmd = data.c_str();
-
-	// Handle command.
-	if (strcmp(cmd, "exit") == 0) {
-	    exit(0);
-	}
-	if (strcmp(cmd, "continue") == 0) {
-	    break;
-	}
-	if (strcmp(cmd, "next") == 0) {
-	    break_at_next = true;
-	    break;
-	}
-	if (strncmp(cmd, "break ", 6) == 0) {
-	    std::string location = data.substr(6);
-	    if (location.length() >= 3) {
-		unsigned int id = add_breakpoint(location);
-		char buf[10];
-		snprintf(buf, sizeof buf, "%d", id);
-		send(buf);
-		continue;
-	    }
-	}
-	if (strncmp(cmd, "enable ", 7) == 0) {
-	    const unsigned int bpid = (unsigned int)strtol(cmd + 7, NULL, 10);
-	    RoxorBreakPoint *bp = find_breakpoint(bpid);
-	    if (bp != NULL) {
-		bp->enabled = true;
-	    }
-	    continue;
-	}
-	if (strncmp(cmd, "disable ", 8) == 0) {
-	    const unsigned int bpid = (unsigned int)strtol(cmd + 8, NULL, 10);
-	    RoxorBreakPoint *bp = find_breakpoint(bpid);
-	    if (bp != NULL) {
-		bp->enabled = false;
-	    }
-	    continue;
-	}
-	if (strncmp(cmd, "delete ", 7) == 0) {
-	    const unsigned int bpid = (unsigned int)strtol(cmd + 7, NULL, 10);
-	    delete_breakpoint(bpid);
-	    continue;
-	}
-	if (strncmp(cmd, "condition ", 10) == 0) {
-	    const char *p = strchr(cmd + 10, ' ');
-	    if (p != NULL) {
-		std::string bpstr = data.substr(10, p - cmd - 10);
-		const unsigned int bpid = (unsigned int)strtol(bpstr.c_str(),
-			NULL, 10);
-		std::string condstr = data.substr(10 + bpstr.length());
-		RoxorBreakPoint *bp = find_breakpoint(bpid);
-		if (bp != NULL) {
-		    bp->condition = condstr;
-		}
-		continue;
-	    }
-	} 
-	if (strcmp(cmd, "info breakpoints") == 0) {
-	    std::string resp;
-	    for (std::map<std::string, RoxorBreakPoint *>::iterator iter
-		    = breakpoints.begin();
-		    iter != breakpoints.end();
-		    ++iter) {
-		char buf[100];
-		snprintf(buf, sizeof buf, "id=%d,location=%s,enabled=%d\n",
-			iter->second->id, iter->first.c_str(),
-			iter->second->enabled);
-		resp.append(buf);
-	    }
-	    if (resp.length() == 0) {
-		resp.append("nil");
-	    }
-	    send(resp);
-	    continue;
-	}
-	if (strcmp(cmd, "backtrace") == 0) {
-	    VALUE bt = rb_vm_backtrace(0);
-	    VALUE str = rb_ary_join(bt, rb_str_new2("\n"));
-	    send(RSTRING_PTR(str));
-	    continue;
-	}
-	if (strncmp(cmd, "frame ", 6) == 0) {
-	    unsigned int frid = (unsigned int)strtol(cmd + 6, NULL, 10);
-	    if (frame != frid) {
-		frame = frid;
-		if (binding != NULL) {
-		    GC_RELEASE(binding);
-		    binding = NULL;
-		}
-		// TODO update location
-	    }
-	    continue;
-	}
-	if (strncmp(cmd, "eval ", 5) == 0) {
-	    std::string expr = data.substr(5);
-	    if (expr.length() > 0) {
-		VALUE obj = evaluate_expression(self, block, lvars_size, lvars,
-			expr);
-		send(RSTRING_PTR(rb_inspect(obj)));
-		continue;
-	    }
-	} 
-
-	// Unknown command, let's exit the program. This should never happen!
-	fprintf(stderr, "unknown command: %s\n", cmd);
-	exit(1); 
-    }
-}
-
-unsigned int
-RoxorDebugger::add_breakpoint(std::string &location)
-{
-    std::map<std::string, RoxorBreakPoint *>::iterator iter
-	= breakpoints.find(location);
-
-    RoxorBreakPoint *bp;
-    if (iter == breakpoints.end()) {
-	bp = new RoxorBreakPoint();
-	breakpoints[location] = bp;
-    }
-    else {
-	bp = iter->second;
-    }
-
-    return bp->id;
-}
-
-VALUE
-RoxorDebugger::evaluate_expression(VALUE self, rb_vm_block_t *block,
-	int lvars_size, va_list lvars, std::string expr)
-{
-    if (binding == NULL) {
-	if (frame == 0) {
-	    binding = rb_vm_create_binding(self, block, NULL, lvars_size, lvars,
-		    false);
-	}
-	else {
-	    binding = GET_VM()->get_binding(frame - 1);
-	    assert(binding != NULL);
-	}
-	GC_RETAIN(binding);
-    }
-
-    try {
-	return rb_vm_eval_string(self, 0, rb_str_new2(expr.c_str()), binding,
-		"(eval)", 1);
-    }
-    catch (...) {
-	rb_vm_print_current_exception();
-	return Qnil;
-    }
-}
-
-RoxorBreakPoint *
-RoxorDebugger::find_breakpoint(unsigned int bpid)
-{
-    for (std::map<std::string, RoxorBreakPoint *>::iterator iter
-	    = breakpoints.begin();
-	    iter != breakpoints.end();
-	    ++iter) {
-	if (iter->second->id == bpid) {
-	    return iter->second;
-	}
-    }
-    return NULL;
-}
-
-bool
-RoxorDebugger::delete_breakpoint(unsigned int bpid)
-{
-    for (std::map<std::string, RoxorBreakPoint *>::iterator iter
-	    = breakpoints.begin();
-	    iter != breakpoints.end();
-	    ++iter) {
-	if (iter->second->id == bpid) {
-	    breakpoints.erase(iter);
-	    return true;
-	}
-    }
-    return false;
-}
-
-#endif // !MACRUBY_STATIC

Deleted: MacRuby/trunk/debugger.h
===================================================================
--- MacRuby/trunk/debugger.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/debugger.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,69 +0,0 @@
-/*
- * MacRuby debugger.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __DEBUGGER_H_
-#define __DEBUGGER_H_
-
-#if defined(__cplusplus)
-
-#if !defined(MACRUBY_STATIC)
-
-class RoxorBreakPoint {
-    public:
-	static unsigned int IDs;
-	unsigned int id;
-	bool enabled;
-	std::string condition;
-
-	RoxorBreakPoint(void) {
-	    id = ++IDs;
-	    enabled = true;
-	}
-};
-
-class RoxorDebugger {
-    private:
-	std::map<std::string, RoxorBreakPoint *> breakpoints;
-	bool break_at_next;
-	std::string location;
-	RoxorBreakPoint *breakpoint;
-	rb_vm_binding_t *binding;
-	unsigned int frame;
-	int pipe;
-
-	bool send(std::string &data);
-	bool send(const char *str) {
-	    std::string s(str);
-	    return send(s);
-	}
-	bool recv(std::string &data);
-
-	unsigned int add_breakpoint(std::string &location);
-	RoxorBreakPoint *find_breakpoint(unsigned int bpid);
-	bool delete_breakpoint(unsigned int bpid);
-
-	VALUE evaluate_expression(VALUE self, rb_vm_block_t *block,
-		int lvars_size, va_list lvars, std::string expr);
-	
-    public:
-	static RoxorDebugger *shared;
-
-	static RoxorDebugger *unix_server(void);
-
-	RoxorDebugger(int pipe);
-	~RoxorDebugger();
-
-	void trap(const char *file, const int line, VALUE self,
-		rb_vm_block_t *block, int lvars_size, va_list lvars);
-};
-
-#endif // !MACRUBY_STATIC
-
-#endif /* __cplusplus */
-
-#endif /* __DEBUGGER_H_ */

Deleted: MacRuby/trunk/dir.c
===================================================================
--- MacRuby/trunk/dir.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dir.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1923 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/util.h"
-#include "vm.h"
-#include "encoding.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <errno.h>
-#include <ctype.h>
-
-#define NAMLEN(dirent) strlen((dirent)->d_name)
-
-#define FNM_NOESCAPE	0x01
-#define FNM_PATHNAME	0x02
-#define FNM_DOTMATCH	0x04
-#define FNM_CASEFOLD	0x08
-#if CASEFOLD_FILESYSTEM
-#define FNM_SYSCASE	FNM_CASEFOLD
-#else
-#define FNM_SYSCASE	0
-#endif
-
-#define FNM_NOMATCH	1
-#define FNM_ERROR	2
-
-#define downcase(c) (nocase && ISUPPER(c) ? TOLOWER(c) : (c))
-#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
-
-/* caution: in case *p == '\0'
-   Next(p) == p + 1 in single byte environment
-   Next(p) == p     in multi byte environment
-*/
-#if defined(CharNext)
-# define Next(p) CharNext(p)
-#elif defined(DJGPP)
-# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-#elif defined(__EMX__)
-# define Next(p) ((p) + emx_mblen(p))
-static inline int
-emx_mblen(const char *p)
-{
-    int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
-    return (n < 0) ? 1 : n;
-}
-#endif
-
-#ifndef Next /* single byte environment */
-# define Next(p) ((p) + 1)
-# define Inc(p) (++(p))
-# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
-#else /* multi byte environment */
-# define Inc(p) ((p) = Next(p))
-# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
-static int
-CompareImpl(const char *p1, const char *p2, int nocase)
-{
-    const int len1 = Next(p1) - p1;
-    const int len2 = Next(p2) - p2;
-#ifdef _WIN32
-    char buf1[10], buf2[10]; /* large enough? */
-#endif
-
-    if (len1 < 0 || len2 < 0) {
-	rb_fatal("CompareImpl: negative len");
-    }
-
-    if (len1 == 0) return  len2;
-    if (len2 == 0) return -len1;
-
-#ifdef _WIN32
-    if (nocase && rb_w32_iswinnt()) {
-	if (len1 > 1) {
-	    if (len1 >= sizeof(buf1)) {
-		rb_fatal("CompareImpl: too large len");
-	    }
-	    memcpy(buf1, p1, len1);
-	    buf1[len1] = '\0';
-	    CharLower(buf1);
-	    p1 = buf1; /* trick */
-	}
-	if (len2 > 1) {
-	    if (len2 >= sizeof(buf2)) {
-		rb_fatal("CompareImpl: too large len");
-	    }
-	    memcpy(buf2, p2, len2);
-	    buf2[len2] = '\0';
-	    CharLower(buf2);
-	    p2 = buf2; /* trick */
-	}
-    }
-#endif
-    if (len1 == 1)
-	if (len2 == 1)
-	    return compare(downcase(*p1), downcase(*p2));
-	else {
-	    const int ret = compare(downcase(*p1), *p2);
-	    return ret ? ret : -1;
-	}
-    else
-	if (len2 == 1) {
-	    const int ret = compare(*p1, downcase(*p2));
-	    return ret ? ret : 1;
-	}
-	else {
-	    const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
-	    return ret ? ret : len1 - len2;
-	}
-}
-#endif /* environment */
-
-static char *
-bracket(
-    const char *p, /* pattern (next to '[') */
-    const char *s, /* string */
-    int flags)
-{
-    const int nocase = flags & FNM_CASEFOLD;
-    const int escape = !(flags & FNM_NOESCAPE);
-
-    int ok = 0, not = 0;
-
-    if (*p == '!' || *p == '^') {
-	not = 1;
-	p++;
-    }
-
-    while (*p != ']') {
-	const char *t1 = p;
-	if (escape && *t1 == '\\')
-	    t1++;
-	if (!*t1)
-	    return NULL;
-	p = Next(t1);
-	if (p[0] == '-' && p[1] != ']') {
-	    const char *t2 = p + 1;
-	    if (escape && *t2 == '\\')
-		t2++;
-	    if (!*t2)
-		return NULL;
-	    p = Next(t2);
-	    if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
-		ok = 1;
-	}
-	else
-	    if (!ok && Compare(t1, s) == 0)
-		ok = 1;
-    }
-
-    return ok == not ? NULL : (char *)p + 1;
-}
-
-/* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
-   Otherwise, entire string will be matched.
-   End marker itself won't be compared.
-   And if function succeeds, *pcur reaches end marker.
-*/
-#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
-#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
-#define RETURN(val) return *pcur = p, *scur = s, (val);
-
-static int
-fnmatch_helper(
-    const char **pcur, /* pattern */
-    const char **scur, /* string */
-    int flags)
-{
-    const int period = !(flags & FNM_DOTMATCH);
-    const int pathname = flags & FNM_PATHNAME;
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int nocase = flags & FNM_CASEFOLD;
-
-    const char *ptmp = 0;
-    const char *stmp = 0;
-
-    const char *p = *pcur;
-    const char *s = *scur;
-
-    if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
-	RETURN(FNM_NOMATCH);
-
-    while (1) {
-	switch (*p) {
-	  case '*':
-	    do { p++; } while (*p == '*');
-	    if (ISEND(UNESCAPE(p))) {
-		p = UNESCAPE(p);
-		RETURN(0);
-	    }
-	    if (ISEND(s))
-		RETURN(FNM_NOMATCH);
-	    ptmp = p;
-	    stmp = s;
-	    continue;
-
-	  case '?':
-	    if (ISEND(s))
-		RETURN(FNM_NOMATCH);
-	    p++;
-	    Inc(s);
-	    continue;
-
-	  case '[': {
-	    const char *t;
-	    if (ISEND(s))
-		RETURN(FNM_NOMATCH);
-	    if ((t = bracket(p + 1, s, flags)) != 0) {
-		p = t;
-		Inc(s);
-		continue;
-	    }
-	    goto failed;
-	  }
-	}
-
-	/* ordinary */
-	p = UNESCAPE(p);
-	if (ISEND(s))
-	    RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
-	if (ISEND(p))
-	    goto failed;
-	if (Compare(p, s) != 0)
-	    goto failed;
-	Inc(p);
-	Inc(s);
-	continue;
-
-      failed: /* try next '*' position */
-	if (ptmp && stmp) {
-	    p = ptmp;
-	    Inc(stmp); /* !ISEND(*stmp) */
-	    s = stmp;
-	    continue;
-	}
-	RETURN(FNM_NOMATCH);
-    }
-}
-
-static int
-fnmatch(
-    const char *p, /* pattern */
-    const char *s, /* string */
-    int flags)
-{
-    const int period = !(flags & FNM_DOTMATCH);
-    const int pathname = flags & FNM_PATHNAME;
-
-    const char *ptmp = 0;
-    const char *stmp = 0;
-
-    if (pathname) {
-	while (1) {
-	    if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
-		do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
-		ptmp = p;
-		stmp = s;
-	    }
-	    if (fnmatch_helper(&p, &s, flags) == 0) {
-		while (*s && *s != '/') Inc(s);
-		if (*p && *s) {
-		    p++;
-		    s++;
-		    continue;
-		}
-		if (!*p && !*s)
-		    return 0;
-	    }
-	    /* failed : try next recursion */
-	    if (ptmp && stmp && !(period && *stmp == '.')) {
-		while (*stmp && *stmp != '/') Inc(stmp);
-		if (*stmp) {
-		    p = ptmp;
-		    stmp++;
-		    s = stmp;
-		    continue;
-		}
-	    }
-	    return FNM_NOMATCH;
-	}
-    }
-    else
-	return fnmatch_helper(&p, &s, flags);
-}
-
-VALUE rb_cDir;
-
-struct dir_data {
-    DIR *dir;
-    char *path;
-};
-
-static void
-free_dir(struct dir_data *dir)
-{
-    if (dir) {
-	if (dir->dir) closedir(dir->dir);
-	if (dir->path) xfree(dir->path);
-    }
-    xfree(dir);
-}
-
-static VALUE dir_close(VALUE, SEL);
-
-static VALUE
-dir_s_alloc(VALUE klass, SEL sel)
-{
-    struct dir_data *dirp;
-    VALUE obj = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dirp);
-
-    dirp->dir = NULL;
-    dirp->path = NULL;
-
-    return obj;
-}
-
-/*
- *  call-seq:
- *     Dir.new( string ) -> aDir
- *
- *  Returns a new directory object for the named directory.
- */
-static VALUE
-dir_initialize(VALUE dir, SEL sel, VALUE dirname)
-{
-    struct dir_data *dp;
-    const char *dirname_cstr;
-
-    FilePathValue(dirname);
-    Data_Get_Struct(dir, struct dir_data, dp);
-    if (dp->dir) closedir(dp->dir);
-    if (dp->path) free(dp->path);
-    dp->dir = NULL;
-    dp->path = NULL;
-    dirname_cstr = RSTRING_PTR(dirname);
-    dp->dir = opendir(dirname_cstr);
-    if (dp->dir == NULL) {
-	if (errno == EMFILE || errno == ENFILE) {
-	    rb_gc();
-	    dp->dir = opendir(dirname_cstr);
-	}
-	if (dp->dir == NULL) {
-	    rb_sys_fail(dirname_cstr);
-	}
-    }
-    dp->path = strdup(dirname_cstr);
-
-    return dir;
-}
-
-/*
- *  call-seq:
- *     Dir.open( string ) => aDir
- *     Dir.open( string ) {| aDir | block } => anObject
- *
- *  With no block, <code>open</code> is a synonym for
- *  <code>Dir::new</code>. If a block is present, it is passed
- *  <i>aDir</i> as a parameter. The directory is closed at the end of
- *  the block, and <code>Dir::open</code> returns the value of the
- *  block.
- */
-static VALUE
-dir_s_open(VALUE klass, SEL sel, VALUE dirname)
-{
-    struct dir_data *dp;
-    VALUE dir = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dp);
-
-    dir_initialize(dir, 0, dirname);
-    if (rb_block_given_p()) {
-	return rb_ensure(rb_yield, dir, dir_close, dir);
-    }
-
-    return dir;
-}
-
-static void
-dir_closed(void)
-{
-    rb_raise(rb_eIOError, "closed directory");
-}
-
-static void
-dir_check(VALUE dir)
-{
-    if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir");
-    rb_check_frozen(dir);
-}
-
-#define GetDIR(obj, dirp) do {\
-    dir_check(dir);\
-    Data_Get_Struct(obj, struct dir_data, dirp);\
-    if (dirp->dir == NULL) dir_closed();\
-} while (0)
-
-/*
- *  call-seq:
- *     dir.inspect => string
- *
- *  Return a string describing this Dir object.
- */
-static VALUE
-dir_inspect(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-
-    Data_Get_Struct(dir, struct dir_data, dirp);
-    if (dirp->path) {
-	const char *c = rb_obj_classname(dir);
-	int len = strlen(c) + strlen(dirp->path) + 4;
-	
-	char *buf = (char *)alloca(len);
-	snprintf(buf, len,  "#<%s:%s>", c, dirp->path);
-	return rb_str_new2(buf);
-    }
-    return rb_funcall(dir, rb_intern("to_s"), 0, 0);
-}
-
-/*
- *  call-seq:
- *     dir.path => string or nil
- *
- *  Returns the path parameter passed to <em>dir</em>'s constructor.
- *
- *     d = Dir.new("..")
- *     d.path   #=> ".."
- */
-static VALUE
-dir_path(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-
-    Data_Get_Struct(dir, struct dir_data, dirp);
-    if (!dirp->path) return Qnil;
-    return rb_str_new2(dirp->path);
-}
-
-/*
- *  call-seq:
- *     dir.read => string or nil
- *
- *  Reads the next entry from <em>dir</em> and returns it as a string.
- *  Returns <code>nil</code> at the end of the stream.
- *
- *     d = Dir.new("testdir")
- *     d.read   #=> "."
- *     d.read   #=> ".."
- *     d.read   #=> "config.h"
- */
-static VALUE
-dir_read(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-    struct dirent *dp;
-
-    GetDIR(dir, dirp);
-    errno = 0;
-    dp = readdir(dirp->dir);
-    if (dp) {
-	return rb_tainted_str_new(dp->d_name, NAMLEN(dp));
-    }
-    else if (errno == 0) {	/* end of stream */
-	return Qnil;
-    }
-    else {
-	rb_sys_fail(0);
-    }
-    return Qnil;		/* not reached */
-}
-
-/*
- *  call-seq:
- *     dir.each { |filename| block }  => dir
- *
- *  Calls the block once for each entry in this directory, passing the
- *  filename of each entry as a parameter to the block.
- *
- *     d = Dir.new("testdir")
- *     d.each  {|x| puts "Got #{x}" }
- *
- *  <em>produces:</em>
- *
- *     Got .
- *     Got ..
- *     Got config.h
- *     Got main.rb
- */
-static VALUE
-dir_each(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-    struct dirent *dp;
-
-    RETURN_ENUMERATOR(dir, 0, 0);
-    GetDIR(dir, dirp);
-    rewinddir(dirp->dir);
-    for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
-	rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
-	RETURN_IF_BROKEN();
-	if (dirp->dir == NULL) dir_closed();
-    }
-    return dir;
-}
-
-/*
- *  call-seq:
- *     dir.pos => integer
- *     dir.tell => integer
- *
- *  Returns the current position in <em>dir</em>. See also
- *  <code>Dir#seek</code>.
- *
- *     d = Dir.new("testdir")
- *     d.tell   #=> 0
- *     d.read   #=> "."
- *     d.tell   #=> 12
- */
-#ifdef HAVE_TELLDIR
-static VALUE
-dir_tell(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-    long pos;
-
-    GetDIR(dir, dirp);
-    pos = telldir(dirp->dir);
-    return rb_int2inum(pos);
-}
-#else
-# define dir_tell rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     dir.seek( integer ) => dir
- *
- *  Seeks to a particular location in <em>dir</em>. <i>integer</i>
- *  must be a value returned by <code>Dir#tell</code>.
- *
- *     d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
- *     d.read                   #=> "."
- *     i = d.tell               #=> 12
- *     d.read                   #=> ".."
- *     d.seek(i)                #=> #<Dir:0x401b3c40>
- *     d.read                   #=> ".."
- */
-#ifdef HAVE_SEEKDIR
-static VALUE
-dir_seek(VALUE dir, SEL sel, VALUE pos)
-{
-    struct dir_data *dirp;
-    off_t p = NUM2OFFT(pos);
-
-    GetDIR(dir, dirp);
-    seekdir(dirp->dir, p);
-    return dir;
-}
-#else
-# define dir_seek rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     dir.pos( integer ) => integer
- *
- *  Synonym for <code>Dir#seek</code>, but returns the position
- *  parameter.
- *
- *     d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
- *     d.read                   #=> "."
- *     i = d.pos                #=> 12
- *     d.read                   #=> ".."
- *     d.pos = i                #=> 12
- *     d.read                   #=> ".."
- */
-static VALUE
-dir_set_pos(VALUE dir, SEL sel, VALUE pos)
-{
-    dir_seek(dir, 0, pos);
-    return pos;
-}
-
-/*
- *  call-seq:
- *     dir.rewind => dir
- *
- *  Repositions <em>dir</em> to the first entry.
- *
- *     d = Dir.new("testdir")
- *     d.read     #=> "."
- *     d.rewind   #=> #<Dir:0x401b3fb0>
- *     d.read     #=> "."
- */
-static VALUE
-dir_rewind(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't close");
-    }
-    GetDIR(dir, dirp);
-    rewinddir(dirp->dir);
-    return dir;
-}
-
-/*
- *  call-seq:
- *     dir.close => nil
- *
- *  Closes the directory stream. Any further attempts to access
- *  <em>dir</em> will raise an <code>IOError</code>.
- *
- *     d = Dir.new("testdir")
- *     d.close   #=> nil
- */
-static VALUE
-dir_close(VALUE dir, SEL sel)
-{
-    struct dir_data *dirp;
-
-    GetDIR(dir, dirp);
-    closedir(dirp->dir);
-    dirp->dir = NULL;
-
-    return Qnil;
-}
-
-static void
-dir_chdir(VALUE path)
-{
-    const char *cpath = RSTRING_PTR(path);
-    if (chdir(cpath) < 0)
-	rb_sys_fail(cpath);
-}
-
-static int chdir_blocking = 0;
-//static VALUE chdir_thread = Qnil;
-
-struct chdir_data {
-    VALUE old_path, new_path;
-    int done;
-};
-
-static VALUE
-chdir_yield(struct chdir_data *args)
-{
-    dir_chdir(args->new_path);
-    args->done = Qtrue;
-    chdir_blocking++;
-//    if (chdir_thread == Qnil)
-//	chdir_thread = rb_thread_current();
-    return rb_yield(args->new_path);
-}
-
-static VALUE
-chdir_restore(struct chdir_data *args)
-{
-    if (args->done) {
-	chdir_blocking--;
-//	if (chdir_blocking == 0)
-//	    chdir_thread = Qnil;
-	dir_chdir(args->old_path);
-    }
-    GC_RELEASE(args->old_path);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     Dir.chdir( [ string] ) => 0
- *     Dir.chdir( [ string] ) {| path | block }  => anObject
- *
- *  Changes the current working directory of the process to the given
- *  string. When called without an argument, changes the directory to
- *  the value of the environment variable <code>HOME</code>, or
- *  <code>LOGDIR</code>. <code>SystemCallError</code> (probably
- *  <code>Errno::ENOENT</code>) if the target directory does not exist.
- *
- *  If a block is given, it is passed the name of the new current
- *  directory, and the block is executed with that as the current
- *  directory. The original working directory is restored when the block
- *  exits. The return value of <code>chdir</code> is the value of the
- *  block. <code>chdir</code> blocks can be nested, but in a
- *  multi-threaded program an error will be raised if a thread attempts
- *  to open a <code>chdir</code> block while another thread has one
- *  open.
- *
- *     Dir.chdir("/var/spool/mail")
- *     puts Dir.pwd
- *     Dir.chdir("/tmp") do
- *       puts Dir.pwd
- *       Dir.chdir("/usr") do
- *         puts Dir.pwd
- *       end
- *       puts Dir.pwd
- *     end
- *     puts Dir.pwd
- *
- *  <em>produces:</em>
- *
- *     /var/spool/mail
- *     /tmp
- *     /usr
- *     /tmp
- *     /var/spool/mail
- */
-static VALUE
-dir_s_chdir(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE path = Qnil;
-
-    rb_secure(2);
-    if (rb_scan_args(argc, argv, "01", &path) == 1) {
-	FilePathValue(path);
-    }
-    else {
-	const char *dist = getenv("HOME");
-	if (!dist) {
-	    dist = getenv("LOGDIR");
-	    if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
-	}
-	path = rb_str_new2(dist);
-    }
-
-    if (chdir_blocking > 0) {
-	//if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
-	if (!rb_block_given_p())
-	    rb_warn("conflicting chdir during another chdir block");
-    }
-
-    if (rb_block_given_p()) {
-	struct chdir_data args;
-	VALUE cwd = ruby_getcwd();
-
-	args.old_path = cwd;
-	GC_RETAIN(args.old_path);
-	args.new_path = path;
-	args.done = Qfalse;
-	return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
-    }
-    dir_chdir(path);
-
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     Dir.getwd => string
- *     Dir.pwd => string
- *
- *  Returns the path to the current working directory of this process as
- *  a string.
- *
- *     Dir.chdir("/tmp")   #=> 0
- *     Dir.getwd           #=> "/tmp"
- */
-static VALUE
-dir_s_getwd(VALUE dir, SEL sel)
-{
-    rb_secure(4);
-    return ruby_getcwd();
-}
-
-static void
-check_dirname(volatile VALUE *dir)
-{
-    const char *path, *pend;
-
-    rb_secure(2);
-    FilePathValue(*dir);
-    path = RSTRING_PTR(*dir);
-    if (path && *(pend = rb_path_end(rb_path_skip_prefix(path)))) {
-	*dir = rb_str_new(path, pend - path);
-    }
-}
-
-/*
- *  call-seq:
- *     Dir.chroot( string ) => 0
- *
- *  Changes this process's idea of the file system root. Only a
- *  privileged process may make this call. Not available on all
- *  platforms. On Unix systems, see <code>chroot(2)</code> for more
- *  information.
- */
-static VALUE
-dir_s_chroot(VALUE dir, SEL sel, VALUE path)
-{
-    check_dirname(&path);
-
-    const char *path_cstr = RSTRING_PTR(path);
-    if (chroot(path_cstr) == -1)
-	rb_sys_fail(path_cstr);
-
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     Dir.mkdir( string [, integer] ) => 0
- *
- *  Makes a new directory named by <i>string</i>, with permissions
- *  specified by the optional parameter <i>anInteger</i>. The
- *  permissions may be modified by the value of
- *  <code>File::umask</code>, and are ignored on NT. Raises a
- *  <code>SystemCallError</code> if the directory cannot be created. See
- *  also the discussion of permissions in the class documentation for
- *  <code>File</code>.
- *
- */
-static VALUE
-dir_s_mkdir(VALUE Obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE path, vmode;
-    int mode;
-    const char *path_cstr;
-
-    if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
-	mode = NUM2INT(vmode);
-    }
-    else {
-	mode = 0777;
-    }
-
-    check_dirname(&path);
-    path_cstr = RSTRING_PTR(path);
-    if (mkdir(path_cstr, mode) == -1)
-	rb_sys_fail(path_cstr);
-
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     Dir.delete( string ) => 0
- *     Dir.rmdir( string ) => 0
- *     Dir.unlink( string ) => 0
- *
- *  Deletes the named directory. Raises a subclass of
- *  <code>SystemCallError</code> if the directory isn't empty.
- */
-static VALUE
-dir_s_rmdir(VALUE obj, SEL sel, VALUE dir)
-{
-    const char *dir_cstr;
-
-    check_dirname(&dir);
-    dir_cstr = RSTRING_PTR(dir);
-    if (rmdir(dir_cstr) < 0)
-	rb_sys_fail(dir_cstr);
-
-    return INT2FIX(0);
-}
-
-static void
-sys_warning_1(const char* mesg)
-{
-    rb_sys_warning("%s", mesg);
-}
-
-#define GLOB_VERBOSE	(1UL << (sizeof(int) * CHAR_BIT - 1))
-#define sys_warning(val) \
-    (void)((flags & GLOB_VERBOSE) && rb_protect((VALUE (*)(VALUE))sys_warning_1, (VALUE)(val), 0))
-
-#define GLOB_ALLOC(type) (type *)malloc(sizeof(type))
-#define GLOB_ALLOC_N(type, n) (type *)malloc(sizeof(type) * (n))
-//#define GLOB_JUMP_TAG(status) ((status == -1) ? rb_memerror() : rb_jump_tag(status))
-
-/*
- * ENOTDIR can be returned by stat(2) if a non-leaf element of the path
- * is not a directory.
- */
-#define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
-
-/* System call with warning */
-static int
-do_stat(const char *path, struct stat *pst, int flags)
-
-{
-    int ret = stat(path, pst);
-    if (ret < 0 && !to_be_ignored(errno))
-	sys_warning(path);
-
-    return ret;
-}
-
-static int
-do_lstat(const char *path, struct stat *pst, int flags)
-{
-    int ret = lstat(path, pst);
-    if (ret < 0 && !to_be_ignored(errno))
-	sys_warning(path);
-
-    return ret;
-}
-
-static DIR *
-do_opendir(const char *path, int flags)
-{
-    DIR *dirp = opendir(path);
-    if (dirp == NULL && !to_be_ignored(errno))
-	sys_warning(path);
-
-    return dirp;
-}
-
-/* Return nonzero if S has any special globbing chars in it.  */
-static int
-has_magic(const char *s, int flags)
-{
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int nocase = flags & FNM_CASEFOLD;
-
-    register const char *p = s;
-    register char c;
-
-    while ((c = *p++) != 0) {
-	switch (c) {
-	  case '*':
-	  case '?':
-	  case '[':
-	    return 1;
-
-	  case '\\':
-	    if (escape && !(c = *p++))
-		return 0;
-	    continue;
-
-	  default:
-	    if (!FNM_SYSCASE && ISALPHA(c) && nocase)
-		return 1;
-	}
-
-	p = Next(p-1);
-    }
-
-    return 0;
-}
-
-/* Find separator in globbing pattern. */
-static char *
-find_dirsep(const char *s, int flags)
-{
-    const int escape = !(flags & FNM_NOESCAPE);
-
-    register const char *p = s;
-    register char c;
-    int open = 0;
-
-    while ((c = *p++) != 0) {
-	switch (c) {
-	  case '[':
-	    open = 1;
-	    continue;
-	  case ']':
-	    open = 0;
-	    continue;
-
-	  case '/':
-	    if (!open)
-		return (char *)p-1;
-	    continue;
-
-	  case '\\':
-	    if (escape && !(c = *p++))
-		return (char *)p-1;
-	    continue;
-	}
-
-	p = Next(p-1);
-    }
-
-    return (char *)p-1;
-}
-
-/* Remove escaping backslashes */
-static void
-remove_backslashes(char *p)
-{
-    char *t = p;
-    char *s = p;
-
-    while (*p) {
-	if (*p == '\\') {
-	    if (t != s)
-		memmove(t, s, p - s);
-	    t += p - s;
-	    s = ++p;
-	    if (!*p) break;
-	}
-	Inc(p);
-    }
-
-    while (*p++);
-
-    if (t != s)
-	memmove(t, s, p - s); /* move '\0' too */
-}
-
-/* Globing pattern */
-enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
-
-struct glob_pattern {
-    char *str;
-    enum glob_pattern_type type;
-    struct glob_pattern *next;
-};
-
-static void glob_free_pattern(struct glob_pattern *list);
-
-static struct glob_pattern *
-glob_make_pattern(const char *p, int flags)
-{
-    struct glob_pattern *list, *tmp, **tail = &list;
-    int dirsep = 0; /* pattern is terminated with '/' */
-
-    while (*p) {
-	tmp = GLOB_ALLOC(struct glob_pattern);
-	if (!tmp) goto error;
-	if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
-	    /* fold continuous RECURSIVEs (needed in glob_helper) */
-	    do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
-	    tmp->type = RECURSIVE;
-	    tmp->str = 0;
-	    dirsep = 1;
-	}
-	else {
-	    const char *m = find_dirsep(p, flags);
-	    char *buf = GLOB_ALLOC_N(char, m-p+1);
-	    if (!buf) {
-		free(tmp);
-		goto error;
-	    }
-	    memcpy(buf, p, m-p);
-	    buf[m-p] = '\0';
-	    tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
-	    tmp->str = buf;
-	    if (*m) {
-		dirsep = 1;
-		p = m + 1;
-	    }
-	    else {
-		dirsep = 0;
-		p = m;
-	    }
-	}
-	*tail = tmp;
-	tail = &tmp->next;
-    }
-
-    tmp = GLOB_ALLOC(struct glob_pattern);
-    if (!tmp) {
-      error:
-	*tail = 0;
-	glob_free_pattern(list);
-	return 0;
-    }
-    tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
-    tmp->str = 0;
-    *tail = tmp;
-    tmp->next = 0;
-
-    return list;
-}
-
-static void
-glob_free_pattern(struct glob_pattern *list)
-{
-    while (list) {
-	struct glob_pattern *tmp = list;
-	list = list->next;
-	if (tmp->str)
-	    free(tmp->str);
-	free(tmp);
-    }
-}
-
-static char *
-join_path(const char *path, int dirsep, const char *name)
-{
-    long len = strlen(path);
-    char *buf = GLOB_ALLOC_N(char, len+strlen(name)+(dirsep?1:0)+1);
-
-    if (!buf) return 0;
-    memcpy(buf, path, len);
-    if (dirsep) {
-	strcpy(buf+len, "/");
-	len++;
-    }
-    strcpy(buf+len, name);
-    return buf;
-}
-
-enum answer { DIR_YES, DIR_NO, DIR_UNKNOWN };
-
-#ifndef S_ISDIR
-#   define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISLNK
-#  ifndef S_IFLNK
-#    define S_ISLNK(m) (0)
-#  else
-#    define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
-#  endif
-#endif
-
-struct glob_args {
-    void (*func)(const char *, VALUE);
-    const char *path;
-    VALUE value;
-};
-
-static VALUE
-glob_func_caller(VALUE val)
-{
-    struct glob_args *args = (struct glob_args *)val;
-
-    (*args->func)(args->path, args->value);
-    return Qnil;
-}
-
-#define glob_call_func(func, path, arg) (*func)(path, arg)
-
-static int
-glob_helper(
-    const char *path,
-    int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */
-    enum answer exist, /* Does 'path' indicate an existing entry? */
-    enum answer isdir, /* Does 'path' indicate a directory or a symlink to a directory? */
-    struct glob_pattern **beg,
-    struct glob_pattern **end,
-    int flags,
-    ruby_glob_func *func,
-    VALUE arg)
-{
-    struct stat st;
-    int status = 0;
-    struct glob_pattern **cur, **new_beg, **new_end;
-    int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
-    int escape = !(flags & FNM_NOESCAPE);
-
-    for (cur = beg; cur < end; ++cur) {
-	struct glob_pattern *p = *cur;
-	if (p->type == RECURSIVE) {
-	    recursive = 1;
-	    p = p->next;
-	}
-	switch (p->type) {
-	  case PLAIN:
-	    plain = 1;
-	    break;
-	  case MAGICAL:
-	    magical = 1;
-	    break;
-	  case MATCH_ALL:
-	    match_all = 1;
-	    break;
-	  case MATCH_DIR:
-	    match_dir = 1;
-	    break;
-	  case RECURSIVE:
-	    rb_bug("continuous RECURSIVEs");
-	}
-    }
-
-    if (*path) {
-	if (match_all && exist == DIR_UNKNOWN) {
-	    if (do_lstat(path, &st, flags) == 0) {
-		exist = DIR_YES;
-		isdir = S_ISDIR(st.st_mode) ? DIR_YES : S_ISLNK(st.st_mode) ? DIR_UNKNOWN : NO;
-	    }
-	    else {
-		exist = DIR_NO;
-		isdir = DIR_NO;
-	    }
-	}
-	if (match_dir && isdir == DIR_UNKNOWN) {
-	    if (do_stat(path, &st, flags) == 0) {
-		exist = DIR_YES;
-		isdir = S_ISDIR(st.st_mode) ? DIR_YES : DIR_NO;
-	    }
-	    else {
-		exist = DIR_NO;
-		isdir = DIR_NO;
-	    }
-	}
-	if (match_all && exist == DIR_YES) {
-	    status = glob_call_func(func, path, arg);
-	    if (status) return status;
-	}
-	if (match_dir && isdir == DIR_YES) {
-	    char *tmp = join_path(path, dirsep, "");
-	    if (!tmp) return -1;
-	    status = glob_call_func(func, tmp, arg);
-	    free(tmp);
-	    if (status) return status;
-	}
-    }
-
-    if (exist == DIR_NO || isdir == DIR_NO) return 0;
-
-    if (magical || recursive) {
-	struct dirent *dp;
-	DIR *dirp = do_opendir(*path ? path : ".", flags);
-	if (dirp == NULL) return 0;
-
-	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
-	    char *buf = join_path(path, dirsep, dp->d_name);
-	    enum answer new_isdir = DIR_UNKNOWN;
-
-	    if (!buf) {
-		status = -1;
-		break;
-	    }
-	    if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
-		&& fnmatch("*", dp->d_name, flags) == 0) {
-		if (do_lstat(buf, &st, flags) == 0)
-		    new_isdir = S_ISDIR(st.st_mode) ? DIR_YES : S_ISLNK(st.st_mode) ? DIR_UNKNOWN : DIR_NO;
-		else
-		    new_isdir = DIR_NO;
-	    }
-
-	    new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
-	    if (!new_beg) {
-		status = -1;
-		break;
-	    }
-
-	    for (cur = beg; cur < end; ++cur) {
-		struct glob_pattern *p = *cur;
-		if (p->type == RECURSIVE) {
-		    if (new_isdir == DIR_YES) /* not symlink but real directory */
-			*new_end++ = p; /* append recursive pattern */
-		    p = p->next; /* 0 times recursion */
-		}
-		if (p->type == PLAIN || p->type == MAGICAL) {
-		    if (fnmatch(p->str, dp->d_name, flags) == 0)
-			*new_end++ = p->next;
-		}
-	    }
-
-	    status = glob_helper(buf, 1, DIR_YES, new_isdir, new_beg, new_end, flags, func, arg);
-	    free(buf);
-	    free(new_beg);
-	    if (status) break;
-	}
-
-	closedir(dirp);
-    }
-    else if (plain) {
-	struct glob_pattern **copy_beg, **copy_end, **cur2;
-
-	copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
-	if (!copy_beg) return -1;
-	for (cur = beg; cur < end; ++cur)
-	    *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
-
-	for (cur = copy_beg; cur < copy_end; ++cur) {
-	    if (*cur) {
-		char *buf;
-		char *name;
-		name = GLOB_ALLOC_N(char, strlen((*cur)->str) + 1);
-		if (!name) {
-		    status = -1;
-		    break;
-		}
-		strcpy(name, (*cur)->str);
-		if (escape) remove_backslashes(name);
-
-		new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
-		if (!new_beg) {
-		    free(name);
-		    status = -1;
-		    break;
-		}
-		*new_end++ = (*cur)->next;
-		for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
-		    if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
-			*new_end++ = (*cur2)->next;
-			*cur2 = 0;
-		    }
-		}
-
-		buf = join_path(path, dirsep, name);
-		free(name);
-		if (!buf) {
-		    free(new_beg);
-		    status = -1;
-		    break;
-		}
-		status = glob_helper(buf, 1, DIR_UNKNOWN, DIR_UNKNOWN, new_beg, new_end, flags, func, arg);
-		free(buf);
-		free(new_beg);
-		if (status) break;
-	    }
-	}
-
-	free(copy_beg);
-    }
-
-    return status;
-}
-
-static int
-ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg)
-{
-    struct glob_pattern *list;
-    const char *root, *start;
-    char *buf;
-    int n;
-    int status;
-
-    start = root = path;
-    flags |= FNM_SYSCASE;
-
-    if (root && *root == '/') root++;
-
-    n = root - start;
-    buf = GLOB_ALLOC_N(char, n + 1);
-    if (!buf) return -1;
-    MEMCPY(buf, start, char, n);
-    buf[n] = '\0';
-
-    list = glob_make_pattern(root, flags);
-    if (!list) {
-	free(buf);
-	return -1;
-    }
-    status = glob_helper(buf, 0, DIR_UNKNOWN, DIR_UNKNOWN, &list, &list + 1, flags, func, arg);
-    glob_free_pattern(list);
-    free(buf);
-
-    return status;
-}
-
-int
-ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
-{
-    return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg);
-}
-
-static int
-rb_glob_caller(const char *path, VALUE a)
-{
-    int status;
-    struct glob_args *args = (struct glob_args *)a;
-
-    args->path = path;
-    rb_protect(glob_func_caller, a, &status);
-    return status;
-}
-
-static int
-rb_glob2(const char *path, int flags, void (*func)(const char *, VALUE), VALUE arg)
-{
-    struct glob_args args;
-
-    args.func = func;
-    args.value = arg;
-
-    if (flags & FNM_SYSCASE) {
-	rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
-    }
-
-    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
-}
-
-void
-rb_glob(const char *path, void (*func)(const char *, VALUE), VALUE arg)
-{
-    /*int status =*/ rb_glob2(path, 0, func, arg);
-    //if (status) GLOB_JUMP_TAG(status);
-}
-
-static void
-push_pattern(const char *path, VALUE ary)
-{
-    VALUE str = rstr_new_path(path);
-    OBJ_TAINT(str);
-    rb_ary_push(ary, str);
-}
-
-int
-ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg)
-{
-    const int escape = !(flags & FNM_NOESCAPE);
-    const char *p = str;
-    const char *s = p;
-    const char *lbrace = 0, *rbrace = 0;
-    int nest = 0, status = 0;
-
-    while (*p) {
-	if (*p == '{' && nest++ == 0) {
-	    lbrace = p;
-	}
-	if (*p == '}' && --nest <= 0) {
-	    rbrace = p;
-	    break;
-	}
-	if (*p == '\\' && escape) {
-	    if (!*++p) break;
-	}
-	Inc(p);
-    }
-
-    if (lbrace && rbrace) {
-	char *buf = GLOB_ALLOC_N(char, strlen(s) + 1);
-	long shift;
-
-	if (!buf) return -1;
-	memcpy(buf, s, lbrace-s);
-	shift = (lbrace-s);
-	p = lbrace;
-	while (p < rbrace) {
-	    const char *t = ++p;
-	    nest = 0;
-	    while (p < rbrace && !(*p == ',' && nest == 0)) {
-		if (*p == '{') nest++;
-		if (*p == '}') nest--;
-		if (*p == '\\' && escape) {
-		    if (++p == rbrace) break;
-		}
-		Inc(p);
-	    }
-	    memcpy(buf+shift, t, p-t);
-	    strcpy(buf+shift+(p-t), rbrace+1);
-	    status = ruby_brace_expand(buf, flags, func, arg);
-	    if (status) break;
-	}
-	free(buf);
-    }
-    else if (!lbrace && !rbrace) {
-	status = (*func)(s, arg);
-    }
-
-    return status;
-}
-
-struct brace_args {
-    ruby_glob_func *func;
-    VALUE value;
-    int flags;
-};
-
-static int
-glob_brace(const char *path, VALUE val)
-{
-    struct brace_args *arg = (struct brace_args *)val;
-
-    return ruby_glob0(path, arg->flags, arg->func, arg->value);
-}
-
-static int
-ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg)
-{
-    struct brace_args args;
-
-    args.func = func;
-    args.value = arg;
-    args.flags = flags;
-    return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args);
-}
-
-int
-ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
-{
-    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg);
-}
-
-static int
-push_glob(VALUE ary, const char *str, int flags)
-{
-    struct glob_args args;
-
-    args.func = push_pattern;
-    args.value = ary;
-    return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
-}
-
-static VALUE
-rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */
-{
-    const char *cstr;
-    long clen;
-    long offset = 0;
-    VALUE ary;
-
-    StringValue(str);
-    ary = rb_ary_new();
-    cstr = RSTRING_PTR(str);
-    clen = RSTRING_LEN(str);
-
-    while (offset < clen) {
-	/*int status =*/ push_glob(ary, cstr + offset, flags);
-	const char *p, *pend;
-	//if (status) GLOB_JUMP_TAG(status);
-	if (offset >= clen) break;
-	p = cstr + offset;
-	p += strlen(p) + 1;
-	pend = cstr + clen;
-	while (p < pend && !*p)
-	    p++;
-	offset = p - cstr;
-    }
-
-    return ary;
-}
-
-static VALUE
-dir_globs(long argc, VALUE *argv, int flags)
-{
-    VALUE ary = rb_ary_new();
-    long i;
-
-    for (i = 0; i < argc; ++i) {
-	//int status;
-	VALUE str = argv[i];
-	StringValue(str);
-	/*status =*/ push_glob(ary, RSTRING_PTR(str), flags);
-	//if (status) GLOB_JUMP_TAG(status);
-    }
-
-    return ary;
-}
-
-#if WITH_OBJC
-static VALUE
-dir_globs0(VALUE args, int flags)
-{
-    VALUE ary = rb_ary_new();
-    long i, n;
-
-    for (i = 0, n = RARRAY_LEN(args); i < n; i++) {
-	//int status;
-	VALUE str = RARRAY_AT(args, i);
-	StringValue(str);
-	/*status =*/ push_glob(ary, RSTRING_PTR(str), flags);
-//	if (status) 
-//	    GLOB_JUMP_TAG(status);
-    }
-
-    return ary;
-}
-#endif
-
-/*
- *  call-seq:
- *     Dir[ array ]                 => array
- *     Dir[ string [, string ...] ] => array
- *
- *  Equivalent to calling
- *  <code>Dir.glob(</code><i>array,</i><code>0)</code> and
- *  <code>Dir.glob([</code><i>string,...</i><code>],0)</code>.
- *
- */
-static VALUE
-dir_s_aref(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 1) {
-	return rb_push_glob(argv[0], 0);
-    }
-    return dir_globs(argc, argv, 0);
-}
-
-/*
- *  call-seq:
- *     Dir.glob( pattern, [flags] ) => array
- *     Dir.glob( pattern, [flags] ) {| filename | block }  => nil
- *
- *  Returns the filenames found by expanding <i>pattern</i> which is
- *  an +Array+ of the patterns or the pattern +String+, either as an
- *  <i>array</i> or as parameters to the block. Note that this pattern
- *  is not a regexp (it's closer to a shell glob). See
- *  <code>File::fnmatch</code> for the meaning of the <i>flags</i>
- *  parameter. Note that case sensitivity depends on your system (so
- *  <code>File::FNM_CASEFOLD</code> is ignored)
- *
- *  <code>*</code>::        Matches any file. Can be restricted by
- *                          other values in the glob. <code>*</code>
- *                          will match all files; <code>c*</code> will
- *                          match all files beginning with
- *                          <code>c</code>; <code>*c</code> will match
- *                          all files ending with <code>c</code>; and
- *                          <code>*c*</code> will match all files that
- *                          have <code>c</code> in them (including at
- *                          the beginning or end). Equivalent to
- *                          <code>/ .* /x</code> in regexp.
- *  <code>**</code>::       Matches directories recursively.
- *  <code>?</code>::        Matches any one character. Equivalent to
- *                          <code>/.{1}/</code> in regexp.
- *  <code>[set]</code>::    Matches any one character in +set+.
- *                          Behaves exactly like character sets in
- *                          Regexp, including set negation
- *                          (<code>[^a-z]</code>).
- *  <code>{p,q}</code>::    Matches either literal <code>p</code> or
- *                          literal <code>q</code>. Matching literals
- *                          may be more than one character in length.
- *                          More than two literals may be specified.
- *                          Equivalent to pattern alternation in
- *                          regexp.
- *  <code>\</code>::        Escapes the next metacharacter.
- *
- *     Dir["config.?"]                     #=> ["config.h"]
- *     Dir.glob("config.?")                #=> ["config.h"]
- *     Dir.glob("*.[a-z][a-z]")            #=> ["main.rb"]
- *     Dir.glob("*.[^r]*")                 #=> ["config.h"]
- *     Dir.glob("*.{rb,h}")                #=> ["main.rb", "config.h"]
- *     Dir.glob("*")                       #=> ["config.h", "main.rb"]
- *     Dir.glob("*", File::FNM_DOTMATCH)   #=> [".", "..", "config.h", "main.rb"]
- *
- *     rbfiles = File.join("**", "*.rb")
- *     Dir.glob(rbfiles)                   #=> ["main.rb",
- *                                         #    "lib/song.rb",
- *                                         #    "lib/song/karaoke.rb"]
- *     libdirs = File.join("**", "lib")
- *     Dir.glob(libdirs)                   #=> ["lib"]
- *
- *     librbfiles = File.join("**", "lib", "**", "*.rb")
- *     Dir.glob(librbfiles)                #=> ["lib/song.rb",
- *                                         #    "lib/song/karaoke.rb"]
- *
- *     librbfiles = File.join("**", "lib", "*.rb")
- *     Dir.glob(librbfiles)                #=> ["lib/song.rb"]
- */
-
-static VALUE
-dir_s_glob(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE str, rflags, ary;
-    int flags;
-
-    if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2) {
-	flags = NUM2INT(rflags);
-    }
-    else {
-	flags = 0;
-    }
-
-    ary = rb_check_array_type(str);
-    if (NIL_P(ary)) {
-	ary = rb_push_glob(str, flags);
-    }
-    else {
-#if WITH_OBJC
-	ary = dir_globs0(ary, flags);
-#else
-	volatile VALUE v = ary;
-	ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
-#endif
-    }
-
-    if (rb_block_given_p()) {
-	rb_ary_each(ary);
-	return Qnil;
-    }
-    return ary;
-}
-
-static VALUE
-dir_open_dir(VALUE path)
-{
-    VALUE dir = rb_funcall(rb_cDir, rb_intern("open"), 1, path);
-
-    if (TYPE(dir) != T_DATA ||
-	RDATA(dir)->dfree != (RUBY_DATA_FUNC)free_dir) {
-	rb_raise(rb_eTypeError, "wrong argument type %s (expected Dir)",
-		 rb_obj_classname(dir));
-    }
-    return dir;
-}
-
-
-/*
- *  call-seq:
- *     Dir.foreach( dirname ) {| filename | block }  => nil
- *
- *  Calls the block once for each entry in the named directory, passing
- *  the filename of each entry as a parameter to the block.
- *
- *     Dir.foreach("testdir") {|x| puts "Got #{x}" }
- *
- *  <em>produces:</em>
- *
- *     Got .
- *     Got ..
- *     Got config.h
- *     Got main.rb
- *
- */
-static VALUE
-dir_foreach(VALUE io, SEL sel, VALUE dirname)
-{
-    VALUE dir;
-
-    RETURN_ENUMERATOR(io, 1, &dirname);
-    dir = dir_open_dir(dirname);
-    rb_ensure(dir_each, dir, dir_close, dir);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     Dir.entries( dirname ) => array
- *
- *  Returns an array containing all of the filenames in the given
- *  directory. Will raise a <code>SystemCallError</code> if the named
- *  directory doesn't exist.
- *
- *     Dir.entries("testdir")   #=> [".", "..", "config.h", "main.rb"]
- *
- */
-static VALUE
-dir_entries(VALUE io, SEL sel, VALUE dirname)
-{
-    VALUE dir;
-
-    dir = dir_open_dir(dirname);
-    return rb_ensure(rb_Array, dir, dir_close, dir);
-}
-
-/*
- *  call-seq:
- *     File.fnmatch( pattern, path, [flags] ) => (true or false)
- *     File.fnmatch?( pattern, path, [flags] ) => (true or false)
- *
- *  Returns true if <i>path</i> matches against <i>pattern</i> The
- *  pattern is not a regular expression; instead it follows rules
- *  similar to shell filename globbing. It may contain the following
- *  metacharacters:
- *
- *  <code>*</code>::        Matches any file. Can be restricted by
- *                          other values in the glob. <code>*</code>
- *                          will match all files; <code>c*</code> will
- *                          match all files beginning with
- *                          <code>c</code>; <code>*c</code> will match
- *                          all files ending with <code>c</code>; and
- *                          <code>*c*</code> will match all files that
- *                          have <code>c</code> in them (including at
- *                          the beginning or end). Equivalent to
- *                          <code>/ .* /x</code> in regexp.
- *  <code>**</code>::       Matches directories recursively or files
- *                          expansively.
- *  <code>?</code>::        Matches any one character. Equivalent to
- *                          <code>/.{1}/</code> in regexp.
- *  <code>[set]</code>::    Matches any one character in +set+.
- *                          Behaves exactly like character sets in
- *                          Regexp, including set negation
- *                          (<code>[^a-z]</code>).
- *  <code>\</code>::        Escapes the next metacharacter.
- *
- *  <i>flags</i> is a bitwise OR of the <code>FNM_xxx</code>
- *  parameters. The same glob pattern and flags are used by
- *  <code>Dir::glob</code>.
- *
- *     File.fnmatch('cat',       'cat')        #=> true  # match entire string
- *     File.fnmatch('cat',       'category')   #=> false # only match partial string
- *     File.fnmatch('c{at,ub}s', 'cats')       #=> false # { } isn't supported
- *
- *     File.fnmatch('c?t',     'cat')          #=> true  # '?' match only 1 character
- *     File.fnmatch('c??t',    'cat')          #=> false # ditto
- *     File.fnmatch('c*',      'cats')         #=> true  # '*' match 0 or more characters
- *     File.fnmatch('c*t',     'c/a/b/t')      #=> true  # ditto
- *     File.fnmatch('ca[a-z]', 'cat')          #=> true  # inclusive bracket expression
- *     File.fnmatch('ca[^t]',  'cat')          #=> false # exclusive bracket expression ('^' or '!')
- *
- *     File.fnmatch('cat', 'CAT')                     #=> false # case sensitive
- *     File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true  # case insensitive
- *
- *     File.fnmatch('?',   '/', File::FNM_PATHNAME)  #=> false # wildcard doesn't match '/' on FNM_PATHNAME
- *     File.fnmatch('*',   '/', File::FNM_PATHNAME)  #=> false # ditto
- *     File.fnmatch('[/]', '/', File::FNM_PATHNAME)  #=> false # ditto
- *
- *     File.fnmatch('\?',   '?')                       #=> true  # escaped wildcard becomes ordinary
- *     File.fnmatch('\a',   'a')                       #=> true  # escaped ordinary remains ordinary
- *     File.fnmatch('\a',   '\a', File::FNM_NOESCAPE)  #=> true  # FNM_NOESACPE makes '\' ordinary
- *     File.fnmatch('[\?]', '?')                       #=> true  # can escape inside bracket expression
- *
- *     File.fnmatch('*',   '.profile')                      #=> false # wildcard doesn't match leading
- *     File.fnmatch('*',   '.profile', File::FNM_DOTMATCH)  #=> true  # period by default.
- *     File.fnmatch('.*',  '.profile')                      #=> true
- *
- *     rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
- *     File.fnmatch(rbfiles, 'main.rb')                    #=> false
- *     File.fnmatch(rbfiles, './main.rb')                  #=> false
- *     File.fnmatch(rbfiles, 'lib/song.rb')                #=> true
- *     File.fnmatch('**.rb', 'main.rb')                    #=> true
- *     File.fnmatch('**.rb', './main.rb')                  #=> false
- *     File.fnmatch('**.rb', 'lib/song.rb')                #=> true
- *     File.fnmatch('*',           'dave/.profile')                      #=> true
- *
- *     pattern = '*' '/' '*'
- *     File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME)  #=> false
- *     File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- *
- *     pattern = '**' '/' 'foo'
- *     File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME)     #=> true
- *     File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME)    #=> true
- *     File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME)  #=> true
- *     File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME)    #=> false
- *     File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- */
-static VALUE
-file_s_fnmatch(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE pattern, path;
-    VALUE rflags;
-    int flags;
-
-    if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
-	flags = NUM2INT(rflags);
-    else
-	flags = 0;
-
-    StringValue(pattern);
-    FilePathStringValue(path);
-
-    if (fnmatch(RSTRING_PTR(pattern), RSTRING_PTR(path), flags) == 0)
-	return Qtrue;
-
-    return Qfalse;
-}
-
-VALUE rb_home_dir(VALUE user);
-
-/*
- *  call-seq:
- *    Dir.home()       => "/home/me"
- *    Dir.home("root") => "/root"
- *
- *  Returns the home directory of the current user or the named user
- *  if given.
- */
-static VALUE
-dir_s_home(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE user;
-
-    rb_scan_args(argc, argv, "01", &user);
-    if (!NIL_P(user)) {
-	SafeStringValue(user);
-	//u = StringValueCStr(user);
-    }
-    return rb_home_dir(user);
-}
-
-/*
- *  Objects of class <code>Dir</code> are directory streams representing
- *  directories in the underlying file system. They provide a variety of
- *  ways to list directories and their contents. See also
- *  <code>File</code>.
- *
- *  The directory used in these examples contains the two regular files
- *  (<code>config.h</code> and <code>main.rb</code>), the parent
- *  directory (<code>..</code>), and the directory itself
- *  (<code>.</code>).
- */
-void
-Init_Dir(void)
-{
-    rb_cDir = rb_define_class("Dir", rb_cObject);
-
-    rb_include_module(rb_cDir, rb_mEnumerable);
-
-    rb_objc_define_method(*(VALUE *)rb_cDir, "alloc", dir_s_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "open", dir_s_open, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "foreach", dir_foreach, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "entries", dir_entries, 1);
-
-    rb_objc_define_method(rb_cDir, "initialize", dir_initialize, 1);
-    rb_objc_define_method(rb_cDir, "path", dir_path, 0);
-    rb_objc_define_method(rb_cDir, "inspect", dir_inspect, 0);
-    rb_objc_define_method(rb_cDir, "read", dir_read, 0);
-    rb_objc_define_method(rb_cDir, "each", dir_each, 0);
-    rb_objc_define_method(rb_cDir, "rewind", dir_rewind, 0);
-    rb_objc_define_method(rb_cDir, "tell", dir_tell, 0);
-    rb_objc_define_method(rb_cDir, "seek", dir_seek, 1);
-    rb_objc_define_method(rb_cDir, "pos", dir_tell, 0);
-    rb_objc_define_method(rb_cDir, "pos=", dir_set_pos, 1);
-    rb_objc_define_method(rb_cDir, "close", dir_close, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_cDir, "chdir", dir_s_chdir, -1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "getwd", dir_s_getwd, 0);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "pwd", dir_s_getwd, 0);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "chroot", dir_s_chroot, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "mkdir", dir_s_mkdir, -1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "rmdir", dir_s_rmdir, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "delete", dir_s_rmdir, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "unlink", dir_s_rmdir, 1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "home", dir_s_home, -1);
-
-    rb_objc_define_method(*(VALUE *)rb_cDir, "glob", dir_s_glob, -1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "[]", dir_s_aref, -1);
-    rb_objc_define_method(*(VALUE *)rb_cDir, "exist?", rb_file_directory_p, 1); /* in file.c */
-    rb_objc_define_method(*(VALUE *)rb_cDir, "exists?", rb_file_directory_p, 1); /* in file.c */
-
-    rb_objc_define_method(*(VALUE *)rb_cFile,"fnmatch", file_s_fnmatch, -1);
-    rb_objc_define_method(*(VALUE *)rb_cFile,"fnmatch?", file_s_fnmatch, -1);
-
-    rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
-    rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
-    rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
-    rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
-    rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
-
-    // MacRuby extension (for tmpdir.rb).
-    char buf[MAXPATHLEN];
-    const size_t buflen = confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof buf);
-    VALUE str = buflen > 0 ? rb_obj_freeze(rb_str_new2(buf)) : Qnil;
-    rb_define_const(rb_cDir, "NS_TMPDIR", str);
-}

Deleted: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dispatcher.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1627 +0,0 @@
-/*
- * MacRuby Dispatcher.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#include "llvm.h"
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "id.h"
-#include "vm.h"
-#include "compiler.h"
-#include "objc.h"
-#include "dtrace.h"
-#include "class.h"
-
-#include <execinfo.h>
-#include <dlfcn.h>
-
-#define ROXOR_VM_DEBUG		0
-#define MAX_DISPATCH_ARGS 	100
-
-static force_inline void
-vm_fix_args(const VALUE *argv, VALUE *new_argv, const rb_vm_arity_t &arity,
-	int argc)
-{
-    assert(argc >= arity.min);
-    assert((arity.max == -1) || (argc <= arity.max));
-    const int used_opt_args = argc - arity.min;
-    int opt_args, rest_pos;
-    if (arity.max == -1) {
-	opt_args = arity.real - arity.min - 1;
-	rest_pos = arity.left_req + opt_args;
-    }
-    else {
-	opt_args = arity.real - arity.min;
-	rest_pos = -1;
-    }
-    for (int i = 0; i < arity.real; ++i) {
-	if (i < arity.left_req) {
-	    // required args before optional args
-	    new_argv[i] = argv[i];
-	}
-	else if (i < arity.left_req + opt_args) {
-	    // optional args
-	    const int opt_arg_index = i - arity.left_req;
-	    if (opt_arg_index >= used_opt_args) {
-		new_argv[i] = Qundef;
-	    }
-	    else {
-		new_argv[i] = argv[i];
-	    }
-	}
-	else if (i == rest_pos) {
-	    // rest
-	    const int rest_size = argc - arity.real + 1;
-	    if (rest_size <= 0) {
-		new_argv[i] = rb_ary_new();
-	    }
-	    else {
-		new_argv[i] = rb_ary_new4(rest_size, &argv[i]);
-	    }
-	}
-	else {
-	    // required args after optional args
-	    new_argv[i] = argv[argc-(arity.real - i)];
-	}
-    }
-}
-
-static force_inline VALUE
-__rb_vm_bcall(VALUE self, SEL sel, VALUE dvars, rb_vm_block_t *b,
-	IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
-{
-    VALUE buf[100];
-    if (arity.real != argc || arity.max == -1) {
-	VALUE *new_argv;
-	if (arity.real < 100) {
-	    new_argv = buf;
-	}
-	else {
-	    new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
-	}
-	vm_fix_args(argv, new_argv, arity, argc);
-	argv = new_argv;
-	argc = arity.real;
-    }
-
-    assert(pimp != NULL);
-
-    VALUE (*imp)(VALUE, SEL, VALUE, rb_vm_block_t *,  ...) =
-	(VALUE (*)(VALUE, SEL, VALUE, rb_vm_block_t *, ...))pimp;
-
-    switch (argc) {
-	case 0:
-	    return (*imp)(self, sel, dvars, b);
-	case 1:
-	    return (*imp)(self, sel, dvars, b, argv[0]);
-	case 2:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1]);
-	case 3:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2]);
-	case 4:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3]);
-	case 5:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3], argv[4]);
-	case 6:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3], argv[4], argv[5]);
-	case 7:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3], argv[4], argv[5], argv[6]);
-	case 8:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3], argv[4], argv[5], argv[6], argv[7]);
-	case 9:
-	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2],
-		    argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
-    }
-
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError,
-	    "MacRuby static doesn't support passing more than 9 arguments");
-#else
-    rb_vm_long_arity_bstub_t *stub = (rb_vm_long_arity_bstub_t *)
-	GET_CORE()->gen_large_arity_stub(argc, true);
-    return (*stub)(pimp, (id)self, sel, dvars, b, argc, argv);
-#endif
-}
-
-static force_inline VALUE
-__rb_vm_rcall(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity,
-	int argc, const VALUE *argv)
-{
-    VALUE buf[100];
-    if (arity.real != argc || arity.max == -1) {
-	VALUE *new_argv;
-	if (arity.real < 100) {
-	    new_argv = buf;
-	}
-	else {
-	    new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
-	}
-	vm_fix_args(argv, new_argv, arity, argc);
-	argv = new_argv;
-	argc = arity.real;
-    }
-
-    assert(pimp != NULL);
-
-    VALUE (*imp)(VALUE, SEL, ...) = (VALUE (*)(VALUE, SEL, ...))pimp;
-
-    switch (argc) {
-	case 0:
-	    return (*imp)(self, sel);
-	case 1:
-	    return (*imp)(self, sel, argv[0]);
-	case 2:
-	    return (*imp)(self, sel, argv[0], argv[1]);		
-	case 3:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2]);
-	case 4:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3]);
-	case 5:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4]);
-	case 6:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5]);
-	case 7:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5], argv[6]);
-	case 8:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5], argv[6], argv[7]);
-	case 9:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5], argv[6], argv[7], argv[8]);
-	case 10:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
-	case 11:
-	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3],
-		    argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
-		    argv[10]);
-    }
-
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError,
-	    "MacRuby static doesn't support passing more than 9 arguments");
-#else
-    rb_vm_long_arity_stub_t *stub = (rb_vm_long_arity_stub_t *)
-	GET_CORE()->gen_large_arity_stub(argc);
-    return (*stub)(pimp, (id)self, sel, argc, argv);
-#endif
-}
-
-static void
-vm_gen_bs_func_types(int argc, const VALUE *argv,
-	bs_element_function_t *bs_func, std::string &types)
-{
-    types.append(bs_func->retval == NULL ? "v" : bs_func->retval->type);
-    int printf_arg = -1;
-    for (int i = 0; i < (int)bs_func->args_count; i++) {
-	types.append(bs_func->args[i].type);
-	if (bs_func->args[i].printf_format) {
-	    printf_arg = i;
-	}
-    }
-    if (bs_func->variadic) {
-	// TODO honor printf_format
-//	if (printf_arg != -1) {	    
-//	}
-	for (int i = bs_func->args_count; i < argc; i++) {
-	    types.append("@");
-	}
-    }
-}
-
-static SEL
-helper_sel(const char *p, size_t len)
-{
-    SEL new_sel = 0;
-    char buf[100];
-
-    // Avoid buffer overflow
-    // len + "sel" + ':' + '\0'
-    if ((len + 5) > sizeof(buf)) {
-	return (SEL)0;
-    }
-
-    if (len >= 3 && isalpha(p[len - 3]) && p[len - 2] == '='
-	&& p[len - 1] == ':') {
-
-	// foo=: -> setFoo: shortcut
-	snprintf(buf, sizeof buf, "set%s", p);
-	buf[3] = toupper(buf[3]);
-	buf[len + 1] = ':';
-	buf[len + 2] = '\0';
-	new_sel = sel_registerName(buf);
-    }
-    else if (len > 1 && p[len - 1] == '?') {
-	// foo?: -> isFoo: shortcut
-	snprintf(buf, sizeof buf, "is%s", p);
-	buf[2] = toupper(buf[2]);
-	buf[len + 1] = '\0';
-	new_sel = sel_registerName(buf);
-    }
-    else if (strcmp(p, "[]:") == 0) {
-	// []: -> objectForKey: shortcut
-	new_sel = selObjectForKey;
-    }
-    else if (strcmp(p, "[]=:") == 0) {
-	// []=: -> setObjectForKey: shortcut
-	new_sel = selSetObjectForKey;
-    }
-
-    return new_sel;
-}
-
-static Method
-rb_vm_super_lookup(Class klass, SEL sel, Class *super_class_p)
-{
-    // Locate the current method implementation.
-    Class self_class = klass;
-    Method method = class_getInstanceMethod(self_class, sel);
-    if (method == NULL) {
-	// The given selector does not exist, let's go through
-	// #method_missing...
-	*super_class_p = NULL;
-	return NULL; 
-    }
-    IMP self_imp = method_getImplementation(method);
-
-    // Iterate over ancestors, locate the current class and return the
-    // super method, if it exists.
-    VALUE ary = rb_mod_ancestors_nocopy((VALUE)klass);
-    const int count = RARRAY_LEN(ary);
-    bool klass_located = false;
-#if ROXOR_VM_DEBUG
-    printf("locating super method %s of class %s (%p) in ancestor chain: ", 
-	    sel_getName(sel), rb_class2name((VALUE)klass), klass);
-    for (int i = 0; i < count; i++) {
-	VALUE sk = RARRAY_AT(ary, i);
-	printf("%s (%p) ", rb_class2name(sk), (void *)sk);
-    }
-    printf("\n");
-#endif
-try_again:
-    for (int i = 0; i < count; i++) {
-        if (!klass_located && RARRAY_AT(ary, i) == (VALUE)self_class) {
-            klass_located = true;
-        }
-        if (klass_located) {
-            if (i < count - 1) {
-                VALUE k = RARRAY_AT(ary, i + 1);
-#if ROXOR_VM_DEBUG
-		printf("looking in %s\n", rb_class2name((VALUE)k));
-#endif
-
-		Method method = class_getInstanceMethod((Class)k, sel);
-		if (method == NULL) {
-		    continue;
-		}
-
-		IMP imp = method_getImplementation(method);
-		if (imp == self_imp || UNAVAILABLE_IMP(imp)) {
-		    continue;
-		}
-
-		VALUE super = RCLASS_SUPER(k);
-		if (super != 0 && class_getInstanceMethod((Class)super,
-			    sel) == method) {
-		    continue;
-		}
-
-#if ROXOR_VM_DEBUG
-		printf("returning method %p of class %s (#%d)\n",
-			method, rb_class2name(k), i + 1);
-#endif
-
-		*super_class_p = (Class)k;
-		return method;
-            }
-        }
-    }
-    if (!klass_located) {
-	// Could not locate the receiver's class in the ancestors list.
-	// It probably means that the receiver has been extended somehow.
-	// We therefore assume that the super method will be in the direct
-	// superclass.
-	klass_located = true;
-	goto try_again;
-    }
-
-    *super_class_p = NULL;
-    return NULL;
-}
-
-static VALUE
-method_missing(VALUE obj, SEL sel, rb_vm_block_t *block, int argc,
-	const VALUE *argv, rb_vm_method_missing_reason_t call_status)
-{
-    if (sel == selAlloc) {
-        rb_raise(rb_eTypeError, "allocator undefined for %s",
-                 rb_class2name(obj));
-    }
-
-    GET_VM()->set_method_missing_reason(call_status);
-
-    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * (argc + 1));
-
-    char buf[100];
-    int n = snprintf(buf, sizeof buf, "%s", sel_getName(sel));
-    if (buf[n - 1] == ':') {
-	// Let's see if there are more colons making this a real selector.
-	bool multiple_colons = false;
-	for (int i = 0; i < (n - 1); i++) {
-	    if (buf[i] == ':') {
-		multiple_colons = true;
-		break;
-	    }
-	}
-	if (!multiple_colons) {
-	    // Not a typical multiple argument selector. So as this is
-	    // probably a typical ruby method name, chop off the colon.
-	    buf[n - 1] = '\0';
-	}
-    }
-    new_argv[0] = ID2SYM(rb_intern(buf));
-    MEMCPY(&new_argv[1], argv, VALUE, argc);
-
-    // In case the missing selector _is_ method_missing: OR the object does
-    // not respond to method_missing: (this can happen for NSProxy-based
-    // objects), directly trigger the exception.
-    Class k = (Class)CLASS_OF(obj);
-    if (sel == selMethodMissing
-	    || class_getInstanceMethod(k, selMethodMissing) == NULL) {
-	rb_vm_method_missing(obj, argc + 1, new_argv);
-	return Qnil; // never reached
-    }
-    else {
-	return rb_vm_call2(block, obj, (VALUE)k, selMethodMissing, argc + 1,
-		new_argv);
-    }
-}
-
-extern "C"
-void *
-rb_vm_undefined_imp(void *rcv, SEL sel)
-{
-    method_missing((VALUE)rcv, sel, NULL, NULL, NULL, METHOD_MISSING_DEFAULT);
-    return NULL; // never reached
-}
-
-extern "C"
-void *
-rb_vm_removed_imp(void *rcv, SEL sel)
-{
-    method_missing((VALUE)rcv, sel, NULL, NULL, NULL, METHOD_MISSING_DEFAULT);
-    return NULL; // never reached
-}
-
-static force_inline VALUE
-ruby_dispatch(VALUE top, VALUE self, SEL sel, rb_vm_method_node_t *node,
-	unsigned char opt, int argc, const VALUE *argv)
-{
-    const rb_vm_arity_t &arity = node->arity;
-    if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
-	short limit = (argc < arity.min) ? arity.min : arity.max;
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		argc, limit);
-    }
-
-    if ((node->flags & VM_METHOD_PRIVATE) && opt == 0) {
-	// Calling a private method with no explicit receiver OR an attribute
-	// assignment to non-self, triggering #method_missing.
-	rb_vm_block_t *b = GET_VM()->current_block();
-	return method_missing(self, sel, b, argc, argv,
-		METHOD_MISSING_PRIVATE);
-    }
-
-    if ((node->flags & VM_METHOD_PROTECTED)
-	    && top != 0 && node->klass != NULL
-	    && !rb_obj_is_kind_of(top, (VALUE)node->klass)) {
-	// Calling a protected method inside a method where 'self' is not
-	// an instance of the class where the method was originally defined,
-	// triggering #method_missing.
-	rb_vm_block_t *b = GET_VM()->current_block();
-	return method_missing(self, sel, b, argc, argv,
-		METHOD_MISSING_PROTECTED);
-    }
-
-    if ((node->flags & VM_METHOD_EMPTY) && arity.max == arity.min) {
-	// Calling an empty method, let's just return nil!
-	return Qnil;
-    }
-
-    if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) {
-	// Calling a function defined with rb_objc_define_method with
-	// a negative arity, which means a different calling convention.
-	if (arity.real == 2) {
-	    return ((VALUE (*)(VALUE, SEL, int, const VALUE *))node->ruby_imp)
-		(self, sel, argc, argv);
-	}
-	else if (arity.real == 1) {
-	    return ((VALUE (*)(VALUE, SEL, ...))node->ruby_imp)
-		(self, sel, rb_ary_new4(argc, argv));
-	}
-	else if (arity.real == 3) {
-	    return ((VALUE (*)(VALUE, SEL, VALUE, int,
-			    const VALUE *))node->ruby_imp)
-		(self, sel, top, argc, argv);
-	}
-	else {
-	    printf("invalid negative arity for C function %d\n",
-		    arity.real);
-	    abort();
-	}
-    }
-
-    return __rb_vm_rcall(self, sel, node->ruby_imp, arity, argc, argv);
-}
-
-static
-#if __LP64__
-// This method can't be inlined in 32-bit because @try compiles as a call
-// to setjmp().
-force_inline
-#endif
-VALUE
-__rb_vm_objc_dispatch(rb_vm_objc_stub_t *stub, IMP imp, id rcv, SEL sel,
-	int argc, const VALUE *argv)
-{
-    @try {
-	return (*stub)(imp, rcv, sel, argc, argv);
-    }
-    @catch (id exc) {
-	bool created = false;
-	VALUE rbexc = rb_oc2rb_exception(exc, &created);
-#if __LP64__
-	if (rb_vm_current_exception() == Qnil) {
-	    rb_vm_set_current_exception(rbexc);
-	    throw;
-	}
-#endif
-	if (created) {
-	    rb_exc_raise(rbexc);
-	}
-	throw;
-    }
-    abort(); // never reached
-}
-
-static void
-fill_rcache(struct mcache *cache, Class klass, SEL sel,
-	rb_vm_method_node_t *node)
-{
-    cache->flag = MCACHE_RCALL;
-    cache->sel = sel;
-    cache->klass = klass;
-    cache->as.rcall.node = node;
-}
-
-static void
-fill_ocache(struct mcache *cache, VALUE self, Class klass, IMP imp, SEL sel,
-	    Method method, int argc)
-{
-    cache->flag = MCACHE_OCALL;
-    cache->sel = sel;
-    cache->klass = klass;
-    cache->as.ocall.imp = imp;
-    cache->as.ocall.argc = argc;
-    cache->as.ocall.bs_method = GET_CORE()->find_bs_method(klass, sel);
-
-    char types[200];
-    if (!rb_objc_get_types(self, klass, sel, method, cache->as.ocall.bs_method,
-		types, sizeof types)) {
-	printf("cannot get encoding types for %c[%s %s]\n",
-		class_isMetaClass(klass) ? '+' : '-',
-		class_getName(klass),
-		sel_getName(sel));
-	abort();
-    }
-    bool variadic = false;
-    if (cache->as.ocall.bs_method != NULL
-	    && cache->as.ocall.bs_method->variadic && method != NULL) {
-	// TODO honor printf_format
-	const int real_argc = rb_method_getNumberOfArguments(method) - 2;
-	if (real_argc < argc) {
-	    const size_t s = strlen(types);
-	    assert(s + argc - real_argc < sizeof types);
-	    for (int i = real_argc; i < argc; i++) {
-		strlcat(types, "@", sizeof types);
-	    }
-	    argc = real_argc;
-	}
-	variadic = true;
-    }
-    cache->as.ocall.stub = (rb_vm_objc_stub_t *)GET_CORE()->gen_stub(types,
-	    variadic, argc, true);
-}
-
-static bool
-reinstall_method_maybe(Class klass, SEL sel, const char *types)
-{
-    Method m = class_getInstanceMethod(klass, sel);
-    if (m == NULL) {
-	return false;
-    }
-
-    rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
-    if (node == NULL) {
-	// We only do that for pure Ruby methods.
-	return false;
-    }
-
-    GET_CORE()->retype_method(klass, node, method_getTypeEncoding(m), types);
-    return true;
-}
-
-static inline bool
-sel_equal(Class klass, SEL x, SEL y)
-{
-    if (x == y) {
-	return true;
-    }
-
-    IMP x_imp = class_getMethodImplementation(klass, x);
-    IMP y_imp = class_getMethodImplementation(klass, y);
-    return x_imp == y_imp;
-}
-
-extern "C"
-VALUE
-rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
-	Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
-	int argc, const VALUE *argv)
-{
-    RoxorVM *vm = (RoxorVM *)_vm;
-
-#if ROXOR_VM_DEBUG
-    bool cached = true;
-#endif
-    bool cache_method = true;
-
-    Class current_super_class = vm->get_current_super_class();
-    SEL current_super_sel = vm->get_current_super_sel();
-
-    if (opt & DISPATCH_SUPER) {
-	// TODO
-	goto recache;
-    }
-
-    if (cache->sel != sel || cache->klass != klass || cache->flag == 0) {
-recache:
-#if ROXOR_VM_DEBUG
-	cached = false;
-#endif
-
-	Method method;
-	if (opt & DISPATCH_SUPER) {
-	    if (!sel_equal(klass, current_super_sel, sel)) {
-		current_super_sel = sel;
-		current_super_class = klass;
-	    }
-	    else {
-		// Let's make sure the current_super_class is valid before
-		// using it; we check this by verifying that it's a real
-		// super class of the current class, as we may be calling
-		// a super method of the same name but on a totally different
-		// class hierarchy.
-		Class k = klass;
-		bool current_super_class_ok = false;
-		while (k != NULL) {
-		    if (k == current_super_class) {
-			current_super_class_ok = true;
-			break;
-		    }
-		    k = class_getSuperclass(k);
-		}
-		if (!current_super_class_ok) {
-		    current_super_class = klass;
-		}
-	    }
-	    method = rb_vm_super_lookup(current_super_class, sel,
-		    &current_super_class);
-	}
-	else {
-	    current_super_sel = 0;
-	    method = class_getInstanceMethod(klass, sel);
-	}
-
-	if (method != NULL) {
-recache2:
-	    IMP imp = method_getImplementation(method);
-
-	    if (UNAVAILABLE_IMP(imp)) {
-		// Method was undefined.
-		goto call_method_missing;
-	    }
-
-	    rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
-
-	    if (node != NULL) {
-		// ruby call
-		fill_rcache(cache, klass, sel, node);
-	    }
-	    else {
-		// objc call
-		fill_ocache(cache, self, klass, imp, sel, method, argc);
-	    }
-
-	    if (opt & DISPATCH_SUPER) {
-		cache->flag |= MCACHE_SUPER;
-	    }
-	}
-	else {
-	    // Method is not found...
-
-#if !defined(MACRUBY_STATIC)
-	    // Force a method resolving, because the objc cache might be
-	    // wrong.
-	    if (rb_vm_resolve_method(klass, sel)) {
-		goto recache;
-	    }
-#endif
-
-	    // Does the receiver implements -forwardInvocation:?
-	    if ((opt & DISPATCH_SUPER) == 0
-		    && rb_objc_supports_forwarding(self, sel)) {
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
-		// In earlier versions of the Objective-C runtime, there seems
-		// to be a bug where class_getInstanceMethod isn't atomic,
-		// and might return NULL while at the exact same time another
-		// thread registers the related method.
-		// As a work-around, we double-check if the method still does
-		// not exist here. If he does, we can dispatch it properly.
-		method = class_getInstanceMethod(klass, sel);
-		if (method != NULL) {
-		    goto recache2;
-		}
-#endif
-		fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL,
-			argc);
-		goto dispatch;
-	    }
-
-	    // Let's see if are not trying to call a Ruby method that accepts
-	    // a regular argument then an optional Hash argument, to be
-	    // compatible with the Ruby specification.
-	    const char *selname = (const char *)sel;
-	    size_t selname_len = strlen(selname);
-	    if (argc > 1) {
-		const char *p = strchr(selname, ':');
-		if (p != NULL && p + 1 != '\0') {
-		    char *tmp = (char *)malloc(selname_len);
-		    strncpy(tmp, selname, p - selname + 1);
-		    tmp[p - selname + 1] = '\0';
-		    sel = sel_registerName(tmp);
-		    VALUE h = rb_hash_new();
-		    bool ok = true;
-		    p += 1;
-		    for (int i = 1; i < argc; i++) {
-			const char *p2 = strchr(p, ':');
-			if (p2 == NULL) {
-			    ok = false;
-			    break;
-			}
-			strlcpy(tmp, p, selname_len);
-			tmp[p2 - p] = '\0';
-			p = p2 + 1; 
-			rb_hash_aset(h, ID2SYM(rb_intern(tmp)), argv[i]);
-		    }
-		    free(tmp);
-		    tmp = NULL;
-		    if (ok) {
-			argc = 2;
-			((VALUE *)argv)[1] = h; // bad, I know...
-			Method m = class_getInstanceMethod(klass, sel);
-			if (m != NULL) {	
-			    method = m;
-			    cache_method = false;
-			    goto recache2;
-			}
-		    }
-		}
-	    }
-
-	    // Enable helpers for classes which are not RubyObject based.
-	    if ((RCLASS_VERSION(klass) & RCLASS_IS_OBJECT_SUBCLASS)
-		    != RCLASS_IS_OBJECT_SUBCLASS) {
-		// Let's try to see if we are not given a helper selector.
-		SEL new_sel = helper_sel(selname, selname_len);
-		if (new_sel != NULL) {
-		    Method m = class_getInstanceMethod(klass, new_sel);
-		    if (m != NULL) {
-		    	sel = new_sel;
-		    	method = m;
-		    	// We need to invert arguments because
-		    	// #[]= and setObject:forKey: take arguments
-		    	// in a reverse order
-		    	if (new_sel == selSetObjectForKey && argc == 2) {
-		    	    VALUE swap = argv[0];
-		    	    ((VALUE *)argv)[0] = argv[1];
-		    	    ((VALUE *)argv)[1] = swap;
-		    	    cache_method = false;
-		    	}
-		    	goto recache2;
-		    }
-		}
-	    }
-
-	    // Let's see if we are not trying to call a BridgeSupport function.
-	    if (selname[selname_len - 1] == ':') {
-		selname_len--;
-	    }
-	    std::string name(selname, selname_len);
-	    bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name);
-	    if (bs_func != NULL) {
-		if ((unsigned)argc < bs_func->args_count
-			|| ((unsigned)argc > bs_func->args_count
-				&& bs_func->variadic == false)) {
-		    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-			argc, bs_func->args_count);
-		}
-		std::string types;
-		vm_gen_bs_func_types(argc, argv, bs_func, types);
-
-		cache->flag = MCACHE_FCALL;
-		cache->sel = sel;
-		cache->klass = klass;
-		cache->as.fcall.bs_function = bs_func;
-		cache->as.fcall.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
-		assert(cache->as.fcall.imp != NULL);
-		cache->as.fcall.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(
-			types, bs_func->variadic, bs_func->args_count, false);
-	    }
-	    else {
-		// Still nothing, then let's call #method_missing.
-		goto call_method_missing;
-	    }
-	}
-    }
-
-dispatch:
-    if (cache->flag & MCACHE_RCALL) {
-	if (!cache_method) {
-	    cache->flag = 0;
-	}
-
-#if ROXOR_VM_DEBUG
-	printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache %p cached %s)\n",
-		class_isMetaClass(klass) ? '+' : '-',
-		class_getName(klass),
-		(void *)self,
-		sel_getName(sel),
-		cache->as.rcall.node->ruby_imp,
-		block,
-		argc,
-		opt,
-		cache,
-		cached ? "true" : "false");
-#endif
-
-	bool block_already_current = vm->is_block_current(block);
-	Class current_klass = vm->get_current_class();
-	if (!block_already_current) {
-	    vm->add_current_block(block);
-	}
-	vm->set_current_class(NULL);
-
-	Class old_current_super_class = vm->get_current_super_class();
-	vm->set_current_super_class(current_super_class);
-	SEL old_current_super_sel = vm->get_current_super_sel();
-	vm->set_current_super_sel(current_super_sel);
-
-	struct Finally {
-	    bool block_already_current;
-	    Class current_class;
-	    Class current_super_class;
-	    SEL current_super_sel;
-	    RoxorVM *vm;
-	    Finally(bool _block_already_current, Class _current_class,
-		    Class _current_super_class, SEL _current_super_sel,
-		    RoxorVM *_vm) {
-		block_already_current = _block_already_current;
-		current_class = _current_class;
-		current_super_class = _current_super_class;
-		current_super_sel = _current_super_sel;
-		vm = _vm;
-	    }
-	    ~Finally() {
-		if (!block_already_current) {
-		    vm->pop_current_block();
-		}
-		vm->set_current_class(current_class);
-		vm->pop_broken_with();
-		vm->set_current_super_class(current_super_class);
-		vm->set_current_super_sel(current_super_sel);
-		vm->pop_current_binding();
-	    }
-	} finalizer(block_already_current, current_klass,
-		old_current_super_class, old_current_super_sel, vm);
-
-	// DTrace probe: method__entry
-	if (MACRUBY_METHOD_ENTRY_ENABLED()) {
-	    char *class_name = (char *)rb_class2name((VALUE)klass);
-	    char *method_name = (char *)sel_getName(sel);
-	    char file[PATH_MAX];
-	    unsigned long line = 0;
-	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
-		    NULL, 0);
-	    MACRUBY_METHOD_ENTRY(class_name, method_name, file, line);
-	}
-
-	VALUE v = ruby_dispatch(top, self, sel, cache->as.rcall.node,
-		opt, argc, argv);
-
-	// DTrace probe: method__return
-	if (MACRUBY_METHOD_RETURN_ENABLED()) {
-	    char *class_name = (char *)rb_class2name((VALUE)klass);
-	    char *method_name = (char *)sel_getName(sel);
-	    char file[PATH_MAX];
-	    unsigned long line = 0;
-	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
-		    NULL, 0);
-	    MACRUBY_METHOD_RETURN(class_name, method_name, file, line);
-	}
-
-	return v;
-    }
-    else if (cache->flag & MCACHE_OCALL) {
-	if (cache->as.ocall.argc != argc) {
-	    goto recache;
-	}
-	if (!cache_method) {
-	    cache->flag = 0;
-	}
-
-	if (block != NULL) {
-	    rb_warn("passing a block to an Objective-C method - " \
-		    "will be ignored");
-	}
-	else if (sel == selNew) {
-	    if (self == rb_cNSMutableArray) {
-		self = rb_cRubyArray;
-	    }
-	}
-	else if (sel == selClass) {
-	    // Because +[NSObject class] returns self.
-	    if (RCLASS_META(klass)) {
-		return RCLASS_MODULE(self) ? rb_cModule : rb_cClass;
-	    }
-	    // Because the CF classes should be hidden, for Ruby compat.
-	    if (self == Qnil) {
-		return rb_cNilClass;
-	    }
-	    if (self == Qtrue) {
-		return rb_cTrueClass;
-	    }
-	    if (self == Qfalse) {
-		return rb_cFalseClass;
-	    }
-	    return rb_class_real((VALUE)klass, true);
-	}
-
-#if ROXOR_VM_DEBUG
-	printf("objc dispatch %c[<%s %p> %s] imp=%p cache=%p argc=%d (cached=%s)\n",
-		class_isMetaClass(klass) ? '+' : '-',
-		class_getName(klass),
-		(void *)self,
-		sel_getName(sel),
-		cache->as.ocall.imp,
-		cache,
-		argc,
-		cached ? "true" : "false");
-#endif
-
-	id ocrcv = RB2OC(self);
-
- 	if (cache->as.ocall.bs_method != NULL) {
-	    Class ocklass = object_getClass(ocrcv);
-	    for (int i = 0; i < (int)cache->as.ocall.bs_method->args_count;
-		    i++) {
-		bs_element_arg_t *arg = &cache->as.ocall.bs_method->args[i];
-		if (arg->sel_of_type != NULL) {
-		    // BridgeSupport tells us that this argument contains a
-		    // selector of the given type, but we don't have any
-		    // information regarding the target. RubyCocoa and the
-		    // other ObjC bridges do not really require it since they
-		    // use the NSObject message forwarding mechanism, but
-		    // MacRuby registers all methods in the runtime.
-		    //
-		    // Therefore, we apply here a naive heuristic by assuming
-		    // that either the receiver or one of the arguments of this
-		    // call is the future target.
-		    const int arg_i = arg->index;
-		    assert(arg_i >= 0 && arg_i < argc);
-		    if (argv[arg_i] != Qnil) {
-			ID arg_selid = rb_to_id(argv[arg_i]);
-			SEL arg_sel = sel_registerName(rb_id2name(arg_selid));
-
-			if (reinstall_method_maybe(ocklass, arg_sel,
-				    arg->sel_of_type)) {
-			    goto sel_target_found;
-			}
-			for (int j = 0; j < argc; j++) {
-			    if (j != arg_i && !SPECIAL_CONST_P(argv[j])) {
-				if (reinstall_method_maybe(*(Class *)argv[j],
-					    arg_sel, arg->sel_of_type)) {
-				    goto sel_target_found;
-				}
-			    }
-			}
-		    }
-
-sel_target_found:
-		    // There can only be one sel_of_type argument.
-		    break; 
-		}
-	    }
-	}
-
-	return __rb_vm_objc_dispatch(cache->as.ocall.stub, cache->as.ocall.imp,
-		ocrcv, sel, argc, argv);
-    }
-    else if (cache->flag & MCACHE_FCALL) {
-#if ROXOR_VM_DEBUG
-	printf("C dispatch %s() imp=%p argc=%d (cached=%s)\n",
-		cache->as.fcall.bs_function->name,
-		cache->as.fcall.imp,
-		argc,
-		cached ? "true" : "false");
-#endif
-	return (*cache->as.fcall.stub)(cache->as.fcall.imp, argc, argv);
-    }
-
-    printf("method dispatch is b0rked\n");
-    abort();
-
-call_method_missing:
-    // Before calling method_missing, let's check if we are not in the following
-    // cases:
-    //
-    //    def foo; end; foo(42)
-    //    def foo(x); end; foo
-    //
-    // If yes, we need to raise an ArgumentError exception instead.
-    const char *selname = sel_getName(sel);
-    const size_t selname_len = strlen(selname);
-    SEL new_sel = 0;
-
-    if (argc > 0 && selname[selname_len - 1] == ':') {
-	char buf[100];
-	assert(sizeof buf > selname_len - 1);
-	strlcpy(buf, selname, sizeof buf);
-	buf[selname_len - 1] = '\0';
-	new_sel = sel_registerName(buf);
-    }
-    else if (argc == 0) {
-	char buf[100];
-	snprintf(buf, sizeof buf, "%s:", selname);
-	new_sel = sel_registerName(buf);
-    }
-    if (new_sel != 0) {
-	Method m = class_getInstanceMethod(klass, new_sel);
-	if (m != NULL) {
-	    IMP mimp = method_getImplementation(m);
-	    if (!UNAVAILABLE_IMP(mimp)) {
-		unsigned expected_argc;
-		rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
-		if (node != NULL) {
-		    expected_argc = node->arity.min;
-		}
-		else {
-		    expected_argc = rb_method_getNumberOfArguments(m);
-		    expected_argc -= 2; // removing receiver and selector
-		}
-		rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-			argc, expected_argc);
-	    }
-	}
-    }
-
-    rb_vm_method_missing_reason_t status;
-    if (opt & DISPATCH_VCALL) {
-	status = METHOD_MISSING_VCALL;
-    }
-    else if (opt & DISPATCH_SUPER) {
-	status = METHOD_MISSING_SUPER;
-    }
-    else {
-	status = METHOD_MISSING_DEFAULT;
-    }
-    return method_missing((VALUE)self, sel, block, argc, argv, status);
-}
-
-static rb_vm_block_t *
-dup_block(rb_vm_block_t *src_b)
-{
-    const size_t block_size = sizeof(rb_vm_block_t)
-	    + (sizeof(VALUE *) * src_b->dvars_size);
-
-    rb_vm_block_t *new_b = (rb_vm_block_t *)xmalloc(block_size);
-
-    memcpy(new_b, src_b, block_size);
-    new_b->proc = src_b->proc; // weak
-    GC_WB(&new_b->parent_block, src_b->parent_block);
-    GC_WB(&new_b->self, src_b->self);
-    new_b->flags = src_b->flags & ~VM_BLOCK_ACTIVE;
-
-    rb_vm_local_t *src_l = src_b->locals;
-    rb_vm_local_t **new_l = &new_b->locals;
-    while (src_l != NULL) {
-	GC_WB(new_l, xmalloc(sizeof(rb_vm_local_t)));
-	(*new_l)->name = src_l->name;
-	(*new_l)->value = src_l->value;
-
-	new_l = &(*new_l)->next;
-	src_l = src_l->next;
-    }
-    *new_l = NULL;
-
-    return new_b;
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_uncache_or_dup_block(rb_vm_block_t *b)
-{
-    return GET_VM()->uncache_or_dup_block(b);
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_dup_block(rb_vm_block_t *b)
-{
-    return dup_block(b);
-}
-
-rb_vm_block_t *
-RoxorVM::uncache_or_dup_block(rb_vm_block_t *b)
-{
-    void *key = (void *)b->imp;
-    std::map<void *, rb_vm_block_t *>::iterator iter = blocks.find(key);
-    if (iter == blocks.end() || iter->second->self != b->self) {
-	if (iter != blocks.end()) {
-	    GC_RELEASE(iter->second);
-	}
-	b = dup_block(b);
-	GC_RETAIN(b);
-	blocks[key] = b;
-    }
-    else {
-	b = iter->second;
-    }
-    return b;
-}
-
-static force_inline VALUE
-vm_block_eval(RoxorVM *vm, rb_vm_block_t *b, SEL sel, VALUE self,
-	int argc, const VALUE *argv)
-{
-    if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
-	// Special case for blocks passed with rb_objc_block_call(), to
-	// preserve API compatibility.
-	VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
-	    (VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
-
-	return (*pimp)(argc == 0 ? Qnil : argv[0], b->userdata, argc, argv);
-    }
-    else if ((b->flags & VM_BLOCK_EMPTY) == VM_BLOCK_EMPTY) {
-	// Trying to call an empty block!
-	return Qnil;
-    }
-
-    rb_vm_arity_t arity = b->arity;    
-
-    if (argc < arity.min || argc > arity.max) {
-	if (arity.max != -1
-		&& (b->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA) {
-	    short limit = (argc < arity.min) ? arity.min : arity.max;
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		    argc, limit);
-	}
-
-	VALUE *new_argv;
-	if (argc == 1 && TYPE(argv[0]) == T_ARRAY
-		&& (arity.min > 1
-		    || (arity.min == 1 && arity.min != arity.max))) {
-	    // Expand the array.
-	    const long ary_len = RARRAY_LEN(argv[0]);
-	    if (ary_len > 0) {
-		new_argv = (VALUE *)RARRAY_PTR(argv[0]);
-	    }
-	    else {
-		new_argv = NULL;
-	    }
-	    argv = new_argv;
-	    argc = ary_len;
-	    if (argc >= arity.min
-		    && (argc <= arity.max || b->arity.max == -1)) {
-		goto block_call;
-	    }
-	}
-
-	int new_argc;
-	if (argc <= arity.min) {
-	    new_argc = arity.min;
-	}
-	else if (argc > arity.max && b->arity.max != -1) {
-	    new_argc = arity.max;
-	}
-	else {
-	    new_argc = argc;
-	}
-
-	if (new_argc > 0) {
-	    new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * new_argc);
-	    for (int i = 0; i < new_argc; i++) {
-		new_argv[i] = i < argc ? argv[i] : Qnil;
-	    }
-	}
-	else {
-	    new_argv = NULL;
-	}
-
-	argc = new_argc;
-	argv = new_argv;
-    }
-#if ROXOR_VM_DEBUG
-    printf("yield block %p argc %d arity %d\n", b, argc, arity.real);
-#endif
-
-block_call:
-
-    if (b->flags & VM_BLOCK_ACTIVE) {
-	b = dup_block(b);
-    }
-    b->flags |= VM_BLOCK_ACTIVE;
-
-    Class old_current_class = vm->get_current_class();
-    vm->set_current_class((Class)b->klass);
-
-    struct Finally {
-	RoxorVM *vm;
-	rb_vm_block_t *b;
-	Class c;
-	Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _c) {
-	    vm = _vm;
-	    b = _b;
-	    c = _c;
-	}
-	~Finally() {
-	    b->flags &= ~VM_BLOCK_ACTIVE;
-	    vm->set_current_class(c);
-	}
-    } finalizer(vm, b, old_current_class);
-
-    if (b->flags & VM_BLOCK_METHOD) {
-	rb_vm_method_t *m = (rb_vm_method_t *)b->imp;
-	return rb_vm_dispatch(vm, (struct mcache *)m->cache, 0, m->recv,
-		(Class)m->oclass, m->sel, NULL, DISPATCH_FCALL, argc, argv);
-    }
-    return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity,
-	    argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
-{
-    return vm_block_eval(GET_VM(), b, NULL, b->self, argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel, int argc,
-	const VALUE *argv)
-{
-    // TODO check given arity and raise exception
-    return vm_block_eval(GET_VM(), b, sel, self, argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_yield_args(void *_vm, int argc, const VALUE *argv)
-{
-    RoxorVM *vm = (RoxorVM *)_vm;
-
-    rb_vm_block_t *b = vm->current_block();
-    if (b == NULL) {
-	rb_raise(rb_eLocalJumpError, "no block given");
-    }
-
-    vm->pop_current_block();
-
-    rb_vm_block_t *top_b = vm->current_block();
-    if (top_b == NULL) {
-	if (vm != RoxorVM::main) {
-	    top_b = GetThreadPtr(vm->get_thread())->body;
-	}
-    }
-    if (top_b != NULL && (top_b->flags & VM_BLOCK_THREAD)) {
-	b->flags |= VM_BLOCK_THREAD;
-    }
-
-    struct Finally {
-	RoxorVM *vm;
-	rb_vm_block_t *b;
-	Finally(RoxorVM *_vm, rb_vm_block_t *_b) { 
-	    vm = _vm;
-	    b = _b;
-	}
-	~Finally() {
-	    vm->add_current_block(b);
-	    if (vm == RoxorVM::main) {
-		b->flags &= ~VM_BLOCK_THREAD;
-	    }
-	}
-    } finalizer(vm, b);
-
-    return vm_block_eval(vm, b, NULL, b->self, argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
-{
-    RoxorVM *vm = GET_VM();
-    rb_vm_block_t *b = vm->current_block();
-    if (b == NULL) {
-	rb_raise(rb_eLocalJumpError, "no block given");
-    }
-
-    vm->pop_current_block();
-
-    VALUE old_self = b->self;
-    b->self = self;
-    VALUE old_class = b->klass;
-    b->klass = klass;
-
-    struct Finally {
-	RoxorVM *vm;
-	rb_vm_block_t *b;
-	VALUE old_class;
-	VALUE old_self;
-	Finally(RoxorVM *_vm, rb_vm_block_t *_b, VALUE _old_class,
-		VALUE _old_self) {
-	    vm = _vm;
-	    b = _b;
-	    old_class = _old_class;
-	    old_self = _old_self;
-	}
-	~Finally() {
-	    b->self = old_self;
-	    b->klass = old_class;
-	    vm->add_current_block(b);
-	}
-    } finalizer(vm, b, old_class, old_self);
-
-    return vm_block_eval(vm, b, NULL, b->self, argc, argv);
-}
-
-force_inline rb_vm_block_t *
-RoxorVM::uncache_or_create_block(void *key, bool *cached, int dvars_size)
-{
-    std::map<void *, rb_vm_block_t *>::iterator iter = blocks.find(key);
-
-    rb_vm_block_t *b;
-    const int create_block_mask =
-	VM_BLOCK_ACTIVE | VM_BLOCK_PROC | VM_BLOCK_IFUNC;
-
-    if ((iter == blocks.end()) || (iter->second->flags & create_block_mask)) {
-	const bool is_ifunc = (iter != blocks.end())
-	    && ((iter->second->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC);
-
-	b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
-		+ (sizeof(VALUE *) * dvars_size));
-	if (!is_ifunc) {
-	    if (iter != blocks.end()) {
-		GC_RELEASE(iter->second);
-	    }
-	    GC_RETAIN(b);
-	    blocks[key] = b;
-	}
-	*cached = false;
-    }
-    else {
-	b = iter->second;
-	*cached = true;
-    }
-
-    return b;
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_prepare_block(void *function, int flags, VALUE self, rb_vm_arity_t arity,
-	rb_vm_var_uses **parent_var_uses, rb_vm_block_t *parent_block,
-	int dvars_size, ...)
-{
-    assert(function != NULL);
-    RoxorVM *vm = GET_VM();
-
-    bool cached = false;
-    rb_vm_block_t *b = vm->uncache_or_create_block(function, &cached,
-	dvars_size);
-
-    bool aot_block = false;
-    if ((flags & VM_BLOCK_AOT) == VM_BLOCK_AOT) {
-	flags ^= VM_BLOCK_AOT;
-	aot_block = true;
-    }
-
-    if (parent_block != NULL && (parent_block->flags & VM_BLOCK_THREAD)) {
-	flags |= VM_BLOCK_THREAD;
-    }
-
-    if (!cached) {
-	if ((flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
-	    b->imp = (IMP)function;
-	}
-	else {
-	    if (aot_block) {
-		b->imp = (IMP)function;
-	    }
-	    else {
-#if MACRUBY_STATIC
-		abort();
-#else
-		GET_CORE()->lock();
-		b->imp = GET_CORE()->compile((Function *)function);
-		GET_CORE()->unlock();
-#endif
-	    }
-	    b->userdata = (VALUE)function;
-	}
-	b->arity = arity;
-	b->flags = flags;
-	b->dvars_size = dvars_size;
-	b->parent_var_uses = NULL;
-	b->parent_block = NULL;
-    }
-    else {
-	assert(b->dvars_size == dvars_size);
-	assert((b->flags & flags) == flags);
-    }
-
-    b->proc = Qnil;
-    GC_WB(&b->self, self);
-    b->klass = (VALUE)vm->get_current_class();
-    b->parent_var_uses = parent_var_uses;
-    GC_WB(&b->parent_block, parent_block);
-
-    va_list ar;
-    va_start(ar, dvars_size);
-    for (int i = 0; i < dvars_size; ++i) {
-	b->dvars[i] = va_arg(ar, VALUE *);
-    }
-    int lvars_size = va_arg(ar, int);
-    if (lvars_size > 0) {
-	if (!cached) {
-	    rb_vm_local_t **l = &b->locals;
-	    for (int i = 0; i < lvars_size; i++) {
-		GC_WB(l, xmalloc(sizeof(rb_vm_local_t)));
-		l = &(*l)->next;
-	    }
-	}
-	rb_vm_local_t *l = b->locals;
-	for (int i = 0; i < lvars_size; ++i) {
-	    assert(l != NULL);
-	    l->name = va_arg(ar, ID);
-	    l->value = va_arg(ar, VALUE *);
-	    l = l->next;
-	}
-    }
-    va_end(ar);
-
-    return b;
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_create_block(IMP imp, VALUE self, VALUE userdata)
-{
-    rb_vm_block_t *b = rb_vm_prepare_block((void *)imp, VM_BLOCK_IFUNC, self,
-	    rb_vm_arity(0), // not used
-	    NULL, NULL, 0, 0);
-    GC_WB(&b->userdata, userdata);
-    return b;
-}
-
-extern "C" void rb_print_undef(VALUE klass, ID id, int scope);
-
-extern "C"
-rb_vm_method_t *
-rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope)
-{
-    SEL sel = 0;
-    IMP imp = NULL;
-    rb_vm_method_node_t *node = NULL;
-
-    // TODO honor scope
-
-    if (!rb_vm_lookup_method2((Class)klass, mid, &sel, &imp, &node)) {
-	rb_print_undef(klass, mid, 0);
-    }
-
-    Class k, oklass = (Class)klass;
-    while ((k = class_getSuperclass(oklass)) != NULL) {
-	if (!rb_vm_lookup_method(k, sel, NULL, NULL)) {
-	    break;
-	}
-	oklass = k;
-    }
-
-    Method method = class_getInstanceMethod((Class)klass, sel);
-    assert(method != NULL);
-
-    int arity;
-    rb_vm_method_node_t *new_node;
-    if (node == NULL) {
-	arity = rb_method_getNumberOfArguments(method) - 2;
-	new_node = NULL;
-    }
-    else {
-	arity = rb_vm_arity_n(node->arity);
-	new_node = (rb_vm_method_node_t *)xmalloc(sizeof(rb_vm_method_node_t));
-	memcpy(new_node, node, sizeof(rb_vm_method_node_t));
-    }
-
-    rb_vm_method_t *m = (rb_vm_method_t *)xmalloc(sizeof(rb_vm_method_t));
-
-    m->oclass = (VALUE)oklass;
-    m->rclass = klass;
-    GC_WB(&m->recv, obj);
-    m->sel = sel;
-    m->arity = arity;
-    GC_WB(&m->node, new_node);
-
-    // Let's allocate a static cache here, since a rb_vm_method_t must always
-    // point to the method it was created from.
-    struct mcache *c = (struct mcache *)xmalloc(sizeof(struct mcache));
-    if (new_node == NULL) {
-	fill_ocache(c, obj, oklass, imp, sel, method, arity);
-    }
-    else {
-	fill_rcache(c, oklass, sel, new_node);
-    }
-    GC_WB(&m->cache, c);
-
-    return m;
-}
-
-extern IMP basic_respond_to_imp; // vm_method.c
-
-bool
-RoxorCore::respond_to(VALUE obj, VALUE klass, SEL sel, bool priv,
-	bool check_override)
-{
-    if (klass == Qnil) {
-	klass = CLASS_OF(obj);
-    }
-    else {
-	assert(!check_override);
-    }
-
-    IMP imp = NULL;
-    const bool overriden = check_override
-	? ((imp = class_getMethodImplementation((Class)klass, selRespondTo))
-		!= basic_respond_to_imp)
-	: false;
-
-    if (!overriden) {
-	lock();
-	const long key = respond_to_key((Class)klass, sel);
-	std::map<long, int>::iterator iter = respond_to_cache.find(key);
-	unlock();
-	int status;
-	if (iter != respond_to_cache.end()) {
-	    status = iter->second;
-	}
-	else {
-	    Method m = class_getInstanceMethod((Class)klass, sel);
-	    if (m == NULL) {
-		const char *selname = sel_getName(sel);
-		sel = helper_sel(selname, strlen(selname));
-		if (sel != NULL) {
-		    m = class_getInstanceMethod((Class)klass, sel);
-		}
-	    }
-
-	    IMP imp = method_getImplementation(m);
-	    if (UNAVAILABLE_IMP(imp) || imp == (IMP)rb_f_notimplement) {
-		status = RESPOND_TO_NOT_EXIST;
-	    }
-	    else {
-		rb_vm_method_node_t *node = method_node_get(m);
-		if (node != NULL && (node->flags & VM_METHOD_PRIVATE)) {
-		    status = RESPOND_TO_PRIVATE;
-		}
-		else {
-		    status = RESPOND_TO_PUBLIC;
-		}
-	    }
-	    lock();
-	    respond_to_cache[key] = status;
-	    unlock();
-	}
-	return status == RESPOND_TO_PUBLIC
-	    || (priv && status == RESPOND_TO_PRIVATE);
-    }
-    else {
-	if (imp == NULL || imp == _objc_msgForward) {
-	    // The class does not respond to respond_to?:, it's probably
-	    // NSProxy-based.
-	    return false;
-	}
-	VALUE args[2];
-	int n = 0;
-	args[n++] = ID2SYM(rb_intern(sel_getName(sel)));
-	if (priv) {
-	    rb_vm_method_node_t *node = method_node_get(imp);
-	    if (node != NULL
-		    && (2 < node->arity.min
-			|| (node->arity.max != -1 && 2 > node->arity.max))) {
-		// Do nothing, custom respond_to? method incompatible arity.
-	    }
-	    else {
-		args[n++] = Qtrue;
-	    }
-	}
-	return rb_vm_call(obj, selRespondTo, n, args) == Qtrue;
-    }
-}
-
-static bool
-respond_to(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override)
-{
-    return GET_CORE()->respond_to(obj, klass, sel, priv, check_override);
-}
-
-extern "C"
-bool
-rb_vm_respond_to(VALUE obj, SEL sel, bool priv)
-{
-    return respond_to(obj, Qnil, sel, priv, true);
-}
-
-extern "C"
-bool
-rb_vm_respond_to2(VALUE obj, VALUE klass, SEL sel, bool priv,
-	bool check_override)
-{
-    return respond_to(obj, klass, sel, priv, check_override);
-}
-
-// Note: rb_call_super() MUST always be called from methods registered using
-// the MRI API (such as rb_define_method() & friends). It must NEVER be used
-// internally inside MacRuby core.
-extern "C"
-VALUE
-rb_call_super(int argc, const VALUE *argv)
-{
-    RoxorVM *vm = GET_VM();
-    VALUE self = vm->get_current_mri_method_self();
-    SEL sel = vm->get_current_mri_method_sel();
-    assert(self != 0 && sel != 0);
-
-    return rb_vm_call_super(self, sel, argc, argv);
-}
-
-extern "C"
-void
-rb_vm_set_current_mri_method_context(VALUE self, SEL sel)
-{
-    RoxorVM *vm = GET_VM();
-    vm->set_current_mri_method_self(self);
-    vm->set_current_mri_method_sel(sel);
-} 

Deleted: MacRuby/trunk/distruby.rb
===================================================================
--- MacRuby/trunk/distruby.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/distruby.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,59 +0,0 @@
-#!./miniruby
-
-if RUBY_PATCHLEVEL.zero?
-	dirname = sprintf 'ruby-%s', RUBY_VERSION
-	tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)/, 'v\1_\2_\3'
-else
-	dirname = sprintf 'ruby-%s-p%u', RUBY_VERSION, RUBY_PATCHLEVEL
-	tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)-p/, 'v\1_\2_\3_'
-end
-tgzname = dirname + '.tar.gz'
-tbzname = dirname + '.tar.bz2'
-zipname = dirname + '.zip'
-repos   = 'http://svn.ruby-lang.org/repos/ruby/tags/' + tagname
-
-STDERR.puts 'exporting sources...'
-system 'svn',  'export',  '-q', repos, dirname
-Dir.chdir dirname do
-	STDERR.puts 'generating configure...'
-	system 'autoconf'
-	system 'rm', '-rf', 'autom4te.cache'
-
-	STDERR.puts 'generating parse.c...'
-	system 'bison', '-y', '-o', 'parse.c', 'parse.y'
-end
-
-STDERR.puts 'generating tarballs...'
-ENV['GZIP'] = '-9'
-system 'tar', 'chofzp', tgzname, dirname
-system 'tar', 'chojfp', tbzname, dirname
-system 'zip', '-q9r', zipname, dirname
-
-require 'digest/md5'
-require 'digest/sha2'
-for name in [tgzname, tbzname, zipname] do
-	open name, 'rb' do |fp|
-		str = fp.read
-		md5 = Digest::MD5.hexdigest str
-		sha = Digest::SHA256.hexdigest str
-		printf "MD5(%s)= %s\nSHA256(%s)= %s\nSIZE(%s)= %s\n\n",
-				 name, md5,
-				 name, sha,
-				 name, str.size
-	end
-end
-
-
-
-# 
-# Local Variables:
-# mode: ruby
-# code: utf-8
-# indent-tabs-mode: t
-# tab-width: 3
-# ruby-indent-level: 3
-# fill-column: 79
-# default-justification: full
-# End:
-# vi: ts=3 sw=3
-

Deleted: MacRuby/trunk/dln.c
===================================================================
--- MacRuby/trunk/dln.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dln.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,277 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "dln.h"
-
-#include <stdlib.h>
-#include <alloca.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <unistd.h>
-
-#define FUNCNAME_PATTERN "Init_%s"
-
-// In file.c
-int eaccess(const char *path, int mode);
-
-static int
-init_funcname_len(char **buf, const char *file)
-{
-    char *p;
-    const char *slash;
-    int len;
-
-    /* Load the file as an object one */
-    for (slash = file-1; *file; file++) /* Find position of last '/' */
-	if (*file == '/') slash = file;
-
-    len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
-    *buf = xmalloc(len);
-    snprintf(*buf, len, FUNCNAME_PATTERN, slash + 1);
-    for (p = *buf; *p; p++) {         /* Delete suffix if it exists */
-	if (*p == '-') {
-	    *p = '_';
-	}
-    }
-    for (p = *buf; *p; p++) {         /* Delete suffix if it exists */
-	if (*p == '.') {
-	    *p = '\0';
-	    break;
-	}
-    }
-    return p - *buf;
-}
-
-#define init_funcname(buf, file) do {\
-    int len = init_funcname_len(buf, file);\
-    char *tmp = ALLOCA_N(char, len+1);\
-    if (tmp == NULL) {\
-	xfree(*buf);\
-	rb_memerror();\
-    }\
-    strcpy(tmp, *buf);\
-    xfree(*buf);\
-    *buf = tmp;\
-} while (0)
-
-#include <dlfcn.h>
-#include <mach-o/dyld.h>
-
-static const char *
-dln_strerror(void)
-{
-    return (char*)dlerror();
-}
-
-bool ruby_is_miniruby = false;
-
-// This function is called back from .rbo files' gcc constructors, passing a
-// pointer to their entry point function, during dlopen(). The entry point
-// function is called right after dlopen() directly. This is because C++
-// exceptions raised within a gcc constructor are not properly propagated.
-static void *__mrep__ = NULL;
-void
-rb_mrep_register(void *imp)
-{
-    __mrep__ = imp;
-}
-
-void*
-dln_load(const char *file, bool call_init)
-{
-    if (ruby_is_miniruby) {
-	rb_raise(rb_eLoadError,
-		"miniruby can't load C extension bundles due to technical problems");
-    }
-
-    const char *error = 0;
-#define DLN_ERROR() (error = dln_strerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
-
-    char *buf;
-    /* Load the file as an object one */
-    init_funcname(&buf, file);
-
-    {
-	void *handle;
-
-	/* Load file */
-	__mrep__ = NULL;
-	if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
-	    error = dln_strerror();
-	    goto failed;
-	}
-
-	if (call_init) {
-	    void (*init_fct)();
-	    init_fct = (void(*)())dlsym(handle, buf);
-	    if (init_fct == NULL) {
-		error = DLN_ERROR();
-		dlclose(handle);
-		goto failed;
-	    }
-	    /* Call the init code */
-	    (*init_fct)();
-	}
-	else {
-	    if (__mrep__ == NULL) {
-		rb_raise(rb_eLoadError, "Can't load %s: entry point function not located (this can happen when you load twice the same .rbo file with a different case on a case-insensitive filesystem)", file);
-	    }
-	    ((IMP)__mrep__)((id)rb_vm_top_self(), 0);
-	}
-
-	return handle;
-    }
-
-  failed:
-    rb_loaderror("%s - %s", error, file);
-
-    return 0;			/* dummy return */
-}
-
-static char *dln_find_1(const char *fname, const char *path, char *buf, int size, int exe_flag);
-
-char *
-dln_find_exe_r(const char *fname, const char *path, char *buf, int size)
-{
-    if (path == NULL) {
-	path = getenv(PATH_ENV);
-    }
-
-    if (path == NULL) {
-	path = "/usr/local/bin:/usr/bin:/bin:.";
-    }
-    return dln_find_1(fname, path, buf, size, 1);
-}
-
-char *
-dln_find_file_r(const char *fname, const char *path, char *buf, int size)
-{
-    if (path == NULL) {
-	path = ".";
-    }
-    return dln_find_1(fname, path, buf, size, 0);
-}
-
-static char fbuf[MAXPATHLEN];
-
-char *
-dln_find_exe(const char *fname, const char *path)
-{
-    return dln_find_exe_r(fname, path, fbuf, sizeof(fbuf));
-}
-
-char *
-dln_find_file(const char *fname, const char *path)
-{
-    return dln_find_file_r(fname, path, fbuf, sizeof(fbuf));
-}
-
-static char *
-dln_find_1(const char *fname, const char *path, char *fbuf, int size,
-	   int exe_flag /* non 0 if looking for executable. */)
-{
-    register const char *dp;
-    register const char *ep;
-    register char *bp;
-    struct stat st;
-
-#define RETURN_IF(expr) if (expr) return (char *)fname;
-
-    RETURN_IF(!fname);
-    RETURN_IF(fname[0] == '/');
-    RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
-    RETURN_IF(exe_flag && strchr(fname, '/'));
-
-#undef RETURN_IF
-
-    for (dp = path;; dp = ++ep) {
-	register int l;
-	int i;
-	int fspace;
-
-	/* extract a component */
-	ep = strchr(dp, PATH_SEP[0]);
-	if (ep == NULL) {
-	    ep = dp+strlen(dp);
-	}
-
-	/* find the length of that component */
-	l = ep - dp;
-	bp = fbuf;
-	fspace = size - 2;
-	if (l > 0) {
-	    /*
-	    **	If the length of the component is zero length,
-	    **	start from the current directory.  If the
-	    **	component begins with "~", start from the
-	    **	user's $HOME environment variable.  Otherwise
-	    **	take the path literally.
-	    */
-
-	    if (*dp == '~' && (l == 1 || dp[1] == '/')) {
-		char *home;
-
-		home = getenv("HOME");
-		if (home != NULL) {
-		    i = strlen(home);
-		    if ((fspace -= i) < 0) {
-			goto toolong;
-		    }
-		    memcpy(bp, home, i);
-		    bp += i;
-		}
-		dp++;
-		l--;
-	    }
-	    if (l > 0) {
-		if ((fspace -= l) < 0) {
-		    goto toolong;
-		}
-		memcpy(bp, dp, l);
-		bp += l;
-	    }
-
-	    /* add a "/" between directory and filename */
-	    if (ep[-1] != '/') {
-		*bp++ = '/';
-	    }
-	}
-
-	/* now append the file name */
-	i = strlen(fname);
-	if ((fspace -= i) < 0) {
-	  toolong:
-	    fprintf(stderr, "openpath: pathname too long (ignored)\n");
-	    *bp = '\0';
-	    fprintf(stderr, "\tDirectory \"%s\"\n", fbuf);
-	    fprintf(stderr, "\tFile \"%s\"\n", fname);
-	    goto next;
-	}
-	memcpy(bp, fname, i + 1);
-
-	if (stat(fbuf, &st) == 0) {
-	    if (!S_ISDIR(st.st_mode)
-		    && (exe_flag == 0 || eaccess(fbuf, X_OK) == 0)) {
-		return fbuf;
-	    }
-	}
-
-      next:
-	/* if not, and no other alternatives, life is bleak */
-	if (*ep == '\0') {
-	    return NULL;
-	}
-
-	/* otherwise try the next component in the search path */
-    }
-}

Deleted: MacRuby/trunk/dln.h
===================================================================
--- MacRuby/trunk/dln.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dln.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,41 +0,0 @@
-/**********************************************************************
-
-  dln.h -
-
-  $Author: nobu $
-  created at: Wed Jan 19 16:53:09 JST 1994
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef DLN_H
-#define DLN_H
-
-#ifdef __cplusplus
-# ifndef  HAVE_PROTOTYPES
-#  define HAVE_PROTOTYPES 1
-# endif
-# ifndef  HAVE_STDARG_PROTOTYPES
-#  define HAVE_STDARG_PROTOTYPES 1
-# endif
-#endif
-
-#undef _
-#ifdef HAVE_PROTOTYPES
-# define _(args) args
-#else
-# define _(args) ()
-#endif
-
-char *dln_find_exe(const char*,const char*);
-char *dln_find_file(const char*,const char*);
-char *dln_find_exe_r(const char*,const char*,char*,int);
-char *dln_find_file_r(const char*,const char*,char*,int);
-
-#ifdef USE_DLN_A_OUT
-extern char *dln_argv0;
-#endif
-
-void *dln_load(const char*, bool);
-#endif

Deleted: MacRuby/trunk/dmydln.c
===================================================================
--- MacRuby/trunk/dmydln.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dmydln.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2 +0,0 @@
-#define NO_DLN_LOAD 1
-#include "dln.c"

Deleted: MacRuby/trunk/dmyencoding.c
===================================================================
--- MacRuby/trunk/dmyencoding.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dmyencoding.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2 +0,0 @@
-#define NO_LOCALE_CHARMAP 1
-#include "encoding.c"

Deleted: MacRuby/trunk/dmyext.c
===================================================================
--- MacRuby/trunk/dmyext.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dmyext.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,4 +0,0 @@
-void
-Init_ext(void)
-{
-}

Deleted: MacRuby/trunk/dmytranscode.c
===================================================================
Deleted: MacRuby/trunk/dtrace.d
===================================================================
--- MacRuby/trunk/dtrace.d	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/dtrace.d	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,6 +0,0 @@
-provider macruby {
-    probe method__entry(char *classname, char *methodname, char *sourcefile, int sourceline);
-    probe method__return(char *classname, char *methodname, char *sourcefile, int sourceline);
-    probe raise(char *classname, char *sourcefile, int sourceline);
-    probe rescue(char *sourcefile, int sourceline);
-};

Deleted: MacRuby/trunk/encoding.c
===================================================================
--- MacRuby/trunk/encoding.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/encoding.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,579 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9 String.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include <string.h>
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "symbol.h"
-
-VALUE rb_cEncoding;
-
-rb_encoding_t *default_internal = NULL;
-static rb_encoding_t *default_external = NULL;
-rb_encoding_t *rb_encodings[ENCODINGS_COUNT];
-
-static VALUE
-mr_enc_s_list(VALUE klass, SEL sel)
-{
-    VALUE ary = rb_ary_new2(ENCODINGS_COUNT);
-    for (unsigned int i = 0; i < ENCODINGS_COUNT; ++i) {
-	rb_ary_push(ary, (VALUE)rb_encodings[i]);
-    }
-    return ary;
-}
-
-static VALUE
-mr_enc_s_name_list(VALUE klass, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    for (unsigned int i = 0; i < ENCODINGS_COUNT; ++i) {
-	rb_encoding_t *encoding = RENC(rb_encodings[i]);
-	// TODO: use US-ASCII strings
-	rb_ary_push(ary, rb_usascii_str_new2(encoding->public_name));
-	for (unsigned int j = 0; j < encoding->aliases_count; ++j) {
-	    rb_ary_push(ary, rb_usascii_str_new2(encoding->aliases[j]));
-	}
-    }
-    return ary;
-}
-
-static VALUE
-mr_enc_s_aliases(VALUE klass, SEL sel)
-{
-    VALUE hash = rb_hash_new();
-    for (unsigned int i = 0; i < ENCODINGS_COUNT; ++i) {
-	rb_encoding_t *encoding = RENC(rb_encodings[i]);
-	for (unsigned int j = 0; j < encoding->aliases_count; ++j) {
-	    rb_hash_aset(hash, rb_usascii_str_new2(encoding->aliases[j]),
-		    rb_usascii_str_new2(encoding->public_name));
-	}
-    }
-    return hash;
-}
-
-static VALUE
-mr_enc_s_find(VALUE klass, SEL sel, VALUE name)
-{
-    StringValue(name);
-    rb_encoding_t *enc = rb_enc_find(RSTRING_PTR(name));
-    if (enc == NULL) {
-	rb_raise(rb_eArgError, "unknown encoding name - %s",
-		RSTRING_PTR(name));
-    }
-    return (VALUE)enc;
-}
-
-static VALUE
-mr_enc_s_default_internal(VALUE klass, SEL sel)
-{
-    return (VALUE)default_internal;
-}
-
-static VALUE
-mr_enc_set_default_internal(VALUE klass, SEL sel, VALUE enc)
-{
-    default_internal = rb_to_encoding(enc);
-    return (VALUE)default_internal;
-}
-
-static VALUE
-mr_enc_s_default_external(VALUE klass, SEL sel)
-{
-    return (VALUE)default_external;
-}
-
-static VALUE
-mr_enc_set_default_external(VALUE klass, SEL sel, VALUE enc)
-{
-    default_external = rb_to_encoding(enc);
-    return (VALUE)default_external;
-}
-
-static VALUE
-mr_enc_name(VALUE self, SEL sel)
-{
-    return rb_usascii_str_new2(RENC(self)->public_name);
-}
-
-static VALUE
-mr_enc_inspect(VALUE self, SEL sel)
-{
-    return rb_sprintf("#<%s:%s>", rb_obj_classname(self),
-	    RENC(self)->public_name);
-}
-
-static VALUE
-mr_enc_names(VALUE self, SEL sel)
-{
-    rb_encoding_t *encoding = RENC(self);
-
-    VALUE ary = rb_ary_new2(encoding->aliases_count + 1);
-    rb_ary_push(ary, rb_usascii_str_new2(encoding->public_name));
-    for (unsigned int i = 0; i < encoding->aliases_count; ++i) {
-	rb_ary_push(ary, rb_usascii_str_new2(encoding->aliases[i]));
-    }
-    return ary;
-}
-
-static VALUE
-mr_enc_ascii_compatible_p(VALUE self, SEL sel)
-{
-    return RENC(self)->ascii_compatible ? Qtrue : Qfalse;
-}
-
-static VALUE
-mr_enc_dummy_p(VALUE self, SEL sel)
-{
-    return Qfalse;
-}
-
-// For UTF-[8, 16, 32] it's /uFFFD, and for others it's '?'
-rb_str_t *replacement_string_for_encoding(rb_encoding_t* destination)
-{
-    rb_str_t *replacement_str = NULL;
-    if (destination == rb_encodings[ENCODING_UTF16BE]) {
-        replacement_str = RSTR(rb_enc_str_new("\xFF\xFD", 2, destination));
-    }
-    else if (destination == rb_encodings[ENCODING_UTF32BE]) {
-        replacement_str = RSTR(rb_enc_str_new("\0\0\xFF\xFD", 4, destination));
-    }
-    else if (destination == rb_encodings[ENCODING_UTF16LE]) {
-        replacement_str = RSTR(rb_enc_str_new("\xFD\xFF", 2, destination));
-    }
-    else if (destination == rb_encodings[ENCODING_UTF32LE]) {
-        replacement_str = RSTR(rb_enc_str_new("\xFD\xFF\0\0", 4, destination));
-    }
-    else if (destination == rb_encodings[ENCODING_UTF8]) {
-        replacement_str = RSTR(rb_enc_str_new("\xEF\xBF\xBD", 3, destination));
-    }
-    else {
-        replacement_str = RSTR(rb_enc_str_new("?", 1, rb_encodings[ENCODING_ASCII]));
-        replacement_str = str_simple_transcode(replacement_str, destination);
-    }
-    return replacement_str;
-}
-
-static void
-define_encoding_constant(const char *name, rb_encoding_t *encoding)
-{
-    char c = name[0];
-    if ((c >= '0') && (c <= '9')) {
-	// constants can't start with a number
-	return;
-    }
-
-    if (strcmp(name, "locale") == 0) {
-	// there is no constant for locale
-	return;
-    }
-
-    char *name_copy = strdup(name);
-    if ((c >= 'a') && (c <= 'z')) {
-	// the first character must be upper case
-	name_copy[0] = c - ('a' - 'A');
-    }
-
-    bool has_lower_case = false;
-    // '.' and '-' must be transformed into '_'
-    for (int i = 0; name_copy[i]; ++i) {
-	if ((name_copy[i] == '.') || (name_copy[i] == '-')) {
-	    name_copy[i] = '_';
-	}
-	else if ((name_copy[i] >= 'a') && (name_copy[i] <= 'z')) {
-	    has_lower_case = true;
-	}
-    }
-    rb_define_const(rb_cEncoding, name_copy, (VALUE)encoding);
-    // if the encoding name has lower case characters,
-    // also define it in upper case
-    if (has_lower_case) {
-	for (int i = 0; name_copy[i]; ++i) {
-	    if ((name_copy[i] >= 'a') && (name_copy[i] <= 'z')) {
-		name_copy[i] = name_copy[i] - 'a' + 'A';
-	    }
-	}
-	rb_define_const(rb_cEncoding, name_copy, (VALUE)encoding);
-    }
-
-    free(name_copy);
-}
-
-extern void enc_init_ucnv_encoding(rb_encoding_t *encoding);
-
-enum {
-    ENCODING_TYPE_SPECIAL = 0,
-    ENCODING_TYPE_UCNV
-};
-
-static void
-add_encoding(
-	unsigned int encoding_index, // index of the encoding in the encodings
-				     // array
-	unsigned int rb_encoding_type,
-	const char *public_name, // public name for the encoding
-	unsigned char min_char_size,
-	bool single_byte_encoding, // in the encoding a character takes only
-				   // one byte
-	bool ascii_compatible, // is the encoding ASCII compatible or not
-	bool little_endian, // for UTF-16/32, if the encoding is little endian
-	... // aliases for the encoding (should no include the public name)
-	    // - must end with a NULL
-	)
-{
-    assert(encoding_index < ENCODINGS_COUNT);
-
-    // create an array for the aliases
-    unsigned int aliases_count = 0;
-    va_list va_aliases;
-    va_start(va_aliases, little_endian);
-    while (va_arg(va_aliases, const char *) != NULL) {
-	++aliases_count;
-    }
-    va_end(va_aliases);
-    const char **aliases = (const char **)
-	malloc(sizeof(const char *) * aliases_count);
-    va_start(va_aliases, little_endian);
-    for (unsigned int i = 0; i < aliases_count; ++i) {
-	aliases[i] = va_arg(va_aliases, const char *);
-    }
-    va_end(va_aliases);
-
-    // create the MacRuby object
-    NEWOBJ(encoding, rb_encoding_t);
-    encoding->basic.flags = 0;
-    encoding->basic.klass = rb_cEncoding;
-    rb_encodings[encoding_index] = encoding;
-    GC_RETAIN(encoding); // it should never be deallocated
-
-    // fill the fields
-    encoding->index = encoding_index;
-    encoding->public_name = public_name;
-    encoding->min_char_size = min_char_size;
-    encoding->single_byte_encoding = single_byte_encoding;
-    encoding->ascii_compatible = ascii_compatible;
-    encoding->little_endian = little_endian;
-    encoding->aliases_count = aliases_count;
-    encoding->aliases = aliases;
-
-    switch (rb_encoding_type) {
-	case ENCODING_TYPE_SPECIAL:
-	    break;
-	case ENCODING_TYPE_UCNV:
-	    enc_init_ucnv_encoding(encoding);
-	    break;
-	default:
-	    abort();
-    }
-}
-
-// This Init function is called very early. Do not use any runtime method
-// because things may not be initialized properly yet.
-void
-Init_PreEncoding(void)
-{
-    add_encoding(ENCODING_BINARY,      ENCODING_TYPE_SPECIAL, "ASCII-8BIT",  1, true,  true,  false, "BINARY", NULL);
-    add_encoding(ENCODING_ASCII,       ENCODING_TYPE_UCNV,    "US-ASCII",    1, true,  true,  false, "ASCII", "ANSI_X3.4-1968", "646", NULL);
-    add_encoding(ENCODING_UTF8,        ENCODING_TYPE_UCNV,    "UTF-8",       1, false, true,  false, "CP65001", "locale", NULL);
-    add_encoding(ENCODING_UTF16BE,     ENCODING_TYPE_UCNV,    "UTF-16BE",    2, false, false, false, NULL);
-    add_encoding(ENCODING_UTF16LE,     ENCODING_TYPE_UCNV,    "UTF-16LE",    2, false, false, true,  NULL);
-    add_encoding(ENCODING_UTF32BE,     ENCODING_TYPE_UCNV,    "UTF-32BE",    4, false, false, false, "UCS-4BE", NULL);
-    add_encoding(ENCODING_UTF32LE,     ENCODING_TYPE_UCNV,    "UTF-32LE",    4, false, false, true,  "UCS-4LE", NULL);
-    add_encoding(ENCODING_ISO8859_1,   ENCODING_TYPE_UCNV,    "ISO-8859-1",  1, true,  true,  false, "ISO8859-1", NULL);
-    add_encoding(ENCODING_ISO8859_2,   ENCODING_TYPE_UCNV,    "ISO-8859-2",  1, true,  true,  false, "ISO8859-2", NULL);
-    add_encoding(ENCODING_ISO8859_3,   ENCODING_TYPE_UCNV,    "ISO-8859-3",  1, true,  true,  false, "ISO8859-3", NULL);
-    add_encoding(ENCODING_ISO8859_4,   ENCODING_TYPE_UCNV,    "ISO-8859-4",  1, true,  true,  false, "ISO8859-4", NULL);
-    add_encoding(ENCODING_ISO8859_5,   ENCODING_TYPE_UCNV,    "ISO-8859-5",  1, true,  true,  false, "ISO8859-5", NULL);
-    add_encoding(ENCODING_ISO8859_6,   ENCODING_TYPE_UCNV,    "ISO-8859-6",  1, true,  true,  false, "ISO8859-6", NULL);
-    add_encoding(ENCODING_ISO8859_7,   ENCODING_TYPE_UCNV,    "ISO-8859-7",  1, true,  true,  false, "ISO8859-7", NULL);
-    add_encoding(ENCODING_ISO8859_8,   ENCODING_TYPE_UCNV,    "ISO-8859-8",  1, true,  true,  false, "ISO8859-8", NULL);
-    add_encoding(ENCODING_ISO8859_9,   ENCODING_TYPE_UCNV,    "ISO-8859-9",  1, true,  true,  false, "ISO8859-9", NULL);
-    add_encoding(ENCODING_ISO8859_10,  ENCODING_TYPE_UCNV,    "ISO-8859-10", 1, true,  true,  false, "ISO8859-10", NULL);
-    add_encoding(ENCODING_ISO8859_11,  ENCODING_TYPE_UCNV,    "ISO-8859-11", 1, true,  true,  false, "ISO8859-11", NULL);
-    add_encoding(ENCODING_ISO8859_13,  ENCODING_TYPE_UCNV,    "ISO-8859-13", 1, true,  true,  false, "ISO8859-13", NULL);
-    add_encoding(ENCODING_ISO8859_14,  ENCODING_TYPE_UCNV,    "ISO-8859-14", 1, true,  true,  false, "ISO8859-14", NULL);
-    add_encoding(ENCODING_ISO8859_15,  ENCODING_TYPE_UCNV,    "ISO-8859-15", 1, true,  true,  false, "ISO8859-15", NULL);
-    add_encoding(ENCODING_ISO8859_16,  ENCODING_TYPE_UCNV,    "ISO-8859-16", 1, true,  true,  false, "ISO8859-16", NULL);
-    add_encoding(ENCODING_MACROMAN,    ENCODING_TYPE_UCNV,    "macRoman",    1, true,  true,  false, NULL);
-    add_encoding(ENCODING_MACCYRILLIC, ENCODING_TYPE_UCNV,    "macCyrillic", 1, true,  true,  false, NULL);
-    add_encoding(ENCODING_BIG5,        ENCODING_TYPE_UCNV,    "Big5",        1, false, true,  false, "CP950", NULL);
-    // FIXME: the ICU conversion tables do not seem to match Ruby's Japanese conversion tables
-    add_encoding(ENCODING_EUCJP,       ENCODING_TYPE_UCNV,    "EUC-JP",      1, false, true,  false, "eucJP", NULL);
-    add_encoding(ENCODING_SJIS,        ENCODING_TYPE_UCNV,    "Shift_JIS",   1, false, true,  false, "SJIS", NULL);
-    //add_encoding(ENCODING_EUCJP,     ENCODING_TYPE_RUBY, "EUC-JP",      1, false, true,  "eucJP", NULL);
-    //add_encoding(ENCODING_SJIS,      ENCODING_TYPE_RUBY, "Shift_JIS",   1, false, true, "SJIS", NULL);
-    //add_encoding(ENCODING_CP932,     ENCODING_TYPE_RUBY, "Windows-31J", 1, false, true, "CP932", "csWindows31J", NULL);
-
-    default_external = rb_encodings[ENCODING_UTF8];
-    default_internal = rb_encodings[ENCODING_UTF8];
-}
-
-void
-Init_Encoding(void)
-{
-    // rb_cEncoding is defined earlier in Init_PreVM().
-    rb_set_class_path(rb_cEncoding, rb_cObject, "Encoding");
-    rb_const_set(rb_cObject, rb_intern("Encoding"), rb_cEncoding);
-
-    rb_undef_alloc_func(rb_cEncoding);
-
-    rb_objc_define_method(rb_cEncoding, "to_s", mr_enc_name, 0);
-    rb_objc_define_method(rb_cEncoding, "inspect", mr_enc_inspect, 0);
-    rb_objc_define_method(rb_cEncoding, "name", mr_enc_name, 0);
-    rb_objc_define_method(rb_cEncoding, "names", mr_enc_names, 0);
-    rb_objc_define_method(rb_cEncoding, "dummy?", mr_enc_dummy_p, 0);
-    rb_objc_define_method(rb_cEncoding, "ascii_compatible?",
-	    mr_enc_ascii_compatible_p, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "list", mr_enc_s_list, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "name_list",
-	    mr_enc_s_name_list, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "aliases",
-	    mr_enc_s_aliases, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "find", mr_enc_s_find, 1);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "compatible?",
-	    mr_enc_s_is_compatible, 2); // in string.c
-
-    //rb_define_method(rb_cEncoding, "_dump", enc_dump, -1);
-    //rb_define_singleton_method(rb_cEncoding, "_load", enc_load, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "default_external",
-	    mr_enc_s_default_external, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "default_external=",
-	    mr_enc_set_default_external, 1);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "default_internal",
-	    mr_enc_s_default_internal, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncoding, "default_internal=",
-	    mr_enc_set_default_internal, 1);
-    //rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0);
-
-    // Create constants.
-    for (unsigned int i = 0; i < ENCODINGS_COUNT; i++) {
-	rb_encoding_t *enc = rb_encodings[i];
-	define_encoding_constant(enc->public_name, enc);
-	for (unsigned int j = 0; j < enc->aliases_count; j++) {
-	    define_encoding_constant(enc->aliases[j], enc);
-	}
-    }
-}
-
-// MRI C-API compatibility.
-
-rb_encoding_t *
-rb_enc_find(const char *name)
-{
-    for (unsigned int i = 0; i < ENCODINGS_COUNT; i++) {
-	rb_encoding_t *enc = rb_encodings[i];
-	if (strcasecmp(enc->public_name, name) == 0) {
-	    return enc;
-	}
-	for (unsigned int j = 0; j < enc->aliases_count; j++) {
-	    const char *alias = enc->aliases[j];
-	    if (strcasecmp(alias, name) == 0) {
-		return enc;
-	    }
-	}
-    }
-    return NULL;
-}
-
-VALUE
-rb_enc_from_encoding(rb_encoding_t *enc)
-{
-    return (VALUE)enc;
-}
-
-rb_encoding_t *
-rb_enc_get(VALUE obj)
-{
-    switch (TYPE(obj)) {
-	case T_STRING:
-	    if (IS_RSTR(obj)) {
-		return RSTR(obj)->encoding;
-	    }
-	    return rb_encodings[ENCODING_UTF8];
-
-	case T_SYMBOL:
-	    return rb_enc_get(rb_sym_str(obj));
-    }
-    return NULL;
-}
-
-rb_encoding_t *
-rb_to_encoding(VALUE obj)
-{
-    rb_encoding_t *enc;
-    if (CLASS_OF(obj) == rb_cEncoding) {
-	enc = RENC(obj);
-    }
-    else {
-	StringValue(obj);
-	enc = rb_enc_find(RSTRING_PTR(obj));
-	if (enc == NULL) {
-	    rb_raise(rb_eArgError, "unknown encoding name - %s",
-		    RSTRING_PTR(obj));
-	}
-    }
-    return enc;
-}
-
-const char *
-rb_enc_name(rb_encoding_t *enc)
-{
-    return RENC(enc)->public_name;
-}
-
-VALUE
-rb_enc_name2(rb_encoding_t *enc)
-{
-    return rb_usascii_str_new2(rb_enc_name(enc));
-}
-
-long
-rb_enc_mbminlen(rb_encoding_t *enc)
-{
-    return enc->min_char_size;    
-}
-
-long
-rb_enc_mbmaxlen(rb_encoding_t *enc)
-{
-    return enc->single_byte_encoding ? 1 : 10; // XXX 10?
-}
-
-rb_encoding *
-rb_ascii8bit_encoding(void)
-{
-    return rb_encodings[ENCODING_BINARY];
-}
-
-rb_encoding *
-rb_utf8_encoding(void)
-{
-    return rb_encodings[ENCODING_UTF8];
-}
-
-rb_encoding *
-rb_usascii_encoding(void)
-{
-    return rb_encodings[ENCODING_ASCII];
-}
-
-rb_encoding_t *
-rb_locale_encoding(void)
-{
-    // XXX
-    return rb_encodings[ENCODING_UTF8];
-}
-
-void
-rb_enc_set_default_external(VALUE encoding)
-{
-    assert(CLASS_OF(encoding) == rb_cEncoding);
-    default_external = RENC(encoding); 
-}
-
-rb_encoding *
-rb_default_internal_encoding(void)
-{
-    return (rb_encoding *)default_internal;
-}
-
-static int
-index_of_encoding(rb_encoding_t *enc)
-{
-    if (enc != NULL) {
-	for (int i = 0; i <ENCODINGS_COUNT; i++) {
-	    if (rb_encodings[i] == enc) {
-		return i;
-	    }
-	}
-    }
-    return -1;
-}
-
-int
-rb_enc_get_index(VALUE obj)
-{
-    return index_of_encoding(rb_enc_get(obj));
-}
-
-void
-rb_enc_set_index(VALUE obj, int encindex)
-{
-    if (encindex < ENCODINGS_COUNT) {
-	return ;
-    }
-    rb_str_force_encoding(obj, rb_encodings[encindex]);
-}
-
-int
-rb_to_encoding_index(VALUE enc)
-{
-    if (CLASS_OF(enc) != rb_cEncoding && TYPE(enc) != T_STRING) {
-        return -1;
-    }
-    else {
-        int idx = index_of_encoding((rb_encoding_t *)enc);
-        if (idx >= 0) {
-            return idx;
-        }
-        else if (NIL_P(enc = rb_check_string_type(enc))) {
-            return -1;
-        }
-        if (!rb_enc_asciicompat(rb_enc_get(enc))) {
-            return -1;
-        }
-        return rb_enc_find_index(StringValueCStr(enc));
-    }
-}
-
-int
-rb_enc_find_index(const char *name)
-{
-    return index_of_encoding(rb_enc_find(name));
-}
-
-int
-rb_ascii8bit_encindex(void)
-{
-    return index_of_encoding(rb_encodings[ENCODING_BINARY]);
-}
-
-int
-rb_utf8_encindex(void)
-{
-    return index_of_encoding(rb_encodings[ENCODING_UTF8]);
-}
-
-int
-rb_usascii_encindex(void)
-{
-    return index_of_encoding(rb_encodings[ENCODING_ASCII]);
-}
-
-rb_encoding *
-rb_enc_from_index(int idx)
-{
-    assert(idx >= 0 && idx < ENCODINGS_COUNT);
-    return rb_encodings[idx];
-}
-
-VALUE
-rb_enc_associate_index(VALUE obj, int idx)
-{
-    if (TYPE(obj) == T_STRING) {
-	assert(idx >= 0 && idx < ENCODINGS_COUNT);
-	rb_str_force_encoding(obj, rb_encodings[idx]);
-	return obj;
-    }
-    rb_raise(rb_eArgError, "cannot set encoding on non-string object");
-}

Deleted: MacRuby/trunk/encoding.h
===================================================================
--- MacRuby/trunk/encoding.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/encoding.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,388 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9 String.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#ifndef __ENCODING_H_
-#define __ENCODING_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if defined(__cplusplus)
-# include "unicode/unistr.h"
-#else
-# include "unicode/ustring.h"
-#endif
-
-#if __LITTLE_ENDIAN__
-#define ENCODING_UTF16_NATIVE ENCODING_UTF16LE
-#define ENCODING_UTF32_NATIVE ENCODING_UTF32LE
-#define ENCODING_UTF16_NON_NATIVE ENCODING_UTF16BE
-#define ENCODING_UTF32_NON_NATIVE ENCODING_UTF32BE
-#else
-#define ENCODING_UTF16_NATIVE ENCODING_UTF16BE
-#define ENCODING_UTF32_NATIVE ENCODING_UTF32BE
-#define ENCODING_UTF16_NON_NATIVE ENCODING_UTF16LE
-#define ENCODING_UTF32_NON_NATIVE ENCODING_UTF32LE
-#endif
-
-#define IS_NATIVE_UTF16_ENC(encoding) \
-    ((encoding) == rb_encodings[ENCODING_UTF16_NATIVE])
-#define IS_NON_NATIVE_UTF16_ENC(encoding) \
-    ((encoding) == rb_encodings[ENCODING_UTF16_NON_NATIVE])
-#define IS_UTF16_ENC(encoding) \
-    (IS_NATIVE_UTF16_ENC(encoding) || IS_NON_NATIVE_UTF16_ENC(encoding))
-#define IS_NATIVE_UTF32_ENC(encoding) \
-    ((encoding) == rb_encodings[ENCODING_UTF32_NATIVE])
-#define IS_NON_NATIVE_UTF32_ENC(encoding) \
-    ((encoding) == rb_encodings[ENCODING_UTF32_NON_NATIVE])
-#define IS_UTF32_ENC(encoding) \
-    (IS_NATIVE_UTF32_ENC(encoding) || IS_NON_NATIVE_UTF32_ENC(encoding))
-#define IS_UTF8_ENC(encoding) ((encoding) == rb_encodings[ENCODING_UTF8])
-#define IS_ASCII_ENC(encoding) ((encoding) == rb_encodings[ENCODING_ASCII])
-#define IS_BINARY_ENC(encoding) ((encoding) == rb_encodings[ENCODING_BINARY])
-
-typedef uint8_t str_flag_t;
-
-typedef struct {
-    struct RBasic basic;
-    struct rb_encoding *encoding;
-    long capacity_in_bytes;
-    long length_in_bytes;
-    char *bytes;
-    str_flag_t flags;
-} rb_str_t;
-
-#define RSTR(x) ((rb_str_t *)x)
-
-static inline bool
-rb_klass_is_rstr(VALUE klass)
-{
-    do {
-	if (klass == rb_cRubyString) {
-	    return true;
-	}
-	if (klass == rb_cNSString) {
-	    return false;
-	}
-	klass = RCLASS_SUPER(klass);
-    }
-    while (klass != 0);
-    return false;
-}
-
-#define IS_RSTR(x) (rb_klass_is_rstr(*(VALUE *)x))
-
-static inline void
-rstr_modify(VALUE str)
-{
-    const long mask = RBASIC(str)->flags;
-    if ((mask & FL_FREEZE) == FL_FREEZE) {
-        rb_raise(rb_eRuntimeError, "can't modify frozen/immutable string");
-    }
-    if ((mask & FL_UNTRUSTED) != FL_UNTRUSTED) {
-	if (rb_safe_level() >= 4) {
-	    rb_raise(rb_eSecurityError, "Insecure: can't modify string");
-	}
-    }
-}
-
-static inline void
-rstr_frozen_check(VALUE str)
-{
-    const long mask = RBASIC(str)->flags;
-    if ((mask & FL_FREEZE) == FL_FREEZE) {
-	rb_raise(rb_eRuntimeError, "string frozen");
-    }
-}
-
-typedef struct {
-    long start_offset_in_bytes;
-    long end_offset_in_bytes;
-} character_boundaries_t;
-
-typedef struct {
-    character_boundaries_t cached_boundaries;
-    long cached_boundaries_index;
-    long cached_length;
-} character_boundaries_cache_t;
-
-typedef struct rb_encoding {
-    struct RBasic basic;
-    unsigned int index;
-    const char *public_name;
-    const char **aliases;
-    unsigned int aliases_count;
-    unsigned char min_char_size;
-    bool single_byte_encoding : 1;
-    bool ascii_compatible : 1;
-    bool little_endian : 1; // only meaningful for UTF-16 or UTF-32
-    void *private_data;
-} rb_encoding_t;
-
-#define RENC(x) ((rb_encoding_t *)(x))
-
-enum {
-    ENCODING_BINARY = 0,
-    ENCODING_ASCII,
-    ENCODING_UTF8,
-    ENCODING_UTF16BE,
-    ENCODING_UTF16LE,
-    ENCODING_UTF32BE,
-    ENCODING_UTF32LE,
-    ENCODING_ISO8859_1,
-    ENCODING_ISO8859_2,
-    ENCODING_ISO8859_3,
-    ENCODING_ISO8859_4,
-    ENCODING_ISO8859_5,
-    ENCODING_ISO8859_6,
-    ENCODING_ISO8859_7,
-    ENCODING_ISO8859_8,
-    ENCODING_ISO8859_9,
-    ENCODING_ISO8859_10,
-    ENCODING_ISO8859_11,
-    ENCODING_ISO8859_13,
-    ENCODING_ISO8859_14,
-    ENCODING_ISO8859_15,
-    ENCODING_ISO8859_16,
-    ENCODING_MACROMAN,
-    ENCODING_MACCYRILLIC,
-    ENCODING_BIG5,
-    ENCODING_EUCJP,
-    ENCODING_SJIS,
-    //ENCODING_CP932,
-
-    ENCODINGS_COUNT
-};
-
-extern rb_encoding_t *rb_encodings[ENCODINGS_COUNT];
-
-#define STRING_ASCII_ONLY_SET        0x010
-#define STRING_ASCII_ONLY            0x008
-#define STRING_VALID_ENCODING_SET    0x004
-#define STRING_VALID_ENCODING        0x002
-
-#define BYTES_TO_UCHARS(len) ((len) / sizeof(UChar))
-#define UCHARS_TO_BYTES(len) ((len) * sizeof(UChar))
-
-#define ODD_NUMBER(x) ((x) & 0x1)
-
-static inline void
-reset_character_boundaries_cache(character_boundaries_cache_t *cache)
-{
-    assert(cache != NULL);
-    cache->cached_boundaries_index = -1;
-    cache->cached_length = -1;
-}
-
-static inline long
-div_round_up(long a, long b)
-{
-    return ((a) + (b - 1)) / b;
-}
-
-void str_update_flags(rb_str_t *self);
-
-static inline void
-str_reset_flags(rb_str_t *self)
-{
-    self->flags = 0;
-}
-
-static inline bool
-str_check_flag_and_update_if_needed(rb_str_t *self, str_flag_t flag_set,
-	str_flag_t flag)
-{
-    if (!(self->flags & flag_set)) {
-	str_update_flags(self);
-	assert(self->flags & flag_set);
-    }
-    return self->flags & flag;
-}
-
-static inline bool
-str_is_valid_encoding(rb_str_t *self)
-{
-    return str_check_flag_and_update_if_needed(self, STRING_VALID_ENCODING_SET,
-	    STRING_VALID_ENCODING);
-}
-
-static inline bool
-str_is_ascii_only(rb_str_t *self)
-{
-    return str_check_flag_and_update_if_needed(self, STRING_ASCII_ONLY_SET,
-	    STRING_ASCII_ONLY);
-}
-
-static inline bool
-str_is_ruby_ascii_only(rb_str_t *self)
-{
-    // for MRI, a string in a non-ASCII-compatible encoding (like UTF-16)
-    // containing only ASCII characters is not "ASCII only" though for us it
-    // is internally
-    if (!self->encoding->ascii_compatible) {
-	return false;
-    }
-    return str_is_ascii_only(self);
-}
-
-static inline void
-str_set_flag(rb_str_t *self, bool status, str_flag_t flag_set,
-	str_flag_t flag)
-{
-    if (status) {
-	self->flags = self->flags | flag_set | flag;
-    }
-    else {
-	self->flags = (self->flags | flag_set) & ~flag;
-    }
-}
-
-static inline void
-str_set_ascii_only(rb_str_t *self, bool status)
-{
-    str_set_flag(self, status, STRING_ASCII_ONLY_SET, STRING_ASCII_ONLY);
-}
-
-static inline void
-str_set_valid_encoding(rb_str_t *self, bool status)
-{
-    str_set_flag(self, status, STRING_VALID_ENCODING_SET,
-	    STRING_VALID_ENCODING);
-}
-
-typedef enum {
-    TRANSCODE_BEHAVIOR_RAISE_EXCEPTION,
-    TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING,
-    TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_TEXT,
-    TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR
-} transcode_behavior_t;
-
-typedef enum {
-    ECONV_INVALID_MASK                = 1,
-    ECONV_INVALID_REPLACE             = 1 << 1,
-    ECONV_UNDEF_MASK                  = 1 << 2,
-    ECONV_UNDEF_REPLACE               = 1 << 3,
-    ECONV_UNDEF_HEX_CHARREF           = 1 << 4,
-    ECONV_PARTIAL_INPUT               = 1 << 5,
-    ECONV_AFTER_OUTPUT                = 1 << 6,
-    ECONV_UNIVERSAL_NEWLINE_DECORATOR = 1 << 7,
-    ECONV_CRLF_NEWLINE_DECORATOR      = 1 << 8,
-    ECONV_CR_NEWLINE_DECORATOR        = 1 << 9,
-    ECONV_XML_TEXT_DECORATOR          = 1 << 10,
-    ECONV_XML_ATTR_CONTENT_DECORATOR  = 1 << 11,
-    ECONV_XML_ATTR_QUOTE_DECORATOR    = 1 << 12
-} transcode_flags_t;
-
-rb_str_t *str_transcode(rb_str_t *self, rb_encoding_t *src_encoding, rb_encoding_t *dst_encoding,
-	int behavior_for_invalid, int behavior_for_undefined, rb_str_t *replacement_str);
-
-static inline rb_str_t *
-str_simple_transcode(rb_str_t *self, rb_encoding_t *dst_encoding)
-{
-    return str_transcode(self, self->encoding, dst_encoding,
-        TRANSCODE_BEHAVIOR_RAISE_EXCEPTION, TRANSCODE_BEHAVIOR_RAISE_EXCEPTION, NULL);
-}
-
-VALUE rb_str_substr_with_cache(VALUE str, long beg, long len,
-	character_boundaries_cache_t *cache);
-VALUE rb_reg_nth_match_with_cache(int nth, VALUE match,
-	character_boundaries_cache_t *cache);
-
-int rstr_compare(rb_str_t *str1, rb_str_t *str2);
-
-void rb_str_NSCoder_encode(void *coder, VALUE str, const char *key);
-VALUE rb_str_NSCoder_decode(void *coder, const char *key);
-
-VALUE mr_enc_s_is_compatible(VALUE klass, SEL sel, VALUE str1, VALUE str2);
-VALUE rb_str_intern_fast(VALUE str);
-VALUE rstr_aref(VALUE str, SEL sel, int argc, VALUE *argv);
-VALUE rstr_swapcase(VALUE str, SEL sel);
-VALUE rstr_capitalize(VALUE str, SEL sel);
-VALUE rstr_upcase(VALUE str, SEL sel);
-VALUE rstr_downcase(VALUE str, SEL sel);
-VALUE rstr_concat(VALUE self, SEL sel, VALUE other);
-
-// The following functions should always been prefered over anything else,
-// especially if this "else" is RSTRING_PTR and RSTRING_LEN.
-// They also work on CFStrings.
-
-VALUE rb_unicode_str_new(const UniChar *ptr, const size_t len);
-
-#define STR_UCHARS_STATIC_BUFSIZE 64
-
-typedef struct {
-    UChar static_buf[STR_UCHARS_STATIC_BUFSIZE];
-    UChar *chars;
-    long len;
-} rb_str_uchars_buf_t;
-
-void rb_str_get_uchars_always(VALUE str, rb_str_uchars_buf_t *buf);
-
-static inline void
-rb_str_get_uchars(VALUE str, rb_str_uchars_buf_t *buf)
-{
-    if (IS_RSTR(str)) {
-	rb_str_t *rstr = RSTR(str);
-	if (rstr->encoding->ascii_compatible && str_is_ascii_only(rstr)
-		&& rstr->length_in_bytes < STR_UCHARS_STATIC_BUFSIZE) {
-	    // Fast path.
-	    long i;
-	    for (i = 0; i < rstr->length_in_bytes; i++) {
-		buf->static_buf[i] = rstr->bytes[i];
-	    }
-	    buf->chars = buf->static_buf;
-	    buf->len = rstr->length_in_bytes;
-	    return;
-	}
-    }
-    rb_str_get_uchars_always(str, buf);
-}
-
-UChar *rb_str_xcopy_uchars(VALUE str, long *len_p);
-
-#define RB_STR_GET_UCHARS(str, _chars, _len) \
-    rb_str_uchars_buf_t __buf; \
-    rb_str_get_uchars(str, &__buf); \
-    UChar *_chars = __buf.chars; \
-    long _len = __buf.len
-
-long rb_str_chars_len(VALUE str);
-UChar rb_str_get_uchar(VALUE str, long pos);
-void rb_str_append_uchar(VALUE str, UChar c);
-void rb_str_append_uchars(VALUE str, const UChar *chars, long len);
-unsigned long rb_str_hash_uchars(const UChar *chars, long chars_len);
-long rb_uchar_strtol(UniChar *chars, long chars_len, long pos,
-	long *end_offset);
-void rb_str_force_encoding(VALUE str, rb_encoding_t *encoding);
-rb_str_t *str_need_string(VALUE str);
-rb_str_t *replacement_string_for_encoding(rb_encoding_t* enc);
-void str_replace_with_string(rb_str_t *self, rb_str_t *source);
-
-static inline void
-str_check_ascii_compatible(VALUE str)
-{
-    if (IS_RSTR(str) && !RSTR(str)->encoding->ascii_compatible) {
-	rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s",
-		RSTR(str)->encoding->public_name);
-    }
-}
-
-VALUE rstr_new_path(const char *path);
-
-const char *nsstr_cstr(VALUE str);
-long nsstr_clen(VALUE str);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif /* __ENCODING_H_ */

Deleted: MacRuby/trunk/encoding_ucnv.h
===================================================================
--- MacRuby/trunk/encoding_ucnv.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/encoding_ucnv.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,37 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9 String.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#ifndef __UCNV_H_
-#define __UCNV_H_
-
-#include "encoding.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef void (^each_uchar32_callback_t)(UChar32 c, long start_index, long length, bool *stop);
-
-void str_ucnv_update_flags(rb_str_t *self);
-long str_ucnv_length(rb_str_t *self, bool ucs2_mode);
-character_boundaries_t str_ucnv_get_character_boundaries(rb_str_t *self, long index, bool ucs2_mode);
-long str_ucnv_offset_in_bytes_to_index(rb_str_t *self, long offset_in_bytes, bool ucs2_mode);
-void str_ucnv_transcode_to_utf16(struct rb_encoding *src_enc, rb_str_t *self, long *pos, UChar **utf16, long *utf16_length);
-void str_ucnv_transcode_from_utf16(struct rb_encoding *dst_enc, UChar *utf16, long utf16_length, long *utf16_pos, char **bytes, long *bytes_length);
-void str_ucnv_each_uchar32_starting_from(rb_str_t *self,
-	long start_offset_in_bytes,
-	each_uchar32_callback_t callback);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif /* __UCNV_H_ */

Deleted: MacRuby/trunk/enum.c
===================================================================
--- MacRuby/trunk/enum.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/enum.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2100 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/util.h"
-#include "vm.h"
-#include "id.h"
-#include "array.h"
-
-VALUE rb_mEnumerable;
-static ID id_each, id_eqq, id_next, id_size;
-
-static VALUE
-enum_values_pack(int argc, VALUE *argv)
-{
-    if (argc == 0) return Qnil;
-    if (argc == 1) return argv[0];
-    return rb_ary_new4(argc, argv);
-}
-
-#define ENUM_WANT_SVALUE() do { \
-    i = enum_values_pack(argc, argv); \
-} while (0)
-
-#define enum_yield rb_yield_values2
-
-static VALUE
-grep_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
-	rb_ary_push(arg[1], i);
-    }
-    return Qnil;
-}
-
-static VALUE
-grep_iter_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
-	rb_ary_push(arg[1], rb_yield(i));
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.grep(pattern)                   => array
- *     enum.grep(pattern) {| obj | block }  => array
- *
- *  Returns an array of every element in <i>enum</i> for which
- *  <code>Pattern === element</code>. If the optional <em>block</em> is
- *  supplied, each matching element is passed to it, and the block's
- *  result is stored in the output array.
- *
- *     (1..100).grep 38..44   #=> [38, 39, 40, 41, 42, 43, 44]
- *     c = IO.constants
- *     c.grep(/SEEK/)         #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
- *     res = c.grep(/SEEK/) {|v| IO.const_get(v) }
- *     res                    #=> [0, 1, 2]
- *
- */
-
-static VALUE
-enum_grep(VALUE obj, SEL sel, VALUE pat)
-{
-    VALUE ary = rb_ary_new();
-    VALUE arg[2];
-
-    arg[0] = pat;
-    arg[1] = ary;
-
-    rb_objc_block_call(obj, selEach, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
-
-    return ary;
-}
-
-static VALUE
-count_i(VALUE i, VALUE memop, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE*)memop;
-
-    ENUM_WANT_SVALUE();
-
-    if (rb_equal(i, memo[1])) {
-	memo[0]++;
-    }
-    return Qnil;
-}
-
-static VALUE
-count_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE*)memop;
-
-    if (RTEST(enum_yield(argc, argv))) {
-	memo[0]++;
-    }
-    return Qnil;
-}
-
-static VALUE
-count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE*)memop;
-
-    memo[0]++;
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.count                   => int
- *     enum.count(item)             => int
- *     enum.count {| obj | block }  => int
- *
- *  Returns the number of items in <i>enum</i>, where #size is called
- *  if it responds to it, otherwise the items are counted through
- *  enumeration.  If an argument is given, counts the number of items
- *  in <i>enum</i>, for which equals to <i>item</i>.  If a block is
- *  given, counts the number of elements yielding a true value.
- *
- *     ary = [1, 2, 4, 2]
- *     ary.count             # => 4
- *     ary.count(2)          # => 2
- *     ary.count{|x|x%2==0}  # => 3
- *
- */
-
-static VALUE
-enum_count(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE memo[2];	/* [count, condition value] */
-    rb_block_call_func *func;
-
-    if (argc == 0) {
-	if (rb_block_given_p()) {
-	    func = count_iter_i;
-	}
-	else {
-	    if (rb_respond_to(obj, id_size)) {
-		return rb_funcall(obj, id_size, 0, 0);
-	    }
-	    func = count_all_i;
-	}
-    }
-    else {
-	rb_scan_args(argc, argv, "1", &memo[1]);
-	if (rb_block_given_p()) {
-	    rb_warn("given block not used");
-	}
-        func = count_i;
-    }
-
-    memo[0] = 0;
-    rb_objc_block_call(obj, selEach, 0, 0, func, (VALUE)&memo);
-    return INT2NUM(memo[0]);
-}
-
-static VALUE
-find_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (RTEST(rb_yield(i))) {
-	*memo = i;
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.detect(ifnone = nil) {| obj | block }  => obj or nil
- *     enum.find(ifnone = nil)   {| obj | block }  => obj or nil
- *
- *  Passes each entry in <i>enum</i> to <em>block</em>. Returns the
- *  first for which <em>block</em> is not <code>false</code>.  If no
- *  object matches, calls <i>ifnone</i> and returns its result when it
- *  is specified, or returns <code>nil</code>
- *
- *     (1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
- *     (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 }   #=> 35
- *
- */
-
-static VALUE
-enum_find(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE memo = Qundef;
-    VALUE if_none;
-
-    rb_scan_args(argc, argv, "01", &if_none);
-    RETURN_ENUMERATOR(obj, argc, argv);
-    rb_objc_block_call(obj, selEach, 0, 0, find_i, (VALUE)&memo);
-    if (memo != Qundef) {
-	return memo;
-    }
-    if (!NIL_P(if_none)) {
-	return rb_funcall(if_none, rb_intern("call"), 0, 0);
-    }
-    return Qnil;
-}
-
-static VALUE
-find_index_i(VALUE i, VALUE memop, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE*)memop;
-
-    ENUM_WANT_SVALUE();
-
-    if (rb_equal(i, memo[2])) {
-	memo[0] = UINT2NUM(memo[1]);
-	rb_iter_break();
-    }
-    memo[1]++;
-    return Qnil;
-}
-
-static VALUE
-find_index_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE*)memop;
-
-    if (RTEST(enum_yield(argc, argv))) {
-	memo[0] = UINT2NUM(memo[1]);
-	rb_iter_break();
-    }
-    memo[1]++;
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.find_index(value)            => int or nil
- *     enum.find_index {| obj | block }  => int or nil
- *
- *  Compares each entry in <i>enum</i> with <em>value</em> or passes
- *  to <em>block</em>.  Returns the index for the first for which the
- *  evaluated value is non-false.  If no object matches, returns
- *  <code>nil</code>
- *
- *     (1..10).find_index  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
- *     (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 }   #=> 34
- *     (1..100).find_index(50)                                #=> 49
- *
- */
-
-static VALUE
-enum_find_index(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE memo[3];	/* [return value, current index, condition value] */
-    rb_block_call_func *func;
-
-    if (argc == 0) {
-        RETURN_ENUMERATOR(obj, 0, 0);
-        func = find_index_iter_i;
-    }
-    else {
-	rb_scan_args(argc, argv, "1", &memo[2]);
-	if (rb_block_given_p()) {
-	    rb_warn("given block not used");
-	}
-        func = find_index_i;
-    }
-
-    memo[0] = Qnil;
-    memo[1] = 0;
-    rb_objc_block_call(obj, selEach, 0, 0, func, (VALUE)memo);
-    return memo[0];
-}
-
-static VALUE
-find_all_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (RTEST(rb_yield(i))) {
-	rb_ary_push(ary, i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.find_all {| obj | block }  => array
- *     enum.select   {| obj | block }  => array
- *
- *  Returns an array containing all elements of <i>enum</i> for which
- *  <em>block</em> is not <code>false</code> (see also
- *  <code>Enumerable#reject</code>).
- *
- *     (1..10).find_all {|i|  i % 3 == 0 }   #=> [3, 6, 9]
- *
- */
-
-static VALUE
-enum_find_all(VALUE obj, SEL sel)
-{
-    VALUE ary;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    ary = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, find_all_i, ary);
-
-    return ary;
-}
-
-static VALUE
-reject_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (!RTEST(rb_yield(i))) {
-	rb_ary_push(ary, i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.reject {| obj | block }  => array
- *
- *  Returns an array for all elements of <i>enum</i> for which
- *  <em>block</em> is false (see also <code>Enumerable#find_all</code>).
- *
- *     (1..10).reject {|i|  i % 3 == 0 }   #=> [1, 2, 4, 5, 7, 8, 10]
- *
- */
-
-static VALUE
-enum_reject(VALUE obj, SEL sel)
-{
-    VALUE ary;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    ary = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, reject_i, ary);
-
-    return ary;
-}
-
-static VALUE
-collect_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    rb_ary_push(ary, enum_yield(argc, argv));
-
-    return Qnil;
-}
-
-static VALUE
-collect_all(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    rb_ary_push(ary, enum_values_pack(argc, argv));
-
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.collect {| obj | block }  => array
- *     enum.map     {| obj | block }  => array
- *
- *  Returns a new array with the results of running <em>block</em> once
- *  for every element in <i>enum</i>.
- *
- *     (1..4).collect {|i| i*i }   #=> [1, 4, 9, 16]
- *     (1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]
- *
- */
-
-static VALUE
-enum_collect(VALUE obj, SEL sel)
-{
-    VALUE ary;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    ary = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, collect_i, ary);
-
-    return ary;
-}
-
-static VALUE
-flat_map_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    VALUE tmp;
-
-    i = enum_yield(argc, argv);
-    tmp = rb_check_array_type(i);
-
-    if (NIL_P(tmp)) {
-	rb_ary_push(ary, i);
-    }
-    else {
-	rb_ary_concat(ary, tmp);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.flat_map       {| obj | block }  => array
- *     enum.collect_concat {| obj | block }  => array
- *
- *  Returns a new array with the concatenated results of running
- *  <em>block</em> once for every element in <i>enum</i>.
- *
- *     [[1,2],[3,4]].flat_map {|i| i }   #=> [1, 2, 3, 4]
- *
- */
-
-static VALUE
-enum_flat_map(VALUE obj, SEL sel)
-{
-    VALUE ary;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    ary = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, flat_map_i, ary);
-
-    return ary;
-}
-
-/*
- *  call-seq:
- *     enum.to_a      =>    array
- *     enum.entries   =>    array
- *
- *  Returns an array containing the items in <i>enum</i>.
- *
- *     (1..7).to_a                       #=> [1, 2, 3, 4, 5, 6, 7]
- *     { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]
- */
-static VALUE
-enum_to_a(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE ary = rb_ary_new();
-
-    rb_objc_block_call(obj, selEach, argc, argv, collect_all, ary);
-
-    return ary;
-}
-
-static VALUE
-inject_i(VALUE i, VALUE p, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE *)p;
-
-    ENUM_WANT_SVALUE();
-
-    if (memo[0] == Qundef) {
-	memo[0] = i;
-    }
-    else {
-	memo[0] = rb_yield_values(2, memo[0], i);
-    }
-    return Qnil;
-}
-
-static VALUE
-inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
-{
-    VALUE *memo = (VALUE *)p;
-
-    ENUM_WANT_SVALUE();
-
-    if (memo[0] == Qundef) {
-	memo[0] = i;
-    }
-    else {
-	memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.inject(initial, sym) => obj
- *     enum.inject(sym)          => obj
- *     enum.inject(initial) {| memo, obj | block }  => obj
- *     enum.inject          {| memo, obj | block }  => obj
- *
- *     enum.reduce(initial, sym) => obj
- *     enum.reduce(sym)          => obj
- *     enum.reduce(initial) {| memo, obj | block }  => obj
- *     enum.reduce          {| memo, obj | block }  => obj
- *
- *  Combines all elements of <i>enum</i> by applying a binary
- *  operation, specified by a block or a symbol that names a
- *  method or operator.
- *
- *  If you specify a block, then for each element in <i>enum<i>
- *  the block is passed an accumulator value (<i>memo</i>) and the element.
- *  If you specify a symbol instead, then each element in the collection
- *  will be passed to the named method of <i>memo</i>.
- *  In either case, the result becomes the new value for <i>memo</i>.
- *  At the end of the iteration, the final value of <i>memo</i> is the
- *  return value fo the method.
- *
- *  If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
- *  then uses the first element of collection is used as the initial value
- *  of <i>memo</i>.
- *
- *  Examples:
- *
- *     # Sum some numbers
- *     (5..10).reduce(:+)                            #=> 45
- *     # Same using a block and inject
- *     (5..10).inject {|sum, n| sum + n }            #=> 45
- *     # Multiply some numbers
- *     (5..10).reduce(1, :*)                         #=> 151200
- *     # Same using a block
- *     (5..10).inject(1) {|product, n| product * n } #=> 151200
- *     # find the longest word
- *     longest = %w{ cat sheep bear }.inject do |memo,word|
- *        memo.length > word.length ? memo : word
- *     end
- *     longest                                       #=> "sheep"
- *
- */
-static VALUE
-enum_inject(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE memo[2];
-    VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;
-
-    switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
-      case 0:
-	memo[0] = Qundef;
-	break;
-      case 1:
-	if (rb_block_given_p()) {
-	    break;
-	}
-	memo[1] = (VALUE)rb_to_id(memo[0]);
-	memo[0] = Qundef;
-	iter = inject_op_i;
-	break;
-      case 2:
-	if (rb_block_given_p()) {
-	    rb_warning("given block not used");
-	}
-	memo[1] = (VALUE)rb_to_id(memo[1]);
-	iter = inject_op_i;
-	break;
-    }
-    rb_objc_block_call(obj, selEach, 0, 0, iter, (VALUE)memo);
-    if (memo[0] == Qundef) {
-	return Qnil;
-    }
-    return memo[0];
-}
-
-static VALUE
-partition_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (RTEST(rb_yield(i))) {
-	rb_ary_push(ary[0], i);
-    }
-    else {
-	rb_ary_push(ary[1], i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.partition {| obj | block }  => [ true_array, false_array ]
- *
- *  Returns two arrays, the first containing the elements of
- *  <i>enum</i> for which the block evaluates to true, the second
- *  containing the rest.
- *
- *     (1..6).partition {|i| (i&1).zero?}   #=> [[2, 4, 6], [1, 3, 5]]
- *
- */
-
-static VALUE
-enum_partition(VALUE obj, SEL sel)
-{
-    VALUE ary[2];
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    ary[0] = rb_ary_new();
-    ary[1] = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, partition_i, (VALUE)ary);
-
-    return rb_assoc_new(ary[0], ary[1]);
-}
-
-static VALUE
-group_by_i(VALUE i, VALUE hash, int argc, VALUE *argv)
-{
-    VALUE group;
-    VALUE values;
-
-    ENUM_WANT_SVALUE();
-
-    group = rb_yield(i);
-    values = rb_hash_aref(hash, group);
-    if (NIL_P(values)) {
-	values = rb_ary_new4(1, &i);
-	rb_hash_aset(hash, group, values);
-    }
-    else {
-	rb_ary_push(values, i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.group_by {| obj | block }  => a_hash
- *
- *  Returns a hash, which keys are evaluated result from the
- *  block, and values are arrays of elements in <i>enum</i>
- *  corresponding to the key.
- *
- *     (1..6).group_by {|i| i%3}   #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
- *
- */
-
-static VALUE
-enum_group_by(VALUE obj, SEL sel)
-{
-    VALUE hash;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    hash = rb_hash_new();
-    rb_objc_block_call(obj, selEach, 0, 0, group_by_i, hash);
-
-    return hash;
-}
-
-static VALUE
-first_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (NIL_P(ary[0])) {
-	ary[1] = i;
-	rb_iter_break();
-    }
-    else {
-	long n = NUM2LONG(ary[0]);
-
-	if (n <= 0) {
-	    rb_iter_break();
-	}
-	else {
-	    rb_ary_push(ary[1], i);
-	    n--;
-	    ary[0] = INT2NUM(n);
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.first      -> obj or nil
- *     enum.first(n)   -> an_array
- *
- *  Returns the first element, or the first +n+ elements, of the enumerable.
- *  If the enumerable is empty, the first form returns <code>nil</code>, and the
- *  second form returns an empty array.
- *
- */
-
-static VALUE
-enum_first(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE n, ary[2];
-
-    if (argc == 0) {
-	ary[0] = ary[1] = Qnil;
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &n);
-	ary[0] = n;
-	ary[1] = rb_ary_new2(NUM2LONG(n));
-    }
-    rb_objc_block_call(obj, selEach, 0, 0, first_i, (VALUE)ary);
-
-    return ary[1];
-}
-
-
-/*
- *  call-seq:
- *     enum.sort                     => array
- *     enum.sort {| a, b | block }   => array
- *
- *  Returns an array containing the items in <i>enum</i> sorted,
- *  either according to their own <code><=></code> method, or by using
- *  the results of the supplied block. The block should return -1, 0, or
- *  +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
- *  Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
- *  built-in Schwartzian Transform, useful when key computation or
- *  comparison is expensive..
- *
- *     %w(rhea kea flea).sort         #=> ["flea", "kea", "rhea"]
- *     (1..10).sort {|a,b| b <=> a}   #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
- */
-
-static VALUE
-enum_sort(VALUE obj, SEL sel)
-{
-    return rb_ary_sort(enum_to_a(obj, 0, 0, 0));
-}
-
-static VALUE
-sort_by_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    NODE *memo;
-
-    ENUM_WANT_SVALUE();
-#if !WITH_OBJC
-    if (RBASIC(ary)->klass) {
-	rb_raise(rb_eRuntimeError, "sort_by reentered");
-    }
-#endif
-    memo = rb_node_newnode(NODE_MEMO, rb_yield(i), i, 0);
-    rb_ary_push(ary, (VALUE)memo);
-    return Qnil;
-}
-
-static int
-sort_by_cmp(void *data, const void *ap, const void *bp)
-{
-    VALUE a = (*(NODE *const *)ap)->u1.value;
-    VALUE b = (*(NODE *const *)bp)->u1.value;
-    return rb_cmpint(rb_objs_cmp(a, b), a, b);
-}
-
-/*
- *  call-seq:
- *     enum.sort_by {| obj | block }    => array
- *
- *  Sorts <i>enum</i> using a set of keys generated by mapping the
- *  values in <i>enum</i> through the given block.
- *
- *     %w{ apple pear fig }.sort_by {|word| word.length}
- *                   #=> ["fig", "pear", "apple"]
- *
- *  The current implementation of <code>sort_by</code> generates an
- *  array of tuples containing the original collection element and the
- *  mapped value. This makes <code>sort_by</code> fairly expensive when
- *  the keysets are simple
- *
- *     require 'benchmark'
- *     include Benchmark
- *
- *     a = (1..100000).map {rand(100000)}
- *
- *     bm(10) do |b|
- *       b.report("Sort")    { a.sort }
- *       b.report("Sort by") { a.sort_by {|a| a} }
- *     end
- *
- *  <em>produces:</em>
- *
- *     user     system      total        real
- *     Sort        0.180000   0.000000   0.180000 (  0.175469)
- *     Sort by     1.980000   0.040000   2.020000 (  2.013586)
- *
- *  However, consider the case where comparing the keys is a non-trivial
- *  operation. The following code sorts some files on modification time
- *  using the basic <code>sort</code> method.
- *
- *     files = Dir["*"]
- *     sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
- *     sorted   #=> ["mon", "tues", "wed", "thurs"]
- *
- *  This sort is inefficient: it generates two new <code>File</code>
- *  objects during every comparison. A slightly better technique is to
- *  use the <code>Kernel#test</code> method to generate the modification
- *  times directly.
- *
- *     files = Dir["*"]
- *     sorted = files.sort { |a,b|
- *       test(?M, a) <=> test(?M, b)
- *     }
- *     sorted   #=> ["mon", "tues", "wed", "thurs"]
- *
- *  This still generates many unnecessary <code>Time</code> objects. A
- *  more efficient technique is to cache the sort keys (modification
- *  times in this case) before the sort. Perl users often call this
- *  approach a Schwartzian Transform, after Randal Schwartz. We
- *  construct a temporary array, where each element is an array
- *  containing our sort key along with the filename. We sort this array,
- *  and then extract the filename from the result.
- *
- *     sorted = Dir["*"].collect { |f|
- *        [test(?M, f), f]
- *     }.sort.collect { |f| f[1] }
- *     sorted   #=> ["mon", "tues", "wed", "thurs"]
- *
- *  This is exactly what <code>sort_by</code> does internally.
- *
- *     sorted = Dir["*"].sort_by {|f| test(?M, f)}
- *     sorted   #=> ["mon", "tues", "wed", "thurs"]
- */
-
-static VALUE
-enum_sort_by(VALUE obj, SEL sel)
-{
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    VALUE ary;
-    if (TYPE(obj) == T_ARRAY) {
-	ary  = rb_ary_new2(RARRAY_LEN(obj));
-    }
-    else {
-	ary = rb_ary_new();
-    }
-    rb_objc_block_call(obj, selEach, 0, 0, sort_by_i, ary);
-    if (RARRAY_LEN(ary) > 1) {
-	qsort_r((VALUE *)RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE), NULL,
-		sort_by_cmp);
-    }
-    for (long i = 0; i < RARRAY_LEN(ary); i++) {
-	rb_ary_store(ary, i, RNODE(RARRAY_AT(ary, i))->u2.value);
-    }
-    return ary;
-}
-
-#define DEFINE_ENUMFUNCS(name) \
-static VALUE \
-name##_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
-{ \
-    return enum_##name##_func(enum_values_pack(argc, argv), memo); \
-} \
-\
-static VALUE \
-name##_iter_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
-{ \
-    return enum_##name##_func(enum_yield(argc, argv), memo); \
-}
-    
-static VALUE
-enum_all_func(VALUE result, VALUE *memo)
-{
-    if (!RTEST(result)) {
-	*memo = Qfalse;
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-DEFINE_ENUMFUNCS(all)
-
-/*
- *  call-seq:
- *     enum.all? [{|obj| block } ]   => true or false
- *
- *  Passes each element of the collection to the given block. The method
- *  returns <code>true</code> if the block never returns
- *  <code>false</code> or <code>nil</code>. If the block is not given,
- *  Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
- *  <code>all?</code> will return <code>true</code> only if none of the
- *  collection members are <code>false</code> or <code>nil</code>.)
- *
- *     %w{ant bear cat}.all? {|word| word.length >= 3}   #=> true
- *     %w{ant bear cat}.all? {|word| word.length >= 4}   #=> false
- *     [ nil, true, 99 ].all?                            #=> false
- *
- */
-
-static VALUE
-enum_all(VALUE obj, SEL sel)
-{
-    VALUE result = Qtrue;
-
-    rb_objc_block_call(obj, selEach, 0, 0, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result);
-    return result;
-}
-
-static VALUE
-enum_any_func(VALUE result, VALUE *memo)
-{
-    if (RTEST(result)) {
-	*memo = Qtrue;
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-DEFINE_ENUMFUNCS(any)
-
-/*
- *  call-seq:
- *     enum.any? [{|obj| block } ]   => true or false
- *
- *  Passes each element of the collection to the given block. The method
- *  returns <code>true</code> if the block ever returns a value other
- *  than <code>false</code> or <code>nil</code>. If the block is not
- *  given, Ruby adds an implicit block of <code>{|obj| obj}</code> (that
- *  is <code>any?</code> will return <code>true</code> if at least one
- *  of the collection members is not <code>false</code> or
- *  <code>nil</code>.
- *
- *     %w{ant bear cat}.any? {|word| word.length >= 3}   #=> true
- *     %w{ant bear cat}.any? {|word| word.length >= 4}   #=> true
- *     [ nil, true, 99 ].any?                            #=> true
- *
- */
-
-static VALUE
-enum_any(VALUE obj, SEL sel)
-{
-    VALUE result = Qfalse;
-
-    rb_objc_block_call(obj, selEach, 0, 0, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result);
-    return result;
-}
-
-static VALUE
-enum_one_func(VALUE result, VALUE *memo)
-{
-    if (RTEST(result)) {
-	if (*memo == Qundef) {
-	    *memo = Qtrue;
-	}
-	else if (*memo == Qtrue) {
-	    *memo = Qfalse;
-	    rb_iter_break();
-	}
-    }
-    return Qnil;
-}
-
-DEFINE_ENUMFUNCS(one)
-
-/*
- *  call-seq:
- *     enum.one? [{|obj| block }]   => true or false
- *
- *  Passes each element of the collection to the given block. The method
- *  returns <code>true</code> if the block returns <code>true</code>
- *  exactly once. If the block is not given, <code>one?</code> will return
- *  <code>true</code> only if exactly one of the collection members is
- *  true.
- *
- *     %w{ant bear cat}.one? {|word| word.length == 4}   #=> true
- *     %w{ant bear cat}.one? {|word| word.length > 4}    #=> false
- *     %w{ant bear cat}.one? {|word| word.length < 4}    #=> false
- *     [ nil, true, 99 ].one?                            #=> false
- *     [ nil, true, false ].one?                         #=> true
- *
- */
-
-static VALUE
-enum_one(VALUE obj, SEL sel)
-{
-    VALUE result = Qundef;
-
-    rb_objc_block_call(obj, selEach, 0, 0, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result);
-    if (result == Qundef) return Qfalse;
-    return result;
-}
-
-static VALUE
-enum_none_func(VALUE result, VALUE *memo)
-{
-    if (RTEST(result)) {
-	*memo = Qfalse;
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-DEFINE_ENUMFUNCS(none)
-
-/*
- *  call-seq:
- *     enum.none? [{|obj| block }]   => true or false
- *
- *  Passes each element of the collection to the given block. The method
- *  returns <code>true</code> if the block never returns <code>true</code>
- *  for all elements. If the block is not given, <code>none?</code> will return
- *  <code>true</code> only if none of the collection members is true.
- *
- *     %w{ant bear cat}.none? {|word| word.length == 5}  #=> true
- *     %w{ant bear cat}.none? {|word| word.length >= 4}  #=> false
- *     [].none?                                          #=> true
- *     [nil].none?                                       #=> true
- *     [nil,false].none?                                 #=> true
- */
-static VALUE
-enum_none(VALUE obj, SEL sel)
-{
-    VALUE result = Qtrue;
-
-    rb_objc_block_call(obj, selEach, 0, 0, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result);
-    return result;
-}
-
-static VALUE
-min_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE cmp;
-
-    ENUM_WANT_SVALUE();
-
-    if (*memo == Qundef) {
-	*memo = i;
-    }
-    else {
-	cmp = rb_objs_cmp(i, *memo);
-	if (rb_cmpint(cmp, i, *memo) < 0) {
-	    *memo = i;
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-min_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE cmp;
-
-    ENUM_WANT_SVALUE();
-
-    if (*memo == Qundef) {
-	*memo = i;
-    }
-    else {
-	VALUE ary = memo[1];
-	rb_ary_store(ary, 0, i);
-	rb_ary_store(ary, 1, *memo);
-	cmp = rb_yield(ary);
-	if (rb_cmpint(cmp, i, *memo) < 0) {
-	    *memo = i;
-	}
-    }
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     enum.min                    => obj
- *     enum.min {| a,b | block }   => obj
- *
- *  Returns the object in <i>enum</i> with the minimum value. The
- *  first form assumes all objects implement <code>Comparable</code>;
- *  the second uses the block to return <em>a <=> b</em>.
- *
- *     a = %w(albatross dog horse)
- *     a.min                                  #=> "albatross"
- *     a.min {|a,b| a.length <=> b.length }   #=> "dog"
- */
-
-static VALUE
-enum_min(VALUE obj, SEL sel)
-{
-    VALUE result[2];
-
-    result[0] = Qundef;
-    if (rb_block_given_p()) {
-	VALUE elems[] = { Qnil, Qnil };
-	result[1] = rb_ary_new4(2, elems);
-	rb_objc_block_call(obj, selEach, 0, 0, min_ii, (VALUE)result);
-    }
-    else {
-	rb_objc_block_call(obj, selEach, 0, 0, min_i, (VALUE)result);
-    }
-    if (result[0] == Qundef) return Qnil;
-    return result[0];
-}
-
-static VALUE
-max_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE cmp;
-
-    ENUM_WANT_SVALUE();
-
-    if (*memo == Qundef) {
-	*memo = i;
-    }
-    else {
-	cmp = rb_objs_cmp(i, *memo);
-	if (rb_cmpint(cmp, i, *memo) > 0) {
-	    *memo = i;
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-max_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE cmp;
-
-    ENUM_WANT_SVALUE();
-
-    if (*memo == Qundef) {
-	*memo = i;
-    }
-    else {
-	VALUE ary = memo[1];
-	rb_ary_store(ary, 0, i);
-	rb_ary_store(ary, 1, *memo);
-	cmp = rb_yield(ary);
-	if (rb_cmpint(cmp, i, *memo) > 0) {
-	    *memo = i;
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.max                   => obj
- *     enum.max {|a,b| block }    => obj
- *
- *  Returns the object in _enum_ with the maximum value. The
- *  first form assumes all objects implement <code>Comparable</code>;
- *  the second uses the block to return <em>a <=> b</em>.
- *
- *     a = %w(albatross dog horse)
- *     a.max                                  #=> "horse"
- *     a.max {|a,b| a.length <=> b.length }   #=> "albatross"
- */
-
-static VALUE
-enum_max(VALUE obj, SEL sel)
-{
-    VALUE result[2];
-
-    result[0] = Qundef;
-    if (rb_block_given_p()) {
-	VALUE elems[] = { Qnil, Qnil };
-	result[1] = rb_ary_new4(2, elems);
-	rb_objc_block_call(obj, selEach, 0, 0, max_ii, (VALUE)result);
-    }
-    else {
-	rb_objc_block_call(obj, selEach, 0, 0, max_i, (VALUE)result);
-    }
-    if (result[0] == Qundef) return Qnil;
-    return result[0];
-}
-
-static VALUE
-minmax_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    int n;
-
-    ENUM_WANT_SVALUE();
-
-    if (memo[0] == Qundef) {
-	memo[0] = i;
-	memo[1] = i;
-    }
-    else {
-	n = rb_cmpint(rb_objs_cmp(i, memo[0]), i, memo[0]);
-	if (n < 0) {
-	    memo[0] = i;
-	}
-	n = rb_cmpint(rb_objs_cmp(i, memo[1]), i, memo[1]);
-	if (n > 0) {
-	    memo[1] = i;
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-minmax_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    int n;
-
-    ENUM_WANT_SVALUE();
-
-    if (memo[0] == Qundef) {
-	memo[0] = i;
-	memo[1] = i;
-    }
-    else {
-	VALUE ary = memo[2];
-
-	rb_ary_store(ary, 0, i);
-	rb_ary_store(ary, 1, memo[0]);
-	n = rb_cmpint(rb_yield(ary), i, memo[0]);
-	if (n < 0) {
-	    memo[0] = i;
-	}
-	rb_ary_store(ary, 0, i);
-	rb_ary_store(ary, 1, memo[1]);
-	n = rb_cmpint(rb_yield(ary), i, memo[1]);
-	if (n > 0) {
-	    memo[1] = i;
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.minmax                   => [min,max]
- *     enum.minmax {|a,b| block }    => [min,max]
- *
- *  Returns two elements array which contains the minimum and the
- *  maximum value in the enumerable.  The first form assumes all
- *  objects implement <code>Comparable</code>; the second uses the
- *  block to return <em>a <=> b</em>.
- *
- *     a = %w(albatross dog horse)
- *     a.minmax                                  #=> ["albatross", "horse"]
- *     a.minmax {|a,b| a.length <=> b.length }   #=> ["dog", "albatross"]
- */
-
-static VALUE
-enum_minmax(VALUE obj, SEL sel)
-{
-    VALUE result[3];
-    VALUE elems[] = { Qnil, Qnil };
-    VALUE ary = rb_ary_new4(2, elems);
-
-    result[0] = Qundef;
-    if (rb_block_given_p()) {
-	result[2] = ary;
-	rb_objc_block_call(obj, selEach, 0, 0, minmax_ii, (VALUE)result);
-    }
-    else {
-	rb_objc_block_call(obj, selEach, 0, 0, minmax_i, (VALUE)result);
-    }
-    if (result[0] != Qundef) {
-	rb_ary_store(ary, 0, result[0]);
-	rb_ary_store(ary, 1, result[1]);
-    }
-    return ary;
-}
-
-static VALUE
-min_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE v;
-
-    ENUM_WANT_SVALUE();
-
-    v = rb_yield(i);
-    if (memo[0] == Qundef) {
-	memo[0] = v;
-	memo[1] = i;
-    }
-    else if (rb_cmpint(rb_objs_cmp(v, memo[0]), v, memo[0]) < 0) {
-	memo[0] = v;
-	memo[1] = i;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.min_by {| obj| block }   => obj
- *
- *  Returns the object in <i>enum</i> that gives the minimum
- *  value from the given block.
- *
- *     a = %w(albatross dog horse)
- *     a.min_by {|x| x.length }   #=> "dog"
- */
-
-static VALUE
-enum_min_by(VALUE obj, SEL sel)
-{
-    VALUE memo[2];
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    memo[0] = Qundef;
-    memo[1] = Qnil;
-    rb_objc_block_call(obj, selEach, 0, 0, min_by_i, (VALUE)memo);
-    return memo[1];
-}
-
-static VALUE
-max_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE v;
-
-    ENUM_WANT_SVALUE();
-
-    v = rb_yield(i);
-    if (memo[0] == Qundef) {
-	memo[0] = v;
-	memo[1] = i;
-    }
-    else if (rb_cmpint(rb_objs_cmp(v, memo[0]), v, memo[0]) > 0) {
-	memo[0] = v;
-	memo[1] = i;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.max_by {| obj| block }   => obj
- *
- *  Returns the object in <i>enum</i> that gives the maximum
- *  value from the given block.
- *
- *     a = %w(albatross dog horse)
- *     a.max_by {|x| x.length }   #=> "albatross"
- */
-
-static VALUE
-enum_max_by(VALUE obj, SEL sel)
-{
-    VALUE memo[2];
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    memo[0] = Qundef;
-    memo[1] = Qnil;
-    rb_objc_block_call(obj, selEach, 0, 0, max_by_i, (VALUE)memo);
-    return memo[1];
-}
-
-static VALUE
-minmax_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE v;
-
-    ENUM_WANT_SVALUE();
-
-    v = rb_yield(i);
-    if (memo[0] == Qundef) {
-	memo[0] = v;
-	memo[1] = v;
-	memo[2] = i;
-	memo[3] = i;
-    }
-    else {
-	if (rb_cmpint(rb_objs_cmp(v, memo[0]), v, memo[0]) < 0) {
-	    memo[0] = v;
-	    memo[2] = i;
-	}
-	if (rb_cmpint(rb_objs_cmp(v, memo[1]), v, memo[1]) > 0) {
-	    memo[1] = v;
-	    memo[3] = i;
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.minmax_by {| obj| block }   => [min, max]
- *
- *  Returns two elements array array containing the objects in
- *  <i>enum</i> that gives the minimum and maximum values respectively
- *  from the given block.
- *
- *     a = %w(albatross dog horse)
- *     a.minmax_by {|x| x.length }   #=> ["dog", "albatross"]
- */
-
-static VALUE
-enum_minmax_by(VALUE obj, SEL sel)
-{
-    VALUE memo[4];
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-
-    memo[0] = Qundef;
-    memo[1] = Qundef;
-    memo[2] = Qnil;
-    memo[3] = Qnil;
-    rb_objc_block_call(obj, selEach, 0, 0, minmax_by_i, (VALUE)memo);
-    return rb_assoc_new(memo[2], memo[3]);
-}
-
-static VALUE
-member_i(VALUE iter, VALUE *memo, int argc, VALUE *argv)
-{
-    if (rb_equal(enum_values_pack(argc, argv), memo[0])) {
-	memo[1] = Qtrue;
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.include?(obj)     => true or false
- *     enum.member?(obj)      => true or false
- *
- *  Returns <code>true</code> if any member of <i>enum</i> equals
- *  <i>obj</i>. Equality is tested using <code>==</code>.
- *
- *     IO.constants.include? :SEEK_SET          #=> true
- *     IO.constants.include? :SEEK_NO_FURTHER   #=> false
- *
- */
-
-static VALUE
-enum_member(VALUE obj, SEL sel, VALUE val)
-{
-    VALUE memo[2];
-
-    memo[0] = val;
-    memo[1] = Qfalse;
-    rb_objc_block_call(obj, selEach, 0, 0, member_i, (VALUE)memo);
-    return memo[1];
-}
-
-static VALUE
-each_with_index_i(VALUE i, VALUE memo, int argc, VALUE *argv)
-{
-    long n = (*(VALUE *)memo)++;
-
-    return rb_yield_values(2, enum_values_pack(argc, argv), INT2NUM(n));
-}
-
-/*
- *  call-seq:
- *     enum.each_with_index {|obj, i| block }  -> enum
- *
- *  Calls <em>block</em> with two arguments, the item and its index,
- *  for each item in <i>enum</i>.  Given arguments are passed through
- *  to #each().
- *
- *     hash = Hash.new
- *     %w(cat dog wombat).each_with_index {|item, index|
- *       hash[item] = index
- *     }
- *     hash   #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
- *
- */
-
-static VALUE
-enum_each_with_index(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    long memo;
-
-    RETURN_ENUMERATOR(obj, argc, argv);
-
-    memo = 0;
-    rb_objc_block_call(obj, selEach, argc, argv, each_with_index_i, (VALUE)&memo);
-    return obj;
-}
-
-
-/*
- *  call-seq:
- *     enum.reverse_each {|item| block } 
- *  
- *  Traverses <i>enum</i> in reverse order.
- */
-
-static VALUE
-enum_reverse_each(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE ary;
-    long i;
-
-    RETURN_ENUMERATOR(obj, argc, argv);
-
-    ary = enum_to_a(obj, 0, argc, argv);
-
-    for (i = RARRAY_LEN(ary); --i >= 0; ) {
-	rb_yield(RARRAY_AT(ary, i));
-	RETURN_IF_BROKEN();
-    }
-
-    return obj;
-}
-
-static VALUE
-each_val_i(VALUE i, VALUE p, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-    rb_yield(i);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.each_entry {|obj| block}  => enum
- *
- *  Calls <i>block</i> once for each element in <i>self</i>, passing that
- *  element as a parameter, converting multiple values from yield to an
- *  array.
- *
- *     class Foo
- *       include Enumerable
- *       def each
- *         yield 1
- *         yield 1,2
- *       end
- *     end
- *     Foo.new.each_entry{|o| print o, " -- "}
- *
- *  produces:
- *
- *     1 -- [1, 2] --
- */
-
-static VALUE
-enum_each_entry(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    RETURN_ENUMERATOR(obj, argc, argv);
-    rb_objc_block_call(obj, selEach, argc, argv, each_val_i, 0);
-    return obj;
-}
-
-static VALUE
-each_slice_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE ary = memo[0];
-    VALUE v = Qnil;
-    long size = (long)memo[1];
-    ENUM_WANT_SVALUE();
-
-    rb_ary_push(ary, i);
-
-    if (RARRAY_LEN(ary) == size) {
-	v = rb_yield(ary);
-	memo[0] = rb_ary_new2(size);
-    }
-
-    return v;
-}
-
-/*
- *  call-seq:
- *    e.each_slice(n) {...}
- *    e.each_slice(n)
- *
- *  Iterates the given block for each slice of <n> elements.  If no
- *  block is given, returns an enumerator.
- *
- *  e.g.:
- *      (1..10).each_slice(3) {|a| p a}
- *      # outputs below
- *      [1, 2, 3]
- *      [4, 5, 6]
- *      [7, 8, 9]
- *      [10]
- *
- */
-static VALUE
-enum_each_slice(VALUE obj, SEL sel, VALUE n)
-{
-    long size = NUM2LONG(n);
-    VALUE args[2], ary;
-
-    if (size <= 0) {
-	rb_raise(rb_eArgError, "invalid slice size");
-    }
-    RETURN_ENUMERATOR(obj, 1, &n);
-    args[0] = rb_ary_new2(size);
-    args[1] = (VALUE)size;
-
-    rb_objc_block_call(obj, selEach, 0, 0, each_slice_i, (VALUE)args);
-
-    ary = args[0];
-    if (RARRAY_LEN(ary) > 0) {
-	rb_yield(ary);
-    }
-
-    return Qnil;
-}
-
-static VALUE
-each_cons_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
-{
-    VALUE ary = memo[0];
-    VALUE v = Qnil;
-    long size = (long)memo[1];
-    ENUM_WANT_SVALUE();
-
-    if (RARRAY_LEN(ary) == size) {
-	rb_ary_shift(ary);
-    }
-    rb_ary_push(ary, i);
-    if (RARRAY_LEN(ary) == size) {
-	v = rb_yield(rb_ary_dup(ary));
-    }
-    return v;
-}
-
-/*
- *  call-seq:
- *    each_cons(n) {...}
- *    each_cons(n)
- *
- *  Iterates the given block for each array of consecutive <n>
- *  elements.  If no block is given, returns an enumerator.
- *
- *  e.g.:
- *      (1..10).each_cons(3) {|a| p a}
- *      # outputs below
- *      [1, 2, 3]
- *      [2, 3, 4]
- *      [3, 4, 5]
- *      [4, 5, 6]
- *      [5, 6, 7]
- *      [6, 7, 8]
- *      [7, 8, 9]
- *      [8, 9, 10]
- *
- */
-static VALUE
-enum_each_cons(VALUE obj, SEL sel, VALUE n)
-{
-    long size = NUM2LONG(n);
-    VALUE args[2];
-
-    if (size <= 0) {
-	rb_raise(rb_eArgError, "invalid size");
-    }
-    RETURN_ENUMERATOR(obj, 1, &n);
-    args[0] = rb_ary_new2(size);
-    args[1] = (VALUE)size;
-
-    rb_objc_block_call(obj, selEach, 0, 0, each_cons_i, (VALUE)args);
-
-    return Qnil;
-}
-
-static VALUE
-each_with_object_i(VALUE i, VALUE memo, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-    return rb_yield_values(2, i, memo);
-}
-
-/*
- *  call-seq:
- *    each_with_object(obj) {|(*args), memo_obj| ... }
- *    each_with_object(obj)
- *
- *  Iterates the given block for each element with an arbitrary
- *  object given, and returns the initially given object.
- *
- *  If no block is given, returns an enumerator.
- *
- *  e.g.:
- *      evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
- *      # => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- *
- */
-static VALUE
-enum_each_with_object(VALUE obj, SEL sel, VALUE memo)
-{
-    RETURN_ENUMERATOR(obj, 1, &memo);
-
-    rb_objc_block_call(obj, selEach, 0, 0, each_with_object_i, (VALUE)memo);
-
-    return memo;
-}
-
-static VALUE
-zip_ary(VALUE val, NODE *memo, int argc, VALUE *argv)
-{
-    volatile VALUE result = memo->u1.value;
-    volatile VALUE args = memo->u2.value;
-    int n = memo->u3.cnt++;
-    volatile VALUE tmp;
-    int i;
-
-    tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
-    rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
-    for (i=0; i<RARRAY_LEN(args); i++) {
-	VALUE e = RARRAY_AT(args, i);
-
-	if (RARRAY_LEN(e) <= n) {
-	    rb_ary_push(tmp, Qnil);
-	}
-	else {
-	    rb_ary_push(tmp, RARRAY_AT(e, n));
-	}
-    }
-    if (NIL_P(result)) {
-	rb_yield(tmp);
-    }
-    else {
-	rb_ary_push(result, tmp);
-    }
-    return Qnil;
-}
-
-static VALUE
-call_next(VALUE *v)
-{
-    return v[0] = rb_funcall(v[1], id_next, 0, 0);
-}
-
-static VALUE
-call_stop(VALUE *v)
-{
-    return v[0] = Qundef;
-}
-
-static VALUE
-zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
-{
-    volatile VALUE result = memo->u1.value;
-    volatile VALUE args = memo->u2.value;
-    volatile VALUE tmp;
-    int i;
-
-    tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
-    rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
-    for (i=0; i<RARRAY_LEN(args); i++) {
-	if (NIL_P(RARRAY_AT(args, i))) {
-	    rb_ary_push(tmp, Qnil);
-	}
-	else {
-	    VALUE v[2];
-
-	    v[1] = RARRAY_AT(args, i);
-	    rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
-	    if (v[0] == Qundef) {
-		rb_ary_store(args, i, Qnil);
-		v[0] = Qnil;
-	    }
-	    rb_ary_push(tmp, v[0]);
-	}
-    }
-    if (NIL_P(result)) {
-	rb_yield(tmp);
-    }
-    else {
-	rb_ary_push(result, tmp);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.zip(arg, ...)                   => enumerator
- *     enum.zip(arg, ...) {|arr| block }    => nil
- *
- *  Takes one element from <i>enum</i> and merges corresponding
- *  elements from each <i>args</i>.  This generates a sequence of
- *  <em>n</em>-element arrays, where <em>n</em> is one more than the
- *  count of arguments.  The length of the resulting sequence will be
- *  <code>enum#size</code.  If the size of any argument is less than
- *  <code>enum#size</code>, <code>nil</code> values are supplied. If
- *  a block is given, it is invoked for each output array, otherwise
- *  an array of arrays is returned.
- *
- *     a = [ 4, 5, 6 ]
- *     b = [ 7, 8, 9 ]
- *
- *     [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- *     [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
- *     a.zip([1,2],[8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
- *
- */
-
-static VALUE
-enum_zip(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    int i;
-    ID conv;
-    NODE *memo;
-    VALUE result = Qnil;
-    VALUE args = rb_ary_new4(argc, argv);
-    int allary = Qtrue;
-
-    for (i = 0; i < argc; i++) {
-	VALUE ary = rb_check_array_type(argv[i]);
-	if (NIL_P(ary)) {
-	    allary = Qfalse;
-	    break;
-	}
-	rary_store(args, i, ary);
-    }
-    if (!allary) {
-	conv = rb_intern("to_enum");
-	for (i = 0; i < argc; i++) {
-	    VALUE res = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
-	    rary_store(args, i, res);
-	}
-    }
-    if (!rb_block_given_p()) {
-	result = rb_ary_new();
-    }
-    memo = rb_node_newnode(NODE_MEMO, result, args, 0);
-    rb_objc_block_call(obj, selEach, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
-
-    return result;
-}
-
-static VALUE
-take_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
-{
-    rb_ary_push(arg[0], enum_values_pack(argc, argv));
-    if (--arg[1] == 0) {
-	rb_iter_break();
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.take(n)               => array
- *
- *  Returns first n elements from <i>enum</i>.
- *
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.take(3)             # => [1, 2, 3]
- *
- */
-
-static VALUE
-enum_take(VALUE obj, SEL sel, VALUE n)
-{
-    VALUE args[2];
-    long len = NUM2LONG(n);
-
-    if (len < 0) {
-	rb_raise(rb_eArgError, "attempt to take negative size");
-    }
-
-    if (len == 0) {
-	return rb_ary_new2(0);
-    }
-    args[0] = rb_ary_new();
-    args[1] = len;
-    rb_objc_block_call(obj, selEach, 0, 0, take_i, (VALUE)args);
-    return args[0];
-}
-
-
-static VALUE
-take_while_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
-{
-    if (!RTEST(enum_yield(argc, argv))) {
-	rb_iter_break();
-    }
-    rb_ary_push(*ary, enum_values_pack(argc, argv));
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.take_while {|arr| block }   => array
- *
- *  Passes elements to the block until the block returns nil or false,
- *  then stops iterating and returns an array of all prior elements.
- *
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.take_while {|i| i < 3 }   # => [1, 2]
- *
- */
-
-static VALUE
-enum_take_while(VALUE obj, SEL sel)
-{
-    VALUE ary;
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-    ary = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, take_while_i, (VALUE)&ary);
-    return ary;
-}
-
-static VALUE
-drop_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
-{
-    if (arg[1] == 0) {
-	rb_ary_push(arg[0], enum_values_pack(argc, argv));
-    }
-    else {
-	arg[1]--;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.drop(n)               => array
- *
- *  Drops first n elements from <i>enum</i>, and returns rest elements
- *  in an array.
- *
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.drop(3)             # => [4, 5, 0]
- *
- */
-
-static VALUE
-enum_drop(VALUE obj, SEL sel, VALUE n)
-{
-    VALUE args[2];
-    long len = NUM2LONG(n);
-
-    if (len < 0) {
-	rb_raise(rb_eArgError, "attempt to drop negative size");
-    }
-
-    args[1] = len;
-    args[0] = rb_ary_new();
-    rb_objc_block_call(obj, selEach, 0, 0, drop_i, (VALUE)args);
-    return args[0];
-}
-
-
-static VALUE
-drop_while_i(VALUE i, VALUE *args, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    if (!args[1] && !RTEST(rb_yield(i))) {
-	args[1] = Qtrue;
-    }
-    if (args[1]) {
-	rb_ary_push(args[0], i);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.drop_while {|arr| block }   => array
- *
- *  Drops elements up to, but not including, the first element for
- *  which the block returns nil or false and returns an array
- *  containing the remaining elements.
- *
- *     a = [1, 2, 3, 4, 5, 0]
- *     a.drop_while {|i| i < 3 }   # => [3, 4, 5, 0]
- *
- */
-
-static VALUE
-enum_drop_while(VALUE obj, SEL sel)
-{
-    VALUE args[2];
-
-    RETURN_ENUMERATOR(obj, 0, 0);
-    args[0] = rb_ary_new();
-    args[1] = Qfalse;
-    rb_objc_block_call(obj, selEach, 0, 0, drop_while_i, (VALUE)args);
-    return args[0];
-}
-
-static VALUE
-cycle_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    ENUM_WANT_SVALUE();
-
-    rb_ary_push(ary, i);
-    rb_yield(i);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     enum.cycle {|obj| block }
- *     enum.cycle(n) {|obj| block }
- *
- *  Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
- *  times or forever if none or nil is given.  If a non-positive
- *  number is given or the collection is empty, does nothing.  Returns
- *  nil if the loop has finished without getting interrupted.
- *
- *  Enumerable#cycle saves elements in an internal array so changes
- *  to <i>enum</i> after the first pass have no effect.
- *
- *     a = ["a", "b", "c"]
- *     a.cycle {|x| puts x }  # print, a, b, c, a, b, c,.. forever.
- *     a.cycle(2) {|x| puts x }  # print, a, b, c, a, b, c.
- *
- */
-
-static VALUE
-enum_cycle(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE ary;
-    VALUE nv = Qnil;
-    long n, i, len;
-
-    rb_scan_args(argc, argv, "01", &nv);
-
-    RETURN_ENUMERATOR(obj, argc, argv);
-    if (NIL_P(nv)) {
-        n = -1;
-    }
-    else {
-        n = NUM2LONG(nv);
-        if (n <= 0) return Qnil;
-    }
-    ary = rb_ary_new();
-#if !WITH_OBJC
-    RBASIC(ary)->klass = 0;
-#endif
-    rb_objc_block_call(obj, selEach, 0, 0, cycle_i, ary);
-    len = RARRAY_LEN(ary);
-    if (len == 0) return Qnil;
-    while (n < 0 || 0 < --n) {
-        for (i=0; i<len; i++) {
-            rb_yield(RARRAY_AT(ary, i));
-	    RETURN_IF_BROKEN();
-        }
-    }
-    return Qnil;		/* not reached */
-}
-
-/*
- *  The <code>Enumerable</code> mixin provides collection classes with
- *  several traversal and searching methods, and with the ability to
- *  sort. The class must provide a method <code>each</code>, which
- *  yields successive members of the collection. If
- *  <code>Enumerable#max</code>, <code>#min</code>, or
- *  <code>#sort</code> is used, the objects in the collection must also
- *  implement a meaningful <code><=></code> operator, as these methods
- *  rely on an ordering between members of the collection.
- */
-
-void
-Init_Enumerable(void)
-{
-    rb_mEnumerable = rb_define_module("Enumerable");
-
-    rb_objc_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
-    rb_objc_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
-
-    rb_objc_define_method(rb_mEnumerable,"sort", enum_sort, 0);
-    rb_objc_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
-    rb_objc_define_method(rb_mEnumerable,"grep", enum_grep, 1);
-#if WITH_OBJC
-    /* FIXME we cannot define count because it overlaps with
-     * NSArray#count, NSDictionary#count, etc... 
-     */
-    rb_objc_define_method(rb_mEnumerable,"_count", enum_count, -1);
-#else
-    rb_objc_define_method(rb_mEnumerable,"count", enum_count, -1);
-#endif
-    rb_objc_define_method(rb_mEnumerable, "find", enum_find, -1);
-    rb_objc_define_method(rb_mEnumerable, "detect", enum_find, -1);
-    rb_objc_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
-    rb_objc_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
-    rb_objc_define_method(rb_mEnumerable, "select", enum_find_all, 0);
-    rb_objc_define_method(rb_mEnumerable, "reject", enum_reject, 0);
-    rb_objc_define_method(rb_mEnumerable, "collect", enum_collect, 0);
-    rb_objc_define_method(rb_mEnumerable, "map", enum_collect, 0);
-    rb_objc_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
-    rb_objc_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
-    rb_objc_define_method(rb_mEnumerable, "inject", enum_inject, -1);
-    rb_objc_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
-    rb_objc_define_method(rb_mEnumerable, "partition", enum_partition, 0);
-    rb_objc_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
-    rb_objc_define_method(rb_mEnumerable, "first", enum_first, -1);
-    rb_objc_define_method(rb_mEnumerable, "all?", enum_all, 0);
-    rb_objc_define_method(rb_mEnumerable, "any?", enum_any, 0);
-    rb_objc_define_method(rb_mEnumerable, "one?", enum_one, 0);
-    rb_objc_define_method(rb_mEnumerable, "none?", enum_none, 0);
-    rb_objc_define_method(rb_mEnumerable, "min", enum_min, 0);
-    rb_objc_define_method(rb_mEnumerable, "max", enum_max, 0);
-    rb_objc_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
-    rb_objc_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
-    rb_objc_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
-    rb_objc_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
-    rb_objc_define_method(rb_mEnumerable, "member?", enum_member, 1);
-    rb_objc_define_method(rb_mEnumerable, "include?", enum_member, 1);
-    rb_objc_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
-    rb_objc_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
-    rb_objc_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
-    rb_objc_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
-    rb_objc_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
-    rb_objc_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
-    rb_objc_define_method(rb_mEnumerable, "zip", enum_zip, -1);
-    rb_objc_define_method(rb_mEnumerable, "take", enum_take, 1);
-    rb_objc_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
-    rb_objc_define_method(rb_mEnumerable, "drop", enum_drop, 1);
-    rb_objc_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
-    rb_objc_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
-
-    id_eqq  = rb_intern("===");
-    id_each = rb_intern("each");
-    id_next = rb_intern("next");
-    id_size = rb_intern("size");
-}
-

Deleted: MacRuby/trunk/enumerator.c
===================================================================
--- MacRuby/trunk/enumerator.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/enumerator.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,505 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2001-2003 Akinori MUSHA
- */
-
-#include "macruby_internal.h"
-#include "id.h"
-#include "ruby/node.h"
-#include "vm.h"
-
-/*
- * Document-class: Enumerable::Enumerator
- *
- * A class which provides a method `each' to be used as an Enumerable
- * object.
- */
-VALUE rb_cEnumerator;
-static VALUE sym_each;
-
-VALUE rb_eStopIteration;
-
-struct enumerator {
-    VALUE obj;
-    SEL   sel;
-    VALUE args;
-    VALUE fib;
-    VALUE dst;
-    VALUE no_next;
-};
-
-static struct enumerator *
-enumerator_ptr(VALUE obj)
-{
-    struct enumerator *ptr;
-
-    Data_Get_Struct(obj, struct enumerator, ptr);
-#if 0
-    if (RDATA(obj)->dmark != enumerator_mark) {
-	rb_raise(rb_eTypeError,
-		 "wrong argument type %s (expected %s)",
-		 rb_obj_classname(obj), rb_class2name(rb_cEnumerator));
-    }
-#endif
-    if (!ptr) {
-	rb_raise(rb_eArgError, "uninitialized enumerator");
-    }
-    return ptr;
-}
-
-/*
- *  call-seq:
- *    obj.to_enum(method = :each, *args)
- *    obj.enum_for(method = :each, *args)
- *
- *  Returns Enumerable::Enumerator.new(self, method, *args).
- *
- *  e.g.:
- *
- *     str = "xyz"
- *
- *     enum = str.enum_for(:each_byte)
- *     a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- *     # protects an array from being modified
- *     a = [1, 2, 3]
- *     some_method(a.to_enum)
- *
- */
-static VALUE
-obj_to_enum(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE meth = sym_each;
-
-    if (argc > 0) {
-	--argc;
-	meth = *argv++;
-    }
-
-    ID meth_id = rb_to_id(meth);
-    SEL enum_sel = rb_vm_id_to_sel(meth_id, argc);
-    return rb_enumeratorize(obj, enum_sel, argc, argv);
-}
-
-static VALUE
-each_slice_i(VALUE val, VALUE *memo)
-{
-    VALUE ary = memo[0];
-    VALUE v = Qnil;
-    long size = (long)memo[1];
-
-    rb_ary_push(ary, val);
-
-    if (RARRAY_LEN(ary) == size) {
-	v = rb_yield(ary);
-	memo[0] = rb_ary_new2(size);
-    }
-
-    return v;
-}
-
-/*
- *  call-seq:
- *    e.each_slice(n) {...}
- *    e.each_slice(n)
- *
- *  Iterates the given block for each slice of <n> elements.  If no
- *  block is given, returns an enumerator.
- *
- *  e.g.:
- *      (1..10).each_slice(3) {|a| p a}
- *      # outputs below
- *      [1, 2, 3]
- *      [4, 5, 6]
- *      [7, 8, 9]
- *      [10]
- *
- */
-static VALUE
-enum_each_slice(VALUE obj, SEL sel, VALUE n)
-{
-    long size = NUM2LONG(n);
-    VALUE args[2], ary;
-
-    if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
-    RETURN_ENUMERATOR(obj, 1, &n);
-    args[0] = rb_ary_new2(size);
-    args[1] = (VALUE)size;
-
-    rb_objc_block_call(obj, selEach, 0, 0, each_slice_i, (VALUE)args);
-
-    ary = args[0];
-    if (RARRAY_LEN(ary) > 0) rb_yield(ary);
-
-    return Qnil;
-}
-
-static VALUE
-each_cons_i(VALUE val, VALUE *memo)
-{
-    VALUE ary = memo[0];
-    VALUE v = Qnil;
-    long size = (long)memo[1];
-
-    if (RARRAY_LEN(ary) == size) {
-	rb_ary_shift(ary);
-    }
-    rb_ary_push(ary, val);
-    if (RARRAY_LEN(ary) == size) {
-	v = rb_yield(rb_ary_dup(ary));
-    }
-    return v;
-}
-
-/*
- *  call-seq:
- *    each_cons(n) {...}
- *    each_cons(n)
- *
- *  Iterates the given block for each array of consecutive <n>
- *  elements.  If no block is given, returns an enumerator.a
- *
- *  e.g.:
- *      (1..10).each_cons(3) {|a| p a}
- *      # outputs below
- *      [1, 2, 3]
- *      [2, 3, 4]
- *      [3, 4, 5]
- *      [4, 5, 6]
- *      [5, 6, 7]
- *      [6, 7, 8]
- *      [7, 8, 9]
- *      [8, 9, 10]
- *
- */
-static VALUE
-enum_each_cons(VALUE obj, SEL sel, VALUE n)
-{
-    long size = NUM2LONG(n);
-    VALUE args[2];
-
-    if (size <= 0) rb_raise(rb_eArgError, "invalid size");
-    RETURN_ENUMERATOR(obj, 1, &n);
-    args[0] = rb_ary_new2(size);
-    args[1] = (VALUE)size;
-
-    rb_objc_block_call(obj, selEach, 0, 0, each_cons_i, (VALUE)args);
-
-    return Qnil;
-}
-
-static VALUE
-enumerator_allocate(VALUE klass)
-{
-    struct enumerator *ptr;
-    return Data_Make_Struct(klass, struct enumerator,
-			    NULL, -1, ptr);
-}
-
-static VALUE
-enumerator_each_i(VALUE v, VALUE enum_obj, int argc, VALUE *argv)
-{
-    return rb_yield_values2(argc, argv);
-}
-
-static VALUE
-enumerator_init(VALUE enum_obj, VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    struct enumerator *ptr = enumerator_ptr(enum_obj);
-
-    GC_WB(&ptr->obj, obj);
-    ptr->sel = sel;
-    if (argc > 0) {
-	GC_WB(&ptr->args, rb_ary_new4(argc, argv));
-    }
-    ptr->fib = 0;
-    ptr->dst = Qnil;
-    ptr->no_next = Qfalse;
-
-    return enum_obj;
-}
-
-/*
- *  call-seq:
- *    Enumerable::Enumerator.new(obj, method = :each, *args)
- *
- *  Creates a new Enumerable::Enumerator object, which is to be
- *  used as an Enumerable object using the given object's given
- *  method with the given arguments.
- *
- *  Use of this method is not discouraged.  Use Kernel#enum_for()
- *  instead.
- */
-static VALUE
-enumerator_initialize(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE recv, meth = sym_each;
-
-    if (argc == 0)
-	rb_raise(rb_eArgError, "wrong number of argument (0 for 1)");
-    recv = *argv++;
-    if (--argc) {
-	meth = *argv++;
-	--argc;
-    }
-    ID meth_id = rb_to_id(meth);
-    SEL meth_sel = rb_vm_id_to_sel(meth_id, argc);
-    return enumerator_init(obj, recv, meth_sel, argc, argv);
-}
-
-/* :nodoc: */
-static VALUE
-enumerator_init_copy(VALUE obj, SEL sel, VALUE orig)
-{
-    struct enumerator *ptr0, *ptr1;
-
-    ptr0 = enumerator_ptr(orig);
-    if (ptr0->fib) {
-	/* Fibers cannot be copied */
-	rb_raise(rb_eTypeError, "can't copy execution context");
-    }
-    ptr1 = enumerator_ptr(obj);
-
-    GC_WB(&ptr1->obj, ptr0->obj);
-    ptr1->sel = ptr0->sel;
-    if (ptr0->args != 0) {
-	GC_WB(&ptr1->args, ptr0->args);
-    }
-    ptr1->fib  = 0;
-
-    return obj;
-}
-
-VALUE
-rb_enumeratorize(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, sel,
-	    argc, argv);
-}
-
-static VALUE
-enumerator_block_call(VALUE obj, VALUE (*func)(ANYARGS), VALUE arg)
-{
-    struct enumerator *e;
-    int argc = 0;
-    const VALUE *argv = 0;
-
-    e = enumerator_ptr(obj);
-    if (e->args != 0) {
-	argc = RARRAY_LEN(e->args);
-	argv = RARRAY_PTR(e->args);
-    }
-    return rb_objc_block_call(e->obj, e->sel, argc, (VALUE *)argv,
-	    func, arg);
-}
-
-/*
- *  call-seq:
- *    enum.each {...}
- *
- *  Iterates the given block using the object and the method specified
- *  in the first place.  If no block is given, returns self.
- *
- */
-static VALUE
-enumerator_each(VALUE obj, SEL sel)
-{
-    if (!rb_block_given_p()) {
-	return obj;
-    }
-    return enumerator_block_call(obj, enumerator_each_i, obj);
-}
-
-static VALUE
-enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv)
-{
-    VALUE idx;
-    VALUE *memo = (VALUE *)m;
-
-    idx = INT2FIX(*memo);
-    ++*memo;
-
-    if (argc <= 1)
-	return rb_yield_values(2, val, idx);
-
-    return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
-}
-
-/*
- *  call-seq:
- *    e.with_index(offset = 0) {|(*args), idx| ... }
- *    e.with_index
- *
- *  Iterates the given block for each elements with an index, which
- *  starts from +offset+.  If no block is given, returns an enumerator.
- *
- */
-static VALUE
-enumerator_with_index(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE memo;
-
-    rb_scan_args(argc, argv, "01", &memo);
-    RETURN_ENUMERATOR(obj, argc, argv);
-    memo = NIL_P(memo) ? 0 : (VALUE)NUM2LONG(memo);
-    return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)&memo);
-}
-
-/*
- *  call-seq:
- *    e.each_with_index {|(*args), idx| ... }
- *    e.each_with_index
- *
- *  Same as Enumeartor#with_index, except each_with_index does not
- *  receive an offset argument.
- *
- */
-static VALUE
-enumerator_each_with_index(VALUE obj, SEL sel)
-{
-    return enumerator_with_index(obj, sel, 0, NULL);
-}
-
-static VALUE
-enumerator_with_object_i(VALUE val, VALUE memo, int argc, VALUE *argv)
-{
-    if (argc <= 1) {
-	return rb_yield_values(2, val, memo);
-    }
-
-    return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
-}
-
-/*
- *  call-seq:
- *    e.with_object(obj) {|(*args), memo_obj| ... }
- *    e.with_object(obj)
- *
- *  Iterates the given block for each element with an arbitrary
- *  object given, and returns the initially given object.
- *
- *  If no block is given, returns an enumerator.
- *
- */
-static VALUE
-enumerator_with_object(VALUE obj, SEL sel, VALUE memo)
-{
-    RETURN_ENUMERATOR(obj, 1, &memo);
-    enumerator_block_call(obj, enumerator_with_object_i, memo);
-    return memo;
-}
-
-#if 0
-static VALUE
-next_ii(VALUE i, VALUE obj, int argc, VALUE *argv)
-{
-    rb_fiber_yield(argc, argv);
-    return Qnil;
-}
-
-static VALUE
-next_i(VALUE curr, VALUE obj)
-{
-    struct enumerator *e = enumerator_ptr(obj);
-    VALUE rnil = Qnil;
-
-    rb_block_call(obj, rb_intern("each"), 0, 0, next_ii, obj);
-    e->no_next = Qtrue;
-    return rb_fiber_yield(1, &rnil);
-}
-
-static void
-next_init(VALUE obj, struct enumerator *e)
-{
-    VALUE curr = rb_fiber_current();
-    e->dst = curr;
-    e->fib = rb_fiber_new(next_i, obj);
-}
-#endif
-
-/*
- * call-seq:
- *   e.next   => object
- *
- * Returns the next object in the enumerator, and move the internal
- * position forward.  When the position reached at the end, internal
- * position is rewinded then StopIteration is raised.
- *
- * Note that enumeration sequence by next method does not affect other
- * non-external enumeration methods, unless underlying iteration
- * methods itself has side-effect, e.g. IO#each_line.
- *
- */
-
-static VALUE
-enumerator_next(VALUE obj, SEL sel)
-{
-    // TODO
-#if 0
-    struct enumerator *e = enumerator_ptr(obj);
-    VALUE curr, v;
-    curr = rb_fiber_current();
-
-    if (!e->fib || !rb_fiber_alive_p(e->fib)) {
-	next_init(obj, e);
-    }
-
-    v = rb_fiber_resume(e->fib, 1, &curr);
-    if (e->no_next) {
-	e->fib = 0;
-	e->dst = Qnil;
-	e->no_next = Qfalse;
-	rb_raise(rb_eStopIteration, "iteration reached at end");
-    }
-    return v;
-#endif
-    return Qnil;
-}
-
-/*
- * call-seq:
- *   e.rewind   => e
- *
- * Rewinds the enumeration sequence by the next method.
- */
-
-static VALUE
-enumerator_rewind(VALUE obj, SEL sel)
-{
-    struct enumerator *e = enumerator_ptr(obj);
-
-    e->fib = 0;
-    e->dst = Qnil;
-    e->no_next = Qfalse;
-    return obj;
-}
-
-void
-Init_Enumerator(void)
-{
-    rb_objc_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
-    rb_objc_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
-
-    rb_objc_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
-    rb_objc_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
-
-    rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
-    rb_include_module(rb_cEnumerator, rb_mEnumerable);
-
-    rb_objc_define_method(*(VALUE *)rb_cEnumerator, "alloc", enumerator_allocate, 0);
-    rb_objc_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
-    rb_objc_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
-    rb_objc_define_method(rb_cEnumerator, "each", enumerator_each, 0);
-    rb_objc_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0);
-    rb_objc_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
-    rb_objc_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1);
-    rb_objc_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
-    rb_objc_define_method(rb_cEnumerator, "next", enumerator_next, 0);
-    rb_objc_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
-
-    rb_eStopIteration   = rb_define_class("StopIteration", rb_eIndexError);
-
-    sym_each	 	= ID2SYM(rb_intern("each"));
-}

Deleted: MacRuby/trunk/env.c
===================================================================
--- MacRuby/trunk/env.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/env.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,739 +0,0 @@
-/* 
- * MacRuby implementation of ENV.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "ruby/node.h"
-#include "vm.h"
-
-char ***_NSGetEnviron();
-
-static VALUE envtbl;
-
-static int path_tainted = -1;
-
-static char **origenviron;
-#define GET_ENVIRON() (*_NSGetEnviron())
-
-static VALUE
-to_hash(VALUE hash)
-{
-    return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
-}
-
-static VALUE
-env_str_new(const char *ptr, long len)
-{
-    VALUE str = rb_tainted_str_new(ptr, len);
-    rb_obj_freeze(str);
-    return str;
-}
-
-static VALUE
-env_str_new2(const char *ptr)
-{
-    if (ptr == NULL) {
-	return Qnil;
-    }
-    return env_str_new(ptr, strlen(ptr));
-}
-
-static VALUE
-env_delete(VALUE obj, VALUE name)
-{
-    rb_secure(4);
-    SafeStringValue(name);
-    const char *nam = RSTRING_PTR(name);
-    if (strlen(nam) != RSTRING_LEN(name)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    const char *val = getenv(nam);
-    if (val != NULL) {
-	VALUE value = env_str_new2(val);
-	ruby_setenv(nam, 0);
-	if (strcmp(nam, PATH_ENV) == 0) {
-	    path_tainted = 0;
-	}
-	return value;
-    }
-    return Qnil;
-}
-
-static VALUE
-env_delete_m(VALUE obj, SEL sel, VALUE name)
-{
-    VALUE val = env_delete(obj, name);
-    if (NIL_P(val) && rb_block_given_p()) {
-	rb_yield(name);
-    }
-    return val;
-}
-
-static VALUE
-rb_f_getenv(VALUE obj, SEL sel, VALUE name)
-{
-    rb_secure(4);
-    SafeStringValue(name);
-    const char *nam = RSTRING_PTR(name);
-    if (strlen(nam) != RSTRING_LEN(name)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    const char *env = getenv(nam);
-    if (env != NULL) {
-	if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted()) {
-	    VALUE str = rb_str_new2(env);
-	    rb_obj_freeze(str);
-	    return str;
-	}
-	return env_str_new2(env);
-    }
-    return Qnil;
-}
-
-static VALUE
-env_fetch(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(4);
-
-    VALUE key, if_none;
-    rb_scan_args(argc, argv, "11", &key, &if_none);
-
-    const bool block_given = rb_block_given_p();
-    if (block_given && argc == 2) {
-	rb_warn("block supersedes default value argument");
-    }
-    SafeStringValue(key);
-    const char *nam = RSTRING_PTR(key);
-    if (strlen(nam) != RSTRING_LEN(key)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    const char *env = getenv(nam);
-    if (env == NULL) {
-	if (block_given) {
-	    return rb_yield(key);
-	}
-	if (argc == 1) {
-	    rb_raise(rb_eKeyError, "key not found");
-	}
-	return if_none;
-    }
-    if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted()) {
-	return rb_str_new2(env);
-    }
-    return env_str_new2(env);
-}
-
-static void
-path_tainted_p(const char *path)
-{
-    path_tainted = rb_path_check(path) ? 0 : 1;
-}
-
-int
-rb_env_path_tainted(void)
-{
-    if (path_tainted < 0) {
-	path_tainted_p(getenv(PATH_ENV));
-    }
-    return path_tainted;
-}
-
-void
-ruby_setenv(const char *name, const char *value)
-{
-    if (value != NULL) {
-	setenv(name, value, 1);
-    }
-    else {
-	unsetenv(name);
-    }
-}
-
-void
-ruby_unsetenv(const char *name)
-{
-    ruby_setenv(name, 0);
-}
-
-static VALUE
-env_aset(VALUE obj, SEL sel, VALUE nm, VALUE val)
-{
-    if (rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "can't change environment variable");
-    }
-
-    if (NIL_P(val)) {
-	env_delete(obj, nm);
-	return Qnil;
-    }
-    StringValue(nm);
-    StringValue(val);
-    const char *name = RSTRING_PTR(nm);
-    const char *value = RSTRING_PTR(val);
-    if (strlen(name) != RSTRING_LEN(nm)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    if (strlen(value) != RSTRING_LEN(val)) {
-	rb_raise(rb_eArgError, "bad environment variable value");
-    }
-
-    ruby_setenv(name, value);
-    if (strcmp(name, PATH_ENV) == 0) {
-	if (OBJ_TAINTED(val)) {
-	    /* already tainted, no check */
-	    path_tainted = 1;
-	    return val;
-	}
-	else {
-	    path_tainted_p(value);
-	}
-    }
-    return val;
-}
-
-static VALUE
-env_keys(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE ary = rb_ary_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_ary_push(ary, env_str_new(*env, s - *env));
-	}
-	env++;
-    }
-    return ary;
-}
-
-static VALUE
-env_each_key(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-    VALUE keys = env_keys(Qnil, 0);	/* rb_secure(4); */
-    for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
-	rb_yield(RARRAY_AT(keys, i));
-	RETURN_IF_BROKEN();
-    }
-    return ehash;
-}
-
-static VALUE
-env_values(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE ary = rb_ary_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_ary_push(ary, env_str_new2(s + 1));
-	}
-	env++;
-    }
-    return ary;
-}
-
-static VALUE
-env_each_value(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-    VALUE values = env_values(Qnil, 0);	/* rb_secure(4); */
-    for (long i = 0, count = RARRAY_LEN(values); i < count; i++) {
-	rb_yield(RARRAY_AT(values, i));
-	RETURN_IF_BROKEN();
-    }
-    return ehash;
-}
-
-static VALUE
-env_each_pair(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-
-    rb_secure(4);
-    VALUE ary = rb_ary_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_ary_push(ary, env_str_new(*env, s - *env));
-	    rb_ary_push(ary, env_str_new2(s + 1));
-	}
-	env++;
-    }
-
-    for (long i = 0, count = RARRAY_LEN(ary); i < count; i += 2) {
-	rb_yield(rb_assoc_new(RARRAY_AT(ary, i), RARRAY_AT(ary, i + 1)));
-	RETURN_IF_BROKEN();
-    }
-    return ehash;
-}
-
-static VALUE
-env_reject_bang(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-    VALUE keys = env_keys(Qnil, 0);	/* rb_secure(4); */
-    bool deleted = false;
-    for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
-	VALUE key = RARRAY_AT(keys, i);
-	VALUE val = rb_f_getenv(Qnil, 0, key);
-	if (!NIL_P(val)) {
-	    VALUE v = rb_yield_values(2, key, val);
-	    RETURN_IF_BROKEN();
-	    if (RTEST(v)) {
-		rb_obj_untaint(key);
-		env_delete(Qnil, key);
-		deleted = true;
-	    }
-	}
-    }
-    return deleted ? envtbl : Qnil;
-}
-
-static VALUE
-env_delete_if(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-    env_reject_bang(ehash, 0);
-    return envtbl;
-}
-
-static VALUE
-env_values_at(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(4);
-    VALUE result = rb_ary_new();
-    for (long i = 0; i < argc; i++) {
-	rb_ary_push(result, rb_f_getenv(Qnil, 0, argv[i]));
-    }
-    return result;
-}
-
-static VALUE
-env_select(VALUE ehash, SEL sel)
-{
-    RETURN_ENUMERATOR(ehash, 0, 0);
-    rb_secure(4);
-    VALUE result = rb_hash_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    VALUE k = env_str_new(*env, s - *env);
-	    VALUE v = env_str_new2(s + 1);
-	    VALUE v2 = rb_yield_values(2, k, v);
-	    RETURN_IF_BROKEN();
-	    if (RTEST(v2)) {
-		rb_hash_aset(result, k, v);
-	    }
-	}
-	env++;
-    }
-    return result;
-}
-
-static VALUE
-rb_env_clear_imp(VALUE rcv, SEL sel)
-{
-    VALUE keys = env_keys(Qnil, 0);	/* rb_secure(4); */
-    for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
-	VALUE val = rb_f_getenv(Qnil, 0, RARRAY_AT(keys, i));
-	if (!NIL_P(val)) {
-	    env_delete(Qnil, RARRAY_AT(keys, i));
-	}
-    }
-    return envtbl;
-}
-
-VALUE
-rb_env_clear(void)
-{
-    return rb_env_clear_imp(Qnil, 0);
-}
-
-static VALUE
-env_to_s(VALUE rcv, SEL sel)
-{
-    return rb_usascii_str_new2("ENV");
-}
-
-static VALUE
-env_inspect(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE str = rb_str_buf_new2("{");
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-
-	if (env != GET_ENVIRON()) {
-	    rb_str_buf_cat2(str, ", ");
-	}
-	if (s != NULL) {
-	    rb_str_buf_cat2(str, "\"");
-	    rb_str_buf_cat(str, *env, s - *env);
-	    rb_str_buf_cat2(str, "\"=>");
-	    VALUE i = rb_inspect(rb_str_new2(s + 1));
-	    rb_str_buf_append(str, i);
-	}
-	env++;
-    }
-    rb_str_buf_cat2(str, "}");
-    OBJ_TAINT(str);
-
-    return str;
-}
-
-static VALUE
-env_to_a(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE ary = rb_ary_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s - *env),
-			env_str_new2(s + 1)));
-	}
-	env++;
-    }
-    return ary;
-}
-
-static VALUE
-env_none(VALUE rcv, SEL sel)
-{
-    return Qnil;
-}
-
-static VALUE
-env_size(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    char **env = GET_ENVIRON();
-    int i = 0;
-    while (env[i] != NULL) {
-	i++;
-    }
-    return INT2FIX(i);
-}
-
-static VALUE
-env_empty_p(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    char **env = GET_ENVIRON();
-    if (env[0] == NULL) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-static VALUE
-env_has_key(VALUE env, SEL sel, VALUE key)
-{
-    rb_secure(4);
-
-    const char *s = StringValuePtr(key);
-    if (strlen(s) != RSTRING_LEN(key)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    if (getenv(s) != NULL) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-static VALUE
-env_assoc(VALUE env, SEL sel, VALUE key)
-{
-    rb_secure(4);
-
-    const char *s = StringValuePtr(key);
-    if (strlen(s) != RSTRING_LEN(key)) {
-	rb_raise(rb_eArgError, "bad environment variable name");
-    }
-    const char *e = getenv(s);
-    if (e != NULL) {
-	return rb_assoc_new(key, rb_tainted_str_new2(e));
-    }
-    return Qnil;
-}
-
-static VALUE
-env_has_value(VALUE dmy, SEL sel, VALUE obj)
-{
-    rb_secure(4);
-
-    obj = rb_check_string_type(obj);
-    if (NIL_P(obj)) {
-	return Qnil;
-    }
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s++ != NULL) {
-	    const long len = strlen(s);
-	    if (RSTRING_LEN(obj) == len
-		    && strncmp(s, RSTRING_PTR(obj), len) == 0) {
-		return Qtrue;
-	    }
-	}
-	env++;
-    }
-    return Qfalse;
-}
-
-static VALUE
-env_rassoc(VALUE dmy, SEL sel, VALUE obj)
-{
-    rb_secure(4);
-
-    obj = rb_check_string_type(obj);
-    if (NIL_P(obj)) {
-	return Qnil;
-    }
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s++ != NULL) {
-	    const long len = strlen(s);
-	    if (RSTRING_LEN(obj) == len
-		    && strncmp(s, RSTRING_PTR(obj), len) == 0) {
-		return rb_assoc_new(rb_tainted_str_new(*env, s - *env - 1),
-			obj);
-	    }
-	}
-	env++;
-    }
-    return Qnil;
-}
-
-static VALUE
-env_key(VALUE dmy, SEL sel, VALUE value)
-{
-    rb_secure(4);
-
-    StringValue(value);
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s++ != NULL) {
-	    const long len = strlen(s);
-	    if (RSTRING_LEN(value) == len
-		    && strncmp(s, RSTRING_PTR(value), len) == 0) {
-		return env_str_new(*env, s - *env - 1);
-	    }
-	}
-	env++;
-    }
-    return Qnil;
-}
-
-static VALUE
-env_index(VALUE dmy, SEL sel, VALUE value)
-{
-    rb_warn("ENV.index is deprecated; use ENV.key");
-    return env_key(dmy, 0, value);
-}
-
-static VALUE
-env_to_hash(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE hash = rb_hash_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_hash_aset(hash, env_str_new(*env, s - *env),
-		    env_str_new2(s + 1));
-	}
-	env++;
-    }
-    return hash;
-}
-
-static VALUE
-env_reject(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    RETURN_ENUMERATOR(rcv, 0, 0);
-
-    VALUE hash = rb_hash_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    VALUE key = env_str_new(*env, s - *env);
-	    VALUE val = env_str_new2(s + 1);
-	    if (!RTEST(rb_yield_values(2, key, val))) {
-		rb_hash_aset(hash, key, val);
-	    }
-	}
-	env++;
-    }
-    return hash;
-}
-
-static VALUE
-env_shift(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    char **env = GET_ENVIRON();
-    if (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    VALUE key = env_str_new(*env, s - *env);
-	    VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
-	    env_delete(Qnil, key);
-	    return rb_assoc_new(key, val);
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-env_invert(VALUE rcv, SEL sel)
-{
-    rb_secure(4);
-
-    VALUE hash = rb_hash_new();
-    char **env = GET_ENVIRON();
-    while (*env != NULL) {
-	const char *s = strchr(*env, '=');
-	if (s != NULL) {
-	    rb_hash_aset(hash, env_str_new2(s + 1),
-		    env_str_new(*env, s - *env));
-	}
-	env++;
-    }
-    return hash;
-}
-
-static int
-env_replace_i(VALUE key, VALUE val, VALUE keys)
-{
-    if (key != Qundef) {
-	env_aset(Qnil, 0, key, val);
-	if (rb_ary_includes(keys, key)) {
-	    rb_ary_delete(keys, key);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-env_replace(VALUE env, SEL sel, VALUE hash)
-{
-    VALUE keys = env_keys(Qnil, 0);	/* rb_secure(4); */
-    if (env == hash) {
-	return env;
-    }
-    hash = to_hash(hash);
-    rb_hash_foreach(hash, env_replace_i, keys);
-
-    for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
-	env_delete(env, RARRAY_AT(keys, i));
-    }
-    return env;
-}
-
-static int
-env_update_i(VALUE key, VALUE val, VALUE ctx)
-{
-    if (key != Qundef) {
-	if (rb_block_given_p()) {
-	    val = rb_yield_values(3, key, rb_f_getenv(Qnil, 0, key), val);
-	    RETURN_IF_BROKEN();
-	}
-	env_aset(Qnil, 0, key, val);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-env_update(VALUE env, SEL sel, VALUE hash)
-{
-    rb_secure(4);
-    if (env == hash) {
-	return env;
-    }
-    hash = to_hash(hash);
-    rb_hash_foreach(hash, env_update_i, 0);
-    return env;
-}
-
-void
-Init_ENV(void)
-{
-    origenviron = GET_ENVIRON();
-    envtbl = rb_obj_alloc(rb_cObject);
-    rb_extend_object(envtbl, rb_mEnumerable);
-
-    VALUE klass = rb_singleton_class(envtbl);
-
-    rb_objc_define_method(klass, "[]", rb_f_getenv, 1);
-    rb_objc_define_method(klass, "fetch", env_fetch, -1);
-    rb_objc_define_method(klass, "[]=", env_aset, 2);
-    rb_objc_define_method(klass, "store", env_aset, 2);
-    rb_objc_define_method(klass, "each", env_each_pair, 0);
-    rb_objc_define_method(klass, "each_pair", env_each_pair, 0);
-    rb_objc_define_method(klass, "each_key", env_each_key, 0);
-    rb_objc_define_method(klass, "each_value", env_each_value, 0);
-    rb_objc_define_method(klass, "delete", env_delete_m, 1);
-    rb_objc_define_method(klass, "delete_if", env_delete_if, 0);
-    rb_objc_define_method(klass, "clear", rb_env_clear_imp, 0);
-    rb_objc_define_method(klass, "reject", env_reject, 0);
-    rb_objc_define_method(klass, "reject!", env_reject_bang, 0);
-    rb_objc_define_method(klass, "select", env_select, 0);
-    rb_objc_define_method(klass, "shift", env_shift, 0);
-    rb_objc_define_method(klass, "invert", env_invert, 0);
-    rb_objc_define_method(klass, "replace", env_replace, 1);
-    rb_objc_define_method(klass, "update", env_update, 1);
-    rb_objc_define_method(klass, "inspect", env_inspect, 0);
-    rb_objc_define_method(klass, "rehash", env_none, 0);
-    rb_objc_define_method(klass, "to_a", env_to_a, 0);
-    rb_objc_define_method(klass, "to_s", env_to_s, 0);
-    rb_objc_define_method(klass, "key", env_key, 1);
-    rb_objc_define_method(klass, "index", env_index, 1);
-    rb_objc_define_method(klass, "size", env_size, 0);
-    rb_objc_define_method(klass, "length", env_size, 0);
-    rb_objc_define_method(klass, "empty?", env_empty_p, 0);
-    rb_objc_define_method(klass, "keys", env_keys, 0);
-    rb_objc_define_method(klass, "values", env_values, 0);
-    rb_objc_define_method(klass, "values_at", env_values_at, -1);
-    rb_objc_define_method(klass, "include?", env_has_key, 1);
-    rb_objc_define_method(klass, "member?", env_has_key, 1);
-    rb_objc_define_method(klass, "has_key?", env_has_key, 1);
-    rb_objc_define_method(klass, "has_value?", env_has_value, 1);
-    rb_objc_define_method(klass, "key?", env_has_key, 1);
-    rb_objc_define_method(klass, "value?", env_has_value, 1);
-    rb_objc_define_method(klass, "to_hash", env_to_hash, 0);
-    rb_objc_define_method(klass, "assoc", env_assoc, 1);
-    rb_objc_define_method(klass, "rassoc", env_rassoc, 1);
-
-    rb_define_global_const("ENV", envtbl);
-}

Deleted: MacRuby/trunk/error.c
===================================================================
--- MacRuby/trunk/error.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/error.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1698 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/st.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "id.h"
-#include "class.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-
-extern const char ruby_description[];
-
-static int
-err_position_0(char *buf, long len, const char *file, int line)
-{
-    if (!file) {
-	return 0;
-    }
-    else if (line == 0) {
-	return snprintf(buf, len, "%s: ", file);
-    }
-    else {
-	return snprintf(buf, len, "%s:%d: ", file, line);
-    }
-}
-
-static int
-err_position(char *buf, long len)
-{
-    return err_position_0(buf, len, rb_sourcefile(), rb_sourceline());
-}
-
-static void
-err_snprintf(char *buf, long len, const char *fmt, va_list args)
-{
-    long n;
-
-    n = err_position(buf, len);
-    if (len > n) {
-	vsnprintf((char*)buf+n, len-n, fmt, args);
-    }
-}
-
-static void
-compile_snprintf(char *buf, long len, const char *file, int line, const char *fmt, va_list args)
-{
-    long n;
-
-    n = err_position_0(buf, len, file, line);
-    if (len > n) {
-	vsnprintf((char*)buf+n, len-n, fmt, args);
-    }
-}
-
-static void err_append(const char*);
-
-void
-rb_compile_error(const char *file, int line, const char *fmt, ...)
-{
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args, fmt);
-    compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
-    va_end(args);
-    err_append(buf);
-}
-
-void
-rb_compile_error_append(const char *fmt, ...)
-{
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args, fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-    err_append(buf);
-}
-
-static void
-compile_warn_print(const char *file, int line, const char *fmt, va_list args)
-{
-    char buf[BUFSIZ];
-    int len;
-
-    compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
-    len = strlen(buf);
-    buf[len++] = '\n';
-    rb_write_error2(buf, len);
-}
-
-void
-rb_compile_warn(const char *file, int line, const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-
-    if (NIL_P(ruby_verbose)) return;
-
-    snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
-    va_start(args, fmt);
-    compile_warn_print(file, line, buf, args);
-    va_end(args);
-}
-
-/* rb_compile_warning() reports only in verbose mode */
-void
-rb_compile_warning(const char *file, int line, const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-
-    if (!RTEST(ruby_verbose)) return;
-
-    snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
-    va_start(args, fmt);
-    compile_warn_print(file, line, buf, args);
-    va_end(args);
-}
-
-static void
-warn_print(const char *fmt, va_list args)
-{
-    char buf[BUFSIZ];
-    int len;
-
-    err_snprintf(buf, BUFSIZ, fmt, args);
-    len = strlen(buf);
-    buf[len++] = '\n';
-    buf[len] = '\0';
-    rb_write_error2(buf, len);
-}
-
-void
-rb_warn(const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-
-    if (NIL_P(ruby_verbose)) return;
-
-    snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
-    va_start(args, fmt);
-    warn_print(buf, args);
-    va_end(args);
-}
-
-/* rb_warning() reports only in verbose mode */
-void
-rb_warning(const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-
-    if (!RTEST(ruby_verbose)) return;
-
-    snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
-    va_start(args, fmt);
-    warn_print(buf, args);
-    va_end(args);
-}
-
-/*
- * call-seq:
- *    warn(msg)   => nil
- *
- * Display the given message (followed by a newline) on STDERR unless
- * warnings are disabled (for example with the <code>-W0</code> flag).
- */
-
-static VALUE
-rb_warn_m(VALUE self, SEL sel, VALUE mesg)
-{
-    if (!NIL_P(ruby_verbose)) {
-	rb_io_write(rb_stderr, mesg);
-	rb_io_write(rb_stderr, rb_default_rs);
-    }
-    return Qnil;
-}
-
-//void rb_vm_bugreport(void);
-
-static void
-report_bug(const char *file, int line, const char *fmt, va_list args)
-{
-    char buf[BUFSIZ];
-    FILE *out = stderr;
-    int len = err_position_0(buf, BUFSIZ, file, line);
-
-    if (fwrite(buf, 1, len, out) == len ||
-	fwrite(buf, 1, len, (out = stdout)) == len) {
-	fputs("[BUG] ", out);
-	vfprintf(out, fmt, args);
-	fprintf(out, "\n%s\n\n", ruby_description);
-	//rb_vm_bugreport();
-    }
-}
-
-void
-rb_bug(const char *fmt, ...)
-{
-    va_list args;
-
-    va_start(args, fmt);
-    report_bug(rb_sourcefile(), rb_sourceline(), fmt, args);
-    va_end(args);
-
-    abort();
-}
-
-void
-rb_compile_bug(const char *file, int line, const char *fmt, ...)
-{
-    va_list args;
-
-    va_start(args, fmt);
-    report_bug(file, line, fmt, args);
-    va_end(args);
-
-    abort();
-}
-
-static const struct types {
-    int type;
-    const char *name;
-} builtin_types[] = {
-    {T_NIL,	"nil"},
-    {T_OBJECT,	"Object"},
-    {T_CLASS,	"Class"},
-    {T_ICLASS,	"iClass"},	/* internal use: mixed-in module holder */
-    {T_MODULE,	"Module"},
-    {T_FLOAT,	"Float"},
-    {T_STRING,	"String"},
-    {T_REGEXP,	"Regexp"},
-    {T_ARRAY,	"Array"},
-    {T_FIXNUM,	"Fixnum"},
-    {T_HASH,	"Hash"},
-    {T_STRUCT,	"Struct"},
-    {T_BIGNUM,	"Bignum"},
-    {T_FILE,	"File"},
-    {T_RATIONAL,"Rational"},
-    {T_COMPLEX, "Complex"},
-    {T_TRUE,	"true"},
-    {T_FALSE,	"false"},
-    {T_SYMBOL,	"Symbol"},	/* :symbol */
-    {T_DATA,	"Data"},	/* internal use: wrapped C pointers */
-    {T_MATCH,	"MatchData"},	/* data of $~ */
-    {T_NODE,	"Node"},	/* internal use: syntax tree node */
-    {T_UNDEF,	"undef"},	/* internal use: #undef; should not happen */
-    {T_NATIVE,  "native"}
-};
-
-const char *
-rb_obj_type(VALUE x)
-{
-    int i;
-    const int t = TYPE(x);
-    for (i = 0; i < sizeof(builtin_types) / sizeof(builtin_types[0]); i++) {
-	if (t == builtin_types[i].type) {
-	    return builtin_types[i].name;
-	}
-    }
-    return "unknown";
-}
-
-void
-rb_check_type(VALUE x, int t)
-{
-    const struct types *type = builtin_types;
-    const struct types *const typeend = builtin_types +
-	sizeof(builtin_types) / sizeof(builtin_types[0]);
-
-    if (x == Qundef) {
-	rb_bug("undef leaked to the Ruby space");
-    }
-
-    if (TYPE(x) != t) {
-	while (type < typeend) {
-	    if (type->type == t) {
-		const char *etype;
-
-		if (NIL_P(x)) {
-		    etype = "nil";
-		}
-		else if (FIXNUM_P(x)) {
-		    etype = "Fixnum";
-		}
-		else if (SYMBOL_P(x)) {
-		    etype = "Symbol";
-		}
-		else if (rb_special_const_p(x)) {
-		    etype = RSTRING_PTR(rb_obj_as_string(x));
-		}
-		else {
-		    etype = rb_obj_classname(x);
-		}
-		rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
-			 etype, type->name);
-	    }
-	    type++;
-	}
-	rb_bug("unknown type 0x%x (0x%x given)", t, TYPE(x));
-    }
-}
-
-/* exception classes */
-#include <errno.h>
-
-VALUE rb_eException;
-VALUE rb_eSystemExit;
-VALUE rb_eInterrupt;
-VALUE rb_eSignal;
-VALUE rb_eFatal;
-VALUE rb_eStandardError;
-VALUE rb_eRuntimeError;
-VALUE rb_eTypeError;
-VALUE rb_eArgError;
-VALUE rb_eIndexError;
-VALUE rb_eKeyError;
-VALUE rb_eRangeError;
-VALUE rb_eNameError;
-VALUE rb_eEncodingError;
-VALUE rb_eEncCompatError;
-VALUE rb_eUndefinedConversionError;
-VALUE rb_eInvalidByteSequenceError;
-VALUE rb_eConverterNotFoundError;
-VALUE rb_eNoMethodError;
-VALUE rb_eSecurityError;
-VALUE rb_eNotImpError;
-VALUE rb_eNoMemError;
-VALUE rb_cNameErrorMesg;
-
-VALUE rb_eScriptError;
-VALUE rb_eSyntaxError;
-VALUE rb_eLoadError;
-
-VALUE rb_eSystemCallError;
-VALUE rb_mErrno;
-static VALUE rb_eNOERROR;
-
-VALUE
-rb_exc_new(VALUE etype, const char *ptr, long len)
-{
-    return rb_funcall(etype, rb_intern("new"), 1, rb_str_new(ptr, len));
-}
-
-VALUE
-rb_exc_new2(VALUE etype, const char *s)
-{
-    return rb_exc_new(etype, s, strlen(s));
-}
-
-VALUE
-rb_exc_new3(VALUE etype, VALUE str)
-{
-    StringValue(str);
-    return rb_funcall(etype, rb_intern("new"), 1, str);
-}
-
-/*
- * call-seq:
- *    Exception.new(msg = nil)   =>  exception
- *
- *  Construct a new Exception object, optionally passing in 
- *  a message.
- */
-
-static VALUE
-exc_initialize(VALUE exc, SEL sel, int argc, VALUE *argv)
-{
-    VALUE arg;
-
-    rb_scan_args(argc, argv, "01", &arg);
-    rb_iv_set(exc, "mesg", arg);
-    rb_iv_set(exc, "bt", Qnil);
-
-    return exc;
-}
-
-/*
- *  Document-method: exception
- *
- *  call-seq:
- *     exc.exception(string) -> an_exception or exc
- *  
- *  With no argument, or if the argument is the same as the receiver,
- *  return the receiver. Otherwise, create a new
- *  exception object of the same class as the receiver, but with a
- *  message equal to <code>string.to_str</code>.
- *     
- */
-
-static VALUE
-exc_exception(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE exc;
-
-    if (argc == 0) return self;
-    if (argc == 1 && self == argv[0]) return self;
-    exc = rb_obj_clone(self);
-    exc_initialize(exc, 0, argc, argv);
-
-    return exc;
-}
-
-/*
- * call-seq:
- *   exception.to_s   =>  string
- *
- * Returns exception's message (or the name of the exception if
- * no message is set).
- */
-
-static VALUE
-exc_to_s(VALUE exc, SEL sel)
-{
-    VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
-
-    if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
-    if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
-    return mesg;
-}
-
-/*
- * call-seq:
- *   exception.message   =>  string
- *
- * Returns the result of invoking <code>exception.to_s</code>.
- * Normally this returns the exception's message or name. By
- * supplying a to_str method, exceptions are agreeing to
- * be used where Strings are expected.
- */
-
-static VALUE
-exc_message(VALUE exc, SEL sel)
-{
-    return rb_funcall(exc, rb_intern("to_s"), 0, 0);
-}
-
-/*
- * call-seq:
- *   exception.inspect   => string
- *
- * Return this exception's class name an message
- */
-
-static VALUE
-exc_inspect(VALUE exc, SEL sel)
-{
-    VALUE str, klass;
-
-    klass = CLASS_OF(exc);
-    exc = rb_obj_as_string(exc);
-    if (RSTRING_LEN(exc) == 0) {
-	return rb_str_dup(rb_class_name(klass));
-    }
-
-    str = rb_str_buf_new2("#<");
-    klass = rb_class_name(klass);
-    rb_str_buf_append(str, klass);
-    rb_str_buf_cat(str, ": ", 2);
-    rb_str_buf_append(str, exc);
-    rb_str_buf_cat(str, ">", 1);
-
-    return str;
-}
-
-/*
- *  call-seq:
- *     exception.backtrace    => array
- *  
- *  Returns any backtrace associated with the exception. The backtrace
- *  is an array of strings, each containing either ``filename:lineNo: in
- *  `method''' or ``filename:lineNo.''
- *     
- *     def a
- *       raise "boom"
- *     end
- *     
- *     def b
- *       a()
- *     end
- *     
- *     begin
- *       b()
- *     rescue => detail
- *       print detail.backtrace.join("\n")
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     prog.rb:2:in `a'
- *     prog.rb:6:in `b'
- *     prog.rb:10
-*/
-
-static VALUE
-exc_backtrace(VALUE exc, SEL sel)
-{
-    static ID bt;
-
-    if (!bt) bt = rb_intern("bt");
-    return rb_attr_get(exc, bt);
-}
-
-VALUE
-rb_check_backtrace(VALUE bt)
-{
-#define BACKTRACE_ERROR "backtrace must be Array of String"
-    if (!NIL_P(bt)) {
-	const int t = TYPE(bt);
-	if (t == T_STRING) {
-	    return rb_ary_new4(1, &bt);
-	}
-	if (t != T_ARRAY) {
-	    rb_raise(rb_eTypeError, BACKTRACE_ERROR);
-	}
-	for (int i = 0, count = RARRAY_LEN(bt); i < count; i++) {
-	    if (TYPE(RARRAY_AT(bt, i)) != T_STRING) {
-		rb_raise(rb_eTypeError, BACKTRACE_ERROR);
-	    }
-	}
-    }
-#undef BACKTRACE_ERROR
-    return bt;
-}
-
-/*
- *  call-seq:
- *     exc.set_backtrace(array)   =>  array
- *  
- *  Sets the backtrace information associated with <i>exc</i>. The
- *  argument must be an array of <code>String</code> objects in the
- *  format described in <code>Exception#backtrace</code>.
- *     
- */
-
-static VALUE
-exc_set_backtrace(VALUE exc, SEL sel, VALUE bt)
-{
-    return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
-}
-
-/*
- *  call-seq:
- *     exc == obj   => true or false
- *  
- *  Equality---If <i>obj</i> is not an <code>Exception</code>, returns
- *  <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and 
- *  <i>obj</i> share same class, messages, and backtrace.
- */
-
-static VALUE
-exc_equal(VALUE exc, SEL sel, VALUE obj)
-{
-    VALUE mesg, backtrace;
-    if (exc == obj) {
-	return Qtrue;
-    }
-    ID id_mesg = rb_intern("mesg");
-    if (rb_obj_class(exc) != rb_obj_class(obj)) {
-	SEL sel_message = sel_registerName("message");
-	SEL sel_backtrace = sel_registerName("backtrace");
-	if (!rb_vm_respond_to(obj, sel_message, false)
-		|| !rb_vm_respond_to(obj, sel_backtrace, false)) {
-	    return Qfalse;
-	}
-	mesg = rb_vm_call(obj, sel_message, 0, NULL);
-	backtrace = rb_vm_call(obj, sel_backtrace, 0, NULL);
-    }
-    else {
-        mesg = rb_attr_get(obj, id_mesg);
-        backtrace = exc_backtrace(obj, 0);
-    }
-    if (!rb_equal(rb_attr_get(exc, id_mesg), mesg)) {
-        return Qfalse;
-    }
-    if (!rb_equal(exc_backtrace(exc, 0), backtrace)) {
-        return Qfalse;
-    }
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *   SystemExit.new(status=0)   => system_exit
- *
- * Create a new +SystemExit+ exception with the given status.
- */
-
-static VALUE
-exit_initialize(VALUE exc, SEL sel, int argc, VALUE *argv)
-{
-    VALUE status = INT2FIX(EXIT_SUCCESS);
-    if (argc > 0 && FIXNUM_P(argv[0])) {
-	status = *argv++;
-	--argc;
-    }
-    if (sel == 0) {
-	sel = argc == 0 ? selInitialize : selInitialize2;
-    }
-    rb_vm_call_super(exc, sel, argc, argv);
-    rb_iv_set(exc, "status", status);
-    return exc;
-}
-
-
-/*
- * call-seq:
- *   system_exit.status   => fixnum
- *
- * Return the status value associated with this system exit.
- */
-
-static VALUE
-exit_status(VALUE exc, SEL sel)
-{
-    return rb_attr_get(exc, rb_intern("status"));
-}
-
-
-/*
- * call-seq:
- *   system_exit.success?  => true or false
- *
- * Returns +true+ if exiting successful, +false+ if not.
- */
-
-static VALUE
-exit_success_p(VALUE exc, SEL sel)
-{
-    VALUE status = rb_attr_get(exc, rb_intern("status"));
-    if (NIL_P(status)) return Qtrue;
-    if (status == INT2FIX(EXIT_SUCCESS)) return Qtrue;
-    return Qfalse;
-}
-
-void
-rb_name_error(ID id, const char *fmt, ...)
-{
-    VALUE exc, argv[2];
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args, fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-
-    argv[0] = rb_str_new2(buf);
-    argv[1] = ID2SYM(id);
-    exc = rb_class_new_instance(2, argv, rb_eNameError);
-    rb_exc_raise(exc);
-}
-
-/*
- * call-seq:
- *   NameError.new(msg [, name])  => name_error
- *
- * Construct a new NameError exception. If given the <i>name</i>
- * parameter may subsequently be examined using the <code>NameError.name</code>
- * method.
- */
-
-static VALUE
-name_err_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE name;
-
-    name = (argc > 1) ? argv[--argc] : Qnil;
-    if (sel == 0) {
-	sel = argc == 0 ? selInitialize : selInitialize2;
-    }
-    rb_vm_call_super(self, sel, argc, argv);
-    rb_iv_set(self, "name", name);
-    return self;
-}
-
-/*
- *  call-seq:
- *    name_error.name    =>  string or nil
- *
- *  Return the name associated with this NameError exception.
- */
-
-static VALUE
-name_err_name(VALUE self, SEL sel)
-{
-    return rb_attr_get(self, rb_intern("name"));
-}
-
-/*
- * call-seq:
- *  name_error.to_s   => string
- *
- * Produce a nicely-formatted string representing the +NameError+.
- */
-
-static VALUE
-name_err_to_s(VALUE exc, SEL sel)
-{
-    VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
-    VALUE str = mesg;
-
-    if (NIL_P(mesg)) {
-	return rb_class_name(CLASS_OF(exc));
-    }
-    StringValue(str);
-    if (str != mesg) {
-	rb_iv_set(exc, "mesg", mesg = str);
-    }
-    if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
-    return mesg;
-}
-
-/*
- * call-seq:
- *   NoMethodError.new(msg, name [, args])  => no_method_error
- *
- * Construct a NoMethodError exception for a method of the given name
- * called with the given arguments. The name may be accessed using
- * the <code>#name</code> method on the resulting object, and the
- * arguments using the <code>#args</code> method.
- */
-
-static VALUE
-nometh_err_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE args = (argc > 2) ? argv[--argc] : Qnil;
-    //name_err_initialize(self, sel, argc, argv);
-    if (sel == 0) {
-	sel = argc == 0 ? selInitialize : selInitialize2;
-    }
-    rb_vm_call_super(self, sel, argc, argv);
-    rb_iv_set(self, "args", args);
-    return self;
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_new(VALUE obj, SEL sel, VALUE mesg, VALUE recv, VALUE method)
-{
-    VALUE *ptr = ALLOC_N(VALUE, 3);
-
-    GC_WB(&ptr[0], mesg);
-    GC_WB(&ptr[1], recv);
-    GC_WB(&ptr[2], method);
-
-    return Data_Wrap_Struct(rb_cNameErrorMesg, NULL, NULL, ptr);
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_equal(VALUE obj1, SEL sel, VALUE obj2)
-{
-    VALUE *ptr1, *ptr2;
-    int i;
-
-    if (obj1 == obj2) return Qtrue;
-    if (rb_obj_class(obj2) != rb_cNameErrorMesg)
-	return Qfalse;
-
-    Data_Get_Struct(obj1, VALUE, ptr1);
-    Data_Get_Struct(obj2, VALUE, ptr2);
-    for (i=0; i<3; i++) {
-	if (!rb_equal(ptr1[i], ptr2[i]))
-	    return Qfalse;
-    }
-    return Qtrue;
-}
-
-static VALUE
-inspect_exec(VALUE obj, VALUE data, int recur)
-{
-    if (recur) {
-	return Qnil;
-    }
-    return rb_inspect(obj);
-}
-
-static VALUE
-safe_inspect(VALUE obj)
-{
-    return rb_exec_recursive(inspect_exec, obj, 0);
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_to_str(VALUE obj, SEL sel)
-{
-    VALUE *ptr, mesg;
-    Data_Get_Struct(obj, VALUE, ptr);
-
-    mesg = ptr[0];
-    if (NIL_P(mesg)) {
-	return Qnil;
-    }
-    else {
-	const char *desc = 0;
-	VALUE d = 0, args[3];
-
-	obj = ptr[1];
-	switch (TYPE(obj)) {
-	  case T_NIL:
-	    desc = "nil";
-	    break;
-	  case T_TRUE:
-	    desc = "true";
-	    break;
-	  case T_FALSE:
-	    desc = "false";
-	    break;
-	  default:
-	    d = rb_protect(safe_inspect, obj, NULL);
-	    if (NIL_P(d) || RSTRING_LEN(d) > 65) {
-		d = rb_any_to_s(obj);
-	    }
-	    desc = RSTRING_PTR(d);
-	    break;
-	}
-	if (desc && desc[0] != '#') {
-	    d = rb_str_new2(desc);
-	    rb_str_cat2(d, ":");
-	    rb_str_cat2(d, rb_obj_classname(obj));
-	}
-	args[0] = mesg;
-	args[1] = ptr[2];
-	args[2] = d;
-	mesg = rb_f_sprintf(3, args);
-    }
-    if (OBJ_TAINTED(obj)) {
-	OBJ_TAINT(mesg);
-    }
-    return mesg;
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_load(VALUE klass, SEL sel, VALUE str)
-{
-    return str;
-}
-
-/*
- * call-seq:
- *   no_method_error.args  => obj
- *
- * Return the arguments passed in as the third parameter to
- * the constructor.
- */
-
-static VALUE
-nometh_err_args(VALUE self, SEL sel)
-{
-    return rb_attr_get(self, rb_intern("args"));
-}
-
-void
-rb_invalid_str(const char *str, const char *type)
-{
-    VALUE s = rb_str_inspect(rb_str_new2(str));
-
-    rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING_PTR(s));
-}
-
-/* 
- *  Document-module: Errno
- *
- *  Ruby exception objects are subclasses of <code>Exception</code>.
- *  However, operating systems typically report errors using plain
- *  integers. Module <code>Errno</code> is created dynamically to map
- *  these operating system errors to Ruby classes, with each error
- *  number generating its own subclass of <code>SystemCallError</code>.
- *  As the subclass is created in module <code>Errno</code>, its name
- *  will start <code>Errno::</code>.
- *     
- *  The names of the <code>Errno::</code> classes depend on
- *  the environment in which Ruby runs. On a typical Unix or Windows
- *  platform, there are <code>Errno</code> classes such as
- *  <code>Errno::EACCES</code>, <code>Errno::EAGAIN</code>,
- *  <code>Errno::EINTR</code>, and so on.
- *     
- *  The integer operating system error number corresponding to a
- *  particular error is available as the class constant
- *  <code>Errno::</code><em>error</em><code>::Errno</code>.
- *     
- *     Errno::EACCES::Errno   #=> 13
- *     Errno::EAGAIN::Errno   #=> 11
- *     Errno::EINTR::Errno    #=> 4
- *     
- *  The full list of operating system errors on your particular platform
- *  are available as the constants of <code>Errno</code>.
- *
- *     Errno.constants   #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
- */
-
-static st_table *syserr_tbl;
-
-static VALUE
-set_syserr(int n, const char *name)
-{
-    VALUE error;
-
-    if (!st_lookup(syserr_tbl, n, &error)) {
-	error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
-	rb_define_const(error, "Errno", INT2NUM(n));
-	st_add_direct(syserr_tbl, n, error);
-    }
-    else {
-	rb_define_const(rb_mErrno, name, error);
-    }
-    return error;
-}
-
-static VALUE
-get_syserr(int n)
-{
-    VALUE error;
-
-    if (!st_lookup(syserr_tbl, n, &error)) {
-	char name[8];	/* some Windows' errno have 5 digits. */
-
-	snprintf(name, sizeof(name), "E%03d", n);
-	error = set_syserr(n, name);
-    }
-    return error;
-}
-
-/*
- * call-seq:
- *   SystemCallError.new(msg, errno)  => system_call_error_subclass
- *
- * If _errno_ corresponds to a known system error code, constructs
- * the appropriate <code>Errno</code> class for that error, otherwise
- * constructs a generic <code>SystemCallError</code> object. The
- * error number is subsequently available via the <code>errno</code>
- * method.
- */
-
-static VALUE
-syserr_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-#if !defined(_WIN32) && !defined(__VMS)
-    char *strerror();
-#endif
-    const char *err;
-    VALUE mesg, error;
-    VALUE klass = rb_obj_class(self);
-
-    if (klass == rb_eSystemCallError) {
-	rb_scan_args(argc, argv, "11", &mesg, &error);
-	if (argc == 1 && FIXNUM_P(mesg)) {
-	    error = mesg; mesg = Qnil;
-	}
-	if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &klass)) {
-	    /* change class */
-	    if (TYPE(self) != T_OBJECT) { /* insurance to avoid type crash */
-		rb_raise(rb_eTypeError, "invalid instance type");
-	    }
-	    RBASIC(self)->klass = klass;
-	}
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &mesg);
-	error = rb_const_get(klass, rb_intern("Errno"));
-    }
-    if (!NIL_P(error)) err = strerror(NUM2LONG(error));
-    else err = "unknown error";
-    if (!NIL_P(mesg)) {
-	VALUE str = mesg;
-
-	StringValue(str);
-	mesg = rb_sprintf("%s - %.*s", err,
-			  (int)RSTRING_LEN(str), RSTRING_PTR(str));
-    }
-    else {
-	mesg = rb_str_new2(err);
-    }
-    rb_vm_call_super(self, selInitialize2, 1, &mesg);
-    rb_iv_set(self, "errno", error);
-    return self;
-}
-
-/*
- * call-seq:
- *   system_call_error.errno   => fixnum
- *
- * Return this SystemCallError's error number.
- */
-
-static VALUE
-syserr_errno(VALUE self, SEL sel)
-{
-    return rb_attr_get(self, rb_intern("errno"));
-}
-
-/*
- * call-seq:
- *   system_call_error === other  => true or false
- *
- * Return +true+ if the receiver is a generic +SystemCallError+, or
- * if the error numbers _self_ and _other_ are the same.
- */
-
-static VALUE
-syserr_eqq(VALUE self, SEL sel, VALUE exc)
-{
-    VALUE num, e;
-    ID en = rb_intern("errno");
-
-    if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
-	if (!rb_respond_to(exc, en)) return Qfalse;
-    }
-    else if (self == rb_eSystemCallError) return Qtrue;
-
-    num = rb_attr_get(exc, rb_intern("errno"));
-    if (NIL_P(num)) {
-	num = rb_funcall(exc, en, 0, 0);
-    }
-    e = rb_const_get(self, rb_intern("Errno"));
-    if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
-	return Qtrue;
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   Errno.const_missing   => SystemCallError
- *
- * Returns default SystemCallError class.
- */
-static VALUE
-errno_missing(VALUE self, SEL sel, VALUE id)
-{
-    return rb_eNOERROR;
-}
-
-/*
- * call-seq:
- *   Errno.code   => Fixnum
- *
- * Returns the current errno value.
- */
-static VALUE
-errno_code(VALUE self, SEL sel)
-{
-    return INT2FIX(errno);
-}
-
-/*
- *  Descendants of class <code>Exception</code> are used to communicate
- *  between <code>raise</code> methods and <code>rescue</code>
- *  statements in <code>begin/end</code> blocks. <code>Exception</code>
- *  objects carry information about the exception---its type (the
- *  exception's class name), an optional descriptive string, and
- *  optional traceback information. Programs may subclass 
- *  <code>Exception</code> to add additional information.
- */
-
-void
-Init_Exception(void)
-{
-    rb_eException   = rb_define_class("Exception", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_eException, "exception", rb_class_new_instance_imp, -1);
-    rb_objc_define_method(rb_eException, "exception", exc_exception, -1);
-    rb_objc_define_method(rb_eException, "initialize", exc_initialize, -1);
-    rb_objc_define_method(rb_eException, "==", exc_equal, 1);
-    rb_objc_define_method(rb_eException, "to_s", exc_to_s, 0);
-    rb_objc_define_method(rb_eException, "message", exc_message, 0);
-    rb_objc_define_method(rb_eException, "inspect", exc_inspect, 0);
-    rb_objc_define_method(rb_eException, "backtrace", exc_backtrace, 0);
-    rb_objc_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
-
-    rb_eSystemExit  = rb_define_class("SystemExit", rb_eException);
-    rb_objc_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
-    rb_objc_define_method(rb_eSystemExit, "status", exit_status, 0);
-    rb_objc_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
-
-    rb_eFatal  	    = rb_define_class("fatal", rb_eException);
-    rb_eSignal      = rb_define_class("SignalException", rb_eException);
-    rb_eInterrupt   = rb_define_class("Interrupt", rb_eSignal);
-
-    rb_eStandardError = rb_define_class("StandardError", rb_eException);
-    rb_eTypeError     = rb_define_class("TypeError", rb_eStandardError);
-    rb_eArgError      = rb_define_class("ArgumentError", rb_eStandardError);
-    rb_eIndexError    = rb_define_class("IndexError", rb_eStandardError);
-    rb_eKeyError      = rb_define_class("KeyError", rb_eIndexError);
-    rb_eRangeError    = rb_define_class("RangeError", rb_eStandardError);
-
-    rb_eScriptError = rb_define_class("ScriptError", rb_eException);
-    rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
-    rb_eLoadError   = rb_define_class("LoadError", rb_eScriptError);
-    rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
-
-    rb_eNameError     = rb_define_class("NameError", rb_eStandardError);
-    rb_objc_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
-    rb_objc_define_method(rb_eNameError, "name", name_err_name, 0);
-    rb_objc_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
-    rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
-    rb_objc_define_method(*(VALUE *)rb_cNameErrorMesg, "!", name_err_mesg_new, 3);
-    rb_objc_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
-    rb_objc_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
-    rb_objc_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 0);
-    rb_objc_define_method(*(VALUE *)rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
-    rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
-    rb_objc_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
-    rb_objc_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
-
-    rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
-    rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
-    rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
-    rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
-    rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
-    rb_eUndefinedConversionError = rb_define_class_under(rb_cEncoding, "UndefinedConversionError", rb_eEncodingError);
-    rb_eInvalidByteSequenceError = rb_define_class_under(rb_cEncoding, "InvalidByteSequenceError", rb_eEncodingError);
-    rb_eConverterNotFoundError = rb_define_class_under(rb_cEncoding, "ConverterNotFoundError", rb_eEncodingError);
-
-    syserr_tbl = st_init_numtable();
-    GC_RETAIN(syserr_tbl);
-    rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
-    rb_objc_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
-    rb_objc_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
-    rb_objc_define_method(*(VALUE *)rb_eSystemCallError, "===", syserr_eqq, 1);
-
-    rb_mErrno = rb_define_module("Errno");
-    rb_objc_define_method(*(VALUE *)rb_mErrno, "const_missing", errno_missing, 1);
-    rb_objc_define_method(*(VALUE *)rb_mErrno, "code", errno_code, 0);
-
-    rb_objc_define_module_function(rb_mKernel, "warn", rb_warn_m, 1);
-}
-
-void
-rb_raise(VALUE exc, const char *fmt, ...)
-{
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args,fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-    rb_exc_raise(rb_exc_new2(exc, buf));
-}
-
-void
-rb_loaderror(const char *fmt, ...)
-{
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args, fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-    rb_exc_raise(rb_exc_new2(rb_eLoadError, buf));
-}
-
-void
-rb_notimplement(void)
-{
-    rb_raise(rb_eNotImpError,
-	     "%s() function is unimplemented on this machine",
-	     "TODO");//rb_id2name(rb_frame_this_func()));
-}
-
-VALUE
-rb_f_notimplement(VALUE rcv, SEL sel)
-{
-    rb_raise(rb_eNotImpError,
-	    "%s() function is unimplemented on this machine",
-	    sel_getName(sel));
-    return Qnil; // never reached
-}
-
-void
-rb_fatal(const char *fmt, ...)
-{
-    va_list args;
-    char buf[BUFSIZ];
-
-    va_start(args, fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-
-    rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
-}
-
-void
-rb_sys_fail(const char *mesg)
-{
-    int n = errno;
-    VALUE arg;
-
-    errno = 0;
-    if (n == 0) {
-	rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
-    }
-
-    arg = mesg ? rb_str_new2(mesg) : Qnil;
-    rb_exc_raise(rb_class_new_instance(1, &arg, get_syserr(n)));
-}
-
-void
-rb_sys_warning(const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-    int errno_save;
-
-    errno_save = errno;
-
-    if (!RTEST(ruby_verbose)) return;
-
-    snprintf(buf, BUFSIZ, "warning: %s", fmt);
-    snprintf(buf+strlen(buf), BUFSIZ-strlen(buf), ": %s", strerror(errno_save));
-
-    va_start(args, fmt);
-    warn_print(buf, args);
-    va_end(args);
-    errno = errno_save;
-}
-
-void
-rb_load_fail(const char *path)
-{
-    rb_loaderror("%s -- %s", strerror(errno), path);
-}
-
-void
-rb_error_frozen(const char *what)
-{
-    rb_raise(rb_eRuntimeError, "can't modify frozen %s", what);
-}
-
-void
-rb_check_frozen(VALUE obj)
-{
-    if (OBJ_FROZEN(obj)) rb_error_frozen(rb_obj_classname(obj));
-}
-
-static VALUE
-format_message(VALUE exc)
-{
-    CFMutableStringRef result = CFStringCreateMutable(NULL, 0);
-    VALUE message = rb_vm_call(exc, sel_registerName("message"), 0, NULL);
-    VALUE bt = rb_vm_call(exc, sel_registerName("backtrace"), 0, NULL);
-
-    const long count = (bt != Qnil ? RARRAY_LEN(bt) : 0);
-    if (count > 0) {
-	for (long i = 0; i < count; i++) {
-	    const char *bte = RSTRING_PTR(RARRAY_AT(bt, i));
-	    if (i == 0) {
-		CFStringAppendFormat(result, NULL, CFSTR("%s: %s (%s)\n"),
-		    bte, RSTRING_PTR(message), rb_class2name(*(VALUE *)exc));
-	    }
-	    else {
-		CFStringAppendFormat(result, NULL, CFSTR("\tfrom %s\n"), bte);
-	    }
-	}
-    }
-    else {
-	CFStringAppendFormat(result, NULL, CFSTR("%s (%s)\n"),
-	    RSTRING_PTR(message), rb_class2name(*(VALUE *)exc));
-    }
-    CFMakeCollectable(result);
-    return (VALUE)result;
-}
-
-static VALUE
-restore_level(VALUE lvl)
-{
-    rb_set_safe_level_force((int)lvl);
-    return Qnil;
-}
-
-VALUE
-rb_format_exception_message(VALUE exc)
-{
-    const int old_level = rb_safe_level();
-    rb_set_safe_level_force(0);
-
-    return rb_ensure(format_message, exc, restore_level, (VALUE)old_level);
-}
-
-void
-Init_syserr(void)
-{
-#ifdef EPERM
-    set_syserr(EPERM, "EPERM");
-#endif
-#ifdef ENOENT
-    set_syserr(ENOENT, "ENOENT");
-#endif
-#ifdef ESRCH
-    set_syserr(ESRCH, "ESRCH");
-#endif
-#ifdef EINTR
-    set_syserr(EINTR, "EINTR");
-#endif
-#ifdef EIO
-    set_syserr(EIO, "EIO");
-#endif
-#ifdef ENXIO
-    set_syserr(ENXIO, "ENXIO");
-#endif
-#ifdef E2BIG
-    set_syserr(E2BIG, "E2BIG");
-#endif
-#ifdef ENOEXEC
-    set_syserr(ENOEXEC, "ENOEXEC");
-#endif
-#ifdef EBADF
-    set_syserr(EBADF, "EBADF");
-#endif
-#ifdef ECHILD
-    set_syserr(ECHILD, "ECHILD");
-#endif
-#ifdef EAGAIN
-    set_syserr(EAGAIN, "EAGAIN");
-#endif
-#ifdef ENOMEM
-    set_syserr(ENOMEM, "ENOMEM");
-#endif
-#ifdef EACCES
-    set_syserr(EACCES, "EACCES");
-#endif
-#ifdef EFAULT
-    set_syserr(EFAULT, "EFAULT");
-#endif
-#ifdef ENOTBLK
-    set_syserr(ENOTBLK, "ENOTBLK");
-#endif
-#ifdef EBUSY
-    set_syserr(EBUSY, "EBUSY");
-#endif
-#ifdef EEXIST
-    set_syserr(EEXIST, "EEXIST");
-#endif
-#ifdef EXDEV
-    set_syserr(EXDEV, "EXDEV");
-#endif
-#ifdef ENODEV
-    set_syserr(ENODEV, "ENODEV");
-#endif
-#ifdef ENOTDIR
-    set_syserr(ENOTDIR, "ENOTDIR");
-#endif
-#ifdef EISDIR
-    set_syserr(EISDIR, "EISDIR");
-#endif
-#ifdef EINVAL
-    set_syserr(EINVAL, "EINVAL");
-#endif
-#ifdef ENFILE
-    set_syserr(ENFILE, "ENFILE");
-#endif
-#ifdef EMFILE
-    set_syserr(EMFILE, "EMFILE");
-#endif
-#ifdef ENOTTY
-    set_syserr(ENOTTY, "ENOTTY");
-#endif
-#ifdef ETXTBSY
-    set_syserr(ETXTBSY, "ETXTBSY");
-#endif
-#ifdef EFBIG
-    set_syserr(EFBIG, "EFBIG");
-#endif
-#ifdef ENOSPC
-    set_syserr(ENOSPC, "ENOSPC");
-#endif
-#ifdef ESPIPE
-    set_syserr(ESPIPE, "ESPIPE");
-#endif
-#ifdef EROFS
-    set_syserr(EROFS, "EROFS");
-#endif
-#ifdef EMLINK
-    set_syserr(EMLINK, "EMLINK");
-#endif
-#ifdef EPIPE
-    set_syserr(EPIPE, "EPIPE");
-#endif
-#ifdef EDOM
-    set_syserr(EDOM, "EDOM");
-#endif
-#ifdef ERANGE
-    set_syserr(ERANGE, "ERANGE");
-#endif
-#ifdef EDEADLK
-    set_syserr(EDEADLK, "EDEADLK");
-#endif
-#ifdef ENAMETOOLONG
-    set_syserr(ENAMETOOLONG, "ENAMETOOLONG");
-#endif
-#ifdef ENOLCK
-    set_syserr(ENOLCK, "ENOLCK");
-#endif
-#ifdef ENOSYS
-    set_syserr(ENOSYS, "ENOSYS");
-#endif
-#ifdef ENOTEMPTY
-    set_syserr(ENOTEMPTY, "ENOTEMPTY");
-#endif
-#ifdef ELOOP
-    set_syserr(ELOOP, "ELOOP");
-#endif
-#ifdef EWOULDBLOCK
-    set_syserr(EWOULDBLOCK, "EWOULDBLOCK");
-#endif
-#ifdef ENOMSG
-    set_syserr(ENOMSG, "ENOMSG");
-#endif
-#ifdef EIDRM
-    set_syserr(EIDRM, "EIDRM");
-#endif
-#ifdef ECHRNG
-    set_syserr(ECHRNG, "ECHRNG");
-#endif
-#ifdef EL2NSYNC
-    set_syserr(EL2NSYNC, "EL2NSYNC");
-#endif
-#ifdef EL3HLT
-    set_syserr(EL3HLT, "EL3HLT");
-#endif
-#ifdef EL3RST
-    set_syserr(EL3RST, "EL3RST");
-#endif
-#ifdef ELNRNG
-    set_syserr(ELNRNG, "ELNRNG");
-#endif
-#ifdef EUNATCH
-    set_syserr(EUNATCH, "EUNATCH");
-#endif
-#ifdef ENOCSI
-    set_syserr(ENOCSI, "ENOCSI");
-#endif
-#ifdef EL2HLT
-    set_syserr(EL2HLT, "EL2HLT");
-#endif
-#ifdef EBADE
-    set_syserr(EBADE, "EBADE");
-#endif
-#ifdef EBADR
-    set_syserr(EBADR, "EBADR");
-#endif
-#ifdef EXFULL
-    set_syserr(EXFULL, "EXFULL");
-#endif
-#ifdef ENOANO
-    set_syserr(ENOANO, "ENOANO");
-#endif
-#ifdef EBADRQC
-    set_syserr(EBADRQC, "EBADRQC");
-#endif
-#ifdef EBADSLT
-    set_syserr(EBADSLT, "EBADSLT");
-#endif
-#ifdef EDEADLOCK
-    set_syserr(EDEADLOCK, "EDEADLOCK");
-#endif
-#ifdef EBFONT
-    set_syserr(EBFONT, "EBFONT");
-#endif
-#ifdef ENOSTR
-    set_syserr(ENOSTR, "ENOSTR");
-#endif
-#ifdef ENODATA
-    set_syserr(ENODATA, "ENODATA");
-#endif
-#ifdef ETIME
-    set_syserr(ETIME, "ETIME");
-#endif
-#ifdef ENOSR
-    set_syserr(ENOSR, "ENOSR");
-#endif
-#ifdef ENONET
-    set_syserr(ENONET, "ENONET");
-#endif
-#ifdef ENOPKG
-    set_syserr(ENOPKG, "ENOPKG");
-#endif
-#ifdef EREMOTE
-    set_syserr(EREMOTE, "EREMOTE");
-#endif
-#ifdef ENOLINK
-    set_syserr(ENOLINK, "ENOLINK");
-#endif
-#ifdef EADV
-    set_syserr(EADV, "EADV");
-#endif
-#ifdef ESRMNT
-    set_syserr(ESRMNT, "ESRMNT");
-#endif
-#ifdef ECOMM
-    set_syserr(ECOMM, "ECOMM");
-#endif
-#ifdef EPROTO
-    set_syserr(EPROTO, "EPROTO");
-#endif
-#ifdef EMULTIHOP
-    set_syserr(EMULTIHOP, "EMULTIHOP");
-#endif
-#ifdef EDOTDOT
-    set_syserr(EDOTDOT, "EDOTDOT");
-#endif
-#ifdef EBADMSG
-    set_syserr(EBADMSG, "EBADMSG");
-#endif
-#ifdef EOVERFLOW
-    set_syserr(EOVERFLOW, "EOVERFLOW");
-#endif
-#ifdef ENOTUNIQ
-    set_syserr(ENOTUNIQ, "ENOTUNIQ");
-#endif
-#ifdef EBADFD
-    set_syserr(EBADFD, "EBADFD");
-#endif
-#ifdef EREMCHG
-    set_syserr(EREMCHG, "EREMCHG");
-#endif
-#ifdef ELIBACC
-    set_syserr(ELIBACC, "ELIBACC");
-#endif
-#ifdef ELIBBAD
-    set_syserr(ELIBBAD, "ELIBBAD");
-#endif
-#ifdef ELIBSCN
-    set_syserr(ELIBSCN, "ELIBSCN");
-#endif
-#ifdef ELIBMAX
-    set_syserr(ELIBMAX, "ELIBMAX");
-#endif
-#ifdef ELIBEXEC
-    set_syserr(ELIBEXEC, "ELIBEXEC");
-#endif
-#ifdef EILSEQ
-    set_syserr(EILSEQ, "EILSEQ");
-#endif
-#ifdef ERESTART
-    set_syserr(ERESTART, "ERESTART");
-#endif
-#ifdef ESTRPIPE
-    set_syserr(ESTRPIPE, "ESTRPIPE");
-#endif
-#ifdef EUSERS
-    set_syserr(EUSERS, "EUSERS");
-#endif
-#ifdef ENOTSOCK
-    set_syserr(ENOTSOCK, "ENOTSOCK");
-#endif
-#ifdef EDESTADDRREQ
-    set_syserr(EDESTADDRREQ, "EDESTADDRREQ");
-#endif
-#ifdef EMSGSIZE
-    set_syserr(EMSGSIZE, "EMSGSIZE");
-#endif
-#ifdef EPROTOTYPE
-    set_syserr(EPROTOTYPE, "EPROTOTYPE");
-#endif
-#ifdef ENOPROTOOPT
-    set_syserr(ENOPROTOOPT, "ENOPROTOOPT");
-#endif
-#ifdef EPROTONOSUPPORT
-    set_syserr(EPROTONOSUPPORT, "EPROTONOSUPPORT");
-#endif
-#ifdef ESOCKTNOSUPPORT
-    set_syserr(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT");
-#endif
-#ifdef EOPNOTSUPP
-    set_syserr(EOPNOTSUPP, "EOPNOTSUPP");
-#endif
-#ifdef EPFNOSUPPORT
-    set_syserr(EPFNOSUPPORT, "EPFNOSUPPORT");
-#endif
-#ifdef EAFNOSUPPORT
-    set_syserr(EAFNOSUPPORT, "EAFNOSUPPORT");
-#endif
-#ifdef EADDRINUSE
-    set_syserr(EADDRINUSE, "EADDRINUSE");
-#endif
-#ifdef EADDRNOTAVAIL
-    set_syserr(EADDRNOTAVAIL, "EADDRNOTAVAIL");
-#endif
-#ifdef ENETDOWN
-    set_syserr(ENETDOWN, "ENETDOWN");
-#endif
-#ifdef ENETUNREACH
-    set_syserr(ENETUNREACH, "ENETUNREACH");
-#endif
-#ifdef ENETRESET
-    set_syserr(ENETRESET, "ENETRESET");
-#endif
-#ifdef ECONNABORTED
-    set_syserr(ECONNABORTED, "ECONNABORTED");
-#endif
-#ifdef ECONNRESET
-    set_syserr(ECONNRESET, "ECONNRESET");
-#endif
-#ifdef ENOBUFS
-    set_syserr(ENOBUFS, "ENOBUFS");
-#endif
-#ifdef EISCONN
-    set_syserr(EISCONN, "EISCONN");
-#endif
-#ifdef ENOTCONN
-    set_syserr(ENOTCONN, "ENOTCONN");
-#endif
-#ifdef ESHUTDOWN
-    set_syserr(ESHUTDOWN, "ESHUTDOWN");
-#endif
-#ifdef ETOOMANYREFS
-    set_syserr(ETOOMANYREFS, "ETOOMANYREFS");
-#endif
-#ifdef ETIMEDOUT
-    set_syserr(ETIMEDOUT, "ETIMEDOUT");
-#endif
-#ifdef ECONNREFUSED
-    set_syserr(ECONNREFUSED, "ECONNREFUSED");
-#endif
-#ifdef EHOSTDOWN
-    set_syserr(EHOSTDOWN, "EHOSTDOWN");
-#endif
-#ifdef EHOSTUNREACH
-    set_syserr(EHOSTUNREACH, "EHOSTUNREACH");
-#endif
-#ifdef EALREADY
-    set_syserr(EALREADY, "EALREADY");
-#endif
-#ifdef EINPROGRESS
-    set_syserr(EINPROGRESS, "EINPROGRESS");
-#endif
-#ifdef ESTALE
-    set_syserr(ESTALE, "ESTALE");
-#endif
-#ifdef EUCLEAN
-    set_syserr(EUCLEAN, "EUCLEAN");
-#endif
-#ifdef ENOTNAM
-    set_syserr(ENOTNAM, "ENOTNAM");
-#endif
-#ifdef ENAVAIL
-    set_syserr(ENAVAIL, "ENAVAIL");
-#endif
-#ifdef EISNAM
-    set_syserr(EISNAM, "EISNAM");
-#endif
-#ifdef EREMOTEIO
-    set_syserr(EREMOTEIO, "EREMOTEIO");
-#endif
-#ifdef EDQUOT
-    set_syserr(EDQUOT, "EDQUOT");
-#endif
-    rb_eNOERROR = set_syserr(0, "NOERROR");
-}
-
-static void
-err_append(const char *s)
-{
-    VALUE err = rb_vm_current_exception();
-
-    if (rb_vm_parse_in_eval()) {
-	if (err == Qnil) {
-	    err = rb_exc_new2(rb_eSyntaxError, s);
-	    rb_vm_set_current_exception(err);
-	}
-	else {
-	    VALUE str = rb_obj_as_string(err);
-
-	    rb_str_cat2(str, "\n");
-	    rb_str_cat2(str, s);
-	    rb_vm_set_current_exception(rb_exc_new3(rb_eSyntaxError, str));
-	}
-    }
-    else {
-	if (err == Qnil) {
-	    err = rb_exc_new2(rb_eSyntaxError, "compile error");
-	    rb_vm_set_current_exception(err);
-	}
-	rb_write_error(s);
-	rb_write_error("\n");
-    }
-}

Deleted: MacRuby/trunk/eval.c
===================================================================
--- MacRuby/trunk/eval.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/eval.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,888 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's eval.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "dtrace.h"
-#include "id.h"
-#include "class.h"
-
-VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
-
-ID rb_frame_callee(void);
-VALUE rb_eLocalJumpError;
-VALUE rb_eSysStackError;
-VALUE sysstack_error;
-
-static VALUE exception_error;
-
-#include "eval_error.c"
-#include "eval_safe.c"
-#include "eval_jump.c"
-
-/* initialize ruby */
-
-extern char ***_NSGetEnviron(void);
-#define environ (*_NSGetEnviron())
-char **rb_origenviron;
-
-void rb_call_inits(void);
-void Init_ext(void);
-void Init_PreGC(void);
-void Init_PreVM(void);
-void Init_PreClass(void);
-void Init_PreGCD(void);
-void Init_PreEncoding(void);
-
-bool ruby_initialized = false;
-
-void
-ruby_init(void)
-{
-    if (ruby_initialized) {
-	return;
-    }
-    ruby_initialized = true;
-
-    rb_origenviron = environ;
-
-    Init_PreClass();	// requires nothing
-    Init_PreGC(); 	// requires nothing
-    Init_PreVM(); 	// requires nothing
-    Init_PreGCD(); 	// requires nothing
-    Init_PreEncoding(); // requires rb_cEncoding, GC
-
-    rb_call_inits();
-    ruby_prog_init();
-}
-
-void *
-ruby_options(int argc, char **argv)
-{
-#if MACRUBY_STATIC
-    printf("command-line options are not supported in MacRuby static\n");
-    abort();
-#else
-    return ruby_process_options(argc, argv);
-#endif
-}
-
-static void
-ruby_finalize_0(void)
-{
-    rb_trap_exit();
-    rb_exec_end_proc();
-}
-
-static void
-ruby_finalize_1(void)
-{
-    rb_vm_finalize();
-    ruby_sig_finalize();
-    //GET_THREAD()->errinfo = Qnil;
-}
-
-void
-ruby_finalize(void)
-{
-    ruby_finalize_0();
-    ruby_finalize_1();
-}
-
-int
-ruby_cleanup(int ex)
-{
-#if 1
-    return 0;
-#else
-    int state;
-    volatile VALUE errs[2];
-    rb_thread_t *th = GET_THREAD();
-    int nerr;
-
-    errs[1] = th->errinfo;
-    th->safe_level = 0;
-
-    ruby_finalize_0();
-
-    errs[0] = th->errinfo;
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	//SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
-    }
-    else if (ex == 0) {
-	ex = state;
-    }
-    GC_WB(&th->errinfo, errs[1]);
-    ex = error_handle(ex);
-    ruby_finalize_1();
-    POP_TAG();
-    //rb_thread_stop_timer_thread();
-
-    for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) {
-	VALUE err = errs[nerr];
-
-	if (!RTEST(err)) continue;
-
-	/* th->errinfo contains a NODE while break'ing */
-	if (TYPE(err) == T_NODE) continue;
-
-	if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
-	    return sysexit_status(err);
-	}
-	else if (rb_obj_is_kind_of(err, rb_eSignal)) {
-	    VALUE sig = rb_iv_get(err, "signo");
-	    ruby_default_signal(NUM2INT(sig));
-	}
-	else if (ex == 0) {
-	    ex = 1;
-	}
-    }
-
-#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
-    switch (ex) {
-#if EXIT_SUCCESS != 0
-      case 0: return EXIT_SUCCESS;
-#endif
-#if EXIT_FAILURE != 1
-      case 1: return EXIT_FAILURE;
-#endif
-    }
-#endif
-
-    return ex;
-#endif
-}
-
-void
-ruby_stop(int ex)
-{
-    exit(ruby_cleanup(ex));
-}
-
-extern VALUE rb_progname;
-
-void rb_require_libraries(void);
-
-int
-ruby_executable_node(void *n, int *status)
-{
-    VALUE v = (VALUE)n;
-    int s;
-
-    switch (v) {
-      case Qtrue:
-        s = EXIT_SUCCESS;
-	break;
-      case Qfalse:
-	s = EXIT_FAILURE;
-	break;
-      default:
-	if (!FIXNUM_P(v)) {
-	    return TRUE;
-	}
-	s = FIX2INT(v);
-    }
-    if (status) {
-	*status = s;
-    }
-    return FALSE;
-}
-
-#if !defined(MACRUBY_STATIC)
-int
-ruby_run_node(void *n)
-{
-    int status;
-    if (!ruby_executable_node(n, &status)) {
-	ruby_cleanup(0);
-	return status;
-    }
-    rb_require_libraries();
-    rb_vm_run(RSTRING_PTR(rb_progname), (NODE *)n, NULL, false);
-    return ruby_cleanup(0);
-}
-#endif
-
-/*
- *  call-seq:
- *     Module.nesting    => array
- *
- *  Returns the list of +Modules+ nested at the point of call.
- *
- *     module M1
- *       module M2
- *         $a = Module.nesting
- *       end
- *     end
- *     $a           #=> [M1::M2, M1]
- *     $a[0].name   #=> "M1::M2"
- */
-
-static VALUE
-rb_mod_nesting(VALUE rcv, SEL sel, VALUE top, int argc, VALUE *argv)
-{
-    rb_scan_args(argc, argv, "00");
-
-    switch (TYPE(top)) {
-	case T_CLASS:
-	case T_MODULE:
-	    return rb_vm_module_nesting(top);
-
-	default:
-	    return rb_ary_new();
-    }
-}
-
-/*
- *  call-seq:
- *     Module.constants   => array
- *
- *  Returns an array of the names of all constants defined in the
- *  system. This list includes the names of all modules and classes.
- *
- *     p Module.constants.sort[1..5]
- *
- *  <em>produces:</em>
- *
- *     ["ARGV", "ArgumentError", "Array", "Bignum", "Binding"]
- */
-
-VALUE rb_mod_constants(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_mod_s_constants(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    if (argc > 0) {
-	return rb_mod_constants(rb_cModule, 0, argc, argv);
-    }
-
-#if 0 // TODO
-    const NODE *cref = vm_cref();
-    VALUE klass;
-    VALUE cbase = 0;
-    void *data = 0;
-
-    while (cref) {
-	klass = cref->nd_clss;
-	if (!NIL_P(klass)) {
-	    data = rb_mod_const_at(cref->nd_clss, data);
-	    if (!cbase) {
-		cbase = klass;
-	    }
-	}
-	cref = cref->nd_next;
-    }
-
-    if (cbase) {
-	data = rb_mod_const_of(cbase, data);
-    }
-    return rb_const_list(data);
-#endif
-    return Qnil;
-}
-
-void
-rb_frozen_class_p(VALUE klass)
-{
-    const char *desc = "something(?!)";
-
-    if (OBJ_FROZEN(klass)) {
-	if (RCLASS_SINGLETON(klass))
-	    desc = "object";
-	else {
-	    switch (TYPE(klass)) {
-	      case T_MODULE:
-	      case T_ICLASS:
-		desc = "module";
-		break;
-	      case T_CLASS:
-		desc = "class";
-		break;
-	    }
-	}
-	rb_error_frozen(desc);
-    }
-}
-
-VALUE rb_make_backtrace(void);
-
-void
-rb_exc_raise(VALUE mesg)
-{
-    rb_vm_raise(mesg);
-    abort();
-}
-
-void
-rb_exc_fatal(VALUE mesg)
-{
-    rb_vm_raise(mesg);
-    abort();
-}
-
-void
-rb_interrupt(void)
-{
-    static const char fmt[1] = {'\0'};
-    rb_raise(rb_eInterrupt, "%s", fmt);
-}
-
-static VALUE get_errinfo(void);
-
-/*
- *  call-seq:
- *     raise
- *     raise(string)
- *     raise(exception [, string [, array]])
- *     fail
- *     fail(string)
- *     fail(exception [, string [, array]])
- *
- *  With no arguments, raises the exception in <code>$!</code> or raises
- *  a <code>RuntimeError</code> if <code>$!</code> is +nil+.
- *  With a single +String+ argument, raises a
- *  +RuntimeError+ with the string as a message. Otherwise,
- *  the first parameter should be the name of an +Exception+
- *  class (or an object that returns an +Exception+ object when sent
- *  an +exception+ message). The optional second parameter sets the
- *  message associated with the exception, and the third parameter is an
- *  array of callback information. Exceptions are caught by the
- *  +rescue+ clause of <code>begin...end</code> blocks.
- *
- *     raise "Failed to create socket"
- *     raise ArgumentError, "No parameters", caller
- */
-
-static VALUE
-rb_f_raise(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE err;
-    if (argc == 0) {
-	err = get_errinfo();
-	if (!NIL_P(err)) {
-	    argc = 1;
-	    argv = &err;
-	}
-    }
-    rb_vm_raise(rb_make_exception(argc, argv));
-    return Qnil;		/* not reached */
-}
-
-VALUE
-rb_make_exception(int argc, VALUE *argv)
-{
-    VALUE mesg;
-    ID exception;
-    int n;
-
-    mesg = Qnil;
-    switch (argc) {
-      case 0:
-	//mesg = Qnil;
-	mesg = rb_exc_new2(rb_eRuntimeError, "");
-	break;
-      case 1:
-	if (NIL_P(argv[0])) {
-	    break;
-	}
-	if (TYPE(argv[0]) == T_STRING) {
-	    mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
-	    break;
-	}
-	n = 0;
-	goto exception_call;
-
-      case 2:
-      case 3:
-	n = 1;
-      exception_call:
-	exception = rb_intern("exception");
-	if (!rb_respond_to(argv[0], exception)) {
-	    rb_raise(rb_eTypeError, "exception class/object expected");
-	}
-	mesg = rb_funcall(argv[0], exception, n, argv[1]);
-	break;
-      default:
-	rb_raise(rb_eArgError, "wrong number of arguments");
-	break;
-    }
-    if (argc > 0) {
-	if (!rb_obj_is_kind_of(mesg, rb_eException))
-	    rb_raise(rb_eTypeError, "exception object expected");
-	if (argc > 2)
-	    set_backtrace(mesg, argv[2]);
-    }
-
-    return mesg;
-}
-
-int
-rb_iterator_p()
-{
-    return rb_block_given_p();
-}
-
-/*
- *  call-seq:
- *     block_given?   => true or false
- *     iterator?      => true or false
- *
- *  Returns <code>true</code> if <code>yield</code> would execute a
- *  block in the current context. The <code>iterator?</code> form
- *  is mildly deprecated.
- *
- *     def try
- *       if block_given?
- *         yield
- *       else
- *         "no block"
- *       end
- *     end
- *     try                  #=> "no block"
- *     try { "hello" }      #=> "hello"
- *     try do "hello" end   #=> "hello"
- */
-
-
-static VALUE
-rb_f_block_given_p(VALUE self, SEL sel)
-{
-    return rb_vm_block_saved() ? Qtrue : Qfalse;
-}
-
-VALUE rb_eThreadError;
-
-void
-rb_need_block()
-{
-    if (!rb_block_given_p()) {
-	// TODO
-	//vm_localjump_error("no block given", Qnil, 0);
-	rb_raise(rb_eRuntimeError, "no block given");
-    }
-}
-
-VALUE
-rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
-	  VALUE (* r_proc)(ANYARGS), VALUE data2)
-{
-    return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
-		      (VALUE)0);
-}
-
-// XXX not thread-safe, but it doesn't matter, since clients are C extensions
-// which are not reentrant anyways.
-static VALUE protect_exc = Qnil;
-
-static VALUE
-protect_rescue(VALUE obj, VALUE exc)
-{
-   int *state = (int *)obj;
-   if (state != NULL) {
-	*state = 1;
-   }
-    GC_RETAIN(exc);
-    protect_exc = exc;
-    return Qnil;
-}
-
-VALUE
-rb_protect(VALUE (*proc) (VALUE), VALUE data, int *state)
-{
-    if (state != NULL) {
-	*state = 0;
-    }
-    return rb_rescue2(proc, data, protect_rescue, (VALUE)state,
-	    rb_eStandardError, (VALUE)0);
-}
-
-void
-rb_jump_tag(int state)
-{
-    assert(state > 0);
-    VALUE exc = protect_exc;
-    assert(exc != Qnil);
-    protect_exc = Qnil;
-    GC_RELEASE(exc);
-    rb_exc_raise(exc);
-}
-
-ID
-rb_frame_this_func(void)
-{
-    // TODO
-    return 0;
-}
-
-ID
-rb_frame_callee(void)
-{
-    // TODO
-    return 0;
-}
-
-/*
- *  call-seq:
- *     append_features(mod)   => mod
- *
- *  When this module is included in another, Ruby calls
- *  <code>append_features</code> in this module, passing it the
- *  receiving module in _mod_. Ruby's default implementation is
- *  to add the constants, methods, and module variables of this module
- *  to _mod_ if this module has not already been added to
- *  _mod_ or one of its ancestors. See also <code>Module#include</code>.
- */
-
-static VALUE
-rb_mod_append_features(VALUE module, SEL sel, VALUE include)
-{
-    VALUE orig = include;
-    switch (TYPE(include)) {
-	case T_CLASS:
-	case T_MODULE:
-	    break;
-	default:
-	    Check_Type(include, T_CLASS);
-	    break;
-    }
-    if (RCLASS_RUBY(include)) {
-	VALUE sinclude = rb_make_singleton_class(RCLASS_SUPER(include));
-	RCLASS_SET_SUPER(include, sinclude);
-	include = sinclude;
-    }	
-    rb_include_module2(include, orig, module, true, true);
-
-    VALUE m = module;
-    do {
-	VALUE ary = rb_attr_get(m, idIncludedModules);
-	if (ary != Qnil) {
-	    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-		VALUE mod = RARRAY_AT(ary, i);
-		rb_mod_append_features(mod, sel, include);
-	    }
-	}
-	m = RCLASS_SUPER(m);
-    }
-    while (m == 0 || RCLASS_SINGLETON(m));
-
-    return module;
-}
-
-/*
- *  call-seq:
- *     include(module, ...)    => self
- *
- *  Invokes <code>Module.append_features</code> on each parameter in turn.
- */
-
-static VALUE
-rb_mod_include(VALUE module, SEL sel, int argc, VALUE *argv)
-{
-    int i;
-
-    for (i = 0; i < argc; i++) {
-	Check_Type(argv[i], T_MODULE);
-    }
-    while (argc--) {
-	rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
-	rb_funcall(argv[argc], rb_intern("included"), 1, module);
-    }
-    return module;
-}
-
-VALUE
-rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
-{
-    return rb_funcall2(obj, idInitialize, argc, argv);
-}
-
-void
-rb_extend_object(VALUE obj, VALUE module)
-{
-    VALUE klass;
-    if (TYPE(obj) == T_CLASS && RCLASS_RUBY(obj)) {
-	VALUE sklass = rb_make_singleton_class(RCLASS_SUPER(obj));
-	RCLASS_SET_SUPER(obj, sklass);
-	klass = *(VALUE *)sklass;
-    }
-    else {
-	klass = rb_singleton_class(obj);
-    }
-
-    rb_include_module(klass, module);
-
-    VALUE m = module;
-    do {
-	VALUE ary = rb_attr_get(m, idIncludedModules);
-	if (ary != Qnil) {
-	    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-		VALUE mod = RARRAY_AT(ary, i);
-		rb_extend_object(obj, mod);
-	    }
-	}
-	m = RCLASS_SUPER(m);
-    }
-    while (m == 0 || RCLASS_SINGLETON(m));
-}
-
-/*
- *  call-seq:
- *     extend_object(obj)    => obj
- *
- *  Extends the specified object by adding this module's constants and
- *  methods (which are added as singleton methods). This is the callback
- *  method used by <code>Object#extend</code>.
- *
- *     module Picky
- *       def Picky.extend_object(o)
- *         if String === o
- *           puts "Can't add Picky to a String"
- *         else
- *           puts "Picky added to #{o.class}"
- *           super
- *         end
- *       end
- *     end
- *     (s = Array.new).extend Picky  # Call Object.extend
- *     (s = "quick brown fox").extend Picky
- *
- *  <em>produces:</em>
- *
- *     Picky added to Array
- *     Can't add Picky to a String
- */
-
-static VALUE
-rb_mod_extend_object(VALUE mod, SEL sel, VALUE obj)
-{
-    rb_extend_object(obj, mod);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     obj.extend(module, ...)    => obj
- *
- *  Adds to _obj_ the instance methods from each module given as a
- *  parameter.
- *
- *     module Mod
- *       def hello
- *         "Hello from Mod.\n"
- *       end
- *     end
- *
- *     class Klass
- *       def hello
- *         "Hello from Klass.\n"
- *       end
- *     end
- *
- *     k = Klass.new
- *     k.hello         #=> "Hello from Klass.\n"
- *     k.extend(Mod)   #=> #<Klass:0x401b3bc8>
- *     k.hello         #=> "Hello from Mod.\n"
- */
-
-static VALUE
-rb_obj_extend(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    if (OBJ_FROZEN(obj)) {
-	rb_raise(rb_eRuntimeError, "cannot extend a frozen object");
-    }
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
-    }
-    for (int i = 0; i < argc; i++) {
-	Check_Type(argv[i], T_MODULE);
-    }
-    while (argc--) {
-	rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
-	rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
-    }
-    return obj;
-}
-
-/*
- *  call-seq:
- *     include(module, ...)   => self
- *
- *  Invokes <code>Module.append_features</code>
- *  on each parameter in turn. Effectively adds the methods and constants
- *  in each module to the receiver.
- */
-
-static VALUE
-top_include(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-#if 0
-    rb_thread_t *th = GET_THREAD();
-
-    rb_secure(4);
-    if (th->top_wrapper) {
-	rb_warning
-	    ("main#include in the wrapped load is effective only in wrapper module");
-	return rb_mod_include(argc, argv, th->top_wrapper);
-    }
-#endif
-    return rb_mod_include(rb_cObject, 0, argc, argv);
-}
-
-VALUE rb_f_trace_var();
-VALUE rb_f_untrace_var();
-
-static VALUE
-get_errinfo(void)
-{
-    VALUE exc = rb_vm_current_exception();
-    if (NIL_P(exc)) {
-	exc = rb_errinfo();
-    }
-    return exc;
-}
-
-static VALUE
-errinfo_getter(ID id)
-{
-    return get_errinfo();
-}
-
-VALUE
-rb_rubylevel_errinfo(void)
-{
-    return get_errinfo();
-}
-
-static VALUE
-errat_getter(ID id)
-{
-    VALUE err = get_errinfo();
-    if (!NIL_P(err)) {
-	return get_backtrace(err);
-    }
-    else {
-	return Qnil;
-    }
-}
-
-static void
-errat_setter(VALUE val, ID id, VALUE *var)
-{
-    VALUE err = get_errinfo();
-    if (NIL_P(err)) {
-	rb_raise(rb_eArgError, "$! not set");
-    }
-    set_backtrace(err, val);
-}
-
-/*
- *  call-seq:
- *     local_variables    => array
- *
- *  Returns the names of the current local variables.
- *
- *     fred = 1
- *     for i in 1..10
- *        # ...
- *     end
- *     local_variables   #=> ["fred", "i"]
- */
-
-static VALUE
-rb_f_local_variables(VALUE rcv, SEL sel)
-{
-    rb_vm_binding_t *b = rb_vm_current_binding();
-    VALUE ary = rb_ary_new();
-    while (b != NULL) {
-	rb_vm_local_t *l;
-	for (l = b->locals; l != NULL; l = l->next) {
-	    rb_ary_push(ary, ID2SYM(l->name));
-	}
-	b = b->next;
-    }
-    return ary;
-}
-
-
-/*
- *  call-seq:
- *     __method__         => symbol
- *     __callee__         => symbol
- *
- *  Returns the name of the current method as a Symbol.
- *  If called outside of a method, it returns <code>nil</code>.
- *
- */
-
-static VALUE
-rb_f_method_name(VALUE rcv, SEL sel)
-{
-    return Qnil;
-}
-
-void Init_vm_eval(void);
-void Init_eval_method(void);
-
-VALUE rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv);
-VALUE rb_f_global_variables(VALUE rcv, SEL sel);
-VALUE rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv);
-VALUE rb_f_trace_var(VALUE rcv, SEL sel, int argc, VALUE *argv);
-VALUE rb_f_untrace_var(VALUE rcv, SEL sel, int argc, VALUE *argv);
-
-void
-Init_eval(void)
-{
-    rb_define_virtual_variable("$@", errat_getter, errat_setter);
-    rb_define_virtual_variable("$!", errinfo_getter, 0);
-
-    rb_objc_define_module_function(rb_mKernel, "eval", rb_f_eval, -1);
-    rb_objc_define_module_function(rb_mKernel, "iterator?", rb_f_block_given_p, 0);
-    rb_objc_define_module_function(rb_mKernel, "block_given?", rb_f_block_given_p, 0);
-
-    rb_objc_define_module_function(rb_mKernel, "fail", rb_f_raise, -1);
-    rb_objc_define_module_function(rb_mKernel, "raise", rb_f_raise, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "global_variables", rb_f_global_variables, 0);	/* in variable.c */
-    rb_objc_define_module_function(rb_mKernel, "local_variables", rb_f_local_variables, 0);
-
-    rb_objc_define_method(rb_mKernel, "__method__", rb_f_method_name, 0);
-    rb_objc_define_method(rb_mKernel, "__callee__", rb_f_method_name, 0);
-
-    rb_objc_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
-    rb_objc_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
-    rb_objc_define_private_method(rb_cModule, "include", rb_mod_include, -1);
-    rb_objc_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
-    rb_objc_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
-
-    rb_undef_method(rb_cClass, "module_function");
-
-    Init_vm_eval();
-    Init_eval_method();
-
-    rb_objc_define_method(*(VALUE *)rb_cModule, "nesting", rb_mod_nesting, -3);
-    rb_objc_define_method(*(VALUE *)rb_cModule, "constants", rb_mod_s_constants, -1);
-
-    VALUE cTopLevel = *(VALUE *)rb_vm_top_self();    
-    rb_objc_define_method(cTopLevel, "include", top_include, -1);
-
-    rb_objc_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "trace_var", rb_f_trace_var, -1);	/* in variable.c */
-    rb_objc_define_module_function(rb_mKernel, "untrace_var", rb_f_untrace_var, -1);	/* in variable.c */
-
-    rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
-
-    exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
-    //rb_ivar_set(exception_error, idThrowState, INT2FIX(TAG_FATAL));
-    GC_RETAIN(exception_error);
-}

Deleted: MacRuby/trunk/eval_error.c
===================================================================
--- MacRuby/trunk/eval_error.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/eval_error.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,197 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-/*
- * included by eval.c
- */
-
-#if 0
-static void
-warn_printf(const char *fmt, ...)
-{
-    char buf[BUFSIZ];
-    va_list args;
-
-    va_init_list(args, fmt);
-    vsnprintf(buf, BUFSIZ, fmt, args);
-    va_end(args);
-    rb_write_error(buf);
-}
-#endif
-
-#define warn_print(x) rb_write_error(x)
-#define warn_print2(x,l) rb_write_error2(x,l)
-
-VALUE rb_check_backtrace(VALUE);
-
-static VALUE
-get_backtrace(VALUE info)
-{
-    if (NIL_P(info)) {
-	return Qnil;
-    }
-    info = rb_funcall(info, rb_intern("backtrace"), 0);
-    if (NIL_P(info)) {
-	return Qnil;
-    }
-    return rb_check_backtrace(info);
-}
-
-VALUE
-rb_get_backtrace(VALUE info)
-{
-    return get_backtrace(info);
-}
-
-static void
-set_backtrace(VALUE info, VALUE bt)
-{
-    rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
-}
-
-static void
-error_print(void)
-{
-#if 0
-    VALUE errat = Qnil;		/* OK */
-    VALUE errinfo = GET_THREAD()->errinfo;
-    volatile VALUE eclass, e;
-    const char *einfo;
-    long elen;
-
-    if (NIL_P(errinfo))
-	return;
-
-    PUSH_TAG();
-    if (EXEC_TAG() == 0) {
-	errat = get_backtrace(errinfo);
-    }
-    else {
-	errat = Qnil;
-    }
-    if (EXEC_TAG())
-	goto error;
-    if (NIL_P(errat)) {
-	const char *file = rb_sourcefile();
-	int line = rb_sourceline();
-	if (file)
-	    warn_printf("%s:%d", file, line);
-	else
-	    warn_printf("%d", line);
-    }
-    else if (RARRAY_LEN(errat) == 0) {
-	error_pos();
-    }
-    else {
-	VALUE mesg = RARRAY_AT(errat, 0);
-
-	if (NIL_P(mesg))
-	    error_pos();
-	else {
-	    warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
-	}
-    }
-
-    eclass = CLASS_OF(errinfo);
-    if (EXEC_TAG() == 0) {
-	e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
-	StringValue(e);
-	einfo = RSTRING_PTR(e);
-	elen = RSTRING_LEN(e);
-    }
-    else {
-	einfo = "";
-	elen = 0;
-    }
-    if (EXEC_TAG())
-	goto error;
-    if (eclass == rb_eRuntimeError && elen == 0) {
-	warn_print(": unhandled exception\n");
-    }
-    else {
-	VALUE epath;
-
-	epath = rb_class_name(eclass);
-	if (elen == 0) {
-	    warn_print(": ");
-	    warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
-	    warn_print("\n");
-	}
-	else {
-	    char *tail = 0;
-	    long len = elen;
-
-	    if (RSTRING_PTR(epath)[0] == '#')
-		epath = 0;
-	    if ((tail = memchr(einfo, '\n', elen)) != 0) {
-		len = tail - einfo;
-		tail++;		/* skip newline */
-	    }
-	    warn_print(": ");
-	    warn_print2(einfo, len);
-	    if (epath) {
-		warn_print(" (");
-		warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
-		warn_print(")\n");
-	    }
-	    if (tail) {
-		warn_print2(tail, elen - len - 1);
-		if (einfo[elen-1] != '\n') warn_print2("\n", 1);
-	    }
-	}
-    }
-
-    if (!NIL_P(errat)) {
-	long i;
-	long len = RARRAY_LEN(errat);
-        int skip = eclass == rb_eSysStackError;
-	
-#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
-#define TRACE_HEAD 8
-#define TRACE_TAIL 5
-
-	for (i = 1; i < len; i++) {
-	    VALUE v = RARRAY_AT(errat, i);
-	    if (TYPE(v) == T_STRING) {
-		warn_printf("\tfrom %s\n", RSTRING_PTR(v));
-	    }
-	    if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
-		warn_printf("\t ... %ld levels...\n",
-			    len - TRACE_HEAD - TRACE_TAIL);
-		i = len - TRACE_TAIL;
-	    }
-	}
-    }
-  error:
-    POP_TAG();
-#endif
-}
-
-void
-ruby_error_print(void)
-{
-    error_print();
-}
-
-void
-rb_print_undef(VALUE klass, ID id, int scope)
-{
-    const char *v;
-
-    switch (scope) {
-      default:
-      case NOEX_PUBLIC: v = ""; break;
-      case NOEX_PRIVATE: v = " private"; break;
-      case NOEX_PROTECTED: v = " protected"; break;
-    }
-    rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
-		  rb_id2name(id),
-		  (TYPE(klass) == T_MODULE) ? "module" : "class",
-		  rb_class2name(klass));
-}

Deleted: MacRuby/trunk/eval_jump.c
===================================================================
--- MacRuby/trunk/eval_jump.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/eval_jump.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,86 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-/*
- * from eval.c
- */
-
-/* exit */
-
-// TODO: move & lock me into RoxorCore
-static VALUE at_exit_procs = Qnil;
-
-/*
- *  call-seq:
- *     at_exit { block } -> proc
- *
- *  Converts _block_ to a +Proc+ object (and therefore
- *  binds it at the point of call) and registers it for execution when
- *  the program exits. If multiple handlers are registered, they are
- *  executed in reverse order of registration.
- *
- *     def do_at_exit(str1)
- *       at_exit { print str1 }
- *     end
- *     at_exit { puts "cruel world" }
- *     do_at_exit("goodbye ")
- *     exit
- *
- *  <em>produces:</em>
- *
- *     goodbye cruel world
- */
-
-static VALUE
-rb_f_at_exit(VALUE self, SEL sel)
-{
-    if (!rb_block_given_p()) {
-	rb_raise(rb_eArgError, "called without a block");
-    }
-    VALUE proc = rb_block_proc();
-    rb_ary_push(at_exit_procs, proc);
-    return proc;
-}
-
-static VALUE
-rb_end_proc_call_try(VALUE proc)
-{
-    return rb_proc_call2(proc, 0, NULL);
-}
-
-static VALUE
-rb_end_proc_call_catch(VALUE data, VALUE exc)
-{
-    rb_vm_print_exception(exc);
-    return Qnil;
-}
-
-void
-rb_exec_end_proc(void)
-{
-    while (true) {
-	const int count = RARRAY_LEN(at_exit_procs);
-	if (count > 0) {
-	    VALUE proc = RARRAY_AT(at_exit_procs, count - 1);
-	    rb_ary_delete_at(at_exit_procs, count - 1);	
-	    rb_rescue(rb_end_proc_call_try, proc, rb_end_proc_call_catch, 0);
-	    continue;
-	}
-	break;
-    }
-}
-
-void
-Init_jump(void)
-{
-    rb_objc_define_module_function(rb_mKernel, "at_exit", rb_f_at_exit, 0);
-
-    at_exit_procs = rb_ary_new();
-    GC_RETAIN(at_exit_procs);
-}

Deleted: MacRuby/trunk/eval_safe.c
===================================================================
--- MacRuby/trunk/eval_safe.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/eval_safe.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,117 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-/*
- * This file is included by eval.c
- */
-
-/* safe-level:
-   0 - strings from streams/environment/ARGV are tainted (default)
-   1 - no dangerous operation by tainted value
-   2 - process/file operations prohibited
-   3 - all generated objects are tainted
-   4 - no global (non-tainted) variable modification/no direct output
-*/
-
-#define SAFE_LEVEL_MAX 4
-
-/* $SAFE accessor */
-
-int
-rb_safe_level(void)
-{
-    return rb_vm_safe_level();
-}
-
-void
-rb_set_safe_level_force(int safe)
-{
-    rb_vm_set_safe_level(safe);
-}
-
-void
-rb_set_safe_level(int level)
-{
-    if (level > rb_vm_safe_level()) {
-	if (level > SAFE_LEVEL_MAX) {
-	    level = SAFE_LEVEL_MAX;
-	}
-	rb_vm_set_safe_level(level);
-    }
-}
-
-static VALUE
-safe_getter(void)
-{
-    return INT2NUM(rb_safe_level());
-}
-
-static void
-safe_setter(VALUE val)
-{
-    int level = NUM2INT(val);
-    int current_level = rb_vm_safe_level();
-
-    if (level < current_level) {
-	rb_raise(rb_eSecurityError,
-		 "tried to downgrade safe level from %d to %d",
-		 current_level, level);
-    }
-    if (level > SAFE_LEVEL_MAX) {
-	level = SAFE_LEVEL_MAX;
-    }
-    rb_vm_set_safe_level(level);
-}
-
-void
-rb_secure(int level)
-{
-    if (level <= rb_safe_level()) {
-	if (rb_frame_callee()) {
-	    rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
-		     rb_id2name(rb_frame_callee()), rb_safe_level());
-	}
-	else {
-	    rb_raise(rb_eSecurityError, "Insecure operation at level %d",
-		     rb_safe_level());
-	}
-    }
-}
-
-void
-rb_secure_update(VALUE obj)
-{
-    if (!OBJ_TAINTED(obj))
-	rb_secure(4);
-}
-
-void
-rb_check_safe_obj(VALUE x)
-{
-    if (rb_safe_level() > 0 && OBJ_TAINTED(x)) {
-	if (rb_frame_callee()) {
-	    rb_raise(rb_eSecurityError, "Insecure operation - %s",
-		     rb_id2name(rb_frame_callee()));
-	}
-	else {
-	    rb_raise(rb_eSecurityError, "Insecure operation: -r");
-	}
-    }
-    rb_secure(4);
-}
-
-void
-rb_check_safe_str(VALUE x)
-{
-    rb_check_safe_obj(x);
-    if (TYPE(x) != T_STRING) {
-	rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
-		 rb_obj_classname(x));
-    }
-}

Deleted: MacRuby/trunk/exported_symbols_list
===================================================================
--- MacRuby/trunk/exported_symbols_list	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/exported_symbols_list	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,27 +0,0 @@
-_rb_*
-_ruby_*
-_macruby_main
-.objc_class_name_MacRuby
-_LLVMLinkInJIT
-___auto_zone
-_st_*
-
-# used by the kernel:
-_rary_reserve
-_rhash_aref
-_rhash_aset
-_rstr_concat
-_selPLUS
-_selMINUS
-_selDIV
-_selMULT
-_selLT
-_selLE
-_selGT
-_selGE
-_selEq
-_selNeq
-_selEqq
-_selLTLT
-_selAREF
-_selASET

Deleted: MacRuby/trunk/file.c
===================================================================
--- MacRuby/trunk/file.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/file.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,4355 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/io.h"
-#include "ruby/signal.h"
-#include "ruby/util.h"
-#include "ruby/node.h"
-#include "dln.h"
-#include "objc.h"
-#include "vm.h"
-#include "encoding.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_FILE_H
-# include <sys/file.h>
-#else
-int flock(int, int);
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#include <ctype.h>
-
-#include <time.h>
-
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#elif defined HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#if !defined HAVE_LSTAT && !defined lstat
-#define lstat stat
-#endif
-
-#ifdef __BEOS__ /* should not change ID if -1 */
-static int
-be_chown(const char *path, uid_t owner, gid_t group)
-{
-    if (owner == -1 || group == -1) {
-	struct stat st;
-	if (stat(path, &st) < 0) return -1;
-	if (owner == -1) owner = st.st_uid;
-	if (group == -1) group = st.st_gid;
-    }
-    return chown(path, owner, group);
-}
-#define chown be_chown
-static int
-be_fchown(int fd, uid_t owner, gid_t group)
-{
-    if (owner == -1 || group == -1) {
-	struct stat st;
-	if (fstat(fd, &st) < 0) return -1;
-	if (owner == -1) owner = st.st_uid;
-	if (group == -1) group = st.st_gid;
-    }
-    return fchown(fd, owner, group);
-}
-#define fchown be_fchown
-#endif /* __BEOS__ */
-
-VALUE rb_cFile;
-VALUE rb_mFileTest;
-VALUE rb_cStat;
-
-static SEL selToPath = 0;
-
-static VALUE
-rb_get_path_check(VALUE obj, int check)
-{
-    VALUE tmp;
-
-    if (check) {
-	rb_check_safe_obj(obj);
-    }
-
-    if (rb_vm_respond_to(obj, selToPath, true)) {
-	tmp = rb_vm_call(obj, selToPath, 0, NULL);
-    }
-    else {
-	tmp = rb_check_string_type(obj);
-	if (NIL_P(tmp)) {
-	    tmp = obj;
-	}
-    }
-
-    StringValueCStr(tmp);
-    if (check && obj != tmp) {
-	rb_check_safe_obj(tmp);
-    }
-    return rb_str_new4(tmp);
-}
-
-VALUE
-rb_get_path_no_checksafe(VALUE obj)
-{
-    return rb_get_path_check(obj, 0);
-}
-
-VALUE
-rb_get_path(VALUE obj)
-{
-    return rb_get_path_check(obj, 1);
-}
-
-static long
-apply2files(void (*func)(const char *, void *), long argc, VALUE *argv,
-	void *arg)
-{
-    rb_secure(4);
-    for (long i = 0; i < argc; i++) {
-	VALUE path = rb_get_path(argv[i]);
-	(*func)(StringValueCStr(path), arg);
-    }
-    return argc;
-}
-
-/*
- *  call-seq:
- *     file.path -> filename
- *  
- *  Returns the pathname used to create <i>file</i> as a string. Does
- *  not normalize the name.
- *     
- *     File.new("testfile").path               #=> "testfile"
- *     File.new("/tmp/../tmp/xxx", "w").path   #=> "/tmp/../tmp/xxx"
- *     
- */
-
-static VALUE
-rb_file_path(VALUE obj, SEL sel)
-{
-    rb_io_t *io = ExtractIOStruct(obj);
-    return io->path == 0 ? Qnil : io->path;
-}
-
-static VALUE
-stat_new_0(VALUE klass, struct stat *st)
-{
-    struct stat *nst = 0;
-
-    if (st != NULL) {
-	nst = ALLOC(struct stat);
-	*nst = *st;
-    }
-    return Data_Wrap_Struct(klass, NULL, xfree, nst);
-}
-
-static VALUE
-stat_new(struct stat *st)
-{
-    return stat_new_0(rb_cStat, st);
-}
-
-static struct stat*
-get_stat(VALUE self)
-{
-    struct stat* st;
-    Data_Get_Struct(self, struct stat, st);
-    if (!st) rb_raise(rb_eTypeError, "uninitialized File::Stat");
-    return st;
-}
-
-static struct timespec stat_mtimespec(struct stat *st);
-
-/*
- *  call-seq:
- *     stat <=> other_stat    => -1, 0, 1
- *  
- *  Compares <code>File::Stat</code> objects by comparing their
- *  respective modification times.
- *     
- *     f1 = File.new("f1", "w")
- *     sleep 1
- *     f2 = File.new("f2", "w")
- *     f1.stat <=> f2.stat   #=> -1
- */
-
-static VALUE
-rb_stat_cmp(VALUE self, SEL sel, VALUE other)
-{
-    if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
-        struct timespec ts1 = stat_mtimespec(get_stat(self));
-        struct timespec ts2 = stat_mtimespec(get_stat(other));
-        if (ts1.tv_sec == ts2.tv_sec) {
-            if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0);
-            if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1);
-            return INT2FIX(1);
-        }
-        if (ts1.tv_sec < ts2.tv_sec) return INT2FIX(-1);
-        return INT2FIX(1);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     stat.dev    => fixnum
- *  
- *  Returns an integer representing the device on which <i>stat</i>
- *  resides.
- *     
- *     File.stat("testfile").dev   #=> 774
- */
-
-static VALUE
-rb_stat_dev(VALUE self, SEL sel)
-{
-    return INT2NUM(get_stat(self)->st_dev);
-}
-
-/*
- *  call-seq:
- *     stat.dev_major   => fixnum
- *  
- *  Returns the major part of <code>File_Stat#dev</code> or
- *  <code>nil</code>.
- *     
- *     File.stat("/dev/fd1").dev_major   #=> 2
- *     File.stat("/dev/tty").dev_major   #=> 5
- */
-
-static VALUE
-rb_stat_dev_major(VALUE self, SEL sel)
-{
-#if defined(major)
-    long dev = get_stat(self)->st_dev;
-    return ULONG2NUM(major(dev));
-#else
-    return Qnil;
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.dev_minor   => fixnum
- *  
- *  Returns the minor part of <code>File_Stat#dev</code> or
- *  <code>nil</code>.
- *     
- *     File.stat("/dev/fd1").dev_minor   #=> 1
- *     File.stat("/dev/tty").dev_minor   #=> 0
- */
-
-static VALUE
-rb_stat_dev_minor(VALUE self, SEL sel)
-{
-#if defined(minor)
-    long dev = get_stat(self)->st_dev;
-    return ULONG2NUM(minor(dev));
-#else
-    return Qnil;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     stat.ino   => fixnum
- *  
- *  Returns the inode number for <i>stat</i>.
- *     
- *     File.stat("testfile").ino   #=> 1083669
- *     
- */
-
-static VALUE
-rb_stat_ino(VALUE self, SEL sel)
-{
-#ifdef HUGE_ST_INO
-    return ULL2NUM(get_stat(self)->st_ino);
-#else
-    return ULONG2NUM(get_stat(self)->st_ino);
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.mode   => fixnum
- *  
- *  Returns an integer representing the permission bits of
- *  <i>stat</i>. The meaning of the bits is platform dependent; on
- *  Unix systems, see <code>stat(2)</code>.
- *     
- *     File.chmod(0644, "testfile")   #=> 1
- *     s = File.stat("testfile")
- *     sprintf("%o", s.mode)          #=> "100644"
- */
-
-static VALUE
-rb_stat_mode(VALUE self, SEL sel)
-{
-#ifdef __BORLANDC__
-    return UINT2NUM((unsigned short)(get_stat(self)->st_mode));
-#else
-    return UINT2NUM(get_stat(self)->st_mode);
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.nlink   => fixnum
- *  
- *  Returns the number of hard links to <i>stat</i>.
- *     
- *     File.stat("testfile").nlink             #=> 1
- *     File.link("testfile", "testfile.bak")   #=> 0
- *     File.stat("testfile").nlink             #=> 2
- *     
- */
-
-static VALUE
-rb_stat_nlink(VALUE self, SEL sel)
-{
-    return UINT2NUM(get_stat(self)->st_nlink);
-}
-
-
-/*
- *  call-seq:
- *     stat.uid    => fixnum
- *  
- *  Returns the numeric user id of the owner of <i>stat</i>.
- *     
- *     File.stat("testfile").uid   #=> 501
- *     
- */
-
-static VALUE
-rb_stat_uid(VALUE self, SEL sel)
-{
-    return UIDT2NUM(get_stat(self)->st_uid);
-}
-
-/*
- *  call-seq:
- *     stat.gid   => fixnum
- *  
- *  Returns the numeric group id of the owner of <i>stat</i>.
- *     
- *     File.stat("testfile").gid   #=> 500
- *     
- */
-
-static VALUE
-rb_stat_gid(VALUE self, SEL sel)
-{
-    return GIDT2NUM(get_stat(self)->st_gid);
-}
-
-
-/*
- *  call-seq:
- *     stat.rdev   =>  fixnum or nil
- *  
- *  Returns an integer representing the device type on which
- *  <i>stat</i> resides. Returns <code>nil</code> if the operating
- *  system doesn't support this feature.
- *     
- *     File.stat("/dev/fd1").rdev   #=> 513
- *     File.stat("/dev/tty").rdev   #=> 1280
- */
-
-static VALUE
-rb_stat_rdev(VALUE self, SEL sel)
-{
-#ifdef HAVE_ST_RDEV
-    return ULONG2NUM(get_stat(self)->st_rdev);
-#else
-    return Qnil;
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.rdev_major   => fixnum
- *  
- *  Returns the major part of <code>File_Stat#rdev</code> or
- *  <code>nil</code>.
- *     
- *     File.stat("/dev/fd1").rdev_major   #=> 2
- *     File.stat("/dev/tty").rdev_major   #=> 5
- */
-
-static VALUE
-rb_stat_rdev_major(VALUE self, SEL sel)
-{
-#if defined(HAVE_ST_RDEV) && defined(major)
-    long rdev = get_stat(self)->st_rdev;
-    return ULONG2NUM(major(rdev));
-#else
-    return Qnil;
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.rdev_minor   => fixnum
- *  
- *  Returns the minor part of <code>File_Stat#rdev</code> or
- *  <code>nil</code>.
- *     
- *     File.stat("/dev/fd1").rdev_minor   #=> 1
- *     File.stat("/dev/tty").rdev_minor   #=> 0
- */
-
-static VALUE
-rb_stat_rdev_minor(VALUE self, SEL sel)
-{
-#if defined(HAVE_ST_RDEV) && defined(minor)
-    long rdev = get_stat(self)->st_rdev;
-    return ULONG2NUM(minor(rdev));
-#else
-    return Qnil;
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.size    => fixnum
- *  
- *  Returns the size of <i>stat</i> in bytes.
- *     
- *     File.stat("testfile").size   #=> 66
- */
-
-static VALUE
-rb_stat_size(VALUE self, SEL sel)
-{
-    return OFFT2NUM(get_stat(self)->st_size);
-}
-
-/*
- *  call-seq:
- *     stat.blksize   => integer or nil
- *  
- *  Returns the native file system's block size. Will return <code>nil</code>
- *  on platforms that don't support this information.
- *     
- *     File.stat("testfile").blksize   #=> 4096
- *     
- */
-
-static VALUE
-rb_stat_blksize(VALUE self, SEL sel)
-{
-#ifdef HAVE_ST_BLKSIZE
-    return ULONG2NUM(get_stat(self)->st_blksize);
-#else
-    return Qnil;
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.blocks    => integer or nil
- *  
- *  Returns the number of native file system blocks allocated for this
- *  file, or <code>nil</code> if the operating system doesn't 
- *  support this feature.
- *     
- *     File.stat("testfile").blocks   #=> 2
- */
-
-static VALUE
-rb_stat_blocks(VALUE self, SEL sel)
-{
-#ifdef HAVE_ST_BLOCKS
-    return ULONG2NUM(get_stat(self)->st_blocks);
-#else
-    return Qnil;
-#endif
-}
-
-static struct timespec
-stat_atimespec(struct stat *st)
-{
-    struct timespec ts;
-    ts.tv_sec = st->st_atime;
-#if defined(HAVE_STRUCT_STAT_ST_ATIM)
-    ts.tv_nsec = st->st_atim.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
-    ts.tv_nsec = st->st_atimespec.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
-    ts.tv_nsec = st->st_atimensec;
-#else
-    ts.tv_nsec = 0;
-#endif
-    return ts;
-}
-
-static VALUE
-stat_atime(struct stat *st)
-{
-    struct timespec ts = stat_atimespec(st);
-    return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
-}
-
-static struct timespec
-stat_mtimespec(struct stat *st)
-{
-    struct timespec ts;
-    ts.tv_sec = st->st_mtime;
-#if defined(HAVE_STRUCT_STAT_ST_MTIM)
-    ts.tv_nsec = st->st_mtim.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
-    ts.tv_nsec = st->st_mtimespec.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
-    ts.tv_nsec = st->st_mtimensec;
-#else
-    ts.tv_nsec = 0;
-#endif
-    return ts;
-}
-
-static VALUE
-stat_mtime(struct stat *st)
-{
-    struct timespec ts = stat_mtimespec(st);
-    return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
-}
-
-static struct timespec
-stat_ctimespec(struct stat *st)
-{
-    struct timespec ts;
-    ts.tv_sec = st->st_ctime;
-#if defined(HAVE_STRUCT_STAT_ST_CTIM)
-    ts.tv_nsec = st->st_ctim.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
-    ts.tv_nsec = st->st_ctimespec.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
-    ts.tv_nsec = st->st_ctimensec;
-#else
-    ts.tv_nsec = 0;
-#endif
-    return ts;
-}
-
-static VALUE
-stat_ctime(struct stat *st)
-{
-    struct timespec ts = stat_ctimespec(st);
-    return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
-}
-
-/*
- *  call-seq:
- *     stat.atime   => time
- *  
- *  Returns the last access time for this file as an object of class
- *  <code>Time</code>.
- *     
- *     File.stat("testfile").atime   #=> Wed Dec 31 18:00:00 CST 1969
- *     
- */
-
-static VALUE
-rb_stat_atime(VALUE self, SEL sel)
-{
-    return stat_atime(get_stat(self));
-}
-
-/*
- *  call-seq:
- *     stat.mtime -> aTime
- *  
- *  Returns the modification time of <i>stat</i>.
- *     
- *     File.stat("testfile").mtime   #=> Wed Apr 09 08:53:14 CDT 2003
- *     
- */
-
-static VALUE
-rb_stat_mtime(VALUE self, SEL sel)
-{
-    return stat_mtime(get_stat(self));
-}
-
-/*
- *  call-seq:
- *     stat.ctime -> aTime
- *  
- *  Returns the change time for <i>stat</i> (that is, the time
- *  directory information about the file was changed, not the file
- *  itself).
- *     
- *     File.stat("testfile").ctime   #=> Wed Apr 09 08:53:14 CDT 2003
- *     
- */
-
-static VALUE
-rb_stat_ctime(VALUE self, SEL sel)
-{
-    return stat_ctime(get_stat(self));
-}
-
-/*
- * call-seq:
- *   stat.inspect  =>  string
- *
- * Produce a nicely formatted description of <i>stat</i>.
- *
- *   File.stat("/etc/passwd").inspect
- *      #=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644, 
- *           nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096, 
- *           blocks=8, atime=Wed Dec 10 10:16:12 CST 2003, 
- *           mtime=Fri Sep 12 15:41:41 CDT 2003, 
- *           ctime=Mon Oct 27 11:20:27 CST 2003>"
- */
-
-static VALUE
-rb_stat_inspect(VALUE self, SEL sel)
-{
-    VALUE str;
-    int i;
-    static const struct {
-	const char *name;
-	VALUE (*func)(VALUE, SEL);
-    } member[] = {
-	{"dev",	    rb_stat_dev},
-	{"ino",	    rb_stat_ino},
-	{"mode",    rb_stat_mode},
-	{"nlink",   rb_stat_nlink},
-	{"uid",	    rb_stat_uid},
-	{"gid",	    rb_stat_gid},
-	{"rdev",    rb_stat_rdev},
-	{"size",    rb_stat_size},
-	{"blksize", rb_stat_blksize},
-	{"blocks",  rb_stat_blocks},
-	{"atime",   rb_stat_atime},
-	{"mtime",   rb_stat_mtime},
-	{"ctime",   rb_stat_ctime},
-    };
-
-    str = rb_str_buf_new2("#<");
-    rb_str_buf_cat2(str, rb_obj_classname(self));
-    rb_str_buf_cat2(str, " ");
-
-    for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
-	VALUE v;
-
-	if (i > 0) {
-	    rb_str_buf_cat2(str, ", ");
-	}
-	rb_str_buf_cat2(str, member[i].name);
-	rb_str_buf_cat2(str, "=");
-	v = (*member[i].func)(self, 0);
-	if (i == 2) {		/* mode */
-	    char buf[32];
-
-	    sprintf(buf, "0%lo", NUM2ULONG(v));
-	    rb_str_buf_cat2(str, buf);
-	}
-	else if (i == 0 || i == 6) { /* dev/rdev */
-	    char buf[32];
-
-	    sprintf(buf, "0x%lx", NUM2ULONG(v));
-	    rb_str_buf_cat2(str, buf);
-	}
-	else {
-	    rb_str_append(str, rb_inspect(v));
-	}
-    }
-    rb_str_buf_cat2(str, ">");
-    OBJ_INFECT(str, self);
-
-    return str;
-}
-
-static int
-rb_stat(VALUE file, struct stat *st)
-{
-    rb_secure(2);
-    VALUE tmp = rb_check_convert_type(file, T_FILE, "IO", "to_io");
-    if (!NIL_P(tmp)) {
-	rb_io_t *io_struct = ExtractIOStruct(tmp);
-	return fstat(io_struct->fd, st);
-    }
-    FilePathValue(file);
-    return stat(StringValueCStr(file), st);
-}
-
-/*
- *  call-seq:
- *     File.stat(file_name)   =>  stat
- *  
- *  Returns a <code>File::Stat</code> object for the named file (see
- *  <code>File::Stat</code>).
- *     
- *     File.stat("testfile").mtime   #=> Tue Apr 08 12:58:04 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_s_stat(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    rb_secure(4);
-    FilePathValue(fname);
-    if (rb_stat(fname, &st) < 0) {
-	rb_sys_fail(StringValueCStr(fname));
-    }
-    return stat_new(&st);
-}
-
-/*
- *  call-seq:
- *     ios.stat    => stat
- *  
- *  Returns status information for <em>ios</em> as an object of type
- *  <code>File::Stat</code>.
- *     
- *     f = File.new("testfile")
- *     s = f.stat
- *     "%o" % s.mode   #=> "100644"
- *     s.blksize       #=> 4096
- *     s.atime         #=> Wed Apr 09 08:53:54 CDT 2003
- *     
- */
-
-static VALUE
-rb_io_stat(VALUE obj, SEL sel)
-{
-    struct rb_io_t *io = ExtractIOStruct(obj);
-    rb_io_check_closed(io);
-    
-    struct stat st;
-    if (fstat(io->fd, &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return stat_new(&st);
-}
-
-/*
- *  call-seq:
- *     File.lstat(file_name)   => stat
- *  
- *  Same as <code>File::stat</code>, but does not follow the last symbolic
- *  link. Instead, reports on the link itself.
- *     
- *     File.symlink("testfile", "link2test")   #=> 0
- *     File.stat("testfile").size              #=> 66
- *     File.lstat("link2test").size            #=> 8
- *     File.stat("link2test").size             #=> 66
- *     
- */
-
-static VALUE
-rb_file_s_lstat(VALUE klass, SEL sel, VALUE fname)
-{
-#ifdef HAVE_LSTAT
-    struct stat st;
-
-    rb_secure(2);
-    FilePathValue(fname);
-    if (lstat(StringValueCStr(fname), &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(fname));
-    }
-    return stat_new(&st);
-#else
-    return rb_file_s_stat(klass, 0, fname);
-#endif
-}
-
-
-/*
- *  call-seq:
- *     file.lstat   =>  stat
- *  
- *  Same as <code>IO#stat</code>, but does not follow the last symbolic
- *  link. Instead, reports on the link itself.
- *     
- *     File.symlink("testfile", "link2test")   #=> 0
- *     File.stat("testfile").size              #=> 66
- *     f = File.new("link2test")
- *     f.lstat.size                            #=> 8
- *     f.stat.size                             #=> 66
- */
-
-#if HAVE_LSTAT
-static VALUE
-rb_file_lstat(VALUE obj, SEL sel)
-{
-    rb_io_t *fptr;
-    struct stat st;
-
-    rb_secure(2);
-    GetOpenFile(obj, fptr);
-    if (fptr->path == 0) {
-	return Qnil;
-    }
-    if (lstat(RSTRING_PTR(fptr->path), &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(fptr->path));
-    }
-    return stat_new(&st);
-}
-#else
-# define rb_file_lstat rb_f_notimplement
-#endif
-
-#ifndef HAVE_GROUP_MEMBER
-static int
-group_member(GETGROUPS_T gid)
-{
-#ifndef _WIN32
-    if (getgid() == gid || getegid() == gid)
-	return Qtrue;
-
-# ifdef HAVE_GETGROUPS
-#  ifndef NGROUPS
-#   ifdef NGROUPS_MAX
-#    define NGROUPS NGROUPS_MAX
-#   else
-#    define NGROUPS 32
-#   endif
-#  endif
-    {
-	GETGROUPS_T gary[NGROUPS];
-	int anum;
-
-	anum = getgroups(NGROUPS, gary);
-	while (--anum >= 0)
-	    if (gary[anum] == gid)
-		return Qtrue;
-    }
-# endif
-#endif
-    return Qfalse;
-}
-#endif
-
-#ifndef S_IXUGO
-#  define S_IXUGO		(S_IXUSR | S_IXGRP | S_IXOTH)
-#endif
-
-#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
-#define USE_GETEUID 1
-#endif
-
-#ifndef HAVE_EACCESS
-int
-eaccess(const char *path, int mode)
-{
-#ifdef USE_GETEUID
-    struct stat st;
-    rb_uid_t euid;
-
-    if (stat(path, &st) < 0) {
-	return -1;
-    }
-
-    euid = geteuid();
-
-    if (euid == 0) {
-	/* Root can read or write any file. */
-	if (!(mode & X_OK)) {
-	    return 0;
-	}
-
-	/* Root can execute any file that has any one of the execute
-	   bits set. */
-	if (st.st_mode & S_IXUGO) {
-	    return 0;
-	}
-
-	return -1;
-    }
-
-    if (st.st_uid == euid) {       /* owner */
-	mode <<= 6;
-    }
-    else if (group_member(st.st_gid)) {
-	mode <<= 3;
-    }
-
-    if ((st.st_mode & mode) == mode) {
-	return 0;
-    }
-
-    return -1;
-#else
-    return access(path, mode);
-#endif
-}
-#endif
-
-
-/*
- * Document-class: FileTest
- *
- *  <code>FileTest</code> implements file test operations similar to
- *  those used in <code>File::Stat</code>. It exists as a standalone
- *  module, and its methods are also insinuated into the <code>File</code>
- *  class. (Note that this is not done by inclusion: the interpreter cheats).
- *     
- */
-
-
-/*
- *   File.directory?(file_name)   =>  true or false
- *   File.directory?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a directory,
- * <code>false</code> otherwise.
- *
- *    File.directory?(".")
- */
-
-/*
- * Document-method: exist?
- *
- * call-seq:
- *   Dir.exist?(file_name)   =>  true or false
- *   Dir.exists?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a directory,
- * <code>false</code> otherwise.
- *
- */
-
-/*
- * Document-method: directory?
- *
- * call-seq:
- *   File.directory?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a directory,
- * <code>false</code> otherwise.
- *
- *    File.directory?(".")
- */
-
-VALUE
-rb_file_directory_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef S_ISDIR
-#   define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISDIR(st.st_mode)) return Qtrue;
-    return Qfalse;
-}
-
-
-/*
- * call-seq:
- *   File.pipe?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a pipe.
- */
-
-static VALUE
-rb_file_pipe_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifdef S_IFIFO
-#  ifndef S_ISFIFO
-#    define S_ISFIFO(m) ((m & S_IFMT) == S_IFIFO)
-#  endif
-
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISFIFO(st.st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   File.symlink?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a symbolic link.
- */
-
-static VALUE
-rb_file_symlink_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef S_ISLNK
-#  ifdef _S_ISLNK
-#    define S_ISLNK(m) _S_ISLNK(m)
-#  else
-#    ifdef _S_IFLNK
-#      define S_ISLNK(m) ((m & S_IFMT) == _S_IFLNK)
-#    else
-#      ifdef S_IFLNK
-#	 define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifdef S_ISLNK
-    struct stat st;
-
-    rb_secure(2);
-    FilePathValue(fname);
-    if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
-    if (S_ISLNK(st.st_mode)) return Qtrue;
-#endif
-
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   File.socket?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a socket.
- */
-
-static VALUE
-rb_file_socket_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef S_ISSOCK
-#  ifdef _S_ISSOCK
-#    define S_ISSOCK(m) _S_ISSOCK(m)
-#  else
-#    ifdef _S_IFSOCK
-#      define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
-#    else
-#      ifdef S_IFSOCK
-#	 define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifdef S_ISSOCK
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISSOCK(st.st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   File.blockdev?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a block device.
- */
-
-static VALUE
-rb_file_blockdev_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef S_ISBLK
-#   ifdef S_IFBLK
-#	define S_ISBLK(m) ((m & S_IFMT) == S_IFBLK)
-#   else
-#	define S_ISBLK(m) (0)  /* anytime false */
-#   endif
-#endif
-
-#ifdef S_ISBLK
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISBLK(st.st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   File.chardev?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file is a character device.
- */
-static VALUE
-rb_file_chardev_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef S_ISCHR
-#   define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR)
-#endif
-
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISCHR(st.st_mode)) return Qtrue;
-
-    return Qfalse;
-}
-
-
-/*
- * call-seq:
- *    File.exist?(file_name)    =>  true or false
- *    File.exists?(file_name)   =>  true or false
- *
- * Return <code>true</code> if the named file exists.
- */
-
-static VALUE
-rb_file_exist_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.readable?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is readable by the effective
- * user id of this process.
- */
-
-static VALUE
-rb_file_readable_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.readable_real?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is readable by the real
- * user id of this process.
- */
-
-static VALUE
-rb_file_readable_real_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-#ifndef S_IRUGO
-#  define S_IRUGO		(S_IRUSR | S_IRGRP | S_IROTH)
-#endif
-
-#ifndef S_IWUGO
-#  define S_IWUGO		(S_IWUSR | S_IWGRP | S_IWOTH)
-#endif
-
-/*
- * call-seq:
- *    File.world_readable?(file_name)   => fixnum or nil
- *
- * If <i>file_name</i> is readable by others, returns an integer
- * representing the file permission bits of <i>file_name</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *     
- *    File.world_readable?("/etc/passwd")	    # => 420
- *    m = File.world_readable?("/etc/passwd")
- *    sprintf("%o", m)				    # => "644"
- */
-
-static VALUE
-rb_file_world_readable_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifdef S_IROTH
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qnil;
-    if ((st.st_mode & (S_IROTH)) == S_IROTH) {
-	return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
-    }
-#endif
-    return Qnil;
-}
-
-/*
- * call-seq:
- *    File.writable?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is writable by the effective
- * user id of this process.
- */
-
-static VALUE
-rb_file_writable_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.writable_real?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is writable by the real
- * user id of this process.
- */
-
-static VALUE
-rb_file_writable_real_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.world_writable?(file_name)   => fixnum or nil
- *
- * If <i>file_name</i> is writable by others, returns an integer
- * representing the file permission bits of <i>file_name</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *     
- *    File.world_writable?("/tmp")		    #=> 511
- *    m = File.world_writable?("/tmp")
- *    sprintf("%o", m)				    #=> "777"
- */
-
-static VALUE
-rb_file_world_writable_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) {
-	return Qnil;
-    }
-    if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
-	return UINT2NUM(st.st_mode & (S_IRUGO | S_IWUGO | S_IXUGO));
-    }
-    return Qnil;
-}
-
-/*
- * call-seq:
- *    File.executable?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is executable by the effective
- * user id of this process.
- */
-
-static VALUE
-rb_file_executable_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.executable_real?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file is executable by the real
- * user id of this process.
- */
-
-static VALUE
-rb_file_executable_real_p(VALUE obj, SEL sel, VALUE fname)
-{
-    rb_secure(2);
-    FilePathValue(fname);
-    if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
-    return Qtrue;
-}
-
-#ifndef S_ISREG
-#   define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
-#endif
-
-/*
- * call-seq:
- *    File.file?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file exists and is a
- * regular file.
- */
-
-static VALUE
-rb_file_file_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (S_ISREG(st.st_mode)) return Qtrue;
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *    File.zero?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file exists and has
- * a zero size.
- */
-
-static VALUE
-rb_file_zero_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (st.st_size == 0) return Qtrue;
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *    File.size?(file_name)   => Integer or nil
- *
- * Returns +nil+ if +file_name+ doesn't exist or has zero size, the size of the
- * file otherwise.
- */
-
-static VALUE
-rb_file_size_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qnil;
-    if (st.st_size == 0) return Qnil;
-    return OFFT2NUM(st.st_size);
-}
-
-/*
- * call-seq:
- *    File.owned?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file exists and the
- * effective used id of the calling process is the owner of
- * the file.
- */
-
-static VALUE
-rb_file_owned_p(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (st.st_uid == geteuid()) return Qtrue;
-    return Qfalse;
-}
-
-static VALUE
-rb_file_rowned_p(VALUE obj, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (st.st_uid == getuid()) return Qtrue;
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *    File.grpowned?(file_name)   => true or false
- *
- * Returns <code>true</code> if the named file exists and the
- * effective group id of the calling process is the owner of
- * the file. Returns <code>false</code> on Windows.
- */
-
-static VALUE
-rb_file_grpowned_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifndef _WIN32
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0) return Qfalse;
-    if (group_member(st.st_gid)) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
-static VALUE
-check3rdbyte(VALUE fname, int mode)
-{
-    struct stat st;
-
-    rb_secure(2);
-    FilePathValue(fname);
-    if (stat(StringValueCStr(fname), &st) < 0) return Qfalse;
-    if (st.st_mode & mode) return Qtrue;
-    return Qfalse;
-}
-#endif
-
-/*
- * call-seq:
- *   File.setuid?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file has the setuid bit set.
- */
-
-static VALUE
-rb_file_suid_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifdef S_ISUID
-    return check3rdbyte(fname, S_ISUID);
-#else
-    return Qfalse;
-#endif
-}
-
-/*
- * call-seq:
- *   File.setgid?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file has the setgid bit set.
- */
-
-static VALUE
-rb_file_sgid_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifdef S_ISGID
-    return check3rdbyte(fname, S_ISGID);
-#else
-    return Qfalse;
-#endif
-}
-
-/*
- * call-seq:
- *   File.sticky?(file_name)   =>  true or false
- *
- * Returns <code>true</code> if the named file has the sticky bit set.
- */
-
-static VALUE
-rb_file_sticky_p(VALUE obj, SEL sel, VALUE fname)
-{
-#ifdef S_ISVTX
-    return check3rdbyte(fname, S_ISVTX);
-#else
-    return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- *   File.identical?(file_1, file_2)   =>  true or false
- *
- * Returns <code>true</code> if the named files are identical.
- *
- *     open("a", "w") {}
- *     p File.identical?("a", "a")      #=> true
- *     p File.identical?("a", "./a")    #=> true
- *     File.link("a", "b")
- *     p File.identical?("a", "b")      #=> true
- *     File.symlink("a", "c")
- *     p File.identical?("a", "c")      #=> true
- *     open("d", "w") {}
- *     p File.identical?("a", "d")      #=> false
- */
-
-static VALUE
-rb_file_identical_p(VALUE obj, SEL sel, VALUE fname1, VALUE fname2)
-{
-    struct stat st1, st2;
-
-    if (rb_stat(fname1, &st1) < 0) return Qfalse;
-    if (rb_stat(fname2, &st2) < 0) return Qfalse;
-    if (st1.st_dev != st2.st_dev) return Qfalse;
-    if (st1.st_ino != st2.st_ino) return Qfalse;
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    File.size(file_name)   => integer
- *
- * Returns the size of <code>file_name</code>.
- */
-
-static VALUE
-rb_file_s_size(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0)
-	rb_sys_fail(StringValueCStr(fname));
-    return OFFT2NUM(st.st_size);
-}
-
-static VALUE
-rb_file_size(VALUE obj, SEL sel)
-{
-    struct stat st;
-    struct rb_io_t *io = ExtractIOStruct(obj);
-    rb_io_check_closed(io);
-    if (fstat(io->fd, &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return OFFT2NUM(st.st_size);
-}
-
-static VALUE
-rb_file_ftype(const struct stat *st)
-{
-    const char *t;
-
-    if (S_ISREG(st->st_mode)) {
-	t = "file";
-    }
-    else if (S_ISDIR(st->st_mode)) {
-	t = "directory";
-    }
-    else if (S_ISCHR(st->st_mode)) {
-	t = "characterSpecial";
-    }
-#ifdef S_ISBLK
-    else if (S_ISBLK(st->st_mode)) {
-	t = "blockSpecial";
-    }
-#endif
-#ifdef S_ISFIFO
-    else if (S_ISFIFO(st->st_mode)) {
-	t = "fifo";
-    }
-#endif
-#ifdef S_ISLNK
-    else if (S_ISLNK(st->st_mode)) {
-	t = "link";
-    }
-#endif
-#ifdef S_ISSOCK
-    else if (S_ISSOCK(st->st_mode)) {
-	t = "socket";
-    }
-#endif
-    else {
-	t = "unknown";
-    }
-
-    return rb_usascii_str_new2(t);
-}
-
-/*
- *  call-seq:
- *     File.ftype(file_name)   => string
- *  
- *  Identifies the type of the named file; the return string is one of
- *  ``<code>file</code>'', ``<code>directory</code>'',
- *  ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
- *  ``<code>fifo</code>'', ``<code>link</code>'',
- *  ``<code>socket</code>'', or ``<code>unknown</code>''.
- *     
- *     File.ftype("testfile")            #=> "file"
- *     File.ftype("/dev/tty")            #=> "characterSpecial"
- *     File.ftype("/tmp/.X11-unix/X0")   #=> "socket"
- */
-
-static VALUE
-rb_file_s_ftype(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    rb_secure(2);
-    FilePathValue(fname);
-    if (lstat(StringValueCStr(fname), &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(fname));
-    }
-
-    return rb_file_ftype(&st);
-}
-
-/*
- *  call-seq:
- *     File.atime(file_name)  =>  time
- *  
- *  Returns the last access time for the named file as a Time object).
- *     
- *     File.atime("testfile")   #=> Wed Apr 09 08:51:48 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_s_atime(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0)
-	rb_sys_fail(StringValueCStr(fname));
-    return stat_atime(&st);
-}
-
-/*
- *  call-seq:
- *     file.atime    => time
- *  
- *  Returns the last access time (a <code>Time</code> object)
- *   for <i>file</i>, or epoch if <i>file</i> has not been accessed.
- *     
- *     File.new("testfile").atime   #=> Wed Dec 31 18:00:00 CST 1969
- *     
- */
-
-static VALUE
-rb_file_atime(VALUE obj, SEL sel)
-{
-    struct stat st;
-    struct rb_io_t *io = ExtractIOStruct(obj);
-    if (fstat(io->fd, &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return stat_atime(&st);
-}
-
-/*
- *  call-seq:
- *     File.mtime(file_name)  =>  time
- *  
- *  Returns the modification time for the named file as a Time object.
- *     
- *     File.mtime("testfile")   #=> Tue Apr 08 12:58:04 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_s_mtime(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0)
-	rb_sys_fail(RSTRING_PTR(fname));
-    return stat_mtime(&st);
-}
-
-/*
- *  call-seq:
- *     file.mtime -> time
- *  
- *  Returns the modification time for <i>file</i>.
- *     
- *     File.new("testfile").mtime   #=> Wed Apr 09 08:53:14 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_mtime(VALUE obj, SEL sel)
-{
-    struct stat st;
-    struct rb_io_t *io = ExtractIOStruct(obj);
-    if (fstat(io->fd, &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return stat_mtime(&st);
-}
-
-/*
- *  call-seq:
- *     File.ctime(file_name)  => time
- *  
- *  Returns the change time for the named file (the time at which
- *  directory information about the file was changed, not the file
- *  itself).
- *     
- *     File.ctime("testfile")   #=> Wed Apr 09 08:53:13 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_s_ctime(VALUE klass, SEL sel, VALUE fname)
-{
-    struct stat st;
-
-    if (rb_stat(fname, &st) < 0)
-	rb_sys_fail(RSTRING_PTR(fname));
-    return stat_ctime(&st);
-}
-
-/*
- *  call-seq:
- *     file.ctime -> time
- *  
- *  Returns the change time for <i>file</i> (that is, the time directory
- *  information about the file was changed, not the file itself).
- *     
- *     File.new("testfile").ctime   #=> Wed Apr 09 08:53:14 CDT 2003
- *     
- */
-
-static VALUE
-rb_file_ctime(VALUE obj, SEL sel)
-{
-    struct stat st;
-    struct rb_io_t *io = ExtractIOStruct(obj);
-    if (fstat(io->fd, &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return stat_ctime(&st);
-}
-
-static void
-chmod_internal(const char *path, void *mode)
-{
-    if (chmod(path, *(int *)mode) < 0)
-	rb_sys_fail(path);
-}
-
-/*
- *  call-seq:
- *     File.chmod(mode_int, file_name, ... ) -> integer
- *  
- *  Changes permission bits on the named file(s) to the bit pattern
- *  represented by <i>mode_int</i>. Actual effects are operating system
- *  dependent (see the beginning of this section). On Unix systems, see
- *  <code>chmod(2)</code> for details. Returns the number of files
- *  processed.
- *     
- *     File.chmod(0644, "testfile", "out")   #=> 2
- */
-
-static VALUE
-rb_file_s_chmod(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(2);
-    if (argc < 1) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-    VALUE vmode = argv[0];
-    vmode = rb_check_to_integer(vmode, "to_int");
-    if (NIL_P(vmode)) {
-	rb_raise(rb_eTypeError, "chmod() takes a numeric argument");
-    }
-    int mode = NUM2INT(vmode);
-
-    long n = apply2files(chmod_internal, argc - 1, &argv[1], &mode);
-    return LONG2FIX(n);
-}
-
-/*
- *  call-seq:
- *     file.chmod(mode_int)   => 0
- *  
- *  Changes permission bits on <i>file</i> to the bit pattern
- *  represented by <i>mode_int</i>. Actual effects are platform
- *  dependent; on Unix systems, see <code>chmod(2)</code> for details.
- *  Follows symbolic links. Also see <code>File#lchmod</code>.
- *     
- *     f = File.new("out", "w");
- *     f.chmod(0644)   #=> 0
- */
-
-static VALUE
-rb_file_chmod(VALUE obj, SEL sel, VALUE vmode)
-{
-    rb_secure(2);
-    rb_io_t *io = ExtractIOStruct(obj);
-    vmode = rb_check_to_integer(vmode, "to_int");
-    if (NIL_P(vmode)) {
-	rb_raise(rb_eTypeError, "chmod() takes a numeric argument");
-    }
-    if (fchmod(io->fd, FIX2INT(vmode)) == -1) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return INT2FIX(0);
-}
-
-#if defined(HAVE_LCHMOD)
-static void
-lchmod_internal(const char *path, void *mode)
-{
-    if (lchmod(path, (int)(VALUE)mode) < 0)
-	rb_sys_fail(path);
-}
-
-/*
- *  call-seq:
- *     File.lchmod(mode_int, file_name, ...)  => integer
- *  
- *  Equivalent to <code>File::chmod</code>, but does not follow symbolic
- *  links (so it will change the permissions associated with the link,
- *  not the file referenced by the link). Often not available.
- *     
- */
-
-static VALUE
-rb_file_s_lchmod(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(2);
-    if (argc < 1) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-    VALUE vmode = argv[0];
-    int mode = NUM2INT(vmode);
-
-    long n = apply2files(lchmod_internal, argc - 1, &argv[1],
-	    (void *)(long)mode);
-    return LONG2FIX(n);
-}
-#else
-# define rb_file_s_lchmod rb_f_notimplement
-#endif
-
-struct chown_args {
-    rb_uid_t owner;
-    rb_gid_t group;
-};
-
-static void
-chown_internal(const char *path, void *arg)
-{
-    struct chown_args *args = arg;
-    if (chown(path, args->owner, args->group) < 0)
-	rb_sys_fail(path);
-}
-
-/*
- *  call-seq:
- *     File.chown(owner_int, group_int, file_name,... ) -> integer
- *  
- *  Changes the owner and group of the named file(s) to the given
- *  numeric owner and group id's. Only a process with superuser
- *  privileges may change the owner of a file. The current owner of a
- *  file may change the file's group to any group to which the owner
- *  belongs. A <code>nil</code> or -1 owner or group id is ignored.
- *  Returns the number of files processed.
- *     
- *     File.chown(nil, 100, "testfile")
- *     
- */
-
-static VALUE
-rb_file_s_chown(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(2);
-    if (argc < 2) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-    VALUE o = argv[0];
-    VALUE g = argv[1];
-    struct chown_args arg;
-    if (NIL_P(o)) {
-	arg.owner = -1;
-    }
-    else {
-	arg.owner = NUM2UIDT(o);
-    }
-    if (NIL_P(g)) {
-	arg.group = -1;
-    }
-    else {
-	arg.group = NUM2GIDT(g);
-    }
-
-    long n = apply2files(chown_internal, argc - 2, &argv[2], &arg);
-    return LONG2FIX(n);
-}
-
-/*
- *  call-seq:
- *     file.chown(owner_int, group_int )   => 0
- *  
- *  Changes the owner and group of <i>file</i> to the given numeric
- *  owner and group id's. Only a process with superuser privileges may
- *  change the owner of a file. The current owner of a file may change
- *  the file's group to any group to which the owner belongs. A
- *  <code>nil</code> or -1 owner or group id is ignored. Follows
- *  symbolic links. See also <code>File#lchown</code>.
- *     
- *     File.new("testfile").chown(502, 1000)
- *     
- */
-
-static VALUE
-rb_file_chown(VALUE obj, SEL sel, VALUE owner, VALUE group)
-{
-    rb_secure(2);
-
-    const int o = NIL_P(owner) ? -1 : NUM2INT(owner);
-    const int g = NIL_P(group) ? -1 : NUM2INT(group);
-    rb_io_t *io_struct = ExtractIOStruct(obj);
-
-    if (fchown(io_struct->fd, o, g) == -1) {
-	rb_sys_fail(RSTRING_PTR(io_struct->path));
-    }
-
-    return INT2FIX(0);
-}
-
-#if defined(HAVE_LCHOWN) && !defined(__CHECKER__)
-static void
-lchown_internal(const char *path, void *arg)
-{
-    struct chown_args *args = arg;
-    if (lchown(path, args->owner, args->group) < 0)
-	rb_sys_fail(path);
-}
-
-
-/*
- *  call-seq:
- *     file.lchown(owner_int, group_int, file_name,..) => integer
- *  
- *  Equivalent to <code>File::chown</code>, but does not follow symbolic
- *  links (so it will change the owner associated with the link, not the
- *  file referenced by the link). Often not available. Returns number
- *  of files in the argument list.
- *     
- */
-
-static VALUE
-rb_file_s_lchown(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(2);
-    if (argc < 2) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-    VALUE o = argv[0];
-    VALUE g = argv[1];
-    struct chown_args arg;
-    if (NIL_P(o)) {
-	arg.owner = -1;
-    }
-    else {
-	arg.owner = NUM2UIDT(o);
-    }
-    if (NIL_P(g)) {
-	arg.group = -1;
-    }
-    else {
-	arg.group = NUM2GIDT(g);
-    }
-
-    long n = apply2files(lchown_internal, argc - 2, &argv[2], &arg);
-    return LONG2FIX(n);
-}
-#else
-# define rb_file_s_lchown rb_f_notimplement
-#endif
-
-struct timespec rb_time_timespec(VALUE time);
-
-#if defined(HAVE_UTIMES)
-
-static void
-utime_internal(const char *path, void *arg)
-{
-    struct timespec *tsp = arg;
-    struct timeval tvbuf[2], *tvp = arg;
-
-#ifdef HAVE_UTIMENSAT
-    static int try_utimensat = 1;
-
-    if (try_utimensat) {
-        struct timespec *tsp = arg;
-        if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
-            if (errno == ENOSYS) {
-                try_utimensat = 0;
-                goto no_utimensat;
-            }
-            rb_sys_fail(path);
-        }
-        return;
-    }
-no_utimensat:
-#endif
-
-    if (tsp) {
-        tvbuf[0].tv_sec = tsp[0].tv_sec;
-        tvbuf[0].tv_usec = tsp[0].tv_nsec / 1000;
-        tvbuf[1].tv_sec = tsp[1].tv_sec;
-        tvbuf[1].tv_usec = tsp[1].tv_nsec / 1000;
-        tvp = tvbuf;
-    }
-    if (utimes(path, tvp) < 0)
-	rb_sys_fail(path);
-}
-
-#else
-
-#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
-struct utimbuf {
-    long actime;
-    long modtime;
-};
-#endif
-
-static void
-utime_internal(const char *path, void *arg)
-{
-    struct timespec *tsp = arg;
-    struct utimbuf utbuf, *utp = NULL;
-    if (tsp) {
-        utbuf.actime = tsp[0].tv_sec;
-        utbuf.modtime = tsp[1].tv_sec;
-        utp = &utbuf;
-    }
-    if (utime(path, utp) < 0)
-	rb_sys_fail(path);
-}
-
-#endif
-
-/*
- * call-seq:
- *  File.utime(atime, mtime, file_name,...)   =>  integer
- *
- * Sets the access and modification times of each
- * named file to the first two arguments. Returns
- * the number of file names in the argument list.
- */
-
-static VALUE
-rb_file_s_utime(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(2);
-    if (argc < 2) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-    VALUE atime = argv[0];
-    VALUE mtime = argv[1];
-
-    struct timespec tss[2], *tsp = NULL;
-    if (!NIL_P(atime) || !NIL_P(mtime)) {
-	tsp = tss;
-	tsp[0] = rb_time_timespec(atime);
-	tsp[1] = rb_time_timespec(mtime);
-    }
-
-    long n = apply2files(utime_internal, argc - 2, &argv[2], tsp);
-    return LONG2FIX(n);
-}
-
-
-NORETURN(static void sys_fail2(VALUE,VALUE));
-static void
-sys_fail2(VALUE s1, VALUE s2)
-{
-    char *buf;
-#ifdef MAX_PATH
-    const int max_pathlen = MAX_PATH;
-#else
-    const int max_pathlen = MAXPATHLEN;
-#endif
-    const char *e1, *e2;
-    int len = 5;
-    int l1 = RSTRING_LEN(s1), l2 = RSTRING_LEN(s2);
-
-    e1 = e2 = "";
-    if (l1 > max_pathlen) {
-	l1 = max_pathlen - 3;
-	e1 = "...";
-	len += 3;
-    }
-    if (l2 > max_pathlen) {
-	l2 = max_pathlen - 3;
-	e2 = "...";
-	len += 3;
-    }
-    len += l1 + l2;
-    buf = ALLOCA_N(char, len);
-    snprintf(buf, len, "(%.*s%s, %.*s%s)",
-	     l1, RSTRING_PTR(s1), e1,
-	     l2, RSTRING_PTR(s2), e2);
-    rb_sys_fail(buf);
-}
-
-/*
- *  call-seq:
- *     File.link(old_name, new_name)    => 0
- *  
- *  Creates a new name for an existing file using a hard link. Will not
- *  overwrite <i>new_name</i> if it already exists (raising a subclass
- *  of <code>SystemCallError</code>). Not available on all platforms.
- *     
- *     File.link("testfile", ".testfile")   #=> 0
- *     IO.readlines(".testfile")[0]         #=> "This is line one\n"
- */
-
-#ifdef HAVE_LINK
-static VALUE
-rb_file_s_link(VALUE klass, SEL sel, VALUE from, VALUE to)
-{
-    rb_secure(2);
-    FilePathValue(from);
-    FilePathValue(to);
-
-    if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
-	sys_fail2(from, to);
-    }
-    return INT2FIX(0);
-}
-#else
-# define rb_file_s_link rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     File.symlink(old_name, new_name)   => 0
- *  
- *  Creates a symbolic link called <i>new_name</i> for the existing file
- *  <i>old_name</i>. Raises a <code>NotImplemented</code> exception on
- *  platforms that do not support symbolic links.
- *     
- *     File.symlink("testfile", "link2test")   #=> 0
- *     
- */
-
-#ifdef HAVE_SYMLINK
-static VALUE
-rb_file_s_symlink(VALUE klass, SEL sel, VALUE from, VALUE to)
-{
-    rb_secure(2);
-    FilePathValue(from);
-    FilePathValue(to);
-
-    if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
-	sys_fail2(from, to);
-    }
-    return INT2FIX(0);
-}
-#else
-# define rb_file_s_symlink rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     File.readlink(link_name) -> file_name
- *  
- *  Returns the name of the file referenced by the given link.
- *  Not available on all platforms.
- *     
- *     File.symlink("testfile", "link2test")   #=> 0
- *     File.readlink("link2test")              #=> "testfile"
- */
-
-#ifdef HAVE_READLINK
-static VALUE
-rb_file_s_readlink(VALUE klass, SEL sel, VALUE path)
-{
-    char *buf;
-    int size = 100;
-    int rv;
-    VALUE v;
-
-    rb_secure(2);
-    FilePathValue(path);
-    buf = xmalloc(size);
-    while ((rv = readlink(RSTRING_PTR(path), buf, size)) == size
-#ifdef _AIX
-	    || (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
-#endif
-	) {
-	size *= 2;
-	buf = xrealloc(buf, size);
-    }
-    if (rv < 0) {
-	xfree(buf);
-	rb_sys_fail(RSTRING_PTR(path));
-    }
-    v = rb_tainted_str_new(buf, rv);
-    xfree(buf);
-
-    return v;
-}
-#else
-# define rb_file_s_readlink rb_f_notimplement 
-#endif
-
-static void
-unlink_internal(const char *path, void *arg)
-{
-    if (unlink(path) < 0)
-	rb_sys_fail(path);
-}
-
-/*
- *  call-seq:
- *     File.delete(file_name, ...)  => integer
- *     File.unlink(file_name, ...)  => integer
- *  
- *  Deletes the named files, returning the number of names
- *  passed as arguments. Raises an exception on any error.
- *  See also <code>Dir::rmdir</code>.
- */
-
-static VALUE
-rb_file_s_unlink(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    long n;
-
-    rb_secure(2);
-    n = apply2files(unlink_internal, argc, argv, 0);
-    return LONG2FIX(n);
-}
-
-/*
- *  call-seq:
- *     File.rename(old_name, new_name)   => 0
- *  
- *  Renames the given file to the new name. Raises a
- *  <code>SystemCallError</code> if the file cannot be renamed.
- *     
- *     File.rename("afile", "afile.bak")   #=> 0
- */
-
-static VALUE
-rb_file_s_rename(VALUE klass, SEL sel, VALUE from, VALUE to)
-{
-    const char *src, *dst;
-
-    rb_secure(2);
-    FilePathValue(from);
-    FilePathValue(to);
-    src = StringValueCStr(from);
-    dst = StringValueCStr(to);
-    if (rename(src, dst) < 0) {
-	sys_fail2(from, to);
-    }
-
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     File.umask()          => integer
- *     File.umask(integer)   => integer
- *  
- *  Returns the current umask value for this process. If the optional
- *  argument is given, set the umask to that value and return the
- *  previous value. Umask values are <em>subtracted</em> from the
- *  default permissions, so a umask of <code>0222</code> would make a
- *  file read-only for everyone.
- *     
- *     File.umask(0006)   #=> 18
- *     File.umask         #=> 6
- */
-
-static VALUE
-rb_file_s_umask(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    int omask = 0;
-
-    rb_secure(2);
-    if (argc == 0) {
-	omask = umask(0);
-	umask(omask);
-    }
-    else if (argc == 1) {
-	omask = umask(NUM2INT(argv[0]));
-    }
-    else {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-    return INT2FIX(omask);
-}
-
-#define isdirsep(x) ((x) == '/')
-
-#define istrailinggabage(x) 0
-
-#ifndef CharNext
-# define CharNext(p) ((p) + 1)
-#endif
-
-static inline char *
-skiproot(const char *path)
-{
-    while (isdirsep(*path)) path++;
-    return (char *)path;
-}
-
-#define nextdirsep rb_path_next
-char *
-rb_path_next(const char *s)
-{
-    while (*s && !isdirsep(*s)) {
-	s = CharNext(s);
-    }
-    return (char *)s;
-}
-
-#define skipprefix(path) (path)
-
-#define strrdirsep rb_path_last_separator
-static char *
-rb_path_last_separator(const char *path)
-{
-    char *last = NULL;
-    while (*path) {
-	if (isdirsep(*path)) {
-	    const char *tmp = path++;
-	    while (isdirsep(*path)) path++;
-	    if (!*path) break;
-	    last = (char *)tmp;
-	}
-	else {
-	    path = CharNext(path);
-	}
-    }
-    return last;
-}
-
-static char *
-chompdirsep(const char *path)
-{
-    while (*path) {
-	if (isdirsep(*path)) {
-	    const char *last = path++;
-	    while (isdirsep(*path)) path++;
-	    if (!*path) return (char *)last;
-	}
-	else {
-	    path = CharNext(path);
-	}
-    }
-    return (char *)path;
-}
-
-char *
-rb_path_end(const char *path)
-{
-    if (isdirsep(*path)) path++;
-    return chompdirsep(path);
-}
-
-static int is_absolute_path(const char*);
-
-/*
- *  call-seq:
- *     File.expand_path(file_name [, dir_string] ) -> abs_file_name
- *  
- *  Converts a pathname to an absolute pathname. Relative paths are
- *  referenced from the current working directory of the process unless
- *  <i>dir_string</i> is given, in which case it will be used as the
- *  starting point. The given pathname may start with a
- *  ``<code>~</code>'', which expands to the process owner's home
- *  directory (the environment variable <code>HOME</code> must be set
- *  correctly). ``<code>~</code><i>user</i>'' expands to the named
- *  user's home directory.
- *     
- *     File.expand_path("~oracle/bin")           #=> "/home/oracle/bin"
- *     File.expand_path("../../bin", "/tmp/x")   #=> "/bin"
- */
-
-static VALUE
-rb_file_s_expand_path(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE fname, dname;
-
-    if (argc == 1) {
-	return rb_file_expand_path(argv[0], Qnil);
-    }
-    rb_scan_args(argc, argv, "11", &fname, &dname);
-
-    return rb_file_expand_path(fname, dname);
-}
-
-/*
- *  call-seq:
- *     File.absolute_path(file_name [, dir_string] ) -> abs_file_name
- *  
- *  Converts a pathname to an absolute pathname. Relative paths are
- *  referenced from the current working directory of the process unless
- *  <i>dir_string</i> is given, in which case it will be used as the
- *  starting point. If the given pathname starts with a ``<code>~</code>''
- *  it is NOT expanded, it is treated as a normal directory name.
- *     
- *     File.absolute_path("~oracle/bin")       #=> "<relative_path>/~oracle/bin"
- */
-
-VALUE
-rb_file_s_absolute_path(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE fname, dname;
-
-    if (argc == 1) {
-	return rb_file_absolute_path(argv[0], Qnil);
-    }
-    rb_scan_args(argc, argv, "11", &fname, &dname);
-    return rb_file_absolute_path(fname, dname);
-}
-
-static void
-realpath_rec(long *prefixlenp, VALUE *resolvedp, char *unresolved, VALUE loopcheck, int strict, int last)
-{
-    ID resolving = rb_intern("resolving");
-    while (*unresolved) {
-        char *testname = unresolved;
-        char *unresolved_firstsep = rb_path_next(unresolved);
-        long testnamelen = unresolved_firstsep - unresolved;
-        char *unresolved_nextname = unresolved_firstsep;
-        while (isdirsep(*unresolved_nextname)) unresolved_nextname++;
-        unresolved = unresolved_nextname;
-        if (testnamelen == 1 && testname[0] == '.') {
-        }
-        else if (testnamelen == 2 && testname[0] == '.' && testname[1] == '.') {
-            if (*prefixlenp < RSTRING_LEN(*resolvedp)) {
-                char *resolved_names = (char *)RSTRING_PTR(*resolvedp) + *prefixlenp;
-                char *lastsep = rb_path_last_separator(resolved_names);
-                long len = lastsep ? lastsep - resolved_names : 0;
-                rb_str_set_len(*resolvedp, *prefixlenp + len);
-            }
-        }
-        else {
-            VALUE checkval;
-            VALUE testpath = rb_str_dup(*resolvedp);
-            if (*prefixlenp < RSTRING_LEN(testpath))
-                rb_str_cat2(testpath, "/");
-            rb_str_cat(testpath, testname, testnamelen);
-            checkval = rb_hash_aref(loopcheck, testpath);
-            if (!NIL_P(checkval)) {
-                if (checkval == ID2SYM(resolving)) {
-                    errno = ELOOP;
-                    rb_sys_fail((char *)RSTRING_PTR(testpath));
-                }
-                else {
-                    *resolvedp = rb_str_dup(checkval);
-                }
-            }
-            else {
-                struct stat sbuf;
-                int ret;
-                ret = lstat((char *)RSTRING_PTR(testpath), &sbuf);
-                if (ret == -1) {
-                    if (errno == ENOENT) {
-                        if (strict || !last || *unresolved_firstsep)
-                            rb_sys_fail(RSTRING_PTR(testpath));
-                        *resolvedp = testpath;
-                        break;
-                    }
-                    else {
-                        rb_sys_fail((char *)RSTRING_PTR(testpath));
-                    }
-                }
-#ifdef HAVE_READLINK
-                if (S_ISLNK(sbuf.st_mode)) {
-                    volatile VALUE link;
-                    char *link_prefix, *link_names;
-                    long link_prefixlen;
-                    rb_hash_aset(loopcheck, testpath, ID2SYM(resolving));
-                    link = rb_file_s_readlink(rb_cFile, 0, testpath);
-                    link_prefix = (char *)RSTRING_PTR(link);
-                    link_names = skiproot(link_prefix);
-                    link_prefixlen = link_names - link_prefix;
-                    if (link_prefixlen == 0) {
-                        realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep == '\0');
-                    }
-                    else {
-                        *resolvedp = rb_str_new(link_prefix, link_prefixlen);
-                        *prefixlenp = link_prefixlen;
-                        realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep == '\0');
-                    }
-                    rb_hash_aset(loopcheck, testpath, rb_str_dup(*resolvedp));
-                }
-                else
-#endif
-                {
-                    VALUE s = rb_str_dup(testpath);
-                    rb_hash_aset(loopcheck, s, s);
-                    *resolvedp = testpath;
-                }
-            }
-        }
-    }
-}
-
-VALUE
-rb_realpath_internal(VALUE basedir, VALUE path, int strict)
-{
-    long prefixlen;
-    VALUE resolved;
-    volatile VALUE unresolved_path;
-    VALUE loopcheck;
-    volatile VALUE curdir = Qnil;
-
-    char *path_names = NULL, *basedir_names = NULL, *curdir_names = NULL;
-    char *ptr, *prefixptr = NULL;
-
-    rb_secure(2);
-
-    FilePathValue(path);
-    unresolved_path = rb_str_dup(path);
-
-    if (!NIL_P(basedir)) {
-        FilePathValue(basedir);
-        basedir = rb_str_dup(basedir);
-    }
-
-    ptr = (char *)RSTRING_PTR(unresolved_path);
-    path_names = skiproot(ptr);
-    if (ptr != path_names) {
-        resolved = rb_str_new(ptr, path_names - ptr);
-        goto root_found;
-    }
-
-    if (!NIL_P(basedir)) {
-        ptr = (char *)RSTRING_PTR(basedir);
-        basedir_names = skiproot(ptr);
-        if (ptr != basedir_names) {
-            resolved = rb_str_new(ptr, basedir_names - ptr);
-            goto root_found;
-        }
-    }
-
-    curdir = ruby_getcwd();
-    ptr = (char *)RSTRING_PTR(curdir);
-    curdir_names = skiproot(ptr);
-    resolved = rb_str_new(ptr, curdir_names - ptr);
-
-  root_found:
-    prefixptr = (char *)RSTRING_PTR(resolved);
-    prefixlen = RSTRING_LEN(resolved);
-    ptr = chompdirsep(prefixptr);
-    if (*ptr) {
-        prefixlen = ++ptr - prefixptr;
-        rb_str_set_len(resolved, prefixlen);
-    }
-#ifdef FILE_ALT_SEPARATOR
-    while (prefixptr < ptr) {
-	if (*prefixptr == FILE_ALT_SEPARATOR) {
-	    *prefixptr = '/';
-	}
-	prefixptr = CharNext(prefixptr);
-    }
-#endif
-
-    loopcheck = rb_hash_new();
-    if (curdir_names)
-        realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, 1, 0);
-    if (basedir_names)
-        realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0);
-    realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1);
-
-    OBJ_TAINT(resolved);
-    return resolved;
-}
-
-/*
- * call-seq:
- *     File.realpath(pathname [, dir_string])  ->  real_pathname
- *
- *  Returns the real (absolute) pathname of _pathname_ in the actual
- *  filesystem not containing symlinks or useless dots.
- *
- *  If _dir_string_ is given, it is used as a base directory
- *  for interpreting relative pathname instead of the current directory.
- *
- *  All components of the pathname must exist when this method is
- *  called.
- */
-static VALUE
-rb_file_s_realpath(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE path, basedir;
-    rb_scan_args(argc, argv, "11", &path, &basedir);
-    return rb_realpath_internal(basedir, path, 1);
-}
-
-/*
- * call-seq:
- *     File.realdirpath(pathname [, dir_string])  ->  real_pathname
- *
- *  Returns the real (absolute) pathname of _pathname_ in the actual filesystem.
- *  The real pathname doesn't contain symlinks or useless dots.
- *
- *  If _dir_string_ is given, it is used as a base directory
- *  for interpreting relative pathname instead of the current directory.
- *
- *  The last component of the real pathname can be nonexistent.
- */
-static VALUE
-rb_file_s_realdirpath(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE path, basedir;
-    rb_scan_args(argc, argv, "11", &path, &basedir);
-    return rb_realpath_internal(basedir, path, 0);
-}
-
-static int
-rmext(const char *p, int l1, const char *e)
-{
-    int l0, l2;
-
-    if (!e) return 0;
-
-    for (l0 = 0; l0 < l1; ++l0) {
-	if (p[l0] != '.') break;
-    }
-
-    l2 = strlen(e);
-    if (l2 == 2 && e[1] == '*') {
-	unsigned char c = *e;
-	e = p + l1;
-	do {
-	    if (e <= p + l0) return 0;
-	} while (*--e != c);
-	return e - p;
-    }
-    if (l1 < l2) return l1;
-
-#if CASEFOLD_FILESYSTEM
-#define fncomp strncasecmp
-#else
-#define fncomp strncmp
-#endif
-    if (fncomp(p+l1-l2, e, l2) == 0) {
-	return l1-l2;
-    }
-    return 0;
-}
-
-/*
- *  call-seq:
- *     File.basename(file_name [, suffix] ) -> base_name
- *  
- *  Returns the last component of the filename given in <i>file_name</i>,
- *  which must be formed using forward slashes (``<code>/</code>'')
- *  regardless of the separator used on the local file system. If
- *  <i>suffix</i> is given and present at the end of <i>file_name</i>,
- *  it is removed.
- *     
- *     File.basename("/home/gumby/work/ruby.rb")          #=> "ruby.rb"
- *     File.basename("/home/gumby/work/ruby.rb", ".rb")   #=> "ruby"
- */
-
-static VALUE
-rb_file_s_basename(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE fname, fext, basename;
-    const char *name, *p;
-    int f, n;
-
-    if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
-	StringValue(fext);
-    }
-    FilePathStringValue(fname);
-    if (RSTRING_LEN(fname) == 0 || !*(name = RSTRING_PTR(fname))) {
-	return fname;
-    }
-    name = skipprefix(name);
-    while (isdirsep(*name))
-	name++;
-    if (!*name) {
-	p = name - 1;
-	f = 1;
-    }
-    else {
-	if (!(p = strrdirsep(name))) {
-	    p = name;
-	}
-	else {
-	    while (isdirsep(*p)) p++; /* skip last / */
-	}
-	n = chompdirsep(p) - p;
-	if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
-	    f = n;
-	}
-	if (f == RSTRING_LEN(fname)) return fname;
-    }
-    basename = rb_str_new(p, f);
-    OBJ_INFECT(basename, fname);
-    return basename;
-}
-
-/*
- *  call-seq:
- *     File.dirname(file_name ) -> dir_name
- *  
- *  Returns all components of the filename given in <i>file_name</i>
- *  except the last one. The filename must be formed using forward
- *  slashes (``<code>/</code>'') regardless of the separator used on the
- *  local file system.
- *     
- *     File.dirname("/home/gumby/work/ruby.rb")   #=> "/home/gumby/work"
- */
-
-static VALUE
-rb_file_s_dirname(VALUE klass, SEL sel, VALUE fname)
-{
-    const char *name, *root, *p;
-    VALUE dirname;
-
-    FilePathStringValue(fname);
-    name = StringValueCStr(fname);
-    root = skiproot(name);
-    if (root > name + 1) {
-	name = root - 1;
-    }
-    p = strrdirsep(root);
-    if (!p) {
-	p = root;
-    }
-    if (p == name)
-	return rb_usascii_str_new2(".");
-    dirname = rb_str_new(name, p - name);
-    OBJ_INFECT(dirname, fname);
-    return dirname;
-}
-
-/*
- * accept a String, and return the pointer of the extension.
- * if len is passed, set the length of extension to it.
- * returned pointer is in ``name'' or NULL.
- *                 returns   *len
- *   no dot        NULL      0
- *   dotfile       top       0
- *   end with dot  dot       1
- *   .ext          dot       len of .ext
- *   .ext:stream   dot       len of .ext without :stream (NT only)
- *
- */
-const char *
-ruby_find_extname(const char *name, long *len)
-{
-    const char *p, *e;
-
-    p = strrdirsep(name);	/* get the last path component */
-    if (!p) {
-	p = name;
-    }
-    else {
-	do {
-	    name = ++p;
-	} while (isdirsep(*p));
-    }
-
-    e = 0;
-    while (*p && *p == '.') { p++; }
-    while (*p) {
-	if (*p == '.') {
-	    e = p;	  /* get the last dot of the last component */
-	}
-	else if (isdirsep(*p)) {
-	    break;
-	}
-	p = CharNext(p);
-    }
-
-    if (len) {
-	/* no dot, or the only dot is first or end? */
-	if (!e || e == name) {
-	    *len = 0;
-	}
-	else if (e+1 == p) {
-	    *len = 1;
-	}
-	else {
-	    *len = p - e;
-	}
-    }
-    return e;
-}
-
-/*
- *  call-seq:
- *     File.extname(path) -> string
- *  
- *  Returns the extension (the portion of file name in <i>path</i>
- *  after the period).
- *     
- *     File.extname("test.rb")         #=> ".rb"
- *     File.extname("a/b/d/test.rb")   #=> ".rb"
- *     File.extname("test")            #=> ""
- *     File.extname(".profile")        #=> ""
- *     
- */
-
-static VALUE
-rb_file_s_extname(VALUE klass, SEL sel, VALUE fname)
-{
-    const char *name, *e;
-    long len;
-    VALUE extname;
-
-    FilePathStringValue(fname);
-    name = StringValueCStr(fname);
-    e = ruby_find_extname(name, &len);
-    if (len <= 1) {
-	return rb_str_new(0, 0);
-    }
-    extname = rb_str_new(e, len);	/* keep the dot, too! */
-    OBJ_INFECT(extname, fname);
-    return extname;
-}
-
-/*
- *  call-seq:
- *     File.path(path) -> string
- *  
- *  Returns the string representation of the path
- * 
- *     File.path("/dev/null")          #=> "/dev/null"
- *     File.path(Pathname.new("/tmp")) #=> "/tmp"
- *     
- */
-
-static VALUE
-rb_file_s_path(VALUE klass, SEL sel, VALUE fname)
-{
-    return rb_get_path(fname);
-}
-
-/*
- *  call-seq:
- *     File.split(file_name)   => array
- *  
- *  Splits the given string into a directory and a file component and
- *  returns them in a two-element array. See also
- *  <code>File::dirname</code> and <code>File::basename</code>.
- *     
- *     File.split("/home/gumby/.profile")   #=> ["/home/gumby", ".profile"]
- */
-
-static VALUE
-rb_file_s_split(VALUE klass, SEL sel, VALUE path)
-{
-    FilePathStringValue(path);		/* get rid of converting twice */
-    return rb_assoc_new(rb_file_s_dirname(Qnil, 0, path),
-	    rb_file_s_basename(0,0,1,&path));
-}
-
-static VALUE separator;
-
-static VALUE
-rb_file_join(VALUE ary, VALUE sep)
-{
-    assert(rb_str_chars_len(sep) == 1);
-    UChar sep_char = rb_str_get_uchar(sep, 0);
-    VALUE res = rb_str_new(NULL, 0);
-
-    for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	VALUE tmp = RARRAY_AT(ary, i);
-	switch (TYPE(tmp)) {
-	    case T_STRING:
-		break;
-
-	    case T_ARRAY:
-		if (ary == tmp) {
-		    rb_raise(rb_eArgError, "recursive array");
-		}
-		tmp = rb_file_join(tmp, sep);
-		break;
-
-	    default:
-		FilePathStringValue(tmp);
-	}
-
-#define uchar_at_is_sep(str, pos) (rb_str_get_uchar(str, pos) == sep_char)
-	if (i > 0 && !NIL_P(sep)) {
-	    const long res_len = rb_str_chars_len(res);
-	    const long tmp_len = rb_str_chars_len(tmp);
-
-	    if (res_len > 0 && uchar_at_is_sep(res, res_len - 1)) {
-		if (tmp_len > 0 && uchar_at_is_sep(tmp, 0)) {
-		    long nb_sep_char = 1;
-		    while (nb_sep_char < res_len
-			&& uchar_at_is_sep(res, res_len - nb_sep_char - 1)) {
-			nb_sep_char++;
-		    }
-		    rb_str_delete(res, res_len - nb_sep_char, nb_sep_char);
-		}
-	    }
-	    else if (tmp_len == 0
-		    || rb_str_get_uchar(tmp, 0) != sep_char) {
-		rb_str_concat(res, sep);
-	    } 
-	}
-	rb_str_concat(res, tmp);
-#undef uchar_at_is_sep
-    }
-    return res;
-}
-
-/*
- *  call-seq:
- *     File.join(string, ...) -> path
- *  
- *  Returns a new string formed by joining the strings using
- *  <code>File::SEPARATOR</code>.
- *     
- *     File.join("usr", "mail", "gumby")   #=> "usr/mail/gumby"
- *     
- */
-
-static VALUE
-rb_file_s_join(VALUE klass, SEL sel, VALUE args)
-{
-    return rb_file_join(args, separator);
-}
-
-/*
- *  call-seq:
- *     File.truncate(file_name, integer)  => 0
- *  
- *  Truncates the file <i>file_name</i> to be at most <i>integer</i>
- *  bytes long. Not available on all platforms.
- *     
- *     f = File.new("out", "w")
- *     f.write("1234567890")     #=> 10
- *     f.close                   #=> nil
- *     File.truncate("out", 5)   #=> 0
- *     File.size("out")          #=> 5
- *     
- */
-
-static VALUE
-rb_file_s_truncate(VALUE klass, SEL sel, VALUE path, VALUE len)
-{
-    rb_secure(2);
-    const off_t pos = NUM2OFFT(len);
-    FilePathValue(path);
-    if (truncate(StringValueCStr(path), pos) < 0) {
-	rb_sys_fail(RSTRING_PTR(path));
-    }
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     file.truncate(integer)    => 0
- *  
- *  Truncates <i>file</i> to at most <i>integer</i> bytes. The file
- *  must be opened for writing. Not available on all platforms.
- *     
- *     f = File.new("out", "w")
- *     f.syswrite("1234567890")   #=> 10
- *     f.truncate(5)              #=> 0
- *     f.close()                  #=> nil
- *     File.size("out")           #=> 5
- */
-
-static VALUE
-rb_file_truncate(VALUE obj, SEL sel, VALUE len)
-{
-    rb_secure(2);
-    rb_io_t *io = ExtractIOStruct(obj);
-    const off_t pos = NUM2OFFT(len);
-    rb_io_assert_writable(io);
-    if (ftruncate(io->fd, pos) < 0) {
-	rb_sys_fail(RSTRING_PTR(io->path));
-    }
-    return INT2FIX(0);
-}
-
-# ifndef LOCK_SH
-#  define LOCK_SH 1
-# endif
-# ifndef LOCK_EX
-#  define LOCK_EX 2
-# endif
-# ifndef LOCK_NB
-#  define LOCK_NB 4
-# endif
-# ifndef LOCK_UN
-#  define LOCK_UN 8
-# endif
-
-#ifdef __CYGWIN__
-#include <winerror.h>
-extern unsigned long __attribute__((stdcall)) GetLastError(void);
-#endif
-
-/*
- *  call-seq:
- *     file.flock (locking_constant ) =>  0 or false
- *  
- *  Locks or unlocks a file according to <i>locking_constant</i> (a
- *  logical <em>or</em> of the values in the table below).
- *  Returns <code>false</code> if <code>File::LOCK_NB</code> is
- *  specified and the operation would otherwise have blocked. Not
- *  available on all platforms.
- *     
- *  Locking constants (in class File):
- *
- *     LOCK_EX   | Exclusive lock. Only one process may hold an
- *               | exclusive lock for a given file at a time.
- *     ----------+------------------------------------------------
- *     LOCK_NB   | Don't block when locking. May be combined
- *               | with other lock options using logical or.
- *     ----------+------------------------------------------------
- *     LOCK_SH   | Shared lock. Multiple processes may each hold a
- *               | shared lock for a given file at the same time.
- *     ----------+------------------------------------------------
- *     LOCK_UN   | Unlock.
- *
- *  Example:
- *
- *     File.new("testfile").flock(File::LOCK_UN)   #=> 0
- *     
- */
-static VALUE
-rb_file_flock(VALUE obj, SEL sel, VALUE operation)
-{
-#ifndef __CHECKER__
-    int op[2], op1;
-
-    rb_secure(2);
-    op[1] = op1 = NUM2INT(operation);
-    rb_io_t *io = ExtractIOStruct(obj);
-    op[0] = io->fd;
-
-//    if (io->mode & FMODE_WRITABLE) {
-//	rb_io_flush(obj);
-//    }
-
-    while (flock(op[0], op[1]) < 0) {
-	switch (errno) {
-	    case EAGAIN:
-	    case EACCES:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
-	    case EWOULDBLOCK:
-#endif
-		if (op1 & LOCK_NB) return Qfalse;
-		rb_thread_polling();
-		rb_io_check_closed(io);
-		continue;
-
-	    case EINTR:
-#if defined(ERESTART)
-	    case ERESTART:
-#endif
-		break;
-
-	    default:
-		rb_sys_fail(RSTRING_PTR(io->path));
-	}
-    }
-#endif
-    return INT2FIX(0);
-}
-#undef flock
-
-static void
-test_check(int n, int argc, VALUE *argv)
-{
-    int i;
-
-    rb_secure(2);
-    n+=1;
-    if (n != argc) rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
-    for (i=1; i<n; i++) {
-	switch (TYPE(argv[i])) {
-	  case T_STRING:
-	  default:
-	    FilePathValue(argv[i]);
-	    break;
-	  case T_FILE:
-	    break;
-	}
-    }
-}
-
-#define CHECK(n) test_check((n), argc, argv)
-
-/*
- *  call-seq:
- *     test(int_cmd, file1 [, file2] ) => obj
- *  
- *  Uses the integer <i>aCmd</i> to perform various tests on
- *  <i>file1</i> (first table below) or on <i>file1</i> and
- *  <i>file2</i> (second table).
- *     
- *  File tests on a single file:
- *
- *    Test   Returns   Meaning
- *     ?A  | Time    | Last access time for file1
- *     ?b  | boolean | True if file1 is a block device
- *     ?c  | boolean | True if file1 is a character device
- *     ?C  | Time    | Last change time for file1
- *     ?d  | boolean | True if file1 exists and is a directory
- *     ?e  | boolean | True if file1 exists
- *     ?f  | boolean | True if file1 exists and is a regular file
- *     ?g  | boolean | True if file1 has the \CF{setgid} bit
- *         |         | set (false under NT)
- *     ?G  | boolean | True if file1 exists and has a group
- *         |         | ownership equal to the caller's group
- *     ?k  | boolean | True if file1 exists and has the sticky bit set
- *     ?l  | boolean | True if file1 exists and is a symbolic link
- *     ?M  | Time    | Last modification time for file1
- *     ?o  | boolean | True if file1 exists and is owned by 
- *         |         | the caller's effective uid
- *     ?O  | boolean | True if file1 exists and is owned by
- *         |         | the caller's real uid
- *     ?p  | boolean | True if file1 exists and is a fifo
- *     ?r  | boolean | True if file1 is readable by the effective
- *         |         | uid/gid of the caller
- *     ?R  | boolean | True if file is readable by the real
- *         |         | uid/gid of the caller
- *     ?s  | int/nil | If file1 has nonzero size, return the size,
- *         |         | otherwise return nil
- *     ?S  | boolean | True if file1 exists and is a socket
- *     ?u  | boolean | True if file1 has the setuid bit set
- *     ?w  | boolean | True if file1 exists and is writable by
- *         |         | the effective uid/gid
- *     ?W  | boolean | True if file1 exists and is writable by
- *         |         | the real uid/gid
- *     ?x  | boolean | True if file1 exists and is executable by
- *         |         | the effective uid/gid
- *     ?X  | boolean | True if file1 exists and is executable by
- *         |         | the real uid/gid
- *     ?z  | boolean | True if file1 exists and has a zero length
- *
- * Tests that take two files:
- *
- *     ?-  | boolean | True if file1 and file2 are identical
- *     ?=  | boolean | True if the modification times of file1
- *         |         | and file2 are equal
- *     ?<  | boolean | True if the modification time of file1
- *         |         | is prior to that of file2
- *     ?>  | boolean | True if the modification time of file1
- *         |         | is after that of file2
- */
-
-static VALUE
-rb_f_test(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    int cmd;
-
-    if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments");
-    cmd = NUM2CHR(argv[0]);
-    if (cmd == 0) goto unknown;
-    if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
-	CHECK(1);
-	switch (cmd) {
-	  case 'b':
-	    return rb_file_blockdev_p(0, 0, argv[1]);
-
-	  case 'c':
-	    return rb_file_chardev_p(0, 0, argv[1]);
-
-	  case 'd':
-	    return rb_file_directory_p(0, 0, argv[1]);
-
-	  case 'a':
-	  case 'e':
-	    return rb_file_exist_p(0, 0, argv[1]);
-
-	  case 'f':
-	    return rb_file_file_p(0, 0, argv[1]);
-
-	  case 'g':
-	    return rb_file_sgid_p(0, 0, argv[1]);
-
-	  case 'G':
-	    return rb_file_grpowned_p(0, 0, argv[1]);
-
-	  case 'k':
-	    return rb_file_sticky_p(0, 0, argv[1]);
-
-	  case 'l':
-	    return rb_file_symlink_p(0, 0, argv[1]);
-
-	  case 'o':
-	    return rb_file_owned_p(0, 0, argv[1]);
-
-	  case 'O':
-	    return rb_file_rowned_p(0, argv[1]);
-
-	  case 'p':
-	    return rb_file_pipe_p(0, 0, argv[1]);
-
-	  case 'r':
-	    return rb_file_readable_p(0, 0, argv[1]);
-
-	  case 'R':
-	    return rb_file_readable_real_p(0, 0, argv[1]);
-
-	  case 's':
-	    return rb_file_size_p(0, 0, argv[1]);
-
-	  case 'S':
-	    return rb_file_socket_p(0, 0, argv[1]);
-
-	  case 'u':
-	    return rb_file_suid_p(0, 0, argv[1]);
-
-	  case 'w':
-	    return rb_file_writable_p(0, 0, argv[1]);
-
-	  case 'W':
-	    return rb_file_world_writable_p(0, 0, argv[1]);
-
-	  case 'x':
-	    return rb_file_executable_p(0, 0, argv[1]);
-
-	  case 'X':
-	    return rb_file_executable_real_p(0, 0, argv[1]);
-
-	  case 'z':
-	    return rb_file_zero_p(0, 0, argv[1]);
-	}
-    }
-
-    if (strchr("MAC", cmd)) {
-	struct stat st;
-
-	CHECK(1);
-	if (rb_stat(argv[1], &st) == -1) {
-	    rb_sys_fail(RSTRING_PTR(argv[1]));
-	}
-
-	switch (cmd) {
-	  case 'A':
-	    return stat_atime(&st);
-	  case 'M':
-	    return stat_mtime(&st);
-	  case 'C':
-	    return stat_ctime(&st);
-	}
-    }
-
-    if (cmd == '-') {
-	CHECK(2);
-	return rb_file_identical_p(0, 0, argv[1], argv[2]);
-    }
-
-    if (strchr("=<>", cmd)) {
-	struct stat st1, st2;
-
-	CHECK(2);
-	if (rb_stat(argv[1], &st1) < 0) return Qfalse;
-	if (rb_stat(argv[2], &st2) < 0) return Qfalse;
-
-	switch (cmd) {
-	  case '=':
-	    if (st1.st_mtime == st2.st_mtime) return Qtrue;
-	    return Qfalse;
-
-	  case '>':
-	    if (st1.st_mtime > st2.st_mtime) return Qtrue;
-	    return Qfalse;
-
-	  case '<':
-	    if (st1.st_mtime < st2.st_mtime) return Qtrue;
-	    return Qfalse;
-	}
-    }
-  unknown:
-    /* unknown command */
-    if (ISPRINT(cmd)) {
-	rb_raise(rb_eArgError, "unknown command ?%c", cmd);
-    }
-    else {
-	rb_raise(rb_eArgError, "unknown command ?\\x%02X", cmd);
-    }
-    return Qnil;		/* not reached */
-}
-
-
-
-/*
- *  Document-class: File::Stat
- *
- *  Objects of class <code>File::Stat</code> encapsulate common status
- *  information for <code>File</code> objects. The information is
- *  recorded at the moment the <code>File::Stat</code> object is
- *  created; changes made to the file after that point will not be
- *  reflected. <code>File::Stat</code> objects are returned by
- *  <code>IO#stat</code>, <code>File::stat</code>,
- *  <code>File#lstat</code>, and <code>File::lstat</code>. Many of these
- *  methods return platform-specific values, and not all values are
- *  meaningful on all systems. See also <code>Kernel#test</code>.
- */
-
-static VALUE
-rb_stat_s_alloc(VALUE klass)
-{
-    return stat_new_0(klass, 0);
-}
-
-/*
- * call-seq:
- *
- *   File::Stat.new(file_name)  => stat
- *
- * Create a File::Stat object for the given file name (raising an
- * exception if the file doesn't exist).
- */
-
-static VALUE
-rb_stat_init(VALUE obj, SEL sel, VALUE fname)
-{
-    struct stat st, *nst;
-
-    rb_secure(2);
-    FilePathValue(fname);
-    if (stat(StringValueCStr(fname), &st) == -1) {
-	rb_sys_fail(RSTRING_PTR(fname));
-    }
-    if (DATA_PTR(obj)) {
-	free(DATA_PTR(obj));
-	DATA_PTR(obj) = NULL;
-    }
-    nst = ALLOC(struct stat);
-    *nst = st;
-    GC_WB(&DATA_PTR(obj), nst);
-
-    return Qnil;
-}
-
-/* :nodoc: */
-static VALUE
-rb_stat_init_copy(VALUE copy, SEL sel, VALUE orig)
-{
-    struct stat *nst;
-
-    if (copy == orig) return orig;
-    rb_check_frozen(copy);
-    /* need better argument type check */
-    if (!rb_obj_is_instance_of(orig, rb_obj_class(copy))) {
-	rb_raise(rb_eTypeError, "wrong argument class");
-    }
-    if (DATA_PTR(copy)) {
-	free(DATA_PTR(copy));
-	DATA_PTR(copy) = 0;
-    }
-    if (DATA_PTR(orig)) {
-	nst = ALLOC(struct stat);
-	*nst = *(struct stat*)DATA_PTR(orig);
-	GC_WB(&DATA_PTR(copy), nst);
-    }
-
-    return copy;
-}
-
-/*
- *  call-seq:
- *     stat.ftype   => string
- *  
- *  Identifies the type of <i>stat</i>. The return string is one of:
- *  ``<code>file</code>'', ``<code>directory</code>'',
- *  ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
- *  ``<code>fifo</code>'', ``<code>link</code>'',
- *  ``<code>socket</code>'', or ``<code>unknown</code>''.
- *     
- *     File.stat("/dev/tty").ftype   #=> "characterSpecial"
- *     
- */
-
-static VALUE
-rb_stat_ftype(VALUE obj, SEL sel)
-{
-    return rb_file_ftype(get_stat(obj));
-}
-
-/*
- *  call-seq:
- *     stat.directory?   => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is a directory,
- *  <code>false</code> otherwise.
- *     
- *     File.stat("testfile").directory?   #=> false
- *     File.stat(".").directory?          #=> true
- */
-
-static VALUE
-rb_stat_d(VALUE obj, SEL sel)
-{
-    if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.pipe?    => true or false
- *  
- *  Returns <code>true</code> if the operating system supports pipes and
- *  <i>stat</i> is a pipe; <code>false</code> otherwise.
- */
-
-static VALUE
-rb_stat_p(VALUE obj, SEL sel)
-{
-#ifdef S_IFIFO
-    if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.symlink?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is a symbolic link,
- *  <code>false</code> if it isn't or if the operating system doesn't
- *  support this feature. As <code>File::stat</code> automatically
- *  follows symbolic links, <code>symlink?</code> will always be
- *  <code>false</code> for an object returned by
- *  <code>File::stat</code>.
- *     
- *     File.symlink("testfile", "alink")   #=> 0
- *     File.stat("alink").symlink?         #=> false
- *     File.lstat("alink").symlink?        #=> true
- *     
- */
-
-static VALUE
-rb_stat_l(VALUE obj, SEL sel)
-{
-#ifdef S_ISLNK
-    if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.socket?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is a socket,
- *  <code>false</code> if it isn't or if the operating system doesn't
- *  support this feature.
- *     
- *     File.stat("testfile").socket?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_S(VALUE obj, SEL sel)
-{
-#ifdef S_ISSOCK
-    if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.blockdev?   => true or false
- *  
- *  Returns <code>true</code> if the file is a block device,
- *  <code>false</code> if it isn't or if the operating system doesn't
- *  support this feature.
- *     
- *     File.stat("testfile").blockdev?    #=> false
- *     File.stat("/dev/hda1").blockdev?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_b(VALUE obj, SEL sel)
-{
-#ifdef S_ISBLK
-    if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.chardev?    => true or false
- *  
- *  Returns <code>true</code> if the file is a character device,
- *  <code>false</code> if it isn't or if the operating system doesn't
- *  support this feature.
- *     
- *     File.stat("/dev/tty").chardev?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_c(VALUE obj, SEL sel)
-{
-    if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
-
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.owned?    => true or false
- *  
- *  Returns <code>true</code> if the effective user id of the process is
- *  the same as the owner of <i>stat</i>.
- *     
- *     File.stat("testfile").owned?      #=> true
- *     File.stat("/etc/passwd").owned?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_owned(VALUE obj, SEL sel)
-{
-    if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
-    return Qfalse;
-}
-
-static VALUE
-rb_stat_rowned(VALUE obj)
-{
-    if (get_stat(obj)->st_uid == getuid()) return Qtrue;
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.grpowned?   => true or false
- *  
- *  Returns true if the effective group id of the process is the same as
- *  the group id of <i>stat</i>. On Windows NT, returns <code>false</code>.
- *     
- *     File.stat("testfile").grpowned?      #=> true
- *     File.stat("/etc/passwd").grpowned?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_grpowned(VALUE obj, SEL sel)
-{
-#ifndef _WIN32
-    if (group_member(get_stat(obj)->st_gid)) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.readable?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is readable by the
- *  effective user id of this process.
- *     
- *     File.stat("testfile").readable?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_r(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (geteuid() == 0) return Qtrue;
-#endif
-#ifdef S_IRUSR
-    if (rb_stat_owned(obj, 0))
-	return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IRGRP
-    if (rb_stat_grpowned(obj, 0))
-	return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IROTH
-    if (!(st->st_mode & S_IROTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-
-
-/*
- *  call-seq:
- *     stat.readable_real? -> true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is readable by the real
- *  user id of this process.
- *     
- *     File.stat("testfile").readable_real?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_R(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (getuid() == 0) return Qtrue;
-#endif
-#ifdef S_IRUSR
-    if (rb_stat_rowned(obj))
-	return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IRGRP
-    if (group_member(get_stat(obj)->st_gid))
-	return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IROTH
-    if (!(st->st_mode & S_IROTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    stat.world_readable? => fixnum or nil
- *
- * If <i>stat</i> is readable by others, returns an integer
- * representing the file permission bits of <i>stat</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *     
- *    m = File.stat("/etc/passwd").world_readable?  # => 420
- *    sprintf("%o", m)				    # => "644"
- */
-
-static VALUE
-rb_stat_wr(VALUE obj, SEL sel)
-{
-#ifdef S_IROTH
-    if ((get_stat(obj)->st_mode & (S_IROTH)) == S_IROTH) {
-      return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
-    }
-    else {
-      return Qnil;
-    }
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.writable? -> true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is writable by the
- *  effective user id of this process.
- *     
- *     File.stat("testfile").writable?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_w(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (geteuid() == 0) return Qtrue;
-#endif
-#ifdef S_IWUSR
-    if (rb_stat_owned(obj, 0))
-	return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWGRP
-    if (rb_stat_grpowned(obj, 0))
-	return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWOTH
-    if (!(st->st_mode & S_IWOTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     stat.writable_real? -> true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is writable by the real
- *  user id of this process.
- *     
- *     File.stat("testfile").writable_real?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_W(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (getuid() == 0) return Qtrue;
-#endif
-#ifdef S_IWUSR
-    if (rb_stat_rowned(obj))
-	return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWGRP
-    if (group_member(get_stat(obj)->st_gid))
-	return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWOTH
-    if (!(st->st_mode & S_IWOTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    stat.world_writable? => fixnum or nil
- *
- * If <i>stat</i> is writable by others, returns an integer
- * representing the file permission bits of <i>stat</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *     
- *    m = File.stat("/tmp").world_writable?	    # => 511
- *    sprintf("%o", m)				    # => "777"
- */
-
-static VALUE
-rb_stat_ww(VALUE obj, SEL sel)
-{
-#ifdef S_IROTH
-    if ((get_stat(obj)->st_mode & (S_IWOTH)) == S_IWOTH) {
-      return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
-    }
-    else {
-      return Qnil;
-    }
-#endif
-}
-
-/*
- *  call-seq:
- *     stat.executable?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is executable or if the
- *  operating system doesn't distinguish executable files from
- *  nonexecutable files. The tests are made using the effective owner of
- *  the process.
- *     
- *     File.stat("testfile").executable?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_x(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (geteuid() == 0) {
-	return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
-    }
-#endif
-#ifdef S_IXUSR
-    if (rb_stat_owned(obj, 0))
-	return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXGRP
-    if (rb_stat_grpowned(obj, 0))
-	return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXOTH
-    if (!(st->st_mode & S_IXOTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     stat.executable_real?    => true or false
- *  
- *  Same as <code>executable?</code>, but tests using the real owner of
- *  the process.
- */
-
-
-static VALUE
-rb_stat_X(VALUE obj, SEL sel)
-{
-    struct stat *st = get_stat(obj);
-
-#ifdef USE_GETEUID
-    if (getuid() == 0) {
-	return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
-    }
-#endif
-#ifdef S_IXUSR
-    if (rb_stat_rowned(obj))
-	return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXGRP
-    if (group_member(get_stat(obj)->st_gid))
-	return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXOTH
-    if (!(st->st_mode & S_IXOTH)) return Qfalse;
-#endif
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     stat.file?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is a regular file (not
- *  a device file, pipe, socket, etc.).
- *     
- *     File.stat("testfile").file?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_f(VALUE obj, SEL sel)
-{
-    if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.zero?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> is a zero-length file;
- *  <code>false</code> otherwise.
- *     
- *     File.stat("testfile").zero?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_z(VALUE obj, SEL sel)
-{
-    if (get_stat(obj)->st_size == 0) return Qtrue;
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     state.size    => integer
- *  
- *  Returns the size of <i>stat</i> in bytes.
- *     
- *     File.stat("testfile").size   #=> 66
- *     
- */
-
-static VALUE
-rb_stat_s(VALUE obj, SEL sel)
-{
-    off_t size = get_stat(obj)->st_size;
-
-    if (size == 0) return Qnil;
-    return OFFT2NUM(size);
-}
-
-/*
- *  call-seq:
- *     stat.setuid?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> has the set-user-id
- *  permission bit set, <code>false</code> if it doesn't or if the
- *  operating system doesn't support this feature.
- *     
- *     File.stat("/bin/su").setuid?   #=> true
- */
-
-static VALUE
-rb_stat_suid(VALUE obj, SEL sel)
-{
-#ifdef S_ISUID
-    if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.setgid?   => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> has the set-group-id
- *  permission bit set, <code>false</code> if it doesn't or if the
- *  operating system doesn't support this feature.
- *     
- *     File.stat("/usr/sbin/lpc").setgid?   #=> true
- *     
- */
-
-static VALUE
-rb_stat_sgid(VALUE obj, SEL sel)
-{
-#ifdef S_ISGID
-    if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     stat.sticky?    => true or false
- *  
- *  Returns <code>true</code> if <i>stat</i> has its sticky bit set,
- *  <code>false</code> if it doesn't or if the operating system doesn't
- *  support this feature.
- *     
- *     File.stat("testfile").sticky?   #=> false
- *     
- */
-
-static VALUE
-rb_stat_sticky(VALUE obj, SEL sel)
-{
-#ifdef S_ISVTX
-    if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
-#endif
-    return Qfalse;
-}
-
-VALUE rb_mFConst;
-
-void
-rb_file_const(const char *name, VALUE value)
-{
-    rb_define_const(rb_mFConst, name, value);
-}
-
-static int
-is_absolute_path(const char *path)
-{
-    return path[0] == '/';
-}
-
-#ifndef ENABLE_PATH_CHECK
-#  define ENABLE_PATH_CHECK 1
-#endif
-
-#if ENABLE_PATH_CHECK
-static int
-path_check_0(VALUE path, int execpath)
-{
-    struct stat st;
-    const char *p0 = StringValueCStr(path);
-    char *p = 0, *s;
-
-    if (!is_absolute_path(p0)) {
-	VALUE newpath = ruby_getcwd();
-	rb_str_cat2(newpath, "/");
-	rb_str_cat2(newpath, p0);
-	path = newpath;
-	p0 = RSTRING_PTR(path);
-    }
-    for (;;) {
-#ifndef S_IWOTH
-# define S_IWOTH 002
-#endif
-	if (stat(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
-#ifdef S_ISVTX
-	    && !(p && execpath && (st.st_mode & S_ISVTX))
-#endif
-	    && !access(p0, W_OK)) {
-	    rb_warn("Insecure world writable dir %s in %sPATH, mode 0%o",
-		    p0, (execpath ? "" : "LOAD_"), st.st_mode);
-	    if (p) *p = '/';
-	    return 0;
-	}
-	s = strrdirsep(p0);
-	if (p) *p = '/';
-	if (!s || s == p0) return 1;
-	p = s;
-	*p = '\0';
-    }
-}
-#endif
-
-static int
-fpath_check(const char *path)
-{
-#if ENABLE_PATH_CHECK
-    return path_check_0(rb_str_new2(path), Qfalse);
-#else
-    return 1;
-#endif
-}
-
-int
-rb_path_check(const char *path)
-{
-#if ENABLE_PATH_CHECK
-    const char *p0, *p, *pend;
-    const char sep = PATH_SEP_CHAR;
-
-    if (!path) return 1;
-
-    pend = path + strlen(path);
-    p0 = path;
-    p = strchr(path, sep);
-    if (!p) p = pend;
-
-    for (;;) {
-	if (!path_check_0(rb_str_new(p0, p - p0), Qtrue)) {
-	    return 0;		/* not safe */
-	}
-	p0 = p + 1;
-	if (p0 > pend) break;
-	p = strchr(p0, sep);
-	if (!p) p = pend;
-    }
-#endif
-    return 1;
-}
-
-static int
-file_load_ok(const char *path)
-{
-    return eaccess(path, R_OK) == 0;
-}
-
-VALUE rb_get_load_path(void);
-
-int
-rb_find_file_ext(VALUE *filep, const char *const *ext)
-{
-    const char *path, *found;
-    const char *f = RSTRING_PTR(*filep);
-    VALUE fname, load_path;
-    long i, j;
-
-    if (f[0] == '~') {
-	fname = rb_file_expand_path(*filep, Qnil);
-	if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
-	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
-	}
-	OBJ_FREEZE(fname);
-	f = StringValueCStr(fname);
-	*filep = fname;
-    }
-
-    if (is_absolute_path(f)) {
-	for (i=0; ext[i]; i++) {
-	    fname = rb_str_dup(*filep);
-	    rb_str_cat2(fname, ext[i]);
-	    OBJ_FREEZE(fname);
-	    if (file_load_ok(StringValueCStr(fname))) {
-		*filep = fname;
-		return i+1;
-	    }
-	}
-	return 0;
-    }
-
-    load_path = rb_get_load_path();
-    if (!load_path) return 0;
-
-    for (j=0; ext[j]; j++) {
-	fname = rb_str_dup(*filep);
-	rb_str_cat2(fname, ext[j]);
-	OBJ_FREEZE(fname);
-	for (i = 0; i < RARRAY_LEN(load_path); i++) {
-	    VALUE str = RARRAY_AT(load_path, i);
-	    char fbuf[MAXPATHLEN];
-
-	    FilePathValue(str);
-	    if (RSTRING_LEN(str) == 0) continue;
-	    path = RSTRING_PTR(str);
-	    found = dln_find_file_r(StringValueCStr(fname), path, fbuf, sizeof(fbuf));
-	    if (found && file_load_ok(found)) {
-		*filep = rb_str_new2(found);
-		return j+1;
-	    }
-	}
-    }
-    RB_GC_GUARD(load_path);
-    return 0;
-}
-
-VALUE
-rb_find_file(VALUE path)
-{
-    VALUE tmp, load_path;
-    char *f = StringValueCStr(path);
-    const char *lpath;
-    char fbuf[MAXPATHLEN];
-
-    if (f[0] == '~') {
-	path = rb_file_expand_path(path, Qnil);
-	if (rb_safe_level() >= 1 && OBJ_TAINTED(path)) {
-	    rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
-	}
-	OBJ_FREEZE(path);
-	f = StringValueCStr(path);
-    }
-
-    if (is_absolute_path(f)) {
-	if (rb_safe_level() >= 1 && !fpath_check(f)) {
-	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
-	}
-	if (file_load_ok(f)) {
-	    return path;
-	}
-    }
-
-    if (rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f);
-    }
-
-    load_path = rb_get_load_path();
-    if (load_path) {
-	long i, count;
-
-	tmp = rb_ary_new();
-	for (i=0, count=RARRAY_LEN(load_path);i < count;i++) {
-	    VALUE str = RARRAY_AT(load_path, i);
-	    FilePathValue(str);
-	    if (RSTRING_LEN(str) > 0) {
-		rb_ary_push(tmp, str);
-	    }
-	}
-	tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP));
-	if (RSTRING_LEN(tmp) == 0) {
-	    lpath = 0;
-	}
-	else {
-	    lpath = RSTRING_PTR(tmp);
-	}
-    }
-    else {
-	lpath = 0;
-    }
-
-    if (!lpath) {
-	return 0;		/* no path, no load */
-    }
-    if (!(f = dln_find_file_r(f, lpath, fbuf, sizeof(fbuf)))) {
-	return 0;
-    }
-    if (rb_safe_level() >= 1 && !fpath_check(f)) {
-	rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
-    }
-    if (file_load_ok(f)) {
-	tmp = rb_str_new2(f);
-	OBJ_FREEZE(tmp);
-	return tmp;
-    }
-    return 0;
-}
-
-static void
-define_filetest_function(const char *name, VALUE (*func)(ANYARGS), int argc)
-{
-    rb_objc_define_method(*(VALUE *)rb_mFileTest, name, func, argc);
-    rb_objc_define_method(*(VALUE *)rb_cFile, name, func, argc);
-}
-
-
-/*
- *  A <code>File</code> is an abstraction of any file object accessible
- *  by the program and is closely associated with class <code>IO</code>
- *  <code>File</code> includes the methods of module
- *  <code>FileTest</code> as class methods, allowing you to write (for
- *  example) <code>File.exist?("foo")</code>.
- *     
- *  In the description of File methods,
- *  <em>permission bits</em> are a platform-specific
- *  set of bits that indicate permissions of a file. On Unix-based
- *  systems, permissions are viewed as a set of three octets, for the
- *  owner, the group, and the rest of the world. For each of these
- *  entities, permissions may be set to read, write, or execute the
- *  file:
- *     
- *  The permission bits <code>0644</code> (in octal) would thus be
- *  interpreted as read/write for owner, and read-only for group and
- *  other. Higher-order bits may also be used to indicate the type of
- *  file (plain, directory, pipe, socket, and so on) and various other
- *  special features. If the permissions are for a directory, the
- *  meaning of the execute bit changes; when set the directory can be
- *  searched.
- *     
- *  On non-Posix operating systems, there may be only the ability to
- *  make a file read-only or read-write. In this case, the remaining
- *  permission bits will be synthesized to resemble typical values. For
- *  instance, on Windows NT the default permission bits are
- *  <code>0644</code>, which means read/write for owner, read-only for
- *  all others. The only change that can be made is to make the file
- *  read-only, which is reported as <code>0444</code>.
- */
-
-void
-Init_File(void)
-{
-    rb_mFileTest = rb_define_module("FileTest");
-    rb_cFile = rb_define_class("File", rb_cIO);
-
-    selToPath = sel_registerName("to_path");
-
-    define_filetest_function("directory?", rb_file_directory_p, 1);
-    define_filetest_function("exist?", rb_file_exist_p, 1);
-    define_filetest_function("exists?", rb_file_exist_p, 1);
-    define_filetest_function("readable?", rb_file_readable_p, 1);
-    define_filetest_function("readable_real?", rb_file_readable_real_p, 1);
-    define_filetest_function("world_readable?", rb_file_world_readable_p, 1);
-    define_filetest_function("writable?", rb_file_writable_p, 1);
-    define_filetest_function("writable_real?", rb_file_writable_real_p, 1);
-    define_filetest_function("world_writable?", rb_file_world_writable_p, 1);
-    define_filetest_function("executable?", rb_file_executable_p, 1);
-    define_filetest_function("executable_real?", rb_file_executable_real_p, 1);
-    define_filetest_function("file?", rb_file_file_p, 1);
-    define_filetest_function("zero?", rb_file_zero_p, 1);
-    define_filetest_function("size?", rb_file_size_p, 1);
-    define_filetest_function("size", rb_file_s_size, 1);
-    define_filetest_function("owned?", rb_file_owned_p, 1);
-    define_filetest_function("grpowned?", rb_file_grpowned_p, 1);
-
-    define_filetest_function("pipe?", rb_file_pipe_p, 1);
-    define_filetest_function("symlink?", rb_file_symlink_p, 1);
-    define_filetest_function("socket?", rb_file_socket_p, 1);
-
-    define_filetest_function("blockdev?", rb_file_blockdev_p, 1);
-    define_filetest_function("chardev?", rb_file_chardev_p, 1);
-
-    define_filetest_function("setuid?", rb_file_suid_p, 1);
-    define_filetest_function("setgid?", rb_file_sgid_p, 1);
-    define_filetest_function("sticky?", rb_file_sticky_p, 1);
-
-    define_filetest_function("identical?", rb_file_identical_p, 2);
-
-    VALUE rb_ccFile = *(VALUE *)rb_cFile;
-    rb_objc_define_method(rb_ccFile, "stat",  rb_file_s_stat, 1);
-    rb_objc_define_method(rb_ccFile, "lstat", rb_file_s_lstat, 1);
-    rb_objc_define_method(rb_ccFile, "ftype", rb_file_s_ftype, 1);
-
-    rb_objc_define_method(rb_ccFile, "atime", rb_file_s_atime, 1);
-    rb_objc_define_method(rb_ccFile, "mtime", rb_file_s_mtime, 1);
-    rb_objc_define_method(rb_ccFile, "ctime", rb_file_s_ctime, 1);
-
-    rb_objc_define_method(rb_ccFile, "utime", rb_file_s_utime, -1);
-    rb_objc_define_method(rb_ccFile, "chmod", rb_file_s_chmod, -1);
-    rb_objc_define_method(rb_ccFile, "chown", rb_file_s_chown, -1);
-    rb_objc_define_method(rb_ccFile, "lchmod", rb_file_s_lchmod, -1);
-    rb_objc_define_method(rb_ccFile, "lchown", rb_file_s_lchown, -1);
-
-    rb_objc_define_method(rb_ccFile, "link", rb_file_s_link, 2);
-    rb_objc_define_method(rb_ccFile, "symlink", rb_file_s_symlink, 2);
-    rb_objc_define_method(rb_ccFile, "readlink", rb_file_s_readlink, 1);
-
-    rb_objc_define_method(rb_ccFile, "unlink", rb_file_s_unlink, -1);
-    rb_objc_define_method(rb_ccFile, "delete", rb_file_s_unlink, -1);
-    rb_objc_define_method(rb_ccFile, "rename", rb_file_s_rename, 2);
-    rb_objc_define_method(rb_ccFile, "umask", rb_file_s_umask, -1);
-    rb_objc_define_method(rb_ccFile, "truncate", rb_file_s_truncate, 2);
-    rb_objc_define_method(rb_ccFile, "expand_path", rb_file_s_expand_path, -1);
-    rb_objc_define_method(rb_ccFile, "absolute_path", rb_file_s_absolute_path, -1);
-    rb_objc_define_method(rb_ccFile, "realpath", rb_file_s_realpath, -1);
-    rb_objc_define_method(rb_ccFile, "realdirpath", rb_file_s_realdirpath, -1);
-    rb_objc_define_method(rb_ccFile, "basename", rb_file_s_basename, -1);
-    rb_objc_define_method(rb_ccFile, "dirname", rb_file_s_dirname, 1);
-    rb_objc_define_method(rb_ccFile, "extname", rb_file_s_extname, 1);
-    rb_objc_define_method(rb_ccFile, "path", rb_file_s_path, 1);
-
-    separator = rb_obj_freeze(rb_usascii_str_new2("/"));
-    rb_define_const(rb_cFile, "Separator", separator);
-    rb_define_const(rb_cFile, "SEPARATOR", separator);
-    rb_objc_define_method(rb_ccFile, "split",  rb_file_s_split, 1);
-    rb_objc_define_method(rb_ccFile, "join",   rb_file_s_join, -2);
-
-    rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
-    rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_obj_freeze(rb_str_new2(PATH_SEP)));
-
-    rb_objc_define_method(rb_cIO, "stat",  rb_io_stat, 0); /* this is IO's method */
-    rb_objc_define_method(rb_cFile, "lstat",  rb_file_lstat, 0);
-
-    rb_objc_define_method(rb_cFile, "atime", rb_file_atime, 0);
-    rb_objc_define_method(rb_cFile, "mtime", rb_file_mtime, 0);
-    rb_objc_define_method(rb_cFile, "ctime", rb_file_ctime, 0);
-    rb_objc_define_method(rb_cFile, "size", rb_file_size, 0);
-
-    rb_objc_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
-    rb_objc_define_method(rb_cFile, "chown", rb_file_chown, 2);
-    rb_objc_define_method(rb_cFile, "truncate", rb_file_truncate, 1);
-
-    rb_objc_define_method(rb_cFile, "flock", rb_file_flock, 1);
-
-    rb_mFConst = rb_define_module_under(rb_cFile, "Constants");
-    rb_include_module(rb_cIO, rb_mFConst);
-    rb_file_const("LOCK_SH", INT2FIX(LOCK_SH));
-    rb_file_const("LOCK_EX", INT2FIX(LOCK_EX));
-    rb_file_const("LOCK_UN", INT2FIX(LOCK_UN));
-    rb_file_const("LOCK_NB", INT2FIX(LOCK_NB));
-
-    rb_objc_define_method(rb_cFile, "path",  rb_file_path, 0);
-    rb_objc_define_method(rb_cFile, "to_path",  rb_file_path, 0);
-    rb_objc_define_module_function(rb_mKernel, "test", rb_f_test, -1);
-
-    rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cStat, "alloc", rb_stat_s_alloc, 0);
-    rb_objc_define_method(rb_cStat, "initialize", rb_stat_init, 1);
-    rb_objc_define_method(rb_cStat, "initialize_copy", rb_stat_init_copy, 1);
-
-    rb_include_module(rb_cStat, rb_mComparable);
-
-    rb_objc_define_method(rb_cStat, "<=>", rb_stat_cmp, 1);
-
-    rb_objc_define_method(rb_cStat, "dev", rb_stat_dev, 0);
-    rb_objc_define_method(rb_cStat, "dev_major", rb_stat_dev_major, 0);
-    rb_objc_define_method(rb_cStat, "dev_minor", rb_stat_dev_minor, 0);
-    rb_objc_define_method(rb_cStat, "ino", rb_stat_ino, 0);
-    rb_objc_define_method(rb_cStat, "mode", rb_stat_mode, 0);
-    rb_objc_define_method(rb_cStat, "nlink", rb_stat_nlink, 0);
-    rb_objc_define_method(rb_cStat, "uid", rb_stat_uid, 0);
-    rb_objc_define_method(rb_cStat, "gid", rb_stat_gid, 0);
-    rb_objc_define_method(rb_cStat, "rdev", rb_stat_rdev, 0);
-    rb_objc_define_method(rb_cStat, "rdev_major", rb_stat_rdev_major, 0);
-    rb_objc_define_method(rb_cStat, "rdev_minor", rb_stat_rdev_minor, 0);
-    rb_objc_define_method(rb_cStat, "size", rb_stat_size, 0);
-    rb_objc_define_method(rb_cStat, "blksize", rb_stat_blksize, 0);
-    rb_objc_define_method(rb_cStat, "blocks", rb_stat_blocks, 0);
-    rb_objc_define_method(rb_cStat, "atime", rb_stat_atime, 0);
-    rb_objc_define_method(rb_cStat, "mtime", rb_stat_mtime, 0);
-    rb_objc_define_method(rb_cStat, "ctime", rb_stat_ctime, 0);
-
-    rb_objc_define_method(rb_cStat, "inspect", rb_stat_inspect, 0);
-
-    rb_objc_define_method(rb_cStat, "ftype", rb_stat_ftype, 0);
-
-    rb_objc_define_method(rb_cStat, "directory?",  rb_stat_d, 0);
-    rb_objc_define_method(rb_cStat, "readable?",  rb_stat_r, 0);
-    rb_objc_define_method(rb_cStat, "readable_real?",  rb_stat_R, 0);
-    rb_objc_define_method(rb_cStat, "world_readable?", rb_stat_wr, 0);
-    rb_objc_define_method(rb_cStat, "writable?",  rb_stat_w, 0);
-    rb_objc_define_method(rb_cStat, "writable_real?",  rb_stat_W, 0);
-    rb_objc_define_method(rb_cStat, "world_writable?", rb_stat_ww, 0);
-    rb_objc_define_method(rb_cStat, "executable?",  rb_stat_x, 0);
-    rb_objc_define_method(rb_cStat, "executable_real?",  rb_stat_X, 0);
-    rb_objc_define_method(rb_cStat, "file?",  rb_stat_f, 0);
-    rb_objc_define_method(rb_cStat, "zero?",  rb_stat_z, 0);
-    rb_objc_define_method(rb_cStat, "size?",  rb_stat_s, 0);
-    rb_objc_define_method(rb_cStat, "owned?",  rb_stat_owned, 0);
-    rb_objc_define_method(rb_cStat, "grpowned?",  rb_stat_grpowned, 0);
-
-    rb_objc_define_method(rb_cStat, "pipe?",  rb_stat_p, 0);
-    rb_objc_define_method(rb_cStat, "symlink?",  rb_stat_l, 0);
-    rb_objc_define_method(rb_cStat, "socket?",  rb_stat_S, 0);
-
-    rb_objc_define_method(rb_cStat, "blockdev?",  rb_stat_b, 0);
-    rb_objc_define_method(rb_cStat, "chardev?",  rb_stat_c, 0);
-
-    rb_objc_define_method(rb_cStat, "setuid?",  rb_stat_suid, 0);
-    rb_objc_define_method(rb_cStat, "setgid?",  rb_stat_sgid, 0);
-    rb_objc_define_method(rb_cStat, "sticky?",  rb_stat_sticky, 0);
-}

Deleted: MacRuby/trunk/gc-stub.m
===================================================================
--- MacRuby/trunk/gc-stub.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gc-stub.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,36 +0,0 @@
-/*  
- *  Copyright (c) 2008-2011, Apple Inc. All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *  1.  Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *  2.  Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *  3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *      its contributors may be used to endorse or promote products derived
- *      from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
- *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- *  ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
- *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- *  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This file is needed to enable GC in miniruby and ruby executables.
- * The __RBDummy__ class is only to have something Objective-C in the 
- * executable bits, for the compiler.
- */
- at interface __RBDummy__
- at end
- at implementation __RBDummy__
- at end

Deleted: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gc.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1058 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's gc.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "ruby/config.h"
-
-#if HAVE_AUTO_ZONE_H
-# include <auto_zone.h>
-#else
-# include "auto_zone_1060.h"
-#endif
-
-#include "macruby_internal.h"
-#include "ruby/signal.h"
-#include "ruby/st.h"
-#include "ruby/node.h"
-#include "ruby/io.h"
-#include "ruby/util.h"
-#include "objc.h"
-#include "vm.h"
-#include "id.h"
-#include "class.h"
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#include <mach/mach.h>
-
-auto_zone_t *__auto_zone = NULL;
-
-static VALUE nomem_error;
-
-static bool dont_gc = false;
-
-void
-rb_memerror(void)
-{
-    rb_exc_raise(nomem_error);
-}
-
-/*
- *  call-seq:
- *    GC.stress                 => true or false
- *
- *  returns current status of GC stress mode.
- */
-
-#if 0
-static VALUE
-gc_stress_get(VALUE self, SEL sel)
-{
-    return Qnil;
-}
-#else
-# define gc_stress_get rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *    GC.stress = bool          => bool
- *
- *  updates GC stress mode.
- *
- *  When GC.stress = true, GC is invoked for all GC opportunity:
- *  all memory and object allocation.
- *
- *  Since it makes Ruby very slow, it is only for debugging.
- */
-
-#if 0
-static VALUE
-gc_stress_set(VALUE self, SEL sel, VALUE flag)
-{
-    return Qnil;
-}
-#else
-# define gc_stress_set rb_f_notimplement
-#endif
-
-static int garbage_collect(void);
-
-static void
-rb_objc_no_gc_error(void)
-{ 
-    fprintf(stderr,
-	    "The client that links against MacRuby was not built for "\
-	    "GC. Please turn on garbage collection (-fobjc-gc) and "\
-	    "try again.\n");
-    exit(1);
-}
-
-static inline void *
-ruby_xmalloc_memory(size_t size, int type)
-{
-    assert(size > 0);
-    if (__auto_zone == NULL) {
-	rb_objc_no_gc_error();
-    }
-
-    void *mem = auto_zone_allocate_object(__auto_zone, size, type, 0, 0);
-    if (mem == NULL) {
-	rb_memerror();
-    }
-    return mem;
-}
-
-void *
-ruby_xmalloc(size_t size)
-{
-    return ruby_xmalloc_memory(size, AUTO_MEMORY_SCANNED);
-}
-
-void *
-ruby_xmalloc_ptrs(size_t size)
-{
-    int type;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-    type = AUTO_MEMORY_ALL_POINTERS;
-#else
-    type = AUTO_MEMORY_SCANNED;
-#endif
-    return ruby_xmalloc_memory(size, type);
-}
-
-void *
-ruby_xmalloc2(size_t n, size_t size)
-{
-    size_t len = size * n;
-    if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "malloc: possible integer overflow");
-    }
-    return ruby_xmalloc(len);
-}
-
-void *
-ruby_xcalloc(size_t n, size_t size)
-{
-    void *mem = ruby_xmalloc2(n, size);
-    memset(mem, 0, n * size);
-    return mem;
-}
-
-void *
-ruby_xrealloc(void *ptr, size_t size)
-{
-    if (ptr == NULL) {
-	return ruby_xmalloc(size);
-    }
-    if (size == 0) {
-	size = 1;
-    }
-    void *mem = malloc_zone_realloc(__auto_zone, ptr, size);
-    if (mem == NULL) {
-	rb_memerror();
-    }
-    return mem;
-}
-
-void *
-ruby_xrealloc2(void *ptr, size_t n, size_t size)
-{
-    size_t len = size * n;
-    if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "realloc: possible integer overflow");
-    }
-    return ruby_xrealloc(ptr, len);
-}
-
-void
-ruby_xfree(void *ptr)
-{
-    if (ptr != NULL) {
-	auto_zone_retain(__auto_zone, ptr);
-	malloc_zone_free(__auto_zone, ptr);
-    }
-}
-
-/*
- *  call-seq:
- *     GC.enable    => true or false
- *
- *  Enables garbage collection, returning <code>true</code> if garbage
- *  collection was previously disabled.
- *
- *     GC.disable   #=> false
- *     GC.enable    #=> true
- *     GC.enable    #=> false
- *
- */
-
-VALUE
-rb_gc_enable(VALUE self, SEL sel)
-{
-    int old = dont_gc;
-
-    auto_collector_reenable(__auto_zone);
-    dont_gc = Qfalse;
-    return old ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     GC.disable    => true or false
- *
- *  Disables garbage collection, returning <code>true</code> if garbage
- *  collection was already disabled.
- *
- *     GC.disable   #=> false
- *     GC.disable   #=> true
- *
- */
-
-VALUE
-rb_gc_disable(VALUE self, SEL sel)
-{
-    int old = dont_gc;
-
-    auto_collector_disable(__auto_zone);
-    dont_gc = Qtrue;
-    return old ? Qtrue : Qfalse;
-}
-
-VALUE rb_mGC;
-
-void *
-rb_gc_memmove(void *dst, const void *src, size_t len)
-{
-    return auto_zone_write_barrier_memmove(__auto_zone, dst, src, len);
-}
-
-void
-rb_objc_set_associative_ref(void *obj, void *key, void *val)
-{
-    auto_zone_set_associative_ref(__auto_zone, obj, key, val);
-}
-
-void *
-rb_objc_get_associative_ref(void *obj, void *key)
-{
-    return auto_zone_get_associative_ref(__auto_zone, obj, key);
-}
-
-const void *
-rb_objc_retain_ni(const void *addr)
-{
-    return rb_objc_retain((void *)addr);
-}
-
-const void *
-rb_objc_release_ni(const void *addr)
-{
-    return rb_objc_release((void *)addr);
-}
-
-void
-rb_register_mark_object(VALUE obj)
-{
-    GC_RETAIN(obj);
-}
-
-void
-rb_gc_unregister_address(VALUE *addr)
-{
-    /* TODO: implement me */
-}
-
-static void *__nsobject = NULL;
-
-void *
-rb_objc_newobj(size_t size)
-{
-    void *obj;
-
-    obj = auto_zone_allocate_object(__auto_zone, size, AUTO_OBJECT_SCANNED,
-	    0, 0);
-    assert(obj != NULL);
-    RBASIC(obj)->klass = (VALUE)__nsobject;
-    return obj;
-}
-
-void
-rb_objc_gc_register_thread(void)
-{
-    auto_zone_register_thread(__auto_zone);
-}
-
-void
-rb_objc_gc_unregister_thread(void)
-{
-    auto_zone_unregister_thread(__auto_zone);
-}
-
-NODE*
-rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
-{
-    NODE *n = xmalloc(sizeof(struct RNode));
-
-    n->flags |= T_NODE;
-    nd_set_type(n, type);
-
-    GC_WB(&n->u1.value, a0);
-    GC_WB(&n->u2.value, a1);
-    GC_WB(&n->u3.value, a2);
-
-    // FIXME this retain is added because the parser is NOT GC-safe at this point
-    GC_RETAIN(n);
-
-    return n;
-}
-
-const char *ruby_node_name(int node);
-
-void
-rb_node_release(NODE *node)
-{
-    if (node == NULL || node == (NODE *)-1) {
-	return;
-    }
-
-//    static int c = 0;
-//    printf("%d RELEASE %s %p\n", ++c, ruby_node_name(nd_type(node)), node);
-
-    switch (nd_type(node)) {
-	case NODE_IF:		/* 1,2,3 */
-	case NODE_FOR:
-	case NODE_ITER:
-	case NODE_WHEN:
-	case NODE_MASGN:
-	case NODE_RESCUE:
-	case NODE_RESBODY:
-	case NODE_CLASS:
-	case NODE_BLOCK_PASS:
-	    rb_node_release(node->u2.node);
-	    /* fall through */
-	case NODE_BLOCK:	/* 1,3 */
-	case NODE_OPTBLOCK:
-	case NODE_ARRAY:
-	case NODE_ENSURE:
-	case NODE_CALL:
-	case NODE_DEFS:
-	case NODE_OP_ASGN1:
-	case NODE_ARGS:
-	    rb_node_release(node->u1.node);
-	    /* fall through */
-	case NODE_SUPER:	/* 3 */
-	case NODE_FCALL:
-	case NODE_DEFN:
-	case NODE_ARGS_AUX:
-	    rb_node_release(node->u3.node);
-	    break;
-
-	case NODE_WHILE:	/* 1,2 */
-	case NODE_UNTIL:
-	case NODE_AND:
-	case NODE_OR:
-	case NODE_CASE:
-	case NODE_SCLASS:
-	case NODE_DOT2:
-	case NODE_DOT3:
-	case NODE_FLIP2:
-	case NODE_FLIP3:
-	case NODE_MATCH2:
-	case NODE_MATCH3:
-	case NODE_OP_ASGN_OR:
-	case NODE_OP_ASGN_AND:
-	case NODE_MODULE:
-	case NODE_ARGSCAT:
-	    rb_node_release(node->u1.node);
-	    /* fall through */
-	case NODE_FBODY:	/* 2 */
-	case NODE_GASGN:
-	case NODE_LASGN:
-	case NODE_DASGN:
-	case NODE_DASGN_CURR:
-	case NODE_IASGN:
-	case NODE_IASGN2:
-	case NODE_CVASGN:
-	case NODE_OPT_N:
-	case NODE_EVSTR:
-	case NODE_UNDEF:
-	case NODE_POSTEXE:
-	    rb_node_release(node->u2.node);
-	    break;
-
-	case NODE_HASH:	/* 1 */
-	case NODE_DEFINED:
-	case NODE_RETURN:
-	case NODE_BREAK:
-	case NODE_NEXT:
-	case NODE_YIELD:
-	case NODE_COLON2:
-	case NODE_SPLAT:
-	case NODE_TO_ARY:
-	    rb_node_release(node->u1.node);
-	    break;
-
-	case NODE_SCOPE:	/* 2,3 */
-	case NODE_CDECL:
-	case NODE_OPT_ARG:
-	    rb_node_release(node->u3.node);
-	    rb_node_release(node->u2.node);
-	    break;
-    }
-
-//    c--;
-
-    // Some NODE structures are apparently reused somewhere in parserland.
-    const int count = auto_zone_retain_count(__auto_zone, node);
-    if (count > 0) {
-	node->u1.node = node->u2.node = node->u3.node = NULL;
-	GC_RELEASE(node);
-    }
-}
-
-VALUE
-rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
-{
-    NEWOBJ(data, struct RData);
-    if (klass) Check_Type(klass, T_CLASS);
-    OBJSETUP(data, klass, T_DATA);
-    GC_WB(&data->data, datap);
-    data->dfree = dfree;
-    data->dmark = dmark;
-
-    return (VALUE)data;
-}
-
-void
-rb_gc_force_recycle(VALUE p)
-{
-    // FIXME this xfree call is commented because it's used by the parser which is NOT GC-safe at this point
-//    xfree((void *)p);
-}
-
-static int
-garbage_collect(void)
-{
-    if (!dont_gc) {
-	auto_collect(__auto_zone,
-		AUTO_COLLECT_EXHAUSTIVE_COLLECTION|AUTO_COLLECT_SYNCHRONOUS,
-		NULL);
-    }
-    return Qtrue;
-}
-
-void
-rb_gc(void)
-{
-    garbage_collect();
-}
-
-/*
- *  call-seq:
- *     GC.start                     => nil
- *     gc.garbage_collect           => nil
- *     ObjectSpace.garbage_collect  => nil
- *
- *  Initiates garbage collection, unless manually disabled.
- *
- */
-
-VALUE
-rb_gc_start(VALUE self, SEL sel)
-{
-    rb_gc();
-    return Qnil;
-}
-
-/*
- * Document-class: ObjectSpace
- *
- *  The <code>ObjectSpace</code> module contains a number of routines
- *  that interact with the garbage collection facility and allow you to
- *  traverse all living objects with an iterator.
- *
- *  <code>ObjectSpace</code> also provides support for object
- *  finalizers, procs that will be called when a specific object is
- *  about to be destroyed by garbage collection.
- *
- *     include ObjectSpace
- *
- *
- *     a = "A"
- *     b = "B"
- *     c = "C"
- *
- *
- *     define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
- *     define_finalizer(a, proc {|id| puts "Finalizer two on #{id}" })
- *     define_finalizer(b, proc {|id| puts "Finalizer three on #{id}" })
- *
- *  <em>produces:</em>
- *
- *     Finalizer three on 537763470
- *     Finalizer one on 537763480
- *     Finalizer two on 537763480
- *
- */
-
-struct rb_objc_recorder_context {
-    VALUE class_of;
-    int count;
-    VALUE break_value;
-};
-
-static int
-rb_objc_yield_classes(VALUE of)
-{
-    int i, count, rcount;
-    Class *buf;
-
-    count = objc_getClassList(NULL, 0);
-    assert(count > 0);
-
-    buf = (Class *)alloca(sizeof(Class) * count);
-    objc_getClassList(buf, count);
-
-    for (i = rcount = 0; i < count; i++) {
-	Class sk, k = buf[i];
-	bool nsobject_based;
-
-	if (class_getName(k)[0] == '_')
-	    continue;
-
-	if (of == rb_cModule && !RCLASS_MODULE(k))
-	    continue;
-
-	nsobject_based = false;
-	sk = k;
-	do {
-	    sk = (Class)RCLASS_SUPER(sk);
-	    if (sk == (Class)rb_cNSObject) {
-		nsobject_based = true;
-		break;
-	    }
-	}
-	while (sk != NULL);	
-
-	if (nsobject_based) {
-	    rb_yield((VALUE)k);
-	    RETURN_IF_BROKEN();
-	    rcount++;
-	}
-    }
-
-    return rcount;
-}
-
-static void 
-rb_objc_recorder(task_t task, void *context, unsigned type_mask,
-		 vm_range_t *ranges, unsigned range_count)
-{
-    struct rb_objc_recorder_context *ctx;
-    vm_range_t *r, *end;
-
-    ctx = (struct rb_objc_recorder_context *)context;
-
-    for (r = ranges, end = ranges + range_count; r < end; r++) {
-	auto_memory_type_t type = auto_zone_get_layout_type(__auto_zone,
-		(void *)r->address);
-	if (type != AUTO_OBJECT_SCANNED && type != AUTO_OBJECT_UNSCANNED) {
-	    continue;
-	}
-	if (*(Class *)r->address == NULL) {
-	    continue;
-	}
-	if (ctx->class_of != 0) {
-	    Class c;
-	    bool ok = false;
-	    for (c = *(Class *)r->address; c != NULL;
-		 c = class_getSuperclass(c)) {
-		if (c == (Class)ctx->class_of) {
-		    ok = true;
-		    break;
-		}
-	    }
-	    if (!ok) {
-		continue;
-	    }
-	}
-	switch (TYPE(r->address)) {
-	    case T_NONE: 
-	    case T_NODE:
-		continue;
-
-	    case T_ICLASS: 
-	    case T_CLASS:
-	    case T_MODULE:
-		rb_bug("object %p of type %d should not be recorded", 
-		       (void *)r->address, TYPE(r->address));
-	}
-	rb_yield((VALUE)r->address);
-	ctx->break_value = rb_vm_pop_broken_value();
-	ctx->count++;
-    }
-}
-
-/*
- *  call-seq:
- *     ObjectSpace.each_object([module]) {|obj| ... } => fixnum
- *
- *  Calls the block once for each living, nonimmediate object in this
- *  Ruby process. If <i>module</i> is specified, calls the block
- *  for only those classes or modules that match (or are a subclass of)
- *  <i>module</i>. Returns the number of objects found. Immediate
- *  objects (<code>Fixnum</code>s, <code>Symbol</code>s
- *  <code>true</code>, <code>false</code>, and <code>nil</code>) are
- *  never returned. In the example below, <code>each_object</code>
- *  returns both the numbers we defined and several constants defined in
- *  the <code>Math</code> module.
- *
- *     a = 102.7
- *     b = 95       # Won't be returned
- *     c = 12345678987654321
- *     count = ObjectSpace.each_object(Numeric) {|x| p x }
- *     puts "Total count: #{count}"
- *
- *  <em>produces:</em>
- *
- *     12345678987654321
- *     102.7
- *     2.71828182845905
- *     3.14159265358979
- *     2.22044604925031e-16
- *     1.7976931348623157e+308
- *     2.2250738585072e-308
- *     Total count: 7
- *
- */
-
-static VALUE
-os_each_obj(VALUE os, SEL sel, int argc, VALUE *argv)
-{
-    VALUE of;
-    int count;
-
-    rb_secure(4);
-    if (argc == 0) {
-	of = 0;
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &of);
-    }
-    RETURN_ENUMERATOR(os, 1, &of);
-
-    /* Class/Module are a special case, because they are not auto objects */
-    if (of == rb_cClass || of == rb_cModule) {
-	count = rb_objc_yield_classes(of);
-    }
-    else {
-	struct rb_objc_recorder_context ctx = {of, 0, Qundef};
-
-	auto_collector_disable(__auto_zone);
-
-	(((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
-	    mach_task_self(), (void *)&ctx, MALLOC_PTR_IN_USE_RANGE_TYPE,
-	    (vm_address_t)__auto_zone, NULL, rb_objc_recorder);
-
-	auto_collector_reenable(__auto_zone);
-
-	if (ctx.break_value != Qundef) {
-	    return ctx.break_value;
-	}
-
-	count = ctx.count;
-    }
-
-    return INT2FIX(count);
-}
-
-/*
- *  call-seq:
- *     ObjectSpace.undefine_finalizer(obj)
- *
- *  Removes all finalizers for <i>obj</i>.
- *
- */
-
-static VALUE rb_cFinalizer;
-
-static void *finalizer_key = NULL; // only used for its address
-
-static IMP rb_objc_finalizer_finalize_super = NULL;
-
-static void
-rb_objc_finalizer_finalize(void *rcv, SEL sel)
-{
-    rb_vm_finalizer_t *f = (rb_vm_finalizer_t *)rcv;
-    rb_vm_call_finalizer(f);
-    rb_vm_unregister_finalizer(f); 
-    if (rb_objc_finalizer_finalize_super != NULL) {
-	((void(*)(void *, SEL))rb_objc_finalizer_finalize_super)(rcv, sel);
-    }
-}
-
-static VALUE
-undefine_final(VALUE os, SEL sel, VALUE obj)
-{
-    if (SPECIAL_CONST_P(obj)) {
-	rb_raise(rb_eArgError, "immediate types are not finalizable");
-    }
-    rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
-	    &finalizer_key);
-    if (finalizer != NULL) {
-	rb_ary_clear(finalizer->finalizers);
-	rb_vm_unregister_finalizer(finalizer); 
-	rb_objc_set_associative_ref((void *)obj, &finalizer_key, NULL);
-    }
-    return obj;
-}
-
-/*
- *  call-seq:
- *     ObjectSpace.define_finalizer(obj, aProc=proc())
- *
- *  Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
- *  was destroyed.
- *
- */
-
-static VALUE
-define_final(VALUE os, SEL sel, int argc, VALUE *argv)
-{
-    VALUE obj, block;
-
-    rb_scan_args(argc, argv, "11", &obj, &block);
-    if (argc == 1) {
-	block = rb_block_proc();
-    }
-    else if (!rb_respond_to(block, rb_intern("call"))) {
-	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
-		rb_obj_classname(block));
-    }
-
-    if (SPECIAL_CONST_P(obj)) {
-	rb_raise(rb_eArgError, "immediate types are not finalizable");
-    }
-
-    rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
-	    &finalizer_key);
-    if (finalizer == NULL) {
-	finalizer = (rb_vm_finalizer_t *)
-	    rb_objc_newobj(sizeof(rb_vm_finalizer_t *));
-	finalizer->klass = rb_cFinalizer;
-	finalizer->objid = rb_obj_id(obj, 0);
-	GC_WB(&finalizer->finalizers, rb_ary_new());
-	rb_objc_set_associative_ref((void *)obj, &finalizer_key, finalizer);
-	rb_vm_register_finalizer(finalizer); 
-    }
-
-    rb_ary_push(finalizer->finalizers, block);
-    
-    // For RubySpec conformance.
-    return rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
-}
-
-void
-rb_gc_copy_finalizer(VALUE dest, VALUE obj)
-{
-    // TODO
-}
-
-/*
- *  call-seq:
- *     ObjectSpace._id2ref(object_id) -> an_object
- *
- *  Converts an object id to a reference to the object. May not be
- *  called on an object id passed as a parameter to a finalizer.
- *
- *     s = "I am a string"                    #=> "I am a string"
- *     r = ObjectSpace._id2ref(s.object_id)   #=> "I am a string"
- *     r == s                                 #=> true
- *
- */
-
-static VALUE
-id2ref(VALUE obj, SEL sel, VALUE objid)
-{
-#if SIZEOF_LONG == SIZEOF_VOIDP
-#define NUM2PTR(x) NUM2ULONG(x)
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
-#define NUM2PTR(x) NUM2ULL(x)
-#endif
-    VALUE ptr;
-    void *p0;
-
-    rb_secure(4);
-    ptr = NUM2PTR(objid);
-    p0 = (void *)ptr;
-
-    if (ptr == Qtrue) return Qtrue;
-    if (ptr == Qfalse) return Qfalse;
-    if (ptr == Qnil) return Qnil;
-    if (FIXNUM_P(ptr) || SYMBOL_P(ptr))
-	return ptr;
-
-    if (auto_zone_is_valid_pointer(__auto_zone, p0)) {
-	auto_memory_type_t type = 
-	    auto_zone_get_layout_type(__auto_zone, p0);
-	if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
-	    && (NATIVE((VALUE)p0)
-		|| (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
-	    return (VALUE)p0;
-    }
-    rb_raise(rb_eRangeError, "%p is not id value", p0);
-}
-
-/*
- *  Document-method: __id__
- *  Document-method: object_id
- *
- *  call-seq:
- *     obj.__id__       => fixnum
- *     obj.object_id    => fixnum
- *
- *  Returns an integer identifier for <i>obj</i>. The same number will
- *  be returned on all calls to <code>id</code> for a given object, and
- *  no two active objects will share an id.
- *  <code>Object#object_id</code> is a different concept from the
- *  <code>:name</code> notation, which returns the symbol id of
- *  <code>name</code>. Replaces the deprecated <code>Object#id</code>.
- */
-
-/*
- *  call-seq:
- *     obj.hash    => fixnum
- *
- *  Generates a <code>Fixnum</code> hash value for this object. This
- *  function must have the property that <code>a.eql?(b)</code> implies
- *  <code>a.hash == b.hash</code>. The hash value is used by class
- *  <code>Hash</code>. Any hash value that exceeds the capacity of a
- *  <code>Fixnum</code> will be truncated before being used.
- */
-
-VALUE
-rb_obj_id(VALUE obj, SEL sel)
-{
-    return (VALUE)LONG2NUM((SIGNED_VALUE)obj);
-}
-
-/*
- *  call-seq:
- *     ObjectSpace.count_objects([result_hash]) -> hash
- *
- *  Counts objects for each type.
- *
- *  It returns a hash as:
- *  {:TOTAL=>10000, :FREE=>3011, :T_OBJECT=>6, :T_CLASS=>404, ...}
- *
- *  If the optional argument, result_hash, is given,
- *  it is overwritten and returned.
- *  This is intended to avoid probe effect.
- *
- *  The contents of the returned hash is implementation defined.
- *  It may be changed in future.
- *
- *  This method is not expected to work except C Ruby.
- *
- */
-
-static VALUE
-count_objects(VALUE os, SEL sel, int argc, VALUE *argv)
-{
-    /* TODO implement me! */
-    return rb_hash_new();
-#if 0
-    rb_objspace_t *objspace = &rb_objspace;
-    size_t counts[T_MASK+1];
-    size_t freed = 0;
-    size_t total = 0;
-    size_t i;
-    VALUE hash;
-
-    if (rb_scan_args(argc, argv, "01", &hash) == 1) {
-        if (TYPE(hash) != T_HASH)
-            rb_raise(rb_eTypeError, "non-hash given");
-    }
-
-    for (i = 0; i <= T_MASK; i++) {
-        counts[i] = 0;
-    }
-
-    for (i = 0; i < heaps_used; i++) {
-        RVALUE *p, *pend;
-
-        p = heaps[i].slot; pend = p + heaps[i].limit;
-        for (;p < pend; p++) {
-            if (p->as.basic.flags) {
-                counts[BUILTIN_TYPE(p)]++;
-            }
-            else {
-                freed++;
-            }
-        }
-        total += heaps[i].limit;
-    }
-
-    if (hash == Qnil)
-        hash = rb_hash_new();
-    rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
-    rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));
-    for (i = 0; i <= T_MASK; i++) {
-        VALUE type;
-        switch (i) {
-#define COUNT_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
-	    COUNT_TYPE(T_NONE);
-	    COUNT_TYPE(T_OBJECT);
-	    COUNT_TYPE(T_CLASS);
-	    COUNT_TYPE(T_MODULE);
-	    COUNT_TYPE(T_FLOAT);
-	    COUNT_TYPE(T_STRING);
-	    COUNT_TYPE(T_REGEXP);
-	    COUNT_TYPE(T_ARRAY);
-	    COUNT_TYPE(T_HASH);
-	    COUNT_TYPE(T_STRUCT);
-	    COUNT_TYPE(T_BIGNUM);
-	    COUNT_TYPE(T_FILE);
-	    COUNT_TYPE(T_DATA);
-	    COUNT_TYPE(T_MATCH);
-	    COUNT_TYPE(T_COMPLEX);
-	    COUNT_TYPE(T_RATIONAL);
-	    COUNT_TYPE(T_NIL);
-	    COUNT_TYPE(T_TRUE);
-	    COUNT_TYPE(T_FALSE);
-	    COUNT_TYPE(T_SYMBOL);
-	    COUNT_TYPE(T_FIXNUM);
-	    COUNT_TYPE(T_VALUES);
-	    COUNT_TYPE(T_UNDEF);
-	    COUNT_TYPE(T_NODE);
-	    COUNT_TYPE(T_ICLASS);
-#undef COUNT_TYPE
-          default:              type = INT2NUM(i); break;
-        }
-        if (counts[i])
-            rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
-    }
-
-    return hash;
-#endif
-}
-
-/*
- *  call-seq:
- *     GC.count -> Integer
- *
- *  The number of times GC occured.
- *
- *  It returns the number of times GC occured since the process started.
- *
- */
-
-#define gc_count rb_f_notimplement
-
-/*
- *  The <code>GC</code> module provides an interface to Ruby's mark and
- *  sweep garbage collection mechanism. Some of the underlying methods
- *  are also available via the <code>ObjectSpace</code> module.
- */
-
-static bool gc_disabled = false;
-
-void
-Init_PreGC(void)
-{
-    auto_collection_control_t *control;
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-    __auto_zone = objc_collectableZone();
-#else
-    __auto_zone = auto_zone();
-#endif
-    
-    if (__auto_zone == NULL) {
-	rb_objc_no_gc_error();
-    }
-
-    __nsobject = (void *)objc_getClass("NSObject");
-
-    control = auto_collection_parameters(__auto_zone);
-    if (getenv("GC_DEBUG")) {
-	control->log = AUTO_LOG_COLLECTIONS | AUTO_LOG_REGIONS | AUTO_LOG_UNUSUAL;
-    }
-    if (getenv("GC_DISABLE")) {
-	gc_disabled = true;
-	auto_collector_disable(__auto_zone);
-    }
-}
-
-void
-Init_PostGC(void)
-{
-    if (!gc_disabled) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
-	objc_startCollectorThread();
-#endif
-    }
-}
-
-void
-Init_GC(void)
-{
-    VALUE rb_mObSpace;
-
-    rb_mGC = rb_define_module("GC");
-    rb_objc_define_module_function(rb_mGC, "start", rb_gc_start, 0);
-    rb_objc_define_module_function(rb_mGC, "enable", rb_gc_enable, 0);
-    rb_objc_define_module_function(rb_mGC, "disable", rb_gc_disable, 0);
-    rb_objc_define_module_function(rb_mGC, "stress", gc_stress_get, 0);
-    rb_objc_define_module_function(rb_mGC, "stress=", gc_stress_set, 1);
-    rb_objc_define_module_function(rb_mGC, "count", gc_count, 0);
-    rb_objc_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
-
-    rb_mObSpace = rb_define_module("ObjectSpace");
-    rb_objc_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
-    rb_objc_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
-
-    rb_objc_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
-    rb_objc_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);
-
-    rb_objc_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
-
-    nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
-    GC_RETAIN(nomem_error);
-
-    rb_objc_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
-    rb_objc_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
-
-    rb_objc_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
-
-    rb_cFinalizer = rb_define_class("__Finalizer", rb_cObject);
-    rb_objc_finalizer_finalize_super =
-	rb_objc_install_method2((Class)rb_cFinalizer,
-		"finalize", (IMP)rb_objc_finalizer_finalize);
-}
-
-void
-rb_global_variable(VALUE *slot)
-{
-    auto_zone_add_root(__auto_zone, (void *)slot, *(void **)slot);
-}
-
-void
-rb_gc_register_address(VALUE *slot)
-{
-    rb_global_variable(slot);
-}

Deleted: MacRuby/trunk/gcd.c
===================================================================
--- MacRuby/trunk/gcd.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gcd.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1368 +0,0 @@
-/*
- * MacRuby API for Grand Central Dispatch.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- */
-
-#define GCD_BLOCKS_COPY_DVARS 1
-
-#include "macruby_internal.h"
-#include "gcd.h"
-#include <unistd.h>
-#include "ruby/intern.h"
-#include "ruby/node.h"
-#include "ruby/io.h"
-#include "objc.h"
-#include "id.h"
-#include "vm.h"
-#include <libkern/OSAtomic.h>
-#include <asl.h>
-
-static SEL selClose;
-
-typedef struct {
-    struct RBasic basic;
-    int suspension_count;
-    dispatch_object_t obj;
-} rb_dispatch_obj_t;
-
-#define RDispatch(val) ((rb_dispatch_obj_t*)val)
-
-typedef struct {
-    struct RBasic basic;
-    int suspension_count;
-    dispatch_queue_t queue;
-    int should_release_queue;
-} rb_queue_t;
-
-#define RQueue(val) ((rb_queue_t*)val)
-
-typedef struct {
-    struct RBasic basic;
-    int suspension_count;
-    dispatch_group_t group;
-} rb_group_t;
-
-#define RGroup(val) ((rb_group_t*)val)
-
-typedef enum SOURCE_TYPE_ENUM
-{
-    SOURCE_TYPE_DATA_ADD,
-    SOURCE_TYPE_DATA_OR,
-    SOURCE_TYPE_MACH_SEND,
-    SOURCE_TYPE_MACH_RECV,
-    SOURCE_TYPE_PROC,
-    SOURCE_TYPE_READ,
-    SOURCE_TYPE_SIGNAL,
-    SOURCE_TYPE_TIMER,
-    SOURCE_TYPE_VNODE,
-    SOURCE_TYPE_WRITE
-} source_enum_t;
-
-typedef struct {
-    struct RBasic basic;
-    int suspension_count;
-    dispatch_source_t source;
-    source_enum_t source_enum;
-    rb_vm_block_t *event_handler;
-    VALUE handle;
-} rb_source_t;
-
-#define RSource(val) ((rb_source_t*)val)
-
-typedef struct {
-    struct RBasic basic;
-    int reserved;
-    dispatch_semaphore_t sem;
-    long count;
-} rb_semaphore_t;
-
-#define RSemaphore(val) ((rb_semaphore_t*)val)
-
-static OSSpinLock _suspensionLock = 0;
-
-static VALUE mDispatch;
-static VALUE cObject;
-
-static void *
-dispatch_object_imp(void *rcv, SEL sel)
-{
-    rb_dispatch_obj_t *obj = RDispatch(rcv);
-    return (void *)obj->obj._do;
-}
-
-// queue stuff
-static VALUE cQueue;
-static VALUE qMain;
-static VALUE qHighPriority;
-static VALUE qDefaultPriority;
-static VALUE qLowPriority;
-static ID high_priority_id;
-static ID low_priority_id;
-static ID default_priority_id;
-
-static VALUE cGroup;
-static VALUE cSource;
-static VALUE cSemaphore;
-
-static inline void
-Check_Queue(VALUE object)
-{
-    if (CLASS_OF(object) != cQueue) {
-	rb_raise(rb_eArgError, "expected Queue object, but got %s",
-		rb_class2name(CLASS_OF(object)));
-    }
-}
-
-dispatch_queue_t
-rb_get_dispatch_queue_object(VALUE queue)
-{
-    Check_Queue(queue);
-    return (dispatch_queue_t)dispatch_object_imp((void *)queue, 0);
-}
-
-static inline void
-Check_Group(VALUE object)
-{
-    if (CLASS_OF(object) != cGroup) {
-	rb_raise(rb_eArgError, "expected Group object, but got %s",
-		rb_class2name(CLASS_OF(object)));
-    }
-}
-
-static VALUE 
-rb_raise_init(VALUE self, SEL sel)
-{
-	rb_raise(rb_eArgError, "initializer called without any arguments");
-    return self;
-}
-
-
-#define SEC2NSEC_UINT64(sec) (uint64_t)(sec * NSEC_PER_SEC)
-#define SEC2NSEC_INT64(sec) (int64_t)(sec * NSEC_PER_SEC)
-#define TIMEOUT_MAX (1.0 * INT64_MAX / NSEC_PER_SEC)
-
-static inline uint64_t
-rb_num2nsec(VALUE num)
-{
-    const double sec = rb_num2dbl(num);
-    if (sec < 0.0) {
-        rb_raise(rb_eArgError, "negative delay specified");
-    }
-    return SEC2NSEC_UINT64(sec);
-}
-
-static inline dispatch_time_t
-rb_num2timeout(VALUE num)
-{
-    dispatch_time_t dispatch_timeout = DISPATCH_TIME_FOREVER;
-    if (!NIL_P(num)) {
-        const double sec = rb_num2dbl(num);
-        if (sec < TIMEOUT_MAX) {
-            dispatch_timeout = dispatch_walltime(NULL, SEC2NSEC_INT64(sec));
-        }
-    }
-    return dispatch_timeout;
-}
-
-static VALUE 
-rb_queue_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(queue, rb_queue_t);
-    OBJSETUP(queue, klass, RUBY_T_NATIVE);
-    queue->suspension_count = 0;
-    queue->should_release_queue = 0;
-    return (VALUE)queue;
-}
-
-static VALUE
-rb_queue_from_dispatch(dispatch_queue_t dq, bool should_retain)
-{
-    VALUE q = rb_queue_alloc(cQueue, 0);
-    if (should_retain) { 
-        GC_RETAIN(q);
-    }
-    RQueue(q)->queue = dq;
-    return q;
-}
-
-/*
- *  call-seq:
- *     Dispatch::Queue.concurrent(priority=:default)    => Dispatch::Queue
- *
- *  Returns one of the global concurrent priority queues.
- * 
- *  A dispatch queue is a FIFO queue that accepts tasks in the form of a block. 
- *  Blocks submitted to dispatch queues are executed on a pool of threads fully 
- *  managed by the system. Dispatched tasks execute one at a time in FIFO order.
- *  GCD takes take of using multiple cores effectively and better accommodate 
- *  the needs of all running applications, matching them to the 
- *  available system resources in a balanced fashion.
- *   
- *  Use concurrent queues to execute large numbers of tasks concurrently.
- *  GCD automatically creates three concurrent dispatch queues that are global 
- *  to your application and are differentiated only by their priority level. 
- *  
- *  The three priority levels are: +:low+, +:default+, 
- *  +:high+, corresponding to the DISPATCH_QUEUE_PRIORITY_HIGH, 
- *  DISPATCH_QUEUE_PRIORITY_DEFAULT, and DISPATCH_QUEUE_PRIORITY_LOW 
- *  (detailed in the dispatch_queue_create(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_queue_create.3.html]
- *  man page). The GCD thread dispatcher
- *  will perform actions submitted to the high priority queue before any actions 
- *  submitted to the default or low queues, and will only perform actions on the 
- *  low queues if there are no actions queued on the high or default queues.
- *
- *     gcdq = Dispatch::Queue.concurrent(:high)
- *     5.times { gcdq.async { print 'foo' } }
- *     gcdq_2 = Dispatch::Queue.concurrent(:low)
- *     gcdq_2.sync { print 'bar' }  # will always print 'foofoofoofoofoobar'.
- *
- */
-static VALUE
-rb_queue_get_concurrent(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE priority;
-    rb_scan_args(argc, argv, "01", &priority);
-    if (!NIL_P(priority)) {
-	ID id = rb_to_id(priority);
-	if (id == high_priority_id) {
-	    return qHighPriority;
-	}
-	else if (id == low_priority_id) {
-	    return qLowPriority;
-	}
-	else if (id != default_priority_id) {
-	    rb_raise(rb_eArgError,
-		    "invalid priority `%s' (expected either :low, :default or :high)",
-		    rb_id2name(id));
-        }
-    }
-    return qDefaultPriority;
-}
-
-
-/*
- *  call-seq:
- *     Dispatch::Queue.current      => Dispatch::Queue
- *
- *  When called from within a block that is being dispatched on a queue,
- *  this returns the queue in question. If executed outside of a block, 
- *  the result depends on whether the run method has been called on the
- *  main queue: if it has, it returns the main queue, otherwise it returns
- *  the default-priority concurrent queue.
- *
- */
-
-static VALUE
-rb_queue_get_current(VALUE klass, SEL sel)
-{
-    // TODO: check this to see if we need to retain it
-    return rb_queue_from_dispatch(dispatch_get_current_queue(), false);
-}
-
-/*
- *  call-seq:
- *     Dispatch::Queue.main           => Dispatch::Queue
- *
- *  Returns the dispatch queue for the main thread.
- *
- */
-
-static VALUE 
-rb_queue_get_main(VALUE klass, SEL sel)
-{
-    return qMain;
-}
-
-/*
- *  call-seq:
- *     Dispatch::Queue.new(label)        => Dispatch::Queue
- *
- *  Returns a new serial dispatch queue.
- * 
- *  A dispatch is a FIFO queue to which you can submit tasks via a block. 
- *  Blocks submitted to dispatch queues are executed on a pool of threads fully 
- *  managed by the system. Dispatched tasks execute one at a time in FIFO order.
- *  GCD takes take of using multiple cores effectively to better accommodate 
- *  the needs of all running applications, matching them to the 
- *  available system resources in a balanced fashion.
- *
- *  Use serial GCD queues to ensure that tasks execute in a predictable order.
- *  It's a good practice to identify a specific purpose for each serial queue, 
- *  such as protecting a resource or synchronizing key processes.
- *  Create as many as you need - serial queues are extremely lightweight 
- *  (with a total memory footprint of less than 300 bytes); however, remember to 
- *  use concurrent queues if you need to perform idempotent tasks in parallel.
- *  Dispatch queues need to be labeled and thereofore you need to pass a name 
- *  to create your queue. By convention, labels are in reverse-DNS style.
- *
- *     gcdq = Dispatch::Queue.new('org.macruby.gcd.example')
- *     gcdq.async { p 'doc' }
- *     gcdq.async { p 'bar' }
- *     gcdq.sync {} 
- *
- */
- 
-static VALUE 
-rb_queue_init(VALUE self, SEL sel, VALUE name)
-{
-    StringValue(name);
-
-    rb_queue_t *queue = RQueue(self);
-    queue->should_release_queue = 1;
-    queue->queue = dispatch_queue_create(RSTRING_PTR(name), NULL);
-    assert(queue->queue != NULL);
-    dispatch_retain(queue->queue);
-    return self;
-}
-
-static IMP rb_queue_finalize_super;
-
-static void
-rb_queue_finalize(void *rcv, SEL sel)
-{
-    rb_queue_t *queue = RQueue(rcv);
-    if (queue->queue != NULL) 
-    {
-        OSSpinLockLock(&_suspensionLock);
-        while (queue->suspension_count > 0) {
-            queue->suspension_count--;
-            dispatch_resume(queue->queue);
-        }
-        if (queue->should_release_queue) {
-            dispatch_release(queue->queue);
-            queue->should_release_queue = 0;
-        }        
-        OSSpinLockUnlock(&_suspensionLock);
-    }
-    if (rb_queue_finalize_super != NULL) {
-        ((void(*)(void *, SEL))rb_queue_finalize_super)(rcv, sel);
-    }
-}
-
-static VALUE
-rb_block_rescue(VALUE data, VALUE exc)
-{
-    fprintf(stderr, "*** Dispatch block exited prematurely because of an uncaught exception:\n%s\n", rb_str_cstr(rb_format_exception_message(exc)));
-    return Qnil;
-}
-
-static VALUE
-rb_block_release_eval(VALUE data)
-{
-    GC_RELEASE(data);
-    rb_vm_block_t *b = (rb_vm_block_t *)data;
-    return rb_vm_block_eval(b, 0, NULL);
-}
-
-static void
-rb_block_dispatcher(void *data)
-{
-    assert(data != NULL);
-    rb_rescue(rb_block_release_eval, (VALUE)data, rb_block_rescue, Qnil);
-}
-
-static rb_vm_block_t *
-get_prepared_block()
-{
-    rb_vm_block_t *block = rb_vm_current_block();
-    if (block == NULL) {
-        rb_raise(rb_eArgError, "block not given");
-    }
-#if GCD_BLOCKS_COPY_DVARS
-    block = rb_vm_dup_block(block);
-    for (int i = 0; i < block->dvars_size; i++) {
-    	VALUE *slot = block->dvars[i];
-    	VALUE *new_slot = xmalloc(sizeof(VALUE));
-    	GC_WB(new_slot, *slot);
-    	GC_WB(&block->dvars[i], new_slot);
-    }
-#else
-    rb_vm_block_make_detachable_proc(block);
-#endif
-    GC_RETAIN(block);
-    return block;
-}
-
-/* 
- *  call-seq:
- *    gcdq.async(group=nil) { @i = 42 }
- *
- *  Yields the passed block asynchronously via dispatch_async(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_async.3.html]:
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     @i = 42
- *     gcdq.async { @i = 42 }
- *     while @i == 0 do; end
- *     p @i #=> 42
- *
- *  If a group is specified, the dispatch will be associated with that group via
- *  dispatch_group_async(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_group_async.3.html]:
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     gcdg = Dispatch::Group.new
- *     @i = 42
- *     gcdq.async(gcdg) { @i = 42 }
- *     gcdg.wait
- *     p @i #=> 42
- *
- */
-
-static VALUE
-rb_queue_dispatch_async(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    rb_vm_block_t *block = get_prepared_block();
-    VALUE group;
-    rb_scan_args(argc, argv, "01", &group);
-
-    if (group != Qnil) {
-	Check_Group(group);
-	dispatch_group_async_f(RGroup(group)->group, RQueue(self)->queue,
-		(void *)block, rb_block_dispatcher);
-    }
-    else {
-	dispatch_async_f(RQueue(self)->queue, (void *)block,
-		rb_block_dispatcher);
-    }
-
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    gcdq.sync { @i = 42 }
- *
- *  Yields the passed block synchronously via dispatch_sync(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_sync.3.html]:
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     @i = 42
- *     gcdq.sync { @i = 42 }
- *     p @i #=> 42
- *
- */
-
-
-static VALUE
-rb_queue_dispatch_sync(VALUE self, SEL sel)
-{
-    rb_vm_block_t *block = get_prepared_block();
-    dispatch_sync_f(RQueue(self)->queue, (void *)block,
-	    rb_block_dispatcher);
-
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    gcdq.after(delay) { block }
- *
- *  Runs the passed block after the given delay (in seconds) using
- *  dispatch_after(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_after.3.html],
- *  
- *     gcdq.after(0.5) { puts 'wait is over :)' }
- *
- */
-static VALUE
-rb_queue_dispatch_after(VALUE self, SEL sel, VALUE delay)
-{
-    dispatch_time_t offset = NIL_P(delay) ? DISPATCH_TIME_NOW : rb_num2timeout(delay);
-    rb_vm_block_t *block = get_prepared_block();
-    dispatch_after_f(offset, RQueue(self)->queue, (void *)block,
-	    rb_block_dispatcher);
-
-    return Qnil;
-}
-
-static VALUE
-rb_block_arg_eval(VALUE *args)
-{
-    rb_vm_block_t *b = (rb_vm_block_t *)args[0];
-    return rb_vm_block_eval(b, 1, &args[1]);
-}
-
-static void
-rb_block_arg_dispatcher(rb_vm_block_t *block, VALUE param)
-{
-    assert(block != NULL);
-    VALUE args[2];
-    args[0] = (VALUE)block;
-    args[1] = param;
-    rb_rescue(rb_block_arg_eval, (VALUE) args, rb_block_rescue, (VALUE)"gcd.c: Exception in rb_block_arg_dispatcher");
-}
-
-static void
-rb_block_applier(void *data, size_t ii)
-{
-    assert(data != NULL);
-    rb_vm_block_t *block = rb_vm_uncache_or_dup_block((rb_vm_block_t *)data);
-    rb_block_arg_dispatcher(block, SIZET2NUM(ii));
-}
-
-/* 
- *  call-seq:
- *    gcdq.apply(count) { |index| block }
- *
- *  Runs a block count number of times in parallel via 
- *  dispatch_apply(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_apply.3.html],
- *  passing in an index and waiting until all of them are done
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     @result = []
- *     gcdq.apply(5) {|i| @result[i] = i*i }
- *     p @result  #=> [0, 1, 4, 9, 16, 25]
- *
- */
-
-static VALUE
-rb_queue_apply(VALUE self, SEL sel, VALUE n)
-{
-    rb_vm_block_t *block = get_prepared_block();
-    dispatch_apply_f(NUM2SIZET(n), RQueue(self)->queue, (void *)block,
-	    rb_block_applier);
-
-    GC_RELEASE(block);
-
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    gcdq.to_s -> str
- *
- *  Returns the label of the dispatch queue
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     gcdq.to_s #=> 'doc'
- *     gcdq = Dispatch::Queue.main
- *     gcdq.to_s #=> 'com.apple.main-thread'
- *
- */
-
-static VALUE 
-rb_queue_label(VALUE self, SEL sel)
-{
-    return rb_str_new2(dispatch_queue_get_label(RQueue(self)->queue));
-}
-
-static VALUE
-rb_main_queue_run(VALUE self, SEL sel)
-{
-    dispatch_main();
-    return Qnil; // never reached
-}
-
-
-/* 
- *  call-seq:
- *    obj.suspend!
- *
- *  Suspends the operation of a
- *  dispatch_object(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_object.3.html#//apple_ref/doc/man/3/dispatch_object]
- *  (queue or source). To resume operation, call +resume!+.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     gcdq.dispatch { sleep 1 }
- *     gcdq.suspend!
- *     gcdq.suspended?  #=> true
- *     gcdq.resume!
- *
- */
- 
-static VALUE
-rb_dispatch_suspend(VALUE self, SEL sel)
-{
-    rb_dispatch_obj_t *dobj = RDispatch(self);
-    OSSpinLockLock(&_suspensionLock);
-    dobj->suspension_count++;
-    OSSpinLockUnlock(&_suspensionLock);    
-    dispatch_suspend(dobj->obj);
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    obj.resume!
- *
- *  Resumes the operation of a
- *  dispatch_object(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_object.3.html#//apple_ref/doc/man/3/dispatch_object]
- *  (queue or source). To suspend operation, call +suspend!+.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     gcdq.dispatch { sleep 1 }
- *     gcdq.suspend!
- *     gcdq.suspended?  #=> true
- *     gcdq.resume!
- *
- */
- 
-static VALUE
-rb_dispatch_resume(VALUE self, SEL sel)
-{
-    rb_dispatch_obj_t *dobj = RDispatch(self);
-    OSSpinLockLock(&_suspensionLock);
-    if (dobj->suspension_count > 0) {
-        dobj->suspension_count--;
-        dispatch_resume(dobj->obj);
-    }
-    OSSpinLockUnlock(&_suspensionLock);    
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    obj.suspended?   => true or false
- *
- *  Returns +true+ if <i>obj</i> is suspended.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     gcdq.dispatch { sleep 1 }
- *     gcdq.suspend!
- *     gcdq.suspended?  #=> true
- *     gcdq.resume!
- *     gcdq.suspended?  #=> false
- *
- */
- 
-static VALUE
-rb_dispatch_suspended_p(VALUE self, SEL sel)
-{
-    return (RDispatch(self)->suspension_count == 0) ? Qfalse : Qtrue;
-}
-
-static VALUE
-rb_group_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(group, rb_group_t);
-    OBJSETUP(group, klass, RUBY_T_NATIVE);
-    group->suspension_count = 0;
-    return (VALUE)group;
-}
-
-/* 
- *  call-seq:
- *    Dispatch::Group.new    =>  Dispatch::Group
- *
- *  Returns a Group allowing for aggregate synchronization, as defined in:
- *  dispatch_group_create(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_group_create.3.html]
- 
- *  You can dispatch multiple blocks and track when they all complete, 
- *  even though they might run on different queues. 
- *  This behavior can be helpful when progress can not be made until all 
- *  of the specified tasks are complete.
- *  
- *     gcdg = Dispatch::Group.new
- *
- */
-
-static VALUE
-rb_group_init(VALUE self, SEL sel)
-{
-    RGroup(self)->group = dispatch_group_create();
-    assert(RGroup(self)->group != NULL);
-    
-    return self;
-}
-
-/* 
- *  call-seq:
- *    grp.notify { block }
- *
- *  Asynchronously schedules a block to be called when the previously
- *  submitted dispatches for that group have completed.
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     grp = Dispatch::Group.new
- *     gcdq.async(grp) { print 'foo' }
- *     grp.notify { print 'bar' } #=> foobar
- */
-
-static VALUE
-rb_group_notify(VALUE self, SEL sel, VALUE target)
-{
-    rb_vm_block_t *block = get_prepared_block();
-    Check_Queue(target);
-
-    dispatch_group_notify_f(RGroup(self)->group, RQueue(target)->queue,
-	    (void *)block, rb_block_dispatcher);
-
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    grp.wait(timeout=nil)     => true or false
- *
- *  Waits until all the blocks associated with the +grp+ have 
- *  finished executing or until the specified +timeout+ has elapsed.
- *  The function will return +true+ if the group became empty within 
- *  the specified amount of time and will return +false+ otherwise.
- *  If the supplied timeout is nil, the function will wait indefinitely until 
- *  the specified group becomes empty, always returning true.
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     grp = Dispatch::Group.new
- *     gcdq.async(grp) { sleep 4 }
- *     grp.wait(5) #=> true
- */
- 
-static VALUE
-rb_group_wait(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE num;
-    rb_scan_args(argc, argv, "01", &num);
-    return dispatch_group_wait(RGroup(self)->group, rb_num2timeout(num))
-        == 0 ? Qtrue : Qfalse;
-}
-
-static IMP rb_group_finalize_super;
-
-static void
-rb_group_finalize(void *rcv, SEL sel)
-{
-    rb_group_t *grp = RGroup(rcv);
-    if (grp->group != NULL) {
-        dispatch_release(grp->group);
-    }
-    if (rb_group_finalize_super != NULL) {
-        ((void(*)(void *, SEL))rb_group_finalize_super)(rcv, sel);
-    }
-}
-
-static inline dispatch_source_type_t
-rb_source_enum2type(source_enum_t value)
-{
-    switch (value)
-    {
-        case SOURCE_TYPE_DATA_ADD: return DISPATCH_SOURCE_TYPE_DATA_ADD;
-        case SOURCE_TYPE_DATA_OR: return DISPATCH_SOURCE_TYPE_DATA_OR;
-        case SOURCE_TYPE_MACH_SEND: return DISPATCH_SOURCE_TYPE_MACH_SEND;
-        case SOURCE_TYPE_MACH_RECV: return DISPATCH_SOURCE_TYPE_MACH_RECV;
-        case SOURCE_TYPE_PROC: return DISPATCH_SOURCE_TYPE_PROC;
-        case SOURCE_TYPE_READ: return DISPATCH_SOURCE_TYPE_READ;
-        case SOURCE_TYPE_SIGNAL: return DISPATCH_SOURCE_TYPE_SIGNAL;
-        case SOURCE_TYPE_TIMER: return DISPATCH_SOURCE_TYPE_TIMER;
-        case SOURCE_TYPE_VNODE: return DISPATCH_SOURCE_TYPE_VNODE;
-        case SOURCE_TYPE_WRITE: return DISPATCH_SOURCE_TYPE_WRITE;
-        default: rb_raise(rb_eArgError, 
-                          "Unknown dispatch source type `%d'", value);
-    }
-    return NULL;
-}
-
-static inline BOOL
-rb_source_is_file(rb_source_t *src)
-{
-    source_enum_t value = src->source_enum;
-    if (value == SOURCE_TYPE_READ || value == SOURCE_TYPE_VNODE 
-        || value == SOURCE_TYPE_WRITE) {
-        return true;
-    }
-    return false;
-}
-
-static VALUE
-rb_source_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(source, rb_source_t);
-    OBJSETUP(source, klass, RUBY_T_NATIVE);
-    source->suspension_count = 1;
-    return (VALUE)source;
-}
-
-static void
-rb_source_event_handler(void* sourceptr)
-{
-    assert(sourceptr != NULL);
-    rb_source_t *source = RSource(sourceptr);
-    rb_block_arg_dispatcher(source->event_handler, (VALUE) source);
-}
-
-static void
-rb_source_close_handler(void* sourceptr)
-{
-    assert(sourceptr != NULL);
-    rb_source_t *src = RSource(sourceptr);
-    rb_io_close(src->handle);
-//    Call rb_io_close directly since rb_vm_call aborts inside block
-//    rb_vm_call(io, selClose, 0, NULL, false);
-}
-
-/* 
- *  call-seq:
- *    Dispatch::Source.new(type, handle, mask, queue) {|src| block}
- *     => Dispatch::Source
- *
- *  Returns a Source used to monitor a variety of system objects and events, 
- *  using dispatch_source_create(3)[http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man3/dispatch_source_create.3.html]
- *
- *  If an IO object (e.g., File) is passed as the handle, it will automatically
- *  create a cancel handler that closes that file (see +cancel!+ for details).
- *  The type must be one of:
- *      - Dispatch::Source::READ (calls +handle.close_read+)
- *      - Dispatch::Source::WRITE (calls +handle.close_write+)
- *      - Dispatch::Source::VNODE (calls +handle.close+)
- *  This is the only way to set the cancel_handler, since in MacRuby
- *  sources start off resumed. This is safer than closing the file
- *  yourself, as the cancel handler is guaranteed to only run once,
- *  and only after all pending events are processed.
- *  If you do *not* want the file closed on cancel, simply use
- *  +file.to_i+ to instead pass a descriptor as the handle.
- */
-
-static VALUE
-rb_source_init(VALUE self, SEL sel,
-    VALUE type, VALUE handle, VALUE mask, VALUE queue)
-{
-    Check_Queue(queue);
-    rb_source_t *src = RSource(self);
-    src->source_enum = (source_enum_t) NUM2LONG(type);
-    dispatch_source_type_t c_type = rb_source_enum2type(src->source_enum);
-    assert(c_type != NULL);
-    uintptr_t c_handle = NUM2UINT(rb_Integer(handle));
-    unsigned long c_mask = NUM2LONG(mask);
-    dispatch_queue_t c_queue = RQueue(queue)->queue;
-    src->source = dispatch_source_create(c_type, c_handle, c_mask, c_queue);
-    assert(src->source != NULL);
-
-    rb_vm_block_t *block = get_prepared_block();
-    GC_WB(&src->event_handler, block);
-    GC_RETAIN(self); // apparently needed to ensure consistent counting
-    dispatch_set_context(src->source, (void *)self);
-    dispatch_source_set_event_handler_f(src->source, rb_source_event_handler);
-
-    GC_WB(&src->handle, handle);
-    if (rb_source_is_file(src) && rb_obj_is_kind_of(handle, rb_cIO)) {
-        dispatch_source_set_cancel_handler_f(src->source,
-          rb_source_close_handler);
-    }
-    rb_dispatch_resume(self, 0);
-    return self;
-}
-
-/* 
- *  call-seq:
- *    Dispatch::Source.timer(delay, interval, leeway, queue) 
- *    =>  Dispatch::Source
- *
- *  Returns a Source that will submit the event handler block to
- *  the target queue after delay, repeated at interval, within leeway, via
- *  a call to dispatch_source_set_timer(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_source_set_timer.3.html].
- *  A best effort attempt is made to submit the event handler block to the
- *  target queue at the specified time; however, actual invocation may occur at
- *  a later time even if the leeway is zero.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     timer = Dispatch::Source.timer(0, 5, 0.1, gcdq) do |s|
- *        puts s.data
- *     end
- *
- */
-
-static VALUE
-rb_source_timer(VALUE klass, VALUE sel, VALUE delay, VALUE interval, VALUE leeway, VALUE queue)
-{
-    Check_Queue(queue);
-    dispatch_time_t start_time;
-    VALUE argv[4] = {INT2FIX(SOURCE_TYPE_TIMER),
-        INT2FIX(0), INT2FIX(0), queue};
-    
-    VALUE self = rb_class_new_instance(4, argv, cSource);
-    rb_source_t *src = RSource(self);
-
-    if (NIL_P(leeway)) {
-        leeway = INT2FIX(0);
-    }
-    if (NIL_P(delay)) {
-        start_time = DISPATCH_TIME_NOW;
-    }
-    else {
-        start_time = rb_num2timeout(delay);
-    }
-
-    rb_dispatch_suspend(self, 0);
-    dispatch_source_set_timer(src->source, start_time,
-	    rb_num2nsec(interval), rb_num2nsec(leeway));
-    rb_dispatch_resume(self, 0);
-    return self;
-}
-
-/* 
- *  call-seq:
- *    src.handle => Number
- *
- *  Returns the underlying Ruby handle for the dispatch source (i.e. file,
- *  file descriptor, process identifer, etc.).
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     name = "/var/tmp/gcd_spec_source-#{$$}-#{Time.now}"
- *     file = File.open(name, "w")
- *     src = Dispatch::Source.new(Dispatch::Source::WRITE, file, 0, gcdq) { }
- *     puts src.handle #=> file
- */
-
-static VALUE
-rb_source_get_handle(VALUE self, SEL sel)
-{
-    return RSource(self)->handle;
-}
-
-/* 
- *  call-seq:
- *    src.mask => Number
- *
- *  Returns a Number representing the mask argument, corresponding to the flags
- *  set when the source was created.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) { }
- *     puts src.mask #=> 0
- */
-
-static VALUE
-rb_source_get_mask(VALUE self, SEL sel)
-{
-    return INT2NUM(dispatch_source_get_mask(RSource(self)->source));
-}
-
-/* 
- *  call-seq:
- *    src.data => Number
- *
- *  Returns a Number containing currently pending data for the dispatch source.
- *  This function should only be called from within the source's event handler.
- *  The result of calling this function from any other context is undefined.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
- *       puts s.data
- *     end
- *     src.merge(1)
- *     gcdq.sync { } #=> 1
- */
-
-static VALUE
-rb_source_get_data(VALUE self, SEL sel)
-{
-    return LONG2NUM(dispatch_source_get_data(RSource(self)->source));
-}
-
-/* 
- *  call-seq:
- *    src.merge(number)
- *
- *  Intended only for use with the Dispatch::Source::DATA_ADD and
- *  Dispatch::Source::DATA_OR source types, calling this function will
- *  atomically ADD or logical OR the count into the source's data, and 
- *  trigger delivery of the source's event handler.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     @sum = 0
- *     src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
- *       @sum += s.data # safe since always serialized
- *     end
- *     src.merge(1)
- *     src.merge(3)
- *     gcdq.sync { }
- *     puts @sum #=> 4
- */
-
-static VALUE
-rb_source_merge(VALUE self, SEL sel, VALUE data)
-{
-    dispatch_source_merge_data(RSource(self)->source, NUM2INT(data));
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    src.cancel!
- *
- *  Asynchronously cancels the dispatch source, preventing any further
- *  invocation of its event handler block. Cancellation does not interrupt a
- *  currently executing handler block (non-preemptive).
- *
- *  When a dispatch source is canceled its cancellation handler will be 
- *  submitted to its target queue. This is only used by Dispatch::Source;
- *  when initialized a File (or IO) object, it will automatically set a
- *  cancellation handler that closes it.
- */
-
-static VALUE
-rb_source_cancel(VALUE self, SEL sel)
-{
-    dispatch_source_cancel(RSource(self)->source);
-    return Qnil;
-}
-
-/* 
- *  call-seq:
- *    src.cancelled?
- *
- *  Used to determine whether the specified source has been cancelled.
- *  True will be returned if the source is cancelled.
- */
-
-static VALUE
-rb_source_cancelled_p(VALUE self, SEL sel)
-{
-    return dispatch_source_testcancel(RSource(self)->source) ? Qtrue : Qfalse;
-}
-
-static IMP rb_source_finalize_super;
-
-static void
-rb_source_finalize(void *rcv, SEL sel)
-{
-    rb_source_t *src = RSource(rcv);
-    if (src->source != NULL) {
-        OSSpinLockLock(&_suspensionLock);    
-        while (src->suspension_count > 0) {
-            src->suspension_count--;
-            dispatch_resume(src->source);
-        }
-        dispatch_release(src->source);
-        OSSpinLockUnlock(&_suspensionLock);            
-    }
-    if (rb_source_finalize_super != NULL) {
-        ((void(*)(void *, SEL))rb_source_finalize_super)(rcv, sel);
-    }
-}
-
-static VALUE
-rb_semaphore_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(s, rb_semaphore_t);
-    OBJSETUP(s, klass, RUBY_T_NATIVE);
-    s->sem = NULL;
-    s->count = 0;
-    return (VALUE)s;
-}
-
-/* 
- *  call-seq:
- *    Dispatch::Semaphore.new(count) =>  Dispatch::Semaphore
- *
- *  Returns a Semaphore used to synchronize threads through a combination of
- *  waiting and signalling, as detailed in the
- *  dispatch_semaphore_create(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch_semaphore_create.3.html]
- *  man page.
- *
- *  If the count parameter is equal to zero, the semaphore is useful for
- *  synchronizing completion of work:
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     sema = Dispatch::Semaphore.new(0)
- *     gcdq.async { puts "Begin."; sema.signal }
- *     puts "Waiting..."
- *     sema.wait
- *     puts "End!"
- *
- *  If the count parameter is greater than zero, then the semaphore is useful
- *  for managing a finite pool of resources.
- *
- */
-
-static VALUE
-rb_semaphore_init(VALUE self, SEL sel, VALUE value)
-{
-    dispatch_semaphore_t s = dispatch_semaphore_create(NUM2LONG(value));
-    if (s == NULL) {
-    	rb_raise(rb_eArgError, "Can't create semaphore based on value `%ld'",
-    		NUM2LONG(value));
-    }
-    RSemaphore(self)->sem = s;
-    RSemaphore(self)->count = NUM2LONG(value);
-    return self;
-}
-
-/* 
- *  call-seq:
- *    sema.signal => true or false
- *
- *  Signals the semaphore to wake up any waiting threads
- *
- *  Returns true if no thread is waiting, false otherwise
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     sema = Dispatch::Semaphore.new(0)
- *     gcdq.async { sleep 0.1; sema.signal } #=> false
- *     sema.wait
- *
- */
-static VALUE
-rb_semaphore_signal(VALUE self, SEL sel)
-{
-    return dispatch_semaphore_signal(RSemaphore(self)->sem) == 0 
-        ? Qtrue : Qfalse;
-}
-
-/* 
- *  call-seq:
- *    sema.wait(timeout) => true or false
- *
- *  Waits (blocks the thread) until a signal arrives or the timeout expires.
- *  Timeout defaults to DISPATCH_TIME_FOREVER.
- *
- *  Returns true if signalled, false if timed out.
- *
- *     gcdq = Dispatch::Queue.new('doc')
- *     sema = Dispatch::Semaphore.new(0)
- *     gcdq.async { sleep 0.1; sema.signal }
- *     sema.wait #=> true
- *
- */
-static VALUE
-rb_semaphore_wait(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE num;
-    rb_scan_args(argc, argv, "01", &num);
-    return dispatch_semaphore_wait(RSemaphore(self)->sem, rb_num2timeout(num))
-        == 0 ? Qtrue : Qfalse;
-}
-
-
-static IMP rb_semaphore_finalize_super;
-
-static void
-rb_semaphore_finalize(void *rcv, SEL sel)
-{
-    if (RSemaphore(rcv)->sem != NULL) {
-	while (dispatch_semaphore_signal(RSemaphore(rcv)->sem) != 0) {}
-	while (--RSemaphore(rcv)->count >= 0) {
-	    dispatch_semaphore_signal(RSemaphore(rcv)->sem);
-	}
-	dispatch_release(RSemaphore(rcv)->sem);
-    }
-    if (rb_semaphore_finalize_super != NULL) {
-        ((void(*)(void *, SEL))rb_semaphore_finalize_super)(rcv, sel);
-    }
-}
-
-// GCD callbacks that will let us know when a POSIX thread is started / ended.
-// We can appropriately create/delete a RoxorVM object based on that.
-static void (*old_dispatch_begin_thread_4GC)(void) = NULL;
-static void (*old_dispatch_end_thread_4GC)(void) = NULL;
-extern void (*dispatch_begin_thread_4GC)(void);
-extern void (*dispatch_end_thread_4GC)(void);
-
-static void
-rb_dispatch_begin_thread(void)
-{
-    if (old_dispatch_begin_thread_4GC != NULL) {
-	(*old_dispatch_begin_thread_4GC)();
-    }
-    rb_vm_register_current_alien_thread();
-}
-
-static void
-rb_dispatch_end_thread(void)
-{
-    if (old_dispatch_end_thread_4GC != NULL) {
-	(*old_dispatch_end_thread_4GC)();
-    }
-    rb_vm_unregister_current_alien_thread();
-}
-
-void
-Init_PreGCD(void)
-{
-    old_dispatch_begin_thread_4GC = dispatch_begin_thread_4GC;
-    old_dispatch_end_thread_4GC = dispatch_end_thread_4GC;
-    dispatch_begin_thread_4GC = rb_dispatch_begin_thread;
-    dispatch_end_thread_4GC = rb_dispatch_end_thread;
-}
-
-void
-Init_Dispatch(void)
-{
-    high_priority_id = rb_intern("high");
-    low_priority_id = rb_intern("low");
-    default_priority_id = rb_intern("default");
-
-/*
- *  Grand Central Dispatch (GCD) is a novel approach to multicore computing
- *  first release in Mac OS X version 10.6 Snow Leopard, and available as
- *  open source via the libdispatch project. GCD shifts the
- *  responsibility for managing threads and their execution from
- *  applications onto the operating system. This allows programmers to easily
- *  refactor their programs into small chunks of independent work, which GCD
- *  then schedules onto per-process thread pools.  Because GCD knows the load
- *  across the entire system, it ensures the resulting programs perform
- *  optimally on a wide range of hardware.
- *
- *  The Dispatch module allows Ruby blocks to be scheduled for asynchronous and
- *  concurrent execution, either explicitly or in response to
- *  various kinds of events. It provides a convenient high-level interface
- *  to the underlying C API via objects for the four primary abstractions.
- *
- *  Dispatch::Queue is the basic units of organization of blocks.
- *  Several queues are created by default, and applications may create
- *  additional queues for their own use.
- *
- *  Dispatch::Group allows applications to track the progress of blocks
- *  submitted to queues and take action when the blocks complete.
- * 
- *  Dispatch::Source monitors and coalesces low-level system events so that they
- *  can be responded to asychronously via simple event handlers.
- *
- *  Dispatch::Semaphore synchronizes threads via a combination of
- *  waiting and signalling.
- *
- *  For more information, see the dispatch(3)[http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man3/dispatch.3.html] man page.  
- */
-    mDispatch = rb_define_module("Dispatch");
-
-    cObject = rb_define_class_under(mDispatch, "Object", rb_cObject);
-    rb_objc_define_method(cObject, "resume!", rb_dispatch_resume, 0);
-    rb_objc_define_method(cObject, "suspend!", rb_dispatch_suspend, 0);
-    rb_objc_define_method(cObject, "suspended?", rb_dispatch_suspended_p, 0);
-
-    // This API allows Ruby code to pass the internal dispatch_queue_t object
-    // to C/Objective-C APIs.
-    class_replaceMethod((Class)cObject, sel_registerName("dispatch_object"),
-	    (IMP)dispatch_object_imp, "^v@:");
-
-/*
- * A Dispatch::Queue is the fundamental mechanism for scheduling blocks for
- * execution, either synchronously or asychronously.
- *
- * All blocks submitted to dispatch queues begin executing in the order
- * they were received. The system-defined concurrent queues can execute
- * multiple blocks in parallel, depending on the number of idle threads
- * in the thread pool. Serial queues (the main and user-created queues)
- * wait for the prior block to complete before dequeuing and executing
- * the next block.
- *
- * Queues are not bound to any specific thread of execution and blocks
- * submitted to independent queues may execute concurrently.
- */ 
- 
-    cQueue = rb_define_class_under(mDispatch, "Queue", cObject);    
-    rb_objc_define_method(*(VALUE *)cQueue, "alloc", rb_queue_alloc, 0);
-    rb_objc_define_method(*(VALUE *)cQueue, "concurrent",
-	    rb_queue_get_concurrent, -1);
-    rb_objc_define_method(*(VALUE *)cQueue, "current", rb_queue_get_current, 0);
-    rb_objc_define_method(*(VALUE *)cQueue, "main", rb_queue_get_main, 0);
-    rb_objc_define_method(cQueue, "initialize", rb_queue_init, 1);
-    rb_objc_define_method(cQueue, "initialize", rb_raise_init, 0);
-    rb_objc_define_method(cQueue, "apply", rb_queue_apply, 1);
-    rb_objc_define_method(cQueue, "async", rb_queue_dispatch_async, -1);
-    rb_objc_define_method(cQueue, "sync", rb_queue_dispatch_sync, 0);
-    rb_objc_define_method(cQueue, "after", rb_queue_dispatch_after, 1);
-    rb_objc_define_method(cQueue, "label", rb_queue_label, 0); // deprecated
-    rb_objc_define_method(cQueue, "to_s", rb_queue_label, 0);
-    
-    rb_queue_finalize_super = rb_objc_install_method2((Class)cQueue,
-	    "finalize", (IMP)rb_queue_finalize);
-
-    qHighPriority = rb_queue_from_dispatch(dispatch_get_global_queue(
-		DISPATCH_QUEUE_PRIORITY_HIGH, 0), true);
-    qDefaultPriority = rb_queue_from_dispatch(dispatch_get_global_queue(
-		DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), true);
-    qLowPriority = rb_queue_from_dispatch(dispatch_get_global_queue(
-		DISPATCH_QUEUE_PRIORITY_LOW, 0), true);
-    
-    qMain = rb_queue_from_dispatch(dispatch_get_main_queue(), true);
-    rb_objc_define_method(rb_singleton_class(qMain), "run", rb_main_queue_run,
-	    0);
-    
-/*
- * Dispatch::Group is used to aggregate multiple blocks 
- * that have been submitted asynchronously to different queues.
- * This lets you ensure they have all completed before beginning
- * or submitting additional work.
- */ 
-    cGroup = rb_define_class_under(mDispatch, "Group", cObject);
-    rb_objc_define_method(*(VALUE *)cGroup, "alloc", rb_group_alloc, 0);
-    rb_objc_define_method(cGroup, "initialize", rb_group_init, 0);
-    rb_objc_define_method(cGroup, "notify", rb_group_notify, 1);
-    rb_objc_define_method(cGroup, "on_completion", rb_group_notify, 1); // deprecated
-    rb_objc_define_method(cGroup, "wait", rb_group_wait, -1);
-    
-    rb_group_finalize_super = rb_objc_install_method2((Class)cGroup,
-	    "finalize", (IMP)rb_group_finalize);
-
-/*
- *  Dispatch::Source monitors a variety of system objects and events including
- *  file descriptors, processes, virtual filesystem nodes, signals and timers.
- *
- *  When a state change occurs, the dispatch source will submit its event
- *  handler block to its target queue, with the source as a parameter.
- *  
- *     gcdq = Dispatch::Queue.new('doc')
- *     src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
- *       puts "Fired with #{s.data}"
- *     end
- *
- *  Unlike GCD's C API, Dispatch::Source objects start off resumed
- *  (since the event handler -et al- have already been set).
- *   
- *     src.suspended? #=? false
- *     src.merge(0)
- *     gcdq.sync { } #=> Fired!
- */
-    cSource = rb_define_class_under(mDispatch, "Source", cObject);
-    rb_define_const(cSource, "DATA_ADD", INT2NUM(SOURCE_TYPE_DATA_ADD));
-    rb_define_const(cSource, "DATA_OR", INT2NUM(SOURCE_TYPE_DATA_OR));
-    rb_define_const(cSource, "PROC", INT2NUM(SOURCE_TYPE_PROC));
-    rb_define_const(cSource, "READ", INT2NUM(SOURCE_TYPE_READ));
-    rb_define_const(cSource, "SIGNAL", INT2NUM(SOURCE_TYPE_SIGNAL));
-    rb_define_const(cSource, "VNODE", INT2NUM(SOURCE_TYPE_VNODE));
-    rb_define_const(cSource, "WRITE", INT2NUM(SOURCE_TYPE_WRITE));
-    
-    rb_define_const(cSource, "PROC_EXIT", INT2NUM(DISPATCH_PROC_EXIT));
-    rb_define_const(cSource, "PROC_FORK", INT2NUM(DISPATCH_PROC_FORK));
-    rb_define_const(cSource, "PROC_EXEC", INT2NUM(DISPATCH_PROC_EXEC));
-    rb_define_const(cSource, "PROC_SIGNAL", INT2NUM(DISPATCH_PROC_SIGNAL));
-
-    rb_define_const(cSource, "VNODE_DELETE", INT2NUM(DISPATCH_VNODE_DELETE));
-    rb_define_const(cSource, "VNODE_WRITE", INT2NUM(DISPATCH_VNODE_WRITE));
-    rb_define_const(cSource, "VNODE_EXTEND", INT2NUM(DISPATCH_VNODE_EXTEND));
-    rb_define_const(cSource, "VNODE_ATTRIB", INT2NUM(DISPATCH_VNODE_ATTRIB));
-    rb_define_const(cSource, "VNODE_LINK", INT2NUM(DISPATCH_VNODE_LINK));
-    rb_define_const(cSource, "VNODE_RENAME", INT2NUM(DISPATCH_VNODE_RENAME));
-    rb_define_const(cSource, "VNODE_REVOKE", INT2NUM(DISPATCH_VNODE_REVOKE));
-
-    rb_objc_define_method(*(VALUE *)cSource, "alloc", rb_source_alloc, 0);
-    rb_objc_define_method(*(VALUE *)cSource, "timer", rb_source_timer, 4);
-    rb_objc_define_method(cSource, "initialize", rb_source_init, 4);
-    rb_objc_define_method(cSource, "initialize", rb_raise_init, 0);
-    rb_objc_define_method(cSource, "cancelled?", rb_source_cancelled_p, 0);
-    rb_objc_define_method(cSource, "cancel!", rb_source_cancel, 0);
-    rb_objc_define_method(cSource, "handle", rb_source_get_handle, 0);
-    rb_objc_define_method(cSource, "mask", rb_source_get_mask, 0);
-    rb_objc_define_method(cSource, "data", rb_source_get_data, 0);
-    rb_objc_define_method(cSource, "<<", rb_source_merge, 1);
-
-    rb_source_finalize_super = rb_objc_install_method2((Class)cSource,
-	    "finalize", (IMP)rb_source_finalize);
-
-/*
- * Dispatch::Semaphore provides an efficient mechanism to synchronizes threads
- * via a combination of waiting and signalling.
- * This is especially useful for controlling access to limited resources.
- */
-    cSemaphore = rb_define_class_under(mDispatch, "Semaphore", cObject);
-    rb_objc_define_method(*(VALUE *)cSemaphore, "alloc", rb_semaphore_alloc, 0);
-    rb_objc_define_method(cSemaphore, "initialize", rb_semaphore_init, 1);
-    rb_objc_define_method(cSemaphore, "initialize", rb_raise_init, 0);
-    rb_objc_define_method(cSemaphore, "wait", rb_semaphore_wait, -1);
-    rb_objc_define_method(cSemaphore, "signal", rb_semaphore_signal, 0);
-
-    rb_semaphore_finalize_super = rb_objc_install_method2((Class)cSemaphore,
-	    "finalize", (IMP)rb_semaphore_finalize);
-
-/*
- * Constants for use with
- * dispatch_time(3)[http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man3/dispatch_time.3.html]
- */
-
-    rb_define_const(mDispatch, "TIME_NOW", ULL2NUM(DISPATCH_TIME_NOW));
-    rb_define_const(mDispatch, "TIME_FOREVER", ULL2NUM(DISPATCH_TIME_FOREVER));
-    
-/* Constants for future reference */
-    selClose = sel_registerName("close");
-    assert(selClose != NULL);
-}

Deleted: MacRuby/trunk/gcd.h
===================================================================
--- MacRuby/trunk/gcd.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gcd.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,24 +0,0 @@
-/*
- * MacRuby API for Grand Central Dispatch.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __GCD_H_
-#define __GCD_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <dispatch/dispatch.h>
-
-dispatch_queue_t rb_get_dispatch_queue_object(VALUE queue);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __GCD_H_

Deleted: MacRuby/trunk/gem_prelude.rb
===================================================================
--- MacRuby/trunk/gem_prelude.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gem_prelude.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,351 +0,0 @@
-# depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
-# vim: filetype=ruby
-# THIS FILE WAS AUTOGENERATED, DO NOT EDIT
-
-if defined?(Gem) then
-
-  module Kernel
-
-    def gem(gem_name, *version_requirements)
-      Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
-    end
-
-  end
-
-  module Gem
-
-    ConfigMap = {
-      :BASERUBY => RbConfig::CONFIG["BASERUBY"],
-      :sitedir => RbConfig::CONFIG["sitedir"],
-      :ruby_version => RbConfig::CONFIG["ruby_version"],
-      :libdir => RbConfig::CONFIG["libdir"],
-      :sitelibdir => RbConfig::CONFIG["sitelibdir"],
-      :arch => RbConfig::CONFIG["arch"],
-      :bindir => RbConfig::CONFIG["bindir"],
-      :EXEEXT => RbConfig::CONFIG["EXEEXT"],
-      :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
-      :ruby_install_name => RbConfig::CONFIG["ruby_install_name"]
-    }
-
-    def self.dir
-      @gem_home ||= nil
-      set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
-      @gem_home
-    end
-
-    def self.path
-      @gem_path ||= nil
-      unless @gem_path
-        paths = [ENV['GEM_PATH']]
-        paths << APPLE_GEM_HOME if defined? APPLE_GEM_HOME
-        set_paths(paths.compact.join(File::PATH_SEPARATOR))
-      end
-      @gem_path
-    end
-
-    def self.post_install(&hook)
-      @post_install_hooks << hook
-    end
-
-    def self.post_uninstall(&hook)
-      @post_uninstall_hooks << hook
-    end
-
-    def self.pre_install(&hook)
-      @pre_install_hooks << hook
-    end
-
-    def self.pre_uninstall(&hook)
-      @pre_uninstall_hooks << hook
-    end
-
-    def self.set_home(home)
-      @gem_home = home
-      ensure_gem_subdirectories(@gem_home)
-    end
-
-    def self.set_paths(gpaths)
-      if gpaths
-        @gem_path = gpaths.split(File::PATH_SEPARATOR)
-        @gem_path << Gem.dir
-      else
-        @gem_path = [Gem.dir]
-      end
-      @gem_path.uniq!
-      @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
-    end
-
-    def self.ensure_gem_subdirectories(path)
-    end
-
-  
-    @post_install_hooks   ||= []
-    @post_uninstall_hooks ||= []
-    @pre_uninstall_hooks  ||= []
-    @pre_install_hooks    ||= []
-  
-    ##
-    # An Array of the default sources that come with RubyGems
-  
-    def self.default_sources
-      %w[http://gems.rubyforge.org/]
-    end
-  
-    ##
-    # Default home directory path to be used if an alternate value is not
-    # specified in the environment
-  
-    def self.default_dir
-      if defined? RUBY_FRAMEWORK_VERSION then
-        File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
-                  ConfigMap[:ruby_version]
-      # 1.9.2dev reverted to 1.8 style path
-      elsif RUBY_VERSION > '1.9' and RUBY_VERSION < '1.9.2' then
-        File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
-                  ConfigMap[:ruby_version])
-      else
-        File.join(ConfigMap[:libdir], ruby_engine, 'gems',
-                  ConfigMap[:ruby_version])
-      end
-    end
-  
-    ##
-    # Path for gems in the user's home directory
-  
-    def self.user_dir
-      File.join(Gem.user_home, '.gem', ruby_engine,
-                ConfigMap[:ruby_version])
-    end
-  
-    ##
-    # Default gem load path
-  
-    def self.default_path
-      if File.exist?(Gem.user_home)
-        [user_dir, default_dir]
-      else
-        [default_dir]
-      end
-    end
-  
-    ##
-    # Deduce Ruby's --program-prefix and --program-suffix from its install name
-  
-    def self.default_exec_format
-      exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
-  
-      unless exec_format =~ /%s/ then
-        raise Gem::Exception,
-          "[BUG] invalid exec_format #{exec_format.inspect}, no %s"
-      end
-  
-      exec_format
-    end
-  
-    ##
-    # The default directory for binaries
-  
-    def self.default_bindir
-      if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
-        '/usr/bin'
-      else # generic install
-        ConfigMap[:bindir]
-      end
-    end
-  
-    ##
-    # The default system-wide source info cache directory
-  
-    def self.default_system_source_cache_dir
-      File.join Gem.dir, 'source_cache'
-    end
-  
-    ##
-    # The default user-specific source info cache directory
-  
-    def self.default_user_source_cache_dir
-      File.join Gem.user_home, '.gem', 'source_cache'
-    end
-  
-    ##
-    # A wrapper around RUBY_ENGINE const that may not be defined
-  
-    def self.ruby_engine
-      if defined? RUBY_ENGINE then
-        RUBY_ENGINE
-      else
-        'ruby'
-      end
-    end
-  
-  
-
-    # Methods before this line will be removed when QuickLoader is replaced
-    # with the real RubyGems
-
-    GEM_PRELUDE_METHODS = Gem.methods(false)
-
-    begin
-      verbose, debug = $VERBOSE, $DEBUG
-      $VERBOSE = $DEBUG = nil
-
-      begin
-        require 'rubygems/defaults/operating_system'
-      rescue LoadError
-      end
-
-      if defined?(RUBY_ENGINE) then
-        begin
-          require "rubygems/defaults/#{RUBY_ENGINE}"
-        rescue LoadError
-        end
-      end
-    ensure
-      $VERBOSE, $DEBUG = verbose, debug
-    end
-
-    module QuickLoader
-
-      def self.load_full_rubygems_library
-        class << Gem
-          Gem::GEM_PRELUDE_METHODS.each do |method_name|
-            undef_method method_name
-          end
-        end
-
-        Kernel.module_eval do
-          undef_method :gem if method_defined? :gem
-        end
-
-        $".delete File.join(Gem::ConfigMap[:libdir],
-                            Gem::ConfigMap[:ruby_install_name],
-                            Gem::ConfigMap[:ruby_version], 'rubygems.rb')
-
-        require 'rubygems'
-      end
-
-      GemPaths = {}
-      GemVersions = {}
-
-      def push_gem_version_on_load_path(gem_name, *version_requirements)
-        if version_requirements.empty?
-          unless GemPaths.has_key?(gem_name)
-            raise LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n")
-          end
-
-          # highest version gems already active
-          return false
-        else
-          if version_requirements.length > 1
-            QuickLoader.load_full_rubygems_library
-            return gem(gem_name, *version_requirements)
-          end
-
-          requirement, version = version_requirements[0].split
-          requirement.strip!
-
-          if requirement == ">" || requirement == ">="
-            if (GemVersions[gem_name] <=> Gem.calculate_integers_for_gem_version(version)) >= 0
-              return false
-            end
-          elsif requirement == "~>"
-            loaded_version = GemVersions[gem_name]
-            required_version = Gem.calculate_integers_for_gem_version(version)
-            if loaded_version && (loaded_version[0] == required_version[0])
-              return false
-            end
-          end
-
-          QuickLoader.load_full_rubygems_library
-          gem(gem_name, *version_requirements)
-        end
-      end
-
-      def calculate_integers_for_gem_version(gem_version)
-        numbers = gem_version.split(".").collect {|n| n.to_i}
-        numbers.pop while numbers.last == 0
-        numbers << 0 if numbers.empty?
-        numbers
-      end
-
-      def push_all_highest_version_gems_on_load_path
-        Gem.path.each do |path|
-          gems_directory = File.join(path, "gems")
-          if File.exist?(gems_directory)
-            Dir.entries(gems_directory).each do |gem_directory_name|
-              next if gem_directory_name == "." || gem_directory_name == ".."
-              dash = gem_directory_name.rindex("-")
-              next if dash.nil?
-              gem_name = gem_directory_name[0...dash]
-              current_version = GemVersions[gem_name]
-              new_version = calculate_integers_for_gem_version(gem_directory_name[dash+1..-1])
-              if current_version
-                if (current_version <=> new_version) == -1
-                  GemVersions[gem_name] = new_version
-                  GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
-                end
-              else
-                GemVersions[gem_name] = new_version
-                GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
-              end
-            end
-          end
-        end
-
-        require_paths = []
-
-        GemPaths.each_value do |path|
-          if File.exist?(file = File.join(path, ".require_paths")) then
-            paths = File.read(file).split.map do |require_path|
-              File.join path, require_path
-            end
-
-            require_paths.concat paths
-          else
-            require_paths << file if File.exist?(file = File.join(path, "bin"))
-            require_paths << file if File.exist?(file = File.join(path, "lib"))
-          end
-        end
-
-        # "tag" the first require_path inserted into the $LOAD_PATH to enable
-        # indexing correctly with rubygems proper when it inserts an explicitly
-        # gem version
-        unless require_paths.empty?
-          require_paths.first.instance_variable_set(:@gem_prelude_index, true)
-        end
-        # gem directories must come after -I and ENV['RUBYLIB']
-        $:[$:.index(ConfigMap[:sitelibdir]),0] = require_paths
-      end
-
-      def const_missing(constant)
-        QuickLoader.load_full_rubygems_library
-        if Gem.const_defined?(constant)
-          Gem.const_get(constant)
-        else
-          super
-        end
-      end
-
-      def method_missing(method, *args, &block)
-        QuickLoader.load_full_rubygems_library
-        super unless Gem.respond_to?(method)
-        Gem.send(method, *args, &block)
-      end
-    end
-
-    extend QuickLoader
-
-  end
-
-  begin
-    Gem.push_all_highest_version_gems_on_load_path
-    $" << File.join(Gem::ConfigMap[:libdir], Gem::ConfigMap[:ruby_install_name],
-                    Gem::ConfigMap[:ruby_version], "rubygems.rb")
-  rescue Exception => e
-    puts "Error loading gem paths on load path in gem_prelude"
-    puts e
-    puts e.backtrace.join("\n")
-  end
-
-end
-

Deleted: MacRuby/trunk/gen_bs_struct_readers.rb
===================================================================
--- MacRuby/trunk/gen_bs_struct_readers.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/gen_bs_struct_readers.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,19 +0,0 @@
-MAX_READERS = 128
-
-puts "// This file was generated by #{__FILE__}, do not modify it manually."
-
-MAX_READERS.times do |i|
-    puts <<EOS
-static VALUE rb_vm_struct_reader_#{i} (VALUE self, SEL sel) {
-    VALUE *data;
-    Data_Get_Struct(self, VALUE, data);
-    return data[#{i}];
-}
-EOS
-end
-
-puts <<EOS
-#define BS_STRUCT_MAX_FIELDS #{MAX_READERS}
-typedef VALUE rb_vm_struct_reader_t(VALUE, SEL);
-static rb_vm_struct_reader_t *struct_readers[] = { #{(0..(MAX_READERS-1)).to_a.map { |x| 'rb_vm_struct_reader_' + x.to_s }.join(', ') } };
-EOS

Deleted: MacRuby/trunk/golf_prelude.rb
===================================================================
--- MacRuby/trunk/golf_prelude.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/golf_prelude.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,104 +0,0 @@
-class Object
-  @@golf_hash = {}
-  def method_missing m, *a, &b
-    t = @@golf_hash[ [m,self.class] ] ||= matching_methods(m)[0]
-    t ? __send__(t, *a, &b) : super
-  end
-
-  def matching_methods(s='', m=callable_methods)
-    r=/^#{s.to_s.gsub(/./){"(.*?)"+Regexp.escape($&)}}/
-    m.grep(r).sort_by do |i|
-      i.to_s.match(r).captures.map(&:size)<<i
-    end
-  end
-
-  def self.const_missing c
-    t = @@golf_hash[ [c,self.class] ] ||= matching_methods(c,constants)[0]
-    t and return const_get(t)
-    raise NameError, "uninitialized constant #{c}", caller(1)
-  end
-
-  def shortest_abbreviation(s='', m=callable_methods)
-    s=s.to_s
-    our_case = (?A..?Z)===s[0]
-    if m.index(s.to_sym)
-      1.upto(s.size){|z|s.scan(/./).combination(z).map{|trial|
-        next unless ((?A..?Z)===trial[0]) == our_case
-        trial*=''
-        return trial if matching_methods(trial,m)[0].to_s==s
-      }}
-    else
-      nil
-    end
-  end
-
-  def callable_methods
-    self.class == Object ? methods + private_methods : methods
-  end
-
-  private
-
-  def h(a='H', b='w', c='!')
-    puts "#{a}ello, #{b}orld#{c}"
-  end
-
-  alias say puts
-
-  def do_while
-    0 while yield
-  end
-
-  def do_until
-    0 until yield
-  end
-end
-
-class Array
-  alias old_to_s to_s
-  alias to_s join
-end
-
-class FalseClass
-  alias old_to_s to_s
-  def to_s
-    ""
-  end
-end
-
-class Integer
-  alias each times
-  include Enumerable
-end
-
-class String
-  alias / split
-
-  def to_a
-    split('')
-  end
-
-  (Array.instance_methods-instance_methods-[:to_ary,:transpose,:flatten,:flatten!,:compact,:compact!,:assoc,:rassoc]).each{|meth|
-    eval"def #{meth}(*args, &block)
-      a=to_a
-      result = a.#{meth}(*args, &block)
-      replace(a.join)
-      if result.class == Array
-        Integer===result[0] ? result.pack('c*') : result.join
-      elsif result.class == Enumerable::Enumerator
-        result.map(&:join).to_enum
-      else
-        result
-      end
-    end"
-  }
-end
-
-class Enumerable::Enumerator
-  alias old_to_s to_s
-  (Array.instance_methods-instance_methods-[:replace]+[:to_s]).each{|meth|
-    eval"def #{meth}(*args, &block)
-      to_a.#{meth}(*args, &block)
-    end"
-  }
-  alias inspect old_to_s
-end

Deleted: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/hash.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1926 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's hash.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "ruby/signal.h"
-#include "ruby/node.h"
-#include "id.h"
-#include "objc.h"
-#include "vm.h"
-#include "hash.h"
-#include "array.h"
-#include "class.h"
-
-static VALUE rhash_try_convert(VALUE, SEL, VALUE);
-
-VALUE
-rb_hash_freeze(VALUE hash)
-{
-    return rb_obj_freeze(hash);
-}
-
-VALUE rb_cRubyHash;
-
-static ID id_yield;
-
-static SEL selFlattenBang = 0;
-static SEL selDefault = 0;
-static SEL selHash = 0;
-
-unsigned long
-rb_hash_code(VALUE obj)
-{
-    switch (TYPE(obj)) {
-	case T_FIXNUM:
-	case T_FLOAT:
-	case T_SYMBOL:
-	case T_NIL:
-	case T_FALSE:
-	case T_TRUE:
-	    return (unsigned long)obj;
-
-	case T_STRING:
-	    return rb_str_hash(obj);
-
-	case T_ARRAY:
-	    return rb_ary_hash(obj);
-    }
-
-    VALUE v = rb_vm_call(obj, selHash, 0, NULL);
-retry:
-    switch (TYPE(v)) {
-	case T_FIXNUM:
-	    return FIX2LONG(v);
-	case T_BIGNUM:
-	    return ((unsigned long *)(RBIGNUM_DIGITS(v)))[0];
-	default:
-	    v = rb_to_int(v);
-	    goto retry;
-    }
-}
-
-VALUE
-rb_hash(VALUE obj)
-{
-    return LONG2NUM(rb_hash_code(obj));
-}
-
-typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
-
-struct foreach_safe_arg {
-    st_foreach_func *func;
-    st_data_t arg;
-};
-
-static int
-foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg)
-{
-    if (key == Qundef) {
-	return ST_CONTINUE;
-    }
-    const int status = (*arg->func)(key, value, arg->arg);
-    if (status == ST_CONTINUE) {
-	return ST_CHECK;
-    }
-    return status;
-}
-
-void
-st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a)
-{
-    struct foreach_safe_arg arg;
-
-    arg.func = (st_foreach_func *)func;
-    arg.arg = a;
-    st_foreach(table, foreach_safe_i, (st_data_t)&arg);
-}
-
-static int
-rb_any_cmp(VALUE a, VALUE b)
-{
-    if (a == b) {
-	return 0;
-    }
-    return !rb_eql(a, b);
-}
-
-static int
-rb_any_hash(VALUE a)
-{
-    return (int)rb_hash_code(a);
-}
-
-static const struct st_hash_type objhash = {
-    rb_any_cmp,
-    rb_any_hash,
-};
-
-static const struct st_hash_type identhash = {
-    st_numcmp,
-    st_numhash,
-};
-
-static VALUE
-rhash_alloc(VALUE klass, SEL sel)
-{
-    assert(klass != 0);
-    assert(rb_klass_is_rhash(klass));
-
-    NEWOBJ(hash, rb_hash_t);
-    hash->basic.flags = 0;
-    hash->basic.klass = klass;
-    GC_WB(&hash->tbl, st_init_table(&objhash));
-    hash->ifnone = Qnil;
-    hash->has_proc_default = false;
-    return (VALUE)hash;
-}
-
-static VALUE
-rhash_copy(VALUE rcv, VALUE klass)
-{
-    NEWOBJ(dup, rb_hash_t);
-    dup->basic.flags = 0;
-    dup->basic.klass = klass;
-    GC_WB(&dup->tbl, st_copy(RHASH(rcv)->tbl));
-    GC_WB(&dup->ifnone, RHASH(rcv)->ifnone);
-    dup->has_proc_default = RHASH(rcv)->has_proc_default;
-    return (VALUE)dup;
-}
-
-VALUE
-rhash_dup(VALUE rcv, SEL sel)
-{
-    VALUE klass = CLASS_OF(rcv);
-    while (RCLASS_SINGLETON(klass)) {
-	klass = RCLASS_SUPER(klass);
-    }
-    assert(rb_klass_is_rhash(klass));
-
-    VALUE dup = rhash_copy(rcv, klass);
-
-    OBJ_INFECT(dup, rcv);
-    return dup;
-}
-
-static VALUE
-rhash_clone(VALUE rcv, SEL sel)
-{
-    VALUE clone = rhash_copy(rcv, CLASS_OF(rcv));
-
-    OBJ_INFECT(clone, rcv);
-    if (OBJ_FROZEN(rcv)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-VALUE
-rb_hash_new(void)
-{
-    return rhash_alloc(rb_cRubyHash, 0);
-}
-
-VALUE
-rb_hash_new_fast(int argc, ...)
-{
-    assert(argc % 2 == 0);
-
-    VALUE hash = rhash_alloc(rb_cRubyHash, 0);
-
-    va_list ar;
-    va_start(ar, argc);
-    for (int i = 0; i < argc; i += 2) {
-	VALUE key = va_arg(ar, VALUE);
-	VALUE val = va_arg(ar, VALUE);
-	rhash_aset(hash, 0, key, val);
-    }
-    va_end(ar);
-
-    return hash;
-}
-
-struct st_table *
-rb_hash_tbl(VALUE hash)
-{
-    if (IS_RHASH(hash)) {
-	return RHASH(hash)->tbl;
-    }
-    rb_raise(rb_eRuntimeError,
-	    "rb_hash_tbl() won't work on pure NSDictionaries");
-}
-
-/*
- *  call-seq:
- *     Hash.new                          => hash
- *     Hash.new(obj)                     => aHash
- *     Hash.new {|hash, key| block }     => aHash
- *
- *  Returns a new, empty hash. If this hash is subsequently accessed by
- *  a key that doesn't correspond to a hash entry, the value returned
- *  depends on the style of <code>new</code> used to create the hash. In
- *  the first form, the access returns <code>nil</code>. If
- *  <i>obj</i> is specified, this single object will be used for
- *  all <em>default values</em>. If a block is specified, it will be
- *  called with the hash object and the key, and should return the
- *  default value. It is the block's responsibility to store the value
- *  in the hash if required.
- *
- *     h = Hash.new("Go Fish")
- *     h["a"] = 100
- *     h["b"] = 200
- *     h["a"]           #=> 100
- *     h["c"]           #=> "Go Fish"
- *     # The following alters the single default object
- *     h["c"].upcase!   #=> "GO FISH"
- *     h["d"]           #=> "GO FISH"
- *     h.keys           #=> ["a", "b"]
- *
- *     # While this creates a new default object each time
- *     h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
- *     h["c"]           #=> "Go Fish: c"
- *     h["c"].upcase!   #=> "GO FISH: C"
- *     h["d"]           #=> "Go Fish: d"
- *     h.keys           #=> ["c", "d"]
- *
- */
-
-static VALUE
-rhash_initialize(VALUE hash, SEL sel, int argc, const VALUE *argv)
-{
-    rhash_modify(hash);
-    if (rb_block_given_p()) {
-	if (argc > 0) {
-	    rb_raise(rb_eArgError, "wrong number of arguments");
-	}
-	GC_WB(&RHASH(hash)->ifnone, rb_block_proc());
-	RHASH(hash)->has_proc_default = true;
-    }
-    else {
-	VALUE ifnone;
-	rb_scan_args(argc, argv, "01", &ifnone);
-	if (ifnone != Qnil) {
-	    GC_WB(&RHASH(hash)->ifnone, ifnone);
-	}
-    }
-    return hash;
-}
-
-VALUE
-rb_hash_new2(int argc, const VALUE *argv)
-{
-    VALUE h = rhash_alloc(rb_cRubyHash, 0);
-    rhash_initialize(h, 0, argc, argv);
-    return h;
-}
-
-/*
- *  call-seq:
- *     Hash.try_convert(obj) -> hash or nil
- *
- *  Try to convert <i>obj</i> into a hash, using to_hash method.
- *  Returns converted hash or nil if <i>obj</i> cannot be converted
- *  for any reason.
- *
- *     Hash.try_convert({1=>2})   # => {1=>2}
- *     Hash.try_convert("1=>2")   # => nil
- */
-
-static VALUE
-rhash_try_convert(VALUE dummy, SEL sel, VALUE hash)
-{
-    return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
-}
-
-/*
- *  call-seq:
- *     Hash[ [key =>|, value]* ]   => hash
- *
- *  Creates a new hash populated with the given objects. Equivalent to
- *  the literal <code>{ <i>key</i>, <i>value</i>, ... }</code>. Keys and
- *  values occur in pairs, so there must be an even number of arguments.
- *
- *     Hash["a", 100, "b", 200]       #=> {"a"=>100, "b"=>200}
- *     Hash["a" => 100, "b" => 200]   #=> {"a"=>100, "b"=>200}
- *     { "a" => 100, "b" => 200 }     #=> {"a"=>100, "b"=>200}
- */
-
-static VALUE
-rhash_create(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 1) {
-	VALUE tmp = rhash_try_convert(Qnil, 0, argv[0]);
-	if (!NIL_P(tmp)) {
-	    VALUE hash = rhash_alloc(klass, 0);
-	    if (IS_RHASH(tmp)) {
-		GC_WB(&RHASH(hash)->tbl, st_copy(RHASH(tmp)->tbl));
-	    }
-	    else {
-		VALUE keys = rb_hash_keys(tmp);
-		for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) {
-		    VALUE key = RARRAY_AT(keys, i);
-		    VALUE val = rb_hash_lookup(tmp, key);
-		    rhash_aset(hash, 0, key, val);  
-		}
-	    }
-	    return hash;
-	}
-
-	tmp = rb_check_array_type(argv[0]);
-	if (!NIL_P(tmp)) {
-	    VALUE hash = rhash_alloc(klass, 0);
-	    for (int i = 0; i < RARRAY_LEN(tmp); ++i) {
-		VALUE v = rb_check_array_type(RARRAY_AT(tmp, i));
-		if (NIL_P(v)) {
-		    continue;
-		}
-		const long len = RARRAY_LEN(v);
-		if (len < 1 || 2 < len) {
-		    continue;
-		}
-		rhash_aset(hash, 0, RARRAY_AT(v, 0), RARRAY_AT(v, 1));
-	    }
-	    return hash;
-	}
-    }
-    if (argc % 2 != 0) {
-	rb_raise(rb_eArgError, "odd number of arguments for Hash");
-    }
-
-    VALUE hash = rhash_alloc(klass, 0);
-    for (int i = 0; i < argc; i += 2) {
-        rb_hash_aset(hash, argv[i], argv[i + 1]);
-    }
-
-    return hash;
-}
-
-static VALUE
-to_hash(VALUE hash)
-{
-    return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
-}
-
-/*
- *  call-seq:
- *     hsh.rehash -> hsh
- *
- *  Rebuilds the hash based on the current hash values for each key. If
- *  values of key objects have changed since they were inserted, this
- *  method will reindex <i>hsh</i>. If <code>Hash#rehash</code> is
- *  called while an iterator is traversing the hash, an
- *  <code>RuntimeError</code> will be raised in the iterator.
- *
- *     a = [ "a", "b" ]
- *     c = [ "c", "d" ]
- *     h = { a => 100, c => 300 }
- *     h[a]       #=> 100
- *     a[0] = "z"
- *     h[a]       #=> nil
- *     h.rehash   #=> {["z", "b"]=>100, ["c", "d"]=>300}
- *     h[a]       #=> 100
- */
-
-static int
-rhash_rehash_i(VALUE key, VALUE value, VALUE arg)
-{
-    st_table *tbl = (st_table *)arg;
-    if (key != Qundef) {
-	st_insert(tbl, key, value);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_rehash(VALUE hash, SEL sel)
-{
-    rhash_modify(hash);
-    st_table *tbl = st_init_table_with_size(RHASH(hash)->tbl->type,
-	    RHASH(hash)->tbl->num_entries);
-    rb_hash_foreach(hash, rhash_rehash_i, (VALUE)tbl);
-    //st_free_table(RHASH(hash)->tbl);
-    GC_WB(&RHASH(hash)->tbl, tbl);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh[key]    =>  value
- *
- *  Element Reference---Retrieves the <i>value</i> object corresponding
- *  to the <i>key</i> object. If not found, returns the a default value (see
- *  <code>Hash::new</code> for details).
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h["a"]   #=> 100
- *     h["c"]   #=> nil
- *
- */
-
-static inline VALUE
-rhash_call_default(VALUE hash, VALUE key)
-{
-    return rb_vm_call(hash, selDefault, 1, &key);
-}
-
-VALUE
-rhash_aref(VALUE hash, SEL sel, VALUE key)
-{
-    VALUE val = rhash_lookup(hash, key);
-    if (val == Qundef) {
-	if (*(VALUE *)hash == rb_cRubyHash
-		&& RHASH(hash)->ifnone == Qnil) {
-	    return Qnil;
-	}
-	return rhash_call_default(hash, key);
-    }
-    return val;
-}
-
-/*
- *  call-seq:
- *     hsh.fetch(key [, default] )       => obj
- *     hsh.fetch(key) {| key | block }   => obj
- *
- *  Returns a value from the hash for the given key. If the key can't be
- *  found, there are several options: With no other arguments, it will
- *  raise an <code>KeyError</code> exception; if <i>default</i> is
- *  given, then that will be returned; if the optional code block is
- *  specified, then that will be run and its result returned.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.fetch("a")                            #=> 100
- *     h.fetch("z", "go fish")                 #=> "go fish"
- *     h.fetch("z") { |el| "go fish, #{el}"}   #=> "go fish, z"
- *
- *  The following example shows that an exception is raised if the key
- *  is not found and a default value is not supplied.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.fetch("z")
- *
- *  <em>produces:</em>
- *
- *     prog.rb:2:in `fetch': key not found (KeyError)
- *      from prog.rb:2
- *
- */
-
-static VALUE
-rhash_fetch(VALUE hash, SEL sel, int argc, VALUE *argv)
-{
-    VALUE key, if_none;
-    rb_scan_args(argc, argv, "11", &key, &if_none);
-
-    const bool block_given = rb_block_given_p();
-    if (block_given && argc == 2) {
-	rb_warn("block supersedes default value argument");
-    }
-
-    VALUE v = rhash_lookup(hash, key);
-    if (v != Qundef) {
-	return v;
-    }
-    if (block_given) {
-	return rb_yield(key);
-    }
-    if (argc == 1) {
-	rb_raise(rb_eKeyError, "key not found");
-    }
-    return if_none;
-}
-
-/*
- *  call-seq:
- *     hsh.default(key=nil)   => obj
- *
- *  Returns the default value, the value that would be returned by
- *  <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
- *  See also <code>Hash::new</code> and <code>Hash#default=</code>.
- *
- *     h = Hash.new                            #=> {}
- *     h.default                               #=> nil
- *     h.default(2)                            #=> nil
- *
- *     h = Hash.new("cat")                     #=> {}
- *     h.default                               #=> "cat"
- *     h.default(2)                            #=> "cat"
- *
- *     h = Hash.new {|h,k| h[k] = k.to_i*10}   #=> {}
- *     h.default                               #=> nil
- *     h.default(2)                            #=> 20
- */
-
-static VALUE
-rhash_default(VALUE hash, SEL sel, int argc, VALUE *argv)
-{
-    VALUE key;
-    rb_scan_args(argc, argv, "01", &key);
-
-    if (RHASH(hash)->has_proc_default) {
-	if (argc == 0) {
-	    return Qnil;
-	}
-	return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
-    }
-    return RHASH(hash)->ifnone;
-}
-
-/*
- *  call-seq:
- *     hsh.default = obj     => hsh
- *
- *  Sets the default value, the value returned for a key that does not
- *  exist in the hash. It is not possible to set the a default to a
- *  <code>Proc</code> that will be executed on each key lookup.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.default = "Go fish"
- *     h["a"]     #=> 100
- *     h["z"]     #=> "Go fish"
- *     # This doesn't do what you might hope...
- *     h.default = proc do |hash, key|
- *       hash[key] = key + key
- *     end
- *     h[2]       #=> #<Proc:0x401b3948 at -:6>
- *     h["cat"]   #=> #<Proc:0x401b3948 at -:6>
- */
-
-VALUE
-rhash_set_default(VALUE hash, SEL sel, VALUE ifnone)
-{
-    rhash_modify(hash);
-    GC_WB(&RHASH(hash)->ifnone, ifnone);
-    RHASH(hash)->has_proc_default = false;
-    return ifnone;
-}
-
-/*
- *  call-seq:
- *     hsh.default_proc -> anObject
- *
- *  If <code>Hash::new</code> was invoked with a block, return that
- *  block, otherwise return <code>nil</code>.
- *
- *     h = Hash.new {|h,k| h[k] = k*k }   #=> {}
- *     p = h.default_proc                 #=> #<Proc:0x401b3d08 at -:1>
- *     a = []                             #=> []
- *     p.call(a, 2)
- *     a                                  #=> [nil, nil, 4]
- */
-
-static VALUE
-rhash_default_proc(VALUE hash, SEL sel)
-{
-    return RHASH(hash)->has_proc_default ? RHASH(hash)->ifnone : Qnil;
-}
-
-/*
- *  call-seq:
- *     hsh.default_proc = proc_obj     => proc_obj
- *
- *  Sets the default proc to be executed on each key lookup.
- *
- *     h.default_proc = proc do |hash, key|
- *       hash[key] = key + key
- *     end
- *     h[2]       #=> 4
- *     h["cat"]   #=> "catcat"
- */
-
-static void
-default_proc_arity_check(VALUE proc)
-{
-    const int arity = rb_proc_arity(proc);
-    if (arity != 0 && arity != 2) {
-	rb_raise(rb_eTypeError, "expected Proc with 2 arguments (but got %d)",
-		arity);
-    }
-}
-
-static VALUE
-rhash_set_default_proc(VALUE hash, SEL sel, VALUE proc)
-{
-    rhash_modify(hash);
-    VALUE tmp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
-    if (NIL_P(tmp)) {
-        rb_raise(rb_eTypeError,
-		"wrong default_proc type %s (expected Proc)",
-		rb_obj_classname(proc));
-    }
-    proc = tmp;
-    default_proc_arity_check(proc);
-    GC_WB(&RHASH(hash)->ifnone, proc);
-    RHASH(hash)->has_proc_default = true;
-    return proc;
-}
-
-/*
- *  call-seq:
- *     hsh.key(value)    => key
- *
- *  Returns the key for a given value. If not found, returns <code>nil</code>.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.key(200)   #=> "b"
- *     h.key(999)   #=> nil
- *
- */
-
-static int
-key_i(VALUE key, VALUE value, VALUE *args)
-{
-    if (rb_equal(value, args[0])) {
-	args[1] = key;
-	return ST_STOP;
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_key(VALUE hash, SEL sel, VALUE value)
-{
-    VALUE args[2] = {value, Qnil};
-    rhash_foreach(hash, key_i, (st_data_t)args);
-    return args[1];
-}
-
-/* :nodoc: */
-static VALUE
-rhash_index(VALUE hash, SEL sel, VALUE value)
-{
-    rb_warn("Hash#index is deprecated; use Hash#key");
-    return rhash_key(hash, 0, value);
-}
-
-/*
- *  call-seq:
- *     hsh.delete(key)                   => value
- *     hsh.delete(key) {| key | block }  => value
- *
- *  Deletes and returns the value from <i>hsh</i> whose key is
- *  equal to <i>key</i>. If the key is not found, returns nil.
- *  If the optional code block is given and the
- *  key is not found, pass in the key and return the result of
- *  <i>block</i>.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.delete("a")                              #=> 100
- *     h.delete("z")                              #=> nil
- *     h.delete("z") { |el| "#{el} not found" }   #=> "z not found"
- *
- */
-
-static VALUE
-rhash_delete(VALUE hash, SEL sel, VALUE key)
-{
-    rhash_modify(hash);
-    VALUE val = rhash_delete_key(hash, key);
-    if (val != Qundef) {
-	return val;
-    }
-    if (rb_block_given_p()) {
-	return rb_yield(key);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     hsh.shift -> anArray or obj
- *
- *  Removes a key-value pair from <i>hsh</i> and returns it as the
- *  two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
- *  the hash's default value if the hash is empty.
- *
- *     h = { 1 => "a", 2 => "b", 3 => "c" }
- *     h.shift   #=> [1, "a"]
- *     h         #=> {2=>"b", 3=>"c"}
- */
-
-static int
-shift_i(VALUE key, VALUE value, VALUE arg)
-{
-    VALUE *ret = (VALUE *)arg;
-    if (key != Qundef) {
-	ret[0] = key;
-	ret[1] = value;
-	return ST_STOP;
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_shift(VALUE hash, SEL sel)
-{
-    VALUE args[2] = {0, 0};
-    rhash_modify(hash);
-    rhash_foreach(hash, shift_i, (st_data_t)args);
-    if (args[0] != 0 && args[1] != 0) {
-	rhash_delete_key(hash, args[0]);
-	return rb_assoc_new(args[0], args[1]);
-    }
-
-    if (RHASH(hash)->ifnone != Qnil) {
-	if (RHASH(hash)->has_proc_default) {
-	    return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash,
-		    Qnil);
-	}
-	return RHASH(hash)->ifnone;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     hsh.delete_if {| key, value | block }  -> hsh
- *
- *  Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
- *  evaluates to <code>true</code>.
- *
- *     h = { "a" => 100, "b" => 200, "c" => 300 }
- *     h.delete_if {|key, value| key >= "b" }   #=> {"a"=>100}
- *
- */
-
-static int
-delete_if_i(VALUE key, VALUE value, VALUE ary)
-{
-    if (key != Qundef) {
-	const bool ok = RTEST(rb_yield_values(2, key, value));
-	ST_STOP_IF_BROKEN();
-	if (ok) {
-	    rb_ary_push(ary, key);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_delete_if(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_modify(hash);
-    VALUE ary = rb_ary_new();
-    rhash_foreach(hash, delete_if_i, ary);
-    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	VALUE key = RARRAY_AT(ary, i);
-	rhash_delete_key(hash, key);	
-    }
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.reject! {| key, value | block }  -> hsh or nil
- *
- *  Equivalent to <code>Hash#delete_if</code>, but returns
- *  <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rhash_reject_bang(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    const long n = rhash_len(hash);
-    rhash_delete_if(hash, 0);
-    return n == rhash_len(hash) ? Qnil : hash;
-}
-
-/*
- *  call-seq:
- *     hsh.reject {| key, value | block }  -> a_hash
- *
- *  Same as <code>Hash#delete_if</code>, but works on (and returns) a
- *  copy of the <i>hsh</i>. Equivalent to
- *  <code><i>hsh</i>.dup.delete_if</code>.
- *
- */
-
-static VALUE
-rhash_reject(VALUE hash, SEL sel)
-{
-    return rhash_delete_if(rhash_dup(hash, 0), 0);
-}
-
-/*
- * call-seq:
- *   hsh.values_at(key, ...)   => array
- *
- * Return an array containing the values associated with the given keys.
- * Also see <code>Hash.select</code>.
- *
- *   h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
- *   h.values_at("cow", "cat")  #=> ["bovine", "feline"]
- */
-
-static VALUE
-rhash_values_at(VALUE hash, SEL sel, int argc, VALUE *argv)
-{
-    VALUE result = rb_ary_new2(argc);
-    for (int i = 0; i < argc; i++) {
-	rb_ary_push(result, rhash_aref(hash, 0, argv[i]));
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     hsh.select {|key, value| block}   => a_hash
- *
- *  Returns a new hash consisting of entries which the block returns true.
- *
- *     h = { "a" => 100, "b" => 200, "c" => 300 }
- *     h.select {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}
- *     h.select {|k,v| v < 200}  #=> {"a" => 100}
- */
-
-static int
-select_i(VALUE key, VALUE value, VALUE result)
-{
-    if (key != Qundef) {
-	const bool ok = RTEST(rb_yield_values(2, key, value));
-	ST_STOP_IF_BROKEN();
-	if (ok) {
-	    rb_hash_aset(result, key, value);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_select(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    VALUE result = rb_hash_new();
-    rhash_foreach(hash, select_i, result);
-    return result;
-}
-
-static int
-keep_if_i(VALUE key, VALUE value, VALUE hash)
-{
-    if (key != Qundef) {
-	const bool ok = RTEST(rb_yield_values(2, key, value));
-	ST_STOP_IF_BROKEN();
-	if (!ok) {
-	    return ST_DELETE;
-	}
-    }
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     hsh.select! {| key, value | block }  -> hsh or nil
- *     hsh.select!                          -> an_enumerator
- *
- *  Equivalent to <code>Hash#keep_if</code>, but returns
- *  <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rhash_select_bang(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_modify(hash);
-    const long n = rhash_len(hash);
-    rb_hash_foreach(hash, keep_if_i, hash);
-    return n == rhash_len(hash) ? Qnil : hash;
-}
-
-/*
- *  call-seq:
- *     hsh.keep_if {| key, value | block }  -> hsh
- *     hsh.keep_if                          -> an_enumerator
- *
- *  Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
- *  evaluates to false.
- *
- *  If no block is given, an enumerator is returned instead.
- *
- */
-
-VALUE
-rhash_keep_if(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_modify(hash);
-    rhash_foreach(hash, keep_if_i, hash);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.clear -> hsh
- *
- *  Removes all key-value pairs from <i>hsh</i>.
- *
- *     h = { "a" => 100, "b" => 200 }   #=> {"a"=>100, "b"=>200}
- *     h.clear                          #=> {}
- *
- */
-
-static VALUE
-rhash_clear(VALUE hash, SEL sel)
-{
-    rhash_modify(hash);
-    st_clear(RHASH(hash)->tbl);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh[key] = value        => value
- *     hsh.store(key, value)   => value
- *
- *  Element Assignment---Associates the value given by
- *  <i>value</i> with the key given by <i>key</i>.
- *  <i>key</i> should not have its value changed while it is in
- *  use as a key (a <code>String</code> passed as a key will be
- *  duplicated and frozen).
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h["a"] = 9
- *     h["c"] = 4
- *     h   #=> {"a"=>9, "b"=>200, "c"=>4}
- *
- */
-
-VALUE
-rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val)
-{
-    rhash_modify(hash);
-    if (TYPE(key) == T_STRING && !OBJ_FROZEN(key)) {
-        key = rb_str_dup(key);
-        OBJ_FREEZE(key);
-    }
-    st_insert(RHASH(hash)->tbl, key, val);
-    return val;
-}
-
-static int
-replace_i(VALUE key, VALUE val, VALUE hash)
-{
-    if (key != Qundef) {
-	rb_hash_aset(hash, key, val);
-    }
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     hsh.replace(other_hash) -> hsh
- *
- *  Replaces the contents of <i>hsh</i> with the contents of
- *  <i>other_hash</i>.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.replace({ "c" => 300, "d" => 400 })   #=> {"c"=>300, "d"=>400}
- *
- */
-
-static VALUE
-rhash_replace(VALUE hash, SEL sel, VALUE hash2)
-{
-    rhash_modify(hash);
-    hash2 = to_hash(hash2);
-    if (hash == hash2) {
-	return hash;
-    }
-
-    rhash_clear(hash, 0);
-    rb_hash_foreach(hash2, replace_i, hash);
-
-    if (IS_RHASH(hash2)) {
-	GC_WB(&RHASH(hash)->ifnone, RHASH(hash2)->ifnone);
-	RHASH(hash)->has_proc_default = RHASH(hash2)->has_proc_default;
-    }
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.length    =>  fixnum
- *     hsh.size      =>  fixnum
- *
- *  Returns the number of key-value pairs in the hash.
- *
- *     h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
- *     h.length        #=> 4
- *     h.delete("a")   #=> 200
- *     h.length        #=> 3
- */
-
-static VALUE
-rhash_size(VALUE hash, SEL sel)
-{
-    return LONG2NUM(rhash_len(hash));
-}
-
-/*
- *  call-seq:
- *     hsh.empty?    => true or false
- *
- *  Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
- *
- *     {}.empty?   #=> true
- *
- */
-
-static VALUE
-rhash_empty(VALUE hash, SEL sel)
-{
-    return rhash_len(hash) == 0 ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     hsh.each_value {| value | block } -> hsh
- *
- *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the
- *  value as a parameter.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.each_value {|value| puts value }
- *
- *  <em>produces:</em>
- *
- *     100
- *     200
- */
-
-static int
-each_value_i(VALUE key, VALUE value)
-{
-    if (key != Qundef) {
-	rb_yield(value);
-	ST_STOP_IF_BROKEN();
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_each_value(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_foreach(hash, each_value_i, 0);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.each_key {| key | block } -> hsh
- *
- *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
- *  as a parameter.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.each_key {|key| puts key }
- *
- *  <em>produces:</em>
- *
- *     a
- *     b
- */
-
-static int
-each_key_i(VALUE key, VALUE value)
-{
-    if (key != Qundef) {
-	rb_yield(key);
-	ST_STOP_IF_BROKEN();
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_each_key(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_foreach(hash, each_key_i, 0);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.each {| key, value | block } -> hsh
- *     hsh.each_pair {| key, value | block } -> hsh
- *
- *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the key-value
- *  pair as parameters.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.each {|key, value| puts "#{key} is #{value}" }
- *
- *  <em>produces:</em>
- *
- *     a is 100
- *     b is 200
- *
- */
-
-static int
-each_pair_i(VALUE key, VALUE value)
-{
-    if (key != Qundef) {
-	rb_yield(rb_assoc_new(key, value));
-	ST_STOP_IF_BROKEN();
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_each_pair(VALUE hash, SEL sel)
-{
-    RETURN_ENUMERATOR(hash, 0, 0);
-    rhash_foreach(hash, each_pair_i, 0);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.to_a -> array
- *
- *  Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
- *  value</i> <code>]</code> arrays.
- *
- *     h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
- *     h.to_a   #=> [["c", 300], ["a", 100], ["d", 400]]
- */
-
-static int
-to_a_i(VALUE key, VALUE value, VALUE ary)
-{
-    if (key != Qundef) {
-	rb_ary_push(ary, rb_assoc_new(key, value));
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_to_a(VALUE hash, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    rhash_foreach(hash, to_a_i, ary);
-    OBJ_INFECT(ary, hash);
-
-    return ary;
-}
-
-/*
- * call-seq:
- *   hsh.to_s   => string
- *   hsh.inspect  => string
- *
- * Return the contents of this hash as a string.
- *
- *     h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
- *     h.to_s   #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"
- */
-
-static int
-inspect_i(VALUE key, VALUE value, VALUE str)
-{
-    if (key != Qundef) {
-	if (RSTRING_LEN(str) > 1) {
-	    rb_str_cat2(str, ", ");
-	}
-	VALUE str2 = rb_inspect(key);
-	rb_str_buf_append(str, str2);
-	rb_str_buf_cat2(str, "=>");
-	str2 = rb_inspect(value);
-	rb_str_buf_append(str, str2);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-inspect_hash(VALUE hash, VALUE dummy, int recur)
-{
-    if (recur) {
-	return rb_usascii_str_new2("{...}");
-    }
-    VALUE str = rb_str_buf_new2("{");
-    rhash_foreach(hash, inspect_i, str);
-    rb_str_buf_cat2(str, "}");
-    OBJ_INFECT(str, hash);
-    return str;
-}
-
-static VALUE
-rhash_inspect(VALUE hash, SEL sel)
-{
-    if (RHASH_EMPTY_P(hash)) {
-	return rb_usascii_str_new2("{}");
-    }
-    return rb_exec_recursive(inspect_hash, hash, 0);
-}
-
-/*
- * call-seq:
- *    hsh.to_hash   => hsh
- *
- * Returns <i>self</i>.
- */
-
-static VALUE
-rhash_to_hash(VALUE hash, SEL sel)
-{
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.keys    => array
- *
- *  Returns a new array populated with the keys from this hash. See also
- *  <code>Hash#values</code>.
- *
- *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
- *     h.keys   #=> ["a", "b", "c", "d"]
- *
- */
-
-static int
-keys_i(VALUE key, VALUE value, VALUE ary)
-{
-    if (key != Qundef) {
-	rb_ary_push(ary, key);
-    }
-    return ST_CONTINUE;
-}
-
-VALUE
-rhash_keys(VALUE hash, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    rhash_foreach(hash, keys_i, ary);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     hsh.values    => array
- *
- *  Returns a new array populated with the values from <i>hsh</i>. See
- *  also <code>Hash#keys</code>.
- *
- *     h = { "a" => 100, "b" => 200, "c" => 300 }
- *     h.values   #=> [100, 200, 300]
- *
- */
-
-static int
-values_i(VALUE key, VALUE value, VALUE ary)
-{
-    if (key != Qundef) {
-	rb_ary_push(ary, value);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_values(VALUE hash, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    rhash_foreach(hash, values_i, ary);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     hsh.has_key?(key)    => true or false
- *     hsh.include?(key)    => true or false
- *     hsh.key?(key)        => true or false
- *     hsh.member?(key)     => true or false
- *
- *  Returns <code>true</code> if the given key is present in <i>hsh</i>.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.has_key?("a")   #=> true
- *     h.has_key?("z")   #=> false
- *
- */
-
-VALUE
-rhash_has_key(VALUE hash, SEL sel, VALUE key)
-{
-    return st_lookup(RHASH(hash)->tbl, key, 0) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     hsh.has_value?(value)    => true or false
- *     hsh.value?(value)        => true or false
- *
- *  Returns <code>true</code> if the given value is present for some key
- *  in <i>hsh</i>.
- *
- *     h = { "a" => 100, "b" => 200 }
- *     h.has_value?(100)   #=> true
- *     h.has_value?(999)   #=> false
- */
-
-static int
-search_value(VALUE key, VALUE value, VALUE arg)
-{
-    VALUE *data = (VALUE *)arg;
-    if (key != Qundef) {
-	if (rb_equal(value, data[1])) {
-	    data[0] = Qtrue;
-	    return ST_STOP;
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_has_value(VALUE hash, SEL sel, VALUE val)
-{
-    VALUE data[2] = {Qfalse, val};
-    rhash_foreach(hash, search_value, (VALUE)data);
-    return data[0];
-}
-
-/*
- *  call-seq:
- *     hsh == other_hash    => true or false
- *
- *  Equality---Two hashes are equal if they each contain the same number
- *  of keys and if each key-value pair is equal to (according to
- *  <code>Object#==</code>) the corresponding elements in the other
- *  hash.
- *
- *     h1 = { "a" => 1, "c" => 2 }
- *     h2 = { 7 => 35, "c" => 2, "a" => 1 }
- *     h3 = { "a" => 1, "c" => 2, 7 => 35 }
- *     h4 = { "a" => 1, "d" => 2, "f" => 35 }
- *     h1 == h2   #=> false
- *     h2 == h3   #=> true
- *     h3 == h4   #=> false
- *
- */
-
-struct equal_data {
-    VALUE result;
-    st_table *tbl;
-    bool eql;
-};
-
-static int
-eql_i(VALUE key, VALUE val1, VALUE arg)
-{
-    struct equal_data *data = (struct equal_data *)arg;
-    VALUE val2;
-
-    if (key == Qundef) {
-	return ST_CONTINUE;
-    }
-    if (!st_lookup(data->tbl, key, &val2)) {
-        data->result = Qfalse;
-        return ST_STOP;
-    }
-    if (data->eql) {
-	if (!rb_eql(val1, val2)) {
-	    data->result = Qfalse;
-	    return ST_STOP;
-	}
-    }
-    else {
-	if (rb_equal(val1, val2) != Qtrue) {
-	    data->result = Qfalse;
-	    return ST_STOP;
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-recursive_eql(VALUE hash1, VALUE data, int recur)
-{
-    if (recur) {
-	return Qtrue;
-    }
-    ((struct equal_data *)data)->result = Qtrue;
-    rb_hash_foreach(hash1, eql_i, data);
-    return ((struct equal_data *)data)->result; 
-}
-
-static VALUE
-hash_equal(VALUE hash1, VALUE hash2, bool eql)
-{
-    if (hash1 == hash2) {
-	return Qtrue;
-    }
-    if (TYPE(hash2) != T_HASH) {
-	if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
-	    return Qfalse;
-	}
-	if (eql) {
-	    return rb_eql(hash2, hash1);
-	}
-	else {
-	    return rb_equal(hash2, hash1);
-	}
-    }
-    if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) {
-	return Qfalse;
-    }
-    if (IS_RHASH(hash2)) {
-	struct equal_data data;
-	data.tbl = RHASH(hash2)->tbl;
-	data.eql = eql;
-	return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
-    }
-    else {
-	return CFEqual((CFTypeRef)hash1, (CFTypeRef)hash2) ? Qtrue : Qfalse;
-    }
-}
-
-static VALUE
-rhash_equal(VALUE hash1, SEL sel, VALUE hash2)
-{
-    return hash_equal(hash1, hash2, false);
-}
-
-VALUE
-rb_hash_equal(VALUE hash1, VALUE hash2)
-{
-    return hash_equal(hash1, hash2, false);
-}
-
-/*
- *  call-seq:
- *     hash.eql?(other)  -> true or false
- *
- *  Returns <code>true</code> if <i>hash</i> and <i>other</i> are
- *  both hashes with the same content.
- */
-
-static VALUE
-rhash_eql(VALUE hash1, SEL sel, VALUE hash2)
-{
-    return hash_equal(hash1, hash2, true);
-}
-
-/*
- *  call-seq:
- *     hsh.invert -> aHash
- *
- *  Returns a new hash created by using <i>hsh</i>'s values as keys, and
- *  the keys as values.
- *
- *     h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
- *     h.invert   #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
- *
- */
-
-static int
-invert_i(VALUE key, VALUE value, VALUE hash)
-{
-    if (key != Qundef) {
-	rhash_aset(hash, 0, value, key);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_invert(VALUE hash, SEL sel)
-{
-    VALUE h = rb_hash_new();
-    rhash_foreach(hash, invert_i, h);
-    return h;
-}
-
-/*
- *  call-seq:
- *     hsh.merge!(other_hash)                                 => hsh
- *     hsh.update(other_hash)                                 => hsh
- *     hsh.merge!(other_hash){|key, oldval, newval| block}    => hsh
- *     hsh.update(other_hash){|key, oldval, newval| block}    => hsh
- *
- *  Adds the contents of <i>other_hash</i> to <i>hsh</i>.  If no
- *  block is specified entries with duplicate keys are overwritten
- *  with the values from <i>other_hash</i>, otherwise the value
- *  of each duplicate key is determined by calling the block with
- *  the key, its value in <i>hsh</i> and its value in <i>other_hash</i>.
- *
- *     h1 = { "a" => 100, "b" => 200 }
- *     h2 = { "b" => 254, "c" => 300 }
- *     h1.merge!(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
- *
- *     h1 = { "a" => 100, "b" => 200 }
- *     h2 = { "b" => 254, "c" => 300 }
- *     h1.merge!(h2) { |key, v1, v2| v1 }
- *                     #=> {"a"=>100, "b"=>200, "c"=>300}
- */
-
-static int
-update_i(VALUE key, VALUE value, VALUE hash)
-{
-    if (key != Qundef) {
-	rhash_aset(hash, 0, key, value);
-    }
-    return ST_CONTINUE;
-}
-
-static int
-update_block_i(VALUE key, VALUE value, VALUE hash)
-{
-    if (key != Qundef) {
-	if (rhash_has_key(hash, 0, key)) {
-	    value = rb_yield_values(3, key, rhash_aref(hash, 0, key), value);
-	    ST_STOP_IF_BROKEN();
-	}
-	rhash_aset(hash, 0, key, value);
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_update(VALUE hash1, SEL sel, VALUE hash2)
-{
-    hash2 = to_hash(hash2);
-    rhash_modify(hash1);
-    if (rb_block_given_p()) {
-	rb_hash_foreach(hash2, update_block_i, hash1);
-    }
-    else {
-	rb_hash_foreach(hash2, update_i, hash1);
-    }
-    return hash1;
-}
-
-/*
- *  call-seq:
- *     hsh.merge(other_hash)                              -> a_hash
- *     hsh.merge(other_hash){|key, oldval, newval| block} -> a_hash
- *
- *  Returns a new hash containing the contents of <i>other_hash</i> and
- *  the contents of <i>hsh</i>, overwriting entries in <i>hsh</i> with
- *  duplicate keys with those from <i>other_hash</i>.
- *
- *     h1 = { "a" => 100, "b" => 200 }
- *     h2 = { "b" => 254, "c" => 300 }
- *     h1.merge(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
- *     h1             #=> {"a"=>100, "b"=>200}
- *
- */
-
-static VALUE
-rhash_merge(VALUE hash1, SEL sel, VALUE hash2)
-{
-    return rhash_update(rhash_dup(hash1, 0), 0, hash2);
-}
-
-/*
- *  call-seq:
- *     hash.assoc(obj)   ->  an_array  or  nil
- *
- *  Searches through the hash comparing _obj_ with the key using <code>==</code>.
- *  Returns the key-value pair (two elements array) or +nil+
- *  if no match is found.  See <code>Array#assoc</code>.
- *
- *     h = {"colors"  => ["red", "blue", "green"],
- *          "letters" => ["a", "b", "c" ]}
- *     h.assoc("letters")  #=> ["letters", ["a", "b", "c"]]
- *     h.assoc("foo")      #=> nil
- */
-
-static int
-assoc_i(VALUE key, VALUE val, VALUE *args)
-{
-    if (key != Qundef) {
-	if (RTEST(rb_equal(args[0], key))) {
-	    args[1] = rb_assoc_new(key, val);
-	    return ST_STOP;
-	}
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-rhash_assoc(VALUE hash, SEL sel, VALUE obj)
-{
-    VALUE args[2] = {obj, Qnil};
-    rhash_foreach(hash, assoc_i, (st_data_t)args);
-    return args[1];
-}
-
-/*
- *  call-seq:
- *     hash.rassoc(key) -> an_array or nil
- *
- *  Searches through the hash comparing _obj_ with the value using <code>==</code>.
- *  Returns the first key-value pair (two elements array) that matches. See
- *  also <code>Array#rassoc</code>.
- *
- *     a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
- *     a.rassoc("two")    #=> [2, "two"]
- *     a.rassoc("four")   #=> nil
- */
-
-static int
-rassoc_i(VALUE key, VALUE val, VALUE *args)
-{
-    if (key != Qundef) {
-	if (RTEST(rb_equal(args[0], val))) {
-	    args[1] = rb_assoc_new(key, val);
-	    return ST_STOP;
-	}
-    }
-    return ST_CONTINUE;
-}
-
-VALUE
-rhash_rassoc(VALUE hash, SEL sel, VALUE obj)
-{
-    VALUE args[2] = {obj, Qnil};
-    rhash_foreach(hash, rassoc_i, (st_data_t)args);
-    return args[1];
-}
-
-/*
- *  call-seq:
- *     hash.flatten -> an_array
- *     hash.flatten(level) -> an_array
- *
- *  Returns a new array that is a one-dimensional flattening of this
- *  hash. That is, for every key or value that is an array, extract
- *  its elements into the new array.  Unlike Array#flatten, this
- *  method does not flatten recursively by default.  If the optional
- *  <i>level</i> argument determines the level of recursion to flatten.
- *
- *     a =  {1=> "one", 2 => [2,"two"], 3 => "three"}
- *     a.flatten    # => [1, "one", 2, [2, "two"], 3, "three"]
- *     a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
- */
-
-static VALUE
-rhash_flatten(VALUE hash, SEL sel, int argc, VALUE *argv)
-{
-    VALUE tmp, ary = rhash_to_a(hash, 0);
-    if (argc == 0) {
-	argc = 1;
-	tmp = INT2FIX(1);
-	argv = &tmp;
-    }
-    rb_vm_call(ary, selFlattenBang, argc, argv);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     hsh.compare_by_identity => hsh
- *
- *  Makes <i>hsh</i> to compare its keys by their identity, i.e. it
- *  will consider exact same objects as same keys.
- *
- *     h1 = { "a" => 100, "b" => 200, :c => "c" }
- *     h1["a"]        #=> 100
- *     h1.compare_by_identity
- *     h1.compare_by_identity? #=> true
- *     h1["a"]        #=> nil  # different objects.
- *     h1[:c]         #=> "c"  # same symbols are all same.
- *
- */
-
-static VALUE
-rhash_compare_by_id(VALUE hash, SEL sel)
-{
-    rhash_modify(hash);
-    RHASH(hash)->tbl->type = &identhash;
-    rhash_rehash(hash, 0);
-    return hash;
-}
-
-/*
- *  call-seq:
- *     hsh.compare_by_identity? => true or false
- *
- *  Returns <code>true</code> if <i>hsh</i> will compare its keys by
- *  their identity.  Also see <code>Hash#compare_by_identity</code>.
- *
- */
-
-static VALUE
-rhash_compare_by_id_p(VALUE hash, SEL sel)
-{
-    return RHASH(hash)->tbl->type == &identhash ? Qtrue : Qfalse;
-}
-
-bool
-rb_objc_hash_is_pure(VALUE hash)
-{
-    VALUE k = *(VALUE *)hash;
-    while (RCLASS_SINGLETON(k)) {
-        k = RCLASS_SUPER(k);
-    }
-    if (k == rb_cRubyHash) {
-	return true;
-    }
-    while (k != 0) {
-	if (k == rb_cRubyHash) {
-	    return false;
-	}
-	k = RCLASS_SUPER(k);
-    }
-    return true;
-}
-
-static VALUE rb_cRubyHashKeyEnumerator;
-
-typedef struct {
-    VALUE klass;
-    VALUE hash;
-    VALUE keys;
-    unsigned pos;
-} rb_hash_keyenum_t;
-
-static void *
-imp_rhash_keyenum_allObjects(void *rcv, SEL sel)
-{
-    rb_hash_keyenum_t *ke = (rb_hash_keyenum_t *)rcv;
-    return (void *)ke->keys;
-}
-
-static void *
-imp_rhash_keyenum_nextObject(void *rcv, SEL sel)
-{
-    rb_hash_keyenum_t *ke = (rb_hash_keyenum_t *)rcv;
-    if (ke->pos == RARRAY_LEN(ke->keys)) {
-	return NULL;
-    }
-    VALUE key = RARRAY_AT(ke->keys, ke->pos);
-    ke->pos++;
-    return (void *)RB2OC(key);
-}
-
-static CFIndex
-imp_rhash_count(void *rcv, SEL sel)
-{
-    return RHASH(rcv)->tbl->num_entries;
-}
-
-static void *
-imp_rhash_objectForKey(void *rcv, SEL sel, void *key)
-{
-    VALUE val;
-    if (!st_lookup(RHASH(rcv)->tbl, OC2RB(key), &val)) {
-	return NULL;
-    }
-    return RB2OC(val);
-}
-
-static void *
-imp_rhash_keyEnumerator(void *rcv, SEL sel)
-{
-    NEWOBJ(keyenum, rb_hash_keyenum_t);
-    keyenum->klass = rb_cRubyHashKeyEnumerator;
-    GC_WB(&keyenum->hash, rcv);
-    VALUE ary = rb_ary_new();
-    st_foreach_safe(RHASH(rcv)->tbl, keys_i, (st_data_t)ary);
-    GC_WB(&keyenum->keys, ary); 
-    keyenum->pos = 0;
-    return keyenum;
-}
-
-static void
-imp_rhash_setObjectForKey(void *rcv, SEL sel, void *val, void *key)
-{
-    st_insert(RHASH(rcv)->tbl, OC2RB(key), OC2RB(val));
-}
-
-static void
-imp_rhash_removeObjectForKey(void *rcv, SEL sel, void *key)
-{
-    VALUE rkey = OC2RB(key);
-    st_delete(RHASH(rcv)->tbl, &rkey, NULL);
-}
-
-/*
- *  A <code>Hash</code> is a collection of key-value pairs. It is
- *  similar to an <code>Array</code>, except that indexing is done via
- *  arbitrary keys of any object type, not an integer index. The order
- *  in which you traverse a hash by either key or value may seem
- *  arbitrary, and will generally not be in the insertion order.
- *
- *  Hashes have a <em>default value</em> that is returned when accessing
- *  keys that do not exist in the hash. By default, that value is
- *  <code>nil</code>.
- *
- */
-
-void Init_NSDictionary(void);
-
-void
-Init_Hash(void)
-{
-    Init_NSDictionary();
-
-    selFlattenBang = sel_registerName("flatten!:");
-    selDefault = sel_registerName("default:");
-    selHash = sel_registerName("hash");
-
-    id_yield = rb_intern("yield");
-
-    rb_cRubyHash = rb_define_class("Hash", rb_cNSMutableHash);
-    rb_objc_install_NSObject_special_methods((Class)rb_cRubyHash);
-
-    rb_objc_define_method(*(VALUE *)rb_cRubyHash, "new",
-	    rb_class_new_instance_imp, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRubyHash, "alloc", rhash_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cRubyHash, "[]", rhash_create, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRubyHash, "try_convert",
-	    rhash_try_convert, 1);
-    rb_objc_define_method(rb_cRubyHash, "initialize", rhash_initialize, -1);
-    rb_objc_define_method(rb_cRubyHash, "initialize_copy", rhash_replace, 1);
-    rb_objc_define_method(rb_cRubyHash, "dup", rhash_dup, 0);
-    rb_objc_define_method(rb_cRubyHash, "clone", rhash_clone, 0);
-    rb_objc_define_method(rb_cRubyHash, "rehash", rhash_rehash, 0);
-    rb_objc_define_method(rb_cRubyHash, "to_hash", rhash_to_hash, 0);
-    rb_objc_define_method(rb_cRubyHash, "to_a", rhash_to_a, 0);
-    rb_objc_define_method(rb_cRubyHash, "to_s", rhash_inspect, 0);
-    rb_objc_define_method(rb_cRubyHash, "inspect", rhash_inspect, 0);
-    rb_objc_define_method(rb_cRubyHash, "==", rhash_equal, 1);
-    rb_objc_define_method(rb_cRubyHash, "[]", rhash_aref, 1);
-    rb_objc_define_method(rb_cRubyHash, "eql?", rhash_eql, 1);
-    rb_objc_define_method(rb_cRubyHash, "fetch", rhash_fetch, -1);
-    rb_objc_define_method(rb_cRubyHash, "[]=", rhash_aset, 2);
-    rb_objc_define_method(rb_cRubyHash, "store", rhash_aset, 2);
-    rb_objc_define_method(rb_cRubyHash, "default", rhash_default, -1);
-    rb_objc_define_method(rb_cRubyHash, "default=", rhash_set_default, 1);
-    rb_objc_define_method(rb_cRubyHash, "default_proc",
-	    rhash_default_proc, 0);
-    rb_objc_define_method(rb_cRubyHash, "default_proc=",
-	    rhash_set_default_proc, 1);
-    rb_objc_define_method(rb_cRubyHash, "key", rhash_key, 1);
-    rb_objc_define_method(rb_cRubyHash, "index", rhash_index, 1);
-    rb_objc_define_method(rb_cRubyHash, "size", rhash_size, 0);
-    rb_objc_define_method(rb_cRubyHash, "length", rhash_size, 0);
-    rb_objc_define_method(rb_cRubyHash, "empty?", rhash_empty, 0);
-    rb_objc_define_method(rb_cRubyHash, "each_value", rhash_each_value, 0);
-    rb_objc_define_method(rb_cRubyHash, "each_key", rhash_each_key, 0);
-    rb_objc_define_method(rb_cRubyHash, "each_pair", rhash_each_pair, 0);
-    rb_objc_define_method(rb_cRubyHash, "each", rhash_each_pair, 0);
-    rb_objc_define_method(rb_cRubyHash, "keys", rhash_keys, 0);
-    rb_objc_define_method(rb_cRubyHash, "values", rhash_values, 0);
-    rb_objc_define_method(rb_cRubyHash, "values_at", rhash_values_at, -1);
-    rb_objc_define_method(rb_cRubyHash, "shift", rhash_shift, 0);
-    rb_objc_define_method(rb_cRubyHash, "delete", rhash_delete, 1);
-    rb_objc_define_method(rb_cRubyHash, "delete_if", rhash_delete_if, 0);
-    rb_objc_define_method(rb_cRubyHash, "keep_if", rhash_keep_if, 0);
-    rb_objc_define_method(rb_cRubyHash, "select", rhash_select, 0);
-    rb_objc_define_method(rb_cRubyHash, "select!", rhash_select_bang, 0);
-    rb_objc_define_method(rb_cRubyHash, "reject", rhash_reject, 0);
-    rb_objc_define_method(rb_cRubyHash, "reject!", rhash_reject_bang, 0);
-    rb_objc_define_method(rb_cRubyHash, "clear", rhash_clear, 0);
-    rb_objc_define_method(rb_cRubyHash, "invert", rhash_invert, 0);
-    rb_objc_define_method(rb_cRubyHash, "update", rhash_update, 1);
-    rb_objc_define_method(rb_cRubyHash, "replace", rhash_replace, 1);
-    rb_objc_define_method(rb_cRubyHash, "merge!", rhash_update, 1);
-    rb_objc_define_method(rb_cRubyHash, "merge", rhash_merge, 1);
-    rb_objc_define_method(rb_cRubyHash, "assoc", rhash_assoc, 1);
-    rb_objc_define_method(rb_cRubyHash, "rassoc", rhash_rassoc, 1);
-    rb_objc_define_method(rb_cRubyHash, "flatten", rhash_flatten, -1);
-    rb_objc_define_method(rb_cRubyHash, "include?", rhash_has_key, 1);
-    rb_objc_define_method(rb_cRubyHash, "member?", rhash_has_key, 1);
-    rb_objc_define_method(rb_cRubyHash, "has_key?", rhash_has_key, 1);
-    rb_objc_define_method(rb_cRubyHash, "has_value?", rhash_has_value, 1);
-    rb_objc_define_method(rb_cRubyHash, "key?", rhash_has_key, 1);
-    rb_objc_define_method(rb_cRubyHash, "value?", rhash_has_value, 1);
-    rb_objc_define_method(rb_cRubyHash, "compare_by_identity",
-	    rhash_compare_by_id, 0);
-    rb_objc_define_method(rb_cRubyHash, "compare_by_identity?",
-	    rhash_compare_by_id_p, 0);
-
-    rb_objc_install_method2((Class)rb_cRubyHash, "count",
-	    (IMP)imp_rhash_count);
-    rb_objc_install_method2((Class)rb_cRubyHash, "objectForKey:",
-	    (IMP)imp_rhash_objectForKey);
-    rb_objc_install_method2((Class)rb_cRubyHash, "keyEnumerator",
-	    (IMP)imp_rhash_keyEnumerator);
-    rb_objc_install_method2((Class)rb_cRubyHash, "setObject:forKey:",
-	    (IMP)imp_rhash_setObjectForKey);
-    rb_objc_install_method2((Class)rb_cRubyHash, "removeObjectForKey:",
-	    (IMP)imp_rhash_removeObjectForKey);
-
-    VALUE NSEnumerator = (VALUE)objc_getClass("NSEnumerator");
-    assert(NSEnumerator != 0);
-    rb_cRubyHashKeyEnumerator = rb_define_class("RubyHashKeyEnumerator",
-	NSEnumerator);
-    rb_objc_install_method2((Class)rb_cRubyHashKeyEnumerator, "allObjects",
-	(IMP)imp_rhash_keyenum_allObjects);
-    rb_objc_install_method2((Class)rb_cRubyHashKeyEnumerator, "nextObject",
-	(IMP)imp_rhash_keyenum_nextObject);
-}

Deleted: MacRuby/trunk/hash.h
===================================================================
--- MacRuby/trunk/hash.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/hash.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,112 +0,0 @@
-/* 
- * MacRuby Hash.
- *
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __HASH_H_
-#define __HASH_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef struct {
-    struct RBasic basic;
-    st_table *tbl;
-    VALUE ifnone;
-    bool has_proc_default; 
-} rb_hash_t;
-
-#define RHASH(x) ((rb_hash_t *)x)
-
-static inline bool
-rb_klass_is_rhash(VALUE klass)
-{
-    do {
-	if (klass == rb_cRubyHash) {
-	    return true;
-	}
-	if (klass == rb_cNSHash) {
-	    return false;
-	}
-	klass = RCLASS_SUPER(klass);
-    }
-    while (klass != 0);
-    return false;
-}
-
-#define IS_RHASH(x) (rb_klass_is_rhash(*(VALUE *)x))
-
-static inline void
-rhash_modify(VALUE hash)
-{
-    const long mask = RBASIC(hash)->flags;
-    if ((mask & FL_FREEZE) == FL_FREEZE) {
-	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable hash");
-    } 
-    if ((mask & FL_UNTRUSTED) != FL_UNTRUSTED) {
-	if (rb_safe_level() >= 4) {
-	    rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
-	}
-    }
-}
-
-static inline long
-rhash_len(VALUE hash)
-{
-    return RHASH(hash)->tbl->num_entries;
-}
-
-static inline void
-rhash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
-{
-    st_foreach_safe(RHASH(hash)->tbl, func, (st_data_t)farg);
-}
-
-static inline VALUE
-rhash_lookup(VALUE hash, VALUE key)
-{
-    VALUE val;
-    if (st_lookup(RHASH(hash)->tbl, key, &val)) {
-	return val;
-    }
-    return Qundef;
-}
-
-static inline VALUE
-rhash_store(VALUE hash, VALUE key, VALUE val)
-{
-    rhash_modify(hash);
-    if (TYPE(key) == T_STRING) {
-        key = rb_str_dup(key);
-        OBJ_FREEZE(key);
-    }
-    st_insert(RHASH(hash)->tbl, key, val);
-    return val;
-}
-
-static inline VALUE
-rhash_delete_key(VALUE hash, VALUE key)
-{
-    VALUE val;
-    if (st_delete(RHASH(hash)->tbl, &key, &val)) {
-	return val;
-    }
-    return Qundef;
-}
-
-VALUE rhash_dup(VALUE rcv, SEL sel);
-VALUE rhash_aref(VALUE hash, SEL sel, VALUE key);
-VALUE rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val);
-VALUE rhash_keys(VALUE hash, SEL sel);
-VALUE rhash_has_key(VALUE hash, SEL sel, VALUE key);
-VALUE rhash_set_default(VALUE hash, SEL sel, VALUE ifnone);
-
-unsigned long rb_hash_code(VALUE obj);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __HASH_H_

Deleted: MacRuby/trunk/id.c
===================================================================
--- MacRuby/trunk/id.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/id.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,139 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2004-2007 Koichi Sasada
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-
-#define extern
-#include "id.h"
-#undef extern
-
-void
-Init_id(void)
-{
-    /* Symbols */
-    symIFUNC = ID2SYM(rb_intern("<IFUNC>"));
-    symCFUNC = ID2SYM(rb_intern("<CFUNC>"));
-
-    /* IDs */
-    idPLUS = rb_intern("+");
-    idMINUS = rb_intern("-");
-    idMULT = rb_intern("*");
-    idDIV = rb_intern("/");
-    idMOD = rb_intern("%");
-    idLT = rb_intern("<");
-    idLTLT = rb_intern("<<");
-    idLE = rb_intern("<=");
-    idGT = rb_intern(">");
-    idGE = rb_intern(">=");
-    idEq = rb_intern("==");
-    idEqq = rb_intern("===");
-    idBackquote = rb_intern("`");
-    idEqTilde = rb_intern("=~");
-    idNot = rb_intern("!");
-    idNeq = rb_intern("!=");
-
-#if WITH_OBJC
-    selPLUS = sel_registerName("+:");
-    selMINUS = sel_registerName("-:");
-    selMULT = sel_registerName("*:");
-    selDIV = sel_registerName("/:");
-    selMOD = sel_registerName("%:");
-    selAND = sel_registerName("&:");
-    selEq = sel_registerName("==:");
-    selNeq = sel_registerName("!=:");
-    selCmp = sel_registerName("<=>:");
-    selLT = sel_registerName("<:");
-    selLE = sel_registerName("<=:");
-    selGT = sel_registerName(">:");
-    selGE = sel_registerName(">=:");
-    selLTLT = sel_registerName("<<:");
-    selAREF = sel_registerName("[]:");
-    selASET = sel_registerName("[]=:");
-    selLength = sel_registerName("length");
-    selSucc = sel_registerName("succ");
-    selNot = sel_registerName("!");
-    selNot2 = sel_registerName("!:");
-    selAlloc = sel_registerName("alloc");
-    selAllocWithZone = sel_registerName("allocWithZone:");
-    selCopyWithZone = sel_registerName("copyWithZone:");
-    selInit = sel_registerName("init");
-    selInitialize = sel_registerName("initialize");
-    selInitialize2 = sel_registerName("initialize:");
-    selInitializeCopy = sel_registerName("initialize_copy:");
-    selDescription = sel_registerName("description");
-    selInspect = sel_registerName("inspect");
-    selNew = sel_registerName("new");
-    selRespondTo = sel_registerName("respond_to?:");
-    selMethodMissing = sel_registerName("method_missing:");
-    selConstMissing = sel_registerName("const_missing:");
-    selCopy = sel_registerName("copy");
-    selMutableCopy = sel_registerName("mutableCopy");
-    sel_zone = sel_registerName("zone");
-    selToS = sel_registerName("to_s");
-    selToAry = sel_registerName("to_ary");
-    selSend = sel_registerName("send:");
-    sel__send__ = sel_registerName("__send__:");
-    selCall = sel_registerName("call:");
-    selEqTilde = sel_registerName("=~:");
-    selClass = sel_registerName("class");
-    selEval = sel_registerName("eval:");
-    selInstanceEval = sel_registerName("instance_eval:");
-    selClassEval = sel_registerName("class_eval:");
-    selModuleEval = sel_registerName("module_eval:");
-    selLocalVariables = sel_registerName("local_variables");
-    selBinding = sel_registerName("binding");
-    selEach = sel_registerName("each");
-    selEqq = sel_registerName("===:");
-    selDup = sel_registerName("dup");
-    selBackquote = sel_registerName("`:");
-    selMethodAdded = sel_registerName("method_added:");
-    selSingletonMethodAdded = sel_registerName("singleton_method_added:");
-    selMethodRemoved = sel_registerName("method_removed:");
-    selSingletonMethodRemoved = sel_registerName("singleton_method_removed:");
-    selMethodUndefined = sel_registerName("method_undefined:");
-    selSingletonMethodUndefined = sel_registerName("singleton_method_undefined:");
-    selIsEqual = sel_registerName("isEqual:");
-    selWrite = sel_registerName("write:");
-    selInherited = sel_registerName("inherited:");
-    selLambda = sel_registerName("lambda");
-    selObjectForKey = sel_registerName("objectForKey:");
-    selSetObjectForKey = sel_registerName("setObject:forKey:");
-
-    sel__method__= sel_registerName("__method__");
-    sel__callee__ = sel_registerName("__callee__");
-#endif
-
-    idAREF = rb_intern("[]");
-    idASET = rb_intern("[]=");
-
-    idEach = rb_intern("each");
-    idTimes = rb_intern("times");
-    idLength = rb_intern("length");
-    idLambda = rb_intern("lambda");
-    idIntern = rb_intern("intern");
-    idGets = rb_intern("gets");
-    idSucc = rb_intern("succ");
-    idEnd = rb_intern("end");
-    idRangeEachLT = rb_intern("Range#each#LT");
-    idRangeEachLE = rb_intern("Range#each#LE");
-    idArrayEach = rb_intern("Array#each");
-    idMethodMissing = rb_intern("method_missing");
-
-    idThrowState = rb_intern("#__ThrowState__");
-
-    idSend = rb_intern("send");
-    id__send__ = rb_intern("__send__");
-
-    idRespond_to = rb_intern("respond_to?");
-    idInitialize = rb_intern("initialize");
-
-    idIncludedModules = rb_intern("__included_modules__");
-    idIncludedInClasses = rb_intern("__included_in_classes__");
-    idAncestors = rb_intern("__ancestors__");
-}

Deleted: MacRuby/trunk/id.h
===================================================================
--- MacRuby/trunk/id.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/id.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,121 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2007 Koichi Sasada
- */
-
-#ifndef RUBY_ID_H
-#define RUBY_ID_H
-
-extern VALUE symIFUNC;
-extern VALUE symCFUNC;
-
-extern ID idPLUS;
-extern ID idMINUS;
-extern ID idMULT;
-extern ID idDIV;
-extern ID idMOD;
-extern ID idLT;
-extern ID idLTLT;
-extern ID idLE;
-extern ID idGT;
-extern ID idGE;
-extern ID idEq;
-extern ID idEqq;
-extern ID idNeq;
-extern ID idNot;
-extern ID idBackquote;
-extern ID idEqTilde;
-extern ID idThrowState;
-extern ID idAREF;
-extern ID idASET;
-extern ID idIntern;
-extern ID idMethodMissing;
-extern ID idLength;
-extern ID idGets;
-extern ID idSucc;
-extern ID idEach;
-extern ID idLambda;
-extern ID idRangeEachLT;
-extern ID idRangeEachLE;
-extern ID idArrayEach;
-extern ID idTimes;
-extern ID idEnd;
-extern ID idSend;
-extern ID id__send__;
-extern ID idRespond_to;
-extern ID idInitialize;
-#if WITH_OBJC
-extern SEL selPLUS;
-extern SEL selMINUS;
-extern SEL selMULT;
-extern SEL selDIV;
-extern SEL selMOD;
-extern SEL selAND;
-extern SEL selEq;
-extern SEL selNeq;
-extern SEL selCmp;
-extern SEL selLT;
-extern SEL selLE;
-extern SEL selGT;
-extern SEL selGE;
-extern SEL selLTLT;
-extern SEL selAREF;
-extern SEL selASET;
-extern SEL selLength;
-extern SEL selSucc;
-extern SEL selNot;
-extern SEL selNot2;
-extern SEL selAlloc;
-extern SEL selAllocWithZone;
-extern SEL selCopyWithZone;
-extern SEL selInit;
-extern SEL selInitialize;
-extern SEL selInitialize2;
-extern SEL selInitializeCopy;
-extern SEL selDescription;
-extern SEL selInspect;
-extern SEL selNew;
-extern SEL selRespondTo;
-extern SEL selMethodMissing;
-extern SEL selConstMissing;
-extern SEL selCopy;
-extern SEL selMutableCopy;
-extern SEL selToS;
-extern SEL selToAry;
-extern SEL sel_zone;
-extern SEL selSend;
-extern SEL sel__send__;
-extern SEL selCall;
-extern SEL selEqTilde;
-extern SEL selClass;
-extern SEL selEval;
-extern SEL selInstanceEval;
-extern SEL selClassEval;
-extern SEL selModuleEval;
-extern SEL selLocalVariables;
-extern SEL selBinding;
-extern SEL selEach;
-extern SEL selEqq;
-extern SEL selDup;
-extern SEL selBackquote;
-extern SEL selMethodAdded;
-extern SEL selSingletonMethodAdded;
-extern SEL selMethodRemoved;
-extern SEL selSingletonMethodRemoved;
-extern SEL selMethodUndefined;
-extern SEL selSingletonMethodUndefined;
-extern SEL selIsEqual;
-extern SEL selWrite;
-extern SEL selInherited;
-extern SEL selLambda;
-extern SEL selObjectForKey;
-extern SEL selSetObjectForKey;
-extern SEL sel__method__;
-extern SEL sel__callee__;
-extern ID idIncludedModules;
-extern ID idIncludedInClasses;
-extern ID idAncestors;
-#endif
-#endif /* RUBY_ID_H */

Deleted: MacRuby/trunk/inits.c
===================================================================
--- MacRuby/trunk/inits.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/inits.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,114 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-
-void Init_Array(void);
-void Init_Bignum(void);
-void Init_Binding(void);
-void Init_Comparable(void);
-void Init_Complex(void);
-void Init_Dir(void);
-void Init_Enumerable(void);
-void Init_Enumerator(void);
-void Init_Exception(void);
-void Init_syserr(void);
-void Init_eval(void);
-void Init_load(void);
-void Init_Proc(void);
-void Init_File(void);
-void Init_GC(void);
-void Init_Hash(void);
-void Init_ENV(void);
-void Init_IO(void);
-void Init_Math(void);
-void Init_marshal(void);
-void Init_Numeric(void);
-void Init_Object(void);
-void Init_pack(void);
-void Init_Precision(void);
-void Init_Symbol(void);
-void Init_PreSymbol(void);
-void Init_id(void);
-void Init_process(void);
-void Init_Random(void);
-void Init_Range(void);
-void Init_Rational(void);
-void Init_Regexp(void);
-void Init_signal(void);
-void Init_String(void);
-void Init_Struct(void);
-void Init_Time(void);   
-void Init_var_tables(void);
-void Init_version(void);
-void Init_VM(void);
-void Init_Thread(void);
-//void Init_Cont(void);
-void Init_Encoding(void);
-void Init_PostGC(void);
-void Init_ObjC(void);
-void Init_BridgeSupport(void);
-void Init_FFI(void);
-void Init_Dispatch(void);
-void Init_Transcode(void);
-void Init_PostVM(void);
-void Init_sandbox(void);
-
-void
-rb_call_inits()
-{
-    Init_PreSymbol();
-    Init_id();
-    Init_var_tables();
-    Init_Object();
-    Init_VM();
-    Init_Encoding();
-    Init_Comparable();
-    Init_Enumerable();
-    Init_Precision();
-    Init_String();
-    Init_Symbol();
-    Init_Exception();
-    Init_eval();
-    Init_jump();
-    Init_Numeric();
-    Init_Bignum();
-    Init_syserr();
-    Init_Array();
-    Init_Hash();
-    Init_ENV();
-    Init_Struct();
-    Init_Regexp();
-    Init_pack();
-    Init_marshal();
-    Init_Range();
-    Init_IO();
-    Init_Dir();
-    Init_Time();
-    Init_Random();
-    Init_signal();
-    Init_process();
-    Init_load();
-    Init_Proc();
-    Init_Binding();
-    Init_Math();
-    Init_GC();
-    Init_Enumerator();
-    Init_Thread();
-    //Init_Cont();
-    Init_Rational();
-    Init_Complex();
-    Init_version();
-    Init_PostGC();
-    Init_ObjC();
-    Init_BridgeSupport();
-    Init_FFI();
-    Init_Dispatch();
-    Init_Transcode();
-    Init_sandbox();
-    Init_PostVM();
-}

Deleted: MacRuby/trunk/instruby.rb
===================================================================
--- MacRuby/trunk/instruby.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/instruby.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,528 +0,0 @@
-#!./miniruby
-
-load "./rbconfig.rb"
-include RbConfig
-
-srcdir = File.dirname(__FILE__)
-$:.clear
-$:.unshift File.expand_path("lib", srcdir)
-require 'fileutils'
-require 'shellwords'
-require 'optparse'
-require 'optparse/shellwords'
-require 'tempfile'
-
-STDOUT.sync = true
-File.umask(0)
-
-def parse_args(argv = ARGV)
-  $mantype = 'doc'
-  $destdir = $sym_destdir = nil
-  $extout = nil
-  $make = 'make'
-  $mflags = []
-  $install = []
-  $installed_list = nil
-  $dryrun = false
-  $rdocdir = nil
-  $data_mode = 0644
-  $prog_mode = 0755
-  $dir_mode = nil
-  $script_mode = nil
-  $cmdtype = ('bat' if File::ALT_SEPARATOR == '\\')
-  mflags = []
-  opt = OptionParser.new
-  opt.on('-n') {$dryrun = true}
-  opt.on('--dest-dir=DIR') {|dir| $destdir = dir}
-  opt.on('--sym-dest-dir=DIR') {|dir| $sym_destdir = dir}
-  opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)}
-  opt.on('--make=COMMAND') {|make| $make = make}
-  opt.on('--mantype=MAN') {|man| $mantype = man}
-  opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v|
-    if arg = v.first
-      arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg
-    end
-    $mflags.concat(v)
-  end
-  opt.on('-i', '--install=TYPE',
-         [:local, :bin, :"bin-arch", :"bin-comm", :lib, :man, :ext, :"ext-arch", :"ext-comm", :rdoc, :data]) do |ins|
-    $install << ins
-  end
-  opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
-    $data_mode = mode
-  end
-  opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
-    $prog_mode = mode
-  end
-  opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
-    $dir_mode = mode
-  end
-  opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
-    $script_mode = mode
-  end
-  opt.on('--installed-list [FILENAME]') {|name| $installed_list = name}
-  opt.on('--rdoc-output [DIR]') {|dir| $rdocdir = dir}
-  opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')}
-
-  opt.order!(argv) do |v|
-    case v
-    when /\AINSTALL[-_]([-\w]+)=(.*)/
-      argv.unshift("--#{$1.tr('_', '-')}=#{$2}")
-    when /\A\w[-\w+]*=\z/
-      mflags << v
-    when /\A\w[-\w+]*\z/
-      $install << v.intern
-    else
-      raise OptionParser::InvalidArgument, v
-    end
-  end rescue abort [$!.message, opt].join("\n")
-
-  $make, *rest = Shellwords.shellwords($make)
-  $mflags.unshift(*rest) unless rest.empty?
-  $mflags.unshift(*mflags)
-
-  def $mflags.set?(flag)
-    grep(/\A-(?!-).*#{flag.chr}/i) { return true }
-    false
-  end
-  def $mflags.defined?(var)
-    grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1}
-    false
-  end
-
-  if $mflags.set?(?n)
-    $dryrun = true
-  else
-    $mflags << '-n' if $dryrun
-  end
-
-  $destdir ||= $mflags.defined?("DESTDIR")
-  if $extout ||= $mflags.defined?("EXTOUT")
-    Config.expand($extout)
-  end
-
-  $continue = $mflags.set?(?k)
-
-  if $installed_list ||= $mflags.defined?('INSTALLED_LIST')
-    Config.expand($installed_list, Config::CONFIG)
-    $installed_list = open($installed_list, "ab")
-    $installed_list.sync = true
-  end
-
-  $rdocdir ||= $mflags.defined?('RDOCOUT')
-
-  $dir_mode ||= $prog_mode | 0700
-  $script_mode ||= $prog_mode
-end
-
-parse_args()
-
-include FileUtils
-include FileUtils::NoWrite if $dryrun
- at fileutils_output = STDOUT
- at fileutils_label = ''
-
-$install_procs = Hash.new {[]}
-def install?(*types, &block)
-  $install_procs[:all] <<= block
-  types.each do |type|
-    $install_procs[type] <<= block
-  end
-end
-
-def install(src, dest, options = {})
-  strip = options.delete(:strip)
-  options[:preserve] = true
-  super(src, with_destdir(dest), options)
-  dest = File.join(dest, File.basename(src)) if $made_dirs[dest]
-  if $installed_list
-    $installed_list.puts dest
-  end
-  if strip
-    system("/usr/bin/strip -x \"#{with_destdir(dest)}\"")
-  end
-end
-
-def ln_sf(src, dest)
-  super(src, with_destdir(dest))
-  $installed_list.puts dest if $installed_list
-end
-
-$made_dirs = {}
-def makedirs(dirs)
-  dirs = fu_list(dirs)
-  dirs.collect! do |dir|
-    realdir = with_destdir(dir)
-    realdir unless $made_dirs.fetch(dir) do
-      $made_dirs[dir] = true
-      $installed_list.puts(File.join(dir, "")) if $installed_list
-      File.directory?(realdir)
-    end
-  end.compact!
-  super(dirs, :mode => $dir_mode) unless dirs.empty?
-end
-
-def install_recursive(srcdir, dest, options = {})
-  opts = options.clone
-  noinst = opts.delete(:no_install)
-  glob = opts.delete(:glob) || "*"
-  subpath = srcdir.size..-1
-  Dir.glob("#{srcdir}/**/#{glob}") do |src|
-    case base = File.basename(src)
-    when /\A\#.*\#\z/, /~\z/
-      next
-    end
-    if noinst
-      if Array === noinst
-        next if noinst.any? {|n| File.fnmatch?(n, base)}
-      else
-        next if File.fnmatch?(noinst, base)
-      end
-    end
-    d = dest + src[subpath]
-    if File.directory?(src)
-      makedirs(d)
-    else
-      makedirs(File.dirname(d))
-      install src, d, opts
-    end
-  end
-end
-
-def open_for_install(path, mode)
-  data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil
-  newdata = yield
-  unless $dryrun
-    unless newdata == data
-      open(realpath, "wb", mode) {|f| f.write newdata}
-    end
-    File.chmod(mode, realpath)
-  end
-  $installed_list.puts path if $installed_list
-end
-
-def with_destdir(dir)
-  return dir if !$destdir or $destdir.empty?
-  dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';'
-  $destdir + dir
-end
-
-exeext = CONFIG["EXEEXT"]
-
-ruby_install_name = CONFIG["ruby_install_name"]
-rubyw_install_name = CONFIG["rubyw_install_name"]
-goruby_install_name = "go" + ruby_install_name
-
-version = CONFIG["ruby_version"]
-bindir = CONFIG["bindir"]
-libdir = CONFIG["libdir"]
-datadir = CONFIG['datadir']
-archhdrdir = rubyhdrdir = CONFIG["rubyhdrdir"]
-archhdrdir += "/" + CONFIG["arch"]
-rubylibdir = CONFIG["rubylibdir"]
-archlibdir = CONFIG["archdir"]
-sitelibdir = CONFIG["sitelibdir"]
-sitearchlibdir = CONFIG["sitearchdir"]
-vendorlibdir = CONFIG["vendorlibdir"]
-vendorarchlibdir = CONFIG["vendorarchdir"]
-mandir = File.join(CONFIG["mandir"], "man")
-configure_args = Shellwords.shellwords(CONFIG["configure_args"])
-enable_shared = CONFIG["ENABLE_SHARED"] == 'yes'
-enable_static = CONFIG["ENABLE_STATIC"] == 'yes'
-dll = CONFIG["LIBRUBY_SO"]
-lib = CONFIG["LIBRUBY"]
-arc = CONFIG["LIBRUBY_A"]
-install_version = CONFIG['INSTALL_VERSION']
-
-install?(:local, :arch, :bin, :'bin-arch') do
-  puts "installing binary commands"
-
-  makedirs [bindir, libdir, archlibdir]
-
-  install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => true
-  if rubyw_install_name and !rubyw_install_name.empty?
-    install rubyw_install_name+exeext, bindir, :mode => $prog_mode
-  end
-  if File.exist? goruby_install_name+exeext
-    install goruby_install_name+exeext, bindir, :mode => $prog_mode
-  end
-  if enable_shared and dll != lib
-    install dll, bindir, :mode => $prog_mode
-  end
-  install lib, libdir, :mode => $prog_mode, :strip => true
-  if enable_static
-    install arc, libdir, :mode => $data_mode, :strip => true
-  end
-  install "rbconfig.rb", archlibdir, :mode => $data_mode
-  install "rbconfig.rbo", archlibdir, :mode => $data_mode
-  if CONFIG["ARCHFILE"]
-    for file in CONFIG["ARCHFILE"].split
-      install file, archlibdir, :mode => $data_mode
-    end
-  end
-
-  if dll == lib and dll != arc
-    for link in CONFIG["LIBRUBY_ALIASES"].split
-      ln_sf(dll, File.join(libdir, link))
-    end
-  end
-end
-
-if $extout
-  extout = "#$extout"
-  install?(:ext, :arch, :'ext-arch') do
-    puts "installing extension objects"
-    makedirs [archlibdir, sitearchlibdir, vendorarchlibdir, archhdrdir]
-    if noinst = CONFIG["no_install_files"] and noinst.empty?
-      noinst = nil
-    end
-    install_recursive("#{extout}/#{CONFIG['arch']}", archlibdir, :no_install => noinst, :mode => $prog_mode)
-    install_recursive("#{extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode)
-  end
-  install?(:ext, :comm, :'ext-comm') do
-    puts "installing extension scripts"
-    hdrdir = rubyhdrdir + "/ruby"
-    makedirs [rubylibdir, sitelibdir, vendorlibdir, hdrdir]
-    install_recursive("#{extout}/common", rubylibdir, :mode => $data_mode)
-    install_recursive("#{extout}/include/ruby", hdrdir, :glob => "*.h", :mode => $data_mode)
-  end
-end
-
-install?(:local, :comm, :bin, :'bin-comm') do
-  puts "installing command scripts"
-
-  Dir.chdir srcdir
-  makedirs [bindir, rubylibdir]
-
-  ruby_shebang = File.join(bindir, ruby_install_name)
-  if File::ALT_SEPARATOR
-    ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR)
-  end
-  for src in Dir["bin/*"]
-    next unless File.file?(src)
-    next if /\/[.#]|(\.(old|bak|orig|rej|diff|patch|core)|~|\/core)$/i =~ src
-
-    bname = File.basename(src)
-    name = case bname
-      when 'hotcocoa', 'rb_nibtool'
-        bname
-      else
-        ruby_install_name.sub(/ruby/, bname)
-    end
-    
-    shebang = ''
-    body = ''
-    open(src, "rb") do |f|
-      shebang = f.gets
-      body = f.read
-    end
-    shebang.sub!(/^\#!.*?ruby\b/) {"#!" + ruby_shebang}
-    shebang.sub!(/\r$/, '')
-    body.gsub!(/\r$/, '')
-
-    cmd = File.join(bindir, name)
-    cmd << ".#{$cmdtype}" if $cmdtype
-    open_for_install(cmd, $script_mode) do
-      case $cmdtype
-      when "bat"
-        "#{<<EOH}#{shebang}#{body}#{<<EOF}".gsub(/$/, "\r")
- at echo off
- at if not "%~d0" == "~d0" goto WinNT
-#{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9
- at goto endofruby
-:WinNT
-"%~dp0#{ruby_install_name}" -x "%~f0" %*
- at goto endofruby
-EOH
-__END__
-:endofruby
-EOF
-      when "cmd"
-        "#{<<EOH}#{shebang}#{body}"
-@"%~dp0#{ruby_install_name}" -x "%~f0" %*
- at exit /b %ERRORLEVEL%
-EOH
-      else
-        shebang + body
-      end
-    end
-  end
-end
-
-install?(:local, :comm, :lib) do
-  puts "installing library scripts"
-
-  Dir.chdir srcdir
-  makedirs [rubylibdir]
-
-  for f in Dir["lib/**/*{.rb,.rbo,help-message}"]
-    dir = File.dirname(f).sub!(/\Alib/, rubylibdir) || rubylibdir
-    makedirs dir
-    install f, dir, :mode => $data_mode
-  end
-end
-
-install?(:local, :arch, :lib) do
-  puts "installing headers"
-
-  Dir.chdir(srcdir)
-  makedirs [rubyhdrdir]
-  noinst = []
-  unless RUBY_PLATFORM =~ /mswin32|mingw|bccwin32/
-    noinst << "win32.h"
-  end
-  noinst = nil if noinst.empty?
-  install_recursive("include", rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode)
-end
-
-install?(:local, :comm, :man) do
-  puts "installing manpages"
-
-  Dir.chdir(srcdir)
-  for mdoc in Dir["*.[1-9]"]
-    next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'}
-
-    destdir = mandir + mdoc[/(\d+)$/]
-    destfile = File.join(destdir, mdoc.sub(/ruby/, ruby_install_name))
-
-    makedirs destdir
-
-    if $mantype == "doc"
-      install mdoc, destfile, :mode => $data_mode
-    else
-      require 'mdoc2man.rb'
-
-      w = Tempfile.open(mdoc)
-
-      open(mdoc) { |r|
-        Mdoc2Man.mdoc2man(r, w)
-      }
-
-      w.close
-
-      install w.path, destfile, :mode => $data_mode
-    end
-  end
-end
-
-#install?(:rdoc) do
-  if $rdocdir
-    puts "installing rdoc"
-
-    ridatadir = File.join(CONFIG['datadir'], 'ri/$(MAJOR).$(MINOR).$(TEENY)/system')
-    Config.expand(ridatadir)
-    makedirs [ridatadir]
-    install_recursive($rdocdir, ridatadir, :mode => $data_mode)
-  end
-#end
-
-install?(:local, :data) do
-  puts "installing data files"
-  destination_dir = datadir.clone
-  Config.expand(destination_dir)
-  makedirs [destination_dir]
-  install_recursive("data", destination_dir, :mode => $data_mode)
-end  
-
-$install << :local << :ext if $install.empty?
-$install.each do |inst|
-  if !(procs = $install_procs[inst]) || procs.empty?
-    next warn("unknown install target - #{inst}")
-  end
-  procs.each do |block|
-    dir = Dir.pwd
-    begin
-      block.call
-    ensure
-      Dir.chdir(dir)
-    end
-  end
-end
-
-def ln_sfh(source, target)
-  ln_sf(source, target) unless File.symlink?(with_destdir(target))
-end
-
-def mkdir_p(target, *flags)
-  super(with_destdir(target), *flags)
-end
-
-def install_stuff(what, from, to, mode)
-  puts "installing #{what}"
-  mkdir_p to, :mode => mode
-  install_recursive from, to, :mode => mode
-  Dir.glob(File.join(to, '**', '.svn')).each { |x| rm_rf(x) }
-end
-
-install_stuff('Xcode 4.x templates', 'misc/xcode4-templates',
-  '/Developer/Library/Xcode/Templates', 0755)
-install_stuff('Xcode 3.x templates', 'misc/xcode-templates', 
-  '/Library/Application Support/Developer/3.0/Xcode', 0755)
-install_stuff('Xcode 2.x templates', 'misc/xcode-templates', 
-  '/Library/Application Support/Developer/Shared/Xcode', 0755)
-install_stuff('samples', 'sample-macruby', 
-  '/Developer/Examples/Ruby/MacRuby', 0775)
-
-if RUBY_FRAMEWORK
-  puts "installing framework"
-  # Creating framework infrastructure.
-  base = File.join(CONFIG["prefix"], '..')
-  resources = File.join(base, 'Resources')
-  mkdir_p resources, :mode => 0755
-  install File.join('framework/Info.plist'), resources, :mode => 0644
-  mkdir_p File.join(resources, 'English.lproj'), :mode => 0755
-  install File.join('framework/InfoPlist.strings'),
-    File.join(resources, 'English.lproj'), :mode => 0644
-  rm_f File.join(base, '..', 'Current') if 
-    File.symlink?(with_destdir(File.join(base, '..', 'Current')))
-  ln_sfh install_version.to_s, File.join(base, '..', 'Current')
-  ln_sfh 'Versions/Current/Headers', File.join(base, '../../Headers')
-  ln_sfh 'Versions/Current/MacRuby', File.join(base, '../../MacRuby')
-  ln_sfh 'Versions/Current/Resources', File.join(base, '../../Resources')
-  ln_sfh "usr/lib/#{CONFIG['LIBRUBY_SO']}", File.join(base, 'MacRuby')
-  ln_sfh "usr/include/ruby-#{RUBY_VERSION}", File.join(base, 'Headers')
-  ln_sfh "../#{CONFIG['arch']}/ruby/config.h", 
-    File.join(base, "usr/include/ruby-#{RUBY_VERSION}/ruby/config.h")
-  # Installing executable links.
-  dest_bin = File.join($sym_destdir, 'bin')
-  mkdir_p dest_bin, :mode => 0755
-  Dir.entries(with_destdir(CONFIG['bindir'])).each do |bin|
-    next if bin[0] == '.'
-    # Except rb_nibtool & llc!
-    next if bin == 'rb_nibtool' or bin == 'llc'
-    link = File.join("../../../", CONFIG['bindir'], bin)
-    link.sub!(/#{install_version}/, 'Current')
-    ln_sfh link, File.join(dest_bin, File.basename(bin))
-  end
-  # Installing man pages links.
-  dest_man = File.join($sym_destdir, 'share', 'man')
-  mkdir_p dest_man, :mode => 0755
-  Dir.entries(with_destdir(CONFIG['mandir'])).each do |mandir|
-    next if mandir[0] == '.'
-    if File.stat(File.join(with_destdir(CONFIG['mandir']), mandir)).directory?
-      mkdir_p File.join(dest_man, File.basename(mandir)), :mode => 0755
-      Dir.entries(File.join(with_destdir(CONFIG['mandir']), mandir)).each do |man|
-        next if man[0] == '.'
-        link = File.join("../../../../../", CONFIG['mandir'], mandir, man)
-        link.sub!(/#{install_version}/, 'Current')
-        ln_sfh link, File.join(dest_man, File.basename(mandir), 
-	  File.basename(man))
-      end
-    else
-      link = File.join("../../../../", CONFIG['mandir'], mandir)
-      link.sub!(/#{install_version}/, 'Current')
-      ln_sfh link, File.join(dest_man, File.basename(mandir))
-    end
-  end
-end
-
-puts "installing IB support"
-ib_dest = '/Developer/usr/bin'
-mkdir_p ib_dest
-ln_sfh File.join("../../..", CONFIG['bindir'], 'rb_nibtool'), ib_dest
-
-puts "installing LLVM tools"
-llc_dest = File.join(CONFIG['bindir'], 'llc')
-install(File.join(CONFIG['LLVM_PATH'], 'bin/llc'), llc_dest, :mode => $prog_mode)
-
-# vi:set sw=2:

Deleted: MacRuby/trunk/interpreter.cpp
===================================================================
--- MacRuby/trunk/interpreter.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/interpreter.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,297 +0,0 @@
-/*
- * MacRuby Interpreter.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#if !defined(MACRUBY_STATIC)
-
-#include "llvm.h"
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "interpreter.h"
-#include "vm.h"
-
-#define PRIMITIVE static inline
-#include "kernel.c"
-
-// Will be set later, in vm.cpp.
-RoxorInterpreter *RoxorInterpreter::shared = NULL;
-
-RoxorInterpreter::RoxorInterpreter(void)
-{
-    stack = (VALUE *)calloc(INTERPRETER_STACK_SIZE, sizeof(VALUE));
-    assert(stack != NULL);
-}
-
-RoxorInterpreter::~RoxorInterpreter(void)
-{
-    free(stack);
-}
-
-extern "C" void rb_vm_prepare_method(Class klass, unsigned char dynamic_class,
-	SEL sel, Function *func, const rb_vm_arity_t arity, int flags);
-
-#define value_as(val, type) ((type)interpret_value(val))
-
-static inline Value *
-call_arg(CallInst *insn, unsigned int i)
-{
-#if LLVM_TOT
-    return insn->getOperand(i + 1);
-#else
-    return insn->getArgOperand(i);
-#endif
-}
-
-static inline uint64_t
-get_const_int(Value *val)
-{
-    return cast<ConstantInt>(val)->getZExtValue();
-}
-
-// A macro to avoid stupid compiler warnings.
-#define oops(msg, val) \
-	printf("interpreter: %s (ID: %d)\n", msg, val->getValueID()); \
-	val->dump(); \
-	abort();
-
-VALUE
-RoxorInterpreter::interpret_call(CallInst *call)
-{
-    Function *called = call->getCalledFunction();
-
-    if (called == RoxorCompiler::shared->prepareMethodFunc) {
-	VALUE klass = value_as(call_arg(call, 0), VALUE);
-	uint8_t dynamic_class = value_as(call_arg(call, 1), uint8_t);
-	SEL sel = value_as(call_arg(call, 2), SEL);
-	Function *func = value_as(call_arg(call, 3), Function *);
-	uint64_t arity_data = get_const_int(call_arg(call, 4));
-	rb_vm_arity_t arity;
-	memcpy(&arity, &arity_data, sizeof(rb_vm_arity_t));
-	int flags = value_as(call_arg(call, 5), int);
-
-	rb_vm_prepare_method((Class)klass, dynamic_class, sel, func, arity,
-		flags);
-	return Qnil;
-    }
-    else if (called == RoxorCompiler::shared->dispatchFunc) {
-	VALUE top = value_as(call_arg(call, 0), VALUE);
-	VALUE self = value_as(call_arg(call, 1), VALUE);
-	void *sel = value_as(call_arg(call, 2), SEL);
-	void *block = value_as(call_arg(call, 3), void *);
-	uint8_t opt = value_as(call_arg(call, 4), uint8_t);
-	int argc = value_as(call_arg(call, 5), int);
-	VALUE *argv = value_as(call_arg(call, 6), VALUE *);
-
-	MDNode *node = call->getMetadata(RoxorCompiler::shared->dbg_mdkind);
-	if (node != NULL) {
-	    std::string path;
-	    DILocation loc(node);
-	    RoxorCompiler::shared->generate_location_path(path, loc);
-
-	    Frame frame;
-	    frame.name = (const char *)sel;
-	    frame.path = path;
-	    frame.line = loc.getLineNumber();
-	    frames.push_back(frame);
-	}
-
-	struct Finally {
-	    RoxorInterpreter *ir;
-	    bool pop;
-	    Finally(RoxorInterpreter *_ir, bool _pop) {
-		ir = _ir;
-		pop = _pop;	
-	    }
-	    ~Finally() { 
-		if (pop) {
-		    ir->frames.pop_back();
-		}
-	    }
-	} finalizer(this, node != NULL);
-
-	return vm_dispatch(top, self, sel, block, opt, argc, argv);
-    }
-    else if (called == RoxorCompiler::shared->singletonClassFunc) {
-	VALUE klass = value_as(call_arg(call, 0), VALUE);
-
-	return rb_singleton_class(klass);
-    }
-
-    oops("unrecognized call instruction:", call);
-}
-
-bool
-RoxorInterpreter::frame_at_index(unsigned int idx, void *addr,
-	std::string *name, std::string *path, unsigned int *line)
-{
-    if ((uintptr_t)addr < (uintptr_t)(void *)&vm_dispatch
-	    || (uintptr_t)addr > (uintptr_t)(void *)&vm_dispatch + 5000) {
-	// Likely not an interpreted dispatch call.
-	return false;
-    }
-    if (idx >= frames.size()) {
-	// Not enough frames!
-	return false;
-    }
-
-    Frame &frame = frames[idx];
-    *name = frame.name;
-    *path = frame.path;
-    *line = frame.line;
-    return true;
-}
-
-#define return_if_cached(__insn) \
-    std::map<Instruction *, VALUE>::iterator __i = insns.find(__insn); \
-    if (__i != insns.end()) { \
-	return __i->second; \
-    } \
-
-VALUE
-RoxorInterpreter::interpret_instruction(Instruction *insn)
-{
-    switch (insn->getOpcode()) {
-	case Instruction::Br:
-	    {
-		BranchInst *br = static_cast<BranchInst *>(insn);
-		if (br->isUnconditional()) {
-		    BasicBlock *bb = br->getSuccessor(0);
-		    assert(bb != NULL);
-		    return interpret_basicblock(bb);
-		}
-		break;
-	    }
-
-	case Instruction::Ret:
-	    {
-		ReturnInst *ret = static_cast<ReturnInst *>(insn);
-		Value *retval = ret->getReturnValue();
-		assert(retval != NULL);
-		return interpret_value(retval);
-	    }
-
-	case Instruction::Call:
-	    {
-		return_if_cached(insn);
-		VALUE ret = interpret_call(static_cast<CallInst *>(insn));
-		insns[insn] = ret;
-		return ret;
-	    }
-
-	case Instruction::Alloca:
-	    {
-		return_if_cached(insn);
-		// Assuming the allocated type is VALUE.
-		AllocaInst *allocai = static_cast<AllocaInst *>(insn);
-		const size_t n = get_const_int(allocai->getArraySize());
-		assert(n > 0 && stack_p + n < INTERPRETER_STACK_SIZE);
-		VALUE *mem = &stack[stack_p];
-		stack_p += n;
-		insns[insn] = (VALUE)mem;
-		return (VALUE)mem;
-	    }
-
-	case Instruction::Store:
-	    {
-		StoreInst *store = static_cast<StoreInst *>(insn);
-		Value *slot = store->getOperand(1);
-		GetElementPtrInst *ptr = dyn_cast<GetElementPtrInst>(slot);
-		if (ptr == NULL) {
-		    break;
-		}
-		if (ptr->getNumIndices() != 1) {
-		    break;
-		}
-		const size_t off = get_const_int(*ptr->idx_begin());
-		VALUE storage = interpret_instruction(cast<AllocaInst>
-			(ptr->getPointerOperand()));
-		VALUE val = interpret_value(store->getOperand(0));
-		((VALUE *)storage)[off] = val;
-		return val;
-	    }
-
-	// Evaluated later.
-	case Instruction::GetElementPtr:
-	    return Qnil;
-    }
-
-    oops("unrecognized instruction:", insn);
-}
-
-VALUE
-RoxorInterpreter::interpret_value(Value *val)
-{
-    unsigned val_id = val->getValueID();
-    switch (val_id) {
-	case Value::ConstantPointerNullVal:
-	    return 0;
-
-	case Value::ConstantExprVal:
-	    val = static_cast<ConstantExpr *>(val)->getOperand(0);
-	    // fall through
-	case Value::ConstantIntVal:
-	    {
-		ConstantInt *ci = static_cast<ConstantInt *>(val);
-		const unsigned w = ci->getBitWidth();
-#if __LP64__
-		if (w > 64) {
-		    break;
-		}
-#else
-		if (w > 32) {
-		    break;
-		}
-#endif
-		return ci->getZExtValue();
-	    }
-
-	case Value::ArgumentVal:
-	    switch (static_cast<Argument *>(val)->getArgNo()) {
-		case 0:
-		    return self_arg;
-		case 1:
-		    return (VALUE)sel_arg;
-	    }
-	    break;
-
-	default:
-	    if (val_id >= Value::InstructionVal) {
-		return interpret_instruction(static_cast<Instruction *>(val));
-	    }
-	    break;
-    }
-
-    oops("unrecognized value:", val);
-}
-
-VALUE
-RoxorInterpreter::interpret_basicblock(BasicBlock *bb)
-{
-    for (BasicBlock::iterator insn = bb->begin(); insn != bb->end(); ++insn) {
-	Instruction *i = &*insn;
-	VALUE v = interpret_instruction(i);
-	if (i->isTerminator()) {	
-	    return v;
-	}
-    }
-
-    oops("malformed block:", bb);
-}
-
-VALUE
-RoxorInterpreter::interpret(Function *func, VALUE self, SEL sel)
-{
-    self_arg = self;
-    sel_arg = sel;
-    stack_p = 0;
-    insns.clear();
-
-    BasicBlock &b = func->getEntryBlock();
-    return interpret_basicblock(&b);
-}
-
-#endif // !MACRUBY_STATIC

Deleted: MacRuby/trunk/interpreter.h
===================================================================
--- MacRuby/trunk/interpreter.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/interpreter.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,53 +0,0 @@
-/*
- * MacRuby Interpreter.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __INTERPRETER_H_
-#define __INTERPRETER_H_
-
-#if defined(__cplusplus)
-
-#if !defined(MACRUBY_STATIC)
-
-class RoxorInterpreter {
-    public:
-	static RoxorInterpreter *shared;
-
-	RoxorInterpreter(void);
-	~RoxorInterpreter(void); 
-
-	VALUE interpret(Function *func, VALUE self, SEL sel);
-
-	bool frame_at_index(unsigned int idx, void *addr, std::string *name,
-		std::string *path, unsigned int *line);	
-
-    private:
-	VALUE self_arg;
-	SEL sel_arg;
-	VALUE *stack;
-	unsigned int stack_p;
-#define INTERPRETER_STACK_SIZE	1000
-	std::map<Instruction *, VALUE> insns;
-	class Frame {
-	    public:
-		std::string name;
-		std::string path;
-		unsigned int line;
-	};
-	std::vector<Frame> frames;
-
-	VALUE interpret_basicblock(BasicBlock *bb);
-	VALUE interpret_instruction(Instruction *insn);
-	VALUE interpret_value(Value *val);
-	VALUE interpret_call(CallInst *call);
-};
-
-#endif // !MACRUBY_STATIC
-
-#endif // __cplusplus
-
-#endif // __INTERPRETER_H_

Deleted: MacRuby/trunk/io.c
===================================================================
--- MacRuby/trunk/io.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/io.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,5073 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's io.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/io.h"
-#include "ruby/util.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "objc.h"
-#include "id.h"
-#include "encoding.h"
-
-#include <errno.h>
-#include <paths.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <copyfile.h>
-
-#include <sys/select.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/syscall.h>
-#include <spawn.h>
-
-#define IS_FD_OF_STDIO(x) (x <= 2)
-#define CLOSE_FD(fd)					\
-    do {						\
-	if (!IS_FD_OF_STDIO(fd)) {			\
-	    close(fd);					\
-	}						\
-    }							\
-    while (0)
-
-char ***_NSGetEnviron();
-
-extern void Init_File(void);
-
-VALUE rb_cIO;
-VALUE rb_eEOFError;
-VALUE rb_eIOError;
-
-VALUE rb_stdin = 0, rb_stdout = 0, rb_stderr = 0;
-VALUE rb_deferr;		/* rescue VIM plugin */
-static VALUE orig_stdout, orig_stderr;
-
-// TODO: After Object#untrusted? and Object#trusted? get implemented,
-// place the appropriate checks on #inspect, #reopen, #close, #close_read,
-// and #close_write.
-
-VALUE rb_output_fs;
-VALUE rb_rs;
-VALUE rb_output_rs;
-VALUE rb_default_rs;
-
-static VALUE argf;
-
-static ID id_write, id_read, id_getc, id_flush, id_encode, id_readpartial;
-
-struct argf {
-    VALUE filename, current_file;
-    int gets_lineno;
-    int init_p, next_p;
-    VALUE lineno;
-    VALUE argv;
-    char *inplace;
-    int binmode;
-    rb_encoding *enc, *enc2;
-};
-
-struct foreach_arg {
-    int argc;
-    VALUE *argv;
-    VALUE io;
-};
-
-#define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
-#define ARGF argf_of(argf)
-
-static VALUE
-pop_last_hash(int *argc_p, VALUE *argv)
-{
-    VALUE last, tmp;
-    if (*argc_p == 0) {
-	return Qnil;
-    }
-    last = argv[*argc_p-1];
-    tmp = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
-    if (NIL_P(tmp)) {
-	return Qnil;
-    }
-    (*argc_p)--;
-    return tmp;
-}
-
-static VALUE
-rb_io_get_io(VALUE io)
-{
-    return rb_convert_type(io, T_FILE, "IO", "to_io");
-}
-
-static VALUE
-rb_io_check_io(VALUE io)
-{
-    return rb_check_convert_type(io, T_FILE, "IO", "to_io");
-}
-
-static int
-convert_mode_string_to_fmode(VALUE rstr)
-{
-    int fmode = 0;
-    const char *m = RSTRING_PTR(rstr);
-
-    switch (*m++) {
-	case 'r':
-	    fmode |= FMODE_READABLE;
-	    break;
-	case 'w':
-	    fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
-	    break;
-	case 'a':
-	    fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;	
-	    break;
-	default:
-error:
-	    rb_raise(rb_eArgError, "invalid access mode %s", m);
-    }
-
-    while (*m) {
-	switch (*m++) {
-	    case 'b':
-		fmode |= FMODE_BINMODE;
-		break;
-	    case 't':
-		fmode |= FMODE_TEXTMODE;
-		break;
-	    case '+':
-		fmode |= FMODE_READWRITE;
-		break;
-	    case ':':
-		goto finished;
-	    default:
-		rb_raise(rb_eArgError, "invalid access mode %s", m);
-	}
-    }
-
-finished:
-    if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
-	goto error;
-
-    return fmode;
-}
-
-static int
-convert_fmode_to_oflags(int fmode)
-{
-    int oflags = 0;
-
-    switch (fmode & FMODE_READWRITE) {
-	case FMODE_READABLE:
-	    oflags |= O_RDONLY;
-	    break;
-	case FMODE_WRITABLE:
-	    oflags |= O_WRONLY;
-	    break;
-	case FMODE_READWRITE:
-	    oflags |= O_RDWR;
-	    break;
-    }
-
-    if (fmode & FMODE_APPEND) {
-	oflags |= O_APPEND;
-    }
-    if (fmode & FMODE_TRUNC) {
-	oflags |= O_TRUNC;
-    }
-    if (fmode & FMODE_CREATE) {
-	oflags |= O_CREAT;
-    }
-
-    return oflags;
-}
-
-static int
-convert_mode_string_to_oflags(VALUE s) 
-{
-    if (TYPE(s) == T_FIXNUM) {
-	return NUM2INT(s);
-    }
-    StringValue(s);
-    return convert_fmode_to_oflags(convert_mode_string_to_fmode(s));
-}
-
-static int
-convert_oflags_to_fmode(int mode)
-{
-    int flags = 0;
-
-    switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
-	case O_RDONLY:
-	    flags = FMODE_READABLE;
-	    break;
-	case O_WRONLY:
-	    flags = FMODE_WRITABLE;
-	    break;
-	case O_RDWR:
-	    flags = FMODE_READWRITE;
-	    break;
-    }
-
-    if (mode & O_APPEND) {
-	flags |= FMODE_APPEND;
-    }
-    if (mode & O_CREAT) {
-	flags |= FMODE_CREATE;
-    }
-
-    return flags;
-}
-
-void
-rb_eof_error(void)
-{
-    rb_raise(rb_eEOFError, "end of file reached");
-}
-
-VALUE
-rb_io_taint_check(VALUE io)
-{
-    if (!OBJ_TAINTED(io) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
-    }
-    rb_check_frozen(io);
-    return io;
-}
-
-static bool
-rb_io_is_open(rb_io_t *io_struct) 
-{
-    return io_struct->fd != -1;
-}
-
-static void
-rb_io_assert_open(rb_io_t *io_struct)
-{
-    if (!rb_io_is_open(io_struct)) {
-	rb_raise(rb_eIOError,
-		"cannot perform that operation on a closed stream");
-    }
-}
-
-static bool
-rb_io_is_closed_for_reading(rb_io_t *io_struct) 
-{
-    return io_struct->read_fd == -1;
-}
-
-static bool
-rb_io_is_closed_for_writing(rb_io_t *io_struct) 
-{
-    return io_struct->write_fd == -1;
-}
-
-static bool
-rb_io_is_readable(rb_io_t *io_struct)
-{
-    return !rb_io_is_closed_for_reading(io_struct);
-}
-
-static bool
-rb_io_is_writable(rb_io_t *io_struct)
-{
-    return !rb_io_is_closed_for_writing(io_struct);
-}
-
-static int
-rb_io_calculate_mode_flags(rb_io_t *io_struct)
-{
-    int flags = 0;
-    if (rb_io_is_readable(io_struct)) {
-	flags |= FMODE_READABLE;
-    }
-    if (rb_io_is_writable(io_struct)) {
-	flags |= FMODE_WRITABLE;
-    }
-    return flags;
-}
-
-static VALUE
-io_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(io, struct RFile);
-    OBJSETUP(io, klass, T_FILE);
-    GC_WB(&io->fptr, ALLOC(rb_io_t));
-    io->fptr->fd = -1;
-    io->fptr->read_fd = -1;
-    io->fptr->write_fd = -1;
-    io->fptr->pid = -1;
-    return (VALUE)io;
-}
-
-static void 
-prepare_io_from_fd(rb_io_t *io_struct, int fd, int mode)
-{
-    // While getting rid of the FMODE_* constants and replacing them with the 
-    // POSIX constants would be very nice, it would be a mistake on Darwin,
-    // as O_RDONLY|O_WRONLY != O_RDWR, whereas FMODE_READABLE|FMODE_WRITABLE = 
-    // FMODE_READWRITE. As such, we have to redefine a whole lot of system-wide
-    // constants, which sucks. But we don't have any other option.
-
-    bool read = false, write = false;
-    switch (mode & FMODE_READWRITE) {
-	case FMODE_READABLE:
-	    read = true;
-	    break;
-
-	case FMODE_WRITABLE:
-	    write = true;
-	    break;
-
-	case FMODE_READWRITE:
-	    read = write = true;
-	    break;
-    }
-    assert(read || write);
-
-    if (read) {
-	io_struct->read_fd = fd;
-    }
-
-    if (write) {
-	io_struct->write_fd = fd;
-    }
- 
-    io_struct->fd = fd;
-    io_struct->pid = -1;
-    io_struct->mode = mode;
-}
-
-static void
-io_close(rb_io_t *io_struct, bool close_read, bool close_write)
-{
-    // TODO we must check the return value of close(2) and appropriately call
-    // rb_sys_fail().
-    if (close_read) {
-	if (io_struct->read_fd != io_struct->write_fd) {
-	    CLOSE_FD(io_struct->read_fd);
-	}
-	else {
-	    io_struct->fd = -1;
-	}
-	io_struct->read_fd = -1;
-    }
-    if (close_write) {
-	if (io_struct->write_fd != io_struct->read_fd) {
-	    CLOSE_FD(io_struct->write_fd);
-	}
-	else {
-	    io_struct->fd = -1;
-	}
-	io_struct->write_fd = -1;
-    }
-    if (io_struct->pid != -1) {
-	if (close_read && close_write) {
-	    rb_last_status_set(0, io_struct->pid);
-	    rb_syswait(io_struct->pid);
-	    io_struct->pid = -1;
-	}
-    }
-    if (io_struct->fd != -1 && io_struct->read_fd == -1
-	    && io_struct->write_fd == -1) {
-	CLOSE_FD(io_struct->fd);
-	io_struct->fd = -1;
-    }
-}
-
-static VALUE
-prep_io(int fd, int mode, VALUE klass)
-{
-    VALUE io = io_alloc(klass, 0);
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    prepare_io_from_fd(io_struct, fd, mode);
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.syswrite(string)   => integer
- *
- *  Writes the given string to <em>ios</em> using a low-level write.
- *  Returns the number of bytes written. Do not mix with other methods
- *  that write to <em>ios</em> or you may get unpredictable results.
- *  Raises <code>SystemCallError</code> on error.
- *
- *     f = File.new("out", "w")
- *     f.syswrite("ABCDEF")   #=> 6
- */
-
-
-static VALUE
-rb_io_syswrite(VALUE io, SEL sel, VALUE data)
-{
-    rb_secure(4);
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_writable(io_struct);
-
-    data = rb_str_bstr(rb_obj_as_string(data));
-    
-    if (io_struct->buf && CFDataGetLength(io_struct->buf) > 0) {
-	rb_warn("Calling #syswrite on buffered I/O may lead to unexpected results");
-    }
-    
-    const uint8_t *buffer = rb_bstr_bytes(data);
-    const long length = rb_bstr_length(data);
-    
-    if (length == 0) {
-        return INT2FIX(0);
-    }
-    
-    ssize_t result = write(io_struct->write_fd, buffer, length);
-    if (result == -1) {
-	rb_sys_fail("write(2) failed.");
-    }
-    
-    return LONG2FIX(result);
-}
-
-/*
- *  call-seq:
- *     ios.write(string)    => integer
- *
- *  Writes the given string to <em>ios</em>. The stream must be opened
- *  for writing. If the argument is not a string, it will be converted
- *  to a string using <code>to_s</code>. Returns the number of bytes
- *  written.
- *
- *     count = $stdout.write( "This is a test\n" )
- *     puts "That was #{count} bytes of data"
- *
- *  <em>produces:</em>
- *
- *     This is a test
- *     That was 15 bytes of data
- */
-
-static VALUE
-io_write(VALUE io, SEL sel, VALUE data)
-{
-    rb_secure(4);
-
-    VALUE tmp = rb_io_check_io(io);
-    if (NIL_P(tmp)) {
-	// receiver is not IO, dispatch the write method on it
-	return rb_vm_call(io, selWrite, 1, &data);
-    }
-    io = tmp;
-
-    data = rb_obj_as_string(data);
-    data = rb_str_bstr(data);
-    const uint8_t *buffer = rb_bstr_bytes(data);
-    const long length = rb_bstr_length(data);
-
-    if (length == 0) {
-        return INT2FIX(0);
-    }
-
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_writable(io_struct);
-
-    ssize_t code = write(io_struct->write_fd, buffer, length);
-    if (code == -1) {
-	rb_sys_fail("write() failed");
-    }
-
-    if (io_struct->buf != NULL && CFDataGetLength(io_struct->buf) > 0) {
-	if (length > CFDataGetLength(io_struct->buf) - io_struct->buf_offset) {
-	    CFDataIncreaseLength(io_struct->buf, length);
-	}
-	UInt8 *data = CFDataGetMutableBytePtr(io_struct->buf);
-	memcpy(data + io_struct->buf_offset, buffer, length);
-	io_struct->buf_offset += length;
-    }
-
-    return LONG2FIX(code);
-}
-
-/*
- *  call-seq:
- *     ios << obj     => ios
- *
- *  String Output---Writes <i>obj</i> to <em>ios</em>.
- *  <i>obj</i> will be converted to a string using
- *  <code>to_s</code>.
- *
- *     $stdout << "Hello " << "world!\n"
- *
- *  <em>produces:</em>
- *
- *     Hello world!
- */
-
-
-VALUE
-rb_io_addstr(VALUE io, SEL sel, VALUE str)
-{
-    rb_io_write(io, str);
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.flush    => ios
- *
- *  Flushes any buffered data within <em>ios</em> to the underlying
- *  operating system (note that this is Ruby internal buffering only;
- *  the OS may buffer the data as well).
- *
- *     $stdout.print "no newline"
- *     $stdout.flush
- *
- *  <em>produces:</em>
- *
- *     no newline
- */
-
-VALUE
-rb_io_flush(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_open(io_struct);
-    // IO#flush on MacRuby is a no-op, as MacRuby does not buffer its IO
-    // streams internally
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.pos     => integer
- *     ios.tell    => integer
- *
- *  Returns the current offset (in bytes) of <em>ios</em>.
- *
- *     f = File.new("testfile")
- *     f.pos    #=> 0
- *     f.gets   #=> "This is line one\n"
- *     f.pos    #=> 17
- */
-
-
-static off_t
-ltell(int fd)
-{
-    off_t code = lseek(fd, 0, SEEK_CUR);
-    if (code == -1) {
-	rb_sys_fail("lseek() failed");
-    }
-    return code;
-}
-
-static VALUE
-rb_io_tell(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_check_closed(io_struct);
-
-    return OFFT2NUM(ltell(io_struct->fd));
-}
-
-static VALUE
-rb_io_seek(VALUE io, VALUE offset, int whence)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_check_closed(io_struct);
-    off_t off = NUM2OFFT(offset);
-//    if (whence == SEEK_CUR) {
-//	off += ltell(io_struct->read_fd);
-//    }
-    const off_t code = lseek(io_struct->fd, off, whence);
-    if (code == -1) {
-	rb_sys_fail("lseek() failed");
-    }
-    if (io_struct->buf != NULL) {
-	io_struct->buf_offset = code;
-    }
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     ios.sysseek(offset, whence=SEEK_SET)   => integer
- *
- *  Seeks to a given <i>offset</i> in the stream according to the value
- *  of <i>whence</i> (see <code>IO#seek</code> for values of
- *  <i>whence</i>). Returns the new offset into the file.
- *
- *     f = File.new("testfile")
- *     f.sysseek(-13, IO::SEEK_END)   #=> 53
- *     f.sysread(10)                  #=> "And so on."
- */
-
-
-/*
- *  call-seq:
- *     ios.seek(amount, whence=SEEK_SET) -> 0
- *
- *  Seeks to a given offset <i>anInteger</i> in the stream according to
- *  the value of <i>whence</i>:
- *
- *    IO::SEEK_CUR  | Seeks to _amount_ plus current position
- *    --------------+----------------------------------------------------
- *    IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
- *                  | want a negative value for _amount_)
- *    --------------+----------------------------------------------------
- *    IO::SEEK_SET  | Seeks to the absolute location given by _amount_
- *
- *  Example:
- *
- *     f = File.new("testfile")
- *     f.seek(-13, IO::SEEK_END)   #=> 0
- *     f.readline                  #=> "And so on...\n"
- */
-
-static VALUE
-rb_io_seek_m(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE offset, ptrname;
-    int whence = SEEK_SET;
- 
-    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
-        whence = NUM2INT(ptrname);
-    }
- 
-    return rb_io_seek(io, offset, whence);
-}
-
-/*
- *  call-seq:
- *     ios.pos = integer    => integer
- *
- *  Seeks to the given position (in bytes) in <em>ios</em>.
- *
- *     f = File.new("testfile")
- *     f.pos = 17
- *     f.gets   #=> "This is line two\n"
- */
-
-static VALUE
-rb_io_set_pos(VALUE io, SEL sel, VALUE offset)
-{
-    return rb_io_seek(io, offset, SEEK_SET);
-}
-
-/*
- *  call-seq:
- *     ios.rewind    => 0
- *
- *  Positions <em>ios</em> to the beginning of input, resetting
- *  <code>lineno</code> to zero.
- *
- *     f = File.new("testfile")
- *     f.readline   #=> "This is line one\n"
- *     f.rewind     #=> 0
- *     f.lineno     #=> 0
- *     f.readline   #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_rewind(VALUE io, SEL sel)
-{
-    ExtractIOStruct(io)->lineno = 0;
-    return rb_io_seek(io, INT2FIX(0), SEEK_SET);
-}
-
-/*
- *  call-seq:
- *     ios.eof     => true or false
- *     ios.eof?    => true or false
- *
- *  Returns true if <em>ios</em> is at end of file that means
- *  there are no more data to read.
- *  The stream must be opened for reading or an <code>IOError</code> will be
- *  raised.
- *
- *     f = File.new("testfile")
- *     dummy = f.readlines
- *     f.eof   #=> true
- *
- *  If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
- *  blocks until the other end sends some data or closes it.
- *
- *     r, w = IO.pipe
- *     Thread.new { sleep 1; w.close }
- *     r.eof?  #=> true after 1 second blocking
- *
- *     r, w = IO.pipe
- *     Thread.new { sleep 1; w.puts "a" }
- *     r.eof?  #=> false after 1 second blocking
- *
- *     r, w = IO.pipe
- *     r.eof?  # blocks forever
- *
- *  Note that <code>IO#eof?</code> reads data to a input buffer.
- *  So <code>IO#sysread</code> doesn't work with <code>IO#eof?</code>.
- */
-
-static long rb_io_read_internal(rb_io_t *io_struct, UInt8 *buffer, long len);
-
-VALUE
-rb_io_eof(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_readable(io_struct);
-
-    if (rb_io_read_pending(io_struct)) {
-	return Qfalse;
-    }
-
-    UInt8 c;
-    const off_t pos = lseek(io_struct->fd, 0, SEEK_CUR);
-    if (rb_io_read_internal(io_struct, &c, 1) != 1) {
-	return Qtrue;
-    }
-
-    lseek(io_struct->fd, pos, SEEK_SET);
-    if (io_struct->buf != NULL) {
-	io_struct->buf_offset--;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     ios.sync    => true or false
- *
- *  Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
- *  true, all output is immediately flushed to the underlying operating
- *  system and is not buffered by Ruby internally. See also
- *  <code>IO#fsync</code>.
- *
- *     f = File.new("testfile")
- *     f.sync   #=> false
- */
-
-static VALUE
-rb_io_sync(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_open(io_struct);
-    return (io_struct->mode & FMODE_SYNC) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     ios.sync = boolean   => boolean
- *
- *  Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
- *  When sync mode is true, all output is immediately flushed to the
- *  underlying operating system and is not buffered internally. Returns
- *  the new state. See also <code>IO#fsync</code>.
- *
- *     f = File.new("testfile")
- *     f.sync = true
- *
- *  <em>(produces no output)</em>
- */
-
-static VALUE
-rb_io_set_sync(VALUE io, SEL sel, VALUE mode)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_open(io_struct);
-    if (RTEST(mode)) {
-	io_struct->mode |= FMODE_SYNC;
-    }
-    else {
-	io_struct->mode &= ~FMODE_SYNC;
-    }
-    return mode;
-}
-
-/*
- *  call-seq:
- *     ios.fsync   => 0 or nil
- *
- *  Immediately writes all buffered data in <em>ios</em> to disk.
- *  Returns <code>nil</code> if the underlying operating system does not
- *  support <em>fsync(2)</em>. Note that <code>fsync</code> differs from
- *  using <code>IO#sync=</code>. The latter ensures that data is flushed
- *  from Ruby's buffers, but doesn't not guarantee that the underlying
- *  operating system actually writes it to disk.
- */
-
-static VALUE
-rb_io_fsync(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_writable(io_struct);
-    if (fsync(io_struct->fd) < 0) {
-	rb_sys_fail("fsync() failed.");
-    }
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     ios.fileno    => fixnum
- *     ios.to_i      => fixnum
- *
- *  Returns an integer representing the numeric file descriptor for
- *  <em>ios</em>.
- *
- *     $stdin.fileno    #=> 0
- *     $stdout.fileno   #=> 1
- */
-
-static VALUE
-rb_io_fileno(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_open(io_struct);
-    return INT2FIX(io_struct->fd);
-}
-
-
-/*
- *  call-seq:
- *     ios.pid    => fixnum
- *
- *  Returns the process ID of a child process associated with
- *  <em>ios</em>. This will be set by <code>IO::popen</code>.
- *
- *     pipe = IO.popen("-")
- *     if pipe
- *       $stderr.puts "In parent, child pid is #{pipe.pid}"
- *     else
- *       $stderr.puts "In child, pid is #{$$}"
- *     end
- *
- *  <em>produces:</em>
- *
- *     In child, pid is 26209
- *     In parent, child pid is 26209
- */
-
-static VALUE
-rb_io_pid(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_open(io_struct);
-    return io_struct->pid == -1 ? Qnil : INT2FIX(io_struct->pid);
-}
-
-
-/*
- * call-seq:
- *   ios.inspect   => string
- *
- * Return a string describing this IO object.
- */
-
-static VALUE
-rb_io_inspect(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    if (io_struct == NULL || io_struct->path == 0) {
-        return rb_any_to_s(io);
-    }
-
-    VALUE str = rb_str_new2("#<");
-    rb_str_cat2(str, rb_obj_classname(io));
-    rb_str_cat2(str, ":");
-    rb_str_concat(str, io_struct->path);
-    if (!rb_io_is_open(io_struct)) {
-	rb_str_cat2(str, " (closed)>");
-    }
-    else {
-	rb_str_cat2(str, ">");
-    }
-    return str;
-}
-
-/*
- *  call-seq:
- *     ios.to_io -> ios
- *
- *  Returns <em>ios</em>.
- */
-
-static VALUE
-rb_io_to_io(VALUE io, SEL sel)
-{
-    return io;
-}
-
-static bool
-__rb_io_wait_readable(int fd)
-{
-    if (errno == EINTR) {
-	fd_set readset;
-	FD_ZERO(&readset);
-	FD_SET(fd, &readset);
-	return select(fd + 1, &readset, NULL, NULL, NULL) >= 0;
-    }
-    return false;
-}
-
-// Note: not bool since it's exported in a public header which does not
-// include stdbool.
-int
-rb_io_wait_readable(int fd)
-{
-    return __rb_io_wait_readable(fd);
-}
-
-// Note: not bool since it's exported in a public header which does not
-// include stdbool.
-int
-rb_io_wait_writable(int fd)
-{
-    // TODO
-    return false;
-}
-
-// Note: not bool since it's exported in a public header which does not
-// include stdbool.
-int
-rb_io_read_pending(rb_io_t *io_struct)
-{
-    return io_struct->buf != NULL && CFDataGetLength(io_struct->buf) > 0;
-}
-
-static long
-read_internal(int fd, UInt8 *buffer, long len)
-{
-    long code;
-
-retry:
-    code = read(fd, buffer, len);
-    if (code == -1) {
-	if (__rb_io_wait_readable(fd)) {
-	    goto retry;
-	}
-	rb_sys_fail("read() failed");
-    }
-    return code;
-}
-
-static void
-rb_io_create_buf(rb_io_t *io_struct)
-{
-    if (io_struct->buf == NULL) {
-	CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
-	GC_WB(&io_struct->buf, data);
-	CFMakeCollectable(data);
-    }
-}
-
-static void
-rb_io_read_update(rb_io_t *io_struct, long len)
-{
-    io_struct->buf_offset += len;
-
-    lseek(io_struct->read_fd, io_struct->buf_offset, SEEK_SET);
-
-    if (io_struct->buf_offset == CFDataGetLength(io_struct->buf)) {
-	CFDataSetLength(io_struct->buf, 0);
-	io_struct->buf_offset = 0;
-    }
-}
-
-static long
-rb_io_read_internal(rb_io_t *io_struct, UInt8 *buffer, long len)
-{
-    assert(io_struct->read_fd != -1);
-
-    if (io_struct->buf == NULL || CFDataGetLength(io_struct->buf) == 0) {
-	struct stat buf;
-	if (fstat(io_struct->read_fd, &buf) == -1 || buf.st_size == 0
-		|| lseek(io_struct->read_fd, 0, SEEK_CUR) > 0) {
-	    // Either a pipe, stdio, or a regular file that was seeked.
-	    return len == 0
-		? 0 : read_internal(io_struct->read_fd, buffer, len);
-	}
-
-	// TODO don't pre-read more than a certain threshold...
-	const long size = buf.st_size;
-	rb_io_create_buf(io_struct);
-	CFDataSetLength(io_struct->buf, size);
-
-	const long s = read_internal(io_struct->read_fd,
-		CFDataGetMutableBytePtr(io_struct->buf), size);
-	CFDataSetLength(io_struct->buf, s);
-    }
-
-    const long s = CFDataGetLength(io_struct->buf);
-    if (s == 0 || len == 0) {
-	return 0;
-    }
-
-    const long n = len > s - io_struct->buf_offset
-	? s - io_struct->buf_offset : len;
-    memcpy(buffer, CFDataGetBytePtr(io_struct->buf) + io_struct->buf_offset, n);
-
-    rb_io_read_update(io_struct, n);
-
-    return n;
-}
-
-static VALUE 
-rb_io_read_all(rb_io_t *io_struct, VALUE outbuf) 
-{
-    struct stat st;
-    long bufsize = 512;
-    if (fstat(io_struct->read_fd, &st) == 0 && S_ISREG(st.st_mode)) {
-	const off_t pos = lseek(io_struct->read_fd, 0, SEEK_CUR);
-	if (st.st_size >= pos && pos >= 0) {
-	    bufsize = st.st_size - pos;
-	    if (bufsize > LONG_MAX) {
-		rb_raise(rb_eIOError, "file too big for single read");
-	    }
-	}
-    }
-
-    outbuf = rb_str_bstr(outbuf);
-    long bytes_read = 0;
-    const long original_position = rb_bstr_length(outbuf);
-
-    while (true) {
-	rb_bstr_resize(outbuf, original_position + bytes_read + bufsize);
-	uint8_t *bytes = rb_bstr_bytes(outbuf) + original_position + bytes_read;
-        const long last_read = rb_io_read_internal(io_struct, bytes, bufsize);
-        bytes_read += last_read;
-	if (last_read == 0) {
-	    break;
-	}
-    }
-
-    rb_bstr_set_length(outbuf, original_position + bytes_read);
-    return outbuf; 
-}
-
-long
-rb_io_primitive_read(rb_io_t *io_struct, char *buffer, long len)
-{
-    return rb_io_read_internal(io_struct, (UInt8 *)buffer, len);
-}
-
-/*
- *  call-seq:
- *     ios.read_nonblock(maxlen)              => string
- *     ios.read_nonblock(maxlen, outbuf)      => outbuf
- *
- *  Reads at most <i>maxlen</i> bytes from <em>ios</em> using
- *  read(2) system call after O_NONBLOCK is set for
- *  the underlying file descriptor.
- *
- *  If the optional <i>outbuf</i> argument is present,
- *  it must reference a String, which will receive the data.
- *
- *  read_nonblock just calls read(2).
- *  It causes all errors read(2) causes: EAGAIN, EINTR, etc.
- *  The caller should care such errors.
- *
- *  read_nonblock causes EOFError on EOF.
- *
- *  If the read buffer is not empty,
- *  read_nonblock reads from the buffer like readpartial.
- *  In this case, read(2) is not called.
- *
- */
-
-#if 0
-static VALUE
-io_read_nonblock(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    return Qnil;
-}
-#else
-# define io_read_nonblock rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     ios.write_nonblock(string)   => integer
- *
- *  Writes the given string to <em>ios</em> using
- *  write(2) system call after O_NONBLOCK is set for
- *  the underlying file descriptor.
- *
- *  write_nonblock just calls write(2).
- *  It causes all errors write(2) causes: EAGAIN, EINTR, etc.
- *  The result may also be smaller than string.length (partial write).
- *  The caller should care such errors and partial write.
- *
- *  If the write buffer is not empty, it is flushed at first.
- *
- */
-
-#if 0
-static VALUE
-rb_io_write_nonblock(VALUE io, SEL sel, VALUE str)
-{
-    return Qnil;
-}
-#else
-# define rb_io_write_nonblock rb_f_notimplement
-#endif
-
-/*
- *  call-seq:
- *     ios.sysread(integer[, outbuf])    => string
- *
- *  Reads <i>integer</i> bytes from <em>ios</em> using a low-level
- *  read and returns them as a string. Do not mix with other methods
- *  that read from <em>ios</em> or you may get unpredictable results.
- *  If the optional <i>outbuf</i> argument is present, it must reference
- *  a String, which will receive the data.
- *  Raises <code>SystemCallError</code> on error and
- *  <code>EOFError</code> at end of file.
- *
- *     f = File.new("testfile")
- *     f.sysread(16)   #=> "This is line one"
- */
-
-static VALUE
-rb_io_sysread(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE count, buffer;
-    rb_scan_args(argc, argv, "11", &count, &buffer);
-    const long to_read = NUM2LONG(count);
-
-    rb_io_t *io = ExtractIOStruct(self);
-    rb_io_assert_readable(io);
-
-    // TODO: throw error if the buffer is not empty;
-
-    if (!NIL_P(buffer)) {
-	// TODO: throw an error if the provided string can't be modified in place
-	buffer = rb_str_bstr(rb_obj_as_string(buffer));
-    }
-    else {
-	buffer = rb_bstr_new();
-    }
-    rb_bstr_resize(buffer, to_read);
-
-    if (to_read == 0) {
-	return buffer;
-    }
-
-    uint8_t *bytes = rb_bstr_bytes(buffer);
-
-    const long r = read(io->read_fd, bytes, (size_t)to_read);
-    if (r == -1) {
-	rb_sys_fail("read(2) failed.");
-    }
-    // Resize the buffer to whatever was read
-    rb_bstr_resize(buffer, r);
-
-    if (r == 0 && to_read > 0) {
-	rb_eof_error();
-    }
-
-    return buffer;
-}
-
-/*
- *  call-seq:
- *     ios.read([length [, buffer]])    => string, buffer, or nil
- *
- *  Reads at most <i>length</i> bytes from the I/O stream, or to the
- *  end of file if <i>length</i> is omitted or is <code>nil</code>.
- *  <i>length</i> must be a non-negative integer or nil.
- *  If the optional <i>buffer</i> argument is present, it must reference
- *  a String, which will receive the data.
- *
- *  At end of file, it returns <code>nil</code> or <code>""</code>
- *  depend on <i>length</i>.
- *  <code><i>ios</i>.read()</code> and
- *  <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
- *  <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns nil.
- *
- *  <code><i>ios</i>.read(0)</code> returns <code>""</code>.
- *
- *     f = File.new("testfile")
- *     f.read(16)   #=> "This is line one"
- */
-
-static VALUE
-io_read(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE len, outbuf;
-    rb_scan_args(argc, argv, "02", &len, &outbuf);
-
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_readable(io_struct);
-
-    bool outbuf_created = false;
-    if (NIL_P(outbuf)) {
-	outbuf = rb_bstr_new();
-	outbuf_created = true;
-    }
-    else {
-	StringValue(outbuf);
-	outbuf = rb_str_bstr(outbuf);
-	rb_str_set_len(outbuf, 0);
-    }
-
-    if (NIL_P(len)) {
-	rb_io_read_all(io_struct, outbuf);
-	if (outbuf_created) {
-	    rb_str_force_encoding(outbuf, rb_encodings[ENCODING_UTF8]);
-	}
-	return outbuf;
-    }
-
-    const long size = FIX2LONG(len);
-    if (size < 0) {
-	rb_raise(rb_eArgError, "negative length %ld given", size);
-    }
-    if (size == 0) {
-	return rb_str_new2("");
-    }
-
-    if (size > 1000000000) {
-	rb_raise(rb_eArgError, "given size `%ld' is too big", size);
-    }
-
-    rb_bstr_resize(outbuf, size);
-    uint8_t *bytes = rb_bstr_bytes(outbuf);
-
-    const long data_read = rb_io_read_internal(io_struct, bytes, size);
-    rb_bstr_set_length(outbuf, data_read);
-
-    if (data_read == 0) {
-	return Qnil;
-    }
-
-    return outbuf;
-}
-
-/*
- *  call-seq:
- *     ios.readpartial(maxlen)              => string
- *     ios.readpartial(maxlen, outbuf)      => outbuf
- *
- *  Reads at most <i>maxlen</i> bytes from the I/O stream.
- *  It blocks only if <em>ios</em> has no data immediately available.
- *  It doesn't block if some data available.
- *  If the optional <i>outbuf</i> argument is present,
- *  it must reference a String, which will receive the data.
- *  It raises <code>EOFError</code> on end of file.
- *
- *  readpartial is designed for streams such as pipe, socket, tty, etc.
- *  It blocks only when no data immediately available.
- *  This means that it blocks only when following all conditions hold.
- *  * the buffer in the IO object is empty.
- *  * the content of the stream is empty.
- *  * the stream is not reached to EOF.
- *
- *  When readpartial blocks, it waits data or EOF on the stream.
- *  If some data is reached, readpartial returns with the data.
- *  If EOF is reached, readpartial raises EOFError.
- *
- *  When readpartial doesn't blocks, it returns or raises immediately.
- *  If the buffer is not empty, it returns the data in the buffer.
- *  Otherwise if the stream has some content,
- *  it returns the data in the stream.
- *  Otherwise if the stream is reached to EOF, it raises EOFError.
- *
- *     r, w = IO.pipe           #               buffer          pipe content
- *     w << "abc"               #               ""              "abc".
- *     r.readpartial(4096)      #=> "abc"       ""              ""
- *     r.readpartial(4096)      # blocks because buffer and pipe is empty.
- *
- *     r, w = IO.pipe           #               buffer          pipe content
- *     w << "abc"               #               ""              "abc"
- *     w.close                  #               ""              "abc" EOF
- *     r.readpartial(4096)      #=> "abc"       ""              EOF
- *     r.readpartial(4096)      # raises EOFError
- *
- *     r, w = IO.pipe           #               buffer          pipe content
- *     w << "abc\ndef\n"        #               ""              "abc\ndef\n"
- *     r.gets                   #=> "abc\n"     "def\n"         ""
- *     w << "ghi\n"             #               "def\n"         "ghi\n"
- *     r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
- *     r.readpartial(4096)      #=> "ghi\n"     ""              ""
- *
- *  Note that readpartial behaves similar to sysread.
- *  The differences are:
- *  * If the buffer is not empty, read from the buffer instead of "sysread for buffered IO (IOError)".
- *  * It doesn't cause Errno::EAGAIN and Errno::EINTR.  When readpartial meets EAGAIN and EINTR by read system call, readpartial retry the system call.
- *
- *  The later means that readpartial is nonblocking-flag insensitive.
- *  It blocks on the situation IO#sysread causes Errno::EAGAIN as if the fd is blocking mode.
- *
- */
-
-static VALUE
-io_readpartial(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE maxlen, buffer;
-    rb_scan_args(argc, argv, "11", &maxlen, &buffer);
-    if (FIX2INT(maxlen) == 0) {
-	return rb_str_new2("");
-    }
-    else if (FIX2INT(maxlen) < 0) {
-	rb_raise(rb_eArgError, "negative numbers not valid");
-    }
-    VALUE read_data = io_read(io, sel, argc, argv);
-    if (NIL_P(read_data)) {
-	rb_eof_error();
-    }
-    return read_data;
-}
-
-static void
-prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *lim, VALUE io)
-{
-    VALUE sep, limit;
-
-    sep = limit = Qnil;
-    if (argc != 0) {
-	rb_scan_args(argc, argv, "02", &sep, &limit);
-    }
-
-    if (NIL_P(rb_rs)) {
-	// TODO: Get rid of this when the fix comes in for the $\ variable.
-	rb_rs = (VALUE)CFSTR("\n");
-    }
-
-    if (NIL_P(sep)) {
-	// no arguments were passed at all.
-	// FIXME: if you pass nil, it's suppose to read everything. that sucks.
-	if (argc == 0) {
-	    sep = rb_rs;
-	    limit = Qnil;
-	}
-    }
-    else {
-	if (TYPE(sep) != T_STRING) {
-	    // sep wasn't given, limit was.
-	    limit = sep;
-	    sep = rb_rs;
-	}
-	else if (RSTRING_LEN(sep) == 0) {
-	    sep = (VALUE)CFSTR("\n\n");
-	}
-    }
-
-    *rsp = sep;
-    *lim = NIL_P(limit) ? -1 : FIX2LONG(limit);
-}
-
-static VALUE
-rb_io_getline_1(VALUE sep, long line_limit, VALUE io)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    VALUE bstr = rb_bstr_new();
-
-    rb_io_assert_readable(io_struct);
-    if (NIL_P(sep)) {
-	if (line_limit != -1) {
-	    rb_bstr_resize(bstr, line_limit);
-	    uint8_t *bytes = rb_bstr_bytes(bstr);
-	    long r = rb_io_read_internal(io_struct, bytes, line_limit);
-	    rb_bstr_set_length(bstr, r);
-	}
-	else {
-	    rb_io_read_all(io_struct, bstr);
-	}
-	if (rb_bstr_length(bstr) == 0 && line_limit != 0) {
-	    return Qnil;
-	}
-    }
-    else if (line_limit != -1) {
-	rb_bstr_resize(bstr, line_limit);
-	uint8_t *bytes = rb_bstr_bytes(bstr);
-	long r = rb_io_read_internal(io_struct, bytes, line_limit);
-	if (r == 0 && line_limit != 0) {
-	    return Qnil;
-	}
-
-	CFRange range = CFStringFind((CFStringRef)bstr, (CFStringRef)sep, 0);
-	if (range.location != kCFNotFound) {
-	    rb_io_create_buf(io_struct);
-	    long rest_size = r - (range.location + 1);
-	    if (rest_size > 0 && line_limit > r) {
-		CFDataAppendBytes(io_struct->buf, bytes + range.location + 1,
-				  rest_size);
-	    }
-	    else {
-		io_struct->buf_offset -= rest_size;
-	    }
-	    r = range.location + 1;
-	}
-	// Resize the buffer to whatever was actually read (can be different
-	// from asked size).
-	rb_bstr_resize(bstr, r);
-    }
-    else {
-	const char *sepstr = RSTRING_PTR(sep);
-	const long seplen = RSTRING_LEN(sep);
-	assert(seplen > 0);
-
-	// Pre-cache if possible.
-	rb_io_read_internal(io_struct, NULL, 0);
-	if (io_struct->buf != NULL && CFDataGetLength(io_struct->buf) > 0) {
-	    // Read from cache (fast).
-	    const UInt8 *cache = CFDataGetMutableBytePtr(io_struct->buf)
-		+ io_struct->buf_offset;
-	    const long cache_len = CFDataGetLength(io_struct->buf)
-		- io_struct->buf_offset;
-	    const UInt8 *pos = cache;
-	    long data_read = 0;
-	    while (true) {
-		const UInt8 *tmp = memchr(pos, sepstr[0], cache_len);
-		if (tmp == NULL) {
-		    data_read = cache_len;
-		    break;
-		}
-		if (seplen == 1
-			|| memcmp(tmp + 1, &sepstr[1], seplen - 1) == 0) {
-		    data_read = tmp - cache + seplen;
-		    break;
-		}
-		pos = tmp + seplen;
-	    }
-	    if (data_read == 0) {
-		return Qnil;
-	    }
-
-	    rb_bstr_concat(bstr, cache, data_read);
-	    rb_io_read_update(io_struct, data_read);
-	}
-	else {
-	    // Read from IO (slow).
-	    long s = 512;
-	    long data_read = 0;
-	    rb_bstr_resize(bstr, s);
-
-	    uint8_t *buf = rb_bstr_bytes(bstr);
-	    while (true) {
-		uint8_t c = 0;
-		if (rb_io_read_internal(io_struct, &c, 1) != 1) {
-		    break;
-		}
-		if (data_read >= s) {
-		    s += s;
-		    rb_bstr_resize(bstr, s);
-		    buf = rb_bstr_bytes(bstr);
-		}
-		buf[data_read] = c;
-		data_read += 1;
-
-		if (data_read >= seplen
-			&& memcmp(&buf[data_read - seplen], sepstr,
-			    seplen) == 0) {
-		    break;
-		}
-	    }
-
-	    if (data_read == 0) {
-		return Qnil;
-	    }
-	    rb_bstr_set_length(bstr, data_read);
-	}
-    }
-    OBJ_TAINT(bstr);
-    io_struct->lineno += 1;
-    ARGF.lineno = INT2FIX(io_struct->lineno);
-    rb_str_force_encoding(bstr, rb_encodings[ENCODING_UTF8]);
-    return bstr;
-}
-
-static VALUE
-rb_io_getline(int argc, VALUE *argv, VALUE io)
-{
-    VALUE rs;
-    long limit;
-
-    prepare_getline_args(argc, argv, &rs, &limit, io);
-    return rb_io_getline_1(rs, limit, io);
-}
-
-/*
- *  call-seq:
- *     ios.gets(sep=$/)     => string or nil
- *     ios.gets(limit)      => string or nil
- *     ios.gets(sep, limit) => string or nil
- *
- *  Reads the next ``line'' from the I/O stream; lines are separated by
- *  <i>sep</i>. A separator of <code>nil</code> reads the entire
- *  contents, and a zero-length separator reads the input a paragraph at
- *  a time (two successive newlines in the input separate paragraphs).
- *  The stream must be opened for reading or an <code>IOError</code>
- *  will be raised. The line read in will be returned and also assigned
- *  to <code>$_</code>. Returns <code>nil</code> if called at end of
- *  file.  If the first argument is an integer, or optional second
- *  argument is given, the returning string would not be longer than the
- *  given value.
- *
- *     File.new("testfile").gets   #=> "This is line one\n"
- *     $_                          #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_gets_m(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE str;
-
-    str = rb_io_getline(argc, argv, io);
-    rb_lastline_set(str);
-
-    return str;
-}
-
-/* 
- *  call-seq:
- *     ios.lineno    => integer
- *
- *  Returns the current line number in <em>ios</em>. The stream must be
- *  opened for reading. <code>lineno</code> counts the number of times
- *  <code>gets</code> is called, rather than the number of newlines
- *  encountered. The two values will differ if <code>gets</code> is
- *  called with a separator other than newline. See also the
- *  <code>$.</code> variable.
- *
- *     f = File.new("testfile")
- *     f.lineno   #=> 0
- *     f.gets     #=> "This is line one\n"
- *     f.lineno   #=> 1
- *     f.gets     #=> "This is line two\n"
- *     f.lineno   #=> 2
- */
-
-static VALUE
-rb_io_lineno(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    rb_io_assert_open(io_s);
-    return INT2FIX(io_s->lineno);
-}
-
-/*
- *  call-seq:
- *     ios.lineno = integer    => integer
- *
- *  Manually sets the current line number to the given value.
- *  <code>$.</code> is updated only on the next read.
- *
- *     f = File.new("testfile")
- *     f.gets                     #=> "This is line one\n"
- *     $.                         #=> 1
- *     f.lineno = 1000
- *     f.lineno                   #=> 1000
- *     $.                         #=> 1         # lineno of last read
- *     f.gets                     #=> "This is line two\n"
- *     $.                         #=> 1001      # lineno of last read
- */
-
-static VALUE
-rb_io_set_lineno(VALUE io, SEL sel, VALUE line_no)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    rb_io_assert_open(io_s);
-    io_s->lineno = NUM2INT(line_no);
-    return line_no;
-}
-
-/*
- *  call-seq:
- *     ios.readline(sep=$/)     => string
- *     ios.readline(limit)      => string
- *     ios.readline(sep, limit) => string
- *
- *  Reads a line as with <code>IO#gets</code>, but raises an
- *  <code>EOFError</code> on end of file.
- */
-
-static VALUE
-rb_io_readline(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE ret = rb_io_gets_m(io, sel, argc, argv);
-    if (NIL_P(ret)) {
-	rb_eof_error();
-    }
-    return ret;
-}
-
-/*
- *  call-seq:
- *     ios.readlines(sep=$/)     => array
- *     ios.readlines(limit)      => array
- *     ios.readlines(sep, limit) => array
- *
- *  Reads all of the lines in <em>ios</em>, and returns them in
- *  <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
- *  <i>sep</i> is <code>nil</code>, the rest of the stream is returned
- *  as a single record.  If the first argument is an integer, or
- *  optional second argument is given, the returning string would not be
- *  longer than the given value. The stream must be opened for reading
- *  or an <code>IOError</code> will be raised.
- *
- *     f = File.new("testfile")
- *     f.readlines[0]   #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_readlines(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rs;
-    long limit;
-
-    prepare_getline_args(argc, argv, &rs, &limit, io);
-    if (limit == 0) {
-	rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
-    }
-
-    VALUE lines = rb_ary_new();
-    while (true) {
-	VALUE line = rb_io_getline_1(rs, limit, io);
-	if (NIL_P(line)) {
-	    break;
-	}
-	rb_ary_push(lines, line);
-    }
-    return lines;
-}
-
-/*
- *  call-seq:
- *     ios.each(sep=$/) {|line| block }         => ios
- *     ios.each(limit) {|line| block }          => ios
- *     ios.each(sep,limit) {|line| block }      => ios
- *     ios.each_line(sep=$/) {|line| block }    => ios
- *     ios.each_line(limit) {|line| block }     => ios
- *     ios.each_line(sep,limit) {|line| block } => ios
- *
- *  Executes the block for every line in <em>ios</em>, where lines are
- *  separated by <i>sep</i>. <em>ios</em> must be opened for
- *  reading or an <code>IOError</code> will be raised.
- *
- *     f = File.new("testfile")
- *     f.each {|line| puts "#{f.lineno}: #{line}" }
- *
- *  <em>produces:</em>
- *
- *     1: This is line one
- *     2: This is line two
- *     3: This is line three
- *     4: And so on...
- */
-
-static SEL sel_each_line = 0;
-static SEL sel_each_byte = 0;
-static SEL sel_each_char = 0;
-
-static VALUE
-rb_io_each_line(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rs;
-    long limit;
-
-    RETURN_ENUMERATOR(io, argc, argv);
-    prepare_getline_args(argc, argv, &rs, &limit, io);
-    if (limit == 0) {
-	rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
-    }
-
-    while (true) {
-	VALUE line = rb_io_getline_1(rs, limit, io);
-	if (NIL_P(line)) {
-	    break;
-	}
-	rb_vm_yield(1, &line);
-	RETURN_IF_BROKEN();
-    }
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.each_byte {|byte| block }  => ios
- *
- *  Calls the given block once for each byte (0..255) in <em>ios</em>,
- *  passing the byte as an argument. The stream must be opened for
- *  reading or an <code>IOError</code> will be raised.
- *
- *     f = File.new("testfile")
- *     checksum = 0
- *     f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
- *     checksum                           #=> 12
- */
-
-static VALUE
-rb_io_each_byte(VALUE io, SEL sel)
-{
-    RETURN_ENUMERATOR(io, 0, 0);
-
-    VALUE b = rb_io_getbyte(io, 0);
-    while (!NIL_P(b)) {
-	rb_vm_yield(1, &b);
-	RETURN_IF_BROKEN();
-	b = rb_io_getbyte(io, 0);
-    }
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.each_char {|c| block }  => ios
- *
- *  Calls the given block once for each character in <em>ios</em>,
- *  passing the character as an argument. The stream must be opened for
- *  reading or an <code>IOError</code> will be raised.
- *
- *     f = File.new("testfile")
- *     f.each_char {|c| print c, ' ' }   #=> #<File:testfile>
- */
-
-static VALUE rb_io_getc(VALUE io, SEL sel);
-
-static VALUE
-rb_io_each_char(VALUE io, SEL sel)
-{
-    RETURN_ENUMERATOR(io, 0, 0);
-
-    VALUE c = rb_io_getc(io, 0);
-    while (!NIL_P(c)) {
-	rb_vm_yield(1, &c);
-	RETURN_IF_BROKEN();
-	c = rb_io_getc(io, 0);
-    }
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.lines(sep=$/)     => anEnumerator
- *     ios.lines(limit)      => anEnumerator
- *     ios.lines(sep, limit) => anEnumerator
- *
- *  Returns an enumerator that gives each line in <em>ios</em>.
- *  The stream must be opened for reading or an <code>IOError</code>
- *  will be raised.
- *
- *     f = File.new("testfile")
- *     f.lines.to_a  #=> ["foo\n", "bar\n"]
- *     f.rewind
- *     f.lines.sort  #=> ["bar\n", "foo\n"]
- */
-
-static VALUE
-rb_io_lines(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    return rb_enumeratorize(io, sel_each_line, 0, NULL);
-}
-
-/*
- *  call-seq:
- *     ios.bytes   => anEnumerator
- *
- *  Returns an enumerator that gives each byte (0..255) in <em>ios</em>.
- *  The stream must be opened for reading or an <code>IOError</code>
- *  will be raised.
- *     
- *     f = File.new("testfile")
- *     f.bytes.to_a  #=> [104, 101, 108, 108, 111]
- *     f.rewind
- *     f.bytes.sort  #=> [101, 104, 108, 108, 111]
- */
-
-static VALUE
-rb_io_bytes(VALUE io, SEL sel)
-{
-    return rb_enumeratorize(io, sel_each_byte, 0, NULL);
-}
-
-/*
- *  call-seq:
- *     ios.chars   => anEnumerator
- *  
- *  Returns an enumerator that gives each character in <em>ios</em>.
- *  The stream must be opened for reading or an <code>IOError</code>
- *  will be raised.
- *     
- *     f = File.new("testfile")
- *     f.chars.to_a  #=> ["h", "e", "l", "l", "o"]
- *     f.rewind
- *     f.chars.sort  #=> ["e", "h", "l", "l", "o"]
- */
-
-
-static VALUE
-rb_io_chars(VALUE io, SEL sel)
-{
-    return rb_enumeratorize(io, sel_each_char, 0, NULL);
-}
-
-/*
- *  call-seq:
- *     ios.getc   => fixnum or nil
- *
- *  Reads a one-character string from <em>ios</em>. Returns
- *  <code>nil</code> if called at end of file.
- *
- *     f = File.new("testfile")
- *     f.getc   #=> "8"
- *     f.getc   #=> "1"
- */
-
-static VALUE
-rb_io_getc(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_readable(io_struct);
-
-    // TODO should be encoding aware
-
-    UInt8 byte;
-    if (rb_io_read_internal(io_struct, &byte, 1) != 1) {
-	return Qnil;
-    }
-
-    char buf[2];
-    buf[0] = byte;
-    buf[1] = '\0';
-
-    return rb_str_new2(buf);
-}
-
-/*
- *  call-seq:
- *     ios.readchar   => string
- *
- *  Reads a one-character string from <em>ios</em>. Raises an
- *  <code>EOFError</code> on end of file.
- *
- *     f = File.new("testfile")
- *     f.readchar   #=> "8"
- *     f.readchar   #=> "1"
- */
-
-static VALUE
-rb_io_readchar(VALUE io, SEL sel)
-{
-    VALUE c = rb_io_getc(io, 0);
-
-    if (NIL_P(c)) {
-	rb_eof_error();
-    }
-    return c;
-}
-
-/*
- *  call-seq:
- *     ios.getbyte   => fixnum or nil
- *
- *  Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
- *  <code>nil</code> if called at end of file.
- *
- *     f = File.new("testfile")
- *     f.getbyte   #=> 84
- *     f.getbyte   #=> 104
- */
-
-VALUE
-rb_io_getbyte(VALUE io, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_readable(io_struct);
-
-    UInt8 byte;
-    if (rb_io_read_internal(io_struct, &byte, 1) != 1) {
-	return Qnil;
-    }
-
-    return INT2FIX(byte);
-}
-
-/*
- *  call-seq:
- *     ios.readbyte   => fixnum
- *
- *  Reads a character as with <code>IO#getc</code>, but raises an
- *  <code>EOFError</code> on end of file.
- */
-
-static VALUE
-rb_io_readbyte(VALUE io, SEL sel)
-{
-    VALUE c = rb_io_getbyte(io, 0);
-
-    if (NIL_P(c)) {
-	rb_eof_error();
-    }
-    return c;
-}
-
-/*
- *  call-seq:
- *     ios.ungetc(string)   => nil
- *
- *  Pushes back one character (passed as a parameter) onto <em>ios</em>,
- *  such that a subsequent read will read it. When calling <code>ungetc</code>
- *	multiple times, the most-recently-pushed character will be read first.
- *
- *     f = File.new("testfile")   #=> #<File:testfile>
- *     c = f.getc                 #=> "8"
- *     f.ungetc(c)                #=> nil
- *     f.getc                     #=> "8"
- */
-
-VALUE
-rb_io_ungetc(VALUE io, SEL sel, VALUE c)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_assert_readable(io_struct);
-
-    if (NIL_P(c)) {
-	return Qnil;
-    }
-
-    UInt8 *bytes;
-    size_t len;
-
-    if (FIXNUM_P(c)) {
-        UInt8 cc = (UInt8)FIX2INT(c);
-
-	bytes = (UInt8 *)alloca(2);
-        bytes[0] = cc;
-        bytes[1] = '\0';
-	len = 1;
-    }
-    else {
-        SafeStringValue(c);
-	bytes = (UInt8 *)RSTRING_PTR(c);
-	len = RSTRING_LEN(c);
-    }
-
-    rb_io_create_buf(io_struct);
-
-    if (len <= io_struct->buf_offset) {
-	io_struct->buf_offset -= len;
-	UInt8 *data = CFDataGetMutableBytePtr(io_struct->buf);
-	memcpy(data + io_struct->buf_offset, bytes, len);
-    }
-    else {
-	const long n = len - io_struct->buf_offset;
-	CFDataIncreaseLength(io_struct->buf, n);
-	// CFDataGetMutableBytePtr must be called after CFDataIncreaseLength
-	UInt8 *data = CFDataGetMutableBytePtr(io_struct->buf);
-	memmove(data + n, data, CFDataGetLength(io_struct->buf) - n);
-	memcpy(data, bytes, len);
-    }
-
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     ios.isatty   => true or false
- *     ios.tty?     => true or false
- *
- *  Returns <code>true</code> if <em>ios</em> is associated with a
- *  terminal device (tty), <code>false</code> otherwise.
- *
- *     File.new("testfile").isatty   #=> false
- *     File.new("/dev/tty").isatty   #=> true
- */
-
-static VALUE
-rb_io_isatty(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    rb_io_assert_open(io_s);
-    return isatty(io_s->fd) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     ios.close_on_exec?   => true or false
- *
- *  Returns <code>true</code> if <em>ios</em> will be closed on exec.
- *
- *     f = open("/dev/null")
- *     f.close_on_exec?                 #=> false
- *     f.close_on_exec = true
- *     f.close_on_exec?                 #=> true
- *     f.close_on_exec = false
- *     f.close_on_exec?                 #=> false
- */
-
-static VALUE
-rb_io_close_on_exec_p(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    const int flags = fcntl(io_s->fd, F_GETFD, 0);
-    return ((flags & FD_CLOEXEC) ? Qtrue : Qfalse);
-}
-
-/*
- *  call-seq:
- *     ios.close_on_exec = bool    => true or false
- *
- *  Sets a close-on-exec flag.
- *
- *     f = open("/dev/null")
- *     f.close_on_exec = true
- *     system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
- *     f.closed?                #=> false
- */
-
-static VALUE
-rb_io_set_close_on_exec(VALUE io, SEL sel, VALUE arg)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    int flags = fcntl(io_s->fd, F_GETFD, 0);
-    if (arg == Qtrue) {		
-	flags |= FD_CLOEXEC;
-    }
-    else {
-	flags &= ~FD_CLOEXEC;
-    }
-    fcntl(io_s->fd, F_SETFD, flags);
-    return arg;
-}
-
-static VALUE
-rb_io_close_m(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't close");
-    }
-    rb_io_check_closed(io_s);
-    io_close(io_s, true, true);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     ios.closed?    => true or false
- *
- *  Returns <code>true</code> if <em>ios</em> is completely closed (for
- *  duplex streams, both reader and writer), <code>false</code>
- *  otherwise.
- *
- *     f = File.new("testfile")
- *     f.close         #=> nil
- *     f.closed?       #=> true
- *     f = IO.popen("/bin/sh","r+")
- *     f.close_write   #=> nil
- *     f.closed?       #=> false
- *     f.close_read    #=> nil
- *     f.closed?       #=> true
- */
-
-
-static VALUE
-rb_io_closed(VALUE io, SEL sel)
-{
-    rb_io_t *ios = ExtractIOStruct(io);
-    return rb_io_is_closed_for_writing(ios) && rb_io_is_closed_for_reading(ios)
-	? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     ios.close_read    => nil
- *
- *  Closes the read end of a duplex I/O stream (i.e., one that contains
- *  both a read and a write stream, such as a pipe). Will raise an
- *  <code>IOError</code> if the stream is not duplexed.
- *
- *     f = IO.popen("/bin/sh","r+")
- *     f.close_read
- *     f.readlines
- *
- *  <em>produces:</em>
- *
- *     prog.rb:3:in `readlines': not opened for reading (IOError)
- *     	from prog.rb:3
- */
-
-static VALUE
-rb_io_close_read(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't close");
-    }
-    rb_io_check_initialized(io_s);
-    if (io_s->read_fd == -1) {
-        rb_raise(rb_eIOError, "closed read stream");
-    }
-    io_close(io_s, true, false);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     ios.close_write   => nil
- *
- *  Closes the write end of a duplex I/O stream (i.e., one that contains
- *  both a read and a write stream, such as a pipe). Will raise an
- *  <code>IOError</code> if the stream is not duplexed.
- *
- *     f = IO.popen("/bin/sh","r+")
- *     f.close_write
- *     f.print "nowhere"
- *
- *  <em>produces:</em>
- *
- *     prog.rb:3:in `write': not opened for writing (IOError)
- *     	from prog.rb:3:in `print'
- *     	from prog.rb:3
- */
-
-static VALUE
-rb_io_close_write(VALUE io, SEL sel)
-{
-    rb_io_t *io_s = ExtractIOStruct(io);
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't close");
-    }
-    rb_io_check_initialized(io_s);
-    if (io_s->write_fd == -1) {
-        rb_raise(rb_eIOError, "closed write stream");
-    }
-    if (io_s->mode & FMODE_READABLE) {
-	rb_raise(rb_eIOError, "closing non-duplex IO for writing");
-    }
-    io_close(io_s, false, true);
-    return Qnil;
-}
-
-VALUE
-rb_io_close(VALUE io)
-{
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    io_close(io_struct, true, true);
-    return Qnil;
-}
-
-VALUE
-rb_io_fdopen(int fd, int mode, const char *path)
-{
-    VALUE klass = rb_cIO;
-
-    if (path != NULL && strcmp(path, "-") != 0) {
-	klass = rb_cFile;
-    }
-    return prep_io(fd, convert_oflags_to_fmode(mode), klass);
-}
-
-VALUE
-rb_io_gets(VALUE io, SEL sel)
-{
-    return rb_io_getline_1(rb_default_rs, -1, io);
-}
-
-VALUE
-rb_io_binmode(VALUE io, SEL sel)
-{
-    // binmode does nothing on Mac OS X
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    rb_io_check_closed(io_struct);
-    return io;
-}
-
-/*
- *  call-seq:
- *     ios.binmode    => ios
- *
- *  Puts <em>ios</em> into binary mode. This is useful only in
- *  MS-DOS/Windows environments. Once a stream is in binary mode, it
- *  cannot be reset to nonbinary mode.
- */
-
-static VALUE
-rb_io_binmode_m(VALUE io, SEL sel)
-{
-    rb_io_binmode(io, 0);
-    return io;
-}
-
-/*
- *  call-seq:
- *     IO.popen(cmd, mode="r")               => io
- *     IO.popen(cmd, mode="r") {|io| block } => obj
- *
- *  Runs the specified command as a subprocess; the subprocess's
- *  standard input and output will be connected to the returned
- *  <code>IO</code> object.  If _cmd_ is a +String+
- *  ``<code>-</code>'', then a new instance of Ruby is started as the
- *  subprocess.  If <i>cmd</i> is an +Array+ of +String+, then it will
- *  be used as the subprocess's +argv+ bypassing a shell.
- *  The array can contains a hash at first for environments and
- *  a hash at last for options similar to <code>spawn</code>.  The default
- *  mode for the new file object is ``r'', but <i>mode</i> may be set
- *  to any of the modes listed in the description for class IO.
- *
- *  Raises exceptions which <code>IO::pipe</code> and
- *  <code>Kernel::system</code> raise.
- *
- *  If a block is given, Ruby will run the command as a child connected
- *  to Ruby with a pipe. Ruby's end of the pipe will be passed as a
- *  parameter to the block.
- *  At the end of block, Ruby close the pipe and sets <code>$?</code>.
- *  In this case <code>IO::popen</code> returns
- *  the value of the block.
- *
- *  If a block is given with a _cmd_ of ``<code>-</code>'',
- *  the block will be run in two separate processes: once in the parent,
- *  and once in a child. The parent process will be passed the pipe
- *  object as a parameter to the block, the child version of the block
- *  will be passed <code>nil</code>, and the child's standard in and
- *  standard out will be connected to the parent through the pipe. Not
- *  available on all platforms.
- *
- *     f = IO.popen("uname")
- *     p f.readlines
- *     puts "Parent is #{Process.pid}"
- *     IO.popen("date") { |f| puts f.gets }
- *     IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
- *     p $?
- *     IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
- *       f.puts "bar"; f.close_write; puts f.gets
- *     }
- *
- *  <em>produces:</em>
- *
- *     ["Linux\n"]
- *     Parent is 26166
- *     Wed Apr  9 08:53:52 CDT 2003
- *     26169 is here, f is
- *     26166 is here, f is #<IO:0x401b3d44>
- *     #<Process::Status: pid=26166,exited(0)>
- *     <foo>bar;zot;
- */
-
-#define rb_sys_fail_unless(action, msg) do { \
-    errno = action; \
-    if (errno != 0) { \
-	rb_sys_fail(msg); \
-    } \
-} while(0)
-
-static VALUE 
-io_from_spawning_new_process(VALUE prog, VALUE mode)
-{
-    VALUE io = io_alloc(rb_cIO, 0);
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    posix_spawn_file_actions_t actions;
-
-    int fd_r[2], fd_w[2];
-    if (pipe(fd_r) < 0) {
-	rb_sys_fail("pipe() failed");
-    }
-    if (pipe(fd_w) < 0) {
-	close(fd_r[0]);
-	close(fd_r[1]);
-	rb_sys_fail("pipe() failed");
-    }
-
-    // MacRuby               child process
-    //  in  : fd_r[0]  -----  fd_r[1] : stdout
-    //  out : fd_w[1]  -----  fd_w[0] : stdin
-    rb_sys_fail_unless(posix_spawn_file_actions_init(&actions),
-	    "could not init file actions");
-    rb_sys_fail_unless(posix_spawn_file_actions_adddup2(&actions, fd_w[0],
-		STDIN_FILENO), "could not add dup2() to stdin");
-    rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, fd_w[0]),
-	    "could not add a close() to stdin");
-    rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, fd_w[1]),
-	    "could not add a close() to stdin");
-    rb_sys_fail_unless(posix_spawn_file_actions_adddup2(&actions, fd_r[1],
-		STDOUT_FILENO), "could not add dup2() to stdout");
-    rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, fd_r[0]),
-	    "could not add a close() to stdout");
-    rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, fd_r[1]),
-	    "could not add a close() to stdout");
-    pid_t pid;
-
-    VALUE argArray = rb_check_array_type(prog);
-    if (!NIL_P(argArray)) {
-	const long len = RARRAY_LEN(argArray);
-	char **spawnedArgs =
-		malloc((len + 1) * sizeof(char *));
-	for (long i = 0; i < len; i++) {
-	    VALUE str = RARRAY_AT(argArray, i);
-	    spawnedArgs[i] = StringValuePtr(str);
-	}
-	spawnedArgs[len] = 0;
-	// using posix_spawnP (look up binary in PATH)
-	errno = posix_spawnp(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs,
-		*(_NSGetEnviron()));
-	const int err = errno;
-	free(spawnedArgs);
-	errno = err;
-    }
-    else {
-	// TODO: Split the process_name up into char* components?
-	char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c",
-		StringValuePtr(prog), NULL};
-	errno = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs,
-		*(_NSGetEnviron()));
-    }
-
-    posix_spawn_file_actions_destroy(&actions);
-    if (errno != 0) {
-	const int err = errno;
-	close(fd_r[0]);
-	close(fd_r[1]);
-	close(fd_w[0]);
-	close(fd_w[1]);
-	errno = err;
-	rb_sys_fail("posix_spawn() failed");
-    }
-
-    io_struct->fd = fd_r[0];
-    io_struct->pid = pid;
-    io_struct->mode = mode;
-
-    const int fmode = convert_mode_string_to_fmode(mode);
-    if (fmode & FMODE_READABLE) {
-	io_struct->read_fd = fd_r[0];
-    }
-    else {
-	close(fd_r[0]);
-    }
-    if (fmode & FMODE_WRITABLE) {
-	io_struct->write_fd = fd_w[1];
-    }
-    else {
-	close(fd_w[1]);
-    }
-    close(fd_r[1]);
-    close(fd_w[0]);
-
-    return io;
-}
-
-static VALUE
-io_pipe_open(VALUE prog, VALUE mode)
-{
-    if (NIL_P(mode)) {
-	mode = (VALUE)CFSTR("r");
-    }
-    return io_from_spawning_new_process(prog, mode);
-}
-
-static VALUE
-rb_io_s_popen(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE process_name, mode;
-    rb_scan_args(argc, argv, "11", &process_name, &mode);
-
-    VALUE io = io_pipe_open(process_name, mode);
-    if (rb_block_given_p()) {
-	VALUE ret = rb_vm_yield(1, &io);
-	rb_io_close(io);
-	return ret;
-    }
-    return io;
-}
-
-/*
- *  call-seq:
- *     IO.open(fd, mode_string="r" )               => io
- *     IO.open(fd, mode_string="r" ) {|io| block } => obj
- *
- *  With no associated block, <code>open</code> is a synonym for
- *  <code>IO::new</code>. If the optional code block is given, it will
- *  be passed <i>io</i> as an argument, and the IO object will
- *  automatically be closed when the block terminates. In this instance,
- *  <code>IO::open</code> returns the value of the block.
- *
- */
-
-static VALUE rb_io_s_new0(VALUE klass, int argc, VALUE *argv);
-
-static VALUE
-rb_io_s_open(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE io = rb_io_s_new0(klass, argc, argv);
-    if (rb_block_given_p()) {
-        VALUE ret = rb_vm_yield(1, &io);
-        rb_io_close(io);
-        return ret;
-    }
-    return io;
-}
-
-static VALUE
-check_pipe_command(VALUE fname)
-{
-    const char *cname = StringValuePtr(fname);
-    const size_t len = strlen(cname);
-
-    if (cname[0] == '|') {
-        VALUE cmd = rb_str_new(cname + 1, len - 1);
-        return cmd;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     open(path [, mode_enc [, perm]] )                => io or nil
- *     open(path [, mode_enc [, perm]] ) {|io| block }  => obj
- *
- *  Creates an <code>IO</code> object connected to the given stream,
- *  file, or subprocess.
- *
- *  If <i>path</i> does not start with a pipe character
- *  (``<code>|</code>''), treat it as the name of a file to open using
- *  the specified mode (defaulting to ``<code>r</code>'').
- *
- *  The mode_enc is
- *  either a string or an integer.  If it is an integer, it must be
- *  bitwise-or of open(2) flags, such as File::RDWR or File::EXCL.
- *  If it is a string, it is either "mode", "mode:ext_enc", or
- *  "mode:ext_enc:int_enc".
- *  The mode is one of the following:
- *
- *   r: read (default)
- *   w: write
- *   a: append
- *
- *  The mode can be followed by "b" (means binary-mode), or "+"
- *  (means both reading and writing allowed) or both.
- *  If ext_enc (external encoding) is specified,
- *  read string will be tagged by the encoding in reading,
- *  and output string will be converted
- *  to the specified encoding in writing.
- *  If two encoding names,
- *  ext_enc and int_enc (external encoding and internal encoding),
- *  are specified, the read string is converted from ext_enc
- *  to int_enc then tagged with the int_enc in read mode,
- *  and in write mode, the output string will be
- *  converted from int_enc to ext_enc before writing.
- *
- *  If a file is being created, its initial permissions may be
- *  set using the integer third parameter.
- *
- *  If a block is specified, it will be invoked with the
- *  <code>File</code> object as a parameter, and the file will be
- *  automatically closed when the block terminates. The call
- *  returns the value of the block.
- *
- *  If <i>path</i> starts with a pipe character, a subprocess is
- *  created, connected to the caller by a pair of pipes. The returned
- *  <code>IO</code> object may be used to write to the standard input
- *  and read from the standard output of this subprocess. If the command
- *  following the ``<code>|</code>'' is a single minus sign, Ruby forks,
- *  and this subprocess is connected to the parent. In the subprocess,
- *  the <code>open</code> call returns <code>nil</code>. If the command
- *  is not ``<code>-</code>'', the subprocess runs the command. If a
- *  block is associated with an <code>open("|-")</code> call, that block
- *  will be run twice---once in the parent and once in the child. The
- *  block parameter will be an <code>IO</code> object in the parent and
- *  <code>nil</code> in the child. The parent's <code>IO</code> object
- *  will be connected to the child's <code>$stdin</code> and
- *  <code>$stdout</code>. The subprocess will be terminated at the end
- *  of the block.
- *
- *     open("testfile") do |f|
- *       print f.gets
- *     end
- *
- *  <em>produces:</em>
- *
- *     This is line one
- *
- *  Open a subprocess and read its output:
- *
- *     cmd = open("|date")
- *     print cmd.gets
- *     cmd.close
- *
- *  <em>produces:</em>
- *
- *     Wed Apr  9 08:56:31 CDT 2003
- *
- *  Open a subprocess running the same Ruby program:
- *
- *     f = open("|-", "w+")
- *     if f == nil
- *       puts "in Child"
- *       exit
- *     else
- *       puts "Got: #{f.gets}"
- *     end
- *
- *  <em>produces:</em>
- *
- *     Got: in Child
- *
- *  Open a subprocess using a block to receive the I/O object:
- *
- *     open("|-") do |f|
- *       if f == nil
- *         puts "in Child"
- *       else
- *         puts "Got: #{f.gets}"
- *       end
- *     end
- *
- *  <em>produces:</em>
- *
- *     Got: in Child
- */
-
-static VALUE
-rb_file_open(VALUE io, int argc, VALUE *argv)
-{
-    if (argc > 0) {
-	// First argument must always be a path, we are checking it here to
-	// conform to RubySpecs which states that the conversion must only
-	// happen once.
-	FilePathValue(argv[0]);
-    }
-    if (argc >= 1) {
-	VALUE cmd = check_pipe_command(argv[0]);
-	if (cmd != Qnil) {
-	    VALUE modes = (argc >= 2) ? argv[1] : Qnil;
-	    return io_pipe_open(cmd, modes);
-	}
-    }
-    VALUE path, modes, permissions;
-    rb_scan_args(argc, argv, "12", &path, &modes, &permissions);
-    if (NIL_P(modes)) {
-	modes = (VALUE)CFSTR("r");
-    }
-    const char *filepath = RSTRING_PTR(path);
-    const int flags = convert_mode_string_to_oflags(modes);
-    const mode_t perm = NIL_P(permissions) ? 0666 : NUM2UINT(permissions);
-    int fd, retry = 0;
-    while (true) {
-       fd = open(filepath, flags, perm);
-       if (fd == -1) {
-	   if (retry < 5 && errno == EMFILE) {
-		// Too many open files. Let's schedule a GC collection.
-	       	rb_gc();
-		usleep(1000);
-	       	retry++;
-	   }
-	   else {
-	       rb_sys_fail("open() failed");
-	   }
-       }
-       else {
-	   break;
-       }
-    }
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    prepare_io_from_fd(io_struct, fd, convert_oflags_to_fmode(flags));
-    GC_WB(&io_struct->path, path); 
-    return io;
-}
-
-static VALUE
-f_open_body(VALUE io)
-{
-    return rb_vm_yield(1, &io);
-}
-
-static VALUE
-f_open_ensure(VALUE io)
-{
-    rb_io_close(io);
-    return Qnil;
-}
-
-VALUE
-rb_f_open(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    if (argc >= 1) {
-	VALUE cmd = check_pipe_command(argv[0]);
-	if (cmd != Qnil) {
-	    return rb_io_s_popen(rb_cIO, 0, 1, &cmd);
-	}
-    }
-    VALUE io = rb_class_new_instance(argc, argv, rb_cFile);
-    if (rb_block_given_p()) {
-	return rb_ensure(f_open_body, io, f_open_ensure, io);
-    }
-    return io;
-}
-
-/*
- *  call-seq:
- *     IO.sysopen(path, [mode, [perm]])  => fixnum
- *
- *  Opens the given path, returning the underlying file descriptor as a
- *  <code>Fixnum</code>.
- *
- *     IO.sysopen("testfile")   #=> 3
- *
- */
-
-static VALUE
-rb_io_s_sysopen(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE f = rb_f_open(klass, sel, argc, argv);
-    return INT2FIX(ExtractIOStruct(f)->fd);
-}
-
-/*
- *  call-seq:
- *     ios.reopen(other_IO)         => ios
- *     ios.reopen(path, mode_str)   => ios
- *
- *  Reassociates <em>ios</em> with the I/O stream given in
- *  <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
- *  dynamically change the actual class of this stream.
- *
- *     f1 = File.new("testfile")
- *     f2 = File.new("testfile")
- *     f2.readlines[0]   #=> "This is line one\n"
- *     f2.reopen(f1)     #=> #<File:testfile>
- *     f2.readlines[0]   #=> "This is line one\n"
- */
-
-static void
-io_replace_streams(int fd, rb_io_t *dest, rb_io_t *origin)
-{
-    prepare_io_from_fd(dest, fd, rb_io_calculate_mode_flags(origin));
-
-    if (origin->buf != NULL) {
-	CFMutableDataRef data = CFDataCreateMutableCopy(NULL, 0, origin->buf);
-	GC_WB(&dest->buf, data);
-	CFMakeCollectable(data);
-    }
-    else {
-	dest->buf = NULL;
-    }
-    dest->buf_offset = origin->buf_offset;
-}
-
-static VALUE
-rb_io_reopen(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(4);
-	
-    VALUE path_or_io, mode_string;
-    rb_scan_args(argc, argv, "11", &path_or_io, &mode_string);
-    rb_io_t *io_s = ExtractIOStruct(io);
-    rb_io_assert_open(io_s);
-
-    if (TYPE(path_or_io) == T_STRING) {
-	// Reassociate it with the stream opened on the given path
-	if (NIL_P(mode_string)) {
-	    mode_string = (VALUE)CFSTR("r");
-	}
-	FilePathValue(path_or_io); // Sanitize the name
-	const char *filepath = RSTRING_PTR(path_or_io);
-	const int fd =
-	    open(filepath, convert_mode_string_to_oflags(mode_string), 0644);
-	prepare_io_from_fd(io_s, fd,
-		convert_mode_string_to_fmode(mode_string));
-	GC_WB(&io_s->path, path_or_io);
-	io_s->buf = NULL;
-	io_s->buf_offset = 0;
-    } 
-    else {
-	// Reassociate it with a duplicate of the stream given
-	path_or_io = rb_io_get_io(path_or_io);
-	rb_io_t *other = ExtractIOStruct(path_or_io);
-	rb_io_assert_open(other);
-	if (io_s == other) {
-	    return io;
-	}
-
-	if (io_s->fd == -1) {
-	    rb_raise(rb_eRuntimeError,
-		    "cannot reopen non file descriptor based IO");
-	}
-	if (other->fd == -1) {
-	    rb_raise(rb_eRuntimeError,
-		    "cannot reopen from non file descriptor based IO");
-	}
-
-	int fd = io_s->fd;
-	io_close(io_s, true, true);
-	fd = dup2(other->fd, fd);
-	if (fd < 0) {
-	    rb_sys_fail("dup2() failed");
-	}
-	io_replace_streams(fd, io_s, other);
-
-	*(VALUE *)io = *(VALUE *)path_or_io;
-    }
-    return io;
-}
-
-/* :nodoc: */
-static VALUE
-rb_io_init_copy(VALUE dest, SEL sel, VALUE origin)
-{
-    origin = rb_io_get_io(origin);
-    rb_io_t *dest_io = ExtractIOStruct(dest);
-    rb_io_t *origin_io = ExtractIOStruct(origin);
-
-    rb_io_check_closed(origin_io);
-    if (dest_io == origin_io) {
-	return dest;
-    }
-
-    if (origin_io->fd == -1) {
-	rb_raise(rb_eRuntimeError,
-		"cannot copy from non file descriptor based IO");
-    }
-
-    const int fd = dup(origin_io->fd);
-    if (fd < 0) {
-	rb_sys_fail("dup() failed");
-    }
-    io_replace_streams(fd, dest_io, origin_io);
-
-    return dest;
-}
-
-/*
- *  call-seq:
- *     ios.printf(format_string [, obj, ...] )   => nil
- *
- *  Formats and writes to <em>ios</em>, converting parameters under
- *  control of the format string. See <code>Kernel#sprintf</code>
- *  for details.
- */
-
-VALUE
-rb_io_printf(VALUE out, SEL sel, int argc, VALUE *argv)
-{
-    return rb_io_write(out, rb_f_sprintf(argc, argv));
-}
-
-/*
- *  call-seq:
- *     printf(io, string [, obj ... ] )    => nil
- *     printf(string [, obj ... ] )        => nil
- *
- *  Equivalent to:
- *     io.write(sprintf(string, obj, ...)
- *  or
- *     $stdout.write(sprintf(string, obj, ...)
- */
-
-static VALUE
-rb_f_printf(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE io;
-    if (argc == 0) {
-        return Qnil;
-    }
-    
-    if (TYPE(argv[0]) == T_STRING) {
-        io = rb_stdout;
-    } 
-    else {
-        io = argv[0];
-        argv++;
-        argc--;
-    }
-    
-    return rb_io_printf(io, sel, argc, argv);
-}
-
-/*
- *  call-seq:
- *     ios.print()             => nil
- *     ios.print(obj, ...)     => nil
- *
- *  Writes the given object(s) to <em>ios</em>. The stream must be
- *  opened for writing. If the output record separator (<code>$\\</code>)
- *  is not <code>nil</code>, it will be appended to the output. If no
- *  arguments are given, prints <code>$_</code>. Objects that aren't
- *  strings will be converted by calling their <code>to_s</code> method.
- *  With no argument, prints the contents of the variable <code>$_</code>.
- *  Returns <code>nil</code>.
- *
- *     $stdout.print("This is ", 100, " percent.\n")
- *
- *  <em>produces:</em>
- *
- *     This is 100 percent.
- */
-
-VALUE
-rb_io_print(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    VALUE line;
-    if (argc == 0) {
-        argc = 1;
-        line = rb_lastline_get();
-        argv = &line;
-    }
-    while (argc--) {
-        rb_io_write(io, *argv++);
-        if (!NIL_P(rb_output_fs)) {
-            rb_io_write(io, rb_output_fs);
-        }
-    }
-    if (!NIL_P(rb_output_rs)) {
-        rb_io_write(io, rb_output_rs);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     print(obj, ...)    => nil
- *
- *  Prints each object in turn to <code>$stdout</code>. If the output
- *  field separator (<code>$,</code>) is not +nil+, its
- *  contents will appear between each field. If the output record
- *  separator (<code>$\\</code>) is not +nil+, it will be
- *  appended to the output. If no arguments are given, prints
- *  <code>$_</code>. Objects that aren't strings will be converted by
- *  calling their <code>to_s</code> method.
- *
- *     print "cat", [1,2,3], 99, "\n"
- *     $, = ", "
- *     $\ = "\n"
- *     print "cat", [1,2,3], 99
- *
- *  <em>produces:</em>
- *
- *     cat12399
- *     cat, 1, 2, 3, 99
- */
-
-static VALUE
-rb_f_print(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    rb_io_print(rb_stdout, 0, argc, argv);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     ios.putc(obj)    => obj
- *
- *  If <i>obj</i> is <code>Numeric</code>, write the character whose
- *  code is <i>obj</i>, otherwise write the first character of the
- *  string representation of  <i>obj</i> to <em>ios</em>.
- *
- *     $stdout.putc "A"
- *     $stdout.putc 65
- *
- *  <em>produces:</em>
- *
- *     AA
- */
-
-static VALUE
-rb_io_putc(VALUE io, SEL sel, VALUE ch)
-{
-    char c = NUM2CHR(ch);
-    rb_io_write(io, rb_str_new(&c, 1));
-    return ch;
-}
-
-/*
- *  call-seq:
- *     putc(int)   => int
- *
- *  Equivalent to:
- *
- *    $stdout.putc(int)
- */
-
-static VALUE
-rb_f_putc(VALUE recv, SEL sel, VALUE ch)
-{
-    return rb_io_putc(rb_stdout, sel, ch);
-}
-
-/*
- *  call-seq:
- *     ios.puts(obj, ...)    => nil
- *
- *  Writes the given objects to <em>ios</em> as with
- *  <code>IO#print</code>. Writes a record separator (typically a
- *  newline) after any that do not already end with a newline sequence.
- *  If called with an array argument, writes each element on a new line.
- *  If called without arguments, outputs a single record separator.
- *
- *     $stdout.puts("this", "is", "a", "test")
- *
- *  <em>produces:</em>
- *
- *     this
- *     is
- *     a
- *     test
- */
- 
-VALUE rb_io_puts(VALUE out, SEL sel, int argc, VALUE *argv);
- 
-static VALUE
-io_puts_ary(VALUE ary, VALUE out, int recur)
-{
-    VALUE tmp;
-    long i, count;
-
-    if (recur) {
-	tmp = rb_str_new2("[...]");
-	rb_io_puts(out, 0, 1, &tmp);
-	return Qnil;
-    }
-    for (i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	tmp = RARRAY_AT(ary, i);
-	rb_io_puts(out, 0, 1, &tmp);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_io_puts(VALUE out, SEL sel, int argc, VALUE *argv)
-{
-    VALUE line;
-    int i;
-    if (argc == 0) {
-        rb_io_write(out, rb_default_rs);
-        return Qnil;
-    }
-    for (i = 0; i < argc; i++) {
-        line = rb_check_array_type(argv[i]);
-        if (!NIL_P(line)) {
-            rb_exec_recursive(io_puts_ary, line, out);
-            continue;
-        }
-        line = rb_obj_as_string(argv[i]);
-        rb_io_write(out, line);
-        if (RSTRING_LEN(line) == 0
-		|| RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
-            // If the last character of line was a newline, there's no reason
-	    // to write another.
-            rb_io_write(out, rb_default_rs);
-        }
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     puts(obj, ...)    => nil
- *
- *  Equivalent to
- *
- *      $stdout.puts(obj, ...)
- */
-
-static VALUE
-rb_f_puts(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_io_puts(rb_stdout, sel, argc, argv);
-}
-
-void
-rb_p(VALUE obj) /* for debug print within C code */
-{
-    rb_io_write(rb_stdout, rb_obj_as_string(rb_inspect(obj)));
-    rb_io_write(rb_stdout, rb_default_rs);
-}
-
-VALUE
-rb_io_write(VALUE v, VALUE i)
-{
-    return rb_funcall(v, id_write, 1, i);
-}
-
-/*
- *  call-seq:
- *     p(obj)              => obj
- *     p(obj1, obj2, ...)  => [obj, ...]
- *     p()                 => nil
- *
- *  For each object, directly writes
- *  _obj_.+inspect+ followed by the current output
- *  record separator to the program's standard output.
- *
- *     S = Struct.new(:name, :state)
- *     s = S['dave', 'TX']
- *     p s
- *
- *  <em>produces:</em>
- *
- *     #<S name="dave", state="TX">
- */
-
-static VALUE
-rb_f_p(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    int i;
-    VALUE ret = Qnil;
-
-    for (i = 0; i < argc; i++) {
-	rb_p(argv[i]);
-    }
-    if (argc == 1) {
-	ret = argv[0];
-    }
-    else if (argc > 1) {
-	ret = rb_ary_new4(argc, argv);
-    }
-
-    return ret;
-}
-
-/*
- *  call-seq:
- *     obj.display(port=$>)    => nil
- *
- *  Prints <i>obj</i> on the given port (default <code>$></code>).
- *  Equivalent to:
- *
- *     def display(port=$>)
- *       port.write self
- *     end
- *
- *  For example:
- *
- *     1.display
- *     "cat".display
- *     [ 4, 5, 6 ].display
- *     puts
- *
- *  <em>produces:</em>
- *
- *     1cat456
- */
- 
-// TODO: The output doesn't match the documentation here; why is that?
-
-static VALUE
-rb_obj_display(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE port;
-    rb_scan_args(argc, argv, "01", &port);
-    if (NIL_P(port)) {
-	port = rb_stdout;
-    }
-    return rb_io_write(port, self);
-}
-
-// static void
-// must_respond_to(ID mid, VALUE val, ID id)
-// {
-//     if (!rb_respond_to(val, mid)) {
-//  rb_raise(rb_eTypeError, "%s must have %s method, %s given",
-//       rb_id2name(id), rb_id2name(mid),
-//       rb_obj_classname(val));
-//     }
-// }
-
-// TODO: Fix this; the documentation is wrong.
-
-/*
- *  call-seq:
- *     IO.new(fd, mode)   => io
- *
- *  Returns a new <code>IO</code> object (a stream) for the given
- *  <code>IO</code> object or integer file descriptor and mode
- *  string. See also <code>IO#fileno</code> and
- *  <code>IO::for_fd</code>.
- *
- *     puts IO.new($stdout).fileno # => 1
- *
- *     a = IO.new(2,"w")      # '2' is standard error
- *     $stderr.puts "Hello"
- *     a.puts "World"
- *
- *  <em>produces:</em>
- *
- *     Hello
- *     World
- */
-
-/*
- *  call-seq:
- *     IO.for_fd(fd, mode)    => io
- *
- *  Synonym for <code>IO::new</code>.
- *
- */
-
-static VALUE
-rb_io_initialize(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    rb_secure(4);
-	
-    VALUE file_descriptor, mode;
-    int mode_flags, fd;
-    struct stat st;
-
-    // TODO handle optional hash
-    /*VALUE opt =*/ pop_last_hash(&argc, argv);
-
-    rb_scan_args(argc, argv, "11", &file_descriptor, &mode);
-
-    rb_io_t *io_struct = ExtractIOStruct(io);
-    file_descriptor = rb_check_to_integer(file_descriptor, "to_int");
-    if (NIL_P(file_descriptor)) {
-	rb_raise(rb_eTypeError, "can't convert %s into Integer",
-		rb_obj_classname(file_descriptor));
-    }
-    fd = FIX2INT(file_descriptor);
-
-    if (fstat(fd, &st) < 0) {
-	rb_sys_fail(0);
-    }
-
-    if (NIL_P(mode)) {
-	mode_flags = FMODE_READABLE;
-    }
-    else if (TYPE(mode) == T_STRING) {
-	mode_flags = convert_mode_string_to_fmode(mode);
-    }
-    else {
-	mode_flags = NUM2INT(mode);
-    }
-
-    prepare_io_from_fd(io_struct, fd, mode_flags);
-    return io;
-}
-
-static IMP rb_objc_io_finalize_super = NULL; 
-
-static void
-rb_objc_io_finalize(void *rcv, SEL sel)
-{
-    rb_io_t *io_struct = ExtractIOStruct((VALUE)rcv);
-    // do not close automatically stdin, stdout and stderr
-    if ((io_struct->fd < 0) || (io_struct->fd > 2)) {
-	rb_io_close((VALUE)rcv);
-	if (rb_objc_io_finalize_super != NULL) {
-	    ((void(*)(void *, SEL))rb_objc_io_finalize_super)(rcv, sel);
-	}
-    }
-}
-
-/*
- *  call-seq:
- *     File.new(filename, mode="r")            => file
- *     File.new(filename [, mode [, perm]])    => file
- *
- *  Opens the file named by _filename_ according to
- *  _mode_ (default is ``r'') and returns a new
- *  <code>File</code> object. See the description of class +IO+ for
- *  a description of _mode_. The file mode may optionally be
- *  specified as a +Fixnum+ by _or_-ing together the
- *  flags (O_RDONLY etc, again described under +IO+). Optional
- *  permission bits may be given in _perm_. These mode and permission
- *  bits are platform dependent; on Unix systems, see
- *  <code>open(2)</code> for details.
- *
- *     f = File.new("testfile", "r")
- *     f = File.new("newfile",  "w+")
- *     f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
- */
-
-static VALUE
-rb_file_initialize(VALUE io, SEL sel, int argc, VALUE *argv)
-{
-    if (0 < argc && argc < 3) {
-	VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
-
-	if (!NIL_P(fd)) {
-	    argv[0] = fd;
-	    return rb_io_initialize(io, sel, argc, argv);
-	}
-    }
-    return rb_file_open(io, argc, argv);
-}
-
-/*
- *  call-seq:
- *     IO.new(fd, mode_string)   => io
- *
- *  Returns a new <code>IO</code> object (a stream) for the given
- *  integer file descriptor and mode string. See also
- *  <code>IO#fileno</code> and <code>IO::for_fd</code>.
- *
- *     a = IO.new(2,"w")      # '2' is standard error
- *     $stderr.puts "Hello"
- *     a.puts "World"
- *
- *  <em>produces:</em>
- *
- *     Hello
- *     World
- */
-
-static VALUE
-rb_io_s_new0(VALUE klass, int argc, VALUE *argv)
-{
-    return rb_class_new_instance(argc, argv, klass);
-}
-
-static VALUE
-rb_io_s_new(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    if (rb_block_given_p()) {
-	VALUE k = klass;
-	bool is_io = true;
-	while (k != 0) {
-	    if (k == rb_cFile) {
-		is_io = false;
-		break;
-	    }
-	    k = RCLASS_SUPER(k);
-	}
-	if (is_io) {
-	    const char *cname = rb_class2name(klass);
-
-	    rb_warn("%s::new() does not take block; use %s::open() instead",
-		    cname, cname);
-	}
-    }
-    return rb_io_s_new0(klass, argc, argv);
-}
-
-static void
-argf_init(struct argf *p, VALUE v)
-{
-    p->filename = Qnil;
-    p->current_file = Qnil;
-    p->lineno = Qnil;
-    GC_WB(&p->argv, v);
-}
-
-static VALUE
-argf_alloc(VALUE klass)
-{
-    struct argf *p;
-
-    VALUE argf = Data_Make_Struct(klass, struct argf, NULL, NULL, p);
-    argf_init(p, Qnil);
-
-    return argf;
-}
-
-#undef rb_argv
-
-static VALUE
-argf_initialize(VALUE argf, SEL sel, VALUE argv)
-{
-    memset(&ARGF, 0, sizeof(ARGF));
-    argf_init(&ARGF, argv);
-
-    return argf;
-}
-
-static VALUE
-argf_initialize_copy(VALUE argf, SEL sel, VALUE orig)
-{
-    ARGF = argf_of(orig);
-    GC_WB(&(ARGF.argv), rb_obj_dup(ARGF.argv));
-    if (ARGF.inplace) {
-	const char *inplace = ARGF.inplace;
-	ARGF.inplace = 0;
-	GC_WB(&ARGF.inplace, ruby_strdup(inplace));
-    }
-    return argf;
-}
-
-static VALUE
-argf_set_lineno(VALUE argf, SEL sel, VALUE val)
-{
-    ARGF.gets_lineno = NUM2INT(val);
-    ARGF.lineno = INT2FIX(ARGF.gets_lineno);
-    return Qnil;
-}
-
-static VALUE
-argf_lineno(VALUE argf, SEL sel)
-{
-    return ARGF.lineno;
-}
-
-static VALUE
-argf_forward(VALUE argf, SEL sel, int argc, VALUE *argv)
-{
-    // TODO
-    // return rb_funcall3(ARGF. current_file, rb_frame_this_func(), argc, argv);
-    rb_notimplement();
-}
-
-#define next_argv() argf_next_argv(argf)
-#define ARGF_GENERIC_INPUT_P() \
-    (ARGF.current_file == rb_stdin && TYPE(ARGF.current_file) != T_FILE)
-
-#define ARGF_FORWARD(argc, argv) do {\
-    if (ARGF_GENERIC_INPUT_P())\
-	return argf_forward(argf, 0, argc, argv);\
-} while (0)
-
-#define NEXT_ARGF_FORWARD(argc, argv) do {\
-    if (!next_argv()) return Qnil;\
-    ARGF_FORWARD(argc, argv);\
-} while (0)
-
-static void
-argf_close(VALUE file, SEL sel)
-{
-    rb_funcall3(file, rb_intern("close"), 0, 0);
-}
-
-static int
-argf_next_argv(VALUE argf)
-{
-    rb_io_t *io = NULL;
-    char *fn = NULL;
-    if (TYPE(rb_stdout) == T_FILE) {
-        io = ExtractIOStruct(rb_stdout);
-    }
-    if (ARGF.init_p == 0) {
-	if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
-	    ARGF.next_p = 1;
-	}
-	else {
-	    ARGF.next_p = -1;
-	}
-	ARGF.init_p = 1;
-	ARGF.gets_lineno = 0;
-    }
-    if (ARGF.next_p == 1) {
-	// we need to shift ARGV and read it into ARGF.
-	ARGF.next_p = 0;
-retry:  
-	if (RARRAY_LEN(ARGF.argv) > 0) {
-	    GC_WB(&ARGF.filename, rb_ary_shift(ARGF.argv));
-	    fn = StringValueCStr(ARGF.filename);
-	    if (strlen(fn) == 1 && fn[0] == '-') {
-		// - means read from standard input, obviously.
-		GC_WB(&ARGF.current_file, rb_stdin);
-		if (ARGF.inplace) {
-		    rb_warn("Can't do inplace edit for stdio; skipping");
-		    goto retry;
-		}
-	    }
-	    else {
-		int fr = open(fn, O_RDONLY);
-		if (ARGF.inplace) {
-		    // we need to rename and create new files for inplace mode
-		    struct stat st, st2;
-		    VALUE str;
-		    int fw;
-		    if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
-			rb_io_close(rb_stdout);
-		    }
-		    fstat(fr, &st);
-		    if (*ARGF.inplace) {
-			// AFAICT, we create a new string here because we need to modify it
-			// and we don't want to mess around with ARGF.filename.
-			str = rb_str_new2(fn);
-			rb_str_cat2(str, ARGF.inplace);
-			if (rename(fn, RSTRING_PTR(str)) < 0) {
-			    rb_warn("Can't rename %s to %s: %s, skipping file",
-				   fn, RSTRING_PTR(str), strerror(errno));
-			    close(fr);
-			    goto retry;
-			}
-		    } 
-		    else {
-			if (unlink(fn) < 0) {
-			    rb_warn("Can't remove %s: %s, skipping file",
-				    fn, strerror(errno));
-			    close(fr);
-			    goto retry;
-			}
-		    }
-		    fw = open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-		    fstat(fw, &st2); // pull out its filestats
-		    fchmod(fw, st.st_mode); // copy the permissions
-		    if ((st.st_uid != st2.st_uid) || (st.st_gid != st2.st_gid)) {
-			// copy the groups and owners
-			fchown(fw, st.st_uid, st.st_gid);
-		    }
-		    rb_stdout = prep_io(fw, FMODE_WRITABLE, rb_cFile);
-		}
-		GC_WB(&ARGF.current_file, prep_io(fr, FMODE_READABLE, rb_cFile));
-	    }
-#if 0 // TODO once we get encodings sorted out.
-	    if (ARGF.encs.enc) {
-		rb_io_t *fptr;
-		GetOpenFile(ARGF.current_file, fptr);
-		fptr->encs = ARGF.encs;
-		clear_codeconv(fptr);
-	    }
-#endif
-	}
-	else {
-	    ARGF.next_p = 1;
-	    return Qfalse;
-	}
-    }
-    else if (ARGF.next_p == -1) {
-	GC_WB(&ARGF.current_file, rb_stdin);
-	GC_WB(&ARGF.filename, rb_str_new2("-"));
-    }
-    return Qtrue;
-}
-
-static VALUE
-argf_getline(VALUE argf, SEL sel, int argc, VALUE *argv)
-{
-    VALUE line;
-
-retry:
-    if (!next_argv()) {
-	return Qnil;
-    }
-    if (ARGF_GENERIC_INPUT_P()) {
-	line = rb_funcall3(ARGF.current_file, rb_intern("gets"), argc, argv);
-    }
-    else {
-	if (argc == 0 && rb_rs == rb_default_rs) {
-	    line = rb_io_gets(ARGF.current_file, 0);
-	}
-	else {
-	    line = rb_io_getline(argc, argv, ARGF.current_file);
-	}
-	if (NIL_P(line) && ARGF.next_p != -1) {
-	    argf_close(ARGF.current_file, 0);
-	    ARGF.next_p = 1;
-	    goto retry;
-	}
-    }
-    if (!NIL_P(line)) {
-	(ARGF.gets_lineno)++;
-	ARGF.lineno = INT2FIX(ARGF.gets_lineno);
-    }
-    return line;
-}
-
-static VALUE
-argf_lineno_getter(ID id, VALUE *var)
-{
-    VALUE argf = *var;
-    return ARGF.lineno;
-}
-
-static void
-argf_lineno_setter(VALUE val, ID id, VALUE *var)
-{
-    VALUE argf = *var;
-    int n = NUM2INT(val);
-    ARGF.gets_lineno = n;
-    ARGF.lineno = INT2FIX(n);    
-}
-
-/*
- *  call-seq:
- *     gets(sep=$/)    => string or nil
- *     gets(limit)     => string or nil
- *     gets(sep,limit) => string or nil
- *
- *  Returns (and assigns to <code>$_</code>) the next line from the list
- *  of files in +ARGV+ (or <code>$*</code>), or from standard input if
- *  no files are present on the command line. Returns +nil+ at end of
- *  file. The optional argument specifies the record separator. The
- *  separator is included with the contents of each record. A separator
- *  of +nil+ reads the entire contents, and a zero-length separator
- *  reads the input one paragraph at a time, where paragraphs are
- *  divided by two consecutive newlines.  If the first argument is an
- *  integer, or optional second argument is given, the returning string
- *  would not be longer than the given value.  If multiple filenames are
- *  present in +ARGV+, +gets(nil)+ will read the contents one file at a
- *  time.
- *
- *     ARGV << "testfile"
- *     print while gets
- *
- *  <em>produces:</em>
- *
- *     This is line one
- *     This is line two
- *     This is line three
- *     And so on...
- *
- *  The style of programming using <code>$_</code> as an implicit
- *  parameter is gradually losing favor in the Ruby community.
- */
-
-static VALUE argf_gets(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_f_gets(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    if (recv == argf) {
-	return argf_gets(argf, 0, argc, argv);
-    }
-    return rb_funcall2(argf, rb_intern("gets"), argc, argv);
-}
-
-static VALUE
-argf_gets(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE line;
-
-    line = argf_getline(argf, 0, argc, argv);
-    rb_lastline_set(line);
-    return line;
-}
-
-/*
- *  call-seq:
- *     readline(sep=$/)     => string
- *     readline(limit)      => string
- *     readline(sep, limit) => string
- *
- *  Equivalent to <code>Kernel::gets</code>, except
- *  +readline+ raises +EOFError+ at end of file.
- */
-
-static VALUE
-argf_readline(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE line;
-
-    if (!next_argv()) {
-	rb_eof_error();
-    }
-    ARGF_FORWARD(argc, argv);
-    line = argf_gets(rcv, sel, argc, argv);
-    if (NIL_P(line)) {
-	rb_eof_error();
-    }
-
-    return line;
-}
-
-static VALUE
-rb_f_readline(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return argf_readline(recv, sel, argc, argv);
-}
-
-static VALUE rb_io_s_readlines(VALUE recv, SEL sel, int argc, VALUE *argv);
-
-/*
- *  call-seq:
- *     readlines(sep=$/)    => array
- *     readlines(limit)     => array
- *     readlines(sep,limit) => array
- *
- *  Returns an array containing the lines returned by calling
- *  <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
- */
-
-static VALUE
-argf_readlines(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE lines = rb_ary_new();
-    while (true) {
-	VALUE line = argf_getline(argf, sel, argc, argv);
-	if (NIL_P(line)) {
-	    break;
-	}
-	rb_ary_push(lines, line);
-    }
-
-    return lines;
-}
-
-static VALUE
-rb_f_readlines(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    return argf_readlines(rcv, sel, argc, argv);
-}
-
-/*
- *  call-seq:
- *     IO.try_convert(obj) -> io or nil
- *
- *  Try to convert <i>obj</i> into an IO, using to_io method.
- *  Returns converted IO or nil if <i>obj</i> cannot be converted
- *  for any reason.
- *
- *     IO.try_convert(STDOUT)     # => STDOUT
- *     IO.try_convert("STDOUT")   # => nil
- */
-static VALUE
-rb_io_s_try_convert(VALUE dummy, SEL sel, VALUE obj)
-{
-    return rb_io_check_io(obj);
-}
-
-/*
- *  call-seq:
- *     `cmd`    => string
- *
- *  Returns the standard output of running _cmd_ in a subshell.
- *  The built-in syntax <code>%x{...}</code> uses
- *  this method. Sets <code>$?</code> to the process status.
- *
- *     `date`                   #=> "Wed Apr  9 08:56:30 CDT 2003\n"
- *     `ls testdir`.split[1]    #=> "main.rb"
- *     `echo oops && exit 99`   #=> "oops\n"
- *     $?.exitstatus            #=> 99
- */
-
-static VALUE
-rb_f_backquote(VALUE obj, SEL sel, VALUE str)
-{
-    VALUE io = rb_io_s_popen(rb_cIO, 0, 1, &str);
-    rb_io_t *io_s = ExtractIOStruct(io);
-
-    VALUE outbuf = rb_bstr_new();
-    rb_io_read_all(ExtractIOStruct(io), outbuf);
-
-    assert(io_s->pid != -1);
-    int status;
-    if (waitpid(io_s->pid, &status, 0) != -1) {
-	rb_last_status_set(status, io_s->pid);
-	io_s->pid = -1;
-    }
-
-    rb_io_close(io);
-
-    rb_str_force_encoding(outbuf, rb_encodings[ENCODING_UTF8]);
-    return outbuf;
-}
-
-/*
- *  call-seq:
- *     IO.select(read_array
- *               [, write_array
- *               [, error_array
- *               [, timeout]]] ) =>  array  or  nil
- *
- *  See <code>Kernel#select</code>.
- */
-
-// helper method. returns the highest-valued file descriptor encountered.
-static int
-build_fd_set_from_io_array(fd_set* set, VALUE arr)
-{
-    int max_fd = 0;
-    FD_ZERO(set);
-    if (!NIL_P(arr)) {
-	if (TYPE(arr) != T_ARRAY) {
-	    rb_raise(rb_eTypeError, "Kernel#select expects arrays of IO objects");
-	}
-
-	long n = RARRAY_LEN(arr);
-	long ii;
-	for (ii = 0; ii < n; ii++) {
-	    VALUE io = RARRAY_AT(arr, ii);
-	    io = rb_check_convert_type(io, T_FILE, "IO", "to_io");
-	    if (NIL_P(io)) {
-		rb_raise(rb_eTypeError, "Kernel#select expects arrays of IO objects");
-	    }
-	    int fd = ExtractIOStruct(io)->fd;
-	    FD_SET(fd, set);
-	    max_fd = MAX(fd, max_fd);
-	}
-    }
-    return max_fd;
-}
-
-static void
-build_timeval_from_numeric(struct timeval *tv, VALUE num)
-{
-    tv->tv_sec = 0L;
-    tv->tv_usec = 0L;
-    if (FIXNUM_P(num)) {
-	if (FIX2LONG(num) < 0) {
-	    rb_raise(rb_eArgError, "select() does not accept negative timeouts.");
-	}
-	tv->tv_sec = FIX2LONG(num);
-    }
-    else if (FIXFLOAT_P(num)) {
-	double quantity = RFLOAT_VALUE(num);
-	if (quantity < 0.0) {
-	    rb_raise(rb_eArgError, "select() does not accept negative timeouts.");
-	}
-	tv->tv_sec = (long)floor(quantity);
-	tv->tv_usec = (long)(1000 * (quantity - floor(quantity)));
-    }
-    else if (!NIL_P(num)) {
-	rb_raise(rb_eTypeError, "timeout parameter must be numeric.");
-    }
-}
-
-static VALUE
-extract_ready_descriptors(VALUE arr, fd_set* set)
-{
-    VALUE ready_ios = rb_ary_new();
-    if (NIL_P(arr)) {
-	return ready_ios;
-    }
-    long len = RARRAY_LEN(arr);
-    long ii;
-    for (ii = 0; ii < len; ii++) {
-	VALUE io = RARRAY_AT(arr, ii);
-	VALUE tmp = rb_check_convert_type(io, T_FILE, "IO", "to_io");
-	if (FD_ISSET(ExtractIOStruct(tmp)->fd, set)) {
-	    rb_ary_push(ready_ios, io);
-	}
-    }
-    return ready_ios;
-}
-
-static VALUE
-rb_f_select(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE read_arr, write_arr, err_arr, timeout_val;
-    VALUE readable_arr, writable_arr, errored_arr;
-    rb_scan_args(argc, argv, "13", &read_arr, &write_arr, &err_arr, &timeout_val);
-    fd_set read_set, write_set, err_set;
-    struct timeval timeout;
-
-    // ndfs has to be 1 + the highest fd we're looking for.
-    int temp = 0;
-    int ndfs = build_fd_set_from_io_array(&read_set, read_arr);
-    temp = build_fd_set_from_io_array(&write_set, write_arr);
-    ndfs = MAX(temp, ndfs);
-    temp = build_fd_set_from_io_array(&err_set, err_arr);
-    ndfs = MAX(temp, ndfs);
-    ndfs++;
-
-    // A timeval of 0 needs to be distinguished from a NULL timeval, as a 
-    // NULL timeval polls indefinitly while a 0 timeval returns immediately.
-    build_timeval_from_numeric(&timeout, timeout_val);
-    struct timeval *timeval_ptr = (NIL_P(timeout_val) ? NULL : &timeout);
-
-    int ready_count = select(ndfs, &read_set, &write_set, &err_set, timeval_ptr);
-    if (ready_count == -1) {
-	rb_sys_fail("select(2) failed");
-    }
-    else if (ready_count == 0) {
-	return Qnil; // no ready file descriptors? return 0.
-    }
-
-    readable_arr = extract_ready_descriptors(read_arr, &read_set);
-    writable_arr = extract_ready_descriptors(write_arr, &write_set);
-    errored_arr = extract_ready_descriptors(err_arr, &err_set);
-
-    return rb_ary_new3(3, readable_arr, writable_arr, errored_arr);
-}
-
-// Here be dragons.
-static VALUE
-rb_io_ctl(VALUE io, VALUE arg, VALUE req, int is_io)
-{
-    rb_secure(2);
-	
-    unsigned long cmd;
-    if (arg == Qnil || arg == Qfalse) {
-	cmd = 0;
-    }
-    else if (FIXNUM_P(arg)) {
-	cmd = FIX2LONG(arg);
-    }
-    else if (arg == Qtrue) {
-	cmd = 1;
-    }
-    else {
-	// TODO arg may be a string
-	cmd = NUM2LONG(arg);
-    }
-
-    unsigned long request;
-    rb_io_t *io_s = ExtractIOStruct(io);
-    if (TYPE(req) == T_STRING) {
-	request = (unsigned long)(intptr_t)RSTRING_PTR(req);
-    }
-    else {
-	request = FIX2ULONG(req);
-    }
-    int retval = is_io ? ioctl(io_s->fd, cmd, request)
-	: fcntl(io_s->fd, cmd, request);
-    return INT2FIX(retval);
-}
-
-/*
- *  call-seq:
- *     ios.ioctl(integer_cmd, arg)    => integer
- *
- *  Provides a mechanism for issuing low-level commands to control or
- *  query I/O devices. Arguments and results are platform dependent. If
- *  <i>arg</i> is a number, its value is passed directly. If it is a
- *  string, it is interpreted as a binary sequence of bytes. On Unix
- *  platforms, see <code>ioctl(2)</code> for details. Not implemented on
- *  all platforms.
- */
-
-static VALUE
-rb_io_ioctl(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE integer_cmd, arg;
-    rb_scan_args(argc, argv, "11", &integer_cmd, &arg);
-
-    rb_io_assert_open(ExtractIOStruct(recv));
-    return rb_io_ctl(recv, integer_cmd, arg, 1);
-}
-
-/*
- *  call-seq:
- *     ios.fcntl(integer_cmd, arg)    => integer
- *
- *  Provides a mechanism for issuing low-level commands to control or
- *  query file-oriented I/O streams. Arguments and results are platform
- *  dependent. If <i>arg</i> is a number, its value is passed
- *  directly. If it is a string, it is interpreted as a binary sequence
- *  of bytes (<code>Array#pack</code> might be a useful way to build this
- *  string). On Unix platforms, see <code>fcntl(2)</code> for details.
- *  Not implemented on all platforms.
- */
-
-static VALUE
-rb_io_fcntl(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE integer_cmd, arg;
-    rb_scan_args(argc, argv, "11", &integer_cmd, &arg);
-
-    rb_io_assert_open(ExtractIOStruct(recv));
-    return rb_io_ctl(recv, integer_cmd, arg, 0);
-}
-
-/*
- *  call-seq:
- *     syscall(fixnum [, args...])   => integer
- *
- *  Calls the operating system function identified by _fixnum_,
- *  passing in the arguments, which must be either +String+
- *  objects, or +Integer+ objects that ultimately fit within
- *  a native +long+. Up to nine parameters may be passed (14
- *  on the Atari-ST). The function identified by _fixnum_ is system
- *  dependent. On some Unix systems, the numbers may be obtained from a
- *  header file called <code>syscall.h</code>.
- *
- *     syscall 4, 1, "hello\n", 6   # '4' is write(2) on our box
- *
- *  <em>produces:</em>
- *
- *     hello
- */
-
-static VALUE
-rb_f_syscall(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    unsigned long arg[8];
-
-    int ii = 1;
-    int retval = -1;
-    int items = argc - 1;
-
-    rb_secure(2);
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "too few arguments to syscall()");
-    }
-    if (argc > 9) {
-	rb_raise(rb_eArgError, "too many arguments to syscall()");
-    }
-
-    arg[0] = NUM2LONG(argv[0]); argv++;
-
-    while (items--) {
-	VALUE v = rb_check_string_type(*argv);
-	if (!NIL_P(v)) {
-	    StringValue(v);
-	    arg[ii] = (unsigned long)StringValueCStr(v);
-	}
-	else {
-	    arg[ii] = (unsigned long)NUM2LONG(*argv);
-	}
-	argv++;
-	ii++;
-    }
-
-    switch (argc) {
-	case 1:
-	    retval = syscall(arg[0]);
-	    break;
-	case 2:
-	    retval = syscall(arg[0],arg[1]);
-	    break;
-	case 3:
-	    retval = syscall(arg[0],arg[1],arg[2]);
-	    break;
-	case 4:
-	    retval = syscall(arg[0],arg[1],arg[2],arg[3]);
-	    break;
-	case 5:
-	    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
-	    break;
-	case 6:
-	    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
-	    break;
-	case 7:
-	    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
-	    break;
-	case 8:
-	    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
-		    arg[7]);
-	    break;
-    }
-
-    if (retval < 0) {
-	rb_sys_fail("call to syscall() failed.");
-    }
-    return INT2NUM(retval);
-}
-/*
- *  call-seq:
- *     IO.pipe                    -> [read_io, write_io]
- *     IO.pipe(ext_enc)           -> [read_io, write_io]
- *     IO.pipe("ext_enc:int_enc") -> [read_io, write_io]
- *     IO.pipe(ext_enc, int_enc)  -> [read_io, write_io]
- *
- *  Creates a pair of pipe endpoints (connected to each other) and
- *  returns them as a two-element array of <code>IO</code> objects:
- *  <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>. Not
- *  available on all platforms.
- *
- *  If an encoding (encoding name or encoding object) is specified as an optional argument,
- *  read string from pipe is tagged with the encoding specified.
- *  If the argument is a colon separated two encoding names "A:B",
- *  the read string is converted from encoding A (external encoding)
- *  to encoding B (internal encoding), then tagged with B.
- *  If two optional arguments are specified, those must be
- *  encoding objects or encoding names,
- *  and the first one is the external encoding,
- *  and the second one is the internal encoding.
- *
- *  In the example below, the two processes close the ends of the pipe
- *  that they are not using. This is not just a cosmetic nicety. The
- *  read end of a pipe will not generate an end of file condition if
- *  there are any writers with the pipe still open. In the case of the
- *  parent process, the <code>rd.read</code> will never return if it
- *  does not first issue a <code>wr.close</code>.
- *
- *     rd, wr = IO.pipe
- *
- *     if fork
- *       wr.close
- *       puts "Parent got: <#{rd.read}>"
- *       rd.close
- *       Process.wait
- *     else
- *       rd.close
- *       puts "Sending message to parent"
- *       wr.write "Hi Dad"
- *       wr.close
- *     end
- *
- *  <em>produces:</em>
- *
- *     Sending message to parent
- *     Parent got: <Hi Dad>
- */
-
-static VALUE
-rb_io_s_pipe(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rd, wr, ext_enc = Qnil, int_enc = Qnil;
-    rb_scan_args(argc, argv, "02", &ext_enc, &int_enc);
-
-    int fd[2] = {-1, -1};
-    if (pipe(fd) != 0) {
-	rb_sys_fail("pipe() failed");
-    }
-
-    rd = prep_io(fd[0], FMODE_READABLE, rb_cIO);
-    wr = prep_io(fd[1], FMODE_WRITABLE, rb_cIO);
-
-    return rb_assoc_new(rd, wr);
-}
-
-/*
- *  call-seq:
- *     IO.foreach(name, sep=$/) {|line| block }     => nil
- *     IO.foreach(name, limit) {|line| block }      => nil
- *     IO.foreach(name, sep, limit) {|line| block } => nil
- *
- *  Executes the block for every line in the named I/O port, where lines
- *  are separated by <em>sep</em>.
- *
- *     IO.foreach("testfile") {|x| print "GOT ", x }
- *
- *  <em>produces:</em>
- *
- *     GOT This is line one
- *     GOT This is line two
- *     GOT This is line three
- *     GOT And so on...
- *
- *  If the last argument is a hash, it's the keyword argument to open.
- *  See <code>IO.read</code> for detail.
- *
- */
-
-static VALUE
-rb_io_s_foreach(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    RETURN_ENUMERATOR(recv, argc, argv);
-    VALUE arr = rb_io_s_readlines(recv, sel, argc, argv);
-    long i, count;
-    for (i = 0, count = RARRAY_LEN(arr); i < count; i++) {
-	VALUE at = RARRAY_AT(arr, i);
-	rb_vm_yield(1, &at);
-	RETURN_IF_BROKEN();
-    }
-    return Qnil;
-}
-
-static VALUE
-io_s_read(struct foreach_arg *arg)
-{
-    return io_read(arg->io, 0, arg->argc, arg->argv);
-}
-
-/*
- *  call-seq:
- *     IO.read(name, [length [, offset]] )   => string
- *     IO.read(name, [length [, offset]], opt)   => string
- *
- *  Opens the file, optionally seeks to the given offset, then returns
- *  <i>length</i> bytes (defaulting to the rest of the file).
- *  <code>read</code> ensures the file is closed before returning.
- *
- *  If the last argument is a hash, it specifies option for internal
- *  open().  The key would be the following.  open_args: is exclusive
- *  to others.
- *
- *   encoding: string or encoding
- *
- *    specifies encoding of the read string.  encoding will be ignored
- *    if length is specified.
- *
- *   mode: string
- *
- *    specifies mode argument for open().  it should start with "r"
- *    otherwise it would cause error.
- *
- *   open_args: array of strings
- *
- *    specifies arguments for open() as an array.
- *
- *     IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
- *     IO.read("testfile", 20)       #=> "This is line one\nThi"
- *     IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "
- */
-
-static VALUE
-rb_io_s_read(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    // TODO handle optional hash
-    /*VALUE opt =*/ pop_last_hash(&argc, argv);
-
-    VALUE fname, length, offset;
-    rb_scan_args(argc, argv, "13", &fname, &length, &offset, NULL);
-
-    FilePathValue(fname);
-    struct foreach_arg arg;
-    arg.io = rb_file_open(io_alloc(recv, 0), 1, &fname);
-    arg.argc = 1;
-    arg.argv = &length;
-
-    if (!NIL_P(offset)) {
-	rb_io_seek(arg.io, offset, 0);
-    }
-    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
-}
-
-static VALUE
-io_s_readlines(struct foreach_arg *arg)
-{
-    return rb_io_readlines(arg->io, 0, arg->argc, arg->argv);
-}
-
-/*
- *  call-seq:
- *     IO.readlines(name, sep=$/)     => array
- *     IO.readlines(name, limit)      => array
- *     IO.readlines(name, sep, limit) => array
- *
- *  Reads the entire file specified by <i>name</i> as individual
- *  lines, and returns those lines in an array. Lines are separated by
- *  <i>sep</i>.
- *
- *     a = IO.readlines("testfile")
- *     a[0]   #=> "This is line one\n"
- *
- *  If the last argument is a hash, it's the keyword argument to open.
- *  See <code>IO.read</code> for detail.
- *
- */
-
-static VALUE
-rb_io_s_readlines(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    // TODO handle optional hash
-    /*VALUE opt =*/ pop_last_hash(&argc, argv);
-
-    VALUE fname;
-    rb_scan_args(argc, argv, "13", &fname, NULL, NULL, NULL);
-
-    struct foreach_arg arg;
-    arg.io = rb_file_open(io_alloc(recv, 0), 1, &fname);
-    arg.argc = argc - 1;
-    arg.argv = argv + 1;
-
-    return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
-}
-
-/*
- *  call-seq:
- *     IO.copy_stream(src, dst)
- *     IO.copy_stream(src, dst, copy_length)
- *     IO.copy_stream(src, dst, copy_length, src_offset)
- *
- *  IO.copy_stream copies <i>src</i> to <i>dst</i>.
- *  <i>src</i> and <i>dst</i> is either a filename or an IO.
- *
- *  This method returns the number of bytes copied.
- *
- *  If optional arguments are not given,
- *  the start position of the copy is
- *  the beginning of the filename or
- *  the current file offset of the IO.
- *  The end position of the copy is the end of file.
- *
- *  If <i>copy_length</i> is given,
- *  No more than <i>copy_length</i> bytes are copied.
- *
- *  If <i>src_offset</i> is given,
- *  it specifies the start position of the copy.
- *
- *  When <i>src_offset</i> is specified and
- *  <i>src</i> is an IO,
- *  IO.copy_stream doesn't move the current file offset.
- *
- */
-static VALUE
-rb_io_s_copy_stream(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE src, dst, len, offset;
-    rb_scan_args(argc, argv, "22", &src, &dst, &len, &offset);
-
-    bool src_is_path = false, dst_is_path = false;
-
-    VALUE old_src_offset = Qnil;
-    if (TYPE(src) != T_FILE) {
-	FilePathValue(src);
-	src_is_path = true;
-    }
-    else {
-	if (!NIL_P(offset)) {
-	    old_src_offset = rb_io_tell(src, 0); // save the old offset
-	    rb_io_seek(src, 0, offset);
-	}
-    }
-
-    if (TYPE(dst) != T_FILE) {
-	FilePathValue(dst);
-	dst_is_path = true;
-    }
-
-    if (src_is_path && dst_is_path) {
-	// Fast path!
-	copyfile_state_t s = copyfile_state_alloc();
-	if (copyfile(RSTRING_PTR(src), RSTRING_PTR(dst), s, COPYFILE_ALL)
-		!= 0) {
-	    copyfile_state_free(s);
-	    rb_sys_fail("copyfile() failed");
-	}
-	int src_fd = -2; 
-	assert(copyfile_state_get(s, COPYFILE_STATE_SRC_FD, &src_fd) == 0);
-	struct stat st;
-	if (fstat(src_fd, &st) != 0) {
-	    rb_sys_fail("fstat() failed");
-	}
-	copyfile_state_free(s);
-	return LONG2NUM(st.st_size);
-    }
-    else {
-	if (src_is_path) {
-	    src = rb_f_open(rcv, 0, 1, &src);
-	}
-	if (dst_is_path) {
-	    VALUE args[2];
-	    args[0] = dst;
-	    args[1] = rb_str_new2("w");
-	    dst = rb_f_open(rcv, 0, 2, args);
-	}
-    }
-
-    VALUE data_read = NIL_P(len)
-	? io_read(src, 0, 0, NULL) : io_read(src, 0, 1, &len);
-
-    VALUE copied = io_write(dst, 0, data_read);
-
-    if (!NIL_P(old_src_offset)) {
-	rb_io_seek(src, old_src_offset, SEEK_SET); // restore the old offset
-    }
-
-    return copied;
-}
-
-/*
- *  call-seq:
- *     io.external_encoding   => encoding
- *
- *  Returns the Encoding object that represents the encoding of the file.
- *  If io is write mode and no encoding is specified, returns <code>nil</code>.
- */
-
-static VALUE
-rb_io_external_encoding(VALUE io, SEL sel)
-{
-    // TODO
-    return (VALUE)rb_locale_encoding();
-}
-
-/*
- *  call-seq:
- *     io.internal_encoding   => encoding
- *
- *  Returns the Encoding of the internal string if conversion is
- *  specified.  Otherwise returns nil.
- */
-
-static VALUE
-rb_io_internal_encoding(VALUE io, SEL sel)
-{
-    // TODO
-    return (VALUE)rb_locale_encoding();
-}
-
-/*
- *  call-seq:
- *     io.set_encoding(ext_enc)           => io
- *     io.set_encoding("ext_enc:int_enc") => io
- *     io.set_encoding(ext_enc, int_enc)  => io
- *
- *  If single argument is specified, read string from io is tagged
- *  with the encoding specified.  If encoding is a colon separated two
- *  encoding names "A:B", the read string is converted from encoding A
- *  (external encoding) to encoding B (internal encoding), then tagged
- *  with B.  If two arguments are specified, those must be encoding
- *  objects or encoding names, and the first one is the external encoding, and the
- *  second one is the internal encoding.
- */
-
-static VALUE
-rb_io_set_encoding(VALUE id, SEL sel, int argc, VALUE *argv)
-{
-    // TODO
-    return Qnil;
-}
-
-static VALUE
-argf_external_encoding(VALUE argf, SEL sel)
-{
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    return rb_io_external_encoding(ARGF.current_file, sel);
-}
-
-static VALUE
-argf_internal_encoding(VALUE argf, SEL sel)
-{
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    return rb_io_internal_encoding(ARGF.current_file, sel);
-}
-
-static VALUE
-argf_set_encoding(VALUE id, SEL sel, int argc, VALUE *argv)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream to set encoding");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_set_encoding(ARGF.current_file, sel, argc, argv);
-}
-
-static VALUE
-argf_tell(VALUE argf, SEL sel)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream to tell");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_tell(ARGF.current_file, 0);
-}
-
-static VALUE
-argf_seek_m(VALUE argf, SEL sel, int argc, VALUE *argv)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream to seek");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_seek_m(ARGF.current_file, sel, argc, argv);
-}
-
-static VALUE
-argf_set_pos(VALUE argf, SEL sel, VALUE offset)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream to set position");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_set_pos(ARGF.current_file, sel, offset);
-}
-
-static VALUE
-argf_rewind(VALUE argf, SEL sel)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream to rewind");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_rewind(ARGF.current_file, 0);
-}
-
-static VALUE
-argf_fileno(VALUE argf, SEL sel)
-{
-    if (!next_argv()) {
-	rb_raise(rb_eArgError, "no stream");
-    }
-    ARGF_FORWARD(0, 0);
-    return rb_io_fileno(ARGF.current_file, 0);
-}
-
-static VALUE
-argf_to_io(VALUE argf, SEL sel)
-{
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    return argf;
-}
-
-static VALUE 
-argf_eof(VALUE argf, SEL sel)
-{
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    return rb_io_eof(ARGF.current_file, 0);
-}
-
-static VALUE
-argf_read(VALUE argf, SEL sel, int argc, VALUE *argv)
-{
-    VALUE tmp, str, length;
-    long len = 0;
-
-    rb_scan_args(argc, argv, "02", &length, &str);
-    if (!NIL_P(length)) {
-	len = NUM2LONG(argv[0]);
-    }
-    if (!NIL_P(str)) {
-	StringValue(str);
-	rb_str_resize(str,0);
-	argv[1] = Qnil;
-    }
-
-  retry:
-    if (!next_argv()) {
-	return str;
-    }
-    if (ARGF_GENERIC_INPUT_P()) {
-	tmp = argf_forward(argf, sel, argc, argv);
-    }
-    else {
-	tmp = io_read(ARGF.current_file, sel, argc, argv);
-    }
-    if (NIL_P(str)) {
-	str = tmp;
-    }
-    else if (!NIL_P(tmp)) {
-	rb_str_append(str, tmp);
-    }
-
-    if (NIL_P(tmp) || NIL_P(length)) {
-	if (ARGF.next_p != -1) {
-	    argf_close(ARGF.current_file, sel);
-	    ARGF.next_p = 1;
-	    goto retry;
-	}
-    }
-    else if (argc >= 1) {
-	if (RSTRING_LEN(str) < len) {
-	    len -= RSTRING_LEN(str);
-	    argv[0] = INT2NUM(len);
-	    goto retry;
-	}
-    }
-    return str;
-}
-
-struct argf_call_arg {
-    int argc;
-    VALUE *argv;
-    VALUE argf;
-};
-
-// static VALUE
-// argf_forward_call(VALUE arg, SEL sel)
-// {
-// rb_notimplement();
-// }
-
-static VALUE
-argf_readpartial(VALUE id, SEL sel, int argc, VALUE *argv)
-{
-    rb_notimplement();
-}
-
-static VALUE
-argf_getc(VALUE argf, SEL sel)
-{
-    VALUE ch;
-
-  retry:
-    if (!next_argv()) {
-	return Qnil;
-    }
-    if (ARGF_GENERIC_INPUT_P()) {
-	ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
-    }
-    else {
-	ch = rb_io_getc(ARGF.current_file, sel);
-    }
-    if (NIL_P(ch) && ARGF.next_p != -1) {
-	argf_close(ARGF.current_file, sel);
-	ARGF.next_p = 1;
-	goto retry;
-    }
-
-    return ch;
-}
-
-static VALUE
-argf_getbyte(VALUE argf, SEL sel)
-{
-    VALUE ch;
-
-  retry:
-    if (!next_argv()) {
-	return Qnil;
-    }
-    if (TYPE(ARGF.current_file) != T_FILE) {
-	ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
-    }
-    else {
-	ch = rb_io_getbyte(ARGF.current_file, sel);
-    }
-    if (NIL_P(ch) && ARGF.next_p != -1) {
-	argf_close(ARGF.current_file, sel);
-	ARGF.next_p = 1;
-	goto retry;
-    }
-
-    return ch;
-}
-
-static VALUE
-argf_readchar(VALUE argf, SEL sel)
-{
-    VALUE ch;
-
-  retry:
-    if (!next_argv()) {
-	rb_eof_error();
-    }
-    if (TYPE(ARGF.current_file) != T_FILE) {
-	ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
-    }
-    else {
-	ch = rb_io_getc(ARGF.current_file, sel);
-    }
-    if (NIL_P(ch) && ARGF.next_p != -1) {
-	argf_close(ARGF.current_file, sel);
-	ARGF.next_p = 1;
-	goto retry;
-    }
-
-    return ch;
-}
-
-static VALUE
-argf_readbyte(VALUE argf, SEL sel)
-{
-    VALUE c;
-
-    NEXT_ARGF_FORWARD(0, 0);
-    c = argf_getbyte(argf, sel);
-    if (NIL_P(c)) {
-	rb_eof_error();
-    }
-    return c;
-}
-
-static VALUE
-argf_each_line(VALUE argf, SEL sel, int argc, VALUE *argv)
-{
-    RETURN_ENUMERATOR(argf, argc, argv);
-    while (true) {
-	if (!next_argv()) {
-	    return argf;
-	}
-	rb_io_each_line(ARGF.current_file, sel, argc, argv);
-	ARGF.next_p = 1;
-    }
-}
-
-static VALUE
-argf_each_byte(VALUE argf, SEL sel)
-{
-    RETURN_ENUMERATOR(argf, 0, 0);
-    while (true) {
-	if (!next_argv()) {
-	    return argf;
-	}
-	rb_io_each_byte(ARGF.current_file, sel);
-	ARGF.next_p = 1;
-    }
-}
-
-static VALUE
-argf_each_char(VALUE argf, SEL sel)
-{
-    RETURN_ENUMERATOR(argf, 0, 0);
-    while (true) {
-	if (!next_argv()) {
-	    return argf;
-	}
-	rb_io_each_char(ARGF.current_file, sel);
-	ARGF.next_p = 1;
-    }
-}
-
-static VALUE
-argf_filename(VALUE argf, SEL sel)
-{
-    next_argv();
-    return ARGF.filename;
-}
-
-static VALUE
-argf_filename_getter(ID id, VALUE *var)
-{
-    return argf_filename(*var, 0);
-}
-
-static VALUE
-argf_file(VALUE argf, SEL sel)
-{
-    next_argv();
-    return ARGF.current_file;
-}
-
-static VALUE
-argf_binmode_m(VALUE argf, SEL sel)
-{
-    ARGF.binmode = 1;
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    rb_io_binmode(ARGF.current_file, 0);
-    return argf;
-}
-
-static VALUE
-argf_skip(VALUE argf, SEL sel)
-{
-    if (ARGF.init_p && ARGF.next_p == 0) {
-	argf_close(ARGF.current_file, 0);
-	ARGF.next_p = 1;
-    }
-    return argf;
-}
-
-static VALUE
-argf_close_m(VALUE argf, SEL sel)
-{
-    next_argv();
-    argf_close(ARGF.current_file, 0);
-    if (ARGF.next_p != -1) {
-	ARGF.next_p = 1;
-    }
-    ARGF.gets_lineno = 0;
-    return argf;
-}
-
-static VALUE
-argf_closed(VALUE argf, SEL sel)
-{
-    next_argv();
-    ARGF_FORWARD(0, 0);
-    return rb_io_closed(ARGF.current_file, 0);
-}
-
-static VALUE
-argf_to_s(VALUE argf, SEL sel)
-{
-    return rb_str_new2("ARGF");
-}
-
-static VALUE
-argf_inplace_mode_get(VALUE argf, SEL sel)
-{
-    if (ARGF.inplace == NULL) {
-	return Qnil;
-    }
-    return rb_str_new2(ARGF.inplace);
-}
-
-static VALUE
-opt_i_get(ID id, VALUE *var)
-{
-    return argf_inplace_mode_get(*var, 0);
-}
-
-static VALUE
-argf_inplace_mode_set(VALUE argf, SEL sel, VALUE val)
-{
-    if (!RTEST(val)) {
-	if (ARGF.inplace != NULL) {
-	    free(ARGF.inplace);
-	}
-	ARGF.inplace = NULL;
-    }
-    else {
-	StringValue(val);
-	if (ARGF.inplace != NULL) {
-	    free(ARGF.inplace);
-	}
-	ARGF.inplace = strdup(RSTRING_PTR(val));
-    }
-    return argf;
-}
-
-static void
-opt_i_set(VALUE val, ID id, VALUE *var)
-{
-    argf_inplace_mode_set(*var, 0, val);
-}
-
-const char *
-ruby_get_inplace_mode(void)
-{
-    return ARGF.inplace;
-}
-
-void
-ruby_set_inplace_mode(const char *suffix)
-{
-    if (ARGF.inplace) free(ARGF.inplace);
-    ARGF.inplace = 0;
-    if (suffix) ARGF.inplace = strdup(suffix);
-}
-
-static VALUE
-argf_argv(VALUE argf, SEL sel)
-{
-    return ARGF.argv;
-}
-
-static VALUE
-argf_argv_getter(ID id, VALUE *var)
-{
-    return argf_argv(*var, 0);
-}
-
-VALUE
-rb_get_argv(void)
-{
-    return ARGF.argv;
-}
-
-/*
- *  Class <code>IO</code> is the basis for all input and output in Ruby.
- *  An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
- *  so may use more than one native operating system stream.
- *
- *  Many of the examples in this section use class <code>File</code>,
- *  the only standard subclass of <code>IO</code>. The two classes are
- *  closely associated.
- *
- *  As used in this section, <em>portname</em> may take any of the
- *  following forms.
- *
- *  * A plain string represents a filename suitable for the underlying
- *    operating system.
- *
- *  * A string starting with ``<code>|</code>'' indicates a subprocess.
- *    The remainder of the string following the ``<code>|</code>'' is
- *    invoked as a process with appropriate input/output channels
- *    connected to it.
- *
- *  * A string equal to ``<code>|-</code>'' will create another Ruby
- *    instance as a subprocess.
- *
- *  Ruby will convert pathnames between different operating system
- *  conventions if possible. For instance, on a Windows system the
- *  filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as
- *  ``<code>\gumby\ruby\test.rb</code>''. When specifying a
- *  Windows-style filename in a Ruby string, remember to escape the
- *  backslashes:
- *
- *     "c:\\gumby\\ruby\\test.rb"
- *
- *  Our examples here will use the Unix-style forward slashes;
- *  <code>File::SEPARATOR</code> can be used to get the
- *  platform-specific separator character.
- *
- *  I/O ports may be opened in any one of several different modes, which
- *  are shown in this section as <em>mode</em>. The mode may
- *  either be a Fixnum or a String. If numeric, it should be
- *  one of the operating system specific constants (O_RDONLY,
- *  O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for
- *  more information.
- *
- *  If the mode is given as a String, it must be one of the
- *  values listed in the following table.
- *
- *    Mode |  Meaning
- *    -----+--------------------------------------------------------
- *    "r"  |  Read-only, starts at beginning of file  (default mode).
- *    -----+--------------------------------------------------------
- *    "r+" |  Read-write, starts at beginning of file.
- *    -----+--------------------------------------------------------
- *    "w"  |  Write-only, truncates existing file
- *         |  to zero length or creates a new file for writing.
- *    -----+--------------------------------------------------------
- *    "w+" |  Read-write, truncates existing file to zero length
- *         |  or creates a new file for reading and writing.
- *    -----+--------------------------------------------------------
- *    "a"  |  Write-only, starts at end of file if file exists,
- *         |  otherwise creates a new file for writing.
- *    -----+--------------------------------------------------------
- *    "a+" |  Read-write, starts at end of file if file exists,
- *         |  otherwise creates a new file for reading and
- *         |  writing.
- *    -----+--------------------------------------------------------
- *     "b" |  (DOS/Windows only) Binary file mode (may appear with
- *         |  any of the key letters listed above).
- *
- *
- *  The global constant ARGF (also accessible as $<) provides an
- *  IO-like stream which allows access to all files mentioned on the
- *  command line (or STDIN if no files are mentioned). ARGF provides
- *  the methods <code>#path</code> and <code>#filename</code> to access
- *  the name of the file currently being read.
- */
- 
- 
-void
-rb_write_error2(const char *mesg, long len)
-{
-    if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
-	fwrite(mesg, sizeof(char), len, stderr);
-    }
-    else {
-	rb_io_write(rb_stderr, rb_str_new(mesg, len));
-    }
-}
-
-void
-rb_write_error(const char *mesg)
-{
-    rb_write_error2(mesg, strlen(mesg));
-}
-
-static void
-must_respond_to(ID mid, VALUE val, ID id)
-{
-    if (!rb_respond_to(val, mid)) {
-	rb_raise(rb_eTypeError, "%s must have %s method, %s given",
-		 rb_id2name(id), rb_id2name(mid),
-		 rb_obj_classname(val));
-    }
-}
-
-static void
-stdout_setter(VALUE val, ID id, VALUE *variable)
-{
-    must_respond_to(id_write, val, id);
-    if (*variable != val) {
-	GC_RELEASE(*variable);
-	*variable = val;
-	GC_RETAIN(*variable);
-    }
-}
-
-static VALUE
-rb_getpass(VALUE self, SEL sel, VALUE prompt)
-{
-    StringValue(prompt);
-    char *pwd = getpass(RSTRING_PTR(prompt));
-    return rb_str_new2(pwd);
-}
-
-void
-Init_IO(void)
-{
-    VALUE rb_cARGF;
-
-    rb_eIOError = rb_define_class("IOError", rb_eStandardError);
-    rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
-
-    id_write = rb_intern("write");
-    id_read = rb_intern("read");
-    id_getc = rb_intern("getc");
-    id_flush = rb_intern("flush");
-    id_encode = rb_intern("encode");
-    id_readpartial = rb_intern("readpartial");
-
-    rb_objc_define_module_function(rb_mKernel, "syscall", rb_f_syscall, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "open", rb_f_open, -1);
-    rb_objc_define_module_function(rb_mKernel, "printf", rb_f_printf, -1);
-    rb_objc_define_module_function(rb_mKernel, "print", rb_f_print, -1);
-    rb_objc_define_module_function(rb_mKernel, "putc", rb_f_putc, 1);
-    rb_objc_define_module_function(rb_mKernel, "puts", rb_f_puts, -1);
-    rb_objc_define_module_function(rb_mKernel, "gets", rb_f_gets, -1);
-    rb_objc_define_module_function(rb_mKernel, "readline", rb_f_readline, -1);
-    rb_objc_define_module_function(rb_mKernel, "select", rb_f_select, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "readlines", rb_f_readlines, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "`", rb_f_backquote, 1);
-
-    rb_objc_define_module_function(rb_mKernel, "p", rb_f_p, -1);
-    rb_objc_define_module_function(rb_mKernel, "display", rb_obj_display, -1);
-
-    rb_cIO = rb_define_class("IO", rb_cObject);
-    rb_include_module(rb_cIO, rb_mEnumerable);
-
-    rb_objc_define_method(*(VALUE *)rb_cIO, "alloc", io_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "new", rb_io_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "open",  rb_io_s_open, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "sysopen",  rb_io_s_sysopen, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "for_fd", rb_io_s_new, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "popen", rb_io_s_popen, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "foreach", rb_io_s_foreach, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "readlines", rb_io_s_readlines, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "read", rb_io_s_read, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "select", rb_f_select, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "pipe", rb_io_s_pipe, -1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "try_convert", rb_io_s_try_convert, 1);
-    rb_objc_define_method(*(VALUE *)rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
-
-    rb_objc_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
-
-    rb_objc_io_finalize_super = rb_objc_install_method2((Class)rb_cIO, "finalize",
-	    (IMP)rb_objc_io_finalize);
-
-    rb_output_fs = Qnil;
-    rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
-
-    rb_rs = rb_default_rs = rb_str_new2("\n");
-    GC_RETAIN(rb_default_rs);
-    GC_RETAIN(rb_rs);
-    rb_output_rs = Qnil;
-    OBJ_FREEZE(rb_default_rs);	/* avoid modifying RS_default */
-    rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
-    rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
-    rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
-
-    rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
-
-    rb_objc_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
-    rb_objc_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
-
-    rb_objc_define_method(rb_cIO, "print", rb_io_print, -1);
-    rb_objc_define_method(rb_cIO, "putc", rb_io_putc, 1);
-    rb_objc_define_method(rb_cIO, "puts", rb_io_puts, -1);
-    rb_objc_define_method(rb_cIO, "printf", rb_io_printf, -1);
-
-    rb_objc_define_method(rb_cIO, "each",  rb_io_each_line, -1);
-    rb_objc_define_method(rb_cIO, "each_line",  rb_io_each_line, -1);
-    rb_objc_define_method(rb_cIO, "each_byte",  rb_io_each_byte, 0);
-    rb_objc_define_method(rb_cIO, "each_char",  rb_io_each_char, 0);
-    rb_objc_define_method(rb_cIO, "lines",  rb_io_lines, -1);
-    rb_objc_define_method(rb_cIO, "bytes",  rb_io_bytes, 0);
-    rb_objc_define_method(rb_cIO, "chars",  rb_io_chars, 0);
-
-    rb_objc_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
-    rb_objc_define_method(rb_cIO, "sysread",  rb_io_sysread, -1);
-
-    rb_objc_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
-    rb_define_alias(rb_cIO, "to_i", "fileno");
-    rb_objc_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
-
-    rb_objc_define_method(rb_cIO, "fsync",   rb_io_fsync, 0);
-    rb_objc_define_method(rb_cIO, "sync",   rb_io_sync, 0);
-    rb_objc_define_method(rb_cIO, "sync=",  rb_io_set_sync, 1);
-
-    rb_objc_define_method(rb_cIO, "lineno",   rb_io_lineno, 0);
-    rb_objc_define_method(rb_cIO, "lineno=",  rb_io_set_lineno, 1);
-
-    rb_objc_define_method(rb_cIO, "readlines",  rb_io_readlines, -1);
-
-    rb_objc_define_method(rb_cIO, "read_nonblock",  io_read_nonblock, -1);
-    rb_objc_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
-    rb_objc_define_method(rb_cIO, "readpartial",  io_readpartial, -1);
-    rb_objc_define_method(rb_cIO, "read",  io_read, -1);
-    rb_objc_define_method(rb_cIO, "write", io_write, 1);
-    rb_objc_define_method(rb_cIO, "gets",  rb_io_gets_m, -1);
-    rb_objc_define_method(rb_cIO, "readline",  rb_io_readline, -1);
-    rb_objc_define_method(rb_cIO, "getc",  rb_io_getc, 0);
-    rb_objc_define_method(rb_cIO, "getbyte",  rb_io_getbyte, 0);
-    rb_objc_define_method(rb_cIO, "readchar",  rb_io_readchar, 0);
-    rb_objc_define_method(rb_cIO, "readbyte",  rb_io_readbyte, 0);
-    rb_objc_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
-    rb_objc_define_method(rb_cIO, "<<",    rb_io_addstr, 1);
-    rb_objc_define_method(rb_cIO, "flush", rb_io_flush, 0);
-    rb_objc_define_method(rb_cIO, "tell", rb_io_tell, 0);
-    rb_objc_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
-    rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
-    rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
-    rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
-    rb_objc_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
-    rb_objc_define_method(rb_cIO, "pos", rb_io_tell, 0);
-    rb_objc_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
-    rb_objc_define_method(rb_cIO, "eof", rb_io_eof, 0);
-    rb_objc_define_method(rb_cIO, "eof?", rb_io_eof, 0);
-
-    rb_objc_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
-    rb_objc_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
-
-    rb_objc_define_method(rb_cIO, "close", rb_io_close_m, 0);
-    rb_objc_define_method(rb_cIO, "closed?", rb_io_closed, 0);
-    rb_objc_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
-    rb_objc_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
-
-    rb_objc_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
-    rb_objc_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
-    rb_objc_define_method(rb_cIO, "binmode",  rb_io_binmode_m, 0);
-    rb_objc_define_method(rb_cIO, "sysseek", rb_io_seek_m, -1);
-
-    rb_objc_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
-    rb_objc_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
-    rb_objc_define_method(rb_cIO, "pid", rb_io_pid, 0);
-    rb_objc_define_method(rb_cIO, "inspect",  rb_io_inspect, 0);
-
-    rb_objc_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
-    rb_objc_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
-    rb_objc_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
-
-    rb_stdin = prep_io(fileno(stdin), FMODE_READABLE, rb_cIO);
-    GC_WB(&(ExtractIOStruct(rb_stdin)->path), CFSTR("<STDIN>"));
-    rb_define_variable("$stdin", &rb_stdin);
-    rb_define_global_const("STDIN", rb_stdin);
-    
-    rb_stdout = prep_io(fileno(stdout), FMODE_WRITABLE, rb_cIO);
-    GC_WB(&(ExtractIOStruct(rb_stdout)->path), CFSTR("<STDOUT>"));
-    rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
-    rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
-    rb_define_global_const("STDOUT", rb_stdout);
-    
-    rb_stderr = prep_io(fileno(stderr), FMODE_WRITABLE|FMODE_SYNC, rb_cIO);
-    GC_WB(&(ExtractIOStruct(rb_stderr)->path), CFSTR("<STDERR>"));
-    rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
-    rb_define_global_const("STDERR", rb_stderr);
- 
-    orig_stdout = rb_stdout;
-    rb_deferr = orig_stderr = rb_stderr;
-
-    rb_cARGF = rb_class_new(rb_cObject);
-    rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
-    rb_objc_define_method(*(VALUE *)rb_cARGF, "alloc", argf_alloc, 0);
-
-    rb_include_module(rb_cARGF, rb_mEnumerable);
-
-    rb_objc_define_method(rb_cARGF, "initialize", argf_initialize, -2);
-    rb_objc_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
-    rb_objc_define_method(rb_cARGF, "to_s", argf_to_s, 0);
-    rb_objc_define_method(rb_cARGF, "argv", argf_argv, 0);
-
-    rb_objc_define_method(rb_cARGF, "fileno", argf_fileno, 0);
-    rb_objc_define_method(rb_cARGF, "to_i", argf_fileno, 0);
-    rb_objc_define_method(rb_cARGF, "to_io", argf_to_io, 0);
-    rb_objc_define_method(rb_cARGF, "each",  argf_each_line, -1);
-    rb_objc_define_method(rb_cARGF, "each_line",  argf_each_line, -1);
-    rb_objc_define_method(rb_cARGF, "each_byte",  argf_each_byte, 0);
-    rb_objc_define_method(rb_cARGF, "each_char",  argf_each_char, 0);
-    rb_objc_define_method(rb_cARGF, "lines", argf_each_line, -1);
-    rb_objc_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
-    rb_objc_define_method(rb_cARGF, "chars", argf_each_char, 0);
-
-    rb_objc_define_method(rb_cARGF, "read",  argf_read, -1);
-    rb_objc_define_method(rb_cARGF, "readpartial",  argf_readpartial, -1);
-    rb_objc_define_method(rb_cARGF, "readlines", argf_readlines, -1);
-    rb_objc_define_method(rb_cARGF, "to_a", argf_readlines, -1);
-    rb_objc_define_method(rb_cARGF, "gets", argf_gets, -1);
-    rb_objc_define_method(rb_cARGF, "readline", argf_readline, -1);
-    rb_objc_define_method(rb_cARGF, "getc", argf_getc, 0);
-    rb_objc_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
-    rb_objc_define_method(rb_cARGF, "readchar", argf_readchar, 0);
-    rb_objc_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
-    rb_objc_define_method(rb_cARGF, "tell", argf_tell, 0);
-    rb_objc_define_method(rb_cARGF, "seek", argf_seek_m, -1);
-    rb_objc_define_method(rb_cARGF, "rewind", argf_rewind, 0);
-    rb_objc_define_method(rb_cARGF, "pos", argf_tell, 0);
-    rb_objc_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
-    rb_objc_define_method(rb_cARGF, "eof", argf_eof, 0);
-    rb_objc_define_method(rb_cARGF, "eof?", argf_eof, 0);
-    rb_objc_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
-
-    rb_objc_define_method(rb_cARGF, "filename", argf_filename, 0);
-    rb_objc_define_method(rb_cARGF, "path", argf_filename, 0);
-    rb_objc_define_method(rb_cARGF, "file", argf_file, 0);
-    rb_objc_define_method(rb_cARGF, "skip", argf_skip, 0);
-    rb_objc_define_method(rb_cARGF, "close", argf_close_m, 0);
-    rb_objc_define_method(rb_cARGF, "closed?", argf_closed, 0);
-
-    rb_objc_define_method(rb_cARGF, "lineno",   argf_lineno, 0);
-    rb_objc_define_method(rb_cARGF, "lineno=",  argf_set_lineno, 1);
-
-    rb_objc_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
-    rb_objc_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
-
-    rb_objc_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
-    rb_objc_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
-    rb_objc_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
-
-    argf = rb_class_new_instance(0, 0, rb_cARGF);
-
-    rb_define_readonly_variable("$<", &argf);
-    rb_define_global_const("ARGF", argf);
-
-    rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
-    rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
-    GC_WB(&(ARGF.filename), rb_str_new2("-"));
-
-    rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
-    rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
-
-    Init_File();
-
-    rb_objc_define_method(rb_cFile, "initialize",  rb_file_initialize, -1);
-
-    rb_file_const("RDONLY", INT2FIX(O_RDONLY));
-    rb_file_const("WRONLY", INT2FIX(O_WRONLY));
-    rb_file_const("RDWR", INT2FIX(O_RDWR));
-    rb_file_const("APPEND", INT2FIX(O_APPEND));
-    rb_file_const("CREAT", INT2FIX(O_CREAT));
-    rb_file_const("EXCL", INT2FIX(O_EXCL));
-    rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
-    rb_file_const("TRUNC", INT2FIX(O_TRUNC));
-    rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
-    rb_file_const("BINARY", INT2FIX(0));
-    rb_file_const("SYNC", INT2FIX(O_SYNC));
-
-    sel_each_byte = sel_registerName("each_byte");
-    sel_each_char = sel_registerName("each_char");
-    sel_each_line = sel_registerName("each_line");
-
-    // MacRuby extensions:
-    rb_objc_define_module_function(rb_mKernel, "getpass", rb_getpass, 1);
-}

Deleted: MacRuby/trunk/irb.1
===================================================================
--- MacRuby/trunk/irb.1	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/irb.1	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,38 +0,0 @@
-.Dd May 20, 2010
-.Dt IRB 1
-.Os
-.Sh NAME
-.Nm macirb , macerb , macri , macrdoc
-.Nd MacRuby helper programs
-.Sh SYNOPSIS
-.Nm macirb
-.Op Ar options
-.Op Ar programfile
-.Op Ar arguments
-.Nm macerb
-.Op Ar switches
-.Op Ar inputfile
-.Nm macri
-.Op Ar options
-.Op Ar names ...
-.Nm macrdoc
-.Op Ar options
-.Op Ar names ...
-.Sh DESCRIPTION
-These are various helper programs that are part of the Ruby distribution. For more information about a specific program, you can use its
-.Fl -help
-flag.
-.Pp
-.Nm macirb
-is the interactive MacRuby interpreter.
-.Pp
-.Nm macerb
-is Tiny eRuby, which interprets a file with embedded Ruby code.
-.Pp
-.Nm macri
-displays information about Ruby classes, modules, and methods.
-.Pp
-.Nm macrdoc
-generates Ruby documentation.
-.Sh SEE ALSO
-.Xr macruby 1

Deleted: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/kernel.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1100 +0,0 @@
-/*
- * MacRuby kernel. This file is compiled into LLVM bitcode and injected into
- * the global module. Some of the functions defined here are inlined in the
- * code MacRuby generates.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "compiler.h"
-#include "bridgesupport.h"
-#include "id.h"
-#include "array.h"
-#include "hash.h"
-#include "encoding.h"
-#include "class.h"
-#include "objc.h"
-
-#ifndef PRIMITIVE
-#define PRIMITIVE
-#endif
-
-PRIMITIVE VALUE
-vm_gc_wb(VALUE *slot, VALUE val)
-{
-    GC_WB_0(slot, val, false);
-    return val;
-}
-
-PRIMITIVE VALUE
-vm_ivar_get(VALUE obj, ID name, void *cache_p)
-{
-    struct icache *cache = (struct icache *)cache_p;
-    VALUE klass = 0;
-
-    if (!SPECIAL_CONST_P(obj)) {
-	klass = *(VALUE *)obj;
-	if (klass == cache->klass) {
-	    if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
-		rb_object_ivar_slot_t *slot;
-use_slot:
-		slot = &ROBJECT(obj)->slots[cache->slot];
-		if (slot->name == name) {
-		    VALUE val = slot->value;
-		    if (val == Qundef) {
-			val = Qnil;
-		    }
-		    return val;
-		}
-	    }
-	    goto find_slot;
-	}
-    }
-
-    if (cache->slot == SLOT_CACHE_VIRGIN) {
-	int slot;
-find_slot:
-	slot = rb_vm_get_ivar_slot(obj, name, true);
-	if (slot >= 0) {
-	    cache->klass = *(VALUE *)obj;
-	    cache->slot = slot;
-	    goto use_slot;
-	}
-	cache->klass = 0;
-	cache->slot = SLOT_CACHE_CANNOT;
-    }
-
-    return rb_ivar_get(obj, name);
-}
-
-PRIMITIVE void
-vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache_p)
-{
-    struct icache *cache = (struct icache *)cache_p; 
-    VALUE klass = 0;
-
-    if (!SPECIAL_CONST_P(obj)) {
-	klass = *(VALUE *)obj;
-	if (klass == cache->klass) {
-	    if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
-		rb_object_ivar_slot_t *slot;
-use_slot:
-		slot = &ROBJECT(obj)->slots[cache->slot];
-		if (slot->name == name) {
-		    if ((ROBJECT(obj)->basic.flags & FL_FREEZE) == FL_FREEZE) {
-			rb_error_frozen("object");
-		    }
-		    GC_WB(&slot->value, val);
-		    return;
-		}
-	    }
-	    goto find_slot;
-	}
-    }
-
-    if (cache->slot == SLOT_CACHE_VIRGIN) {
-	int slot;
-find_slot:
-	slot = rb_vm_get_ivar_slot(obj, name, true);
-	if (slot >= 0) {
-	    cache->klass = *(VALUE *)obj;
-	    cache->slot = slot;
-	    goto use_slot;
-	}
-	cache->slot = SLOT_CACHE_CANNOT;
-    }
-
-    rb_ivar_set(obj, name, val);
-}
-
-PRIMITIVE VALUE
-vm_cvar_get(VALUE klass, ID id, unsigned char check,
-	unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = rb_vm_get_current_class();
-	if (k != NULL) {
-	    klass = (VALUE)k;
-	}
-    }
-    return rb_cvar_get2(klass, id, check);
-}
-
-PRIMITIVE VALUE
-vm_cvar_set(VALUE klass, ID id, VALUE val, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = rb_vm_get_current_class();
-	if (k != NULL) {
-	    klass = (VALUE)k;
-	}
-    }
-    rb_cvar_set(klass, id, val);
-    return val;
-}
-
-PRIMITIVE VALUE
-vm_get_const(VALUE outer, uint64_t outer_mask, void *cache_p, ID path,
-	int flags)
-{
-    struct ccache *cache = (struct ccache *)cache_p;
-    const bool lexical_lookup = (flags & CONST_LOOKUP_LEXICAL);
-    const bool dynamic_class = (flags & CONST_LOOKUP_DYNAMIC_CLASS);
-
-    if (dynamic_class) {
-	Class k = rb_vm_get_current_class();
-	if (lexical_lookup && k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-
-    VALUE val;
-    if (cache->outer == outer && cache->outer_mask == outer_mask
-	    && cache->val != Qundef) {
-	val = cache->val;
-    }
-    else {
-	val = rb_vm_const_lookup_level(outer, outer_mask, path,
-		lexical_lookup, false);
-	cache->outer = outer;
-	cache->outer_mask = outer_mask;
-	cache->val = val;
-    }
-    return val;
-}
-
-PRIMITIVE void 
-vm_set_const(VALUE outer, ID id, VALUE obj, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = rb_vm_get_current_class();
-	if (k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-    rb_const_set(outer, id, obj);
-}
-
-static void __attribute__((noinline))
-vm_resolve_args(VALUE **pargv, size_t argv_size, int *pargc, VALUE *args)
-{
-    unsigned int i, argc = *pargc, real_argc = 0, j = 0;
-    VALUE *argv = *pargv;
-    bool splat_arg_follows = false;
-    for (i = 0; i < argc; i++) {
-	VALUE arg = args[j++];
-	if (arg == SPLAT_ARG_FOLLOWS) {
-	    splat_arg_follows = true;
-	    i--;
-	}
-	else {
-	    if (splat_arg_follows) {
-		VALUE ary = rb_check_convert_type(arg, T_ARRAY, "Array",
-			"to_a");
-		if (NIL_P(ary)) {
-		    ary = rb_ary_new4(1, &arg);
-		}
-		int count = RARRAY_LEN(ary);
-		if (real_argc + count >= argv_size) {
-		    const size_t new_argv_size = real_argc + count + 100;
-		    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
-			    * new_argv_size);
-		    memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
-		    argv = new_argv;
-		    argv_size = new_argv_size;
-		}
-		int j;
-		for (j = 0; j < count; j++) {
-		    argv[real_argc++] = RARRAY_AT(ary, j);
-		}
-		splat_arg_follows = false;
-	    }
-	    else {
-		if (real_argc >= argv_size) {
-		    const size_t new_argv_size = real_argc + 100;
-		    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
-			    * new_argv_size);
-		    memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
-		    argv = new_argv;
-		    argv_size = new_argv_size;
-		}
-		argv[real_argc++] = arg;
-	    }
-	}
-    }
-    *pargv = argv;
-    *pargc = real_argc;
-}
-
-static inline VALUE
-vm_class_of(VALUE obj)
-{
-    // TODO: separate the const bits of CLASS_OF to make sure they will get
-    // reduced by the optimizer.
-    return CLASS_OF(obj);
-}
-
-PRIMITIVE VALUE
-vm_dispatch(VALUE top, VALUE self, void *sel, void *block, unsigned char opt,
-	int argc, VALUE *argv)
-{
-    if (opt & DISPATCH_SUPER) {
-	if (sel == 0) {
-	    rb_raise(rb_eNoMethodError, "super called outside of method");
-	}
-    }
-
-    VALUE buf[100];
-    if (opt & DISPATCH_SPLAT) {
-	if (argc == 1 && !SPECIAL_CONST_P(argv[1])
-		&& *(VALUE *)argv[1] == rb_cRubyArray) {
-	    argc = RARY(argv[1])->len;
-	    argv = rary_ptr(argv[1]);
-	}
-	else {
-	    VALUE *new_argv = buf;
-	    vm_resolve_args(&new_argv, 100, &argc, argv);
-	    argv = new_argv;
-	}
-	if (argc == 0) {
-	    const char *selname = sel_getName((SEL)sel);
-	    const size_t selnamelen = strlen(selname);
-	    if (selname[selnamelen - 1] == ':') {
-		// Because
-		//   def foo; end; foo(*[])
-		// creates foo but dispatches foo:.
-		char buf[100];
-		strncpy(buf, selname, sizeof buf);
-		buf[selnamelen - 1] = '\0';
-		sel = sel_registerName(buf);
-	    }
-	}
-    }
-
-    void *vm = rb_vm_current_vm();
-    VALUE klass = vm_class_of(self);
-    return rb_vm_call0(vm, top, self, (Class)klass, (SEL)sel,
-	    (rb_vm_block_t *)block, opt, argc, argv);
-}
-
-PRIMITIVE VALUE
-vm_yield_args(int argc, unsigned char opt, VALUE *argv)
-{
-    VALUE buf[100];
-    if (opt & DISPATCH_SPLAT) {
-	if (argc == 1 && !SPECIAL_CONST_P(argv[1])
-		&& *(VALUE *)argv[1] == rb_cRubyArray) {
-	    argc = RARY(argv[1])->len;
-	    argv = rary_ptr(argv[1]);
-	}
-	else {
-	    VALUE *new_argv = buf;
-	    vm_resolve_args(&new_argv, 100, &argc, argv);
-	    argv = new_argv;
-	}
-    }
-
-    void *vm = rb_vm_current_vm();
-    return rb_vm_yield_args(vm, argc, argv);
-}
-
-PRIMITIVE VALUE
-vm_get_broken_value(void)
-{
-    return rb_vm_get_broken_value(rb_vm_current_vm());
-}
-
-PRIMITIVE VALUE
-vm_returned_from_block(int id)
-{
-    return rb_vm_returned_from_block(rb_vm_current_vm(), id);
-}
-
-PRIMITIVE void
-vm_release_ownership(VALUE obj)
-{
-    rb_vm_release_ownership(obj);
-}
-
-PRIMITIVE void *
-vm_get_block(VALUE obj)
-{
-    if (obj == Qnil) {
-	return NULL;
-    }
-
-    VALUE proc = rb_check_convert_type(obj, T_DATA, "Proc", "to_proc");
-    if (NIL_P(proc)) {
-	rb_raise(rb_eTypeError,
-		"wrong argument type %s (expected Proc)",
-		rb_obj_classname(obj));
-    }
-    return rb_proc_get_block(proc);
-}
-
-// Only numeric immediates have their lsb at 1.
-#define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1)
-
-#define IMM2DBL(x) (FIXFLOAT_P(x) ? FIXFLOAT2DBL(x) : FIX2LONG(x))
-
-PRIMITIVE VALUE
-vm_fast_plus(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    const long res = FIX2LONG(left) + FIX2LONG(right);
-	    if (FIXABLE(res)) {
-		return LONG2FIX(res);
-	    }
-	}
-	else {
-	    const double res = IMM2DBL(left) + IMM2DBL(right);
-	    return DBL2FIXFLOAT(res);
-	}
-    }
-    return vm_dispatch(0, left, selPLUS, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_minus(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    const long res = FIX2LONG(left) - FIX2LONG(right);
-	    if (FIXABLE(res)) {
-		return LONG2FIX(res);
-	    }
-	}
-	else {
-	    const double res = IMM2DBL(left) - IMM2DBL(right);
-	    return DBL2FIXFLOAT(res);
-	}
-    }
-    return vm_dispatch(0, left, selMINUS, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_mult(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    const long a = FIX2LONG(left);
-	    if (a == 0) {
-		return left;
-	    }
-	    const long b = FIX2LONG(right);
-	    const long res = a * b;
-	    if (FIXABLE(res) && res / a == b) {
-		return LONG2FIX(res);
-	    }
-	}
-	else {
-	    const double res = IMM2DBL(left) * IMM2DBL(right);
-	    return DBL2FIXFLOAT(res);
-	}
-    }
-    return vm_dispatch(0, left, selMULT, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_div(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    const long x = FIX2LONG(left);
-	    const long y = FIX2LONG(right);
-	    if (y != 0) {
-		long res = x / y;
-		if (((x < 0 && y >= 0) || (x >= 0 && y < 0))
-			&& (x % y) != 0) {
-		    res--;
-		}
-		if (FIXABLE(res)) {
-		    return LONG2FIX(res);
-		}
-	    }
-	}
-	else {
-	    const double res = IMM2DBL(left) / IMM2DBL(right);
-	    return DBL2FIXFLOAT(res);
-	}
-    }
-    return vm_dispatch(0, left, selDIV, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_lt(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    return FIX2LONG(left) < FIX2LONG(right) ? Qtrue : Qfalse;
-	}
-	else {
-	    return IMM2DBL(left) < IMM2DBL(right) ? Qtrue : Qfalse;
-	}
-    }
-    return vm_dispatch(0, left, selLT, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_le(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    return FIX2LONG(left) <= FIX2LONG(right) ? Qtrue : Qfalse;
-	}
-	else {
-	    return IMM2DBL(left) <= IMM2DBL(right) ? Qtrue : Qfalse;
-	}
-    }
-    return vm_dispatch(0, left, selLE, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_gt(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    return FIX2LONG(left) > FIX2LONG(right) ? Qtrue : Qfalse;
-	}
-	else {
-	    return IMM2DBL(left) > IMM2DBL(right) ? Qtrue : Qfalse;
-	}
-    }
-    return vm_dispatch(0, left, selGT, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_ge(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	if (FIXNUM_P(left) && FIXNUM_P(right)) {
-	    return FIX2LONG(left) >= FIX2LONG(right) ? Qtrue : Qfalse;
-	}
-	else {
-	    return IMM2DBL(left) >= IMM2DBL(right) ? Qtrue : Qfalse;
-	}
-    }
-    return vm_dispatch(0, left, selGE, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_eq(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0) {
-	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
-		return FIX2LONG(left) == FIX2LONG(right) ? Qtrue : Qfalse;
-	    }
-	    else {
-		return IMM2DBL(left) == IMM2DBL(right) ? Qtrue : Qfalse;
-	    }
-	}
-	if (left == Qtrue || left == Qfalse) {
-	    return left == right ? Qtrue : Qfalse;
-	}
-	// TODO: opt for non-immediate types
-    }
-    return vm_dispatch(0, left, selEq, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_eqq(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0) {
-	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
-		return FIX2LONG(left) == FIX2LONG(right) ? Qtrue : Qfalse;
-	    }
-	    else {
-		return IMM2DBL(left) == IMM2DBL(right) ? Qtrue : Qfalse;
-	    }
-	}
-	if (left == Qtrue || left == Qfalse) {
-	    return left == right ? Qtrue : Qfalse;
-	}
-	// TODO: opt for non-immediate types
-    }
-    return vm_dispatch(0, left, selEqq, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_neq(VALUE left, VALUE right, unsigned char overriden)
-{
-    if (overriden == 0) {
-	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
-	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
-		return FIX2LONG(left) != FIX2LONG(right) ? Qtrue : Qfalse;
-	    }
-	    else {
-		return IMM2DBL(left) != IMM2DBL(right) ? Qtrue : Qfalse;
-	    }
-	} 
-	if (left == Qtrue || left == Qfalse) {
-	    return left != right ? Qtrue : Qfalse;
-	}
-	// TODO: opt for non-immediate types
-    }
-    return vm_dispatch(0, left, selNeq, NULL, 0, 1, &right);
-}
-
-PRIMITIVE VALUE
-vm_fast_aref(VALUE obj, VALUE other, unsigned char overriden)
-{
-    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
-	VALUE klass = *(VALUE *)obj;
-	if (klass == rb_cRubyArray) {
-	    if (FIXNUM_P(other)) {
-		return rary_entry(obj, FIX2LONG(other));
-	    }
-	}
-	else if (klass == rb_cRubyHash) {
-	    return rhash_aref(obj, 0, other);
-	}
-    }
-    return vm_dispatch(0, obj, selAREF, NULL, 0, 1, &other);
-}
-
-PRIMITIVE VALUE
-vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, unsigned char overriden)
-{
-    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
-	VALUE klass = *(VALUE *)obj;
-	if (klass == rb_cRubyArray) {
-	    if (FIXNUM_P(other1)) {
-		rary_store(obj, FIX2LONG(other1), other2);
-		return other2;
-	    }
-	}
-	else if (klass == rb_cRubyHash) {
-	    return rhash_aset(obj, 0, other1, other2);
-	}
-    }
-    VALUE args[] = {other1, other2};
-    return vm_dispatch(0, obj, selASET, NULL, 0, 2, args);
-}
-
-PRIMITIVE VALUE
-vm_fast_shift(VALUE obj, VALUE other, unsigned char overriden)
-{
-    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
-	VALUE klass = *(VALUE *)obj;
-	if (klass == rb_cRubyArray) {
-	    rary_modify(obj);
-	    rary_push(obj, other);
-	    return obj;
-	}
-	else if (klass == rb_cRubyString) {
-	    return rstr_concat(obj, 0, other);
-	}
-    }
-    return vm_dispatch(0, obj, selLTLT, NULL, 0, 1, &other);
-}
-
-PRIMITIVE VALUE
-vm_when_splat(unsigned char overriden, VALUE comparedTo, VALUE splat)
-{
-    VALUE ary = rb_check_convert_type(splat, T_ARRAY, "Array", "to_a");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new4(1, &splat);
-    }
-    long i, count = RARRAY_LEN(ary);
-    for (i = 0; i < count; i++) {
-	VALUE o = RARRAY_AT(ary, i);
-	if (RTEST(vm_fast_eqq(o, comparedTo, overriden))) {
-	    return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-PRIMITIVE void
-vm_set_current_scope(VALUE mod, int scope)
-{
-    rb_vm_set_current_scope(mod, (rb_vm_scope_t)scope);
-}
-
-PRIMITIVE VALUE
-vm_ocval_to_rval(void *ocval)
-{
-    return OC2RB(ocval);
-}
-
-PRIMITIVE VALUE
-vm_char_to_rval(char c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_uchar_to_rval(unsigned char c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_short_to_rval(short c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_ushort_to_rval(unsigned short c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_int_to_rval(int c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_uint_to_rval(unsigned int c)
-{
-    return INT2FIX(c);
-}
-
-PRIMITIVE VALUE
-vm_long_to_rval(long l)
-{
-    return LONG2NUM(l);
-}
-
-PRIMITIVE VALUE
-vm_ulong_to_rval(unsigned long l)
-{
-    return ULONG2NUM(l);
-}
-
-PRIMITIVE VALUE
-vm_long_long_to_rval(long long l)
-{
-    return LL2NUM(l);
-}
-
-PRIMITIVE VALUE
-vm_ulong_long_to_rval(unsigned long long l)
-{
-    return ULL2NUM(l);
-}
-
-PRIMITIVE VALUE
-vm_float_to_rval(float f)
-{
-    return DOUBLE2NUM(f);
-}
-
-PRIMITIVE VALUE
-vm_double_to_rval(double d)
-{
-    return DOUBLE2NUM(d);
-}
-
-PRIMITIVE VALUE
-vm_sel_to_rval(void *sel)
-{
-    return sel == 0 ? Qnil : ID2SYM(rb_intern(sel_getName((SEL)sel)));
-}
-
-PRIMITIVE VALUE
-vm_charptr_to_rval(const char *ptr)
-{
-    return ptr == NULL ? Qnil : rb_str_new2(ptr);
-}
-
-PRIMITIVE void
-vm_rval_to_ocval(VALUE rval, void **ocval)
-{
-    *ocval = rval == Qnil ? NULL : RB2OC(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_bool(VALUE rval, BOOL *ocval)
-{
-    if (rval == Qfalse || rval == Qnil) {
-	*ocval = NO;
-    }
-    else {
-	// All other types should be converted as true, to follow the Ruby
-	// semantics (where for example any integer is always true, even 0).
-	*ocval = YES;
-    }
-}
-
-static inline const char *
-rval_to_c_str(VALUE rval)
-{
-    if (NIL_P(rval)) {
-	return NULL;
-    }
-    else {
-	if (CLASS_OF(rval) == rb_cSymbol) {
-	    return rb_sym2name(rval);
-	}
-	if (rb_obj_is_kind_of(rval, rb_cPointer)) {
-	    return (const char *)rb_pointer_get_data(rval, "^c");
-	}
-	return StringValueCStr(rval);
-    }
-}
-
-PRIMITIVE void
-vm_rval_to_sel(VALUE rval, void **ocval)
-{
-    const char *cstr = rval_to_c_str(rval);
-    *(SEL *)ocval = cstr == NULL ? NULL : sel_registerName(cstr);
-}
-
-PRIMITIVE void
-vm_rval_to_charptr(VALUE rval, const char **ocval)
-{
-    *ocval = rval_to_c_str(rval);
-}
-
-static inline long
-bool_to_fix(VALUE rval)
-{
-    if (rval == Qtrue) {
-	return INT2FIX(1);
-    }
-    if (rval == Qfalse) {
-	return INT2FIX(0);
-    }
-    return rval;
-}
-
-static inline long
-rval_to_long(VALUE rval)
-{
-   return NUM2LONG(rb_Integer(bool_to_fix(rval))); 
-}
-
-static inline long long
-rval_to_long_long(VALUE rval)
-{
-    return NUM2LL(rb_Integer(bool_to_fix(rval)));
-}
-
-static inline double
-rval_to_double(VALUE rval)
-{
-    return RFLOAT_VALUE(rb_Float(bool_to_fix(rval)));
-}
-
-PRIMITIVE void
-vm_rval_to_char(VALUE rval, char *ocval)
-{
-    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
-	*ocval = (char)RSTRING_PTR(rval)[0];
-    }
-    else {
-	*ocval = (char)rval_to_long(rval);
-    }
-}
-
-PRIMITIVE void
-vm_rval_to_uchar(VALUE rval, unsigned char *ocval)
-{
-    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
-	*ocval = (unsigned char)RSTRING_PTR(rval)[0];
-    }
-    else {
-	*ocval = (unsigned char)rval_to_long(rval);
-    }
-}
-
-PRIMITIVE void
-vm_rval_to_short(VALUE rval, short *ocval)
-{
-    *ocval = (short)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_ushort(VALUE rval, unsigned short *ocval)
-{
-    *ocval = (unsigned short)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_int(VALUE rval, int *ocval)
-{
-    *ocval = (int)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_uint(VALUE rval, unsigned int *ocval)
-{
-    *ocval = (unsigned int)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_long(VALUE rval, long *ocval)
-{
-    *ocval = (long)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_ulong(VALUE rval, unsigned long *ocval)
-{
-    *ocval = (unsigned long)rval_to_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_long_long(VALUE rval, long long *ocval)
-{
-    *ocval = (long long)rval_to_long_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_ulong_long(VALUE rval, unsigned long long *ocval)
-{
-    *ocval = (unsigned long long)rval_to_long_long(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_double(VALUE rval, double *ocval)
-{
-    *ocval = (double)rval_to_double(rval);
-}
-
-PRIMITIVE void
-vm_rval_to_float(VALUE rval, float *ocval)
-{
-    *ocval = (float)rval_to_double(rval);
-}
-
-PRIMITIVE void *
-vm_rval_to_cptr(VALUE rval, const char *type, void **cptr)
-{
-    if (NIL_P(rval)) {
-	*cptr = NULL;
-    }
-    else {
-	if (TYPE(rval) == T_ARRAY
-	    || rb_boxed_is_type(CLASS_OF(rval), type + 1)) {
-	    // A convenience helper so that the user can pass a Boxed or an 
-	    // Array object instead of a Pointer to the object.
-	    rval = rb_pointer_new2(type + 1, rval);
-	}
-	*cptr = rb_pointer_get_data(rval, type);
-    }
-    return *cptr;
-}
-
-PRIMITIVE VALUE
-vm_to_a(VALUE obj)
-{
-    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new4(1, &obj);
-    }
-    return ary;
-}
-
-PRIMITIVE VALUE
-vm_to_ary(VALUE obj)
-{
-    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new4(1, &obj);
-    }
-    return ary;
-}
-
-PRIMITIVE VALUE
-vm_ary_cat(VALUE ary, VALUE obj)
-{
-    VALUE ary2 = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
-    if (!NIL_P(ary2)) {
-	rb_ary_concat(ary, ary2);
-    }
-    else {
-	rb_ary_push(ary, obj);
-    }
-    return ary;
-}
-
-PRIMITIVE VALUE
-vm_ary_dup(VALUE ary)
-{
-    return rb_ary_dup(ary);
-}
-
-PRIMITIVE VALUE
-vm_ary_check(VALUE obj, int size)
-{
-    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
-    if (NIL_P(ary)) {
-	rb_raise(rb_eTypeError, "expected Array");
-    }
-    if (RARRAY_LEN(ary) != size) {
-	rb_raise(rb_eArgError, "expected Array of size %d, got %ld",
-		size, RARRAY_LEN(ary));
-    }
-    return ary;
-}
-
-PRIMITIVE VALUE
-vm_ary_entry(VALUE ary, int i)
-{
-    return rb_ary_entry(ary, i);
-}
-
-PRIMITIVE long
-vm_ary_length(VALUE ary)
-{
-    return RARRAY_LEN(ary);
-}
-
-PRIMITIVE const VALUE *
-vm_ary_ptr(VALUE ary)
-{
-    return RARRAY_PTR(ary);
-}
-
-PRIMITIVE VALUE
-vm_rary_new(int len)
-{
-    VALUE ary = rb_ary_new2(len);
-    RARY(ary)->len = len;
-    return ary;
-}
-
-PRIMITIVE void
-vm_rary_aset(VALUE ary, int i, VALUE obj)
-{
-    rary_elt_set(ary, i, obj);
-}
-
-PRIMITIVE VALUE
-vm_rhash_new(void)
-{
-    return rb_hash_new();
-}
-
-PRIMITIVE void
-vm_rhash_store(VALUE hash, VALUE key, VALUE obj)
-{
-    rhash_store(hash, key, obj);
-}
-
-PRIMITIVE VALUE
-vm_masgn_get_elem_before_splat(VALUE ary, int offset)
-{
-    if (offset < RARRAY_LEN(ary)) {
-	return RARRAY_AT(ary, offset);
-    }
-    return Qnil;
-}
-
-PRIMITIVE VALUE
-vm_masgn_get_elem_after_splat(VALUE ary, int before_splat_count,
-	int after_splat_count, int offset)
-{
-    const int len = RARRAY_LEN(ary);
-    if (len < before_splat_count + after_splat_count) {
-	offset += before_splat_count;
-	if (offset < len) {
-	    return RARRAY_AT(ary, offset);
-	}
-    }
-    else {
-	offset += len - after_splat_count;
-	return RARRAY_AT(ary, offset);
-    }
-    return Qnil;
-}
-
-PRIMITIVE VALUE
-vm_masgn_get_splat(VALUE ary, int before_splat_count, int after_splat_count)
-{
-    const int len = RARRAY_LEN(ary);
-    if (len > before_splat_count + after_splat_count) {
-	return rb_ary_subseq(ary, before_splat_count,
-		len - before_splat_count - after_splat_count);
-    }
-    else {
-	return rb_ary_new();
-    }
-}
-
-PRIMITIVE VALUE
-vm_get_special(char code)
-{
-    VALUE backref = rb_backref_get();
-    if (backref == Qnil) {
-	return Qnil;
-    }
-
-    VALUE val;
-    switch (code) {
-	case '&':
-	    val = rb_reg_last_match(backref);
-	    break;
-	case '`':
-	    val = rb_reg_match_pre(backref);
-	    break;
-	case '\'':
-	    val = rb_reg_match_post(backref);
-	    break;
-	case '+':
-	    val = rb_reg_match_last(backref);
-	    break;
-	default:
-	    // Boundaries check is done in rb_reg_nth_match().
-	    val = rb_reg_nth_match((int)code, backref);
-	    break;
-    }
-    return val;
-}
-
-// Support for C-level blocks.
-// Following the ABI specifications as documented in the
-// BlockImplementation.txt file of LLVM.
-
-struct ruby_block_descriptor {
-    unsigned long int reserved;
-    unsigned long int block_size;
-};
-
-struct ruby_block_literal {
-    void *isa;
-    int flags;
-    int reserved;
-    void *imp;
-    struct ruby_block_descriptor *descriptor;
-    VALUE ruby_proc;
-};
-
-static struct ruby_block_descriptor ruby_block_descriptor_value = {
-    0, sizeof(struct ruby_block_literal)
-};
-
-extern void *_NSConcreteAutoBlock[32];
-
-#define __MR_BLOCK_IS_GC		(1 << 27)
-#define __MR_BLOCK_HAS_DESCRIPTOR 	(1 << 29)
-
-PRIMITIVE void
-vm_init_c_block(struct ruby_block_literal *b, void *imp, VALUE proc)
-{
-    b->isa = &_NSConcreteAutoBlock;
-    b->flags = __MR_BLOCK_IS_GC | __MR_BLOCK_HAS_DESCRIPTOR;
-    b->reserved = 0;
-    b->imp = imp;
-    b->descriptor = &ruby_block_descriptor_value;
-    GC_WB(&b->ruby_proc, proc);
-}
-
-PRIMITIVE VALUE
-vm_ruby_block_literal_proc(struct ruby_block_literal *b)
-{
-    return b->ruby_proc;
-}

Deleted: MacRuby/trunk/keywords
===================================================================
--- MacRuby/trunk/keywords	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/keywords	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,51 +0,0 @@
-%{
-struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
-const struct kwtable *rb_reserved_word(const char *, unsigned int);
-#ifndef RIPPER
-%}
-
-struct kwtable;
-%%
-__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END
-__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
-__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
-BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
-END, {keyword_END, keyword_END}, EXPR_END
-alias, {keyword_alias, keyword_alias}, EXPR_FNAME
-and, {keyword_and, keyword_and}, EXPR_VALUE
-begin, {keyword_begin, keyword_begin}, EXPR_BEG
-break, {keyword_break, keyword_break}, EXPR_MID
-case, {keyword_case, keyword_case}, EXPR_VALUE
-class, {keyword_class, keyword_class}, EXPR_CLASS
-def, {keyword_def, keyword_def}, EXPR_FNAME
-defined?, {keyword_defined, keyword_defined}, EXPR_ARG
-do, {keyword_do, keyword_do}, EXPR_BEG
-else, {keyword_else, keyword_else}, EXPR_BEG
-elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
-end, {keyword_end, keyword_end}, EXPR_END
-ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
-false, {keyword_false, keyword_false}, EXPR_END
-for, {keyword_for, keyword_for}, EXPR_VALUE
-if, {keyword_if, modifier_if}, EXPR_VALUE
-in, {keyword_in, keyword_in}, EXPR_VALUE
-module, {keyword_module, keyword_module}, EXPR_VALUE
-next, {keyword_next, keyword_next}, EXPR_MID
-nil, {keyword_nil, keyword_nil}, EXPR_END
-not, {keyword_not, keyword_not}, EXPR_VALUE
-or, {keyword_or, keyword_or}, EXPR_VALUE
-redo, {keyword_redo, keyword_redo}, EXPR_END
-rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
-retry, {keyword_retry, keyword_retry}, EXPR_END
-return, {keyword_return, keyword_return}, EXPR_MID
-self, {keyword_self, keyword_self}, EXPR_END
-super, {keyword_super, keyword_super}, EXPR_ARG
-then, {keyword_then, keyword_then}, EXPR_BEG
-true, {keyword_true, keyword_true}, EXPR_END
-undef, {keyword_undef, keyword_undef}, EXPR_FNAME
-unless, {keyword_unless, modifier_unless}, EXPR_VALUE
-until, {keyword_until, modifier_until}, EXPR_VALUE
-when, {keyword_when, keyword_when}, EXPR_VALUE
-while, {keyword_while, modifier_while}, EXPR_VALUE
-yield, {keyword_yield, keyword_yield}, EXPR_ARG
-%%
-#endif

Deleted: MacRuby/trunk/lex.c.blt
===================================================================
--- MacRuby/trunk/lex.c.blt	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/lex.c.blt	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,214 +0,0 @@
-/* C code produced by gperf version 3.0.2 */
-/* Command-line: gperf --output-file=lex.c.tmp -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' keywords  */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf at gnu.org>."
-#endif
-
-#line 1 "keywords"
-
-struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
-const struct kwtable *rb_reserved_word(const char *, unsigned int);
-#ifndef RIPPER
-#line 7 "keywords"
-struct kwtable;
-
-#define TOTAL_KEYWORDS 41
-#define MIN_WORD_LENGTH 2
-#define MAX_WORD_LENGTH 12
-#define MIN_HASH_VALUE 8
-#define MAX_HASH_VALUE 50
-/* maximum key range = 43, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
-     register const char *str;
-     register unsigned int len;
-{
-  static const unsigned char asso_values[] =
-    {
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 26, 51, 51, 14, 51, 16,  8,
-      11, 13, 51, 51, 51, 51, 10, 51, 13, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 11, 51, 13,  1, 26,
-       4,  1,  8, 28, 51, 23, 51,  1,  1, 27,
-       5, 19, 21, 51,  8,  3,  3, 11, 51, 21,
-      24, 16, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-      51, 51, 51, 51, 51, 51
-    };
-  register int hval = len;
-
-  switch (hval)
-    {
-      default:
-        hval += asso_values[(unsigned char)str[2]];
-      /*FALLTHROUGH*/
-      case 2:
-      case 1:
-        hval += asso_values[(unsigned char)str[0]];
-        break;
-    }
-  return hval + asso_values[(unsigned char)str[len - 1]];
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-const struct kwtable *
-rb_reserved_word (str, len)
-     register const char *str;
-     register unsigned int len;
-{
-  static const struct kwtable wordlist[] =
-    {
-      {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 17 "keywords"
-      {"break", {keyword_break, keyword_break}, EXPR_MID},
-#line 23 "keywords"
-      {"else", {keyword_else, keyword_else}, EXPR_BEG},
-#line 33 "keywords"
-      {"nil", {keyword_nil, keyword_nil}, EXPR_END},
-#line 26 "keywords"
-      {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
-#line 25 "keywords"
-      {"end", {keyword_end, keyword_end}, EXPR_END},
-#line 42 "keywords"
-      {"then", {keyword_then, keyword_then}, EXPR_BEG},
-#line 34 "keywords"
-      {"not", {keyword_not, keyword_not}, EXPR_VALUE},
-#line 27 "keywords"
-      {"false", {keyword_false, keyword_false}, EXPR_END},
-#line 40 "keywords"
-      {"self", {keyword_self, keyword_self}, EXPR_END},
-#line 24 "keywords"
-      {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
-#line 37 "keywords"
-      {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
-#line 43 "keywords"
-      {"true", {keyword_true, keyword_true}, EXPR_END},
-#line 46 "keywords"
-      {"until", {keyword_until, modifier_until}, EXPR_VALUE},
-#line 45 "keywords"
-      {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
-#line 39 "keywords"
-      {"return", {keyword_return, keyword_return}, EXPR_MID},
-#line 20 "keywords"
-      {"def", {keyword_def, keyword_def}, EXPR_FNAME},
-#line 15 "keywords"
-      {"and", {keyword_and, keyword_and}, EXPR_VALUE},
-#line 22 "keywords"
-      {"do", {keyword_do, keyword_do}, EXPR_BEG},
-#line 49 "keywords"
-      {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
-#line 28 "keywords"
-      {"for", {keyword_for, keyword_for}, EXPR_VALUE},
-#line 44 "keywords"
-      {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
-#line 35 "keywords"
-      {"or", {keyword_or, keyword_or}, EXPR_VALUE},
-#line 30 "keywords"
-      {"in", {keyword_in, keyword_in}, EXPR_VALUE},
-#line 47 "keywords"
-      {"when", {keyword_when, keyword_when}, EXPR_VALUE},
-#line 38 "keywords"
-      {"retry", {keyword_retry, keyword_retry}, EXPR_END},
-#line 29 "keywords"
-      {"if", {keyword_if, modifier_if}, EXPR_VALUE},
-#line 18 "keywords"
-      {"case", {keyword_case, keyword_case}, EXPR_VALUE},
-#line 36 "keywords"
-      {"redo", {keyword_redo, keyword_redo}, EXPR_END},
-#line 32 "keywords"
-      {"next", {keyword_next, keyword_next}, EXPR_MID},
-#line 41 "keywords"
-      {"super", {keyword_super, keyword_super}, EXPR_ARG},
-#line 31 "keywords"
-      {"module", {keyword_module, keyword_module}, EXPR_VALUE},
-#line 16 "keywords"
-      {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
-#line 10 "keywords"
-      {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
-#line 11 "keywords"
-      {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
-#line 9 "keywords"
-      {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
-#line 13 "keywords"
-      {"END", {keyword_END, keyword_END}, EXPR_END},
-#line 14 "keywords"
-      {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
-#line 12 "keywords"
-      {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
-#line 21 "keywords"
-      {"defined?", {keyword_defined, keyword_defined}, EXPR_ARG},
-#line 19 "keywords"
-      {"class", {keyword_class, keyword_class}, EXPR_CLASS},
-      {""}, {""},
-#line 48 "keywords"
-      {"while", {keyword_while, modifier_while}, EXPR_VALUE}
-    };
-
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register const char *s = wordlist[key].name;
-
-          if (*str == *s && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}
-#line 50 "keywords"
-
-#endif

Deleted: MacRuby/trunk/lex.c.src
===================================================================
--- MacRuby/trunk/lex.c.src	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/lex.c.src	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,51 +0,0 @@
-%{
-struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
-const struct kwtable *rb_reserved_word(const char *, unsigned int);
-#ifndef RIPPER
-%}
-
-struct kwtable;
-%%
-__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END
-__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
-__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
-BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
-END, {keyword_END, keyword_END}, EXPR_END
-alias, {keyword_alias, keyword_alias}, EXPR_FNAME
-and, {keyword_and, keyword_and}, EXPR_VALUE
-begin, {keyword_begin, keyword_begin}, EXPR_BEG
-break, {keyword_break, keyword_break}, EXPR_MID
-case, {keyword_case, keyword_case}, EXPR_VALUE
-class, {keyword_class, keyword_class}, EXPR_CLASS
-def, {keyword_def, keyword_def}, EXPR_FNAME
-defined?, {keyword_defined, keyword_defined}, EXPR_ARG
-do, {keyword_do, keyword_do}, EXPR_BEG
-else, {keyword_else, keyword_else}, EXPR_BEG
-elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
-end, {keyword_end, keyword_end}, EXPR_END
-ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
-false, {keyword_false, keyword_false}, EXPR_END
-for, {keyword_for, keyword_for}, EXPR_VALUE
-if, {keyword_if, modifier_if}, EXPR_VALUE
-in, {keyword_in, keyword_in}, EXPR_VALUE
-module, {keyword_module, keyword_module}, EXPR_VALUE
-next, {keyword_next, keyword_next}, EXPR_MID
-nil, {keyword_nil, keyword_nil}, EXPR_END
-not, {keyword_not, keyword_not}, EXPR_VALUE
-or, {keyword_or, keyword_or}, EXPR_VALUE
-redo, {keyword_redo, keyword_redo}, EXPR_END
-rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
-retry, {keyword_retry, keyword_retry}, EXPR_END
-return, {keyword_return, keyword_return}, EXPR_MID
-self, {keyword_self, keyword_self}, EXPR_END
-super, {keyword_super, keyword_super}, EXPR_ARG
-then, {keyword_then, keyword_then}, EXPR_BEG
-true, {keyword_true, keyword_true}, EXPR_END
-undef, {keyword_undef, keyword_undef}, EXPR_FNAME
-unless, {keyword_unless, modifier_unless}, EXPR_VALUE
-until, {keyword_until, modifier_until}, EXPR_VALUE
-when, {keyword_when, keyword_when}, EXPR_VALUE
-while, {keyword_while, modifier_while}, EXPR_VALUE
-yield, {keyword_yield, keyword_yield}, EXPR_ARG
-%%
-#endif

Deleted: MacRuby/trunk/lgamma_r.c
===================================================================
--- MacRuby/trunk/lgamma_r.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/lgamma_r.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,68 +0,0 @@
-/* lgamma_r.c  - public domain implementation of error function lgamma_r(3m)
-
-lgamma_r() is based on gamma().  modified by Tanaka Akira.
-
-reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten
-            (New Algorithm handbook in C language) (Gijyutsu hyouron
-            sha, Tokyo, 1991) [in Japanese]
-            http://oku.edu.mie-u.ac.jp/~okumura/algo/
-*/
-
-/***********************************************************
-    gamma.c -- Gamma function
-***********************************************************/
-#include <math.h>
-#include <errno.h>
-#define PI      3.14159265358979324  /* $\pi$ */
-#define LOG_2PI 1.83787706640934548  /* $\log 2\pi$ */
-#define LOG_PI  1.14472988584940017  /* $\log_e \pi$ */
-#define N       8
-
-#define B0  1                 /* Bernoulli numbers */
-#define B1  (-1.0 / 2.0)
-#define B2  ( 1.0 / 6.0)
-#define B4  (-1.0 / 30.0)
-#define B6  ( 1.0 / 42.0)
-#define B8  (-1.0 / 30.0)
-#define B10 ( 5.0 / 66.0)
-#define B12 (-691.0 / 2730.0)
-#define B14 ( 7.0 / 6.0)
-#define B16 (-3617.0 / 510.0)
-
-static double
-loggamma(double x)  /* the natural logarithm of the Gamma function. */
-{
-    double v, w;
-
-    if (x == 1.0 || x == 2.0) return 0.0;
-
-    v = 1;
-    while (x < N) {  v *= x;  x++;  }
-    w = 1 / (x * x);
-    return ((((((((B16 / (16 * 15))  * w + (B14 / (14 * 13))) * w
-                + (B12 / (12 * 11))) * w + (B10 / (10 *  9))) * w
-                + (B8  / ( 8 *  7))) * w + (B6  / ( 6 *  5))) * w
-                + (B4  / ( 4 *  3))) * w + (B2  / ( 2 *  1))) / x
-                + 0.5 * LOG_2PI - log(v) - x + (x - 0.5) * log(x);
-}
-
-/* the natural logarithm of the absolute value of the Gamma function */
-double
-lgamma_r(double x, int *signp)
-{
-    if (x <= 0) {
-        double i, f, s;
-        f = modf(-x, &i);
-        if (f == 0.0) { /* pole error */
-            *signp = 1;
-            errno = ERANGE;
-            return HUGE_VAL;
-        }
-        *signp = (fmod(i, 2.0) != 0.0) ? 1 : -1;
-        s = sin(PI * f);
-        if (s < 0) s = -s;
-        return LOG_PI - log(s) - loggamma(1 - x);
-    }
-    *signp = 1;
-    return loggamma(x);
-}

Deleted: MacRuby/trunk/llvm.h
===================================================================
--- MacRuby/trunk/llvm.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/llvm.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,30 +0,0 @@
-#ifndef __MR_LLVM_H_
-#define __MR_LLVM_H_
-
-#if MACRUBY_STATIC
-# include <string>
-# include <vector>
-# include <map>
-#else
-
-// This file must be included at the very beginning of every C++ file in the
-// project, due to type collisions between LLVM and the MRI C API.
-
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/Constants.h>
-#include <llvm/CallingConv.h>
-#include <llvm/Instructions.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/Analysis/DebugInfo.h>
-#if !defined(LLVM_TOT)
-# include <llvm/Analysis/DIBuilder.h>
-#endif
-#include <llvm/ExecutionEngine/JIT.h>
-#include <llvm/PassManager.h>
-#include <llvm/Target/TargetData.h>
-using namespace llvm;
-
-#endif // !MACRUBY_STATIC
-
-#endif // __MR_LLVM_H_

Deleted: MacRuby/trunk/load.c
===================================================================
--- MacRuby/trunk/load.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/load.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,433 +0,0 @@
-/*
- * MacRuby file loader.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- */
-
-#include <sys/stat.h>
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "dln.h"
-
-extern bool ruby_is_miniruby;
-static bool rbo_enabled = true;
-
-VALUE
-rb_get_load_path(void)
-{
-    VALUE load_path = rb_vm_load_path();
-    VALUE ary = rb_ary_new();
-    for (long i = 0, count = RARRAY_LEN(load_path); i < count; i++) {
-	rb_ary_push(ary, rb_file_expand_path(RARRAY_AT(load_path, i), Qnil));
-    }
-    return ary;
-}
-
-static VALUE
-get_loaded_features(void)
-{
-    return rb_vm_loaded_features();
-}
-
-int
-rb_provided(const char *feature)
-{
-    VALUE ary = get_loaded_features();
-    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	VALUE path = RARRAY_AT(ary, i);
-	// TODO: this is very naive
-	if (strstr(RSTRING_PTR(path), feature) != NULL) {
-	    return true;
-	}
-    }
-    return false;
-}
-
-static void
-rb_provide_feature(VALUE feature)
-{
-    rb_ary_push(get_loaded_features(), feature);
-}
-
-#if !defined(MACRUBY_STATIC)
-static void
-load_failed(VALUE fname)
-{
-    rb_raise(rb_eLoadError, "no such file to load -- %s",
-	    RSTRING_PTR(fname));
-}
-#endif
-
-void
-rb_provide(const char *feature)
-{
-    rb_provide_feature(rb_str_new2(feature));
-}
-
-void
-rb_load(VALUE fname, int wrap)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "#load is not supported in MacRuby static");
-#else
-    // TODO honor wrap
-
-    // Locate file.
-    FilePathValue(fname);
-    fname = rb_str_new4(fname);
-    VALUE tmp = rb_find_file(fname);
-    if (tmp == 0) {
-	load_failed(fname);
-    }
-    fname = tmp;
-
-    // Load it.
-    const char *fname_str = RSTRING_PTR(fname);
-//printf("load %s\n", fname_str);
-
-    rb_vm_binding_t *b = rb_vm_current_binding();
-    if (b != NULL) {
-	rb_vm_pop_binding();
-    }
-    NODE *node = (NODE *)rb_load_file(fname_str);
-    if (b != NULL) {
-	rb_vm_add_binding(b);
-    }
-    if (node == NULL) {
-	rb_raise(rb_eSyntaxError, "compile error");
-    }
-    Class old_klass = rb_vm_set_current_class(NULL);
-    rb_vm_run(fname_str, node, NULL, false);
-    rb_vm_set_current_class(old_klass);
-#endif
-}
-
-/*
- *  call-seq:
- *     load(filename, wrap=false)   => true
- *  
- *  Loads and executes the Ruby
- *  program in the file _filename_. If the filename does not
- *  resolve to an absolute path, the file is searched for in the library
- *  directories listed in <code>$:</code>. If the optional _wrap_
- *  parameter is +true+, the loaded script will be executed
- *  under an anonymous module, protecting the calling program's global
- *  namespace. In no circumstance will any local variables in the loaded
- *  file be propagated to the loading environment.
- */
-
-static VALUE
-rb_f_load(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE fname, wrap;
-
-    rb_scan_args(argc, argv, "11", &fname, &wrap);
-    rb_load(fname, RTEST(wrap));
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     require(string)    => true or false
- *  
- *  Ruby tries to load the library named _string_, returning
- *  +true+ if successful. If the filename does not resolve to
- *  an absolute path, it will be searched for in the directories listed
- *  in <code>$:</code>. If the file has the extension ``.rb'', it is
- *  loaded as a source file; if the extension is ``.so'', ``.o'', or
- *  ``.dll'', or whatever the default shared library extension is on
- *  the current platform, Ruby loads the shared library as a Ruby
- *  extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
- *  to the name. The name of the loaded feature is added to the array in
- *  <code>$"</code>. A feature will not be loaded if it's name already
- *  appears in <code>$"</code>. However, the file name is not converted
- *  to an absolute path, so that ``<code>require 'a';require
- *  './a'</code>'' will load <code>a.rb</code> twice.
- *     
- *     require "my-library.rb"
- *     require "db-driver"
- */
-
-VALUE
-rb_f_require(VALUE obj, VALUE fname)
-{
-    return rb_require_safe(fname, rb_safe_level());
-}
-
-static VALUE
-rb_f_require_imp(VALUE obj, SEL sel, VALUE fname)
-{
-    return rb_f_require(obj, fname);
-}
-
-#if !defined(MACRUBY_STATIC)
-#define TYPE_RB		0x1
-#define TYPE_RBO	0x2
-#define TYPE_BUNDLE	0x3
-
-static bool
-path_ok(const char *path, VALUE *out)
-{
-    struct stat s;
-    if (stat(path, &s) == 0 && S_ISREG(s.st_mode)) {
-	VALUE found_path = rb_str_new2(path);
-	VALUE features = get_loaded_features();
-	*out = rb_ary_includes(features, found_path) == Qtrue
-	    ? 0 : found_path;
-	return true;
-    }
-    return false;
-}
-
-static bool
-check_path(const char *path, VALUE *out, int *type)
-{
-    char *p = strrchr(path, '.');
-    if (p != NULL) {
-	// The given path already contains a file extension. Let's check if
-	// it's a valid one, then try to validate the path.
-	int t = 0;
-	if (strcmp(p + 1, "rb") == 0) {
-	    t = TYPE_RB;
-	}
-	else if (rbo_enabled && strcmp(p + 1, "rbo") == 0) {
-	    t = TYPE_RBO;
-	}
-	else if (strcmp(p + 1, "bundle") == 0) {
-	    t = TYPE_BUNDLE;
-	}
-	if (t != 0 && path_ok(path, out)) {
-	    *type = t;
-	    return true;
-	}
-    }
-
-    // No valid extension, let's append the valid ones and try to validate
-    // the path.
-    char buf[PATH_MAX];
-    if (rbo_enabled) {
-	snprintf(buf, sizeof buf, "%s.rbo", path);
-	if (path_ok(buf, out)) {
-	    *type = TYPE_RBO;
-	    return true;
-	}
-    }
-    snprintf(buf, sizeof buf, "%s.rb", path);
-    if (path_ok(buf, out)) {
-	*type = TYPE_RB;
-	return true;
-    }
-    snprintf(buf, sizeof buf, "%s.bundle", path);
-    if (path_ok(buf, out)) {
-	*type = TYPE_BUNDLE;
-	return true;
-    }
-
-    return false;
-}
-
-static bool
-search_required(VALUE name, VALUE *out, int *type)
-{
-    const char *name_cstr = RSTRING_PTR(name);
-    if (*name_cstr == '/' || *name_cstr == '.' || *name_cstr == '~') {
-	// Given name is an absolute path.
-	name = rb_file_expand_path(name, Qnil);
-	return check_path(RSTRING_PTR(name), out, type);	
-    }
-
-    // Given name is not an absolute path, we need to go through $:.
-    VALUE load_path = rb_get_load_path();
-    for (long i = 0, count = RARRAY_LEN(load_path); i < count; i++) {
-	const char *path = RSTRING_PTR(RARRAY_AT(load_path, i));
-	char buf[PATH_MAX];
-	snprintf(buf, sizeof buf, "%s/%s", path, name_cstr);
-	if (check_path(buf, out, type)) {
-	    return true;
-	}
-    }
-
-    return false;
-}
-
-static VALUE
-load_try(VALUE path)
-{
-    rb_load(path, 0);
-    return Qnil;
-}
-
-static void
-rb_remove_feature(VALUE feature)
-{
-    rb_ary_delete(get_loaded_features(), feature);
-}
-
-static VALUE
-load_rescue(VALUE path, VALUE exc)
-{
-    rb_remove_feature(path);
-    rb_exc_raise(exc);
-    return Qnil;
-}
-#endif
-
-VALUE
-rb_require_safe(VALUE fname, int safe)
-{
-    FilePathValue(fname);
-
-    // Immediately, check out if we have an AOT feature for this.
-    if (rb_vm_aot_feature_load(RSTRING_PTR(fname))) {
-	rb_provide_feature(fname);
-	return Qtrue;
-    }
-
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "#require is not supported in MacRuby static");
-#else
-    VALUE result = Qnil;
-    VALUE path;
-    int type = 0;
-
-    if (search_required(fname, &path, &type)) {
-	if (path == 0) {
-	    result = Qfalse;
-	}
-	else {
-	    rb_set_safe_level_force(0);
-	    rb_provide_feature(path);
-	    switch (type) {
-		case TYPE_RB:
-		    rb_rescue2(load_try, path, load_rescue, path,
-			    rb_eException, 0);
-		    break;
-
-		case TYPE_RBO:
-		    dln_load(RSTRING_PTR(path), false);
-		    break;
-
-		case TYPE_BUNDLE:
-		    dln_load(RSTRING_PTR(path), true);
-		    break;
-
-		default:
-		    abort();
-	    }
-	    result = Qtrue;
-	}
-    }
-
-    if (NIL_P(result)) {
-	load_failed(fname);
-    }
-
-    return result;
-#endif
-}
-
-VALUE
-rb_require(const char *fname)
-{
-    VALUE fn = rb_str_new2(fname);
-    OBJ_FREEZE(fn);
-    return rb_require_safe(fn, rb_safe_level());
-}
-
-/*
- *  call-seq:
- *     mod.autoload(name, filename)   => nil
- *  
- *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
- *  the first time that _module_ (which may be a <code>String</code> or
- *  a symbol) is accessed in the namespace of _mod_.
- *     
- *     module A
- *     end
- *     A.autoload(:B, "b")
- *     A::B.doit            # autoloads "b"
- */
-
-static VALUE
-rb_mod_autoload(VALUE mod, SEL sel, VALUE sym, VALUE file)
-{
-    ID id = rb_to_id(sym);
-
-    Check_SafeStr(file);
-    rb_autoload(mod, id, RSTRING_PTR(file));
-    return Qnil;
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_mod_autoload_p(VALUE mod, SEL sel, VALUE sym)
-{
-    return rb_autoload_p(mod, rb_to_id(sym));
-}
-
-/*
- *  call-seq:
- *     autoload(module, filename)   => nil
- *  
- *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
- *  the first time that _module_ (which may be a <code>String</code> or
- *  a symbol) is accessed.
- *     
- *     autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
- */
-
-static VALUE
-rb_f_autoload(VALUE obj, SEL sel, VALUE sym, VALUE file)
-{
-    VALUE klass = (VALUE)rb_vm_get_current_class();
-    if (klass == 0) {
-	klass = rb_cObject;
-    }
-    return rb_mod_autoload(klass, 0, sym, file);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_f_autoload_p(VALUE obj, SEL sel, VALUE sym)
-{
-    VALUE klass = (VALUE)rb_vm_get_current_class();
-    if (klass == 0) {
-	klass = rb_cObject;
-    }
-    return rb_mod_autoload_p(klass, 0, sym);
-}
-
-void
-Init_load()
-{
-    const char *var_load_path = "$:";
-    ID id_load_path = rb_intern(var_load_path);
-
-    rbo_enabled = !ruby_is_miniruby && getenv("VM_DISABLE_RBO") == NULL;
-
-    rb_define_virtual_variable("$:", rb_vm_load_path, 0);
-    rb_alias_variable((rb_intern)("$-I"), id_load_path);
-    rb_alias_variable((rb_intern)("$LOAD_PATH"), id_load_path);
-
-    rb_define_virtual_variable("$\"", rb_vm_loaded_features, 0);
-    rb_define_virtual_variable("$LOADED_FEATURES", rb_vm_loaded_features, 0);
-
-    rb_objc_define_module_function(rb_mKernel, "load", rb_f_load, -1);
-    rb_objc_define_module_function(rb_mKernel, "require", rb_f_require_imp, 1);
-    rb_objc_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
-    rb_objc_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
-    rb_objc_define_module_function(rb_mKernel, "autoload", rb_f_autoload, 2);
-    rb_objc_define_module_function(rb_mKernel, "autoload?", rb_f_autoload_p, 1);
-
-    rb_objc_define_module_function(rb_mKernel, "framework",
-	    rb_require_framework, -1);
-}

Deleted: MacRuby/trunk/macruby_internal.h
===================================================================
--- MacRuby/trunk/macruby_internal.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/macruby_internal.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,143 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved 
- */
-
-#ifndef __MACRUBY_INTERNAL_H
-#define __MACRUBY_INTERNAL_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include "ruby.h"
-
-#include <objc/objc.h>
-#include <objc/runtime.h>
-#include <objc/message.h>
-#include <objc/objc-auto.h>
-#include <assert.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-void rb_include_module2(VALUE klass, VALUE orig_klass, VALUE module, bool check,
-	bool add_methods);
-
-VALUE rb_objc_block_call(VALUE obj, SEL sel, int argc,
-	VALUE *argv, VALUE (*bl_proc) (ANYARGS), VALUE data2);
-
-#if !defined(__AUTO_ZONE__)
-boolean_t auto_zone_set_write_barrier(void *zone, const void *dest, const void *new_value);
-void auto_zone_add_root(void *zone, void *address_of_root_ptr, void *value);
-void auto_zone_retain(void *zone, void *ptr);
-unsigned int auto_zone_release(void *zone, void *ptr);
-extern void *__auto_zone;
-#else
-extern auto_zone_t *__auto_zone;
-#endif
-
-#define GC_WB_0(dst, newval, check) \
-    do { \
-	void *nv = (void *)newval; \
-	if (!SPECIAL_CONST_P(nv)) { \
-	    if (!auto_zone_set_write_barrier(__auto_zone, \
-			(const void *)dst, (const void *)nv)) { \
-		if (check) { \
-		    rb_bug("destination %p isn't in the auto zone", dst); \
-		} \
-	    } \
-	} \
-	*(void **)dst = nv; \
-    } \
-    while (0)
-
-#define GC_WB(dst, newval) GC_WB_0(dst, newval, true)
-
-static inline void *
-rb_objc_retain(void *addr)
-{
-    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
-        auto_zone_retain(__auto_zone, addr);
-    }
-    return addr;
-}
-#define GC_RETAIN(obj) (rb_objc_retain((void *)obj))
-
-static inline void *
-rb_objc_release(void *addr)
-{
-    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
-        auto_zone_release(__auto_zone, addr);
-    }
-    return addr;
-}
-#define GC_RELEASE(obj) (rb_objc_release((void *)obj))
-
-// MacRubyIntern.h
-
-/* enumerator.c */
-VALUE rb_enumeratorize(VALUE, SEL, int, VALUE *);
-#define RETURN_ENUMERATOR(obj, argc, argv) \
-    do {	\
-	if (!rb_block_given_p()) { \
-	    return rb_enumeratorize((VALUE)obj, sel, argc, argv); \
-	} \
-    } while (0)
-VALUE rb_f_notimplement(VALUE rcv, SEL sel);
-VALUE rb_method_call(VALUE, SEL, int, VALUE*);
-VALUE rb_file_directory_p(VALUE,SEL,VALUE);
-VALUE rb_obj_id(VALUE obj, SEL sel);
-
-void rb_objc_gc_register_thread(void);
-void rb_objc_gc_unregister_thread(void);
-void rb_objc_set_associative_ref(void *, void *, void *);
-void *rb_objc_get_associative_ref(void *, void *);
-
-VALUE rb_io_gets(VALUE, SEL);
-VALUE rb_io_getbyte(VALUE, SEL);
-VALUE rb_io_ungetc(VALUE, SEL, VALUE);
-VALUE rb_io_flush(VALUE, SEL);
-VALUE rb_io_eof(VALUE, SEL);
-VALUE rb_io_binmode(VALUE, SEL);
-VALUE rb_io_addstr(VALUE, SEL, VALUE);
-VALUE rb_io_printf(VALUE, SEL, int, VALUE *);
-VALUE rb_io_print(VALUE, SEL, int, VALUE *);
-
-VALUE rb_objc_num_coerce_bin(VALUE x, VALUE Y, SEL sel);
-VALUE rb_objc_num_coerce_cmp(VALUE, VALUE, SEL sel);
-VALUE rb_objc_num_coerce_relop(VALUE, VALUE, SEL sel);
-
-VALUE rb_f_kill(VALUE, SEL, int, VALUE*);
-VALUE rb_struct_initialize(VALUE, SEL, VALUE);
-VALUE rb_class_real(VALUE, bool hide_builtin_foundation_classes);
-void rb_range_extract(VALUE range, VALUE *begp, VALUE *endp, bool *exclude);
-VALUE rb_cvar_get2(VALUE klass, ID id, bool check);
-
-VALUE rb_require_framework(VALUE, SEL, int, VALUE *);
-
-RUBY_EXTERN VALUE rb_cNSObject;
-RUBY_EXTERN VALUE rb_cRubyObject;
-RUBY_EXTERN VALUE rb_cNSString;
-RUBY_EXTERN VALUE rb_cNSMutableString;
-RUBY_EXTERN VALUE rb_cRubyString;
-RUBY_EXTERN VALUE rb_cNSArray;
-RUBY_EXTERN VALUE rb_cNSMutableArray;
-RUBY_EXTERN VALUE rb_cRubyArray;
-RUBY_EXTERN VALUE rb_cNSHash;
-RUBY_EXTERN VALUE rb_cNSMutableHash;
-RUBY_EXTERN VALUE rb_cRubyHash;
-RUBY_EXTERN VALUE rb_cNSNumber;
-RUBY_EXTERN VALUE rb_cNSDate;
-RUBY_EXTERN VALUE rb_cBoxed;
-RUBY_EXTERN VALUE rb_cPointer;
-RUBY_EXTERN VALUE rb_cTopLevel;
-
-long rb_objc_flag_get_mask(const void *);
-void rb_objc_flag_set(const void *, int, bool);
-bool rb_objc_flag_check(const void *, int);
-
-#if defined(__cplusplus)
-}  // extern "C" {
-#endif
-
-#endif /* __MACRUBY_INTERNAL_H */

Deleted: MacRuby/trunk/main.cpp
===================================================================
--- MacRuby/trunk/main.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/main.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,47 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "llvm.h"
-
-#undef RUBY_EXPORT
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#include "vm.h"
-
-extern bool ruby_is_miniruby;
-
-int
-main(int argc, char **argv, char **envp)
-{
-#ifdef HAVE_LOCALE_H
-    setlocale(LC_CTYPE, "");
-#endif
-
-    ruby_is_miniruby = argc > 0 && strstr(argv[0], "miniruby") != NULL;
-
-    try {
-	ruby_sysinit(&argc, &argv);
-	ruby_init();
-	void *node = ruby_options(argc, argv);
-	rb_vm_init_compiler();
-	if (ruby_aot_compile) {
-	    rb_vm_aot_compile((NODE *)node);
-	    rb_exit(0);
-	}
-	else {	
-	    rb_exit(ruby_run_node(node));
-	}
-    }
-    catch (...) {
-	rb_vm_print_current_exception();
-	rb_exit(1);
-    }
-}

Deleted: MacRuby/trunk/markgc.c
===================================================================
--- MacRuby/trunk/markgc.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/markgc.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,451 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Apple Inc.  All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#import <stdio.h>
-#include <fcntl.h>
-#import <sys/stat.h>
-#import <mach-o/fat.h>
-#import <mach-o/arch.h>
-#import <mach-o/loader.h>
-
-typedef char bool;
-#define true 1
-#define false 0
-
-bool debug;
-bool verbose;
-bool quiet;
-bool rrOnly;
-bool patch = true;
-
-struct gcinfo {
-        bool hasObjC;
-        bool hasInfo;
-        uint32_t flags;
-        char *arch;
-} GCInfo[4];
-
-void dumpinfo(char *filename);
-
-int Errors = 0;
-char *FileBase;
-size_t FileSize;
-const char *FileName;
-
-int main(int argc, char *argv[]) {
-    //NSAutoreleasePool *pool = [NSAutoreleasePool new];
-    int i;
-    //dumpinfo("/System/Library/Frameworks/AppKit.framework/AppKit");
-    if (argc == 1) {
-        printf("Usage: gcinfo [-v] [-r] [--] library_or_executable_image [image2 ...]\n");
-        printf(" prints Garbage Collection readiness of named images, ignoring those without ObjC segments\n");
-        printf("  'GC'      - compiled with write-barriers, presumably otherwise aware\n");
-        printf("  'RR'      - retain/release (presumed) aware for non-GC\n");
-        printf("  'GC-only' - compiled with write-barriers and marked at compile time as not being retain/release savvy\n");
-        printf("  -v        - provide archtectural details\n");
-        printf("  -r        - only show libraries that are non-GC, e.g. RR only\n");
-        printf("  --        - read files & directories from stdin, e.g. find /Plug-ins | gcinfo --\n");
-        printf("\nAuthor: blaine at apple.com\n");
-        exit(0);
-    }
-    for (i = 1; i < argc; ++i) {
-        if (!strcmp(argv[i], "-v")) {
-            verbose = true;
-            continue;
-        }
-        if (!strcmp(argv[i], "-d")) {
-            debug = true;
-            continue;
-        }
-        if (!strcmp(argv[i], "-q")) {
-            quiet = true;
-            continue;
-        }
-        if (!strcmp(argv[i], "-r")) {
-            quiet = true;
-            rrOnly = true;
-            continue;
-        }
-        if (!strcmp(argv[i], "-p")) {
-            patch = true;
-            continue;
-        }
-        if (!strcmp(argv[i], "--")) {
-            char buf[1024];
-            while (fgets(buf, 1024, stdin)) {
-                int len = strlen(buf);
-                buf[len-1] = 0;
-                dumpinfo(buf);
-            }
-            continue;
-        }
-        dumpinfo(argv[i]);
-    }
-    return Errors;
-}
-
-struct imageInfo {
-    uint32_t version;
-    uint32_t flags;
-};
-
-void patchFile(uint32_t value, size_t offset) {
-    int fd = open(FileName, 1);
-    off_t lresult = lseek(fd, offset, SEEK_SET);
-    if (lresult == -1) {
-        printf("couldn't seek to %x position on fd %d\n", offset, fd);
-        ++Errors;
-        return;
-    }
-    int wresult = write(fd, &value, 4);
-    if (wresult != 4) {
-        ++Errors;
-        printf("didn't write new value\n");
-    }
-    else {
-        printf("patched %s at offset %p\n", FileName, offset);
-    }
-    close(fd);
-}
-
-uint32_t iiflags(struct imageInfo *ii, uint32_t size, bool needsFlip) {
-    if (needsFlip) {
-        ii->flags = OSSwapInt32(ii->flags);
-    }
-    if (debug) printf("flags->%x, nitems %d\n", ii->flags, size/sizeof(struct imageInfo));
-    uint32_t flags = ii->flags;
-    if (patch && (flags&0x2)==0) {
-        //printf("will patch %s at offset %p\n", FileName, (char*)(&ii->flags) - FileBase);
-        uint32_t newvalue = flags | 0x2;
-        if (needsFlip) newvalue = OSSwapInt32(newvalue);
-        patchFile(newvalue, (char*)(&ii->flags) - FileBase);
-    }
-    for(int niis = 1; niis < size/sizeof(struct imageInfo); ++niis) {
-        if (needsFlip) ii[niis].flags = OSSwapInt32(ii[niis].flags);
-        if (ii[niis].flags != flags) {
-            // uh, oh.
-            printf("XXX ii[%d].flags %x != ii[0].flags %x\n", niis, ii[niis].flags, flags);
-            ++Errors;
-        }
-    }
-    return flags;
-}
-
-void printflags(uint32_t flags) {
-    if (flags & 0x1) printf(" F&C");
-    if (flags & 0x2) printf(" GC");
-    if (flags & 0x4) printf(" GC-only");
-    else printf(" RR");
-}
-
-/*
-void doimageinfo(struct imageInfo *ii, uint32_t size, bool needsFlip) {
-    uint32_t flags = iiflags(ii, size, needsFlip);
-    printflags(flags);
-}
-*/
-
-
-void dosect32(void *start, struct section *sect, bool needsFlip, struct gcinfo *gcip) {
-    if (debug) printf("section %s from segment %s\n", sect->sectname, sect->segname);
-    if (strcmp(sect->segname, "__OBJC")) return;
-    gcip->hasObjC = true;
-    if (strcmp(sect->sectname, "__image_info")) return;
-    gcip->hasInfo = true;
-    if (needsFlip) {
-        sect->offset = OSSwapInt32(sect->offset);
-        sect->size = OSSwapInt32(sect->size);
-    }
-    // these guys aren't inline - they point elsewhere
-    gcip->flags = iiflags(start + sect->offset, sect->size, needsFlip);
-}
-
-void dosect64(void *start, struct section_64 *sect, bool needsFlip, struct gcinfo *gcip) {
-    if (debug) printf("section %s from segment %s\n", sect->sectname, sect->segname);
-    if (strcmp(sect->segname, "__OBJC") && strcmp(sect->segname, "__DATA")) return;
-    if (strcmp(sect->sectname, "__image_info") && strncmp(sect->sectname, "__objc_imageinfo", 16)) return;
-    gcip->hasObjC = true;
-    gcip->hasInfo = true;
-    if (needsFlip) {
-        sect->offset = OSSwapInt32(sect->offset);
-        sect->size = OSSwapInt64(sect->size);
-    }
-    // these guys aren't inline - they point elsewhere
-    gcip->flags = iiflags(start + sect->offset, sect->size, needsFlip);
-}
-
-void doseg32(void *start, struct segment_command *seg, bool needsFlip, struct gcinfo *gcip) {
-    // lets do sections
-    if (needsFlip) {
-        seg->fileoff = OSSwapInt32(seg->fileoff);
-        seg->nsects = OSSwapInt32(seg->nsects);
-    }
-    if (debug) printf("segment name: %s, nsects %d\n", seg->segname, seg->nsects);
-    if (seg->segname[0]) {
-        if (strcmp("__OBJC", seg->segname)) return;
-    }
-    int nsects;
-    struct section *sect = (struct section *)(seg + 1);
-    for (int nsects = 0; nsects < seg->nsects; ++nsects) {
-        // sections directly follow
-        
-        dosect32(start, sect + nsects, needsFlip, gcip);
-    }
-}
-void doseg64(void *start, struct segment_command_64 *seg, bool needsFlip, struct gcinfo *gcip) {
-    if (debug) printf("segment name: %s\n", seg->segname);
-    if (seg->segname[0] && strcmp("__OBJC", seg->segname) && strcmp("__DATA", seg->segname)) return;
-    gcip->hasObjC = true;
-    // lets do sections
-    if (needsFlip) {
-        seg->fileoff = OSSwapInt64(seg->fileoff);
-        seg->nsects = OSSwapInt32(seg->nsects);
-    }
-    int nsects;
-    struct section_64 *sect = (struct section_64 *)(seg + 1);
-    for (int nsects = 0; nsects < seg->nsects; ++nsects) {
-        // sections directly follow
-        
-        dosect64(start, sect + nsects, needsFlip, gcip);
-    }
-}
-
-#if 0
-/*
- * A variable length string in a load command is represented by an lc_str
- * union.  The strings are stored just after the load command structure and
- * the offset is from the start of the load command structure.  The size
- * of the string is reflected in the cmdsize field of the load command.
- * Once again any padded bytes to bring the cmdsize field to a multiple
- * of 4 bytes must be zero.
- */
-union lc_str {
-	uint32_t	offset;	/* offset to the string */
-#ifndef __LP64__
-	char		*ptr;	/* pointer to the string */
-#endif 
-};
-
-struct dylib {
-    union lc_str  name;			/* library's path name */
-    uint32_t timestamp;			/* library's build time stamp */
-    uint32_t current_version;		/* library's current version number */
-    uint32_t compatibility_version;	/* library's compatibility vers number*/
-};
-
- * A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
- * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
- * An object that uses a dynamically linked shared library also contains a
- * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
- * LC_REEXPORT_DYLIB) for each library it uses.
-
-struct dylib_command {
-	uint32_t	cmd;		/* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
-					   LC_REEXPORT_DYLIB */
-	uint32_t	cmdsize;	/* includes pathname string */
-	struct dylib	dylib;		/* the library identification */
-};
-#endif
-
-void dodylib(void *start, struct dylib_command *dylibCmd, bool needsFlip) {
-    if (!verbose) return;
-    if (needsFlip) {
-    }
-    int count = dylibCmd->cmdsize - sizeof(struct dylib_command);
-    //printf("offset is %d, count is %d\n", dylibCmd->dylib.name.offset, count);
-    if (dylibCmd->dylib.name.offset > count) return;
-    //printf("-->%.*s<---", count, ((void *)dylibCmd)+dylibCmd->dylib.name.offset);
-    if (verbose) printf("load %s\n", ((void *)dylibCmd)+dylibCmd->dylib.name.offset);
-}
-
-struct load_command *doloadcommand(void *start, struct load_command *lc, bool needsFlip, bool is32, struct gcinfo *gcip) {
-    if (needsFlip) {
-        lc->cmd = OSSwapInt32(lc->cmd);
-        lc->cmdsize = OSSwapInt32(lc->cmdsize);
-    }
-
-    switch(lc->cmd) {
-    case LC_SEGMENT_64:
-	if (debug) printf("...segment64\n");
-        if (is32) printf("XXX we have a 64-bit segment in a 32-bit mach-o\n");
-        doseg64(start, (struct segment_command_64 *)lc, needsFlip, gcip);
-        break;
-    case LC_SEGMENT:
-	if (debug) printf("...segment32\n");
-        doseg32(start, (struct segment_command *)lc, needsFlip, gcip);
-        break;
-    case LC_SYMTAB: if (debug) printf("...dynamic symtab\n"); break;
-    case LC_DYSYMTAB: if (debug) printf("...symtab\n"); break;
-    case LC_LOAD_DYLIB:
-        dodylib(start, (struct dylib_command *)lc, needsFlip);
-        break;
-    case LC_SUB_UMBRELLA: if (debug) printf("...load subumbrella\n"); break;
-    default:    if (debug) printf("cmd is %x\n", lc->cmd); break;
-    }
-    
-    return (struct load_command *)((void *)lc + lc->cmdsize);
-}
-
-void doofile(void *start, uint32_t size, struct gcinfo *gcip) {
-    struct mach_header *mh = (struct mach_header *)start;
-    bool isFlipped = false;
-    if (mh->magic == MH_CIGAM || mh->magic == MH_CIGAM_64) {
-        if (debug) printf("(flipping)\n");
-        mh->magic = OSSwapInt32(mh->magic);
-        mh->cputype = OSSwapInt32(mh->cputype);
-        mh->cpusubtype = OSSwapInt32(mh->cpusubtype);
-        mh->filetype = OSSwapInt32(mh->filetype);
-        mh->ncmds = OSSwapInt32(mh->ncmds);
-        mh->sizeofcmds = OSSwapInt32(mh->sizeofcmds);
-        mh->flags = OSSwapInt32(mh->flags);
-        isFlipped = true;
-    }
-    if (rrOnly && mh->filetype != 6) return; // ignore executables
-    NXArchInfo *info = (NXArchInfo *)NXGetArchInfoFromCpuType(mh->cputype, mh->cpusubtype);
-    //printf("%s:", info->description);
-    gcip->arch = (char *)info->description;
-    //if (debug) printf("...description is %s\n", info->description);
-    bool is32 = (mh->cputype == 18 || mh->cputype == 7);
-    if (debug) printf("is 32? %d\n", is32);
-    if (debug) printf("filetype -> %d\n", mh->filetype);
-    if (debug) printf("ncmds -> %d\n", mh->ncmds);
-    struct load_command *lc = (is32 ? (struct load_command *)(mh + 1) : (struct load_command *)((struct mach_header_64 *)start + 1));
-    int ncmds;
-    for (ncmds = 0; ncmds < mh->ncmds; ++ncmds) {
-        lc = doloadcommand(start, lc, isFlipped, is32, gcip);
-    }
-    //printf("\n");
-}
-
-void initGCInfo() {
-    bzero((void *)GCInfo, sizeof(GCInfo));
-}
-
-void printGCInfo(char *filename) {
-    if (!GCInfo[0].hasObjC) return; // don't bother
-    // verify that flags are all the same
-    uint32_t flags = GCInfo[0].flags;
-    bool allSame = true;
-    for (int i = 1; i < 4 && GCInfo[i].arch; ++i) {
-        if (flags != GCInfo[i].flags) {
-            allSame = false;
-        }
-    }
-    if (rrOnly) {
-        if (allSame && (flags & 0x2))
-            return;
-        printf("*** not all GC in %s:\n", filename);
-    }
-    if (allSame && !verbose) {
-        printf("%s:", filename);
-        printflags(flags);
-        printf("\n");
-    }
-    else {
-        printf("%s:\n", filename);
-        for (int i = 0; i < 4 && GCInfo[i].arch; ++i) {
-            printf("%s:", GCInfo[i].arch);
-            printflags(GCInfo[i].flags);
-            printf("\n");
-        }
-        printf("\n");
-    }
-}
-
-void dofat(void *start) {
-    struct fat_header *fh = start;
-    bool needsFlip = false;
-    if (fh->magic == FAT_CIGAM) {
-        fh->nfat_arch = OSSwapInt32(fh->nfat_arch);
-        needsFlip = true;
-    }
-    if (debug) printf("%d architectures\n", fh->nfat_arch);
-    int narchs;
-    struct fat_arch *arch_ptr = (struct fat_arch *)(fh + 1);
-    for (narchs = 0; narchs < fh->nfat_arch; ++narchs) {
-        if (needsFlip) {
-            arch_ptr->offset = OSSwapInt32(arch_ptr->offset);
-            arch_ptr->size = OSSwapInt32(arch_ptr->size);
-        }
-        doofile(start+arch_ptr->offset, arch_ptr->size, &GCInfo[narchs]);
-        arch_ptr++;
-    }
-}
-
-bool openFile(const char *filename) {
-    FileName = filename;
-    // get size
-    struct stat statb;
-    int fd = open(filename, 0);
-    if (fd < 0) {
-        printf("couldn't open %s for reading\n", filename);
-        return false;
-    }
-    int osresult = fstat(fd, &statb);
-    if (osresult != 0) {
-        printf("couldn't get size of %s\n", filename);
-        close(fd);
-        return false;
-    }
-    FileSize = statb.st_size;
-    FileBase = malloc(FileSize);
-    if (!FileBase) {
-        printf("couldn't malloc %d bytes\n", FileSize);
-        close(fd);
-        return false;
-    }
-    off_t readsize = read(fd, FileBase, FileSize);
-    if (readsize != FileSize) {
-        printf("read %d bytes, wanted %d\n", readsize, FileSize);
-        close(fd);
-        return false;
-    }
-    close(fd);
-    return true;
-}
-
-void closeFile() {
-    free(FileBase);
-}
-
-void dumpinfo(char *filename) {
-    initGCInfo();
-    openFile(filename);
-    struct fat_header *fh = (struct fat_header *)FileBase;
-    if (fh->magic == FAT_MAGIC || fh->magic == FAT_CIGAM) {
-        dofat((void *)FileBase);
-        //printGCInfo(filename);
-    }
-    else if (fh->magic == MH_MAGIC || fh->magic == MH_CIGAM || fh->magic == MH_MAGIC_64 || fh->magic == MH_CIGAM_64) {
-        doofile((void *)FileBase, FileSize, &GCInfo[0]);
-        //printGCInfo(filename);
-    }
-    else if (!quiet) {
-        printf("don't understand %s!\n", filename);
-    }
-    closeFile();
- }
-

Deleted: MacRuby/trunk/marshal.c
===================================================================
--- MacRuby/trunk/marshal.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/marshal.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1850 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/io.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "id.h"
-#include "re.h"
-#include "class.h"
-
-#include <math.h>
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#define BITSPERSHORT (2*CHAR_BIT)
-#define SHORTMASK ((1<<BITSPERSHORT)-1)
-#define SHORTDN(x) RSHIFT(x,BITSPERSHORT)
-
-#if SIZEOF_SHORT == SIZEOF_BDIGITS
-#define SHORTLEN(x) (x)
-#else
-static int
-shortlen(long len, BDIGIT *ds)
-{
-    BDIGIT num;
-    int offset = 0;
-
-    num = ds[len-1];
-    while (num) {
-	num = SHORTDN(num);
-	offset++;
-    }
-    return (len - 1)*sizeof(BDIGIT)/2 + offset;
-}
-#define SHORTLEN(x) shortlen((x),d)
-#endif
-
-#define MARSHAL_MAJOR   4
-#define MARSHAL_MINOR   8
-
-#define TYPE_NIL	'0'
-#define TYPE_TRUE	'T'
-#define TYPE_FALSE	'F'
-#define TYPE_FIXNUM	'i'
-
-#define TYPE_EXTENDED_R	'e'
-#define TYPE_UCLASS	'C'
-#define TYPE_OBJECT	'o'
-#define TYPE_DATA       'd'
-#define TYPE_USERDEF	'u'
-#define TYPE_USRMARSHAL	'U'
-#define TYPE_FLOAT	'f'
-#define TYPE_BIGNUM	'l'
-#define TYPE_STRING	'"'
-#define TYPE_REGEXP	'/'
-#define TYPE_ARRAY	'['
-#define TYPE_HASH	'{'
-#define TYPE_HASH_DEF	'}'
-#define TYPE_STRUCT	'S'
-#define TYPE_MODULE_OLD	'M'
-#define TYPE_CLASS	'c'
-#define TYPE_MODULE	'm'
-
-#define TYPE_SYMBOL	':'
-#define TYPE_SYMLINK	';'
-
-#define TYPE_IVAR	'I'
-#define TYPE_LINK	'@'
-
-static ID s_dump, s_load, s_mdump, s_mload;
-static ID s_dump_data, s_load_data, s_alloc;
-static ID s_getbyte, s_read, s_write, s_binmode;
-
-static ID
-rb_id_encoding(void)
-{
-    static ID id = 0;
-    if (id == 0) {
-	id = rb_intern("encoding");
-    }
-    return id;
-}
-
-typedef struct {
-    VALUE newclass;
-    VALUE oldclass;
-    VALUE (*dumper)(VALUE);
-    VALUE (*loader)(VALUE, VALUE);
-} marshal_compat_t;
-
-static st_table *compat_allocator_tbl;
-static VALUE compat_allocator_tbl_wrapper;
-
-static rb_alloc_func_t
-rb_get_alloc_func(VALUE klass)
-{
-    // TODO... or is this really needed...
-    return NULL;
-}
-
-void
-rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE))
-{
-    marshal_compat_t *compat;
-    rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
-
-    if (!allocator) {
-        rb_raise(rb_eTypeError, "no allocator");
-    }
-
-    compat = ALLOC(marshal_compat_t);
-    compat->newclass = Qnil;
-    compat->oldclass = Qnil;
-    compat->newclass = newclass;
-    compat->oldclass = oldclass;
-    compat->dumper = dumper;
-    compat->loader = loader;
-
-    st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat);
-}
-
-struct dump_arg {
-    VALUE obj;
-    VALUE str, dest;
-    st_table *symbols;
-    st_table *data;
-    int taint;
-    st_table *compat_tbl;
-    VALUE wrapper;
-    st_table *encodings;
-};
-
-struct dump_call_arg {
-    VALUE obj;
-    struct dump_arg *arg;
-    int limit;
-};
-
-static void
-check_dump_arg(struct dump_arg *arg)
-{
-    if (!DATA_PTR(arg->wrapper)) {
-	rb_raise(rb_eRuntimeError, "Marshal.dump reentered");
-    }
-}
-
-static VALUE
-class2path(VALUE klass)
-{
-    VALUE path;
-    if (klass == rb_cNSObject) {
-	path = rb_str_new2("Object");
-    }
-    else if (klass == rb_cNSMutableString) {
-	path = rb_str_new2("String");
-    }
-    else {
-	path = rb_class_path(klass);
-    }
-    const char *n = RSTRING_PTR(path);
-
-    if (n[0] == '#') {
-	rb_raise(rb_eTypeError, "can't dump anonymous %s %s",
-		 (TYPE(klass) == T_CLASS ? "class" : "module"),
-		 n);
-    }
-    if (rb_path2class(n) != rb_class_real(klass, true)) {
-	rb_raise(rb_eTypeError, "%s can't be referred", n);
-    }
-    return path;
-}
-
-static void w_long(long, struct dump_arg*);
-
-static void
-w_nbyte(const char *s, int n, struct dump_arg *arg)
-{
-    VALUE buf = arg->str;
-    rb_bstr_concat(buf, (const uint8_t *)s, n);
-#if 0 // unused
-    if (arg->dest && RSTRING_LEN(buf) >= BUFSIZ) {
-	if (arg->taint) {
-	    OBJ_TAINT(buf);
-	}
-	rb_io_write(arg->dest, buf);
-	rb_str_resize(buf, 0);
-    }
-#endif
-}
-
-static void
-w_byte(char c, struct dump_arg *arg)
-{
-    w_nbyte(&c, 1, arg);
-}
-
-static void
-w_bytes(const char *s, int n, struct dump_arg *arg)
-{
-    w_long(n, arg);
-    w_nbyte(s, n, arg);
-}
-
-static void
-w_short(int x, struct dump_arg *arg)
-{
-    w_byte((char)((x >> 0) & 0xff), arg);
-    w_byte((char)((x >> 8) & 0xff), arg);
-}
-
-static void
-w_long(long x, struct dump_arg *arg)
-{
-    char buf[sizeof(long)+1];
-    int i, len = 0;
-
-#if SIZEOF_LONG > 4
-    if (!(RSHIFT(x, 31) == 0 || RSHIFT(x, 31) == -1)) {
-	/* big long does not fit in 4 bytes */
-	rb_raise(rb_eTypeError, "long too big to dump");
-    }
-#endif
-
-    if (x == 0) {
-	w_byte(0, arg);
-	return;
-    }
-    if (0 < x && x < 123) {
-	w_byte((char)(x + 5), arg);
-	return;
-    }
-    if (-124 < x && x < 0) {
-	w_byte((char)((x - 5)&0xff), arg);
-	return;
-    }
-    for (i=1;i<sizeof(long)+1;i++) {
-	buf[i] = x & 0xff;
-	x = RSHIFT(x,8);
-	if (x == 0) {
-	    buf[0] = i;
-	    break;
-	}
-	if (x == -1) {
-	    buf[0] = -i;
-	    break;
-	}
-    }
-    len = i;
-    for (i=0;i<=len;i++) {
-	w_byte(buf[i], arg);
-    }
-}
-
-#ifdef DBL_MANT_DIG
-#define DECIMAL_MANT (53-16)	/* from IEEE754 double precision */
-
-#if DBL_MANT_DIG > 32
-#define MANT_BITS 32
-#elif DBL_MANT_DIG > 24
-#define MANT_BITS 24
-#elif DBL_MANT_DIG > 16
-#define MANT_BITS 16
-#else
-#define MANT_BITS 8
-#endif
-
-static int
-save_mantissa(double d, char *buf)
-{
-    int e, i = 0;
-    unsigned long m;
-    double n;
-
-    d = modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
-    if (d > 0) {
-	buf[i++] = 0;
-	do {
-	    d = modf(ldexp(d, MANT_BITS), &n);
-	    m = (unsigned long)n;
-#if MANT_BITS > 24
-	    buf[i++] = m >> 24;
-#endif
-#if MANT_BITS > 16
-	    buf[i++] = m >> 16;
-#endif
-#if MANT_BITS > 8
-	    buf[i++] = m >> 8;
-#endif
-	    buf[i++] = m;
-	} while (d > 0);
-	while (!buf[i - 1]) --i;
-    }
-    return i;
-}
-
-static double
-load_mantissa(double d, const char *buf, int len)
-{
-    if (--len > 0 && !*buf++) {	/* binary mantissa mark */
-	int e, s = d < 0, dig = 0;
-	unsigned long m;
-
-	modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
-	do {
-	    m = 0;
-	    switch (len) {
-	      default: m = *buf++ & 0xff;
-#if MANT_BITS > 24
-	      case 3: m = (m << 8) | (*buf++ & 0xff);
-#endif
-#if MANT_BITS > 16
-	      case 2: m = (m << 8) | (*buf++ & 0xff);
-#endif
-#if MANT_BITS > 8
-	      case 1: m = (m << 8) | (*buf++ & 0xff);
-#endif
-	    }
-	    dig -= len < MANT_BITS / 8 ? 8 * (unsigned)len : MANT_BITS;
-	    d += ldexp((double)m, dig);
-	} while ((len -= MANT_BITS / 8) > 0);
-	d = ldexp(d, e - DECIMAL_MANT);
-	if (s) d = -d;
-    }
-    return d;
-}
-#else
-#define load_mantissa(d, buf, len) (d)
-#define save_mantissa(d, buf) 0
-#endif
-
-#ifdef DBL_DIG
-#define FLOAT_DIG (DBL_DIG+2)
-#else
-#define FLOAT_DIG 17
-#endif
-
-static void
-w_float(double d, struct dump_arg *arg)
-{
-    char buf[FLOAT_DIG + (DECIMAL_MANT + 7) / 8 + 10];
-
-    if (isinf(d)) {
-	if (d < 0) strcpy(buf, "-inf");
-	else       strcpy(buf, "inf");
-    }
-    else if (isnan(d)) {
-	strcpy(buf, "nan");
-    }
-    else if (d == 0.0) {
-	if (1.0/d < 0) strcpy(buf, "-0");
-	else           strcpy(buf, "0");
-    }
-    else {
-	int len;
-
-	/* xxx: should not use system's sprintf(3) */
-	snprintf(buf, sizeof(buf), "%.*g", FLOAT_DIG, d);
-	len = strlen(buf);
-	w_bytes(buf, len + save_mantissa(d, buf + len), arg);
-	return;
-    }
-    w_bytes(buf, strlen(buf), arg);
-}
-
-static void
-w_symbol(ID id, struct dump_arg *arg)
-{
-    const char *sym;
-    st_data_t num;
-
-    if (st_lookup(arg->symbols, id, &num)) {
-	w_byte(TYPE_SYMLINK, arg);
-	w_long((long)num, arg);
-    }
-    else {
-	sym = rb_id2name(id);
-	if (!sym) {
-	    rb_raise(rb_eTypeError, "can't dump anonymous ID %ld", id);
-	}
-	w_byte(TYPE_SYMBOL, arg);
-	w_bytes(sym, strlen(sym), arg);
-	st_add_direct(arg->symbols, id, arg->symbols->num_entries);
-    }
-}
-
-static void
-w_unique(const char *s, struct dump_arg *arg)
-{
-    if (s[0] == '#') {
-	rb_raise(rb_eTypeError, "can't dump anonymous class %s", s);
-    }
-    w_symbol(rb_intern(s), arg);
-}
-
-static void w_object(VALUE,struct dump_arg*,int);
-
-static int
-hash_each(VALUE key, VALUE value, struct dump_call_arg *arg)
-{
-    w_object(key, arg->arg, arg->limit);
-    w_object(value, arg->arg, arg->limit);
-    return ST_CONTINUE;
-}
-
-static void
-w_extended(VALUE klass, struct dump_arg *arg, int check)
-{
-#if 0
-    const char *path;
-    if (check && RCLASS_SINGLETON(klass)) {
-#if !WITH_OBJC // TODO
-	if (RCLASS_M_TBL(klass)->num_entries ||
-	    (RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) {
-	    rb_raise(rb_eTypeError, "singleton can't be dumped");
-	}
-	klass = RCLASS_SUPER(klass);
-#endif
-    }
-    while (TYPE(klass) == T_ICLASS) {
-	path = rb_class2name(RBASIC(klass)->klass);
-	w_byte(TYPE_EXTENDED_R, arg);
-	w_unique(path, arg);
-	klass = RCLASS_SUPER(klass);
-    }
-#endif
-    if (RCLASS_SINGLETON(klass)) {
-	VALUE ary = rb_attr_get(klass, idIncludedModules);
-	if (ary != Qnil) {
-	    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-		VALUE mod = RARRAY_AT(ary, i);
-		const char *path = rb_class2name(mod);
-		w_byte(TYPE_EXTENDED_R, arg);
-		w_unique(path, arg);
-	    }
-	}
-    }
-}
-
-static void
-w_class(char type, VALUE obj, struct dump_arg *arg, int check)
-{
-    volatile VALUE p;
-    const char *path;
-    st_data_t real_obj;
-    VALUE klass;
-
-    if (st_lookup(arg->compat_tbl, (st_data_t)obj, &real_obj)) {
-        obj = (VALUE)real_obj;
-    }
-    klass = CLASS_OF(obj);
-    w_extended(klass, arg, check);
-    w_byte(type, arg);
-    p = class2path(rb_class_real(klass, true));
-    path = RSTRING_PTR(p);
-    w_unique(path, arg);
-}
-
-static void
-#if WITH_OBJC
-w_uclass(VALUE obj, bool is_pure, struct dump_arg *arg)
-#else
-w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
-#endif
-{
-    VALUE klass = CLASS_OF(obj);
-
-    w_extended(klass, arg, Qtrue);
-    klass = rb_class_real(klass, true);
-#if WITH_OBJC
-    if (!is_pure) {
-#else
-    if (klass != super) {
-#endif
-	w_byte(TYPE_UCLASS, arg);
-	w_unique(RSTRING_PTR(class2path(klass)), arg);
-    }
-}
-
-static int
-w_obj_each(ID id, VALUE value, struct dump_call_arg *arg)
-{
-    if (id == rb_id_encoding()) return ST_CONTINUE;
-    w_symbol(id, arg->arg);
-    w_object(value, arg->arg, arg->limit);
-    return ST_CONTINUE;
-}
-
-static void
-w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
-{
-    rb_encoding *enc = 0;
-#if WITH_OBJC
-    VALUE name;
-
-    enc = rb_enc_get(obj);
-    if (enc == NULL) {
-	w_long(num, arg->arg);
-	return;
-    }
-    name = rb_enc_name2(enc);
-#else
-    int encidx = rb_enc_get_index(obj);
-    rb_encoding *enc = 0;
-    st_data_t name;
-
-    if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
-	w_long(num, arg->arg);
-	return;
-    }
-    w_long(num + 1, arg->arg);
-    w_symbol(rb_id_encoding(), arg->arg);
-    do {
-	if (!arg->arg->encodings)
-	    arg->arg->encodings = st_init_strcasetable();
-	else if (st_lookup(arg->arg->encodings, (st_data_t)rb_enc_name(enc), &name))
-	    break;
-	name = (st_data_t)rb_str_new2(rb_enc_name(enc));
-	st_insert(arg->arg->encodings, (st_data_t)rb_enc_name(enc), name);
-    } while (0);
-#endif
-    w_object(name, arg->arg, arg->limit);
-}
-
-static void
-w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
-{
-    long num = tbl ? tbl->num_entries : 0;
-
-    w_encoding(obj, num, arg);
-    if (tbl) {
-	st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
-    }
-}
-
-static void
-w_objivar(VALUE obj, struct dump_call_arg *arg)
-{
-#if WITH_OBJC
-    VALUE ary = rb_obj_instance_variables(obj);
-    int i, len = RARRAY_LEN(ary);
-
-    w_encoding(obj, len, arg);
-
-    for (i = 0; i < len; i++) {
-	ID var_id = SYM2ID(RARRAY_AT(ary, i));
-	VALUE var_val = rb_ivar_get(obj, var_id);
-	w_obj_each(var_id, var_val, arg);
-    }
-#else
-    VALUE *ptr;
-    long i, len, num;
-
-    len = ROBJECT_NUMIV(obj);
-    ptr = ROBJECT_IVPTR(obj);
-    num = 0;
-    for (i = 0; i < len; i++)
-        if (ptr[i] != Qundef)
-            num += 1;
-
-    w_encoding(obj, num, arg);
-    if (num != 0) {
-        rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
-    }
-#endif
-}
-
-static void
-w_object(VALUE obj, struct dump_arg *arg, int limit)
-{
-    struct dump_call_arg c_arg;
-    st_table *ivtbl = 0;
-    st_data_t num;
-    int hasiv = 0;
-#if WITH_OBJC
-// TODO
-#define has_ivars(obj, ivtbl) (false)
-#else
-#define has_ivars(obj, ivtbl) ((ivtbl = rb_generic_ivar_table(obj)) != 0 || \
-			       (!SPECIAL_CONST_P(obj) && !ENCODING_IS_ASCII8BIT(obj)))
-#endif
-
-    if (limit == 0) {
-	rb_raise(rb_eArgError, "exceed depth limit");
-    }
-
-    limit--;
-    c_arg.limit = limit;
-    c_arg.arg = arg;
-
-    if (st_lookup(arg->data, obj, &num)) {
-	w_byte(TYPE_LINK, arg);
-	w_long((long)num, arg);
-	return;
-    }
-
-    if ((hasiv = has_ivars(obj, ivtbl)) != 0) {
-	w_byte(TYPE_IVAR, arg);
-    }
-    if (obj == Qnil) {
-	w_byte(TYPE_NIL, arg);
-    }
-    else if (obj == Qtrue) {
-	w_byte(TYPE_TRUE, arg);
-    }
-    else if (obj == Qfalse) {
-	w_byte(TYPE_FALSE, arg);
-    }
-    else if (FIXNUM_P(obj)) {
-#if SIZEOF_LONG <= 4
-	w_byte(TYPE_FIXNUM, arg);
-	w_long(FIX2INT(obj), arg);
-#else
-	if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
-	    w_byte(TYPE_FIXNUM, arg);
-	    w_long(FIX2LONG(obj), arg);
-	}
-	else {
-	    w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
-	}
-#endif
-    }
-    else if (FIXFLOAT_P(obj)) {
-	w_byte(TYPE_FLOAT, arg);
-	w_float(RFLOAT_VALUE(obj), arg);
-    }
-    else if (SYMBOL_P(obj)) {
-	w_symbol(SYM2ID(obj), arg);
-    }
-    else {
-	if (OBJ_TAINTED(obj)) {
-	    arg->taint = Qtrue;
-	}
-
-	if (rb_obj_respond_to(obj, s_mdump, Qtrue)) {
-	    volatile VALUE v;
-
-            st_add_direct(arg->data, obj, arg->data->num_entries);
-
-	    v = rb_funcall(obj, s_mdump, 0, 0);
-	    check_dump_arg(arg);
-	    w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
-	    w_object(v, arg, limit);
-	    if (hasiv) w_ivar(obj, 0, &c_arg);
-	    return;
-	}
-	if (rb_obj_respond_to(obj, s_dump, Qtrue)) {
-	    VALUE v;
-            st_table *ivtbl2 = 0;
-            int hasiv2;
-
-	    v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
-	    check_dump_arg(arg);
-	    if (TYPE(v) != T_STRING) {
-		rb_raise(rb_eTypeError, "_dump() must return string");
-	    }
-	    if ((hasiv2 = has_ivars(v, ivtbl2)) != 0 && !hasiv) {
-		w_byte(TYPE_IVAR, arg);
-	    }
-	    w_class(TYPE_USERDEF, obj, arg, Qfalse);
-	    w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
-            if (hasiv2) {
-		w_ivar(v, ivtbl2, &c_arg);
-            }
-            else if (hasiv) {
-		w_ivar(obj, ivtbl, &c_arg);
-	    }
-            st_add_direct(arg->data, obj, arg->data->num_entries);
-	    return;
-	}
-
-        st_add_direct(arg->data, obj, arg->data->num_entries);
-
-	if (!NATIVE(obj)) {
-            st_data_t compat_data;
-            rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
-            if (st_lookup(compat_allocator_tbl,
-                          (st_data_t)allocator,
-                          &compat_data)) {
-                marshal_compat_t *compat = (marshal_compat_t*)compat_data;
-                VALUE real_obj = obj;
-                obj = compat->dumper(real_obj);
-                st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
-            }
-        }
-
-	switch (TYPE(obj)) {
-	  case T_CLASS:
-	    if (RCLASS_SINGLETON(obj)) {
-		rb_raise(rb_eTypeError, "singleton class can't be dumped");
-	    }
-	    w_byte(TYPE_CLASS, arg);
-	    {
-		volatile VALUE path = class2path(obj);
-		w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
-	    }
-	    break;
-
-	  case T_MODULE:
-	    w_byte(TYPE_MODULE, arg);
-	    {
-		VALUE path = class2path(obj);
-		w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
-	    }
-	    break;
-
-	  case T_BIGNUM:
-	    w_byte(TYPE_BIGNUM, arg);
-	    {
-		char sign = RBIGNUM_SIGN(obj) ? '+' : '-';
-		long len = RBIGNUM_LEN(obj);
-		BDIGIT *d = RBIGNUM_DIGITS(obj);
-
-		w_byte(sign, arg);
-		w_long(SHORTLEN(len), arg); /* w_short? */
-		while (len--) {
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
-		    BDIGIT num = *d;
-		    int i;
-
-		    for (i=0; i<SIZEOF_BDIGITS; i+=SIZEOF_SHORT) {
-			w_short(num & SHORTMASK, arg);
-			num = SHORTDN(num);
-			if (len == 0 && num == 0) break;
-		    }
-#else
-		    w_short(*d, arg);
-#endif
-		    d++;
-		}
-	    }
-	    break;
-
-	  case T_STRING:
-#if WITH_OBJC
-	    w_uclass(obj, rb_objc_str_is_pure(obj), arg);
-#else
-	    w_uclass(obj, rb_cString, arg);
-#endif
-	    w_byte(TYPE_STRING, arg);
-	    w_bytes(RSTRING_PTR(obj), RSTRING_LEN(obj), arg);
-	    break;
-
-	  case T_REGEXP:
-	    w_uclass(obj, rb_cRegexp, arg);
-	    w_byte(TYPE_REGEXP, arg);
-	    VALUE re_str = rb_regexp_source(obj);
-	    w_bytes(RSTRING_PTR(re_str), RSTRING_LEN(re_str), arg);
-	    w_byte(rb_reg_options_to_mri(rb_reg_options(obj)), arg);
-	    break;
-
-	  case T_ARRAY:
-#if WITH_OBJC
-	    w_uclass(obj, rb_objc_ary_is_pure(obj), arg);
-#else
-	    w_uclass(obj, rb_cArray, arg);
-#endif
-	    w_byte(TYPE_ARRAY, arg);
-	    {
-		long len = RARRAY_LEN(obj);
-#if WITH_OBJC
-		long i;
-		w_long(len, arg);
-		for (i = 0; i < len; i++)
-		    w_object(RARRAY_AT(obj, i), arg, limit);
-#else
-		VALUE *ptr = RARRAY_PTR(obj);
-
-		w_long(len, arg);
-		while (len--) {
-		    w_object(*ptr, arg, limit);
-		    ptr++;
-		}
-#endif
-	    }
-	    break;
-
-	  case T_HASH:
-#if WITH_OBJC
-	    w_uclass(obj, rb_objc_hash_is_pure(obj), arg);
-#else
-	    w_uclass(obj, rb_cHash, arg);
-#endif
-#if WITH_OBJC
-	    w_byte(TYPE_HASH, arg);
-	    /* TODO: encode ifnone too */
-#else
-	    if (NIL_P(RHASH(obj)->ifnone)) {
-		w_byte(TYPE_HASH, arg);
-	    }
-	    else if (FL_TEST(obj, FL_USER2)) {
-		/* FL_USER2 means HASH_PROC_DEFAULT (see hash.c) */
-		rb_raise(rb_eTypeError, "can't dump hash with default proc");
-	    }
-	    else {
-		w_byte(TYPE_HASH_DEF, arg);
-	    }
-#endif
-	    w_long(RHASH_SIZE(obj), arg);
-	    rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
-#if !WITH_OBJC
-	    if (!NIL_P(RHASH(obj)->ifnone)) {
-		w_object(RHASH(obj)->ifnone, arg, limit);
-	    }
-#endif
-	    break;
-
-	  case T_STRUCT:
-	    w_class(TYPE_STRUCT, obj, arg, Qtrue);
-	    {
-		long len = RSTRUCT_LEN(obj);
-		VALUE mem;
-		long i;
-
-		w_long(len, arg);
-		mem = rb_struct_members(obj);
-		for (i=0; i<len; i++) {
-		    w_symbol(SYM2ID(RARRAY_AT(mem, i)), arg);
-		    w_object(RSTRUCT_PTR(obj)[i], arg, limit);
-		}
-	    }
-	    break;
-
-	  case T_NATIVE:
-	  case T_OBJECT:
-	    w_class(TYPE_OBJECT, obj, arg, Qtrue);
-	    w_objivar(obj, &c_arg);
-	    break;
-
-	  case T_DATA:
-	    {
-		VALUE v;
-
-		if (!rb_obj_respond_to(obj, s_dump_data, Qtrue)) {
-		    rb_raise(rb_eTypeError,
-			     "no marshal_dump is defined for class %s",
-			     rb_obj_classname(obj));
-		}
-		v = rb_funcall(obj, s_dump_data, 0);
-		check_dump_arg(arg);
-		w_class(TYPE_DATA, obj, arg, Qtrue);
-		w_object(v, arg, limit);
-	    }
-	    break;
-
-	  default:
-	    rb_raise(rb_eTypeError, "can't dump %s (type %d)",
-		    rb_obj_classname(obj), TYPE(obj));
-	    break;
-	}
-    }
-    if (hasiv) {
-	w_ivar(obj, ivtbl, &c_arg);
-    }
-}
-
-static VALUE
-dump(struct dump_call_arg *arg)
-{
-    w_object(arg->obj, arg->arg, arg->limit);
-#if 0 // unused
-    if (arg->arg->dest) {
-	rb_io_write(arg->arg->dest, arg->arg->str);
-	rb_bstr_resize(arg->arg->str, 0);
-    }
-#endif
-    return 0;
-}
-
-static VALUE
-dump_ensure(struct dump_arg *arg)
-{
-    if (!DATA_PTR(arg->wrapper)) return 0;
-    st_free_table(arg->symbols);
-    st_free_table(arg->data);
-    st_free_table(arg->compat_tbl);
-    DATA_PTR(arg->wrapper) = 0;
-    arg->wrapper = 0;
-    if (arg->taint) {
-	OBJ_TAINT(arg->str);
-    }
-    return 0;
-}
-
-/*
- * call-seq:
- *      dump( obj [, anIO] , limit=--1 ) => anIO
- *
- * Serializes obj and all descendent objects. If anIO is
- * specified, the serialized data will be written to it, otherwise the
- * data will be returned as a String. If limit is specified, the
- * traversal of subobjects will be limited to that depth. If limit is
- * negative, no checking of depth will be performed.
- *
- *     class Klass
- *       def initialize(str)
- *         @str = str
- *       end
- *       def sayHello
- *         @str
- *       end
- *     end
- *
- * (produces no output)
- *
- *     o = Klass.new("hello\n")
- *     data = Marshal.dump(o)
- *     obj = Marshal.load(data)
- *     obj.sayHello   #=> "hello\n"
- */
-static VALUE
-marshal_dump(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE obj, port, a1, a2;
-    int limit = -1;
-    struct dump_arg *arg;
-    struct dump_call_arg *c_arg;
-
-    port = Qnil;
-    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
-    arg = (struct dump_arg *)xmalloc(sizeof(struct dump_arg));
-    c_arg = (struct dump_call_arg *)xmalloc(sizeof(struct dump_call_arg));
-    if (argc == 3) {
-	if (!NIL_P(a2)) {
-	    limit = NUM2INT(a2);
-	}
-	if (NIL_P(a1)) {
-	    goto type_error;
-	}
-	port = a1;
-    }
-    else if (argc == 2) {
-	if (FIXNUM_P(a1)) {
-	    limit = FIX2INT(a1);
-	}
-	else if (NIL_P(a1)) {
-	    goto type_error;
-	}
-	else {
-	    port = a1;
-	}
-    }
-    arg->dest = 0;
-    bool got_io = false;
-    if (!NIL_P(port)) {
-	if (!rb_obj_respond_to(port, s_write, Qtrue)) {
-type_error:
-	    rb_raise(rb_eTypeError, "instance of IO needed");
-	}
-	GC_WB(&arg->str, rb_bstr_new());
-#if 0 // unused
-	GC_WB(&arg->dest, port);
-#endif
-	if (rb_obj_respond_to(port, s_binmode, Qtrue)) {
-	    rb_funcall2(port, s_binmode, 0, 0);
-	}
-	got_io = true;
-    }
-    else {
-	port = rb_bstr_new();
-	GC_WB(&arg->str, port);
-    }
-
-    GC_WB(&arg->symbols, st_init_numtable());
-    GC_WB(&arg->data, st_init_numtable());
-    arg->taint = Qfalse;
-    GC_WB(&arg->compat_tbl, st_init_numtable());
-    GC_WB(&arg->wrapper, Data_Wrap_Struct(rb_cData, NULL, 0, arg));
-    arg->encodings = 0;
-    GC_WB(&c_arg->obj, obj);
-    GC_WB(&c_arg->arg, arg);
-    c_arg->limit = limit;
-
-    w_byte(MARSHAL_MAJOR, arg);
-    w_byte(MARSHAL_MINOR, arg);
-
-    rb_ensure(dump, (VALUE)c_arg, dump_ensure, (VALUE)arg);
-
-    // If we got an IO object as the port, make sure to write the bytestring
-    // to it before leaving!
-    if (got_io) {
-	rb_io_write(port, arg->str);	
-    }
-    else {
-	rb_str_force_encoding(port, rb_encodings[ENCODING_UTF8]);
-    }
-    return port;
-}
-
-struct load_arg {
-    VALUE src;
-    long offset;
-    st_table *symbols;
-    VALUE data;
-    VALUE proc;
-    int taint;
-    st_table *compat_tbl;
-    VALUE compat_tbl_wrapper;
-};
-
-static void
-check_load_arg(struct load_arg *arg)
-{
-    if (!DATA_PTR(arg->compat_tbl_wrapper)) {
-	rb_raise(rb_eRuntimeError, "Marshal.load reentered");
-    }
-}
-
-static VALUE r_entry(VALUE v, struct load_arg *arg);
-static VALUE r_object(struct load_arg *arg);
-static VALUE path2class(const char *path);
-
-static int
-r_byte(struct load_arg *arg)
-{
-    int c;
-
-    if (TYPE(arg->src) == T_STRING) {
-	if (RSTRING_LEN(arg->src) > arg->offset) {
-	    c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
-	}
-	else {
-	    rb_raise(rb_eArgError, "marshal data too short");
-	}
-    }
-    else {
-	VALUE src = arg->src;
-	VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
-	check_load_arg(arg);
-	if (NIL_P(v)) {
-	    rb_eof_error();
-	}
-	c = (unsigned char)NUM2CHR(v);
-    }
-
-    return c;
-}
-
-static void
-long_toobig(int size)
-{
-    rb_raise(rb_eTypeError,
-	    "long too big for this architecture (size %zd, given %d)",
-	    sizeof(long), size);
-}
-
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
-#else  /* not __STDC__ */
-/* As in Harbison and Steele.  */
-# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
-#endif
-
-static long
-r_long(struct load_arg *arg)
-{
-    register long x;
-    int c = SIGN_EXTEND_CHAR(r_byte(arg));
-    long i;
-
-    if (c == 0) return 0;
-    if (c > 0) {
-	if (4 < c && c < 128) {
-	    return c - 5;
-	}
-	if (c > sizeof(long)) long_toobig(c);
-	x = 0;
-	for (i=0;i<c;i++) {
-	    x |= (long)r_byte(arg) << (8*i);
-	}
-    }
-    else {
-	if (-129 < c && c < -4) {
-	    return c + 5;
-	}
-	c = -c;
-	if (c > sizeof(long)) long_toobig(c);
-	x = -1;
-	for (i=0;i<c;i++) {
-	    x &= ~((long)0xff << (8*i));
-	    x |= (long)r_byte(arg) << (8*i);
-	}
-    }
-    return x;
-}
-
-#define r_bytes(arg) r_bytes0(r_long(arg), (arg))
-
-static VALUE
-r_bytes0(long len, struct load_arg *arg)
-{
-    VALUE str;
-
-    if (len == 0) {
-	return rb_str_new(0, 0);
-    }
-    if (TYPE(arg->src) == T_STRING) {
-	if (RSTRING_LEN(arg->src) - arg->offset >= len) {
-	    str = rb_bstr_new();
-	    rb_bstr_resize(str, len + 1);
-	    uint8_t *data = rb_bstr_bytes(str);
-	    memcpy(data, (UInt8 *)RSTRING_PTR(arg->src) + arg->offset, len);
-	    data[len] = '\0';
-	    arg->offset += len;
-	}
-	else {
-too_short:
-	    rb_raise(rb_eArgError, "marshal data too short");
-	}
-    }
-    else {
-	VALUE src = arg->src;
-	VALUE n = LONG2NUM(len);
-	str = rb_funcall2(src, s_read, 1, &n);
-	check_load_arg(arg);
-	if (NIL_P(str)) {
-	    goto too_short;
-	}
-	StringValue(str);
-	if (RSTRING_LEN(str) != len) {
-	    goto too_short;
-	}
-	if (OBJ_TAINTED(str)) {
-	    arg->taint = Qtrue;
-	}
-    }
-    return str;
-}
-
-static ID
-r_symlink(struct load_arg *arg)
-{
-    ID id;
-    long num = r_long(arg);
-
-    if (st_lookup(arg->symbols, num, (st_data_t *)&id)) {
-	return id;
-    }
-    rb_raise(rb_eArgError, "bad symbol");
-}
-
-static ID
-r_symreal(struct load_arg *arg)
-{
-    volatile VALUE s = r_bytes(arg);
-    ID id = rb_intern(RSTRING_PTR(s));
-
-    st_insert(arg->symbols, arg->symbols->num_entries, id);
-
-    return id;
-}
-
-static ID
-r_symbol(struct load_arg *arg)
-{
-    int type;
-
-    switch ((type = r_byte(arg))) {
-      case TYPE_SYMBOL:
-	return r_symreal(arg);
-      case TYPE_SYMLINK:
-	return r_symlink(arg);
-      default:
-	rb_raise(rb_eArgError, "dump format error(0x%x)", type);
-	break;
-    }
-}
-
-static const char*
-r_unique(struct load_arg *arg)
-{
-    return rb_id2name(r_symbol(arg));
-}
-
-static VALUE
-r_string(struct load_arg *arg)
-{
-    return rb_str_new2(RSTRING_PTR(r_bytes(arg)));
-}
-
-static VALUE
-r_entry(VALUE v, struct load_arg *arg)
-{
-    st_data_t real_obj = (VALUE)Qundef;
-    if (st_lookup(arg->compat_tbl, v, &real_obj)) {
-        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), (VALUE)real_obj);
-    }
-    else {
-        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
-    }
-    if (arg->taint) {
-        OBJ_TAINT(v);
-        if ((VALUE)real_obj != Qundef)
-            OBJ_TAINT((VALUE)real_obj);
-    }
-    return v;
-}
-
-static VALUE
-r_leave(VALUE v, struct load_arg *arg)
-{
-    st_data_t data;
-    if (st_lookup(arg->compat_tbl, v, &data)) {
-        VALUE real_obj = (VALUE)data;
-        rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj));
-        st_data_t key = v;
-        if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
-            marshal_compat_t *compat = (marshal_compat_t*)data;
-            compat->loader(real_obj, v);
-        }
-        st_delete(arg->compat_tbl, &key, 0);
-        v = real_obj;
-    }
-    if (arg->proc) {
-	v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
-	check_load_arg(arg);
-    }
-    return v;
-}
-
-static void
-r_ivar(VALUE obj, struct load_arg *arg)
-{
-    long len;
-
-    len = r_long(arg);
-    if (len > 0) {
-	while (len--) {
-	    ID id = r_symbol(arg);
-	    VALUE val = r_object(arg);
-#if !WITH_OBJC
-	    if (id == rb_id_encoding()) {
-		int idx = rb_enc_find_index(StringValueCStr(val));
-		if (idx > 0) rb_enc_associate_index(obj, idx);
-	    }
-	    else 
-#endif
-	    {
-		rb_ivar_set(obj, id, val);
-	    }
-	}
-    }
-}
-
-static VALUE
-path2class(const char *path)
-{
-    VALUE v = rb_path2class(path);
-
-    if (TYPE(v) != T_CLASS) {
-	rb_raise(rb_eArgError, "%s does not refer class", path);
-    }
-    return v;
-}
-
-static VALUE
-path2module(const char *path)
-{
-    VALUE v = rb_path2class(path);
-
-    if (TYPE(v) != T_MODULE) {
-	rb_raise(rb_eArgError, "%s does not refer module", path);
-    }
-    return v;
-}
-
-static VALUE
-obj_alloc_by_path(const char *path, struct load_arg *arg)
-{
-    VALUE klass;
-    st_data_t data;
-    rb_alloc_func_t allocator;
-
-    klass = path2class(path);
-
-    allocator = rb_get_alloc_func(klass);
-    if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
-        marshal_compat_t *compat = (marshal_compat_t*)data;
-        VALUE real_obj = rb_obj_alloc(klass);
-        VALUE obj = rb_obj_alloc(compat->oldclass);
-        st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
-        return obj;
-    }
-
-    return rb_obj_alloc(klass);
-}
-
-static VALUE
-r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
-{
-    VALUE v = Qnil;
-    int type = r_byte(arg);
-    long id;
-
-    switch (type) {
-      case TYPE_LINK:
-	id = r_long(arg);
-	v = rb_hash_aref(arg->data, LONG2FIX(id));
-	check_load_arg(arg);
-	if (NIL_P(v)) {
-	    rb_raise(rb_eArgError, "dump format error (unlinked)");
-	}
-	if (arg->proc) {
-	    v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
-	    check_load_arg(arg);
-	}
-	break;
-
-      case TYPE_IVAR:
-        {
-	    int ivar = Qtrue;
-
-	    v = r_object0(arg, &ivar, extmod);
-	    if (ivar) r_ivar(v, arg);
-	}
-	break;
-
-      case TYPE_EXTENDED_R:
-	{
-	    VALUE m = path2module(r_unique(arg));
-
-            if (NIL_P(extmod)) extmod = rb_ary_new2(0);
-            rb_ary_push(extmod, m);
-
-	    v = r_object0(arg, 0, extmod);
-            while (RARRAY_LEN(extmod) > 0) {
-                m = rb_ary_pop(extmod);
-                rb_extend_object(v, m);
-            }
-	}
-	break;
-
-      case TYPE_UCLASS:
-	{
-	    VALUE c = path2class(r_unique(arg));
-
-	    if (RCLASS_SINGLETON(c)) {
-		rb_raise(rb_eTypeError, "singleton can't be loaded");
-	    }
-	    v = r_object0(arg, 0, extmod);
-	    if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
-format_error:
-		rb_raise(rb_eArgError, "dump format error (user class)");
-	    }
-	    if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
-		VALUE tmp = rb_obj_alloc(c);
-
-		if (TYPE(v) != TYPE(tmp)) goto format_error;
-	    }
-	    RBASIC(v)->klass = c;
-	}
-	break;
-
-      case TYPE_NIL:
-	v = Qnil;
-	v = r_leave(v, arg);
-	break;
-
-      case TYPE_TRUE:
-	v = Qtrue;
-	v = r_leave(v, arg);
-	break;
-
-      case TYPE_FALSE:
-	v = Qfalse;
-	v = r_leave(v, arg);
-	break;
-
-      case TYPE_FIXNUM:
-	{
-	    long i = r_long(arg);
-	    v = LONG2FIX(i);
-	}
-	v = r_leave(v, arg);
-	break;
-
-      case TYPE_FLOAT:
-	{
-	    double d, t = 0.0;
-	    VALUE str = r_bytes(arg);
-	    const char *ptr = RSTRING_PTR(str);
-
-	    if (strcmp(ptr, "nan") == 0) {
-		d = t / t;
-	    }
-	    else if (strcmp(ptr, "inf") == 0) {
-		d = 1.0 / t;
-	    }
-	    else if (strcmp(ptr, "-inf") == 0) {
-		d = -1.0 / t;
-	    }
-	    else {
-		char *e;
-		d = ruby_strtod(ptr, &e);
-		d = load_mantissa(d, e, strlen(ptr) - (e - ptr));
-	    }
-	    v = DOUBLE2NUM(d);
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_BIGNUM:
-	{
-	    long len;
-	    BDIGIT *digits;
-	    volatile VALUE data;
-
-	    NEWOBJ(big, struct RBignum);
-	    OBJSETUP(big, rb_cBignum, T_BIGNUM);
-	    RBIGNUM_SET_SIGN(big, (r_byte(arg) == '+'));
-	    len = r_long(arg);
-	    data = r_bytes0(len * SIZEOF_SHORT, arg);
-	    rb_big_resize((VALUE)big, (len + (SIZEOF_BDIGITS/SIZEOF_SHORT - 1)) * SIZEOF_SHORT / SIZEOF_BDIGITS);
-	    digits = RBIGNUM_DIGITS(big);
-	    MEMCPY(digits, RSTRING_PTR(data), char, len * SIZEOF_SHORT);
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
-	    MEMZERO((char *)digits + len * SIZEOF_SHORT, char,
-		RBIGNUM_LEN(big) * SIZEOF_BDIGITS - len * SIZEOF_SHORT);
-#endif
-	    len = RBIGNUM_LEN(big);
-	    while (len > 0) {
-		unsigned char *p = (unsigned char *)digits;
-		BDIGIT num = 0;
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
-		int shift = 0;
-		int i;
-
-		for (i=0; i<SIZEOF_BDIGITS; i++) {
-		    num |= (BDIGIT)p[i] << shift;
-		    shift += 8;
-		}
-#else
-		num = p[0] | (p[1] << 8);
-#endif
-		*digits++ = num;
-		len--;
-	    }
-	    v = rb_big_norm((VALUE)big);
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_STRING:
-	v = r_entry(r_string(arg), arg);
-        v = r_leave(v, arg);
-	break;
-
-      case TYPE_REGEXP:
-	{
-	    volatile VALUE str = r_bytes(arg);
-	    const char *cstr = RSTRING_PTR(str);
-	    const int options = rb_reg_options_from_mri(r_byte(arg));
-	    v = r_entry(rb_reg_new(cstr, strlen(cstr), options), arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_ARRAY:
-	{
-	    volatile long len = r_long(arg); /* gcc 2.7.2.3 -O2 bug?? */
-
-	    v = rb_ary_new2(len);
-	    v = r_entry(v, arg);
-	    while (len--) {
-		rb_ary_push(v, r_object(arg));
-	    }
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_HASH:
-      case TYPE_HASH_DEF:
-	{
-	    long len = r_long(arg);
-
-	    v = rb_hash_new();
-	    v = r_entry(v, arg);
-	    while (len--) {
-		VALUE key = r_object(arg);
-		VALUE value = r_object(arg);
-		rb_hash_aset(v, key, value);
-	    }
-#if !WITH_OBJC
-	    if (type == TYPE_HASH_DEF) {
-		RHASH(v)->ifnone = r_object(arg);
-	    }
-#endif
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_STRUCT:
-	{
-	    VALUE klass, mem;
-            VALUE values;
-	    volatile long i;	/* gcc 2.7.2.3 -O2 bug?? */
-	    long len;
-	    ID slot;
-
-	    klass = path2class(r_unique(arg));
-	    len = r_long(arg);
-
-            v = rb_obj_alloc(klass);
-	    if (TYPE(v) != T_STRUCT) {
-		rb_raise(rb_eTypeError, "class %s not a struct", rb_class2name(klass));
-	    }
-	    mem = rb_struct_s_members(klass);
-            if (RARRAY_LEN(mem) != len) {
-                rb_raise(rb_eTypeError, "struct %s not compatible (struct size differs)",
-                         rb_class2name(klass));
-            }
-
-	    v = r_entry(v, arg);
-	    values = rb_ary_new2(len);
-	    for (i=0; i<len; i++) {
-		slot = r_symbol(arg);
-
-		if (RARRAY_AT(mem, i) != ID2SYM(slot)) {
-		    rb_raise(rb_eTypeError, "struct %s not compatible (:%s for :%s)",
-			     rb_class2name(klass),
-			     rb_id2name(slot),
-			     rb_id2name(SYM2ID(RARRAY_AT(mem, i))));
-		}
-                rb_ary_push(values, r_object(arg));
-	    }
-            rb_struct_initialize(v, 0, values);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_USERDEF:
-        {
-	    VALUE klass = path2class(r_unique(arg));
-	    VALUE data;
-
-	    if (!rb_obj_respond_to(klass, s_load, Qtrue)) {
-		rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
-			 rb_class2name(klass));
-	    }
-	    data = r_bytes(arg);
-	    if (ivp) {
-		r_ivar(data, arg);
-		*ivp = Qfalse;
-	    }
-	    v = rb_funcall(klass, s_load, 1, data);
-	    check_load_arg(arg);
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-        break;
-
-      case TYPE_USRMARSHAL:
-        {
-	    VALUE klass = path2class(r_unique(arg));
-	    VALUE data;
-
-	    v = rb_obj_alloc(klass);
-            if (!NIL_P(extmod)) {
-                while (RARRAY_LEN(extmod) > 0) {
-                    VALUE m = rb_ary_pop(extmod);
-                    rb_extend_object(v, m);
-                }
-            }
-	    if (!rb_obj_respond_to(v, s_mload, Qtrue)) {
-		rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
-			 rb_class2name(klass));
-	    }
-	    v = r_entry(v, arg);
-	    data = r_object(arg);
-	    rb_funcall(v, s_mload, 1, data);
-	    check_load_arg(arg);
-            v = r_leave(v, arg);
-	}
-        break;
-
-      case TYPE_OBJECT:
-	{
-            v = obj_alloc_by_path(r_unique(arg), arg);
-	    const int vt = TYPE(v);
-	    if (vt != T_OBJECT && vt != T_NATIVE) {
-		rb_raise(rb_eArgError, "dump format error");
-	    }
-	    v = r_entry(v, arg);
-	    r_ivar(v, arg);
-	    v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_DATA:
-       {
-           VALUE klass = path2class(r_unique(arg));
-           if (rb_obj_respond_to(klass, s_alloc, Qtrue)) {
-	       static int warn = Qtrue;
-	       if (warn) {
-		   rb_warn("define `allocate' instead of `_alloc'");
-		   warn = Qfalse;
-	       }
-	       v = rb_funcall(klass, s_alloc, 0);
-	       check_load_arg(arg);
-           }
-	   else {
-	       v = rb_obj_alloc(klass);
-	   }
-           if (TYPE(v) != T_DATA) {
-               rb_raise(rb_eArgError, "dump format error");
-           }
-           v = r_entry(v, arg);
-           if (!rb_obj_respond_to(v, s_load_data, Qtrue)) {
-               rb_raise(rb_eTypeError,
-                        "class %s needs to have instance method `_load_data'",
-                        rb_class2name(klass));
-           }
-           rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
-	   check_load_arg(arg);
-           v = r_leave(v, arg);
-       }
-       break;
-
-      case TYPE_MODULE_OLD:
-        {
-	    volatile VALUE str = r_bytes(arg);
-
-	    v = rb_path2class(RSTRING_PTR(str));
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_CLASS:
-        {
-	    volatile VALUE str = r_bytes(arg);
-
-	    v = path2class(RSTRING_PTR(str));
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_MODULE:
-        {
-	    volatile VALUE str = r_bytes(arg);
-
-	    v = path2module(RSTRING_PTR(str));
-	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
-	}
-	break;
-
-      case TYPE_SYMBOL:
-	v = ID2SYM(r_symreal(arg));
-	v = r_leave(v, arg);
-	break;
-
-      case TYPE_SYMLINK:
-	v = ID2SYM(r_symlink(arg));
-	break;
-
-      default:
-	rb_raise(rb_eArgError, "dump format error(0x%x)", type);
-	break;
-    }
-    return v;
-}
-
-static VALUE
-r_object(struct load_arg *arg)
-{
-    return r_object0(arg, 0, Qnil);
-}
-
-static VALUE
-load(struct load_arg *arg)
-{
-    return r_object(arg);
-}
-
-static VALUE
-load_ensure(struct load_arg *arg)
-{
-    if (!DATA_PTR(arg->compat_tbl_wrapper)) {
-	return 0;
-    }
-    st_free_table(arg->symbols);
-    st_free_table(arg->compat_tbl);
-    DATA_PTR(arg->compat_tbl_wrapper) = 0;
-    arg->compat_tbl_wrapper = 0;
-    return 0;
-}
-
-/*
- * call-seq:
- *     load( source [, proc] ) => obj
- *     restore( source [, proc] ) => obj
- * 
- * Returns the result of converting the serialized data in source into a
- * Ruby object (possibly with associated subordinate objects). source
- * may be either an instance of IO or an object that responds to
- * to_str. If proc is specified, it will be passed each object as it
- * is deserialized.
- */
-static VALUE
-marshal_load(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE port, proc;
-    int major, minor;
-    VALUE v;
-    struct load_arg *arg;
-
-    arg = (struct load_arg *)xmalloc(sizeof(struct load_arg));
-    rb_scan_args(argc, argv, "11", &port, &proc);
-    v = rb_check_string_type(port);
-    if (!NIL_P(v)) {
-	arg->taint = OBJ_TAINTED(port); /* original taintedness */
-	v = rb_str_bstr(v);
-	port = v;
-    }
-    else if (rb_obj_respond_to(port, s_getbyte, Qtrue)
-	    && rb_obj_respond_to(port, s_read, Qtrue)) {
-	if (rb_obj_respond_to(port, s_binmode, Qtrue)) {
-	    rb_funcall2(port, s_binmode, 0, 0);
-	}
-	arg->taint = Qtrue;
-    }
-    else {
-	rb_raise(rb_eTypeError, "instance of IO needed");
-    }
-    GC_WB(&arg->src, port);
-    arg->offset = 0;
-    GC_WB(&arg->compat_tbl, st_init_numtable());
-    GC_WB(&arg->compat_tbl_wrapper, Data_Wrap_Struct(rb_cData, NULL, 0, arg->compat_tbl));
-
-    major = r_byte(arg);
-    minor = r_byte(arg);
-    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
-	rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
-\tformat version %d.%d required; %d.%d given",
-		 MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
-    }
-    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
-	rb_warn("incompatible marshal file format (can be read)\n\
-\tformat version %d.%d required; %d.%d given",
-		MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
-    }
-
-    GC_WB(&arg->symbols, st_init_numtable());
-    GC_WB(&arg->data, rb_hash_new());
-    if (NIL_P(proc)) {
-	arg->proc = 0;
-    }
-    else {
-	GC_WB(&arg->proc, proc);
-    }
-    v = rb_ensure(load, (VALUE)arg, load_ensure, (VALUE)arg);
-
-    return v;
-}
-
-/*
- * The marshaling library converts collections of Ruby objects into a
- * byte stream, allowing them to be stored outside the currently
- * active script. This data may subsequently be read and the original
- * objects reconstituted.
- * Marshaled data has major and minor version numbers stored along
- * with the object information. In normal use, marshaling can only
- * load data written with the same major version number and an equal
- * or lower minor version number. If Ruby's ``verbose'' flag is set
- * (normally using -d, -v, -w, or --verbose) the major and minor
- * numbers must match exactly. Marshal versioning is independent of
- * Ruby's version numbers. You can extract the version by reading the
- * first two bytes of marshaled data.
- *
- *     str = Marshal.dump("thing")
- *     RUBY_VERSION   #=> "1.9.0"
- *     str[0].ord     #=> 4
- *     str[1].ord     #=> 8
- *
- * Some objects cannot be dumped: if the objects to be dumped include
- * bindings, procedure or method objects, instances of class IO, or
- * singleton objects, a TypeError will be raised.
- * If your class has special serialization needs (for example, if you
- * want to serialize in some specific format), or if it contains
- * objects that would otherwise not be serializable, you can implement
- * your own serialization strategy by defining two methods, _dump and
- * _load:
- * The instance method _dump should return a String object containing
- * all the information necessary to reconstitute objects of this class
- * and all referenced objects up to a maximum depth given as an integer
- * parameter (a value of -1 implies that you should disable depth checking).
- * The class method _load should take a String and return an object of this class.
- */
-void
-Init_marshal(void)
-{
-    VALUE rb_mMarshal = rb_define_module("Marshal");
-
-    s_dump = rb_intern("_dump");
-    s_load = rb_intern("_load");
-    s_mdump = rb_intern("marshal_dump");
-    s_mload = rb_intern("marshal_load");
-    s_dump_data = rb_intern("_dump_data");
-    s_load_data = rb_intern("_load_data");
-    s_alloc = rb_intern("_alloc");
-    s_getbyte = rb_intern("getbyte");
-    s_read = rb_intern("read");
-    s_write = rb_intern("write");
-    s_binmode = rb_intern("binmode");
-
-    rb_objc_define_method(*(VALUE *)rb_mMarshal, "dump", marshal_dump, -1);
-    rb_objc_define_method(*(VALUE *)rb_mMarshal, "load", marshal_load, -1);
-    rb_objc_define_method(*(VALUE *)rb_mMarshal, "restore", marshal_load, -1);
-
-    rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
-    rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
-
-    compat_allocator_tbl = st_init_numtable();
-    compat_allocator_tbl_wrapper =
-	Data_Wrap_Struct(rb_cData, NULL, 0, compat_allocator_tbl);
-    GC_RETAIN(compat_allocator_tbl_wrapper);
-}
-
-VALUE
-rb_marshal_dump(VALUE obj, VALUE port)
-{
-    int argc = 1;
-    VALUE argv[2];
-
-    argv[0] = obj;
-    argv[1] = port;
-    if (!NIL_P(port)) argc = 2;
-    return marshal_dump(0, 0, argc, argv);
-}
-
-VALUE
-rb_marshal_load(VALUE port)
-{
-    return marshal_load(0, 0, 1, &port);
-}

Deleted: MacRuby/trunk/math.c
===================================================================
--- MacRuby/trunk/math.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/math.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,728 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include <math.h>
-#include <errno.h>
-
-VALUE rb_mMath;
-VALUE rb_eMathDomainError;
-
-#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
-#define domain_error(msg) \
-    rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg);
-
-static VALUE
-to_flo(VALUE x)
-{
-    if (CLASS_OF(x) == rb_cFloat) {
-	return x;
-    }
-    if (!rb_obj_is_kind_of(x, rb_cNumeric)) {
-	rb_raise(rb_eTypeError, "can't convert %s into Float",
-		 NIL_P(x) ? "nil" :
-		 x == Qtrue ? "true" :
-		 x == Qfalse ? "false" :
-		 rb_obj_classname(x));
-    }
-    return rb_convert_type(x, T_FLOAT, "Float", "to_f");
-}
-
-#define Need_Float(x) do {if (TYPE(x) != T_FLOAT) {(x) = to_flo(x);}} while(0)
-#define Need_Float2(x,y) do {\
-    Need_Float(x);\
-    Need_Float(y);\
-} while (0)
-
-/*
- *  call-seq:
- *     Math.atan2(y, x)  => float
- *  
- *  Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
- *  -PI..PI.
- *     
- */
-
-VALUE
-math_atan2(VALUE obj, SEL sel, VALUE y, VALUE x)
-{
-    double dx, dy;
-    Need_Float2(y, x);
-    dx = RFLOAT_VALUE(x);
-    dy = RFLOAT_VALUE(y);
-    if (dx == 0.0 && dy == 0.0) {
-	domain_error("atan2");
-    }
-    if (isinf(dx) && isinf(dy)) {
-	domain_error("atan2");
-    }
-    return DBL2NUM(atan2(dy, dx));
-}
-
-
-/*
- *  call-seq:
- *     Math.cos(x)    => float
- *  
- *  Computes the cosine of <i>x</i> (expressed in radians). Returns
- *  -1..1.
- */
-
-VALUE
-math_cos(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(cos(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.sin(x)    => float
- *  
- *  Computes the sine of <i>x</i> (expressed in radians). Returns
- *  -1..1.
- */
-
-VALUE
-math_sin(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-
-    return DOUBLE2NUM(sin(RFLOAT_VALUE(x)));
-}
-
-
-/*
- *  call-seq:
- *     Math.tan(x)    => float
- *  
- *  Returns the tangent of <i>x</i> (expressed in radians).
- */
-
-static VALUE
-math_tan(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-
-    return DOUBLE2NUM(tan(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.acos(x)    => float
- *  
- *  Computes the arc cosine of <i>x</i>. Returns 0..PI.
- */
-
-static VALUE
-math_acos(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < -1.0 || 1.0 < d0) {
-	domain_error("acos");
-    }
-    d = acos(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.asin(x)    => float
- *  
- *  Computes the arc sine of <i>x</i>. Returns -{PI/2} .. {PI/2}.
- */
-
-static VALUE
-math_asin(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < -1.0 || 1.0 < d0) {
-	domain_error("asin");
-    }
-    d = asin(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.atan(x)    => float
- *  
- *  Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
- */
-
-static VALUE
-math_atan(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(atan(RFLOAT_VALUE(x)));
-}
-
-#ifndef HAVE_COSH
-double
-cosh(double x)
-{
-    return (exp(x) + exp(-x)) / 2;
-}
-#endif
-
-/*
- *  call-seq:
- *     Math.cosh(x)    => float
- *  
- *  Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
- */
-
-VALUE
-math_cosh(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    
-    return DOUBLE2NUM(cosh(RFLOAT_VALUE(x)));
-}
-
-#ifndef HAVE_SINH
-double
-sinh(double x)
-{
-    return (exp(x) - exp(-x)) / 2;
-}
-#endif
-
-/*
- *  call-seq:
- *     Math.sinh(x)    => float
- *  
- *  Computes the hyperbolic sine of <i>x</i> (expressed in
- *  radians).
- */
-
-VALUE
-math_sinh(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(sinh(RFLOAT_VALUE(x)));
-}
-
-#ifndef HAVE_TANH
-double
-tanh(double x)
-{
-    return sinh(x) / cosh(x);
-}
-#endif
-
-/*
- *  call-seq:
- *     Math.tanh()    => float
- *  
- *  Computes the hyperbolic tangent of <i>x</i> (expressed in
- *  radians).
- */
-
-static VALUE
-math_tanh(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(tanh(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.acosh(x)    => float
- *  
- *  Computes the inverse hyperbolic cosine of <i>x</i>.
- */
-
-static VALUE
-math_acosh(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < 1.0) {
-	domain_error("acosh");
-    }
-    d = acosh(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.asinh(x)    => float
- *  
- *  Computes the inverse hyperbolic sine of <i>x</i>.
- */
-
-static VALUE
-math_asinh(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(asinh(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.atanh(x)    => float
- *  
- *  Computes the inverse hyperbolic tangent of <i>x</i>.
- */
-
-static VALUE
-math_atanh(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 <  -1.0 || +1.0 <  d0) {
-	domain_error("atanh");
-    }
-    /* check for pole error */
-    if (d0 == -1.0) return DBL2NUM(-INFINITY);
-    if (d0 == +1.0) return DBL2NUM(+INFINITY);
-    d = atanh(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.exp(x)    => float
- *  
- *  Returns e**x.
- */
-
-VALUE
-math_exp(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(exp(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.log(numeric)    => float
- *     Math.log(num,base)   => float
- *  
- *  Returns the natural logarithm of <i>numeric</i>.
- *  If additional second argument is given, it will be the base
- *  of logarithm.
- */
-
-VALUE
-math_log(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE x, base;
-    double d0, d;
-
-    rb_scan_args(argc, argv, "11", &x, &base);
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < 0.0) {
-	domain_error("log");
-    }
-    /* check for pole error */
-    if (d0 == 0.0) {
-	return DBL2NUM(-INFINITY);
-    }
-    d = log(d0);
-    if (argc == 2) {
-	Need_Float(base);
-	d /= log(RFLOAT_VALUE(base));
-    }
-    return DBL2NUM(d);
-}
-
-#ifndef log2
-#ifndef HAVE_LOG2
-double
-log2(double x)
-{
-    return log10(x)/log10(2.0);
-}
-#else
-extern double log2(double);
-#endif
-#endif
-
-/*
- *  call-seq:
- *     Math.log2(numeric)    => float
- *  
- *  Returns the base 2 logarithm of <i>numeric</i>.
- */
-
-static VALUE
-math_log2(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < 0.0) {
-	domain_error("log2");
-    }
-    /* check for pole error */
-    if (d0 == 0.0) {
-	return DBL2NUM(-INFINITY);
-    }
-    d = log2(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.log10(numeric)    => float
- *  
- *  Returns the base 10 logarithm of <i>numeric</i>.
- */
-
-static VALUE
-math_log10(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < 0.0) {
-	domain_error("log10");
-    }
-    /* check for pole error */
-    if (d0 == 0.0) {
-	return DBL2NUM(-INFINITY);
-    }
-    d = log10(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.sqrt(numeric)    => float
- *  
- *  Returns the non-negative square root of <i>numeric</i>.
- */
-
-VALUE
-math_sqrt(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (d0 < 0.0) {
-	domain_error("sqrt");
-    }
-    if (d0 == 0.0) {
-	return DBL2NUM(0.0);
-    }
-    d = sqrt(d0);
-    return DBL2NUM(d);
-}
-
-/*
- *  call-seq:
- *     Math.cbrt(numeric)    => float
- *  
- *  Returns the cube root of <i>numeric</i>.
- */
-
-static VALUE
-math_cbrt(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(cbrt(RFLOAT_VALUE(x)));
-}
-
-/*
- *  call-seq:
- *     Math.frexp(numeric)    => [ fraction, exponent ]
- *  
- *  Returns a two-element array containing the normalized fraction (a
- *  <code>Float</code>) and exponent (a <code>Fixnum</code>) of
- *  <i>numeric</i>.
- *     
- *     fraction, exponent = Math.frexp(1234)   #=> [0.6025390625, 11]
- *     fraction * 2**exponent                  #=> 1234.0
- */
-
-static VALUE
-math_frexp(VALUE obj, SEL sel, VALUE x)
-{
-    double d;
-    int exp;
-
-    Need_Float(x);
-    
-    d = frexp(RFLOAT_VALUE(x), &exp);
-    return rb_assoc_new(DOUBLE2NUM(d), INT2NUM(exp));
-}
-
-/*
- *  call-seq:
- *     Math.ldexp(flt, int) -> float
- *  
- *  Returns the value of <i>flt</i>*(2**<i>int</i>).
- *     
- *     fraction, exponent = Math.frexp(1234)
- *     Math.ldexp(fraction, exponent)   #=> 1234.0
- */
-
-static VALUE
-math_ldexp(VALUE obj, SEL sel, VALUE x, VALUE n)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(ldexp(RFLOAT_VALUE(x), NUM2INT(n)));
-}
-
-/*
- *  call-seq:
- *     Math.hypot(x, y)    => float
- *  
- *  Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
- *  with sides <i>x</i> and <i>y</i>.
- *     
- *     Math.hypot(3, 4)   #=> 5.0
- */
-
-VALUE
-math_hypot(VALUE obj, SEL sel, VALUE x, VALUE y)
-{
-    Need_Float2(x, y);
-    return DOUBLE2NUM(hypot(RFLOAT_VALUE(x), RFLOAT_VALUE(y)));
-}
-
-/*
- * call-seq:
- *    Math.erf(x)  => float
- *
- *  Calculates the error function of x.
- */
-
-static VALUE
-math_erf(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(erf(RFLOAT_VALUE(x)));
-}
-
-/*
- * call-seq:
- *    Math.erfc(x)  => float
- *
- *  Calculates the complementary error function of x.
- */
-
-static VALUE
-math_erfc(VALUE obj, SEL sel, VALUE x)
-{
-    Need_Float(x);
-    return DOUBLE2NUM(erfc(RFLOAT_VALUE(x)));
-}
-
-/*
- * call-seq:
- *    Math.gamma(x)  => float
- *
- *  Calculates the gamma function of x.
- *
- *  Note that gamma(n) is same as fact(n-1) for integer n > 0.
- *  However gamma(n) returns float and can be an approximation.
- *
- *   def fact(n) (1..n).inject(1) {|r,i| r*i } end
- *   1.upto(26) {|i| p [i, Math.gamma(i), fact(i-1)] }
- *   #=> [1, 1.0, 1]
- *   #   [2, 1.0, 1]
- *   #   [3, 2.0, 2]
- *   #   [4, 6.0, 6]
- *   #   [5, 24.0, 24]
- *   #   [6, 120.0, 120]
- *   #   [7, 720.0, 720]
- *   #   [8, 5040.0, 5040]
- *   #   [9, 40320.0, 40320]
- *   #   [10, 362880.0, 362880]
- *   #   [11, 3628800.0, 3628800]
- *   #   [12, 39916800.0, 39916800]
- *   #   [13, 479001600.0, 479001600]
- *   #   [14, 6227020800.0, 6227020800]
- *   #   [15, 87178291200.0, 87178291200]
- *   #   [16, 1307674368000.0, 1307674368000]
- *   #   [17, 20922789888000.0, 20922789888000]
- *   #   [18, 355687428096000.0, 355687428096000]
- *   #   [19, 6.402373705728e+15, 6402373705728000]
- *   #   [20, 1.21645100408832e+17, 121645100408832000]
- *   #   [21, 2.43290200817664e+18, 2432902008176640000]
- *   #   [22, 5.109094217170944e+19, 51090942171709440000]
- *   #   [23, 1.1240007277776077e+21, 1124000727777607680000]
- *   #   [24, 2.5852016738885062e+22, 25852016738884976640000]
- *   #   [25, 6.204484017332391e+23, 620448401733239439360000]
- *   #   [26, 1.5511210043330954e+25, 15511210043330985984000000]
- *
- */
-
-static VALUE
-math_gamma(VALUE obj, SEL sel, VALUE x)
-{
-    static const double fact_table[] = {
-        /* fact(0) */ 1.0,
-        /* fact(1) */ 1.0,
-        /* fact(2) */ 2.0,
-        /* fact(3) */ 6.0,
-        /* fact(4) */ 24.0,
-        /* fact(5) */ 120.0,
-        /* fact(6) */ 720.0,
-        /* fact(7) */ 5040.0,
-        /* fact(8) */ 40320.0,
-        /* fact(9) */ 362880.0,
-        /* fact(10) */ 3628800.0,
-        /* fact(11) */ 39916800.0,
-        /* fact(12) */ 479001600.0,
-        /* fact(13) */ 6227020800.0,
-        /* fact(14) */ 87178291200.0,
-        /* fact(15) */ 1307674368000.0,
-        /* fact(16) */ 20922789888000.0,
-        /* fact(17) */ 355687428096000.0,
-        /* fact(18) */ 6402373705728000.0,
-        /* fact(19) */ 121645100408832000.0,
-        /* fact(20) */ 2432902008176640000.0,
-        /* fact(21) */ 51090942171709440000.0,
-        /* fact(22) */ 1124000727777607680000.0,
-        /* fact(23)=25852016738884976640000 needs 56bit mantissa which is
-         * impossible to represent exactly in IEEE 754 double which have
-         * 53bit mantissa. */
-    };
-    double d0, d;
-    double intpart, fracpart;
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (isinf(d0) && signbit(d0)) {
-	domain_error("gamma");
-    }
-    fracpart = modf(d0, &intpart);
-    if (fracpart == 0.0) {
-	if (intpart < 0) {
-	    domain_error("gamma");
-	}
-	if (0 < intpart &&
-	    intpart - 1 < (double)numberof(fact_table)) {
-	    return DBL2NUM(fact_table[(int)intpart - 1]);
-	}
-    }
-    d = tgamma(d0);
-    return DBL2NUM(d);
-}
-
-/*
- * call-seq:
- *    Math.lgamma(x)  => [float, -1 or 1]
- *
- *  Calculates the logarithmic gamma of x and
- *  the sign of gamma of x.
- *
- *  Math.lgamma(x) is same as
- *   [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]
- *  but avoid overflow by Math.gamma(x) for large x.
- */
-
-#include "lgamma_r.c"
-
-static VALUE
-math_lgamma(VALUE obj, SEL sel, VALUE x)
-{
-    double d0, d;
-    int sign = 1;
-    VALUE v;
-    Need_Float(x);
-    d0 = RFLOAT_VALUE(x);
-    /* check for domain error */
-    if (isinf(d0)) {
-	if (signbit(d0)) {
-	    domain_error("lgamma");
-	}
-	return rb_assoc_new(DBL2NUM(INFINITY), INT2FIX(1));
-    }
-    d = lgamma_r(d0, &sign);
-    v = DBL2NUM(d);
-    return rb_assoc_new(v, INT2FIX(sign));
-
-}
-
-/*
- *  The <code>Math</code> module contains module functions for basic
- *  trigonometric and transcendental functions. See class
- *  <code>Float</code> for a list of constants that
- *  define Ruby's floating point accuracy.
- */     
-
-
-void
-Init_Math(void)
-{
-    rb_mMath = rb_define_module("Math");
-    rb_eMathDomainError = rb_define_class_under(rb_mMath, "DomainError", rb_eStandardError);
-
-#ifdef M_PI
-    rb_define_const(rb_mMath, "PI", DOUBLE2NUM(M_PI));
-#else
-    rb_define_const(rb_mMath, "PI", DOUBLE2NUM(atan(1.0)*4.0));
-#endif
-
-#ifdef M_E
-    rb_define_const(rb_mMath, "E", DOUBLE2NUM(M_E));
-#else
-    rb_define_const(rb_mMath, "E", DOUBLE2NUM(exp(1.0)));
-#endif
-
-    rb_objc_define_module_function(rb_mMath, "atan2", math_atan2, 2);
-    rb_objc_define_module_function(rb_mMath, "cos", math_cos, 1);
-    rb_objc_define_module_function(rb_mMath, "sin", math_sin, 1);
-    rb_objc_define_module_function(rb_mMath, "tan", math_tan, 1);
-
-    rb_objc_define_module_function(rb_mMath, "acos", math_acos, 1);
-    rb_objc_define_module_function(rb_mMath, "asin", math_asin, 1);
-    rb_objc_define_module_function(rb_mMath, "atan", math_atan, 1);
-
-    rb_objc_define_module_function(rb_mMath, "cosh", math_cosh, 1);
-    rb_objc_define_module_function(rb_mMath, "sinh", math_sinh, 1);
-    rb_objc_define_module_function(rb_mMath, "tanh", math_tanh, 1);
-
-    rb_objc_define_module_function(rb_mMath, "acosh", math_acosh, 1);
-    rb_objc_define_module_function(rb_mMath, "asinh", math_asinh, 1);
-    rb_objc_define_module_function(rb_mMath, "atanh", math_atanh, 1);
-
-    rb_objc_define_module_function(rb_mMath, "exp", math_exp, 1);
-    rb_objc_define_module_function(rb_mMath, "log", math_log, -1);
-    rb_objc_define_module_function(rb_mMath, "log2", math_log2, 1);
-    rb_objc_define_module_function(rb_mMath, "log10", math_log10, 1);
-    rb_objc_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
-    rb_objc_define_module_function(rb_mMath, "cbrt", math_cbrt, 1);
-
-    rb_objc_define_module_function(rb_mMath, "frexp", math_frexp, 1);
-    rb_objc_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
-
-    rb_objc_define_module_function(rb_mMath, "hypot", math_hypot, 2);
-
-    rb_objc_define_module_function(rb_mMath, "erf",  math_erf,  1);
-    rb_objc_define_module_function(rb_mMath, "erfc", math_erfc, 1);
-
-    rb_objc_define_module_function(rb_mMath, "gamma", math_gamma, 1);
-    rb_objc_define_module_function(rb_mMath, "lgamma", math_lgamma, 1);
-}

Deleted: MacRuby/trunk/mt.c
===================================================================
--- MacRuby/trunk/mt.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/mt.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,178 +0,0 @@
-/*
- * This is based on trimmed version of MT19937.  To get the original version,
- * contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>.
- * 
- * The original copyright notice follows.
- * 
- * A C-program for MT19937, with initialization improved 2002/2/10.
- * Coded by Takuji Nishimura and Makoto Matsumoto.
- * This is a faster version by taking Shawn Cokus's optimization,
- * Matthe Bellew's simplification, Isaku Wada's real version.
- * 
- * Before using, initialize the state by using init_genrand(mt, seed)
- * or init_by_array(mt, init_key, key_length).
- * 
- * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- * 
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- * 
- *   3. The names of its contributors may not be used to endorse or promote
- *      products derived from this software without specific prior written
- *      permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
- * 
- * Any feedback is very welcome.
- * http://www.math.keio.ac.jp/matumoto/emt.html
- * email: matumoto at math.keio.ac.jp
- */
-
-#include <limits.h>
-typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
-
-/* Period parameters */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0dfU	/* constant vector a */
-#define UMASK 0x80000000U	/* most significant w-r bits */
-#define LMASK 0x7fffffffU	/* least significant r bits */
-#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
-#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))
-
-enum {MT_MAX_STATE = N};
-
-struct MT {
-    /* assume int is enough to store 32bits */
-    unsigned int state[N]; /* the array for the state vector  */
-    unsigned int *next;
-    int left;
-};
-
-#define genrand_initialized(mt) ((mt)->next != 0)
-#define uninit_genrand(mt) ((mt)->next = 0)
-
-/* initializes state[N] with a seed */
-static void
-init_genrand(struct MT *mt, unsigned int s)
-{
-    int j;
-    mt->state[0] = s & 0xffffffffU;
-    for (j=1; j<N; j++) {
-        mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->state[j-1] >> 30)) + j);
-        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
-        /* In the previous versions, MSBs of the seed affect   */
-        /* only MSBs of the array state[].                     */
-        /* 2002/01/09 modified by Makoto Matsumoto             */
-        mt->state[j] &= 0xffffffff;  /* for >32 bit machines */
-    }
-    mt->left = 1;
-    mt->next = mt->state + N;
-}
-
-/* initialize by an array with array-length */
-/* init_key is the array for initializing keys */
-/* key_length is its length */
-/* slight change for C++, 2004/2/26 */
-static void
-init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
-{
-    int i, j, k;
-    init_genrand(mt, 19650218U);
-    i=1; j=0;
-    k = (N>key_length ? N : key_length);
-    for (; k; k--) {
-        mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
-          + init_key[j] + j; /* non linear */
-        mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
-        i++; j++;
-        if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
-        if (j>=key_length) j=0;
-    }
-    for (k=N-1; k; k--) {
-        mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
-          - i; /* non linear */
-        mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
-        i++;
-        if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
-    }
-
-    mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
-}
-
-static void
-next_state(struct MT *mt)
-{
-    unsigned int *p = mt->state;
-    int j;
-
-    /* if init_genrand() has not been called, */
-    /* a default initial seed is used         */
-    if (!genrand_initialized(mt)) init_genrand(mt, 5489U);
-
-    mt->left = N;
-    mt->next = mt->state;
-
-    for (j=N-M+1; --j; p++)
-        *p = p[M] ^ TWIST(p[0], p[1]);
-
-    for (j=M; --j; p++)
-        *p = p[M-N] ^ TWIST(p[0], p[1]);
-
-    *p = p[M-N] ^ TWIST(p[0], mt->state[0]);
-}
-
-/* generates a random number on [0,0xffffffff]-interval */
-static unsigned int
-genrand_int32(struct MT *mt)
-{
-    unsigned int y;
-
-    if (--mt->left <= 0) next_state(mt);
-    y = *mt->next++;
-
-    /* Tempering */
-    y ^= (y >> 11);
-    y ^= (y << 7) & 0x9d2c5680;
-    y ^= (y << 15) & 0xefc60000;
-    y ^= (y >> 18);
-
-    return y;
-}
-
-/* generates a random number on [0,1) with 53-bit resolution*/
-static double
-genrand_real(struct MT *mt)
-{
-    unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
-    return(a*67108864.0+b)*(1.0/9007199254740992.0);
-}
-
-/* generates a random number on [0,1] with 53-bit resolution*/
-// TODO
-#define genrand_real2 genrand_real
-
-/* These real versions are due to Isaku Wada, 2002/01/09 added */
-
-#undef N
-#undef M

Deleted: MacRuby/trunk/numeric.c
===================================================================
--- MacRuby/trunk/numeric.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/numeric.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,3575 +0,0 @@
-/*
- * MacRuby numeric types.
- * 
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include <ctype.h>
-#include <math.h>
-#include <stdio.h>
-
-#include "objc.h"
-#include <ruby/node.h>
-#include "vm.h"
-#include "id.h"
-#include "encoding.h"
-#include "class.h"
-
-#include <unicode/utf8.h>
-
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-/* use IEEE 64bit values if not defined */
-#ifndef FLT_RADIX
-#define FLT_RADIX 2
-#endif
-#ifndef FLT_ROUNDS
-#define FLT_ROUNDS 1
-#endif
-#ifndef DBL_MIN
-#define DBL_MIN 2.2250738585072014e-308
-#endif
-#ifndef DBL_MAX
-#define DBL_MAX 1.7976931348623157e+308
-#endif
-#ifndef DBL_MIN_EXP
-#define DBL_MIN_EXP (-1021)
-#endif
-#ifndef DBL_MAX_EXP
-#define DBL_MAX_EXP 1024
-#endif
-#ifndef DBL_MIN_10_EXP
-#define DBL_MIN_10_EXP (-307)
-#endif
-#ifndef DBL_MAX_10_EXP
-#define DBL_MAX_10_EXP 308
-#endif
-#ifndef DBL_DIG
-#define DBL_DIG 15
-#endif
-#ifndef DBL_MANT_DIG
-#define DBL_MANT_DIG 53
-#endif
-#ifndef DBL_EPSILON
-#define DBL_EPSILON 2.2204460492503131e-16
-#endif
-
-#ifdef HAVE_INFINITY
-#elif BYTE_ORDER == LITTLE_ENDIAN
-const unsigned char rb_infinity[] = "\x00\x00\x80\x7f";
-#else
-const unsigned char rb_infinity[] = "\x7f\x80\x00\x00";
-#endif
-
-#ifdef HAVE_NAN
-#elif BYTE_ORDER == LITTLE_ENDIAN
-const unsigned char rb_nan[] = "\x00\x00\xc0\x7f";
-#else
-const unsigned char rb_nan[] = "\x7f\xc0\x00\x00";
-#endif
-
-#ifndef HAVE_ROUND
-double
-round(double x)
-{
-    double f;
-
-    if (x > 0.0) {
-	f = floor(x);
-	x = f + (x - f >= 0.5);
-    }
-    else if (x < 0.0) {
-	f = ceil(x);
-	x = f - (f - x >= 0.5);
-    }
-    return x;
-}
-#endif
-
-static SEL sel_coerce, selDiv, selDivmod, selExp;
-static ID id_to_i, id_eq;
-
-VALUE rb_cNumeric;
-VALUE rb_cFloat;
-VALUE rb_cInteger;
-VALUE rb_cFixnum;
-VALUE rb_cNSNumber;
-
-VALUE rb_eZeroDivError;
-VALUE rb_eFloatDomainError;
-
-void
-rb_num_zerodiv(void)
-{
-    rb_raise(rb_eZeroDivError, "divided by 0");
-}
-
-/*
- *  call-seq:
- *     num.coerce(numeric)   => array
- *
- *  If <i>aNumeric</i> is the same type as <i>num</i>, returns an array
- *  containing <i>aNumeric</i> and <i>num</i>. Otherwise, returns an
- *  array with both <i>aNumeric</i> and <i>num</i> represented as
- *  <code>Float</code> objects. 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.
- *
- *     1.coerce(2.5)   #=> [2.5, 1.0]
- *     1.2.coerce(3)   #=> [3.0, 1.2]
- *     1.coerce(2)     #=> [2, 1]
- */
-
-static VALUE
-num_coerce(VALUE x, SEL sel, VALUE y)
-{
-    if (CLASS_OF(x) == CLASS_OF(y))
-	return rb_assoc_new(y, x);
-    return rb_assoc_new(rb_Float(y), rb_Float(x));
-}
-
-static VALUE
-coerce_body(VALUE *x)
-{
-    return rb_vm_call(x[1], sel_coerce, 1, &x[0]);
-}
-
-static VALUE
-coerce_rescue(VALUE *x)
-{
-    volatile VALUE v = rb_inspect(x[1]);
-
-    rb_raise(rb_eTypeError, "%s can't be coerced into %s",
-	     rb_special_const_p(x[1])?
-	     RSTRING_PTR(v):
-	     rb_obj_classname(x[1]),
-	     rb_obj_classname(x[0]));
-    return Qnil;		/* dummy */
-}
-
-static int
-do_coerce(VALUE *x, VALUE *y, int err)
-{
-    VALUE ary;
-    VALUE a[2];
-
-    a[0] = *x; a[1] = *y;
-
-    ary = rb_rescue(coerce_body, (VALUE)a, err?coerce_rescue:0, (VALUE)a);
-    if (TYPE(ary) != T_ARRAY || RARRAY_LEN(ary) != 2) {
-	if (err) {
-	    rb_raise(rb_eTypeError, "coerce must return [x, y]");
-	}
-	return Qfalse;
-    }
-
-    *x = RARRAY_AT(ary, 0);
-    *y = RARRAY_AT(ary, 1);
-    return Qtrue;
-}
-
-VALUE
-rb_num_coerce_bin(VALUE x, VALUE y, ID func)
-{
-    do_coerce(&x, &y, Qtrue);
-    return rb_funcall(x, func, 1, y);
-}
-
-VALUE
-rb_objc_num_coerce_bin(VALUE x, VALUE y, SEL sel)
-{
-    do_coerce(&x, &y, Qtrue);
-    return rb_vm_call(x, sel, 1, &y);
-}
-
-VALUE
-rb_num_coerce_cmp(VALUE x, VALUE y, ID func)
-{
-    if (do_coerce(&x, &y, Qfalse)) {
-	return rb_funcall(x, func, 1, y);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_objc_num_coerce_cmp(VALUE x, VALUE y, SEL sel)
-{
-    if (do_coerce(&x, &y, Qfalse)) {
-	return rb_vm_call(x, sel, 1, &y);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_num_coerce_relop(VALUE x, VALUE y, ID func)
-{
-    VALUE c, x0 = x, y0 = y;
-
-    if (!do_coerce(&x, &y, FALSE) ||
-	NIL_P(c = rb_funcall(x, func, 1, y))) {
-	rb_cmperr(x0, y0);
-	return Qnil;		/* not reached */
-    }
-    return c;
-}
-
-VALUE
-rb_objc_num_coerce_relop(VALUE x, VALUE y, SEL sel)
-{
-    VALUE c, x0 = x, y0 = y;
-
-    if (!do_coerce(&x, &y, Qfalse) ||
-	NIL_P(c = rb_vm_call(x, sel, 1, &y))) {
-	rb_cmperr(x0, y0);
-	return Qnil;		/* not reached */
-    }
-    return c;
-}
-
-
-/*
- * Trap attempts to add methods to <code>Numeric</code> objects. Always
- * raises a <code>TypeError</code>
- */
-
-static VALUE
-num_sadded(VALUE x, SEL sel, VALUE name)
-{
-    /* ruby_frame = ruby_frame->prev; */ /* pop frame for "singleton_method_added" */
-    /* Numerics should be values; singleton_methods should not be added to them */
-    rb_raise(rb_eTypeError,
-	     "can't define singleton method \"%s\" for %s",
-	     rb_id2name(rb_to_id(name)),
-	     rb_obj_classname(x));
-    return Qnil;		/* not reached */
-}
-
-/* :nodoc: */
-static VALUE
-num_init_copy(VALUE x, SEL sel, VALUE y)
-{
-    /* Numerics are immutable values, which should not be copied */
-    rb_raise(rb_eTypeError, "can't copy %s", rb_obj_classname(x));
-    return Qnil;		/* not reached */
-}
-
-/*
- *  call-seq:
- *     +num    => num
- *
- *  Unary Plus---Returns the receiver's value.
- */
-
-static VALUE
-num_uplus(VALUE num, SEL sel)
-{
-    return num;
-}
-
-/*
- *  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.
- */
-
-static VALUE
-num_uminus(VALUE num, SEL sel)
-{
-    VALUE zero;
-
-    zero = INT2FIX(0);
-    do_coerce(&zero, &num, Qtrue);
-
-    return rb_vm_call(zero, selMINUS, 1, &num);
-}
-
-/*
- *  call-seq:
- *     num.quo(numeric)    =>   result
- *
- *  Returns most exact division (rational for integers, float for floats).
- */
-
-static VALUE
-num_quo(VALUE x, SEL sel, VALUE y)
-{
-    return rb_vm_call(rb_rational_raw1(x), selDIV, 1, &y);
-}
-
-
-/*
- *  call-seq:
- *     num.fdiv(numeric)    =>   float
- *
- *  Returns float division.
- */
-
-static VALUE
-num_fdiv(VALUE x, SEL sel, VALUE y)
-{
-    return rb_vm_call(rb_Float(x), selDIV, 1, &y);
-}
-
-
-static VALUE num_floor(VALUE num, SEL sel);
-
-/*
- *  call-seq:
- *     num.div(numeric)    => integer
- *
- *  Uses <code>/</code> to perform division, then converts the result to
- *  an integer. <code>Numeric</code> does not define the <code>/</code>
- *  operator; this is left to subclasses.
- */
-
-static VALUE
-num_div(VALUE x, SEL sel, VALUE y)
-{
-    if (rb_equal(INT2FIX(0), y)) {
-	rb_num_zerodiv();
-    }
-    return num_floor(rb_vm_call(x, selDIV, 1, &y), 0);
-}
-
-
-/*
- *  call-seq:
- *     num.divmod( aNumeric ) -> anArray
- *
- *  Returns an array containing the quotient and modulus obtained by
- *  dividing <i>num</i> by <i>aNumeric</i>. If <code>q, r =
- *  x.divmod(y)</code>, then
- *
- *      q = floor(float(x)/float(y))
- *      x = q*y + r
- *
- *  The quotient is rounded toward -infinity, as shown in the following table:
- *
- *     a    |  b  |  a.divmod(b)  |   a/b   | a.modulo(b) | a.remainder(b)
- *    ------+-----+---------------+---------+-------------+---------------
- *     13   |  4  |   3,    1     |   3     |    1        |     1
- *    ------+-----+---------------+---------+-------------+---------------
- *     13   | -4  |  -4,   -3     |  -3     |   -3        |     1
- *    ------+-----+---------------+---------+-------------+---------------
- *    -13   |  4  |  -4,    3     |  -4     |    3        |    -1
- *    ------+-----+---------------+---------+-------------+---------------
- *    -13   | -4  |   3,   -1     |   3     |   -1        |    -1
- *    ------+-----+---------------+---------+-------------+---------------
- *     11.5 |  4  |   2,    3.5   |   2.875 |    3.5      |     3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *     11.5 | -4  |  -3,   -0.5   |  -2.875 |   -0.5      |     3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *    -11.5 |  4  |  -3,    0.5   |  -2.875 |    0.5      |    -3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *    -11.5 | -4  |   2,   -3.5   |   2.875 |   -3.5      |    -3.5
- *
- *
- *  Examples
- *
- *     11.divmod(3)         #=> [3, 2]
- *     11.divmod(-3)        #=> [-4, -1]
- *     11.divmod(3.5)       #=> [3, 0.5]
- *     (-11).divmod(3.5)    #=> [-4, 3.0]
- *     (11.5).divmod(3.5)   #=> [3, 1.0]
- */
-
-static VALUE
-num_divmod(VALUE x, SEL sel, VALUE y)
-{
-    return rb_assoc_new(num_div(x, 0, y), rb_vm_call(x, selMOD, 1, &y));
-}
-
-/*
- *  call-seq:
- *     num.modulo(numeric)    => result
- *
- *  Equivalent to
- *  <i>num</i>.<code>divmod(</code><i>aNumeric</i><code>)[1]</code>.
- */
-
-static VALUE
-num_modulo(VALUE x, SEL sel, VALUE y)
-{
-    VALUE tmp1 = rb_vm_call(x, selDiv, 1, &y);
-    VALUE tmp2 = rb_vm_call(y, selMULT, 1, &tmp1);
-    return rb_vm_call(x, selMINUS, 1, &tmp2);
-}
-
-/*
- *  call-seq:
- *     num.remainder(numeric)    => result
- *
- *  If <i>num</i> and <i>numeric</i> have different signs, returns
- *  <em>mod</em>-<i>numeric</i>; otherwise, returns <em>mod</em>. In
- *  both cases <em>mod</em> is the value
- *  <i>num</i>.<code>modulo(</code><i>numeric</i><code>)</code>. The
- *  differences between <code>remainder</code> and modulo
- *  (<code>%</code>) are shown in the table under <code>Numeric#divmod</code>.
- */
-
-static VALUE
-num_remainder(VALUE x, SEL sel, VALUE y)
-{
-    VALUE z = rb_vm_call(x, selMOD, 1, &y);
-
-    VALUE zero = INT2FIX(0);
-    if ((!rb_equal(z, INT2FIX(0))) &&
-	((RTEST(rb_vm_call(x, selLT, 1, &zero)) &&
-	  RTEST(rb_vm_call(y, selGT, 1, &zero))) ||
-	 (RTEST(rb_vm_call(x, selGT, 1, &zero)) &&
-	  RTEST(rb_vm_call(y, selLT, 1, &zero))))) {
-	return rb_vm_call(z, selMINUS, 1, &y);
-    }
-    return z;
-}
-
-/*
- *  call-seq:
- *     num.real?  ->  true or false
- *
- *  Returns <code>true</code> if <i>num</i> is a <code>Real</code>
- *  (i.e. non <code>Complex</code>).
- */
-
-static VALUE
-num_real_p(VALUE num, SEL sel)
-{
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     num.scalar? -> true or false
- *
- *  Returns <code>true</code> if <i>num</i> is an <code>Scalar</code>
- *  (i.e. non <code>Complex</code>).
- */
-
-static VALUE
-num_scalar_p(VALUE num, SEL sel)
-{
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     num.integer? -> true or false
- *
- *  Returns <code>true</code> if <i>num</i> is an <code>Integer</code>
- *  (including <code>Fixnum</code> and <code>Bignum</code>).
- */
-
-static VALUE
-num_int_p(VALUE num, SEL sel)
-{
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     num.abs   => num or numeric
- *
- *  Returns the absolute value of <i>num</i>.
- *
- *     12.abs         #=> 12
- *     (-34.56).abs   #=> 34.56
- *     -34.56.abs     #=> 34.56
- */
-
-static VALUE
-num_abs(VALUE num, SEL sel)
-{
-    VALUE zero = INT2FIX(0);
-    if (RTEST(rb_vm_call(num, selLT, 1, &zero))) {
-	return rb_funcall(num, rb_intern("-@"), 0);
-    }
-    return num;
-}
-
-
-/*
- *  call-seq:
- *     num.zero?    => true or false
- *
- *  Returns <code>true</code> if <i>num</i> has a zero value.
- */
-
-static VALUE
-num_zero_p(VALUE num, SEL sel)
-{
-    if (rb_equal(num, INT2FIX(0))) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     num.nonzero?    => num or nil
- *
- *  Returns <i>num</i> if <i>num</i> is not zero, <code>nil</code>
- *  otherwise. This behavior is useful when chaining comparisons:
- *
- *     a = %w( z Bb bB bb BB a aA Aa AA A )
- *     b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
- *     b   #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]
- */
-
-static VALUE
-num_nonzero_p(VALUE num, SEL sel)
-{
-    if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
-	return Qnil;
-    }
-    return num;
-}
-
-/*
- *  call-seq:
- *     num.to_int    => integer
- *
- *  Invokes the child class's <code>to_i</code> method to convert
- *  <i>num</i> to an integer.
- */
-
-static VALUE
-num_to_int(VALUE num, SEL sel)
-{
-    return rb_funcall(num, id_to_i, 0, 0);
-}
-
-
-/********************************************************************
- *
- * Document-class: Float
- *
- *  <code>Float</code> objects represent real numbers using the native
- *  architecture's double-precision floating point representation.
- */
-
-VALUE
-rb_float_new(double d)
-{
-    return DBL2FIXFLOAT(d);
-}
-
-/*
- *  call-seq:
- *     flt.to_s    => string
- *
- *  Returns a string containing a representation of self. As well as a
- *  fixed or exponential form of the number, the call may return
- *  ``<code>NaN</code>'', ``<code>Infinity</code>'', and
- *  ``<code>-Infinity</code>''.
- */
-
-static VALUE
-flo_to_s(VALUE flt, SEL sel)
-{
-    char buf[32];
-    double value = RFLOAT_VALUE(flt);
-    char *p, *e;
-
-    if (isinf(value))
-	return rb_usascii_str_new2(value < 0 ? "-Infinity" : "Infinity");
-    else if(isnan(value))
-	return rb_usascii_str_new2("NaN");
-
-    sprintf(buf, "%#.15g", value); /* ensure to print decimal point */
-    if (!(e = strchr(buf, 'e'))) {
-	e = buf + strlen(buf);
-    }
-    if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */
-	sprintf(buf, "%#.14e", value);
-	if (!(e = strchr(buf, 'e'))) {
-	    e = buf + strlen(buf);
-	}
-    }
-    p = e;
-    while (p[-1]=='0' && ISDIGIT(p[-2]))
-	p--;
-    memmove(p, e, strlen(e)+1);
-    return rb_usascii_str_new2(buf);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-flo_coerce(VALUE x, SEL sel, VALUE y)
-{
-    return rb_assoc_new(rb_Float(y), x);
-}
-
-/*
- * call-seq:
- *    -float   => float
- *
- * Returns float, negated.
- */
-
-static VALUE
-flo_uminus(VALUE flt, SEL sel)
-{
-    return DOUBLE2NUM(-RFLOAT_VALUE(flt));
-}
-
-/*
- * call-seq:
- *   float + other   => float
- *
- * Returns a new float which is the sum of <code>float</code>
- * and <code>other</code>.
- */
-
-VALUE
-rb_flo_plus(VALUE x, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
-      case T_BIGNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
-      case T_FLOAT:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selPLUS);
-    }
-}
-
-static VALUE
-flo_plus(VALUE x, SEL sel, VALUE y)
-{
-    return rb_flo_plus(x, y);
-}
-
-/*
- * call-seq:
- *   float + other   => float
- *
- * Returns a new float which is the difference of <code>float</code>
- * and <code>other</code>.
- */
-
-VALUE
-rb_flo_minus(VALUE x, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
-      case T_BIGNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
-      case T_FLOAT:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMINUS);
-    }
-}
-
-static VALUE
-flo_minus(VALUE x, SEL sel, VALUE y)
-{
-    return rb_flo_minus(x, y);
-}
-
-/*
- * call-seq:
- *   float * other   => float
- *
- * Returns a new float which is the product of <code>float</code>
- * and <code>other</code>.
- */
-
-VALUE
-rb_flo_mul(VALUE x, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
-      case T_BIGNUM:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
-      case T_FLOAT:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMULT);
-    }
-}
-
-static VALUE
-flo_mul(VALUE x, SEL sel, VALUE y)
-{
-    return rb_flo_mul(x, y);
-}
-
-/*
- * call-seq:
- *   float / other   => float
- *
- * Returns a new float which is the result of dividing
- * <code>float</code> by <code>other</code>.
- */
-
-VALUE
-rb_flo_div(VALUE x, VALUE y)
-{
-    long f_y;
-    double d;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	f_y = FIX2LONG(y);
-	return DOUBLE2NUM(RFLOAT_VALUE(x) / (double)f_y);
-      case T_BIGNUM:
-	d = rb_big2dbl(y);
-	return DOUBLE2NUM(RFLOAT_VALUE(x) / d);
-      case T_FLOAT:
-	return DOUBLE2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selDIV);
-    }
-}
-
-static VALUE
-flo_div(VALUE x, SEL sel, VALUE y)
-{
-    return rb_flo_div(x, y);
-}
-
-static VALUE
-flo_quo(VALUE x, SEL sel, VALUE y)
-{
-    return rb_vm_call(x, selDIV, 1, &y);
-}
-
-static void
-flodivmod(double x, double y, double *divp, double *modp)
-{
-    double div, mod;
-
-    if (y == 0.0) {
-	rb_num_zerodiv();
-    }
-#ifdef HAVE_FMOD
-    mod = fmod(x, y);
-#else
-    {
-	double z;
-
-	modf(x/y, &z);
-	mod = x - z * y;
-    }
-#endif
-    if (isinf(x) && !isinf(y) && !isnan(y))
-	div = x;
-    else
-	div = (x - mod) / y;
-    if (y*mod < 0) {
-	mod += y;
-	div -= 1.0;
-    }
-    if (modp) *modp = mod;
-    if (divp) *divp = div;
-}
-
-
-/*
- *  call-seq:
- *     flt % other         => float
- *     flt.modulo(other)   => float
- *
- *  Return the modulo after division of <code>flt</code> by <code>other</code>.
- *
- *     6543.21.modulo(137)      #=> 104.21
- *     6543.21.modulo(137.24)   #=> 92.9299999999996
- */
-
-static VALUE
-flo_mod(VALUE x, SEL sel, VALUE y)
-{
-    double fy, mod;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	fy = (double)FIX2LONG(y);
-	break;
-      case T_BIGNUM:
-	fy = rb_big2dbl(y);
-	break;
-      case T_FLOAT:
-	fy = RFLOAT_VALUE(y);
-	break;
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMOD);
-    }
-    flodivmod(RFLOAT_VALUE(x), fy, 0, &mod);
-    return DOUBLE2NUM(mod);
-}
-
-static VALUE
-dbl2ival(double d)
-{
-    if (FIXABLE(d)) {
-	d = round(d);
-	return LONG2FIX((long)d);
-    }
-    return rb_dbl2big(d);
-}
-
-/*
- *  call-seq:
- *     flt.divmod(numeric)    => array
- *
- *  See <code>Numeric#divmod</code>.
- */
-
-static VALUE
-flo_divmod(VALUE x, SEL sel, VALUE y)
-{
-    double fy, div, mod;
-    volatile VALUE a, b;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	fy = (double)FIX2LONG(y);
-	break;
-      case T_BIGNUM:
-	fy = rb_big2dbl(y);
-	break;
-      case T_FLOAT:
-	fy = RFLOAT_VALUE(y);
-	break;
-      default:
-	return rb_objc_num_coerce_bin(x, y, selDivmod);
-    }
-    flodivmod(RFLOAT_VALUE(x), fy, &div, &mod);
-    a = dbl2ival(div);
-    b = DOUBLE2NUM(mod);
-    return rb_assoc_new(a, b);
-}
-
-/*
- * call-seq:
- *
- *  flt ** other   => float
- *
- * Raises <code>float</code> the <code>other</code> power.
- */
-
-static VALUE
-flo_pow(VALUE x, SEL sel, VALUE y)
-{
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	return DOUBLE2NUM(pow(RFLOAT_VALUE(x), (double)FIX2LONG(y)));
-      case T_BIGNUM:
-	return DOUBLE2NUM(pow(RFLOAT_VALUE(x), rb_big2dbl(y)));
-      case T_FLOAT:
-	return DOUBLE2NUM(pow(RFLOAT_VALUE(x), RFLOAT_VALUE(y)));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selExp);
-    }
-}
-
-/*
- *  call-seq:
- *     num.eql?(numeric)    => true or false
- *
- *  Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
- *  same type and have equal values.
- *
- *     1 == 1.0          #=> true
- *     1.eql?(1.0)       #=> false
- *     (1.0).eql?(1.0)   #=> true
- */
-
-static VALUE
-num_eql(VALUE x, SEL sel, VALUE y)
-{
-    if (TYPE(x) != TYPE(y)) return Qfalse;
-
-    return rb_equal(x, y);
-}
-
-/*
- *  call-seq:
- *     num <=> other -> 0 or nil
- *
- *  Returns zero if <i>num</i> equals <i>other</i>, <code>nil</code>
- *  otherwise.
- */
-
-static VALUE
-num_cmp(VALUE x, SEL sel, VALUE y)
-{
-    if (x == y) return INT2FIX(0);
-    return Qnil;
-}
-
-static VALUE
-num_equal(VALUE x, VALUE y)
-{
-    if (x == y) return Qtrue;
-    return rb_funcall(y, id_eq, 1, x);
-}
-
-/*
- *  call-seq:
- *     flt == obj   => true or false
- *
- *  Returns <code>true</code> only if <i>obj</i> has the same value
- *  as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
- *  requires <i>obj</i> to be a <code>Float</code>.
- *
- *     1.0 == 1   #=> true
- *
- */
-
-static VALUE
-flo_eq(VALUE x, SEL sel, VALUE y)
-{
-    volatile double a, b;
-
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = FIX2LONG(y);
-	break;
-      case T_BIGNUM:
-	b = rb_big2dbl(y);
-	break;
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	if (isnan(b)) return Qfalse;
-	break;
-      default:
-	return num_equal(x, y);
-    }
-    a = RFLOAT_VALUE(x);
-    if (isnan(a)) return Qfalse;
-    return (a == b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- *   flt.hash   => integer
- *
- * Returns a hash code for this float.
- */
-
-static VALUE
-flo_hash(VALUE num, SEL sel)
-{
-    double d;
-    int hash;
-
-    d = RFLOAT_VALUE(num);
-    hash = rb_memhash(&d, sizeof(d));
-    return INT2FIX(hash);
-}
-
-VALUE
-rb_dbl_cmp(double a, double b)
-{
-    if (isnan(a) || isnan(b)) return Qnil;
-    if (a == b) return INT2FIX(0);
-    if (a > b) return INT2FIX(1);
-    if (a < b) return INT2FIX(-1);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     flt <=> numeric   => -1, 0, +1
- *
- *  Returns -1, 0, or +1 depending on whether <i>flt</i> is less than,
- *  equal to, or greater than <i>numeric</i>. This is the basis for the
- *  tests in <code>Comparable</code>.
- */
-
-static VALUE
-flo_cmp(VALUE x, SEL sel, VALUE y)
-{
-    double a, b;
-
-    a = RFLOAT_VALUE(x);
-    if (isnan(a)) {
-	return Qnil;
-    }
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	if (isinf(a)) {
-	    if (a > 0.0) {
-		return INT2FIX(1);
-	    }
-	    else {
-		return INT2FIX(-1);
-	    }
-	}
-	b = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	break;
-
-      default:
-	if (isinf(a) && (!rb_respond_to(y, rb_intern("infinite?")) ||
-			 !RTEST(rb_funcall(y, rb_intern("infinite?"), 0, 0)))) {
-	    if (a > 0.0) {
-		return INT2FIX(1);
-	    }
-	    return INT2FIX(-1);
-	}
-	return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
-    }
-    return rb_dbl_cmp(a, b);
-}
-
-/*
- * call-seq:
- *   flt > other    =>  true or false
- *
- * <code>true</code> if <code>flt</code> is greater than <code>other</code>.
- */
-
-static VALUE
-flo_gt(VALUE x, SEL sel, VALUE y)
-{
-    double a, b;
-
-    a = RFLOAT_VALUE(x);
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	b = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	if (isnan(b)) return Qfalse;
-	break;
-
-      default:
-	return rb_objc_num_coerce_relop(x, y, selGT);
-    }
-    if (isnan(a)) return Qfalse;
-    return (a > b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- *   flt >= other    =>  true or false
- *
- * <code>true</code> if <code>flt</code> is greater than
- * or equal to <code>other</code>.
- */
-
-static VALUE
-flo_ge(VALUE x, SEL sel, VALUE y)
-{
-    double a, b;
-
-    a = RFLOAT_VALUE(x);
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	b = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	if (isnan(b)) return Qfalse;
-	break;
-
-      default:
-	return rb_objc_num_coerce_relop(x, y, selGE);
-    }
-    if (isnan(a)) return Qfalse;
-    return (a >= b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- *   flt < other    =>  true or false
- *
- * <code>true</code> if <code>flt</code> is less than <code>other</code>.
- */
-
-static VALUE
-flo_lt(VALUE x, SEL sel, VALUE y)
-{
-    double a, b;
-
-    a = RFLOAT_VALUE(x);
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	b = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	if (isnan(b)) return Qfalse;
-	break;
-
-      default:
-	return rb_objc_num_coerce_relop(x, y, selLT);
-    }
-    if (isnan(a)) return Qfalse;
-    return (a < b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- *   flt <= other    =>  true or false
- *
- * <code>true</code> if <code>flt</code> is less than
- * or equal to <code>other</code>.
- */
-
-static VALUE
-flo_le(VALUE x, SEL sel, VALUE y)
-{
-    double a, b;
-
-    a = RFLOAT_VALUE(x);
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	b = (double)FIX2LONG(y);
-	break;
-
-      case T_BIGNUM:
-	b = rb_big2dbl(y);
-	break;
-
-      case T_FLOAT:
-	b = RFLOAT_VALUE(y);
-	if (isnan(b)) return Qfalse;
-	break;
-
-      default:
-	return rb_objc_num_coerce_relop(x, y, selLE);
-    }
-    if (isnan(a)) return Qfalse;
-    return (a <= b)?Qtrue:Qfalse;
-}
-
-/*
- *  call-seq:
- *     flt.eql?(obj)   => true or false
- *
- *  Returns <code>true</code> only if <i>obj</i> is a
- *  <code>Float</code> with the same value as <i>flt</i>. Contrast this
- *  with <code>Float#==</code>, which performs type conversions.
- *
- *     1.0.eql?(1)   #=> false
- */
-
-static VALUE
-flo_eql(VALUE x, SEL sel, VALUE y)
-{
-    if (TYPE(y) == T_FLOAT) {
-	double a = RFLOAT_VALUE(x);
-	double b = RFLOAT_VALUE(y);
-
-	if (isnan(a) || isnan(b)) return Qfalse;
-	if (a == b) return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   flt.to_f   => flt
- *
- * As <code>flt</code> is already a float, returns <i>self</i>.
- */
-
-static VALUE
-flo_to_f(VALUE num, SEL sel)
-{
-    return num;
-}
-
-/*
- *  call-seq:
- *     flt.abs    => float
- *
- *  Returns the absolute value of <i>flt</i>.
- *
- *     (-34.56).abs   #=> 34.56
- *     -34.56.abs     #=> 34.56
- *
- */
-
-static VALUE
-flo_abs(VALUE flt, SEL sel)
-{
-    double val = fabs(RFLOAT_VALUE(flt));
-    return DOUBLE2NUM(val);
-}
-
-/*
- *  call-seq:
- *     flt.zero? -> true or false
- *
- *  Returns <code>true</code> if <i>flt</i> is 0.0.
- *
- */
-
-static VALUE
-flo_zero_p(VALUE num, SEL sel)
-{
-    if (RFLOAT_VALUE(num) == 0.0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     flt.nan? -> true or false
- *
- *  Returns <code>true</code> if <i>flt</i> is an invalid IEEE floating
- *  point number.
- *
- *     a = -1.0      #=> -1.0
- *     a.nan?        #=> false
- *     a = 0.0/0.0   #=> NaN
- *     a.nan?        #=> true
- */
-
-static VALUE
-flo_is_nan_p(VALUE num, SEL sel)
-{
-    double value = RFLOAT_VALUE(num);
-
-    return isnan(value) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     flt.infinite? -> nil, -1, +1
- *
- *  Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
- *  is finite, -infinity, or +infinity.
- *
- *     (0.0).infinite?        #=> nil
- *     (-1.0/0.0).infinite?   #=> -1
- *     (+1.0/0.0).infinite?   #=> 1
- */
-
-static VALUE
-flo_is_infinite_p(VALUE num, SEL sel)
-{
-    double value = RFLOAT_VALUE(num);
-
-    if (isinf(value)) {
-	return INT2FIX( value < 0 ? -1 : 1 );
-    }
-
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     flt.finite? -> true or false
- *
- *  Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
- *  point number (it is not infinite, and <code>nan?</code> is
- *  <code>false</code>).
- *
- */
-
-static VALUE
-flo_is_finite_p(VALUE num, SEL sel)
-{
-    double value = RFLOAT_VALUE(num);
-
-#if 0//HAVE_FINITE
-    if (!finite(value))
-	return Qfalse;
-#else
-    if (isinf(value) || isnan(value))
-	return Qfalse;
-#endif
-
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     flt.floor   => integer
- *
- *  Returns the largest integer less than or equal to <i>flt</i>.
- *
- *     1.2.floor      #=> 1
- *     2.0.floor      #=> 2
- *     (-1.2).floor   #=> -2
- *     (-2.0).floor   #=> -2
- */
-
-static VALUE
-flo_floor(VALUE num, SEL sel)
-{
-    double f = floor(RFLOAT_VALUE(num));
-    long val;
-
-    if (!FIXABLE(f)) {
-	return rb_dbl2big(f);
-    }
-    val = f;
-    return LONG2FIX(val);
-}
-
-/*
- *  call-seq:
- *     flt.ceil    => integer
- *
- *  Returns the smallest <code>Integer</code> greater than or equal to
- *  <i>flt</i>.
- *
- *     1.2.ceil      #=> 2
- *     2.0.ceil      #=> 2
- *     (-1.2).ceil   #=> -1
- *     (-2.0).ceil   #=> -2
- */
-
-static VALUE
-flo_ceil(VALUE num, SEL sel)
-{
-    double f = ceil(RFLOAT_VALUE(num));
-    long val;
-
-    if (!FIXABLE(f)) {
-	return rb_dbl2big(f);
-    }
-    val = f;
-    return LONG2FIX(val);
-}
-
-/*
- *  call-seq:
- *     flt.round([ndigits])   => integer or float
- *
- *  Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits).
- *  Precision may be negative.  Returns a a floating point number when ndigits
- *  is more than one.
- *
- *     1.5.round      #=> 2
- *     (-1.5).round   #=> -2
- */
-
-static VALUE
-flo_round(VALUE num, SEL sel, int argc, VALUE *argv)
-{
-    VALUE nd;
-    double number, f;
-    int ndigits = 0, i;
-    long val;
-
-    if (argc > 0 && rb_scan_args(argc, argv, "01", &nd) == 1) {
-	ndigits = NUM2INT(nd);
-    }
-    number  = RFLOAT_VALUE(num);
-    f = 1.0;
-    i = abs(ndigits);
-    while  (--i >= 0)
-	f = f*10.0;
-
-    if (ndigits < 0) number /= f;
-    else number *= f;
-    number = round(number);
-    if (ndigits < 0) number *= f;
-    else number /= f;
-
-    if (ndigits > 0) return DOUBLE2NUM(number);
-
-    if (!FIXABLE(number)) {
-	return rb_dbl2big(number);
-    }
-    val = number;
-    return LONG2FIX(val);
-}
-
-/*
- *  call-seq:
- *     flt.to_i       => integer
- *     flt.to_int     => integer
- *     flt.truncate   => integer
- *
- *  Returns <i>flt</i> truncated to an <code>Integer</code>.
- */
-
-static VALUE
-flo_truncate(VALUE num, SEL sel)
-{
-    double f = RFLOAT_VALUE(num);
-    long val;
-
-    if (f > 0.0) f = floor(f);
-    if (f < 0.0) f = ceil(f);
-
-    if (!FIXABLE(f)) {
-	return rb_dbl2big(f);
-    }
-    val = f;
-    return LONG2FIX(val);
-}
-
-/*
- *  call-seq:
- *     num.floor    => integer
- *
- *  Returns the largest integer less than or equal to <i>num</i>.
- *  <code>Numeric</code> implements this by converting <i>anInteger</i>
- *  to a <code>Float</code> and invoking <code>Float#floor</code>.
- *
- *     1.floor      #=> 1
- *     (-1).floor   #=> -1
- */
-
-static VALUE
-num_floor(VALUE num, SEL sel)
-{
-    return flo_floor(rb_Float(num), 0);
-}
-
-
-/*
- *  call-seq:
- *     num.ceil    => integer
- *
- *  Returns the smallest <code>Integer</code> greater than or equal to
- *  <i>num</i>. Class <code>Numeric</code> achieves this by converting
- *  itself to a <code>Float</code> then invoking
- *  <code>Float#ceil</code>.
- *
- *     1.ceil        #=> 1
- *     1.2.ceil      #=> 2
- *     (-1.2).ceil   #=> -1
- *     (-1.0).ceil   #=> -1
- */
-
-static VALUE
-num_ceil(VALUE num, SEL sel)
-{
-    return flo_ceil(rb_Float(num), 0);
-}
-
-/*
- *  call-seq:
- *     num.round([ndigits])    => integer or float
- *
- *  Rounds <i>num</i> to a given precision in decimal digits (default 0 digits).
- *  Precision may be negative.  Returns a a floating point number when ndigits
- *  is more than one.  <code>Numeric</code> implements this by converting itself
- *  to a <code>Float</code> and invoking <code>Float#round</code>.
- */
-
-static VALUE
-num_round(VALUE num, SEL sel, int argc, VALUE* argv)
-{
-    return flo_round(rb_Float(num), 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     num.truncate    => integer
- *
- *  Returns <i>num</i> truncated to an integer. <code>Numeric</code>
- *  implements this by converting its value to a float and invoking
- *  <code>Float#truncate</code>.
- */
-
-static VALUE
-num_truncate(VALUE num, SEL sel)
-{
-    return flo_truncate(rb_Float(num), 0);
-}
-
-
-/*
- *  call-seq:
- *     num.step(limit, step ) {|i| block }     => num
- *
- *  Invokes <em>block</em> with the sequence of numbers starting at
- *  <i>num</i>, incremented by <i>step</i> on each call. The loop
- *  finishes when the value to be passed to the block is greater than
- *  <i>limit</i> (if <i>step</i> is positive) or less than
- *  <i>limit</i> (if <i>step</i> is negative). If all the arguments are
- *  integers, the loop operates using an integer counter. If any of the
- *  arguments are floating point numbers, all are converted to floats,
- *  and the loop is executed <i>floor(n + n*epsilon)+ 1</i> times,
- *  where <i>n = (limit - num)/step</i>. Otherwise, the loop
- *  starts at <i>num</i>, uses either the <code><</code> or
- *  <code>></code> operator to compare the counter against
- *  <i>limit</i>, and increments itself using the <code>+</code>
- *  operator.
- *
- *     1.step(10, 2) { |i| print i, " " }
- *     Math::E.step(Math::PI, 0.2) { |f| print f, " " }
- *
- *  <em>produces:</em>
- *
- *     1 3 5 7 9
- *     2.71828182845905 2.91828182845905 3.11828182845905
- */
-
-static VALUE
-num_step(VALUE from, SEL sel, int argc, VALUE *argv)
-{
-    VALUE to, step;
-
-    RETURN_ENUMERATOR(from, argc, argv);
-    if (argc == 1) {
-	to = argv[0];
-	step = INT2FIX(1);
-    }
-    else {
-	if (argc == 2) {
-	    to = argv[0];
-	    step = argv[1];
-	}
-	else {
-	    rb_raise(rb_eArgError, "wrong number of arguments");
-	}
-	if (rb_equal(step, INT2FIX(0))) {
-	    rb_raise(rb_eArgError, "step can't be 0");
-	}
-    }
-
-    if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
-	long i, end, diff;
-
-	i = FIX2LONG(from);
-	end = FIX2LONG(to);
-	diff = FIX2LONG(step);
-
-	if (diff > 0) {
-	    while (i <= end) {
-		rb_yield(LONG2FIX(i));
-		RETURN_IF_BROKEN();
-		i += diff;
-	    }
-	}
-	else {
-	    while (i >= end) {
-		rb_yield(LONG2FIX(i));
-		RETURN_IF_BROKEN();
-		i += diff;
-	    }
-	}
-    }
-    else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) {
-	const double epsilon = DBL_EPSILON;
-	double beg = NUM2DBL(from);
-	double end = NUM2DBL(to);
-	double unit = NUM2DBL(step);
-	double n = (end - beg)/unit;
-	double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
-	long i;
-
-	if (err>0.5) err=0.5;
-	n = floor(n + err) + 1;
-	for (i=0; i<n; i++) {
-	    rb_yield(DOUBLE2NUM(i*unit+beg));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {
-	VALUE i = from;
-	SEL cmp;
-
-	VALUE zero = INT2FIX(0);
-	if (RTEST(rb_vm_call(step, selGT, 1, &zero))) {
-	    cmp = selGT;
-	}
-	else {
-	    cmp = selLT;
-	}
-	for (;;) {
-	    if (RTEST(rb_vm_call(i, cmp, 1, &to))) {
-		break;
-	    }
-	    rb_yield(i);
-	    RETURN_IF_BROKEN();
-	    i = rb_vm_call(i, selPLUS, 1, &step);
-	}
-    }
-    return from;
-}
-
-SIGNED_VALUE
-rb_num2long(VALUE val)
-{
-  again:
-    if (NIL_P(val)) {
-	rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
-    }
-
-    if (FIXNUM_P(val)) return FIX2LONG(val);
-
-    switch (TYPE(val)) {
-      case T_FLOAT:
-	if (RFLOAT_VALUE(val) <= (double)LONG_MAX
-	    && RFLOAT_VALUE(val) >= (double)LONG_MIN) {
-	    return (SIGNED_VALUE)(RFLOAT_VALUE(val));
-	}
-	else {
-	    char buf[24];
-	    char *s;
-
-	    sprintf(buf, "%-.10g", RFLOAT_VALUE(val));
-	    if ((s = strchr(buf, ' ')) != 0) *s = '\0';
-	    rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
-	}
-
-      case T_BIGNUM:
-	return rb_big2long(val);
-
-      default:
-	val = rb_to_int(val);
-	goto again;
-    }
-}
-
-VALUE
-rb_num2ulong(VALUE val)
-{
-    if (TYPE(val) == T_BIGNUM) {
-	return rb_big2ulong(val);
-    }
-    return (VALUE)rb_num2long(val);
-}
-
-#if SIZEOF_INT < SIZEOF_VALUE
-static void
-check_int(SIGNED_VALUE num)
-{
-    const char *s;
-
-    if (num < INT_MIN) {
-	s = "small";
-    }
-    else if (num > INT_MAX) {
-	s = "big";
-    }
-    else {
-	return;
-    }
-    rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `int'", num, s);
-}
-
-static void
-check_uint(VALUE num)
-{
-    if (num > UINT_MAX) {
-	rb_raise(rb_eRangeError, "integer %"PRIuVALUE " too big to convert to `unsigned int'", num);
-    }
-}
-
-long
-rb_num2int(VALUE val)
-{
-    long num = rb_num2long(val);
-
-    check_int(num);
-    return num;
-}
-
-long
-rb_fix2int(VALUE val)
-{
-    long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
-
-    check_int(num);
-    return num;
-}
-
-unsigned long
-rb_num2uint(VALUE val)
-{
-    unsigned long num = rb_num2ulong(val);
-
-    if (RTEST(rb_vm_call(INT2FIX(0), selLT, 1, &val))) {
-	check_uint(num);
-    }
-    return num;
-}
-
-unsigned long
-rb_fix2uint(VALUE val)
-{
-    unsigned long num;
-
-    if (!FIXNUM_P(val)) {
-	return rb_num2uint(val);
-    }
-    num = FIX2ULONG(val);
-    if (FIX2LONG(val) > 0) {
-	check_uint(num);
-    }
-    return num;
-}
-#else
-long
-rb_num2int(VALUE val)
-{
-    return rb_num2long(val);
-}
-
-long
-rb_fix2int(VALUE val)
-{
-    return FIX2INT(val);
-}
-#endif
-
-VALUE
-rb_num2fix(VALUE val)
-{
-    long v;
-
-    if (FIXNUM_P(val)) return val;
-
-    v = rb_num2long(val);
-    if (!FIXABLE(v))
-	rb_raise(rb_eRangeError, "integer %"PRIdVALUE " out of range of fixnum", v);
-    return LONG2FIX(v);
-}
-
-#if HAVE_LONG_LONG
-
-LONG_LONG
-rb_num2ll(VALUE val)
-{
-    if (NIL_P(val)) {
-	rb_raise(rb_eTypeError, "no implicit conversion from nil");
-    }
-
-    if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
-
-    switch (TYPE(val)) {
-      case T_FLOAT:
-	if (RFLOAT_VALUE(val) <= (double)LLONG_MAX
-	    && RFLOAT_VALUE(val) >= (double)LLONG_MIN) {
-	    return (LONG_LONG)(RFLOAT_VALUE(val));
-	}
-	else {
-	    char buf[24];
-	    char *s;
-
-	    sprintf(buf, "%-.10g", RFLOAT_VALUE(val));
-	    if ((s = strchr(buf, ' ')) != 0) *s = '\0';
-	    rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
-	}
-
-      case T_BIGNUM:
-	return rb_big2ll(val);
-
-      case T_STRING:
-	rb_raise(rb_eTypeError, "no implicit conversion from string");
-	return Qnil;            /* not reached */
-
-      case T_TRUE:
-      case T_FALSE:
-	rb_raise(rb_eTypeError, "no implicit conversion from boolean");
-	return Qnil;		/* not reached */
-
-      default:
-	val = rb_to_int(val);
-	return NUM2LL(val);
-    }
-}
-
-unsigned LONG_LONG
-rb_num2ull(VALUE val)
-{
-    if (TYPE(val) == T_BIGNUM) {
-	return rb_big2ull(val);
-    }
-    return (unsigned LONG_LONG)rb_num2ll(val);
-}
-
-#endif  /* HAVE_LONG_LONG */
-
-static VALUE
-num_numerator(VALUE num, SEL sel)
-{
-    return rb_funcall(rb_Rational1(num), rb_intern("numerator"), 0);
-}
-
-static VALUE
-num_denominator(VALUE num, SEL sel)
-{
-    return rb_funcall(rb_Rational1(num), rb_intern("denominator"), 0);
-}
-
-/*
- * Document-class: Integer
- *
- *  <code>Integer</code> is the basis for the two concrete classes that
- *  hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>.
- *
- */
-
-
-/*
- *  call-seq:
- *     int.to_i      => int
- *     int.to_int    => int
- *     int.floor     => int
- *     int.ceil      => int
- *     int.round     => int
- *     int.truncate  => int
- *
- *  As <i>int</i> is already an <code>Integer</code>, all these
- *  methods simply return the receiver.
- */
-
-static VALUE
-int_to_i(VALUE num, SEL sel)
-{
-    return num;
-}
-
-/*
- *  call-seq:
- *     int.integer? -> true
- *
- *  Always returns <code>true</code>.
- */
-
-static VALUE
-int_int_p(VALUE num, SEL sel)
-{
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     int.odd? -> true or false
- *
- *  Returns <code>true</code> if <i>int</i> is an odd number.
- */
-
-static VALUE
-int_odd_p(VALUE num, SEL sel)
-{
-    VALUE two = INT2FIX(2);
-    if (rb_vm_call(num, selMOD, 1, &two) != INT2FIX(0)) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     int.even? -> true or false
- *
- *  Returns <code>true</code> if <i>int</i> is an even number.
- */
-
-static VALUE
-int_even_p(VALUE num, SEL sel)
-{
-    return int_odd_p(num, 0) == Qtrue ? Qfalse : Qtrue;
-}
-
-/*
- *  call-seq:
- *     fixnum.next    => integer
- *     fixnum.succ    => integer
- *
- *  Returns the <code>Integer</code> equal to <i>int</i> + 1.
- *
- *     1.next      #=> 2
- *     (-1).next   #=> 0
- */
-
-static VALUE
-fix_succ(VALUE num, SEL sel)
-{
-    long i = FIX2LONG(num) + 1;
-    return LONG2NUM(i);
-}
-
-/*
- *  call-seq:
- *     int.next    => integer
- *     int.succ    => integer
- *
- *  Returns the <code>Integer</code> equal to <i>int</i> + 1.
- *
- *     1.next      #=> 2
- *     (-1).next   #=> 0
- */
-
-static VALUE
-int_succ(VALUE num, SEL sel)
-{
-    if (FIXNUM_P(num)) {
-	long i = FIX2LONG(num) + 1;
-	return LONG2NUM(i);
-    }
-    VALUE one = INT2FIX(1);
-    return rb_vm_call(num, selPLUS, 1, &one);
-}
-
-/*
- *  call-seq:
- *     int.pred    => integer
- *
- *  Returns the <code>Integer</code> equal to <i>int</i> - 1.
- *
- *     1.pred      #=> 0
- *     (-1).pred   #=> -2
- */
-
-static VALUE
-int_pred(VALUE num, SEL sel)
-{
-    if (FIXNUM_P(num)) {
-	long i = FIX2LONG(num) - 1;
-	return LONG2NUM(i);
-    }
-    VALUE one = INT2FIX(1);
-    return rb_vm_call(num, selMINUS, 1, &one);
-}
-
-/*
- *  call-seq:
- *     int.chr([encoding])    => string
- *
- *  Returns a string containing the character represented by the
- *  receiver's value according to +encoding+.
- *
- *     65.chr    #=> "A"
- *     230.chr   #=> "\346"
- *     255.chr(Encoding::UTF_8)   #=> "\303\277"
- */
-
-static VALUE
-int_chr(VALUE num, SEL sel, int argc, VALUE *argv)
-{
-    long i = NUM2LONG(num);
-    rb_encoding_t *enc = NULL;
-
-    switch (argc) {
-	case 0:
-	    if (i < 0) {
-out_of_range:
-		rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i);
-	    }
-	    if (0xff < i) {
-		goto decode;
-	    }
-	    else {
-		char c = (char)i;
-		if (i < 0x80) {
-		    return rb_usascii_str_new(&c, 1);
-		}
-		return rb_bstr_new_with_data((uint8_t *)&c, 1);
-	    }
-	    break;
-
-	case 1:
-	    break;
-
-	default:
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)",
-		    argc);
-    }
-
-    enc = rb_to_encoding(argv[0]);
-
-decode:
-    if (i < 0 || i > UINT_MAX) {
-	goto out_of_range;
-    }
-
-    if (enc == NULL) {
-	enc = rb_encodings[ENCODING_BINARY];
-    }
-
-    if (enc == rb_encodings[ENCODING_BINARY]) {
-	uint8_t c = (uint8_t)i;
-	return rb_bstr_new_with_data(&c, 1);
-    }
-
-    if (enc == rb_encodings[ENCODING_ASCII]) {
-	if (i >= 0x80) {
-	    goto out_of_range;
-	}
-	char c = (char)i;
-	return rb_enc_str_new(&c, 1, enc);	
-    }
-
-    if (enc == rb_encodings[ENCODING_UTF8]) {
-	const int bytelen = U8_LENGTH(i);
-	if (bytelen <= 0) {
-	    goto out_of_range;
-	}
-	uint8_t *buf = (uint8_t *)malloc(bytelen);
-	int offset = 0;
-	UBool error = false;
-	U8_APPEND(buf, offset, bytelen, i, error);
-	if (error) {
-	    free(buf);
-	    goto out_of_range;
-	}
-	VALUE str = rb_enc_str_new((char *)buf, bytelen, enc);
-	free(buf);
-	return str;
-    }
-
-    rb_raise(rb_eArgError, "encoding `%s' not supported yet",
-	    RSTRING_PTR(rb_inspect((VALUE)enc)));
-}
-
-static VALUE
-int_numerator(VALUE num, SEL sel)
-{
-    return num;
-}
-
-static VALUE
-int_denominator(VALUE num, SEL sel)
-{
-    return INT2FIX(1);
-}
-
-/*
- *  call-seq:
- *     int.ord  ->  self
- *
- *  Returns the int itself.
- *
- *     ?a.ord    #=> 97
- *
- *  This method is intended for compatibility to
- *  character constant in Ruby 1.9.
- *  For example, ?a.ord returns 97 both in 1.8 and 1.9.
- */
-
-static VALUE
-int_ord(VALUE num, SEL sel)
-{
-    return num;
-}
-
-/********************************************************************
- *
- * Document-class: Fixnum
- *
- *  A <code>Fixnum</code> holds <code>Integer</code> values that can be
- *  represented in a native machine word (minus 2 bits). If any operation
- *  on a <code>Fixnum</code> exceeds this range, the value is
- *  automatically converted to a <code>Bignum</code>.
- *
- *  <code>Fixnum</code> objects have immediate value. This means that
- *  when they are assigned or passed as parameters, the actual object is
- *  passed, rather than a reference to that object. Assignment does not
- *  alias <code>Fixnum</code> objects. There is effectively only one
- *  <code>Fixnum</code> object instance for any given integer value, so,
- *  for example, you cannot add a singleton method to a
- *  <code>Fixnum</code>.
- */
-
-
-/*
- * call-seq:
- *   Fixnum.induced_from(obj)    =>  fixnum
- *
- * Convert <code>obj</code> to a Fixnum. Works with numeric parameters.
- * Also works with Symbols, but this is deprecated.
- */
-
-static VALUE
-rb_fix_induced_from(VALUE klass, SEL sel, VALUE x)
-{
-    return rb_num2fix(x);
-}
-
-/*
- * call-seq:
- *   Integer.induced_from(obj)    =>  fixnum, bignum
- *
- * Convert <code>obj</code> to an Integer.
- */
-
-static VALUE
-rb_int_induced_from(VALUE klass, SEL sel, VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	return x;
-      case T_FLOAT:
-      case T_RATIONAL:
-	return rb_funcall(x, id_to_i, 0);
-      default:
-	rb_raise(rb_eTypeError, "failed to convert %s into Integer",
-		 rb_obj_classname(x));
-    }
-}
-
-/*
- * call-seq:
- *   Float.induced_from(obj)    =>  float
- *
- * Convert <code>obj</code> to a float.
- */
-
-static VALUE
-rb_flo_induced_from(VALUE klass, SEL sel, VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-      case T_RATIONAL:
-	return rb_funcall(x, rb_intern("to_f"), 0);
-      case T_FLOAT:
-	return x;
-      default:
-	rb_raise(rb_eTypeError, "failed to convert %s into Float",
-		 rb_obj_classname(x));
-    }
-}
-
-/*
- * call-seq:
- *   -fix   =>  integer
- *
- * Negates <code>fix</code> (which might return a Bignum).
- */
-
-VALUE
-rb_fix_uminus(VALUE num)
-{
-    return LONG2NUM(-FIX2LONG(num));
-}
-
-
-static VALUE
-fix_uminus(VALUE num, SEL sel)
-{
-    return rb_fix_uminus(num);
-}
-
-VALUE
-rb_fix2str(VALUE x, int base)
-{
-    extern const char ruby_digitmap[];
-    char buf[SIZEOF_VALUE*CHAR_BIT + 2], *b = buf + sizeof buf;
-    long val = FIX2LONG(x);
-    int neg = 0;
-
-    if (base < 2 || 36 < base) {
-	rb_raise(rb_eArgError, "invalid radix %d", base);
-    }
-    if (val == 0) {
-	return rb_usascii_str_new2("0");
-    }
-    if (val < 0) {
-	val = -val;
-	neg = 1;
-    }
-    *--b = '\0';
-    do {
-	*--b = ruby_digitmap[(int)(val % base)];
-    } while (val /= base);
-    if (neg) {
-	*--b = '-';
-    }
-
-    return rb_usascii_str_new2(b);
-}
-
-/*
- *  call-seq:
- *     fix.to_s( base=10 ) -> aString
- *
- *  Returns a string containing the representation of <i>fix</i> radix
- *  <i>base</i> (between 2 and 36).
- *
- *     12345.to_s       #=> "12345"
- *     12345.to_s(2)    #=> "11000000111001"
- *     12345.to_s(8)    #=> "30071"
- *     12345.to_s(10)   #=> "12345"
- *     12345.to_s(16)   #=> "3039"
- *     12345.to_s(36)   #=> "9ix"
- *
- */
-static VALUE
-fix_to_s(VALUE x, SEL sel, int argc, VALUE *argv)
-{
-    int base;
-
-    if (argc == 0) base = 10;
-    else {
-	VALUE b;
-
-	rb_scan_args(argc, argv, "01", &b);
-	base = NUM2INT(b);
-    }
-
-    return rb_fix2str(x, base);
-}
-
-/*
- * call-seq:
- *   fix + numeric   =>  numeric_result
- *
- * Performs addition: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-VALUE
-rb_fix_plus(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	long a, b, c;
-	VALUE r;
-
-	a = FIX2LONG(x);
-	b = FIX2LONG(y);
-	c = a + b;
-	r = LONG2NUM(c);
-
-	return r;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return rb_big_plus(y, x);
-      case T_FLOAT:
-	return DOUBLE2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selPLUS);
-    }
-}
-
-static VALUE
-fix_plus(VALUE x, SEL sel, VALUE y)
-{
-    return rb_fix_plus(x, y);
-}
-
-/*
- * call-seq:
- *   fix - numeric   =>  numeric_result
- *
- * Performs subtraction: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-VALUE
-rb_fix_minus(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	long a, b, c;
-	VALUE r;
-
-	a = FIX2LONG(x);
-	b = FIX2LONG(y);
-	c = a - b;
-	r = LONG2NUM(c);
-
-	return r;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	x = rb_int2big(FIX2LONG(x));
-	return rb_big_minus(x, y);
-      case T_FLOAT:
-	return DOUBLE2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMINUS);
-    }
-}
-
-static VALUE
-fix_minus(VALUE x, SEL sel, VALUE y)
-{
-    return rb_fix_minus(x, y);
-}
-
-#define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
-/*tests if N*N would overflow*/
-#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
-
-/*
- * call-seq:
- *   fix * numeric   =>  numeric_result
- *
- * Performs multiplication: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-VALUE
-rb_fix_mul(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-#ifdef __HP_cc
-/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
-	volatile
-#endif
-	SIGNED_VALUE a, b;
-#if SIZEOF_VALUE * 2 <= SIZEOF_LONG_LONG
-	LONG_LONG d;
-#else
-	SIGNED_VALUE c;
-	VALUE r;
-#endif
-
-	a = FIX2LONG(x);
-	b = FIX2LONG(y);
-
-#if SIZEOF_VALUE * 2 <= SIZEOF_LONG_LONG
-	d = (LONG_LONG)a * b;
-	if (FIXABLE(d)) return LONG2FIX(d);
-	return rb_ll2inum(d);
-#else
-	if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
-	    return LONG2FIX(a*b);
-	c = a * b;
-	r = LONG2FIX(c);
-
-	if (a == 0) return x;
-	if (FIX2LONG(r) != c || c/a != b) {
-	    r = rb_big_mul(rb_int2big(a), rb_int2big(b));
-	}
-	return r;
-#endif
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return rb_big_mul(y, x);
-      case T_FLOAT:
-	return DOUBLE2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMULT);
-    }
-}
-
-static VALUE
-fix_mul(VALUE x, SEL sel, VALUE y)
-{
-    return rb_fix_mul(x, y);
-}
-
-static void
-fixdivmod(long x, long y, long *divp, long *modp)
-{
-    long div, mod;
-
-    if (y == 0) {
-	rb_num_zerodiv();
-    }
-    if (y < 0) {
-	if (x < 0)
-	    div = -x / -y;
-	else
-	    div = - (x / -y);
-    }
-    else {
-	if (x < 0)
-	    div = - (-x / y);
-	else
-	    div = x / y;
-    }
-    mod = x - div*y;
-    if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
-	mod += y;
-	div -= 1;
-    }
-    if (divp) *divp = div;
-    if (modp) *modp = mod;
-}
-
-/*
- *  call-seq:
- *     fix.fdiv(numeric)   => float
- *
- *  Returns the floating point result of dividing <i>fix</i> by
- *  <i>numeric</i>.
- *
- *     654321.fdiv(13731)      #=> 47.6528293642124
- *     654321.fdiv(13731.24)   #=> 47.6519964693647
- *
- */
-
-static VALUE
-fix_fdiv(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	return DOUBLE2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return DOUBLE2NUM((double)FIX2LONG(x) / rb_big2dbl(y));
-      case T_FLOAT:
-	return DOUBLE2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
-      default:
-	return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
-    }
-}
-
-static VALUE
-fix_divide(VALUE x, VALUE y, SEL op)
-{
-    if (FIXNUM_P(y)) {
-	long div;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
-	return LONG2NUM(div);
-    }
-    switch (TYPE(y)) {
-	case T_BIGNUM:
-	    x = rb_int2big(FIX2LONG(x));
-	    return rb_big_div(x, y);
-	case T_FLOAT:
-	    {
-		double div;
-
-		if (op == selDIV) {
-		    div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
-		    return DOUBLE2NUM(div);
-		}
-		else {
-		    if (RFLOAT_VALUE(y) == 0) {
-			rb_num_zerodiv();
-		    }
-		    div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
-		    return rb_dbl2big(floor(div));
-		}
-	    }
-	default:
-	    return rb_objc_num_coerce_bin(x, y, op);
-    }
-}
-
-/*
- * call-seq:
- *   fix / numeric      =>  numeric_result
- *
- * Performs division: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-static VALUE
-fix_div(VALUE x, SEL sel, VALUE y)
-{
-    return fix_divide(x, y, selDIV);
-}
-
-VALUE
-rb_fix_div(VALUE x, VALUE y)
-{
-    return fix_divide(x, y, selDIV);
-}
-
-/*
- * call-seq:
- *   fix.div(numeric)   =>  numeric_result
- *
- * Performs integer division: returns integer value.
- */
-
-static VALUE
-fix_idiv(VALUE x, SEL sel, VALUE y)
-{
-    return fix_divide(x, y, selDiv);
-}
-
-/*
- *  call-seq:
- *    fix % other         => Numeric
- *    fix.modulo(other)   => Numeric
- *
- *  Returns <code>fix</code> modulo <code>other</code>.
- *  See <code>Numeric.divmod</code> for more information.
- */
-
-static VALUE
-fix_mod(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	long mod;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
-	return LONG2NUM(mod);
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	x = rb_int2big(FIX2LONG(x));
-	return rb_big_modulo(x, y);
-      case T_FLOAT:
-	{
-	    double mod;
-
-	    flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), 0, &mod);
-	    return DOUBLE2NUM(mod);
-	}
-      default:
-	return rb_objc_num_coerce_bin(x, y, selMOD);
-    }
-}
-
-/*
- *  call-seq:
- *     fix.divmod(numeric)    => array
- *
- *  See <code>Numeric#divmod</code>.
- */
-static VALUE
-fix_divmod(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	long div, mod;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
-
-	return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	x = rb_int2big(FIX2LONG(x));
-	return rb_big_divmod(x, y);
-      case T_FLOAT:
-	{
-	    double div, mod;
-	    volatile VALUE a, b;
-
-	    flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
-	    a = dbl2ival(div);
-	    b = DOUBLE2NUM(mod);
-	    return rb_assoc_new(a, b);
-	}
-      default:
-	return rb_objc_num_coerce_bin(x, y, selDivmod);
-    }
-}
-
-static VALUE
-int_pow(long x, unsigned long y)
-{
-    int neg = x < 0;
-    long z = 1;
-
-    if (neg) x = -x;
-    if (y & 1)
-	z = x;
-    else
-	neg = 0;
-    y &= ~1;
-    do {
-	while (y % 2 == 0) {
-	    if (!FIT_SQRT_LONG(x)) {
-		VALUE v;
-	      bignum:
-		v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
-		if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
-		return v;
-	    }
-	    x = x * x;
-	    y >>= 1;
-	}
-	{
-	    long xz = x * z;
-	    if (!POSFIXABLE(xz) || xz / x != z) {
-		goto bignum;
-	    }
-	    z = xz;
-	}
-    } while (--y);
-    if (neg) z = -z;
-    return LONG2NUM(z);
-}
-
-/*
- *  call-seq:
- *    fix ** other         => Numeric
- *
- *  Raises <code>fix</code> to the <code>other</code> power, which may
- *  be negative or fractional.
- *
- *    2 ** 3      #=> 8
- *    2 ** -1     #=> 0.5
- *    2 ** 0.5    #=> 1.4142135623731
- */
-
-static VALUE
-fix_pow(VALUE x, SEL sel, VALUE y)
-{
-    static const double zero = 0.0;
-    long a = FIX2LONG(x);
-
-    if (FIXNUM_P(y)) {
-	long b = FIX2LONG(y);
-
-	if (b < 0) {
-	  return rb_vm_call(rb_rational_raw1(x), selExp, 1, &y);
-	}
-
-	if (b == 0) {
-	    return INT2FIX(1);
-	}
-	if (b == 1) {
-	    return x;
-	}
-	if (a == 0) {
-	    if (b > 0) {
-		return INT2FIX(0);
-	    }
-	    return DOUBLE2NUM(1.0 / zero);
-	}
-	if (a == 1) {
-	    return INT2FIX(1);
-	}
-	if (a == -1) {
-	    if (b % 2 == 0) {
-		return INT2FIX(1);
-	    }
-	    else {
-		return INT2FIX(-1);
-	    }
-	}
-	return int_pow(a, b);
-    }
-    VALUE zerov = INT2FIX(0);
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	  if (rb_vm_call(y, selLT, 1, &zerov)) {
-	      return rb_vm_call(rb_rational_raw1(x), selExp, 1, &y);
-	  }
-	  if (a == 0) {
-	      return INT2FIX(0);
-	  }
-	  if (a == 1) {
-	      return INT2FIX(1);
-	  }
-	  if (a == -1) {
-	      if (int_even_p(y, 0)) {
-		  return INT2FIX(1);
-	      }
-	      return INT2FIX(-1);
-	  }
-	  x = rb_int2big(FIX2LONG(x));
-	  return rb_big_pow(x, y);
-
-      case T_FLOAT:
-	  if (RFLOAT_VALUE(y) == 0.0) {
-	      return DOUBLE2NUM(1.0);
-	  }
-	  if (a == 0) {
-	      return DOUBLE2NUM(RFLOAT_VALUE(y) < 0 ? (1.0 / zero) : 0.0);
-	  }
-	  if (a == 1) {
-	      return DOUBLE2NUM(1.0);
-	  }
-	  return DOUBLE2NUM(pow((double)a, RFLOAT_VALUE(y)));
-
-      default:
-	  return rb_objc_num_coerce_bin(x, y, selExp);
-    }
-}
-
-/*
- * call-seq:
- *   fix == other
- *
- * Return <code>true</code> if <code>fix</code> equals <code>other</code>
- * numerically.
- *
- *   1 == 2      #=> false
- *   1 == 1.0    #=> true
- */
-
-static VALUE
-fix_equal(VALUE x, SEL sel, VALUE y)
-{
-    if (x == y) return Qtrue;
-    if (FIXNUM_P(y)) return Qfalse;
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return rb_big_eq(y, x);
-      case T_FLOAT:
-	return (double)FIX2LONG(x) == RFLOAT_VALUE(y) ? Qtrue : Qfalse;
-      default:
-	return num_equal(x, y);
-    }
-}
-
-/*
- *  call-seq:
- *     fix <=> numeric    => -1, 0, +1
- *
- *  Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
- *  less than, equal to, or greater than <i>numeric</i>. This is the
- *  basis for the tests in <code>Comparable</code>.
- */
-
-static VALUE
-fix_cmp(VALUE x, SEL sel, VALUE y)
-{
-    if (x == y) return INT2FIX(0);
-    if (FIXNUM_P(y)) {
-	if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
-	return INT2FIX(-1);
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
-      case T_FLOAT:
-	return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT_VALUE(y));
-      default:
-	return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
-    }
-}
-
-/*
- * call-seq:
- *   fix > other     => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * greater than that of <code>other</code>.
- */
-
-static VALUE
-fix_gt(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
-	return Qfalse;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
-      case T_FLOAT:
-	return (double)FIX2LONG(x) > RFLOAT_VALUE(y) ? Qtrue : Qfalse;
-      default:
-	return rb_objc_num_coerce_relop(x, y, selGT);
-    }
-}
-
-/*
- * call-seq:
- *   fix >= other     => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * greater than or equal to that of <code>other</code>.
- */
-
-static VALUE
-fix_ge(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
-	return Qfalse;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
-      case T_FLOAT:
-	return (double)FIX2LONG(x) >= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
-      default:
-	return rb_objc_num_coerce_relop(x, y, selGE);
-    }
-}
-
-/*
- * call-seq:
- *   fix < other     => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * less than that of <code>other</code>.
- */
-
-static VALUE
-fix_lt(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
-	return Qfalse;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
-      case T_FLOAT:
-	return (double)FIX2LONG(x) < RFLOAT_VALUE(y) ? Qtrue : Qfalse;
-      default:
-	return rb_objc_num_coerce_relop(x, y, selLT);
-    }
-}
-
-/*
- * call-seq:
- *   fix <= other     => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * less than or equal to that of <code>other</code>.
- */
-
-static VALUE
-fix_le(VALUE x, SEL sel, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
-	return Qfalse;
-    }
-    switch (TYPE(y)) {
-      case T_BIGNUM:
-	return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
-      case T_FLOAT:
-	return (double)FIX2LONG(x) <= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
-      default:
-	return rb_objc_num_coerce_relop(x, y, selLE);
-    }
-}
-
-/*
- * call-seq:
- *   ~fix     => integer
- *
- * One's complement: returns a number where each bit is flipped.
- */
-
-static VALUE
-fix_rev(VALUE num, SEL sel)
-{
-    long val = FIX2LONG(num);
-
-    val = ~val;
-    return LONG2NUM(val);
-}
-
-static VALUE
-bit_coerce(VALUE x)
-{
-    while (!FIXNUM_P(x) && TYPE(x) != T_BIGNUM) {
-	if (TYPE(x) == T_FLOAT) {
-	    rb_raise(rb_eTypeError, "can't convert Float into Integer");
-	}
-	x = rb_to_int(x);
-    }
-    return x;
-}
-
-/*
- * call-seq:
- *   fix & other     => integer
- *
- * Bitwise AND.
- */
-
-static VALUE
-fix_and(VALUE x, SEL sel, VALUE y)
-{
-    long val;
-
-    if (!FIXNUM_P(y = bit_coerce(y))) {
-	return rb_big_and(y, x);
-    }
-    val = FIX2LONG(x) & FIX2LONG(y);
-    return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- *   fix | other     => integer
- *
- * Bitwise OR.
- */
-
-static VALUE
-fix_or(VALUE x, SEL sel, VALUE y)
-{
-    long val;
-
-    if (!FIXNUM_P(y = bit_coerce(y))) {
-	return rb_big_or(y, x);
-    }
-    val = FIX2LONG(x) | FIX2LONG(y);
-    return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- *   fix ^ other     => integer
- *
- * Bitwise EXCLUSIVE OR.
- */
-
-static VALUE
-fix_xor(VALUE x, SEL sel, VALUE y)
-{
-    long val;
-
-    if (!FIXNUM_P(y = bit_coerce(y))) {
-	return rb_big_xor(y, x);
-    }
-    val = FIX2LONG(x) ^ FIX2LONG(y);
-    return LONG2NUM(val);
-}
-
-static VALUE fix_lshift(long, unsigned long);
-static VALUE fix_rshift(long, unsigned long);
-
-/*
- * call-seq:
- *   fix << count     => integer
- *
- * Shifts _fix_ left _count_ positions (right if _count_ is negative).
- */
-
-static VALUE
-rb_fix_lshift(VALUE x, SEL sel, VALUE y)
-{
-    long val, width;
-
-    val = NUM2LONG(x);
-    if (!FIXNUM_P(y))
-	return rb_big_lshift(rb_int2big(val), y);
-    width = FIX2LONG(y);
-    if (width < 0)
-	return fix_rshift(val, (unsigned long)-width);
-    return fix_lshift(val, width);
-}
-
-static VALUE
-fix_lshift(long val, unsigned long width)
-{
-    if (width > (SIZEOF_LONG*CHAR_BIT-1)
-	|| ((unsigned long)val)>>(SIZEOF_LONG*CHAR_BIT-1-width) > 0) {
-	return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
-    }
-    val = val << width;
-    return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- *   fix >> count     => integer
- *
- * Shifts _fix_ right _count_ positions (left if _count_ is negative).
- */
-
-static VALUE
-rb_fix_rshift(VALUE x, SEL sel, VALUE y)
-{
-    long i, val;
-
-    val = FIX2LONG(x);
-    if (!FIXNUM_P(y))
-	return rb_big_rshift(rb_int2big(val), y);
-    i = FIX2LONG(y);
-    if (i == 0) return x;
-    if (i < 0)
-	return fix_lshift(val, (unsigned long)-i);
-    return fix_rshift(val, i);
-}
-
-static VALUE
-fix_rshift(long val, unsigned long i)
-{
-    if (i >= sizeof(long)*CHAR_BIT-1) {
-	if (val < 0) return INT2FIX(-1);
-	return INT2FIX(0);
-    }
-    val = RSHIFT(val, i);
-    return LONG2FIX(val);
-}
-
-/*
- *  call-seq:
- *     fix[n]     => 0, 1
- *
- *  Bit Reference---Returns the <em>n</em>th bit in the binary
- *  representation of <i>fix</i>, where <i>fix</i>[0] is the least
- *  significant bit.
- *
- *     a = 0b11001100101010
- *     30.downto(0) do |n| print a[n] end
- *
- *  <em>produces:</em>
- *
- *     0000000000000000011001100101010
- */
-
-static VALUE
-fix_aref(VALUE fix, SEL sel, VALUE idx)
-{
-    long val = FIX2LONG(fix);
-    long i;
-
-    idx = rb_to_int(idx);
-    if (!FIXNUM_P(idx)) {
-	idx = rb_big_norm(idx);
-	if (!FIXNUM_P(idx)) {
-	    if (!RBIGNUM_SIGN(idx) || val >= 0)
-		return INT2FIX(0);
-	    return INT2FIX(1);
-	}
-    }
-    i = FIX2LONG(idx);
-
-    if (i < 0) return INT2FIX(0);
-    if (SIZEOF_LONG*CHAR_BIT-1 < i) {
-	if (val < 0) return INT2FIX(1);
-	return INT2FIX(0);
-    }
-    if (val & (1L<<i))
-	return INT2FIX(1);
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     fix.to_f -> float
- *
- *  Converts <i>fix</i> to a <code>Float</code>.
- *
- */
-
-static VALUE
-fix_to_f(VALUE num, SEL sel)
-{
-    double val;
-
-    val = (double)FIX2LONG(num);
-
-    return DOUBLE2NUM(val);
-}
-
-/*
- *  call-seq:
- *     fix.abs -> aFixnum
- *
- *  Returns the absolute value of <i>fix</i>.
- *
- *     -12345.abs   #=> 12345
- *     12345.abs    #=> 12345
- *
- */
-
-static VALUE
-fix_abs(VALUE fix, SEL sel)
-{
-    long i = FIX2LONG(fix);
-
-    if (i < 0) i = -i;
-
-    return LONG2NUM(i);
-}
-
-
-
-/*
- *  call-seq:
- *     fix.size -> fixnum
- *
- *  Returns the number of <em>bytes</em> in the machine representation
- *  of a <code>Fixnum</code>.
- *
- *     1.size            #=> 4
- *     -1.size           #=> 4
- *     2147483647.size   #=> 4
- */
-
-static VALUE
-fix_size(VALUE fix, SEL sel)
-{
-    return INT2FIX(sizeof(long));
-}
-
-/*
- *  call-seq:
- *     int.upto(limit) {|i| block }     => int
- *
- *  Iterates <em>block</em>, passing in integer values from <i>int</i>
- *  up to and including <i>limit</i>.
- *
- *     5.upto(10) { |i| print i, " " }
- *
- *  <em>produces:</em>
- *
- *     5 6 7 8 9 10
- */
-
-static VALUE
-int_upto(VALUE from, SEL sel, VALUE to)
-{
-    RETURN_ENUMERATOR(from, 1, &to);
-    if (FIXNUM_P(from) && FIXNUM_P(to)) {
-	long i, end;
-
-	end = FIX2LONG(to);
-	for (i = FIX2LONG(from); i <= end; i++) {
-	    rb_yield(LONG2FIX(i));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {
-	VALUE i = from, c;
-
-	while (!(c = rb_vm_call(i, selGT, 1, &to))) {
-	    rb_yield(i);
-	    RETURN_IF_BROKEN();
-	    VALUE one = INT2FIX(1);
-	    i = rb_vm_call(i, selPLUS, 1, &one);
-	}
-	if (NIL_P(c)) rb_cmperr(i, to);
-    }
-    return from;
-}
-
-/*
- *  call-seq:
- *     int.downto(limit) {|i| block }     => int
- *
- *  Iterates <em>block</em>, passing decreasing values from <i>int</i>
- *  down to and including <i>limit</i>.
- *
- *     5.downto(1) { |n| print n, ".. " }
- *     print "  Liftoff!\n"
- *
- *  <em>produces:</em>
- *
- *     5.. 4.. 3.. 2.. 1..   Liftoff!
- */
-
-static VALUE
-int_downto(VALUE from, SEL sel, VALUE to)
-{
-    RETURN_ENUMERATOR(from, 1, &to);
-    if (FIXNUM_P(from) && FIXNUM_P(to)) {
-	long i, end;
-
-	end = FIX2LONG(to);
-	for (i=FIX2LONG(from); i >= end; i--) {
-	    rb_yield(LONG2FIX(i));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {
-	VALUE i = from, c;
-
-	while (!(c = rb_vm_call(i, selLT, 1, &to))) {
-	    rb_yield(i);
-	    RETURN_IF_BROKEN();
-	    VALUE one = INT2FIX(1);
-	    i = rb_vm_call(i, selMINUS, 1, &one);
-	}
-	if (NIL_P(c)) rb_cmperr(i, to);
-    }
-    return from;
-}
-
-/*
- *  call-seq:
- *     int.times {|i| block }     => int
- *
- *  Iterates block <i>int</i> times, passing in values from zero to
- *  <i>int</i> - 1.
- *
- *     5.times do |i|
- *       print i, " "
- *     end
- *
- *  <em>produces:</em>
- *
- *     0 1 2 3 4
- */
-
-static VALUE
-int_dotimes(VALUE num, SEL sel)
-{
-    RETURN_ENUMERATOR(num, 0, 0);
-
-    if (FIXNUM_P(num)) {
-	long i, end;
-
-	end = FIX2LONG(num);
-	for (i=0; i<end; i++) {
-	    rb_yield(LONG2FIX(i));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else {
-	VALUE i = INT2FIX(0);
-
-	for (;;) {
-	    if (!RTEST(rb_vm_call(i, selLT, 1, &num))) {
-		break;
-	    }
-	    rb_yield(i);
-	    RETURN_IF_BROKEN();
-	    VALUE one = INT2FIX(1);
-	    i = rb_vm_call(i, selPLUS, 1, &one);
-	}
-    }
-    return num;
-}
-
-static VALUE
-int_round(VALUE num, SEL sel, int argc, VALUE* argv)
-{
-    VALUE n, f, h, r;
-    int ndigits;
-
-    if (argc == 0) return num;
-    rb_scan_args(argc, argv, "1", &n);
-    ndigits = NUM2INT(n);
-    if (ndigits > 0) {
-	return rb_Float(num);
-    }
-    if (ndigits == 0) {
-	return num;
-    }
-    ndigits = -ndigits;
-    if (ndigits < 0) {
-	rb_raise(rb_eArgError, "ndigits out of range");
-    }
-    f = int_pow(10, ndigits);
-    if (FIXNUM_P(num) && FIXNUM_P(f)) {
-	SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
-	int neg = x < 0;
-	if (neg) x = -x;
-	x = (x + y / 2) / y * y;
-	if (neg) x = -x;
-	return LONG2NUM(x);
-    }
-    VALUE two = INT2FIX(2);
-    h = rb_vm_call(f, selDIV, 1, &two);
-    r = rb_vm_call(num, selMOD, 1, &f);
-    n = rb_vm_call(num, selMINUS, 1, &r);
-    if (!RTEST(rb_vm_call(r, selLT, 1, &h))) {
-	n = rb_vm_call(n, selPLUS, 1, &f);
-    }
-    return n;
-}
-
-/*
- *  call-seq:
- *     fix.zero?    => true or false
- *
- *  Returns <code>true</code> if <i>fix</i> is zero.
- *
- */
-
-static VALUE
-fix_zero_p(VALUE num, SEL sel)
-{
-    if (FIX2LONG(num) == 0) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     fix.popcnt    => Fixnum
- *
- *  Returns the number of 1 bits set in the internal representation of 
- *  <i>fix</i>. This function returns consistent results across platforms for 
- *  positive numbers, but may vary for negative numbers.
- *
- */
-
-static VALUE
-fix_popcnt(VALUE num, SEL sel)
-{
-    return INT2FIX(__builtin_popcountl(FIX2ULONG(num)));
-}
-
-/*
- *  call-seq:
- *     fix.odd? -> true or false
- *
- *  Returns <code>true</code> if <i>fix</i> is an odd number.
- */
-
-static VALUE
-fix_odd_p(VALUE num, SEL sel)
-{
-    if (FIX2LONG(num) & 1) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     fix.even? -> true or false
- *
- *  Returns <code>true</code> if <i>fix</i> is an even number.
- */
-
-static VALUE
-fix_even_p(VALUE num, SEL sel)
-{
-    if (FIX2LONG(num) & 1) {
-	return Qfalse;
-    }
-    return Qtrue;
-}
-
-static void *
-imp_nsnumber_to_int(void *rcv, SEL sel)
-{
-    // This is because some NSNumber subclasses must be converted to real
-    // CFNumber objects, in order to be coerced into Fixnum objects.
-    long val = 0;
-    if (!CFNumberGetValue((CFNumberRef)rcv, kCFNumberLongType, &val)) {
-	rb_raise(rb_eTypeError, "cannot get 'long' value out of NSNumber %p",
-		rcv);
-    }
-    CFNumberRef new_num = CFNumberCreate(NULL, kCFNumberLongType, &val);
-    CFMakeCollectable(new_num);
-    return (void *)new_num;
-}
-
-void
-Init_Numeric(void)
-{
-    rb_cNSNumber = (VALUE)objc_getClass("NSNumber");
-    assert(rb_cNSNumber != 0);
-
-    sel_coerce = sel_registerName("coerce:");
-    selDiv = sel_registerName("div:");
-    selDivmod = sel_registerName("divmod:");
-    selExp = sel_registerName("**:");
-
-    id_to_i = rb_intern("to_i");
-    id_eq = rb_intern("==");
-
-    rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
-    rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
-    rb_cNumeric = rb_define_class("Numeric", rb_cNSNumber);
-    RCLASS_SET_VERSION_FLAG(rb_cNumeric, RCLASS_IS_OBJECT_SUBCLASS);
-    rb_define_object_special_methods(rb_cNumeric);
-
-    // Override NSObject methods.
-    rb_objc_define_method(rb_cNumeric, "class", rb_obj_class, 0);
-    rb_objc_define_method(rb_cNumeric, "dup", rb_obj_dup, 0);
-
-    // Undefine methods defined on NSNumber.
-    rb_undef_method(rb_cNumeric, "to_i");
-    rb_undef_method(rb_cNumeric, "to_f");
-
-    rb_objc_define_method(rb_cNumeric, "singleton_method_added", num_sadded, 1);
-    rb_include_module(rb_cNumeric, rb_mComparable);
-    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);
-    rb_objc_define_method(rb_cNumeric, "eql?", num_eql, 1);
-    rb_objc_define_method(rb_cNumeric, "quo", num_quo, 1);
-    rb_objc_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
-    rb_objc_define_method(rb_cNumeric, "div", num_div, 1);
-    rb_objc_define_method(rb_cNumeric, "divmod", num_divmod, 1);
-    rb_objc_define_method(rb_cNumeric, "%", num_modulo, 1);
-    rb_objc_define_method(rb_cNumeric, "modulo", num_modulo, 1);
-    rb_objc_define_method(rb_cNumeric, "remainder", num_remainder, 1);
-    rb_objc_define_method(rb_cNumeric, "abs", num_abs, 0);
-    rb_objc_define_method(rb_cNumeric, "magnitude", num_abs, 0);
-    rb_objc_define_method(rb_cNumeric, "to_int", num_to_int, 0);
-    
-    rb_objc_define_method(rb_cNumeric, "real?", num_real_p, 0);
-    rb_objc_define_method(rb_cNumeric, "scalar?", num_scalar_p, 0);
-    rb_objc_define_method(rb_cNumeric, "integer?", num_int_p, 0);
-    rb_objc_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
-    rb_objc_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
-
-    rb_objc_define_method(rb_cNumeric, "floor", num_floor, 0);
-    rb_objc_define_method(rb_cNumeric, "ceil", num_ceil, 0);
-    rb_objc_define_method(rb_cNumeric, "round", num_round, -1);
-    rb_objc_define_method(rb_cNumeric, "truncate", num_truncate, 0);
-    rb_objc_define_method(rb_cNumeric, "step", num_step, -1);
-
-    rb_objc_define_method(rb_cNumeric, "numerator", num_numerator, 0);
-    rb_objc_define_method(rb_cNumeric, "denominator", num_denominator, 0);
-
-    rb_cInteger = rb_define_class("Integer", rb_cNumeric);
-    rb_undef_alloc_func(rb_cInteger);
-    rb_undef_method(CLASS_OF(rb_cInteger), "new");
-
-    rb_objc_define_method(rb_cInteger, "integer?", int_int_p, 0);
-    rb_objc_define_method(rb_cInteger, "odd?", int_odd_p, 0);
-    rb_objc_define_method(rb_cInteger, "even?", int_even_p, 0);
-    rb_objc_define_method(rb_cInteger, "upto", int_upto, 1);
-    rb_objc_define_method(rb_cInteger, "downto", int_downto, 1);
-    rb_objc_define_method(rb_cInteger, "times", int_dotimes, 0);
-    rb_include_module(rb_cInteger, rb_mPrecision);
-    rb_objc_define_method(rb_cInteger, "succ", int_succ, 0);
-    rb_objc_define_method(rb_cInteger, "next", int_succ, 0);
-    rb_objc_define_method(rb_cInteger, "pred", int_pred, 0);
-    rb_objc_define_method(rb_cInteger, "chr", int_chr, -1);
-    rb_objc_define_method(rb_cInteger, "ord", int_ord, 0);
-    rb_objc_define_method(rb_cInteger, "to_i", int_to_i, 0);
-    rb_objc_define_method(rb_cInteger, "to_int", int_to_i, 0);
-    rb_objc_define_method(rb_cInteger, "floor", int_to_i, 0);
-    rb_objc_define_method(rb_cInteger, "ceil", int_to_i, 0);
-    rb_objc_define_method(rb_cInteger, "truncate", int_to_i, 0);
-    rb_objc_define_method(rb_cInteger, "round", int_round, -1);
-
-    rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
-    rb_include_module(rb_cFixnum, rb_mPrecision);
-    rb_objc_define_method(*(VALUE *)rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
-    rb_objc_define_method(*(VALUE *)rb_cInteger, "induced_from", rb_int_induced_from, 1);
-
-    rb_objc_define_method(rb_cInteger, "numerator", int_numerator, 0);
-    rb_objc_define_method(rb_cInteger, "denominator", int_denominator, 0);
-
-    rb_objc_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
-
-    rb_objc_define_method(rb_cFixnum, "-@", fix_uminus, 0);
-    rb_objc_define_method(rb_cFixnum, "+", fix_plus, 1);
-    rb_objc_define_method(rb_cFixnum, "-", fix_minus, 1);
-    rb_objc_define_method(rb_cFixnum, "*", fix_mul, 1);
-    rb_objc_define_method(rb_cFixnum, "/", fix_div, 1);
-    rb_objc_define_method(rb_cFixnum, "div", fix_idiv, 1);
-    rb_objc_define_method(rb_cFixnum, "%", fix_mod, 1);
-    rb_objc_define_method(rb_cFixnum, "modulo", fix_mod, 1);
-    rb_objc_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
-    rb_objc_define_method(rb_cFixnum, "fdiv", fix_fdiv, 1);
-    rb_objc_define_method(rb_cFixnum, "**", fix_pow, 1);
-
-    rb_objc_define_method(rb_cFixnum, "abs", fix_abs, 0);
-    rb_objc_define_method(rb_cFixnum, "magnitude", fix_abs, 0);
-
-    rb_objc_define_method(rb_cFixnum, "==", fix_equal, 1);
-    rb_objc_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
-    rb_objc_define_method(rb_cFixnum, ">",  fix_gt, 1);
-    rb_objc_define_method(rb_cFixnum, ">=", fix_ge, 1);
-    rb_objc_define_method(rb_cFixnum, "<",  fix_lt, 1);
-    rb_objc_define_method(rb_cFixnum, "<=", fix_le, 1);
-
-    rb_objc_define_method(rb_cFixnum, "~", fix_rev, 0);
-    rb_objc_define_method(rb_cFixnum, "&", fix_and, 1);
-    rb_objc_define_method(rb_cFixnum, "|", fix_or,  1);
-    rb_objc_define_method(rb_cFixnum, "^", fix_xor, 1);
-    rb_objc_define_method(rb_cFixnum, "[]", fix_aref, 1);
-
-    rb_objc_define_method(rb_cFixnum, "<<", rb_fix_lshift, 1);
-    rb_objc_define_method(rb_cFixnum, ">>", rb_fix_rshift, 1);
-
-    rb_objc_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
-    rb_objc_define_method(rb_cFixnum, "size", fix_size, 0);
-    rb_objc_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
-    rb_objc_define_method(rb_cFixnum, "odd?", fix_odd_p, 0);
-    rb_objc_define_method(rb_cFixnum, "even?", fix_even_p, 0);
-    rb_objc_define_method(rb_cFixnum, "succ", fix_succ, 0);
-    rb_objc_define_method(rb_cFixnum, "popcnt", fix_popcnt, 0);
-
-    rb_cFloat  = rb_define_class("Float", rb_cNumeric);
-
-    rb_undef_alloc_func(rb_cFloat);
-    rb_undef_method(CLASS_OF(rb_cFloat), "new");
-
-    rb_objc_define_method(*(VALUE *)rb_cFloat, "induced_from", rb_flo_induced_from, 1);
-    rb_include_module(rb_cFloat, rb_mPrecision);
-
-    rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
-    rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
-    rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
-    rb_define_const(rb_cFloat, "DIG", INT2FIX(DBL_DIG));
-    rb_define_const(rb_cFloat, "MIN_EXP", INT2FIX(DBL_MIN_EXP));
-    rb_define_const(rb_cFloat, "MAX_EXP", INT2FIX(DBL_MAX_EXP));
-    rb_define_const(rb_cFloat, "MIN_10_EXP", INT2FIX(DBL_MIN_10_EXP));
-    rb_define_const(rb_cFloat, "MAX_10_EXP", INT2FIX(DBL_MAX_10_EXP));
-    rb_define_const(rb_cFloat, "MIN", DOUBLE2NUM(DBL_MIN));
-    rb_define_const(rb_cFloat, "MAX", DOUBLE2NUM(DBL_MAX));
-    rb_define_const(rb_cFloat, "EPSILON", DOUBLE2NUM(DBL_EPSILON));
-    rb_define_const(rb_cFloat, "INFINITY", DBL2NUM(INFINITY));
-    rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN));
-
-    rb_objc_define_method(rb_cFloat, "to_s", flo_to_s, 0);
-    rb_objc_define_method(rb_cFloat, "coerce", flo_coerce, 1);
-    rb_objc_define_method(rb_cFloat, "-@", flo_uminus, 0);
-    rb_objc_define_method(rb_cFloat, "+", flo_plus, 1);
-    rb_objc_define_method(rb_cFloat, "-", flo_minus, 1);
-    rb_objc_define_method(rb_cFloat, "*", flo_mul, 1);
-    rb_objc_define_method(rb_cFloat, "/", flo_div, 1);
-    rb_objc_define_method(rb_cFloat, "quo", flo_quo, 1);
-    rb_objc_define_method(rb_cFloat, "fdiv", flo_quo, 1);
-    rb_objc_define_method(rb_cFloat, "%", flo_mod, 1);
-    rb_objc_define_method(rb_cFloat, "modulo", flo_mod, 1);
-    rb_objc_define_method(rb_cFloat, "divmod", flo_divmod, 1);
-    rb_objc_define_method(rb_cFloat, "**", flo_pow, 1);
-    rb_objc_define_method(rb_cFloat, "==", flo_eq, 1);
-    rb_objc_define_method(rb_cFloat, "<=>", flo_cmp, 1);
-    rb_objc_define_method(rb_cFloat, ">",  flo_gt, 1);
-    rb_objc_define_method(rb_cFloat, ">=", flo_ge, 1);
-    rb_objc_define_method(rb_cFloat, "<",  flo_lt, 1);
-    rb_objc_define_method(rb_cFloat, "<=", flo_le, 1);
-    rb_objc_define_method(rb_cFloat, "eql?", flo_eql, 1);
-    rb_objc_define_method(rb_cFloat, "hash", flo_hash, 0);
-    rb_objc_define_method(rb_cFloat, "to_f", flo_to_f, 0);
-    rb_objc_define_method(rb_cFloat, "abs", flo_abs, 0);
-    rb_objc_define_method(rb_cFloat, "magnitude", flo_abs, 0);
-    rb_objc_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
-
-    rb_objc_define_method(rb_cFloat, "to_i", flo_truncate, 0);
-    rb_objc_define_method(rb_cFloat, "to_int", flo_truncate, 0);
-    rb_objc_define_method(rb_cFloat, "floor", flo_floor, 0);
-    rb_objc_define_method(rb_cFloat, "ceil", flo_ceil, 0);
-    rb_objc_define_method(rb_cFloat, "round", flo_round, -1);
-    rb_objc_define_method(rb_cFloat, "truncate", flo_truncate, 0);
-
-    rb_objc_define_method(rb_cFloat, "nan?",      flo_is_nan_p, 0);
-    rb_objc_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
-    rb_objc_define_method(rb_cFloat, "finite?",   flo_is_finite_p, 0);
-
-    class_replaceMethod((Class)rb_cNSNumber, sel_registerName("to_int"),
-	    (IMP)imp_nsnumber_to_int, "@@:");
-}

Deleted: MacRuby/trunk/objc.h
===================================================================
--- MacRuby/trunk/objc.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/objc.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,277 +0,0 @@
-/*
- * MacRuby ObjC helpers.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __OBJC_H_
-#define __OBJC_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include "bs.h"
-
-static inline const char *
-rb_get_bs_method_type(bs_element_method_t *bs_method, int arg)
-{
-    if (bs_method != NULL) {
-	if (arg == -1) {
-	    if (bs_method->retval != NULL) {
-		return bs_method->retval->type;
-	    }
-	}
-	else {
-	    unsigned int i;
-	    for (i = 0; i < bs_method->args_count; i++) {
-		if (bs_method->args[i].index == arg) {
-		    return bs_method->args[i].type;
-		}
-	    }
-	}
-    }
-    return NULL;
-}
-
-bool rb_objc_get_types(VALUE recv, Class klass, SEL sel, Method m,
-	bs_element_method_t *bs_method, char *buf, size_t buflen);
-
-bool rb_objc_supports_forwarding(VALUE recv, SEL sel);
-
-void rb_objc_define_kvo_setter(VALUE klass, ID mid);
-
-static inline IMP
-rb_objc_install_method(Class klass, SEL sel, IMP imp)
-{
-    Method method = class_getInstanceMethod(klass, sel);
-    if (method == NULL) {
-	printf("method %s not found on class %p - aborting\n",
-		sel_getName(sel), klass);
-	abort();
-    }
-    IMP old = method_getImplementation(method);
-    class_replaceMethod(klass, sel, imp, method_getTypeEncoding(method));
-    return old;
-}
-
-static inline IMP
-rb_objc_install_method2(Class klass, const char *selname, IMP imp)
-{
-    return rb_objc_install_method(klass, sel_registerName(selname), imp);
-}
-
-static inline bool
-rb_objc_is_kind_of(id object, Class klass)
-{
-    Class cls;
-    for (cls = *(Class *)object; cls != NULL; cls = class_getSuperclass(cls)) {
-	if (cls == klass) {
-	    return true;
-	}
-    }
-    return false;
-}
-
-id rb_rb2oc_exception(VALUE exc);
-VALUE rb_oc2rb_exception(id exc, bool *created);
-
-size_t rb_objc_type_size(const char *type);
-
-static inline int
-SubtypeUntil(const char *type, char end)
-{
-    int level = 0;
-    const char *head = type;
-
-    while (*type)
-    {
-	if (!*type || (!level && (*type == end)))
-	    return (int)(type - head);
-
-	switch (*type)
-	{
-	    case ']': case '}': case ')': case '>': level--; break;
-	    case '[': case '{': case '(': case '<': level += 1; break;
-	}
-
-	type += 1;
-    }
-
-    rb_bug ("Object: SubtypeUntil: end of type encountered prematurely\n");
-    return 0;
-}
-
-static inline const char *
-SkipStackSize(const char *type)
-{
-    while ((*type >= '0') && (*type <= '9')) {
-	type += 1;
-    }
-    return type;
-}
-
-static inline const char *
-SkipTypeModifiers(const char *type)
-{
-    while (true) {
-	switch (*type) {
-	    case _C_CONST:
-	    case 'O': /* bycopy */
-	    case 'n': /* in */
-	    case 'o': /* out */
-	    case 'N': /* inout */
-	    case 'V': /* oneway */
-		type++;
-		break;
-
-	    default:
-		return type;
-	}
-    }
-}
-
-static inline const char *
-SkipFirstType(const char *type)
-{
-    while (1) {
-        switch (*type++) {
-	    case _C_CONST:
-	    case _C_PTR:
-            case 'O':   /* bycopy */
-            case 'n':   /* in */
-            case 'o':   /* out */
-            case 'N':   /* inout */
-            case 'V':   /* oneway */
-                break;
-
-	    case _C_ID:
-		if (*type == _C_UNDEF) {
-		    type++;  /* Blocks */
-		}
-		return type;
-
-                /* arrays */
-            case _C_ARY_B:
-                return type + SubtypeUntil (type, _C_ARY_E) + 1;
-
-                /* structures */
-            case _C_STRUCT_B:
-                return type + SubtypeUntil (type, _C_STRUCT_E) + 1;
-
-                /* unions */
-            case _C_UNION_B:
-                return type + SubtypeUntil (type, _C_UNION_E) + 1;
-
-                /* lambdas */
-            case _MR_C_LAMBDA_B:
-                return type + SubtypeUntil (type, _MR_C_LAMBDA_E) + 1;
-
-                /* basic types */
-            default:
-                return type;
-        }
-    }
-}
-
-static inline const char *
-GetFirstType(const char *p, char *buf, size_t buflen)
-{
-    const char *p2 = SkipFirstType(p);
-    const size_t len = p2 - p;
-    assert(len < buflen);
-    strncpy(buf, p, len);
-    buf[len] = '\0';
-    return SkipStackSize(p2);
-}
-
-static inline unsigned int
-TypeArity(const char *type)
-{
-    unsigned int arity = 0;
-    while (*type != '\0') {
-	type = SkipFirstType(type);
-	type = SkipStackSize(type);
-	arity++;
-    }
-    return arity;
-}
-
-// We do not use method_getNumberOfArguments since it's broken on 
-// SnowLeopard for signatures containing Block objects.
-static inline unsigned int
-rb_method_getNumberOfArguments(Method m)
-{
-    const unsigned int arity = TypeArity(method_getTypeEncoding(m));
-    assert(arity >= 2);
-    return arity - 1; // Skip return type.
-}
-
-id rb_objc_numeric2nsnumber(VALUE obj);
-VALUE rb_objc_convert_immediate(id obj);
-
-static inline id
-rb_rval_to_ocid(VALUE obj)
-{
-    if (SPECIAL_CONST_P(obj)) {
-        if (obj == Qtrue) {
-            return (id)kCFBooleanTrue;
-        }
-        if (obj == Qfalse) {
-            return (id)kCFBooleanFalse;
-        }
-        if (obj == Qnil) {
-            return (id)kCFNull;
-        }
-	if (IMMEDIATE_P(obj)) {
-	    return rb_objc_numeric2nsnumber(obj);
-	}
-    }
-    return (id)obj;
-}
-
-static inline VALUE
-rb_ocid_to_rval(id obj)
-{
-    if (obj == (id)kCFBooleanTrue) {
-	return Qtrue;
-    }
-    if (obj == (id)kCFBooleanFalse) {
-	return Qfalse;
-    }
-    if (obj == (id)kCFNull || obj == nil) {
-	return Qnil;
-    }
-    return rb_objc_convert_immediate(obj);
-}
-
-#define RB2OC(obj) (rb_rval_to_ocid((VALUE)obj))
-#define OC2RB(obj) (rb_ocid_to_rval((id)obj))
-
-void rb_objc_exception_raise(const char *name, const char *message);
-
-bool rb_objc_ignored_sel(SEL sel);
-bool rb_objc_isEqual(VALUE x, VALUE y); 
-void rb_objc_force_class_initialize(Class klass);
-void rb_objc_fix_relocatable_load_path(void);
-void rb_objc_load_loaded_frameworks_bridgesupport(void);
-void rb_objc_install_NSObject_special_methods(Class k);
-
-extern bool rb_objc_enable_ivar_set_kvo_notifications;
-
-#if !defined(MACRUBY_STATIC)
-void rb_vm_parse_bs_full_file(const char *path,
-	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
-	void *ctx);
-#endif
-
-#define SINCE_EPOCH 978307200.0
-#define CF_REFERENCE_DATE SINCE_EPOCH
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __OBJC_H_ */

Deleted: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/objc.m	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1003 +0,0 @@
-/*
- * MacRuby ObjC helpers.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- */
-
-#include <Foundation/Foundation.h>
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/encoding.h"
-#include "ruby/objc.h"
-#include "vm.h"
-#include "objc.h"
-#include "id.h"
-#include "class.h"
-
-#include <unistd.h>
-#include <dlfcn.h>
-#include <mach-o/dyld.h>
-#include <sys/mman.h>
-#if HAVE_BRIDGESUPPORT_FRAMEWORK
-# include <BridgeSupport/BridgeSupport.h>
-#else
-# include "bs.h"
-#endif
-
-bool
-rb_objc_get_types(VALUE recv, Class klass, SEL sel, Method method,
-		  bs_element_method_t *bs_method, char *buf, size_t buflen)
-{
-    const char *type;
-    unsigned i;
-
-    memset(buf, 0, buflen);
-
-    if (method != NULL) {
-	if (bs_method == NULL) {
-	    type = method_getTypeEncoding(method);
-	    assert(strlen(type) < buflen);
-	    buf[0] = '\0';
-	    do {
-		const char *type2 = SkipFirstType(type);
-		strncat(buf, type, type2 - type);
-		type = SkipStackSize(type2);
-	    }
-	    while (*type != '\0');
-	}
-	else {
-	    char buf2[100];
-	    type = rb_get_bs_method_type(bs_method, -1);
-	    if (type != NULL) {
-		strlcpy(buf, type, buflen);
-	    }
-	    else {
-		method_getReturnType(method, buf2, sizeof buf2);
-		strlcpy(buf, buf2, buflen);
-	    }
-
-	    const unsigned int argc = rb_method_getNumberOfArguments(method);
-	    for (i = 0; i < argc; i++) {
-		if (i >= 2 && (type = rb_get_bs_method_type(bs_method, i - 2))
-			!= NULL) {
-		    strlcat(buf, type, buflen);
-		}
-		else {
-		    method_getArgumentType(method, i, buf2, sizeof(buf2));
-		    strlcat(buf, buf2, buflen);
-		}
-	    }
-	}
-	return true;
-    }
-    else if (!SPECIAL_CONST_P(recv)) {
-	NSMethodSignature *msig = [(id)recv methodSignatureForSelector:sel];
-	if (msig != NULL) {
-	    unsigned i;
-
-	    type = rb_get_bs_method_type(bs_method, -1);
-	    if (type == NULL) {
-		type = [msig methodReturnType];
-	    }
-	    strlcpy(buf, type, buflen);
-
-	    const int argc = [msig numberOfArguments];
-	    for (i = 0; i < argc; i++) {
-		if (i < 2 || (type = rb_get_bs_method_type(bs_method, i - 2))
-			== NULL) {
-		    type = [msig getArgumentTypeAtIndex:i];
-		}
-		strlcat(buf, type, buflen);
-	    }
-
-	    return true;
-	}
-    }
-    return false;
-}
-
-bool
-rb_objc_supports_forwarding(VALUE recv, SEL sel)
-{
-    if (!SPECIAL_CONST_P(recv)) {
-	return [(id)recv methodSignatureForSelector:sel] != nil;
-    }
-    return false;
-}
-
-static const char *
-fileSystemPath(NSString *str)
-{
-    @try {
-	return [str fileSystemRepresentation];
-    }
-    @catch (id exc) {
-	// Sometimes, -fileSystemRepresentation can fail.
-    }
-    return [str UTF8String];
-}
-
-VALUE
-rb_home_dir(VALUE user_name)
-{
-    NSString *user = nil;
-    NSString *home_dir = nil;
-
-    if (user_name != Qnil) {
-	user = (NSString *)user_name;
-	home_dir = NSHomeDirectoryForUser(user);
-	if (home_dir == nil) {
-	    rb_raise(rb_eArgError, "user %s doesn't exist",
-		[user UTF8String]);
-	}
-    }
-    else {
-	home_dir = NSHomeDirectory();
-	if (home_dir == nil) {
-	    return Qnil;
-	}
-    }
-    return rb_str_new2(fileSystemPath(home_dir));
-}
-
-static bool
-is_absolute_path(NSString *path, bool expand_tilde)
-{
-    if (!expand_tilde && [path isAbsolutePath] && [path hasPrefix:@"~"]) {
-	return false;
-    }
-    return [path isAbsolutePath];    
-}
-
-static VALUE
-file_expand_path(VALUE fname, VALUE dname, bool absolute)
-{
-    NSString *res = (NSString *)FilePathValue(fname);
-
-    if (is_absolute_path(res, !absolute)) {
-	// Resolve symlinks only in absolute mode.
-	NSString *tmp = absolute
-	    ? [res stringByResolvingSymlinksInPath]
-	    : [[res stringByExpandingTildeInPath] stringByStandardizingPath];
-	// Make sure we don't have an invalid user path.
-	if ([res hasPrefix:@"~"] && [tmp isEqualToString:res]) {
-	    NSString *user = [[[res pathComponents] objectAtIndex:0]
-		substringFromIndex:1];
-	    rb_raise(rb_eArgError, "user %s doesn't exist", [user UTF8String]);
-	}
-	res = tmp;
-    }
-    else {
-	NSString *dir = dname != Qnil
-	    ? (NSString *)FilePathValue(dname)
-	    : [[NSFileManager defaultManager] currentDirectoryPath];
-
-	if (!is_absolute_path(dir, !absolute)) {
-	    dir = (NSString *)file_expand_path((VALUE)dir, Qnil, 0);
-	}
-
-	// stringByStandardizingPath does not expand "/." to "/".
-	if ([res isEqualToString:@"."] && [dir isEqualToString:@"/"]) {
-	    res = @"/";
-	}
-	else {
-	    res = [[dir stringByAppendingPathComponent:res]
-		stringByStandardizingPath];
-	}
-    }
-
-    return rb_str_new2(fileSystemPath(res));
-}
-
-VALUE
-rb_file_expand_path(VALUE fname, VALUE dname)
-{
-    return file_expand_path(fname, dname, 0);
-}
-
-VALUE
-rb_file_absolute_path(VALUE fname, VALUE dname)
-{
-    return file_expand_path(fname, dname, 1);
-}
-
-static VALUE
-rb_objc_load_bs(VALUE recv, SEL sel, VALUE path)
-{
-#if MACRUBY_STATIC
-    not_implemented_in_static(sel);
-#else
-    rb_vm_load_bridge_support(StringValuePtr(path), NULL, 0);
-    return recv;
-#endif
-}
-
-#if !defined(MACRUBY_STATIC)
-static void
-rb_objc_search_and_load_bridge_support(const char *framework_path)
-{
-    char path[PATH_MAX];
-
-    if (bs_find_path(framework_path, path, sizeof path)) {
-	rb_vm_load_bridge_support(path, framework_path,
-                                    BS_PARSE_OPTIONS_LOAD_DYLIBS);
-    }
-}
-#endif
-
-bool rb_objc_enable_ivar_set_kvo_notifications = false;
-
-VALUE
-rb_require_framework(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-#if MACRUBY_STATIC
-    not_implemented_in_static(sel);
-#else
-    VALUE framework;
-    VALUE search_network;
-    const char *cstr;
-    NSFileManager *fileManager;
-    NSString *path;
-    NSBundle *bundle;
-    NSError *error;
-    
-    rb_scan_args(argc, argv, "11", &framework, &search_network);
-
-    Check_Type(framework, T_STRING);
-    cstr = RSTRING_PTR(framework);
-
-    fileManager = [NSFileManager defaultManager];
-    path = [fileManager stringWithFileSystemRepresentation:cstr
-	length:strlen(cstr)];
-
-    if (![fileManager fileExistsAtPath:path]) {
-	/* framework name is given */
-	NSSearchPathDomainMask pathDomainMask;
-	NSString *frameworkName;
-	NSArray *dirs;
-	NSUInteger i, count;
-
-	cstr = NULL;
-
-#define FIND_LOAD_PATH_IN_LIBRARY(dir) 					  \
-    do { 								  \
-	path = [[dir stringByAppendingPathComponent:@"Frameworks"]	  \
-	   stringByAppendingPathComponent:frameworkName];		  \
-	if ([fileManager fileExistsAtPath:path]) {			  \
-	    goto success; 						  \
-	}								  \
-	path = [[dir stringByAppendingPathComponent:@"PrivateFrameworks"] \
-	   stringByAppendingPathComponent:frameworkName];		  \
-	if ([fileManager fileExistsAtPath:path]) {			  \
-	    goto success; 						  \
-	}								  \
-    } 									  \
-    while (0)
-
-	pathDomainMask = RTEST(search_network)
-	    ? NSAllDomainsMask
-	    : NSUserDomainMask | NSLocalDomainMask | NSSystemDomainMask;
-
-	frameworkName = [path stringByAppendingPathExtension:@"framework"];
-
-	path = [[[[NSBundle mainBundle] bundlePath] 
-	    stringByAppendingPathComponent:@"Contents/Frameworks"] 
-		stringByAppendingPathComponent:frameworkName];
-	if ([fileManager fileExistsAtPath:path]) {
-	    goto success;
-	}
-
-	dirs = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, 
-	    pathDomainMask, YES);
-	for (i = 0, count = [dirs count]; i < count; i++) {
-	    NSString *dir = [dirs objectAtIndex:i];
-	    FIND_LOAD_PATH_IN_LIBRARY(dir);
-	}	
-
-	dirs = NSSearchPathForDirectoriesInDomains(NSDeveloperDirectory, 
-	    pathDomainMask, YES);
-	for (i = 0, count = [dirs count]; i < count; i++) {
-	    NSString *dir = [[dirs objectAtIndex:i] 
-		stringByAppendingPathComponent:@"Library"];
-	    FIND_LOAD_PATH_IN_LIBRARY(dir); 
-	}
-	
-    dirs = [[[[NSProcessInfo processInfo] environment] valueForKey:@"DYLD_FRAMEWORK_PATH"] componentsSeparatedByString: @":"];
-    for (i = 0, count = [dirs count]; i < count; i++) {
-        NSString *dir = [dirs objectAtIndex:i];
-        path = [dir stringByAppendingPathComponent:frameworkName];
-        if ([fileManager fileExistsAtPath:path]) {
-            goto success;
-	}
-    }
-
-#undef FIND_LOAD_PATH_IN_LIBRARY
-
-	rb_raise(rb_eRuntimeError, "framework `%s' not found", 
-		RSTRING_PTR(framework));
-    }
-
-success:
-
-    if (cstr == NULL) {
-	cstr = fileSystemPath(path);
-    }
-
-    bundle = [NSBundle bundleWithPath:path];
-    if (bundle == nil) {
-	rb_raise(rb_eRuntimeError, 
-	         "framework at path `%s' cannot be located",
-		 cstr);
-    }
-
-    const bool loaded = [bundle isLoaded];
-    if (!loaded && ![bundle loadAndReturnError:&error]) {
-	rb_raise(rb_eRuntimeError,
-		 "framework at path `%s' cannot be loaded: %s",
-		 cstr,
-		 [[error description] UTF8String]); 
-    }
-
-    rb_objc_search_and_load_bridge_support(cstr);
-
-    rb_objc_enable_ivar_set_kvo_notifications = true;
-
-    return loaded ? Qfalse : Qtrue;
-#endif
-}
-
-void rb_vm_init_compiler(void);
-
-static void
-rb_objc_kvo_setter_imp(void *recv, SEL sel, void *value)
-{
-    const char *selname;
-    char buf[128];
-    size_t s;   
-
-    selname = sel_getName(sel);
-    buf[0] = '@';
-    buf[1] = tolower(selname[3]);
-    s = strlcpy(&buf[2], &selname[4], sizeof buf - 2);
-    buf[s + 1] = '\0';
-
-    rb_ivar_set((VALUE)recv, rb_intern(buf), value == NULL
-	    ? Qnil : OC2RB(value));
-}
-
-/*
-  Defines an attribute writer method which conforms to Key-Value Coding.
-  (See http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html)
-  
-    attr_accessor :foo
-  
-  Will create the normal accessor methods, plus <tt>setFoo</tt>
-  
-  TODO: Does not handle the case were the user might override #foo=
-*/
-void
-rb_objc_define_kvo_setter(VALUE klass, ID mid)
-{
-    char buf[100];
-    const char *mid_name;
-
-    buf[0] = 's'; buf[1] = 'e'; buf[2] = 't';
-    mid_name = rb_id2name(mid);
-
-    buf[3] = toupper(mid_name[0]);
-    buf[4] = '\0';
-    strlcat(buf, &mid_name[1], sizeof buf);
-    strlcat(buf, ":", sizeof buf);
-
-    if (!class_addMethod((Class)klass, sel_registerName(buf), 
-			 (IMP)rb_objc_kvo_setter_imp, "v@:@")) {
-	rb_warning("can't register `%s' as an KVO setter on class `%s' "\
-		"(method `%s')",
-		mid_name, rb_class2name(klass), buf);
-    }
-}
-
-VALUE
-rb_mod_objc_ib_outlet(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    int i;
-
-    rb_warn("ib_outlet has been deprecated, please use attr_writer instead");
-
-    for (i = 0; i < argc; i++) {
-	VALUE sym = argv[i];
-	
-	Check_Type(sym, T_SYMBOL);
-	rb_objc_define_kvo_setter(recv, SYM2ID(sym));
-    }
-
-    return recv;
-}
-
-static void *__obj_flags; // used as a static key
-
-long
-rb_objc_flag_get_mask(const void *obj)
-{
-    return (long)rb_objc_get_associative_ref((void *)obj, &__obj_flags);
-}
-
-bool
-rb_objc_flag_check(const void *obj, int flag)
-{
-    const long v = rb_objc_flag_get_mask(obj);
-    if (v == 0) {
-	return false; 
-    }
-    return (v & flag) == flag;
-}
-
-void
-rb_objc_flag_set(const void *obj, int flag, bool val)
-{
-    long v = (long)rb_objc_get_associative_ref((void *)obj, &__obj_flags);
-    if (val) {
-	v |= flag;
-    }
-    else {
-	v ^= flag;
-    }
-    rb_objc_set_associative_ref((void *)obj, &__obj_flags, (void *)v);
-}
-
-static IMP old_imp_isaForAutonotifying;
-
-static Class
-rb_obj_imp_isaForAutonotifying(void *rcv, SEL sel)
-{
-    long ret_version;
-
-    Class ret = ((Class (*)(void *, SEL))old_imp_isaForAutonotifying)(rcv, sel);
-
-    if (ret != NULL && ((ret_version = RCLASS_VERSION(ret)) & RCLASS_KVO_CHECK_DONE) == 0) {
-	const char *name = class_getName(ret);
-	if (strncmp(name, "NSKVONotifying_", 15) == 0) {
-	    Class ret_orig;
-	    name += 15;
-	    ret_orig = objc_getClass(name);
-	    if (ret_orig != NULL) {
-		const long orig_v = RCLASS_VERSION(ret_orig);
-		if ((orig_v & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
-		    ret_version |= RCLASS_IS_OBJECT_SUBCLASS;
-		}
-		if ((orig_v & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS) {
-		    ret_version |= RCLASS_IS_RUBY_CLASS;
-		}
-	    }
-	}
-	ret_version |= RCLASS_KVO_CHECK_DONE;
-	RCLASS_SET_VERSION(ret, ret_version);
-    }
-    return ret;
-}
-
-id
-rb_rb2oc_exception(VALUE exc)
-{
-    NSString *name = [NSString stringWithUTF8String:rb_obj_classname(exc)];
-    NSString *reason = (NSString *)rb_format_exception_message(exc);
-    NSDictionary *dict = [NSDictionary dictionaryWithObject:(id)exc
-	forKey:@"RubyException"];
-    return [NSException exceptionWithName:name reason:reason userInfo:dict];
-}
-
-VALUE
-rb_oc2rb_exception(id exc, bool *created)
-{
-    VALUE e;
-    id rubyExc;
-
-    rubyExc = [[exc userInfo] objectForKey:@"RubyException"];
-    if (rubyExc == nil) {
-	*created = true;
-
-	char buf[1000];
-	snprintf(buf, sizeof buf, "%s: %s", [[exc name] UTF8String],
-		[[exc reason] UTF8String]);
-	e = rb_exc_new2(rb_eRuntimeError, buf);
-	// Set the backtrace for Obj-C exceptions
-	rb_iv_set(e, "bt", rb_vm_backtrace(0));
-    }
-    else {
-	*created = false;
-	e = (VALUE)rubyExc;
-    }
-    return e;
-}
-
-void
-rb_objc_exception_raise(const char *name, const char *message)
-{
-    assert(name != NULL && message != NULL);
-    [[NSException exceptionWithName:[NSString stringWithUTF8String:name]
-	reason:[NSString stringWithUTF8String:message] userInfo:nil] raise];
-}
-
-id
-rb_objc_numeric2nsnumber(VALUE obj)
-{
-    if (FIXNUM_P(obj)) {
-	// TODO: this could be optimized in case we can fit the fixnum
-	// into an immediate NSNumber directly.
-	long val = FIX2LONG(obj);
-	CFNumberRef number = CFNumberCreate(NULL, kCFNumberLongType, &val);
-	CFMakeCollectable(number);
-	return (id)number;
-    }
-    if (FIXFLOAT_P(obj)) {
-	double val = NUM2DBL(obj);
-	CFNumberRef number = CFNumberCreate(NULL, kCFNumberDoubleType,
-		&val);
-	CFMakeCollectable(number);
-	return (id)number;
-    }
-    abort();
-}
-
-static SEL sel_at = 0;
-
-VALUE
-rb_objc_convert_immediate(id obj)
-{
-    const bool is_immediate = ((unsigned long)obj & 0x1) == 0x1;
-
-    Class orig_k = object_getClass(obj); // might be an immediate
-    Class k = orig_k;
-    do {
-	if (k == (Class)rb_cNSNumber) {
-	    // TODO: this could be optimized in case the object is an immediate.
-	    if (CFNumberIsFloatType((CFNumberRef)obj)) {
-		double v = 0;
-		assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberDoubleType, &v));
-		return DOUBLE2NUM(v);
-	    }
-	    else {
-		long v = 0;
-		assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberLongType, &v));
-		return LONG2FIX(v);
-	    }
-	}
-	else if (k == (Class)rb_cNSDate) {
-	    @try {
-		CFAbsoluteTime time = CFDateGetAbsoluteTime((CFDateRef)obj) + CF_REFERENCE_DATE;
-#if __LP64__
-		VALUE arg = DBL2NUM(time);
-		return rb_vm_call(rb_cTime, sel_at, 1, &arg);
-#else
-		// immediate floats have not enough precision in 32-bit
-		// so instead of using Time.at(time in float),
-		// we use Time.at(sec, usec)
-		double integral, fractional;
-		fractional = modf(time, &integral);
-		VALUE args[] = {
-		    LONG2NUM((long)integral),
-		    LONG2NUM((long)(fractional * 1e6 + 0.5))
-		};
-		return rb_vm_call(rb_cTime, sel_at, 2, args);
-#endif
-	    }
-	    @catch (NSException *e) {
-		// Some NSDates might return an exception (example: uninitialized objects).
-		break;
-	    }
-	}
-	k = class_getSuperclass(k);
-    }
-    while (k != NULL);
-
-    if (is_immediate) {
-	rb_bug("unknown Objective-C immediate: %p (%s)\n", obj, class_getName(orig_k));
-    }
-    return (VALUE)obj;
-}
-
-bool
-rb_objc_ignored_sel(SEL sel)
-{
-    return sel == @selector(retain)
-	|| sel == @selector(release)
-	|| sel == @selector(autorelease)
-	|| sel == @selector(retainCount)
-	|| sel == @selector(dealloc);
-}
-
-bool
-rb_objc_isEqual(VALUE x, VALUE y)
-{
-    return [RB2OC(x) isEqual:RB2OC(y)];
-}
-
-void
-rb_objc_force_class_initialize(Class klass)
-{
-    // Do not do anything in case the class is not NSObject-based
-    // (likely Proxy).
-    bool ok = false;
-    for (Class k = klass; k != NULL; k = class_getSuperclass(k)) {
-	if (k == (Class)rb_cNSObject) {
-	    ok = true;
-	    break;
-	}
-    }
-    if (!ok) {
-	return;
-    }
-
-    // This forces +initialize to be called.
-    class_getMethodImplementation(klass, @selector(initialize));
-}
-
-size_t
-rb_objc_type_size(const char *type)
-{
-    @try {
-	NSUInteger size, align;
-	NSGetSizeAndAlignment(type, &size, &align);
-	return size;
-    }
-    @catch (id ex) {
-	rb_raise(rb_eRuntimeError, "can't get the size of type `%s': %s",
-		type, [[ex description] UTF8String]);
-    }
-    return 0; // never reached
-}
-
-static NSString *
-relocated_load_path(NSString *path, NSString *macruby_path)
-{
-    NSRange r = [path rangeOfString:@"MacRuby.framework"];
-    if (r.location == NSNotFound) {
-	return nil;
-    }
-    r = NSMakeRange(0, r.location + r.length);
-    return [path stringByReplacingCharactersInRange:r withString:macruby_path];
-}
-
-void
-rb_objc_fix_relocatable_load_path(void)
-{
-    NSString *path = [[NSBundle mainBundle] privateFrameworksPath];
-    path = [path stringByAppendingPathComponent:@"MacRuby.framework"];
-
-    NSFileManager *fm = [NSFileManager defaultManager];
-    if ([fm fileExistsAtPath:path]) {
-	VALUE ary = rb_vm_load_path();
-	for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	    NSString *p1 = (NSString *)RARRAY_AT(ary, i);
-	    NSString *p2 = relocated_load_path(p1, path);
-	    if (p2 != nil) {
-		rb_ary_store(ary, i, (VALUE)p2);
-	    }
-	}
-    }
-}
-
-void
-rb_objc_load_loaded_frameworks_bridgesupport(void)
-{
-#if !defined(MACRUBY_STATIC)
-    for (NSBundle *b in [NSBundle allFrameworks]) {
-	if ([b isLoaded]) {
-	    NSString *path = [b bundlePath];
-	    rb_objc_search_and_load_bridge_support(fileSystemPath(path));
-	}
-    }
-#endif
-}
-
-void
-rb_objc_willChangeValueForKey(VALUE obj, NSString *key)
-{
-    if (!SPECIAL_CONST_P(obj)) {
-	[(id)obj willChangeValueForKey:key];
-    }
-}
-
-void
-rb_objc_didChangeValueForKey(VALUE obj, NSString *key)
-{
-    if (!SPECIAL_CONST_P(obj)) {
-	[(id)obj didChangeValueForKey:key];
-    }
-}
-
-static VALUE
-rb_objc_load_plist(VALUE recv, SEL sel, VALUE str)
-{
-    StringValue(str);
-    VALUE bstr = rb_str_bstr(str);
-    NSData *data = [NSData dataWithBytes:rb_bstr_bytes(bstr)
-	length:rb_bstr_length(bstr)];
-    NSError *err = nil;
-    id plist = [NSPropertyListSerialization propertyListWithData:data options:0
-	format:NULL error:&err];
-    if (plist == nil) {
-	rb_raise(rb_eArgError, "error loading property list: '%s'",
-		[[err localizedDescription] UTF8String]);
-    }
-    return OC2RB(plist);
-}
-
-extern VALUE rb_cNSDate;
-
-static VALUE
-rb_objc_to_plist(VALUE recv, SEL sel)
-{
-    switch (TYPE(recv)) {
-	case T_STRING:
-	case T_FIXNUM:
-	case T_FLOAT:
-	case T_BIGNUM:
-	case T_HASH:
-	case T_ARRAY:
-	case T_TRUE:
-	case T_FALSE:
-	    break;
-
-	default:
-	    if (!rb_obj_is_kind_of(recv, rb_cNSDate)) {
-		rb_raise(rb_eArgError,
-			"object of class '%s' cannot be serialized to " \
-			"property-list format",
-			rb_obj_classname(recv));
-	    }
-    }
-
-    id objc_obj = RB2OC(recv);
-    NSError *err = nil;
-    NSData *data = [NSPropertyListSerialization dataWithPropertyList:objc_obj
-	format:NSPropertyListXMLFormat_v1_0 options:0 error:&err];
-    if (data == nil) {
-	rb_raise(rb_eArgError, "error serializing property list: '%s'",
-		[[err localizedDescription] UTF8String]);
-    }
-    const uint8_t* bytes = [data bytes];
-    const size_t len = [data length];
-    return rb_bstr_new_with_data(bytes, len);
-}
-
-static bool
-implementsProtocolMethods(Protocol *p, Class klass, bool instanceMethods)
-{
-    unsigned int count = 0;
-    struct objc_method_description *list =
-	protocol_copyMethodDescriptionList(p, true, instanceMethods, &count);
-    if (list != NULL) {
-	bool success = true;
-	for (unsigned int i = 0; i < count; i++) {
-	    SEL msel = list[i].name;
-	    Method m;
-	    if (instanceMethods) {
-		m = class_getInstanceMethod(klass, msel);
-	    }
-	    else {
-		m = class_getClassMethod(klass, msel);
-	    }
-	    if (m == NULL) {
-		success = false;
-		break;
-	    }
-	}
-	free(list);
-	if (success) {
-	    return true;
-	}
-	return false;
-    }
-    return true;
-}
-
-static bool
-conformsToProtocol(Class klass, Protocol *p)
-{
-    if (implementsProtocolMethods(p, klass, true)
-	    && implementsProtocolMethods(p, klass, false)) {
-	unsigned int count = 0;
-	Protocol **list = protocol_copyProtocolList(p, &count);
-	bool success = true;
-	for (unsigned int i = 0; i < count; i++) {
-	    if (!conformsToProtocol(klass, list[i])) {
-		success = false;
-		break;
-	    }
-	}
-	free(list);
-	return success;
-    }
-    return false;
-}
-
-static bool
-conformsToProtocolAndAncestors(void *self, SEL sel, Class klass,
-	void *protocol)
-{
-    if (protocol != NULL) {
-	for (Class k = klass; k != NULL; k = class_getSuperclass(k)) {
-	    if (class_conformsToProtocol(k, protocol)) {
-		return true;
-	    }
-	}
-
-	Protocol *p = (Protocol *)protocol;
-	if (conformsToProtocol(klass, p)) {
-	    class_addProtocol(klass, p);
-	    return true;
-	}
-    }
-    return false;
-}
-
-static bool
-robj_conformsToProtocol(void *self, SEL sel, void *protocol)
-{
-    return conformsToProtocolAndAncestors(self, sel, object_getClass(self),
-	    protocol);
-}
-
-static bool
-robj_conformsToProtocol_m(void *self, SEL sel, void *protocol)
-{
-    return conformsToProtocolAndAncestors(self, sel, (Class)self, protocol);
-}
-
-static id
-robj_performSelector(void *self, SEL sel, SEL msg)
-{
-    return RB2OC(rb_vm_call(OC2RB(self), msg, 0, NULL));
-}
-
-static id
-robj_performSelectorWithObject(void *self, SEL sel, SEL msg, void *arg)
-{
-    VALUE rarg = OC2RB(arg);
-    return RB2OC(rb_vm_call(OC2RB(self), msg, 1, &rarg));
-}
-
-static id
-robj_performSelectorWithObjectWithObject(void *self, SEL sel, SEL msg,
-	void *arg1, void *arg2)
-{
-    VALUE rarg[2] = { OC2RB(arg1), OC2RB(arg2) };
-    return RB2OC(rb_vm_call(OC2RB(self), msg, 2, rarg));
-}
-
-void
-rb_objc_install_NSObject_special_methods(Class k)
-{
-    SEL sel = sel_registerName("conformsToProtocol:");
-    rb_objc_install_method(k, sel, (IMP)robj_conformsToProtocol);
-    rb_objc_install_method(*(Class *)k, sel, (IMP)robj_conformsToProtocol_m);
-
-    rb_objc_install_method2(k, "performSelector:", (IMP)robj_performSelector);
-    rb_objc_install_method2(k, "performSelector:withObject:",
-	    (IMP)robj_performSelectorWithObject);
-    rb_objc_install_method2(k, "performSelector:withObject:withObject:",
-	    (IMP)robj_performSelectorWithObjectWithObject);  
-}
-
-void
-Init_ObjC(void)
-{
-    sel_at = sel_registerName("at:");
-
-    rb_objc_define_module_function(rb_mKernel, "load_bridge_support_file",
-	    rb_objc_load_bs, 1);
-    rb_objc_define_module_function(rb_mKernel, "load_plist",
-	    rb_objc_load_plist, 1);
-    
-    rb_objc_define_method(rb_cObject, "to_plist", rb_objc_to_plist, 0);
-
-    // Overwrite -[NSKeyValueUnnestedProperty isaForAutonotifying].
-    Class k = objc_getClass("NSKeyValueUnnestedProperty");
-    assert(k != NULL);
-    Method m = class_getInstanceMethod(k, @selector(isaForAutonotifying));
-    assert(m != NULL);
-    old_imp_isaForAutonotifying = method_getImplementation(m);
-    method_setImplementation(m, (IMP)rb_obj_imp_isaForAutonotifying);
-
-    // Mark Foundation as multithreaded.
-    [NSThread detachNewThreadSelector:@selector(self) toTarget:[NSThread class]
-	withObject:nil];
-}
-
- at interface Protocol
- at end
-
- at implementation Protocol (MRFindProtocol)
-+ (Protocol *)protocolWithName:(NSString *)name
-{
-    return (Protocol *)objc_getProtocol([name UTF8String]);
-}
- at end
-
-#if !defined(MACRUBY_STATIC)
-static NSString *
-get_type(NSXMLElement *elem)
-{
-    NSXMLNode *node = nil;
-#if __LP64__
-    node = [elem attributeForName:@"type64"];
-#endif
-    if (node == nil) {
-	node = [elem attributeForName:@"type"];
-	if (node == nil) {
-	    return nil;
-	}
-    }
-    return [node stringValue];
-}
-
-static void
-add_stub_types(NSXMLElement *elem,
-	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
-	void *ctx,
-	bool is_objc)
-{
-    NSXMLNode *name = [elem attributeForName:is_objc
-	? @"selector" : @"name"];
-    if (name == nil) {
-	return;
-    }
-    NSArray *ary = [elem elementsForName:@"retval"];
-    if ([ary count] != 1) {
-	return;
-    }
-    NSXMLElement *retval = [ary objectAtIndex:0];
-    NSMutableString *types = [NSMutableString new];
-    NSString *type = get_type(retval);
-    if (type == nil) {
-	return;
-    }
-    [types appendString:type];
-    if (is_objc) {
-	[types appendString:@"@:"]; // self, sel
-    }
-    ary = [elem elementsForName:@"arg"];
-    for (NSXMLElement *a in ary) {
-	type = get_type(a);
-	if (type == nil) {
-	    return;
-	}
-	[types appendString:type];
-    }
-    NSString *sel_str = [name stringValue];
-    if (!is_objc && [ary count] > 0) {
-	sel_str = [sel_str stringByAppendingString:@":"];
-    }
-    SEL sel = sel_registerName([sel_str UTF8String]);
-    add_stub_types_cb(sel, [types UTF8String], is_objc, ctx);
-}
-
-void
-rb_vm_parse_bs_full_file(const char *path,
-	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
-	void *ctx)
-{
-    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:path]];
-    NSError *err = nil;
-    NSXMLDocument *doc = [[NSXMLDocument alloc] initWithContentsOfURL: url
-	options: 0 error: &err];
-    if (doc == nil) {
-	NSLog(@"can't open BridgeSupport full file at path `%s': %@",
-		path, err);
-	exit(1);
-    }
-    NSXMLElement *root = [doc rootElement];
-
-    for (NSXMLElement *k in [root elementsForName:@"class"]) {
-	for (NSXMLElement *m in [k elementsForName:@"method"]) {
-	    add_stub_types(m, add_stub_types_cb, ctx, true);
-	}
-    }
-    for (NSXMLElement *f in [root elementsForName:@"function"]) {
-	add_stub_types(f, add_stub_types_cb, ctx, false);
-    }
-}
-#endif

Deleted: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/object.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,3263 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's object.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "ruby/node.h"
-#include "id.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <math.h>
-#include <float.h>
-#include "objc.h"
-#include "vm.h"
-#include "encoding.h"
-#include "array.h"
-#include "hash.h"
-#include "class.h"
-
-VALUE rb_cBasicObject;
-VALUE rb_mKernel;
-VALUE rb_cNSObject;
-VALUE rb_cObject;
-VALUE rb_cRubyObject;
-VALUE rb_cModule;
-VALUE rb_cClass;
-VALUE rb_cData;
-
-VALUE rb_cNilClass;
-VALUE rb_cTrueClass;
-VALUE rb_cFalseClass;
-
-static ID id_eq, id_match, id_inspect, id_init_copy;
-
-static SEL eqlSel = 0;
-
-VALUE
-rb_send_dup(VALUE obj)
-{
-    return rb_vm_call(obj, selDup, 0, NULL);
-}
-
-/*
- *  call-seq:
- *     obj === other   => true or false
- *  
- *  Case Equality---For class <code>Object</code>, effectively the same
- *  as calling  <code>#==</code>, but typically overridden by descendents
- *  to provide meaningful semantics in <code>case</code> statements.
- */
-
-VALUE
-rb_equal(VALUE obj1, VALUE obj2)
-{
-    if (obj1 == obj2) {
-	return Qtrue;
-    }
-    VALUE result = rb_vm_call(obj1, selEq, 1, &obj2);
-    if (RTEST(result)) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-static VALUE
-rb_equal_imp(VALUE obj1, SEL sel, VALUE obj2)
-{
-    return rb_equal(obj1, obj2);
-}
-
-int
-rb_eql(VALUE obj1, VALUE obj2)
-{
-    VALUE obj1_class = CLASS_OF(obj1);
-
-    if (obj1_class == rb_cFixnum || obj1_class == rb_cFloat
-	    || obj1_class == rb_cSymbol) {
-	return obj1 == obj2;
-    }
-
-    VALUE obj2_class = CLASS_OF(obj2);
-    if (obj1_class == obj2_class) {
-	if (obj1_class == rb_cRubyString) {
-	    return rstr_compare(RSTR(obj1), RSTR(obj2)) == 0;
-	}
-	if (obj1_class == rb_cRubyArray) {
-	    return rary_eql_fast(RARY(obj1), RARY(obj2));
-	}
-    }
-
-    return RTEST(rb_vm_call(obj1, eqlSel, 1, &obj2));
-}
-
-/*
- *  call-seq:
- *     obj == other        => true or false
- *     obj.equal?(other)   => true or false
- *     obj.eql?(other)     => true or false
- *  
- *  Equality---At the <code>Object</code> level, <code>==</code> returns
- *  <code>true</code> only if <i>obj</i> and <i>other</i> are the
- *  same object. Typically, this method is overridden in descendent
- *  classes to provide class-specific meaning.
- *
- *  Unlike <code>==</code>, the <code>equal?</code> method should never be
- *  overridden by subclasses: it is used to determine object identity
- *  (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
- *  object as <code>b</code>).
- *
- *  The <code>eql?</code> method returns <code>true</code> if
- *  <i>obj</i> and <i>anObject</i> have the same value. Used by
- *  <code>Hash</code> to test members for equality.  For objects of
- *  class <code>Object</code>, <code>eql?</code> is synonymous with
- *  <code>==</code>. Subclasses normally continue this tradition, but
- *  there are exceptions. <code>Numeric</code> types, for example,
- *  perform type conversion across <code>==</code>, but not across
- *  <code>eql?</code>, so:
- *     
- *     1 == 1.0     #=> true
- *     1.eql? 1.0   #=> false
- */
-
-static VALUE
-rb_obj_equal(VALUE obj1, SEL sel, VALUE obj2)
-{
-    return obj1 == obj2 ? Qtrue : Qfalse;
-}
-
-static VALUE
-rb_nsobj_equal(VALUE obj1, SEL sel, VALUE obj2)
-{
-    return rb_objc_isEqual(obj1, obj2) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     !obj    => true or false
- *
- *  Boolean negate.
- */
-
-static VALUE
-rb_obj_not(VALUE obj, SEL sel)
-{
-    return RTEST(obj) ? Qfalse : Qtrue;
-}
-
-/*
- *  call-seq:
- *     obj != other        => true or false
- *
- *  Returns true if two objects are not-equal, otherwise false.
- */
-
-static VALUE
-rb_obj_not_equal(VALUE obj1, SEL sel, VALUE obj2)
-{
-    VALUE result = rb_vm_call(obj1, selEq, 1, &obj2);
-    return RTEST(result) ? Qfalse : Qtrue;
-}
-
-/*
- *  call-seq:
- *     obj.class    => class
- *  
- *  Returns the class of <i>obj</i>, now preferred over
- *  <code>Object#type</code>, as an object's type in Ruby is only
- *  loosely tied to that object's class. This method must always be
- *  called with an explicit receiver, as <code>class</code> is also a
- *  reserved word in Ruby.
- *     
- *     1.class      #=> Fixnum
- *     self.class   #=> Object
- */
-
-VALUE
-rb_obj_class(VALUE obj)
-{
-    return rb_class_real(CLASS_OF(obj), true);
-}
-
-static void
-init_copy(VALUE dest, VALUE obj)
-{
-    if (NATIVE(obj)) {
-	if (OBJ_TAINTED(obj)) {
-	    OBJ_TAINT(dest);
-	} 
-	goto call_init_copy;
-    }
-    if (OBJ_FROZEN(dest)) {
-        rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
-    }
-    RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
-    RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT);
-    rb_copy_generic_ivar(dest, obj);
-    rb_gc_copy_finalizer(dest, obj);
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    if (ROBJECT(obj)->num_slots > 0) {
-		if (ROBJECT(dest)->num_slots < ROBJECT(obj)->num_slots) {
-		    rb_vm_regrow_robject_slots(ROBJECT(dest),
-			    ROBJECT(obj)->num_slots);
-		}
-		for (int i = 0; i < ROBJECT(obj)->num_slots; i++) {
-		    rb_object_ivar_slot_t *dest_sl = &ROBJECT(dest)->slots[i];
-		    rb_object_ivar_slot_t *orig_sl = &ROBJECT(obj)->slots[i];
-		    dest_sl->name = orig_sl->name;
-		    GC_WB(&dest_sl->value, orig_sl->value);
-		}
-	    }
-	    ROBJECT(dest)->num_slots = ROBJECT(obj)->num_slots;
-	    break;
-      case T_CLASS:
-      case T_MODULE:
-	{
-	    CFMutableDictionaryRef dest_dict, obj_dict;
-	    
-	    obj_dict = rb_class_ivar_dict(obj);
-	    dest_dict = rb_class_ivar_dict(dest);
-	    if (dest_dict != NULL)
-		CFDictionaryRemoveAllValues(dest_dict);
-	    if (obj_dict != NULL) {
-		dest_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)obj_dict);
-		CFMakeCollectable(dest_dict);
-		rb_class_ivar_set_dict(dest, dest_dict);
-	    }
-	    else {
-		if (dest_dict)
-		    rb_class_ivar_set_dict(dest, NULL);
-	    }
-	}
-        break;
-    }
-call_init_copy:
-    rb_vm_call(dest, selInitializeCopy, 1, &obj);
-}
-
-/*
- *  call-seq:
- *     obj.clone -> an_object
- *  
- *  Produces a shallow copy of <i>obj</i>---the instance variables of
- *  <i>obj</i> are copied, but not the objects they reference. Copies
- *  the frozen and tainted state of <i>obj</i>. See also the discussion
- *  under <code>Object#dup</code>.
- *     
- *     class Klass
- *        attr_accessor :str
- *     end
- *     s1 = Klass.new      #=> #<Klass:0x401b3a38>
- *     s1.str = "Hello"    #=> "Hello"
- *     s2 = s1.clone       #=> #<Klass:0x401b3998 @str="Hello">
- *     s2.str[1,4] = "i"   #=> "i"
- *     s1.inspect          #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
- *     s2.inspect          #=> "#<Klass:0x401b3998 @str=\"Hi\">"
- *
- *  This method may have class-specific behavior.  If so, that
- *  behavior will be documented under the #+initialize_copy+ method of
- *  the class.
- */
-
-static VALUE rb_class_s_alloc(VALUE, SEL);
-
-static VALUE
-rb_obj_clone_imp(VALUE obj, SEL sel)
-{
-    VALUE clone;
-
-    if (rb_special_const_p(obj)) {
-        rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
-    }
-    switch (TYPE(obj)) {
-	case T_NATIVE:
-	    clone = rb_obj_alloc(rb_obj_class(obj));
-	    RBASIC(clone)->klass = rb_singleton_class_clone(obj);
-	    break;
-	case T_CLASS:
-	case T_MODULE:
-	    clone = rb_class_s_alloc(Qnil, 0);
-	    break;
-	default:
-	    clone = rb_obj_alloc(rb_obj_class(obj));
-	    RBASIC(clone)->klass = rb_singleton_class_clone(obj);
-	    RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
-	    break;
-    }
-
-    init_copy(clone, obj);
-    if (OBJ_FROZEN(obj)) {
-	OBJ_FREEZE(clone);
-    }
-
-    return clone;
-}
-
-VALUE
-rb_obj_clone(VALUE obj)
-{
-    return rb_obj_clone_imp(obj, 0);
-}
-
-/*
- *  call-seq:
- *     obj.dup -> an_object
- *  
- *  Produces a shallow copy of <i>obj</i>---the instance variables of
- *  <i>obj</i> are copied, but not the objects they reference.
- *  <code>dup</code> copies the tainted state of <i>obj</i>. See also
- *  the discussion under <code>Object#clone</code>. In general,
- *  <code>clone</code> and <code>dup</code> may have different semantics
- *  in descendent classes. While <code>clone</code> is used to duplicate
- *  an object, including its internal state, <code>dup</code> typically
- *  uses the class of the descendent object to create the new instance.
- *
- *  This method may have class-specific behavior.  If so, that
- *  behavior will be documented under the #+initialize_copy+ method of
- *  the class.
- */
-
-VALUE
-rb_obj_dup(VALUE obj)
-{
-    VALUE dup;
-
-    if (rb_special_const_p(obj) || TYPE(obj) == T_SYMBOL) {
-        rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
-    }
-    dup = rb_obj_alloc(rb_obj_class(obj));
-    init_copy(dup, obj);
-    if (OBJ_UNTRUSTED(obj))
-	OBJ_UNTRUST(dup);
-
-    return dup;
-}
-
-static VALUE
-rb_obj_type(VALUE obj)
-{
-    return LONG2FIX(TYPE(obj));
-}
-
-/* :nodoc: */
-VALUE
-rb_obj_init_copy(VALUE obj, SEL sel, VALUE orig)
-{
-    if (obj == orig) {
-	return obj;
-    }
-    rb_check_frozen(obj);
-    if (rb_obj_class(obj) != rb_obj_class(orig)) {
-	rb_raise(rb_eTypeError,
-		"initialize_copy should take same class object");
-    }
-    return obj;
-}
-
-static VALUE
-rb_nsobj_dup(VALUE obj, VALUE sel)
-{
-    VALUE klass = rb_class_real(CLASS_OF(obj), true);
-    if (class_respondsToSelector((Class)klass, selCopyWithZone)) {
-	return (VALUE)objc_msgSend((id)obj, selCopy); 
-    }
-
-    VALUE copy = rb_vm_new_rb_object(klass);
-    rb_obj_init_copy(copy, 0, (VALUE)obj);
-    return copy;
-}
-
-/*
- *  call-seq:
- *     obj.to_s    => string
- *  
- *  Returns a string representing <i>obj</i>. The default
- *  <code>to_s</code> prints the object's class and an encoding of the
- *  object id. As a special case, the top-level object that is the
- *  initial execution context of Ruby programs returns ``main.''
- */
-
-VALUE
-rb_any_to_string(VALUE obj, SEL sel)
-{
-    const char *cname = rb_obj_classname(obj);
-    VALUE str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
-    if (OBJ_TAINTED(obj)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-VALUE
-rb_any_to_s(VALUE obj)
-{
-    return rb_any_to_string(obj, 0);
-}
-
-VALUE
-rb_inspect(VALUE obj)
-{
-    return rb_obj_as_string(rb_funcall(obj, id_inspect, 0, 0));
-}
-
-static int
-inspect_i(ID id, VALUE value, VALUE str)
-{
-    if (!rb_is_instance_id(id)) {
-	return ST_CONTINUE;
-    }
-
-    const char *cstr = RSTRING_PTR(str);
-    if (cstr[0] == '-') { /* first element */
-	rb_str_update(str, 0, 0, rb_str_new2("#"));
-	rb_str_cat2(str, " ");
-    }
-    else {
-	rb_str_cat2(str, " ");
-    }
-
-    const char *ivname = rb_id2name(id);
-    rb_str_cat2(str, ivname);
-    rb_str_cat2(str, "=");
-    VALUE str2 = rb_inspect(value);
-    rb_str_append(str, str2);
-    OBJ_INFECT(str, str2);
-
-    return ST_CONTINUE;
-}
-
-static VALUE
-inspect_obj(VALUE obj, VALUE str, int recur)
-{
-    if (recur) {
-	rb_str_cat2(str, " ...");
-    }
-    else {
-	rb_ivar_foreach(obj, inspect_i, str);
-    }
-    rb_str_cat2(str, ">");
-    OBJ_INFECT(str, obj);
-
-    return str;
-}
-
-/*
- *  call-seq:
- *     obj.inspect   => string
- *  
- *  Returns a string containing a human-readable representation of
- *  <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
- *  generate the string.
- *     
- *     [ 1, 2, 3..4, 'five' ].inspect   #=> "[1, 2, 3..4, \"five\"]"
- *     Time.new.inspect                 #=> "2008-03-08 19:43:39 +0900"
- */
-
-
-static VALUE
-rb_obj_inspect(VALUE obj, SEL sel)
-{
-    if (TYPE(obj) == T_OBJECT) {
-	for (int i = 0; i < ROBJECT(obj)->num_slots; i++) {
-	    if (ROBJECT(obj)->slots[i].value != Qundef) {
-		// There is at least an ivar.
-		const char *c = rb_obj_classname(obj);
-		VALUE str = rb_sprintf("#<%s:%p", c, (void*)obj);
-		return rb_exec_recursive(inspect_obj, obj, str);
-	    }
-	}
-    }
-    return rb_funcall(obj, rb_intern("to_s"), 0, 0);
-}
-
-/*
- *  call-seq:
- *     obj.instance_of?(class)    => true or false
- *  
- *  Returns <code>true</code> if <i>obj</i> is an instance of the given
- *  class. See also <code>Object#kind_of?</code>.
- */
-
-VALUE
-rb_obj_is_instance_of(VALUE obj, VALUE c)
-{
-    switch (TYPE(c)) {
-      case T_MODULE:
-      case T_CLASS:
-      case T_ICLASS:
-	break;
-      default:
-	rb_raise(rb_eTypeError, "class or module required");
-    }
-
-    if (rb_obj_class(obj) == c) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-static VALUE
-rb_obj_is_instance_of_imp(VALUE obj, SEL sel, VALUE c)
-{
-    return rb_obj_is_instance_of(obj, c);
-}
-
-/*
- *  call-seq:
- *     obj.is_a?(class)       => true or false
- *     obj.kind_of?(class)    => true or false
- *  
- *  Returns <code>true</code> if <i>class</i> is the class of
- *  <i>obj</i>, or if <i>class</i> is one of the superclasses of
- *  <i>obj</i> or modules included in <i>obj</i>.
- *     
- *     module M;    end
- *     class A
- *       include M
- *     end
- *     class B < A; end
- *     class C < B; end
- *     b = B.new
- *     b.instance_of? A   #=> false
- *     b.instance_of? B   #=> true
- *     b.instance_of? C   #=> false
- *     b.instance_of? M   #=> false
- *     b.kind_of? A       #=> true
- *     b.kind_of? B       #=> true
- *     b.kind_of? C       #=> false
- *     b.kind_of? M       #=> true
- */
-
-VALUE
-rb_obj_is_kind_of(VALUE obj, VALUE c)
-{
-    VALUE cl = CLASS_OF(obj);
-    bool is_module = false;
-
-    switch (TYPE(c)) {
-      case T_MODULE:
-	  is_module = true;
-	  // fall through
-      case T_CLASS:
-      case T_ICLASS:
-	  break;
-
-      default:
-	  rb_raise(rb_eTypeError, "class or module required");
-    }
-
-    const int t = TYPE(obj);
-    if (c == rb_cRubyString && t == T_STRING) {
-	return Qtrue;
-    }
-    if (c == rb_cRubyArray && t == T_ARRAY) {
-	return Qtrue;
-    }
-    if (c == rb_cRubyHash && t == T_HASH) {
-	return Qtrue;
-    }
-
-    if (RCLASS_META(cl)) {
-	is_module = true;
-    }
-
-    while (cl != 0) {
-	if (cl == c) {
-	    return Qtrue;
-	}
-	if (is_module) {
-	    VALUE ary = rb_attr_get(cl, idIncludedModules);
-	    if (ary != Qnil) {
-		for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-		    VALUE imod = RARRAY_AT(ary, i);
-		    if (imod == c) {
-			return Qtrue;
-		    }
-		}
-	    }
-	}
-	cl = RCLASS_SUPER(cl);
-    }
-    return Qfalse;
-}
-
-static VALUE
-rb_obj_is_kind_of_imp(VALUE obj, SEL sel, VALUE c)
-{
-    return rb_obj_is_kind_of(obj, c);
-}
-
-/*
- *  call-seq:
- *     obj.tap{|x|...}    => obj
- *  
- *  Yields <code>x</code> to the block, and then returns <code>x</code>.
- *  The primary purpose of this method is to "tap into" a method chain,
- *  in order to perform operations on intermediate results within the chain.
- *
- *	(1..10)                .tap {|x| puts "original: #{x.inspect}"}
- *	  .to_a                .tap {|x| puts "array: #{x.inspect}"}
- *	  .select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
- *	  .map { |x| x*x }     .tap {|x| puts "squares: #{x.inspect}"}
- *
- */
-
-static VALUE
-rb_obj_tap(VALUE obj, SEL sel)
-{
-    rb_yield(obj);
-    return obj;
-}
-
-
-/*
- * Document-method: inherited
- *
- * call-seq:
- *    inherited(subclass)
- *
- * Callback invoked whenever a subclass of the current class is created.
- *
- * Example:
- *
- *    class Foo
- *       def self.inherited(subclass)
- *          puts "New subclass: #{subclass}"
- *       end
- *    end
- *
- *    class Bar < Foo
- *    end
- *
- *    class Baz < Bar
- *    end
- *
- * produces:
- *
- *    New subclass: Bar
- *    New subclass: Baz
- */
-
-/*
- * Document-method: singleton_method_added
- *
- *  call-seq:
- *     singleton_method_added(symbol)
- *  
- *  Invoked as a callback whenever a singleton method is added to the
- *  receiver.
- *     
- *     module Chatty
- *       def Chatty.singleton_method_added(id)
- *         puts "Adding #{id.id2name}"
- *       end
- *       def self.one()     end
- *       def two()          end
- *       def Chatty.three() end
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     Adding singleton_method_added
- *     Adding one
- *     Adding three
- *     
- */
-
-/*
- * Document-method: singleton_method_removed
- *
- *  call-seq:
- *     singleton_method_removed(symbol)
- *  
- *  Invoked as a callback whenever a singleton method is removed from
- *  the receiver.
- *     
- *     module Chatty
- *       def Chatty.singleton_method_removed(id)
- *         puts "Removing #{id.id2name}"
- *       end
- *       def self.one()     end
- *       def two()          end
- *       def Chatty.three() end
- *       class <<self
- *         remove_method :three
- *         remove_method :one
- *       end
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     Removing three
- *     Removing one
- */
-
-/*
- * Document-method: singleton_method_undefined
- *
- *  call-seq:
- *     singleton_method_undefined(symbol)
- *  
- *  Invoked as a callback whenever a singleton method is undefined in
- *  the receiver.
- *     
- *     module Chatty
- *       def Chatty.singleton_method_undefined(id)
- *         puts "Undefining #{id.id2name}"
- *       end
- *       def Chatty.one()   end
- *       class << self
- *          undef_method(:one)
- *       end
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     Undefining one
- */
-
-
-/*
- * Document-method: included
- *
- * call-seq:
- *    included( othermod )
- *
- * Callback invoked whenever the receiver is included in another
- * module or class. This should be used in preference to
- * <tt>Module.append_features</tt> if your code wants to perform some
- * action when a module is included in another.
- *
- *        module A
- *          def A.included(mod)
- *            puts "#{self} included in #{mod}"
- *          end
- *        end
- *        module Enumerable
- *          include A
- *        end
- */
-
-
-/*
- * Not documented
- */
-
-static VALUE
-rb_obj_dummy(VALUE self, SEL sel)
-{
-    return Qnil;
-}
-
-static VALUE
-rb_obj_dummy2(VALUE self, SEL sel, VALUE other)
-{
-    return Qnil;
-}
-
-// In order to mimic 1.9, we allow Floats to be tainted and untrusted, even
-// though they are technically immediates.
-static st_table *immediate_flags_tbl = 0;
-
-
-/*
- *  call-seq:
- *     obj.tainted?    => true or false
- *  
- *  Returns <code>true</code> if the object is tainted.
- */
-
-static VALUE
-rb_obj_tainted_p(VALUE obj, SEL sel)
-{
-    if (SPECIAL_CONST_P(obj)) {
-	if (immediate_flags_tbl && FIXFLOAT_P(obj)) {
-	    VALUE flags = 0;
-	    if (st_lookup(immediate_flags_tbl, obj, &flags) && (flags & FL_TAINT)) {
-		return Qtrue;
-	    }
-	}
-	return Qfalse;
-    }
-    else if (NATIVE(obj)) {
-	switch (TYPE(obj)) {
-	    case T_SYMBOL:
-		return Qfalse;
-	    case T_ARRAY:
-		if (rb_klass_is_rary(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
-		}
-		// fall through
-	    case T_STRING:
-		if (rb_klass_is_rstr(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
-		}
-		// fall through
-	    case T_HASH:
-		if (rb_klass_is_rhash(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
-		}
-	    default:
-		return rb_objc_flag_check((const void *)obj, FL_TAINT)
-		    ? Qtrue : Qfalse;
-	}
-    }
-    if (FL_TEST(obj, FL_TAINT)) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-VALUE
-rb_obj_tainted(VALUE obj)
-{
-    return rb_obj_tainted_p(obj, 0);
-}
-
-/*
- *  call-seq:
- *     obj.taint -> obj
- *  
- *  Marks <i>obj</i> as tainted---if the <code>$SAFE</code> level is
- *  set appropriately, many method calls which might alter the running
- *  programs environment will refuse to accept tainted strings.
- */
-
-static VALUE
-rb_obj_taint_m(VALUE obj, SEL sel)
-{
-    rb_secure(4);
-    if (SPECIAL_CONST_P(obj)) {
-	if (!FIXFLOAT_P(obj)) {
-	    return obj;
-	}
-	else if (!immediate_flags_tbl) {
-	    immediate_flags_tbl = st_init_numtable();
-	    GC_RETAIN(immediate_flags_tbl);
-	    st_insert(immediate_flags_tbl, obj, (st_data_t)FL_TAINT);
-	}
-	else {
-	    VALUE flags = 0;
-	    st_lookup(immediate_flags_tbl, obj, &flags);
-	    flags |= FL_TAINT;
-	    st_insert(immediate_flags_tbl, obj, (st_data_t)flags);
-	}
-	return obj;
-    }
-    else if (NATIVE(obj)) {
-	switch (TYPE(obj)) {
-	    case T_SYMBOL:
-		return obj;
-	    case T_ARRAY:
-		if (rb_klass_is_rary(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags |= FL_TAINT;
-		    break;
-		}
-		// fall through
-	    case T_STRING:
-		if (rb_klass_is_rstr(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags |= FL_TAINT;
-		    break;
-		}
-		// fall through
-	    case T_HASH:
-		if (rb_klass_is_rhash(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags |= FL_TAINT;
-		    break;
-		}
-	    default:
-		rb_objc_flag_set((const void *)obj, FL_TAINT, true);
-	}
-	return obj;
-    }
-    if (!OBJ_TAINTED(obj)) {
-	if (OBJ_FROZEN(obj)) {
-	    rb_error_frozen("object");
-	}
-	FL_SET(obj, FL_TAINT);
-    }
-    return obj;
-}
-
-VALUE 
-rb_obj_taint(VALUE obj)
-{
-    return rb_obj_taint_m(obj, 0);
-}
-
-
-/*
- *  call-seq:
- *     obj.untaint    => obj
- *  
- *  Removes the taint from <i>obj</i>.
- */
-
-static VALUE
-rb_obj_untaint_m(VALUE obj, SEL sel)
-{
-    rb_secure(3);
-    if (SPECIAL_CONST_P(obj)) {
-	if (immediate_flags_tbl && FIXFLOAT_P(obj)) {
-	    VALUE flags = 0;
-	    st_lookup(immediate_flags_tbl, obj, &flags);
-	    flags &= ~FL_TAINT;
-	    st_insert(immediate_flags_tbl, obj, (st_data_t)flags);
-	}
-	return obj;
-    }
-    else if (NATIVE(obj)) {
-	switch (TYPE(obj)) {
-	    case T_SYMBOL:
-		return obj;
-	    case T_ARRAY:
-		if (rb_klass_is_rary(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags &= ~FL_TAINT;
-		    break;
-		}	
-		// fall through
-	    case T_STRING:
-		if (rb_klass_is_rstr(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags &= ~FL_TAINT;
-		    break;
-		}
-		// fall through
-	    case T_HASH:
-		if (rb_klass_is_rhash(*(VALUE *)obj)) {
-		    RBASIC(obj)->flags &= ~FL_TAINT;
-		    break;
-		}
-	    default:
-		rb_objc_flag_set((const void *)obj, FL_TAINT, false);
-	}
-	return obj;
-    }
-    if (OBJ_TAINTED(obj)) {
-	if (OBJ_FROZEN(obj)) {
-	    rb_error_frozen("object");
-	}
-	FL_UNSET(obj, FL_TAINT);
-    }
-    return obj;
-}
-
-VALUE
-rb_obj_untaint(VALUE obj)
-{
-    return rb_obj_untaint_m(obj, 0);
-}
-
-static VALUE
-rb_obj_untrusted_imp(VALUE obj, SEL sel)
-{
-    if (SPECIAL_CONST_P(obj)) {
-	if (immediate_flags_tbl && FIXFLOAT_P(obj)) {
-	    VALUE flags = 0;
-	    if (st_lookup(immediate_flags_tbl, obj, &flags) && (flags && FL_UNTRUSTED)) {
-		return Qtrue;
-	    }
-	}
-	return Qfalse;
-    }
-    else if (NATIVE(obj)) {
-	switch (TYPE(obj)) {
-	    case T_SYMBOL:
-		return Qfalse;	
-	    case T_ARRAY:
-		if (rb_klass_is_rary(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_UNTRUSTED ? Qtrue : Qfalse;
-		}
-		// fall through
-	    case T_STRING:
-		if (rb_klass_is_rstr(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_UNTRUSTED ? Qtrue : Qfalse;
-		}
-		// fall through
-	    case T_HASH:
-		if (rb_klass_is_rhash(*(VALUE *)obj)) {
-		    return RBASIC(obj)->flags & FL_UNTRUSTED ? Qtrue : Qfalse;
-		}
-	    default:
-		return rb_objc_flag_check((const void *)obj, FL_UNTRUSTED) ? Qtrue : Qfalse;
-	}
-    }
-    if (FL_TEST(obj, FL_UNTRUSTED)) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-VALUE
-rb_obj_untrusted(VALUE obj)
-{
-    return rb_obj_untrusted_imp(obj, 0);
-}
-
-static VALUE
-rb_obj_trust_imp(VALUE obj, SEL sel)
-{
-    rb_secure(3);
-    if (OBJ_UNTRUSTED(obj)) {
-	if (OBJ_FROZEN(obj)) {
-	    rb_error_frozen("object");
-	}
-	else if (SPECIAL_CONST_P(obj)) {
-	    if(!FIXFLOAT_P(obj)) {
-		return obj;
-	    }
-	    else if(!immediate_flags_tbl) {
-		immediate_flags_tbl = st_init_numtable();
-		GC_RETAIN(immediate_flags_tbl);
-		st_insert(immediate_flags_tbl, obj, FL_UNTRUSTED);
-	    }
-	    else {
-		VALUE flags = 0;
-		st_lookup(immediate_flags_tbl, obj, &flags);
-		flags &= ~FL_UNTRUSTED;
-		st_insert(immediate_flags_tbl, obj, (st_data_t)flags);
-	    }
-	    return obj;
-	}
-	else if (NATIVE(obj)) {
-	    switch (TYPE(obj)) {
-		case T_SYMBOL:
-		    return obj;
-		case T_ARRAY:
-		    if (rb_klass_is_rary(*(VALUE *)obj)) {
-			RBASIC(obj)->flags &= ~FL_UNTRUSTED;
-			break;
-		    }
-		    // fall through
-		case T_STRING:
-		    if (rb_klass_is_rstr(*(VALUE *)obj)) {
-			RBASIC(obj)->flags &= ~FL_UNTRUSTED;
-			break;
-		    }
-		    // fall through
-		case T_HASH:
-		    if (rb_klass_is_rhash(*(VALUE *)obj)) {
-			RBASIC(obj)->flags &= ~FL_UNTRUSTED;
-			break;
-		    }
-		default:
-		    rb_objc_flag_set((const void *)obj, FL_UNTRUSTED, false);
-	    }
-	    return obj;
-	}
-	FL_UNSET(obj, FL_UNTRUSTED);
-    }
-    return obj;
-}
-
-VALUE
-rb_obj_trust(VALUE obj)
-{
-    return rb_obj_trust_imp(obj, 0);
-}
-
-static VALUE
-rb_obj_untrust_imp(VALUE obj, SEL sel)
-{
-    rb_secure(4);
-    if (!OBJ_UNTRUSTED(obj)) {
-	if (OBJ_FROZEN(obj)) {
-	    rb_error_frozen("object");
-	}
-	else if (SPECIAL_CONST_P(obj)) {
-	    if (!FIXFLOAT_P(obj)) {
-		return obj;
-	    }
-	    else if (!immediate_flags_tbl) {
-		immediate_flags_tbl = st_init_numtable();
-		GC_RETAIN(immediate_flags_tbl);
-		st_insert(immediate_flags_tbl, obj, (st_data_t)FL_UNTRUSTED);
-	    }
-	    else {
-		VALUE flags = 0;
-		st_lookup(immediate_flags_tbl, obj, &flags);
-		flags |= FL_UNTRUSTED;
-		st_insert(immediate_flags_tbl, obj, (st_data_t)flags);
-	    }
-	    return obj;
-	}
-	else if (NATIVE(obj)) {
-	    switch (TYPE(obj)) {
-		case T_SYMBOL:
-		    return Qfalse;
-		case T_ARRAY:
-		    if (rb_klass_is_rary(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_UNTRUSTED;
-			break;
-		    }
-		    // fall through
-		case T_STRING:
-		    if (rb_klass_is_rstr(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_UNTRUSTED;
-			break;
-		    }
-		    // fall through
-		case T_HASH:
-		    if (rb_klass_is_rhash(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_UNTRUSTED;
-			break;
-		    }
-		default:
-		    rb_objc_flag_set((const void *)obj, FL_UNTRUSTED, true);
-	    }
-	    return obj;
-	}
-	FL_SET(obj, FL_UNTRUSTED);
-    }
-    return obj;
-}
-
-VALUE
-rb_obj_untrust(VALUE obj)
-{
-	return rb_obj_untrust_imp(obj, 0);
-}
-
-void
-rb_obj_infect(VALUE obj1, VALUE obj2)
-{
-    OBJ_INFECT(obj1, obj2);
-}
-
-/*
- *  call-seq:
- *     obj.freeze    => obj
- *  
- *  Prevents further modifications to <i>obj</i>. A
- *  <code>TypeError</code> will be raised if modification is attempted.
- *  There is no way to unfreeze a frozen object. See also
- *  <code>Object#frozen?</code>.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.freeze
- *     a << "z"
- *     
- *  <em>produces:</em>
- *     
- *     prog.rb:3:in `<<': can't modify frozen array (TypeError)
- *     	from prog.rb:3
- */
-
-static VALUE
-rb_obj_freeze_m(VALUE obj, SEL sel)
-{
-    if (!OBJ_FROZEN(obj)) {
-	int type;
-	if (rb_safe_level() >= 4 && OBJ_UNTRUSTED(obj)) {
-	    rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
-	}
-	else if (SPECIAL_CONST_P(obj)) {
-immediate:
-	    if (!immediate_flags_tbl) {
-		immediate_flags_tbl = st_init_numtable();
-	 	GC_RETAIN(immediate_flags_tbl);
-		st_insert(immediate_flags_tbl, obj, (st_data_t)FL_FREEZE);
-	    } 
-	    else {
-		VALUE flags = 0;
-		st_lookup(immediate_flags_tbl, obj, &flags);
-		flags |= FL_FREEZE;
-		st_insert(immediate_flags_tbl, obj, (st_data_t)flags);
-	    }
-	    return obj;
-	}
-	else if ((type = TYPE(obj)) == T_CLASS || type == T_MODULE) {
-	    RCLASS_SET_VERSION_FLAG(obj, RCLASS_IS_FROZEN);
-	}
-	else if (NATIVE(obj)) {
-	    switch (TYPE(obj)) {
-		case T_SYMBOL:
-		    goto immediate;
-
-		case T_ARRAY:
-		    if (rb_klass_is_rary(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_FREEZE;
-			break;
-		    }
-		    // fall through
-		case T_STRING:
-		    if (rb_klass_is_rstr(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_FREEZE;
-			break;
-		    }
-		    // fall through
-		case T_HASH:
-		    if (rb_klass_is_rhash(*(VALUE *)obj)) {
-			RBASIC(obj)->flags |= FL_FREEZE;
-			break;
-		    }
-		default:
-		    rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
-	    }
-	}
-	else {
-	    FL_SET(obj, FL_FREEZE);
-	}
-    }
-    return obj;
-}
-
-VALUE
-rb_obj_freeze(VALUE obj)
-{
-    return rb_obj_freeze_m(obj, 0);
-}
-
-/*
- *  call-seq:
- *     obj.frozen?    => true or false
- *  
- *  Returns the freeze status of <i>obj</i>.
- *     
- *     a = [ "a", "b", "c" ]
- *     a.freeze    #=> ["a", "b", "c"]
- *     a.frozen?   #=> true
- */
-
-static VALUE
-rb_obj_frozen(VALUE obj, SEL sel)
-{
-    if (SPECIAL_CONST_P(obj)) {
-immediate:
-	if (immediate_flags_tbl) {
-	    VALUE flags = 0;
-	    if (st_lookup(immediate_flags_tbl, obj, &flags) && (flags & FL_FREEZE)) {
-	    	return Qtrue;
-	    }
-	}
-	return Qfalse;
-    }
-    switch (TYPE(obj)) {
-	case T_SYMBOL:
-	    goto immediate;
-
-	case T_ARRAY:
-	    if (rb_klass_is_rary(*(VALUE *)obj)) {
-		return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
-	    }
-	    // fall through
-	case T_STRING:
-	    if (rb_klass_is_rstr(*(VALUE *)obj)) {
-		return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
-	    }
-	    // fall through
-	case T_HASH:
-	    if (rb_klass_is_rhash(*(VALUE *)obj)) {
-		return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
-	    }
-	case T_NATIVE:
-	    return rb_objc_flag_check((const void *)obj, FL_FREEZE)
-		? Qtrue : Qfalse;
-	case T_CLASS:
-	case T_ICLASS:
-	case T_MODULE:
-	    return (RCLASS_VERSION(obj) & RCLASS_IS_FROZEN) == RCLASS_IS_FROZEN ? Qtrue : Qfalse;
-	default:
-	    return FL_TEST(obj, FL_FREEZE) ? Qtrue : Qfalse;
-    }
-}
-
-VALUE
-rb_obj_frozen_p(VALUE obj)
-{
-    return rb_obj_frozen(obj, 0);
-}
-
-
-/*
- * Document-class: NilClass
- *
- *  The class of the singleton object <code>nil</code>.
- */
-
-/*
- *  call-seq:
- *     nil.to_i => 0
- *  
- *  Always returns zero.
- *     
- *     nil.to_i   #=> 0
- */
-
-
-static VALUE
-nil_to_i(VALUE obj, SEL sel)
-{
-    return INT2FIX(0);
-}
-
-/*
- *  call-seq:
- *     nil.to_f    => 0.0
- *  
- *  Always returns zero.
- *     
- *     nil.to_f   #=> 0.0
- */
-
-static VALUE
-nil_to_f(VALUE obj, SEL sel)
-{
-    return DOUBLE2NUM(0.0);
-}
-
-/*
- *  call-seq:
- *     nil.to_s    => ""
- *  
- *  Always returns the empty string.
- */
-
-static VALUE
-nil_to_s(VALUE obj, SEL sel)
-{
-    return rb_usascii_str_new(0, 0);
-}
-
-/*
- * Document-method: to_a
- *
- *  call-seq:
- *     nil.to_a    => []
- *  
- *  Always returns an empty array.
- *     
- *     nil.to_a   #=> []
- */
-
-static VALUE
-nil_to_a(VALUE obj, SEL sel)
-{
-    return rb_ary_new2(0);
-}
-
-/*
- *  call-seq:
- *    nil.inspect  => "nil"
- *
- *  Always returns the string "nil".
- */
-
-static VALUE
-nil_inspect(VALUE obj, SEL sel)
-{
-    return rb_usascii_str_new2("nil");
-}
-
-/***********************************************************************
- *  Document-class: TrueClass
- *
- *  The global value <code>true</code> is the only instance of class
- *  <code>TrueClass</code> and represents a logically true value in
- *  boolean expressions. The class provides operators allowing
- *  <code>true</code> to be used in logical expressions.
- */
-
-
-/*
- * call-seq:
- *   true.to_s   =>  "true"
- *
- * The string representation of <code>true</code> is "true".
- */
-
-static VALUE
-true_to_s(VALUE obj, SEL sel)
-{
-    return rb_usascii_str_new2("true");
-}
-
-
-/*
- *  call-seq:
- *     true & obj    => true or false
- *  
- *  And---Returns <code>false</code> if <i>obj</i> is
- *  <code>nil</code> or <code>false</code>, <code>true</code> otherwise.
- */
-
-static VALUE
-true_and(VALUE obj, SEL sel, VALUE obj2)
-{
-    return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-/*
- *  call-seq:
- *     true | obj   => true
- *  
- *  Or---Returns <code>true</code>. As <i>anObject</i> is an argument to
- *  a method call, it is always evaluated; there is no short-circuit
- *  evaluation in this case.
- *     
- *     true |  puts("or")
- *     true || puts("logical or")
- *     
- *  <em>produces:</em>
- *     
- *     or
- */
-
-static VALUE
-true_or(VALUE obj, SEL sel, VALUE obj2)
-{
-    return Qtrue;
-}
-
-
-/*
- *  call-seq:
- *     true ^ obj   => !obj
- *  
- *  Exclusive Or---Returns <code>true</code> if <i>obj</i> is
- *  <code>nil</code> or <code>false</code>, <code>false</code>
- *  otherwise.
- */
-
-static VALUE
-true_xor(VALUE obj, SEL sel, VALUE obj2)
-{
-    return RTEST(obj2)?Qfalse:Qtrue;
-}
-
-
-/*
- *  Document-class: FalseClass
- *
- *  The global value <code>false</code> is the only instance of class
- *  <code>FalseClass</code> and represents a logically false value in
- *  boolean expressions. The class provides operators allowing
- *  <code>false</code> to participate correctly in logical expressions.
- *     
- */
-
-/*
- * call-seq:
- *   false.to_s   =>  "false"
- *
- * 'nuf said...
- */
-
-static VALUE
-false_to_s(VALUE obj, SEL sel)
-{
-    return rb_usascii_str_new2("false");
-}
-
-/*
- *  call-seq:
- *     false & obj   => false
- *     nil & obj     => false
- *  
- *  And---Returns <code>false</code>. <i>obj</i> is always
- *  evaluated as it is the argument to a method call---there is no
- *  short-circuit evaluation in this case.
- */
-
-static VALUE
-false_and(VALUE obj, SEL sel, VALUE obj2)
-{
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     false | obj   =>   true or false
- *     nil   | obj   =>   true or false
- *  
- *  Or---Returns <code>false</code> if <i>obj</i> is
- *  <code>nil</code> or <code>false</code>; <code>true</code> otherwise.
- */
-
-static VALUE
-false_or(VALUE obj, SEL sel, VALUE obj2)
-{
-    return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-/*
- *  call-seq:
- *     false ^ obj    => true or false
- *     nil   ^ obj    => true or false
- *  
- *  Exclusive Or---If <i>obj</i> is <code>nil</code> or
- *  <code>false</code>, returns <code>false</code>; otherwise, returns
- *  <code>true</code>.
- *     
- */
-
-static VALUE
-false_xor(VALUE obj, SEL sel, VALUE obj2)
-{
-    return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-/*
- * call_seq:
- *   nil.nil?               => true
- *
- * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
- */
-
-static VALUE
-rb_true(VALUE obj, SEL sel)
-{
-    return Qtrue;
-}
-
-/*
- * call_seq:
- *   nil.nil?               => true
- *   <anything_else>.nil?   => false
- *
- * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
- */
-
-
-static VALUE
-rb_false(VALUE obj, SEL sel)
-{
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     obj =~ other  => nil
- *  
- *  Pattern Match---Overridden by descendents (notably
- *  <code>Regexp</code> and <code>String</code>) to provide meaningful
- *  pattern-match semantics.
- */
-
-static VALUE
-rb_obj_match(VALUE obj1, SEL sel, VALUE obj2)
-{
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     obj !~ other  => nil
- *  
- *  Returns true if two objects does not match, using <i>=~</i> method.
- */
-
-static VALUE
-rb_obj_not_match(VALUE obj1, SEL sel, VALUE obj2)
-{
-    VALUE result = rb_funcall(obj1, id_match, 1, obj2);
-    return RTEST(result) ? Qfalse : Qtrue;
-}
-
-static VALUE
-rb_obj_cmp(VALUE obj1, SEL sel, VALUE obj2)
-{
-    if (rb_equal(obj1, obj2) == Qtrue) {
-	return INT2FIX(0);
-    }
-    return Qnil;
-}
-
-
-/***********************************************************************
- *
- * Document-class: Module
- *
- *  A <code>Module</code> is a collection of methods and constants. The
- *  methods in a module may be instance methods or module methods.
- *  Instance methods appear as methods in a class when the module is
- *  included, module methods do not. Conversely, module methods may be
- *  called without creating an encapsulating object, while instance
- *  methods may not. (See <code>Module#module_function</code>)
- *     
- *  In the descriptions that follow, the parameter <i>syml</i> refers
- *  to a symbol, which is either a quoted string or a
- *  <code>Symbol</code> (such as <code>:name</code>).
- *     
- *     module Mod
- *       include Math
- *       CONST = 1
- *       def meth
- *         #  ...
- *       end
- *     end
- *     Mod.class              #=> Module
- *     Mod.constants          #=> [:CONST, :PI, :E]
- *     Mod.instance_methods   #=> [:meth]
- *     
- */
-
-/*
- * call-seq:
- *   mod.to_s   => string
- *
- * Return a string representing this module or class. For basic
- * classes and modules, this is the name. For singletons, we
- * show information on the thing we're attached to as well.
- */
-
-static VALUE
-rb_mod_to_s(VALUE klass, SEL sel)
-{
-    if (RCLASS_SINGLETON(klass)) {
-	VALUE s = rb_usascii_str_new2("#<");
-	VALUE v = rb_iv_get(klass, "__attached__");
-
-	rb_str_cat2(s, "Class:");
-	switch (TYPE(v)) {
-	  case T_CLASS: case T_MODULE:
-	    rb_str_append(s, rb_inspect(v));
-	    break;
-	  default:
-	    rb_str_append(s, rb_any_to_s(v));
-	    break;
-	}
-	rb_str_cat2(s, ">");
-
-	return s;
-    }
-    return rb_str_dup(rb_class_name(klass));
-}
-
-static VALUE 
-rb_mod_included_modules_imp(VALUE recv, SEL sel)
-{
-    return rb_mod_included_modules(recv);
-}
-
-static VALUE
-rb_mod_ancestors_imp(VALUE self, SEL sel)
-{
-    return rb_mod_ancestors(self);
-}
-
-static VALUE
-rb_mod_ancestors_all_imp(VALUE self, SEL sel)
-{
-    return rb_mod_ancestors_nocopy(self);
-}
-
-static VALUE
-rb_mod_properties_imp(VALUE self, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    unsigned int count = 0;
-    objc_property_t *list = class_copyPropertyList((Class)self, &count);
-    if (list != NULL) {
-	for (unsigned int i = 0; i < count; i++) {
-	    rb_ary_push(ary, ID2SYM(rb_intern(property_getName(list[i]))));
-	}
-	free(list);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     mod.freeze
- *  
- *  Prevents further modifications to <i>mod</i>.
- */
-
-static VALUE
-rb_mod_freeze(VALUE mod, SEL sel)
-{
-    rb_class_name(mod);
-    return rb_obj_freeze(mod);
-}
-
-/*
- *  call-seq:
- *     mod === obj    => true or false
- *  
- *  Case Equality---Returns <code>true</code> if <i>anObject</i> is an
- *  instance of <i>mod</i> or one of <i>mod</i>'s descendents. Of
- *  limited use for modules, but can be used in <code>case</code>
- *  statements to classify objects by class.
- */
-
-static VALUE
-rb_mod_eqq(VALUE mod, SEL sel, VALUE arg)
-{
-    return rb_obj_is_kind_of(arg, mod);
-}
-
-/*
- * call-seq:
- *   mod <= other   =>  true, false, or nil
- *
- * Returns true if <i>mod</i> is a subclass of <i>other</i> or
- * is the same as <i>other</i>. Returns 
- * <code>nil</code> if there's no relationship between the two. 
- * (Think of the relationship in terms of the class definition: 
- * "class A<B" implies "A<B").
- *
- */
-
-static inline bool
-rb_class_mixin_inherited(VALUE mod, VALUE arg)
-{
-    VALUE ary = rb_attr_get(mod, idIncludedModules);
-    if (ary != Qnil) {
-	for (int i = 0; i < RARRAY_LEN(ary); i++) {
-	    if (RARRAY_AT(ary, i) == arg) {
-		return true;
-	    }
-	} 
-    }
-    return false;
-}
-
-VALUE
-rb_class_inherited_p(VALUE mod, VALUE arg)
-{
-    VALUE start = mod;
-
-    if (mod == arg) {
-	return Qtrue;
-    }
-    switch (TYPE(arg)) {
-	case T_MODULE:
-	case T_CLASS:
-	    break;
-	default:
-	    rb_raise(rb_eTypeError, "compared with non class/module");
-    }
-    while (mod) {
-	if (mod == arg || rb_class_mixin_inherited(mod, arg)) {
-	    return Qtrue;
-	}
-	mod = RCLASS_SUPER(mod);
-    }
-    /* not mod < arg; check if mod > arg */
-    while (arg) {
-	if (arg == start || rb_class_mixin_inherited(arg, start)) {
-	    return Qfalse;
-	}
-	arg = RCLASS_SUPER(arg);
-    }
-    return Qnil;
-}
-
-static VALUE
-rb_class_inherited_imp(VALUE mod, SEL sel, VALUE arg)
-{
-    return rb_class_inherited_p(mod, arg);
-}
-
-/*
- * call-seq:
- *   mod < other   =>  true, false, or nil
- *
- * Returns true if <i>mod</i> is a subclass of <i>other</i>. Returns 
- * <code>nil</code> if there's no relationship between the two. 
- * (Think of the relationship in terms of the class definition: 
- * "class A<B" implies "A<B").
- *
- */
-
-static VALUE
-rb_mod_lt(VALUE mod, SEL sel, VALUE arg)
-{
-    if (mod == arg) return Qfalse;
-    return rb_class_inherited_p(mod, arg);
-}
-
-
-/*
- * call-seq:
- *   mod >= other   =>  true, false, or nil
- *
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>, or the
- * two modules are the same. Returns 
- * <code>nil</code> if there's no relationship between the two. 
- * (Think of the relationship in terms of the class definition: 
- * "class A<B" implies "B>A").
- *
- */
-
-static VALUE
-rb_mod_ge(VALUE mod, SEL sel, VALUE arg)
-{
-    switch (TYPE(arg)) {
-      case T_MODULE:
-      case T_CLASS:
-	break;
-      default:
-	rb_raise(rb_eTypeError, "compared with non class/module");
-    }
-
-    return rb_class_inherited_p(arg, mod);
-}
-
-/*
- * call-seq:
- *   mod > other   =>  true, false, or nil
- *
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>. Returns 
- * <code>nil</code> if there's no relationship between the two. 
- * (Think of the relationship in terms of the class definition: 
- * "class A<B" implies "B>A").
- *
- */
-
-static VALUE
-rb_mod_gt(VALUE mod, SEL sel, VALUE arg)
-{
-    if (mod == arg) return Qfalse;
-    return rb_mod_ge(mod, 0, arg);
-}
-
-/*
- *  call-seq:
- *     mod <=> other_mod   => -1, 0, +1, or nil
- *  
- *  Comparison---Returns -1 if <i>mod</i> includes <i>other_mod</i>, 0 if
- *  <i>mod</i> is the same as <i>other_mod</i>, and +1 if <i>mod</i> is
- *  included by <i>other_mod</i> or if <i>mod</i> has no relationship with
- *  <i>other_mod</i>. Returns <code>nil</code> if <i>other_mod</i> is
- *  not a module.
- */
-
-static VALUE
-rb_mod_cmp(VALUE mod, SEL sel, VALUE arg)
-{
-    VALUE cmp;
-
-    if (mod == arg) return INT2FIX(0);
-    switch (TYPE(arg)) {
-      case T_MODULE:
-      case T_CLASS:
-	break;
-      default:
-	return Qnil;
-    }
-
-    cmp = rb_class_inherited_p(mod, arg);
-    if (NIL_P(cmp)) return Qnil;
-    if (cmp) {
-	return INT2FIX(-1);
-    }
-    return INT2FIX(1);
-}
-
-static VALUE
-rb_module_s_alloc(VALUE klass, SEL sel)
-{
-    return rb_module_new();
-}
-
-static VALUE
-rb_class_s_alloc(VALUE klass, SEL sel)
-{
-    return rb_class_boot(0);
-}
-
-/*
- *  call-seq:
- *    Module.new                  => mod
- *    Module.new {|mod| block }   => mod
- *  
- *  Creates a new anonymous module. If a block is given, it is passed
- *  the module object, and the block is evaluated in the context of this
- *  module using <code>module_eval</code>.
- *     
- *     Fred = Module.new do
- *       def meth1
- *         "hello"
- *       end
- *       def meth2
- *         "bye"
- *       end
- *     end
- *     a = "my string"
- *     a.extend(Fred)   #=> "my string"
- *     a.meth1          #=> "hello"
- *     a.meth2          #=> "bye"
- */
-
-VALUE rb_mod_module_exec(VALUE mod, SEL sel, int argc, VALUE *argv);
-
-VALUE
-rb_mod_initialize(VALUE module, SEL sel)
-{
-    static bool initialized = false;
-    if (!initialized) {
-	initialized = true;
-	rb_objc_force_class_initialize((Class)module);
-	initialized = false;
-
-	if (rb_block_given_p()) {
-	    rb_mod_module_exec(module, 0, 1, &module);
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *    class Something
- *      def setThing(thing, forIndex: i); @things[i] = thing; end
- *      method_signature :'setThing:forIndex:', 'v@:@i'
- *    end
- *
- *  Changes the type signature stored in the Objective-C runtime for the
- *  given method.
- *
- */
-static VALUE
-rb_mod_method_signature(VALUE module, SEL sel, VALUE mid, VALUE sim)
-{
-    // TODO
-    abort();
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     Class.new(super_class=Object)   =>    a_class
- *  
- *  Creates a new anonymous (unnamed) class with the given superclass
- *  (or <code>Object</code> if no parameter is given). You can give a
- *  class a name by assigning the class object to a constant.
- *     
- */
-
-static VALUE
-rb_class_initialize(int argc, VALUE *argv, VALUE klass)
-{
-    VALUE super;
-
-    if (argc == 0) {
-	super = rb_cObject;
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &super);
-	rb_check_inheritable(super);
-    }
-    if (super == rb_cObject) {
-	super = rb_cRubyObject;
-    }
-    RCLASS_SET_SUPER(klass, super);
-    rb_objc_class_sync_version((Class)klass, (Class)super);
-
-    rb_class_inherited(super, klass);
-    rb_mod_initialize(klass, 0);
-
-    return klass;
-}
-
-/*
- *  call-seq:
- *     class.allocate()   =>   obj
- *  
- *  Allocates space for a new object of <i>class</i>'s class. The
- *  returned object must be an instance of <i>class</i>.
- *     
- */
-
-static inline VALUE
-rb_obj_alloc0(VALUE klass)
-{
-    if (RCLASS_SINGLETON(klass)) {
-	rb_raise(rb_eTypeError, "can't create instance of singleton class");
-    }
-
-    if ((RCLASS_VERSION(*(void **)klass) & RCLASS_HAS_ROBJECT_ALLOC) == RCLASS_HAS_ROBJECT_ALLOC) {
-	// Fast path!
-	return rb_vm_new_rb_object(klass);
-    }
-    return rb_vm_call(klass, selAlloc, 0, NULL);
-}
-
-VALUE
-rb_obj_alloc(VALUE klass)
-{
-    return rb_obj_alloc0(klass);
-}
-
-static VALUE
-rb_obj_alloc_imp(VALUE klass, SEL sel)
-{
-    return rb_obj_alloc0(klass);
-}
-
-/*
- *  call-seq:
- *     class.new(args, ...)    =>  obj
- *  
- *  Calls <code>allocate</code> to create a new object of
- *  <i>class</i>'s class, then invokes that object's
- *  <code>initialize</code> method, passing it <i>args</i>.
- *  This is the method that ends up getting called whenever
- *  an object is constructed using .new.
- *     
- */
-
-static inline VALUE
-rb_class_new_instance0(int argc, VALUE *argv, VALUE klass)
-{
-    VALUE obj = rb_obj_alloc0(klass);
-
-    /* Because we cannot override +[NSObject initialize] */
-    if (klass == rb_cClass) {
-	return rb_class_initialize(argc, argv, obj);
-    }
-
-    //init_obj = rb_obj_call_init(obj, argc, argv);
-
-    rb_vm_block_t *block = rb_vm_current_block();
-    if (argc == 0) {
-	rb_vm_call2(block, obj, CLASS_OF(obj), selInitialize, argc, argv);
-    }
-    else {
-	rb_vm_call2(block, obj, CLASS_OF(obj), selInitialize2, argc, argv);
-    }
-
-    return obj;
-}
-
-VALUE
-rb_class_new_instance_imp(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    return rb_class_new_instance0(argc, argv, klass);
-}
-
-VALUE
-rb_class_new_instance(int argc, VALUE *argv, VALUE klass)
-{
-    return rb_class_new_instance0(argc, argv, klass);
-}
-
-/*
- *  call-seq:
- *     attr_reader(symbol, ...)    => nil
- *     attr(symbol, ...)             => nil
- *  
- *  Creates instance variables and corresponding methods that return the
- *  value of each instance variable. Equivalent to calling
- *  ``<code>attr</code><i>:name</i>'' on each name in turn.
- */
-
-static VALUE
-rb_mod_attr_reader(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	rb_attr(klass, rb_to_id(argv[i]), Qtrue, Qfalse, Qtrue);
-    }
-    return Qnil;
-}
-
-static VALUE
-rb_mod_attr(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
-	rb_warning("optional boolean argument is obsoleted");
-	rb_attr(klass, rb_to_id(argv[0]), 1, RTEST(argv[1]), Qtrue);
-	return Qnil;
-    }
-    return rb_mod_attr_reader(klass, 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *      attr_writer(symbol, ...)    => nil
- *  
- *  Creates an accessor method to allow assignment to the attribute
- *  <i>aSymbol</i><code>.id2name</code>.
- */
-
-static VALUE
-rb_mod_attr_writer(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	rb_attr(klass, rb_to_id(argv[i]), Qfalse, Qtrue, Qtrue);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     attr_accessor(symbol, ...)    => nil
- *  
- *  Defines a named attribute for this module, where the name is
- *  <i>symbol.</i><code>id2name</code>, creating an instance variable
- *  (<code>@name</code>) and a corresponding access method to read it.
- *  Also creates a method called <code>name=</code> to set the attribute.
- *     
- *     module Mod
- *       attr_accessor(:one, :two)
- *     end
- *     Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
- */
-
-static VALUE
-rb_mod_attr_accessor(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	rb_attr(klass, rb_to_id(argv[i]), Qtrue, Qtrue, Qtrue);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     mod.const_get(sym, inherit=true)    => obj
- *  
- *  Returns the value of the named constant in <i>mod</i>.
- *     
- *     Math.const_get(:PI)   #=> 3.14159265358979
- *
- *  If the constant is not defined or is defined by the ancestors and
- *  +inherit+ is false, +NameError+ will be raised.
- */
-
-static VALUE
-rb_mod_const_get(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    VALUE name, recur;
-    ID id;
-
-    if (argc == 1) {
-	name = argv[0];
-	recur = Qtrue;
-    }
-    else {
-	rb_scan_args(argc, argv, "11", &name, &recur);
-    }
-    id = rb_to_id(name);
-    if (!rb_is_const_id(id)) {
-	rb_name_error(id, "wrong constant name %s", rb_id2name(id));
-    }
-    return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
-}
-
-/*
- *  call-seq:
- *     mod.const_set(sym, obj)    => obj
- *  
- *  Sets the named constant to the given object, returning that object.
- *  Creates a new constant if no constant with the given name previously
- *  existed.
- *     
- *     Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0)   #=> 3.14285714285714
- *     Math::HIGH_SCHOOL_PI - Math::PI              #=> 0.00126448926734968
- */
-
-static VALUE
-rb_mod_const_set(VALUE mod, SEL sel, VALUE name, VALUE value)
-{
-    ID id = rb_to_id(name);
-
-    if (!rb_is_const_id(id)) {
-	rb_name_error(id, "wrong constant name %s", rb_id2name(id));
-    }
-    rb_const_set(mod, id, value);
-    return value;
-}
-
-/*
- *  call-seq:
- *     mod.const_defined?(sym, inherit=true)   => true or false
- *  
- *  Returns <code>true</code> if a constant with the given name is
- *  defined by <i>mod</i>, or its ancestors if +inherit+ is not false.
- *     
- *     Math.const_defined? "PI"   #=> true
- *     IO.const_defined? "SYNC"   #=> true
- *     IO.const_defined? "SYNC", false   #=> false
- */
-
-static VALUE
-rb_mod_const_defined(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    VALUE name, recur;
-    ID id;
-
-    if (argc == 1) {
-	name = argv[0];
-	recur = Qtrue;
-    }
-    else {
-	rb_scan_args(argc, argv, "11", &name, &recur);
-    }
-    id = rb_to_id(name);
-    if (!rb_is_const_id(id)) {
-	rb_name_error(id, "wrong constant name %s", rb_id2name(id));
-    }
-    return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
-}
-
-static VALUE
-rb_mod_remove_const_imp(VALUE mod, SEL sel, VALUE name)
-{
-    return rb_mod_remove_const(mod, name);
-}
-
-/*
- *  call-seq:
- *     obj.methods    => array
- *  
- *  Returns a list of the names of methods publicly accessible in
- *  <i>obj</i>. This will include all the methods accessible in
- *  <i>obj</i>'s ancestors.
- *     
- *     class Klass
- *       def kMethod()
- *       end
- *     end
- *     k = Klass.new
- *     k.methods[0..9]    #=> ["kMethod", "freeze", "nil?", "is_a?", 
- *                        #    "class", "instance_variable_set",
- *                        #    "methods", "extend", "__send__", "instance_eval"]
- *     k.methods.length   #=> 42
- */
-
-VALUE rb_class_instance_methods(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_obj_methods(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE recur, objc_methods;
-    VALUE args[2];
-
-    if (argc == 0) {
-	recur = Qtrue;
-	objc_methods = Qfalse;
-    }
-    else {
-	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
-    }
-
-    args[0] = recur;
-    args[1] = objc_methods;
-
-    return rb_class_instance_methods(CLASS_OF(obj), 0, 2, args);
-}
-
-/*
- *  call-seq:
- *     obj.protected_methods(all=true)   => array
- *  
- *  Returns the list of protected methods accessible to <i>obj</i>. If
- *  the <i>all</i> parameter is set to <code>false</code>, only those methods
- *  in the receiver will be listed.
- */
-
-VALUE rb_class_protected_instance_methods(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_obj_protected_methods(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {		/* hack to stop warning */
-	VALUE args[1];
-
-	args[0] = Qtrue;
-	return rb_class_protected_instance_methods(CLASS_OF(obj), 0, 1, args);
-    }
-    return rb_class_protected_instance_methods(CLASS_OF(obj), 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     obj.private_methods(all=true)   => array
- *  
- *  Returns the list of private methods accessible to <i>obj</i>. If
- *  the <i>all</i> parameter is set to <code>false</code>, only those methods
- *  in the receiver will be listed.
- */
-
-VALUE rb_class_private_instance_methods(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_obj_private_methods(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {		/* hack to stop warning */
-	VALUE args[1];
-
-	args[0] = Qtrue;
-	return rb_class_private_instance_methods(CLASS_OF(obj), 0, 1, args);
-    }
-    return rb_class_private_instance_methods(CLASS_OF(obj), 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     obj.public_methods(all=true)   => array
- *  
- *  Returns the list of public methods accessible to <i>obj</i>. If
- *  the <i>all</i> parameter is set to <code>false</code>, only those methods
- *  in the receiver will be listed.
- */
-
-VALUE rb_class_public_instance_methods(VALUE, SEL, int, VALUE *);
-
-static VALUE
-rb_obj_public_methods(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {		/* hack to stop warning */
-	VALUE args[1];
-
-	args[0] = Qtrue;
-	return rb_class_public_instance_methods(CLASS_OF(obj), 0, 1, args);
-    }
-    return rb_class_public_instance_methods(CLASS_OF(obj), 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     obj.instance_variable_get(symbol)    => obj
- *
- *  Returns the value of the given instance variable, or nil if the
- *  instance variable is not set. The <code>@</code> part of the
- *  variable name should be included for regular instance
- *  variables. Throws a <code>NameError</code> exception if the
- *  supplied symbol is not valid as an instance variable name.
- *     
- *     class Fred
- *       def initialize(p1, p2)
- *         @a, @b = p1, p2
- *       end
- *     end
- *     fred = Fred.new('cat', 99)
- *     fred.instance_variable_get(:@a)    #=> "cat"
- *     fred.instance_variable_get("@b")   #=> 99
- */
-
-static VALUE
-rb_obj_ivar_get(VALUE obj, SEL sel, VALUE iv)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_instance_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
-    }
-    return rb_ivar_get(obj, id);
-}
-
-/*
- *  call-seq:
- *     obj.instance_variable_set(symbol, obj)    => obj
- *  
- *  Sets the instance variable names by <i>symbol</i> to
- *  <i>object</i>, thereby frustrating the efforts of the class's
- *  author to attempt to provide proper encapsulation. The variable
- *  did not have to exist prior to this call.
- *     
- *     class Fred
- *       def initialize(p1, p2)
- *         @a, @b = p1, p2
- *       end
- *     end
- *     fred = Fred.new('cat', 99)
- *     fred.instance_variable_set(:@a, 'dog')   #=> "dog"
- *     fred.instance_variable_set(:@c, 'cat')   #=> "cat"
- *     fred.inspect                             #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
- */
-
-static VALUE
-rb_obj_ivar_set(VALUE obj, SEL sel, VALUE iv, VALUE val)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_instance_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
-    }
-    return rb_ivar_set(obj, id, val);
-}
-
-/*
- *  call-seq:
- *     obj.instance_variable_defined?(symbol)    => true or false
- *
- *  Returns <code>true</code> if the given instance variable is
- *  defined in <i>obj</i>.
- *
- *     class Fred
- *       def initialize(p1, p2)
- *         @a, @b = p1, p2
- *       end
- *     end
- *     fred = Fred.new('cat', 99)
- *     fred.instance_variable_defined?(:@a)    #=> true
- *     fred.instance_variable_defined?("@b")   #=> true
- *     fred.instance_variable_defined?("@c")   #=> false
- */
-
-static VALUE
-rb_obj_ivar_defined(VALUE obj, SEL sel, VALUE iv)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_instance_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
-    }
-    return rb_ivar_defined(obj, id);
-}
-
-/*
- *  call-seq:
- *     mod.class_variable_get(symbol)    => obj
- *  
- *  Returns the value of the given class variable (or throws a
- *  <code>NameError</code> exception). The <code>@@</code> part of the
- *  variable name should be included for regular class variables
- *     
- *     class Fred
- *       @@foo = 99
- *     end
- *     Fred.class_variable_get(:@@foo)     #=> 99
- */
-
-static VALUE
-rb_mod_cvar_get(VALUE obj, SEL sel, VALUE iv)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
-    }
-    return rb_cvar_get(obj, id);
-}
-
-/*
- *  call-seq:
- *     obj.class_variable_set(symbol, obj)    => obj
- *  
- *  Sets the class variable names by <i>symbol</i> to
- *  <i>object</i>.
- *     
- *     class Fred
- *       @@foo = 99
- *       def foo
- *         @@foo
- *       end
- *     end
- *     Fred.class_variable_set(:@@foo, 101)     #=> 101
- *     Fred.new.foo                             #=> 101
- */
-
-static VALUE
-rb_mod_cvar_set(VALUE obj, SEL sel, VALUE iv, VALUE val)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
-    }
-    rb_cvar_set(obj, id, val);
-    return val;
-}
-
-/*
- *  call-seq:
- *     obj.class_variable_defined?(symbol)    => true or false
- *
- *  Returns <code>true</code> if the given class variable is defined
- *  in <i>obj</i>.
- *
- *     class Fred
- *       @@foo = 99
- *     end
- *     Fred.class_variable_defined?(:@@foo)    #=> true
- *     Fred.class_variable_defined?(:@@bar)    #=> false
- */
-
-static VALUE
-rb_mod_cvar_defined(VALUE obj, SEL sel, VALUE iv)
-{
-    ID id = rb_to_id(iv);
-
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
-    }
-    return rb_cvar_defined(obj, id);
-}
-
-static VALUE
-convert_type(VALUE val, const char *tname, const char *method, int raise)
-{
-//    ID m;
-
-//    m = rb_intern(method);
-//    if (!rb_obj_respond_to(val, m, Qtrue)) {
-
-    SEL sel = sel_registerName(method);
-    if (!rb_vm_respond_to(val, sel, true)) {
-	if (raise) {
-	    rb_raise(rb_eTypeError, "can't convert %s into %s",
-		    NIL_P(val) ? "nil" :
-		    val == Qtrue ? "true" :
-		    val == Qfalse ? "false" :
-		    rb_obj_classname(val), 
-		    tname);
-	}
-	else {
-	    return Qnil;
-	}
-    }
-    return rb_vm_call(val, sel, 0, NULL);
-}
-
-VALUE
-rb_convert_type(VALUE val, int type, const char *tname, const char *method)
-{
-    if (TYPE(val) == type) {
-	return val;
-    }
-    VALUE v = convert_type(val, tname, method, TRUE);
-    if (TYPE(v) != type) {
-	const char *cname = rb_obj_classname(val);
-	rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
-		 cname, tname, cname, method, rb_obj_classname(v));
-    }
-    return v;
-}
-
-VALUE
-rb_check_convert_type(VALUE val, int type, const char *tname, const char *method)
-{
-    VALUE v;
-
-    /* always convert T_DATA */
-    if (TYPE(val) == type && type != T_DATA) {
-	return val;
-    }
-    v = convert_type(val, tname, method, FALSE);
-    if (NIL_P(v)) {
-	return Qnil;
-    }
-    if (TYPE(v) != type) {
-	const char *cname = rb_obj_classname(val);
-	rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
-		 cname, tname, cname, method, rb_obj_classname(v));
-    }
-    return v;
-}
-
-
-static VALUE
-rb_to_integer(VALUE val, const char *method)
-{
-    VALUE v;
-
-    if (FIXNUM_P(val)) return val;
-    v = convert_type(val, "Integer", method, TRUE);
-    if (!rb_obj_is_kind_of(v, rb_cInteger)) {
-	const char *cname = rb_obj_classname(val);
-	rb_raise(rb_eTypeError, "can't convert %s to Integer (%s#%s gives %s)",
-		 cname, cname, method, rb_obj_classname(v));
-    }
-    return v;
-}
-
-VALUE
-rb_check_to_integer(VALUE val, const char *method)
-{
-    VALUE v;
-
-    if (FIXNUM_P(val)) return val;
-    v = convert_type(val, "Integer", method, FALSE);
-    if (!rb_obj_is_kind_of(v, rb_cInteger)) {
-	return Qnil;
-    }
-    return v;
-}
-
-VALUE
-rb_to_int(VALUE val)
-{
-    return rb_to_integer(val, "to_int");
-}
-
-static VALUE
-rb_convert_to_integer(VALUE val, int base)
-{
-    VALUE tmp;
-
-    switch (TYPE(val)) {
-	case T_FLOAT:
-	    if (base != 0) {
-		goto arg_error;
-	    }
-	    if (RFLOAT_VALUE(val) <= (double)FIXNUM_MAX
-		    && RFLOAT_VALUE(val) >= (double)FIXNUM_MIN) {
-		break;
-	    }
-	    return rb_dbl2big(RFLOAT_VALUE(val));
-
-	case T_FIXNUM:
-	case T_BIGNUM:
-	    if (base != 0) {
-		goto arg_error;
-	    }
-	    return val;
-
-	case T_STRING:
-string_conv:
-	    return rb_str_to_inum(val, base, TRUE);
-
-	case T_NIL:
-	    if (base != 0) {
-		goto arg_error;
-	    }
-	    rb_raise(rb_eTypeError, "can't convert nil into Integer");
-	    break;
-
-	default:
-	    break;
-    }
-    if (base != 0) {
-	tmp = rb_check_string_type(val);
-	if (!NIL_P(tmp)) {
-	    goto string_conv;
-	}
-arg_error:
-	rb_raise(rb_eArgError, "base specified for non string value");
-    }
-    tmp = convert_type(val, "Integer", "to_int", FALSE);
-    if (NIL_P(tmp)) {
-	return rb_to_integer(val, "to_i");
-    }
-    return tmp;
-
-}
-
-VALUE
-rb_Integer(VALUE val)
-{
-    return rb_convert_to_integer(val, 0);
-}
-
-/*
- *  call-seq:
- *     Integer(arg)    => integer
- *  
- *  Converts <i>arg</i> to a <code>Fixnum</code> or <code>Bignum</code>.
- *  Numeric types are converted directly (with floating point numbers
- *  being truncated). If <i>arg</i> is a <code>String</code>, leading
- *  radix indicators (<code>0</code>, <code>0b</code>, and
- *  <code>0x</code>) are honored. Others are converted using
- *  <code>to_int</code> and <code>to_i</code>. This behavior is
- *  different from that of <code>String#to_i</code>.
- *     
- *     Integer(123.999)    #=> 123
- *     Integer("0x1a")     #=> 26
- *     Integer(Time.new)   #=> 1204973019
- */
-
-static VALUE
-rb_f_integer(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE arg = Qnil;
-    int base = 0;
-
-    switch (argc) {
-	case 2:
-	    base = NUM2INT(argv[1]);
-	case 1:
-	    arg = argv[0];
-	    break;
-	default:
-	    // Should cause ArgumentError.
-	    rb_scan_args(argc, argv, "11", NULL, NULL);
-    }
-    return rb_convert_to_integer(arg, base);
-}
-
-double
-rb_cstr_to_dbl(const char *p, int badcheck)
-{
-    const char *q;
-    char *end;
-    double d;
-    const char *ellipsis = "";
-    int w;
-    enum {max_width = 20};
-#define OutOfRange() ((end - p > max_width) ? \
-		      (w = max_width, ellipsis = "...") : \
-		      (w = (int)(end - p), ellipsis = ""))
-
-    if (!p) return 0.0;
-    q = p;
-    while (ISSPACE(*p)) p++;
-
-    if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
-	return 0.0;
-    }
-
-    d = ruby_strtod(p, &end);
-    if (errno == ERANGE) {
-	OutOfRange();
-	rb_warning("Float %.*s%s out of range", w, p, ellipsis);
-	errno = 0;
-    }
-    if (p == end) {
-	if (badcheck) {
-	  bad:
-	    rb_invalid_str(q, "Float()");
-	}
-	return d;
-    }
-    if (*end) {
-	char buf[DBL_DIG * 4 + 10];
-	char *n = buf;
-	char *e = buf + sizeof(buf) - 1;
-	char prev = 0;
-
-	while (p < end && n < e) prev = *n++ = *p++;
-	while (*p) {
-	    if (*p == '_') {
-		/* remove underscores between digits */
-		if (badcheck) {
-		    if (n == buf || !ISDIGIT(prev)) goto bad;
-		    ++p;
-		    if (!ISDIGIT(*p)) goto bad;
-		}
-		else {
-		    while (*++p == '_');
-		    continue;
-		}
-	    }
-	    prev = *p++;
-	    if (n < e) *n++ = prev;
-	}
-	*n = '\0';
-	p = buf;
-
-	if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
-	    return 0.0;
-	}
-
-	d = ruby_strtod(p, &end);
-	if (errno == ERANGE) {
-	    OutOfRange();
-	    rb_warning("Float %.*s%s out of range", w, p, ellipsis);
-	    errno = 0;
-	}
-	if (badcheck) {
-	    if (!end || p == end) goto bad;
-	    while (*end && ISSPACE(*end)) end++;
-	    if (*end) goto bad;
-	}
-    }
-    if (errno == ERANGE) {
-	errno = 0;
-	OutOfRange();
-	rb_raise(rb_eArgError, "Float %.*s%s out of range", w, q, ellipsis);
-    }
-    return d;
-}
-double
-rb_str_to_dbl(VALUE str, int badcheck)
-{
-    const char *s;
-    long len;
-
-    StringValue(str);
-    s = RSTRING_PTR(str);
-    len = RSTRING_LEN(str);
-    if (s) {
-	if (badcheck && memchr(s, '\0', len)) {
-	    rb_raise(rb_eArgError, "string for Float contains null byte");
-	}
-	if (s[len]) {		/* no sentinel somehow */
-	    char *p = ALLOCA_N(char, len+1);
-
-	    MEMCPY(p, s, char, len);
-	    p[len] = '\0';
-	    s = p;
-	}
-    }
-    return rb_cstr_to_dbl(s, badcheck);
-}
-
-VALUE
-rb_Float(VALUE val)
-{
-    switch (TYPE(val)) {
-      case T_FIXNUM:
-	return DOUBLE2NUM((double)FIX2LONG(val));
-
-      case T_FLOAT:
-	return val;
-
-      case T_BIGNUM:
-	return DOUBLE2NUM(rb_big2dbl(val));
-
-      case T_STRING:
-	return DOUBLE2NUM(rb_str_to_dbl(val, 1));
-
-      case T_NIL:
-	rb_raise(rb_eTypeError, "can't convert nil into Float");
-	break;
-
-      default:
-	return rb_convert_type(val, T_FLOAT, "Float", "to_f");
-    }
-}
-
-/*
- *  call-seq:
- *     Float(arg)    => float
- *  
- *  Returns <i>arg</i> converted to a float. Numeric types are converted
- *  directly, the rest are converted using <i>arg</i>.to_f. As of Ruby
- *  1.8, converting <code>nil</code> generates a <code>TypeError</code>.
- *     
- *     Float(1)           #=> 1.0
- *     Float("123.456")   #=> 123.456
- */
-
-static VALUE
-rb_f_float(VALUE obj, SEL sel, VALUE arg)
-{
-    return rb_Float(arg);
-}
-
-VALUE
-rb_to_float(VALUE val)
-{
-    if (TYPE(val) ==  T_FLOAT) return val;
-    if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
-	rb_raise(rb_eTypeError, "can't convert %s into Float",
-		 NIL_P(val) ? "nil" :
-		 val ==  Qtrue ? "true" :
-		 val ==  Qfalse ? "false" :
-		 rb_obj_classname(val));
-    }
-    return rb_convert_type(val, T_FLOAT, "Float", "to_f");
-}
-
-VALUE
-rb_check_to_float(VALUE val)
-{
-    if (TYPE(val) == T_FLOAT) {
-	return val;
-    }
-    if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
-        return Qnil;
-    }
-    return rb_check_convert_type(val, T_FLOAT, "Float", "to_f");
-}
-
-double
-rb_num2dbl(VALUE val)
-{
-    switch (TYPE(val)) {
-      case T_FLOAT:
-	return RFLOAT_VALUE(val);
-
-      case T_STRING:
-	rb_raise(rb_eTypeError, "no implicit conversion to float from string");
-	break;
-
-      case T_NIL:
-	rb_raise(rb_eTypeError, "no implicit conversion to float from nil");
-	break;
-
-      default:
-	break;
-    }
-
-    return RFLOAT_VALUE(rb_Float(val));
-}
-
-const char*
-rb_str2cstr(VALUE str, long *len)
-{
-    StringValue(str);
-    if (len) *len = RSTRING_LEN(str);
-    else if (RTEST(ruby_verbose) && RSTRING_LEN(str) != strlen(RSTRING_PTR(str))) {
-	rb_warn("string contains \\0 character");
-    }
-    return RSTRING_PTR(str);
-}
-
-VALUE
-rb_String(VALUE val)
-{
-    return rb_convert_type(val, T_STRING, "String", "to_s");
-}
-
-/*
- *  call-seq:
- *     String(arg)   => string
- *  
- *  Converts <i>arg</i> to a <code>String</code> by calling its
- *  <code>to_s</code> method.
- *     
- *     String(self)        #=> "main"
- *     String(self.class)  #=> "Object"
- *     String(123456)      #=> "123456"
- */
-
-static VALUE
-rb_f_string(VALUE obj, SEL sel, VALUE arg)
-{
-    return rb_String(arg);
-}
-
-VALUE
-rb_Array(VALUE val)
-{
-    VALUE tmp = rb_check_array_type(val);
-
-    if (NIL_P(tmp)) {
-	tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a");
-	if (NIL_P(tmp)) {
-	    return rb_ary_new4(1, &val);
-	}
-    }
-    return tmp;
-}
-
-/*
- *  call-seq:
- *     Array(arg)    => array
- *  
- *  Returns <i>arg</i> as an <code>Array</code>. First tries to call
- *  <i>arg</i><code>.to_ary</code>, then <i>arg</i><code>.to_a</code>.
- *     
- *     Array(1..5)   #=> [1, 2, 3, 4, 5]
- */
-
-static VALUE
-rb_f_array(VALUE obj, SEL sel, VALUE arg)
-{
-    return rb_Array(arg);
-}
-
-static VALUE
-boot_defclass(const char *name, VALUE super)
-{
-    ID id = rb_intern(name);
-    extern st_table *rb_class_tbl;
-    VALUE obj = rb_objc_create_class(name, super);
-    st_add_direct(rb_class_tbl, id, obj);
-    rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
-    return obj;
-}
-
-static VALUE
-rb_class_is_meta(VALUE klass, SEL sel)
-{
-    return RCLASS_META(klass) ? Qtrue : Qfalse;
-}
-
-/*
- *  Document-class: Class
- *
- *  Classes in Ruby are first-class objects---each is an instance of
- *  class <code>Class</code>.
- *     
- *  When a new class is created (typically using <code>class Name ...
- *  end</code>), an object of type <code>Class</code> is created and
- *  assigned to a global constant (<code>Name</code> in this case). When
- *  <code>Name.new</code> is called to create a new object, the
- *  <code>new</code> method in <code>Class</code> is run by default.
- *  This can be demonstrated by overriding <code>new</code> in
- *  <code>Class</code>:
- *     
- *     class Class
- *        alias oldNew  new
- *        def new(*args)
- *          print "Creating a new ", self.name, "\n"
- *          oldNew(*args)
- *        end
- *      end
- *     
- *     
- *      class Name
- *      end
- *     
- *     
- *      n = Name.new
- *     
- *  <em>produces:</em>
- *     
- *     Creating a new Name
- *     
- *  Classes, modules, and objects are interrelated. In the diagram
- *  that follows, the vertical arrows represent inheritance, and the
- *  parentheses meta-classes. All metaclasses are instances 
- *  of the class `Class'.
- *
- *                             +-----------------+
- *                            |                  |
- *           BasicObject-->(BasicObject)         |
- *                ^           ^                  |
- *                |           |                  |
- *              Object---->(Object)              |
- *               ^  ^        ^  ^                |
- *               |  |        |  |                |
- *               |  |  +-----+  +---------+      |
- *               |  |  |                  |      |
- *               |  +-----------+         |      |
- *               |     |        |         |      |
- *        +------+     |     Module--->(Module)  |
- *        |            |        ^         ^      |
- *   OtherClass-->(OtherClass)  |         |      |
- *                              |         |      |
- *                            Class---->(Class)  |
- *                              ^                |
- *                              |                |
- *                              +----------------+
- */
-
-
-/*
- *  <code>BasicObject</code> is the parent class of all classes in Ruby.
- *  It's an explicit blank class.  <code>Object</code>, the root of Ruby's
- *  class hierarchy is a direct subclass of <code>BasicObject</code>.  Its
- *  methods are therefore available to all objects unless explicitly
- *  overridden.
- *     
- *  <code>Object</code> mixes in the <code>Kernel</code> module, making
- *  the built-in kernel functions globally accessible. Although the
- *  instance methods of <code>Object</code> are defined by the
- *  <code>Kernel</code> module, we have chosen to document them here for
- *  clarity.
- *     
- *  In the descriptions of Object's methods, the parameter <i>symbol</i> refers
- *  to a symbol, which is either a quoted string or a
- *  <code>Symbol</code> (such as <code>:name</code>).
- */
-
-VALUE rb_f_sprintf_imp(VALUE recv, SEL sel, int argc, VALUE *argv);
-
-void
-Init_Object(void)
-{
-    rb_cObject = rb_cNSObject = (VALUE)objc_getClass("NSObject");
-    rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
-    rb_set_class_path(rb_cObject, rb_cObject, "NSObject");
-    rb_cBasicObject = (VALUE)objc_duplicateClass((Class)rb_cObject,
-	    "BasicObject", 0);
-    rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
-    rb_cModule = boot_defclass("Module", rb_cNSObject);
-    rb_define_object_special_methods(rb_cModule);
-    rb_cClass =  boot_defclass("Class",  rb_cModule);
-    rb_cRubyObject = boot_defclass("RubyObject", rb_cObject);
-    RCLASS_SET_VERSION_FLAG(rb_cRubyObject, RCLASS_IS_SINGLETON);
-    RCLASS_SET_VERSION_FLAG(rb_cRubyObject, RCLASS_IS_OBJECT_SUBCLASS);
-    rb_define_object_special_methods(rb_cRubyObject);
-    rb_objc_install_NSObject_special_methods((Class)rb_cRubyObject);
-
-    eqlSel = sel_registerName("eql?:");
-
-    rb_objc_define_method(*(VALUE *)rb_cModule, "alloc", rb_module_s_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cClass, "alloc", rb_class_s_alloc, 0);
-    rb_objc_define_method(rb_cClass, "new", rb_class_new_instance_imp, -1);
-
-    // At this point, methods defined on Class or Module will be automatically
-    // added to NSObject's metaclass.
-    rb_include_module2(*(VALUE *)rb_cNSObject, 0, rb_cClass, false, false);
-    rb_include_module2(*(VALUE *)rb_cNSObject, 0, rb_cModule, false, false);
-
-    rb_objc_define_direct_method(*(VALUE *)rb_cNSObject, "new:", rb_class_new_instance_imp, -1);
-
-    rb_objc_define_private_method(rb_cNSObject, "initialize", rb_obj_dummy, 0);
-    rb_objc_define_method(rb_cRubyObject, "==", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cNSObject, "equal?", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cNSObject, "==", rb_nsobj_equal, 1);
-    rb_objc_define_method(rb_cNSObject, "!", rb_obj_not, 0);
-    rb_objc_define_method(rb_cNSObject, "!=", rb_obj_not_equal, 1);
-
-    rb_objc_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
-    rb_objc_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cBasicObject, "!", rb_obj_not, 0);
-    rb_objc_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1);
-
-    rb_objc_define_private_method(rb_cNSObject, "singleton_method_added", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cNSObject, "singleton_method_removed", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cNSObject, "singleton_method_undefined", rb_obj_dummy2, 1);
-
-    rb_objc_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy2, 1);
-
-    rb_mKernel = rb_define_module("Kernel");
-    rb_include_module(rb_cNSObject, rb_mKernel);
-    rb_objc_define_private_method(rb_cClass, "inherited", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "included", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "extended", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "method_added", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "method_removed", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy2, 1);
-    rb_objc_define_private_method(rb_cModule, "method_signature", rb_mod_method_signature, 2);
-
-    rb_objc_define_method(rb_mKernel, "nil?", rb_false, 0);
-    rb_objc_define_method(rb_mKernel, "===", rb_equal_imp, 1); 
-    rb_objc_define_method(rb_mKernel, "=~", rb_obj_match, 1);
-    rb_objc_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
-    rb_objc_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cNSObject, "eql?", rb_nsobj_equal, 1);
-    rb_objc_define_method(rb_mKernel, "<=>", rb_obj_cmp, 1);
-
-    rb_objc_define_method(rb_cNSObject, "clone", rb_obj_clone_imp, 0);
-    rb_objc_define_method(rb_cNSObject, "dup", rb_nsobj_dup, 0);
-    rb_objc_define_method(rb_cNSObject, "__type__", rb_obj_type, 0);
-
-    rb_objc_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
-    rb_objc_define_method(rb_mKernel, "taint", rb_obj_taint_m, 0);
-    rb_objc_define_method(rb_mKernel, "tainted?", rb_obj_tainted_p, 0);
-    rb_objc_define_method(rb_mKernel, "untaint", rb_obj_untaint_m, 0);
-    rb_objc_define_method(rb_mKernel, "freeze", rb_obj_freeze_m, 0);
-    rb_objc_define_method(rb_mKernel, "frozen?", rb_obj_frozen, 0);
-    rb_objc_define_method(rb_mKernel, "trust", rb_obj_trust_imp, 0);
-    rb_objc_define_method(rb_mKernel, "untrust", rb_obj_untrust_imp, 0);
-    rb_objc_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted_imp, 0);
-
-    rb_objc_define_method(rb_mKernel, "to_s", rb_any_to_string, 0);
-    rb_objc_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
-    rb_objc_define_method(rb_mKernel, "methods", rb_obj_methods, -1);
-
-    VALUE rb_obj_singleton_methods(VALUE obj, SEL sel, int argc, VALUE *argv);
-    rb_objc_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1); /* in class.c */
-    rb_objc_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, -1);
-    rb_objc_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, -1);
-    rb_objc_define_method(rb_mKernel, "public_methods", rb_obj_public_methods, -1);
-    rb_objc_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0); /* in variable.c */
-    rb_objc_define_method(rb_mKernel, "instance_variable_get", rb_obj_ivar_get, 1);
-    rb_objc_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set, 2);
-    rb_objc_define_method(rb_mKernel, "instance_variable_defined?", rb_obj_ivar_defined, 1);
-    VALUE rb_obj_remove_instance_variable(VALUE obj, SEL sel, VALUE other);
-    rb_objc_define_private_method(rb_mKernel, "remove_instance_variable",
-	    rb_obj_remove_instance_variable, 1); /* in variable.c */
-
-    rb_objc_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of_imp, 1);
-    rb_objc_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of_imp, 1);
-    rb_objc_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of_imp, 1);
-    rb_objc_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
-
-    rb_objc_define_module_function(rb_mKernel, "sprintf", rb_f_sprintf_imp, -1); /* in sprintf.c */
-    rb_objc_define_module_function(rb_mKernel, "format", rb_f_sprintf_imp, -1);  /* in sprintf.c */
-
-    rb_objc_define_module_function(rb_mKernel, "Integer", rb_f_integer, -1);
-    rb_objc_define_module_function(rb_mKernel, "Float", rb_f_float, 1);
-    rb_objc_define_module_function(rb_mKernel, "String", rb_f_string, 1);
-    rb_objc_define_module_function(rb_mKernel, "Array", rb_f_array, 1);
-
-    rb_const_set(rb_cObject, rb_intern("NSNull"), (VALUE)objc_getClass("NSNull"));
-
-    rb_cNilClass = rb_define_class("NilClass", rb_cObject);
-    rb_objc_define_method(rb_cNilClass, "to_i", nil_to_i, 0);
-    rb_objc_define_method(rb_cNilClass, "to_f", nil_to_f, 0);
-    rb_objc_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
-    rb_objc_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
-    rb_objc_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
-    rb_objc_define_method(rb_cNilClass, "&", false_and, 1);
-    rb_objc_define_method(rb_cNilClass, "|", false_or, 1);
-    rb_objc_define_method(rb_cNilClass, "^", false_xor, 1);
-
-    rb_objc_define_method(rb_cNilClass, "nil?", rb_true, 0);
-    rb_undef_method(*(VALUE *)rb_cNilClass, "alloc");
-    rb_undef_method(*(VALUE *)rb_cNilClass, "new");
-    rb_define_global_const("NIL", Qnil);
-
-    rb_objc_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
-    rb_objc_define_method(rb_cModule, "===", rb_mod_eqq, 1);
-    rb_objc_define_method(rb_cModule, "==", rb_obj_equal, 1);
-    rb_objc_define_method(rb_cModule, "<=>",  rb_mod_cmp, 1);
-    rb_objc_define_method(rb_cModule, "<",  rb_mod_lt, 1);
-    rb_objc_define_method(rb_cModule, "<=", rb_class_inherited_imp, 1);
-    rb_objc_define_method(rb_cModule, ">",  rb_mod_gt, 1);
-    rb_objc_define_method(rb_cModule, ">=", rb_mod_ge, 1);
-    VALUE rb_mod_init_copy(VALUE recv, SEL sel, VALUE copy);
-    rb_objc_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1); /* in class.c */
-    rb_objc_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
-    rb_objc_define_method(rb_cModule, "included_modules", rb_mod_included_modules_imp, 0);
-    VALUE rb_mod_include_p(VALUE, SEL, VALUE);
-    rb_objc_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */
-    VALUE rb_mod_name(VALUE, SEL);
-    rb_objc_define_method(rb_cModule, "name", rb_mod_name, 0);  /* in variable.c */
-    rb_objc_define_method(rb_cModule, "ancestors", rb_mod_ancestors_imp, 0);
-    rb_objc_define_method(rb_cModule, "__ancestors__", rb_mod_ancestors_all_imp, 0);
-    rb_objc_define_method(rb_cModule, "__properties__", rb_mod_properties_imp, 0);
-    VALUE rb_mod_objc_ib_outlet(VALUE, SEL, int, VALUE *);
-    rb_objc_define_private_method(rb_cModule, "ib_outlet", rb_mod_objc_ib_outlet, -1); /* in objc.m */
-    rb_objc_define_method(rb_cClass, "__meta__?", rb_class_is_meta, 0);
-
-    rb_objc_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
-    rb_objc_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
-    rb_objc_define_private_method(rb_cModule, "attr_writer", rb_mod_attr_writer, -1);
-    rb_objc_define_private_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
-
-    rb_objc_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1); /* in class.c */
-    rb_objc_define_method(rb_cModule, "public_instance_methods", 
-		     rb_class_public_instance_methods, -1);    /* in class.c */
-    rb_objc_define_method(rb_cModule, "protected_instance_methods", 
-		     rb_class_protected_instance_methods, -1); /* in class.c */
-    rb_objc_define_method(rb_cModule, "private_instance_methods", 
-		     rb_class_private_instance_methods, -1);   /* in class.c */
-
-    VALUE rb_mod_constants(VALUE, SEL, int, VALUE *);
-    rb_objc_define_method(rb_cModule, "constants", rb_mod_constants, -1); /* in variable.c */
-    rb_objc_define_method(rb_cModule, "const_get", rb_mod_const_get, -1);
-    rb_objc_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
-    rb_objc_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, -1);
-    rb_objc_define_private_method(rb_cModule, "remove_const", 
-			     rb_mod_remove_const_imp, 1); /* in variable.c */
-    VALUE rb_mod_const_missing(VALUE, SEL, VALUE);
-    rb_objc_define_method(rb_cModule, "const_missing", 
-		     rb_mod_const_missing, 1); /* in variable.c */
-    VALUE rb_mod_class_variables(VALUE, SEL);
-    rb_objc_define_method(rb_cModule, "class_variables", 
-		     rb_mod_class_variables, 0); /* in variable.c */
-    VALUE rb_mod_remove_cvar(VALUE, SEL, VALUE);
-    rb_objc_define_method(rb_cModule, "remove_class_variable", 
-		     rb_mod_remove_cvar, 1); /* in variable.c */
-    rb_objc_define_method(rb_cModule, "class_variable_get", rb_mod_cvar_get, 1);
-    rb_objc_define_method(rb_cModule, "class_variable_set", rb_mod_cvar_set, 2);
-    rb_objc_define_method(rb_cModule, "class_variable_defined?", rb_mod_cvar_defined, 1);
-
-    rb_objc_define_method(rb_cClass, "allocate", rb_obj_alloc_imp, 0);
-    VALUE rb_class_init_copy(VALUE, SEL, VALUE);
-    rb_objc_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
-    rb_undef_method(rb_cClass, "extend_object");
-    rb_undef_method(rb_cClass, "append_features");
-
-    rb_cData = rb_define_class("Data", rb_cObject);
-    rb_undef_method(*(VALUE *)rb_cData, "alloc");
-
-    rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
-    rb_objc_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
-    rb_objc_define_method(rb_cTrueClass, "&", true_and, 1);
-    rb_objc_define_method(rb_cTrueClass, "|", true_or, 1);
-    rb_objc_define_method(rb_cTrueClass, "^", true_xor, 1);
-    rb_undef_method(*(VALUE *)rb_cTrueClass, "alloc");
-    rb_undef_method(*(VALUE *)rb_cTrueClass, "new");
-    rb_define_global_const("TRUE", Qtrue);
-
-    rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
-    rb_objc_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
-    rb_objc_define_method(rb_cFalseClass, "&", false_and, 1);
-    rb_objc_define_method(rb_cFalseClass, "|", false_or, 1);
-    rb_objc_define_method(rb_cFalseClass, "^", false_xor, 1);
-    rb_undef_method(*(VALUE *)rb_cFalseClass, "alloc");
-    rb_undef_method(*(VALUE *)rb_cFalseClass, "new");
-    rb_define_global_const("FALSE", Qfalse);
-
-    id_eq = rb_intern("==");
-    id_match = rb_intern("=~");
-    id_inspect = rb_intern("inspect");
-    id_init_copy = rb_intern("initialize_copy");
-}

Deleted: MacRuby/trunk/pack.c
===================================================================
--- MacRuby/trunk/pack.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/pack.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2244 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "encoding.h"
-
-#define SIZE16 2
-#define SIZE32 4
-
-#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4
-# define NATINT_PACK
-#endif
-
-#ifdef NATINT_PACK
-# define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16)))
-# define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32)))
-# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
-# ifdef WORDS_BIGENDIAN
-#   define OFF16(p) OFF16B(p)
-#   define OFF32(p) OFF32B(p)
-# endif
-# define NATINT_HTOVS(x) (natint?htovs(x):htov16(x))
-# define NATINT_HTOVL(x) (natint?htovl(x):htov32(x))
-# define NATINT_HTONS(x) (natint?htons(x):hton16(x))
-# define NATINT_HTONL(x) (natint?htonl(x):hton32(x))
-#else
-# define NATINT_LEN(type,len) sizeof(type)
-# define NATINT_HTOVS(x) htovs(x)
-# define NATINT_HTOVL(x) htovl(x)
-# define NATINT_HTONS(x) htons(x)
-# define NATINT_HTONL(x) htonl(x)
-#endif
-
-#ifndef OFF16
-# define OFF16(p) (char*)(p)
-# define OFF32(p) (char*)(p)
-#endif
-#ifndef OFF16B
-# define OFF16B(p) (char*)(p)
-# define OFF32B(p) (char*)(p)
-#endif
-
-#define define_swapx(x, xtype)		\
-static xtype				\
-TOKEN_PASTE(swap,x)(xtype z)		\
-{					\
-    xtype r;				\
-    xtype *zp;				\
-    unsigned char *s, *t;		\
-    int i;				\
-					\
-    zp = malloc(sizeof(xtype));	\
-    *zp = z;				\
-    s = (unsigned char*)zp;		\
-    t = malloc(sizeof(xtype));		\
-    for (i=0; i<sizeof(xtype); i++) {	\
-	t[sizeof(xtype)-i-1] = s[i];	\
-    }					\
-    r = *(xtype *)t;			\
-    free(t);				\
-    free(zp);				\
-    return r;				\
-}
-
-#ifndef swap16
-#define swap16(x)	((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
-#endif
-#if SIZEOF_SHORT == 2
-#define swaps(x)	swap16(x)
-#else
-#if SIZEOF_SHORT == 4
-#define swaps(x)	((((x)&0xFF)<<24)	\
-			|(((x)>>24)&0xFF)	\
-			|(((x)&0x0000FF00)<<8)	\
-			|(((x)&0x00FF0000)>>8)	)
-#else
-define_swapx(s,short)
-#endif
-#endif
-
-#ifndef swap32
-#define swap32(x)	((((x)&0xFF)<<24)	\
-			|(((x)>>24)&0xFF)	\
-			|(((x)&0x0000FF00)<<8)	\
-			|(((x)&0x00FF0000)>>8)	)
-#endif
-#if SIZEOF_LONG == 4
-#define swapl(x)	swap32(x)
-#else
-#if SIZEOF_LONG == 8
-#define swapl(x)        ((((x)&0x00000000000000FF)<<56)	\
-			|(((x)&0xFF00000000000000)>>56)	\
-			|(((x)&0x000000000000FF00)<<40)	\
-			|(((x)&0x00FF000000000000)>>40)	\
-			|(((x)&0x0000000000FF0000)<<24)	\
-			|(((x)&0x0000FF0000000000)>>24)	\
-			|(((x)&0x00000000FF000000)<<8)	\
-			|(((x)&0x000000FF00000000)>>8))
-#else
-define_swapx(l,long)
-#endif
-#endif
-
-#if SIZEOF_FLOAT == 4
-#if SIZEOF_LONG == 4	/* SIZEOF_FLOAT == 4 == SIZEOF_LONG */
-#define swapf(x)	swapl(x)
-#define FLOAT_SWAPPER	unsigned long
-#else
-#if SIZEOF_SHORT == 4	/* SIZEOF_FLOAT == 4 == SIZEOF_SHORT */
-#define swapf(x)	swaps(x)
-#define FLOAT_SWAPPER	unsigned short
-#else	/* SIZEOF_FLOAT == 4 but undivide by known size of int */
-define_swapx(f,float)
-#endif	/* #if SIZEOF_SHORT == 4 */
-#endif	/* #if SIZEOF_LONG == 4 */
-#else	/* SIZEOF_FLOAT != 4 */
-define_swapx(f,float)
-#endif	/* #if SIZEOF_FLOAT == 4 */
-
-#if SIZEOF_DOUBLE == 8
-#if SIZEOF_LONG == 8	/* SIZEOF_DOUBLE == 8 == SIZEOF_LONG */
-#define swapd(x)	swapl(x)
-#define DOUBLE_SWAPPER	unsigned long
-#else
-#if SIZEOF_LONG == 4	/* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
-static double
-swapd(const double d)
-{
-    double dtmp = d;
-    unsigned long utmp[2];
-    unsigned long utmp0;
-
-    utmp[0] = 0; utmp[1] = 0;
-    memcpy(utmp,&dtmp,sizeof(double));
-    utmp0 = utmp[0];
-    utmp[0] = swapl(utmp[1]);
-    utmp[1] = swapl(utmp0);
-    memcpy(&dtmp,utmp,sizeof(double));
-    return dtmp;
-}
-#else
-#if SIZEOF_SHORT == 4	/* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
-static double
-swapd(const double d)
-{
-    double dtmp = d;
-    unsigned short utmp[2];
-    unsigned short utmp0;
-
-    utmp[0] = 0; utmp[1] = 0;
-    memcpy(utmp,&dtmp,sizeof(double));
-    utmp0 = utmp[0];
-    utmp[0] = swaps(utmp[1]);
-    utmp[1] = swaps(utmp0);
-    memcpy(&dtmp,utmp,sizeof(double));
-    return dtmp;
-}
-#else	/* SIZEOF_DOUBLE == 8 but undivied by known size of int */
-define_swapx(d, double)
-#endif	/* #if SIZEOF_SHORT == 4 */
-#endif	/* #if SIZEOF_LONG == 4 */
-#endif	/* #if SIZEOF_LONG == 8 */
-#else	/* SIZEOF_DOUBLE != 8 */
-define_swapx(d, double)
-#endif	/* #if SIZEOF_DOUBLE == 8 */
-
-#undef define_swapx
-
-#ifdef DYNAMIC_ENDIAN
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-static int
-endian(void)
-{
-    static int init = 0;
-    static int endian_value;
-    char *p;
-
-    if (init) return endian_value;
-    init = 1;
-    p = (char*)&init;
-    return endian_value = p[0]?0:1;
-}
-
-#define ntohs(x) (endian()?(x):swaps(x))
-#define ntohl(x) (endian()?(x):swapl(x))
-#define ntohf(x) (endian()?(x):swapf(x))
-#define ntohd(x) (endian()?(x):swapd(x))
-#define htons(x) (endian()?(x):swaps(x))
-#define htonl(x) (endian()?(x):swapl(x))
-#define htonf(x) (endian()?(x):swapf(x))
-#define htond(x) (endian()?(x):swapd(x))
-#define htovs(x) (endian()?swaps(x):(x))
-#define htovl(x) (endian()?swapl(x):(x))
-#define htovf(x) (endian()?swapf(x):(x))
-#define htovd(x) (endian()?swapd(x):(x))
-#define vtohs(x) (endian()?swaps(x):(x))
-#define vtohl(x) (endian()?swapl(x):(x))
-#define vtohf(x) (endian()?swapf(x):(x))
-#define vtohd(x) (endian()?swapd(x):(x))
-# ifdef NATINT_PACK
-#define htov16(x) (endian()?swap16(x):(x))
-#define htov32(x) (endian()?swap32(x):(x))
-#define hton16(x) (endian()?(x):swap16(x))
-#define hton32(x) (endian()?(x):swap32(x))
-# endif
-#else
-#ifdef WORDS_BIGENDIAN
-#ifndef ntohs
-#define ntohs(x) (x)
-#define ntohl(x) (x)
-#define htons(x) (x)
-#define htonl(x) (x)
-#endif
-#define ntohf(x) (x)
-#define ntohd(x) (x)
-#define htonf(x) (x)
-#define htond(x) (x)
-#define htovs(x) swaps(x)
-#define htovl(x) swapl(x)
-#define htovf(x) swapf(x)
-#define htovd(x) swapd(x)
-#define vtohs(x) swaps(x)
-#define vtohl(x) swapl(x)
-#define vtohf(x) swapf(x)
-#define vtohd(x) swapd(x)
-# ifdef NATINT_PACK
-#define htov16(x) swap16(x)
-#define htov32(x) swap32(x)
-#define hton16(x) (x)
-#define hton32(x) (x)
-# endif
-#else /* LITTLE ENDIAN */
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-#define ntohs(x) swaps(x)
-#define ntohl(x) swapl(x)
-#define htons(x) swaps(x)
-#define htonl(x) swapl(x)
-#define ntohf(x) swapf(x)
-#define ntohd(x) swapd(x)
-#define htonf(x) swapf(x)
-#define htond(x) swapd(x)
-#define htovs(x) (x)
-#define htovl(x) (x)
-#define htovf(x) (x)
-#define htovd(x) (x)
-#define vtohs(x) (x)
-#define vtohl(x) (x)
-#define vtohf(x) (x)
-#define vtohd(x) (x)
-# ifdef NATINT_PACK
-#define htov16(x) (x)
-#define htov32(x) (x)
-#define hton16(x) swap16(x)
-#define hton32(x) swap32(x)
-# endif
-#endif
-#endif
-
-#ifdef FLOAT_SWAPPER
-#define FLOAT_CONVWITH(y)	FLOAT_SWAPPER y;
-#define HTONF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = htonf((FLOAT_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(float)),	\
-			 x)
-#define HTOVF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = htovf((FLOAT_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(float)),	\
-			 x)
-#define NTOHF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = ntohf((FLOAT_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(float)),	\
-			 x)
-#define VTOHF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = vtohf((FLOAT_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(float)),	\
-			 x)
-#else
-#define FLOAT_CONVWITH(y)
-#define HTONF(x,y)	htonf(x)
-#define HTOVF(x,y)	htovf(x)
-#define NTOHF(x,y)	ntohf(x)
-#define VTOHF(x,y)	vtohf(x)
-#endif
-
-#ifdef DOUBLE_SWAPPER
-#define DOUBLE_CONVWITH(y)	DOUBLE_SWAPPER y;
-#define HTOND(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = htond((DOUBLE_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(double)),	\
-			 x)
-#define HTOVD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = htovd((DOUBLE_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(double)),	\
-			 x)
-#define NTOHD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = ntohd((DOUBLE_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(double)),	\
-			 x)
-#define VTOHD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = vtohd((DOUBLE_SWAPPER)y),	\
-			 memcpy(&x,&y,sizeof(double)),	\
-			 x)
-#else
-#define DOUBLE_CONVWITH(y)
-#define HTOND(x,y)	htond(x)
-#define HTOVD(x,y)	htovd(x)
-#define NTOHD(x,y)	ntohd(x)
-#define VTOHD(x,y)	vtohd(x)
-#endif
-
-unsigned long rb_big2ulong_pack(VALUE x);
-
-static unsigned long
-num2i32(VALUE x)
-{
-    x = rb_to_int(x); /* is nil OK? (should not) */
-
-    if (FIXNUM_P(x)) return FIX2LONG(x);
-    if (TYPE(x) == T_BIGNUM) {
-	return rb_big2ulong_pack(x);
-    }
-    rb_raise(rb_eTypeError, "can't convert %s to `integer'", rb_obj_classname(x));
-    return 0;			/* not reached */
-}
-
-#if SIZEOF_LONG == SIZE32
-# define EXTEND32(x)
-#else
-/* invariant in modulo 1<<31 */
-# define EXTEND32(x) do { if (!natint) {(x) = (((1L<<31)-1-(x))^~(~0L<<31));}} while(0)
-#endif
-#if SIZEOF_SHORT == SIZE16
-# define EXTEND16(x)
-#else
-# define EXTEND16(x) do { if (!natint) {(x) = (short)(((1<<15)-1-(x))^~(~0<<15));}} while(0)
-#endif
-
-#ifdef HAVE_LONG_LONG
-# define QUAD_SIZE sizeof(LONG_LONG)
-#else
-# define QUAD_SIZE 8
-#endif
-static const char toofew[] = "too few arguments";
-
-static void encodes(VALUE,const char*,long,int,int);
-static void qpencode(VALUE,VALUE,long);
-
-static unsigned long utf8_to_uv(const char*,long*);
-
-/*
- *  call-seq:
- *     arr.pack ( aTemplateString ) -> aBinaryString
- *
- *  Packs the contents of <i>arr</i> into a binary sequence according to
- *  the directives in <i>aTemplateString</i> (see the table below)
- *  Directives ``A,'' ``a,'' and ``Z'' may be followed by a count,
- *  which gives the width of the resulting field. The remaining
- *  directives also may take a count, indicating the number of array
- *  elements to convert. If the count is an asterisk
- *  (``<code>*</code>''), all remaining array elements will be
- *  converted. Any of the directives ``<code>sSiIlL</code>'' may be
- *  followed by an underscore (``<code>_</code>'') to use the underlying
- *  platform's native size for the specified type; otherwise, they use a
- *  platform-independent size. Spaces are ignored in the template
- *  string. See also <code>String#unpack</code>.
- *
- *     a = [ "a", "b", "c" ]
- *     n = [ 65, 66, 67 ]
- *     a.pack("A3A3A3")   #=> "a  b  c  "
- *     a.pack("a3a3a3")   #=> "a\000\000b\000\000c\000\000"
- *     n.pack("ccc")      #=> "ABC"
- *
- *  Directives for +pack+.
- *
- *   Directive    Meaning
- *   ---------------------------------------------------------------
- *       @     |  Moves to absolute position
- *       A     |  arbitrary binary string (space padded, count is width)
- *       a     |  arbitrary binary string (null padded, count is width)
- *       B     |  Bit string (descending bit order)
- *       b     |  Bit string (ascending bit order)
- *       C     |  Unsigned byte (C unsigned char)
- *       c     |  Byte (C char)
- *       D, d  |  Double-precision float, native format
- *       E     |  Double-precision float, little-endian byte order
- *       e     |  Single-precision float, little-endian byte order
- *       F, f  |  Single-precision float, native format
- *       G     |  Double-precision float, network (big-endian) byte order
- *       g     |  Single-precision float, network (big-endian) byte order
- *       H     |  Hex string (high nibble first)
- *       h     |  Hex string (low nibble first)
- *       I     |  Unsigned integer
- *       i     |  Integer
- *       L     |  Unsigned long
- *       l     |  Long
- *       M     |  Quoted printable, MIME encoding (see RFC2045)
- *       m     |  Base64 encoded string
- *       N     |  Long, network (big-endian) byte order
- *       n     |  Short, network (big-endian) byte-order
- *       P     |  Pointer to a structure (fixed-length string)
- *       p     |  Pointer to a null-terminated string
- *       Q, q  |  64-bit number
- *       S     |  Unsigned short
- *       s     |  Short
- *       U     |  UTF-8
- *       u     |  UU-encoded string
- *       V     |  Long, little-endian byte order
- *       v     |  Short, little-endian byte order
- *       w     |  BER-compressed integer\fnm
- *       X     |  Back up a byte
- *       x     |  Null byte
- *       Z     |  Same as ``a'', except that null is added with *
- */
-
-#define PRE_ALLOCATE(bstr, len) \
-    do { \
-	const long datalen = rb_bstr_length(data); \
-	rb_bstr_resize(bstr, datalen + len); \
-	rb_bstr_set_length(bstr, datalen); \
-    } \
-    while (0)
-
-static VALUE
-pack_pack(VALUE ary, SEL sel, VALUE fmt)
-{
-    static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
-    static const char spc10[] = "          ";
-    const char *p, *pend;
-    VALUE from, associates = 0;
-    char type;
-    long items, len, idx, plen;
-    const char *ptr;
-    int enc_info = 1;		/* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
-#ifdef NATINT_PACK
-    int natint;		/* native integer */
-#endif
-
-    StringValue(fmt);
-    p = RSTRING_PTR(fmt);
-    pend = p + RSTRING_LEN(fmt);
-
-    VALUE data = rb_bstr_new();
-
-    items = RARRAY_LEN(ary);
-    idx = 0;
-
-#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
-#define THISFROM (items > 0 ? RARRAY_AT(ary, idx) : TOO_FEW)
-#define NEXTFROM (items-- > 0 ? RARRAY_AT(ary, idx++) : TOO_FEW)
-
-    while (p < pend) {
-	if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
-	    rb_raise(rb_eRuntimeError, "format string modified");
-	}
-	type = *p++;		/* get data type */
-#ifdef NATINT_PACK
-	natint = 0;
-#endif
-
-	if (ISSPACE(type)) continue;
-	if (type == '#') {
-	    while ((p < pend) && (*p != '\n')) {
-		p++;
-	    }
-	    continue;
-	}
-        if (*p == '_' || *p == '!') {
-	    static const char natstr[] = "sSiIlL";
-
-	    if (strchr(natstr, type)) {
-#ifdef NATINT_PACK
-		natint = 1;
-#endif
-		p++;
-	    }
-	    else {
-		rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
-	    }
-	}
-	if (*p == '*') {	/* set data length */
-	    len = strchr("@Xxu", type) ? 0
-		: strchr("PMm", type) ? 1
-		: items;
-	    p++;
-	}
-	else if (ISDIGIT(*p)) {
-	    errno = 0;
-	    len = STRTOUL(p, (char**)&p, 10);
-	    if (errno) {
-		rb_raise(rb_eRangeError, "pack length too big");
-	    }
-	}
-	else {
-	    len = 1;
-	}
-
-	switch (type) {
-	  case 'U':
-	    /* if encoding is US-ASCII, upgrade to UTF-8 */
-	    if (enc_info == 1) {
-		enc_info = 2;
-	    }
-	    break;
-	  case 'm': case 'M': case 'u':
-	    /* keep US-ASCII (do nothing) */
-	    break;
-	  default:
-	    /* fall back to BINARY */
-	    enc_info = 0;
-	    break;
-	}
-
-	switch (type) {
-	  case 'A': case 'a': case 'Z':
-	  case 'B': case 'b':
-	  case 'H': case 'h':
-	    from = NEXTFROM;
-	    if (NIL_P(from)) {
-		ptr = "";
-		plen = 0;
-	    }
-	    else {
-		StringValue(from);
-		ptr = RSTRING_PTR(from);
-		plen = RSTRING_LEN(from);
-		OBJ_INFECT(data, from);
-	    }
-
-	    if (p[-1] == '*')
-		len = plen;
-
-	    switch (type) {
-	      case 'a':		/* arbitrary binary string (null padded)  */
-	      case 'A':         /* arbitrary binary string (ASCII space padded) */
-	      case 'Z':         /* null terminated string  */
-		if (plen >= len) {
-		    PRE_ALLOCATE(data, len + 1);
-		    rb_bstr_concat(data, (const UInt8 *)ptr, len);
-		    if (p[-1] == '*' && type == 'Z') {
-			rb_bstr_concat(data, (const UInt8 *)nul10, 1);
-		    }
-		}
-		else {
-		    PRE_ALLOCATE(data, len);
-		    rb_bstr_concat(data, (const UInt8 *)ptr, plen);
-		    len -= plen;
-		    while (len >= 10) {
-			rb_bstr_concat(data, (const UInt8 *)((type == 'A')?spc10:nul10), 10);
-			len -= 10;
-		    }
-		    rb_bstr_concat(data, (const UInt8 *)((type == 'A')?spc10:nul10), len);
-		}
-		break;
-
-	      case 'b':		/* bit string (ascending) */
-		{
-		    int byte = 0;
-		    long i, j = 0;
-
-		    if (len > plen) {
-			j = (len - plen + 1)/2;
-			len = plen;
-		    }
-		    PRE_ALLOCATE(data, len);
-		    for (i=0; i++ < len; ptr++) {
-			if (*ptr & 1)
-			    byte |= 128;
-			if (i & 7)
-			    byte >>= 1;
-			else {
-			    char c = byte & 0xff;
-			    rb_bstr_concat(data, (const UInt8 *)&c, 1);
-			    byte = 0;
-			}
-		    }
-		    if (len & 7) {
-			char c;
-			byte >>= 7 - (len & 7);
-			c = byte & 0xff;
-			rb_bstr_concat(data, (const UInt8 *)&c, 1);
-		    }
-		    len = j;
-		    goto grow;
-		}
-		break;
-
-	      case 'B':		/* bit string (descending) */
-		{
-		    int byte = 0;
-		    long i, j = 0;
-
-		    if (len > plen) {
-			j = (len - plen + 1)/2;
-			len = plen;
-		    }
-		    PRE_ALLOCATE(data, len);
-		    for (i=0; i++ < len; ptr++) {
-			byte |= *ptr & 1;
-			if (i & 7)
-			    byte <<= 1;
-			else {
-			    char c = byte & 0xff;
-			    rb_bstr_concat(data, (const UInt8 *)&c, 1);
-			    byte = 0;
-			}
-		    }
-		    if (len & 7) {
-			char c;
-			byte <<= 7 - (len & 7);
-			c = byte & 0xff;
-			rb_bstr_concat(data, (const UInt8 *)&c, 1);
-		    }
-		    len = j;
-		    goto grow;
-		}
-		break;
-
-	      case 'h':		/* hex string (low nibble first) */
-		{
-		    int byte = 0;
-		    long i, j = 0;
-
-		    if (len > plen) {
-			j = (len + 1) / 2 - (plen + 1) / 2;
-			len = plen;
-		    }
-		    PRE_ALLOCATE(data, len);
-		    for (i=0; i++ < len; ptr++) {
-			if (ISALPHA(*ptr))
-			    byte |= (((*ptr & 15) + 9) & 15) << 4;
-			else
-			    byte |= (*ptr & 15) << 4;
-			if (i & 1)
-			    byte >>= 4;
-			else {
-			    char c = byte & 0xff;
-			    rb_bstr_concat(data, (const UInt8 *)&c, 1);
-			    byte = 0;
-			}
-		    }
-		    if (len & 1) {
-			char c = byte & 0xff;
-			rb_bstr_concat(data, (const UInt8 *)&c, 1);
-		    }
-		    len = j;
-		    goto grow;
-		}
-		break;
-
-	      case 'H':		/* hex string (high nibble first) */
-		{
-		    int byte = 0;
-		    long i, j = 0;
-
-		    if (len > plen) {
-			j = (len + 1) / 2 - (plen + 1) / 2;
-			len = plen;
-		    }
-		    PRE_ALLOCATE(data, len);
-		    for (i=0; i++ < len; ptr++) {
-			if (ISALPHA(*ptr))
-			    byte |= ((*ptr & 15) + 9) & 15;
-			else
-			    byte |= *ptr & 15;
-			if (i & 1)
-			    byte <<= 4;
-			else {
-			    char c = byte & 0xff;
-			    rb_bstr_concat(data, (const UInt8 *)&c, 1);
-			    byte = 0;
-			}
-		    }
-		    if (len & 1) {
-			char c = byte & 0xff;
-			rb_bstr_concat(data, (const UInt8 *)&c, 1);
-		    }
-		    len = j;
-		    goto grow;
-		}
-		break;
-	    }
-	    break;
-
-	  case 'c':		/* signed char */
-	  case 'C':		/* unsigned char */
-	    PRE_ALLOCATE(data, len);
-	    while (len-- > 0) {
-		char c;
-
-		from = NEXTFROM;
-		c = num2i32(from);
-		rb_bstr_concat(data, (const UInt8 *)&c, 1);
-	    }
-	    break;
-
-	  case 's':		/* signed short */
-	  case 'S':		/* unsigned short */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(short,2));
-	    while (len-- > 0) {
-		short s;
-
-		from = NEXTFROM;
-		s = num2i32(from);
-		rb_bstr_concat(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
-
-	  case 'i':		/* signed int */
-	  case 'I':		/* unsigned int */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(int,4));
-	    while (len-- > 0) {
-		long i;
-
-		from = NEXTFROM;
-		i = num2i32(from);
-		rb_bstr_concat(data, (const UInt8 *)OFF32(&i), NATINT_LEN(int,4));
-	    }
-	    break;
-
-	  case 'l':		/* signed long */
-	  case 'L':		/* unsigned long */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(long,4));
-	    while (len-- > 0) {
-		long l;
-
-		from = NEXTFROM;
-		l = num2i32(from);
-		rb_bstr_concat(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
-
-	  case 'q':		/* signed quad (64bit) int */
-	  case 'Q':		/* unsigned quad (64bit) int */
-	    PRE_ALLOCATE(data, len * QUAD_SIZE);
-	    while (len-- > 0) {
-		char tmp[QUAD_SIZE];
-
-		from = NEXTFROM;
-		rb_quad_pack(tmp, from);
-		rb_bstr_concat(data, (const UInt8 *)&tmp, QUAD_SIZE);
-	    }
-	    break;
-
-	  case 'n':		/* unsigned short (network byte-order)  */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(short,2));
-	    while (len-- > 0) {
-		unsigned short s;
-
-		from = NEXTFROM;
-		s = num2i32(from);
-		s = NATINT_HTONS(s);
-		rb_bstr_concat(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
-
-	  case 'N':		/* unsigned long (network byte-order) */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(long,4));
-	    while (len-- > 0) {
-		unsigned long l;
-
-		from = NEXTFROM;
-		l = num2i32(from);
-		l = NATINT_HTONL(l);
-		rb_bstr_concat(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
-
-	  case 'v':		/* unsigned short (VAX byte-order) */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(short,2));
-	    while (len-- > 0) {
-		unsigned short s;
-
-		from = NEXTFROM;
-		s = num2i32(from);
-		s = NATINT_HTOVS(s);
-		rb_bstr_concat(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
-
-	  case 'V':		/* unsigned long (VAX byte-order) */
-	    PRE_ALLOCATE(data, len * NATINT_LEN(long,4));
-	    while (len-- > 0) {
-		unsigned long l;
-
-		from = NEXTFROM;
-		l = num2i32(from);
-		l = NATINT_HTOVL(l);
-		rb_bstr_concat(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
-
-	  case 'f':		/* single precision float in native format */
-	  case 'F':		/* ditto */
-	    PRE_ALLOCATE(data, len * sizeof(float));
-	    while (len-- > 0) {
-		float f;
-
-		from = NEXTFROM;
-		f = RFLOAT_VALUE(rb_to_float(from));
-		rb_bstr_concat(data, (const UInt8 *)&f, sizeof(float));
-	    }
-	    break;
-
-	  case 'e':		/* single precision float in VAX byte-order */
-	    PRE_ALLOCATE(data, len * sizeof(float));
-	    while (len-- > 0) {
-		float f;
-		FLOAT_CONVWITH(ftmp);
-
-		from = NEXTFROM;
-		f = RFLOAT_VALUE(rb_to_float(from));
-		f = HTOVF(f,ftmp);
-		rb_bstr_concat(data, (const UInt8 *)&f, sizeof(float));
-	    }
-	    break;
-
-	  case 'E':		/* double precision float in VAX byte-order */
-	    PRE_ALLOCATE(data, len * sizeof(double));
-	    while (len-- > 0) {
-		double d;
-		DOUBLE_CONVWITH(dtmp);
-
-		from = NEXTFROM;
-		d = RFLOAT_VALUE(rb_to_float(from));
-		d = HTOVD(d,dtmp);
-		rb_bstr_concat(data, (const UInt8 *)&d, sizeof(double));
-	    }
-	    break;
-
-	  case 'd':		/* double precision float in native format */
-	  case 'D':		/* ditto */
-	    PRE_ALLOCATE(data, len * sizeof(double));
-	    while (len-- > 0) {
-		double d;
-
-		from = NEXTFROM;
-		d = RFLOAT_VALUE(rb_to_float(from));
-		rb_bstr_concat(data, (const UInt8 *)&d, sizeof(double));
-	    }
-	    break;
-
-	  case 'g':		/* single precision float in network byte-order */
-	    PRE_ALLOCATE(data, len * sizeof(float));
-	    while (len-- > 0) {
-		float f;
-		FLOAT_CONVWITH(ftmp);
-
-		from = NEXTFROM;
-		f = RFLOAT_VALUE(rb_to_float(from));
-		f = HTONF(f,ftmp);
-		rb_bstr_concat(data, (const UInt8 *)&f, sizeof(float));
-	    }
-	    break;
-
-	  case 'G':		/* double precision float in network byte-order */
-	    PRE_ALLOCATE(data, len * sizeof(double));
-	    while (len-- > 0) {
-		double d;
-		DOUBLE_CONVWITH(dtmp);
-
-		from = NEXTFROM;
-		d = RFLOAT_VALUE(rb_to_float(from));
-		d = HTOND(d,dtmp);
-		rb_bstr_concat(data, (const UInt8 *)&d, sizeof(double));
-	    }
-	    break;
-
-	  case 'x':		/* null byte */
-	  grow:
-	    PRE_ALLOCATE(data, len);
-	    while (len >= 10) {
-		rb_bstr_concat(data, (const UInt8 *)nul10, 10);
-		len -= 10;
-	    }
-	    rb_bstr_concat(data, (const UInt8 *)nul10, len);
-	    break;
-
-	  case 'X':		/* back up byte */
-	  shrink:
-	    plen = rb_bstr_length(data);
-	    if (plen < len) {
-		rb_raise(rb_eArgError, "X outside of string");
-	    }
-	    rb_bstr_set_length(data, plen - len);
-	    break;
-
-	  case '@':		/* null fill to absolute position */
-	    len -= rb_bstr_length(data);
-	    if (len > 0) {
-		goto grow;
-	    }
-	    len = -len;
-	    if (len > 0) {
-		goto shrink;
-	    }
-	    break;
-
-	  case '%':
-	    rb_raise(rb_eArgError, "%% is not supported");
-	    break;
-
-	  case 'U':		/* Unicode character */
-	    PRE_ALLOCATE(data, 6 * len);
-	    while (len-- > 0) {
-		SIGNED_VALUE l;
-		char buf[8];
-		int le;
-
-		from = NEXTFROM;
-		from = rb_to_int(from);
-		l = NUM2LONG(from);
-		if (l < 0) {
-		    rb_raise(rb_eRangeError, "pack(U): value out of range");
-		}
-		le = rb_uv_to_utf8(buf, l);
-		rb_bstr_concat(data, (const UInt8 *)buf, le);
-	    }
-	    break;
-
-	  case 'u':		/* uuencoded string */
-	  case 'm':		/* base64 encoded string */
-	    from = NEXTFROM;
-	    StringValue(from);
-	    ptr = RSTRING_PTR(from);
-	    plen = RSTRING_LEN(from);
-
-	    if (len == 0 && type == 'm') {
-		encodes(data, ptr, plen, type, 0);
-		ptr += plen;
-		break;
-	    }
-	    if (len <= 2) {
-		len = 45;
-	    }
-	    else {
-		len = len / 3 * 3;
-	    }
-
-	    PRE_ALLOCATE(data, (plen / len) * (len * 4 / 3 + 6));
-
-	    while (plen > 0) {
-		long todo;
-
-		if (plen > len) {
-		    todo = len;
-		}
-		else {
-		    todo = plen;
-		}
-		encodes(data, ptr, todo, type, 1);
-		plen -= todo;
-		ptr += todo;
-	    }
-	    break;
-
-	  case 'M':		/* quoted-printable encoded string */
-	    from = rb_obj_as_string(NEXTFROM);
-	    if (len <= 1) {
-		len = 72;
-	    }
-	    qpencode(data, from, len);
-	    break;
-
-	  case 'P':		/* pointer to packed byte string */
-	    from = THISFROM;
-	    if (!NIL_P(from)) {
-		StringValue(from);
-		if (RSTRING_LEN(from) < len) {
-		    rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
-			     RSTRING_LEN(from), len);
-		}
-	    }
-	    len = 1;
-	    /* FALL THROUGH */
-	  case 'p':		/* pointer to string */
-	    PRE_ALLOCATE(data, len * sizeof(char *));
-	    while (len-- > 0) {
-		char *t;
-		from = NEXTFROM;
-		if (NIL_P(from)) {
-		    t = 0;
-		}
-		else {
-		    t = StringValuePtr(from);
-		}
-		if (!associates) {
-		    associates = rb_ary_new();
-		}
-		rb_ary_push(associates, from);
-		rb_obj_taint(from);
-		rb_bstr_concat(data, (const UInt8 *)&t, sizeof(char*));
-	    }
-	    break;
-
-	  case 'w':		/* BER compressed integer  */
-	    // TODO: data bstr pre-allocation
-	    while (len-- > 0) {
-		unsigned long ul;
-		VALUE bufdata = rb_bstr_new();
-		char c, *bufs, *bufe;
-
-		from = NEXTFROM;
-		if (TYPE(from) == T_BIGNUM) {
-		    VALUE big128 = rb_uint2big(128);
-		    while (TYPE(from) == T_BIGNUM) {
-			from = rb_big_divmod(from, big128);
-			c = NUM2INT(RARRAY_AT(from, 1)) | 0x80; /* mod */
-			rb_bstr_concat(bufdata, (const UInt8 *)&c, sizeof(char));
-			from = RARRAY_AT(from, 0); /* div */
-		    }
-		}
-
-		long l = NUM2LONG(from);
-		if (l < 0) {
-		    rb_raise(rb_eArgError, "can't compress negative numbers");
-		}
-		ul = l;
-
-		while (ul) {
-		    c = ((ul & 0x7f) | 0x80);
-		    rb_bstr_concat(bufdata, (const UInt8 *)&c, sizeof(char));
-		    ul >>=  7;
-		}
-
-		if (rb_bstr_length(bufdata) > 0) {
-		    UInt8 *buf_beg = rb_bstr_bytes(bufdata);
-		    bufs = (char *)buf_beg;
-		    bufe = bufs + rb_bstr_length(bufdata) - 1;
-		    *bufs &= 0x7f; /* clear continue bit */
-		    while (bufs < bufe) { /* reverse */
-			c = *bufs;
-			*bufs++ = *bufe;
-			*bufe-- = c;
-		    }
-		    rb_bstr_concat(data, buf_beg, rb_bstr_length(bufdata));
-		}
-		else {
-		    c = 0;
-		    rb_bstr_concat(data, (const UInt8 *)&c, sizeof(char));
-		}
-	    }
-	    break;
-
-	  default:
-	    break;
-	}
-    }
-
-    OBJ_INFECT(data, fmt);
-    switch (enc_info) {
-      case 1:
-	// TODO
-	// ENCODING_CODERANGE_SET(data, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
-	break;
-      case 2:
-	rb_str_force_encoding(data, rb_encodings[ENCODING_UTF8]);
-	break;
-      default:
-	/* do nothing, keep ASCII-8BIT */
-	break;
-    }
-
-    return data;
-}
-
-static const char uu_table[] =
-"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
-static const char b64_table[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static void
-encodes(VALUE data, const char *s, long len, int type, int tail_lf)
-{
-    char buff[4096];
-    long i = 0;
-    const char *trans = type == 'u' ? uu_table : b64_table;
-    int padding;
-
-    if (type == 'u') {
-	buff[i++] = len + ' ';
-	padding = '`';
-    }
-    else {
-	padding = '=';
-    }
-    while (len >= 3) {
-	while (len >= 3 && sizeof(buff) - i >= 4) {
-	    buff[i++] = trans[077 & (*s >> 2)];
-	    buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
-	    buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
-	    buff[i++] = trans[077 & s[2]];
-	    s += 3;
-	    len -= 3;
-	}
-	if (sizeof(buff) - i < 4) {
-	    rb_bstr_concat(data, (const UInt8 *)buff, i);
-	    i = 0;
-	}
-    }
-    if (len == 2) {
-	buff[i++] = trans[077 & (*s >> 2)];
-	buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
-	buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
-	buff[i++] = padding;
-    }
-    else if (len == 1) {
-	buff[i++] = trans[077 & (*s >> 2)];
-	buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
-	buff[i++] = padding;
-	buff[i++] = padding;
-    }
-    if (tail_lf) {
-	buff[i++] = '\n';
-    }
-    rb_bstr_concat(data, (const UInt8 *)buff, i);
-}
-static const char hex_table[] = "0123456789ABCDEF";
-
-static void
-qpencode(VALUE data, VALUE from, long len)
-{
-    char buff[1024];
-    long i = 0, n = 0, prev = EOF;
-    const unsigned char *s = (unsigned char*)RSTRING_PTR(from);
-    const unsigned char *send = s + RSTRING_LEN(from);
-
-    while (s < send) {
-        if ((*s > 126) ||
-	    (*s < 32 && *s != '\n' && *s != '\t') ||
-	    (*s == '=')) {
-	    buff[i++] = '=';
-	    buff[i++] = hex_table[*s >> 4];
-	    buff[i++] = hex_table[*s & 0x0f];
-            n += 3;
-            prev = EOF;
-        }
-	else if (*s == '\n') {
-            if (prev == ' ' || prev == '\t') {
-		buff[i++] = '=';
-		buff[i++] = *s;
-            }
-	    buff[i++] = *s;
-            n = 0;
-            prev = *s;
-        }
-	else {
-	    buff[i++] = *s;
-            n++;
-            prev = *s;
-        }
-        if (n > len) {
-	    buff[i++] = '=';
-	    buff[i++] = '\n';
-            n = 0;
-            prev = '\n';
-        }
-	if (i > 1024 - 5) {
-	    rb_bstr_concat(data, (const UInt8 *)buff, i);
-	    i = 0;
-	}
-	s++;
-    }
-    if (n > 0) {
-	buff[i++] = '=';
-	buff[i++] = '\n';
-    }
-    if (i > 0) {
-	rb_bstr_concat(data, (const UInt8 *)buff, i);
-    }
-}
-
-static inline int
-hex2num(char c)
-{
-    switch (c) {
-      case '0': case '1': case '2': case '3': case '4':
-      case '5': case '6': case '7': case '8': case '9':
-        return c - '0';
-      case 'a': case 'b': case 'c':
-      case 'd': case 'e': case 'f':
-	return c - 'a' + 10;
-      case 'A': case 'B': case 'C':
-      case 'D': case 'E': case 'F':
-	return c - 'A' + 10;
-      default:
-	return -1;
-    }
-}
-
-#define PACK_LENGTH_ADJUST_SIZE(sz) do {	\
-    tmp = 0;					\
-    if (len > (send-s)/sz) {			\
-        if (!star) {				\
-	    tmp = len-(send-s)/sz;		\
-        }					\
-	len = (send-s)/sz;			\
-    }						\
-} while (0)
-
-#ifdef NATINT_PACK
-#define PACK_LENGTH_ADJUST(type,sz) do {	\
-    int t__len = NATINT_LEN(type,(sz));		\
-    PACK_LENGTH_ADJUST_SIZE(t__len);		\
-} while (0)
-#else
-#define PACK_LENGTH_ADJUST(type,sz) 		\
-    PACK_LENGTH_ADJUST_SIZE(sizeof(type))
-#endif
-
-#define PACK_ITEM_ADJUST() do {				\
-	if (!block_p) {					\
-	    while (tmp--) rb_ary_push(ary, Qnil);	\
-	}						\
-    }							\
-    while (0)
-
-static VALUE
-infected_str_new(const char *ptr, long len, VALUE str)
-{
-    return rb_str_new(ptr, len);
-}
-
-/*
- *  call-seq:
- *     str.unpack(format)   => anArray
- *
- *  Decodes <i>str</i> (which may contain binary data) according to the
- *  format string, returning an array of each value extracted. The
- *  format string consists of a sequence of single-character directives,
- *  summarized in the table at the end of this entry.
- *  Each directive may be followed
- *  by a number, indicating the number of times to repeat with this
- *  directive. An asterisk (``<code>*</code>'') will use up all
- *  remaining elements. The directives <code>sSiIlL</code> may each be
- *  followed by an underscore (``<code>_</code>'') to use the underlying
- *  platform's native size for the specified type; otherwise, it uses a
- *  platform-independent consistent size. Spaces are ignored in the
- *  format string. See also <code>Array#pack</code>.
- *
- *     "abc \0\0abc \0\0".unpack('A6Z6')   #=> ["abc", "abc "]
- *     "abc \0\0".unpack('a3a3')           #=> ["abc", " \000\000"]
- *     "abc \0abc \0".unpack('Z*Z*')       #=> ["abc ", "abc "]
- *     "aa".unpack('b8B8')                 #=> ["10000110", "01100001"]
- *     "aaa".unpack('h2H2c')               #=> ["16", "61", 97]
- *     "\xfe\xff\xfe\xff".unpack('sS')     #=> [-2, 65534]
- *     "now=20is".unpack('M*')             #=> ["now is"]
- *     "whole".unpack('xax2aX2aX1aX2a')    #=> ["h", "e", "l", "l", "o"]
- *
- *  This table summarizes the various formats and the Ruby classes
- *  returned by each.
- *
- *     Format | Returns | Function
- *     -------+---------+-----------------------------------------
- *       A    | String  | arbitrary binary string with trailing
- *            |         | nulls and ASCII spaces removed
- *     -------+---------+-----------------------------------------
- *       a    | String  | arbitrary binary string
- *     -------+---------+-----------------------------------------
- *       B    | String  | extract bits from each character (msb first)
- *     -------+---------+-----------------------------------------
- *       b    | String  | extract bits from each character (lsb first)
- *     -------+---------+-----------------------------------------
- *       C    | Fixnum  | extract a byte (C char) as an unsigned integer
- *     -------+---------+-----------------------------------------
- *       c    | Fixnum  | extract a byte (C char) as an integer
- *     -------+---------+-----------------------------------------
- *       d,D  | Float   | treat sizeof(double) characters as
- *            |         | a native double
- *     -------+---------+-----------------------------------------
- *       E    | Float   | treat sizeof(double) characters as
- *            |         | a double in little-endian byte order
- *     -------+---------+-----------------------------------------
- *       e    | Float   | treat sizeof(float) characters as
- *            |         | a float in little-endian byte order
- *     -------+---------+-----------------------------------------
- *       f,F  | Float   | treat sizeof(float) characters as
- *            |         | a native float
- *     -------+---------+-----------------------------------------
- *       G    | Float   | treat sizeof(double) characters as
- *            |         | a double in network byte order
- *     -------+---------+-----------------------------------------
- *       g    | Float   | treat sizeof(float) characters as a
- *            |         | float in network byte order
- *     -------+---------+-----------------------------------------
- *       H    | String  | extract hex nibbles from each character
- *            |         | (most significant first)
- *     -------+---------+-----------------------------------------
- *       h    | String  | extract hex nibbles from each character
- *            |         | (least significant first)
- *     -------+---------+-----------------------------------------
- *       I    | Integer | treat sizeof(int) (modified by _)
- *            |         | successive characters as an unsigned
- *            |         | native integer
- *     -------+---------+-----------------------------------------
- *       i    | Integer | treat sizeof(int) (modified by _)
- *            |         | successive characters as a signed
- *            |         | native integer
- *     -------+---------+-----------------------------------------
- *       L    | Integer | treat four (modified by _) successive
- *            |         | characters as an unsigned native
- *            |         | long integer
- *     -------+---------+-----------------------------------------
- *       l    | Integer | treat four (modified by _) successive
- *            |         | characters as a signed native
- *            |         | long integer
- *     -------+---------+-----------------------------------------
- *       M    | String  | quoted-printable
- *     -------+---------+-----------------------------------------
- *       m    | String  | base64-encoded
- *     -------+---------+-----------------------------------------
- *       N    | Integer | treat four characters as an unsigned
- *            |         | long in network byte order
- *     -------+---------+-----------------------------------------
- *       n    | Fixnum  | treat two characters as an unsigned
- *            |         | short in network byte order
- *     -------+---------+-----------------------------------------
- *       P    | String  | treat sizeof(char *) characters as a
- *            |         | pointer, and  return \emph{len} characters
- *            |         | from the referenced location
- *     -------+---------+-----------------------------------------
- *       p    | String  | treat sizeof(char *) characters as a
- *            |         | pointer to a  null-terminated string
- *     -------+---------+-----------------------------------------
- *       Q    | Integer | treat 8 characters as an unsigned
- *            |         | quad word (64 bits)
- *     -------+---------+-----------------------------------------
- *       q    | Integer | treat 8 characters as a signed
- *            |         | quad word (64 bits)
- *     -------+---------+-----------------------------------------
- *       S    | Fixnum  | treat two (different if _ used)
- *            |         | successive characters as an unsigned
- *            |         | short in native byte order
- *     -------+---------+-----------------------------------------
- *       s    | Fixnum  | Treat two (different if _ used)
- *            |         | successive characters as a signed short
- *            |         | in native byte order
- *     -------+---------+-----------------------------------------
- *       U    | Integer | UTF-8 characters as unsigned integers
- *     -------+---------+-----------------------------------------
- *       u    | String  | UU-encoded
- *     -------+---------+-----------------------------------------
- *       V    | Fixnum  | treat four characters as an unsigned
- *            |         | long in little-endian byte order
- *     -------+---------+-----------------------------------------
- *       v    | Fixnum  | treat two characters as an unsigned
- *            |         | short in little-endian byte order
- *     -------+---------+-----------------------------------------
- *       w    | Integer | BER-compressed integer (see Array.pack)
- *     -------+---------+-----------------------------------------
- *       X    | ---     | skip backward one character
- *     -------+---------+-----------------------------------------
- *       x    | ---     | skip forward one character
- *     -------+---------+-----------------------------------------
- *       Z    | String  | with trailing nulls removed
- *            |         | upto first null with *
- *     -------+---------+-----------------------------------------
- *       @    | ---     | skip to the offset given by the
- *            |         | length argument
- *     -------+---------+-----------------------------------------
- */
-
-static VALUE
-pack_unpack(VALUE str, SEL sel, VALUE fmt)
-{
-    static const char *hexdigits = "0123456789abcdef0123456789ABCDEFx";
-    const char *s, *send;
-    const char *p, *pend;
-    VALUE ary;
-    char type;
-    long len;
-    int tmp, star;
-#ifdef NATINT_PACK
-    int natint;			/* native integer */
-#endif
-    int block_p = rb_block_given_p();
-#define UNPACK_PUSH(item) do {\
-	VALUE item_val = (item);\
-	if (block_p) {\
-	    rb_yield(item_val);\
-	    RETURN_IF_BROKEN();\
-	}\
-	else {\
-	    rb_ary_push(ary, item_val);\
-	}\
-    } while (0)
-
-    StringValue(str);
-    StringValue(fmt);
-    s = RSTRING_PTR(str);
-    send = s + RSTRING_LEN(str);
-    p = RSTRING_PTR(fmt);
-    pend = p + RSTRING_LEN(fmt);
-
-    ary = block_p ? Qnil : rb_ary_new();
-    while (p < pend) {
-	type = *p++;
-#ifdef NATINT_PACK
-	natint = 0;
-#endif
-
-	if (ISSPACE(type)) continue;
-	if (type == '#') {
-	    while ((p < pend) && (*p != '\n')) {
-		p++;
-	    }
-	    continue;
-	}
-	star = 0;
-	if (*p == '_' || *p == '!') {
-	    static const char natstr[] = "sSiIlL";
-
-	    if (strchr(natstr, type)) {
-#ifdef NATINT_PACK
-		natint = 1;
-#endif
-		p++;
-	    }
-	    else {
-		rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
-	    }
-	}
-	if (p >= pend)
-	    len = 1;
-	else if (*p == '*') {
-	    star = 1;
-	    len = send - s;
-	    p++;
-	}
-	else if (ISDIGIT(*p)) {
-	    errno = 0;
-	    len = STRTOUL(p, (char**)&p, 10);
-	    if (errno) {
-		rb_raise(rb_eRangeError, "pack length too big");
-	    }
-	}
-	else {
-	    len = (type != '@');
-	}
-
-	switch (type) {
-	  case '%':
-	    rb_raise(rb_eArgError, "%% is not supported");
-	    break;
-
-	  case 'A':
-	    if (len > send - s) len = send - s;
-	    {
-		long end = len;
-		const char *t = s + len - 1;
-
-		while (t >= s) {
-		    if (*t != ' ' && *t != '\0') break;
-		    t--; len--;
-		}
-		UNPACK_PUSH(infected_str_new(s, len, str));
-		s += end;
-	    }
-	    break;
-
-	  case 'Z':
-	    {
-		const char *t = s;
-
-		if (len > send-s) len = send-s;
-		while (t < s+len && *t) t++;
-		UNPACK_PUSH(infected_str_new(s, t-s, str));
-		if (t < send) t++;
-		s = star ? t : s+len;
-	    }
-	    break;
-
-	  case 'a':
-	    if (len > send - s) len = send - s;
-	    UNPACK_PUSH(infected_str_new(s, len, str));
-	    s += len;
-	    break;
-
-	  case 'b':
-	    {
-		VALUE bitstr;
-		char *t;
-		int bits;
-		long i;
-
-		if (p[-1] == '*' || len > (send - s) * 8)
-		    len = (send - s) * 8;
-		bits = 0;
-		bitstr = rb_bstr_new();
-		rb_bstr_resize(bitstr, len);
-		UNPACK_PUSH(bitstr);
-		t = (char *)rb_bstr_bytes(bitstr);
-		for (i=0; i<len; i++) {
-		    if (i & 7) {
-			bits >>= 1;
-		    }
-		    else {
-			bits = *s++;
-		    }
-		    *t++ = (bits & 1) ? '1' : '0';
-		}
-	    }
-	    break;
-
-	  case 'B':
-	    {
-		VALUE bitstr;
-		char *t;
-		int bits;
-		long i;
-
-		if (p[-1] == '*' || len > (send - s) * 8)
-		    len = (send - s) * 8;
-		bits = 0;
-		bitstr = rb_bstr_new();
-		rb_bstr_resize(bitstr, len);
-		UNPACK_PUSH(bitstr);
-		t = (char *)rb_bstr_bytes(bitstr);
-		for (i=0; i<len; i++) {
-		    if (i & 7) {
-			bits <<= 1;
-		    }
-		    else {
-			bits = *s++;
-		    }
-		    *t++ = (bits & 128) ? '1' : '0';
-		}
-	    }
-	    break;
-
-	  case 'h':
-	    {
-		VALUE bitstr;
-		char *t;
-		int bits;
-		long i;
-
-		if (p[-1] == '*' || len > (send - s) * 2)
-		    len = (send - s) * 2;
-		bits = 0;
-		bitstr = rb_bstr_new();
-		rb_bstr_resize(bitstr, len);
-		UNPACK_PUSH(bitstr);
-		t = (char *)rb_bstr_bytes(bitstr);
-		for (i=0; i<len; i++) {
-		    if (i & 1) {
-			bits >>= 4;
-		    }
-		    else {
-			bits = *s++;
-		    }
-		    *t++ = hexdigits[bits & 15];
-		}
-	    }
-	    break;
-
-	  case 'H':
-	    {
-		VALUE bitstr;
-		char *t;
-		int bits;
-		long i;
-
-		if (p[-1] == '*' || len > (send - s) * 2)
-		    len = (send - s) * 2;
-		bits = 0;
-		bitstr = rb_bstr_new();
-		rb_bstr_resize(bitstr, len);
-		UNPACK_PUSH(bitstr);
-		t = (char *)rb_bstr_bytes(bitstr);
-		for (i=0; i<len; i++) {
-		    if (i & 1) {
-			bits <<= 4;
-		    }
-		    else {
-			bits = *s++;
-		    }
-		    *t++ = hexdigits[(bits >> 4) & 15];
-		}
-	    }
-	    break;
-
-	  case 'c':
-	    PACK_LENGTH_ADJUST(char,sizeof(char));
-	    while (len-- > 0) {
-                int c = *s++;
-                if (c > (char)127) c-=256;
-		UNPACK_PUSH(INT2FIX(c));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'C':
-	    PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
-	    while (len-- > 0) {
-		unsigned char c = *s++;
-		UNPACK_PUSH(INT2FIX(c));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 's':
-	    PACK_LENGTH_ADJUST(short,2);
-	    while (len-- > 0) {
-		short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(short,2));
-		EXTEND16(tmp);
-		s += NATINT_LEN(short,2);
-		UNPACK_PUSH(INT2FIX(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'S':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		UNPACK_PUSH(INT2FIX(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'i':
-	    PACK_LENGTH_ADJUST(int,sizeof(int));
-	    while (len-- > 0) {
-		int tmp;
-		memcpy(&tmp, s, sizeof(int));
-		s += sizeof(int);
-		UNPACK_PUSH(INT2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'I':
-	    PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
-	    while (len-- > 0) {
-		unsigned int tmp;
-		memcpy(&tmp, s, sizeof(unsigned int));
-		s += sizeof(unsigned int);
-		UNPACK_PUSH(UINT2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'l':
-	    PACK_LENGTH_ADJUST(long,4);
-	    while (len-- > 0) {
-		long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
-		EXTEND32(tmp);
-		s += NATINT_LEN(long,4);
-		UNPACK_PUSH(LONG2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-	  case 'L':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(unsigned long,4));
-		s += NATINT_LEN(unsigned long,4);
-		UNPACK_PUSH(ULONG2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'q':
-	    PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
-	    while (len-- > 0) {
-		char *tmp = (char*)s;
-		s += QUAD_SIZE;
-		UNPACK_PUSH(rb_quad_unpack(tmp, 1));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-	  case 'Q':
-	    PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
-	    while (len-- > 0) {
-		char *tmp = (char*)s;
-		s += QUAD_SIZE;
-		UNPACK_PUSH(rb_quad_unpack(tmp, 0));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'n':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16B(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		UNPACK_PUSH(UINT2NUM(ntohs(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'N':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32B(&tmp), s, NATINT_LEN(unsigned long,4));
-		s += NATINT_LEN(unsigned long,4);
-		UNPACK_PUSH(ULONG2NUM(ntohl(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'v':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		UNPACK_PUSH(UINT2NUM(vtohs(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'V':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
-		s += NATINT_LEN(long,4);
-		UNPACK_PUSH(ULONG2NUM(vtohl(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'f':
-	  case 'F':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
-	    while (len-- > 0) {
-		float tmp;
-		memcpy(&tmp, s, sizeof(float));
-		s += sizeof(float);
-		UNPACK_PUSH(DOUBLE2NUM((double)tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'e':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
-	    while (len-- > 0) {
-	        float tmp;
-		FLOAT_CONVWITH(ftmp);
-
-		memcpy(&tmp, s, sizeof(float));
-		s += sizeof(float);
-		tmp = VTOHF(tmp,ftmp);
-		UNPACK_PUSH(DOUBLE2NUM((double)tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'E':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
-	    while (len-- > 0) {
-		double tmp;
-		DOUBLE_CONVWITH(dtmp);
-
-		memcpy(&tmp, s, sizeof(double));
-		s += sizeof(double);
-		tmp = VTOHD(tmp,dtmp);
-		UNPACK_PUSH(DOUBLE2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'D':
-	  case 'd':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
-	    while (len-- > 0) {
-		double tmp;
-		memcpy(&tmp, s, sizeof(double));
-		s += sizeof(double);
-		UNPACK_PUSH(DOUBLE2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'g':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
-	    while (len-- > 0) {
-	        float tmp;
-		FLOAT_CONVWITH(ftmp;)
-
-		memcpy(&tmp, s, sizeof(float));
-		s += sizeof(float);
-		tmp = NTOHF(tmp,ftmp);
-		UNPACK_PUSH(DOUBLE2NUM((double)tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'G':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
-	    while (len-- > 0) {
-		double tmp;
-		DOUBLE_CONVWITH(dtmp);
-
-		memcpy(&tmp, s, sizeof(double));
-		s += sizeof(double);
-		tmp = NTOHD(tmp,dtmp);
-		UNPACK_PUSH(DOUBLE2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
-
-	  case 'U':
-	    if (len > send - s) len = send - s;
-	    while (len > 0 && s < send) {
-		long alen = send - s;
-		unsigned long l;
-
-		l = utf8_to_uv(s, &alen);
-		s += alen; len--;
-		UNPACK_PUSH(ULONG2NUM(l));
-	    }
-	    break;
-
-	  case 'u':
-	    {
-		VALUE buf = rb_bstr_new();
-		rb_bstr_resize(buf, (send - s)*3/4);
-		char *ptr = (char *)rb_bstr_bytes(buf);
-		long total = 0;
-		const long buflen = rb_bstr_length(buf);
-
-		while (s < send && *s > ' ' && *s < 'a') {
-		    long a,b,c,d;
-		    char hunk[4];
-
-		    hunk[3] = '\0';
-		    len = (*s++ - ' ') & 077;
-		    total += len;
-		    if (total > buflen) {
-			len -= total - buflen;
-			total = buflen;
-		    }
-
-		    while (len > 0) {
-			long mlen = len > 3 ? 3 : len;
-
-			if (s < send && *s >= ' ') {
-			    a = (*s++ - ' ') & 077;
-			}
-			else {
-			    a = 0;
-			}
-			if (s < send && *s >= ' ') {
-			    b = (*s++ - ' ') & 077;
-			}
-			else {
-			    b = 0;
-			}
-			if (s < send && *s >= ' ') {
-			    c = (*s++ - ' ') & 077;
-			}
-			else {
-			    c = 0;
-			}
-			if (s < send && *s >= ' ') {
-			    d = (*s++ - ' ') & 077;
-			}
-			else {
-			    d = 0;
-			}
-			hunk[0] = a << 2 | b >> 4;
-			hunk[1] = b << 4 | c >> 2;
-			hunk[2] = c << 6 | d;
-			memcpy(ptr, hunk, mlen);
-			ptr += mlen;
-			len -= mlen;
-		    }
-		    if (*s == '\r') {
-			s++;
-		    }
-		    if (*s == '\n') {
-			s++;
-		    }
-		    else if (s < send && (s+1 == send || s[1] == '\n')) {
-			s += 2;	/* possible checksum byte */
-		    }
-		}
-
-		rb_bstr_resize(buf, total);
-		UNPACK_PUSH(buf);
-	    }
-	    break;
-
-	  case 'm':
-	    {
-		VALUE buf = rb_bstr_new();
-		rb_bstr_resize(buf, (send - s)*3/4);
-		char *ptr = (char *)rb_bstr_bytes(buf);
-		char *ptr_beg = ptr;
-		int a = -1,b = -1,c = 0,d;
-		static int first = 1;
-		static int b64_xtable[256];
-
-		if (first) {
-		    int i;
-		    first = 0;
-
-		    for (i = 0; i < 256; i++) {
-			b64_xtable[i] = -1;
-		    }
-		    for (i = 0; i < 64; i++) {
-			b64_xtable[(int)b64_table[i]] = i;
-		    }
-		}
-		while (s < send) {
-		    a = b = c = d = -1;
-		    while((a = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { s++; }
-		    if( s >= send ) break;
-		    s++;
-		    while((b = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { s++; }
-		    if( s >= send ) break;
-		    s++;
-		    while((c = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { if( *s == '=' ) break; s++; }
-		    if( *s == '=' || s >= send ) break;
-		    s++;
-		    while((d = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { if( *s == '=' ) break; s++; }
-		    if( *s == '=' || s >= send ) break;
-		    s++;
-		    *ptr++ = a << 2 | b >> 4;
-		    *ptr++ = b << 4 | c >> 2;
-		    *ptr++ = c << 6 | d;
-		}
-		if (a != -1 && b != -1) {
-		    if (c == -1 && *s == '=') {
-			*ptr++ = a << 2 | b >> 4;
-		    }
-		    else if (c != -1 && *s == '=') {
-			*ptr++ = a << 2 | b >> 4;
-			*ptr++ = b << 4 | c >> 2;
-		    }
-		}
-		rb_bstr_resize(buf, ptr - ptr_beg);
-		UNPACK_PUSH(buf);
-	    }
-	    break;
-
-	  case 'M':
-	    {
-		VALUE buf = rb_bstr_new();
-		rb_bstr_resize(buf, send - s);
-		char *ptr = (char *)rb_bstr_bytes(buf);
-		char *ptr_beg = ptr;
-		int c1, c2;
-
-		while (s < send) {
-		    if (*s == '=') {
-			if (++s == send) break;
-                       if (s+1 < send && *s == '\r' && *(s+1) == '\n')
-                         s++;
-			if (*s != '\n') {
-			    if ((c1 = hex2num(*s)) == -1) break;
-			    if (++s == send) break;
-			    if ((c2 = hex2num(*s)) == -1) break;
-			    *ptr++ = c1 << 4 | c2;
-			}
-		    }
-		    else {
-			*ptr++ = *s;
-		    }
-		    s++;
-		}
-		rb_bstr_resize(buf, ptr - ptr_beg);
-		UNPACK_PUSH(buf);
-	    }
-	    break;
-
-	  case '@':
-	    if (len > RSTRING_LEN(str))
-		rb_raise(rb_eArgError, "@ outside of string");
-	    s = RSTRING_PTR(str) + len;
-	    break;
-
-	  case 'X':
-	    if (len > s - RSTRING_PTR(str))
-		rb_raise(rb_eArgError, "X outside of string");
-	    s -= len;
-	    break;
-
-	  case 'x':
-	    if (len > send - s)
-		rb_raise(rb_eArgError, "x outside of string");
-	    s += len;
-	    break;
-
-	  case 'P':
-	    if (sizeof(char *) <= send - s) {
-		VALUE tmp = Qnil;
-		char *t;
-
-		memcpy(&t, s, sizeof(char *));
-		s += sizeof(char *);
-
-		if (t) {
-		    VALUE a;
-		    long i, count;
-		    if (!(a = rb_str_associated(str))) {
-			rb_raise(rb_eArgError, "no associated pointer");
-		    }
-		    count = RARRAY_LEN(a);
-		    for (i = 0; i < count; i++) {
-			VALUE p = RARRAY_AT(a, i);
-			if (TYPE(p) == T_STRING && RSTRING_PTR(p) == t) {
-			    if (len < RSTRING_LEN(p)) {
-				tmp = rb_tainted_str_new(t, len);
-				rb_str_associate(tmp, a);
-			    }
-			    else {
-				tmp = p;
-			    }
-			    break;
-			}
-		    }
-		    if (i == count) {
-			rb_raise(rb_eArgError, "non associated pointer");
-		    }
-		}
-		else {
-		    tmp = Qnil;
-		}
-		UNPACK_PUSH(tmp);
-	    }
-	    break;
-
-	  case 'p':
-	    if (len > (send - s) / sizeof(char *))
-		len = (send - s) / sizeof(char *);
-	    while (len-- > 0) {
-		if (send - s < sizeof(char *))
-		    break;
-		else {
-		    VALUE tmp = Qnil;
-		    char *t;
-
-		    memcpy(&t, s, sizeof(char *));
-		    s += sizeof(char *);
-
-		    if (t != NULL) {
-			VALUE a;
-			long i, count;
-
-			if (!(a = rb_str_associated(str))) {
-			    rb_raise(rb_eArgError, "no associated pointer");
-			}
-			count = RARRAY_LEN(a);
-			for (i = 0; i < count; i++) {
-			    VALUE p = RARRAY_AT(a, i);
-			    if (TYPE(p) == T_STRING && RSTRING_PTR(p) == t) {
-				tmp = p;
-				break;
-			    }
-			}
-			if (i == count) {
-			    rb_raise(rb_eArgError, "non associated pointer");
-			}
-		    }
-		    else {
-			tmp = Qnil;
-		    }
-		    UNPACK_PUSH(tmp);
-		}
-	    }
-	    break;
-
-	  case 'w':
-	    {
-		unsigned long ul = 0;
-		unsigned long ulmask = 0xfeUL << ((sizeof(unsigned long) - 1) * 8);
-
-		while (len > 0 && s < send) {
-		    ul <<= 7;
-		    ul |= (*s & 0x7f);
-		    if (!(*s++ & 0x80)) {
-			UNPACK_PUSH(ULONG2NUM(ul));
-			len--;
-			ul = 0;
-		    }
-		    else if (ul & ulmask) {
-			VALUE big = rb_uint2big(ul);
-			VALUE big128 = rb_uint2big(128);
-			while (s < send) {
-			    big = rb_big_mul(big, big128);
-			    big = rb_big_plus(big, rb_uint2big(*s & 0x7f));
-			    if (!(*s++ & 0x80)) {
-				UNPACK_PUSH(big);
-				len--;
-				ul = 0;
-				break;
-			    }
-			}
-		    }
-		}
-	    }
-	    break;
-
-	  default:
-	    break;
-	}
-    }
-
-    return ary;
-}
-
-#define BYTEWIDTH 8
-
-int
-rb_uv_to_utf8(char buf[6], unsigned long uv)
-{
-    if (uv <= 0x7f) {
-	buf[0] = (char)uv;
-	return 1;
-    }
-    if (uv <= 0x7ff) {
-	buf[0] = ((uv>>6)&0xff)|0xc0;
-	buf[1] = (uv&0x3f)|0x80;
-	return 2;
-    }
-    if (uv <= 0xffff) {
-	buf[0] = ((uv>>12)&0xff)|0xe0;
-	buf[1] = ((uv>>6)&0x3f)|0x80;
-	buf[2] = (uv&0x3f)|0x80;
-	return 3;
-    }
-    if (uv <= 0x1fffff) {
-	buf[0] = ((uv>>18)&0xff)|0xf0;
-	buf[1] = ((uv>>12)&0x3f)|0x80;
-	buf[2] = ((uv>>6)&0x3f)|0x80;
-	buf[3] = (uv&0x3f)|0x80;
-	return 4;
-    }
-    if (uv <= 0x3ffffff) {
-	buf[0] = ((uv>>24)&0xff)|0xf8;
-	buf[1] = ((uv>>18)&0x3f)|0x80;
-	buf[2] = ((uv>>12)&0x3f)|0x80;
-	buf[3] = ((uv>>6)&0x3f)|0x80;
-	buf[4] = (uv&0x3f)|0x80;
-	return 5;
-    }
-    if (uv <= 0x7fffffff) {
-	buf[0] = ((uv>>30)&0xff)|0xfc;
-	buf[1] = ((uv>>24)&0x3f)|0x80;
-	buf[2] = ((uv>>18)&0x3f)|0x80;
-	buf[3] = ((uv>>12)&0x3f)|0x80;
-	buf[4] = ((uv>>6)&0x3f)|0x80;
-	buf[5] = (uv&0x3f)|0x80;
-	return 6;
-    }
-    rb_raise(rb_eRangeError, "pack(U): value out of range");
-}
-
-static const unsigned long utf8_limits[] = {
-    0x0,			/* 1 */
-    0x80,			/* 2 */
-    0x800,			/* 3 */
-    0x10000,			/* 4 */
-    0x200000,			/* 5 */
-    0x4000000,			/* 6 */
-    0x80000000,			/* 7 */
-};
-
-static unsigned long
-utf8_to_uv(const char *p, long *lenp)
-{
-    int c = *p++ & 0xff;
-    unsigned long uv = c;
-    long n;
-
-    if (!(uv & 0x80)) {
-	*lenp = 1;
-        return uv;
-    }
-    if (!(uv & 0x40)) {
-	*lenp = 1;
-	rb_raise(rb_eArgError, "malformed UTF-8 character");
-    }
-
-    if      (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
-    else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
-    else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
-    else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
-    else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
-    else {
-	*lenp = 1;
-	rb_raise(rb_eArgError, "malformed UTF-8 character");
-    }
-    if (n > *lenp) {
-	rb_raise(rb_eArgError, "malformed UTF-8 character (expected %ld bytes, given %ld bytes)",
-		 n, *lenp);
-    }
-    *lenp = n--;
-    if (n != 0) {
-	while (n--) {
-	    c = *p++ & 0xff;
-	    if ((c & 0xc0) != 0x80) {
-		*lenp -= n + 1;
-		rb_raise(rb_eArgError, "malformed UTF-8 character");
-	    }
-	    else {
-		c &= 0x3f;
-		uv = uv << 6 | c;
-	    }
-	}
-    }
-    n = *lenp - 1;
-    if (uv < utf8_limits[n]) {
-	rb_raise(rb_eArgError, "redundant UTF-8 sequence");
-    }
-    return uv;
-}
-
-void
-Init_pack(void)
-{
-    rb_objc_define_method(rb_cArray, "pack", pack_pack, 1);
-    rb_objc_define_method(rb_cString, "unpack", pack_unpack, 1);
-}

Deleted: MacRuby/trunk/parse.y
===================================================================
--- MacRuby/trunk/parse.y	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/parse.y	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,10036 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2010, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-%{
-
-#define YYDEBUG 1
-#define YYERROR_VERBOSE 1
-#define YYSTACK_USE_ALLOCA 0
-
-#include "macruby_internal.h"
-#include "ruby/intern.h"
-#define __IN_PARSE_Y__ 1
-#include "ruby/node.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "symbol.h"
-#include "id.h"
-#include "re.h"
-#include "class.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-
-#define YYMALLOC(size)		rb_parser_malloc(parser, size)
-#define YYREALLOC(ptr, size)	rb_parser_realloc(parser, ptr, size)
-#define YYCALLOC(nelem, size)	rb_parser_calloc(parser, nelem, size)
-#define YYFREE(ptr)		rb_parser_free(parser, ptr)
-static inline void *orig_malloc(size_t l) { return malloc(l); }
-static inline void orig_free(void *ptr) { free(ptr); }
-#define malloc	YYMALLOC
-#define realloc	YYREALLOC
-#define calloc	YYCALLOC
-#define free	YYFREE
-
-enum lex_state_e {
-    EXPR_BEG,			/* ignore newline, +/- is a sign. */
-    EXPR_END,			/* newline significant, +/- is a operator. */
-    EXPR_ENDARG,		/* ditto, and unbound braces. */
-    EXPR_ARG,			/* newline significant, +/- is a operator. */
-    EXPR_CMDARG,		/* newline significant, +/- is a operator. */
-    EXPR_MID,			/* newline significant, +/- is a operator. */
-    EXPR_FNAME,			/* ignore newline, no reserved words. */
-    EXPR_DOT,			/* right after `.' or `::', no reserved words. */
-    EXPR_CLASS,			/* immediate after `class', no here document. */
-    EXPR_VALUE,			/* alike EXPR_BEG but label is disallowed. */
-};
-
-# ifdef HAVE_LONG_LONG
-typedef unsigned LONG_LONG stack_type;
-# else
-typedef unsigned long stack_type;
-# endif
-
-# define BITSTACK_PUSH(stack, n)	(stack = (stack<<1)|((n)&1))
-# define BITSTACK_POP(stack)	(stack = stack >> 1)
-# define BITSTACK_LEXPOP(stack)	(stack = (stack >> 1) | (stack & 1))
-# define BITSTACK_SET_P(stack)	(stack&1)
-
-#define COND_PUSH(n)	BITSTACK_PUSH(cond_stack, n)
-#define COND_POP()	BITSTACK_POP(cond_stack)
-#define COND_LEXPOP()	BITSTACK_LEXPOP(cond_stack)
-#define COND_P()	BITSTACK_SET_P(cond_stack)
-
-#define CMDARG_PUSH(n)	BITSTACK_PUSH(cmdarg_stack, n)
-#define CMDARG_POP()	BITSTACK_POP(cmdarg_stack)
-#define CMDARG_LEXPOP()	BITSTACK_LEXPOP(cmdarg_stack)
-#define CMDARG_P()	BITSTACK_SET_P(cmdarg_stack)
-
-/* must sync with real YYSTYPE */
-union tmpyystype {
-    VALUE val;
-    NODE *node;
-    unsigned long id;
-    int num;
-    struct RVarmap *vars;
-};
-
-struct vtable {
-    ID *tbl;
-    int pos;
-    int capa;
-    struct vtable *prev;
-};
-
-struct local_vars {
-    struct vtable *args;
-    struct vtable *vars;
-    struct local_vars *prev;
-};
-
-#define DVARS_INHERIT ((void*)1)
-#define DVARS_TOPSCOPE NULL
-#define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
-#define POINTER_P(val) ((VALUE)(val) & ~(VALUE)3)
-
-#ifndef RIPPER
-static int
-vtable_size(const struct vtable *tbl)
-{
-    if (POINTER_P(tbl)) {
-        return tbl->pos;
-    }
-    else {
-        return 0;
-    }
-}
-
-#define VTBL_DEBUG 0
-
-static struct vtable *
-vtable_alloc(struct vtable *prev)
-{
-    struct vtable *tbl = ALLOC(struct vtable);
-    tbl->pos = 0;
-    tbl->capa = 8;
-    GC_WB(&tbl->tbl, ALLOC_N(ID, tbl->capa));
-    GC_WB(&tbl->prev, prev);
-    if (VTBL_DEBUG) printf("vtable_alloc: %p\n", tbl);
-    return tbl;
-}
-
-static void
-vtable_free(struct vtable *tbl)
-{
-    if (VTBL_DEBUG)printf("vtable_free: %p\n", tbl);
-    if (POINTER_P(tbl)) {
-        if (tbl->tbl) {
-            xfree(tbl->tbl);
-        }
-        if (tbl) {
-            xfree(tbl);
-        }
-    }
-}
-
-static void
-vtable_add(struct vtable *tbl, ID id)
-{
-    if (!POINTER_P(tbl)) {
-        rb_bug("vtable_add: vtable is not allocated (%p)", tbl);
-    }
-    if (VTBL_DEBUG) printf("vtable_add: %p, %s\n", tbl, rb_id2name(id));
-
-    if (tbl->pos == tbl->capa) {
-        tbl->capa = tbl->capa * 2;
-        REALLOC_N(tbl->tbl, ID, tbl->capa);
-        GC_WB(&tbl->tbl, tbl->tbl);
-    }
-    tbl->tbl[tbl->pos++] = id;
-}
-
-static int
-vtable_included(const struct vtable * tbl, ID id)
-{
-    int i;
-
-    if (POINTER_P(tbl)) {
-        for (i = 0; i < tbl->pos; i++) {
-            if (tbl->tbl[i] == id) {
-                return 1;
-            }
-        }
-    }
-    return 0;
-}
-
-static ID*
-vtable_tblcpy(ID *buf, const struct vtable *src)
-{
-    int i, cnt = vtable_size(src);
-
-    if (cnt > 0) {
-        buf[0] = cnt;
-        for (i = 0; i < cnt; i++) {
-            buf[i] = src->tbl[i];
-        }
-        return buf;
-    }
-    return 0;
-}
-
-#endif
-
-/*
-    Structure of Lexer Buffer:
-
- lex_pbeg      tokp         lex_p        lex_pend
-    |           |              |            |
-    |-----------+--------------+------------|
-                |<------------>|
-                     token
-*/
-struct parser_params {
-    int is_ripper;
-    NODE *heap;
-
-    union tmpyystype *parser_yylval;   /* YYSTYPE not defined yet */
-    VALUE eofp;
-
-    NODE *parser_lex_strterm;
-    enum lex_state_e parser_lex_state;
-    stack_type parser_cond_stack;
-    stack_type parser_cmdarg_stack;
-    int parser_class_nest;
-    int parser_paren_nest;
-    int parser_lpar_beg;
-    int parser_in_single;
-    int parser_in_def;
-#if WITH_OBJC
-    int parser_in_def_named_args;
-    char parser_named_mid[1024];
-#endif
-    int parser_compile_for_eval;
-    VALUE parser_cur_mid;
-    int parser_in_defined;
-    char *parser_tokenbuf;
-    int parser_tokidx;
-    int parser_toksiz;
-    VALUE parser_lex_input;
-    VALUE parser_lex_lastline;
-    VALUE parser_lex_nextline;
-    const char *parser_lex_pbeg;
-    const char *parser_lex_p;
-    const char *parser_lex_pend;
-    int parser_heredoc_end;
-    int parser_command_start;
-    int parser_lex_gets_ptr;
-    VALUE (*parser_lex_gets)(struct parser_params*,VALUE);
-    struct local_vars *parser_lvtbl;
-    int parser_ruby__end__seen;
-    int line_count;
-    int has_shebang;
-    char *parser_ruby_sourcefile; /* current source file */
-    int parser_ruby_sourceline;	/* current line no. */
-    rb_encoding *enc;
-    rb_encoding *utf8;
-
-    int parser_yydebug;
-
-#ifndef RIPPER
-    /* Ruby core only */
-    NODE *parser_eval_tree_begin;
-    NODE *parser_eval_tree;
-    VALUE debug_lines;
-    int nerr;
-#else
-    /* Ripper only */
-    VALUE parser_ruby_sourcefile_string;
-    const char *tokp;
-    VALUE delayed;
-    int delayed_line;
-    int delayed_col;
-
-    VALUE value;
-    VALUE result;
-    VALUE parsing_thread;
-    int toplevel_p;
-#endif
-};
-
-#if WITH_OBJC
-// TODO: we should probably mimic what 1.9 does here and use the right/given
-// encoding instead of always UTF8.
-# define UTF8_ENC() (NULL)
-# define __new_tmp_str(p, n) (rb_str_new(p, n))
-# define STR_NEW(p,n) __new_tmp_str(p, n)
-# define STR_NEW0() __new_tmp_str(0, 0)
-# define STR_NEW2(p) __new_tmp_str(p, strlen(p))
-# define STR_NEW3(p,n,e,func) __new_tmp_str(p, n)
-#else
-# define UTF8_ENC() (parser->utf8 ? parser->utf8 : \
-		    (parser->utf8 = rb_utf8_encoding()))
-# define STR_NEW(p,n) rb_enc_str_new((p),(n),parser->enc)
-# define STR_NEW0() rb_usascii_str_new(0,0)
-# define STR_NEW2(p) rb_enc_str_new((p),strlen(p),parser->enc)
-# define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),parser->enc)
-#endif
-#if WITH_OBJC
-# define STR_ENC(m) (NULL)
-# define ENC_SINGLE(cr) (1)
-#else
-# define STR_ENC(m) ((m)?parser->enc:rb_usascii_encoding())
-# define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
-#endif
-#define TOK_INTERN(mb) rb_intern3(tok(), toklen(), STR_ENC(mb))
-
-#ifdef YYMALLOC
-void *rb_parser_malloc(struct parser_params *, size_t);
-void *rb_parser_realloc(struct parser_params *, void *, size_t);
-void *rb_parser_calloc(struct parser_params *, size_t, size_t);
-void rb_parser_free(struct parser_params *, void *);
-#endif
-
-static int parser_yyerror(struct parser_params*, const char*);
-#define yyerror(msg) parser_yyerror(parser, msg)
-
-#define YYLEX_PARAM parser
-
-#define lex_strterm		(parser->parser_lex_strterm)
-#define lex_state		(parser->parser_lex_state)
-#define cond_stack		(parser->parser_cond_stack)
-#define cmdarg_stack		(parser->parser_cmdarg_stack)
-#define class_nest		(parser->parser_class_nest)
-#define paren_nest		(parser->parser_paren_nest)
-#define lpar_beg		(parser->parser_lpar_beg)
-#define in_single		(parser->parser_in_single)
-#define in_def			(parser->parser_in_def)
-#if WITH_OBJC
-# define in_def_named_args	(parser->parser_in_def_named_args)
-# define named_mid		(parser->parser_named_mid)
-#endif
-#define compile_for_eval	(parser->parser_compile_for_eval)
-#define cur_mid			(parser->parser_cur_mid)
-#define in_defined		(parser->parser_in_defined)
-#define tokenbuf		(parser->parser_tokenbuf)
-#define tokidx			(parser->parser_tokidx)
-#define toksiz			(parser->parser_toksiz)
-#define lex_input		(parser->parser_lex_input)
-#define lex_lastline		(parser->parser_lex_lastline)
-#define lex_nextline		(parser->parser_lex_nextline)
-#define lex_pbeg		(parser->parser_lex_pbeg)
-#define lex_p			(parser->parser_lex_p)
-#define lex_pend		(parser->parser_lex_pend)
-#define heredoc_end		(parser->parser_heredoc_end)
-#define command_start		(parser->parser_command_start)
-#define lex_gets_ptr		(parser->parser_lex_gets_ptr)
-#define lex_gets		(parser->parser_lex_gets)
-#define lvtbl			(parser->parser_lvtbl)
-#define ruby__end__seen		(parser->parser_ruby__end__seen)
-#define ruby_sourceline		(parser->parser_ruby_sourceline)
-#define ruby_sourcefile		(parser->parser_ruby_sourcefile)
-#define yydebug			(parser->parser_yydebug)
-#ifdef RIPPER
-#else
-#define ruby_eval_tree		(parser->parser_eval_tree)
-#define ruby_eval_tree_begin	(parser->parser_eval_tree_begin)
-#define ruby_debug_lines	(parser->debug_lines)
-#endif
-
-static int yylex(void*, void*);
-
-#ifndef RIPPER
-#define yyparse ruby_yyparse
-
-static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE);
-#define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, type, a1, a2, a3)
-
-static NODE *cond_gen(struct parser_params*,NODE*);
-#define cond(node) cond_gen(parser, node)
-static NODE *logop_gen(struct parser_params*,enum node_type,NODE*,NODE*);
-#define logop(type,node1,node2) logop_gen(parser, type, node1, node2)
-
-static NODE *newline_node(NODE*);
-static void fixpos(NODE*,NODE*);
-
-static int value_expr_gen(struct parser_params*,NODE*);
-static void void_expr_gen(struct parser_params*,NODE*);
-static NODE *remove_begin(NODE*);
-#define value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
-#define void_expr0(node) void_expr_gen(parser, (node))
-#define void_expr(node) void_expr0((node) = remove_begin(node))
-static void void_stmts_gen(struct parser_params*,NODE*);
-#define void_stmts(node) void_stmts_gen(parser, node)
-static void reduce_nodes_gen(struct parser_params*,NODE**);
-#define reduce_nodes(n) reduce_nodes_gen(parser,n)
-static void block_dup_check_gen(struct parser_params*,NODE*,NODE*);
-#define block_dup_check(n1,n2) block_dup_check_gen(parser,n1,n2)
-
-static NODE *block_append_gen(struct parser_params*,NODE*,NODE*);
-#define block_append(h,t) block_append_gen(parser,h,t)
-static NODE *list_append_gen(struct parser_params*,NODE*,NODE*);
-#define list_append(l,i) list_append_gen(parser,l,i)
-static NODE *list_concat_gen(struct parser_params*,NODE*,NODE*);
-#define list_concat(h,t) list_concat_gen(parser,h,t)
-static NODE *arg_append_gen(struct parser_params*,NODE*,NODE*);
-#define arg_append(h,t) arg_append_gen(parser,h,t)
-static NODE *arg_concat_gen(struct parser_params*,NODE*,NODE*);
-#define arg_concat(h,t) arg_concat_gen(parser,h,t)
-static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*);
-#define literal_concat(h,t) literal_concat_gen(parser,h,t)
-static NODE *new_evstr_gen(struct parser_params*,NODE*);
-#define new_evstr(n) new_evstr_gen(parser,n)
-static NODE *evstr2dstr_gen(struct parser_params*,NODE*);
-#define evstr2dstr(n) evstr2dstr_gen(parser,n)
-static NODE *splat_array(NODE*);
-
-static NODE *call_bin_op_gen(struct parser_params*,NODE*,ID,NODE*);
-#define call_bin_op(recv,id,arg1) call_bin_op_gen(parser, recv,id,arg1)
-static NODE *call_uni_op_gen(struct parser_params*,NODE*,ID);
-#define call_uni_op(recv,id) call_uni_op_gen(parser, recv,id)
-
-static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,ID);
-#define new_args(f,o,r,p,b) new_args_gen(parser, f,o,r,p,b)
-static void shadowing_lvar_gen(struct parser_params*,ID);
-#define shadowing_lvar(name) shadowing_lvar_gen(parser, name)
-
-static NODE *negate_lit(NODE*);
-static NODE *ret_args_gen(struct parser_params*,NODE*);
-#define ret_args(node) ret_args_gen(parser, node)
-static NODE *arg_blk_pass(NODE*,NODE*);
-static NODE *new_yield_gen(struct parser_params*,NODE*);
-#define new_yield(node) new_yield_gen(parser, node)
-
-static NODE *gettable_gen(struct parser_params*,ID);
-#define gettable(id) gettable_gen(parser,id)
-static NODE *assignable_gen(struct parser_params*,ID,NODE*);
-#define assignable(id,node) assignable_gen(parser, id, node)
-static void new_bv_gen(struct parser_params*,ID);
-#define new_bv(id) new_bv_gen(parser, id)
-static NODE *aryset_gen(struct parser_params*,NODE*,NODE*);
-#define aryset(node1,node2) aryset_gen(parser, node1, node2)
-static NODE *attrset_gen(struct parser_params*,NODE*,ID);
-#define attrset(node,id) attrset_gen(parser, node, id)
-
-static void rb_backref_error_gen(struct parser_params*,NODE*);
-#define rb_backref_error(n) rb_backref_error_gen(parser,n)
-static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*);
-#define node_assign(node1, node2) node_assign_gen(parser, node1, node2)
-
-static NODE *match_op_gen(struct parser_params*,NODE*,NODE*);
-#define match_op(node1,node2) match_op_gen(parser, node1, node2)
-
-static void local_push_gen(struct parser_params*,int);
-#define local_push(top) local_push_gen(parser,top)
-static void local_pop_gen(struct parser_params*);
-#define local_pop() local_pop_gen(parser)
-static int local_var_gen(struct parser_params*, ID);
-#define local_var(id) local_var_gen(parser, id);
-static int arg_var_gen(struct parser_params*, ID);
-#define arg_var(id) arg_var_gen(parser, id)
-#if WITH_OBJC
-static void named_arg_gen(struct parser_params*, ID, int);
-# define named_arg(id, flag) named_arg_gen(parser, id, flag)
-static NODE *process_named_args_gen(struct parser_params*, NODE*);
-# define process_named_args(node) process_named_args_gen(parser, node)
-static NODE *unprocess_named_args_gen(struct parser_params*, NODE*);
-# define unprocess_named_args(node) unprocess_named_args_gen(parser, node)
-#endif
-static int  local_id_gen(struct parser_params*, ID);
-#define local_id(id) local_id_gen(parser, id)
-static ID  *local_tbl_gen(struct parser_params*);
-#define local_tbl() local_tbl_gen(parser)
-static ID   internal_id_gen(struct parser_params*);
-#define internal_id() internal_id_gen(parser)
-
-static void dyna_push_gen(struct parser_params*);
-#define dyna_push() dyna_push_gen(parser)
-static void dyna_pop_gen(struct parser_params*);
-#define dyna_pop() dyna_pop_gen(parser)
-static int dyna_in_block_gen(struct parser_params*);
-#define dyna_in_block() dyna_in_block_gen(parser)
-#define dyna_var(id) local_var(id)
-static int dvar_defined_gen(struct parser_params*,ID);
-#define dvar_defined(id) dvar_defined_gen(parser, id)
-static int dvar_curr_gen(struct parser_params*,ID);
-#define dvar_curr(id) dvar_curr_gen(parser, id)
-
-extern int rb_dvar_defined(ID);
-extern int rb_local_defined(ID);
-extern int rb_parse_in_eval(void);
-
-static VALUE reg_compile_gen(struct parser_params*, VALUE, int);
-#define reg_compile(str,options) reg_compile_gen(parser, str, options)
-static void reg_fragment_setenc_gen(struct parser_params*, VALUE, int);
-#define reg_fragment_setenc(str,options) reg_fragment_setenc_gen(parser, str, options)
-static void reg_fragment_check_gen(struct parser_params*, VALUE, int);
-#define reg_fragment_check(str,options) reg_fragment_check_gen(parser, str, options)
-static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
-#define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,regexp,match)
-#else
-#define remove_begin(node) (node)
-#endif /* !RIPPER */
-static int lvar_defined_gen(struct parser_params*, ID);
-#define lvar_defined(id) lvar_defined_gen(parser, id)
-
-#define RE_OPTION_ONCE (1<<16)
-#define RE_OPTION_ENCODING_SHIFT 8
-#define RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
-#define RE_OPTION_ENCODING_IDX(o) (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
-#define RE_OPTION_ENCODING_NONE(o) ((o)&RE_OPTION_ARG_ENCODING_NONE)
-#define RE_OPTION_MASK  0xff
-#define RE_OPTION_ARG_ENCODING_NONE 32
-
-#define NODE_STRTERM NODE_ZARRAY	/* nothing to gc */
-#define NODE_HEREDOC NODE_ARRAY 	/* 1, 3 to gc */
-#define SIGN_EXTEND(x,n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
-#define nd_func u1.id
-#if SIZEOF_SHORT == 2
-#define nd_term(node) ((signed short)(node)->u2.id)
-#else
-#define nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
-#endif
-#define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
-#define nd_nest u3.cnt
-
-/****** Ripper *******/
-
-#ifdef RIPPER
-#define RIPPER_VERSION "0.1.0"
-
-#include "eventids1.c"
-#include "eventids2.c"
-static ID ripper_id_gets;
-
-static VALUE ripper_dispatch0(struct parser_params*,ID);
-static VALUE ripper_dispatch1(struct parser_params*,ID,VALUE);
-static VALUE ripper_dispatch2(struct parser_params*,ID,VALUE,VALUE);
-static VALUE ripper_dispatch3(struct parser_params*,ID,VALUE,VALUE,VALUE);
-static VALUE ripper_dispatch4(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE);
-static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE);
-
-#define dispatch0(n)            ripper_dispatch0(parser, TOKEN_PASTE(ripper_id_, n))
-#define dispatch1(n,a)          ripper_dispatch1(parser, TOKEN_PASTE(ripper_id_, n), a)
-#define dispatch2(n,a,b)        ripper_dispatch2(parser, TOKEN_PASTE(ripper_id_, n), a, b)
-#define dispatch3(n,a,b,c)      ripper_dispatch3(parser, TOKEN_PASTE(ripper_id_, n), a, b, c)
-#define dispatch4(n,a,b,c,d)    ripper_dispatch4(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d)
-#define dispatch5(n,a,b,c,d,e)  ripper_dispatch5(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d, e)
-
-#define named_arg(id, flag)
-
-#define yyparse ripper_yyparse
-
-static VALUE ripper_intern(const char*);
-static VALUE ripper_id2sym(ID);
-
-#define arg_new() dispatch0(args_new)
-#define arg_add(l,a) dispatch2(args_add, l, a)
-#define arg_prepend(l,a) dispatch2(args_prepend, l, a)
-#define arg_add_star(l,a) dispatch2(args_add_star, l, a)
-#define arg_add_block(l,b) dispatch2(args_add_block, l, b)
-#define arg_add_optblock(l,b) ((b)==Qundef? l : dispatch2(args_add_block, l, b))
-#define bare_assoc(v) dispatch1(bare_assoc_hash, v)
-#define arg_add_assocs(l,b) arg_add(l, bare_assoc(b))
-
-#define args2mrhs(a) dispatch1(mrhs_new_from_args, a)
-#define mrhs_new() dispatch0(mrhs_new)
-#define mrhs_add(l,a) dispatch2(mrhs_add, l, a)
-#define mrhs_add_star(l,a) dispatch2(mrhs_add_star, l, a)
-
-#define mlhs_new() dispatch0(mlhs_new)
-#define mlhs_add(l,a) dispatch2(mlhs_add, l, a)
-#define mlhs_add_star(l,a) dispatch2(mlhs_add_star, l, a)
-
-#define params_new(pars, opts, rest, pars2, blk) \
-        dispatch5(params, pars, opts, rest, pars2, blk)
-
-#define blockvar_new(p,v) dispatch2(block_var, p, v)
-#define blockvar_add_star(l,a) dispatch2(block_var_add_star, l, a)
-#define blockvar_add_block(l,a) dispatch2(block_var_add_block, l, a)
-
-#define method_optarg(m,a) ((a)==Qundef ? m : dispatch2(method_add_arg,m,a))
-#define method_arg(m,a) dispatch2(method_add_arg,m,a)
-#define method_add_block(m,b) dispatch2(method_add_block, m, b)
-
-#define escape_Qundef(x) ((x)==Qundef ? Qnil : (x))
-
-#define FIXME 0
-
-#endif /* RIPPER */
-
-#ifndef RIPPER
-# define ifndef_ripper(x) x
-#else
-# define ifndef_ripper(x)
-#endif
-
-#ifndef RIPPER
-# define rb_warn0(fmt)    rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt)
-# define rb_warnI(fmt,a)  rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a)
-# define rb_warnS(fmt,a)  rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a)
-# define rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt)
-# define rb_warningS(fmt,a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt, a)
-#else
-# define rb_warn0(fmt)    ripper_warn0(parser, fmt)
-# define rb_warnI(fmt,a)  ripper_warnI(parser, fmt, a)
-# define rb_warnS(fmt,a)  ripper_warnS(parser, fmt, a)
-# define rb_warning0(fmt) ripper_warning0(parser, fmt)
-# define rb_warningS(fmt,a) ripper_warningS(parser, fmt, a)
-static void ripper_warn0(struct parser_params*, const char*);
-static void ripper_warnI(struct parser_params*, const char*, int);
-//static void ripper_warnS(struct parser_params*, const char*, const char*);
-static void ripper_warning0(struct parser_params*, const char*);
-static void ripper_warningS(struct parser_params*, const char*, const char*);
-#endif
-
-#ifdef RIPPER
-static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
-# define rb_compile_error ripper_compile_error
-# define compile_error ripper_compile_error
-# define PARSER_ARG parser,
-#else
-# define compile_error parser->nerr++,rb_compile_error
-# define PARSER_ARG ruby_sourcefile, ruby_sourceline,
-#endif
-
-/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
-   for instance).  This is too low for Ruby to parse some files, such as
-   date/format.rb, therefore bump the value up to at least Bison's default. */
-#ifdef OLD_YACC
-#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
-#endif
-#endif
-
-%}
-
-%pure_parser
-%parse-param {struct parser_params *parser}
-
-%union {
-    VALUE val;
-    NODE *node;
-    ID id;
-    int num;
-    struct RVarmap *vars;
-}
-
-/*%%%*/
-%token
-/*%
-%token <val>
-%*/
-	keyword_class
-	keyword_module
-	keyword_def
-	keyword_undef
-	keyword_begin
-	keyword_rescue
-	keyword_ensure
-	keyword_end
-	keyword_if
-	keyword_unless
-	keyword_then
-	keyword_elsif
-	keyword_else
-	keyword_case
-	keyword_when
-	keyword_while
-	keyword_until
-	keyword_for
-	keyword_break
-	keyword_next
-	keyword_redo
-	keyword_retry
-	keyword_in
-	keyword_do
-	keyword_do_cond
-	keyword_do_block
-	keyword_do_LAMBDA
-	keyword_return
-	keyword_yield
-	keyword_super
-	keyword_self
-	keyword_nil
-	keyword_true
-	keyword_false
-	keyword_and
-	keyword_or
-	keyword_not
-	modifier_if
-	modifier_unless
-	modifier_while
-	modifier_until
-	modifier_rescue
-	keyword_alias
-	keyword_defined
-	keyword_BEGIN
-	keyword_END
-	keyword__LINE__
-	keyword__FILE__
-	keyword__ENCODING__
-
-%token <id>   tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
-%token <node> tINTEGER tFLOAT tSTRING_CONTENT tCHAR
-%token <node> tNTH_REF tBACK_REF
-%token <num>  tREGEXP_END
-
-%type <node> singleton strings string string1 xstring regexp
-%type <node> string_contents xstring_contents string_content
-%type <node> words qwords word_list qword_list word
-%type <node> literal numeric dsym cpath
-%type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
-%type <node> expr_value arg_value primary_value
-%type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
-%type <node> args call_args call_args2 opt_call_args
-%type <node> open_args paren_args opt_paren_args
-%type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
-%type <node> mrhs superclass block_call block_command
-%type <node> f_block_optarg f_block_opt
-%type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
-%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
-%type <node> block_param opt_block_param block_param_def f_opt
-%type <node> bv_decls opt_bv_decl bvar
-%type <node> lambda f_larglist lambda_body
-%type <node> brace_block cmd_brace_block do_block lhs none fitem
-%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
-%type <id>   fsym variable sym symbol operation operation2 operation3
-%type <id>   cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
-/*%%%*/
-/*%
-%type <val> program reswords then do dot_or_colon
-%*/
-%token tUPLUS		/* unary+ */
-%token tUMINUS		/* unary- */
-%token tPOW		/* ** */
-%token tCMP		/* <=> */
-%token tEQ		/* == */
-%token tEQQ		/* === */
-%token tNEQ		/* != */
-%token tGEQ		/* >= */
-%token tLEQ		/* <= */
-%token tANDOP tOROP	/* && and || */
-%token tMATCH tNMATCH	/* =~ and !~ */
-%token tDOT2 tDOT3	/* .. and ... */
-%token tAREF tASET	/* [] and []= */
-%token tLSHFT tRSHFT	/* << and >> */
-%token tCOLON2		/* :: */
-%token tCOLON3		/* :: at EXPR_BEG */
-%token <id> tOP_ASGN	/* +=, -=  etc. */
-%token tASSOC		/* => */
-%token tLPAREN		/* ( */
-%token tLPAREN_ARG	/* ( */
-%token tRPAREN		/* ) */
-%token tLBRACK		/* [ */
-%token tLBRACE		/* { */
-%token tLBRACE_ARG	/* { */
-%token tSTAR		/* * */
-%token tAMPER		/* & */
-%token tLAMBDA		/* -> */
-%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
-%token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
-
-/*
- *	precedence table
- */
-
-%nonassoc tLOWEST
-%nonassoc tLBRACE_ARG
-
-%nonassoc  modifier_if modifier_unless modifier_while modifier_until
-%left  keyword_or keyword_and
-%right keyword_not
-%nonassoc keyword_defined
-%right '=' tOP_ASGN
-%left modifier_rescue
-%right '?' ':'
-%nonassoc tDOT2 tDOT3
-%left  tOROP
-%left  tANDOP
-%nonassoc  tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
-%left  '>' tGEQ '<' tLEQ
-%left  '|' '^'
-%left  '&'
-%left  tLSHFT tRSHFT
-%left  '+' '-'
-%left  '*' '/' '%'
-%right tUMINUS_NUM tUMINUS
-%right tPOW
-%right '!' '~' tUPLUS
-
-%token tLAST_TOKEN
-
-%%
-program		:  {
-			lex_state = EXPR_BEG;
-		    /*%%%*/
-			local_push(compile_for_eval);
-		    /*%
-		    %*/
-		    }
-		  compstmt
-		    {
-		    /*%%%*/
-			if ($2 && !compile_for_eval) {
-			    /* last expression should not be void */
-			    if (nd_type($2) != NODE_BLOCK) void_expr($2);
-			    else {
-				NODE *node = $2;
-				while (node->nd_next) {
-				    node = node->nd_next;
-				}
-				void_expr(node->nd_head);
-			    }
-			}
-			GC_WB(&ruby_eval_tree, NEW_SCOPE(0, block_append(ruby_eval_tree, $2)));
-			local_pop();
-		    /*%
-			$$ = $2;
-			parser->result = dispatch1(program, $$);
-		    %*/
-		    }
-		;
-
-bodystmt	: compstmt
-		  opt_rescue
-		  opt_else
-		  opt_ensure
-		    {
-		    /*%%%*/
-			$$ = $1;
-			if ($2) {
-			    $$ = NEW_RESCUE($1, $2, $3);
-			}
-			else if ($3) {
-			    rb_warn0("else without rescue is useless");
-			    $$ = block_append($$, $3);
-			}
-			if ($4) {
-			    if ($$) {
-				$$ = NEW_ENSURE($$, $4);
-			    }
-			    else {
-				$$ = block_append($4, NEW_NIL());
-			    }
-			}
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch4(body_stmt,
-				       escape_Qundef($1),
-				       escape_Qundef($2),
-				       escape_Qundef($3),
-				       escape_Qundef($4));
-		    %*/
-		    }
-		;
-
-compstmt	: stmts opt_terms
-		    {
-		    /*%%%*/
-			void_stmts($1);
-		    /*%
-		    %*/
-			$$ = $1;
-		    }
-		;
-
-stmts		: none
-                    {
-		    /*%%%*/
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch2(stmts_add, dispatch0(stmts_new),
-						  dispatch0(void_stmt));
-		    %*/
-		    }
-		| stmt
-		    {
-		    /*%%%*/
-			$$ = newline_node($1);
-		    /*%
-			$$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
-		    %*/
-		    }
-		| stmts terms stmt
-		    {
-		    /*%%%*/
-			$$ = block_append($1, newline_node($3));
-		    /*%
-			$$ = dispatch2(stmts_add, $1, $3);
-		    %*/
-		    }
-		| error stmt
-		    {
-			$$ = remove_begin($2);
-		    }
-		;
-
-stmt		: keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
-		    {
-		    /*%%%*/
-			$$ = NEW_ALIAS($2, $4);
-		    /*%
-			$$ = dispatch2(alias, $2, $4);
-		    %*/
-		    }
-		| keyword_alias tGVAR tGVAR
-		    {
-		    /*%%%*/
-			$$ = NEW_VALIAS($2, $3);
-		    /*%
-			$$ = dispatch2(var_alias, $2, $3);
-		    %*/
-		    }
-		| keyword_alias tGVAR tBACK_REF
-		    {
-		    /*%%%*/
-			char buf[3];
-
-			sprintf(buf, "$%c", (char)$3->nd_nth);
-			$$ = NEW_VALIAS($2, rb_intern(buf));
-		    /*%
-			$$ = dispatch2(var_alias, $2, $3);
-		    %*/
-		    }
-		| keyword_alias tGVAR tNTH_REF
-		    {
-		    /*%%%*/
-			yyerror("can't make alias for the number variables");
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch2(var_alias, $2, $3);
-			$$ = dispatch1(alias_error, $$);
-		    %*/
-		    }
-		| keyword_undef undef_list
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(undef, $2);
-		    %*/
-		    }
-		| stmt modifier_if expr_value
-		    {
-		    /*%%%*/
-			$$ = NEW_IF(cond($3), remove_begin($1), 0);
-			fixpos($$, $3);
-		    /*%
-			$$ = dispatch2(if_mod, $3, $1);
-		    %*/
-		    }
-		| stmt modifier_unless expr_value
-		    {
-		    /*%%%*/
-			$$ = NEW_UNLESS(cond($3), remove_begin($1), 0);
-			fixpos($$, $3);
-		    /*%
-			$$ = dispatch2(unless_mod, $3, $1);
-		    %*/
-		    }
-		| stmt modifier_while expr_value
-		    {
-		    /*%%%*/
-			if ($1 && nd_type($1) == NODE_BEGIN) {
-			    $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
-			}
-			else {
-			    $$ = NEW_WHILE(cond($3), $1, 1);
-			}
-		    /*%
-			$$ = dispatch2(while_mod, $3, $1);
-		    %*/
-		    }
-		| stmt modifier_until expr_value
-		    {
-		    /*%%%*/
-			if ($1 && nd_type($1) == NODE_BEGIN) {
-			    $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
-			}
-			else {
-			    $$ = NEW_UNTIL(cond($3), $1, 1);
-			}
-		    /*%
-			$$ = dispatch2(until_mod, $3, $1);
-		    %*/
-		    }
-		| stmt modifier_rescue stmt
-		    {
-		    /*%%%*/
-			NODE *resq = NEW_RESBODY(0, remove_begin($3), 0);
-			$$ = NEW_RESCUE(remove_begin($1), resq, 0);
-		    /*%
-			$$ = dispatch2(rescue_mod, $3, $1);
-		    %*/
-		    }
-		| keyword_BEGIN
-		    {
-			if (in_def || in_single) {
-			    yyerror("BEGIN in method");
-			}
-		    /*%%%*/
-			/* local_push(0); */
-		    /*%
-		    %*/
-		    }
-		  '{' compstmt '}'
-		    {
-		    /*%%%*/
-			ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
-							    $4);
-			/* NEW_PREEXE($4)); */
-			/* local_pop(); */
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(BEGIN, $4);
-		    %*/
-		    }
-		| keyword_END '{' compstmt '}'
-		    {
-			if (in_def || in_single) {
-			    rb_warn0("END in method; use at_exit");
-			}
-		    /*%%%*/
-			$$ = NEW_POSTEXE(NEW_NODE(
-			    NODE_SCOPE, 0 /* tbl */, $3 /* body */, 0 /* args */));
-		    /*%
-			$$ = dispatch1(END, $3);
-		    %*/
-		    }
-		| lhs '=' command_call
-		    {
-		    /*%%%*/
-			value_expr($3);
-			$$ = node_assign($1, $3);
-		    /*%
-			$$ = dispatch2(assign, $1, $3);
-		    %*/
-		    }
-		| mlhs '=' command_call
-		    {
-		    /*%%%*/
-			value_expr($3);
-			GC_WB(&$1->nd_value, $3);
-			$$ = $1;
-		    /*%
-			$$ = dispatch2(massign, $1, $3);
-		    %*/
-		    }
-		| var_lhs tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			value_expr($3);
-			if ($1) {
-			    ID vid = $1->nd_vid;
-			    if ($2 == tOROP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
-				if (is_asgn_or_id(vid)) {
-				    $$->nd_aid = vid;
-				}
-			    }
-			    else if ($2 == tANDOP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
-			    }
-			    else {
-				$$ = $1;
-				GC_WB(&$$->nd_value, NEW_CALL(gettable(vid), $2, NEW_LIST($3)));
-			    }
-			}
-			else {
-			    $$ = NEW_BEGIN(0);
-			}
-		    /*%
-			$$ = dispatch3(opassign, $1, $2, $3);
-		    %*/
-		    }
-		| primary_value '[' opt_call_args rbracket tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			NODE *args;
-
-			value_expr($6);
-			if (!$3) $3 = NEW_ZARRAY();
-			args = arg_concat($6, $3);
-			if ($5 == tOROP) {
-			    $5 = 0;
-			}
-			else if ($5 == tANDOP) {
-			    $5 = 1;
-			}
-			$$ = NEW_OP_ASGN1($1, $5, args);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch2(aref_field, $1, escape_Qundef($3));
-			$$ = dispatch3(opassign, $$, $5, $6);
-		    %*/
-		    }
-		| primary_value '.' tIDENTIFIER tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-			$$ = dispatch3(opassign, $$, $4, $5);
-		    %*/
-		    }
-		| primary_value '.' tCONSTANT tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-			$$ = dispatch3(opassign, $$, $4, $5);
-		    %*/
-		    }
-		| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_intern("::"), $3);
-			$$ = dispatch3(opassign, $$, $4, $5);
-		    %*/
-		    }
-		| backref tOP_ASGN command_call
-		    {
-		    /*%%%*/
-			rb_backref_error($1);
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch2(assign, dispatch1(var_field, $1), $3);
-			$$ = dispatch1(assign_error, $$);
-		    %*/
-		    }
-		| lhs '=' mrhs
-		    {
-		    /*%%%*/
-			value_expr($3);
-			$$ = node_assign($1, $3);
-		    /*%
-			$$ = dispatch2(assign, $1, $3);
-		    %*/
-		    }
-		| mlhs '=' arg_value
-		    {
-		    /*%%%*/
-			GC_WB(&$1->nd_value, $3);
-			$$ = $1;
-		    /*%
-			dispatch2(massign, $1, $3);
-		    %*/
-		    }
-		| mlhs '=' mrhs
-		    {
-		    /*%%%*/
-			GC_WB(&$1->nd_value, $3);
-			$$ = $1;
-		    /*%
-			$$ = dispatch2(massign, $1, $3);
-		    %*/
-		    }
-		| expr
-		;
-
-expr		: command_call
-		| expr keyword_and expr
-		    {
-		    /*%%%*/
-			$$ = logop(NODE_AND, $1, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("and"), $3);
-		    %*/
-		    }
-		| expr keyword_or expr
-		    {
-		    /*%%%*/
-			$$ = logop(NODE_OR, $1, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("or"), $3);
-		    %*/
-		    }
-                | keyword_not opt_nl expr
-                    {
-                    /*%%%*/
-                        $$ = call_uni_op(cond($3), '!');
-                    /*%
-                        $$ = dispatch2(unary, ripper_intern("not"), $3);
-                    %*/
-                    }
-		| '!' command_call
-		    {
-		    /*%%%*/
-			$$ = call_uni_op(cond($2), '!');
-		    /*%
-			$$ = dispatch2(unary, ripper_id2sym('!'), $2);
-		    %*/
-		    }
-		| arg
-		;
-
-expr_value	: expr
-		    {
-		    /*%%%*/
-			value_expr($1);
-			$$ = $1;
-		        if (!$$) $$ = NEW_NIL();
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-command_call	: command
-		| block_command
-		| keyword_return call_args
-		    {
-		    /*%%%*/
-			$$ = NEW_RETURN(ret_args($2));
-		    /*%
-			$$ = dispatch1(return, $2);
-		    %*/
-		    }
-		| keyword_break call_args
-		    {
-		    /*%%%*/
-			$$ = NEW_BREAK(ret_args($2));
-		    /*%
-			$$ = dispatch1(break, $2);
-		    %*/
-		    }
-		| keyword_next call_args
-		    {
-		    /*%%%*/
-			$$ = NEW_NEXT(ret_args($2));
-		    /*%
-			$$ = dispatch1(next, $2);
-		    %*/
-		    }
-		;
-
-block_command	: block_call
-		| block_call '.' operation2 command_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
-			$$ = method_arg($$, $4);
-		    %*/
-		    }
-		| block_call tCOLON2 operation2 command_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_intern("::"), $3);
-			$$ = method_arg($$, $4);
-		    %*/
-		    }
-		;
-
-cmd_brace_block	: tLBRACE_ARG
-		    {
-		    /*%%%*/
-			dyna_push();
-			$<num>$ = ruby_sourceline;
-		    /*%
-		    %*/
-		    }
-		  opt_block_param
-		  compstmt
-		  '}'
-		    {
-		    /*%%%*/
-			$$ = NEW_ITER($3,$4);
-			nd_set_line($$, $<num>2);
-			dyna_pop();
-		    /*%
-			$$ = dispatch2(brace_block, escape_Qundef($3), $4);
-		    %*/
-		    }
-		;
-
-command		: operation command_args       %prec tLOWEST
-		    {
-		    /*%%%*/
-			$$ = NEW_FCALL($1, $2);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch2(command, $1, $2);
-		    %*/
-		    }
-		| operation command_args cmd_brace_block
-		    {
-		    /*%%%*/
-			block_dup_check($2,$3);
-		        GC_WB(&$3->nd_iter, NEW_FCALL($1, $2));
-			$$ = $3;
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch2(command, $1, $2);
-			$$ = method_add_block($$, $3);
-		    %*/
-		    }
-		| primary_value '.' operation2 command_args	%prec tLOWEST
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
-		    %*/
-		    }
-		| primary_value '.' operation2 command_args cmd_brace_block
-		    {
-		    /*%%%*/
-			block_dup_check($4,$5);
-		        GC_WB(&$5->nd_iter, NEW_CALL($1, $3, $4));
-			$$ = $5;
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
-			$$ = method_add_block($$, $5);
-		    %*/
-		   }
-		| primary_value tCOLON2 operation2 command_args	%prec tLOWEST
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
-		    %*/
-		    }
-		| primary_value tCOLON2 operation2 command_args cmd_brace_block
-		    {
-		    /*%%%*/
-			block_dup_check($4,$5);
-		        GC_WB(&$5->nd_iter, NEW_CALL($1, $3, $4));
-			$$ = $5;
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
-			$$ = method_add_block($$, $5);
-		    %*/
-		   }
-		| keyword_super command_args
-		    {
-		    /*%%%*/
-			$$ = NEW_SUPER($2);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch1(super, $2);
-		    %*/
-		    }
-		| keyword_yield command_args
-		    {
-		    /*%%%*/
-			$$ = new_yield($2);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch1(yield, $2);
-		    %*/
-		    }
-		;
-
-mlhs		: mlhs_basic
-		| tLPAREN mlhs_inner rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-mlhs_inner	: mlhs_basic
-		| tLPAREN mlhs_inner rparen
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(NEW_LIST($2), 0);
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-mlhs_basic	: mlhs_head
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, 0);
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| mlhs_head mlhs_item
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(list_append($1,$2), 0);
-		    /*%
-			$$ = mlhs_add($1, $2);
-		    %*/
-		    }
-		| mlhs_head tSTAR mlhs_node
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, $3);
-		    /*%
-			$$ = mlhs_add_star($1, $3);
-		    %*/
-		    }
-		| mlhs_head tSTAR mlhs_node ',' mlhs_post
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
-		    /*%
-			$$ = mlhs_add_star($1, $3);
-		    %*/
-		    }
-		| mlhs_head tSTAR
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, -1);
-		    /*%
-			$$ = mlhs_add_star($1, Qnil);
-		    %*/
-		    }
-		| mlhs_head tSTAR ',' mlhs_post
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, NEW_POSTARG(-1, $4));
-		    /*%
-			$$ = mlhs_add_star($1, Qnil);
-		    %*/
-		    }
-		| tSTAR mlhs_node
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, $2);
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), $2);
-		    %*/
-		    }
-		| tSTAR mlhs_node ',' mlhs_post
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), $2);
-		    %*/
-		    }
-		| tSTAR
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, -1);
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), Qnil);
-		    %*/
-		    }
-		| tSTAR ',' mlhs_post
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), Qnil);
-		    %*/
-		    }
-		;
-
-mlhs_item	: mlhs_node
-		| tLPAREN mlhs_inner rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-mlhs_head	: mlhs_item ','
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = mlhs_add(mlhs_new(), $1);
-		    %*/
-		    }
-		| mlhs_head mlhs_item ','
-		    {
-		    /*%%%*/
-			$$ = list_append($1, $2);
-		    /*%
-			$$ = mlhs_add($1, $2);
-		    %*/
-		    }
-		;
-
-mlhs_post	: mlhs_item
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = mlhs_add(mlhs_new(), $1);
-		    %*/
-		    }
-		| mlhs_post ',' mlhs_item
-		    {
-		    /*%%%*/
-			$$ = list_append($1, $3);
-		    /*%
-			$$ = mlhs_add($1, $3);
-		    %*/
-		    }
-		;
-
-mlhs_node	: variable
-		    {
-		    /*%%%*/
-			$$ = assignable($1, 0);
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| primary_value '[' opt_call_args rbracket
-		    {
-		    /*%%%*/
-			$$ = aryset($1, $3);
-		    /*%
-			$$ = dispatch2(aref_field, $1, escape_Qundef($3));
-		    %*/
-		    }
-		| primary_value '.' tIDENTIFIER
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-		    %*/
-		    }
-		| primary_value tCOLON2 tIDENTIFIER
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch2(const_path_field, $1, $3);
-		    %*/
-		    }
-		| primary_value '.' tCONSTANT
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-		    %*/
-		    }
-		| primary_value tCOLON2 tCONSTANT
-		    {
-		    /*%%%*/
-			if (in_def || in_single)
-			    yyerror("dynamic constant assignment");
-			$$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
-		    /*%
-			if (in_def || in_single)
-			    yyerror("dynamic constant assignment");
-			$$ = dispatch2(const_path_field, $1, $3);
-		    %*/
-		    }
-		| tCOLON3 tCONSTANT
-		    {
-		    /*%%%*/
-			if (in_def || in_single)
-			    yyerror("dynamic constant assignment");
-			$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
-		    /*%
-			$$ = dispatch1(top_const_field, $2);
-		    %*/
-		    }
-		| backref
-		    {
-		    /*%%%*/
-			rb_backref_error($1);
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(var_field, $1);
-			$$ = dispatch1(assign_error, $$);
-		    %*/
-		    }
-		;
-
-lhs		: variable
-		    {
-		    /*%%%*/
-			if (!($$ = assignable($1, 0))) $$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(var_field, $1);
-		    %*/
-		    }
-		| primary_value '[' opt_call_args rbracket
-		    {
-		    /*%%%*/
-			$$ = aryset($1, $3);
-		    /*%
-			$$ = dispatch2(aref_field, $1, escape_Qundef($3));
-		    %*/
-		    }
-		| primary_value '.' tIDENTIFIER
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-		    %*/
-		    }
-		| primary_value tCOLON2 tIDENTIFIER
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_intern("::"), $3);
-		    %*/
-		    }
-		| primary_value '.' tCONSTANT
-		    {
-		    /*%%%*/
-			$$ = attrset($1, $3);
-		    /*%
-			$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
-		    %*/
-		    }
-		| primary_value tCOLON2 tCONSTANT
-		    {
-		    /*%%%*/
-			if (in_def || in_single)
-			    yyerror("dynamic constant assignment");
-			$$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
-		    /*%
-			$$ = dispatch2(const_path_field, $1, $3);
-			if (in_def || in_single) {
-			    $$ = dispatch1(assign_error, $$);
-			}
-		    %*/
-		    }
-		| tCOLON3 tCONSTANT
-		    {
-		    /*%%%*/
-			if (in_def || in_single)
-			    yyerror("dynamic constant assignment");
-			$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
-		    /*%
-			$$ = dispatch1(top_const_field, $2);
-			if (in_def || in_single) {
-			    $$ = dispatch1(assign_error, $$);
-			}
-		    %*/
-		    }
-		| backref
-		    {
-		    /*%%%*/
-			rb_backref_error($1);
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(assign_error, $1);
-		    %*/
-		    }
-		;
-
-cname		: tIDENTIFIER
-		    {
-		    /*%%%*/
-			yyerror("class/module name must be CONSTANT");
-		    /*%
-			$$ = dispatch1(class_name_error, $1);
-		    %*/
-		    }
-		| tCONSTANT
-		;
-
-cpath		: tCOLON3 cname
-		    {
-		    /*%%%*/
-			$$ = NEW_COLON3($2);
-		    /*%
-			$$ = dispatch1(top_const_ref, $2);
-		    %*/
-		    }
-		| cname
-		    {
-		    /*%%%*/
-			$$ = NEW_COLON2(0, $$);
-		    /*%
-			$$ = dispatch1(const_ref, $1);
-		    %*/
-		    }
-		| primary_value tCOLON2 cname
-		    {
-		    /*%%%*/
-			$$ = NEW_COLON2($1, $3);
-		    /*%
-			$$ = dispatch2(const_path_ref, $1, $3);
-		    %*/
-		    }
-		;
-
-fname		: tIDENTIFIER
-		| tCONSTANT
-		| tFID
-		| op
-		    {
-		    /*%%%*/
-			lex_state = EXPR_END;
-			$$ = $1;
-		    /*%
-			lex_state = EXPR_END;
-			$$ = $1;
-		    %*/
-		    }
-		| reswords
-		    {
-		    /*%%%*/
-			lex_state = EXPR_END;
-			$$ = $<id>1;
-		    /*%
-			lex_state = EXPR_END;
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-fsym		: fname
-		| symbol
-		;
-
-fitem		: fsym
-		    {
-		    /*%%%*/
-			$$ = NEW_LIT(ID2SYM($1));
-		    /*%
-			$$ = dispatch1(symbol_literal, $1);
-		    %*/
-		    }
-		| dsym
-		;
-
-undef_list	: fitem
-		    {
-		    /*%%%*/
-			$$ = NEW_UNDEF($1);
-		    /*%
-			$$ = rb_ary_new3(1, $1);
-		    %*/
-		    }
-		| undef_list ',' {lex_state = EXPR_FNAME;} fitem
-		    {
-		    /*%%%*/
-			$$ = block_append($1, NEW_UNDEF($4));
-		    /*%
-			rb_ary_push($1, $4);
-		    %*/
-		    }
-		;
-
-op		: '|'		{ ifndef_ripper($$ = '|'); }
-		| '^'		{ ifndef_ripper($$ = '^'); }
-		| '&'		{ ifndef_ripper($$ = '&'); }
-		| tCMP		{ ifndef_ripper($$ = tCMP); }
-		| tEQ		{ ifndef_ripper($$ = tEQ); }
-		| tEQQ		{ ifndef_ripper($$ = tEQQ); }
-		| tMATCH	{ ifndef_ripper($$ = tMATCH); }
-		| tNMATCH	{ ifndef_ripper($$ = tNMATCH); }
-		| '>'		{ ifndef_ripper($$ = '>'); }
-		| tGEQ		{ ifndef_ripper($$ = tGEQ); }
-		| '<'		{ ifndef_ripper($$ = '<'); }
-		| tLEQ		{ ifndef_ripper($$ = tLEQ); }
-		| tNEQ		{ ifndef_ripper($$ = tNEQ); }
-		| tLSHFT	{ ifndef_ripper($$ = tLSHFT); }
-		| tRSHFT	{ ifndef_ripper($$ = tRSHFT); }
-		| '+'		{ ifndef_ripper($$ = '+'); }
-		| '-'		{ ifndef_ripper($$ = '-'); }
-		| '*'		{ ifndef_ripper($$ = '*'); }
-		| tSTAR		{ ifndef_ripper($$ = '*'); }
-		| '/'		{ ifndef_ripper($$ = '/'); }
-		| '%'		{ ifndef_ripper($$ = '%'); }
-		| tPOW		{ ifndef_ripper($$ = tPOW); }
-		| '!'		{ ifndef_ripper($$ = '!'); }
-		| '~'		{ ifndef_ripper($$ = '~'); }
-		| tUPLUS	{ ifndef_ripper($$ = tUPLUS); }
-		| tUMINUS	{ ifndef_ripper($$ = tUMINUS); }
-		| tAREF		{ ifndef_ripper($$ = tAREF); }
-		| tASET		{ ifndef_ripper($$ = tASET); }
-		| '`'		{ ifndef_ripper($$ = '`'); }
-		;
-
-reswords	: keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
-		| keyword_BEGIN | keyword_END
-		| keyword_alias | keyword_and | keyword_begin
-		| keyword_break | keyword_case | keyword_class | keyword_def
-		| keyword_defined | keyword_do | keyword_else | keyword_elsif
-		| keyword_end | keyword_ensure | keyword_false
-		| keyword_for | keyword_in | keyword_module | keyword_next
-		| keyword_nil | keyword_not | keyword_or | keyword_redo
-		| keyword_rescue | keyword_retry | keyword_return | keyword_self
-		| keyword_super | keyword_then | keyword_true | keyword_undef
-		| keyword_when | keyword_yield | keyword_if | keyword_unless
-		| keyword_while | keyword_until
-		;
-
-arg		: lhs '=' arg
-		    {
-		    /*%%%*/
-			value_expr($3);
-			$$ = node_assign($1, $3);
-		    /*%
-			$$ = dispatch2(assign, $1, $3);
-		    %*/
-		    }
-		| lhs '=' arg modifier_rescue arg
-		    {
-		    /*%%%*/
-			value_expr($3);
-		        $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
-			$$ = node_assign($1, $3);
-		    /*%
-			$$ = dispatch2(assign, $1, dispatch2(rescue_mod, $3, $5));
-		    %*/
-		    }
-		| var_lhs tOP_ASGN arg
-		    {
-		    /*%%%*/
-			value_expr($3);
-			if ($1) {
-			    ID vid = $1->nd_vid;
-			    if ($2 == tOROP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
-				if (is_asgn_or_id(vid)) {
-				    $$->nd_aid = vid;
-				}
-			    }
-			    else if ($2 == tANDOP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
-			    }
-			    else {
-				$$ = $1;
-				GC_WB(&$$->nd_value, NEW_CALL(gettable(vid), $2, NEW_LIST($3)));
-			    }
-			}
-			else {
-			    $$ = NEW_BEGIN(0);
-			}
-		    /*%
-			$$ = dispatch3(opassign, $1, $2, $3);
-		    %*/
-		    }
-		| var_lhs tOP_ASGN arg modifier_rescue arg
-		    {
-		    /*%%%*/
-			value_expr($3);
-		        $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
-			if ($1) {
-			    ID vid = $1->nd_vid;
-			    if ($2 == tOROP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
-				if (is_asgn_or_id(vid)) {
-				    $$->nd_aid = vid;
-				}
-			    }
-			    else if ($2 == tANDOP) {
-				GC_WB(&$1->nd_value, $3);
-				$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
-			    }
-			    else {
-				$$ = $1;
-				GC_WB(&$$->nd_value, NEW_CALL(gettable(vid), $2, NEW_LIST($3)));
-			    }
-			}
-			else {
-			    $$ = NEW_BEGIN(0);
-			}
-		    /*%
-			$3 = dispatch2(rescue_mod, $3, $5);
-			$$ = dispatch3(opassign, $1, $2, $3);
-		    %*/
-		    }
-		| primary_value '[' opt_call_args rbracket tOP_ASGN arg
-		    {
-		    /*%%%*/
-			NODE *args;
-
-			value_expr($6);
-			if (!$3) $3 = NEW_ZARRAY();
-			args = arg_concat($6, $3);
-			if ($5 == tOROP) {
-			    $5 = 0;
-			}
-			else if ($5 == tANDOP) {
-			    $5 = 1;
-			}
-			$$ = NEW_OP_ASGN1($1, $5, args);
-			fixpos($$, $1);
-		    /*%
-			$1 = dispatch2(aref_field, $1, escape_Qundef($3));
-			$$ = dispatch3(opassign, $1, $5, $6);
-		    %*/
-		    }
-		| primary_value '.' tIDENTIFIER tOP_ASGN arg
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
-			$$ = dispatch3(opassign, $1, $4, $5);
-		    %*/
-		    }
-		| primary_value '.' tCONSTANT tOP_ASGN arg
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
-			$$ = dispatch3(opassign, $1, $4, $5);
-		    %*/
-		    }
-		| primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
-		    {
-		    /*%%%*/
-			value_expr($5);
-			if ($4 == tOROP) {
-			    $4 = 0;
-			}
-			else if ($4 == tANDOP) {
-			    $4 = 1;
-			}
-			$$ = NEW_OP_ASGN2($1, $3, $4, $5);
-			fixpos($$, $1);
-		    /*%
-			$1 = dispatch3(field, $1, ripper_intern("::"), $3);
-			$$ = dispatch3(opassign, $1, $4, $5);
-		    %*/
-		    }
-		| primary_value tCOLON2 tCONSTANT tOP_ASGN arg
-		    {
-		    /*%%%*/
-			yyerror("constant re-assignment");
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch2(const_path_field, $1, $3);
-			$$ = dispatch3(opassign, $$, $4, $5);
-			$$ = dispatch1(assign_error, $$);
-		    %*/
-		    }
-		| tCOLON3 tCONSTANT tOP_ASGN arg
-		    {
-		    /*%%%*/
-			yyerror("constant re-assignment");
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(top_const_field, $2);
-			$$ = dispatch3(opassign, $$, $3, $4);
-			$$ = dispatch1(assign_error, $$);
-		    %*/
-		    }
-		| backref tOP_ASGN arg
-		    {
-		    /*%%%*/
-			rb_backref_error($1);
-			$$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(var_field, $1);
-			$$ = dispatch3(opassign, $$, $2, $3);
-			$$ = dispatch1(assign_error, $$);
-		    %*/
-		    }
-		| arg tDOT2 arg
-		    {
-		    /*%%%*/
-			value_expr($1);
-			value_expr($3);
-			$$ = NEW_DOT2($1, $3);
-		    /*%
-			$$ = dispatch2(dot2, $1, $3);
-		    %*/
-		    }
-		| arg tDOT3 arg
-		    {
-		    /*%%%*/
-			value_expr($1);
-			value_expr($3);
-			$$ = NEW_DOT3($1, $3);
-		    /*%
-			$$ = dispatch2(dot3, $1, $3);
-		    %*/
-		    }
-		| arg '+' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '+', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('+'), $3);
-		    %*/
-		    }
-		| arg '-' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '-', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('-'), $3);
-		    %*/
-		    }
-		| arg '*' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '*', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('*'), $3);
-		    %*/
-		    }
-		| arg '/' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '/', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('/'), $3);
-		    %*/
-		    }
-		| arg '%' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '%', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('%'), $3);
-		    %*/
-		    }
-		| arg tPOW arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tPOW, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("**"), $3);
-		    %*/
-		    }
-		| tUMINUS_NUM tINTEGER tPOW arg
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
-		    /*%
-			$$ = dispatch3(binary, $2, ripper_intern("**"), $4);
-			$$ = dispatch2(unary, ripper_intern("-@"), $$);
-		    %*/
-		    }
-		| tUMINUS_NUM tFLOAT tPOW arg
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
-		    /*%
-			$$ = dispatch3(binary, $2, ripper_intern("**"), $4);
-			$$ = dispatch2(unary, ripper_intern("-@"), $$);
-		    %*/
-		    }
-		| tUPLUS arg
-		    {
-		    /*%%%*/
-			$$ = call_uni_op($2, tUPLUS);
-		    /*%
-			$$ = dispatch2(unary, ripper_intern("+@"), $2);
-		    %*/
-		    }
-		| tUMINUS arg
-		    {
-		    /*%%%*/
-			$$ = call_uni_op($2, tUMINUS);
-		    /*%
-			$$ = dispatch2(unary, ripper_intern("-@"), $2);
-		    %*/
-		    }
-		| arg '|' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '|', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('|'), $3);
-		    %*/
-		    }
-		| arg '^' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '^', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('^'), $3);
-		    %*/
-		    }
-		| arg '&' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '&', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('&'), $3);
-		    %*/
-		    }
-		| arg tCMP arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tCMP, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("<=>"), $3);
-		    %*/
-		    }
-		| arg '>' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '>', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('>'), $3);
-		    %*/
-		    }
-		| arg tGEQ arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tGEQ, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern(">="), $3);
-		    %*/
-		    }
-		| arg '<' arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, '<', $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ID2SYM('<'), $3);
-		    %*/
-		    }
-		| arg tLEQ arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tLEQ, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("<="), $3);
-		    %*/
-		    }
-		| arg tEQ arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tEQ, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("=="), $3);
-		    %*/
-		    }
-		| arg tEQQ arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tEQQ, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("==="), $3);
-		    %*/
-		    }
-		| arg tNEQ arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tNEQ, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("!="), $3);
-		    %*/
-		    }
-		| arg tMATCH arg
-		    {
-		    /*%%%*/
-			$$ = match_op($1, $3);
-                        if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
-                            $$ = reg_named_capture_assign($1->nd_lit, $$);
-                        }
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("=~"), $3);
-		    %*/
-		    }
-		| arg tNMATCH arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tNMATCH, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("!~"), $3);
-		    %*/
-		    }
-		| '!' arg
-		    {
-		    /*%%%*/
-			$$ = call_uni_op(cond($2), '!');
-		    /*%
-			$$ = dispatch2(unary, ID2SYM('!'), $2);
-		    %*/
-		    }
-		| '~' arg
-		    {
-		    /*%%%*/
-			$$ = call_uni_op($2, '~');
-		    /*%
-			$$ = dispatch2(unary, ID2SYM('~'), $2);
-		    %*/
-		    }
-		| arg tLSHFT arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tLSHFT, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("<<"), $3);
-		    %*/
-		    }
-		| arg tRSHFT arg
-		    {
-		    /*%%%*/
-			$$ = call_bin_op($1, tRSHFT, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern(">>"), $3);
-		    %*/
-		    }
-		| arg tANDOP arg
-		    {
-		    /*%%%*/
-			$$ = logop(NODE_AND, $1, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("&&"), $3);
-		    %*/
-		    }
-		| arg tOROP arg
-		    {
-		    /*%%%*/
-			$$ = logop(NODE_OR, $1, $3);
-		    /*%
-			$$ = dispatch3(binary, $1, ripper_intern("||"), $3);
-		    %*/
-		    }
-		| keyword_defined opt_nl {in_defined = 1;} arg
-		    {
-		    /*%%%*/
-			in_defined = 0;
-			$$ = NEW_DEFINED($4);
-		    /*%
-			in_defined = 0;
-			$$ = dispatch1(defined, $4);
-		    %*/
-		    }
-		| arg '?' arg opt_nl ':' arg
-		    {
-		    /*%%%*/
-			value_expr($1);
-			$$ = NEW_IF(cond($1), $3, $6);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(ifop, $1, $3, $6);
-		    %*/
-		    }
-		| primary
-		    {
-			$$ = $1;
-		    }
-		;
-
-arg_value	: arg
-		    {
-		    /*%%%*/
-			value_expr($1);
-			$$ = $1;
-		        if (!$$) $$ = NEW_NIL();
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-aref_args	: none
-		| args trailer
-		    {
-			$$ = $1;
-		    }
-		| args ',' assocs trailer
-		    {
-		    /*%%%*/
-			$$ = arg_append($1, NEW_HASH($3));
-		    /*%
-			$$ = arg_add_assocs($1, $3);
-		    %*/
-		    }
-		| assocs trailer
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST(NEW_HASH($1));
-		    /*%
-			$$ = arg_add_assocs(arg_new(), $1);
-		    %*/
-		    }
-		;
-
-paren_args	: '(' opt_call_args rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(arg_paren, escape_Qundef($2));
-		    %*/
-		    }
-		;
-
-opt_paren_args	: none
-		| paren_args
-		;
-
-opt_call_args	: none
-		| call_args
-		;
-
-call_args	: command
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = arg_add(arg_new(), $1);
-		    %*/
-		    }
-		| args opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_blk_pass($1, $2);
-		    /*%
-			$$ = arg_add_optblock($1, $2);
-		    %*/
-		    }
-		| assocs opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST(NEW_HASH($1));
-			$$ = arg_blk_pass($$, $2);
-		    /*%
-			$$ = arg_add_assocs(arg_new(), $1);
-			$$ = arg_add_optblock($$, $2);
-		    %*/
-		    }
-		| args ',' assocs opt_block_arg
-		    {
-		    /*%%%*/
-#if WITH_OBJC
-			if ($1->nd_alen == 1) {
-			    NODE *n;
-			    unsigned all_symbol_pairs = 1;
-			    for (n = $3; n != NULL; 
-				 n = n->nd_next->nd_next) {
-				if (nd_type(n->nd_head) != NODE_LIT
-				    || TYPE(n->nd_head->nd_head) != T_SYMBOL) {
-				    all_symbol_pairs = 0;
-				    break;
-				}
-			    }
-			    if (all_symbol_pairs) {
-				$$ = arg_append($1, $3);
-				$3->flags |= NODE_ARRAY_NAMED_ARGS;
-			    }
-			    else {
-				$$ = arg_append($1, NEW_HASH($3));
-			    }
-			}
-			else
-#endif
-			    $$ = arg_append($1, NEW_HASH($3));
-			$$ = arg_blk_pass($$, $4);
-		    /*%
-			$$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
-		    %*/
-		    }
-		| args ',' assocs ',' args opt_block_arg
-		    {
-		    /*%%%*/
-#if WITH_OBJC
-			NODE *n;
-			unsigned all_symbol_pairs = 1;
-			if ($1->nd_alen != 1)
-			    yyerror("invalid use of named arguments in method call");
-			for (n = $3; n != NULL; 
-			     n = n->nd_next->nd_next) {
-			    if (nd_type(n->nd_head) != NODE_LIT
-			        || TYPE(n->nd_head->nd_head) != T_SYMBOL) {
-			        all_symbol_pairs = 0;
-			        break;
-			    }
-			}
-			if (!all_symbol_pairs)
-			    yyerror("invalid use of named arguments in method call");
-                        $$ = arg_append($1, $3);
-                        $3->flags |= NODE_ARRAY_NAMED_ARGS;
-			$$ = arg_append($1, $5);
-			$$ = arg_blk_pass($$, $6);
-		    /*%
-			$$ = arg_add_optblock(arg_add_star(arg_add_assocs($1, $3), $5), $6);
-		    %*/
-#endif
-		    }
-		| block_arg
-		    /*%c%*/
-		    /*%c
-		    {
-			$$ = arg_add_block(arg_new(), $1);
-		    }
-		    %*/
-		;
-
-call_args2	: arg_value ',' args opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
-		    /*%
-			$$ = arg_add_optblock(arg_prepend($3, $1), $4);
-		    %*/
-		    }
-		| arg_value ',' block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_blk_pass(NEW_LIST($1), $3);
-		    /*%
-			$$ = arg_add_block(arg_add(arg_new(), $1), $3);
-		    %*/
-		    }
-		| assocs opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST(NEW_HASH($1));
-			$$ = arg_blk_pass($$, $2);
-		    /*%
-			$$ = arg_add_assocs(arg_new(), $1);
-			$$ = arg_add_optblock($$, $2);
-		    %*/
-		    }
-		| arg_value ',' assocs opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_append(NEW_LIST($1), NEW_HASH($3));
-			$$ = arg_blk_pass($$, $4);
-		    /*%
-			$$ = arg_add_assocs(arg_add(arg_new(), $1), $3);
-			$$ = arg_add_optblock($$, $4);
-		    %*/
-		    }
-		| arg_value ',' args ',' assocs opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
-			$$ = arg_blk_pass($$, $6);
-		    /*%
-			$$ = arg_add_assocs(arg_prepend($3, $1), $5);
-			$$ = arg_add_optblock($$, $6);
-		    %*/
-		    }
-		| block_arg
-		;
-
-command_args	:  {
-			$<num>$ = cmdarg_stack;
-			CMDARG_PUSH(1);
-		    }
-		  open_args
-		    {
-			/* CMDARG_POP() */
-			cmdarg_stack = $<num>1;
-			$$ = $2;
-		    }
-		;
-
-open_args	: call_args
-		| tLPAREN_ARG  {lex_state = EXPR_ENDARG;} rparen
-		    {
-		    /*%%%*/
-			rb_warning0("don't put space before argument parentheses");
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(space, dispatch1(arg_paren, arg_new()));
-		    %*/
-		    }
-		| tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} rparen
-		    {
-		    /*%%%*/
-			rb_warning0("don't put space before argument parentheses");
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(space, dispatch1(arg_paren, $2));
-		    %*/
-		    }
-		;
-
-block_arg	: tAMPER arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_BLOCK_PASS($2);
-		    /*%
-			$$ = $2;
-		    %*/
-		    }
-		;
-
-opt_block_arg	: ',' block_arg
-		    {
-			$$ = $2;
-		    }
-		| ','
-		    {
-			$$ = 0;
-		    }
-		| none
-		    {
-			$$ = 0;
-		    }
-		;
-
-args		: arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = arg_add(arg_new(), $1);
-		    %*/
-		    }
-		| tSTAR arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_SPLAT($2);
-		    /*%
-			$$ = arg_add_star(arg_new(), $2);
-		    %*/
-		    }
-		| args ',' arg_value
-		    {
-		    /*%%%*/
-			NODE *n1;
-			if ((n1 = splat_array($1)) != 0) {
-			    $$ = list_append(n1, $3);
-			}
-			else {
-			    $$ = arg_append($1, $3);
-			}
-		    /*%
-			$$ = arg_add($1, $3);
-		    %*/
-		    }
-		| args ',' tSTAR arg_value
-		    {
-		    /*%%%*/
-			NODE *n1;
-			if (nd_type($4) == NODE_ARRAY &&
-			    (n1 = splat_array($1)) != 0) {
-			    $$ = list_concat(n1, $4);
-			}
-			else {
-			    $$ = arg_concat($1, $4);
-			}
-		    /*%
-			$$ = arg_add_star($1, $4);
-		    %*/
-		    }
-		;
-
-mrhs		: args ',' arg_value
-		    {
-		    /*%%%*/
-			NODE *n1;
-			if ((n1 = splat_array($1)) != 0) {
-			    $$ = list_append(n1, $3);
-			}
-			else {
-			    $$ = arg_append($1, $3);
-			}
-		    /*%
-			$$ = mrhs_add(args2mrhs($1), $3);
-		    %*/
-		    }
-		| args ',' tSTAR arg_value
-		    {
-		    /*%%%*/
-			NODE *n1;
-			if (nd_type($4) == NODE_ARRAY &&
-			    (n1 = splat_array($1)) != 0) {
-			    $$ = list_concat(n1, $4);
-			}
-			else {
-			    $$ = arg_concat($1, $4);
-			}
-		    /*%
-			$$ = mrhs_add_star(args2mrhs($1), $4);
-		    %*/
-		    }
-		| tSTAR arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_SPLAT($2);
-		    /*%
-			$$ = mrhs_add_star(mrhs_new(), $2);
-		    %*/
-		    }
-		;
-
-primary		: literal
-		| strings
-		| xstring
-		| regexp
-		| words
-		| qwords
-		| var_ref
-		| backref
-		| tFID
-		    {
-		    /*%%%*/
-			$$ = NEW_FCALL($1, 0);
-		    /*%
-			$$ = method_arg(dispatch1(fcall, $1), arg_new());
-		    %*/
-		    }
-		| keyword_begin
-		    {
-		    /*%%%*/
-			$<num>$ = ruby_sourceline;
-		    /*%
-		    %*/
-		    }
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			if ($3 == NULL) {
-			    $$ = NEW_NIL();
-			}
-			else {
-			    if (nd_type($3) == NODE_RESCUE ||
-				nd_type($3) == NODE_ENSURE)
-				nd_set_line($3, $<num>2);
-			    $$ = NEW_BEGIN($3);
-			}
-			nd_set_line($$, $<num>2);
-		    /*%
-			$$ = dispatch1(begin, $3);
-		    %*/
-		    }
-		| tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen
-		    {
-			rb_warning0("(...) interpreted as grouped expression");
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(paren, $2);
-		    %*/
-		    }
-		| tLPAREN compstmt ')'
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(paren, $2);
-		    %*/
-		    }
-		| primary_value tCOLON2 tCONSTANT
-		    {
-		    /*%%%*/
-			$$ = NEW_COLON2($1, $3);
-		    /*%
-			$$ = dispatch2(const_path_ref, $1, $3);
-		    %*/
-		    }
-		| tCOLON3 tCONSTANT
-		    {
-		    /*%%%*/
-			$$ = NEW_COLON3($2);
-		    /*%
-			$$ = dispatch1(top_const_ref, $2);
-		    %*/
-		    }
-		| tLBRACK aref_args ']'
-		    {
-		    /*%%%*/
-			if ($2 == 0) {
-			    $$ = NEW_ZARRAY(); /* zero length array*/
-			}
-			else {
-			    $$ = $2;
-			}
-		    /*%
-			$$ = dispatch1(array, escape_Qundef($2));
-		    %*/
-		    }
-		| tLBRACE assoc_list '}'
-		    {
-		    /*%%%*/
-			$$ = NEW_HASH($2);
-		    /*%
-			$$ = dispatch1(hash, escape_Qundef($2));
-		    %*/
-		    }
-		| keyword_return
-		    {
-		    /*%%%*/
-			$$ = NEW_RETURN(0);
-		    /*%
-			$$ = dispatch0(return0);
-		    %*/
-		    }
-		| keyword_yield '(' call_args rparen
-		    {
-		    /*%%%*/
-			$$ = new_yield($3);
-		    /*%
-			$$ = dispatch1(yield, dispatch1(paren, $3));
-		    %*/
-		    }
-		| keyword_yield '(' rparen
-		    {
-		    /*%%%*/
-			$$ = NEW_YIELD(0, Qfalse);
-		    /*%
-			$$ = dispatch1(yield, dispatch1(paren, arg_new()));
-		    %*/
-		    }
-		| keyword_yield
-		    {
-		    /*%%%*/
-			$$ = NEW_YIELD(0, Qfalse);
-		    /*%
-			$$ = dispatch0(yield0);
-		    %*/
-		    }
-		| keyword_defined opt_nl '(' {in_defined = 1;} expr rparen
-		    {
-		    /*%%%*/
-			in_defined = 0;
-			$$ = NEW_DEFINED($5);
-		    /*%
-			in_defined = 0;
-			$$ = dispatch1(defined, $5);
-		    %*/
-		    }
-                | keyword_not tLPAREN expr rparen
-                    {
-                    /*%%%*/
-                        $$ = call_uni_op(cond($3), '!');
-                    /*%
-                        $$ = dispatch2(unary, ripper_intern("not"), $3);
-                    %*/
-                    }
-                | keyword_not tLPAREN rparen
-                    {
-                    /*%%%*/
-                        $$ = call_uni_op(cond(NEW_NIL()), '!');
-                    /*%
-                        $$ = dispatch2(unary, ripper_intern("not"), Qnil);
-                    %*/
-                    }
-		| operation brace_block
-		    {
-		    /*%%%*/
-			GC_WB(&$2->nd_iter, NEW_FCALL($1, 0));
-			$$ = $2;
-			fixpos($2->nd_iter, $2);
-		    /*%
-			$$ = method_arg(dispatch1(fcall, $1), arg_new());
-			$$ = method_add_block($$, $2);
-		    %*/
-		    }
-		| method_call
-		| method_call brace_block
-		    {
-		    /*%%%*/
-			block_dup_check($1->nd_args, $2);
-			GC_WB(&$2->nd_iter, $1);
-			$$ = $2;
-			fixpos($$, $1);
-		    /*%
-			$$ = method_add_block($1, $2);
-		    %*/
-		    }
-		| tLAMBDA lambda
-		    {
-			$$ = $2;
-		    }
-		| keyword_if expr_value then
-		  compstmt
-		  if_tail
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_IF(cond($2), $4, $5);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch3(if, $2, $4, escape_Qundef($5));
-		    %*/
-		    }
-		| keyword_unless expr_value then
-		  compstmt
-		  opt_else
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_UNLESS(cond($2), $4, $5);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch3(unless, $2, $4, escape_Qundef($5));
-		    %*/
-		    }
-		| keyword_while {COND_PUSH(1);} expr_value do {COND_POP();}
-		  compstmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_WHILE(cond($3), $6, 1);
-			fixpos($$, $3);
-		    /*%
-			$$ = dispatch2(while, $3, $6);
-		    %*/
-		    }
-		| keyword_until {COND_PUSH(1);} expr_value do {COND_POP();}
-		  compstmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_UNTIL(cond($3), $6, 1);
-			fixpos($$, $3);
-		    /*%
-			$$ = dispatch2(until, $3, $6);
-		    %*/
-		    }
-		| keyword_case expr_value opt_terms
-		  case_body
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_CASE($2, $4);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch2(case, $2, $4);
-		    %*/
-		    }
-		| keyword_case opt_terms case_body keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_CASE(0, $3);
-		    /*%
-			$$ = dispatch2(case, Qnil, $3);
-		    %*/
-		    }
-		| keyword_for for_var keyword_in
-		  {COND_PUSH(1);}
-		  expr_value do
-		  {COND_POP();}
-		  compstmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			/*
-			 *  for a, b, c in e
-			 *  #=>
-			 *  e.each{|*x| a, b, c = x
-			 *
-			 *  for a in e
-			 *  #=>
-			 *  e.each{|x| a, = x}
-			 */
-			ID id = internal_id();
-			ID *tbl;
-			NODE *m = NEW_ARGS_AUX(0, 0);
-			NODE *args, *scope;
-
-			if (nd_type($2) == NODE_MASGN) {
-			    /* if args.length == 1 && args[0].kind_of?(Array)
-			     *   args = args[0]
-			     * end
-			     */
-			    NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
-			    NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
-			    GC_WB(&m->nd_next, block_append(
-				NEW_IF(
-				    NEW_NODE(NODE_AND,
-					     NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("length"), 0),
-						      rb_intern("=="), one),
-					     NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
-						      rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
-					     0),
-				    NEW_DASGN_CURR(id,
-						   NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
-				    0),
-				node_assign($2, NEW_DVAR(id))));
-
-			    args = new_args(m, 0, id, 0, 0);
-			}
-			else {
-			    if (nd_type($2) == NODE_LASGN ||
-				nd_type($2) == NODE_DASGN ||
-				nd_type($2) == NODE_DASGN_CURR) {
-				GC_WB(&$2->nd_value, NEW_DVAR(id));
-				m->nd_plen = 1;
-				GC_WB(&m->nd_next, $2);
-				args = new_args(m, 0, 0, 0, 0);
-			    }
-			    else {
-				GC_WB(&m->nd_next, node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id)));
-				args = new_args(m, 0, id, 0, 0);
-			    }
-			}
-
-			int args_count = vtable_size(lvtbl->args);
-			int vars_count = vtable_size(lvtbl->vars);
-			tbl = ALLOC_N(ID, args_count + vars_count + 3);
-			tbl[0] = 1; tbl[1] = id;
-			tbl[2] = args_count + vars_count;
-			vtable_tblcpy(tbl+3, lvtbl->args);
-			vtable_tblcpy(tbl+3+args_count, lvtbl->vars);
-
-			scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
-			$$ = NEW_FOR(0, $5, scope);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch3(for, $2, $5, $8);
-		    %*/
-		    }
-		| keyword_class cpath superclass
-		    {
-			if (in_def || in_single)
-			    yyerror("class definition in method body");
-		    /*%%%*/
-			local_push(0);
-			$<num>$ = ruby_sourceline;
-		    /*%
-		    %*/
-		    }
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_CLASS($2, $5, $3);
-			nd_set_line($$, $<num>4);
-			local_pop();
-		    /*%
-			$$ = dispatch3(class, $2, $3, $5);
-		    %*/
-		    }
-		| keyword_class tLSHFT expr
-		    {
-		    /*%%%*/
-			$<num>$ = in_def;
-			in_def = 0;
-		    /*%
-			in_def = 0;
-		    %*/
-		    }
-		  term
-		    {
-		    /*%%%*/
-			$<num>$ = in_single;
-			in_single = 0;
-			local_push(0);
-		    /*%
-			$$ = in_single;
-			in_single = 0;
-		    %*/
-		    }
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_SCLASS($3, $7);
-			fixpos($$, $3);
-			local_pop();
-			in_def = $<num>4;
-			in_single = $<num>6;
-		    /*%
-			$$ = dispatch2(sclass, $3, $7);
-			in_def = $<val>4;
-			in_single = $<val>6;
-		    %*/
-		    }
-		| keyword_module cpath
-		    {
-			if (in_def || in_single)
-			    yyerror("module definition in method body");
-		    /*%%%*/
-			local_push(0);
-			$<num>$ = ruby_sourceline;
-		    /*%
-		    %*/
-		    }
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_MODULE($2, $4);
-			nd_set_line($$, $<num>3);
-			local_pop();
-		    /*%
-			$$ = dispatch2(module, $2, $4);
-		    %*/
-		    }
-		| keyword_def fname
-		    {
-			$<id>$ = cur_mid;
-			cur_mid = $2;
-			in_def++;
-#if WITH_OBJC
-			in_def_named_args = 0;
-			named_arg($2, 1);
-#endif
-		    /*%%%*/
-			local_push(0);
-		    /*%
-		    %*/
-		    }
-		  f_arglist
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			NODE *body = remove_begin($5);
-			ID mid = $2;
-			reduce_nodes(&body);
-#if WITH_OBJC
-			if (in_def_named_args > 0)
-			    mid = rb_intern(named_mid);
-#endif
-			$$ = NEW_DEFN(mid, $4, body, NOEX_PRIVATE);
-			fixpos($$, $4);
-#if WITH_OBJC
-			if (in_def_named_args > 0
-			    && in_def_named_args 
-			       != $$->nd_defn->nd_args->nd_frml - 1) {
-			    yyerror("invalid use of named arguments in " \
-				    "method definition");
-			}
-			in_def_named_args = 0;
-#endif
-			local_pop();
-			in_def--;
-			cur_mid = $<id>3;
-		    /*%
-			$$ = dispatch3(def, $2, $4, $5);
-			in_def--;
-			cur_mid = $<id>3;
-		    %*/
-		    }
-		| keyword_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
-		    {
-			in_single++;
-			lex_state = EXPR_END; /* force for args */
-#if WITH_OBJC
-			in_def_named_args = 0;
-			named_arg($5, 1);
-#endif
-		    /*%%%*/
-			local_push(0);
-		    /*%
-		    %*/
-		    }
-		  f_arglist
-		  bodystmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			NODE *body = remove_begin($8);
-			ID mid = $5;
-			reduce_nodes(&body);
-#if WITH_OBJC
-			if (in_def_named_args > 0)
-			    mid = rb_intern(named_mid);
-#endif
-			$$ = NEW_DEFS($2, mid, $7, body);
-			fixpos($$, $2);
-#if WITH_OBJC
-			if (in_def_named_args > 0 
-			    && in_def_named_args 
-			       != $$->nd_defn->nd_args->nd_frml - 1) {
-			    yyerror("invalid use of named arguments in " \
-				    "method definition");
-			}
-			in_def_named_args = 0;
-#endif
-			local_pop();
-			in_single--;
-		    /*%
-			$$ = dispatch5(defs, $2, $3, $5, $7, $8);
-			in_single--;
-		    %*/
-		    }
-		| keyword_break
-		    {
-		    /*%%%*/
-			$$ = NEW_BREAK(0);
-		    /*%
-			$$ = dispatch1(break, arg_new());
-		    %*/
-		    }
-		| keyword_next
-		    {
-		    /*%%%*/
-			$$ = NEW_NEXT(0);
-		    /*%
-			$$ = dispatch1(next, arg_new());
-		    %*/
-		    }
-		| keyword_redo
-		    {
-		    /*%%%*/
-			$$ = NEW_REDO();
-		    /*%
-			$$ = dispatch0(redo);
-		    %*/
-		    }
-		| keyword_retry
-		    {
-		    /*%%%*/
-			$$ = NEW_RETRY();
-		    /*%
-			$$ = dispatch0(retry);
-		    %*/
-		    }
-		;
-
-primary_value	: primary
-		    {
-		    /*%%%*/
-			value_expr($1);
-			$$ = $1;
-		        if (!$$) $$ = NEW_NIL();
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-then		: term
-		    /*%c%*/
-		    /*%c
-		    { $$ = Qnil; }
-		    %*/
-		| keyword_then
-		| term keyword_then
-		    /*%c%*/
-		    /*%c
-		    { $$ = $2; }
-		    %*/
-		;
-
-do		: term
-		    /*%c%*/
-		    /*%c
-		    { $$ = Qnil; }
-		    %*/
-		| keyword_do_cond
-		;
-
-if_tail		: opt_else
-		| keyword_elsif expr_value then
-		  compstmt
-		  if_tail
-		    {
-		    /*%%%*/
-			$$ = NEW_IF(cond($2), $4, $5);
-			fixpos($$, $2);
-		    /*%
-			$$ = dispatch3(elsif, $2, $4, escape_Qundef($5));
-		    %*/
-		    }
-		;
-
-opt_else	: none
-		| keyword_else compstmt
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(else, $2);
-		    %*/
-		    }
-		;
-
-for_var		: lhs
-		| mlhs
-		;
-
-f_marg		: f_norm_arg
-		    {
-		    /*%%%*/
-			$$ = assignable($1, 0);
-		    /*%
-			$$ = dispatch1(mlhs_paren, $1);
-		    %*/
-		    }
-		| tLPAREN f_margs rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-f_marg_list	: f_marg
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = mlhs_add(mlhs_new(), $1);
-		    %*/
-		    }
-		| f_marg_list ',' f_marg
-		    {
-		    /*%%%*/
-			$$ = list_append($1, $3);
-		    /*%
-			$$ = mlhs_add($1, $3);
-		    %*/
-		    }
-		;
-
-f_margs		: f_marg_list
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, 0);
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| f_marg_list ',' tSTAR f_norm_arg
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, assignable($4, 0));
-		    /*%
-			$$ = mlhs_add_star($1, $4);
-		    %*/
-		    }
-		| f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, NEW_POSTARG(assignable($4, 0), $6));
-		    /*%
-			$$ = mlhs_add_star($1, $4);
-		    %*/
-		    }
-		| f_marg_list ',' tSTAR
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, -1);
-		    /*%
-			$$ = mlhs_add_star($1, Qnil);
-		    %*/
-		    }
-		| f_marg_list ',' tSTAR ',' f_marg_list
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN($1, NEW_POSTARG(-1, $5));
-		    /*%
-			$$ = mlhs_add_star($1, $5);
-		    %*/
-		    }
-		| tSTAR f_norm_arg
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, assignable($2, 0));
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), $2);
-		    %*/
-		    }
-		| tSTAR f_norm_arg ',' f_marg_list
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, NEW_POSTARG(assignable($2, 0), $4));
-		    /*%
-		      #if 0
-		      TODO: Check me
-		      #endif
-			$$ = mlhs_add_star($2, $4);
-		    %*/
-		    }
-		| tSTAR
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, -1);
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), Qnil);
-		    %*/
-		    }
-		| tSTAR ',' f_marg_list
-		    {
-		    /*%%%*/
-			$$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
-		    /*%
-			$$ = mlhs_add_star(mlhs_new(), Qnil);
-		    %*/
-		    }
-		;
-
-block_param	: f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, $5, 0, $6);
-		    /*%
-			$$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
-		    %*/
-		    }
-		| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, $5, $7, $8);
-		    /*%
-			$$ = params_new($1, $3, $5, $7, escape_Qundef($8));
-		    %*/
-		    }
-		| f_arg ',' f_block_optarg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, 0, 0, $4);
-		    /*%
-			$$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, 0, $5, $6);
-		    /*%
-			$$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
-		    %*/
-		    }
-                | f_arg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, $3, 0, $4);
-		    /*%
-			$$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_arg ','
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, 1, 0, 0);
-		    /*%
-			$$ = params_new($1, Qnil, Qnil, Qnil, Qnil);
-                        dispatch1(excessed_comma, $$);
-		    %*/
-		    }
-		| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, $3, $5, $6);
-		    /*%
-			$$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
-		    %*/
-		    }
-		| f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, 0, 0, $2);
-		    /*%
-			$$ = params_new($1, Qnil,Qnil, Qnil, escape_Qundef($2));
-		    %*/
-		    }
-		| f_block_optarg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, $3, 0, $4);
-		    /*%
-			$$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, $3, $5, $6);
-		    /*%
-			$$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
-		    %*/
-		    }
-		| f_block_optarg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, 0, 0, $2);
-		    /*%
-			$$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
-		    %*/
-		    }
-		| f_block_optarg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, 0, $3, $4);
-		    /*%
-			$$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
-		    %*/
-		    }
-		| f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, $1, 0, $2);
-		    /*%
-			$$ = params_new(Qnil, Qnil, $1, Qnil, escape_Qundef($2));
-		    %*/
-		    }
-		| f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, $1, $3, $4);
-		    /*%
-			$$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
-		    %*/
-		    }
-		| f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, 0, 0, $1);
-		    /*%
-			$$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
-		    %*/
-		    }
-		;
-
-opt_block_param	: none
-		| block_param_def
-		    {
-			command_start = Qtrue;
-		    }
-		;
-
-block_param_def	: '|' opt_bv_decl '|'
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
-                                          escape_Qundef($2));
-		    %*/
-		    }
-		| tOROP
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
-                                          Qnil);
-		    %*/
-		    }
-		| '|' block_param opt_bv_decl '|'
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = blockvar_new(escape_Qundef($2), escape_Qundef($3));
-		    %*/
-		    }
-		;
-
-
-opt_bv_decl	: none
-		| ';' bv_decls
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = $2;
-		    %*/
-		    }
-		;
-
-bv_decls	: bvar
-		    /*%c%*/
-		    /*%c
-		    {
-			$$ = rb_ary_new2($1);
-		    }
-		    %*/
-		| bv_decls ',' bvar
-		    /*%c%*/
-		    /*%c
-		    {
-			rb_ary_push($$, $3);
-		    }
-		    %*/
-		;
-
-bvar		: tIDENTIFIER
-		    {
-		    /*%%%*/
-			new_bv($1);
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| f_bad_arg
-		    {
-			$$ = 0;
-		    }
-		;
-
-lambda		:   {
-		    /*%%%*/
-			dyna_push();
-			$<num>$ = lpar_beg;
-			lpar_beg = ++paren_nest;
-		    /*%
-		    %*/
-		    }
-		  f_larglist
-		  lambda_body
-		    {
-		    /*%%%*/
-			$$ = $2;
-			GC_WB(&$$->nd_body, NEW_SCOPE($2->nd_head, $3));
-			dyna_pop();
-			lpar_beg = $<num>1;
-		    /*%
-			$$ = dispatch2(lambda, $2, $3);
-		    %*/
-		    }
-		;
-
-f_larglist	: '(' f_args opt_bv_decl rparen
-		    {
-		    /*%%%*/
-			$$ = NEW_LAMBDA($2);
-		    /*%
-			$$ = dispatch1(paren, $2);
-		    %*/
-		    }
-		| f_args opt_bv_decl
-		    {
-		    /*%%%*/
-			$$ = NEW_LAMBDA($1);
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-lambda_body	: tLAMBEG compstmt '}'
-		    {
-			$$ = $2;
-		    }
-		| keyword_do_LAMBDA compstmt keyword_end
-		    {
-			$$ = $2;
-		    }
-		;
-
-do_block	: keyword_do_block
-		    {
-		    /*%%%*/
-			dyna_push();
-			$<num>$ = ruby_sourceline;
-		    /*% %*/
-		    }
-		  opt_block_param
-		  compstmt
-		  keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_ITER($3,$4);
-			nd_set_line($$, $<num>2);
-			dyna_pop();
-		    /*%
-			$$ = dispatch2(do_block, escape_Qundef($3), $4);
-		    %*/
-		    }
-		;
-
-block_call	: command do_block
-		    {
-		    /*%%%*/
-			block_dup_check($1->nd_args, $2);
-			GC_WB(&$2->nd_iter, $1);
-			$$ = $2;
-			fixpos($$, $1);
-		    /*%
-			$$ = method_add_block($1, $2);
-		    %*/
-		    }
-		| block_call '.' operation2 opt_paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
-			$$ = method_optarg($$, $4);
-		    %*/
-		    }
-		| block_call tCOLON2 operation2 opt_paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_intern("::"), $3);
-			$$ = method_optarg($$, $4);
-		    %*/
-		    }
-		;
-
-method_call	: operation paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_FCALL($1, $2);
-			fixpos($$, $2);
-		    /*%
-			$$ = method_arg(dispatch1(fcall, $1), $2);
-		    %*/
-		    }
-		| primary_value '.' operation2 opt_paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
-			$$ = method_optarg($$, $4);
-		    %*/
-		    }
-		| primary_value tCOLON2 operation2 paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, $4);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
-			$$ = method_optarg($$, $4);
-		    %*/
-		    }
-		| primary_value tCOLON2 operation3
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, $3, 0);
-		    /*%
-			$$ = dispatch3(call, $1, ripper_intern("::"), $3);
-		    %*/
-		    }
-		| primary_value '.' paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, rb_intern("call"), $3);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(call, dispatch1(paren, $1),
-				       ripper_id2sym('.'), rb_intern("call"));
-			$$ = method_optarg($$, $3);
-		    %*/
-		    }
-		| primary_value tCOLON2 paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_CALL($1, rb_intern("call"), $3);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch3(call, dispatch1(paren, $1),
-				       ripper_id2sym('.'), rb_intern("call"));
-			$$ = method_optarg($$, $3);
-		    %*/
-		    }
-		| keyword_super paren_args
-		    {
-		    /*%%%*/
-			$$ = NEW_SUPER($2);
-		    /*%
-			$$ = dispatch1(super, $2);
-		    %*/
-		    }
-		| keyword_super
-		    {
-		    /*%%%*/
-			$$ = NEW_ZSUPER();
-		    /*%
-			$$ = dispatch0(zsuper);
-		    %*/
-		    }
-		| primary_value '[' opt_call_args rbracket
-		    {
-		    /*%%%*/
-			if ($1 && nd_type($1) == NODE_SELF)
-			    $$ = NEW_FCALL(tAREF, $3);
-			else
-			    $$ = NEW_CALL($1, tAREF, $3);
-			fixpos($$, $1);
-		    /*%
-			$$ = dispatch2(aref, $1, escape_Qundef($3));
-		    %*/
-		    }
-		;
-
-brace_block	: '{'
-		    {
-		    /*%%%*/
-			dyna_push();
-			$<num>$ = ruby_sourceline;
-		    /*%
-                    %*/
-		    }
-		  opt_block_param
-		  compstmt '}'
-		    {
-		    /*%%%*/
-			$$ = NEW_ITER($3,$4);
-			nd_set_line($$, $<num>2);
-			dyna_pop();
-		    /*%
-			$$ = dispatch2(brace_block, escape_Qundef($3), $4);
-		    %*/
-		    }
-		| keyword_do
-		    {
-		    /*%%%*/
-			dyna_push();
-			$<num>$ = ruby_sourceline;
-		    /*%
-                    %*/
-		    }
-		  opt_block_param
-		  compstmt keyword_end
-		    {
-		    /*%%%*/
-			$$ = NEW_ITER($3,$4);
-			nd_set_line($$, $<num>2);
-			dyna_pop();
-		    /*%
-			$$ = dispatch2(do_block, escape_Qundef($3), $4);
-		    %*/
-		    }
-		;
-
-case_body	: keyword_when args then
-		  compstmt
-		  cases
-		    {
-		    /*%%%*/
-			$$ = NEW_WHEN($2, $4, $5);
-		    /*%
-			$$ = dispatch3(when, $2, $4, escape_Qundef($5));
-		    %*/
-		    }
-		;
-
-cases		: opt_else
-		| case_body
-		;
-
-opt_rescue	: keyword_rescue exc_list exc_var then
-		  compstmt
-		  opt_rescue
-		    {
-		    /*%%%*/
-			if ($3) {
-			    $3 = node_assign($3, NEW_ERRINFO());
-			    $5 = block_append($3, $5);
-			}
-			$$ = NEW_RESBODY($2, $5, $6);
-			fixpos($$, $2?$2:$5);
-		    /*%
-			$$ = dispatch4(rescue,
-				       escape_Qundef($2),
-				       escape_Qundef($3),
-				       escape_Qundef($5),
-				       escape_Qundef($6));
-		    %*/
-		    }
-		| none
-		;
-
-exc_list	: arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST($1);
-		    /*%
-			$$ = rb_ary_new3(1, $1);
-		    %*/
-		    }
-		| mrhs
-		    {
-		    /*%%%*/
-			if (!($$ = splat_array($1))) $$ = $1;
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| none
-		;
-
-exc_var		: tASSOC lhs
-		    {
-			$$ = $2;
-		    }
-		| none
-		;
-
-opt_ensure	: keyword_ensure compstmt
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(ensure, $2);
-		    %*/
-		    }
-		| none
-		;
-
-literal		: numeric
-		| symbol
-		    {
-		    /*%%%*/
-			$$ = NEW_LIT(ID2SYM($1));
-		    /*%
-			$$ = dispatch1(symbol_literal, $1);
-		    %*/
-		    }
-		| dsym
-		;
-
-strings		: string
-		    {
-		    /*%%%*/
-			NODE *node = $1;
-			if (!node) {
-			    node = NEW_STR(STR_NEW0());
-			}
-			else {
-			    node = evstr2dstr(node);
-			}
-			$$ = node;
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		;
-
-string		: tCHAR
-		| string1
-		| string string1
-		    {
-		    /*%%%*/
-			$$ = literal_concat($1, $2);
-		    /*%
-			$$ = dispatch2(string_concat, $1, $2);
-		    %*/
-		    }
-		;
-
-string1		: tSTRING_BEG string_contents tSTRING_END
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(string_literal, $2);
-		    %*/
-		    }
-		;
-
-xstring		: tXSTRING_BEG xstring_contents tSTRING_END
-		    {
-		    /*%%%*/
-			NODE *node = $2;
-			if (!node) {
-			    node = NEW_XSTR(STR_NEW0());
-			}
-			else {
-			    switch (nd_type(node)) {
-			      case NODE_STR:
-				nd_set_type(node, NODE_XSTR);
-				break;
-			      case NODE_DSTR:
-				nd_set_type(node, NODE_DXSTR);
-				break;
-			      default:
-				node = NEW_NODE(NODE_DXSTR, STR_NEW0(), 1, NEW_LIST(node));
-				break;
-			    }
-			}
-			$$ = node;
-		    /*%
-			$$ = dispatch1(xstring_literal, $2);
-		    %*/
-		    }
-		;
-
-regexp		: tREGEXP_BEG xstring_contents tREGEXP_END
-		    {
-		    /*%%%*/
-			int options = $3;
-			NODE *node = $2;
-                        NODE *list;
-			if (!node) {
-			    node = NEW_LIT(reg_compile(STR_NEW0(), options));
-			}
-			else switch (nd_type(node)) {
-			  case NODE_STR:
-			    {
-				VALUE src = node->nd_lit;
-				nd_set_type(node, NODE_LIT);
-				GC_WB(&node->nd_lit, GC_RETAIN(reg_compile(src, options)));
-			    }
-			    break;
-			  default:
-			    node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node));
-			  case NODE_DSTR:
-			    if (options & RE_OPTION_ONCE) {
-				nd_set_type(node, NODE_DREGX_ONCE);
-			    }
-			    else {
-				nd_set_type(node, NODE_DREGX);
-			    }
-			    node->nd_cflag = options & RE_OPTION_MASK;
-                            reg_fragment_check(node->nd_lit, options);
-                            for (list = node->nd_next; list; list = list->nd_next) {
-                                if (nd_type(list->nd_head) == NODE_STR) {
-                                    reg_fragment_check(list->nd_head->nd_lit, options);
-                                }
-                            }
-			    break;
-			}
-			$$ = node;
-		    /*%
-			$$ = dispatch2(regexp_literal, $2, $3);
-		    %*/
-		    }
-		;
-
-words		: tWORDS_BEG ' ' tSTRING_END
-		    {
-		    /*%%%*/
-			$$ = NEW_ZARRAY();
-		    /*%
-			$$ = dispatch0(words_new);
-		    %*/
-		    }
-		| tWORDS_BEG word_list tSTRING_END
-		    {
-			$$ = $2;
-		    }
-		;
-
-word_list	: /* none */
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = dispatch0(words_new);
-		    %*/
-		    }
-		| word_list word ' '
-		    {
-		    /*%%%*/
-			$$ = list_append($1, evstr2dstr($2));
-		    /*%
-			$$ = dispatch2(words_add, $1, $2);
-		    %*/
-		    }
-		;
-
-word		: string_content
-		    /*%c%*/
-		    /*%c
-		    {
-			$$ = dispatch0(word_new);
-			$$ = dispatch2(word_add, $$, $1);
-		    }
-		    %*/
-		| word string_content
-		    {
-		    /*%%%*/
-			$$ = literal_concat($1, $2);
-		    /*%
-			$$ = dispatch2(word_add, $1, $2);
-		    %*/
-		    }
-		;
-
-qwords		: tQWORDS_BEG ' ' tSTRING_END
-		    {
-		    /*%%%*/
-			$$ = NEW_ZARRAY();
-		    /*%
-			$$ = dispatch0(qwords_new);
-		    %*/
-		    }
-		| tQWORDS_BEG qword_list tSTRING_END
-		    {
-			$$ = $2;
-		    }
-		;
-
-qword_list	: /* none */
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = dispatch0(qwords_new);
-		    %*/
-		    }
-		| qword_list tSTRING_CONTENT ' '
-		    {
-		    /*%%%*/
-			$$ = list_append($1, $2);
-		    /*%
-			$$ = dispatch2(qwords_add, $1, $2);
-		    %*/
-		    }
-		;
-
-string_contents : /* none */
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = dispatch0(string_content);
-		    %*/
-		    }
-		| string_contents string_content
-		    {
-		    /*%%%*/
-			$$ = literal_concat($1, $2);
-		    /*%
-			$$ = dispatch2(string_add, $1, $2);
-		    %*/
-		    }
-		;
-
-xstring_contents: /* none */
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = dispatch0(xstring_new);
-		    %*/
-		    }
-		| xstring_contents string_content
-		    {
-		    /*%%%*/
-			$$ = literal_concat($1, $2);
-		    /*%
-			$$ = dispatch2(xstring_add, $1, $2);
-		    %*/
-		    }
-		;
-
-string_content	: tSTRING_CONTENT
-		| tSTRING_DVAR
-		    {
-			$<node>$ = lex_strterm;
-			lex_strterm = 0;
-			lex_state = EXPR_BEG;
-		    }
-		  string_dvar
-		    {
-		    /*%%%*/
-			GC_WB(&lex_strterm, $<node>2);
-			$$ = NEW_EVSTR($3);
-		    /*%
-			lex_strterm = $<node>2;
-			$$ = dispatch1(string_dvar, $3);
-		    %*/
-		    }
-		| tSTRING_DBEG
-		    {
-			$<node>$ = lex_strterm;
-			lex_strterm = 0;
-			lex_state = EXPR_BEG;
-			COND_PUSH(0);
-			CMDARG_PUSH(0);
-		    }
-		  compstmt '}'
-		    {
-			GC_WB(&lex_strterm, $<node>2);
-			COND_LEXPOP();
-			CMDARG_LEXPOP();
-		    /*%%%*/
-			if ($3) $3->flags &= ~NODE_FL_NEWLINE;
-			$$ = new_evstr($3);
-		    /*%
-			$$ = dispatch1(string_embexpr, $3);
-		    %*/
-		    }
-		;
-
-string_dvar	: tGVAR
-		    {
-		    /*%%%*/
-			$$ = NEW_GVAR($1);
-		    /*%
-			$$ = dispatch1(var_ref, $1);
-		    %*/
-		    }
-		| tIVAR
-		    {
-		    /*%%%*/
-			$$ = NEW_IVAR($1);
-		    /*%
-			$$ = dispatch1(var_ref, $1);
-		    %*/
-		    }
-		| tCVAR
-		    {
-		    /*%%%*/
-			$$ = NEW_CVAR($1);
-		    /*%
-			$$ = dispatch1(var_ref, $1);
-		    %*/
-		    }
-		| backref
-		;
-
-symbol		: tSYMBEG sym
-		    {
-		    /*%%%*/
-			lex_state = EXPR_ENDARG;
-			$$ = $2;
-		    /*%
-			lex_state = EXPR_ENDARG;
-			$$ = dispatch1(symbol, $2);
-		    %*/
-		    }
-		;
-
-sym		: fname
-		| tIVAR
-		| tGVAR
-		| tCVAR
-		;
-
-dsym		: tSYMBEG xstring_contents tSTRING_END
-		    {
-		    /*%%%*/
-			lex_state = EXPR_ENDARG;
-			if (!($$ = $2)) {
-			    $$ = NEW_LIT(ID2SYM(rb_intern("")));
-			}
-			else {
-			    VALUE lit;
-
-			    switch (nd_type($$)) {
-			      case NODE_DSTR:
-				nd_set_type($$, NODE_DSYM);
-				break;
-			      case NODE_STR:
-				lit = $$->nd_lit;
-				$$->nd_lit = ID2SYM(rb_intern_str(lit));
-				nd_set_type($$, NODE_LIT);
-				break;
-			      default:
-				$$ = NEW_NODE(NODE_DSYM, STR_NEW0(), 1, NEW_LIST($$));
-				break;
-			    }
-			}
-		    /*%
-			lex_state = EXPR_ENDARG;
-			$$ = dispatch1(dyna_symbol, $2);
-		    %*/
-		    }
-		;
-
-numeric 	: tINTEGER
-		| tFLOAT
-		| tUMINUS_NUM tINTEGER	       %prec tLOWEST
-		    {
-		    /*%%%*/
-			$$ = negate_lit($2);
-		    /*%
-			$$ = dispatch2(unary, ripper_intern("-@"), $2);
-		    %*/
-		    }
-		| tUMINUS_NUM tFLOAT	       %prec tLOWEST
-		    {
-		    /*%%%*/
-			$$ = negate_lit($2);
-		    /*%
-			$$ = dispatch2(unary, ripper_intern("-@"), $2);
-		    %*/
-		    }
-		;
-
-variable	: tIDENTIFIER
-		| tIVAR
-		| tGVAR
-		| tCONSTANT
-		| tCVAR
-		| keyword_nil {ifndef_ripper($$ = keyword_nil);}
-		| keyword_self {ifndef_ripper($$ = keyword_self);}
-		| keyword_true {ifndef_ripper($$ = keyword_true);}
-		| keyword_false {ifndef_ripper($$ = keyword_false);}
-		| keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);}
-		| keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);}
-		| keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);}
-		;
-
-var_ref		: variable
-		    {
-		    /*%%%*/
-			if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
-		    /*%
-			$$ = dispatch1(var_ref, $1);
-		    %*/
-		    }
-		;
-
-var_lhs		: variable
-		    {
-		    /*%%%*/
-			$$ = assignable($1, 0);
-		    /*%
-			$$ = dispatch1(var_field, $1);
-		    %*/
-		    }
-		;
-
-backref		: tNTH_REF
-		| tBACK_REF
-		;
-
-superclass	: term
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = Qnil;
-		    %*/
-		    }
-		| '<'
-		    {
-			lex_state = EXPR_BEG;
-		    }
-		  expr_value term
-		    {
-			$$ = $3;
-		    }
-		| error term
-		    {
-		    /*%%%*/
-			yyerrok;
-			$$ = 0;
-		    /*%
-			yyerrok;
-			$$ = Qnil;
-		    %*/
-		    }
-		;
-
-f_arglist	: '(' f_args rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-			lex_state = EXPR_BEG;
-			command_start = Qtrue;
-		    /*%
-			$$ = dispatch1(paren, $2);
-			lex_state = EXPR_BEG;
-			command_start = Qtrue;
-		    %*/
-		    }
-		| f_args term
-		    {
-			$$ = $1;
-		    }
-		;
-
-f_args		: f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, $5, 0, $6);
-		    /*%
-			$$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
-		    %*/
-		    }
-		| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, $5, $7, $8);
-		    /*%
-			$$ = params_new($1, $3, $5, $7, escape_Qundef($8));
-		    %*/
-		    }
-		| f_arg ',' f_optarg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, 0, 0, $4);
-		    /*%
-			$$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_arg ',' f_optarg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, $3, 0, $5, $6);
-		    /*%
-			$$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
-		    %*/
-		    }
-		| f_arg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, $3, 0, $4);
-		    /*%
-			$$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, $3, $5, $6);
-		    /*%
-			$$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
-		    %*/
-		    }
-		| f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args($1, 0, 0, 0, $2);
-		    /*%
-			$$ = params_new($1, Qnil, Qnil, Qnil,escape_Qundef($2));
-		    %*/
-		    }
-		| f_optarg ',' f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, $3, 0, $4);
-		    /*%
-			$$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
-		    %*/
-		    }
-		| f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, $3, $5, $6);
-		    /*%
-			$$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
-		    %*/
-		    }
-		| f_optarg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, 0, 0, $2);
-		    /*%
-			$$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
-		    %*/
-		    }
-		| f_optarg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, $1, 0, $3, $4);
-		    /*%
-			$$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
-		    %*/
-		    }
-		| f_rest_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, $1, 0, $2);
-		    /*%
-			$$ = params_new(Qnil, Qnil, $1, Qnil,escape_Qundef($2));
-		    %*/
-		    }
-		| f_rest_arg ',' f_arg opt_f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, $1, $3, $4);
-		    /*%
-			$$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
-		    %*/
-		    }
-		| f_block_arg
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, 0, 0, $1);
-		    /*%
-			$$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
-		    %*/
-		    }
-		| /* none */
-		    {
-		    /*%%%*/
-			$$ = new_args(0, 0, 0, 0, 0);
-		    /*%
-			$$ = params_new(Qnil, Qnil, Qnil, Qnil, Qnil);
-		    %*/
-		    }
-		;
-
-f_bad_arg	: tCONSTANT
-		    {
-		    /*%%%*/
-			yyerror("formal argument cannot be a constant");
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(param_error, $1);
-		    %*/
-		    }
-		| tIVAR
-		    {
-		    /*%%%*/
-			yyerror("formal argument cannot be an instance variable");
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(param_error, $1);
-		    %*/
-		    }
-		| tGVAR
-		    {
-		    /*%%%*/
-			yyerror("formal argument cannot be a global variable");
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(param_error, $1);
-		    %*/
-		    }
-		| tCVAR
-		    {
-		    /*%%%*/
-			yyerror("formal argument cannot be a class variable");
-			$$ = 0;
-		    /*%
-			$$ = dispatch1(param_error, $1);
-		    %*/
-		    }
-		;
-
-f_norm_arg	: f_bad_arg
-		| tIDENTIFIER
-		    {
-		    /*%%%*/
-			if (!is_local_id($1))
-			    yyerror("formal argument must be local variable");
-			shadowing_lvar($1);
-		    /*%
-		    %*/
-			$$ = $1;
-		    }
-		| tIDENTIFIER tASSOC tIDENTIFIER
-                    {
-#if WITH_OBJC
-			named_arg($1, 0);
-#endif
-			$$ = $3;
-                    }
-                | tLABEL tIDENTIFIER
-                    {
-#if WITH_OBJC
-			named_arg($1, 0);
-#endif
-			$$ = $2;
-                    }
-		;
-
-f_arg_item	: f_norm_arg
-		    {
-		    /*%%%*/
-			arg_var($1);
-			$$ = NEW_ARGS_AUX($1, 1);
-		    /*%
-		    %*/
-		    }
-		| tLPAREN f_margs rparen
-		    {
-		    /*%%%*/
-			ID tid = internal_id();
-			arg_var(tid);
-			if (dyna_in_block()) {
-			    GC_WB(&$2->nd_value, NEW_DVAR(tid));
-			}
-			else {
-			    GC_WB(&$2->nd_value, NEW_LVAR(tid));
-			}
-			$$ = NEW_ARGS_AUX(tid, 1);
-			GC_WB(&$$->nd_next, $2);
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-f_arg		: f_arg_item
-		    /*%c%*/
-		    /*%c
-		    {
-			$$ = rb_ary_new3(1, $1);
-		    }
-		    c%*/
-		| f_arg ',' f_arg_item
-		    {
-		    /*%%%*/
-			$$ = $1;
-			$$->nd_plen++;
-			GC_WB(&$$->nd_next, block_append($$->nd_next, $3->nd_next));
-			rb_gc_force_recycle((VALUE)$3);
-		    /*%
-			$$ = rb_ary_push($1, $3);
-		    %*/
-		    }
-		;
-
-f_opt		: tIDENTIFIER '=' arg_value
-		    {
-		    /*%%%*/
-			if (!is_local_id($1))
-			    yyerror("formal argument must be local variable");
-			shadowing_lvar($1);
-			arg_var($1);
-			$$ = NEW_OPT_ARG(0, assignable($1, $3));
-		    /*%
-			$$ = rb_assoc_new($1, $3);
-		    %*/
-		    }
-		;
-
-f_block_opt	: tIDENTIFIER '=' primary_value
-		    {
-		    /*%%%*/
-			if (!is_local_id($1))
-			    yyerror("formal argument must be local variable");
-			shadowing_lvar($1);
-			arg_var($1);
-			$$ = NEW_OPT_ARG(0, assignable($1, $3));
-		    /*%
-			$$ = rb_assoc_new($1, $3);
-		    %*/
-		    }
-		;
-
-f_block_optarg	: f_block_opt
-		    {
-		    /*%%%*/
-			$$ = $1;
-		    /*%
-			$$ = rb_ary_new3(1, $1);
-		    %*/
-		    }
-		| f_block_optarg ',' f_block_opt
-		    {
-		    /*%%%*/
-			NODE *opts = $1;
-
-			while (opts->nd_next) {
-			    opts = opts->nd_next;
-			}
-			opts->nd_next = $3;
-			$$ = $1;
-		    /*%
-			$$ = rb_ary_push($1, $3);
-		    %*/
-		    }
-		;
-
-f_optarg	: f_opt
-		    {
-		    /*%%%*/
-			$$ = $1;
-		    /*%
-			$$ = rb_ary_new3(1, $1);
-		    %*/
-		    }
-		| f_optarg ',' f_opt
-		    {
-		    /*%%%*/
-			NODE *opts = $1;
-
-			while (opts->nd_next) {
-			    opts = opts->nd_next;
-			}
-			GC_WB(&opts->nd_next, $3);
-			$$ = $1;
-		    /*%
-			$$ = rb_ary_push($1, $3);
-		    %*/
-		    }
-		;
-
-restarg_mark	: '*'
-		| tSTAR
-		;
-
-f_rest_arg	: restarg_mark tIDENTIFIER
-		    {
-		    /*%%%*/
-			if (!is_local_id($2))
-			    yyerror("rest argument must be local variable");
-			shadowing_lvar($2);
-			arg_var($2);
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(rest_param, $2);
-		    %*/
-		    }
-		| restarg_mark
-		    {
-		    /*%%%*/
-			$$ = internal_id();
-			arg_var($$);
-		    /*%
-			$$ = dispatch1(rest_param, Qnil);
-		    %*/
-		    }
-		;
-
-blkarg_mark	: '&'
-		| tAMPER
-		;
-
-f_block_arg	: blkarg_mark tIDENTIFIER
-		    {
-		    /*%%%*/
-			if (!is_local_id($2))
-			    yyerror("block argument must be local variable");
-			else if (!dyna_in_block() && local_id($2))
-			    yyerror("duplicated block argument name");
-			shadowing_lvar($2);
-			arg_var($2);
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(blockarg, $2);
-		    %*/
-		    }
-		;
-
-opt_f_block_arg	: ',' f_block_arg
-		    {
-			$$ = $2;
-		    }
-		| none
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = Qundef;
-		    %*/
-		    }
-		;
-
-singleton	: var_ref
-		    {
-		    /*%%%*/
-			value_expr($1);
-			$$ = $1;
-		        if (!$$) $$ = NEW_NIL();
-		    /*%
-			$$ = $1;
-		    %*/
-		    }
-		| '(' {lex_state = EXPR_BEG;} expr rparen
-		    {
-		    /*%%%*/
-			if ($3 == 0) {
-			    yyerror("can't define singleton method for ().");
-			}
-			else {
-			    switch (nd_type($3)) {
-			      case NODE_STR:
-			      case NODE_DSTR:
-			      case NODE_XSTR:
-			      case NODE_DXSTR:
-			      case NODE_DREGX:
-			      case NODE_LIT:
-			      case NODE_ARRAY:
-			      case NODE_ZARRAY:
-				yyerror("can't define singleton method for literals");
-			      default:
-				value_expr($3);
-				break;
-			    }
-			}
-			$$ = $3;
-		    /*%
-			$$ = dispatch1(paren, $3);
-		    %*/
-		    }
-		;
-
-assoc_list	: none
-		| assocs trailer
-		    {
-		    /*%%%*/
-			$$ = $1;
-		    /*%
-			$$ = dispatch1(assoclist_from_args, $1);
-		    %*/
-		    }
-		;
-
-assocs		: assoc
-		    /*%c%*/
-		    /*%c
-		    {
-			$$ = rb_ary_new3(1, $1);
-		    }
-		    %*/
-		| assocs ',' assoc
-		    {
-		    /*%%%*/
-			$$ = list_concat($1, $3);
-		    /*%
-			$$ = rb_ary_push($1, $3);
-		    %*/
-		    }
-		;
-
-assoc		: arg_value tASSOC arg_value
-		    {
-		    /*%%%*/
-			$$ = list_append(NEW_LIST($1), $3);
-		    /*%
-			$$ = dispatch2(assoc_new, $1, $3);
-		    %*/
-		    }
-		| tLABEL arg_value
-		    {
-		    /*%%%*/
-			$$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
-		    /*%
-			$$ = dispatch2(assoc_new, $1, $2);
-		    %*/
-		    }
-		;
-
-operation	: tIDENTIFIER
-		| tCONSTANT
-		| tFID
-		;
-
-operation2	: tIDENTIFIER
-		| tCONSTANT
-		| tFID
-		| op
-		;
-
-operation3	: tIDENTIFIER
-		| tFID
-		| op
-		;
-
-dot_or_colon	: '.'
-		    /*%c%*/
-		    /*%c
-		    { $$ = $<val>1; }
-		    %*/
-		| tCOLON2
-		    /*%c%*/
-		    /*%c
-		    { $$ = $<val>1; }
-		    %*/
-		;
-
-opt_terms	: /* none */
-		| terms
-		;
-
-opt_nl		: /* none */
-		| '\n'
-		;
-
-rparen		: opt_nl ')'
-		;
-
-rbracket	: opt_nl ']'
-		;
-
-trailer		: /* none */
-		| '\n'
-		| ','
-		;
-
-term		: ';' {yyerrok;}
-		| '\n'
-		;
-
-terms		: term
-		| terms ';' {yyerrok;}
-		;
-
-none		: /* none */
-		    {
-		    /*%%%*/
-			$$ = 0;
-		    /*%
-			$$ = Qundef;
-		    %*/
-		    }
-		;
-%%
-# undef parser
-# undef yylex
-# undef yylval
-# define yylval  (*((YYSTYPE*)(parser->parser_yylval)))
-
-static int parser_regx_options(struct parser_params*);
-static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);
-static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);
-static int parser_parse_string(struct parser_params*,NODE*);
-static int parser_here_document(struct parser_params*,NODE*);
-
-
-# define nextc()                   parser_nextc(parser)
-# define pushback(c)               parser_pushback(parser, c)
-# define newtok()                  parser_newtok(parser)
-# define tokspace(n)               parser_tokspace(parser, n)
-# define tokadd(c)                 parser_tokadd(parser, c)
-# define tok_hex(numlen)           parser_tok_hex(parser, numlen)
-# define read_escape(flags,e)      parser_read_escape(parser, flags, e)
-# define tokadd_escape(e)          parser_tokadd_escape(parser, e)
-# define regx_options()            parser_regx_options(parser)
-# define tokadd_string(f,t,p,n,e)  parser_tokadd_string(parser,f,t,p,n,e)
-# define parse_string(n)           parser_parse_string(parser,n)
-# define tokaddmbc(c, enc)         parser_tokaddmbc(parser, c, enc)
-# define here_document(n)          parser_here_document(parser,n)
-# define heredoc_identifier()      parser_heredoc_identifier(parser)
-# define heredoc_restore(n)        parser_heredoc_restore(parser,n)
-# define whole_match_p(e,l,i)      parser_whole_match_p(parser,e,l,i)
-
-#ifdef RIPPER
-/* FIXME */
-# define local_id(x)       1
-# define dyna_in_block()   1
-#endif /* RIPPER */
-
-#ifndef RIPPER
-# define set_yylval_str(x) yylval.node = NEW_STR(x)
-# define set_yylval_num(x) yylval.num = x
-# define set_yylval_id(x)  yylval.id = x
-# define set_yylval_literal(x) yylval.node = NEW_LIT(x)
-# define set_yylval_node(x) yylval.node = x
-# define yylval_id() yylval.id
-#else
-# define set_yylval_str(x) (void)(x)
-# define set_yylval_num(x) (void)(x)
-# define set_yylval_id(x) (void)(x)
-# define set_yylval_literal(x) (void)(x)
-# define set_yylval_node(x) (void)(x)
-# define yylval_id() SYM2ID(yylval.val)
-#endif
-
-#ifdef RIPPER
-#define ripper_flush(p) (p->tokp = p->parser_lex_p)
-
-static void
-ripper_dispatch_scan_event(struct parser_params *parser, int t)
-{
-    VALUE str;
-
-    if (lex_p < parser->tokp) rb_raise(rb_eRuntimeError, "lex_p < tokp");
-    if (lex_p == parser->tokp) return;
-    str = STR_NEW(parser->tokp, lex_p - parser->tokp);
-    yylval.val = ripper_dispatch1(parser, ripper_token2eventid(t), str);
-    ripper_flush(parser);
-}
-
-static void
-ripper_dispatch_delayed_token(struct parser_params *parser, int t)
-{
-    int saved_line = ruby_sourceline;
-    const char *saved_tokp = parser->tokp;
-
-    ruby_sourceline = parser->delayed_line;
-    parser->tokp = lex_pbeg + parser->delayed_col;
-    yylval.val = ripper_dispatch1(parser, ripper_token2eventid(t), parser->delayed);
-    parser->delayed = Qnil;
-    ruby_sourceline = saved_line;
-    parser->tokp = saved_tokp;
-}
-#endif /* RIPPER */
-
-#include "ruby/util.h"
-
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
-   since ours (we hope) works properly with all combinations of
-   machines, compilers, `char' and `unsigned char' argument types.
-   (Per Bothner suggested the basic approach.)  */
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
-#else  /* not __STDC__ */
-/* As in Harbison and Steele.  */
-# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
-#endif
-
-#define is_identchar(p,e,enc) (rb_enc_isalnum(*p,enc) || (*p) == '_' || !ISASCII(*p))
-#define parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,parser->enc))
-
-#define parser_isascii() ISASCII(*(lex_p-1))
-
-static int
-parser_yyerror(struct parser_params *parser, const char *msg)
-{
-#ifndef RIPPER
-    const int max_line_margin = 30;
-    const char *p, *pe;
-    char *buf;
-    int len, i;
-
-    compile_error(PARSER_ARG "%s", msg);
-    p = lex_p;
-    while (lex_pbeg <= p) {
-	if (*p == '\n') break;
-	p--;
-    }
-    p++;
-
-    pe = lex_p;
-    while (pe < lex_pend) {
-	if (*pe == '\n') break;
-	pe++;
-    }
-
-    len = pe - p;
-    if (len > 4) {
-	char *p2;
-	const char *pre = "", *post = "";
-
-	if (len > max_line_margin * 2 + 10) {
-	    if (lex_p - p > max_line_margin) {
-#if WITH_OBJC
-		p = lex_p - max_line_margin;
-#else
-		p = rb_enc_prev_char(p, lex_p - max_line_margin, rb_enc_get(lex_lastline));
-#endif
-		pre = "...";
-	    }
-	    if (pe - lex_p > max_line_margin) {
-#if WITH_OBJC
-		pe = lex_p + max_line_margin;
-#else
-		pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, rb_enc_get(lex_lastline));
-#endif
-		post = "...";
-	    }
-	    len = pe - p;
-	}
-	buf = ALLOCA_N(char, len+2);
-	MEMCPY(buf, p, char, len);
-	buf[len] = '\0';
-	rb_compile_error_append("%s%s%s", pre, buf, post);
-
-	i = lex_p - p;
-	p2 = buf; pe = buf + len;
-
-	while (p2 < pe) {
-	    if (*p2 != '\t') *p2 = ' ';
-	    p2++;
-	}
-	buf[i] = '^';
-	buf[i+1] = '\0';
-	rb_compile_error_append("%s%s", pre, buf);
-    }
-#else
-    dispatch1(parse_error, STR_NEW2(msg));
-#endif /* !RIPPER */
-    return 0;
-}
-
-static void parser_prepare(struct parser_params *parser);
-
-#ifndef RIPPER
-//VALUE ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always);
-
-static VALUE
-debug_lines(const char *f)
-{
-    if (rb_const_defined_at(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
-	VALUE hash = rb_const_get_at(rb_cObject, rb_intern("SCRIPT_LINES__"));
-	if (TYPE(hash) == T_HASH) {
-	    VALUE fname = rb_str_new2(f);
-	    VALUE lines = rb_ary_new();
-	    rb_hash_aset(hash, fname, lines);
-	    return lines;
-	}
-    }
-    return 0;
-}
-
-static VALUE
-yycompile0(VALUE arg, int tracing)
-{
-    int n;
-    NODE *tree;
-    struct parser_params *parser = (struct parser_params *)arg;
-
-    if (!compile_for_eval && rb_safe_level() == 0) {
-	ruby_debug_lines = debug_lines(ruby_sourcefile);
-	if (ruby_debug_lines && ruby_sourceline > 0) {
-	    VALUE str = STR_NEW0();
-	    n = ruby_sourceline;
-	    do {
-		rb_ary_push(ruby_debug_lines, str);
-	    } while (--n);
-	}
-    }
-
-    parser_prepare(parser);
-    n = yyparse((void*)parser);
-    ruby_debug_lines = 0;
-    compile_for_eval = 0;
-
-    lex_strterm = 0;
-    lex_p = lex_pbeg = lex_pend = 0;
-    lex_lastline = lex_nextline = 0;
-    if (parser->nerr) {
-	return 0;
-    }
-    tree = ruby_eval_tree;
-    if (!tree) {
-	tree = NEW_NIL();
-    }
-    if (ruby_eval_tree_begin) {
-	NODE *scope = ruby_eval_tree;
-
-        if (scope) {
-	    GC_WB(&scope->nd_body, NEW_PRELUDE(ruby_eval_tree_begin, scope->nd_body));
-	}
-	tree = scope;
-    }
-    else {
-	tree = ruby_eval_tree;
-    }
-    return (VALUE)tree;
-}
-
-static NODE*
-yycompile(struct parser_params *parser, const char *f, int line)
-{
-    GC_WB(&ruby_sourcefile, ruby_strdup(f));
-    ruby_sourceline = line - 1;
-    return (NODE *)yycompile0((VALUE)parser, Qtrue);
-//    return (NODE *)ruby_suppress_tracing(yycompile0, (VALUE)parser, Qtrue);
-}
-#endif /* !RIPPER */
-
-struct lex_get_str_context {
-    VALUE str;
-    UChar *chars;
-    long chars_len;
-};
-
-static VALUE
-lex_get_str(struct parser_params *parser, VALUE s)
-{
-    struct lex_get_str_context *ctx = (struct lex_get_str_context *)s;
-
-    long beg = 0;
-    if (lex_gets_ptr > 0) {
-	if (ctx->chars_len == lex_gets_ptr) {
-	    return Qnil;
-	}
-	beg += lex_gets_ptr;
-    }
-
-    lex_gets_ptr = ctx->chars_len;
-    for (long i = beg; i < ctx->chars_len; i++) {
-	if (ctx->chars[i] == '\n') {
-	    lex_gets_ptr = i + 1;
-	    break;
-	}
-    }
-
-    return rb_unicode_str_new(&ctx->chars[beg], lex_gets_ptr - beg);
-}
-
-static VALUE
-lex_getline(struct parser_params *parser)
-{
-    VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input);
-#ifndef RIPPER
-    if (ruby_debug_lines && !NIL_P(line)) {
-	rb_ary_push(ruby_debug_lines, line);
-    }
-#endif
-    return line;
-}
-
-#ifndef RIPPER
-NODE*
-rb_compile_string(const char *f, VALUE s, int line)
-{
-    return rb_parser_compile_string(rb_parser_new(), f, s, line);
-}
-
-NODE *
-rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
-{
-    struct parser_params *parser;
-    Data_Get_Struct(vparser, struct parser_params, parser);
-
-    long chars_len = 0;
-    UChar *chars = rb_str_xcopy_uchars(s, &chars_len); 
-
-    struct lex_get_str_context *ctx = (struct lex_get_str_context *)
-	xmalloc(sizeof(struct lex_get_str_context));
-    GC_WB(&ctx->str, s);
-    GC_WB(&ctx->chars, chars);
-    ctx->chars_len = chars_len;
-
-    lex_gets = lex_get_str;
-    lex_gets_ptr = 0;
-    GC_WB(&lex_input, ctx);
-    lex_pbeg = lex_p = lex_pend = 0;
-    compile_for_eval = rb_parse_in_eval();
-
-    return yycompile(parser, f, line);
-}
-
-NODE*
-rb_compile_cstr(const char *f, const char *s, int len, int line)
-{
-    return rb_compile_string(f, rb_str_new(s, len), line);
-}
-
-NODE*
-rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line)
-{
-    return rb_parser_compile_string(vparser, f, rb_str_new(s, len), line);
-}
-
-static VALUE
-lex_io_gets(struct parser_params *parser, VALUE io)
-{
-    return rb_io_gets(io, 0);
-}
-
-NODE*
-rb_compile_file(const char *f, VALUE file, int start)
-{
-    return rb_parser_compile_file(rb_parser_new(), f, file, start);
-}
-
-NODE *
-rb_parser_compile_file(VALUE vparser, const char *f, VALUE file,
-	int start)
-{
-    struct parser_params *parser;
-    Data_Get_Struct(vparser, struct parser_params, parser);
-
-    lex_gets = lex_io_gets;
-    GC_WB(&lex_input, file);
-    lex_pbeg = lex_p = lex_pend = 0;
-
-    return yycompile(parser, f, start);
-}
-#endif  /* !RIPPER */
-
-#define STR_FUNC_ESCAPE 0x01
-#define STR_FUNC_EXPAND 0x02
-#define STR_FUNC_REGEXP 0x04
-#define STR_FUNC_QWORDS 0x08
-#define STR_FUNC_SYMBOL 0x10
-#define STR_FUNC_INDENT 0x20
-
-enum string_type {
-    str_squote = (0),
-    str_dquote = (STR_FUNC_EXPAND),
-    str_xquote = (STR_FUNC_EXPAND),
-    str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
-    str_sword  = (STR_FUNC_QWORDS),
-    str_dword  = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
-    str_ssym   = (STR_FUNC_SYMBOL),
-    str_dsym   = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND),
-};
-
-#if 0
-static VALUE
-parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0)
-{
-    VALUE str;
-
-#if WITH_OBJC
-    if (p[n] != '\0') {
-	/* Let's not create unnecessary bytestrings. */
-	long slen = strlen(p);
-	if (slen < n)
-	    n = slen;
-    }
-#endif
-
-    str = rb_enc_str_new(p, n, enc);
-#if !WITH_OBJC
-    if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
-	if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
-	    rb_enc_associate(str, rb_usascii_encoding());
-	}
-	else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
-	    rb_enc_associate(str, rb_ascii8bit_encoding());
-	}
-    }
-#endif
-
-    return str;
-}
-#endif
-
-#define lex_goto_eol(parser) (parser->parser_lex_p = parser->parser_lex_pend)
-
-static inline int
-parser_nextc(struct parser_params *parser)
-{
-    int c;
-
-    if (lex_p == lex_pend) {
-	VALUE v = lex_nextline;
-	lex_nextline = 0;
-	if (!v) {
-	    if (parser->eofp)
-		return -1;
-
-	    if (!lex_input || NIL_P(v = lex_getline(parser))) {
-		parser->eofp = Qtrue;
-		lex_goto_eol(parser);
-		return -1;
-	    }
-	}
-	{	
-#ifdef RIPPER
-	    if (parser->tokp < lex_pend) {
-		if (NIL_P(parser->delayed)) {
-		    parser->delayed = rb_str_buf_new(1024);
-		    rb_str_buf_cat(parser->delayed,
-				   parser->tokp, lex_pend - parser->tokp);
-		    parser->delayed_line = ruby_sourceline;
-		    parser->delayed_col = parser->tokp - lex_pbeg;
-		}
-		else {
-		    rb_str_buf_cat(parser->delayed,
-				   parser->tokp, lex_pend - parser->tokp);
-		}
-	    }
-#endif
-	    if (heredoc_end > 0) {
-		ruby_sourceline = heredoc_end;
-		heredoc_end = 0;
-	    }
-	    ruby_sourceline++;
-	    parser->line_count++;
-	    lex_pbeg = lex_p = RSTRING_PTR(v);
-	    lex_pend = lex_p + RSTRING_LEN(v);
-#ifdef RIPPER
-	    ripper_flush(parser);
-#endif
-	    GC_WB(&lex_lastline, v);
-	}
-    }
-    c = (unsigned char)*lex_p++;
-    if (c == '\r' && lex_p < lex_pend && *lex_p == '\n') {
-	lex_p++;
-	c = '\n';
-    }
-
-    return c;
-}
-
-static void
-parser_pushback(struct parser_params *parser, int c)
-{
-    if (c == -1) return;
-    lex_p--;
-    if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') {
-	lex_p--;
-    }
-}
-
-#define was_bol() (lex_p == lex_pbeg + 1)
-#define peek(c) (lex_p != lex_pend && (c) == *lex_p)
-
-#define tokfix() (tokenbuf[tokidx]='\0')
-#define tok() tokenbuf
-#define toklen() tokidx
-#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
-
-static char*
-parser_newtok(struct parser_params *parser)
-{
-    tokidx = 0;
-    if (!tokenbuf) {
-	toksiz = 60;
-	GC_WB(&tokenbuf, ALLOC_N(char, 60));
-    }
-    if (toksiz > 4096) {
-	toksiz = 60;
-	REALLOC_N(tokenbuf, char, 60);
-	GC_WB(&tokenbuf, tokenbuf);
-    }
-    return tokenbuf;
-}
-
-static char *
-parser_tokspace(struct parser_params *parser, int n)
-{
-    tokidx += n;
-
-    if (tokidx >= toksiz) {
-	do {toksiz *= 2;} while (toksiz < tokidx);
-	REALLOC_N(tokenbuf, char, toksiz);
-	GC_WB(&tokenbuf, tokenbuf);
-    }
-    return &tokenbuf[tokidx-n];
-}
-
-static void
-parser_tokadd(struct parser_params *parser, int c)
-{
-    tokenbuf[tokidx++] = (char)c;
-    if (tokidx >= toksiz) {
-	toksiz *= 2;
-	REALLOC_N(tokenbuf, char, toksiz);
-	GC_WB(&tokenbuf, tokenbuf);
-    }
-}
-
-static int
-parser_tok_hex(struct parser_params *parser, int *numlen)
-{
-    int c;
-
-    c = scan_hex(lex_p, 2, numlen);
-    if (!*numlen) {
-	yyerror("invalid hex escape");
-	return 0;
-    }
-    lex_p += *numlen;
-    return c;
-}
-
-#define tokcopy(n) memcpy(tokspace(n), lex_p - (n), (n))
-
-static int
-parser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp,
-                   int string_literal, int symbol_literal, int regexp_literal)
-{
-    /*
-     * If string_literal is true, then we allow multiple codepoints
-     * in \u{}, and add the codepoints to the current token.
-     * Otherwise we're parsing a character literal and return a single
-     * codepoint without adding it 
-     */
-
-    int codepoint;
-    int numlen;
-
-    if (regexp_literal) { tokadd('\\'); tokadd('u'); }
-
-    if (peek('{')) {  /* handle \u{...} form */
-	do {
-            if (regexp_literal) { tokadd(*lex_p); }
-	    nextc();
-	    codepoint = scan_hex(lex_p, 6, &numlen);
-	    if (numlen == 0)  {
-		yyerror("invalid Unicode escape");
-		return 0;
-	    }
-	    if (codepoint > 0x10ffff) {
-		yyerror("invalid Unicode codepoint (too large)");
-		return 0;
-	    }
-	    lex_p += numlen;
-            if (regexp_literal) {
-                tokcopy(numlen);
-            }
-            else if (codepoint >= 0x80) {
-		*encp = UTF8_ENC();
-		if (string_literal) tokaddmbc(codepoint, *encp);
-	    }
-	    else if (string_literal) {
-		if (codepoint == 0 && symbol_literal) {
-		    yyerror("symbol cannot contain '\\u{0}'");
-		    return 0;
-		}
-
-		tokadd(codepoint);
-	    }
-	} while (string_literal && (peek(' ') || peek('\t')));
-
-	if (!peek('}')) {
-	    yyerror("unterminated Unicode escape");
-	    return 0;
-	}
-
-        if (regexp_literal) { tokadd('}'); }
-	nextc();
-    }
-    else {			/* handle \uxxxx form */
-	codepoint = scan_hex(lex_p, 4, &numlen);
-	if (numlen < 4) {
-	    yyerror("invalid Unicode escape");
-	    return 0;
-	}
-	lex_p += 4;
-        if (regexp_literal) {
-            tokcopy(4);
-        }
-	else if (codepoint >= 0x80) {
-	    *encp = UTF8_ENC();
-	    if (string_literal) tokaddmbc(codepoint, *encp);
-	}
-	else if (string_literal) {
-	    if (codepoint == 0 && symbol_literal) {
-		yyerror("symbol cannot contain '\\u0000'");
-		return 0;
-	    }
-
-	    tokadd(codepoint);
-	}
-    }
-
-    return codepoint;
-}
-
-#define ESCAPE_CONTROL 1
-#define ESCAPE_META    2
-
-static int
-parser_read_escape(struct parser_params *parser, int flags,
-		   rb_encoding **encp)
-{
-    int c;
-    int numlen;
-
-    switch (c = nextc()) {
-      case '\\':	/* Backslash */
-	return c;
-
-      case 'n':	/* newline */
-	return '\n';
-
-      case 't':	/* horizontal tab */
-	return '\t';
-
-      case 'r':	/* carriage-return */
-	return '\r';
-
-      case 'f':	/* form-feed */
-	return '\f';
-
-      case 'v':	/* vertical tab */
-	return '\13';
-
-      case 'a':	/* alarm(bell) */
-	return '\007';
-
-      case 'e':	/* escape */
-	return 033;
-
-      case '0': case '1': case '2': case '3': /* octal constant */
-      case '4': case '5': case '6': case '7':
-	if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
-	{
-	    int numlen;
-
-	    pushback(c);
-	    c = scan_oct(lex_p, 3, &numlen);
-	    lex_p += numlen;
-	}
-	return c;
-
-      case 'x':	/* hex constant */
-	if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
-	c = tok_hex(&numlen);
-	if (numlen == 0) return 0;
-	return c;
-
-      case 'b':	/* backspace */
-	return '\010';
-
-      case 's':	/* space */
-	return ' ';
-
-      case 'M':
-	if (flags & ESCAPE_META) goto eof;
-	if ((c = nextc()) != '-') {
-	    pushback(c);
-	    goto eof;
-	}
-	if ((c = nextc()) == '\\') {
-	    return read_escape(flags|ESCAPE_META, encp) | 0x80;
-	}
-	else if (c == -1 || !ISASCII(c)) goto eof;
-	else {
-	    return ((c & 0xff) | 0x80);
-	}
-
-      case 'C':
-	if ((c = nextc()) != '-') {
-	    pushback(c);
-	    goto eof;
-	}
-      case 'c':
-	if (flags & ESCAPE_CONTROL) goto eof;
-	if ((c = nextc())== '\\') {
-	    c = read_escape(flags|ESCAPE_CONTROL, encp);
-	}
-	else if (c == '?')
-	    return 0177;
-	else if (c == -1 || !ISASCII(c)) goto eof;
-	return c & 0x9f;
-
-      eof:
-      case -1:
-        yyerror("Invalid escape character syntax");
-	return '\0';
-
-      default:
-	return c;
-    }
-}
-
-#include <unicode/utf8.h>
-
-static void
-parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc)
-{
-#if WITH_OBJC
-    const int bytelen = U8_LENGTH(c);
-    uint8_t *buf = (uint8_t *)tokspace(bytelen);
-    UBool error = false;
-    int offset = 0;
-    U8_APPEND(buf, offset, bytelen, c, error);
-    if (error) {
-	rb_raise(rb_eArgError, "invalid unicode point U+%d", c);
-    }
-#else
-    int len = rb_enc_codelen(c, enc);
-    rb_enc_mbcput(c, tokspace(len), enc);
-#endif
-}
-
-static int
-parser_tokadd_escape(struct parser_params *parser, rb_encoding **encp)
-{
-    int c;
-    int flags = 0;
-
-  first:
-    switch (c = nextc()) {
-      case '\n':
-	return 0;		/* just ignore */
-
-      case '0': case '1': case '2': case '3': /* octal constant */
-      case '4': case '5': case '6': case '7':
-	if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
-	{
-	    int numlen;
-	    int oct;
-
-	    oct = scan_oct(--lex_p, 3, &numlen);
-	    if (numlen == 0) goto eof;
-	    lex_p += numlen;
-	    tokcopy(numlen + 1);
-	}
-	return 0;
-
-      case 'x':	/* hex constant */
-	if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
-	{
-	    int numlen;
-	    int hex;
-
-	    hex = tok_hex(&numlen);
-	    if (numlen == 0) goto eof;
-	    tokcopy(numlen + 2);
-	}
-	return 0;
-
-      case 'M':
-	if (flags & ESCAPE_META) goto eof;
-	if ((c = nextc()) != '-') {
-	    pushback(c);
-	    goto eof;
-	}
-	tokcopy(3);
-	flags |= ESCAPE_META;
-	goto escaped;
-
-      case 'C':
-	if (flags & ESCAPE_CONTROL) goto eof;
-	if ((c = nextc()) != '-') {
-	    pushback(c);
-	    goto eof;
-	}
-	tokcopy(3);
-	goto escaped;
-
-      case 'c':
-	if (flags & ESCAPE_CONTROL) goto eof;
-	tokcopy(2);
-	flags |= ESCAPE_CONTROL;
-      escaped:
-	if ((c = nextc()) == '\\') {
-	    goto first;
-	}
-	else if (c == -1) goto eof;
-	tokadd(c);
-	return 0;
-
-      eof:
-      case -1:
-        yyerror("Invalid escape character syntax");
-	return -1;
-
-      default:
-        tokadd('\\');
-	tokadd(c);
-    }
-    return 0;
-}
-
-static int
-parser_regx_options(struct parser_params *parser)
-{
-    int options = 0;
-    int c, opt;
-
-    newtok();
-    while (c = nextc(), ISALPHA(c)) {
-        if (c == 'o') {
-            options |= RE_OPTION_ONCE;
-        }
-	else if (rb_char_to_icu_option(c, &opt)) {
-            options |= opt;
-        }
-        else {
-	    tokadd(c);
-        }
-    }
-    pushback(c);
-    if (toklen()) {
-	tokfix();
-	compile_error(PARSER_ARG "unknown regexp option%s - %s",
-		      toklen() > 1 ? "s" : "", tok());
-    }
-    return options;
-}
-
-static void
-dispose_string(VALUE str)
-{
-    /* TODO: should use another API? */
-    rb_gc_force_recycle(str);
-}
-
-static int
-parser_tokadd_mbchar(struct parser_params *parser, int c)
-{
-#if WITH_OBJC
-    int len = 1;
-#else
-    int len = parser_precise_mbclen();
-    if (!MBCLEN_CHARFOUND_P(len)) {
-	compile_error(PARSER_ARG "invalid multibyte char");
-	return -1;
-    }
-#endif
-    tokadd(c);
-    lex_p += --len;
-    if (len > 0) tokcopy(len);
-    return c;
-}
-
-#define tokadd_mbchar(c) parser_tokadd_mbchar(parser, c)
-
-static int
-parser_tokadd_string(struct parser_params *parser,
-		     int func, int term, int paren, long *nest,
-		     rb_encoding **encp)
-{
-    int c;
-    int has_nonascii = 0;
-    rb_encoding *enc = *encp;
-
-#if 1
-# define mixed_error(enc1, enc2) yyerror("mixed error")
-# define mixed_escape(beg, enc1, enc2) \
-    do { \
-	const char *pos = lex_p; \
-	lex_p = beg; \
-	mixed_error(enc1, enc2); \
-	lex_p = pos; \
-    } \
-    while (0)
-#else
-    char *errbuf = 0;
-    static const char mixed_msg[] = "%s mixed within %s source";
-
-#define mixed_error(enc1, enc2) if (!errbuf) {	\
-	int len = sizeof(mixed_msg) - 4;	\
-	len += strlen(rb_enc_name(enc1));	\
-	len += strlen(rb_enc_name(enc2));	\
-	errbuf = ALLOCA_N(char, len);		\
-	snprintf(errbuf, len, mixed_msg,	\
-		 rb_enc_name(enc1),		\
-		 rb_enc_name(enc2));		\
-	yyerror(errbuf);			\
-    }
-#define mixed_escape(beg, enc1, enc2) do {	\
-	const char *pos = lex_p;		\
-	lex_p = beg;				\
-	mixed_error(enc1, enc2);		\
-	lex_p = pos;				\
-    } while (0)
-#endif
-
-    while ((c = nextc()) != -1) {
-	if (paren && c == paren) {
-	    ++*nest;
-	}
-	else if (c == term) {
-	    if (!nest || !*nest) {
-		pushback(c);
-		break;
-	    }
-	    --*nest;
-	}
-	else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
-	    int c2 = *lex_p;
-	    if (c2 == '$' || c2 == '@' || c2 == '{') {
-		pushback(c);
-		break;
-	    }
-	}
-	else if (c == '\\') {
-#if 0
-	    const char *beg = lex_p - 1;
-#endif
-	    c = nextc();
-	    switch (c) {
-	      case '\n':
-		if (func & STR_FUNC_QWORDS) break;
-		if (func & STR_FUNC_EXPAND) continue;
-		tokadd('\\');
-		break;
-
-	      case '\\':
-		if (func & STR_FUNC_ESCAPE) tokadd(c);
-		break;
-
-	      case 'u':
-		if ((func & STR_FUNC_EXPAND) == 0) {
-		    tokadd('\\');
-		    break;
-		}
-		parser_tokadd_utf8(parser, &enc, 1,
-				   func & STR_FUNC_SYMBOL,
-                                   func & STR_FUNC_REGEXP);
-#if 0
-		if (has_nonascii && enc != *encp) {
-		    mixed_escape(beg, enc, *encp);
-		}
-#endif
-		continue;
-
-	      default:
-		if (func & STR_FUNC_REGEXP) {
-		    pushback(c);
-		    if ((c = tokadd_escape(&enc)) < 0)
-			return -1;
-#if 0
-		    if (has_nonascii && enc != *encp) {
-			mixed_escape(beg, enc, *encp);
-		    }
-#endif
-		    continue;
-		}
-		else if (func & STR_FUNC_EXPAND) {
-		    pushback(c);
-		    if (func & STR_FUNC_ESCAPE) tokadd('\\');
-		    c = read_escape(0, &enc);
-		}
-		else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
-		    /* ignore backslashed spaces in %w */
-		}
-		else if (c != term && !(paren && c == paren)) {
-		    tokadd('\\');
-		}
-	    }
-	}
-	else if (!parser_isascii()) {
-	    has_nonascii = 1;
-#if 0
-	    if (enc != *encp) {
-		mixed_error(enc, *encp);
-		continue;
-	    }
-#endif
-	    if (tokadd_mbchar(c) == -1) return -1;
-	    continue;
-	}
-	else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
-	    pushback(c);
-	    break;
-	}
-	if (!c && (func & STR_FUNC_SYMBOL)) {
-	    func &= ~STR_FUNC_SYMBOL;
-	    compile_error(PARSER_ARG "symbol cannot contain '\\0'");
-	    continue;
-	}
-        if (c & 0x80) {
-            has_nonascii = 1;
-#if 0
-	    if (enc != *encp) {
-		mixed_error(enc, *encp);
-		continue;
-	    }
-#endif
-        }
-	tokadd(c);
-    }
-    *encp = enc;
-    return c;
-}
-
-#define NEW_STRTERM(func, term, paren) \
-	rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
-
-static int
-parser_parse_string(struct parser_params *parser, NODE *quote)
-{
-    int func = quote->nd_func;
-    int term = nd_term(quote);
-    int paren = nd_paren(quote);
-    int c, space = 0;
-    rb_encoding *enc = parser->enc;
-
-    if (func == -1) return tSTRING_END;
-    c = nextc();
-    if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
-	do {c = nextc();} while (ISSPACE(c));
-	space = 1;
-    }
-    if (c == term && !quote->nd_nest) {
-	if (func & STR_FUNC_QWORDS) {
-	    quote->nd_func = -1;
-	    return ' ';
-	}
-	if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
-        set_yylval_num(regx_options());
-	return tREGEXP_END;
-    }
-    if (space) {
-	pushback(c);
-	return ' ';
-    }
-    newtok();
-    if ((func & STR_FUNC_EXPAND) && c == '#') {
-	switch (c = nextc()) {
-	  case '$':
-	  case '@':
-	    pushback(c);
-	    return tSTRING_DVAR;
-	  case '{':
-	    return tSTRING_DBEG;
-	}
-	tokadd('#');
-    }
-    pushback(c);
-    if (tokadd_string(func, term, paren, &quote->nd_nest,
-		      &enc) == -1) {
-	ruby_sourceline = nd_line(quote);
-	if (func & STR_FUNC_REGEXP) {
-	    if (parser->eofp)
-		compile_error(PARSER_ARG "unterminated regexp meets end of file");
-	    return tREGEXP_END;
-	}
-	else {
-	    if (parser->eofp)
-		compile_error(PARSER_ARG "unterminated string meets end of file");
-	    return tSTRING_END;
-	}
-    }
-
-    tokfix();
-    set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
-    return tSTRING_CONTENT;
-}
-
-static int
-parser_heredoc_identifier(struct parser_params *parser)
-{
-    int c = nextc(), term, func = 0, len;
-
-    if (c == '-') {
-	c = nextc();
-	func = STR_FUNC_INDENT;
-    }
-    switch (c) {
-      case '\'':
-	func |= str_squote; goto quoted;
-      case '"':
-	func |= str_dquote; goto quoted;
-      case '`':
-	func |= str_xquote;
-      quoted:
-	newtok();
-	tokadd(func);
-	term = c;
-	while ((c = nextc()) != -1 && c != term) {
-	    if (tokadd_mbchar(c) == -1) return 0;
-	}
-	if (c == -1) {
-	    compile_error(PARSER_ARG "unterminated here document identifier");
-	    return 0;
-	}
-	break;
-
-      default:
-	if (!parser_is_identchar()) {
-	    pushback(c);
-	    if (func & STR_FUNC_INDENT) {
-		pushback('-');
-	    }
-	    return 0;
-	}
-	newtok();
-	term = '"';
-	tokadd(func |= str_dquote);
-	do {
-	    if (tokadd_mbchar(c) == -1) return 0;
-	} while ((c = nextc()) != -1 && parser_is_identchar());
-	pushback(c);
-	break;
-    }
-
-    tokfix();
-#ifdef RIPPER
-    ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
-#endif
-    len = lex_p - lex_pbeg;
-    lex_goto_eol(parser);
-    GC_WB(&lex_strterm, rb_node_newnode(NODE_HEREDOC,
-		STR_NEW(tok(), toklen()),	/* nd_lit */
-		len,				/* nd_nth */
-		lex_lastline));		/* nd_orig */
-    nd_set_line(lex_strterm, ruby_sourceline);
-#ifdef RIPPER
-    ripper_flush(parser);
-#endif
-    return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
-}
-
-static void
-parser_heredoc_restore(struct parser_params *parser, NODE *here)
-{
-    VALUE line;
-
-#ifdef RIPPER
-    if (!NIL_P(parser->delayed))
-	ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
-    lex_goto_eol(parser);
-    ripper_dispatch_scan_event(parser, tHEREDOC_END);
-#endif
-    line = here->nd_orig;
-    GC_WB(&lex_lastline, line);
-    lex_pbeg = RSTRING_PTR(line);
-    lex_pend = lex_pbeg + RSTRING_LEN(line);
-    lex_p = lex_pbeg + here->nd_nth;
-    heredoc_end = ruby_sourceline;
-    ruby_sourceline = nd_line(here);
-    dispose_string(here->nd_lit);
-    rb_gc_force_recycle((VALUE)here);
-#ifdef RIPPER
-    ripper_flush(parser);
-#endif
-}
-
-static int
-parser_whole_match_p(struct parser_params *parser,
-    const char *eos, int len, int indent)
-{
-    const char *p = lex_pbeg;
-    int n;
-
-    if (indent) {
-	while (*p && ISSPACE(*p)) p++;
-    }
-    n= lex_pend - (p + len);
-    if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return Qfalse;
-    if (strncmp(eos, p, len) == 0) return Qtrue;
-    return Qfalse;
-}
-
-static int
-parser_here_document(struct parser_params *parser, NODE *here)
-{
-    int c, func, indent = 0;
-    const char *eos, *p, *pend;
-    long len;
-    VALUE str = 0;
-
-    eos = RSTRING_PTR(here->nd_lit);
-    len = RSTRING_LEN(here->nd_lit) - 1;
-    indent = (func = *eos++) & STR_FUNC_INDENT;
-
-    if ((c = nextc()) == -1) {
-      error:
-	compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
-      restore:
-	heredoc_restore(lex_strterm);
-	lex_strterm = 0;
-	return 0;
-    }
-    if (was_bol() && whole_match_p(eos, len, indent)) {
-	heredoc_restore(lex_strterm);
-	return tSTRING_END;
-    }
-
-    if (!(func & STR_FUNC_EXPAND)) {
-	do {
-	    p = RSTRING_PTR(lex_lastline);
-	    pend = lex_pend;
-	    if (pend > p) {
-		switch (pend[-1]) {
-		  case '\n':
-		    if (--pend == p || pend[-1] != '\r') {
-			pend++;
-			break;
-		    }
-		  case '\r':
-		    --pend;
-		}
-	    }
-	    if (str)
-		rb_str_cat(str, p, pend - p);
-	    else
-		str = STR_NEW(p, pend - p);
-	    if (pend < lex_pend) rb_str_cat(str, "\n", 1);
-	    lex_goto_eol(parser);
-	    if (nextc() == -1) {
-		if (str) dispose_string(str);
-		goto error;
-	    }
-	} while (!whole_match_p(eos, len, indent));
-    }
-    else {
-	/*	int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
-	rb_encoding *enc = parser->enc;
-	newtok();
-	if (c == '#') {
-	    switch (c = nextc()) {
-	      case '$':
-	      case '@':
-		pushback(c);
-		return tSTRING_DVAR;
-	      case '{':
-		return tSTRING_DBEG;
-	    }
-	    tokadd('#');
-	}
-	do {
-	    pushback(c);
-	    if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) {
-		if (parser->eofp) goto error;
-		goto restore;
-	    }
-	    if (c != '\n') {
-		set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
-		return tSTRING_CONTENT;
-	    }
-	    tokadd(nextc());
-	    /*	    if (mbp && mb == ENC_CODERANGE_UNKNOWN) mbp = 0;*/
-	    if ((c = nextc()) == -1) goto error;
-	} while (!whole_match_p(eos, len, indent));
-	str = STR_NEW3(tok(), toklen(), enc, func);
-    }
-    heredoc_restore(lex_strterm);
-    GC_WB(&lex_strterm, NEW_STRTERM(-1, 0, 0));
-    set_yylval_str(str);
-    return tSTRING_CONTENT;
-}
-
-#include "lex.c"
-
-#ifndef RIPPER
-static void
-arg_ambiguous_gen(struct parser_params *parser)
-{
-    rb_warning0("ambiguous first argument; put parentheses or even spaces");
-}
-#else
-static void
-arg_ambiguous_gen(struct parser_params *parser)
-{
-    dispatch0(arg_ambiguous);
-}
-#endif
-#define arg_ambiguous() arg_ambiguous_gen(parser)
-
-static int
-lvar_defined_gen(struct parser_params *parser, ID id)
-{
-#ifndef RIPPER
-    return (dyna_in_block() && dvar_defined(id)) || local_id(id);
-#else
-    return 0;
-#endif
-}
-
-/* emacsen -*- hack */
-static int
-parser_encode_length(struct parser_params *parser, const char *name, int len)
-{
-#if 0
-    int nlen;
-
-    if (len > 5 && name[nlen = len - 5] == '-') {
-	if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0)
-	    return nlen;
-    }
-    if (len > 4 && name[nlen = len - 5] == '-') {
-	if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0)
-	    return nlen;
-	if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0)
-	    return nlen;
-    }
-#endif
-    return len;
-}
-
-static void
-parser_set_encode(struct parser_params *parser, const char *name)
-{
-    rb_encoding *enc;
-#if WITH_OBJC
-    enc = rb_enc_find(name);
-    if (enc == NULL) {
-	// XXX we currently don't support this functionality, so let's not
-	// raise any exception for now.
-	// (this seems to be triggered if the encoding is 'binary').
-	//rb_raise(rb_eArgError, "unknown encoding name: %s", name);
-	enc = rb_locale_encoding();
-    }
-    /* TODO should raise if the encoding is not ASCII compatible */
-#else
-    int idx = rb_enc_find_index(name);
-
-    if (idx < 0) {
-	rb_raise(rb_eArgError, "unknown encoding name: %s", name);
-    }
-    enc = rb_enc_from_index(idx);
-    if (!rb_enc_asciicompat(enc)) {
-	rb_raise(rb_eArgError, "%s is not ASCII compatible", rb_enc_name(enc));
-    }
-#endif
-    parser->enc = enc;
-}
-
-#ifndef RIPPER
-typedef int (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, int len);
-typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
-
-static void
-magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
-{
-    if (parser && parser->line_count != (parser->has_shebang ? 2 : 1))
-	return;
-    parser_set_encode(parser, val);
-}
-
-struct magic_comment {
-    const char *name;
-    rb_magic_comment_setter_t func;
-    rb_magic_comment_length_t length;
-};
-
-static const struct magic_comment magic_comments[] = {
-    {"coding", magic_comment_encoding, parser_encode_length},
-    {"encoding", magic_comment_encoding, parser_encode_length},
-};
-#endif
-
-static const char *
-magic_comment_marker(const char *str, int len)
-{
-    int i = 2;
-
-    while (i < len) {
-	switch (str[i]) {
-	  case '-':
-	    if (str[i-1] == '*' && str[i-2] == '-') {
-		return str + i + 1;
-	    }
-	    i += 2;
-	    break;
-	  case '*':
-	    if (i + 1 >= len) return 0;
-	    if (str[i+1] != '-') {
-		i += 4;
-	    }
-	    else if (str[i-1] != '-') {
-		i += 2;
-	    }
-	    else {
-		return str + i + 2;
-	    }
-	    break;
-	  default:
-	    i += 3;
-	    break;
-	}
-    }
-    return 0;
-}
-
-static int
-parser_magic_comment(struct parser_params *parser, const char *str, int len)
-{
-    VALUE name = 0, val = 0;
-    const char *beg, *end, *vbeg, *vend;
-
-    if (len <= 7) return Qfalse;
-    if (!(beg = magic_comment_marker(str, len))) return Qfalse;
-    if (!(end = magic_comment_marker(beg, str + len - beg))) return Qfalse;
-    str = beg;
-    len = end - beg - 3;
-
-    /* %r"([^\\s\'\":;]+)\\s*:\\s*(\"(?:\\\\.|[^\"])*\"|[^\"\\s;]+)[\\s;]*" */
-    while (len > 0) {
-#ifndef RIPPER
-	const struct magic_comment *p = magic_comments;
-#endif
-	int n = 0;
-
-	for (; len > 0 && *str; str++, --len) {
-	    switch (*str) {
-	      case '\'': case '"': case ':': case ';':
-		continue;
-	    }
-	    if (!ISSPACE(*str)) break;
-	}
-	for (beg = str; len > 0; str++, --len) {
-	    switch (*str) {
-	      case '\'': case '"': case ':': case ';':
-		break;
-	      default:
-		if (ISSPACE(*str)) break;
-		continue;
-	    }
-	    break;
-	}
-	for (end = str; len > 0 && ISSPACE(*str); str++, --len);
-	if (!len) break;
-	if (*str != ':') continue;
-
-	do str++; while (--len > 0 && ISSPACE(*str));
-	if (!len) break;
-	if (*str == '"') {
-	    for (vbeg = ++str; --len > 0 && *str != '"'; str++) {
-		if (*str == '\\') {
-		    --len;
-		    ++str;
-		}
-	    }
-	    vend = str;
-	    if (len) {
-		--len;
-		++str;
-	    }
-	}
-	else {
-	    for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++);
-	    vend = str;
-	}
-	while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++;
-
-	n = end - beg;
-	name = STR_NEW(beg, n);
-#ifndef RIPPER
-	do {
-	    if (STRNCASECMP(p->name, RSTRING_PTR(name), n) == 0) {
-		n = vend - vbeg;
-		if (p->length) {
-		    n = (*p->length)(parser, vbeg, n);
-		}
-		val = STR_NEW(vbeg, n); 
-		(*p->func)(parser, RSTRING_PTR(name), RSTRING_PTR(val));
-		break;
-	    }
-	} while (++p < magic_comments + sizeof(magic_comments) / sizeof(*p));
-#else
-	dispatch2(magic_comment, name, val);
-#endif
-    }
-
-    return Qtrue;
-}
-
-static void
-set_file_encoding(struct parser_params *parser, const char *str, const char *send)
-{
-    int sep = 0;
-    const char *beg = str;
-    VALUE s;
-
-    for (;;) {
-	if (send - str <= 6) return;
-	switch (str[6]) {
-	  case 'C': case 'c': str += 6; continue;
-	  case 'O': case 'o': str += 5; continue;
-	  case 'D': case 'd': str += 4; continue;
-	  case 'I': case 'i': str += 3; continue;
-	  case 'N': case 'n': str += 2; continue;
-	  case 'G': case 'g': str += 1; continue;
-	  case '=': case ':':
-	    sep = 1;
-	    str += 6;
-	    break;
-	  default:
-	    str += 6;
-	    if (ISSPACE(*str)) break;
-	    continue;
-	}
-	if (STRNCASECMP(str-6, "coding", 6) == 0) break;
-    }
-    for (;;) {
-	do {
-	    if (++str >= send) return;
-	} while (ISSPACE(*str));
-	if (sep) break;
-	if (*str != '=' && *str != ':') return;
-	sep = 1;
-	str++;
-    }
-    beg = str;
-    while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send);
-    s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg));
-    parser_set_encode(parser, RSTRING_PTR(s));
-    rb_str_resize(s, 0);
-}
-
-static void
-parser_prepare(struct parser_params *parser)
-{
-    int c = nextc();
-    switch (c) {
-      case '#':
-	if (peek('!')) parser->has_shebang = 1;
-	break;
-      case 0xef:		/* UTF-8 BOM marker */
-	if (lex_pend - lex_p >= 2 &&
-	    (unsigned char)lex_p[0] == 0xbb &&
-	    (unsigned char)lex_p[1] == 0xbf) {
-	    parser_set_encode(parser, "UTF-8");
-	    lex_p += 2;
-	    lex_pbeg = lex_p;
-	    return;
-	}
-	break;
-      case EOF:
-	return;
-    }
-    pushback(c);
-    parser->enc = rb_enc_get(lex_lastline);
-    if (parser->enc == NULL)
-#if WITH_OBJC
-	parser->enc = rb_locale_encoding();
-#else
-	parser->enc = rb_utf8_encoding();
-#endif
-}
-
-#define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
-#define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS)
-
-static int
-parser_yylex(struct parser_params *parser)
-{
-    register int c;
-    int space_seen = 0;
-    int cmd_state;
-    enum lex_state_e last_state;
-    rb_encoding *enc;
-#if !WITH_OBJC
-    int mb;
-#endif
-#ifdef RIPPER
-    int fallthru = Qfalse;
-#endif
-
-    if (lex_strterm) {
-	int token;
-	if (nd_type(lex_strterm) == NODE_HEREDOC) {
-	    token = here_document(lex_strterm);
-	    if (token == tSTRING_END) {
-		lex_strterm = 0;
-		lex_state = EXPR_ENDARG;
-	    }
-	}
-	else {
-	    token = parse_string(lex_strterm);
-	    if (token == tSTRING_END || token == tREGEXP_END) {
-		rb_gc_force_recycle((VALUE)lex_strterm);
-		lex_strterm = 0;
-		lex_state = EXPR_ENDARG;
-	    }
-	}
-	return token;
-    }
-    cmd_state = command_start;
-    command_start = Qfalse;
-  retry:
-    switch (c = nextc()) {
-      case '\0':		/* NUL */
-      case '\004':		/* ^D */
-      case '\032':		/* ^Z */
-      case -1:			/* end of script. */
-	return 0;
-
-	/* white spaces */
-      case ' ': case '\t': case '\f': case '\r':
-      case '\13': /* '\v' */
-	space_seen++;
-#ifdef RIPPER
-	while ((c = nextc())) {
-	    switch (c) {
-	      case ' ': case '\t': case '\f': case '\r':
-	      case '\13': /* '\v' */
-		break;
-	      default:
-		goto outofloop;
-	    }
-	}
-      outofloop:
-	pushback(c);
-	ripper_dispatch_scan_event(parser, tSP);
-#endif
-	goto retry;
-
-      case '#':		/* it's a comment */
-	if (!parser->has_shebang || parser->line_count != 1) {
-	    /* no magic_comment in shebang line */
-	    if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
-		if (parser->line_count == (parser->has_shebang ? 2 : 1)) {
-		    set_file_encoding(parser, lex_p, lex_pend);
-		}
-	    }
-	}
-	lex_p = lex_pend;
-#ifdef RIPPER
-        ripper_dispatch_scan_event(parser, tCOMMENT);
-        fallthru = Qtrue;
-#endif
-	/* fall through */
-      case '\n':
-	switch (lex_state) {
-	  case EXPR_BEG:
-	  case EXPR_FNAME:
-	  case EXPR_DOT:
-	  case EXPR_CLASS:
-	  case EXPR_VALUE:
-#ifdef RIPPER
-            if (!fallthru) {
-                ripper_dispatch_scan_event(parser, tIGNORED_NL);
-            }
-            fallthru = Qfalse;
-#endif
-	    goto retry;
-	  default:
-	    break;
-	}
-	while ((c = nextc())) {
-	    switch (c) {
-	      case ' ': case '\t': case '\f': case '\r':
-	      case '\13': /* '\v' */
-		space_seen++;
-		break;
-	      case '.': {
-		  if ((c = nextc()) != '.') {
-		      pushback(c);
-		      pushback('.');
-		      goto retry;
-		  }
-	      }
-	      default:
-		--ruby_sourceline;
-		GC_WB(&lex_nextline, lex_lastline);
-	      case -1:		/* EOF no decrement*/
-		lex_goto_eol(parser);
-#ifdef RIPPER
-		if (c != -1) {
-		    parser->tokp = lex_p;
-		}
-#endif
-		goto normal_newline;
-	    }
-	}
-      normal_newline:
-	command_start = Qtrue;
-	lex_state = EXPR_BEG;
-	return '\n';
-
-      case '*':
-	if ((c = nextc()) == '*') {
-	    if ((c = nextc()) == '=') {
-                set_yylval_id(tPOW);
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    c = tPOW;
-	}
-	else {
-	    if (c == '=') {
-                set_yylval_id('*');
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    if (IS_ARG() && space_seen && !ISSPACE(c)) {
-		rb_warning0("`*' interpreted as argument prefix");
-		c = tSTAR;
-	    }
-	    else if (IS_BEG()) {
-		c = tSTAR;
-	    }
-	    else {
-		c = '*';
-	    }
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	return c;
-
-      case '!':
-	c = nextc();
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    lex_state = EXPR_ARG;
-	    if (c == '@') {
-		return '!';
-	    }
-	}
-	else {
-	    lex_state = EXPR_BEG;
-	}
-	if (c == '=') {
-	    return tNEQ;
-	}
-	if (c == '~') {
-	    return tNMATCH;
-	}
-	pushback(c);
-	return '!';
-
-      case '=':
-	if (was_bol()) {
-	    /* skip embedded rd document */
-	    if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
-#ifdef RIPPER
-                int first_p = Qtrue;
-
-                lex_goto_eol(parser);
-                ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
-#endif
-		for (;;) {
-		    lex_goto_eol(parser);
-#ifdef RIPPER
-                    if (!first_p) {
-                        ripper_dispatch_scan_event(parser, tEMBDOC);
-                    }
-                    first_p = Qfalse;
-#endif
-		    c = nextc();
-		    if (c == -1) {
-			compile_error(PARSER_ARG "embedded document meets end of file");
-			return 0;
-		    }
-		    if (c != '=') continue;
-		    if (strncmp(lex_p, "end", 3) == 0 &&
-			(lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
-			break;
-		    }
-		}
-		lex_goto_eol(parser);
-#ifdef RIPPER
-                ripper_dispatch_scan_event(parser, tEMBDOC_END);
-#endif
-		goto retry;
-	    }
-	}
-
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	if ((c = nextc()) == '=') {
-	    if ((c = nextc()) == '=') {
-		return tEQQ;
-	    }
-	    pushback(c);
-	    return tEQ;
-	}
-	if (c == '~') {
-	    return tMATCH;
-	}
-	else if (c == '>') {
-	    return tASSOC;
-	}
-	pushback(c);
-	return '=';
-
-      case '<':
-	c = nextc();
-	if (c == '<' &&
-	    lex_state != EXPR_END &&
-	    lex_state != EXPR_DOT &&
-	    lex_state != EXPR_ENDARG &&
-	    lex_state != EXPR_CLASS &&
-	    (!IS_ARG() || space_seen)) {
-	    int token = heredoc_identifier();
-	    if (token) return token;
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	if (c == '=') {
-	    if ((c = nextc()) == '>') {
-		return tCMP;
-	    }
-	    pushback(c);
-	    return tLEQ;
-	}
-	if (c == '<') {
-	    if ((c = nextc()) == '=') {
-                set_yylval_id(tLSHFT);
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    return tLSHFT;
-	}
-	pushback(c);
-	return '<';
-
-      case '>':
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	if ((c = nextc()) == '=') {
-	    return tGEQ;
-	}
-	if (c == '>') {
-	    if ((c = nextc()) == '=') {
-                set_yylval_id(tRSHFT);
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    return tRSHFT;
-	}
-	pushback(c);
-	return '>';
-
-      case '"':
-	GC_WB(&lex_strterm, NEW_STRTERM(str_dquote, '"', 0));
-	return tSTRING_BEG;
-
-      case '`':
-	if (lex_state == EXPR_FNAME) {
-	    lex_state = EXPR_END;
-	    return c;
-	}
-	if (lex_state == EXPR_DOT) {
-	    if (cmd_state)
-		lex_state = EXPR_CMDARG;
-	    else
-		lex_state = EXPR_ARG;
-	    return c;
-	}
-	GC_WB(&lex_strterm, NEW_STRTERM(str_xquote, '`', 0));
-	return tXSTRING_BEG;
-
-      case '\'':
-	GC_WB(&lex_strterm, NEW_STRTERM(str_squote, '\'', 0));
-	return tSTRING_BEG;
-
-      case '?':
-	if (lex_state == EXPR_END ||
-	    lex_state == EXPR_ENDARG) {
-	    lex_state = EXPR_VALUE;
-	    return '?';
-	}
-	c = nextc();
-	if (c == -1) {
-	    compile_error(PARSER_ARG "incomplete character syntax");
-	    return 0;
-	}
-	if (rb_enc_isspace(c, parser->enc)) {
-	    if (!IS_ARG()) {
-		int c2 = 0;
-		switch (c) {
-		  case ' ':
-		    c2 = 's';
-		    break;
-		  case '\n':
-		    c2 = 'n';
-		    break;
-		  case '\t':
-		    c2 = 't';
-		    break;
-		  case '\v':
-		    c2 = 'v';
-		    break;
-		  case '\r':
-		    c2 = 'r';
-		    break;
-		  case '\f':
-		    c2 = 'f';
-		    break;
-		}
-		if (c2) {
-		    rb_warnI("invalid character syntax; use ?\\%c", c2);
-		}
-	    }
-	  ternary:
-	    pushback(c);
-	    lex_state = EXPR_VALUE;
-	    return '?';
-	}
-	newtok();
-	enc = parser->enc;
-	if (!parser_isascii()) {
-	    if (tokadd_mbchar(c) == -1) return 0;
-	}
-	else if ((rb_enc_isalnum(c, parser->enc) || c == '_') &&
-		 lex_p < lex_pend && is_identchar(lex_p, lex_pend, parser->enc)) {
-	    goto ternary;
-	}
-        else if (c == '\\') {
-            if (peek('u')) {
-                nextc();
-                c = parser_tokadd_utf8(parser, &enc, 0, 0, 0);
-                if (0x80 <= c) {
-                    tokaddmbc(c, enc);
-                }
-                else {
-                    tokadd(c);
-                }
-            }
-            else {
-                c = read_escape(0, &enc);
-                tokadd(c);
-            }
-        }
-        else {
-	    tokadd(c);
-        }
-	tokfix();
-	set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0));
-	lex_state = EXPR_ENDARG;
-	return tCHAR;
-
-      case '&':
-	if ((c = nextc()) == '&') {
-	    lex_state = EXPR_BEG;
-	    if ((c = nextc()) == '=') {
-                set_yylval_id(tANDOP);
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    return tANDOP;
-	}
-	else if (c == '=') {
-            set_yylval_id('&');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	pushback(c);
-	if (IS_ARG() && space_seen && !ISSPACE(c)) {
-	    rb_warning0("`&' interpreted as argument prefix");
-	    c = tAMPER;
-	}
-	else if (IS_BEG()) {
-	    c = tAMPER;
-	}
-	else {
-	    c = '&';
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG;
-	}
-	return c;
-
-      case '|':
-	if ((c = nextc()) == '|') {
-	    lex_state = EXPR_BEG;
-	    if ((c = nextc()) == '=') {
-                set_yylval_id(tOROP);
-		lex_state = EXPR_BEG;
-		return tOP_ASGN;
-	    }
-	    pushback(c);
-	    return tOROP;
-	}
-	if (c == '=') {
-            set_yylval_id('|');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    lex_state = EXPR_ARG;
-	}
-	else {
-	    lex_state = EXPR_BEG;
-	}
-	pushback(c);
-	return '|';
-
-      case '+':
-	c = nextc();
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    lex_state = EXPR_ARG;
-	    if (c == '@') {
-		return tUPLUS;
-	    }
-	    pushback(c);
-	    return '+';
-	}
-	if (c == '=') {
-            set_yylval_id('+');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	if (IS_BEG() ||
-	    (IS_ARG() && space_seen && !ISSPACE(c))) {
-	    if (IS_ARG()) arg_ambiguous();
-	    lex_state = EXPR_BEG;
-	    pushback(c);
-	    if (ISDIGIT(c)) {
-		c = '+';
-		goto start_num;
-	    }
-	    return tUPLUS;
-	}
-	lex_state = EXPR_BEG;
-	pushback(c);
-	return '+';
-
-      case '-':
-	c = nextc();
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    lex_state = EXPR_ARG;
-	    if (c == '@') {
-		return tUMINUS;
-	    }
-	    pushback(c);
-	    return '-';
-	}
-	if (c == '=') {
-            set_yylval_id('-');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	if (c == '>') {
-	    lex_state = EXPR_ARG;
-	    return tLAMBDA;
-	}
-	if (IS_BEG() ||
-	    (IS_ARG() && space_seen && !ISSPACE(c))) {
-	    if (IS_ARG()) arg_ambiguous();
-	    lex_state = EXPR_BEG;
-	    pushback(c);
-	    if (ISDIGIT(c)) {
-		return tUMINUS_NUM;
-	    }
-	    return tUMINUS;
-	}
-	lex_state = EXPR_BEG;
-	pushback(c);
-	return '-';
-
-      case '.':
-	lex_state = EXPR_BEG;
-	if ((c = nextc()) == '.') {
-	    if ((c = nextc()) == '.') {
-		return tDOT3;
-	    }
-	    pushback(c);
-	    return tDOT2;
-	}
-	pushback(c);
-	if (ISDIGIT(c)) {
-	    yyerror("no .<digit> floating literal anymore; put 0 before dot");
-	}
-	lex_state = EXPR_DOT;
-	return '.';
-
-      start_num:
-      case '0': case '1': case '2': case '3': case '4':
-      case '5': case '6': case '7': case '8': case '9':
-	{
-	    int is_float, seen_point, seen_e, nondigit;
-
-	    is_float = seen_point = seen_e = nondigit = 0;
-	    lex_state = EXPR_ENDARG;
-	    newtok();
-	    if (c == '-' || c == '+') {
-		tokadd(c);
-		c = nextc();
-	    }
-	    if (c == '0') {
-		int start = toklen();
-		c = nextc();
-		if (c == 'x' || c == 'X') {
-		    /* hexadecimal */
-		    c = nextc();
-		    if (ISXDIGIT(c)) {
-			do {
-			    if (c == '_') {
-				if (nondigit) break;
-				nondigit = c;
-				continue;
-			    }
-			    if (!ISXDIGIT(c)) break;
-			    nondigit = 0;
-			    tokadd(c);
-			} while ((c = nextc()) != -1);
-		    }
-		    pushback(c);
-		    tokfix();
-		    if (toklen() == start) {
-			yyerror("numeric literal without digits");
-		    }
-		    else if (nondigit) goto trailing_uc;
-                    set_yylval_literal(rb_cstr_to_inum(tok(), 16, Qfalse));
-		    return tINTEGER;
-		}
-		if (c == 'b' || c == 'B') {
-		    /* binary */
-		    c = nextc();
-		    if (c == '0' || c == '1') {
-			do {
-			    if (c == '_') {
-				if (nondigit) break;
-				nondigit = c;
-				continue;
-			    }
-			    if (c != '0' && c != '1') break;
-			    nondigit = 0;
-			    tokadd(c);
-			} while ((c = nextc()) != -1);
-		    }
-		    pushback(c);
-		    tokfix();
-		    if (toklen() == start) {
-			yyerror("numeric literal without digits");
-		    }
-		    else if (nondigit) goto trailing_uc;
-                    set_yylval_literal(rb_cstr_to_inum(tok(), 2, Qfalse));
-		    return tINTEGER;
-		}
-		if (c == 'd' || c == 'D') {
-		    /* decimal */
-		    c = nextc();
-		    if (ISDIGIT(c)) {
-			do {
-			    if (c == '_') {
-				if (nondigit) break;
-				nondigit = c;
-				continue;
-			    }
-			    if (!ISDIGIT(c)) break;
-			    nondigit = 0;
-			    tokadd(c);
-			} while ((c = nextc()) != -1);
-		    }
-		    pushback(c);
-		    tokfix();
-		    if (toklen() == start) {
-			yyerror("numeric literal without digits");
-		    }
-		    else if (nondigit) goto trailing_uc;
-                    set_yylval_literal(rb_cstr_to_inum(tok(), 10, Qfalse));
-		    return tINTEGER;
-		}
-		if (c == '_') {
-		    /* 0_0 */
-		    goto octal_number;
-		}
-		if (c == 'o' || c == 'O') {
-		    /* prefixed octal */
-		    c = nextc();
-		    if (c == '_' || !ISDIGIT(c)) {
-			yyerror("numeric literal without digits");
-		    }
-		}
-		if (c >= '0' && c <= '7') {
-		    /* octal */
-		  octal_number:
-	            do {
-			if (c == '_') {
-			    if (nondigit) break;
-			    nondigit = c;
-			    continue;
-			}
-			if (c < '0' || c > '7') break;
-			nondigit = 0;
-			tokadd(c);
-		    } while ((c = nextc()) != -1);
-		    if (toklen() > start) {
-			pushback(c);
-			tokfix();
-			if (nondigit) goto trailing_uc;
-                        set_yylval_literal(rb_cstr_to_inum(tok(), 8, Qfalse));
-			return tINTEGER;
-		    }
-		    if (nondigit) {
-			pushback(c);
-			goto trailing_uc;
-		    }
-		}
-		if (c > '7' && c <= '9') {
-		    yyerror("Invalid octal digit");
-		}
-		else if (c == '.' || c == 'e' || c == 'E') {
-		    tokadd('0');
-		}
-		else {
-		    pushback(c);
-                    set_yylval_literal(INT2FIX(0));
-		    return tINTEGER;
-		}
-	    }
-
-	    for (;;) {
-		switch (c) {
-		  case '0': case '1': case '2': case '3': case '4':
-		  case '5': case '6': case '7': case '8': case '9':
-		    nondigit = 0;
-		    tokadd(c);
-		    break;
-
-		  case '.':
-		    if (nondigit) goto trailing_uc;
-		    if (seen_point || seen_e) {
-			goto decode_num;
-		    }
-		    else {
-			int c0 = nextc();
-			if (!ISDIGIT(c0)) {
-			    pushback(c0);
-			    goto decode_num;
-			}
-			c = c0;
-		    }
-		    tokadd('.');
-		    tokadd(c);
-		    is_float++;
-		    seen_point++;
-		    nondigit = 0;
-		    break;
-
-		  case 'e':
-		  case 'E':
-		    if (nondigit) {
-			pushback(c);
-			c = nondigit;
-			goto decode_num;
-		    }
-		    if (seen_e) {
-			goto decode_num;
-		    }
-		    tokadd(c);
-		    seen_e++;
-		    is_float++;
-		    nondigit = c;
-		    c = nextc();
-		    if (c != '-' && c != '+') continue;
-		    tokadd(c);
-		    nondigit = c;
-		    break;
-
-		  case '_':	/* `_' in number just ignored */
-		    if (nondigit) goto decode_num;
-		    nondigit = c;
-		    break;
-
-		  default:
-		    goto decode_num;
-		}
-		c = nextc();
-	    }
-
-	  decode_num:
-	    pushback(c);
-	    tokfix();
-	    if (nondigit) {
-		char tmp[30];
-	      trailing_uc:
-		sprintf(tmp, "trailing `%c' in number", nondigit);
-		yyerror(tmp);
-	    }
-	    if (is_float) {
-		double d = ruby_strtod(tok(), 0);
-		if (errno == ERANGE) {
-		    rb_warningS("Float %s out of range", tok());
-		    errno = 0;
-		}
-                set_yylval_literal(DOUBLE2NUM(d));
-		return tFLOAT;
-	    }
-            set_yylval_literal(rb_cstr_to_inum(tok(), 10, Qfalse));
-	    return tINTEGER;
-	}
-
-      case ')':
-      case ']':
-	paren_nest--;
-      case '}':
-	COND_LEXPOP();
-	CMDARG_LEXPOP();
-	if (c == ')')
-	    lex_state = EXPR_END;
-	else
-	    lex_state = EXPR_ENDARG;
-	return c;
-
-      case ':':
-	c = nextc();
-	if (c == ':') {
-	    if (IS_BEG() ||
-		lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {
-		lex_state = EXPR_BEG;
-		return tCOLON3;
-	    }
-	    lex_state = EXPR_DOT;
-	    return tCOLON2;
-	}
-	if (lex_state == EXPR_END ||
-	    lex_state == EXPR_ENDARG || ISSPACE(c)) {
-	    pushback(c);
-	    lex_state = EXPR_BEG;
-	    return ':';
-	}
-	switch (c) {
-	  case '\'':
-	    GC_WB(&lex_strterm, NEW_STRTERM(str_ssym, c, 0));
-	    break;
-	  case '"':
-	    GC_WB(&lex_strterm, NEW_STRTERM(str_dsym, c, 0));
-	    break;
-	  default:
-	    pushback(c);
-	    break;
-	}
-	lex_state = EXPR_FNAME;
-	return tSYMBEG;
-
-      case '/':
-	if (IS_BEG()) {
-	    GC_WB(&lex_strterm, NEW_STRTERM(str_regexp, '/', 0));
-	    return tREGEXP_BEG;
-	}
-	if ((c = nextc()) == '=') {
-            set_yylval_id('/');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	pushback(c);
-	if (IS_ARG() && space_seen) {
-	    if (!ISSPACE(c)) {
-		arg_ambiguous();
-		GC_WB(&lex_strterm, NEW_STRTERM(str_regexp, '/', 0));
-		return tREGEXP_BEG;
-	    }
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	return '/';
-
-      case '^':
-	if ((c = nextc()) == '=') {
-            set_yylval_id('^');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	pushback(c);
-	return '^';
-
-      case ';':
-	lex_state = EXPR_BEG;
-	command_start = Qtrue;
-	return ';';
-
-      case ',':
-	lex_state = EXPR_BEG;
-	return ',';
-
-      case '~':
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    if ((c = nextc()) != '@') {
-		pushback(c);
-	    }
-	    lex_state = EXPR_ARG;
-	}
-	else {
-	    lex_state = EXPR_BEG;
-	}
-	return '~';
-
-      case '(':
-	if (IS_BEG()) {
-	    c = tLPAREN;
-	}
-	else if (space_seen) {
-	    if (lex_state == EXPR_CMDARG) {
-		c = tLPAREN_ARG;
-	    }
-	    else if (lex_state == EXPR_ARG) {
-		rb_warning0("don't put space before argument parentheses");
-		c = '(';
-	    }
-	}
-	paren_nest++;
-	COND_PUSH(0);
-	CMDARG_PUSH(0);
-	lex_state = EXPR_BEG;
-	return c;
-
-      case '[':
-	paren_nest++;
-	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
-	    lex_state = EXPR_ARG;
-	    if ((c = nextc()) == ']') {
-		if ((c = nextc()) == '=') {
-		    return tASET;
-		}
-		pushback(c);
-		return tAREF;
-	    }
-	    pushback(c);
-	    return '[';
-	}
-	else if (IS_BEG()) {
-	    c = tLBRACK;
-	}
-	else if (IS_ARG() && space_seen) {
-	    c = tLBRACK;
-	}
-	lex_state = EXPR_BEG;
-	COND_PUSH(0);
-	CMDARG_PUSH(0);
-	return c;
-
-      case '{':
-	if (lpar_beg && lpar_beg == paren_nest) {
-	    lex_state = EXPR_BEG;
-	    lpar_beg = 0;
-	    --paren_nest;
-	    return tLAMBEG;
-	}
-	if (IS_ARG() || lex_state == EXPR_END)
-	    c = '{';          /* block (primary) */
-	else if (lex_state == EXPR_ENDARG)
-	    c = tLBRACE_ARG;  /* block (expr) */
-	else
-	    c = tLBRACE;      /* hash */
-	COND_PUSH(0);
-	CMDARG_PUSH(0);
-	lex_state = EXPR_BEG;
-	if (c != tLBRACE) command_start = Qtrue;
-	return c;
-
-      case '\\':
-	c = nextc();
-	if (c == '\n') {
-	    space_seen = 1;
-#ifdef RIPPER
-	    ripper_dispatch_scan_event(parser, tSP);
-#endif
-	    goto retry; /* skip \\n */
-	}
-	pushback(c);
-	return '\\';
-
-      case '%':
-	if (IS_BEG()) {
-	    int term;
-	    int paren;
-
-	    c = nextc();
-	  quotation:
-	    if (!ISALNUM(c)) {
-		term = c;
-		c = 'Q';
-	    }
-	    else {
-		term = nextc();
-		if (rb_enc_isalnum(term, parser->enc) || !parser_isascii()) {
-		    yyerror("unknown type of %string");
-		    return 0;
-		}
-	    }
-	    if (c == -1 || term == -1) {
-		compile_error(PARSER_ARG "unterminated quoted string meets end of file");
-		return 0;
-	    }
-	    paren = term;
-	    if (term == '(') term = ')';
-	    else if (term == '[') term = ']';
-	    else if (term == '{') term = '}';
-	    else if (term == '<') term = '>';
-	    else paren = 0;
-
-	    switch (c) {
-	      case 'Q':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_dquote, term, paren));
-		return tSTRING_BEG;
-
-	      case 'q':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_squote, term, paren));
-		return tSTRING_BEG;
-
-	      case 'W':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_dword, term, paren));
-		do {c = nextc();} while (ISSPACE(c));
-		pushback(c);
-		return tWORDS_BEG;
-
-	      case 'w':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_sword, term, paren));
-		do {c = nextc();} while (ISSPACE(c));
-		pushback(c);
-		return tQWORDS_BEG;
-
-	      case 'x':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_xquote, term, paren));
-		return tXSTRING_BEG;
-
-	      case 'r':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_regexp, term, paren));
-		return tREGEXP_BEG;
-
-	      case 's':
-		GC_WB(&lex_strterm, NEW_STRTERM(str_ssym, term, paren));
-		lex_state = EXPR_FNAME;
-		return tSYMBEG;
-
-	      default:
-		yyerror("unknown type of %string");
-		return 0;
-	    }
-	}
-	if ((c = nextc()) == '=') {
-            set_yylval_id('%');
-	    lex_state = EXPR_BEG;
-	    return tOP_ASGN;
-	}
-	if (IS_ARG() && space_seen && !ISSPACE(c)) {
-	    goto quotation;
-	}
-	switch (lex_state) {
-	  case EXPR_FNAME: case EXPR_DOT:
-	    lex_state = EXPR_ARG; break;
-	  default:
-	    lex_state = EXPR_BEG; break;
-	}
-	pushback(c);
-	return '%';
-
-      case '$':
-	last_state = lex_state;
-	lex_state = EXPR_ENDARG;
-	newtok();
-	c = nextc();
-	switch (c) {
-	  case '_':		/* $_: last read line string */
-	    c = nextc();
-	    if (parser_is_identchar()) {
-		tokadd('$');
-		tokadd('_');
-		break;
-	    }
-	    pushback(c);
-	    c = '_';
-	    /* fall through */
-	  case '~':		/* $~: match-data */
-	  case '*':		/* $*: argv */
-	  case '$':		/* $$: pid */
-	  case '?':		/* $?: last status */
-	  case '!':		/* $!: error string */
-	  case '@':		/* $@: error position */
-	  case '/':		/* $/: input record separator */
-	  case '\\':		/* $\: output record separator */
-	  case ';':		/* $;: field separator */
-	  case ',':		/* $,: output field separator */
-	  case '.':		/* $.: last read line number */
-	  case '=':		/* $=: ignorecase */
-	  case ':':		/* $:: load path */
-	  case '<':		/* $<: reading filename */
-	  case '>':		/* $>: default output handle */
-	  case '\"':		/* $": already loaded files */
-	    tokadd('$');
-	    tokadd(c);
-	    tokfix();
-            set_yylval_id(rb_intern(tok()));
-	    return tGVAR;
-
-	  case '-':
-	    tokadd('$');
-	    tokadd(c);
-	    c = nextc();
-	    if (parser_is_identchar()) {
-		if (tokadd_mbchar(c) == -1) return 0;
-	    }
-	    else {
-		pushback(c);
-	    }
-	  gvar:
-	    tokfix();
-            set_yylval_id(rb_intern(tok()));
-	    return tGVAR;
-
-	  case '&':		/* $&: last match */
-	  case '`':		/* $`: string before last match */
-	  case '\'':		/* $': string after last match */
-	  case '+':		/* $+: string matches last paren. */
-	    if (last_state == EXPR_FNAME) {
-		tokadd('$');
-		tokadd(c);
-		goto gvar;
-	    }
-	    set_yylval_node(NEW_BACK_REF(c));
-	    return tBACK_REF;
-
-	  case '1': case '2': case '3':
-	  case '4': case '5': case '6':
-	  case '7': case '8': case '9':
-	    tokadd('$');
-	    do {
-		tokadd(c);
-		c = nextc();
-	    } while (ISDIGIT(c));
-	    pushback(c);
-	    if (last_state == EXPR_FNAME) goto gvar;
-	    tokfix();
-	    set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
-	    return tNTH_REF;
-
-	  default:
-	    if (!parser_is_identchar()) {
-		pushback(c);
-		return '$';
-	    }
-	  case '0':
-	    tokadd('$');
-	}
-	break;
-
-      case '@':
-	c = nextc();
-	newtok();
-	tokadd('@');
-	if (c == '@') {
-	    tokadd('@');
-	    c = nextc();
-	}
-	if (ISDIGIT(c)) {
-	    if (tokidx == 1) {
-		compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
-	    }
-	    else {
-		compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
-	    }
-	    return 0;
-	}
-	if (!parser_is_identchar()) {
-	    pushback(c);
-	    return '@';
-	}
-	break;
-
-      case '_':
-	if (was_bol() && whole_match_p("__END__", 7, 0)) {
-	    ruby__end__seen = 1;
-	    parser->eofp = Qtrue;
-#ifndef RIPPER
-	    return -1;
-#else
-            lex_goto_eol(parser);
-            ripper_dispatch_scan_event(parser, k__END__);
-            return 0;
-#endif
-	}
-	newtok();
-	break;
-
-      default:
-	if (!parser_is_identchar()) {
-	    rb_compile_error(PARSER_ARG  "Invalid char `\\x%02X' in expression", c);
-	    goto retry;
-	}
-
-	newtok();
-	break;
-    }
-
-#if !WITH_OBJC
-    mb = ENC_CODERANGE_7BIT;
-#endif
-    do {
-#if !WITH_OBJC
-	if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
-#endif
-	if (tokadd_mbchar(c) == -1) return 0;
-	c = nextc();
-    } while (parser_is_identchar());
-    switch (tok()[0]) {
-      case '@': case '$':
-	pushback(c);
-	break;
-      default:
-	if ((c == '!' || c == '?') && !peek('=')) {
-	    tokadd(c);
-	}
-	else {
-	    pushback(c);
-	}
-    }
-    tokfix();
-
-    {
-	int result = 0;
-
-	last_state = lex_state;
-	switch (tok()[0]) {
-	  case '$':
-	    lex_state = EXPR_ENDARG;
-	    result = tGVAR;
-	    break;
-	  case '@':
-	    lex_state = EXPR_ENDARG;
-	    if (tok()[1] == '@')
-		result = tCVAR;
-	    else
-		result = tIVAR;
-	    break;
-
-	  default:
-	    if (toklast() == '!' || toklast() == '?') {
-		result = tFID;
-	    }
-	    else {
-		if (lex_state == EXPR_FNAME) {
-		    if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
-			(!peek('=') || (lex_p + 1 < lex_pend && lex_p[1] == '>'))) {
-			result = tIDENTIFIER;
-			tokadd(c);
-			tokfix();
-		    }
-		    else {
-			pushback(c);
-		    }
-		}
-		if (result == 0 && ISUPPER(tok()[0])) {
-		    result = tCONSTANT;
-		}
-		else {
-		    result = tIDENTIFIER;
-		}
-	    }
-
-	    if ((lex_state == EXPR_BEG && !cmd_state) ||
-		lex_state == EXPR_ARG ||
-		lex_state == EXPR_CMDARG) {
-		if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
-		    lex_state = EXPR_BEG;
-		    nextc();
-		    set_yylval_id(TOK_INTERN(!ENC_SINGLE(mb)));
-		    return tLABEL;
-		}
-	    }
-#if WITH_OBJC
-	    if (lex_state != EXPR_DOT) {
-#else
-	    if (mb == ENC_CODERANGE_7BIT && lex_state != EXPR_DOT) {
-#endif
-		const struct kwtable *kw;
-
-		/* See if it is a reserved word.  */
-		kw = rb_reserved_word(tok(), toklen());
-		if (kw) {
-		    enum lex_state_e state = lex_state;
-		    lex_state = kw->state;
-		    if (state == EXPR_FNAME) {
-                        set_yylval_id(rb_intern(kw->name));
-			return kw->id[0];
-		    }
-		    if (kw->id[0] == keyword_do) {
-			command_start = Qtrue;
-			if (lpar_beg && lpar_beg == paren_nest) {
-			    lpar_beg = 0;
-			    --paren_nest;
-			    return keyword_do_LAMBDA;
-			}
-			if (COND_P()) return keyword_do_cond;
-			if (CMDARG_P() && state != EXPR_CMDARG)
-			    return keyword_do_block;
-			if (state == EXPR_ENDARG || state == EXPR_BEG)
-			    return keyword_do_block;
-			return keyword_do;
-		    }
-		    if (state == EXPR_BEG || state == EXPR_VALUE)
-			return kw->id[0];
-		    else {
-			if (kw->id[0] != kw->id[1])
-			    lex_state = EXPR_BEG;
-			return kw->id[1];
-		    }
-		}
-	    }
-
-	    if (IS_BEG() ||
-		lex_state == EXPR_DOT ||
-		IS_ARG()) {
-		if (cmd_state) {
-		    lex_state = EXPR_CMDARG;
-		}
-		else {
-		    lex_state = EXPR_ARG;
-		}
-	    }
-	    else {
-		lex_state = EXPR_END;
-	    }
-	}
-        {
-            ID ident = TOK_INTERN(!ENC_SINGLE(mb));
-
-            set_yylval_id(ident);
-            if (last_state != EXPR_DOT && is_local_id(ident) && lvar_defined(ident)) {
-                lex_state = EXPR_END;
-            }
-        }
-	return result;
-    }
-}
-
-#if YYPURE
-static int
-yylex(void *lval, void *p)
-#else
-yylex(void *p)
-#endif
-{
-    struct parser_params *parser = (struct parser_params*)p;
-    int t;
-
-#if YYPURE
-    parser->parser_yylval = (union tmpyystype*)lval;
-    parser->parser_yylval->val = Qundef;
-#endif
-    t = parser_yylex(parser);
-#ifdef RIPPER
-    if (!NIL_P(parser->delayed)) {
-	ripper_dispatch_delayed_token(parser, t);
-	return t;
-    }
-    if (t != 0)
-	ripper_dispatch_scan_event(parser, t);
-#endif
-
-    return t;
-}
-
-#ifndef RIPPER
-static NODE*
-node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
-{
-    NODE *n = (rb_node_newnode)(type, a0, a1, a2);
-    nd_set_line(n, ruby_sourceline);
-    return n;
-}
-
-enum node_type
-nodetype(NODE *node)			/* for debug */
-{
-    return (enum node_type)nd_type(node);
-}
-
-int
-nodeline(NODE *node)
-{
-    return nd_line(node);
-}
-
-static NODE*
-newline_node(NODE *node)
-{
-    if (node) {
-	node = remove_begin(node);
-	node->flags |= NODE_FL_NEWLINE;
-    }
-    return node;
-}
-
-static void
-fixpos(NODE *node, NODE *orig)
-{
-    if (!node) return;
-    if (!orig) return;
-    if (orig == (NODE*)1) return;
-    nd_set_line(node, nd_line(orig));
-}
-
-static void
-parser_warning(struct parser_params *parser, NODE *node, const char *mesg)
-{
-    rb_compile_warning(ruby_sourcefile, nd_line(node), "%s", mesg);
-}
-#define parser_warning(node, mesg) parser_warning(parser, node, mesg)
-
-static void
-parser_warn(struct parser_params *parser, NODE *node, const char *mesg)
-{
-    rb_compile_warn(ruby_sourcefile, nd_line(node), "%s", mesg);
-}
-#define parser_warn(node, mesg) parser_warn(parser, node, mesg)
-
-static NODE*
-block_append_gen(struct parser_params *parser, NODE *head, NODE *tail)
-{
-    NODE *end, *h = head, *nd;
-
-    if (tail == 0) return head;
-
-    if (h == 0) return tail;
-    switch (nd_type(h)) {
-      case NODE_LIT:
-      case NODE_STR:
-      case NODE_SELF:
-      case NODE_TRUE:
-      case NODE_FALSE:
-      case NODE_NIL:
-	parser_warning(h, "unused literal ignored");
-	return tail;
-      default:
-	h = end = NEW_BLOCK(head);
-	GC_WB(&end->nd_end, end);
-	fixpos(end, head);
-	head = end;
-	break;
-      case NODE_BLOCK:
-	end = h->nd_end;
-	break;
-    }
-
-    nd = end->nd_head;
-    switch (nd_type(nd)) {
-      case NODE_RETURN:
-      case NODE_BREAK:
-      case NODE_NEXT:
-      case NODE_REDO:
-      case NODE_RETRY:
-	if (RTEST(ruby_verbose)) {
-	    parser_warning(nd, "statement not reached");
-	}
-	break;
-
-      default:
-	break;
-    }
-
-    if (nd_type(tail) != NODE_BLOCK) {
-	tail = NEW_BLOCK(tail);
-	GC_WB(&tail->nd_end, tail);
-    }
-    GC_WB(&end->nd_next, tail);
-    GC_WB(&h->nd_end, tail->nd_end);
-    return head;
-}
-
-/* append item to the list */
-static NODE*
-list_append_gen(struct parser_params *parser, NODE *list, NODE *item)
-{
-    NODE *last;
-
-    if (list == 0) return NEW_LIST(item);
-    if (list->nd_next) {
-	last = list->nd_next->nd_end;
-    }
-    else {
-	last = list;
-    }
-
-    list->nd_alen += 1;
-    GC_WB(&last->nd_next, NEW_LIST(item));
-    GC_WB(&list->nd_next->nd_end, last->nd_next);
-    return list;
-}
-
-/* concat two lists */
-static NODE*
-list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
-{
-    NODE *last;
-
-    if (head->nd_next) {
-	last = head->nd_next->nd_end;
-    }
-    else {
-	last = head;
-    }
-
-    head->nd_alen += tail->nd_alen;
-    GC_WB(&last->nd_next, tail);
-    if (tail->nd_next) {
-	GC_WB(&head->nd_next->nd_end, tail->nd_next->nd_end);
-    }
-    else {
-	GC_WB(&head->nd_next->nd_end, tail);
-    }
-
-    return head;
-}
-
-static int
-literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
-{
-    rb_str_buf_append(head, tail);
-    return 1;
-}
-
-/* concat two string literals */
-static NODE *
-literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
-{
-    enum node_type htype;
-
-    if (!head) return tail;
-    if (!tail) return head;
-
-    htype = nd_type(head);
-    if (htype == NODE_EVSTR) {
-	NODE *node = NEW_DSTR(STR_NEW0());
-	head = list_append(node, head);
-    }
-    switch (nd_type(tail)) {
-      case NODE_STR:
-	if (htype == NODE_STR) {
-	    if (!literal_concat0(parser, head->nd_lit, tail->nd_lit)) {
-	      error:
-		rb_gc_force_recycle((VALUE)head);
-		rb_gc_force_recycle((VALUE)tail);
-		return 0;
-	    }
-	    rb_gc_force_recycle((VALUE)tail);
-	}
-	else {
-	    list_append(head, tail);
-	}
-	break;
-
-      case NODE_DSTR:
-	if (htype == NODE_STR) {
-	    if (!literal_concat0(parser, head->nd_lit, tail->nd_lit))
-		goto error;
-	    GC_WB(&tail->nd_lit, head->nd_lit);
-	    rb_gc_force_recycle((VALUE)head);
-	    head = tail;
-	}
-	else {
-	    nd_set_type(tail, NODE_ARRAY);
-	    GC_WB(&tail->nd_head, NEW_STR(tail->nd_lit));
-	    list_concat(head, tail);
-	}
-	break;
-
-      case NODE_EVSTR:
-	if (htype == NODE_STR) {
-	    nd_set_type(head, NODE_DSTR);
-	    head->nd_alen = 1;
-	}
-	list_append(head, tail);
-	break;
-    }
-    return head;
-}
-
-static NODE *
-evstr2dstr_gen(struct parser_params *parser, NODE *node)
-{
-    if (nd_type(node) == NODE_EVSTR) {
-	node = list_append(NEW_DSTR(STR_NEW0()), node);
-    }
-    return node;
-}
-
-static NODE *
-new_evstr_gen(struct parser_params *parser, NODE *node)
-{
-    NODE *head = node;
-
-    if (node) {
-	switch (nd_type(node)) {
-	  case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
-	    return node;
-	}
-    }
-    return NEW_EVSTR(head);
-}
-
-static NODE *
-call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
-{
-    value_expr(recv);
-    value_expr(arg1);
-    return NEW_CALL(recv, id, NEW_LIST(arg1));
-}
-
-static NODE *
-call_uni_op_gen(struct parser_params *parser, NODE *recv, ID id)
-{
-    value_expr(recv);
-    return NEW_CALL(recv, id, 0);
-}
-
-static NODE*
-match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
-{
-    value_expr(node1);
-    value_expr(node2);
-    if (node1) {
-	switch (nd_type(node1)) {
-	  case NODE_DREGX:
-	  case NODE_DREGX_ONCE:
-	    return NEW_MATCH2(node1, node2);
-
-	  case NODE_LIT:
-	    if (TYPE(node1->nd_lit) == T_REGEXP) {
-		return NEW_MATCH2(node1, node2);
-	    }
-	}
-    }
-
-    if (node2) {
-	switch (nd_type(node2)) {
-	  case NODE_DREGX:
-	  case NODE_DREGX_ONCE:
-	    return NEW_MATCH3(node2, node1);
-
-	  case NODE_LIT:
-	    if (TYPE(node2->nd_lit) == T_REGEXP) {
-		return NEW_MATCH3(node2, node1);
-	    }
-	}
-    }
-
-    return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
-}
-
-static NODE*
-gettable_gen(struct parser_params *parser, ID id)
-{
-    if (id == keyword_self) {
-	return NEW_SELF();
-    }
-    else if (id == keyword_nil) {
-	return NEW_NIL();
-    }
-    else if (id == keyword_true) {
-	return NEW_TRUE();
-    }
-    else if (id == keyword_false) {
-	return NEW_FALSE();
-    }
-    else if (id == keyword__FILE__) {
-	return NEW_STR(STR_NEW2(ruby_sourcefile));
-    }
-    else if (id == keyword__LINE__) {
-	return NEW_LIT(INT2FIX(ruby_sourceline));
-    }
-    else if (id == keyword__ENCODING__) {
-	return NEW_LIT(rb_enc_from_encoding(parser->enc));
-    }
-    else if (is_local_id(id)) {
-#if WITH_OBJC
-	if (dyna_in_block() && dvar_defined(id)) {
-	    dyna_var(id);
-	    return NEW_DVAR(id);
-	}
-#else
-	if (dyna_in_block() && dvar_defined(id)) return NEW_DVAR(id);
-#endif
-	if (local_id(id)) return NEW_LVAR(id);
-	/* method call without arguments */
-	return NEW_VCALL(id);
-    }
-    else if (is_global_id(id)) {
-	return NEW_GVAR(id);
-    }
-    else if (is_instance_id(id)) {
-	return NEW_IVAR(id);
-    }
-    else if (is_const_id(id)) {
-	return NEW_CONST(id);
-    }
-    else if (is_class_id(id)) {
-	return NEW_CVAR(id);
-    }
-    compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
-    return 0;
-}
-
-int rb_local_define(ID id);
-
-static NODE*
-assignable_gen(struct parser_params *parser, ID id, NODE *val)
-{
-    if (!id) return 0;
-    if (id == keyword_self) {
-	yyerror("Can't change the value of self");
-    }
-    else if (id == keyword_nil) {
-	yyerror("Can't assign to nil");
-    }
-    else if (id == keyword_true) {
-	yyerror("Can't assign to true");
-    }
-    else if (id == keyword_false) {
-	yyerror("Can't assign to false");
-    }
-    else if (id == keyword__FILE__) {
-	yyerror("Can't assign to __FILE__");
-    }
-    else if (id == keyword__LINE__) {
-	yyerror("Can't assign to __LINE__");
-    }
-    else if (id == keyword__ENCODING__) {
-	yyerror("Can't assign to __ENCODING__");
-    }
-    else if (is_local_id(id)) {
-	if (dyna_in_block()) {
-	    if (dvar_curr(id)) {
-#if WITH_OBJC
-		dyna_var(id);
-#endif
-		return NEW_DASGN_CURR(id, val);
-	    }
-	    else if (dvar_defined(id)) {
-#if WITH_OBJC
-		dyna_var(id);
-#endif
-		return NEW_DASGN(id, val);
-	    }
-	    else if (local_id(id)) {
-		return NEW_LASGN(id, val);
-	    }
-	    else {
-		if (in_def > 0 || in_single > 0 || !rb_local_define(id)) {
-		    dyna_var(id);
-		}
-		return NEW_DASGN_CURR(id, val);
-	    }
-	}
-	else {
-	    if (!local_id(id)) {
-		local_var(id);
-	    }
-	    return NEW_LASGN(id, val);
-	}
-    }
-    else if (is_global_id(id)) {
-	return NEW_GASGN(id, val);
-    }
-    else if (is_instance_id(id)) {
-	return NEW_IASGN(id, val);
-    }
-    else if (is_const_id(id)) {
-	if (in_def || in_single)
-	    yyerror("dynamic constant assignment");
-	return NEW_CDECL(id, val, 0);
-    }
-    else if (is_class_id(id)) {
-	return NEW_CVASGN(id, val);
-    }
-    else {
-	compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
-    }
-    return 0;
-}
-
-static void
-shadowing_lvar_gen(struct parser_params *parser, ID name)
-{
-    static ID uscore;
-
-    if (!uscore) uscore = rb_intern("_");
-    if (uscore == name) return;
-    if (dyna_in_block()) {
-	if (dvar_curr(name)) {
-	    yyerror("duplicated argument name");
-	}
-	else if (dvar_defined(name) || local_id(name)) {
-	    rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
-	    vtable_add(lvtbl->vars, name);
-	}
-    }
-    else {
-	if (local_id(name)) {
-	    yyerror("duplicated argument name");
-	}
-    }
-}
-
-static void
-new_bv_gen(struct parser_params *parser, ID name)
-{
-    if (!name) return;
-    if (!is_local_id(name)) {
-	compile_error(PARSER_ARG "invalid local variable - %s",
-		      rb_id2name(name));
-	return;
-    }
-    shadowing_lvar(name);
-    dyna_var(name);
-}
-
-static NODE *
-aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
-{
-    if (recv && nd_type(recv) == NODE_SELF)
-	recv = (NODE *)1;
-    return NEW_ATTRASGN(recv, tASET, idx);
-}
-
-static void
-block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
-{
-    if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
-	compile_error(PARSER_ARG "both block arg and actual block given");
-    }
-}
-
-static NODE *
-attrset_gen(struct parser_params *parser, NODE *recv, ID id)
-{
-    if (recv && nd_type(recv) == NODE_SELF)
-	recv = (NODE *)1;
-    return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
-}
-
-static void
-rb_backref_error_gen(struct parser_params *parser, NODE *node)
-{
-    switch (nd_type(node)) {
-      case NODE_NTH_REF:
-	compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth);
-	break;
-      case NODE_BACK_REF:
-	compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth);
-	break;
-    }
-}
-
-static NODE *
-arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
-{
-    if (!node2) return node1;
-    switch (nd_type(node1)) {
-      case NODE_BLOCK_PASS:
-	GC_WB(&node1->nd_iter, arg_concat(node1->nd_iter, node2));
-	return node1;
-      case NODE_ARGSPUSH:
-	if (nd_type(node2) != NODE_ARRAY) break;
-	GC_WB(&node1->nd_body, list_concat(NEW_LIST(node1->nd_body), node2));
-	nd_set_type(node1, NODE_ARGSCAT);
-	return node1;
-      case NODE_ARGSCAT:
-	if (nd_type(node2) != NODE_ARRAY) break;
-	GC_WB(&node1->nd_body, list_concat(node1->nd_body, node2));
-	return node1;
-    }
-    return NEW_ARGSCAT(node1, node2);
-}
-
-static NODE *
-arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2)
-{
-    if (!node1) return NEW_LIST(node2);
-    switch (nd_type(node1))  {
-      case NODE_ARRAY:
-	return list_append(node1, node2);
-      case NODE_BLOCK_PASS:
-	GC_WB(&node1->nd_head, arg_append(node1->nd_head, node2));
-	return node1;
-      case NODE_ARGSPUSH:
-	GC_WB(&node1->nd_body, list_append(NEW_LIST(node1->nd_body), node2));
-	nd_set_type(node1, NODE_ARGSCAT);
-	return node1;
-    }
-    return NEW_ARGSPUSH(node1, node2);
-}
-
-static NODE *
-splat_array(NODE* node)
-{
-    if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
-    if (nd_type(node) == NODE_ARRAY) return node;
-    return 0;
-}
-
-static NODE *
-node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
-{
-    if (!lhs) return 0;
-
-    switch (nd_type(lhs)) {
-      case NODE_GASGN:
-      case NODE_IASGN:
-      case NODE_IASGN2:
-      case NODE_LASGN:
-      case NODE_DASGN:
-      case NODE_DASGN_CURR:
-      case NODE_MASGN:
-      case NODE_CDECL:
-      case NODE_CVASGN:
-	GC_WB(&lhs->nd_value, rhs);
-	break;
-
-      case NODE_ATTRASGN:
-      case NODE_CALL:
-	GC_WB(&lhs->nd_args, arg_append(lhs->nd_args, rhs));
-	break;
-
-      default:
-	/* should not happen */
-	break;
-    }
-
-    return lhs;
-}
-
-static int
-value_expr_gen(struct parser_params *parser, NODE *node)
-{
-    int cond = 0;
-
-    if (!node) {
-	rb_warning0("empty expression");
-    }
-    while (node) {
-	switch (nd_type(node)) {
-	  case NODE_DEFN:
-	  case NODE_DEFS:
-	    parser_warning(node, "void value expression");
-	    return Qfalse;
-
-	  case NODE_RETURN:
-	  case NODE_BREAK:
-	  case NODE_NEXT:
-	  case NODE_REDO:
-	  case NODE_RETRY:
-	    if (!cond) yyerror("void value expression");
-	    /* or "control never reach"? */
-	    return Qfalse;
-
-	  case NODE_BLOCK:
-	    while (node->nd_next) {
-		node = node->nd_next;
-	    }
-	    node = node->nd_head;
-	    break;
-
-	  case NODE_BEGIN:
-	    node = node->nd_body;
-	    break;
-
-	  case NODE_IF:
-	    if (!node->nd_body) {
-		node = node->nd_else;
-		break;
-	    }
-	    else if (!node->nd_else) {
-		node = node->nd_body;
-		break;
-	    }
-	    if (!value_expr(node->nd_body)) return Qfalse;
-	    node = node->nd_else;
-	    break;
-
-	  case NODE_AND:
-	  case NODE_OR:
-	    cond = 1;
-	    node = node->nd_2nd;
-	    break;
-
-	  default:
-	    return Qtrue;
-	}
-    }
-
-    return Qtrue;
-}
-
-static void
-void_expr_gen(struct parser_params *parser, NODE *node)
-{
-    const char *useless = 0;
-
-    if (!RTEST(ruby_verbose)) return;
-
-    if (!node) return;
-    switch (nd_type(node)) {
-      case NODE_CALL:
-	switch (node->nd_mid) {
-	  case '+':
-	  case '-':
-	  case '*':
-	  case '/':
-	  case '%':
-	  case tPOW:
-	  case tUPLUS:
-	  case tUMINUS:
-	  case '|':
-	  case '^':
-	  case '&':
-	  case tCMP:
-	  case '>':
-	  case tGEQ:
-	  case '<':
-	  case tLEQ:
-	  case tEQ:
-	  case tNEQ:
-	    useless = rb_id2name(node->nd_mid);
-	    break;
-	}
-	break;
-
-      case NODE_LVAR:
-      case NODE_DVAR:
-      case NODE_GVAR:
-      case NODE_IVAR:
-      case NODE_CVAR:
-      case NODE_NTH_REF:
-      case NODE_BACK_REF:
-	useless = "a variable";
-	break;
-      case NODE_CONST:
-	useless = "a constant";
-	break;
-      case NODE_LIT:
-      case NODE_STR:
-      case NODE_DSTR:
-      case NODE_DREGX:
-      case NODE_DREGX_ONCE:
-	useless = "a literal";
-	break;
-      case NODE_COLON2:
-      case NODE_COLON3:
-	useless = "::";
-	break;
-      case NODE_DOT2:
-	useless = "..";
-	break;
-      case NODE_DOT3:
-	useless = "...";
-	break;
-      case NODE_SELF:
-	useless = "self";
-	break;
-      case NODE_NIL:
-	useless = "nil";
-	break;
-      case NODE_TRUE:
-	useless = "true";
-	break;
-      case NODE_FALSE:
-	useless = "false";
-	break;
-      case NODE_DEFINED:
-	useless = "defined?";
-	break;
-    }
-
-    if (useless) {
-	int line = ruby_sourceline;
-
-	ruby_sourceline = nd_line(node);
-	rb_warnS("useless use of %s in void context", useless);
-	ruby_sourceline = line;
-    }
-}
-
-static void
-void_stmts_gen(struct parser_params *parser, NODE *node)
-{
-    if (!RTEST(ruby_verbose)) return;
-    if (!node) return;
-    if (nd_type(node) != NODE_BLOCK) return;
-
-    for (;;) {
-	if (!node->nd_next) return;
-	void_expr0(node->nd_head);
-	node = node->nd_next;
-    }
-}
-
-static NODE *
-remove_begin(NODE *node)
-{
-    NODE **n = &node, *n1 = node;
-    while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
-	*n = n1 = n1->nd_body;
-    }
-    return node;
-}
-
-static void
-reduce_nodes_gen(struct parser_params *parser, NODE **body)
-{
-    NODE *node = *body;
-
-    if (!node) {
-	*body = NEW_NIL();
-	return;
-    }
-#define subnodes(n1, n2) \
-    ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
-     (!node->n2) ? (body = &node->n1, 1) : \
-     (reduce_nodes(&node->n1), body = &node->n2, 1))
-
-    while (node) {
-	switch (nd_type(node)) {
-	  end:
-	  case NODE_NIL:
-	    *body = 0;
-	    return;
-	  case NODE_RETURN:
-	    *body = node = node->nd_stts;
-	    continue;
-	  case NODE_BEGIN:
-	    *body = node = node->nd_body;
-	    continue;
-	  case NODE_BLOCK:
-	    body = &node->nd_end->nd_head;
-	    break;
-	  case NODE_IF:
-	    if (subnodes(nd_body, nd_else)) break;
-	    return;
-	  case NODE_CASE:
-	    body = &node->nd_body;
-	    break;
-	  case NODE_WHEN:
-	    if (!subnodes(nd_body, nd_next)) goto end;
-	    break;
-	  case NODE_ENSURE:
-	    if (!subnodes(nd_head, nd_resq)) goto end;
-	    break;
-	  case NODE_RESCUE:
-	    if (!subnodes(nd_head, nd_resq)) goto end;
-	    break;
-	  default:
-	    return;
-	}
-	node = *body;
-    }
-
-#undef subnodes
-}
-
-static int
-assign_in_cond(struct parser_params *parser, NODE *node)
-{
-    switch (nd_type(node)) {
-      case NODE_MASGN:
-	yyerror("multiple assignment in conditional");
-	return 1;
-
-      case NODE_LASGN:
-      case NODE_DASGN:
-      case NODE_GASGN:
-      case NODE_IASGN:
-	break;
-
-      default:
-	return 0;
-    }
-
-    switch (nd_type(node->nd_value)) {
-      case NODE_LIT:
-      case NODE_STR:
-      case NODE_NIL:
-      case NODE_TRUE:
-      case NODE_FALSE:
-	/* reports always */
-	parser_warn(node->nd_value, "found = in conditional, should be ==");
-	return 1;
-
-      case NODE_DSTR:
-      case NODE_XSTR:
-      case NODE_DXSTR:
-      case NODE_EVSTR:
-      case NODE_DREGX:
-      default:
-	break;
-    }
-    return 1;
-}
-
-static int
-e_option_supplied(struct parser_params *parser)
-{
-    if (strcmp(ruby_sourcefile, "-e") == 0)
-	return Qtrue;
-    return Qfalse;
-}
-
-static void
-warn_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
-{
-    if (!e_option_supplied(parser)) parser_warn(node, str);
-}
-
-static void
-warning_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
-{
-    if (!e_option_supplied(parser)) parser_warning(node, str);
-}
-
-static NODE *cond0(struct parser_params*,NODE*);
-
-static NODE*
-range_op(struct parser_params *parser, NODE *node)
-{
-    enum node_type type;
-
-    if (!e_option_supplied(parser)) return node;
-    if (node == 0) return 0;
-
-    value_expr(node);
-    node = cond0(parser, node);
-    type = nd_type(node);
-    if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
-	warn_unless_e_option(parser, node, "integer literal in conditional range");
-	return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."))));
-    }
-    return node;
-}
-
-static int
-literal_node(NODE *node)
-{
-    if (!node) return 1;	/* same as NODE_NIL */
-    switch (nd_type(node)) {
-      case NODE_LIT:
-      case NODE_STR:
-      case NODE_DSTR:
-      case NODE_EVSTR:
-      case NODE_DREGX:
-      case NODE_DREGX_ONCE:
-      case NODE_DSYM:
-	return 2;
-      case NODE_TRUE:
-      case NODE_FALSE:
-      case NODE_NIL:
-	return 1;
-    }
-    return 0;
-}
-
-static NODE*
-cond0(struct parser_params *parser, NODE *node)
-{
-    if (node == 0) return 0;
-    assign_in_cond(parser, node);
-
-    switch (nd_type(node)) {
-      case NODE_DSTR:
-      case NODE_EVSTR:
-      case NODE_STR:
-	rb_warn0("string literal in condition");
-	break;
-
-      case NODE_DREGX:
-      case NODE_DREGX_ONCE:
-	warning_unless_e_option(parser, node, "regex literal in condition");
-	return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
-
-      case NODE_AND:
-      case NODE_OR:
-	GC_WB(&node->nd_1st, cond0(parser, node->nd_1st));
-	GC_WB(&node->nd_2nd, cond0(parser, node->nd_2nd));
-	break;
-
-      case NODE_DOT2:
-      case NODE_DOT3:
-	GC_WB(&node->nd_beg, range_op(parser, node->nd_beg));
-	GC_WB(&node->nd_end, range_op(parser, node->nd_end));
-	if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
-	else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
-	if (!e_option_supplied(parser)) {
-	    int b = literal_node(node->nd_beg);
-	    int e = literal_node(node->nd_end);
-	    if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
-		parser_warn(node, "range literal in condition");
-	    }
-	}
-	break;
-
-      case NODE_DSYM:
-	parser_warning(node, "literal in condition");
-	break;
-
-      case NODE_LIT:
-	if (TYPE(node->nd_lit) == T_REGEXP) {
-	    warn_unless_e_option(parser, node, "regex literal in condition");
-	    nd_set_type(node, NODE_MATCH);
-	}
-	else {
-	    parser_warning(node, "literal in condition");
-	}
-      default:
-	break;
-    }
-    return node;
-}
-
-static NODE*
-cond_gen(struct parser_params *parser, NODE *node)
-{
-    if (node == 0) return 0;
-    return cond0(parser, node);
-}
-
-static NODE*
-logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
-{
-    value_expr(left);
-    if (left && nd_type(left) == type) {
-	NODE *node = left, *second;
-	while ((second = node->nd_2nd) != 0 && nd_type(second) == type) {
-	    node = second;
-	}
-	GC_WB(&node->nd_2nd, NEW_NODE(type, second, right, 0));
-	return left;
-    }
-    return NEW_NODE(type, left, right, 0);
-}
-
-static void
-no_blockarg(struct parser_params *parser, NODE *node)
-{
-    if (node && nd_type(node) == NODE_BLOCK_PASS) {
-	compile_error(PARSER_ARG "block argument should not be given");
-    }
-}
-
-static NODE *
-ret_args_gen(struct parser_params *parser, NODE *node)
-{
-    if (node) {
-	no_blockarg(parser, node);
-	if (nd_type(node) == NODE_ARRAY) {
-	    if (node->nd_next == 0) {
-		node = node->nd_head;
-	    }
-	    else {
-		nd_set_type(node, NODE_VALUES);
-	    }
-	}
-    }
-    return node;
-}
-
-static NODE *
-new_yield_gen(struct parser_params *parser, NODE *node)
-{
-    long state = Qtrue;
-
-    if (node) {
-        no_blockarg(parser, node);
-	if (node && nd_type(node) == NODE_SPLAT) {
-	    state = Qtrue;
-	}
-    }
-    else {
-        state = Qfalse;
-    }
-    return NEW_YIELD(node, state);
-}
-
-static NODE*
-negate_lit(NODE *node)
-{
-    switch (TYPE(node->nd_lit)) {
-      case T_FIXNUM:
-	node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
-	break;
-      case T_BIGNUM:
-	GC_WB(&node->nd_lit, rb_funcall(node->nd_lit,tUMINUS,0,0));
-	break;
-      case T_FLOAT:
-	{
-	    double v = -RFLOAT_VALUE(node->nd_lit);
-	    node->nd_lit = DBL2FIXFLOAT(v);
-	}
-	break;
-      default:
-	break;
-    }
-    return node;
-}
-
-static NODE *
-arg_blk_pass(NODE *node1, NODE *node2)
-{
-    if (node2) {
-	GC_WB(&node2->nd_head, node1);
-	return node2;
-    }
-    return node1;
-}
-
-static NODE*
-new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
-{
-    int saved_line = ruby_sourceline;
-    NODE *node;
-    NODE *i1, *i2 = 0;
-
-    node = NEW_ARGS(m ? m->nd_plen : 0, o);
-    i1 = m ? m->nd_next : 0;
-    GC_WB(&node->nd_next, NEW_ARGS_AUX(r, b));
-
-    if (p) {
-	i2 = p->nd_next;
-	GC_WB(&node->nd_next->nd_next, NEW_ARGS_AUX(p->nd_pid, p->nd_plen));
-    }
-    else if (i1) {
-	GC_WB(&node->nd_next->nd_next, NEW_ARGS_AUX(0, 0));
-    }
-    if (i1 || i2) {
-	GC_WB(&node->nd_next->nd_next->nd_next, NEW_NODE(NODE_AND, i1, i2, 0));
-    }
-    ruby_sourceline = saved_line;
-    return node;
-}
-
-static void
-local_push_gen(struct parser_params *parser, int inherit_dvars)
-{
-    struct local_vars *local;
-
-    local = ALLOC(struct local_vars);
-    GC_WB(&local->prev, lvtbl);
-    GC_WB(&local->args, vtable_alloc(0));
-    GC_WB(&local->vars, vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE));
-    GC_WB(&lvtbl, local);
-}
-
-static void
-local_pop_gen(struct parser_params *parser)
-{
-    struct local_vars *local = lvtbl->prev;
-    vtable_free(lvtbl->args);
-    vtable_free(lvtbl->vars);
-    xfree(lvtbl);
-    GC_WB(&lvtbl, local);
-}
-
-static ID*
-local_tbl_gen(struct parser_params *parser)
-{
-    int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars);
-    ID *buf;
-
-    if (cnt <= 0) return 0;
-#if WITH_OBJC
-    buf = ALLOC_N(ID, cnt + 2);
-    buf[0] = vtable_size(lvtbl->args);
-    vtable_tblcpy(buf+1, lvtbl->args);
-    buf[vtable_size(lvtbl->args) + 1] = vtable_size(lvtbl->vars);
-    vtable_tblcpy(buf+vtable_size(lvtbl->args)+2, lvtbl->vars);
-#else
-    buf = ALLOC_N(ID, cnt + 1);
-    vtable_tblcpy(buf+1, lvtbl->args);
-    vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars);
-    buf[0] = cnt;
-#endif
-    return buf;
-}
-
-static int
-arg_var_gen(struct parser_params *parser, ID id)
-{
-    vtable_add(lvtbl->args, id);
-    return vtable_size(lvtbl->args) - 1;
-}
-
-#if WITH_OBJC
-static NODE *
-process_named_args_gen(struct parser_params *parser, NODE *n)
-{
-    NODE *args = n->nd_args;
-    if (args != NULL 
-	&& (args->nd_argc == 2 || args->nd_argc == 3)
-	&& nd_type(args->u3.node->u1.node) == NODE_ARRAY
-	&& args->u3.node->u1.node->flags & NODE_ARRAY_NAMED_ARGS) {
-
-	NODE *named_args;
-	NODE *new_argv;
-	NODE *p;
-	char buf[512];
-	bool flip;	
-
-	new_argv = NEW_LIST(args->nd_head);
-
-	strlcpy(buf, rb_id2name(n->u2.id), sizeof buf);
-	strlcat(buf, ":", sizeof buf);
-	
-	named_args = args->u3.node->u1.node;
-	for (flip = true, p = named_args; 
-	     p != NULL; 
-	     p = p->nd_next, flip = !flip) {
-	    if (flip) {
-		strlcat(buf, rb_sym2name(p->nd_head->nd_lit),
-			sizeof buf);
-		strlcat(buf, ":", sizeof buf);
-	    }
-	    else {
-		list_append(new_argv, p->nd_head);
-	    }	    
-	}
-
-	n->nd_mid = rb_intern(buf);
-        if (args->nd_argc == 3) {
-            NODE *variadic_args = args->nd_next->nd_next->nd_head;
-            for (p = variadic_args; p != NULL; p = p->nd_next) {
-		list_append(new_argv, p->nd_head);
-            }
-	}
-	GC_WB(&n->nd_args, new_argv);
-    }
-    return n;
-}
-
-static NODE *
-unprocess_named_args_gen(struct parser_params *parser, NODE *n)
-{
-    NODE *args = n->nd_args;
-    if (args != NULL 
-	&& args->nd_argc == 2 
-	&& nd_type(args->u3.node->u1.node) == NODE_ARRAY
-	&& args->u3.node->u1.node->flags & NODE_ARRAY_NAMED_ARGS) {
-
-	NODE *new_argv = NEW_LIST(args->nd_head);
-	arg_append(new_argv, NEW_HASH(args->u3.node->u1.node));
-	GC_WB(&n->nd_args, new_argv);
-    }
-    return n;
-}
-
-static void
-named_arg_gen(struct parser_params *parser, ID id, int init)
-{
-    if (init)
-	memset(named_mid, 0, sizeof named_mid);
-
-    strlcat(named_mid, rb_id2name(id), sizeof named_mid);
-    strlcat(named_mid, ":", sizeof named_mid);
-
-    if (!init) 
-	in_def_named_args++;
-}
-#endif
-
-static int
-local_var_gen(struct parser_params *parser, ID id)
-{
-    vtable_add(lvtbl->vars, id);
-    return vtable_size(lvtbl->vars) - 1;
-}
-
-static int
-local_id_gen(struct parser_params *parser, ID id)
-{
-    struct vtable *vars, *args;
-
-    vars = lvtbl->vars;
-    args = lvtbl->args;
-
-    while (vars && POINTER_P(vars->prev)) {
-	vars = vars->prev;
-	args = args->prev;
-    }
-
-    if (vars && vars->prev == DVARS_INHERIT) {
-	return rb_local_defined(id);
-    }
-    else {
-	return (vtable_included(args, id) ||
-		vtable_included(vars, id));
-    }
-}
-
-static void
-dyna_push_gen(struct parser_params *parser)
-{
-    GC_WB(&lvtbl->args, vtable_alloc(lvtbl->args));
-    GC_WB(&lvtbl->vars, vtable_alloc(lvtbl->vars));
-}
-
-static void
-dyna_pop_gen(struct parser_params *parser)
-{
-    struct vtable *tmp;
-    struct vtable *prev_vars = NULL, *prev_args = NULL;
-
-    prev_vars = lvtbl->vars->prev;
-    prev_args = lvtbl->args->prev;
-
-    if ((prev_vars != NULL) && (prev_vars->prev != NULL)) {
-	// copy vars in the outer block if they are not already there
-	// and if they are in an even outer scope
-	int i;
-	for (i = 0; i < lvtbl->vars->pos; ++i) {
-	    struct vtable *pprev_vars = NULL, *pprev_args = NULL;
-	    ID id = lvtbl->vars->tbl[i];
-
-	    if (vtable_included(prev_vars, id) || vtable_included(prev_args, id)) {
-		continue;
-	    }
-
-	    pprev_vars = prev_vars->prev;
-	    pprev_args = prev_args->prev;
-	    while ((pprev_vars != NULL) && (pprev_vars != DVARS_INHERIT)) {
-		if (vtable_included(pprev_vars, id) || vtable_included(pprev_args, id)) {
-		    vtable_add(prev_vars, id);
-		    break;
-		}
-		pprev_vars = pprev_vars->prev;
-		pprev_args = pprev_args->prev;
-	    }
-	}
-    }
-
-    tmp = lvtbl->args;
-    GC_WB(&lvtbl->args, prev_args);
-    vtable_free(tmp);
-    tmp = lvtbl->vars;
-    GC_WB(&lvtbl->vars, prev_vars);
-    vtable_free(tmp);
-}
-
-static int
-dyna_in_block_gen(struct parser_params *parser)
-{
-    return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE;
-}
-
-static int
-dvar_defined_gen(struct parser_params *parser, ID id)
-{
-    struct vtable *vars, *args;
-
-    args = lvtbl->args;
-    vars = lvtbl->vars;
-
-    while (POINTER_P(vars)) {
-	if (vtable_included(args, id)) {
-	    return 1;
-	}
-	if (vtable_included(vars, id)) {
-	    return 1;
-	}
-	args = args->prev;
-	vars = vars->prev;
-    }
-
-    if (vars == DVARS_INHERIT) {
-        return rb_dvar_defined(id);
-    }
-
-    return 0;
-}
-
-static int
-dvar_curr_gen(struct parser_params *parser, ID id)
-{
-    return (vtable_included(lvtbl->args, id) ||
-	    vtable_included(lvtbl->vars, id));
-}
-
-static void
-reg_fragment_setenc_gen(struct parser_params* parser, VALUE str, int options)
-{
-#if WITH_OBJC
-    /* TODO */
-#else
-    int c = RE_OPTION_ENCODING_IDX(options);
-
-    if (c) {
-	int opt, idx;
-	rb_char_to_option_kcode(c, &opt, &idx);
-	if (idx != ENCODING_GET(str) &&
-	    rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
-            goto error;
-	}
-	ENCODING_SET(str, idx);
-    }
-    else if (RE_OPTION_ENCODING_NONE(options)) {
-        if (!ENCODING_IS_ASCII8BIT(str) &&
-            rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
-            c = 'n';
-            goto error;
-        }
-	rb_enc_associate(str, rb_ascii8bit_encoding());
-    }
-    else if (parser->enc == rb_usascii_encoding()) {
-	if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
-	    /* raise in re.c */
-	    rb_enc_associate(str, rb_usascii_encoding());
-	}
-	else {
-	    rb_enc_associate(str, rb_ascii8bit_encoding());
-	}
-    }
-    return;
-
-  error:
-    compile_error(PARSER_ARG
-        "regexp encoding option '%c' differs from source encoding '%s'",
-        c, rb_enc_name(rb_enc_get(str)));
-#endif
-}
-
-static void
-reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
-{
-    VALUE err;
-    reg_fragment_setenc_gen(parser, str, options);
-    err = rb_reg_check_preprocess(str);
-    if (err != Qnil) {
-        err = rb_obj_as_string(err);
-        compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
-	RB_GC_GUARD(err);
-    }
-}
-
-#if 0
-typedef struct {
-    struct parser_params* parser;
-    rb_encoding *enc;
-    NODE *succ_block;
-    NODE *fail_block;
-    int num;
-} reg_named_capture_assign_t;
-
-static int
-reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
-          int back_num, int *back_refs, OnigRegex regex, void *arg0)
-{
-    reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
-    struct parser_params* parser = arg->parser;
-    rb_encoding *enc = arg->enc;
-    int len = name_end - name;
-    const char *s = (const char *)name;
-    ID var;
-
-    arg->num++;
-
-    if (arg->succ_block == 0) {
-        arg->succ_block = NEW_BEGIN(0);
-        arg->fail_block = NEW_BEGIN(0);
-    }
-
-    if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
-	rb_reserved_word(s, len) || !rb_enc_symname2_p(s, len, enc)) {
-        return ST_CONTINUE;
-    }
-    var = rb_intern3(s, len, enc);
-    if (dvar_defined(var) || local_id(var)) {
-        rb_warningS("named capture conflicts a local variable - %s", 
-                    rb_id2name(var));
-    }
-    arg->succ_block = block_append(arg->succ_block,
-        newline_node(node_assign(assignable(var,0),
-            NEW_CALL(
-              gettable(rb_intern("$~")),
-              idAREF,
-              NEW_LIST(NEW_LIT(ID2SYM(var))))
-            )));
-    arg->fail_block = block_append(arg->fail_block,
-        newline_node(node_assign(assignable(var,0), NEW_LIT(Qnil))));
-    return ST_CONTINUE;
-}
-#endif
-
-static NODE *
-reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match)
-{
-    // TODO
-    return match;
-#if 0
-    reg_named_capture_assign_t arg;
-
-    arg.parser = parser;
-    arg.enc = rb_enc_get(regexp);
-    arg.succ_block = 0;
-    arg.fail_block = 0;
-    arg.num = 0;
-    onig_foreach_name(RREGEXP(regexp)->ptr, reg_named_capture_assign_iter, (void*)&arg);
-
-    if (arg.num == 0)
-        return match;
-
-    return 
-        block_append(
-            newline_node(match),
-            NEW_IF(gettable(rb_intern("$~")),
-                block_append(
-                    newline_node(arg.succ_block),
-                    newline_node(
-                        NEW_CALL(
-                          gettable(rb_intern("$~")),
-                          rb_intern("begin"),
-                          NEW_LIST(NEW_LIT(INT2FIX(0)))))),
-                block_append(
-                    newline_node(arg.fail_block),
-                    newline_node(
-                        NEW_LIT(Qnil)))));
-#endif
-}
-
-static VALUE
-reg_compile_gen(struct parser_params* parser, VALUE str, int options)
-{
-    VALUE re;
-    VALUE err;
-
-    reg_fragment_setenc(str, options);
-    err = rb_errinfo();
-    re = rb_reg_compile(str, options & RE_OPTION_MASK);
-    if (NIL_P(re)) {
-	ID mesg = rb_intern("mesg");
-	VALUE m = rb_attr_get(rb_errinfo(), mesg);
-	rb_set_errinfo(err);
-	if (!NIL_P(err)) {
-	    rb_str_append(rb_str_cat(rb_attr_get(err, mesg), "\n", 1), m);
-	}
-	else {
-	    compile_error(PARSER_ARG "%s", RSTRING_PTR(m));
-	}
-	return Qnil;
-    }
-    return re;
-}
-
-void
-rb_gc_mark_parser(void)
-{
-}
-
-NODE*
-rb_parser_append_print(VALUE vparser, NODE *node)
-{
-    NODE *prelude = 0;
-    NODE *scope = node;
-    struct parser_params *parser;
-
-    if (!node) return node;
-
-    Data_Get_Struct(vparser, struct parser_params, parser);
-
-    node = node->nd_body;
-
-    if (nd_type(node) == NODE_PRELUDE) {
-	prelude = node;
-	node = node->nd_body;
-    }
-
-    node = block_append(node,
-			NEW_FCALL(rb_intern("print"),
-				  NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
-    if (prelude) {
-	GC_WB(&prelude->nd_body, node);
-	GC_WB(&scope->nd_body, prelude);
-    }
-    else {
-	GC_WB(&scope->nd_body, node);
-    }
-
-    return scope;
-}
-
-NODE *
-rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split)
-{
-    NODE *prelude = 0;
-    NODE *scope = node;
-    struct parser_params *parser;
-
-    if (!node) return node;
-
-    Data_Get_Struct(vparser, struct parser_params, parser);
-
-    node = node->nd_body;
-
-    if (nd_type(node) == NODE_PRELUDE) {
-	prelude = node;
-	node = node->nd_body;
-    }
-    if (split) {
-	node = block_append(NEW_GASGN(rb_intern("$F"),
-				      NEW_CALL(NEW_GVAR(rb_intern("$_")),
-					       rb_intern("split"), 0)),
-			    node);
-    }
-    if (chop) {
-	node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
-				     rb_intern("chop!"), 0), node);
-    }
-
-    node = NEW_OPT_N(node);
-
-    if (prelude) {
-	GC_WB(&prelude->nd_body, node);
-	GC_WB(&scope->nd_body, prelude);
-    }
-    else {
-	GC_WB(&scope->nd_body, node);
-    }
-
-    return scope;
-}
-
-// XXX not thread-safe
-static long internal_count = 0;
-
-static ID
-internal_id_gen(struct parser_params *parser)
-{
-    char buf[100];
-    snprintf(buf, sizeof buf, "__internal_id_tmp_%ld__", internal_count++);
-    return rb_intern(buf);
-}
-
-struct rb_op_tbl_entry rb_op_tbl[] = {
-    {'+',       "+"},
-    {'-',       "-"},
-    {'*',       "*"},
-    {'/',       "/"},
-    {'%',       "%"},
-    {'|',       "|"},
-    {'^',       "^"},
-    {'&',       "&"},
-    {'!',       "!"},
-    {'>',       ">"},
-    {'<',       "<"},
-    {'~',       "~"},
-    {'!',       "!"},
-    {'`',       "`"},
-    {tDOT2,     ".."},
-    {tDOT3,     "..."},
-    {tPOW,      "**"},
-    {tUPLUS,    "+@"},
-    {tUMINUS,   "-@"},
-    {tCMP,      "<=>"},
-    {tGEQ,      ">="},
-    {tLEQ,      "<="},
-    {tEQ,       "=="},
-    {tEQQ,      "==="},
-    {tNEQ,      "!="},
-    {tMATCH,    "=~"},
-    {tNMATCH,   "!~"},
-    {tAREF,     "[]"},
-    {tASET,     "[]="},
-    {tLSHFT,    "<<"},
-    {tRSHFT,    ">>"},
-    {tCOLON2,   "::"},
-    {0,         NULL}
-};
-
-const char *
-ruby_node_name(int node)
-{
-    switch (node) {
-#include "node_name.inc"
-	default:
-	    rb_bug("unknown node (%d)", node);
-	    return 0;
-    }
-}
-#endif /* !RIPPER */
-
-static void
-parser_initialize(struct parser_params *parser)
-{
-    parser->eofp = Qfalse;
-
-    parser->parser_lex_strterm = 0;
-    parser->parser_cond_stack = 0;
-    parser->parser_cmdarg_stack = 0;
-    parser->parser_class_nest = 0;
-    parser->parser_paren_nest = 0;
-    parser->parser_lpar_beg = 0;
-    parser->parser_in_single = 0;
-    parser->parser_in_def = 0;
-#if WITH_OBJC
-    parser->parser_in_def_named_args = 0;
-#endif
-    parser->parser_in_defined = 0;
-    parser->parser_compile_for_eval = 0;
-    parser->parser_cur_mid = 0;
-    parser->parser_tokenbuf = NULL;
-    parser->parser_tokidx = 0;
-    parser->parser_toksiz = 0;
-    parser->parser_heredoc_end = 0;
-    parser->parser_command_start = Qtrue;
-    parser->parser_lex_pbeg = 0;
-    parser->parser_lex_p = 0;
-    parser->parser_lex_pend = 0;
-    parser->parser_lvtbl = 0;
-    parser->parser_ruby__end__seen = 0;
-    parser->parser_ruby_sourcefile = 0;
-#ifndef RIPPER
-    parser->is_ripper = 0;
-    parser->parser_eval_tree_begin = 0;
-    parser->parser_eval_tree = 0;
-#else
-    parser->is_ripper = 1;
-    parser->parser_ruby_sourcefile_string = Qnil;
-    parser->delayed = Qnil;
-
-    parser->result = Qnil;
-    parser->parsing_thread = Qnil;
-    parser->toplevel_p = Qtrue;
-#endif
-#ifdef YYMALLOC
-    parser->heap = NULL;
-#endif
-#if WITH_OBJC
-    parser->enc = rb_locale_encoding();
-#else
-    parser->enc = rb_usascii_encoding();
-#endif
-}
-
-#ifdef RIPPER
-#define parser_free ripper_parser_free
-#endif
-
-static void
-parser_free(void *ptr)
-{
-    struct parser_params *p = (struct parser_params*)ptr;
-    struct local_vars *local, *prev;
-
-    if (p->parser_tokenbuf) {
-        xfree(p->parser_tokenbuf);
-    }
-    for (local = p->parser_lvtbl; local; local = prev) {
-	if (local->vars) xfree(local->vars);
-	prev = local->prev;
-	xfree(local);
-    }
-#ifndef RIPPER
-    xfree(p->parser_ruby_sourcefile);
-#endif
-    xfree(p);
-}
-
-VALUE rb_parser_get_yydebug(VALUE);
-VALUE rb_parser_set_yydebug(VALUE, VALUE);
-
-/*
- *  call-seq:
- *    ripper#end_seen?   -> Boolean
- *
- *  Return if parsed source ended by +\_\_END\_\_+.
- *  This number starts from 1.
- */
-static VALUE
-rb_parser_end_seen_p_imp(VALUE vparser, SEL sel)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(vparser, struct parser_params, parser);
-    return ruby__end__seen ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *    ripper#encoding   -> encoding
- *
- *  Return encoding of the source.
- */
-static VALUE
-rb_parser_encoding_imp(VALUE vparser, SEL sel)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(vparser, struct parser_params, parser);
-    return rb_enc_from_encoding(parser->enc);
-}
-
-/*
- *  call-seq:
- *    ripper.yydebug   -> true or false
- *
- *  Get yydebug.
- */
-static VALUE
-rb_parser_get_yydebug_imp(VALUE self, SEL sel)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    return yydebug ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *    ripper.yydebug = flag
- *
- *  Set yydebug.
- */
-static VALUE
-rb_parser_set_yydebug_imp(VALUE self, SEL sel, VALUE flag)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    yydebug = RTEST(flag);
-    return flag;
-}
-
-#ifndef RIPPER
-
-static struct parser_params *
-parser_new(void)
-{
-    struct parser_params *p;
-
-    p = ALLOC_N(struct parser_params, 1);
-    MEMZERO(p, struct parser_params, 1);
-    parser_initialize(p);
-    return p;
-}
-
-VALUE
-rb_parser_new(void)
-{
-    struct parser_params *p = parser_new();
-#if 1
-    VALUE c = rb_cData;
-#else
-    static VALUE c = 0;
-    if (c == 0) {
-	c = rb_define_class("__Parser", rb_cObject);
-    }
-#endif
-
-    return Data_Wrap_Struct(c, NULL, parser_free, p);
-}
-
-VALUE
-rb_parser_end_seen_p(VALUE vparser)
-{
-    return rb_parser_end_seen_p_imp(vparser, 0);
-}
-
-VALUE
-rb_parser_encoding(VALUE vparser)
-{
-    return rb_parser_encoding_imp(vparser, 0);
-}
-
-VALUE
-rb_parse_get_yydebug(VALUE self)
-{
-    return rb_parser_get_yydebug_imp(self, 0);
-}
-
-VALUE
-rb_parser_set_yydebug(VALUE self, VALUE flag)
-{
-    return rb_parser_set_yydebug_imp(self, 0, flag);
-}
-
-#ifdef YYMALLOC
-#define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
-#define NEWHEAP() (NODE *)GC_RELEASE(rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0))
-
-static inline void *
-__add2heap(struct parser_params *parser, NODE *n, size_t c, void *p)
-{
-    GC_WB(&parser->heap, n);
-    GC_WB(&n->u1.node, p);
-    n->u3.cnt = c;
-    return p;
-}
-#define ADD2HEAP(n, c, p) (__add2heap(parser, (NODE *)n, (size_t)c, (void *)p))
-
-void *
-rb_parser_malloc(struct parser_params *parser, size_t size)
-{
-    size_t cnt = HEAPCNT(1, size);
-    NODE *n = NEWHEAP();
-    void *ptr = xmalloc(size);
-
-    return ADD2HEAP(n, cnt, ptr);
-}
-
-void *
-rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size)
-{
-    size_t cnt = HEAPCNT(nelem, size);
-    NODE *n = NEWHEAP();
-    void *ptr = xcalloc(nelem, size);
-
-    return ADD2HEAP(n, cnt, ptr);
-}
-
-void *
-rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size)
-{
-    NODE *n;
-    size_t cnt = HEAPCNT(1, size);
-
-    if (ptr && (n = parser->heap) != NULL) {
-	do {
-	    if (n->u1.node == ptr) {
-		ptr = xrealloc(ptr, size);
-		GC_WB(&n->u1.node, ptr);
-		if (n->u3.cnt) n->u3.cnt = cnt;
-		return ptr;
-	    }
-	} while ((n = n->u2.node) != NULL);
-    }
-    n = NEWHEAP();
-    ptr = xrealloc(ptr, size);
-    return ADD2HEAP(n, cnt, ptr);
-}
-
-void
-rb_parser_free(struct parser_params *parser, void *ptr)
-{
-    NODE **prev = &parser->heap, *n;
-
-    while ((n = *prev) != NULL) {
-	if (n->u1.node == ptr) {
-	    GC_WB(prev, n->u2.node);
-	    rb_gc_force_recycle((VALUE)n);
-	    break;
-	}
-	prev = &n->u2.node;
-    }
-    xfree(ptr);
-}
-#endif
-#endif
-
-#ifdef RIPPER
-#ifdef RIPPER_DEBUG
-extern int rb_is_pointer_to_heap(VALUE);
-
-/* :nodoc: */
-static VALUE
-ripper_validate_object(VALUE self, VALUE x)
-{
-    if (x == Qfalse) return x;
-    if (x == Qtrue) return x;
-    if (x == Qnil) return x;
-    if (x == Qundef)
-        rb_raise(rb_eArgError, "Qundef given");
-    if (FIXNUM_P(x)) return x;
-    if (SYMBOL_P(x)) return x;
-    if (!rb_is_pointer_to_heap(x))
-        rb_raise(rb_eArgError, "invalid pointer: %p", x);
-    switch (TYPE(x)) {
-      case T_STRING:
-      case T_OBJECT:
-      case T_ARRAY:
-      case T_BIGNUM:
-      case T_FLOAT:
-        return x;
-      case T_NODE:
-        rb_raise(rb_eArgError, "NODE given: %p", x);
-      default:
-        rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
-                 x, rb_obj_classname(x));
-    }
-    return x;
-}
-#endif
-
-#define validate(x)
-
-static VALUE
-ripper_dispatch0(struct parser_params *parser, ID mid)
-{
-    return rb_funcall(parser->value, mid, 0);
-}
-
-static VALUE
-ripper_dispatch1(struct parser_params *parser, ID mid, VALUE a)
-{
-    validate(a);
-    return rb_funcall(parser->value, mid, 1, a);
-}
-
-static VALUE
-ripper_dispatch2(struct parser_params *parser, ID mid, VALUE a, VALUE b)
-{
-    validate(a);
-    validate(b);
-    return rb_funcall(parser->value, mid, 2, a, b);
-}
-
-static VALUE
-ripper_dispatch3(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c)
-{
-    validate(a);
-    validate(b);
-    validate(c);
-    return rb_funcall(parser->value, mid, 3, a, b, c);
-}
-
-static VALUE
-ripper_dispatch4(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d)
-{
-    validate(a);
-    validate(b);
-    validate(c);
-    validate(d);
-    return rb_funcall(parser->value, mid, 4, a, b, c, d);
-}
-
-static VALUE
-ripper_dispatch5(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e)
-{
-    validate(a);
-    validate(b);
-    validate(c);
-    validate(d);
-    validate(e);
-    return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
-}
-
-static const struct kw_assoc {
-    ID id;
-    const char *name;
-} keyword_to_name[] = {
-    {keyword_class,	"class"},
-    {keyword_module,	"module"},
-    {keyword_def,	"def"},
-    {keyword_undef,	"undef"},
-    {keyword_begin,	"begin"},
-    {keyword_rescue,	"rescue"},
-    {keyword_ensure,	"ensure"},
-    {keyword_end,	"end"},
-    {keyword_if,	"if"},
-    {keyword_unless,	"unless"},
-    {keyword_then,	"then"},
-    {keyword_elsif,	"elsif"},
-    {keyword_else,	"else"},
-    {keyword_case,	"case"},
-    {keyword_when,	"when"},
-    {keyword_while,	"while"},
-    {keyword_until,	"until"},
-    {keyword_for,	"for"},
-    {keyword_break,	"break"},
-    {keyword_next,	"next"},
-    {keyword_redo,	"redo"},
-    {keyword_retry,	"retry"},
-    {keyword_in,	"in"},
-    {keyword_do,	"do"},
-    {keyword_do_cond,	"do"},
-    {keyword_do_block,	"do"},
-    {keyword_return,	"return"},
-    {keyword_yield,	"yield"},
-    {keyword_super,	"super"},
-    {keyword_self,	"self"},
-    {keyword_nil,	"nil"},
-    {keyword_true,	"true"},
-    {keyword_false,	"false"},
-    {keyword_and,	"and"},
-    {keyword_or,	"or"},
-    {keyword_not,	"not"},
-    {modifier_if,	"if"},
-    {modifier_unless,	"unless"},
-    {modifier_while,	"while"},
-    {modifier_until,	"until"},
-    {modifier_rescue,	"rescue"},
-    {keyword_alias,	"alias"},
-    {keyword_defined,	"defined?"},
-    {keyword_BEGIN,	"BEGIN"},
-    {keyword_END,	"END"},
-    {keyword__LINE__,	"__LINE__"},
-    {keyword__FILE__,	"__FILE__"},
-    {keyword__ENCODING__, "__ENCODING__"},
-    {0, NULL}
-};
-
-static const char*
-keyword_id_to_str(ID id)
-{
-    const struct kw_assoc *a;
-
-    for (a = keyword_to_name; a->id; a++) {
-        if (a->id == id)
-            return a->name;
-    }
-    return NULL;
-}
-
-static VALUE
-ripper_id2sym(ID id)
-{
-    const char *name;
-    char buf[8];
-
-    if (id <= 256) {
-        buf[0] = id;
-        buf[1] = '\0';
-        return ID2SYM(rb_intern(buf));
-    }
-    if ((name = keyword_id_to_str(id))) {
-        return ID2SYM(rb_intern(name));
-    }
-    switch (id) {
-      case tOROP:
-        name = "||";
-        break;
-      case tANDOP:
-        name = "&&";
-        break;
-      default:
-        name = rb_id2name(id);
-        if (!name) {
-            rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
-        }
-        break;
-    }
-    return ID2SYM(rb_intern(name));
-}
-
-static VALUE
-ripper_intern(const char *s)
-{
-    return ID2SYM(rb_intern(s));
-}
-
-static void
-ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
-{
-    VALUE str;
-    va_list args;
-
-    va_start(args, fmt);
-    str = rb_vsprintf(fmt, args);
-    va_end(args);
-    rb_funcall(parser->value, rb_intern("compile_error"), 1, str);
-}
-
-static void
-ripper_warn0(struct parser_params *parser, const char *fmt)
-{
-    rb_funcall(parser->value, rb_intern("warn"), 1, STR_NEW2(fmt));
-}
-
-static void
-ripper_warnI(struct parser_params *parser, const char *fmt, int a)
-{
-    rb_funcall(parser->value, rb_intern("warn"), 2,
-               STR_NEW2(fmt), INT2NUM(a));
-}
-
-#if 0
-static void
-ripper_warnS(struct parser_params *parser, const char *fmt, const char *str)
-{
-    rb_funcall(parser->value, rb_intern("warn"), 2,
-    	       STR_NEW2(fmt), STR_NEW2(str));
-}
-#endif
-
-static void
-ripper_warning0(struct parser_params *parser, const char *fmt)
-{
-    rb_funcall(parser->value, rb_intern("warning"), 1, STR_NEW2(fmt));
-}
-
-static void
-ripper_warningS(struct parser_params *parser, const char *fmt, const char *str)
-{
-    rb_funcall(parser->value, rb_intern("warning"), 2,
-               STR_NEW2(fmt), STR_NEW2(str));
-}
-
-#if 0
-static VALUE
-ripper_lex_get_generic(struct parser_params *parser, VALUE src)
-{
-    return rb_funcall(src, ripper_id_gets, 0);
-}
-#endif
-
-static VALUE
-ripper_s_allocate(VALUE klass)
-{
-    struct parser_params *p;
-    VALUE self;
-
-    p = ALLOC_N(struct parser_params, 1);
-    MEMZERO(p, struct parser_params, 1);
-    self = Data_Wrap_Struct(klass, NULL, parser_free, p);
-    p->value = self;
-    return self;
-}
-
-#define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
-
-/*
- *  call-seq:
- *    Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
- *
- *  Create a new Ripper object.
- *  _src_ must be a String, a IO, or an Object which has #gets method.
- *
- *  This method does not starts parsing.
- *  See also Ripper#parse and Ripper.parse.
- */
-static VALUE
-ripper_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    struct parser_params *parser;
-    VALUE src, fname, lineno;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
-
-    long chars_len = 0;
-    UChar *chars = rb_str_xcopy_uchars(src, &chars_len);
-
-    struct lex_get_str_context *ctx = (struct lex_get_str_context *)
-	xmalloc(sizeof(struct lex_get_str_context));
-    GC_WB(&ctx->str, src);
-    GC_WB(&ctx->chars, chars);
-    ctx->chars_len = chars_len;
-
-    parser->parser_lex_gets = lex_get_str;
-    GC_WB(&parser->parser_lex_input, ctx);
-    parser->eofp = Qfalse;
-
-    if (NIL_P(fname)) {
-        fname = STR_NEW2("(ripper)");
-    }
-    else {
-        StringValue(fname);
-    }
-    parser_initialize(parser);
-
-    GC_WB(&parser->parser_ruby_sourcefile_string, fname);
-    parser->parser_ruby_sourcefile = (char *)RSTRING_PTR(fname);
-    parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
-
-    return Qnil;
-}
-
-extern VALUE rb_thread_pass(void);
-
-struct ripper_args {
-    struct parser_params *parser;
-    int argc;
-    VALUE *argv;
-};
-
-static VALUE
-ripper_parse0(VALUE parser_v)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(parser_v, struct parser_params, parser);
-    parser_prepare(parser);
-    ripper_yyparse((void*)parser);
-    return parser->result;
-}
-
-static VALUE
-ripper_ensure(VALUE parser_v)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(parser_v, struct parser_params, parser);
-    parser->parsing_thread = Qnil;
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *    ripper#parse
- *
- *  Start parsing and returns the value of the root action.
- */
-static VALUE
-ripper_parse(VALUE self, SEL sel)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    if (!ripper_initialized_p(parser)) {
-        rb_raise(rb_eArgError, "method called for uninitialized object");
-    }
-    if (!NIL_P(parser->parsing_thread)) {
-        if (parser->parsing_thread == rb_thread_current())
-            rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
-        else
-            rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
-    }
-    parser->parsing_thread = rb_thread_current();
-    rb_ensure(ripper_parse0, self, ripper_ensure, self);
-
-    return parser->result;
-}
-
-/*
- *  call-seq:
- *    ripper#column   -> Integer
- *
- *  Return column number of current parsing line.
- *  This number starts from 0.
- */
-static VALUE
-ripper_column(VALUE self, SEL sel)
-{
-    struct parser_params *parser;
-    long col;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    if (!ripper_initialized_p(parser)) {
-        rb_raise(rb_eArgError, "method called for uninitialized object");
-    }
-    if (NIL_P(parser->parsing_thread)) return Qnil;
-    col = parser->tokp - parser->parser_lex_pbeg;
-    return LONG2NUM(col);
-}
-
-/*
- *  call-seq:
- *    ripper#lineno   -> Integer
- *
- *  Return line number of current parsing line.
- *  This number starts from 1.
- */
-static VALUE
-ripper_lineno(VALUE self, SEL sel)
-{
-    struct parser_params *parser;
-
-    Data_Get_Struct(self, struct parser_params, parser);
-    if (!ripper_initialized_p(parser)) {
-        rb_raise(rb_eArgError, "method called for uninitialized object");
-    }
-    if (NIL_P(parser->parsing_thread)) return Qnil;
-    return INT2NUM(parser->parser_ruby_sourceline);
-}
-
-#ifdef RIPPER_DEBUG
-/* :nodoc: */
-static VALUE
-ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
-{
-    StringValue(msg);
-    if (obj == Qundef) {
-        rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
-    }
-    return Qnil;
-}
-
-/* :nodoc: */
-static VALUE
-ripper_value(VALUE self, VALUE obj)
-{
-    return ULONG2NUM(obj);
-}
-#endif
-
-void
-Init_ripper(void)
-{
-    VALUE Ripper = rb_define_class("Ripper", rb_cObject);
-    rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
-    rb_objc_define_method(*(VALUE *)Ripper, "alloc", ripper_s_allocate, 0);
-    rb_objc_define_method(Ripper, "initialize", ripper_initialize, -1);
-    rb_objc_define_method(Ripper, "parse", ripper_parse, 0);
-    rb_objc_define_method(Ripper, "column", ripper_column, 0);
-    rb_objc_define_method(Ripper, "lineno", ripper_lineno, 0);
-    rb_objc_define_method(Ripper, "end_seen?", rb_parser_end_seen_p_imp, 0);
-    rb_objc_define_method(Ripper, "encoding", rb_parser_encoding_imp, 0);
-    rb_objc_define_method(Ripper, "yydebug", rb_parser_get_yydebug_imp, 0);
-    rb_objc_define_method(Ripper, "yydebug=", rb_parser_set_yydebug_imp, 1);
-#ifdef RIPPER_DEBUG
-    rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
-    rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
-    rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
-#endif
-
-    ripper_id_gets = rb_intern("gets");
-    ripper_init_eventids1(Ripper);
-    ripper_init_eventids2(Ripper);
-    /* ensure existing in symbol table */
-    rb_intern("||");
-    rb_intern("&&");
-}
-#endif /* RIPPER */

Deleted: MacRuby/trunk/prec.c
===================================================================
--- MacRuby/trunk/prec.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/prec.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,131 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-
-VALUE rb_mPrecision;
-
-static ID prc_pr, prc_if;
-
-
-/*
- *  call-seq:
- *   num.prec(klass)   => a_class
- *
- *  Converts _self_ into an instance of _klass_. By default,
- *  +prec+ invokes 
- *
- *     klass.induced_from(num)
- *
- *  and returns its value. So, if <code>klass.induced_from</code>
- *  doesn't return an instance of _klass_, it will be necessary
- *  to reimplement +prec+.
- */
-
-static VALUE
-prec_prec(VALUE x, SEL sel, VALUE klass)
-{
-    return rb_funcall(klass, prc_if, 1, x);
-}
-
-/*
- *  call-seq:
- *    num.prec_i  =>  Integer
- *
- *  Returns an +Integer+ converted from _num_. It is equivalent 
- *  to <code>prec(Integer)</code>.
- */
-
-static VALUE
-prec_prec_i(VALUE x, SEL sel)
-{
-    VALUE klass = rb_cInteger;
-
-    return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- *  call-seq:
- *    num.prec_f  =>  Float
- *
- *  Returns a +Float+ converted from _num_. It is equivalent 
- *  to <code>prec(Float)</code>.
- */
-
-static VALUE
-prec_prec_f(VALUE x, SEL sel)
-{
-    VALUE klass = rb_cFloat;
-
-    return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- *   Mod.induced_from(number)  =>  a_mod
- * 
- * Creates an instance of mod from. This method is overridden
- * by concrete +Numeric+ classes, so that (for example)
- *
- *   Fixnum.induced_from(9.9)   #=>  9
- *
- * Note that a use of +prec+ in a redefinition may cause
- * an infinite loop.
- */
-
-static VALUE
-prec_induced_from(VALUE module, SEL sel, VALUE x)
-{
-    rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
-            rb_obj_classname(x), rb_class2name(module));
-    return Qnil;		/* not reached */
-}
-
-/*
- * call_seq:
- *   included
- *
- * When the +Precision+ module is mixed-in to a class, this +included+
- * method is used to add our default +induced_from+ implementation
- * to the host class.
- */
-
-static VALUE
-prec_included(VALUE module, SEL sel, VALUE include)
-{
-    switch (TYPE(include)) {
-      case T_CLASS:
-      case T_MODULE:
-       break;
-      default:
-       Check_Type(include, T_CLASS);
-       break;
-    }
-    rb_objc_define_method(*(VALUE *)include, "induced_from", prec_induced_from, 1);
-    return module;
-}
-
-/*
- * Precision is a mixin for concrete numeric classes with
- * precision.  Here, `precision' means the fineness of approximation
- * of a real number, so, this module should not be included into
- * anything which is not a subset of Real (so it should not be
- * included in classes such as +Complex+ or +Matrix+).
-*/
-
-void
-Init_Precision(void)
-{
-    rb_mPrecision = rb_define_module("Precision");
-    rb_objc_define_method(*(VALUE *)rb_mPrecision, "included", prec_included, 1);
-    rb_objc_define_method(rb_mPrecision, "prec", prec_prec, 1);
-    rb_objc_define_method(rb_mPrecision, "prec_i", prec_prec_i, 0);
-    rb_objc_define_method(rb_mPrecision, "prec_f", prec_prec_f, 0);
-
-    prc_pr = rb_intern("prec");
-    prc_if = rb_intern("induced_from");
-}

Deleted: MacRuby/trunk/proc.c
===================================================================
--- MacRuby/trunk/proc.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/proc.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1638 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's proc.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2004-2007 Koichi Sasada
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "class.h"
-
-#define GetCoreDataFromValue(obj, type, ptr) do { \
-    ptr = (type*)DATA_PTR(obj); \
-} while (0)
-
-#define GetProcPtr(obj, ptr) GetCoreDataFromValue(obj, rb_vm_block_t, ptr)
-
-VALUE rb_cUnboundMethod;
-VALUE rb_cMethod;
-VALUE rb_cBinding;
-VALUE rb_cProc;
-
-/* Proc */
-
-VALUE
-rb_proc_alloc(VALUE klass)
-{
-    VALUE obj;
-    rb_vm_block_t *proc;
-    obj = Data_Make_Struct(klass, rb_vm_block_t, NULL, NULL, proc);
-    MEMZERO(proc, rb_vm_block_t, 1);
-    return obj;
-}
-
-VALUE
-rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc)
-{
-    if (proc->proc != Qnil) {
-	return proc->proc;
-    }
-
-    VALUE obj;
-    obj = Data_Wrap_Struct(klass, NULL, NULL, proc);
-    proc->proc = obj; // weak
-    rb_vm_block_make_detachable_proc(proc);
-    return obj;
-}
-
-static inline bool
-rb_obj_is_proc(VALUE obj)
-{
-    return CLASS_OF(obj) == rb_cProc;
-}
-
-static inline bool
-rb_obj_is_method(VALUE obj)
-{
-    return CLASS_OF(obj) == rb_cMethod;
-}
-
-static VALUE
-proc_dup(VALUE self, SEL sel)
-{
-    rb_vm_block_t *src;
-    GetProcPtr(self, src);
-    return Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, src);
-}
-
-static VALUE
-proc_clone(VALUE self, SEL sel)
-{
-    VALUE procval = proc_dup(self, 0);
-    CLONESETUP(procval, self);
-    return procval;
-}
-
-/*
- * call-seq:
- *   prc.lambda? => true or false
- *
- * Returns true for a Proc object which argument handling is rigid.
- * Such procs are typically generated by lambda.
- *
- * A Proc object generated by proc ignore extra arguments.
- *
- *   proc {|a,b| [a,b] }.call(1,2,3)    => [1,2]
- *
- * It provides nil for lacked arguments.
- *
- *   proc {|a,b| [a,b] }.call(1)        => [1,nil]
- *
- * It expand single-array argument.
- *
- *   proc {|a,b| [a,b] }.call([1,2])    => [1,2]
- *
- * A Proc object generated by lambda doesn't have such tricks.
- *
- *   lambda {|a,b| [a,b] }.call(1,2,3)  => ArgumentError
- *   lambda {|a,b| [a,b] }.call(1)      => ArgumentError
- *   lambda {|a,b| [a,b] }.call([1,2])  => ArgumentError
- *
- * Proc#lambda? is a predicate for the tricks.
- * It returns true if no tricks.
- *
- *   lambda {}.lambda?          => true
- *   proc {}.lambda?            => false
- *
- * Proc.new is same as proc.
- *
- *   Proc.new {}.lambda?        => false
- *
- * lambda, proc and Proc.new preserves the tricks of
- * a Proc object given by & argument.
- *
- *   lambda(&lambda {}).lambda?   => true
- *   proc(&lambda {}).lambda?     => true
- *   Proc.new(&lambda {}).lambda? => true
- *
- *   lambda(&proc {}).lambda?   => false
- *   proc(&proc {}).lambda?     => false
- *   Proc.new(&proc {}).lambda? => false
- *
- * A Proc object generated by & argument has the tricks
- *
- *   def n(&b) b.lambda? end
- *   n {}                       => false
- *
- * The & argument preserves the tricks if a Proc object is given
- * by & argument.
- *
- *   n(&lambda {})              => true
- *   n(&proc {})                => false
- *   n(&Proc.new {})            => false
- *
- * A Proc object converted from a method has no tricks.
- *
- *   def m() end
- *   method(:m).to_proc.lambda? => true
- *
- *   n(&method(:m))             => true
- *   n(&method(:m).to_proc)     => true
- *
- * define_method is treated same as method definition.
- * The defined method has no tricks.
- *
- *   class C
- *     define_method(:d) {}
- *   end
- *   C.new.e(1,2)       => ArgumentError
- *   C.new.method(:d).to_proc.lambda?   => true
- *
- * define_method always defines a method without the tricks,
- * even if a non-lambda Proc object is given.
- * This is the only exception which the tricks are not preserved.
- *
- *   class C
- *     define_method(:e, &proc {})
- *   end
- *   C.new.e(1,2)       => ArgumentError
- *   C.new.method(:e).to_proc.lambda?   => true
- *
- * This exception is for a wrapper of define_method.
- * It eases defining a method defining method which defines a usual method which has no tricks.
- *
- *   class << C
- *     def def2(name, &body)
- *       define_method(name, &body)
- *     end
- *   end
- *   class C
- *     def2(:f) {}
- *   end
- *   C.new.f(1,2)       => ArgumentError
- *
- * The wrapper, def2, defines a method which has no tricks.
- *
- */
-
-static VALUE
-proc_lambda_p(VALUE procval, SEL sel)
-{
-    rb_vm_block_t *proc;
-    GetProcPtr(procval, proc);
-
-    return (proc->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA
-	? Qtrue : Qfalse;
-}
-
-/* Binding */
-
-static VALUE
-binding_alloc(VALUE klass)
-{
-    VALUE obj;
-    rb_vm_binding_t *bind;
-    obj = Data_Make_Struct(klass, rb_vm_binding_t,
-			   NULL, NULL, bind);
-    return obj;
-}
-
-static VALUE
-binding_dup(VALUE self, SEL sel)
-{
-    VALUE bindval = binding_alloc(rb_cBinding);
-#if 0 // TODO
-    rb_binding_t *src, *dst;
-    GetBindingPtr(self, src);
-    GetBindingPtr(bindval, dst);
-    dst->env = src->env;
-#endif
-    return bindval;
-}
-
-static VALUE
-binding_clone(VALUE self, SEL sel)
-{
-    VALUE bindval = binding_dup(self, 0);
-    CLONESETUP(bindval, self);
-    return bindval;
-}
-
-VALUE
-rb_binding_new(void)
-{
-    rb_vm_binding_t *bind = rb_vm_current_binding();
-    assert(bind != NULL);
-    return Data_Wrap_Struct(rb_cBinding, NULL, NULL, bind);
-}
-
-VALUE
-rb_binding_new_from_binding(rb_vm_binding_t *bind)
-{
-    return Data_Wrap_Struct(rb_cBinding, NULL, NULL, bind);
-}
-
-/*
- *  call-seq:
- *     binding -> a_binding
- *  
- *  Returns a +Binding+ object, describing the variable and
- *  method bindings at the point of call. This object can be used when
- *  calling +eval+ to execute the evaluated command in this
- *  environment. Also see the description of class +Binding+.
- *     
- *     def getBinding(param)
- *       return binding
- *     end
- *     b = getBinding("hello")
- *     eval("param", b)   #=> "hello"
- */
-
-static VALUE
-rb_f_binding(VALUE self, SEL sel)
-{
-    return rb_binding_new();
-}
-
-/*
- *  call-seq:
- *     binding.eval(string [, filename [,lineno]])  => obj
- *
- *  Evaluates the Ruby expression(s) in <em>string</em>, in the
- *  <em>binding</em>'s context.  If the optional <em>filename</em> and
- *  <em>lineno</em> parameters are present, they will be used when
- *  reporting syntax errors.
- *
- *     def getBinding(param)
- *       return binding
- *     end
- *     b = getBinding("hello")
- *     b.eval("param")   #=> "hello"
- */
-
-VALUE rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv);
-
-static VALUE
-bind_eval(VALUE bindval, SEL sel, int argc, VALUE *argv)
-{
-    VALUE args[4];
-
-    rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
-    args[1] = bindval;
-    return rb_f_eval(Qnil, 0, argc+1, args /* self will be searched in eval */);
-}
-
-static VALUE
-proc_new(VALUE klass, bool is_lambda)
-{
-    rb_vm_block_t *block = rb_vm_first_block();
-    if (block == NULL) {
-	rb_raise(rb_eArgError,
-		"tried to create Proc object without a block");
-    }
-    if (is_lambda) {
-	block->flags |= VM_BLOCK_LAMBDA;
-    }
-    return rb_proc_alloc_with_block(klass, block);
-}
-
-/*
- *  call-seq:
- *     Proc.new {|...| block } => a_proc
- *     Proc.new                => a_proc
- *  
- *  Creates a new <code>Proc</code> object, bound to the current
- *  context. <code>Proc::new</code> may be called without a block only
- *  within a method with an attached block, in which case that block is
- *  converted to the <code>Proc</code> object.
- *     
- *     def proc_from
- *       Proc.new
- *     end
- *     proc = proc_from { "hello" }
- *     proc.call   #=> "hello"
- */
-
-static VALUE
-rb_proc_s_new(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE block = proc_new(klass, false);
-
-    rb_obj_call_init(block, argc, argv);
-    return block;
-}
-
-/*
- * call-seq:
- *   proc   { |...| block }  => a_proc
- *
- * Equivalent to <code>Proc.new</code>.
- */
-
-VALUE
-rb_block_proc(void)
-{
-    return proc_new(rb_cProc, false);
-}
-
-VALUE
-rb_block_proc_imp(void)
-{
-    return rb_block_proc();
-}
-
-VALUE
-rb_block_lambda(void)
-{
-    return proc_new(rb_cProc, true);
-}
-
-VALUE
-rb_f_lambda(void)
-{
-    rb_warn("rb_f_lambda() is deprecated; use rb_block_proc() instead");
-    return rb_block_lambda();
-}
-
-/*
- * call-seq:
- *   lambda { |...| block }  => a_proc
- *
- * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
- * check the number of parameters passed when called.
- */
-
-static VALUE
-proc_lambda(VALUE klass, SEL sel)
-{
-    return rb_block_lambda();
-}
-
-/* CHECKME: are the argument checking semantics correct? */
-
-/*
- *  call-seq:
- *     prc.call(params,...)   => obj
- *     prc[params,...]        => obj
- *  
- *  Invokes the block, setting the block's parameters to the values in
- *  <i>params</i> using something close to method calling semantics.
- *  Generates a warning if multiple values are passed to a proc that
- *  expects just one (previously this silently converted the parameters
- *  to an array).
- *
- *  For procs created using <code>Kernel.proc</code>, generates an
- *  error if the wrong number of parameters
- *  are passed to a proc with multiple parameters. For procs created using
- *  <code>Proc.new</code>, extra parameters are silently discarded.
- *
- *  Returns the value of the last expression evaluated in the block. See
- *  also <code>Proc#yield</code>.
- *     
- *     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
- *     a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
- *     a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
- *     a_proc = Proc.new {|a,b| a}
- *     a_proc.call(1,2,3)
- *     
- *  <em>produces:</em>
- *     
- *     prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError)
- *     	from prog.rb:4:in `call'
- *     	from prog.rb:5
- */
-
-static VALUE
-proc_call(VALUE procval, SEL sel, int argc, const VALUE *argv)
-{
-#if 0
-    rb_proc_t *proc;
-    rb_block_t *blockptr = 0;
-    GetProcPtr(procval, proc);
-
-    if (BUILTIN_TYPE(proc->block.iseq) != T_NODE &&
-	proc->block.iseq->arg_block != -1) {
-
-	if (rb_block_given_p()) {
-	    rb_proc_t *proc;
-	    VALUE procval;
-	    procval = rb_block_proc();
-	    GetProcPtr(procval, proc);
-	    blockptr = &proc->block;
-	}
-    }
-
-    return vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
-			  argc, argv, blockptr);
-#endif
-    rb_vm_block_t *proc;
-    GetProcPtr(procval, proc);
-    return rb_vm_block_eval(proc, argc, argv);
-}
-
-VALUE
-rb_proc_call(VALUE self, VALUE args)
-{
-#if 0
-    rb_proc_t *proc;
-    GetProcPtr(self, proc);
-    return vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
-			  RARRAY_LEN(args), RARRAY_PTR(args), 0);
-#endif
-    return proc_call(self, 0, RARRAY_LEN(args), RARRAY_PTR(args));
-}
-
-VALUE
-rb_proc_call2(VALUE self, int argc, VALUE *argv)
-{
-    return proc_call(self, 0, argc, argv);
-}
-
-VALUE
-rb_proc_check_and_call(VALUE proc, int argc, VALUE *argv)
-{
-    VALUE tmp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
-    if (NIL_P(tmp)) {
-        rb_raise(rb_eTypeError,
-		"wrong type %s (expected Proc)",
-		rb_obj_classname(proc));
-    }
-    proc = tmp;
-
-    const int arity = rb_proc_arity(proc);
-    if (arity != argc) {
-	rb_raise(rb_eArgError, "expected Proc with %d arguments (got %d)",
-		argc, arity);
-    }
-    return proc_call(proc, 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     prc.arity -> fixnum
- *  
- *  Returns the number of arguments that would not be ignored. If the block
- *  is declared to take no arguments, returns 0. If the block is known
- *  to take exactly n arguments, returns n. If the block has optional
- *  arguments, return -n-1, where n is the number of mandatory
- *  arguments. A <code>proc</code> with no argument declarations
- *  is the same a block declaring <code>||</code> as its arguments.
- *     
- *     Proc.new {}.arity          #=>  0
- *     Proc.new {||}.arity        #=>  0
- *     Proc.new {|a|}.arity       #=>  1
- *     Proc.new {|a,b|}.arity     #=>  2
- *     Proc.new {|a,b,c|}.arity   #=>  3
- *     Proc.new {|*a|}.arity      #=> -1
- *     Proc.new {|a,*b|}.arity    #=> -2
- *     Proc.new {|a,*b, c|}.arity    #=> -3
- */
-
-static inline int
-method_arity(VALUE method)
-{
-    rb_vm_method_t *data;
-    Data_Get_Struct(method, rb_vm_method_t, data);
-    return data->arity;
-}
-
-static VALUE
-proc_arity(VALUE self, SEL sel)
-{
-    return INT2FIX(rb_proc_arity(self));
-}
-
-int
-rb_proc_arity(VALUE proc)
-{
-    rb_vm_block_t *b;
-    GetProcPtr(proc, b);
-    return rb_vm_arity_n(b->arity);
-}
-
-#if 0
-static rb_iseq_t *
-get_proc_iseq(VALUE self)
-{
-    rb_proc_t *proc;
-    rb_iseq_t *iseq;
-
-    GetProcPtr(self, proc);
-    iseq = proc->block.iseq;
-    if (!RUBY_VM_NORMAL_ISEQ_P(iseq))
-	return 0;
-    return iseq;
-}
-
-VALUE
-rb_proc_location(VALUE self)
-{
-    rb_iseq_t *iseq = get_proc_iseq(self);
-    VALUE loc[2];
-
-    if (!iseq) return Qnil;
-    loc[0] = iseq->filename;
-    if (iseq->insn_info_table) {
-	loc[1] = INT2FIX(iseq->insn_info_table[0].line_no);
-    }
-    else {
-	loc[1] = Qnil;
-    }
-    return rb_ary_new4(2, loc);
-}
-#endif
-
-/*
- * call-seq:
- *   prc == other_proc   =>  true or false
- *
- * Return <code>true</code> if <i>prc</i> is the same object as
- * <i>other_proc</i>, or if they are both procs with the same body.
- */
-
-static VALUE
-proc_eq(VALUE self, SEL sel, VALUE other)
-{
-    if (self == other) {
-	return Qtrue;
-    }
-    else if (rb_obj_is_kind_of(other, rb_cProc)) {
-	rb_vm_block_t *self_b, *other_b;
-	GetProcPtr(self, self_b);
-	GetProcPtr(other, other_b);
-	return self_b == other_b ? Qtrue : Qfalse;
-    }
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   prc.hash   =>  integer
- *
- * Return hash value corresponding to proc body.
- */
-
-static VALUE
-proc_hash(VALUE self, SEL sel)
-{
-    rb_vm_block_t *b;
-    GetProcPtr(self, b);
-    return LONG2FIX(b);
-}
-
-/*
- * call-seq:
- *   prc.to_s   => string
- *
- * Shows the unique identifier for this proc, along with
- * an indication of where the proc was defined.
- */
-
-static VALUE
-proc_to_s(VALUE self, SEL sel)
-{
-    const char		*cname = rb_obj_classname(self);
-    rb_vm_block_t	*proc;
-
-    GetProcPtr(self, proc);
-
-    const char *is_lambda = (proc->flags & VM_BLOCK_LAMBDA) ? " (lambda)" : "";
-    VALUE str = rb_sprintf("#<%s:%p%s>", cname, (void *)self, is_lambda);
-
-    if (OBJ_TAINTED(self)) {
-	OBJ_TAINT(str);
-    }
-
-    return str;
-}
-
-#if 0 // TODO
-static VALUE
-proc_to_s(VALUE self, SEL sel)
-{
-    VALUE str = 0;
-    rb_proc_t *proc;
-    const char *cname = rb_obj_classname(self);
-    rb_iseq_t *iseq;
-    const char *is_lambda;
-    
-    GetProcPtr(self, proc);
-    iseq = proc->block.iseq;
-    is_lambda = proc->is_lambda ? " (lambda)" : "";
-
-    if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
-	int line_no = 0;
-	
-	if (iseq->insn_info_table) {
-	    line_no = iseq->insn_info_table[0].line_no;
-	}
-	str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self,
-			 RSTRING_PTR(iseq->filename),
-			 line_no, is_lambda);
-    }
-    else {
-	str = rb_sprintf("#<%s:%p%s>", cname, proc->block.iseq,
-			 is_lambda);
-    }
-
-    if (OBJ_TAINTED(self)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-#endif
-
-/*
- *  call-seq:
- *     prc.to_proc -> prc
- *  
- *  Part of the protocol for converting objects to <code>Proc</code>
- *  objects. Instances of class <code>Proc</code> simply return
- *  themselves.
- */
-
-static VALUE
-proc_to_proc(VALUE self, SEL sel)
-{
-    return self;
-}
-
-NODE *rb_get_method_body(VALUE klass, ID id, ID *idp);
-void rb_print_undef(VALUE klass, ID id, int scope);
-
-static inline VALUE
-mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
-{
-    rb_vm_method_t *m = rb_vm_get_method(klass, obj, id, scope);
-    assert(m != NULL);
-
-    if (m->node) {
-	const int flag = m->node->flags & NOEX_MASK;
-	if (scope && flag != NOEX_PUBLIC) {
-	    const char *v = "";
-	    switch (flag) {
-	      case NOEX_PRIVATE:
-		v = "private";
-		break;
-	      case NOEX_PROTECTED:
-		v = "protected";
-		break;
-	    }
-	    rb_name_error(id, "method `%s' for %s `%s' is %s",
-			  rb_id2name(id),
-			  (TYPE(klass) == T_MODULE) ? "module" : "class",
-			  rb_class2name(klass),
-			  v);
-	}
-    }
-
-    return Data_Wrap_Struct(mclass, NULL, NULL, m);
-}
-
-/**********************************************************************
- *
- * Document-class : Method
- *
- *  Method objects are created by <code>Object#method</code>, and are
- *  associated with a particular object (not just with a class). They
- *  may be used to invoke the method within the object, and as a block
- *  associated with an iterator. They may also be unbound from one
- *  object (creating an <code>UnboundMethod</code>) and bound to
- *  another.
- *     
- *     class Thing
- *       def square(n)
- *         n*n
- *       end
- *     end
- *     thing = Thing.new
- *     meth  = thing.method(:square)
- *     
- *     meth.call(9)                 #=> 81
- *     [ 1, 2, 3 ].collect(&meth)   #=> [1, 4, 9]
- *     
- */
-
-/*
- * call-seq:
- *   meth == other_meth  => true or false
- *
- * Two method objects are equal if that are bound to the same
- * object and contain the same body.
- */
-
-
-static VALUE
-method_eq(VALUE method, SEL sel, VALUE other)
-{
-    rb_vm_method_t *m1, *m2;
-
-    if (CLASS_OF(method) != CLASS_OF(other)) {
-	return Qfalse;
-    }
-
-    Data_Get_Struct(method, rb_vm_method_t, m1);
-    Data_Get_Struct(other, rb_vm_method_t, m2);
-
-    if (m1->oclass != m2->oclass
-	|| m1->rclass != m2->rclass
-	|| m1->recv != m2->recv) {
-	return Qfalse;
-    }
-
-    IMP m1_imp = m1->node == NULL
-	? class_getMethodImplementation((Class)m1->oclass, m1->sel)
-	: m1->node->objc_imp;
-    IMP m2_imp = m2->node == NULL
-	? class_getMethodImplementation((Class)m2->oclass, m2->sel)
-	: m2->node->objc_imp;
-    if (m1_imp != m2_imp) {
-	return Qfalse;
-    }
-
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *    meth.hash   => integer
- *
- * Return a hash value corresponding to the method object.
- */
-
-static VALUE
-method_hash(VALUE method, SEL sel)
-{
-    rb_vm_method_t *m;
-    long hash;
-
-    Data_Get_Struct(method, rb_vm_method_t, m);
-    hash = (long)m->oclass;
-    hash ^= (long)m->rclass;
-    hash ^= (long)m->recv;
-    hash ^= (long)m->node;
-
-    return INT2FIX(hash);
-}
-
-/*
- *  call-seq:
- *     meth.unbind    => unbound_method
- *  
- *  Dissociates <i>meth</i> from it's current receiver. The resulting
- *  <code>UnboundMethod</code> can subsequently be bound to a new object
- *  of the same class (see <code>UnboundMethod</code>).
- */
-
-static VALUE
-method_unbind(VALUE obj, SEL sel)
-{
-    VALUE method;
-    rb_vm_method_t *orig, *data;
-
-    Data_Get_Struct(obj, rb_vm_method_t, orig);
-    method =
-	Data_Make_Struct(rb_cUnboundMethod, rb_vm_method_t, NULL, NULL, data);
-    data->oclass = orig->oclass;
-    data->recv = Qundef;
-    data->node = orig->node;
-    data->rclass = orig->rclass;
-    data->sel = orig->sel;
-    data->cache = orig->cache;
-    data->arity = orig->arity;
-
-    return method;
-}
-
-/*
- *  call-seq:
- *     meth.receiver    => object
- *  
- *  Returns the bound receiver of the method object.
- */
-
-static VALUE
-method_receiver(VALUE obj, SEL sel)
-{
-    rb_vm_method_t *data;
-    Data_Get_Struct(obj, rb_vm_method_t, data);
-    return data->recv;
-}
-
-/*
- *  call-seq:
- *     meth.name    => symbol
- *  
- *  Returns the name of the method.
- */
-
-static VALUE
-method_name(VALUE obj, SEL sel)
-{
-    rb_vm_method_t *data;
-    Data_Get_Struct(obj, rb_vm_method_t, data);
-    ID mid = rb_intern(sel_getName(data->sel));
-    return ID2SYM(mid);
-}
-
-/*
- *  call-seq:
- *     meth.owner    => class_or_module
- *  
- *  Returns the class or module that defines the method.
- */
-
-static VALUE
-method_owner(VALUE obj, SEL sel)
-{
-    rb_vm_method_t *data;
-    Data_Get_Struct(obj, rb_vm_method_t, data);
-    return data->oclass;
-}
-
-/*
- *  call-seq:
- *     obj.method(sym)    => method
- *  
- *  Looks up the named method as a receiver in <i>obj</i>, returning a
- *  <code>Method</code> object (or raising <code>NameError</code>). The
- *  <code>Method</code> object acts as a closure in <i>obj</i>'s object
- *  instance, so instance variables and the value of <code>self</code>
- *  remain available.
- *     
- *     class Demo
- *       def initialize(n)
- *         @iv = n
- *       end
- *       def hello()
- *         "Hello, @iv = #{@iv}"
- *       end
- *     end
- *     
- *     k = Demo.new(99)
- *     m = k.method(:hello)
- *     m.call   #=> "Hello, @iv = 99"
- *     
- *     l = Demo.new('Fred')
- *     m = l.method("hello")
- *     m.call   #=> "Hello, @iv = Fred"
- */
-
-static VALUE
-rb_obj_method(VALUE obj, SEL sel, VALUE vid)
-{
-    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qfalse);
-}
-
-static VALUE
-rb_obj_public_method(VALUE obj, SEL sel, VALUE vid)
-{
-    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qtrue);
-}
-
-/*
- *  call-seq:
- *     mod.instance_method(symbol)   => unbound_method
- *  
- *  Returns an +UnboundMethod+ representing the given
- *  instance method in _mod_.
- *     
- *     class Interpreter
- *       def do_a() print "there, "; end
- *       def do_d() print "Hello ";  end
- *       def do_e() print "!\n";     end
- *       def do_v() print "Dave";    end
- *       Dispatcher = {
- *        ?a => instance_method(:do_a),
- *        ?d => instance_method(:do_d),
- *        ?e => instance_method(:do_e),
- *        ?v => instance_method(:do_v)
- *       }
- *       def interpret(string)
- *         string.each_byte {|b| Dispatcher[b].bind(self).call }
- *       end
- *     end
- *     
- *     
- *     interpreter = Interpreter.new
- *     interpreter.interpret('dave')
- *     
- *  <em>produces:</em>
- *     
- *     Hello there, Dave!
- */
-
-static VALUE
-rb_mod_instance_method(VALUE mod, SEL sel, VALUE vid)
-{
-    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qfalse);
-}
-
-static VALUE
-rb_mod_public_instance_method(VALUE mod, SEL sel, VALUE vid)
-{
-    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qtrue);
-}
-
-/*
- *  call-seq:
- *     define_method(symbol, method)     => new_method
- *     define_method(symbol) { block }   => proc
- *  
- *  Defines an instance method in the receiver. The _method_
- *  parameter can be a +Proc+ or +Method+ object.
- *  If a block is specified, it is used as the method body. This block
- *  is evaluated using <code>instance_eval</code>, a point that is
- *  tricky to demonstrate because <code>define_method</code> is private.
- *  (This is why we resort to the +send+ hack in this example.)
- *     
- *     class A
- *       def fred
- *         puts "In Fred"
- *       end
- *       def create_method(name, &block)
- *         self.class.send(:define_method, name, &block)
- *       end
- *       define_method(:wilma) { puts "Charge it!" }
- *     end
- *     class B < A
- *       define_method(:barney, instance_method(:fred))
- *     end
- *     a = B.new
- *     a.barney
- *     a.wilma
- *     a.create_method(:betty) { p self }
- *     a.betty
- *     
- *  <em>produces:</em>
- *     
- *     In Fred
- *     Charge it!
- *     #<B:0x401b39e8>
- */
-
-static VALUE
-rb_mod_define_method(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-#if MACRUBY_STATIC
-    not_implemented_in_static(sel);
-#else
-    ID id;
-    VALUE body;
-
-    if (argc == 1) {
-	id = rb_to_id(argv[0]);
-	body = rb_block_lambda();
-    }
-    else if (argc == 2) {
-	id = rb_to_id(argv[0]);
-	body = argv[1];
-	if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) {
-	    rb_raise(rb_eTypeError,
-		     "wrong argument type %s (expected Proc/Method)",
-		     rb_obj_classname(body));
-	}
-    }
-    else {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-
-    if (rb_obj_is_method(body)) {
-	rb_vm_method_t *data;
-	Data_Get_Struct(body, rb_vm_method_t, data);
-	if (data->node == NULL) {
-	    rb_raise(rb_eArgError, "cannot use Method object of pure Objective-C method");
-	}
-	SEL msel = rb_vm_id_to_sel(id, data->arity);
-	rb_vm_define_method2((Class)mod, msel, data->node, data->node->flags, false);
-    }
-    else {
-	rb_vm_block_t *proc;
-	GetProcPtr(body, proc);
-	rb_vm_define_method3((Class)mod, id, proc);
-    }
-
-    return body;
-#endif
-}
-
-static VALUE
-rb_obj_define_method(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE klass = rb_singleton_class(obj);
-
-    return rb_mod_define_method(klass, 0, argc, argv);
-}
-
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-method_clone(VALUE self, SEL sel)
-{
-    VALUE clone;
-    rb_vm_method_t *orig, *data;
-
-    Data_Get_Struct(self, rb_vm_method_t, orig);
-    clone =
-	Data_Make_Struct(CLASS_OF(self), rb_vm_method_t, NULL, NULL, data);
-    CLONESETUP(clone, self);
-    *data = *orig;
-    GC_WB(&data->recv, orig->recv);
-
-    return clone;
-}
-
-/*
- *  call-seq:
- *     meth.call(args, ...)    => obj
- *     meth[args, ...]         => obj
- *  
- *  Invokes the <i>meth</i> with the specified arguments, returning the
- *  method's return value.
- *     
- *     m = 12.method("+")
- *     m.call(3)    #=> 15
- *     m.call(20)   #=> 32
- */
-
-VALUE
-rb_method_call(VALUE method, SEL sel, int argc, VALUE *argv)
-{
-    rb_vm_method_t *data;
-
-    Data_Get_Struct(method, rb_vm_method_t, data);
-    if (data->recv == Qundef) {
-	rb_raise(rb_eTypeError, "can't call unbound method; bind first");
-    }
-    
-    int safe = -1;
-    if (OBJ_TAINTED(method)) {
-	safe = rb_safe_level();
-	if (rb_safe_level() < 4) {
-	    rb_set_safe_level_force(4);
-	}
-    }
-
-    VALUE result = rb_vm_method_call(data, NULL, argc, argv);
-
-    if (safe >= 0) {
-	rb_set_safe_level_force(safe);
-    }
-
-    return result;
-}
-
-/**********************************************************************
- *
- * Document-class: UnboundMethod
- *
- *  Ruby supports two forms of objectified methods. Class
- *  <code>Method</code> is used to represent methods that are associated
- *  with a particular object: these method objects are bound to that
- *  object. Bound method objects for an object can be created using
- *  <code>Object#method</code>.
- *     
- *  Ruby also supports unbound methods; methods objects that are not
- *  associated with a particular object. These can be created either by
- *  calling <code>Module#instance_method</code> or by calling
- *  <code>unbind</code> on a bound method object. The result of both of
- *  these is an <code>UnboundMethod</code> object.
- *     
- *  Unbound methods can only be called after they are bound to an
- *  object. That object must be be a kind_of? the method's original
- *  class.
- *     
- *     class Square
- *       def area
- *         @side * @side
- *       end
- *       def initialize(side)
- *         @side = side
- *       end
- *     end
- *     
- *     area_un = Square.instance_method(:area)
- *     
- *     s = Square.new(12)
- *     area = area_un.bind(s)
- *     area.call   #=> 144
- *     
- *  Unbound methods are a reference to the method at the time it was
- *  objectified: subsequent changes to the underlying class will not
- *  affect the unbound method.
- *     
- *     class Test
- *       def test
- *         :original
- *       end
- *     end
- *     um = Test.instance_method(:test)
- *     class Test
- *       def test
- *         :modified
- *       end
- *     end
- *     t = Test.new
- *     t.test            #=> :modified
- *     um.bind(t).call   #=> :original
- *     
- */
-
-/*
- *  call-seq:
- *     umeth.bind(obj) -> method
- *  
- *  Bind <i>umeth</i> to <i>obj</i>. If <code>Klass</code> was the class
- *  from which <i>umeth</i> was obtained,
- *  <code>obj.kind_of?(Klass)</code> must be true.
- *     
- *     class A
- *       def test
- *         puts "In test, class = #{self.class}"
- *       end
- *     end
- *     class B < A
- *     end
- *     class C < B
- *     end
- *     
- *     
- *     um = B.instance_method(:test)
- *     bm = um.bind(C.new)
- *     bm.call
- *     bm = um.bind(B.new)
- *     bm.call
- *     bm = um.bind(A.new)
- *     bm.call
- *     
- *  <em>produces:</em>
- *     
- *     In test, class = C
- *     In test, class = B
- *     prog.rb:16:in `bind': bind argument must be an instance of B (TypeError)
- *     	from prog.rb:16
- */
-
-static VALUE
-umethod_bind(VALUE method, SEL sel, VALUE recv)
-{
-    rb_vm_method_t *data, *bound;
-
-    Data_Get_Struct(method, rb_vm_method_t, data);
-    if (data->rclass != CLASS_OF(recv)) {
-	if (RCLASS_SINGLETON(data->rclass)) {
-	    rb_raise(rb_eTypeError,
-		     "singleton method called for a different object");
-	}
-	if (!rb_obj_is_kind_of(recv, data->rclass)) {
-	    rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
-		     rb_class2name(data->rclass));
-	}
-    }
-
-    method = Data_Make_Struct(rb_cMethod, rb_vm_method_t, NULL, NULL, bound);
-    *bound = *data;
-    GC_WB(&bound->recv, recv);
-    bound->rclass = CLASS_OF(recv);
-
-    return method;
-}
-
-int
-rb_node_arity(NODE* body)
-{
-    // TODO should be replaced by the roxor.cpp's stuff
-    switch (nd_type(body)) {
-	case NODE_CFUNC:
-	    if (body->nd_argc < 0) {
-		return -1;
-	    }
-	    return body->nd_argc;
-	case NODE_ZSUPER:
-	    return -1;
-	case NODE_ATTRSET:
-	    return 1;
-	case NODE_IVAR:
-	    return 0;
-	case NODE_BMETHOD:
-	    return rb_proc_arity(body->nd_cval);
-	default:
-	    rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
-    }
-}
-
-/*
- *  call-seq:
- *     meth.arity    => fixnum
- *  
- *  Returns an indication of the number of arguments accepted by a
- *  method. Returns a nonnegative integer for methods that take a fixed
- *  number of arguments. For Ruby methods that take a variable number of
- *  arguments, returns -n-1, where n is the number of required
- *  arguments. For methods written in C, returns -1 if the call takes a
- *  variable number of arguments.
- *     
- *     class C
- *       def one;    end
- *       def two(a); end
- *       def three(*a);  end
- *       def four(a, b); end
- *       def five(a, b, *c);    end
- *       def six(a, b, *c, &d); end
- *     end
- *     c = C.new
- *     c.method(:one).arity     #=> 0
- *     c.method(:two).arity     #=> 1
- *     c.method(:three).arity   #=> -1
- *     c.method(:four).arity    #=> 2
- *     c.method(:five).arity    #=> -3
- *     c.method(:six).arity     #=> -3
- *     
- *     "cat".method(:size).arity      #=> 0
- *     "cat".method(:replace).arity   #=> 1
- *     "cat".method(:squeeze).arity   #=> -1
- *     "cat".method(:count).arity     #=> -1
- */
-
-static VALUE
-method_arity_m(VALUE method, SEL sel)
-{
-    int n = method_arity(method);
-    return INT2FIX(n);
-}
-
-/*
- *  call-seq:
- *   meth.to_s      =>  string
- *   meth.inspect   =>  string
- *
- *  Show the name of the underlying method.
- *
- *    "cat".method(:count).inspect   #=> "#<Method: String#count>"
- */
-
-static VALUE
-method_inspect(VALUE method, SEL sel)
-{
-    rb_vm_method_t *data;
-    VALUE str;
-    const char *s;
-    const char *sharp = "#";
-
-    Data_Get_Struct(method, rb_vm_method_t, data);
-    str = rb_str_buf_new2("#<");
-    s = rb_obj_classname(method);
-    rb_str_buf_cat2(str, s);
-    rb_str_buf_cat2(str, ": ");
-
-    rb_str_buf_cat2(str, rb_class2name(data->rclass));
-    if (data->rclass != data->oclass) {
-	rb_str_buf_cat2(str, "(");
-	rb_str_buf_cat2(str, rb_class2name(data->oclass));
-	rb_str_buf_cat2(str, ")");
-    }
-    rb_str_buf_cat2(str, sharp);
-    rb_str_buf_cat2(str, sel_getName(data->sel));
-    rb_str_buf_cat2(str, ">");
-
-    return str;
-}
-
-#if 0
-static VALUE
-mproc(VALUE method)
-{
-    return rb_funcall(Qnil, rb_intern("proc"), 0);
-}
-
-static VALUE
-mlambda(VALUE method)
-{
-    return rb_funcall(Qnil, rb_intern("lambda"), 0);
-}
-#endif
-
-#if 0
-static VALUE
-bmcall(VALUE args, VALUE method)
-{
-    volatile VALUE a;
-
-#if WITH_OBJC
-    if (TYPE(args) != T_ARRAY) {
-    	return rb_method_call(1, &args, method);
-    }
-#else
-    if (CLASS_OF(args) != rb_cArray) {
-	args = rb_ary_new3(1, args);
-    }
-#endif
-
-    a = args;
-    return rb_method_call(RARRAY_LEN(a), (VALUE *)RARRAY_PTR(a), method);
-}
-#endif
-
-/*
- *  call-seq:
- *     meth.to_proc    => prc
- *  
- *  Returns a <code>Proc</code> object corresponding to this method.
- */
-
-static VALUE
-method_proc(VALUE method, SEL sel)
-{
-    rb_vm_method_t *data;
-    Data_Get_Struct(method, rb_vm_method_t, data);
-    rb_vm_block_t *block = rb_vm_create_block_from_method(data);
-    return rb_proc_alloc_with_block(rb_cProc, block);
-}
-
-/*
- * call_seq:
- *   local_jump_error.exit_value  => obj
- *
- * Returns the exit value associated with this +LocalJumpError+.
- */
-static VALUE
-localjump_xvalue(VALUE exc, SEL sel)
-{
-    return rb_iv_get(exc, "@exit_value");
-}
-
-/*
- * call-seq:
- *    local_jump_error.reason   => symbol
- *
- * The reason this block was terminated:
- * :break, :redo, :retry, :next, :return, or :noreason.
- */
-
-static VALUE
-localjump_reason(VALUE exc, SEL sel)
-{
-    return rb_iv_get(exc, "@reason");
-}
-
-/*
- *  call-seq:
- *     prc.binding    => binding
- *  
- *  Returns the binding associated with <i>prc</i>. Note that
- *  <code>Kernel#eval</code> accepts either a <code>Proc</code> or a
- *  <code>Binding</code> object as its second parameter.
- *     
- *     def fred(param)
- *       proc {}
- *     end
- *     
- *     b = fred(99)
- *     eval("param", b.binding)   #=> 99
- */
-static VALUE
-proc_binding(VALUE self, SEL sel)
-{
-    rb_vm_block_t *block;
-    GetProcPtr(self, block);
-
-    rb_vm_binding_t *binding = (rb_vm_binding_t *)xmalloc(
-	    sizeof(rb_vm_binding_t));
-
-    binding->block = NULL;
-    GC_WB(&binding->self, block->self);
-    GC_WB(&binding->locals, block->locals);
-
-    return Data_Wrap_Struct(rb_cBinding, NULL, NULL, binding);
-}
-
- /*
-  *  call-seq:
-  *     prc.curry         => a_proc
-  *     prc.curry(arity)  => a_proc
-  *
-  *  Returns a curried proc. If the optional <i>arity</i> argument is given,
-  *  it determines the number of arguments.
-  *  A curried proc receives some arguments. If a sufficient number of
-  *  arguments are supplied, it passes the supplied arguments to the original
-  *  proc and returns the result. Otherwise, returns another curried proc that
-  *  takes the rest of arguments.
-  *
-  *     b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
-  *     p b.curry[1][2][3]           #=> 6
-  *     p b.curry[1, 2][3, 4]        #=> 6
-  *     p b.curry(5)[1][2][3][4][5]  #=> 6
-  *     p b.curry(5)[1, 2][3, 4][5]  #=> 6
-  *     p b.curry(1)[1]              #=> 1
-  *
-  *     b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
-  *     p b.curry[1][2][3]           #=> 6
-  *     p b.curry[1, 2][3, 4]        #=> 10
-  *     p b.curry(5)[1][2][3][4][5]  #=> 15
-  *     p b.curry(5)[1, 2][3, 4][5]  #=> 15
-  *     p b.curry(1)[1]              #=> 1
-  *
-  *     b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
-  *     p b.curry[1][2][3]           #=> 6
-  *     p b.curry[1, 2][3, 4]        #=> wrong number of arguments (4 or 3)
-  *     p b.curry(5)                 #=> wrong number of arguments (5 or 3)
-  *     p b.curry(1)                 #=> wrong number of arguments (1 or 3)
-  *
-  *     b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
-  *     p b.curry[1][2][3]           #=> 6
-  *     p b.curry[1, 2][3, 4]        #=> 10
-  *     p b.curry(5)[1][2][3][4][5]  #=> 15
-  *     p b.curry(5)[1, 2][3, 4][5]  #=> 15
-  *     p b.curry(1)                 #=> wrong number of arguments (1 or 3)
-  *
-  *     b = proc { :foo }
-  *     p b.curry[]                  #=> :foo
-  */
-static VALUE
-proc_curry(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    int sarity, marity = FIX2INT(proc_arity(self, 0));
-    VALUE arity, opt = Qfalse;
-
-    if (marity < 0) {
-	marity = -marity - 1;
-	opt = Qtrue;
-    }
-
-    rb_scan_args(argc, argv, "01", &arity);
-    if (NIL_P(arity)) {
-	arity = INT2FIX(marity);
-    }
-    else {
-	sarity = FIX2INT(arity);
-	if (proc_lambda_p(self, 0) && (sarity < marity || (sarity > marity && !opt))) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", sarity, marity);
-	}
-    }
-
-    return rb_vm_make_curry_proc(self, rb_ary_new(), arity);
-}
-
-/*
- *  <code>Proc</code> objects are blocks of code that have been bound to
- *  a set of local variables. Once bound, the code may be called in
- *  different contexts and still access those variables.
- *     
- *     def gen_times(factor)
- *       return Proc.new {|n| n*factor }
- *     end
- *     
- *     times3 = gen_times(3)
- *     times5 = gen_times(5)
- *     
- *     times3.call(12)               #=> 36
- *     times5.call(5)                #=> 25
- *     times3.call(times5.call(4))   #=> 60
- *     
- */
-
-extern VALUE sysstack_error; // defined in eval.c for WTF reason
-
-void
-Init_Proc(void)
-{
-    /* Proc */
-    rb_cProc = rb_define_class("Proc", rb_cObject);
-    rb_undef_alloc_func(rb_cProc);
-    rb_objc_define_method(*(VALUE *)rb_cProc, "new", rb_proc_s_new, -1);
-    rb_objc_define_method(rb_cProc, "call", proc_call, -1);
-    rb_objc_define_method(rb_cProc, "[]", proc_call, -1);
-    rb_objc_define_method(rb_cProc, "===", proc_call, -1);
-    rb_objc_define_method(rb_cProc, "yield", proc_call, -1);
-    rb_objc_define_method(rb_cProc, "to_proc", proc_to_proc, 0);
-    rb_objc_define_method(rb_cProc, "arity", proc_arity, 0);
-    rb_objc_define_method(rb_cProc, "clone", proc_clone, 0);
-    rb_objc_define_method(rb_cProc, "dup", proc_dup, 0);
-    rb_objc_define_method(rb_cProc, "==", proc_eq, 1);
-    rb_objc_define_method(rb_cProc, "eql?", proc_eq, 1);
-    rb_objc_define_method(rb_cProc, "hash", proc_hash, 0);
-    rb_objc_define_method(rb_cProc, "to_s", proc_to_s, 0);
-    rb_objc_define_method(rb_cProc, "lambda?", proc_lambda_p, 0);
-    rb_objc_define_method(rb_cProc, "binding", proc_binding, 0);
-    rb_objc_define_method(rb_cProc, "curry", proc_curry, -1);
-
-    /* Exceptions */
-    rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
-    rb_objc_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0);
-    rb_objc_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
-
-    rb_eSysStackError = rb_define_class("SystemStackError", rb_eException);
-    sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
-    OBJ_TAINT(sysstack_error);
-    GC_RETAIN(sysstack_error);
-
-    /* utility functions */
-    rb_objc_define_module_function(rb_mKernel, "proc", rb_block_proc_imp, 0);
-    rb_objc_define_module_function(rb_mKernel, "lambda", proc_lambda, 0);
-
-    /* Method */
-    rb_cMethod = rb_define_class("Method", rb_cObject);
-    rb_undef_alloc_func(rb_cMethod);
-    rb_undef_method(CLASS_OF(rb_cMethod), "new");
-    rb_objc_define_method(rb_cMethod, "==", method_eq, 1);
-    rb_objc_define_method(rb_cMethod, "eql?", method_eq, 1);
-    rb_objc_define_method(rb_cMethod, "hash", method_hash, 0);
-    rb_objc_define_method(rb_cMethod, "clone", method_clone, 0);
-    rb_objc_define_method(rb_cMethod, "call", rb_method_call, -1);
-    rb_objc_define_method(rb_cMethod, "[]", rb_method_call, -1);
-    rb_objc_define_method(rb_cMethod, "arity", method_arity_m, 0);
-    rb_objc_define_method(rb_cMethod, "inspect", method_inspect, 0);
-    rb_objc_define_method(rb_cMethod, "to_s", method_inspect, 0);
-    rb_objc_define_method(rb_cMethod, "to_proc", method_proc, 0);
-    rb_objc_define_method(rb_cMethod, "receiver", method_receiver, 0);
-    rb_objc_define_method(rb_cMethod, "name", method_name, 0);
-    rb_objc_define_method(rb_cMethod, "owner", method_owner, 0);
-    rb_objc_define_method(rb_cMethod, "unbind", method_unbind, 0);
-
-    rb_objc_define_method(rb_mKernel, "method", rb_obj_method, 1);
-    rb_objc_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
-
-    /* UnboundMethod */
-    rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject);
-    rb_undef_alloc_func(rb_cUnboundMethod);
-    rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new");
-    rb_objc_define_method(rb_cUnboundMethod, "==", method_eq, 1);
-    rb_objc_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
-    rb_objc_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "name", method_name, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
-    rb_objc_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
-
-    /* Module#*_method */
-    rb_objc_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);
-    rb_objc_define_method(rb_cModule, "public_instance_method", rb_mod_public_instance_method, 1);
-    rb_objc_define_private_method(rb_cModule, "define_method", rb_mod_define_method, -1);
-
-    /* Kernel */
-    rb_objc_define_method(rb_mKernel, "define_singleton_method", rb_obj_define_method, -1);
-}
-
-/*
- *  Objects of class <code>Binding</code> encapsulate the execution
- *  context at some particular place in the code and retain this context
- *  for future use. The variables, methods, value of <code>self</code>,
- *  and possibly an iterator block that can be accessed in this context
- *  are all retained. Binding objects can be created using
- *  <code>Kernel#binding</code>, and are made available to the callback
- *  of <code>Kernel#set_trace_func</code>.
- *     
- *  These binding objects can be passed as the second argument of the
- *  <code>Kernel#eval</code> method, establishing an environment for the
- *  evaluation.
- *     
- *     class Demo
- *       def initialize(n)
- *         @secret = n
- *       end
- *       def getBinding
- *         return binding()
- *       end
- *     end
- *     
- *     k1 = Demo.new(99)
- *     b1 = k1.getBinding
- *     k2 = Demo.new(-3)
- *     b2 = k2.getBinding
- *     
- *     eval("@secret", b1)   #=> 99
- *     eval("@secret", b2)   #=> -3
- *     eval("@secret")       #=> nil
- *     
- *  Binding objects have no class-specific methods.
- *     
- */
-
-void
-Init_Binding(void)
-{
-    rb_cBinding = rb_define_class("Binding", rb_cObject);
-    rb_undef_alloc_func(rb_cBinding);
-    rb_undef_method(CLASS_OF(rb_cBinding), "new");
-    rb_objc_define_method(rb_cBinding, "clone", binding_clone, 0);
-    rb_objc_define_method(rb_cBinding, "dup", binding_dup, 0);
-    rb_objc_define_method(rb_cBinding, "eval", bind_eval, -1);
-    rb_objc_define_module_function(rb_mKernel, "binding", rb_f_binding, 0);
-
-    rb_vm_binding_t *binding = (rb_vm_binding_t *)xmalloc(
-	    sizeof(rb_vm_binding_t));
-    GC_WB(&binding->self, rb_vm_top_self());
-    rb_define_global_const("TOPLEVEL_BINDING",
-	    rb_binding_new_from_binding(binding));
-}
-

Deleted: MacRuby/trunk/process.c
===================================================================
--- MacRuby/trunk/process.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/process.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,5242 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/signal.h"
-#include "ruby/io.h"
-#include "ruby/util.h"
-#include "id.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef __DJGPP__
-#include <process.h>
-#endif
-
-#include <time.h>
-#include <ctype.h>
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-struct timeval rb_time_interval(VALUE);
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-#include "ruby/st.h"
-
-#ifdef __EMX__
-#undef HAVE_GETPGRP
-#endif
-
-#include <sys/stat.h>
-
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-#if defined(HAVE_TIMES) || defined(_WIN32)
-static VALUE rb_cProcessTms;
-#endif
-
-#ifndef WIFEXITED
-#define WIFEXITED(w)    (((w) & 0xff) == 0)
-#endif
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(w)  (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
-#endif
-#ifndef WIFSTOPPED
-#define WIFSTOPPED(w)   (((w) & 0xff) == 0x7f)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(w)  (((w) >> 8) & 0xff)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(w)     ((w) & 0x7f)
-#endif
-#ifndef WSTOPSIG
-#define WSTOPSIG        WEXITSTATUS
-#endif
-
-#if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
-#define __MacOS_X__ 1
-#endif
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
-#define HAVE_44BSD_SETUID 1
-#define HAVE_44BSD_SETGID 1
-#endif
-
-#ifdef __NetBSD__
-#undef HAVE_SETRUID
-#undef HAVE_SETRGID
-#endif
-
-#ifdef BROKEN_SETREUID
-#define setreuid ruby_setreuid
-#endif
-#ifdef BROKEN_SETREGID
-#define setregid ruby_setregid
-#endif
-
-#if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
-#if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
-#define OBSOLETE_SETREUID 1
-#endif
-#if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
-#define OBSOLETE_SETREGID 1
-#endif
-#endif
-
-#if SIZEOF_RLIM_T == SIZEOF_INT
-# define RLIM2NUM(v) UINT2NUM(v)
-# define NUM2RLIM(v) NUM2UINT(v)
-#elif SIZEOF_RLIM_T == SIZEOF_LONG
-# define RLIM2NUM(v) ULONG2NUM(v)
-# define NUM2RLIM(v) NUM2ULONG(v)
-#elif SIZEOF_RLIM_T == SIZEOF_LONG_LONG
-# define RLIM2NUM(v) ULL2NUM(v)
-# define NUM2RLIM(v) NUM2ULL(v)
-#endif
-
-#define preserving_errno(stmts) \
-	do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
-
-
-/*
- *  call-seq:
- *     Process.pid   => fixnum
- *
- *  Returns the process id of this process. Not available on all
- *  platforms.
- *
- *     Process.pid   #=> 27415
- */
-
-static VALUE
-get_pid(VALUE rcv, SEL sel)
-{
-    rb_secure(2);
-    return PIDT2NUM(getpid());
-}
-
-
-/*
- *  call-seq:
- *     Process.ppid   => fixnum
- *
- *  Returns the process id of the parent of this process. Always
- *  returns 0 on NT. Not available on all platforms.
- *
- *     puts "I am #{Process.pid}"
- *     Process.fork { puts "Dad is #{Process.ppid}" }
- *
- *  <em>produces:</em>
- *
- *     I am 27417
- *     Dad is 27417
- */
-
-static VALUE
-get_ppid(VALUE rcv, SEL sel)
-{
-    rb_secure(2);
-#ifdef _WIN32
-    return INT2FIX(0);
-#else
-    return PIDT2NUM(getppid());
-#endif
-}
-
-
-/*********************************************************************
- *
- * Document-class: Process::Status
- *
- *  <code>Process::Status</code> encapsulates the information on the
- *  status of a running or terminated system process. The built-in
- *  variable <code>$?</code> is either +nil+ or a
- *  <code>Process::Status</code> object.
- *
- *     fork { exit 99 }   #=> 26557
- *     Process.wait       #=> 26557
- *     $?.class           #=> Process::Status
- *     $?.to_i            #=> 25344
- *     $? >> 8            #=> 99
- *     $?.stopped?        #=> false
- *     $?.exited?         #=> true
- *     $?.exitstatus      #=> 99
- *
- *  Posix systems record information on processes using a 16-bit
- *  integer.  The lower bits record the process status (stopped,
- *  exited, signaled) and the upper bits possibly contain additional
- *  information (for example the program's return code in the case of
- *  exited processes). Pre Ruby 1.8, these bits were exposed directly
- *  to the Ruby program. Ruby now encapsulates these in a
- *  <code>Process::Status</code> object. To maximize compatibility,
- *  however, these objects retain a bit-oriented interface. In the
- *  descriptions that follow, when we talk about the integer value of
- *  _stat_, we're referring to this 16 bit value.
- */
-
-VALUE rb_cProcessStatus;
-
-static void
-rb_last_status_clear(void)
-{
-    rb_last_status_set(0, -1);
-}
-
-/*
- *  call-seq:
- *     stat.to_i     => fixnum
- *     stat.to_int   => fixnum
- *
- *  Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
- *  around in these bits is platform dependent.
- *
- *     fork { exit 0xab }         #=> 26566
- *     Process.wait               #=> 26566
- *     sprintf('%04x', $?.to_i)   #=> "ab00"
- */
-
-static VALUE
-pst_to_i(VALUE st, SEL sel)
-{
-    return rb_iv_get(st, "status");
-}
-
-
-/*
- *  call-seq:
- *     stat.pid   => fixnum
- *
- *  Returns the process ID that this status object represents.
- *
- *     fork { exit }   #=> 26569
- *     Process.wait    #=> 26569
- *     $?.pid          #=> 26569
- */
-
-static VALUE
-pst_pid(VALUE st, SEL sel)
-{
-    return rb_iv_get(st, "pid");
-}
-
-static void
-pst_message(VALUE str, rb_pid_t pid, int status)
-{
-    char buf[256];
-    snprintf(buf, sizeof(buf), "pid %ld", (long)pid);
-    rb_str_cat2(str, buf);
-    if (WIFSTOPPED(status)) {
-	int stopsig = WSTOPSIG(status);
-	const char *signame = ruby_signal_name(stopsig);
-	if (signame) {
-	    snprintf(buf, sizeof(buf), " stopped SIG%s (signal %d)", signame, stopsig);
-	}
-	else {
-	    snprintf(buf, sizeof(buf), " stopped signal %d", stopsig);
-	}
-	rb_str_cat2(str, buf);
-    }
-    if (WIFSIGNALED(status)) {
-	int termsig = WTERMSIG(status);
-	const char *signame = ruby_signal_name(termsig);
-	if (signame) {
-	    snprintf(buf, sizeof(buf), " SIG%s (signal %d)", signame, termsig);
-	}
-	else {
-	    snprintf(buf, sizeof(buf), " signal %d", termsig);
-	}
-	rb_str_cat2(str, buf);
-    }
-    if (WIFEXITED(status)) {
-	snprintf(buf, sizeof(buf), " exit %d", WEXITSTATUS(status));
-	rb_str_cat2(str, buf);
-    }
-#ifdef WCOREDUMP
-    if (WCOREDUMP(status)) {
-	rb_str_cat2(str, " (core dumped)");
-    }
-#endif
-}
-
-
-/*
- *  call-seq:
- *     stat.to_s   => string
- *
- *  Show pid and exit status as a string.
- */
-
-static VALUE
-pst_to_s(VALUE st, SEL sel)
-{
-    rb_pid_t pid;
-    int status;
-    VALUE str;
-
-    pid = NUM2LONG(pst_pid(st, 0));
-    status = NUM2INT(pst_to_i(st, 0));
-
-    str = rb_str_buf_new(0);
-    pst_message(str, pid, status);
-    return str;
-}
-
-
-/*
- *  call-seq:
- *     stat.inspect   => string
- *
- *  Override the inspection method.
- */
-
-static VALUE
-pst_inspect(VALUE st, SEL sel)
-{
-    rb_pid_t pid;
-    int status;
-    VALUE str;
-
-    pid = NUM2LONG(pst_pid(st, 0));
-    status = NUM2INT(pst_to_i(st, 0));
-
-    str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
-    pst_message(str, pid, status);
-    rb_str_cat2(str, ">");
-    return str;
-}
-
-
-/*
- *  call-seq:
- *     stat == other   => true or false
- *
- *  Returns +true+ if the integer value of _stat_
- *  equals <em>other</em>.
- */
-
-static VALUE
-pst_equal(VALUE st1, SEL sel, VALUE st2)
-{
-    if (st1 == st2) {
-	return Qtrue;
-    }
-    return rb_equal(pst_to_i(st1, 0), st2);
-}
-
-
-/*
- *  call-seq:
- *     stat & num   => fixnum
- *
- *  Logical AND of the bits in _stat_ with <em>num</em>.
- *
- *     fork { exit 0x37 }
- *     Process.wait
- *     sprintf('%04x', $?.to_i)       #=> "3700"
- *     sprintf('%04x', $? & 0x1e00)   #=> "1600"
- */
-
-static VALUE
-pst_bitand(VALUE st1, SEL sel, VALUE st2)
-{
-    int status = NUM2INT(st1) & NUM2INT(st2);
-
-    return INT2NUM(status);
-}
-
-
-/*
- *  call-seq:
- *     stat >> num   => fixnum
- *
- *  Shift the bits in _stat_ right <em>num</em> places.
- *
- *     fork { exit 99 }   #=> 26563
- *     Process.wait       #=> 26563
- *     $?.to_i            #=> 25344
- *     $? >> 8            #=> 99
- */
-
-static VALUE
-pst_rshift(VALUE st1, SEL sel, VALUE st2)
-{
-    int status = NUM2INT(st1) >> NUM2INT(st2);
-
-    return INT2NUM(status);
-}
-
-
-/*
- *  call-seq:
- *     stat.stopped?   => true or false
- *
- *  Returns +true+ if this process is stopped. This is only
- *  returned if the corresponding <code>wait</code> call had the
- *  <code>WUNTRACED</code> flag set.
- */
-
-static VALUE
-pst_wifstopped(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFSTOPPED(status))
-	return Qtrue;
-    else
-	return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     stat.stopsig   => fixnum or nil
- *
- *  Returns the number of the signal that caused _stat_ to stop
- *  (or +nil+ if self is not stopped).
- */
-
-static VALUE
-pst_wstopsig(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFSTOPPED(status))
-	return INT2NUM(WSTOPSIG(status));
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     stat.signaled?   => true or false
- *
- *  Returns +true+ if _stat_ terminated because of
- *  an uncaught signal.
- */
-
-static VALUE
-pst_wifsignaled(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFSIGNALED(status))
-	return Qtrue;
-    else
-	return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     stat.termsig   => fixnum or nil
- *
- *  Returns the number of the signal that caused _stat_ to
- *  terminate (or +nil+ if self was not terminated by an
- *  uncaught signal).
- */
-
-static VALUE
-pst_wtermsig(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFSIGNALED(status))
-	return INT2NUM(WTERMSIG(status));
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     stat.exited?   => true or false
- *
- *  Returns +true+ if _stat_ exited normally (for
- *  example using an <code>exit()</code> call or finishing the
- *  program).
- */
-
-static VALUE
-pst_wifexited(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFEXITED(status))
-	return Qtrue;
-    else
-	return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     stat.exitstatus   => fixnum or nil
- *
- *  Returns the least significant eight bits of the return code of
- *  _stat_. Only available if <code>exited?</code> is
- *  +true+.
- *
- *     fork { }           #=> 26572
- *     Process.wait       #=> 26572
- *     $?.exited?         #=> true
- *     $?.exitstatus      #=> 0
- *
- *     fork { exit 99 }   #=> 26573
- *     Process.wait       #=> 26573
- *     $?.exited?         #=> true
- *     $?.exitstatus      #=> 99
- */
-
-static VALUE
-pst_wexitstatus(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (WIFEXITED(status))
-	return INT2NUM(WEXITSTATUS(status));
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     stat.success?   => true, false or nil
- *
- *  Returns +true+ if _stat_ is successful, +false+ if not.
- *  Returns +nil+ if <code>exited?</code> is not +true+.
- */
-
-static VALUE
-pst_success_p(VALUE st, SEL sel)
-{
-    int status = NUM2INT(st);
-
-    if (!WIFEXITED(status))
-	return Qnil;
-    return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     stat.coredump?   => true or false
- *
- *  Returns +true+ if _stat_ generated a coredump
- *  when it terminated. Not available on all platforms.
- */
-
-static VALUE
-pst_wcoredump(VALUE st, SEL sel)
-{
-#ifdef WCOREDUMP
-    int status = NUM2INT(st);
-
-    if (WCOREDUMP(status))
-	return Qtrue;
-    else
-	return Qfalse;
-#else
-    return Qfalse;
-#endif
-}
-
-#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
-#define NO_WAITPID
-static st_table *pid_tbl;
-#else
-struct waitpid_arg {
-    rb_pid_t pid;
-    int *st;
-    int flags;
-};
-#endif
-
-static VALUE
-rb_waitpid_blocking(void *data)
-{
-    rb_pid_t result;
-#ifndef NO_WAITPID
-    struct waitpid_arg *arg = data;
-#endif
-
-#if defined NO_WAITPID
-    result = wait(data);
-#elif defined HAVE_WAITPID
-    result = waitpid(arg->pid, arg->st, arg->flags);
-#else  /* HAVE_WAIT4 */
-    result = wait4(arg->pid, arg->st, arg->flags, NULL);
-#endif
-    return (VALUE)result;
-}
-
-rb_pid_t
-rb_waitpid(rb_pid_t pid, int *st, int flags)
-{
-    rb_pid_t result;
-#ifndef NO_WAITPID
-    struct waitpid_arg arg;
-
-    arg.pid = pid;
-    arg.st = st;
-    arg.flags = flags;
-    result = rb_waitpid_blocking(&arg);
-//    result = (rb_pid_t)rb_thread_blocking_region(rb_waitpid_blocking, &arg,
-//						 RB_UBF_DFL, 0);
-    if (result < 0) {
-#if 0
-	if (errno == EINTR) {
-	    rb_thread_polling();
-	    goto retry;
-	}
-#endif
-	return -1;
-    }
-#else  /* NO_WAITPID */
-    if (pid_tbl && st_lookup(pid_tbl, pid, (st_data_t *)st)) {
-	rb_last_status_set(*st, pid);
-	st_delete(pid_tbl, (st_data_t*)&pid, NULL);
-	return pid;
-    }
-
-    if (flags) {
-	rb_raise(rb_eArgError, "can't do waitpid with flags");
-    }
-
-    for (;;) {
-	result = (rb_pid_t)rb_thread_blocking_region(rb_waitpid_blocking,
-						     st, RB_UBF_DFL);
-	if (result < 0) {
-	    if (errno == EINTR) {
-		rb_thread_schedule();
-		continue;
-	    }
-	    return -1;
-	}
-	if (result == pid) {
-	    break;
-	}
-	if (!pid_tbl)
-	  pid_tbl = st_init_numtable();
-	st_insert(pid_tbl, pid, (st_data_t)st);
-	if (!rb_thread_alone()) rb_thread_schedule();
-    }
-#endif
-    if (result > 0) {
-	rb_last_status_set(*st, result);
-    }
-    return result;
-}
-
-#ifdef NO_WAITPID
-struct wait_data {
-    rb_pid_t pid;
-    int status;
-};
-
-static int
-wait_each(rb_pid_t pid, int status, struct wait_data *data)
-{
-    if (data->status != -1) return ST_STOP;
-
-    data->pid = pid;
-    data->status = status;
-    return ST_DELETE;
-}
-
-static int
-waitall_each(rb_pid_t pid, int status, VALUE ary)
-{
-    rb_last_status_set(status, pid);
-    rb_ary_push(ary, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get());
-    return ST_DELETE;
-}
-#endif
-
-
-/* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
-   has historically been documented as if it didn't take any arguments
-   despite the fact that it's just an alias for ::waitpid(). The way I
-   have it below is more truthful, but a little confusing.
-
-   I also took the liberty of putting in the pid values, as they're
-   pretty useful, and it looked as if the original 'ri' output was
-   supposed to contain them after "[...]depending on the value of
-   aPid:".
-
-   The 'ansi' and 'bs' formats of the ri output don't display the
-   definition list for some reason, but the plain text one does.
- */
-
-/*
- *  call-seq:
- *     Process.wait()                     => fixnum
- *     Process.wait(pid=-1, flags=0)      => fixnum
- *     Process.waitpid(pid=-1, flags=0)   => fixnum
- *
- *  Waits for a child process to exit, returns its process id, and
- *  sets <code>$?</code> to a <code>Process::Status</code> object
- *  containing information on that process. Which child it waits on
- *  depends on the value of _pid_:
- *
- *  > 0::   Waits for the child whose process ID equals _pid_.
- *
- *  0::     Waits for any child whose process group ID equals that of the
- *          calling process.
- *
- *  -1::    Waits for any child process (the default if no _pid_ is
- *          given).
- *
- *  < -1::  Waits for any child whose process group ID equals the absolute
- *          value of _pid_.
- *
- *  The _flags_ argument may be a logical or of the flag values
- *  <code>Process::WNOHANG</code> (do not block if no child available)
- *  or <code>Process::WUNTRACED</code> (return stopped children that
- *  haven't been reported). Not all flags are available on all
- *  platforms, but a flag value of zero will work on all platforms.
- *
- *  Calling this method raises a <code>SystemError</code> if there are
- *  no child processes. Not available on all platforms.
- *
- *     include Process
- *     fork { exit 99 }                 #=> 27429
- *     wait                             #=> 27429
- *     $?.exitstatus                    #=> 99
- *
- *     pid = fork { sleep 3 }           #=> 27440
- *     Time.now                         #=> 2008-03-08 19:56:16 +0900
- *     waitpid(pid, Process::WNOHANG)   #=> nil
- *     Time.now                         #=> 2008-03-08 19:56:16 +0900
- *     waitpid(pid, 0)                  #=> 27440
- *     Time.now                         #=> 2008-03-08 19:56:19 +0900
- */
-
-static VALUE
-proc_wait(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE vpid, vflags;
-    rb_pid_t pid;
-    int flags, status;
-
-    rb_secure(2);
-    flags = 0;
-    if (argc == 0) {
-	pid = -1;
-    }
-    else {
-	rb_scan_args(argc, argv, "02", &vpid, &vflags);
-	pid = NUM2PIDT(vpid);
-	if (argc == 2 && !NIL_P(vflags)) {
-	    flags = NUM2UINT(vflags);
-	}
-    }
-    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
-	rb_sys_fail(0);
-    if (pid == 0) {
-	rb_last_status_clear();
-	return Qnil;
-    }
-    return PIDT2NUM(pid);
-}
-
-
-/*
- *  call-seq:
- *     Process.wait2(pid=-1, flags=0)      => [pid, status]
- *     Process.waitpid2(pid=-1, flags=0)   => [pid, status]
- *
- *  Waits for a child process to exit (see Process::waitpid for exact
- *  semantics) and returns an array containing the process id and the
- *  exit status (a <code>Process::Status</code> object) of that
- *  child. Raises a <code>SystemError</code> if there are no child
- *  processes.
- *
- *     Process.fork { exit 99 }   #=> 27437
- *     pid, status = Process.wait2
- *     pid                        #=> 27437
- *     status.exitstatus          #=> 99
- */
-
-static VALUE
-proc_wait2(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE pid = proc_wait(rcv, 0, argc, argv);
-    if (NIL_P(pid)) return Qnil;
-    return rb_assoc_new(pid, rb_last_status_get());
-}
-
-
-/*
- *  call-seq:
- *     Process.waitall   => [ [pid1,status1], ...]
- *
- *  Waits for all children, returning an array of
- *  _pid_/_status_ pairs (where _status_ is a
- *  <code>Process::Status</code> object).
- *
- *     fork { sleep 0.2; exit 2 }   #=> 27432
- *     fork { sleep 0.1; exit 1 }   #=> 27433
- *     fork {            exit 0 }   #=> 27434
- *     p Process.waitall
- *
- *  <em>produces</em>:
- *
- *     [[27434, #<Process::Status: pid=27434,exited(0)>],
- *      [27433, #<Process::Status: pid=27433,exited(1)>],
- *      [27432, #<Process::Status: pid=27432,exited(2)>]]
- */
-
-static VALUE
-proc_waitall(VALUE rcv, SEL sel)
-{
-    VALUE result;
-    rb_pid_t pid;
-    int status;
-
-    rb_secure(2);
-    result = rb_ary_new();
-#ifdef NO_WAITPID
-    if (pid_tbl) {
-	st_foreach(pid_tbl, waitall_each, result);
-    }
-#else
-    rb_last_status_clear();
-#endif
-
-    for (pid = -1;;) {
-#ifdef NO_WAITPID
-	pid = wait(&status);
-#else
-	pid = rb_waitpid(-1, &status, 0);
-#endif
-	if (pid == -1) {
-	    if (errno == ECHILD)
-		break;
-#ifdef NO_WAITPID
-	    if (errno == EINTR) {
-		rb_thread_schedule();
-		continue;
-	    }
-#endif
-	    rb_sys_fail(0);
-	}
-#ifdef NO_WAITPID
-	rb_last_status_set(status, pid);
-#endif
-	rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
-    }
-    return result;
-}
-
-static VALUE
-detach_process_watcher(void *arg)
-{
-    rb_pid_t cpid, pid = (rb_pid_t)(VALUE)arg;
-    int status;
-
-    while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
-	/* wait while alive */
-    }
-    return rb_last_status_get();
-}
-
-VALUE
-rb_detach_process(rb_pid_t pid)
-{
-    return rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
-}
-
-
-/*
- *  call-seq:
- *     Process.detach(pid)   => thread
- *
- *  Some operating systems retain the status of terminated child
- *  processes until the parent collects that status (normally using
- *  some variant of <code>wait()</code>. If the parent never collects
- *  this status, the child stays around as a <em>zombie</em> process.
- *  <code>Process::detach</code> prevents this by setting up a
- *  separate Ruby thread whose sole job is to reap the status of the
- *  process _pid_ when it terminates. Use <code>detach</code>
- *  only when you do not intent to explicitly wait for the child to
- *  terminate.
- *
- *  The waiting thread returns the exit status of the detached process
- *  when it terminates, so you can use <code>Thread#join</code> to
- *  know the result.  If specified _pid_ is not a valid child process
- *  ID, the thread returns +nil+ immediately.
- *
- *  In this first example, we don't reap the first child process, so
- *  it appears as a zombie in the process status display.
- *
- *     p1 = fork { sleep 0.1 }
- *     p2 = fork { sleep 0.2 }
- *     Process.waitpid(p2)
- *     sleep 2
- *     system("ps -ho pid,state -p #{p1}")
- *
- *  <em>produces:</em>
- *
- *     27389 Z
- *
- *  In the next example, <code>Process::detach</code> is used to reap
- *  the child automatically.
- *
- *     p1 = fork { sleep 0.1 }
- *     p2 = fork { sleep 0.2 }
- *     Process.detach(p1)
- *     Process.waitpid(p2)
- *     sleep 2
- *     system("ps -ho pid,state -p #{p1}")
- *
- *  <em>(produces no output)</em>
- */
-
-static VALUE
-proc_detach(VALUE obj, SEL sel, VALUE pid)
-{
-    rb_secure(2);
-    return rb_detach_process(NUM2PIDT(pid));
-}
-
-#ifndef HAVE_STRING_H
-char *strtok();
-#endif
-
-#if 1
-#define before_exec() 
-#define after_exec()
-#else
-void rb_thread_stop_timer_thread(void);
-void rb_thread_start_timer_thread(void);
-void rb_thread_reset_timer_thread(void);
-
-#define before_exec() \
-  (rb_enable_interrupt(), rb_thread_stop_timer_thread())
-#define after_exec() \
-  (rb_thread_start_timer_thread(), rb_disable_interrupt())
-#endif
-
-#include "dln.h"
-
-static void
-security(const char *str)
-{
-    if (rb_env_path_tainted()) {
-	if (rb_safe_level() > 0) {
-	    rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
-	}
-    }
-}
-
-static int
-proc_exec_v(char **argv, const char *prog)
-{
-    char fbuf[MAXPATHLEN];
-
-    if (!prog)
-	prog = argv[0];
-    prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
-    if (!prog) {
-	errno = ENOENT;
-	return -1;
-    }
-
-#if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
-    {
-#if defined(__human68k__)
-#define COMMAND "command.x"
-#endif
-#if defined(__EMX__) || defined(OS2) /* OS/2 emx */
-#define COMMAND "cmd.exe"
-#endif
-#if (defined(MSDOS) && !defined(DJGPP))
-#define COMMAND "command.com"
-#endif
-	char *extension;
-
-	if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
-	    char **new_argv;
-	    char *p;
-	    int n;
-
-	    for (n = 0; argv[n]; n++)
-		/* no-op */;
-	    new_argv = ALLOCA_N(char*, n + 2);
-	    for (; n > 0; n--)
-		new_argv[n + 1] = argv[n];
-	    new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
-	    for (p = new_argv[1]; *p != '\0'; p++)
-		if (*p == '/')
-		    *p = '\\';
-	    new_argv[0] = COMMAND;
-	    argv = new_argv;
-	    prog = dln_find_exe_r(argv[0], 0, fbuf, sizeof(fbuf));
-	    if (!prog) {
-		errno = ENOENT;
-		return -1;
-	    }
-	}
-    }
-#endif /* MSDOS or __human68k__ or __EMX__ */
-    before_exec();
-    execv(prog, argv);
-    preserving_errno(after_exec());
-    return -1;
-}
-
-int
-rb_proc_exec_n(int argc, VALUE *argv, const char *prog)
-{
-    char **args;
-    int i;
-
-    args = ALLOCA_N(char*, argc+1);
-    for (i=0; i<argc; i++) {
-	args[i] = (char *)RSTRING_PTR(argv[i]);
-    }
-    args[i] = 0;
-    if (args[0]) {
-	return proc_exec_v(args, prog);
-    }
-    return -1;
-}
-
-int
-rb_proc_exec(const char *str)
-{
-#ifndef _WIN32
-    const char *s = str;
-    char *ss, *t;
-    char **argv, **a;
-#endif
-
-    while (*str && ISSPACE(*str))
-	str++;
-
-#ifdef _WIN32
-    before_exec();
-    rb_w32_spawn(P_OVERLAY, (char *)str, 0);
-    after_exec();
-#else
-    for (s=str; *s; s++) {
-	if (ISSPACE(*s)) {
-	    const char *p, *nl = NULL;
-	    for (p = s; ISSPACE(*p); p++) {
-		if (*p == '\n') nl = p;
-	    }
-	    if (!*p) break;
-	    if (nl) s = nl;
-	}
-	if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
-#if defined(MSDOS)
-	    int status;
-	    before_exec();
-	    status = system(str);
-	    after_exec();
-	    if (status != -1)
-		exit(status);
-#elif defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
-	    char fbuf[MAXPATHLEN];
-	    char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
-	    int status = -1;
-	    before_exec();
-	    if (shell)
-		execl(shell, "sh", "-c", str, (char *) NULL);
-	    else
-		status = system(str);
-	    after_exec();
-	    if (status != -1)
-		exit(status);
-#else
-	    before_exec();
-	    execl("/bin/sh", "sh", "-c", str, (char *)NULL);
-	    preserving_errno(after_exec());
-#endif
-	    return -1;
-	}
-    }
-    a = argv = ALLOCA_N(char*, (s-str)/2+2);
-    ss = ALLOCA_N(char, s-str+1);
-    memcpy(ss, str, s-str);
-    ss[s-str] = '\0';
-    if ((*a++ = strtok(ss, " \t")) != 0) {
-	while ((t = strtok(NULL, " \t")) != 0) {
-	    *a++ = t;
-	}
-	*a = NULL;
-    }
-    if (argv[0]) {
-	return proc_exec_v(argv, 0);
-    }
-    errno = ENOENT;
-#endif	/* _WIN32 */
-    return -1;
-}
-
-#if defined(_WIN32)
-#define HAVE_SPAWNV 1
-#endif
-
-#if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
-#if defined(_WIN32)
-#define proc_spawn_v(argv, prog) rb_w32_aspawn(P_NOWAIT, prog, argv)
-#else
-static rb_pid_t
-proc_spawn_v(char **argv, char *prog)
-{
-    char fbuf[MAXPATHLEN];
-    char *extension;
-    rb_pid_t status;
-
-    if (!prog)
-	prog = argv[0];
-    security(prog);
-    prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
-    if (!prog)
-	return -1;
-
-#if defined(__human68k__)
-    if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
-	char **new_argv;
-	char *p;
-	int n;
-
-	for (n = 0; argv[n]; n++)
-	    /* no-op */;
-	new_argv = ALLOCA_N(char*, n + 2);
-	for (; n > 0; n--)
-	    new_argv[n + 1] = argv[n];
-	new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
-	for (p = new_argv[1]; *p != '\0'; p++)
-	    if (*p == '/')
-		*p = '\\';
-	new_argv[0] = COMMAND;
-	argv = new_argv;
-	prog = dln_find_exe_r(argv[0], 0, fbuf, sizeof(fbuf));
-	if (!prog) {
-	    errno = ENOENT;
-	    return -1;
-	}
-    }
-#endif
-    before_exec();
-    status = spawnv(P_WAIT, prog, argv);
-    rb_last_status_set(status == -1 ? 127 : status, 0);
-    after_exec();
-    return status;
-}
-#endif
-
-static rb_pid_t
-proc_spawn_n(int argc, VALUE *argv, VALUE prog)
-{
-    char **args;
-    int i;
-
-    args = ALLOCA_N(char*, argc + 1);
-    for (i = 0; i < argc; i++) {
-	args[i] = RSTRING_PTR(argv[i]);
-    }
-    args[i] = (char*) 0;
-    if (args[0])
-	return proc_spawn_v(args, prog ? RSTRING_PTR(prog) : 0);
-    return -1;
-}
-
-#if defined(_WIN32)
-#define proc_spawn(str) rb_w32_spawn(P_NOWAIT, str, 0)
-#else
-static rb_pid_t
-proc_spawn(char *str)
-{
-    char fbuf[MAXPATHLEN];
-    char *s, *t;
-    char **argv, **a;
-    rb_pid_t status;
-
-    for (s = str; *s; s++) {
-	if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
-	    char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
-	    before_exec();
-	    status = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
-	    rb_last_status_set(status == -1 ? 127 : status, 0);
-	    after_exec();
-	    return status;
-	}
-    }
-    a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
-    s = ALLOCA_N(char, s - str + 1);
-    strcpy(s, str);
-    if (*a++ = strtok(s, " \t")) {
-	while (t = strtok(NULL, " \t"))
-	    *a++ = t;
-	*a = NULL;
-    }
-    return argv[0] ? proc_spawn_v(argv, 0) : -1;
-}
-#endif
-#endif
-
-static VALUE
-hide_obj(VALUE obj)
-{
-#if !WITH_OBJC
-    RBASIC(obj)->klass = 0;
-#endif
-    return obj;
-}
-
-enum {
-    EXEC_OPTION_PGROUP,
-    EXEC_OPTION_RLIMIT,
-    EXEC_OPTION_UNSETENV_OTHERS,
-    EXEC_OPTION_ENV,
-    EXEC_OPTION_CHDIR,
-    EXEC_OPTION_UMASK,
-    EXEC_OPTION_DUP2,
-    EXEC_OPTION_CLOSE,
-    EXEC_OPTION_OPEN,
-    EXEC_OPTION_CLOSE_OTHERS,
-};
-
-static VALUE
-check_exec_redirect_fd(VALUE v)
-{
-    VALUE tmp;
-    int fd;
-    if (FIXNUM_P(v)) {
-        fd = FIX2INT(v);
-    }
-    else if (SYMBOL_P(v)) {
-        ID id = SYM2ID(v);
-        if (id == rb_intern("in"))
-            fd = 0;
-        else if (id == rb_intern("out"))
-            fd = 1;
-        else if (id == rb_intern("err"))
-            fd = 2;
-        else
-            goto wrong;
-    }
-    else if (!NIL_P(tmp = rb_check_convert_type(v, T_FILE, "IO", "to_io"))) {
-        rb_io_t *fptr = ExtractIOStruct(tmp);
-#if 0
-        if (fptr->tied_io_for_writing)
-            rb_raise(rb_eArgError, "duplex IO redirection");
-#endif
-        fd = fptr->fd;
-    }
-    else {
-        rb_raise(rb_eArgError, "wrong exec redirect");
-    }
-    if (fd < 0) {
-      wrong:
-        rb_raise(rb_eArgError, "negative file descriptor");
-    }
-    return INT2FIX(fd);
-}
-
-static void
-check_exec_redirect(VALUE key, VALUE val, VALUE options)
-{
-    int index;
-    VALUE ary, param;
-    VALUE path, flags, perm;
-    ID id;
-
-    switch (TYPE(val)) {
-      case T_SYMBOL:
-        id = SYM2ID(val);
-        if (id == rb_intern("close")) {
-            index = EXEC_OPTION_CLOSE;
-            param = Qnil;
-        }
-        else {
-            rb_raise(rb_eArgError, "wrong exec redirect symbol: %s",
-                                   rb_id2name(id));
-        }
-        break;
-
-      case T_FILE:
-        val = check_exec_redirect_fd(val);
-        /* fall through */
-      case T_FIXNUM:
-        index = EXEC_OPTION_DUP2;
-        param = val;
-        break;
-
-      case T_ARRAY:
-        index = EXEC_OPTION_OPEN;
-        path = rb_ary_entry(val, 0);
-        FilePathValue(path);
-        flags = rb_ary_entry(val, 1);
-        if (NIL_P(flags))
-            flags = INT2NUM(O_RDONLY);
-        else if (TYPE(flags) == T_STRING)
-            flags = INT2FIX(0);//TODO INT2NUM(rb_io_mode_modenum(StringValueCStr(flags)));
-        else
-            flags = rb_to_int(flags);
-        perm = rb_ary_entry(val, 2);
-        perm = NIL_P(perm) ? INT2FIX(0644) : rb_to_int(perm);
-        param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
-                                        flags, perm));
-        break;
-
-      case T_STRING:
-        index = EXEC_OPTION_OPEN;
-        path = val;
-        FilePathValue(path);
-        if ((FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2)) ||
-            key == rb_stdout || key == rb_stderr)
-            flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
-        else
-            flags = INT2NUM(O_RDONLY);
-        perm = INT2FIX(0644);
-        param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
-                                        flags, perm));
-        break;
-
-      default:
-        rb_raise(rb_eArgError, "wrong exec redirect action");
-    }
-
-    ary = rb_ary_entry(options, index);
-    if (NIL_P(ary)) {
-        ary = hide_obj(rb_ary_new());
-        rb_ary_store(options, index, ary);
-    }
-    if (TYPE(key) != T_ARRAY) {
-        VALUE fd = check_exec_redirect_fd(key);
-        rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
-    }
-    else {
-        int i, n=0;
-        for (i = 0 ; i < RARRAY_LEN(key); i++) {
-            VALUE v = RARRAY_AT(key, i);
-            VALUE fd = check_exec_redirect_fd(v);
-            rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
-            n++;
-        }
-    }
-}
-
-#ifdef RLIM2NUM
-static int rlimit_type_by_lname(const char *name);
-#endif
-
-int
-rb_exec_arg_addopt(struct rb_exec_arg *e, VALUE key, VALUE val)
-{
-    VALUE options = e->options;
-    ID id;
-#ifdef RLIM2NUM
-    int rtype;
-#endif
-
-    rb_secure(2);
-
-    switch (TYPE(key)) {
-      case T_SYMBOL:
-        id = SYM2ID(key);
-#ifdef HAVE_SETPGID
-        if (id == rb_intern("pgroup")) {
-            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_PGROUP))) {
-                rb_raise(rb_eArgError, "pgroup option specified twice");
-            }
-            if (!RTEST(val))
-                val = Qfalse;
-            else if (val == Qtrue)
-                val = INT2FIX(0);
-            else {
-                pid_t pgroup = NUM2PIDT(val);
-                if (pgroup < 0) {
-                    rb_raise(rb_eArgError, "negative process group ID : %ld", (long)pgroup);
-                }
-                val = PIDT2NUM(pgroup);
-            }
-            rb_ary_store(options, EXEC_OPTION_PGROUP, val);
-        }
-        else
-#endif
-#ifdef RLIM2NUM
-        if (strncmp("rlimit_", rb_id2name(id), 7) == 0 &&
-            (rtype = rlimit_type_by_lname(rb_id2name(id)+7)) != -1) {
-            VALUE ary = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
-            VALUE tmp, softlim, hardlim;
-            if (NIL_P(ary)) {
-                ary = hide_obj(rb_ary_new());
-                rb_ary_store(options, EXEC_OPTION_RLIMIT, ary);
-            }
-            tmp = rb_check_array_type(val);
-            if (!NIL_P(tmp)) {
-                if (RARRAY_LEN(tmp) == 1)
-                    softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
-                else if (RARRAY_LEN(tmp) == 2) {
-                    softlim = rb_to_int(rb_ary_entry(tmp, 0));
-                    hardlim = rb_to_int(rb_ary_entry(tmp, 1));
-                }
-                else {
-                    rb_raise(rb_eArgError, "wrong exec rlimit option");
-                }
-            }
-            else {
-                softlim = hardlim = rb_to_int(val);
-            }
-            tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
-            rb_ary_push(ary, tmp);
-        }
-        else
-#endif
-        if (id == rb_intern("unsetenv_others")) {
-            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_UNSETENV_OTHERS))) {
-                rb_raise(rb_eArgError, "unsetenv_others option specified twice");
-            }
-            val = RTEST(val) ? Qtrue : Qfalse;
-            rb_ary_store(options, EXEC_OPTION_UNSETENV_OTHERS, val);
-        }
-        else if (id == rb_intern("chdir")) {
-            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_CHDIR))) {
-                rb_raise(rb_eArgError, "chdir option specified twice");
-            }
-            FilePathValue(val);
-            rb_ary_store(options, EXEC_OPTION_CHDIR,
-                                  hide_obj(rb_str_dup(val)));
-        }
-        else if (id == rb_intern("umask")) {
-            mode_t cmask = NUM2LONG(val);
-            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_UMASK))) {
-                rb_raise(rb_eArgError, "umask option specified twice");
-            }
-            rb_ary_store(options, EXEC_OPTION_UMASK, LONG2NUM(cmask));
-        }
-        else if (id == rb_intern("close_others")) {
-            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS))) {
-                rb_raise(rb_eArgError, "close_others option specified twice");
-            }
-            val = RTEST(val) ? Qtrue : Qfalse;
-            rb_ary_store(options, EXEC_OPTION_CLOSE_OTHERS, val);
-        }
-        else if (id == rb_intern("in")) {
-            key = INT2FIX(0);
-            goto redirect;
-        }
-        else if (id == rb_intern("out")) {
-            key = INT2FIX(1);
-            goto redirect;
-        }
-        else if (id == rb_intern("err")) {
-            key = INT2FIX(2);
-            goto redirect;
-        }
-        else {
-            rb_raise(rb_eArgError, "wrong exec option symbol: %s",
-                                   rb_id2name(id));
-        }
-        break;
-
-      case T_FIXNUM:
-      case T_FILE:
-      case T_ARRAY:
-redirect:
-        check_exec_redirect(key, val, options);
-        break;
-
-      default:
-        rb_raise(rb_eArgError, "wrong exec option");
-    }
-
-    return ST_CONTINUE;
-}
-
-static int
-check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
-{
-    VALUE key = (VALUE)st_key;
-    VALUE val = (VALUE)st_val;
-    struct rb_exec_arg *e = (struct rb_exec_arg *)arg;
-    return rb_exec_arg_addopt(e, key, val);
-}
-
-static VALUE
-check_exec_fds(VALUE options)
-{
-    VALUE h = rb_hash_new();
-    VALUE ary;
-    int index, i;
-    int maxhint = -1;
-
-    for (index = EXEC_OPTION_DUP2; index <= EXEC_OPTION_OPEN; index++) {
-        ary = rb_ary_entry(options, index);
-        if (NIL_P(ary))
-            continue;
-        for (i = 0; i < RARRAY_LEN(ary); i++) {
-            VALUE elt = RARRAY_AT(ary, i);
-            int fd = FIX2INT(RARRAY_AT(elt, 0));
-            if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
-                rb_raise(rb_eArgError, "fd %d specified twice", fd);
-            }
-            rb_hash_aset(h, INT2FIX(fd), Qtrue);
-            if (maxhint < fd)
-                maxhint = fd;
-            if (index == EXEC_OPTION_DUP2) {
-                fd = FIX2INT(RARRAY_AT(elt, 1));
-                if (maxhint < fd)
-                    maxhint = fd;
-            }
-        }
-    }
-    if (rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS) != Qfalse) {
-        rb_ary_store(options, EXEC_OPTION_CLOSE_OTHERS, INT2FIX(maxhint));
-    }
-    return h;
-}
-
-static void
-rb_check_exec_options(VALUE opthash, struct rb_exec_arg *e)
-{
-    if (RHASH_EMPTY_P(opthash))
-        return;
-    rb_hash_foreach(opthash, check_exec_options_i, (VALUE)e);
-}
-
-static int
-check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
-{
-    VALUE key = (VALUE)st_key;
-    VALUE val = (VALUE)st_val;
-    VALUE env = (VALUE)arg;
-    char *k;
-
-    k = StringValueCStr(key);
-    if (strchr(k, '='))
-        rb_raise(rb_eArgError, "environment name contains a equal : %s", k);
-
-    if (!NIL_P(val))
-        StringValueCStr(val);
-
-    rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
-
-    return ST_CONTINUE;
-}
-
-static VALUE
-rb_check_exec_env(VALUE hash)
-{
-    VALUE env;
-
-    env = hide_obj(rb_ary_new());
-    rb_hash_foreach(hash, check_exec_env_i, env);
-
-    return env;
-}
-
-static VALUE
-rb_check_argv(int argc, VALUE *argv)
-{
-    VALUE tmp, prog;
-    int i;
-    const char *name = 0;
-
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-
-    prog = 0;
-    tmp = rb_check_array_type(argv[0]);
-    if (!NIL_P(tmp)) {
-	if (RARRAY_LEN(tmp) != 2) {
-	    rb_raise(rb_eArgError, "wrong first argument");
-	}
-	prog = RARRAY_AT(tmp, 0);
-	argv[0] = RARRAY_AT(tmp, 1);
-	SafeStringValue(prog);
-	StringValueCStr(prog);
-	prog = rb_str_new4(prog);
-	name = RSTRING_PTR(prog);
-    }
-    for (i = 0; i < argc; i++) {
-	SafeStringValue(argv[i]);
-	argv[i] = rb_str_new4(argv[i]);
-	StringValueCStr(argv[i]);
-    }
-    security(name ? name : RSTRING_PTR(argv[0]));
-    return prog;
-}
-
-static VALUE
-rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret, struct rb_exec_arg *e)
-{
-    VALUE hash, prog;
-
-    if (0 < *argc_p) {
-        hash = rb_check_convert_type((*argv_p)[*argc_p-1], T_HASH, "Hash", "to_hash");
-        if (!NIL_P(hash)) {
-            *opthash_ret = hash;
-            (*argc_p)--;
-        }
-    }
-
-    if (0 < *argc_p) {
-        hash = rb_check_convert_type((*argv_p)[0], T_HASH, "Hash", "to_hash");
-        if (!NIL_P(hash)) {
-            *env_ret = hash;
-            (*argc_p)--;
-            (*argv_p)++;
-        }
-    }
-    prog = rb_check_argv(*argc_p, *argv_p);
-    if (!prog) {
-        prog = (*argv_p)[0];
-        if (accept_shell && *argc_p == 1) {
-            *argc_p = 0;
-            *argv_p = 0;
-        }
-    }
-    return prog;
-}
-
-static void
-rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, struct rb_exec_arg *e)
-{
-    VALUE options;
-    MEMZERO(e, struct rb_exec_arg, 1);
-    options = hide_obj(rb_ary_new());
-    e->options = options;
-
-    if (!NIL_P(opthash)) {
-        rb_check_exec_options(opthash, e);
-    }
-    if (!NIL_P(env)) {
-        env = rb_check_exec_env(env);
-        rb_ary_store(options, EXEC_OPTION_ENV, env);
-    }
-
-    e->argc = argc;
-    e->argv = argv;
-    e->prog = prog ? RSTRING_PTR(prog) : 0;
-}
-
-VALUE
-rb_exec_arg_init(int argc, VALUE *argv, int accept_shell, struct rb_exec_arg *e)
-{
-    VALUE prog;
-    VALUE env = Qnil, opthash = Qnil;
-    prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash, e);
-    rb_exec_fillarg(prog, argc, argv, env, opthash, e);
-    return prog;
-}
-
-void
-rb_exec_arg_fixup(struct rb_exec_arg *e)
-{
-    e->redirect_fds = check_exec_fds(e->options);
-}
-
-/*
- *  call-seq:
- *     exec([env,] command [, arg, ...] [,options])
- *
- *  Replaces the current process by running the given external _command_.
- *  If optional arguments, sequence of +arg+, are not given, that argument is
- *  taken as a line that is subject to shell expansion before being
- *  executed. If one or more +arg+ given, they
- *  are passed as parameters to _command_ with no shell
- *  expansion. If +command+ is a two-element array, the first
- *  element is the command to be executed, and the second argument is
- *  used as the <code>argv[0]</code> value, which may show up in process
- *  listings. In MSDOS environments, the command is executed in a
- *  subshell; otherwise, one of the <code>exec(2)</code> system calls is
- *  used, so the running command may inherit some of the environment of
- *  the original program (including open file descriptors).
- *
- *  The hash arguments, env and options, are same as
- *  <code>system</code> and <code>spawn</code>.
- *  See <code>spawn</code> for details.
- *
- *  Raises SystemCallError if the _command_ couldn't execute (typically
- *  <code>Errno::ENOENT</code> when it was not found).
- *
- *     exec "echo *"       # echoes list of files in current directory
- *     # never get here
- *
- *
- *     exec "echo", "*"    # echoes an asterisk
- *     # never get here
- */
-
-static VALUE
-rb_f_exec(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    struct rb_exec_arg earg;
-
-    rb_exec_arg_init(argc, argv, Qtrue, &earg);
-    if (NIL_P(rb_ary_entry(earg.options, EXEC_OPTION_CLOSE_OTHERS)))
-        rb_exec_arg_addopt(&earg, ID2SYM(rb_intern("close_others")), Qfalse);
-    rb_exec_arg_fixup(&earg);
-
-    rb_exec(&earg);
-    rb_sys_fail(earg.prog);
-    return Qnil;		/* dummy */
-}
-
-/*#define DEBUG_REDIRECT*/
-#if defined(DEBUG_REDIRECT)
-
-#include <stdarg.h>
-
-static void
-ttyprintf(const char *fmt, ...)
-{
-    va_list ap;
-    FILE *tty;
-    int save = errno;
-    tty = fopen("/dev/tty", "w");
-    if (!tty)
-        return;
-
-    va_start(ap, fmt);
-    vfprintf(tty, fmt, ap);
-    va_end(ap);
-    fclose(tty);
-    errno = save;
-}
-
-static int
-redirect_dup(int oldfd)
-{
-    int ret;
-    ret = dup(oldfd);
-    ttyprintf("dup(%d) => %d\n", oldfd, ret);
-    return ret;
-}
-
-static int
-redirect_dup2(int oldfd, int newfd)
-{
-    int ret;
-    ret = dup2(oldfd, newfd);
-    ttyprintf("dup2(%d, %d)\n", oldfd, newfd);
-    return ret;
-}
-
-static int
-redirect_close(int fd)
-{
-    int ret;
-    ret = close(fd);
-    ttyprintf("close(%d)\n", fd);
-    return ret;
-}
-
-static int
-redirect_open(const char *pathname, int flags, mode_t perm)
-{
-    int ret;
-    ret = open(pathname, flags, perm);
-    ttyprintf("open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
-    return ret;
-}
-
-#else
-#define redirect_dup(oldfd) dup(oldfd)
-#define redirect_dup2(oldfd, newfd) dup2(oldfd, newfd)
-#define redirect_close(fd) close(fd)
-#define redirect_open(pathname, flags, perm) open(pathname, flags, perm)
-#endif
-
-static int
-save_redirect_fd(int fd, VALUE save)
-{
-    if (!NIL_P(save)) {
-        VALUE newary;
-        int save_fd = redirect_dup(fd);
-        if (save_fd == -1) return -1;
-        newary = rb_ary_entry(save, EXEC_OPTION_DUP2);
-        if (NIL_P(newary)) {
-            newary = hide_obj(rb_ary_new());
-            rb_ary_store(save, EXEC_OPTION_DUP2, newary);
-        }
-        rb_ary_push(newary,
-                    hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
-
-        newary = rb_ary_entry(save, EXEC_OPTION_CLOSE);
-        if (NIL_P(newary)) {
-            newary = hide_obj(rb_ary_new());
-            rb_ary_store(save, EXEC_OPTION_CLOSE, newary);
-        }
-        rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
-    }
-
-    return 0;
-}
-
-static VALUE
-save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
-{
-    rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
-    return Qnil;
-}
-
-static void
-save_env(VALUE save)
-{
-    if (!NIL_P(save) && NIL_P(rb_ary_entry(save, EXEC_OPTION_ENV))) {
-        VALUE env = rb_const_get(rb_cObject, rb_intern("ENV"));
-        if (RTEST(env)) {
-            VALUE ary = hide_obj(rb_ary_new());
-            rb_objc_block_call(env, selEach, 0, 0, save_env_i, (VALUE)ary);
-            rb_ary_store(save, EXEC_OPTION_ENV, ary);
-        }
-        rb_ary_store(save, EXEC_OPTION_UNSETENV_OTHERS, Qtrue);
-    }
-}
-
-static int
-intcmp(const void *a, const void *b)
-{
-    return *(int*)a - *(int*)b;
-}
-
-static int
-run_exec_dup2(VALUE ary, VALUE save)
-{
-    int n, i;
-    int ret;
-    int extra_fd = -1;
-    struct fd_pair {
-        int oldfd;
-        int newfd;
-        int older_index;
-        int num_newer;
-    } *pairs = 0;
-
-    n = RARRAY_LEN(ary);
-    pairs = ALLOC_N(struct fd_pair, n);
-
-    /* initialize oldfd and newfd: O(n) */
-    for (i = 0; i < n; i++) {
-        VALUE elt = RARRAY_AT(ary, i);
-        pairs[i].oldfd = FIX2INT(RARRAY_AT(elt, 1));
-        pairs[i].newfd = FIX2INT(RARRAY_AT(elt, 0)); /* unique */
-        pairs[i].older_index = -1;
-    }
-
-    /* sort the table by oldfd: O(n log n) */
-    qsort(pairs, n, sizeof(struct fd_pair), intcmp);
-
-    /* initialize older_index and num_newer: O(n log n) */
-    for (i = 0; i < n; i++) {
-        int newfd = pairs[i].newfd;
-        struct fd_pair key, *found;
-        key.oldfd = newfd;
-        found = bsearch(&key, pairs, n, sizeof(struct fd_pair), intcmp);
-        pairs[i].num_newer = 0;
-        if (found) {
-            while (pairs < found && (found-1)->oldfd == newfd)
-                found--;
-            while (found < pairs+n && found->oldfd == newfd) {
-                pairs[i].num_newer++;
-                found->older_index = i;
-                found++;
-            }
-        }
-    }
-
-    /* non-cyclic redirection: O(n) */
-    for (i = 0; i < n; i++) {
-        int j = i;
-        while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
-            if (save_redirect_fd(pairs[j].newfd, save) < 0)
-                return -1;
-            ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
-            if (ret == -1)
-                goto fail;
-            pairs[j].oldfd = -1;
-            j = pairs[j].older_index;
-            if (j != -1)
-                pairs[j].num_newer--;
-        }
-    }
-
-    /* cyclic redirection: O(n) */
-    for (i = 0; i < n; i++) {
-        int j;
-        if (pairs[i].oldfd == -1)
-            continue;
-        if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
-#ifdef F_GETFD
-            int fd = pairs[i].oldfd;
-            ret = fcntl(fd, F_GETFD);
-            if (ret == -1)
-                goto fail;
-            if (ret & FD_CLOEXEC) {
-                ret &= ~FD_CLOEXEC;
-                ret = fcntl(fd, F_SETFD, ret);
-                if (ret == -1)
-                    goto fail;
-            }
-#endif
-            pairs[i].oldfd = -1;
-            continue;
-        }
-        if (extra_fd == -1) {
-            extra_fd = redirect_dup(pairs[i].oldfd);
-            if (extra_fd == -1)
-                goto fail;
-        }
-        else {
-            ret = redirect_dup2(pairs[i].oldfd, extra_fd);
-            if (ret == -1)
-                goto fail;
-        }
-        pairs[i].oldfd = extra_fd;
-        j = pairs[i].older_index;
-        pairs[i].older_index = -1;
-        while (j != -1) {
-            ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
-            if (ret == -1)
-                goto fail;
-            pairs[j].oldfd = -1;
-            j = pairs[j].older_index;
-        }
-    }
-    if (extra_fd != -1) {
-        ret = redirect_close(extra_fd);
-        if (ret == -1)
-            goto fail;
-    }
-
-    return 0;
-
-fail:
-    if (pairs)
-        xfree(pairs);
-    return -1;
-}
-
-static int
-run_exec_close(VALUE ary)
-{
-    int i, ret;
-
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-        VALUE elt = RARRAY_AT(ary, i);
-        int fd = FIX2INT(RARRAY_AT(elt, 0));
-        ret = redirect_close(fd);
-        if (ret == -1)
-            return -1;
-    }
-    return 0;
-}
-
-static int
-run_exec_open(VALUE ary, VALUE save)
-{
-    int i, ret;
-
-    for (i = 0; i < RARRAY_LEN(ary);) {
-        VALUE elt = RARRAY_AT(ary, i);;
-        int fd = FIX2INT(RARRAY_AT(elt, 0));
-        VALUE param = RARRAY_AT(elt, 1);
-        const char *path = RSTRING_PTR(RARRAY_AT(param, 0));
-        int flags = NUM2INT(RARRAY_AT(param, 1));
-        int perm = NUM2INT(RARRAY_AT(param, 2));
-        int need_close = 1;
-        int fd2 = redirect_open(path, flags, perm);
-        if (fd2 == -1) return -1;
-        while (i < RARRAY_LEN(ary) &&
-               (elt = RARRAY_AT(ary, i), RARRAY_AT(elt, 1) == param)) {
-            fd = FIX2INT(RARRAY_AT(elt, 0));
-            if (fd == fd2) {
-                need_close = 0;
-            }
-            else {
-                if (save_redirect_fd(fd, save) < 0)
-                    return -1;
-                ret = redirect_dup2(fd2, fd);
-                if (ret == -1) return -1;
-            }
-            i++;
-        }
-        if (need_close) {
-            ret = redirect_close(fd2);
-            if (ret == -1) return -1;
-        }
-    }
-    return 0;
-}
-
-#ifdef HAVE_SETPGID
-static int
-run_exec_pgroup(VALUE obj, VALUE save)
-{
-    /*
-     * If FD_CLOEXEC is available, rb_fork waits the child's execve.
-     * So setpgid is done in the child when rb_fork is returned in the parent.
-     * No race condition, even without setpgid from the parent.
-     * (Is there an environment which has setpgid but FD_CLOEXEC?)
-     */
-    if (!NIL_P(save)) {
-        /* maybe meaningless with no fork environment... */
-        rb_ary_store(save, EXEC_OPTION_PGROUP, PIDT2NUM(getpgrp()));
-    }
-    pid_t pgroup = NUM2PIDT(obj);
-    if (pgroup == 0) {
-        pgroup = getpid();
-    }
-    return setpgid(getpid(), pgroup);
-}
-#endif
-
-#ifdef RLIM2NUM
-static int
-run_exec_rlimit(VALUE ary, VALUE save)
-{
-    int i;
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-        VALUE elt = RARRAY_AT(ary, i);
-        int rtype = NUM2INT(RARRAY_AT(elt, 0));
-        struct rlimit rlim;
-        if (!NIL_P(save)) {
-            if (getrlimit(rtype, &rlim) == -1)
-                return -1;
-            VALUE tmp = hide_obj(rb_ary_new3(3, RARRAY_AT(elt, 0),
-                                             RLIM2NUM(rlim.rlim_cur),
-                                             RLIM2NUM(rlim.rlim_max)));
-            VALUE newary = rb_ary_entry(save, EXEC_OPTION_RLIMIT);
-            if (NIL_P(newary)) {
-                newary = hide_obj(rb_ary_new());
-                rb_ary_store(save, EXEC_OPTION_RLIMIT, newary);
-            }
-            rb_ary_push(newary, tmp);
-        }
-        rlim.rlim_cur = NUM2RLIM(RARRAY_AT(elt, 1));
-        rlim.rlim_max = NUM2RLIM(RARRAY_AT(elt, 2));
-        if (setrlimit(rtype, &rlim) == -1)
-            return -1;
-    }
-    return 0;
-}
-#endif
-
-int
-rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
-{
-    VALUE options = e->options;
-    VALUE soptions = Qnil;
-    VALUE obj;
-
-    if (!RTEST(options))
-        return 0;
-
-    if (s) {
-        s->argc = 0;
-        s->argv = NULL;
-        s->prog = NULL;
-        s->options = soptions = hide_obj(rb_ary_new());
-        s->redirect_fds = Qnil;
-    }
-
-#ifdef HAVE_SETPGID
-    obj = rb_ary_entry(options, EXEC_OPTION_PGROUP);
-    if (RTEST(obj)) {
-        if (run_exec_pgroup(obj, soptions) == -1)
-            return -1;
-    }
-#endif
-
-#ifdef RLIM2NUM
-    obj = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
-    if (!NIL_P(obj)) {
-        if (run_exec_rlimit(obj, soptions) == -1)
-            return -1;
-    }
-#endif
-
-    obj = rb_ary_entry(options, EXEC_OPTION_UNSETENV_OTHERS);
-    if (RTEST(obj)) {
-        save_env(soptions);
-        rb_env_clear();
-    }
-
-    obj = rb_ary_entry(options, EXEC_OPTION_ENV);
-    if (!NIL_P(obj)) {
-        int i;
-        save_env(soptions);
-        for (i = 0; i < RARRAY_LEN(obj); i++) {
-            VALUE pair = RARRAY_AT(obj, i);
-            VALUE key = RARRAY_AT(pair, 0);
-            VALUE val = RARRAY_AT(pair, 1);
-            if (NIL_P(val))
-                ruby_setenv(StringValueCStr(key), 0);
-            else
-                ruby_setenv(StringValueCStr(key), StringValueCStr(val));
-        }
-    }
-
-    obj = rb_ary_entry(options, EXEC_OPTION_CHDIR);
-    if (!NIL_P(obj)) {
-        if (!NIL_P(soptions)) {
-            VALUE cwd = ruby_getcwd();
-            rb_ary_store(soptions, EXEC_OPTION_CHDIR,
-                         hide_obj(cwd));
-        }
-        if (chdir(RSTRING_PTR(obj)) == -1)
-            return -1;
-    }
-
-    obj = rb_ary_entry(options, EXEC_OPTION_UMASK);
-    if (!NIL_P(obj)) {
-        mode_t mask = NUM2LONG(obj);
-        mode_t oldmask = umask(mask); /* never fail */
-        if (!NIL_P(soptions))
-            rb_ary_store(soptions, EXEC_OPTION_UMASK, LONG2NUM(oldmask));
-    }
-
-    obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
-    if (!NIL_P(obj)) {
-        if (run_exec_dup2(obj, soptions) == -1)
-            return -1;
-    }
-
-    obj = rb_ary_entry(options, EXEC_OPTION_CLOSE);
-    if (!NIL_P(obj)) {
-        if (!NIL_P(soptions))
-            rb_warn("cannot close fd before spawn");
-        else {
-            if (run_exec_close(obj) == -1)
-                return -1;
-        }
-    }
-
-#ifdef HAVE_FORK
-    obj = rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS);
-    if (obj != Qfalse) {
-        // TODO rb_close_before_exec(3, FIX2LONG(obj), e->redirect_fds);
-    }
-#endif
-
-    obj = rb_ary_entry(options, EXEC_OPTION_OPEN);
-    if (!NIL_P(obj)) {
-        if (run_exec_open(obj, soptions) == -1)
-            return -1;
-    }
-
-    return 0;
-}
-
-int
-rb_exec(const struct rb_exec_arg *e)
-{
-    int argc = e->argc;
-    VALUE *argv = e->argv;
-    const char *prog = e->prog;
-
-    if (rb_run_exec_options(e, NULL) < 0) {
-        return -1;
-    }
-
-    if (argc == 0) {
-	rb_proc_exec(prog);
-    }
-    else {
-	rb_proc_exec_n(argc, argv, prog);
-    }
-#ifndef FD_CLOEXEC
-    preserving_errno({
-	fprintf(stderr, "%s:%d: command not found: %s\n",
-		rb_sourcefile(), rb_sourceline(), prog);
-    });
-#endif
-    return -1;
-}
-
-#ifdef HAVE_FORK
-static int
-rb_exec_atfork(void* arg)
-{
-    //rb_thread_atfork_before_exec();
-    return rb_exec(arg);
-}
-#endif
-
-#ifdef HAVE_FORK
-#ifdef FD_CLOEXEC
-#if SIZEOF_INT == SIZEOF_LONG
-#define proc_syswait (VALUE (*)(VALUE))rb_syswait
-#else
-#if 0 // not used
-static VALUE
-proc_syswait(VALUE pid)
-{
-    rb_syswait((int)pid);
-    return Qnil;
-}
-#endif
-#endif
-#endif
-
-#if 0 // not used
-static int
-move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
-{
-    long min = 0;
-    int i;
-    for (i = 0; i < n; i++) {
-        int ret;
-        while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
-            if (min <= fdp[i])
-                min = fdp[i]+1;
-            while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
-                min++;
-            ret = fcntl(fdp[i], F_DUPFD, min);
-            if (ret == -1)
-                return -1;
-            close(fdp[i]);
-            fdp[i] = ret;
-        }
-    }
-    return 0;
-}
-#endif
-
-#if 0 // not used
-static int
-pipe_nocrash(int filedes[2], VALUE fds)
-{
-    int ret;
-    ret = pipe(filedes);
-    if (ret == -1)
-        return -1;
-    if (RTEST(fds)) {
-        int save = errno;
-        if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
-            close(filedes[0]);
-            close(filedes[1]);
-            return -1;
-        }
-        errno = save;
-    }
-    return ret;
-}
-#endif
-
-/*
- * Forks child process, and returns the process ID in the parent
- * process.
- *
- * If +status+ is given, protects from any exceptions and sets the
- * jump status to it.
- *
- * In the child process, just returns 0 if +chfunc+ is +NULL+.
- * Otherwise +chfunc+ will be called with +charg+, and then the child
- * process exits with +EXIT_SUCCESS+ when it returned zero.
- *
- * In the case of the function is called and returns non-zero value,
- * the child process exits with non-+EXIT_SUCCESS+ value (normally
- * 127).  And, on the platforms where +FD_CLOEXEC+ is available,
- * +errno+ is propagated to the parent process, and this function
- * returns -1 in the parent process.  On the other platforms, just
- * returns pid.
- *
- * If fds is not Qnil, internal pipe for the errno propagation is
- * arranged to avoid conflicts of the hash keys in +fds+.
- *
- * +chfunc+ must not raise any exceptions.
- */
-rb_pid_t
-rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
-{
-    rb_pid_t pid;
-    int err, state = 0;
-    int ep[2];
-
-#define prefork() (		\
-	rb_io_flush(rb_stdout, 0), \
-	rb_io_flush(rb_stderr, 0)	\
-	)
-
-    prefork();
-
-    if (chfunc) {
-		if (pipe(ep)) return -1;
-		if (fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
-		    preserving_errno((close(ep[0]), close(ep[1])));
-		    return -1;
-		}
-    }
-    for (; (pid = fork()) < 0; prefork()) {
-	switch (errno) {
-	  case EWOULDBLOCK:
-	    if (!status && !chfunc) {
-		rb_thread_sleep(1);
-		continue;
-	    }
-	    else {
-		rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
-		if (status) *status = state;
-		if (!state) continue;
-	    }
-	  default:
-	    if (chfunc) {
-		preserving_errno((close(ep[0]), close(ep[1])));
-	    }
-	    //if (state && !status) rb_jump_tag(state);
-	    return -1;
-	}
-    }
-    if (!pid) {
-	//rb_thread_reset_timer_thread();
-	if (chfunc) {
-	    close(ep[0]);
-	    if (!(*chfunc)(charg)) _exit(EXIT_SUCCESS);
-	    err = errno;
-	    write(ep[1], &err, sizeof(err));
-#if EXIT_SUCCESS == 127
-	    _exit(EXIT_FAILURE);
-#else
-	    _exit(127);
-#endif
-	}
-	//rb_thread_start_timer_thread();
-    }
-    else if (chfunc) {
-	close(ep[1]);
-	if ((state = read(ep[0], &err, sizeof(err))) < 0) {
-	    err = errno;
-	}
-	close(ep[0]);
-	if (state) {
-	    if (status) {
-		rb_protect((VALUE (*)(VALUE))rb_syswait, (VALUE)pid, status);
-	    }
-	    else {
-		rb_syswait(pid);
-	    }
-	    errno = err;
-	    return -1;
-	}
-    }
-#endif
-    return pid;
-}
-
-/*
- *  call-seq:
- *     Kernel.fork  [{ block }]   => fixnum or nil
- *     Process.fork [{ block }]   => fixnum or nil
- *
- *  Creates a subprocess. If a block is specified, that block is run
- *  in the subprocess, and the subprocess terminates with a status of
- *  zero. Otherwise, the +fork+ call returns twice, once in
- *  the parent, returning the process ID of the child, and once in
- *  the child, returning _nil_. The child process can exit using
- *  <code>Kernel.exit!</code> to avoid running any
- *  <code>at_exit</code> functions. The parent process should
- *  use <code>Process.wait</code> to collect the termination statuses
- *  of its children or use <code>Process.detach</code> to register
- *  disinterest in their status; otherwise, the operating system
- *  may accumulate zombie processes.
- *
- *  The thread calling fork is the only thread in the created child process.
- *  fork doesn't copy other threads.
- */
-
-#if 0
-static VALUE
-rb_f_fork(VALUE obj, SEL sel)
-{
-    rb_pid_t pid;
-
-    rb_secure(2);
-
-    switch (pid = rb_fork(0, 0, 0, Qnil)) {
-      case 0:
-	//rb_thread_atfork();
-	if (rb_block_given_p()) {
-	    int status;
-
-	    rb_protect(rb_yield, Qundef, &status);
-	    ruby_stop(status);
-	}
-	return Qnil;
-
-      case -1:
-	rb_sys_fail("fork(2)");
-	return Qnil;
-
-      default:
-	return PIDT2NUM(pid);
-    }
-}
-#else
-# define rb_f_fork rb_f_notimplement
-#endif
-
-
-/*
- *  call-seq:
- *     Process.exit!(fixnum=-1)
- *
- *  Exits the process immediately. No exit handlers are
- *  run. <em>fixnum</em> is returned to the underlying system as the
- *  exit status.
- *
- *     Process.exit!(0)
- */
-
-static VALUE
-rb_f_exit_bang(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE status;
-    int istatus;
-
-    rb_secure(4);
-    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
-	switch (status) {
-	  case Qtrue:
-	    istatus = EXIT_SUCCESS;
-	    break;
-	  case Qfalse:
-	    istatus = EXIT_FAILURE;
-	    break;
-	  default:
-	    istatus = NUM2INT(status);
-	    break;
-	}
-    }
-    else {
-	istatus = EXIT_FAILURE;
-    }
-    _exit(istatus);
-
-    return Qnil;		/* not reached */
-}
-
-void
-rb_exit(int status)
-{
-#if 0 // XXX should we call pthread_exit()
-    if (GET_THREAD()->tag) {
-	VALUE args[2];
-
-	args[0] = INT2NUM(status);
-	args[1] = rb_str_new2("exit");
-	rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
-    }
-#endif
-    ruby_finalize();
-    exit(status);
-}
-
-
-/*
- *  call-seq:
- *     exit(integer=0)
- *     Kernel::exit(integer=0)
- *     Process::exit(integer=0)
- *  
- *  Initiates the termination of the Ruby script by raising the
- *  <code>SystemExit</code> exception. This exception may be caught. The
- *  optional parameter is used to return a status code to the invoking
- *  environment.
- *     
- *     begin
- *       exit
- *       puts "never get here"
- *     rescue SystemExit
- *       puts "rescued a SystemExit exception"
- *     end
- *     puts "after begin block"
- *     
- *  <em>produces:</em>
- *     
- *     rescued a SystemExit exception
- *     after begin block
- *     
- *  Just prior to termination, Ruby executes any <code>at_exit</code> functions
- *  (see Kernel::at_exit) and runs any object finalizers (see
- *  ObjectSpace::define_finalizer).
- *     
- *     at_exit { puts "at_exit function" }
- *     ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
- *     exit
- *     
- *  <em>produces:</em>
- *     
- *     at_exit function
- *     in finalizer
- */
-
-static VALUE
-rb_f_exit(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE status;
-    int istatus;
-
-    rb_secure(4);
-    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
-	switch (status) {
-	  case Qtrue:
-	    istatus = EXIT_SUCCESS;
-	    break;
-	  case Qfalse:
-	    istatus = EXIT_FAILURE;
-	    break;
-	  default:
-	    istatus = NUM2INT(status);
-#if EXIT_SUCCESS != 0
-	    if (istatus == 0)
-		istatus = EXIT_SUCCESS;
-#endif
-	    break;
-	}
-    }
-    else {
-	istatus = EXIT_SUCCESS;
-    }
-    rb_exit(istatus);
-    return Qnil;		/* not reached */
-}
-
-
-/*
- *  call-seq:
- *     abort
- *     Kernel::abort
- *     Process::abort
- *  
- *  Terminate execution immediately, effectively by calling
- *  <code>Kernel.exit(1)</code>. If _msg_ is given, it is written
- *  to STDERR prior to terminating.
- */
-
-VALUE rb_io_puts(VALUE out, SEL sel, int argc, VALUE *argv);
-
-static VALUE
-rb_f_abort(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    extern void ruby_error_print(void);
-
-    rb_secure(4);
-    if (argc == 0) {
-#if 0 // XXX
-	if (!NIL_P(GET_THREAD()->errinfo)) {
-	    ruby_error_print();
-	}
-#endif
-	rb_exit(EXIT_FAILURE);
-    }
-    else {
-	VALUE args[2];
-
-	rb_scan_args(argc, argv, "1", &args[1]);
-	StringValue(argv[0]);
-	rb_io_puts(rb_stderr, 0, argc, argv);
-	args[0] = INT2NUM(EXIT_FAILURE);
-	rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
-    }
-    return Qnil;		/* not reached */
-}
-
-
-#if defined(sun)
-#define signal(a,b) sigset(a,b)
-#else
-# if defined(POSIX_SIGNAL)
-#  define signal(a,b) posix_signal(a,b)
-# endif
-#endif
-
-void
-rb_syswait(rb_pid_t pid)
-{
-    static int overriding;
-#ifdef SIGHUP
-    RETSIGTYPE (*hfunc)(int) = 0;
-#endif
-#ifdef SIGQUIT
-    RETSIGTYPE (*qfunc)(int) = 0;
-#endif
-    RETSIGTYPE (*ifunc)(int) = 0;
-    int status;
-    int i, hooked = Qfalse;
-
-    if (!overriding) {
-#ifdef SIGHUP
-	hfunc = signal(SIGHUP, SIG_IGN);
-#endif
-#ifdef SIGQUIT
-	qfunc = signal(SIGQUIT, SIG_IGN);
-#endif
-	ifunc = signal(SIGINT, SIG_IGN);
-	overriding = Qtrue;
-	hooked = Qtrue;
-    }
-
-    do {
-	i = rb_waitpid(pid, &status, 0);
-    } while (i == -1 && errno == EINTR);
-
-    if (hooked) {
-#ifdef SIGHUP
-	signal(SIGHUP, hfunc);
-#endif
-#ifdef SIGQUIT
-	signal(SIGQUIT, qfunc);
-#endif
-	signal(SIGINT, ifunc);
-	overriding = Qfalse;
-    }
-}
-
-static rb_pid_t
-rb_spawn_internal(int argc, VALUE *argv, int default_close_others)
-{
-    rb_pid_t status;
-    VALUE prog;
-    struct rb_exec_arg earg;
-#if !defined HAVE_FORK
-    struct rb_exec_arg sarg;
-#endif
-
-    prog = rb_exec_arg_init(argc, argv, Qtrue, &earg);
-    if (NIL_P(rb_ary_entry(earg.options, EXEC_OPTION_CLOSE_OTHERS))) {
-        VALUE v = default_close_others ? Qtrue : Qfalse;
-        rb_exec_arg_addopt(&earg, ID2SYM(rb_intern("close_others")), v);
-    }
-    rb_exec_arg_fixup(&earg);
-
-#if defined HAVE_FORK
-    status = rb_fork(&status, rb_exec_atfork, &earg, earg.redirect_fds);
-    if (prog && earg.argc) earg.argv[0] = prog;
-#else
-    if (rb_run_exec_options(&earg, &sarg) < 0) {
-        return -1;
-    }
-
-    argc = earg.argc;
-    argv = earg.argv;
-    if (prog && argc) argv[0] = prog;
-# if defined HAVE_SPAWNV
-    if (!argc) {
-	status = proc_spawn(RSTRING_PTR(prog));
-    }
-    else {
-	status = proc_spawn_n(argc, argv, prog);
-    }
-#  if defined(_WIN32)
-    if (status == -1)
-	rb_last_status_set(0x7f << 8, 0);
-#  endif
-# else
-    if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
-    status = system(StringValuePtr(prog));
-#  if defined(__human68k__) || defined(__DJGPP__)
-    rb_last_status_set(status == -1 ? 127 : status, 0);
-#  else
-    rb_last_status_set((status & 0xff) << 8, 0);
-#  endif
-# endif
-
-    rb_run_exec_options(&sarg, NULL);
-#endif
-    return status;
-}
-
-rb_pid_t
-rb_spawn(int argc, VALUE *argv)
-{
-    return rb_spawn_internal(argc, argv, Qtrue);
-}
-
-/*
- *  call-seq:
- *     system([env,] cmd [, arg, ...] [,options])    => true, false or nil
- *
- *  Executes _cmd_ in a subshell, returning +true+ if the command
- *  gives zero exit status, +false+ for non zero exit status. Returns
- *  +nil+ if command execution fails.  An error status is available in
- *  <code>$?</code>. The arguments are processed in the same way as
- *  for <code>Kernel::exec</code>.
- *
- *  The hash arguments, env and options, are same as
- *  <code>exec</code> and <code>spawn</code>.
- *  See <code>spawn</code> for details.
- *
- *     system("echo *")
- *     system("echo", "*")
- *
- *  <em>produces:</em>
- *
- *     config.h main.rb
- *     *
- */
-
-static VALUE
-rb_f_system(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    int status;
-
-#if defined(SIGCLD) && !defined(SIGCHLD)
-# define SIGCHLD SIGCLD
-#endif
-
-#ifdef SIGCHLD
-    RETSIGTYPE (*chfunc)(int);
-
-    chfunc = signal(SIGCHLD, SIG_DFL);
-#endif
-    status = rb_spawn_internal(argc, argv, Qfalse);
-#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
-    if (status > 0) {
-	rb_syswait(status);
-    }
-#endif
-#ifdef SIGCHLD
-    signal(SIGCHLD, chfunc);
-#endif
-    if (status < 0) {
-	return Qnil;
-    }
-    status = NUM2INT(rb_last_status_get());
-    if (status == EXIT_SUCCESS) return Qtrue;
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     spawn([env,] cmd [, arg, ...] [,options])     => pid
- *
- *  Similar to <code>Kernel::system</code> except for not waiting for
- *  end of _cmd_, but returns its <i>pid</i>.
- *
- *  If a hash is given as +env+, the environment is
- *  updated by +env+ before <code>exec(2)</code> in the child process.
- *
- *  If a hash is given as +options+,
- *  it specifies
- *  process group,
- *  resource limit, 
- *  current directory,
- *  umask and
- *  redirects for the child process.
- *  Also, it can be specified to clear environment variables.
- *
- *  The <code>:unsetenv_others</code> key in +options+ specifies
- *  to clear environment variables, other than specified by +env+.
- *
- *    pid = spawn(command, :unsetenv_others=>true) # no environment variable
- *    pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
- *
- *  The <code>:pgroup</code> key in +options+ specifies a process group.
- *  The corresponding value should be true, zero or positive integer.
- *  true and zero means the process should be a process leader.
- *  Other values specifies a process group to be belongs.
- *
- *    pid = spawn(command, :pgroup=>true) # process leader
- *    pid = spawn(command, :pgroup=>10) # belongs to the process group 10
- *
- *  The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
- *  <em>foo</em> should be one of resource types such as <code>core</code>
- *  The corresponding value should be an integer or an array which have one or
- *  two integers: same as cur_limit and max_limit arguments for
- *  Process.setrlimit.
- *
- *    pid = spawn(command, :rlimit_core=>0) # never dump core.
- *    cur, max = Process.getrlimit(:CORE)
- *    pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
- *    pid = spawn(command, :rlimit_core=>max) # enable core dump
- *
- *  The <code>:chdir</code> key in +options+ specifies the current directory.
- *
- *    pid = spawn(command, :chdir=>"/var/tmp")
- *
- *  The <code>:umask</code> key in +options+ specifies the umask.
- *
- *    pid = spawn(command, :umask=>077)
- *
- *  The :in, :out, :err, a fixnum, an IO and an array key specifies a redirect.
- *  The redirection maps a file descriptor in the child process.
- *
- *  For example, stderr can be merged into stdout:
- *
- *    pid = spawn(command, :err=>:out)
- *    pid = spawn(command, STDERR=>STDOUT)
- *    pid = spawn(command, 2=>1)
- *
- *  The hash keys specifies a file descriptor
- *  in the child process started by <code>spawn</code>.
- *  :err, STDERR and 2 specifies the standard error stream.
- *
- *  The hash values specifies a file descriptor
- *  in the parent process which invokes <code>spawn</code>.
- *  :out, STDOUT and 1 specifies the standard output stream.
- *
- *  The standard output in the child process is not specified.
- *  So it is inherited from the parent process.
- *
- *  The standard input stream can be specifed by :in, STDIN and 0.
- *  
- *  A filename can be specified as a hash value.
- *
- *    pid = spawn(command, STDIN=>"/dev/null") # read mode
- *    pid = spawn(command, STDOUT=>"/dev/null") # write mode
- *    pid = spawn(command, STDERR=>"log") # write mode
- *    pid = spawn(command, 3=>"/dev/null") # read mode
- *
- *  For standard output and standard error,
- *  it is opened in write mode.
- *  Otherwise read mode is used.
- *
- *  For specifying flags and permission of file creation explicitly,
- *  an array is used instead.
- *
- *    pid = spawn(command, STDIN=>["file"]) # read mode is assumed
- *    pid = spawn(command, STDIN=>["file", "r"])
- *    pid = spawn(command, STDOUT=>["log", "w"]) # 0644 assumed
- *    pid = spawn(command, STDOUT=>["log", "w", 0600])
- *    pid = spawn(command, STDOUT=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
- *
- *  The array specifies a filename, flags and permission.
- *  The flags can be a string or an integer.
- *  If the flags is ommitted or nil, File::RDONLY is assumed.
- *  The permission should be an integer.
- *  If the permission is ommitted or nil, 0644 is assumed.
- *
- *  If an array of IOs and integers are specified as a hash key,
- *  all the elemetns are redirected.
- *
- *    # standard output and standard error is redirected to log file.
- *    pid = spawn(command, [STDOUT, STDERR]=>["log", "w"])
- *
- *  spawn closes all non-standard unspecified descriptors by default.
- *  The "standard" descriptors are 0, 1 and 2.
- *  This behavior is specified by :close_others option.
- *  :close_others doesn't affect the standard descriptors which are
- *  closed only if :close is specified explicitly.
- *
- *    pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
- *    pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
- *
- *  :close_others is true by default for spawn and IO.popen.
- *
- *  So IO.pipe and spawn can be used as IO.popen.
- *
- *    # similar to r = IO.popen(command)
- *    r, w = IO.pipe
- *    pid = spawn(command, STDOUT=>w)   # r, w is closed in the child process.
- *    w.close
- *
- *  :close is specified as a hash value to close a fd individualy.
- *
- *    f = open(foo)
- *    system(command, f=>:close)        # don't inherit f.
- *
- *  It is also possible to exchange file descriptors.
- *
- *    pid = spawn(command, STDOUT=>STDERR, STDERR=>STDOUT)
- *
- *  The hash keys specify file descriptors in the child process.
- *  The hash values specifies file descriptors in the parent process.
- *  So the above specifies exchanging STDOUT and STDERR.
- *  Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
- *  file descriptor mapping.
- *
- */
-
-static VALUE
-rb_f_spawn(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    rb_pid_t pid;
-
-    pid = rb_spawn(argc, argv);
-    if (pid == -1) rb_sys_fail(RSTRING_PTR(argv[0]));
-    return PIDT2NUM(pid);
-}
-
-/*
- *  call-seq:
- *     sleep([duration])    => fixnum
- *
- *  Suspends the current thread for _duration_ seconds (which may be any number,
- *  including a +Float+ with fractional seconds). Returns the actual number of
- *  seconds slept (rounded), which may be less than that asked for if another
- *  thread calls <code>Thread#run</code>. Zero arguments causes +sleep+ to sleep
- *  forever.
- *
- *     Time.new    #=> 2008-03-08 19:56:19 +0900
- *     sleep 1.2   #=> 1
- *     Time.new    #=> 2008-03-08 19:56:20 +0900
- *     sleep 1.9   #=> 2
- *     Time.new    #=> 2008-03-08 19:56:22 +0900
- */
-
-static VALUE
-rb_f_sleep(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    int beg, end;
-
-    beg = time(0);
-    if (argc == 0) {
-	rb_thread_sleep_forever();
-    }
-    else if (argc == 1) {
-	rb_thread_wait_for(rb_time_interval(argv[0]));
-    }
-    else {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-
-    end = time(0) - beg;
-
-    return INT2FIX(end);
-}
-
-
-/*
- *  call-seq:
- *     Process.getpgrp   => integer
- *
- *  Returns the process group ID for this process. Not available on
- *  all platforms.
- *
- *     Process.getpgid(0)   #=> 25527
- *     Process.getpgrp      #=> 25527
- */
-
-static VALUE
-proc_getpgrp(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID) || defined(HAVE_GETPGID)
-    rb_pid_t pgrp;
-#endif
-
-    rb_secure(2);
-#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
-    pgrp = getpgrp();
-    if (pgrp < 0) rb_sys_fail(0);
-    return PIDT2NUM(pgrp);
-#else
-# ifdef HAVE_GETPGID
-    pgrp = getpgid(0);
-    if (pgrp < 0) rb_sys_fail(0);
-    return PIDT2NUM(pgrp);
-# else
-    rb_notimplement();
-# endif
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.setpgrp   => 0
- *
- *  Equivalent to <code>setpgid(0,0)</code>. Not available on all
- *  platforms.
- */
-
-static VALUE
-proc_setpgrp(VALUE rcv, SEL sel)
-{
-    rb_secure(2);
-  /* check for posix setpgid() first; this matches the posix */
-  /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
-  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
-  /* this confusion. */
-#ifdef HAVE_SETPGID
-    if (setpgid(0,0) < 0) rb_sys_fail(0);
-#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
-    if (setpgrp() < 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return INT2FIX(0);
-}
-
-
-/*
- *  call-seq:
- *     Process.getpgid(pid)   => integer
- *
- *  Returns the process group ID for the given process id. Not
- *  available on all platforms.
- *
- *     Process.getpgid(Process.ppid())   #=> 25527
- */
-
-static VALUE
-proc_getpgid(VALUE obj, SEL sel, VALUE pid)
-{
-#if defined(HAVE_GETPGID) && !defined(__CHECKER__)
-    rb_pid_t i;
-
-    rb_secure(2);
-    i = getpgid(NUM2PIDT(pid));
-    if (i < 0) rb_sys_fail(0);
-    return PIDT2NUM(i);
-#else
-    rb_notimplement();
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.setpgid(pid, integer)   => 0
- *
- *  Sets the process group ID of _pid_ (0 indicates this
- *  process) to <em>integer</em>. Not available on all platforms.
- */
-
-static VALUE
-proc_setpgid(VALUE obj, SEL sel, VALUE pid, VALUE pgrp)
-{
-#ifdef HAVE_SETPGID
-    rb_pid_t ipid, ipgrp;
-
-    rb_secure(2);
-    ipid = NUM2PIDT(pid);
-    ipgrp = NUM2PIDT(pgrp);
-
-    if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
-    return INT2FIX(0);
-#else
-    rb_notimplement();
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.setsid   => fixnum
- *
- *  Establishes this process as a new session and process group
- *  leader, with no controlling tty. Returns the session id. Not
- *  available on all platforms.
- *
- *     Process.setsid   #=> 27422
- */
-
-static VALUE
-proc_setsid(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_SETSID)
-    rb_pid_t pid;
-
-    rb_secure(2);
-    pid = setsid();
-    if (pid < 0) rb_sys_fail(0);
-    return PIDT2NUM(pid);
-#elif defined(HAVE_SETPGRP) && defined(TIOCNOTTY)
-    rb_pid_t pid;
-    int ret;
-
-    rb_secure(2);
-    pid = getpid();
-#if defined(SETPGRP_VOID)
-    ret = setpgrp();
-    /* If `pid_t setpgrp(void)' is equivalent to setsid(),
-       `ret' will be the same value as `pid', and following open() will fail.
-       In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
-#else
-    ret = setpgrp(0, pid);
-#endif
-    if (ret == -1) rb_sys_fail(0);
-
-    if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
-	ioctl(fd, TIOCNOTTY, NULL);
-	close(fd);
-    }
-    return PIDT2NUM(pid);
-#else
-    rb_notimplement();
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.getpriority(kind, integer)   => fixnum
- *
- *  Gets the scheduling priority for specified process, process group,
- *  or user. <em>kind</em> indicates the kind of entity to find: one
- *  of <code>Process::PRIO_PGRP</code>,
- *  <code>Process::PRIO_USER</code>, or
- *  <code>Process::PRIO_PROCESS</code>. _integer_ is an id
- *  indicating the particular process, process group, or user (an id
- *  of 0 means _current_). Lower priorities are more favorable
- *  for scheduling. Not available on all platforms.
- *
- *     Process.getpriority(Process::PRIO_USER, 0)      #=> 19
- *     Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19
- */
-
-static VALUE
-proc_getpriority(VALUE obj, SEL sel, VALUE which, VALUE who)
-{
-#ifdef HAVE_GETPRIORITY
-    int prio, iwhich, iwho;
-
-    rb_secure(2);
-    iwhich = NUM2INT(which);
-    iwho   = NUM2INT(who);
-
-    errno = 0;
-    prio = getpriority(iwhich, iwho);
-    if (errno) rb_sys_fail(0);
-    return INT2FIX(prio);
-#else
-    rb_notimplement();
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.setpriority(kind, integer, priority)   => 0
- *
- *  See <code>Process#getpriority</code>.
- *
- *     Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
- *     Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
- *     Process.getpriority(Process::PRIO_USER, 0)          #=> 19
- *     Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19
- */
-
-static VALUE
-proc_setpriority(VALUE obj, SEL sel, VALUE which, VALUE who, VALUE prio)
-{
-#ifdef HAVE_GETPRIORITY
-    int iwhich, iwho, iprio;
-
-    rb_secure(2);
-    iwhich = NUM2INT(which);
-    iwho   = NUM2INT(who);
-    iprio  = NUM2INT(prio);
-
-    if (setpriority(iwhich, iwho, iprio) < 0)
-	rb_sys_fail(0);
-    return INT2FIX(0);
-#else
-    rb_notimplement();
-#endif
-}
-
-#if defined(RLIM2NUM)
-static int
-rlimit_resource_name2int(const char *name, int casetype)
-{
-    size_t len = strlen(name);
-    if (16 < len) return -1;
-    if (casetype == 1) {
-        int i;
-        char *name2 = ALLOCA_N(char, len+1);
-        for (i = 0; i < len; i++) {
-            if (!ISLOWER(name[i]))
-                return -1;
-            name2[i] = TOUPPER(name[i]);
-        }
-        name2[len] = '\0';
-        name = name2;
-    }
-
-    switch (*name) {
-      case 'A':
-#ifdef RLIMIT_AS
-        if (strcmp(name, "AS") == 0) return RLIMIT_AS;
-#endif
-        break;
-
-      case 'C':
-#ifdef RLIMIT_CORE
-        if (strcmp(name, "CORE") == 0) return RLIMIT_CORE;
-#endif
-#ifdef RLIMIT_CPU
-        if (strcmp(name, "CPU") == 0) return RLIMIT_CPU;
-#endif
-        break;
-
-      case 'D':
-#ifdef RLIMIT_DATA
-        if (strcmp(name, "DATA") == 0) return RLIMIT_DATA;
-#endif
-        break;
-
-      case 'F':
-#ifdef RLIMIT_FSIZE
-        if (strcmp(name, "FSIZE") == 0) return RLIMIT_FSIZE;
-#endif
-        break;
-
-      case 'M':
-#ifdef RLIMIT_MEMLOCK
-        if (strcmp(name, "MEMLOCK") == 0) return RLIMIT_MEMLOCK;
-#endif
-        break;
-
-      case 'N':
-#ifdef RLIMIT_NOFILE
-        if (strcmp(name, "NOFILE") == 0) return RLIMIT_NOFILE;
-#endif
-#ifdef RLIMIT_NPROC
-        if (strcmp(name, "NPROC") == 0) return RLIMIT_NPROC;
-#endif
-        break;
-
-      case 'R':
-#ifdef RLIMIT_RSS
-        if (strcmp(name, "RSS") == 0) return RLIMIT_RSS;
-#endif
-        break;
-
-      case 'S':
-#ifdef RLIMIT_STACK
-        if (strcmp(name, "STACK") == 0) return RLIMIT_STACK;
-#endif
-#ifdef RLIMIT_SBSIZE
-        if (strcmp(name, "SBSIZE") == 0) return RLIMIT_SBSIZE;
-#endif
-        break;
-    }
-    return -1;
-}
-
-static int
-rlimit_type_by_hname(const char *name)
-{
-    return rlimit_resource_name2int(name, 0);
-}
-
-static int
-rlimit_type_by_lname(const char *name)
-{
-    return rlimit_resource_name2int(name, 1);
-}
-
-static int
-rlimit_resource_type(VALUE rtype)
-{
-    const char *name;
-    VALUE v;
-    int r;
-
-    switch (TYPE(rtype)) {
-      case T_SYMBOL:
-        name = rb_sym2name(rtype);
-        break;
-
-      default:
-        v = rb_check_string_type(rtype);
-        if (!NIL_P(v)) {
-            rtype = v;
-      case T_STRING:
-            name = StringValueCStr(rtype);
-            break;
-        }
-        /* fall through */
-
-      case T_FIXNUM:
-      case T_BIGNUM:
-        return NUM2INT(rtype);
-    }
-
-    r = rlimit_type_by_hname(name);
-    if (r != -1)
-        return r;
-
-    rb_raise(rb_eArgError, "invalid resource name: %s", name);
-}
-
-static rlim_t
-rlimit_resource_value(VALUE rval)
-{
-    const char *name;
-    VALUE v;
-
-    switch (TYPE(rval)) {
-      case T_SYMBOL:
-        name = rb_sym2name(rval);
-        break;
-
-      default:
-        v = rb_check_string_type(rval);
-        if (!NIL_P(v)) {
-            rval = v;
-      case T_STRING:
-            name = StringValueCStr(rval);
-            break;
-        }
-        /* fall through */
-
-      case T_FIXNUM:
-      case T_BIGNUM:
-        return NUM2RLIM(rval);
-    }
-
-#ifdef RLIM_INFINITY
-    if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
-#endif
-#ifdef RLIM_SAVED_MAX
-    if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
-#endif
-#ifdef RLIM_SAVED_CUR
-    if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
-#endif
-    rb_raise(rb_eArgError, "invalid resource value: %s", name);
-}
-#endif
-
-/*
- *  call-seq:
- *     Process.getrlimit(resource)   => [cur_limit, max_limit]
- *
- *  Gets the resource limit of the process.
- *  _cur_limit_ means current (soft) limit and
- *  _max_limit_ means maximum (hard) limit.
- *
- *  _resource_ indicates the kind of resource to limit.
- *  It is specified as a symbol such as <code>:CORE</code>,
- *  a string such as <code>"CORE"</code> or
- *  a constant such as <code>Process::RLIMIT_CORE</code>.
- *  See Process.setrlimit for details.
- *
- *  _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
- *  <code>Process::RLIM_SAVED_MAX</code> or
- *  <code>Process::RLIM_SAVED_CUR</code>.
- *  See Process.setrlimit and the system getrlimit(2) manual for details.
- */
-
-static VALUE
-proc_getrlimit(VALUE obj, SEL sel, VALUE resource)
-{
-#if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
-    struct rlimit rlim;
-
-    rb_secure(2);
-
-    if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
-	rb_sys_fail("getrlimit");
-    }
-    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
-#else
-    rb_notimplement();
-#endif
-}
-
-/*
- *  call-seq:
- *     Process.setrlimit(resource, cur_limit, max_limit)        => nil
- *     Process.setrlimit(resource, cur_limit)                   => nil
- *
- *  Sets the resource limit of the process.
- *  _cur_limit_ means current (soft) limit and
- *  _max_limit_ means maximum (hard) limit.
- *
- *  If _max_limit_ is not given, _cur_limit_ is used.
- *
- *  _resource_ indicates the kind of resource to limit.
- *  It should be a symbol such as <code>:CORE</code>,
- *  a string such as <code>"CORE"</code> or
- *  a constant such as <code>Process::RLIMIT_CORE</code>.
- *  The available resources are OS dependent.
- *  Ruby may support following resources.
- *
- *  [CORE] core size (bytes) (SUSv3)
- *  [CPU] CPU time (seconds) (SUSv3)
- *  [DATA] data segment (bytes) (SUSv3)
- *  [FSIZE] file size (bytes) (SUSv3)
- *  [NOFILE] file descriptors (number) (SUSv3)
- *  [STACK] stack size (bytes) (SUSv3)
- *  [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
- *  [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
- *  [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
- *  [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
- *  [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
- *
- *  _cur_limit_ and _max_limit_ may be
- *  <code>:INFINITY</code>, <code>"INFINITY"</code> or
- *  <code>Process::RLIM_INFINITY</code>,
- *  which means that the resource is not limited.
- *  They may be <code>Process::RLIM_SAVED_MAX</code>,
- *  <code>Process::RLIM_SAVED_CUR</code> and
- *  corresponding symbols and strings too.
- *  See system setrlimit(2) manual for details.
- *
- *  The following example raise the soft limit of core size to
- *  the hard limit to try to make core dump possible.
- *
- *    Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
- *
- */
-
-static VALUE
-proc_setrlimit(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-#if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
-    VALUE resource, rlim_cur, rlim_max;
-    struct rlimit rlim;
-
-    rb_secure(2);
-
-    rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
-    if (rlim_max == Qnil)
-        rlim_max = rlim_cur;
-
-    rlim.rlim_cur = rlimit_resource_value(rlim_cur);
-    rlim.rlim_max = rlimit_resource_value(rlim_max);
-
-    if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
-	rb_sys_fail("setrlimit");
-    }
-    return Qnil;
-#else
-    rb_notimplement();
-#endif
-}
-
-static int under_uid_switch = 0;
-static void
-check_uid_switch(void)
-{
-    rb_secure(2);
-    if (under_uid_switch) {
-	rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
-    }
-}
-
-static int under_gid_switch = 0;
-static void
-check_gid_switch(void)
-{
-    rb_secure(2);
-    if (under_gid_switch) {
-	rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
-    }
-}
-
-
-/*********************************************************************
- * Document-class: Process::Sys
- *
- *  The <code>Process::Sys</code> module contains UID and GID
- *  functions which provide direct bindings to the system calls of the
- *  same names instead of the more-portable versions of the same
- *  functionality found in the <code>Process</code>,
- *  <code>Process::UID</code>, and <code>Process::GID</code> modules.
- */
-
-
-/*
- *  call-seq:
- *     Process::Sys.setuid(integer)   => nil
- *
- *  Set the user ID of the current process to _integer_. Not
- *  available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setuid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETUID
-    check_uid_switch();
-    if (setuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-
-/*
- *  call-seq:
- *     Process::Sys.setruid(integer)   => nil
- *
- *  Set the real user ID of the calling process to _integer_.
- *  Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setruid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETRUID
-    check_uid_switch();
-    if (setruid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.seteuid(integer)   => nil
- *
- *  Set the effective user ID of the calling process to
- *  _integer_.  Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_seteuid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETEUID
-    check_uid_switch();
-    if (seteuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.setreuid(rid, eid)   => nil
- *
- *  Sets the (integer) real and/or effective user IDs of the current
- *  process to _rid_ and _eid_, respectively. A value of
- *  <code>-1</code> for either means to leave that ID unchanged. Not
- *  available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setreuid(VALUE obj, SEL sel, VALUE rid, VALUE eid)
-{
-#if defined HAVE_SETREUID
-    check_uid_switch();
-    if (setreuid(NUM2UIDT(rid),NUM2UIDT(eid)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.setresuid(rid, eid, sid)   => nil
- *
- *  Sets the (integer) real, effective, and saved user IDs of the
- *  current process to _rid_, _eid_, and _sid_ respectively. A
- *  value of <code>-1</code> for any value means to
- *  leave that ID unchanged. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setresuid(VALUE obj, SEL sel, VALUE rid, VALUE eid, VALUE sid)
-{
-#if defined HAVE_SETRESUID
-    check_uid_switch();
-    if (setresuid(NUM2UIDT(rid),NUM2UIDT(eid),NUM2UIDT(sid)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process.uid           => fixnum
- *     Process::UID.rid      => fixnum
- *     Process::Sys.getuid   => fixnum
- *
- *  Returns the (real) user ID of this process.
- *
- *     Process.uid   #=> 501
- */
-
-static VALUE
-proc_getuid(VALUE obj, SEL sel)
-{
-    rb_uid_t uid = getuid();
-    return UIDT2NUM(uid);
-}
-
-
-/*
- *  call-seq:
- *     Process.uid= integer   => numeric
- *
- *  Sets the (integer) user ID for this process. Not available on all
- *  platforms.
- */
-
-static VALUE
-proc_setuid(VALUE obj, SEL sel, VALUE id)
-{
-    rb_uid_t uid;
-
-    check_uid_switch();
-
-    uid = NUM2UIDT(id);
-#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
-    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREUID
-    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRUID
-    if (setruid(uid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
-    {
-	if (geteuid() == uid) {
-	    if (setuid(uid) < 0) rb_sys_fail(0);
-	}
-	else {
-	    rb_notimplement();
-	}
-    }
-#else
-    rb_notimplement();
-#endif
-    return id;
-}
-
-
-/********************************************************************
- *
- * Document-class: Process::UID
- *
- *  The <code>Process::UID</code> module contains a collection of
- *  module functions which can be used to portably get, set, and
- *  switch the current process's real, effective, and saved user IDs.
- *
- */
-
-static rb_uid_t SAVED_USER_ID = -1;
-
-#ifdef BROKEN_SETREUID
-int
-setreuid(rb_uid_t ruid, rb_uid_t euid)
-{
-    if (ruid != -1 && ruid != getuid()) {
-	if (euid == -1) euid = geteuid();
-	if (setuid(ruid) < 0) return -1;
-    }
-    if (euid != -1 && euid != geteuid()) {
-	if (seteuid(euid) < 0) return -1;
-    }
-    return 0;
-}
-#endif
-
-/*
- *  call-seq:
- *     Process::UID.change_privilege(integer)   => fixnum
- *
- *  Change the current process's real and effective user ID to that
- *  specified by _integer_. Returns the new user ID. Not
- *  available on all platforms.
- *
- *     [Process.uid, Process.euid]          #=> [0, 0]
- *     Process::UID.change_privilege(31)    #=> 31
- *     [Process.uid, Process.euid]          #=> [31, 31]
- */
-
-static VALUE
-p_uid_change_privilege(VALUE obj, SEL sel, VALUE id)
-{
-    rb_uid_t uid;
-
-    check_uid_switch();
-
-    uid = NUM2UIDT(id);
-
-    if (geteuid() == 0) { /* root-user */
-#if defined(HAVE_SETRESUID)
-	if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
-	SAVED_USER_ID = uid;
-#elif defined(HAVE_SETUID)
-	if (setuid(uid) < 0) rb_sys_fail(0);
-	SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
-	if (getuid() == uid) {
-	    if (SAVED_USER_ID == uid) {
-		if (setreuid(-1, uid) < 0) rb_sys_fail(0);
-	    } else {
-		if (uid == 0) { /* (r,e,s) == (root, root, x) */
-		    if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
-		    if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
-		    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = uid;
-		} else {
-		    if (setreuid(0, -1) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = 0;
-		    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = uid;
-		}
-	    }
-	} else {
-	    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	}
-#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
-	if (getuid() == uid) {
-	    if (SAVED_USER_ID == uid) {
-		if (seteuid(uid) < 0) rb_sys_fail(0);
-	    } else {
-		if (uid == 0) {
-		    if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = 0;
-		    if (setruid(0) < 0) rb_sys_fail(0);
-		} else {
-		    if (setruid(0) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = 0;
-		    if (seteuid(uid) < 0) rb_sys_fail(0);
-		    if (setruid(uid) < 0) rb_sys_fail(0);
-		    SAVED_USER_ID = uid;
-		}
-	    }
-	} else {
-	    if (seteuid(uid) < 0) rb_sys_fail(0);
-	    if (setruid(uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	}
-#else
-	rb_notimplement();
-#endif
-    } else { /* unprivileged user */
-#if defined(HAVE_SETRESUID)
-	if (setresuid((getuid() == uid)? -1: uid,
-		      (geteuid() == uid)? -1: uid,
-		      (SAVED_USER_ID == uid)? -1: uid) < 0) rb_sys_fail(0);
-	SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
-	if (SAVED_USER_ID == uid) {
-	    if (setreuid((getuid() == uid)? -1: uid,
-			 (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
-	} else if (getuid() != uid) {
-	    if (setreuid(uid, (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	} else if (/* getuid() == uid && */ geteuid() != uid) {
-	    if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
-	} else { /* getuid() == uid && geteuid() == uid */
-	    if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
-	    if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
-	}
-#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
-	if (SAVED_USER_ID == uid) {
-	    if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
-	    if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
-	} else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
-	    if (getuid() != uid) {
-		if (setruid(uid) < 0) rb_sys_fail(0);
-		SAVED_USER_ID = uid;
-	    } else {
-		if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
-		SAVED_USER_ID = uid;
-		if (setruid(uid) < 0) rb_sys_fail(0);
-	    }
-	} else if (/* geteuid() != uid && */ getuid() == uid) {
-	    if (seteuid(uid) < 0) rb_sys_fail(0);
-	    if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	    if (setruid(uid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_44BSD_SETUID
-	if (getuid() == uid) {
-	    /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
-	    if (setuid(uid) < 0) rb_sys_fail(0);
-	    SAVED_USER_ID = uid;
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_SETEUID
-	if (getuid() == uid && SAVED_USER_ID == uid) {
-	    if (seteuid(uid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_SETUID
-	if (getuid() == uid && SAVED_USER_ID == uid) {
-	    if (setuid(uid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#else
-	rb_notimplement();
-#endif
-    }
-    return id;
-}
-
-
-
-/*
- *  call-seq:
- *     Process::Sys.setgid(integer)   => nil
- *
- *  Set the group ID of the current process to _integer_. Not
- *  available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setgid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETGID
-    check_gid_switch();
-    if (setgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.setrgid(integer)   => nil
- *
- *  Set the real group ID of the calling process to _integer_.
- *  Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setrgid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETRGID
-    check_gid_switch();
-    if (setrgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-
-/*
- *  call-seq:
- *     Process::Sys.setegid(integer)   => nil
- *
- *  Set the effective group ID of the calling process to
- *  _integer_.  Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setegid(VALUE obj, SEL sel, VALUE id)
-{
-#if defined HAVE_SETEGID
-    check_gid_switch();
-    if (setegid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.setregid(rid, eid)   => nil
- *
- *  Sets the (integer) real and/or effective group IDs of the current
- *  process to <em>rid</em> and <em>eid</em>, respectively. A value of
- *  <code>-1</code> for either means to leave that ID unchanged. Not
- *  available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setregid(VALUE obj, SEL sel, VALUE rid, VALUE eid)
-{
-#if defined HAVE_SETREGID
-    check_gid_switch();
-    if (setregid(NUM2GIDT(rid),NUM2GIDT(eid)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     Process::Sys.setresgid(rid, eid, sid)   => nil
- *
- *  Sets the (integer) real, effective, and saved user IDs of the
- *  current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
- *  respectively. A value of <code>-1</code> for any value means to
- *  leave that ID unchanged. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setresgid(VALUE obj, SEL sel, VALUE rid, VALUE eid, VALUE sid)
-{
-#if defined HAVE_SETRESGID
-    check_gid_switch();
-    if (setresgid(NUM2GIDT(rid),NUM2GIDT(eid),NUM2GIDT(sid)) != 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     Process::Sys.issetugid   => true or false
- *
- *  Returns +true+ if the process was created as a result
- *  of an execve(2) system call which had either of the setuid or
- *  setgid bits set (and extra privileges were given as a result) or
- *  if it has changed any of its real, effective or saved user or
- *  group IDs since it began execution.
- *
- */
-
-static VALUE
-p_sys_issetugid(VALUE obj, SEL sel)
-{
-#if defined HAVE_ISSETUGID
-    rb_secure(2);
-    if (issetugid()) {
-	return Qtrue;
-    } else {
-	return Qfalse;
-    }
-#else
-    rb_notimplement();
-    return Qnil;		/* not reached */
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.gid           => fixnum
- *     Process::GID.rid      => fixnum
- *     Process::Sys.getgid   => fixnum
- *
- *  Returns the (real) group ID for this process.
- *
- *     Process.gid   #=> 500
- */
-
-static VALUE
-proc_getgid(VALUE obj, SEL sel)
-{
-    rb_gid_t gid = getgid();
-    return GIDT2NUM(gid);
-}
-
-
-/*
- *  call-seq:
- *     Process.gid= fixnum   => fixnum
- *
- *  Sets the group ID for this process.
- */
-
-static VALUE
-proc_setgid(VALUE obj, SEL sel, VALUE id)
-{
-    rb_gid_t gid;
-
-    check_gid_switch();
-
-    gid = NUM2GIDT(id);
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
-    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
-    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRGID
-    if (setrgid(gid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
-    {
-	if (getegid() == gid) {
-	    if (setgid(gid) < 0) rb_sys_fail(0);
-	}
-	else {
-	    rb_notimplement();
-	}
-    }
-#else
-    rb_notimplement();
-#endif
-    return GIDT2NUM(gid);
-}
-
-
-static size_t maxgroups = NGROUPS_MAX;
-
-
-/*
- *  call-seq:
- *     Process.groups   => array
- *
- *  Get an <code>Array</code> of the gids of groups in the
- *  supplemental group access list for this process.
- *
- *     Process.groups   #=> [27, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_getgroups(VALUE obj, SEL sel)
-{
-#ifdef HAVE_GETGROUPS
-    VALUE ary;
-    size_t ngroups;
-    rb_gid_t *groups;
-    int i;
-
-    groups = ALLOCA_N(rb_gid_t, maxgroups);
-
-    ngroups = getgroups(maxgroups, groups);
-    if (ngroups == -1)
-	rb_sys_fail(0);
-
-    ary = rb_ary_new();
-    for (i = 0; i < ngroups; i++)
-	rb_ary_push(ary, GIDT2NUM(groups[i]));
-
-    return ary;
-#else
-    rb_notimplement();
-    return Qnil;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.groups= array   => array
- *
- *  Set the supplemental group access list to the given
- *  <code>Array</code> of group IDs.
- *
- *     Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
- *     Process.groups = [27, 6, 10, 11]   #=> [27, 6, 10, 11]
- *     Process.groups   #=> [27, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_setgroups(VALUE obj, SEL sel, VALUE ary)
-{
-#ifdef HAVE_SETGROUPS
-    size_t ngroups;
-    rb_gid_t *groups;
-    int i;
-    struct group *gr;
-
-    Check_Type(ary, T_ARRAY);
-
-    ngroups = RARRAY_LEN(ary);
-    if (ngroups > maxgroups)
-	rb_raise(rb_eArgError, "too many groups, %lu max", (unsigned long)maxgroups);
-
-    groups = ALLOCA_N(rb_gid_t, ngroups);
-
-    for (i = 0; i < ngroups && i < RARRAY_LEN(ary); i++) {
-	VALUE g = RARRAY_AT(ary, i);
-
-	if (FIXNUM_P(g)) {
-	    groups[i] = NUM2GIDT(g);
-	}
-	else {
-	    VALUE tmp = rb_check_string_type(g);
-
-	    if (NIL_P(tmp)) {
-		groups[i] = NUM2GIDT(g);
-	    }
-	    else {
-		gr = getgrnam(RSTRING_PTR(tmp));
-		if (gr == NULL)
-		    rb_raise(rb_eArgError,
-			     "can't find group for %s", RSTRING_PTR(tmp));
-		groups[i] = gr->gr_gid;
-	    }
-	}
-    }
-
-    i = setgroups(ngroups, groups);
-    if (i == -1)
-	rb_sys_fail(0);
-
-    return proc_getgroups(obj, 0);
-#else
-    rb_notimplement();
-    return Qnil;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.initgroups(username, gid)   => array
- *
- *  Initializes the supplemental group access list by reading the
- *  system group database and using all groups of which the given user
- *  is a member. The group with the specified <em>gid</em> is also
- *  added to the list. Returns the resulting <code>Array</code> of the
- *  gids of all the groups in the supplementary group access list. Not
- *  available on all platforms.
- *
- *     Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
- *     Process.initgroups( "mgranger", 30 )   #=> [30, 6, 10, 11]
- *     Process.groups   #=> [30, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_initgroups(VALUE obj, SEL sel, VALUE uname, VALUE base_grp)
-{
-#ifdef HAVE_INITGROUPS
-    if (initgroups(StringValuePtr(uname), NUM2GIDT(base_grp)) != 0) {
-	rb_sys_fail(0);
-    }
-    return proc_getgroups(obj, 0);
-#else
-    rb_notimplement();
-    return Qnil;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process.maxgroups   => fixnum
- *
- *  Returns the maximum number of gids allowed in the supplemental
- *  group access list.
- *
- *     Process.maxgroups   #=> 32
- */
-
-static VALUE
-proc_getmaxgroups(VALUE obj, SEL sel)
-{
-    return INT2FIX(maxgroups);
-}
-
-
-/*
- *  call-seq:
- *     Process.maxgroups= fixnum   => fixnum
- *
- *  Sets the maximum number of gids allowed in the supplemental group
- *  access list.
- */
-
-static VALUE
-proc_setmaxgroups(VALUE obj, SEL sel, VALUE val)
-{
-    size_t  ngroups = FIX2INT(val);
-
-    if (ngroups > 4096)
-	ngroups = 4096;
-
-    maxgroups = ngroups;
-
-    return INT2FIX(maxgroups);
-}
-
-/*
- *  call-seq:
- *     Process.daemon()                        => fixnum
- *     Process.daemon(nochdir=nil,noclose=nil) => fixnum
- *
- *  Detach the process from controlling terminal and run in
- *  the background as system daemon.  Unless the argument
- *  nochdir is true (i.e. non false), it changes the current
- *  working directory to the root ("/"). Unless the argument
- *  noclose is true, daemon() will redirect standard input,
- *  standard output and standard error to /dev/null.
- */
-
-static VALUE
-proc_daemon(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE nochdir, noclose;
-#if defined(HAVE_DAEMON) || defined(HAVE_FORK)
-    int n;
-#endif
-
-    rb_secure(2);
-    rb_scan_args(argc, argv, "02", &nochdir, &noclose);
-
-#if defined(HAVE_DAEMON)
-    n = daemon(RTEST(nochdir), RTEST(noclose));
-    if (n < 0) rb_sys_fail("daemon");
-    return INT2FIX(n);
-#elif defined(HAVE_FORK)
-    switch (rb_fork(0, 0, 0, Qnil)) {
-      case -1:
-	return (-1);
-      case 0:
-	break;
-      default:
-	_exit(0);
-    }
-
-    proc_setsid(0, 0);
-
-    if (!RTEST(nochdir))
-	(void)chdir("/");
-
-    if (!RTEST(noclose) && (n = open("/dev/null", O_RDWR, 0)) != -1) {
-	(void)dup2(n, 0);
-	(void)dup2(n, 1);
-	(void)dup2(n, 2);
-	if (n > 2)
-	    (void)close (n);
-    }
-    return INT2FIX(0);
-#else
-    rb_notimplement();
-#endif
-}
-
-/********************************************************************
- *
- * Document-class: Process::GID
- *
- *  The <code>Process::GID</code> module contains a collection of
- *  module functions which can be used to portably get, set, and
- *  switch the current process's real, effective, and saved group IDs.
- *
- */
-
-static int SAVED_GROUP_ID = -1;
-
-#ifdef BROKEN_SETREGID
-int
-setregid(rb_gid_t rgid, rb_gid_t egid)
-{
-    if (rgid != -1 && rgid != getgid()) {
-	if (egid == -1) egid = getegid();
-	if (setgid(rgid) < 0) return -1;
-    }
-    if (egid != -1 && egid != getegid()) {
-	if (setegid(egid) < 0) return -1;
-    }
-    return 0;
-}
-#endif
-
-/*
- *  call-seq:
- *     Process::GID.change_privilege(integer)   => fixnum
- *
- *  Change the current process's real and effective group ID to that
- *  specified by _integer_. Returns the new group ID. Not
- *  available on all platforms.
- *
- *     [Process.gid, Process.egid]          #=> [0, 0]
- *     Process::GID.change_privilege(33)    #=> 33
- *     [Process.gid, Process.egid]          #=> [33, 33]
- */
-
-static VALUE
-p_gid_change_privilege(VALUE obj, SEL sel, VALUE id)
-{
-    rb_gid_t gid;
-
-    check_gid_switch();
-
-    gid = NUM2GIDT(id);
-
-    if (geteuid() == 0) { /* root-user */
-#if defined(HAVE_SETRESGID)
-	if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
-	SAVED_GROUP_ID = gid;
-#elif defined HAVE_SETGID
-	if (setgid(gid) < 0) rb_sys_fail(0);
-	SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
-	if (getgid() == gid) {
-	    if (SAVED_GROUP_ID == gid) {
-		if (setregid(-1, gid) < 0) rb_sys_fail(0);
-	    } else {
-		if (gid == 0) { /* (r,e,s) == (root, y, x) */
-		    if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
-		    if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
-		    if (setregid(gid, gid) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = gid;
-		} else { /* (r,e,s) == (z, y, x) */
-		    if (setregid(0, 0) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = 0;
-		    if (setregid(gid, gid) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = gid;
-		}
-	    }
-	} else {
-	    if (setregid(gid, gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	}
-#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
-	if (getgid() == gid) {
-	    if (SAVED_GROUP_ID == gid) {
-		if (setegid(gid) < 0) rb_sys_fail(0);
-	    } else {
-		if (gid == 0) {
-		    if (setegid(gid) < 0) rb_sys_fail(0);
-		    if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = 0;
-		    if (setrgid(0) < 0) rb_sys_fail(0);
-		} else {
-		    if (setrgid(0) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = 0;
-		    if (setegid(gid) < 0) rb_sys_fail(0);
-		    if (setrgid(gid) < 0) rb_sys_fail(0);
-		    SAVED_GROUP_ID = gid;
-		}
-	    }
-	} else {
-	    if (setegid(gid) < 0) rb_sys_fail(0);
-	    if (setrgid(gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	}
-#else
-	rb_notimplement();
-#endif
-    } else { /* unprivileged user */
-#if defined(HAVE_SETRESGID)
-	if (setresgid((getgid() == gid)? -1: gid,
-		      (getegid() == gid)? -1: gid,
-		      (SAVED_GROUP_ID == gid)? -1: gid) < 0) rb_sys_fail(0);
-	SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
-	if (SAVED_GROUP_ID == gid) {
-	    if (setregid((getgid() == gid)? -1: gid,
-			 (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
-	} else if (getgid() != gid) {
-	    if (setregid(gid, (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	} else if (/* getgid() == gid && */ getegid() != gid) {
-	    if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-	} else { /* getgid() == gid && getegid() == gid */
-	    if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
-	    if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-	}
-#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
-	if (SAVED_GROUP_ID == gid) {
-	    if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
-	    if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
-	} else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
-	    if (getgid() != gid) {
-		if (setrgid(gid) < 0) rb_sys_fail(0);
-		SAVED_GROUP_ID = gid;
-	    } else {
-		if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
-		SAVED_GROUP_ID = gid;
-		if (setrgid(gid) < 0) rb_sys_fail(0);
-	}
-	} else if (/* getegid() != gid && */ getgid() == gid) {
-	    if (setegid(gid) < 0) rb_sys_fail(0);
-	    if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	    if (setrgid(gid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_44BSD_SETGID
-	if (getgid() == gid) {
-	    /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
-	    if (setgid(gid) < 0) rb_sys_fail(0);
-	    SAVED_GROUP_ID = gid;
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_SETEGID
-	if (getgid() == gid && SAVED_GROUP_ID == gid) {
-	    if (setegid(gid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#elif defined HAVE_SETGID
-	if (getgid() == gid && SAVED_GROUP_ID == gid) {
-	    if (setgid(gid) < 0) rb_sys_fail(0);
-	} else {
-	    errno = EPERM;
-	    rb_sys_fail(0);
-	}
-#else
-	rb_notimplement();
-#endif
-    }
-    return id;
-}
-
-
-/*
- *  call-seq:
- *     Process.euid           => fixnum
- *     Process::UID.eid       => fixnum
- *     Process::Sys.geteuid   => fixnum
- *
- *  Returns the effective user ID for this process.
- *
- *     Process.euid   #=> 501
- */
-
-static VALUE
-proc_geteuid(VALUE obj, SEL sel)
-{
-    rb_uid_t euid = geteuid();
-    return UIDT2NUM(euid);
-}
-
-
-/*
- *  call-seq:
- *     Process.euid= integer
- *
- *  Sets the effective user ID for this process. Not available on all
- *  platforms.
- */
-
-static VALUE
-proc_seteuid(VALUE obj, SEL sel, VALUE euid)
-{
-    rb_uid_t uid;
-
-    check_uid_switch();
-
-    uid = NUM2UIDT(euid);
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
-    if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREUID
-    if (setreuid(-1, uid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETEUID
-    if (seteuid(uid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
-    if (uid == getuid()) {
-	if (setuid(uid) < 0) rb_sys_fail(0);
-    }
-    else {
-	rb_notimplement();
-    }
-#else
-    rb_notimplement();
-#endif
-    return euid;
-}
-
-static rb_uid_t
-rb_seteuid_core(rb_uid_t euid)
-{
-    rb_uid_t uid;
-
-    check_uid_switch();
-
-    uid = getuid();
-
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
-    if (uid != euid) {
-	if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
-	SAVED_USER_ID = euid;
-    } else {
-	if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
-    }
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
-    if (setreuid(-1, euid) < 0) rb_sys_fail(0);
-    if (uid != euid) {
-	if (setreuid(euid,uid) < 0) rb_sys_fail(0);
-	if (setreuid(uid,euid) < 0) rb_sys_fail(0);
-	SAVED_USER_ID = euid;
-    }
-#elif defined HAVE_SETEUID
-    if (seteuid(euid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
-    if (geteuid() == 0) rb_sys_fail(0);
-    if (setuid(euid) < 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return euid;
-}
-
-
-/*
- *  call-seq:
- *     Process::UID.grant_privilege(integer)   => fixnum
- *     Process::UID.eid= integer               => fixnum
- *
- *  Set the effective user ID, and if possible, the saved user ID of
- *  the process to the given _integer_. Returns the new
- *  effective user ID. Not available on all platforms.
- *
- *     [Process.uid, Process.euid]          #=> [0, 0]
- *     Process::UID.grant_privilege(31)     #=> 31
- *     [Process.uid, Process.euid]          #=> [0, 31]
- */
-
-static VALUE
-p_uid_grant_privilege(VALUE obj, SEL sel, VALUE id)
-{
-    rb_seteuid_core(NUM2UIDT(id));
-    return id;
-}
-
-
-/*
- *  call-seq:
- *     Process.egid          => fixnum
- *     Process::GID.eid      => fixnum
- *     Process::Sys.geteid   => fixnum
- *
- *  Returns the effective group ID for this process. Not available on
- *  all platforms.
- *
- *     Process.egid   #=> 500
- */
-
-static VALUE
-proc_getegid(VALUE obj, SEL sel)
-{
-    rb_gid_t egid = getegid();
-
-    return GIDT2NUM(egid);
-}
-
-
-/*
- *  call-seq:
- *     Process.egid = fixnum   => fixnum
- *
- *  Sets the effective group ID for this process. Not available on all
- *  platforms.
- */
-
-static VALUE
-proc_setegid(VALUE obj, SEL sel, VALUE egid)
-{
-    rb_gid_t gid;
-
-    check_gid_switch();
-
-    gid = NUM2GIDT(egid);
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
-    if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
-    if (setregid(-1, gid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETEGID
-    if (setegid(gid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
-    if (gid == getgid()) {
-	if (setgid(gid) < 0) rb_sys_fail(0);
-    }
-    else {
-	rb_notimplement();
-    }
-#else
-    rb_notimplement();
-#endif
-    return egid;
-}
-
-static rb_gid_t
-rb_setegid_core(rb_gid_t egid)
-{
-    rb_gid_t gid;
-
-    check_gid_switch();
-
-    gid = getgid();
-
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
-    if (gid != egid) {
-	if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
-	SAVED_GROUP_ID = egid;
-    } else {
-	if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
-    }
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
-    if (setregid(-1, egid) < 0) rb_sys_fail(0);
-    if (gid != egid) {
-	if (setregid(egid,gid) < 0) rb_sys_fail(0);
-	if (setregid(gid,egid) < 0) rb_sys_fail(0);
-	SAVED_GROUP_ID = egid;
-    }
-#elif defined HAVE_SETEGID
-    if (setegid(egid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
-    if (geteuid() == 0 /* root user */) rb_sys_fail(0);
-    if (setgid(egid) < 0) rb_sys_fail(0);
-#else
-    rb_notimplement();
-#endif
-    return egid;
-}
-
-
-/*
- *  call-seq:
- *     Process::GID.grant_privilege(integer)    => fixnum
- *     Process::GID.eid = integer               => fixnum
- *
- *  Set the effective group ID, and if possible, the saved group ID of
- *  the process to the given _integer_. Returns the new
- *  effective group ID. Not available on all platforms.
- *
- *     [Process.gid, Process.egid]          #=> [0, 0]
- *     Process::GID.grant_privilege(31)     #=> 33
- *     [Process.gid, Process.egid]          #=> [0, 33]
- */
-
-static VALUE
-p_gid_grant_privilege(VALUE obj, SEL sel, VALUE id)
-{
-    rb_setegid_core(NUM2GIDT(id));
-    return id;
-}
-
-
-/*
- *  call-seq:
- *     Process::UID.re_exchangeable?   => true or false
- *
- *  Returns +true+ if the real and effective user IDs of a
- *  process may be exchanged on the current platform.
- *
- */
-
-static VALUE
-p_uid_exchangeable(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
-    return Qtrue;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
-    return Qtrue;
-#else
-    return Qfalse;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process::UID.re_exchange   => fixnum
- *
- *  Exchange real and effective user IDs and return the new effective
- *  user ID. Not available on all platforms.
- *
- *     [Process.uid, Process.euid]   #=> [0, 31]
- *     Process::UID.re_exchange      #=> 0
- *     [Process.uid, Process.euid]   #=> [31, 0]
- */
-
-static VALUE
-p_uid_exchange(VALUE obj, SEL sel)
-{
-    rb_uid_t uid, euid;
-
-    check_uid_switch();
-
-    uid = getuid();
-    euid = geteuid();
-
-#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
-    if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
-    SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
-    if (setreuid(euid,uid) < 0) rb_sys_fail(0);
-    SAVED_USER_ID = uid;
-#else
-    rb_notimplement();
-#endif
-    return UIDT2NUM(uid);
-}
-
-
-/*
- *  call-seq:
- *     Process::GID.re_exchangeable?   => true or false
- *
- *  Returns +true+ if the real and effective group IDs of a
- *  process may be exchanged on the current platform.
- *
- */
-
-static VALUE
-p_gid_exchangeable(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_SETRESGID) &&  !defined(__CHECKER__)
-    return Qtrue;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
-    return Qtrue;
-#else
-    return Qfalse;
-#endif
-}
-
-
-/*
- *  call-seq:
- *     Process::GID.re_exchange   => fixnum
- *
- *  Exchange real and effective group IDs and return the new effective
- *  group ID. Not available on all platforms.
- *
- *     [Process.gid, Process.egid]   #=> [0, 33]
- *     Process::GID.re_exchange      #=> 0
- *     [Process.gid, Process.egid]   #=> [33, 0]
- */
-
-static VALUE
-p_gid_exchange(VALUE obj, SEL sel)
-{
-    rb_gid_t gid, egid;
-
-    check_gid_switch();
-
-    gid = getgid();
-    egid = getegid();
-
-#if defined(HAVE_SETRESGID) &&  !defined(__CHECKER__)
-    if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
-    SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
-    if (setregid(egid,gid) < 0) rb_sys_fail(0);
-    SAVED_GROUP_ID = gid;
-#else
-    rb_notimplement();
-#endif
-    return GIDT2NUM(gid);
-}
-
-/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
-
-/*
- *  call-seq:
- *     Process::UID.sid_available?   => true or false
- *
- *  Returns +true+ if the current platform has saved user
- *  ID functionality.
- *
- */
-
-static VALUE
-p_uid_have_saved_id(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
-    return Qtrue;
-#else
-    return Qfalse;
-#endif
-}
-
-
-#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
-static VALUE
-p_uid_sw_ensure(rb_uid_t id)
-{
-    under_uid_switch = 0;
-    id = rb_seteuid_core(id);
-    return UIDT2NUM(id);
-}
-
-
-/*
- *  call-seq:
- *     Process::UID.switch              => fixnum
- *     Process::UID.switch {|| block}   => object
- *
- *  Switch the effective and real user IDs of the current process. If
- *  a <em>block</em> is given, the user IDs will be switched back
- *  after the block is executed. Returns the new effective user ID if
- *  called without a block, and the return value of the block if one
- *  is given.
- *
- */
-
-static VALUE
-p_uid_switch(VALUE obj, SEL sel)
-{
-    rb_uid_t uid, euid;
-
-    check_uid_switch();
-
-    uid = getuid();
-    euid = geteuid();
-
-    if (uid != euid) {
-	proc_seteuid(obj, 0, UIDT2NUM(uid));
-	if (rb_block_given_p()) {
-	    under_uid_switch = 1;
-	    return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
-	} else {
-	    return UIDT2NUM(euid);
-	}
-    } else if (euid != SAVED_USER_ID) {
-	proc_seteuid(obj, 0, UIDT2NUM(SAVED_USER_ID));
-	if (rb_block_given_p()) {
-	    under_uid_switch = 1;
-	    return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
-	} else {
-	    return UIDT2NUM(uid);
-	}
-    } else {
-	errno = EPERM;
-	rb_sys_fail(0);
-    }
-}
-#else
-static VALUE
-p_uid_sw_ensure(VALUE obj)
-{
-    under_uid_switch = 0;
-    return p_uid_exchange(obj, 0);
-}
-
-static VALUE
-p_uid_switch(VALUE obj, SEL sel)
-{
-    rb_uid_t uid, euid;
-
-    check_uid_switch();
-
-    uid = getuid();
-    euid = geteuid();
-
-    if (uid == euid) {
-	errno = EPERM;
-	rb_sys_fail(0);
-    }
-    p_uid_exchange(obj, 0);
-    if (rb_block_given_p()) {
-	under_uid_switch = 1;
-	return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
-    } else {
-	return UIDT2NUM(euid);
-    }
-}
-#endif
-
-
-/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
-
-/*
- *  call-seq:
- *     Process::GID.sid_available?   => true or false
- *
- *  Returns +true+ if the current platform has saved group
- *  ID functionality.
- *
- */
-
-static VALUE
-p_gid_have_saved_id(VALUE rcv, SEL sel)
-{
-#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
-    return Qtrue;
-#else
-    return Qfalse;
-#endif
-}
-
-#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
-static VALUE
-p_gid_sw_ensure(rb_gid_t id)
-{
-    under_gid_switch = 0;
-    id = rb_setegid_core(id);
-    return GIDT2NUM(id);
-}
-
-
-/*
- *  call-seq:
- *     Process::GID.switch              => fixnum
- *     Process::GID.switch {|| block}   => object
- *
- *  Switch the effective and real group IDs of the current process. If
- *  a <em>block</em> is given, the group IDs will be switched back
- *  after the block is executed. Returns the new effective group ID if
- *  called without a block, and the return value of the block if one
- *  is given.
- *
- */
-
-static VALUE
-p_gid_switch(VALUE obj, SEL sel)
-{
-    int gid, egid;
-
-    check_gid_switch();
-
-    gid = getgid();
-    egid = getegid();
-
-    if (gid != egid) {
-	proc_setegid(obj, 0, GIDT2NUM(gid));
-	if (rb_block_given_p()) {
-	    under_gid_switch = 1;
-	    return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
-	} else {
-	    return GIDT2NUM(egid);
-	}
-    } else if (egid != SAVED_GROUP_ID) {
-	proc_setegid(obj, 0, GIDT2NUM(SAVED_GROUP_ID));
-	if (rb_block_given_p()) {
-	    under_gid_switch = 1;
-	    return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
-	} else {
-	    return GIDT2NUM(gid);
-	}
-    } else {
-	errno = EPERM;
-	rb_sys_fail(0);
-    }
-}
-#else
-static VALUE
-p_gid_sw_ensure(VALUE obj)
-{
-    under_gid_switch = 0;
-    return p_gid_exchange(obj, 0);
-}
-
-static VALUE
-p_gid_switch(VALUE obj, SEL sel)
-{
-    rb_gid_t gid, egid;
-
-    check_gid_switch();
-
-    gid = getgid();
-    egid = getegid();
-
-    if (gid == egid) {
-	errno = EPERM;
-	rb_sys_fail(0);
-    }
-    p_gid_exchange(obj, 0);
-    if (rb_block_given_p()) {
-	under_gid_switch = 1;
-	return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
-    } else {
-	return GIDT2NUM(egid);
-    }
-}
-#endif
-
-
-/*
- *  call-seq:
- *     Process.times   => aStructTms
- *
- *  Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>
- *  on page 388) that contains user and system CPU times for this
- *  process.
- *
- *     t = Process.times
- *     [ t.utime, t.stime ]   #=> [0.0, 0.02]
- */
-
-static VALUE
-rb_proc_times(VALUE obj, SEL sel)
-{
-#if defined(HAVE_TIMES) && !defined(__CHECKER__)
-    const double hertz =
-#ifdef HAVE__SC_CLK_TCK
-	(double)sysconf(_SC_CLK_TCK);
-#else
-#ifndef HZ
-# ifdef CLK_TCK
-#   define HZ CLK_TCK
-# else
-#   define HZ 60
-# endif
-#endif /* HZ */
-	HZ;
-#endif
-    struct tms buf;
-    volatile VALUE utime, stime, cutime, sctime;
-
-    times(&buf);
-    return rb_struct_new(rb_cProcessTms,
-			 utime = DOUBLE2NUM(buf.tms_utime / hertz),
-			 stime = DOUBLE2NUM(buf.tms_stime / hertz),
-			 cutime = DOUBLE2NUM(buf.tms_cutime / hertz),
-			 sctime = DOUBLE2NUM(buf.tms_cstime / hertz));
-#else
-    rb_notimplement();
-#endif
-}
-
-VALUE rb_mProcess;
-VALUE rb_mProcUID;
-VALUE rb_mProcGID;
-VALUE rb_mProcID_Syscall;
-
-
-/*
- *  The <code>Process</code> module is a collection of methods used to
- *  manipulate processes.
- */
-
-void
-Init_process(void)
-{
-    rb_define_virtual_variable("$?", rb_last_status_get, 0);
-    rb_define_virtual_variable("$$", get_pid, 0);
-    rb_objc_define_module_function(rb_mKernel, "exec", rb_f_exec, -1);
-    rb_objc_define_module_function(rb_mKernel, "fork", rb_f_fork, 0);
-    rb_objc_define_module_function(rb_mKernel, "exit!", rb_f_exit_bang, -1);
-    rb_objc_define_module_function(rb_mKernel, "system", rb_f_system, -1);
-    rb_objc_define_module_function(rb_mKernel, "spawn", rb_f_spawn, -1);
-    rb_objc_define_module_function(rb_mKernel, "sleep", rb_f_sleep, -1);
-    rb_objc_define_module_function(rb_mKernel, "exit", rb_f_exit, -1);
-    rb_objc_define_module_function(rb_mKernel, "abort", rb_f_abort, -1);
-
-    rb_mProcess = rb_define_module("Process");
-
-#ifdef WNOHANG
-    rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
-#else
-    rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
-#endif
-#ifdef WUNTRACED
-    rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
-#else
-    rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
-#endif
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "exec", rb_f_exec, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "fork", rb_f_fork, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "spawn", rb_f_spawn, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "exit!", rb_f_exit_bang, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "exit", rb_f_exit, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "abort", rb_f_abort, -1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "wait", proc_wait, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "wait2", proc_wait2, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "waitpid", proc_wait, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "waitpid2", proc_wait2, -1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "waitall", proc_waitall, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "detach", proc_detach, 1);
-
-    rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
-    rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
-
-    rb_objc_define_method(rb_cProcessStatus, "==", pst_equal, 1);
-    rb_objc_define_method(rb_cProcessStatus, "&", pst_bitand, 1);
-    rb_objc_define_method(rb_cProcessStatus, ">>", pst_rshift, 1);
-    rb_objc_define_method(rb_cProcessStatus, "to_i", pst_to_i, 0);
-    rb_objc_define_method(rb_cProcessStatus, "to_int", pst_to_i, 0);
-    rb_objc_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
-    rb_objc_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
-
-    rb_objc_define_method(rb_cProcessStatus, "pid", pst_pid, 0);
-
-    rb_objc_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0);
-    rb_objc_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0);
-    rb_objc_define_method(rb_cProcessStatus, "signaled?", pst_wifsignaled, 0);
-    rb_objc_define_method(rb_cProcessStatus, "termsig", pst_wtermsig, 0);
-    rb_objc_define_method(rb_cProcessStatus, "exited?", pst_wifexited, 0);
-    rb_objc_define_method(rb_cProcessStatus, "exitstatus", pst_wexitstatus, 0);
-    rb_objc_define_method(rb_cProcessStatus, "success?", pst_success_p, 0);
-    rb_objc_define_method(rb_cProcessStatus, "coredump?", pst_wcoredump, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "pid", get_pid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "ppid", get_ppid, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "getpgrp", proc_getpgrp, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "setpgrp", proc_setpgrp, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "getpgid", proc_getpgid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "setpgid", proc_setpgid, 2);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "setsid", proc_setsid, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "getpriority", proc_getpriority, 2);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "setpriority", proc_setpriority, 3);
-
-#ifdef HAVE_GETPRIORITY
-    rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
-    rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
-    rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
-#endif
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "getrlimit", proc_getrlimit, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "setrlimit", proc_setrlimit, -1);
-#ifdef RLIM2NUM
-    {
-        VALUE inf = RLIM2NUM(RLIM_INFINITY), v;
-        rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
-#ifdef RLIM_SAVED_MAX
-        v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
-        rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
-#endif
-#ifdef RLIM_SAVED_CUR
-        v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
-        rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
-#endif
-    }
-#ifdef RLIMIT_CORE
-    rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
-#endif
-#ifdef RLIMIT_CPU
-    rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
-#endif
-#ifdef RLIMIT_DATA
-    rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
-#endif
-#ifdef RLIMIT_FSIZE
-    rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
-#endif
-#ifdef RLIMIT_NOFILE
-    rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
-#endif
-#ifdef RLIMIT_STACK
-    rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
-#endif
-#ifdef RLIMIT_AS
-    rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
-#endif
-#ifdef RLIMIT_MEMLOCK
-    rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
-#endif
-#ifdef RLIMIT_NPROC
-    rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
-#endif
-#ifdef RLIMIT_RSS
-    rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
-#endif
-#ifdef RLIMIT_SBSIZE
-    rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
-#endif
-#endif
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "uid", proc_getuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "uid=", proc_setuid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "gid", proc_getgid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "gid=", proc_setgid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "euid", proc_geteuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "euid=", proc_seteuid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "egid", proc_getegid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "egid=", proc_setegid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "initgroups", proc_initgroups, 2);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "groups", proc_getgroups, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "groups=", proc_setgroups, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "daemon", proc_daemon, -1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcess, "times", rb_proc_times, 0);
-
-#if defined(HAVE_TIMES) || defined(_WIN32)
-    rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
-#endif
-
-    SAVED_USER_ID = geteuid();
-    SAVED_GROUP_ID = getegid();
-
-    rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
-    rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
-
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "rid", proc_getuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "rid", proc_getgid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "eid", proc_geteuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "eid", proc_getegid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
-    rb_define_alias(*(VALUE *)rb_mProcUID, "eid=", "grant_privilege");
-    rb_define_alias(*(VALUE *)rb_mProcGID, "eid=", "grant_privilege");
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "re_exchange", p_uid_exchange, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "re_exchange", p_gid_exchange, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcUID, "switch", p_uid_switch, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcGID, "switch", p_gid_switch, 0);
-
-    rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "getuid", proc_getuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "getgid", proc_getgid, 0);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "getegid", proc_getegid, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
-
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
-    rb_objc_define_method(*(VALUE *)rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
-}

Deleted: MacRuby/trunk/random.c
===================================================================
--- MacRuby/trunk/random.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/random.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,881 +0,0 @@
-/* 
- * Random Numbers.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "id.h"
-#include "encoding.h"
-
-#include <unistd.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <math.h>
-#include <errno.h>
-
-#include "mt.c"
-
-VALUE rb_cRandom;
-
-typedef struct {
-    VALUE seed;
-    struct MT mt;
-} rb_random_t;
-
-#define get_rnd(obj) ((rb_random_t *)DATA_PTR(obj))
-#define default_rnd() (get_rnd(rb_vm_default_random()))
-
-unsigned int
-rb_genrand_int32(void)
-{
-    return genrand_int32(&default_rnd()->mt);
-}
-
-double
-rb_genrand_real(void)
-{
-    return genrand_real(&default_rnd()->mt);
-}
-
-#define BDIGITS(x) (RBIGNUM_DIGITS(x))
-#define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
-#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
-#define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS)
-#define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
-#define BIGDN(x) RSHIFT(x,BITSPERDIG)
-#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
-#define BDIGMAX ((BDIGIT)-1)
-
-#define roomof(n, m) (int)(((n)+(m)-1) / (m))
-#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
-#define SIZEOF_INT32 (31/CHAR_BIT + 1)
-
-static VALUE random_seed(VALUE, SEL);
-
-/* :nodoc: */
-static VALUE
-random_alloc(VALUE klass, SEL sel)
-{
-    rb_random_t *r = (rb_random_t *)xmalloc(sizeof(rb_random_t));
-    r->seed = INT2FIX(0);
-    return Data_Wrap_Struct(rb_cRandom, NULL, NULL, r);
-}
-
-static VALUE
-rand_init(struct MT *mt, VALUE vseed)
-{
-    VALUE seed;
-    long blen = 0;
-    int i, j, len;
-    unsigned int buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;
-
-    seed = rb_to_int(vseed);
-    switch (TYPE(seed)) {
-      case T_FIXNUM:
-	len = 1;
-	buf[0] = (unsigned int)(FIX2ULONG(seed) & 0xffffffff);
-#if SIZEOF_LONG > SIZEOF_INT32
-	if ((buf[1] = (unsigned int)(FIX2ULONG(seed) >> 32)) != 0) ++len;
-#endif
-	break;
-      case T_BIGNUM:
-	blen = RBIGNUM_LEN(seed);
-	if (blen == 0) {
-	    len = 1;
-	}
-	else {
-	    if (blen > MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS)
-		blen = (len = MT_MAX_STATE) * SIZEOF_INT32 / SIZEOF_BDIGITS;
-	    len = roomof((int)blen * SIZEOF_BDIGITS, SIZEOF_INT32);
-	}
-	/* allocate ints for init_by_array */
-	if (len > numberof(buf0)) buf = ALLOC_N(unsigned int, len);
-	memset(buf, 0, len * sizeof(*buf));
-	len = 0;
-	for (i = (int)(blen-1); 0 <= i; i--) {
-	    j = i * SIZEOF_BDIGITS / SIZEOF_INT32;
-#if SIZEOF_BDIGITS < SIZEOF_INT32
-	    buf[j] <<= BITSPERDIG;
-#endif
-	    buf[j] |= RBIGNUM_DIGITS(seed)[i];
-	    if (!len && buf[j]) len = j;
-	}
-	++len;
-	break;
-      default:
-	rb_raise(rb_eTypeError, "failed to convert %s into Integer",
-		 rb_obj_classname(vseed));
-    }
-    if (len <= 1) {
-        init_genrand(mt, buf[0]);
-    }
-    else {
-        if (buf[len-1] == 1) /* remove leading-zero-guard */
-            len--;
-        init_by_array(mt, buf, len);
-    }
-    return seed;
-}
-
-/*
- * call-seq: Random.new([seed]) -> prng
- *
- * Creates new Mersenne Twister based pseudorandom number generator with
- * seed.  When the argument seed is omitted, the generator is initialized
- * with Random.seed.
- *
- * The argument seed is used to ensure repeatable sequences of random numbers
- * between different runs of the program.
- *
- *     prng = Random.new(1234)
- *     [ prng.rand, prng.rand ]   #=> [0.191519450378892, 0.622108771039832]
- *     [ prng.integer(10), prng.integer(1000) ]  #=> [4, 664]
- *     prng = Random.new(1234)
- *     [ prng.rand, prng.rand ]   #=> [0.191519450378892, 0.622108771039832]
- */
-static VALUE
-random_init(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE vseed;
-    rb_random_t *rnd = get_rnd(obj);
-
-    if (argc == 0) {
-	vseed = random_seed(0, 0);
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &vseed);
-    }
-    GC_WB(&rnd->seed, rand_init(&rnd->mt, vseed));
-    return obj;
-}
-
-#define DEFAULT_SEED_CNT 4
-#define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * sizeof(int))
-
-static void
-fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT])
-{
-    static int n = 0;
-    struct timeval tv;
-    int fd;
-    struct stat statbuf;
-
-    memset(seed, 0, DEFAULT_SEED_LEN);
-
-    if ((fd = open("/dev/urandom", O_RDONLY
-#ifdef O_NONBLOCK
-            |O_NONBLOCK
-#endif
-#ifdef O_NOCTTY
-            |O_NOCTTY
-#endif
-#ifdef O_NOFOLLOW
-            |O_NOFOLLOW
-#endif
-            )) >= 0) {
-        if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
-            (void)read(fd, seed, DEFAULT_SEED_LEN);
-        }
-        close(fd);
-    }
-
-    gettimeofday(&tv, 0);
-    seed[0] ^= tv.tv_usec;
-    seed[1] ^= (unsigned int)tv.tv_sec;
-#if SIZEOF_TIME_T > SIZEOF_INT
-    seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
-#endif
-    seed[2] ^= getpid() ^ (n++ << 16);
-    seed[3] ^= (unsigned int)(VALUE)&seed;
-#if SIZEOF_VOIDP > SIZEOF_INT
-    seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
-#endif
-}
-
-static VALUE
-make_seed_value(const void *ptr)
-{
-    BDIGIT *digits;
-    NEWOBJ(big, struct RBignum);
-    OBJSETUP(big, rb_cBignum, T_BIGNUM);
-
-    RBIGNUM_SET_SIGN(big, 1);
-    rb_big_resize((VALUE)big, DEFAULT_SEED_LEN / SIZEOF_BDIGITS + 1);
-    digits = RBIGNUM_DIGITS(big);
-
-    MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
-
-    /* set leading-zero-guard if need. */
-    digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0;
-
-    return rb_big_norm((VALUE)big);
-}
-
-/*
- * call-seq: Random.seed -> integer
- *
- * Returns arbitrary value for seed.
- */
-static VALUE
-random_seed(VALUE rcv, SEL sel)
-{
-    unsigned int buf[DEFAULT_SEED_CNT];
-    fill_random_seed(buf);
-    return make_seed_value(buf);
-}
-
-/*
- * call-seq: prng.seed -> integer
- *
- * Returns the seed of the generator.
- */
-static VALUE
-random_get_seed(VALUE obj, SEL sel)
-{
-    return get_rnd(obj)->seed;
-}
-
-/* :nodoc: */
-static VALUE
-random_copy(VALUE obj, SEL sel, VALUE orig)
-{
-    rb_random_t *rnd1 = get_rnd(obj);
-    rb_random_t *rnd2 = get_rnd(orig);
-    struct MT *mt = &rnd1->mt;
-
-    *rnd1 = *rnd2;
-    GC_WB(&rnd1->seed, rnd2->seed);
-    mt->next = mt->state + numberof(mt->state) - mt->left + 1;
-    return obj;
-}
-
-static VALUE
-mt_state(const struct MT *mt)
-{
-    const int n = numberof(mt->state);
-    VALUE bigo = rb_big_new(n, 1);
-    BDIGIT *d = RBIGNUM_DIGITS(bigo);
-    for (int i = 0; i < n; i++) {
-	unsigned int x = mt->state[i];
-	*d++ = (BDIGIT)x;
-    }
-    return rb_big_norm(bigo);
-}
-
-/* :nodoc: */
-static VALUE
-random_state(VALUE obj, SEL sel)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    return mt_state(&rnd->mt);
-}
-
-/* :nodoc: */
-static VALUE
-random_s_state(VALUE klass, SEL sel)
-{
-    return mt_state(&default_rnd()->mt);
-}
-
-/* :nodoc: */
-static VALUE
-random_left(VALUE obj, SEL sel)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    return INT2FIX(rnd->mt.left);
-}
-
-/* :nodoc: */
-static VALUE
-random_s_left(VALUE klass, SEL sel)
-{
-    return INT2FIX(default_rnd()->mt.left);
-}
-
-/* :nodoc: */
-static VALUE
-random_dump(VALUE obj, SEL sel)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    VALUE dump = rb_ary_new2(3);
-
-    rb_ary_push(dump, mt_state(&rnd->mt));
-    rb_ary_push(dump, INT2FIX(rnd->mt.left));
-    rb_ary_push(dump, rnd->seed);
-
-    return dump;
-}
-
-/* :nodoc: */
-static VALUE
-random_load(VALUE obj, SEL sel, VALUE dump)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    struct MT *mt = &rnd->mt;
-    VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
-    unsigned long x;
-
-    Check_Type(dump, T_ARRAY);
-    switch (RARRAY_LEN(dump)) {
-      case 3:
-	seed = RARRAY_AT(dump, 2);
-      case 2:
-	left = RARRAY_AT(dump, 1);
-      case 1:
-	state = RARRAY_AT(dump, 0);
-	break;
-      default:
-	rb_raise(rb_eArgError, "wrong dump data");
-    }
-    memset(mt->state, 0, sizeof(mt->state));
-#if 0
-    if (FIXNUM_P(state)) {
-	x = FIX2ULONG(state);
-	mt->state[0] = (unsigned int)x;
-#if SIZEOF_LONG / SIZEOF_INT >= 2
-	mt->state[1] = (unsigned int)(x >> BITSPERDIG);
-#endif
-#if SIZEOF_LONG / SIZEOF_INT >= 3
-	mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG);
-#endif
-#if SIZEOF_LONG / SIZEOF_INT >= 4
-	mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG);
-#endif
-    }
-    else {
-	BDIGIT *d;
-	long len;
-	Check_Type(state, T_BIGNUM);
-	len = RBIGNUM_LEN(state);
-	if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) {
-	    len = roomof(sizeof(mt->state), SIZEOF_BDIGITS);
-	}
-#if SIZEOF_BDIGITS < SIZEOF_INT
-	else if (len % DIGSPERINT) {
-	    d = RBIGNUM_DIGITS(state) + len;
-# if DIGSPERINT == 2
-	    --len;
-	    x = *--d;
-# else
-	    x = 0;
-	    do {
-		x = (x << BITSPERDIG) | *--d;
-	    } while (--len % DIGSPERINT);
-# endif
-	    mt->state[len / DIGSPERINT] = (unsigned int)x;
-	}
-#endif
-	if (len > 0) {
-	    d = BDIGITS(state) + len;
-	    do {
-		--len;
-		x = *--d;
-# if DIGSPERINT == 2
-		--len;
-		x = (x << BITSPERDIG) | *--d;
-# elif SIZEOF_BDIGITS < SIZEOF_INT
-		do {
-		    x = (x << BITSPERDIG) | *--d;
-		} while (--len % DIGSPERINT);
-# endif
-		mt->state[len / DIGSPERINT] = (unsigned int)x;
-	    } while (len > 0);
-	}
-    }
-#endif
-    x = NUM2ULONG(left);
-    if (x > numberof(mt->state)) {
-	rb_raise(rb_eArgError, "wrong value");
-    }
-    mt->left = (unsigned int)x;
-    mt->next = mt->state + numberof(mt->state) - x + 1;
-    GC_WB(&rnd->seed, rb_to_int(seed));
-
-    return obj;
-}
-
-/*
- *  call-seq:
- *     srand(number=0)    => old_seed
- *
- *  Seeds the pseudorandom number generator to the value of
- *  <i>number</i>. If <i>number</i> is omitted
- *  or zero, seeds the generator using a combination of the time, the
- *  process id, and a sequence number. (This is also the behavior if
- *  <code>Kernel::rand</code> is called without previously calling
- *  <code>srand</code>, but without the sequence.) By setting the seed
- *  to a known value, scripts can be made deterministic during testing.
- *  The previous seed value is returned. Also see <code>Kernel::rand</code>.
- */
-
-static VALUE
-rb_f_srand(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE seed, old;
-    rb_random_t *r = default_rnd();
-
-    rb_secure(4);
-    if (argc == 0) {
-	seed = random_seed(0, 0);
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &seed);
-    }
-    old = r->seed;
-    GC_WB(&r->seed, rand_init(&r->mt, seed));
-
-    return old;
-}
-
-static unsigned long
-make_mask(unsigned long x)
-{
-    x = x | x >> 1;
-    x = x | x >> 2;
-    x = x | x >> 4;
-    x = x | x >> 8;
-    x = x | x >> 16;
-#if 4 < SIZEOF_LONG
-    x = x | x >> 32;
-#endif
-    return x;
-}
-
-static unsigned long
-limited_rand(struct MT *mt, unsigned long limit)
-{
-    if (limit == 0) {
-	return 0;
-    }
-    unsigned long val, mask = make_mask(limit);
-retry:
-    val = 0;
-    for (int i = SIZEOF_LONG / SIZEOF_INT32 - 1; 0 <= i; i--) {
-        if ((mask >> (i * 32)) & 0xffffffff) {
-            val |= (unsigned long)genrand_int32(mt) << (i * 32);
-            val &= mask;
-            if (limit < val) {
-                goto retry;
-	    }
-        }
-    }
-    return val;
-}
-
-static VALUE
-limited_big_rand(struct MT *mt, struct RBignum *limit)
-{
-#if SIZEOF_BDIGITS < 8
-    const long len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4;
-#else
-    const long len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 8;
-#endif
-    struct RBignum *val = (struct RBignum *)rb_big_clone((VALUE)limit);
-    RBIGNUM_SET_SIGN(val, 1);
-#if SIZEOF_BDIGITS == 2
-# define BIG_GET32(big,i) \
-    (RBIGNUM_DIGITS(big)[(i)*2] | \
-     ((i)*2+1 < RBIGNUM_LEN(big) ? \
-      (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \
-      0))
-# define BIG_SET32(big,i,d) \
-    ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \
-     ((i)*2+1 < RBIGNUM_LEN(big) ? \
-      (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \
-      0))
-#else
-    /* SIZEOF_BDIGITS == 4 */
-# define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[i])
-# define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[i] = (d))
-#endif
-    unsigned long mask;
-    int boundary;
-retry:
-    mask = 0;
-    boundary = 1;
-    for (long i = len - 1; 0 <= i; i--) {
-        const unsigned long lim = BIG_GET32(limit, i);
-	unsigned long rnd;
-        mask = mask != 0 ? 0xffffffff : make_mask(lim);
-        if (mask != 0) {
-            rnd = genrand_int32(mt) & mask;
-            if (boundary) {
-                if (lim < rnd) {
-                    goto retry;
-		}
-                if (rnd < lim) {
-                    boundary = 0;
-		}
-            }
-        }
-        else {
-            rnd = 0;
-        }
-        BIG_SET32(val, i, (BDIGIT)rnd);
-    }
-    return rb_big_norm((VALUE)val);
-}
-
-unsigned long
-rb_rand_internal(unsigned long i)
-{
-    struct MT *mt = &default_rnd()->mt;
-    if (!genrand_initialized(mt)) {
-	rand_init(mt, random_seed(0, 0));
-    }
-    return limited_rand(mt, i);
-}
-
-unsigned int
-rb_random_int32(VALUE obj)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    return genrand_int32(&rnd->mt);
-}
-
-double
-rb_random_real(VALUE obj)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    return genrand_real(&rnd->mt);
-}
-
-/*
- * call-seq: prng.bytes(size) -> prng
- *
- * Returns a random binary string.  The argument size specified the length of
- * the result string.
- */
-static VALUE
-random_bytes(VALUE obj, SEL sel, VALUE len)
-{
-    long n = NUM2LONG(rb_to_int(len));
-    if (n <= 0) {
-	return rb_str_new2("");
-    } 
-    rb_random_t *rnd = get_rnd(obj);
-    UInt8 *ptr = (UInt8 *)malloc(n);
-    unsigned int r = genrand_int32(&rnd->mt);
-    for (long i = 0; i < n; i++) {
-	ptr[i] = (char)r;
-	r >>= CHAR_BIT;
-    }
-    VALUE bytes = rb_bstr_new_with_data(ptr, n);
-    free(ptr);
-    return bytes;
-}
-
-static VALUE
-range_values(VALUE vmax, VALUE *begp, int *exclp)
-{
-    VALUE end;
-    if (!rb_range_values(vmax, begp, &end, exclp)) {
-	return Qfalse;
-    }
-    if (!rb_vm_respond_to(end, selMINUS, false)) {
-	return Qfalse;
-    }
-    VALUE r = rb_vm_call(end, selMINUS, 1, begp);
-    if (NIL_P(r)) {
-	return Qfalse;
-    }
-    return r;
-}
-
-static VALUE
-rand_int(struct MT *mt, VALUE vmax, int restrictive)
-{
-    long max;
-    unsigned long r;
-
-    if (FIXNUM_P(vmax)) {
-	max = FIX2LONG(vmax);
-	if (!max) return Qnil;
-	if (max < 0) {
-	    if (restrictive) return Qnil;
-	    max = -max;
-	}
-	r = limited_rand(mt, (unsigned long)max - 1);
-	return ULONG2NUM(r);
-    }
-    else {
-	VALUE ret;
-	if (rb_bigzero_p(vmax)) return Qnil;
-	if (!RBIGNUM_SIGN(vmax)) {
-	    if (restrictive) return Qnil;
-	    vmax = rb_big_clone(vmax);
-	    RBIGNUM_SET_SIGN(vmax, 1);
-	}
-	vmax = rb_big_minus(vmax, INT2FIX(1));
-	if (FIXNUM_P(vmax)) {
-	    max = FIX2LONG(vmax);
-	    if (max == -1) return Qnil;
-	    r = limited_rand(mt, max);
-	    return LONG2NUM(r);
-	}
-	ret = limited_big_rand(mt, RBIGNUM(vmax));
-	return ret;
-    }
-}
-
-static inline double
-float_value(VALUE v)
-{
-    double x = RFLOAT_VALUE(v);
-    if (isinf(x) || isnan(x)) {
-	VALUE error = INT2FIX(EDOM);
-	rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
-    }
-    return x;
-}
-
-/*
- * call-seq:
- *     prng.rand -> float
- *     prng.rand(limit) -> number
- *
- * When the argument is an +Integer+ or a +Bignum+, it returns a
- * random integer greater than or equal to zero and less than the
- * argument.  Unlike Random.rand, when the argument is a negative
- * integer or zero, it raises an ArgumentError.
- *
- * When the argument is a +Float+, it returns a random floating point
- * number between 0.0 and _max_, including 0.0 and excluding _max_.
- *
- * When the argument _limit_ is a +Range+, it returns a random
- * number where range.member?(number) == true.
- *     prng.rand(5..9)  # => one of [5, 6, 7, 8, 9]
- *     prng.rand(5...9) # => one of [5, 6, 7, 8]
- *     prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0
- *     prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0
- *
- * +begin+/+end+ of the range have to have subtract and add methods.
- *
- * Otherwise, it raises an ArgumentError.
- */
-static VALUE
-random_rand(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    rb_random_t *rnd = get_rnd(obj);
-    VALUE beg = Qundef, v;
-    int excl = 0;
-
-    if (argc == 0) {
-zero_arg:
-	return rb_float_new(genrand_real(&rnd->mt));
-    }
-    else if (argc != 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
-    }
-    VALUE vmax = argv[0];
-    if (NIL_P(vmax)) {
-	goto zero_arg;
-    }
-    else if (TYPE(vmax) != T_FLOAT
-	    && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
-	v = rand_int(&rnd->mt, vmax = v, 1);
-    }
-    else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
-	const double max = float_value(v);
-	if (max > 0.0) {
-	    v = rb_float_new(max * genrand_real(&rnd->mt));
-	} 
-	else {
-	    v = Qnil;
-	}
-    }
-    else if ((v = range_values(vmax, &beg, &excl)) != Qfalse) {
-	vmax = v;
-	if (TYPE(vmax) != T_FLOAT
-		&& (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
-	    long max;
-	    vmax = v;
-	    v = Qnil;
-	    if (FIXNUM_P(vmax)) {
-fixnum:
-		if ((max = FIX2LONG(vmax) - excl) >= 0) {
-		    unsigned long r = limited_rand(&rnd->mt, (unsigned long)max);
-		    v = ULONG2NUM(r);
-		}
-	    }
-	    else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax)
-		    && !rb_bigzero_p(vmax)) {
-		vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
-		if (FIXNUM_P(vmax)) {
-		    excl = 0;
-		    goto fixnum;
-		}
-		v = limited_big_rand(&rnd->mt, RBIGNUM(vmax));
-	    }
-	}
-	else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
-	    double max = float_value(v), r;
-	    v = Qnil;
-	    if (max > 0.0) {
-		if (excl) {
-		    r = genrand_real(&rnd->mt);
-		}
-		else {
-		    r = genrand_real2(&rnd->mt);
-		}
-		v = rb_float_new(r * max);
-	    }
-	    else if (max == 0.0 && !excl) {
-		v = rb_float_new(0.0);
-	    }
-	}
-    }
-    else {
-	v = Qnil;
-	(void)NUM2LONG(vmax);
-    }
-    if (NIL_P(v)) {
-	VALUE mesg = rb_str_new2("invalid argument - ");
-	rb_str_append(mesg, rb_obj_as_string(argv[0]));
-	rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
-    }
-    if (beg == Qundef) {
-	return v;
-    }
-    if (FIXNUM_P(beg) && FIXNUM_P(v)) {
-	long x = FIX2LONG(beg) + FIX2LONG(v);
-	return LONG2NUM(x);
-    }
-    switch (TYPE(v)) {
-	case T_BIGNUM:
-	    return rb_big_plus(v, beg);
-	case T_FLOAT:
-	    {
-		double d = RFLOAT_VALUE(v) + RFLOAT_VALUE(rb_check_to_float(beg));
-		return DOUBLE2NUM(d);
-	    }
-	default:
-	    return rb_vm_call(v, selPLUS, 1, &beg);
-    }
-}
-
-/*
- * call-seq:
- *     prng1 == prng2 -> true or false
- *
- * Returns true if the generators' states equal.
- */
-static VALUE
-random_equal(VALUE self, SEL sel, VALUE other)
-{
-    if (rb_obj_class(self) != rb_obj_class(other)) {
-	return Qfalse;
-    }
-    rb_random_t *r1 = get_rnd(self);
-    rb_random_t *r2 = get_rnd(other);
-    if (rb_equal(r1->seed, r2->seed) != Qtrue) {
-	return Qfalse;
-    }
-    if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) {
-	return Qfalse;
-    }
-    if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) {
-	return Qfalse;
-    }
-    if (r1->mt.left != r2->mt.left) {
-	return Qfalse;
-    }
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     rand(max=0)    => number
- *
- *  Converts <i>max</i> to an integer using max1 =
- *  max<code>.to_i.abs</code>. If the result is zero, returns a
- *  pseudorandom floating point number greater than or equal to 0.0 and
- *  less than 1.0. Otherwise, returns a pseudorandom integer greater
- *  than or equal to zero and less than max1. <code>Kernel::srand</code>
- *  may be used to ensure repeatable sequences of random numbers between
- *  different runs of the program. Ruby currently uses a modified
- *  Mersenne Twister with a period of 2**19937-1.
- *
- *     srand 1234                 #=> 0
- *     [ rand,  rand ]            #=> [0.191519450163469, 0.49766366626136]
- *     [ rand(10), rand(1000) ]   #=> [6, 817]
- *     srand 1234                 #=> 1234
- *     [ rand,  rand ]            #=> [0.191519450163469, 0.49766366626136]
- */
-
-static VALUE
-rb_f_rand(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    struct MT *mt = &default_rnd()->mt;
-
-    if (!genrand_initialized(mt)) {
-	rand_init(mt, random_seed(0, 0));
-    }
-    if (argc == 0) {
-	goto zero_arg;
-    }
-    VALUE vmax;
-    rb_scan_args(argc, argv, "01", &vmax);
-    if (NIL_P(vmax)) {
-	goto zero_arg;
-    }
-    vmax = rb_to_int(vmax);
-    VALUE r;
-    if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
-zero_arg:
-	return DBL2NUM(genrand_real(mt));
-    }
-    return r;
-}
-
-static void
-Init_RandomSeed(void)
-{
-    VALUE random = random_alloc(0, 0);
-    unsigned int initial[DEFAULT_SEED_CNT];
-    GC_WB(&get_rnd(random)->seed, make_seed_value(initial));
-    rb_vm_set_default_random(random);
-}
-
-void
-rb_reset_random_seed(void)
-{
-    rb_random_t *r = default_rnd();
-    uninit_genrand(&r->mt);
-    r->seed = INT2FIX(0);
-}
-
-void
-Init_Random(void)
-{
-    Init_RandomSeed();
-    rb_objc_define_module_function(rb_mKernel, "srand", rb_f_srand, -1);
-    rb_objc_define_module_function(rb_mKernel, "rand", rb_f_rand, -1);
-
-    rb_cRandom = rb_define_class("Random", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cRandom, "alloc", random_alloc, 0);
-    rb_objc_define_method(rb_cRandom, "initialize", random_init, -1);
-    rb_objc_define_method(rb_cRandom, "rand", random_rand, -1);
-    rb_objc_define_method(rb_cRandom, "bytes", random_bytes, 1);
-    rb_objc_define_method(rb_cRandom, "seed", random_get_seed, 0);
-    rb_objc_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
-    rb_objc_define_method(rb_cRandom, "marshal_dump", random_dump, 0);
-    rb_objc_define_method(rb_cRandom, "marshal_load", random_load, 1);
-    rb_objc_define_private_method(rb_cRandom, "state", random_state, 0);
-    rb_objc_define_private_method(rb_cRandom, "left", random_left, 0);
-    rb_objc_define_method(rb_cRandom, "==", random_equal, 1);
-
-    rb_objc_define_method(*(VALUE *)rb_cRandom, "srand", rb_f_srand, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRandom, "rand", rb_f_rand, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRandom, "new_seed", random_seed, 0);
-    rb_objc_define_private_method(*(VALUE *)rb_cRandom, "state", random_s_state, 0);
-    rb_objc_define_private_method(*(VALUE *)rb_cRandom, "left", random_s_left, 0);
-}

Deleted: MacRuby/trunk/range.c
===================================================================
--- MacRuby/trunk/range.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/range.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1059 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "id.h"
-#include "array.h"
-
-VALUE rb_cRange;
-static SEL selUpto, selBeg, selEnd, selExcludeEnd, selInclude; 
-
-#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
-#define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
-#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
-
-#define EXCL(r) RTEST(RANGE_EXCL(r))
-#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
-
-static VALUE
-range_failed(void)
-{
-    rb_raise(rb_eArgError, "bad value for range");
-    return Qnil;		/* dummy */
-}
-
-static VALUE
-range_check(VALUE *args)
-{
-    return rb_objs_cmp(args[0], args[1]);
-}
-
-static void
-range_init(VALUE range, VALUE beg, VALUE end, int exclude_end)
-{
-    VALUE args[2];
-
-    args[0] = beg;
-    args[1] = end;
-    
-    if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
-	VALUE v;
-
-	v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
-	if (NIL_P(v))
-	    range_failed();
-    }
-
-    SET_EXCL(range, exclude_end);
-    GC_WB(&RANGE_BEG(range), beg);
-    GC_WB(&RANGE_END(range), end);
-}
-
-VALUE
-rb_range_new(VALUE beg, VALUE end, int exclude_end)
-{
-    VALUE range = rb_obj_alloc(rb_cRange);
-
-    range_init(range, beg, end, exclude_end);
-    return range;
-}
-
-VALUE
-rb_range_new2(VALUE beg, VALUE end, int exclude_end, int retain)
-{
-    VALUE range = rb_range_new(beg, end, exclude_end);
-    if (retain) {
-	GC_RETAIN(range);
-    }
-    return range;
-}
-
-/*
- *  call-seq:
- *     Range.new(start, end, exclusive=false)    => range
- *  
- *  Constructs a range using the given <i>start</i> and <i>end</i>. If the third
- *  parameter is omitted or is <code>false</code>, the <i>range</i> will include
- *  the end object; otherwise, it will be excluded.
- */
-
-static VALUE
-range_initialize(VALUE range, SEL sel ,int argc, VALUE *argv)
-{
-    VALUE beg, end, flags;
-    
-    rb_scan_args(argc, argv, "21", &beg, &end, &flags);
-    /* Ranges are immutable, so that they should be initialized only once. */
-    if (RANGE_EXCL(range) != Qnil) {
-	rb_name_error(rb_intern("initialize"), "`initialize' called twice");
-    }
-    range_init(range, beg, end, RTEST(flags));
-    return Qnil;
-}
-
-
-/*
- *  call-seq:
- *     rng.exclude_end?    => true or false
- *  
- *  Returns <code>true</code> if <i>rng</i> excludes its end value.
- */
-
-static VALUE
-range_exclude_end_p(VALUE range, SEL sel)
-{
-    return EXCL(range) ? Qtrue : Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     rng == obj    => true or false
- *  
- *  Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
- *  beginning and end items (by comparing them with <code>==</code>), and has
- *  the same #exclude_end? setting as <i>rng</t>.
- *     
- *    (0..2) == (0..2)            #=> true
- *    (0..2) == Range.new(0,2)    #=> true
- *    (0..2) == (0...2)           #=> false
- *     
- */
-
-static VALUE
-range_eq(VALUE range, SEL sel, VALUE obj)
-{
-    if (range == obj) {
-	return Qtrue;
-    }
-    if (!rb_obj_is_kind_of(obj, rb_cRange)) {
-	return Qfalse;
-    }
-
-    if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj))) {
-	return Qfalse;
-    }
-    if (!rb_equal(RANGE_END(range), RANGE_END(obj))) {
-	return Qfalse;
-    }
-
-    if (EXCL(range) != EXCL(obj)) {
-	return Qfalse;
-    }
-
-    return Qtrue;
-}
-
-static int
-r_lt(VALUE a, VALUE b)
-{
-    VALUE r = rb_objs_cmp(a, b);
-
-    if (NIL_P(r))
-	return Qfalse;
-    if (rb_cmpint(r, a, b) < 0)
-	return Qtrue;
-    return Qfalse;
-}
-
-static int
-r_le(VALUE a, VALUE b)
-{
-    int c;
-    VALUE r = rb_objs_cmp(a, b);
-
-    if (NIL_P(r))
-	return Qfalse;
-    c = rb_cmpint(r, a, b);
-    if (c == 0)
-	return INT2FIX(0);
-    if (c < 0)
-	return Qtrue;
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     rng.eql?(obj)    => true or false
- *  
- *  Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
- *  beginning and end items (by comparing them with #eql?), and has the same
- *  #exclude_end? setting as <i>rng</i>.
- *     
- *    (0..2) == (0..2)            #=> true
- *    (0..2) == Range.new(0,2)    #=> true
- *    (0..2) == (0...2)           #=> false
- *     
- */
-
-static VALUE
-range_eql(VALUE range, SEL sel, VALUE obj)
-{
-    if (range == obj) {
-	return Qtrue;
-    }
-    if (!rb_obj_is_kind_of(obj, rb_cRange)) {
-	return Qfalse;
-    }
-
-    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj))) {
-	return Qfalse;
-    }
-    if (!rb_eql(RANGE_END(range), RANGE_END(obj))) {
-	return Qfalse;
-    }
-
-    if (EXCL(range) != EXCL(obj)) {
-	return Qfalse;
-    }
-
-    return Qtrue;
-}
-
-/*
- * call-seq:
- *   rng.hash    => fixnum
- *
- * Generate a hash value such that two ranges with the same start and
- * end points, and the same value for the "exclude end" flag, generate
- * the same hash value.
- */
-
-static VALUE
-range_hash(VALUE range, SEL sel)
-{
-    long hash = EXCL(range);
-    VALUE v;
-
-    v = rb_hash(RANGE_BEG(range));
-    hash ^= v << 1;
-    v = rb_hash(RANGE_END(range));
-    hash ^= v << 9;
-    hash ^= EXCL(range) << 24;
-
-    return LONG2FIX(hash);
-}
-
-static VALUE
-range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
-{
-    int c;
-    VALUE b = RANGE_BEG(range);
-    VALUE e = RANGE_END(range);
-    VALUE v = b;
-
-    if (EXCL(range)) {
-	while (r_lt(v, e)) {
-	    (*func) (v, arg);
-	    RETURN_IF_BROKEN();
-	    v = rb_vm_call(v, selSucc, 0, NULL);
-	}
-    }
-    else {
-	while (RTEST(c = r_le(v, e))) {
-	    (*func) (v, arg);
-	    RETURN_IF_BROKEN();
-	    if (c == INT2FIX(0))
-		break;
-	    v = rb_vm_call(v, selSucc, 0, NULL);
-	}
-    }
-    return range;
-}
-
-static VALUE
-step_i(VALUE i, void *arg)
-{
-    VALUE *iter = arg;
-
-    if (FIXNUM_P(iter[0])) {
-	iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
-    }
-    else {
-	VALUE one = INT2FIX(1);
-	iter[0] = rb_vm_call(iter[0], selMINUS, 1, &one);
-    }
-    if (iter[0] == INT2FIX(0)) {
-	rb_yield(i);
-	iter[0] = iter[1];
-    }
-    return Qnil;
-}
-
-static VALUE
-sym_step_i(VALUE i, void *arg)
-{
-    VALUE *iter = arg;
-
-    if (FIXNUM_P(iter[0])) {
-	iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
-    }
-    else {
-	VALUE one = INT2FIX(1);
-	iter[0] = rb_vm_call(iter[0], selMINUS,1, &one);
-    }
-    if (iter[0] == INT2FIX(0)) {
-	rb_yield(ID2SYM(rb_intern_str(i)));
-	iter[0] = iter[1];
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     rng.step(n=1) {| obj | block }    => rng
- *  
- *  Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
- *  the range contains numbers, <i>n</i> is added for each iteration.  Otherwise
- *  <code>step</code> invokes <code>succ</code> to iterate through range
- *  elements. The following code uses class <code>Xs</code>, which is defined
- *  in the class-level documentation.
- *     
- *     range = Xs.new(1)..Xs.new(10)
- *     range.step(2) {|x| puts x}
- *     range.step(3) {|x| puts x}
- *     
- *  <em>produces:</em>
- *     
- *      1 x
- *      3 xxx
- *      5 xxxxx
- *      7 xxxxxxx
- *      9 xxxxxxxxx
- *      1 x
- *      4 xxxx
- *      7 xxxxxxx
- *     10 xxxxxxxxxx
- */
-
-
-static VALUE
-range_step(VALUE range, SEL sel, int argc, VALUE *argv)
-{
-    VALUE b, e, step, tmp;
-
-    RETURN_ENUMERATOR(range, argc, argv);
-
-    b = RANGE_BEG(range);
-    e = RANGE_END(range);
-    if (argc == 0) {
-	step = INT2FIX(1);
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &step);
-	if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
-	    step = rb_to_int(step);
-	}
-	VALUE zero = INT2FIX(0);
-	if (rb_vm_call(step, selLT, 1, &zero)) {
-	    rb_raise(rb_eArgError, "step can't be negative");
-	}
-	else if (!rb_vm_call(step, selGT, 1, &zero)) {
-	    rb_raise(rb_eArgError, "step can't be 0");
-	}
-    }
-
-    if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
-	long end = FIX2LONG(e);
-	long i, unit = FIX2LONG(step);
-
-	if (!EXCL(range))
-	    end += 1;
-	i = FIX2LONG(b);	
-	while (i < end) {
-	    rb_yield(LONG2NUM(i));
-	    RETURN_IF_BROKEN();
-	    if (i + unit < i) break;
-	    i += unit;
-	}
-
-    }
-    else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
-	VALUE args[2];
-	VALUE iter[2];
-
-	args[0] = rb_sym_to_s(e);
-	args[1] = EXCL(range) ? Qtrue : Qfalse;
-	iter[0] = INT2FIX(1);
-	iter[1] = step;
-	rb_objc_block_call(rb_sym_to_s(b), selUpto, 2, args, sym_step_i, (VALUE)iter);
-    }
-    else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
-	     !NIL_P(rb_check_to_integer(b, "to_int")) ||
-	     !NIL_P(rb_check_to_integer(e, "to_int"))) {
-	SEL op = EXCL(range) ? selLT : selLE;
-
-	while (RTEST(rb_vm_call(b, op, 1, &e))) {
-	    rb_yield(b);
-	    RETURN_IF_BROKEN();
-	    b = rb_vm_call(b, selPLUS, 1, &step);
-	}
-    }
-    else {
-	tmp = rb_check_string_type(b);
-
-	if (!NIL_P(tmp)) {
-	    VALUE args[2], iter[2];
-
-	    b = tmp;
-	    args[0] = e;
-	    args[1] = EXCL(range) ? Qtrue : Qfalse;
-	    iter[0] = INT2FIX(1);
-	    iter[1] = step;
-	    rb_objc_block_call(b, selUpto, 2, args, step_i, (VALUE)iter);
-	}
-	else {
-	    VALUE args[2];
-
-	    if (!rb_vm_respond_to(b, selSucc, true)) {
-		rb_raise(rb_eTypeError, "can't iterate from %s",
-			 rb_obj_classname(b));
-	    }
-	    args[0] = INT2FIX(1);
-	    args[1] = step;
-	    return range_each_func(range, step_i, args);
-	}
-    }
-    return range;
-}
-
-static VALUE
-each_i(VALUE v, void *arg)
-{
-    rb_yield(v);
-    return Qnil;
-}
-
-static VALUE
-sym_each_i(VALUE v, void *arg)
-{
-    rb_yield(ID2SYM(rb_intern_str(v)));
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     rng.each {| i | block } => rng
- *  
- *  Iterates over the elements <i>rng</i>, passing each in turn to the
- *  block. You can only iterate if the start object of the range
- *  supports the +succ+ method (which means that you can't iterate over
- *  ranges of +Float+ objects).
- *     
- *     (10..15).each do |n|
- *        print n, ' '
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     10 11 12 13 14 15
- */
-
-static VALUE
-range_each(VALUE range, SEL sel)
-{
-    VALUE beg, end;
-
-    RETURN_ENUMERATOR(range, 0, 0);
-
-    beg = RANGE_BEG(range);
-    end = RANGE_END(range);
-
-    if (!rb_vm_respond_to(beg, selSucc, false)) {
-	rb_raise(rb_eTypeError, "can't iterate from %s",
-		 rb_obj_classname(beg));
-    }
-    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
-	long lim = FIX2LONG(end);
-	long i;
-
-	if (!EXCL(range))
-	    lim += 1;
-	for (i = FIX2LONG(beg); i < lim; i++) {
-	    rb_yield(LONG2FIX(i));
-	    RETURN_IF_BROKEN();
-	}
-    }
-    else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
-	VALUE args[2];
-
-	args[0] = rb_sym_to_s(end);
-	args[1] = EXCL(range) ? Qtrue : Qfalse;
-	rb_objc_block_call(rb_sym_to_s(beg), selUpto, 2, args, sym_each_i, 0);
-    }
-    else if (TYPE(beg) == T_STRING) {
-	VALUE args[2];
-
-	args[0] = end;
-	args[1] = EXCL(range) ? Qtrue : Qfalse;
-	rb_objc_block_call(beg, selUpto, 2, args, rb_yield, 0);
-    }
-    else {
-	return range_each_func(range, each_i, NULL);
-    }
-    return range;
-}
-
-/*
- *  call-seq:
- *     rng.begin    => obj
- *  
- *  Returns the first object in <i>rng</i>.
- */
-
-static VALUE
-range_begin(VALUE range, SEL sel)
-{
-    return RANGE_BEG(range);
-}
-
-
-/*
- *  call-seq:
- *     rng.end    => obj
- *  
- *  Returns the object that defines the end of <i>rng</i>.
- *     
- *     (1..10).end    #=> 10
- *     (1...10).end   #=> 10
- */
-
-
-static VALUE
-range_end(VALUE range, SEL sel)
-{
-    return RANGE_END(range);
-}
-
-
-static VALUE
-first_i(VALUE i, VALUE *ary)
-{
-    long n = NUM2LONG(ary[0]);
-
-    if (n <= 0) {
-	rb_iter_break();
-    }
-    rb_ary_push(ary[1], i);
-    n--;
-    ary[0] = INT2NUM(n);
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     rng.first    => obj
- *     rng.first(n) => an_array
- *  
- *  Returns the first object in <i>rng</i>, or the first +n+ elements.
- */
-
-static VALUE
-range_first(VALUE range, SEL sel, int argc, VALUE *argv)
-{
-    VALUE n, ary[2];
-
-    if (argc == 0) return RANGE_BEG(range);
-
-    rb_scan_args(argc, argv, "1", &n);
-    ary[0] = n;
-    ary[1] = rb_ary_new2(NUM2LONG(n));
-    rb_objc_block_call(range, selEach, 0, 0, first_i, (VALUE)ary);
-
-    return ary[1];
-}
-
-
-/*
- *  call-seq:
- *     rng.last    => obj
- *     rng.last(n) => an_array
- *  
- *  Returns the last object in <i>rng</i>, or the last +n+ elements.
- */
-
-static VALUE
-range_last(VALUE range, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0) {
-	return RANGE_END(range);
-    }
-    return rary_last(rb_Array(range), 0, argc, argv);
-}
-
-
-/*
- *  call-seq:
- *     rng.min                    => obj
- *     rng.min {| a,b | block }   => obj
- *  
- *  Returns the minimum value in <i>rng</i>. The second uses
- *  the block to compare values.  Returns nil if the first
- *  value in range is larger than the last value.
- *     
- */
-
-
-static VALUE
-range_min(VALUE range, SEL sel)
-{
-    if (rb_block_given_p()) {
-	if (sel == NULL) {
-	    sel = sel_registerName("min");
-	}
-	return rb_vm_call_super(range, sel, 0, NULL);
-    }
-    else {
-	VALUE b = RANGE_BEG(range);
-	VALUE e = RANGE_END(range);
-	int c = rb_cmpint(rb_objs_cmp(b, e), b, e);
-
-	if (c > 0 || (c == 0 && EXCL(range)))
-	    return Qnil;
-	return b;
-    }
-}
-
-/*
- *  call-seq:
- *     rng.max                    => obj
- *     rng.max {| a,b | block }   => obj
- *  
- *  Returns the maximum value in <i>rng</i>. The second uses
- *  the block to compare values.  Returns nil if the first
- *  value in range is larger than the last value.
- *     
- */
-
-
-static VALUE
-range_max(VALUE range, SEL sel)
-{
-    VALUE e = RANGE_END(range);
-    int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
-
-    if (rb_block_given_p() || (EXCL(range) && !nm)) {
-	if (sel == NULL) {
-	    sel = sel_registerName("max");
-	}
-	return rb_vm_call_super(range, sel, 0, NULL);
-    }
-    else {
-	VALUE b = RANGE_BEG(range);
-	int c = rb_cmpint(rb_objs_cmp(b, e), b, e);
-
-	if (c > 0)
-	    return Qnil;
-	if (EXCL(range)) {
-	    if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
-		rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
-	    }
-	    if (c == 0) {
-		return Qnil;
-	    }
-	    if (FIXNUM_P(e)) {
-		return LONG2NUM(FIX2LONG(e) - 1);
-	    }
-	    VALUE one = INT2FIX(1);
-	    return rb_vm_call(e, selMINUS, 1, &one);
-	}
-	return e;
-    }
-}
-
-void
-rb_range_extract(VALUE range, VALUE *begp, VALUE *endp, bool *exclude)
-{
-    assert(begp != NULL && endp != NULL && exclude != NULL);
-    *begp = RANGE_BEG(range);
-    *endp = RANGE_END(range);
-    *exclude = EXCL(range);
-}
-
-int
-rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
-{
-    VALUE b, e;
-    int excl;
-
-    if (rb_obj_is_kind_of(range, rb_cRange)) {
-        b = RANGE_BEG(range);
-        e = RANGE_END(range);
-        excl = EXCL(range);
-    }
-    else {
-	if (!rb_vm_respond_to(range, selBeg, false)) {
-	    return Qfalse;
-	}
-	if (!rb_vm_respond_to(range, selEnd, false)) {
-	    return Qfalse;
-	}
-	b = rb_vm_call(range, selBeg, 0, NULL);
-	e = rb_vm_call(range, selEnd, 0, NULL);
-	excl = RTEST(rb_vm_call(range, selExcludeEnd, 0, NULL));
-    }
-    *begp = b;
-    *endp = e;
-    *exclp = excl;
-    return 1;
-}
-
-VALUE
-rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
-{
-    VALUE b, e;
-    long beg, end, excl;
-
-    if (rb_obj_is_kind_of(range, rb_cRange)) {
-	b = RANGE_BEG(range);
-	e = RANGE_END(range);
-	excl = EXCL(range);
-    }
-    else {
-	if (!rb_vm_respond_to(range, selBeg, false)) {
-	    return Qfalse;
-	}
-	if (!rb_vm_respond_to(range, selEnd, false)) {
-	    return Qfalse;
-	}
-	b = rb_vm_call(range, selBeg, 0, NULL);
-	e = rb_vm_call(range, selEnd, 0, NULL);
-	excl = RTEST(rb_vm_call(range, selExcludeEnd, 0, NULL));
-    }
-    beg = NUM2LONG(b);
-    end = NUM2LONG(e);
-
-    if (beg < 0) {
-	beg += len;
-	if (beg < 0)
-	    goto out_of_range;
-    }
-    if (err == 0 || err == 2) {
-	if (beg > len)
-	    goto out_of_range;
-	if (end > len)
-	    end = len;
-    }
-    if (end < 0)
-	end += len;
-    if (!excl)
-	end++;			/* include end point */
-    len = end - beg;
-    if (len < 0)
-	len = 0;
-
-    *begp = beg;
-    *lenp = len;
-    return Qtrue;
-
-  out_of_range:
-    if (err) {
-	rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
-		 b, excl ? "." : "", e);
-    }
-    return Qnil;
-}
-
-/*
- * call-seq:
- *   rng.to_s   => string
- *
- * Convert this range object to a printable form.
- */
-
-static VALUE
-range_to_s(VALUE range, SEL sel)
-{
-    VALUE str, str2;
-
-    str = rb_obj_as_string(RANGE_BEG(range));
-    str2 = rb_obj_as_string(RANGE_END(range));
-    str = rb_str_dup(str);
-    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
-    rb_str_append(str, str2);
-    OBJ_INFECT(str, str2);
-
-    return str;
-}
-
-/*
- * call-seq:
- *   rng.inspect  => string
- *
- * Convert this range object to a printable form (using 
- * <code>inspect</code> to convert the start and end
- * objects).
- */
-
-
-static VALUE
-range_inspect(VALUE range, SEL sel)
-{
-    VALUE str, str2;
-
-    str = rb_inspect(RANGE_BEG(range));
-    str2 = rb_inspect(RANGE_END(range));
-    str = rb_str_dup(str);
-    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
-    rb_str_append(str, str2);
-    OBJ_INFECT(str, str2);
-
-    return str;
-}
-
-/*
- *  call-seq:
- *     rng === obj       =>  true or false
- *  
- *  Returns <code>true</code> if <i>obj</i> is an element of
- *  <i>rng</i>, <code>false</code> otherwise. Conveniently,
- *  <code>===</code> is the comparison operator used by
- *  <code>case</code> statements.
- *     
- *     case 79
- *     when 1..50   then   print "low\n"
- *     when 51..75  then   print "medium\n"
- *     when 76..100 then   print "high\n"
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     high
- */
-
-static VALUE
-range_eqq(VALUE range, SEL sel, VALUE val)
-{
-    return rb_vm_call(range, selInclude, 1, &val);
-}
-
-/*
- *  call-seq:
- *     rng.member?(val)  =>  true or false
- *     rng.include?(val) =>  true or false
- *  
- *  Returns <code>true</code> if <i>obj</i> is an element of
- *  <i>rng</i>, <code>false</code> otherwise.  If beg and end are
- *  numeric, comparison is done according magnitude of values.
- *     
- *     ("a".."z").include?("g")  # => true
- *     ("a".."z").include?("A")  # => false
- */
-
-static VALUE
-range_include(VALUE range, SEL sel, VALUE val)
-{
-    VALUE beg = RANGE_BEG(range);
-    VALUE end = RANGE_END(range);
-    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
-	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
-	     rb_obj_is_kind_of(end, rb_cNumeric);
-
-    if (nv ||
-	!NIL_P(rb_check_to_integer(beg, "to_int")) ||
-	!NIL_P(rb_check_to_integer(end, "to_int"))) {
-	if (r_le(beg, val)) {
-	    if (EXCL(range)) {
-		if (r_lt(val, end))
-		    return Qtrue;
-	    }
-	    else {
-		if (r_le(val, end))
-		    return Qtrue;
-	    }
-	}
-	return Qfalse;
-    }
-    else if (TYPE(beg) == T_STRING && TYPE(end) == T_STRING &&
-	     RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
-	if (NIL_P(val)) return Qfalse;
-	if (TYPE(val) == T_STRING) {
-	    if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
-		return Qfalse;
-	    else {
-		char b = RSTRING_PTR(beg)[0];
-		char e = RSTRING_PTR(end)[0];
-		char v = RSTRING_PTR(val)[0];
-
-		if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
-		    if (b <= v && v < e) return Qtrue;
-		    if (!EXCL(range) && v == e) return Qtrue;
-		    return Qfalse;
-		}
-	    }
-	}
-    }
-    if (sel == NULL) {
-	sel = sel_registerName("include?:");
-    }
-    return rb_vm_call_super(range, sel, 1, &val);
-}
-
-
-/*
- *  call-seq:
- *     rng.cover?(val)  =>  true or false
- *  
- *  Returns <code>true</code> if <i>obj</i> is between beg and end,
- *  i.e <code>beg <= obj <= end</code> (or <i>end</i> exclusive when
- *  <code>exclude_end?</code> is true).
- *     
- *     ("a".."z").cover?("c")    #=> true
- *     ("a".."z").cover?("5")    #=> false
- */
-
-static VALUE
-range_cover(VALUE range, SEL sel, VALUE val)
-{
-    VALUE beg, end;
-
-    beg = RANGE_BEG(range);
-    end = RANGE_END(range);
-    if (r_le(beg, val)) {
-	if (EXCL(range)) {
-	    if (r_lt(val, end))
-		return Qtrue;
-	}
-	else {
-	    if (r_le(val, end))
-		return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-#if 0
-static VALUE
-range_dumper(VALUE range)
-{
-    VALUE v;
-    NEWOBJ(m, struct RObject);
-    OBJSETUP(m, rb_cObject, T_OBJECT);
-
-    v = (VALUE)m;
-
-    rb_ivar_set(v, id_excl, RANGE_EXCL(range));
-    rb_ivar_set(v, id_beg, RANGE_BEG(range));
-    rb_ivar_set(v, id_end, RANGE_END(range));
-    return v;
-}
-
-static VALUE
-range_loader(VALUE range, VALUE obj)
-{
-    if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
-        rb_raise(rb_eTypeError, "not a dumped range object");
-    }
-
-    RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
-    RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
-    RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
-    return range;
-}
-#endif
-
-static VALUE
-range_alloc(VALUE klass)
-{
-  /* rb_struct_alloc_noinit itself should not be used because
-   * rb_marshal_define_compat uses equality of allocaiton function */
-    return rb_struct_alloc_noinit(klass);
-}
-
-/*  A <code>Range</code> represents an interval---a set of values with a
- *  start and an end. Ranges may be constructed using the
- *  <em>s</em><code>..</code><em>e</em> and
- *  <em>s</em><code>...</code><em>e</em> literals, or with
- *  <code>Range::new</code>. Ranges constructed using <code>..</code>
- *  run from the start to the end inclusively. Those created using
- *  <code>...</code> exclude the end value. When used as an iterator,
- *  ranges return each value in the sequence.
- *     
- *     (-1..-5).to_a      #=> []
- *     (-5..-1).to_a      #=> [-5, -4, -3, -2, -1]
- *     ('a'..'e').to_a    #=> ["a", "b", "c", "d", "e"]
- *     ('a'...'e').to_a   #=> ["a", "b", "c", "d"]
- *     
- *  Ranges can be constructed using objects of any type, as long as the
- *  objects can be compared using their <code><=></code> operator and
- *  they support the <code>succ</code> method to return the next object
- *  in sequence.
- *     
- *     class Xs                # represent a string of 'x's
- *       include Comparable
- *       attr :length
- *       def initialize(n)
- *         @length = n
- *       end
- *       def succ
- *         Xs.new(@length + 1)
- *       end
- *       def <=>(other)
- *         @length <=> other.length
- *       end
- *       def to_s
- *         sprintf "%2d #{inspect}", @length
- *       end
- *       def inspect
- *         'x' * @length
- *       end
- *     end
- *     
- *     r = Xs.new(3)..Xs.new(6)   #=> xxx..xxxxxx
- *     r.to_a                     #=> [xxx, xxxx, xxxxx, xxxxxx]
- *     r.member?(Xs.new(5))       #=> true
- *     
- *  In the previous code example, class <code>Xs</code> includes the
- *  <code>Comparable</code> module. This is because
- *  <code>Enumerable#member?</code> checks for equality using
- *  <code>==</code>. Including <code>Comparable</code> ensures that the
- *  <code>==</code> method is defined in terms of the <code><=></code>
- *  method implemented in <code>Xs</code>.
- *     
- */
-
-void
-Init_Range(void)
-{
-    rb_cRange = rb_struct_define_without_accessor(
-        "Range", rb_cObject, range_alloc,
-        "begin", "end", "excl", NULL);
-
-    rb_include_module(rb_cRange, rb_mEnumerable);
-    //rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
-    rb_objc_define_method(rb_cRange, "initialize", range_initialize, -1);
-    rb_objc_define_method(rb_cRange, "==", range_eq, 1);
-    rb_objc_define_method(rb_cRange, "===", range_eqq, 1);
-    rb_objc_define_method(rb_cRange, "eql?", range_eql, 1);
-    rb_objc_define_method(rb_cRange, "hash", range_hash, 0);
-    rb_objc_define_method(rb_cRange, "each", range_each, 0);
-    rb_objc_define_method(rb_cRange, "step", range_step, -1);
-    rb_objc_define_method(rb_cRange, "begin", range_begin, 0);
-    rb_objc_define_method(rb_cRange, "end", range_end, 0);
-    rb_objc_define_method(rb_cRange, "first", range_first, -1);
-    rb_objc_define_method(rb_cRange, "last", range_last, -1);
-    rb_objc_define_method(rb_cRange, "min", range_min, 0);
-    rb_objc_define_method(rb_cRange, "max", range_max, 0);
-    rb_objc_define_method(rb_cRange, "to_s", range_to_s, 0);
-    rb_objc_define_method(rb_cRange, "inspect", range_inspect, 0);
-
-    rb_objc_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
-
-    rb_objc_define_method(rb_cRange, "member?", range_include, 1);
-    rb_objc_define_method(rb_cRange, "include?", range_include, 1);
-    rb_objc_define_method(rb_cRange, "cover?", range_cover, 1);
-
-    selUpto = sel_registerName("upto:");
-    selBeg = sel_registerName("begin");
-    selEnd = sel_registerName("end");
-    selExcludeEnd = sel_registerName("exclude_end?");
-    selInclude = sel_registerName("include?:");
-}

Deleted: MacRuby/trunk/rational.c
===================================================================
--- MacRuby/trunk/rational.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/rational.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2379 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2008-2009, Tadayoshi Funaba
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-
-#include <math.h>
-#include <float.h>
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#define NDEBUG
-#include <assert.h>
-
-#define ZERO INT2FIX(0)
-#define ONE INT2FIX(1)
-#define TWO INT2FIX(2)
-
-VALUE rb_cRational;
-
-static ID id_abs, id_cmp, id_convert, id_eqeq_p, id_expt, id_fdiv,
-    id_floor, id_idiv, id_inspect, id_integer_p, id_negate, id_to_f,
-    id_to_i, id_to_s, id_truncate;
-
-#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
-
-#define binop(n,op) \
-inline static VALUE \
-f_##n(VALUE x, VALUE y)\
-{\
-  return rb_funcall(x, op, 1, y);\
-}
-
-#define fun1(n) \
-inline static VALUE \
-f_##n(VALUE x)\
-{\
-    return rb_funcall(x, id_##n, 0);\
-}
-
-#define fun2(n) \
-inline static VALUE \
-f_##n(VALUE x, VALUE y)\
-{\
-    return rb_funcall(x, id_##n, 1, y);\
-}
-
-inline static VALUE
-f_add(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
-	return x;
-    else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
-	return y;
-    return rb_funcall(x, '+', 1, y);
-}
-
-inline static VALUE
-f_cmp(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y)) {
-	long c = FIX2LONG(x) - FIX2LONG(y);
-	if (c > 0)
-	    c = 1;
-	else if (c < 0)
-	    c = -1;
-	return INT2FIX(c);
-    }
-    return rb_funcall(x, id_cmp, 1, y);
-}
-
-inline static VALUE
-f_div(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y) && FIX2LONG(y) == 1)
-	return x;
-    return rb_funcall(x, '/', 1, y);
-}
-
-inline static VALUE
-f_gt_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y))
-	return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
-    return rb_funcall(x, '>', 1, y);
-}
-
-inline static VALUE
-f_lt_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y))
-	return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
-    return rb_funcall(x, '<', 1, y);
-}
-
-binop(mod, '%')
-
-inline static VALUE
-f_mul(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y)) {
-	long iy = FIX2LONG(y);
-	if (iy == 0) {
-	    if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM)
-		return ZERO;
-	}
-	else if (iy == 1)
-	    return x;
-    }
-    else if (FIXNUM_P(x)) {
-	long ix = FIX2LONG(x);
-	if (ix == 0) {
-	    if (FIXNUM_P(y) || TYPE(y) == T_BIGNUM)
-		return ZERO;
-	}
-	else if (ix == 1)
-	    return y;
-    }
-    return rb_funcall(x, '*', 1, y);
-}
-
-inline static VALUE
-f_sub(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
-	return x;
-    return rb_funcall(x, '-', 1, y);
-}
-
-fun1(abs)
-fun1(floor)
-fun1(inspect)
-fun1(integer_p)
-fun1(negate)
-fun1(to_f)
-fun1(to_i)
-fun1(to_s)
-fun1(truncate)
-
-inline static VALUE
-f_eqeq_p(VALUE x, VALUE y)
-{
-    if (FIXNUM_P(x) && FIXNUM_P(y))
-	return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
-    return rb_funcall(x, id_eqeq_p, 1, y);
-}
-
-fun2(expt)
-fun2(fdiv)
-fun2(idiv)
-
-inline static VALUE
-f_negative_p(VALUE x)
-{
-    if (FIXNUM_P(x))
-	return f_boolcast(FIX2LONG(x) < 0);
-    return rb_funcall(x, '<', 1, ZERO);
-}
-
-#define f_positive_p(x) (!f_negative_p(x))
-
-inline static VALUE
-f_zero_p(VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-	return f_boolcast(FIX2LONG(x) == 0);
-      case T_BIGNUM:
-	return Qfalse;
-      case T_RATIONAL:
-      {
-	  VALUE num = RRATIONAL(x)->num;
-
-	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
-      }
-    }
-    return rb_funcall(x, id_eqeq_p, 1, ZERO);
-}
-
-#define f_nonzero_p(x) (!f_zero_p(x))
-
-inline static VALUE
-f_one_p(VALUE x)
-{
-    switch (TYPE(x)) {
-      case T_FIXNUM:
-	return f_boolcast(FIX2LONG(x) == 1);
-      case T_BIGNUM:
-	return Qfalse;
-      case T_RATIONAL:
-      {
-	  VALUE num = RRATIONAL(x)->num;
-	  VALUE den = RRATIONAL(x)->den;
-
-	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
-			    FIXNUM_P(den) && FIX2LONG(den) == 1);
-      }
-    }
-    return rb_funcall(x, id_eqeq_p, 1, ONE);
-}
-
-inline static VALUE
-f_kind_of_p(VALUE x, VALUE c)
-{
-    return rb_obj_is_kind_of(x, c);
-}
-
-inline static VALUE
-k_numeric_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cNumeric);
-}
-
-inline static VALUE
-k_integer_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cInteger);
-}
-
-inline static VALUE
-k_float_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cFloat);
-}
-
-inline static VALUE
-k_rational_p(VALUE x)
-{
-    return f_kind_of_p(x, rb_cRational);
-}
-
-#define k_exact_p(x) (!k_float_p(x))
-#define k_inexact_p(x) k_float_p(x)
-
-#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
-#define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
-
-#ifndef NDEBUG
-#define f_gcd f_gcd_orig
-#endif
-
-inline static long
-i_gcd(long x, long y)
-{
-    if (x < 0)
-	x = -x;
-    if (y < 0)
-	y = -y;
-
-    if (x == 0)
-	return y;
-    if (y == 0)
-	return x;
-
-    while (x > 0) {
-	long t = x;
-	x = y % x;
-	y = t;
-    }
-    return y;
-}
-
-inline static VALUE
-f_gcd(VALUE x, VALUE y)
-{
-    VALUE z;
-
-    if (FIXNUM_P(x) && FIXNUM_P(y))
-	return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
-
-    if (f_negative_p(x))
-	x = f_negate(x);
-    if (f_negative_p(y))
-	y = f_negate(y);
-
-    if (f_zero_p(x))
-	return y;
-    if (f_zero_p(y))
-	return x;
-
-    for (;;) {
-	if (FIXNUM_P(x)) {
-	    if (FIX2LONG(x) == 0)
-		return y;
-	    if (FIXNUM_P(y))
-		return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
-	}
-	z = x;
-	x = f_mod(y, x);
-	y = z;
-    }
-    /* NOTREACHED */
-}
-
-#ifndef NDEBUG
-#undef f_gcd
-
-inline static VALUE
-f_gcd(VALUE x, VALUE y)
-{
-    VALUE r = f_gcd_orig(x, y);
-    if (f_nonzero_p(r)) {
-	assert(f_zero_p(f_mod(x, r)));
-	assert(f_zero_p(f_mod(y, r)));
-    }
-    return r;
-}
-#endif
-
-inline static VALUE
-f_lcm(VALUE x, VALUE y)
-{
-    if (f_zero_p(x) || f_zero_p(y))
-	return ZERO;
-    return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
-}
-
-#define get_dat1(x) \
-    struct RRational *dat;\
-    dat = ((struct RRational *)(x))
-
-#define get_dat2(x,y) \
-    struct RRational *adat, *bdat;\
-    adat = ((struct RRational *)(x));\
-    bdat = ((struct RRational *)(y))
-
-inline static VALUE
-nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
-{
-    NEWOBJ(obj, struct RRational);
-    OBJSETUP(obj, klass, T_RATIONAL);
-
-    obj->num = num;
-    obj->den = den;
-
-    return (VALUE)obj;
-}
-
-static VALUE
-nurat_s_alloc(VALUE klass, SEL sel)
-{
-    return nurat_s_new_internal(klass, ZERO, ONE);
-}
-
-#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
-
-#if 0
-static VALUE
-nurat_s_new_bang(int argc, VALUE *argv, VALUE klass)
-{
-    VALUE num, den;
-
-    switch (rb_scan_args(argc, argv, "11", &num, &den)) {
-      case 1:
-	if (!k_integer_p(num))
-	    num = f_to_i(num);
-	den = ONE;
-	break;
-      default:
-	if (!k_integer_p(num))
-	    num = f_to_i(num);
-	if (!k_integer_p(den))
-	    den = f_to_i(den);
-
-	switch (FIX2INT(f_cmp(den, ZERO))) {
-	  case -1:
-	    num = f_negate(num);
-	    den = f_negate(den);
-	    break;
-	  case 0:
-	    rb_raise_zerodiv();
-	    break;
-	}
-	break;
-    }
-
-    return nurat_s_new_internal(klass, num, den);
-}
-#endif
-
-inline static VALUE
-f_rational_new_bang1(VALUE klass, VALUE x)
-{
-    return nurat_s_new_internal(klass, x, ONE);
-}
-
-inline static VALUE
-f_rational_new_bang2(VALUE klass, VALUE x, VALUE y)
-{
-    assert(f_positive_p(y));
-    assert(f_nonzero_p(y));
-    return nurat_s_new_internal(klass, x, y);
-}
-
-#ifdef CANONICALIZATION_FOR_MATHN
-#define CANON
-#endif
-
-#ifdef CANON
-static int canonicalization = 0;
-
-void
-nurat_canonicalization(int f)
-{
-    canonicalization = f;
-}
-#endif
-
-inline static void
-nurat_int_check(VALUE num)
-{
-    switch (TYPE(num)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	break;
-      default:
-	if (!k_numeric_p(num) || !f_integer_p(num))
-	    rb_raise(rb_eTypeError, "not an integer");
-    }
-}
-
-inline static VALUE
-nurat_int_value(VALUE num)
-{
-    nurat_int_check(num);
-    if (!k_integer_p(num))
-	num = f_to_i(num);
-    return num;
-}
-
-inline static VALUE
-nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
-{
-    VALUE gcd;
-
-    switch (FIX2INT(f_cmp(den, ZERO))) {
-      case -1:
-	num = f_negate(num);
-	den = f_negate(den);
-	break;
-      case 0:
-	rb_raise_zerodiv();
-	break;
-    }
-
-    gcd = f_gcd(num, den);
-    num = f_idiv(num, gcd);
-    den = f_idiv(den, gcd);
-
-#ifdef CANON
-    if (f_one_p(den) && canonicalization)
-	return num;
-#endif
-    return nurat_s_new_internal(klass, num, den);
-}
-
-inline static VALUE
-nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
-{
-    switch (FIX2INT(f_cmp(den, ZERO))) {
-      case -1:
-	num = f_negate(num);
-	den = f_negate(den);
-	break;
-      case 0:
-	rb_raise_zerodiv();
-	break;
-    }
-
-#ifdef CANON
-    if (f_one_p(den) && canonicalization)
-	return num;
-#endif
-    return nurat_s_new_internal(klass, num, den);
-}
-
-static VALUE
-nurat_s_new(int argc, VALUE *argv, VALUE klass)
-{
-    VALUE num, den;
-
-    switch (rb_scan_args(argc, argv, "11", &num, &den)) {
-      case 1:
-	num = nurat_int_value(num);
-	den = ONE;
-	break;
-      default:
-	num = nurat_int_value(num);
-	den = nurat_int_value(den);
-	break;
-    }
-
-    return nurat_s_canonicalize_internal(klass, num, den);
-}
-
-inline static VALUE
-f_rational_new1(VALUE klass, VALUE x)
-{
-    assert(!k_rational_p(x));
-    return nurat_s_canonicalize_internal(klass, x, ONE);
-}
-
-inline static VALUE
-f_rational_new2(VALUE klass, VALUE x, VALUE y)
-{
-    assert(!k_rational_p(x));
-    assert(!k_rational_p(y));
-    return nurat_s_canonicalize_internal(klass, x, y);
-}
-
-inline static VALUE
-f_rational_new_no_reduce1(VALUE klass, VALUE x)
-{
-    assert(!k_rational_p(x));
-    return nurat_s_canonicalize_internal_no_reduce(klass, x, ONE);
-}
-
-inline static VALUE
-f_rational_new_no_reduce2(VALUE klass, VALUE x, VALUE y)
-{
-    assert(!k_rational_p(x));
-    assert(!k_rational_p(y));
-    return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
-}
-
-/*
- * call-seq:
- *    Rational(x[, y])  ->  numeric
- *
- * Returns x/y;
- */
-static VALUE
-nurat_f_rational(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    return rb_funcall2(rb_cRational, id_convert, argc, argv);
-}
-
-/*
- * call-seq:
- *    rat.numerator  ->  integer
- *
- * Returns the numerator.
- *
- * For example:
- *
- *    Rational(7).numerator        #=> 7
- *    Rational(7, 1).numerator     #=> 7
- *    Rational(9, -4).numerator    #=> -9
- *    Rational(-2, -10).numerator  #=> 1
- */
-static VALUE
-nurat_numerator(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return dat->num;
-}
-
-/*
- * call-seq:
- *    rat.denominator  ->  integer
- *
- * Returns the denominator (always positive).
- *
- * For example:
- *
- *    Rational(7).denominator             #=> 1
- *    Rational(7, 1).denominator          #=> 1
- *    Rational(9, -4).denominator         #=> 4
- *    Rational(-2, -10).denominator       #=> 5
- *    rat.numerator.gcd(rat.denominator)  #=> 1
- */
-static VALUE
-nurat_denominator(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return dat->den;
-}
-
-#ifndef NDEBUG
-#define f_imul f_imul_orig
-#endif
-
-inline static VALUE
-f_imul(long a, long b)
-{
-    VALUE r;
-    long c;
-
-    if (a == 0 || b == 0)
-	return ZERO;
-    else if (a == 1)
-	return LONG2NUM(b);
-    else if (b == 1)
-	return LONG2NUM(a);
-
-    c = a * b;
-    r = LONG2NUM(c);
-    if (NUM2LONG(r) != c || (c / a) != b)
-	r = rb_big_mul(rb_int2big(a), rb_int2big(b));
-    return r;
-}
-
-#ifndef NDEBUG
-#undef f_imul
-
-inline static VALUE
-f_imul(long x, long y)
-{
-    VALUE r = f_imul_orig(x, y);
-    assert(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
-    return r;
-}
-#endif
-
-inline static VALUE
-f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
-{
-    VALUE num, den;
-
-    if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
-	FIXNUM_P(bnum) && FIXNUM_P(bden)) {
-	long an = FIX2LONG(anum);
-	long ad = FIX2LONG(aden);
-	long bn = FIX2LONG(bnum);
-	long bd = FIX2LONG(bden);
-	long ig = i_gcd(ad, bd);
-
-	VALUE g = LONG2NUM(ig);
-	VALUE a = f_imul(an, bd / ig);
-	VALUE b = f_imul(bn, ad / ig);
-	VALUE c;
-
-	if (k == '+')
-	    c = f_add(a, b);
-	else
-	    c = f_sub(a, b);
-
-	b = f_idiv(aden, g);
-	g = f_gcd(c, g);
-	num = f_idiv(c, g);
-	a = f_idiv(bden, g);
-	den = f_mul(a, b);
-    }
-    else {
-	VALUE g = f_gcd(aden, bden);
-	VALUE a = f_mul(anum, f_idiv(bden, g));
-	VALUE b = f_mul(bnum, f_idiv(aden, g));
-	VALUE c;
-
-	if (k == '+')
-	    c = f_add(a, b);
-	else
-	    c = f_sub(a, b);
-
-	b = f_idiv(aden, g);
-	g = f_gcd(c, g);
-	num = f_idiv(c, g);
-	a = f_idiv(bden, g);
-	den = f_mul(a, b);
-    }
-    return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
-}
-
-/*
- * call-seq:
- *    rat + numeric  ->  numeric_result
- *
- * Performs addition.
- *
- * For example:
- *
- *    Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
- *    Rational(900)   + Rational(1)      #=> (900/1)
- *    Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
- *    Rational(9, 8)  + 4                #=> (41/8)
- *    Rational(20, 9) + 9.8              #=> 12.022222222222222
- */
-static VALUE
-nurat_add(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	{
-	    get_dat1(self);
-
-	    return f_addsub(self,
-			    dat->num, dat->den,
-			    other, ONE, '+');
-	}
-      case T_FLOAT:
-	return f_add(f_to_f(self), other);
-      case T_RATIONAL:
-	{
-	    get_dat2(self, other);
-
-	    return f_addsub(self,
-			    adat->num, adat->den,
-			    bdat->num, bdat->den, '+');
-	}
-      default:
-	return rb_num_coerce_bin(self, other, '+');
-    }
-}
-
-/*
- * call-seq:
- *    rat - numeric  ->  numeric_result
- *
- * Performs subtraction.
- *
- * For example:
- *
- *    Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
- *    Rational(900)   - Rational(1)      #=> (899/1)
- *    Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
- *    Rational(9, 8)  - 4                #=> (23/8)
- *    Rational(20, 9) - 9.8              #=> -7.577777777777778
- */
-static VALUE
-nurat_sub(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	{
-	    get_dat1(self);
-
-	    return f_addsub(self,
-			    dat->num, dat->den,
-			    other, ONE, '-');
-	}
-      case T_FLOAT:
-	return f_sub(f_to_f(self), other);
-      case T_RATIONAL:
-	{
-	    get_dat2(self, other);
-
-	    return f_addsub(self,
-			    adat->num, adat->den,
-			    bdat->num, bdat->den, '-');
-	}
-      default:
-	return rb_num_coerce_bin(self, other, '-');
-    }
-}
-
-inline static VALUE
-f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
-{
-    VALUE num, den;
-
-    if (k == '/') {
-	VALUE t;
-
-	if (f_negative_p(bnum)) {
-	    anum = f_negate(anum);
-	    bnum = f_negate(bnum);
-	}
-	t = bnum;
-	bnum = bden;
-	bden = t;
-    }
-
-    if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
-	FIXNUM_P(bnum) && FIXNUM_P(bden)) {
-	long an = FIX2LONG(anum);
-	long ad = FIX2LONG(aden);
-	long bn = FIX2LONG(bnum);
-	long bd = FIX2LONG(bden);
-	long g1 = i_gcd(an, bd);
-	long g2 = i_gcd(ad, bn);
-
-	num = f_imul(an / g1, bn / g2);
-	den = f_imul(ad / g2, bd / g1);
-    }
-    else {
-	VALUE g1 = f_gcd(anum, bden);
-	VALUE g2 = f_gcd(aden, bnum);
-
-	num = f_mul(f_idiv(anum, g1), f_idiv(bnum, g2));
-	den = f_mul(f_idiv(aden, g2), f_idiv(bden, g1));
-    }
-    return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
-}
-
-/*
- * call-seq:
- *    rat * numeric  ->  numeric_result
- *
- * Performs multiplication.
- *
- * For example:
- *
- *    Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
- *    Rational(900)   * Rational(1)      #=> (900/1)
- *    Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
- *    Rational(9, 8)  * 4                #=> (9/2)
- *    Rational(20, 9) * 9.8              #=> 21.77777777777778
- */
-static VALUE
-nurat_mul(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	{
-	    get_dat1(self);
-
-	    return f_muldiv(self,
-			    dat->num, dat->den,
-			    other, ONE, '*');
-	}
-      case T_FLOAT:
-	return f_mul(f_to_f(self), other);
-      case T_RATIONAL:
-	{
-	    get_dat2(self, other);
-
-	    return f_muldiv(self,
-			    adat->num, adat->den,
-			    bdat->num, bdat->den, '*');
-	}
-      default:
-	return rb_num_coerce_bin(self, other, '*');
-    }
-}
-
-/*
- * call-seq:
- *    rat / numeric     ->  numeric_result
- *    rat.quo(numeric)  ->  numeric_result
- *
- * Performs division.
- *
- * For example:
- *
- *    Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
- *    Rational(900)   / Rational(1)      #=> (900/1)
- *    Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
- *    Rational(9, 8)  / 4                #=> (9/32)
- *    Rational(20, 9) / 9.8              #=> 0.22675736961451246
- */
-static VALUE
-nurat_div(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	if (f_zero_p(other))
-	    rb_raise_zerodiv();
-	{
-	    get_dat1(self);
-
-	    return f_muldiv(self,
-			    dat->num, dat->den,
-			    other, ONE, '/');
-	}
-      case T_FLOAT:
-	return rb_funcall(f_to_f(self), '/', 1, other);
-      case T_RATIONAL:
-	if (f_zero_p(other))
-	    rb_raise_zerodiv();
-	{
-	    get_dat2(self, other);
-
-	    if (f_one_p(self))
-		return f_rational_new_no_reduce2(CLASS_OF(self),
-						 bdat->den, bdat->num);
-
-	    return f_muldiv(self,
-			    adat->num, adat->den,
-			    bdat->num, bdat->den, '/');
-	}
-      default:
-	return rb_num_coerce_bin(self, other, '/');
-    }
-}
-
-/*
- * call-seq:
- *    rat.fdiv(numeric)  ->  float
- *
- * Performs division and returns the value as a float.
- *
- * For example:
- *
- *    Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
- *    Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
- *    Rational(2).fdiv(3)          #=> 0.6666666666666666
- */
-static VALUE
-nurat_fdiv(VALUE self, SEL sel, VALUE other)
-{
-    if (f_zero_p(other))
-	return f_div(self, f_to_f(other));
-    return f_to_f(f_div(self, other));
-}
-
-extern VALUE rb_fexpt(VALUE x, VALUE y);
-
-/*
- * call-seq:
- *    rat ** numeric  ->  numeric_result
- *
- * Performs exponentiation.
- *
- * For example:
- *
- *    Rational(2)    ** Rational(3)    #=> (8/1)
- *    Rational(10)   ** -2             #=> (1/100)
- *    Rational(10)   ** -2.0           #=> 0.01
- *    Rational(-4)   ** Rational(1,2)  #=> (1.2246063538223773e-16+2.0i)
- *    Rational(1, 2) ** 0              #=> (1/1)
- *    Rational(1, 2) ** 0.0            #=> 1.0
- */
-static VALUE
-nurat_expt(VALUE self, SEL sel, VALUE other)
-{
-    if (k_exact_zero_p(other))
-	return f_rational_new_bang1(CLASS_OF(self), ONE);
-
-    if (k_rational_p(other)) {
-	get_dat1(other);
-
-	if (f_one_p(dat->den))
-	    other = dat->num; /* c14n */
-    }
-
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-	{
-	    VALUE num, den;
-
-	    get_dat1(self);
-
-	    switch (FIX2INT(f_cmp(other, ZERO))) {
-	      case 1:
-		num = f_expt(dat->num, other);
-		den = f_expt(dat->den, other);
-		break;
-	      case -1:
-		num = f_expt(dat->den, f_negate(other));
-		den = f_expt(dat->num, f_negate(other));
-		break;
-	      default:
-		num = ONE;
-		den = ONE;
-		break;
-	    }
-	    return f_rational_new2(CLASS_OF(self), num, den);
-	}
-      case T_BIGNUM:
-	rb_warn("in a**b, b may be too big");
-	/* fall through */
-      case T_FLOAT:
-      case T_RATIONAL:
-	return f_expt(f_to_f(self), other);
-      default:
-	return rb_num_coerce_bin(self, other, id_expt);
-    }
-}
-
-/*
- * call-seq:
- *    rat <=> numeric  ->  -1, 0, +1 or nil
- *
- * Performs comparison and returns -1, 0, or +1.
- *
- * For example:
- *
- *    Rational(2, 3)  <=> Rational(2, 3)  #=> 0
- *    Rational(5)     <=> 5               #=> 0
- *    Rational(2,3)   <=> Rational(1,3)   #=> 1
- *    Rational(1,3)   <=> 1               #=> -1
- *    Rational(1,3)   <=> 0.3             #=> 1
- */
-static VALUE
-nurat_cmp(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	{
-	    get_dat1(self);
-
-	    if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
-		return f_cmp(dat->num, other); /* c14n */
-	    return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
-	}
-      case T_FLOAT:
-	return f_cmp(f_to_f(self), other);
-      case T_RATIONAL:
-	{
-	    VALUE num1, num2;
-
-	    get_dat2(self, other);
-
-	    if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
-		FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
-		num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
-		num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
-	    }
-	    else {
-		num1 = f_mul(adat->num, bdat->den);
-		num2 = f_mul(bdat->num, adat->den);
-	    }
-	    return f_cmp(f_sub(num1, num2), ZERO);
-	}
-      default:
-	return rb_num_coerce_cmp(self, other, id_cmp);
-    }
-}
-
-/*
- * call-seq:
- *    rat == object  ->  true or false
- *
- * Returns true if rat equals object numerically.
- *
- * For example:
- *
- *    Rational(2, 3)  == Rational(2, 3)   #=> true
- *    Rational(5)     == 5                #=> true
- *    Rational(0)     == 0.0              #=> true
- *    Rational('1/3') == 0.33             #=> false
- *    Rational('1/2') == '1/2'            #=> false
- */
-static VALUE
-nurat_eqeq_p(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	{
-	    get_dat1(self);
-
-	    if (f_zero_p(dat->num) && f_zero_p(other))
-		return Qtrue;
-
-	    if (!FIXNUM_P(dat->den))
-		return Qfalse;
-	    if (FIX2LONG(dat->den) != 1)
-		return Qfalse;
-	    if (f_eqeq_p(dat->num, other))
-		return Qtrue;
-	    return Qfalse;
-	}
-      case T_FLOAT:
-	return f_eqeq_p(f_to_f(self), other);
-      case T_RATIONAL:
-	{
-	    get_dat2(self, other);
-
-	    if (f_zero_p(adat->num) && f_zero_p(bdat->num))
-		return Qtrue;
-
-	    return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
-			      f_eqeq_p(adat->den, bdat->den));
-	}
-      default:
-	return f_eqeq_p(other, self);
-    }
-}
-
-/* :nodoc: */
-static VALUE
-nurat_coerce(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
-      case T_FLOAT:
-	return rb_assoc_new(other, f_to_f(self));
-      case T_RATIONAL:
-	return rb_assoc_new(other, self);
-      case T_COMPLEX:
-	if (k_exact_zero_p(RCOMPLEX(other)->imag))
-	    return rb_assoc_new(f_rational_new_bang1
-				(CLASS_OF(self), RCOMPLEX(other)->real), self);
-    }
-
-    rb_raise(rb_eTypeError, "%s can't be coerced into %s",
-	     rb_obj_classname(other), rb_obj_classname(self));
-    return Qnil;
-}
-
-#if 0
-/* :nodoc: */
-static VALUE
-nurat_idiv(VALUE self, VALUE other)
-{
-    return f_idiv(self, other);
-}
-
-/* :nodoc: */
-static VALUE
-nurat_quot(VALUE self, VALUE other)
-{
-    return f_truncate(f_div(self, other));
-}
-
-/* :nodoc: */
-static VALUE
-nurat_quotrem(VALUE self, VALUE other)
-{
-    VALUE val = f_truncate(f_div(self, other));
-    return rb_assoc_new(val, f_sub(self, f_mul(other, val)));
-}
-#endif
-
-#if 0
-/* :nodoc: */
-static VALUE
-nurat_true(VALUE self)
-{
-    return Qtrue;
-}
-#endif
-
-static VALUE
-nurat_floor(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return f_idiv(dat->num, dat->den);
-}
-
-static VALUE
-nurat_ceil(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return f_negate(f_idiv(f_negate(dat->num), dat->den));
-}
-
-
-/*
- * call-seq:
- *    rat.to_i  ->  integer
- *
- * Returns the truncated value as an integer.
- *
- * Equivalent to
- *    rat.truncate.
- *
- * For example:
- *
- *    Rational(2, 3).to_i   #=> 0
- *    Rational(3).to_i      #=> 3
- *    Rational(300.6).to_i  #=> 300
- *    Rational(98,71).to_i  #=> 1
- *    Rational(-30,2).to_i  #=> -15
- */
-static VALUE
-nurat_truncate(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    if (f_negative_p(dat->num))
-	return f_negate(f_idiv(f_negate(dat->num), dat->den));
-    return f_idiv(dat->num, dat->den);
-}
-
-static VALUE
-nurat_round(VALUE self, SEL sel)
-{
-    VALUE num, den, neg;
-
-    get_dat1(self);
-
-    num = dat->num;
-    den = dat->den;
-    neg = f_negative_p(num);
-
-    if (neg)
-	num = f_negate(num);
-
-    num = f_add(f_mul(num, TWO), den);
-    den = f_mul(den, TWO);
-    num = f_idiv(num, den);
-
-    if (neg)
-	num = f_negate(num);
-
-    return num;
-}
-
-static VALUE
-f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE, SEL))
-{
-    VALUE n, b, s;
-
-    if (argc == 0)
-	return (*func)(self, NULL);
-
-    rb_scan_args(argc, argv, "01", &n);
-
-    if (!k_integer_p(n))
-	rb_raise(rb_eTypeError, "not an integer");
-
-    b = f_expt(INT2FIX(10), n);
-    s = f_mul(self, b);
-
-    s = (*func)(s, NULL);
-
-    s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
-
-    if (f_lt_p(n, ONE))
-	s = f_to_i(s);
-
-    return s;
-}
-
-/*
- * call-seq:
- *    rat.floor               ->  integer
- *    rat.floor(precision=0)  ->  rational
- *
- * Returns the truncated value (toward negative infinity).
- *
- * For example:
- *
- *    Rational(3).floor      #=> 3
- *    Rational(2, 3).floor   #=> 0
- *    Rational(-3, 2).floor  #=> -1
- *
- *           decimal      -  1  2  3 . 4  5  6
- *                          ^  ^  ^  ^   ^  ^
- *          precision      -3 -2 -1  0  +1 +2
- *
- *    '%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
- *    '%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"
- */
-static VALUE
-nurat_floor_n(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    return f_round_common(argc, argv, self, nurat_floor);
-}
-
-/*
- * call-seq:
- *    rat.ceil               ->  integer
- *    rat.ceil(precision=0)  ->  rational
- *
- * Returns the truncated value (toward positive infinity).
- *
- * For example:
- *
- *    Rational(3).ceil      #=> 3
- *    Rational(2, 3).ceil   #=> 1
- *    Rational(-3, 2).ceil  #=> -1
- *
- *           decimal      -  1  2  3 . 4  5  6
- *                          ^  ^  ^  ^   ^  ^
- *          precision      -3 -2 -1  0  +1 +2
- *
- *    '%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
- *    '%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"
- */
-static VALUE
-nurat_ceil_n(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    return f_round_common(argc, argv, self, nurat_ceil);
-}
-
-/*
- * call-seq:
- *    rat.truncate               ->  integer
- *    rat.truncate(precision=0)  ->  rational
- *
- * Returns the truncated value (toward zero).
- *
- * For example:
- *
- *    Rational(3).truncate      #=> 3
- *    Rational(2, 3).truncate   #=> 0
- *    Rational(-3, 2).truncate  #=> -1
- *
- *           decimal      -  1  2  3 . 4  5  6
- *                          ^  ^  ^  ^   ^  ^
- *          precision      -3 -2 -1  0  +1 +2
- *
- *    '%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
- *    '%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"
- */
-static VALUE
-nurat_truncate_n(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    return f_round_common(argc, argv, self, nurat_truncate);
-}
-
-/*
- * call-seq:
- *    rat.round               ->  integer
- *    rat.round(precision=0)  ->  rational
- *
- * Returns the truncated value (toward the nearest integer;
- * 0.5 => 1; -0.5 => -1).
- *
- * For example:
- *
- *    Rational(3).round      #=> 3
- *    Rational(2, 3).round   #=> 1
- *    Rational(-3, 2).round  #=> -2
- *
- *           decimal      -  1  2  3 . 4  5  6
- *                          ^  ^  ^  ^   ^  ^
- *          precision      -3 -2 -1  0  +1 +2
- *
- *    '%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
- *    '%f' % Rational('-123.456').round(-1)  #=> "-120.000000"
- */
-static VALUE
-nurat_round_n(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    return f_round_common(argc, argv, self, nurat_round);
-}
-
-/*
- * call-seq:
- *    rat.to_f  ->  float
- *
- * Return the value as a float.
- *
- * For example:
- *
- *    Rational(2).to_f      #=> 2.0
- *    Rational(9, 4).to_f   #=> 2.25
- *    Rational(-3, 4).to_f  #=> -0.75
- *    Rational(20, 3).to_f  #=> 6.666666666666667
- */
-static VALUE
-nurat_to_f(VALUE self, SEL sel)
-{
-    get_dat1(self);
-    return f_fdiv(dat->num, dat->den);
-}
-
-/*
- * call-seq:
- *    rat.to_r  ->  self
- *
- * Returns self.
- *
- * For example:
- *
- *    Rational(2).to_r      #=> (2/1)
- *    Rational(-8, 6).to_r  #=> (-4/3)
- */
-static VALUE
-nurat_to_r(VALUE self, SEL sel)
-{
-    return self;
-}
-
-#define id_ceil rb_intern("ceil")
-#define f_ceil(x) rb_funcall(x, id_ceil, 0)
-
-#define id_quo rb_intern("quo")
-#define f_quo(x,y) rb_funcall(x, id_quo, 1, y)
-
-#define f_reciprocal(x) f_quo(ONE, x)
-
-/*
-  The algorithm here is the method described in CLISP.  Bruno Haible has
-  graciously given permission to use this algorithm.  He says, "You can use
-  it, if you present the following explanation of the algorithm."
-
-  Algorithm (recursively presented):
-    If x is a rational number, return x.
-    If x = 0.0, return 0.
-    If x < 0.0, return (- (rationalize (- x))).
-    If x > 0.0:
-      Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
-      exponent, sign).
-      If m = 0 or e >= 0: return x = m*2^e.
-      Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
-      with smallest possible numerator and denominator.
-      Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
-        But in this case the result will be x itself anyway, regardless of
-        the choice of a. Therefore we can simply ignore this case.
-      Note 2: At first, we need to consider the closed interval [a,b].
-        but since a and b have the denominator 2^(|e|+1) whereas x itself
-        has a denominator <= 2^|e|, we can restrict the search to the open
-        interval (a,b).
-      So, for given a and b (0 < a < b) we are searching a rational number
-      y with a <= y <= b.
-      Recursive algorithm fraction_between(a,b):
-        c := (ceiling a)
-        if c < b
-          then return c       ; because a <= c < b, c integer
-          else
-            ; a is not integer (otherwise we would have had c = a < b)
-            k := c-1          ; k = floor(a), k < a < b <= k+1
-            return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
-                              ; note 1 <= 1/(b-k) < 1/(a-k)
-
-  You can see that we are actually computing a continued fraction expansion.
-
-  Algorithm (iterative):
-    If x is rational, return x.
-    Call (integer-decode-float x). It returns a m,e,s (mantissa,
-      exponent, sign).
-    If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
-    Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
-    (positive and already in lowest terms because the denominator is a
-    power of two and the numerator is odd).
-    Start a continued fraction expansion
-      p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
-    Loop
-      c := (ceiling a)
-      if c >= b
-        then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
-             goto Loop
-    finally partial_quotient(c).
-    Here partial_quotient(c) denotes the iteration
-      i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
-    At the end, return s * (p[i]/q[i]).
-    This rational number is already in lowest terms because
-    p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
-*/
-
-static void
-nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
-{
-    VALUE c, k, t, p0, p1, p2, q0, q1, q2;
-
-    p0 = ZERO;
-    p1 = ONE;
-    q0 = ONE;
-    q1 = ZERO;
-
-    while (1) {
-	c = f_ceil(a);
-	if (f_lt_p(c, b))
-	    break;
-	k = f_sub(c, ONE);
-	p2 = f_add(f_mul(k, p1), p0);
-	q2 = f_add(f_mul(k, q1), q0);
-	t = f_reciprocal(f_sub(b, k));
-	b = f_reciprocal(f_sub(a, k));
-	a = t;
-	p0 = p1;
-	q0 = q1;
-	p1 = p2;
-	q1 = q2;
-    }
-    *p = f_add(f_mul(c, p1), p0);
-    *q = f_add(f_mul(c, q1), q0);
-}
-
-/*
- * call-seq:
- *    rat.rationalize       ->  self
- *    rat.rationalize(eps)  ->  rational
- *
- * Returns a simpler approximation of the value if an optional
- * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
- * otherwise.
- *
- * For example:
- *
- *    r = Rational(5033165, 16777216)
- *    r.rationalize                    #=> (5033165/16777216)
- *    r.rationalize(Rational('0.01'))  #=> (3/10)
- *    r.rationalize(Rational('0.1'))   #=> (1/3)
- */
-static VALUE
-nurat_rationalize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE e, a, b, p, q;
-
-    if (argc == 0)
-	return self;
-
-    if (f_negative_p(self))
-	return f_negate(nurat_rationalize(f_abs(self), sel, argc, argv));
-
-    rb_scan_args(argc, argv, "01", &e);
-    e = f_abs(e);
-    a = f_sub(self, e);
-    b = f_add(self, e);
-
-    if (f_eqeq_p(a, b))
-	return self;
-
-    nurat_rationalize_internal(a, b, &p, &q);
-    return f_rational_new2(CLASS_OF(self), p, q);
-}
-
-/* :nodoc: */
-static VALUE
-nurat_hash(VALUE self, SEL sel)
-{
-    long v, h[2];
-    VALUE n;
-
-    get_dat1(self);
-    n = rb_hash(dat->num);
-    h[0] = NUM2LONG(n);
-    n = rb_hash(dat->den);
-    h[1] = NUM2LONG(n);
-    v = rb_memhash(h, sizeof(h));
-    return LONG2FIX(v);
-}
-
-static VALUE
-f_format(VALUE self, VALUE (*func)(VALUE))
-{
-    VALUE s;
-    get_dat1(self);
-
-    s = (*func)(dat->num);
-    rb_str_cat2(s, "/");
-    rb_str_concat(s, (*func)(dat->den));
-
-    return s;
-}
-
-/*
- * call-seq:
- *    rat.to_s  ->  string
- *
- * Returns the value as a string.
- *
- * For example:
- *
- *    Rational(2).to_s      #=> "2/1"
- *    Rational(-8, 6).to_s  #=> "-4/3"
- *    Rational('0.5').to_s  #=> "1/2"
- */
-static VALUE
-nurat_to_s(VALUE self, SEL sel)
-{
-    return f_format(self, f_to_s);
-}
-
-/*
- * call-seq:
- *    rat.inspect  ->  string
- *
- * Returns the value as a string for inspection.
- *
- * For example:
- *
- *    Rational(2).inspect      #=> "(2/1)"
- *    Rational(-8, 6).inspect  #=> "(-4/3)"
- *    Rational('0.5').inspect  #=> "(1/2)"
- */
-static VALUE
-nurat_inspect(VALUE self, SEL sel)
-{
-    VALUE s;
-
-    s = rb_usascii_str_new2("(");
-    rb_str_concat(s, f_format(self, f_inspect));
-    rb_str_cat2(s, ")");
-
-    return s;
-}
-
-/* :nodoc: */
-static VALUE
-nurat_marshal_dump(VALUE self, SEL sel)
-{
-    VALUE a;
-    get_dat1(self);
-
-    a = rb_assoc_new(dat->num, dat->den);
-    rb_copy_generic_ivar(a, self);
-    return a;
-}
-
-/* :nodoc: */
-static VALUE
-nurat_marshal_load(VALUE self, SEL sel, VALUE a)
-{
-    get_dat1(self);
-    VALUE ary = rb_convert_type(a, T_ARRAY, "Array", "to_ary");
-    dat->num = RARRAY_AT(ary, 0);
-    dat->den = RARRAY_AT(ary ,1);
-    rb_copy_generic_ivar(self, ary);
-    if (f_zero_p(dat->den)) {
-	rb_raise_zerodiv();
-    }
-    return self;
-}
-
-/* --- */
-
-VALUE
-rb_rational_reciprocal(VALUE x, SEL sel)
-{
-    get_dat1(x);
-    return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num);
-}
-
-/*
- * call-seq:
- *    int.gcd(int2)  ->  integer
- *
- * Returns the greatest common divisor (always positive).  0.gcd(x)
- * and x.gcd(0) return abs(x).
- *
- * For example:
- *
- *    2.gcd(2)                    #=> 2
- *    3.gcd(-7)                   #=> 1
- *    ((1<<31)-1).gcd((1<<61)-1)  #=> 1
- */
-VALUE
-rb_gcd(VALUE self, SEL sel, VALUE other)
-{
-    other = nurat_int_value(other);
-    return f_gcd(self, other);
-}
-
-/*
- * call-seq:
- *    int.lcm(int2)  ->  integer
- *
- * Returns the least common multiple (always positive).  0.lcm(x) and
- * x.lcm(0) return zero.
- *
- * For example:
- *
- *    2.lcm(2)                    #=> 2
- *    3.lcm(-7)                   #=> 21
- *    ((1<<31)-1).lcm((1<<61)-1)  #=> 4951760154835678088235319297
- */
-VALUE
-rb_lcm(VALUE self, SEL sel, VALUE other)
-{
-    other = nurat_int_value(other);
-    return f_lcm(self, other);
-}
-
-/*
- * call-seq:
- *    int.gcdlcm(int2)  ->  array
- *
- * Returns an array; [int.gcd(int2), int.lcm(int2)].
- *
- * For example:
- *
- *    2.gcdlcm(2)                    #=> [2, 2]
- *    3.gcdlcm(-7)                   #=> [1, 21]
- *    ((1<<31)-1).gcdlcm((1<<61)-1)  #=> [1, 4951760154835678088235319297]
- */
-VALUE
-rb_gcdlcm(VALUE self, SEL sel, VALUE other)
-{
-    other = nurat_int_value(other);
-    return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
-}
-
-VALUE
-rb_rational_raw(VALUE x, VALUE y)
-{
-    return nurat_s_new_internal(rb_cRational, x, y);
-}
-
-VALUE
-rb_rational_new(VALUE x, VALUE y)
-{
-    return nurat_s_canonicalize_internal(rb_cRational, x, y);
-}
-
-static VALUE nurat_s_convert(VALUE klass, SEL sel, int argc, VALUE *argv);
-
-VALUE
-rb_Rational(VALUE x, VALUE y)
-{
-    VALUE a[2];
-    a[0] = x;
-    a[1] = y;
-    return nurat_s_convert(rb_cRational, NULL, 2, a);
-}
-
-#define id_numerator rb_intern("numerator")
-#define f_numerator(x) rb_funcall(x, id_numerator, 0)
-
-#define id_denominator rb_intern("denominator")
-#define f_denominator(x) rb_funcall(x, id_denominator, 0)
-
-#define id_to_r rb_intern("to_r")
-#define f_to_r(x) rb_funcall(x, id_to_r, 0)
-
-/*
- * call-seq:
- *    num.numerator  ->  integer
- *
- * Returns the numerator.
- */
-static VALUE
-numeric_numerator(VALUE self, SEL sel)
-{
-    return f_numerator(f_to_r(self));
-}
-
-/*
- * call-seq:
- *    num.denominator  ->  integer
- *
- * Returns the denominator (always positive).
- */
-static VALUE
-numeric_denominator(VALUE self, SEL sel)
-{
-    return f_denominator(f_to_r(self));
-}
-
-/*
- * call-seq:
- *    int.numerator  ->  self
- *
- * Returns self.
- */
-static VALUE
-integer_numerator(VALUE self, SEL sel)
-{
-    return self;
-}
-
-/*
- * call-seq:
- *    int.denominator  ->  1
- *
- * Returns 1.
- */
-static VALUE
-integer_denominator(VALUE self, SEL sel)
-{
-    return INT2FIX(1);
-}
-
-/*
- * call-seq:
- *    flo.numerator  ->  integer
- *
- * Returns the numerator.  The result is machine dependent.
- *
- * For example:
- *
- *    n = 0.3.numerator    #=> 5404319552844595
- *    d = 0.3.denominator  #=> 18014398509481984
- *    n.fdiv(d)            #=> 0.3
- */
-static VALUE
-float_numerator(VALUE self, SEL sel)
-{
-    double d = RFLOAT_VALUE(self);
-    if (isinf(d) || isnan(d)) {
-	return self;
-    }
-    return rb_vm_call_super(self, sel, 0, 0);
-}
-
-/*
- * call-seq:
- *    flo.denominator  ->  integer
- *
- * Returns the denominator (always positive).  The result is machine
- * dependent.
- *
- * See numerator.
- */
-static VALUE
-float_denominator(VALUE self, SEL sel)
-{
-    double d = RFLOAT_VALUE(self);
-    if (isinf(d) || isnan(d)) {
-	return INT2FIX(1);
-    }
-    return rb_vm_call_super(self, sel, 0, 0);
-//    return ZERO;
-//    return rb_call_super(0, 0);
-}
-
-/*
- * call-seq:
- *    nil.to_r  ->  (0/1)
- *
- * Returns zero as a rational.
- */
-static VALUE
-nilclass_to_r(VALUE self, SEL sel)
-{
-    return rb_rational_new1(INT2FIX(0));
-}
-
-/*
- * call-seq:
- *    nil.rationalize([eps])  ->  (0/1)
- *
- * Returns zero as a rational.  An optional argument eps is always
- * ignored.
- */
-static VALUE
-nilclass_rationalize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    rb_scan_args(argc, argv, "01", NULL);
-    return nilclass_to_r(self, sel);
-}
-
-/*
- * call-seq:
- *    int.to_r  ->  rational
- *
- * Returns the value as a rational.
- *
- * For example:
- *
- *    1.to_r        #=> (1/1)
- *    (1<<64).to_r  #=> (18446744073709551616/1)
- */
-static VALUE
-integer_to_r(VALUE self, SEL sel)
-{
-    return rb_rational_new1(self);
-}
-
-/*
- * call-seq:
- *    int.rationalize([eps])  ->  rational
- *
- * Returns the value as a rational.  An optional argument eps is
- * always ignored.
- */
-static VALUE
-integer_rationalize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    rb_scan_args(argc, argv, "01", NULL);
-    return integer_to_r(self, sel);
-}
-
-static void
-float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
-{
-    double f;
-    int n;
-
-    f = frexp(RFLOAT_VALUE(self), &n);
-    f = ldexp(f, DBL_MANT_DIG);
-    n -= DBL_MANT_DIG;
-    *rf = rb_dbl2big(f);
-    *rn = INT2FIX(n);
-}
-
-#if 0
-static VALUE
-float_decode(VALUE self)
-{
-    VALUE f, n;
-
-    float_decode_internal(self, &f, &n);
-    return rb_assoc_new(f, n);
-}
-#endif
-
-#define id_lshift rb_intern("<<")
-#define f_lshift(x,n) rb_funcall(x, id_lshift, 1, n)
-
-/*
- * call-seq:
- *    flt.to_r  ->  rational
- *
- * Returns the value as a rational.
- *
- * NOTE: 0.3.to_r isn't the same as '0.3'.to_r.  The latter is
- * equivalent to '3/10'.to_r, but the former isn't so.
- *
- * For example:
- *
- *    2.0.to_r    #=> (2/1)
- *    2.5.to_r    #=> (5/2)
- *    -0.75.to_r  #=> (-3/4)
- *    0.0.to_r    #=> (0/1)
- */
-static VALUE
-float_to_r(VALUE self, SEL sel)
-{
-    VALUE f, n;
-
-    float_decode_internal(self, &f, &n);
-#if FLT_RADIX == 2
-    {
-	long ln = FIX2LONG(n);
-
-	if (ln == 0)
-	    return f_to_r(f);
-	if (ln > 0)
-	    return f_to_r(f_lshift(f, n));
-	ln = -ln;
-	return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
-    }
-#else
-    return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
-#endif
-}
-
-/*
- * call-seq:
- *    flt.rationalize([eps])  ->  rational
- *
- * Returns a simpler approximation of the value (flt-|eps| <= result
- * <= flt+|eps|).  if eps is not given, it will be chosen
- * automatically.
- *
- * For example:
- *
- *    0.3.rationalize          #=> (3/10)
- *    1.333.rationalize        #=> (1333/1000)
- *    1.333.rationalize(0.01)  #=> (4/3)
- */
-static VALUE
-float_rationalize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE e, a, b, p, q;
-
-    if (f_negative_p(self))
-	return f_negate(float_rationalize(f_abs(self), sel, argc, argv));
-
-    rb_scan_args(argc, argv, "01", &e);
-
-    if (argc != 0) {
-	e = f_abs(e);
-	a = f_sub(self, e);
-	b = f_add(self, e);
-    }
-    else {
-	VALUE f, n;
-
-	float_decode_internal(self, &f, &n);
-	if (f_zero_p(f) || f_positive_p(n))
-	    return rb_rational_new1(f_lshift(f, n));
-
-#if FLT_RADIX == 2
-	a = rb_rational_new2(f_sub(f_mul(TWO, f), ONE),
-			     f_lshift(ONE, f_sub(ONE, n)));
-	b = rb_rational_new2(f_add(f_mul(TWO, f), ONE),
-			     f_lshift(ONE, f_sub(ONE, n)));
-#else
-	a = rb_rational_new2(f_sub(f_mul(INT2FIX(FLT_RADIX), f),
-				   INT2FIX(FLT_RADIX - 1)),
-			     f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)));
-	b = rb_rational_new2(f_add(f_mul(INT2FIX(FLT_RADIX), f),
-				   INT2FIX(FLT_RADIX - 1)),
-			     f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)));
-#endif
-    }
-
-    if (f_eqeq_p(a, b))
-	return f_to_r(self);
-
-    nurat_rationalize_internal(a, b, &p, &q);
-    return rb_rational_new2(p, q);
-}
-
-static VALUE rat_pat, an_e_pat, a_dot_pat, underscores_pat, an_underscore;
-
-#define WS "\\s*"
-#define DIGITS "(?:[0-9](?:_[0-9]|[0-9])*)"
-#define NUMERATOR "(?:" DIGITS "?\\.)?" DIGITS "(?:[eE][-+]?" DIGITS ")?"
-#define DENOMINATOR DIGITS
-#define PATTERN "\\A" WS "([-+])?(" NUMERATOR ")(?:\\/(" DENOMINATOR "))?" WS
-
-static void
-make_patterns(void)
-{
-    static const char rat_pat_source[] = PATTERN;
-    static const char an_e_pat_source[] = "[eE]";
-    static const char a_dot_pat_source[] = "\\.";
-    static const char underscores_pat_source[] = "_+";
-
-    if (rat_pat) return;
-
-    rat_pat = rb_reg_new(rat_pat_source, sizeof rat_pat_source - 1, 0);
-    GC_RETAIN(rat_pat);
-
-    an_e_pat = rb_reg_new(an_e_pat_source, sizeof an_e_pat_source - 1, 0);
-    GC_RETAIN(an_e_pat);
-
-    a_dot_pat = rb_reg_new(a_dot_pat_source, sizeof a_dot_pat_source - 1, 0);
-    GC_RETAIN(a_dot_pat);
-
-    underscores_pat = rb_reg_new(underscores_pat_source,
-	    sizeof underscores_pat_source - 1, 0);
-    GC_RETAIN(underscores_pat);
-
-    an_underscore = rb_usascii_str_new2("_");
-    GC_RETAIN(an_underscore);
-}
-
-#define id_match rb_intern("match")
-#define f_match(x,y) rb_funcall(x, id_match, 1, y)
-
-#define id_aref rb_intern("[]")
-#define f_aref(x,y) rb_funcall(x, id_aref, 1, y)
-
-#define id_post_match rb_intern("post_match")
-#define f_post_match(x) rb_funcall(x, id_post_match, 0)
-
-#define id_split rb_intern("split")
-#define f_split(x,y) rb_funcall(x, id_split, 1, y)
-
-#define id_strip rb_intern("strip")
-#define f_strip(x) rb_funcall(x, id_strip, 0)
-
-#include <ctype.h>
-
-static VALUE
-string_to_r_internal(VALUE self)
-{
-    VALUE s, m;
-
-    s = self;
-
-    if (RSTRING_LEN(s) == 0)
-	return rb_assoc_new(Qnil, self);
-
-    m = f_match(rat_pat, s);
-
-    if (!NIL_P(m)) {
-	VALUE v, ifp, exp, ip, fp;
-	VALUE si = f_aref(m, INT2FIX(1));
-	VALUE nu = f_aref(m, INT2FIX(2));
-	VALUE de = f_aref(m, INT2FIX(3));
-	VALUE re = f_post_match(m);
-
-	{
-	    VALUE a;
-
-	    a = f_split(nu, an_e_pat);
-	    ifp = RARRAY_PTR(a)[0];
-	    if (RARRAY_LEN(a) != 2)
-		exp = Qnil;
-	    else
-		exp = RARRAY_PTR(a)[1];
-
-	    a = f_split(ifp, a_dot_pat);
-	    ip = RARRAY_PTR(a)[0];
-	    if (RARRAY_LEN(a) != 2)
-		fp = Qnil;
-	    else
-		fp = RARRAY_PTR(a)[1];
-	}
-
-	v = rb_rational_new1(f_to_i(ip));
-
-	if (!NIL_P(fp)) {
-	    char *p = StringValuePtr(fp);
-	    long count = 0;
-	    VALUE l;
-
-	    while (*p) {
-		if (rb_isdigit(*p))
-		    count++;
-		p++;
-	    }
-
-	    l = f_expt(INT2FIX(10), LONG2NUM(count));
-	    v = f_mul(v, l);
-	    v = f_add(v, f_to_i(fp));
-	    v = f_div(v, l);
-	}
-	if (!NIL_P(si) && *StringValuePtr(si) == '-')
-	    v = f_negate(v);
-	if (!NIL_P(exp))
-	    v = f_mul(v, f_expt(INT2FIX(10), f_to_i(exp)));
-#if 0
-	if (!NIL_P(de) && (!NIL_P(fp) || !NIL_P(exp)))
-	    return rb_assoc_new(v, rb_usascii_str_new2("dummy"));
-#endif
-	if (!NIL_P(de))
-	    v = f_div(v, f_to_i(de));
-
-	return rb_assoc_new(v, re);
-    }
-    return rb_assoc_new(Qnil, self);
-}
-
-static VALUE
-string_to_r_strict(VALUE self)
-{
-    VALUE a = string_to_r_internal(self);
-    if (NIL_P(RARRAY_PTR(a)[0]) || RSTRING_LEN(RARRAY_PTR(a)[1]) > 0) {
-	VALUE s = f_inspect(self);
-	rb_raise(rb_eArgError, "invalid value for convert(): %s",
-		 StringValuePtr(s));
-    }
-    return RARRAY_PTR(a)[0];
-}
-
-#define id_gsub rb_intern("gsub")
-#define f_gsub(x,y,z) rb_funcall(x, id_gsub, 2, y, z)
-
-/*
- * call-seq:
- *    str.to_r  ->  rational
- *
- * Returns a rational which denotes the string form.  The parser
- * ignores leading whitespaces and trailing garbage.  Any digit
- * sequences can be separeted by an underscore.  Returns zero for null
- * or garbage string.
- *
- * NOTE: '0.3'.to_r isn't the same as 0.3.to_r.  The former is
- * equivalent to '3/10'.to_r, but the latter isn't so.
- *
- * For example:
- *
- *    '  2  '.to_r       #=> (2/1)
- *    '300/2'.to_r       #=> (150/1)
- *    '-9.2'.to_r        #=> (-46/5)
- *    '-9.2e2'.to_r      #=> (-920/1)
- *    '1_234_567'.to_r   #=> (1234567/1)
- *    '21 june 09'.to_r  #=> (21/1)
- *    '21/06/09'.to_r    #=> (7/2)
- *    'bwv 1079'.to_r    #=> (0/1)
- */
-static VALUE
-string_to_r(VALUE self, SEL sel)
-{
-    VALUE s, a, backref;
-
-    backref = rb_backref_get();
-    rb_match_busy(backref);
-
-    s = f_gsub(self, underscores_pat, an_underscore);
-    a = string_to_r_internal(s);
-
-    rb_backref_set(backref);
-
-    if (!NIL_P(RARRAY_PTR(a)[0]))
-	return RARRAY_PTR(a)[0];
-    return rb_rational_new1(INT2FIX(0));
-}
-
-#define id_to_r rb_intern("to_r")
-#define f_to_r(x) rb_funcall(x, id_to_r, 0)
-
-static VALUE
-nurat_s_convert(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE a1, a2, backref;
-
-    rb_scan_args(argc, argv, "11", &a1, &a2);
-
-    if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
-	rb_raise(rb_eTypeError, "can't convert nil into Rational");
-
-    switch (TYPE(a1)) {
-      case T_COMPLEX:
-	if (k_exact_zero_p(RCOMPLEX(a1)->imag))
-	    a1 = RCOMPLEX(a1)->real;
-    }
-
-    switch (TYPE(a2)) {
-      case T_COMPLEX:
-	if (k_exact_zero_p(RCOMPLEX(a2)->imag))
-	    a2 = RCOMPLEX(a2)->real;
-    }
-
-    backref = rb_backref_get();
-    rb_match_busy(backref);
-
-    switch (TYPE(a1)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	break;
-      case T_FLOAT:
-	a1 = f_to_r(a1);
-	break;
-      case T_STRING:
-	a1 = string_to_r_strict(a1);
-	break;
-    }
-
-    switch (TYPE(a2)) {
-      case T_FIXNUM:
-      case T_BIGNUM:
-	break;
-      case T_FLOAT:
-	a2 = f_to_r(a2);
-	break;
-      case T_STRING:
-	a2 = string_to_r_strict(a2);
-	break;
-    }
-
-    rb_backref_set(backref);
-
-    switch (TYPE(a1)) {
-      case T_RATIONAL:
-	if (argc == 1 || (k_exact_one_p(a2)))
-	    return a1;
-    }
-
-    if (argc == 1) {
-	if (!(k_numeric_p(a1) && k_integer_p(a1)))
-	    return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
-    }
-    else {
-	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
-	    (!f_integer_p(a1) || !f_integer_p(a2)))
-	    return f_div(a1, a2);
-    }
-
-    {
-	VALUE argv2[2];
-	argv2[0] = a1;
-	argv2[1] = a2;
-	return nurat_s_new(argc, argv2, klass);
-    }
-}
-
-/*
- * A rational number can be represented as a paired integer number;
- * a/b (b>0).  Where a is numerator and b is denominator.  Integer a
- * equals rational a/1 mathematically.
- *
- * In ruby, you can create rational object with Rational or to_r
- * method.  The return values will be irreducible.
- *
- *    Rational(1)      #=> (1/1)
- *    Rational(2, 3)   #=> (2/3)
- *    Rational(4, -6)  #=> (-2/3)
- *    3.to_r           #=> (3/1)
- *
- * You can also create ratioanl object from floating-point numbers or
- * strings.
- *
- *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
- *    Rational('0.3')  #=> (3/10)
- *    Rational('2/3')  #=> (2/3)
- *
- *    0.3.to_r         #=> (5404319552844595/18014398509481984)
- *    '0.3'.to_r       #=> (3/10)
- *    '2/3'.to_r       #=> (2/3)
- *
- * A rational object is an exact number, which helps you to write
- * program without any rounding errors.
- *
- *    10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
- *    10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)
- *
- * However, when an expression has inexact factor (numerical value or
- * operation), will produce an inexact result.
- *
- *    Rational(10) / 3   #=> (10/3)
- *    Rational(10) / 3.0 #=> 3.3333333333333335
- *
- *    Rational(-8) ** Rational(1, 3)
- *                       #=> (1.0000000000000002+1.7320508075688772i)
- */
-void
-Init_Rational(void)
-{
-    assert(fprintf(stderr, "assert() is now active\n"));
-
-    id_abs = rb_intern("abs");
-    id_cmp = rb_intern("<=>");
-    id_convert = rb_intern("convert");
-    id_eqeq_p = rb_intern("==");
-    id_expt = rb_intern("**");
-    id_fdiv = rb_intern("fdiv");
-    id_floor = rb_intern("floor");
-    id_idiv = rb_intern("div");
-    id_inspect = rb_intern("inspect");
-    id_integer_p = rb_intern("integer?");
-    id_negate = rb_intern("-@");
-    id_to_f = rb_intern("to_f");
-    id_to_i = rb_intern("to_i");
-    id_to_s = rb_intern("to_s");
-    id_truncate = rb_intern("truncate");
-
-    rb_cRational = rb_define_class("Rational", rb_cNumeric);
-
-    rb_objc_define_method(rb_cRational, "alloc", nurat_s_alloc, 0);
-    rb_undef_method(CLASS_OF(rb_cRational), "allocate");
-
-#if 0
-    rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
-    rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
-#else
-    rb_undef_method(CLASS_OF(rb_cRational), "new");
-#endif
-
-    rb_objc_define_method(rb_mKernel, "Rational", nurat_f_rational, -1);
-
-    rb_objc_define_method(rb_cRational, "numerator", nurat_numerator, 0);
-    rb_objc_define_method(rb_cRational, "denominator", nurat_denominator, 0);
-
-    rb_objc_define_method(rb_cRational, "+", nurat_add, 1);
-    rb_objc_define_method(rb_cRational, "-", nurat_sub, 1);
-    rb_objc_define_method(rb_cRational, "*", nurat_mul, 1);
-    rb_objc_define_method(rb_cRational, "/", nurat_div, 1);
-    rb_objc_define_method(rb_cRational, "quo", nurat_div, 1);
-    rb_objc_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
-    rb_objc_define_method(rb_cRational, "**", nurat_expt, 1);
-
-    rb_objc_define_method(rb_cRational, "<=>", nurat_cmp, 1);
-    rb_objc_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
-    rb_objc_define_method(rb_cRational, "coerce", nurat_coerce, 1);
-
-#if 0 /* NUBY */
-    rb_define_method(rb_cRational, "//", nurat_idiv, 1);
-#endif
-
-#if 0
-    rb_define_method(rb_cRational, "quot", nurat_quot, 1);
-    rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
-#endif
-
-#if 0
-    rb_define_method(rb_cRational, "rational?", nurat_true, 0);
-    rb_define_method(rb_cRational, "exact?", nurat_true, 0);
-#endif
-
-    rb_objc_define_method(rb_cRational, "floor", nurat_floor_n, -1);
-    rb_objc_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
-    rb_objc_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
-    rb_objc_define_method(rb_cRational, "round", nurat_round_n, -1);
-
-    rb_objc_define_method(rb_cRational, "to_i", nurat_truncate, 0);
-    rb_objc_define_method(rb_cRational, "to_f", nurat_to_f, 0);
-    rb_objc_define_method(rb_cRational, "to_r", nurat_to_r, 0);
-    rb_objc_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
-
-    rb_objc_define_method(rb_cRational, "hash", nurat_hash, 0);
-
-    rb_objc_define_method(rb_cRational, "to_s", nurat_to_s, 0);
-    rb_objc_define_method(rb_cRational, "inspect", nurat_inspect, 0);
-
-    rb_objc_define_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
-    rb_objc_define_method(rb_cRational, "marshal_load", nurat_marshal_load, 1);
-
-    /* --- */
-
-    rb_objc_define_method(rb_cInteger, "gcd", rb_gcd, 1);
-    rb_objc_define_method(rb_cInteger, "lcm", rb_lcm, 1);
-    rb_objc_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
-
-    rb_objc_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
-    rb_objc_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
-
-    rb_objc_define_method(rb_cInteger, "numerator", integer_numerator, 0);
-    rb_objc_define_method(rb_cInteger, "denominator", integer_denominator, 0);
-
-    rb_objc_define_method(rb_cFloat, "numerator", float_numerator, 0);
-    rb_objc_define_method(rb_cFloat, "denominator", float_denominator, 0);
-
-    rb_objc_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
-    rb_objc_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
-    rb_objc_define_method(rb_cInteger, "to_r", integer_to_r, 0);
-    rb_objc_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
-    rb_objc_define_method(rb_cFloat, "to_r", float_to_r, 0);
-    rb_objc_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
-
-    make_patterns();
-
-    rb_objc_define_method(rb_cString, "to_r", string_to_r, 0);
-
-    rb_objc_define_method(*(VALUE *)rb_cRational, "convert", nurat_s_convert, -1);
-//    rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
-    // TODO: insert NSNumber primitives
-}
-
-/*
-Local variables:
-c-file-style: "ruby"
-End:
-*/

Deleted: MacRuby/trunk/re.c
===================================================================
--- MacRuby/trunk/re.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/re.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2210 +0,0 @@
-/* 
- * MacRuby Regular Expressions.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "unicode/uregex.h"
-#include "unicode/ustring.h"
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "objc.h"
-#include "class.h"
-#include "re.h"
-
-VALUE rb_eRegexpError;
-VALUE rb_cRegexp;
-VALUE rb_cMatch;
-
-static VALUE rb_cRegexpMatcher;
-
-typedef struct rb_regexp {
-    struct RBasic basic;
-    URegularExpression *pattern;
-    bool fixed_encoding;
-} rb_regexp_t;
-
-#define RREGEXP(o) ((rb_regexp_t *)o)
-
-#define REGEXP_OPT_DEFAULT	(UREGEX_MULTILINE)
-#define REGEXP_OPT_IGNORECASE 	(UREGEX_CASE_INSENSITIVE)
-#define REGEXP_OPT_EXTENDED 	(UREGEX_COMMENTS)
-#define REGEXP_OPT_MULTILINE	(UREGEX_DOTALL)
-
-typedef struct rb_match {
-    struct RBasic basic;
-    rb_regexp_t *regexp;
-    VALUE str;
-    rb_match_result_t *results;
-    int results_count;
-    bool busy;
-} rb_match_t;
-
-#define RMATCH(o) ((rb_match_t *)o)
-
-static rb_regexp_t *
-regexp_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(re, struct rb_regexp);
-    OBJSETUP(re, klass, T_REGEXP);
-    re->pattern = NULL;
-    re->fixed_encoding = false;
-    return re;
-}
-
-static rb_match_t *
-match_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(match, struct rb_match);
-    OBJSETUP(match, klass, T_MATCH);
-    match->regexp = NULL;
-    match->str = 0;
-    match->results = NULL;
-    match->results_count = 0;
-    match->busy = false;
-    return match;
-}
-
-static void
-regexp_finalize(rb_regexp_t *regexp)
-{
-    if (regexp->pattern != NULL) {
-	uregex_close(regexp->pattern);
-	regexp->pattern = NULL;
-    }
-}
-
-static IMP regexp_finalize_imp_super = NULL; 
-
-static void
-regexp_finalize_imp(void *rcv, SEL sel)
-{
-    regexp_finalize(RREGEXP(rcv));
-    if (regexp_finalize_imp_super != NULL) {
-	((void(*)(void *, SEL))regexp_finalize_imp_super)(rcv, sel);
-    }
-}
-
-// Work around ICU limitations.
-static void
-sanitize_regexp_string(UChar **chars_p, long *chars_len_p)
-{
-    UChar *chars = *chars_p;
-    long chars_len = *chars_len_p;
-
-#define copy_if_needed() \
-    do { \
-	UChar *tmp = (UChar *)xmalloc(sizeof(UChar) * chars_len); \
-	memcpy(tmp, chars, sizeof(UChar) * chars_len); \
-	chars = tmp; \
-    } \
-    while (0)
-
-    // Replace all occurences [[:word:]] by \w.
-    UChar word_chars[10] = {'[', '[', ':', 'w', 'o', 'r', 'd', ':', ']', ']'};
-    size_t pos = 0;
-    while (true) {
-	UChar *p = u_strFindFirst(chars + pos, chars_len - pos, word_chars, 10);
-	if (p == NULL) {
-	    break;
-	}
-	pos = p - chars;
-	copy_if_needed();
-	chars[pos] = '\\';
-	chars[pos + 1] = 'w';
-	memmove(&chars[pos + 2], &chars[pos + 10],
-		sizeof(UChar) * (chars_len - (pos + 8)));
-	chars_len -= 8;
-    }
-
-    // Replace all occurences of \n (where n is a number < 1 or > 9) by the
-    // number value.
-    UChar backslash_chars[] = {'\\'};
-    char buf[11];
-    pos = 0;
-    while (true) {
-	UChar *p = u_strFindFirst(chars + pos, chars_len - pos,
-		backslash_chars, 1);
-	if (p == NULL) {
-	    break;
-	}
-	pos = p - chars;
-	copy_if_needed();
-
-	int n = 0;
-	while (true) {
-	    const int i = pos + n + 1;
-	    if (i >= chars_len) {
-		break;
-	    }
-	    UChar c = chars[i];
-	    if (c >= '0' && c <= '9') {
-		assert(n < 10);
-		buf[n++] = (char)c;
-	    }
-	    else {
-		break;
-	    }
-	}
-
-	if (n > 0) {
-	    buf[n] = '\0';
-	    const int l = atoi(buf);
-	    if (l < 1 || l > 9) {
-		chars[pos] = (UChar)l;
-		memmove(&chars[pos + 1], &chars[pos + n + 1],
-			sizeof(UChar) * (chars_len - (pos + n + 1)));
-		chars_len -= n;
-		pos = 0;
-		continue;
-	    }
-	    // A backreference (\1 .. \9).
-	}
-	pos++;
-    }
-
-#undef copy_if_needed
-
-#if 0
-printf("out:\n");
-for (int i = 0; i < chars_len; i++) {
-printf("%c", chars[i]);
-}
-printf("\n");
-#endif
-
-    *chars_p = chars;
-    *chars_len_p = chars_len;
-}
-
-static bool
-init_from_string(rb_regexp_t *regexp, VALUE str, int option, VALUE *excp)
-{
-    option |= REGEXP_OPT_DEFAULT;
-
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    UChar null_char = '\0';
-    if (chars_len == 0) {
-	// uregex_open() will complain if we pass a NULL pattern or a
-	// pattern length of 0, so we do pass an empty pattern with a length
-	// of -1 which indicates it's terminated by \0.
-	chars = &null_char;
-	chars_len = -1;
-    }
-    else {
-	sanitize_regexp_string(&chars, &chars_len);
-    }
-
-    UParseError pe;
-    UErrorCode status = U_ZERO_ERROR;
-    URegularExpression *pattern = uregex_open(chars, chars_len, option,
-	    &pe, &status);
-
-    if (pattern == NULL) {
-	if (excp != NULL) {
-	    char error[1024];
-	    snprintf(error, sizeof error, "regexp `%s' compilation error: %s",
-		    RSTRING_PTR(str),
-		    u_errorName(status));
-	    *excp = rb_exc_new2(rb_eRegexpError, error);
-	}
-	return false;
-    }
-
-    bool fixed_encoding = false;
-    if (IS_RSTR(str) && !str_is_ruby_ascii_only(RSTR(str))) {
-	fixed_encoding = true;
-    }
-
-    regexp_finalize(regexp);
-    regexp->pattern = pattern;
-    regexp->fixed_encoding = fixed_encoding;
-
-    return true;
-}
-
-static void
-init_from_regexp(rb_regexp_t *regexp, rb_regexp_t *from)
-{
-    regexp_finalize(regexp);
-
-    UErrorCode status = U_ZERO_ERROR;
-    regexp->pattern = uregex_clone(from->pattern, &status);
-    if (regexp->pattern == NULL) {
-	rb_raise(rb_eRegexpError, "can't clone given regexp: %s",
-		u_errorName(status));
-    }
-}
-
-static VALUE
-rb_str_compile_regexp(VALUE str, int options, VALUE *excp)
-{
-    rb_regexp_t *regexp = regexp_alloc(rb_cRegexp, 0);
-    if (!init_from_string(regexp, str, options, excp)) {
-	return Qnil;
-    }
-    return (VALUE)regexp;
-}
-
-bool
-rb_char_to_icu_option(int c, int *option)
-{
-    assert(option != NULL);
-    switch (c) {
-	case 'i':
-	    *option = REGEXP_OPT_IGNORECASE;
-	    return true;
-	case 'x':
-	    *option = REGEXP_OPT_EXTENDED;
-	    return true;
-	case 'm':
-	    *option = REGEXP_OPT_MULTILINE;
-	    return true;
-
-	// Stupid MRI encoding flags, let's ignore them for now.
-	case 'n':
-	case 'e':
-	case 'u':
-	case 's':
-	    *option = 0;
-	    return true;
-    }
-    *option = -1;
-    return false;
-}
-
-static VALUE
-reg_operand(VALUE s, bool check)
-{
-    if (SYMBOL_P(s)) {
-	return rb_sym_to_s(s);
-    }
-    else {
-	VALUE tmp = rb_check_string_type(s);
-	if (check && NIL_P(tmp)) {
-	    rb_raise(rb_eTypeError, "can't convert %s to String",
-		     rb_obj_classname(s));
-	}
-	return tmp;
-    }
-}
-
-static VALUE
-rb_check_regexp_type(VALUE re)
-{
-    return rb_check_convert_type(re, T_REGEXP, "Regexp", "to_regexp");
-}
-
-/*
- *  call-seq:
- *     Regexp.escape(str)   => string
- *     Regexp.quote(str)    => string
- *
- *  Escapes any characters that would have special meaning in a regular
- *  expression. Returns a new escaped string, or self if no characters are
- *  escaped.  For any string,
- *  <code>Regexp.new(Regexp.escape(<i>str</i>))=~<i>str</i></code> will be true.
- *
- *     Regexp.escape('\*?{}.')   #=> \\\*\?\{\}\.
- *
- */
-
-static VALUE
-regexp_quote(VALUE klass, SEL sel, VALUE pat)
-{
-    return rb_reg_quote(reg_operand(pat, true));
-}
-
-/*
- *  call-seq:
- *     Regexp.union(pat1, pat2, ...)            => new_regexp
- *     Regexp.union(pats_ary)                   => new_regexp
- *
- *  Return a <code>Regexp</code> object that is the union of the given
- *  <em>pattern</em>s, i.e., will match any of its parts. The <em>pattern</em>s
- *  can be Regexp objects, in which case their options will be preserved, or
- *  Strings. If no patterns are given, returns <code>/(?!)/</code>.
- *
- *     Regexp.union                         #=> /(?!)/
- *     Regexp.union("penzance")             #=> /penzance/
- *     Regexp.union("a+b*c")                #=> /a\+b\*c/
- *     Regexp.union("skiing", "sledding")   #=> /skiing|sledding/
- *     Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
- *     Regexp.union(/dogs/, /cats/i)        #=> /(?-mix:dogs)|(?i-mx:cats)/
- */
-
-static VALUE regexp_to_s(VALUE rcv, SEL sel);
-
-static VALUE
-regexp_union(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    const VALUE *args;
-
-    if (argc == 0) {
-	return rb_reg_new_str(rb_str_new2("(?!)"), 0);
-    }
-    else if (argc == 1) {
-	VALUE v = rb_check_regexp_type(argv[0]);
-	if (!NIL_P(v)) {
-	    return v;
-	}
-	v = rb_check_array_type(argv[0]);
-	if (!NIL_P(v)) {
-	    argc = RARRAY_LEN(argv[0]);
-	    args = RARRAY_PTR(argv[0]);
-	}
-	else {
-	    StringValue(argv[0]);
-	    return rb_reg_new_str(rb_reg_quote(argv[0]), 0);
-	}
-    }
-    else {
-	args = argv;
-    }
-
-    VALUE source = rb_unicode_str_new(NULL, 0);
-
-    for (int i = 0; i < argc; i++) {
-	VALUE arg = args[i];
-
-	if (i > 0) {
-	    rb_str_cat2(source, "|");
-	}
-
-	VALUE substr;
-	VALUE re = rb_check_regexp_type(arg);
-	if (!NIL_P(re)) {
-	    substr = regexp_to_s(re, 0);
-	}
-	else {
-	    StringValue(arg);
-	    substr = rb_reg_quote(arg);
-	}
-
-	rb_str_append(source, substr);
-    }
-
-    return rb_reg_new_str(source, 0);
-}
-
-/*
- *  call-seq:
- *     Regexp.last_match           => matchdata
- *     Regexp.last_match(n)        => str
- *
- *  The first form returns the <code>MatchData</code> object generated by the
- *  last successful pattern match. Equivalent to reading the global variable
- *  <code>$~</code>. The second form returns the <i>n</i>th field in this
- *  <code>MatchData</code> object.
- *  <em>n</em> can be a string or symbol to reference a named capture.
- *
- *     /c(.)t/ =~ 'cat'        #=> 0
- *     Regexp.last_match       #=> #<MatchData "cat" 1:"a">
- *     Regexp.last_match(0)    #=> "cat"
- *     Regexp.last_match(1)    #=> "a"
- *     Regexp.last_match(2)    #=> nil
- *
- *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "var = val"
- *     Regexp.last_match       #=> #<MatchData "var = val" lhs:"var" rhs:"val">
- *     Regexp.last_match(:lhs) #=> "var"
- *     Regexp.last_match(:rhs) #=> "val"
- */
-
-static VALUE match_getter(void);
-static int match_backref_number(VALUE match, VALUE backref, bool check);
-
-static VALUE
-regexp_last_match(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE nth;
-
-    if (argc > 0 && rb_scan_args(argc, argv, "01", &nth) == 1) {
-	VALUE match = rb_backref_get();
-	if (NIL_P(match)) {
-	    return Qnil;
-	}
-	const int n = match_backref_number(match, nth, true);
-	return rb_reg_nth_match(n, match);
-    }
-    return match_getter();
-}
-
-/*
- *  call-seq:
- *     Regexp.try_convert(obj) -> re or nil
- *
- *  Try to convert <i>obj</i> into a Regexp, using to_regexp method.
- *  Returns converted regexp or nil if <i>obj</i> cannot be converted
- *  for any reason.
- *
- *     Regexp.try_convert(/re/)         #=> /re/
- *     Regexp.try_convert("re")         #=> nil
- *
- *     o = Object.new
- *     Regexp.try_convert(o)            #=> nil
- *     def o.to_regexp() /foo/ end
- *     Regexp.try_convert(o)            #=> /foo/
- *
- */
-
-static VALUE
-regexp_try_convert(VALUE klass, SEL sel, VALUE obj)
-{
-    return rb_check_regexp_type(obj);
-}
-
-/*
- *  call-seq:
- *     Regexp.new(string [, options])                => regexp
- *     Regexp.new(regexp)                            => regexp
- *     Regexp.compile(string [, options])            => regexp
- *     Regexp.compile(regexp)                        => regexp
- *
- *  Constructs a new regular expression from <i>pattern</i>, which can be either
- *  a <code>String</code> or a <code>Regexp</code> (in which case that regexp's
- *  options are propagated, and new options may not be specified (a change as of
- *  Ruby 1.8). If <i>options</i> is a <code>Fixnum</code>, it should be one or
- *  more of the constants <code>Regexp::EXTENDED</code>,
- *  <code>Regexp::IGNORECASE</code>, and <code>Regexp::MULTILINE</code>,
- *  <em>or</em>-ed together. Otherwise, if <i>options</i> is not
- *  <code>nil</code>, the regexp will be case insensitive.
- *
- *     r1 = Regexp.new('^a-z+:\\s+\w+')           #=> /^a-z+:\s+\w+/
- *     r2 = Regexp.new('cat', true)               #=> /cat/i
- *     r3 = Regexp.new('dog', Regexp::EXTENDED)   #=> /dog/x
- *     r4 = Regexp.new(r2)                        #=> /cat/i
- */
-
-static VALUE
-regexp_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 0 || argc > 3) {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-    if (TYPE(argv[0]) == T_REGEXP) {
-	VALUE re = argv[0];
-	if (argc > 1) {
-	    rb_warn("flags ignored");
-	}
-	assert(RREGEXP(re)->pattern != NULL);
-	init_from_regexp(RREGEXP(self), RREGEXP(re));
-    }
-    else {
-	int options = 0;
-	if (argc >= 2) {
-	    if (FIXNUM_P(argv[1])) {
-		options = FIX2INT(argv[1]);
-	    }
-	    else if (RTEST(argv[1])) {
-		options = REGEXP_OPT_IGNORECASE;
-	    }
-	}
-	VALUE str = argv[0];
-	StringValue(str);
-
-	VALUE exc = Qnil;
-	if (!init_from_string(RREGEXP(self), str, options, &exc)) {
-	    rb_exc_raise(exc);
-	}
-    }
-    return self;
-}
-
-static VALUE
-regexp_initialize_copy(VALUE rcv, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_REGEXP) {
-	rb_raise(rb_eTypeError, "wrong argument type");
-    }
-    init_from_regexp(RREGEXP(rcv), RREGEXP(other));
-    return rcv;
-}
-
-/*
- * call-seq:
- *   rxp.hash   => fixnum
- *
- * Produce a hash based on the text and options of this regular expression.
- */
-
-static void
-regexp_get_pattern(URegularExpression *pat, const UChar **chars,
-	int32_t *chars_len)
-{
-    assert(pat != NULL);
-
-    UErrorCode status = U_ZERO_ERROR;
-    *chars = uregex_pattern(pat, chars_len, &status);
-    if (*chars == NULL) {
-	rb_raise(rb_eRegexpError, "can't retrieve regexp pattern: %s",
-		u_errorName(status));
-    }
-    if (*chars_len < 0) {
-	*chars_len = 0;
-    }
-}
-
-static VALUE
-regexp_hash(VALUE rcv, SEL sel)
-{
-    const UChar *chars = NULL;
-    int32_t chars_len = 0;
-    regexp_get_pattern(RREGEXP(rcv)->pattern, &chars, &chars_len);
-
-    unsigned long code = rb_str_hash_uchars(chars, chars_len);
-    code += rb_reg_options(rcv);
-    return LONG2NUM(code);
-}
-
-/*
- *  call-seq:
- *     rxp == other_rxp      => true or false
- *     rxp.eql?(other_rxp)   => true or false
- *
- *  Equality---Two regexps are equal if their patterns are identical, they have
- *  the same character set code, and their <code>casefold?</code> values are the
- *  same.
- *
- *     /abc/  == /abc/x   #=> false
- *     /abc/  == /abc/i   #=> false
- *     /abc/  == /abc/n   #=> false
- *     /abc/u == /abc/n   #=> false
- */
-
-static VALUE
-regexp_equal(VALUE rcv, SEL sel, VALUE other)
-{
-    if (rcv == other) {
-	return Qtrue;
-    }
-    if (TYPE(other) != T_REGEXP) {
-	return Qfalse;
-    }
-
-    assert(RREGEXP(rcv)->pattern != NULL);
-    assert(RREGEXP(other)->pattern != NULL);
-
-    UErrorCode status = U_ZERO_ERROR;
-
-    if (uregex_flags(RREGEXP(rcv)->pattern, &status)
-	    != uregex_flags(RREGEXP(other)->pattern, &status)) {
-	return Qfalse;
-    }
-
-    int32_t rcv_chars_len = 0;
-    const UChar *rcv_chars = NULL;
-    regexp_get_pattern(RREGEXP(rcv)->pattern, &rcv_chars, &rcv_chars_len);
-
-    int32_t other_chars_len = 0;
-    const UChar *other_chars = NULL;
-    regexp_get_pattern(RREGEXP(other)->pattern, &other_chars, &other_chars_len);
-
-    if (rcv_chars_len != other_chars_len) {
-	return Qfalse;
-    }
-    if (memcmp(rcv_chars, other_chars, sizeof(UChar) * rcv_chars_len) != 0) {
-	return Qfalse;
-    }
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *     rxp =~ str    => integer or nil
- *
- *  Match---Matches <i>rxp</i> against <i>str</i>.
- *
- *     /at/ =~ "input data"   #=> 7
- *     /ax/ =~ "input data"   #=> nil
- *
- *  If <code>=~</code> is used with a regexp literal with named captures,
- *  captured strings (or nil) is assigned to local variables named by
- *  the capture names.
- *
- *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = y  "
- *     p lhs    #=> "x"
- *     p rhs    #=> "y"
- *
- *  If it is not matched, nil is assigned for the variables.
- *
- *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = "   
- *     p lhs    #=> nil
- *     p rhs    #=> nil
- *
- *  This assignment is implemented in the Ruby parser.
- *  So a regexp literal is required for the assignment. 
- *  The assignment is not occur if the regexp is not a literal.
- *
- *     re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
- *     re =~ "  x = "
- *     p lhs    # undefined local variable
- *     p rhs    # undefined local variable
- *
- *  A regexp interpolation, <code>#{}</code>, also disables
- *  the assignment.
- *
- *     rhs_pat = /(?<rhs>\w+)/
- *     /(?<lhs>\w+)\s*=\s*#{rhs_pat}/ =~ "x = y"
- *     p lhs    # undefined local variable
- */
-
-typedef struct rb_regexp_matcher {
-    struct RBasic basic;
-    URegularExpression *pattern;
-    UChar *text_chars;
-    rb_encoding_t *encoding;
-    VALUE frozen_str;
-} rb_regexp_matcher_t;
-
-static void
-reg_matcher_cleanup(rb_regexp_matcher_t *m)
-{
-    if (m->pattern != NULL) {
-	uregex_close(m->pattern);
-	m->pattern = NULL;
-    }
-}
-
-static IMP regexp_matcher_finalize_imp_super = NULL; 
-
-static void
-regexp_matcher_finalize_imp(void *rcv, SEL sel)
-{
-    reg_matcher_cleanup((rb_regexp_matcher_t *)rcv);
-    if (regexp_matcher_finalize_imp_super != NULL) {
-	((void(*)(void *, SEL))regexp_matcher_finalize_imp_super)(rcv, sel);
-    }
-}
-
-VALUE
-rb_reg_matcher_new(VALUE re, VALUE str)
-{
-    NEWOBJ(matcher, struct rb_regexp_matcher);
-    OBJSETUP(matcher, rb_cRegexpMatcher, T_OBJECT);
-
-    UErrorCode status = U_ZERO_ERROR;
-    assert(RREGEXP(re)->pattern != NULL);
-    URegularExpression *match_pattern = uregex_clone(RREGEXP(re)->pattern,
-	    &status);
-    if (match_pattern == NULL) {
-	rb_raise(rb_eRegexpError, "can't clone given regexp: %s",
-		u_errorName(status));
-    }
-
-    long chars_len = 0;
-    UChar *chars = rb_str_xcopy_uchars(str, &chars_len);
-
-    if (chars_len == 0) {
-	// uregex_setText() will complain if we pass a NULL pattern or a
-	// pattern length of 0, so we do pass an empty pattern with a length
-	// of -1 which indicates it's terminated by \0.
-	chars = (UChar *)xmalloc(sizeof(UChar));
-	*chars = '\0';
-	chars_len = -1;
-    }
-
-    uregex_setText(match_pattern, chars, chars_len, &status);
-
-    if (status != U_ZERO_ERROR) {
-	uregex_close(match_pattern);
-	rb_raise(rb_eRegexpError, "can't set pattern text: %s",
-		u_errorName(status));	
-    }
-
-    matcher->pattern = match_pattern;
-    matcher->encoding = rb_enc_get(str);
-    matcher->frozen_str = 0; // set lazily
-
-    // Apparently uregex_setText doesn't copy the given string, so we need
-    // to keep it around until we finally destroy the matcher object.
-    GC_WB(&matcher->text_chars, chars);
-
-    return (VALUE)matcher;
-}
-
-void
-rb_reg_matcher_destroy(VALUE matcher)
-{
-    reg_matcher_cleanup((rb_regexp_matcher_t *)matcher);
-    xfree((void *)matcher);
-}
-
-int
-rb_reg_matcher_search_find(VALUE re, VALUE matcher, int pos, bool reverse,
-	bool findFirst)
-{
-    rb_regexp_matcher_t *re_matcher = (rb_regexp_matcher_t *)matcher;
-
-    UErrorCode status = U_ZERO_ERROR;
-    int32_t chars_len = 0;
-    const UChar *chars = uregex_getText(re_matcher->pattern, &chars_len,
-	    &status);
-    if (chars == NULL) {
-	rb_raise(rb_eRegexpError, "can't get text from regexp: %s",
-		u_errorName(status));
-    }
-    if (chars_len < 0) {
-	chars_len = 0;
-    }
-
-    if (pos > chars_len || pos < 0) {
-	rb_backref_set(Qnil);
-	return -1;
-    }
-
-    if (reverse) {
-	const int orig = pos;
-	while (pos >= 0) {
-	    if (uregex_find(re_matcher->pattern, pos, &status)) {
-		if (uregex_start(re_matcher->pattern, 0, &status) <= orig) {
-		    break;
-		}
-	    }
-	    pos--;
-	}
-	if (pos < 0) {
-	    // No match.
-	    rb_backref_set(Qnil);
-	    return -1;
-	}
-    }
-    else {
-	if (findFirst) {
-	    uregex_setRegion(re_matcher->pattern, pos, chars_len, &status);
-	}
-	if (!uregex_findNext(re_matcher->pattern, &status)) {
-	    // No match.
-	    rb_backref_set(Qnil);
-	    return -1;
-	}
-    }
-
-    // Match found.
-    const int res_count = 1 + uregex_groupCount(re_matcher->pattern, &status);
-    rb_match_result_t *res = NULL;
-
-    VALUE match = rb_backref_get();
-    if (NIL_P(match) || RMATCH(match)->busy) {
-	// Creating a new Match object.
-	match = (VALUE)match_alloc(rb_cMatch, 0);
-	rb_backref_set(match);
-	res = (rb_match_result_t *)xmalloc(sizeof(rb_match_result_t)
-		* res_count);
-	GC_WB(&RMATCH(match)->results, res);
-    }
-    else {
-	// Reusing the previous Match object.
-	assert(RMATCH(match)->results != NULL);
-	if (res_count > RMATCH(match)->results_count) {
-	    res = (rb_match_result_t *)xrealloc(RMATCH(match)->results,
-		    sizeof(rb_match_result_t) * res_count);
-	    if (res != RMATCH(match)->results) {
-		GC_WB(&RMATCH(match)->results, res);
-	    }
-	}
-	else {
-	    res = RMATCH(match)->results;
-	    memset(res, 0, sizeof(rb_match_result_t) * res_count);
-	}
-    }
-
-    RMATCH(match)->results_count = res_count;
-    if (RMATCH(match)->regexp != (rb_regexp_t *)re) {
-	GC_WB(&RMATCH(match)->regexp, re);
-    }
-
-    if (re_matcher->frozen_str == 0) {
-	// To reduce memory usage, the Match string is a singleton object.
-	GC_WB(&re_matcher->frozen_str, rb_str_new(NULL, 0));
-	rb_str_force_encoding(re_matcher->frozen_str, re_matcher->encoding);
-	rb_str_append_uchars(re_matcher->frozen_str, chars, chars_len);
-	OBJ_FREEZE(re_matcher->frozen_str);
-    }
-    GC_WB(&RMATCH(match)->str, re_matcher->frozen_str);
-
-    for (int i = 0; i < res_count; i++) {
-	res[i].beg = uregex_start(re_matcher->pattern, i, &status);
-	res[i].end = uregex_end(re_matcher->pattern, i, &status);
-    }
-
-    return res[0].beg;
-}
-
-static long
-reg_match_pos(VALUE re, VALUE *strp, long pos)
-{
-    VALUE str = *strp;
-
-    if (NIL_P(str)) {
-	rb_backref_set(Qnil);
-	return -1;
-    }
-    *strp = str = reg_operand(str, true);
-    if (pos != 0) {
-	if (pos < 0) {
-	    VALUE l = rb_str_length(str);
-	    pos += NUM2INT(l);
-	    if (pos < 0) {
-		return pos;
-	    }
-	}
-	pos = rb_reg_adjust_startpos(re, str, pos, false);
-    }
-    return rb_reg_search(re, str, pos, 0);
-}
-
-VALUE
-regexp_match(VALUE rcv, SEL sel, VALUE str)
-{
-    const long pos = reg_match_pos(rcv, &str, 0);
-    if (pos < 0) {
-	return Qnil;
-    }
-    return LONG2FIX(pos);
-}
-
-/*
- *  call-seq:
- *     rxp.match(str)       => matchdata or nil
- *     rxp.match(str,pos)   => matchdata or nil
- *
- *  Returns a <code>MatchData</code> object describing the match, or
- *  <code>nil</code> if there was no match. This is equivalent to retrieving the
- *  value of the special variable <code>$~</code> following a normal match.
- *  If the second parameter is present, it specifies the position in the string
- *  to begin the search.
- *
- *     /(.)(.)(.)/.match("abc")[2]   #=> "b"
- *     /(.)(.)/.match("abc", 1)[2]   #=> "c"
- *     
- *  If a block is given, invoke the block with MatchData if match succeed, so
- *  that you can write
- *     
- *     pat.match(str) {|m| ...}
- *     
- *  instead of
- *      
- *     if m = pat.match(str)
- *       ...
- *     end
- *      
- *  The return value is a value from block execution in this case.
- */
-
-VALUE
-regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE result, str, initpos;
-    long pos;
-
-    if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) {
-	pos = NUM2LONG(initpos);
-    }
-    else {
-	pos = 0;
-    }
-
-    pos = reg_match_pos(rcv, &str, pos);
-    if (pos < 0) {
-	rb_backref_set(Qnil);
-	return Qnil;
-    }
-    result = rb_backref_get();
-    rb_match_busy(result);
-    if (!NIL_P(result) && rb_block_given_p()) {
-	return rb_yield(result);
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     ~ rxp   => integer or nil
- *
- *  Match---Matches <i>rxp</i> against the contents of <code>$_</code>.
- *  Equivalent to <code><i>rxp</i> =~ $_</code>.
- *
- *     $_ = "input data"
- *     ~ /at/   #=> 7
- */
-
-static VALUE
-regexp_match3(VALUE rcv, SEL sel)
-{
-    VALUE line = rb_lastline_get();
-    if (TYPE(line) != T_STRING) {
-	rb_backref_set(Qnil);
-	return Qnil;
-    }
-    const long start = rb_reg_search(rcv, line, 0, 0);
-    if (start < 0) {
-	return Qnil;
-    }
-    return LONG2FIX(start);
-}
-
-/*
- *  call-seq:
- *     rxp === str   => true or false
- *
- *  Case Equality---Synonym for <code>Regexp#=~</code> used in case statements.
- *
- *     a = "HELLO"
- *     case a
- *     when /^[a-z]*$/; print "Lower case\n"
- *     when /^[A-Z]*$/; print "Upper case\n"
- *     else;            print "Mixed case\n"
- *     end
- *
- *  <em>produces:</em>
- *
- *     Upper case
- */
-
-VALUE
-regexp_eqq(VALUE rcv, SEL sel, VALUE str)
-{
-    str = reg_operand(str, Qfalse);
-    if (NIL_P(str)) {
-	rb_backref_set(Qnil);
-	return Qfalse;
-    }
-    const long start = rb_reg_search(rcv, str, 0, false);
-    if (start < 0) {
-	return Qfalse;
-    }
-    return Qtrue;
-}
-
-/*
- *  call-seq:
- *      rxp.source   => str
- *
- *  Returns the original string of the pattern.
- *
- *      /ab+c/ix.source #=> "ab+c"
- *
- *  Note that escape sequences are retained as is.
- *
- *     /\x20\+/.source  #=> "\\x20\\+"
- *
- */
-
-VALUE
-rb_regexp_source(VALUE re)
-{
-    int32_t chars_len = 0;
-    const UChar *chars = NULL;
-    regexp_get_pattern(RREGEXP(re)->pattern, &chars, &chars_len);
-
-    return rb_unicode_str_new(chars, chars_len);
-}
-
-static VALUE
-regexp_source(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_regexp_source(rcv);
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-/*
- * call-seq:
- *    rxp.inspect   => string
- *
- * Produce a nicely formatted string-version of _rxp_. Perhaps surprisingly,
- * <code>#inspect</code> actually produces the more natural version of
- * the string than <code>#to_s</code>.
- *
- *      /ab+c/ix.inspect        #=> "/ab+c/ix"
- *
- */
-
-static VALUE
-regexp_inspect(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_unicode_str_new(NULL, 0);
-    rb_str_append_uchar(str, '/');
-
-    int32_t chars_len = 0;
-    const UChar *chars = NULL;
-    regexp_get_pattern(RREGEXP(rcv)->pattern, &chars, &chars_len);
-
-    for (int i = 0; i < chars_len; i++) {
-	UChar c = chars[i];
-	if (c == '/') {
-	    rb_str_append_uchar(str, '\\');
-	}
-	rb_str_append_uchar(str, c);
-    }
-
-    rb_str_append_uchar(str, '/');
-
-    const uint32_t options = rb_reg_options(rcv);
-    const bool mode_m = options & REGEXP_OPT_MULTILINE;
-    const bool mode_i = options & REGEXP_OPT_IGNORECASE;
-    const bool mode_x = options & REGEXP_OPT_EXTENDED;
-
-    if (mode_m) {
-	rb_str_cat2(str, "m");
-    }
-    if (mode_i) {
-	rb_str_cat2(str, "i");
-    }
-    if (mode_x) {
-	rb_str_cat2(str, "x");
-    }
-    
-    return str;
-}
-
-/*
- *  call-seq:
- *     rxp.to_s   => str
- *
- *  Returns a string containing the regular expression and its options (using the
- *  <code>(?opts:source)</code> notation. This string can be fed back in to
- *  <code>Regexp::new</code> to a regular expression with the same semantics as
- *  the original. (However, <code>Regexp#==</code> may not return true when
- *  comparing the two, as the source of the regular expression itself may
- *  differ, as the example shows).  <code>Regexp#inspect</code> produces a
- *  generally more readable version of <i>rxp</i>.
- *
- *      r1 = /ab+c/ix           #=> /ab+c/ix
- *      s1 = r1.to_s            #=> "(?ix-m:ab+c)"
- *      r2 = Regexp.new(s1)     #=> /(?ix-m:ab+c)/
- *      r1 == r2                #=> false
- *      r1.source               #=> "ab+c"
- *      r2.source               #=> "(?ix-m:ab+c)"
- */
-
-static VALUE
-regexp_to_s(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_str_new2("(?");
-
-    const uint32_t options = rb_reg_options(rcv);
-    const bool mode_m = options & REGEXP_OPT_MULTILINE;
-    const bool mode_i = options & REGEXP_OPT_IGNORECASE;
-    const bool mode_x = options & REGEXP_OPT_EXTENDED;
-
-    if (mode_m) {
-	rb_str_cat2(str, "m");
-    }
-    if (mode_i) {
-	rb_str_cat2(str, "i");
-    }
-    if (mode_x) {
-	rb_str_cat2(str, "x");
-    }
-
-    if (!mode_m || !mode_i || !mode_x) {
-	rb_str_cat2(str, "-");
-	if (!mode_m) {
-	    rb_str_cat2(str, "m");
-	}
-	if (!mode_i) {
-	    rb_str_cat2(str, "i");
-	}
-	if (!mode_x) {
-	    rb_str_cat2(str, "x");
-	}
-    }
-
-    rb_str_cat2(str, ":");
-    rb_str_concat(str, regexp_source(rcv, 0));
-    rb_str_cat2(str, ")");
-
-    return str;
-}
-
-/*
- *  call-seq:
- *     rxp.casefold?   => true or false
- *
- *  Returns the value of the case-insensitive flag.
- *
- *      /a/.casefold?           #=> false
- *      /a/i.casefold?          #=> true
- *      /(?i:a)/.casefold?      #=> false
- */
-
-int
-rb_reg_options(VALUE re)
-{
-    assert(RREGEXP(re)->pattern != NULL);
-    UErrorCode status = U_ZERO_ERROR;
-    return uregex_flags(RREGEXP(re)->pattern, &status);
-}
-
-static VALUE
-regexp_casefold(VALUE rcv, SEL sel)
-{
-    return rb_reg_options(rcv) & REGEXP_OPT_IGNORECASE ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     rxp.options   => fixnum
- *
- *  Returns the set of bits corresponding to the options used when creating this
- *  Regexp (see <code>Regexp::new</code> for details. Note that additional bits
- *  may be set in the returned options: these are used internally by the regular
- *  expression code. These extra bits are ignored if the options are passed to
- *  <code>Regexp::new</code>.
- *
- *     Regexp::IGNORECASE                  #=> 1
- *     Regexp::EXTENDED                    #=> 2
- *     Regexp::MULTILINE                   #=> 4
- *
- *     /cat/.options                       #=> 0
- *     /cat/ix.options                     #=> 3
- *     Regexp.new('cat', true).options     #=> 1
- *     /\xa1\xa2/e.options                 #=> 16
- *
- *     r = /cat/ix
- *     Regexp.new(r.source, r.options)     #=> /cat/ix
- */
-
-static VALUE
-regexp_options(VALUE rcv, SEL sel)
-{
-    return INT2FIX(rb_reg_options(rcv));
-}
-
-/*
- *  call-seq:
- *     rxp.fixed_encoding?   => true or false
- *
- *  Returns false if rxp is applicable to
- *  a string with any ASCII compatible encoding.
- *  Returns true otherwise.
- *
- *      r = /a/
- *      r.fixed_encoding?                               #=> false
- *      r =~ "\u{6666} a"                               #=> 2
- *      r =~ "\xa1\xa2 a".force_encoding("euc-jp")      #=> 2
- *      r =~ "abc".force_encoding("euc-jp")             #=> 0
- *      r =~ "\u{6666} a"                               #=> 2
- *      r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
- *      r =~ "abc".force_encoding("euc-jp")             #=> 0
- *
- *      r = /\u{6666}/
- *      r.fixed_encoding?                               #=> true
- *      r.encoding                                      #=> #<Encoding:UTF-8>
- *      r =~ "\u{6666} a"                               #=> 0
- *      r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
- *      r =~ "abc".force_encoding("euc-jp")             #=> nil
- *
- *      r = /a/u
- *      r.fixed_encoding?                               #=> true
- *      r.encoding                                      #=> #<Encoding:UTF-8>
- */
-
-static VALUE
-regexp_fixed_encoding(VALUE rcv, SEL sel)
-{
-    return RREGEXP(rcv)->fixed_encoding ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *    rxp.names   => [name1, name2, ...]
- *
- * Returns a list of names of captures as an array of strings.
- *
- *     /(?<foo>.)(?<bar>.)(?<baz>.)/.names
- *     #=> ["foo", "bar", "baz"]
- *
- *     /(?<foo>.)(?<foo>.)/.names
- *     #=> ["foo"]
- *
- *     /(.)(.)/.names
- *     #=> []
- */
-
-static VALUE
-regexp_names(VALUE rcv, SEL sel)
-{
-    // TODO
-    return rb_ary_new();
-}
-
-/*
- * call-seq:
- *    rxp.named_captures  => hash
- *
- * Returns a hash representing information about named captures of <i>rxp</i>.
- *
- * A key of the hash is a name of the named captures.
- * A value of the hash is an array which is list of indexes of corresponding
- * named captures.
- *
- *    /(?<foo>.)(?<bar>.)/.named_captures
- *    #=> {"foo"=>[1], "bar"=>[2]}
- *
- *    /(?<foo>.)(?<foo>.)/.named_captures
- *    #=> {"foo"=>[1, 2]}
- *
- * If there are no named captures, an empty hash is returned.
- *
- *    /(.)(.)/.named_captures
- *    #=> {}
- */
-
-static VALUE
-regexp_named_captures(VALUE rcv, SEL sel)
-{
-    // TODO
-    return rb_hash_new();
-}
-
-static VALUE
-match_getter(void)
-{
-    VALUE match = rb_backref_get();
-    if (NIL_P(match)) {
-	return Qnil;
-    }
-    rb_match_busy(match);
-    return match;
-}
-
-static void
-match_setter(VALUE val)
-{
-    if (!NIL_P(val)) {
-	Check_Type(val, T_MATCH);
-    }
-    rb_backref_set(val);
-}
-
-static VALUE
-last_match_getter(void)
-{
-    return rb_reg_last_match(rb_backref_get());
-}
-
-static VALUE
-prematch_getter(void)
-{
-    return rb_reg_match_pre(rb_backref_get());
-}
-
-static VALUE
-postmatch_getter(void)
-{
-    return rb_reg_match_post(rb_backref_get());
-}
-
-static VALUE
-last_paren_match_getter(void)
-{
-    return rb_reg_match_last(rb_backref_get());
-}
-
-static VALUE
-kcode_getter(void)
-{
-    rb_warn("variable $KCODE is no longer effective");
-    return Qnil;
-}
-
-static void
-kcode_setter(VALUE val, ID id)
-{
-    rb_warn("variable $KCODE is no longer effective; ignored");
-}
-
-static VALUE
-ignorecase_getter(void)
-{
-    rb_warn("variable $= is no longer effective");
-    return Qfalse;
-}
-
-static void
-ignorecase_setter(VALUE val, ID id)
-{
-    rb_warn("variable $= is no longer effective; ignored");
-}
-
-/*
- *  Document-class: Regexp
- *
- *  A <code>Regexp</code> holds a regular expression, used to match a pattern
- *  against strings. Regexps are created using the <code>/.../</code> and
- *  <code>%r{...}</code> literals, and by the <code>Regexp::new</code>
- *  constructor.
- *
- */
-
-static void Init_Match(void);
-
-void
-Init_Regexp(void)
-{
-    rb_eRegexpError = rb_define_class("RegexpError", rb_eStandardError);
-
-    rb_define_virtual_variable("$~", match_getter, match_setter);
-    rb_define_virtual_variable("$&", last_match_getter, 0);
-    rb_define_virtual_variable("$`", prematch_getter, 0);
-    rb_define_virtual_variable("$'", postmatch_getter, 0);
-    rb_define_virtual_variable("$+", last_paren_match_getter, 0);
-    rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
-    rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
-    rb_define_virtual_variable("$-K", kcode_getter, kcode_setter);
-
-    rb_cRegexp = rb_define_class("Regexp", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "alloc", regexp_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "compile",
-	    rb_class_new_instance_imp, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "quote", regexp_quote, 1);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "escape", regexp_quote, 1);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "union", regexp_union, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "last_match",
-	    regexp_last_match, -1);
-    rb_objc_define_method(*(VALUE *)rb_cRegexp, "try_convert",
-	    regexp_try_convert, 1);
-
-    rb_objc_define_method(rb_cRegexp, "initialize", regexp_initialize, -1);
-    rb_objc_define_method(rb_cRegexp, "initialize_copy",
-	    regexp_initialize_copy, 1);
-    rb_objc_define_method(rb_cRegexp, "hash", regexp_hash, 0);
-    rb_objc_define_method(rb_cRegexp, "eql?", regexp_equal, 1);
-    rb_objc_define_method(rb_cRegexp, "==", regexp_equal, 1);
-    rb_objc_define_method(rb_cRegexp, "=~", regexp_match, 1);
-    rb_objc_define_method(rb_cRegexp, "match", regexp_match2, -1);
-    rb_objc_define_method(rb_cRegexp, "~", regexp_match3, 0);
-    rb_objc_define_method(rb_cRegexp, "===", regexp_eqq, 1);
-    rb_objc_define_method(rb_cRegexp, "source", regexp_source, 0);
-    rb_objc_define_method(rb_cRegexp, "casefold?", regexp_casefold, 0);
-    rb_objc_define_method(rb_cRegexp, "options", regexp_options, 0);
-    rb_objc_define_method(rb_cRegexp, "fixed_encoding?",
-	    regexp_fixed_encoding, 0);
-#if 0
-    rb_objc_define_method(rb_cRegexp, "encoding", rb_reg_encoding, 0);
-#endif
-    rb_objc_define_method(rb_cRegexp, "names", regexp_names, 0);
-    rb_objc_define_method(rb_cRegexp, "named_captures",
-	    regexp_named_captures, 0);
-    rb_objc_define_method(rb_cRegexp, "to_s", regexp_to_s, 0);
-    rb_objc_define_method(rb_cRegexp, "inspect", regexp_inspect, 0);
-
-    regexp_finalize_imp_super = rb_objc_install_method2((Class)rb_cRegexp,
-	    "finalize", (IMP)regexp_finalize_imp);
-
-    rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(REGEXP_OPT_IGNORECASE));
-    rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(REGEXP_OPT_EXTENDED));
-    rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(REGEXP_OPT_MULTILINE));
-
-    rb_cRegexpMatcher = rb_define_class("_RegexpMatcher", rb_cObject);
-
-    regexp_matcher_finalize_imp_super = rb_objc_install_method2(
-	    (Class)rb_cRegexpMatcher, "finalize",
-	    (IMP)regexp_matcher_finalize_imp);
-
-    Init_Match();
-}
-
-static VALUE
-match_initialize_copy(VALUE rcv, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_MATCH) {
-	rb_raise(rb_eTypeError, "wrong argument type");
-    }
-
-    GC_WB(&RMATCH(rcv)->str, RMATCH(other)->str);
-    GC_WB(&RMATCH(rcv)->regexp, RMATCH(other)->regexp);
-
-    const long len = sizeof(rb_match_result_t) * RMATCH(other)->results_count;
-    rb_match_result_t *res = (rb_match_result_t *)xmalloc(len);
-    memcpy(res, RMATCH(other)->results, len);
-    GC_WB(&RMATCH(rcv)->results, res);
-
-    return rcv;
-}
-
-/*
- * call-seq:
- *    mtch.regexp   => regexp
- *
- * Returns the regexp.
- *
- *     m = /a.*b/.match("abc")
- *     m.regexp #=> /a.*b/
- */
-
-static VALUE
-match_regexp(VALUE rcv, SEL sel)
-{
-    assert(RMATCH(rcv)->regexp != NULL);
-    return (VALUE)RMATCH(rcv)->regexp;
-}
-
-/*
- * call-seq:
- *    mtch.names   => [name1, name2, ...]
- *
- * Returns a list of names of captures as an array of strings.
- * It is same as mtch.regexp.names.
- *
- *     /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
- *     #=> ["foo", "bar", "baz"]
- *
- *     m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
- *     m.names                          #=> ["x", "y"]
- */
-
-static VALUE
-match_names(VALUE rcv, SEL sel)
-{
-    // TODO
-    return rb_ary_new();
-}
-
-/*
- *  call-seq:
- *     mtch.length   => integer
- *     mtch.size     => integer
- *
- *  Returns the number of elements in the match array.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.length   #=> 5
- *     m.size     #=> 5
- */
-
-static VALUE
-match_size(VALUE rcv, SEL sel)
-{
-    return INT2FIX(RMATCH(rcv)->results_count);
-}
-
-/*
- *  call-seq:
- *     mtch.offset(n)   => array
- *
- *  Returns a two-element array containing the beginning and ending offsets of
- *  the <em>n</em>th match.
- *  <em>n</em> can be a string or symbol to reference a named capture.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.offset(0)      #=> [1, 7]
- *     m.offset(4)      #=> [6, 7]
- *
- *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- *     p m.offset(:foo) #=> [0, 1]
- *     p m.offset(:bar) #=> [2, 3]
- *
- */
-
-static int
-match_backref_number(VALUE match, VALUE backref, bool check)
-{
-    const char *name;
-
-    switch (TYPE(backref)) {
-	default:
-	    {
-		const int pos = NUM2INT(backref);
-		if (check) {
-		    if (pos < 0 || pos >= RMATCH(match)->results_count) {
-			rb_raise(rb_eIndexError,
-				"index %d out of matches", pos);
-		    }
-		}
-		return pos;
-	    }
-
-	case T_SYMBOL:
-	    name = rb_sym2name(backref);
-	    break;
-
-	case T_STRING:
-	    name = StringValueCStr(backref);
-	    break;
-    }
-
-    // TODO
-    rb_raise(rb_eIndexError, "named captures are not yet supported");
-}
- 
-static VALUE
-match_offset(VALUE rcv, SEL sel, VALUE backref)
-{
-    const int pos = match_backref_number(rcv, backref, true);
-    return rb_assoc_new(INT2FIX(RMATCH(rcv)->results[pos].beg),
-	    INT2FIX(RMATCH(rcv)->results[pos].end));
-}
-
-/*
- *  call-seq:
- *     mtch.begin(n)   => integer
- *
- *  Returns the offset of the start of the <em>n</em>th element of the match
- *  array in the string.
- *  <em>n</em> can be a string or symbol to reference a named capture.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.begin(0)       #=> 1
- *     m.begin(2)       #=> 2
- *
- *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- *     p m.begin(:foo)  #=> 0
- *     p m.begin(:bar)  #=> 2
- */
-
-static VALUE
-match_begin(VALUE rcv, SEL sel, VALUE backref)
-{
-    const int pos = match_backref_number(rcv, backref, true);
-    return INT2FIX(RMATCH(rcv)->results[pos].beg);
-}
-
-/*
- *  call-seq:
- *     mtch.end(n)   => integer
- *
- *  Returns the offset of the character immediately following the end of the
- *  <em>n</em>th element of the match array in the string.
- *  <em>n</em> can be a string or symbol to reference a named capture.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.end(0)         #=> 7
- *     m.end(2)         #=> 3
- *
- *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- *     p m.end(:foo)    #=> 1
- *     p m.end(:bar)    #=> 3
- */
-
-static VALUE
-match_end(VALUE rcv, SEL sel, VALUE backref)
-{
-    const int pos = match_backref_number(rcv, backref, true);
-    return INT2FIX(RMATCH(rcv)->results[pos].end);
-}
-
-/*
- *  call-seq:
- *     mtch.to_a   => anArray
- *
- *  Returns the array of matches.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.to_a   #=> ["HX1138", "H", "X", "113", "8"]
- *
- *  Because <code>to_a</code> is called when expanding
- *  <code>*</code><em>variable</em>, there's a useful assignment
- *  shortcut for extracting matched fields. This is slightly slower than
- *  accessing the fields directly (as an intermediate array is
- *  generated).
- *
- *     all,f1,f2,f3 = *(/(.)(.)(\d+)(\d)/.match("THX1138."))
- *     all   #=> "HX1138"
- *     f1    #=> "H"
- *     f2    #=> "X"
- *     f3    #=> "113"
- */
-
-static VALUE
-match_array(VALUE match, int start)
-{
-    const int len = RMATCH(match)->results_count;
-    assert(start >= 0);
-    const bool tainted = OBJ_TAINTED(match);
-
-    VALUE ary = rb_ary_new2(len);
-    for (int i = start; i < len; i++) {
-	VALUE str = rb_reg_nth_match(i, match);
-	if (tainted) {
-	    OBJ_TAINT(str);
-	}
-	rb_ary_push(ary, str);
-    }
-    return ary;
-}
-
-static VALUE
-match_to_a(VALUE rcv, SEL sel)
-{
-    return match_array(rcv, 0);
-}
-
-/*
- *  call-seq:
- *     mtch.captures   => array
- *
- *  Returns the array of captures; equivalent to <code>mtch.to_a[1..-1]</code>.
- *
- *     f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
- *     f1    #=> "H"
- *     f2    #=> "X"
- *     f3    #=> "113"
- *     f4    #=> "8"
- */
-
-static VALUE
-match_captures(VALUE rcv, SEL sel)
-{
-    return match_array(rcv, 1);
-}
-
-/*
- *  call-seq:
- *     mtch[i]               => str or nil
- *     mtch[start, length]   => array
- *     mtch[range]           => array
- *     mtch[name]            => str or nil
- *
- *  Match Reference---<code>MatchData</code> acts as an array, and may be
- *  accessed using the normal array indexing techniques.  <i>mtch</i>[0] is
- *  equivalent to the special variable <code>$&</code>, and returns the entire
- *  matched string.  <i>mtch</i>[1], <i>mtch</i>[2], and so on return the values
- *  of the matched backreferences (portions of the pattern between parentheses).
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m          #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
- *     m[0]       #=> "HX1138"
- *     m[1, 2]    #=> ["H", "X"]
- *     m[1..3]    #=> ["H", "X", "113"]
- *     m[-3, 2]   #=> ["X", "113"]
- *
- *     m = /(?<foo>a+)b/.match("ccaaab")
- *     m          #=> #<MatchData "aaab" foo:"aaa">
- *     m["foo"]   #=> "aaa"
- *     m[:foo]    #=> "aaa"
- */
-
-static VALUE
-match_aref(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE backref, rest;
-
-    rb_scan_args(argc, argv, "11", &backref, &rest);
-
-    if (NIL_P(rest)) {
-	switch (TYPE(backref)) {
-	    case T_STRING:
-	    case T_SYMBOL:
-	    case T_FIXNUM:
-		{
-		    const int pos = match_backref_number(rcv, backref, false);
-		    return rb_reg_nth_match(pos, rcv);
-		}
-	}
-    }
-    return rb_ary_aref(argc, argv, match_to_a(rcv, 0));
-}
-
-/*
- *  call-seq:
- *
- *     mtch.values_at([index]*)   => array
- *
- *  Uses each <i>index</i> to access the matching values, returning an array of
- *  the corresponding matches.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- *     m.to_a               #=> ["HX1138", "H", "X", "113", "8"]
- *     m.values_at(0, 2, -2)   #=> ["HX1138", "X", "113"]
- */
-
-static VALUE
-match_entry(VALUE match, long n)
-{
-    return rb_reg_nth_match(n, match);
-}
-
-static VALUE
-match_values_at(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_get_values_at(rcv, RMATCH(rcv)->results_count, argc, argv,
-	    match_entry);
-}
-
-/*
- *  call-seq:
- *     mtch.pre_match   => str
- *
- *  Returns the portion of the original string before the current match.
- *  Equivalent to the special variable <code>$`</code>.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.pre_match   #=> "T"
- */
-
-static VALUE
-match_pre(VALUE rcv, SEL sel)
-{
-    assert(RMATCH(rcv)->results_count > 0);
-
-    VALUE str = rb_str_substr(RMATCH(rcv)->str, 0,
-	    RMATCH(rcv)->results[0].beg);
-
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-VALUE
-rb_reg_match_pre(VALUE rcv)
-{
-    if (NIL_P(rcv)) {
-	return Qnil;
-    }
-    return match_pre(rcv, 0);
-}
-
-/*
- *  call-seq:
- *     mtch.post_match   => str
- *
- *  Returns the portion of the original string after the current match.
- *  Equivalent to the special variable <code>$'</code>.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- *     m.post_match   #=> ": The Movie"
- */
-
-static VALUE
-match_post(VALUE rcv, SEL sel)
-{
-    assert(RMATCH(rcv)->results_count > 0);
-
-    const int pos = RMATCH(rcv)->results[0].end;
-    VALUE str = rb_str_substr(RMATCH(rcv)->str, pos,
-	    rb_str_chars_len(RMATCH(rcv)->str) - pos);
-
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-VALUE
-rb_reg_match_post(VALUE rcv)
-{
-    if (NIL_P(rcv)) {
-	return Qnil;
-    }
-    return match_post(rcv, 0);
-}
-
-VALUE
-rb_reg_match_last(VALUE rcv)
-{
-    if (NIL_P(rcv)) {
-	return Qnil;
-    }
-    assert(RMATCH(rcv)->results_count > 0);
-
-    int nth = RMATCH(rcv)->results_count - 1;
-    while(nth > 0) {
-	if (RMATCH(rcv)->results[nth].beg != -1) {
-	    break;
-	}
-	nth--;
-    }
-    if (nth == 0) {
-	return Qnil;
-    }
-    return rb_reg_nth_match(nth, rcv);
-}
-
-/*
- * call-seq:
- *    mtch.inspect   => str
- *
- * Returns a printable version of <i>mtch</i>.
- *
- *     puts /.$/.match("foo").inspect
- *     #=> #<MatchData "o">
- *
- *     puts /(.)(.)(.)/.match("foo").inspect
- *     #=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
- *
- *     puts /(.)(.)?(.)/.match("fo").inspect
- *     #=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
- *
- *     puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
- *     #=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
- *
- */
-
-rb_match_result_t *
-rb_reg_match_results(VALUE match, int *count)
-{
-    assert(match != Qnil);
-    if (count != NULL) {
-	*count = RMATCH(match)->results_count;
-    }
-    return RMATCH(match)->results;
-}
-
-VALUE
-rb_reg_nth_match_with_cache(int nth, VALUE match,
-	character_boundaries_cache_t *cache)
-{
-    if (NIL_P(match)) {
-	return Qnil;
-    }
-    if (nth >= RMATCH(match)->results_count) {
-	return Qnil;
-    }
-    if (nth < 0) {
-	nth += RMATCH(match)->results_count;
-	if (nth <= 0) {
-	    return Qnil;
-	}
-    }
-
-    const int beg = RMATCH(match)->results[nth].beg;
-    const int end = RMATCH(match)->results[nth].end;
-    if (beg == -1 || end == -1) {
-	return Qnil;
-    }
-
-    return rb_str_substr_with_cache(RMATCH(match)->str, beg, end - beg, cache);
-}
-
-VALUE
-rb_reg_nth_match(int nth, VALUE match)
-{
-    return rb_reg_nth_match_with_cache(nth, match, NULL);
-}
-
-VALUE
-rb_reg_last_match(VALUE match)
-{
-    return rb_reg_nth_match(0, match);
-}
-
-static VALUE
-match_inspect(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_str_buf_new2("#<");
-    rb_str_buf_cat2(str, rb_obj_classname(rcv));
-    for (int i = 0; i < RMATCH(rcv)->results_count; i++) {
-	rb_str_buf_cat2(str, " ");
-	if (i > 0) {
-	    char buf[10];
-	    snprintf(buf, sizeof buf, "%d:", i);
-	    rb_str_buf_cat2(str, buf);
-	}
-	VALUE v = rb_reg_nth_match(i, rcv);
-	if (v == Qnil) {
-	    rb_str_buf_cat2(str, "nil");
-	}
-	else {
-	    rb_str_buf_append(str, rb_str_inspect(v));
-	}
-    }
-    rb_str_buf_cat2(str, ">");
-    return str;
-}
-
-/*
- *  call-seq:
- *     mtch.string   => str
- *
- *  Returns a frozen copy of the string passed in to <code>match</code>.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.string   #=> "THX1138."
- */
-
-static VALUE
-match_string(VALUE rcv, SEL sel)
-{
-    assert(RMATCH(rcv)->str != 0);
-    return RMATCH(rcv)->str;
-}
-
-/*
- *  call-seq:
- *     mtch.to_s   => str
- *
- *  Returns the entire matched string.
- *
- *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- *     m.to_s   #=> "HX1138"
- */
-
-static VALUE
-match_to_s(VALUE rcv, SEL sel)
-{
-    VALUE str = rb_reg_last_match(rcv);
-
-    if (NIL_P(str)) {
-	str = rb_str_new(0, 0);
-    }
-    if (OBJ_TAINTED(rcv)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-/*
- * call-seq:
- *    mtch == mtch2   => true or false
- *
- *  Equality---Two matchdata are equal if their target strings,
- *  patterns, and matched positions are identical.
- */
-
-static VALUE
-match_equal(VALUE rcv, SEL sel, VALUE other)
-{
-    if (rcv == other) {
-	return Qtrue;
-    }
-    if (TYPE(other) != T_MATCH) {
-	return Qfalse;
-    }
-    if (regexp_equal((VALUE)RMATCH(rcv)->regexp, 0,
-		(VALUE)RMATCH(other)->regexp) != Qtrue) {
-	return Qfalse;
-    }
-    if (rb_str_equal(RMATCH(rcv)->str, RMATCH(other)->str) != Qtrue) {
-	return Qfalse;
-    }
-    if (RMATCH(rcv)->results_count != RMATCH(other)->results_count) {
-	return Qfalse;
-    }
-    for (int i = 0; i < RMATCH(rcv)->results_count; i++) {
-	rb_match_result_t *res1 = RMATCH(rcv)->results;
-	rb_match_result_t *res2 = RMATCH(other)->results;
-	if (res1[i].beg != res2[i].beg || res1[i].end != res2[i].end) {
-	    return Qfalse;
-	}
-    }
-    return Qtrue;
-}
-
-/*
- *  Document-class: MatchData
- *
- *  <code>MatchData</code> is the type of the special variable <code>$~</code>,
- *  and is the type of the object returned by <code>Regexp#match</code> and
- *  <code>Regexp.last_match</code>. It encapsulates all the results of a pattern
- *  match, results normally accessed through the special variables
- *  <code>$&</code>, <code>$'</code>, <code>$`</code>, <code>$1</code>,
- *  <code>$2</code>, and so on.
- *
- */
-
-static void
-Init_Match(void)
-{
-    rb_cMatch = rb_define_class("MatchData", rb_cObject);
-    rb_undef_method(CLASS_OF(rb_cMatch), "new");
-
-    rb_objc_define_method(*(VALUE *)rb_cMatch, "alloc", match_alloc, 0);
-    rb_objc_define_method(rb_cMatch, "initialize_copy",
-	    match_initialize_copy, 1);
-    rb_objc_define_method(rb_cMatch, "regexp", match_regexp, 0);
-    rb_objc_define_method(rb_cMatch, "names", match_names, 0);
-    rb_objc_define_method(rb_cMatch, "size", match_size, 0);
-    rb_objc_define_method(rb_cMatch, "length", match_size, 0);
-    rb_objc_define_method(rb_cMatch, "offset", match_offset, 1);
-    rb_objc_define_method(rb_cMatch, "begin", match_begin, 1);
-    rb_objc_define_method(rb_cMatch, "end", match_end, 1);
-    rb_objc_define_method(rb_cMatch, "to_a", match_to_a, 0);
-    rb_objc_define_method(rb_cMatch, "captures", match_captures, 0);
-    rb_objc_define_method(rb_cMatch, "[]", match_aref, -1);
-    rb_objc_define_method(rb_cMatch, "values_at", match_values_at, -1);
-    rb_objc_define_method(rb_cMatch, "pre_match", match_pre, 0);
-    rb_objc_define_method(rb_cMatch, "post_match",match_post, 0);
-    rb_objc_define_method(rb_cMatch, "to_s", match_to_s, 0);
-    rb_objc_define_method(rb_cMatch, "string", match_string, 0);
-    rb_objc_define_method(rb_cMatch, "inspect", match_inspect, 0);
-    rb_objc_define_method(rb_cMatch, "eql?", match_equal, 1);
-    rb_objc_define_method(rb_cMatch, "==", match_equal, 1);
-}
-
-// Compiler primitives.
-
-void
-regexp_get_uchars(VALUE re, const UChar **chars_p, int32_t *chars_len_p)
-{
-    assert(chars_p != NULL && chars_len_p != NULL);
-    regexp_get_pattern(RREGEXP(re)->pattern, chars_p, chars_len_p);
-}
-
-VALUE
-rb_unicode_regex_new_retained(UChar *chars, int chars_len, int options)
-{
-    VALUE str = rb_unicode_str_new(chars, chars_len);
-    VALUE re = rb_reg_new_str(str, options);
-    GC_RETAIN(re);
-    return re;
-}
-
-// MRI compatibility.
-
-VALUE
-rb_reg_check_preprocess(VALUE str)
-{
-    return Qnil;
-}
-
-VALUE
-rb_reg_compile(VALUE str, int options)
-{
-    VALUE exc = Qnil;
-    VALUE regexp = rb_str_compile_regexp(str, options, &exc); 
-    if (regexp == Qnil) {
-	rb_set_errinfo(exc);
-    }
-    return regexp;
-}
-
-VALUE
-rb_reg_new_str(VALUE str, int options)
-{
-    VALUE exc = Qnil;
-    VALUE regexp = rb_str_compile_regexp(str, options, &exc); 
-    if (regexp == Qnil) {
-	rb_exc_raise(exc);
-    }
-    return regexp;
-}
-
-VALUE
-rb_reg_regcomp(VALUE str)
-{
-    // XXX MRI caches the regexp here, maybe we should do the same...
-    return rb_reg_new_str(str, 0);
-}
-
-VALUE
-rb_reg_new(const char *cstr, long len, int options)
-{
-    return rb_reg_new_str(rb_usascii_str_new(cstr, len), options);
-}
-
-VALUE
-rb_reg_quote(VALUE pat)
-{
-    VALUE result;
-
-    RB_STR_GET_UCHARS(pat, chars, chars_len);
-
-    long pos = 0;
-    for (; pos < chars_len; pos++) {
-	switch (chars[pos]) {
-	    case '[': case ']': case '{': case '}':
-	    case '(': case ')': case '|': case '-':
-	    case '*': case '.': case '\\': case '?':
-	    case '+': case '^': case '$': case ' ':
-	    case '#': case '\t': case '\f': case '\v':
-	    case '\n': case '\r':
-		goto meta_found;
-	} 
-    }
-
-    result = rb_unicode_str_new(chars, chars_len);
-    goto bail;
-
-meta_found:
-    result = rb_unicode_str_new(NULL, (chars_len * 2) + 1);
-
-    // Copy up to metacharacter.
-    rb_str_append_uchars(result, &chars[0], pos);
-
-    for (; pos < chars_len; pos++) {
-	UChar c = chars[pos];
-	switch (c) {
-	    case '[': case ']': case '{': case '}':
-	    case '(': case ')': case '|': case '-':
-	    case '*': case '.': case '\\': case '?':
-	    case '+': case '^': case '$': case '#':
-		rb_str_append_uchar(result, '\\');
-		break;
-
-	    case ' ':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, ' ');
-		continue;
-
-	    case '\t':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, 't');
-		continue;
-
-	    case '\n':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, 'n');
-		continue;
-
-	    case '\r':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, 'r');
-		continue;
-
-	    case '\f':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, 'f');
-		continue;
-
-	    case '\v':
-		rb_str_append_uchar(result, '\\');
-		rb_str_append_uchar(result, 'v');
-		continue;
-	}
-	rb_str_append_uchar(result, c);
-    }
-
-bail:
-    return result;
-}
-
-void
-rb_match_busy(VALUE match)
-{
-    if (match != Qnil) {
-	RMATCH(match)->busy = true;
-    }
-}
-
-int
-rb_reg_options_from_mri(int mri_opt)
-{
-    int opt = 0;
-    if (mri_opt & 1) {
-	opt |= REGEXP_OPT_IGNORECASE;
-    }
-    if (mri_opt & 2) {
-	opt |= REGEXP_OPT_EXTENDED;
-    }
-    if (mri_opt & 4) {
-	opt |= REGEXP_OPT_MULTILINE;
-    }
-    return opt;
-}
-
-int
-rb_reg_options_to_mri(int opt)
-{
-    int mri_opt = 0;
-    if (opt & REGEXP_OPT_IGNORECASE) {
-	mri_opt |= 1;
-    }
-    if (opt & REGEXP_OPT_EXTENDED) {
-	mri_opt |= 2;
-    }
-    if (opt & REGEXP_OPT_MULTILINE) {
-	mri_opt |= 4;
-    }
-    return mri_opt;
-}

Deleted: MacRuby/trunk/re.h
===================================================================
--- MacRuby/trunk/re.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/re.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,80 +0,0 @@
-/* 
- * MacRuby Regular Expressions.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __RE_H_
-#define __RE_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-bool rb_char_to_icu_option(int c, int *option);
-
-VALUE regexp_eqq(VALUE rcv, SEL sel, VALUE str);
-VALUE regexp_match(VALUE rcv, SEL sel, VALUE str);
-VALUE regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv);
-
-VALUE rb_reg_quote(VALUE pat);
-VALUE rb_reg_regcomp(VALUE str);
-VALUE rb_regexp_source(VALUE re);
-
-VALUE rb_reg_matcher_new(VALUE re, VALUE str);
-int rb_reg_matcher_search_find(VALUE re, VALUE matcher, int pos, bool reverse,
-	bool findFirst);
-void rb_reg_matcher_destroy(VALUE matcher);
-
-static inline int
-rb_reg_matcher_search_first(VALUE re, VALUE matcher, int pos, bool reverse)
-{
-    return rb_reg_matcher_search_find(re, matcher, pos, reverse, true);
-}
-
-static inline int
-rb_reg_matcher_search_next(VALUE re, VALUE matcher, int pos, bool reverse)
-{
-    return rb_reg_matcher_search_find(re, matcher, pos, reverse, false);
-}
-
-static inline int
-rb_reg_matcher_search(VALUE re, VALUE matcher, int pos, bool reverse)
-{
-    return rb_reg_matcher_search_next(re, matcher, pos, reverse);
-}
-
-static inline int
-rb_reg_search(VALUE re, VALUE str, int pos, bool reverse)
-{
-    VALUE matcher = rb_reg_matcher_new(re, str);
-    const int res = rb_reg_matcher_search_first(re, matcher, pos, reverse);
-    rb_reg_matcher_destroy(matcher);
-    return res; 
-}
-
-int rb_reg_options_to_mri(int opt);
-int rb_reg_options_from_mri(int mri_opt);
-
-void regexp_get_uchars(VALUE re, const UChar **chars_p, int32_t *chars_len_p);
-
-typedef struct rb_match_result {
-    unsigned int beg;
-    unsigned int end;
-} rb_match_result_t;
-
-rb_match_result_t *rb_reg_match_results(VALUE match, int *count);
-
-static inline int
-rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, bool reverse)
-{
-    return reverse ? -pos : rb_str_chars_len(str) - pos;
-}
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __RE_H_

Deleted: MacRuby/trunk/ruby.1
===================================================================
--- MacRuby/trunk/ruby.1	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/ruby.1	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,414 +0,0 @@
-.\"Ruby is copyrighted by Yukihiro Matsumoto <matz at netlab.jp>.
-.Dd December 31, 2002
-.Dt RUBY(1) "" "Ruby Programmers Reference Guide"
-.\".Dt RUBY 1
-.Os UNIX
-.Sh NAME
-.Nm ruby
-.Nd Interpreted object-oriented scripting language
-.Sh SYNOPSIS
-.Nm
-.Op Fl -copyright
-.Op Fl -version
-.Op Fl Sacdlnpswvy
-.Op Fl 0 Ns Op Ar octal
-.Op Fl C Ar directory
-.Op Fl E Ar encoding
-.Op Fl F Ar pattern
-.Op Fl I Ar directory
-.Op Fl K Ar c
-.Op Fl T Ns Op Ar level
-.Op Fl W Ns Op Ar level
-.Op Fl e Ar command
-.Op Fl i Ns Op Ar extension
-.Op Fl r Ar library
-.Op Fl x Ns Op Ar directory
-.Op - Ns Bro Cm enable Ns | Ns Cm disable Brc Ns - Ns Ar FEATURE
-.Op Fl -verbose
-.Op Fl -
-.Op Ar program_file
-.Op Ar argument ...
-.Sh DESCRIPTION
-Ruby is an interpreted scripting language for quick and easy
-object-oriented programming.  It has many features to process text
-files and to do system management tasks (as in Perl).  It is simple,
-straight-forward, and extensible.
-.Pp
-If you want a language for easy object-oriented programming, or you
-don't like the Perl ugliness, or you do like the concept of LISP, but
-don't like too much parentheses, Ruby may be the language of your
-choice.
-.Sh FEATURES
-Ruby's features are as follows:
-.Bl -tag -width 6n
-.It Sy "Interpretive"
-Ruby is an interpreted language, so you don't have to recompile
-programs written in Ruby to execute them.
-.Pp
-.It Sy "Variables have no type (dynamic typing)"
-Variables in Ruby can contain data of any type.  You don't have to
-worry about variable typing.  Consequently, it has a weaker compile
-time check.
-.Pp
-.It Sy "No declaration needed"
-You can use variables in your Ruby programs without any declarations.
-Variable names denote their scope, local, global, instance, etc.
-.Pp
-.It Sy "Simple syntax"
-Ruby has a simple syntax influenced slightly from Eiffel.
-.Pp
-.It Sy "No user-level memory management"
-Ruby has automatic memory management.  Objects no longer referenced
-from anywhere are automatically collected by the garbage collector
-built into the interpreter.
-.Pp
-.It Sy "Everything is an object"
-Ruby is the purely object-oriented language, and was so since its
-creation.  Even such basic data as integers are seen as objects.
-.Pp
-.It Sy "Class, inheritance, and methods"
-Of course, as an object-oriented language, Ruby has such basic
-features like classes, inheritance, and methods.
-.Pp
-.It Sy "Singleton methods"
-Ruby has the ability to define methods for certain objects.  For
-example, you can define a press-button action for certain widget by
-defining a singleton method for the button.  Or, you can make up your
-own prototype based object system using singleton methods, if you want
-to.
-.Pp
-.It Sy "Mix-in by modules"
-Ruby intentionally does not have the multiple inheritance as it is a
-source of confusion.  Instead, Ruby has the ability to share
-implementations across the inheritance tree.  This is often called
-.Sq Mix-in .
-.Pp
-.It Sy "Iterators"
-Ruby has iterators for loop abstraction.
-.Pp
-.It Sy "Closures"
-In Ruby, you can objectify the procedure.
-.Pp
-.It Sy "Text processing and regular expression"
-Ruby has a bunch of text processing features like in Perl.
-.Pp
-.It Sy "Bignums"
-With built-in bignums, you can for example calculate factorial(400).
-.Pp
-.It Sy "Exception handling"
-As in Java(tm).
-.Pp
-.It Sy "Direct access to the OS"
-Ruby can use most
-.Ux
-system calls, often used in system programming.
-.Pp
-.It Sy "Dynamic loading"
-On most
-.Ux
-systems, you can load object files into the Ruby interpreter
-on-the-fly.
-.El
-.Pp
-.Sh OPTIONS
-Ruby interpreter accepts following command-line options (switches).
-They are quite similar to those of
-.Xr perl 1 .
-.Bl -tag -width "1234567890123" -compact
-.Pp
-.It Fl -copyright
-Prints the copyright notice.
-.Pp
-.It Fl -version
-Prints the version of Ruby interpreter.
-.Pp
-.It Fl 0 Ns Op Ar octal
-(The digit
-.Dq zero . )
-Specifies the input record separator
-.Pf ( Li "$/" )
-as an octal number. If no digit is given, the null character is taken
-as the separator.  Other switches may follow the digits.
-.Fl 00
-turns Ruby into paragraph mode.
-.Fl 0777
-makes Ruby read whole file at once as a single string since there is
-no legal character with that value.
-.Pp
-.It Fl C Ar directory
-.It Fl X Ar directory
-Causes Ruby to switch to the directory.
-.Pp
-.It Fl E Ar encname
-.It Fl -encoding Ar encname
-Specifies the encoding for the program codes.
-.Pp
-.It Fl F Ar pattern
-Specifies input field separator
-.Pf ( Li "$;" ) .
-.Pp
-.It Fl I Ar directory
-Used to tell Ruby where to load the library scripts.  Directory path
-will be added to the load-path variable
-.Pf ( Li "$:" ) .
-.Pp
-.It Fl K Ar kcode
-Specifies KANJI (Japanese) encoding.
-.Pp
-.It Fl S
-Makes Ruby use the
-.Ev PATH
-environment variable to search for script, unless if its name begins
-with a slash.  This is used to emulate
-.Li #!
-on machines that don't support it, in the following manner:
-.Bd -literal -offset indent
-#! /usr/local/bin/ruby
-# This line makes the next one a comment in Ruby \e
-  exec /usr/local/bin/ruby -S $0 $*
-.Ed
-.Pp
-.It Fl T Ns Op Ar level
-Turns on taint checks at the specified level (default 1).
-.Pp
-.It Fl W Ns Op Ar level
-Turns on verbose mode at the specified level, without printing version 
-message at the beginning. The level can be;
-.Bl -hang -offset indent
-.It Sy 0
-Verbose mode is "silence". It sets the
-.Li "$VERBOSE"
-to nil.
-.Pp
-.It Sy 1
-Verbose mode is "medium". It sets the
-.Li "$VERBOSE"
-to false.
-.Pp
-.It Sy 2 (default)
-Verbose mode is "verbose". It sets the
-.Li "$VERBOSE"
-to true.
-.Fl W Ns
-2 is same as
-.Fl w
-.
-.El
-.Pp
-.It Fl a
-Turns on auto-split mode when used with
-.Fl n
-or
-.Fl p .
-In auto-split mode, Ruby executes
-.Dl $F = $_.split
-at beginning of each loop.
-.Pp
-.It Fl c
-Causes Ruby to check the syntax of the script and exit without
-executing. If there are no syntax errors, Ruby will print
-.Dq Syntax OK
-to the standard output.
-.Pp
-.It Fl d
-.It Fl -debug
-Turns on debug mode.
-.Li "$DEBUG"
-will be set to true.
-.Pp
-.It Fl e Ar command
-Specifies script from command-line while telling Ruby not to search
-the rest of arguments for a script file name.
-.Pp
-.It Fl h
-.It Fl -help
-Prints a summary of the options.
-.Pp
-.It Fl i Ar extension
-Specifies in-place-edit mode.  The extension, if specified, is added
-to old file name to make a backup copy.  For example:
-.Bd -literal -offset indent
-% echo matz > /tmp/junk
-% cat /tmp/junk
-matz
-% ruby -p -i.bak -e '$_.upcase!' /tmp/junk
-% cat /tmp/junk
-MATZ
-% cat /tmp/junk.bak
-matz
-.Ed
-.Pp
-.It Fl l
-(The lowercase letter
-.Dq ell . )
-Enables automatic line-ending processing, which means to firstly set
-.Li "$\e"
-to the value of
-.Li "$/" ,
-and secondly chops every line read using
-.Li chop! .
-.Pp
-.It Fl n
-Causes Ruby to assume the following loop around your script, which
-makes it iterate over file name arguments somewhat like
-.Nm sed
-.Fl n
-or
-.Nm awk .
-.Bd -literal -offset indent
-while gets
-  ...
-end
-.Ed
-.Pp
-.It Fl p
-Acts mostly same as -n switch, but print the value of variable
-.Li "$_"
-at the each end of the loop.  For example:
-.Bd -literal -offset indent
-% echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"'
-MATZ
-.Ed
-.Pp
-.It Fl r Ar library
-Causes Ruby to load the library using require.  It is useful when using
-.Fl n
-or
-.Fl p .
-.Pp
-.It Fl s
-Enables some switch parsing for switches after script name but before
-any file name arguments (or before a
-.Fl - ) .
-Any switches found there are removed from
-.Li ARGV
-and set the corresponding variable in the script.  For example:
-.Bd -literal -offset indent
-#! /usr/local/bin/ruby -s
-# prints "true" if invoked with `-xyz' switch.
-print "true\en" if $xyz
-.Ed
-.Pp
-On some systems
-.Li "$0"
-does not always contain the full pathname, so you need the
-.Fl S
-switch to tell Ruby to search for the script if necessary.  To handle
-embedded spaces or such.  A better construct than
-.Li "$*"
-would be
-.Li ${1+"$@"} ,
-but it does not work if the script is being interpreted by
-.Xr csh 1 .
-.Pp
-.It Fl v
-Enables verbose mode.  Ruby will print its version at the beginning,
-and set the variable
-.Li "$VERBOSE"
-to true.  Some methods print extra messages if this variable is true.
-If this switch is given, and no other switches are present, Ruby quits
-after printing its version.
-.Pp
-.It Fl w
-Enables verbose mode without printing version message at the
-beginning.  It sets the
-.Li "$VERBOSE"
-variable to true.
-.Pp
-.It Fl x Ns Op Ar directory
-Tells Ruby that the script is embedded in a message.  Leading garbage
-will be discarded until the first that starts with
-.Dq #!
-and contains the string,
-.Dq ruby .
-Any meaningful switches on that line will applied.  The end of script
-must be specified with either
-.Li EOF ,
-.Li "^D" ( Li "control-D" ) ,
-.Li "^Z" ( Li "control-Z" ) ,
-or reserved word
-.Li __END__ .
-If the directory name is specified, Ruby will switch to that directory
-before executing script.
-.Pp
-.It Fl y
-.It Fl -yydebug
-Turns on compiler debug mode.  Ruby will print a bunch of internal
-state messages during compiling scripts.  You don't have to specify
-this switch, unless you are going to debug the Ruby interpreter.
-.Pp
-.It Fl -disable- Ns Ar FEATURE
-.It Fl -enable- Ns Ar FEATURE
-Disables (or enables) the specified
-.Ar FEATURE Ns
-\&.
-.Pp
-.It Fl -disable-gems
-.It Fl -enable-gems
-Disables (or enables) RubyGems libraries.  By default, Ruby will load the latest
-version of each installed gem. The
-.Li Gem::Enable
-constant is true if RubyGems is enabled, false if otherwise.
-.Pp
-.It Fl -disable-rubyopt
-.It Fl -enable-rubyopt
-Ignores (or considers) the
-.Ev RUBYOPT
-environment variable. By default, Ruby considers the variable.
-.Pp
-.It Fl -disable-all
-.It Fl -enable-all
-Disables (or enables) all features.
-.Pp
-.It Fl -verbose
-Enables verbose mode without printing version message at the
-beginning.  It sets the
-.Li "$VERBOSE"
-variable to true.
-If this switch is given, and no other switches are present, Ruby quits
-after printing its version.
-.El
-.Pp
-.Sh ENVIRONMENT
-.Bl -tag -width "RUBYLIB_PREFIX" -compact
-.It Ev RUBYLIB
-A colon-separated list of directories that are added to Ruby's
-library load path
-.Pf ( Li "$:" ) . Directories from this environment variable are searched
-before the standard load path is searched.
-.Pp
-e.g.:
-.Dl RUBYLIB="$HOME/lib/ruby:$HOME/lib/rubyext"
-.Pp
-.It Ev RUBYOPT
-Additional Ruby options.
-.Pp
-e.g.
-.Dl RUBYOPT="-w -Ke"
-.Pp
-.It Ev RUBYPATH
-A colon-separated list of directories that Ruby searches for
-Ruby programs when the
-.Fl S
-flag is specified.  This variable precedes the
-.Ev PATH
-environment variable.
-.Pp
-.It Ev RUBYSHELL
-The path to the system shell command.  This environment variable is
-enabled for only mswin32, mingw32, and OS/2 platforms.  If this
-variable is not defined, Ruby refers to
-.Ev COMSPEC .
-.Pp
-.It Ev PATH
-Ruby refers to the
-.Ev PATH
-environment variable on calling Kernel#system.
-.Pp
-.It Ev RUBYLIB_PREFIX
-This variable is obsolete.
-.El
-.Pp
-.Sh AUTHORS
-Ruby is designed and implemented by
-.An Yukihiro Matsumoto Aq matz at netlab.jp .

Deleted: MacRuby/trunk/ruby.c
===================================================================
--- MacRuby/trunk/ruby.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/ruby.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1464 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/param.h>
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/encoding.h"
-#include "dln.h"
-#include "vm.h"
-#include "encoding.h"
-#include "ruby/util.h"
-
-#ifndef HAVE_STDLIB_H
-char *getenv();
-#endif
-
-/* TODO: move to VM */
-VALUE ruby_debug = Qfalse;
-VALUE ruby_verbose = Qfalse;
-VALUE ruby_debug_socket_path = Qfalse;
-VALUE ruby_aot_compile = Qfalse;
-VALUE ruby_aot_init_func = Qfalse;
-VALUE ruby_aot_bs_files = Qnil;
-VALUE rb_progname = Qnil;
-
-static int uid, euid, gid, egid;
-
-static void
-init_ids(void)
-{
-    uid = (int)getuid();
-    euid = (int)geteuid();
-    gid = (int)getgid();
-    egid = (int)getegid();
-    if (uid && (euid != uid || egid != gid)) {
-	rb_set_safe_level(1);
-    }
-}
-
-#if !defined(MACRUBY_STATIC)
-
-VALUE rb_parser_get_yydebug(VALUE);
-VALUE rb_parser_set_yydebug(VALUE, VALUE);
-
-const char *ruby_get_inplace_mode(void);
-void ruby_set_inplace_mode(const char *);
-
-#define DISABLE_BIT(bit) (1U << disable_##bit)
-enum disable_flag_bits {
-    disable_gems,
-    disable_rubyopt,
-};
-
-#define DUMP_BIT(bit) (1U << dump_##bit)
-enum dump_flag_bits {
-    dump_insns,
-};
-
-struct cmdline_options {
-    int sflag, xflag;
-    int do_loop, do_print;
-    int do_check, do_line;
-    int do_split, do_search;
-    int usage;
-    int version;
-    int copyright;
-    unsigned int disable;
-    int verbose;
-    int yydebug;
-    unsigned int dump;
-    const char *script;
-    VALUE script_name;
-    VALUE e_script;
-    struct {
-	struct {
-	    VALUE name;
-	    rb_encoding *enc;
-	} enc;
-    } src, ext;
-};
-
-struct cmdline_arguments {
-    int argc;
-    char **argv;
-    struct cmdline_options *opt;
-};
-
-static NODE *load_file(VALUE, const char *, int, struct cmdline_options *);
-static void forbid_setid(const char *);
-
-static struct {
-    int argc;
-    char **argv;
-#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
-    int len;
-#endif
-} origarg;
-
-static void
-usage(const char *name)
-{
-    /* This message really ought to be max 23 lines.
-     * Removed -h because the user already knows that option. Others? */
-
-    static const char *const usage_msg[] = {
-	"-0[octal]       specify record separator (\\0, if no argument)",
-	"-a              autosplit mode with -n or -p (splits $_ into $F)",
-	"-c              check syntax only",
-	"-Cdirectory     cd to directory, before executing your script",
-	"-d              set debugging flags (set $DEBUG to true)",
-	"-e 'command'    one line of script. Several -e's allowed. Omit [programfile]",
-	"-Eencoding      specifies the character encoding for the program codes",
-	"-Fpattern       split() pattern for autosplit (-a)",
-	"-i[extension]   edit ARGV files in place (make backup if extension supplied)",
-	"-Idirectory     specify $LOAD_PATH directory (may be used more than once)",
-	"-l              enable line ending processing",
-	"-n              assume 'while gets(); ... end' loop around your script",
-	"-p              assume loop like -n but print line also like sed",
-	"-rlibrary       require the library, before executing your script",
-	"-s              enable some switch parsing for switches after script name",
-	"-S              look for the script using PATH environment variable",
-	"-T[level]       turn on tainting checks",
-	"-v              print version number, then turn on verbose mode",
-	"-w              turn warnings on for your script",
-	"-W[level]       set warning level; 0=silence, 1=medium, 2=verbose (default)",
-	"-x[directory]   strip off text before #!ruby line and perhaps cd to directory",
-	"--copyright     print the copyright",
-	"--version       print the version",
-	NULL
-    };
-    const char *const *p = usage_msg;
-
-    printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
-    while (*p)
-	printf("  %s\n", *p++);
-}
-
-VALUE rb_get_load_path(void);
-
-#ifndef CharNext		/* defined as CharNext[AW] on Windows. */
-#define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-#endif
-
-#define rubylib_mangled_path rb_str_new
-#define rubylib_mangled_path2 rb_str_new2
-
-static void
-push_include(const char *path, VALUE (*filter)(VALUE))
-{
-    const char sep = PATH_SEP_CHAR;
-    const char *p, *s;
-    VALUE load_path = rb_vm_load_path();
-
-    p = path;
-    while (*p) {
-	while (*p == sep) {
-	    p++;
-	}
-	if (!*p) {
-	    break;
-	}
-	for (s = p; *s && *s != sep; s = CharNext(s));
-	rb_ary_push(load_path, (*filter)(rubylib_mangled_path(p, s - p)));
-	p = s;
-    }
-}
-
-void
-ruby_push_include(const char *path, VALUE (*filter)(VALUE))
-{
-    if (path != NULL) {
-	push_include(path, filter);
-    }
-}
-
-static VALUE
-identical_path(VALUE path)
-{
-    return path;
-}
-
-void
-ruby_incpush(const char *path)
-{
-    ruby_push_include(path, identical_path);
-}
-
-static VALUE
-expand_include_path(VALUE path)
-{
-    const char *p = RSTRING_PTR(path);
-    if (!p) {
-	return path;
-    }
-    if (*p == '.' && p[1] == '/') {
-	return path;
-    }
-    return rb_file_expand_path(path, Qnil);
-}
-
-void 
-ruby_incpush_expand(const char *path)
-{
-    ruby_push_include(path, expand_include_path);
-}
-
-static CFMutableArrayRef req_list = NULL;
-
-static void
-add_modules(const char *mod)
-{
-    CFStringRef mod_str;
-    if (req_list == NULL) {
-	req_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    }
-    mod_str = CFStringCreateWithFileSystemRepresentation(NULL, mod);
-    CFArrayAppendValue(req_list, mod_str);
-    CFRelease(mod_str);
-}
-
-extern void Init_ext(void);
-extern VALUE rb_vm_top_self(void);
-
-void
-rb_require_libraries(void)
-{
-    static bool init = false;
-    if (init) {
-	return;
-    }
-    init = true;
-
-    Init_ext();		/* should be called here for some reason :-( */
-
-    if (req_list != NULL) {
-	VALUE vm;
-	ID require;
-	int i, count;
-       
-	vm = rb_vm_top_self();
-	require	= rb_intern("require");
-	for (i = 0, count = CFArrayGetCount(req_list); i < count; i++) {
-	    const void *feature = CFArrayGetValueAtIndex(req_list, i);
-	    rb_funcall2(vm, require, 1, (VALUE *)&feature);
-	}
-	CFRelease(req_list);
-    }
-}
-
-static void
-process_sflag(struct cmdline_options *opt)
-{
-    if (opt->sflag) {
-	long i, n;
-	VALUE argv = rb_argv;
-
-	n = RARRAY_LEN(argv);
-	i = 0;
-	while (n > 0) {
-	    VALUE v = RARRAY_AT(argv, i++);
-	    char *s = StringValuePtr(v);
-	    char *p;
-	    int hyphen = Qfalse;
-
-	    if (s[0] != '-')
-		break;
-	    n--;
-	    if (s[1] == '-' && s[2] == '\0')
-		break;
-
-	    v = Qtrue;
-	    /* check if valid name before replacing - with _ */
-	    for (p = s + 1; *p; p++) {
-		if (*p == '=') {
-		    *p++ = '\0';
-		    v = rb_str_new2(p);
-		    break;
-		}
-		if (*p == '-') {
-		    hyphen = Qtrue;
-		}
-		else if (*p != '_' && !ISALNUM(*p)) {
-		    VALUE name_error[2];
-		    name_error[0] =
-			rb_str_new2("invalid name for global variable - ");
-		    if (!(p = strchr(p, '='))) {
-			rb_str_cat2(name_error[0], s);
-		    }
-		    else {
-			rb_str_cat(name_error[0], s, p - s);
-		    }
-		    name_error[1] = RARRAY_AT(argv, -1);
-		    rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
-		}
-	    }
-	    s[0] = '$';
-	    if (hyphen) {
-		for (p = s + 1; *p; ++p) {
-		    if (*p == '-')
-			*p = '_';
-		}
-	    }
-	    rb_gv_set(s, v);
-	}
-	n = RARRAY_LEN(argv) - n;
-	while (n--) {
-	    rb_ary_shift(argv);
-	}
-    }
-    opt->sflag = 0;
-}
-
-NODE *rb_parser_append_print(VALUE, NODE *);
-NODE *rb_parser_while_loop(VALUE, NODE *, int, int);
-static int proc_options(int argc, char **argv, struct cmdline_options *opt);
-
-static char *
-moreswitches(const char *s, struct cmdline_options *opt)
-{
-    int argc;
-    char *argv[3];
-    const char *p = s;
-
-    argc = 2;
-    argv[0] = argv[2] = 0;
-    while (*s && !ISSPACE(*s))
-	s++;
-    argv[1] = ALLOCA_N(char, s - p + 2);
-    argv[1][0] = '-';
-    strncpy(argv[1] + 1, p, s - p);
-    argv[1][s - p + 1] = '\0';
-    proc_options(argc, argv, opt);
-    while (*s && ISSPACE(*s))
-	s++;
-    return (char *)s;
-}
-
-#define NAME_MATCH_P(name, str, len) \
-    ((len) < sizeof(name) && strncmp((str), name, (len)) == 0)
-
-#define UNSET_WHEN(name, bit, str, len)	\
-    if (NAME_MATCH_P(name, str, len)) { \
-	*(unsigned int *)arg &= ~(bit); \
-	return;				\
-    }
-
-#define SET_WHEN(name, bit, str, len)	\
-    if (NAME_MATCH_P(name, str, len)) { \
-	*(unsigned int *)arg |= (bit);	\
-	return;				\
-    }
-
-static void
-enable_option(const char *str, int len, void *arg)
-{
-#define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
-    UNSET_WHEN_DISABLE(gems);
-    UNSET_WHEN_DISABLE(rubyopt);
-    if (NAME_MATCH_P("all", str, len)) {
-	*(unsigned int *)arg = 0U;
-	return;
-    }
-    rb_warn("unknown argument for --enable: `%.*s'", len, str);
-}
-
-static void
-disable_option(const char *str, int len, void *arg)
-{
-#define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
-    SET_WHEN_DISABLE(gems);
-    SET_WHEN_DISABLE(rubyopt);
-    if (NAME_MATCH_P("all", str, len)) {
-	*(unsigned int *)arg = ~0U;
-	return;
-    }
-    rb_warn("unknown argument for --disable: `%.*s'", len, str);
-}
-
-static void
-dump_option(const char *str, int len, void *arg)
-{
-#define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
-    SET_WHEN_DUMP(insns);
-    rb_warn("don't know how to dump `%.*s', (insns)", len, str);
-}
-
-static int
-proc_options(int argc, char **argv, struct cmdline_options *opt)
-{
-    int n, argc0 = argc;
-    const char *s;
-
-    if (argc == 0)
-	return 0;
-
-    for (argc--, argv++; argc > 0; argc--, argv++) {
-	if (argv[0][0] != '-' || !argv[0][1])
-	    break;
-
-	s = argv[0] + 1;
-      reswitch:
-	switch (*s) {
-	  case 'a':
-	    opt->do_split = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 'p':
-	    opt->do_print = Qtrue;
-	    /* through */
-	  case 'n':
-	    opt->do_loop = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 'd':
-	    ruby_debug = Qtrue;
-	    ruby_verbose = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 'y':
-	    opt->yydebug = 1;
-	    s++;
-	    goto reswitch;
-
-	  case 'v':
-	    if (opt->verbose) {
-		s++;
-		goto reswitch;
-	    }
-	    ruby_show_version();
-	    opt->verbose = 1;
-	  case 'w':
-	    ruby_verbose = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 'W':
-	    {
-		int numlen;
-		int v = 2;	/* -W as -W2 */
-
-		if (*++s) {
-		    v = scan_oct(s, 1, &numlen);
-		    if (numlen == 0)
-			v = 1;
-		    s += numlen;
-		}
-		switch (v) {
-		  case 0:
-		    ruby_verbose = Qnil;
-		    break;
-		  case 1:
-		    ruby_verbose = Qfalse;
-		    break;
-		  default:
-		    ruby_verbose = Qtrue;
-		    break;
-		}
-	    }
-	    goto reswitch;
-
-	  case 'c':
-	    opt->do_check = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 's':
-	    forbid_setid("-s");
-	    opt->sflag = 1;
-	    s++;
-	    goto reswitch;
-
-	  case 'h':
-	    usage(origarg.argv[0]);
-	    rb_exit(EXIT_SUCCESS);
-	    break;
-
-	  case 'l':
-	    opt->do_line = Qtrue;
-	    rb_output_rs = rb_rs;
-	    s++;
-	    goto reswitch;
-
-	  case 'S':
-	    forbid_setid("-S");
-	    opt->do_search = Qtrue;
-	    s++;
-	    goto reswitch;
-
-	  case 'e':
-	    forbid_setid("-e");
-	    if (*++s == '\0') {
-		s = argv[1];
-		argc--;
-		argv++;
-	    }
-	    if (s == NULL) {
-		rb_raise(rb_eRuntimeError, "no code specified for -e");
-	    }
-	    if (opt->e_script == 0) {
-		opt->e_script = rb_str_new(NULL, 0);
-		if (opt->script == NULL) {
-		    opt->script = "-e";
-		}
-	    }
-	    rb_str_cat2(opt->e_script, s);
-	    rb_str_cat2(opt->e_script, "\n");
-	    break;
-
-	  case 'r':
-	    forbid_setid("-r");
-	    if (*++s != '\0') {
-		add_modules(s);
-	    }
-	    else if (argv[1]) {
-		add_modules(argv[1]);
-		argc--;
-		argv++;
-	    }
-	    break;
-
-	  case 'i':
-	    forbid_setid("-i");
-	    ruby_set_inplace_mode(s + 1);
-	    break;
-
-	  case 'x':
-	    opt->xflag = Qtrue;
-	    s++;
-	    if (*s && chdir(s) < 0) {
-		rb_fatal("Can't chdir to %s", s);
-	    }
-	    break;
-
-	  case 'C':
-	  case 'X':
-	    s++;
-	    if (!*s) {
-		s = argv[1];
-		argc--, argv++;
-	    }
-	    if (!s || !*s) {
-		rb_fatal("Can't chdir");
-	    }
-	    if (chdir(s) < 0) {
-		rb_fatal("Can't chdir to %s", s);
-	    }
-	    break;
-
-	  case 'F':
-	    if (*++s) {
-		rb_fs = rb_reg_new(s, strlen(s), 0);
-	    }
-	    break;
-
-	  case 'E':
-	    if (!*++s) goto next_encoding;
-	    goto encoding;
-
-	  case 'K':
-	    if (*++s) {
-		const char *enc_name = 0;
-		switch (*s) {
-		  case 'E': case 'e':
-		    enc_name = "EUC-JP";
-		    break;
-		  case 'S': case 's':
-		    enc_name = "Windows-31J";
-		    break;
-		  case 'U': case 'u':
-		    enc_name = "UTF-8";
-		    break;
-		  case 'N': case 'n': case 'A': case 'a':
-		    enc_name = "ASCII-8BIT";
-		    break;
-		}
-		if (enc_name) {
-		    opt->src.enc.name = rb_str_new2(enc_name);
-		    opt->ext.enc.name = opt->src.enc.name;
-		}
-		s++;
-	    }
-	    goto reswitch;
-
-	  case 'T':
-	    {
-		int numlen;
-		int v = 1;
-
-		if (*++s) {
-		    v = scan_oct(s, 2, &numlen);
-		    if (numlen == 0)
-			v = 1;
-		    s += numlen;
-		}
-		rb_set_safe_level(v);
-	    }
-	    goto reswitch;
-
-	  case 'I':
-	    forbid_setid("-I");
-	    if (*++s)
-		ruby_incpush_expand(s);
-	    else if (argv[1]) {
-		ruby_incpush_expand(argv[1]);
-		argc--, argv++;
-	    }
-	    break;
-
-	  case '0':
-	    {
-		int numlen;
-		int v;
-		char c;
-
-		v = scan_oct(s, 4, &numlen);
-		s += numlen;
-		if (v > 0377)
-		    rb_rs = Qnil;
-		else if (v == 0 && numlen >= 2) {
-		    rb_rs = rb_str_new2("\n\n");
-		}
-		else {
-		    c = v & 0xff;
-		    rb_rs = rb_str_new(&c, 1);
-		}
-	    }
-	    goto reswitch;
-
-	  case '-':
-	    if (!s[1] || (s[1] == '\r' && !s[2])) {
-		argc--, argv++;
-		goto switch_end;
-	    }
-	    s++;
-	    if (strcmp("copyright", s) == 0) {
-		opt->copyright = 1;
-	    }
-	    else if (strcmp("debug", s) == 0) {
-		ruby_debug = Qtrue;
-                ruby_verbose = Qtrue;
-            }
-	    else if (strncmp("enable", s, n = 6) == 0 &&
-		     (!s[n] || s[n] == '-' || s[n] == '=')) {
-		if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
-		    rb_raise(rb_eRuntimeError, "missing argument for --enable");
-		}
-		ruby_each_words(s, enable_option, &opt->disable);
-	    }
-	    else if (strncmp("disable", s, n = 7) == 0 &&
-		     (!s[n] || s[n] == '-' || s[n] == '=')) {
-		if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
-		    rb_raise(rb_eRuntimeError, "missing argument for --disable");
-		}
-		ruby_each_words(s, disable_option, &opt->disable);
-	    }
-	    else if (strncmp("encoding", s, n = 8) == 0 && (!s[n] || s[n] == '=')) {
-		s += n;
-		if (!*s++) {
-		  next_encoding:
-		    if (!--argc || !(s = *++argv)) {
-			rb_raise(rb_eRuntimeError, "missing argument for --encoding");
-		    }
-		}
-	      encoding:
-		opt->ext.enc.name = rb_str_new2(s);
-	    }
-	    else if (strcmp("version", s) == 0) {
-		opt->version = 1;
-	    }
-	    else if (strcmp("verbose", s) == 0) {
-		opt->verbose = 1;
-		ruby_verbose = Qtrue;
-	    }
-	    else if (strcmp("yydebug", s) == 0) {
-		opt->yydebug = 1;
-	    }
-	    else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) {
-		if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break;
-		ruby_each_words(s, dump_option, &opt->dump);
-	    }
-	    else if (strcmp("help", s) == 0) {
-		usage(origarg.argv[0]);
-		rb_exit(EXIT_SUCCESS);
-	    }
-	    else if (strcmp("emit-llvm", s) == 0) {
-		// This option is not documented and only used by macrubyc.
-		// Users should use macrubyc and never call this option
-		// directly.
-		if (argc < 3) {
-		    rb_raise(rb_eRuntimeError,
-			    "expected 2 arguments (output file and init function) for --emit-llvm");
-		}
-		ruby_aot_compile = rb_str_new2(argv[1]);
-		ruby_aot_init_func = rb_str_new2(argv[2]);
-		GC_RETAIN(ruby_aot_compile);
-		GC_RETAIN(ruby_aot_init_func);
-		argc--; argv++;
-		argc--; argv++;
-	    }
-	    else if (strcmp("uses-bs", s) == 0) {
-		// This option is not documented and only used by macrubyc.
-		// Users should use macrubyc and never call this option
-		// directly.
-		if (argc < 2) {
-		    rb_raise(rb_eRuntimeError,
-			    "expected 1 argument (complete BridgeSupport file ) for --uses-bs");
-		}
-		if (ruby_aot_bs_files == Qnil) {
-		    ruby_aot_bs_files = rb_ary_new();
-		    GC_RETAIN(ruby_aot_bs_files);
-		}
-		rb_ary_push(ruby_aot_bs_files, rb_str_new2(argv[1]));
-		argc--; argv++;
-	    }
-	    else if (strcmp("debug-mode", s) == 0) {
-		// This option is not documented and only used by macrubyd.
-		// Users should use macrubyd and never call this option
-		// directly.
-		if (argc < 2) {
-		    rb_raise(rb_eRuntimeError,
-			    "expected 1 argument (unix socket path) for --debug-mode");
-		}
-		ruby_debug_socket_path = rb_str_new2(argv[1]);
-		GC_RETAIN(ruby_debug_socket_path);
-		argc--; argv++;
-	    }
-	    else {
-		rb_raise(rb_eRuntimeError,
-			 "invalid option --%s  (-h will show valid options)", s);
-	    }
-	    break;
-
-	  case '\r':
-	    if (!s[1])
-		break;
-
-	  default:
-	    {
-		if (ISPRINT(*s)) {
-                    rb_raise(rb_eRuntimeError,
-			"invalid option -%c  (-h will show valid options)",
-                        (int)(unsigned char)*s);
-		}
-		else {
-                    rb_raise(rb_eRuntimeError,
-			"invalid option -\\x%02X  (-h will show valid options)",
-                        (int)(unsigned char)*s);
-		}
-	    }
-	    goto switch_end;
-
-	  case 0:
-	    break;
-	}
-    }
-
-  switch_end:
-    return argc0 - argc;
-}
-
-void Init_prelude(void);
-
-static void
-ruby_init_gems(int enable)
-{
-    // TODO
-}
-
-static rb_encoding *
-opt_enc_find(VALUE enc_name)
-{
-    rb_encoding *enc = rb_enc_find(RSTRING_PTR(enc_name));
-    if (enc == NULL) {
-	rb_raise(rb_eRuntimeError, "unknown encoding name - %s", 
-	    RSTRING_PTR(enc_name));
-    }
-    return enc;
-}
-
-VALUE rb_argv0;
-
-static rb_encoding *src_encoding;
-
-static VALUE
-process_options(VALUE arg)
-{
-    struct cmdline_arguments *argp = (struct cmdline_arguments *)arg;
-    struct cmdline_options *opt = argp->opt;
-    int argc = argp->argc;
-    char **argv = argp->argv;
-    NODE *tree = 0;
-    VALUE parser;
-    rb_encoding *enc, *lenc;
-    const char *s;
-    char fbuf[MAXPATHLEN];
-    int i = proc_options(argc, argv, opt);
-    int safe;
-
-    argc -= i;
-    argv += i;
-
-    if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
-	rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
-	VALUE src_enc_name = opt->src.enc.name;
-	VALUE ext_enc_name = opt->ext.enc.name;
-
-	while (ISSPACE(*s))
-	    s++;
-	if (*s == 'T' || (*s == '-' && *(s + 1) == 'T')) {
-	    int numlen;
-	    int v = 1;
-
-	    if (*s != 'T')
-		++s;
-	    if (*++s) {
-		v = scan_oct(s, 2, &numlen);
-		if (numlen == 0)
-		    v = 1;
-	    }
-	    rb_set_safe_level(v);
-	}
-	else {
-	    while (s && *s) {
-		if (*s == '-') {
-		    s++;
-		    if (ISSPACE(*s)) {
-			do {
-			    s++;
-			} while (ISSPACE(*s));
-			continue;
-		    }
-		}
-		if (!*s)
-		    break;
-		if (!strchr("EIdvwWrK", *s))
-		    rb_raise(rb_eRuntimeError,
-			     "invalid switch in RUBYOPT: -%c", *s);
-		s = moreswitches(s, opt);
-	    }
-	}
-	if (src_enc_name)
-	    opt->src.enc.name = src_enc_name;
-	if (ext_enc_name)
-	    opt->ext.enc.name = ext_enc_name;
-    }
-
-    if (!ruby_aot_compile) {
-	rb_vm_init_jit();
-    }
-
-    if (opt->version) {
-	ruby_show_version();
-	return Qtrue;
-    }
-    if (opt->copyright) {
-	ruby_show_copyright();
-    }
-
-    if (rb_safe_level() >= 4) {
-	OBJ_TAINT(rb_argv);
-	OBJ_TAINT(rb_vm_load_path());
-    }
-
-    if (!opt->e_script) {
-	if (argc == 0) {	/* no more args */
-	    if (opt->verbose)
-		return Qtrue;
-	    opt->script = "-";
-	}
-	else {
-	    opt->script = argv[0];
-	    if (opt->script[0] == '\0') {
-		opt->script = "-";
-	    }
-	    else if (opt->do_search) {
-		char *path = getenv("RUBYPATH");
-
-		opt->script = 0;
-		if (path) {
-		    opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
-		}
-		if (!opt->script) {
-		    opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
-		}
-		if (!opt->script)
-		    opt->script = argv[0];
-	    }
-	    argc--;
-	    argv++;
-	}
-    }
-
-    ruby_script(opt->script);
-    GC_WB(&opt->script_name, rb_str_new4(rb_progname));
-    opt->script = RSTRING_PTR(opt->script_name);
-    ruby_set_argv(argc, argv);
-    process_sflag(opt);
-
-    ruby_init_loadpath();
-    safe = rb_safe_level();
-    rb_set_safe_level_force(0);
-    ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
-    lenc = rb_locale_encoding();
-    parser = rb_parser_new();
-    if (opt->yydebug) rb_parser_set_yydebug(parser, Qtrue);
-    if (opt->ext.enc.name != 0) {
-	opt->ext.enc.enc = opt_enc_find(opt->ext.enc.name);
-    }
-    if (opt->src.enc.name != 0) {
-	opt->src.enc.enc = opt_enc_find(opt->src.enc.name);
-	src_encoding = opt->src.enc.enc;
-    }
-    if (opt->ext.enc.enc != NULL) {
-	enc = opt->ext.enc.enc;
-    }
-    else {
-	enc = lenc;
-    }
-    rb_enc_set_default_external(rb_enc_from_encoding(enc));
-
-    rb_set_safe_level_force(safe);
-    if (opt->e_script) {
-	rb_encoding *eenc;
-	if (opt->src.enc.enc != NULL) {
-	    eenc = opt->src.enc.enc;
-	}
-	else {
-	    eenc = lenc;
-	}
-	//require_libraries();
-	tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
-    }
-    else {
-	if (opt->script[0] == '-' && !opt->script[1]) {
-	    forbid_setid("program input from stdin");
-	}
-	tree = load_file(parser, opt->script, 1, opt);
-    }
-
-    if (!tree) return Qfalse;
-
-    process_sflag(opt);
-    opt->xflag = 0;
-
-    if (rb_safe_level() >= 4) {
-	OBJ_TAINT(rb_argv);
-	OBJ_TAINT(rb_vm_load_path());
-    }
-
-    if (opt->do_check) {
-	printf("Syntax OK\n");
-	return Qtrue;
-    }
-
-    if (opt->do_print) {
-	tree = rb_parser_append_print(parser, tree);
-    }
-    if (opt->do_loop) {
-	tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
-    }
-
-    return (VALUE)tree;
-}
-
-static NODE *
-load_file(VALUE parser, const char *fname, int script,
-	struct cmdline_options *opt)
-{
-    extern VALUE rb_stdin;
-    VALUE f;
-    int line_start = 1;
-    NODE *tree = 0;
-    rb_encoding *enc;
-
-    if (fname == NULL) {
-	rb_load_fail(fname);
-    }
-    if (strcmp(fname, "-") == 0) {
-	f = rb_stdin;
-    }
-    else {
-	int fd, mode = O_RDONLY;
-	if ((fd = open(fname, mode)) < 0) {
-	    rb_load_fail(fname);
-	}
-	f = rb_io_fdopen(fd, mode, fname);
-    }
-
-    if (script) {
-	VALUE c = 1;		/* something not nil */
-	VALUE line;
-	char *p;
-	int no_src_enc = !opt->src.enc.name;
-	int no_ext_enc = !opt->ext.enc.name;
-
-	if (opt->xflag) {
-	    forbid_setid("-x");
-	    opt->xflag = Qfalse;
-	    while (!NIL_P(line = rb_io_gets(f, 0))) {
-		line_start++;
-		const char *lineptr = RSTRING_PTR(line);
-		if (RSTRING_LEN(line) > 2
-		    && lineptr[0] == '#'
-		    && lineptr[1] == '!') {
-		    if ((p = strstr(lineptr, "ruby")) != 0) {
-			goto start_read;
-		    }
-		}
-	    }
-	    rb_raise(rb_eLoadError, "no Ruby script found in input");
-	}
-
-	c = rb_io_getbyte(f, 0);
-	if (c == INT2FIX('#')) {
-	    c = rb_io_getbyte(f, 0);
-	    if (c == INT2FIX('!')) {
-		line = rb_io_gets(f, 0);
-		if (NIL_P(line)) {
-		    return 0;
-		}
-		if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) {
-		    /* not ruby script, kick the program */
-		    char **argv;
-		    char *path;
-		    char *pend;
-
-		    line = rb_str_bstr(line);
-		    p = (char *)rb_bstr_bytes(line);
-		    pend = p + rb_bstr_length(line);
-
-		    if (pend[-1] == '\n') {
-			pend--;	/* chomp line */
-		    }
-		    if (pend[-1] == '\r') {
-			pend--;
-		    }
-		    *pend = '\0';
-		    while (p < pend && ISSPACE(*p)) {
-			p++;
-		    }
-		    path = p;	/* interpreter path */
-		    while (p < pend && !ISSPACE(*p)) {
-			p++;
-		    }
-		    *p++ = '\0';
-		    if (p < pend) {
-			argv = ALLOCA_N(char *, origarg.argc + 3);
-			argv[1] = p;
-			MEMCPY(argv + 2, origarg.argv + 1, char *, origarg.argc);
-		    }
-		    else {
-			argv = origarg.argv;
-		    }
-		    argv[0] = path;
-		    execv(path, argv);
-
-		    rb_fatal("Can't exec %s", path);
-		}
-
-	      start_read:
-		p += 4;
-
-		char *linebuf = (char *)rb_bstr_bytes(line);
-		const long linebuflen = rb_bstr_length(line);
-
-		linebuf[linebuflen - 1] = '\0';
-		if (linebuf[linebuflen - 2] == '\r') {
-		    linebuf[linebuflen - 2] = '\0';
-		}
-		if ((p = strstr(p, " -")) != 0) {
-		    p++;	/* skip space before `-' */
-		    while (*p == '-') {
-			p = moreswitches(p + 1, opt);
-		    }
-		}
-
-		/* push back shebang for pragma may exist in next line */
-		rb_io_ungetc(f, 0, rb_str_new2("!\n"));
-	    }
-	    else if (!NIL_P(c)) {
-		rb_io_ungetc(f, 0, c);
-	    }
-	    rb_io_ungetc(f, 0, INT2FIX('#'));
-	    if (no_src_enc && opt->src.enc.name) {
-		opt->src.enc.enc = opt_enc_find(opt->src.enc.name);
-		src_encoding = opt->src.enc.enc;
-	    }
-	    if (no_ext_enc && opt->ext.enc.name) {
-		opt->ext.enc.enc = opt_enc_find(opt->ext.enc.name);
-	    }
-	}
-	else if (!NIL_P(c)) {
-	    rb_io_ungetc(f, 0, c);
-	}
-	//require_libraries();	/* Why here? unnatural */
-    }
-    if (opt->src.enc.enc != NULL) {
-    	enc = opt->src.enc.enc;
-    }
-    else {
-	enc = rb_locale_encoding();
-    }
-    tree = (NODE *)rb_parser_compile_file(parser, fname, f, line_start);
-    if (script && rb_parser_end_seen_p(parser)) {
-	rb_define_global_const("DATA", f);
-    }
-    else if (f != rb_stdin) {
-	rb_io_close(f);
-    }
-    return tree;
-}
-
-void *
-rb_load_file(const char *fname)
-{
-    struct cmdline_options opt;
-
-    MEMZERO(&opt, opt, 1);
-    opt.src.enc.enc = src_encoding;
-    return load_file(rb_parser_new(), fname, 0, &opt);
-}
-
-#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
-#if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
-#define USE_ENVSPACE_FOR_ARG0
-#endif
-
-#ifdef USE_ENVSPACE_FOR_ARG0
-extern char **environ;
-#endif
-
-static int
-get_arglen(int argc, char **argv)
-{
-    char *s = argv[0];
-    int i;
-
-    if (!argc) return 0;
-    s += strlen(s);
-    /* See if all the arguments are contiguous in memory */
-    for (i = 1; i < argc; i++) {
-	if (argv[i] == s + 1) {
-	    s++;
-	    s += strlen(s);	/* this one is ok too */
-	}
-	else {
-	    break;
-	}
-    }
-#if defined(USE_ENVSPACE_FOR_ARG0)
-    if (environ && (s == environ[0])) {
-	s += strlen(s);
-	for (i = 1; environ[i]; i++) {
-	    if (environ[i] == s + 1) {
-		s++;
-		s += strlen(s);	/* this one is ok too */
-	    }
-	}
-	ruby_setenv("", NULL); /* duplicate environ vars */
-    }
-#endif
-    return s - argv[0];
-}
-#endif
-
-static void
-forbid_setid(const char *s)
-{
-    if (euid != uid) {
-	rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
-    }
-    if (egid != gid) {
-	rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
-    }
-    if (rb_safe_level() > 0) {
-	rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
-    }
-}
-
-static VALUE
-false_value(void)
-{
-    return Qfalse;
-}
-
-static VALUE
-true_value(void)
-{
-    return Qtrue;
-}
-
-#define rb_define_readonly_boolean(name, val) \
-    rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
-
-void *
-ruby_process_options(int argc, char **argv)
-{
-    struct cmdline_arguments *args;
-    struct cmdline_options *opt;
-    NODE *tree;
-
-    args = (struct cmdline_arguments *)xmalloc(sizeof(struct cmdline_arguments));
-    opt = (struct cmdline_options *)xmalloc(sizeof(struct cmdline_options));
-
-    MEMZERO(opt, opt, 1);
-    ruby_script(argv[0]);	/* for the time being */
-    rb_argv0 = rb_progname;
-    GC_RETAIN(rb_argv0);
-    args->argc = argc;
-    args->argv = argv;
-    args->opt = opt;
-    opt->src.enc.enc = src_encoding;
-    opt->ext.enc.enc = NULL;
-    tree = (NODE *)process_options((VALUE)args);
-//    tree = (NODE *)rb_vm_call_cfunc(rb_vm_top_self(),
-//				    process_options, (VALUE)args,
-//				    0, rb_progname);
-
-    rb_define_readonly_boolean("$-p", opt->do_print);
-    rb_define_readonly_boolean("$-l", opt->do_line);
-    rb_define_readonly_boolean("$-a", opt->do_split);
-
-    errno = 0; // Reset errno value.
-
-    return tree;
-}
-
-#endif // !MACRUBY_STATIC
-
-void
-ruby_sysinit(int *argc, char ***argv)
-{
-    int i, n = *argc, len = 0;
-    char **v1 = *argv, **v2, *p;
-
-    for (i = 0; i < n; ++i) {
-	len += strlen(v1[i]) + 1;
-    }
-    v2 = malloc((n + 1)* sizeof(char*) + len);
-    p = (char *)&v2[n + 1];
-    for (i = 0; i < n; ++i) {
-	int l = strlen(v1[i]);
-	memcpy(p, v1[i], l + 1);
-	v2[i] = p;
-	p += l + 1;
-    }
-    v2[n] = 0;
-    *argv = v2;
-
-#if !defined(MACRUBY_STATIC)
-    origarg.argc = *argc;
-    origarg.argv = *argv;
-
-# if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
-    origarg.len = get_arglen(origarg.argc, origarg.argv);
-# endif
-#endif
-}
-
-void
-ruby_init_loadpath(void)
-{
-#if !defined(MACRUBY_STATIC)
-    VALUE load_path;
-#if defined LOAD_RELATIVE
-    char libpath[MAXPATHLEN + 1];
-    char *p;
-    int rest;
-
-    libpath[sizeof(libpath) - 1] = '\0';
-    p = strrchr(libpath, '/');
-    if (p) {
-	*p = 0;
-	if (p - libpath > 3 && !STRCASECMP(p - 4, "/bin")) {
-	    p -= 4;
-	    *p = 0;
-	}
-    }
-    else {
-	strcpy(libpath, ".");
-	p = libpath + 1;
-    }
-
-    rest = sizeof(libpath) - 1 - (p - libpath);
-
-#define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
-#else
-#define RUBY_RELATIVE(path) (path)
-#endif
-#define incpush(path) rb_ary_push(load_path, rubylib_mangled_path2(path))
-    load_path = rb_vm_load_path();
-
-    if (rb_safe_level() == 0) {
-	ruby_incpush(getenv("RUBYLIB"));
-    }
-
-#ifdef RUBY_SEARCH_PATH
-    incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH));
-#endif
-
-    incpush(RUBY_RELATIVE(RUBY_SITE_LIB2));
-#ifdef RUBY_SITE_THIN_ARCHLIB
-    incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB));
-#endif
-    incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB));
-    incpush(RUBY_RELATIVE(RUBY_SITE_LIB));
-
-    incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB2));
-#ifdef RUBY_VENDOR_THIN_ARCHLIB
-    incpush(RUBY_RELATIVE(RUBY_VENDOR_THIN_ARCHLIB));
-#endif
-    incpush(RUBY_RELATIVE(RUBY_VENDOR_ARCHLIB));
-    incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB));
-
-    incpush(RUBY_RELATIVE(RUBY_LIB));
-#ifdef RUBY_THIN_ARCHLIB
-    incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB));
-#endif
-    incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
-
-    if (rb_safe_level() == 0) {
-	incpush(".");
-    }
-#endif // !MACRUBY_STATIC
-}
-
-void
-ruby_set_argv(int argc, char **argv)
-{
-    int i;
-    VALUE av = rb_argv;
-
-    rb_ary_clear(av);
-    for (i = 0; i < argc; i++) {
-	VALUE arg = rb_tainted_str_new2(argv[i]);
-
-	OBJ_FREEZE(arg);
-	rb_ary_push(av, arg);
-    }
-}
-
-void
-ruby_script(const char *name)
-{
-    if (name != NULL) {
-	GC_RELEASE(rb_progname);
-	rb_progname = rb_tainted_str_new2(name);
-	GC_RETAIN(rb_progname);
-    }
-}
-
-static void
-verbose_setter(VALUE val, ID id, VALUE *variable)
-{
-    ruby_verbose = RTEST(val) ? Qtrue : val;
-}
-
-static VALUE
-opt_W_getter(VALUE val, ID id)
-{
-    if (ruby_verbose == Qnil) {
-	return INT2FIX(0);
-    }
-    if (ruby_verbose == Qfalse) {
-	return INT2FIX(1);
-    }
-    if (ruby_verbose == Qtrue) {
-	return INT2FIX(2);
-    }
-    return Qnil; // not reached
-}
-
-static void
-set_arg0(VALUE val, ID id)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError,
-	    "changing program name is not supported in MacRuby static");
-#else
-    const char *s;
-    long i;
-
-    if (origarg.argv == 0) {
-	rb_raise(rb_eRuntimeError, "$0 not initialized");
-    }
-    StringValue(val);
-    s = RSTRING_PTR(val);
-    i = RSTRING_LEN(val);
-#if defined(PSTAT_SETCMD)
-    if (i > PST_CLEN) {
-	union pstun un;
-	char buf[PST_CLEN + 1];	/* PST_CLEN is 64 (HP-UX 11.23) */
-	strncpy(buf, s, PST_CLEN);
-	buf[PST_CLEN] = '\0';
-	un.pst_command = buf;
-	pstat(PSTAT_SETCMD, un, PST_CLEN, 0, 0);
-    }
-    else {
-	union pstun un;
-	un.pst_command = s;
-	pstat(PSTAT_SETCMD, un, i, 0, 0);
-    }
-#elif defined(HAVE_SETPROCTITLE)
-    setproctitle("%.*s", (int)i, s);
-#else
-
-    if (i >= origarg.len) {
-	i = origarg.len;
-    }
-
-    memcpy(origarg.argv[0], s, i);
-
-    {
-	int j;
-	char *t = origarg.argv[0] + i;
-	*t = '\0';
-
-	if (i + 1 < origarg.len) memset(t + 1, ' ', origarg.len - i - 1);
-	for (j = 1; j < origarg.argc; j++) {
-	    origarg.argv[j] = t;
-	}
-    }
-#endif
-    GC_RELEASE(rb_progname);
-    rb_progname = rb_tainted_str_new(s, i);
-    GC_RETAIN(rb_progname);
-#endif // !MACRUBY_STATIC
-}
-
-void
-ruby_prog_init(void)
-{
-    init_ids();
-
-    rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
-    rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
-    rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
-    rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter);
-    rb_define_variable("$DEBUG", &ruby_debug);
-    rb_define_variable("$-d", &ruby_debug);
-
-    rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
-    rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
-
-    rb_define_global_const("ARGV", rb_argv);
-
-    rb_vm_set_running(true);
-}
-

Deleted: MacRuby/trunk/ruby_deploy.1
===================================================================
--- MacRuby/trunk/ruby_deploy.1	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/ruby_deploy.1	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,43 +0,0 @@
-.Dd Mac 20, 2010
-.Dt MACRUBY_DEPLOY 1
-.Os
-.Sh NAME
-.Nm macruby_deploy
-.Nd Embed the MacRuby runtime inside an application bundle
-.Sh SYNOPSIS
-.Nm macruby_deploy
-.Op Ar options
-.Ar application-bundle
-.Sh DESCRIPTION
-.Nm macruby_deploy
-is a command-line tool that embeds the MacRuby runtime inside a specific application bundle, thus allowing the deployment of the application on computers that do not have MacRuby installed.
-.Sh OPTIONS
-.Nm macruby_deploy
-accepts the following arguments:
-.Bl -tag -width "123"
-.It Fl -compile
-Compile the bundle source code
-.It Fl -embed
-Embed MacRuby inside the bundle
-.It Fl -no-stdlib
-Do not embed the standard library (creates smaller bundles)
-.It Fl -stdlib Ar lib
-Embed only
-.Ar lib
-from the standard library
-.It Fl -gem Ar gem
-Embed
-.Ar gem
-and its dependencies
-.It Fl -bs
-Embed the BridgeSupport system files
-.It Fl -verbose
-Log actions to standard out
-.It Fl v , Fl -version
-Display the version
-.El
-.Sh SEE ALSO
-.Xr macruby 1 ,
-.Xr macirb 1 ,
-.Xr macrubyc 1 ,
-.Xr macrubyd 1

Deleted: MacRuby/trunk/rubyc.1
===================================================================
--- MacRuby/trunk/rubyc.1	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/rubyc.1	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,162 +0,0 @@
-.Dd December 16, 2009
-.Dt MACRUBYC 1
-.Os
-.Sh NAME
-.Nm macrubyc
-.Nd MacRuby Ahead-of-Time Compiler
-.Sh SYNOPSIS
-.Nm macrubyc
-.Op Ar options...
-.Ar files...
-.Sh DESCRIPTION
-.Nm macrubyc
-is a command-line interface to the MacRuby Ahead-of-Time (AOT) compiler. It statically compiles Ruby source code into native machine code (object files), and can then link it (dynamically or statically) into executables or dynamic libraries.  It is typically invoked from
-.Nm ruby_deploy
-rather than being called directly.
-.Pp
-The Ahead-of-Time compilation process has two major advantages. The Ruby code does not need to be parsed and compiled at runtime, which improves the startup time of the program, and the original Ruby source code is no longer available, as it has been compiled down to machine code.
-.Pp
-.Nm macrubyc
-allows the compilation of Ruby programs that will use the MacRuby dynamic runtime, supporting the entire Ruby specifications set. It also permits static compilation of Ruby code into a standalone executable that embeds a static version of the MacRuby runtime. These executables can be deployed on environments where MacRuby is not installed, but some features of the Ruby language are not supported.
-.Sh OPTIONS
-The
-.Nm macrubyc
-tool accepts the following command-line options:
-.Bl -tag -width "123" -compact
-.Pp
-.It Fl a Ar arch , Fl -arch Ar arch
-Compile for specified CPU architecture. By default,
-.Nm macrubyc
-will compile for the current architecture. This option will compile for a different architecture. When this option is provided more than once,
-.Nm macrubyc
-will create a universal binary. At the time of this writing, only the i386 and x86_64 architectures are supported.
-.Pp
-.It Fl c
-Compile and assemble, but do not link. This option produces a Mach-O object file (.o) for every Ruby source file passed to
-.Nm macrubyc ,
-using a default file name which consists of the source file name with the .o file extension. Such a file can later be passed to
-.Nm macrubyc
-to create a dynamic library or executable.
-.Pp
-.It Fl C
-Compile, assemble, and link a loadable object file. This option produces a Mach-O MacRuby loadable object bundle (.rbo) for every Ruby source file passed to
-.Nm macrubyc ,
-using a default file name which consists of the source file name with the .rbo file extension. A MacRuby loadable object is a Mach-O bundle, compiled with a global constructor that will evaluate the Ruby machine code once it's loaded by the dynamic linker, at runtime, generally upon a call to Ruby's 
-.Nm require
-method.
-.Pp
-.It Fl h, Fl -help
-Display a short description of the command line options.
-.Pp
-.It Fl o Ar file
-Place the output into
-.Ar file .
-If this option is not given, 
-.Nm macrubyc
-will try to determine a default output file name based on the object file type that is being generated. For executables, the default is a.out. For objects, the default is the original source file name with the object type extension. For dynamic libraries, this option is mandatory.
-.Pp
-.It Fl -dylib
-Create a dynamic library instead of an executable. This option compiles every Ruby source file passed to 
-.Nm macrubyc
-and produces a Mach-O dynamic library (.dylib). This library is compiled with a global constructor that will register every Ruby machine code file into the MacRuby runtime once it's loaded by the dynamic linker, at runtime. This library is intended to be linked against an executable that uses the MacRuby runtime, for example executables generated by
-.Nm macrubyc .
-The
-.Fl o
-option must be provided when building dynamic libraries.
-.Pp
-.Bl -tag -width XXXXXXXXXX
-The
-.Fl -dylib
-option can also take the following optional linker arguments (see
-.Xr libtool 1
-for more information):
-.It Fl -compatibility_version Ar VERSION
-.It Fl -current_version Ar VERSION
-.It Fl -install_name Ar NAME
-.El
-.Pp
-.It Fl -static
-Create a standalone, static executable. By default, executables created by
-.Nm macrubyc
-are dynamically linked against the MacRuby runtime. This option will generate executables that are statically linked against the MacRuby runtime, significantly increasing the binary size but allowing its distribution on environments where MacRuby is not installed. This option can only be used when creating executables. Some features of the Ruby language are disabled when using this option.
-.Pp
-.It Fl -framework Ar name
-Use a given framework during compilation and link. This also activates pre-compilation of the BridgeSupport metadata in the generated binary. This option is only used with --static. The Foundation framework is pre-included.
-.Pp
-.It Fl -sdk Ar path
-Use a given SDK during compilation and link. This option is useful when cross-compiling MacRuby programs for different platform versions. This option is only used with --static.
-.Pp
-.It Fl v, Fl -version
-Display the version.
-.Pp
-.It Fl V, Fl -verbose
-Print every command line executed by
-.Nm macrubyc .
-This option is generally used for internal debugging.
-.El
-.Sh EXAMPLES
-When used without options,
-.Nm macrubyc
-will create a binary executable, like the C compiler.
-.Pp
-.Dl $ echo """p 42""" > test.rb
-.Dl $ macrubyc test.rb
-.Dl $ ./a.out
-.Pp
-When building an executable, the very first file passed to
-.Nm macrubyc
-will be considered as the main file. Its machine code will be run once the executable starts. Other machine code files will be linked into the executable, but only run upon calls to the 
-.Nm require
-method.
-.Pp
-.Dl $ echo """def t1; 21; end""" > t1.rb
-.Dl $ echo """def t2; 21; end""" > t2.rb
-.Dl $ echo """require 't1'; require 't2'; p t1+t2""" > test.rb
-.Dl $ macrubyc test.rb t1.rb t2.rb -o test
-.Dl $ ./test
-.Pp
-.Nm macrubyc
-is also able to generate a dynamic library (.dylib) out of Ruby source files, using the
-.Fl -dylib
-option. Such a library can later be linked against an executable that uses the MacRuby runtime. Like executables, the Ruby machine code files will run upon calls to the 
-.Nm require
-method. Libraries can also be passed to
-.Nm macrubyc
-when forming an executable, allowing the compilation of multiple executables sharing common code.
-.Pp
-.Dl $ macrubyc t1.rb t2.rb -o code.dylib --dylib
-.Dl $ macrubyc test.rb code.dylib -o test
-.Dl $ ./test
-.Pp
-It is possible to statically compile MacRuby code into a standalone executable. The resulted binary includes the MacRuby static runtime and therefore can be executed on environments where MacRuby is not installed. Please note that the static runtime disables some features of the Ruby language.
-.Pp
-.Dl $ macrubyc test.rb -o test --static
-.Pp
-Static compilation may require --framework and --sdk flags depending of your project.
-.Pp
-.Sh USAGE
-Generally, you should use
-.Nm macruby
-and
-.Nm macirb
-during development, and
-.Nm macruby_deploy
-(via the Xcode target) when deploying Cocoa applications.  However, calling
-.Nm macrubyc
-provides greater control, and allows you to create libraries and standalone executables. 
-.Pp
-The easiest way to compile an existing project is to generate loadable object bundles for every Ruby source file, e.g., using the
-.Fl C
-option and the find command:
-.Pp
-.Dl $ find ./lib -name """*.rb""" -exec macrubyc -C {} \e;
-.Pp
-This creates bundles with the .rbo file extension in the same directory as the original .rb source files. The MacRuby runtime will always pick .rbo files over .rb files upon calls to the 
-.Nm require
-method. The source files can then be removed. 
-.Pp
-.Sh SEE ALSO
-.Xr macruby 1 ,
-.Xr macirb 1 ,
-.Xr macrubyd 1 ,
-.Xr macruby_deploy 1

Deleted: MacRuby/trunk/rubyd.1
===================================================================
--- MacRuby/trunk/rubyd.1	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/rubyd.1	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,24 +0,0 @@
-.Dd May 20, 2010
-.Dt MACRUBYD 1
-.Os
-.Sh NAME
-.Nm macrubyd
-.Nd MacRuby Debugger
-.Sh SYNOPSIS
-.Nm macrubyd
-.Ar path_to_ruby_file
-.Op Ar arguments...
-.Sh DESCRIPTION
-.Nm macrubyd
-can be used to debug your MacRuby scripts
-.Pp
-Please run
-.Ar help
-within
-.Nm macrubyd
-to get the list of available commands
-.Sh SEE ALSO
-.Xr macruby 1 ,
-.Xr macirb 1 ,
-.Xr macrubyc 1 ,
-.Xr macruby_deploy 1

Deleted: MacRuby/trunk/rubytest.rb
===================================================================
--- MacRuby/trunk/rubytest.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/rubytest.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,49 +0,0 @@
-#! ./miniruby
-
-exit if defined?(CROSS_COMPILING)
-load './rbconfig.rb'
-include RbConfig
-
-ruby = "./#{CONFIG['ruby_install_name']}#{CONFIG['EXEEXT']}"
-unless File.exist? ruby
-  print "#{ruby} is not found.\n"
-  print "Try `make' first, then `make test', please.\n"
-  exit false
-end
-
-if File.exist? CONFIG['LIBRUBY_SO']
-  case RUBY_PLATFORM
-  when /-hpux/
-    dldpath = "SHLIB_PATH"
-  when /-aix/
-    dldpath = "LIBPATH"
-  when /-beos/
-    dldpath = "LIBRARY_PATH"
-  when /-darwin/
-    dldpath = "DYLD_LIBRARY_PATH"
-  else
-    dldpath = "LD_LIBRARY_PATH"
-  end
-  x = ENV[dldpath]
-  x = x ? ".:"+x : "."
-  ENV[dldpath] = x
-end
-
-if /linux/ =~ RUBY_PLATFORM and File.exist? CONFIG['LIBRUBY_SO']
-  ENV["LD_PRELOAD"] = "./#{CONFIG['LIBRUBY_SO']}"
-end
-
-$stderr.reopen($stdout)
-error = ''
-
-srcdir = File.dirname(__FILE__)
-`#{ruby} -I.ext/#{RUBY_PLATFORM} -I#{srcdir}/lib #{srcdir}/sample/test.rb`.each_line do |line|
-  if line =~ /^end of test/
-    print "\ntest succeeded\n"
-    exit true
-  end
-  error << line if %r:^(sample/test.rb|not): =~ line
-end
-print error
-print "test failed\n"
-exit false

Deleted: MacRuby/trunk/runruby.rb
===================================================================
--- MacRuby/trunk/runruby.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/runruby.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,71 +0,0 @@
-#!./miniruby
-
-pure = true
-while arg = ARGV[0]
-  break ARGV.shift if arg == '--'
-  /\A--([-\w]+)(?:=(.*))?\z/ =~ arg or break
-  arg, value = $1, $2
-  re = Regexp.new('\A'+arg.gsub(/\w+\b/, '\&\\w*')+'\z', "i")
-  case
-  when re =~ "srcdir"
-    srcdir = value
-  when re =~ "archdir"
-    archdir = value
-  when re =~ "extout"
-    extout = value
-  when re =~ "pure"
-    pure = (value != "no")
-  when re =~ "debugger"
-    debugger = value ? (value.split unless value == "no") : %w"gdb --args"
-  else
-    break
-  end
-  ARGV.shift
-end
-
-srcdir ||= File.dirname(__FILE__)
-archdir ||= '.'
-
-abs_archdir = File.expand_path(archdir)
-$:.unshift(abs_archdir)
-
-require 'rbconfig'
-config = RbConfig::CONFIG
-
-ruby = File.join(archdir, config["RUBY_INSTALL_NAME"]+config['EXEEXT'])
-unless File.exist?(ruby)
-  abort "#{ruby} is not found.\nTry `make' first, then `make test', please.\n"
-end
-
-libs = [abs_archdir]
-if extout
-  abs_extout = File.expand_path(extout)
-  libs << File.expand_path("common", abs_extout) << File.expand_path(RUBY_PLATFORM, abs_extout)
-end
-libs << File.expand_path("lib", srcdir)
-config["bindir"] = abs_archdir
-ENV["RUBY"] = File.expand_path(ruby)
-ENV["PATH"] = [abs_archdir, ENV["PATH"]].compact.join(File::PATH_SEPARATOR)
-
-if pure
-  libs << File.expand_path("ext", srcdir) << "-"
-elsif e = ENV["RUBYLIB"]
-  libs |= e.split(File::PATH_SEPARATOR)
-end
-ENV["RUBYLIB"] = $:.replace(libs).join(File::PATH_SEPARATOR)
-
-libruby_so = File.join(abs_archdir, config['LIBRUBY_SO'])
-if File.file?(libruby_so)
-  if e = config['LIBPATHENV'] and !e.empty?
-    ENV[e] = [abs_archdir, ENV[e]].compact.join(File::PATH_SEPARATOR)
-  end
-  if /linux/ =~ RUBY_PLATFORM
-    ENV["LD_PRELOAD"] = [libruby_so, ENV["LD_PRELOAD"]].compact.join(' ')
-  end
-end
-
-cmd = [ruby]
-cmd << "-rpurelib.rb" if pure
-cmd.concat(ARGV)
-cmd.unshift(*debugger) if debugger
-exec(*cmd)

Deleted: MacRuby/trunk/sandbox.c
===================================================================
--- MacRuby/trunk/sandbox.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/sandbox.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,110 +0,0 @@
-/* 
- * MacRuby interface to sandbox/seatbelt.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2011, Apple Inc. All rights reserved.
- */
-
-#include <sandbox.h>
-#include "macruby_internal.h"
-#include "ruby/util.h"
-
-static VALUE rb_cSandbox;
-
-typedef struct {
-    const char *profile;
-    uint64_t flags;
-} rb_sandbox_t;
-
-static VALUE
-rb_sandbox_s_alloc(VALUE klass, SEL sel)
-{
-    rb_sandbox_t *sb = ALLOC(rb_sandbox_t);
-    sb->profile = NULL;
-    sb->flags = 0;
-    return Data_Wrap_Struct(klass, NULL, NULL, sb);
-}
-
-static VALUE
-rb_sandbox_init(VALUE obj, SEL sel, VALUE profile)
-{
-    rb_sandbox_t *box;
-
-    StringValue(profile);
-    Data_Get_Struct(obj, rb_sandbox_t, box);
-    GC_WB(&box->profile, ruby_strdup(RSTRING_PTR(profile)));
-    box->flags = 0;
-
-    return obj;
-}
-
-
-static inline VALUE
-predefined_sandbox(const char *name)
-{
-    VALUE obj = rb_sandbox_s_alloc(rb_cSandbox, 0);
-    rb_sandbox_t *box; 
-    Data_Get_Struct(obj, rb_sandbox_t, box);
-    box->profile = name;
-    box->flags = SANDBOX_NAMED;
-    return rb_obj_freeze(obj);
-}
-
-static VALUE
-rb_sandbox_s_no_internet(VALUE klass, SEL sel)
-{
-    return predefined_sandbox(kSBXProfileNoInternet);
-}
-
-static VALUE
-rb_sandbox_s_no_network(VALUE klass, SEL sel)
-{
-    return predefined_sandbox(kSBXProfileNoNetwork); 
-}
-
-static VALUE
-rb_sandbox_s_no_writes(VALUE klass, SEL sel)
-{
-    return predefined_sandbox(kSBXProfileNoWrite);
-}
-
-static VALUE
-rb_sandbox_s_temporary_writes(VALUE klass, SEL sel)
-{
-    return predefined_sandbox(kSBXProfileNoWriteExceptTemporary);
-}
-
-static VALUE
-rb_sandbox_s_pure_computation(VALUE klass, SEL sel)
-{
-    return predefined_sandbox(kSBXProfilePureComputation);
-}
-
-static VALUE
-rb_sandbox_apply(VALUE self, SEL sel)
-{
-    rb_sandbox_t *box;
-    Data_Get_Struct(self, rb_sandbox_t, box);
-    char *error = NULL;
-    if (sandbox_init(box->profile, box->flags, &error) == -1) {
-        rb_raise(rb_eSecurityError, "Couldn't apply sandbox: `%s`", error);
-    }
-    return Qnil;
-}
-
-void
-Init_sandbox(void)
-{
-    rb_cSandbox = rb_define_class("Sandbox", rb_cData);
-    
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "alloc", rb_sandbox_s_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "no_internet", rb_sandbox_s_no_internet, 0);
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "no_network", rb_sandbox_s_no_network, 0);
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "no_writes", rb_sandbox_s_no_writes, 0);
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "temporary_writes", rb_sandbox_s_temporary_writes, 0);
-    rb_objc_define_method(*(VALUE *)rb_cSandbox, "pure_computation", rb_sandbox_s_pure_computation, 0);
-    
-    rb_objc_define_method(rb_cSandbox, "initialize", rb_sandbox_init, 1);
-    rb_objc_define_method(rb_cSandbox, "apply!", rb_sandbox_apply, 0);
-}

Deleted: MacRuby/trunk/signal.c
===================================================================
--- MacRuby/trunk/signal.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/signal.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,734 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-// TODO: rewrite me!
-
-#include "macruby_internal.h"
-#include "ruby/signal.h"
-#include "ruby/node.h"
-#include "id.h"
-#include "vm.h"
-#include <signal.h>
-#include <stdio.h>
-
-#define USE_DEFAULT_HANDLER (void (*)(int))-1
-
-static RETSIGTYPE sighandler(int sig);
-
-static const struct signals {
-    const char *signm;
-    int  signo;
-} siglist [] = {
-    {"EXIT",   0},
-    {"HUP",    SIGHUP},
-    {"INT",    SIGINT},
-    {"QUIT",   SIGQUIT},
-    {"ILL",    SIGILL},
-    {"TRAP",   SIGTRAP},
-    {"IOT",    SIGIOT},
-    {"ABRT",   SIGABRT},
-    {"EMT",    SIGEMT},
-    {"FPE",    SIGFPE},
-    {"KILL",   SIGKILL},
-    {"BUS",    SIGBUS},
-    {"SEGV",   SIGSEGV},
-    {"SYS",    SIGSYS},
-    {"PIPE",   SIGPIPE},
-    {"ALRM",   SIGALRM},
-    {"TERM",   SIGTERM},
-    {"URG",    SIGURG},
-    {"STOP",   SIGSTOP},
-    {"TSTP",   SIGTSTP},
-    {"CONT",   SIGCONT},
-    {"CHLD",   SIGCHLD},
-    {"CLD",    SIGCHLD},
-    {"TTIN",   SIGTTIN},
-    {"TTOU",   SIGTTOU},
-    {"IO",     SIGIO},
-    {"XCPU",   SIGXCPU},
-    {"XFSZ",   SIGXFSZ},
-    {"VTALRM", SIGVTALRM},
-    {"PROF",   SIGPROF},
-    {"WINCH",  SIGWINCH},
-    {"INFO",   SIGINFO},
-    {"USR1",   SIGUSR1},
-    {"USR2",   SIGUSR2},
-    {NULL, 0}
-};
-
-static const struct trap_handlers {
-    const char   *command;
-    VALUE        new_cmd_value;
-    sighandler_t handler;
-} gl_trap_handlers[] = {
-    {"SYSTEM_DEFAULT", 0,      SIG_DFL},
-    {"SIG_IGN",        0,      SIG_IGN},
-    {"IGNORE",         0,      SIG_IGN},
-    {"",               0,      SIG_IGN},
-    {"SIG_DFL",        0,      USE_DEFAULT_HANDLER},
-    {"DEFAULT",        0,      USE_DEFAULT_HANDLER},
-    {"EXIT",           Qundef, sighandler},
-    {NULL, 0}
- };
-
-static int
-signm2signo(const char *nm)
-{
-    const struct signals *sigs;
-
-    for (sigs = siglist; sigs->signm; sigs++)
-	if (strcmp(sigs->signm, nm) == 0)
-	    return sigs->signo;
-    return 0;
-}
-
-static const char*
-signo2signm(int no)
-{
-    const struct signals *sigs;
-
-    for (sigs = siglist; sigs->signm; sigs++)
-	if (sigs->signo == no)
-	    return sigs->signm;
-    return 0;
-}
-
-const char *
-ruby_signal_name(int no)
-{
-    return signo2signm(no);
-}
-
-/*
- * call-seq:
- *    SignalException.new(sig)   =>  signal_exception
- *
- *  Construct a new SignalException object.  +sig+ should be a known
- *  signal name, or a signal number.
- */
-
-static VALUE
-esignal_init(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    int argnum = 1;
-    VALUE sig = Qnil;
-    int signo;
-    const char *signm;
-
-    if (argc > 0) {
-	sig = rb_check_to_integer(argv[0], "to_int");
-	if (!NIL_P(sig)) argnum = 2;
-	else sig = argv[0];
-    }
-    if (argc < 1 || argnum < argc) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		 argc, argnum);
-    }
-    if (argnum == 2) {
-	signo = NUM2INT(sig);
-	if (signo < 0 || signo > NSIG) {
-	    rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
-	}
-	if (argc > 1) {
-	    sig = argv[1];
-	}
-	else {
-	    signm = signo2signm(signo);
-	    if (signm) {
-		sig = rb_sprintf("SIG%s", signm);
-	    }
-	    else {
-		sig = rb_sprintf("SIG%u", signo);
-	    }
-	}
-    }
-    else {
-	signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
-	if (strncmp(signm, "SIG", 3) == 0) signm += 3;
-	signo = signm2signo(signm);
-	if (!signo) {
-	    rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
-	}
-	sig = rb_sprintf("SIG%s", signm);
-    }
-    rb_vm_call_super(self, selInitialize2, 1, &sig);
-    rb_iv_set(self, "signo", INT2NUM(signo));
-
-    return self;
-}
-
-/*
- * call-seq:
- *    signal_exception.signo   =>  num
- *
- *  Returns a signal number.
- */
-
-static VALUE
-esignal_signo(VALUE self, SEL sel)
-{
-    return rb_iv_get(self, "signo");
-}
-
-static VALUE
-interrupt_init(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE args[2];
-
-    args[0] = INT2FIX(SIGINT);
-    rb_scan_args(argc, argv, "01", &args[1]);
-    return rb_vm_call_super(self, selInitialize2, 2, args);
-}
-
-void
-ruby_default_signal(int sig)
-{
-#ifndef MACOS_UNUSE_SIGNAL
-    signal(sig, SIG_DFL);
-    raise(sig);
-#endif
-}
-
-/*
- *  call-seq:
- *     Process.kill(signal, pid, ...)    => fixnum
- *  
- *  Sends the given signal to the specified process id(s), or to the
- *  current process if _pid_ is zero. _signal_ may be an
- *  integer signal number or a POSIX signal name (either with or without
- *  a +SIG+ prefix). If _signal_ is negative (or starts
- *  with a minus sign), kills process groups instead of
- *  processes. Not all signals are available on all platforms.
- *     
- *     pid = fork do
- *        Signal.trap("HUP") { puts "Ouch!"; exit }
- *        # ... do some work ...
- *     end
- *     # ...
- *     Process.kill("HUP", pid)
- *     Process.wait
- *     
- *  <em>produces:</em>
- *     
- *     Ouch!
- */
-
-VALUE
-rb_f_kill(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    int negative = 0;
-    int sig;
-    int i;
-    int type;
-    const char *s = NULL;
-
-    rb_secure(2);
-    if (argc < 2)
-	rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
-
-    type = TYPE(argv[0]);
-    if (type == T_FIXNUM) {
-	sig = FIX2INT(argv[0]);
-    }
-    else {
-	if (type == T_SYMBOL) {
-	    s = rb_sym2name(argv[0]);
-	    if (!s)
-		rb_raise(rb_eArgError, "bad signal");
-	}
-	else if (type == T_STRING) {
-	    s = RSTRING_PTR(argv[0]);
-	    if (s[0] == '-') {
-		negative++;
-		s++;
-	    }
-	}
-	else {
-	    VALUE str;
-	    str = rb_check_string_type(argv[0]);
-	    if (!NIL_P(str)) {
-		s = RSTRING_PTR(str);
-	    }
-	}
-	if (s == NULL)
-	    rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0]));
-
-	if (strncmp("SIG", s, 3) == 0)
-	    s += 3;
-	if ((sig = signm2signo(s)) == 0)
-	    rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
-	if (negative)
-	    sig = -sig;
-    }
-
-    if (sig < 0) {
-	sig = -sig;
-	for (i = 1; i < argc; i++) {
-	    if (killpg(NUM2PIDT(argv[i]), sig) < 0)
-		rb_sys_fail(0);
-	}
-    }
-    else {
-	for (i = 1; i < argc; i++) {
-	    if (kill(NUM2PIDT(argv[i]), sig) < 0)
-		rb_sys_fail(0);
-	}
-    }
-    rb_thread_polling();
-    return INT2FIX(i - 1);
-}
-
-VALUE
-rb_get_trap_cmd(int sig)
-{
-    return rb_vm_trap_cmd_for_signal(sig);
-}
-
-sighandler_t
-ruby_signal(int signum, sighandler_t handler)
-{
-    struct sigaction sigact;
-    struct sigaction old;
-
-    sigemptyset(&sigact.sa_mask);
-    sigact.sa_handler = handler;
-    sigact.sa_flags = 0;
-
-    if (signum == SIGCHLD && handler == SIG_IGN)
-	sigact.sa_flags |= SA_NOCLDWAIT;
-    if (signum == SIGSEGV)
-	sigact.sa_flags |= SA_ONSTACK;
-    if (sigaction(signum, &sigact, &old) < 0) {
-	if (errno != 0 && errno != EINVAL) {
-	    rb_bug("sigaction error.\n");
-	}
-    }
-    return old.sa_handler;
-}
-
-sighandler_t
-posix_signal(int signum, sighandler_t handler)
-{
-    return ruby_signal(signum, handler);
-}
-
-static void signal_exec(VALUE cmd, int level, int sig);
-static void rb_signal_exec(int sig);
-
-static RETSIGTYPE
-sighandler(int sig)
-{
-    int olderrno = errno;
-    rb_signal_exec(sig);
-    ruby_signal(sig, sighandler);
-    errno = olderrno;
-}
-
-#include <pthread.h>
-
-void
-rb_disable_interrupt(void)
-{
-    sigset_t mask;
-    sigfillset(&mask);
-    sigdelset(&mask, SIGVTALRM);
-    sigdelset(&mask, SIGSEGV);
-    pthread_sigmask(SIG_SETMASK, &mask, NULL);
-}
-
-void
-rb_enable_interrupt(void)
-{
-    sigset_t mask;
-    sigemptyset(&mask);
-    pthread_sigmask(SIG_SETMASK, &mask, NULL);
-}
-
-static RETSIGTYPE
-sigpipe(int sig)
-{
-    /* do nothing */
-}
-
-static void
-signal_exec(VALUE cmd, int level, int sig)
-{
-    VALUE signum = INT2NUM(sig);
-    rb_eval_cmd(cmd, rb_ary_new3(1, signum), level);
-}
-
-void
-rb_trap_exit(void)
-{
-#if 0//ndef MACOS_UNUSE_SIGNAL
-    VALUE trap_exit;
-    int safe;
-
-    trap_exit = rb_vm_trap_cmd_for_signal(0);
-    if (trap_exit != (VALUE)NULL) {
-	safe = rb_vm_trap_level_for_signal(0);
-	rb_vm_set_trap_for_signal((VALUE)0, safe, 0);
-	signal_exec(trap_exit, safe, 0);
-    }
-#endif
-}
-
-static void
-rb_signal_exec(int sig)
-{
-/*     rb_vm_thread_t *t; */
-/*     VALUE exc; */
-    VALUE cmd = rb_get_trap_cmd(sig);
-
-    if (cmd == 0) {
-	switch (sig) {
-	  case SIGINT:
-	    rb_interrupt();
-	    break;
-	  case SIGHUP:
-	  case SIGQUIT:
-	  case SIGTERM:
-	  case SIGALRM:
-	  case SIGUSR1:
-	  case SIGUSR2:
-/* 	    t = GetThreadPtr(rb_vm_main_thread()); */
-/* 	    exc = rb_exc_new2(rb_eSignal, ruby_signal_name(sig)); */
-/* 	    rb_vm_thread_raise(t, exc); */
-/* 	    rb_raise(rb_eSignal, "%s", signo2signm(sig)); */
-	    break;
-	}
-    }
-    else if (cmd == Qundef) {
-	//rb_thread_signal_exit(th);
-    }
-    else {
-	signal_exec(cmd, rb_vm_trap_level_for_signal(sig), sig);
-    }
-}
-
-struct trap_arg {
-    int sig;
-    sighandler_t func;
-    VALUE cmd;
-};
-
-static sighandler_t
-default_handler(int sig)
-{
-    sighandler_t func;
-    switch (sig) {
-      case SIGINT:
-      case SIGHUP:
-      case SIGQUIT:
-      case SIGTERM:
-      case SIGALRM:
-      case SIGUSR1:
-      case SIGUSR2:
-        func = sighandler;
-        break;
-      case SIGPIPE:
-        func = sigpipe;
-        break;
-      default:
-        func = SIG_DFL;
-        break;
-    }
-
-    return func;
-}
-
-static sighandler_t
-trap_handler(VALUE *cmd, int sig)
-{
-    sighandler_t func = sighandler;
-    VALUE command;
-
-    if (NIL_P(*cmd)) {
-	func = SIG_IGN;
-    }
-    else {
-	command = rb_check_string_type(*cmd);
-	if (NIL_P(command) && SYMBOL_P(*cmd)) {
-	    command = rb_id2str(SYM2ID(*cmd));
-	    if (!command) rb_raise(rb_eArgError, "bad handler");
-	}
-	if (!NIL_P(command)) {
-	    SafeStringValue(command);	/* taint check */
-	    *cmd = command;
-	    for (int i = 0; gl_trap_handlers[i].command != NULL; i++) {
-		if (strcmp(gl_trap_handlers[i].command, RSTRING_PTR(command)) == 0) {
-		    func = gl_trap_handlers[i].handler;
-		    if (func == USE_DEFAULT_HANDLER) {
-			func = default_handler(sig);
-		    }
-		    *cmd = gl_trap_handlers[i].new_cmd_value;
-		    break;
-		}
-	    }
-	}
-	else {
-/* 	    func = sighandler; */
-	}
-    }
-
-    return func;
-}
-
-static int
-trap_signm(VALUE vsig)
-{
-    int sig = -1;
-    const char *s;
-
-    if (TYPE(vsig) == T_FIXNUM) {
-	sig = FIX2INT(vsig);
-	if (sig < 0 || sig >= NSIG) {
-	    rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
-	}
-    }
-    else {
-	if (TYPE(vsig) == T_SYMBOL) {
-	    s = rb_sym2name(vsig);
-	    if (s == NULL)
-		rb_raise(rb_eArgError, "bad signal");
-	}
-	else
-	    s = StringValuePtr(vsig);
-
-	if (strncmp("SIG", s, 3) == 0)
-	    s += 3;
-	sig = signm2signo(s);
-	if (sig == 0 && strcmp(s, "EXIT") != 0)
-	    rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
-    }
-    return sig;
-}
-
-static VALUE
-trap(struct trap_arg *arg)
-{
-    sighandler_t oldfunc;
-    sighandler_t func = arg->func;
-    VALUE oldcmd;
-    VALUE command = arg->cmd;
-    int sig = arg->sig;
-
-    oldfunc = ruby_signal(sig, func);
-    oldcmd = rb_vm_trap_cmd_for_signal(sig);
-    if (oldcmd == 0) {
-	if (oldfunc == SIG_IGN)
-	    oldcmd = rb_str_new2("IGNORE");
-	else if (oldfunc == sighandler)
-	    oldcmd = rb_str_new2("DEFAULT");
-	else
-	    oldcmd = Qnil;
-    }
-    else if (oldcmd == Qundef)
-	oldcmd = rb_str_new2("EXIT");
-
-    // Assign trap to signal
-    rb_vm_set_trap_for_signal(command, rb_safe_level(), sig);
-
-    return oldcmd;
-}
-
-void
-rb_trap_restore_mask(void)
-{
-}
-
-/*
- * call-seq:
- *   Signal.trap( signal, command ) => obj
- *   Signal.trap( signal ) {| | block } => obj
- *
- * Specifies the handling of signals. The first parameter is a signal
- * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
- * signal number. The characters ``SIG'' may be omitted from the
- * signal name. The command or block specifies code to be run when the
- * signal is raised.
- * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
- * will be ignored.
- * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
- * will be invoked.
- * If the command is ``EXIT'', the script will be terminated by the signal.
- * If the command is ``SYSTEM_DEFAULT'', the operating system's default
- * handler will be invoked.
- * Otherwise, the given command or block will be run.
- * The special signal name ``EXIT'' or signal number zero will be
- * invoked just prior to program termination.
- * trap returns the previous handler for the given signal.
- *
- *     Signal.trap(0, proc { puts "Terminating: #{$$}" })
- *     Signal.trap("CLD")  { puts "Child died" }
- *     fork && Process.wait
- *
- * produces:
- *     Terminating: 27461
- *     Child died
- *     Terminating: 27460
- */
-
-static VALUE
-sig_trap(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    struct trap_arg arg;
-
-    rb_secure(2);
-    if (argc == 0 || argc > 2) {
-	rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
-    }
-
-    arg.sig = trap_signm(argv[0]);
-    if (argc == 1) {
-	arg.cmd = rb_block_proc();
-	arg.func = sighandler;
-    }
-    else {
-	arg.cmd = argv[1];
-	arg.func = trap_handler(&arg.cmd, arg.sig);
-    }
-
-    if (OBJ_TAINTED(arg.cmd)) {
-	rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
-    }
-
-    return trap(&arg);
-}
-
-/*
- * call-seq:
- *   Signal.list => a_hash
- *
- * Returns a list of signal names mapped to the corresponding
- * underlying signal numbers.
- *
- * Signal.list   #=> {"ABRT"=>6, "ALRM"=>14, "BUS"=>7, "CHLD"=>17, "CLD"=>17, "CONT"=>18, "FPE"=>8, "HUP"=>1, "ILL"=>4, "INT"=>2, "IO"=>29, "IOT"=>6, "KILL"=>9, "PIPE"=>13, "POLL"=>29, "PROF"=>27, "PWR"=>30, "QUIT"=>3, "SEGV"=>11, "STOP"=>19, "SYS"=>31, "TERM"=>15, "TRAP"=>5, "TSTP"=>20, "TTIN"=>21, "TTOU"=>22, "URG"=>23, "USR1"=>10, "USR2"=>12, "VTALRM"=>26, "WINCH"=>28, "XCPU"=>24, "XFSZ"=>25}
- */
-static VALUE
-sig_list(VALUE rcv, SEL sel)
-{
-    VALUE h = rb_hash_new();
-    const struct signals *sigs;
-
-    for (sigs = siglist; sigs->signm; sigs++) {
-	rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
-    }
-    return h;
-}
-
-static void
-install_sighandler(int signum, sighandler_t handler)
-{
-    sighandler_t old;
-
-    old = ruby_signal(signum, handler);
-    if (old != SIG_DFL) {
-	ruby_signal(signum, old);
-    }
-}
-
-#if defined(SIGCLD) || defined(SIGCHLD)
-static void
-init_sigchld(int sig)
-{
-    sighandler_t oldfunc;
-
-    oldfunc = ruby_signal(sig, SIG_DFL);
-    if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
-	ruby_signal(sig, oldfunc);
-    } else {
-	rb_vm_set_trap_for_signal((VALUE)0, rb_safe_level(), sig);
-    }
-}
-#endif
-
-void
-ruby_sig_finalize()
-{
-    sighandler_t oldfunc;
-
-    oldfunc = ruby_signal(SIGINT, SIG_IGN);
-    if (oldfunc == sighandler) {
-	ruby_signal(SIGINT, SIG_DFL);
-    }
-}
-
-#ifdef RUBY_DEBUG_ENV
-int ruby_enable_coredump = 0;
-#endif
-
-/*
- * Many operating systems allow signals to be sent to running
- * processes. Some signals have a defined effect on the process, while
- * others may be trapped at the code level and acted upon. For
- * example, your process may trap the USR1 signal and use it to toggle
- * debugging, and may use TERM to initiate a controlled shutdown.
- *
- *     pid = fork do
- *       Signal.trap("USR1") do
- *         $debug = !$debug
- *         puts "Debug now: #$debug"
- *       end
- *       Signal.trap("TERM") do
- *         puts "Terminating..."
- *         shutdown()
- *       end
- *       # . . . do some work . . .
- *     end
- *
- *     Process.detach(pid)
- *
- *     # Controlling program:
- *     Process.kill("USR1", pid)
- *     # ...
- *     Process.kill("USR1", pid)
- *     # ...
- *     Process.kill("TERM", pid)
- *
- * produces:
- *     Debug now: true
- *     Debug now: false
- *    Terminating...
- *
- * The list of available signal names and their interpretation is
- * system dependent. Signal delivery semantics may also vary between
- * systems; in particular signal delivery may not always be reliable.
- */
-void
-Init_signal(void)
-{
-#ifndef MACOS_UNUSE_SIGNAL
-    VALUE mSignal = rb_define_module("Signal");
-
-    rb_objc_define_module_function(rb_mKernel, "trap", sig_trap, -1);
-    rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
-    rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);
-
-    rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
-    rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
-    rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
-    rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
-
-/*     install_sighandler(SIGINT, sighandler); */
-/*     install_sighandler(SIGHUP, sighandler); */
-/*     install_sighandler(SIGQUIT, sighandler); */
-/*     install_sighandler(SIGTERM, sighandler); */
-/*     install_sighandler(SIGALRM, sighandler); */
-/*     install_sighandler(SIGUSR1, sighandler); */
-/*     install_sighandler(SIGUSR2, sighandler); */
-
-#ifdef RUBY_DEBUG_ENV
-    if (!ruby_enable_coredump)
-#endif
-    install_sighandler(SIGPIPE, sigpipe);
-
-    init_sigchld(SIGCHLD);
-#endif /* !MACOS_UNUSE_SIGNAL */
-}

Deleted: MacRuby/trunk/sprintf.c
===================================================================
--- MacRuby/trunk/sprintf.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/sprintf.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,880 +0,0 @@
-/*
- * MacRuby implementation of Ruby 1.9's sprintf.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- *
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include <stdarg.h>
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-
-/*
- *  call-seq:
- *     format(format_string [, arguments...] )   => string
- *     sprintf(format_string [, arguments...] )  => string
- *  
- *  Returns the string resulting from applying <i>format_string</i> to
- *  any additional arguments.  Within the format string, any characters
- *  other than format sequences are copied to the result. 
- *
- *  The syntax of a format sequence is follows.
- *
- *    %[flags][width][.precision]type
- *
- *  A format
- *  sequence consists of a percent sign, followed by optional flags,
- *  width, and precision indicators, then terminated with a field type
- *  character.  The field type controls how the corresponding
- *  <code>sprintf</code> argument is to be interpreted, while the flags
- *  modify that interpretation.
- *
- *  The field type characters are:
- *
- *      Field |  Integer Format
- *      ------+--------------------------------------------------------------
- *        b   | Convert argument as a binary number.
- *            | Negative numbers will be displayed as a two's complement
- *            | prefixed with `..1'.
- *        B   | Equivalent to `b', but uses an uppercase 0B for prefix
- *            | in the alternative format by #.
- *        d   | Convert argument as a decimal number.
- *        i   | Identical to `d'.
- *        o   | Convert argument as an octal number.
- *            | Negative numbers will be displayed as a two's complement
- *            | prefixed with `..7'.
- *        u   | Identical to `d'.
- *        x   | Convert argument as a hexadecimal number.
- *            | Negative numbers will be displayed as a two's complement
- *            | prefixed with `..f' (representing an infinite string of
- *            | leading 'ff's).
- *        X   | Equivalent to `x', but uses uppercase letters.
- *
- *      Field |  Float Format
- *      ------+--------------------------------------------------------------
- *        e   | Convert floating point argument into exponential notation 
- *            | with one digit before the decimal point as [-]d.dddddde[+-]dd.
- *            | The precision specifies the number of digits after the decimal
- *            | point (defaulting to six).
- *        E   | Equivalent to `e', but uses an uppercase E to indicate
- *            | the exponent.
- *        f   | Convert floating point argument as [-]ddd.dddddd, 
- *            | where the precision specifies the number of digits after
- *            | the decimal point.
- *        g   | Convert a floating point number using exponential form
- *            | if the exponent is less than -4 or greater than or
- *            | equal to the precision, or in dd.dddd form otherwise.
- *            | The precision specifies the number of significant digits.
- *        G   | Equivalent to `g', but use an uppercase `E' in exponent form.
- *
- *      Field |  Other Format
- *      ------+--------------------------------------------------------------
- *        c   | Argument is the numeric code for a single character or
- *            | a single character string itself.
- *        p   | The valuing of argument.inspect.
- *        s   | Argument is a string to be substituted.  If the format
- *            | sequence contains a precision, at most that many characters
- *            | will be copied.
- *     
- *  The flags modifies the behavior of the formats.
- *  The flag characters are:
- *
- *    Flag     | Applies to    | Meaning
- *    ---------+---------------+-----------------------------------------
- *    space    | bBdiouxX      | Leave a space at the start of 
- *             | eEfgG         | non-negative numbers.
- *             | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- *             |               | a minus sign with absolute value for
- *             |               | negative values.
- *    ---------+---------------+-----------------------------------------
- *    (digit)$ | all           | Specifies the absolute argument number
- *             |               | for this field.  Absolute and relative
- *             |               | argument numbers cannot be mixed in a
- *             |               | sprintf string.
- *    ---------+---------------+-----------------------------------------
- *     #       | bBoxX         | Use an alternative format.
- *             | eEfgG         | For the conversions `o', increase the precision
- *             |               | until the first digit will be `0' if
- *             |               | it is not formatted as complements.
- *             |               | For the conversions `x', `X', `b' and `B'
- *             |               | on non-zero, prefix the result with ``0x'',
- *             |               | ``0X'', ``0b'' and ``0B'', respectively.
- *             |               | For `e', `E', `f', `g', and 'G',
- *             |               | force a decimal point to be added,
- *             |               | even if no digits follow.
- *             |               | For `g' and 'G', do not remove trailing zeros.
- *    ---------+---------------+-----------------------------------------
- *    +        | bBdiouxX      | Add a leading plus sign to non-negative
- *             | eEfgG         | numbers.
- *             | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- *             |               | a minus sign with absolute value for
- *             |               | negative values.
- *    ---------+---------------+-----------------------------------------
- *    -        | all           | Left-justify the result of this conversion.
- *    ---------+---------------+-----------------------------------------
- *    0 (zero) | bBdiouxX      | Pad with zeros, not spaces.
- *             | eEfgG         | For `o', `x', `X', `b' and `B', radix-1
- *             | (numeric fmt) | is used for negative numbers formatted as
- *             |               | complements.
- *    ---------+---------------+-----------------------------------------
- *    *        | all           | Use the next argument as the field width. 
- *             |               | If negative, left-justify the result. If the
- *             |               | asterisk is followed by a number and a dollar 
- *             |               | sign, use the indicated argument as the width.
- *
- *  Examples of flags:
- *
- *   # `+' and space flag specifies the sign of non-negative numbers.
- *   sprintf("%d", 123)  #=> "123"
- *   sprintf("%+d", 123) #=> "+123"
- *   sprintf("% d", 123) #=> " 123"
- *
- *   # `#' flag for `o' increases number of digits to show `0'.
- *   # `+' and space flag changes format of negative numbers.
- *   sprintf("%o", 123)   #=> "173"
- *   sprintf("%#o", 123)  #=> "0173"
- *   sprintf("%+o", -123) #=> "-173"
- *   sprintf("%o", -123)  #=> "..7605"
- *   sprintf("%#o", -123) #=> "..7605"
- *
- *   # `#' flag for `x' add a prefix `0x' for non-zero numbers.
- *   # `+' and space flag disables complements for negative numbers.
- *   sprintf("%x", 123)   #=> "7b"
- *   sprintf("%#x", 123)  #=> "0x7b"
- *   sprintf("%+x", -123) #=> "-7b"
- *   sprintf("%x", -123)  #=> "..f85"
- *   sprintf("%#x", -123) #=> "0x..f85"
- *   sprintf("%#x", 0)    #=> "0"
- *
- *   # `#' for `X' uses the prefix `0X'.
- *   sprintf("%X", 123)  #=> "7B"
- *   sprintf("%#X", 123) #=> "0X7B"
- *
- *   # `#' flag for `b' add a prefix `0b' for non-zero numbers.
- *   # `+' and space flag disables complements for negative numbers.
- *   sprintf("%b", 123)   #=> "1111011"
- *   sprintf("%#b", 123)  #=> "0b1111011"
- *   sprintf("%+b", -123) #=> "-1111011"
- *   sprintf("%b", -123)  #=> "..10000101"
- *   sprintf("%#b", -123) #=> "0b..10000101"
- *   sprintf("%#b", 0)    #=> "0"
- *
- *   # `#' for `B' uses the prefix `0B'.
- *   sprintf("%B", 123)  #=> "1111011"
- *   sprintf("%#B", 123) #=> "0B1111011"
- *
- *   # `#' for `e' forces to show the decimal point.
- *   sprintf("%.0e", 1)  #=> "1e+00"
- *   sprintf("%#.0e", 1) #=> "1.e+00"
- *
- *   # `#' for `f' forces to show the decimal point.
- *   sprintf("%.0f", 1234)  #=> "1234"
- *   sprintf("%#.0f", 1234) #=> "1234."
- *
- *   # `#' for `g' forces to show the decimal point.
- *   # It also disables stripping lowest zeros.
- *   sprintf("%g", 123.4)   #=> "123.4"
- *   sprintf("%#g", 123.4)  #=> "123.400"
- *   sprintf("%g", 123456)  #=> "123456"
- *   sprintf("%#g", 123456) #=> "123456."
- *     
- *  The field width is an optional integer, followed optionally by a
- *  period and a precision.  The width specifies the minimum number of
- *  characters that will be written to the result for this field.
- *
- *  Examples of width:
- *
- *   # padding is done by spaces,       width=20
- *   # 0 or radix-1.             <------------------>
- *   sprintf("%20d", 123)   #=> "                 123"
- *   sprintf("%+20d", 123)  #=> "                +123"
- *   sprintf("%020d", 123)  #=> "00000000000000000123"
- *   sprintf("%+020d", 123) #=> "+0000000000000000123"
- *   sprintf("% 020d", 123) #=> " 0000000000000000123"
- *   sprintf("%-20d", 123)  #=> "123                 "
- *   sprintf("%-+20d", 123) #=> "+123                "
- *   sprintf("%- 20d", 123) #=> " 123                "
- *   sprintf("%020x", -123) #=> "..ffffffffffffffff85"
- *
- *  For
- *  numeric fields, the precision controls the number of decimal places
- *  displayed.  For string fields, the precision determines the maximum
- *  number of characters to be copied from the string.  (Thus, the format
- *  sequence <code>%10.10s</code> will always contribute exactly ten
- *  characters to the result.)
- *
- *  Examples of precisions:
- *
- *   # precision for `d', 'o', 'x' and 'b' is
- *   # minimum number of digits               <------>
- *   sprintf("%20.8d", 123)  #=> "            00000123"
- *   sprintf("%20.8o", 123)  #=> "            00000173"
- *   sprintf("%20.8x", 123)  #=> "            0000007b"
- *   sprintf("%20.8b", 123)  #=> "            01111011"
- *   sprintf("%20.8d", -123) #=> "           -00000123"
- *   sprintf("%20.8o", -123) #=> "            ..777605"
- *   sprintf("%20.8x", -123) #=> "            ..ffff85"
- *   sprintf("%20.8b", -11)  #=> "            ..110101"
- *
- *   # "0x" and "0b" for `#x' and `#b' is not counted for
- *   # precision but "0" for `#o' is counted.  <------>
- *   sprintf("%#20.8d", 123)  #=> "            00000123"
- *   sprintf("%#20.8o", 123)  #=> "            00000173"
- *   sprintf("%#20.8x", 123)  #=> "          0x0000007b"
- *   sprintf("%#20.8b", 123)  #=> "          0b01111011"
- *   sprintf("%#20.8d", -123) #=> "           -00000123"
- *   sprintf("%#20.8o", -123) #=> "            ..777605"
- *   sprintf("%#20.8x", -123) #=> "          0x..ffff85"
- *   sprintf("%#20.8b", -11)  #=> "          0b..110101"
- *
- *   # precision for `e' is number of
- *   # digits after the decimal point           <------>
- *   sprintf("%20.8e", 1234.56789) #=> "      1.23456789e+03"
- *                                    
- *   # precision for `f' is number of
- *   # digits after the decimal point               <------>
- *   sprintf("%20.8f", 1234.56789) #=> "       1234.56789000"
- *
- *   # precision for `g' is number of
- *   # significant digits                          <------->
- *   sprintf("%20.8g", 1234.56789) #=> "           1234.5679"
- *
- *   #                                         <------->
- *   sprintf("%20.8g", 123456789)  #=> "       1.2345679e+08"
- *
- *   # precision for `s' is
- *   # maximum number of characters                    <------>
- *   sprintf("%20.8s", "string test") #=> "            string t"
- *     
- *  Examples:
- *
- *     sprintf("%d %04x", 123, 123)               #=> "123 007b"
- *     sprintf("%08b '%4s'", 123, 123)            #=> "01111011 ' 123'"
- *     sprintf("%1$*2$s %2$d %1$s", "hello", 8)   #=> "   hello 8 hello"
- *     sprintf("%1$*2$s %2$d", "hello", -8)       #=> "hello    -8"
- *     sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23)   #=> "+1.23: 1.23:1.23"
- *     sprintf("%u", -123)                        #=> "-123"
- */
-
-#define GETNTHARG(nth) \
-    ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : \
-    argv[nth])
-
-VALUE
-rb_f_sprintf_imp(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
-}
-
-VALUE
-rb_f_sprintf(int argc, const VALUE *argv)
-{
-    return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
-}
-
-VALUE
-rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
-{
-    char buffer[512];
-    int n;
-    n = vsnprintf(buffer, sizeof buffer, fmt, ap);
-    return rb_enc_str_new(buffer, n, enc);
-}
-
-VALUE
-rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    VALUE result = rb_enc_vsprintf(enc, format, ap);
-    va_end(ap);
-    return result;
-}
-
-VALUE
-rb_vsprintf(const char *fmt, va_list ap)
-{
-    return rb_enc_vsprintf(NULL, fmt, ap);
-}
-
-VALUE
-rb_sprintf(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    VALUE result = rb_vsprintf(format, ap);
-    va_end(ap);
-    return result;
-}
-
-#define IS_NEG(num) RBIGNUM_NEGATIVE_P(num)
-#define REL_REF	    1
-#define ABS_REF	    2
-#define NAMED_REF   3
-
-#define REF_NAME(type) \
-    ((type) == REL_REF ? "relative" : (type) == ABS_REF ? "absolute" : "named")
-
-#define SET_REF_TYPE(type) \
-    if (arg == 0 && ref_type != 0 && (type) != ref_type) { \
-	rb_raise(rb_eArgError, "can't mix %s references with %s references", \
-		REF_NAME(type), REF_NAME(ref_type)); \
-    } \
-    ref_type = (type);
-
-#define GET_ARG() \
-    if (arg == 0) { \
-	SET_REF_TYPE(REL_REF); \
-	arg = GETNTHARG(j); \
-	j++; \
-    }
-    
-#define isprenum(ch) ((ch) == '-' || (ch) == ' ' || (ch) == '+')
-
-static void
-pad_format_value(VALUE arg, long start, long width, VALUE pad)
-{
-    const long slen = rb_str_chars_len(arg);
-    if (width <= slen) {
-	return;
-    }
-    if (start < 0) {
-	start += slen + 1;
-    }
-    width -= slen;
-    do {
-	rb_str_update(arg, start, 0, pad);
-    }
-    while (--width > 0);
-}
-
-static long
-cstr_update(UChar **str, long *str_len, long start, long num, VALUE replace)
-{
-    const long len = *str_len;
-    long replace_len = replace == 0 ? 0 : rb_str_chars_len(replace);
-    if (start + num > len) {
-	num = len - start;
-    }
-    if (replace_len >= num) {
-	*str_len = len + replace_len - num;
-	*str = (UChar *)xrealloc(*str,
-		sizeof(UChar) * (len + replace_len - num));
-    }
-    if (replace_len != num) {
-	bcopy(*str + start + num, *str + start + replace_len,
-		sizeof(UChar) * (len - start - num));
-    }
-    if (replace_len > 0) {
-	RB_STR_GET_UCHARS(replace, replace_chars, replace_len2);
-	assert(replace_len2 == replace_len);
-	bcopy(replace_chars, *str + start, sizeof(UChar) * replace_len);
-    }
-    return replace_len - num;
-}
-
-static VALUE
-get_named_arg(UChar *format_str, long format_len, long *i, VALUE hash)
-{
-    if (TYPE(hash) != T_HASH) {
-	rb_raise(rb_eArgError,
-		 "hash required for named references");
-    }
-    UChar closing = format_str[(*i)++] + 2;
-    UChar *str_ptr = &format_str[*i];
-    long  length = 0;
-    while (*i < format_len && format_str[*i] != closing) {
-	(*i)++;
-	length++;
-    }
-    if (*i == format_len) {
-	rb_raise(rb_eArgError,
-		 "malformed name - unmatched parenthesis");
-    }
-    VALUE substr = rb_unicode_str_new(str_ptr, (size_t)length);
-    hash = rb_hash_aref(hash, ID2SYM(rb_intern_str(substr)));
-    return hash;
-}
-
-// XXX look for arguments that are altered but not duped
-VALUE
-rb_str_format(int argc, const VALUE *argv, VALUE fmt)
-{
-    bool tainted = OBJ_TAINTED(fmt);
-
-    long format_len = 0;
-    UChar *format_str = rb_str_xcopy_uchars(fmt, &format_len);
-    if (format_len == 0) {
-	goto bail;
-    }
-
-    long num, pos;
-    int j = 0;
-    int ref_type = 0;
-    long format_str_capa = format_len;
-
-    for (long i = 0; i < format_len; i++) {
-	if (format_str[i] != '%') {
-	    continue;
-	}
-	if (format_str[i + 1] == '%') {
-	    num = cstr_update(&format_str, &format_str_capa, i, 1, 0);
-	    format_len += num;
-	    continue;
-	}
-
-	bool sharp_flag = false;
-	bool space_flag = false;
-	bool plus_flag = false;
-	bool minus_flag = false;
-	bool zero_flag = false;
-	bool width_flag = false;
-	bool precision_flag = false;
-	bool named_flag = false;
-	bool complete = false;
-	VALUE arg = 0;
-	long width = 0;
-	long precision = 0;
-	int base = 0;
-	VALUE negative_pad = 0;
-	VALUE sharp_pad = rb_str_new2("");
-	const long start = i;
-
-#define CHECK_FOR_WIDTH()				 \
-	if (width_flag) {				 \
-	    rb_raise(rb_eArgError, "width given twice"); \
-	}
-
-	while (i++ < format_len) {
-	    switch (format_str[i]) {
-		case '#':
-		    sharp_flag = true;
-		    break;
-
-		case '*':
-		    CHECK_FOR_WIDTH();
-		    width_flag = true;
-		    if (format_str[++i] == '<' || format_str[i] == '{') {
-			SET_REF_TYPE(NAMED_REF);
-			width = NUM2LONG(rb_Integer(get_named_arg(format_str,
-				format_len, &i, GETNTHARG(0))));
-		    }
-		    else {
-			if (isprenum(format_str[i])) {
-			    i--;
-			    break;
-			}
-
-			num = rb_uchar_strtol(format_str, format_len, i, &pos);
-			if (pos == i--) {
-			    SET_REF_TYPE(REL_REF);
-			    width = NUM2LONG(rb_Integer(GETNTHARG(j)));
-			    j++;
-			}
-			else if (format_str[pos] == '$') {
-			    if (num == 0) {
-				rb_raise(rb_eArgError, "invalid absolute argument");
-			    }
-			    SET_REF_TYPE(ABS_REF);
-			    width = NUM2LONG(rb_Integer(GETNTHARG(num - 1)));
-			    i = pos;
-			}
-		    }
-		    if (width < 0) {
-			minus_flag = true;
-			width = -width;
-		    }
-		    break;
-
-		case ' ':
-		    if (!plus_flag) {
-			space_flag = true;
-		    }
-		    break;
-
-		case '+':
-		    plus_flag = true;
-		    space_flag = false;
-		    break;
-
-		case '-':
-		    zero_flag = false;
-		    minus_flag = true;
-		    break;
-
-		case '0':
-		    if (!precision_flag && !minus_flag) {
-			zero_flag = true;
-		    }
-		    break;
-
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-		    num = rb_uchar_strtol(format_str, format_len, i, &pos);
-		    i = pos;
-		    if (format_str[pos] == '$') {
-			if (num == 0) {
-			    rb_raise(rb_eArgError, "invalid absolute argument");
-			}
-			if (arg != 0) {
-			    rb_raise(rb_eArgError, "value given twice");
-			}
-			SET_REF_TYPE(ABS_REF);
-			arg = GETNTHARG(num - 1);
-		    }
-		    else {
-			SET_REF_TYPE(REL_REF);
-			width = num;
-			i--;
-			CHECK_FOR_WIDTH();
-			width_flag = true;
-		    }
-		    break;
-
-		case '.':
-		    if (precision_flag) {
-			rb_raise(rb_eArgError, "precision given twice");
-		    }
-		    precision_flag = true;
-		    if (format_str[++i] == '*') {
-			if (format_str[++i] == '<' || format_str[i] == '{') {
-			    SET_REF_TYPE(NAMED_REF);
-			    precision = NUM2LONG(rb_Integer(get_named_arg(
-				    format_str, format_len, &i, GETNTHARG(0))));
-			}
-			else {
-			    if (isprenum(format_str[i])) {
-				i--;
-				break;
-			    }
-
-			    num = rb_uchar_strtol(format_str, format_len,
-				    i, &pos);
-			    if (format_str[pos] == '$') {
-				if (num == 0) {
-				    rb_raise(rb_eArgError, "invalid absolute argument");
-				}
-				SET_REF_TYPE(ABS_REF);
-				precision = NUM2LONG(rb_Integer(GETNTHARG(
-					num - 1)));
-				i = pos;
-			    }
-			    else {
-				SET_REF_TYPE(REL_REF);
-				precision = NUM2LONG(rb_Integer(GETNTHARG(j)));
-				j++;
-				i--;
-			    }
-			}
-		    }
-		    else if (isdigit(format_str[i])) {
-			precision = rb_uchar_strtol(format_str, format_len,
-				i, &pos);
-			i = pos - 1;
-		    }
-		    else {
-			rb_raise(rb_eArgError, "invalid precision");
-		    }
-
-		    if (precision < 0) {
-			precision = 0;
-		    }
-		    break;
-
-		case '<':
-		case '{':
-		{
-		    char term = (format_str[i] == '<') ? '>' : '}';
-
-		    if (named_flag) {
-			rb_raise(rb_eArgError, "named given twice");
-		    }
-		    if (ref_type != 0) {
-			rb_raise(rb_eArgError, "named after numbered");
-		    }
-		    named_flag = true;
-		    SET_REF_TYPE(NAMED_REF);
-		    arg = get_named_arg(format_str, format_len, &i,
-			    GETNTHARG(0));
-		    if (term == '}') {
-			if (TYPE(arg) != T_STRING) {
-			    arg = rb_obj_as_string(arg);
-			}
-			goto format_s;
-		    }
-		    break;
-		}
-
-		case 'd':
-		case 'D':
-		case 'i':
-		case 'u':
-		case 'U':
-		    base = 10;
-		    sharp_flag = false;
-		    if (precision_flag) {
-			zero_flag = false;
-		    }
-		    complete = true;
-		    break;
-
-		case 'x':
-		case 'X':
-		    base = 16;
-		    negative_pad = rb_str_new2("f");
-		    sharp_pad = rb_str_new2("0x");
-		    if (precision_flag) {
-			zero_flag = false;
-		    }
-		    complete = true;
-		    break;
-
-		case 'o':
-		case 'O':
-		    base = 8;
-		    negative_pad = rb_str_new2("7");
-		    sharp_pad = rb_str_new2("0");
-		    complete = true;
-		    break;
-
-		case 'B':
-		case 'b':
-		    base = 2;
-		    negative_pad = rb_str_new2("1");
-		    sharp_pad = rb_str_new2("0b");
-		    complete = true;
-		    break;
-
-		case 'c':
-		case 'C':
-		    GET_ARG();
-		    if (TYPE(arg) == T_STRING) {
-			if(RSTRING_LEN(arg) != 1) {
-			    rb_raise(rb_eArgError, "%%c requires a character");
-			}
-		    }
-		    else {
-			long num = NUM2LONG(arg);
-			if (num < 0 || i > 0xff) {
-			    rb_raise(rb_eRangeError, "%ld out of char range",
-				    num);
-			}
-			char c = (char)num;
-			arg = rb_str_new(&c, 1);
-		    }
-		    complete = true;
-		    break;
-
-		case 'f':
-		case 'F':
-		case 'e':
-		case 'E':
-		case 'g':
-		case 'G':
-		case 'a':
-		case 'A':
-		{
-		    // here we construct a new format str and then use
-		    // c's sprintf. why? because floats are retarded
-		    GET_ARG();
-		    double value = RFLOAT_VALUE(rb_Float(arg));
-		    complete = true;
-		    
-		    if (isnan(value) || isinf(value)) {
-			arg = rb_str_new2((char *)(isnan(value) ? "NaN" :
-				value < 0 ? "-Inf" : "Inf"));
-			if (isnan(value) || value > 0) {
-			    if (plus_flag) {
-				rb_str_update(arg, 0, 0, rb_str_new2("+"));
-			    }
-			    else if (space_flag) {
-				rb_str_update(arg, 0, 0, rb_str_new2(" "));
-			    }
-			}
-			break;
-		    }
-
-		    arg = rb_unicode_str_new(&format_str[i], 1);
-		    if (precision_flag) {
-			rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(precision),
-				10));
-			rb_str_update(arg, 0, 0, rb_str_new2("."));
-		    }
-		    rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(width), 10));
-		    if (minus_flag) {
-			rb_str_update(arg, 0, 0, rb_str_new2("-"));
-		    }
-		    else if (zero_flag) {
-			rb_str_update(arg, 0, 0, rb_str_new2("0"));
-		    }
-		    if (plus_flag) {
-			rb_str_update(arg, 0, 0, rb_str_new2("+"));
-		    }
-		    else if (space_flag) {
-			rb_str_update(arg, 0, 0, rb_str_new2(" "));
-		    }
-		    if (sharp_flag) {
-			rb_str_update(arg, 0, 0, rb_str_new2("#"));
-		    }
-		    rb_str_update(arg, 0, 0, rb_str_new2("%"));
-
-		    char *ptr;
-		    asprintf(&ptr, RSTRING_PTR(arg), value);
-		    arg = rb_str_new2(ptr);
-		    free(ptr);
-		    break;
-		}
-
-		case 's':
-		case 'S':
-		case 'p':
-		case '@':
-		    GET_ARG();
-		    arg = (tolower(format_str[i]) != 's'
-			    ? rb_inspect(arg) : TYPE(arg) == T_STRING
-				? rb_str_new3(arg) : rb_obj_as_string(arg));
-		format_s:
-		    if (precision_flag && precision < rb_str_chars_len(arg)) {
-			CFStringPad((CFMutableStringRef)arg, NULL, precision,
-				0);
-		    }
-		    complete = true;
-		    break;
-
-		case '\n':
-		case '\0':
-		    if (format_str[i - 1] == '%') {
-			if (format_str[i] == '\n') {
-			    arg = rb_str_new("%\n", 2);
-			}
-			else {
-			    if (format_len > i) {
-				arg = rb_str_new("%\0", 2);
-			    }
-			    else {
-				arg = rb_str_new("%", 1);
-			    }
-			}
-			complete = true;
-			break;
-		    }
-		    rb_raise(rb_eArgError, "malformed format string - %%%c",
-			     format_str[i]);
-		    break;
-
-		default:
-		    rb_raise(rb_eArgError, "malformed format string - %%%c",
-			     format_str[i]);
-	    }
-	    if (!complete) {
-		continue;
-	    }
-
-	    GET_ARG();
-
-	    if (base != 0) {
-		bool sign_pad = false;
-		unsigned long num_index = 0;
-		unsigned long sharp_beg = 0;
-		VALUE zero_pad = rb_str_new2("0");
-
-		VALUE num = rb_Integer(arg);
-		if (TYPE(num) == T_FIXNUM) {
-		    num = rb_int2big(FIX2LONG(num));
-		}
-		if (plus_flag || space_flag) {
-		    sign_pad = 1;
-		}
-		if (IS_NEG(num)) {
-		    num_index = 1;
-		    sharp_beg = 1;
-		    if (!sign_pad && negative_pad != 0) {
-			zero_pad = negative_pad;
-			num = rb_big_clone(num);
-			rb_big_2comp(num);
-		    }
-		}
-
-		arg = rb_big2str(num, base);
-		if (!sign_pad && IS_NEG(num) && negative_pad != 0) {
-		    UChar neg = rb_str_get_uchar(negative_pad, 0);
-		    if (base == 8) {
-			UChar c = rb_str_get_uchar(arg, 1);
-			const long len = rb_str_chars_len(arg) - 1;
-			c |= ((~0 << 3) >> ((3 * len)
-				    % (sizeof(BDIGIT) * 8))) & ~(~0 << 3);
-			rb_str_update(arg, 1, 1, rb_unicode_str_new(&c, 1));
-		    }
-		    for (int i = 1, count = rb_str_chars_len(arg); i < count;
-			    i++) {
-			if (rb_str_get_uchar(arg, i) != neg) {
-			    break;
-			}
-			num_index++;
-		    }
-		    rb_str_update(arg, 0, num_index, negative_pad);
-		    rb_str_update(arg, 0, 0, rb_str_new2(".."));
-		    num_index = 2;
-		    sharp_beg = 0;
-		}
-		if (precision_flag) {
-		    pad_format_value(arg, num_index,
-			    precision + (IS_NEG(num)
-				&& (sign_pad || negative_pad == 0) ? 1 : 0),
-			    zero_pad);
-		}
-		if (sharp_flag && rb_cmpint(num, Qfalse, Qfalse) != 0) {
-		    rb_str_update(arg, sharp_beg, 0, (VALUE)sharp_pad);
-		    num_index += 2;
-		}
-		if (sign_pad && RBIGNUM_POSITIVE_P(num)) {
-		    rb_str_update(arg, 0, 0, (VALUE)(plus_flag ?
-			    rb_str_new2("+") : rb_str_new2(" ")));
-		    num_index++;
-		}
-		if (zero_flag) {
-		    pad_format_value(arg, num_index, width, zero_pad);
-		}
-		if (ISUPPER(format_str[i])) {
-		    CFStringUppercase((CFMutableStringRef)arg, NULL);
-		}
-	    }
-	    
-	    if (OBJ_TAINTED(arg)) {
-		tainted = true;
-	    }
-
-	    if (TYPE(arg) == T_SYMBOL) {
-		// Because symbols are not mutable and pad_format_value()
-		// mutates its first argument.
-		arg = rb_sym_to_s(arg);
-	    }
-	    pad_format_value(arg, minus_flag ? -1 : 0, width, rb_str_new2(" "));
-	    num = cstr_update(&format_str, &format_str_capa, start,
-		    i - start + 1, arg);
-	    format_len += num;
-	    i += num;
-	    break;
-	}
-    }
-
-bail:
-    fmt = rb_unicode_str_new(format_str, format_len);
-    if (tainted) {
-	OBJ_TAINT(fmt);
-    }
-    return fmt;
-}

Deleted: MacRuby/trunk/st.c
===================================================================
--- MacRuby/trunk/st.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/st.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,968 +0,0 @@
-/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
-
-/* static	char	sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
-
-#ifdef NOT_RUBY
-#include "regint.h"
-#include "st.h"
-#else
-#include "ruby/config.h"
-#include "ruby/defines.h"
-#include "ruby/st.h"
-#include "macruby_internal.h"
-#endif
-
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <string.h>
-
-typedef struct st_table_entry st_table_entry;
-
-struct st_table_entry {
-    unsigned int hash;
-    st_data_t key;
-    st_data_t record;
-    st_table_entry *next;
-    st_table_entry *fore, *back;
-};
-
-#define ST_DEFAULT_MAX_DENSITY 5
-#define ST_DEFAULT_INIT_TABLE_SIZE 11
-
-    /*
-     * DEFAULT_MAX_DENSITY is the default for the largest we allow the
-     * average number of items per bin before increasing the number of
-     * bins
-     *
-     * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
-     * allocated initially
-     *
-     */
-
-static const struct st_hash_type type_numhash = {
-    st_numcmp,
-    st_numhash,
-};
-
-/* extern int strcmp(const char *, const char *); */
-static int strhash(const char *);
-static const struct st_hash_type type_strhash = {
-    strcmp,
-    strhash,
-};
-
-static int strcasehash(const char *);
-static const struct st_hash_type type_strcasehash = {
-    st_strcasecmp,
-    strcasehash,
-};
-
-static void rehash(st_table *);
-
-#ifdef RUBY
-#define malloc xmalloc
-#define calloc xcalloc
-//#define free xfree
-#define free(x) ((void)0)
-void *rb_gc_memmove(void *dst, const void *src, size_t len);
-#define xmemmove rb_gc_memmove
-#endif
-
-#define alloc(type) (type*)malloc((size_t)sizeof(type))
-#define Calloc(n,s) (char*)calloc((n),(s))
-
-#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
-
-#define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
-#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
-
-/*
- * MINSIZE is the minimum size of a dictionary.
- */
-
-#define MINSIZE 8
-
-/*
-Table of prime numbers 2^n+a, 2<=n<=30.
-*/
-static const long primes[] = {
-	8 + 3,
-	16 + 3,
-	32 + 5,
-	64 + 3,
-	128 + 3,
-	256 + 27,
-	512 + 9,
-	1024 + 9,
-	2048 + 5,
-	4096 + 3,
-	8192 + 27,
-	16384 + 43,
-	32768 + 3,
-	65536 + 45,
-	131072 + 29,
-	262144 + 3,
-	524288 + 21,
-	1048576 + 7,
-	2097152 + 17,
-	4194304 + 15,
-	8388608 + 9,
-	16777216 + 43,
-	33554432 + 35,
-	67108864 + 15,
-	134217728 + 29,
-	268435456 + 3,
-	536870912 + 11,
-	1073741824 + 85,
-	0
-};
-
-static int
-new_size(int size)
-{
-    int i;
-
-#if 0
-    for (i=3; i<31; i++) {
-	if ((1<<i) > size) return 1<<i;
-    }
-    return -1;
-#else
-    int newsize;
-
-    for (i = 0, newsize = MINSIZE;
-	 i < (int )(sizeof(primes)/sizeof(primes[0]));
-	 i++, newsize <<= 1)
-    {
-	if (newsize > size) return primes[i];
-    }
-    /* Ran out of polynomials */
-    return -1;			/* should raise exception */
-#endif
-}
-
-#ifdef HASH_LOG
-static int collision = 0;
-static int init_st = 0;
-
-static void
-stat_col()
-{
-    FILE *f = fopen("/tmp/col", "w");
-    fprintf(f, "collision: %d\n", collision);
-    fclose(f);
-}
-#endif
-
-#define MAX_PACKED_NUMHASH 5
-
-st_table*
-st_init_table_with_size(const struct st_hash_type *type, int size)
-{
-    st_table *tbl;
-
-#ifdef HASH_LOG
-    if (init_st == 0) {
-	init_st = 1;
-	atexit(stat_col);
-    }
-#endif
-
-    size = new_size(size);	/* round up to prime number */
-
-    tbl = alloc(st_table);
-    tbl->type = type;
-    tbl->num_entries = 0;
-    tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH;
-    tbl->num_bins = size;
-    GC_WB(&tbl->bins, (st_table_entry **)Calloc(size, sizeof(st_table_entry*)));
-    tbl->head = 0;
-
-    return tbl;
-}
-
-st_table*
-st_init_table(const struct st_hash_type *type)
-{
-    return st_init_table_with_size(type, 0);
-}
-
-st_table*
-st_init_numtable(void)
-{
-    return st_init_table(&type_numhash);
-}
-
-st_table*
-st_init_numtable_with_size(int size)
-{
-    return st_init_table_with_size(&type_numhash, size);
-}
-
-st_table*
-st_init_strtable(void)
-{
-    return st_init_table(&type_strhash);
-}
-
-st_table*
-st_init_strtable_with_size(int size)
-{
-    return st_init_table_with_size(&type_strhash, size);
-}
-
-st_table*
-st_init_strcasetable(void)
-{
-    return st_init_table(&type_strcasehash);
-}
-
-st_table*
-st_init_strcasetable_with_size(int size)
-{
-    return st_init_table_with_size(&type_strcasehash, size);
-}
-
-void
-st_clear(st_table *table)
-{
-    register st_table_entry *ptr, *next;
-    int i;
-
-    if (table->entries_packed) {
-        table->num_entries = 0;
-        return;
-    }
-
-    for(i = 0; i < table->num_bins; i++) {
-	ptr = table->bins[i];
-	table->bins[i] = 0;
-	while (ptr != 0) {
-	    next = ptr->next;
-	    free(ptr);
-	    ptr = next;
-	}
-    }
-    table->num_entries = 0;
-    table->head = 0;
-}
-
-void
-st_free_table(st_table *table)
-{
-    st_clear(table);
-    free(table->bins);
-    free(table);
-}
-
-#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
-((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
-
-#ifdef HASH_LOG
-#define COLLISION collision++
-#else
-#define COLLISION
-#endif
-
-#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
-    bin_pos = hash_val%(table)->num_bins;\
-    ptr = (table)->bins[bin_pos];\
-    if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
-	COLLISION;\
-	while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
-	    ptr = ptr->next;\
-	}\
-	ptr = ptr->next;\
-    }\
-} while (0)
-
-int
-st_lookup(st_table *table, register st_data_t key, st_data_t *value)
-{
-    unsigned int hash_val, bin_pos;
-    register st_table_entry *ptr;
-
-    if (table->entries_packed) {
-        int i;
-        for (i = 0; i < table->num_entries; i++) {
-            if ((st_data_t)table->bins[i*2] == key) {
-                if (value !=0) *value = (st_data_t)table->bins[i*2+1];
-                return 1;
-            }
-        }
-        return 0;
-    }
-
-    hash_val = do_hash(key, table);
-    FIND_ENTRY(table, ptr, hash_val, bin_pos);
-
-    if (ptr == 0) {
-	return 0;
-    }
-    else {
-	if (value != 0)  *value = ptr->record;
-	return 1;
-    }
-}
-
-int
-st_get_key(st_table *table, register st_data_t key, st_data_t *result)
-{
-    unsigned int hash_val, bin_pos;
-    register st_table_entry *ptr;
-
-    if (table->entries_packed) {
-        int i;
-        for (i = 0; i < table->num_entries; i++) {
-            if ((st_data_t)table->bins[i*2] == key) {
-                if (result !=0) *result = (st_data_t)table->bins[i*2];
-                return 1;
-            }
-        }
-        return 0;
-    }
-
-    hash_val = do_hash(key, table);
-    FIND_ENTRY(table, ptr, hash_val, bin_pos);
-
-    if (ptr == 0) {
-	return 0;
-    }
-    else {
-	if (result != 0)  *result = ptr->key;
-	return 1;
-    }
-}
-
-#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
-do {\
-    st_table_entry *entry, *head;\
-    if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\
-	rehash(table);\
-        bin_pos = hash_val % table->num_bins;\
-    }\
-    \
-    entry = alloc(st_table_entry);\
-    \
-    entry->hash = hash_val;\
-    GC_WB(&entry->key, key);\
-    GC_WB(&entry->record, value); \
-    GC_WB(&entry->next, table->bins[bin_pos]);\
-    if ((head = table->head) != 0) {\
-	entry->fore = head;\
-	(entry->back = head->back)->fore = entry;\
-	head->back = entry;\
-    }\
-    else {\
-	GC_WB(&table->head, entry);\
-	entry->fore = entry;\
-	entry->back = entry;\
-    }\
-    GC_WB(&table->bins[bin_pos], entry); \
-    table->num_entries++;\
-} while (0)
-
-static void
-unpack_entries(register st_table *table)
-{
-    int i;
-    struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2];
-    int num_entries = table->num_entries;
-
-    memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * num_entries*2);
-    table->entries_packed = 0;
-    table->num_entries = 0;
-    memset(table->bins, 0, sizeof(struct st_table_entry *) * table->num_bins);
-    for (i = 0; i < num_entries; i++) {
-        st_insert(table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]);
-    }
-}
-
-int
-st_insert(register st_table *table, register st_data_t key, st_data_t value)
-{
-    unsigned int hash_val, bin_pos;
-    register st_table_entry *ptr;
-
-    if (table->entries_packed) {
-        int i;
-        for (i = 0; i < table->num_entries; i++) {
-            if ((st_data_t)table->bins[i*2] == key) {
-		GC_WB(&table->bins[i*2+1], (struct st_table_entry*)value);
-                return 1;
-            }
-        }
-        if ((table->num_entries+1) * 2 <= table->num_bins && table->num_entries+1 <= MAX_PACKED_NUMHASH) {
-            i = table->num_entries++;
-            GC_WB(&table->bins[i*2], (struct st_table_entry*)key);
-	    GC_WB(&table->bins[i*2+1], (struct st_table_entry*)value);
-            return 0;
-        }
-        else {
-            unpack_entries(table);
-        }
-    }
-
-    hash_val = do_hash(key, table);
-    FIND_ENTRY(table, ptr, hash_val, bin_pos);
-
-    if (ptr == 0) {
-	ADD_DIRECT(table, key, value, hash_val, bin_pos);
-	return 0;
-    }
-    else {
-	GC_WB(&ptr->record, value);
-	return 1;
-    }
-}
-
-void
-st_add_direct(st_table *table, st_data_t key, st_data_t value)
-{
-    unsigned int hash_val, bin_pos;
-
-    if (table->entries_packed) {
-        int i;
-        if ((table->num_entries+1) * 2 <= table->num_bins && table->num_entries+1 <= MAX_PACKED_NUMHASH) {
-            i = table->num_entries++;
-            table->bins[i*2] = (struct st_table_entry*)key;
-	    GC_WB(&table->bins[i*2+1], (struct st_table_entry*)value);
-            return;
-        }
-        else {
-            unpack_entries(table);
-        }
-    }
-
-    hash_val = do_hash(key, table);
-    bin_pos = hash_val % table->num_bins;
-    ADD_DIRECT(table, key, value, hash_val, bin_pos);
-}
-
-static void
-rehash(register st_table *table)
-{
-    register st_table_entry *ptr, **new_bins;
-    int i, new_num_bins;
-    unsigned int hash_val;
-
-    new_num_bins = new_size(table->num_bins+1);
-    new_bins = (st_table_entry**)
-	xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*));
-    for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0;
-    table->num_bins = new_num_bins;
-    GC_WB(&table->bins, new_bins);
-
-    if ((ptr = table->head) != 0) {
-	do {
-	    hash_val = ptr->hash % new_num_bins;
-	    GC_WB(&ptr->next, new_bins[hash_val]);
-	    GC_WB(&new_bins[hash_val], ptr);
-	} while ((ptr = ptr->fore) != table->head);
-    }
-}
-
-st_table*
-st_copy(st_table *old_table)
-{
-    st_table *new_table;
-    st_table_entry *ptr, *entry, *prev, **tail;
-    int num_bins = old_table->num_bins;
-    unsigned int hash_val;
-
-    new_table = alloc(st_table);
-    assert(new_table != NULL);
-
-    *new_table = *old_table;
-    GC_WB(&new_table->bins, (st_table_entry**)
-	Calloc((unsigned)num_bins, sizeof(st_table_entry*)));
-
-    assert(new_table->bins != NULL);
-
-    if (old_table->entries_packed) {
-        xmemmove(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins);
-        return new_table;
-    }
-
-    if ((ptr = old_table->head) != 0) {
-	prev = 0;
-	tail = &new_table->head;
-	do {
-	    entry = alloc(st_table_entry);
-	    assert(entry != NULL);
-	    *entry = *ptr;
-	    GC_WB(&entry->key, ptr->key);
-	    GC_WB(&entry->record, ptr->record);
-	    hash_val = entry->hash % num_bins;
-	    GC_WB(&entry->next, new_table->bins[hash_val]);
-	    GC_WB(&new_table->bins[hash_val], entry);
-	    entry->back = prev;
-	    prev = entry;
-	    *tail = entry;
-	    tail = &entry->fore;
-	} while ((ptr = ptr->fore) != old_table->head && ptr != NULL);
-	GC_WB(&new_table->head, new_table->head);
-	entry = new_table->head;
-	entry->back = prev;
-	*tail = entry;
-    }
-
-    return new_table;
-}
-
-#define REMOVE_ENTRY(table, ptr) do					\
-    {									\
-	if (ptr == ptr->fore) {						\
-	    table->head = 0;						\
-	}								\
-	else {								\
-	    st_table_entry *fore = ptr->fore, *back = ptr->back;	\
-	    fore->back = back;						\
-	    back->fore = fore;						\
-	    if (ptr == table->head) table->head = fore;			\
-	}								\
-	table->num_entries--;						\
-    } while (0)
-
-int
-st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
-{
-    unsigned int hash_val;
-    st_table_entry **prev;
-    register st_table_entry *ptr;
-
-    if (table->entries_packed) {
-        int i;
-        for (i = 0; i < table->num_entries; i++) {
-            if ((st_data_t)table->bins[i*2] == *key) {
-                if (value != 0) *value = (st_data_t)table->bins[i*2+1];
-                table->num_entries--;
-                xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
-                        sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
-                return 1;
-            }
-        }
-        if (value != 0) *value = 0;
-        return 0;
-    }
-
-    hash_val = do_hash_bin(*key, table);
-
-    for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) {
-	if (EQUAL(table, *key, ptr->key)) {
-	    *prev = ptr->next;
-	    REMOVE_ENTRY(table, ptr);
-	    if (value != 0) *value = ptr->record;
-	    *key = ptr->key;
-	    free(ptr);
-	    return 1;
-	}
-    }
-
-    if (value != 0) *value = 0;
-    return 0;
-}
-
-int
-st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *value, st_data_t never)
-{
-    st_index_t hash_val;
-    register st_table_entry *ptr;
-
-    if (table->entries_packed) {
-        st_index_t i;
-        for (i = 0; i < table->num_entries; i++) {
-            if ((st_data_t)table->bins[i*2] == *key) {
-                if (value != 0) *value = (st_data_t)table->bins[i*2+1];
-                table->bins[i*2] = (void *)never;
-                return 1;
-            }
-        }
-        if (value != 0) *value = 0;
-        return 0;
-    }
-
-    hash_val = do_hash_bin(*key, table);
-    ptr = table->bins[hash_val];
-
-    for (; ptr != 0; ptr = ptr->next) {
-        if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
-            REMOVE_ENTRY(table, ptr);
-            *key = ptr->key;
-            if (value != 0) *value = ptr->record;
-            ptr->key = ptr->record = never;
-            return 1;
-        }
-    }
-
-    if (value != 0) *value = 0;
-    return 0;
-}
-
-void
-st_cleanup_safe(st_table *table, st_data_t never)
-{
-    st_table_entry *ptr, **last, *tmp;
-    int i;
-
-    for (i = 0; i < table->num_bins; i++) {
-	ptr = *(last = &table->bins[i]);
-	while (ptr != 0) {
-	    if (ptr->key == never) {
-		tmp = ptr;
-		*last = ptr = ptr->next;
-		free(tmp);
-	    }
-	    else {
-		ptr = *(last = &ptr->next);
-	    }
-	}
-    }
-}
-
-int
-st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
-{
-    st_table_entry *ptr, **last, *tmp;
-    enum st_retval retval;
-    int i, end;
-
-    if (table->entries_packed) {
-        for (i = 0; i < table->num_entries; i++) {
-            //int j;
-            st_data_t key, val;
-            key = (st_data_t)table->bins[i*2];
-            val = (st_data_t)table->bins[i*2+1];
-            retval = (*func)(key, val, arg);
-            switch (retval) {
-	      case ST_CHECK:	/* check if hash is modified during iteration */
-#if 0 // XXX disabled because unused and causes clang errors
-                for (j = 0; j < table->num_entries; j++) {
-                    if ((st_data_t)table->bins[j*2] == key)
-                        break;
-                }
-                if (j == table->num_entries) {
-                    /* call func with error notice */
-                    retval = (*func)(0, 0, arg, 1);
-                    return 1;
-                }
-		/* fall through */
-#endif
-	      case ST_CONTINUE:
-		break;
-	      case ST_STOP:
-		return 0;
-	      case ST_DELETE:
-                table->num_entries--;
-                xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
-                        sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
-                i--;
-                break;
-            }
-        }
-        return 0;
-    }
-
-    if ((ptr = table->head) != 0) {
-	do {
-	    end = ptr->fore == table->head;
-	    retval = (*func)(ptr->key, ptr->record, arg);
-	    switch (retval) {
-	      case ST_CHECK:	/* check if hash is modified during iteration */
-#if 0 // XXX disabled because unused and causes clang errors
-		i = ptr->hash % table->num_bins;
-		for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
-		    if (!tmp) {
-			/* call func with error notice */
-			retval = (*func)(0, 0, arg, 1);
-			return 1;
-		    }
-		}
-		/* fall through */
-#endif
-	      case ST_CONTINUE:
-		ptr = ptr->fore;
-		break;
-	      case ST_STOP:
-		return 0;
-	      case ST_DELETE:
-		last = &table->bins[ptr->hash % table->num_bins];
-		for (; (tmp = *last) != 0; last = &tmp->next) {
-		    if (ptr == tmp) {
-			tmp = ptr->fore;
-			*last = ptr->next;
-			REMOVE_ENTRY(table, ptr);
-			free(ptr);
-			if (ptr == tmp) return 0;
-			ptr = tmp;
-			break;
-		    }
-		}
-	    }
-	} while (!end && table->head);
-    }
-    return 0;
-}
-
-int
-st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
-{
-    st_table_entry *ptr, **last, *tmp;
-    enum st_retval retval;
-    int i, end;
-
-    if (table->entries_packed) {
-        for (i = table->num_entries-1; 0 <= i; i--) {
-            int j;
-            st_data_t key, val;
-            key = (st_data_t)table->bins[i*2];
-            val = (st_data_t)table->bins[i*2+1];
-            retval = (*func)(key, val, arg);
-            switch (retval) {
-	      case ST_CHECK:	/* check if hash is modified during iteration */
-                for (j = 0; j < table->num_entries; j++) {
-                    if ((st_data_t)table->bins[j*2] == key)
-                        break;
-                }
-                if (j == table->num_entries) {
-                    /* call func with error notice */
-                    retval = (*func)(0, 0, arg, 1);
-                    return 1;
-                }
-		/* fall through */
-	      case ST_CONTINUE:
-		break;
-	      case ST_STOP:
-		return 0;
-	      case ST_DELETE:
-                table->num_entries--;
-                xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
-                        sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
-                break;
-            }
-        }
-        return 0;
-    }
-
-    if ((ptr = table->head) != 0) {
-	ptr = ptr->back;
-	do {
-	    end = ptr == table->head;
-	    retval = (*func)(ptr->key, ptr->record, arg, 0);
-	    switch (retval) {
-	      case ST_CHECK:	/* check if hash is modified during iteration */
-		i = ptr->hash % table->num_bins;
-		for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
-		    if (!tmp) {
-			/* call func with error notice */
-			retval = (*func)(0, 0, arg, 1);
-			return 1;
-		    }
-		}
-		/* fall through */
-	      case ST_CONTINUE:
-		ptr = ptr->back;
-		break;
-	      case ST_STOP:
-		return 0;
-	      case ST_DELETE:
-		last = &table->bins[ptr->hash % table->num_bins];
-		for (; (tmp = *last) != 0; last = &tmp->next) {
-		    if (ptr == tmp) {
-			tmp = ptr->back;
-			*last = ptr->next;
-			REMOVE_ENTRY(table, ptr);
-			free(ptr);
-			ptr = tmp;
-			break;
-		    }
-		}
-		ptr = ptr->next;
-		free(tmp);
-		table->num_entries--;
-	    }
-	} while (!end && table->head);
-    }
-    return 0;
-}
-
-/*
- * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
- *
- * @(#) $Hash32: Revision: 1.1 $
- * @(#) $Hash32: Id: hash_32a.c,v 1.1 2003/10/03 20:38:53 chongo Exp $
- * @(#) $Hash32: Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $
- *
- ***
- *
- * Fowler/Noll/Vo hash
- *
- * The basis of this hash algorithm was taken from an idea sent
- * as reviewer comments to the IEEE POSIX P1003.2 committee by:
- *
- *      Phong Vo (http://www.research.att.com/info/kpv/)
- *      Glenn Fowler (http://www.research.att.com/~gsf/)
- *
- * In a subsequent ballot round:
- *
- *      Landon Curt Noll (http://www.isthe.com/chongo/)
- *
- * improved on their algorithm.  Some people tried this hash
- * and found that it worked rather well.  In an EMail message
- * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
- *
- * FNV hashes are designed to be fast while maintaining a low
- * collision rate. The FNV speed allows one to quickly hash lots
- * of data while maintaining a reasonable collision rate.  See:
- *
- *      http://www.isthe.com/chongo/tech/comp/fnv/index.html
- *
- * for more details as well as other forms of the FNV hash.
- ***
- *
- * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
- * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
- *
- ***
- *
- * Please do not copyright this code.  This code is in the public domain.
- *
- * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
- * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * By:
- *	chongo <Landon Curt Noll> /\oo/\
- *      http://www.isthe.com/chongo/
- *
- * Share and Enjoy!	:-)
- */
-
-/*
- * 32 bit FNV-1 and FNV-1a non-zero initial basis
- *
- * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
- *
- *              chongo <Landon Curt Noll> /\../\
- *
- * NOTE: The \'s above are not back-slashing escape characters.
- * They are literal ASCII  backslash 0x5c characters.
- *
- * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
- */
-#define FNV1_32A_INIT 0x811c9dc5
-
-/*
- * 32 bit magic FNV-1a prime
- */
-#define FNV_32_PRIME 0x01000193
-
-static int
-strhash(register const char *string)
-{
-    register unsigned int hval = FNV1_32A_INIT;
-
-    /*
-     * FNV-1a hash each octet in the buffer
-     */
-    while (*string) {
-	/* xor the bottom with the current octet */
-	hval ^= (unsigned int)*string++;
-
-	/* multiply by the 32 bit FNV magic prime mod 2^32 */
-	hval *= FNV_32_PRIME;
-    }
-    return hval;
-}
-
-int
-rb_hash_string(const char *str)
-{
-    return strhash(str);
-}
-
-int
-st_strcasecmp(const char *s1, const char *s2)
-{
-    unsigned int c1, c2;
-
-    while (1) {
-        c1 = (unsigned char)*s1++;
-        c2 = (unsigned char)*s2++;
-        if (c1 == '\0' || c2 == '\0') {
-            if (c1 != '\0') return 1;
-            if (c2 != '\0') return -1;
-            return 0;
-        }
-        if ((unsigned int)(c1 - 'A') <= ('Z' - 'A')) c1 += 'a' - 'A';
-        if ((unsigned int)(c2 - 'A') <= ('Z' - 'A')) c2 += 'a' - 'A';
-        if (c1 != c2) {
-            if (c1 > c2)
-                return 1;
-            else
-                return -1;
-        }
-    }
-}
-
-int
-st_strncasecmp(const char *s1, const char *s2, size_t n)
-{
-    unsigned int c1, c2;
-
-    while (n--) {
-        c1 = (unsigned char)*s1++;
-        c2 = (unsigned char)*s2++;
-        if (c1 == '\0' || c2 == '\0') {
-            if (c1 != '\0') return 1;
-            if (c2 != '\0') return -1;
-            return 0;
-        }
-        if ((unsigned int)(c1 - 'A') <= ('Z' - 'A')) c1 += 'a' - 'A';
-        if ((unsigned int)(c2 - 'A') <= ('Z' - 'A')) c2 += 'a' - 'A';
-        if (c1 != c2) {
-            if (c1 > c2)
-                return 1;
-            else
-                return -1;
-        }
-    }
-    return 0;
-}
-
-static int
-strcasehash(register const char *string)
-{
-    register unsigned int hval = FNV1_32A_INIT;
-
-    /*
-     * FNV-1a hash each octet in the buffer
-     */
-    while (*string) {
-	unsigned int c = (unsigned char)*string++;
-	if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
-	hval ^= c;
-
-	/* multiply by the 32 bit FNV magic prime mod 2^32 */
-	hval *= FNV_32_PRIME;
-    }
-    return hval;
-}
-
-int
-st_numcmp(st_data_t x, st_data_t y)
-{
-    return x != y;
-}
-
-int
-st_numhash(st_data_t n)
-{
-    return (int)n;
-}

Deleted: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/string.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,6828 +0,0 @@
-/* 
- * MacRuby Strings.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <wctype.h>
-#include <unistd.h>
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "re.h"
-#include "objc.h"
-#include "id.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "class.h"
-#include "encoding_ucnv.h"
-
-#include <unicode/unum.h>
-#include <unicode/utrans.h>
-
-VALUE rb_cRubyString;
-
-VALUE rb_fs;
-
-// rb_str_t primitives.
-
-static void
-str_update_flags_utf16(rb_str_t *self)
-{
-    assert(IS_UTF16_ENC(self->encoding));
-
-    bool ascii_only = true;
-    bool valid_encoding = true;
-    // if the length is an odd number, it can't be valid UTF-16
-    if (ODD_NUMBER(self->length_in_bytes)) {
-	valid_encoding = false;
-    }
-
-    UChar *uchars = (UChar *)self->bytes;
-    long uchars_count = BYTES_TO_UCHARS(self->length_in_bytes);
-    bool native_byte_order = IS_NATIVE_UTF16_ENC(self->encoding);
-    UChar32 lead = 0;
-    for (int i = 0; i < uchars_count; ++i) {
-	UChar32 c;
-	if (native_byte_order) {
-	    c = uchars[i];
-	}
-	else {
-	    uint8_t *bytes = (uint8_t *)&uchars[i];
-	    c = (uint16_t)bytes[0] << 8 | (uint16_t)bytes[1];
-	}
-	if (U16_IS_SURROGATE(c)) { // surrogate
-	    if (U16_IS_SURROGATE_LEAD(c)) { // lead surrogate
-		// a lead surrogate should not be
-		// after an other lead surrogate
-		if (lead != 0) {
-		    valid_encoding = false;
-		}
-		lead = c;
-	    }
-	    else { // trail surrogate
-		// a trail surrogate must follow a lead surrogate
-		if (lead == 0) {
-		    valid_encoding = false;
-		}
-		else {
-		    c = U16_GET_SUPPLEMENTARY(lead, c);
-		    if (!U_IS_UNICODE_CHAR(c)) {
-			valid_encoding = false;
-		    }
-		}
-		lead = 0;
-	    }
-	}
-	else { // not a surrogate
-	    // a non-surrogate character should not be after a lead surrogate
-	    // and it should be a valid Unicode character
-	    // Warning: Ruby 1.9 does not do the IS_UNICODE_CHAR check
-	    // (for 1.9, 0xffff is valid though it's not a Unicode character)
-	    if ((lead != 0) || !U_IS_UNICODE_CHAR(c)) {
-		valid_encoding = false;
-	    }
-
-	    if (c > 127) {
-		ascii_only = false;
-	    }
-	}
-    }
-    // the last character should not be a lead surrogate
-    if (lead != 0) {
-	valid_encoding = false;
-    }
-
-    if (valid_encoding) {
-	str_set_valid_encoding(self, true);
-	str_set_ascii_only(self, ascii_only);
-    }
-    else {
-	str_set_valid_encoding(self, false);
-	str_set_ascii_only(self, false);
-    }
-}
-
-void
-str_update_flags(rb_str_t *self)
-{
-    if (self->length_in_bytes == 0) {
-	str_set_valid_encoding(self, true);
-	str_set_ascii_only(self, true);
-    }
-    else if (IS_BINARY_ENC(self->encoding)) {
-	str_set_valid_encoding(self, true);
-	bool ascii_only = true;
-	for (long i = 0; i < self->length_in_bytes; ++i) {
-	    if ((uint8_t)self->bytes[i] > 127) {
-		ascii_only = false;
-		break;
-	    }
-	}
-	str_set_ascii_only(self, ascii_only);
-    }
-    else if (IS_UTF8_ENC(self->encoding)) {
-	bool ascii_only = true;
-	bool valid_encoding = true;
-
-	for (int i = 0; i < self->length_in_bytes; ) {
-	    UChar32 c;
-	    U8_NEXT(self->bytes, i, self->length_in_bytes, c);
-	    if (c == U_SENTINEL) {
-		valid_encoding = false;
-		ascii_only = false;
-		break;
-	    }
-	    else if (c > 127) {
-		ascii_only = false;
-	    }
-	}
-
-	str_set_valid_encoding(self, valid_encoding);
-	str_set_ascii_only(self, ascii_only);
-    }
-    else if (IS_UTF16_ENC(self->encoding)) {
-	str_update_flags_utf16(self);
-    }
-    else {
-	str_ucnv_update_flags(self);
-    }
-}
-
-static rb_encoding_t *
-str_compatible_encoding(rb_str_t *str1, rb_str_t *str2)
-{
-    if (str1->encoding == str2->encoding) {
-	return str1->encoding;
-    }
-    if (str2->length_in_bytes == 0) {
-	return str1->encoding;
-    }
-    if (str1->length_in_bytes == 0) {
-	return str2->encoding;
-    }
-    if (!str1->encoding->ascii_compatible
-	    || !str2->encoding->ascii_compatible) {
-	return NULL;
-    }
-    if (str_is_ruby_ascii_only(str2)) {
-	return str1->encoding;
-    }
-    if (str_is_ruby_ascii_only(str1)) {
-	return str2->encoding;
-    }
-    return NULL;
-}
-
-static rb_encoding_t *
-str_must_have_compatible_encoding(rb_str_t *str1, rb_str_t *str2)
-{
-    rb_encoding_t *new_encoding = str_compatible_encoding(str1, str2);
-    if (new_encoding == NULL) {
-	rb_raise(rb_eEncCompatError,
-		"incompatible character encodings: %s and %s",
-		str1->encoding->public_name, str2->encoding->public_name);
-    }
-    return new_encoding;
-}
-
-static void
-str_modifiable(VALUE str)
-{
-    if (OBJ_FROZEN(str)) {
-	rb_error_frozen("string");
-    }
-    if (!OBJ_UNTRUSTED(str) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't modify string");
-    }
-}
-
-static rb_str_t *
-str_alloc(VALUE klass)
-{
-    assert(rb_klass_is_rstr(klass));
-    assert(klass != 0);
-
-    NEWOBJ(str, rb_str_t);
-    str->basic.flags = 0;
-    str->basic.klass = klass;
-    str->encoding = rb_encodings[ENCODING_UTF8];
-    str->capacity_in_bytes = 0;
-    str->length_in_bytes = 0;
-    str->bytes = NULL;
-    str_reset_flags(str);
-
-    return str;
-}
-
-static VALUE
-str_new(void)
-{
-    return (VALUE)str_alloc(rb_cRubyString);
-}
-
-static VALUE
-str_new_like(VALUE obj)
-{
-    return (VALUE)str_alloc(rb_obj_class(obj));
-}
-
-static void
-str_replace_with_bytes(rb_str_t *self, const char *bytes, long len,
-	rb_encoding_t *enc)
-{
-    assert(len >= 0);
-    assert(enc != NULL);
-
-    str_reset_flags(self);
-    self->encoding = enc;
-    self->capacity_in_bytes = len;
-    if (len > 0) {
-	GC_WB(&self->bytes, xmalloc(len));
-	if (bytes != NULL) {
-	    memcpy(self->bytes, bytes, len);
-	    self->length_in_bytes = len;
-	}
-	else {
-	    self->length_in_bytes = 0;
-	}
-    }
-    else {
-	self->bytes = NULL;
-	self->length_in_bytes = 0;
-    }
-}
-
-void
-str_replace_with_string(rb_str_t *self, rb_str_t *source)
-{
-    if (self == source) {
-	return;
-    }
-    str_replace_with_bytes(self, source->bytes, source->length_in_bytes,
-	    source->encoding);
-    self->flags = source->flags;
-}
-
-static void str_resize_bytes(rb_str_t *self, long new_capacity);
-static void str_concat_bytes(rb_str_t *self, const char *bytes, long len);
-
-static void
-str_append_uchar32(rb_str_t *self, UChar32 c)
-{
-    str_reset_flags(self);
-    if ((c <= 127) && self->encoding->ascii_compatible) {
-	str_resize_bytes(self, self->length_in_bytes + 1);
-	self->bytes[self->length_in_bytes] = c;
-	self->length_in_bytes++;
-    }
-    else if (IS_UTF8_ENC(self->encoding)) {
-	long len = U8_LENGTH(c);
-	if (len > 0) {
-	    str_resize_bytes(self, self->length_in_bytes + len);
-	    U8_APPEND_UNSAFE(self->bytes, self->length_in_bytes, c);
-	    // U8_APPEND_UNSAFE increments length_in_bytes
-	    // by the number of bytes appended
-	}
-    }
-    else if (IS_NATIVE_UTF32_ENC(self->encoding)) {
-	str_concat_bytes(self, (char *)&c, 4);
-    }
-    else if (IS_NATIVE_UTF16_ENC(self->encoding) && U_IS_BMP(c)) {
-	UChar uchar = c;
-	str_concat_bytes(self, (char *)&uchar, 2);
-    }
-    else {
-	rb_str_t *str = RSTR(rb_enc_str_new((char *)&c, 4,
-		    rb_encodings[ENCODING_UTF32_NATIVE]));
-	str = str_simple_transcode(str, self->encoding);
-	str_concat_bytes(self, str->bytes, str->length_in_bytes);
-    }
-}
-
-static void str_concat_uchars(rb_str_t *self, const UChar *chars, long len);
-static void
-str_replace_with_uchars(rb_str_t *self, const UChar *chars, long len)
-{
-    assert(len >= 0);
-
-    str_reset_flags(self);
-    self->length_in_bytes = 0;
-    self->encoding = rb_encodings[ENCODING_UTF8];
-    if (len > 0) {
-	if (chars == NULL) {
-	    str_resize_bytes(self, len);
-	}
-	else if (self->bytes == (char *)chars) {
-	    self->length_in_bytes = UCHARS_TO_BYTES(len);
-	}
-	else {
-	    str_concat_uchars(self, chars, len);
-	}
-    }
-}
-
-static void
-str_replace_with_cfstring(rb_str_t *self, CFStringRef source)
-{
-    const long len = CFStringGetLength(source);
-    UniChar *chars = NULL;
-    if (len > 0) {
-	chars = (UniChar *)malloc(sizeof(UniChar) * len);
-	CFStringGetCharacters(source, CFRangeMake(0, len), chars);
-    }
-    str_replace_with_uchars(self, chars, len);
-    if (chars != NULL) {
-	free(chars);
-    }
-}
-
-static void
-str_replace(rb_str_t *self, VALUE arg)
-{
-    switch (TYPE(arg)) {
-	case T_STRING:
-	    if (IS_RSTR(arg)) {
-		str_replace_with_string(self, RSTR(arg));
-	    }
-	    else {
-		str_replace_with_cfstring(self, (CFStringRef)arg);
-	    }
-	    break;
-	default:
-	    str_replace(self, rb_str_to_str(arg));
-	    break;
-    }
-}
-
-static rb_str_t *
-str_dup(rb_str_t *source)
-{
-    rb_str_t *destination = str_alloc(rb_cRubyString);
-    str_replace_with_string(destination, source);
-    if (source->flags & STRING_ASCII_ONLY_SET) {
-	str_set_ascii_only(destination, str_is_ascii_only(source));
-    }
-    return destination;
-}
-
-static rb_str_t *
-str_new_from_cfstring(CFStringRef source)
-{
-    rb_str_t *destination = str_alloc(rb_cRubyString);
-    str_replace_with_cfstring(destination, source);
-    return destination;
-}
-
-static long
-str_length_with_cache(rb_str_t *self, character_boundaries_cache_t *cache)
-{
-    // fast paths
-    if (self->length_in_bytes == 0) {
-	return 0;
-    }
-    else if (self->encoding->single_byte_encoding
-	    || (self->encoding->ascii_compatible && str_is_ascii_only(self))) {
-	return self->length_in_bytes;
-    }
-    else if (IS_UTF16_ENC(self->encoding)) {
-	return div_round_up(self->length_in_bytes, 2);
-    }
-
-    if (cache != NULL
-	    && cache->cached_length >= 0) {
-	return cache->cached_length;
-    }
-
-    // slow paths
-    long length = 0;
-    if (IS_UTF8_ENC(self->encoding)) {
-	int i = 0;
-	while (i < self->length_in_bytes) {
-	    UChar32 c;
-	    int old_i = i;
-	    U8_NEXT(self->bytes, i, self->length_in_bytes, c);
-	    if (c == U_SENTINEL) {
-		length += i - old_i;
-	    }
-	    else if (U_IS_BMP(c)) {
-		length++;
-	    }
-	    else {
-		length += 2;
-	    }
-	}
-    }
-    else {
-	length = str_ucnv_length(self, true);
-    }
-
-    if (cache != NULL) {
-	cache->cached_length = length;
-    }
-    return length;
-}
-
-static long
-str_length(rb_str_t *self)
-{
-    return str_length_with_cache(self, NULL);
-}
-
-NORETURN(static void
-str_invalid_byte_sequence(rb_str_t *str))
-{
-    rb_raise(rb_eArgError, "invalid byte sequence in %s", str->encoding->public_name);
-}
-
-// Note that each_uchar32 iterates on Unicode characters
-// With a character not in the BMP the callback will only be called once!
-// start_offset_in_bytes MUST be at a character boundary
-static void
-str_each_uchar32_starting_from(rb_str_t *self,
-	long start_offset_in_bytes,
-	each_uchar32_callback_t callback)
-{
-    if (IS_BINARY_ENC(self->encoding) || IS_ASCII_ENC(self->encoding)) {
-	bool stop = false;
-	for (long i = start_offset_in_bytes; i < self->length_in_bytes; ++i) {
-	    UChar32 c = (uint8_t)self->bytes[i];
-	    if (!IS_BINARY_ENC(self->encoding) && c > 127) {
-		c = U_SENTINEL;
-	    }
-	    callback(c, i, 1, &stop);
-	    if (stop) {
-		return;
-	    }
-	}
-    }
-    else if (IS_UTF8_ENC(self->encoding)) {
-	bool stop = false;
-	for (int i = start_offset_in_bytes; i < self->length_in_bytes; ) {
-	    UChar32 c;
-	    int old_i = i;
-	    U8_NEXT(self->bytes, i, self->length_in_bytes, c);
-	    int char_length = i - old_i;
-	    if (c == U_SENTINEL) {
-		for (long j = 0; j < char_length; ++j) {
-		    callback(c, old_i+j, 1, &stop);
-		    if (stop) {
-			return;
-		    }
-		}
-	    }
-	    else {
-		callback(c, old_i, char_length, &stop);
-		if (stop) {
-		    return;
-		}
-	    }
-	};
-    }
-    else if (IS_NATIVE_UTF16_ENC(self->encoding)) {
-	assert(!ODD_NUMBER(start_offset_in_bytes));
-	bool stop = false;
-	long length = BYTES_TO_UCHARS(self->length_in_bytes);
-	UChar *uchars = (UChar *)self->bytes;
-	for (long i = 0; i < length;) {
-	    UChar32 c;
-	    long old_i = i;
-	    U16_NEXT(uchars, i, length, c);
-	    callback(c, UCHARS_TO_BYTES(old_i),
-		    UCHARS_TO_BYTES(i-old_i), &stop);
-	    if (stop) {
-		return;
-	    }
-	    // in case the length changed
-	    // (it should not happen but never know)
-	    length = BYTES_TO_UCHARS(self->length_in_bytes);
-	};
-    }
-    else {
-	str_ucnv_each_uchar32_starting_from(self,
-		start_offset_in_bytes, callback);
-    }
-}
-
-static void
-str_each_uchar32(rb_str_t *self, each_uchar32_callback_t callback)
-{
-    str_each_uchar32_starting_from(self, 0, callback);
-}
-
-static UChar
-str_get_uchar(rb_str_t *self, long pos)
-{
-    assert(pos >= 0 && pos < str_length(self));
-
-    if (IS_NATIVE_UTF16_ENC(self->encoding)) {
-	return ((UChar *)self->bytes)[pos];
-    }
-
-    __block UChar return_value = 0;
-    __block long i = 0;
-    str_each_uchar32(self, ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	if (c == U_SENTINEL || U_IS_BMP(c)) {
-	    if (i == pos) {
-		return_value = c;
-		*stop = true;
-	    }
-	    else {
-		++i;
-	    }
-	}
-	else {
-	    if (i == pos) {
-		return_value = U16_LEAD(c);
-		*stop = true;
-	    }
-	    else if (i+1 == pos) {
-		return_value = U16_TRAIL(c);
-		*stop = true;
-	    }
-	    else {
-		i += 2;
-	    }
-	}
-    });
-
-    return return_value;
-}
-
-static long
-str_bytesize(rb_str_t *self)
-{
-    return self->length_in_bytes;
-}
-
-static rb_str_t *
-str_new_similar_empty_string(rb_str_t *self)
-{
-    rb_str_t *str = str_alloc(rb_cRubyString);
-    str->encoding = self->encoding;
-    return str;
-}
-
-static rb_str_t *
-str_new_copy_of_part(rb_str_t *self, long offset_in_bytes,
-	long length_in_bytes)
-{
-    assert(length_in_bytes > 0);
-    rb_str_t *str = str_alloc(rb_cRubyString);
-    str->encoding = self->encoding;
-    str->capacity_in_bytes = str->length_in_bytes = length_in_bytes;
-    GC_WB(&str->bytes, xmalloc(length_in_bytes));
-    memcpy(str->bytes, &self->bytes[offset_in_bytes],
-	    length_in_bytes);
-    if ((self->flags & STRING_ASCII_ONLY_SET) && (self->flags & STRING_ASCII_ONLY)) {
-	// if the source string is ASCII only,
-	// then a part of that string is also ASCII only
-	str_set_ascii_only(str, true);
-    }
-    return str;
-}
-
-// you cannot cut a surrogate in an encoding that is not UTF-16
-// (it's in theory possible to store the surrogate in
-//  UTF-8 or UTF-32 but that would be incorrect Unicode)
-NORETURN(static void
-str_cannot_cut_surrogate(void))
-{
-    rb_raise(rb_eIndexError, "You can't cut a surrogate in two in an encoding that is not UTF-16");
-}
-
-static character_boundaries_t
-str_get_character_boundaries(rb_str_t *self, long index,
-	character_boundaries_cache_t *cache)
-{
-    character_boundaries_t boundaries = {-1, -1};
-
-    // fast paths
-    if (self->encoding->single_byte_encoding
-	    || (self->encoding->ascii_compatible && str_is_ascii_only(self))) {
-	if (index < 0) {
-	    index += self->length_in_bytes;
-	    if (index < 0) {
-		return boundaries;
-	    }
-	}
-	boundaries.start_offset_in_bytes = index;
-	boundaries.end_offset_in_bytes = boundaries.start_offset_in_bytes + 1;
-
-	return boundaries; // getting the offset is fast so no use caching it
-    }
-    else if (IS_UTF16_ENC(self->encoding)) {
-	if (index < 0) {
-	    index += div_round_up(self->length_in_bytes, 2);
-	    if (index < 0) {
-		return boundaries;
-	    }
-	}
-	boundaries.start_offset_in_bytes = UCHARS_TO_BYTES(index);
-	boundaries.end_offset_in_bytes = boundaries.start_offset_in_bytes + 2;
-
-	return boundaries; // getting the offset is fast so no use caching it
-    }
-
-    // slow path
-    if (index < 0) {
-	index += str_length_with_cache(self, cache);
-	if (index < 0) {
-	    return boundaries;
-	}
-    }
-
-    bool can_use_cache = (cache != NULL
-	    && cache->cached_boundaries_index >= 0);
-    if (can_use_cache && cache->cached_boundaries_index == index) {
-	return cache->cached_boundaries;
-    }
-
-    if (IS_UTF8_ENC(self->encoding)) {
-	long pos = 0;
-	int index_in_bytes = 0;
-	if (can_use_cache && cache->cached_boundaries_index < index) {
-	    // if we are in the middle of a non-BMP character,
-	    // end_offset_in_bytes or start_offset_in_bytes might be -1
-	    if (cache->cached_boundaries.end_offset_in_bytes == -1) {
-		index_in_bytes = cache->cached_boundaries.start_offset_in_bytes;
-		pos = cache->cached_boundaries_index;
-	    }
-	    else {
-		index_in_bytes = cache->cached_boundaries.end_offset_in_bytes;
-		pos = cache->cached_boundaries_index + 1;
-	    }
-	}
-	while (index_in_bytes < self->length_in_bytes) {
-	    UChar32 c;
-	    int old_index_in_bytes = index_in_bytes;
-	    long new_pos = pos;
-	    U8_NEXT(self->bytes, index_in_bytes, self->length_in_bytes, c);
-	    if (c == U_SENTINEL) {
-		new_pos += index_in_bytes - old_index_in_bytes;
-		if (new_pos > index) {
-		    boundaries.start_offset_in_bytes =
-			old_index_in_bytes + (index - pos);
-		    boundaries.end_offset_in_bytes =
-			boundaries.start_offset_in_bytes + 1;
-		    break;
-		}
-	    }
-	    else if (U_IS_BMP(c)) {
-		new_pos++;
-		if (new_pos > index) {
-		    boundaries.start_offset_in_bytes = old_index_in_bytes;
-		    boundaries.end_offset_in_bytes = index_in_bytes;
-		    break;
-		}
-	    }
-	    else {
-		new_pos += 2;
-		if (new_pos > index) {
-		    if (index == pos) {
-			boundaries.start_offset_in_bytes = old_index_in_bytes;
-		    }
-		    else {
-			assert(index == pos + 1);
-			boundaries.end_offset_in_bytes = index_in_bytes;
-		    }
-		    break;
-		}
-	    }
-	    pos = new_pos;
-	}
-    }
-    else {
-	boundaries = str_ucnv_get_character_boundaries(self, index, true);
-    }
-
-    if (cache != NULL) {
-	cache->cached_boundaries_index = index;
-	cache->cached_boundaries = boundaries;
-    }
-
-    return boundaries;
-}
-
-static rb_str_t *
-str_get_characters(rb_str_t *self, long first, long last,
-	character_boundaries_cache_t *cache)
-{
-    if (self->length_in_bytes == 0) {
-	if (first == 0) {
-	    return str_new_similar_empty_string(self);
-	}
-	else {
-	    return NULL;
-	}
-    }
-
-    character_boundaries_cache_t local_cache;
-    if (cache == NULL) {
-	reset_character_boundaries_cache(&local_cache);
-	cache = &local_cache;
-    }
-
-    character_boundaries_t first_boundaries =
-	str_get_character_boundaries(self, first, cache);
-    character_boundaries_t last_boundaries =
-	str_get_character_boundaries(self, last, cache);
-
-    if ((first_boundaries.start_offset_in_bytes == -1) ||
-	    (last_boundaries.end_offset_in_bytes == -1)) {
-	// you cannot cut a surrogate in an encoding that is not UTF-16
-	str_cannot_cut_surrogate();
-    }
-
-    if (first_boundaries.start_offset_in_bytes == self->length_in_bytes) {
-	return str_new_similar_empty_string(self);
-    }
-    else if (first_boundaries.start_offset_in_bytes > self->length_in_bytes) {
-	return NULL;
-    }
-    if (last_boundaries.end_offset_in_bytes >= self->length_in_bytes) {
-	last_boundaries.end_offset_in_bytes = self->length_in_bytes;
-    }
-
-    return str_new_copy_of_part(self, first_boundaries.start_offset_in_bytes,
-	    last_boundaries.end_offset_in_bytes
-	    - first_boundaries.start_offset_in_bytes);
-}
-
-static void
-str_resize_bytes(rb_str_t *self, long new_capacity)
-{
-    if (new_capacity < 0) {
-	rb_raise(rb_eArgError, "negative string size (or size too big)");
-    }
-    if (self->capacity_in_bytes < new_capacity) {
-	if (self->bytes == NULL) {
-	    GC_WB(&self->bytes, xmalloc(new_capacity));
-	}
-	else {
-	    char *bytes = xrealloc(self->bytes, new_capacity);
-	    if (bytes != self->bytes) {
-		GC_WB(&self->bytes, bytes);
-	    }
-	}
-	self->capacity_in_bytes = new_capacity;
-    }
-}
-
-static void
-str_ensure_null_terminator(rb_str_t *self)
-{
-    if (self->length_in_bytes > 0
-	&& (self->capacity_in_bytes == self->length_in_bytes
-	    || self->bytes[self->length_in_bytes] != '\0')) {
-	str_resize_bytes(self, self->length_in_bytes + 1);
-	self->bytes[self->length_in_bytes] = '\0';
-    }
-}
-
-static void
-str_splice(rb_str_t *self, long pos, long len, rb_str_t *str)
-{
-    // self[pos..pos+len] = str
-    assert(pos >= 0 && len >= 0);
-
-    if (str != NULL) {
-	str_must_have_compatible_encoding(self, str);
-    }
-
-    character_boundaries_t beg, end;
-    if (pos + len == 0) {
-	// Positioning before the string.
-	const long offset = 0;
-	beg.start_offset_in_bytes = beg.end_offset_in_bytes = offset;
-	end.start_offset_in_bytes = end.end_offset_in_bytes = offset;
-    }
-    else if (len == 0 && str_length(self) == pos) {
-	// Positioning after the string.
-	const long offset = self->length_in_bytes;
-	beg.start_offset_in_bytes = beg.end_offset_in_bytes = offset;
-	end.start_offset_in_bytes = end.end_offset_in_bytes = offset;
-    }
-    else {
-	character_boundaries_cache_t local_cache;
-	reset_character_boundaries_cache(&local_cache);
-
-	// Positioning in the string.
-	beg = str_get_character_boundaries(self, pos, &local_cache);
-	end = str_get_character_boundaries(self, pos + len - 1, &local_cache);
-
-	if ((beg.start_offset_in_bytes == -1) ||
-		(end.end_offset_in_bytes == -1)) {
-	    // you cannot cut a surrogate in an encoding that is not UTF-16
-	    str_cannot_cut_surrogate();
-	}
-    }
-
-    const long bytes_to_splice = end.end_offset_in_bytes
-	- beg.start_offset_in_bytes;
-
-    long bytes_to_add = 0; 
-    if (str != NULL) {
-	if (str->length_in_bytes > bytes_to_splice) {
-	    str_resize_bytes(self, self->length_in_bytes
-		    + (str->length_in_bytes - bytes_to_splice));
-	}
-	bytes_to_add = str->length_in_bytes;
-    }
-
-    if (beg.start_offset_in_bytes == end.end_offset_in_bytes
-	    && end.end_offset_in_bytes == self->length_in_bytes) {
-    	if (bytes_to_add > 0) {
-	    // We are splicing at the very end.
-	    memcpy(self->bytes + self->length_in_bytes, str->bytes,
-		    bytes_to_add);
-	}
-    }
-    else {
-	// We are splicing in the middle.
-	memmove(self->bytes + beg.start_offset_in_bytes + bytes_to_add,
-		self->bytes + end.end_offset_in_bytes,
-		self->length_in_bytes - end.end_offset_in_bytes);
-	if (bytes_to_add > 0) {
-	    memcpy(self->bytes + beg.start_offset_in_bytes,
-		    str->bytes, bytes_to_add);
-	}
-    }
-
-    self->length_in_bytes = self->length_in_bytes - bytes_to_splice
-	+ bytes_to_add; 
-}
-
-static void
-str_delete(rb_str_t *self, long pos, long len)
-{
-    str_splice(self, pos, len, NULL);
-}
-
-static void
-str_insert(rb_str_t *self, long pos, rb_str_t *str)
-{
-    str_splice(self, pos, 0, str);
-}
-
-static void
-str_concat_bytes(rb_str_t *self, const char *bytes, long len)
-{
-    assert(bytes != NULL && len >= 0);
-
-    const long new_length_in_bytes = self->length_in_bytes + len;
-
-    str_reset_flags(self);
-    str_resize_bytes(self, new_length_in_bytes);
-    memcpy(self->bytes + self->length_in_bytes, bytes, len);
-    self->length_in_bytes = new_length_in_bytes;
-}
-
-static void
-str_concat_uchars(rb_str_t *self, const UChar *chars, long len)
-{
-    if (len == 0) {
-	return;
-    }
-    str_reset_flags(self);
-    if (IS_UTF8_ENC(self->encoding)) {
-	long new_length_in_bytes = self->length_in_bytes;
-	for (long i = 0; i < len; ) {
-	    UChar32 c;
-	    U16_NEXT(chars, i, len, c);
-	    new_length_in_bytes += U8_LENGTH(c);
-	}
-	str_resize_bytes(self, new_length_in_bytes);
-	for (long pos_in_src = 0, pos_in_dst = self->length_in_bytes;
-		pos_in_src < len; ) {
-	    UChar32 c;
-	    UBool is_error;
-	    U16_NEXT(chars, pos_in_src, len, c);
-	    U8_APPEND((uint8_t *)self->bytes, pos_in_dst,
-		    new_length_in_bytes, c, is_error);
-	}
-	self->length_in_bytes = new_length_in_bytes;
-    }
-    else if (IS_NATIVE_UTF16_ENC(self->encoding)) {
-	str_concat_bytes(self, (char *)chars, UCHARS_TO_BYTES(len));
-    }
-    else if (IS_BINARY_ENC(self->encoding) || IS_ASCII_ENC(self->encoding)) {
-	const long new_length_in_bytes = RSTR(self)->length_in_bytes + len;
-
-	str_resize_bytes(self, new_length_in_bytes);
-	char *ptr = (RSTR(self)->bytes + RSTR(self)->length_in_bytes);
-	for (int i = 0; i < len; ++i) {
-	    ptr[i] = chars[i];
-	}
-	self->length_in_bytes = new_length_in_bytes;
-    }
-    else {
-	rb_str_t *str = RSTR(rb_enc_str_new((char *)chars,
-		    UCHARS_TO_BYTES(len),
-		    rb_encodings[ENCODING_UTF16_NATIVE]));
-	str = str_simple_transcode(str, self->encoding);
-	str_concat_bytes(self, str->bytes, str->length_in_bytes);
-    }
-}
-
-static void
-str_concat_string(rb_str_t *self, rb_str_t *str)
-{
-    if (str->length_in_bytes == 0) {
-	return;
-    }
-
-    rb_encoding_t *enc = str_must_have_compatible_encoding(self, str);
-    str_reset_flags(self);
-    self->encoding = enc;
-    str_concat_bytes(self, str->bytes, str->length_in_bytes);
-}
-
-static void
-str_concat_string_part(rb_str_t *self, rb_str_t *str, long start, long len,
-	character_boundaries_cache_t *cache_for_str)
-{
-    assert(len >= 0 && start >= 0);
-    if (len == 0) {
-	return;
-    }
-
-    rb_encoding_t *enc = str_must_have_compatible_encoding(self, str);
-    str_reset_flags(self);
-    self->encoding = enc;
-
-    character_boundaries_t first_boundaries =
-	str_get_character_boundaries(str, start, cache_for_str);
-    character_boundaries_t last_boundaries;
-    if (len == 1) {
-	last_boundaries = first_boundaries;
-    }
-    else {
-	last_boundaries = str_get_character_boundaries(str, start+len-1,
-		cache_for_str);
-    }
-
-    if ((first_boundaries.start_offset_in_bytes == -1) ||
-	    (last_boundaries.end_offset_in_bytes == -1)) {
-	// you cannot cut a surrogate in an encoding that is not UTF-16
-	str_cannot_cut_surrogate();
-    }
-
-    str_concat_bytes(self, &str->bytes[first_boundaries.start_offset_in_bytes],
-	    last_boundaries.end_offset_in_bytes -
-		first_boundaries.start_offset_in_bytes);
-}
-
-static int
-str_compare(rb_str_t *self, rb_str_t *str)
-{
-    if (self == str) {
-	return 0;
-    }
-
-    if (self->length_in_bytes == 0 && str->length_in_bytes == 0) {
-	// both strings are empty
-	return 0;
-    }
-
-    if (str_compatible_encoding(self, str) == NULL) {
-	// incompatible encodings
-	return -1;
-    }
-
-    const long min_len = self->length_in_bytes < str->length_in_bytes
-	? self->length_in_bytes : str->length_in_bytes;
-
-    const int res = memcmp(self->bytes, str->bytes, min_len);
-
-    if (res == 0) {
-	if (self->length_in_bytes == str->length_in_bytes) {
-	    return 0;
-	}
-	return self->length_in_bytes > str->length_in_bytes
-	    ? 1 : -1;
-    }
-    return res > 0 ? 1 : -1;
-}
-
-int
-rstr_compare(rb_str_t *str1, rb_str_t *str2)
-{
-    return str_compare(str1, str2);
-}
-
-static int
-str_case_compare(rb_str_t *self, rb_str_t *str)
-{
-    if (self == str) {
-	return 0;
-    }
-
-    if (self->length_in_bytes == 0 && str->length_in_bytes == 0) {
-	// both strings are empty
-	return 0;
-    }
-
-    if (str_compatible_encoding(self, str) == NULL) {
-	// incompatible encodings
-	return -1;
-    }
-
-    const long min_length = self->length_in_bytes < str->length_in_bytes
-	? self->length_in_bytes : str->length_in_bytes;
-
-    for (long i = 0; i < min_length; i++) {
-	char c1 = self->bytes[i];
-	char c2 = str->bytes[i];
-	if (c1 != c2) {
-	    c1 = isascii(c1) ? toupper(c1) : c1;
-	    c2 = isascii(c2) ? toupper(c2) : c2;
-	    if (c1 != c2) {
-		return c1 < c2 ? -1 : 1;
-	    }
-	}
-    }
-
-    if (self->length_in_bytes == str->length_in_bytes) {
-	return 0;
-    }
-    return self->length_in_bytes > str->length_in_bytes ? 1 : -1;
-}
-
-static long
-str_offset_in_bytes_to_index(rb_str_t *self, long offset_in_bytes)
-{
-    if ((offset_in_bytes >= self->length_in_bytes) || (offset_in_bytes < 0)) {
-	return -1;
-    }
-    if (offset_in_bytes == 0) {
-	return 0;
-    }
-
-    if (self->encoding->single_byte_encoding
-	    || (self->encoding->ascii_compatible && str_is_ascii_only(self))) {
-	return offset_in_bytes;
-    }
-    else if (IS_UTF16_ENC(self->encoding)) {
-	if (!ODD_NUMBER(offset_in_bytes)) {
-	    // if we are in the middle of a character, there's no valid index
-	    return -1;
-	}
-	return BYTES_TO_UCHARS(offset_in_bytes);
-    }
-    else {
-	return str_ucnv_offset_in_bytes_to_index(self, offset_in_bytes, true);
-    }
-}
-
-static long
-str_index_for_string_with_cache(rb_str_t *self, rb_str_t *searched,
-	long start_index, long end_index, bool backward_search,
-	character_boundaries_cache_t *cache)
-{
-    str_must_have_compatible_encoding(self, searched);
-
-    if (searched->length_in_bytes == 0 && self->length_in_bytes == 0) {
-	return start_index;
-    }
-    if (searched->length_in_bytes > self->length_in_bytes) {
-	return -1;
-    }
-
-    long start_offset_in_bytes;
-    if (start_index == 0) {
-	start_offset_in_bytes = 0;
-    }
-    else {
-	character_boundaries_t boundaries = str_get_character_boundaries(self,
-		start_index, cache);
-	if (boundaries.start_offset_in_bytes == -1) {
-	    if (boundaries.end_offset_in_bytes == -1) {
-		return -1;
-	    }
-	    else {
-		// you cannot cut a surrogate in an encoding that is not UTF-16
-		str_cannot_cut_surrogate();
-	    }
-	}
-	start_offset_in_bytes = boundaries.start_offset_in_bytes;
-    }
-
-    if (self == searched) {
-	if (start_offset_in_bytes == 0) {
-	    return 0;
-	}
-	else {
-	    return -1;
-	}
-    }
-
-    if (start_offset_in_bytes >= self->length_in_bytes) {
-	return -1;
-    }
-
-    long last_offset_in_bytes;
-    if (end_index < 0
-	    || end_index == str_length_with_cache(self, cache)) {
-	last_offset_in_bytes = self->length_in_bytes;
-    }
-    else {
-	character_boundaries_t boundaries = str_get_character_boundaries(self,
-		end_index, cache);
-	if (boundaries.start_offset_in_bytes == -1) {
-	    if (boundaries.end_offset_in_bytes == -1) {
-		return -1;
-	    }
-	    else {
-		// you cannot cut a surrogate in an encoding that is not UTF-16
-		str_cannot_cut_surrogate();
-	    }
-	}
-	last_offset_in_bytes = boundaries.start_offset_in_bytes;
-    }
-    long min_end_offset = self->length_in_bytes - searched->length_in_bytes;
-    if (last_offset_in_bytes > min_end_offset) {
-	last_offset_in_bytes = min_end_offset;
-    }
-
-    if (!backward_search) {
-	if (searched->length_in_bytes == 0) {
-	    assert(start_index >= 0);
-	    return start_index;
-	}
-	__block long returned_index = -1;
-	__block long current_index = start_index;
-	str_each_uchar32_starting_from(self, start_offset_in_bytes,
-		^(UChar32 c, long character_start_offset, long char_len, bool *stop) {
-	    if (character_start_offset > last_offset_in_bytes) {
-		// not enough characters left: we could not find the string
-		*stop = true;
-		return;
-	    }
-	    if (memcmp(self->bytes + character_start_offset,
-		    searched->bytes, searched->length_in_bytes) == 0) {
-		returned_index = current_index;
-		*stop = true;
-		return;
-	    }
-	    ++current_index;
-	});
-	return returned_index;
-    }
-
-    // backward search
-    if (searched->length_in_bytes == 0) {
-	if (end_index < 0) {
-	    return str_length_with_cache(self, cache);
-	}
-	else {
-	    return end_index;
-	}
-    }
-
-    for (;;) {
-	long offset_found = -1;
-	for (long offset = last_offset_in_bytes;
-		offset >= start_offset_in_bytes;
-		--offset) {
-	    if (memcmp(self->bytes + offset, searched->bytes,
-			searched->length_in_bytes) == 0) {
-		offset_found = offset;
-		break;
-	    }
-	}
-	if (offset_found < 0) {
-	    // not found
-	    return -1;
-	}
-
-	long index = str_offset_in_bytes_to_index(RSTR(self), offset_found);
-	if (index != -1) {
-	    // the offset was valid, at the start of a character
-	    return index;
-	}
-
-	last_offset_in_bytes = offset_found - 1;
-    }
-}
-
-static long
-str_index_for_string(rb_str_t *self, rb_str_t *searched, long start_index,
-	long end_index, bool backward_search)
-{
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-    return str_index_for_string_with_cache(self, searched, start_index,
-	    end_index, backward_search, &local_cache);
-}
-
-static bool
-str_include_string(rb_str_t *self, rb_str_t *searched)
-{
-    return str_index_for_string_with_cache(self, searched,
-	0, -1, false, NULL) != -1;
-}
-
-rb_str_t *
-str_need_string(VALUE str)
-{
-    switch (TYPE(str)) {
-	case T_SYMBOL:
-	    str = rb_sym_to_s(str);
-	    break;
-
-	case T_STRING:
-	    break;
-
-	default:
-	    str = rb_str_to_str(str);
-	    break;
-    }
-    return IS_RSTR(str)
-	? (rb_str_t *)str : str_new_from_cfstring((CFStringRef)str);
-}
-
-static void
-str_extract_uchars_range(rb_str_t *self, long range_start_offset_in_uchars,
-	long range_length_in_uchars, UChar *buffer)
-{
-    if (range_length_in_uchars <= 0) {
-	return;
-    }
-    if (self->encoding->ascii_compatible && str_is_ascii_only(self)) {
-	char *source_bytes = &self->bytes[range_start_offset_in_uchars];
-	for (long i = 0; i < range_length_in_uchars; ++i) {
-	    buffer[i] = source_bytes[i];
-	}
-    }
-    else if (IS_UTF8_ENC(self->encoding)) {
-	long pos_in_src = 0;
-	long pos_in_dst = 0;
-	for (int i = 0; i < self->length_in_bytes; ) {
-	    UChar32 c;
-	    int old_i = i;
-	    U8_NEXT(self->bytes, i, self->length_in_bytes, c);
-	    if (c == U_SENTINEL) {
-		int diff = i - old_i;
-		if (pos_in_src + diff > range_start_offset_in_uchars) {
-		    int start = range_start_offset_in_uchars - pos_in_src;
-		    if (start < 0) {
-			start = 0;
-		    }
-		    for (int j = start; j < diff && pos_in_dst < range_length_in_uchars; ++j) {
-			buffer[pos_in_dst++] = self->bytes[old_i+j];
-		    }
-		}
-		pos_in_src += diff;
-	    }
-	    else if (U_IS_BMP(c)) {
-		if (pos_in_src >= range_start_offset_in_uchars) {
-		    buffer[pos_in_dst++] = c;
-		}
-		++pos_in_src;
-	    }
-	    else {
-		if (pos_in_src >= range_start_offset_in_uchars) {
-		    buffer[pos_in_dst++] = U16_LEAD(c);
-		    if (pos_in_dst < range_length_in_uchars) {
-			buffer[pos_in_dst++] = U16_TRAIL(c);
-		    }
-		}
-		else if (pos_in_src + 1 >= range_length_in_uchars) {
-		    buffer[pos_in_dst++] = U16_TRAIL(c);
-		}
-		pos_in_src += 2;
-	    }
-	    if (pos_in_dst >= range_length_in_uchars) {
-		break;
-	    }
-	}
-    }
-    else if (IS_NATIVE_UTF16_ENC(self->encoding)) {
-	memcpy(buffer,
-		&self->bytes[UCHARS_TO_BYTES(range_start_offset_in_uchars)],
-		UCHARS_TO_BYTES(range_length_in_uchars));
-    }
-    else {
-	__block long pos_in_src = 0;
-	__block long pos_in_dst = 0;
-	str_each_uchar32(self, ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	    if (pos_in_src >= range_start_offset_in_uchars) {
-		if (c == U_SENTINEL) {
-		    if (char_len == 1) {
-			buffer[pos_in_dst++] = self->bytes[start_index];
-		    }
-		    else {
-			UChar accumulator = 0;
-			if (self->encoding->little_endian) {
-			    for (long i = char_len-1; i >= 0; --i) {
-				accumulator = accumulator << 8
-				    | self->bytes[start_index+i];
-			    }
-			}
-			else {
-			    for (long i = 0; i < char_len; ++i) {
-				accumulator = accumulator << 8
-				    | self->bytes[start_index+i];
-			    }
-			}
-			buffer[pos_in_dst++] = accumulator;
-		    }
-		}
-		else if (U_IS_BMP(c)) {
-		    buffer[pos_in_dst++] = c;
-		}
-		else {
-		    buffer[pos_in_dst++] = U16_LEAD(c);
-		    if (pos_in_dst < range_length_in_uchars) {
-			buffer[pos_in_dst++] = U16_TRAIL(c);
-		    }
-		}
-	    }
-	    if ((c == U_SENTINEL) || U_IS_BMP(c)) {
-		pos_in_src++;
-	    }
-	    else {
-		if (pos_in_src + 1 == range_start_offset_in_uchars) {
-		    buffer[pos_in_dst++] = U16_TRAIL(c);
-		}
-		pos_in_src += 2;
-	    }
-	    if (pos_in_dst >= range_length_in_uchars) {
-		*stop = true;
-	    }
-	});
-	assert(pos_in_dst == range_length_in_uchars);
-    }
-}
-
-void
-rb_str_get_uchars_always(VALUE str, rb_str_uchars_buf_t *buf)
-{
-    long len = 0;
-
-    buf->chars = NULL;
-
-    if (IS_RSTR(str)) {
-	rb_str_t *rstr = RSTR(str);
-	if (rstr->length_in_bytes > 0) {
-	    len = str_length(rstr);
-	    if (IS_NATIVE_UTF16_ENC(rstr->encoding)) {
-		buf->chars = (UChar *)rstr->bytes;
-	    }
-	    else {
-		if (len > STR_UCHARS_STATIC_BUFSIZE) {
-		    buf->chars = (UChar *)malloc(sizeof(UChar) * len);
-		}
-		else {
-		    buf->chars = buf->static_buf;
-		}
-		str_extract_uchars_range(rstr, 0, len, buf->chars);
-	    }
-	}
-    }
-    else {
-	len = CFStringGetLength((CFStringRef)str);
-	if (len > 0) {
-	    if (len > STR_UCHARS_STATIC_BUFSIZE) {
-		buf->chars = (UChar *)malloc(sizeof(UChar) * len);
-	    }
-	    else {
-		buf->chars = buf->static_buf;
-	    }
-	    CFStringGetCharacters((CFStringRef)str, CFRangeMake(0, len),
-		    buf->chars);
-	}
-    }
-
-    buf->len = len;
-}
-
-UChar *
-rb_str_xcopy_uchars(VALUE str, long *len_p)
-{
-    UChar *chars = NULL;
-    long len = 0;
-
-    if (IS_RSTR(str)) {
-	rb_str_t *rstr = RSTR(str);
-	len = str_length(rstr);
-	if (len > 0) {
-	    chars = (UChar *)xmalloc(sizeof(UChar) * len);
-	    str_extract_uchars_range(rstr, 0, len, chars);
-	}
-    }
-    else {
-	len = CFStringGetLength((CFStringRef)str);
-	if (len > 0) {
-	    chars = (UChar *)xmalloc(sizeof(UChar) * len);
-	    CFStringGetCharacters((CFStringRef)str, CFRangeMake(0, len),
-		    chars);
-	}
-    }
-
-    if (len_p != NULL) {
-	*len_p = len;
-    }
-    return chars;
-}
-
-static VALUE
-rstr_substr_with_cache(VALUE str, long beg, long len,
-	character_boundaries_cache_t *cache)
-{
-    if (len < 0) {
-	return Qnil;
-    }
-
-    const long n = str_length_with_cache(RSTR(str), cache);
-    if (beg < 0) {
-	beg += n;
-    }
-    if (beg > n || beg < 0) {
-	return Qnil;
-    }
-    if (len == 0 || beg == n) {
-	return str_new();
-    }
-    if (beg + len > n) {
-	len = n - beg;
-    }
-
-    rb_str_t *substr = str_get_characters(RSTR(str), beg, beg + len - 1, cache);
-    OBJ_INFECT(substr, str);
-    return substr == NULL ? Qnil : (VALUE)substr;
-}
-
-static VALUE
-rstr_substr(VALUE str, long beg, long len)
-{
-    return rstr_substr_with_cache(str, beg, len, NULL);
-}
-
-static void
-rstr_splice(VALUE self, long beg, long len, VALUE str)
-{
-    rb_str_t *strstr = str_need_string(str);
-
-    if (len < 0) {
-	rb_raise(rb_eIndexError, "negative length %ld", len);
-    }
-
-    const long slen = str_length(RSTR(self));
-    if (slen < beg) {
-out_of_range:
-	rb_raise(rb_eIndexError, "index %ld out of string", beg);
-    }
-    if (beg < 0) {
-	if (-beg > slen) {
-	    goto out_of_range;
-	}
-	beg += slen;
-    }
-    if (slen < len || slen < beg + len) {
-	len = slen - beg;
-    }
-
-    rstr_modify(self);
-
-    str_splice(RSTR(self), beg, len, strstr);
-
-    if (OBJ_TAINTED(strstr)) {
-	OBJ_TAINT(self);
-    }
-}
-
-static void
-rstr_append(VALUE str, VALUE substr)
-{
-    str_concat_string(RSTR(str), str_need_string(substr));
-
-    if (OBJ_TAINTED(substr)) {
-	OBJ_TAINT(str);
-    }
-}
-
-static void inline
-str_concat_ascii_cstr(rb_str_t *self, char *cstr)
-{
-    long len = strlen(cstr);
-    if (self->encoding->ascii_compatible) {
-	str_concat_bytes(self, cstr, len);
-    }
-    else {
-	rb_str_t *str = RSTR(rb_enc_str_new(cstr, len, rb_encodings[ENCODING_ASCII]));
-	str = str_simple_transcode(str, self->encoding);
-	str_concat_bytes(self, str->bytes, str->length_in_bytes);
-    }
-}
-
-rb_str_t *
-str_transcode(rb_str_t *self, rb_encoding_t *src_encoding, rb_encoding_t *dst_encoding,
-	int behavior_for_invalid, int behavior_for_undefined, rb_str_t *replacement_str)
-{
-    if ((behavior_for_invalid == TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING)
-	   || (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING)) {
-	assert(replacement_str != NULL);
-	assert(replacement_str->encoding != NULL);
-	assert((replacement_str->length_in_bytes == 0) || (replacement_str->encoding == dst_encoding));
-    }
-
-    rb_str_t *dst_str = str_alloc(rb_cRubyString);
-    dst_str->encoding = dst_encoding;
-
-    if ((self->length_in_bytes == 0) &&
-	    (behavior_for_undefined != TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR)) {
-	return dst_str;
-    }
-
-    rb_encoding_t *src_encoding_used;
-    rb_encoding_t *dst_encoding_used;
-    if (IS_BINARY_ENC(dst_encoding)) {
-	dst_encoding_used = rb_encodings[ENCODING_ASCII];
-    }
-    else {
-	dst_encoding_used = dst_encoding;
-    }
-    if (IS_BINARY_ENC(src_encoding)) {
-	src_encoding_used = rb_encodings[ENCODING_ASCII];
-    }
-    else {
-	src_encoding_used = src_encoding;
-    }
-
-    if (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR) {
-	str_concat_ascii_cstr(dst_str, "\"");
-    }
-
-    long pos_in_src = 0;
-    for (;;) {
-	UChar *utf16;
-	long utf16_length;
-	// we need to transcode even if the source encoding is native UTF-16
-	// because it could contain invalid bytes
-	str_ucnv_transcode_to_utf16(src_encoding_used,
-		    self, &pos_in_src, &utf16, &utf16_length);
-
-	if (utf16_length > 0) {
-	    if ((behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_TEXT)
-		   || (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR)) {
-		long new_utf16_length = 0;
-		for (long i = 0; i < utf16_length; ++i) {
-		    switch (utf16[i]) {
-			case '&':
-			    new_utf16_length += 5;
-			    break;
-			case '<':
-			case '>':
-			    new_utf16_length += 4;
-			    break;
-			case '"':
-			    if (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR) {
-				new_utf16_length += 6;
-			    }
-			    else {
-				++new_utf16_length;
-			    }
-			    break;
-			default:
-			    ++new_utf16_length;
-		    }
-		}
-		if (new_utf16_length != utf16_length) {
-		    UChar *new_utf16 = xmalloc(UCHARS_TO_BYTES(new_utf16_length));
-		    long new_utf16_pos = 0;
-		    for (long i = 0; i < utf16_length; ++i) {
-			switch (utf16[i]) {
-			    case '&':
-				new_utf16[new_utf16_pos++] = '&';
-				new_utf16[new_utf16_pos++] = 'a';
-				new_utf16[new_utf16_pos++] = 'm';
-				new_utf16[new_utf16_pos++] = 'p';
-				new_utf16[new_utf16_pos++] = ';';
-				break;
-			    case '<':
-				new_utf16[new_utf16_pos++] = '&';
-				new_utf16[new_utf16_pos++] = 'l';
-				new_utf16[new_utf16_pos++] = 't';
-				new_utf16[new_utf16_pos++] = ';';
-				break;
-			    case '>':
-				new_utf16[new_utf16_pos++] = '&';
-				new_utf16[new_utf16_pos++] = 'g';
-				new_utf16[new_utf16_pos++] = 't';
-				new_utf16[new_utf16_pos++] = ';';
-				break;
-			    case '"':
-				if (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR) {
-				    new_utf16[new_utf16_pos++] = '&';
-				    new_utf16[new_utf16_pos++] = 'q';
-				    new_utf16[new_utf16_pos++] = 'u';
-				    new_utf16[new_utf16_pos++] = 'o';
-				    new_utf16[new_utf16_pos++] = 't';
-				    new_utf16[new_utf16_pos++] = ';';
-				}
-				else {
-				    new_utf16[new_utf16_pos++] = utf16[i];
-				}
-				break;
-			    default:
-				new_utf16[new_utf16_pos++] = utf16[i];
-			}
-		    }
-		    utf16_length = new_utf16_length;
-		    utf16 = new_utf16;
-		}
-	    }
-
-	    long utf16_pos = 0;
-	    for (;;) {
-		long bytes_length;
-		char *bytes;
-		str_ucnv_transcode_from_utf16(dst_encoding_used,
-			utf16, utf16_length, &utf16_pos, &bytes, &bytes_length);
-		if (bytes_length > 0) {
-		    str_concat_bytes(dst_str, bytes, bytes_length);
-		}
-		if (utf16_pos < utf16_length) {
-		    // undefined char
-		    UChar32 c;
-		    U16_NEXT(utf16, utf16_pos, utf16_length, c);
-		    switch (behavior_for_undefined) {
-			case TRANSCODE_BEHAVIOR_RAISE_EXCEPTION:
-			    rb_raise(rb_eUndefinedConversionError, "U+%04X from %s to %s", c, src_encoding->public_name, dst_encoding->public_name);
-			    break;
-			case TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING:
-			    if (replacement_str->length_in_bytes > 0) {
-				str_concat_bytes(dst_str, replacement_str->bytes, replacement_str->length_in_bytes);
-			    }
-			    break;
-			case TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_TEXT:
-			case TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR:
-			    {
-				char xml[10];
-				snprintf(xml, 10, "&#x%X;", c);
-				str_concat_ascii_cstr(dst_str, xml);
-			    }
-			    break;
-			default:
-			    abort();
-		    }
-		}
-		if (utf16_pos == utf16_length) {
-		    break;
-		}
-	    }
-	}
-
-	if (pos_in_src < self->length_in_bytes) {
-	    // invalid bytes
-	    long invalid_bytes_length = src_encoding->min_char_size;
-	    if (invalid_bytes_length + pos_in_src > self->length_in_bytes) {
-		invalid_bytes_length = self->length_in_bytes - pos_in_src;
-	    }
-	    switch (behavior_for_invalid) {
-		case TRANSCODE_BEHAVIOR_RAISE_EXCEPTION:
-		    {
-			char *bytes_list = xmalloc(invalid_bytes_length * 4);
-			char *bytes_list_pos = bytes_list;
-			for (long i = 0; i < invalid_bytes_length; ++i) {
-			    sprintf(bytes_list_pos, "\\x%02X", (unsigned char)self->bytes[pos_in_src+i]);
-			    bytes_list_pos += 4;
-			}
-			rb_raise(rb_eInvalidByteSequenceError, "\"%s\" on %s", bytes_list, src_encoding->public_name);
-		    }
-		    break;
-		case TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING:
-		    if (replacement_str->length_in_bytes > 0) {
-			str_concat_bytes(dst_str, replacement_str->bytes, replacement_str->length_in_bytes);
-		    }
-		    break;
-		default:
-		    abort();
-	    }
-	    pos_in_src += invalid_bytes_length;
-	}
-
-	if (pos_in_src == self->length_in_bytes) {
-	    break;
-	}
-    }
-
-    if (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR) {
-	str_concat_ascii_cstr(dst_str, "\"");
-    }
-
-    return dst_str;
-}
-
-
-//----------------------------------------------
-// Functions called by MacRuby
-
-VALUE
-mr_enc_s_is_compatible(VALUE klass, SEL sel, VALUE str1, VALUE str2)
-{
-    rb_encoding_t *encoding = str_compatible_encoding(str_need_string(str1),
-	    str_need_string(str2));
-    if (encoding == NULL) {
-	return Qnil;
-    }
-    return (VALUE)encoding;
-}
-
-static VALUE
-rstr_alloc(VALUE klass, SEL sel)
-{
-    return (VALUE)str_alloc(klass);
-}
-
-/*
- *  call-seq:
- *     String.try_convert(obj) -> string or nil
- *
- *  Try to convert <i>obj</i> into a String, using to_str method.
- *  Returns converted regexp or nil if <i>obj</i> cannot be converted
- *  for any reason.
- *
- *     String.try_convert("str")     # => str
- *     String.try_convert(/re/)      # => nil
- */
-
-static VALUE
-rstr_try_convert(VALUE self, SEL sel, VALUE other)
-{
-    return rb_check_string_type(other);
-}
-
-/*
- *  call-seq:
- *     str.replace(other_str)   => str
- *  
- *  Replaces the contents and taintedness of <i>str</i> with the corresponding
- *  values in <i>other_str</i>.
- *     
- *     s = "hello"         #=> "hello"
- *     s.replace "world"   #=> "world"
- */
-
-static VALUE
-rstr_replace(VALUE self, SEL sel, VALUE arg)
-{
-    rstr_modify(self);
-    str_replace(RSTR(self), arg);
-    if (OBJ_TAINTED(arg)) {
-	OBJ_TAINT(self);
-    }
-    return self;
-}
-
-/*
- *  call-seq:
- *     String.new(str="")   => new_str
- *  
- *  Returns a new string object containing a copy of <i>str</i>.
- */
-
-static VALUE
-rstr_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE orig;
-    if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1) {
-	rstr_modify(self);
-	if (self != orig) {
-	    rstr_replace(self, 0, orig);
-	}
-    }
-    return self;
-}
-
-static VALUE
-rstr_copy(VALUE rcv, VALUE klass)
-{
-    VALUE dup = rstr_alloc(klass, 0);
-    rstr_replace(dup, 0, rcv);
-    return dup;
-}
-
-static VALUE
-rstr_dup(VALUE str, SEL sel)
-{
-    VALUE klass = CLASS_OF(str);
-    while (RCLASS_SINGLETON(klass)) {
-	klass = RCLASS_SUPER(klass);
-    }
-    assert(rb_klass_is_rstr(klass));
-
-    VALUE dup = rstr_copy(str, klass);
-
-    OBJ_INFECT(dup, str);
-    return dup;
-}
-
-static VALUE
-rstr_clone(VALUE str, SEL sel)
-{
-    VALUE clone = rstr_copy(str, CLASS_OF(str));
-
-    OBJ_INFECT(clone, str);
-    if (OBJ_FROZEN(str)) {
-	OBJ_FREEZE(clone);
-    }
-    return clone;
-}
-
-/*
- *  call-seq:
- *     string.clear    ->  string
- *
- *  Makes string empty.
- *
- *     a = "abcde"
- *     a.clear    #=> ""
- */
-
-static VALUE
-rstr_clear(VALUE self, SEL sel)
-{
-    rstr_modify(self);
-    RSTR(self)->length_in_bytes = 0;
-    return self;
-}
-
-/*
- *  call-seq:
- *     str.length   => integer
- *     str.size     => integer
- *  
- *  Returns the character length of <i>str</i>.
- */
-
-static VALUE
-rstr_length(VALUE self, SEL sel)
-{
-    return INT2NUM(str_length(RSTR(self)));
-}
-
-/*
- *  call-seq:
- *     str.empty?   => true or false
- *  
- *  Returns <code>true</code> if <i>str</i> has a length of zero.
- *     
- *     "hello".empty?   #=> false
- *     "".empty?        #=> true
- */
-
-static VALUE
-rstr_empty(VALUE self, SEL sel)
-{
-    return RSTR(self)->length_in_bytes == 0 ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.bytesize  => integer
- *  
- *  Returns the length of <i>str</i> in bytes.
- */
-
-static VALUE
-rstr_bytesize(VALUE self, SEL sel)
-{
-    return INT2NUM(str_bytesize(RSTR(self)));
-}
-
-static VALUE
-rstr_encoding(VALUE self, SEL sel)
-{
-    return (VALUE)RSTR(self)->encoding;
-}
-
-/*
- *  call-seq:
- *     str.getbyte(index)          => 0 .. 255
- *
- *  returns the <i>index</i>th byte as an integer.
- */
-
-static VALUE
-rstr_getbyte(VALUE self, SEL sel, VALUE index)
-{
-    unsigned char c = 0;
-    long idx = NUM2LONG(index);
-
-    if (idx < 0) {
-	idx += RSTR(self)->length_in_bytes;
-	if (idx < 0) {
-	    return Qnil;
-	}
-    }
-    if (idx >= RSTR(self)->length_in_bytes) {
-	return Qnil;
-    }
-    c = RSTR(self)->bytes[idx];
-
-    return INT2FIX(c); 
-}
-
-/*
- *  call-seq:
- *     str.setbyte(index, int) => int
- *
- *  modifies the <i>index</i>th byte as <i>int</i>.
- */
-
-static VALUE
-rstr_setbyte(VALUE self, SEL sel, VALUE idx, VALUE value)
-{
-    rstr_modify(self);
-
-    long index = NUM2LONG(idx);
-    int byte = NUM2INT(value);
-    if ((index < -RSTR(self)->length_in_bytes)
-	    || (index >= RSTR(self)->length_in_bytes)) {
-	rb_raise(rb_eIndexError, "index %ld out of string", index);
-    }
-    if (index < 0) {
-	index += RSTR(self)->length_in_bytes;
-    }
-    str_reset_flags(RSTR(self));
-    RSTR(self)->bytes[index] = byte;
-    return value;
-}
-
-/*
- *  call-seq:
- *     str.to_data => NSData
- *
- *  returns an NSData object wrapping the receiver's internal storage.
- *  
- */
-
-static VALUE
-rstr_to_data(VALUE self, SEL sel)
-{
-    CFDataRef data = CFDataCreate(NULL, (const UInt8 *)RSTR(self)->bytes,
-	    RSTR(self)->length_in_bytes); 
-    CFMakeCollectable(data);
-    return (VALUE)data;
-}
-
-/*
- *  call-seq:
- *     str.pointer => Pointer
- *
- *  returns a Pointer object wrapping the receiver's internal storage (be
- *  very careful, changing the pointer will change the original string's
- *  content!).
- */
-
-static VALUE
-rstr_pointer(VALUE self, SEL sel)
-{
-    return rb_pointer_new("C", RSTR(self)->bytes,
-	    RSTR(self)->length_in_bytes); 
-}
-
-/*
- *  call-seq:
- *     str.force_encoding(encoding)   => str
- *
- *  Changes the encoding to +encoding+ and returns self.
- */
-
-void
-rb_str_force_encoding(VALUE str, rb_encoding_t *enc)
-{
-    assert(IS_RSTR(str));
-    if (enc != RSTR(str)->encoding) {
-	RSTR(str)->encoding = enc;
-	str_reset_flags(RSTR(str));
-    }
-}
-
-static VALUE
-rstr_force_encoding(VALUE self, SEL sel, VALUE encoding)
-{
-    rstr_modify(self);
-    rb_str_force_encoding(self, rb_to_encoding(encoding));
-    return self;
-}
-
-/*
- *  call-seq:
- *     str.valid_encoding?  => true or false
- *  
- *  Returns true for a string which encoded correctly.
- *
- *    "\xc2\xa1".force_encoding("UTF-8").valid_encoding? => true
- *    "\xc2".force_encoding("UTF-8").valid_encoding? => false
- *    "\x80".force_encoding("UTF-8").valid_encoding? => false
- */
-
-static VALUE
-rstr_is_valid_encoding(VALUE self, SEL sel)
-{
-    return str_is_valid_encoding(RSTR(self)) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.ascii_only?  => true or false
- *  
- *  Returns true for a string which has only ASCII characters.
- *
- *    "abc".force_encoding("UTF-8").ascii_only? => true
- *    "abc\u{6666}".force_encoding("UTF-8").ascii_only? => false
- */
-
-static VALUE
-rstr_is_ascii_only(VALUE self, SEL sel)
-{
-    return str_is_ruby_ascii_only(RSTR(self)) ? Qtrue : Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     str[fixnum]                 => new_str or nil
- *     str[fixnum, fixnum]         => new_str or nil
- *     str[range]                  => new_str or nil
- *     str[regexp]                 => new_str or nil
- *     str[regexp, fixnum]         => new_str or nil
- *     str[other_str]              => new_str or nil
- *     str.slice(fixnum)           => new_str or nil
- *     str.slice(fixnum, fixnum)   => new_str or nil
- *     str.slice(range)            => new_str or nil
- *     str.slice(regexp)           => new_str or nil
- *     str.slice(regexp, fixnum)   => new_str or nil
- *     str.slice(other_str)        => new_str or nil
- *  
- *  Element Reference---If passed a single <code>Fixnum</code>, returns a
- *  substring of one character at that position. If passed two <code>Fixnum</code>
- *  objects, returns a substring starting at the offset given by the first, and
- *  a length given by the second. If given a range, a substring containing
- *  characters at offsets given by the range is returned. In all three cases, if
- *  an offset is negative, it is counted from the end of <i>str</i>. Returns
- *  <code>nil</code> if the initial offset falls outside the string, the length
- *  is negative, or the beginning of the range is greater than the end.
- *     
- *  If a <code>Regexp</code> is supplied, the matching portion of <i>str</i> is
- *  returned. If a numeric parameter follows the regular expression, that
- *  component of the <code>MatchData</code> is returned instead. If a
- *  <code>String</code> is given, that string is returned if it occurs in
- *  <i>str</i>. In both cases, <code>nil</code> is returned if there is no
- *  match.
- *     
- *     a = "hello there"
- *     a[1]                   #=> "e"
- *     a[1,3]                 #=> "ell"
- *     a[1..3]                #=> "ell"
- *     a[-3,2]                #=> "er"
- *     a[-4..-2]              #=> "her"
- *     a[12..-1]              #=> nil
- *     a[-2..-4]              #=> ""
- *     a[/[aeiou](.)\1/]      #=> "ell"
- *     a[/[aeiou](.)\1/, 0]   #=> "ell"
- *     a[/[aeiou](.)\1/, 1]   #=> "l"
- *     a[/[aeiou](.)\1/, 2]   #=> nil
- *     a["lo"]                #=> "lo"
- *     a["bye"]               #=> nil
- */
-
-static VALUE
-rb_str_subpat(VALUE str, VALUE re, int nth)
-{
-    if (rb_reg_search(re, str, 0, false) >= 0) {
-	return rb_reg_nth_match(nth, rb_backref_get());
-    }
-    return Qnil;
-}
-
-VALUE
-rstr_aref(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE result = Qnil;
-    bool tainted = OBJ_TAINTED(str);
-
-    if (argc == 2) {
-	if (TYPE(argv[0]) == T_REGEXP) {
-	    result = rb_str_subpat(str, argv[0], NUM2INT(argv[1]));
-	}
-	else {
-	    result = rstr_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
-	}
-	goto bail;
-    }
-
-    if (argc != 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-
-    VALUE indx = argv[0];
-    switch (TYPE(indx)) {
-	case T_FIXNUM:
-	    result = rstr_substr(str, FIX2LONG(indx), 1);
-	    if (NIL_P(result) || rb_str_chars_len(result) == 0) {
-		return Qnil;
-	    }
-	    break;
-
-	case T_REGEXP:
-	    result = rb_str_subpat(str, indx, 0);
-	    break;
-
-	case T_STRING:
-	    {
-		tainted = false;
-		if (IS_RSTR(indx)) {
-		    rb_str_t *searched = RSTR(indx);
-		    if (str_include_string(RSTR(str), searched)) {
-			result = (VALUE)str_dup(searched);
-			goto bail;
-		    }
-		}
-		else {
-		    rb_str_t *searched =
-			str_new_from_cfstring((CFStringRef)indx);
-		    if (str_include_string(RSTR(str), searched)) {
-			// no need to duplicate the string as we just
-			// created it
-			result = (VALUE)searched;
-			goto bail;
-		    }
-		}
-		return Qnil;
-	    }
-
-	default:
-	    {
-		long beg = 0, len = 0;
-		switch (rb_range_beg_len(indx, &beg, &len,
-			    str_length(RSTR(str)), 0)) {
-		    case Qfalse:
-			break;
-		    case Qnil:
-			return Qnil;
-		    default:
-			result = rstr_substr(str, beg, len);
-			goto bail;
-		}
-		result = rstr_substr(str, NUM2LONG(indx), 1);
-		if (NIL_P(result) || rb_str_chars_len(result) == 0) {
-		    return Qnil;
-		}
-		break;
-	    }
-    }
-
-bail:
-    if (!tainted) {
-	for (int i = 0; i < argc; i++) {
-	    if (OBJ_TAINTED(argv[i])) {
-		tainted = true;
-		break;
-	    }
-	}
-    }
-    if (tainted) {
-	OBJ_TAINT(result);
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     str[fixnum] = new_str
- *     str[fixnum, fixnum] = new_str
- *     str[range] = aString
- *     str[regexp] = new_str
- *     str[regexp, fixnum] = new_str
- *     str[other_str] = new_str
- *  
- *  Element Assignment---Replaces some or all of the content of <i>str</i>. The
- *  portion of the string affected is determined using the same criteria as
- *  <code>String#[]</code>. If the replacement string is not the same length as
- *  the text it is replacing, the string will be adjusted accordingly. If the
- *  regular expression or string is used as the index doesn't match a position
- *  in the string, <code>IndexError</code> is raised. If the regular expression
- *  form is used, the optional second <code>Fixnum</code> allows you to specify
- *  which portion of the match to replace (effectively using the
- *  <code>MatchData</code> indexing rules. The forms that take a
- *  <code>Fixnum</code> will raise an <code>IndexError</code> if the value is
- *  out of range; the <code>Range</code> form will raise a
- *  <code>RangeError</code>, and the <code>Regexp</code> and <code>String</code>
- *  forms will silently ignore the assignment.
- */
-
-static void
-rb_str_subpat_set(VALUE str, VALUE re, int nth, VALUE val)
-{
-    if (rb_reg_search(re, str, 0, false) < 0) {
-	rb_raise(rb_eIndexError, "regexp not matched");
-    }
-    VALUE match = rb_backref_get();
-
-    int count = 0;
-    rb_match_result_t *results = rb_reg_match_results(match, &count);
-    assert(count > 0);
-
-    if (nth >= count) {
-out_of_range:
-	rb_raise(rb_eIndexError, "index %d out of regexp", nth);
-    }
-    if (nth < 0) {
-	if (-nth >= count) {
-	    goto out_of_range;
-	}
-	nth += count;
-    }
-
-    const long start = results[nth].beg;
-    if (start == -1) {
-	rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
-    }
-    const long end = results[nth].end;
-    const long len = end - start;
-    rstr_splice(str, start, len, val);
-}
-
-static VALUE
-rstr_aset(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    if (argc == 3) {
-	if (TYPE(argv[0]) == T_REGEXP) {
-	    rb_str_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]);
-	}
-	else {
-	    rstr_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]),
-		    argv[2]);
-	}
-	return argv[2];
-    }
-
-    if (argc != 2) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-
-    VALUE indx = argv[0];
-    VALUE val = argv[1];
-    long pos = 0;
-
-    switch (TYPE(indx)) {
-	case T_FIXNUM:
-	    pos = FIX2LONG(indx);
-num_index:
-	    rstr_splice(str, pos, 1, val);
-	    return val;
-
-	case T_REGEXP:
-	    rb_str_subpat_set(str, indx, 0, val);
-	    return val;
-
-	case T_STRING:
-	    pos = str_index_for_string(RSTR(str), str_need_string(indx),
-		    0, -1, false);
-	    if (pos < 0) {
-		rb_raise(rb_eIndexError, "string not matched");
-	    }
-	    rstr_splice(str, pos, rb_str_chars_len(indx), val);
-	    return val;
-
-	default:
-	    /* check if indx is Range */
-	    {
-		long beg, len;
-		if (rb_range_beg_len(indx, &beg, &len,
-			    str_length(RSTR(str)), 2)) {
-		    rstr_splice(str, beg, len, val);
-		    return val;
-		}
-	    }
-	    pos = NUM2LONG(indx);
-	    goto num_index;
-    }
-}
-
-/*
- *  call-seq:
- *     str.slice!(fixnum)           => fixnum or nil
- *     str.slice!(fixnum, fixnum)   => new_str or nil
- *     str.slice!(range)            => new_str or nil
- *     str.slice!(regexp)           => new_str or nil
- *     str.slice!(other_str)        => new_str or nil
- *
- *  Deletes the specified portion from <i>str</i>, and returns the portion
- *  deleted.
- *
- *     string = "this is a string"
- *     string.slice!(2)        #=> "i"
- *     string.slice!(3..6)     #=> " is "
- *     string.slice!(/s.*t/)   #=> "sa st"
- *     string.slice!("r")      #=> "r"
- *     string                  #=> "thing"
- */
-
-static VALUE
-rstr_slice_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    if (argc < 1 || 2 < argc) {
-        rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-
-    rstr_modify(str);
-
-    int i;
-    VALUE buf[3];
-    for (i=0; i < argc; i++) {
-        buf[i] = argv[i];
-    }
-    buf[i] = rb_str_new(NULL, 0);
-
-    VALUE result = rstr_aref(str, 0, argc, buf);
-    if (!NIL_P(result)) {
-        rstr_aset(str, 0, argc + 1, buf);
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     str.insert(index, other_str)   => str
- *  
- *  Inserts <i>other_str</i> before the character at the given
- *  <i>index</i>, modifying <i>str</i>. Negative indices count from the
- *  end of the string, and insert <em>after</em> the given character.
- *  The intent is insert <i>aString</i> so that it starts at the given
- *  <i>index</i>.
- *     
- *     "abcd".insert(0, 'X')    #=> "Xabcd"
- *     "abcd".insert(3, 'X')    #=> "abcXd"
- *     "abcd".insert(4, 'X')    #=> "abcdX"
- *     "abcd".insert(-3, 'X')   #=> "abXcd"
- *     "abcd".insert(-1, 'X')   #=> "abcdX"
- */
-
-static VALUE
-rstr_insert(VALUE str, SEL sel, VALUE idx, VALUE substr)
-{
-    long pos = NUM2LONG(idx);
-    if (pos == -1) {
-	rstr_append(str, substr);
-    }
-    else {
-	if (pos < 0) {
-	    pos++;
-	}
-	rstr_splice(str, pos, 0, substr);
-    }
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.index(substring [, offset])   => fixnum or nil
- *     str.index(fixnum [, offset])      => fixnum or nil
- *     str.index(regexp [, offset])      => fixnum or nil
- *  
- *  Returns the index of the first occurrence of the given <i>substring</i>,
- *  character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
- *  <code>nil</code> if not found. If the second parameter is present, it
- *  specifies the position in the string to begin the search.
- *     
- *     "hello".index('e')             #=> 1
- *     "hello".index('lo')            #=> 3
- *     "hello".index('a')             #=> nil
- *     "hello".index(?e)              #=> 1
- *     "hello".index(101)             #=> 1
- *     "hello".index(/[aeiou]/, -3)   #=> 4
- */
-
-static VALUE
-rstr_index(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    const long len = str_length(RSTR(self));
-    VALUE sub, initpos;
-    long pos;
-
-    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
-	pos = NUM2LONG(initpos);
-	if (pos < 0) {
-	    pos += len;
-	}
-	if (pos < 0) {
-	    if (TYPE(sub) == T_REGEXP) {
-		rb_backref_set(Qnil);
-	    }
-	    return Qnil;
-	}
-    }
-    else {
-	pos = 0;
-    }
-
-    switch (TYPE(sub)) {
-	case T_REGEXP:
-	    if (pos > len) {
-		return Qnil;
-	    }
-	    pos = rb_reg_search(sub, self, pos, false);
-	    break;
-
-	default: 
-	    StringValue(sub);
-	    // fall through
-	case T_STRING:
-	    if (pos == len && rb_str_chars_len(sub) == 0) {
-		// Do nothing... RubySpec compliance...
-	    }
-	    else {
-		pos = str_index_for_string(RSTR(self), str_need_string(sub),
-			pos, -1, false);
-	    }
-	    break;
-    }
-
-    return pos >= 0 ? LONG2NUM(pos) : Qnil;
-}
-
-/*
- *  call-seq:
- *     str.rindex(substring [, fixnum])   => fixnum or nil
- *     str.rindex(fixnum [, fixnum])   => fixnum or nil
- *     str.rindex(regexp [, fixnum])   => fixnum or nil
- *  
- *  Returns the index of the last occurrence of the given <i>substring</i>,
- *  character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
- *  <code>nil</code> if not found. If the second parameter is present, it
- *  specifies the position in the string to end the search---characters beyond
- *  this point will not be considered.
- *     
- *     "hello".rindex('e')             #=> 1
- *     "hello".rindex('l')             #=> 3
- *     "hello".rindex('a')             #=> nil
- *     "hello".rindex(?e)              #=> 1
- *     "hello".rindex(101)             #=> 1
- *     "hello".rindex(/[aeiou]/, -2)   #=> 1
- */
-
-static VALUE
-rstr_rindex(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    const long len = str_length(RSTR(self));
-    VALUE sub, initpos;
-    long pos;
-
-    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
-	pos = NUM2LONG(initpos);
-	if (pos < 0) {
-	    pos += len;
-	    if (pos < 0) {
-		if (TYPE(sub) == T_REGEXP) {
-		    rb_backref_set(Qnil);
-		}
-		return Qnil;
-	    }
-	}
-	if (pos >= len) {
-	    pos = len;
-	}
-    }
-    else {
-	pos = len;
-    }
-
-    switch (TYPE(sub)) {
-	case T_REGEXP:
-	    pos = rb_reg_search(sub, self, pos, true);
-	    break;
-
-	default: 
-	    StringValue(sub);
-	    // fall through
-	case T_STRING:
-	    if (rb_str_chars_len(sub) > 0) {
-		pos = str_index_for_string(RSTR(self), str_need_string(sub),
-			0, pos, true);
-	    }
-	    break;
-    }
-
-    return pos >= 0 ? LONG2NUM(pos) : Qnil;
-}
-
-/*
- *  call-seq:
- *     str + other_str   => new_str
- *  
- *  Concatenation---Returns a new <code>String</code> containing
- *  <i>other_str</i> concatenated to <i>str</i>.
- *     
- *     "Hello from " + self.to_s   #=> "Hello from main"
- */
-
-static VALUE
-rstr_plus(VALUE self, SEL sel, VALUE other)
-{
-    StringValue(other);
-
-    rb_str_t *newstr = str_dup(RSTR(self));
-    rb_str_t *otherstr = str_need_string(other);
-    str_concat_string(newstr, otherstr);
-    if (OBJ_TAINTED(self) || OBJ_TAINTED(other)) {
-	OBJ_TAINT(newstr);
-    }
-    return (VALUE)newstr;
-}
-
-/*
- *  call-seq:
- *     str * integer   => new_str
- *  
- *  Copy---Returns a new <code>String</code> containing <i>integer</i> copies of
- *  the receiver.
- *     
- *     "Ho! " * 3   #=> "Ho! Ho! Ho! "
- */
-
-static VALUE
-rstr_times(VALUE self, SEL sel, VALUE times)
-{
-    const long n = NUM2LONG(times);
-    if (n < 0) {
-	rb_raise(rb_eArgError, "negative argument");
-    }
-    if (n > 0 && LONG_MAX/n < RSTR(self)->length_in_bytes) {
-	rb_raise(rb_eArgError, "argument too big");
-    }
-
-    VALUE new = str_new_like(self);
-    str_resize_bytes(RSTR(new), n * RSTR(self)->length_in_bytes);
-    for (long i = 0; i < n; ++i) {
-	str_concat_string(RSTR(new), RSTR(self));
-    }
-    OBJ_INFECT(new, self);
-    return new;
-}
-
-/*
- *  call-seq:
- *     str % arg   => new_str
- *  
- *  Format---Uses <i>str</i> as a format specification, and returns the result
- *  of applying it to <i>arg</i>. If the format specification contains more than
- *  one substitution, then <i>arg</i> must be an <code>Array</code> containing
- *  the values to be substituted. See <code>Kernel::sprintf</code> for details
- *  of the format string.
- *     
- *     "%05d" % 123                              #=> "00123"
- *     "%-5s: %08x" % [ "ID", self.object_id ]   #=> "ID   : 200e14d6"
- */
-
-static VALUE
-rstr_format(VALUE str, SEL sel, VALUE arg)
-{
-    VALUE tmp = rb_check_array_type(arg);
-
-    if (!NIL_P(tmp)) {
-	return rb_str_format(RARRAY_LEN(tmp), RARRAY_PTR(tmp), str);
-    }
-    return rb_str_format(1, &arg, str);
-}
-
-/*
- *  call-seq:
- *     str << fixnum        => str
- *     str.concat(fixnum)   => str
- *     str << obj           => str
- *     str.concat(obj)      => str
- *  
- *  Append---Concatenates the given object to <i>str</i>. If the object is a
- *  <code>Fixnum</code>, it is considered as a codepoint, and is converted
- *  to a character before concatenation.
- *     
- *     a = "hello "
- *     a << "world"   #=> "hello world"
- *     a.concat(33)   #=> "hello world!"
- */
-
-VALUE
-rstr_concat(VALUE self, SEL sel, VALUE other)
-{
-    rstr_modify(self);
-
-    long codepoint = 0;
-    switch (TYPE(other)) {
-	case T_FIXNUM:
-	    codepoint = FIX2LONG(other);
-	    break;
-
-	case T_BIGNUM:
-	    codepoint = rb_big2ulong(other);
-	    break;
-	    
-	default:
-	    rstr_append(self, other);
-	    return self;
-    }
-
-    if (IS_UTF8_ENC(RSTR(self)->encoding)) {
-	const int bytelen = U8_LENGTH(codepoint);
-	if (bytelen <= 0) {
-	    goto out_of_range;
-	}
-	uint8_t *buf = (uint8_t *)malloc(bytelen);
-	int offset = 0;
-	UBool error = false;
-	U8_APPEND(buf, offset, bytelen, codepoint, error);
-	if (error) {
-	    free(buf);
-	    goto out_of_range;
-	}
-	str_concat_bytes(RSTR(self), (const char *)buf, bytelen);
-	free(buf);
-    }
-    else {
-	rb_raise(rb_eArgError,
-		"receiver encoding `%s' not supported for codepoint insertion",
-		RSTRING_PTR(rb_inspect((VALUE)RSTR(self)->encoding)));
-    }
-
-    return self;
-
-out_of_range:
-    rb_raise(rb_eArgError, "codepoint %ld out of range", codepoint);
-}
-
-/*
- *  call-seq:
- *     str == obj   => true or false
- *  
- *  Equality---If <i>obj</i> is not a <code>String</code>, returns
- *  <code>false</code>. Otherwise, returns <code>true</code> if <i>str</i>
- *  <code><=></code> <i>obj</i> returns zero.
- */
-
-static VALUE
-rstr_equal(VALUE self, SEL sel, VALUE other)
-{
-    if (self == other) {
-	return Qtrue;
-    }
-    if (TYPE(other) != T_STRING) {
-	if (!rb_respond_to(other, rb_intern("to_str"))) {
-	    return Qfalse;
-	}
-	return rb_equal(other, self);
-    }
-    return str_compare(RSTR(self), str_need_string(other)) == 0
-	? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     str <=> other_str   => -1, 0, +1
- *  
- *  Comparison---Returns -1 if <i>other_str</i> is less than, 0 if
- *  <i>other_str</i> is equal to, and +1 if <i>other_str</i> is greater than
- *  <i>str</i>. If the strings are of different lengths, and the strings are
- *  equal when compared up to the shortest length, then the longer string is
- *  considered greater than the shorter one. In older versions of Ruby, setting
- *  <code>$=</code> allowed case-insensitive comparisons; this is now deprecated
- *  in favor of using <code>String#casecmp</code>.
- *
- *  <code><=></code> is the basis for the methods <code><</code>,
- *  <code><=</code>, <code>></code>, <code>>=</code>, and <code>between?</code>,
- *  included from module <code>Comparable</code>.  The method
- *  <code>String#==</code> does not use <code>Comparable#==</code>.
- *     
- *     "abcdef" <=> "abcde"     #=> 1
- *     "abcdef" <=> "abcdef"    #=> 0
- *     "abcdef" <=> "abcdefg"   #=> -1
- *     "abcdef" <=> "ABCDEF"    #=> 1
- */
-
-static VALUE
-rstr_cmp(VALUE self, SEL sel, VALUE other)
-{
-    long result;
-
-    if (TYPE(other) != T_STRING) {
-	if (!rb_respond_to(other, rb_intern("to_str"))) {
-	    return Qnil;
-	}
-	else if (!rb_vm_respond_to(other, selCmp, false)) {
-	    return Qnil;
-	}
-	else {
-	    VALUE tmp = rb_vm_call(other, selCmp, 1, &self);
-	    if (NIL_P(tmp)) {
-		return Qnil;
-	    }
-	    if (!FIXNUM_P(tmp)) {
-		return rb_vm_call(LONG2FIX(0), selMINUS, 1, &tmp);
-	    }
-	    result = -FIX2LONG(tmp);
-	}
-    }
-    else {
-	result = str_compare(RSTR(self), str_need_string(other));
-    }
-    return LONG2NUM(result);
-}
-
-/*
- *  call-seq:
- *     str.casecmp(other_str)   => -1, 0, +1 or nil
- *
- *  Case-insensitive version of <code>String#<=></code>.
- *
- *     "abcdef".casecmp("abcde")     #=> 1
- *     "aBcDeF".casecmp("abcdef")    #=> 0
- *     "abcdef".casecmp("abcdefg")   #=> -1
- *     "abcdef".casecmp("ABCDEF")    #=> 0
- */
-
-static VALUE
-rstr_casecmp(VALUE str, SEL sel, VALUE other)
-{
-    return INT2FIX(str_case_compare(RSTR(str), str_need_string(other)));
-}
-
-/*
- * call-seq:
- *   str.eql?(other)   => true or false
- *
- * Two strings are equal if they have the same length and content.
- */
-
-static VALUE
-rstr_eql(VALUE self, SEL sel, VALUE other)
-{
-    if (self == other) {
-	return Qtrue;
-    }
-    if (TYPE(other) != T_STRING) {
-	return Qfalse;
-    }
-    return str_compare(RSTR(self), str_need_string(other)) == 0
-	? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.include? other_str   => true or false
- *     str.include? fixnum      => true or false
- *  
- *  Returns <code>true</code> if <i>str</i> contains the given string or
- *  character.
- *     
- *     "hello".include? "lo"   #=> true
- *     "hello".include? "ol"   #=> false
- *     "hello".include? ?h     #=> true
- */
-
-static VALUE
-rstr_includes(VALUE self, SEL sel, VALUE searched)
-{
-    return str_include_string(RSTR(self), str_need_string(searched))
-	? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.start_with?([prefix]+)   => true or false
- *  
- *  Returns true if <i>str</i> starts with the prefix given.
- */
-
-static VALUE
-rstr_start_with(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	VALUE tmp = rb_check_string_type(argv[i]);
-	if (NIL_P(tmp)) {
-	    continue;
-	}
-	const long pos = str_index_for_string(RSTR(str), str_need_string(tmp),
-		0, rb_str_chars_len(tmp), false);
-	if (pos == 0) {
-	    return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.end_with?([suffix]+)   => true or false
- *  
- *  Returns true if <i>str</i> ends with the suffix given.
- */
-
-static VALUE
-rstr_end_with(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    const long len = rb_str_chars_len(str);
-    for (int i = 0; i < argc; i++) {
-	VALUE tmp = rb_check_string_type(argv[i]);
-	if (NIL_P(tmp)) {
-	    continue;
-	}
-	const long sublen = rb_str_chars_len(tmp);
-	if (sublen > len) {
-	    continue;
-	}
-	const long pos = str_index_for_string(RSTR(str), str_need_string(tmp),
-		len - sublen, len, false);
-	if (pos == len - sublen) {
-	    return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     str.to_s     => str
- *     str.to_str   => str
- *  
- *  Returns the receiver.
- */
-
-static VALUE
-rstr_to_s(VALUE self, SEL sel)
-{
-    if (CLASS_OF(self) != rb_cRubyString) {
-	VALUE dup = (VALUE)str_dup(RSTR(self));
-	if (OBJ_TAINTED(self)) {
-	    OBJ_TAINT(dup);
-	}
-	return dup;
-    }
-    return self;
-}
-
-/*
- *  call-seq:
- *     str.intern   => symbol
- *     str.to_sym   => symbol
- *  
- *  Returns the <code>Symbol</code> corresponding to <i>str</i>, creating the
- *  symbol if it did not previously exist. See <code>Symbol#id2name</code>.
- *     
- *     "Koala".intern         #=> :Koala
- *     s = 'cat'.to_sym       #=> :cat
- *     s == :cat              #=> true
- *     s = '@cat'.to_sym      #=> :@cat
- *     s == :@cat             #=> true
- *
- *  This can also be used to create symbols that cannot be represented using the
- *  <code>:xxx</code> notation.
- *     
- *     'cat and dog'.to_sym   #=> :"cat and dog"
- */
-
-static VALUE
-rstr_intern(VALUE self, SEL sel)
-{
-    if (OBJ_TAINTED(self) && rb_safe_level() >= 1) {
-	rb_raise(rb_eSecurityError, "Insecure: can't intern tainted string");
-    }
-    return rb_str_intern_fast(self);
-}
-
-/*
- * call-seq:
- *   str.inspect   => string
- *
- * Returns a printable version of _str_, surrounded by quote marks,
- * with special characters escaped.
- *
- *    str = "hello"
- *    str[3] = "\b"
- *    str.inspect       #=> "\"hel\\bo\""
- */
-
-static void
-inspect_append(VALUE result, UChar32 c, bool escape)
-{
-    if (escape) {
-	str_append_uchar32(RSTR(result), '\\');
-    }
-    str_append_uchar32(RSTR(result), c);
-}
-
-static VALUE
-str_inspect(rb_str_t *str, bool dump)
-{
-    VALUE result;
-    if (str->length_in_bytes == 0) {
-	result = rb_str_new2("\"\"");
-	OBJ_INFECT(result, str);
-	return result;
-    }
-
-    const long result_init_len = str->length_in_bytes * 3 / 2;
-    result = rb_unicode_str_new(NULL, result_init_len);
-
-    inspect_append(result, '"', false);
-    __block UChar32 prev = 0;
-    str_each_uchar32(str, ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	bool print = iswprint(c);
-	if (IS_BINARY_ENC(str->encoding) && c > 127) {
-	    print = false;
-	}
-	if (dump && prev == '#') {
-	    inspect_append(result, prev, (c == '$' || c == '@' || c == '{'));
-	}
-	if (print) {
-	    if (c == '"' || c == '\\') {
-		inspect_append(result, c, true);
-	    }
-	    else if (c != '#' || !dump) {
-		inspect_append(result, c, false);
-	    }
-	}
-	else if (c == '\n') {
-	    inspect_append(result, 'n', true);
-	} 
-	else if (c == '\r') {
-	    inspect_append(result, 'r', true);
-	} 
-	else if (c == '\t') {
-	    inspect_append(result, 't', true);
-	} 
-	else if (c == '\f') {
-	    inspect_append(result, 'f', true);
-	}
-	else if (c == '\013') {
-	    inspect_append(result, 'v', true);
-	}
-	else if (c == '\010') {
-	    inspect_append(result, 'b', true);
-	}
-	else if (c == '\007') {
-	    inspect_append(result, 'a', true);
-	}
-	else if (c == 033) {
-	    inspect_append(result, 'e', true);
-	}
-	else {
-	    char buf[10];
-	    for (long i = 0; i < char_len; ++i) {
-		uint8_t byte = (uint8_t)str->bytes[start_index+i];
-		snprintf(buf, sizeof buf, "\\x%02X", byte);
-		char *p = buf;
-		while (*p != '\0') {
-		    inspect_append(result, *p, false);
-		    p++;
-		}
-	    }
-	}
-	prev = c;
-    });
-    if (dump && prev == '#') {
-	inspect_append(result, prev, false);
-    }
-    inspect_append(result, '"', false);
-   
-    OBJ_INFECT(result, str);
-    return result; 
-}
-
-static VALUE
-rstr_inspect(VALUE self, SEL sel)
-{
-    return str_inspect(RSTR(self), false);
-}
-
-/*
- *  call-seq:
- *     str.dump   => new_str
- *  
- *  Produces a version of <i>str</i> with all nonprinting characters replaced by
- *  <code>\nnn</code> notation and all special characters escaped.
- */
-
-static VALUE
-rstr_dump(VALUE self, SEL sel)
-{
-    VALUE res = str_inspect(RSTR(self), true);
-    *(VALUE *)res = *(VALUE *)self;
-    return res;
-}
-
-/*
- *  call-seq:
- *     str.match(pattern)   => matchdata or nil
- *  
- *  Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
- *  then invokes its <code>match</code> method on <i>str</i>.  If the second
- *  parameter is present, it specifies the position in the string to begin the
- *  search.
- *     
- *     'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
- *     'hello'.match('(.)\1')[0]   #=> "ll"
- *     'hello'.match(/(.)\1/)[0]   #=> "ll"
- *     'hello'.match('xx')         #=> nil
- *     
- *  If a block is given, invoke the block with MatchData if match succeed, so
- *  that you can write
- *     
- *     str.match(pat) {|m| ...}
- *     
- *  instead of
- *      
- *     if m = str.match(pat)
- *       ...
- *     end
- *      
- *  The return value is a value from block execution in this case.
- */
-
-static VALUE
-get_pat(VALUE pat, bool quote)
-{
-    switch (TYPE(pat)) {
-	case T_REGEXP:
-	    return pat;
-
-	case T_STRING:
-	    break;
-
-	default:
-	    {
-		VALUE val = rb_check_string_type(pat);
-		if (NIL_P(val)) {
-		    Check_Type(pat, T_REGEXP);
-		}
-		pat = val;
-	    }
-    }
-
-    if (quote) {
-	pat = rb_reg_quote(pat);
-    }
-    return rb_reg_regcomp(pat);
-}
-
-static VALUE
-rstr_match2(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-    }
-    VALUE re = get_pat(argv[0], false);
-    argv[0] = self;
-    return regexp_match2(re, 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     str =~ obj   => fixnum or nil
- *  
- *  Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
- *  against <i>str</i>,and returns the position the match starts, or 
- *  <code>nil</code> if there is no match. Otherwise, invokes
- *  <i>obj.=~</i>, passing <i>str</i> as an argument. The default
- *  <code>=~</code> in <code>Object</code> returns <code>false</code>.
- *     
- *     "cat o' 9 tails" =~ /\d/   #=> 7
- *     "cat o' 9 tails" =~ 9      #=> nil
- */
-
-static VALUE
-rstr_match(VALUE self, SEL sel, VALUE other)
-{
-    switch (TYPE(other)) {
-	case T_STRING:
-	    rb_raise(rb_eTypeError, "type mismatch: String given");
-
-	case T_REGEXP:
-	    return regexp_match(other, 0, self);
-
-	default:
-	    return rb_vm_call(other, selEqTilde, 1, &self);
-    }
-}
-
-/*
- *  call-seq:
- *     str.scan(pattern)                         => array
- *     str.scan(pattern) {|match, ...| block }   => str
- *  
- *  Both forms iterate through <i>str</i>, matching the pattern (which may be a
- *  <code>Regexp</code> or a <code>String</code>). For each match, a result is
- *  generated and either added to the result array or passed to the block. If
- *  the pattern contains no groups, each individual result consists of the
- *  matched string, <code>$&</code>.  If the pattern contains groups, each
- *  individual result is itself an array containing one entry per group.
- *     
- *     a = "cruel world"
- *     a.scan(/\w+/)        #=> ["cruel", "world"]
- *     a.scan(/.../)        #=> ["cru", "el ", "wor"]
- *     a.scan(/(...)/)      #=> [["cru"], ["el "], ["wor"]]
- *     a.scan(/(..)(..)/)   #=> [["cr", "ue"], ["l ", "wo"]]
- *     
- *  And the block form:
- *     
- *     a.scan(/\w+/) {|w| print "<<#{w}>> " }
- *     print "\n"
- *     a.scan(/(.)(.)/) {|x,y| print y, x }
- *     print "\n"
- *     
- *  <em>produces:</em>
- *     
- *     <<cruel>> <<world>>
- *     rceu lowlr
- */
-
-static VALUE
-rstr_scan(VALUE self, SEL sel, VALUE pat)
-{
-    const bool block_given = rb_block_given_p();
-
-    const bool untrusted = OBJ_UNTRUSTED(self) || OBJ_UNTRUSTED(pat);
-    pat = get_pat(pat, true);
-    const bool tainted = OBJ_TAINTED(self) || OBJ_TAINTED(pat);
-
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-
-    VALUE ary = 0;
-    if (!block_given) {
-	ary = rb_ary_new();
-    }
-
-    VALUE matcher = rb_reg_matcher_new(pat, self);
-
-    VALUE match = Qnil;
-    long start = 0;
-    while (rb_reg_matcher_search(pat, matcher, start, false) >= 0) {
-	match = rb_backref_get();
-
-	int count = 0;
-	rb_match_result_t *results = rb_reg_match_results(match, &count);
-	assert(count > 0);
-
-	if (results[0].beg == results[0].end) {
-	    start = results[0].end + 1;
-	}
-	else {
-	    start = results[0].end;
-	}
-
-	VALUE scan_result;
-	if (count == 1) {
-	    scan_result = rb_reg_nth_match_with_cache(0, match, &local_cache);
-	    if (tainted) {
-		OBJ_TAINT(scan_result);
-	    }
-	    if (untrusted) {
-		OBJ_UNTRUST(scan_result);
-	    }
-	}
-	else {
-	    scan_result = rb_ary_new2(count);
-	    for (int i = 1; i < count; i++) {
-		VALUE substr = rb_reg_nth_match_with_cache(i, match,
-			&local_cache);
-		if (tainted) {
-		    OBJ_TAINT(substr);
-		}
-		if (untrusted) {
-		    OBJ_UNTRUST(substr);
-		}
-		rb_ary_push(scan_result, substr);
-	    }
-	}
-
-	if (block_given) {
-	    rb_match_busy(match);
-	    rb_yield(scan_result);
-	    rb_backref_set(match);
-	    RETURN_IF_BROKEN();
-	}
-	else {
-	    rb_ary_push(ary, scan_result);
-	}
-    }
-
-    rb_backref_set(match);
-
-    rb_reg_matcher_destroy(matcher);
-
-    return block_given ? self : ary;
-}
-
-/*
- *  call-seq:
- *     str.split(pattern=$;, [limit])   => anArray
- *  
- *  Divides <i>str</i> into substrings based on a delimiter, returning an array
- *  of these substrings.
- *     
- *  If <i>pattern</i> is a <code>String</code>, then its contents are used as
- *  the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
- *  space, <i>str</i> is split on whitespace, with leading whitespace and runs
- *  of contiguous whitespace characters ignored.
- *     
- *  If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the
- *  pattern matches. Whenever the pattern matches a zero-length string,
- *  <i>str</i> is split into individual characters. If <i>pattern</i> contains
- *  groups, the respective matches will be returned in the array as well.
- *     
- *  If <i>pattern</i> is omitted, the value of <code>$;</code> is used.  If
- *  <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
- *  split on whitespace as if ` ' were specified.
- *     
- *  If the <i>limit</i> parameter is omitted, trailing null fields are
- *  suppressed. If <i>limit</i> is a positive number, at most that number of
- *  fields will be returned (if <i>limit</i> is <code>1</code>, the entire
- *  string is returned as the only entry in an array). If negative, there is no
- *  limit to the number of fields returned, and trailing null fields are not
- *  suppressed.
- *     
- *     " now's  the time".split        #=> ["now's", "the", "time"]
- *     " now's  the time".split(' ')   #=> ["now's", "the", "time"]
- *     " now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
- *     "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
- *     "hello".split(//)               #=> ["h", "e", "l", "l", "o"]
- *     "hello".split(//, 3)            #=> ["h", "e", "llo"]
- *     "hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]
- *     
- *     "mellow yellow".split("ello")   #=> ["m", "w y", "w"]
- *     "1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]
- *     "1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
- *     "1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]
- */
-
-static VALUE str_strip(VALUE str, int direction);
-
-static VALUE
-rstr_split(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-    const long len = str_length_with_cache(RSTR(str), &local_cache);
-    int lim = 0;
-
-    VALUE spat, limit;
-    if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
-	lim = NUM2INT(limit);
-	if (lim <= 0) {
-	    limit = Qnil;
-	}
-	else if (lim == 1) {
-	    if (len == 0) {
-		return rb_ary_new2(0);
-	    }
-	    return rb_ary_new4(1, &str);
-	}
-    }
-
-    VALUE result = rb_ary_new();
-    if (len == 0) {
-	return result;
-    }
-
-    bool awk_split = false, spat_string = false;
-    long spat_len = 0;
-    if (NIL_P(spat)) {
-	if (!NIL_P(rb_fs)) {
-	    spat = rb_fs;
-	    goto fs_set;
-	}
-	awk_split = true;
-    }
-    else {
-fs_set:
-	if (TYPE(spat) == T_STRING) {
-	    spat_string = true;
-	    spat_len = rb_str_chars_len(spat);
-	    if (spat_len == 1 && rb_str_get_uchar(spat, 0) == ' ') {
-		awk_split = true;
-	    }
-	}
-	else {
-	    spat = get_pat(spat, true);
-	}
-    }
-
-    const int lim_orig = lim;
-    long beg = 0;
-    if (awk_split) {
-	RB_STR_GET_UCHARS(str, chars, chars_len);
-
-	for (long i = 0; i < chars_len; i++) {
-	    UChar c = chars[i];
-	    if (c == ' ' || c == '\t' || c == '\n' || c == '\v') {
-		VALUE substr = rstr_substr_with_cache(str, beg, i - beg,
-			&local_cache);
-		str_strip(substr, 0);
-		if (rb_str_chars_len(substr) > 0) {
-		    rb_ary_push(result, substr); 
-		}
-		beg = i + 1;
-
-		if (limit != Qnil && --lim <= 1) {
-		    break;
-		}
-	    }
-	}
-    }
-    else if (spat_string) {
-	if (spat_len == 0) {
-	    do {
-		VALUE substr = rstr_substr_with_cache(str, beg, 1, &local_cache);
-		rb_ary_push(result, substr);
-		beg++;
-		if (beg >= len) {
-		    break;
-		}
-	    }
-	    while (limit == Qnil || --lim > 1);
-	}
-	else {
-	    rb_str_t *spat_str = str_need_string(spat);
-	    const long spat_len = str_length(spat_str);
-	    do {
-		const long pos = str_index_for_string_with_cache(RSTR(str),
-			spat_str, beg, -1, false, &local_cache);
-		if (pos == -1) {
-		    break;
-		}
-		rb_ary_push(result, rstr_substr_with_cache(str, beg, pos - beg,
-			    &local_cache));
-		beg = pos + spat_len;
-	    }
-	    while (limit == Qnil || --lim > 1);
-	}
-    }
-    else {
-	long start = beg;
-	bool last_null = false;
-	VALUE matcher = rb_reg_matcher_new(spat, str);
-again:
-	do {
-	    const long pos = rb_reg_matcher_search(spat, matcher, start, false);
-	    if (pos < 0) {
-		break;
-	    }
-	    VALUE match = rb_backref_get();
-
-	    int count = 0;
-	    rb_match_result_t *results = rb_reg_match_results(match, &count);
-	    assert(count > 0);
-
-	    if (start == pos && results[0].beg == results[0].end) {
-		if (last_null) {
-		    VALUE substr;
-		    if (beg + 1 <= len) {
-			substr = rstr_substr_with_cache(str, beg, 1,
-				&local_cache);
-		    }
-		    else {
-			substr = rb_str_new(NULL, 0);
-		    }
-		    rb_ary_push(result, substr);
-		    beg = start;
-		}
-		else {
-		    start++;
-		    last_null = true;
-		    goto again;
-		}
-	    }
-	    else {
-		VALUE substr = rstr_substr_with_cache(str, beg, pos - beg,
-			&local_cache);
-		rb_ary_push(result, substr);
-		beg = start = results[0].end;
-	    }
-	    last_null = false;
-
-	    for (int i = 1; i < count; i++) {
-		if (results[i].beg == -1 || results[i].end == -1) {
-		    continue;
-		}
-		VALUE substr;
-		if (results[i].beg == results[i].end) {
-		    substr = rb_str_new(NULL, 0);
-		}
-		else {
-		    substr = rstr_substr_with_cache(str, results[i].beg,
-			    results[i].end - results[i].beg, &local_cache);
-		}
-		rb_ary_push(result, substr);
-	    }
-	}
-	while (limit == Qnil || --lim > 1);
-
-	rb_reg_matcher_destroy(matcher);
-    }
-
-    if (len > 0 && (!NIL_P(limit) || len > beg || lim_orig < 0)) {
-	VALUE tmp;
-	if (beg >= len) {
-	    tmp = rb_str_new(NULL, 0);
-	}
-	else {
-	    tmp = rb_str_substr(str, beg, len - beg);
-	}
-	rb_ary_push(result, tmp);
-    }
-
-    if (NIL_P(limit) && lim_orig == 0) {
-	while (true) {
-	    const long n = RARRAY_LEN(result);
-	    if (n > 0 && rb_str_chars_len(RARRAY_AT(result, n - 1)) == 0) {
-		rb_ary_pop(result);
-	    }
-	    else {
-		break;
-	    }
-	}
-    }
-
-    if (OBJ_TAINTED(str)) {
-	for (int i = 0, count = RARRAY_LEN(result); i < count; i++) {
-	    OBJ_TAINT(RARRAY_AT(result, i));
-	}
-    }
-
-    return result;
-}
-
-/*
- *  call-seq:
- *     str.to_i(base=10)   => integer
- *  
- *  Returns the result of interpreting leading characters in <i>str</i> as an
- *  integer base <i>base</i> (between 2 and 36). Extraneous characters past the
- *  end of a valid number are ignored. If there is not a valid number at the
- *  start of <i>str</i>, <code>0</code> is returned. This method never raises an
- *  exception.
- *     
- *     "12345".to_i             #=> 12345
- *     "99 red balloons".to_i   #=> 99
- *     "0a".to_i                #=> 0
- *     "0a".to_i(16)            #=> 10
- *     "hello".to_i             #=> 0
- *     "1100101".to_i(2)        #=> 101
- *     "1100101".to_i(8)        #=> 294977
- *     "1100101".to_i(10)       #=> 1100101
- *     "1100101".to_i(16)       #=> 17826049
- */
-
-static VALUE
-rstr_to_i(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    int base = 10;
-
-    if (argc > 0) {
-	VALUE b;
-	rb_scan_args(argc, argv, "01", &b);
-
-	base = NUM2INT(b);
-	if (base < 0) {
-	    rb_raise(rb_eArgError, "invalid radix %d", base);
-	}
-    }
-
-    return rb_str_to_inum(str, base, Qfalse);
-}
-
-/*
- *  call-seq:
- *     str.hex   => integer
- *  
- *  Treats leading characters from <i>str</i> as a string of hexadecimal digits
- *  (with an optional sign and an optional <code>0x</code>) and returns the
- *  corresponding number. Zero is returned on error.
- *     
- *     "0x0a".hex     #=> 10
- *     "-1234".hex    #=> -4660
- *     "0".hex        #=> 0
- *     "wombat".hex   #=> 0
- */
-
-static VALUE
-rstr_hex(VALUE str, SEL sel)
-{
-    return rb_str_to_inum(str, 16, Qfalse);
-}
-
-/*
- *  call-seq:
- *     str.oct   => integer
- *  
- *  Treats leading characters of <i>str</i> as a string of octal digits (with an
- *  optional sign) and returns the corresponding number.  Returns 0 if the
- *  conversion fails.
- *     
- *     "123".oct       #=> 83
- *     "-377".oct      #=> -255
- *     "bad".oct       #=> 0
- *     "0377bad".oct   #=> 255
- */
-
-static VALUE
-rstr_oct(VALUE str, SEL sel)
-{
-    return rb_str_to_inum(str, -8, Qfalse);
-}
-
-/*
- *  call-seq:
- *     str.ord   => integer
- *  
- *  Return the <code>Integer</code> ordinal of a one-character string.
- *     
- *     "a".ord         #=> 97
- */
-
-static VALUE
-rstr_ord(VALUE str, SEL sel)
-{
-    if (RSTR(str)->length_in_bytes == 0) {
-	rb_raise(rb_eArgError, "empty string");
-    }
-    UChar c = rb_str_get_uchar(str, 0);
-    if (c == (UChar)U_SENTINEL) {
-	str_invalid_byte_sequence(RSTR(str));
-    }
-    return INT2NUM(c);
-}
-
-/*
- *  call-seq:
- *     string.chr    ->  string
- *
- *  Returns a one-character string at the beginning of the string.
- *
- *     a = "abcde"
- *     a.chr    #=> "a"
- */
-
-static VALUE
-rstr_chr(VALUE str, SEL sel)
-{
-    return rstr_substr(str, 0, 1);
-}
-
-/*
- *  call-seq:
- *     str.to_f   => float
- *  
- *  Returns the result of interpreting leading characters in <i>str</i> as a
- *  floating point number. Extraneous characters past the end of a valid number
- *  are ignored. If there is not a valid number at the start of <i>str</i>,
- *  <code>0.0</code> is returned. This method never raises an exception.
- *     
- *     "123.45e1".to_f        #=> 1234.5
- *     "45.67 degrees".to_f   #=> 45.67
- *     "thx1138".to_f         #=> 0.0
- */
-
-static VALUE
-rstr_to_f(VALUE str, SEL sel)
-{
-    return DOUBLE2NUM(rb_str_to_dbl(str, 0));
-}
-
-/*
- *  call-seq:
- *     str.chomp!(separator=$/)   => str or nil
- *  
- *  Modifies <i>str</i> in place as described for <code>String#chomp</code>,
- *  returning <i>str</i>, or <code>nil</code> if no modifications were made.
- */
-
-static VALUE
-rstr_chomp_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rs;
-    if (rb_scan_args(argc, argv, "01", &rs) == 0) {
-	rs = rb_rs;
-    }
-    rstr_modify(str);
-    if (rs == Qnil) {
-	return Qnil;
-    }
-    StringValue(rs);
-
-    const long len = rb_str_chars_len(str);
-    if (len == 0) {
-	return Qnil;
-    }
-
-    const long rslen = rb_str_chars_len(rs);
-    long to_del = 0;
-
-    if (rs == rb_default_rs
-	|| (rslen == 1 && rb_str_get_uchar(rs, 0) == '\n')) {
-	// Remove trailing carriage return.
-	UChar c = str_get_uchar(RSTR(str), len - 1);
-	if (c == '\n') {
-	    to_del++;
-	    c = len > 1 ? str_get_uchar(RSTR(str), len - 2) : 0;
-	}
-	if (c == '\r' && (rslen > 0 || to_del != 0)) {
-	    to_del++;
-	}
-    }
-    else if (rslen == 0) {
-	// Remove all trailing carriage returns.
-	for (int i = len - 1; i >= 0; i--) {
-	    UChar c = str_get_uchar(RSTR(str), i);
-	    if (c != '\n') {
-		break;
-	    }
-	    to_del++;
-	    if (i > 0 && str_get_uchar(RSTR(str), i - 1) == '\r') {
-		to_del++;
-		i--;
-	    }
-	}
-    }
-    else if (rslen <= len) {
-	// Remove trailing substring.
-	if (str_index_for_string(RSTR(str), str_need_string(rs),
-		    len - rslen, -1, false) >= 0) {
-	    to_del += rslen;
-	}
-    }
-
-    if (to_del == 0) {
-	return Qnil;
-    }
-    str_delete(RSTR(str), len - to_del, to_del);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.chomp(separator=$/)   => new_str
- *  
- *  Returns a new <code>String</code> with the given record separator removed
- *  from the end of <i>str</i> (if present). If <code>$/</code> has not been
- *  changed from the default Ruby record separator, then <code>chomp</code> also
- *  removes carriage return characters (that is it will remove <code>\n</code>,
- *  <code>\r</code>, and <code>\r\n</code>).
- *     
- *     "hello".chomp            #=> "hello"
- *     "hello\n".chomp          #=> "hello"
- *     "hello\r\n".chomp        #=> "hello"
- *     "hello\n\r".chomp        #=> "hello\n"
- *     "hello\r".chomp          #=> "hello"
- *     "hello \n there".chomp   #=> "hello \n there"
- *     "hello".chomp("llo")     #=> "he"
- */
-
-static VALUE
-rstr_chomp(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    str = rb_str_new3(str);
-    rstr_chomp_bang(str, 0, argc, argv);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.chop!   => str or nil
- *  
- *  Processes <i>str</i> as for <code>String#chop</code>, returning <i>str</i>,
- *  or <code>nil</code> if <i>str</i> is the empty string.  See also
- *  <code>String#chomp!</code>.
- */
-
-static VALUE
-rstr_chop_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    const long len = str_length(RSTR(str));
-    if (len == 0) {
-	return Qnil;
-    }
-
-    long to_del = 1;
-    if (len >= 2) {
-	// if the string ends with \r\n we have to remove both \r and \n
-	// if the string ends with a character not in the BMP,
-	// we have to remove the whole character
-	UChar last_char = rb_str_get_uchar(str, len - 1);
-	if ((last_char == '\n') || U16_IS_TRAIL(last_char)) {
-	    UChar before_last = rb_str_get_uchar(str, len - 2);
-	    if (((before_last == '\r') && (last_char == '\n'))
-		    || (U16_IS_LEAD(before_last) && U16_IS_TRAIL(last_char))) {
-		to_del++;
-	    }
-	}
-    }
-
-    str_delete(RSTR(str), len - to_del, to_del);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.chop   => new_str
- *  
- *  Returns a new <code>String</code> with the last character removed.  If the
- *  string ends with <code>\r\n</code>, both characters are removed. Applying
- *  <code>chop</code> to an empty string returns an empty
- *  string. <code>String#chomp</code> is often a safer alternative, as it leaves
- *  the string unchanged if it doesn't end in a record separator.
- *     
- *     "string\r\n".chop   #=> "string"
- *     "string\n\r".chop   #=> "string\n"
- *     "string\n".chop     #=> "string"
- *     "string".chop       #=> "strin"
- *     "x".chop.chop       #=> ""
- */
-
-static VALUE
-rstr_chop(VALUE str, SEL sel)
-{
-    str = rb_str_new3(str);
-    rstr_chop_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.sub!(pattern, replacement)          => str or nil
- *     str.sub!(pattern) {|match| block }      => str or nil
- *  
- *  Performs the substitutions of <code>String#sub</code> in place,
- *  returning <i>str</i>, or <code>nil</code> if no substitutions were
- *  performed.
- */
-
-static VALUE
-rb_reg_regsub(VALUE str, VALUE src, VALUE regexp, rb_match_result_t *results,
-	int results_count, character_boundaries_cache_t *cache_for_src)
-{
-    VALUE val = 0;
-
-    RB_STR_GET_UCHARS(str, str_chars, str_chars_len);
-
-    long pos = 0;
-
-    // if we already have a cache, we will make a local copy just before
-    // using it to be sure not to have to start from scratch later
-    // (as for instance with "\\2\\1" would make us do)
-    character_boundaries_cache_t local_cache_for_src;
-    reset_character_boundaries_cache(&local_cache_for_src);
-
-    for (long i = 0; i < str_chars_len; i++) {
-	UChar c = str_chars[i];
-	if (c != '\\') {
-	    continue;
-	}
-	if (i + 1 == str_chars_len) {
-	    break;
-	}
-
-	if (val == 0) {
-	    val = rb_unicode_str_new(NULL, 0);
-	}
-	str_concat_uchars(RSTR(val), &str_chars[pos], i - pos);
-
-	i++;
-	pos = i + 1;
-
-	int no = -1;
-	c = str_chars[i];
-	switch (c) {
-	    case '1': case '2': case '3':
-	    case '4': case '5': case '6':
-	    case '7': case '8': case '9':
-		no = c - '0';
-		break;
-
-	    case '0':
-	    case '&':
-		no = 0;
-		break;
-
-	    case '`':
-		if (cache_for_src != NULL) {
-		    local_cache_for_src = *cache_for_src;
-		}
-		str_concat_string_part(RSTR(val), RSTR(src),
-			0, results[0].beg, cache_for_src);
-		break;
-
-	    case '\'':
-		{
-		    long src_chars_len;
-		    if (cache_for_src == NULL) {
-			src_chars_len = str_length_with_cache(RSTR(src),
-				&local_cache_for_src);
-		    }
-		    else {
-			src_chars_len = str_length_with_cache(RSTR(src),
-				cache_for_src);
-			local_cache_for_src = *cache_for_src;
-		    }
-		    str_concat_string_part(RSTR(val), RSTR(src),
-			    results[0].end, src_chars_len - results[0].end,
-			    cache_for_src);
-		}
-		break;
-
-	    case '+':
-		no = results_count - 1;
-		while (results[no].beg == -1 && no > 0) {
-		    no--;
-		}
-		if (no == 0) {
-		    no = -1;
-		}
-		break;
-
-	    default:
-		str_append_uchar32(RSTR(val), '\\');
-		// fall through
-	    case '\\':
-		str_append_uchar32(RSTR(val), c);
-		break;
-	}
-
-	if (no >= 0) {
-	    if (no >= results_count) {
-		continue;
-	    }
-	    if (results[no].beg == -1) {
-		continue;
-	    }
-	    if (cache_for_src != NULL) {
-		local_cache_for_src = *cache_for_src;
-	    }
-	    str_concat_string_part(RSTR(val), RSTR(src),
-		    results[no].beg, results[no].end - results[no].beg,
-		    cache_for_src);
-	}
-    }
-
-    if (val != 0 && pos < str_chars_len) {
-	str_concat_uchars(RSTR(val), &str_chars[pos], str_chars_len - pos);
-    }
-
-    if (val == 0) {
-	return str;
-    }
-    else {
-	return val;
-    }
-}
-
-static VALUE
-rstr_sub_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE repl, hash = Qnil;
-    bool block_given = false;
-    bool tainted = false;
-    bool untrusted = false;
-
-    if (argc == 1 && rb_block_given_p()) {
-	block_given = true;
-    }
-    else if (argc == 2) {
-	repl = argv[1];
-	hash = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash");
-	if (NIL_P(hash)) {
-	    StringValue(repl);
-	}
-	if (OBJ_TAINTED(repl)) {
-	    tainted = true;
-	}
-	if (OBJ_UNTRUSTED(repl)) {
-	    untrusted = true;
-	}
-    }
-    else {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
-    }
-
-    if (!block_given) {
-	// RubySpec compliance...
-	rstr_modify(str);
-    }
-
-    VALUE pat = get_pat(argv[0], true);
-    str_modifiable(str);
-    if (rb_reg_search(pat, str, 0, false) >= 0) {
-	VALUE match = rb_backref_get();
-	int count = 0;
-	rb_match_result_t *results = rb_reg_match_results(match, &count);
-	assert(count > 0);
-
-	if (block_given || !NIL_P(hash)) {
-            if (block_given) {
-		rb_match_busy(match);
-		const unsigned long hash = rb_str_hash(str);
-		repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
-		if (rb_str_hash(str) != hash) {
-		    rb_raise(rb_eRuntimeError, "string modified");
-		}
-            }
-            else {
-                repl = rb_hash_aref(hash, rstr_substr(str, results[0].beg,
-			    results[0].end - results[0].beg));
-                repl = rb_obj_as_string(repl);
-            }
-	    rstr_frozen_check(str);
-	    if (block_given) {
-		rb_backref_set(match);
-		RETURN_IF_BROKEN();
-	    }
-	}
-	else {
-	    repl = rb_reg_regsub(repl, str, pat, results, count, NULL);
-	}
-
-	rstr_modify(str);
-	str_splice(RSTR(str), results[0].beg, results[0].end - results[0].beg,
-		str_need_string(repl));
-	if (OBJ_TAINTED(repl)) {
-	    tainted = true;
-	}
-	if (OBJ_UNTRUSTED(repl)) {
-	    untrusted = true;
-	}
-
-	if (tainted) {
-	    OBJ_TAINT(str);
-	}
-	if (untrusted) {
-	    OBJ_UNTRUST(str);
-	}
-	return str;
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     str.sub(pattern, replacement)         => new_str
- *     str.sub(pattern) {|match| block }     => new_str
- *  
- *  Returns a copy of <i>str</i> with the <em>first</em> occurrence of
- *  <i>pattern</i> replaced with either <i>replacement</i> or the value of the
- *  block. The <i>pattern</i> will typically be a <code>Regexp</code>; if it is
- *  a <code>String</code> then no regular expression metacharacters will be
- *  interpreted (that is <code>/\d/</code> will match a digit, but
- *  <code>'\d'</code> will match a backslash followed by a 'd').
- *     
- *  If the method call specifies <i>replacement</i>, special variables such as
- *  <code>$&</code> will not be useful, as substitution into the string occurs
- *  before the pattern match starts. However, the sequences <code>\1</code>,
- *  <code>\2</code>, <code>\k<group_name></code>, etc., may be used.
- *     
- *  In the block form, the current match string is passed in as a parameter, and
- *  variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- *  <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- *  returned by the block will be substituted for the match on each call.
- *     
- *  The result inherits any tainting in the original string or any supplied
- *  replacement string.
- *     
- *     "hello".sub(/[aeiou]/, '*')                  #=> "h*llo"
- *     "hello".sub(/([aeiou])/, '<\1>')             #=> "h<e>llo"
- *     "hello".sub(/./) {|s| s[0].ord.to_s + ' ' }  #=> "104 ello"
- *     "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*')  #=> "h*e*llo"
- */
-
-static VALUE
-rstr_sub(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    str = rb_str_new3(str);
-    rstr_sub_bang(str, 0, argc, argv);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.gsub!(pattern, replacement)        => str or nil
- *     str.gsub!(pattern) {|match| block }    => str or nil
- *  
- *  Performs the substitutions of <code>String#gsub</code> in place, returning
- *  <i>str</i>, or <code>nil</code> if no substitutions were performed.
- */
-
-static VALUE
-str_gsub(SEL sel, int argc, VALUE *argv, VALUE str, bool bang)
-{
-    bool block_given = false;
-    bool tainted = false;
-    bool untrusted = false;
-    VALUE hash = Qnil, repl = Qnil;
- 
-    switch (argc) {
-	case 1:
-	    RETURN_ENUMERATOR(str, argc, argv);
-	    block_given = true;
-	    break;
-
-	case 2:
-	    repl = argv[1];
-	    hash = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash");
-	    if (NIL_P(hash)) {
-		StringValue(repl);
-	    }
-	    if (OBJ_TAINTED(repl)) {
-		tainted = true;
-	    }
-	    if (OBJ_UNTRUSTED(repl)) {
-		untrusted = true;
-	    }
-	    break;
-
-	default:
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)",
-		    argc);
-    }
-
-    VALUE pat = get_pat(argv[0], 1);
-    VALUE dest = rb_str_new5(str, NULL, 0);
-    long offset = 0, last = 0;
-    bool changed = false;
-    const long len = str_length(RSTR(str));
-    VALUE match = Qnil;
-
-    if (bang) {
-	// RubySpec compliance...
-	rstr_modify(str);
-    }
-
-    VALUE matcher = rb_reg_matcher_new(pat, str);
-
-    character_boundaries_cache_t local_cache_for_str;
-    reset_character_boundaries_cache(&local_cache_for_str);
-
-    while (true) {
-        const long pos = rb_reg_matcher_search(pat, matcher, offset, false);
-	if (pos < 0) {
-	    if (!changed) {
-		rb_reg_matcher_destroy(matcher);
-		return bang ? Qnil : rstr_dup(str, 0);
-	    }
-	    if (last < len) {
-		VALUE substr = rstr_substr_with_cache(str, last, len - last,
-			&local_cache_for_str);
-		if (substr != Qnil) {
-		    str_concat_string(RSTR(dest), RSTR(substr));
-		}
-	    }
-	    break;
-	}
-
-	if (pos - last > 0) {
-	    // this concatenation must be done before calling the block
-	    // or doing the replacement or else the cache can't be used
-	    str_concat_string_part(RSTR(dest), RSTR(str), last, pos - last,
-		    &local_cache_for_str);
-	}
-
-	match = rb_backref_get();
-	int count = 0;
-	rb_match_result_t *results = rb_reg_match_results(match, &count);
-	assert(count > 0);
-
-	VALUE val;
-	if (block_given || !NIL_P(hash)) {
-            if (block_given) {
-		rb_match_busy(match);
-		VALUE to_yield = rb_reg_nth_match_with_cache(0, match,
-			&local_cache_for_str);
-		val = rb_obj_as_string(rb_yield(to_yield));
-            }
-            else {
-                val = rb_hash_aref(hash, rstr_substr_with_cache(str,
-			    results[0].beg,
-			    results[0].end - results[0].beg,
-			    &local_cache_for_str));
-                val = rb_obj_as_string(val);
-            }
-	    if (bang) {
-		rstr_frozen_check(str);
-	    }
-	    if (block_given) {
-		rb_backref_set(match);
-		RETURN_IF_BROKEN();
-	    }
-	}
-	else {
-	    val = rb_reg_regsub(repl, str, pat, results, count,
-		    &local_cache_for_str);
-	}
-
-	str_concat_string(RSTR(dest), str_need_string(val));
-
-	if (OBJ_TAINTED(val)) {
-	    tainted = true;
-	}
-	if (OBJ_UNTRUSTED(val)) {
-	    untrusted = true;
-	}
-	changed = true;
-
-	offset = last = results[0].end;
-	if (results[0].beg == offset) {
-	    offset++;
-	}
-    }
-
-    rb_reg_matcher_destroy(matcher);
-
-    rb_backref_set(match);
-
-    if (bang) {
-	str_replace(RSTR(str), dest);
-    }
-    else {
-    	if (!tainted && OBJ_TAINTED(str)) {
-	    tainted = true;
-	}
-	if (!untrusted && OBJ_UNTRUSTED(str)) {
-	    untrusted = true;
-	}
-	str = dest;
-    }
-
-    if (tainted) {
-	OBJ_TAINT(str);
-    }
-    if (untrusted) {
-	OBJ_UNTRUST(str);
-    }
-    return str;
-}
-
-static VALUE
-rstr_gsub_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    return str_gsub(sel, argc, argv, str, true);
-}
-
-/*
- *  call-seq:
- *     str.gsub(pattern, replacement)       => new_str
- *     str.gsub(pattern) {|match| block }   => new_str
- *  
- *  Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i>
- *  replaced with either <i>replacement</i> or the value of the block. The
- *  <i>pattern</i> will typically be a <code>Regexp</code>; if it is a
- *  <code>String</code> then no regular expression metacharacters will be
- *  interpreted (that is <code>/\d/</code> will match a digit, but
- *  <code>'\d'</code> will match a backslash followed by a 'd').
- *     
- *  If a string is used as the replacement, special variables from the match
- *  (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it,
- *  as substitution into the string occurs before the pattern match
- *  starts. However, the sequences <code>\1</code>, <code>\2</code>,
- *  <code>\k<group_name></code>, and so on may be used to interpolate
- *  successive groups in the match.
- *     
- *  In the block form, the current match string is passed in as a parameter, and
- *  variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- *  <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- *  returned by the block will be substituted for the match on each call.
- *     
- *  The result inherits any tainting in the original string or any supplied
- *  replacement string.
- *     
- *     "hello".gsub(/[aeiou]/, '*')                  #=> "h*ll*"
- *     "hello".gsub(/([aeiou])/, '<\1>')             #=> "h<e>ll<o>"
- *     "hello".gsub(/./) {|s| s[0].ord.to_s + ' '}   #=> "104 101 108 108 111 "
- *     "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}')  #=> "h{e}ll{o}"
- */
-
-static VALUE
-rstr_gsub(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    return str_gsub(sel, argc, argv, str, false);
-}
-
-/*
- *  call-seq:
- *     str.downcase!   => str or nil
- *  
- *  Downcases the contents of <i>str</i>, returning <code>nil</code> if no
- *  changes were made.
- *  Note: case replacement is effective only in ASCII region.
- */
-typedef char (^change_case_callback_t)(char c, bool first_char);
-static bool
-rstr_change_case(VALUE str, change_case_callback_t callback)
-{
-    if (RSTR(str)->encoding->ascii_compatible) {
-	bool changed = false;
-	for (long i = 0; i < RSTR(str)->length_in_bytes; ++i) {
-	    char c = RSTR(str)->bytes[i];
-	    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
-		char new_c = callback(c, i == 0);
-		if (new_c != c) {
-		    changed = true;
-		    RSTR(str)->bytes[i] = new_c;
-		}
-	    }
-	}
-	return changed;
-    }
-    else {
-	assert(IS_UTF32_ENC(RSTR(str)->encoding)
-		|| IS_UTF16_ENC(RSTR(str)->encoding));
-
-	__block bool changed = true;
-	str_each_uchar32(RSTR(str), ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
-		char new_c = callback(c, start_index == 0);
-		if (new_c != c) {
-		    changed = true;
-		    memset(&RSTR(str)->bytes[start_index], 0, char_len);
-		    if (RSTR(str)->encoding->little_endian) {
-			RSTR(str)->bytes[start_index] = new_c;
-		    }
-		    else {
-			RSTR(str)->bytes[start_index+char_len-1] = new_c;
-		    }
-		}
-	    }
-	});
-	return changed;
-    }
-}
-
-static VALUE
-rstr_downcase_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    bool changed = rstr_change_case(str, ^ char (char c, bool first_char) {
-	if (c >= 'A' && c <= 'Z') {
-	    return 'a' + (c - 'A');
-	}
-	return c;
-    });
-
-    return changed ? str : Qnil;
-}
-
-/*
- *  call-seq:
- *     str.downcase   => new_str
- *  
- *  Returns a copy of <i>str</i> with all uppercase letters replaced with their
- *  lowercase counterparts. The operation is locale insensitive---only
- *  characters ``A'' to ``Z'' are affected.
- *  Note: case replacement is effective only in ASCII region.
- *     
- *     "hEllO".downcase   #=> "hello"
- */
-
-VALUE
-rstr_downcase(VALUE str, SEL sel)
-{
-    str = rb_str_new3(str);
-    rstr_downcase_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.upcase!   => str or nil
- *  
- *  Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes
- *  were made.
- *  Note: case replacement is effective only in ASCII region.
- */
-
-static VALUE
-rstr_upcase_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    bool changed = rstr_change_case(str, ^ char (char c, bool first_char) {
-	if (c >= 'a' && c <= 'z') {
-	    return 'A' + (c - 'a');
-	}
-	return c;
-    });
-
-    return changed ? str : Qnil;
-}
-
-/*
- *  call-seq:
- *     str.upcase   => new_str
- *  
- *  Returns a copy of <i>str</i> with all lowercase letters replaced with their
- *  uppercase counterparts. The operation is locale insensitive---only
- *  characters ``a'' to ``z'' are affected.
- *  Note: case replacement is effective only in ASCII region.
- *     
- *     "hEllO".upcase   #=> "HELLO"
- */
-
-VALUE
-rstr_upcase(VALUE str, SEL sel)
-{
-    str = rb_str_new3(str);
-    rstr_upcase_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq: 
- *     str.swapcase!   => str or nil
- *  
- *  Equivalent to <code>String#swapcase</code>, but modifies the receiver in
- *  place, returning <i>str</i>, or <code>nil</code> if no changes were made.
- *  Note: case conversion is effective only in ASCII region.
- */
-
-static VALUE
-rstr_swapcase_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    bool changed = rstr_change_case(str, ^ char (char c, bool first_char) {
-	if (c >= 'A' && c <= 'Z') {
-	    return 'a' + (c - 'A');
-	}
-        else if (c >= 'a' && c <= 'z') {
-	    return 'A' + (c - 'a');
-	}
-	return c;
-    });
-
-    return changed ? str : Qnil;
-}
-
-/*
- *  call-seq:
- *     str.swapcase   => new_str
- *  
- *  Returns a copy of <i>str</i> with uppercase alphabetic characters converted
- *  to lowercase and lowercase characters converted to uppercase.
- *  Note: case conversion is effective only in ASCII region.
- *     
- *     "Hello".swapcase          #=> "hELLO"
- *     "cYbEr_PuNk11".swapcase   #=> "CyBeR_pUnK11"
- */
-
-VALUE
-rstr_swapcase(VALUE str, SEL sel)
-{
-    str = rb_str_new3(str);
-    rstr_swapcase_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.capitalize!   => str or nil
- *  
- *  Modifies <i>str</i> by converting the first character to uppercase and the
- *  remainder to lowercase. Returns <code>nil</code> if no changes are made.
- *  Note: case conversion is effective only in ASCII region.
- *     
- *     a = "hello"
- *     a.capitalize!   #=> "Hello"
- *     a               #=> "Hello"
- *     a.capitalize!   #=> nil
- */
-
-static VALUE
-rstr_capitalize_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    bool changed = rstr_change_case(str, ^ char (char c, bool first_char) {
-        if (first_char) {
-	    if (c >= 'a' && c <= 'z') {
-		return 'A' + (c - 'a');
-	    }
-	}
-	else if (c >= 'A' && c <= 'Z') {
-	    return 'a' + (c - 'A');
-	}
-	return c;
-    });
-
-    return changed ? str : Qnil;
-}
-
-/*
- *  call-seq:
- *     str.capitalize   => new_str
- *  
- *  Returns a copy of <i>str</i> with the first character converted to uppercase
- *  and the remainder to lowercase.
- *  Note: case conversion is effective only in ASCII region.
- *     
- *     "hello".capitalize    #=> "Hello"
- *     "HELLO".capitalize    #=> "Hello"
- *     "123ABC".capitalize   #=> "123abc"
- */
-
-VALUE
-rstr_capitalize(VALUE str, SEL sel)
-{
-    str = rb_str_new3(str);
-    rstr_capitalize_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.ljust(integer, padstr=' ')   => new_str
- *  
- *  If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- *  <code>String</code> of length <i>integer</i> with <i>str</i> left justified
- *  and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *     
- *     "hello".ljust(4)            #=> "hello"
- *     "hello".ljust(20)           #=> "hello               "
- *     "hello".ljust(20, '1234')   #=> "hello123412341234123"
- */
-
-static void
-rstr_justify_part(rb_str_t *str, rb_str_t *pad, long width, long padwidth,
-	long index)
-{
-    do {
-	if (padwidth > width) {
-	    pad = RSTR(rstr_substr((VALUE)pad, 0, width));
-	}
-	str_insert(str, index, pad);
-	width -= padwidth;
-	index += padwidth;
-    }
-    while (width > 0);
-}
-
-static VALUE
-rstr_justify(int argc, VALUE *argv, VALUE str, char mode)
-{
-    VALUE w, pad;
-    rb_scan_args(argc, argv, "11", &w, &pad);
-
-    if (NIL_P(pad)) {
-	pad = rb_str_new(" ", 1);
-    }
-    else {
-	StringValue(pad);
-    }
-
-    rb_str_t *padstr = str_need_string(pad);
-    const long padwidth = str_length(RSTR(padstr));
-    if (padwidth == 0) {
-	rb_raise(rb_eArgError, "zero width padding");
-    }
-
-    const long len = str_length(RSTR(str));
-    long width = NUM2LONG(w);
-    str = rb_str_new3(str);
-    if (width < 0 || width <= len) {
-	return str;
-    }
-    width -= len;
-
-    if (mode == 'c') {
-	rstr_justify_part(RSTR(str), padstr, ceil(width / 2.0), padwidth, len);
-	rstr_justify_part(RSTR(str), padstr, floor(width / 2.0), padwidth, 0);
-    }
-    else if (mode == 'l') {
-	rstr_justify_part(RSTR(str), padstr, width, padwidth, len);
-    }
-    else if (mode == 'r') {
-	rstr_justify_part(RSTR(str), padstr, width, padwidth, 0);
-    }
-    else {
-	rb_bug("invalid mode");
-    }
-
-    if (OBJ_TAINTED(pad)) {
-	OBJ_TAINT(str);
-    }
-
-    return str;
-}
-
-static VALUE
-rstr_ljust(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    return rstr_justify(argc, argv, str, 'l');
-}
-
-/*
- *  call-seq:
- *     str.rjust(integer, padstr=' ')   => new_str
- *  
- *  If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- *  <code>String</code> of length <i>integer</i> with <i>str</i> right justified
- *  and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *     
- *     "hello".rjust(4)            #=> "hello"
- *     "hello".rjust(20)           #=> "               hello"
- *     "hello".rjust(20, '1234')   #=> "123412341234123hello"
- */
-
-static VALUE
-rstr_rjust(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    return rstr_justify(argc, argv, str, 'r');
-}
-
-/*
- *  call-seq:
- *     str.center(integer, padstr)   => new_str
- *  
- *  If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- *  <code>String</code> of length <i>integer</i> with <i>str</i> centered and
- *  padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *     
- *     "hello".center(4)         #=> "hello"
- *     "hello".center(20)        #=> "       hello        "
- *     "hello".center(20, '123') #=> "1231231hello12312312"
- */
-
-static VALUE
-rstr_center(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    return rstr_justify(argc, argv, str, 'c');
-}
-
-/*
- *  call-seq:
- *     str.strip!   => str or nil
- *  
- *  Removes leading and trailing whitespace from <i>str</i>. Returns
- *  <code>nil</code> if <i>str</i> was not altered.
- */
-
-static VALUE
-str_strip(VALUE str, int direction)
-{
-    rstr_modify(str);
-
-    long len = str_length(RSTR(str));
-    if (len == 0) {
-	return Qnil;
-    }
-
-    bool changed = false;
-
-    if (direction <= 0) {
-	// Strip left side.
-	long pos = 0;
-	while (pos < len) {
-	    if (!isspace((char)rb_str_get_uchar(str, pos))) {
-		break;
-	    }
-	    pos++;
-	}
-
-	if (pos > 0) {
-	    str_delete(RSTR(str), 0, pos);
-	    len -= pos;
-	    changed = true;
-	}
-    }
-
-    if (direction >= 0) {
-	// Strip right side.
-	long pos = len - 1;
-	while (pos >= 0) {
-	    UChar c = rb_str_get_uchar(str, pos);
-	    if (!isspace((char)c) && c != '\0') {
-		break;
-	    }
-	    pos--;
-	}
-
-	if (pos < len - 1 && pos >= 0) {
-	    str_delete(RSTR(str), pos + 1, len - pos - 1);
-	    changed = true;
-	}
-    }
-
-    return changed ? str : Qnil;
-}
-
-static VALUE
-rstr_strip_bang(VALUE str, SEL sel)
-{
-    return str_strip(str, 0);
-}
-
-/*
- *  call-seq:
- *     str.strip   => new_str
- *  
- *  Returns a copy of <i>str</i> with leading and trailing whitespace removed.
- *     
- *     "    hello    ".strip   #=> "hello"
- *     "\tgoodbye\r\n".strip   #=> "goodbye"
- */
-
-static VALUE
-rstr_strip(VALUE str, SEL sel)
-{
-    str = rstr_dup(str, 0);
-    rstr_strip_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.lstrip!   => self or nil
- *  
- *  Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no
- *  change was made. See also <code>String#rstrip!</code> and
- *  <code>String#strip!</code>.
- *     
- *     "  hello  ".lstrip   #=> "hello  "
- *     "hello".lstrip!      #=> nil
- */
-
-static VALUE
-rstr_lstrip_bang(VALUE str, SEL sel)
-{
-    return str_strip(str, -1);
-}
-
-/*
- *  call-seq:
- *     str.lstrip   => new_str
- *  
- *  Returns a copy of <i>str</i> with leading whitespace removed. See also
- *  <code>String#rstrip</code> and <code>String#strip</code>.
- *     
- *     "  hello  ".lstrip   #=> "hello  "
- *     "hello".lstrip       #=> "hello"
- */
-
-static VALUE
-rstr_lstrip(VALUE str, SEL sel)
-{
-    str = rstr_dup(str, 0);
-    rstr_lstrip_bang(str, 0);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.rstrip!   => self or nil
- *  
- *  Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if
- *  no change was made. See also <code>String#lstrip!</code> and
- *  <code>String#strip!</code>.
- *     
- *     "  hello  ".rstrip   #=> "  hello"
- *     "hello".rstrip!      #=> nil
- */
-
-static VALUE
-rstr_rstrip_bang(VALUE str, SEL sel)
-{
-    return str_strip(str, 1);
-}
-
-/*
- *  call-seq:
- *     str.rstrip   => new_str
- *  
- *  Returns a copy of <i>str</i> with trailing whitespace removed. See also
- *  <code>String#lstrip</code> and <code>String#strip</code>.
- *     
- *     "  hello  ".rstrip   #=> "  hello"
- *     "hello".rstrip       #=> "hello"
- */
-
-static VALUE
-rstr_rstrip(VALUE str, SEL sel)
-{
-    str = rstr_dup(str, 0);
-    rstr_rstrip_bang(str, 0);
-    return str;
-}
-
-/*
- *  Document-method: lines
- *  call-seq:
- *     str.lines(separator=$/)   => anEnumerator
- *     str.lines(separator=$/) {|substr| block }        => str
- *  
- *  Returns an enumerator that gives each line in the string.  If a block is
- *  given, it iterates over each line in the string.
- *     
- *     "foo\nbar\n".lines.to_a   #=> ["foo\n", "bar\n"]
- *     "foo\nb ar".lines.sort    #=> ["b ar", "foo\n"]
- */
-
-/*
- *  Document-method: each_line
- *  call-seq:
- *     str.each_line(separator=$/) {|substr| block }   => str
- *  
- *  Splits <i>str</i> using the supplied parameter as the record separator
- *  (<code>$/</code> by default), passing each substring in turn to the supplied
- *  block. If a zero-length record separator is supplied, the string is split
- *  into paragraphs delimited by multiple successive newlines.
- *     
- *     print "Example one\n"
- *     "hello\nworld".each {|s| p s}
- *     print "Example two\n"
- *     "hello\nworld".each('l') {|s| p s}
- *     print "Example three\n"
- *     "hello\n\n\nworld".each('') {|s| p s}
- *     
- *  <em>produces:</em>
- *     
- *     Example one
- *     "hello\n"
- *     "world"
- *     Example two
- *     "hel"
- *     "l"
- *     "o\nworl"
- *     "d"
- *     Example three
- *     "hello\n\n\n"
- *     "world"
- */
-
-static VALUE
-rstr_each_line(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE rs;
-    if (rb_scan_args(argc, argv, "01", &rs) == 0) {
-	rs = rb_rs;
-    }
-
-    RETURN_ENUMERATOR(str, argc, argv);
-
-    if (NIL_P(rs)) {
-	rb_yield(str);
-	return str;
-    }
-
-    StringValue(rs);
-
-    rb_str_t *rs_str = str_need_string(rs);
-    bool paragraph = false;
-    if (rs_str->length_in_bytes == 0) {
-	rs_str = RSTR(rb_str_new("\n\n", 2));
-	paragraph = true;
-    }
-
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-
-    const long len = str_length_with_cache(RSTR(str), &local_cache);
-    const bool tainted = OBJ_TAINTED(str);
-
-    long pos = 0;
-    while (true) {
-	long off = str_index_for_string_with_cache(RSTR(str), rs_str, pos, -1,
-		false, &local_cache);
-	if (paragraph && off >= 0) {
-	    // XXX this is slow if str is UTF-8 multibyte.
-	    int i;
-	    for (i = off + 1; i < len; i++) {
-		UChar c = str_get_uchar(RSTR(str), i);
-		if (c != '\n') {
-		    break;
-		}
-	    }
-	    off = i - 1;
-	}
-
-	long substr_len = 0;
-	if (off < 0) {
-	    if (pos == len) {
-		break;
-	    }
-	    substr_len = len - pos;
-	}
-	else {
-	    substr_len = off - pos + 1;
-	}
-
-	VALUE substr = rstr_substr_with_cache(str, pos, substr_len,
-		&local_cache);
-	if (tainted) {
-	    OBJ_TAINT(substr);
-	}
-	rb_yield(substr);
-	RETURN_IF_BROKEN();
-
-	if (off < 0) {
-	    break;
-	}
-	pos = off + 1;
-    }
-
-    return str;
-}
-
-/*
- *  Document-method: chars
- *  call-seq:
- *     str.chars                   => anEnumerator
- *     str.chars {|substr| block } => str
- *  
- *  Returns an enumerator that gives each character in the string.
- *  If a block is given, it iterates over each character in the string.
- *     
- *     "foo".chars.to_a   #=> ["f","o","o"]
- */
-
-/*
- *  Document-method: each_char
- *  call-seq:
- *     str.each_char {|cstr| block }    => str
- *  
- *  Passes each character in <i>str</i> to the given block.
- *     
- *     "hello".each_char {|c| print c, ' ' }
- *     
- *  <em>produces:</em>
- *     
- *     h e l l o 
- */
-
-static VALUE
-rstr_each_char(VALUE str, SEL sel)
-{
-    RETURN_ENUMERATOR(str, 0, 0);
-
-    __block VALUE return_value = str;
-
-    str_each_uchar32(RSTR(str), ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	VALUE charstr = (VALUE)str_new_copy_of_part(RSTR(str),
-	    start_index, char_len);
-	rb_yield(charstr);
-	VALUE v = rb_vm_pop_broken_value();
-	if (v != Qundef) {
-	    return_value = v;
-	    *stop = true;
-	}
-    });
-
-    return return_value;
-}
-
-/*
- *  Document-method: each_byte
- *  call-seq:
- *     str.each_byte {|fixnum| block }    => str
- *  
- *  Passes each byte in <i>str</i> to the given block.
- *     
- *     "hello".each_byte {|c| print c, ' ' }
- *     
- *  <em>produces:</em>
- *     
- *     104 101 108 108 111
- */
-
-static VALUE
-rstr_each_byte(VALUE str, SEL sel)
-{
-    RETURN_ENUMERATOR(str, 0, 0);
-
-    for (long i = 0; i < RSTR(str)->length_in_bytes; i++) {
-	rb_yield(INT2FIX((unsigned char)RSTR(str)->bytes[i]));
-	RETURN_IF_BROKEN();
-    }
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.codepoints {|integer| block }        -> str
- *     str.codepoints                           -> an_enumerator
- *
- *     str.each_codepoint {|integer| block }    -> str
- *     str.each_codepoint                       -> an_enumerator
- *
- *  Passes the <code>Integer</code> ordinal of each character in <i>str</i>,
- *  also known as a <i>codepoint</i> when applied to Unicode strings to the
- *  given block.
- *
- *  If no block is given, an enumerator is returned instead.
- *
- *     "hello\u0639".each_codepoint {|c| print c, ' ' }
- *
- *  <em>produces:</em>
- *
- *     104 101 108 108 111 1593
- */
-
-static VALUE
-rstr_each_codepoint(VALUE str, SEL sel)
-{
-    RETURN_ENUMERATOR(str, 0, 0);
-
-    __block VALUE return_value = str;
-    str_each_uchar32(RSTR(str), ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	if (c == U_SENTINEL) {
-	    str_invalid_byte_sequence(RSTR(str));
-	}
-	rb_yield(INT2NUM(c));
-	VALUE v = rb_vm_pop_broken_value();
-	if (v != Qundef) {
-	    return_value = v;
-	    *stop = true;
-	}
-    });
-
-    return return_value;
-}
-
-/*
- *  call-seq:
- *     str.succ   => new_str
- *     str.next   => new_str
- *  
- *  Returns the successor to <i>str</i>. The successor is calculated by
- *  incrementing characters starting from the rightmost alphanumeric (or
- *  the rightmost character if there are no alphanumerics) in the
- *  string. Incrementing a digit always results in another digit, and
- *  incrementing a letter results in another letter of the same case.
- *  Incrementing nonalphanumerics uses the underlying character set's
- *  collating sequence.
- *     
- *  If the increment generates a ``carry,'' the character to the left of
- *  it is incremented. This process repeats until there is no carry,
- *  adding an additional character if necessary.
- *     
- *     "abcd".succ        #=> "abce"
- *     "THX1138".succ     #=> "THX1139"
- *     "<<koala>>".succ   #=> "<<koalb>>"
- *     "1999zzz".succ     #=> "2000aaa"
- *     "ZZZ9999".succ     #=> "AAAA0000"
- *     "***".succ         #=> "**+"
- */
-
-static VALUE
-rstr_succ(VALUE str, SEL sel)
-{
-    if (rb_str_chars_len(str) == 0) {
-	return str;
-    }
-
-    if (!RSTR(str)->encoding->ascii_compatible) {
-	rb_raise(rb_eArgError, "The encoding must be ASCII-compatible");
-    }
-
-    char *chars_buf = (char *)malloc(RSTR(str)->length_in_bytes + 1);
-    char *chars_ptr = &chars_buf[1];
-
-    memcpy(chars_ptr, RSTR(str)->bytes, RSTR(str)->length_in_bytes);
-
-    long len = RSTR(str)->length_in_bytes;
-    char carry = 0;
-    bool modified = false;
-
-    for (long i = len - 1; i >= 0; i--) {
-	char c = chars_ptr[i];
-	if (isdigit(c)) {
-	    modified = true;
-	    if (c != '9') {
-		chars_ptr[i]++;
-		carry = 0;
-		break;
-	    }
-	    else {
-		chars_ptr[i] = '0';
-		carry = '1';
-	    }
-	}
-	else if (isalpha(c)) {
-	    const bool lower = islower(c);
-	    UChar e = lower ? 'z' : 'Z';
-	    modified = true;
-	    if (c != e) {
-		chars_ptr[i]++;
-		carry = 0;
-		break;
-	    }
-	    else {
-		carry = chars_ptr[i] = lower ? 'a' : 'A';
-	    }
-	}
-#if 0 // TODO: this requires more love
-	else if (!isascii(c)) {
-	    modified = true;
-	    chars_ptr[i]++;
-	    carry = 0;
-	    break;
-	}
-#endif
-    }
-
-    if (!modified) {
-	chars_ptr[len - 1]++;
-    }
-    else if (carry != 0) {
-	chars_ptr = chars_buf;
-	chars_ptr[0] = carry;
-	len++;
-    }
-
-    VALUE newstr = rb_enc_str_new(chars_ptr, len, RSTR(str)->encoding);
-    free(chars_buf);
-    OBJ_INFECT(newstr, str);
-
-    return newstr;
-}
-
-/*
- *  call-seq:
- *     str.succ!   => str
- *     str.next!   => str
- *  
- *  Equivalent to <code>String#succ</code>, but modifies the receiver in
- *  place.
- */
-
-static VALUE
-rstr_succ_bang(VALUE str, SEL sel)
-{
-    rstr_replace(str, 0, rstr_succ(str, 0));
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.upto(other_str, exclusive=false) {|s| block }   => str
- *  
- *  Iterates through successive values, starting at <i>str</i> and
- *  ending at <i>other_str</i> inclusive, passing each value in turn to
- *  the block. The <code>String#succ</code> method is used to generate
- *  each value.  If optional second argument exclusive is omitted or is <code>false</code>,
- *  the last value will be included; otherwise it will be excluded.
- *     
- *     "a8".upto("b6") {|s| print s, ' ' }
- *     for s in "a8".."b6"
- *       print s, ' '
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     a8 a9 b0 b1 b2 b3 b4 b5 b6
- *     a8 a9 b0 b1 b2 b3 b4 b5 b6
- */
-
-static VALUE
-rstr_upto(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE beg = str;
-    VALUE end, exclusive;
-    rb_scan_args(argc, argv, "11", &end, &exclusive);
-
-    bool excl = RTEST(exclusive);
-    StringValue(end);
-
-    if (rb_str_chars_len(beg) == 1 && rb_str_chars_len(end) == 1) {
-	UChar begc = rb_str_get_uchar(beg, 0);
-	UChar endc = rb_str_get_uchar(end, 0);
-
-	if (begc > endc || (excl && begc == endc)) {
-	    return beg;
-	}
-	while (true) {
-	    rb_yield(rb_unicode_str_new(&begc, 1));
-	    RETURN_IF_BROKEN();
-	    if (!excl && begc == endc) {
-		break;
-	    }
-	    begc++;
-	    if (excl && begc == endc) {
-		break;
-	    }
-	}
-	return beg;
-    }
-
-    const int cmp = rb_str_cmp(beg, end);
-    if (cmp > 0 || (excl && cmp == 0)) {
-	return beg;
-    }
-
-    SEL succ_sel = sel_registerName("succ");
-
-    VALUE current = beg;
-    VALUE after_end = rb_vm_call(end, succ_sel, 0, NULL);
-    StringValue(after_end);
-    while (!rb_str_equal(current, after_end)) {
-	rb_yield(current);
-	RETURN_IF_BROKEN();
-	if (!excl && rb_str_equal(current, end)) {
-	    break;
-	}
-	current = rb_vm_call(current, succ_sel, 0, NULL);
-	StringValue(current);
-	if (excl && rb_str_equal(current, end)) {
-	    break;
-	}
-	if (rb_str_chars_len(current) > rb_str_chars_len(end)
-		|| rb_str_chars_len(current) == 0) {
-	    break;
-	}
-    }
-    return beg;
-}
-
-// :nodoc
-static VALUE
-rstr_transform(VALUE str, SEL sel, VALUE transform_pat)
-{
-    StringValue(transform_pat);
-
-    long new_chars_len = 0;
-    UChar *new_chars = rb_str_xcopy_uchars(str, &new_chars_len);
-    if (new_chars_len == 0) {
-	return Qnil;
-    }
-
-    RB_STR_GET_UCHARS(str, transform_chars, transform_chars_len);
-
-    UErrorCode status = U_ZERO_ERROR;
-    UTransliterator *trans = utrans_openU(transform_chars, transform_chars_len,
-	    UTRANS_FORWARD, NULL, 0, NULL, &status);
-
-    if (trans == NULL) {
-	rb_raise(rb_eArgError, "cannot create transliterator");
-    }
-
-    int32_t capacity = (int32_t)new_chars_len;
-    int32_t limit = capacity;
-    utrans_transUChars(trans, new_chars, &capacity, capacity,
-	    0, &limit, &status);
-
-    return rb_unicode_str_new(new_chars, (long)capacity);
-}
-
-/*
- *  call-seq:
- *     str.reverse!   => str
- *  
- *  Reverses <i>str</i> in place.
- */
-
-static VALUE
-rstr_reverse_bang(VALUE str, SEL sel)
-{
-    rstr_modify(str);
-
-    if (RSTR(str)->length_in_bytes <= 1) {
-	return str;
-    }
-
-    char *new_bytes = xmalloc(RSTR(str)->length_in_bytes);
-    __block long pos = RSTR(str)->length_in_bytes;
-    str_each_uchar32(RSTR(str), ^(UChar32 c, long start_index, long char_len, bool *stop) {
-	pos -= char_len;
-	memcpy(&new_bytes[pos], &RSTR(str)->bytes[start_index], char_len);
-    });
-    assert(pos == 0);
-
-    RSTR(str)->capacity_in_bytes = RSTR(str)->length_in_bytes;
-    GC_WB(&RSTR(str)->bytes, new_bytes);
-
-    // we modify it directly so the information stored
-    // in the facultative flags might be outdated
-    str_reset_flags(RSTR(str));
-
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.reverse   => new_str
- *  
- *  Returns a new string with the characters from <i>str</i> in reverse order.
- *     
- *     "stressed".reverse   #=> "desserts"
- */
-
-static VALUE
-rstr_reverse(VALUE str, SEL sel)
-{
-    VALUE obj = rb_str_new3(str);
-    rstr_reverse_bang(obj, 0);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     str.count([other_str]+)   => fixnum
- *  
- *  Each <i>other_str</i> parameter defines a set of characters to count.  The
- *  intersection of these sets defines the characters to count in
- *  <i>str</i>. Any <i>other_str</i> that starts with a caret (^) is
- *  negated. The sequence c1--c2 means all characters between c1 and c2.
- *     
- *     a = "hello world"
- *     a.count "lo"            #=> 5
- *     a.count "lo", "o"       #=> 2
- *     a.count "hello", "^l"   #=> 4
- *     a.count "ej-m"          #=> 4
- */
-
-static void
-fill_linear_charset_buffer(char *buf, long bufsize, long *lenp, bool *negatep,
-	VALUE source)
-{
-    StringValue(source);
-
-    RB_STR_GET_UCHARS(source, chars, chars_len);
-
-    long pos = 0;
-    if (negatep != NULL) {
-	if (chars_len > 0 && chars[0] == '^') {
-	    *negatep = true;
-	    pos++;
-	} 
-	else {
-	    *negatep = false;
-	}
-    }
-
-    bool error = false;
-    long bufpos = 0;
-
-    while (pos < chars_len) {
-	UChar c = chars[pos];
-
-	if (pos + 2 < chars_len && c != '\\' && chars[pos + 1] == '-') {
-	    // Range
-	    UChar e = chars[pos + 2];
-	    if (c > e) {
-		error = true;
-		goto bail;
-	    }
-
-	    if (c < 0xff && e < 0xff) {
-		while (c <= e) {
-		    if (bufpos >= bufsize) {
-			error = true;
-			goto bail;
-		    }
-		    buf[bufpos++] = (char)c;
-		    c++; 
-		}
-	    }
-	    pos += 2;
-	}
-	else {
-	    if (c < 0xff) {
-		if (bufpos >= bufsize) {
-		    error = true;
-		    goto bail;
-		}
-		buf[bufpos++] = (char)c;
-	    }
-	    pos++;
-	}
-    }
-
-    *lenp = bufpos;
-
-bail:
-    if (error) {
-	rb_raise(rb_eArgError, "invalid string transliteration");
-    }
-}
-
-static void
-intersect_charset_table(char *tbl, VALUE source)
-{
-    // Generate linear buffer based on source pattern.
-    char buf[0xff];
-    bool negate = false;
-    long buflen = 0;
-    fill_linear_charset_buffer(buf, sizeof buf, &buflen, &negate, source);
-
-    // Create character table based on linear buffer.
-    char source_tbl[0xff];
-    char cflag = negate ? 1 : 0;
-    for (int i = 0; i < 0xff; i++) {
-	source_tbl[i] = cflag;
-    }
-    cflag = negate ? 0 : 1;
-    for (long i = 0; i < buflen; i++) {
-	char c = buf[i];
-	source_tbl[(int)c] = cflag;
-    }
-
-    // Intersect both tables.
-    for (int i = 0; i < 0xff; i++) {
-	tbl[i] = tbl[i] && source_tbl[i];
-    }
-}
-
-static void
-create_intersected_charset_table(char *tbl, int argc, VALUE *argv)
-{
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-
-    // Fill the table with 1s before starting the intersections.
-    for (int i = 0; i < 0xff; i++) {
-	tbl[i] = 1;
-    }
-
-    for (int i = 0; i < argc; i++) {
-	intersect_charset_table(tbl, argv[i]);	
-    }
-}
-
-static void
-create_translate_charset_table(char *tbl, VALUE source, VALUE repl)
-{
-    // Generate linear buffer based on source pattern.
-    char source_buf[0xff];
-    bool negate = false;
-    long source_buflen = 0;
-    fill_linear_charset_buffer(source_buf, sizeof source_buf, &source_buflen,
-	    &negate, source);
-
-    // Generate linear buffer based on repl pattern.
-    char repl_buf[0xff];
-    long repl_buflen = 0;
-    fill_linear_charset_buffer(repl_buf, sizeof repl_buf, &repl_buflen,
-	    NULL, repl);
-    assert(repl_buflen > 0);
-
-    // Fill the table based on the values from the linear buffers.
-    if (negate) {
-	for (int i = 0; i < 0xff; i++) {
-	    tbl[i] = 1;
-	}
-
-	long pos = 0;
-	while (pos < source_buflen) {
-	    const char source_c = source_buf[pos];
-	    tbl[(int)source_c] = 0;
-	    pos++;
-	}
-
-	for (int i = 0, pos = 0; i < 0xff; i++) {
-	    if (tbl[i] == 1) {
-		const char repl_c = pos >= repl_buflen
-		    ? repl_buf[repl_buflen - 1] : repl_buf[pos];
-		tbl[i] = repl_c;
-		pos++;
-	    }
-	}
-    }
-    else {
-	for (int i = 0; i < 0xff; i++) {
-	    tbl[i] = 0;
-	}
-
-	long pos = 0;
-	while (pos < source_buflen) {
-	    const char source_c = source_buf[pos];
-	    const char repl_c = pos >= repl_buflen
-		? repl_buf[repl_buflen - 1] : repl_buf[pos];
-	    tbl[(int)source_c] = repl_c;
-	    pos++;
-	}
-    } 
-}
-
-#define INTERSECT_CHARSET_TABLE_CREATE() \
-	char __tbl__[0xff]; \
-	create_intersected_charset_table(__tbl__, argc, argv);
-
-#define CHARSET_TABLE_INCLUDES(c) \
-	((c) < 0xff && __tbl__[(c) & 0xff] == 1)
-
-static VALUE
-rstr_count(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    INTERSECT_CHARSET_TABLE_CREATE();
-
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    long count = 0;
-    for (long i = 0; i < chars_len; i++) {
-	if (CHARSET_TABLE_INCLUDES(chars[i])) {
-	    count++;
-	}
-    }
-    return LONG2NUM(count); 
-}
-
-/*
- *  call-seq:
- *     str.delete!([other_str]+)   => str or nil
- *  
- *  Performs a <code>delete</code> operation in place, returning <i>str</i>, or
- *  <code>nil</code> if <i>str</i> was not modified.
- */
-
-static VALUE
-rstr_delete_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    rstr_modify(str);
-
-    INTERSECT_CHARSET_TABLE_CREATE();
-
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    bool modified = false;
-    for (long i = 0; i < chars_len; i++) {
-	while (i < chars_len && CHARSET_TABLE_INCLUDES(chars[i])) {
-	    for (long j = i; j < chars_len - 1; j++) {
-		chars[j] = chars[j + 1];
-	    }
-	    chars_len--;
-	    modified = true;
-	}
-    }
-
-    if (!modified) {
-	return Qnil;
-    }
-
-    str_replace_with_uchars(RSTR(str), chars, chars_len);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.delete([other_str]+)   => new_str
- *  
- *  Returns a copy of <i>str</i> with all characters in the intersection of its
- *  arguments deleted. Uses the same rules for building the set of characters as
- *  <code>String#count</code>.
- *     
- *     "hello".delete "l","lo"        #=> "heo"
- *     "hello".delete "lo"            #=> "he"
- *     "hello".delete "aeiou", "^e"   #=> "hell"
- *     "hello".delete "ej-m"          #=> "ho"
- */
-
-static VALUE
-rstr_delete(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    str = rb_str_new3(str);
-    rstr_delete_bang(str, 0, argc, argv);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.squeeze!([other_str]*)   => str or nil
- *  
- *  Squeezes <i>str</i> in place, returning either <i>str</i>, or
- *  <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rstr_squeeze_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    rstr_modify(str);
-
-    // If no arguments are provided, we build a pattern string that contains
-    // the characters of the receiver itself.
-    VALUE tmp[1];
-    if (argc == 0) {
-	tmp[0] = str;
-	argv = tmp;
-	argc = 1;
-    }
-
-    INTERSECT_CHARSET_TABLE_CREATE();
-
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    bool modified = false;
-    for (long i = 0; i < chars_len; i++) {
-	UChar c = chars[i];
-	if (CHARSET_TABLE_INCLUDES(c)) {
-	    while (i + 1 < chars_len && chars[i + 1] == c) {
-		for (long j = i + 1; j < chars_len - 1; j++) {
-		    chars[j] = chars[j + 1];
-		}
-		chars_len--;
-		modified = true;
-	    }
-	}
-    }
-
-    if (!modified) {
-	return Qnil;
-    }
-
-    str_replace_with_uchars(RSTR(str), chars, chars_len);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.squeeze([other_str]*)    => new_str
- *  
- *  Builds a set of characters from the <i>other_str</i> parameter(s) using the
- *  procedure described for <code>String#count</code>. Returns a new string
- *  where runs of the same character that occur in this set are replaced by a
- *  single character. If no arguments are given, all runs of identical
- *  characters are replaced by a single character.
- *     
- *     "yellow moon".squeeze                  #=> "yelow mon"
- *     "  now   is  the".squeeze(" ")         #=> " now is the"
- *     "putters shoot balls".squeeze("m-z")   #=> "puters shot balls"
- */
-
-static VALUE
-rstr_squeeze(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    str = rb_str_new3(str);
-    rstr_squeeze_bang(str, 0, argc, argv);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.tr!(from_str, to_str)   => str or nil
- *  
- *  Translates <i>str</i> in place, using the same rules as
- *  <code>String#tr</code>. Returns <i>str</i>, or <code>nil</code> if no
- *  changes were made.
- */
-
-static VALUE
-translate(VALUE str, VALUE source, VALUE repl, bool sflag)
-{
-    StringValue(source);
-    StringValue(repl);
-
-    if (rb_str_chars_len(repl) == 0) {
-	return rstr_delete_bang(str, 0, 1, &source);
-    }
-
-    rstr_modify(str);
-
-    char tbl[0xff]; 
-    create_translate_charset_table(tbl, source, repl);
-
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    bool modified = false;
-    for (long i = 0; i < chars_len; i++) {
-	UChar c = chars[i];
-	if (c < 0xff) {
-	    char repl = tbl[(c & 0xff)];
-	    if (repl != 0) {
-		chars[i] = repl;
-		modified = true;
-// TODO
-//		if (sflag) {
-//		}
-	    }
-	}
-    } 
-
-    if (!modified) {
-	return Qnil;
-    }
-
-    str_replace_with_uchars(RSTR(str), chars, chars_len);
-    return str;
-}
-
-static VALUE
-rstr_tr_bang(VALUE str, SEL sel, VALUE src, VALUE repl)
-{
-    return translate(str, src, repl, false);
-}
-
-/*
- *  call-seq:
- *     str.tr(from_str, to_str)   => new_str
- *  
- *  Returns a copy of <i>str</i> with the characters in <i>from_str</i> replaced
- *  by the corresponding characters in <i>to_str</i>. If <i>to_str</i> is
- *  shorter than <i>from_str</i>, it is padded with its last character. Both
- *  strings may use the c1--c2 notation to denote ranges of characters, and
- *  <i>from_str</i> may start with a <code>^</code>, which denotes all
- *  characters except those listed.
- *     
- *     "hello".tr('aeiou', '*')    #=> "h*ll*"
- *     "hello".tr('^aeiou', '*')   #=> "*e**o"
- *     "hello".tr('el', 'ip')      #=> "hippo"
- *     "hello".tr('a-y', 'b-z')    #=> "ifmmp"
- */
-
-static VALUE
-rstr_tr(VALUE str, SEL sel, VALUE src, VALUE repl)
-{
-    str = rb_str_new3(str);
-    rstr_tr_bang(str, 0, src, repl);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.tr_s!(from_str, to_str)   => str or nil
- *  
- *  Performs <code>String#tr_s</code> processing on <i>str</i> in place,
- *  returning <i>str</i>, or <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rstr_tr_s_bang(VALUE str, SEL sel, VALUE src, VALUE repl)
-{
-    return translate(str, src, repl, true);
-}
-
-/*
- *  call-seq:
- *     str.tr_s(from_str, to_str)   => new_str
- *  
- *  Processes a copy of <i>str</i> as described under <code>String#tr</code>,
- *  then removes duplicate characters in regions that were affected by the
- *  translation.
- *     
- *     "hello".tr_s('l', 'r')     #=> "hero"
- *     "hello".tr_s('el', '*')    #=> "h*o"
- *     "hello".tr_s('el', 'hx')   #=> "hhxo"
- */
-
-static VALUE
-rstr_tr_s(VALUE str, SEL sel, VALUE src, VALUE repl)
-{
-    str = rb_str_new3(str);
-    rstr_tr_s_bang(str, 0, src, repl);
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.sum(n=16)   => integer
- *  
- *  Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>,
- *  where <em>n</em> is the optional <code>Fixnum</code> parameter, defaulting
- *  to 16. The result is simply the sum of the binary value of each character in
- *  <i>str</i> modulo <code>2n - 1</code>. This is not a particularly good
- *  checksum.
- */
-
-static inline VALUE
-rb_vm_call_simple(VALUE rcv, SEL sel, VALUE arg)
-{
-    return rb_vm_call(rcv, sel, 1, &arg);
-}
-
-static VALUE
-rstr_sum(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    int bits = 16;
-    if (argc > 0) {
-	VALUE vbits;
-	rb_scan_args(argc, argv, "01", &vbits);
-	bits = NUM2INT(vbits);
-    }
-
-    VALUE sum = INT2FIX(0);
-    unsigned long sum0 = 0;
-    for (long i = 0; i < RSTR(str)->length_in_bytes; i++) {
-	if (FIXNUM_MAX - UCHAR_MAX < sum0) {
-	    sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
-	    sum0 = 0;
-	}
-	sum0 += (unsigned char)RSTR(str)->bytes[i];
-    }
-    if (bits == 0) {
-	if (sum0 != 0) {
-	    sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
-	}
-    }
-    else {
-        if (sum == INT2FIX(0)) {
-            if (bits < (int)sizeof(long) * CHAR_BIT) {
-                sum0 &= (((unsigned long)1) << bits) - 1;
-            }
-            sum = LONG2FIX(sum0);
-        }
-        else {
-            if (sum0 != 0) {
-                sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
-            }
-
-            VALUE mod = rb_vm_call_simple(INT2FIX(1), selLTLT, INT2FIX(bits));
-            mod = rb_vm_call_simple(mod, selMINUS, INT2FIX(1));
-            sum = rb_vm_call_simple(sum, selAND, mod);
-	}
-    }
-
-    return sum;
-}
-
-/*
- *  call-seq:
- *     str.partition(sep)              => [head, sep, tail]
- *  
- *  Searches the string for <i>sep</i> and returns the part before
- *  it, the <i>sep</i>, and the part after it.  If <i>sep</i> is not found,
- *  returns <i>str</i> and two empty strings.
- *     
- *     "hello".partition("l")         #=> ["he", "l", "lo"]
- *     "hello".partition("x")         #=> ["hello", "", ""]
- */
-
-static VALUE
-rstr_partition(VALUE str, SEL sel, VALUE sep)
-{
-    long pos = 0;
-    long seplen = 0;
-    bool regex = false;
-
-    if (TYPE(sep) == T_REGEXP) {
-	pos = rb_reg_search(sep, str, 0, false);
-	regex = true;
-    }
-    else {
-	StringValue(sep);
-	seplen = rb_str_chars_len(sep);
-	pos = str_index_for_string(RSTR(str), str_need_string(sep),
-		0, -1, false);
-    }
-    if (pos < 0) {
-failed:
-	{
-	    VALUE elems[] = { str, rb_str_new(NULL, 0), rb_str_new(NULL, 0) };
-	    return rb_ary_new4(3, elems);
-	}
-    }
-    if (regex) {
-	sep = rb_str_subpat(str, sep, 0);
-	seplen = rb_str_chars_len(sep);
-	if (pos == 0 && seplen == 0) {
-	    goto failed;
-	}
-    }
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-    const long len = str_length_with_cache(RSTR(str), &local_cache);
-    VALUE elems[] = {
-	rstr_substr_with_cache(str, 0, pos, &local_cache),
-	sep,
-	rstr_substr_with_cache(str, pos + seplen, len - pos - seplen, &local_cache)
-    };
-    return rb_ary_new4(3, elems);
-}
-
-/*
- *  call-seq:
- *     str.rpartition(sep)            => [head, sep, tail]
- *  
- *  Searches <i>sep</i> in the string from the end of the string, and
- *  returns the part before it, the <i>sep</i>, and the part after it.
- *  If <i>sep</i> is not found, returns two empty strings and
- *  <i>str</i>.
- *     
- *     "hello".rpartition("l")         #=> ["hel", "l", "o"]
- *     "hello".rpartition("x")         #=> ["", "", "hello"]
- */
-
-static VALUE
-rstr_rpartition(VALUE str, SEL sel, VALUE sep)
-{
-    character_boundaries_cache_t local_cache;
-    reset_character_boundaries_cache(&local_cache);
-    const long len = str_length_with_cache(RSTR(str), &local_cache);
-    long pos = len;
-    bool regex = false;
-
-    if (TYPE(sep) == T_REGEXP) {
-	pos = rb_reg_search(sep, str, pos, true);
-	regex = true;
-    }
-    else {
-	StringValue(sep);
-	pos = str_index_for_string(RSTR(str), str_need_string(sep),
-		0, -1, true);
-    }
-    if (pos < 0) {
-failed:
-	{
-	    VALUE elems[] = { rb_str_new(NULL, 0), rb_str_new(NULL,0), str };
-	    return rb_ary_new4(3, elems);
-	}
-    }
-    if (regex) {
-	sep = rb_reg_nth_match(0, rb_backref_get());
-	if (sep == Qnil) {
-	    goto failed;
-	}
-    }
-    const long seplen = rb_str_chars_len(sep);
-    VALUE elems[] = {
-	rstr_substr_with_cache(str, 0, pos, &local_cache),
-	sep,
-	rstr_substr_with_cache(str, pos + seplen, len - pos - seplen, &local_cache)
-    };
-    return rb_ary_new4(3, elems);
-}
-
-/*
- *  call-seq:
- *     str.crypt(other_str)   => new_str
- *  
- *  Applies a one-way cryptographic hash to <i>str</i> by invoking the standard
- *  library function <code>crypt</code>. The argument is the salt string, which
- *  should be two characters long, each character drawn from
- *  <code>[a-zA-Z0-9./]</code>.
- */
-
-static VALUE
-rstr_crypt(VALUE str, SEL sel, VALUE salt)
-{
-    StringValue(salt);
-    if (RSTRING_LEN(salt) < 2) {
-	rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
-    }
-
-    VALUE crypted = rb_str_new2(crypt(RSTRING_PTR(str), RSTRING_PTR(salt)));
-    OBJ_INFECT(crypted, str);
-    OBJ_INFECT(crypted, salt);
-    return crypted;
-}
-
-// NSString primitives.
-
-static void
-check_bounds(void *rcv, long pos, bool can_be_end)
-{
-    const long len = str_length(RSTR(rcv));
-    if (pos >= 0) {
-	if (can_be_end) {
-	    if (pos <= len) {
-		return;
-	    }
-	}
-	else if (pos < len) {
-	    return;
-	}
-    }
-
-    char buf[100];
-    snprintf(buf, sizeof buf, "Position (%ld) out of bounds (%ld)",
-	    pos, len);
-    rb_objc_exception_raise("NSRangeException", buf);
-}
-
-static CFIndex
-rstr_imp_length(void *rcv, SEL sel)
-{
-    return str_length(RSTR(rcv));
-}
-
-static UniChar
-rstr_imp_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
-    check_bounds(rcv, idx, false);
-    return str_get_uchar(RSTR(rcv), idx);
-}
-
-static void
-rstr_imp_getCharactersRange(void *rcv, SEL sel, UniChar *buffer, CFRange range)
-{
-    check_bounds(rcv, range.location + range.length, true);
-    str_extract_uchars_range(RSTR(rcv), range.location, range.length, buffer);
-}
-
-static void
-rstr_imp_replaceCharactersInRangeWithString(void *rcv, SEL sel, CFRange range,
-	void *str)
-{
-    check_bounds(rcv, range.location + range.length, true);
-    rb_str_t *spat = str_need_string((VALUE)str);
-    str_splice(RSTR(rcv), range.location, range.length, spat);
-}
-
-// :nodoc:
-static VALUE
-nsdata_to_str(VALUE data, SEL sel)
-{
-    CFDataRef dataref = (CFDataRef)data;
-    return rb_bstr_new_with_data(CFDataGetBytePtr(dataref),
-	    CFDataGetLength(dataref));
-}
-
-void Init_NSString(void);
-
-void
-Init_String(void)
-{
-    Init_NSString();
-
-    // rb_cRubyString is defined earlier in Init_PreVM().
-    rb_objc_install_NSObject_special_methods((Class)rb_cRubyString);
-    rb_set_class_path(rb_cRubyString, rb_cObject, "String");
-    rb_const_set(rb_cObject, rb_intern("String"), rb_cRubyString);
-
-    rb_objc_define_method(*(VALUE *)rb_cRubyString, "alloc", rstr_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cRubyString, "try_convert",
-	    rstr_try_convert, 1);
-    rb_objc_define_method(rb_cRubyString, "initialize", rstr_initialize, -1);
-    rb_objc_define_method(rb_cRubyString, "initialize_copy", rstr_replace, 1);
-    rb_objc_define_method(rb_cRubyString, "dup", rstr_dup, 0);
-    rb_objc_define_method(rb_cRubyString, "clone", rstr_clone, 0);
-    rb_objc_define_method(rb_cRubyString, "replace", rstr_replace, 1);
-    rb_objc_define_method(rb_cRubyString, "clear", rstr_clear, 0);
-    rb_objc_define_method(rb_cRubyString, "encoding", rstr_encoding, 0);
-    rb_objc_define_method(rb_cRubyString, "size", rstr_length, 0);
-    rb_objc_define_method(rb_cRubyString, "empty?", rstr_empty, 0);
-    rb_objc_define_method(rb_cRubyString, "bytesize", rstr_bytesize, 0);
-    rb_objc_define_method(rb_cRubyString, "getbyte", rstr_getbyte, 1);
-    rb_objc_define_method(rb_cRubyString, "setbyte", rstr_setbyte, 2);
-    rb_objc_define_method(rb_cRubyString, "to_data", rstr_to_data, 0);
-    rb_objc_define_method(rb_cRubyString, "pointer", rstr_pointer, 0);
-    rb_objc_define_method(rb_cRubyString, "force_encoding",
-	    rstr_force_encoding, 1);
-    rb_objc_define_method(rb_cRubyString, "valid_encoding?",
-	    rstr_is_valid_encoding, 0);
-    rb_objc_define_method(rb_cRubyString, "ascii_only?", rstr_is_ascii_only, 0);
-    rb_objc_define_method(rb_cRubyString, "[]", rstr_aref, -1);
-    rb_objc_define_method(rb_cRubyString, "[]=", rstr_aset, -1);
-    rb_objc_define_method(rb_cRubyString, "slice", rstr_aref, -1);
-    rb_objc_define_method(rb_cRubyString, "slice!", rstr_slice_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "insert", rstr_insert, 2);
-    rb_objc_define_method(rb_cRubyString, "index", rstr_index, -1);
-    rb_objc_define_method(rb_cRubyString, "rindex", rstr_rindex, -1);
-    rb_objc_define_method(rb_cRubyString, "+", rstr_plus, 1);
-    rb_objc_define_method(rb_cRubyString, "*", rstr_times, 1);
-    rb_objc_define_method(rb_cRubyString, "%", rstr_format, 1);
-    rb_objc_define_method(rb_cRubyString, "<<", rstr_concat, 1);
-    rb_objc_define_method(rb_cRubyString, "concat", rstr_concat, 1);
-    rb_objc_define_method(rb_cRubyString, "==", rstr_equal, 1);
-    rb_objc_define_method(rb_cRubyString, "<=>", rstr_cmp, 1);
-    rb_objc_define_method(rb_cRubyString, "casecmp", rstr_casecmp, 1);
-    rb_objc_define_method(rb_cRubyString, "eql?", rstr_eql, 1);
-    rb_objc_define_method(rb_cRubyString, "include?", rstr_includes, 1);
-    rb_objc_define_method(rb_cRubyString, "start_with?", rstr_start_with, -1);
-    rb_objc_define_method(rb_cRubyString, "end_with?", rstr_end_with, -1);
-    rb_objc_define_method(rb_cRubyString, "to_s", rstr_to_s, 0);
-    rb_objc_define_method(rb_cRubyString, "to_str", rstr_to_s, 0);
-    rb_objc_define_method(rb_cRubyString, "to_sym", rstr_intern, 0);
-    rb_objc_define_method(rb_cRubyString, "intern", rstr_intern, 0);
-    rb_objc_define_method(rb_cRubyString, "inspect", rstr_inspect, 0);
-    rb_objc_define_method(rb_cRubyString, "dump", rstr_dump, 0);
-    rb_objc_define_method(rb_cRubyString, "match", rstr_match2, -1);
-    rb_objc_define_method(rb_cRubyString, "=~", rstr_match, 1);
-    rb_objc_define_method(rb_cRubyString, "scan", rstr_scan, 1);
-    rb_objc_define_method(rb_cRubyString, "split", rstr_split, -1);
-    rb_objc_define_method(rb_cRubyString, "to_i", rstr_to_i, -1);
-    rb_objc_define_method(rb_cRubyString, "hex", rstr_hex, 0);
-    rb_objc_define_method(rb_cRubyString, "oct", rstr_oct, 0);
-    rb_objc_define_method(rb_cRubyString, "ord", rstr_ord, 0);
-    rb_objc_define_method(rb_cRubyString, "chr", rstr_chr, 0);
-    rb_objc_define_method(rb_cRubyString, "to_f", rstr_to_f, 0);
-    rb_objc_define_method(rb_cRubyString, "chomp", rstr_chomp, -1);
-    rb_objc_define_method(rb_cRubyString, "chomp!", rstr_chomp_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "chop", rstr_chop, -1);
-    rb_objc_define_method(rb_cRubyString, "chop!", rstr_chop_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "sub", rstr_sub, -1);
-    rb_objc_define_method(rb_cRubyString, "sub!", rstr_sub_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "gsub", rstr_gsub, -1);
-    rb_objc_define_method(rb_cRubyString, "gsub!", rstr_gsub_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "downcase", rstr_downcase, 0);
-    rb_objc_define_method(rb_cRubyString, "downcase!", rstr_downcase_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "upcase", rstr_upcase, 0);
-    rb_objc_define_method(rb_cRubyString, "upcase!", rstr_upcase_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "swapcase", rstr_swapcase, 0);
-    rb_objc_define_method(rb_cRubyString, "swapcase!", rstr_swapcase_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "capitalize", rstr_capitalize, 0);
-    rb_objc_define_method(rb_cRubyString, "capitalize!",
-	    rstr_capitalize_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "ljust", rstr_ljust, -1);
-    rb_objc_define_method(rb_cRubyString, "rjust", rstr_rjust, -1);
-    rb_objc_define_method(rb_cRubyString, "center", rstr_center, -1);
-    rb_objc_define_method(rb_cRubyString, "strip", rstr_strip, 0);
-    rb_objc_define_method(rb_cRubyString, "lstrip", rstr_lstrip, 0);
-    rb_objc_define_method(rb_cRubyString, "rstrip", rstr_rstrip, 0);
-    rb_objc_define_method(rb_cRubyString, "strip!", rstr_strip_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "lstrip!", rstr_lstrip_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "rstrip!", rstr_rstrip_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "lines", rstr_each_line, -1);
-    rb_objc_define_method(rb_cRubyString, "each_line", rstr_each_line, -1);
-    rb_objc_define_method(rb_cRubyString, "chars", rstr_each_char, 0);
-    rb_objc_define_method(rb_cRubyString, "each_char", rstr_each_char, 0);
-    rb_objc_define_method(rb_cRubyString, "bytes", rstr_each_byte, 0);
-    rb_objc_define_method(rb_cRubyString, "each_byte", rstr_each_byte, 0);
-    rb_objc_define_method(rb_cRubyString, "codepoints", rstr_each_codepoint, 0);
-    rb_objc_define_method(rb_cRubyString, "each_codepoint", rstr_each_codepoint, 0);
-    rb_objc_define_method(rb_cRubyString, "succ", rstr_succ, 0);
-    rb_objc_define_method(rb_cRubyString, "succ!", rstr_succ_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "next", rstr_succ, 0);
-    rb_objc_define_method(rb_cRubyString, "next!", rstr_succ_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "upto", rstr_upto, -1);
-    rb_objc_define_method(rb_cRubyString, "reverse", rstr_reverse, 0);
-    rb_objc_define_method(rb_cRubyString, "reverse!", rstr_reverse_bang, 0);
-    rb_objc_define_method(rb_cRubyString, "count", rstr_count, -1);
-    rb_objc_define_method(rb_cRubyString, "delete", rstr_delete, -1);
-    rb_objc_define_method(rb_cRubyString, "delete!", rstr_delete_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "squeeze", rstr_squeeze, -1);
-    rb_objc_define_method(rb_cRubyString, "squeeze!", rstr_squeeze_bang, -1);
-    rb_objc_define_method(rb_cRubyString, "tr", rstr_tr, 2);
-    rb_objc_define_method(rb_cRubyString, "tr!", rstr_tr_bang, 2);
-    rb_objc_define_method(rb_cRubyString, "tr_s", rstr_tr_s, 2);
-    rb_objc_define_method(rb_cRubyString, "tr_s!", rstr_tr_s_bang, 2);
-    rb_objc_define_method(rb_cRubyString, "sum", rstr_sum, -1);
-    rb_objc_define_method(rb_cRubyString, "partition", rstr_partition, 1);
-    rb_objc_define_method(rb_cRubyString, "rpartition", rstr_rpartition, 1);
-    rb_objc_define_method(rb_cRubyString, "crypt", rstr_crypt, 1);
-
-    // MacRuby extensions.
-    rb_objc_define_method(rb_cRubyString, "transform", rstr_transform, 1);
-
-    // Cocoa primitives.
-    rb_objc_install_method2((Class)rb_cRubyString, "length",
-	    (IMP)rstr_imp_length);
-    rb_objc_install_method2((Class)rb_cRubyString, "characterAtIndex:",
-	    (IMP)rstr_imp_characterAtIndex);
-    rb_objc_install_method2((Class)rb_cRubyString, "getCharacters:range:",
-	    (IMP)rstr_imp_getCharactersRange);
-    rb_objc_install_method2((Class)rb_cRubyString,
-	    "replaceCharactersInRange:withString:", 
-	    (IMP)rstr_imp_replaceCharactersInRangeWithString);
-
-    rb_fs = Qnil;
-    rb_define_variable("$;", &rb_fs);
-    rb_define_variable("$-F", &rb_fs);
-
-    // NSData extensions.
-    VALUE NSData = (VALUE)objc_getClass("NSData");
-    assert(NSData != 0);
-    rb_objc_define_method(NSData, "to_str", nsdata_to_str, 0);
-}
-
-bool
-rb_objc_str_is_pure(VALUE str)
-{
-    VALUE k = *(VALUE *)str;
-    while (RCLASS_SINGLETON(k)) {
-        k = RCLASS_SUPER(k);
-    }
-    if (k == rb_cRubyString) {
-        return true;
-    }
-    while (k != 0) {
-        if (k == rb_cRubyString) {
-            return false;
-        }
-        k = RCLASS_SUPER(k);
-    }
-    return true;
-}
-
-// ByteString emulation.
-
-VALUE
-rb_str_bstr(VALUE str)
-{
-    if (!IS_RSTR(str)) {
-	if (CFStringGetLength((CFStringRef)str) == 0) {
-	    return rb_bstr_new();
-	}
-	const char *cptr = CFStringGetCStringPtr((CFStringRef)str,
-		kCFStringEncodingUTF8);
-	if (cptr != NULL) {
-	    str = rb_str_new2(cptr);
-	}
-	else {
-	    const long max = CFStringGetMaximumSizeForEncoding(
-		    CFStringGetLength((CFStringRef)str), kCFStringEncodingUTF8);
-	    assert(max > 0);
-	    char *buf = (char *)malloc(max + 1);
-	    if (!CFStringGetCString((CFStringRef)str, buf, max,
-			kCFStringEncodingUTF8)) {
-		free(buf);
-		rb_raise(rb_eArgError,
-			"cannot coerce NSString %p as UTF-8 data", (void *)str);
-	    }
-	    str = rb_str_new2(buf);
-	    free(buf);
-	}
-    }
-    return str;
-}
-
-uint8_t *
-rb_bstr_bytes(VALUE str)
-{
-    assert(IS_RSTR(str));
-    return (uint8_t *)RSTR(str)->bytes;
-}
-
-VALUE
-rb_bstr_new_with_data(const uint8_t *bytes, long len)
-{
-    rb_str_t *str = str_alloc(rb_cRubyString);
-    str_replace_with_bytes(str, (char *)bytes, len,
-	    rb_encodings[ENCODING_BINARY]);
-    return (VALUE)str;
-}
-
-VALUE
-rb_bstr_new(void)
-{
-    return rb_bstr_new_with_data(NULL, 0);
-}
-
-long
-rb_bstr_length(VALUE str)
-{
-    assert(IS_RSTR(str));
-    return RSTR(str)->length_in_bytes;
-}
-
-void
-rb_bstr_concat(VALUE str, const uint8_t *bytes, long len)
-{
-    assert(IS_RSTR(str));
-    str_concat_bytes(RSTR(str), (const char *)bytes, len);
-}
-
-void
-rb_bstr_resize(VALUE str, long capa)
-{
-    assert(IS_RSTR(str));
-    str_resize_bytes(RSTR(str), capa);
-    RSTR(str)->length_in_bytes = capa;
-}
-
-void
-rb_bstr_set_length(VALUE str, long len)
-{
-    assert(IS_RSTR(str));
-    assert(len <= RSTR(str)->capacity_in_bytes);
-    RSTR(str)->length_in_bytes = len;
-}
-
-// Compiler primitives.
-
-VALUE
-rb_str_new_empty(void)
-{
-    return (VALUE)str_alloc(rb_cRubyString);
-}
-
-VALUE
-rb_unicode_str_new(const UniChar *ptr, const size_t len)
-{
-    VALUE str = rb_str_new_empty();
-    str_replace_with_uchars(RSTR(str), ptr, len);
-    return str;
-}
-
-VALUE
-rb_str_new_fast(int argc, ...)
-{
-    VALUE str = rb_str_new(NULL, 0);
-
-    if (argc > 0) {
-	va_list ar;
-	va_start(ar, argc);
-	for (int i = 0; i < argc; ++i) {
-	    VALUE fragment = va_arg(ar, VALUE);
-	    switch (TYPE(fragment)) {
-		default:
-		    fragment = rb_obj_as_string(fragment);
-		    // fall through
-
-		case T_STRING:
-		    rstr_concat(str, 0, fragment);
-		    break;
-	    }
-	}
-	va_end(ar);
-    }
-
-    return str;
-}
-
-VALUE
-rb_str_intern_fast(VALUE str)
-{
-    // TODO: this currently does 2 hash lookups, could be optimized.
-    return ID2SYM(rb_intern_str(str));
-}
-
-// MRI C-API compatibility.
-
-VALUE
-rb_enc_str_new(const char *cstr, long len, rb_encoding_t *enc)
-{
-    // XXX should we assert that enc is single byte?
-    if (enc == NULL) {
-	// This function can be called with a NULL encoding. 
-	enc = rb_encodings[ENCODING_UTF8];
-    }
-    else {
-	// People must use the bstr_ APIs to deal with binary.
-	assert(enc != rb_encodings[ENCODING_BINARY]);
-    }
-    rb_str_t *str = str_alloc(rb_cRubyString);
-    str_replace_with_bytes(str, cstr, len, enc);
-    return (VALUE)str;
-}
-
-VALUE
-rb_str_new(const char *cstr, long len)
-{
-    return rb_enc_str_new(cstr, len, rb_encodings[ENCODING_UTF8]);
-}
-
-VALUE
-rb_str_buf_new(long len)
-{
-    return rb_str_new(NULL, len);
-}
-
-VALUE
-rb_str_new2(const char *cstr)
-{
-    return rb_str_new(cstr, strlen(cstr));
-}
-
-VALUE
-rb_str_new3(VALUE source)
-{
-    rb_str_t *str = str_alloc(rb_obj_class(source));
-    str_replace(str, source);
-    OBJ_INFECT(str, source);
-    return (VALUE)str;
-}
-
-VALUE
-rb_str_new4(VALUE source)
-{
-    VALUE str = rb_str_new3(source);
-    OBJ_FREEZE(str);
-    return str;
-}
-
-VALUE
-rb_str_new5(VALUE source, const char *cstr, long len)
-{
-    rb_str_t *str = str_alloc(rb_obj_class(source));
-    str_replace_with_bytes(str, cstr, len, rb_encodings[ENCODING_UTF8]);
-    return (VALUE)str;
-}
-
-VALUE
-rb_tainted_str_new(const char *cstr, long len)
-{
-    VALUE str = rb_str_new(cstr, len);
-    OBJ_TAINT(str);
-    return str;
-}
-
-VALUE
-rb_tainted_str_new2(const char *cstr)
-{
-    return rb_tainted_str_new(cstr, strlen(cstr));
-}
-
-VALUE
-rb_usascii_str_new(const char *cstr, long len)
-{
-    VALUE str = rb_str_new(cstr, len);
-    RSTR(str)->encoding = rb_encodings[ENCODING_ASCII];
-    return str;
-}
-
-VALUE
-rb_usascii_str_new2(const char *cstr)
-{
-    return rb_usascii_str_new(cstr, strlen(cstr));
-}
-
-const char *
-rb_str_cstr(VALUE str)
-{
-    if (IS_RSTR(str)) {
-	if (RSTR(str)->length_in_bytes == 0) {
-	    return "";
-	}
-	str_ensure_null_terminator(RSTR(str));
-	return RSTR(str)->bytes;
-    }
-    return nsstr_cstr(str);
-}
-
-long
-rb_str_clen(VALUE str)
-{
-    if (IS_RSTR(str)) {
-	return RSTR(str)->length_in_bytes;
-    }
-    return nsstr_clen(str);
-}
-
-char *
-rb_string_value_cstr(volatile VALUE *ptr)
-{
-    VALUE str = rb_string_value(ptr);
-    return (char *)rb_str_cstr(str);
-}
-
-char *
-rb_string_value_ptr(volatile VALUE *ptr)
-{
-    return rb_string_value_cstr(ptr);
-}
-
-VALUE
-rb_string_value(volatile VALUE *ptr)
-{
-    VALUE s = *ptr;
-    if (TYPE(s) != T_STRING) {
-	s = rb_str_to_str(s);
-	*ptr = s;
-    }
-    return s;
-}
-
-VALUE
-rb_check_string_type(VALUE str)
-{
-    return rb_check_convert_type(str, T_STRING, "String", "to_str");
-}
-
-VALUE
-rb_str_to_str(VALUE str)
-{
-    return rb_convert_type(str, T_STRING, "String", "to_str");
-}
-
-VALUE
-rb_obj_as_string(VALUE obj)
-{
-    if (TYPE(obj) == T_STRING || TYPE(obj) == T_SYMBOL) {
-	return obj;
-    }
-    VALUE str = rb_vm_call(obj, selToS, 0, NULL);
-    if (TYPE(str) != T_STRING) {
-	return rb_any_to_s(obj);
-    }
-    if (OBJ_TAINTED(obj)) {
-	OBJ_TAINT(str);
-    }
-    return str;
-}
-
-void
-rb_str_setter(VALUE val, ID id, VALUE *var)
-{
-    if (!NIL_P(val) && TYPE(val) != T_STRING) {
-	rb_raise(rb_eTypeError, "value of %s must be String", rb_id2name(id));
-    }
-    if (*var != val) {
-	GC_RELEASE(*var);
-	*var = val;
-	GC_RETAIN(*var);
-    }
-}
-
-ID
-rb_to_id(VALUE name)
-{
-    VALUE tmp;
-    switch (TYPE(name)) {
-	default:
-	    tmp = rb_check_string_type(name);
-	    if (NIL_P(tmp)) {
-		rb_raise(rb_eTypeError, "%s is not a symbol",
-			RSTRING_PTR(rb_inspect(name)));
-	    }
-	    name = tmp;
-	    /* fall through */
-	case T_STRING:
-	    name = rstr_intern(name, 0);
-	    /* fall through */
-	case T_SYMBOL:
-	    return SYM2ID(name);
-    }
-}
-
-UChar
-rb_str_get_uchar(VALUE str, long pos)
-{
-    if (IS_RSTR(str)) {
-	return str_get_uchar(RSTR(str), pos);
-    }
-    assert(pos >= 0 && pos < CFStringGetLength((CFStringRef)str));
-    return CFStringGetCharacterAtIndex((CFStringRef)str, pos);
-}
-
-void
-rb_str_append_uchar(VALUE str, UChar c)
-{
-    if (IS_RSTR(str)) {
-	str_append_uchar32(RSTR(str), c);
-    }
-    else {
-	CFStringAppendCharacters((CFMutableStringRef)str, &c, 1);
-    }	
-}
-
-void
-rb_str_append_uchars(VALUE str, const UChar *chars, long len)
-{
-    assert(chars != NULL && len >= 0);
-
-    if (len > 0) {
-	if (IS_RSTR(str)) {
-	    str_concat_uchars(RSTR(str), chars, len);
-	}
-	else {
-	    CFStringAppendCharacters((CFMutableStringRef)str, chars, len);
-	}
-    }
-}
-
-long
-rb_str_chars_len(VALUE str)
-{
-    if (IS_RSTR(str)) {
-	return str_length(RSTR(str));
-    }
-    return CFStringGetLength((CFStringRef)str);
-}
-
-VALUE
-rb_str_length(VALUE str)
-{
-    return LONG2NUM(rb_str_chars_len(str));
-}
-
-VALUE
-rb_str_buf_new2(const char *cstr)
-{
-    return rb_str_new2(cstr);
-}
-
-VALUE
-rb_enc_str_buf_cat(VALUE str, const char *cstr, long len, rb_encoding_t *enc)
-{
-    if (IS_RSTR(str)) {
-	// XXX this could be optimized
-	VALUE substr = rb_enc_str_new(cstr, len, enc);
-	str_concat_string(RSTR(str), RSTR(substr));
-    }
-    else {
-	abort(); // TODO
-    }
-    return str;
-}
-
-VALUE
-rb_str_buf_cat(VALUE str, const char *cstr, long len)
-{
-    return rb_enc_str_buf_cat(str, cstr, len, RSTR(str)->encoding);
-}
-
-VALUE
-rb_str_buf_cat2(VALUE str, const char *cstr)
-{
-    return rb_str_buf_cat(str, cstr, strlen(cstr));
-}
-
-VALUE
-rb_str_cat(VALUE str, const char *cstr, long len)
-{
-    return rb_str_buf_cat(str, cstr, len);
-}
-
-VALUE
-rb_str_cat2(VALUE str, const char *cstr)
-{
-    return rb_str_buf_cat2(str, cstr);
-}
-
-VALUE
-rb_str_buf_cat_ascii(VALUE str, const char *cstr)
-{
-    return rb_str_buf_cat2(str, cstr);
-}
-
-VALUE
-rb_str_buf_append(VALUE str, VALUE str2)
-{
-    if (IS_RSTR(str)) {
-	return rstr_concat(str, 0, str2);
-    }
-    CFStringAppend((CFMutableStringRef)str, (CFStringRef)str2);
-    return str;
-}
-
-VALUE
-rb_str_append(VALUE str, VALUE str2)
-{
-    return rb_str_buf_append(str, str2);
-}
-
-VALUE
-rb_str_concat(VALUE str, VALUE str2)
-{
-    return rb_str_buf_append(str, str2);
-}
-
-void
-rb_str_associate(VALUE str, VALUE add)
-{
-    // Do nothing.
-}
-
-VALUE
-rb_str_associated(VALUE str)
-{
-    // Do nothing.
-    return Qfalse;
-}
-
-VALUE
-rb_str_resize(VALUE str, long len)
-{
-    if (IS_RSTR(str)) {
-	str_resize_bytes(RSTR(str), len);
-    }
-    else {
-	abort(); // TODO
-    }
-    return str;
-}
-
-void
-rb_str_set_len(VALUE str, long len)
-{
-    if (IS_RSTR(str)) {
-	assert(len <= RSTR(str)->length_in_bytes);
-	RSTR(str)->length_in_bytes = len;
-    }
-    else {
-	abort(); // TODO
-    }
-}
-
-VALUE
-rb_str_equal(VALUE str, VALUE str2)
-{
-    if (IS_RSTR(str)) {
-	return rstr_equal(str, 0, str2);
-    }
-    return CFEqual((CFStringRef)str, (CFStringRef)str2) ? Qtrue : Qfalse;
-}
-
-VALUE
-rb_str_dup(VALUE str)
-{
-    if (IS_RSTR(str)) {
-	return (VALUE)str_dup(RSTR(str));
-    }
-    if (TYPE(str) == T_SYMBOL) {
-	return rb_sym_to_s(str);
-    }
-    CFMutableStringRef copy
-	= CFStringCreateMutableCopy(NULL, 0, (CFStringRef)str);
-    CFMakeCollectable(copy);
-    return (VALUE)copy;
-}
-
-// Unicode characters hashing function, copied from CoreFoundation.
-// This function might have some performance issues on large strings.
-unsigned long
-rb_str_hash_uchars(const UChar *chars, long len)
-{
-    if (len == 0 || chars == NULL) {
-	return 0;
-    }
-#define HashNextFourUniChars(accessStart, accessEnd, pointer) \
-    {result = result * 67503105 + (accessStart 0 accessEnd) * 16974593  + (accessStart 1 accessEnd) * 66049  + (accessStart 2 accessEnd) * 257 + (accessStart 3 accessEnd); pointer += 4;}
-
-#define HashNextUniChar(accessStart, accessEnd, pointer) \
-    {result = result * 257 + (accessStart 0 accessEnd); pointer++;}
-
-    unsigned long result = len;
-    const UChar *end4 = chars + (len & ~3);
-    const UChar *end = chars + len;
-    // First count in fours
-    while (chars < end4) HashNextFourUniChars(chars[, ], chars);
-    // Then for the last <4 chars, count in ones...
-    while (chars < end) HashNextUniChar(chars[, ], chars);
-    return result + (result << (len & 31));
-
-#undef HashNextFourUniChars
-#undef HashNextUniChar
-}
-
-unsigned long
-rb_str_hash(VALUE str)
-{
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-    return rb_str_hash_uchars(chars, chars_len);
-}
-
-long
-rb_uchar_strtol(UniChar *chars, long chars_len, long pos, long *end_offset)
-{
-    assert(chars != NULL && chars_len > 0 && pos >= 0);
-
-    UErrorCode status = U_ZERO_ERROR;
-    UNumberFormat *nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, &status);
-    assert(nf != NULL);
-
-    int32_t parse_pos = (int32_t)pos;
-    int64_t val = unum_parseInt64(nf, chars, chars_len, &parse_pos, &status);
-    unum_close(nf);
-
-    if (end_offset != NULL) {
-	long offset = (long)pos;
-	do {
-	    if (!isdigit(chars[offset])) {
-		break;
-	    }
-	}
-	while (++offset < parse_pos);
-	*end_offset = offset;
-    }
-    return val;
-}
-
-long
-rb_memhash(const void *ptr, long len)
-{
-    CFDataRef data = CFDataCreate(NULL, (const UInt8 *)ptr, len);
-    const long code = CFHash(data);
-    CFRelease((CFTypeRef)data);
-    return code;
-}
-
-VALUE
-rb_str_inspect(VALUE str)
-{
-    if (!IS_RSTR(str)) {
-	str = (VALUE)str_need_string(str);
-    }
-    return rstr_inspect(str, 0);
-}
-
-VALUE
-rb_str_subseq(VALUE str, long beg, long len)
-{
-    assert(IS_RSTR(str) && beg >= 0 && len >= 0
-	    && RSTR(str)->length_in_bytes >= len + beg);
-    VALUE subseq;
-    if (len == 0) {
-	subseq = (VALUE)str_new_similar_empty_string(RSTR(str));
-    }
-    else {
-	subseq = (VALUE)str_new_copy_of_part(RSTR(str), beg, len);
-    }
-    OBJ_INFECT(subseq, str);
-    return subseq;
-}
-
-VALUE
-rb_str_substr_with_cache(VALUE str, long beg, long len,
-	character_boundaries_cache_t *cache)
-{
-    if (!IS_RSTR(str)) {
-	str = (VALUE)str_need_string(str);
-    }
-    return rstr_substr_with_cache(str, beg, len, cache);
-}
-
-VALUE
-rb_str_substr(VALUE str, long beg, long len)
-{
-    return rb_str_substr_with_cache(str, beg, len, NULL);
-}
-
-void
-rb_str_update(VALUE str, long beg, long len, VALUE val)
-{
-    if (IS_RSTR(str)) {
-	rstr_splice(str, beg, len, val);
-    }
-    else {
-	CFStringReplace((CFMutableStringRef)str, CFRangeMake(beg, len),
-		(CFStringRef)val);
-    }
-}
-
-void
-rb_str_delete(VALUE str, long beg, long len)
-{
-    if (IS_RSTR(str)) {
-	str_delete(RSTR(str), beg, len);
-    }
-    else {
-	CFStringDelete((CFMutableStringRef)str, CFRangeMake(beg, len));
-    }
-}
-
-int
-rb_str_cmp(VALUE str1, VALUE str2)
-{
-    return str_compare(str_need_string(str1), str_need_string(str2));
-}
-
-int
-rb_str_casecmp(VALUE str1, VALUE str2)
-{
-    return str_case_compare(str_need_string(str1), str_need_string(str2));
-}
-
-VALUE
-rb_enc_associate(VALUE str, rb_encoding *enc)
-{
-    if (!IS_RSTR(str)) {
-	rb_raise(rb_eArgError, "cannot change the encoding of an NSString");
-    }
-    assert(enc != NULL);
-    RSTR(str)->encoding = enc;
-    return str;
-}
-
-VALUE
-rb_str_export_to_enc(VALUE str, rb_encoding *enc)
-{
-    if (!IS_RSTR(str)) {
-	rb_raise(rb_eArgError, "cannot transcode NSString");
-    }
-    return (VALUE)str_simple_transcode(RSTR(str), enc);
-}
-
-VALUE
-rb_str_split(VALUE str, const char *sep0)
-{
-    str = (VALUE)str_need_string(str);
-    VALUE sep = rb_str_new2(sep0);
-    return rstr_split(str, 0, 1, &sep);
-}
-
-void
-rb_str_modify(VALUE obj)
-{
-    if (IS_RSTR(obj)) {
-	rstr_modify(obj);
-    }
-    else {
-	rb_raise(rb_eArgError, "can't modify NSString");
-    }
-}
-
-VALUE
-rb_str_plus(VALUE str1, VALUE str2)
-{
-    str1 = (VALUE)str_need_string(str1);
-    return rstr_plus(str1, 0, str2);
-}
-
-VALUE
-rstr_new_path(const char *path)
-{
-    // XXX this should be rewritten using ICU (utrans.h?) to avoid creating
-    // these 2 temporary CFStrings.
-    CFStringRef tmp = CFStringCreateWithFileSystemRepresentation(NULL, path); 
-    assert(tmp != NULL);
-
-    CFMutableStringRef tmp2 = CFStringCreateMutableCopy(NULL, 0, tmp); 
-    assert(tmp2 != NULL); 
-    CFRelease(tmp); 
-    CFStringNormalize(tmp2, kCFStringNormalizationFormC); 
-
-    rb_str_t *str = str_new_from_cfstring(tmp2);
-    CFRelease(tmp2);
- 
-    return (VALUE)str;
-}

Deleted: MacRuby/trunk/struct.c
===================================================================
--- MacRuby/trunk/struct.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/struct.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,975 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "class.h"
-
-VALUE rb_cStruct;
-
-static VALUE struct_alloc(VALUE);
-
-VALUE
-rb_struct_iv_get(VALUE c, const char *name)
-{
-    ID id;
-
-    id = rb_intern(name);
-    for (;;) {
-	if (rb_ivar_defined(c, id))
-	    return rb_ivar_get(c, id);
-	c = RCLASS_SUPER(c);
-	if (c == 0 || c == rb_cStruct)
-	    return Qnil;
-    }
-}
-
-VALUE
-rb_struct_s_members(VALUE klass)
-{
-    VALUE members = rb_struct_iv_get(klass, "__members__");
-
-    if (NIL_P(members)) {
-	rb_raise(rb_eTypeError, "uninitialized struct");
-    }
-    if (TYPE(members) != T_ARRAY) {
-	rb_raise(rb_eTypeError, "corrupted struct");
-    }
-    return members;
-}
-
-VALUE
-rb_struct_members(VALUE s)
-{
-    VALUE members = rb_struct_s_members(rb_obj_class(s));
-
-    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
-	rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-		 RARRAY_LEN(members), RSTRUCT_LEN(s));
-    }
-    return members;
-}
-
-static VALUE
-rb_struct_s_members_m(VALUE klass)
-{
-#if WITH_OBJC
-    return rb_ary_dup(rb_struct_s_members(klass));
-#else
-    VALUE members, ary;
-    VALUE *p, *pend;
-
-    members = rb_struct_s_members(klass);
-    ary = rb_ary_new2(RARRAY_LEN(members));
-    p = RARRAY_PTR(members); pend = p + RARRAY_LEN(members);
-    while (p < pend) {
-	rb_ary_push(ary, *p);
-	p++;
-    }
-
-    return ary;
-#endif
-}
-
-/*
- *  call-seq:
- *     struct.members    => array
- *  
- *  Returns an array of strings representing the names of the instance
- *  variables.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joe.members   #=> [:name, :address, :zip]
- */
-
-static VALUE
-rb_struct_members_m(VALUE obj, SEL sel)
-{
-    return rb_struct_s_members_m(rb_obj_class(obj));
-}
-
-VALUE
-rb_struct_getmember(VALUE obj, ID id)
-{
-    VALUE members, slot;
-    long i;
-
-    members = rb_struct_members(obj);
-    slot = ID2SYM(id);
-    for (i=0; i<RARRAY_LEN(members); i++) {
-	if (RARRAY_AT(members, i) == slot) {
-	    return RSTRUCT_PTR(obj)[i];
-	}
-    }
-    rb_name_error(id, "%s is not struct member", rb_id2name(id));
-    return Qnil;		/* not reached */
-}
-
-static VALUE
-rb_struct_ref(VALUE obj, SEL sel)
-{
-    return rb_struct_getmember(obj, rb_frame_this_func());
-}
-
-static VALUE rb_struct_ref0(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[0];}
-static VALUE rb_struct_ref1(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[1];}
-static VALUE rb_struct_ref2(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[2];}
-static VALUE rb_struct_ref3(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[3];}
-static VALUE rb_struct_ref4(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[4];}
-static VALUE rb_struct_ref5(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[5];}
-static VALUE rb_struct_ref6(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[6];}
-static VALUE rb_struct_ref7(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[7];}
-static VALUE rb_struct_ref8(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[8];}
-static VALUE rb_struct_ref9(VALUE obj, SEL sel) {return RSTRUCT_PTR(obj)[9];}
-
-#define N_REF_FUNC (sizeof(ref_func) / sizeof(ref_func[0]))
-
-static VALUE (*const ref_func[])(VALUE,SEL) = {
-    rb_struct_ref0,
-    rb_struct_ref1,
-    rb_struct_ref2,
-    rb_struct_ref3,
-    rb_struct_ref4,
-    rb_struct_ref5,
-    rb_struct_ref6,
-    rb_struct_ref7,
-    rb_struct_ref8,
-    rb_struct_ref9,
-};
-
-static void
-rb_struct_modify(VALUE s)
-{
-    if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
-    if (!OBJ_TAINTED(s) && rb_safe_level() >= 4)
-       rb_raise(rb_eSecurityError, "Insecure: can't modify Struct");
-}
-
-static VALUE
-rb_struct_set(VALUE obj, SEL sel, VALUE val)
-{
-    VALUE members, slot;
-    long i;
-
-    // foo=: -> foo
-    char buf[100];
-    const size_t s = strlcpy(buf, sel_getName(sel), sizeof buf);
-    buf[s - 2] = '\0';
-    ID field = rb_intern(buf);
-
-    members = rb_struct_members(obj);
-    rb_struct_modify(obj);
-    for (i=0; i<RARRAY_LEN(members); i++) {
-	slot = RARRAY_AT(members, i);
-	if (SYM2ID(slot) == field) {
-	    GC_WB(&RSTRUCT_PTR(obj)[i], val);
-	    return val;
-	}
-    }
-    rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
-		  rb_id2name(field));
-    return Qnil;		/* not reached */
-}
-
-static VALUE
-make_struct(VALUE name, VALUE members, VALUE klass)
-{
-    VALUE nstr;
-    ID id;
-    long i, count;
-
-    OBJ_FREEZE(members);
-    if (NIL_P(name)) {
-	nstr = rb_class_new(klass);
-#if !WITH_OBJC
-	rb_make_metaclass(nstr, RBASIC(klass)->klass);
-#endif
-	rb_class_inherited(klass, nstr);
-    }
-    else {
-	/* old style: should we warn? */
-	name = rb_str_to_str(name);
-	id = rb_to_id(name);
-	if (!rb_is_const_id(id)) {
-	    rb_name_error(id, "identifier %s needs to be constant",
-		    StringValuePtr(name));
-	}
-	if (rb_const_defined_at(klass, id)) {
-	    rb_warn("redefining constant Struct::%s", StringValuePtr(name));
-	    rb_mod_remove_const(klass, ID2SYM(id));
-	}
-	nstr = rb_define_class_under(klass, rb_id2name(id), klass);
-    }
-    rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY_LEN(members)));
-    rb_iv_set(nstr, "__members__", members);
-
-    rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0);
-    rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1);
-    rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1);
-    rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0);
-    for (i = 0, count = RARRAY_LEN(members); i < count; i++) {
-	ID id = SYM2ID(RARRAY_AT(members, i));
-	if (rb_is_local_id(id) || rb_is_const_id(id)) {
-	    if (i < N_REF_FUNC) {
-		rb_objc_define_method(nstr, rb_id2name(id), ref_func[i], 0);
-	    }
-	    else {
-		rb_objc_define_method(nstr, rb_id2name(id), rb_struct_ref, 0);
-	    }
-	    rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)),
-		    rb_struct_set, 1);
-	}
-    }
-
-    return nstr;
-}
-
-VALUE
-rb_struct_alloc_noinit(VALUE klass)
-{
-    return struct_alloc(klass);
-}
-
-VALUE
-rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
-{
-    VALUE klass;
-    va_list ar;
-    VALUE members;
-    long i;
-    char *name;
-
-    members = rb_ary_new2(0);
-    va_start(ar, alloc);
-    i = 0;
-    while ((name = va_arg(ar, char*)) != NULL) {
-        rb_ary_push(members, ID2SYM(rb_intern(name)));
-    }
-    va_end(ar);
-    OBJ_FREEZE(members);
-
-    if (class_name) {
-        klass = rb_define_class(class_name, super);
-    }
-    else {
-	klass = rb_class_new(super);
-	rb_make_metaclass(klass, RBASIC(super)->klass);
-	rb_class_inherited(super, klass);
-    }
-
-    rb_iv_set(klass, "__size__", LONG2NUM(RARRAY_LEN(members)));
-    rb_iv_set(klass, "__members__", members);
-
-    rb_objc_define_method(*(VALUE *)klass, "alloc",
-	    alloc != NULL ? alloc : struct_alloc,
-	    0);
-
-    return klass;
-}
-
-VALUE
-rb_struct_define(const char *name, ...)
-{
-    va_list ar;
-    VALUE nm, ary;
-    char *mem;
-
-    if (!name) nm = Qnil;
-    else nm = rb_str_new2(name);
-    ary = rb_ary_new();
-
-    va_start(ar, name);
-    while ((mem = va_arg(ar, char*)) != 0) {
-	ID slot = rb_intern(mem);
-	rb_ary_push(ary, ID2SYM(slot));
-    }
-    va_end(ar);
-
-    return make_struct(nm, ary, rb_cStruct);
-}
-
-/*
- *  call-seq:
- *     Struct.new( [aString] [, aSym]+> )    => StructClass
- *     StructClass.new(arg, ...)             => obj
- *     StructClass[arg, ...]                 => obj
- *
- *  Creates a new class, named by <i>aString</i>, containing accessor
- *  methods for the given symbols. If the name <i>aString</i> is
- *  omitted, an anonymous structure class will be created. Otherwise,
- *  the name of this struct will appear as a constant in class
- *  <code>Struct</code>, so it must be unique for all
- *  <code>Struct</code>s in the system and should start with a capital
- *  letter. Assigning a structure class to a constant effectively gives
- *  the class the name of the constant.
- *     
- *  <code>Struct::new</code> returns a new <code>Class</code> object,
- *  which can then be used to create specific instances of the new
- *  structure. The number of actual parameters must be
- *  less than or equal to the number of attributes defined for this
- *  class; unset parameters default to \nil{}.  Passing too many
- *  parameters will raise an \E{ArgumentError}.
- *
- *  The remaining methods listed in this section (class and instance)
- *  are defined for this generated class. 
- *     
- *     # Create a structure with a name in Struct
- *     Struct.new("Customer", :name, :address)    #=> Struct::Customer
- *     Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">
- *     
- *     # Create a structure named by its constant
- *     Customer = Struct.new(:name, :address)     #=> Customer
- *     Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">
- */
-
-VALUE rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv);
-
-static VALUE
-rb_struct_s_def(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE name, rest;
-    long i, count;
-    VALUE st;
-    ID id;
-
-    rb_scan_args(argc, argv, "1*", &name, &rest);
-    if (!NIL_P(name) && SYMBOL_P(name)) {
-	rb_ary_unshift(rest, name);
-	name = Qnil;
-    }
-    for (i = 0, count = RARRAY_LEN(rest); i < count; i++) {
-	id = rb_to_id(RARRAY_AT(rest, i));
-	rb_ary_store(rest, i, ID2SYM(id));
-    }
-    st = make_struct(name, rest, klass);
-    if (rb_block_given_p()) {
-	rb_mod_module_eval(st, 0, 0, 0);
-    }
-
-    return st;
-}
-
-/*
- */
-
-VALUE
-rb_struct_initialize(VALUE self, SEL sel, VALUE values)
-{
-    VALUE klass = rb_obj_class(self);
-    VALUE size;
-    long n;
-
-    rb_struct_modify(self);
-    size = rb_struct_iv_get(klass, "__size__");
-    n = FIX2LONG(size);
-    if (n < RARRAY_LEN(values)) {
-	rb_raise(rb_eArgError, "struct size differs");
-    }
-    for (int i = 0; i < RARRAY_LEN(values); i++) {
-	GC_WB(&RSTRUCT_PTR(self)[i], RARRAY_AT(values, i));
-    }
-    if (n > RARRAY_LEN(values)) {
-	for (int i = RARRAY_LEN(values); i < n; i++) {
-	    RSTRUCT_PTR(self)[i] = Qnil;
-	}
-    }
-    return Qnil;
-}
-
-static VALUE
-struct_alloc(VALUE klass)
-{
-    VALUE size;
-    long n;
-    NEWOBJ(st, struct RStruct);
-    OBJSETUP(st, klass, T_STRUCT);
-
-    size = rb_struct_iv_get(klass, "__size__");
-    n = FIX2LONG(size);
-
-    if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
-        RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
-        RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
-	rb_mem_clear(st->as.ary, n);
-    }
-    else {
-	if (n > 0) {
-	    GC_WB(&st->as.heap.ptr, xmalloc_ptrs(sizeof(VALUE) * n));
-	    rb_mem_clear(st->as.heap.ptr, n);
-	}
-	else {
-	    st->as.heap.ptr = NULL;
-	}
-	st->as.heap.len = n;
-    }
-
-    return (VALUE)st;
-}
-
-VALUE
-rb_struct_alloc(VALUE klass, VALUE values)
-{
-    return rb_class_new_instance(RARRAY_LEN(values), (VALUE *)RARRAY_PTR(values), klass);
-}
-
-VALUE
-rb_struct_new(VALUE klass, ...)
-{
-    VALUE sz, *mem;
-    long size, i;
-    va_list args;
-
-    sz = rb_struct_iv_get(klass, "__size__");
-    size = FIX2LONG(sz); 
-    mem = ALLOCA_N(VALUE, size);
-    va_start(args, klass);
-    for (i=0; i<size; i++) {
-	mem[i] = va_arg(args, VALUE);
-    }
-    va_end(args);
-
-    return rb_class_new_instance(size, mem, klass);
-}
-
-/*
- *  call-seq:
- *     struct.each {|obj| block }  => struct
- *  
- *  Calls <i>block</i> once for each instance variable, passing the
- *  value as a parameter.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joe.each {|x| puts(x) }
- *     
- *  <em>produces:</em>
- *     
- *     Joe Smith
- *     123 Maple, Anytown NC
- *     12345
- */
-
-static VALUE
-rb_struct_each(VALUE s, SEL sel)
-{
-    long i;
-
-    RETURN_ENUMERATOR(s, 0, 0);
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
-	rb_yield(RSTRUCT_PTR(s)[i]);
-	RETURN_IF_BROKEN();
-    }
-    return s;
-}
-
-/*
- *  call-seq:
- *     struct.each_pair {|sym, obj| block }     => struct
- *  
- *  Calls <i>block</i> once for each instance variable, passing the name
- *  (as a symbol) and the value as parameters.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joe.each_pair {|name, value| puts("#{name} => #{value}") }
- *     
- *  <em>produces:</em>
- *     
- *     name => Joe Smith
- *     address => 123 Maple, Anytown NC
- *     zip => 12345
- */
-
-static VALUE
-rb_struct_each_pair(VALUE s, SEL sel)
-{
-    VALUE members;
-    long i;
-
-    RETURN_ENUMERATOR(s, 0, 0);
-    members = rb_struct_members(s);
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
-	rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
-	RETURN_IF_BROKEN();
-    }
-    return s;
-}
-
-static VALUE
-inspect_struct(VALUE s, VALUE dummy, int recur)
-{
-    const char *cname = rb_class2name(rb_obj_class(s));
-    VALUE str, members;
-    long i;
-
-    if (recur) {
-	return rb_sprintf("#<struct %s:...>", cname);
-    }
-
-    members = rb_struct_members(s);
-    if (cname[0] == '#') {
-	str = rb_str_new2("#<struct ");
-    }
-    else {
-	str = rb_sprintf("#<struct %s ", cname);
-    }
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
-	VALUE slot;
-	ID id;
-
-	if (i > 0) {
-	    rb_str_cat2(str, ", ");
-	}
-	slot = RARRAY_AT(members, i);
-	id = SYM2ID(slot);
-	if (rb_is_local_id(id) || rb_is_const_id(id)) {
-	    rb_str_buf_append(str, rb_id2str(id));
-	}
-	else {
-	    rb_str_buf_append(str, rb_inspect(slot));
-	}
-	rb_str_cat2(str, "=");
-	rb_str_buf_append(str, rb_inspect(RSTRUCT_PTR(s)[i]));
-    }
-    rb_str_cat2(str, ">");
-    OBJ_INFECT(str, s);
-
-    return str;
-}
-
-/*
- * call-seq:
- *   struct.to_s      => string
- *   struct.inspect   => string
- *
- * Describe the contents of this struct in a string.
- */
-
-static VALUE
-rb_struct_inspect(VALUE s, SEL sel)
-{
-    return rb_exec_recursive(inspect_struct, s, 0);
-}
-
-/*
- *  call-seq:
- *     struct.to_a     => array
- *     struct.values   => array
- *  
- *  Returns the values for this instance as an array.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joe.to_a[1]   #=> "123 Maple, Anytown NC"
- */
-
-static VALUE
-rb_struct_to_a(VALUE s, SEL sel)
-{
-    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
-}
-
-/* :nodoc: */
-static VALUE
-rb_struct_init_copy(VALUE copy, SEL sel, VALUE s)
-{
-    if (copy == s) return copy;
-    rb_check_frozen(copy);
-    if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) {
-	rb_raise(rb_eTypeError, "wrong argument class");
-    }
-    if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
-	rb_raise(rb_eTypeError, "struct size mismatch");
-    }
-    for (int i = 0; i < RSTRUCT_LEN(copy); i++) {
-	GC_WB(&RSTRUCT_PTR(copy)[i], RSTRUCT_PTR(s)[i]);
-    }
-
-    return copy;
-}
-
-static VALUE
-rb_struct_aref_id(VALUE s, ID id)
-{
-    VALUE members;
-    long i, len;
-
-    members = rb_struct_members(s);
-    len = RARRAY_LEN(members);
-    for (i=0; i<len; i++) {
-	if (SYM2ID(RARRAY_AT(members, i)) == id) {
-	    return RSTRUCT_PTR(s)[i];
-	}
-    }
-    rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
-    return Qnil;		/* not reached */
-}
-
-/*
- *  call-seq:
- *     struct[symbol]    => anObject
- *     struct[fixnum]    => anObject 
- *  
- *  Attribute Reference---Returns the value of the instance variable
- *  named by <i>symbol</i>, or indexed (0..length-1) by
- *  <i>fixnum</i>. Will raise <code>NameError</code> if the named
- *  variable does not exist, or <code>IndexError</code> if the index is
- *  out of range.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     
- *     joe["name"]   #=> "Joe Smith"
- *     joe[:name]    #=> "Joe Smith"
- *     joe[0]        #=> "Joe Smith"
- */
-
-static VALUE
-rb_struct_aref_imp(VALUE s, SEL sel, VALUE idx)
-{
-    long i;
-
-    if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
-	return rb_struct_aref_id(s, rb_to_id(idx));
-    }
-
-    i = NUM2LONG(idx);
-    if (i < 0) i = RSTRUCT_LEN(s) + i;
-    if (i < 0)
-        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
-		 i, RSTRUCT_LEN(s));
-    if (RSTRUCT_LEN(s) <= i)
-        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
-		 i, RSTRUCT_LEN(s));
-    return RSTRUCT_PTR(s)[i];
-}
-
-VALUE
-rb_struct_aref(VALUE s, VALUE idx)
-{
-    return rb_struct_aref_imp(s, 0, idx);
-}
-
-static VALUE
-rb_struct_aset_id(VALUE s, ID id, VALUE val)
-{
-    VALUE members;
-    long i, len;
-
-    members = rb_struct_members(s);
-    rb_struct_modify(s);
-    len = RARRAY_LEN(members);
-    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
-	rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-		 RARRAY_LEN(members), RSTRUCT_LEN(s));
-    }
-    for (i=0; i<len; i++) {
-	if (SYM2ID(RARRAY_AT(members, i)) == id) {
-	    GC_WB(&RSTRUCT_PTR(s)[i], val);
-	    return val;
-	}
-    }
-    rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
-}
-
-/*
- *  call-seq:
- *     struct[symbol] = obj    => obj
- *     struct[fixnum] = obj    => obj
- *  
- *  Attribute Assignment---Assigns to the instance variable named by
- *  <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
- *  returns it. Will raise a <code>NameError</code> if the named
- *  variable does not exist, or an <code>IndexError</code> if the index
- *  is out of range.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     
- *     joe["name"] = "Luke"
- *     joe[:zip]   = "90210"
- *     
- *     joe.name   #=> "Luke"
- *     joe.zip    #=> "90210"
- */
-
-static VALUE
-rb_struct_aset_imp(VALUE s, SEL sel, VALUE idx, VALUE val)
-{
-    long i;
-
-    if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
-	return rb_struct_aset_id(s, rb_to_id(idx), val);
-    }
-
-    i = NUM2LONG(idx);
-    if (i < 0) i = RSTRUCT_LEN(s) + i;
-    if (i < 0) {
-        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
-		 i, RSTRUCT_LEN(s));
-    }
-    if (RSTRUCT_LEN(s) <= i) {
-        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
-		 i, RSTRUCT_LEN(s));
-    }
-    rb_struct_modify(s);
-    GC_WB(&RSTRUCT_PTR(s)[i], val);
-    return val;
-}
-
-VALUE
-rb_struct_aset(VALUE s, VALUE idx, VALUE val)
-{
-    return rb_struct_aset_imp(s, 0, idx, val);
-}
-
-static VALUE
-struct_entry(VALUE s, long n)
-{
-    return rb_struct_aref(s, LONG2NUM(n));
-}
-
-/* 
- * call-seq:
- *   struct.values_at(selector,... )  => an_array
- *
- *   Returns an array containing the elements in
- *   _self_ corresponding to the given selector(s). The selectors
- *   may be either integer indices or ranges. 
- *   See also </code>.select<code>.
- * 
- *      a = %w{ a b c d e f }
- *      a.values_at(1, 3, 5)
- *      a.values_at(1, 3, 5, 7)
- *      a.values_at(-1, -3, -5, -7)
- *      a.values_at(1..3, 2...5)
- */
-
-static VALUE
-rb_struct_values_at(VALUE s, SEL sel, int argc, VALUE *argv)
-{
-    return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
-}
-
-/*
- *  call-seq:
- *     struct.select {|i| block }    => array
- *  
- *  Invokes the block passing in successive elements from
- *  <i>struct</i>, returning an array containing those elements
- *  for which the block returns a true value (equivalent to
- *  <code>Enumerable#select</code>).
- *     
- *     Lots = Struct.new(:a, :b, :c, :d, :e, :f)
- *     l = Lots.new(11, 22, 33, 44, 55, 66)
- *     l.select {|v| (v % 2).zero? }   #=> [22, 44, 66]
- */
-
-static VALUE
-rb_struct_select(VALUE s, SEL sel, int argc, VALUE *argv)
-{
-    VALUE result;
-    long i;
-
-    if (argc > 0) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
-    }
-    result = rb_ary_new();
-    for (i = 0; i < RSTRUCT_LEN(s); i++) {
-	VALUE v = rb_yield(RSTRUCT_PTR(s)[i]);
-	RETURN_IF_BROKEN();
-	if (RTEST(v)) {
-	    rb_ary_push(result, RSTRUCT_PTR(s)[i]);
-	}
-    }
-
-    return result;
-}
-
-/*
- *  call-seq:
- *     struct == other_struct     => true or false
- *  
- *  Equality---Returns <code>true</code> if <i>other_struct</i> is
- *  equal to this one: they must be of the same class as generated by
- *  <code>Struct::new</code>, and the values of all instance variables
- *  must be equal (according to <code>Object#==</code>).
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe   = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     jane  = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
- *     joe == joejr   #=> true
- *     joe == jane    #=> false
- */
-
-static VALUE
-rb_struct_equal_r(VALUE s, VALUE s2, int recur)
-{
-    if (recur) {
-	return Qtrue;
-    }
-    for (int i = 0; i < RSTRUCT_LEN(s); i++) {
-	if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) {
-	    return Qfalse;
-	}
-    }
-    return Qtrue;
-}
-
-static VALUE
-rb_struct_equal(VALUE s, SEL sel, VALUE s2)
-{
-    if (s == s2) {
-	return Qtrue;
-    }
-    if (TYPE(s2) != T_STRUCT) {
-	return Qfalse;
-    }
-    if (rb_obj_class(s) != rb_obj_class(s2)) {
-	return Qfalse;
-    }
-    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
-	rb_bug("inconsistent struct"); /* should never happen */
-    }
-    return rb_exec_recursive(rb_struct_equal_r, s, s2);
-}
-
-/*
- * call-seq:
- *   struct.hash   => fixnum
- *
- * Return a hash value based on this struct's contents.
- */
-
-static VALUE
-rb_struct_hash_r(VALUE s, VALUE s2, int recur)
-{
-    long h = rb_hash(rb_obj_class(s));
-    if (!recur) {
-	for (long i = 0; i < RSTRUCT_LEN(s); i++) {
-	    h = (h << 1) | (h < 0 ? 1 : 0);
-	    VALUE n = rb_hash(RSTRUCT_PTR(s)[i]);
-	    h ^= NUM2LONG(n);
-	}
-    }
-    return LONG2FIX(h);
-}
-
-static VALUE
-rb_struct_hash(VALUE s, SEL sel)
-{
-    return rb_exec_recursive(rb_struct_hash_r, s, Qnil);
-}
-
-/*
- * code-seq:
- *   struct.eql?(other)   => true or false
- *
- * Two structures are equal if they are the same object, or if all their
- * fields are equal (using <code>eql?</code>).
- */
-
-static VALUE
-rb_struct_eql_r(VALUE s, VALUE s2, int recur)
-{
-    if (recur) {
-	return Qtrue;
-    }
-    for (int i = 0; i < RSTRUCT_LEN(s); i++) {
-	if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) {
-	    return Qfalse;
-	}
-    }
-    return Qtrue;
-}
-
-static VALUE
-rb_struct_eql(VALUE s, SEL sel, VALUE s2)
-{
-    if (s == s2) {
-	return Qtrue;
-    }
-    if (TYPE(s2) != T_STRUCT) {
-	return Qfalse;
-    }
-    if (rb_obj_class(s) != rb_obj_class(s2)) {
-	return Qfalse;
-    }
-    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
-	rb_bug("inconsistent struct"); /* should never happen */
-    }
-    return rb_exec_recursive(rb_struct_eql_r, s, s2);
-}
-
-/*
- *  call-seq:
- *     struct.length    => fixnum
- *     struct.size      => fixnum
- *  
- *  Returns the number of instance variables.
- *     
- *     Customer = Struct.new(:name, :address, :zip)
- *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *     joe.length   #=> 3
- */
-
-static VALUE
-rb_struct_size(VALUE s, SEL sel)
-{
-    return LONG2FIX(RSTRUCT_LEN(s));
-}
-
-/*
- *  A <code>Struct</code> is a convenient way to bundle a number of
- *  attributes together, using accessor methods, without having to write
- *  an explicit class.
- *     
- *  The <code>Struct</code> class is a generator of specific classes,
- *  each one of which is defined to hold a set of variables and their
- *  accessors. In these examples, we'll call the generated class
- *  ``<i>Customer</i>Class,'' and we'll show an example instance of that
- *  class as ``<i>Customer</i>Inst.''
- *     
- *  In the descriptions that follow, the parameter <i>symbol</i> refers
- *  to a symbol, which is either a quoted string or a
- *  <code>Symbol</code> (such as <code>:name</code>).
- */
-void
-Init_Struct(void)
-{
-    rb_cStruct = rb_define_class("Struct", rb_cObject);
-    rb_include_module(rb_cStruct, rb_mEnumerable);
-
-    rb_undef_alloc_func(rb_cStruct);
-    rb_objc_define_method(*(VALUE *)rb_cStruct, "new", rb_struct_s_def, -1);
-
-    rb_objc_define_method(rb_cStruct, "initialize", rb_struct_initialize, -2);
-    rb_objc_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
-
-    rb_objc_define_method(rb_cStruct, "==", rb_struct_equal, 1);
-    rb_objc_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
-    rb_objc_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
-
-    rb_objc_define_method(rb_cStruct, "to_s", rb_struct_inspect, 0);
-    rb_objc_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
-    rb_objc_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
-    rb_objc_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
-    rb_objc_define_method(rb_cStruct, "size", rb_struct_size, 0);
-    rb_objc_define_method(rb_cStruct, "length", rb_struct_size, 0);
-
-    rb_objc_define_method(rb_cStruct, "each", rb_struct_each, 0);
-    rb_objc_define_method(rb_cStruct, "each_pair", rb_struct_each_pair, 0);
-    rb_objc_define_method(rb_cStruct, "[]", rb_struct_aref_imp, 1);
-    rb_objc_define_method(rb_cStruct, "[]=", rb_struct_aset_imp, 2);
-    rb_objc_define_method(rb_cStruct, "select", rb_struct_select, -1);
-    rb_objc_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
-
-    rb_objc_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
-}

Deleted: MacRuby/trunk/symbol.c
===================================================================
--- MacRuby/trunk/symbol.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/symbol.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,842 +0,0 @@
-/* 
- * MacRuby Symbols.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#include <wctype.h>
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "symbol.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "objc.h"
-
-VALUE rb_cSymbol;
-
-static CFMutableDictionaryRef sym_id = NULL, id_str = NULL;
-static long last_id = 0;
-
-typedef struct {
-    VALUE klass;
-    VALUE str;
-    ID id;
-} rb_sym_t;
-
-#define RSYM(obj) ((rb_sym_t *)(obj))
-
-static rb_sym_t *
-sym_alloc(VALUE str, ID id)
-{
-    rb_sym_t *sym = (rb_sym_t *)xmalloc(sizeof(rb_sym_t));
-    assert(rb_cSymbol != 0);
-    sym->klass = rb_cSymbol;
-    GC_WB(&sym->str, str);
-    sym->id = id;
-    return sym;
-}
-
-static bool
-is_identchar(UChar c)
-{
-    return isalnum(c) || c == '_' || !isascii(c);
-}
-
-ID
-rb_intern_str(VALUE str)
-{
-    RB_STR_GET_UCHARS(str, chars, chars_len);
-
-    const unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
-    ID id = (ID)CFDictionaryGetValue(sym_id, (const void *)name_hash); 
-    if (id != 0) {
-	goto return_id;
-    } 
-
-    rb_sym_t *sym = NULL;
-    long pos = 0;
-    if (chars_len > 0) {
-	UChar c = chars[0];
-	switch (c) {
-	    case '$':
-		id = ID_GLOBAL;
-		goto new_id;
-
-	    case '@':
-		if (chars_len > 1 && chars[1] == '@') {
-		    pos++;
-		    id = ID_CLASS;
-		}
-		else {
-		    id = ID_INSTANCE;
-		}
-		pos++;
-		break;
-
-	    default:
-		if (chars_len > 1 && chars[chars_len - 1] == '=') {
-		    // Attribute assignment.
-		    id = rb_intern_str(rb_str_substr(str, 0, chars_len - 1));
-		    if (!is_attrset_id(id)) {
-			id = rb_id_attrset(id);
-			goto id_register;
-		    }
-		    id = ID_ATTRSET;
-		}
-		else if (iswupper(c)) {
-		    id = ID_CONST;
-		}
-		else {
-		    id = ID_LOCAL;
-		}
-		break;
-	}
-    }
-
-    if (pos < chars_len && !isdigit(chars[pos])) {
-	for (; pos < chars_len; pos++) {
-	    if (!is_identchar(chars[pos])) {
-		break;
-	    }
-	}
-    }
-    if (pos < chars_len) {
-	id = ID_JUNK;
-    }
-
-new_id:
-    id |= ++last_id << ID_SCOPE_SHIFT;
-
-id_register:
-//printf("register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
-    sym = sym_alloc(str, id);
-    CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
-    CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
-
-return_id:
-    return id;
-}
-
-VALUE
-rb_id2str(ID id)
-{
-    VALUE sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
-    if (sym != 0) {
-//printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
-	return sym;
-    }
-
-    if (is_attrset_id(id)) {
-	// Attribute assignment.
-	ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
-
-	while ((sym = rb_id2str(id2)) == 0) {
-	    if (!is_local_id(id2)) {
-//printf("lookup %ld -> FAIL\n", id);
-		return 0;
-	    }
-	    id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
-	}
-
-	VALUE str = rb_str_dup(RSYM(sym)->str);
-	rb_str_cat(str, "=", 1);
-	rb_intern_str(str);
-
-	// Retry one more time.
-	sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
-	if (sym != 0) {
-//printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
-	    return sym;
-	}
-    }
-//printf("lookup %ld -> FAIL\n", id);
-    return 0;
-}
-
-ID
-rb_intern3(const char *name, long len, rb_encoding *enc)
-{
-    VALUE str = rb_enc_str_new(name, len, enc);
-    return rb_intern_str(str);
-}
-
-ID
-rb_intern2(const char *name, long len)
-{
-    return rb_intern_str(rb_str_new(name, len));
-}
-
-ID
-rb_intern(const char *name)
-{
-    return rb_intern_str(rb_str_new2(name));
-}
-
-ID
-rb_sym2id(VALUE sym)
-{
-    return RSYM(sym)->id;
-}
-
-VALUE
-rb_name2sym(const char *name)
-{
-    return rb_id2str(rb_intern(name));
-}
-
-VALUE
-rb_sym_to_s(VALUE sym)
-{
-    return rb_str_dup(RSYM(sym)->str);
-}
-
-const char *
-rb_sym2name(VALUE sym)
-{
-    return RSTRING_PTR(RSYM(sym)->str);
-}
-
-/*
- *  call-seq:
- *     Symbol.all_symbols    => array
- *
- *  Returns an array of all the symbols currently in Ruby's symbol
- *  table.
- *
- *     Symbol.all_symbols.size    #=> 903
- *     Symbol.all_symbols[1,20]   #=> [:floor, :ARGV, :Binding, :symlink,
- *                                     :chown, :EOFError, :$;, :String,
- *                                     :LOCK_SH, :"setuid?", :$<,
- *                                     :default_proc, :compact, :extend,
- *                                     :Tms, :getwd, :$=, :ThreadGroup,
- *                                     :wait2, :$>]
- */
-
-static VALUE
-rsym_all_symbols(VALUE klass, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    const long count = CFDictionaryGetCount(id_str);
-    if (count >= 0) {
-	const void **values = (const void **)malloc(sizeof(void *) * count);
-	CFDictionaryGetKeysAndValues(id_str, NULL, values);
-	for (long i = 0; i < count; i++) {
-	    rb_ary_push(ary, (VALUE)values[i]);
-	}
-	free(values);
-    }
-    return ary;
-}
-
-#if MACRUBY_STATIC
-struct rb_op_tbl_entry rb_op_tbl[] = {
-    {'+', "+"},
-    {'-', "-"},
-    {'*', "*"},
-    {'/', "/"},
-    {'%', "%"},
-    {'|', "|"},
-    {'^', "^"},
-    {'&', "&"},
-    {'!', "!"},
-    {'>', ">"},
-    {'<', "<"},
-    {'~', "~"},
-    {'!', "!"},
-    {'`', "`"},
-    {334, ".."},
-    {335, "..."},
-    {323, "**"},
-    {321, "+@"},
-    {322, "-@"},
-    {324, "<=>"},
-    {328, ">="},
-    {329, "<="},
-    {325, "=="},
-    {326, "==="},
-    {327, "!="},
-    {332, "=~"},
-    {333, "!~"},
-    {336, "[]"},
-    {337, "[]="},
-    {338, "<<"},
-    {339, ">>"},
-    {340, "::"},
-    {0,   NULL}
-};
-#endif
-
-void
-Init_PreSymbol(void)
-{
-    sym_id = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-    id_str = CFDictionaryCreateMutable(NULL, 0, NULL,
-	    &kCFTypeDictionaryValueCallBacks);
-    last_id = 1000;
-
-    // Pre-register parser symbols.
-    for (int i = 0; rb_op_tbl[i].token != 0; i++) {
-	ID id = rb_op_tbl[i].token;
-	VALUE str = rb_str_new2(rb_op_tbl[i].name);
-	rb_sym_t *sym = sym_alloc(str, id);
-	unsigned long name_hash = rb_str_hash(str);
-
-//printf("pre-register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
-
-	CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
-	CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
-    }
-}
-
-/*
- * call-seq:
- *
- *   str <=> other       => -1, 0, +1 or nil
- *
- * Compares _sym_ with _other_ in string form.
- */
-
-static VALUE
-rsym_cmp(VALUE sym, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_SYMBOL) {
-	return Qnil;
-    }
-    return INT2FIX(rb_str_cmp(RSYM(sym)->str, RSYM(other)->str));
-}
-
-/*
- * call-seq:
- *
- *   sym.casecmp(other)  => -1, 0, +1 or nil
- *
- * Case-insensitive version of <code>Symbol#<=></code>.
- */
-
-static VALUE
-rsym_casecmp(VALUE sym, SEL sel, VALUE other)
-{
-    if (TYPE(other) != T_SYMBOL) {
-	return Qnil;
-    }
-    return INT2FIX(rb_str_casecmp(RSYM(sym)->str, RSYM(other)->str));
-}
-
-/*
- *  call-seq:
- *     sym == obj   => true or false
- *  
- *  Equality---If <i>sym</i> and <i>obj</i> are exactly the same
- *  symbol, returns <code>true</code>. Otherwise, compares them
- *  as strings.
- */
-
-static VALUE
-rsym_equal(VALUE sym, SEL sel, VALUE other)
-{
-    return sym == other ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     sym.inspect    => string
- *  
- *  Returns the representation of <i>sym</i> as a symbol literal.
- *     
- *     :fred.inspect   #=> ":fred"
- */
-
-static bool
-is_special_global_name(UChar *ptr, long len)
-{
-    if (len <= 0) {
-	return false;
-    }
-
-    long pos = 0;
-    switch (ptr[pos]) {
-	case '~': case '*': case '$': case '?': case '!':
-	case '@': case '/': case '\\': case ';': case ',':
-	case '.': case '=': case ':': case '<': case '>': 
-	case '\"': case '&': case '`': case '\'': case '+': case '0':
-	    pos++;
-	    break;
-
-	case '-':
-	    pos++;
-	    if (pos < len && is_identchar(ptr[pos])) {
-		pos++;
-	    }
-	    break;
-
-	default:
-	    if (!isdigit(ptr[pos])) {
-		return false;
-	    }
-	    do {
-		pos++;
-	    }
-	    while (pos < len && isdigit(ptr[pos]));
-	    break;
-    }
-    return pos == len;
-}
-
-static bool
-sym_should_be_escaped(VALUE sym)
-{
-    RB_STR_GET_UCHARS(RSYM(sym)->str, chars, chars_len);
-
-    if (chars_len == 0) {
-	return true;
-    }
-
-    bool escape = false;
-    for (long i = 0; i < chars_len; i++) {
-	if (!isprint(chars[i])) {
-	    escape = true;
-	    break;
-	}
-    }
-
-    if (escape) {
-	goto bail;
-    }
-
-    long pos = 0;
-    bool localid = false;
-
-    switch (chars[pos]) {
-	case '\0':
-	    escape = true;
-	    break;
-
-	case '$':
-	    pos++;
-	    if (pos < chars_len && is_special_global_name(&chars[pos],
-			chars_len - pos)) {
-		goto bail;
-	    }
-	    goto id;
-
-	case '@':
-	    pos++;
-	    if (pos < chars_len && chars[pos] == '@') {
-		pos++;
-	    }
-	    goto id;
-
-	case '<':
-	    pos++;
-	    if (pos < chars_len) {
-		if (chars[pos] == '<') {
-		    pos++;
-		}
-		else if (chars[pos] == '=') {
-		    pos++;
-		    if (pos < chars_len && chars[pos] == '>') {
-			pos++;
-		    }
-		}
-	    }
-	    break;
-
-	case '>':
-	    pos++;
-	    if (pos < chars_len) {
-		if (chars[pos] == '>' || chars[pos] == '=') {
-		    pos++;
-		}
-	    }
-	    break;
-
-	case '=':
-	    pos++;
-	    if (pos == chars_len) {
-		escape = true;
-		goto bail;
-	    }
-	    else {
-		if (chars[pos] == '~') {
-		    pos++;
-		}
-		else if (chars[pos] == '=') {
-		    pos++;
-		    if (pos < chars_len && chars[pos] == '=') {
-			pos++;
-		    }
-		}
-		else {
-		    escape = true;
-		    goto bail;
-		}
-	    }
-	    break;
-
-	case '*':
-	    pos++;
-	    if (pos < chars_len && chars[pos] == '*') {
-		pos++;
-	    }
-	    break;
-
-	case '+':
-	case '-':
-	    pos++;
-	    if (pos < chars_len && chars[pos] == '@') {
-		pos++;
-	    }
-	    break;
-
-	case '|': case '^': case '&': case '/':
-	case '%': case '~': case '`':
-	    pos++;
-	    break;
-
-	case '[':
-	    pos++;
-	    if (pos < chars_len && chars[pos] != ']') {
-		escape = true;
-		goto bail;
-	    }
-	    pos++;
-	    if (pos < chars_len && chars[pos] == '=') {
-		pos++;
-	    }
-	    break;
-
-	case '!':
-	    pos++;
-	    if (pos == chars_len) {
-		goto bail;
-	    }
-	    else {
-		if (chars[pos] == '=' || chars[pos] == '~') {
-		    pos++;
-		}
-		else {
-		    escape = true;
-		    goto bail;
-		}
-	    }
-	    break;
-
-	default:
-	    localid = !isupper(chars[pos]);
-	    // fall through	
-
-	id:
-	    if (pos >= chars_len
-		    || (chars[pos] != '_' && !isalpha(chars[pos])
-			&& isascii(chars[pos]))) {
-		escape = true;
-		goto bail;
-	    }
-	    while (pos < chars_len && is_identchar(chars[pos])) {
-		pos++;
-	    }
-	    if (localid) {
-		if (pos < chars_len
-			&& (chars[pos] == '!' || chars[pos] == '?'
-			    || chars[pos] == '=')) {
-		    pos++;
-		}
-	    }
-	    break;
-    }
-
-    if (pos < chars_len) {
-	escape = true;
-    }
-
-bail:
-    return escape;
-}
-
-static VALUE
-rsym_inspect(VALUE sym, SEL sel)
-{
-    VALUE str = rb_str_new2(":");
-    if (sym_should_be_escaped(sym)) {
-	rb_str_concat(str, rb_str_inspect(RSYM(sym)->str));
-    }
-    else {
-	rb_str_concat(str, RSYM(sym)->str);
-    }
-    return str;
-}
-
-/*
- * call-seq:
- *   sym.to_proc
- *
- * Returns a _Proc_ object which respond to the given method by _sym_.
- *
- *   (1..3).collect(&:to_s)  #=> ["1", "2", "3"]
- */
-
-static VALUE
-rsym_to_proc(VALUE sym, SEL sel)
-{
-    ID mid = SYM2ID(sym);
-    rb_vm_block_t *b = rb_vm_create_block_calling_mid(mid);
-    return rb_proc_alloc_with_block(rb_cProc, b);
-}
-
-/*
- *  call-seq:
- *     sym.id2name   => string
- *     sym.to_s      => string
- *  
- *  Returns the name or string corresponding to <i>sym</i>.
- *     
- *     :fred.id2name   #=> "fred"
- */
-
-static VALUE
-rsym_to_s(VALUE sym, SEL sel)
-{
-    return rb_sym_to_s(sym);
-}
-
-/*
- * call-seq:
- *   sym.to_sym   => sym
- *   sym.intern   => sym
- *
- * In general, <code>to_sym</code> returns the <code>Symbol</code>
- * corresponding to an object. As <i>sym</i> is already a symbol,
- * <code>self</code> is returned in this case.
- */
-
-static VALUE
-rsym_to_sym(VALUE sym, SEL sel)
-{
-    return sym;
-}
-
-/*
- * call-seq:
- *   sym.empty?   => true or false
- *
- * Returns that _sym_ is :"" or not.
- */
-
-static VALUE
-rsym_empty(VALUE sym, SEL sel)
-{
-    return rb_str_chars_len(RSYM(sym)->str) == 0 ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   sym[idx]      => char
- *   sym[b, n]     => char
- *
- * Returns <code>sym.to_s[]</code>.
- */
-
-static VALUE
-rsym_aref(VALUE sym, SEL sel, int argc, VALUE *argv)
-{
-    return rstr_aref(RSYM(sym)->str, sel, argc, argv);
-}
-
-/*
- * call-seq:
- *   sym.upcase    => symbol
- *
- * Same as <code>sym.to_s.upcase.intern</code>.
- */
-
-static VALUE
-rsym_upcase(VALUE sym, SEL sel)
-{
-    return ID2SYM(rb_intern_str(rstr_upcase(RSYM(sym)->str, sel)));
-}
-
-/*
- * call-seq:
- *   sym.downcase    => symbol
- *
- * Same as <code>sym.to_s.downcase.intern</code>.
- */
-
-static VALUE
-rsym_downcase(VALUE sym, SEL sel)
-{
-    return ID2SYM(rb_intern_str(rstr_downcase(RSYM(sym)->str, sel)));
-}
-
-/*
- * call-seq:
- *   sym.capitalize  => symbol
- *
- * Same as <code>sym.to_s.capitalize.intern</code>.
- */
-
-static VALUE
-rsym_capitalize(VALUE sym, SEL sel)
-{
-    return ID2SYM(rb_intern_str(rstr_capitalize(RSYM(sym)->str, sel)));
-}
-
-/*
- * call-seq:
- *   sym.swapcase  => symbol
- *
- * Same as <code>sym.to_s.swapcase.intern</code>.
- */
-
-static VALUE
-rsym_swapcase(VALUE sym, SEL sel)
-{
-    return ID2SYM(rb_intern_str(rstr_swapcase(RSYM(sym)->str, sel)));
-}
-
-// Cocoa primitives
-
-static void *
-rsym_imp_copy(void *rcv, SEL sel)
-{
-    return rcv;
-}
-
-static CFIndex
-rsym_imp_length(void *rcv, SEL sel)
-{
-    return CFStringGetLength((CFStringRef)RSYM(rcv)->str);
-}
-
-static UniChar
-rsym_imp_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
-{
-    return CFStringGetCharacterAtIndex((CFStringRef)RSYM(rcv)->str, idx);
-}
-
-#define RSYM_NSCODER_KEY "MRSymbolStr"
-
-static void
-rsym_imp_encodeWithCoder(void *rcv, SEL sel, void *coder)
-{
-    rb_str_NSCoder_encode(coder, RSYM(rcv)->str, RSYM_NSCODER_KEY);
-}
-
-static VALUE
-rsym_imp_initWithCoder(void *rcv, SEL sel, void *coder)
-{
-    return ID2SYM(rb_intern_str(rb_str_NSCoder_decode(coder, RSYM_NSCODER_KEY)));
-}
-
-static Class
-rsym_imp_classForKeyedArchiver(void *rcv, SEL sel)
-{
-    return (Class)rb_cSymbol;
-}
-
-void
-Init_Symbol(void)
-{
-    // rb_cSymbol is defined earlier in Init_PreVM().
-    rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
-    rb_const_set(rb_cObject, rb_intern("Symbol"), rb_cSymbol);
-
-    rb_undef_alloc_func(rb_cSymbol);
-    rb_undef_method(*(VALUE *)rb_cSymbol, "new");
-    rb_objc_define_method(*(VALUE *)rb_cSymbol, "all_symbols",
-	    rsym_all_symbols, 0);
-
-    // Undefine methods defined on NSString.
-    rb_undef_method(rb_cSymbol, "to_i");
-    rb_undef_method(rb_cSymbol, "to_f");
-    rb_undef_method(rb_cSymbol, "to_str");
-
-    rb_objc_define_method(rb_cSymbol, "==", rsym_equal, 1);
-    rb_objc_define_method(rb_cSymbol, "<=>", rsym_cmp, 1);
-    rb_objc_define_method(rb_cSymbol, "casecmp", rsym_casecmp, 1);
-    rb_objc_define_method(rb_cSymbol, "eql?", rsym_equal, 1);
-    rb_objc_define_method(rb_cSymbol, "inspect", rsym_inspect, 0);
-    rb_objc_define_method(rb_cSymbol, "to_proc", rsym_to_proc, 0);
-    rb_objc_define_method(rb_cSymbol, "to_s", rsym_to_s, 0);
-    rb_objc_define_method(rb_cSymbol, "id2name", rsym_to_s, 0);
-    rb_objc_define_method(rb_cSymbol, "description", rsym_to_s, 0);
-    rb_objc_define_method(rb_cSymbol, "intern", rsym_to_sym, 0);
-    rb_objc_define_method(rb_cSymbol, "to_sym", rsym_to_sym, 0);
-    rb_objc_define_method(rb_cSymbol, "empty?", rsym_empty, 0);
-    rb_objc_define_method(rb_cSymbol, "[]", rsym_aref, -1);
-    rb_objc_define_method(rb_cSymbol, "upcase", rsym_upcase, 0);
-    rb_objc_define_method(rb_cSymbol, "downcase", rsym_downcase, 0);
-    rb_objc_define_method(rb_cSymbol, "swapcase", rsym_swapcase, 0);
-    rb_objc_define_method(rb_cSymbol, "capitalize", rsym_capitalize, 0);
-
-    // Cocoa primitives.
-    rb_objc_install_method2((Class)rb_cSymbol, "copy",
-	    (IMP)rsym_imp_copy);
-    rb_objc_install_method2((Class)rb_cSymbol, "length",
-	    (IMP)rsym_imp_length);
-    rb_objc_install_method2((Class)rb_cSymbol, "characterAtIndex:",
-	    (IMP)rsym_imp_characterAtIndex);
-    rb_objc_install_method2((Class)rb_cSymbol, "encodeWithCoder:",
-	    (IMP)rsym_imp_encodeWithCoder);
-    rb_objc_install_method2((Class)rb_cSymbol, "initWithCoder:",
-	    (IMP)rsym_imp_initWithCoder);
-    rb_objc_install_method2((Class)rb_cSymbol, "classForKeyedArchiver",
-	    (IMP)rsym_imp_classForKeyedArchiver);
-}
-
-int
-rb_is_const_id(ID id)
-{
-    return is_const_id(id) ? Qtrue : Qfalse;
-}
-
-int
-rb_is_class_id(ID id)
-{
-    return is_class_id(id) ? Qtrue : Qfalse;
-}
-
-int
-rb_is_instance_id(ID id)
-{
-    return is_instance_id(id) ? Qtrue : Qfalse;
-}
-
-int
-rb_is_local_id(ID id)
-{
-    return is_local_id(id) ? Qtrue : Qfalse;
-}
-
-int
-rb_is_junk_id(ID id)
-{
-    return is_junk_id(id) ? Qtrue : Qfalse;
-}
-
-ID
-rb_id_attrset(ID id)
-{
-    id &= ~ID_SCOPE_MASK;
-    id |= ID_ATTRSET;
-    return id;
-}
-
-VALUE
-rb_sym_str(VALUE sym)
-{
-    return RSYM(sym)->str;
-}
-
-VALUE
-rb_sel_to_sym(SEL sel)
-{
-    if (sel == 0) {
-	return Qnil;
-    }
-    return ID2SYM(rb_intern(sel_getName(sel)));
-}

Deleted: MacRuby/trunk/symbol.h
===================================================================
--- MacRuby/trunk/symbol.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/symbol.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,56 +0,0 @@
-/* 
- * MacRuby Symbols.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __SYMBOL_H_
-#define __SYMBOL_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-// For the parser.
-#define ID_SCOPE_SHIFT 3
-#define ID_SCOPE_MASK 0x07
-#define ID_LOCAL      0x00
-#define ID_INSTANCE   0x01
-#define ID_GLOBAL     0x03
-#define ID_ATTRSET    0x04
-#define ID_CONST      0x05
-#define ID_CLASS      0x06
-#define ID_JUNK       0x07
-#define ID_INTERNAL   ID_JUNK
-
-#define is_notop_id(id) (true)
-#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
-#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
-#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
-#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
-#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
-#define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
-
-#define is_asgn_or_id(id) ((is_notop_id(id)) && \
-	(((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
-	 ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
-	 ((id)&ID_SCOPE_MASK) == ID_CLASS))
-
-struct rb_op_tbl_entry {
-    ID token;
-    const char *name;
-};
-
-// Defined in parse.y.
-extern struct rb_op_tbl_entry rb_op_tbl[];
-
-VALUE rb_sym_str(VALUE sym);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // __SYMBOL_H_

Deleted: MacRuby/trunk/test_vm.rb
===================================================================
--- MacRuby/trunk/test_vm.rb	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/test_vm.rb	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,103 +0,0 @@
-#!/usr/bin/ruby
-# Preliminary test suite for the MacRuby VM.
-# Aimed at testing critical features of the VM.
-#
-# Please do not contribute tests that cover any higher level features here, 
-# use the rubyspec directory instead.
-
-$test_only = []
-test_commands = []
-ARGV.each do |arg|
-  if md = /--ruby=(.*)/.match(arg)
-    test_commands << md[1]
-  else
-    $test_only << arg
-  end
-end
-if test_commands.empty?
-  miniruby_path = File.join(Dir.pwd, 'miniruby')
-  test_commands << "arch -i386 #{miniruby_path}"
-  test_commands << "arch -x86_64 #{miniruby_path}" if system("arch -x86_64 #{miniruby_path} -e '' 2> /dev/null")
-end
-$test_archs = {}
-test_commands.each do |command|
-  if md = /\barch -([^\s]+)/.match(command)
-    arch_name = md[1]
-  else
-    arch_name = 'default'
-  end
-  $test_archs[arch_name] ||= []
-  $test_archs[arch_name] << command
-end
-$problems = []
-$problems_count = 0
-$assertions_count = 0
-
-def assert(expectation, code, options={})
-  return if options[:known_bug]
-  if options[:archs]
-    archs = $test_archs.select {|arch, command| options[:archs].include?(arch) }
-  else
-    archs = $test_archs
-  end
-  archs.each do |arch, commands|
-    commands.each do |command|
-      output = nil
-      IO.popen("#{command} -I.", 'r+') do |io|
-        io.puts(code)
-        io.close_write
-        output = io.read
-      end
-      result = if $? and $?.exitstatus == 0
-        output.chomp == expectation ? '.' : 'F'
-      else
-        output = "ERROR CODE #{$?.exitstatus}"
-        'E'
-      end
-      print result
-      $stdout.flush
-      if result != '.'
-        $problems_count += 1
-        new_problem = [[$problems_count], code, expectation, [arch], command, output]
-        previous_problem = $problems.last
-        if previous_problem and [1, 2, 5].all? {|i| previous_problem[i] == new_problem[i]}
-          previous_problem[0] << $problems_count
-          previous_problem[3] << arch
-        else
-          $problems << new_problem
-        end
-      end
-      $assertions_count += 1
-    end
-  end
-end
-
-Dir.chdir("#{File.dirname(__FILE__)}/test_vm")
-$tests = Dir.glob('*.rb').map {|filename| File.basename(filename, '.rb')}.sort
-
-$test_only = $tests if $test_only.empty?
-$test_only.each do |what|
-  print "#{what} "
-  $stdout.flush
-  load "./#{what}.rb"
-  puts
-end
-
-at_exit do
-  if $problems.empty?
-    puts "Successfully passed all #{$assertions_count} assertions."
-  else
-    puts ''
-    puts "#{$problems_count} assertion#{$problems_count > 1 ? 's' : ''} over #{$assertions_count} failed:"
-    $problems.each do |ids, code, expectation, archs, command, output|
-      puts ''
-      puts "Problem#{ids.length > 1 ? 's' : ''} #{ids.join(', ')}:"
-      puts "Code: #{code}"
-      puts "Arch#{archs.length > 1 ? 's' : ''}: #{archs.join(', ')}"
-      puts "Command: #{command}"
-      puts "Expectation: #{expectation}"
-      puts "Output: #{output}"
-    end
-    exit 1
-  end
-end

Deleted: MacRuby/trunk/thread.c
===================================================================
--- MacRuby/trunk/thread.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/thread.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1675 +0,0 @@
-/* 
- * MacRuby implementation of Thread.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2009-2011, Apple Inc. All rights reserved.
- * Copyright (C) 2004-2007 Koichi Sasada
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "vm.h"
-#include "objc.h"
-
-VALUE rb_cThread;
-VALUE rb_cThGroup;
-VALUE rb_cMutex;
-
-typedef struct rb_vm_mutex {
-    pthread_mutex_t mutex;
-    rb_vm_thread_t *thread;
-} rb_vm_mutex_t;
-
-#define GetMutexPtr(obj) ((rb_vm_mutex_t *)DATA_PTR(obj))
-
-typedef struct {
-    bool enclosed;
-    VALUE threads;
-    VALUE mutex;
-} rb_thread_group_t;
-
-#define GetThreadGroupPtr(obj) ((rb_thread_group_t *)DATA_PTR(obj))
-
-#if 0
-static VALUE
-thread_s_new(int argc, VALUE *argv, VALUE klass)
-{
-    // TODO
-    return Qnil;
-}
-#endif
-
-static VALUE
-thread_s_alloc(VALUE self, SEL sel)
-{
-    rb_vm_thread_t *t = (rb_vm_thread_t *)xmalloc(sizeof(rb_vm_thread_t));
-    t->thread = 0;
-    return Data_Wrap_Struct(self, NULL, NULL, t);
-}
-
-static IMP
-thread_finalize_imp_super = NULL;
-
-static void
-thread_finalize_imp(void *rcv, SEL sel)
-{
-    rb_vm_thread_t *t = GetThreadPtr(rcv);
-    if (t->exception != Qnil && !t->joined_on_exception) {
-	fprintf(stderr, "*** Thread %p exited prematurely because of an uncaught exception:\n%s\n",
-		t->thread,
-		rb_str_cstr(rb_format_exception_message(t->exception)));
-    }
-    if (thread_finalize_imp_super != NULL) {
-        ((void(*)(void *, SEL))thread_finalize_imp_super)(rcv, sel);
-    }
-}
-
-static VALUE
-thread_initialize(VALUE thread, SEL sel, int argc, const VALUE *argv)
-{
-    if (!rb_block_given_p()) {
-	rb_raise(rb_eThreadError, "must be called with a block");
-    }
-    rb_vm_block_t *b = rb_vm_current_block();
-    assert(b != NULL);
-
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    if (t->thread != 0) {
-	rb_raise(rb_eThreadError, "already initialized thread");
-    }
-    rb_vm_thread_pre_init(t, b, argc, argv, rb_vm_create_vm());
-
-    // The thread's group is always the parent's one.
-    // The parent group might be nil (ex. if created from GCD).
-    VALUE group = GetThreadPtr(rb_vm_current_thread())->group;
-    if (group != Qnil) {
-	rb_thgroup_add(group, thread);
-    }
-
-    // Retain the Thread object to avoid a potential GC, the corresponding
-    // release is done in rb_vm_thread_run().
-    GC_RETAIN(thread);
-
-    // Prepare attributes for the thread.
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
-    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-    // Launch it.
-    if (pthread_create(&t->thread, &attr, (void *(*)(void *))rb_vm_thread_run,
-		(void *)thread) != 0) {
-	rb_sys_fail("pthread_create() failed");
-    }
-    pthread_attr_destroy(&attr);
-
-    return thread;
-}
-
-/*
- *  call-seq:
- *     Thread.start([args]*) {|args| block }   => thread
- *     Thread.fork([args]*) {|args| block }    => thread
- *
- *  Basically the same as <code>Thread::new</code>. However, if class
- *  <code>Thread</code> is subclassed, then calling <code>start</code> in that
- *  subclass will not invoke the subclass's <code>initialize</code> method.
- */
-
-static VALUE
-thread_start(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE th = thread_s_alloc(klass, 0);
-    return thread_initialize(th, 0, argc, argv);
-}
-
-VALUE
-rb_thread_create(VALUE (*fn)(ANYARGS), void *arg)
-{
-    // TODO
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     thr.join          => thr
- *     thr.join(limit)   => thr
- *
- *  The calling thread will suspend execution and run <i>thr</i>. Does not
- *  return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
- *  the time limit expires, <code>nil</code> will be returned, otherwise
- *  <i>thr</i> is returned.
- *
- *  Any threads not joined will be killed when the main program exits.  If
- *  <i>thr</i> had previously raised an exception and the
- *  <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
- *  (so the exception has not yet been processed) it will be processed at this
- *  time.
- *
- *     a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
- *     x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
- *     x.join # Let x thread finish, a will be killed on exit.
- *
- *  <em>produces:</em>
- *
- *     axyz
- *
- *  The following example illustrates the <i>limit</i> parameter.
- *
- *     y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
- *     puts "Waiting" until y.join(0.15)
- *
- *  <em>produces:</em>
- *
- *     tick...
- *     Waiting
- *     tick...
- *     Waitingtick...
- *
- *
- *     tick...
- */
-
-static VALUE
-thread_join_m(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE timeout;
-
-    rb_scan_args(argc, argv, "01", &timeout);
-
-    rb_vm_thread_t *t = GetThreadPtr(self);
-    if (t->status != THREAD_DEAD) {
-	if (timeout == Qnil) {
-	    // No timeout given: block until the thread finishes.
-	    //pthread_assert(pthread_join(t->thread, NULL));
-	    struct timespec ts;
-	    ts.tv_sec = 0;
-	    ts.tv_nsec = 10000000;
-	    while (t->status != THREAD_DEAD) {
-		nanosleep(&ts, NULL);
-		pthread_yield_np();
-	    }
-	}
-	else {
-	    // Timeout given: sleep and check if the thread is dead.
-	    struct timeval tv = rb_time_interval(timeout);
-	    struct timespec ts;
-	    ts.tv_sec = tv.tv_sec;
-	    ts.tv_nsec = tv.tv_usec * 1000;
-	    while (ts.tv_nsec >= 1000000000) {
-		ts.tv_sec += 1;
-		ts.tv_nsec -= 1000000000;
-	    }
-
-	    while (ts.tv_sec > 0 || ts.tv_nsec > 0) {
-		struct timespec its;
-again:
-		if (ts.tv_nsec > 100000000) {
-		    ts.tv_nsec -= 100000000;
-		    its.tv_sec = 0;
-		    its.tv_nsec = 100000000;
-		}
-		else if (ts.tv_sec > 0) {
-		    ts.tv_sec -= 1;
-		    ts.tv_nsec += 1000000000;
-		    goto again;
-		}
-		else {
-		    its = ts;
-		    ts.tv_sec = ts.tv_nsec = 0;
-		}
-		nanosleep(&its, NULL);
-		if (t->status == THREAD_DEAD) {
-		    goto dead;
-		}
-	    }
-	    return Qnil;
-	}
-    }
-
-dead:
-    // If the thread was terminated because of an exception, we need to
-    // propagate it.
-    if (t->exception != Qnil) {
-	t->joined_on_exception = true;
-	rb_exc_raise(t->exception);
-    }
-    return self;
-}
-
-/*
- *  call-seq:
- *     thr.value   => obj
- *
- *  Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
- *  its value.
- *
- *     a = Thread.new { 2 + 2 }
- *     a.value   #=> 4
- */
-
-static VALUE
-thread_value(VALUE self, SEL sel)
-{
-    thread_join_m(self, 0, 0, NULL);
-    return GetThreadPtr(self)->value;
-}
-
-void
-rb_thread_polling(void)
-{
-    // TODO
-}
-
-void
-rb_thread_schedule(void)
-{
-    // TODO
-}
-
-int rb_thread_critical; /* TODO: dummy variable */
-
-/*
- *  call-seq:
- *     Thread.pass   => nil
- *
- *  Invokes the thread scheduler to pass execution to another thread.
- *
- *     a = Thread.new { print "a"; Thread.pass;
- *                      print "b"; Thread.pass;
- *                      print "c" }
- *     b = Thread.new { print "x"; Thread.pass;
- *                      print "y"; Thread.pass;
- *                      print "z" }
- *     a.join
- *     b.join
- *
- *  <em>produces:</em>
- *
- *     axbycz
- */
-
-static VALUE
-thread_s_pass(VALUE klass, SEL sel)
-{
-    pthread_yield_np();
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     thr.raise(exception)
- *
- *  Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
- *  caller does not have to be <i>thr</i>.
- *
- *     Thread.abort_on_exception = true
- *     a = Thread.new { sleep(200) }
- *     a.raise("Gotcha")
- *
- *  <em>produces:</em>
- *
- *     prog.rb:3: Gotcha (RuntimeError)
- *     	from prog.rb:2:in `initialize'
- *     	from prog.rb:2:in `new'
- *     	from prog.rb:2
- */
-
-static VALUE
-thread_raise_m(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE exc = rb_make_exception(argc, argv);
-
-    rb_vm_thread_t *t = GetThreadPtr(self);
-
-    if (t->thread == pthread_self()) {
-	rb_exc_raise(exc);
-    }
-    else if (t->status != THREAD_DEAD) {
-	rb_vm_thread_raise(t, exc);
-    }
-
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     thr.exit        => thr
- *     thr.kill        => thr
- *     thr.terminate   => thr
- *
- *  Terminates <i>thr</i> and schedules another thread to be run. If this thread
- *  is already marked to be killed, <code>exit</code> returns the
- *  <code>Thread</code>. If this is the main thread, or the last thread, exits
- *  the process.
- */
-
-static VALUE
-rb_thread_kill(VALUE thread, SEL sel)
-{
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    rb_vm_thread_t *t_main = GetThreadPtr(rb_vm_main_thread()); 
-    if (t->thread == t_main->thread) { 
-	rb_exit(EXIT_SUCCESS); 
-    } 
-    if (t->status != THREAD_KILLED) {
-	rb_vm_thread_cancel(t);
-    }
-    return thread;
-}
-
-/*
- *  call-seq:
- *     Thread.kill(thread)   => thread
- *
- *  Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
- *
- *     count = 0
- *     a = Thread.new { loop { count += 1 } }
- *     sleep(0.1)       #=> 0
- *     Thread.kill(a)   #=> #<Thread:0x401b3d30 dead>
- *     count            #=> 93947
- *     a.alive?         #=> false
- */
-
-static VALUE
-rb_thread_s_kill(VALUE obj, SEL sel, VALUE th)
-{
-    if (!rb_obj_is_kind_of(th, rb_cThread)) {
-	rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
-		rb_obj_classname(th));
-    }
-    return rb_thread_kill(th, 0);
-}
-
-/*
- *  call-seq:
- *     Thread.exit   => thread
- *
- *  Terminates the currently running thread and schedules another thread to be
- *  run. If this thread is already marked to be killed, <code>exit</code>
- *  returns the <code>Thread</code>. If this is the main thread, or the last
- *  thread, exit the process.
- */
-
-static VALUE
-rb_thread_exit(void)
-{
-    return rb_thread_kill(rb_vm_current_thread(), 0);
-}
-
-/*
- *  call-seq:
- *     thr.wakeup   => thr
- *
- *  Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
- *  I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
- *
- *     c = Thread.new { Thread.stop; puts "hey!" }
- *     c.wakeup
- *
- *  <em>produces:</em>
- *
- *     hey!
- */
-
-static VALUE
-rb_thread_wakeup(VALUE thread, SEL sel)
-{
-    rb_vm_thread_wakeup(GetThreadPtr(thread));
-    return thread;
-}
-
-/*
- *  call-seq:
- *     thr.run   => thr
- *
- *  Wakes up <i>thr</i>, making it eligible for scheduling.
- *
- *     a = Thread.new { puts "a"; Thread.stop; puts "c" }
- *     Thread.pass
- *     puts "Got here"
- *     a.run
- *     a.join
- *
- *  <em>produces:</em>
- *
- *     a
- *     Got here
- *     c
- */
-
-static VALUE
-rb_thread_run(VALUE thread, SEL sel)
-{
-    rb_vm_thread_wakeup(GetThreadPtr(thread));
-    pthread_yield_np();
-    return thread;
-}
-
-/*
- *  call-seq:
- *     Thread.stop   => nil
- *
- *  Stops execution of the current thread, putting it into a ``sleep'' state,
- *  and schedules execution of another thread.
- *
- *     a = Thread.new { print "a"; Thread.stop; print "c" }
- *     Thread.pass
- *     print "b"
- *     a.run
- *     a.join
- *
- *  <em>produces:</em>
- *
- *     abc
- */
-
-static VALUE
-rb_thread_stop(VALUE rcv, SEL sel)
-{
-    rb_thread_sleep_forever();
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     Thread.list   => array
- *
- *  Returns an array of <code>Thread</code> objects for all threads that are
- *  either runnable or stopped.
- *
- *     Thread.new { sleep(200) }
- *     Thread.new { 1000000.times {|i| i*i } }
- *     Thread.new { Thread.stop }
- *     Thread.list.each {|t| p t}
- *
- *  <em>produces:</em>
- *
- *     #<Thread:0x401b3e84 sleep>
- *     #<Thread:0x401b3f38 run>
- *     #<Thread:0x401b3fb0 sleep>
- *     #<Thread:0x401bdf4c run>
- */
-
-VALUE
-rb_thread_list(VALUE rcv, SEL sel)
-{
-    return rb_ary_dup(rb_vm_threads());
-}
-
-/*
- *  call-seq:
- *     Thread.current   => thread
- *
- *  Returns the currently executing thread.
- *
- *     Thread.current   #=> #<Thread:0x401bdf4c run>
- */
-
-static VALUE
-thread_s_current(VALUE klass, SEL sel)
-{
-    return rb_vm_current_thread();
-}
-
-static VALUE
-rb_thread_s_main(VALUE klass, SEL sel)
-{
-    return rb_vm_main_thread();
-}
-
-/*
- *  call-seq:
- *     Thread.abort_on_exception   => true or false
- *
- *  Returns the status of the global ``abort on exception'' condition.  The
- *  default is <code>false</code>. When set to <code>true</code>, or if the
- *  global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
- *  command line option <code>-d</code> was specified) all threads will abort
- *  (the process will <code>exit(0)</code>) if an exception is raised in any
- *  thread. See also <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_s_abort_exc(VALUE rcv, SEL sel)
-{
-    return rb_vm_abort_on_exception() ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     Thread.abort_on_exception= boolean   => true or false
- *
- *  When set to <code>true</code>, all threads will abort if an exception is
- *  raised. Returns the new state.
- *
- *     Thread.abort_on_exception = true
- *     t1 = Thread.new do
- *       puts  "In new thread"
- *       raise "Exception from thread"
- *     end
- *     sleep(1)
- *     puts "not reached"
- *
- *  <em>produces:</em>
- *
- *     In new thread
- *     prog.rb:4: Exception from thread (RuntimeError)
- *     	from prog.rb:2:in `initialize'
- *     	from prog.rb:2:in `new'
- *     	from prog.rb:2
- */
-
-static VALUE
-rb_thread_s_abort_exc_set(VALUE self, SEL sel, VALUE val)
-{
-    rb_vm_set_abort_on_exception(RTEST(val));
-    return val;
-}
-
-/*
- *  call-seq:
- *     thr.abort_on_exception   => true or false
- *
- *  Returns the status of the thread-local ``abort on exception'' condition for
- *  <i>thr</i>. The default is <code>false</code>. See also
- *  <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_abort_exc(VALUE thread, SEL sel)
-{
-    return GetThreadPtr(thread)->abort_on_exception ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     thr.abort_on_exception= boolean   => true or false
- *
- *  When set to <code>true</code>, causes all threads (including the main
- *  program) to abort if an exception is raised in <i>thr</i>. The process will
- *  effectively <code>exit(0)</code>.
- */
-
-static VALUE
-rb_thread_abort_exc_set(VALUE thread, SEL sel, VALUE val)
-{
-    GetThreadPtr(thread)->abort_on_exception = RTEST(val);
-    return val;
-}
-
-/*
- *  call-seq:
- *     thr.group   => thgrp or nil
- *
- *  Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
- *  the thread is not a member of any group.
- *
- *     Thread.main.group   #=> #<ThreadGroup:0x4029d914>
- */
-
-static VALUE
-rb_thread_group(VALUE thread, SEL sel)
-{
-    return GetThreadPtr(thread)->group;
-}
-
-/*
- *  call-seq:
- *     thr.status   => string, false or nil
- *
- *  Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
- *  sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
- *  ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
- *  <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
- *  terminated with an exception.
- *
- *     a = Thread.new { raise("die now") }
- *     b = Thread.new { Thread.stop }
- *     c = Thread.new { Thread.exit }
- *     d = Thread.new { sleep }
- *     d.kill                  #=> #<Thread:0x401b3678 aborting>
- *     a.status                #=> nil
- *     b.status                #=> "sleep"
- *     c.status                #=> false
- *     d.status                #=> "aborting"
- *     Thread.current.status   #=> "run"
- */
-
-static const char *
-rb_thread_status_cstr(VALUE thread)
-{
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    switch (t->status) {
-	case THREAD_ALIVE:
-	    return "run";
-
-	case THREAD_SLEEP:
-	    return "sleep";
-
-	case THREAD_KILLED:
-	    return "aborting";
-
-	case THREAD_DEAD:
-	    return "dead";
-    }
-    return "unknown";
-}
-
-static VALUE
-rb_thread_status(VALUE thread, SEL sel)
-{
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    if (t->status == THREAD_DEAD) {
-	return t->exception == Qnil ? Qfalse : Qnil;
-    }
-    return rb_str_new2(rb_thread_status_cstr(thread));
-}
-
-/*
- *  call-seq:
- *     thr.alive?   => true or false
- *
- *  Returns <code>true</code> if <i>thr</i> is running or sleeping.
- *
- *     thr = Thread.new { }
- *     thr.join                #=> #<Thread:0x401b3fb0 dead>
- *     Thread.current.alive?   #=> true
- *     thr.alive?              #=> false
- */
-
-static VALUE
-rb_thread_alive_p(VALUE thread, SEL sel)
-{
-    rb_vm_thread_status_t s = GetThreadPtr(thread)->status;
-    return s != THREAD_DEAD ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     thr.stop?   => true or false
- *
- *  Returns <code>true</code> if <i>thr</i> is dead or sleeping.
- *
- *     a = Thread.new { Thread.stop }
- *     b = Thread.current
- *     a.stop?   #=> true
- *     b.stop?   #=> false
- */
-
-static VALUE
-rb_thread_stop_p(VALUE thread)
-{
-    rb_vm_thread_status_t s = GetThreadPtr(thread)->status;
-    return s == THREAD_DEAD || s == THREAD_SLEEP ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     thr.safe_level   => integer
- *
- *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
- *  levels can help when implementing sandboxes which run insecure code.
- *
- *     thr = Thread.new { $SAFE = 3; sleep }
- *     Thread.current.safe_level   #=> 0
- *     thr.safe_level              #=> 3
- */
-
-static VALUE
-rb_thread_safe_level(VALUE thread, SEL sel)
-{
-    return INT2FIX(rb_vm_thread_safe_level(GetThreadPtr(thread)));
-}
-
-/*
- * call-seq:
- *   thr.inspect   => string
- *
- * Dump the name, id, and status of _thr_ to a string.
- */
-
-static VALUE
-rb_thread_inspect(VALUE thread, SEL sel)
-{
-    const char *status = rb_thread_status_cstr(thread);
-
-    char buf[100];
-    snprintf(buf, sizeof buf, "#<%s:%p %s>", rb_obj_classname(thread),
-	    (void *)thread, status);
-
-    return rb_str_new2(buf);
-}
-
-/*
- *  call-seq:
- *      thr[sym]   => obj or nil
- *
- *  Attribute Reference---Returns the value of a thread-local variable, using
- *  either a symbol or a string name. If the specified variable does not exist,
- *  returns <code>nil</code>.
- *
- *     a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
- *     b = Thread.new { Thread.current[:name]  = "B"; Thread.stop }
- *     c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
- *     Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
- *
- *  <em>produces:</em>
- *
- *     #<Thread:0x401b3b3c sleep>: C
- *     #<Thread:0x401b3bc8 sleep>: B
- *     #<Thread:0x401b3c68 sleep>: A
- *     #<Thread:0x401bdf4c run>:
- */
-
-static VALUE
-rb_thread_aref(VALUE thread, SEL sel, VALUE key)
-{
-    key = ID2SYM(rb_to_id(key));
-    VALUE h = rb_vm_thread_locals(thread, false);
-    if (h != Qnil) {
-	return rb_hash_aref(h, key);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_thread_local_aref(VALUE self, ID key)
-{
-    return rb_thread_aref(self, 0, ID2SYM(key));
-}
-
-/*
- *  call-seq:
- *      thr[sym] = obj   => obj
- *
- *  Attribute Assignment---Sets or creates the value of a thread-local variable,
- *  using either a symbol or a string. See also <code>Thread#[]</code>.
- */
-
-static VALUE
-rb_thread_aset(VALUE self, SEL sel, VALUE key, VALUE val)
-{
-    key = ID2SYM(rb_to_id(key));
-    return rb_hash_aset(rb_vm_thread_locals(self, true), key, val);
-}
-
-VALUE
-rb_thread_local_aset(VALUE self, ID key, VALUE val)
-{
-    return rb_thread_aset(self, 0, ID2SYM(key), val);
-}
-
-/*
- *  call-seq:
- *     thr.key?(sym)   => true or false
- *
- *  Returns <code>true</code> if the given string (or symbol) exists as a
- *  thread-local variable.
- *
- *     me = Thread.current
- *     me[:oliver] = "a"
- *     me.key?(:oliver)    #=> true
- *     me.key?(:stanley)   #=> false
- */
-
-static VALUE
-rb_thread_key_p(VALUE self, SEL sel, VALUE key)
-{
-    key = ID2SYM(rb_to_id(key));
-    VALUE h = rb_vm_thread_locals(self, false);
-    if (h == Qnil) {
-	return Qfalse;
-    }
-    return rb_hash_has_key(h, key);
-}
-
-int
-rb_thread_alone()
-{
-    return RARRAY_LEN(rb_vm_threads()) <= 1;
-}
-
-/*
- *  call-seq:
- *     thr.keys   => array
- *
- *  Returns an an array of the names of the thread-local variables (as Symbols).
- *
- *     thr = Thread.new do
- *       Thread.current[:cat] = 'meow'
- *       Thread.current["dog"] = 'woof'
- *     end
- *     thr.join   #=> #<Thread:0x401b3f10 dead>
- *     thr.keys   #=> [:dog, :cat]
- */
-
-static VALUE
-rb_thread_keys(VALUE self, SEL sel)
-{
-    VALUE h = rb_vm_thread_locals(self, false);
-    return h == Qnil ? rb_ary_new() : rb_hash_keys(h);
-}
-
-/*
- *  call-seq:
- *     thr.priority   => integer
- *
- *  Returns the priority of <i>thr</i>. Default is inherited from the
- *  current thread which creating the new thread, or zero for the
- *  initial main thread; higher-priority threads will run before
- *  lower-priority threads.
- *
- *     Thread.current.priority   #=> 0
- */
-
-static VALUE
-rb_thread_priority(VALUE thread, SEL sel)
-{
-    // FIXME this doesn't really minic what 1.9 does, but do we care?
-    struct sched_param param;
-    pthread_assert(pthread_getschedparam(GetThreadPtr(thread)->thread,
-		NULL, &param));
-    return INT2FIX(param.sched_priority);
-}
-
-/*
- *  call-seq:
- *     thr.priority= integer   => thr
- *
- *  Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
- *  will run before lower-priority threads.
- *
- *     count1 = count2 = 0
- *     a = Thread.new do
- *           loop { count1 += 1 }
- *         end
- *     a.priority = -1
- *
- *     b = Thread.new do
- *           loop { count2 += 1 }
- *         end
- *     b.priority = -2
- *     sleep 1   #=> 1
- *     count1    #=> 622504
- *     count2    #=> 5832
- */
-
-static VALUE
-rb_thread_priority_set(VALUE thread, SEL sel, VALUE prio)
-{
-    // FIXME this doesn't really minic what 1.9 does, but do we care?
-    int policy;
-    struct sched_param param;
-    pthread_assert(pthread_getschedparam(GetThreadPtr(thread)->thread,
-		&policy, &param));
- 
-    const int max = sched_get_priority_max(policy);
-    const int min = sched_get_priority_min(policy);
-
-    int priority = FIX2INT(prio);
-    if (min > priority) {
-	priority = min;
-    }
-    else if (max > priority) {
-	priority = max;
-    }
-
-    param.sched_priority = priority;
-    pthread_assert(pthread_setschedparam(GetThreadPtr(thread)->thread,
-		policy, &param));
-
-    return Qnil;
-}
-
-/* for IO */
-// TODO these should be moved into io.c
-
-#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
-void
-rb_fd_init(volatile rb_fdset_t *fds)
-{
-    fds->maxfd = 0;
-    GC_WB(&fds->fdset, ALLOC(fd_set));
-    FD_ZERO(fds->fdset);
-}
-
-void
-rb_fd_term(rb_fdset_t *fds)
-{
-    if (fds->fdset) xfree(fds->fdset);
-    fds->maxfd = 0;
-    fds->fdset = 0;
-}
-
-void
-rb_fd_zero(rb_fdset_t *fds)
-{
-    if (fds->fdset) {
-	MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
-	FD_ZERO(fds->fdset);
-    }
-}
-
-static void
-rb_fd_resize(int n, rb_fdset_t *fds)
-{
-    int m = howmany(n + 1, NFDBITS) * sizeof(fd_mask);
-    int o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask);
-
-    if (m < sizeof(fd_set)) m = sizeof(fd_set);
-    if (o < sizeof(fd_set)) o = sizeof(fd_set);
-
-    if (m > o) {
-	GC_WB(&fds->fdset, xrealloc(fds->fdset, m));
-	memset((char *)fds->fdset + o, 0, m - o);
-    }
-    if (n >= fds->maxfd) fds->maxfd = n + 1;
-}
-
-void
-rb_fd_set(int n, rb_fdset_t *fds)
-{
-    rb_fd_resize(n, fds);
-    FD_SET(n, fds->fdset);
-}
-
-void
-rb_fd_clr(int n, rb_fdset_t *fds)
-{
-    if (n >= fds->maxfd) return;
-    FD_CLR(n, fds->fdset);
-}
-
-int
-rb_fd_isset(int n, const rb_fdset_t *fds)
-{
-    if (n >= fds->maxfd) return 0;
-    return FD_ISSET(n, fds->fdset) != 0; /* "!= 0" avoids FreeBSD PR 91421 */
-}
-
-void
-rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
-{
-    int size = howmany(max, NFDBITS) * sizeof(fd_mask);
-
-    if (size < sizeof(fd_set)) size = sizeof(fd_set);
-    dst->maxfd = max;
-    GC_WB(&dst->fdset, xrealloc(dst->fdset, size));
-    memcpy(dst->fdset, src, size);
-}
-
-int
-rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout)
-{
-    fd_set *r = NULL, *w = NULL, *e = NULL;
-    if (readfds) {
-        rb_fd_resize(n - 1, readfds);
-        r = rb_fd_ptr(readfds);
-    }
-    if (writefds) {
-        rb_fd_resize(n - 1, writefds);
-        w = rb_fd_ptr(writefds);
-    }
-    if (exceptfds) {
-        rb_fd_resize(n - 1, exceptfds);
-        e = rb_fd_ptr(exceptfds);
-    }
-    return select(n, r, w, e, timeout);
-}
-
-#undef FD_ZERO
-#undef FD_SET
-#undef FD_CLR
-#undef FD_ISSET
-
-#define FD_ZERO(f)	rb_fd_zero(f)
-#define FD_SET(i, f)	rb_fd_set(i, f)
-#define FD_CLR(i, f)	rb_fd_clr(i, f)
-#define FD_ISSET(i, f)	rb_fd_isset(i, f)
-
-#endif
-
-static double
-timeofday(void)
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
-}
-
-static int
-do_select(int n, fd_set *read, fd_set *write, fd_set *except,
-	  struct timeval *timeout)
-{
-    int result, lerrno;
-    fd_set orig_read, orig_write, orig_except;
-
-    bzero(&orig_read, sizeof(fd_set));
-    bzero(&orig_write, sizeof(fd_set));
-    bzero(&orig_except, sizeof(fd_set));
-
-#ifndef linux
-    double limit = 0;
-    struct timeval wait_rest;
-
-    if (timeout) {
-	limit = timeofday() +
-	  (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
-	wait_rest = *timeout;
-	timeout = &wait_rest;
-    }
-#endif
-
-    if (read) orig_read = *read;
-    if (write) orig_write = *write;
-    if (except) orig_except = *except;
-
-  retry:
-    lerrno = 0;
-
-    //BLOCKING_REGION({
-	result = select(n, read, write, except, timeout);
-	if (result < 0) lerrno = errno;
-    //}, ubf_select, GET_THREAD());
-
-    errno = lerrno;
-
-    if (result < 0) {
-	switch (errno) {
-	  case EINTR:
-#ifdef ERESTART
-	  case ERESTART:
-#endif
-	    if (read) *read = orig_read;
-	    if (write) *write = orig_write;
-	    if (except) *except = orig_except;
-#ifndef linux
-	    if (timeout) {
-		double d = limit - timeofday();
-
-		wait_rest.tv_sec = (unsigned int)d;
-		wait_rest.tv_usec = (long)((d-(double)wait_rest.tv_sec)*1e6);
-		if (wait_rest.tv_sec < 0)  wait_rest.tv_sec = 0;
-		if (wait_rest.tv_usec < 0) wait_rest.tv_usec = 0;
-	    }
-#endif
-	    goto retry;
-	  default:
-	    break;
-	}
-    }
-    return result;
-}
-
-static void
-rb_thread_wait_fd_rw(int fd, int read)
-{
-    int result = 0;
-
-    while (result <= 0) {
-	rb_fdset_t *set = ALLOC(rb_fdset_t);
-	rb_fd_init(set);
-	FD_SET(fd, set);
-
-	if (read) {
-	    result = do_select(fd + 1, rb_fd_ptr(set), 0, 0, 0);
-	}
-	else {
-	    result = do_select(fd + 1, 0, rb_fd_ptr(set), 0, 0);
-	}
-
-	rb_fd_term(set);
-
-	if (result < 0) {
-	    rb_sys_fail(0);
-	}
-    }
-}
-
-void
-rb_thread_wait_fd(int fd)
-{
-    rb_thread_wait_fd_rw(fd, 1);
-}
-
-int
-rb_thread_fd_writable(int fd)
-{
-    rb_thread_wait_fd_rw(fd, 0);
-    return Qtrue;
-}
-
-int
-rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
-		 struct timeval *timeout)
-{
-    if (!read && !write && !except) {
-	if (!timeout) {
-	    rb_thread_sleep_forever();
-	    return 0;
-	}
-	rb_thread_wait_for(*timeout);
-	return 0;
-    }
-    else {
-	return do_select(max, read, write, except, timeout);
-    }
-}
-
-/*
- * Document-class: ThreadGroup
- *
- *  <code>ThreadGroup</code> provides a means of keeping track of a number of
- *  threads as a group. A <code>Thread</code> can belong to only one
- *  <code>ThreadGroup</code> at a time; adding a thread to a new group will
- *  remove it from any previous group.
- *
- *  Newly created threads belong to the same group as the thread from which they
- *  were created.
- */
-
-static VALUE mutex_s_alloc(VALUE self, SEL sel);
-static VALUE mutex_initialize(VALUE self, SEL sel);
-
-static VALUE
-thgroup_s_alloc(VALUE self, SEL sel)
-{
-    rb_thread_group_t *t = (rb_thread_group_t *)xmalloc(
-	    sizeof(rb_thread_group_t));
-    t->enclosed = false;
-    GC_WB(&t->threads, rb_ary_new());
-    OBJ_UNTRUST(t->threads);
-
-    VALUE mutex = mutex_s_alloc(rb_cMutex, 0);
-    mutex_initialize(mutex, 0);
-    GC_WB(&t->mutex, mutex);
-
-    return Data_Wrap_Struct(self, NULL, NULL, t);
-}
-
-/*
- *  call-seq:
- *     thgrp.list   => array
- *
- *  Returns an array of all existing <code>Thread</code> objects that belong to
- *  this group.
- *
- *     ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]
- */
-
-static VALUE
-thgroup_list(VALUE group, SEL sel)
-{
-    return GetThreadGroupPtr(group)->threads;
-}
-
-/*
- *  call-seq:
- *     thgrp.enclose   => thgrp
- *
- *  Prevents threads from being added to or removed from the receiving
- *  <code>ThreadGroup</code>. New threads can still be started in an enclosed
- *  <code>ThreadGroup</code>.
- *
- *     ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
- *     thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
- *     tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
- *     tg.add thr
- *
- *  <em>produces:</em>
- *
- *     ThreadError: can't move from the enclosed thread group
- */
-
-static VALUE
-thgroup_enclose(VALUE group, SEL sel)
-{
-    GetThreadGroupPtr(group)->enclosed = true;
-    return group;
-}
-
-/*
- *  call-seq:
- *     thgrp.enclosed?   => true or false
- *
- *  Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
- *  ThreadGroup#enclose.
- */
-
-static VALUE
-thgroup_enclosed_p(VALUE group)
-{
-    return GetThreadGroupPtr(group)->enclosed ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     thgrp.add(thread)   => thgrp
- *
- *  Adds the given <em>thread</em> to this group, removing it from any other
- *  group to which it may have previously belonged.
- *
- *     puts "Initial group is #{ThreadGroup::Default.list}"
- *     tg = ThreadGroup.new
- *     t1 = Thread.new { sleep }
- *     t2 = Thread.new { sleep }
- *     puts "t1 is #{t1}"
- *     puts "t2 is #{t2}"
- *     tg.add(t1)
- *     puts "Initial group now #{ThreadGroup::Default.list}"
- *     puts "tg group now #{tg.list}"
- *
- *  <em>produces:</em>
- *
- *     Initial group is #<Thread:0x401bdf4c>
- *     t1 is #<Thread:0x401b3c90>
- *     t2 is #<Thread:0x401b3c18>
- *     Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
- *     tg group now #<Thread:0x401b3c90>
- */
-
-static inline void
-thgroup_lock(rb_thread_group_t *tg)
-{
-    pthread_assert(pthread_mutex_lock(&GetMutexPtr(tg->mutex)->mutex));
-}
-
-static inline void
-thgroup_unlock(rb_thread_group_t *tg)
-{
-    pthread_assert(pthread_mutex_unlock(&GetMutexPtr(tg->mutex)->mutex));
-}
-
-static VALUE
-thgroup_add(VALUE group, SEL sel, VALUE thread)
-{
-    if (OBJ_FROZEN(group)) {
-	rb_raise(rb_eThreadError, "can't move to the frozen thread group");
-    }
-
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-
-    rb_thread_group_t *new_tg = GetThreadGroupPtr(group);
-    if (new_tg->enclosed) {
-	rb_raise(rb_eThreadError, "can't move from the enclosed thread group");
-    }
-
-    if (t->group != Qnil) {
-	if (OBJ_FROZEN(t->group)) {
-	    rb_raise(rb_eThreadError,
-		    "can't move from the frozen thread group");
-	}
-	rb_thread_group_t *old_tg = GetThreadGroupPtr(t->group);
-	if (old_tg->enclosed) {
-	    rb_raise(rb_eThreadError,
-		    "can't move from the enclosed thread group");
-	}
- 	thgroup_lock(old_tg);
-	rb_ary_delete(old_tg->threads, thread); 
- 	thgroup_unlock(old_tg);
-    }
-
-    thgroup_lock(new_tg);
-    rb_ary_push(new_tg->threads, thread);
-    thgroup_unlock(new_tg);
-    GC_WB(&t->group, group);
-
-    return group;
-}
-
-VALUE
-rb_thgroup_add(VALUE group, VALUE thread)
-{
-    return thgroup_add(group, 0, thread);
-}
-
-void
-rb_thread_remove_from_group(VALUE thread)
-{
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    if (t->group != Qnil) {
-	rb_thread_group_t *tg = GetThreadGroupPtr(t->group);
-	thgroup_lock(tg);
-	if (rb_ary_delete(tg->threads, thread) != thread) {
-	    printf("trying to remove a thread (%p) from a group that doesn't "\
-		    "contain it\n", (void *)thread);
-	    abort();
-	}
-	thgroup_unlock(tg);
-	t->group = Qnil;
-    }
-}
-
-/*
- *  Document-class: Mutex
- *
- *  Mutex implements a simple semaphore that can be used to coordinate access to
- *  shared data from multiple concurrent threads.
- *
- *  Example:
- *
- *    require 'thread'
- *    semaphore = Mutex.new
- *
- *    a = Thread.new {
- *      semaphore.synchronize {
- *        # access shared resource
- *      }
- *    }
- *
- *    b = Thread.new {
- *      semaphore.synchronize {
- *        # access shared resource
- *      }
- *    }
- *
- */
-
-/*
- *  call-seq:
- *     Mutex.new   => mutex
- *
- *  Creates a new Mutex
- */
-
-static VALUE
-mutex_s_alloc(VALUE self, SEL sel)
-{
-    rb_vm_mutex_t *t = (rb_vm_mutex_t *)xmalloc(sizeof(rb_vm_mutex_t));
-    return Data_Wrap_Struct(self, NULL, NULL, t);
-}
-
-static VALUE
-mutex_initialize(VALUE self, SEL sel)
-{
-    pthread_assert(pthread_mutex_init(&GetMutexPtr(self)->mutex, NULL));
-    return self;
-}
-
-/*
- * call-seq:
- *    mutex.locked?  => true or false
- *
- * Returns +true+ if this lock is currently held by some thread.
- */
-
-static VALUE
-rb_mutex_locked_p(VALUE self, SEL sel)
-{
-    return GetMutexPtr(self)->thread == 0 ? Qfalse : Qtrue;
-}
-
-/*
- * call-seq:
- *    mutex.try_lock  => true or false
- *
- * Attempts to obtain the lock and returns immediately. Returns +true+ if the
- * lock was granted.
- */
-
-static VALUE
-rb_mutex_trylock(VALUE self, SEL sel)
-{
-    rb_vm_mutex_t *m = GetMutexPtr(self);
-
-    if (pthread_mutex_trylock(&m->mutex) == 0) {
-	rb_vm_thread_t *current = GetThreadPtr(rb_vm_current_thread());
-	m->thread = current;
-	if (current->mutexes == Qnil) {
-	    GC_WB(&current->mutexes, rb_ary_new());
-	    OBJ_UNTRUST(current->mutexes);
-	}
-	rb_ary_push(current->mutexes, self);
-	return Qtrue;
-    }
-
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *    mutex.lock  => self
- *
- * Attempts to grab the lock and waits if it isn't available.
- * Raises +ThreadError+ if +mutex+ was locked by the current thread.
- */
-
-static VALUE
-rb_mutex_lock(VALUE self, SEL sel)
-{
-    rb_vm_thread_t *current = GetThreadPtr(rb_vm_current_thread());
-    rb_vm_mutex_t *m = GetMutexPtr(self);
-    if (m->thread == current) {
-	rb_raise(rb_eThreadError, "deadlock; recursive locking");
-    }
-
-    current->status = THREAD_SLEEP;
-    pthread_assert(pthread_mutex_lock(&m->mutex));
-    current->status = THREAD_ALIVE;
-    m->thread = current;
-    if (current->mutexes == Qnil) {
-	GC_WB(&current->mutexes, rb_ary_new());
-	OBJ_UNTRUST(current->mutexes);
-    }
-    rb_ary_push(current->mutexes, self);
-
-    return self;
-}
-
-/*
- * call-seq:
- *    mutex.unlock    => self
- *
- * Releases the lock.
- * Raises +ThreadError+ if +mutex+ wasn't locked by the current thread.
- */
-
-static bool
-rb_mutex_can_unlock(rb_vm_mutex_t *m, bool raise)
-{
-    if (m->thread == NULL) {
-	if (!raise) {
-	    return false;
-	}
-	rb_raise(rb_eThreadError,
-		"Attempt to unlock a mutex which is not locked");
-    }
-    else if (m->thread != GetThreadPtr(rb_vm_current_thread())) {
-	if (!raise) {
-	    return false;
-	}
-	rb_raise(rb_eThreadError,
-		"Attempt to unlock a mutex which is locked by another thread");
-    }
-    return true;
-}
-
-static void
-rb_mutex_unlock0(VALUE self, bool assert_unlockable,
-	bool delete_from_thread_mutexes)
-{
-    rb_vm_mutex_t *m = GetMutexPtr(self);
-    bool ok = rb_mutex_can_unlock(m, assert_unlockable);
-    if (ok) {
-	if (delete_from_thread_mutexes) {
-	    assert(m->thread->mutexes != Qnil);
-	    rb_ary_delete(m->thread->mutexes, self);
-	}
-	pthread_assert(pthread_mutex_unlock(&m->mutex));
-	m->thread = NULL;
-    }
-}
-
-static VALUE
-rb_mutex_unlock(VALUE self, SEL sel)
-{
-    rb_mutex_unlock0(self, true, true);
-    return self;
-}
-
-void
-rb_thread_unlock_all_mutexes(rb_vm_thread_t *thread)
-{
-    if (thread->mutexes != Qnil) {
-	int i, count = RARRAY_LEN(thread->mutexes);
-	for (i = 0; i < count; i++) {
-	    rb_mutex_unlock0(RARRAY_AT(thread->mutexes, i), false, false);
-	}
-	rb_ary_clear(thread->mutexes);
-    }
-}
-
-/*
- * call-seq:
- *    mutex.sleep(timeout = nil)    => number
- *
- * Releases the lock and sleeps +timeout+ seconds if it is given and
- * non-nil or forever.  Raises +ThreadError+ if +mutex+ wasn't locked by
- * the current thread.
- */
-
-static VALUE
-mutex_sleep(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE timeout;
-    rb_scan_args(argc, argv, "01", &timeout);
-
-    rb_mutex_unlock(self, 0);
-    
-    time_t beg, end;
-    beg = time(0);
-
-    if (timeout == Qnil) {
-	rb_thread_sleep_forever();	
-    }
-    else {
-	struct timeval t = rb_time_interval(timeout);
-	rb_thread_wait_for(t);
-    }
-
-    end = time(0) - beg;
-    return INT2FIX(end);        
-}
-
-/*
- * call-seq:
- *    mutex.synchronize { ... }    => result of the block
- *
- * Obtains a lock, runs the block, and releases the lock when the block
- * completes.  See the example under +Mutex+.
- */
-
-static VALUE
-sync_body(VALUE a)
-{
-    return rb_yield(Qundef);
-}
-
-static VALUE
-sync_ensure(VALUE mutex)
-{
-    rb_mutex_unlock0(mutex, false, true);
-    return Qnil;
-}
-
-static VALUE
-mutex_synchronize(VALUE self, SEL sel)
-{
-    rb_mutex_lock(self, 0);
-    return rb_ensure(sync_body, Qundef, sync_ensure, self);
-}
-
-VALUE
-rb_thread_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
-{
-    // TODO
-    return Qnil;
-}
-
-/*
- *  +Thread+ encapsulates the behavior of a thread of
- *  execution, including the main thread of the Ruby script.
- *
- *  In the descriptions of the methods in this class, the parameter _sym_
- *  refers to a symbol, which is either a quoted string or a
- *  +Symbol+ (such as <code>:name</code>).
- */
-
-void
-Init_Thread(void)
-{
-    rb_cThread = rb_define_class("Thread", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "alloc", thread_s_alloc, 0);
-
-    thread_finalize_imp_super = rb_objc_install_method2((Class)rb_cThread,
-	    "finalize", (IMP)thread_finalize_imp);
-
-    rb_objc_define_method(*(VALUE *)rb_cThread, "start", thread_start, -1);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "fork", thread_start, -1);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "main", rb_thread_s_main, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "current", thread_s_current, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "stop", rb_thread_stop, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "kill", rb_thread_s_kill, 1);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "exit", rb_thread_exit, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "pass", thread_s_pass, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "list", rb_thread_list, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
-
-    rb_objc_define_method(rb_cThread, "initialize", thread_initialize, -1);
-    rb_objc_define_method(rb_cThread, "raise", thread_raise_m, -1);
-    rb_objc_define_method(rb_cThread, "join", thread_join_m, -1);
-    rb_objc_define_method(rb_cThread, "value", thread_value, 0);
-    rb_objc_define_method(rb_cThread, "kill", rb_thread_kill, 0);
-    rb_objc_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
-    rb_objc_define_method(rb_cThread, "exit", rb_thread_kill, 0);
-    rb_objc_define_method(rb_cThread, "run", rb_thread_run, 0);
-    rb_objc_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
-    rb_objc_define_method(rb_cThread, "[]", rb_thread_aref, 1);
-    rb_objc_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
-    rb_objc_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
-    rb_objc_define_method(rb_cThread, "keys", rb_thread_keys, 0);
-    rb_objc_define_method(rb_cThread, "priority", rb_thread_priority, 0);
-    rb_objc_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
-    rb_objc_define_method(rb_cThread, "status", rb_thread_status, 0);
-    rb_objc_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
-    rb_objc_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
-    rb_objc_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
-    rb_objc_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
-    rb_objc_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
-    rb_objc_define_method(rb_cThread, "group", rb_thread_group, 0);
-
-    rb_objc_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
-
-    rb_cThGroup = rb_define_class("ThreadGroup", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cThGroup, "alloc", thgroup_s_alloc, 0);
-    rb_objc_define_method(rb_cThGroup, "list", thgroup_list, 0);
-    rb_objc_define_method(rb_cThGroup, "enclose", thgroup_enclose, 0);
-    rb_objc_define_method(rb_cThGroup, "enclosed?", thgroup_enclosed_p, 0);
-    rb_objc_define_method(rb_cThGroup, "add", thgroup_add, 1);
-
-    rb_cMutex = rb_define_class("Mutex", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cMutex, "alloc", mutex_s_alloc, 0);
-    rb_objc_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
-    rb_objc_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
-    rb_objc_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
-    rb_objc_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
-    rb_objc_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
-    rb_objc_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
-    rb_objc_define_method(rb_cMutex, "synchronize", mutex_synchronize, 0);
-
-    rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
-}
-
-VALUE
-rb_thread_blocking_region(rb_blocking_function_t *func, void *data1,
-	rb_unblock_function_t *ubf, void *data2)
-{
-    // For compatibility with CRuby. We do not have a global lock to release,
-    // so we can just call the function directly.
-    return func(data1);
-}

Deleted: MacRuby/trunk/time.c
===================================================================
--- MacRuby/trunk/time.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/time.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2452 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9's time.c
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include <sys/types.h>
-#include <time.h>
-#include <errno.h>
-#include <unistd.h>
-#include <math.h>
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-#include "objc.h"
-#include "class.h"
-
-VALUE rb_cTime;
-VALUE rb_cNSDate;
-static VALUE time_utc_offset _((VALUE, SEL));
-
-static ID id_divmod, id_mul, id_submicro;
-
-struct time_object {
-    struct RBasic basic;
-    struct timespec ts;
-    struct tm tm;
-    int gmt;
-    int tm_got;
-};
-
-#define GetTimeval(obj, tobj) (tobj = (struct time_object *)obj)
-
-static VALUE
-time_s_alloc(VALUE klass, SEL sel)
-{
-    NEWOBJ(tobj, struct time_object);
-    tobj->basic.klass = klass;
-    tobj->basic.flags = 0;
-    tobj->tm_got=0;
-    tobj->ts.tv_sec = 0;
-    tobj->ts.tv_nsec = 0;
-    return (VALUE)tobj;
-}
-
-static void
-time_modify(VALUE time)
-{
-    rb_check_frozen(time);
-    if (!OBJ_TAINTED(time) && rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: can't modify Time");
-}
-
-/*
- *  Document-method: now
- *
- *  Synonym for <code>Time.new</code>. Returns a +Time+ object
- *  initialized to the current system time.
- */
-
-/*
- *  call-seq:
- *     Time.new -> time
- *  
- *  Returns a <code>Time</code> object initialized to the current system
- *  time. <b>Note:</b> The object created will be created using the
- *  resolution available on your system clock, and so may include
- *  fractional seconds.
- *     
- *     a = Time.new      #=> 2007-11-19 07:50:02 -0600
- *     b = Time.new      #=> 2007-11-19 07:50:02 -0600
- *     a == b            #=> false
- *     "%.6f" % a.to_f   #=> "1195480202.282373"
- *     "%.6f" % b.to_f   #=> "1195480202.283415"
- *     
- */
-
-static VALUE
-time_init(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    time_modify(time);
-    GetTimeval(time, tobj);
-    tobj->tm_got=0;
-    tobj->ts.tv_sec = 0;
-    tobj->ts.tv_nsec = 0;
-#ifdef HAVE_CLOCK_GETTIME
-    if (clock_gettime(CLOCK_REALTIME, &tobj->ts) == -1) {
-	rb_sys_fail("clock_gettime");
-    }
-#else
-    {
-        struct timeval tv; 
-        if (gettimeofday(&tv, 0) < 0) {
-            rb_sys_fail("gettimeofday");
-        }
-        tobj->ts.tv_sec = tv.tv_sec;
-        tobj->ts.tv_nsec = tv.tv_usec * 1000;
-    }
-#endif
-
-    return time;
-}
-
-#define NDIV(x,y) (-(-((x)+1)/(y))-1)
-#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
-
-static void
-time_overflow_p(time_t *secp, long *nsecp)
-{
-    time_t tmp, sec = *secp;
-    long nsec = *nsecp;
-
-    if (nsec >= 1000000000) {	/* nsec positive overflow */
-	tmp = sec + nsec / 1000000000;
-	nsec %= 1000000000;
-	if (sec > 0 && tmp < 0) {
-	    rb_raise(rb_eRangeError, "out of Time range");
-	}
-	sec = tmp;
-    }
-    if (nsec < 0) {		/* nsec negative overflow */
-	tmp = sec + NDIV(nsec,1000000000); /* negative div */
-	nsec = NMOD(nsec,1000000000);      /* negative mod */
-	if (sec < 0 && tmp > 0) {
-	    rb_raise(rb_eRangeError, "out of Time range");
-	}
-	sec = tmp;
-    }
-#ifndef NEGATIVE_TIME_T
-    if (sec < 0)
-	rb_raise(rb_eArgError, "time must be positive");
-#endif
-    *secp = sec;
-    *nsecp = nsec;
-}
-
-static VALUE
-time_new_internal(VALUE klass, time_t sec, long nsec)
-{
-    VALUE time = time_s_alloc(klass, 0);
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    time_overflow_p(&sec, &nsec);
-    tobj->ts.tv_sec = sec;
-    tobj->ts.tv_nsec = nsec;
-
-    return time;
-}
-
-VALUE
-rb_time_new(time_t sec, long usec)
-{
-    return time_new_internal(rb_cTime, sec, usec * 1000);
-}
-
-VALUE
-rb_time_nano_new(time_t sec, long nsec)
-{
-    return time_new_internal(rb_cTime, sec, nsec);
-}
-
-static struct timespec
-time_timespec(VALUE num, int interval)
-{
-    struct timespec t;
-    const char *tstr = interval ? "time interval" : "time";
-    VALUE i, f, ary;
-
-#ifndef NEGATIVE_TIME_T
-    interval = 1;
-#endif
-
-    switch (TYPE(num)) {
-      case T_FIXNUM:
-	t.tv_sec = FIX2LONG(num);
-	if (interval && t.tv_sec < 0)
-	    rb_raise(rb_eArgError, "%s must be positive", tstr);
-	t.tv_nsec = 0;
-	break;
-
-      case T_FLOAT:
-	if (interval && RFLOAT_VALUE(num) < 0.0)
-	    rb_raise(rb_eArgError, "%s must be positive", tstr);
-	else {
-	    double f, d;
-
-	    d = modf(RFLOAT_VALUE(num), &f);
-	    t.tv_sec = (time_t)f;
-	    if (f != t.tv_sec) {
-		rb_raise(rb_eRangeError, "%f out of Time range", RFLOAT_VALUE(num));
-	    }
-	    t.tv_nsec = (long)(d*1e9+0.5);
-	}
-	break;
-
-      case T_BIGNUM:
-	t.tv_sec = NUM2LONG(num);
-	if (interval && t.tv_sec < 0)
-	    rb_raise(rb_eArgError, "%s must be positive", tstr);
-	t.tv_nsec = 0;
-	break;
-
-      default:
-        if (rb_respond_to(num, id_divmod)) {
-            ary = rb_check_array_type(rb_funcall(num, id_divmod, 1, INT2FIX(1)));
-            if (NIL_P(ary)) {
-                goto typeerror;
-            }
-            i = rb_ary_entry(ary, 0);
-            f = rb_ary_entry(ary, 1);
-            t.tv_sec = NUM2LONG(i);
-            if (interval && t.tv_sec < 0)
-                rb_raise(rb_eArgError, "%s must be positive", tstr);
-            f = rb_funcall(f, id_mul, 1, INT2FIX(1000000000));
-            t.tv_nsec = NUM2LONG(f);
-        }
-        else {
-typeerror:
-            rb_raise(rb_eTypeError, "can't convert %s into %s",
-                     rb_obj_classname(num), tstr);
-        }
-	break;
-    }
-    return t;
-}
-
-static struct timeval
-time_timeval(VALUE num, int interval)
-{
-    struct timespec ts;
-    struct timeval tv;
-
-    ts = time_timespec(num, interval);
-    tv.tv_sec = ts.tv_sec;
-    tv.tv_usec = ts.tv_nsec / 1000;
-
-    return tv;
-}
-
-struct timeval
-rb_time_interval(VALUE num)
-{
-    return time_timeval(num, Qtrue);
-}
-
-struct timeval
-rb_time_timeval(VALUE time)
-{
-    struct time_object *tobj;
-    struct timeval t;
-
-    if (CLASS_OF(time) == rb_cTime) {
-	GetTimeval(time, tobj);
-        t.tv_sec = tobj->ts.tv_sec;
-        t.tv_usec = tobj->ts.tv_nsec / 1000;
-	return t;
-    }
-    return time_timeval(time, Qfalse);
-}
-
-struct timespec
-rb_time_timespec(VALUE time)
-{
-    struct time_object *tobj;
-    struct timespec t;
-
-    if (CLASS_OF(time) == rb_cTime) {
-	GetTimeval(time, tobj);
-        t = tobj->ts;
-	return t;
-    }
-    return time_timespec(time, Qfalse);
-}
-
-/*
- *  call-seq:
- *     Time.at(time) => time
- *     Time.at(seconds_with_frac) => time
- *     Time.at(seconds, microseconds_with_frac) => time
- *  
- *  Creates a new time object with the value given by <i>time</i>,
- *  the given number of <i>seconds_with_frac</i>, or
- *  <i>seconds</i> and <i>microseconds_with_frac</i> from the Epoch.
- *  <i>seconds_with_frac</i> and <i>microseconds_with_frac</i>
- *  can be Integer, Float, Rational, or other Numeric.
- *  non-portable feature allows the offset to be negative on some systems.
- *     
- *     Time.at(0)            #=> 1969-12-31 18:00:00 -0600
- *     Time.at(Time.at(0))   #=> 1969-12-31 18:00:00 -0600
- *     Time.at(946702800)    #=> 1999-12-31 23:00:00 -0600
- *     Time.at(-284061600)   #=> 1960-12-31 00:00:00 -0600
- *     Time.at(946684800.2).usec #=> 200000
- *     Time.at(946684800, 123456.789).nsec #=> 123456789
- */
-
-static VALUE
-time_s_at(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    struct timespec ts;
-    VALUE time, t;
-
-    if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
-	ts.tv_sec = NUM2LONG(time);
-	ts.tv_nsec = NUM2LONG(rb_funcall(t, id_mul, 1, INT2FIX(1000)));
-    }
-    else {
-	ts = rb_time_timespec(time);
-    }
-    t = time_new_internal(klass, ts.tv_sec, ts.tv_nsec);
-    if (CLASS_OF(time) == rb_cTime) {
-	struct time_object *tobj, *tobj2;
-
-	GetTimeval(time, tobj);
-	GetTimeval(t, tobj2);
-	tobj2->gmt = tobj->gmt;
-    }
-    return t;
-}
-
-static const char months[][4] = {
-    "jan", "feb", "mar", "apr", "may", "jun",
-    "jul", "aug", "sep", "oct", "nov", "dec",
-};
-
-static long
-obj2long(VALUE obj)
-{
-    if (TYPE(obj) == T_STRING) {
-	obj = rb_str_to_inum(obj, 10, Qfalse);
-    }
-
-    return NUM2LONG(obj);
-}
-
-static long
-obj2nsec(VALUE obj, long *nsec)
-{
-    struct timespec ts;
-
-    if (TYPE(obj) == T_STRING) {
-	obj = rb_str_to_inum(obj, 10, Qfalse);
-        *nsec = 0;
-        return NUM2LONG(obj);
-    }
-
-    ts = time_timespec(obj, 1);
-    *nsec = ts.tv_nsec;
-    return ts.tv_sec;
-}
-
-static long
-obj2long1000(VALUE obj)
-{
-    if (TYPE(obj) == T_STRING) {
-	obj = rb_str_to_inum(obj, 10, Qfalse);
-        return NUM2LONG(obj) * 1000;
-    }
-
-    return NUM2LONG(rb_funcall(obj, id_mul, 1, INT2FIX(1000)));
-}
-
-static void
-time_arg(int argc, VALUE *argv, struct tm *tm, long *nsec)
-{
-    VALUE v[8];
-    int i;
-    long year;
-
-    MEMZERO(tm, struct tm, 1);
-    *nsec = 0;
-    if (argc == 10) {
-	v[0] = argv[5];
-	v[1] = argv[4];
-	v[2] = argv[3];
-	v[3] = argv[2];
-	v[4] = argv[1];
-	v[5] = argv[0];
-	v[6] = Qnil;
-	tm->tm_isdst = RTEST(argv[8]) ? 1 : 0;
-    }
-    else {
-	rb_scan_args(argc, argv, "17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
-	/* v[6] may be usec or zone (parsedate) */
-	/* v[7] is wday (parsedate; ignored) */
-	tm->tm_wday = -1;
-	tm->tm_isdst = -1;
-    }
-
-    year = obj2long(v[0]);
-
-    if (0 <= year && year < 39) {
-        rb_warning("2 digits year is used: %ld", year);
-	year += 100;
-    }
-    else if (69 <= year && year < 139) {
-        rb_warning("2 or 3 digits year is used: %ld", year);
-    }
-    else {
-	year -= 1900;
-    }
-
-    tm->tm_year = year;
-
-    if (NIL_P(v[1])) {
-	tm->tm_mon = 0;
-    }
-    else {
-	VALUE s = rb_check_string_type(v[1]);
-	if (!NIL_P(s)) {
-	    tm->tm_mon = -1;
-	    for (i=0; i<12; i++) {
-		if (RSTRING_LEN(s) == 3 &&
-		    STRCASECMP(months[i], RSTRING_PTR(s)) == 0) {
-		    tm->tm_mon = i;
-		    break;
-		}
-	    }
-	    if (tm->tm_mon == -1) {
-		char c = RSTRING_PTR(s)[0];
-
-		if ('0' <= c && c <= '9') {
-		    tm->tm_mon = obj2long(s)-1;
-		}
-	    }
-	}
-	else {
-	    tm->tm_mon = obj2long(v[1])-1;
-	}
-    }
-    if (NIL_P(v[2])) {
-	tm->tm_mday = 1;
-    }
-    else {
-	tm->tm_mday = obj2long(v[2]);
-    }
-    tm->tm_hour = NIL_P(v[3])?0:obj2long(v[3]);
-    tm->tm_min  = NIL_P(v[4])?0:obj2long(v[4]);
-    if (!NIL_P(v[6]) && argc == 7) {
-        tm->tm_sec  = NIL_P(v[5])?0:obj2long(v[5]);
-        *nsec = obj2long1000(v[6]);
-    }
-    else {
-	/* when argc == 8, v[6] is timezone, but ignored */
-        tm->tm_sec  = NIL_P(v[5])?0:obj2nsec(v[5], nsec);
-    }
-
-    /* value validation */
-    if (
-	tm->tm_year != year ||
-#ifndef NEGATIVE_TIME_T
-	tm->tm_year < 69 ||
-#endif
-	   tm->tm_mon  < 0 || tm->tm_mon  > 11
-	|| tm->tm_mday < 1 || tm->tm_mday > 31
-	|| tm->tm_hour < 0 || tm->tm_hour > 24
-	|| (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0))
-	|| tm->tm_min  < 0 || tm->tm_min  > 59
-	|| tm->tm_sec  < 0 || tm->tm_sec  > 60)
-	rb_raise(rb_eArgError, "argument out of range");
-}
-
-static VALUE time_gmtime(VALUE, SEL);
-static VALUE time_localtime(VALUE, SEL);
-static VALUE time_get_tm(VALUE, int);
-
-static int
-leap_year_p(long y)
-{
-    return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
-}
-
-#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
-
-static time_t
-timegm_noleapsecond(struct tm *tm)
-{
-    static int common_year_yday_offset[] = {
-	-1,
-	-1 + 31,
-	-1 + 31 + 28,
-	-1 + 31 + 28 + 31,
-	-1 + 31 + 28 + 31 + 30,
-	-1 + 31 + 28 + 31 + 30 + 31,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
-	-1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
-	  /* 1    2    3    4    5    6    7    8    9    10   11 */
-    };
-    static int leap_year_yday_offset[] = {
-	-1,
-	-1 + 31,
-	-1 + 31 + 29,
-	-1 + 31 + 29 + 31,
-	-1 + 31 + 29 + 31 + 30,
-	-1 + 31 + 29 + 31 + 30 + 31,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
-	-1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
-	  /* 1    2    3    4    5    6    7    8    9    10   11 */
-    };
-
-    long tm_year = tm->tm_year;
-    int tm_yday = tm->tm_mday;
-    if (leap_year_p(tm_year + 1900))
-	tm_yday += leap_year_yday_offset[tm->tm_mon];
-    else
-	tm_yday += common_year_yday_offset[tm->tm_mon];
-
-    /*
-     *  `Seconds Since the Epoch' in SUSv3:
-     *  tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
-     *  (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
-     *  ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
-     */
-    return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
-	   (time_t)(tm_yday +
-		    (tm_year-70)*365 +
-		    DIV(tm_year-69,4) -
-		    DIV(tm_year-1,100) +
-		    DIV(tm_year+299,400))*86400;
-}
-
-static int
-tmcmp(struct tm *a, struct tm *b)
-{
-    if (a->tm_year != b->tm_year)
-	return a->tm_year < b->tm_year ? -1 : 1;
-    else if (a->tm_mon != b->tm_mon)
-	return a->tm_mon < b->tm_mon ? -1 : 1;
-    else if (a->tm_mday != b->tm_mday)
-	return a->tm_mday < b->tm_mday ? -1 : 1;
-    else if (a->tm_hour != b->tm_hour)
-	return a->tm_hour < b->tm_hour ? -1 : 1;
-    else if (a->tm_min != b->tm_min)
-	return a->tm_min < b->tm_min ? -1 : 1;
-    else if (a->tm_sec != b->tm_sec)
-	return a->tm_sec < b->tm_sec ? -1 : 1;
-    else
-        return 0;
-}
-
-#if SIZEOF_TIME_T == SIZEOF_LONG
-typedef unsigned long unsigned_time_t;
-#elif SIZEOF_TIME_T == SIZEOF_INT
-typedef unsigned int unsigned_time_t;
-#elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
-typedef unsigned LONG_LONG unsigned_time_t;
-#else
-# error cannot find integer type which size is same as time_t.
-#endif
-
-static time_t
-search_time_t(struct tm *tptr, int utc_p)
-{
-    time_t guess, guess_lo, guess_hi;
-    struct tm *tm, tm_lo, tm_hi;
-    int d, have_guess;
-    int find_dst;
-
-    find_dst = 0 < tptr->tm_isdst;
-
-#ifdef NEGATIVE_TIME_T
-    guess_lo = (time_t)~((unsigned_time_t)~(time_t)0 >> 1);
-#else
-    guess_lo = 0;
-#endif
-    guess_hi = ((time_t)-1) < ((time_t)0) ?
-	       (time_t)((unsigned_time_t)~(time_t)0 >> 1) :
-	       ~(time_t)0;
-
-    guess = timegm_noleapsecond(tptr);
-    tm = (utc_p ? gmtime : localtime)(&guess);
-    if (tm) {
-	d = tmcmp(tptr, tm);
-	if (d == 0) return guess;
-	if (d < 0) {
-	    guess_hi = guess;
-	    guess -= 24 * 60 * 60;
-	}
-	else {
-	    guess_lo = guess;
-	    guess += 24 * 60 * 60;
-	}
-	if (guess_lo < guess && guess < guess_hi &&
-	    (tm = (utc_p ? gmtime : localtime)(&guess)) != NULL) {
-	    d = tmcmp(tptr, tm);
-	    if (d == 0) return guess;
-	    if (d < 0)
-		guess_hi = guess;
-	    else
-		guess_lo = guess;
-	}
-    }
-
-    tm = (utc_p ? gmtime : localtime)(&guess_lo);
-    if (!tm) goto error;
-    d = tmcmp(tptr, tm);
-    if (d < 0) goto out_of_range;
-    if (d == 0) return guess_lo;
-    tm_lo = *tm;
-
-    tm = (utc_p ? gmtime : localtime)(&guess_hi);
-    if (!tm) goto error;
-    d = tmcmp(tptr, tm);
-    if (d > 0) goto out_of_range;
-    if (d == 0) return guess_hi;
-    tm_hi = *tm;
-
-    have_guess = 0;
-
-    while (guess_lo + 1 < guess_hi) {
-	/* there is a gap between guess_lo and guess_hi. */
-	unsigned long range = 0;
-	if (!have_guess) {
-	    int a, b;
-	    /*
-	      Try precious guess by a linear interpolation at first.
-	      `a' and `b' is a coefficient of guess_lo and guess_hi as:
-
-	        guess = (guess_lo * a + guess_hi * b) / (a + b)
-
-	      However this causes overflow in most cases, following assignment
-	      is used instead:
-
-		guess = guess_lo / d * a + (guess_lo % d) * a / d
-			+ guess_hi / d * b + (guess_hi % d) * b / d
-		where d = a + b
-
-	      To avoid overflow in this assignment, `d' is restricted to less than
-	      sqrt(2**31).  By this restriction and other reasons, the guess is
-	      not accurate and some error is expected.  `range' approximates 
-	      the maximum error.
-
-	      When these parameters are not suitable, i.e. guess is not within
-	      guess_lo and guess_hi, simple guess by binary search is used.
-	    */
-	    range = 366 * 24 * 60 * 60;
-	    a = (tm_hi.tm_year - tptr->tm_year);
-	    b = (tptr->tm_year - tm_lo.tm_year);
-	    /* 46000 is selected as `some big number less than sqrt(2**31)'. */
-	    if (a + b <= 46000 / 12) {
-		range = 31 * 24 * 60 * 60;
-		a *= 12;
-		b *= 12;
-		a += tm_hi.tm_mon - tptr->tm_mon;
-		b += tptr->tm_mon - tm_lo.tm_mon;
-		if (a + b <= 46000 / 31) {
-		    range = 24 * 60 * 60;
-		    a *= 31;
-		    b *= 31;
-		    a += tm_hi.tm_mday - tptr->tm_mday;
-		    b += tptr->tm_mday - tm_lo.tm_mday;
-		    if (a + b <= 46000 / 24) {
-			range = 60 * 60;
-			a *= 24;
-			b *= 24;
-			a += tm_hi.tm_hour - tptr->tm_hour;
-			b += tptr->tm_hour - tm_lo.tm_hour;
-			if (a + b <= 46000 / 60) {
-			    range = 60;
-			    a *= 60;
-			    b *= 60;
-			    a += tm_hi.tm_min - tptr->tm_min;
-			    b += tptr->tm_min - tm_lo.tm_min;
-			    if (a + b <= 46000 / 60) {
-				range = 1;
-				a *= 60;
-				b *= 60;
-				a += tm_hi.tm_sec - tptr->tm_sec;
-				b += tptr->tm_sec - tm_lo.tm_sec;
-			    }
-			}
-		    }
-		}
-	    }
-	    if (a <= 0) a = 1;
-	    if (b <= 0) b = 1;
-	    d = a + b;
-	    /*
-	      Although `/' and `%' may produce unexpected result with negative
-	      argument, it doesn't cause serious problem because there is a
-	      fail safe.
-	    */
-	    guess = guess_lo / d * a + (guess_lo % d) * a / d
-		    + guess_hi / d * b + (guess_hi % d) * b / d;
-	    have_guess = 1;
-	}
-
-	if (guess <= guess_lo || guess_hi <= guess) {
-	    /* Precious guess is invalid. try binary search. */ 
-	    guess = guess_lo / 2 + guess_hi / 2;
-	    if (guess <= guess_lo)
-		guess = guess_lo + 1;
-	    else if (guess >= guess_hi)
-		guess = guess_hi - 1;
-	    range = 0;
-	}
-
-	tm = (utc_p ? gmtime : localtime)(&guess);
-	if (!tm) goto error;
-	have_guess = 0;
-	
-	d = tmcmp(tptr, tm);
-	if (d < 0) {
-	    guess_hi = guess;
-	    tm_hi = *tm;
-	    if (range) {
-		guess = guess - range;
-		range = 0;
-		if (guess_lo < guess && guess < guess_hi)
-		    have_guess = 1;
-	    }
-	}
-	else if (d > 0) {
-	    guess_lo = guess;
-	    tm_lo = *tm;
-	    if (range) {
-		guess = guess + range;
-		range = 0;
-		if (guess_lo < guess && guess < guess_hi)
-		    have_guess = 1;
-	    }
-	}
-	else {
-	    if (!utc_p) {
-		/* If localtime is nonmonotonic, another result may exist. */
-		time_t guess2;
-		if (find_dst) {
-		    guess2 = guess - 2 * 60 * 60;
-		    tm = localtime(&guess2);
-		    if (tm) {
-			if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
-			    tptr->tm_min != tm->tm_min ||
-			    tptr->tm_sec != tm->tm_sec
-			) {
-			    guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
-				      (tm->tm_min - tptr->tm_min) * 60 +
-				      (tm->tm_sec - tptr->tm_sec);
-			    if (tptr->tm_mday != tm->tm_mday)
-				guess2 += 24 * 60 * 60;
-			    if (guess != guess2) {
-				tm = localtime(&guess2);
-				if (tmcmp(tptr, tm) == 0) {
-				    if (guess < guess2)
-					return guess;
-				    else
-					return guess2;
-				}
-			    }
-			}
-		    }
-		}
-		else {
-		    guess2 = guess + 2 * 60 * 60;
-		    tm = localtime(&guess2);
-		    if (tm) {
-			if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
-			    tptr->tm_min != tm->tm_min ||
-			    tptr->tm_sec != tm->tm_sec
-			) {
-			    guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
-				      (tm->tm_min - tptr->tm_min) * 60 +
-				      (tm->tm_sec - tptr->tm_sec);
-			    if (tptr->tm_mday != tm->tm_mday)
-				guess2 -= 24 * 60 * 60;
-			    if (guess != guess2) {
-				tm = localtime(&guess2);
-				if (tmcmp(tptr, tm) == 0) {
-				    if (guess < guess2)
-					return guess2;
-				    else
-					return guess;
-				}
-			    }
-			}
-		    }
-		}
-	    }
-	    return guess;
-	}
-    }
-    /* Given argument has no corresponding time_t. Let's outerpolation. */
-    if (tm_lo.tm_year == tptr->tm_year && tm_lo.tm_mon == tptr->tm_mon) {
-	return guess_lo +
-	       (tptr->tm_mday - tm_lo.tm_mday) * 24 * 60 * 60 +
-	       (tptr->tm_hour - tm_lo.tm_hour) * 60 * 60 +
-	       (tptr->tm_min - tm_lo.tm_min) * 60 +
-	       (tptr->tm_sec - tm_lo.tm_sec);
-    }
-    else if (tm_hi.tm_year == tptr->tm_year && tm_hi.tm_mon == tptr->tm_mon) {
-	return guess_hi +
-	       (tptr->tm_mday - tm_hi.tm_mday) * 24 * 60 * 60 +
-	       (tptr->tm_hour - tm_hi.tm_hour) * 60 * 60 +
-	       (tptr->tm_min - tm_hi.tm_min) * 60 +
-	       (tptr->tm_sec - tm_hi.tm_sec);
-    }
-
-  out_of_range:
-    rb_raise(rb_eArgError, "time out of range");
-
-  error:
-    rb_raise(rb_eArgError, "gmtime/localtime error");
-    return 0;			/* not reached */
-}
-
-static time_t
-make_time_t(struct tm *tptr, int utc_p)
-{
-    time_t t;
-#ifdef NEGATIVE_TIME_T
-    struct tm *tmp;
-#endif
-    struct tm buf;
-    buf = *tptr;
-    if (utc_p) {
-#if defined(HAVE_TIMEGM)
-	if ((t = timegm(&buf)) != -1)
-	    return t;
-#ifdef NEGATIVE_TIME_T
-	if ((tmp = gmtime(&t)) &&
-	    tptr->tm_year == tmp->tm_year &&
-	    tptr->tm_mon == tmp->tm_mon &&
-	    tptr->tm_mday == tmp->tm_mday &&
-	    tptr->tm_hour == tmp->tm_hour &&
-	    tptr->tm_min == tmp->tm_min &&
-	    tptr->tm_sec == tmp->tm_sec
-	)
-	    return t;
-#endif
-#endif
-	return search_time_t(&buf, utc_p);
-    }
-    else {
-#if defined(HAVE_MKTIME)
-	if ((t = mktime(&buf)) != -1)
-	    return t;
-#ifdef NEGATIVE_TIME_T
-	if ((tmp = localtime(&t)) &&
-	    tptr->tm_year == tmp->tm_year &&
-	    tptr->tm_mon == tmp->tm_mon &&
-	    tptr->tm_mday == tmp->tm_mday &&
-	    tptr->tm_hour == tmp->tm_hour &&
-	    tptr->tm_min == tmp->tm_min &&
-	    tptr->tm_sec == tmp->tm_sec
-	)
-            return t;
-#endif
-#endif
-	return search_time_t(&buf, utc_p);
-    }
-}
-
-static VALUE
-time_utc_or_local(int argc, VALUE *argv, int utc_p, VALUE klass)
-{
-    struct tm tm;
-    VALUE time;
-    long nsec;
-
-    time_arg(argc, argv, &tm, &nsec);
-    time = time_new_internal(klass, make_time_t(&tm, utc_p), nsec);
-    if (utc_p) return time_gmtime(time, 0);
-    return time_localtime(time, 0);
-}
-
-/*
- *  call-seq:
- *    Time.utc(year) => time
- *    Time.utc(year, month) => time
- *    Time.utc(year, month, day) => time
- *    Time.utc(year, month, day, hour) => time
- *    Time.utc(year, month, day, hour, min) => time
- *    Time.utc(year, month, day, hour, min, sec_with_frac) => time
- *    Time.utc(year, month, day, hour, min, sec, usec_with_frac) => time
- *    Time.utc(sec, min, hour, day, month, year, wday, yday, isdst, tz) => time
- *    Time.gm(year) => time
- *    Time.gm(year, month) => time
- *    Time.gm(year, month, day) => time
- *    Time.gm(year, month, day, hour) => time
- *    Time.gm(year, month, day, hour, min) => time
- *    Time.gm(year, month, day, hour, min, sec_with_frac) => time
- *    Time.gm(year, month, day, hour, min, sec, usec_with_frac) => time
- *    Time.gm(sec, min, hour, day, month, year, wday, yday, isdst, tz) => time
- *     
- *  Creates a time based on given values, interpreted as UTC (GMT). The
- *  year must be specified. Other values default to the minimum value
- *  for that field (and may be <code>nil</code> or omitted). Months may
- *  be specified by numbers from 1 to 12, or by the three-letter English
- *  month names. Hours are specified on a 24-hour clock (0..23). Raises
- *  an <code>ArgumentError</code> if any values are out of range. Will
- *  also accept ten arguments in the order output by
- *  <code>Time#to_a</code>.
- *  <i>sec_with_frac</i> and <i>usec_with_frac</i> can have a fractional part.
- *
- *     Time.utc(2000,"jan",1,20,15,1)  #=> 2000-01-01 20:15:01 UTC
- *     Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
- */
-static VALUE
-time_s_mkutc(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    return time_utc_or_local(argc, argv, Qtrue, klass);
-}
-
-/*
- *  call-seq:
- *   Time.local(year) => time
- *   Time.local(year, month) => time
- *   Time.local(year, month, day) => time
- *   Time.local(year, month, day, hour) => time
- *   Time.local(year, month, day, hour, min) => time
- *   Time.local(year, month, day, hour, min, sec_with_frac) => time
- *   Time.local(year, month, day, hour, min, sec, usec_with_frac) => time
- *   Time.local(sec, min, hour, day, month, year, wday, yday, isdst, tz) => time
- *   Time.mktime(year) => time
- *   Time.mktime(year, month) => time
- *   Time.mktime(year, month, day) => time
- *   Time.mktime(year, month, day, hour) => time
- *   Time.mktime(year, month, day, hour, min) => time
- *   Time.mktime(year, month, day, hour, min, sec_with_frac) => time
- *   Time.mktime(year, month, day, hour, min, sec, usec_with_frac) => time
- *   Time.mktime(sec, min, hour, day, month, year, wday, yday, isdst, tz) => time
- *  
- *  Same as <code>Time::gm</code>, but interprets the values in the
- *  local time zone.
- *     
- *     Time.local(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 -0600
- */
-
-static VALUE
-time_s_mktime(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    return time_utc_or_local(argc, argv, Qfalse, klass);
-}
-
-/*
- *  call-seq:
- *     time.to_i   => int
- *     time.tv_sec => int
- *  
- *  Returns the value of <i>time</i> as an integer number of seconds
- *  since the Epoch.
- *     
- *     t = Time.now
- *     "%10.5f" % t.to_f   #=> "1049896564.17839"
- *     t.to_i              #=> 1049896564
- */
-
-static VALUE
-time_to_i(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    return LONG2NUM(tobj->ts.tv_sec);
-}
-
-/*
- *  call-seq:
- *     time.to_f => float
- *  
- *  Returns the value of <i>time</i> as a floating point number of
- *  seconds since the Epoch.
- *     
- *     t = Time.now
- *     "%10.5f" % t.to_f   #=> "1049896564.13654"
- *     t.to_i              #=> 1049896564
- *
- *  Note that IEEE 754 double is not accurate enough to represent
- *  nanoseconds from the Epoch.
- */
-
-static double
-time_since_epoch(VALUE time)
-{
-    struct time_object *tobj;
-    GetTimeval(time, tobj);
-    return (double)tobj->ts.tv_sec + (double)tobj->ts.tv_nsec/1e9;
-}
-
-static VALUE
-time_to_f(VALUE time, SEL sel)
-{
-    return DOUBLE2NUM(time_since_epoch(time));
-}
-
-/*
- *  call-seq:
- *     time.usec    => int
- *     time.tv_usec => int
- *  
- *  Returns just the number of microseconds for <i>time</i>.
- *     
- *     t = Time.now        #=> 2007-11-19 08:03:26 -0600
- *     "%10.6f" % t.to_f   #=> "1195481006.775195"
- *     t.usec              #=> 775195
- */
-
-static VALUE
-time_usec(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    return LONG2NUM(tobj->ts.tv_nsec/1000);
-}
-
-/*
- *  call-seq:
- *     time.nsec    => int
- *     time.tv_nsec => int
- *  
- *  Returns just the number of nanoseconds for <i>time</i>.
- *     
- *     t = Time.now        #=> 2007-11-17 15:18:03 +0900
- *     "%10.9f" % t.to_f   #=> "1195280283.536151409"
- *     t.nsec              #=> 536151406
- *
- *  The lowest digit of to_f and nsec is different because
- *  IEEE 754 double is not accurate enough to represent
- *  nanoseconds from the Epoch.
- *  The accurate value is returned by nsec.
- */
-
-static VALUE
-time_nsec(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    return LONG2NUM(tobj->ts.tv_nsec);
-}
-
-/*
- *  call-seq:
- *     time <=> other_time => -1, 0, +1 
- *  
- *  Comparison---Compares <i>time</i> with <i>other_time</i>.
- *     
- *     t = Time.now       #=> 2007-11-19 08:12:12 -0600
- *     t2 = t + 2592000   #=> 2007-12-19 08:12:12 -0600
- *     t <=> t2           #=> -1
- *     t2 <=> t           #=> 1
- *     
- *     t = Time.now       #=> 2007-11-19 08:13:38 -0600
- *     t2 = t + 0.1       #=> 2007-11-19 08:13:38 -0600
- *     t.nsec             #=> 98222999
- *     t2.nsec            #=> 198222999
- *     t <=> t2           #=> -1
- *     t2 <=> t           #=> 1
- *     t <=> t            #=> 0
- */
-
-static VALUE
-time_cmp(VALUE time1, SEL sel, VALUE time2)
-{
-    struct time_object *tobj1, *tobj2;
-
-    GetTimeval(time1, tobj1);
-    if (CLASS_OF(time2) == rb_cTime) {
-	GetTimeval(time2, tobj2);
-	if (tobj1->ts.tv_sec == tobj2->ts.tv_sec) {
-	    if (tobj1->ts.tv_nsec == tobj2->ts.tv_nsec) return INT2FIX(0);
-	    if (tobj1->ts.tv_nsec > tobj2->ts.tv_nsec) return INT2FIX(1);
-	    return INT2FIX(-1);
-	}
-	if (tobj1->ts.tv_sec > tobj2->ts.tv_sec) return INT2FIX(1);
-	return INT2FIX(-1);
-    }
-
-    return Qnil;
-}
-
-/*
- * call-seq:
- *  time.eql?(other_time)
- *
- * Return <code>true</code> if <i>time</i> and <i>other_time</i> are
- * both <code>Time</code> objects with the same seconds and fractional
- * seconds.
- */
-
-static VALUE
-time_eql(VALUE time1, SEL sel, VALUE time2)
-{
-    struct time_object *tobj1, *tobj2;
-
-    GetTimeval(time1, tobj1);
-    if (CLASS_OF(time2) == rb_cTime) {
-	GetTimeval(time2, tobj2);
-	if (tobj1->ts.tv_sec == tobj2->ts.tv_sec) {
-	    if (tobj1->ts.tv_nsec == tobj2->ts.tv_nsec) return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     time.utc? => true or false
- *     time.gmt? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents a time in UTC
- *  (GMT).
- *     
- *     t = Time.now                        #=> 2007-11-19 08:15:23 -0600
- *     t.utc?                              #=> false
- *     t = Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
- *     t.utc?                              #=> true
- *
- *     t = Time.now                        #=> 2007-11-19 08:16:03 -0600
- *     t.gmt?                              #=> false
- *     t = Time.gm(2000,1,1,20,15,1)       #=> 2000-01-01 20:15:01 UTC
- *     t.gmt?                              #=> true
- */
-
-static VALUE
-time_utc_p(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->gmt) return Qtrue;
-    return Qfalse;
-}
-
-/*
- * call-seq:
- *   time.hash   => fixnum
- *
- * Return a hash code for this time object.
- */
-
-static VALUE
-time_hash(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    long hash;
-
-    GetTimeval(time, tobj);
-    hash = tobj->ts.tv_sec ^ tobj->ts.tv_nsec;
-    return LONG2FIX(hash);
-}
-
-/* :nodoc: */
-static VALUE
-time_init_copy(VALUE copy, SEL sel, VALUE time)
-{
-    struct time_object *tobj, *tcopy;
-
-    if (copy == time) return copy;
-    time_modify(copy);
-    if (CLASS_OF(time) != rb_cTime) {
-	rb_raise(rb_eTypeError, "wrong argument type");
-    }
-    GetTimeval(time, tobj);
-    GetTimeval(copy, tcopy);
-    MEMCPY(tcopy, tobj, struct time_object, 1);
-
-    return copy;
-}
-
-static VALUE
-time_dup(VALUE time)
-{
-    VALUE dup = time_s_alloc(CLASS_OF(time), 0);
-    time_init_copy(dup, 0, time);
-    return dup;
-}
-
-/*
- *  call-seq:
- *     time.localtime => time
- *  
- *  Converts <i>time</i> to local time (using the local time zone in
- *  effect for this process) modifying the receiver.
- *     
- *     t = Time.gm(2000, "jan", 1, 20, 15, 1)  #=> 2000-01-01 20:15:01 UTC
- *     t.gmt?                                  #=> true
- *     t.localtime                             #=> 2000-01-01 14:15:01 -0600
- *     t.gmt?                                  #=> false
- */
-
-static VALUE
-time_localtime(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    struct tm *tm_tmp;
-    time_t t;
-
-    GetTimeval(time, tobj);
-    if (!tobj->gmt) {
-	if (tobj->tm_got)
-	    return time;
-    }
-    else {
-	time_modify(time);
-    }
-    t = tobj->ts.tv_sec;
-    tm_tmp = localtime(&t);
-    if (!tm_tmp)
-	rb_raise(rb_eArgError, "localtime error");
-    tobj->tm = *tm_tmp;
-    tobj->tm_got = 1;
-    tobj->gmt = 0;
-    return time;
-}
-
-/*
- *  call-seq:
- *     time.gmtime    => time
- *     time.utc       => time
- *  
- *  Converts <i>time</i> to UTC (GMT), modifying the receiver.
- *     
- *     t = Time.now   #=> 2007-11-19 08:18:31 -0600
- *     t.gmt?         #=> false
- *     t.gmtime       #=> 2007-11-19 14:18:31 UTC
- *     t.gmt?         #=> true
- *
- *     t = Time.now   #=> 2007-11-19 08:18:51 -0600
- *     t.utc?         #=> false
- *     t.utc          #=> 2007-11-19 14:18:51 UTC
- *     t.utc?         #=> true
- */
-
-static VALUE
-time_gmtime(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    struct tm *tm_tmp;
-    time_t t;
-
-    GetTimeval(time, tobj);
-    if (tobj->gmt) {
-	if (tobj->tm_got)
-	    return time;
-    }
-    else {
-	time_modify(time);
-    }
-    t = tobj->ts.tv_sec;
-    tm_tmp = gmtime(&t);
-    if (!tm_tmp)
-	rb_raise(rb_eArgError, "gmtime error");
-    tobj->tm = *tm_tmp;
-    tobj->tm_got = 1;
-    tobj->gmt = 1;
-    return time;
-}
-
-/*
- *  call-seq:
- *     time.getlocal => new_time
- *  
- *  Returns a new <code>new_time</code> object representing <i>time</i> in
- *  local time (using the local time zone in effect for this process).
- *     
- *     t = Time.gm(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
- *     t.gmt?                          #=> true
- *     l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
- *     l.gmt?                          #=> false
- *     t == l                          #=> true
- */
-
-static VALUE
-time_getlocaltime(VALUE time, SEL sel)
-{
-    return time_localtime(time_dup(time), 0);
-}
-
-/*
- *  call-seq:
- *     time.getgm  => new_time
- *     time.getutc => new_time
- *  
- *  Returns a new <code>new_time</code> object representing <i>time</i> in
- *  UTC.
- *     
- *     t = Time.local(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 -0600
- *     t.gmt?                             #=> false
- *     y = t.getgm                        #=> 2000-01-02 02:15:01 UTC
- *     y.gmt?                             #=> true
- *     t == y                             #=> true
- */
-
-static VALUE
-time_getgmtime(VALUE time, SEL sel)
-{
-    return time_gmtime(time_dup(time), 0);
-}
-
-static VALUE
-time_get_tm(VALUE time, int gmt)
-{
-    if (gmt) return time_gmtime(time, 0);
-    return time_localtime(time, 0);
-}
-
-/*
- *  call-seq:
- *     time.asctime => string
- *     time.ctime   => string
- *  
- *  Returns a canonical string representation of <i>time</i>.
- *     
- *     Time.now.asctime   #=> "Wed Apr  9 08:56:03 2003"
- */
-
-static VALUE
-time_asctime(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    char *s;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    s = asctime(&tobj->tm);
-    if (s[24] == '\n') s[24] = '\0';
-
-    return rb_str_new2(s);
-}
-
-/*
- *  call-seq:
- *     time.inspect => string
- *     time.to_s    => string
- *  
- *  Returns a string representing <i>time</i>. Equivalent to calling
- *  <code>Time#strftime</code> with a format string of
- *  ``<code>%Y-%m-%d</code> <code>%H:%M:%S</code> <code>%z</code>''
- *  for a local time and
- *  ``<code>%Y-%m-%d</code> <code>%H:%M:%S</code> <code>UTC</code>''
- *  for a UTC time.
- *     
- *     Time.now.to_s       #=> "2007-10-05 16:09:51 +0900"
- *     Time.now.utc.to_s   #=> "2007-10-05 07:09:51 UTC"
- */
-
-static VALUE
-time_to_s(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    char buf[128];
-    int len;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    if (tobj->gmt == 1) {
-	len = strftime(buf, 128, "%Y-%m-%d %H:%M:%S UTC", &tobj->tm);
-    }
-    else {
-	long off;
-	char sign = '+';
-#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
-	off = tobj->tm.tm_gmtoff;
-#else
-	VALUE tmp = time_utc_offset(time, 0);
-	off = NUM2INT(tmp);
-#endif
-	if (off < 0) {
-	    sign = '-';
-	    off = -off;
-	}
-	len = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S ", &tobj->tm);
-        len += snprintf(buf+len, sizeof(buf)-len, "%c%02d%02d", sign,
-                        (int)(off/3600), (int)(off%3600/60));
-    }
-    return rb_str_new(buf, len);
-}
-
-static VALUE
-time_add(struct time_object *tobj, VALUE offset, int sign)
-{
-    double v = NUM2DBL(offset);
-    double f, d;
-    unsigned_time_t sec_off;
-    time_t sec;
-    long nsec_off, nsec;
-    VALUE result;
-
-    if (v < 0) {
-	v = -v;
-	sign = -sign;
-    }
-    d = modf(v, &f);
-    sec_off = (unsigned_time_t)f;
-    if (f != (double)sec_off)
-	rb_raise(rb_eRangeError, "time %s %f out of Time range",
-		 sign < 0 ? "-" : "+", v);
-    nsec_off = (long)(d*1e9+0.5);
-
-    if (sign < 0) {
-	sec = tobj->ts.tv_sec - sec_off;
-	nsec = tobj->ts.tv_nsec - nsec_off;
-	if (sec > tobj->ts.tv_sec)
-	    rb_raise(rb_eRangeError, "time - %f out of Time range", v);
-    }
-    else {
-	sec = tobj->ts.tv_sec + sec_off;
-	nsec = tobj->ts.tv_nsec + nsec_off;
-	if (sec < tobj->ts.tv_sec)
-	    rb_raise(rb_eRangeError, "time + %f out of Time range", v);
-    }
-    result = rb_time_nano_new(sec, nsec);
-    if (tobj->gmt) {
-	GetTimeval(result, tobj);
-	tobj->gmt = 1;
-    }
-    return result;
-}
-
-/*
- *  call-seq:
- *     time + numeric => time
- *  
- *  Addition---Adds some number of seconds (possibly fractional) to
- *  <i>time</i> and returns that value as a new time.
- *     
- *     t = Time.now         #=> 2007-11-19 08:22:21 -0600
- *     t + (60 * 60 * 24)   #=> 2007-11-20 08:22:21 -0600
- */
-
-static VALUE
-time_plus(VALUE time1, SEL sel, VALUE time2)
-{
-    struct time_object *tobj;
-    GetTimeval(time1, tobj);
-
-    if (CLASS_OF(time2) == rb_cTime) {
-	rb_raise(rb_eTypeError, "time + time?");
-    }
-    return time_add(tobj, time2, 1);
-}
-
-/*
- *  call-seq:
- *     time - other_time => float
- *     time - numeric    => time
- *  
- *  Difference---Returns a new time that represents the difference
- *  between two times, or subtracts the given number of seconds in
- *  <i>numeric</i> from <i>time</i>.
- *     
- *     t = Time.now       #=> 2007-11-19 08:23:10 -0600
- *     t2 = t + 2592000   #=> 2007-12-19 08:23:10 -0600
- *     t2 - t             #=> 2592000.0
- *     t2 - 2592000       #=> 2007-11-19 08:23:10 -0600
- */
-
-static VALUE
-time_minus(VALUE time1, SEL sel, VALUE time2)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time1, tobj);
-    if (CLASS_OF(time2) == rb_cTime) {
-	struct time_object *tobj2;
-	double f;
-
-	GetTimeval(time2, tobj2);
-        if (tobj->ts.tv_sec < tobj2->ts.tv_sec)
-            f = -(double)(unsigned_time_t)(tobj2->ts.tv_sec - tobj->ts.tv_sec);
-        else
-            f = (double)(unsigned_time_t)(tobj->ts.tv_sec - tobj2->ts.tv_sec);
-	f += ((double)tobj->ts.tv_nsec - (double)tobj2->ts.tv_nsec)*1e-9;
-
-	return DOUBLE2NUM(f);
-    }
-    return time_add(tobj, time2, -1);
-}
-
-/*
- * call-seq:
- *   time.succ   => new_time
- *
- * Return a new time object, one second later than <code>time</code>.
- *
- *     t = Time.now       #=> 2007-11-19 08:23:57 -0600
- *     t.succ             #=> 2007-11-19 08:23:58 -0600
- */
-
-static VALUE
-time_succ(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-    int gmt;
-
-    GetTimeval(time, tobj);
-    gmt = tobj->gmt;
-    time = rb_time_nano_new(tobj->ts.tv_sec + 1, tobj->ts.tv_nsec);
-    GetTimeval(time, tobj);
-    tobj->gmt = gmt;
-    return time;
-}
-
-VALUE
-rb_time_succ(VALUE time)
-{
-  return time_succ(time, 0);
-}
-
-/*
- *  call-seq:
- *     time.sec => fixnum
- *  
- *  Returns the second of the minute (0..60)<em>[Yes, seconds really can
- *  range from zero to 60. This allows the system to inject leap seconds
- *  every now and then to correct for the fact that years are not really
- *  a convenient number of hours long.]</em> for <i>time</i>.
- *     
- *     t = Time.now   #=> 2007-11-19 08:25:02 -0600
- *     t.sec          #=> 2
- */
-
-static VALUE
-time_sec(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_sec);
-}
-
-/*
- *  call-seq:
- *     time.min => fixnum
- *  
- *  Returns the minute of the hour (0..59) for <i>time</i>.
- *     
- *     t = Time.now   #=> 2007-11-19 08:25:51 -0600
- *     t.min          #=> 25
- */
-
-static VALUE
-time_min(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_min);
-}
-
-/*
- *  call-seq:
- *     time.hour => fixnum
- *  
- *  Returns the hour of the day (0..23) for <i>time</i>.
- *     
- *     t = Time.now   #=> 2007-11-19 08:26:20 -0600
- *     t.hour         #=> 8
- */
-
-static VALUE
-time_hour(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_hour);
-}
-
-/*
- *  call-seq:
- *     time.day  => fixnum
- *     time.mday => fixnum
- *  
- *  Returns the day of the month (1..n) for <i>time</i>.
- *     
- *     t = Time.now   #=> 2007-11-19 08:27:03 -0600
- *     t.day          #=> 19
- *     t.mday         #=> 19
- */
-
-static VALUE
-time_mday(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_mday);
-}
-
-/*
- *  call-seq:
- *     time.mon   => fixnum
- *     time.month => fixnum
- *  
- *  Returns the month of the year (1..12) for <i>time</i>.
- *     
- *     t = Time.now   #=> 2007-11-19 08:27:30 -0600
- *     t.mon          #=> 11
- *     t.month        #=> 11
- */
-
-static VALUE
-time_mon(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_mon+1);
-}
-
-/*
- *  call-seq:
- *     time.year => fixnum
- *  
- *  Returns the year for <i>time</i> (including the century).
- *     
- *     t = Time.now   #=> 2007-11-19 08:27:51 -0600
- *     t.year         #=> 2007
- */
-
-static VALUE
-time_year(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return LONG2NUM((long)tobj->tm.tm_year+1900);
-}
-
-/*
- *  call-seq:
- *     time.wday => fixnum
- *  
- *  Returns an integer representing the day of the week, 0..6, with
- *  Sunday == 0.
- *     
- *     t = Time.now   #=> 2007-11-20 02:35:35 -0600
- *     t.wday         #=> 2
- *     t.sunday?      #=> false
- *     t.monday?      #=> false
- *     t.tuesday?     #=> true
- *     t.wednesday?   #=> false
- *     t.thursday?    #=> false
- *     t.friday?      #=> false
- *     t.saturday?    #=> false
- */
-
-static VALUE
-time_wday(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_wday);
-}
-
-#define wday_p(n) {\
-    struct time_object *tobj;\
-    GetTimeval(time, tobj);\
-    if (tobj->tm_got == 0) {\
-	time_get_tm(time, tobj->gmt);\
-    }\
-    return (tobj->tm.tm_wday == (n)) ? Qtrue : Qfalse;\
-}
-
-/*
- *  call-seq:
- *     time.sunday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Sunday.
- *     
- *     t = Time.local(1990, 4, 1)       #=> 1990-04-01 00:00:00 -0600
- *     t.sunday?                        #=> true
- */
-
-static VALUE
-time_sunday(VALUE time, SEL sel)
-{
-    wday_p(0);
-}
-
-/*
- *  call-seq:
- *     time.monday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Monday.
- *
- *     t = Time.local(2003, 8, 4)       #=> 2003-08-04 00:00:00 -0500
- *     p t.monday?                      #=> true
- */
-
-static VALUE
-time_monday(VALUE time, SEL sel)
-{
-    wday_p(1);
-}
-
-/*
- *  call-seq:
- *     time.tuesday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Tuesday.
- *
- *     t = Time.local(1991, 2, 19)      #=> 1991-02-19 00:00:00 -0600
- *     p t.tuesday?                     #=> true
- */
-
-static VALUE
-time_tuesday(VALUE time, SEL sel)
-{
-    wday_p(2);
-}
-
-/*
- *  call-seq:
- *     time.wednesday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Wednesday.
- *
- *     t = Time.local(1993, 2, 24)      #=> 1993-02-24 00:00:00 -0600
- *     p t.wednesday?                   #=> true
- */
-
-static VALUE
-time_wednesday(VALUE time, SEL sel)
-{
-    wday_p(3);
-}
-
-/*
- *  call-seq:
- *     time.thursday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Thursday.
- *
- *     t = Time.local(1995, 12, 21)     #=> 1995-12-21 00:00:00 -0600
- *     p t.thursday?                    #=> true
- */
-
-static VALUE
-time_thursday(VALUE time, SEL sel)
-{
-    wday_p(4);
-}
-
-/*
- *  call-seq:
- *     time.friday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Friday.
- *
- *     t = Time.local(1987, 12, 18)     #=> 1987-12-18 00:00:00 -0600
- *     t.friday?                        #=> true
- */
-
-static VALUE
-time_friday(VALUE time, SEL sel)
-{
-    wday_p(5);
-}
-
-/*
- *  call-seq:
- *     time.saturday? => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> represents Saturday.
- *
- *     t = Time.local(2006, 6, 10)      #=> 2006-06-10 00:00:00 -0500
- *     t.saturday?                      #=> true
- */
-
-static VALUE
-time_saturday(VALUE time, SEL sel)
-{
-    wday_p(6);
-}
-
-/*
- *  call-seq:
- *     time.yday => fixnum
- *  
- *  Returns an integer representing the day of the year, 1..366.
- *     
- *     t = Time.now   #=> 2007-11-19 08:32:31 -0600
- *     t.yday         #=> 323
- */
-
-static VALUE
-time_yday(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return INT2FIX(tobj->tm.tm_yday+1);
-}
-
-/*
- *  call-seq:
- *     time.isdst => true or false
- *     time.dst?  => true or false
- *  
- *  Returns <code>true</code> if <i>time</i> occurs during Daylight
- *  Saving Time in its time zone.
- *     
- *   # CST6CDT:
- *     Time.local(2000, 1, 1).zone    #=> "CST"
- *     Time.local(2000, 1, 1).isdst   #=> false
- *     Time.local(2000, 1, 1).dst?    #=> false
- *     Time.local(2000, 7, 1).zone    #=> "CDT"
- *     Time.local(2000, 7, 1).isdst   #=> true
- *     Time.local(2000, 7, 1).dst?    #=> true
- *
- *   # Asia/Tokyo:
- *     Time.local(2000, 1, 1).zone    #=> "JST"
- *     Time.local(2000, 1, 1).isdst   #=> false
- *     Time.local(2000, 1, 1).dst?    #=> false
- *     Time.local(2000, 7, 1).zone    #=> "JST"
- *     Time.local(2000, 7, 1).isdst   #=> false
- *     Time.local(2000, 7, 1).dst?    #=> false
- */
-
-static VALUE
-time_isdst(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return tobj->tm.tm_isdst?Qtrue:Qfalse;
-}
-
-/*
- *  call-seq:
- *     time.zone => string
- *  
- *  Returns the name of the time zone used for <i>time</i>. As of Ruby
- *  1.8, returns ``UTC'' rather than ``GMT'' for UTC times.
- *     
- *     t = Time.gm(2000, "jan", 1, 20, 15, 1)
- *     t.zone   #=> "UTC"
- *     t = Time.local(2000, "jan", 1, 20, 15, 1)
- *     t.zone   #=> "CST"
- */
-
-static VALUE
-time_zone(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-#if !defined(HAVE_TM_ZONE) && (!defined(HAVE_TZNAME) || !defined(HAVE_DAYLIGHT))
-    char buf[64];
-    int len;
-#endif
-    
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-
-    if (tobj->gmt == 1) {
-	return rb_str_new2("UTC");
-    }
-#if defined(HAVE_TM_ZONE)
-    return rb_str_new2(tobj->tm.tm_zone);
-#elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
-    return rb_str_new2(tzname[daylight && tobj->tm.tm_isdst]);
-#else
-    len = strftime(buf, 64, "%Z", &tobj->tm);
-    return rb_str_new(buf, len);
-#endif
-}
-
-/*
- *  call-seq:
- *     time.gmt_offset => fixnum
- *     time.gmtoff     => fixnum
- *     time.utc_offset => fixnum
- *  
- *  Returns the offset in seconds between the timezone of <i>time</i>
- *  and UTC.
- *     
- *     t = Time.gm(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
- *     t.gmt_offset                    #=> 0
- *     l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
- *     l.gmt_offset                    #=> -21600
- */
-
-static VALUE
-time_utc_offset(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-
-    if (tobj->gmt == 1) {
-	return INT2FIX(0);
-    }
-    else {
-#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
-	return INT2NUM(tobj->tm.tm_gmtoff);
-#else
-	struct tm *u, *l;
-	time_t t;
-	long off;
-	l = &tobj->tm;
-	t = tobj->ts.tv_sec;
-	u = gmtime(&t);
-	if (!u)
-	    rb_raise(rb_eArgError, "gmtime error");
-	if (l->tm_year != u->tm_year)
-	    off = l->tm_year < u->tm_year ? -1 : 1;
-	else if (l->tm_mon != u->tm_mon)
-	    off = l->tm_mon < u->tm_mon ? -1 : 1;
-	else if (l->tm_mday != u->tm_mday)
-	    off = l->tm_mday < u->tm_mday ? -1 : 1;
-	else
-	    off = 0;
-	off = off * 24 + l->tm_hour - u->tm_hour;
-	off = off * 60 + l->tm_min - u->tm_min;
-	off = off * 60 + l->tm_sec - u->tm_sec;
-	return LONG2FIX(off);
-#endif
-    }
-}
-
-/*
- *  call-seq:
- *     time.to_a => array
- *  
- *  Returns a ten-element <i>array</i> of values for <i>time</i>:
- *  {<code>[ sec, min, hour, day, month, year, wday, yday, isdst, zone
- *  ]</code>}. See the individual methods for an explanation of the
- *  valid ranges of each value. The ten elements can be passed directly
- *  to <code>Time::utc</code> or <code>Time::local</code> to create a
- *  new <code>Time</code>.
- *     
- *     t = Time.now     #=> 2007-11-19 08:36:01 -0600
- *     now = t.to_a     #=> [1, 36, 8, 19, 11, 2007, 1, 323, false, "CST"]
- */
-
-static VALUE
-time_to_a(VALUE time, SEL sel)
-{
-    struct time_object *tobj;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    return rb_ary_new3(10,
-		    INT2FIX(tobj->tm.tm_sec),
-		    INT2FIX(tobj->tm.tm_min),
-		    INT2FIX(tobj->tm.tm_hour),
-		    INT2FIX(tobj->tm.tm_mday),
-		    INT2FIX(tobj->tm.tm_mon+1),
-		    LONG2NUM((long)tobj->tm.tm_year+1900),
-		    INT2FIX(tobj->tm.tm_wday),
-		    INT2FIX(tobj->tm.tm_yday+1),
-		    tobj->tm.tm_isdst?Qtrue:Qfalse,
-		    time_zone(time, 0));
-}
-
-#define SMALLBUF 100
-static int
-rb_strftime(char **buf, const char *format, struct tm *time)
-{
-    int size, len, flen;
-
-    (*buf)[0] = '\0';
-    flen = strlen(format);
-    if (flen == 0) {
-	return 0;
-    }
-    errno = 0;
-    len = strftime(*buf, SMALLBUF, format, time);
-    if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
-    for (size=1024; ; size*=2) {
-	*buf = xmalloc(size);
-	(*buf)[0] = '\0';
-	len = strftime(*buf, size, format, time);
-	/*
-	 * buflen can be zero EITHER because there's not enough
-	 * room in the string, or because the control command
-	 * goes to the empty string. Make a reasonable guess that
-	 * if the buffer is 1024 times bigger than the length of the
-	 * format string, it's not failing for lack of room.
-	 */
-	if (len > 0 || size >= 1024 * flen) return len;
-	free(*buf);
-    }
-    /* not reached */
-}
-
-/*
- *  call-seq:
- *     time.strftime( string ) => string
- *  
- *  Formats <i>time</i> according to the directives in the given format
- *  string. Any text not listed as a directive will be passed through
- *  to the output string.
- *
- *  Format meaning:
- *    %a - The abbreviated weekday name (``Sun'')
- *    %A - The  full  weekday  name (``Sunday'')
- *    %b - The abbreviated month name (``Jan'')
- *    %B - The  full  month  name (``January'')
- *    %c - The preferred local date and time representation
- *    %d - Day of the month (01..31)
- *    %H - Hour of the day, 24-hour clock (00..23)
- *    %I - Hour of the day, 12-hour clock (01..12)
- *    %j - Day of the year (001..366)
- *    %m - Month of the year (01..12)
- *    %M - Minute of the hour (00..59)
- *    %p - Meridian indicator (``AM''  or  ``PM'')
- *    %S - Second of the minute (00..60)
- *    %U - Week  number  of the current year,
- *            starting with the first Sunday as the first
- *            day of the first week (00..53)
- *    %W - Week  number  of the current year,
- *            starting with the first Monday as the first
- *            day of the first week (00..53)
- *    %w - Day of the week (Sunday is 0, 0..6)
- *    %x - Preferred representation for the date alone, no time
- *    %X - Preferred representation for the time alone, no date
- *    %y - Year without a century (00..99)
- *    %Y - Year with century
- *    %Z - Time zone name
- *    %% - Literal ``%'' character
- *     
- *     t = Time.now                        #=> 2007-11-19 08:37:48 -0600
- *     t.strftime("Printed on %m/%d/%Y")   #=> "Printed on 11/19/2007"
- *     t.strftime("at %I:%M%p")            #=> "at 08:37AM"
- */
-
-static VALUE
-time_strftime(VALUE time, SEL sel, VALUE format)
-{
-    struct time_object *tobj;
-    char buffer[SMALLBUF], *buf = buffer;
-    const char *fmt;
-    long len;
-    VALUE str;
-
-    GetTimeval(time, tobj);
-    if (tobj->tm_got == 0) {
-	time_get_tm(time, tobj->gmt);
-    }
-    StringValue(format);
-    if (!rb_enc_str_asciicompat_p(format)) {
-	rb_raise(rb_eArgError, "format should have ASCII compatible encoding");
-    }
-    format = rb_str_new4(format);
-    fmt = RSTRING_PTR(format);
-    len = RSTRING_LEN(format);
-    if (len == 0) {
-	rb_warning("strftime called with empty format string");
-    }
-    else if (strlen(fmt) < len) {
-	/* Ruby string may contain \0's. */
-	const char *p = fmt, *pe = fmt + len;
-
-	str = rb_str_new(0, 0);
-	while (p < pe) {
-	    len = rb_strftime(&buf, p, &tobj->tm);
-	    rb_str_cat(str, buf, len);
-	    p += strlen(p);
-	    if (buf != buffer) {
-		xfree(buf);
-		buf = buffer;
-	    }
-	    for (fmt = p; p < pe && !*p; ++p);
-	    if (p > fmt) rb_str_cat(str, fmt, p - fmt);
-	}
-	return str;
-    }
-    else {
-	len = rb_strftime(&buf, RSTRING_PTR(format), &tobj->tm);
-    }
-    str = rb_str_new(buf, len);
-    if (buf != buffer) xfree(buf);
-    return str;
-}
-
-/*
- * undocumented
- */
-
-static VALUE
-time_mdump(VALUE time)
-{
-    struct time_object *tobj;
-    struct tm *tm;
-    unsigned long p, s;
-    UInt8 buf[8];
-    time_t t;
-    int nsec;
-    int i;
-    VALUE str;
-
-    GetTimeval(time, tobj);
-
-    t = tobj->ts.tv_sec;
-    tm = gmtime(&t);
-
-    if ((tm->tm_year & 0xffff) != tm->tm_year)
-        rb_raise(rb_eArgError, "year too big to marshal: %ld", (long)tm->tm_year);
-
-    p = 0x1UL        << 31 | /*  1 */
-	tobj->gmt    << 30 | /*  1 */
-	tm->tm_year  << 14 | /* 16 */
-	tm->tm_mon   << 10 | /*  4 */
-	tm->tm_mday  <<  5 | /*  5 */
-	tm->tm_hour;         /*  5 */
-    s = tm->tm_min   << 26 | /*  6 */
-	tm->tm_sec   << 20 | /*  6 */
-	tobj->ts.tv_nsec / 1000;    /* 20 */
-    nsec = tobj->ts.tv_nsec % 1000;
-
-    for (i=0; i<4; i++) {
-	buf[i] = p & 0xff;
-	p = RSHIFT(p, 8);
-    }
-    for (i=4; i<8; i++) {
-	buf[i] = s & 0xff;
-	s = RSHIFT(s, 8);
-    }
-
-    str = rb_bstr_new_with_data(buf, 8);
-    rb_copy_generic_ivar(str, time);
-    if (nsec) {
-        /*
-         * submicro is formatted in fixed-point packed BCD (without sign).
-         * It represent digits under microsecond.
-         * For nanosecond resolution, 3 digits (2 bytes) are used.
-         * However it can be longer.
-         * Extra digits are ignored for loading.
-         */
-        UInt8 buf[2];
-        int len = sizeof(buf);
-        buf[1] = (nsec % 10) << 4;
-        nsec /= 10;
-        buf[0] = nsec % 10;
-        nsec /= 10;
-        buf[0] |= (nsec % 10) << 4;
-        if (buf[1] == 0)
-            len = 1;
-        rb_ivar_set(str, id_submicro, rb_bstr_new_with_data(buf, len));
-    }
-    return str;
-}
-
-/*
- * call-seq:
- *   time._dump   => string
- *
- * Dump _time_ for marshaling.
- */
-
-static VALUE
-time_dump(VALUE time, SEL sel, int argc, VALUE *argv)
-{
-    VALUE str;
-
-    rb_scan_args(argc, argv, "01", 0);
-    str = time_mdump(time); 
-
-    return str;
-}
-
-/*
- * undocumented
- */
-
-static VALUE
-time_mload(VALUE time, VALUE str)
-{
-    struct time_object *tobj;
-    time_t sec;
-    long usec;
-    struct tm tm;
-    int gmt;
-    long nsec;
-
-    time_modify(time);
-
-    VALUE submicro = rb_attr_get(str, id_submicro);
-#if 0 // TODO
-    if (submicro != Qnil) {
-        st_delete(rb_generic_ivar_table(str), (st_data_t*)&id_submicro, 0);
-    }
-#endif
-    rb_copy_generic_ivar(time, str);
-
-    StringValue(str);
-    str = rb_str_bstr(str);
-
-    uint8_t *buf = rb_bstr_bytes(str);
-    const long buflen = rb_bstr_length(str); 
-    if (buflen != 8 && buflen != 9) {
-	rb_raise(rb_eTypeError, "marshaled time format differ");
-    }
-
-    unsigned long p = 0;
-    unsigned long s = 0;
-    for (int i = 0; i < 4; i++) {
-	p |= buf[i] << (8 * i);
-    }
-    for (int i = 4; i < 8; i++) {
-	s |= buf[i] << (8 * (i - 4));
-    }
-
-    if ((p & (1UL<<31)) == 0) {
-        gmt = 0;
-	sec = p;
-	usec = s;
-        nsec = usec * 1000;
-    }
-    else {
-	p &= ~(1UL<<31);
-	gmt        = (p >> 30) & 0x1;
-	tm.tm_year = (p >> 14) & 0xffff;
-	tm.tm_mon  = (p >> 10) & 0xf;
-	tm.tm_mday = (p >>  5) & 0x1f;
-	tm.tm_hour =  p        & 0x1f;
-	tm.tm_min  = (s >> 26) & 0x3f;
-	tm.tm_sec  = (s >> 20) & 0x3f;
-	tm.tm_isdst = 0;
-
-	sec = make_time_t(&tm, Qtrue);
-	usec = (long)(s & 0xfffff);
-        nsec = usec * 1000;
-
-        if (submicro != Qnil) {
-            unsigned char *ptr;
-            long len;
-            int digit;
-            ptr = (unsigned char*)StringValuePtr(submicro);
-            len = RSTRING_LEN(submicro);
-            if (0 < len) {
-                if (10 <= (digit = ptr[0] >> 4)) goto end_submicro;
-                nsec += digit * 100;
-                if (10 <= (digit = ptr[0] & 0xf)) goto end_submicro;
-                nsec += digit * 10;
-            }
-            if (1 < len) {
-                if (10 <= (digit = ptr[1] >> 4)) goto end_submicro;
-                nsec += digit;
-            }
-end_submicro: ;
-        }
-    }
-    time_overflow_p(&sec, &nsec);
-
-    GetTimeval(time, tobj);
-    tobj->tm_got = 0;
-    tobj->gmt = gmt;
-    tobj->ts.tv_sec = sec;
-    tobj->ts.tv_nsec = nsec;
-
-    return time;
-}
-
-/*
- * call-seq:
- *   Time._load(string)   => time
- *
- * Unmarshal a dumped +Time+ object.
- */
-
-static VALUE
-time_load(VALUE klass, SEL sel, VALUE str)
-{
-    VALUE time = time_s_alloc(klass, 0);
-
-    time_mload(time, str);
-    return time;
-}
-
-/*
- *  <code>Time</code> is an abstraction of dates and times. Time is
- *  stored internally as the number of seconds and nanoseconds since
- *  the <em>Epoch</em>, January 1, 1970 00:00 UTC. On some operating
- *  systems, this offset is allowed to be negative. Also see the
- *  library modules <code>Date</code>. The
- *  <code>Time</code> class treats GMT (Greenwich Mean Time) and UTC
- *  (Coordinated Universal Time)<em>[Yes, UTC really does stand for
- *  Coordinated Universal Time. There was a committee involved.]</em>
- *  as equivalent.  GMT is the older way of referring to these
- *  baseline times but persists in the names of calls on POSIX
- *  systems.
- *     
- *  All times are stored with some number of nanoseconds. Be aware of
- *  this fact when comparing times with each other---times that are
- *  apparently equal when displayed may be different when compared.
- */
-
-static double
-imp_timeIntervalSinceReferenceDate(void *rcv, SEL sel)
-{
-    return time_since_epoch((VALUE)rcv) - SINCE_EPOCH; 
-}
-
-static void *
-imp_initWithTimeIntervalSinceReferenceDate(void *rcv, SEL sel, double interval)
-{
-    struct timespec ts = rb_time_timespec(DOUBLE2NUM(interval + SINCE_EPOCH));
-    struct time_object *tobj;
-    GetTimeval(rcv, tobj);
-    tobj->ts = ts;
-    return rcv;
-}
-
-void
-Init_Time(void)
-{
-    id_divmod = rb_intern("divmod");
-    id_mul = rb_intern("*");
-    id_submicro = rb_intern("submicro");
-
-    rb_cNSDate = (VALUE)objc_getClass("NSDate");
-    assert(rb_cNSDate != 0);
-
-    rb_cTime = rb_define_class("Time", rb_cNSDate);
-    rb_include_module(rb_cTime, rb_mComparable);
-    rb_objc_install_NSObject_special_methods((Class)rb_cTime);
-
-    rb_objc_define_method(*(VALUE *)rb_cTime, "alloc", time_s_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "new", rb_class_new_instance_imp,
-	    -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "now", rb_class_new_instance_imp,
-	    -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "at", time_s_at, -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "utc", time_s_mkutc, -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "gm", time_s_mkutc, -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "local", time_s_mktime, -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "mktime", time_s_mktime, -1);
-
-    rb_objc_define_method(rb_cTime, "dup", rb_obj_dup, 0);
-    rb_objc_define_method(rb_cTime, "to_i", time_to_i, 0);
-    rb_objc_define_method(rb_cTime, "to_f", time_to_f, 0);
-    rb_objc_define_method(rb_cTime, "<=>", time_cmp, 1);
-    rb_objc_define_method(rb_cTime, "eql?", time_eql, 1);
-    rb_objc_define_method(rb_cTime, "hash", time_hash, 0);
-    rb_objc_define_method(rb_cTime, "initialize", time_init, 0);
-    rb_objc_define_method(rb_cTime, "initialize_copy", time_init_copy, 1);
-
-    rb_objc_define_method(rb_cTime, "localtime", time_localtime, 0);
-    rb_objc_define_method(rb_cTime, "gmtime", time_gmtime, 0);
-    rb_objc_define_method(rb_cTime, "utc", time_gmtime, 0);
-    rb_objc_define_method(rb_cTime, "getlocal", time_getlocaltime, 0);
-    rb_objc_define_method(rb_cTime, "getgm", time_getgmtime, 0);
-    rb_objc_define_method(rb_cTime, "getutc", time_getgmtime, 0);
-
-    rb_objc_define_method(rb_cTime, "ctime", time_asctime, 0);
-    rb_objc_define_method(rb_cTime, "asctime", time_asctime, 0);
-    rb_objc_define_method(rb_cTime, "to_s", time_to_s, 0);
-    rb_objc_define_method(rb_cTime, "inspect", time_to_s, 0);
-    rb_objc_define_method(rb_cTime, "to_a", time_to_a, 0);
-
-    rb_objc_define_method(rb_cTime, "+", time_plus, 1);
-    rb_objc_define_method(rb_cTime, "-", time_minus, 1);
-
-    rb_objc_define_method(rb_cTime, "succ", time_succ, 0);
-    rb_objc_define_method(rb_cTime, "sec", time_sec, 0);
-    rb_objc_define_method(rb_cTime, "min", time_min, 0);
-    rb_objc_define_method(rb_cTime, "hour", time_hour, 0);
-    rb_objc_define_method(rb_cTime, "mday", time_mday, 0);
-    rb_objc_define_method(rb_cTime, "day", time_mday, 0);
-    rb_objc_define_method(rb_cTime, "mon", time_mon, 0);
-    rb_objc_define_method(rb_cTime, "month", time_mon, 0);
-    rb_objc_define_method(rb_cTime, "year", time_year, 0);
-    rb_objc_define_method(rb_cTime, "wday", time_wday, 0);
-    rb_objc_define_method(rb_cTime, "yday", time_yday, 0);
-    rb_objc_define_method(rb_cTime, "isdst", time_isdst, 0);
-    rb_objc_define_method(rb_cTime, "dst?", time_isdst, 0);
-    rb_objc_define_method(rb_cTime, "zone", time_zone, 0);
-    rb_objc_define_method(rb_cTime, "gmtoff", time_utc_offset, 0);
-    rb_objc_define_method(rb_cTime, "gmt_offset", time_utc_offset, 0);
-    rb_objc_define_method(rb_cTime, "utc_offset", time_utc_offset, 0);
-
-    rb_objc_define_method(rb_cTime, "utc?", time_utc_p, 0);
-    rb_objc_define_method(rb_cTime, "gmt?", time_utc_p, 0);
-
-    rb_objc_define_method(rb_cTime, "sunday?", time_sunday, 0);
-    rb_objc_define_method(rb_cTime, "monday?", time_monday, 0);
-    rb_objc_define_method(rb_cTime, "tuesday?", time_tuesday, 0);
-    rb_objc_define_method(rb_cTime, "wednesday?", time_wednesday, 0);
-    rb_objc_define_method(rb_cTime, "thursday?", time_thursday, 0);
-    rb_objc_define_method(rb_cTime, "friday?", time_friday, 0);
-    rb_objc_define_method(rb_cTime, "saturday?", time_saturday, 0);
-
-    rb_objc_define_method(rb_cTime, "tv_sec", time_to_i, 0);
-    rb_objc_define_method(rb_cTime, "tv_usec", time_usec, 0);
-    rb_objc_define_method(rb_cTime, "usec", time_usec, 0);
-    rb_objc_define_method(rb_cTime, "tv_nsec", time_nsec, 0);
-    rb_objc_define_method(rb_cTime, "nsec", time_nsec, 0);
-
-    rb_objc_define_method(rb_cTime, "strftime", time_strftime, 1);
-
-    /* methods for marshaling */
-    rb_objc_define_method(rb_cTime, "_dump", time_dump, -1);
-    rb_objc_define_method(*(VALUE *)rb_cTime, "_load", time_load, 1);
-#if 0
-    /* Time will support marshal_dump and marshal_load in the future (1.9 maybe) */
-    rb_define_method(rb_cTime, "marshal_dump", time_mdump, 0);
-    rb_define_method(rb_cTime, "marshal_load", time_mload, 1);
-#endif
-
-    Class k = (Class)rb_cTime;
-    rb_objc_install_method2(k, "timeIntervalSinceReferenceDate",
-	    (IMP)imp_timeIntervalSinceReferenceDate);
-    rb_objc_install_method2(k, "initWithTimeIntervalSinceReferenceDate:",
-	    (IMP)imp_initWithTimeIntervalSinceReferenceDate);
-}

Deleted: MacRuby/trunk/transcode.c
===================================================================
--- MacRuby/trunk/transcode.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/transcode.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,446 +0,0 @@
-/* 
- * MacRuby implementation of transcode.c.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
- 
-// Notes:
-// AFAICT, we need to add support for newline decorators.
-
-#include "macruby_internal.h"
-#include "ruby/encoding.h"
-#include "encoding.h"
-
-static VALUE sym_invalid;
-static VALUE sym_undef;
-static VALUE sym_replace;
-static VALUE sym_xml;
-static VALUE sym_text;
-static VALUE sym_attr;
-
-typedef struct rb_econv_s {
-    rb_encoding_t *source;
-    rb_encoding_t *destination;
-    transcode_behavior_t invalid_sequence_behavior;
-    transcode_behavior_t undefined_conversion_behavior;
-    transcode_flags_t special_flags;
-    rb_str_t *replacement;
-    bool finished;
-} rb_econv_t;
-
-VALUE rb_cEncodingConverter;
-
-static rb_econv_t* RConverter(VALUE self) {
-    rb_econv_t *conv;
-    Data_Get_Struct(self, rb_econv_t, conv);
-    return conv;
-}
-
-static VALUE
-rb_econv_alloc(VALUE klass, SEL sel)
-{
-    rb_econv_t *conv = ALLOC(rb_econv_t);
-    conv->source = NULL;
-    conv->destination = NULL;
-    conv->replacement = NULL;
-    conv->special_flags = 0;
-    conv->finished = false;
-    return Data_Wrap_Struct(klass, 0, 0, conv);
-}
-
-static VALUE 
-rb_econv_asciicompat_encoding(VALUE klass, SEL sel, VALUE arg)
-{
-    rb_encoding_t *enc = NULL;
-    if (CLASS_OF(arg) == rb_cEncoding) {
-        enc = rb_to_encoding(arg);
-    } 
-    else {
-        StringValue(arg);
-        enc = rb_enc_find(RSTRING_PTR(arg));
-    }
-
-    if ((enc == NULL) || (enc->ascii_compatible)) {
-        return Qnil;
-    }
-    else if (IS_UTF16_ENC(enc) || IS_UTF32_ENC(enc)) {
-        return (VALUE)rb_utf8_encoding();
-    }
-    // TODO: Port MRI's table that maps ASCII-incompatible encodings to compatible ones.
-    rb_raise(rb_eConverterNotFoundError, "could not find ASCII-compatible encoding for %s", enc->public_name);
-}
-
-static VALUE rb_econv_convpath(VALUE self, SEL sel);
-
-static VALUE
-rb_econv_search_convpath(VALUE klass, SEL sel, int argc, VALUE* argv)
-{
-    return rb_econv_convpath(rb_class_new_instance(argc, argv, klass), sel);
-}
-
-static transcode_behavior_t
-symbol_option_with_default(VALUE given_symbol, transcode_behavior_t otherwise, const char* name)
-{
-    if (given_symbol == sym_replace) {
-        return TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING;
-    }
-    else if (given_symbol == sym_attr) {
-        return TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_ATTR;
-    }
-    else if (given_symbol == sym_text) {
-        return TRANSCODE_BEHAVIOR_REPLACE_WITH_XML_TEXT;
-    }
-    else if (!NIL_P(given_symbol)) {
-        rb_raise(rb_eArgError, "unknown value '%s' for option %s", StringValuePtr(given_symbol), name);
-    }
-    return otherwise;
-}
-
-static void parse_conversion_options(VALUE options, transcode_behavior_t* behavior_for_invalid, 
-    transcode_behavior_t* behavior_for_undefined, rb_str_t** replacement_str, rb_encoding_t* destination) 
-{
-    
-    *behavior_for_invalid = symbol_option_with_default(rb_hash_aref(options, sym_invalid), 
-        TRANSCODE_BEHAVIOR_RAISE_EXCEPTION, "invalid-character");
-    
-    *behavior_for_undefined = symbol_option_with_default(rb_hash_aref(options, sym_undef),
-        TRANSCODE_BEHAVIOR_RAISE_EXCEPTION, "undefined-conversion");
-    
-    // Because the API conflates the :xml and :undef options, we pass in the previous setting
-    *behavior_for_undefined = symbol_option_with_default(rb_hash_aref(options, sym_xml),
-        *behavior_for_undefined, "xml-replacement");
-    
-    *behavior_for_undefined = symbol_option_with_default(rb_hash_aref(options, sym_xml),
-        *behavior_for_undefined, "xml-replacement");
-    
-    VALUE replacement = rb_hash_aref(options, sym_replace);
-    if (!NIL_P(replacement)) {
-        *replacement_str = str_simple_transcode(str_need_string(replacement), destination);
-    }
-    
-}
-
-static VALUE
-rb_econv_initialize(VALUE self, SEL sel, int argc, VALUE* argv)
-{
-    rb_econv_t *conv = RConverter(self);
-    VALUE sourceobj, destobj, options;
-    rb_scan_args(argc, argv, "21", &sourceobj, &destobj, &options);
-    
-    rb_encoding_t* source = rb_to_encoding(sourceobj);
-    rb_encoding_t* destination = rb_to_encoding(destobj);
-    rb_str_t* replacement_str = NULL;
-    
-    conv->source = source;
-    conv->destination = destination;
-
-    conv->invalid_sequence_behavior = TRANSCODE_BEHAVIOR_RAISE_EXCEPTION;
-    conv->undefined_conversion_behavior = TRANSCODE_BEHAVIOR_RAISE_EXCEPTION;
-    
-    // Extract the options. This is a hateful, hateful API.
-    if (!NIL_P(options)) {
-        
-        if (FIXNUM_P(options)) {
-            rb_bug("fixnum arguments are not supported yet.");
-        } 
-        else if (TYPE(options) == T_HASH) {
-            parse_conversion_options(options, &conv->invalid_sequence_behavior, 
-                &conv->undefined_conversion_behavior, &replacement_str, destination);
-        } 
-        else {
-            rb_raise(rb_eArgError, "expected either a hash or a fixnum as the last parameter");
-        }   
-    }
-    
-    // Get the default replacement string. For UTF-[8, 16, 32] it's /uFFFD, and for others it's '?'
-    if (replacement_str == NULL) {
-        replacement_str = replacement_string_for_encoding(destination);
-    }
-    GC_WB(&conv->replacement, replacement_str);
-    
-    return self;
-}
-
-static VALUE
-rb_econv_inspect(VALUE self, SEL sel)
-{
-    // TODO: make this comply with the MRI output when we add newline decorators
-    rb_econv_t *conv = RConverter(self);
-    return rb_sprintf("#<%s: %s to %s>", rb_obj_classname(self), conv->source->public_name, 
-        conv->destination->public_name);
-}
-
-static VALUE
-rb_econv_convpath(VALUE self, SEL sel)
-{
-    // in MacRuby, the convpath always looks like this:
-    // [[source_encoding, native UTF-16], [native UTF-16, dest_encoding]]
-    // The first element is omitted if the source encoding is UTF-16, obviously.
-    rb_econv_t *conv = RConverter(self);
-    VALUE to_return = rb_ary_new2(2);
-    rb_encoding_t* nativeUTF16 = rb_encodings[ENCODING_UTF16_NATIVE];
-    
-    if (conv->source != nativeUTF16) {
-        rb_ary_push(to_return, rb_assoc_new((VALUE)conv->source, (VALUE)nativeUTF16));
-    }
-    
-    rb_ary_push(to_return, rb_assoc_new((VALUE)nativeUTF16, (VALUE)conv->destination));
-    
-    return to_return;
-}
-
-static VALUE
-rb_econv_source_encoding(VALUE self, SEL sel)
-{
-    return (VALUE)(RConverter(self)->source);
-}
-
-static VALUE
-rb_econv_destination_encoding(VALUE self, SEL sel)
-{
-    return (VALUE)(RConverter(self)->destination);
-}
-
-// Since our converter is basically a black box at this point, we'll leave 
-// the lower-level methods unimplemented.
-#define rb_econv_primitive_convert rb_f_notimplement
-
-static VALUE 
-rb_econv_convert(VALUE self, SEL sel, VALUE str)
-{
-    rb_econv_t *conv;
-    Data_Get_Struct(self, rb_econv_t, conv);
-    
-    if (conv->finished) {
-        rb_raise(rb_eArgError, "convert() called on a finished stream");
-    }
-    
-    assert(conv->replacement->encoding == conv->destination);
-    return (VALUE)str_transcode(str_need_string(str), conv->source, conv->destination, conv->invalid_sequence_behavior, conv->undefined_conversion_behavior, conv->replacement);
-}
-
-static VALUE
-rb_econv_finish(VALUE self, SEL sel)
-{
-    // TODO: Flesh this out later.
-    RConverter(self)->finished = true;
-    return rb_str_new2("");
-}
-
-#define rb_econv_primitive_errinfo rb_f_notimplement
-
-#define rb_econv_insert_output rb_f_notimplement
-
-#define rb_econv_putback rb_f_notimplement
-
-#define rb_econv_last_error rb_f_notimplement
-
-static VALUE
-rb_econv_replacement(VALUE self, SEL sel)
-{
-    return (VALUE)(RConverter(self)->replacement);
-}
-
-static VALUE 
-rb_econv_set_replacement(VALUE self, SEL sel, VALUE str)
-{
-    // TODO: Should we copy this string? Probably.
-    rb_econv_t *conv = RConverter(self);
-    if (TYPE(str) != T_STRING) {
-        rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", rb_obj_classname(str));
-    }
-    rb_str_force_encoding(str, conv->destination);
-    GC_WB(&conv->replacement, str_need_string(str));
-    return str;
-}
-
-/*
- *  call-seq:
- *     str.encode(encoding [, options] )   => str
- *     str.encode(dst_encoding, src_encoding [, options] )   => str
- *     str.encode([options])   => str
- *
- *  The first form returns a copy of <i>str</i> transcoded
- *  to encoding +encoding+.
- *  The second form returns a copy of <i>str</i> transcoded
- *  from src_encoding to dst_encoding.
- *  The last form returns a copy of <i>str</i> transcoded to
- *  <code>Encoding.default_internal</code>.
- *  By default, the first and second form raise
- *  Encoding::UndefinedConversionError for characters that are
- *  undefined in the destination encoding, and
- *  Encoding::InvalidByteSequenceError for invalid byte sequences
- *  in the source encoding. The last form by default does not raise
- *  exceptions but uses replacement strings.
- *  The <code>options</code> Hash gives details for conversion.
- *
- *  === options
- *  The hash <code>options</code> can have the following keys:
- *  :invalid ::
- *    If the value is <code>:replace</code>, <code>#encode</code> replaces
- *    invalid byte sequences in <code>str</code> with the replacement character.
- *    The default is to raise the exception
- *  :undef ::
- *    If the value is <code>:replace</code>, <code>#encode</code> replaces
- *    characters which are undefined in the destination encoding with
- *    the replacement character.
- *  :replace ::
- *    Sets the replacement string to the value. The default replacement
- *    string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
- *  :xml ::
- *    The value must be <code>:text</code> or <code>:attr</code>.
- *    If the value is <code>:text</code> <code>#encode</code> replaces
- *    undefined characters with their (upper-case hexadecimal) numeric
- *    character references. '&', '<', and '>' are converted to "&",
- *    "<", and ">", respectively.
- *    If the value is <code>:attr</code>, <code>#encode</code> also quotes
- *    the replacement result (using '"'), and replaces '"' with """.
- */
-extern rb_encoding_t *default_internal;
-static VALUE
-rstr_encode(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    VALUE opt = Qnil;
-    if (argc > 0) {
-        opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
-        if (!NIL_P(opt)) {
-            argc--;
-        }
-    }
-
-    rb_str_t *self = RSTR(str);
-    rb_str_t *replacement_str = NULL;
-    rb_encoding_t *src_encoding, *dst_encoding;
-    transcode_behavior_t behavior_for_invalid = TRANSCODE_BEHAVIOR_RAISE_EXCEPTION;
-    transcode_behavior_t behavior_for_undefined = TRANSCODE_BEHAVIOR_RAISE_EXCEPTION;
-    if (argc == 0) {
-	src_encoding = self->encoding;
-	dst_encoding = default_internal;
-	behavior_for_invalid = TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING;
-	behavior_for_undefined = TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING;
-    }
-    else if (argc == 1) {
-	src_encoding = self->encoding;
-	dst_encoding = rb_to_encoding(argv[0]);
-    }
-    else if (argc == 2) {
-	dst_encoding = rb_to_encoding(argv[0]);
-	src_encoding = rb_to_encoding(argv[1]);
-    }
-    else {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
-    }
-
-    if (!NIL_P(opt)) {
-        parse_conversion_options(opt, &behavior_for_invalid, &behavior_for_undefined, &replacement_str, dst_encoding);
-	    if ((replacement_str != NULL) 
-	        && (behavior_for_invalid != TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING)
-		    && (behavior_for_undefined == TRANSCODE_BEHAVIOR_RAISE_EXCEPTION)) {
-		behavior_for_undefined = TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING;
-	    }
-	}
-
-    if ((replacement_str == NULL)
-	    && ((behavior_for_invalid == TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING)
-		|| (behavior_for_undefined == TRANSCODE_BEHAVIOR_REPLACE_WITH_STRING))) {
-	replacement_str = replacement_string_for_encoding(dst_encoding);
-    }
-
-    return (VALUE)str_transcode(self, src_encoding, dst_encoding,
-	    behavior_for_invalid, behavior_for_undefined, replacement_str);
-}
-
-/*
- *  call-seq:
- *     str.encode!(encoding [, options] )   => str
- *     str.encode!(dst_encoding, src_encoding [, options] )   => str
- *
- *  The first form transcodes the contents of <i>str</i> from
- *  str.encoding to +encoding+.
- *  The second form transcodes the contents of <i>str</i> from
- *  src_encoding to dst_encoding.
- *  The options Hash gives details for conversion. See String#encode
- *  for details.
- *  Returns the string even if no changes were made.
- */
-static VALUE
-rstr_encode_bang(VALUE str, SEL sel, int argc, VALUE *argv)
-{
-    rstr_modify(str);
-
-    VALUE new_str = rstr_encode(str, sel, argc, argv);
-    str_replace_with_string(RSTR(str), RSTR(new_str));
-    return str;
-}
-
-void
-Init_Transcode(void)
-{
-    rb_objc_define_method(rb_cRubyString, "encode", rstr_encode, -1);
-    rb_objc_define_method(rb_cRubyString, "encode!", rstr_encode_bang, -1);
-
-    rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cObject);
-    rb_objc_define_method(*(VALUE *)rb_cEncodingConverter, "alloc", rb_econv_alloc, 0);
-    rb_objc_define_method(*(VALUE *)rb_cEncodingConverter, "asciicompat_encoding", rb_econv_asciicompat_encoding, 1);
-    rb_objc_define_method(*(VALUE *)rb_cEncodingConverter, "search_convpath", rb_econv_search_convpath, -1);
-    
-    rb_objc_define_method(rb_cEncodingConverter, "initialize", rb_econv_initialize, -1);
-    rb_objc_define_method(rb_cEncodingConverter, "inspect", rb_econv_inspect, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "convpath", rb_econv_convpath, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "source_encoding", rb_econv_source_encoding, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "destination_encoding", rb_econv_destination_encoding, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "primitive_convert", rb_econv_primitive_convert, -1);
-    rb_objc_define_method(rb_cEncodingConverter, "convert", rb_econv_convert, 1);
-    rb_objc_define_method(rb_cEncodingConverter, "finish", rb_econv_finish, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "primitive_errinfo", rb_econv_primitive_errinfo, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "insert_output", rb_econv_insert_output, 1);
-    rb_objc_define_method(rb_cEncodingConverter, "putback", rb_econv_putback, -1);
-    rb_objc_define_method(rb_cEncodingConverter, "last_error", rb_econv_last_error, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "replacement", rb_econv_replacement, 0);
-    rb_objc_define_method(rb_cEncodingConverter, "replacement=", rb_econv_set_replacement, 1);
-    
-    sym_invalid = ID2SYM(rb_intern("invalid"));
-    sym_undef = ID2SYM(rb_intern("undef"));
-    sym_replace = ID2SYM(rb_intern("replace"));
-    sym_attr = ID2SYM(rb_intern("attr"));
-    sym_text = ID2SYM(rb_intern("text"));
-    sym_xml = ID2SYM(rb_intern("xml"));
-    
-    // If only these mapped to the internal enums...
-    rb_define_const(rb_cEncodingConverter, "INVALID_MASK", INT2FIX(ECONV_INVALID_MASK));
-    rb_define_const(rb_cEncodingConverter, "INVALID_REPLACE", INT2FIX(ECONV_INVALID_REPLACE));
-    rb_define_const(rb_cEncodingConverter, "UNDEF_MASK", INT2FIX(ECONV_UNDEF_MASK));
-    rb_define_const(rb_cEncodingConverter, "UNDEF_REPLACE", INT2FIX(ECONV_UNDEF_REPLACE));
-    rb_define_const(rb_cEncodingConverter, "UNDEF_HEX_CHARREF", INT2FIX(ECONV_UNDEF_HEX_CHARREF));
-    rb_define_const(rb_cEncodingConverter, "PARTIAL_INPUT", INT2FIX(ECONV_PARTIAL_INPUT));
-    rb_define_const(rb_cEncodingConverter, "AFTER_OUTPUT", INT2FIX(ECONV_AFTER_OUTPUT));
-    rb_define_const(rb_cEncodingConverter, "UNIVERSAL_NEWLINE_DECORATOR", INT2FIX(ECONV_UNIVERSAL_NEWLINE_DECORATOR));
-    rb_define_const(rb_cEncodingConverter, "CRLF_NEWLINE_DECORATOR", INT2FIX(ECONV_CRLF_NEWLINE_DECORATOR));
-    rb_define_const(rb_cEncodingConverter, "CR_NEWLINE_DECORATOR", INT2FIX(ECONV_CR_NEWLINE_DECORATOR));
-    rb_define_const(rb_cEncodingConverter, "XML_TEXT_DECORATOR", INT2FIX(ECONV_XML_TEXT_DECORATOR));
-    rb_define_const(rb_cEncodingConverter, "XML_ATTR_CONTENT_DECORATOR", INT2FIX(ECONV_XML_ATTR_CONTENT_DECORATOR));
-    rb_define_const(rb_cEncodingConverter, "XML_ATTR_QUOTE_DECORATOR", INT2FIX(ECONV_XML_ATTR_QUOTE_DECORATOR));
-
-#if 0
-    rb_define_method(rb_eUndefinedConversionError, "source_encoding_name", ecerr_source_encoding_name, 0);
-    rb_define_method(rb_eUndefinedConversionError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
-    rb_define_method(rb_eUndefinedConversionError, "source_encoding", ecerr_source_encoding, 0);
-    rb_define_method(rb_eUndefinedConversionError, "destination_encoding", ecerr_destination_encoding, 0);
-    rb_define_method(rb_eUndefinedConversionError, "error_char", ecerr_error_char, 0);
-
-    rb_define_method(rb_eInvalidByteSequenceError, "source_encoding_name", ecerr_source_encoding_name, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "source_encoding", ecerr_source_encoding, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding", ecerr_destination_encoding, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "error_bytes", ecerr_error_bytes, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "readagain_bytes", ecerr_readagain_bytes, 0);
-    rb_define_method(rb_eInvalidByteSequenceError, "incomplete_input?", ecerr_incomplete_input, 0);
-
-    Init_newline();
-#endif
-}

Deleted: MacRuby/trunk/ucnv.c
===================================================================
--- MacRuby/trunk/ucnv.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/ucnv.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,429 +0,0 @@
-/* 
- * MacRuby implementation of Ruby 1.9 String.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000 Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "encoding_ucnv.h"
-#include "unicode/ucnv.h"
-
-// do not forget to close the converter
-// before leaving the function
-#define USE_CONVERTER(cnv, encoding) \
-    assert(encoding->private_data != NULL); \
-    char cnv##_buffer[U_CNV_SAFECLONE_BUFFERSIZE]; \
-    UErrorCode cnv##_err = U_ZERO_ERROR; \
-    int32_t cnv##_buffer_size = U_CNV_SAFECLONE_BUFFERSIZE; \
-    UConverter *cnv = ucnv_safeClone( \
-	    (UConverter *)encoding->private_data, \
-	    cnv##_buffer, \
-	    &cnv##_buffer_size, \
-	    &cnv##_err \
-	); \
-    ucnv_reset(cnv);
-
-void
-str_ucnv_update_flags(rb_str_t *self)
-{
-    USE_CONVERTER(cnv, self->encoding);
-
-    bool ascii_only = true;
-    bool valid_encoding = true;
-
-    const char *pos = self->bytes;
-    const char *end = pos + self->length_in_bytes;
-    for (;;) {
-	// iterate through the string one Unicode code point at a time
-	UErrorCode err = U_ZERO_ERROR;
-	UChar32 c = ucnv_getNextUChar(cnv, &pos, end, &err);
-	if (U_FAILURE(err)) {
-	    if (err == U_INDEX_OUTOFBOUNDS_ERROR) {
-		// end of the string
-		break;
-	    }
-	    else {
-		// conversion error
-		valid_encoding = false;
-		ascii_only = false;
-		break;
-	    }
-	}
-	else {
-	    if (c > 127) {
-		ascii_only = false;
-	    }
-	}
-    }
-
-    ucnv_close(cnv);
-
-    str_set_valid_encoding(self, valid_encoding);
-    str_set_ascii_only(self, ascii_only);
-}
-
-static long
-utf16_bytesize_approximation(rb_encoding_t *enc, int bytesize)
-{
-    long approximation;
-    if (IS_UTF16_ENC(enc)) {
-	approximation = bytesize; // the bytesize in UTF-16 is the same
-				  // whatever the endianness
-    }
-    else if (IS_UTF32_ENC(enc)) {
-	// the bytesize in UTF-16 is nearly half of the bytesize in UTF-32
-	// (if there characters not in the BMP it's a bit more though)
-	approximation = bytesize / 2;
-    }
-    else {
-	// take a quite large size to not have to reallocate
-	approximation = bytesize * 2;
-    }
-
-    if (ODD_NUMBER(approximation)) {
-	// the size must be an even number
-	++approximation;
-    }
-
-    return approximation;
-}
-
-long
-str_ucnv_length(rb_str_t *self, bool ucs2_mode)
-{
-    USE_CONVERTER(cnv, self->encoding);
-
-    const char *pos = self->bytes;
-    const char *end = pos + self->length_in_bytes;
-    long len = 0;
-    bool valid_encoding = true;
-    for (;;) {
-	const char *character_start_pos = pos;
-	// iterate through the string one Unicode code point at a time
-	UErrorCode err = U_ZERO_ERROR;
-	UChar32 c = ucnv_getNextUChar(cnv, &pos, end, &err);
-	if (err == U_INDEX_OUTOFBOUNDS_ERROR) {
-	    // end of the string
-	    break;
-	}
-	else if (U_FAILURE(err)) {
-	    valid_encoding = false;
-	    long min_char_size = self->encoding->min_char_size;
-	    long converted_width = pos - character_start_pos;
-	    len += div_round_up(converted_width, min_char_size);
-	}
-	else {
-	    if (ucs2_mode && !U_IS_BMP(c)) {
-		len += 2;
-	    }
-	    else {
-		++len;
-	    }
-	}
-    }
-
-    ucnv_close(cnv);
-
-    str_set_valid_encoding(self, valid_encoding);
-
-    return len;
-}
-
-
-void rb_ensure_b(void (^b_block)(void), void (^e_block)(void));
-
-void
-str_ucnv_each_uchar32_starting_from(rb_str_t *self,
-	long start_offset_in_bytes,
-	each_uchar32_callback_t callback)
-{
-    USE_CONVERTER(cnv, self->encoding);
-
-    rb_ensure_b(^{
-	const char *pos = self->bytes + start_offset_in_bytes;
-	const char *end = pos + self->length_in_bytes;
-	bool stop = false;
-	for (;;) {
-	    const char *char_start_pos = pos;
-	    // iterate through the string one Unicode code point at a time
-	    UErrorCode err = U_ZERO_ERROR;
-	    UChar32 c = ucnv_getNextUChar(cnv, &pos, end, &err);
-	    if (err == U_INDEX_OUTOFBOUNDS_ERROR) {
-		// end of the string
-		break;
-	    }
-	    else if (U_FAILURE(err)) {
-		long min_char_size = self->encoding->min_char_size;
-		while (char_start_pos < pos) {
-		    long char_len = pos - char_start_pos;
-		    if (char_len > min_char_size) {
-			char_len = min_char_size;
-		    }
-		    callback(U_SENTINEL, char_start_pos-self->bytes, char_len, &stop);
-		    if (stop) {
-			return;
-		    }
-		    char_start_pos += char_len;
-		}
-	    }
-	    else {
-		long char_len = pos - char_start_pos;
-		callback(c, char_start_pos-self->bytes, char_len, &stop);
-		if (stop) {
-		    return;
-		}
-	    }
-	}
-    }, ^{
-	ucnv_close(cnv);
-    });
-}
-
-character_boundaries_t
-str_ucnv_get_character_boundaries(rb_str_t *self, long index, bool ucs2_mode)
-{
-    character_boundaries_t boundaries = {-1, -1};
-    assert(index >= 0);
-
-    // the code has many similarities with str_length
-    USE_CONVERTER(cnv, self->encoding);
-
-    const char *pos = self->bytes;
-    const char *end = pos + self->length_in_bytes;
-    long current_index = 0;
-    for (;;) {
-	const char *character_start_pos = pos;
-	// iterate through the string one Unicode code point at a time
-	// (we dont care what the character is or if it's valid or not)
-	UErrorCode err = U_ZERO_ERROR;
-	UChar32 c = ucnv_getNextUChar(cnv, &pos, end, &err);
-	if (err == U_INDEX_OUTOFBOUNDS_ERROR) {
-	    // end of the string
-	    break;
-	}
-	long offset_in_bytes = character_start_pos - self->bytes;
-	long converted_width = pos - character_start_pos;
-	if (U_FAILURE(err)) {
-	    long min_char_size = self->encoding->min_char_size;
-	    // division of converted_width by min_char_size rounded up
-	    long diff = div_round_up(converted_width, min_char_size);
-	    long length_in_bytes;
-	    if (current_index == index) {
-		if (min_char_size > converted_width) {
-		    length_in_bytes = converted_width;
-		}
-		else {
-		    length_in_bytes = min_char_size;
-		}
-		boundaries.start_offset_in_bytes = offset_in_bytes;
-		boundaries.end_offset_in_bytes =
-		    boundaries.start_offset_in_bytes + length_in_bytes;
-		break;
-	    }
-	    else if (current_index + diff > index) {
-		long adjusted_offset = offset_in_bytes + (index
-			- current_index) * min_char_size;
-		if (adjusted_offset + min_char_size > offset_in_bytes
-			+ converted_width) {
-		    length_in_bytes = offset_in_bytes + converted_width
-			- adjusted_offset;
-		}
-		else {
-		    length_in_bytes = min_char_size;
-		}
-		boundaries.start_offset_in_bytes = adjusted_offset;
-		boundaries.end_offset_in_bytes =
-		    boundaries.start_offset_in_bytes + length_in_bytes;
-		break;
-	    }
-	    current_index += diff;
-	}
-	else {
-	    if (ucs2_mode && !U_IS_BMP(c)) {
-		// you cannot cut a surrogate in an encoding that is not UTF-16
-		if (current_index == index) {
-		    boundaries.start_offset_in_bytes = offset_in_bytes;
-		    break;
-		}
-		else if (current_index+1 == index) {
-		    boundaries.end_offset_in_bytes = offset_in_bytes
-			+ converted_width;
-		    break;
-		}
-		++current_index;
-	    }
-
-	    if (current_index == index) {
-		boundaries.start_offset_in_bytes = offset_in_bytes;
-		boundaries.end_offset_in_bytes =
-		    boundaries.start_offset_in_bytes + converted_width;
-		break;
-	    }
-
-	    ++current_index;
-	}
-    }
-
-    ucnv_close(cnv);
-
-    return boundaries;
-}
-
-long
-str_ucnv_offset_in_bytes_to_index(rb_str_t *self, long offset_in_bytes,
-	bool ucs2_mode)
-{
-    // the code has many similarities with str_length
-    USE_CONVERTER(cnv, self->encoding);
-
-    const char *current_position = self->bytes;
-    const char *searched_position = current_position + offset_in_bytes;
-    const char *end = current_position + self->length_in_bytes;
-    long index = 0;
-    for (;;) {
-	const char *character_start_position = current_position;
-	// iterate through the string one Unicode code point at a time
-	UErrorCode err = U_ZERO_ERROR;
-	UChar32 c = ucnv_getNextUChar(cnv, &current_position, end, &err);
-	if (err == U_INDEX_OUTOFBOUNDS_ERROR) {
-	    // end of the string
-	    // should not happen because str_offset_in_bytes_to_index
-	    // checks before that offset_in_bytes is inferior to the length
-	    // in bytes
-	    abort();
-	}
-	else if (U_FAILURE(err)) {
-	    long min_char_size = self->encoding->min_char_size;
-	    long converted_width = current_position - character_start_position;
-	    long to_add = div_round_up(converted_width, min_char_size);
-	    if (searched_position < character_start_position + to_add) {
-		long difference = searched_position - character_start_position;
-		index += (difference / min_char_size);
-		break;
-	    }
-	    index += to_add;
-	}
-	else {
-	    if (searched_position < current_position) {
-		// if we are in the middle of a character
-		// there is no valid index
-		index = -1;
-		break;
-	    }
-	    if (ucs2_mode && !U_IS_BMP(c)) {
-		index += 2;
-	    }
-	    else {
-		++index;
-	    }
-	}
-	if (searched_position == current_position) {
-	    break;
-	}
-    }
-
-    ucnv_close(cnv);
-
-    return index;
-}
-
-void
-str_ucnv_transcode_to_utf16(struct rb_encoding *src_enc,
-	rb_str_t *self, long *pos,
-	UChar **utf16, long *utf16_length)
-{
-    USE_CONVERTER(cnv, src_enc);
-
-    long capa = utf16_bytesize_approximation(src_enc,
-	    self->length_in_bytes);
-    const char *source_pos = self->bytes + *pos;
-    const char *source_end = self->bytes + self->length_in_bytes;
-    UChar *buffer = xmalloc(capa);
-    UChar *target_pos = buffer;
-    UErrorCode err = U_ZERO_ERROR;
-    for (;;) {
-	UChar *target_end = buffer + BYTES_TO_UCHARS(capa);
-	err = U_ZERO_ERROR;
-	ucnv_toUnicode(cnv, &target_pos, target_end, &source_pos, source_end,
-		NULL, true, &err);
-	if (err == U_BUFFER_OVERFLOW_ERROR) {
-	    long index = target_pos - buffer;
-	    capa *= 2; // double the buffer's size
-	    buffer = xrealloc(buffer, capa);
-	    target_pos = buffer + index;
-	}
-	else {
-	    break;
-	}
-    }
-
-    ucnv_close(cnv);
-
-    *utf16 = buffer;
-    *utf16_length = target_pos - buffer;
-    *pos = source_pos - self->bytes;
-
-    if (U_FAILURE(err)) {
-	// the invalid character will be skipped by str_transcode
-	*pos -= src_enc->min_char_size;
-    }
-}
-
-void
-str_ucnv_transcode_from_utf16(struct rb_encoding *dst_enc,
-	UChar *utf16, long utf16_length, long *utf16_pos,
-	char **bytes, long *bytes_length)
-{
-    USE_CONVERTER(cnv, dst_enc);
-
-    UErrorCode err = U_ZERO_ERROR;
-    long capa = UCNV_GET_MAX_BYTES_FOR_STRING(
-	    utf16_length - *utf16_pos, ucnv_getMaxCharSize(cnv));
-    char *buffer = xmalloc(capa);
-    const UChar *source_pos = &utf16[*utf16_pos];
-    const UChar *source_end = &utf16[utf16_length];
-    char *target_pos = buffer;
-    char *target_end = buffer + capa;
-    ucnv_fromUnicode(cnv, &target_pos, target_end, &source_pos, source_end,
-	    NULL, true, &err);
-    assert((err != U_ILLEGAL_ARGUMENT_ERROR) && (err != U_BUFFER_OVERFLOW_ERROR));
-
-    ucnv_close(cnv);
-
-    *bytes = buffer;
-    *bytes_length = target_pos - buffer;
-    *utf16_pos = source_pos - utf16;
-
-    if (U_FAILURE(err)) {
-	// the undefined character will be skipped by str_transcode
-	U16_BACK_1(utf16, 0, *utf16_pos);
-    }
-}
-
-void
-enc_init_ucnv_encoding(rb_encoding_t *encoding)
-{
-    // create the ICU converter
-    UErrorCode err = U_ZERO_ERROR;
-    UConverter *converter = ucnv_open(encoding->public_name, &err);
-    if (!U_SUCCESS(err) || (converter == NULL)) {
-	fprintf(stderr, "Couldn't create the encoder for %s\n",
-		encoding->public_name);
-	abort();
-    }
-    // stop the conversion when the conversion failed
-    err = U_ZERO_ERROR;
-    ucnv_setToUCallBack(converter, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL,
-	    &err);
-    err = U_ZERO_ERROR;
-    ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL,
-	    NULL, &err);
-
-    // fill the fields not filled yet
-    encoding->private_data = converter;
-}

Deleted: MacRuby/trunk/util.c
===================================================================
--- MacRuby/trunk/util.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/util.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,3990 +0,0 @@
-/**********************************************************************
-
-  util.c -
-
-  $Author: nobu $
-  created at: Fri Mar 10 17:22:34 JST 1995
-
-  Copyright (C) 1993-2008 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "macruby_internal.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <math.h>
-#include <float.h>
-
-#ifdef _WIN32
-#include "missing/file.h"
-#endif
-#if defined(__CYGWIN32__)
-#define _open open
-#define _close close
-#define _unlink unlink
-#define _access access
-#elif defined(_WIN32)
-#include <io.h>
-#endif
-
-#include "ruby/util.h"
-
-unsigned long
-ruby_scan_oct(const char *start, int len, int *retlen)
-{
-    register const char *s = start;
-    register unsigned long retval = 0;
-
-    while (len-- && *s >= '0' && *s <= '7') {
-	retval <<= 3;
-	retval |= *s++ - '0';
-    }
-    *retlen = s - start;
-    return retval;
-}
-
-unsigned long
-ruby_scan_hex(const char *start, int len, int *retlen)
-{
-    static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
-    register const char *s = start;
-    register unsigned long retval = 0;
-    char *tmp;
-
-    while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
-	retval <<= 4;
-	retval |= (tmp - hexdigit) & 15;
-	s++;
-    }
-    *retlen = s - start;
-    return retval;
-}
-
-static unsigned long
-scan_digits(const char *str, int base, size_t *retlen, int *overflow)
-{
-    static signed char table[] = {
-        /*     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
-        /*0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*1*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*2*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*3*/  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-        /*4*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
-        /*5*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
-        /*6*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
-        /*7*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
-        /*8*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*9*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*a*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*b*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*c*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*d*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*e*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-        /*f*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-    };
-
-    const char *start = str;
-    unsigned long ret = 0, x;
-    unsigned long mul_overflow = (~(unsigned long)0) / base;
-    int c;
-    *overflow = 0;
-
-    while ((c = (unsigned char)*str++) != '\0') {
-        int d = table[c];
-        if (d == -1 || base <= d) {
-            *retlen = (str-1) - start;
-            return ret;
-        }
-        if (mul_overflow < ret)
-            *overflow = 1;
-        ret *= base;
-        x = ret;
-        ret += d; 
-        if (ret < x)
-            *overflow = 1;
-    }
-    *retlen = (str-1) - start;
-    return ret;
-}
-
-unsigned long
-ruby_strtoul(const char *str, char **endptr, int base)
-{
-    int c, b, overflow;
-    int sign = 0;
-    size_t len;
-    unsigned long ret;
-    const char *subject_found = str;
-
-    if (base == 1 || 36 < base) {
-        errno = EINVAL;
-        return 0;
-    }
-
-    while ((c = *str) && ISSPACE(c))
-        str++;
-
-    if (c == '+') {
-        sign = 1;
-        str++;
-    }
-    else if (c == '-') {
-        sign = -1;
-        str++;
-    }
-
-    if (str[0] == '0') {
-        subject_found = str+1;
-        if (base == 0 || base == 16) {
-            if (str[1] == 'x' || str[1] == 'X') {
-                b = 16;
-                str += 2;
-            }
-            else {
-                b = base == 0 ? 8 : 16;
-                str++;
-            }
-        }
-        else {
-            b = base;
-            str++;
-        }
-    }
-    else {
-        b = base == 0 ? 10 : base;
-    }
-
-    ret = scan_digits(str, b, &len, &overflow);
-
-    if (0 < len)
-        subject_found = str+len;
-
-    if (endptr)
-        *endptr = (char*)subject_found;
-
-    if (overflow) {
-        errno = ERANGE;
-        return ULONG_MAX;
-    }
-
-    if (sign < 0) {
-        ret = -ret;
-        return ret;
-    }
-    else {
-        return ret;
-    }
-}
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(HAVE_FCNTL_H)
-#include <fcntl.h>
-#endif
-
-#ifndef S_ISDIR
-#   define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
-/*
- *  Copyright (c) 1993, Intergraph Corporation
- *
- *  You may distribute under the terms of either the GNU General Public
- *  License or the Artistic License, as specified in the perl README file.
- *
- *  Various Unix compatibility functions and NT specific functions.
- *
- *  Some of this code was derived from the MSDOS port(s) and the OS/2 port.
- *
- */
-
-
-/*
- * Suffix appending for in-place editing under MS-DOS and OS/2 (and now NT!).
- *
- * Here are the rules:
- *
- * Style 0:  Append the suffix exactly as standard perl would do it.
- *           If the filesystem groks it, use it.  (HPFS will always
- *           grok it.  So will NTFS. FAT will rarely accept it.)
- *
- * Style 1:  The suffix begins with a '.'.  The extension is replaced.
- *           If the name matches the original name, use the fallback method.
- *
- * Style 2:  The suffix is a single character, not a '.'.  Try to add the 
- *           suffix to the following places, using the first one that works.
- *               [1] Append to extension.  
- *               [2] Append to filename, 
- *               [3] Replace end of extension, 
- *               [4] Replace end of filename.
- *           If the name matches the original name, use the fallback method.
- *
- * Style 3:  Any other case:  Ignore the suffix completely and use the
- *           fallback method.
- *
- * Fallback method:  Change the extension to ".$$$".  If that matches the
- *           original name, then change the extension to ".~~~".
- *
- * If filename is more than 1000 characters long, we die a horrible
- * death.  Sorry.
- *
- * The filename restriction is a cheat so that we can use buf[] to store
- * assorted temporary goo.
- *
- * Examples, assuming style 0 failed.
- *
- * suffix = ".bak" (style 1)
- *                foo.bar => foo.bak
- *                foo.bak => foo.$$$	(fallback)
- *                foo.$$$ => foo.~~~	(fallback)
- *                makefile => makefile.bak
- *
- * suffix = "~" (style 2)
- *                foo.c => foo.c~
- *                foo.c~ => foo.c~~
- *                foo.c~~ => foo~.c~~
- *                foo~.c~~ => foo~~.c~~
- *                foo~~~~~.c~~ => foo~~~~~.$$$ (fallback)
- *
- *                foo.pas => foo~.pas
- *                makefile => makefile.~
- *                longname.fil => longname.fi~
- *                longname.fi~ => longnam~.fi~
- *                longnam~.fi~ => longnam~.$$$
- *                
- */
-
-
-static int valid_filename(const char *s);
-
-static const char suffix1[] = ".$$$";
-static const char suffix2[] = ".~~~";
-
-#define ext (&buf[1000])
-
-#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
-
-void
-ruby_add_suffix(VALUE str, const char *suffix)
-{
-    int baselen;
-    int extlen = strlen(suffix);
-    char *s, *t, *p;
-    long slen;
-    char buf[1024];
-
-    if (RSTRING_LEN(str) > 1000)
-        rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
-		 RSTRING_LEN(str));
-
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32)
-    /* Style 0 */
-    slen = RSTRING_LEN(str);
-    rb_str_cat(str, suffix, extlen);
-#if defined(DJGPP)
-    if (_USE_LFN) return;
-#else
-    if (valid_filename(RSTRING_PTR(str))) return;
-#endif
-
-    /* Fooey, style 0 failed.  Fix str before continuing. */
-    rb_str_resize(str, slen);
-#endif
-
-    slen = extlen;
-    t = buf; baselen = 0; s = RSTRING_PTR(str);
-    while ((*t = *s) && *s != '.') {
-	baselen++;
-	if (*s == '\\' || *s == '/') baselen = 0;
- 	s++; t++;
-    }
-    p = t;
-
-    t = ext; extlen = 0;
-    while ((*t++ = *s++) != 0) extlen++;
-    if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
-
-    if (*suffix == '.') {        /* Style 1 */
-        if (strEQ(ext, suffix)) goto fallback;
-	strcpy(p, suffix);
-    }
-    else if (suffix[1] == '\0') {  /* Style 2 */
-        if (extlen < 4) { 
-	    ext[extlen] = *suffix;
-	    ext[++extlen] = '\0';
-        }
-	else if (baselen < 8) {
-   	    *p++ = *suffix;
-	}
-	else if (ext[3] != *suffix) {
-	    ext[3] = *suffix;
-	}
-	else if (buf[7] != *suffix) {
-	    buf[7] = *suffix;
-	}
-	else goto fallback;
-	strcpy(p, ext);
-    }
-    else { /* Style 3:  Panic */
-fallback:
-	(void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
-    }
-    rb_str_replace(str, rb_str_new(buf, strlen(buf)));
-}
-
-#if defined(__CYGWIN32__) || defined(_WIN32)
-static int 
-valid_filename(const char *s)
-{
-    int fd;
-
-    /*
-    // It doesn't exist, so see if we can open it.
-    */
-
-    if ((fd = _open(s, O_CREAT|O_EXCL, 0666)) >= 0) {
-	_close(fd);
-	_unlink(s);	/* don't leave it laying around */
-	return 1;
-    }
-    else if (errno == EEXIST) {
-	/* if the file exists, then it's a valid filename! */
-	return 1;
-    }
-    return 0;
-}
-#endif
-#endif
-
-#if defined __DJGPP__
-
-#include <dpmi.h>
-
-static char dbcs_table[256];
-
-int
-make_dbcs_table()
-{
-    __dpmi_regs r;
-    struct {
-	unsigned char start;
-	unsigned char end;
-    } vec;
-    int offset;
-
-    memset(&r, 0, sizeof(r));
-    r.x.ax = 0x6300;
-    __dpmi_int(0x21, &r);
-    offset = r.x.ds * 16 + r.x.si;
-
-    for (;;) {
-	int i;
-	dosmemget(offset, sizeof vec, &vec);
-	if (!vec.start && !vec.end)
-	    break;
-	for (i = vec.start; i <= vec.end; i++)
-	    dbcs_table[i] = 1;
-	offset += 2;
-    }
-}
-
-int
-mblen(const char *s, size_t n)
-{
-    static int need_init = 1;
-    if (need_init) {
-	make_dbcs_table();
-	need_init = 0;
-    }
-    if (s) {
-	if (n == 0 || *s == 0)
-	    return 0;
-	else if (!s[1])
-	    return 1;
-	return dbcs_table[(unsigned char)*s] + 1;
-    }
-    else
-	return 1;
-}
-
-struct PathList {
-    struct PathList *next;
-    char *path;
-};
-
-struct PathInfo {
-    struct PathList *head;
-    int count;
-};
-
-static int
-push_element(const char *path, VALUE vinfo)
-{
-    struct PathList *p;
-    struct PathInfo *info = (struct PathInfo *)vinfo;
-
-    p = ALLOC(struct PathList);
-    MEMZERO(p, struct PathList, 1);
-    GC_WB(&p->path, ruby_strdup(path));
-    p->next = info->head;
-    info->head = p;
-    info->count++;
-
-    return 0;
-}
-
-#include <dirent.h>
-int __opendir_flags = __OPENDIR_PRESERVE_CASE;
-
-char **
-__crt0_glob_function(char *path)
-{
-    int len = strlen(path);
-    int i;
-    char **rv;
-    char path_buffer[PATH_MAX];
-    char *buf = path_buffer;
-    char *p;
-    struct PathInfo info;
-    struct PathList *plist;
-
-    if (PATH_MAX <= len)
-	buf = ruby_xmalloc(len + 1);
-
-    strncpy(buf, path, len);
-    buf[len] = '\0';
-
-    for (p = buf; *p; p += mblen(p, RUBY_MBCHAR_MAXSIZE))
-	if (*p == '\\')
-	    *p = '/';
-
-    info.count = 0;
-    info.head = 0;
-
-    ruby_glob(buf, 0, push_element, (VALUE)&info);
-
-    if (buf != path_buffer)
-	ruby_xfree(buf);
-
-    if (info.count == 0)
-	return 0;
-
-    rv = ruby_xmalloc((info.count + 1) * sizeof (char *));
-
-    plist = info.head;
-    i = 0;
-    while (plist) {
-	struct PathList *cur;
-	rv[i] = plist->path;
-	cur = plist;
-	plist = plist->next;
-	ruby_xfree(cur);
-	i++;
-    }
-    rv[i] = 0;
-    return rv;
-}
-
-#endif
-
-/* mm.c */
-
-#define A ((int*)a)
-#define B ((int*)b)
-#define C ((int*)c)
-#define D ((int*)d)
-
-#define mmprepare(base, size) do {\
- if (((long)base & (0x3)) == 0)\
-   if (size >= 16) mmkind = 1;\
-   else            mmkind = 0;\
- else              mmkind = -1;\
- high = (size & (~0xf));\
- low  = (size &  0x0c);\
-} while (0)\
-
-#define mmarg mmkind, size, high, low
-
-static void mmswap_(register char *a, register char *b, int mmkind, int size, int high, int low)
-{
- register int s;
- if (a == b) return;
- if (mmkind >= 0) {
-   if (mmkind > 0) {
-     register char *t = a + high;
-     do {
-       s = A[0]; A[0] = B[0]; B[0] = s;
-       s = A[1]; A[1] = B[1]; B[1] = s;
-       s = A[2]; A[2] = B[2]; B[2] = s;
-       s = A[3]; A[3] = B[3]; B[3] = s;  a += 16; b += 16;
-     } while (a < t);
-   }
-   if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
-     if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
-       if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
- }
- else {
-   register char *t = a + size;
-   do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
- }
-}
-#define mmswap(a,b) mmswap_((a),(b),mmarg)
-
-static void mmrot3_(register char *a, register char *b, register char *c, int mmkind, int size, int high, int low)
-{
- register int s;
- if (mmkind >= 0) {
-   if (mmkind > 0) {
-     register char *t = a + high;
-     do {
-       s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
-       s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
-       s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
-       s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
-     } while (a < t);
-   }
-   if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
-     if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
-       if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
- }
- else {
-   register char *t = a + size;
-   do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
- }
-}
-#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
-
-/* qs6.c */
-/*****************************************************/
-/*                                                   */
-/*          qs6   (Quick sort function)              */
-/*                                                   */
-/* by  Tomoyuki Kawamura              1995.4.21      */
-/* kawamura at tokuyama.ac.jp                           */
-/*****************************************************/
-
-typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
-#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)  /* Push L,l,R,r */
-#define POP(ll,rr)  do { --top; ll = top->LL; rr = top->RR; } while (0)      /* Pop L,l,R,r */
-
-#define med3(a,b,c) ((*cmp)(a,b,d)<0 ?                                   \
-                       ((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \
-                       ((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c)))
-
-void
-ruby_qsort(void* base, const int nel, const int size,
-	   int (*cmp)(const void*, const void*, void*), void *d)
-{
-  register char *l, *r, *m;          	/* l,r:left,right group   m:median point */
-  register int  t, eq_l, eq_r;       	/* eq_l: all items in left group are equal to S */
-  char *L = base;                    	/* left end of curren region */
-  char *R = (char*)base + size*(nel-1); /* right end of current region */
-  int  chklim = 63;                     /* threshold of ordering element check */
-  stack_node stack[32], *top = stack;   /* 32 is enough for 32bit CPU */
-  int mmkind, high, low;
-
-  if (nel <= 1) return;        /* need not to sort */
-  mmprepare(base, size);
-  goto start;
-
-  nxt:
-  if (stack == top) return;    /* return if stack is empty */
-  POP(L,R);
-
-  for (;;) {
-    start:
-    if (L + size == R) {       /* 2 elements */
-      if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
-    }
-
-    l = L; r = R;
-    t = (r - l + size) / size;  /* number of elements */
-    m = l + size * (t >> 1);    /* calculate median value */
-
-    if (t >= 60) {
-      register char *m1;
-      register char *m3;
-      if (t >= 200) {
-	t = size*(t>>3); /* number of bytes in splitting 8 */
-	{
-	  register char *p1 = l  + t;
-	  register char *p2 = p1 + t;
-	  register char *p3 = p2 + t;
-	  m1 = med3(p1, p2, p3);
-	  p1 = m  + t;
-	  p2 = p1 + t;
-	  p3 = p2 + t;
-	  m3 = med3(p1, p2, p3);
-	}
-      }
-      else {
-	t = size*(t>>2); /* number of bytes in splitting 4 */
-	m1 = l + t;
-	m3 = m + t;
-      }
-      m = med3(m1, m, m3);
-    }
-
-    if ((t = (*cmp)(l,m,d)) < 0) {                           /*3-5-?*/
-      if ((t = (*cmp)(m,r,d)) < 0) {                         /*3-5-7*/
-	if (chklim && nel >= chklim) {   /* check if already ascending order */
-	  char *p;
-	  chklim = 0;
-	  for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
-	  goto nxt;
-	}
-	fail: goto loopA;                                    /*3-5-7*/
-      }
-      if (t > 0) {
-	if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;}     /*3-5-4*/
-	mmrot3(r,m,l); goto loopA;                           /*3-5-2*/
-      }
-      goto loopB;                                            /*3-5-5*/
-    }
-
-    if (t > 0) {                                             /*7-5-?*/
-      if ((t = (*cmp)(m,r,d)) > 0) {                         /*7-5-3*/
-	if (chklim && nel >= chklim) {   /* check if already ascending order */
-	  char *p;
-	  chklim = 0;
-	  for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
-	  while (l<r) {mmswap(l,r); l+=size; r-=size;}  /* reverse region */
-	  goto nxt;
-	}
-	fail2: mmswap(l,r); goto loopA;                      /*7-5-3*/
-      }
-      if (t < 0) {
-	if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;}   /*7-5-8*/
-	mmrot3(l,m,r); goto loopA;                           /*7-5-6*/
-      }
-      mmswap(l,r); goto loopA;                               /*7-5-5*/
-    }
-
-    if ((t = (*cmp)(m,r,d)) < 0)  {goto loopA;}              /*5-5-7*/
-    if (t > 0) {mmswap(l,r); goto loopB;}                    /*5-5-3*/
-
-    /* determining splitting type in case 5-5-5 */           /*5-5-5*/
-    for (;;) {
-      if ((l += size) == r)      goto nxt;                   /*5-5-5*/
-      if (l == m) continue;
-      if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/
-      if (t < 0)                 {mmswap(L,l); l = L; goto loopB;}  /*535-5*/
-    }
-
-    loopA: eq_l = 1; eq_r = 1;  /* splitting type A */ /* left <= median < right */
-    for (;;) {
-      for (;;) {
-	if ((l += size) == r)
-	  {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
-	if (l == m) continue;
-	if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
-	if (t < 0) eq_l = 0;
-      }
-      for (;;) {
-	if (l == (r -= size))
-	  {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
-	if (r == m) {m = l; break;}
-	if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
-	if (t == 0) break;
-      }
-      mmswap(l,r);    /* swap left and right */
-    }
-
-    loopB: eq_l = 1; eq_r = 1;  /* splitting type B */ /* left < median <= right */
-    for (;;) {
-      for (;;) {
-	if (l == (r -= size))
-	  {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
-	if (r == m) continue;
-	if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
-	if (t > 0) eq_r = 0;
-      }
-      for (;;) {
-	if ((l += size) == r)
-	  {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
-	if (l == m) {m = r; break;}
-	if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
-	if (t == 0) break;
-      }
-      mmswap(l,r);    /* swap left and right */
-    }
-
-    fin:
-    if (eq_l == 0)                         /* need to sort left side */
-      if (eq_r == 0)                       /* need to sort right side */
-	if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */
-	else           {PUSH(L,l); L = r;} /* sort right side first */
-      else R = l;                          /* need to sort left side only */
-    else if (eq_r == 0) L = r;             /* need to sort right side only */
-    else goto nxt;                         /* need not to sort both sides */
-  }
-}
-
-char *
-ruby_strdup(const char *str)
-{
-    char *tmp;
-    int len = strlen(str) + 1;
-
-    tmp = xmalloc(len);
-    memcpy(tmp, str, len);
-
-    return tmp;
-}
-
-VALUE
-ruby_getcwd(void)
-{
-    char buf[PATH_MAX];
-    if (getcwd(buf, sizeof buf) == NULL) {
-	rb_sys_fail("getcwd");
-    }
-    VALUE str = rb_str_new2(buf);
-    OBJ_TAINT(str); 
-    return str;
-}
-
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to David M. Gay (dmg at acm dot org,
- * with " at " changed at "@" and " dot " changed to ".").	*/
-
-/* On a machine with IEEE extended-precision registers, it is
- * necessary to specify double-precision (53-bit) rounding precision
- * before invoking strtod or dtoa.  If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- *	_control87(PC_53, MCW_PC);
- * does this with many compilers.  Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule.  Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- *	1. We only require IEEE, IBM, or VAX double-precision
- *		arithmetic (not IEEE double-extended).
- *	2. We get by with floating-point arithmetic in a case that
- *		Clinger missed -- when we're computing d * 10^n
- *		for a small integer d and the integer n is not too
- *		much larger than 22 (the maximum integer k for which
- *		we can represent 10^k exactly), we may be able to
- *		compute (d*10^k) * 10^(e-k) with just one roundoff.
- *	3. Rather than a bit-at-a-time adjustment of the binary
- *		result in the hard case, we use floating-point
- *		arithmetic to determine the adjustment to within
- *		one bit; only in really hard cases do we need to
- *		compute a second residual.
- *	4. Because of 3., we don't need a large table of powers of 10
- *		for ten-to-e (just some small tables, e.g. of 10^k
- *		for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
- *	significant byte has the lowest address.
- * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
- *	significant byte has the lowest address.
- * #define Long int on machines with 32-bit ints and 64-bit longs.
- * #define IBM for IBM mainframe-style floating-point arithmetic.
- * #define VAX for VAX-style floating-point arithmetic (D_floating).
- * #define No_leftright to omit left-right logic in fast floating-point
- *	computation of dtoa.
- * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- *	and strtod and dtoa should round accordingly.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- *	and Honor_FLT_ROUNDS is not #defined.
- * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
- *	that use extended-precision instructions to compute rounded
- *	products and quotients) with IBM.
- * #define ROUND_BIASED for IEEE-format with biased rounding.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- *	products but inaccurate quotients, e.g., for Intel i860.
- * #define NO_LONG_LONG on machines that do not have a "long long"
- *	integer type (of >= 64 bits).  On such machines, you can
- *	#define Just_16 to store 16 bits per 32-bit Long when doing
- *	high-precision integer arithmetic.  Whether this speeds things
- *	up or slows things down depends on the machine and the number
- *	being converted.  If long long is available and the name is
- *	something other than "long long", #define Llong to be the name,
- *	and if "unsigned Llong" does not work as an unsigned version of
- *	Llong, #define #ULLong to be the corresponding unsigned type.
- * #define KR_headers for old-style C function headers.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- *	define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- *	FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
- *	if memory is available and otherwise does something you deem
- *	appropriate.  If MALLOC is undefined, malloc will be invoked
- *	directly -- and assumed always to succeed.
- * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
- *	memory allocations from a private pool of memory when possible.
- *	When used, the private pool is PRIVATE_MEM bytes long:  2304 bytes,
- *	unless #defined to be a different length.  This default length
- *	suffices to get rid of MALLOC calls except for unusual cases,
- *	such as decimal-to-binary conversion of a very long string of
- *	digits.  The longest string dtoa can return is about 751 bytes
- *	long.  For conversions by strtod of strings of 800 digits and
- *	all dtoa conversions in single-threaded executions with 8-byte
- *	pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
- *	pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- *	Infinity and NaN (case insensitively).  On some systems (e.g.,
- *	some HP systems), it may be necessary to #define NAN_WORD0
- *	appropriately -- to the most significant word of a quiet NaN.
- *	(On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- *	When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- *	strtod also accepts (case insensitively) strings of the form
- *	NaN(x), where x is a string of hexadecimal digits and spaces;
- *	if there is only one string of hexadecimal digits, it is taken
- *	for the 52 fraction bits of the resulting NaN; if there are two
- *	or more strings of hex digits, the first is for the high 20 bits,
- *	the second and subsequent for the low 32 bits, with intervening
- *	white space ignored; but if this results in none of the 52
- *	fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- *	and NAN_WORD1 are used instead.
- * #define MULTIPLE_THREADS if the system offers preemptively scheduled
- *	multiple threads.  In this case, you must provide (or suitably
- *	#define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
- *	by FREE_DTOA_LOCK(n) for n = 0 or 1.  (The second lock, accessed
- *	in pow5mult, ensures lazy evaluation of only one copy of high
- *	powers of 5; omitting this lock would introduce a small
- *	probability of wasting memory, but would otherwise be harmless.)
- *	You must also invoke freedtoa(s) to free the value s returned by
- *	dtoa.  You may do so whether or not MULTIPLE_THREADS is #defined.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- *	avoids underflows on inputs whose result does not underflow.
- *	If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- *	floating-point numbers and flushes underflows to zero rather
- *	than implementing gradual underflow, then you must also #define
- *	Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- *	arrays of ULongs.  This leads to slightly better code with
- *	some compilers and was always used prior to 19990916, but it
- *	is not strictly legal and can cause trouble with aggressively
- *	optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define USE_LOCALE to use the current locale's decimal_point value.
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- *	computation should be done to set the inexact flag when the
- *	result is inexact and avoid setting inexact when the result
- *	is exact.  In this case, dtoa.c must be compiled in
- *	an environment, perhaps provided by #include "dtoa.c" in a
- *	suitable wrapper, that defines two functions,
- *		int get_inexact(void);
- *		void clear_inexact(void);
- *	such that get_inexact() returns a nonzero value if the
- *	inexact bit is already set, and clear_inexact() sets the
- *	inexact bit to 0.  When SET_INEXACT is #defined, strtod
- *	also does extra computations to set the underflow and overflow
- *	flags when appropriate (i.e., when the result is tiny and
- *	inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- *	the result overflows to +-Infinity or underflows to 0.
- */
-
-#ifdef WORDS_BIGENDIAN
-#define IEEE_BIG_ENDIAN
-#else
-#define IEEE_LITTLE_ENDIAN
-#endif
-
-#ifdef __vax__
-#define VAX
-#undef IEEE_BIG_ENDIAN
-#undef IEEE_LITTLE_ENDIAN
-#endif
-
-#if defined(__arm__) && !defined(__VFP_FP__)
-#define IEEE_BIG_ENDIAN
-#undef IEEE_LITTLE_ENDIAN
-#endif
-
-#undef Long
-#undef ULong
-
-#if SIZEOF_INT == 4
-#define Long int
-#define ULong unsigned int
-#elif SIZEOF_LONG == 4
-#define Long long int
-#define ULong unsigned long int
-#endif
-
-#if HAVE_LONG_LONG
-#define Llong LONG_LONG
-#endif
-
-#ifdef DEBUG
-#include "stdio.h"
-#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
-#endif
-
-#include "stdlib.h"
-#include "string.h"
-
-#ifdef USE_LOCALE
-#include "locale.h"
-#endif
-
-#ifdef MALLOC
-extern void *MALLOC(size_t);
-#else
-#define MALLOC malloc
-#endif
-
-#ifndef Omit_Private_Memory
-#ifndef PRIVATE_MEM
-#define PRIVATE_MEM 2304
-#endif
-#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
-static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
-#endif
-
-#undef IEEE_Arith
-#undef Avoid_Underflow
-#ifdef IEEE_BIG_ENDIAN
-#define IEEE_Arith
-#endif
-#ifdef IEEE_LITTLE_ENDIAN
-#define IEEE_Arith
-#endif
-
-#ifdef Bad_float_h
-
-#ifdef IEEE_Arith
-#define DBL_DIG 15
-#define DBL_MAX_10_EXP 308
-#define DBL_MAX_EXP 1024
-#define FLT_RADIX 2
-#endif /*IEEE_Arith*/
-
-#ifdef IBM
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 75
-#define DBL_MAX_EXP 63
-#define FLT_RADIX 16
-#define DBL_MAX 7.2370055773322621e+75
-#endif
-
-#ifdef VAX
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 38
-#define DBL_MAX_EXP 127
-#define FLT_RADIX 2
-#define DBL_MAX 1.7014118346046923e+38
-#endif
-
-#ifndef LONG_MAX
-#define LONG_MAX 2147483647
-#endif
-
-#else /* ifndef Bad_float_h */
-#include "float.h"
-#endif /* Bad_float_h */
-
-#ifndef __MATH_H__
-#include "math.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1
-Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM should be defined.
-#endif
-
-typedef union { double d; ULong L[2]; } U;
-
-#ifdef YES_ALIAS
-#define dval(x) x
-#ifdef IEEE_LITTLE_ENDIAN
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
-#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
-#endif
-#else
-#ifdef IEEE_LITTLE_ENDIAN
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
-#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
-((unsigned short *)a)[0] = (unsigned short)c, a++)
-#else
-#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
-((unsigned short *)a)[1] = (unsigned short)c, a++)
-#endif
-
-/* #define P DBL_MANT_DIG */
-/* Ten_pmax = floor(P*log(2)/log(5)) */
-/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
-/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
-/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
-
-#ifdef IEEE_Arith
-#define Exp_shift  20
-#define Exp_shift1 20
-#define Exp_msk1    0x100000
-#define Exp_msk11   0x100000
-#define Exp_mask  0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1  0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask  0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask  0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-#ifndef NO_IEEE_Scale
-#define Avoid_Underflow
-#ifdef Flush_Denorm	/* debugging option */
-#undef Sudden_Underflow
-#endif
-#endif
-
-#ifndef Flt_Rounds
-#ifdef FLT_ROUNDS
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
-#undef Check_FLT_ROUNDS
-#define Check_FLT_ROUNDS
-#else
-#define Rounding Flt_Rounds
-#endif
-
-#else /* ifndef IEEE_Arith */
-#undef Check_FLT_ROUNDS
-#undef Honor_FLT_ROUNDS
-#undef SET_INEXACT
-#undef  Sudden_Underflow
-#define Sudden_Underflow
-#ifdef IBM
-#undef Flt_Rounds
-#define Flt_Rounds 0
-#define Exp_shift  24
-#define Exp_shift1 24
-#define Exp_msk1   0x1000000
-#define Exp_msk11  0x1000000
-#define Exp_mask  0x7f000000
-#define P 14
-#define Bias 65
-#define Exp_1  0x41000000
-#define Exp_11 0x41000000
-#define Ebits 8	/* exponent has 7 bits, but 8 is the right value in b2d */
-#define Frac_mask  0xffffff
-#define Frac_mask1 0xffffff
-#define Bletch 4
-#define Ten_pmax 22
-#define Bndry_mask  0xefffff
-#define Bndry_mask1 0xffffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 4
-#define Tiny0 0x100000
-#define Tiny1 0
-#define Quick_max 14
-#define Int_max 15
-#else /* VAX */
-#undef Flt_Rounds
-#define Flt_Rounds 1
-#define Exp_shift  23
-#define Exp_shift1 7
-#define Exp_msk1    0x80
-#define Exp_msk11   0x800000
-#define Exp_mask  0x7f80
-#define P 56
-#define Bias 129
-#define Exp_1  0x40800000
-#define Exp_11 0x4080
-#define Ebits 8
-#define Frac_mask  0x7fffff
-#define Frac_mask1 0xffff007f
-#define Ten_pmax 24
-#define Bletch 2
-#define Bndry_mask  0xffff007f
-#define Bndry_mask1 0xffff007f
-#define LSB 0x10000
-#define Sign_bit 0x8000
-#define Log2P 1
-#define Tiny0 0x80
-#define Tiny1 0
-#define Quick_max 15
-#define Int_max 15
-#endif /* IBM, VAX */
-#endif /* IEEE_Arith */
-
-#ifndef IEEE_Arith
-#define ROUND_BIASED
-#endif
-
-#ifdef RND_PRODQUOT
-#define rounded_product(a,b) a = rnd_prod(a, b)
-#define rounded_quotient(a,b) a = rnd_quot(a, b)
-extern double rnd_prod(double, double), rnd_quot(double, double);
-#else
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
-#endif
-
-#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
-#define Big1 0xffffffff
-
-#ifndef Pack_32
-#define Pack_32
-#endif
-
-#define FFFFFFFF 0xffffffffUL
-
-#ifdef NO_LONG_LONG
-#undef ULLong
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower.  Hence the default is now to store 32 bits per Long.
- */
-#endif
-#else	/* long long available */
-#ifndef Llong
-#define Llong long long
-#endif
-#ifndef ULLong
-#define ULLong unsigned Llong
-#endif
-#endif /* NO_LONG_LONG */
-
-#ifndef MULTIPLE_THREADS
-#define ACQUIRE_DTOA_LOCK(n)	/*nothing*/
-#define FREE_DTOA_LOCK(n)	/*nothing*/
-#endif
-
-#define Kmax 15
-
-struct Bigint {
-    struct Bigint *next;
-    int k, maxwds, sign, wds;
-    ULong x[1];
-};
-
-typedef struct Bigint Bigint;
-
-static Bigint *freelist[Kmax+1];
-
-static Bigint *
-Balloc(int k)
-{
-    int x;
-    Bigint *rv;
-#ifndef Omit_Private_Memory
-    unsigned int len;
-#endif
-
-    ACQUIRE_DTOA_LOCK(0);
-    if ((rv = freelist[k]) != 0) {
-        freelist[k] = rv->next;
-    }
-    else {
-        x = 1 << k;
-#ifdef Omit_Private_Memory
-        rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
-#else
-        len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
-                /sizeof(double);
-        if (pmem_next - private_mem + len <= PRIVATE_mem) {
-            rv = (Bigint*)pmem_next;
-            pmem_next += len;
-        }
-        else
-            rv = (Bigint*)MALLOC(len*sizeof(double));
-#endif
-        rv->k = k;
-        rv->maxwds = x;
-    }
-    FREE_DTOA_LOCK(0);
-    rv->sign = rv->wds = 0;
-    return rv;
-}
-
-static void
-Bfree(Bigint *v)
-{
-    if (v) {
-        ACQUIRE_DTOA_LOCK(0);
-        v->next = freelist[v->k];
-        freelist[v->k] = v;
-        FREE_DTOA_LOCK(0);
-    }
-}
-
-#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
-y->wds*sizeof(Long) + 2*sizeof(int))
-
-static Bigint *
-multadd(Bigint *b, int m, int a)   /* multiply by m and add a */
-{
-    int i, wds;
-#ifdef ULLong
-    ULong *x;
-    ULLong carry, y;
-#else
-    ULong carry, *x, y;
-#ifdef Pack_32
-    ULong xi, z;
-#endif
-#endif
-    Bigint *b1;
-
-    wds = b->wds;
-    x = b->x;
-    i = 0;
-    carry = a;
-    do {
-#ifdef ULLong
-        y = *x * (ULLong)m + carry;
-        carry = y >> 32;
-        *x++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-        xi = *x;
-        y = (xi & 0xffff) * m + carry;
-        z = (xi >> 16) * m + (y >> 16);
-        carry = z >> 16;
-        *x++ = (z << 16) + (y & 0xffff);
-#else
-        y = *x * m + carry;
-        carry = y >> 16;
-        *x++ = y & 0xffff;
-#endif
-#endif
-    } while (++i < wds);
-    if (carry) {
-        if (wds >= b->maxwds) {
-            b1 = Balloc(b->k+1);
-            Bcopy(b1, b);
-            Bfree(b);
-            b = b1;
-        }
-        b->x[wds++] = carry;
-        b->wds = wds;
-    }
-    return b;
-}
-
-static Bigint *
-s2b(const char *s, int nd0, int nd, ULong y9)
-{
-    Bigint *b;
-    int i, k;
-    Long x, y;
-
-    x = (nd + 8) / 9;
-    for (k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
-    b = Balloc(k);
-    b->x[0] = y9;
-    b->wds = 1;
-#else
-    b = Balloc(k+1);
-    b->x[0] = y9 & 0xffff;
-    b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
-    i = 9;
-    if (9 < nd0) {
-        s += 9;
-        do {
-            b = multadd(b, 10, *s++ - '0');
-        } while (++i < nd0);
-        s++;
-    }
-    else
-        s += 10;
-    for (; i < nd; i++)
-        b = multadd(b, 10, *s++ - '0');
-    return b;
-}
-
-static int
-hi0bits(register ULong x)
-{
-    register int k = 0;
-
-    if (!(x & 0xffff0000)) {
-        k = 16;
-        x <<= 16;
-    }
-    if (!(x & 0xff000000)) {
-        k += 8;
-        x <<= 8;
-    }
-    if (!(x & 0xf0000000)) {
-        k += 4;
-        x <<= 4;
-    }
-    if (!(x & 0xc0000000)) {
-        k += 2;
-        x <<= 2;
-    }
-    if (!(x & 0x80000000)) {
-        k++;
-        if (!(x & 0x40000000))
-            return 32;
-    }
-    return k;
-}
-
-static int
-lo0bits(ULong *y)
-{
-    register int k;
-    register ULong x = *y;
-
-    if (x & 7) {
-        if (x & 1)
-            return 0;
-        if (x & 2) {
-            *y = x >> 1;
-            return 1;
-        }
-        *y = x >> 2;
-        return 2;
-    }
-    k = 0;
-    if (!(x & 0xffff)) {
-        k = 16;
-        x >>= 16;
-    }
-    if (!(x & 0xff)) {
-        k += 8;
-        x >>= 8;
-    }
-    if (!(x & 0xf)) {
-        k += 4;
-        x >>= 4;
-    }
-    if (!(x & 0x3)) {
-        k += 2;
-        x >>= 2;
-    }
-    if (!(x & 1)) {
-        k++;
-        x >>= 1;
-        if (!x)
-            return 32;
-    }
-    *y = x;
-    return k;
-}
-
-static Bigint *
-i2b(int i)
-{
-    Bigint *b;
-
-    b = Balloc(1);
-    b->x[0] = i;
-    b->wds = 1;
-    return b;
-}
-
-static Bigint *
-mult(Bigint *a, Bigint *b)
-{
-    Bigint *c;
-    int k, wa, wb, wc;
-    ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
-    ULong y;
-#ifdef ULLong
-    ULLong carry, z;
-#else
-    ULong carry, z;
-#ifdef Pack_32
-    ULong z2;
-#endif
-#endif
-
-    if (a->wds < b->wds) {
-        c = a;
-        a = b;
-        b = c;
-    }
-    k = a->k;
-    wa = a->wds;
-    wb = b->wds;
-    wc = wa + wb;
-    if (wc > a->maxwds)
-        k++;
-    c = Balloc(k);
-    for (x = c->x, xa = x + wc; x < xa; x++)
-        *x = 0;
-    xa = a->x;
-    xae = xa + wa;
-    xb = b->x;
-    xbe = xb + wb;
-    xc0 = c->x;
-#ifdef ULLong
-    for (; xb < xbe; xc0++) {
-        if ((y = *xb++) != 0) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = *x++ * (ULLong)y + *xc + carry;
-                carry = z >> 32;
-                *xc++ = z & FFFFFFFF;
-            } while (x < xae);
-            *xc = carry;
-        }
-    }
-#else
-#ifdef Pack_32
-    for (; xb < xbe; xb++, xc0++) {
-        if (y = *xb & 0xffff) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
-                carry = z >> 16;
-                z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
-                carry = z2 >> 16;
-                Storeinc(xc, z2, z);
-            } while (x < xae);
-            *xc = carry;
-        }
-        if (y = *xb >> 16) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            z2 = *xc;
-            do {
-                z = (*x & 0xffff) * y + (*xc >> 16) + carry;
-                carry = z >> 16;
-                Storeinc(xc, z, z2);
-                z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
-                carry = z2 >> 16;
-            } while (x < xae);
-            *xc = z2;
-        }
-    }
-#else
-    for (; xb < xbe; xc0++) {
-        if (y = *xb++) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = *x++ * y + *xc + carry;
-                carry = z >> 16;
-                *xc++ = z & 0xffff;
-            } while (x < xae);
-            *xc = carry;
-        }
-    }
-#endif
-#endif
-    for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
-    c->wds = wc;
-    return c;
-}
-
-static Bigint *p5s;
-
-static Bigint *
-pow5mult(Bigint *b, int k)
-{
-    Bigint *b1, *p5, *p51;
-    int i;
-    static int p05[3] = { 5, 25, 125 };
-
-    if ((i = k & 3) != 0)
-        b = multadd(b, p05[i-1], 0);
-
-    if (!(k >>= 2))
-        return b;
-    if (!(p5 = p5s)) {
-        /* first time */
-#ifdef MULTIPLE_THREADS
-        ACQUIRE_DTOA_LOCK(1);
-        if (!(p5 = p5s)) {
-            p5 = p5s = i2b(625);
-            p5->next = 0;
-        }
-        FREE_DTOA_LOCK(1);
-#else
-        p5 = p5s = i2b(625);
-        p5->next = 0;
-#endif
-    }
-    for (;;) {
-        if (k & 1) {
-            b1 = mult(b, p5);
-            Bfree(b);
-            b = b1;
-        }
-        if (!(k >>= 1))
-            break;
-        if (!(p51 = p5->next)) {
-#ifdef MULTIPLE_THREADS
-            ACQUIRE_DTOA_LOCK(1);
-            if (!(p51 = p5->next)) {
-                p51 = p5->next = mult(p5,p5);
-                p51->next = 0;
-            }
-            FREE_DTOA_LOCK(1);
-#else
-            p51 = p5->next = mult(p5,p5);
-            p51->next = 0;
-#endif
-        }
-        p5 = p51;
-    }
-    return b;
-}
-
-static Bigint *
-lshift(Bigint *b, int k)
-{
-    int i, k1, n, n1;
-    Bigint *b1;
-    ULong *x, *x1, *xe, z;
-
-#ifdef Pack_32
-    n = k >> 5;
-#else
-    n = k >> 4;
-#endif
-    k1 = b->k;
-    n1 = n + b->wds + 1;
-    for (i = b->maxwds; n1 > i; i <<= 1)
-        k1++;
-    b1 = Balloc(k1);
-    x1 = b1->x;
-    for (i = 0; i < n; i++)
-        *x1++ = 0;
-    x = b->x;
-    xe = x + b->wds;
-#ifdef Pack_32
-    if (k &= 0x1f) {
-        k1 = 32 - k;
-        z = 0;
-        do {
-            *x1++ = *x << k | z;
-            z = *x++ >> k1;
-        } while (x < xe);
-        if ((*x1 = z) != 0)
-            ++n1;
-    }
-#else
-    if (k &= 0xf) {
-        k1 = 16 - k;
-        z = 0;
-        do {
-            *x1++ = *x << k  & 0xffff | z;
-            z = *x++ >> k1;
-        } while (x < xe);
-        if (*x1 = z)
-            ++n1;
-    }
-#endif
-    else
-        do {
-            *x1++ = *x++;
-        } while (x < xe);
-    b1->wds = n1 - 1;
-    Bfree(b);
-    return b1;
-}
-
-static int
-cmp(Bigint *a, Bigint *b)
-{
-    ULong *xa, *xa0, *xb, *xb0;
-    int i, j;
-
-    i = a->wds;
-    j = b->wds;
-#ifdef DEBUG
-    if (i > 1 && !a->x[i-1])
-        Bug("cmp called with a->x[a->wds-1] == 0");
-    if (j > 1 && !b->x[j-1])
-        Bug("cmp called with b->x[b->wds-1] == 0");
-#endif
-    if (i -= j)
-        return i;
-    xa0 = a->x;
-    xa = xa0 + j;
-    xb0 = b->x;
-    xb = xb0 + j;
-    for (;;) {
-        if (*--xa != *--xb)
-            return *xa < *xb ? -1 : 1;
-        if (xa <= xa0)
-            break;
-    }
-    return 0;
-}
-
-static Bigint *
-diff(Bigint *a, Bigint *b)
-{
-    Bigint *c;
-    int i, wa, wb;
-    ULong *xa, *xae, *xb, *xbe, *xc;
-#ifdef ULLong
-    ULLong borrow, y;
-#else
-    ULong borrow, y;
-#ifdef Pack_32
-    ULong z;
-#endif
-#endif
-
-    i = cmp(a,b);
-    if (!i) {
-        c = Balloc(0);
-        c->wds = 1;
-        c->x[0] = 0;
-        return c;
-    }
-    if (i < 0) {
-        c = a;
-        a = b;
-        b = c;
-        i = 1;
-    }
-    else
-        i = 0;
-    c = Balloc(a->k);
-    c->sign = i;
-    wa = a->wds;
-    xa = a->x;
-    xae = xa + wa;
-    wb = b->wds;
-    xb = b->x;
-    xbe = xb + wb;
-    xc = c->x;
-    borrow = 0;
-#ifdef ULLong
-    do {
-        y = (ULLong)*xa++ - *xb++ - borrow;
-        borrow = y >> 32 & (ULong)1;
-        *xc++ = y & FFFFFFFF;
-    } while (xb < xbe);
-    while (xa < xae) {
-        y = *xa++ - borrow;
-        borrow = y >> 32 & (ULong)1;
-        *xc++ = y & FFFFFFFF;
-    }
-#else
-#ifdef Pack_32
-    do {
-        y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
-        borrow = (y & 0x10000) >> 16;
-        z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
-        borrow = (z & 0x10000) >> 16;
-        Storeinc(xc, z, y);
-    } while (xb < xbe);
-    while (xa < xae) {
-        y = (*xa & 0xffff) - borrow;
-        borrow = (y & 0x10000) >> 16;
-        z = (*xa++ >> 16) - borrow;
-        borrow = (z & 0x10000) >> 16;
-        Storeinc(xc, z, y);
-    }
-#else
-    do {
-        y = *xa++ - *xb++ - borrow;
-        borrow = (y & 0x10000) >> 16;
-        *xc++ = y & 0xffff;
-    } while (xb < xbe);
-    while (xa < xae) {
-        y = *xa++ - borrow;
-        borrow = (y & 0x10000) >> 16;
-        *xc++ = y & 0xffff;
-    }
-#endif
-#endif
-    while (!*--xc)
-        wa--;
-    c->wds = wa;
-    return c;
-}
-
-static double
-ulp(double x)
-{
-    register Long L;
-    double a;
-
-    L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-    if (L > 0) {
-#endif
-#endif
-#ifdef IBM
-        L |= Exp_msk1 >> 4;
-#endif
-        word0(a) = L;
-        word1(a) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-    }
-    else {
-        L = -L >> Exp_shift;
-        if (L < Exp_shift) {
-            word0(a) = 0x80000 >> L;
-            word1(a) = 0;
-        }
-        else {
-            word0(a) = 0;
-            L -= Exp_shift;
-            word1(a) = L >= 31 ? 1 : 1 << 31 - L;
-        }
-    }
-#endif
-#endif
-    return dval(a);
-}
-
-static double
-b2d(Bigint *a, int *e)
-{
-    ULong *xa, *xa0, w, y, z;
-    int k;
-    double d;
-#ifdef VAX
-    ULong d0, d1;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-    xa0 = a->x;
-    xa = xa0 + a->wds;
-    y = *--xa;
-#ifdef DEBUG
-    if (!y) Bug("zero y in b2d");
-#endif
-    k = hi0bits(y);
-    *e = 32 - k;
-#ifdef Pack_32
-    if (k < Ebits) {
-        d0 = Exp_1 | y >> (Ebits - k);
-        w = xa > xa0 ? *--xa : 0;
-        d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
-        goto ret_d;
-    }
-    z = xa > xa0 ? *--xa : 0;
-    if (k -= Ebits) {
-        d0 = Exp_1 | y << k | z >> (32 - k);
-        y = xa > xa0 ? *--xa : 0;
-        d1 = z << k | y >> (32 - k);
-    }
-    else {
-        d0 = Exp_1 | y;
-        d1 = z;
-    }
-#else
-    if (k < Ebits + 16) {
-        z = xa > xa0 ? *--xa : 0;
-        d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
-        w = xa > xa0 ? *--xa : 0;
-        y = xa > xa0 ? *--xa : 0;
-        d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
-        goto ret_d;
-    }
-    z = xa > xa0 ? *--xa : 0;
-    w = xa > xa0 ? *--xa : 0;
-    k -= Ebits + 16;
-    d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
-    y = xa > xa0 ? *--xa : 0;
-    d1 = w << k + 16 | y << k;
-#endif
-ret_d:
-#ifdef VAX
-    word0(d) = d0 >> 16 | d0 << 16;
-    word1(d) = d1 >> 16 | d1 << 16;
-#else
-#undef d0
-#undef d1
-#endif
-    return dval(d);
-}
-
-static Bigint *
-d2b(double d, int *e, int *bits)
-{
-    Bigint *b;
-    int de, k;
-    ULong *x, y, z;
-#ifndef Sudden_Underflow
-    int i;
-#endif
-#ifdef VAX
-    ULong d0, d1;
-    d0 = word0(d) >> 16 | word0(d) << 16;
-    d1 = word1(d) >> 16 | word1(d) << 16;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-#ifdef Pack_32
-    b = Balloc(1);
-#else
-    b = Balloc(2);
-#endif
-    x = b->x;
-
-    z = d0 & Frac_mask;
-    d0 &= 0x7fffffff;   /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
-    de = (int)(d0 >> Exp_shift);
-#ifndef IBM
-    z |= Exp_msk11;
-#endif
-#else
-    if ((de = (int)(d0 >> Exp_shift)) != 0)
-        z |= Exp_msk1;
-#endif
-#ifdef Pack_32
-    if ((y = d1) != 0) {
-        if ((k = lo0bits(&y)) != 0) {
-            x[0] = y | z << (32 - k);
-            z >>= k;
-        }
-        else
-            x[0] = y;
-#ifndef Sudden_Underflow
-        i =
-#endif
-        b->wds = (x[1] = z) ? 2 : 1;
-    }
-    else {
-#ifdef DEBUG
-        if (!z)
-            Bug("Zero passed to d2b");
-#endif
-        k = lo0bits(&z);
-        x[0] = z;
-#ifndef Sudden_Underflow
-        i =
-#endif
-        b->wds = 1;
-        k += 32;
-    }
-#else
-    if (y = d1) {
-        if (k = lo0bits(&y))
-            if (k >= 16) {
-                x[0] = y | z << 32 - k & 0xffff;
-                x[1] = z >> k - 16 & 0xffff;
-                x[2] = z >> k;
-                i = 2;
-            }
-            else {
-                x[0] = y & 0xffff;
-                x[1] = y >> 16 | z << 16 - k & 0xffff;
-                x[2] = z >> k & 0xffff;
-                x[3] = z >> k+16;
-                i = 3;
-            }
-        else {
-            x[0] = y & 0xffff;
-            x[1] = y >> 16;
-            x[2] = z & 0xffff;
-            x[3] = z >> 16;
-            i = 3;
-        }
-    }
-    else {
-#ifdef DEBUG
-        if (!z)
-            Bug("Zero passed to d2b");
-#endif
-        k = lo0bits(&z);
-        if (k >= 16) {
-            x[0] = z;
-            i = 0;
-        }
-        else {
-            x[0] = z & 0xffff;
-            x[1] = z >> 16;
-            i = 1;
-        }
-        k += 32;
-    }
-    while (!x[i])
-        --i;
-    b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
-    if (de) {
-#endif
-#ifdef IBM
-        *e = (de - Bias - (P-1) << 2) + k;
-        *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
-#else
-        *e = de - Bias - (P-1) + k;
-        *bits = P - k;
-#endif
-#ifndef Sudden_Underflow
-    }
-    else {
-        *e = de - Bias - (P-1) + 1 + k;
-#ifdef Pack_32
-        *bits = 32*i - hi0bits(x[i-1]);
-#else
-        *bits = (i+2)*16 - hi0bits(x[i]);
-#endif
-    }
-#endif
-    return b;
-}
-#undef d0
-#undef d1
-
-static double
-ratio(Bigint *a, Bigint *b)
-{
-    double da, db;
-    int k, ka, kb;
-
-    dval(da) = b2d(a, &ka);
-    dval(db) = b2d(b, &kb);
-#ifdef Pack_32
-    k = ka - kb + 32*(a->wds - b->wds);
-#else
-    k = ka - kb + 16*(a->wds - b->wds);
-#endif
-#ifdef IBM
-    if (k > 0) {
-        word0(da) += (k >> 2)*Exp_msk1;
-        if (k &= 3)
-            dval(da) *= 1 << k;
-    }
-    else {
-        k = -k;
-        word0(db) += (k >> 2)*Exp_msk1;
-        if (k &= 3)
-            dval(db) *= 1 << k;
-    }
-#else
-    if (k > 0)
-        word0(da) += k*Exp_msk1;
-    else {
-        k = -k;
-        word0(db) += k*Exp_msk1;
-    }
-#endif
-    return dval(da) / dval(db);
-}
-
-static const double
-tens[] = {
-    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-    1e20, 1e21, 1e22
-#ifdef VAX
-    , 1e23, 1e24
-#endif
-};
-
-static const double
-#ifdef IEEE_Arith
-bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
-    9007199254740992.*9007199254740992.e-256
-    /* = 2^106 * 1e-53 */
-#else
-    1e-256
-#endif
-};
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-#else
-#ifdef IBM
-bigtens[] = { 1e16, 1e32, 1e64 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64 };
-#define n_bigtens 3
-#else
-bigtens[] = { 1e16, 1e32 };
-static const double tinytens[] = { 1e-16, 1e-32 };
-#define n_bigtens 2
-#endif
-#endif
-
-#ifndef IEEE_Arith
-#undef INFNAN_CHECK
-#endif
-
-#ifdef INFNAN_CHECK
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
-static int
-match(const char **sp, char *t)
-{
-    int c, d;
-    const char *s = *sp;
-
-    while (d = *t++) {
-        if ((c = *++s) >= 'A' && c <= 'Z')
-            c += 'a' - 'A';
-        if (c != d)
-            return 0;
-    }
-    *sp = s + 1;
-    return 1;
-}
-
-#ifndef No_Hex_NaN
-static void
-hexnan(double *rvp, const char **sp)
-{
-    ULong c, x[2];
-    const char *s;
-    int havedig, udx0, xshift;
-
-    x[0] = x[1] = 0;
-    havedig = xshift = 0;
-    udx0 = 1;
-    s = *sp;
-    while (c = *(const unsigned char*)++s) {
-        if (c >= '0' && c <= '9')
-            c -= '0';
-        else if (c >= 'a' && c <= 'f')
-            c += 10 - 'a';
-        else if (c >= 'A' && c <= 'F')
-            c += 10 - 'A';
-        else if (c <= ' ') {
-            if (udx0 && havedig) {
-                udx0 = 0;
-                xshift = 1;
-            }
-            continue;
-        }
-        else if (/*(*/ c == ')' && havedig) {
-            *sp = s + 1;
-            break;
-        }
-        else
-            return; /* invalid form: don't change *sp */
-        havedig = 1;
-        if (xshift) {
-            xshift = 0;
-            x[0] = x[1];
-            x[1] = 0;
-        }
-        if (udx0)
-            x[0] = (x[0] << 4) | (x[1] >> 28);
-        x[1] = (x[1] << 4) | c;
-    }
-    if ((x[0] &= 0xfffff) || x[1]) {
-        word0(*rvp) = Exp_mask | x[0];
-        word1(*rvp) = x[1];
-    }
-}
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
-double
-ruby_strtod(const char *s00, char **se)
-{
-#ifdef Avoid_Underflow
-    int scale;
-#endif
-    int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
-         e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
-    const char *s, *s0, *s1;
-    double aadj, aadj1, adj, rv, rv0;
-    Long L;
-    ULong y, z;
-    Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
-#ifdef SET_INEXACT
-    int inexact, oldinexact;
-#endif
-#ifdef Honor_FLT_ROUNDS
-    int rounding;
-#endif
-#ifdef USE_LOCALE
-    const char *s2;
-#endif
-
-    errno = 0;
-    sign = nz0 = nz = 0;
-    dval(rv) = 0.;
-    for (s = s00;;s++)
-        switch (*s) {
-          case '-':
-            sign = 1;
-            /* no break */
-          case '+':
-            if (*++s)
-                goto break2;
-            /* no break */
-          case 0:
-            goto ret0;
-          case '\t':
-          case '\n':
-          case '\v':
-          case '\f':
-          case '\r':
-          case ' ':
-            continue;
-          default:
-            goto break2;
-        }
-break2:
-    if (*s == '0') {
-      if (s[1] == 'x' || s[1] == 'X') {
-	  static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
-	  s0 = ++s;
-	  adj = 0;
-
-	  while (*++s && (s1 = strchr(hexdigit, *s))) {
-	      adj *= 16;
-	      adj += (s1 - hexdigit) & 15;
-	  }
-
-	  if (*s == '.') {
-	      aadj = 1.;
-	      while (*++s && (s1 = strchr(hexdigit, *s))) {
-		  aadj /= 16;
-		  adj += aadj * ((s1 - hexdigit) & 15);
-	      }
-	  }
-
-	  if (*s == 'P' || *s == 'p') {
-	      dsign = 0x2C - *++s; /* +: 2B, -: 2D */
-	      if (abs(dsign) == 1) s++;
-	      else dsign = 1;
-
-	      for (nd = 0; (c = *s) >= '0' && c <= '9'; s++) {
-		  nd *= 10;
-		  nd += c;
-		  nd -= '0';
-	      }
-	      dval(rv) = ldexp(adj, nd * dsign);
-	  }
-	  else {
-	      dval(rv) = adj;
-	  }
-	  goto ret;
-      }
-      nz0 = 1;
-      while (*++s == '0') ;
-      if (!*s)
-	  goto ret;
-    }
-    s0 = s;
-    y = z = 0;
-    for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
-        if (nd < 9)
-            y = 10*y + c - '0';
-        else if (nd < 16)
-            z = 10*z + c - '0';
-    nd0 = nd;
-#ifdef USE_LOCALE
-    s1 = localeconv()->decimal_point;
-    if (c == *s1) {
-        c = '.';
-        if (*++s1) {
-            s2 = s;
-            for (;;) {
-                if (*++s2 != *s1) {
-                    c = 0;
-                    break;
-                }
-                if (!*++s1) {
-                    s = s2;
-                    break;
-                }
-            }
-        }
-    }
-#endif
-    if (c == '.') {
-        if (!ISDIGIT(s[1])) {
-            goto dig_done;
-	}
-        c = *++s;
-        if (!nd) {
-            for (; c == '0'; c = *++s)
-                nz++;
-            if (c > '0' && c <= '9') {
-                s0 = s;
-                nf += nz;
-                nz = 0;
-                goto have_dig;
-            }
-            goto dig_done;
-        }
-        for (; c >= '0' && c <= '9'; c = *++s) {
-have_dig:
-            nz++;
-            if (c -= '0') {
-                nf += nz;
-                for (i = 1; i < nz; i++)
-                    if (nd++ < 9)
-                        y *= 10;
-                    else if (nd <= DBL_DIG + 1)
-                        z *= 10;
-                if (nd++ < 9)
-                    y = 10*y + c;
-                else if (nd <= DBL_DIG + 1)
-                    z = 10*z + c;
-                nz = 0;
-            }
-        }
-    }
-dig_done:
-    e = 0;
-    if (c == 'e' || c == 'E') {
-        if (!nd && !nz && !nz0) {
-            goto ret0;
-        }
-        s00 = s;
-        esign = 0;
-        switch (c = *++s) {
-          case '-':
-            esign = 1;
-          case '+':
-            c = *++s;
-        }
-        if (c >= '0' && c <= '9') {
-            while (c == '0')
-                c = *++s;
-            if (c > '0' && c <= '9') {
-                L = c - '0';
-                s1 = s;
-                while ((c = *++s) >= '0' && c <= '9')
-                    L = 10*L + c - '0';
-                if (s - s1 > 8 || L > 19999)
-                    /* Avoid confusion from exponents
-                     * so large that e might overflow.
-                     */
-                    e = 19999; /* safe for 16 bit ints */
-                else
-                    e = (int)L;
-                if (esign)
-                    e = -e;
-            }
-            else
-                e = 0;
-        }
-        else
-            s = s00;
-    }
-    if (!nd) {
-        if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
-            /* Check for Nan and Infinity */
-            switch (c) {
-              case 'i':
-              case 'I':
-                if (match(&s,"nf")) {
-                    --s;
-                    if (!match(&s,"inity"))
-                        ++s;
-                    word0(rv) = 0x7ff00000;
-                    word1(rv) = 0;
-                    goto ret;
-                }
-                break;
-              case 'n':
-              case 'N':
-                if (match(&s, "an")) {
-                    word0(rv) = NAN_WORD0;
-                    word1(rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
-                    if (*s == '(') /*)*/
-                        hexnan(&rv, &s);
-#endif
-                    goto ret;
-                }
-            }
-#endif /* INFNAN_CHECK */
-ret0:
-            s = s00;
-            sign = 0;
-        }
-        goto ret;
-    }
-    e1 = e -= nf;
-
-    /* Now we have nd0 digits, starting at s0, followed by a
-     * decimal point, followed by nd-nd0 digits.  The number we're
-     * after is the integer represented by those digits times
-     * 10**e */
-
-    if (!nd0)
-        nd0 = nd;
-    k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
-    dval(rv) = y;
-    if (k > 9) {
-#ifdef SET_INEXACT
-        if (k > DBL_DIG)
-            oldinexact = get_inexact();
-#endif
-        dval(rv) = tens[k - 9] * dval(rv) + z;
-    }
-    bd0 = bb = bd = bs = delta = 0;
-    if (nd <= DBL_DIG
-#ifndef RND_PRODQUOT
-#ifndef Honor_FLT_ROUNDS
-        && Flt_Rounds == 1
-#endif
-#endif
-    ) {
-        if (!e)
-            goto ret;
-        if (e > 0) {
-            if (e <= Ten_pmax) {
-#ifdef VAX
-                goto vax_ovfl_check;
-#else
-#ifdef Honor_FLT_ROUNDS
-                /* round correctly FLT_ROUNDS = 2 or 3 */
-                if (sign) {
-                    rv = -rv;
-                    sign = 0;
-                }
-#endif
-                /* rv = */ rounded_product(dval(rv), tens[e]);
-                goto ret;
-#endif
-            }
-            i = DBL_DIG - nd;
-            if (e <= Ten_pmax + i) {
-                /* A fancier test would sometimes let us do
-                 * this for larger i values.
-                 */
-#ifdef Honor_FLT_ROUNDS
-                /* round correctly FLT_ROUNDS = 2 or 3 */
-                if (sign) {
-                    rv = -rv;
-                    sign = 0;
-                }
-#endif
-                e -= i;
-                dval(rv) *= tens[i];
-#ifdef VAX
-                /* VAX exponent range is so narrow we must
-                 * worry about overflow here...
-                 */
-vax_ovfl_check:
-                word0(rv) -= P*Exp_msk1;
-                /* rv = */ rounded_product(dval(rv), tens[e]);
-                if ((word0(rv) & Exp_mask)
-                        > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
-                    goto ovfl;
-                word0(rv) += P*Exp_msk1;
-#else
-                /* rv = */ rounded_product(dval(rv), tens[e]);
-#endif
-                goto ret;
-            }
-        }
-#ifndef Inaccurate_Divide
-        else if (e >= -Ten_pmax) {
-#ifdef Honor_FLT_ROUNDS
-            /* round correctly FLT_ROUNDS = 2 or 3 */
-            if (sign) {
-                rv = -rv;
-                sign = 0;
-            }
-#endif
-            /* rv = */ rounded_quotient(dval(rv), tens[-e]);
-            goto ret;
-        }
-#endif
-    }
-    e1 += nd - k;
-
-#ifdef IEEE_Arith
-#ifdef SET_INEXACT
-    inexact = 1;
-    if (k <= DBL_DIG)
-        oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
-    scale = 0;
-#endif
-#ifdef Honor_FLT_ROUNDS
-    if ((rounding = Flt_Rounds) >= 2) {
-        if (sign)
-            rounding = rounding == 2 ? 0 : 2;
-        else
-            if (rounding != 2)
-                rounding = 0;
-    }
-#endif
-#endif /*IEEE_Arith*/
-
-    /* Get starting approximation = rv * 10**e1 */
-
-    if (e1 > 0) {
-        if ((i = e1 & 15) != 0)
-            dval(rv) *= tens[i];
-        if (e1 &= ~15) {
-            if (e1 > DBL_MAX_10_EXP) {
-ovfl:
-#ifndef NO_ERRNO
-                errno = ERANGE;
-#endif
-                /* Can't trust HUGE_VAL */
-#ifdef IEEE_Arith
-#ifdef Honor_FLT_ROUNDS
-                switch (rounding) {
-                  case 0: /* toward 0 */
-                  case 3: /* toward -infinity */
-                    word0(rv) = Big0;
-                    word1(rv) = Big1;
-                    break;
-                  default:
-                    word0(rv) = Exp_mask;
-                    word1(rv) = 0;
-                }
-#else /*Honor_FLT_ROUNDS*/
-                word0(rv) = Exp_mask;
-                word1(rv) = 0;
-#endif /*Honor_FLT_ROUNDS*/
-#ifdef SET_INEXACT
-                /* set overflow bit */
-                dval(rv0) = 1e300;
-                dval(rv0) *= dval(rv0);
-#endif
-#else /*IEEE_Arith*/
-                word0(rv) = Big0;
-                word1(rv) = Big1;
-#endif /*IEEE_Arith*/
-                if (bd0)
-                    goto retfree;
-                goto ret;
-            }
-            e1 >>= 4;
-            for (j = 0; e1 > 1; j++, e1 >>= 1)
-                if (e1 & 1)
-                    dval(rv) *= bigtens[j];
-            /* The last multiplication could overflow. */
-            word0(rv) -= P*Exp_msk1;
-            dval(rv) *= bigtens[j];
-            if ((z = word0(rv) & Exp_mask)
-                    > Exp_msk1*(DBL_MAX_EXP+Bias-P))
-                goto ovfl;
-            if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
-                /* set to largest number */
-                /* (Can't trust DBL_MAX) */
-                word0(rv) = Big0;
-                word1(rv) = Big1;
-            }
-            else
-                word0(rv) += P*Exp_msk1;
-        }
-    }
-    else if (e1 < 0) {
-        e1 = -e1;
-        if ((i = e1 & 15) != 0)
-            dval(rv) /= tens[i];
-        if (e1 >>= 4) {
-            if (e1 >= 1 << n_bigtens)
-                goto undfl;
-#ifdef Avoid_Underflow
-            if (e1 & Scale_Bit)
-                scale = 2*P;
-            for (j = 0; e1 > 0; j++, e1 >>= 1)
-                if (e1 & 1)
-                    dval(rv) *= tinytens[j];
-            if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
-                    >> Exp_shift)) > 0) {
-                /* scaled rv is denormal; zap j low bits */
-                if (j >= 32) {
-                    word1(rv) = 0;
-                    if (j >= 53)
-                        word0(rv) = (P+2)*Exp_msk1;
-                    else
-                        word0(rv) &= 0xffffffff << (j-32);
-                }
-                else
-                    word1(rv) &= 0xffffffff << j;
-            }
-#else
-            for (j = 0; e1 > 1; j++, e1 >>= 1)
-                if (e1 & 1)
-                    dval(rv) *= tinytens[j];
-            /* The last multiplication could underflow. */
-            dval(rv0) = dval(rv);
-            dval(rv) *= tinytens[j];
-            if (!dval(rv)) {
-                dval(rv) = 2.*dval(rv0);
-                dval(rv) *= tinytens[j];
-#endif
-                if (!dval(rv)) {
-undfl:
-                    dval(rv) = 0.;
-#ifndef NO_ERRNO
-                    errno = ERANGE;
-#endif
-                    if (bd0)
-                        goto retfree;
-                    goto ret;
-                }
-#ifndef Avoid_Underflow
-                word0(rv) = Tiny0;
-                word1(rv) = Tiny1;
-                /* The refinement below will clean
-                 * this approximation up.
-                 */
-            }
-#endif
-        }
-    }
-
-    /* Now the hard part -- adjusting rv to the correct value.*/
-
-    /* Put digits into bd: true value = bd * 10^e */
-
-    bd0 = s2b(s0, nd0, nd, y);
-
-    for (;;) {
-        bd = Balloc(bd0->k);
-        Bcopy(bd, bd0);
-        bb = d2b(dval(rv), &bbe, &bbbits);  /* rv = bb * 2^bbe */
-        bs = i2b(1);
-
-        if (e >= 0) {
-            bb2 = bb5 = 0;
-            bd2 = bd5 = e;
-        }
-        else {
-            bb2 = bb5 = -e;
-            bd2 = bd5 = 0;
-        }
-        if (bbe >= 0)
-            bb2 += bbe;
-        else
-            bd2 -= bbe;
-        bs2 = bb2;
-#ifdef Honor_FLT_ROUNDS
-        if (rounding != 1)
-            bs2++;
-#endif
-#ifdef Avoid_Underflow
-        j = bbe - scale;
-        i = j + bbbits - 1; /* logb(rv) */
-        if (i < Emin)   /* denormal */
-            j += P - Emin;
-        else
-            j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
-#ifdef IBM
-        j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
-#else
-        j = P + 1 - bbbits;
-#endif
-#else /*Sudden_Underflow*/
-        j = bbe;
-        i = j + bbbits - 1; /* logb(rv) */
-        if (i < Emin)   /* denormal */
-            j += P - Emin;
-        else
-            j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-        bb2 += j;
-        bd2 += j;
-#ifdef Avoid_Underflow
-        bd2 += scale;
-#endif
-        i = bb2 < bd2 ? bb2 : bd2;
-        if (i > bs2)
-            i = bs2;
-        if (i > 0) {
-            bb2 -= i;
-            bd2 -= i;
-            bs2 -= i;
-        }
-        if (bb5 > 0) {
-            bs = pow5mult(bs, bb5);
-            bb1 = mult(bs, bb);
-            Bfree(bb);
-            bb = bb1;
-        }
-        if (bb2 > 0)
-            bb = lshift(bb, bb2);
-        if (bd5 > 0)
-            bd = pow5mult(bd, bd5);
-        if (bd2 > 0)
-            bd = lshift(bd, bd2);
-        if (bs2 > 0)
-            bs = lshift(bs, bs2);
-        delta = diff(bb, bd);
-        dsign = delta->sign;
-        delta->sign = 0;
-        i = cmp(delta, bs);
-#ifdef Honor_FLT_ROUNDS
-        if (rounding != 1) {
-            if (i < 0) {
-                /* Error is less than an ulp */
-                if (!delta->x[0] && delta->wds <= 1) {
-                    /* exact */
-#ifdef SET_INEXACT
-                    inexact = 0;
-#endif
-                    break;
-                }
-                if (rounding) {
-                    if (dsign) {
-                        adj = 1.;
-                        goto apply_adj;
-                    }
-                }
-                else if (!dsign) {
-                    adj = -1.;
-                    if (!word1(rv)
-                     && !(word0(rv) & Frac_mask)) {
-                        y = word0(rv) & Exp_mask;
-#ifdef Avoid_Underflow
-                        if (!scale || y > 2*P*Exp_msk1)
-#else
-                        if (y)
-#endif
-                        {
-                            delta = lshift(delta,Log2P);
-                            if (cmp(delta, bs) <= 0)
-                                adj = -0.5;
-                        }
-                    }
-apply_adj:
-#ifdef Avoid_Underflow
-                    if (scale && (y = word0(rv) & Exp_mask)
-                            <= 2*P*Exp_msk1)
-                        word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
-                    if ((word0(rv) & Exp_mask) <=
-                            P*Exp_msk1) {
-                        word0(rv) += P*Exp_msk1;
-                        dval(rv) += adj*ulp(dval(rv));
-                        word0(rv) -= P*Exp_msk1;
-                    }
-                    else
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-                    dval(rv) += adj*ulp(dval(rv));
-                }
-                break;
-            }
-            adj = ratio(delta, bs);
-            if (adj < 1.)
-                adj = 1.;
-            if (adj <= 0x7ffffffe) {
-                /* adj = rounding ? ceil(adj) : floor(adj); */
-                y = adj;
-                if (y != adj) {
-                    if (!((rounding>>1) ^ dsign))
-                        y++;
-                    adj = y;
-                }
-            }
-#ifdef Avoid_Underflow
-            if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
-                word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
-            if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
-                word0(rv) += P*Exp_msk1;
-                adj *= ulp(dval(rv));
-                if (dsign)
-                    dval(rv) += adj;
-                else
-                    dval(rv) -= adj;
-                word0(rv) -= P*Exp_msk1;
-                goto cont;
-            }
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-            adj *= ulp(dval(rv));
-            if (dsign)
-                dval(rv) += adj;
-            else
-                dval(rv) -= adj;
-            goto cont;
-        }
-#endif /*Honor_FLT_ROUNDS*/
-
-        if (i < 0) {
-            /* Error is less than half an ulp -- check for
-             * special case of mantissa a power of two.
-             */
-            if (dsign || word1(rv) || word0(rv) & Bndry_mask
-#ifdef IEEE_Arith
-#ifdef Avoid_Underflow
-                || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
-#else
-                || (word0(rv) & Exp_mask) <= Exp_msk1
-#endif
-#endif
-            ) {
-#ifdef SET_INEXACT
-                if (!delta->x[0] && delta->wds <= 1)
-                    inexact = 0;
-#endif
-                break;
-            }
-            if (!delta->x[0] && delta->wds <= 1) {
-                /* exact result */
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
-                break;
-            }
-            delta = lshift(delta,Log2P);
-            if (cmp(delta, bs) > 0)
-                goto drop_down;
-            break;
-        }
-        if (i == 0) {
-            /* exactly half-way between */
-            if (dsign) {
-                if ((word0(rv) & Bndry_mask1) == Bndry_mask1
-                        &&  word1(rv) == (
-#ifdef Avoid_Underflow
-                        (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
-                        ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
-#endif
-                        0xffffffff)) {
-                    /*boundary case -- increment exponent*/
-                    word0(rv) = (word0(rv) & Exp_mask)
-                                + Exp_msk1
-#ifdef IBM
-                                | Exp_msk1 >> 4
-#endif
-                    ;
-                    word1(rv) = 0;
-#ifdef Avoid_Underflow
-                    dsign = 0;
-#endif
-                    break;
-                }
-            }
-            else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
-drop_down:
-                /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
-                L = word0(rv) & Exp_mask;
-#ifdef IBM
-                if (L <  Exp_msk1)
-#else
-#ifdef Avoid_Underflow
-                if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
-#else
-                if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
-#endif /*IBM*/
-                    goto undfl;
-                L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
-                if (scale) {
-                    L = word0(rv) & Exp_mask;
-                    if (L <= (2*P+1)*Exp_msk1) {
-                        if (L > (P+2)*Exp_msk1)
-                            /* round even ==> */
-                            /* accept rv */
-                            break;
-                        /* rv = smallest denormal */
-                        goto undfl;
-                    }
-                }
-#endif /*Avoid_Underflow*/
-                L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
-                word0(rv) = L | Bndry_mask1;
-                word1(rv) = 0xffffffff;
-#ifdef IBM
-                goto cont;
-#else
-                break;
-#endif
-            }
-#ifndef ROUND_BIASED
-            if (!(word1(rv) & LSB))
-                break;
-#endif
-            if (dsign)
-                dval(rv) += ulp(dval(rv));
-#ifndef ROUND_BIASED
-            else {
-                dval(rv) -= ulp(dval(rv));
-#ifndef Sudden_Underflow
-                if (!dval(rv))
-                    goto undfl;
-#endif
-            }
-#ifdef Avoid_Underflow
-            dsign = 1 - dsign;
-#endif
-#endif
-            break;
-        }
-        if ((aadj = ratio(delta, bs)) <= 2.) {
-            if (dsign)
-                aadj = aadj1 = 1.;
-            else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
-                if (word1(rv) == Tiny1 && !word0(rv))
-                    goto undfl;
-#endif
-                aadj = 1.;
-                aadj1 = -1.;
-            }
-            else {
-                /* special case -- power of FLT_RADIX to be */
-                /* rounded down... */
-
-                if (aadj < 2./FLT_RADIX)
-                    aadj = 1./FLT_RADIX;
-                else
-                    aadj *= 0.5;
-                aadj1 = -aadj;
-            }
-        }
-        else {
-            aadj *= 0.5;
-            aadj1 = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
-            switch (Rounding) {
-              case 2: /* towards +infinity */
-                aadj1 -= 0.5;
-                break;
-              case 0: /* towards 0 */
-              case 3: /* towards -infinity */
-                aadj1 += 0.5;
-            }
-#else
-            if (Flt_Rounds == 0)
-                aadj1 += 0.5;
-#endif /*Check_FLT_ROUNDS*/
-        }
-        y = word0(rv) & Exp_mask;
-
-        /* Check for overflow */
-
-        if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
-            dval(rv0) = dval(rv);
-            word0(rv) -= P*Exp_msk1;
-            adj = aadj1 * ulp(dval(rv));
-            dval(rv) += adj;
-            if ((word0(rv) & Exp_mask) >=
-                    Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
-                if (word0(rv0) == Big0 && word1(rv0) == Big1)
-                    goto ovfl;
-                word0(rv) = Big0;
-                word1(rv) = Big1;
-                goto cont;
-            }
-            else
-                word0(rv) += P*Exp_msk1;
-        }
-        else {
-#ifdef Avoid_Underflow
-            if (scale && y <= 2*P*Exp_msk1) {
-                if (aadj <= 0x7fffffff) {
-                    if ((z = aadj) <= 0)
-                        z = 1;
-                    aadj = z;
-                    aadj1 = dsign ? aadj : -aadj;
-                }
-                word0(aadj1) += (2*P+1)*Exp_msk1 - y;
-            }
-            adj = aadj1 * ulp(dval(rv));
-            dval(rv) += adj;
-#else
-#ifdef Sudden_Underflow
-            if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
-                dval(rv0) = dval(rv);
-                word0(rv) += P*Exp_msk1;
-                adj = aadj1 * ulp(dval(rv));
-                dval(rv) += adj;
-#ifdef IBM
-                if ((word0(rv) & Exp_mask) <  P*Exp_msk1)
-#else
-                if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
-#endif
-                {
-                    if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
-                        goto undfl;
-                    word0(rv) = Tiny0;
-                    word1(rv) = Tiny1;
-                    goto cont;
-                }
-                else
-                    word0(rv) -= P*Exp_msk1;
-            }
-            else {
-                adj = aadj1 * ulp(dval(rv));
-                dval(rv) += adj;
-            }
-#else /*Sudden_Underflow*/
-            /* Compute adj so that the IEEE rounding rules will
-             * correctly round rv + adj in some half-way cases.
-             * If rv * ulp(rv) is denormalized (i.e.,
-             * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
-             * trouble from bits lost to denormalization;
-             * example: 1.2e-307 .
-             */
-            if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
-                aadj1 = (double)(int)(aadj + 0.5);
-                if (!dsign)
-                    aadj1 = -aadj1;
-            }
-            adj = aadj1 * ulp(dval(rv));
-            dval(rv) += adj;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-        }
-        z = word0(rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
-        if (!scale)
-#endif
-        if (y == z) {
-            /* Can we stop now? */
-            L = (Long)aadj;
-            aadj -= L;
-            /* The tolerances below are conservative. */
-            if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
-                if (aadj < .4999999 || aadj > .5000001)
-                    break;
-            }
-            else if (aadj < .4999999/FLT_RADIX)
-                break;
-        }
-#endif
-cont:
-        Bfree(bb);
-        Bfree(bd);
-        Bfree(bs);
-        Bfree(delta);
-    }
-#ifdef SET_INEXACT
-    if (inexact) {
-        if (!oldinexact) {
-            word0(rv0) = Exp_1 + (70 << Exp_shift);
-            word1(rv0) = 0;
-            dval(rv0) += 1.;
-        }
-    }
-    else if (!oldinexact)
-        clear_inexact();
-#endif
-#ifdef Avoid_Underflow
-    if (scale) {
-        word0(rv0) = Exp_1 - 2*P*Exp_msk1;
-        word1(rv0) = 0;
-        dval(rv) *= dval(rv0);
-#ifndef NO_ERRNO
-        /* try to avoid the bug of testing an 8087 register value */
-        if (word0(rv) == 0 && word1(rv) == 0)
-            errno = ERANGE;
-#endif
-    }
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
-    if (inexact && !(word0(rv) & Exp_mask)) {
-        /* set underflow bit */
-        dval(rv0) = 1e-300;
-        dval(rv0) *= dval(rv0);
-    }
-#endif
-retfree:
-    Bfree(bb);
-    Bfree(bd);
-    Bfree(bs);
-    Bfree(bd0);
-    Bfree(delta);
-ret:
-    if (se)
-        *se = (char *)s;
-    return sign ? -dval(rv) : dval(rv);
-}
-
-static int
-quorem(Bigint *b, Bigint *S)
-{
-    int n;
-    ULong *bx, *bxe, q, *sx, *sxe;
-#ifdef ULLong
-    ULLong borrow, carry, y, ys;
-#else
-    ULong borrow, carry, y, ys;
-#ifdef Pack_32
-    ULong si, z, zs;
-#endif
-#endif
-
-    n = S->wds;
-#ifdef DEBUG
-    /*debug*/ if (b->wds > n)
-    /*debug*/   Bug("oversize b in quorem");
-#endif
-    if (b->wds < n)
-        return 0;
-    sx = S->x;
-    sxe = sx + --n;
-    bx = b->x;
-    bxe = bx + n;
-    q = *bxe / (*sxe + 1);  /* ensure q <= true quotient */
-#ifdef DEBUG
-    /*debug*/ if (q > 9)
-    /*debug*/   Bug("oversized quotient in quorem");
-#endif
-    if (q) {
-        borrow = 0;
-        carry = 0;
-        do {
-#ifdef ULLong
-            ys = *sx++ * (ULLong)q + carry;
-            carry = ys >> 32;
-            y = *bx - (ys & FFFFFFFF) - borrow;
-            borrow = y >> 32 & (ULong)1;
-            *bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-            si = *sx++;
-            ys = (si & 0xffff) * q + carry;
-            zs = (si >> 16) * q + (ys >> 16);
-            carry = zs >> 16;
-            y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            z = (*bx >> 16) - (zs & 0xffff) - borrow;
-            borrow = (z & 0x10000) >> 16;
-            Storeinc(bx, z, y);
-#else
-            ys = *sx++ * q + carry;
-            carry = ys >> 16;
-            y = *bx - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            *bx++ = y & 0xffff;
-#endif
-#endif
-        } while (sx <= sxe);
-        if (!*bxe) {
-            bx = b->x;
-            while (--bxe > bx && !*bxe)
-                --n;
-            b->wds = n;
-        }
-    }
-    if (cmp(b, S) >= 0) {
-        q++;
-        borrow = 0;
-        carry = 0;
-        bx = b->x;
-        sx = S->x;
-        do {
-#ifdef ULLong
-            ys = *sx++ + carry;
-            carry = ys >> 32;
-            y = *bx - (ys & FFFFFFFF) - borrow;
-            borrow = y >> 32 & (ULong)1;
-            *bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-            si = *sx++;
-            ys = (si & 0xffff) + carry;
-            zs = (si >> 16) + (ys >> 16);
-            carry = zs >> 16;
-            y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            z = (*bx >> 16) - (zs & 0xffff) - borrow;
-            borrow = (z & 0x10000) >> 16;
-            Storeinc(bx, z, y);
-#else
-            ys = *sx++ + carry;
-            carry = ys >> 16;
-            y = *bx - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            *bx++ = y & 0xffff;
-#endif
-#endif
-        } while (sx <= sxe);
-        bx = b->x;
-        bxe = bx + n;
-        if (!*bxe) {
-            while (--bxe > bx && !*bxe)
-                --n;
-            b->wds = n;
-        }
-    }
-    return q;
-}
-
-#ifndef MULTIPLE_THREADS
-static char *dtoa_result;
-#endif
-
-static char *
-rv_alloc(int i)
-{
-    int j, k, *r;
-
-    j = sizeof(ULong);
-    for (k = 0;
-            sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
-            j <<= 1)
-        k++;
-    r = (int*)Balloc(k);
-    *r = k;
-    return
-#ifndef MULTIPLE_THREADS
-        dtoa_result =
-#endif
-        (char *)(r+1);
-}
-
-static char *
-nrv_alloc(const char *s, char **rve, int n)
-{
-    char *rv, *t;
-
-    t = rv = rv_alloc(n);
-    while ((*t = *s++) != 0) t++;
-    if (rve)
-        *rve = t;
-    return rv;
-}
-
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
-void
-freedtoa(char *s)
-{
-    Bigint *b = (Bigint *)((int *)s - 1);
-    b->maxwds = 1 << (b->k = *(int*)b);
-    Bfree(b);
-#ifndef MULTIPLE_THREADS
-    if (s == dtoa_result)
-        dtoa_result = 0;
-#endif
-}
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
- *
- * Modifications:
- *  1. Rather than iterating, we use a simple numeric overestimate
- *     to determine k = floor(log10(d)).  We scale relevant
- *     quantities using O(log2(k)) rather than O(k) multiplications.
- *  2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- *     try to generate digits strictly left to right.  Instead, we
- *     compute with fewer bits and propagate the carry if necessary
- *     when rounding the final digit up.  This is often faster.
- *  3. Under the assumption that input will be rounded nearest,
- *     mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- *     That is, we allow equality in stopping tests when the
- *     round-nearest rule will give the same floating-point value
- *     as would satisfaction of the stopping test with strict
- *     inequality.
- *  4. We remove common factors of powers of 2 from relevant
- *     quantities.
- *  5. When converting floating-point integers less than 1e16,
- *     we use floating-point arithmetic rather than resorting
- *     to multiple-precision integers.
- *  6. When asked to produce fewer than 15 digits, we first try
- *     to get by with floating-point arithmetic; we resort to
- *     multiple-precision integer arithmetic only if we cannot
- *     guarantee that the floating-point calculation has given
- *     the correctly rounded result.  For k requested digits and
- *     "uniformly" distributed input, the probability is
- *     something like 10^(k-15) that we must resort to the Long
- *     calculation.
- */
-
-char *
-dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
-{
- /* Arguments ndigits, decpt, sign are similar to those
-    of ecvt and fcvt; trailing zeros are suppressed from
-    the returned string.  If not null, *rve is set to point
-    to the end of the return value.  If d is +-Infinity or NaN,
-    then *decpt is set to 9999.
-
-    mode:
-        0 ==> shortest string that yields d when read in
-            and rounded to nearest.
-        1 ==> like 0, but with Steele & White stopping rule;
-            e.g. with IEEE P754 arithmetic , mode 0 gives
-            1e23 whereas mode 1 gives 9.999999999999999e22.
-        2 ==> max(1,ndigits) significant digits.  This gives a
-            return value similar to that of ecvt, except
-            that trailing zeros are suppressed.
-        3 ==> through ndigits past the decimal point.  This
-            gives a return value similar to that from fcvt,
-            except that trailing zeros are suppressed, and
-            ndigits can be negative.
-        4,5 ==> similar to 2 and 3, respectively, but (in
-            round-nearest mode) with the tests of mode 0 to
-            possibly return a shorter string that rounds to d.
-            With IEEE arithmetic and compilation with
-            -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
-            as modes 2 and 3 when FLT_ROUNDS != 1.
-        6-9 ==> Debugging modes similar to mode - 4:  don't try
-            fast floating-point estimate (if applicable).
-
-        Values of mode other than 0-9 are treated as mode 0.
-
-        Sufficient space is allocated to the return value
-        to hold the suppressed trailing zeros.
-    */
-
-    int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
-        j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
-        spec_case, try_quick;
-    Long L;
-#ifndef Sudden_Underflow
-    int denorm;
-    ULong x;
-#endif
-    Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S;
-    double d2, ds, eps;
-    char *s, *s0;
-#ifdef Honor_FLT_ROUNDS
-    int rounding;
-#endif
-#ifdef SET_INEXACT
-    int inexact, oldinexact;
-#endif
-
-#ifndef MULTIPLE_THREADS
-    if (dtoa_result) {
-        freedtoa(dtoa_result);
-        dtoa_result = 0;
-    }
-#endif
-
-    if (word0(d) & Sign_bit) {
-        /* set sign for everything, including 0's and NaNs */
-        *sign = 1;
-        word0(d) &= ~Sign_bit;  /* clear sign bit */
-    }
-    else
-        *sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
-    if ((word0(d) & Exp_mask) == Exp_mask)
-#else
-    if (word0(d)  == 0x8000)
-#endif
-    {
-        /* Infinity or NaN */
-        *decpt = 9999;
-#ifdef IEEE_Arith
-        if (!word1(d) && !(word0(d) & 0xfffff))
-            return nrv_alloc("Infinity", rve, 8);
-#endif
-        return nrv_alloc("NaN", rve, 3);
-    }
-#endif
-#ifdef IBM
-    dval(d) += 0; /* normalize */
-#endif
-    if (!dval(d)) {
-        *decpt = 1;
-        return nrv_alloc("0", rve, 1);
-    }
-
-#ifdef SET_INEXACT
-    try_quick = oldinexact = get_inexact();
-    inexact = 1;
-#endif
-#ifdef Honor_FLT_ROUNDS
-    if ((rounding = Flt_Rounds) >= 2) {
-        if (*sign)
-            rounding = rounding == 2 ? 0 : 2;
-        else
-            if (rounding != 2)
-                rounding = 0;
-    }
-#endif
-
-    b = d2b(dval(d), &be, &bbits);
-#ifdef Sudden_Underflow
-    i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
-    if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
-#endif
-        dval(d2) = dval(d);
-        word0(d2) &= Frac_mask1;
-        word0(d2) |= Exp_11;
-#ifdef IBM
-        if (j = 11 - hi0bits(word0(d2) & Frac_mask))
-            dval(d2) /= 1 << j;
-#endif
-
-        /* log(x)   ~=~ log(1.5) + (x-1.5)/1.5
-         * log10(x)  =  log(x) / log(10)
-         *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
-         * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
-         *
-         * This suggests computing an approximation k to log10(d) by
-         *
-         * k = (i - Bias)*0.301029995663981
-         *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
-         *
-         * We want k to be too large rather than too small.
-         * The error in the first-order Taylor series approximation
-         * is in our favor, so we just round up the constant enough
-         * to compensate for any error in the multiplication of
-         * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
-         * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
-         * adding 1e-13 to the constant term more than suffices.
-         * Hence we adjust the constant term to 0.1760912590558.
-         * (We could get a more accurate k by invoking log10,
-         *  but this is probably not worthwhile.)
-         */
-
-        i -= Bias;
-#ifdef IBM
-        i <<= 2;
-        i += j;
-#endif
-#ifndef Sudden_Underflow
-        denorm = 0;
-    }
-    else {
-        /* d is denormalized */
-
-        i = bbits + be + (Bias + (P-1) - 1);
-        x = i > 32  ? word0(d) << (64 - i) | word1(d) >> (i - 32)
-	    : word1(d) << (32 - i);
-        dval(d2) = x;
-        word0(d2) -= 31*Exp_msk1; /* adjust exponent */
-        i -= (Bias + (P-1) - 1) + 1;
-        denorm = 1;
-    }
-#endif
-    ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
-    k = (int)ds;
-    if (ds < 0. && ds != k)
-        k--;    /* want k = floor(ds) */
-    k_check = 1;
-    if (k >= 0 && k <= Ten_pmax) {
-        if (dval(d) < tens[k])
-            k--;
-        k_check = 0;
-    }
-    j = bbits - i - 1;
-    if (j >= 0) {
-        b2 = 0;
-        s2 = j;
-    }
-    else {
-        b2 = -j;
-        s2 = 0;
-    }
-    if (k >= 0) {
-        b5 = 0;
-        s5 = k;
-        s2 += k;
-    }
-    else {
-        b2 -= k;
-        b5 = -k;
-        s5 = 0;
-    }
-    if (mode < 0 || mode > 9)
-        mode = 0;
-
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
-    try_quick = Rounding == 1;
-#else
-    try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
-
-    if (mode > 5) {
-        mode -= 4;
-        try_quick = 0;
-    }
-    leftright = 1;
-    ilim = ilim1 = -1;
-    switch (mode) {
-      case 0:
-      case 1:
-        i = 18;
-        ndigits = 0;
-        break;
-      case 2:
-        leftright = 0;
-        /* no break */
-      case 4:
-        if (ndigits <= 0)
-            ndigits = 1;
-        ilim = ilim1 = i = ndigits;
-        break;
-      case 3:
-        leftright = 0;
-        /* no break */
-      case 5:
-        i = ndigits + k + 1;
-        ilim = i;
-        ilim1 = i - 1;
-        if (i <= 0)
-            i = 1;
-    }
-    s = s0 = rv_alloc(i);
-
-#ifdef Honor_FLT_ROUNDS
-    if (mode > 1 && rounding != 1)
-        leftright = 0;
-#endif
-
-    if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
-        /* Try to get by with floating-point arithmetic. */
-
-        i = 0;
-        dval(d2) = dval(d);
-        k0 = k;
-        ilim0 = ilim;
-        ieps = 2; /* conservative */
-        if (k > 0) {
-            ds = tens[k&0xf];
-            j = k >> 4;
-            if (j & Bletch) {
-                /* prevent overflows */
-                j &= Bletch - 1;
-                dval(d) /= bigtens[n_bigtens-1];
-                ieps++;
-            }
-            for (; j; j >>= 1, i++)
-                if (j & 1) {
-                    ieps++;
-                    ds *= bigtens[i];
-                }
-            dval(d) /= ds;
-        }
-        else if ((j1 = -k) != 0) {
-            dval(d) *= tens[j1 & 0xf];
-            for (j = j1 >> 4; j; j >>= 1, i++)
-                if (j & 1) {
-                    ieps++;
-                    dval(d) *= bigtens[i];
-                }
-        }
-        if (k_check && dval(d) < 1. && ilim > 0) {
-            if (ilim1 <= 0)
-                goto fast_failed;
-            ilim = ilim1;
-            k--;
-            dval(d) *= 10.;
-            ieps++;
-        }
-        dval(eps) = ieps*dval(d) + 7.;
-        word0(eps) -= (P-1)*Exp_msk1;
-        if (ilim == 0) {
-            S = mhi = 0;
-            dval(d) -= 5.;
-            if (dval(d) > dval(eps))
-                goto one_digit;
-            if (dval(d) < -dval(eps))
-                goto no_digits;
-            goto fast_failed;
-        }
-#ifndef No_leftright
-        if (leftright) {
-            /* Use Steele & White method of only
-             * generating digits needed.
-             */
-            dval(eps) = 0.5/tens[ilim-1] - dval(eps);
-            for (i = 0;;) {
-                L = dval(d);
-                dval(d) -= L;
-                *s++ = '0' + (int)L;
-                if (dval(d) < dval(eps))
-                    goto ret1;
-                if (1. - dval(d) < dval(eps))
-                    goto bump_up;
-                if (++i >= ilim)
-                    break;
-                dval(eps) *= 10.;
-                dval(d) *= 10.;
-            }
-        }
-        else {
-#endif
-            /* Generate ilim digits, then fix them up. */
-            dval(eps) *= tens[ilim-1];
-            for (i = 1;; i++, dval(d) *= 10.) {
-                L = (Long)(dval(d));
-                if (!(dval(d) -= L))
-                    ilim = i;
-                *s++ = '0' + (int)L;
-                if (i == ilim) {
-                    if (dval(d) > 0.5 + dval(eps))
-                        goto bump_up;
-                    else if (dval(d) < 0.5 - dval(eps)) {
-                        while (*--s == '0') ;
-                        s++;
-                        goto ret1;
-                    }
-                    break;
-                }
-            }
-#ifndef No_leftright
-        }
-#endif
-fast_failed:
-        s = s0;
-        dval(d) = dval(d2);
-        k = k0;
-        ilim = ilim0;
-    }
-
-    /* Do we have a "small" integer? */
-
-    if (be >= 0 && k <= Int_max) {
-        /* Yes. */
-        ds = tens[k];
-        if (ndigits < 0 && ilim <= 0) {
-            S = mhi = 0;
-            if (ilim < 0 || dval(d) <= 5*ds)
-                goto no_digits;
-            goto one_digit;
-        }
-        for (i = 1;; i++, dval(d) *= 10.) {
-            L = (Long)(dval(d) / ds);
-            dval(d) -= L*ds;
-#ifdef Check_FLT_ROUNDS
-            /* If FLT_ROUNDS == 2, L will usually be high by 1 */
-            if (dval(d) < 0) {
-                L--;
-                dval(d) += ds;
-            }
-#endif
-            *s++ = '0' + (int)L;
-            if (!dval(d)) {
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
-                break;
-            }
-            if (i == ilim) {
-#ifdef Honor_FLT_ROUNDS
-                if (mode > 1)
-                switch (rounding) {
-                  case 0: goto ret1;
-                  case 2: goto bump_up;
-                }
-#endif
-                dval(d) += dval(d);
-                if (dval(d) > ds || (dval(d) == ds && (L & 1))) {
-bump_up:
-                    while (*--s == '9')
-                        if (s == s0) {
-                            k++;
-                            *s = '0';
-                            break;
-                        }
-                    ++*s++;
-                }
-                break;
-            }
-        }
-        goto ret1;
-    }
-
-    m2 = b2;
-    m5 = b5;
-    if (leftright) {
-        i =
-#ifndef Sudden_Underflow
-            denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
-            1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
-            1 + P - bbits;
-#endif
-        b2 += i;
-        s2 += i;
-        mhi = i2b(1);
-    }
-    if (m2 > 0 && s2 > 0) {
-        i = m2 < s2 ? m2 : s2;
-        b2 -= i;
-        m2 -= i;
-        s2 -= i;
-    }
-    if (b5 > 0) {
-        if (leftright) {
-            if (m5 > 0) {
-                mhi = pow5mult(mhi, m5);
-                b1 = mult(mhi, b);
-                Bfree(b);
-                b = b1;
-            }
-            if ((j = b5 - m5) != 0)
-                b = pow5mult(b, j);
-        }
-        else
-            b = pow5mult(b, b5);
-    }
-    S = i2b(1);
-    if (s5 > 0)
-        S = pow5mult(S, s5);
-
-    /* Check for special case that d is a normalized power of 2. */
-
-    spec_case = 0;
-    if ((mode < 2 || leftright)
-#ifdef Honor_FLT_ROUNDS
-            && rounding == 1
-#endif
-    ) {
-        if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
-            && word0(d) & (Exp_mask & ~Exp_msk1)
-#endif
-        ) {
-            /* The special case */
-            b2 += Log2P;
-            s2 += Log2P;
-            spec_case = 1;
-        }
-    }
-
-    /* Arrange for convenient computation of quotients:
-     * shift left if necessary so divisor has 4 leading 0 bits.
-     *
-     * Perhaps we should just compute leading 28 bits of S once
-     * and for all and pass them and a shift to quorem, so it
-     * can do shifts and ors to compute the numerator for q.
-     */
-#ifdef Pack_32
-    if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
-        i = 32 - i;
-#else
-    if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) != 0)
-        i = 16 - i;
-#endif
-    if (i > 4) {
-        i -= 4;
-        b2 += i;
-        m2 += i;
-        s2 += i;
-    }
-    else if (i < 4) {
-        i += 28;
-        b2 += i;
-        m2 += i;
-        s2 += i;
-    }
-    if (b2 > 0)
-        b = lshift(b, b2);
-    if (s2 > 0)
-        S = lshift(S, s2);
-    if (k_check) {
-        if (cmp(b,S) < 0) {
-            k--;
-            b = multadd(b, 10, 0);  /* we botched the k estimate */
-            if (leftright)
-                mhi = multadd(mhi, 10, 0);
-            ilim = ilim1;
-        }
-    }
-    if (ilim <= 0 && (mode == 3 || mode == 5)) {
-        if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
-            /* no digits, fcvt style */
-no_digits:
-            k = -1 - ndigits;
-            goto ret;
-        }
-one_digit:
-        *s++ = '1';
-        k++;
-        goto ret;
-    }
-    if (leftright) {
-        if (m2 > 0)
-            mhi = lshift(mhi, m2);
-
-        /* Compute mlo -- check for special case
-         * that d is a normalized power of 2.
-         */
-
-        mlo = mhi;
-        if (spec_case) {
-            mhi = Balloc(mhi->k);
-            Bcopy(mhi, mlo);
-            mhi = lshift(mhi, Log2P);
-        }
-
-        for (i = 1;;i++) {
-            dig = quorem(b,S) + '0';
-            /* Do we yet have the shortest decimal string
-             * that will round to d?
-             */
-            j = cmp(b, mlo);
-            delta = diff(S, mhi);
-            j1 = delta->sign ? 1 : cmp(b, delta);
-            Bfree(delta);
-#ifndef ROUND_BIASED
-            if (j1 == 0 && mode != 1 && !(word1(d) & 1)
-#ifdef Honor_FLT_ROUNDS
-                && rounding >= 1
-#endif
-            ) {
-                if (dig == '9')
-                    goto round_9_up;
-                if (j > 0)
-                    dig++;
-#ifdef SET_INEXACT
-                else if (!b->x[0] && b->wds <= 1)
-                    inexact = 0;
-#endif
-                *s++ = dig;
-                goto ret;
-            }
-#endif
-            if (j < 0 || (j == 0 && mode != 1
-#ifndef ROUND_BIASED
-                && !(word1(d) & 1)
-#endif
-            )) {
-                if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
-                    inexact = 0;
-#endif
-                    goto accept_dig;
-                }
-#ifdef Honor_FLT_ROUNDS
-                if (mode > 1)
-                    switch (rounding) {
-                      case 0: goto accept_dig;
-                      case 2: goto keep_dig;
-                    }
-#endif /*Honor_FLT_ROUNDS*/
-                if (j1 > 0) {
-                    b = lshift(b, 1);
-                    j1 = cmp(b, S);
-                    if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
-                        goto round_9_up;
-                }
-accept_dig:
-                *s++ = dig;
-                goto ret;
-            }
-            if (j1 > 0) {
-#ifdef Honor_FLT_ROUNDS
-                if (!rounding)
-                    goto accept_dig;
-#endif
-                if (dig == '9') { /* possible if i == 1 */
-round_9_up:
-                    *s++ = '9';
-                    goto roundoff;
-                }
-                *s++ = dig + 1;
-                goto ret;
-            }
-#ifdef Honor_FLT_ROUNDS
-keep_dig:
-#endif
-            *s++ = dig;
-            if (i == ilim)
-                break;
-            b = multadd(b, 10, 0);
-            if (mlo == mhi)
-                mlo = mhi = multadd(mhi, 10, 0);
-            else {
-                mlo = multadd(mlo, 10, 0);
-                mhi = multadd(mhi, 10, 0);
-            }
-        }
-    }
-    else
-        for (i = 1;; i++) {
-            *s++ = dig = quorem(b,S) + '0';
-            if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
-                goto ret;
-            }
-            if (i >= ilim)
-                break;
-            b = multadd(b, 10, 0);
-        }
-
-    /* Round off last digit */
-
-#ifdef Honor_FLT_ROUNDS
-    switch (rounding) {
-      case 0: goto trimzeros;
-      case 2: goto roundoff;
-    }
-#endif
-    b = lshift(b, 1);
-    j = cmp(b, S);
-    if (j > 0 || (j == 0 && (dig & 1))) {
- roundoff:
-        while (*--s == '9')
-            if (s == s0) {
-                k++;
-                *s++ = '1';
-                goto ret;
-            }
-        ++*s++;
-    }
-    else {
-        while (*--s == '0') ;
-        s++;
-    }
-ret:
-    Bfree(S);
-    if (mhi) {
-        if (mlo && mlo != mhi)
-            Bfree(mlo);
-        Bfree(mhi);
-    }
-ret1:
-#ifdef SET_INEXACT
-    if (inexact) {
-        if (!oldinexact) {
-            word0(d) = Exp_1 + (70 << Exp_shift);
-            word1(d) = 0;
-            dval(d) += 1.;
-        }
-    }
-    else if (!oldinexact)
-        clear_inexact();
-#endif
-    Bfree(b);
-    *s = 0;
-    *decpt = k + 1;
-    if (rve)
-        *rve = s;
-    return s0;
-}
-
-void
-ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg)
-{
-    const char *end;
-    int len;
-
-    if (!str) return;
-    for (; *str; str = end) {
-	while (ISSPACE(*str) || *str == ',') str++;
-	if (!*str) break;
-	end = str;
-	while (*end && !ISSPACE(*end) && *end != ',') end++;
-	len = end - str;
-	(*func)(str, len, arg);
-    }
-}
-
-#if defined(__clang__)
-// Strangely, this function used by the LLVM runtime isn't exported when we
-// build with clang.
-void
-__eprintf(const char* format, const char* assertion_expression,
-	const char* line, const char* file)
-{
-    fprintf(stderr, format, assertion_expression, line, file);
-    fflush(stderr);
-    abort();
-}
-#endif // __clang__
-
-#ifdef __cplusplus
-}
-#endif

Deleted: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/variable.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,2013 +0,0 @@
-/* 
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "id.h"
-#include "vm.h"
-#include "objc.h"
-#include "class.h"
-
-st_table *rb_global_tbl;
-st_table *rb_class_tbl;
-static ID autoload, classpath, tmp_classpath;
-
-static const void *
-retain_cb(CFAllocatorRef allocator, const void *v)
-{
-    GC_RETAIN(v);
-    return v;
-}
-
-static void
-release_cb(CFAllocatorRef allocator, const void *v)
-{
-    GC_RELEASE(v);
-}
-
-static void
-ivar_dict_foreach(CFDictionaryRef dict, int (*func)(ANYARGS), VALUE farg)
-{
-    const long count = CFDictionaryGetCount(dict);
-    if (count == 0) {
-	return;
-    }
-
-    const void **keys = (const void **)malloc(sizeof(void *) * count);
-    const void **values = (const void **)malloc(sizeof(void *) * count);
-
-    CFDictionaryGetKeysAndValues(dict, keys, values);
-
-    for (long i = 0; i < count; i++) {
-	if ((*func)(keys[i], values[i], farg) != ST_CONTINUE) {
-	    break;
-	}
-    }
-
-    free(keys);
-    free(values);
-}
-
-static CFDictionaryValueCallBacks rb_cfdictionary_value_cb = {
-    0, retain_cb, release_cb, NULL, NULL
-};
-
-static SEL selRequire = 0;
-
-void
-Init_var_tables(void)
-{
-    rb_global_tbl = st_init_numtable();
-    GC_RETAIN(rb_global_tbl);
-    rb_class_tbl = st_init_numtable();
-    GC_RETAIN(rb_class_tbl);
-    autoload = rb_intern("__autoload__");
-    classpath = rb_intern("__classpath__");
-    tmp_classpath = rb_intern("__tmp_classpath__");
-    selRequire = sel_registerName("require:");
-}
-
-struct fc_result {
-    ID name;
-    VALUE klass;
-    VALUE path;
-    VALUE track;
-    struct fc_result *prev;
-};
-
-static VALUE
-fc_path(struct fc_result *fc, ID name)
-{
-    VALUE path, tmp;
-
-    path = rb_str_dup(rb_id2str(name));
-    while (fc) {
-	if (fc->track == rb_cObject) break;
-	if ((tmp = rb_attr_get(fc->track, classpath)) != Qnil) {
-	    tmp = rb_str_dup(tmp);
-	    rb_str_cat2(tmp, "::");
-	    rb_str_append(tmp, path);
-	    path = tmp;
-	    break;
-	}
-	tmp = rb_str_dup(rb_id2str(fc->name));
-	rb_str_cat2(tmp, "::");
-	rb_str_append(tmp, path);
-	path = tmp;
-	fc = fc->prev;
-    }
-    OBJ_FREEZE(path);
-    return path;
-}
-
-static int
-fc_i(ID key, VALUE value, struct fc_result *res)
-{
-    if (!rb_is_const_id(key)) return ST_CONTINUE;
-
-    if (value == res->klass) {
-	res->path = fc_path(res, key);
-	return ST_STOP;
-    }
-    switch (TYPE(value)) {
-      case T_MODULE:
-      case T_CLASS:
-      {
-	CFDictionaryRef iv_dict = rb_class_ivar_dict(value);
-	if (iv_dict == NULL) return ST_CONTINUE;
-	else {
-	    struct fc_result arg;
-	    struct fc_result *list;
-
-	    list = res;
-	    while (list) {
-		if (list->track == value) return ST_CONTINUE;
-		list = list->prev;
-	    }
-
-	    arg.name = key;
-	    arg.path = 0;
-	    arg.klass = res->klass;
-	    arg.track = value;
-	    arg.prev = res;
-	    ivar_dict_foreach(iv_dict, fc_i, (VALUE)&arg);
-	    if (arg.path) {
-		res->path = arg.path;
-		return ST_STOP;
-	    }
-	}
-	break;
-      }
-
-      default:
-	break;
-    }
-    return ST_CONTINUE;
-}
-
-static VALUE
-find_class_path(VALUE klass)
-{
-    struct fc_result arg;
-
-    arg.name = 0;
-    arg.path = 0;
-    arg.klass = klass;
-    arg.track = rb_cObject;
-    arg.prev = 0;
-
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
-    if (iv_dict != NULL) {
-	ivar_dict_foreach(iv_dict, fc_i, (VALUE)&arg);
-    }
-    if (arg.path == 0) {
-	st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
-    }
-    if (arg.path) {
-	iv_dict = rb_class_ivar_dict_or_create(klass);
-	CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)arg.path);
-	CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
-	return arg.path;
-    }
-    if (!RCLASS_RUBY(klass)) {
-	VALUE name = rb_str_new2(class_getName((Class)klass));
-	iv_dict = rb_class_ivar_dict_or_create(klass);
-	CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)name);
-	CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
-	return name;
-    }
-    return Qnil;
-}
-
-static VALUE
-classname(VALUE klass)
-{
-    VALUE path = Qnil;
-
-    if (!klass) klass = rb_cObject;
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
-    if (iv_dict != NULL) {
-	if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, 
-	    (const void *)classpath, (const void **)&path)) {
-
-	    static ID classid = 0;
-	    if (classid == 0)
-		classid = rb_intern("__classid__");
-
-	    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, 
-		(const void *)classid, (const void **)&path))
-		return find_class_path(klass);
-
-	    path = rb_str_dup(path);
-	    OBJ_FREEZE(path);
-	    CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)path);
-	    CFDictionaryRemoveValue(iv_dict, (const void *)classid);
-	}
-	if (TYPE(path) != T_STRING) {
-	    rb_bug("class path is not set properly");
-	}
-	return path;
-    }
-    return find_class_path(klass);
-}
-
-/*
- *  call-seq:
- *     mod.name    => string
- *  
- *  Returns the name of the module <i>mod</i>.  Returns nil for anonymous modules.
- */
-
-VALUE
-rb_mod_name(VALUE mod, SEL sel)
-{
-    VALUE path = classname(mod);
-
-    if (!NIL_P(path)) {
-	return rb_str_dup(path);
-    }
-    return path;
-}
-
-VALUE
-rb_class_path(VALUE klass)
-{
-    VALUE path = classname(klass);
-
-    if (!NIL_P(path)) return path;
-    if ((path = rb_attr_get(klass, tmp_classpath)) != Qnil) {
-	return path;
-    }
-    else {
-	const char *s = "Class";
-
-	if (TYPE(klass) == T_MODULE) {
-	    if (rb_obj_class(klass) == rb_cModule) {
-		s = "Module";
-	    }
-	    else {
-		s = rb_class2name(RBASIC(klass)->klass);
-	    }
-	}
-	path = rb_sprintf("#<%s:%p>", s, (void*)klass);
-	OBJ_FREEZE(path);
-	rb_ivar_set(klass, tmp_classpath, path);
-
-	return path;
-    }
-}
-
-void
-rb_set_class_path2(VALUE klass, VALUE under, const char *name, VALUE outer)
-{
-    VALUE str;
-
-    if (under == rb_cObject) {
-	str = rb_str_new2(name);
-    }
-    else {
-	str = rb_str_dup(rb_class_path(under));
-	rb_str_cat2(str, "::");
-	rb_str_cat2(str, name);
-    }
-    OBJ_FREEZE(str);
-    rb_ivar_set(klass, classpath, str);
-
-    rb_vm_set_outer(klass, outer);
-}
-
-void
-rb_set_class_path(VALUE klass, VALUE under, const char *name)
-{
-    return rb_set_class_path2(klass, under, name, under);
-}
-
-VALUE
-rb_path2class(const char *path)
-{
-    const char *pbeg, *p;
-    ID id;
-    VALUE c = rb_cObject;
-
-    if (path[0] == '#') {
-	rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
-    }
-    pbeg = p = path;
-    while (*p) {
-	while (*p && *p != ':') p++;
-	id = rb_intern2(pbeg, p-pbeg);
-	if (p[0] == ':') {
-	    if (p[1] != ':') goto undefined_class;
-	    p += 2;
-	    pbeg = p;
-	}
-	if (!rb_const_defined(c, id)) {
-	  undefined_class:
-	    rb_raise(rb_eArgError, "undefined class/module %.*s", (int)(p-path), path);
-	}
-	c = rb_const_get_at(c, id);
-	switch (TYPE(c)) {
-	  case T_MODULE:
-	  case T_CLASS:
-	    break;
-	  default:
-	    rb_raise(rb_eTypeError, "%s does not refer class/module", path);
-	}
-    }
-
-    return c;
-}
-
-void
-rb_name_class(VALUE klass, ID id)
-{
-    rb_iv_set(klass, "__classid__", ID2SYM(id));
-}
-
-VALUE
-rb_class_name(VALUE klass)
-{
-    return rb_class_path(rb_class_real(klass, false));
-}
-
-const char *
-rb_class2name(VALUE klass)
-{
-    return RSTRING_PTR(rb_class_name(klass));
-}
-
-const char *
-rb_obj_classname(VALUE obj)
-{
-    return rb_class2name(rb_class_real(CLASS_OF(obj), true));
-}
-
-struct trace_var {
-    int removed;
-    void (*func)();
-    VALUE data;
-    struct trace_var *next;
-};
-
-struct global_variable {
-    int   counter;
-    void *data;
-    VALUE (*getter)();
-    void  (*setter)();
-    void  (*marker)();
-    int block_trace;
-    struct trace_var *trace;
-};
-
-struct global_entry {
-    struct global_variable *var;
-    ID id;
-};
-
-static VALUE undef_getter(ID id);
-static void  undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
-static void  undef_marker(void);
-
-static VALUE val_getter(ID id, VALUE val);
-static void  val_setter(VALUE val, ID id, void *data, struct global_variable *var);
-static void  val_marker(VALUE data);
-
-static VALUE var_getter(ID id, VALUE *var);
-static void  var_setter(VALUE val, ID id, VALUE *var);
-static void  var_marker(VALUE *var);
-
-#define readonly_setter rb_gvar_readonly_setter
-
-struct global_entry*
-rb_global_entry(ID id)
-{
-    struct global_entry *entry;
-    st_data_t data;
-
-    if (!st_lookup(rb_global_tbl, id, &data)) {
-	struct global_variable *var;
-	entry = ALLOC(struct global_entry);
-	var = ALLOC(struct global_variable);
-	entry->id = id;
-	GC_WB(&entry->var, var);
-	var->counter = 1;
-	var->data = 0;
-	var->getter = undef_getter;
-	var->setter = undef_setter;
-	var->marker = undef_marker;
-
-	var->block_trace = 0;
-	var->trace = 0;
-	st_add_direct(rb_global_tbl, id, (st_data_t)entry);
-    }
-    else {
-	entry = (struct global_entry *)data;
-    }
-    return entry;
-}
-
-static VALUE
-undef_getter(ID id)
-{
-    rb_warning("global variable `%s' not initialized", rb_id2name(id));
-
-    return Qnil;
-}
-
-static void
-undef_setter(VALUE val, ID id, void *data, struct global_variable *var)
-{
-    var->getter = val_getter;
-    var->setter = val_setter;
-    var->marker = val_marker;
-
-    GC_WB(&var->data, val);
-}
-
-static void
-undef_marker(void)
-{
-}
-
-static VALUE
-val_getter(ID id, VALUE val)
-{
-    return val;
-}
-
-static void
-val_setter(VALUE val, ID id, void *data, struct global_variable *var)
-{
-    GC_WB(&var->data, val);
-}
-
-static void
-val_marker(VALUE data)
-{
-    // Do nothing.
-}
-
-static VALUE
-var_getter(ID id, VALUE *var)
-{
-    if (var == NULL) {
-	return Qnil;
-    }
-    return *var;
-}
-
-static void
-var_setter(VALUE val, ID id, VALUE *var)
-{
-    if (*var != val) {
-	GC_RELEASE(*var);
-	*var = val;
-	GC_RETAIN(*var);
-    }
-}
-
-static void
-var_marker(VALUE *var)
-{
-    // Do nothing.
-}
-
-void
-readonly_setter(VALUE val, ID id, void *var)
-{
-    rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
-}
-
-static ID
-global_id(const char *name)
-{
-    ID id;
-
-    if (name[0] == '$') id = rb_intern(name);
-    else {
-	char *buf = ALLOCA_N(char, strlen(name)+2);
-	buf[0] = '$';
-	strcpy(buf+1, name);
-	id = rb_intern(buf);
-    }
-    return id;
-}
-
-void
-rb_define_hooked_variable(const char *name, VALUE *var,
-	VALUE (*getter)(ANYARGS), void  (*setter)(ANYARGS))
-{
-    ID id = global_id(name);
-    struct global_variable *gvar = rb_global_entry(id)->var;
-    gvar->data = (void *)var;
-    gvar->getter = getter != NULL ? getter : var_getter;
-    gvar->setter = setter != NULL ? setter : var_setter;
-    gvar->marker = var_marker;
-}
-
-void
-rb_define_variable(const char *name, VALUE *var)
-{
-    rb_define_hooked_variable(name, var, 0, 0);
-}
-
-void
-rb_define_readonly_variable(const char *name, VALUE *var)
-{
-    rb_define_hooked_variable(name, var, 0, readonly_setter);
-}
-
-void
-rb_define_virtual_variable(
-    const char *name,
-    VALUE (*getter)(ANYARGS),
-    void  (*setter)(ANYARGS))
-{
-    if (!getter) getter = val_getter;
-    if (!setter) setter = readonly_setter;
-    rb_define_hooked_variable(name, 0, getter, setter);
-}
-
-static void
-rb_trace_eval(VALUE cmd, VALUE val)
-{
-    rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
-}
-
-/*
- *  call-seq:
- *     trace_var(symbol, cmd )             => nil
- *     trace_var(symbol) {|val| block }    => nil
- *  
- *  Controls tracing of assignments to global variables. The parameter
- *  +symbol_ identifies the variable (as either a string name or a
- *  symbol identifier). _cmd_ (which may be a string or a
- *  +Proc+ object) or block is executed whenever the variable
- *  is assigned. The block or +Proc+ object receives the
- *  variable's new value as a parameter. Also see
- *  <code>Kernel::untrace_var</code>.
- *     
- *     trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
- *     $_ = "hello"
- *     $_ = ' there'
- *     
- *  <em>produces:</em>
- *     
- *     $_ is now 'hello'
- *     $_ is now ' there'
- */
-
-VALUE rb_f_untrace_var(VALUE rcv, SEL sel, int argc, VALUE *argv);
-
-VALUE
-rb_f_trace_var(VALUE rcv, SEL sel,int argc, VALUE *argv)
-{
-    VALUE var, cmd;
-    struct global_entry *entry;
-    struct trace_var *trace;
-
-    rb_secure(4);
-    if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
-	cmd = rb_block_proc();
-    }
-    if (NIL_P(cmd)) {
-	return rb_f_untrace_var(0, 0, argc, argv);
-    }
-    entry = rb_global_entry(rb_to_id(var));
-    if (OBJ_TAINTED(cmd)) {
-	rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
-    }
-    trace = ALLOC(struct trace_var);
-    trace->next = entry->var->trace;
-    trace->func = rb_trace_eval;
-    trace->data = cmd;
-    trace->removed = 0;
-    GC_WB(&entry->var->trace, trace);
-
-    return Qnil;
-}
-
-static void
-remove_trace(struct global_variable *var)
-{
-    struct trace_var *trace = var->trace;
-    struct trace_var t;
-    struct trace_var *next;
-
-    t.next = trace;
-    trace = &t;
-    while (trace->next) {
-	next = trace->next;
-	if (next->removed) {
-	    trace->next = next->next;
-	    xfree(next);
-	}
-	else {
-	    trace = next;
-	}
-    }
-    var->trace = t.next;
-}
-
-/*
- *  call-seq:
- *     untrace_var(symbol [, cmd] )   => array or nil
- *  
- *  Removes tracing for the specified command on the given global
- *  variable and returns +nil+. If no command is specified,
- *  removes all tracing for that variable and returns an array
- *  containing the commands actually removed.
- */
-
-VALUE
-rb_f_untrace_var(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE var, cmd;
-    ID id;
-    struct global_entry *entry;
-    struct trace_var *trace;
-    st_data_t data;
-
-    rb_scan_args(argc, argv, "11", &var, &cmd);
-    id = rb_to_id(var);
-    if (!st_lookup(rb_global_tbl, id, &data)) {
-	rb_name_error(id, "undefined global variable %s", rb_id2name(id));
-    }
-
-    trace = (entry = (struct global_entry *)data)->var->trace;
-    if (NIL_P(cmd)) {
-	VALUE ary = rb_ary_new();
-
-	while (trace) {
-	    struct trace_var *next = trace->next;
-	    rb_ary_push(ary, (VALUE)trace->data);
-	    trace->removed = 1;
-	    trace = next;
-	}
-
-	if (!entry->var->block_trace) remove_trace(entry->var);
-	return ary;
-    }
-    else {
-	while (trace) {
-	    if (trace->data == cmd) {
-		trace->removed = 1;
-		if (!entry->var->block_trace) remove_trace(entry->var);
-		return rb_ary_new3(1, cmd);
-	    }
-	    trace = trace->next;
-	}
-    }
-    return Qnil;
-}
-
-VALUE
-rb_gvar_get(struct global_entry *entry)
-{
-    struct global_variable *var = entry->var;
-    return (*var->getter)(entry->id, var->data, var);
-}
-
-struct trace_data {
-    struct trace_var *trace;
-    VALUE val;
-};
-
-static VALUE
-trace_ev(struct trace_data *data)
-{
-    struct trace_var *trace = data->trace;
-
-    while (trace) {
-	(*trace->func)(trace->data, data->val);
-	trace = trace->next;
-    }
-    return Qnil;		/* not reached */
-}
-
-static VALUE
-trace_en(struct global_variable *var)
-{
-    var->block_trace = 0;
-    remove_trace(var);
-    return Qnil;		/* not reached */
-}
-
-VALUE
-rb_gvar_set(struct global_entry *entry, VALUE val)
-{
-    struct trace_data trace;
-    struct global_variable *var = entry->var;
-
-    if (rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
-    (*var->setter)(val, entry->id, var->data, var);
-
-    if (var->trace && !var->block_trace) {
-	var->block_trace = 1;
-	trace.trace = var->trace;
-	trace.val = val;
-	rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
-    }
-    return val;
-}
-
-VALUE
-rb_gv_set(const char *name, VALUE val)
-{
-    struct global_entry *entry;
-
-    entry = rb_global_entry(global_id(name));
-    return rb_gvar_set(entry, val);
-}
-
-VALUE
-rb_gv_get(const char *name)
-{
-    struct global_entry *entry;
-
-    entry = rb_global_entry(global_id(name));
-    return rb_gvar_get(entry);
-}
-
-VALUE
-rb_gvar_defined(struct global_entry *entry)
-{
-    if (entry->var->getter == undef_getter) return Qfalse;
-    return Qtrue;
-}
-
-static int
-gvar_i(ID key, struct global_entry *entry, VALUE ary)
-{
-    rb_ary_push(ary, ID2SYM(key));
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     global_variables    => array
- *  
- *  Returns an array of the names of global variables.
- *     
- *     global_variables.grep /std/   #=> [:$stdin, :$stdout, :$stderr]
- */
-
-VALUE
-rb_f_global_variables(VALUE rcv, SEL sel)
-{
-    VALUE ary = rb_ary_new();
-    char buf[4];
-    const char *s = "123456789";
-
-    st_foreach_safe(rb_global_tbl, gvar_i, ary);
-    while (*s) {
-	sprintf(buf, "$%c", *s++);
-	rb_ary_push(ary, ID2SYM(rb_intern(buf)));
-    }
-    return ary;
-}
-
-void
-rb_alias_variable(ID name1, ID name2)
-{
-    struct global_entry *entry1, *entry2;
-    st_data_t data1;
-
-    if (rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
-
-    entry2 = rb_global_entry(name2);
-    if (!st_lookup(rb_global_tbl, name1, &data1)) {
- 	entry1 = ALLOC(struct global_entry);
-	entry1->id = name1;
-	st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
-    }
-    else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) {
-	struct global_variable *var = entry1->var;
-	if (var->block_trace) {
-	    rb_raise(rb_eRuntimeError, "can't alias in tracer");
-	}
-	var->counter--;
-	if (var->counter == 0) {
-	    struct trace_var *trace = var->trace;
-	    while (trace) {
-		struct trace_var *next = trace->next;
-		xfree(trace);
-		trace = next;
-	    }
-	    xfree(var);
-	}
-    }
-    else {
-	return;
-    }
-    entry2->var->counter++;
-    entry1->var = entry2->var;
-}
-
-static CFMutableDictionaryRef generic_iv_dict = NULL;
-
-static CFMutableDictionaryRef
-generic_ivar_dict(VALUE obj, bool create)
-{
-    CFMutableDictionaryRef obj_dict = NULL;
-    if (SPECIAL_CONST_P(obj)) {
-	if (generic_iv_dict == NULL) {	
-	    generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL,
-		    &kCFTypeDictionaryValueCallBacks);
-	}
-	if (!CFDictionaryGetValueIfPresent(generic_iv_dict, 
-		    (const void *)obj, (const void **)&obj_dict) && create) {
-	    obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL,
-		    &rb_cfdictionary_value_cb);
-	    CFMakeCollectable(obj_dict);
-	    CFDictionarySetValue(generic_iv_dict, (const void *)obj,
-		    (const void *)obj_dict);	
-	}
-    }
-    else {
-	obj_dict = rb_objc_get_associative_ref((void *)obj, &generic_iv_dict);
-	if (obj_dict == NULL && create) {
-	    obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL,
-		    &rb_cfdictionary_value_cb);
-	    CFMakeCollectable(obj_dict);
-	    rb_objc_set_associative_ref((void *)obj, &generic_iv_dict,
-		    (void *)obj_dict);
-	}
-    }
-    return obj_dict;
-}
-
-static void
-generic_ivar_dict_set(VALUE obj, CFMutableDictionaryRef obj_dict)
-{
-    if (SPECIAL_CONST_P(obj)) {
-	if (generic_iv_dict == NULL) {	
-	    generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL,
-		    &kCFTypeDictionaryValueCallBacks);
-	}
-	CFDictionarySetValue(generic_iv_dict, (const void *)obj,
-		(const void *)obj_dict);	
-    }
-    else {
-	rb_objc_set_associative_ref((void *)obj, &generic_iv_dict,
-		(void *)obj_dict);
-    }
-}
-
-static VALUE
-generic_ivar_get(VALUE obj, ID id, bool warn, bool undef)
-{
-    CFDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-    if (obj_dict != NULL) {
-	VALUE val;
-	if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id, 
-		    (const void **)&val)) {
-	    return val;
-	}
-    }
-    if (warn) {
-	rb_warning("instance variable %s not initialized", rb_id2name(id));
-    }
-    return undef ? Qundef : Qnil;
-}
-
-static void
-generic_ivar_set(VALUE obj, ID id, VALUE val)
-{
-    if (rb_special_const_p(obj)) {
-	if (rb_obj_frozen_p(obj)) {
-	    rb_error_frozen("object");
-	}
-    }
-    CFMutableDictionaryRef obj_dict = generic_ivar_dict(obj, true);
-//printf("generic_ivar_set %p %ld %p dict %p\n", (void*)obj,id,(void*)val,obj_dict);
-    CFDictionarySetValue(obj_dict, (const void *)id, (const void *)val);
-}
-
-static VALUE
-generic_ivar_defined(VALUE obj, ID id)
-{
-    CFDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-    if (obj_dict != NULL) {
-	if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id, NULL)) {
-	    return Qtrue;
-	}
-    }
-    return Qfalse;    
-}
-
-static bool
-generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
-{
-    CFMutableDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-    if (obj_dict != NULL) {
-	VALUE val;
-	if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id, 
-		    (const void **)&val)) {
-	    *valp = val;
-	    CFDictionaryRemoveValue(obj_dict, (const void *)id);
-	    return true;
-	}
-    }
-    return false;
-}
-
-void
-rb_copy_generic_ivar(VALUE clone, VALUE obj)
-{
-    CFMutableDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-    if (obj_dict != NULL) {
-	generic_ivar_dict_set(clone, obj_dict);
-    }
-}
-
-static inline bool
-rb_class_has_ivar_dict(VALUE mod)
-{
-    const long v = RCLASS_VERSION(mod);
-    return (v & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS
-	&& (v & RCLASS_KVO_CHECK_DONE) != RCLASS_KVO_CHECK_DONE;
-}
-
-#define RCLASS_RUBY_IVAR_DICT(mod) \
-    (*(CFMutableDictionaryRef *) \
-     	((void *)mod + class_getInstanceSize(*(Class *)RCLASS_SUPER(mod))))
-
-CFMutableDictionaryRef 
-rb_class_ivar_dict(VALUE mod)
-{
-    if (rb_class_has_ivar_dict(mod)) {
-	return RCLASS_RUBY_IVAR_DICT(mod);
-    }
-    return generic_ivar_dict(mod, false);
-}
- 
-void
-rb_class_ivar_set_dict(VALUE mod, CFMutableDictionaryRef dict)
-{
-    if (rb_class_has_ivar_dict(mod)) {
-	CFMutableDictionaryRef old_dict = RCLASS_RUBY_IVAR_DICT(mod);
-	if (old_dict != dict) {
-	    if (old_dict != NULL) {
-		GC_RELEASE(old_dict);
-	    }
-	    GC_RETAIN(dict);
-	    RCLASS_RUBY_IVAR_DICT(mod) = dict;
-	}
-    }
-    else {
-	generic_ivar_dict_set(mod, dict);
-    }
-}
-
-CFMutableDictionaryRef
-rb_class_ivar_dict_or_create(VALUE mod)
-{
-    CFMutableDictionaryRef dict;
-
-    dict = rb_class_ivar_dict(mod);
-    if (dict == NULL) {
-	dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
-	rb_class_ivar_set_dict(mod, dict);
-	CFMakeCollectable(dict);
-    }
-    return dict;
-}
-
-static VALUE
-ivar_get(VALUE obj, ID id, bool warn, bool undef)
-{
-    VALUE val;
-
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    {
-		const int slot = rb_vm_get_ivar_slot(obj, id, false);
-		if (slot != -1) {
-		    val = rb_vm_get_ivar_from_slot(obj, slot);
-		    if (val != Qundef) {
-			return val;
-		    }
-		}
-	    }
-	    break;
-
-	case T_CLASS:
-	case T_MODULE:
-	    {
-		CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
-		if (iv_dict != NULL 
-			&& CFDictionaryGetValueIfPresent(
-			    iv_dict, (const void *)id, (const void **)&val)) {
-		    return val;
-		}
-	    }
-	    break;
-
-	case T_NATIVE:
-	default:
-	    return generic_ivar_get(obj, id, warn, undef);
-    }
-    if (warn) {
-	rb_warning("instance variable %s not initialized", rb_id2name(id));
-    }
-    return undef ? Qundef : Qnil;
-}
-
-VALUE
-rb_ivar_get(VALUE obj, ID id)
-{
-    return ivar_get(obj, id, true, false);
-}
-
-VALUE
-rb_attr_get(VALUE obj, ID id)
-{
-    return ivar_get(obj, id, false, false);
-}
-
-VALUE
-rb_ivar_set(VALUE obj, ID id, VALUE val)
-{
-    if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
-    }
-    if (OBJ_FROZEN(obj)) {
-	rb_error_frozen("object");
-    }
-
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    {
-		const int slot = rb_vm_get_ivar_slot(obj, id, true);
-		assert(slot >= 0);
-		rb_vm_set_ivar_from_slot(obj, val, slot);
-		return val;
-	    }
-	    break;
-
-	case T_CLASS:
-	case T_MODULE:
-	    {
-		CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(obj);
-		CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
-	    }
-	    break;
-
-	case T_NATIVE:
-	default:
-	    generic_ivar_set(obj, id, val);
-	    break;
-    }
-    return val;
-}
-
-VALUE
-rb_ivar_defined(VALUE obj, ID id)
-{
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    {
-		const int slot = rb_vm_get_ivar_slot(obj, id, false);
-		if (slot != -1) {
-		    if (rb_vm_get_ivar_from_slot(obj, slot) != Qundef) {
-			return Qtrue;
-		    }
-		}
-	    }
-	    break;
-
-	case T_CLASS:
-	case T_MODULE:
-	    {
-		CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
-		if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, NULL)) {
-		    return Qtrue;
-		}
-		break;
-	    }
-
-	case T_NATIVE:
-	default:
-	    return generic_ivar_defined(obj, id);
-    }
-    return Qfalse;
-}
-
-void
-rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
-{
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    for (unsigned int i = 0; i < ROBJECT(obj)->num_slots; i++) {
-		ID name = ROBJECT(obj)->slots[i].name;
-		VALUE value = ROBJECT(obj)->slots[i].value;
-		if (name != 0 && value != Qundef) {
-		    func(name, value, arg);
-		}
-	    }
-	    break;
-
-      case T_CLASS:
-      case T_MODULE:
-	    {
-		CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
-		if (iv_dict != NULL) {
-		    ivar_dict_foreach(iv_dict, func, arg);
-		}
-	    }
-	    break;
-
-      case T_NATIVE:
-      default:
-	    {
-		CFDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-		if (obj_dict != NULL) {
-		    CFDictionaryApplyFunction(obj_dict,
-			    (CFDictionaryApplierFunction)func, (void *)arg);
-		}
-	    }
-	    break;
-    }
-}
-
-static int
-ivar_i(ID key, VALUE val, VALUE ary)
-{
-    if (rb_is_instance_id(key)) {
-	rb_ary_push(ary, ID2SYM(key));
-    }
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     obj.instance_variables    => array
- *  
- *  Returns an array of instance variable names for the receiver. Note
- *  that simply defining an accessor does not create the corresponding
- *  instance variable.
- *     
- *     class Fred
- *       attr_accessor :a1
- *       def initialize
- *         @iv = 3
- *       end
- *     end
- *     Fred.new.instance_variables   #=> [:@iv]
- */
-
-VALUE
-rb_obj_instance_variables(VALUE obj)
-{
-    VALUE ary;
-
-    ary = rb_ary_new();
-    rb_ivar_foreach(obj, ivar_i, ary);
-    return ary;
-}
-
-/*
- *  call-seq:
- *     obj.remove_instance_variable(symbol)    => obj
- *  
- *  Removes the named instance variable from <i>obj</i>, returning that
- *  variable's value.
- *     
- *     class Dummy
- *       attr_reader :var
- *       def initialize
- *         @var = 99
- *       end
- *       def remove
- *         remove_instance_variable(:@var)
- *       end
- *     end
- *     d = Dummy.new
- *     d.var      #=> 99
- *     d.remove   #=> 99
- *     d.var      #=> nil
- */
-
-VALUE
-rb_obj_remove_instance_variable(VALUE obj, SEL sel, VALUE name)
-{
-    VALUE val = Qnil;
-    ID id = rb_to_id(name);
-
-    if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
-    }
-    if (OBJ_FROZEN(obj)) {
-	rb_error_frozen("object");
-    }
-    if (!rb_is_instance_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
-    }
-
-    switch (TYPE(obj)) {
-	case T_OBJECT:
-	    {
-		const int slot = rb_vm_get_ivar_slot(obj, id, false);
-		if (slot != -1) {
-		    val = rb_vm_get_ivar_from_slot(obj, slot);
-		    if (val != Qundef) {
-			rb_vm_set_ivar_from_slot(obj, Qundef, slot);
-			return val;
-		    }
-		}
-	    }
-	    break;
-
-	case T_CLASS:
-	case T_MODULE:
-	    {
-		CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
-		if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)) {
-		    CFDictionaryRemoveValue(iv_dict, (const void *)id);
-		    return val;
-		}	      
-	    }
-	    break;
-
-	default:
-	    if (generic_ivar_remove(obj, id, &val)) {
-		return val;
-	    }
-	    break;
-    }
-    rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
-    return Qnil;		/* not reached */
-}
-
-NORETURN(static void uninitialized_constant(VALUE, ID));
-static void
-uninitialized_constant(VALUE klass, ID id)
-{
-    if (klass && klass != rb_cObject)
-	rb_name_error(id, "uninitialized constant %s::%s",
-		      rb_class2name(klass),
-		      rb_id2name(id));
-    else {
-	rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
-    }
-}
-
-static VALUE
-call_const_missing(VALUE klass, ID id)
-{
-    VALUE arg = ID2SYM(id);
-    return rb_vm_call(klass, selConstMissing, 1, &arg);
-}
-
-/*
- * call-seq:
- *    mod.const_missing(sym)    => obj
- *
- *  Invoked when a reference is made to an undefined constant in
- *  <i>mod</i>. It is passed a symbol for the undefined constant, and
- *  returns a value to be used for that constant. The
- *  following code is a (very bad) example: if reference is made to
- *  an undefined constant, it attempts to load a file whose name is
- *  the lowercase version of the constant (thus class <code>Fred</code> is
- *  assumed to be in file <code>fred.rb</code>). If found, it returns the
- *  value of the loaded class. It therefore implements a perverse
- *  kind of autoload facility.
- *  
- *    def Object.const_missing(name)
- *      @looked_for ||= {}
- *      str_name = name.to_s
- *      raise "Class not found: #{name}" if @looked_for[str_name]
- *      @looked_for[str_name] = 1
- *      file = str_name.downcase
- *      require file
- *      klass = const_get(name)
- *      return klass if klass
- *      raise "Class not found: #{name}"
- *    end
- *  
- */
-
-VALUE
-rb_mod_const_missing(VALUE klass, SEL sel, VALUE name)
-{
-    //rb_frame_pop(); /* pop frame for "const_missing" */
-    uninitialized_constant(klass, rb_to_id(name));
-    return Qnil;		/* not reached */
-}
-
-static struct st_table *
-check_autoload_table(VALUE av)
-{
-    Check_Type(av, T_DATA);
-    if (false) {
-	// TODO
-	VALUE desc = rb_inspect(av);
-	rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING_PTR(desc));
-    }
-    return (struct st_table *)DATA_PTR(av);
-}
-
-void
-rb_autoload(VALUE mod, ID id, const char *file)
-{
-    VALUE av, fn;
-    struct st_table *tbl;
-
-    if (!rb_is_const_id(id)) {
-	rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
-    }
-    if (!file || !*file) {
-	rb_raise(rb_eArgError, "empty file name");
-    }
-
-    if ((av = rb_attr_get(mod, id)) != Qnil && av != Qundef) {
-	return;
-    }
-
-    rb_const_set(mod, id, Qundef);
-    if ((av = rb_attr_get(mod, autoload)) != Qnil) {
-	tbl = check_autoload_table(av);
-    }
-    else {
-	av = Data_Wrap_Struct(rb_cData, NULL, NULL, 0);
-	rb_ivar_set(mod, autoload, av);
-	tbl = st_init_numtable();
-	GC_WB(&DATA_PTR(av), tbl);
-    }
-    fn = rb_str_new2(file);
-    rb_obj_untaint(fn);
-    OBJ_FREEZE(fn);
-    NODE *n = rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0);
-    GC_RELEASE(n);
-    st_insert(tbl, id, (st_data_t)n);
-}
-
-static NODE*
-autoload_delete(VALUE mod, ID id)
-{
-    VALUE val;
-    st_data_t load = 0;
-
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
-    assert(iv_dict != NULL);
-    CFDictionaryRemoveValue(iv_dict, (const void *)id);
-    if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, 
-	(const void *)autoload, (const void **)&val)) {
-	struct st_table *tbl = check_autoload_table(val);
-
-	st_delete(tbl, (st_data_t*)&id, &load);
-
-	if (tbl->num_entries == 0) {
-	    DATA_PTR(val) = 0;
-	    st_free_table(tbl);
-	    id = autoload;
-	    CFDictionaryRemoveValue(iv_dict, (const void *)id);
-	}
-    }
-
-    return (NODE *)load;
-}
-
-VALUE
-rb_autoload_load(VALUE klass, ID id)
-{
-    VALUE file;
-    NODE *load = autoload_delete(klass, id);
-
-    if (!load || !(file = load->nd_lit)) {
-	return Qfalse;
-    }
-    return rb_require_safe(file, load->nd_nth);
-}
-
-static VALUE
-autoload_file(VALUE mod, ID id)
-{
-    VALUE val, file;
-    struct st_table *tbl;
-    st_data_t load;
-
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
-    assert(iv_dict != NULL);
-    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, 
-	   (const void *)autoload, (const void **)&val)
-	|| (tbl = check_autoload_table(val)) == NULL
-	|| !st_lookup(tbl, id, &load))
-	return Qnil;
-    file = ((NODE *)load)->nd_lit;
-    Check_Type(file, T_STRING);
-    if (RSTRING_LEN(file) == 0) {
-	rb_raise(rb_eArgError, "empty file name");
-    }
-    if (!rb_provided(RSTRING_PTR(file))) {
-	return file;
-    }
-
-    /* already loaded but not defined */
-    st_delete(tbl, (st_data_t*)&id, 0);
-    if (!tbl->num_entries) {
-	DATA_PTR(val) = 0;
-	st_free_table(tbl);
-	id = autoload;
-	CFDictionaryRemoveValue(iv_dict, (const void *)id);
-    }
-    return Qnil;
-}
-
-VALUE
-rb_autoload_p(VALUE mod, ID id)
-{
-    CFDictionaryRef iv_dict = (CFDictionaryRef)rb_class_ivar_dict(mod);
-    VALUE val;
-
-    if (iv_dict == NULL 
-	|| !CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)
-	|| val != Qundef)
-	return Qnil;
-    return autoload_file(mod, id);
-}
-
-static VALUE
-retrieve_dynamic_objc_class(VALUE klass, ID name)
-{
-    // The Objective-C class dynamic resolver. By default, MacRuby doesn't
-    // know about native classes. They will be resolved and added into the
-    // NSObject dictionary on demand.
-    Class k = (Class)objc_getClass(rb_id2name(name));
-    if (k != NULL && !RCLASS_RUBY(k)) {
-	// Skip classes that aren't pure Objective-C, to avoid namespace
-	// conflicts in Ruby land.
-	CFMutableDictionaryRef dict = rb_class_ivar_dict_or_create(rb_cObject);
-	if (!CFDictionaryContainsKey(dict, (const void *)name)) {
-	    CFDictionarySetValue(dict, (const void *)name, (const void *)k);
-	    rb_objc_force_class_initialize(k);
-	}
-	return (VALUE)k;
-    }
-    return Qnil;
-}
-
-static VALUE
-rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
-{
-    VALUE value, tmp;
-    int mod_retry = 0;
-
-    tmp = klass;
-retry:
-    while (RTEST(tmp)) {
-	CFDictionaryRef iv_dict;
-	while ((iv_dict = rb_class_ivar_dict(tmp)) != NULL
-		&& CFDictionaryGetValueIfPresent(iv_dict, (const void *)id,
-		    (const void **)&value)) {
-	    if (value == Qundef) {
-		if (!RTEST(rb_autoload_load(tmp, id))) {
-		    break;
-		}
-		goto retry;
-	    }
-	    if (exclude && tmp == rb_cObject && klass != rb_cObject) {
-		rb_warn("toplevel constant %s referenced by %s::%s",
-			rb_id2name(id), rb_class2name(klass), rb_id2name(id));
-	    }
-	    return rb_vm_resolve_const_value(value, klass, id);
-	}
-	if (!recurse && klass != rb_cObject) {
-	    break;
-	}
-	VALUE inc_mods = rb_attr_get(tmp, idIncludedModules);
-	if (inc_mods != Qnil) {
-	    int i, count = RARRAY_LEN(inc_mods);
-	    for (i = 0; i < count; i++) {
-		VALUE mod = RARRAY_AT(inc_mods, i);
-		iv_dict = rb_class_ivar_dict(mod);
-		if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id,
-			    (const void **)&value)) {
- 		    if (value == Qundef) {
-			if (!RTEST(rb_autoload_load(mod, id))) {
-			    break;
-			}
-			goto retry;
-		    }
-		    return rb_vm_resolve_const_value(value, klass, id);
-		}
-	    }
-	}
-	tmp = RCLASS_SUPER(tmp);
-    }
-    if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
-	mod_retry = 1;
-	tmp = rb_cObject;
-	goto retry;
-    }
-    VALUE k = retrieve_dynamic_objc_class(klass, id);
-    if (k != Qnil) {
-	return k;
-    }
-    return call_const_missing(klass, id);
-}
-
-VALUE
-rb_const_get_from(VALUE klass, ID id)
-{
-    return rb_const_get_0(klass, id, Qtrue, Qtrue);
-}
-
-VALUE
-rb_const_get(VALUE klass, ID id)
-{
-    return rb_const_get_0(klass, id, Qfalse, Qtrue);
-}
-
-VALUE
-rb_const_get_at(VALUE klass, ID id)
-{
-    return rb_const_get_0(klass, id, Qtrue, Qfalse);
-}
-
-/*
- *  call-seq:
- *     remove_const(sym)   => obj
- *  
- *  Removes the definition of the given constant, returning that
- *  constant's value. Predefined classes and singleton objects (such as
- *  <i>true</i>) cannot be removed.
- */
-
-VALUE
-rb_mod_remove_const(VALUE mod, VALUE name)
-{
-    ID id = rb_to_id(name);
-    VALUE val;
-
-    if (!rb_is_const_id(id)) {
-	rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
-    }
-    if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
-    }
-    if (OBJ_FROZEN(mod)) {
-	rb_error_frozen("class/module");
-    }
-
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
-    if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
-	CFDictionaryRemoveValue(iv_dict, (const void *)id);
-	if (val == Qundef) {
-	    autoload_delete(mod, id);
-	    val = Qnil;
-	}
-	return val;
-    }
-    if (rb_const_defined_at(mod, id)) {
-	rb_name_error(id, "cannot remove %s::%s",
-		 rb_class2name(mod), rb_id2name(id));
-    }
-    rb_name_error(id, "constant %s::%s not defined",
-		  rb_class2name(mod), rb_id2name(id));
-    return Qnil;		/* not reached */
-}
-
-static int
-sv_i(ID key, VALUE value, st_table *tbl)
-{
-    if (rb_is_const_id(key)) {
-	if (!st_lookup(tbl, key, 0)) {
-	    st_insert(tbl, key, key);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-void*
-rb_mod_const_at(VALUE mod, void *data)
-{
-    st_table *tbl = data;
-    if (!tbl) {
-	tbl = st_init_numtable();
-    }
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
-    if (iv_dict != NULL) {
-	ivar_dict_foreach(iv_dict, sv_i, (VALUE)tbl);
-    }
-    return tbl;
-}
-
-void*
-rb_mod_const_of(VALUE mod, void *data)
-{
-    VALUE tmp = mod;
-    for (;;) {
-	data = rb_mod_const_at(tmp, data);
-	tmp = RCLASS_SUPER(tmp);
-	if (tmp == 0) {
-	    break;
-	}
-	if (tmp == rb_cObject && mod != rb_cObject) {
-	    break;
-	}
-    }
-    return data;
-}
-
-static int
-list_i(ID key, ID value, VALUE ary)
-{
-    rb_ary_push(ary, ID2SYM(key));
-    return ST_CONTINUE;
-}
-
-VALUE
-rb_const_list(void *data)
-{
-    st_table *tbl = data;
-    VALUE ary;
-
-    if (tbl == NULL) {
-	return rb_ary_new2(0);
-    }
-    ary = rb_ary_new2(tbl->num_entries);
-    st_foreach_safe(tbl, list_i, ary);
-    st_free_table(tbl);
-
-    return ary;
-}
-
-/*
- *  call-seq:
- *     mod.constants(inherit=true)    => array
- *  
- *  Returns an array of the names of the constants accessible in
- *  <i>mod</i>. This includes the names of constants in any included
- *  modules (example at start of section), unless the <i>all</i>
- *  parameter is set to <code>false</code>.
- *
- *    IO.constants.include?(:SYNC)         => true
- *    IO.constants(false).include?(:SYNC)  => false
- *
- *  Also see <code>Module::const_defined?</code>.
- */
-
-VALUE
-rb_mod_constants(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    VALUE inherit;
-    st_table *tbl;
-
-    if (argc == 0) {
-	inherit = Qtrue;
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &inherit);
-    }
-    if (RTEST(inherit)) {
-	tbl = rb_mod_const_of(mod, 0);
-    }
-    else {
-	tbl = rb_mod_const_at(mod, 0);
-    }
-    return rb_const_list(tbl);
-}
-
-static int
-rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse)
-{
-    VALUE value, tmp;
-    int mod_retry = 0;
-
-    tmp = klass;
-  retry:
-    while (tmp) {
-	CFDictionaryRef iv_dict = rb_class_ivar_dict(tmp);
-	if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, 
-	    (const void *)id, (const void **)&value)) {
-	    if (value == Qundef && NIL_P(autoload_file(klass, id))) {
-		return Qfalse;
-	    }
-	    return Qtrue;
-	}
-	if (!recurse && klass != rb_cObject) {
-	    break;
-	}
-	VALUE inc_mods = rb_attr_get(tmp, idIncludedModules);
-	if (inc_mods != Qnil) {
-	    int i, count = RARRAY_LEN(inc_mods);
-	    for (i = 0; i < count; i++) {
-		iv_dict = rb_class_ivar_dict(RARRAY_AT(inc_mods, i));
-		if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value))
-		    return Qtrue;
-	    }
-	}
-	tmp = RCLASS_SUPER(tmp);
-    }
-    if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
-	mod_retry = 1;
-	tmp = rb_cObject;
-	goto retry;
-    }
-    VALUE k = retrieve_dynamic_objc_class(klass, id);
-    if (k != Qnil) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-int
-rb_const_defined_from(VALUE klass, ID id)
-{
-    return rb_const_defined_0(klass, id, Qtrue, Qtrue);
-}
-
-int
-rb_const_defined(VALUE klass, ID id)
-{
-    return rb_const_defined_0(klass, id, Qfalse, Qtrue);
-}
-
-int
-rb_const_defined_at(VALUE klass, ID id)
-{
-    return rb_const_defined_0(klass, id, Qtrue, Qfalse);
-}
-
-static void
-mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
-{
-    const char *dest = isconst ? "constant" : "class variable";
-
-    if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
-    }
-    if (OBJ_FROZEN(klass)) {
-	if (BUILTIN_TYPE(klass) == T_MODULE) {
-	    rb_error_frozen("module");
-	}
-	else {
-	    rb_error_frozen("class");
-	}
-    }
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(klass);
-    if (isconst) {
-	VALUE value = Qfalse;
-
-	if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&value)) {
-	    if (value == Qundef) {
-		autoload_delete(klass, id);
-	    }
-	    else {
-		rb_warn("already initialized %s %s", dest, rb_id2name(id));
-	    }
-	}
-    }
-
-    CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
-    rb_vm_const_is_defined(id);
-}
-
-void
-rb_const_set(VALUE klass, ID id, VALUE val)
-{
-    if (NIL_P(klass)) {
-	rb_raise(rb_eTypeError, "no class/module to define constant %s",
-		 rb_id2name(id));
-    }
-    mod_av_set(klass, id, val, Qtrue);
-}
-
-void
-rb_define_const(VALUE klass, const char *name, VALUE val)
-{
-    ID id = rb_intern(name);
-
-    if (!rb_is_const_id(id)) {
-	rb_warn("rb_define_const: invalid name `%s' for constant", name);
-    }
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    rb_const_set(klass, id, val);
-}
-
-void
-rb_define_global_const(const char *name, VALUE val)
-{
-    rb_define_const(rb_cObject, name, val);
-}
-
-static inline VALUE
-unmeta_class(VALUE klass)
-{
-    if (RCLASS_META(klass)) {
-	klass = (VALUE)objc_getClass(class_getName((Class)klass));
-    }
-    return klass;
-}
-
-void
-rb_cvar_set(VALUE klass, ID id, VALUE val)
-{
-    klass = unmeta_class(klass);
-
-    // Locate the class where the cvar should be set by looking through the
-    // current class ancestry.
-    VALUE k = klass;
-    while (k != 0) {
-	if (ivar_get(k, id, false, true) != Qundef) {
-	    klass = k;
-	    break;
-	}
-	k = RCLASS_SUPER(k);
-    }
-
-    rb_ivar_set(klass, id, val);
-}
-
-static VALUE
-rb_cvar_get3(VALUE klass, ID id, bool check, bool defined)
-{
-    VALUE orig = klass;
-    klass = unmeta_class(klass);
-
-    // Locate the cvar by looking through the class ancestry.
-    while (klass != 0) {
-	VALUE value = ivar_get(klass, id, false, true);
-	if (value != Qundef) {
-	    return defined ? Qtrue : value;
-	}
-	klass = RCLASS_SUPER(klass);
-    }
-
-    if (check) {
-	rb_name_error(id,"uninitialized class variable %s in %s",
-		rb_id2name(id), rb_class2name(orig));
-    }
-    else {
-	return defined ? Qfalse : Qnil;
-    }
-}
-
-VALUE
-rb_cvar_get2(VALUE klass, ID id, bool check)
-{
-    return rb_cvar_get3(klass, id, check, false);
-}
-
-VALUE
-rb_cvar_get(VALUE klass, ID id)
-{
-    return rb_cvar_get2(klass, id, true);
-}
-
-VALUE
-rb_cvar_defined(VALUE klass, ID id)
-{
-    return rb_cvar_get3(klass, id, false, true);
-}
-
-void
-rb_cv_set(VALUE klass, const char *name, VALUE val)
-{
-    ID id = rb_intern(name);
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "wrong class variable name %s", name);
-    }
-    rb_cvar_set(klass, id, val);
-}
-
-VALUE
-rb_cv_get(VALUE klass, const char *name)
-{
-    ID id = rb_intern(name);
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "wrong class variable name %s", name);
-    }
-    return rb_cvar_get(klass, id);
-}
-
-void
-rb_define_class_variable(VALUE klass, const char *name, VALUE val)
-{
-    ID id = rb_intern(name);
-
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "wrong class variable name %s", name);
-    }
-    rb_cvar_set(klass, id, val);
-}
-
-static int
-cv_i(ID key, VALUE value, VALUE ary)
-{
-    if (rb_is_class_id(key)) {
-	VALUE kval = ID2SYM(key);
-	if (!rb_ary_includes(ary, kval)) {
-	    rb_ary_push(ary, kval);
-	}
-    }
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     mod.class_variables   => array
- *  
- *  Returns an array of the names of class variables in <i>mod</i>.
- *     
- *     class One
- *       @@var1 = 1
- *     end
- *     class Two < One
- *       @@var2 = 2
- *     end
- *     One.class_variables   #=> [:@@var1]
- *     Two.class_variables   #=> [:@@var2]
- */
-
-VALUE
-rb_mod_class_variables(VALUE klass, SEL sel)
-{
-    klass = unmeta_class(klass);
-    VALUE ary = rb_ary_new();
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
-    if (iv_dict != NULL) {
-	ivar_dict_foreach(iv_dict, cv_i, (VALUE)ary);
-    }
-    return ary;
-}
-
-/*
- *  call-seq:
- *     remove_class_variable(sym)    => obj
- *  
- *  Removes the definition of the <i>sym</i>, returning that
- *  constant's value.
- *     
- *     class Dummy
- *       @@var = 99
- *       puts @@var
- *       remove_class_variable(:@@var)
- *       puts(defined? @@var)
- *     end
- *     
- *  <em>produces:</em>
- *     
- *     99
- *     nil
- */
-
-VALUE
-rb_mod_remove_cvar(VALUE mod, SEL sel, VALUE name)
-{
-    ID id = rb_to_id(name);
-    VALUE val;
-
-    if (!rb_is_class_id(id)) {
-	rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
-    }
-    if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4) {
-	rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
-    }
-    if (OBJ_FROZEN(mod)) {
-	rb_error_frozen("class/module");
-    }
-
-    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
-    if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
-	CFDictionaryRemoveValue(iv_dict, (const void *)id);
-	return val;
-    }
-    if (rb_cvar_defined(mod, id)) {
-	rb_name_error(id, "cannot remove %s for %s",
-		 rb_id2name(id), rb_class2name(mod));
-    }
-    rb_name_error(id, "class variable %s not defined for %s",
-		  rb_id2name(id), rb_class2name(mod));
-    return Qnil;		/* not reached */
-}
-
-VALUE
-rb_iv_get(VALUE obj, const char *name)
-{
-    ID id = rb_intern(name);
-
-    return rb_ivar_get(obj, id);
-}
-
-VALUE
-rb_iv_set(VALUE obj, const char *name, VALUE val)
-{
-    ID id = rb_intern(name);
-
-    return rb_ivar_set(obj, id, val);
-}

Deleted: MacRuby/trunk/version.c
===================================================================
--- MacRuby/trunk/version.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/version.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,55 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#include "macruby_internal.h"
-#include "version.h"
-#include "revision.h"
-#include <stdio.h>
-
-#define PRINT(type) puts(ruby_##type)
-#define MKSTR(type) rb_obj_freeze(rb_usascii_str_new(ruby_##type, sizeof(ruby_##type)-1))
-
-const int ruby_version_code = RUBY_VERSION_CODE;
-const char ruby_version[] = RUBY_VERSION;
-const char ruby_release_date[] = RUBY_RELEASE_DATE;
-const char ruby_platform[] = RUBY_PLATFORM;
-const int ruby_patchlevel = RUBY_PATCHLEVEL;
-const char ruby_description[] = RUBY_DESCRIPTION;
-const char ruby_copyright[] = RUBY_COPYRIGHT;
-const char ruby_engine[] = RUBY_ENGINE;
-
-void
-Init_version(void)
-{
-    rb_define_global_const("RUBY_VERSION", MKSTR(version));
-    rb_define_global_const("RUBY_RELEASE_DATE", MKSTR(release_date));
-    rb_define_global_const("RUBY_PLATFORM", MKSTR(platform));
-    rb_define_global_const("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL));
-    rb_define_global_const("RUBY_REVISION", INT2FIX(RUBY_REVISION));
-    rb_define_global_const("RUBY_DESCRIPTION", MKSTR(description));
-    rb_define_global_const("RUBY_COPYRIGHT", MKSTR(copyright));
-    rb_define_global_const("RUBY_ENGINE", MKSTR(engine));
-#if WITH_OBJC
-    rb_define_global_const("RUBY_ARCH", rb_str_new2(RUBY_ARCH));
-    rb_define_global_const("MACRUBY_VERSION", rb_str_new2(MACRUBY_VERSION));
-    rb_define_global_const("MACRUBY_REVISION", rb_str_new2(MACRUBY_REVISION));
-#endif
-}
-
-void
-ruby_show_version(void)
-{
-    PRINT(description);
-    fflush(stdout);
-}
-
-void
-ruby_show_copyright(void)
-{
-    PRINT(copyright);
-    exit(0);
-}

Deleted: MacRuby/trunk/version.h
===================================================================
--- MacRuby/trunk/version.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/version.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,82 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- */
-
-#define RUBY_ENGINE 		"macruby"
-#define MACRUBY_VERSION 	"0.11"
-
-#define RUBY_VERSION 		"1.9.2"
-#define RUBY_RELEASE_DATE 	"2008-06-03"
-#define RUBY_VERSION_CODE 	190
-#define RUBY_RELEASE_CODE 	20080603
-#define RUBY_PATCHLEVEL 	0
-
-#define RUBY_VERSION_MAJOR 	1
-#define RUBY_VERSION_MINOR 	9
-#define RUBY_VERSION_TEENY 	0
-#define RUBY_RELEASE_YEAR 	2008
-#define RUBY_RELEASE_MONTH 	6
-#define RUBY_RELEASE_DAY 	3
-
-#ifdef RUBY_EXTERN
-RUBY_EXTERN const int ruby_version_code;
-RUBY_EXTERN const char ruby_version[];
-RUBY_EXTERN const char ruby_release_date[];
-RUBY_EXTERN const char ruby_platform[];
-RUBY_EXTERN const int ruby_patchlevel;
-RUBY_EXTERN const char ruby_description[];
-RUBY_EXTERN const char ruby_copyright[];
-#endif
-
-#define RUBY_AUTHOR 		"Apple Inc."
-#define RUBY_BIRTH_YEAR 	2007
-
-#ifndef RUBY_REVISION
-# define RUBY_REVISION 0
-#endif
-
-#if RUBY_VERSION_TEENY > 0 && RUBY_PATCHLEVEL < 5000 && !RUBY_REVISION
-#define RUBY_RELEASE_STR "patchlevel"
-#define RUBY_RELEASE_NUM RUBY_PATCHLEVEL
-#else
-#ifdef RUBY_BRANCH_NAME
-#define RUBY_RELEASE_STR RUBY_BRANCH_NAME
-#else
-#define RUBY_RELEASE_STR "revision"
-#endif
-#define RUBY_RELEASE_NUM RUBY_REVISION
-#endif
-
-#if defined(__LP64__)
-#  if BYTE_ORDER == BIG_ENDIAN
-#    define RUBY_ARCH "ppc64"
-#  else
-#    define RUBY_ARCH "x86_64"
-#  endif
-#else
-#  if BYTE_ORDER == BIG_ENDIAN
-#    define RUBY_ARCH "ppc"
-#  else
-#    define RUBY_ARCH "i386"
-#  endif
-#endif
-
-#if MACRUBY_STATIC
-# define MACRUBY_NAME "MacRuby-static"
-#else
-# define MACRUBY_NAME "MacRuby"
-#endif
-
-#define RUBY_DESCRIPTION	    	\
-    MACRUBY_NAME " " MACRUBY_VERSION	\
-    " (ruby "RUBY_VERSION	    	\
-    ") ["RUBY_PLATFORM", "RUBY_ARCH"]"
-
-#define RUBY_COPYRIGHT 	    \
-    "MacRuby - Copyright (C) "	    \
-    STRINGIZE(RUBY_BIRTH_YEAR)"-"   \
-    STRINGIZE(RUBY_RELEASE_YEAR)" " \
-    RUBY_AUTHOR

Deleted: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/vm.cpp	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,5258 +0,0 @@
-/*
- * MacRuby VM.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#define ROXOR_VM_DEBUG		0
-#define ROXOR_COMPILER_DEBUG 	0
-
-#if MACRUBY_STATIC
-# include <vector>
-# include <map>
-# include <string>
-#else
-# include <llvm/Module.h>
-# include <llvm/DerivedTypes.h>
-# include <llvm/Constants.h>
-# include <llvm/CallingConv.h>
-# include <llvm/Instructions.h>
-# include <llvm/PassManager.h>
-# include <llvm/Analysis/DebugInfo.h>
-# if !defined(LLVM_TOT)
-#  include <llvm/Analysis/DIBuilder.h>
-# endif
-# include <llvm/Analysis/Verifier.h>
-# include <llvm/Target/TargetData.h>
-# include <llvm/CodeGen/MachineFunction.h>
-# include <llvm/ExecutionEngine/JIT.h>
-# include <llvm/ExecutionEngine/JITMemoryManager.h>
-# include <llvm/ExecutionEngine/JITEventListener.h>
-# include <llvm/ExecutionEngine/GenericValue.h>
-# include <llvm/Target/TargetData.h>
-# include <llvm/Target/TargetMachine.h>
-# include <llvm/Target/TargetOptions.h>
-# include <llvm/Target/TargetSelect.h>
-# include <llvm/Transforms/Scalar.h>
-# include <llvm/Transforms/IPO.h>
-# include <llvm/Support/raw_ostream.h>
-# if !defined(LLVM_TOT)
-#  include <llvm/Support/system_error.h>
-# endif
-# include <llvm/Support/PrettyStackTrace.h>
-# include <llvm/Support/MemoryBuffer.h>
-# include <llvm/Support/StandardPasses.h>
-# include <llvm/Intrinsics.h>
-# include <llvm/Bitcode/ReaderWriter.h>
-# include <llvm/LLVMContext.h>
-using namespace llvm;
-#endif // MACRUBY_STATIC
-
-#if ROXOR_COMPILER_DEBUG
-# include <mach/mach.h>
-# include <mach/mach_time.h>
-#endif
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "id.h"
-#include "vm.h"
-#include "compiler.h"
-#include "debugger.h"
-#include "interpreter.h"
-#include "objc.h"
-#include "dtrace.h"
-#include "class.h"
-
-#include <objc/objc-exception.h>
-
-#include <execinfo.h>
-#include <dlfcn.h>
-
-#include <iostream>
-#include <fstream>
-
-RoxorCore *RoxorCore::shared = NULL;
-RoxorVM *RoxorVM::main = NULL;
-pthread_key_t RoxorVM::vm_thread_key;
-
-VALUE rb_cTopLevel = 0;
-
-// A simple class that acquires the core global lock in its constructor and
-// releases it in its destructor. It is used to make sure the lock will be
-// released in case an exception happens inside the scope (since C++ exceptions
-// call object destructors).
-class RoxorCoreLock {
-    private:
-	bool locked;
-
-    public:
-	RoxorCoreLock() {
-	    GET_CORE()->lock();
-	    locked = true;
-	}
-
-	~RoxorCoreLock() {
-	    if (locked) {
-		GET_CORE()->unlock();
-		locked = false;
-	    }
-	}
-
-	void unlock(void) {
-	    assert(locked);
-	    GET_CORE()->unlock();
-	    locked = false;
-	}
-};
-
-#if !defined(MACRUBY_STATIC)
-class RoxorFunction {
-    public: 
-	// Information retrieved from JITManager.
-	Function *f;
-	unsigned char *start;
-	unsigned char *end;
-	std::vector<unsigned char *> ehs;
-
-	// Information retrieved from JITListener.
-	std::string path;
-	class Line {
-	    public:
-		uintptr_t address;
-		unsigned line;
-		Line(uintptr_t _address, unsigned _line) {
-		    address = _address;
-		    line = _line;
-		}
-	};
-	std::vector<Line> lines;
-
-	// Information retrieved later (lazily).
-	void *imp;
-
-	RoxorFunction(Function *_f, unsigned char *_start,
-		unsigned char *_end) {
-	    f = _f;
-	    start = _start;
-	    end = _end;
-	    imp = NULL;
-	}
-};
-
-class RoxorJITManager : public JITMemoryManager, public JITEventListener {
-    private:
-        JITMemoryManager *mm;
-	std::vector<RoxorFunction *> functions;
-
-	RoxorFunction *current_function(void) {
-	    assert(!functions.empty());
-	    return functions.back();
-	}
-
-    public:
-	RoxorJITManager() : JITMemoryManager() { 
-	    mm = CreateDefaultMemManager(); 
-	}
-
-	RoxorFunction *find_function(uint8_t *addr) {
-	     if (functions.empty()) {
-		return NULL;
-	     }
-	     // TODO optimize me!
-	     RoxorFunction *front = functions.front();
-	     RoxorFunction *back = functions.back();
-	     if (addr < front->start || addr > back->end) {
-		return NULL;
-	     }
-	     std::vector<RoxorFunction *>::iterator iter = 
-		 functions.begin();
-	     while (iter != functions.end()) {
-		RoxorFunction *f = *iter;
-		if (addr >= f->start && addr <= f->end) {
-		    return f;
-		}
-		++iter;
-	     }
-	     return NULL;
-	}
-
-	RoxorFunction *delete_function(Function *func) {
-	    std::vector<RoxorFunction *>::iterator iter = 
-		functions.begin();
-	    while (iter != functions.end()) {
-		RoxorFunction *f = *iter;
-		if (f->f == func) {
-		    functions.erase(iter);
-		    return f;
-		}
-		++iter;
-	    }
-	    return NULL;
-	}
-
-	// JITMemoryManager callbacks.
-
-	void setMemoryWritable(void) { 
-	    mm->setMemoryWritable(); 
-	}
-
-	void setMemoryExecutable(void) { 
-	    mm->setMemoryExecutable(); 
-	}
-
-	uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { 
-	    return mm->allocateSpace(Size, Alignment); 
-	}
-
-	uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
-	    return mm->allocateGlobal(Size, Alignment);
-	}
-
-	void AllocateGOT(void) {
-	    mm->AllocateGOT();
-	}
-
-	uint8_t *getGOTBase() const {
-	    return mm->getGOTBase();
-	}
-
-	uint8_t *startFunctionBody(const Function *F, 
-		uintptr_t &ActualSize) {
-	    return mm->startFunctionBody(F, ActualSize);
-	}
-
-	uint8_t *allocateStub(const GlobalValue* F, 
-		unsigned StubSize, 
-		unsigned Alignment) {
-	    return mm->allocateStub(F, StubSize, Alignment);
-	}
-
-	void endFunctionBody(const Function *F, uint8_t *FunctionStart, 
-		uint8_t *FunctionEnd) {
-	    mm->endFunctionBody(F, FunctionStart, FunctionEnd);
-	    Function *f = const_cast<Function *>(F);
-	    functions.push_back(new RoxorFunction(f, FunctionStart,
-			FunctionEnd));
-	}
-
-	void deallocateFunctionBody(void *data) {
-	    mm->deallocateFunctionBody(data);
-	}
-
-	void deallocateExceptionTable(void *data) {
-	    mm->deallocateExceptionTable(data);
-	}
-
-	uint8_t* startExceptionTable(const Function* F, 
-		uintptr_t &ActualSize) {
-	    return mm->startExceptionTable(F, ActualSize);
-	}
-
-	void endExceptionTable(const Function *F, uint8_t *TableStart, 
-		uint8_t *TableEnd, uint8_t* FrameRegister) {
-	    current_function()->ehs.push_back(FrameRegister);
-	    mm->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
-	}
-
-	void setPoisonMemory(bool poison) {
-	    mm->setPoisonMemory(poison);
-	}
-
-	// JITEventListener callbacks.
-
-	void NotifyFunctionEmitted(const Function &F,
-		void *Code, size_t Size,
-		const EmittedFunctionDetails &Details) {
-	    RoxorFunction *function = current_function();
-
-	    std::string path;
-	    for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator iter = Details.LineStarts.begin(); iter != Details.LineStarts.end(); ++iter) {
-		MDNode *scope = iter->Loc.getAsMDNode(F.getContext());
-		DILocation loc = DILocation(scope);
-		if (path.size() == 0) {
-		    RoxorCompiler::shared->generate_location_path(path, loc);
-		}
-//printf("%p -> %d\n", (void*)iter->Address, loc.getLineNumber());
-		RoxorFunction::Line line(iter->Address, loc.getLineNumber());
-		function->lines.push_back(line);
-	    }
-
-	    function->path = path;
-	}
-};
-#endif
-
-extern "C" void *__cxa_allocate_exception(size_t);
-extern "C" void __cxa_throw(void *, void *, void (*)(void *));
-extern "C" void __cxa_rethrow(void);
-extern "C" std::type_info *__cxa_current_exception_type(void);
-
-RoxorCore::RoxorCore(void)
-{
-    running = false;
-    abort_on_exception = false;
-
-    pthread_assert(pthread_mutex_init(&gl, 0));
-
-    // Will be set later.
-    default_random = Qnil;
-
-    load_path = rb_ary_new();
-    GC_RETAIN(load_path);
-
-    loaded_features = rb_ary_new();
-    GC_RETAIN(loaded_features);
-
-    threads = rb_ary_new();
-    GC_RETAIN(threads);
-
-#if !MACRUBY_STATIC
-    bs_parser = NULL;
-    llvm_start_multithreaded();
-    interpreter_enabled = getenv("VM_DISABLE_INTERPRETER") == NULL;
-
-    // The JIT is created later, if necessary.
-    InitializeNativeTarget();
-    jmm = NULL; 
-    ee = NULL;
-    fpm = NULL;
-
-# if ROXOR_VM_DEBUG
-    functions_compiled = 0;
-# endif
-#endif // !MACRUBY_STATIC
-}
-
-void
-RoxorCore::prepare_jit(void)
-{
-#if !defined(MACRUBY_STATIC)
-    assert(ee == NULL);
-    jmm = new RoxorJITManager;
-
-    CodeGenOpt::Level opt = CodeGenOpt::Default;
-    inlining_enabled = false;
-    optims_enabled = true;
-    const char *env_str = getenv("VM_OPT_LEVEL");
-    if (env_str != NULL) {
-	const int tmp = atoi(env_str);
-	if (tmp >= 0 && tmp <= 3) {
-	    switch (tmp) {
-		case 0:
-		    opt = CodeGenOpt::None;
-		    optims_enabled = false;
-		    break;
-		case 1:
-		    opt = CodeGenOpt::Less;
-		    break;
-		case 2:
-		    opt = CodeGenOpt::Default;
-		    break;
-		case 3:
-		    opt = CodeGenOpt::Aggressive;
-		    inlining_enabled = true;
-		    break;
-	    }
-	}
-    }
-
-    std::string err;
-    ee = ExecutionEngine::createJIT(RoxorCompiler::module, &err, jmm, opt,
-	    false);
-    if (ee == NULL) {
-	fprintf(stderr, "error while creating JIT: %s\n", err.c_str());
-	abort();
-    }
-    ee->DisableLazyCompilation();
-    ee->RegisterJITEventListener(jmm);
-
-    fpm = new FunctionPassManager(RoxorCompiler::module);
-    fpm->add(new TargetData(*ee->getTargetData()));
-
-    // Do simple "peephole" optimizations and bit-twiddling optzns.
-    fpm->add(createInstructionCombiningPass());
-    // Eliminate unnecessary alloca.
-    fpm->add(createPromoteMemoryToRegisterPass());
-    // Reassociate expressions.
-    fpm->add(createReassociatePass());
-    // Eliminate Common SubExpressions.
-    fpm->add(createGVNPass());
-    // Simplify the control flow graph (deleting unreachable blocks, etc).
-    fpm->add(createCFGSimplificationPass());
-    // Eliminate tail calls.
-    fpm->add(createTailCallEliminationPass());
-#endif
-}
-
-RoxorCore::~RoxorCore(void)
-{
-    // TODO
-}
-
-RoxorVM::RoxorVM(void)
-{
-    current_top_object = Qnil;
-    current_class = NULL;
-    safe_level = 0;
-    backref = Qnil;
-    broken_with = Qundef;
-    last_line = Qnil;
-    last_status = Qnil;
-    errinfo = Qnil;
-    parse_in_eval = false;
-    has_ensure = false;
-    return_from_block = -1;
-    special_exc = NULL;
-    current_super_class = NULL;
-    current_super_sel = 0;
-    current_mri_method_self = Qnil;
-    current_mri_method_sel = 0;
-
-    mcache = (struct mcache *)calloc(VM_MCACHE_SIZE, sizeof(struct mcache));
-    assert(mcache != NULL);
-}
-
-static inline void *
-block_cache_key(const rb_vm_block_t *b)
-{
-    if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
-	return (void *)b->imp;
-    }
-    return (void *)b->userdata;
-}
-
-RoxorVM::RoxorVM(const RoxorVM &vm)
-{
-    current_top_object = vm.current_top_object;
-    current_class = vm.current_class;
-    safe_level = vm.safe_level;
-
-    std::vector<rb_vm_block_t *> &vm_blocks =
-	const_cast<RoxorVM &>(vm).current_blocks;
-
-    for (std::vector<rb_vm_block_t *>::iterator i = vm_blocks.begin();
-	 (i + 1) != vm_blocks.end();
-	 ++i) {
-
-	const rb_vm_block_t *orig = *i;
-	rb_vm_block_t *b = NULL;
-	if (orig != NULL) {
-#if 1
-	    b = const_cast<rb_vm_block_t *>(orig);
-#else
-	    // XXX: This code does not work yet, it raises a failed integrity
-	    // check when running the specs.
-	    const size_t block_size = sizeof(rb_vm_block_t *)
-		+ (orig->dvars_size * sizeof(VALUE *));
-
-	    b = (rb_vm_block_t *)xmalloc(block_size);
-	    memcpy(b, orig, block_size);
-
-	    b->proc = orig->proc; // weak
-	    GC_WB(&b->self, orig->self);
-	    GC_WB(&b->locals, orig->locals);
-	    GC_WB(&b->parent_block, orig->parent_block);  // XXX not sure
-#endif
-	    GC_RETAIN(b);
-	    blocks[block_cache_key(orig)] = b;
-	}
-	current_blocks.push_back(b);
-    }
-
-    // TODO bindings, exceptions?
-
-    backref = Qnil;
-    broken_with = Qundef;
-    last_line = Qnil;
-    last_status = Qnil;
-    errinfo = Qnil;
-    parse_in_eval = false;
-    has_ensure = false;
-    return_from_block = -1;
-    special_exc = NULL;
-    current_super_class = NULL;
-    current_super_sel = 0;
-
-    mcache = (struct mcache *)calloc(VM_MCACHE_SIZE, sizeof(struct mcache));
-    assert(mcache != NULL);
-}
-
-RoxorVM::~RoxorVM(void)
-{
-    for (std::map<void *, rb_vm_block_t *>::iterator i = blocks.begin();
-	i != blocks.end();
-	++i) {
-	GC_RELEASE(i->second);
-    }
-    blocks.clear();
-
-    GC_RELEASE(backref);
-    GC_RELEASE(broken_with);
-    GC_RELEASE(last_status);
-    GC_RELEASE(errinfo);
-
-    free(mcache);
-    mcache = NULL;
-}
-
-void
-RoxorVM::debug_blocks(void)
-{
-    for (std::vector<rb_vm_block_t *>::iterator i = current_blocks.begin();
-	    i != current_blocks.end();
-	    ++i) {
-	printf("%p ", *i);
-    }
-    printf("\n");
-}
-
-void
-RoxorVM::debug_exceptions(void)
-{
-    for (std::vector<VALUE>::iterator i = current_exceptions.begin();
-	    i != current_exceptions.end();
-	    ++i) {
-	printf("%p ", (void *)*i);
-    }
-    printf("\n");
-}
-
-void
-RoxorCore::debug_outers(Class k)
-{
-    struct rb_vm_outer *o = get_outer(k);
-    std::string s;
-    while (o != NULL) {
-	printf("%p ", o->klass);
-	o = o->outer;
-    }
-    printf("\n");
-}
-
-#if !defined(MACRUBY_STATIC)
-void
-RoxorCore::optimize(Function *func)
-{
-    if (inlining_enabled) {
-	RoxorCompiler::shared->inline_function_calls(func);
-    }
-    if (optims_enabled && fpm != NULL) {
-	fpm->run(*func);
-    }
-}
-
-extern "C"
-void
-rb_verify_module(void)
-{
-    if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
-	printf("Error during module verification\n");
-	abort();
-    }
-}
-
-IMP
-RoxorCore::compile(Function *func, bool run_optimize)
-{
-    std::map<Function *, IMP>::iterator iter = JITcache.find(func);
-    if (iter != JITcache.end()) {
-	return iter->second;
-    }
-
-#if ROXOR_COMPILER_DEBUG
-    // in AOT mode, the verifier is already called
-    // (and calling it here would check functions not fully compiled yet)
-    if (!ruby_aot_compile) {
-	rb_verify_module();
-    }
-
-    uint64_t start = mach_absolute_time();
-#endif
-
-    // Optimize if needed.
-    if (run_optimize) {
-	optimize(func);
-    }
-
-    // Compile & cache.
-    IMP imp = (IMP)ee->getPointerToFunction(func);
-    JITcache[func] = imp;
-
-#if ROXOR_COMPILER_DEBUG
-    uint64_t elapsed = mach_absolute_time() - start;
-
-    static mach_timebase_info_data_t sTimebaseInfo;
-
-    if (sTimebaseInfo.denom == 0) {
-	(void) mach_timebase_info(&sTimebaseInfo);
-    }
-
-    uint64_t elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom;
-
-    fprintf(stderr, "compilation of LLVM function %p done, took %lld ns\n",
-	func, elapsedNano);
-#endif
-
-#if ROXOR_VM_DEBUG
-    functions_compiled++;
-#endif
-
-    return imp;
-}
-
-// in libgcc
-extern "C" void __deregister_frame(const void *);
-
-void
-RoxorCore::delenda(Function *func)
-{
-    assert(func->use_empty());
-
-    RoxorCoreLock lock;
-
-    // Remove from cache.
-    std::map<Function *, IMP>::iterator iter = JITcache.find(func);
-    if (iter != JITcache.end()) {
-	JITcache.erase(iter);
-    }
-
-    // Delete for JIT memory manager list.
-    RoxorFunction *f = jmm->delete_function(func);
-    assert(f != NULL);
-
-    // Unregister each dwarf exception handler.
-    // XXX this should really be done by LLVM...
-    for (std::vector<unsigned char *>::iterator i = f->ehs.begin();
-	    i != f->ehs.end(); ++i) {
-	__deregister_frame((const void *)*i);
-    }
-
-    // Remove the compiler scope.
-    delete f;
-
-    // Delete machine code.
-    ee->freeMachineCodeForFunction(func);
-
-    // Delete IR.
-    func->eraseFromParent();
-}
-#endif
-
-// Dummy function to be used for debugging (in gdb).
-extern "C"
-void
-rb_symbolicate(void *addr)
-{
-    char path[1000];
-    char name[100];
-    unsigned long ln = 0;
-    if (GET_CORE()->symbolize_call_address(addr, path, sizeof path,
-		&ln, name, sizeof name, NULL)) {
-	printf("addr %p selector %s location %s:%ld\n",
-		addr, name, path, ln);
-    }
-    else {
-	printf("addr %p unknown\n", addr);
-    }
-}
-
-bool
-RoxorCore::symbolize_call_address(void *addr, char *path, size_t path_len,
-	unsigned long *ln, char *name, size_t name_len,
-	unsigned int *interpreter_frame_idx)
-{
-#if MACRUBY_STATIC
-    return false;
-#else
-    if (jmm == NULL) {
-	return false;
-    }
-
-    RoxorFunction *f = jmm->find_function((unsigned char *)addr);
-    if (f != NULL) {
-	if (f->imp == NULL) {
-	    f->imp = ee->getPointerToFunctionOrStub(f->f);
-	}
-    }
-    else {
-	std::string fr_name;
-	std::string fr_path;
-	unsigned int fr_line = 0;
-	if (interpreter_frame_idx == NULL
-		|| !RoxorInterpreter::shared->frame_at_index(*interpreter_frame_idx,
-		    addr, &fr_name, &fr_path, &fr_line)) {
-	    return false;
-	}
-	(*interpreter_frame_idx)++;
-	if (name != NULL) {
-	    strlcpy(name, fr_name.c_str(), name_len);
-	}
-	if (path != NULL) {
-	    strlcpy(path, fr_path.c_str(), path_len);
-	}
-	if (ln != NULL) {
-	    *ln = fr_line;
-	}
-	return true;
-    }
-
-    if (f != NULL) {
-	if (ln != NULL) {
-	    *ln = 0;
-	    for (std::vector<RoxorFunction::Line>::iterator iter =
-		    f->lines.begin(); iter != f->lines.end(); ++iter) {
-		if ((uintptr_t)addr <= (*iter).address) {
-		    break;
-		}
-		*ln = (*iter).line;
-	    }
-	}
-	if (path != NULL) {
-	    strncpy(path, f->path.c_str(), path_len);
-	}
-	if (name != NULL) {
-	    std::map<IMP, rb_vm_method_node_t *>::iterator iter = 
-		ruby_imps.find((IMP)f->imp);
-	    if (iter == ruby_imps.end()) {
-		strncpy(name, "block", name_len);
-	    }
-	    else {
-		strncpy(name, sel_getName(iter->second->sel), name_len);
-	    }
-	}
-    }
-    else {
-	if (ln != NULL) {
-	    *ln = 0;
-	}
-	if (path != NULL) {
-	    strncpy(path, "core", path_len);
-	}
-	if (name != NULL) {
-	    name[0] = '\0';
-	}
-    }
-
-    return true;
-#endif
-}
-
-void
-RoxorCore::symbolize_backtrace_entry(int index, char *path, size_t path_len,
-	unsigned long *ln, char *name, size_t name_len)
-{
-    void *callstack[10];
-    const int callstack_n = backtrace(callstack, 10);
-
-    index++; // count us!
-
-    if (callstack_n < index
-	    || !GET_CORE()->symbolize_call_address(callstack[index], path,
-		path_len, ln, name, name_len, NULL)) {
-	if (path != NULL) {
-	    strncpy(path, "core", path_len);
-	}
-	if (ln != NULL) {
-	    *ln = 0;
-	}
-    }
-}
-
-struct ccache *
-RoxorCore::constant_cache_get(ID path)
-{
-    std::map<ID, struct ccache *>::iterator iter = ccache.find(path);
-    if (iter == ccache.end()) {
-	struct ccache *cache = (struct ccache *)malloc(sizeof(struct ccache));
-	cache->outer = 0;
-	cache->outer_mask = 0;
-	cache->val = Qundef;
-	ccache[path] = cache;
-	return cache;
-    }
-    return iter->second;
-}
-
-extern "C"
-void *
-rb_vm_get_constant_cache(const char *name)
-{
-    return GET_CORE()->constant_cache_get(rb_intern(name));
-}
-
-rb_vm_method_node_t *
-RoxorCore::method_node_get(IMP imp, bool create)
-{
-    rb_vm_method_node_t *n;
-    std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
-    if (iter == ruby_imps.end()) {
-	if (create) {
-	    n = (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
-	    ruby_imps[imp] = n;
-	}
-	else {
-	    n = NULL;
-	}
-    }
-    else {
-	n = iter->second;
-    }
-    return n;
-}
-
-rb_vm_method_node_t *
-RoxorCore::method_node_get(Method m, bool create)
-{
-    rb_vm_method_node_t *n;
-    std::map<Method, rb_vm_method_node_t *>::iterator iter =
-	ruby_methods.find(m);
-    if (iter == ruby_methods.end()) {
-	if (create) {
-	    n = (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
-	    ruby_methods[m] = n;
-	}
-	else {
-	    n = NULL;
-	}
-    }
-    else {
-	n = iter->second;
-    }
-    return n;
-}
-
-extern "C"
-bool
-rb_vm_is_ruby_method(Method m)
-{
-    return GET_CORE()->method_node_get(m) != NULL;
-}
-
-#if !defined(MACRUBY_STATIC)
-size_t
-RoxorCore::get_sizeof(const Type *type)
-{
-    return ee->getTargetData()->getTypeSizeInBits(type) / 8;
-}
-
-size_t
-RoxorCore::get_sizeof(const char *type)
-{
-    return get_sizeof(RoxorCompiler::shared->convert_type(type));
-}
-
-#ifdef __LP64__
-# define LARGE_STRUCT_SIZE 128
-#else
-# define LARGE_STRUCT_SIZE 64
-#endif /* !__LP64__ */
-
-bool
-RoxorCore::is_large_struct_type(const Type *type)
-{
-    return type->getTypeID() == Type::StructTyID
-	&& ee->getTargetData()->getTypeSizeInBits(type) > LARGE_STRUCT_SIZE;
-}
-
-GlobalVariable *
-RoxorCore::redefined_op_gvar(SEL sel, bool create)
-{
-    std::map <SEL, GlobalVariable *>::iterator iter =
-	redefined_ops_gvars.find(sel);
-    GlobalVariable *gvar = NULL;
-    if (iter == redefined_ops_gvars.end()) {
-	if (create) {
-	    // TODO: if OPTZ_LEVEL is 3, force global variables to always be
-	    // true and read-only.
-	    gvar = new GlobalVariable(*RoxorCompiler::module,
-		    Type::getInt8Ty(context),
-		    false,
-		    GlobalValue::InternalLinkage,
-		    ConstantInt::get(Type::getInt8Ty(context), 0),
-		    "");
-	    assert(gvar != NULL);
-	    redefined_ops_gvars[sel] = gvar;
-	}
-    }
-    else {
-	gvar = iter->second;
-    }
-    return gvar;
-}
-#endif
-
-bool
-RoxorCore::should_invalidate_inline_op(SEL sel, Class klass)
-{
-    if (sel == selEq || sel == selEqq || sel == selNeq) {
-	return klass == (Class)rb_cFixnum
-	    || klass == (Class)rb_cFloat
-	    || klass == (Class)rb_cBignum
-	    || klass == (Class)rb_cSymbol
-	    || klass == (Class)rb_cNSString
-	    || klass == (Class)rb_cNSMutableString
-	    || klass == (Class)rb_cNSArray
-	    || klass == (Class)rb_cNSMutableArray
-	    || klass == (Class)rb_cNSHash
-	    || klass == (Class)rb_cNSMutableHash;
-    }
-    if (sel == selPLUS || sel == selMINUS || sel == selDIV 
-	|| sel == selMULT || sel == selLT || sel == selLE 
-	|| sel == selGT || sel == selGE) {
-	return klass == (Class)rb_cFixnum
-	    || klass == (Class)rb_cFloat
-	    || klass == (Class)rb_cBignum;
-    }
-    if (sel == selLTLT || sel == selAREF || sel == selASET) {
-	return klass == (Class)rb_cNSArray
-	    || klass == (Class)rb_cNSMutableArray;
-    }
-    if (sel == selSend || sel == sel__send__ || sel == selEval) {
-	// Matches any class, since these are Kernel methods.
-	return true;
-    }
-
-    // Assume yes by default.
-    return true;
-}
-
-static ID
-sanitize_mid(SEL sel)
-{
-    const char *selname = sel_getName(sel);
-    const size_t sellen = strlen(selname);
-    if (selname[sellen - 1] == ':') {
-	if (memchr(selname, ':', sellen - 1) != NULL) {
-	    return 0;
-	}
-	char buf[100];
-	strncpy(buf, selname, sellen);
-	buf[sellen - 1] = '\0';
-	return rb_intern(buf);
-    }
-    return rb_intern(selname);
-}
-
-void
-RoxorCore::method_added(Class klass, SEL sel)
-{
-    if (get_running()) {
-	// Call method_added: or singleton_method_added:.
-	ID mid = sanitize_mid(sel);
-	if (mid != 0) {
-	    VALUE sym = ID2SYM(mid);
-	    if (RCLASS_SINGLETON(klass)) {
-		VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
-		rb_vm_call(sk, selSingletonMethodAdded, 1, &sym);
-	    }
-	    else {
-		rb_vm_call((VALUE)klass, selMethodAdded, 1, &sym);
-	    }
-	}
-    }
-}
-
-void
-RoxorCore::invalidate_method_cache(SEL sel)
-{
-    struct mcache *cache = GET_VM()->get_mcache();
-    for (int i = 0; i < VM_MCACHE_SIZE; i++) {
-	struct mcache *e = &cache[i];
-	if (e->sel == sel) {
-	    e->flag = 0;
-	}
-    }
-}
-
-rb_vm_method_node_t *
-RoxorCore::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
-	const rb_vm_arity_t &arity, int flags, const char *types)
-{
-    // #initialize and #initialize_copy are always private.
-    if (sel == selInitialize || sel == selInitialize2
-	    || sel == selInitializeCopy) {
-	flags |= VM_METHOD_PRIVATE;
-    }
-
-#if ROXOR_VM_DEBUG
-    printf("defining %c[%s %s] with imp %p/%p types %s flags %d arity %d\n",
-	    class_isMetaClass(klass) ? '+' : '-',
-	    class_getName(klass),
-	    sel_getName(sel),
-	    imp,
-	    ruby_imp,
-	    types,
-	    flags,
-	    arity.real);
-#endif
-
-    // Register the implementation into the runtime.
-    class_replaceMethod(klass, sel, imp, types);
-
-    // Cache the method.
-    Method m = class_getInstanceMethod(klass, sel);
-    assert(m != NULL);
-    assert(method_getImplementation(m) == imp);
-    rb_vm_method_node_t *real_node = method_node_get(m, true);
-    real_node->klass = klass;
-    real_node->objc_imp = imp;
-    real_node->ruby_imp = ruby_imp;
-    real_node->arity = arity;
-    real_node->flags = flags;
-    real_node->sel = sel;
-
-    // Cache the implementation.
-    std::map<IMP, rb_vm_method_node_t *>::iterator iter2 = ruby_imps.find(imp);
-    rb_vm_method_node_t *node;
-    if (iter2 == ruby_imps.end()) {
-	node = (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
-	node->objc_imp = imp;
-	ruby_imps[imp] = node;
-    }
-    else {
-	node = iter2->second;
-	assert(node->objc_imp == imp);
-    }
-    node->klass = klass;
-    node->arity = arity;
-    node->flags = flags;
-    node->sel = sel;
-    node->ruby_imp = ruby_imp;
-    if (imp != ruby_imp) {
-	ruby_imps[ruby_imp] = node;
-    }
-
-    if (running) {
-	// Invalidate respond_to cache.
-	invalidate_respond_to_cache();
-
-	// Invalidate dispatch cache.
-	invalidate_method_cache(sel);
-
-	// Invalidate inline operations.
-#if !defined(MACRUBY_STATIC)
-	GlobalVariable *gvar = redefined_op_gvar(sel, false);
-	if (gvar != NULL && should_invalidate_inline_op(sel, klass)) {
-	    void *val = ee->getOrEmitGlobalVariable(gvar);
-#if ROXOR_VM_DEBUG
-	    printf("change redefined global for [%s %s] to true\n",
-		    class_getName(klass),
-		    sel_getName(sel));
-#endif
-	    assert(val != NULL);
-	    *(unsigned char *)val = 1;
-	}
-#endif
-    }
-
-    // If alloc is redefined, mark the class as such.
-    if (sel == selAlloc
-	&& (RCLASS_VERSION(klass) & RCLASS_HAS_ROBJECT_ALLOC) 
-	== RCLASS_HAS_ROBJECT_ALLOC) {
-	RCLASS_SET_VERSION(klass, (RCLASS_VERSION(klass) ^ 
-		    RCLASS_HAS_ROBJECT_ALLOC));
-    }
-
-    // Forward method definition to the included classes.
-    if (RCLASS_VERSION(klass) & RCLASS_IS_INCLUDED) {
-	VALUE included_in_classes = rb_attr_get((VALUE)klass, 
-		idIncludedInClasses);
-	if (included_in_classes != Qnil) {
-	    for (int i = 0, count = RARRAY_LEN(included_in_classes);
-		    i < count; i++) {
-		VALUE mod = RARRAY_AT(included_in_classes, i);
-#if ROXOR_VM_DEBUG
-		printf("forward %c[%s %s] with imp %p node %p types %s\n",
-			class_isMetaClass((Class)mod) ? '+' : '-',
-			class_getName((Class)mod),
-			sel_getName(sel),
-			imp,
-			node,
-			types);
-#endif
-		class_replaceMethod((Class)mod, sel, imp, types);
-
-		Method m = class_getInstanceMethod((Class)mod, sel);
-		assert(m != NULL);
-		assert(method_getImplementation(m) == imp);
-		node = method_node_get(m, true);
-		node->klass = (Class)mod;
-		node->objc_imp = imp;
-		node->ruby_imp = ruby_imp;
-		node->arity = arity;
-		node->flags = flags;
-		node->sel = sel;
-	    }
-	}
-    }
-
-    return real_node;
-}
-
-void
-RoxorCore::const_defined(ID path)
-{
-    // Invalidate constant cache.
-    std::map<ID, struct ccache *>::iterator iter = ccache.find(path);
-    if (iter != ccache.end()) {
-	iter->second->val = Qundef;
-    }
-}
-
-extern "C"
-bool
-rb_vm_running(void)
-{
-    return GET_CORE()->get_running();
-}
-
-extern "C"
-void
-rb_vm_set_running(bool flag)
-{
-    GET_CORE()->set_running(flag); 
-}
-
-extern "C"
-VALUE
-rb_vm_default_random(void)
-{
-    return GET_CORE()->get_default_random();
-}
-
-extern "C"
-void
-rb_vm_set_default_random(VALUE random)
-{
-    RoxorCore *core = GET_CORE();
-    RoxorCoreLock lock;
-
-    if (core->get_default_random() != random) {
-	GC_RELEASE(core->get_default_random());
-	GC_RETAIN(random);
-	core->set_default_random(random);
-    }
-}
-
-VALUE
-RoxorCore::trap_cmd_for_signal(int signal)
-{
-    RoxorCoreLock lock;
-
-    return trap_cmd[signal];
-}
-
-extern "C"
-VALUE
-rb_vm_trap_cmd_for_signal(int signal)
-{
-    return GET_CORE()->trap_cmd_for_signal(signal);
-}
-
-int
-RoxorCore::trap_level_for_signal(int signal)
-{
-    RoxorCoreLock lock;
-
-    return trap_level[signal];
-}
-
-extern "C"
-int
-rb_vm_trap_level_for_signal(int signal)
-{
-    return GET_CORE()->trap_level_for_signal(signal);
-}
-
-void
-RoxorCore::set_trap_for_signal(VALUE trap, int level, int signal)
-{
-    RoxorCoreLock lock;
-
-    VALUE oldtrap = trap_cmd[signal];
-    if (oldtrap != trap) {
-	GC_RELEASE(oldtrap);
-	GC_RETAIN(trap);
-	trap_cmd[signal] = trap;
-	trap_level[signal] = level;
-    }
-}
-
-extern "C"
-void
-rb_vm_set_trap_for_signal(VALUE trap, int level, int signal)
-{
-    GET_CORE()->set_trap_for_signal(trap, level, signal);
-}
-
-extern "C"
-bool
-rb_vm_abort_on_exception(void)
-{
-    return GET_CORE()->get_abort_on_exception();
-}
-
-extern "C"
-void
-rb_vm_set_abort_on_exception(bool flag)
-{
-    GET_CORE()->set_abort_on_exception(flag);
-}
-
-static inline VALUE
-rb_const_get_direct(VALUE klass, ID id)
-{
-    // Search the given class.
-    CFDictionaryRef iv_dict = rb_class_ivar_dict(klass);
-    if (iv_dict != NULL) {
-retry:
-	VALUE value;
-	if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id,
-		    (const void **)&value)) {
-	    if (value == Qundef) {
-		// Constant is a candidate for autoload. We must release the
-		// GIL before requiring the file and acquire it again.
-		GET_CORE()->unlock();
-		const bool autoloaded = RTEST(rb_autoload_load(klass, id));
-		GET_CORE()->lock();
-		if (autoloaded) {
-		    goto retry;
-		}
-	    }
-	    return value;
-	}
-    }
-    // Search the included modules.
-    VALUE mods = rb_attr_get(klass, idIncludedModules);
-    if (mods != Qnil) {
-	int i, count = RARRAY_LEN(mods);
-	for (i = 0; i < count; i++) {
-	    VALUE mod = RARRAY_AT(mods, i);
-	    VALUE val = rb_const_get_direct(mod, id);
-	    if (val != Qundef) {
-		return val;
-	    }
-	}
-    }
-    return Qundef;
-}
-
-extern "C"
-VALUE
-rb_vm_const_lookup_level(VALUE outer, uint64_t outer_mask, ID path,
-	bool lexical, bool defined)
-{
-    rb_vm_check_if_module(outer);
-
-    if (lexical) {
-	// Let's do a lexical lookup before a hierarchical one, by looking for
-	// the given constant in all modules under the given outer.
-	GET_CORE()->lock();
-	struct rb_vm_outer *o = GET_CORE()->get_outer((Class)outer);
-	unsigned int n = 0;
-	while (o != NULL && o->klass != (Class)rb_cNSObject) {
-	    // If the current outer isn't in the mask, it means we can use it
-	    // for const lookup. The outer mask is used when performing const
-	    // lookups inside modules defined using the :: notation
-	    // (ex: class A::B; class C; class D::E; ...)
-	    if (!(outer_mask & (1 << n))) {
-		VALUE val = rb_const_get_direct((VALUE)o->klass, path);
-		if (val != Qundef) {
-		    GET_CORE()->unlock();
-		    return defined ? Qtrue : val;
-		}
-	    }
-	    o = o->outer;
-	    n++;
-	}
-	GET_CORE()->unlock();
-    }
-
-    // Nothing was found earlier so here we do a hierarchical lookup.
-    return defined ? rb_const_defined(outer, path) : rb_const_get(outer, path);
-}
-
-extern "C"
-void
-rb_vm_const_is_defined(ID path)
-{
-    GET_CORE()->const_defined(path);
-}
-
-struct rb_vm_outer *
-RoxorCore::get_outer(Class klass)
-{
-    std::map<Class, struct rb_vm_outer *>::iterator iter =
-	outers.find(klass);
-    return iter == outers.end() ? NULL : iter->second;
-}
-
-void
-RoxorCore::set_outer(Class klass, Class mod) 
-{
-    if (klass != mod) {
-	struct rb_vm_outer *mod_outer = get_outer(mod);
-	struct rb_vm_outer *class_outer = get_outer(klass);
-	if (class_outer == NULL || class_outer->outer != mod_outer) {
-	    if (class_outer == NULL) {
-		class_outer = (struct rb_vm_outer *)
-		    malloc(sizeof(struct rb_vm_outer));
-		class_outer->klass = klass;
-	    }
-	    class_outer->outer = mod_outer;
-	    outers[klass] = class_outer;
-#if ROXOR_VM_DEBUG
-	    printf("set outer of %s to %s (%p)\n", class_getName(klass),
-		    class_getName(mod), mod_outer);
-#endif
-	}
-    }
-}
-
-extern "C"
-void
-rb_vm_set_outer(VALUE klass, VALUE under)
-{
-    GET_CORE()->set_outer((Class)klass, (Class)under);
-}
-
-extern "C"
-VALUE
-rb_vm_get_outer(VALUE klass)
-{
-    rb_vm_outer_t *o = GET_CORE()->get_outer((Class)klass);
-    return o == NULL ? Qundef : (VALUE)o->klass;
-}
-
-extern "C"
-VALUE
-rb_vm_module_nesting(VALUE mod)
-{
-    VALUE ary = rb_ary_new();
-    rb_vm_outer_t *o = GET_CORE()->get_outer((Class)mod);
-    while (o != NULL) {
-	rb_ary_push(ary, (VALUE)o->klass);
-	o = o->outer;
-    }
-    return ary;
-}
-
-static VALUE
-get_klass_const(VALUE outer, ID path, bool lexical)
-{
-    VALUE klass = Qundef;
-    if (lexical) {
-	if (rb_vm_const_lookup(outer, path, true, true) == Qtrue) {
-	    klass = rb_vm_const_lookup(outer, path, true, false);
-	}
-    }
-    else {
-	if (rb_const_defined_at(outer, path)) {
-	    klass = rb_const_get_at(outer, path);
-	}
-    }
-    if (klass != Qundef) {
-	rb_vm_check_if_module(klass);
-	if (outer != rb_cObject && !RCLASS_RUBY(klass)) {
-	    // Ignore classes retrieved by the dynamic resolver.
-	    klass = Qundef;
-	}
-    }
-    return klass;
-}
-
-extern "C"
-VALUE
-rb_vm_define_class(ID path, VALUE outer, VALUE super, int flags,
-	unsigned char dynamic_class)
-{
-    assert(path > 0);
-    rb_vm_check_if_module(outer);
-
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-
-    VALUE klass = get_klass_const(outer, path, dynamic_class);
-    if (klass != Qundef) {
-	// Constant is already defined.
-	if (!(flags & DEFINE_MODULE) && super != 0) {
-	    if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
-		rb_raise(rb_eTypeError, "superclass mismatch for class %s",
-			rb_class2name(klass));
-	    }
-	}
-    }
-    else {
-	// Prepare the constant outer.
-	VALUE const_outer;
-	if ((flags & DEFINE_OUTER) || (flags & DEFINE_SUB_OUTER)) {
-	    const_outer = outer;
-	}
-	else {
-	    const_outer = rb_cObject;
-	}
-
-	// Define the constant.
-	if (flags & DEFINE_MODULE) {
-	    assert(super == 0);
-	    klass = rb_define_module_id(path);
-	    rb_set_class_path2(klass, outer, rb_id2name(path), const_outer);
-	    rb_const_set(outer, path, klass);
-	}
-	else {
-	    if (super == 0) {
-		super = rb_cObject;
-	    }
-	    else {
-		if (TYPE(super) != T_CLASS) {
-		    rb_raise(rb_eTypeError,
-			"wrong argument type (expected Class)");
-		}
-	    }
-	    klass = rb_define_class_id(path, super);
-	    rb_set_class_path2(klass, outer, rb_id2name(path), const_outer);
-	    rb_const_set(outer, path, klass);
-	    rb_class_inherited(super, klass);
-	}
-    }
-
-#if ROXOR_VM_DEBUG
-    if (flags & DEFINE_MODULE) {
-	printf("define module %s::%s\n", 
-		class_getName((Class)outer), 
-		rb_id2name(path));
-    }
-    else {
-	printf("define class %s::%s < %s\n", 
-		class_getName((Class)outer), 
-		rb_id2name(path), 
-		class_getName((Class)super));
-    }
-#endif
-
-    return klass;
-}
-
-extern "C"
-struct icache *
-rb_vm_ivar_slot_allocate(void)
-{
-    struct icache *icache = (struct icache *)malloc(sizeof(struct icache));
-    icache->klass = 0;
-    icache->slot = SLOT_CACHE_VIRGIN;
-    return icache;
-}
-
-extern "C"
-int
-rb_vm_get_ivar_slot(VALUE obj, ID name, bool create)
-{
-    if (TYPE(obj) == T_OBJECT) {
-        unsigned int i;
-        for (i = 0; i < ROBJECT(obj)->num_slots; i++) {
-            if (ROBJECT(obj)->slots[i].name == name) {
-                return i;
-            }
-        }
-	if (create) {
-	    for (i = 0; i < ROBJECT(obj)->num_slots; i++) {
-		if (ROBJECT(obj)->slots[i].value == Qundef) {
-		    ROBJECT(obj)->slots[i].name = name;
-		    return i;
-		}
-	    }
-	    const int new_slot = ROBJECT(obj)->num_slots;
-	    rb_vm_regrow_robject_slots(ROBJECT(obj), new_slot + 1);
-	    ROBJECT(obj)->slots[new_slot].name = name;
-	    return new_slot;
-	}
-    }
-    return -1;
-}
-
-extern "C" void rb_print_undef(VALUE, ID, int);
-
-static void
-vm_alias_method(Class klass, Method method, ID name, bool noargs)
-{
-    IMP imp = method_getImplementation(method);
-    if (UNAVAILABLE_IMP(imp)) {
-	return;
-    }
-
-    const char *types = method_getTypeEncoding(method);
-    SEL sel = rb_vm_id_to_sel(name, noargs ? 0 : 1);
-    rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
-    if (node != NULL) {
-	GET_CORE()->add_method(klass, sel, imp, node->ruby_imp,
-		node->arity, node->flags, types);
-    }
-    else {
-	class_replaceMethod(klass, sel, imp, types);
-    }
-}
-
-static void
-vm_alias(VALUE outer, ID name, ID def)
-{
-    rb_frozen_class_p(outer);
-    if (outer == rb_cObject) {
-        rb_secure(4);
-    }
-
-    VALUE dest = outer;
-    Class klass = (Class)outer;
-    Class dest_klass = (Class)dest;
-
-    const char *def_str = rb_id2name(def);
-    SEL sel = sel_registerName(def_str);
-    Method def_method1 = class_getInstanceMethod(klass, sel);
-    Method def_method2 = NULL;
-    if (def_str[strlen(def_str) - 1] != ':') {
-	char tmp[100];
-	snprintf(tmp, sizeof tmp, "%s:", def_str);
-	sel = sel_registerName(tmp);
- 	def_method2 = class_getInstanceMethod(klass, sel);
-    }
-
-    if (def_method1 == NULL && def_method2 == NULL) {
-	rb_print_undef((VALUE)klass, def, 0);
-    }
-    if (def_method1 != NULL) {
-	vm_alias_method(dest_klass, def_method1, name, true);
-    }
-    if (def_method2 != NULL) {
-	vm_alias_method(dest_klass, def_method2, name, false);
-    }
-}
-
-extern "C"
-void
-rb_vm_alias2(VALUE outer, VALUE name, VALUE def, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-
-    // Given arguments should always be symbols (compiled as such).
-    assert(TYPE(name) == T_SYMBOL);
-    assert(TYPE(def) == T_SYMBOL);
-
-    vm_alias(outer, SYM2ID(name), SYM2ID(def));
-}
-
-extern "C"
-void
-rb_vm_alias(VALUE outer, ID name, ID def)
-{
-    vm_alias(outer, name, def);
-}
-
-extern "C"
-void
-rb_vm_undef(VALUE klass, ID name, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    klass = (VALUE)k;
-	}
-    }
-    rb_vm_undef_method((Class)klass, name, true);
-}
-
-extern "C"
-void
-rb_vm_undef2(VALUE klass, VALUE sym, unsigned char dynamic_class)
-{
-    assert(TYPE(sym) == T_SYMBOL);
-    return rb_vm_undef(klass, SYM2ID(sym), dynamic_class);
-}
-
-extern "C"
-VALUE
-rb_vm_defined(VALUE self, int type, VALUE what, VALUE what2)
-{
-    const char *str = NULL;
-
-    switch (type) {
-	case DEFINED_IVAR:
-	    if (rb_ivar_defined(self, (ID)what)) {
-		str = "instance-variable";
-	    }
-	    break;
-
-	case DEFINED_GVAR:
-	    if (rb_gvar_defined((struct global_entry *)what)) {
-		str = "global-variable";
-	    }
-	    break;
-
-	case DEFINED_CVAR:
-	    if (rb_cvar_defined(CLASS_OF(self), (ID)what)) {
-		str = "class variable";
-	    }
-	    break;
-
-	case DEFINED_CONST:
-	case DEFINED_LCONST:
-	    {
-		if (rb_vm_const_lookup(what2, (ID)what,
-			    type == DEFINED_LCONST, true)) {
-		    str = "constant";
-		}
-	    }
-	    break;
-
-	case DEFINED_SUPER:
-	case DEFINED_METHOD:
-	    {
-		VALUE klass = CLASS_OF(self);
-		if (type == DEFINED_SUPER) {
-		    klass = RCLASS_SUPER(klass);
-		}
-		if (what == 0) {
-		    rb_raise(rb_eRuntimeError,
-			    "defined?(super) out of a method block isn't supported");
-		}
-		const char *idname = rb_id2name((ID)what);
-		SEL sel = sel_registerName(idname);
-
-		bool ok = class_getInstanceMethod((Class)klass, sel) != NULL;
-		if (!ok && idname[strlen(idname) - 1] != ':') {
-		    char buf[100];
-		    snprintf(buf, sizeof buf, "%s:", idname);
-		    sel = sel_registerName(buf);
-		    ok = class_getInstanceMethod((Class)klass, sel) != NULL;
-		}
-
-		if (ok) {
-		    str = type == DEFINED_SUPER ? "super" : "method";
-		}
-	    }
-	    break;
-
-	default:
-	    printf("unknown defined? type %d", type);
-	    abort();
-    }
-
-    return str == NULL ? Qnil : rb_str_new2(str);
-}
-
-static bool
-kvo_sel(Class klass, const char *selname, const size_t selsize,
-	const char *begin, const char *end)
-{
-    // ^#{begin}(.+)#{end}$ -> token
-    const size_t begin_len = strlen(begin);
-    const size_t end_len = strlen(end);
-    unsigned int token_beg = 0, token_end = selsize;
-    if (begin_len > 0) {
-	if (strncmp(selname, begin, begin_len) != 0 || selsize <= begin_len) {
-	    return false;
-	}
-	token_beg = begin_len;
-    }
-    if (end_len > 0) {
-	const char *p = strstr(selname, end);
-	if (p == NULL || p + end_len != selname + selsize) {
-	    return false;
-	}
-	token_end = p - selname;
-    }
-    const size_t token_len = token_end - token_beg;
-    char token[100];
-    if (token_len > sizeof(token)) {
-	return false;
-    }
-    memcpy(token, &selname[token_beg], token_len);
-    token[token_len] = '\0';
-
-    if (strchr(token, ':') != NULL) {
-	return false;
-    }
-
-#if 1
-    // token must start with a capital character.
-    return isupper(token[0]);
-#else
-    // token must start with a capital character.
-    if (!isupper(token[0])) {
-	return false;
-    }
-
-    // Decapitalize the token and look if it's a valid KVO attribute.
-    token[0] = tolower(token[0]);
-    SEL sel = sel_registerName(token);
-    return class_getInstanceMethod(klass, sel) != NULL;
-#endif
-}
-
-static const char *
-get_bs_method_type(bs_element_method_t *bs_method, int idx)
-{
-    const char *type = rb_get_bs_method_type(bs_method, idx);
-    if (type == NULL) {
-	type = "@";
-    }
-    return type;
-}
-
-static void 
-resolve_method_type(char *buf, const size_t buflen, Class klass, Method m,
-	SEL sel, const unsigned int types_count)
-{
-    bs_element_method_t *bs_method = GET_CORE()->find_bs_method(klass, sel);
-
-    if (m == NULL
-	|| !rb_objc_get_types(Qnil, klass, sel, m, bs_method, buf, buflen)) {
-
-	std::string *informal_type =
-	    GET_CORE()->find_bs_informal_protocol_method(sel,
-		    class_isMetaClass(klass));
-	if (informal_type != NULL) {
-	    // Get the signature from the BridgeSupport database as an
-	    // informal protocol method.
-	    const char *informal_type_str = informal_type->c_str();
-	    strncpy(buf, informal_type_str, buflen);
-	    for (unsigned int i = TypeArity(informal_type_str);
-		    i < types_count; i++) {
-		strlcat(buf, "@", buflen);
-	    }
-	}
-	else {
-	    // Generate an automatic signature. We do check for KVO selectors
-	    // which require a customized signature, otherwise we do generate
-	    // one that assumes that the return value and all arguments are
-	    // objects ('@').
-	    const char *selname = sel_getName(sel);
-	    const size_t selsize = strlen(selname);
-
-	    if (kvo_sel(klass, selname, selsize, "countOf", "")) {
-		strncpy(buf, "i@:", buflen);
-	    }
-	    else if (kvo_sel(klass, selname, selsize, "objectIn", "AtIndex:")) {
-		strncpy(buf, "@@:i", buflen);
-	    }
-	    else if (kvo_sel(klass, selname, selsize, "insertObject:in",
-			"AtIndex:")) {
-		strncpy(buf, "v@:@i", buflen);
-	    }
-	    else if (kvo_sel(klass, selname, selsize, "removeObjectFrom",
-			"AtIndex:")) {
-		strncpy(buf, "v@:i", buflen);
-	    }
-	    else if (kvo_sel(klass, selname, selsize, "replaceObjectIn",
-			"AtIndex:withObject:")) {
-		strncpy(buf, "v@:i@", buflen);
-	    }
-#if 0 // TODO
-	    else if (kvo_sel(klass, selname, selsize, "get", ":range:")) {
-	    }
-#endif
-	    else if (bs_method != NULL) {
-		buf[0] = '\0';
-
-		// retval, self and sel.
-		strlcat(buf, get_bs_method_type(bs_method, -1), buflen);
-		strlcat(buf, "@", buflen);
-		strlcat(buf, ":", buflen);
-
-		// Arguments.
-		for (unsigned int i = 3; i < types_count; i++) {
-		    strlcat(buf, get_bs_method_type(bs_method, i - 3), buflen);
-		}
-	    }
-	    else {
-		assert(types_count < buflen);
-
-		// retval, self and sel.
-		buf[0] = strncmp(selname, "set", 3) == 0 ? 'v' : '@';
-		buf[1] = '@';
-		buf[2] = ':';
-
-		// Arguments.
-		for (unsigned int i = 3; i < types_count; i++) {
-		    buf[i] = '@';
-		}
-		buf[types_count] = '\0';
-	    }
-	}
-    }
-    else {
-	assert(strlen(buf) >= 3);
-	for (unsigned int i = rb_method_getNumberOfArguments(m) + 1;
-		i < types_count; i++) {
-	    strlcat(buf, "@", buflen);
-	}
-    }
-}
-
-rb_vm_method_node_t *
-RoxorCore::retype_method(Class klass, rb_vm_method_node_t *node,
-	const char *old_types, const char *new_types)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "methods cannot be retyped in MacRuby static");
-#else
-    if (strcmp(old_types, new_types) == 0) {
-	// No need to retype.
-	// XXX might be better to compare every type after filtering stack
-	// size and other crappy modifiers.
-	return node;
-    }
-
-    const int new_types_arity = TypeArity(new_types);
-    char buf[100];
-    if (node->arity.real + 3 >= new_types_arity) {
-	// The method arity is bigger than the number of types of the new
-	// signature, so we need to pad.
-	strlcpy(buf, new_types, sizeof buf);
-	for (int i = 0; i < node->arity.real + 3 - new_types_arity; i++) {
-	    strlcat(buf, "@", sizeof buf);
-	}
-	new_types = &buf[0];
-    }
-
-    RoxorCoreLock lock;
-
-    // Re-generate ObjC stub. 
-    Function *objc_func = RoxorCompiler::shared->compile_objc_stub(NULL,
-	    node->ruby_imp, node->arity, new_types);
-    node->objc_imp = compile(objc_func, false);
-    // TODO: free LLVM machine code from old objc IMP
-    objc_to_ruby_stubs[node->ruby_imp] = node->objc_imp;
-
-    // Re-add the method.
-    return add_method(klass, node->sel, node->objc_imp, node->ruby_imp,
-	    node->arity, node->flags, new_types);
-#endif
-}
-
-struct vm_objc_imp_type {
-    const char *types;
-    IMP imp;
-
-    vm_objc_imp_type(const char *_types, IMP _imp) {
-	types = _types;
-	imp = _imp;
-    }
-};
-
-rb_vm_method_node_t *
-RoxorCore::resolve_method(Class klass, SEL sel, void *func,
-	const rb_vm_arity_t &arity, int flags, IMP imp, Method m,
-	void *objc_imp_types)
-{
-#if MACRUBY_STATIC
-    assert(imp != NULL);
-#else
-    if (imp == NULL) {
-	// Compile if necessary.
-	assert(func != NULL);
-	imp = compile((Function *)func);
-    }
-#endif
-
-    // Resolve Objective-C signature.
-    const int types_count = arity.real + 3; // retval, self and sel
-    char types[100];
-    resolve_method_type(types, sizeof types, klass, m, sel, types_count);
-
-    // Retrieve previous-generated Objective-C stub if possible.
-    IMP objc_imp = NULL;
-    if (objc_imp_types != NULL) {
-	std::vector<vm_objc_imp_type> *v =
-	    (std::vector<vm_objc_imp_type> *)objc_imp_types;
-
-	for (std::vector<vm_objc_imp_type>::iterator i = v->begin();
-		i != v->end(); ++i) {
-	    if (strcmp(types, i->types) == 0) {
-		objc_imp = i->imp;
-		break;
-	    }
-	}
-    }
-
-#if MACRUBY_STATIC
-    if (objc_imp == NULL) {
-	printf("can't define method `%s' because no Objective-C stub was pre-compiled for types `%s'\n", sel_getName(sel), types);
-	abort();
-    }
-#else
-    // Generate Objective-C stub if needed.
-    if (objc_imp == NULL) {
-	std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
-	if (iter == objc_to_ruby_stubs.end()) {
-	    Function *objc_func = RoxorCompiler::shared->compile_objc_stub(
-		    (Function *)func, imp, arity, types);
-	    objc_imp = compile(objc_func);
-	    objc_to_ruby_stubs[imp] = objc_imp;
-	}
-	else {
-	    objc_imp = iter->second;
-	}
-    }
-
-    // Delete the selector from the not-yet-JIT'ed cache if needed.
-    std::multimap<Class, SEL>::iterator iter2, last2;
-    iter2 = method_source_sels.find(klass);
-    if (iter2 != method_source_sels.end()) {
-	last2 = method_source_sels.upper_bound(klass);
-	while (iter2 != last2) {
-	    if (iter2->second == sel) {
-		method_source_sels.erase(iter2);
-		break;
-	    }
-	    ++iter2;
-	}
-    }
-#endif
-
-    // Finally, add the method.
-    return add_method(klass, sel, objc_imp, imp, arity, flags, types);
-}
-
-#if !defined(MACRUBY_STATIC)
-bool
-RoxorCore::resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
-	Class klass, SEL sel)
-{
-    bool did_something = false;
-    std::map<Class, rb_vm_method_source_t *>::iterator iter = map->begin();
-    while (iter != map->end()) {
-	Class k = iter->first;
-	while (k != klass && k != NULL) {
-	    k = class_getSuperclass(k);
-	}
-
-	if (k != NULL) {
-	    rb_vm_method_source_t *m = iter->second;
-	    resolve_method(iter->first, sel, m->func, m->arity, m->flags,
-		    NULL, NULL, NULL);
-	    map->erase(iter++);
-	    free(m);
-	    did_something = true;
-	}
-	else {
-	    ++iter;
-	}
-    }
-
-    // If the map is empty, there is no point in keeping it.
-    if (map->size() == 0) {
-	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator
-	    iter = method_sources.find(sel);
-	assert(iter != method_sources.end());
-	method_sources.erase(iter);
-	delete map;	
-    }
-
-    return did_something;
-}
-
-extern "C"
-bool
-rb_vm_resolve_method(Class klass, SEL sel)
-{
-    if (!GET_CORE()->get_running()) {
-	return false;
-    }
-
-    // Make sure the VM is created & registered to avoid a deadlock.
-    GET_VM();
-
-    RoxorCoreLock lock;
-
-    bool status = false;
-
-#if ROXOR_VM_DEBUG
-    printf("resolving %c[%s %s]\n",
-	class_isMetaClass(klass) ? '+' : '-',
-	class_getName(klass),
-	sel_getName(sel));
-#endif
-
-    std::map<Class, rb_vm_method_source_t *> *map =
-	GET_CORE()->method_sources_for_sel(sel, false);
-    if (map == NULL) {
-	goto bails;
-    }
-
-    // Find the class where the method should be defined.
-    while (map->find(klass) == map->end() && klass != NULL) {
-	klass = class_getSuperclass(klass);
-    }
-    if (klass == NULL) {
-	goto bails;
-    }
-
-    // Now let's resolve all methods of the given name on the given class
-    // and superclasses.
-    status = GET_CORE()->resolve_methods(map, klass, sel);
-
-bails:
-    return status;
-}
-
-void
-RoxorCore::prepare_method(Class klass, SEL sel, Function *func,
-	const rb_vm_arity_t &arity, int flags)
-{
-#if ROXOR_VM_DEBUG
-    printf("preparing %c[%s %s] on class %p LLVM func %p flags %d\n",
-	    class_isMetaClass(klass) ? '+' : '-',
-	    class_getName(klass),
-	    sel_getName(sel),
-	    klass,
-	    func,
-	    flags);
-#endif
-
-    std::map<Class, rb_vm_method_source_t *> *map =
-	method_sources_for_sel(sel, true);
-
-    std::map<Class, rb_vm_method_source_t *>::iterator iter = map->find(klass);
-
-    rb_vm_method_source_t *m = NULL;
-    if (iter == map->end()) {
-	m = (rb_vm_method_source_t *)malloc(sizeof(rb_vm_method_source_t));
-	map->insert(std::make_pair(klass, m));
-	method_source_sels.insert(std::make_pair(klass, sel));
-    }
-    else {
-	m = iter->second;
-    }
-
-    m->func = func;
-    m->arity = arity;
-    m->flags = flags;
-
-    invalidate_respond_to_cache();
-}
-#endif
-
-#if !defined(MACRUBY_STATIC)
-static bool class_has_custom_resolver(Class klass);
-#endif
-
-static void
-prepare_method(Class klass, bool dynamic_class, SEL sel, void *data,
-	const rb_vm_arity_t &arity, int flags, bool precompiled,
-	void *objc_imp_types)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    const bool meta = class_isMetaClass(klass);
-	    klass = k;
-	    if (meta && !class_isMetaClass(klass)) {
-		klass = *(Class *)klass;
-	    }
-	}
-    }
-
-    const long v = RCLASS_VERSION(klass);
-    if (v & RCLASS_SCOPE_PRIVATE) {
-	flags |= VM_METHOD_PRIVATE;
-    }
-    else if (v & RCLASS_SCOPE_PROTECTED) {
-	flags |= VM_METHOD_PROTECTED;
-    }
-
-    if (rb_objc_ignored_sel(sel)) {
-	return;
-    }
-
-    const char *sel_name = sel_getName(sel);
-    const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
-#if !defined(MACRUBY_STATIC)
-    const bool custom_resolver = class_has_custom_resolver(klass);
-#endif
-    bool redefined = false;
-    bool added_modfunc = false;
-    SEL orig_sel = sel;
-    Method m;
-    IMP imp = NULL;
-
-prepare_method:
-
-    m = class_getInstanceMethod(klass, sel);
-#if !defined(MACRUBY_STATIC)
-    if (m == NULL && rb_vm_resolve_method(klass, sel)) {
-	m = class_getInstanceMethod(klass, sel);
-	assert(m != NULL);
-    }
-#endif
-
-    if (precompiled) {
-	if (imp == NULL) {
-	    imp = (IMP)data;
-	}
-	assert(objc_imp_types != NULL);
-	GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m,
-		objc_imp_types);
-    }
-    else {
-#if MACRUBY_STATIC
-	abort();
-#else
-	Function *func = (Function *)data;
-	if (m != NULL || custom_resolver) {
-	    // The method already exists _or_ the class implemented a custom
-	    // Objective-C method resolver - we need to JIT it.
-	    if (imp == NULL) {
-		imp = GET_CORE()->compile(func);
-	    }
-	    GET_CORE()->resolve_method(klass, sel, func, arity, flags, imp, m,
-		    objc_imp_types);
-	}
-	else {
-	    // Let's keep the method and JIT it later on demand.
-	    GET_CORE()->prepare_method(klass, sel, func, arity, flags);
-	}
-#endif
-    }
-
-    if (!redefined) {
-	char buf[100];
-	SEL new_sel = 0;
-	if (!genuine_selector) {
-	    snprintf(buf, sizeof buf, "%s:", sel_name);
-	    new_sel = sel_registerName(buf);
-	    if (arity.max != arity.min) {
-		sel = new_sel;
-		redefined = true;
-		goto prepare_method;
-	    }
-	}
-	else {
-	    strlcpy(buf, sel_name, sizeof buf);
-	    buf[strlen(buf) - 1] = 0; // remove the ending ':'
-	    new_sel = sel_registerName(buf);
-	    if (arity.min == 0) {
-		sel = new_sel;
-		redefined = true;
-		goto prepare_method;
-	    }
-	}
-	Method tmp_m = class_getInstanceMethod(klass, new_sel);
-	if (tmp_m != NULL) {
-	    // If we add -[foo:] and the class responds to -[foo], we need
-	    // to disable it (and vice-versa).
-	    class_replaceMethod(klass, new_sel,
-		    (IMP)rb_vm_undefined_imp, method_getTypeEncoding(tmp_m));
-	    // Invalidate the cache so that the previously defined
-	    // implementation is not called anymore if the call was cached
-	    GET_CORE()->invalidate_method_cache(new_sel);
-	}
-    }
-
-    if (RCLASS_VERSION(klass) & RCLASS_IS_INCLUDED) {
-	VALUE included_in_classes = rb_attr_get((VALUE)klass, 
-		idIncludedInClasses);
-	if (included_in_classes != Qnil) {
-	    int i, count = RARRAY_LEN(included_in_classes);
-	    for (i = 0; i < count; i++) {
-		VALUE mod = RARRAY_AT(included_in_classes, i);
-		rb_vm_set_current_scope(mod, SCOPE_PUBLIC);
-		prepare_method((Class)mod, false, orig_sel, data, arity,
-			flags, precompiled, objc_imp_types);
-		rb_vm_set_current_scope(mod, SCOPE_DEFAULT);
-	    }
-	}
-    }
-
-    GET_CORE()->method_added(klass, sel);
-
-    if (!added_modfunc && (v & RCLASS_SCOPE_MOD_FUNC)) {
-	added_modfunc = true;
-	redefined = false;
-	klass = *(Class *)klass;
-	sel = orig_sel;
-	goto prepare_method;
-    }
-}
-
-#if !defined(MACRUBY_STATIC)
-extern "C"
-void
-rb_vm_prepare_method(Class klass, unsigned char dynamic_class, SEL sel,
-	Function *func, const rb_vm_arity_t arity, int flags)
-{
-    prepare_method(klass, dynamic_class, sel, (void *)func, arity,
-	    flags, false, NULL);
-}
-#endif
-
-extern "C"
-void
-rb_vm_prepare_method2(Class klass, unsigned char dynamic_class, SEL sel,
-	IMP ruby_imp, const rb_vm_arity_t arity, int flags, ...)
-{
-    std::vector<vm_objc_imp_type> v;
-    va_list ar;
-    va_start(ar, flags);
-    do {
-	const char *types = va_arg(ar, const char *);
-	if (types == NULL) {
-	    break;
-	}
-	IMP imp = va_arg(ar, IMP);
-	assert(imp != NULL);
-	v.push_back(vm_objc_imp_type(types, imp));
-    }
-    while (true);
-    va_end(ar);
-
-    prepare_method(klass, dynamic_class, sel, (void *)ruby_imp, arity,
-	    flags, true, (void *)&v);
-}
-
-#define VISI(x) ((x)&NOEX_MASK)
-#define VISI_CHECK(x,f) (VISI(x) == (f))
-
-static void
-push_method(VALUE ary, SEL sel, int flags, int (*filter) (VALUE, ID, VALUE))
-{
-    if (rb_objc_ignored_sel(sel)) {
-	return; 
-    }
-
-    const char *selname = sel_getName(sel);
-    const size_t len = strlen(selname);
-    assert(len > 0);
-    char *buf = NULL;
-
-    const char *p = strchr(selname, ':');
-    if (p != NULL && strchr(p + 1, ':') == NULL) {
-	// remove trailing ':' for methods with arity 1
-	buf = (char *)malloc(len);
-	assert(buf != NULL);
-	strncpy(buf, selname, len);
-	buf[len - 1] = '\0';
-	selname = buf;
-    }
- 
-    ID mid = rb_intern(selname);
-    VALUE sym = ID2SYM(mid);
-
-    if (buf != NULL) {
-	free(buf);
-	buf = NULL;
-    }
-
-    if (rb_ary_includes(ary, sym) == Qfalse) {
-	int type = NOEX_PUBLIC;
-	if (flags & VM_METHOD_PRIVATE) {
-	    type = NOEX_PRIVATE;
-	}
-	else if (flags & VM_METHOD_PROTECTED) {
-	    type = NOEX_PROTECTED;
-	}
-	(*filter)(sym, type, ary);
-    }
-} 
-
-#if !defined(MACRUBY_STATIC)
-rb_vm_method_source_t *
-RoxorCore::method_source_get(Class klass, SEL sel)
-{
-    std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator iter
-	= method_sources.find(sel);
-    if (iter != method_sources.end()) {
-	std::map<Class, rb_vm_method_source_t *> *m = iter->second;
-	std::map<Class, rb_vm_method_source_t *>::iterator iter2
-	    = m->find(klass);
-	if (iter2 != m->end()) {
-	    return iter2->second;
-	}
-    }
-    return NULL;
-}
-#endif
-
-void
-RoxorCore::get_methods(VALUE ary, Class klass, bool include_objc_methods,
-	int (*filter) (VALUE, ID, VALUE))
-{
-    // TODO take into account undefined methods
-
-    unsigned int count;
-    Method *methods = class_copyMethodList(klass, &count); 
-    if (methods != NULL) {
-	for (unsigned int i = 0; i < count; i++) {
-	    Method m = methods[i];
-	    if (UNAVAILABLE_IMP(method_getImplementation(m))) {
-		continue;
-	    }
-	    rb_vm_method_node_t *node = method_node_get(m);
-	    if (node == NULL && !include_objc_methods) {
-		continue;
-	    }
-	    SEL sel = method_getName(m);
-	    push_method(ary, sel, node == NULL ? 0 : node->flags, filter);
-	}
-	free(methods);
-    }
-
-#if !defined(MACRUBY_STATIC)
-    Class k = klass;
-    std::multimap<Class, SEL>::iterator iter =
-	method_source_sels.find(k);
-
-    if (iter != method_source_sels.end()) {
-	std::multimap<Class, SEL>::iterator last =
-	    method_source_sels.upper_bound(k);
-
-	for (; iter != last; ++iter) {
-	    SEL sel = iter->second;
-	    rb_vm_method_source_t *src = method_source_get(k, sel);
-	    assert(src != NULL);
-	    push_method(ary, sel, src->flags, filter);
-	}
-    }
-#endif
-}
-
-extern "C"
-void
-rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
-		   int (*filter) (VALUE, ID, VALUE))
-{
-    GET_CORE()->get_methods(ary, (Class)mod, include_objc_methods, filter);
-}
-
-extern "C"
-void
-rb_vm_copy_methods(Class from_class, Class to_class)
-{
-    GET_CORE()->copy_methods(from_class, to_class);
-}
-
-extern "C"
-bool
-rb_vm_copy_method(Class klass, Method m)
-{
-    return GET_CORE()->copy_method(klass, m);
-}
-
-bool
-RoxorCore::copy_method(Class klass, Method m)
-{
-    rb_vm_method_node_t *node = method_node_get(m);
-    if (node == NULL) {
-	// Only copy pure-Ruby methods.
-	return false;
-    }
-    SEL sel = method_getName(m);
-
-#if ROXOR_VM_DEBUG
-    printf("copy %c[%s %s] from method %p imp %p\n",
-	    class_isMetaClass(klass) ? '+' : '-',
-	    class_getName(klass),
-	    sel_getName(sel),
-	    m,
-	    method_getImplementation(m));
-#endif
-
-    class_replaceMethod(klass, sel, method_getImplementation(m),
-	    method_getTypeEncoding(m));
-
-    Method m2 = class_getInstanceMethod(klass, sel);
-    assert(m2 != NULL);
-    assert(method_getImplementation(m2) == method_getImplementation(m));
-    rb_vm_method_node_t *node2 = method_node_get(m2, true);
-    memcpy(node2, node, sizeof(rb_vm_method_node_t));
-
-    return true;
-}
-
-void
-RoxorCore::copy_methods(Class from_class, Class to_class)
-{
-    Method *methods;
-    unsigned int i, methods_count;
-
-    // Copy existing Objective-C methods.
-    methods = class_copyMethodList(from_class, &methods_count);
-    if (methods != NULL) {
-	for (i = 0; i < methods_count; i++) {
-	    Method m = methods[i];
-	    if (!copy_method(to_class, m)) {
-		continue;
-	    }
-
-#if !defined(MACRUBY_STATIC)
-	    SEL sel = method_getName(m);
-	    std::map<Class, rb_vm_method_source_t *> *map =
-		method_sources_for_sel(sel, false);
-	    if (map != NULL) {
-		// There might be some non-JIT'ed yet methods on subclasses.
-		resolve_methods(map, to_class, sel);
-	    }
-#endif
-	}
-	free(methods);
-    }
-
-#if !defined(MACRUBY_STATIC)
-    // Copy methods that have not been JIT'ed yet.
-
-    // First, make a list of selectors.
-    std::vector<SEL> sels_to_copy;
-    std::multimap<Class, SEL>::iterator iter =
-	method_source_sels.find(from_class);
-
-    if (iter != method_source_sels.end()) {
-	std::multimap<Class, SEL>::iterator last =
-	    method_source_sels.upper_bound(from_class);
-
-	for (; iter != last; ++iter) {
-	    sels_to_copy.push_back(iter->second);
-	}
-    }
-
-    // Force a resolving of these selectors on the target class. This must be
-    // done outside the next loop since the resolver messes up the Core
-    // structures.
-    for (std::vector<SEL>::iterator iter = sels_to_copy.begin();
-	    iter != sels_to_copy.end();
-	    ++iter) {
-	class_getInstanceMethod(to_class, *iter);
-    }
-
-    // Now, let's really copy the lazy methods.
-    std::vector<SEL> sels_to_add;
-    for (std::vector<SEL>::iterator iter = sels_to_copy.begin();
-	    iter != sels_to_copy.end();
-	    ++iter) {
-	SEL sel = *iter;
-
-	std::map<Class, rb_vm_method_source_t *> *dict =
-	    method_sources_for_sel(sel, false);
-	if (dict == NULL) {
-	    continue;
-	}
-
-	std::map<Class, rb_vm_method_source_t *>::iterator
-	    iter2 = dict->find(from_class);
-	if (iter2 == dict->end()) {
-	    continue;
-	}
-
-	rb_vm_method_source_t *m_src = iter2->second;
-
-	Method m = class_getInstanceMethod(to_class, sel);
-	if (m != NULL) {
-	    // The method already exists on the target class, we need to
-	    // JIT it.
-	    IMP imp = GET_CORE()->compile(m_src->func);
-	    resolve_method(to_class, sel, m_src->func, m_src->arity,
-		    m_src->flags, imp, m, NULL);
-	}
-	else {
-#if ROXOR_VM_DEBUG
-	    printf("lazy copy %c[%s %s] to %c%s\n",
-		    class_isMetaClass(from_class) ? '+' : '-',
-		    class_getName(from_class),
-		    sel_getName(sel),
-		    class_isMetaClass(to_class) ? '+' : '-',
-		    class_getName(to_class));
-#endif
-
-	    rb_vm_method_source_t *m = (rb_vm_method_source_t *)
-		malloc(sizeof(rb_vm_method_source_t));
-	    m->func = m_src->func;
-	    m->arity = m_src->arity;
-	    m->flags = m_src->flags;
-	    dict->insert(std::make_pair(to_class, m));
-	    sels_to_add.push_back(sel);
-	}
-    }
-
-    for (std::vector<SEL>::iterator i = sels_to_add.begin();
-	    i != sels_to_add.end();
-	    ++i) {
-	method_source_sels.insert(std::make_pair(to_class, *i));
-    }
-#endif
-}
-
-extern "C"
-bool
-rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
-		     rb_vm_method_node_t **pnode)
-{
-    const char *idstr = rb_id2name(mid);
-    SEL sel = sel_registerName(idstr);
-
-    if (!rb_vm_lookup_method(klass, sel, pimp, pnode)) {
-	char buf[100];
-	snprintf(buf, sizeof buf, "%s:", idstr);
-	sel = sel_registerName(buf);
-	if (!rb_vm_lookup_method(klass, sel, pimp, pnode)) {
-	    return false;
-	}
-    }
-
-    if (psel != NULL) {
-	*psel = sel;
-    }
-    return true;
-}
-
-extern "C"
-bool
-rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
-		    rb_vm_method_node_t **pnode)
-{
-    Method m = class_getInstanceMethod(klass, sel);
-    if (m == NULL) {
-	return false;
-    }
-    IMP imp = method_getImplementation(m);
-    if (UNAVAILABLE_IMP(imp)) {
-	return false;
-    }
-    if (pimp != NULL) {
-	*pimp = imp;
-    }
-    if (pnode != NULL) {
-	*pnode = GET_CORE()->method_node_get(m);
-    }
-    return true;
-}
-
-extern "C"
-void
-rb_vm_define_attr(Class klass, const char *name, bool read, bool write)
-{
-    assert(klass != NULL);
-    assert(read || write);
-
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "attr_* is not supported in MacRuby static");
-#else
-    char buf[100];
-    snprintf(buf, sizeof buf, "@%s", name);
-    ID iname = rb_intern(buf);
-
-    if (read) {
-	Function *f = RoxorCompiler::shared->compile_read_attr(iname);
-	SEL sel = sel_registerName(name);
-	rb_vm_prepare_method(klass, false, sel, f, rb_vm_arity(0),
-		VM_METHOD_FBODY);
-    }
-
-    if (write) {
-	Function *f = RoxorCompiler::shared->compile_write_attr(iname);
-	snprintf(buf, sizeof buf, "%s=:", name);
-	SEL sel = sel_registerName(buf);
-	rb_vm_prepare_method(klass, false, sel, f, rb_vm_arity(1),
-		VM_METHOD_FBODY);
-    }
-#endif
-}
-
-static rb_vm_method_node_t *
-__rb_vm_define_method(Class klass, SEL sel, IMP objc_imp, IMP ruby_imp,
-	const rb_vm_arity_t &arity, int flags, bool direct)
-{
-    assert(klass != NULL);
-
-    if (rb_objc_ignored_sel(sel)) {
-	return NULL;
-    }
-
-    const char *sel_name = sel_getName(sel);
-    const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
-    int types_count = genuine_selector ? arity.real + 3 : 3;
-    bool redefined = direct;
-    rb_vm_method_node_t *node;
-
-define_method:
-    Method method = class_getInstanceMethod(klass, sel);
-
-    char types[100];
-    resolve_method_type(types, sizeof types, klass, method, sel, types_count);
-
-    node = GET_CORE()->add_method(klass, sel, objc_imp, ruby_imp, arity,
-	    flags, types);
-
-    if (!redefined) {
-	if (!genuine_selector && arity.max != arity.min) {
-	    char buf[100];
-	    snprintf(buf, sizeof buf, "%s:", sel_name);
-	    sel = sel_registerName(buf);
-	    types_count = arity.real + 3;
-	    redefined = true;
-
-	    goto define_method;
-	}
-	else if (genuine_selector && arity.min == 0) {
-	    char buf[100];
-	    strlcpy(buf, sel_name, sizeof buf);
-	    buf[strlen(buf) - 1] = 0; // remove the ending ':'
-	    sel = sel_registerName(buf);
-	    types_count = 3;
-	    redefined = true;
-
-	    goto define_method;
-	}
-    }
-
-    return node;
-}
-
-extern "C"
-rb_vm_method_node_t * 
-rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct)
-{
-    assert(node != NULL);
-
-    // TODO: create objc_imp
-    return __rb_vm_define_method(klass, sel, imp, imp, rb_vm_node_arity(node),
-	    rb_vm_node_flags(node), direct);
-}
-
-extern "C"
-rb_vm_method_node_t * 
-rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
-	long flags, bool direct)
-{
-    assert(node != NULL);
-
-    if (flags == -1) {
-	flags = node->flags;
-	flags &= ~VM_METHOD_PRIVATE;
-	flags &= ~VM_METHOD_PROTECTED;
-    }
-
-    return __rb_vm_define_method(klass, sel, node->objc_imp, node->ruby_imp,
-	    node->arity, flags, direct);
-}
-
-#if !defined(MACRUBY_STATIC)
-extern "C"
-void
-rb_vm_define_method3(Class klass, ID mid, rb_vm_block_t *block)
-{
-    assert(block != NULL);
-
-    const int arity = rb_vm_arity_n(block->arity);
-    SEL sel = rb_vm_id_to_sel(mid, arity);
-
-    Function *func = RoxorCompiler::shared->compile_block_caller(block);
-    IMP imp = GET_CORE()->compile(func);
-    NODE *body = rb_vm_cfunc_node_from_imp(klass, arity < -1 ? -2 : arity, imp, 0);
-    GC_RETAIN(body);
-    GC_RETAIN(block);
-
-    rb_vm_define_method(klass, sel, imp, body, false);
-}
-
-extern "C"
-void *
-rb_vm_generate_mri_stub(void *imp, const int arity)
-{
-    Function *func = RoxorCompiler::shared->compile_mri_stub(imp, arity);
-    if (func == NULL) {
-	// Not needed!
-	return imp;
-    }
-    return (void *)GET_CORE()->compile(func, false); 
-}
-#endif
-
-void
-RoxorCore::undef_method(Class klass, SEL sel)
-{
-#if ROXOR_VM_DEBUG
-    printf("undef %c[%s %s]\n",
-	    class_isMetaClass(klass) ? '+' : '-',
-	    class_getName(klass),
-	    sel_getName(sel));
-#endif
-
-    class_replaceMethod((Class)klass, sel, (IMP)rb_vm_undefined_imp, "@@:");
-    invalidate_respond_to_cache();
-
-#if 0
-    std::map<Method, rb_vm_method_node_t *>::iterator iter
-	= ruby_methods.find(m);
-    assert(iter != ruby_methods.end());
-    free(iter->second);
-    ruby_methods.erase(iter);
-#endif
-
-    if (get_running()) {
-	ID mid = sanitize_mid(sel);
-	if (mid != 0) {
-	    VALUE sym = ID2SYM(mid);
-	    if (RCLASS_SINGLETON(klass)) {
-		VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
-		rb_vm_call(sk, selSingletonMethodUndefined, 1, &sym);
-	    }
-	    else {
-		rb_vm_call((VALUE)klass, selMethodUndefined, 1, &sym);
-	    }
-	}
-    }
-}
-
-extern "C"
-void
-rb_vm_undef_method(Class klass, ID name, bool must_exist)
-{
-    rb_vm_method_node_t *node = NULL;
-
-    if (!rb_vm_lookup_method2((Class)klass, name, NULL, NULL, &node)) {
-	if (must_exist) {
-	    rb_raise(rb_eNameError, "undefined method `%s' for %s `%s'",
-		    rb_id2name(name),
-		    TYPE(klass) == T_MODULE ? "module" : "class",
-		    rb_class2name((VALUE)klass));
-	}
-	const char *namestr = rb_id2name(name);
-	SEL sel = sel_registerName(namestr);
-	GET_CORE()->undef_method(klass, sel);
-    }
-    else if (node == NULL) {
-	if (must_exist) {
-	    rb_raise(rb_eRuntimeError,
-		    "cannot undefine method `%s' because it is a native method",
-		    rb_id2name(name));
-	}
-    }
-    else {
-	GET_CORE()->undef_method(klass, node->sel);
-    }
-}
-
-void
-RoxorCore::remove_method(Class klass, SEL sel)
-{
-#if ROXOR_VM_DEBUG
-    printf("remove %c[%s %s]\n",
-	    class_isMetaClass(klass) ? '+' : '-',
-	    class_getName(klass),
-	    sel_getName(sel));
-#endif
-
-    Method m = class_getInstanceMethod(klass, sel);
-    assert(m != NULL);
-    method_setImplementation(m, (IMP)rb_vm_removed_imp);
-    invalidate_respond_to_cache();
-
-    ID mid = sanitize_mid(sel);
-    if (mid != 0) {
-	VALUE sym = ID2SYM(mid);
-	if (RCLASS_SINGLETON(klass)) {
-	    VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
-	    rb_vm_call(sk, selSingletonMethodRemoved, 1, &sym);
-	}
-	else {
-	    rb_vm_call((VALUE)klass, selMethodRemoved, 1, &sym);
-	}
-    }
-}
-
-extern "C"
-void
-rb_vm_remove_method(Class klass, ID name)
-{
-    rb_vm_method_node_t *node = NULL;
-
-    if (!rb_vm_lookup_method2((Class)klass, name, NULL, NULL, &node)) {
-	rb_raise(rb_eNameError, "undefined method `%s' for %s `%s'",
-		rb_id2name(name),
-		TYPE(klass) == T_MODULE ? "module" : "class",
-		rb_class2name((VALUE)klass));
-    }
-    if (node == NULL) {
-	rb_raise(rb_eRuntimeError,
-		"cannot remove method `%s' because it is a native method",
-		rb_id2name(name));
-    }
-    if (node->klass != klass) {
-	rb_raise(rb_eNameError, "method `%s' not defined in %s",
-		rb_id2name(name), rb_class2name((VALUE)klass));
-    }
-
-    GET_CORE()->remove_method(klass, node->sel);
-}
-
-extern "C"
-VALUE
-rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv)
-{
-    if (argc == 0 || !SYMBOL_P(argv[0])) {
-        rb_raise(rb_eArgError, "no id given");
-    }
-
-    const rb_vm_method_missing_reason_t last_call_status =
-	GET_VM()->get_method_missing_reason();
-    const char *format = NULL;
-    VALUE exc = rb_eNoMethodError;
-
-    switch (last_call_status) {
-	case METHOD_MISSING_PRIVATE:
-	    format = "private method `%s' called for %s";
-	    break;
-
-	case METHOD_MISSING_PROTECTED:
-	    format = "protected method `%s' called for %s";
-	    break;
-
-	case METHOD_MISSING_VCALL:
-	    format = "undefined local variable or method `%s' for %s";
-	    exc = rb_eNameError;
-	    break;
-
-	case METHOD_MISSING_SUPER:
-	    format = "super: no superclass method `%s' for %s";
-	    break;
-
-	case METHOD_MISSING_DEFAULT:
-	default:
-	    format = "undefined method `%s' for %s";
-	    break;
-    }
-
-    VALUE meth = rb_sym_to_s(argv[0]);
-    if (!rb_vm_respond_to(obj, selToS, true)) {
-	// In case #to_s was undefined on the object, let's generate a
-	// basic string based on it, because otherwise the following code
-	// will raise a #method_missing which will result in an infinite loop.
-	obj = rb_any_to_s(obj);
-    }
-
-    int n = 0;
-    VALUE args[3];
-    VALUE not_args[3] = {rb_str_new2(format), obj, meth};
-    args[n++] = rb_vm_call(rb_cNameErrorMesg, selNot2, 3, not_args);
-    args[n++] = meth;
-    if (exc == rb_eNoMethodError) {
-	args[n++] = rb_ary_new4(argc - 1, argv + 1);
-    }
-
-    exc = rb_class_new_instance(n, args, exc);
-    rb_exc_raise(exc);
-
-    abort(); // never reached
-}
-
-void *
-RoxorCore::gen_large_arity_stub(int argc, bool is_block)
-{
-    RoxorCoreLock lock;
-
-    std::map<int, void *> &stubs =
-	is_block ? rb_large_arity_bstubs : rb_large_arity_rstubs;
-    std::map<int, void *>::iterator iter = stubs.find(argc);
-    void *stub;
-    if (iter == stubs.end()) {
-#if MACRUBY_STATIC
-	printf("uncached large arity stub (%d)\n", argc);
-	abort();
-#else
-	Function *f = RoxorCompiler::shared->compile_long_arity_stub(argc,
-		is_block);
-	stub = (void *)compile(f, false);
-	stubs.insert(std::make_pair(argc, stub));
-#endif
-    }
-    else {
-	stub = iter->second;
-    }
-
-    return stub;
-}
-
-void *
-RoxorCore::gen_stub(std::string types, bool variadic, int min_argc,
-	bool is_objc)
-{
-    RoxorCoreLock lock;
-
-#if ROXOR_VM_DEBUG
-    printf("gen Ruby -> %s stub with types %s\n", is_objc ? "ObjC" : "C",
-	    types.c_str());
-#endif
-
-    std::map<std::string, void *> &stubs = is_objc ? objc_stubs : c_stubs;
-    std::map<std::string, void *>::iterator iter = stubs.find(types);
-    void *stub;
-    if (iter == stubs.end()) {
-#if MACRUBY_STATIC
-	printf("uncached %s stub `%s'\n", is_objc ? "ObjC" : "C",
-		types.c_str());
-	abort();
-#else
-	Function *f = RoxorCompiler::shared->compile_stub(types.c_str(),
-		variadic, min_argc, is_objc);
-	stub = (void *)compile(f);
-	stubs.insert(std::make_pair(types, stub));
-#endif
-    }
-    else {
-	stub = iter->second;
-    }
-
-    return stub;
-}
-
-void *
-RoxorCore::gen_to_rval_convertor(std::string type)
-{
-    RoxorCoreLock lock;
-
-    std::map<std::string, void *>::iterator iter =
-	to_rval_convertors.find(type);
-    if (iter != to_rval_convertors.end()) {
-	return iter->second;
-    }
-
-#if MACRUBY_STATIC
-    printf("uncached to_rval convertor %s\n", type.c_str());
-    abort();
-#else
-    Function *f = RoxorCompiler::shared->compile_to_rval_convertor(
-	    type.c_str());
-    void *convertor = (void *)compile(f);
-    to_rval_convertors.insert(std::make_pair(type, convertor));
-    
-    return convertor; 
-#endif
-}
-
-void *
-RoxorCore::gen_to_ocval_convertor(std::string type)
-{
-    std::map<std::string, void *>::iterator iter =
-	to_ocval_convertors.find(type);
-    if (iter != to_ocval_convertors.end()) {
-	return iter->second;
-    }
-
-#if MACRUBY_STATIC
-    printf("uncached to_ocval convertor %s\n", type.c_str());
-    abort();
-#else
-    Function *f = RoxorCompiler::shared->compile_to_ocval_convertor(
-	    type.c_str());
-    void *convertor = (void *)compile(f);
-    to_ocval_convertors.insert(std::make_pair(type, convertor));
-    
-    return convertor; 
-#endif
-}
-
-static const int VM_LVAR_USES_SIZE = 8;
-enum {
-    VM_LVAR_USE_TYPE_BLOCK   = 1,
-    VM_LVAR_USE_TYPE_BINDING = 2
-};
-struct rb_vm_var_uses {
-    int uses_count;
-    void *uses[VM_LVAR_USES_SIZE];
-    unsigned char use_types[VM_LVAR_USES_SIZE];
-    struct rb_vm_var_uses *next;
-};
-
-static void
-rb_vm_add_lvar_use(rb_vm_var_uses **var_uses, void *use,
-	unsigned char use_type)
-{
-    if (var_uses == NULL) {
-	return;
-    }
-
-    if ((*var_uses == NULL)
-	|| ((*var_uses)->uses_count == VM_LVAR_USES_SIZE)) {
-
-	rb_vm_var_uses *new_uses =
-	    (rb_vm_var_uses *)xmalloc(sizeof(rb_vm_var_uses));
-	new_uses->uses_count = 0;
-	GC_WB(&new_uses->next, *var_uses);
-	// var_uses should be on the stack so no need for GC_WB
-	*var_uses = new_uses;
-    }
-
-    const int current_index = (*var_uses)->uses_count;
-    GC_WB(&(*var_uses)->uses[current_index], use);
-    (*var_uses)->use_types[current_index] = use_type;
-    ++(*var_uses)->uses_count;
-}
-
-extern "C"
-void
-rb_vm_add_block_lvar_use(rb_vm_block_t *block)
-{
-    for (rb_vm_block_t *block_for_uses = block;
-	 block_for_uses != NULL;
-	 block_for_uses = block_for_uses->parent_block) {
-
-	rb_vm_add_lvar_use(block_for_uses->parent_var_uses, block,
-		VM_LVAR_USE_TYPE_BLOCK);
-    }
-}
-
-static void
-rb_vm_add_binding_lvar_use(rb_vm_binding_t *binding, rb_vm_block_t *block,
-	rb_vm_var_uses **parent_var_uses)
-{
-    for (rb_vm_block_t *block_for_uses = block;
-	 block_for_uses != NULL;
-	 block_for_uses = block_for_uses->parent_block) {
-
-	rb_vm_add_lvar_use(block_for_uses->parent_var_uses, binding,
-		VM_LVAR_USE_TYPE_BINDING);
-    }
-    rb_vm_add_lvar_use(parent_var_uses, binding, VM_LVAR_USE_TYPE_BINDING);
-}
-
-struct rb_vm_kept_local {
-    ID name;
-    VALUE *stack_address;
-    VALUE *new_address;
-};
-
-extern "C"
-void
-rb_vm_keep_vars(rb_vm_var_uses *uses, int lvars_size, ...)
-{
-    rb_vm_var_uses *current = uses;
-
-    if (current == NULL || current->uses_count == 0) {
-	// there's no use alive so nothing to do
-	return;
-    }
-
-    rb_vm_kept_local *locals = NULL;
-    if (lvars_size > 0) {
-	locals = (rb_vm_kept_local *)xmalloc(sizeof(rb_vm_kept_local)
-		* lvars_size);
-
-	va_list ar;
-	va_start(ar, lvars_size);
-	for (int i = 0; i < lvars_size; ++i) {
-	    locals[i].name = va_arg(ar, ID);
-	    locals[i].stack_address = va_arg(ar, VALUE *);
-	    GC_WB(&locals[i].new_address, (VALUE *)xmalloc(sizeof(VALUE)));
-	    GC_WB(locals[i].new_address, *locals[i].stack_address);
-	}
-	va_end(ar);
-    }
-
-    while (current != NULL) {
-	for (int use_index = 0; use_index < current->uses_count; ++use_index) {
-	    void *use = current->uses[use_index];
-	    unsigned char type = current->use_types[use_index];
-	    rb_vm_local_t *locals_to_replace;
-	    if (type == VM_LVAR_USE_TYPE_BLOCK) {
-		rb_vm_block_t *block = (rb_vm_block_t *)use;
-		for (int dvar_index = 0; dvar_index < block->dvars_size; ++dvar_index) {
-		    for (int lvar_index = 0; lvar_index < lvars_size; ++lvar_index) {
-			if (block->dvars[dvar_index] == locals[lvar_index].stack_address) {
-			    GC_WB(&block->dvars[dvar_index], locals[lvar_index].new_address);
-			    break;
-			}
-		    }
-		}
-
-		// the parent pointers can't be used anymore
-		block->parent_block = NULL;
-		block->parent_var_uses = NULL;
-
-		locals_to_replace = block->locals;
-	    }
-	    else { // VM_LVAR_USE_TYPE_BINDING
-		rb_vm_binding_t *binding = (rb_vm_binding_t *)use;
-		locals_to_replace = binding->locals;
-	    }
-
-	    for (rb_vm_local_t *l = locals_to_replace; l != NULL; l = l->next) {
-		for (int lvar_index = 0; lvar_index < lvars_size; ++lvar_index) {
-		    if (l->value == locals[lvar_index].stack_address) {
-			GC_WB(&l->value, locals[lvar_index].new_address);
-			break;
-		    }
-		}
-	    }
-
-	    // indicate to the GC that we do not have a reference here anymore
-	    GC_WB(&current->uses[use_index], NULL);
-	}
-	current = current->next;
-    }
-}
-
-static inline rb_vm_local_t **
-push_local(rb_vm_local_t **l, ID name, VALUE *value)
-{
-    GC_WB(l, xmalloc(sizeof(rb_vm_local_t)));
-    (*l)->name = name;
-    (*l)->value = value;
-    (*l)->next = NULL;
-    return &(*l)->next;
-}
-
-extern "C"
-rb_vm_binding_t *
-rb_vm_create_binding(VALUE self, rb_vm_block_t *current_block,
-	rb_vm_binding_t *top_binding, int lvars_size, va_list lvars,
-	bool vm_push)
-{
-    rb_vm_binding_t *binding =
-	(rb_vm_binding_t *)xmalloc(sizeof(rb_vm_binding_t));
-    GC_WB(&binding->self, self);
-    GC_WB(&binding->next, top_binding);
-
-    rb_vm_local_t **l = &binding->locals;
-
-    for (rb_vm_block_t *b = current_block; b != NULL; b = b->parent_block) {
-	for (rb_vm_local_t *li = b->locals; li != NULL; li = li->next) {
-	    l = push_local(l, li->name, li->value);
-	}
-    }
-
-    for (int i = 0; i < lvars_size; ++i) {
-	ID name = va_arg(lvars, ID);
-	VALUE *value = va_arg(lvars, VALUE *);
-	l = push_local(l, name, value);
-    }
-
-    RoxorVM *vm = GET_VM();
-    GC_WB(&binding->block, vm->current_block());
-    if (vm_push) {
-	vm->push_current_binding(binding);
-    }
-
-    return binding;
-}
-
-extern "C"
-void
-rb_vm_push_binding(VALUE self, rb_vm_block_t *current_block,
-	rb_vm_binding_t *top_binding, rb_vm_var_uses **parent_var_uses,
-	int lvars_size, ...)
-{
-    va_list lvars;
-    va_start(lvars, lvars_size);
-    rb_vm_binding_t *binding = rb_vm_create_binding(self, current_block,
-	    top_binding, lvars_size, lvars, true);
-    va_end(lvars);
-
-    rb_vm_add_binding_lvar_use(binding, current_block, parent_var_uses);
-}
-
-extern "C"
-rb_vm_binding_t *
-rb_vm_current_binding(void)
-{
-    return GET_VM()->current_binding();
-}
-
-extern "C"
-void
-rb_vm_add_binding(rb_vm_binding_t *binding)
-{
-    GET_VM()->push_current_binding(binding);
-}
-
-extern "C"
-void
-rb_vm_pop_binding(void)
-{
-    GET_VM()->pop_current_binding();
-}
-
-// Should be used inside a method implementation.
-extern "C"
-int
-rb_block_given_p(void)
-{
-    return GET_VM()->current_block() != NULL ? Qtrue : Qfalse;
-}
-
-// Should only be used by Proc.new.
-extern "C"
-rb_vm_block_t *
-rb_vm_first_block(void)
-{
-    return GET_VM()->first_block();
-}
-
-// Should only be used by #block_given?
-extern "C"
-bool
-rb_vm_block_saved(void)
-{
-    return GET_VM()->previous_block() != NULL;
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_current_block(void)
-{
-    return GET_VM()->current_block();
-}
-
-extern "C"
-VALUE
-rb_vm_current_block_object(void)
-{
-    rb_vm_block_t *b = GET_VM()->current_block();
-    if (b != NULL) {
-	return rb_proc_alloc_with_block(rb_cProc, b);
-    }
-    return Qnil;
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_create_block_from_method(rb_vm_method_t *method)
-{
-    rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t));
-
-    b->proc = Qnil;
-    GC_WB(&b->self, method->recv);
-    b->klass = 0;
-    b->arity = method->node == NULL
-	? rb_vm_arity(method->arity) : method->node->arity;
-    b->imp = (IMP)method;
-    b->flags = VM_BLOCK_PROC | VM_BLOCK_METHOD;
-    b->locals = NULL;
-    b->parent_var_uses = NULL;
-    b->parent_block = NULL;
-    b->dvars_size = 0;
-
-    return b;
-}
-
-static VALUE
-rb_vm_block_call_sel(VALUE rcv, SEL sel, VALUE **dvars, rb_vm_block_t *b,
-	VALUE args)
-{
-    const VALUE *argv = RARRAY_PTR(args);
-    const long argc = RARRAY_LEN(args);
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "no receiver given");
-    }
-    SEL msel = argc - 1 == 0 ? (SEL)dvars[0] : (SEL)dvars[1];
-    return rb_vm_call(argv[0], msel, argc - 1, &argv[1]);
-}
-
-extern "C"
-rb_vm_block_t *
-rb_vm_create_block_calling_mid(ID mid)
-{
-    rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
-	    + (2 * sizeof(VALUE *)));
-
-    b->klass = 0;
-    b->proc = Qnil;
-    b->flags = VM_BLOCK_PROC;
-    b->imp = (IMP)rb_vm_block_call_sel;
-
-    // Arity is -1.
-    b->arity.min = 0;
-    b->arity.max = -1;
-    b->arity.left_req = 0;
-    b->arity.real = 1;
-
-    // Prepare 2 selectors for the dispatcher later. One for 0 arity, one for
-    // 1 or more arity.
-    const char *midstr = rb_id2name(mid);
-    if (midstr[strlen(midstr) - 1] == ':') {
-	rb_raise(rb_eArgError, "invalid method name `%s'", midstr);
-    }
-    char buf[100];
-    snprintf(buf, sizeof buf, "%s:", midstr);
-    b->dvars[0] = (VALUE *)sel_registerName(midstr);
-    b->dvars[1] = (VALUE *)sel_registerName(buf);
-
-    return b;
-}
-
-static VALUE
-rb_vm_block_curry(VALUE rcv, SEL sel, VALUE **dvars, rb_vm_block_t *b,
-	VALUE args)
-{
-    VALUE proc = (VALUE)dvars[0];
-    VALUE passed = (VALUE)dvars[1];
-    VALUE arity = (VALUE)dvars[2];
-
-    passed = rb_ary_plus(passed, args);
-    rb_ary_freeze(passed);
-    if (RARRAY_LEN(passed) < FIX2INT(arity)) {
-	return rb_vm_make_curry_proc(proc, passed, arity);
-    }
-    return rb_proc_call(proc, passed);
-}
-
-extern "C"
-VALUE
-rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
-{
-    // Proc.new { |*args| curry... }
-    rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
-	    + (3 * sizeof(VALUE *)));
-
-    b->klass = 0;
-    b->proc = Qnil;
-    b->arity.min = 0;
-    b->arity.max = -1;
-    b->arity.left_req = 0;
-    b->arity.real = 1;
-    b->flags = VM_BLOCK_PROC;
-    b->imp = (IMP)rb_vm_block_curry;
-    GC_WB(&b->dvars[0], (VALUE *)proc);
-    GC_WB(&b->dvars[1], (VALUE *)passed);
-    b->dvars[2] = (VALUE *)arity;
-
-    return rb_proc_alloc_with_block(rb_cProc, b);
-}
-
-static VALUE
-rb_vm_iterate_block(VALUE rcv, SEL sel, VALUE **dvars, rb_vm_block_t *b,
-	VALUE args)
-{
-    VALUE (*bl_proc) (ANYARGS) = (VALUE (*) (ANYARGS))dvars[0];
-    VALUE data2 = (VALUE)dvars[1];
-
-    return (*bl_proc)(args, data2, rcv);
-}
-
-extern "C"
-VALUE
-rb_iterate(VALUE (*it_proc) (VALUE), VALUE data1, VALUE (*bl_proc) (ANYARGS),
-	VALUE data2)
-{
-    // Proc.new { |*args| curry... }
-    rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
-	    + (2 * sizeof(VALUE *)));
-
-    b->klass = 0;
-    b->proc = Qnil;
-    b->arity.min = 0;
-    b->arity.max = -1;
-    b->arity.left_req = 0;
-    b->arity.real = 1;
-    b->flags = VM_BLOCK_PROC;
-    b->imp = (IMP)rb_vm_iterate_block;
-    b->dvars[0] =(VALUE *)bl_proc;
-    GC_WB(&b->dvars[1], (VALUE *)data2);
-
-    RoxorVM *vm = GET_VM();
-    vm->add_current_block(b);
-
-    struct Finally {
-	RoxorVM *vm;
-	Finally(RoxorVM *_vm) {
-	    vm = _vm;
-	}
-	~Finally() {
-	    vm->pop_current_block();
-	}
-    } finalizer(vm);
-
-    return (*it_proc)(data1);
-}
-
-#if 0
-static inline IMP
-class_respond_to(Class klass, SEL sel)
-{
-    IMP imp = class_getMethodImplementation(klass, sel);
-    if (imp == _objc_msgForward) {
-	if (rb_vm_resolve_method(klass, sel)) {
-	    imp = class_getMethodImplementation(klass, sel);
-	}
-	else {
-	    imp = NULL;
-	}
-    }
-    return imp;
-}
-#endif
-
-static inline void
-__vm_raise(void)
-{
-    VALUE rb_exc = GET_VM()->current_exception();
-
-    // DTrace probe: raise
-    if (MACRUBY_RAISE_ENABLED()) {
-	char *classname = (char *)rb_class2name(CLASS_OF(rb_exc));
-	char file[PATH_MAX];
-	unsigned long line = 0;
-	GET_CORE()->symbolize_backtrace_entry(2, file, sizeof file, &line,
-		NULL, 0);
-	MACRUBY_RAISE(classname, file, line);
-    } 
-#if __LP64__
-    // In 64-bit, an Objective-C exception is a C++ exception.
-    id exc = rb_rb2oc_exception(rb_exc);
-    objc_exception_throw(exc);
-#else
-    void *exc = __cxa_allocate_exception(0);
-    __cxa_throw(exc, NULL, NULL);
-#endif
-}
-
-void
-RoxorVM::push_current_exception(VALUE exc)
-{
-    assert(!NIL_P(exc));
-    GC_RETAIN(exc);
-    current_exceptions.push_back(exc);
-//printf("PUSH %p %s\n", (void *)exc, RSTRING_PTR(rb_inspect(exc)));
-}
-
-void
-RoxorVM::pop_current_exception(int pos)
-{
-    RoxorSpecialException *sexc = get_special_exc();
-    if (sexc != NULL) {
-	return;
-    }
-
-    assert((size_t)pos < current_exceptions.size());
-
-    std::vector<VALUE>::iterator iter = current_exceptions.end() - (pos + 1);
-    VALUE exc = *iter;
-    current_exceptions.erase(iter);
-
-    GC_RELEASE(exc);
-//printf("POP (%d) %p %s\n", pos, (void *)exc, RSTRING_PTR(rb_inspect(exc)));
-}
-
-#if !__LP64__
-extern "C"
-void
-rb_rb2oc_exc_handler(void)
-{
-    VALUE exc = GET_VM()->current_exception();
-    if (exc != Qnil) {
-	id ocexc = rb_rb2oc_exception(exc);
-	objc_exception_throw(ocexc);
-    }
-    else {
-	__cxa_rethrow();
-    }
-}
-#endif
-
-extern "C"
-void
-rb_vm_raise_current_exception(void)
-{
-    VALUE exception = GET_VM()->current_exception();
-    assert(exception != Qnil);
-    rb_iv_set(exception, "bt", rb_vm_backtrace(0));
-    __vm_raise(); 
-}
-
-extern "C"
-void
-rb_vm_raise(VALUE exception)
-{
-    rb_iv_set(exception, "bt", rb_vm_backtrace(0));
-    GC_RETAIN(exception);
-    GET_VM()->push_current_exception(exception);
-    __vm_raise();
-}
-
-extern "C"
-VALUE
-rb_rescue2(VALUE (*b_proc) (ANYARGS), VALUE data1,
-	VALUE (*r_proc) (ANYARGS), VALUE data2, ...)
-{
-    try {
-	return (*b_proc)(data1);
-    }
-    catch (...) {
-	RoxorVM *vm = GET_VM();
-	VALUE exc = vm->current_exception();
-	if (exc != Qnil) {
-	    va_list ar;
-	    VALUE eclass;
-	    bool handled = false;
-
-	    va_start(ar, data2);
-	    while ((eclass = va_arg(ar, VALUE)) != 0) {
-		if (rb_obj_is_kind_of(exc, eclass)) {
-		    handled = true;
-		    break;
-		}
-	    }
-	    va_end(ar);
-
-	    if (handled) {
-		vm->pop_current_exception();
-		if (r_proc != NULL) {
-		    return (*r_proc)(data2, exc);
-		}
-		return Qnil;
-	    }
-	}
-	throw;
-    }
-    return Qnil; // never reached
-}
-
-extern "C"
-VALUE
-rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1,
-	VALUE (*e_proc)(ANYARGS), VALUE data2)
-{
-    struct Finally {
-	VALUE (*e_proc)(ANYARGS);
-	VALUE data2;
-	Finally(VALUE (*_e_proc)(ANYARGS), VALUE _data2) {
-	    e_proc = _e_proc;
-	    data2 = _data2;
-	}
-	~Finally() { (*e_proc)(data2); }
-    } finalizer(e_proc, data2);
-
-    return (*b_proc)(data1);
-}
-
-extern "C"
-void
-rb_ensure_b(void (^b_block)(void), void (^e_block)(void))
-{
-    struct Finally {
-	void (^e_block)(void);
-	Finally(void (^_e_block)(void)) {
-	    e_block = _e_block;
-	}
-	~Finally() { e_block(); }
-    } finalizer(e_block);
-
-    b_block();
-}
-
-extern "C"
-void
-rb_vm_break(VALUE val)
-{
-#if 0
-    // XXX this doesn't work yet since break is called inside the block and
-    // we do not have a reference to it. This isn't very important though,
-    // but since 1.9 doesn't support break without Proc objects we should also
-    // raise a similar exception.
-    assert(GET_VM()->current_block != NULL);
-    if (GET_VM()->current_block->flags & VM_BLOCK_PROC) {
-	rb_raise(rb_eLocalJumpError, "break from proc-closure");
-    }
-#endif
-    RoxorVM *vm = GET_VM();
-    if (vm->get_broken_with() != val) {
-	GC_RELEASE(vm->get_broken_with());
-	vm->set_broken_with(val);
-	GC_RETAIN(val);
-    }
-}
-
-extern "C"
-VALUE
-rb_vm_get_broken_value(void *vm)
-{
-    return ((RoxorVM *)vm)->get_broken_with();
-}
-
-extern "C"
-VALUE
-rb_vm_pop_broken_value(void)
-{
-    return GET_VM()->pop_broken_with();
-}
-
-extern "C"
-unsigned char
-rb_vm_set_has_ensure(unsigned char state)
-{
-    RoxorVM *vm = GET_VM();
-    const bool old_state = vm->get_has_ensure();
-    vm->set_has_ensure(state);
-    return old_state ? 1 : 0;
-}
-
-extern "C"
-void
-rb_vm_return_from_block(VALUE val, int id, rb_vm_block_t *running_block)
-{
-    RoxorVM *vm = GET_VM();
-
-    // Do not trigger a return from the calling scope if the running block
-    // is a lambda, to conform to the ruby 1.9 specifications.
-    if (running_block->flags & VM_BLOCK_LAMBDA) {
-	return;
-    }
-
-    // If we are inside an ensure block or if the running block is a Proc,
-    // let's implement return-from-block using a C++ exception (slow).
-    if (vm->get_has_ensure() || (running_block->flags & VM_BLOCK_PROC)) {
-	RoxorReturnFromBlockException *exc =
-	    new RoxorReturnFromBlockException();
-	vm->set_special_exc(exc);
-	exc->val = val;
-	exc->id = id;
-	throw exc;
-    }
-
-    // Otherwise, let's mark the VM (fast).
-    vm->set_return_from_block(id);
-    if (vm->get_broken_with() != val) {
-	GC_RELEASE(vm->get_broken_with());
-	vm->set_broken_with(val);
-	GC_RETAIN(val);
-    }
-}
-
-extern "C"
-VALUE
-rb_vm_returned_from_block(void *_vm, int id)
-{
-    RoxorVM *vm = (RoxorVM *)_vm;
-    if (id != -1 && vm->get_return_from_block() == id) {
-	vm->set_return_from_block(-1);
-    }
-    return vm->pop_broken_with();
-}
-
-extern "C"
-VALUE
-rb_vm_check_return_from_block_exc(RoxorReturnFromBlockException **pexc, int id)
-{
-    RoxorVM *vm = GET_VM();
-    RoxorSpecialException *sexc = vm->get_special_exc();
-    if (sexc != NULL && sexc->type == RETURN_FROM_BLOCK_EXCEPTION) {
-	RoxorReturnFromBlockException *exc = *pexc;
-	if (id == -1 || exc->id == id) {
-	    VALUE val = exc->val;
-	    delete exc;
-	    vm->set_special_exc(NULL);
-	    return val;
-	}
-    }
-    return Qundef;
-}
-
-extern "C"
-VALUE
-rb_vm_backtrace(int skip)
-{
-    assert(skip >= 0);
-
-    void *callstack[128];
-    int callstack_n = backtrace(callstack, 128);
-
-    // TODO should honor level
-
-    VALUE ary = rb_ary_new();
-
-    unsigned int interpreter_frame_idx = 0;
-
-    for (int i = 0; i < callstack_n; i++) {
-	char path[PATH_MAX];
-	char name[100];
-	unsigned long ln = 0;
-
-	path[0] = name[0] = '\0';
-
-	if (GET_CORE()->symbolize_call_address(callstack[i], path, sizeof path,
-		    &ln, name, sizeof name, &interpreter_frame_idx)
-		&& name[0] != '\0' && path[0] != '\0') {
-	    char entry[PATH_MAX];
-	    if (ln == 0) {
-		snprintf(entry, sizeof entry, "%s:in `%s'",
-			path, name);
-	    }
-	    else {
-		snprintf(entry, sizeof entry, "%s:%ld:in `%s'",
-			path, ln, name);
-	    }
-	    rb_ary_push(ary, rb_str_new2(entry));
-	}
-    }
-
-    while (skip-- > 0) {
-	rb_ary_shift(ary);
-    }
-
-    return ary;
-}
-
-extern "C"
-unsigned char
-rb_vm_is_eh_active(int argc, ...)
-{
-    assert(argc > 0);
-
-    VALUE current_exception = GET_VM()->current_exception();
-    if (current_exception == Qnil) {
-	// Not a Ruby exception...
-	return 0;
-    }
-
-    va_list ar;
-    unsigned char active = 0;
-
-    va_start(ar, argc);
-    for (int i = 0; i < argc && active == 0; ++i) {
-	VALUE obj = va_arg(ar, VALUE);
-	if (TYPE(obj) == T_ARRAY) {
-	    for (int j = 0, count = RARRAY_LEN(obj); j < count; ++j) {
-		VALUE obj2 = RARRAY_AT(obj, j);
-		if (rb_obj_is_kind_of(current_exception, obj2)) {
-		    active = 1;
-		    break;
-		}
-	    }
-	}
-	else {
-	    if (rb_obj_is_kind_of(current_exception, obj)) {
-		active = 1;
-	    }
-	}
-    }
-    va_end(ar);
-
-    return active;
-}
-
-extern "C"
-void
-rb_vm_pop_exception(int pos)
-{
-    GET_VM()->pop_current_exception(pos);
-}
-
-extern "C"
-VALUE
-rb_vm_current_exception(void)
-{
-    return GET_VM()->current_exception();
-}
-
-extern "C"
-void
-rb_vm_set_current_exception(VALUE exception)
-{
-    assert(!NIL_P(exception));
-
-    VALUE current = GET_VM()->current_exception();
-    assert(exception != current);
-    if (!NIL_P(current)) {
-	GET_VM()->pop_current_exception();
-    }
-    GET_VM()->push_current_exception(exception);
-}
-
-extern "C"
-void 
-rb_vm_debug(void)
-{
-    printf("rb_vm_debug\n");
-}
-
-extern "C"
-void
-rb_vm_print_exception(VALUE exc)
-{
-    printf("%s", rb_str_cstr(rb_format_exception_message(exc)));
-}
-
-extern "C"
-void
-rb_vm_print_current_exception(void)
-{
-    VALUE exc = GET_VM()->current_exception();
-    if (exc == Qnil) {
-	printf("uncaught Objective-C/C++ exception...\n");
-	std::terminate();
-    }
-    rb_vm_print_exception(exc);
-}
-
-extern "C"
-bool
-rb_vm_parse_in_eval(void)
-{
-    return GET_VM()->get_parse_in_eval();
-}
-
-extern "C"
-void
-rb_vm_set_parse_in_eval(bool flag)
-{
-    GET_VM()->set_parse_in_eval(flag);
-}
-
-extern "C"
-int
-rb_parse_in_eval(void)
-{
-    return rb_vm_parse_in_eval() ? 1 : 0;
-}
-
-VALUE *
-RoxorVM::get_binding_lvar(ID name, bool create)
-{
-    rb_vm_binding_t *current_b = current_binding();
-    rb_vm_binding_t *b = current_b;
-    while (b != NULL) {
-	rb_vm_local_t **l = &b->locals;
-	while (*l != NULL) {
-	    if ((*l)->name == name) {
-		return (*l)->value;
-	    }
-	    l = &(*l)->next;
-	}
-	b = b->next;
-    }
-    if (create && current_b != NULL) {
-	rb_vm_binding_t *b = current_b;
-	rb_vm_local_t **l = &b->locals;
-	while (*l != NULL) {
-	    l = &(*l)->next;
-	}
-	GC_WB(l, xmalloc(sizeof(rb_vm_local_t)));
-	(*l)->name = name;
-	GC_WB(&(*l)->value, xmalloc(sizeof(VALUE *)));
-	(*l)->next = NULL;
-	return (*l)->value;
-    }
-    return NULL;
-}
-
-extern "C"
-int
-rb_local_define(ID id)
-{
-    return GET_VM()->get_binding_lvar(id, true) != NULL ? 1 : 0;
-}
-
-extern "C"
-int
-rb_local_defined(ID id)
-{
-    return GET_VM()->get_binding_lvar(id, false) != NULL ? 1 : 0;
-}
-
-extern "C"
-int
-rb_dvar_defined(ID id)
-{
-    // TODO
-    return 0;
-}
-
-extern "C"
-void
-rb_vm_init_jit(void)
-{
-    GET_CORE()->prepare_jit();
-}
-
-extern "C"
-void
-rb_vm_init_compiler(void)
-{
-#if !defined(MACRUBY_STATIC)
-    if (ruby_aot_compile && ruby_debug_socket_path) {
-	fprintf(stderr, "cannot run in both AOT and debug mode\n");
-	exit(1);
-    }
-    RoxorCompiler::shared = ruby_aot_compile
-	? new RoxorAOTCompiler()
-	: new RoxorCompiler(ruby_debug_socket_path);
-#endif
-}
-
-extern "C" void rb_node_release(NODE *node);
-
-extern "C"
-VALUE
-rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
-	bool inside_eval)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "codegen is not supported in MacRuby static");
-#else
-    RoxorVM *vm = GET_VM();
-    RoxorCompiler *compiler = RoxorCompiler::shared;
-    RoxorCoreLock lock;
-
-    // Compile IR.
-    if (binding != NULL) {
-	vm->push_current_binding(binding);
-    }
-    bool old_inside_eval = compiler->is_inside_eval();
-    compiler->set_inside_eval(inside_eval);
-    compiler->set_fname(fname);
-    bool can_interpret = false;
-    Function *func = compiler->compile_main_function(node, &can_interpret);
-    //compiler->set_fname(NULL);
-    compiler->set_inside_eval(old_inside_eval);
-    if (binding != NULL) {
-	vm->pop_current_binding();
-    }
-
-    VALUE ret;
-
-    if (can_interpret && GET_CORE()->get_interpreter_enabled()) {
-//printf("interpret:\n");
-//func->dump();
-	// If the function can be interpreted, do it, then delete the IR.
-	lock.unlock();
-	ret = RoxorInterpreter::shared->interpret(func,
-		vm->get_current_top_object(), 0);
- 	func->eraseFromParent();
-    }
-    else {
-//printf("jit:\n");
-//func->dump();
-	// Optimize & compile the function.
-	IMP imp = GET_CORE()->compile(func);
-
-	// Register it for symbolication.
-	rb_vm_method_node_t *mnode = GET_CORE()->method_node_get(imp, true);
-	mnode->klass = 0;
-	mnode->arity = rb_vm_arity(2);
-	mnode->sel = sel_registerName("<main>");
-	mnode->objc_imp = mnode->ruby_imp = imp;
-	mnode->flags = 0;
-
-	// Execute the function.
-	lock.unlock();
-	ret = ((VALUE(*)(VALUE, SEL))imp)(vm->get_current_top_object(), 0);
-
-	if (inside_eval) {
-	    // XXX We only delete functions created by #eval. In theory it
-	    // should also work for other functions, but it makes spec:ci crash.
-	    GET_CORE()->delenda(func);
-	}
-    }
-
-    rb_node_release(node);
-
-    return ret;
-#endif
-}
-
-extern "C"
-VALUE
-rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
-	rb_vm_binding_t *binding, bool inside_eval)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError, "codegen is not supported in MacRuby static");
-#else
-    RoxorVM *vm = GET_VM();
-
-    VALUE old_top_object = vm->get_current_top_object();
-    if (binding != NULL) {
-	self = binding->self;
-    }
-    if (self != 0) {
-	vm->set_current_top_object(self);
-    }
-    Class old_class = GET_VM()->get_current_class();
-    bool old_dynamic_class = RoxorCompiler::shared->is_dynamic_class();
-    vm->set_current_class((Class)klass);
-    RoxorCompiler::shared->set_dynamic_class(true);
-
-    vm->add_current_block(binding != NULL ? binding->block : NULL);
-
-    struct Finally {
-	RoxorVM *vm;
-	bool old_dynamic_class;
-	Class old_class;
-	VALUE old_top_object;
-	Finally(RoxorVM *_vm, bool _dynamic_class, Class _class, VALUE _obj) {
-	    vm = _vm;
-	    old_dynamic_class = _dynamic_class;
-	    old_class = _class;
-	    old_top_object = _obj;
-	}
-	~Finally() { 
-	    RoxorCompiler::shared->set_dynamic_class(old_dynamic_class);
-	    vm->set_current_top_object(old_top_object);
-	    vm->set_current_class(old_class);
-	    vm->pop_current_block();
-	}
-    } finalizer(vm, old_dynamic_class, old_class, old_top_object);
-
-    return rb_vm_run(fname, node, binding, inside_eval);
-#endif
-}
-
-extern VALUE rb_progname;
-extern "C" void rb_vm_aot_load_bs_files(VALUE);
-
-extern "C"
-void
-rb_vm_aot_compile(NODE *node)
-{
-#if MACRUBY_STATIC
-    abort();
-#else
-    assert(ruby_aot_compile);
-    assert(ruby_aot_init_func);
-
-    // Load the BridgeSupport files.
-    if (ruby_aot_bs_files != Qnil) {
-	for (int i = 0, count = RARRAY_LEN(ruby_aot_bs_files); i < count;
-		i++) {
-	    ((RoxorAOTCompiler *)RoxorCompiler::shared)->load_bs_full_file(
-		RSTRING_PTR(RARRAY_AT(ruby_aot_bs_files, i)));
-	}
-    }
-
-    // Mark all VM primitives as static, to avoid symbol collision when
-    // linking with other AOT compiled files.
-    llvm::Module::FunctionListType &funcs =
-	RoxorCompiler::module->getFunctionList();
-    for (llvm::Module::FunctionListType::iterator i = funcs.begin();
-	    i != funcs.end(); ++i) {
-	if (i->getName().startswith("vm_")) {
-	    i->setLinkage(GlobalValue::InternalLinkage);
-	}
-    }
-
-    // Compile the program as IR.
-    RoxorCompiler::shared->set_fname(RSTRING_PTR(rb_progname));
-    Function *f = RoxorCompiler::shared->compile_main_function(node, NULL);
-    f->setName(RSTRING_PTR(ruby_aot_init_func));
-
-    // Force a module verification.
-    rb_verify_module();
-
-    // Run standard optimization passes on the module.
-    PassManager pm;
-    createStandardModulePasses(&pm, 3, false, true, true, true, true,
-	    createFunctionInliningPass());
-    pm.run(*RoxorCompiler::module);
-
-    // Dump the bitcode.
-    std::string err;
-    const char *output = RSTRING_PTR(ruby_aot_compile);
-    raw_fd_ostream out(output, err, raw_fd_ostream::F_Binary);
-    if (!err.empty()) {
-	fprintf(stderr, "error when opening the output bitcode file: %s\n",
-		err.c_str());
-	abort();
-    }
-    WriteBitcodeToFile(RoxorCompiler::module, out);
-    out.close();
-#endif
-}
-
-extern "C"
-VALUE
-rb_vm_top_self(void)
-{
-    return GET_VM()->get_current_top_object();
-}
-
-extern "C"
-VALUE
-rb_vm_loaded_features(void)
-{
-    return GET_CORE()->get_loaded_features();
-}
-
-extern "C"
-VALUE
-rb_vm_load_path(void)
-{
-    return GET_CORE()->get_load_path();
-}
-
-extern "C"
-int
-rb_vm_safe_level(void)
-{
-    return GET_VM()->get_safe_level();
-}
-
-extern "C"
-int
-rb_vm_thread_safe_level(rb_vm_thread_t *thread)
-{
-    return ((RoxorVM *)thread->vm)->get_safe_level();
-}
-
-extern "C"
-void 
-rb_vm_set_safe_level(int level)
-{
-    GET_VM()->set_safe_level(level);
-}
-
-extern "C"
-VALUE
-rb_last_status_get(void)
-{
-    return GET_VM()->get_last_status();
-}
-
-extern "C"
-void
-rb_last_status_set(int status, rb_pid_t pid)
-{
-    VALUE last_status = GET_VM()->get_last_status();
-    if (last_status != Qnil) {
-	GC_RELEASE(last_status);
-    }
-
-    if (pid == -1) {
-	last_status = Qnil;
-    }
-    else {
-	last_status = rb_obj_alloc(rb_cProcessStatus);
-	rb_iv_set(last_status, "status", INT2FIX(status));
-	rb_iv_set(last_status, "pid", PIDT2NUM(pid));
-	GC_RETAIN(last_status);
-    }
-    GET_VM()->set_last_status(last_status);
-}
-
-extern "C"
-VALUE
-rb_errinfo(void)
-{
-    return GET_VM()->get_errinfo();
-}
-
-void
-rb_set_errinfo(VALUE err)
-{
-    if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
-        rb_raise(rb_eTypeError, "assigning non-exception to $!");
-    }
-    VALUE errinfo = GET_VM()->get_errinfo();
-    if (errinfo != Qnil) {
-	GC_RELEASE(errinfo);
-    }
-    GET_VM()->set_errinfo(err);
-    GC_RETAIN(err);
-}
-
-extern "C"
-const char *
-rb_sourcefile(void)
-{
-    // TODO
-    return "unknown";
-}
-
-extern "C"
-int
-rb_sourceline(void)
-{
-    // TODO
-    return 0;
-}
-
-extern "C"
-VALUE
-rb_lastline_get(void)
-{
-    return GET_VM()->get_last_line();
-}
-
-extern "C"
-void
-rb_lastline_set(VALUE val)
-{
-    VALUE old = GET_VM()->get_last_line();
-    if (old != val) {
-	GC_RELEASE(old);
-	GET_VM()->set_last_line(val);
-	GC_RETAIN(val);
-    }
-}
-
-extern "C"
-void
-rb_iter_break(void)
-{
-    RoxorVM *vm = GET_VM();
-    GC_RELEASE(vm->get_broken_with());
-    vm->set_broken_with(Qnil);
-}
-
-extern "C"
-VALUE
-rb_backref_get(void)
-{
-    return GET_VM()->get_backref();
-}
-
-extern "C"
-void
-rb_backref_set(VALUE val)
-{
-    VALUE old = GET_VM()->get_backref();
-    if (old != val) {
-	GC_RELEASE(old);
-	GET_VM()->set_backref(val);
-	GC_RETAIN(val);
-    }
-}
-
-void
-RoxorVM::increase_nesting_for_tag(VALUE tag)
-{
-    std::map<VALUE, int*>::iterator iter = this->catch_nesting.find(tag);
-    int *nested_ptr = NULL;
-
-    if (iter == catch_nesting.end()) {
-	nested_ptr = (int *)malloc(sizeof(int));
-	*nested_ptr = 1;
-	catch_nesting[tag] = nested_ptr;
-	GC_RETAIN(tag);
-    }
-    else {
-	nested_ptr = iter->second;
-	(*nested_ptr)++;
-    }
-}
-
-void
-RoxorVM::decrease_nesting_for_tag(VALUE tag)
-{
-    std::map<VALUE, int*>::iterator iter = this->catch_nesting.find(tag);
-    int *nested_ptr = NULL;
- 
-    iter = catch_nesting.find(tag);
-    assert(iter != catch_nesting.end());
-    nested_ptr = iter->second;
-
-    (*nested_ptr)--;
-    if (*nested_ptr == 0) {
-	nested_ptr = iter->second;
-	free(nested_ptr);
-	catch_nesting.erase(iter);
-	GC_RELEASE(tag);
-    }
-}
-
-VALUE
-RoxorVM::ruby_catch(VALUE tag)
-{
-    VALUE retval = Qundef;
-
-    increase_nesting_for_tag(tag);
-    try {
-	retval = rb_vm_yield(1, &tag);
-    }
-    catch (...) {
-	RoxorSpecialException *sexc = get_special_exc();
-	if (sexc != NULL && sexc->type == CATCH_THROW_EXCEPTION) {
-	    RoxorCatchThrowException *exc = (RoxorCatchThrowException *)sexc;
-	    if (exc->throw_symbol == tag) {
-		retval = exc->throw_value;
-		GC_RELEASE(retval);
-		delete exc;
-		set_special_exc(NULL);
-	    }
-	}
-	if (retval == Qundef) {
-	    decrease_nesting_for_tag(tag);
-	    throw;
-	}
-    }
-    decrease_nesting_for_tag(tag); 
-
-    return retval;
-}
-
-extern "C"
-VALUE
-rb_vm_catch(VALUE tag)
-{
-    return GET_VM()->ruby_catch(tag);
-}
-
-VALUE
-RoxorVM::ruby_throw(VALUE tag, VALUE value)
-{
-    std::map<VALUE, int*>::iterator iter = catch_nesting.find(tag);
-    if (iter == catch_nesting.end()) {
-        VALUE desc = rb_inspect(tag);
-        rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
-    }
-
-    GC_RETAIN(value);
-
-    // We must pop the current VM exception in case we are in a rescue handler,
-    // since we are going to unwind the stack.
-    if (current_exception() != Qnil) {
-	pop_current_exception();
-    }
-
-    RoxorCatchThrowException *exc = new RoxorCatchThrowException;
-    set_special_exc(exc);
-    exc->throw_symbol = tag;
-    exc->throw_value = value;
-    throw exc;
-
-    return Qnil; // Never reached;
-}
-
-extern "C"
-VALUE
-rb_vm_throw(VALUE tag, VALUE value)
-{
-    return GET_VM()->ruby_throw(tag, value);
-}
-
-extern "C"
-VALUE
-rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
-{
-    return GET_VM()->exec_recursive(func, obj, arg);
-}
-
-VALUE
-RoxorVM::exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj,
-	VALUE arg)
-{
-    std::vector<VALUE>::iterator iter =
-	std::find(recursive_objects.begin(), recursive_objects.end(), obj);
-    if (iter != recursive_objects.end()) {
-	// Object is already being iterated!
-	return (*func) (obj, arg, Qtrue);
-    }
-
-    recursive_objects.push_back(obj);
-    // XXX the function is not supposed to raise an exception.
-    VALUE ret = (*func) (obj, arg, Qfalse);
-
-    iter = std::find(recursive_objects.begin(), recursive_objects.end(), obj);
-    assert(iter != recursive_objects.end());
-    recursive_objects.erase(iter);
-
-    return ret;
-}
-
-extern "C"
-void
-rb_vm_register_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    GET_CORE()->register_finalizer(finalizer);
-}
-
-extern "C"
-void
-rb_vm_unregister_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    GET_CORE()->unregister_finalizer(finalizer);
-}
-
-void
-RoxorCore::register_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    RoxorCoreLock lock;
-
-    finalizers.push_back(finalizer);
-}
-
-void
-RoxorCore::unregister_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    RoxorCoreLock lock;
-
-    std::vector<rb_vm_finalizer_t *>::iterator i = std::find(finalizers.begin(),
-	    finalizers.end(), finalizer);
-    if (i != finalizers.end()) {
-	finalizers.erase(i);
-    }
-}
-
-static void
-call_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    for (int i = 0, count = RARRAY_LEN(finalizer->finalizers); i < count; i++) {
-	VALUE b = RARRAY_AT(finalizer->finalizers, i);
-	try {
-	    rb_vm_call(b, selCall, 1, &finalizer->objid);
-	}
-	catch (...) {
-	    // Do nothing.
-	}
-    }
-    rb_ary_clear(finalizer->finalizers);
-}
-
-extern "C"
-void
-rb_vm_call_finalizer(rb_vm_finalizer_t *finalizer)
-{
-    call_finalizer(finalizer);
-}
-
-void
-RoxorCore::call_all_finalizers(void)
-{
-    for (std::vector<rb_vm_finalizer_t *>::iterator i = finalizers.begin();
-	    i != finalizers.end();
-	    ++i) {
-	call_finalizer(*i);
-    }
-    finalizers.clear();
-}
-
-extern "C"
-void *
-rb_vm_create_vm(void)
-{
-    return (void *)new RoxorVM(*GET_VM());
-}
-
-extern "C"
-void *
-rb_vm_current_vm(void)
-{
-    return (void *)GET_VM();
-}
-
-extern "C"
-struct mcache *
-rb_vm_get_mcache(void *vm)
-{
-    return ((RoxorVM *)vm)->get_mcache();
-} 
-
-void
-RoxorCore::register_thread(VALUE thread)
-{
-    RoxorCoreLock lock;
-
-    rb_ary_push(threads, thread);
-
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    pthread_assert(pthread_setspecific(RoxorVM::vm_thread_key, t->vm));
-
-    RoxorVM *vm = (RoxorVM *)t->vm;
-    vm->set_thread(thread);
-}
-
-extern "C" void rb_thread_unlock_all_mutexes(rb_vm_thread_t *thread);
-
-void
-RoxorCore::unregister_thread(VALUE thread)
-{
-    RoxorCoreLock lock;
-
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    t->status = THREAD_DEAD;
-
-    // We do not call #delete because it might trigger #== in case it has been
-    // overriden on the thread object, and therefore cause a deadlock if the
-    // new method tries to acquire the RoxorCore GIL.
-    bool deleted = false;
-    for (long i = 0, n = RARRAY_LEN(threads); i < n; i++) {
-	VALUE ti = RARRAY_AT(threads, i);
-	if (ti == thread) {
-	    rb_ary_delete_at(threads, i);
-	    deleted = true;
-	    break;
-	}
-    }
-    if (!deleted) {
-	printf("trying to unregister a thread (%p) that was never registered!",
-		(void *)thread);
-	abort();
-    }
-
-    lock.unlock();
-
-    const int code = pthread_mutex_destroy(&t->sleep_mutex);
-    if (code == EBUSY) {
-	// The mutex is already locked, which means we are being called from
-	// a cancellation point inside the wait logic. Let's unlock the mutex
-	// and try again.
-	pthread_assert(pthread_mutex_unlock(&t->sleep_mutex));
-	pthread_assert(pthread_mutex_destroy(&t->sleep_mutex));
-    }
-    else if (code != 0) {
-	abort();
-    }
-    pthread_assert(pthread_cond_destroy(&t->sleep_cond));
-
-    rb_thread_unlock_all_mutexes(t); 
-
-    RoxorVM *vm = (RoxorVM *)t->vm;
-    delete vm;
-    t->vm = NULL;
-
-    pthread_assert(pthread_setspecific(RoxorVM::vm_thread_key, NULL));
-}
-
-static inline void
-rb_vm_thread_throw_kill(void)
-{
-    // Killing a thread is implemented using a non-catchable (from Ruby)
-    // exception, which allows us to call the ensure blocks before dying,
-    // which is unfortunately covered in the Ruby specifications.
-    throw new RoxorThreadRaiseException();
-}
-
-static void
-rb_vm_thread_destructor(void *userdata)
-{
-    rb_vm_thread_throw_kill();
-}
-
-extern "C"
-void *
-rb_vm_thread_run(VALUE thread)
-{
-    rb_objc_gc_register_thread();
-    GET_CORE()->register_thread(thread);
-
-    // Release the thread now.
-    GC_RELEASE(thread);
-
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-
-    // Normally the pthread ID is set into the VM structure in the other
-    // thread right after pthread_create(), but we might run before the
-    // assignment!
-    t->thread = pthread_self();
-
-    pthread_cleanup_push(rb_vm_thread_destructor, (void *)thread);
-
-    RoxorVM *vm = GET_VM();
-    try {
-	VALUE val = rb_vm_block_eval(t->body, t->argc, t->argv);
-	GC_WB(&t->value, val);
-    }
-    catch (...) {
-	VALUE exc;
-	RoxorSpecialException *sexc = vm->get_special_exc();
-	if (sexc != NULL && sexc->type == RETURN_FROM_BLOCK_EXCEPTION) {
-	    delete sexc;
-	    vm->set_special_exc(NULL);
-	    exc = rb_exc_new2(rb_eLocalJumpError,
-		    "unexpected return from Thread");
-	}
-	else {
-	    exc = rb_vm_current_exception();
-	}
-	if (exc != Qnil) {
-	    GC_WB(&t->exception, exc);
-	}
-	t->value = Qnil;
-    }
-
-    pthread_cleanup_pop(0);
-
-    rb_thread_remove_from_group(thread); 
-    GET_CORE()->unregister_thread(thread);
-    rb_objc_gc_unregister_thread();
-
-#if 0
-    if (t->exception != Qnil) {
-	if (t->abort_on_exception || GET_CORE()->get_abort_on_exception()) {
- 	    // TODO: move the exception to the main thread
-	    //rb_exc_raise(t->exception);
-	}
-    }
-#endif
-
-    return NULL;
-}
-
-extern "C"
-VALUE
-rb_vm_threads(void)
-{
-    return GET_CORE()->get_threads();
-}
-
-extern "C"
-VALUE
-rb_vm_current_thread(void)
-{
-    return GET_VM()->get_thread();
-}
-
-extern "C"
-VALUE
-rb_thread_current(void)
-{
-    // For compatibility with MRI 1.9.
-    return rb_vm_current_thread();
-}
-
-extern "C"
-VALUE
-rb_vm_main_thread(void)
-{
-    return RoxorVM::main->get_thread();
-}
-
-extern "C"
-VALUE
-rb_vm_thread_locals(VALUE thread, bool create_storage)
-{
-    rb_vm_thread_t *t = GetThreadPtr(thread);
-    if (t->locals == Qnil && create_storage) {
-	GC_WB(&t->locals, rb_hash_new());
-    }
-    return t->locals;
-}
-
-extern "C"
-void
-rb_vm_thread_pre_init(rb_vm_thread_t *t, rb_vm_block_t *body, int argc,
-	const VALUE *argv, void *vm)
-{
-    t->thread = 0; // this will be set later
-
-    if (body != NULL) {
-	GC_WB(&t->body, body);
-	rb_vm_block_make_detachable_proc(body);
-
-	// Release ownership of all dynamic variables, mark the block as
-	// being run from a thread.
-	for (int i = 0; i < body->dvars_size; i++) {
-	    VALUE *dvar = body->dvars[i];
-	    rb_vm_release_ownership(*dvar);
-	}
-	body->flags |= VM_BLOCK_THREAD;
-    }
-    else {
-	t->body = NULL;
-    }
-   
-    if (argc > 0) {
-	t->argc = argc;
-	GC_WB(&t->argv, xmalloc_ptrs(sizeof(VALUE) * argc));
-	for (int i = 0; i < argc; i++) {
-	    GC_WB(&t->argv[i], argv[i]);
-	}
-    }
-    else {
-	t->argc = 0;
-	t->argv = NULL;
-    }
-
-    t->vm  = vm;
-    t->value = Qundef;
-    t->locals = Qnil;
-    t->exception = Qnil;
-    t->status = THREAD_ALIVE;
-    t->in_cond_wait = false;
-    t->abort_on_exception = false;
-    t->joined_on_exception = false;
-    t->group = Qnil; // will be set right after
-    t->mutexes = Qnil;
-
-    pthread_assert(pthread_mutex_init(&t->sleep_mutex, NULL));
-    pthread_assert(pthread_cond_init(&t->sleep_cond, NULL)); 
-}
-
-static inline void
-pre_wait(rb_vm_thread_t *t)
-{
-    pthread_assert(pthread_mutex_lock(&t->sleep_mutex));
-    t->status = THREAD_SLEEP;
-    t->in_cond_wait = true;
-}
-
-static inline void
-post_wait(rb_vm_thread_t *t)
-{
-    t->in_cond_wait = false;
-    pthread_assert(pthread_mutex_unlock(&t->sleep_mutex));
-    if (t->status == THREAD_KILLED) {
-	rb_vm_thread_throw_kill();
-    }
-    t->status = THREAD_ALIVE;
-}
-
-extern "C"
-void
-rb_thread_sleep_forever()
-{
-    rb_vm_thread_t *t = GET_THREAD();
-
-    if (rb_thread_alone()) {
-	rb_raise(rb_eThreadError,
-		"stopping only thread\n\tnote: use sleep to stop forever");
-    }
-
-    pre_wait(t);
-    const int code = pthread_cond_wait(&t->sleep_cond, &t->sleep_mutex);
-    assert(code == 0 || code == ETIMEDOUT);
-    post_wait(t);
-}
-
-extern "C"
-void
-rb_thread_wait_for(struct timeval time)
-{
-    struct timeval tvn;
-    gettimeofday(&tvn, NULL);
-
-    struct timespec ts;
-    ts.tv_sec = tvn.tv_sec + time.tv_sec;
-    ts.tv_nsec = (tvn.tv_usec + time.tv_usec) * 1000;
-    while (ts.tv_nsec >= 1000000000) {
-	ts.tv_sec += 1;
-	ts.tv_nsec -= 1000000000;
-    }
-
-    rb_vm_thread_t *t = GET_THREAD();
-
-    pre_wait(t);
-    const int code = pthread_cond_timedwait(&t->sleep_cond, &t->sleep_mutex,
-	    &ts);
-    assert(code == 0 || code == ETIMEDOUT);
-    post_wait(t);
-}
-
-extern "C"
-void
-rb_vm_thread_wakeup(rb_vm_thread_t *t)
-{
-    if (t->status == THREAD_DEAD) {
-	rb_raise(rb_eThreadError, "can't wake up thread from the death");
-    }
-    if (t->status == THREAD_SLEEP && t->in_cond_wait) {
-	pthread_assert(pthread_mutex_lock(&t->sleep_mutex));
-	pthread_assert(pthread_cond_signal(&t->sleep_cond));
-	pthread_assert(pthread_mutex_unlock(&t->sleep_mutex));
-    }
-}
-
-extern "C"
-void
-rb_vm_thread_cancel(rb_vm_thread_t *t)
-{
-    RoxorCoreLock lock;
-
-    if (t->status != THREAD_KILLED && t->status != THREAD_DEAD) {
-	t->status = THREAD_KILLED;
-	if (t->thread == pthread_self()) {
-	    lock.unlock();
-	    rb_vm_thread_throw_kill();
-	    return;
-	}
-	else {
-	    pthread_assert(pthread_mutex_lock(&t->sleep_mutex));
-	    if (t->in_cond_wait) {
-		// We are trying to kill a thread which is currently waiting
-		// for a condition variable (#sleep). Instead of canceling the
-		// thread, we are simply signaling the variable, and the thread
-		// will autodestroy itself, to work around a stack unwinding
-		// bug in the Mac OS X pthread implementation that messes our
-		// C++ exception handlers.
-		pthread_assert(pthread_cond_signal(&t->sleep_cond));
-	    }
-	    else {
-		pthread_assert(pthread_cancel(t->thread));
-	    }
-	    pthread_assert(pthread_mutex_unlock(&t->sleep_mutex));
-	}
-    }
-    lock.unlock();
-}
-
-extern "C"
-void
-rb_vm_thread_raise(rb_vm_thread_t *t, VALUE exc)
-{
-    // XXX we should lock here
-    RoxorVM *vm = (RoxorVM *)t->vm;
-    vm->push_current_exception(exc);
-
-    rb_vm_thread_cancel(t);
-}
-
-extern "C"
-void
-rb_thread_sleep(int sec)
-{
-    struct timeval time;
-    time.tv_sec = sec;
-    time.tv_usec = 0;
-    rb_thread_wait_for(time);
-}
-
-extern "C"
-Class
-rb_vm_set_current_class(Class klass)
-{
-    RoxorVM *vm = GET_VM();
-    Class old = vm->get_current_class();
-    vm->set_current_class(klass);
-    return old;
-}
-
-extern "C"
-Class
-rb_vm_get_current_class(void)
-{
-    return GET_VM()->get_current_class();
-}
-
-extern "C"
-bool
-rb_vm_generate_objc_class_name(const char *name, char *buf, size_t buflen)
-{
-    RoxorCoreLock lock;
-
-    if (name == NULL) {
-	static unsigned long anon_count = 1;
-	if (anon_count == ULONG_MAX) {
-	    return false;
-	}
-	snprintf(buf, buflen, "RBAnonymous%ld", ++anon_count);
-    }
-    else {
-	if (objc_getClass(name) != NULL) {
-	    unsigned long count = 1;
-	    snprintf(buf, buflen, "RB%s", name);
-	    while (objc_getClass(buf) != NULL) {
-		if (count == ULONG_MAX) {
-		    return false;
-		}
-		snprintf(buf, buflen, "RB%s%ld", name, ++count);
-	    }
-	}
-	else {
-	    strncpy(buf, name, buflen);
-	}
-    }
-    return true;
-}
-
-static VALUE
-builtin_ostub1(IMP imp, id self, SEL sel, int argc, VALUE *argv)
-{
-    return OC2RB(((id (*)(id, SEL))*imp)(self, sel));
-}
-
-static void
-setup_builtin_stubs(void)
-{
-    GET_CORE()->insert_stub("@@:", (void *)builtin_ostub1, true);
-    GET_CORE()->insert_stub("#@:", (void *)builtin_ostub1, true);
-}
-
-extern "C"
-void
-rb_vm_add_stub(const char *types, void *func, unsigned char is_objc)
-{
-    GET_CORE()->insert_stub(types, func, is_objc);
-}
-
-#if !defined(MACRUBY_STATIC)
-static IMP old_resolveClassMethod_imp = NULL;
-static IMP old_resolveInstanceMethod_imp = NULL;
-static SEL sel_resolveClassMethod = 0;
-static SEL sel_resolveInstanceMethod = 0;
-
-static BOOL
-resolveClassMethod_imp(void *self, SEL sel, SEL name)
-{
-    if (rb_vm_resolve_method(*(Class *)self, name)) {
-	return YES;
-    }
-    return NO; // TODO call old IMP
-}
-
-static BOOL
-resolveInstanceMethod_imp(void *self, SEL sel, SEL name)
-{
-    if (rb_vm_resolve_method((Class)self, name)) {
-	return YES;
-    }
-    return NO; // TODO call old IMP
-}
-
-static bool
-class_has_custom_resolver(Class klass)
-{
-    if (!class_isMetaClass(klass)) {
-	klass = *(Class *)klass;
-    }
-    if (class_getMethodImplementation(klass, sel_resolveClassMethod)
-	    != (IMP)resolveClassMethod_imp) {
-	return true;
-    }
-    if (class_getMethodImplementation(klass, sel_resolveInstanceMethod)
-	    != (IMP)resolveInstanceMethod_imp) {
-	return true;
-    }
-    return false;
-}
-#endif
-
-#if !defined(MACRUBY_STATIC)
-# include ".objs/kernel_data.c"
-#endif
-
-extern "C"
-void 
-Init_PreVM(void)
-{
-#if !defined(MACRUBY_STATIC)
-    // To emit DWARF exception tables. 
-    llvm::JITExceptionHandling = true;
-    // To emit DWARF debug metadata. 
-    llvm::JITEmitDebugInfo = true; 
-    // To not interfere with our signal handling mechanism.
-    llvm::DisablePrettyStackTrace = true;
-    // To not corrupt stack pointer (essential for backtracing).
-    llvm::NoFramePointerElim = true;
-
-    MemoryBuffer *mbuf = NULL;
-    const char *kernel_file = getenv("VM_KERNEL_PATH");
-    if (kernel_file != NULL) {
-	std::string err;
-#if !defined(LLVM_TOT)
-	OwningPtr<MemoryBuffer> MB;
-	error_code errcode = MemoryBuffer::getFile(kernel_file, MB);
-	if (errcode) {
-	    err = errcode.message();
-	}
-	else {
-	    mbuf = MB.take();
-	    assert(mbuf != NULL);
-	}
-#else
-	mbuf = MemoryBuffer::getFile(kernel_file, &err);
-#endif
-	if (mbuf == NULL) {
-	    printf("can't open given kernel file `%s': %s\n", kernel_file,
-		    err.c_str());
-	    abort();
-	}
-    }
-    else {
-	// Retrieve the kernel bitcode for the right architecture. We substract
-	// 1 to the length because it's NULL terminated.
-	const char *kernel_beg;
-	const char *kernel_end;
-#if __LP64__
-	kernel_beg = (const char *)_objs_kernel_x86_64_bc;
-	kernel_end = kernel_beg + _objs_kernel_x86_64_bc_len - 1;
-#else
-	kernel_beg = (const char *)_objs_kernel_i386_bc;
-	kernel_end = kernel_beg + _objs_kernel_i386_bc_len - 1;
-#endif
-
-	mbuf = MemoryBuffer::getMemBuffer(StringRef(kernel_beg, kernel_end - kernel_beg));
-    }
-    std::string err;
-    RoxorCompiler::module = ParseBitcodeFile(mbuf, getGlobalContext(), &err);
-    delete mbuf;
-    if (RoxorCompiler::module == NULL) {
-	printf("kernel bitcode couldn't be read: %s\n", err.c_str());
-    }
-    assert(RoxorCompiler::module != NULL);
-
-    RoxorInterpreter::shared = new RoxorInterpreter();
-#endif // !MACRUBY_STATIC
-
-    RoxorCore::shared = new RoxorCore();
-    RoxorVM::main = new RoxorVM();
-
-    pthread_assert(pthread_key_create(&RoxorVM::vm_thread_key, NULL));
-    pthread_assert(pthread_setspecific(RoxorVM::vm_thread_key,
-		(void *)RoxorVM::main));
-
-    setup_builtin_stubs();
-
-#if !defined(MACRUBY_STATIC)
-    Class ns_object = (Class)objc_getClass("NSObject");
-    Method m;
-    sel_resolveClassMethod = sel_registerName("resolveClassMethod:");
-    m = class_getInstanceMethod(*(Class *)ns_object, sel_resolveClassMethod);
-    assert(m != NULL);
-    old_resolveClassMethod_imp = method_getImplementation(m);
-    method_setImplementation(m, (IMP)resolveClassMethod_imp);
-
-    sel_resolveInstanceMethod = sel_registerName("resolveInstanceMethod:");
-    m = class_getInstanceMethod(*(Class *)ns_object, sel_resolveInstanceMethod);
-    assert(m != NULL);
-    old_resolveInstanceMethod_imp = method_getImplementation(m);
-    method_setImplementation(m, (IMP)resolveInstanceMethod_imp);
-#endif // !MACRUBY_STATIC
-
-    // Early define some classes.
-    rb_cNSString = (VALUE)objc_getClass("NSString");
-    assert(rb_cNSString != 0);
-    rb_cNSArray = (VALUE)objc_getClass("NSArray");
-    assert(rb_cNSArray != 0);
-    rb_cNSHash = (VALUE)objc_getClass("NSDictionary");
-    assert(rb_cNSHash != 0);
-    rb_cSymbol = rb_objc_create_class("Symbol", rb_cNSString);
-    rb_cEncoding = rb_objc_create_class("Encoding",
-	    (VALUE)objc_getClass("NSObject"));
-    rb_cRubyString = rb_objc_create_class("String",
-	    (VALUE)objc_getClass("NSMutableString"));
-}
-
-static VALUE
-rb_toplevel_to_s(VALUE rcv, SEL sel)
-{
-    return rb_str_new2("main");
-}
-
-#if !defined(MACRUBY_STATIC)
-static const char *
-resources_path(char *path, size_t len)
-{
-    CFBundleRef bundle;
-    CFURLRef url;
-
-    bundle = CFBundleGetMainBundle();
-    assert(bundle != NULL);
-
-    url = CFBundleCopyResourcesDirectoryURL(bundle);
-    *path = '-'; 
-    *(path+1) = 'I';
-    assert(CFURLGetFileSystemRepresentation(url, true, (UInt8 *)&path[2],
-		len - 2));
-    CFRelease(url);
-
-    return path;
-}
-
-extern "C"
-int
-macruby_main(const char *path, int argc, char **argv)
-{
-    // Transform the original argv into something like this:
-    // argv[0] = original value
-    // argv[1] = -I/path-to-app-dir/(...)/Resources
-    // argv[2] = main .rb file
-    // argv[3 .. N] = rest of original argv
-
-    char **newargv = (char **)malloc(sizeof(char *) * (argc + 2));
-    newargv[0] = argv[0];
-    
-    char *p1 = (char *)malloc(PATH_MAX);
-    newargv[1] = (char *)resources_path(p1, PATH_MAX);
-    
-    char *p2 = (char *)malloc(PATH_MAX);
-    snprintf(p2, PATH_MAX, "%s/%s", (path[0] != '/') ? &p1[2] : "", path);
-    newargv[2] = p2;
-   
-    int n = 3; 
-    for (int i = 1; i < argc; i++) {
-	if (strncmp(argv[i], "-psn_", 5) != 0) {
-	    newargv[n++] = argv[i];
-	}
-    }
- 
-    argv = newargv;    
-    argc = n;
-
-    unsetenv("RUBYOPT");
-
-    try {
-	ruby_sysinit(&argc, &argv);
-	ruby_init();
-	void *tree = ruby_options(argc, argv);
-	rb_vm_init_compiler();
-	free(newargv);
-	free(p1);
-	free(p2);
-	rb_objc_fix_relocatable_load_path();
-	rb_objc_load_loaded_frameworks_bridgesupport();
-	return ruby_run_node(tree);
-    }
-    catch (...) {
-	rb_vm_print_current_exception();
-	exit(1);	
-    }
-}
-#endif
-
-extern "C"
-void
-Init_VM(void)
-{
-    rb_cTopLevel = rb_define_class("TopLevel", rb_cObject);
-    rb_objc_define_method(rb_cTopLevel, "to_s", (void *)rb_toplevel_to_s, 0);
-    rb_objc_define_method(rb_cTopLevel, "inspect", (void *)rb_toplevel_to_s, 0);
-
-    GET_VM()->set_current_class(NULL);
-
-    VALUE top_self = rb_obj_alloc(rb_cTopLevel);
-    GC_RETAIN(top_self);
-    GET_VM()->set_current_top_object(top_self);
-
-    rb_vm_set_current_scope(rb_cNSObject, SCOPE_PRIVATE);
-}
-
-void
-RoxorVM::setup_from_current_thread(void)
-{
-    pthread_assert(pthread_setspecific(RoxorVM::vm_thread_key, (void *)this));
-
-    rb_vm_thread_t *t = (rb_vm_thread_t *)xmalloc(sizeof(rb_vm_thread_t));
-    rb_vm_thread_pre_init(t, NULL, 0, NULL, (void *)this);
-    t->thread = pthread_self();
-
-    VALUE thread = Data_Wrap_Struct(rb_cThread, NULL, NULL, t);
-    GET_CORE()->register_thread(thread);
-    this->set_thread(thread);
-}
-
-extern "C"
-void
-rb_vm_register_current_alien_thread(void)
-{
-    // The creation of RoxorVM objects is done lazily (in RoxorVM::current())
-    // for performance reason, because the callback is called *a lot* and most
-    // of the time from various parts of the system which will never ask us to
-    // execute Ruby code.
-#if 0
-    if (GET_CORE()->get_running()) {
-	printf("registered alien thread %p\n", pthread_self());
-	RoxorVM *vm = new RoxorVM();
-	vm->setup_from_current_thread();
-    }
-#endif
-}
-
-extern "C"
-void
-rb_vm_unregister_current_alien_thread(void)
-{
-    if (!GET_CORE()->get_running()) {
-	return;
-    }
-
-    pthread_t self = pthread_self();
-    if (GetThreadPtr(RoxorVM::main->get_thread())->thread == self) {
-	// Do not unregister the main thread.
-	return;
-    }
-
-    // Check if the current pthread has been registered.
-    RoxorCoreLock lock;
-    VALUE ary = GET_CORE()->get_threads();
-    bool need_to_unregister = false;
-    for (int i = 0; i < RARRAY_LEN(ary); i++) {
-	VALUE t = RARRAY_AT(ary, i);
-	if (GetThreadPtr(t)->thread == self) {
-	    need_to_unregister = true;
-	}
-    }
-    lock.unlock();
-
-    // If yes, appropriately unregister it.
-    if (need_to_unregister) {
-	//printf("unregistered alien thread %p\n", pthread_self());
-	GET_CORE()->unregister_thread(GET_VM()->get_thread());
-    }
-}
-
-// AOT features. These are registered at runtime once an AOT object file
-// is loaded, either directly from an executable's main() function or from
-// a gcc constructor (in case of a dylib).
-//
-// XXX this shared map is not part of RoxorCore because gcc constructors can
-// potentially be called *before* RoxorCore has been initialized. This is
-// definitely not thread-safe, but it shouldn't be a big deal at this point.
-static std::map<std::string, void *> aot_features;
-
-extern "C"
-bool
-rb_vm_aot_feature_load(const char *name)
-{
-    std::string key(name);
-    std::map<std::string, void *>::iterator iter = aot_features.find(name);
-    if (iter == aot_features.end()) {
-	return false;
-    }
-    void *init_func = iter->second;
-    if (init_func != NULL) {
-        ((void *(*)(void *, void *))init_func)((void *)rb_vm_top_self(), NULL);
-        iter->second = NULL;
-    }
-    return true;
-}
-
-extern "C"
-void
-rb_vm_aot_feature_provide(const char *name, void *init_func)
-{
-    std::string key(name);
-    std::map<std::string, void *>::iterator iter = aot_features.find(key);
-    if (iter != aot_features.end()) {
-	printf("WARNING: AOT feature '%s' already registered, new one will be ignored. This could happen if you link your executable against dylibs that contain the same Ruby file.\n", name);
-    }
-    aot_features[key] = init_func;
-}
-
-extern "C"
-void
-Init_PostVM(void)
-{
-    // Create and register the main thread.
-    RoxorVM *main_vm = GET_VM();
-    main_vm->setup_from_current_thread();
-
-    // Create main thread group.
-    VALUE group = rb_obj_alloc(rb_cThGroup);
-    rb_thgroup_add(group, main_vm->get_thread());
-    rb_define_const(rb_cThGroup, "Default", group);
-}
-
-extern "C"
-void
-rb_vm_finalize(void)
-{
-#if !defined(MACRUBY_STATIC)
-    if (getenv("VM_DUMP_IR") != NULL) {
-	printf("IR dump ----------------------------------------------\n");
-	RoxorCompiler::module->dump();
-	printf("------------------------------------------------------\n");
-    }
-#if ROXOR_VM_DEBUG
-    printf("functions all=%ld compiled=%ld\n", RoxorCompiler::module->size(),
-	    GET_CORE()->get_functions_compiled());
-#endif
-
-    if (getenv("VM_VERIFY_IR") != NULL) {
-	rb_verify_module();
-	printf("IR verified!\n");
-    }
-#endif
-
-    // XXX: deleting the core is not safe at this point because there might be
-    // threads still running and trying to unregister.
-//    delete RoxorCore::shared;
-//    RoxorCore::shared = NULL;
-    GET_CORE()->call_all_finalizers();
-}

Deleted: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/vm.h	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,1224 +0,0 @@
-/*
- * MacRuby VM.
- *
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2008-2011, Apple Inc. All rights reserved.
- */
-
-#ifndef __VM_H_
-#define __VM_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef struct {
-    short min;		// min number of args that we accept
-    short max;		// max number of args that we accept (-1 if rest)
-    short left_req;	// number of args required on the left side
-    short real;		// number of args of the low level function
-} rb_vm_arity_t;
-
-typedef struct rb_vm_local {
-    ID name;
-    VALUE *value;
-    struct rb_vm_local *next;
-} rb_vm_local_t;
-
-#define VM_BLOCK_PROC	(1<<0)	// block is a Proc object
-#define VM_BLOCK_LAMBDA (1<<1)	// block is a lambda
-#define VM_BLOCK_ACTIVE (1<<2)	// block is active (being executed)
-#define VM_BLOCK_METHOD (1<<3)	// block is created from Method
-#define VM_BLOCK_IFUNC  (1<<4)  // block is created from rb_vm_create_block()
-#define VM_BLOCK_EMPTY  (1<<5)	// block has an empty body
-#define VM_BLOCK_THREAD (1<<6)	// block is being executed as a Thread
-#define VM_BLOCK_AOT	(1<<10) // block is created by the AOT compiler
-				// (temporary)
-
-typedef struct rb_vm_block {
-    // IMPORTANT: the flags field should always be at the beginning.
-    // Look at how rb_vm_take_ownership() is called in compiler.cpp.
-    int flags;
-    VALUE proc; // a reference to a Proc object, or nil.
-    VALUE self;
-    VALUE klass;
-    VALUE userdata; // if VM_BLOCK_IFUNC, contains the user data, otherwise
-		    // contains the key used in the blocks cache.
-    rb_vm_arity_t arity;
-    IMP imp;
-    rb_vm_local_t *locals;
-    struct rb_vm_var_uses **parent_var_uses;
-    struct rb_vm_block *parent_block;
-    int dvars_size;
-    // IMPORTANT: do not add fields after dvars, because it would mess with
-    // the way the structure is allocated.
-    VALUE *dvars[1];
-} rb_vm_block_t;
-
-typedef struct rb_vm_binding {
-    VALUE self;
-    rb_vm_block_t *block;
-    rb_vm_local_t *locals;
-    struct rb_vm_binding *next;
-} rb_vm_binding_t;
-
-#define VM_METHOD_EMPTY		1 // method has an empty body (compilation)
-#define VM_METHOD_PRIVATE	2 // method is private (runtime)
-#define VM_METHOD_PROTECTED	4 // method is protected (runtime)
-#define VM_METHOD_FBODY		8 // method has a MRI C prototype (compilation) 
-
-static inline int
-rb_vm_noex_flag(const int noex)
-{
-    switch (noex) {
-	case NOEX_PRIVATE:
-	    return VM_METHOD_PRIVATE;
-	case NOEX_PROTECTED:
-	    return VM_METHOD_PROTECTED;
-	default:
-	case NOEX_PUBLIC:
-	    return 0;
-    }
-}
-
-static inline int
-rb_vm_node_flags(NODE *node)
-{
-    int flags = 0;
-    if (nd_type(node) == NODE_FBODY) {
-	flags |= VM_METHOD_FBODY;
-	if (nd_type(node->nd_body) == NODE_METHOD) {
-	    flags |= rb_vm_noex_flag(node->nd_body->nd_noex);
-	}
-    }
-    if (node->nd_body == NULL) {
-	flags |= VM_METHOD_EMPTY;
-    }
-    return flags;
-}
-
-static inline SEL
-rb_vm_name_to_sel(const char *name, int arity)
-{
-    SEL sel;
-    if (arity > 0 && name[strlen(name) - 1] != ':') {
-	char buf[100];
-	snprintf(buf, sizeof buf, "%s:", name);
-	sel = sel_registerName(buf);
-    }
-    else {
-	sel = sel_registerName(name);
-    }
-    return sel;
-}
-
-static inline SEL
-rb_vm_id_to_sel(ID mid, int arity)
-{
-    return rb_vm_name_to_sel(rb_id2name(mid), arity);
-}
-
-typedef struct rb_vm_method_node {
-    rb_vm_arity_t arity;
-    Class klass;
-    SEL sel;
-    IMP objc_imp;
-    IMP ruby_imp;
-    int flags;
-} rb_vm_method_node_t;
-
-typedef struct {
-    VALUE oclass;
-    VALUE rclass;
-    VALUE recv;
-    SEL sel;
-    int arity;
-    rb_vm_method_node_t *node;	// NULL in case the method is ObjC
-    void *cache;
-} rb_vm_method_t;
-
-#define GetThreadPtr(obj) ((rb_vm_thread_t *)DATA_PTR(obj))
-
-typedef enum {
-    THREAD_ALIVE,  // this thread was born to be alive
-    THREAD_SLEEP,  // this thread is sleeping
-    THREAD_KILLED, // this thread is being killed!
-    THREAD_DEAD    // this thread is dead, sigh
-} rb_vm_thread_status_t;
-
-#include <pthread.h>
-
-#define pthread_assert(cmd) \
-    do { \
-	const int code = cmd; \
-	if (code != 0) { \
-	    printf("pthread command `%s' failed: %s (%d)\n", \
-		#cmd, strerror(code), code); \
-	    abort(); \
-	} \
-    } \
-    while (0)
-
-typedef struct rb_vm_thread {
-    pthread_t thread;
-    rb_vm_block_t *body;
-    int argc;
-    const VALUE *argv;
-    void *vm;		// a C++ instance of RoxorVM
-    VALUE value;
-    pthread_mutex_t sleep_mutex;
-    pthread_cond_t sleep_cond;
-    rb_vm_thread_status_t status;
-    bool in_cond_wait;
-    bool abort_on_exception;	// per-local state, global one is in RoxorCore
-    bool joined_on_exception;
-    VALUE locals;	// a Hash object or Qnil
-    VALUE exception;	// killed-by exception or Qnil 
-    VALUE group;	// always a ThreadGroup object
-    VALUE mutexes;	// an Array object or Qnil
-} rb_vm_thread_t;
-
-typedef struct rb_vm_outer {
-    Class klass;
-    struct rb_vm_outer *outer;
-} rb_vm_outer_t;
-
-typedef struct {
-    jmp_buf buf;
-    VALUE throw_value;
-    int nested;
-} rb_vm_catch_t;
-
-static inline rb_vm_arity_t
-rb_vm_arity(int argc)
-{
-    rb_vm_arity_t arity;
-    arity.left_req = arity.min = arity.max = arity.real = argc;
-    return arity;
-}
-
-static inline int
-rb_vm_arity_n(rb_vm_arity_t arity)
-{
-    int n = arity.min;
-    if (arity.min != arity.max) {
-	n = -n - 1;
-    }
-    return n;
-}
-
-static inline rb_vm_arity_t
-rb_vm_node_arity(NODE *node)
-{
-    const int type = nd_type(node);
-    rb_vm_arity_t arity;
-
-    if (type == NODE_SCOPE) {
-	NODE *n = node->nd_args;
-	short opt_args = 0, req_args = 0;
-	bool has_rest = false;
-	if (n == NULL) {
-	    arity.left_req = 0;
-	}
-	else {
-	    req_args = n->nd_frml;
-	    arity.left_req = req_args;
-	    NODE *n_opt = n->nd_opt;
-	    if (n_opt != NULL) {
-		NODE *ni = n_opt;
-		while (ni != NULL) {
-		    opt_args++;
-		    ni = ni->nd_next;
-		}
-	    }
-	    if (n->nd_next != NULL) {
-		NODE *rest_node = n->nd_next;
-		if (rest_node->nd_rest) {
-		    has_rest = true;
-		}
-		if (rest_node->nd_next) {
-		    req_args += rest_node->nd_next->nd_frml;
-		}
-	    }
-	}
-	arity.min = req_args;
-	if (has_rest) {
-	    arity.max = -1;
-	    arity.real = req_args + opt_args + 1;
-	}
-	else {
-	    arity.max = arity.real = req_args + opt_args;
-	}
-	return arity;
-    }
-
-    if (type == NODE_FBODY) {
-	assert(node->nd_body != NULL);
-	assert(node->nd_body->nd_body != NULL);
-	int argc = node->nd_body->nd_body->nd_argc;
-	if (argc >= 0) {
-	    arity.left_req = arity.real = arity.min = arity.max = argc;
-	}
-	else {
-	    arity.left_req = arity.min = 0;
-	    arity.max = -1;
-	    if (argc == -1) {
-		arity.real = 2;
-	    }
-	    else if (argc == -2) {
-		arity.real = 1;
-	    }
-	    else if (argc == -3) {
-		arity.real = 3;
-	    }
-	    else {
-		printf("invalid FBODY arity: %d\n", argc);
-		abort();
-	    }
-	}
-	return arity; 
-    }
-
-    printf("invalid node %p type %d\n", node, type);
-    abort();
-}
-
-static inline NODE *
-rb_vm_cfunc_node_from_imp(Class klass, int arity, IMP imp, int noex)
-{
-    NODE *node = NEW_CFUNC(imp, arity);
-    return NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
-}
-
-VALUE rb_vm_eval_string(VALUE self, VALUE klass, VALUE src,
-	rb_vm_binding_t *binding, const char *file, const int line);
-VALUE rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
-	bool inside_eval);
-VALUE rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
-	rb_vm_binding_t *binding, bool inside_eval);
-void rb_vm_aot_compile(NODE *node);
-
-void rb_vm_init_compiler(void);
-void rb_vm_init_jit(void);
-
-bool rb_vm_running(void);
-void rb_vm_set_running(bool flag);
-VALUE rb_vm_default_random(void);
-void rb_vm_set_default_random(VALUE rand);
-bool rb_vm_parse_in_eval(void);
-void rb_vm_set_parse_in_eval(bool flag);
-VALUE rb_vm_load_path(void);
-VALUE rb_vm_loaded_features(void);
-VALUE rb_vm_trap_cmd_for_signal(int signal);
-int rb_vm_trap_level_for_signal(int signal);
-void rb_vm_set_trap_for_signal(VALUE trap, int level, int signal);
-int rb_vm_safe_level(void);
-void rb_vm_set_safe_level(int level);
-int rb_vm_thread_safe_level(rb_vm_thread_t *thread);
-VALUE rb_vm_top_self(void);
-void rb_vm_const_is_defined(ID path);
-VALUE rb_vm_resolve_const_value(VALUE val, VALUE klass, ID name);
-
-VALUE rb_vm_const_lookup_level(VALUE outer, uint64_t outer_mask, ID path,
-	bool lexical, bool defined);
-static inline VALUE
-rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined)
-{
-    return rb_vm_const_lookup_level(outer, 0, path, lexical, defined);
-}
-
-bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
-	rb_vm_method_node_t **pnode);
-bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
-	rb_vm_method_node_t **pnode);
-bool rb_vm_is_ruby_method(Method m);
-rb_vm_method_node_t *rb_vm_define_method(Class klass, SEL sel, IMP imp,
-	NODE *node, bool direct);
-rb_vm_method_node_t *rb_vm_define_method2(Class klass, SEL sel,
-	rb_vm_method_node_t *node, long flags, bool direct);
-void rb_vm_define_method3(Class klass, ID mid, rb_vm_block_t *node);
-bool rb_vm_resolve_method(Class klass, SEL sel);
-void *rb_vm_undefined_imp(void *rcv, SEL sel);
-void *rb_vm_removed_imp(void *rcv, SEL sel);
-#define UNAVAILABLE_IMP(imp) \
-    (imp == NULL || imp == (IMP)rb_vm_undefined_imp \
-     || imp == (IMP)rb_vm_removed_imp)
-void rb_vm_define_attr(Class klass, const char *name, bool read, bool write);
-void rb_vm_undef_method(Class klass, ID name, bool must_exist);
-void rb_vm_remove_method(Class klass, ID name);
-void rb_vm_alias(VALUE klass, ID name, ID def);
-bool rb_vm_copy_method(Class klass, Method method);
-void rb_vm_copy_methods(Class from_class, Class to_class);
-VALUE rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv);
-bool rb_vm_respond_to(VALUE obj, SEL sel, bool priv);
-bool rb_vm_respond_to2(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override);
-VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv);
-void rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
-	int (*filter) (VALUE, ID, VALUE));
-void rb_vm_set_outer(VALUE klass, VALUE under);
-VALUE rb_vm_get_outer(VALUE klass);
-VALUE rb_vm_module_nesting(VALUE mod);
-VALUE rb_vm_catch(VALUE tag);
-VALUE rb_vm_throw(VALUE tag, VALUE value);
-
-typedef struct {
-    ID name;
-    VALUE value; 
-} rb_object_ivar_slot_t;
-
-#define SLOT_CACHE_VIRGIN	-2
-#define SLOT_CACHE_CANNOT	-1
-
-#define RB_OBJECT_DEFAULT_NUM_SLOTS	4
-
-typedef struct {
-    struct RBasic basic;
-    rb_object_ivar_slot_t *slots;
-    unsigned int num_slots;
-} rb_object_t;
-
-#define ROBJECT(o) ((rb_object_t *)o)
-
-static inline void
-rb_vm_regrow_robject_slots(rb_object_t *obj, unsigned int new_num_slot)
-{
-    rb_object_ivar_slot_t *new_slots =
-	(rb_object_ivar_slot_t *)xrealloc(obj->slots,
-		sizeof(rb_object_ivar_slot_t) * (new_num_slot + 1));
-    if (new_slots != obj->slots) {
-	GC_WB(&obj->slots, new_slots);
-    }
-
-    unsigned int i;
-    for (i = obj->num_slots; i <= new_num_slot; i++) {
-	obj->slots[i].name = 0;
-	obj->slots[i].value = Qundef;
-    }
-    obj->num_slots = new_num_slot + 1;
-}
-
-int rb_vm_get_ivar_slot(VALUE obj, ID name, bool create);
-
-static inline VALUE
-rb_vm_get_ivar_from_slot(VALUE obj, int slot) 
-{
-    rb_object_t *robj = ROBJECT(obj);
-    return robj->slots[slot].value;
-}
-
-static inline void
-rb_vm_set_ivar_from_slot(VALUE obj, VALUE val, int slot) 
-{
-    rb_object_t *robj = ROBJECT(obj);
-    GC_WB(&robj->slots[slot].value, val);
-}
-
-static inline VALUE
-rb_vm_new_rb_object(VALUE klass)
-{
-    const int num_slots = RB_OBJECT_DEFAULT_NUM_SLOTS;
-
-    rb_object_t *obj = (rb_object_t *)rb_objc_newobj(sizeof(rb_object_t));
-    GC_WB(&obj->slots, xmalloc(sizeof(rb_object_ivar_slot_t) * num_slots));
-
-    OBJSETUP(obj, klass, T_OBJECT);
-    obj->num_slots = num_slots;
-
-    int i;
-    for (i = 0; i < num_slots; i++) {
-	obj->slots[i].name = 0;
-	obj->slots[i].value = Qundef;
-    }
-    return (VALUE)obj;
-}
-
-// Defined in proc.c
-VALUE rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc);
-
-rb_vm_method_t *rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope);
-rb_vm_block_t *rb_vm_create_block_from_method(rb_vm_method_t *method);
-rb_vm_block_t *rb_vm_create_block_calling_mid(ID mid);
-VALUE rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity);
-
-static inline rb_vm_block_t *
-rb_proc_get_block(VALUE proc)
-{
-    return (rb_vm_block_t *)DATA_PTR(proc);
-}
-
-void rb_vm_add_block_lvar_use(rb_vm_block_t *block);
-rb_vm_block_t *rb_vm_create_block(IMP imp, VALUE self, VALUE userdata);
-rb_vm_block_t *rb_vm_current_block(void);
-rb_vm_block_t *rb_vm_first_block(void);
-bool rb_vm_block_saved(void);
-VALUE rb_vm_block_eval(rb_vm_block_t *block, int argc, const VALUE *argv);
-
-rb_vm_block_t *rb_vm_uncache_or_dup_block(rb_vm_block_t *b);
-rb_vm_block_t *rb_vm_dup_block(rb_vm_block_t *b);
-
-static inline void
-rb_vm_block_make_detachable_proc(rb_vm_block_t *b)
-{
-    if (!(b->flags & VM_BLOCK_PROC)) {
-	b->flags |= VM_BLOCK_PROC;
-	if (!(b->flags & VM_BLOCK_METHOD)) {
-	    rb_vm_add_block_lvar_use(b);
-	}
-    }
-}
-
-rb_vm_binding_t *rb_vm_create_binding(VALUE self, rb_vm_block_t *current_block,
-	rb_vm_binding_t *top_binding, int lvars_size, va_list lvars,
-	bool vm_push);
-rb_vm_binding_t *rb_vm_current_binding(void);
-void rb_vm_add_binding(rb_vm_binding_t *binding);
-void rb_vm_pop_binding();
-VALUE rb_binding_new_from_binding(rb_vm_binding_t *binding);
-
-void rb_vm_thread_pre_init(rb_vm_thread_t *t, rb_vm_block_t *body, int argc,
-	const VALUE *argv, void *vm);
-void *rb_vm_create_vm(void);
-void *rb_vm_thread_run(VALUE thread);
-VALUE rb_vm_current_thread(void);
-VALUE rb_vm_main_thread(void);
-VALUE rb_vm_threads(void);
-VALUE rb_vm_thread_locals(VALUE thread, bool create_storage);
-void rb_vm_thread_wakeup(rb_vm_thread_t *t);
-void rb_vm_thread_cancel(rb_vm_thread_t *t);
-void rb_vm_thread_raise(rb_vm_thread_t *t, VALUE exc);
-
-void rb_vm_register_current_alien_thread(void);
-void rb_vm_unregister_current_alien_thread(void);
-
-bool rb_vm_abort_on_exception(void);
-void rb_vm_set_abort_on_exception(bool flag);
-
-Class rb_vm_set_current_class(Class klass);
-Class rb_vm_get_current_class(void);
-
-bool rb_vm_aot_feature_load(const char *name);
-
-bool rb_vm_generate_objc_class_name(const char *name, char *buf,
-	size_t buflen);
-
-void rb_vm_raise(VALUE exception);
-void rb_vm_raise_current_exception(void);
-VALUE rb_vm_current_exception(void);
-void rb_vm_set_current_exception(VALUE exception);
-VALUE rb_vm_backtrace(int skip);
-void rb_vm_print_exception(VALUE exc);
-void rb_vm_print_current_exception(void);
-
-#define TEST_THREAD_CANCEL() (pthread_testcancel())
-
-VALUE rb_vm_get_broken_value(void *vm);
-VALUE rb_vm_returned_from_block(void *_vm, int id);
-
-#define ST_STOP_IF_BROKEN() \
-    do { \
-	VALUE __v = rb_vm_get_broken_value(rb_vm_current_vm()); \
-	if (__v != Qundef) { \
-	    return ST_STOP; \
-	} \
-    } \
-    while (0)
-
-VALUE rb_vm_pop_broken_value(void);
-#define RETURN_IF_BROKEN() \
-    do { \
-	VALUE __v = rb_vm_pop_broken_value(); \
-	if (__v != Qundef) { \
-	    return __v; \
-	} \
-    } \
-    while (0)
-
-#define ENSURE_AND_RETURN_IF_BROKEN(code) \
-    do { \
-        VALUE __v = rb_vm_pop_broken_value(); \
-        if (__v != Qundef) { \
-	    code; \
-            return __v; \
-        } \
-    } \
-    while (0)
-
-static inline void
-rb_vm_release_ownership(VALUE obj)
-{
-    if (!SPECIAL_CONST_P(obj)) {
-	// This function allows the given object's ownership to be transfered
-	// to the current thread. It is used when objects are allocated from a
-	// thread but assigned into another thread's stack, which is prohibited
-	// by the thread-local collector.
-	GC_RETAIN(obj);
-	GC_RELEASE(obj);
-    }
-}
-
-void rb_vm_finalize(void);
-
-void rb_vm_load_bridge_support(const char *path, const char *framework_path,
-	int options);
-
-typedef struct {
-    VALUE klass;
-    VALUE objid;
-    VALUE finalizers;
-} rb_vm_finalizer_t;
-
-void rb_vm_register_finalizer(rb_vm_finalizer_t *finalizer);
-void rb_vm_unregister_finalizer(rb_vm_finalizer_t *finalizer);
-void rb_vm_call_finalizer(rb_vm_finalizer_t *finalizer);
-
-struct icache {
-    VALUE klass;
-    int slot;
-};
-
-struct icache *rb_vm_ivar_slot_allocate(void);
-
-struct ccache {
-    VALUE outer;
-    uint64_t outer_mask;
-    VALUE val;
-};
-
-typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
-	const VALUE *argv);
-typedef VALUE rb_vm_c_stub_t(IMP imp, int argc, const VALUE *argv);
-
-#include "bridgesupport.h"
-#include "compiler.h"
-
-struct mcache {
-#define MCACHE_RCALL 0x1 // Ruby call
-#define MCACHE_OCALL 0x2 // Objective-C call
-#define MCACHE_FCALL 0x4 // C call
-#define MCACHE_SUPER 0x8 // Super call (only applied with RCALL or OCALL)
-    uint8_t flag;
-    SEL sel;
-    Class klass;
-    union {
-	struct {
-	    rb_vm_method_node_t *node;
-	} rcall;
-	struct {
-	    IMP imp;
-	    int argc;
-	    bs_element_method_t *bs_method;	
-	    rb_vm_objc_stub_t *stub;
-	} ocall;
-	struct {
-	    IMP imp;
-	    bs_element_function_t *bs_function;
-	    rb_vm_c_stub_t *stub;
-	} fcall;
-    } as;
-};
-
-#define VM_MCACHE_SIZE	0x1000
-
-VALUE rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
-	Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
-	int argc, const VALUE *argv);
-
-void *rb_vm_current_vm(void) __attribute__((const));
-struct mcache *rb_vm_get_mcache(void *vm) __attribute__((const));
-
-static inline int
-rb_vm_mcache_hash(Class klass, SEL sel)
-{
-    return (((unsigned long)klass >> 3) ^ (unsigned long)sel)
-	& (VM_MCACHE_SIZE - 1);
-}
-
-static inline VALUE
-rb_vm_call0(void *vm, VALUE top, VALUE self, Class klass, SEL sel,
-	rb_vm_block_t *block, unsigned char opt, int argc, const VALUE *argv)
-{
-    int hash = rb_vm_mcache_hash(klass, sel);
-    if (opt & DISPATCH_SUPER) {
-	hash++;
-    }
-    struct mcache *cache = &rb_vm_get_mcache(vm)[hash];
-    return rb_vm_dispatch(vm, cache, top, self, klass, sel, block, opt,
-	    argc, argv);
-}
-
-static inline VALUE
-rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv)
-{
-    return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)CLASS_OF(self), sel,
-	    NULL, DISPATCH_FCALL, argc, argv);
-}
-
-static inline VALUE
-rb_vm_call_super(VALUE self, SEL sel, int argc, const VALUE *argv)
-{
-    return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)CLASS_OF(self), sel,
-	    NULL, DISPATCH_SUPER, argc, argv);
-}
-
-static inline VALUE
-rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc,
-	const VALUE *argv)
-{
-    if (klass == 0) {
-	klass = CLASS_OF(self);
-    }
-    return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)klass, sel, block,
-	    DISPATCH_FCALL, argc, argv);
-}
-
-static inline VALUE
-rb_vm_method_call(rb_vm_method_t *m, rb_vm_block_t *block, int argc,
-	const VALUE *argv)
-{
-    return rb_vm_dispatch(rb_vm_current_vm(), (struct mcache *)m->cache, 0,
-	    m->recv, (Class)m->oclass, m->sel, block, DISPATCH_FCALL,
-	    argc, argv);
-}
-
-VALUE rb_vm_yield_args(void *vm, int argc, const VALUE *argv);
-
-static inline VALUE
-rb_vm_yield(int argc, const VALUE *argv)
-{
-    return rb_vm_yield_args(rb_vm_current_vm(), argc, argv);
-}
-
-#if defined(__cplusplus)
-}
-
-#if !defined(MACRUBY_STATIC)
-typedef struct {
-    Function *func;
-    rb_vm_arity_t arity;
-    int flags;
-} rb_vm_method_source_t;
-#endif
-
-#define rb_vm_long_arity_stub_t rb_vm_objc_stub_t
-typedef VALUE rb_vm_long_arity_bstub_t(IMP imp, id self, SEL sel,
-	VALUE dvars, rb_vm_block_t *b, int argc, const VALUE *argv);
-
-// For rb_vm_define_class()
-#define DEFINE_MODULE		0x1
-#define DEFINE_OUTER 		0x2
-#define DEFINE_SUB_OUTER	0x4
-
-class RoxorCompiler;
-class RoxorJITManager;
-
-#define READER(name, type) \
-    type get_##name(void) { return name; }
-
-#define WRITER(name, type) \
-    void set_##name(type v) { name = v; }
-
-#define ACCESSOR(name, type) \
-    READER(name, type) \
-    WRITER(name, type)
-
-// The Core class is a singleton, it's only created once and it's used by the
-// VMs. All calls to the Core are thread-safe, they acquire a shared lock.
-class RoxorCore {
-    public:
-	static RoxorCore *shared;
-
-    private:
-	// LLVM objects.
-#if !defined(MACRUBY_STATIC)
-	RoxorJITManager *jmm;
-	ExecutionEngine *ee;
-	FunctionPassManager *fpm;
-#endif
-
-	// Running threads.
-	VALUE threads;
-
-	// Finalizers. They are automatically called during garbage collection
-	// but we still need to keep a list of them, because the list may not
-	// be empty when we exit and we need to call the remaining finalizers.
-	std::vector<rb_vm_finalizer_t *> finalizers;
-
-	// The global lock.
-	pthread_mutex_t gl;
-
-	// State.
-	bool interpreter_enabled;
-	bool inlining_enabled;
-	bool optims_enabled;
-	bool running;
-	bool abort_on_exception;
-	VALUE loaded_features;
-	VALUE load_path;
-	VALUE default_random;
-
-	// Signals.
-	std::map<int, VALUE> trap_cmd;
-	std::map<int, int> trap_level;
-
-#if !defined(MACRUBY_STATIC)
-	// Cache to avoid compiling the same Function twice.
-	std::map<Function *, IMP> JITcache;
-#endif
-
-	// Cache to identify pure Ruby implementations / methods.
-	std::map<IMP, rb_vm_method_node_t *> ruby_imps;
-	std::map<Method, rb_vm_method_node_t *> ruby_methods;
-
-	// Constants cache.
-	std::map<ID, struct ccache *> ccache;
-
-	// Outers map (where a class is actually defined).
-	std::map<Class, struct rb_vm_outer *> outers;
-
-#if !defined(MACRUBY_STATIC)
-	// Optimized selectors redefinition cache.
-	std::map<SEL, GlobalVariable *> redefined_ops_gvars;
-
-	// Caches for the lazy JIT.
-	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
-	    method_sources;
-	std::multimap<Class, SEL> method_source_sels;
-#endif
-
-	// Maps to cache compiled stubs for a given Objective-C runtime type.
-	std::map<std::string, void *> c_stubs, objc_stubs,
-	    to_rval_convertors, to_ocval_convertors;
-#if !defined(MACRUBY_STATIC)
-	std::map<IMP, IMP> objc_to_ruby_stubs;
-#endif
-	std::map<int, void *> rb_large_arity_rstubs; // Large arity Ruby calls
-	std::map<int, void *> rb_large_arity_bstubs; // Large arity block calls
-
-	// BridgeSupport caches.
-	bs_parser_t *bs_parser;
-	std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
-	std::map<std::string, bs_element_function_t *> bs_funcs;
-	std::map<ID, bs_element_constant_t *> bs_consts;
-	std::map<std::string, std::map<SEL, bs_element_method_t *> *>
-	    bs_classes_class_methods, bs_classes_instance_methods;
-	std::map<std::string, bs_element_cftype_t *> bs_cftypes;
-	std::map<SEL, std::string *> bs_informal_protocol_imethods,
-	    bs_informal_protocol_cmethods;
-
-	// respond_to? cache.
-#define RESPOND_TO_NOT_EXIST	0
-#define RESPOND_TO_PUBLIC 	1
-#define RESPOND_TO_PRIVATE 	2
-	std::map<long, int> respond_to_cache;
-
-#if ROXOR_VM_DEBUG
-	long functions_compiled;
-#endif
-
-    public:
-	RoxorCore(void);
-	~RoxorCore(void);
-
-	void prepare_jit(void);
-
-	ACCESSOR(running, bool);
-	ACCESSOR(abort_on_exception, bool);
-	ACCESSOR(default_random, VALUE);
-	READER(interpreter_enabled, bool);
-	READER(loaded_features, VALUE);
-	READER(load_path, VALUE);
-	READER(threads, VALUE);
-
-#if ROXOR_VM_DEBUG
-	READER(functions_compiled, long);
-#endif
-
-	// signals
-	void set_trap_for_signal(VALUE trap, int level, int signal);
-	VALUE trap_cmd_for_signal(int signal);
-	int trap_level_for_signal(int signal);
-
-	void lock(void) { 
-	    assert(pthread_mutex_lock(&gl) == 0);
-	}
-	void unlock(void) {
-	    assert(pthread_mutex_unlock(&gl) == 0);
-	}
-
-	void register_thread(VALUE thread);
-	void unregister_thread(VALUE thread);
-
-#if !defined(MACRUBY_STATIC)
-	void optimize(Function *func);
-	IMP compile(Function *func, bool optimize=true);
-	void delenda(Function *func);
-
-	void load_bridge_support(const char *path, const char *framework_path,
-		int options);
-#endif
-
-	bs_element_constant_t *find_bs_const(ID name);
-	bs_element_method_t *find_bs_method(Class klass, SEL sel);
-	rb_vm_bs_boxed_t *find_bs_boxed(std::string type);
-	rb_vm_bs_boxed_t *find_bs_struct(std::string type);
-	rb_vm_bs_boxed_t *find_bs_opaque(std::string type);
-	bs_element_cftype_t *find_bs_cftype(std::string type);
-	std::string *find_bs_informal_protocol_method(SEL sel,
-		bool class_method);
-	bs_element_function_t *find_bs_function(std::string &name);
-
-	// This callback is public for the only reason it's called by C.
-	void bs_parse_cb(bs_element_type_t type, void *value, void *ctx);
-
-	void insert_stub(const char *types, void *stub, bool is_objc) {
-	    std::map<std::string, void *> &m =
-		is_objc ? objc_stubs : c_stubs;
-	    m.insert(std::make_pair(types, stub));
-	}
-
-	void *gen_large_arity_stub(int argc, bool is_block=false);
-	void *gen_stub(std::string types, bool variadic, int min_argc,
-		bool is_objc);
-	void *gen_to_rval_convertor(std::string type);
-	void *gen_to_ocval_convertor(std::string type);
-
-#if !defined(MACRUBY_STATIC)
-	std::map<Class, rb_vm_method_source_t *> *
-	method_sources_for_sel(SEL sel, bool create) {
-	    std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator
-		iter = method_sources.find(sel);
-		
-	    std::map<Class, rb_vm_method_source_t *> *map = NULL;
-	    if (iter == method_sources.end()) {
-		if (!create) {
-		    return NULL;
-		}
-		map = new std::map<Class, rb_vm_method_source_t *>();
-		method_sources[sel] = map;
-	    }
-	    else {
-		map = iter->second;
-	    }
-	    return map;
-	}
-#endif
-
-	bool symbolize_call_address(void *addr, char *path, size_t path_len,
-		unsigned long *ln, char *name, size_t name_len,
-		unsigned int *interpreter_frame_idx);
-
-	void symbolize_backtrace_entry(int index, char *path, size_t path_len, 
-		unsigned long *ln, char *name, size_t name_len);
-
-	void invalidate_method_cache(SEL sel);
-	rb_vm_method_node_t *method_node_get(IMP imp, bool create=false);
-	rb_vm_method_node_t *method_node_get(Method m, bool create=false);
-
-#if !defined(MACRUBY_STATIC)
-	rb_vm_method_source_t *method_source_get(Class klass, SEL sel);
-
-	void prepare_method(Class klass, SEL sel, Function *func,
-		const rb_vm_arity_t &arity, int flag);
-	bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
-		Class klass, SEL sel);
-#endif
-	rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
-		void *func, const rb_vm_arity_t &arity, int flags,
-		IMP imp, Method m, void *objc_imp_types);
-	rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
-		IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
-		const char *types);
-	rb_vm_method_node_t *retype_method(Class klass,
-		rb_vm_method_node_t *node, const char *old_types,
-		const char *new_types);
-	void undef_method(Class klass, SEL sel);
-	void remove_method(Class klass, SEL sel);
-	bool copy_method(Class klass, Method m);
-	void copy_methods(Class from_class, Class to_class);
-	void get_methods(VALUE ary, Class klass, bool include_objc_methods,
-		int (*filter) (VALUE, ID, VALUE));
-	void method_added(Class klass, SEL sel);
-
-#if !defined(MACRUBY_STATIC)
-	GlobalVariable *redefined_op_gvar(SEL sel, bool create);
-#endif
-	bool should_invalidate_inline_op(SEL sel, Class klass);
-
-	struct ccache *constant_cache_get(ID path);
-	void const_defined(ID path);
-	
-	struct rb_vm_outer *get_outer(Class klass);
-	void set_outer(Class klass, Class mod);
-
-#if !defined(MACRUBY_STATIC)
-	size_t get_sizeof(const Type *type);
-	size_t get_sizeof(const char *type);
-	bool is_large_struct_type(const Type *type);
-#endif
-
-	void register_finalizer(rb_vm_finalizer_t *finalizer);
-	void unregister_finalizer(rb_vm_finalizer_t *finalizer);
-	void call_all_finalizers(void);
-
-	long respond_to_key(Class klass, SEL sel) {
-	    return (long)klass + (long)sel;
-	}
-	void invalidate_respond_to_cache(void) {
-	    respond_to_cache.clear();
-	}
-	bool respond_to(VALUE obj, VALUE klass, SEL sel, bool priv,
-		bool check_override);
-
-	void debug_outers(Class k);
-
-    private:
-	bool register_bs_boxed(bs_element_type_t type, void *value);
-	void register_bs_class(bs_element_class_t *bs_class);
-	rb_vm_bs_boxed_t *register_anonymous_bs_struct(const char *type);
-};
-
-#define GET_CORE() (RoxorCore::shared)
-
-typedef enum {
-    METHOD_MISSING_DEFAULT = 0,
-    METHOD_MISSING_PRIVATE,
-    METHOD_MISSING_PROTECTED,
-    METHOD_MISSING_VCALL,
-    METHOD_MISSING_SUPER
-} rb_vm_method_missing_reason_t;
-
-// MacRuby doesn't compile with rtti so we make our own.
-#define CATCH_THROW_EXCEPTION		1
-#define RETURN_FROM_BLOCK_EXCEPTION	2
-#define THREAD_RAISE_EXCEPTION		3
-
-class RoxorSpecialException {
-    public:
-	int type;
-
-	RoxorSpecialException(int _type) { type = _type; }
-};
-
-// Custom C++ exception class used to implement catch/throw.
-class RoxorCatchThrowException : public RoxorSpecialException {
-    public:
-	VALUE throw_symbol;
-	VALUE throw_value;
-
-	RoxorCatchThrowException()
-	    : RoxorSpecialException(CATCH_THROW_EXCEPTION) {}
-};
-
-// Custom C++ exception class used to implement "return-from-block".
-class RoxorReturnFromBlockException : public RoxorSpecialException {
-    public:
-	VALUE val;
-	int id;
-
-	RoxorReturnFromBlockException()
-	    : RoxorSpecialException(RETURN_FROM_BLOCK_EXCEPTION) {}
-};
-
-// Custom C++ exception class used to implement thread cancelation.
-class RoxorThreadRaiseException : public RoxorSpecialException {
-    public:
-	RoxorThreadRaiseException()
-	    : RoxorSpecialException(THREAD_RAISE_EXCEPTION) {}
-};
-
-// The VM class is instantiated per thread. There is always at least one
-// instance. The VM class is purely thread-safe and concurrent, it does not
-// acquire any lock, except when it calls the Core.
-class RoxorVM {
-    public:
-	// The main VM object.
-	static RoxorVM *main;
-
-	// The pthread specific key to retrieve the current VM thread.
-	static pthread_key_t vm_thread_key;
-
-	static force_inline RoxorVM *current(void) {
-	    void *vm = pthread_getspecific(vm_thread_key);
-	    if (vm == NULL) {
-		// The value does not exist yet, which means we are called
-		// from a thread that was not created by MacRuby directly
-		// (potentially the GC thread or Cocoa). In this case, we
-		// create a new VM object just for this thread.
-		RoxorVM *new_vm = new RoxorVM();
-		new_vm->setup_from_current_thread();
-		return new_vm;
-	    }
-	    return (RoxorVM *)vm;
-	}
-
-    private:
-	// Cache to avoid allocating the same block twice.
-	std::map<void *, rb_vm_block_t *> blocks;
-
-	// Keeps track of the current VM state (blocks, exceptions, bindings).
-	std::vector<rb_vm_block_t *> current_blocks;
-	std::vector<VALUE> current_exceptions;
-	std::vector<rb_vm_binding_t *> bindings;
-	std::map<VALUE, int *> catch_nesting;
-	std::vector<VALUE> recursive_objects;
-
-	// Method cache.
-	struct mcache *mcache;
-
-	VALUE thread;
-	Class current_class;
-	VALUE current_top_object;
-	VALUE backref;
-	VALUE broken_with;
-	VALUE last_line;
-	VALUE last_status;
-	VALUE errinfo;
-	int safe_level;
-	rb_vm_method_missing_reason_t method_missing_reason;
-	bool parse_in_eval;
-	bool has_ensure;
-	int return_from_block;
-	Class current_super_class;
-	SEL current_super_sel;
-	VALUE current_mri_method_self;
-	SEL current_mri_method_sel;
-
-	RoxorSpecialException *special_exc;
-
-	void increase_nesting_for_tag(VALUE tag);
-	void decrease_nesting_for_tag(VALUE tag);
-
-    public:
-	RoxorVM(void);
-	RoxorVM(const RoxorVM &vm);
-	~RoxorVM(void);
-
-	ACCESSOR(thread, VALUE);
-	ACCESSOR(current_class, Class);
-	ACCESSOR(current_top_object, VALUE);
-	ACCESSOR(backref, VALUE);
-	ACCESSOR(broken_with, VALUE);
-	ACCESSOR(last_line, VALUE);
-	ACCESSOR(last_status, VALUE);
-	ACCESSOR(errinfo, VALUE);
-	ACCESSOR(safe_level, int);
-	ACCESSOR(method_missing_reason, rb_vm_method_missing_reason_t);
-	ACCESSOR(parse_in_eval, bool);
-	ACCESSOR(has_ensure, bool);
-	ACCESSOR(return_from_block, int);
-	ACCESSOR(special_exc, RoxorSpecialException *);
-	ACCESSOR(current_super_class, Class);
-	ACCESSOR(current_super_sel, SEL);
-	READER(mcache, struct mcache *);
-	ACCESSOR(current_mri_method_self, VALUE);
-	ACCESSOR(current_mri_method_sel, SEL);
-
-	void debug_blocks(void);
-
-	bool is_block_current(rb_vm_block_t *b) {
-	    return b == NULL
-		? false
-		: current_blocks.empty()
-		? false
-		: current_blocks.back() == b;
-	}
-
-	void add_current_block(rb_vm_block_t *b) {
-	    current_blocks.push_back(b);
-	}
-
-	void pop_current_block(void) {
-	    assert(!current_blocks.empty());
-	    current_blocks.pop_back();
-	}
-
-	rb_vm_block_t *current_block(void) {
-	    return current_blocks.empty()
-		? NULL : current_blocks.back();
-	}
-
-	rb_vm_block_t *previous_block(void) {
-	    if (current_blocks.size() > 1) {
-		return current_blocks[current_blocks.size() - 2];
-	    }
-	    return NULL;
-	}
-
-	rb_vm_block_t *first_block(void) {
-	    rb_vm_block_t *b = current_block();
-	    if (b == NULL) {
-		b = previous_block();
-	    }
-	    return b;
-	}
-
-	rb_vm_block_t *uncache_or_create_block(void *key, bool *cached,
-		int dvars_size);
-	rb_vm_block_t *uncache_or_dup_block(rb_vm_block_t *b);
-
-	rb_vm_binding_t *current_binding(void) {
-	    return bindings.empty()
-		? NULL : bindings.back();
-	}
-
-	rb_vm_binding_t *get_binding(unsigned int index) {
-	    if (!bindings.empty()) {
-		if (index < bindings.size()) {
-		    return bindings[index];
-		}
-	    }
-	    return NULL;
-	}
-
-	void push_current_binding(rb_vm_binding_t *binding) {
-	    GC_RETAIN(binding);
-	    bindings.push_back(binding);
-	}
-
-	void pop_current_binding() {
-	    if (!bindings.empty()) {
-		GC_RELEASE(bindings.back());
-		bindings.pop_back();
-	    }
-	}
-
-	void debug_exceptions(void);
-
-	VALUE current_exception(void) {
-	    return current_exceptions.empty()
-		? Qnil : current_exceptions.back();
-	}
-
-	void push_current_exception(VALUE exc);
-	void pop_current_exception(int pos=0);
-
-	VALUE *get_binding_lvar(ID name, bool create);
-
-	VALUE ruby_catch(VALUE tag);
-	VALUE ruby_throw(VALUE tag, VALUE value);
-
-	VALUE pop_broken_with(void) {
-	    VALUE val = broken_with;
-	    if (return_from_block == -1) {
-		GC_RELEASE(val);
-		broken_with = Qundef;
-	    }
-	    return val;
-	}
-
-	void setup_from_current_thread(void);
-
-	VALUE exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj,
-		VALUE arg);
-};
-
-#define GET_VM() (RoxorVM::current())
-#define GET_THREAD() (GetThreadPtr(GET_VM()->get_thread()))
-
-#endif /* __cplusplus */
-
-#define not_implemented_in_static(s) \
-    rb_raise(rb_eRuntimeError, "%s: not supported in static compilation", sel_getName(s))
-
-#endif /* __VM_H_ */

Deleted: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/vm_eval.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,797 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-#include "macruby_internal.h"
-#include "ruby/node.h"
-#include "ruby/st.h"
-#include "vm.h"
-#include "objc.h"
-#include "id.h"
-#include "class.h"
-
-#include "vm_method.c"
-
-static inline VALUE
-rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope,
-	bool pass_current_block)
-{
-    SEL sel;
-    if (mid == ID_ALLOCATOR) {
-	sel = selAlloc;
-    }
-    else {
-	sel = rb_vm_id_to_sel(mid, argc);
-    }
-    rb_vm_block_t *block = pass_current_block ? rb_vm_current_block() : NULL;
-    return rb_vm_call2(block, recv, CLASS_OF(recv), sel, argc, argv);
-}
-
-/*
- *  call-seq:
- *     obj.method_missing(symbol [, *args] )   => result
- *
- *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
- *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
- *  are any arguments that were passed to it. By default, the interpreter
- *  raises an error when this method is called. However, it is possible
- *  to override the method to provide more dynamic behavior.
- *  If it is decided that a particular method should not be handled, then
- *  <i>super</i> should be called, so that ancestors can pick up the
- *  missing method.
- *  The example below creates
- *  a class <code>Roman</code>, which responds to methods with names
- *  consisting of roman numerals, returning the corresponding integer
- *  values.
- *
- *     class Roman
- *       def romanToInt(str)
- *         # ...
- *       end
- *       def method_missing(methId)
- *         str = methId.id2name
- *         romanToInt(str)
- *       end
- *     end
- *
- *     r = Roman.new
- *     r.iv      #=> 4
- *     r.xxiii   #=> 23
- *     r.mm      #=> 2000
- */
-
-static VALUE
-rb_method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv)
-{
-    return rb_vm_method_missing(obj, argc, argv);
-}
-
-VALUE
-rb_apply(VALUE recv, ID mid, VALUE args)
-{
-    int argc;
-    VALUE *argv;
-
-    argc = RARRAY_LEN(args);	/* Assigns LONG, but argc is INT */
-    argv = ALLOCA_N(VALUE, argc);
-    MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
-    return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
-}
-
-VALUE
-rb_funcall(VALUE recv, ID mid, int n, ...)
-{
-    VALUE *argv;
-    va_list ar;
-    va_start(ar, n);
-
-    if (n > 0) {
-	long i;
-
-	argv = ALLOCA_N(VALUE, n);
-
-	for (i = 0; i < n; i++) {
-	    argv[i] = va_arg(ar, VALUE);
-	}
-	va_end(ar);
-    }
-    else {
-	argv = 0;
-    }
-    return rb_call(recv, mid, n, argv, CALL_FCALL, false);
-}
-
-VALUE
-rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
-}
-
-VALUE
-rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(recv, mid, argc, argv, CALL_PUBLIC, false);
-}
-
-static VALUE
-send_internal(int argc, VALUE *argv, VALUE recv, int scope)
-{
-    VALUE vid;
-
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "no method name given");
-    }
-
-    vid = *argv++; argc--;
-    return rb_call(recv, rb_to_id(vid), argc, argv, scope, true);
-}
-
-/*
- *  call-seq:
- *     obj.send(symbol [, args...])        => obj
- *     obj.__send__(symbol [, args...])      => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. You can use <code>__send__</code> if the name
- *  +send+ clashes with an existing method in _obj_.
- *
- *     class Klass
- *       def hello(*args)
- *         "Hello " + args.join(' ')
- *       end
- *     end
- *     k = Klass.new
- *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
- */
-
-static VALUE
-rb_f_send(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
-}
-
-/*
- *  call-seq:
- *     obj.public_send(symbol [, args...])  => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. Unlike send, public_send calls public
- *  methods only.
- *
- *     1.public_send(:puts, "hello")  # causes NoMethodError
- */
-
-static VALUE
-rb_f_public_send(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return send_internal(argc, argv, recv, NOEX_PUBLIC);
-}
-
-/* yield */
-
-VALUE
-rb_yield(VALUE val)
-{
-    if (val == Qundef) {
-        return rb_vm_yield(0, NULL);
-    }
-    return rb_vm_yield(1, &val);
-}
-
-VALUE
-rb_yield_values2(int argc, const VALUE *argv)
-{
-    return rb_vm_yield(argc, argv);
-}
-
-VALUE
-rb_yield_values(int n, ...)
-{
-    if (n == 0) {
-	return rb_vm_yield(0, 0);
-    }
-    else {
-	int i;
-	VALUE *argv;
-	va_list args;
-	argv = ALLOCA_N(VALUE, n);
-
-	va_start(args, n);
-	for (i=0; i<n; i++) {
-	    argv[i] = va_arg(args, VALUE);
-	}
-	va_end(args);
-
-	return rb_vm_yield(n, argv);
-    }
-}
-
-VALUE
-rb_yield_splat(VALUE values)
-{
-    VALUE tmp = rb_check_array_type(values);
-    if (NIL_P(tmp)) {
-        rb_raise(rb_eArgError, "not an array");
-    }
-    return rb_vm_yield(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
-}
-
-static VALUE
-loop_i(void)
-{
-    int count = 0;
-    for (;;) {
-	rb_yield(Qundef);
-	RETURN_IF_BROKEN();
-	if (++count >= 100) {
-	    TEST_THREAD_CANCEL();
-	    count = 0;
-	}
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     loop {|| block }
- *
- *  Repeatedly executes the block.
- *
- *     loop do
- *       print "Input: "
- *       line = gets
- *       break if !line or line =~ /^qQ/
- *       # ...
- *     end
- *
- *  StopIteration raised in the block breaks the loop.
- */
-
-static VALUE
-rb_f_loop(VALUE rcv, SEL sel)
-{
-    RETURN_ENUMERATOR(rcv, 0, 0);
-    return rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
-}
-
-VALUE
-rb_objc_block_call(VALUE obj, SEL sel, int argc, VALUE *argv,
-	VALUE (*bl_proc) (ANYARGS), VALUE data2)
-{
-    rb_vm_block_t *b = rb_vm_create_block((IMP)bl_proc, obj, data2);
-    return rb_vm_call2(b, obj, 0, sel, argc, argv);
-}
-
-VALUE
-rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv,
-	VALUE (*bl_proc) (ANYARGS), VALUE data2)
-{
-    SEL sel = rb_vm_id_to_sel(mid, argc);
-    return rb_objc_block_call(obj, sel, argc, argv, bl_proc, data2);
-}
-
-VALUE
-rb_each(VALUE obj)
-{
-    return rb_call(obj, idEach, 0, 0, CALL_FCALL, false);
-}
-
-VALUE
-rb_vm_eval_string(VALUE self, VALUE klass, VALUE src, rb_vm_binding_t *binding,
-	const char *file, const int line)
-{
-#if MACRUBY_STATIC
-    rb_raise(rb_eRuntimeError,
-	    "evaluating strings is not supported in MacRuby static");
-#else
-    bool old_parse_in_eval = rb_vm_parse_in_eval();
-    rb_vm_set_parse_in_eval(true);
-    if (binding != NULL) {
-	// Binding must be added because the parser needs it.
-	rb_vm_add_binding(binding);
-    }
-
-    NODE *node = rb_compile_string(file, src, line);
-
-    if (binding != NULL) {
-	// We remove the binding now but we still pass it to the VM, which
-	// will use it for compilation.
-	rb_vm_pop_binding();
-    }
-    rb_vm_set_parse_in_eval(old_parse_in_eval);
-
-    if (node == NULL) {
-	VALUE exc = rb_vm_current_exception();
-	if (exc != Qnil) {
-	    rb_vm_raise_current_exception();
-	}
-	else {
-	    rb_raise(rb_eSyntaxError, "compile error");
-	}
-    }
-
-    return rb_vm_run_under(klass, self, file, node, binding, true);
-#endif
-}
-
-#define GetBindingPtr(obj) ((rb_vm_binding_t *)DATA_PTR(obj))
-
-static VALUE
-eval_string(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file,
-	    const int line)
-{
-    rb_vm_binding_t *binding = NULL;
-    if (scope != Qnil) {
-	if (!rb_obj_is_kind_of(scope, rb_cBinding)) {
-	    rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)",
-		     rb_obj_classname(scope));
-	}
-	binding = GetBindingPtr(scope);
-    }
-    return rb_vm_eval_string(self, klass, src, binding, file, line);
-}
-
-static VALUE
-specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
-{
-    VALUE retval;
-
-    // XXX: not exception-safe
-    const long old_version = RCLASS_VERSION(klass);
-
-    if (rb_block_given_p()) {
-        if (argc > 0) {
-            rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
-		    argc);
-        }
-	rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
-        retval = rb_vm_yield_under(klass, self, 0, NULL);
-    }
-    else {
-	const char *file = "(eval)";
-	int line = 1;
-
-        if (argc == 0) {
-            rb_raise(rb_eArgError, "block not supplied");
-        }
-	if (rb_safe_level() >= 4) {
-	    StringValue(argv[0]);
-	}
-	else {
-	    SafeStringValue(argv[0]);
-	}
-	if (argc > 3) {
-	    const char *name = rb_id2name(rb_frame_callee());
-	    rb_raise(rb_eArgError,
-		    "wrong number of arguments: %s(src) or %s{..}",
-		    name, name);
-	}
-	if (argc > 2) {
-	    line = NUM2INT(argv[2]);
-	}
-	if (argc > 1) {
-	    file = StringValuePtr(argv[1]);
-	}
-	rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
-	retval = eval_string(self, klass, argv[0], Qnil, file, line);
-    }
-
-    RCLASS_SET_VERSION(klass, old_version);
-
-    return retval;
-}
-
-/*
- *  call-seq:
- *     eval(string [, binding [, filename [,lineno]]])  => obj
- *
- *  Evaluates the Ruby expression(s) in <em>string</em>. If
- *  <em>binding</em> is given, the evaluation is performed in its
- *  context. The binding may be a <code>Binding</code> object or a
- *  <code>Proc</code> object. If the optional <em>filename</em> and
- *  <em>lineno</em> parameters are present, they will be used when
- *  reporting syntax errors.
- *
- *     def getBinding(str)
- *       return binding
- *     end
- *     str = "hello"
- *     eval "str + ' Fred'"                      #=> "hello Fred"
- *     eval "str + ' Fred'", getBinding("bye")   #=> "bye Fred"
- */
-
-VALUE
-rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE src, scope, vfile, vline;
-    const char *file = "(eval)";
-    int line = 1;
-
-    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
-    if (rb_safe_level() >= 4) {
-	StringValue(src);
-	if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
-	    rb_raise(rb_eSecurityError,
-		     "Insecure: can't modify trusted binding");
-	}
-    }
-    else {
-	SafeStringValue(src);
-    }
-    if (argc >= 3) {
-	StringValue(vfile);
-    }
-    if (argc >= 4) {
-	line = NUM2INT(vline);
-    }
-    if (!NIL_P(vfile)) {
-	file = RSTRING_PTR(vfile);
-    }
-    VALUE klass;
-    switch (TYPE(self)) {
-	case T_CLASS:
-	case T_MODULE:
-	    klass = self;
-	    break;
-	default:
-	    klass = 0;
-	    break;
-    }
-#if 0
-    if (!NIL_P(scope)) {
-	rb_vm_binding_t *t = rb_vm_current_binding();
-	assert(t != NULL);
-	rb_vm_binding_t *tmp = rb_vm_create_binding(t->self,
-		t->block, GetBindingPtr(scope), 0, NULL, false);
-	GC_WB(&tmp->locals, t->locals);
-	scope = rb_binding_new_from_binding(tmp);
-    }
-#endif
-    return eval_string(self, klass, src, scope, file, line);
-}
-
-VALUE
-rb_eval_string(const char *str)
-{
-    return eval_string(rb_vm_top_self(), 0, rb_str_new2(str), Qnil, "(eval)", 1);
-}
-
-VALUE
-rb_eval_cmd(VALUE cmd, VALUE arg, int level)
-{
-    VALUE val = Qnil;		/* OK */
-    volatile int safe = rb_safe_level();
-
-    if (OBJ_TAINTED(cmd)) {
-	level = 4;
-    }
-
-    if (TYPE(cmd) != T_STRING) {
-	rb_set_safe_level_force(level);
-	val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
-		RARRAY_PTR(arg));
-	rb_set_safe_level_force(safe);
-	return val;
-    }
-
-    val = eval_string(0, rb_vm_top_self(), cmd, Qnil, "(eval)", 1);
-    rb_set_safe_level_force(safe);
-    return val;
-}
-
-/*
- *  call-seq:
- *     obj.instance_eval(string [, filename [, lineno]] )   => obj
- *     obj.instance_eval {| | block }                       => obj
- *
- *  Evaluates a string containing Ruby source code, or the given block,
- *  within the context of the receiver (_obj_). In order to set the
- *  context, the variable +self+ is set to _obj_ while
- *  the code is executing, giving the code access to _obj_'s
- *  instance variables. In the version of <code>instance_eval</code>
- *  that takes a +String+, the optional second and third
- *  parameters supply a filename and starting line number that are used
- *  when reporting compilation errors.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_eval { @secret }   #=> 99
- */
-
-static VALUE
-rb_obj_instance_eval_imp(VALUE self, SEL sel, VALUE top, int argc, VALUE *argv)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self) || CLASS_OF(self) == rb_cSymbol) {
-	klass = 0;
-    }
-    else {
-	klass = rb_singleton_class(self);
-	if (top != Qundef) {
-	    switch (TYPE(top)) {
-		case T_CLASS:
-		case T_MODULE:
-		    rb_vm_set_outer(klass, top);
-		    break;
-	    }
-	}
-    }
-    return specific_eval(argc, argv, klass, self);
-}
-
-VALUE
-rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
-{
-    // XXX: does not honor top context variable, so certain const lookups
-    // might fail.
-    return rb_obj_instance_eval_imp(self, 0, Qundef, argc, argv);
-}
-
-/*
- *  call-seq:
- *     obj.instance_exec(arg...) {|var...| block }                       => obj
- *
- *  Executes the given block within the context of the receiver
- *  (_obj_). In order to set the context, the variable +self+ is set
- *  to _obj_ while the code is executing, giving the code access to
- *  _obj_'s instance variables.  Arguments are passed as block parameters.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_exec(5) {|x| @secret+x }   #=> 104
- */
-
-static VALUE
-rb_obj_instance_exec(VALUE self, SEL sel, int argc, VALUE *argv)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self)) {
-	klass = 0;
-    }
-    else {
-	klass = rb_singleton_class(self);
-    }
-    if (!rb_block_given_p()) {
-	rb_raise(rb_eLocalJumpError, "no block given");
-    }
-    return rb_vm_yield_under(klass, self, argc, argv);
-}
-
-/*
- *  call-seq:
- *     mod.class_eval(string [, filename [, lineno]])  => obj
- *     mod.module_eval {|| block }                     => obj
- *
- *  Evaluates the string or block in the context of _mod_. This can
- *  be used to add methods to a class. <code>module_eval</code> returns
- *  the result of evaluating its argument. The optional _filename_
- *  and _lineno_ parameters set the text for error messages.
- *
- *     class Thing
- *     end
- *     a = %q{def hello() "Hello there!" end}
- *     Thing.module_eval(a)
- *     puts Thing.new.hello()
- *     Thing.module_eval("invalid code", "dummy", 123)
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- *     dummy:123:in `module_eval': undefined local variable
- *         or method `code' for Thing:Class
- */
-
-VALUE
-rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return specific_eval(argc, argv, mod, mod);
-}
-
-/*
- *  call-seq:
- *     mod.module_exec(arg...) {|var...| block }       => obj
- *     mod.class_exec(arg...) {|var...| block }        => obj
- *
- *  Evaluates the given block in the context of the class/module.
- *  The method defined in the block will belong to the receiver.
- *
- *     class Thing
- *     end
- *     Thing.class_exec{
- *       def hello() "Hello there!" end
- *     }
- *     puts Thing.new.hello()
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- */
-
-VALUE
-rb_mod_module_exec(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    return rb_vm_yield_under(mod, mod, argc, argv);
-}
-
-/*
- *  call-seq:
- *     throw(symbol [, obj])
- *
- *  Transfers control to the end of the active +catch+ block
- *  waiting for _symbol_. Raises +NameError+ if there
- *  is no +catch+ block for the symbol. The optional second
- *  parameter supplies a return value for the +catch+ block,
- *  which otherwise defaults to +nil+. For examples, see
- *  <code>Kernel::catch</code>.
- */
-
-static VALUE
-rb_f_throw(VALUE rcv, SEL sel, int argc, VALUE *argv)
-{
-    VALUE tag, value;
-
-    rb_scan_args(argc, argv, "11", &tag, &value);
-   
-    return rb_vm_throw(tag, value);
-}
-
-void
-rb_throw(const char *tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = ID2SYM(rb_intern(tag));
-    argv[1] = val;
-    rb_f_throw(Qnil, 0, 2, argv);
-}
-
-void
-rb_throw_obj(VALUE tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = tag;
-    argv[1] = val;
-    rb_f_throw(Qnil, 0, 2, argv);
-}
-
-/*
- *  call-seq:
- *     catch(symbol) {| | block }  > obj
- *
- *  +catch+ executes its block. If a +throw+ is
- *  executed, Ruby searches up its stack for a +catch+ block
- *  with a tag corresponding to the +throw+'s
- *  _symbol_. If found, that block is terminated, and
- *  +catch+ returns the value given to +throw+. If
- *  +throw+ is not called, the block terminates normally, and
- *  the value of +catch+ is the value of the last expression
- *  evaluated. +catch+ expressions may be nested, and the
- *  +throw+ call need not be in lexical scope.
- *
- *     def routine(n)
- *       puts n
- *       throw :done if n <= 0
- *       routine(n-1)
- *     end
- *
- *
- *     catch(:done) { routine(3) }
- *
- *  <em>produces:</em>
- *
- *     3
- *     2
- *     1
- *     0
- */
-
-static VALUE
-rb_f_catch(VALUE rcv, SEL sel, VALUE tag)
-{
-    return rb_vm_catch(tag);
-}
-
-/*
- *  call-seq:
- *     caller(start=1)    => array
- *
- *  Returns the current execution stack---an array containing strings in
- *  the form ``<em>file:line</em>'' or ``<em>file:line: in
- *  `method'</em>''. The optional _start_ parameter
- *  determines the number of initial stack entries to omit from the
- *  result.
- *
- *     def a(skip)
- *       caller(skip)
- *     end
- *     def b(skip)
- *       a(skip)
- *     end
- *     def c(skip)
- *       b(skip)
- *     end
- *     c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
- *     c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
- *     c(2)   #=> ["prog:8:in `c'", "prog:12"]
- *     c(3)   #=> ["prog:13"]
- */
-
-static VALUE
-rb_f_caller(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE level;
-    rb_scan_args(argc, argv, "01", &level);
-
-    int lev;
-    if (NIL_P(level)) {
-	lev = 1;
-    }
-    else {
-	lev = NUM2INT(level);
-    }
-
-    if (lev < 0) {
-	rb_raise(rb_eArgError, "negative level (%d)", lev);
-    }
-
-    return rb_vm_backtrace(lev);
-}
-
-void
-rb_backtrace(void)
-{
-    VALUE ary = rb_vm_backtrace(0);
-    for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
-	printf("\tfrom %s\n", RSTRING_PTR(RARRAY_AT(ary, i)));
-    }
-}
-
-VALUE
-rb_make_backtrace(void)
-{
-    return rb_vm_backtrace(0);
-}
-
-void
-Init_vm_eval(void)
-{
-    rb_objc_define_module_function(rb_mKernel, "catch", rb_f_catch, 1);
-    rb_objc_define_module_function(rb_mKernel, "throw", rb_f_throw, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "loop", rb_f_loop, 0);
-
-    rb_objc_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval_imp, -3);
-    rb_objc_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
-    rb_objc_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
-    rb_objc_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
-
-    rb_objc_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_imp, -3);
-    rb_objc_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
-    rb_objc_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
-    rb_objc_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
-
-    rb_objc_define_method(rb_mKernel, "send", rb_f_send, -1);
-    rb_objc_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
-
-    rb_objc_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
-    rb_objc_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
-
-    rb_objc_define_module_function(rb_mKernel, "caller", rb_f_caller, -1);
-}
-

Deleted: MacRuby/trunk/vm_method.c
===================================================================
--- MacRuby/trunk/vm_method.c	2011-03-27 06:57:10 UTC (rev 5309)
+++ MacRuby/trunk/vm_method.c	2011-03-28 20:06:57 UTC (rev 5310)
@@ -1,766 +0,0 @@
-/*
- * This file is covered by the Ruby license. See COPYING for more details.
- * 
- * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
- * Copyright (C) 1993-2007 Yukihiro Matsumoto
- * Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
- * Copyright (C) 2000  Information-technology Promotion Agency, Japan
- */
-
-/*
- * This file is included by vm_eval.c
- */
-
-static ID __send__, object_id;
-static ID removed, singleton_removed, undefined, singleton_undefined;
-static ID eqq, each, aref, aset, match, missing;
-static ID added, singleton_added;
-
-static void
-remove_method(VALUE klass, ID mid)
-{
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
-    }
-    if (OBJ_FROZEN(klass)) {
-	rb_error_frozen("class/module");
-    }
-    if (mid == object_id || mid == __send__ || mid == idInitialize) {
-	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
-    }
-
-    rb_vm_remove_method((Class)klass, mid);
-}
-
-void
-rb_remove_method(VALUE klass, const char *name)
-{
-    remove_method(klass, rb_intern(name));
-}
-
-/*
- *  call-seq:
- *     remove_method(symbol)   => self
- *
- *  Removes the method identified by _symbol_ from the current
- *  class. For an example, see <code>Module.undef_method</code>.
- */
-
-static VALUE
-rb_mod_remove_method(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	remove_method(mod, rb_to_id(argv[i]));
-    }
-    return mod;
-}
-
-#undef rb_disable_super
-#undef rb_enable_super
-
-void
-rb_disable_super(VALUE klass, const char *name)
-{
-    /* obsolete - no use */
-}
-
-void
-rb_enable_super(VALUE klass, const char *name)
-{
-    rb_warning("rb_enable_super() is obsolete");
-}
-
-void rb_print_undef(VALUE, ID, int);
-
-static void
-rb_export_method(VALUE klass, ID name, ID noex)
-{
-    rb_vm_method_node_t *node;
-    SEL sel;
-
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-
-    if (!rb_vm_lookup_method2((Class)klass, name, &sel, NULL, &node)) {
-	if (TYPE(klass) != T_MODULE
-	    || !rb_vm_lookup_method2((Class)rb_cObject, name, &sel, NULL, &node)) {
-	    rb_print_undef(klass, name, 0);
-	}
-    }
-
-    if (node == NULL) {
-	rb_raise(rb_eRuntimeError,
-		"can't change visibility of non Ruby method `%s'",
-		sel_getName(sel));
-    }
-
-    long flags = (node->flags & ~VM_METHOD_PRIVATE) & ~VM_METHOD_PROTECTED;
-    switch (noex) {
-	case NOEX_PRIVATE:
-	    flags |= VM_METHOD_PRIVATE;
-	    break;
-
-	case NOEX_PROTECTED:
-	    flags |= VM_METHOD_PROTECTED;
-	    break;
-
-	default:
-	    break;
-    }
-
-    VALUE sklass = RCLASS_SUPER(klass);
-    if (sklass != 0) {
-	IMP imp;
-	rb_vm_method_node_t *snode;
-	if (rb_vm_lookup_method((Class)sklass, sel, &imp, &snode)
-		&& imp == node->objc_imp) {
-	    // The method actually exists on a superclass, we need to duplicate
-	    // it to the current class, keeping the same flags.
-	    if (snode != NULL) {
-		if (snode->flags & VM_METHOD_EMPTY) {
-		    flags |= VM_METHOD_EMPTY;
-		}
-		if (snode->flags & VM_METHOD_FBODY) {
-		    flags |= VM_METHOD_FBODY;
-		}
-	    }
-	    rb_vm_define_method2((Class)klass, sel, node, flags, false);
-	    return;
-	}
-    }
-
-    node->flags = flags;
-}
-
-void
-rb_attr(VALUE klass, ID id, int read, int write, int ex)
-{
-    if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
-	rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
-    }
-    const char *name = rb_id2name(id);
-    if (name == NULL) {
-	rb_raise(rb_eArgError, "argument needs to be symbol or string");
-    }
-    rb_vm_define_attr((Class)klass, name, read, write);
-    if (write) {
-	rb_objc_define_kvo_setter(klass, id);
-    }
-}
-
-void
-rb_undef(VALUE klass, ID id)
-{
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
-		rb_id2name(id));
-    }
-    rb_frozen_class_p(klass);
-    if (id == object_id || id == __send__ || id == idInitialize) {
-	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
-    }
-
-    rb_vm_undef_method((Class)klass, id, true);
-}
-
-/*
- *  call-seq:
- *     undef_method(symbol)    => self
- *
- *  Prevents the current class from responding to calls to the named
- *  method. Contrast this with <code>remove_method</code>, which deletes
- *  the method from the particular class; Ruby will still search
- *  superclasses and mixed-in modules for a possible receiver.
- *
- *     class Parent
- *       def hello
- *         puts "In parent"
- *       end
- *     end
- *     class Child < Parent
- *       def hello
- *         puts "In child"
- *       end
- *     end
- *
- *
- *     c = Child.new
- *     c.hello
- *
- *
- *     class Child
- *       remove_method :hello  # remove from child, still in parent
- *     end
- *     c.hello
- *
- *
- *     class Child
- *       undef_method :hello   # prevent any calls to 'hello'
- *     end
- *     c.hello
- *
- *  <em>produces:</em>
- *
- *     In child
- *     In parent
- *     prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
- */
-
-static VALUE
-rb_mod_undef_method(VALUE mod, SEL sel, int argc, VALUE *argv)
-{
-    for (int i = 0; i < argc; i++) {
-	rb_undef(mod, rb_to_id(argv[i]));
-    }
-    return mod;
-}
-
-/*
- *  call-seq:
- *     mod.method_defined?(symbol)    => true or false
- *
- *  Returns +true+ if the named method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors). Public and protected methods are matched.
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1    #=> true
- *     C.method_defined? "method1"   #=> true
- *     C.method_defined? "method2"   #=> true
- *     C.method_defined? "method3"   #=> true
- *     C.method_defined? "method4"   #=> false
- */
-
-static SEL selRespondToDefault = 0;
-
-static bool
-rb_obj_respond_to2(VALUE obj, VALUE klass, ID id, int priv, int check_override)
-{
-    const char *id_name = rb_id2name(id);
-    SEL sel = sel_registerName(id_name);
-    if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) {
-	char buf[100];
-	snprintf(buf, sizeof buf, "%s:", id_name);
-	sel = sel_registerName(buf);
-	if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) {
-	    VALUE args[2];
-	    args[0] = ID2SYM(id);
-	    args[1] = priv ? Qtrue : Qfalse;
-	    return RTEST(rb_vm_call(obj, selRespondToDefault, 2, args));
-	}
-    }
-    return true;
-}
-
-static VALUE
-rb_mod_method_defined(VALUE mod, SEL sel, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    if (rb_obj_respond_to2(Qnil, mod, id, true, false)) {
-	rb_vm_method_node_t *node;
-	if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
-	    if (node != NULL) {
-		if (node->flags & NOEX_PRIVATE) {
-		    return Qfalse;
-		}
-	    }
-	    return Qtrue;
-	}
-    }
-    return Qfalse;
-}
-
-#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
-
-/*
- *  call-seq:
- *     mod.public_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named public method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       protected
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1           #=> true
- *     C.public_method_defined? "method1"   #=> true
- *     C.public_method_defined? "method2"   #=> false
- *     C.method_defined? "method2"          #=> true
- */
-
-static VALUE
-check_method_visibility(VALUE mod, ID id, int visi)
-{
-    rb_vm_method_node_t *node;
-    if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
-	if (node != NULL) {
-	    if ((node->flags & NOEX_MASK) == visi) {
-		return Qtrue;
-	    }
-	}
-    }
-    return Qfalse;
-}
-
-static VALUE
-rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    return check_method_visibility(mod, id, NOEX_PUBLIC);
-}
-
-/*
- *  call-seq:
- *     mod.private_method_defined?(symbol)    => true or false
- *
- *  Returns +true+ if the named private method is defined by
- *  _ mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       private
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1            #=> true
- *     C.private_method_defined? "method1"   #=> false
- *     C.private_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"           #=> false
- */
-
-static VALUE
-rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    return check_method_visibility(mod, id, NOEX_PRIVATE);
-}
-
-/*
- *  call-seq:
- *     mod.protected_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named protected method is defined
- *  by _mod_ (or its included modules and, if _mod_ is a
- *  class, its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       protected
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1              #=> true
- *     C.protected_method_defined? "method1"   #=> false
- *     C.protected_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"             #=> true
- */
-
-static VALUE
-rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    return check_method_visibility(mod, id, NOEX_PROTECTED);
-}
-
-void
-rb_alias(VALUE klass, ID name, ID def)
-{
-    rb_vm_alias(klass, name, def);
-}
-
-/*
- *  call-seq:
- *     alias_method(new_name, old_name)   => self
- *
- *  Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
- *  be used to retain access to methods that are overridden.
- *
- *     module Mod
- *       alias_method :orig_exit, :exit
- *       def exit(code=0)
- *         puts "Exiting with code #{code}"
- *         orig_exit(code)
- *       end
- *     end
- *     include Mod
- *     exit(99)
- *
- *  <em>produces:</em>
- *
- *     Exiting with code 99
- */
-
-static VALUE
-rb_mod_alias_method(VALUE mod, SEL sel, VALUE newname, VALUE oldname)
-{
-    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
-    return mod;
-}
-
-static void
-secure_visibility(VALUE self)
-{
-    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) {
-	rb_raise(rb_eSecurityError,
-		 "Insecure: can't change method visibility");
-    }
-}
-
-static void
-set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
-{
-    secure_visibility(self);
-    for (int i = 0; i < argc; i++) {
-	rb_export_method(self, rb_to_id(argv[i]), ex);
-    }
-}
-
-/*
- *  call-seq:
- *     public                 => self
- *     public(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-rb_mod_public(VALUE module, SEL sel, int argc, VALUE *argv)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	rb_vm_set_current_scope(module, SCOPE_PUBLIC);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     protected                => self
- *     protected(symbol, ...)   => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to protected. With arguments, sets the named methods
- *  to have protected visibility.
- */
-
-static VALUE
-rb_mod_protected(VALUE module, SEL sel, int argc, VALUE *argv)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	rb_vm_set_current_scope(module, SCOPE_PROTECTED);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     private                 => self
- *     private(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to private. With arguments, sets the named methods
- *  to have private visibility.
- *
- *     module Mod
- *       def a()  end
- *       def b()  end
- *       private
- *       def c()  end
- *       private :a
- *     end
- *     Mod.private_instance_methods   #=> [:a, :c]
- */
-
-static VALUE
-rb_mod_private(VALUE module, SEL sel, int argc, VALUE *argv)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	rb_vm_set_current_scope(module, SCOPE_PRIVATE);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     mod.public_class_method(symbol, ...)    => mod
- *
- *  Makes a list of existing class methods public.
- */
-
-static VALUE
-rb_mod_public_method(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     mod.private_class_method(symbol, ...)   => mod
- *
- *  Makes existing class methods private. Often used to hide the default
- *  constructor <code>new</code>.
- *
- *     class SimpleSingleton  # Not thread safe
- *       private_class_method :new
- *       def SimpleSingleton.create(*args, &block)
- *         @me = new(*args, &block) if ! @me
- *         @me
- *       end
- *     end
- */
-
-static VALUE
-rb_mod_private_method(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     public
- *     public(symbol, ...)
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-top_public(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_mod_public(rb_cObject, 0, argc, argv);
-}
-
-static VALUE
-top_private(VALUE recv, SEL sel, int argc, VALUE *argv)
-{
-    return rb_mod_private(rb_cObject, 0, argc, argv);
-}
-
-/*
- *  call-seq:
- *     module_function(symbol, ...)    => self
- *
- *  Creates module functions for the named methods. These functions may
- *  be called with the module as a receiver, and also become available
- *  as instance methods to classes that mix in the module. Module
- *  functions are copies of the original, and so may be changed
- *  independently. The instance-method versions are made private. If
- *  used with no arguments, subsequently defined methods become module
- *  functions.
- *
- *     module Mod
- *       def one
- *         "This is one"
- *       end
- *       module_function :one
- *     end
- *     class Cls
- *       include Mod
- *       def callOne
- *         one
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c = Cls.new
- *     c.callOne   #=> "This is one"
- *     module Mod
- *       def one
- *         "This is the new one"
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c.callOne   #=> "This is the new one"
- */
-
-static VALUE
-rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
-{
-    if (TYPE(module) != T_MODULE) {
-	rb_raise(rb_eTypeError, "module_function must be called for modules");
-    }
-
-    secure_visibility(module);
-    if (argc == 0) {
-	rb_vm_set_current_scope(module, SCOPE_MODULE_FUNC);
-	return module;
-    }
-
-    set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-
-    for (int i = 0; i < argc; i++) {
-	ID id = rb_to_id(argv[i]);
-	IMP imp;
-	rb_vm_method_node_t *node;
-	SEL sel;
-
-	if (!rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)) {
-	    // Methods are checked in set_method_visibility().
-	    rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
-	}
-
-	rb_vm_define_method2(*(Class *)module, sel, node, -1, false);
-    }
-
-    return module;
-}
-
-/*
- *  call-seq:
- *     obj.respond_to?(symbol, include_private=false) => true or false
- *
- *  Returns +true+ if _obj_ responds to the given
- *  method. Private methods are included in the search only if the
- *  optional second parameter evaluates to +true+.
- *
- *  If the method is not implemented,
- *  as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
- *  false is returned.
- *
- *  If the method is not defined, <code>respond_to_missing?</code>
- *  method is called and the result is returned.
- */
-
-int
-rb_obj_respond_to(VALUE obj, ID id, int priv)
-{
-    return rb_obj_respond_to2(obj, Qnil, id, priv, true);
-}
-
-int
-rb_respond_to(VALUE obj, ID id)
-{
-    return rb_obj_respond_to(obj, id, false);
-}
-
-static VALUE
-obj_respond_to(VALUE obj, SEL sel, int argc, VALUE *argv)
-{
-    VALUE mid, priv;
-    ID id;
-
-    rb_scan_args(argc, argv, "11", &mid, &priv);
-    id = rb_to_id(mid);
-    return rb_obj_respond_to2(obj, Qnil, id, RTEST(priv), false) ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *     obj.respond_to_missing?(symbol, include_private) => true or false
- *
- *  Hook method to return whether the _obj_ can respond to _id_ method
- *  or not.
- *
- *  See #respond_to?.
- */
-
-static VALUE
-obj_respond_to_missing(VALUE obj, SEL sel, VALUE sym, VALUE priv)
-{
-    return Qfalse;
-}
-
-IMP basic_respond_to_imp = NULL;
-
-void
-Init_eval_method(void)
-{
-    rb_objc_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
-    rb_objc_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
-    selRespondToDefault = sel_registerName("respond_to_missing?:");
-    basic_respond_to_imp = class_getMethodImplementation((Class)rb_mKernel,
-	    selRespondTo);
-
-    rb_objc_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
-    rb_objc_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
-    rb_objc_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
-    rb_objc_define_private_method(rb_cModule, "public", rb_mod_public, -1);
-    rb_objc_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
-    rb_objc_define_private_method(rb_cModule, "private", rb_mod_private, -1);
-    rb_objc_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
-
-    rb_objc_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
-    rb_objc_define_method(rb_cModule, "public_method_defined?",
-	    rb_mod_public_method_defined, 1);
-    rb_objc_define_method(rb_cModule, "private_method_defined?",
-	    rb_mod_private_method_defined, 1);
-    rb_objc_define_method(rb_cModule, "protected_method_defined?",
-	    rb_mod_protected_method_defined, 1);
-    rb_objc_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
-    rb_objc_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
-
-    VALUE cTopLevel = *(VALUE *)rb_vm_top_self();
-    rb_objc_define_method(cTopLevel, "public", top_public, -1);
-    rb_objc_define_method(cTopLevel, "private", top_private, -1);
-
-    object_id = rb_intern("object_id");
-    __send__ = rb_intern("__send__");
-    eqq = rb_intern("===");
-    each = rb_intern("each");
-    aref = rb_intern("[]");
-    aset = rb_intern("[]=");
-    match = rb_intern("=~");
-    missing = rb_intern("method_missing");
-    added = rb_intern("method_added");
-    singleton_added = rb_intern("singleton_method_added");
-    removed = rb_intern("method_removed");
-    singleton_removed = rb_intern("singleton_method_removed");
-    undefined = rb_intern("method_undefined");
-    singleton_undefined = rb_intern("singleton_method_undefined");
-}
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20110328/e032de75/attachment-0001.html>


More information about the macruby-changes mailing list