summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-01-20 04:59:39 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-01-20 04:59:39 +0000
commit62e648e148b3cb9f96dcce808c55c02b7ccb4486 (patch)
tree9708892ece92e860d81559ab55e6b1f9400d7ffc
parentaeb049c573be4dc24dd20650f40e4777e0f698cf (diff)
ruby 1.3 cycle
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/RUBY@372 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--COPYING358
-rw-r--r--ChangeLog2354
-rw-r--r--MANIFEST64
-rw-r--r--Makefile.in102
-rw-r--r--README42
-rw-r--r--README.EXT499
-rw-r--r--README.EXT.jp1147
-rw-r--r--README.jp38
-rw-r--r--ToDo41
-rw-r--r--array.c1037
-rw-r--r--bignum.c568
-rw-r--r--class.c268
-rw-r--r--compar.c48
-rw-r--r--config.guess485
-rw-r--r--config.sub156
-rw-r--r--config_h.dj64
-rw-r--r--config_s.dj51
-rw-r--r--configure1325
-rw-r--r--configure.bat3
-rw-r--r--configure.in249
-rw-r--r--defines.h24
-rw-r--r--dir.c155
-rw-r--r--dln.c298
-rw-r--r--dln.h14
-rw-r--r--enum.c141
-rw-r--r--env.h11
-rw-r--r--error.c656
-rw-r--r--eval.c4790
-rw-r--r--ext/Setup1
-rw-r--r--ext/Win32API/MANIFEST7
-rw-r--r--ext/Win32API/Win32API.c223
-rw-r--r--ext/Win32API/extconf.rb7
-rw-r--r--ext/Win32API/getch.rb5
-rw-r--r--ext/Win32API/point.rb18
-rw-r--r--ext/aix_ld.rb2
-rw-r--r--ext/curses/curses.c107
-rw-r--r--ext/curses/extconf.rb5
-rw-r--r--ext/curses/hello.rb4
-rw-r--r--ext/curses/view.rb1
-rw-r--r--ext/cygwin32_ld.rb90
-rw-r--r--ext/dbm/dbm.c175
-rw-r--r--ext/dbm/extconf.rb6
-rw-r--r--ext/etc/etc.c91
-rw-r--r--ext/etc/extconf.rb24
-rw-r--r--ext/extmk.rb.in235
-rw-r--r--ext/extmk.rb.nt6
-rw-r--r--ext/fcntl/fcntl.c2
-rw-r--r--ext/kconv/kconv.c89
-rw-r--r--ext/md5/md5init.c14
-rw-r--r--ext/socket/depend2
-rw-r--r--ext/socket/extconf.rb12
-rw-r--r--ext/socket/socket.c829
-rw-r--r--ext/tcltklib/extconf.rb114
-rw-r--r--ext/tcltklib/lib/tcltk.rb287
-rw-r--r--ext/tcltklib/tcltklib.c293
-rw-r--r--ext/tk/MANIFEST25
-rw-r--r--ext/tk/depend1
-rw-r--r--ext/tk/extconf.rb2
-rw-r--r--ext/tk/lib/tk.rb2499
-rw-r--r--ext/tk/lib/tkafter.rb296
-rw-r--r--ext/tk/lib/tkbgerror.rb17
-rw-r--r--ext/tk/lib/tkcanvas.rb829
-rw-r--r--ext/tk/lib/tkclass.rb38
-rw-r--r--ext/tk/lib/tkdialog.rb141
-rw-r--r--ext/tk/lib/tkentry.rb73
-rw-r--r--ext/tk/lib/tkfont.rb944
-rw-r--r--ext/tk/lib/tkmenubar.rb137
-rw-r--r--ext/tk/lib/tkmngfocus.rb27
-rw-r--r--ext/tk/lib/tkpalette.rb48
-rw-r--r--ext/tk/lib/tkscrollbox.rb27
-rw-r--r--ext/tk/lib/tktext.rb797
-rw-r--r--ext/tk/lib/tkvirtevent.rb66
-rw-r--r--ext/tk/sample/tkbiff.rb149
-rw-r--r--ext/tk/sample/tkbrowse.rb79
-rw-r--r--ext/tk/sample/tkdialog.rb62
-rw-r--r--ext/tk/sample/tkfrom.rb132
-rw-r--r--ext/tk/sample/tkhello.rb10
-rw-r--r--ext/tk/sample/tkline.rb45
-rw-r--r--ext/tk/sample/tktimer.rb50
-rw-r--r--ext/tk/tkutil.c45
-rw-r--r--file.c905
-rw-r--r--fnmatch.c83
-rw-r--r--gc.c496
-rw-r--r--glob.c119
-rw-r--r--hash.c921
-rw-r--r--inits.c10
-rw-r--r--instruby.rb54
-rw-r--r--intern.h484
-rw-r--r--io.c1562
-rw-r--r--keywords2
-rw-r--r--lex.c44
-rw-r--r--lib/Env.rb31
-rw-r--r--lib/README61
-rw-r--r--lib/base64.rb45
-rw-r--r--lib/cgi-lib.rb39
-rw-r--r--lib/complex.rb14
-rw-r--r--lib/date.rb91
-rw-r--r--lib/date2.rb219
-rw-r--r--lib/debug.rb12
-rw-r--r--lib/delegate.rb100
-rw-r--r--lib/e2mmap.rb77
-rw-r--r--lib/eregex.rb11
-rw-r--r--lib/final.rb41
-rw-r--r--lib/finalize.rb66
-rw-r--r--lib/find.rb4
-rw-r--r--lib/ftools.rb31
-rw-r--r--lib/ftplib.rb1123
-rw-r--r--lib/getoptlong.rb473
-rw-r--r--lib/getopts.rb3
-rw-r--r--lib/importenv.rb15
-rw-r--r--lib/jcode.rb23
-rw-r--r--lib/mailread.rb5
-rw-r--r--lib/mathn.rb5
-rw-r--r--lib/matrix.rb239
-rw-r--r--lib/mkmf.rb144
-rw-r--r--lib/monitor.rb325
-rw-r--r--lib/mutex_m.rb60
-rw-r--r--lib/observer.rb8
-rw-r--r--lib/open3.rb55
-rw-r--r--lib/parsearg.rb5
-rw-r--r--lib/parsedate.rb81
-rw-r--r--lib/ping.rb33
-rw-r--r--lib/profile.rb53
-rw-r--r--lib/pstore.rb39
-rw-r--r--lib/rational.rb9
-rw-r--r--lib/readbytes.rb36
-rw-r--r--lib/shellwords.rb16
-rw-r--r--lib/singleton.rb37
-rw-r--r--lib/sync.rb13
-rw-r--r--lib/telnet.rb439
-rw-r--r--lib/tempfile.rb91
-rw-r--r--lib/thread.rb163
-rw-r--r--lib/thwait.rb113
-rw-r--r--lib/timeout.rb42
-rw-r--r--lib/tracer.rb147
-rw-r--r--lib/weakref.rb39
-rw-r--r--main.c1
-rw-r--r--marshal.c289
-rw-r--r--math.c74
-rw-r--r--misc/README5
-rw-r--r--misc/inf-ruby.el316
-rw-r--r--misc/ruby-mode.el699
-rw-r--r--misc/rubydb2x.el104
-rw-r--r--misc/rubydb3x.el104
-rw-r--r--missing/dir.h126
-rw-r--r--missing/file.h1
-rw-r--r--missing/memcmp.c21
-rw-r--r--missing/strchr.c45
-rw-r--r--missing/vsnprintf.c1153
-rw-r--r--missing/x68.c24
-rw-r--r--mkconfig.rb4
-rw-r--r--node.h231
-rw-r--r--numeric.c1066
-rw-r--r--object.c871
-rw-r--r--pack.c407
-rw-r--r--parse.y2025
-rw-r--r--process.c410
-rw-r--r--random.c122
-rw-r--r--range.c174
-rw-r--r--re.c705
-rw-r--r--re.h16
-rw-r--r--regex.h205
-rw-r--r--ruby.1216
-rw-r--r--ruby.c393
-rw-r--r--ruby.h428
-rw-r--r--rubyio.h60
-rw-r--r--rubysig.h54
-rw-r--r--rubytest.rb2
-rw-r--r--sample/README60
-rw-r--r--sample/cal.rb118
-rw-r--r--sample/fib.py10
-rw-r--r--sample/fib.scm4
-rw-r--r--sample/freq.rb8
-rw-r--r--sample/from.rb36
-rw-r--r--sample/goodfriday.rb48
-rw-r--r--sample/mkproto.rb8
-rw-r--r--sample/observ.rb15
-rw-r--r--sample/occur.rb8
-rw-r--r--sample/rbc.rb257
-rw-r--r--sample/sieve.rb3
-rw-r--r--sample/test.rb218
-rw-r--r--sample/trojan.rb4
-rw-r--r--sample/tsvr.rb2
-rw-r--r--signal.c141
-rw-r--r--sprintf.c463
-rw-r--r--string.c2015
-rw-r--r--struct.c414
-rw-r--r--time.c405
-rw-r--r--top.sed96
-rw-r--r--util.c353
-rw-r--r--util.h26
-rw-r--r--variable.c613
-rw-r--r--version.c12
-rw-r--r--version.h4
-rw-r--r--win32/Makefile31
-rw-r--r--win32/config.h12
-rw-r--r--win32/ruby.def469
-rw-r--r--win32/sdbm.c2
198 files changed, 36559 insertions, 13179 deletions
diff --git a/COPYING b/COPYING
index 3c68f02bb4..eeb586b392 100644
--- a/COPYING
+++ b/COPYING
@@ -1,37 +1,40 @@
GNU GENERAL PUBLIC LICENSE
- Version 1, February 1989
+ Version 2, June 1991
- Copyright (C) 1989 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ 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 license agreements of most software companies try to keep users
-at the mercy of those companies. By contrast, our General Public
+ 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. The
-General Public License applies to the Free Software Foundation's
-software and to any other program whose authors commit to using it.
-You can use it for your programs, too.
+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. Specifically, the General Public License is designed to make
-sure that you have the freedom to give away or sell copies of free
-software, 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.
+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 a such a program, whether
+ 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 tell them their rights.
+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,
@@ -44,120 +47,207 @@ 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 Agreement 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 work containing the
-Program or a portion of it, either verbatim or with modifications. Each
-licensee is addressed as "you".
-
- 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
-General Public License and to the absence of any warranty; and give any
-other recipients of the Program a copy of this General Public License
-along with the Program. You may charge a fee for the physical act of
-transferring a copy.
-
- 2. You may modify your copy or copies of the Program or any portion of
-it, and copy and distribute such modifications under the terms of Paragraph
-1 above, provided that you also do the following:
-
- a) cause the modified files to carry prominent notices stating that
- you changed the files and the date of any change; and
-
- b) cause the whole of any work that you distribute or publish, that
- in whole or in part contains the Program or any part thereof, either
- with or without modifications, to be licensed at no charge to all
- third parties under the terms of this General Public License (except
- that you may choose to grant warranty protection to some or all
- third parties, at your option).
-
- c) If the modified program normally reads commands interactively when
- run, you must cause it, when started running for such interactive use
- in the simplest and most usual 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 General
- Public License.
-
- d) 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.
-
-Mere aggregation of another independent work with the Program (or its
-derivative) on a volume of a storage or distribution medium does not bring
-the other work under the scope of these terms.
+ 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.)
- 3. You may copy and distribute the Program (or a portion or derivative of
-it, under Paragraph 2) in object code or executable form under the terms of
-Paragraphs 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
- Paragraphs 1 and 2 above; or,
-
- b) accompany it with a written offer, valid for at least three
- years, to give any third party free (except for a nominal charge
- for the cost of distribution) a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- c) accompany it with the information you received as to where the
- corresponding source code may be obtained. (This alternative is
+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 alone.)
-
-Source code for a work means the preferred form of the work for making
-modifications to it. For an executable file, complete source code means
-all the source code for all modules it contains; but, as a special
-exception, it need not include source code for modules which are standard
-libraries that accompany the operating system on which the executable
-file runs, or for standard header files or definitions files that
-accompany that operating system.
-
- 4. You may not copy, modify, sublicense, distribute or transfer the
-Program except as expressly provided under this General Public License.
-Any attempt otherwise to copy, modify, sublicense, distribute or transfer
-the Program is void, and will automatically terminate your rights to use
-the Program under this License. However, parties who have received
-copies, or rights to use copies, from you under this General Public
-License will not have their licenses terminated so long as such parties
-remain in full compliance.
-
- 5. By copying, distributing or modifying 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.
+ 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.
+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.
- 7. The Free Software Foundation may publish revised and/or new versions
+ 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 the license which applies to it and "any
+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
-the license, you may choose any version ever published by the Free Software
+this License, you may choose any version ever published by the Free Software
Foundation.
- 8. If you wish to incorporate parts of the Program into other free
+ 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
@@ -167,7 +257,7 @@ of promoting the sharing and reuse of software generally.
NO WARRANTY
- 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS 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
@@ -177,7 +267,7 @@ 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.
- 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ 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
@@ -189,25 +279,24 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Programs
+ 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 humanity, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
+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.
+ 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) 19yy <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 1, or (at your option)
- any later version.
+ 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
@@ -216,33 +305,36 @@ the exclusion of warranty; and each file should have at least the
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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 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) 19xx name of author
+ Gnomovision version 69, Copyright (C) 19yy 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.
+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 a sample; alter the names:
+necessary. Here is a sample; alter the names:
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- program `Gnomovision' (a program to direct compilers to make passes
- at assemblers) written by James Hacker.
+ 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
-That's all there is to it!
+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.
diff --git a/ChangeLog b/ChangeLog
index 029e20077c..6a317e294b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,2355 @@
+Wed Jan 20 03:39:48 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yycompile): rb_in_compile renamed to ruby_in_compile.
+
+ * ruby.c (load_file): define DATA iff __END__ appeared in script.
+
+Tue Jan 19 14:57:51 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): need to protect lex_lastline.
+
+ * parse.y (yylex): disable %//, %'', %``.
+
+Tue Jan 19 05:01:16 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * array.c (beg_len): round range value too much.
+
+Mon Jan 18 13:02:27 1999 Kuroda Jun <jkuro@dwe.co.j>
+
+ * hash.c (env_keys): strchr() may return NULL.
+
+Mon Jan 18 17:51:47 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * instruby.rb (wdir): install libruby.a in archdir.
+
+ * lib/ftools.rb (install): removes file before installing.
+
+Mon Jan 18 16:55:31 1999 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * eval.c (rb_callcc): experimental continuation support.
+
+Sun Jan 17 19:45:37 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * pack.c (pack_pack): nil packing caused SEGV.
+
+Sat Jan 16 13:18:03 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_concat): character (fixnum) can be append to
+ strings
+
+ * array.c (rb_ary_unshift): unshift returns array.
+
+Sat Jan 16 01:39:19 1999 Yoshida Masato <yoshidam@tau.bekkoame.ne.jp>
+
+ * string.c (rb_str_split_method): UTF-8 support.
+
+ * regex.c: UTF-8 support.
+
+Thu Jan 14 00:42:55 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_gsub_bang): forget to add offset for null match.
+
+ * eval.c (rb_thread_local_aset): can't modify in tainted mode.
+
+ * hash.c (env_each_key): avoid generating temporary array.
+
+Wed Jan 13 23:58:50 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_f_setenv): name and value can be tainted.
+
+Wed Jan 6 02:42:08 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (Init_Bignum): forgot to define Bignum#===.
+
+ * gc.c (gc_sweep): if add_heap() is called during GC, objects on
+ allocated heap page(s) are not marked, should not be recycled.
+
+ * gc.c (gc_sweep): should refer latest freelist.
+
+ * gc.c (id2ref): modified to support performance patch.
+
+ * object.c (rb_obj_id): performance patch (no bignum for id).
+
+Tue Jan 5 01:56:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * config.guess: merge up-to-date from autoconf 2.12.
+
+ * array.c (rb_ary_join): avoid calling rb_protect_inspect() till
+ it is really needed.
+
+ * object.c (rb_obj_inspect): show detailed information for the
+ instance variables (infinite loop can avoid now).
+
+ * struct.c (rb_struct_inspect): avoid infinite loop.
+
+Sun Jan 3 01:37:58 1999 Takao KAWAMURA <kawamura@ike.tottori-u.ac.jp>
+
+ * misc/ruby-mode.el (ruby-end-of-defun): moved too much.
+
+ * misc/ruby-mode.el (ruby-mode-variables): set paragraph-separator
+ for the mode.
+
+ * misc/ruby-mode.el: proper font-lock for `def' and `nil' etc.
+
+Sat Jan 2 17:09:06 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_jump_tag): new api to invoke JUMP_TAG. tag values
+ can obtained from rb_eval_string_protect()/rb_load_protect().
+
+ * eval.c (rb_rescue): now catches all exceptions but SystemExit.
+
+ * eval.c (rb_eval_string_protect): eval string with protection.
+
+ * eval.c (rb_load_protect): load file with protection.
+
+ * io.c (rb_io_puts): avoid infinite loop for cyclic arrays.
+
+ * eval.c (rb_thread_local_aref): thread local hash tables.
+
+ * object.c (rb_equal): check exact equal before calling `=='.
+
+Thu Dec 31 22:28:53 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * eval.c (rb_f_require): feature names should be provided with
+ DLEXT extension.
+
+ * marshal.c (Init_marshal): need to provide `marshal.so'.
+
+Wed Dec 30 02:29:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (classname): do not call rb_ivar_set().
+
+ * eval.c (ruby_run): finalizers were called too early.
+
+Fri Dec 25 12:19:30 1998 Fukuda Masaki <fukuda@wni.co.jp>
+
+ * gc.c (rb_gc_mark): should not return on FL_EXIVAR.
+
+Fri Dec 25 11:56:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (gc_mark): proper scanning for temporary region.
+
+ * eval.c (TMP_ALLOC): protection for C_ALLOCA was broken.
+
+Thu Dec 24 18:26:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * development version 1.3 released.
+
+Thu Dec 24 00:17:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_load): top self should be set properly.
+
+ * variable.c (classname): check __classpath__ iff it is defined.
+
+ * variable.c (classname): invalid warning at -v with static linked
+ ruby interpreter.
+
+ * eval.c (is_defined): modified for expr::Const support.
+
+ * eval.c (rb_eval): invoke method expr::Const if expr is not class
+ nor module.
+
+ * parse.y (primary): enable expr::identifier as method
+ invocation.
+
+Wed Dec 23 03:04:36 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): avoid too many loop pops for (?:..).
+
+Tue Dec 22 18:01:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental version 1.1d1 released.
+
+Mon Dec 21 01:33:03 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (TMP_PROTECT): add volatile to ensure GC protection.
+
+ * string.c (rb_str_gsub_bang): calculate buffer size properly.
+
+ * parse.y (lex_get_str): needed to return Qnil at EOS.
+
+ * eval.c (find_file): check policy modified, raise exception
+ immediately for tainted load_path.
+
+ * hash.c (rb_f_setenv): do not depend on setenv() nor putenv().
+
+Thu Dec 17 06:29:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/tk/tkutil.c (tk_s_new): use rb_obj_instance_eval(), instead
+ of rb_yield_0().
+
+ * eval.c (rb_f_require): forgot to call find_file in some cases.
+
+ * eval.c (rb_f_require): `require "feature.so"' to load dynamic
+ libraries. old `require "feature.o"' is still OK.
+
+ * eval.c (rb_eval): yield without value dumped core.
+
+Wed Dec 16 16:28:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental version 1.1d0 (pre1.2) released.
+
+Wed Dec 16 10:43:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): bound check before calling re_match().
+
+Tue Dec 15 13:59:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (exc_to_s): returns class name for unset mesg.
+
+ * error.c (exc_initialize): do not initialize @mesg by "".
+
+ * parse.y (nextc): __END__ should handle CR+LF newlines.
+
+Wed Dec 9 13:37:12 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * pack.c (encodes): use buffering for B-encoding.
+
+ * pack.c (pack_pack): Q-encoding by 'M'.
+
+Tue Dec 8 14:10:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (generic_ivar_get): any object can have instance
+ variables now. great improvement.
+
+ * variable.c (rb_name_class): do not set __classpath__ by default,
+ use __classid__ instead.
+
+Mon Dec 7 22:08:22 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h (struct RFile): IO objects can have instance variables now.
+
+ * parse.y (primary): allows `def obj::foo; .. end'.
+
+Mon Dec 7 18:24:50 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ruby.c (set_arg0): $0 supprt for HP-UX.
+
+Mon Dec 7 01:30:28 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dln.c (dln_strerror): better error messages on win32.
+
+Sat Dec 5 23:27:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): indentable here-doc delimiter by
+ `<<-'. Proposed by Clemens <c.hintze@gmx.net>. Thanks.
+
+Thu Dec 3 16:50:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/extmk.rb.in (realclean): trouble on install.
+
+Sun Nov 29 22:25:39 1998 Takaaki Tateishi <ttate@jaist.ac.jp>
+
+ * process.c (f_exec): check number of argument.
+
+Thu Nov 26 17:27:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c9 released.
+
+Wed Nov 25 13:07:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_dup): do not copy additional data (STR_NO_ORIG).
+
+ * parse.y (yycompile): reduce known memory leak (hard to remove).
+
+Wed Nov 25 03:41:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * st.c (st_init_table_with_size): round size up to prime number.
+
+Sat Nov 21 23:27:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_aset): reduce copying key strings.
+
+ * gc.c (looks_pointerp): declare as inline function if possible.
+
+ * st.c (PTR_NOT_EQUAL): compare hash values first before calling
+ comparing function.
+
+ * st.c (ADD_DIRECT): save hash value in entries to reduce hash
+ calculation.
+
+ * string.c (rb_str_gsub_bang): avoid rb_scan_args() to speed-up.
+
+ * string.c (rb_str_sub_bang): ditto.
+
+Sat Nov 21 18:44:06 1998 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * time.c (time_s_now): had memory leak.
+
+ * ext/md5/md5init.c (md5_new): had memory leak.
+
+ * ext/md5/md5init.c (md5_clone): ditto.
+
+Fri Nov 20 23:23:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/delegate.rb: do not propagate hash and eql?.
+
+Thu Nov 19 01:40:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sample/ruby-mode.el (ruby-expr-beg): failed to find reserved
+ word boundary.
+
+ * eval.c (rb_eval): avoid calling `concat' method. calls
+ rb_ary_concat() directly for efficiency.
+
+ * eval.c (rb_eval): actual rest arguments extended arrays too much.
+
+Wed Nov 18 14:30:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (rb_define_global_function): global functions now be
+ module function of the Kernel.
+
+Wed Nov 18 10:48:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (read_all): SEGV on large files.
+
+Tue Nov 17 18:11:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c8 released.
+
+Tue Nov 17 16:58:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): assignment to attribute name start with capital
+ should be allowed.
+
+ * eval.c (thread_alloc): needed to mark terminated threads too.
+
+Tue Nov 17 12:33:48 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * ext/extmk.rb.in (create_makefile): Set `libdir' to `@libdir@',
+ Set `pkglibdir' to `$libdir/$(RUBY_INSTALL_NAME)'.
+
+Tue Nov 17 10:30:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): %l%%c -> %%l%c
+
+Tue Nov 17 01:08:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (ret_args): distinguish `a' and `*a' for the arguments
+ of yield and return.
+
+ * eval.c (rb_eval): flip3 should work like sed.
+
+ * eval.c (rb_eval): flip{2,3} now have independent state for each
+ scope to work fine with thread.
+
+Mon Nov 16 23:26:29 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (primary): exec else clause if no exception raised.
+
+Sun Nov 15 15:44:07 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * ext/extmk.rb.in (install): bug in target.
+
+Sat Nov 14 11:02:05 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * Makefile.in (install): Give the argument `$(DESTDIR)' to
+ `instruby.rb'.
+ * instruby.rb: Recognize ARG[0] as `destdir'.
+ * instruby.rb: Give the argument `destdir' to `extmk.rb'.
+ * ext/extmk.rb.in: Recognize ARG[1] as `$destdir'.
+
+ * instruby.rb: Create the installation directories (bindir, libdir,
+ archdir, pkglibdir, archdir, and mandir) under `destdir', and
+ install all files under there.
+ * ext/extmk.rb.in: Likewise.
+
+Sat Nov 14 10:56:55 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * instruby.rb: Add the variable `pkglibdir'.
+ * instruby.rb: Set the variable `libdir' to `$(libdir)', not
+ `$(libdir)/$(ruby_install_name)'. `libruby.so' and `libruby.so.LIB'
+ are installed at `libdir'.
+ * instruby.rb: Set the variable `archdir' to `$(pkglibdir)/$(arch)'.
+
+Fri Nov 13 19:43:29 1998 KIMURA Koichi <kbk@kt.rim.or.jp>
+
+ * missing/nt.c (SafeFree): wrong free offset.
+
+Thu Nov 12 20:11:53 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sample/ruby-mode.el: wrong highlight.
+
+ * parse.y (parse_regx): newline in regexp was ignored.
+
+Wed Nov 11 10:54:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): <<'FOO' should not escape anything.
+
+ * parse.y (here_document): bare << here-doc available, even though
+ it's deprecated.
+
+ * file.c (rb_file_s_readlink): return value should be tainted.
+
+ * ext/etc/etc.c (setup_passwd): information (eg. GCOS name) should
+ be tainted (modified at Perl Conference).
+
+Tue Nov 10 00:22:11 1998 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: elf supprt for FreeBSD 3.x
+
+Tue Nov 10 00:05:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): here document available in eval.
+
+Mon Nov 9 17:55:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c7 released.
+
+Fri Nov 6 19:25:27 1998 Takao KAWAMURA <kawamura@ike.tottori-u.ac.jp>
+
+ * sample/ruby-mode.el: font-lock patch.
+
+Thu Nov 5 15:42:22 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sample/README, lib/README: simple description for each file.
+
+Wed Nov 4 18:14:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (assign): attribute assignment should be called as public.
+
+Tue Nov 3 23:36:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_dump): dumps core for negative char value.
+
+ * regex.c (re_compile_pattern): out of boundary access for empty
+ regexp.
+
+Mon Nov 2 22:54:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_aset): `str[str]' replaces first match.
+
+Mon Nov 2 18:24:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_create): was accessing modified status.
+
+Sun Nov 1 01:18:52 1998 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * gc.c (xrealloc): size 0 needs round up to 1.
+
+Sat Oct 31 23:18:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_split_method): negative LIMIT means number of
+ splitted fields are unlimited, as in perl.
+
+ * string.c (rb_str_split_method): if LIMIT is unspecified,
+ trailing null fields are stripped.
+
+Sat Oct 31 04:16:14 1998 Inaba Hiroto <inaba@st.rim.or.jp>
+
+ * string.c (str_aref): regexp index SEGVed.
+
+Fri Oct 30 14:33:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_match): returns nil for unmatch.
+
+ * dir.c (dir_entries): new method.
+
+ * eval.c (block_pass): do not push block, substitute it.
+
+Fri Oct 30 01:28:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * range.c (range_check): avoid <=> check for Fixnums.
+
+ * array.c (rb_ary_aset): accept negative index.
+
+Wed Oct 28 22:00:54 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): access out of boundary fixed.
+
+Wed Oct 28 11:37:42 1998 TAMITO <tommy@valley.ne.jp>
+
+ * io.c (f_select): fd number comparison bug.
+
+Tue Oct 27 23:07:11 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sample/ruby-mode.el (ruby-parse-region): forgot to support %w()
+ style array literal.
+
+ * eval.c (rb_eval): unused block raises warning.
+
+Mon Oct 26 09:37:53 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (dvar_asgn_push): dvar pushed too many times if
+ variable-in-block first appear in loops.
+
+Sun Oct 25 22:59:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (set_list_bits): was using wrong offset.
+
+Thu Oct 22 00:07:11 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_obj_method): method retrieved from tainted object
+ should be tainted too.
+
+ * eval.c (method_call): safe_level should be restored during
+ Method#call.
+
+Wed Oct 21 14:21:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (Init_IO): new constants IO::SEEK_{SET,CUR,END}.
+
+ * io.c (rb_f_ungetc): ungetc pushes a char back into STDIN.
+
+Mon Oct 19 11:50:00 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * ext/extmk.rb: Load '@top_srcdir@/lib/find.rb', not
+ '../lib/find.rb'.
+ * ext/extmk.rb: Distinguish between `top_srcdir' and `topdir'.
+ * Makefile.in (CFLAGS): Add `-I.'.
+ * Makefile.in (lex.c): Give `@srcdir@/keywords' to gperf, not
+ `keywords'.
+ * instruby.rb: Use `CONFIG["bindir"]', instead of `prefix + "/bin"'.
+ * instruby.rb: Use `CONFIG["libdir"]', instead of `prefix + "/lib"'.
+ * instruby.rb Use `CONFIG["mandir"]', instead of `prefix + "/man"'.
+ * instruby.rb (wdir): Add the variable to preserve the current
+ working directory.
+ * instruby.rb: Chdir to wdir before install `config.h' and
+ `rbconfig.rb'.
+
+Mon Oct 19 10:07:01 1998 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * eval.c (rb_eval): reduce recursive calls to rb_eval().
+
+Fri Oct 16 15:31:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_new_internal): timeval must be positive.
+
+Thu Oct 15 13:54:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): local variabls can be accessed within right side
+ expression in assignment, notably in blocks.
+
+Wed Oct 14 00:18:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (Init_Array): Array#=== is now for equal check, not
+ inclusion check.
+
+ * parse.y (when_args): `when a, *b' style new syntax for array
+ expansion in `case'.
+
+Tue Oct 13 14:30:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_obj_untaint): taint marks can be unset.
+
+ * eval.c (rb_eval): taint propagation for embedded strings.
+
+Mon Oct 12 13:27:15 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call0): check stack depth more frequently.
+
+Mon Oct 12 08:08:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_p): can print even in secure mode.
+
+Sun Oct 11 22:50:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_const_set): taint check for modification.
+
+ * variable.c (rb_ivar_set): taint check for modification.
+
+ * string.c (rb_str_modify): taint check for modification.
+
+ * hash.c (rb_hash_modify): taint check for modification.
+
+ * array.c (rb_ary_modify): taint check for modification.
+
+ * ruby.h (FL_TAINT): taint for all objects, not only strings.
+
+Fri Oct 9 17:01:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (read_all): read() returns "" at immediate EOF.
+
+ * io.c (io_read): read(nil) read all until EOF.
+
+Thu Oct 8 13:32:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_dump): marshal can dump Time object now.
+
+ * marshal.c (Init_marshal): rename marshal methods `_dump_to' to
+ `_dump', `_load_from' to `_load'.
+
+ * parse.y (rb_intern): "+=".intern generates proper symbol.
+
+Mon Oct 5 18:31:53 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c6 released.
+
+Fri Oct 2 14:22:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): `/\s*(--)$/ =~ "- --"' did not match,
+ because of wrong optimize condition.
+
+Mon Oct 1 01:55:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (rb_intern): should not raise exceptions.
+
+ * parse.y (yylex): symbol like `:foo?=' should not be allowed.
+
+ * ext/extmk.rb.in: makes *.a for static link modules.
+
+Wed Sep 30 14:13:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_start): supports making a subclass of the
+ Thread class.
+
+Tue Sep 29 17:46:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_join): join is now an instance method.
+
+Fri Sep 25 12:01:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `@foo!' should be an error.
+
+Thu Sep 24 14:55:06 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ext/etc/etc.c (Init_etc): wrong field definition.
+
+Thu Sep 17 17:09:05 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_reopen): was creating FILE* for wrong fd.
+
+Tue Sep 15 05:28:11 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * regex.c (re_compile_pattern): forgot to fixup for the pattern
+ like (?=(A)|(B)).
+
+Tue Sep 15 01:06:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_gets_internal): do not set $_ by default, only
+ gets/readline set the variable.
+
+ * eval.c (rb_f_load): load toplevel class is set to anonymous
+ module if safe_level >= 5, to encapsulate modification.
+
+ * eval.c (rb_f_load): set frame properly.
+
+ * string.c (rb_str_each_line): do not set $_.
+
+Mon Sep 14 14:42:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): beginning and end of the string, do not
+ automatically match `\b'.
+
+ * string.c (scan_once): comsume at leaset on character.
+
+ * regex.c (re_search): wrong behavior for negative range.
+
+Sat Sep 12 21:21:26 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * regex.c (re_search): range value should be maintained.
+
+Thu Sep 10 10:55:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (backref_error): yyerror does not understand formats.
+
+Tue Sep 8 18:05:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c5 released.
+
+Tue Sep 8 10:03:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_each_line): wrong line splitting with newline at
+ top of the string.
+
+ * string.c: non bang methods return copied string.
+
+ * eval.c (f_END): needed to initialize frame->argc;
+
+Fri Sep 4 11:27:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (bigadd): proper sign combination.
+
+ * regex.c (re_search): wrong return value for \A.
+
+>>>>>>> 1.1.1.2.2.154
+Thu Sep 3 14:08:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c4 released.
+
+Tue Sep 1 10:47:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (slow_search): do not compare llen and blen. llen may
+ be longer than blen, if little contains 0xff.
+
+ * regex.c (mbctab_euc): set 0x8e as multibyte character.
+
+ * string.c (str_inspect): mask character for octal output.
+
+Mon Aug 31 15:32:41 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): use calculated offset if exactn is the
+ first opcode in the compiled regexp.
+
+ * regex.c (bm_search): use Boyer-Moore search for simple search.
+
+ * regex.c (must_instr): wrong length check if pattern includes
+ byte escape by 0xff.
+
+ * regex.c (re_compile_pattern): need not to check current_mbctype.
+
+Sat Aug 29 16:31:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_check_safe_str): avoid calling rb_id2name() in normal
+ cases to speed-up.
+
+ * eval.c (thread_raise): do not save context of terminated thread.
+
+ * regex.c (re_compile_pattern): mask \nnn over 256.
+
+Sat Aug 29 02:09:46 1998 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sprintf.c (f_sprintf): wrong buffer size check.
+
+Fri Aug 28 01:57:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): accepts (?ix-ix) and (?ix-ix:...).
+
+Fri Aug 28 12:25:33 1998 Hiroshi Igarashi <igarashi@ueda.info.waseda.ac.jp>
+
+ * ruby.c (ruby_require_modules): load modules in appearing order.
+
+Fri Aug 28 01:57:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): accepts (?ix-ix) and (?ix-ix:...).
+
+Thu Aug 27 12:54:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c3 released.
+
+Wed Aug 26 14:40:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): check whether ruby_class is properly set,
+ before accessing it.
+
+ * eval.c (rb_obj_instance_eval): ruby_class should be Qnil for
+ special objects like Fixnums.
+
+ * ext/tkutil/tkutil.c (Init_tkutil): removes calls to
+ rb_yield_0(). used instance_eval() instead in the tk.rb.
+
+Wed Aug 26 11:47:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): pop non-greedy stack elements on success.
+
+Wed Aug 26 09:25:35 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ruby.h: add #define environ for cygwin32.
+
+Tue Aug 25 08:57:41 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_sort_bang): temporarily freeze sorting array.
+
+Mon Aug 24 18:46:44 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dln.c (dln_find_1): path check was too strict.
+
+Mon Aug 24 15:28:11 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * parse.y (f_arglist): opt_nl added after f_args.
+
+Fri Aug 21 01:06:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c: grand renaming on socket.c.
+
+ * ext/socket/socket.c (inet_aton): supply inet_aton for those
+ systems that do not have it.
+
+ * ext/socket/socket.c (setipaddr): use inet_aton instead of
+ inet_addr.
+
+ * ext/socket/socket.c (tcp_s_gethostbyname): new method: works
+ like Socket.gethostbyname but returning array contains ip-addrs
+ as octet decimal string format like "127.0.0.1".
+
+ * ext/socket/socket.c (mkhostent): return format changed to
+ [host, aliases, type, ipaddr..] as documented.
+
+Wed Aug 19 00:31:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_ctl): forgot to place TRAP_END at right position.
+
+Fri Aug 14 11:01:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (call_trace_func): save __FILE__, __LINE__ before
+ executing trace_func, since trace function should not corrupt
+ line number information.
+
+Thu Aug 13 15:09:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_s_new): was marking unallocated region on GC.
+
+Tue Aug 11 11:57:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c2 released.
+
+Mon Aug 10 14:05:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * process.c (f_system): removed fflush(stdin).
+
+Fri Aug 7 17:44:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (err_snprintf): replace sprintf for fixed sized buffer,
+ with snprintf to avoid buffer over-run. For systems which does
+ dot provide snprintf, missing/snprintf.c added.
+
+Wed Aug 5 00:47:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_search): recycle match object.
+
+Mon Aug 3 09:17:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_gsub_bang): do not allocate temporary string.
+
+ * string.c (rb_str_sub_bang): use inline replace.
+
+Wed Jul 29 00:36:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_s_new): the default value can be specified.
+
+ * hash.c (hash_default): method to set the default value.
+
+ * hash.c (hash_aref): now returns the default value.
+
+Tue Jul 28 13:03:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_s_new): argument to specify initial value is added.
+
+ * array.c (ary_s_new): specifies size, not capacity.
+
+Mon Jul 27 12:39:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_replace): zero fill for expansion gap.
+
+ * regex.c (mbctab_euc): set flags on for 0xA1-0xFE. suggested by
+ <inaba@st.rim.or.jp>.
+
+ * string.c (str_inspect): consider current_mbctype.
+
+Sun Jul 26 15:37:11 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * array.c (ary_s_new): Array.new(1<<30) dumps core.
+
+Fri Jul 24 13:40:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c1 released.
+
+Fri Jul 24 02:10:22 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_bytes2): allocated buffer size was too short.
+
+ * marshal.c (w_object): saves all options, not only casefold flag.
+
+ * re.c (reg_clone): now copies options properly.
+
+ * re.c (reg_get_kcode): code number was wrong.
+
+Thu Jul 23 13:11:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_attr): argument should be symbol or string.
+
+Wed Jul 22 11:59:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (calculate_must_string): wrong offset added.
+
+Wed Jul 22 11:59:59 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * st.c (rehash): still had a GC problem. fixed.
+
+Tue Jul 21 13:19:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (gc_mark_threads): crashed on GC before thread allocation.
+
+ * st.c (rehash): GC during rehash caused SEGV.
+
+Tue Jul 21 01:25:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): integer formatter totally re-written.
+
+ * sprintf.c (remove_sign_bits): support uppercase hexadecimal.
+
+Sat Jul 18 00:14:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): proper sign position for %X and %O.
+
+Fri Jul 17 14:10:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c0 released.
+
+Fri Jul 17 08:01:49 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * process.c (f_exec): Check_SafeStr() added.
+
+ * process.c (f_system): Check_SafeStr() moved before fork().
+
+Thu Jul 16 22:58:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (scan_once): substrings to the block should not be
+ tainted. use reg_nth_match(), not str_substr().
+
+ * string.c (str_substr): needed to transfer taint.
+
+Thu Jul 16 16:15:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (xmalloc): object allocation count added to GC trigger.
+
+ * eval.c (thread_save_context): avoid marking uninitialized stack
+ in thread_mark. GC may be triggered by REALLOC_N().
+
+Wed Jul 15 15:11:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_31.
+
+Wed Jul 15 15:05:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_create): exit() and abort() in threads now
+ forwarded to main_thread.
+
+Tue Jul 14 14:03:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (obj_instance_variables): list names that is not
+ instance variables.
+
+ * gc.c (GC_MALLOC_LIMIT): choose smaller limit value.
+
+Mon Jul 13 12:39:38 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (str2cstr): should not return NULL.
+
+Fri Jul 10 11:51:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (gettable): needed to add dyna_in_block() check.
+
+Thu Jul 9 17:38:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_30.
+
+Thu Jul 9 16:01:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (fmt_setup): format specifier for long needed.
+
+ * sprintf.c (f_sprintf): ditto.
+
+ * numeric.c (fix2str): ditto.
+
+ * eval.c (thread_create): no more ITIMER_REAL.
+
+ * eval.c (thread_create): thread finalization needed before
+ aborting thread if thread_abort is set.
+
+Wed Jul 8 18:17:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (big_pow): abandon power by bignum (too big).
+
+Tue Jul 7 13:58:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_catch): add C level catch/throw feature.
+
+Mon Jul 6 15:18:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): proper return values for `||=' and `&&='.
+
+Fri Jul 3 16:05:11 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_29.
+
+Fri Jul 3 11:20:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_byte): byte should not extend sign bit.
+
+ * numeric.c (fix_mul): use FIX2LONG() instead of FIX2INT() for
+ 64bit architectures.
+
+ * marshal.c (r_bytes): remove weird casting bwetween pointer and int.
+
+ * process.c (proc_setsid): new method Process#setsid().
+
+Thu Jul 2 12:49:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (w_object): remove `write_bignum' label for 64bit
+ architectures.
+
+ * marshal.c (r_bytes): needs int, not long.
+
+Wed Jul 1 14:21:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (flo_plus): should not allow addition with strings.
+
+Wed Jul 1 13:09:01 1998 Keiju ISHITSUKA <keiju@rational.com>
+
+ * numeric.c (num_uminus): wrong coerce direction.
+
+Tue Jun 30 10:13:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (f_p): accepts arbitrary number of arguments.
+
+ * eval.c (rb_yield_0): there's some case that iterator_p() returns
+ true even if the_block was not set. check added.
+
+Tue Jun 30 01:05:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (BEGIN_CALLARGS): adjust the_block before evaluating the
+ receiver's value and the arguments.
+
+Fri Jun 26 18:02:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_28.
+
+Fri Jun 26 11:01:26 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (str_aset_method): needed to convert to string.
+
+Thu Jun 25 02:05:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): optimize for `.*' at beginning of the
+ pattern.
+
+ * regex.c (re_search): optimize for character class repeat at
+ beginning of the pattern.
+
+ * regex.c (re_compile_pattern): detect optimization potential for
+ the compiled patterns.
+
+Thu Jun 25 00:02:26 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * re.c (reg_s_new): flag value was wrong.
+
+Wed Jun 24 23:45:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): wrong anchor handling for reverse search.
+
+Wed Jun 24 02:18:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (mlhs): `((a,b)),c = [[1,2]],3' assigns a=1,b=2,c=3.
+
+Tue Jun 23 11:46:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `&&=' and `||=' added.
+
+Sat Jun 20 02:53:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (assignable): nesting local variables should have higher
+ priority than normal local variables for assignment too.
+
+Fri Jun 19 18:28:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_27.
+
+Fri Jun 19 14:34:49 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (assign): support hack for nested multiple assignment.
+
+ * parse.y (mlhs): nested multiple assignment.
+
+ * eval.c (rb_eval): in-block variables now honors static scope.
+
+ * configure.in: RSHIFT check moved to configure.
+
+Thu Jun 18 16:46:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_26.
+
+Thu Jun 18 13:37:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (file_s_ftype): uses lstat(2) instead of stat(2).
+
+ * dir.c (dir_s_glob): there can be buffer overrun, check added.
+
+ * eval.c (f_binding): handles in-block variables declared after
+ binding's generation.
+
+ * numeric.c (flo_floor): floor, ceil, round added to Float.
+
+Wed Jun 17 11:20:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (gettable): nesting local variables should have higher
+ priority than normal local variables.
+
+Tue Jun 16 12:30:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (str2inum): handles `+ddd'.
+
+ * struct.c (make_struct): name parameter can be nil for unnamed
+ structures.
+
+Mon Jun 15 16:30:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (class_s_inherited): prohibiting to make subclass of
+ class Class.
+
+ * object.c (module_s_new): support for making subclass of Module.
+
+ * parse.y (yycompile): clear eval_tree before compiling.
+
+Fri Jun 12 17:58:18 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (eval): write back the_dyna_var into the block.
+
+Thu Jun 11 18:19:18 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_25.
+
+ * eval.c (dvar_add_compiling): register dyna_var at compile time.
+
+ * regex.c (re_compile_pattern): RE_DUP_MAX iteration is too big.
+
+Wed Jun 10 15:12:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_eof): do not block other threads.
+
+ * signal.c (trap): reserve SIGALRM for thread.
+
+ * eval.c (thread_create): use ITIMER_REAL also to avoid system
+ call blocking.
+
+ * io.c (f_syscall): add TRAP_BEG, TRAP_END around system calls.
+
+ * io.c (io_ctl): add TRAP_BEG, TRAP_END around system calls.
+
+ * enum.c (enum_collect): did not collect false values.
+
+ * array.c (ary_new2): forgot to initialize capa field.
+
+Tue Jun 9 18:36:15 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (str_split_method): split dumped core for "\xff".
+
+Tue Jun 9 16:22:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_24.
+
+Tue Jun 9 16:04:07 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/kconv/kconv.c (kconv_guess): more precise decision for EUC,
+ using jless algorithm (3 sequential EUC hiragana characters).
+
+Tue Jun 9 15:12:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/kconv/kconv.c (kconv_guess): wrong guess for EUC as SJIS in
+ some cases (0xe0 - 0xef).
+
+ * gc.c (xmalloc): insert size check for big (negative in signed)
+ allocation size.
+
+Tue Jun 9 02:54:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/parsedate.rb: wday moved to the last in the return values.
+
+Mon Jun 8 10:40:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_split_method): split dumped core for "\0".
+
+Sat Jun 6 22:50:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (calculate_must_string): wrong condition for
+ {start,stop}_nowidth.
+
+ * regex.c (re_match): various features imported from GNU regex.c
+ 0.12, such as nested grouping, avoiding infinite loop with empty
+ match, etc.
+
+ * regex.c (register_info_type): now use union.
+
+ * regex.c (re_search): more precise anchor(^) check.
+
+Wed Jun 3 18:07:54 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_raise): check rb_in_compile, not rb_in_eval.
+
+Mon Jun 1 05:26:06 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * string.c (trnext): casting to signed char* needed.
+
+Tue Jun 2 16:00:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (udp_addrsetup): error check enhanced.
+
+ * ext/socket/socket.c (sock_s_getservbyaname): use strtoul(), if
+ possible.
+
+Sat May 30 07:10:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_prepare_re): no more needless regular expression
+ recompile on casefold conditions.
+
+Thu May 28 18:02:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (nil_plus): no more `+' method for nil.
+
+Wed May 27 17:33:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_fetch): new method.
+
+ * regex.c (re_search): check whether translate table is set.
+
+Tue May 26 11:39:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_23.
+
+ * parse.y (yylex): no UPLUS/UMINUS for 1st argument if
+ parenthesises are omitted.
+
+Tue May 26 01:09:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): (?XI) for turns off the
+ corresponding option.
+
+Mon May 25 12:38:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): inline i option (?i).
+
+ * regex.c (re_compile_pattern): inline x option (?x).
+
+ * regex.c (re_compile_pattern): x option for regexp.
+
+ * dir.c (dir_s_open): returns block's evaluated value.
+
+ * io.c (f_open): returns block's evaluated value.
+
+ * ext/curses/curses.c (curses_addstr): nil argument caused SEGV.
+
+Fri May 22 11:52:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): push mark on (?:), so that
+ laststart check for {a,b} can be done.
+
+Thu May 21 17:31:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): wrong match (too non-greedy) for `{a,b}?'.
+
+ * io.c (io_lineno): new method IO#lineno, IO#lineno=.
+
+Wed May 20 06:04:43 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * BeOS patch.
+
+Wed May 20 16:32:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (BIGDN): use RSHIFT(), instead of mere `>>'.
+
+Tue May 19 16:36:26 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_22.
+
+Tue May 19 16:31:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (assignable): specification changed for in-block
+ variable definition.
+
+ * eval.c (dyna_var_asgn): error in in-block variables' compile
+ time definition.
+
+ * parse.y (str_extend): wrong nesting detection.
+
+Tue May 19 09:47:55 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * numeric.c (num2int): re-defined (extensions may use this).
+
+Mon May 18 16:40:50 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * error.c (get_syserr): BeOS support.
+
+ * configure.in: modified for BeOS.
+
+ * string.c (str_dump): do not call isascii().
+
+ * sprintf.c (remove_sign_bits): forgot to initialize end pointer.
+
+ * glob.c: #include <alloca.h> added.
+
+Mon May 18 14:52:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_21.
+
+Mon May 18 03:27:57 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * file.c (file_s_expand_path): optional second argument
+ `default_directory' added.
+
+Sat May 16 22:06:52 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * error.c (RAISE_ERROR): wrong error message
+
+Fri May 15 14:43:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_20.
+
+Thu May 14 14:44:21 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * sun4 cc patches for intern.h and regex.h.
+
+Thu May 14 14:03:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (RANDOM_MAX): guessing proper maximum value for random
+ numbers.
+
+ * random.c (f_rand): use drand48 if possible.
+
+Wed May 13 19:05:20 1998 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * BeOS patches for io.c, error.c and config.guess.
+
+Wed May 13 14:56:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_19.
+
+ * most of the Mac and BeOS patches merged, except path separators.
+
+ * error.c (err_append): generated SyntaxError was String.
+
+ * ruby.h: xxx2INT, xxx2UINT checks values as int, not long.
+
+ * ruby.h: remove typedef's. INT, UINT, UCHAR, USHORT.
+
+Tue May 12 17:38:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_18.
+
+Tue May 12 11:38:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (syserr_errno): returns errno of the SystemCallError.
+
+ * error.c (rb_sys_fail): saves errno in the Exception.
+
+ * error.c (set_syserr): no need to protect syserr_list.
+
+ * error.c (rb_sys_fail): no more bufsize limit.
+
+ * error.c (set_syserr): integer value of errno can be accessed by
+ Errno::EXXX::Errno.
+
+Sun May 10 03:10:33 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * io.c (io_tell etc.): moved from File class to IO class.
+
+Fri May 8 12:26:37 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_unpack): should be unsigned int (was signed int).
+
+Thu May 7 16:34:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_pack): `V', `N' uses newly created NUM2UINT().
+
+ * ruby.h (NUM2UINT): new macro.
+
+ * bignum.c (big2uint): try to convert bignum into UINT.
+
+ * re.c (reg_match): needed to return false for match with nil.
+
+ * gc.c (obj_free): wrong condition to free string.
+
+Wed May 6 21:08:08 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ruby.c (ruby_process_options): modified for DJGPP.
+
+Wed May 6 15:48:03 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_17.
+
+Wed May 6 01:37:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c: remove global variable `errat'.
+
+ * eval.c (rb_longjmp): embed error position information in the
+ exception object.
+
+Sat May 2 12:20:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_search): supports reverse search.
+
+ * string.c (str_index_method): does update $~ etc.
+
+ * eval.c (f_load): needed to clear the_dyna_vars.
+
+ * eval.c (dyna_var_asgn): do not push dyna_var, which is id == 0.
+
+ * error.c (Init_Exception): NotImplementError is no longer
+ StandardError, which is not handled by default rescue.
+
+Fri May 1 00:35:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): `-d' turns on verbose flag too.
+
+ * error.c (exception): last argument may be the superclass of the
+ defining exception(s).
+
+ * io.c (Init_IO): EOFError is now subclass of the IOError.
+
+ * io.c (Init_IO): forgot to define IOError.
+
+ * error.c (Init_Exception): old Exception class renamed to
+ StandardError. Exception now replaces old GlobalExit.
+
+ * error.c (Init_Exception): Exception is now the root of the
+ Global Exits. There's no longer GlobalExit class.
+
+ * util.c (ruby_mktemp): check TMP, TMPDIR first.
+
+Thu Apr 30 01:08:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/tk.rb: call 'unknown', if proc not defined.
+
+ * eval.c (handle_rescue): default rescue handles `Exceptional' not
+ only the instance of the `Exception's.
+
+ * eval.c (f_raise): exception can be any object.
+
+ * time.c (time_gm_or_local): call time_gmtime or time_localtime.
+
+ * eval.c (f_raise): raises TypeError if the class which is not a
+ subclass of String is specified (checked in exc_new()).
+
+ * error.c (exc_new): need to check whether invalid class (not a
+ subclass of String) is specified.
+
+Wed Apr 29 21:05:44 1998 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ruby.c (proc_options): option '-e' via tempfile.
+
+Tue Apr 28 15:27:58 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_16.
+
+Tue Apr 28 00:07:38 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_is_proc): type check predicate.
+
+ * eval.c (obj_is_block): ditto.
+
+Mon Apr 27 16:59:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/gtk/gtk.c (Init_gtk): use timeout, not idle to avoid
+ comsuming CPU too much.
+
+ * lib/tk.rb: use tcltklib#_invoke instead of `_eval'.
+
+Mon Apr 27 16:59:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_sort): use dup, not clone.
+
+Mon Apr 27 13:46:27 1998 Tadahiro Maebashi <maebashi@iij.ad.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_invoke): invoke tcl command
+ directly. need not worry about escaping tcl characters.
+
+Mon Apr 27 12:04:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (f_rand): do not call srand() implicitly.
+
+Fri Apr 24 14:35:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_15.
+
+ * parse.y (assignable): dyna_var_asgn actually defines nested
+ local variables in outer context.
+
+ * random.c (f_rand): call srand(), if it has not called yet.
+
+ * random.c (f_srand): use tv_usec as the default seed.
+
+ * eval.c (rb_eval): values of nested local variables should be
+ independent.
+
+ * eval.c (rb_yield_0): local variables wrong nested conditions.
+
+Wed Apr 22 23:27:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (select_get_io): get IO object by `to_io'.
+
+ * io.c (io_to_io): method to retrieve IO object, from delegating
+ object for example.
+
+Wed Apr 22 16:52:37 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_14.
+
+ * string.c (str_modify): check for embedded pointer reference.
+
+ * gc.c (obj_free): ditto.
+
+ * pack.c (pack_pack): p/P template to embed pointers.
+
+Wed Apr 22 00:07:10 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * array.c (ary_rindex): embarrassing typo.
+
+Tue Apr 21 12:31:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_13.
+
+ * configure.in (RUBY_LIB): supports --program-{prefix,suffix}.
+
+ * array.c (ary_rindex): new method.
+
+ * io.c (io_binmode): should return self.
+
+Tue Apr 21 08:23:04 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * parse.y (here_document): calling parse_string with wrong
+ arguments.
+
+ * struct.c (struct_aset): problem member assignment with name.
+
+Mon Apr 20 14:47:49 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_12.
+
+ * time.c (time_arg): args may be string (support for reduced
+ implicit type conversion).
+
+ * lib/base64.rb: changed to use pack/unpack with `m' template.
+
+Mon Apr 20 06:23:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (mod_remove_const): new method.
+
+Sat Apr 18 03:53:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_each_with_index): removed. use Enumerable's
+ each_with_index instead.
+
+ * class.c (rb_include_module): check for super modules, since
+ module's included modules may be changed.
+
+Fri Apr 17 21:50:47 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * marshal.c (r_long): r_byte() may return signed byte.
+
+Fri Apr 17 11:58:30 1998 NAGAI Hidetoshi <nagai@dumbo.ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_mainloop): thread and interrupt check.
+
+Fri Apr 17 11:06:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (find_file): try to fopen() to check whether file exists.
+
+ * ruby.c (load_file): ditto.
+
+ * struct.c (struct_aset): struct member can be set by member name.
+
+Fri Apr 17 00:47:19 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/extmk.rb.in: added m68k-human support
+
+ * file.c (LOCK_SH): defines moved.
+
+ * array.c (ary_flatten_bang): simplified loop.
+
+Thu Apr 16 16:52:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_11.
+
+ * lib/tk.rb: thread support (experimental - maybe slow).
+
+ * eval.c (rb_longjmp): trace event on exception in raising
+ context, just before raising exception.
+
+ * struct.c (struct_s_members): forgot to check singletons.
+
+ * struct.c (struct_aref): members can be accessed by names too.
+
+ * array.c (ary_flatten): new method.
+
+ * eval.c (rb_longjmp): prints exception information with `-d'.
+
+ * object.c (any_to_s): remove class name restriction.
+
+Thu Apr 16 01:38:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (thread_flock): do not block other threads.
+
+ * eval.c (thread_trap_eval): signals are now delivered to the
+ current thread again. In case that the current thread is dead,
+ signals are forwarded to the main thread.
+
+ * string.c (str_new4): need not to duplicate frozen strings.
+
+Wed Apr 15 08:33:47 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * struct.c (struct_inspect): remove restriction for struct names.
+
+Wed Apr 15 02:55:02 1998 Kazuya 'Sharl' Masuda <sharl@www.ufo.co.jp>
+
+ * x68 patches to config.sub, ext/extmk.rb.in
+
+Wed Apr 15 01:22:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_dup_frozen): do not duplicate frozen strings.
+
+ * parse.y (yylex): allow nested parenthesises.
+
+ * io.c (obj_displayln): prints newline after `display'ing the
+ receiver.
+
+ * io.c (io_puts): avoid generating "\n" each time. use RS_default
+ instead.
+
+ * io.c (f_p): ditto.
+
+Tue Apr 14 22:18:17 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * struct.c (struct_aref): should not subtract negative index.
+
+Tue Apr 14 11:34:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_10.
+
+ * parse.y: token names prefixed by `t'.
+
+ * struct.c (struct_s_def): supports subclassing of Struct.
+
+ * io.c (io_s_new): supports subclassing of IO.
+
+Mon Apr 13 11:07:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (f_binding): need to restore method name.
+
+ * eval.c (rb_call0): raises SystemStackError, not Fatal.
+
+ * io.c (obj_display): same as `print self'.
+
+ * io.c (f_p): can now be called in the method form.
+
+ * re.c (reg_regsub): needed to be mbchar aware.
+
+Mon Apr 13 13:18:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_trap_eval): all signals delivered to main_thread.
+
+Mon Apr 13 12:47:03 1998 TAKAHASHI Masayoshi <maki@inac.co.jp>
+
+ * re.c (kcode_set_option): did not set SJIS on SJIS condition.
+
+Sun Apr 12 22:14:07 1998 Kazunori NISHI <kazunori@swlab.csce.kyushu-u.ac.jp>
+
+ * array.c (ary_uniq_bang): should be `==', not `='. embarrassing.
+
+Sat Apr 11 02:13:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_subseq): SEGVed for `[][1,1]'.
+
+Fri Apr 10 21:29:06 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * array.c (ary_subseq): add check for beg larger than array length.
+
+Wed Apr 8 17:24:11 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * dir.c (dir_s_open): can be called with block (like IO#open).
+
+ * dir.c (dir_s_chdir): print directory path on error.
+
+ * dir.c (dir_s_chroot): ditto
+
+ * dir.c (Init_Dir): needed to override `new'.
+
+Thu Apr 9 18:24:58 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_09.
+
+ * string.c (str_cmp): do not depend on sentinel at the end of the
+ strings.
+
+ * string.c (str_chomp_bang): forgot to set the sentinel.
+
+Wed Apr 8 00:59:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (big2int): converted int may be too big to fit in
+ signed int.
+
+ * parse.y (arg): `foo += 1' should not cause an error.
+
+ * variable.c (rb_const_defined): returned false even if the
+ constant is defined at the top level.
+
+ * eval.c (f_local_variables): dyna_var->id may be null. should
+ have checked before calling str_new2().
+
+Tue Apr 7 01:15:15 1998 Kaneko Naoshi <wbs01621@mail.wbs.or.jp>
+
+ * re.c (reg_regsub): need to check string boundary.
+
+Tue Apr 7 19:19:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_cmp): returns either 1, 0, -1.
+
+ * array.c (ary_cmp): should check array length, too
+
+Tue Apr 7 18:50:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_08.
+
+Tue Apr 7 18:31:27 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * instruby.rb (mandir): dll installation for cygwin32
+
+Tue Apr 7 01:16:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * config.sub (maybe_os): TOWNS support?
+
+ * config.guess: too strict check for libc versions on linuxes.
+
+ * experimental release 1.1b9_07.
+
+ * array.c (ary_cmp): compare each element using `<=>'.
+
+ * hash.c (hash_each_with_index): yields [value, key] pair.
+
+ * class.c (class_protected_instance_methods): list protected
+ method names.
+
+ * class.c (ins_methods_i): exclude protected methods.
+
+ * eval.c (PUSH_BLOCK): dynamic variables can be accessed from
+ eval() with bindings.
+
+Mon Apr 6 14:49:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_yield): must return evaluated value.
+
+Fri Apr 3 13:07:29 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_schedule): context switch bypassed on wrong
+ conditions.
+
+ * variable.c (rb_name_class): set classname by id before String
+ class is initialized (1.0 behavior restored).
+
+Fri Apr 3 11:25:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (num2int): no implicit conversion from string.
+
+ * numeric.c (num2int): check whether `to_i' returns an Integer.
+
+ * numeric.c (num_zero_p): new method.
+
+ * numeric.c (num_nonzero_p): new method. returns the receiver if
+ it's not zero.
+
+ * eval.c (obj_instance_eval): the_class should be the object's
+ singleton class.
+
+ * error.c (exc_s_new): message is converted into a string.
+
+Thu Apr 2 18:31:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_call_init): every object call `initialize'.
+
+Wed Apr 1 08:51:53 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * parse.y (stmt): UNTIL_MOD should be for stmt, not only for expr.
+
+Wed Apr 1 01:20:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (true_and): boolean operators &, | and ^.
+
+Tue Mar 31 13:23:58 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_compact_bang): returns nil, if it does not modify
+ the array like String's bang methods.
+
+ * array.c (ary_uniq_bang): new method to remove duplicate items.
+
+ * eval.c (bind_s_new): new method.
+
+ * numeric.c (num2int): raise exception if Fixnums too big to
+ convert into `int' in case that sizeof(int) < sizeof(INT).
+
+ * string.c (str_center): SEGV on negative width.
+
+ * eval.c (eval): forgot to set sourcefile.
+
+Mon Mar 30 11:12:29 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (f_test): raises exception for unkown command.
+
+ * eval.c (Init_eval): `class_eval': alias to the module_eval.
+
+Mon Mar 30 18:50:42 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * string.c (str_capitalize_bang): did not check string modification.
+
+ * string.c (str_delete_bang): wrong conversion.
+
+ * string.c (str_intern): typo in error message.
+
+Mon Mar 30 01:44:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_instance_eval): accepts block as evaluation body.
+ No compilation needed each time.
+
+ * eval.c (mod_module_eval): ditto
+
+ * file.c (file_s_umask): umask did not return old values, if no
+ argument given.
+
+Sun Mar 29 00:54:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (f_throw): nil returned always.
+
+Sat Mar 28 20:40:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_06.
+
+Sat Mar 28 16:07:11 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * io.c (io_closed): should not cause exception fot closed IO.
+
+ * string.c (str_tr): returned nil for success.
+
+Sat Mar 28 00:47:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (f_local_variables): new method to return an array of
+ local variable names.
+
+ * variable.c (obj_instance_variables): now returns an array of
+ variable names, as described in the reference.
+
+ * eval.c (rb_attr): honors default method visibility of the
+ current scope.
+
+Fri Mar 27 13:49:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_05.
+
+ * ruby.c (ruby_prog_init): `site_ruby' added to load_path.
+
+ * ruby.c (ruby_prog_init): load-path order changed. Paths in
+ the RUBYLIB environment variable comes first in non-tainted
+ mode.
+
+Thu Mar 26 11:51:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call): new feature: `protected' methods.
+
+ * string.c (str_dump): new method.
+
+ * eval.c (block_pass): block argument can be nil, which means no
+ block is supplied for the method.
+
+Wed Mar 25 21:20:13 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * string.c (str_reverse_bang): string copied to wrong place.
+
+Wed Mar 25 08:12:07 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (flo_modulo): caused SEGV if left operand is not a
+ float value.
+
+ * eval.c (f_eval): optional third and fourth argument to specify
+ file-name and line-number.
+
+ * eval.c (eval): file-name and line-number set properly.
+
+ * parse.y (assign_in_cond): literal assignment is now warning, not
+ compile error.
+
+ * error.c (Warn): Warn() always print message, OTOH Waring()
+ prints when verbose flag is set.
+
+Tue Mar 24 12:50:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (ruby_prog_init): `.' should come last in the load-path.
+
+ * eval.c (Init_eval): `__send__', alias for `send'.
+
+Mon Mar 23 12:44:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_chomp_bang): now takes `rs' as an argument.
+
+ * eval.c (thread_free): main_thread should not be freed.
+
+Fri Mar 20 16:40:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_chomp_bang): chomp! (and other ! methods) returns
+ nil if it does not modify the string.
+
+ * string.c (str_sub_iter_s): should check last pattern since it
+ may be matched to null.
+
+Thu Mar 19 13:48:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_04.
+
+ * parse.y (yylex): `10e0.9' should cause syntax error.
+
+Wed Mar 18 17:46:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (load_file): new file object constant DATA. Only
+ available for the script from the file.
+
+ * regex.c (re_match): forwading failure point popped too much.
+
+Tue Mar 17 18:23:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * math.c (math_frexp): newly added.
+
+ * math.c (math_ldexp): ditto.
+
+ * bignum.c (bigdivmod): calculates modulo.
+
+ * numeric.c (fix_remainder): returns reminder, formerly introduced
+ as modulo.
+
+ * numeric.c (fix_modulo): calculates proper `modulo'.
+
+ * bignum.c (bigdivmod): wrong sign for reminder.
+
+Mon Mar 16 17:07:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_03.
+
+Mon Mar 16 16:33:53 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * io.c (pipe_finalize): needed to add pipe_finalize to pipes on
+ cygwin32.
+
+Mon Mar 16 14:11:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (ins_methods_i): needed to consider NOEX_UNDEF.
+
+Mon Mar 16 13:23:53 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * io.c (io_check_closed): check for `fptr->f2 == NULL'.
+
+ * io.c (io_fptr_close): ditto.
+
+Mon Mar 16 11:49:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (pipe_atexit): free()ing referencing pipe_list.
+
+ * range.c (range_length): returns zero, if the first is greater
+ than the last.
+
+ * signal.c (trap_restore_mask): restore signal mask before raising
+ exceptions and throws.
+
+Fri Mar 13 13:49:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_02.
+
+ * object.c (mod_clone): need to dups constants and instance
+ variables.
+
+ * eval.c (rb_eval): forgot to initialize body for NODE_DEFS.
+
+ * eval.c (rb_eval): retrieve self from calling frame, since self
+ changes sometimes.
+
+ * env.h (FRAME): need to save self in the calling frame.
+
+ * io.c (f_gets_method): rs should be initialized by RS.
+
+Thu Mar 12 15:33:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_01.
+
+ * range.c (range_s_new): check values by `first <= last'.
+
+ * parse.y (lastline_set): fixed offset for $_ and $~ in the local
+ variable space.
+
+Wed Mar 11 02:14:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_gets): handle normal case specially for speed.
+
+ * eval.c (rb_disable_super): function to disable superclass's
+ method explicitly.
+
+ * eval.c (rb_eval): inherits previous method definition's
+ NOEX_UNDEF-ness, if exists.
+
+ * class.c (rb_define_method): disables superclass's overriding
+ method by default.
+
+Wed Mar 11 01:40:48 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * numeric.c (flo_gt,etc.): do not depend on `<=>', to handle NaN.
+
+Tue Mar 10 00:03:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (load_file): understands multiple options in #! line.
+
+ * regex.c (re_compile_pattern): support for [:alpha:] etc.
+
+Mon Mar 9 16:53:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.h (GetOpenFile): embed io_check_closed in GetOpenFile.
+
+ * sprintf.c (f_sprintf): zero padding failed for negative
+ integers.
+
+ * sprintf.c (remove_sign_bits): failed to remove some bits.
+
+Sat Mar 7 21:51:46 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * class.c (ins_methods_i): body may be NULL for some case.
+
+Fri Mar 6 17:23:07 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (mbcinit): table driven mbchar detection.
+
+ * object.c (obj_alloc): check for allocating instance for the
+ primitive classes (mostly perfect).
+
+ * ext/curses/curses.c (curses_finalize): restore original state at
+ interpreter temination.
+
+ * ext/curses/curses.c (curses_addstr): forgot to check argument
+ type (caused SEGV). now uses STR2CSTR() macro.
+
+Thu Mar 5 13:47:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (block_pass): accepts method object as block args.
+
+ * eval.c (f_missing): use any_to_s() for stringify.
+
+Wed Mar 4 01:39:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (block_arg): new syntax - block argument in the
+ calling arglist.
+
+ * eval.c (rb_call): no module search. simplified a lot.
+
+ * eval.c (rb_eval): block arg support.
+
+ * parse.y (f_block_arg): new syntax - block argument in the
+ formal arglist.
+
+Tue Mar 3 14:20:15 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_method): returns bound method object.
+
+ * eval.c (rb_call): argument check for empty methods.
+
+ * ruby.h (NUM2CHR): new macro, originally from curses module.
+
+Tue Mar 3 13:03:35 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * io.c (io_putc): new method.
+
+Tue Mar 3 11:21:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_inspect): more strict charcode detection.
+
+ * eval.c (thread_stop): stopping only thread raises ThreadError
+ exception.
+
+Tue Mar 3 08:04:56 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * struct.c (struct_alloc): imcomplete struct initialization made
+ GC to access unallocated addresses.
+
+Mon Mar 2 16:28:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_stop_method): remove Thread#stop.
+
+Fri Feb 27 18:16:26 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1b9 released.
+
+Fri Feb 27 09:36:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_delete_nil): needed to compare value to nil, since
+ nil is the valid key for hashes.
+
+ * hash.c (hash_foreach_iter): rehashing causes IndexError.
+
+ * hash.c (hash_foreach_iter): rehash check by pointer comparison.
+
+Thu Feb 26 17:22:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (fname): convert reswords into symbols.
+
+ * parse.y (reswords): reserved words are now embedded in the
+ syntax (sigh).
+
+ * parse.y: now reserved words can be method names safely.
+
+Wed Feb 25 15:50:07 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (mod_module_eval): clear the_scope's PRIVATE flag before
+ calling eval().
+
+ * gc.c (gc_call_finalizer_at_exit): run finalizers before any data
+ object being freed.
+
+ * eval.c (rb_eval): needed to keep prot_tag->retval before
+ evaluating the ensure clause.
+
+Tue Feb 24 11:16:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): reserved words can be appear as method names at
+ right after 'def' and `.'(dot), like foo.next.
+
+ * eval.c (return_check): checks for return out of thread (formerly
+ done in return_value).
+
+ * eval.c (POP_TAG): copy retval to outer level.
+
+ * eval.c (return_value): just set retval, no check, no unwinding.
+
+ * parse.y (nextc): line continuation by backslash at end of line.
+
+ * regex.c (re_compile_pattern): forgot to clear pending_exact on
+ closing parentheses.
+
+ * parse.y (assignable): should not assign dyna_var to true, if it
+ is already defined.
+
+Mon Feb 23 14:35:03 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (obj_is_kind_of): no longer accepts true/false/nil.
+
+ * object.c ({true,false,nil}_to_i): can be converted into integers.
+
+Mon Feb 23 12:11:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_s_quote): needed to be mbchar aware.
+
+ * eval.c (proc_s_new): wrong iter mark.
+
+Sat Feb 21 22:59:30 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * io.c (f_syscall): no argument check.
+
+Fri Feb 20 10:17:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1b8 released.
+
+ * ext/kconv/kconv.c (kconv_kconv): default output code now be
+ determined according to the value of $KCODE.
+
+ * re.c (rb_get_kcode): can retrieve $KCODE from C code.
+
+ * parse.y (stmt): if/unless modifiers returns nil, if condition is
+ not established.
+
+Thu Feb 19 11:06:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/kconv/kconv.c (kconv_kconv): charcode can be specified by
+ code name (JIS, SJIS, EUC like value of $KCODE).
+
+ * regex.c (re_compile_pattern): forgot to fixup_jump for (?:..).
+
+ * regex.c (re_compile_pattern): needed to clear pending_exact on
+ non-registering grouping (?:...).
+
+Wed Feb 18 19:54:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): needed to set lex_state to EXPR_END.
+
+Wed Feb 18 18:45:10 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * patches for cygwin32 applied.
+
+Wed Feb 18 00:41:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_sub_s): needed to be mbchar aware to increment one
+ character.
+
+ * regex.c (re_match): \Z matches newline just before the end of
+ the string.
+
+Tue Feb 17 00:04:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_arg): Time.gm and Time.local now understands
+ Time#to_a format.
+
+ * string.c (str_sub_s): replace happened twice for null pattern.
+
+ * regex.c (re_search): null pattern should not match after newline
+ at the end of string.
+
+ * time.c (time_isdst): now returns boolean value.
+
+ * error.c (rb_check_type): treat special constants in messages.
+
+ * parse.y (yylex): new form `::Const' to see toplevel constants.
+
+ * parse.y (cond): SEGV on `if ()'.
+
+ * gc.c (obj_free): some data needed explicit free().
+
+Mon Feb 16 23:55:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (blk_free): release duplicated block informations.
+
+ * eval.c (blk_copy_prev): duplicate outer block information into
+ the heap, when proc/binding created.
+
+Mon Feb 16 14:38:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_mon): now 1 for January and so on.
+
+ * time.c (time_year): year in 19xx (no + 1900 needed anymore).
+
+Mon Feb 16 13:28:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): need to fetch mbchar's second byte
+ without translation.
+
+Mon Feb 16 12:29:27 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * eval.c (f_pass_block): pass iterator block to other method.
+
+Fri Feb 13 08:16:11 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_regx): handle \s before read_escape().
+
+ * parse.y (read_escape): `\s' in strings as space.
+
+Tue Feb 10 17:29:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1b7 released.
+
+ * string.c (str_aset): string insertion by `str[n] = str2'.
+
+ * string.c (str_oct): does recognize `0x'.
+
+ * sprintf.c (f_sprintf): use baes 10 for conversion from string to
+ integer.
+
+Mon Feb 9 14:51:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (do_coerce): proper error message.
+
+ * string.c (str_sum): bug - masked by wrong value. (sigh..)
+
+Sat Feb 7 15:11:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_empty): new method
+
+Fri Feb 6 01:42:15 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_asctime): use asctime(3), not strftime(3).
+
+Thu Feb 5 18:58:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_fptr_close): do not free path on close().
+
+ * array.c (ary_filter): new method.
+
+ * enum.c (enum_each_with_index): new method.
+
+Thu Feb 5 14:10:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (primary): singleton class def can be appeared inside
+ method bodies.
+
+ * hash.c (hash_replace): replace content.
+
+ * string.c (str_replace_method): replace content.
+
+ * array.c (ary_replace_method): replace elements.
+
+ * string.c (str_succ_bang): String#succ!
+
+Thu Feb 5 18:20:30 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (str_upcase_bang): multi byte character support.
+
+Wed Feb 4 13:55:26 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_reverse): SEGV on empty array reverse.
+
+Tue Feb 3 12:24:07 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (match_to_a): non matching element should be nil.
+
+ * ruby.c (ruby_load_script): load script after all initialization.
+
+ * bignum.c (str2inum): need to interpret prefix `0' of `0x'.
+
+Tue Feb 3 10:00:18 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * numeric.c (fix_rshift): use `sizeof(INT)*8' instead of 32.
+
+Mon Feb 2 14:09:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (set_arg0): grab environment region too.
+
+Thu Jan 29 18:36:25 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * process.c (rb_proc_exec): check `sh' to be exist.
+
+Thu Jan 29 18:18:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_stdio_set): assignment to $stdin or $stdout does
+ reopen() as well as $stderr.
+
+Thu Jan 29 14:18:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (mod_ancestors): should not include singleton classes.
+
+ * object.c (obj_type): should not return internal class.
+
+ * io.c (io_reopen): unwillingly closes stdio streams.
+
+Thu Jan 29 11:50:35 1998 Toshihiko SHIMOKAWA <toshi@csce.kyushu-u.ac.jp>
+
+ * ext/socket/socket.c (udp_addrsetup): forgot to use htons().
+
+Tue Jan 27 23:15:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * keywords: __FILE__, __LINE__ are available again.
+
+Fri Jan 23 14:19:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1b6 released.
+
+ * object.c (mod_to_s): need to duplicate classpath.
+
+ * error.c (exc_inspect): need to duplicate classpath.
+
+Thu Jan 22 00:37:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h (STR2CSTR): new macro to retrieve char*.
+
+ * class.c (rb_define_method): `initialize' should always be
+ private, even if it defined by C extensions.
+
+ * eval.c (rb_eval): `initialize' should always be private.
+
+Thu Jan 22 16:21:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): some singleton class def cause SEGV.
+
+ * eval.c (TMP_ALLOC): replace ALLOCA_N, where thread context
+ switch may happen.
+
+Wed Jan 21 01:43:42 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (PUSH_FRAME): do not use ALLOCA_N(). crash on some
+ platforms that use missing/alloca.c.
+
+ * regex.c (re_compile_pattern): too many pops for non register
+ subexpr.
+
+ * parse.y (yylex): open parentheses after identifiers are argument
+ list, even if whitespaces have seen.
+
+Tue Jan 20 15:19:59 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (terms): quoted word list by %w(a b c).
+
+ * ext/tcltklib/extconf.rb: more accurate check for tcl/tk libs.
+
+ * file.c (rb_stat): most of the FileTest methods (and function
+ `test') accept File objects as the argument.
+
+Tue Jan 19 18:19:24 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/extmk.rb.in (install): there should be no newline after install:
+
+ * re.c (MIN): renamed from min(). there's a local variable named
+ min in the file, so that some cpp will raise an error.
+
+Mon Jan 19 16:30:05 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1b5 released.
+
+ * process.c (rb_syswait): no exception raised.
+
Fri Jan 16 00:43:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* ruby.h (CLONESETUP): copies its singleton classes too.
@@ -27,6 +2379,8 @@ Tue Jan 13 10:00:18 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
Fri Jan 9 13:19:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+ * version 1.1b4 released.
+
* eval.c (f_missing): class name omitted from the error message.
* error.c (exc_inspect): description changed.
diff --git a/MANIFEST b/MANIFEST
index 2bdaf290b3..5c697d612f 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -5,6 +5,7 @@ Makefile.in
README
README.jp
README.EXT
+README.EXT.jp
ToDo
array.c
bignum.c
@@ -13,7 +14,8 @@ compar.c
configure
configure.bat
configure.in
-config.dj
+config_h.dj
+config_s.dj
config.guess
config.sub
defines.h
@@ -36,7 +38,6 @@ install-sh
instruby.rb
intern.h
io.c
-io.h
keywords
lex.c
main.c
@@ -47,6 +48,7 @@ node.h
numeric.c
object.c
pack.c
+parse.c
parse.y
process.c
random.c
@@ -58,8 +60,9 @@ regex.h
ruby.1
ruby.c
ruby.h
+rubyio.h
+rubysig.h
rubytest.rb
-sig.h
signal.c
sprintf.c
st.c
@@ -73,74 +76,89 @@ util.c
variable.c
version.c
version.h
+beos/ruby.def.in
ext/Setup
ext/Setup.dj
ext/Setup.nt
ext/Setup.x68
+ext/aix_ld.rb
+ext/cygwin32_ld.rb
ext/extmk.rb.in
ext/extmk.rb.nt
-ext/aix_ld.rb
lib/English.rb
+lib/Env.rb
+lib/README
lib/base64.rb
lib/cgi-lib.rb
lib/complex.rb
lib/date.rb
+lib/date2.rb
lib/debug.rb
lib/delegate.rb
lib/e2mmap.rb
lib/eregex.rb
lib/find.rb
+lib/final.rb
lib/finalize.rb
lib/ftplib.rb
lib/ftools.rb
lib/getopts.rb
+lib/getoptlong.rb
lib/importenv.rb
lib/jcode.rb
lib/mailread.rb
lib/mathn.rb
lib/matrix.rb
lib/mkmf.rb
+lib/monitor.rb
lib/mutex_m.rb
lib/observer.rb
+lib/open3.rb
lib/ostruct.rb
lib/parsearg.rb
lib/parsedate.rb
lib/ping.rb
+lib/profile.rb
lib/pstore.rb
lib/rational.rb
+lib/readbytes.rb
lib/shellwords.rb
+lib/singleton.rb
lib/sync.rb
+lib/telnet.rb
+lib/tempfile.rb
lib/thread.rb
lib/thwait.rb
-lib/tk.rb
-lib/tkcanvas.rb
-lib/tkclass.rb
-lib/tkdialog.rb
-lib/tkentry.rb
-lib/tkscrollbox.rb
-lib/tktext.rb
+lib/timeout.rb
lib/tracer.rb
lib/weakref.rb
+misc/README
+misc/inf-ruby.el
+misc/ruby-mode.el
+misc/rubydb2x.el
+misc/rubydb3x.el
missing/alloca.c
missing/crypt.c
missing/dir.h
missing/dup2.c
missing/file.h
missing/flock.c
+missing/memcmp.c
missing/memmove.c
missing/mkdir.c
-missing/nt.c
-missing/nt.h
-missing/setenv.c
missing/strcasecmp.c
+missing/strchr.c
missing/strdup.c
missing/strerror.c
missing/strftime.c
missing/strstr.c
missing/strtol.c
missing/strtoul.c
+missing/vsnprintf.c
missing/x68.c
+sample/README
sample/biorhythm.rb
+sample/cal.rb
sample/cbreak.rb
sample/clnt.rb
sample/dbmtest.rb
@@ -151,44 +169,38 @@ sample/exyacc.rb
sample/fact.rb
sample/fib.awk
sample/fib.pl
+sample/fib.py
sample/fib.rb
sample/fib.scm
sample/freq.rb
sample/from.rb
sample/fullpath.rb
sample/getopts.test
+sample/goodfriday.rb
sample/less.rb
sample/list.rb
sample/list2.rb
sample/list3.rb
-sample/mrshtest.rb
+sample/mine.rb
sample/mkproto.rb
sample/mpart.rb
+sample/mrshtest.rb
sample/observ.rb
sample/occur.pl
sample/occur.rb
sample/occur2.rb
sample/philos.rb
sample/pi.rb
+sample/rename.rb
sample/rbc.rb
sample/rcs.awk
sample/rcs.dat
sample/rcs.rb
sample/regx.rb
-sample/ruby-mode.el
-sample/rubydb2x.el
-sample/rubydb3x.el
sample/sieve.rb
sample/svr.rb
sample/test.rb
sample/time.rb
-sample/tkbiff.rb
-sample/tkbrowse.rb
-sample/tkdialog.rb
-sample/tkfrom.rb
-sample/tkhello.rb
-sample/tkline.rb
-sample/tktimer.rb
sample/trojan.rb
sample/tsvr.rb
sample/uumerge.rb
@@ -198,6 +210,8 @@ win32/ntsetup.bat
win32/ruby.def
win32/sdbm.c
win32/sdbm.h
+win32/win32.c
+win32/win32.h
x68/fconvert.c
x68/select.c
x68/_dtos18.c
diff --git a/Makefile.in b/Makefile.in
index 3c616d9983..628b0e0778 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -8,19 +8,26 @@ VPATH = @srcdir@:@srcdir@/missing
CC = @CC@
YACC = @YACC@
PURIFY =
+AUTOCONF = autoconf
@SET_MAKE@
-CFLAGS = @CFLAGS@ -I@srcdir@
+prefix = @prefix@
+CFLAGS = @CFLAGS@ -I. -I@srcdir@ -I@includedir@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
+EXTLIBS =
LIBS = @LIBS@ $(EXTLIBS)
MISSING = @LIBOBJS@ @ALLOCA@
+LDSHARED = @LDSHARED@
+DLDFLAGS = @DLDFLAGS@
+SOLIBS = @SOLIBS@
binsuffix = @binsuffix@
#### End of system configuration section. ####
-LIBRUBY = libruby.a
+LIBRUBY = @LIBRUBY@
+LIBRUBYARG = @LIBRUBYARG@
EXTOBJS =
@@ -42,8 +49,8 @@ OBJS = array.o \
hash.o \
inits.o \
io.o \
- math.o \
marshal.o \
+ math.o \
numeric.o \
object.o \
pack.o \
@@ -66,44 +73,58 @@ OBJS = array.o \
$(MISSING)
all: miniruby$(binsuffix) rbconfig.rb
- @cd ext; ../miniruby$(binsuffix) ./extmk.rb @EXTSTATIC@
+ @./miniruby$(binsuffix) -Xext extmk.rb @EXTSTATIC@
-miniruby$(binsuffix): $(OBJS) $(MAINOBJ) dmyext.o
+miniruby$(binsuffix): libruby.a $(MAINOBJ) dmyext.o
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) dmyext.o $(LIBS) -o miniruby
+ $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) dmyext.o libruby.a $(LIBS) -o $@
ruby$(binsuffix): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o ruby
+ $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
-$(LIBRUBY): $(OBJS) dmyext.o
- @AR@ rcu $(LIBRUBY) $(OBJS) dmyext.o
- @-@RANLIB@ $(LIBRUBY) 2> /dev/null || true
+libruby.a: $(OBJS) dmyext.o
+ @AR@ rcu $@ $(OBJS) dmyext.o
+ @-@RANLIB@ $@ 2> /dev/null || true
+
+libruby.so: $(OBJS) dmyext.o
+ $(LDSHARED) $(DLDFLAGS) $(SOLIBS) $(OBJS) dmyext.o -o $@
install: rbconfig.rb
- ./miniruby$(binsuffix) $(srcdir)/instruby.rb
+ ./miniruby$(binsuffix) $(srcdir)/instruby.rb $(DESTDIR)
clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) rbconfig.rb
@rm -f ext/extinit.c ext/extinit.o dmyext.o
- @if test -f ./miniruby; then cd ext; ../miniruby ./extmk.rb clean; fi
-
-realclean: clean
- @rm -f Makefile ext/extmk.rb ext/config.cache
- @rm -f config.cache config.h config.log config.status
- @rm -f parse.c lex.c *~ core *.core gmon.out
+ @if test -f ./miniruby$(binsuffix); then \
+ ./miniruby$(binsuffix) -Xext extmk.rb clean; \
+ fi
+
+distclean: clean
+ @rm -f Makefile ext/extmk.rb config.h
+ @rm -f ext/config.cache config.cache config.log config.status
+ @rm -f parse.c *~ core *.core gmon.out y.tab.c y.output
@rm -f ruby$(binsuffix) miniruby$(binsuffix)
+realclean: distclean
+ @rm -f lex.c
+
test: miniruby$(binsuffix)
@./miniruby$(binsuffix) $(srcdir)/rubytest.rb
rbconfig.rb: config.status miniruby$(binsuffix)
@./miniruby$(binsuffix) $(srcdir)/mkconfig.rb rbconfig.rb
+config.status: $(srcdir)/configure
+ $(SHELL) ./config.status --recheck
+
+$(srcdir)/configure: $(srcdir)/configure.in
+ cd $(srcdir) && $(AUTOCONF)
+
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
lex.c: keywords
- gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ keywords > lex.c
+ gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ @srcdir@/keywords > lex.c
parse.c: parse.y
$(YACC) $<
@@ -121,24 +142,30 @@ dup2.o: @srcdir@/missing/dup2.c
flock.o: @srcdir@/missing/flock.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/flock.c
+memcmp.o: @srcdir@/missing/memcmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memcmp.c
+
memmove.o: @srcdir@/missing/memmove.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memmove.c
mkdir.o: @srcdir@/missing/mkdir.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/mkdir.c
-setenv.o: @srcdir@/missing/setenv.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/setenv.c
+vsnprintf.o: @srcdir@/missing/vsnprintf.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/vsnprintf.c
strcasecmp.o: @srcdir@/missing/strcasecmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strcasecmp.c
-strerror.o: @srcdir@/missing/strerror.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c
+strchr.o: @srcdir@/missing/strchr.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strchr.c
strdup.o: @srcdir@/missing/strdup.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strdup.c
+strerror.o: @srcdir@/missing/strerror.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c
+
strftime.o: @srcdir@/missing/strftime.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strftime.c
@@ -160,40 +187,43 @@ x68.o: @srcdir@/missing/x68.c
# Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT:
###
-parse.o : parse.y ruby.h defines.h config.h intern.h env.h node.h st.h regex.h lex.c
+parse.o: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c
###
array.o: array.c ruby.h config.h defines.h intern.h
bignum.o: bignum.c ruby.h config.h defines.h intern.h
class.o: class.c ruby.h config.h defines.h intern.h node.h st.h
compar.o: compar.c ruby.h config.h defines.h intern.h
dir.o: dir.c ruby.h config.h defines.h intern.h
-dln.o: dln.c config.h defines.h dln.h st.h
+dln.o: dln.c config.h defines.h dln.h
dmyext.o: dmyext.c
enum.o: enum.c ruby.h config.h defines.h intern.h
error.o: error.c ruby.h config.h defines.h intern.h env.h
-eval.o: eval.c ruby.h config.h defines.h intern.h env.h node.h sig.h st.h dln.h
-file.o: file.c ruby.h config.h defines.h intern.h io.h sig.h
-gc.o: gc.c ruby.h config.h defines.h intern.h env.h sig.h st.h node.h re.h regex.h
-hash.o: hash.c ruby.h config.h defines.h intern.h st.h
+eval.o: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
+file.o: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
+fnmatch.o: fnmatch.c config.h fnmatch.h
+gc.o: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
+glob.o: config.h glob.c fnmatch.h
+hash.o: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h
inits.o: inits.c ruby.h config.h defines.h intern.h
-io.o: io.c ruby.h config.h defines.h intern.h io.h sig.h
-main.o: main.c
-marshal.o: marshal.c ruby.h config.h defines.h intern.h io.h sig.h st.h
+io.o: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
+main.o: main.c ruby.h config.h defines.h intern.h
+marshal.o: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h
math.o: math.c ruby.h config.h defines.h intern.h
numeric.o: numeric.c ruby.h config.h defines.h intern.h
object.o: object.c ruby.h config.h defines.h intern.h st.h
pack.o: pack.c ruby.h config.h defines.h intern.h
-process.o: process.c ruby.h config.h defines.h intern.h sig.h st.h
+process.o: process.c ruby.h config.h defines.h intern.h rubysig.h st.h
random.o: random.c ruby.h config.h defines.h intern.h
range.o: range.c ruby.h config.h defines.h intern.h
re.o: re.c ruby.h config.h defines.h intern.h re.h regex.h
-ruby.o: ruby.c ruby.h config.h defines.h intern.h re.h regex.h dln.h
-signal.o: signal.c ruby.h config.h defines.h intern.h sig.h
+regex.o: regex.c config.h regex.h util.h
+ruby.o: ruby.c ruby.h config.h defines.h intern.h dln.h util.h
+signal.o: signal.c ruby.h config.h defines.h intern.h rubysig.h
sprintf.o: sprintf.c ruby.h config.h defines.h intern.h
st.o: st.c config.h st.h
string.o: string.c ruby.h config.h defines.h intern.h re.h regex.h
struct.o: struct.c ruby.h config.h defines.h intern.h
time.o: time.c ruby.h config.h defines.h intern.h
-util.o: util.c defines.h intern.h config.h util.h
-variable.o: variable.c ruby.h config.h defines.h intern.h env.h st.h
+util.o: util.c ruby.h config.h defines.h intern.h util.h
+variable.o: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h
version.o: version.c ruby.h config.h defines.h intern.h version.h
diff --git a/README b/README
index d41fb9f79a..dd93c592be 100644
--- a/README
+++ b/README
@@ -3,7 +3,7 @@
Ruby is the 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.
+Perl). It is simple, straight-forward, and extensible.
* Features of Ruby
@@ -15,7 +15,8 @@ perl). It is simple, straight-forward, and extensible.
+ Iterators and Closures
+ Garbage Collection
+ Dynamic Loading of Object files(on some architecture)
- + Highly Portable(works on many UNIX machines)
+ + Highly Portable(works on many UNIX machines, and on DOS,
+ Windows, Mac, BeOS etc.)
* How to get Ruby
@@ -31,21 +32,26 @@ This is what you need to do to compile and install Ruby:
2. Edit defines.h if you need. Probably this step will not need.
- 3. Remove comment mark(#) before the module names from ext/Setup, if
- you want to link modules statically.
+ 3. Remove comment mark(#) before the module names from ext/Setup (or
+ add module names if not present), if you want to link modules
+ statically.
- If you want to link all the extension modules, remove comment
- mark from the line "#option nodynamic".
+ If you don't want to compile non static extension modules
+ (probably on architectures which does not allow dynamic loading),
+ remove comment mark from the line "#option nodynamic" in
+ ext/Setup.
4. Run make.
- 5. Optionally, run 'make test' to check that the compiled Ruby
- interpreter works well. If you see the message "test succeeded",
- your Ruby works as it should (hopefully).
+ 5. Optionally, run 'make test' to check whether the compiled Ruby
+ interpreter works well. If you see the message "test succeeded",
+ your ruby works as it should (hopefully).
6. Run 'make install'
-If you fail to compile Ruby, please send the detailed error report with
+ You may have to be a super user to install ruby.
+
+If you fail to compile ruby, please send the detailed error report with
the error log and machine/OS type, to help others.
* Copying
@@ -61,12 +67,13 @@ You can redistribute it and/or modify it under either the terms of the GPL
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.
+ 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.
+ b) use the modified software only within your corporation or
+ organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided.
@@ -84,8 +91,7 @@ You can redistribute it and/or modify it under either the terms of the GPL
the software.
c) give non-standard executables non-standard names, with
- instructions on where to get the original software
- distribution.
+ instructions on where to get the original software distribution.
d) make other distribution arrangements with the author.
@@ -94,7 +100,7 @@ You can redistribute it and/or modify it under either the terms of the GPL
are not written by the author, so that they are not under this terms.
They are gc.c(partly), utils.c(partly), regex.[ch], fnmatch.[ch],
glob.c, st.[ch] and some files under the ./missing directory. See
- each files for the copying condition.
+ each file for the copying condition.
5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the
diff --git a/README.EXT b/README.EXT
index c2f81d1a7a..f169e54995 100644
--- a/README.EXT
+++ b/README.EXT
@@ -1,21 +1,16 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
-This document explains how to make extention modules for ruby.
+This document explains how to make extention modules for Ruby.
1¡¥Basic knowledge
In C, variables have types and data do not have types. In contrast,
-ruby variables do not have static type and data themselves have
+Ruby variables do not have static type and data themselves have
types. So, data need to be converted across the languages.
-Data in ruby represented C type `VALUE'. Each VALUE data have its
+Data in Ruby represented C type `VALUE'. Each VALUE data have its
data-type.
-ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
-¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È
-¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤ruby
-¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥
-
To retrieve an C data from the VALUE, you need to:
(1) Identify VALUE's data type
@@ -38,7 +33,7 @@ Ruby interpreter has data-types as below:
T_ARRAY array
T_FIXNUM Fixnum(31bit integer)
T_HASH assosiative array
- T_STRUCT (ruby) structure
+ T_STRUCT (Ruby) structure
T_BIGNUM multi precision integer
T_TRUE true
T_FALSE false
@@ -89,37 +84,28 @@ There are faster check-macros for fixnums and nil.
1.3 Convert VALUE into C data
-¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_NIL, T_FALSE, T_TRUE¤Ç¤¢¤ë»þ¡¤¥Ç¡¼¥¿¤Ï¤½¤ì¤¾
-¤ìnil, FALSE, TRUE¤Ç¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤Ò¤È
-¤Ä¤º¤Ä¤·¤«Â¸ºß¤·¤Þ¤»¤ó¡¥
-
-¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç
-¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È
-¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºruby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
-¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤
-¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤­¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬
-ȯÀ¸¤¹¤ë)¡¥
-
-¤½¤ì°Ê³°¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ÏÂбþ¤¹¤ëC¤Î¹½Â¤ÂΤ¬¤¢¤ê¤Þ¤¹¡¥Âбþ¤¹
-¤ë¹½Â¤ÂΤΤ¢¤ëVALUE¤Ï¤½¤Î¤Þ¤Þ¥­¥ã¥¹¥È(·¿ÊÑ´¹)¤¹¤ì¤Ð¹½Â¤ÂΤÎ
-¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¤Ç¤­¤Þ¤¹¡¥
+The data for type T_NIL, T_FALSE, T_TRUE are nil, true, false
+respectively. They are singletons for the data type.
-¹½Â¤ÂΤϡÖstruct RXxxxx¡×¤È¤¤¤¦Ì¾Á°¤Çruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤Þ
-¤¹¡¥Î㤨¤Ðʸ»úÎó¤Ï¡Östruct RString¡×¤Ç¤¹¡¥¼ÂºÝ¤Ë»È¤¦²ÄǽÀ­¤¬
-¤¢¤ë¤Î¤Ïʸ»úÎó¤ÈÇÛÎ󤯤餤¤À¤È»×¤¤¤Þ¤¹¡¥
+The T_FIXNUM data is the 31bit length fixed integer (63bit length on
+some machines), which can be conver to the C integer by using
+FIX2INT() macro. There also be NUM2INT() which converts any Ruby
+numbers into C integer. The NUM2INT() macro includes type check, so
+the exception will be raised if conversion failed.
-ruby.h¤Ç¤Ï¹½Â¤ÂΤإ­¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ
-»ú¤Ë¤·¤¿¤â¤Î)¤È¤¤¤¦Ì¾Á°¤ÇÄ󶡤µ¤ì¤Æ¤¤¤Þ¤¹(Îã: RSTRING())¡¥
+Other data types have corresponding C structures, e.g. struct RArray
+for T_ARRAY etc. VALUE of the type which has corresponding structure
+can be cast to retrieve the pointer to the struct. The casting macro
+RXXXX for each data type like RARRAY(obj). see "ruby.h".
-Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È
-¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡×
-¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAT(str)->len¡×¡¤
-¡ÖRARRAT(str)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
+For example, `RSTRING(size)->len' is the way to get the size of the
+Ruby String object. The allocated region can be accessed by
+`RSTRING(str)->ptr'. For arrays, `RARRAY(ary)->len' and
+`RARRAY(ary)->ptr' respectively.
-ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
-¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤·
-¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍƤÎÀ°¹çÀ­¤¬
-¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥
+Notice: Do not change the value of the structure directly, unless you
+are responsible about the result. It will be the cause of interesting
+bugs.
1.4 Convert C data into VALUE
@@ -137,10 +123,10 @@ VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
¤¤¤ë)¡¥
-¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤Îruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
+¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤ÎRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
-¤Ïruby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
+¤ÏRuby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
¤Î¤â¤Î)¤À¤±¤Ë¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡¥
FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
@@ -153,256 +139,241 @@ FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
-1.5 Manipulate ruby data
+1.5 Manipulate Ruby data
-ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤruby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍƤι¹¿·¤ò
-¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
-ruby¤¬ÍÑ°Õ¤·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
-
-¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô
-¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥
+As I already told, it is not recommended to modify object's internal
+structure. To manipulate objects, use functions supplied by Ruby
+interpreter. Useful functions are listed below (not all):
String funtions
- str_new(char *ptr, int len)
+ rb_str_new(char *ptr, int len)
- Creates a new ruby string.
+ Creates a new Ruby string.
- str_new2(char *ptr)
+ rb_str_new2(char *ptr)
- Creates a new ruby string from C string. This is equivalent to
- str_new(ptr, strlen(ptr)).
+ Creates a new Ruby string from C string. This is equivalent to
+ rb_str_new(ptr, strlen(ptr)).
- str_cat(VALUE str, char *ptr, int len)
+ rb_str_cat(VALUE str, char *ptr, int len)
- Appends len bytes data from ptr to the ruby string.
+ Appends len bytes data from ptr to the Ruby string.
Array functions
- ary_new()
+ rb_ary_new()
Creates an array with no element.
- ary_new2(int len)
+ rb_ary_new2(int len)
Creates an array with no element, with allocating internal buffer
for len elements.
- ary_new3(int n, ...)
+ rb_ary_new3(int n, ...)
Creates an n-elements array from arguments.
- ary_new4(int n, VALUE *elts)
+ rb_ary_new4(int n, VALUE *elts)
Creates an n-elements array from C array.
- ary_push(VALUE ary)
- ary_pop(VALUE ary, VALUE val)
- ary_shift(VALUE ary)
- ary_unshift(VALUE ary, VALUE val)
- ary_entry(VALUE ary, int idx)
+ rb_ary_push(VALUE ary, VALUE val)
+ rb_ary_pop(VALUE ary)
+ rb_ary_shift(VALUE ary)
+ rb_ary_unshift(VALUE ary, VALUE val)
+ rb_ary_entry(VALUE ary, int idx)
Array operations. The first argument to each functions must be an
array. They may dump core if other types given.
-2. Extend ruby with C
+2. Extend Ruby with C
-¸¶ÍýŪ¤Ëruby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
+¸¶ÍýŪ¤ËRuby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥Ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
-¤Ïruby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
+¤ÏRuby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
²ð¤·¤Þ¤¹¡¥
-2.1 Add new features to ruby
+2.1 Add new features to Ruby
-ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
-¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲ乤ë´Ø¿ô¤¬
+Ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤ÐRuby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
+¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥Ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲ乤ë´Ø¿ô¤¬
Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
- * ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë
- * ¥á¥½¥Ã¥É¡¤Æðۥ᥽¥Ã¥É¤Ê¤É
- * Äê¿ô
+ * Classes, Modules
+ * Methods, Singleton Methods
+ * Constants
¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥
2.1.1 Class/module definition
-¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+To define class or module, use functions below:
VALUE rb_define_class(char *name, VALUE super)
VALUE rb_define_module(char *name)
-¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥
-¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç
-¤ÏÌá¤êÃͤòÊÑ¿ô¤Ë³ÊǼ¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ë¤Ç¤·¤ç¤¦¡¥
+These functions return the newly created class ot module. You may
+want to save this reference into the variable to use later.
2.1.2 Method/singleton method definition
-¥á¥½¥Ã¥É¤äÆðۥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+To define methods or singleton methods, use functions below:
void rb_define_method(VALUE class, char *name,
VALUE (*func)(), int argc)
void rb_define_singleton_method(VALUE object, char *name,
- VALUE (*func)(), int argc)
+ VALUE (*func)(), int argc)
+The `argc' represents the number of the arguments to the C function,
+which must be less than 17. But I believe you don't need that much. :-)
-Ç°¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆðۥ᥽¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯
-¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
-¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆðۥ᥽¥Ã¥É¤¬»È¤ï¤ì
-¤Þ¤¹¡¥
+If `argc' is negative, it specifies calling sequence, not number of
+the arguments.
+
+If argc is -1, the function will be called like:
-¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È
-·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬Àµ¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°ÕÌ£
-¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½¤ó
-¤Ê¤Ë)¡¥
+ VALUE func(int argc, VALUE *argv, VALUE obj)
-argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
-argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú
-¿ô¤Ïruby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
+where argc is the actual number of arguments, argv is the C array of
+the arguments, and obj is the receiver.
-¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á
-¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥
+if argc is -2, the arguments are passed in Ruby array. The function
+will be called like:
+
+ VALUE func(VALUE obj, VALUE args)
+
+where obj is the receiver, and args is the Ruby array containing
+actual arguments.
+
+There're two more functions to define method. One is to define
+private method:
void rb_define_private_method(VALUE class, char *name,
VALUE (*func)(), int argc)
-private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
-¥É¤Ç¤¹¡¥
-
-¤â¤¦¤Ò¤È¤Ä¤Ï¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô
-¤È¤Ï¥â¥¸¥å¡¼¥ë¤ÎÆðۥ᥽¥Ã¥É¤Ç¤¢¤ê¡¤Æ±»þ¤Ëprivate¥á¥½¥Ã¥É¤Ç
-¤â¤¢¤ë¤â¤Î¤Ç¤¹¡¥Îã¤ò¤¢¤²¤ë¤ÈMath¥â¥¸¥å¡¼¥ë¤Îsqrt()¤Ê¤É¤¬¤¢¤²
-¤é¤ì¤Þ¤¹¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï
+The other is to define module function, which is private AND singleton
+method of the module. For example, sqrt is the module function
+defined in Math module. It can be call in the form like:
Math.sqrt(4)
-¤È¤¤¤¦·Á¼°¤Ç¤â
+or
include Math
sqrt(4)
-¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î
-Ä̤ê¤Ç¤¹¡¥
+To define module function
void rb_define_module_function(VALUE module, char *name,
VALUE (*func)(), int argc)
-´Ø¿ôŪ¥á¥½¥Ã¥É(Kernel¥â¥¸¥å¡¼¥ë¤Îprivaet method)¤òÄêµÁ¤¹¤ë¤¿
-¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡¥
+Oh, in addition, function-like method, which is private method defined
+in Kernel module, can be defined using:
void rb_define_global_function(char *name, VALUE (*func)(), int argc)
2.1.3 Constant definition
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
-¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥
+We have 2 functions to define constants:
void rb_define_const(VALUE class, char *name, VALUE val)
void rb_define_global_const(char *name, VALUE val)
-Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å
-¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥
-
-2.2 Use ruby features from C
+The former is to define constant under specified class/module. The
+latter is to define global constant.
-´û¤Ë¡Ø1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
-»È¤¨¤Ð¡¤ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
-¤Þ¤¹¡¥
-
-# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸«
-# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥
+2.2 Use Ruby features from C
-¤½¤ì°Ê³°¤Ë¤âruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
+There are several ways to invoke Ruby's features from C code.
-2.2.1 ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
+2.2.1 Evaluate Ruby Program in String
-C¤«¤éruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
-Í¿¤¨¤é¤ì¤¿ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+Easiest way to call Ruby's function from C program is to evaluate the
+string as Ruby program. This function will do the job.
VALUE rb_eval_string(char *str)
-¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶­¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô
-¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥
+Evaluation is done under current context, thus current local variables
+of the innermost method (which is defined by Ruby) can be accessed.
2.2.2 ID or Symbol
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
-¤¹¡¥¤½¤ÎÁ°¤Ë¡¤ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
-»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
-
-ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥ruby¤ÎÃæ¤Ç¤Ï
+You can invoke methods directly, without parsing the string. First I
+need to explain about symbols (which data type is ID). ID is the
+integer number to represent Ruby's identifiers such as variable names.
+It can be accessed from Ruby in the form like:
- :¼±ÊÌ»Ò
+ :Identifier
-¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô
+You can get the symbol value from string within C code, by using
rb_intern(char *name)
-¤ò»È¤¤¤Þ¤¹¡¥¤Þ¤¿°ìʸ»ú¤Î±é»»»Ò¤Ï¤½¤Îʸ»ú¥³¡¼¥É¤¬¤½¤Î¤Þ¤Þ¥·¥ó
-¥Ü¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+In addition, the symbols for one character operators (e.g +) is the
+code for that character.
-2.2.3 Invoke ruby method from C
+2.2.3 Invoke Ruby method from C
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
-¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+To invoke methods directly, you can use the function below
VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
-¤³¤Î´Ø¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥Èrecv¤Îmid¤Ç»ØÄꤵ¤ì¤ë¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð
-¤·¤Þ¤¹¡¥
+This function invokes the method of the recv, which name is specified
+by the symbol mid.
-2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë
+2.2.4 Accessing the variables and constants
C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤¥¯¥é¥¹Äê¿ô¡¤¥¤¥ó¥¹¥¿
¥ó¥¹ÊÑ¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»
¥¹¤Ç¤­¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
-¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ
-¤ê¤Ç¤¹¡¥
+The functions to access/modify instance variables are below:
VALUE rb_ivar_get(VALUE obj, ID id)
VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
-id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+id must be the symbol, which can be retrieved by rb_intern().
-¥¯¥é¥¹Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+To access the constants of the class/module:
VALUE rb_const_get(VALUE obj, ID id)
-¥¯¥é¥¹Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
-¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+See 2.1.3 for defining new constant.
-3. Informatin sharing between ruby and C
+3. Informatin sharing between Ruby and C
-C¸À¸ì¤Èruby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
+C¸À¸ì¤ÈRuby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
-3.1 Ruby constant that C¤«¤é»²¾È¤Ç¤­¤ëruby¤ÎÄê¿ô
+3.1 Ruby constant that C¤«¤é»²¾È¤Ç¤­¤ëRuby¤ÎÄê¿ô
-Following ruby constants can be referred from C.
+Following Ruby constants can be referred from C.
- TRUE
- FALSE
+ Qtrue
+ Qfalse
-Boolean values. FALSE is false in the C also (i.e. 0).
+Boolean values. Qfalse is false in the C also (i.e. 0).
Qnil
Ruby nil in C scope.
-3.2 Global variables shared between C and ruby
+3.2 Global variables shared between C and Ruby
-C¤Èruby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
+C¤ÈRuby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï
¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥
void rb_define_variable(char *name, VALUE *var)
-¤³¤Î´Ø¿ô¤Ïruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
+¤³¤Î´Ø¿ô¤ÏRuby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
-¹¹¤¹¤ë¤È¼«Æ°Åª¤Ëruby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+¹¹¤¹¤ë¤È¼«Æ°Åª¤ËRuby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
-¤Þ¤¿ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
+¤Þ¤¿Ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥
void rb_define_readonly_variable(char *name, VALUE *var)
@@ -421,13 +392,13 @@ setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
-¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëruby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
+¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRuby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
void rb_define_virtual_variable(char *name,
VALUE (*getter)(), VALUE (*setter)())
-¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
+¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿Ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥
The prototypes of the getter and setter functions are as following:
@@ -435,14 +406,14 @@ The prototypes of the getter and setter functions are as following:
(*getter)(ID id, void *data, struct global_entry* entry);
(*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
-3.3 Encapsulate C data into ruby object
+3.3 Encapsulate C data into Ruby object
-C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
+C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤Çruby
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤ÇRuby
¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
-Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
+Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
Data_Wrap_Struct(class,mark,free,ptr)
@@ -450,7 +421,7 @@ Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
-C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬ruby¤Î¥ª¥Ö¥¸¥§
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬Ruby¤Î¥ª¥Ö¥¸¥§
¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
@@ -482,47 +453,38 @@ C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤ÏÊÑ¿ôsval¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥
4¡¥Example - Create dbm module
-¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
-ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë
+¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
+Ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë
¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥
(1) make the directory
% mkdir ext/dbm
-ruby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥¥â
-¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤ËÁª¤ó¤Ç¹½¤¤¤Þ
-¤»¤ó¡¥
+Make a directory for the extension library under ext directory.
(2) create MANIFEST file
% cd ext/dbm
% touch MANIFEST
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
-ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
-¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
-
-MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤make¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤¬³ÈÄ¥¥â¥¸¥å¡¼
-¥ë¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ¤¤¤Þ¤¹¡¥
+There should be MANIFEST file in the directory for the extension
+library. Make empty file now.
(3) design the library
-¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
-·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
-¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
-¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+You need to design the library features, before making it.
(4) write C code.
-³ÈÄ¥¥â¥¸¥å¡¼¥ëËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
+³ÈÄ¥¥é¥¤¥Ö¥é¥êËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤È¤¤¤¦¥Õ¥¡
¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼
¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥â¥¸¥å¡¼¥ë̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
¤È¤¬¾×Æͤ¹¤ë¤«¤é¤Ç¤¹¡¥
-ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
+Ruby¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤Î¾ì¹ç¡ÖInit_dbm¡×
¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î
ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥
@@ -530,27 +492,25 @@ ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
--
Init_dbm()
{
- /* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */
- cDBM = rb_define_class("DBM", cObject);
- /* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */
- rb_include_module(cDBM, mEnumerable);
+ /* define DBM class */
+ cDBM = rb_define_class("DBM", rb_cObject);
+ /* DBM includes Enumerate module */
+ rb_include_module(cDBM, rb_mEnumerable);
- /* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */
+ /* DBM has class method open(): arguments are received as C array */
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
- /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥Éclose(): °ú¿ô¤Ï¤Ê¤· */
+ /* DBM instance method close(): no args */
rb_define_method(cDBM, "close", fdbm_close, 0);
- /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥É[]: °ú¿ô¤Ï1¸Ä */
+ /* DBM instance method []: 1 argument */
rb_define_method(cDBM, "[]", fdbm_fetch, 1);
:
- /* DBM¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô̾¤Î¤¿¤á¤ÎID */
- id_dbm = rb_intern("dbm");
}
--
DBM¥â¥¸¥å¡¼¥ë¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
-¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òruby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òRuby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
dbm.c¤Ç¤ÏData_Make_Struct¤ò°Ê²¼¤Î¤è¤¦¤Ë»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
@@ -600,7 +560,7 @@ fdbm_delete(obj, keystr)
°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É
¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥
-°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤Èruby¤ÎÇÛÎó¤Ç¼õ¤±
+°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤ÈRuby¤ÎÇÛÎó¤Ç¼õ¤±
¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø
¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
@@ -634,7 +594,7 @@ fdbm_s_open(argc, argv, class)
¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î
ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥
-ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
+Ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
¤¦¤Ç¤¹¡¥
--
@@ -647,15 +607,14 @@ fdbm_indexes(obj, args)
}
--
-Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤Ïruby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥­¥ã¥¹¥È¤ò¸º
+Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤ÏRuby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥­¥ã¥¹¥È¤ò¸º
¤é¤¹¤¿¤á struct RArray* ¤Ç¼õ¤±¤Æ¤¤¤Þ¤¹¤¬¡¤VALUE¤Ç¤âƱ¤¸¤³¤È
¤Ç¤¹¡¥
-** Ãí°Õ»ö¹à
+** Notice
-ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
-C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
-¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤·¤Þ¤¹¡¥
+GC should know about global variables which refers Ruby's objects, but
+not exported to the Ruby world. You need to protect them by
void rb_global_variable(VALUE *var)
@@ -665,7 +624,7 @@ C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
make»þ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡¥¤Ê¤±¤ì¤ÐŬÅö¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥
extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã¥¯¤Ê¤É
-¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤Îruby´Ø¿ô¤ò»È¤¦
+¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤ÎRuby´Ø¿ô¤ò»È¤¦
¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
@@ -704,31 +663,31 @@ make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍƤϻ²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê
(8) make
-ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤
-ɬÍפˤè¤Ã¤Æ¤Ï¤½¤Î¥â¥¸¥å¡¼¥ë¤Îruby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô
+Ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤
+ɬÍפˤè¤Ã¤Æ¤Ï¤½¤Î¥â¥¸¥å¡¼¥ë¤ÎRuby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô
¤·¤Æ¤¯¤ì¤Þ¤¹¡¥extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®
-¤¬É¬Íפʻþ¤Ï¤Þ¤¿ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+¤¬É¬Íפʻþ¤Ï¤Þ¤¿Ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
(9) debug
-¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤ÈÆ°¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì
-¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê
-¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥
+You may need to rb_debug the module. The modules can be linked
+statically by adding directory name in the ext/Setup file,
+so that you can inspect the module by the debugger.
-(10) done, now you have the extension module
+(10) done, now you have the extension library
¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
-»È¤¤¤¯¤À¤µ¤¤¡¥ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
+»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
¼çÄ¥¤·¤Þ¤»¤ó¡¥
-Appendix A. ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
+Appendix A. Ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
-ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
-¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
+Ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
+¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
»×¤¤¤Þ¤¹¡¥
-coore ruby language
+ruby language core
class.c
error.c
@@ -780,13 +739,13 @@ class library
Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹
-C¸À¸ì¤«¤éruby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+C¸À¸ì¤«¤éRuby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
** ·¿
VALUE
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡¥
@@ -797,21 +756,21 @@ ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
const: nil object
- TRUE
+ Qtrue
-const: TRUE object(default true value)
+const: Qtrue object(default true value)
- FALSE
+ Qfalse
-const: FALSE object
+const: Qfalse object
** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
-C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
-¤Î¥Ý¥¤¥ó¥¿¤¬ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
-´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤Îruby¥ª¥Ö
+C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
+¤Î¥Ý¥¤¥ó¥¿¤¬Ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
+´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤ÎRuby¥ª¥Ö
¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
¤¬¤¢¤ë¡¥
@@ -828,20 +787,20 @@ data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
VALUE rb_define_class(char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
+super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
VALUE rb_define_module(char *name)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
void rb_include_module(VALUE class, VALUE module)
@@ -852,61 +811,70 @@ super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
-** Âç°èÊÑ¿ôÄêµÁ
+** Defining Global Variables
void rb_define_variable(char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï
-¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤Æruby¤Î¼±Ê̻ҤȤ·
-¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤Ïruby¥×¥í¥°¥é¥à¤«¤é
-¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
+Defines a global variable which is shared between C and Ruby. If name
+contains the character which is not allowed to be part of the symbol,
+it can't be seen from Ruby programs.
void rb_define_readonly_variable(char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read
-only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
+Defines a read-only global variable. Works just like
+rb_define_variable(), except defined variable is read-only.
void rb_define_virtual_variable(char *name,
VALUE (*getter)(), VALUE (*setter)())
-´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ërubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ
-¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥
+Defines a virtual variable, whose behavior is defined by pair of C
+functions. The getter function is called when the variable is
+referred. The setter function is called when the value is set to the
+variable. The prototype for getter/setter functions are:
+
+ VALUE getter(ID id)
+ void setter(VALUE val, ID id)
+
+The getter function must return the value for the access.
void rb_define_hooked_variable(char *name, VALUE *var,
VALUE (*getter)(), VALUE (*setter)())
-´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬
-»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter
-¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê
-¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
+Defines hooked variable. It's virtual variable with C variable. The
+getter is called as
+
+ VALUE getter(ID id, VALUE *var)
+
+returning new value. The setter is called as
+
+ void setter(VALUE val, ID id, VALUE *var)
+
+GC requires to mark the C global variables which hold Ruby values.
void rb_global_variable(VALUE *var)
-GC¤Î¤¿¤á¡¤ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, ruby¥ª¥Ö¥¸¥§
-¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
+Tells GC to protect these variables.
-** ¥¯¥é¥¹Äê¿ô
+** Constant Definition
- void rb_define_const(VALUE class, char *name, VALUE val)
+ void rb_define_const(VALUE klass, char *name, VALUE val)
-¥¯¥é¥¹Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
+Defines a new constant under the class/module.
void rb_define_global_const(char *name, VALUE val)
-Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
+Defines global contant. This is just work as
rb_define_const(cKernal, name, val)
-¤ÈƱ¤¸°ÕÌ£¡¥
-
-** ¥á¥½¥Ã¥ÉÄêµÁ
+** Method Definition
rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú
¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú
-¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àruby¤ÎÇÛÎó)¤È¤¤¤¦·Á
+¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àRuby¤ÎÇÛÎó)¤È¤¤¤¦·Á
¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
@@ -927,7 +895,7 @@ argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì
¤ë¡¥
-** ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
+** Ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
@@ -939,7 +907,7 @@ argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
VALUE rb_eval_string(char *str)
-ʸ»úÎó¤òruby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+ʸ»úÎó¤òRuby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
ID rb_intern(char *name)
@@ -959,7 +927,7 @@ class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
VALUE rb_iv_get(VALUE obj, char *name)
obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹
-ÊÑ¿ô¤Ï ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿
+ÊÑ¿ô¤Ï Ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿
¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥
VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
@@ -993,69 +961,66 @@ val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
** Îã³°¡¦¥¨¥é¡¼
- void Warning(char *fmt, ...)
+ void rb_warning(char *fmt, ...)
-verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+rb_verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
- void Fail(char *fmt, ...)
+ void rb_raise(rb_eRuntimeError, char *fmt, ...)
Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
- void Fatal(char *fmt, ...)
+ void rb_fatal(char *fmt, ...)
Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â
¹Ô¤µ¤ì¤ë)¡¥
- void Bug(char *fmt, ...)
+ void rb_bug(char *fmt, ...)
¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ
¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°
½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
-** ruby¤Î½é´ü²½¡¦¼Â¹Ô
+** Initialize and Starts the Interpreter
-ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
-¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤ÏɬÍפʤ¤¡¥
+The embedding API are below (not needed for extension libraries):
void ruby_init(int argc, char **argv, char **envp)
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
+Initializes the interpreter.
void ruby_run()
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+Starts execution of the interpreter.
void ruby_script(char *name)
-ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
+Specifies the name of the script ($0).
-Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
+Appendix B. Functions Available in extconf.rb
extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
have_library(lib, func)
-´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é
-¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥
+Checks whether library which contains specified function exists.
+Returns true if the library exists.
have_func(func)
-´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é
-¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê
-¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þTRUE¤òÊÖ¤¹¡¥
+Checks whether func exists. Returns true if the function exists. To
+check functions in the additional library, you need to check that
+library first using have_library().
have_header(header)
-¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë
-»þTRUE¤òÊÖ¤¹¡¥
+Checks for the header files. Returns true if the header file exists.
create_makefile(target)
-³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð
-¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾¤òɽ
-¤¹¡¥
+Generates the Makefile for the extension library. If you don't invoke
+this method, the compilation will not be done.
/*
* Local variables:
diff --git a/README.EXT.jp b/README.EXT.jp
new file mode 100644
index 0000000000..87175be853
--- /dev/null
+++ b/README.EXT.jp
@@ -0,0 +1,1147 @@
+.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
+
+Ruby¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Îºî¤êÊý¤òÀâÌÀ¤·¤Þ¤¹¡¥
+
+1¡¥´ðÁÃÃμ±
+
+C¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤¢¤ê¡¤¥Ç¡¼¥¿¤Ë¤Ï·¿¤¬¤¢¤ê¤Þ¤»¤ó¡¥¤Ç¤¹¤«¤é¡¤¤¿
+¤È¤¨¤Ð¥Ý¥¤¥ó¥¿¤òint¤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë¤È¡¤¤½¤ÎÃͤÏÀ°¿ô¤È¤·¤Æ¼è
+¤ê°·¤ï¤ì¤Þ¤¹¡¥µÕ¤ËRuby¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤Ê¤¯¡¤¥Ç¡¼¥¿¤Ë·¿¤¬¤¢¤ê¤Þ
+¤¹¡¥¤³¤Î°ã¤¤¤Î¤¿¤á¡¤C¤ÈRuby¤ÏÁê¸ß¤ËÊÑ´¹¤·¤Ê¤±¤ì¤Ð¡¤¤ª¸ß¤¤¤Î
+¥Ç¡¼¥¿¤ò¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤»¤ó¡¥
+
+Ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
+¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È
+¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤Ruby
+¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥
+
+VALUE¤«¤éC¤Ë¤È¤Ã¤Æ°ÕÌ£¤Î¤¢¤ë¥Ç¡¼¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï
+
+ (1) VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤òÃΤë
+ (2) VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë
+
+¤ÎξÊý¤¬É¬ÍפǤ¹¡¥(1)¤ò˺¤ì¤ë¤È´Ö°ã¤Ã¤¿¥Ç¡¼¥¿¤ÎÊÑ´¹¤¬¹Ô¤ï¤ì
+¤Æ¡¤ºÇ°­¥×¥í¥°¥é¥à¤¬core dump¤·¤Þ¤¹¡¥
+
+1.1 ¥Ç¡¼¥¿¥¿¥¤¥×
+
+Ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ­¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ T_NIL nil
+ T_OBJECT Ä̾ï¤Î¥ª¥Ö¥¸¥§¥¯¥È
+ T_CLASS ¥¯¥é¥¹
+ T_MODULE ¥â¥¸¥å¡¼¥ë
+ T_FLOAT ÉâÆ°¾®¿ôÅÀ¿ô
+ T_STRING ʸ»úÎó
+ T_REGEXP Àµµ¬É½¸½
+ T_ARRAY ÇÛÎó
+ T_FIXNUM Fixnum(31bitĹÀ°¿ô)
+ T_HASH Ï¢ÁÛÇÛÎó
+ T_STRUCT (Ruby¤Î)¹½Â¤ÂÎ
+ T_BIGNUM ¿ÇÜĹÀ°¿ô
+ T_FILE Æþ½ÐÎÏ
+ T_TRUE ¿¿
+ T_FALSE µ¶
+ T_DATA ¥Ç¡¼¥¿
+
+¤½¤Î¾¤ËÆâÉô¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ T_ICLASS
+ T_MATCH
+ T_VARMAP
+ T_SCOPE
+ T_NODE
+
+¤Û¤È¤ó¤É¤Î¥¿¥¤¥×¤ÏC¤Î¹½Â¤ÂΤǼÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+1.2 VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤¹¤ë
+
+ruby.h¤Ç¤ÏTYPE()¤È¤¤¤¦¥Þ¥¯¥í¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¡¤VALUE¤Î¥Ç¡¼¥¿
+¥¿¥¤¥×¤òÃΤ뤳¤È¤¬½ÐÍè¤Þ¤¹¡¥TYPE()¥Þ¥¯¥í¤Ï¾å¤Ç¾Ò²ð¤·¤¿T_XXXX
+¤Î·Á¼°¤ÎÄê¿ô¤òÊÖ¤·¤Þ¤¹¡¥VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Ë±þ¤¸¤Æ½èÍý¤¹¤ë
+¾ì¹ç¤Ë¤Ï¡¤TYPE()¤ÎÃͤÇʬ´ô¤¹¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+ switch (TYPE(obj)) {
+ case T_FIXNUM:
+ /* FIXNUM¤Î½èÍý */
+ break;
+ case T_STRING:
+ /* ʸ»úÎó¤Î½èÍý */
+ break;
+ case T_ARRAY:
+ /* ÇÛÎó¤Î½èÍý */
+ break;
+ default:
+ /* Îã³°¤òȯÀ¸¤µ¤»¤ë */
+ TypeError("not valid value");
+ break;
+ }
+
+¤½¤ì¤È¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤·¤Æ¡¤Àµ¤·¤¯¤Ê¤±¤ì¤ÐÎã³°¤òȯÀ¸¤¹
+¤ë´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ void Check_Type(VALUE value, int type)
+
+¤³¤Î´Ø¿ô¤Ïvalue¤¬type¤Ç̵¤±¤ì¤Ð¡¤Îã³°¤òȯÀ¸¤µ¤»¤Þ¤¹¡¥°ú¿ô¤È
+¤·¤ÆÍ¿¤¨¤é¤ì¤¿VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤¬Àµ¤·¤¤¤«¤É¤¦¤«¥Á¥§¥Ã¥¯¤¹
+¤ë¤¿¤á¤Ë¤Ï¡¤¤³¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+FIXNUM¤ÈNIL¤Ë´Ø¤·¤Æ¤Ï¤è¤ê¹â®¤ÊȽÊÌ¥Þ¥¯¥í¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ FIXNUM_P(obj)
+ NIL_P(obj)
+
+1.3 VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë
+
+¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_NIL, T_FALSE, T_TRUE¤Ç¤¢¤ë»þ¡¤¥Ç¡¼¥¿¤Ï¤½¤ì¤¾
+¤ìnil, false, true¤Ç¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤Ò¤È
+¤Ä¤º¤Ä¤·¤«Â¸ºß¤·¤Þ¤»¤ó¡¥
+
+¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç
+¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È
+¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºRuby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
+¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤
+¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤­¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬
+ȯÀ¸¤¹¤ë)¡¥
+
+ƱÍͤ˥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤ëÊÑ´¹¥Þ¥¯¥í¤Ïdouble¤ò¼è¤ê½Ð¤¹
+¡ÖNUM2DBL()¡×¤Èchar*¤ò¼è¤ê½Ð¤¹¡ÖSTR2CSTR()¡×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+¤½¤ì°Ê³°¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ÏÂбþ¤¹¤ëC¤Î¹½Â¤ÂΤ¬¤¢¤ê¤Þ¤¹¡¥Âбþ¤¹
+¤ë¹½Â¤ÂΤΤ¢¤ëVALUE¤Ï¤½¤Î¤Þ¤Þ¥­¥ã¥¹¥È(·¿ÊÑ´¹)¤¹¤ì¤Ð¹½Â¤ÂΤÎ
+¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¤Ç¤­¤Þ¤¹¡¥
+
+¹½Â¤ÂΤϡÖstruct RXxxxx¡×¤È¤¤¤¦Ì¾Á°¤Çruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤Þ
+¤¹¡¥Î㤨¤Ðʸ»úÎó¤Ï¡Östruct RString¡×¤Ç¤¹¡¥¼ÂºÝ¤Ë»È¤¦²ÄǽÀ­¤¬
+¤¢¤ë¤Î¤Ïʸ»úÎó¤ÈÇÛÎ󤯤餤¤À¤È»×¤¤¤Þ¤¹¡¥
+
+ruby.h¤Ç¤Ï¹½Â¤ÂΤإ­¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ
+»ú¤Ë¤·¤¿¤â¤Î)¤È¤¤¤¦Ì¾Á°¤ÇÄ󶡤µ¤ì¤Æ¤¤¤Þ¤¹(Îã: RSTRING())¡¥
+
+Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È
+¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡×
+¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAY(ary)->len¡×¡¤
+¡ÖRARRAY(ary)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
+
+Ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
+¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤·
+¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍƤÎÀ°¹çÀ­¤¬
+¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+1.4 C¤Î¥Ç¡¼¥¿¤òVALUE¤ËÊÑ´¹¤¹¤ë
+
+VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
+
+ * FIXNUM¤Î¾ì¹ç
+
+ 1bit±¦¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
+
+ * ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç
+
+ ¤½¤Î¤Þ¤ÞVALUE¤Ë¥­¥ã¥¹¥È¤¹¤ë¡¥
+
+¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥¤è¤Ã¤Æ¡¤LSB¤ò¥Á¥§¥Ã¥¯¤¹¤ì¤ÐVALUE¤¬FIXNUM¤«¤É
+¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
+¤¤¤ë)¡¥
+
+¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤ÎRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
+¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
+ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
+¤ÏRuby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
+¤Î¤â¤Î)¤À¤±¤Ç¤¹¡¥
+
+FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
+¤«¤éVALUE¤ËÊÑ´¹¤¹¤ë¥Þ¥¯¥í¤Ï°Ê²¼¤Î¤â¤Î¤¬¤¢¤ê¤Þ¤¹¡¥É¬Íפ˱þ¤¸
+¤Æ»È¤¤Ê¬¤±¤Æ¤¯¤À¤µ¤¤¡¥
+
+ INT2FIX() ¤â¤È¤ÎÀ°¿ô¤¬31bit°ÊÆâ¤Ë¼ý¤Þ¤ë¼«¿®¤¬¤¢¤ë»þ
+ INT2NUM() Ǥ°Õ¤ÎÀ°¿ô¤«¤éVALUE¤Ø
+
+INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
+¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
+
+1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë
+
+ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤRuby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍƤι¹¿·¤ò
+¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
+Ruby¤¬ÍÑ°Õ¤·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
+
+¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô
+¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥
+
+ ʸ»úÎó¤ËÂФ¹¤ë´Ø¿ô
+
+ rb_str_new(char *ptr, int len)
+
+ ¿·¤·¤¤Ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_str_new2(char *ptr)
+
+ C¤Îʸ»úÎ󤫤éRuby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤Îµ¡Ç½¤Ï
+ rb_str_new(ptr, strlen(ptr))¤ÈƱÅù¤Ç¤¢¤ë¡¥
+
+ rb_str_cat(VALUE str, char *ptr, int len)
+
+ Ruby¤Îʸ»úÎóstr¤Ëlen¥Ð¥¤¥È¤Îʸ»úÎóptr¤òÄɲ乤롥
+
+ ÇÛÎó¤ËÂФ¹¤ë´Ø¿ô
+
+ rb_ary_new()
+
+ Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_new2(int len)
+
+ Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥lenÍ×ÁÇʬ¤ÎÎΰè¤ò¤¢¤é¤«¤¸¤á³ä¤ê
+ Åö¤Æ¤Æ¤ª¤¯¡¥
+
+ rb_ary_new3(int n, ...)
+
+ °ú¿ô¤Ç»ØÄꤷ¤¿nÍ×ÁǤò´Þ¤àÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_new4(int n, VALUE *elts)
+
+ ÇÛÎó¤ÇÍ¿¤¨¤¿nÍ×ÁǤÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_push(VALUE ary, VALUE val)
+ rb_ary_pop(VALUE ary)
+ rb_ary_shift(VALUE ary)
+ rb_ary_unshift(VALUE ary, VALUE val)
+ rb_ary_entry(VALUE ary, int idx)
+
+ Array¤ÎƱ̾¤Î¥á¥½¥Ã¥É¤ÈƱ¤¸Æ¯¤­¤ò¤¹¤ë´Ø¿ô¡¥Âè1°ú¿ô¤Ïɬ¤º
+ ÇÛÎó¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡¥
+
+2¡¥Ruby¤Îµ¡Ç½¤ò»È¤¦
+
+¸¶ÍýŪ¤ËRuby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥Ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
+½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
+¤ÏRuby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
+²ð¤·¤Þ¤¹¡¥
+
+2.1 Ruby¤Ëµ¡Ç½¤òÄɲ乤ë
+
+Ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤ÐRuby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
+¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥Ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲ乤ë´Ø¿ô¤¬
+Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ * ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë
+ * ¥á¥½¥Ã¥É¡¤Æðۥ᥽¥Ã¥É¤Ê¤É
+ * Äê¿ô
+
+¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥
+
+2.1.1 ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
+
+¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_define_class(char *name, VALUE super)
+ VALUE rb_define_module(char *name)
+
+¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥
+¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç
+¤ÏÌá¤êÃͤòÊÑ¿ô¤Ë³ÊǼ¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ë¤Ç¤·¤ç¤¦¡¥
+
+¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤ò¾¤Î¥¯¥é¥¹¤ÎÆâÉô¤Ë¥Í¥¹¥È¤·¤ÆÄêµÁ¤¹¤ë»þ¤Ë
+¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_define_class(VALUE outer, char *name, VALUE super)
+ VALUE rb_define_module(VALUE outer, char *name)
+
+2.1.2 ¥á¥½¥Ã¥É/Æðۥ᥽¥Ã¥ÉÄêµÁ
+
+¥á¥½¥Ã¥É¤äÆðۥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ void rb_define_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+ void rb_define_singleton_method(VALUE object, char *name,
+ VALUE (*func)(), int argc)
+
+
+Ç°¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆðۥ᥽¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯
+¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥Ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
+¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆðۥ᥽¥Ã¥É¤¬»È¤ï¤ì
+¤Þ¤¹¡¥
+
+¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È
+·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬Àµ¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°ÕÌ£
+¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½¤ó
+¤Ê¤Ë)¡¥¼ÂºÝ¤Î´Ø¿ô¤Ë¤ÏÀèƬ¤Î°ú¿ô¤È¤·¤Æself¤¬Í¿¤¨¤é¤ì¤Þ¤¹¤Î¤Ç¡¤
+»ØÄꤷ¤¿¿ô¤è¤ê1¿¤¤°ú¿ô¤ò»ý¤Ä¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú
+¿ô¤ÏRuby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
+
+¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á
+¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥
+
+ void rb_define_private_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
+¥É¤Ç¤¹¡¥
+
+¤â¤¦¤Ò¤È¤Ä¤Ï¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô
+¤È¤Ï¥â¥¸¥å¡¼¥ë¤ÎÆðۥ᥽¥Ã¥É¤Ç¤¢¤ê¡¤Æ±»þ¤Ëprivate¥á¥½¥Ã¥É¤Ç
+¤â¤¢¤ë¤â¤Î¤Ç¤¹¡¥Îã¤ò¤¢¤²¤ë¤ÈMath¥â¥¸¥å¡¼¥ë¤Îsqrt()¤Ê¤É¤¬¤¢¤²
+¤é¤ì¤Þ¤¹¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï
+
+ Math.sqrt(4)
+
+¤È¤¤¤¦·Á¼°¤Ç¤â
+
+ include Math
+ sqrt(4)
+
+¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î
+Ä̤ê¤Ç¤¹¡¥
+
+ void rb_define_module_function(VALUE module, char *name,
+ VALUE (*func)(), int argc)
+
+´Ø¿ôŪ¥á¥½¥Ã¥É(Kernel¥â¥¸¥å¡¼¥ë¤Îprivate method)¤òÄêµÁ¤¹¤ë¤¿
+¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ void rb_define_global_function(char *name, VALUE (*func)(), int argc)
+
+
+2.1.3 Äê¿ôÄêµÁ
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
+¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_const(VALUE class, char *name, VALUE val)
+ void rb_define_global_const(char *name, VALUE val)
+
+Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å
+¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥
+
+2.2 Ruby¤Îµ¡Ç½¤òC¤«¤é¸Æ¤Ó½Ð¤¹
+
+´û¤Ë¡Ø1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
+»È¤¨¤Ð¡¤Ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
+¤Þ¤¹¡¥
+
+# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸«
+# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥
+
+¤½¤ì°Ê³°¤Ë¤âRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
+
+2.2.1 Ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
+
+C¤«¤éRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
+Í¿¤¨¤é¤ì¤¿Ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ VALUE rb_eval_string(char *str)
+
+¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶­¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô
+¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥
+
+2.2.2 ID¤Þ¤¿¤Ï¥·¥ó¥Ü¥ë
+
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
+¤¹¡¥¤½¤ÎÁ°¤Ë¡¤Ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
+»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
+
+ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤ÎÃæ¤Ç¤Ï
+
+ :¼±ÊÌ»Ò
+
+¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô
+
+ rb_intern(char *name)
+
+¤ò»È¤¤¤Þ¤¹¡¥¤Þ¤¿°ìʸ»ú¤Î±é»»»Ò¤Ï¤½¤Îʸ»ú¥³¡¼¥É¤¬¤½¤Î¤Þ¤Þ¥·¥ó
+¥Ü¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥Ruby¤«¤é°ú¿ô¤È¤·¤ÆÍ¿¤¨¤é¤ì¤¿¥·¥ó¥Ü¥ë(¤Þ
+¤¿¤Ïʸ»úÎó)¤òID¤ËÊÑ´¹¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ rb_to_id(VALUE symbol)
+
+2.2.3 C¤«¤éRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹
+
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
+¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
+
+¤³¤Î´Ø¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥Èrecv¤Îmid¤Ç»ØÄꤵ¤ì¤ë¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð
+¤·¤Þ¤¹¡¥¤½¤Î¾¤Ë°ú¿ô¤Î»ØÄê¤Î»ÅÊý¤¬°ã¤¦°Ê²¼¤Î´Ø¿ô¤â¤¢¤ê¤Þ¤¹¡¥
+
+ VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
+ VALUE rb_apply(VALUE recv, ID mid, VALUE args)
+
+apply¤Ë¤Ï°ú¿ô¤È¤·¤ÆRuby¤ÎÇÛÎó¤òÍ¿¤¨¤Þ¤¹¡¥
+
+2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë
+
+C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤Äê¿ô¡¤¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ
+¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»¥¹¤Ç¤­
+¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
+
+¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ
+¤ê¤Ç¤¹¡¥
+
+ VALUE rb_ivar_get(VALUE obj, ID id)
+ VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
+
+id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+ VALUE rb_const_get(VALUE obj, ID id)
+
+Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
+¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+3¡¥Ruby¤ÈC¤È¤Î¾ðÊó¶¦Í­
+
+C¸À¸ì¤ÈRuby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
+
+3.1 C¤«¤é»²¾È¤Ç¤­¤ëRuby¤ÎÄê¿ô
+
+°Ê²¼¤ÎRuby¤ÎÄê¿ô¤ÏC¤Î¥ì¥Ù¥ë¤«¤é»²¾È¤Ç¤­¤ë¡¥
+
+ Qtrue
+ Qfalse
+
+¿¿µ¶ÃÍ¡¥Qfalse¤ÏC¸À¸ì¤Ç¤âµ¶¤È¤ß¤Ê¤µ¤ì¤ë(¤Ä¤Þ¤ê0)¡¥
+
+ Qnil
+
+C¸À¸ì¤«¤é¸«¤¿¡Önil¡×¡¥
+
+3.2 C¤ÈRuby¤Ç¶¦Í­¤µ¤ì¤ëÂç°èÊÑ¿ô
+
+C¤ÈRuby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
+ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï
+¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥
+
+ void rb_define_variable(char *name, VALUE *var)
+
+¤³¤Î´Ø¿ô¤ÏRuby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
+`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
+¹¹¤¹¤ë¤È¼«Æ°Åª¤ËRuby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+
+¤Þ¤¿Ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
+ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥
+
+ void rb_define_readonly_variable(char *name, VALUE *var)
+
+¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤­¤Þ¤¹¡¥hookÉÕ¤­
+¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥hookÉÕ¤­Âç°èÊÑ¿ô¤Î
+Ãͤλ²¾È¤äÀßÄê¤Ïhook¤Ç¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_hooked_variable(char *name, VALUE *var,
+ VALUE (*getter)(), VALUE (*setter)())
+
+¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ
+¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì
+¤¿»þ¤Ë¤Ï´Ø¿ôsetter¤¬¸Æ¤Ð¤ì¤ë¡¥hook¤ò»ØÄꤷ¤Ê¤¤¾ì¹ç¤Ïgetter¤ä
+setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
+
+# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
+
+¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRuby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
+´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_virtual_variable(char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿Ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
+getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥
+
+getter¤Èsetter¤Î»ÅÍͤϰʲ¼¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ (*getter)(ID id, void *data, struct global_entry* entry);
+ (*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
+
+3.3 C¤Î¥Ç¡¼¥¿¤òRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¹¤ë
+
+C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
+¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤ÇRuby
+¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
+²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+
+ Data_Wrap_Struct(class,mark,free,ptr)
+
+¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+
+class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬Ruby¤Î¥ª¥Ö¥¸¥§
+¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
+»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
+
+# ¤½¤Î¤è¤¦¤Ê»²¾È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
+
+free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔÍפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î
+´Ø¿ô¤¬¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡¥
+
+C¤Î¹½Â¤ÂΤγäÅö¤ÈData¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤òƱ»þ¤Ë¹Ô¤¦¥Þ¥¯¥í¤È
+¤·¤Æ°Ê²¼¤Î¤â¤Î¤¬Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ Data_Make_Struct(class, type, mark, free, sval)
+
+¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+
+class, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
+¤Ï³ä¤êÅö¤Æ¤ëC¹½Â¤ÂΤη¿¤Ç¤¹¡¥³ä¤êÅö¤Æ¤é¤ì¤¿¹½Â¤ÂΤÏÊÑ¿ôsval
+¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤Î·¿¤Ï (type*) ¤Ç¤¢¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤é¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤Î¤Ï°Ê²¼¤Î¥Þ¥¯¥í¤òÍѤ¤
+¤Þ¤¹¡¥
+
+ Data_Get_Struct(obj, type, sval)
+
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤ÏÊÑ¿ôsval¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥
+
+¤³¤ì¤é¤ÎData¤Î»È¤¤Êý¤Ï¤Á¤ç¤Ã¤Èʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç¡¤¸å¤ÇÀâÌÀ¤¹¤ë
+ÎãÂê¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+4¡¥ÎãÂê - dbm¥Ñ¥Ã¥±¡¼¥¸¤òºî¤ë
+
+¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
+Ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë
+¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥
+
+(1) ¥Ç¥£¥ì¥¯¥È¥ê¤òºî¤ë
+
+ % mkdir ext/dbm
+
+Ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
+¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤·¤¿¡¥Ruby¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¾ì¹ç¤Ë
+¤ÏRuby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥
+¥â¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤Ë
+Áª¤ó¤Ç¹½¤¤¤Þ¤»¤ó¡¥
+
+(2) MANIFEST¥Õ¥¡¥¤¥ë¤òºî¤ë
+
+ % cd ext/dbm
+ % touch MANIFEST
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
+ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
+¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤ÀÅŪ¥ê¥ó¥¯¤Îmake¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê
+¤¬³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ
+¤¤¤Þ¤¹¡¥¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî¤ë¾ì¹ç¤Ë¤Ïɬ¤º¤·¤âɬÍפǤÏ
+¤¢¤ê¤Þ¤»¤ó¡¥
+
+(3) À߷פ¹¤ë
+
+¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
+·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
+¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
+¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+(4) C¥³¡¼¥É¤ò½ñ¤¯
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥êËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
+¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
+¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤È¤¤¤¦¥Õ¥¡
+¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼
+¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥â¥¸¥å¡¼¥ë̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
+¤È¤¬¾×Æͤ¹¤ë¤«¤é¤Ç¤¹¡¥
+
+Ruby¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
+¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤Î¾ì¹ç¡ÖInit_dbm¡×
+¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î
+ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥
+
+--
+Init_dbm()
+{
+ /* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */
+ cDBM = rb_define_class("DBM", rb_cObject);
+ /* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */
+ rb_include_module(cDBM, rb_mEnumerable);
+
+ /* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */
+ rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
+
+ /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥Éclose(): °ú¿ô¤Ï¤Ê¤· */
+ rb_define_method(cDBM, "close", fdbm_close, 0);
+ /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥É[]: °ú¿ô¤Ï1¸Ä */
+ rb_define_method(cDBM, "[]", fdbm_fetch, 1);
+ :
+
+ /* DBM¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô̾¤Î¤¿¤á¤ÎID */
+ id_dbm = rb_intern("dbm");
+}
+--
+
+DBM¥â¥¸¥å¡¼¥ë¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
+¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òRuby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+
+
+dbm.c¤Ç¤ÏData_Make_Struct¤ò°Ê²¼¤Î¤è¤¦¤Ë»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
+
+obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+--
+
+¤³¤³¤Ç¤Ïdbmstruct¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤òData¤Ë¥«¥×¥»¥ë²½¤·¤Æ¤¤
+¤Þ¤¹¡¥DBM*¤òľÀÜ¥«¥×¥»¥ë²½¤·¤Ê¤¤¤Î¤Ïclose()¤·¤¿»þ¤Î½èÍý¤ò¹Í
+¤¨¤Æ¤Î¤³¤È¤Ç¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤édbmstruct¹½Â¤ÂΤΥݥ¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á
+¤Ë°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closed_dbm();\
+}
+--
+
+¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¥Þ¥¯¥í¤Ç¤¹¤¬¡¤Íפ¹¤ë¤Ëdbmdata¹½Â¤ÂΤΥݥ¤¥ó¥¿
+¤Î¼è¤ê½Ð¤·¤È¡¤close¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Î¥Á¥§¥Ã¥¯¤ò¤Þ¤È¤á¤Æ¤¤
+¤ë¤À¤±¤Ç¤¹¡¥
+
+DBM¥¯¥é¥¹¤Ë¤Ï¤¿¤¯¤µ¤ó¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¤¬¡¤Ê¬Îह¤ë¤È3¼ïÎà¤Î
+°ú¿ô¤Î¼õ¤±Êý¤¬¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ï°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¤â¤Î¤Ç¡¤Îã¤È
+¤·¤Æ¤Ïdelete¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¡¥delete¥á¥½¥Ã¥É¤ò¼ÂÁõ¤·¤Æ¤¤¤ë
+fdbm_delete()¤Ï¤³¤Î¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+static VALUE
+fdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ :
+}
+--
+
+°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É
+¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥
+
+°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤ÈRuby¤ÎÇÛÎó¤Ç¼õ¤±
+¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
+¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø
+¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+static VALUE
+fdbm_s_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ :
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ :
+}
+--
+
+¤³¤Î¥¿¥¤¥×¤Î´Ø¿ô¤ÏÂè1°ú¿ô¤¬Í¿¤¨¤é¤ì¤¿°ú¿ô¤Î¿ô¡¤Âè2°ú¿ô¤¬Í¿¤¨
+¤é¤ì¤¿°ú¿ô¤ÎÆþ¤Ã¤Æ¤¤¤ëÇÛÎó¤Ë¤Ê¤ê¤Þ¤¹¡¥self¤ÏÂè3°ú¿ô¤È¤·¤ÆÍ¿
+¤¨¤é¤ì¤Þ¤¹¡¥
+
+¤³¤ÎÇÛÎó¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤ò²òÀϤ¹¤ë¤¿¤á¤Î´Ø¿ô¤¬open()¤Ç¤â»È¤ï
+¤ì¤Æ¤¤¤ërb_scan_args()¤Ç¤¹¡¥Âè3°ú¿ô¤Ë»ØÄꤷ¤¿¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë
+½¾¤¤¡¤Âè4ÊÑ¿ô°Ê¹ß¤Ë»ØÄꤷ¤¿ÊÑ¿ô¤ËÃͤòÂåÆþ¤·¤Æ¤¯¤ì¤Þ¤¹¡¥¤³¤Î
+¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¡¤Âè1ʸ»úÌܤ¬¾Êά¤Ç¤­¤Ê¤¤°ú¿ô¤Î¿ô¡¤Âè2ʸ»úÌܤ¬
+¾Êά¤Ç¤­¤ë°ú¿ô¤Î¿ô¡¤Âè3ʸ»úÌܤ¬Âбþ¤¹¤ëÁê¼ê¤¬Ìµ¤¤¤¢¤Þ¤ê¤Î°ú
+¿ô¤¬¤¢¤ë¤«¤É¤¦¤«¤ò¼¨¤¹"*"¤Ç¤¹¡¥2ʸ»úÌܤÈ3ʸ»úÌܤϾÊά¤Ç¤­¤Þ
+¤¹¡¥dbm.c¤ÎÎã¤Ç¤Ï¡¤¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï"11"¤Ç¤¹¤«¤é¡¤°ú¿ô¤ÏºÇÄã1¤Ä
+¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î
+ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+Ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
+¤¦¤Ç¤¹¡¥
+
+--
+static VALUE
+fdbm_indexes(obj, args)
+ VALUE obj;
+ struct RArray *args;
+{
+ :
+}
+--
+
+Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤ÏRuby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥­¥ã¥¹¥È¤ò¸º
+¤é¤¹¤¿¤á struct RArray* ¤Ç¼õ¤±¤Æ¤¤¤Þ¤¹¤¬¡¤VALUE¤Ç¤âƱ¤¸¤³¤È
+¤Ç¤¹¡¥
+
+** Ãí°Õ»ö¹à
+
+Ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬Ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
+C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤ÆRuby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
+¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤·¤Þ¤¹¡¥
+
+ void rb_global_variable(VALUE *var)
+
+(5) extconf.rb¤òÍÑ°Õ¤¹¤ë
+
+Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
+¤Þ¤¹¡¥extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã
+¥¯¤Ê¤É¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤ÎRuby´Ø¿ô
+¤ò»È¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
+
+ have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
+ have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
+ have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯
+ create_makefile(target): Makefile¤ÎÀ¸À®
+
+°Ê²¼¤ÎÊÑ¿ô¤ò»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+
+ $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
+ $LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
+
+¥â¥¸¥å¡¼¥ë¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤Ê¤º¡¤¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³
+¥ó¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤Ï
+À¸À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
+
+¥â¥¸¥å¡¼¥ë¤¬Ruby 1.1ÀìÍѤǤ¢¤ë¾ì¹ç¤Ë¤Ï
+
+ require 'mkmf'
+
+¤òextconf.rb¤ÎÀèƬ¤ËÃÖ¤¯¤ÈÊØÍø¤Ç¤·¤ç¤¦¡¥
+
+(6) depend¤òÍÑ°Õ¤¹¤ë
+
+¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
+Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+
+ % gcc -MM *.c > depend
+
+¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤Æ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
+
+(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë
+
+ % ls > MANIFEST
+ % vi MANIFEST
+
+*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤­¤Þ¤¹¡¥
+make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍƤϻ²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê
+¤Ïµ¯¤­¤Þ¤»¤ó¤¬¡¤¥Ñ¥Ã¥±¡¼¥¸¥ó¥°¤Î»þ¤Ë»²¾È¤¹¤ë¤³¤È¤¬¤¢¤ë¤Î¤È¡¤
+ɬÍפʥե¡¥¤¥ë¤ò¶èÊ̤Ǥ­¤ë¤Î¤Ç¡¤ÍÑ°Õ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤Ç¤·¤ç
+¤¦¡¥
+
+(8) Makefile¤òÀ¸À®¤¹¤ë
+
+Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
+
+ ruby extconf.rb
+
+¤È¤·¤Þ¤¹¡¥extconf.rb¤Ë require 'mkmf' ¤Î¹Ô¤¬¤Ê¤¤¾ì¹ç¤Ë¤Ï¥¨¥é¡¼
+¤Ë¤Ê¤ê¤Þ¤¹¤Î¤Ç¡¤°ú¿ô¤òÄɲä·¤Æ
+
+ ruby -r mkmf extconf.rb
+
+¤È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍÑ°Õ¤·¤¿¾ì¹ç¤Ë¤ÏRubyÁ´ÂΤÎmake¤Î»þ¤Ë
+¼«Æ°Åª¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¤Î¤Ç¡¤¤³¤Î¥¹¥Æ¥Ã¥×¤ÏÉÔÍפǤ¹¡¥
+
+(9) make¤¹¤ë
+
+ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤òÀ¸À®¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¾ì¤Çmake¤·¤Æ¤¯¤À¤µ
+¤¤¡¥É¬ÍפǤ¢¤ì¤Ð make install ¤Ç¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
+
+ext°Ê²¼¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÍÑ°Õ¤·¤¿¾ì¹ç¤Ï¡¤Ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç
+make¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤É¬Íפˤè¤Ã¤Æ¤Ï¤½¤Î¥â
+¥¸¥å¡¼¥ë¤ÎRuby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ
+¤¿Ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤Ïmake install¤ÇRuby¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯
+¥È¥ê¤Î²¼¤Ë¥³¥Ô¡¼¤µ¤ì¤Þ¤¹¡¥¤â¤·¥â¥¸¥å¡¼¥ë¤È¶¨Ä´¤·¤Æ»È¤¦Ruby¤Ç
+µ­½Ò¤µ¤ì¤¿¥×¥í¥°¥é¥à¤¬¤¢¤ê¡¤Ruby¥é¥¤¥Ö¥é¥ê¤ËÃÖ¤­¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤
+³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤Î²¼¤Ë lib ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê
+¤òºî¤ê¡¤¤½¤³¤Ë ³ÈÄ¥»Ò .rb ¤Î¥Õ¥¡¥¤¥ë¤òÃÖ¤¤¤Æ¤ª¤±¤ÐƱ»þ¤Ë¥¤¥ó
+¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
+
+(10) ¥Ç¥Ð¥Ã¥°
+
+¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤ÈÆ°¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì
+¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê
+¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥
+
+(11) ¤Ç¤­¤¢¤¬¤ê
+
+¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
+»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
+¼çÄ¥¤·¤Þ¤»¤ó¡¥
+
+Appendix A. Ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
+
+Ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
+¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
+¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
+»×¤¤¤Þ¤¹¡¥
+
+Ruby¸À¸ì¤Î¥³¥¢
+
+ class.c
+ error.c
+ eval.c
+ gc.c
+ object.c
+ parse.y
+ variable.c
+
+¥æ¡¼¥Æ¥£¥ê¥Æ¥£´Ø¿ô
+
+ dln.c
+ fnmatch.c
+ glob.c
+ regex.c
+ st.c
+ util.c
+
+Ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
+
+ dmyext.c
+ inits.c
+ main.c
+ ruby.c
+ version.c
+
+¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê
+
+ array.c
+ bignum.c
+ compar.c
+ dir.c
+ enum.c
+ file.c
+ hash.c
+ io.c
+ marshal.c
+ math.c
+ numeric.c
+ pack.c
+ process.c
+ random.c
+ range.c
+ re.c
+ signal.c
+ sprintf.c
+ string.c
+ struct.c
+ time.c
+
+Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹
+
+C¸À¸ì¤«¤éRuby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+
+** ·¿
+
+ VALUE
+
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
+ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
+ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
+̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡¥
+
+** ÊÑ¿ô¡¦Äê¿ô
+
+ Qnil
+
+Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È
+
+ Qtrue
+
+Äê¿ô: true¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ)
+
+ Qfalse
+
+Äê¿ô: false¥ª¥Ö¥¸¥§¥¯¥È
+
+** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
+
+ Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
+
+C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
+¤Î¥Ý¥¤¥ó¥¿¤¬Ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
+´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤ÎRuby¥ª¥Ö
+¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
+¤¬¤¢¤ë¡¥
+
+ Data_Make_Struct(class, type, mark, free, sval)
+
+type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»
+¥ë²½¤·¤¿¥Ç¡¼¥¿¤òÊÖ¤¹¥Þ¥¯¥í¡¥
+
+ Data_Get_Struct(data, type, sval)
+
+data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
+
+** ·¿¥Á¥§¥Ã¥¯
+
+ TYPE(value)
+ FIXNUM_P(value)
+ NIL_P(value)
+ void Check_Type(VALUE value, int type)
+ void Check_SafeStr(VALUE value)
+
+** ·¿ÊÑ´¹
+
+ FIX2INT(value)
+ INT2FIX(i)
+ NUM2INT(value)
+ INT2NUM(i)
+ NUM2DBL(value)
+ rb_float_new(f)
+ STR2CSTR(value)
+ rb_str_new2(s)
+
+** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
+
+ VALUE rb_define_class(char *name, VALUE super)
+
+super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+
+ VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
+
+super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
+¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+
+ VALUE rb_define_module(char *name)
+
+¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+
+ VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
+
+¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+
+ void rb_include_module(VALUE class, VALUE module)
+
+¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯¥ë¡¼
+¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥
+
+ void rb_extend_object(VALUE object, VALUE module)
+
+¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
+
+** Âç°èÊÑ¿ôÄêµÁ
+
+ void rb_define_variable(char *name, VALUE *var)
+
+Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï
+¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤ÆRuby¤Î¼±Ê̻ҤȤ·
+¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤ÏRuby¥×¥í¥°¥é¥à¤«¤é
+¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
+
+ void rb_define_readonly_variable(char *name, VALUE *var)
+
+Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read
+only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
+
+ void rb_define_virtual_variable(char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ
+¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥
+
+ void rb_define_hooked_variable(char *name, VALUE *var,
+ VALUE (*getter)(), VALUE (*setter)())
+
+´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬
+»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter
+¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê
+¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
+
+ void rb_global_variable(VALUE *var)
+
+GC¤Î¤¿¤á¡¤Ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, Ruby¥ª¥Ö¥¸¥§
+¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
+
+** Äê¿ô
+
+ void rb_define_const(VALUE klass, char *name, VALUE val)
+
+Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
+
+ void rb_define_global_const(char *name, VALUE val)
+
+Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
+
+ rb_define_const(cKernal, name, val)
+
+¤ÈƱ¤¸°ÕÌ£¡¥
+
+** ¥á¥½¥Ã¥ÉÄêµÁ
+
+ rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
+´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú
+¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú
+¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àRuby¤ÎÇÛÎó)¤È¤¤¤¦·Á
+¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+
+ rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+
+ rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+Æðۥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+
+ rb_scan_args(int atgc, VALUE *argv, char *fmt, ...)
+
+argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
+Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú¿ô
+»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Äǽ¤Ç
+¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê¹ß¤ÏÊÑ
+¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥Éղðú
+¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì
+¤ë¡¥
+
+** Ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
+
+ VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
+
+¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò»È¤¦¡¥
+
+ VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
+
+¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥
+
+ VALUE rb_eval_string(char *str)
+
+ʸ»úÎó¤òRuby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+
+ ID rb_intern(char *name)
+
+ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
+
+ char *rb_id2name(ID id)
+
+ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
+
+ char *rb_class2name(VALUE class)
+
+class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
+ÁÄÀè¤òÁ̤äÆ̾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
+
+** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô
+
+ VALUE rb_iv_get(VALUE obj, char *name)
+
+obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹
+ÊÑ¿ô¤Ï Ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿
+¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥Äê¿ô¤ÏÂçʸ»ú¤Î̾Á°¤ò»ý¤Ä¥¯¥é¥¹(¤Þ¤¿¤Ï¥â¥¸¥å¡¼
+¥ë)¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤È¤·¤Æ¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¡¥
+
+ VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
+
+obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥
+
+** À©¸æ¹½Â¤
+
+ VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+
+func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥
+func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼
+¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥
+
+ VALUE rb_yield(VALUE val)
+
+val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
+
+ VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+
+´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸¤·
+¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸¤·¤Ê
+¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá¤êÃͤÇ
+¤¢¤ë¡¥
+
+ VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
+
+´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬È¯
+À¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1¤ÎÌá
+¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥
+
+** Îã³°¡¦¥¨¥é¡¼
+
+ void rb_warning(char *fmt, ...)
+
+rb_verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+
+ void rb_raise(rb_eRuntimeError, char *fmt, ...)
+
+RuntimeErrorÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+
+ void rb_raise(VALUE exception, char *fmt, ...)
+
+exception¤Ç»ØÄꤷ¤¿Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥fmt°Ê²¼¤Î°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+
+ void rb_fatal(char *fmt, ...)
+
+Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
+¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â
+¹Ô¤µ¤ì¤ë)¡¥
+
+ void rb_bug(char *fmt, ...)
+
+¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ
+¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°
+½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
+
+** Ruby¤Î½é´ü²½¡¦¼Â¹Ô
+
+Ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
+¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤ÏɬÍפʤ¤¡¥
+
+ void ruby_init(int argc, char **argv, char **envp)
+
+Ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
+
+ void ruby_run()
+
+Ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+
+ void ruby_script(char *name)
+
+Ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
+
+
+Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
+
+extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
+²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+
+ have_library(lib, func)
+
+´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é
+¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤true¤òÊÖ¤¹¡¥
+
+ have_func(func)
+
+´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é
+¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê
+¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þTRUE¤òÊÖ¤¹¡¥
+
+ have_header(header)
+
+¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë
+»þtrue¤òÊÖ¤¹¡¥
+
+ create_makefile(target)
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð
+¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾¤òɽ
+¤¹¡¥
+
+/*
+ * Local variables:
+ * fill-column: 60
+ * end:
+ */
diff --git a/README.jp b/README.jp
index 00822a3658..d137a435d8 100644
--- a/README.jp
+++ b/README.jp
@@ -5,7 +5,7 @@ Ruby¤ÏºÇ½é¤«¤é½ã¿è¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¸À¸ì¤È¤·¤ÆÀ߷פµ¤ì¤Æ¤¤¤Þ
¤¹¤«¤é¡¤¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥×¥í¥°¥é¥ß¥ó¥°¤ò¼ê·Ú¤Ë¹Ô¤¦»ö¤¬½ÐÍè¤Þ
¤¹¡¥¤â¤Á¤í¤óÄ̾ï¤Î¼ê³¤­·¿¤Î¥×¥í¥°¥é¥ß¥ó¥°¤â²Äǽ¤Ç¤¹¡¥
-Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
+Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤Perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
¤Ç¤¹¡¥¤µ¤é¤Ë¥·¥ó¥×¥ë¤Êʸˡ¤È¡¤Îã³°½èÍý¤ä¥¤¥Æ¥ì¡¼¥¿¤Ê¤É¤Îµ¡¹½
¤Ë¤è¤Ã¤Æ¡¤¤è¤êʬ¤«¤ê¤ä¤¹¤¤¥×¥í¥°¥é¥ß¥ó¥°¤¬½ÐÍè¤Þ¤¹¡¥
@@ -20,7 +20,8 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
+ ¥¤¥Æ¥ì¡¼¥¿¤È¥¯¥í¡¼¥¸¥ã
+ ¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿
+ ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥° (¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ë¤è¤ë)
- + °Ü¿¢À­¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤ÇÆ°¤¯
+ + °Ü¿¢À­¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤ÇÆ°¤¯¤À¤±¤Ç¤Ê¤¯¡¤DOS¤äWindows¡¤
+ Mac¡¤BeOS¤Ê¤É¤Î¾å¤Ç¤âÆ°¤¯
* Æþ¼êË¡
@@ -41,14 +42,14 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
¤Ç¤¹¡¥
-* ¥á¥¤¥ê¥ó¥°¥ê¥¹¥È
+* ¥á¡¼¥ê¥ó¥°¥ê¥¹¥È
- Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¥¤¥ê¥ó¥°¥ê¥¹¥È¤ò³«Àߤ·¤Þ¤·¤¿¡¥¥¢
+ Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤ò³«Àߤ·¤Þ¤·¤¿¡¥¥¢
¥É¥ì¥¹¤Ï
ruby-list@netlab.co.jp
- ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¥¤¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥
+ ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¡¼¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥
* ¥³¥ó¥Ñ¥¤¥ë¡¦¥¤¥ó¥¹¥È¡¼¥ë
@@ -81,6 +82,8 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
6. make install
+ root¤Çºî¶È¤¹¤ëɬÍפ¬¤¢¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡¥
+
¤â¤·¡¤¥³¥ó¥Ñ¥¤¥ë»þ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¤Ë¤Ï¥¨¥é¡¼¤Î¥í¥°¤È¥Þ
¥·¥ó¡¤OS¤Î¼ïÎà¤ò´Þ¤à¤Ç¤­¤ë¤À¤±¾Ü¤·¤¤¥ì¥Ý¡¼¥È¤òºî¼Ô¤ËÁ÷¤Ã¤Æ¤¯
¤À¤µ¤ë¤È¾¤ÎÊý¤Î¤¿¤á¤Ë¤â¤Ê¤ê¤Þ¤¹¡¥
@@ -92,7 +95,7 @@ UNIX¤Ç¤¢¤ì¤Ðconfigure¤¬¤Û¤È¤ó¤É¤Îº¹°Û¤òµÛ¼ý¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç
¤¹¤¬¡¤»×¤ï¤Ì¸«Íî¤È¤·¤¬¤¢¤Ã¤¿¾ì¹ç(¤¢¤ë¤Ë°ã¤¤¤Ê¤¤)¡¤ºî¼Ô¤Ë¤½¤Î
¤³¤È¤ò¥ì¥Ý¡¼¥È¤¹¤ì¤Ð¡¤²ò·è¤Ç¤­¤ë¤«¤âÃΤì¤Þ¤»¤ó¡¥
-¥¢¡¼¥¯¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥Ruby¤ÎGC¤ÏÂоÝ
+¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥Ruby¤ÎGC¤ÏÂоÝ
¤Î¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤¬setjmp()¤Ë¤è¤Ã¤ÆÁ´¤Æ¤Î¥ì¥¸¥¹¥¿¤ò jmp_buf¤Ë
³ÊǼ¤¹¤ë¤³¤È¤È¡¤jmp_buf¤È¥¹¥¿¥Ã¥¯¤¬32bit¥¢¥é¥¤¥ó¥á¥ó¥È¤µ¤ì¤Æ
¤¤¤ë¤³¤È¤ò²¾Äꤷ¤Æ¤¤¤Þ¤¹¡¥ÆäËÁ°¼Ô¤¬À®Î©¤·¤Ê¤¤¾ì¹ç¤ÎÂбþ¤ÏÈó
@@ -120,34 +123,37 @@ Licence)¤Þ¤¿¤Ï°Ê²¼¤Ë¼¨¤¹¾ò·ï¤ÇRuby¤òºÆÇÛÉۤǤ­¤Þ¤¹¡¥GPL¤Ë¤Ä
ͳ¤ËÊѹ¹¤Ç¤­¤Þ¤¹¡¥
(a) ¥Í¥Ã¥È¥Ë¥å¡¼¥º¤Ë¥Ý¥¹¥È¤·¤¿¤ê¡¤ºî¼Ô¤ËÊѹ¹¤òÁ÷ÉÕ¤¹¤ë
- ¤Ê¤É¤ÎÊýË¡¤Ç¡¤Êѹ¹¤ò¸ø³«¤¹¤ë
+ ¤Ê¤É¤ÎÊýË¡¤Ç¡¤Êѹ¹¤ò¸ø³«¤¹¤ë¡¥
- (b) Êѹ¹¤·¤¿Ruby¤ò¼«Ê¬¤Î½ê°¤¹¤ëÁÈ¿¥ÆâÉô¤À¤±¤Ç»È¤¦
+ (b) Êѹ¹¤·¤¿Ruby¤ò¼«Ê¬¤Î½ê°¤¹¤ëÁÈ¿¥ÆâÉô¤À¤±¤Ç»È¤¦¡¥
(c) Êѹ¹ÅÀ¤òÌÀ¼¨¤·¤¿¤¦¤¨¡¤¥½¥Õ¥È¥¦¥§¥¢¤Î̾Á°¤òÊѹ¹¤¹¤ë¡¥
- ¤½¤Î¥½¥Õ¥È¥¦¥§¥¢¤òÇÛÉÛ¤¹¤ë»þ¤Ë¤Ï¤â¤È¤ÎRuby¤âƱ»þ¤Ë
- ÇÛÉÛ¤¹¤ë
+ ¤½¤Î¥½¥Õ¥È¥¦¥§¥¢¤òÇÛÉÛ¤¹¤ë»þ¤Ë¤ÏÊѹ¹Á°¤ÎRuby¤âƱ»þ
+ ¤ËÇÛÉÛ¤¹¤ë¡¥¤Þ¤¿¤ÏÊѹ¹Á°¤ÎRuby¤Î¥½¡¼¥¹¤ÎÆþ¼êË¡¤òÌÀ
+ ¼¨¤¹¤ë¡¥
- (d) ¤½¤Î¾¤ÎÊѹ¹¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë
+ (d) ¤½¤Î¾¤ÎÊѹ¹¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë¡¥
3. °Ê²¼¤Î¾ò·ï¤Î¤¤¤º¤ì¤«¤òËþ¤¿¤¹»þ¤ËRuby¤ò¥ª¥Ö¥¸¥§¥¯¥È¥³¡¼
¥É¤ä¼Â¹Ô·Á¼°¤Ç¤âÇÛÉۤǤ­¤Þ¤¹¡¥
- (a) ¥Ð¥¤¥Ê¥ê¤ò¼õ¤±¼è¤Ã¤¿¿Í¤¬¥½¡¼¥¹¤òÆþ¼ê¤Ç¤­¤ë¤è¤¦¤Ë¥½¡¼
- ¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë
+ (a) ¥Ð¥¤¥Ê¥ê¤ò¼õ¤±¼è¤Ã¤¿¿Í¤¬¥½¡¼¥¹¤òÆþ¼ê¤Ç¤­¤ë¤è¤¦¤Ë¡¤
+ ¥½¡¼¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
- (b) µ¡³£²ÄÆɤʥ½¡¼¥¹¥³¡¼¥É¤òźÉÕ¤¹¤ë
+ (b) µ¡³£²ÄÆɤʥ½¡¼¥¹¥³¡¼¥É¤òźÉÕ¤¹¤ë¡¥
(c) Êѹ¹¤ò¹Ô¤Ã¤¿¥Ð¥¤¥Ê¥ê¤Ï̾Á°¤òÊѹ¹¤·¤¿¤¦¤¨¡¤¥½¡¼¥¹¤Î
- Æþ¼êË¡¤òÌÀ¼¨¤¹¤ë
+ Æþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
- (d) ¤½¤Î¾¤ÎÇÛÉÛ¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë
+ (d) ¤½¤Î¾¤ÎÇÛÉÛ¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë¡¥
4. ¾¤Î¥×¥í¥°¥é¥à¤Ø¤Î°úÍѤϤ¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿
¤À¤·¡¤Ruby¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½¤ì¤¾¤ì¤Î
ºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é¤ì¤Þ¤¹¡¥¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤
util.c(°ìÉô)¡¤st.[ch]¡¤regex.[ch], fnmatch.[ch], glob.c
¤ª¤è¤Ó./missing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö¤·¤Þ¤¹¡¥
+ ¤½¤ì¤¾¤ì¤ÎÇÛÉÛ¾ò·ï¤Ê¤É¤ËÉÕ¤¤¤Æ¤Ï³Æ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ¤¯
+ ¤À¤µ¤¤¡¥
5. Ruby¤Ø¤ÎÆþÎϤȤʤ륹¥¯¥ê¥×¥È¤ª¤è¤Ó¡¤Ruby¤«¤é¤Î½ÐÎϤθ¢
Íø¤ÏRuby¤Îºî¼Ô¤Ç¤Ï¤Ê¤¯¡¤¤½¤ì¤¾¤ì¤ÎÆþ½ÐÎϤòÀ¸À®¤·¤¿¿Í¤Ë
diff --git a/ToDo b/ToDo
index 3b6edee08f..3bc7887489 100644
--- a/ToDo
+++ b/ToDo
@@ -1,4 +1,37 @@
-* non-blocking open/write for thread
-* ¥Ñ¥Ã¥±¡¼¥¸¤Þ¤¿¤ÏÂç°èÊÑ¿ô¤Î¥¢¥¯¥»¥¹À©¸æ
-* formatµ¡Ç½
-* re-write regex code for speed and copyright
+Language Spec.
+
+* package or access control for global variables
+* named arguments like foo(nation:="german").
+* multiple return values, yield values. maybe imcompatible
+
+Hacking Interpreter
+
+* non-blocking open (e.g. named pipe) for thread
+* avoid blocking with gethostbyname/gethostbyaddr
+* objectify interpreters
+* remove rb_eval() recursions
+* syntax tree -> bytecode ???
+* scrambled script, or script filter
+* regular expression bug /(?:\s+\d+){2}/ URGENT!!
+
+Extension Libraries
+
+* mod_ruby, FastCGI ruby
+* InterBase module
+* ptk.rb pTk wrapper that is compatible to tk.rb
+
+Ruby Libraries
+
+* CGI.rb
+* httplib.rb, urllib.rb, nttplib.rb, etc.
+* format like perl's
+
+Tools
+
+* extension library maker like XS or SWIG
+* freeze or undump to bundle everything
+
+Misc
+
+* translate README.EXT fully into English
+* publish Ruby books
diff --git a/array.c b/array.c
index 388fb05bd7..8f6c0c223f 100644
--- a/array.c
+++ b/array.c
@@ -6,41 +6,55 @@
$Date$
created at: Fri Aug 6 09:46:12 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
+#include "util.h"
-
-VALUE cArray;
+VALUE rb_cArray;
#define ARY_DEFAULT_SIZE 16
void
-memclear(mem, size)
+rb_mem_clear(mem, size)
register VALUE *mem;
- register int size;
+ register size_t size;
{
while (size--) {
*mem++ = Qnil;
}
}
+static void
+memfill(mem, size, val)
+ register VALUE *mem;
+ register size_t size;
+ register VALUE val;
+{
+ while (size--) {
+ *mem++ = val;
+ }
+}
+
#define ARY_FREEZE FL_USER1
+#define ARY_TMPLOCK FL_USER2
static void
-ary_modify(ary)
+rb_ary_modify(ary)
VALUE ary;
{
- rb_secure(5);
- if (FL_TEST(ary, ARY_FREEZE)) {
- TypeError("can't modify frozen array");
- }
+ if (FL_TEST(ary, ARY_FREEZE))
+ rb_raise(rb_eTypeError, "can't modify frozen array");
+ if (FL_TEST(ary, ARY_TMPLOCK))
+ rb_raise(rb_eTypeError, "can't modify array during sort");
+ if (rb_safe_level() >= 4 && !FL_TEST(ary, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
VALUE
-ary_freeze(ary)
+rb_ary_freeze(ary)
VALUE ary;
{
FL_SET(ary, ARY_FREEZE);
@@ -48,56 +62,68 @@ ary_freeze(ary)
}
static VALUE
-ary_frozen_p(ary)
+rb_ary_frozen_p(ary)
VALUE ary;
{
- if (FL_TEST(ary, ARY_FREEZE))
- return TRUE;
- return FALSE;
+ if (FL_TEST(ary, ARY_FREEZE|ARY_TMPLOCK))
+ return Qtrue;
+ return Qfalse;
}
VALUE
-ary_new2(len)
- int len;
+rb_ary_new2(len)
+ size_t len;
{
NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, cArray, T_ARRAY);
+ OBJSETUP(ary, rb_cArray, T_ARRAY);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
+ }
+ if (len > 0 && len*sizeof(VALUE) <= 0) {
+ rb_raise(rb_eArgError, "array size too big");
+ }
ary->len = 0;
ary->capa = len;
- if (len == 0)
- ary->ptr = 0;
- else {
- ary->ptr = ALLOC_N(VALUE, len);
- memclear(ary->ptr, len);
- }
+ ary->ptr = 0;
+ ary->ptr = ALLOC_N(VALUE, len);
return (VALUE)ary;
}
VALUE
-ary_new()
+rb_ary_new()
{
- return ary_new2(ARY_DEFAULT_SIZE);
+ return rb_ary_new2(ARY_DEFAULT_SIZE);
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
VALUE
-ary_new3(n, va_alist)
- int n;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_ary_new3(size_t n, ...)
+#else
+rb_ary_new3(n, va_alist)
+ size_t n;
va_dcl
+#endif
{
va_list ar;
VALUE ary;
- int i;
+ size_t i;
if (n < 0) {
- IndexError("Negative number of items(%d)", n);
+ rb_raise(rb_eIndexError, "negative number of items(%d)", n);
}
- ary = ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
+ ary = rb_ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
- va_start(ar);
+ va_init_list(ar, n);
for (i=0; i<n; i++) {
RARRAY(ary)->ptr[i] = va_arg(ar, VALUE);
}
@@ -108,26 +134,28 @@ ary_new3(n, va_alist)
}
VALUE
-ary_new4(n, elts)
- int n;
+rb_ary_new4(n, elts)
+ size_t n;
VALUE *elts;
{
VALUE ary;
- ary = ary_new2(n);
- MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
+ ary = rb_ary_new2(n);
+ if (elts) {
+ MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
+ }
RARRAY(ary)->len = n;
return ary;
}
VALUE
-assoc_new(car, cdr)
+rb_assoc_new(car, cdr)
VALUE car, cdr;
{
VALUE ary;
- ary = ary_new2(2);
+ ary = rb_ary_new2(2);
RARRAY(ary)->ptr[0] = car;
RARRAY(ary)->ptr[1] = cdr;
RARRAY(ary)->len = 2;
@@ -136,32 +164,49 @@ assoc_new(car, cdr)
}
static VALUE
-ary_s_new(argc, argv, class)
+rb_ary_s_new(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
- VALUE size;
+ size_t len = 0;
+ VALUE size, val;
NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, class, T_ARRAY);
+ OBJSETUP(ary, klass, T_ARRAY);
- rb_scan_args(argc, argv, "01", &size);
ary->len = 0;
- ary->capa = NIL_P(size)?ARY_DEFAULT_SIZE:NUM2INT(size);
+ ary->ptr = 0;
+ if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
+ ary->capa = ARY_DEFAULT_SIZE;
+ }
+ else {
+ size_t capa = NUM2UINT(size);
+
+ if (capa < 0) {
+ rb_raise(rb_eArgError, "negative array size");
+ }
+ if (capa > 0 && capa*sizeof(VALUE) <= 0) {
+ rb_raise(rb_eArgError, "array size too big");
+ }
+ ary->capa = capa;
+ len = capa;
+ }
ary->ptr = ALLOC_N(VALUE, ary->capa);
- memclear(ary->ptr, ary->capa);
+ memfill(ary->ptr, len, val);
+ ary->len = len;
+ rb_obj_call_init((VALUE)ary);
return (VALUE)ary;
}
static VALUE
-ary_s_create(argc, argv, class)
+rb_ary_s_create(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, class, T_ARRAY);
+ OBJSETUP(ary, klass, T_ARRAY);
ary->len = argc;
ary->capa = argc;
@@ -177,14 +222,17 @@ ary_s_create(argc, argv, class)
}
void
-ary_store(ary, idx, val)
+rb_ary_store(ary, idx, val)
VALUE ary;
- int idx;
+ size_t idx;
VALUE val;
{
- ary_modify(ary);
+ rb_ary_modify(ary);
if (idx < 0) {
- IndexError("negative index for array");
+ idx = RARRAY(ary)->len + idx;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "negative index of array");
+ }
}
if (idx >= RARRAY(ary)->capa) {
@@ -192,7 +240,8 @@ ary_store(ary, idx, val)
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
if (idx > RARRAY(ary)->len) {
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, idx-RARRAY(ary)->len+1);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,
+ idx-RARRAY(ary)->len+1);
}
if (idx >= RARRAY(ary)->len) {
@@ -202,28 +251,28 @@ ary_store(ary, idx, val)
}
VALUE
-ary_push(ary, item)
+rb_ary_push(ary, item)
VALUE ary;
VALUE item;
{
- ary_store(ary, RARRAY(ary)->len, item);
+ rb_ary_store(ary, RARRAY(ary)->len, item);
return ary;
}
static VALUE
-ary_push_method(argc, argv, ary)
+rb_ary_push_method(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
while (argc--) {
- ary_store(ary, RARRAY(ary)->len, *argv++);
+ rb_ary_store(ary, RARRAY(ary)->len, *argv++);
}
return ary;
}
VALUE
-ary_pop(ary)
+rb_ary_pop(ary)
VALUE ary;
{
if (RARRAY(ary)->len == 0) return Qnil;
@@ -235,7 +284,7 @@ ary_pop(ary)
}
VALUE
-ary_shift(ary)
+rb_ary_shift(ary)
VALUE ary;
{
VALUE top;
@@ -256,10 +305,10 @@ ary_shift(ary)
}
VALUE
-ary_unshift(ary, item)
+rb_ary_unshift(ary, item)
VALUE ary, item;
{
- ary_modify(ary);
+ rb_ary_modify(ary);
if (RARRAY(ary)->len >= RARRAY(ary)->capa) {
RARRAY(ary)->capa+=ARY_DEFAULT_SIZE;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
@@ -269,13 +318,15 @@ ary_unshift(ary, item)
MEMMOVE(RARRAY(ary)->ptr+1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
RARRAY(ary)->len++;
- return RARRAY(ary)->ptr[0] = item;
+ RARRAY(ary)->ptr[0] = item;
+
+ return ary;
}
VALUE
-ary_entry(ary, offset)
+rb_ary_entry(ary, offset)
VALUE ary;
- int offset;
+ size_t offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
@@ -290,27 +341,27 @@ ary_entry(ary, offset)
}
static VALUE
-ary_subseq(ary, beg, len)
+rb_ary_subseq(ary, beg, len)
VALUE ary;
- int beg, len;
+ size_t beg, len;
{
VALUE ary2;
- if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
- }
- if (len < 0) {
- IndexError("negative length %d", RARRAY(ary)->len);
+ if (len <= 0) {
+ return rb_ary_new2(0);
}
- if (len == 0) {
- return ary_new2(0);
+ if (beg < 0) {
+ len += beg;
+ beg = 0;
}
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
+ if (len < 0) {
+ len = 0;
+ }
- ary2 = ary_new2(len);
+ ary2 = rb_ary_new2(len);
MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len);
RARRAY(ary2)->len = len;
@@ -320,80 +371,74 @@ ary_subseq(ary, beg, len)
static VALUE
beg_len(range, begp, lenp, len)
VALUE range;
- int *begp, *lenp;
- int len;
+ size_t *begp, *lenp;
+ size_t len;
{
- int beg, end;
+ size_t beg, end;
+ size_t b, e;
- if (!range_beg_end(range, &beg, &end)) return FALSE;
-
- if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- IndexError("end smaller than beg [%d..%d]", beg, end);
- }
+ if (!rb_range_beg_end(range, &beg, &end)) return Qfalse;
+ b = beg; e = end;
if (beg < 0) {
beg = len + beg;
- if (beg < 0) beg = 0;
}
+ if (end < 0) {
+ end = len + end;
+ }
+ if (beg > end) {
+ rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", b, e);
+ }
+
*begp = beg;
if (beg > len) {
*lenp = 0;
}
else {
- if (end < 0) {
- end = len + end;
- if (end < 0) end = -1;
- }
- if (beg > end) {
- *lenp = 0;
- }
- else {
- *lenp = end - beg +1;
- }
+ len = end - beg +1;
+ *lenp = len;
}
- return TRUE;
+ return Qtrue;
}
VALUE
-ary_aref(argc, argv, ary)
+rb_ary_aref(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE arg1, arg2;
- int beg, len;
+ size_t beg, len;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- beg = NUM2INT(arg1);
- len = NUM2INT(arg2);
- if (len <= 0) {
- return ary_new();
+ beg = NUM2UINT(arg1);
+ len = NUM2UINT(arg2);
+ if (beg < 0) {
+ beg = RARRAY(ary)->len + beg;
}
- return ary_subseq(ary, beg, len);
+ return rb_ary_subseq(ary, beg, len);
}
/* special case - speeding up */
if (FIXNUM_P(arg1)) {
- return ary_entry(ary, FIX2INT(arg1));
+ return rb_ary_entry(ary, FIX2UINT(arg1));
}
- else {
- /* check if idx is Range */
- if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
- return ary_subseq(ary, beg, len);
- }
+ else if (TYPE(arg1) == T_BIGNUM) {
+ rb_raise(rb_eIndexError, "index too big");
}
- if (TYPE(arg1) == T_BIGNUM) {
- IndexError("index too big");
+ else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
+ /* check if idx is Range */
+ return rb_ary_subseq(ary, beg, len);
}
- return ary_entry(ary, NUM2INT(arg1));
+ return rb_ary_entry(ary, NUM2UINT(arg1));
}
static VALUE
-ary_index(ary, val)
+rb_ary_index(ary, val)
VALUE ary;
VALUE val;
{
- int i;
+ size_t i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
@@ -403,59 +448,74 @@ ary_index(ary, val)
}
static VALUE
-ary_indexes(ary, args)
- VALUE ary, args;
+rb_ary_rindex(ary, val)
+ VALUE ary;
+ VALUE val;
{
- VALUE *p, *pend;
- VALUE new_ary;
- int i = 0;
+ size_t i = RARRAY(ary)->len;
- if (!args || NIL_P(args)) {
- return ary_new2(0);
+ while (i--) {
+ if (rb_equal(RARRAY(ary)->ptr[i], val))
+ return INT2FIX(i);
}
+ return Qnil;
+}
- new_ary = ary_new2(RARRAY(args)->len);
+static VALUE
+rb_ary_indexes(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ VALUE new_ary;
+ size_t i;
- p = RARRAY(args)->ptr; pend = p + RARRAY(args)->len;
- while (p < pend) {
- ary_store(new_ary, i++, ary_entry(ary, NUM2INT(*p)));
- p++;
+ new_ary = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_store(new_ary, i, rb_ary_entry(ary, NUM2UINT(argv[i])));
}
+
return new_ary;
}
static void
-ary_replace(ary, beg, len, rpl)
+rb_ary_replace(ary, beg, len, rpl)
VALUE ary, rpl;
- int beg, len;
+ size_t beg, len;
{
- ary_modify(ary);
+ if (len < 0) {
+ rb_raise(rb_eIndexError, "negative length %d", len);
+ }
+
if (TYPE(rpl) != T_ARRAY) {
rpl = rb_Array(rpl);
}
+
+ if (beg + len < 0 || (beg < 0 && beg <= -len)) {
+ rb_raise(rb_eIndexError, "index %d out of range", beg);
+ }
if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
+ len += beg;
+ beg = 0;
}
+
+ rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
len = beg + RARRAY(rpl)->len;
if (len >= RARRAY(ary)->capa) {
RARRAY(ary)->capa=len;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len);
MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, RARRAY(rpl)->len);
RARRAY(ary)->len = len;
}
else {
- int alen;
+ size_t alen;
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
- if (len < 0) {
- IndexError("negative length %d", RARRAY(ary)->len);
- }
alen = RARRAY(ary)->len + RARRAY(rpl)->len - len;
if (alen >= RARRAY(ary)->capa) {
@@ -473,48 +533,49 @@ ary_replace(ary, beg, len, rpl)
}
static VALUE
-ary_aset(argc, argv, ary)
+rb_ary_aset(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE arg1, arg2, arg3;
- int offset;
- int beg, len;
+ size_t offset;
+ size_t beg, len;
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- beg = NUM2INT(arg1);
- len = NUM2INT(arg2);
- ary_replace(ary, beg, len, arg3);
+ beg = NUM2UINT(arg1);
+ len = NUM2UINT(arg2);
+
+ if (beg < 0) {
+ beg = RARRAY(ary)->len + beg;
+ }
+ rb_ary_replace(ary, beg, len, arg3);
return arg3;
}
else if (FIXNUM_P(arg1)) {
- offset = FIX2INT(arg1);
+ offset = FIX2UINT(arg1);
goto fixnum;
}
else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
/* check if idx is Range */
- ary_replace(ary, beg, len, arg2);
+ rb_ary_replace(ary, beg, len, arg2);
return arg2;
}
if (TYPE(arg1) == T_BIGNUM) {
- IndexError("index too big");
+ rb_raise(rb_eIndexError, "index too big");
}
- offset = NUM2INT(arg1);
+ offset = NUM2UINT(arg1);
fixnum:
- if (offset < 0) {
- offset = RARRAY(ary)->len + offset;
- }
- ary_store(ary, offset, arg2);
+ rb_ary_store(ary, offset, arg2);
return arg2;
}
VALUE
-ary_each(ary)
+rb_ary_each(ary)
VALUE ary;
{
- int i;
+ size_t i;
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
@@ -523,10 +584,10 @@ ary_each(ary)
}
static VALUE
-ary_each_index(ary)
+rb_ary_each_index(ary)
VALUE ary;
{
- int i;
+ size_t i;
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(INT2FIX(i));
@@ -535,10 +596,10 @@ ary_each_index(ary)
}
static VALUE
-ary_reverse_each(ary)
+rb_ary_reverse_each(ary)
VALUE ary;
{
- int len = RARRAY(ary)->len;
+ size_t len = RARRAY(ary)->len;
while (len--) {
rb_yield(RARRAY(ary)->ptr[len]);
@@ -547,26 +608,26 @@ ary_reverse_each(ary)
}
static VALUE
-ary_length(ary)
+rb_ary_length(ary)
VALUE ary;
{
return INT2FIX(RARRAY(ary)->len);
}
static VALUE
-ary_empty_p(ary)
+rb_ary_empty_p(ary)
VALUE ary;
{
if (RARRAY(ary)->len == 0)
- return TRUE;
- return FALSE;
+ return Qtrue;
+ return Qfalse;
}
static VALUE
-ary_clone(ary)
+rb_ary_clone(ary)
VALUE ary;
{
- VALUE ary2 = ary_new2(RARRAY(ary)->len);
+ VALUE ary2 = rb_ary_new2(RARRAY(ary)->len);
CLONESETUP(ary2, ary);
MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
@@ -575,32 +636,56 @@ ary_clone(ary)
}
static VALUE
-ary_dup(ary)
+rb_ary_dup(ary)
VALUE ary;
{
- return ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
+ return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
}
-extern VALUE OFS;
+static VALUE
+to_ary(ary)
+ VALUE ary;
+{
+ return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
+}
-VALUE
-ary_join(ary, sep)
+extern VALUE rb_output_fs;
+
+static VALUE
+inspect_join(ary, arg)
VALUE ary;
- VALUE sep;
+ VALUE *arg;
{
- int i;
+ return rb_ary_join(arg[0], arg[1]);
+}
+
+VALUE
+rb_ary_join(ary, sep)
+ VALUE ary, sep;
+{
+ size_t i;
VALUE result, tmp;
- if (RARRAY(ary)->len == 0) return str_new(0, 0);
+ if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
- switch (TYPE(RARRAY(ary)->ptr[0])) {
+ tmp = RARRAY(ary)->ptr[0];
+ switch (TYPE(tmp)) {
case T_STRING:
- result = str_dup(RARRAY(ary)->ptr[0]);
+ result = rb_str_dup(tmp);
break;
case T_ARRAY:
- result = ary_join(RARRAY(ary)->ptr[0], sep);
+ if (rb_inspecting_p(tmp)) {
+ result = rb_str_new2("[...]");
+ }
+ else {
+ VALUE args[2];
+
+ args[0] = tmp;
+ args[1] = sep;
+ result = rb_protect_inspect(inspect_join, ary, (VALUE)args);
+ }
break;
default:
- result = obj_as_string(RARRAY(ary)->ptr[0]);
+ result = rb_obj_as_string(tmp);
break;
}
@@ -610,21 +695,30 @@ ary_join(ary, sep)
case T_STRING:
break;
case T_ARRAY:
- tmp = ary_join(tmp, sep);
+ if (rb_inspecting_p(tmp)) {
+ tmp = rb_str_new2("[...]");
+ }
+ else {
+ VALUE args[2];
+
+ args[0] = tmp;
+ args[1] = sep;
+ tmp = rb_protect_inspect(inspect_join, ary, (VALUE)args);
+ }
break;
default:
- tmp = obj_as_string(tmp);
+ tmp = rb_obj_as_string(tmp);
}
- if (!NIL_P(sep)) str_cat(result, RSTRING(sep)->ptr, RSTRING(sep)->len);
- str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
- if (str_tainted(tmp)) str_taint(result);
+ if (!NIL_P(sep)) rb_str_concat(result, sep);
+ rb_str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
+ if (OBJ_TAINTED(tmp)) OBJ_TAINT(result);
}
return result;
}
static VALUE
-ary_join_method(argc, argv, ary)
+rb_ary_join_method(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
@@ -632,57 +726,144 @@ ary_join_method(argc, argv, ary)
VALUE sep;
rb_scan_args(argc, argv, "01", &sep);
- if (NIL_P(sep)) sep = OFS;
- if (!NIL_P(sep)) Check_Type(sep, T_STRING);
-
- return ary_join(ary, sep);
+ if (NIL_P(sep)) sep = rb_output_fs;
+ return rb_ary_join(ary, sep);
}
VALUE
-ary_to_s(ary)
+rb_ary_to_s(ary)
VALUE ary;
{
- VALUE str = ary_join(ary, OFS);
- if (NIL_P(str)) return str_new(0, 0);
+ VALUE str;
+
+ if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
+ str = rb_ary_join(ary, rb_output_fs);
+ if (NIL_P(str)) return rb_str_new(0, 0);
return str;
}
+#ifdef USE_THREAD
+static ID inspect_key;
+#else
+static VALUE inspect_tbl;
+#endif
+
+struct inspect_arg {
+ VALUE (*func)();
+ VALUE arg1, arg2;
+};
+
+VALUE
+inspect_call(arg)
+ struct inspect_arg *arg;
+{
+ return (*arg->func)(arg->arg1, arg->arg2);
+}
+
static VALUE
-ary_inspect(ary)
+inspect_ensure(obj)
+ VALUE obj;
+{
+#ifdef USE_THREAD
+ VALUE inspect_tbl;
+
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+#endif
+ rb_ary_pop(inspect_tbl);
+ return 0;
+}
+
+VALUE
+rb_protect_inspect(func, obj, arg)
+ VALUE (*func)();
+ VALUE obj, arg;
+{
+ struct inspect_arg iarg;
+
+#ifdef USE_THREAD
+ VALUE inspect_tbl;
+
+ if (!inspect_key) {
+ inspect_key = rb_intern("__inspect_key__");
+ }
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+ if (NIL_P(inspect_tbl)) {
+ inspect_tbl = rb_ary_new();
+ rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
+ }
+#else
+ if (!inspect_tbl) {
+ inspect_tbl = rb_ary_new();
+ rb_global_variable(&inspect_tbl);
+ }
+#endif
+ rb_ary_push(inspect_tbl, obj);
+ iarg.func = func;
+ iarg.arg1 = obj;
+ iarg.arg2 = arg;
+ return rb_ensure(inspect_call, (VALUE)&iarg, inspect_ensure, obj);
+}
+
+VALUE
+rb_inspecting_p(obj)
+ VALUE obj;
+{
+#ifdef USE_THREAD
+ VALUE inspect_tbl;
+
+ if (!inspect_key) return Qfalse;
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+ if (NIL_P(inspect_tbl)) return Qfalse;
+#else
+ if (!inspect_tbl) return Qnil;
+#endif
+ return rb_ary_includes(inspect_tbl, obj);
+}
+
+static VALUE
+inspect_ary(ary)
VALUE ary;
{
- int i, len;
+ size_t i = 0;
VALUE s, str;
- if (RARRAY(ary)->len == 0) return str_new2("[]");
- str = str_new2("[");
- len = 1;
+ str = rb_str_new2("[");
for (i=0; i<RARRAY(ary)->len; i++) {
s = rb_inspect(RARRAY(ary)->ptr[i]);
- if (i > 0) str_cat(str, ", ", 2);
- str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len);
- len += RSTRING(s)->len + 2;
+ if (i > 0) rb_str_cat(str, ", ", 2);
+ rb_str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len);
}
- str_cat(str, "]", 1);
+ rb_str_cat(str, "]", 1);
return str;
}
static VALUE
-ary_to_a(ary)
+rb_ary_inspect(ary)
+ VALUE ary;
+{
+ if (RARRAY(ary)->len == 0) return rb_str_new2("[]");
+ if (rb_inspecting_p(ary)) return rb_str_new2("[...]");
+ return rb_protect_inspect(inspect_ary, ary, 0);
+}
+
+static VALUE
+rb_ary_to_a(ary)
VALUE ary;
{
return ary;
}
VALUE
-ary_reverse(ary)
+rb_ary_reverse(ary)
VALUE ary;
{
VALUE *p1, *p2;
VALUE tmp;
+ if (RARRAY(ary)->len == 0) return ary;
+
p1 = RARRAY(ary)->ptr;
p2 = p1 + RARRAY(ary)->len - 1; /* points last item */
@@ -697,10 +878,10 @@ ary_reverse(ary)
}
static VALUE
-ary_reverse_method(ary)
+rb_ary_reverse_method(ary)
VALUE ary;
{
- return ary_reverse(ary_clone(ary));
+ return rb_ary_reverse(rb_ary_dup(ary));
}
static ID cmp;
@@ -709,7 +890,7 @@ static int
sort_1(a, b)
VALUE *a, *b;
{
- VALUE retval = rb_yield(assoc_new(*a, *b));
+ VALUE retval = rb_yield(rb_assoc_new(*a, *b));
return NUM2INT(retval);
}
@@ -722,38 +903,59 @@ sort_2(a, b)
if (FIXNUM_P(*a)) {
if (FIXNUM_P(*b)) return *a - *b;
}
- else if (TYPE(*a) == T_STRING) {
- if (TYPE(*b) == T_STRING) return str_cmp(*a, *b);
+ else if (TYPE(*a) == T_STRING && TYPE(*b) == T_STRING) {
+ return rb_str_cmp(*a, *b);
}
retval = rb_funcall(*a, cmp, 1, *b);
return NUM2INT(retval);
}
+static VALUE
+sort_internal(ary)
+ VALUE ary;
+{
+ qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
+ rb_iterator_p()?sort_1:sort_2);
+ return ary;
+}
+
+static VALUE
+sort_unlock(ary)
+ VALUE ary;
+{
+ FL_UNSET(ary, ARY_TMPLOCK);
+ return ary;
+}
+
VALUE
-ary_sort_bang(ary)
+rb_ary_sort_bang(ary)
VALUE ary;
{
- ary_modify(ary);
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), iterator_p()?sort_1:sort_2);
+ if (RARRAY(ary)->len <= 1) return ary;
+
+ rb_ary_modify(ary);
+ FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */
+ rb_ensure(sort_internal, ary, sort_unlock, ary);
return ary;
}
VALUE
-ary_sort(ary)
+rb_ary_sort(ary)
VALUE ary;
{
- return ary_sort_bang(ary_clone(ary));
+ if (RARRAY(ary)->len == 0) return ary;
+ return rb_ary_sort_bang(rb_ary_dup(ary));
}
VALUE
-ary_delete(ary, item)
+rb_ary_delete(ary, item)
VALUE ary;
VALUE item;
{
- int i1, i2;
+ size_t i1, i2;
- ary_modify(ary);
+ rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue;
if (i1 != i2) {
@@ -762,7 +964,9 @@ ary_delete(ary, item)
i2++;
}
if (RARRAY(ary)->len == i2) {
- if (iterator_p()) rb_yield(item);
+ if (rb_iterator_p()) {
+ return rb_yield(item);
+ }
return Qnil;
}
else {
@@ -773,15 +977,15 @@ ary_delete(ary, item)
}
VALUE
-ary_delete_at(ary, at)
+rb_ary_delete_at(ary, at)
VALUE ary;
VALUE at;
{
- int i1, i2, pos;
+ size_t i1, i2, pos;
VALUE del = Qnil;
- ary_modify(ary);
- pos = NUM2INT(at);
+ rb_ary_modify(ary);
+ pos = NUM2UINT(at);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (i1 == pos) {
del = RARRAY(ary)->ptr[i1];
@@ -798,12 +1002,12 @@ ary_delete_at(ary, at)
}
static VALUE
-ary_delete_if(ary)
+rb_ary_delete_if(ary)
VALUE ary;
{
- int i1, i2;
+ size_t i1, i2;
- ary_modify(ary);
+ rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (rb_yield(RARRAY(ary)->ptr[i1])) continue;
if (i1 != i2) {
@@ -816,23 +1020,30 @@ ary_delete_if(ary)
return ary;
}
-#if 0
static VALUE
-ary_replace(ary)
+rb_ary_filter(ary)
VALUE ary;
{
- int i;
+ size_t i;
+ rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) {
RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
}
+ return ary;
+}
+static VALUE
+rb_ary_replace_method(ary, ary2)
+ VALUE ary, ary2;
+{
+ ary2 = to_ary(ary2);
+ rb_ary_replace(ary, 0, RARRAY(ary2)->len, ary2);
return ary;
}
-#endif
static VALUE
-ary_clear(ary)
+rb_ary_clear(ary)
VALUE ary;
{
RARRAY(ary)->len = 0;
@@ -844,32 +1055,28 @@ ary_clear(ary)
}
static VALUE
-ary_fill(argc, argv, ary)
+rb_ary_fill(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE item, arg1, arg2;
- int beg, len, end;
+ size_t beg, len, end;
VALUE *p, *pend;
- rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
- if (NIL_P(arg2) && beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
+ if (rb_scan_args(argc, argv, "12", &item, &arg1, &arg2) == 2 &&
+ beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
/* beg and len set already */
}
else {
- beg = NUM2INT(arg1);
+ beg = NIL_P(arg1)?0:NUM2UINT(arg1);
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
if (beg < 0) beg = 0;
}
- if (!NIL_P(arg2)) {
- len = NUM2INT(arg2);
- }
- else {
- len = RARRAY(ary)->len - beg;
- }
+ len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2UINT(arg2);
}
+ rb_ary_modify(ary);
end = beg + len;
if (end > RARRAY(ary)->len) {
if (end >= RARRAY(ary)->capa) {
@@ -877,7 +1084,7 @@ ary_fill(argc, argv, ary)
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
if (beg > RARRAY(ary)->len) {
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, end-RARRAY(ary)->len);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,end-RARRAY(ary)->len);
}
RARRAY(ary)->len = end;
}
@@ -890,16 +1097,16 @@ ary_fill(argc, argv, ary)
}
VALUE
-ary_plus(x, y)
+rb_ary_plus(x, y)
VALUE x, y;
{
VALUE z;
if (TYPE(y) != T_ARRAY) {
- return ary_plus(x, rb_Array(y));
+ return rb_ary_plus(x, rb_Array(y));
}
- z = ary_new2(RARRAY(x)->len + RARRAY(y)->len);
+ z = rb_ary_new2(RARRAY(x)->len + RARRAY(y)->len);
MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len);
MEMCPY(RARRAY(z)->ptr+RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len);
RARRAY(z)->len = RARRAY(x)->len + RARRAY(y)->len;
@@ -907,43 +1114,44 @@ ary_plus(x, y)
}
VALUE
-ary_concat(x, y)
+rb_ary_concat(x, y)
VALUE x, y;
{
VALUE *p, *pend;
if (TYPE(y) != T_ARRAY) {
- return ary_concat(x, rb_Array(y));
+ return rb_ary_concat(x, rb_Array(y));
}
p = RARRAY(y)->ptr;
pend = p + RARRAY(y)->len;
while (p < pend) {
- ary_store(x, RARRAY(x)->len, *p);
+ rb_ary_store(x, RARRAY(x)->len, *p);
p++;
}
return x;
}
static VALUE
-ary_times(ary, times)
+rb_ary_times(ary, times)
VALUE ary;
VALUE times;
{
VALUE ary2;
- int i, len;
+ size_t i, len;
if (TYPE(times) == T_STRING) {
- return ary_join(ary, times);
+ return rb_ary_join(ary, times);
}
- len = NUM2INT(times) * RARRAY(ary)->len;
- ary2 = ary_new2(len);
- RARRAY(ary2)->len = len;
-
+ len = NUM2UINT(times);
if (len < 0) {
- ArgError("negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
+ len *= RARRAY(ary)->len;
+
+ ary2 = rb_ary_new2(len);
+ RARRAY(ary2)->len = len;
for (i=0; i<len; i+=RARRAY(ary)->len) {
MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
@@ -953,7 +1161,7 @@ ary_times(ary, times)
}
VALUE
-ary_assoc(ary, key)
+rb_ary_assoc(ary, key)
VALUE ary;
VALUE key;
{
@@ -971,7 +1179,7 @@ ary_assoc(ary, key)
}
VALUE
-ary_rassoc(ary, value)
+rb_ary_rassoc(ary, value)
VALUE ary;
VALUE value;
{
@@ -989,135 +1197,203 @@ ary_rassoc(ary, value)
}
static VALUE
-ary_equal(ary1, ary2)
+rb_ary_equal(ary1, ary2)
VALUE ary1, ary2;
{
- int i;
+ size_t i;
- if (TYPE(ary2) != T_ARRAY) return FALSE;
- if (RARRAY(ary1)->len != RARRAY(ary2)->len) return FALSE;
+ if (TYPE(ary2) != T_ARRAY) return Qfalse;
+ if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
- return FALSE;
+ return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-ary_eql(ary1, ary2)
+rb_ary_eql(ary1, ary2)
VALUE ary1, ary2;
{
- int i;
+ size_t i;
- if (TYPE(ary2) != T_ARRAY) return FALSE;
+ if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len)
- return FALSE;
+ return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
if (!rb_eql(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
- return FALSE;
+ return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-ary_hash(ary)
+rb_ary_hash(ary)
VALUE ary;
{
- int h, i;
+ size_t i;
+ int h;
h = RARRAY(ary)->len;
for (i=0; i<RARRAY(ary)->len; i++) {
- h ^= rb_hash(RARRAY(ary)->ptr[i]);
+ int n = rb_hash(RARRAY(ary)->ptr[i]);
+ h ^= NUM2LONG(n);
}
return INT2FIX(h);
}
VALUE
-ary_includes(ary, item)
+rb_ary_includes(ary, item)
VALUE ary;
VALUE item;
{
- int i;
+ size_t i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], item)) {
- return TRUE;
+ return Qtrue;
+ }
+ }
+ return Qfalse;
+}
+
+static VALUE
+rb_ary_cmp(ary, ary2)
+ VALUE ary;
+ VALUE ary2;
+{
+ size_t i, len;
+
+ ary2 = to_ary(ary2);
+ len = RARRAY(ary)->len;
+ if (len > RARRAY(ary2)->len) {
+ len = RARRAY(ary2)->len;
+ }
+ for (i=0; i<len; i++) {
+ VALUE v = rb_funcall(RARRAY(ary)->ptr[i],cmp,1,RARRAY(ary2)->ptr[i]);
+ if (v != INT2FIX(0)) {
+ return v;
}
}
- return FALSE;
+ len = RARRAY(ary)->len - RARRAY(ary2)->len;
+ if (len == 0) return INT2FIX(0);
+ if (len > 0) return INT2FIX(1);
+ return INT2FIX(-1);
}
static VALUE
-ary_diff(ary1, ary2)
+rb_ary_diff(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- int i;
+ size_t i;
- Check_Type(ary2, T_ARRAY);
- ary3 = ary_new();
+ ary2 = to_ary(ary2);
+ ary3 = rb_ary_new();
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (ary_includes(ary2, RARRAY(ary1)->ptr[i])) continue;
- if (ary_includes(ary3, RARRAY(ary1)->ptr[i])) continue;
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ if (rb_ary_includes(ary2, RARRAY(ary1)->ptr[i])) continue;
+ if (rb_ary_includes(ary3, RARRAY(ary1)->ptr[i])) continue;
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
}
return ary3;
}
static VALUE
-ary_and(ary1, ary2)
+rb_ary_and(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- int i;
+ size_t i;
- Check_Type(ary2, T_ARRAY);
- ary3 = ary_new();
+ ary2 = to_ary(ary2);
+ ary3 = rb_ary_new();
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (ary_includes(ary2, RARRAY(ary1)->ptr[i])
- && !ary_includes(ary3, RARRAY(ary1)->ptr[i])) {
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ if (rb_ary_includes(ary2, RARRAY(ary1)->ptr[i])
+ && !rb_ary_includes(ary3, RARRAY(ary1)->ptr[i])) {
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
}
}
return ary3;
}
static VALUE
-ary_or(ary1, ary2)
+rb_ary_or(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- int i;
+ size_t i;
if (TYPE(ary2) != T_ARRAY) {
- if (ary_includes(ary1, ary2)) return ary1;
- else return ary_plus(ary1, ary2);
+ if (rb_ary_includes(ary1, ary2)) return ary1;
+ else return rb_ary_plus(ary1, ary2);
}
- ary3 = ary_new();
+ ary3 = rb_ary_new();
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!ary_includes(ary3, RARRAY(ary1)->ptr[i]))
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ if (!rb_ary_includes(ary3, RARRAY(ary1)->ptr[i]))
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
}
for (i=0; i<RARRAY(ary2)->len; i++) {
- if (!ary_includes(ary3, RARRAY(ary2)->ptr[i]))
- ary_push(ary3, RARRAY(ary2)->ptr[i]);
+ if (!rb_ary_includes(ary3, RARRAY(ary2)->ptr[i]))
+ rb_ary_push(ary3, RARRAY(ary2)->ptr[i]);
}
return ary3;
}
static VALUE
-ary_compact_bang(ary)
+rb_ary_uniq_bang(ary)
+ VALUE ary;
+{
+ VALUE *p, *q, *t, *end;
+ VALUE v;
+
+ rb_ary_modify(ary);
+ p = RARRAY(ary)->ptr;
+ end = p + RARRAY(ary)->len;
+
+ while (p < end) {
+ v = *p++;
+ q = t = p;
+ while (q < end) {
+ if (rb_equal(*q, v)) q++;
+ else *t++ = *q++;
+ }
+ end = t;
+ }
+ if (RARRAY(ary)->len == (end - RARRAY(ary)->ptr)) {
+ return Qnil;
+ }
+
+ RARRAY(ary)->len = (end - RARRAY(ary)->ptr);
+
+ return ary;
+}
+
+static VALUE
+rb_ary_uniq(ary)
+ VALUE ary;
+{
+ VALUE v = rb_ary_uniq_bang(rb_ary_dup(ary));
+
+ if (NIL_P(v)) return ary;
+ return v;
+}
+
+static VALUE
+rb_ary_compact_bang(ary)
VALUE ary;
{
VALUE *p, *t, *end;
- ary_modify(ary);
+ rb_ary_modify(ary);
p = t = RARRAY(ary)->ptr;
end = p + RARRAY(ary)->len;
while (t < end) {
if (NIL_P(*t)) t++;
else *p++ = *t++;
}
+ if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) {
+ return Qnil;
+ }
RARRAY(ary)->len = RARRAY(ary)->capa = (p - RARRAY(ary)->ptr);
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
@@ -1125,17 +1401,20 @@ ary_compact_bang(ary)
}
static VALUE
-ary_compact(ary)
+rb_ary_compact(ary)
VALUE ary;
{
- return ary_compact_bang(ary_clone(ary));
+ VALUE v = rb_ary_compact_bang(rb_ary_dup(ary));
+
+ if (NIL_P(v)) return ary;
+ return v;
}
static VALUE
-ary_nitems(ary)
+rb_ary_nitems(ary)
VALUE ary;
{
- int n = 0;
+ size_t n = 0;
VALUE *p, *pend;
p = RARRAY(ary)->ptr;
@@ -1147,74 +1426,108 @@ ary_nitems(ary)
return INT2FIX(n);
}
-extern VALUE mEnumerable;
-
-void
-Init_Array()
+static VALUE
+rb_ary_flatten_bang(ary)
+ VALUE ary;
{
- cArray = rb_define_class("Array", cObject);
- rb_include_module(cArray, mEnumerable);
-
- rb_define_singleton_method(cArray, "new", ary_s_new, -1);
- rb_define_singleton_method(cArray, "[]", ary_s_create, -1);
- rb_define_method(cArray, "to_s", ary_to_s, 0);
- rb_define_method(cArray, "inspect", ary_inspect, 0);
- rb_define_method(cArray, "to_a", ary_to_a, 0);
-
- rb_define_method(cArray, "freeze", ary_freeze, 0);
- rb_define_method(cArray, "frozen?", ary_frozen_p, 0);
-
- rb_define_method(cArray, "==", ary_equal, 1);
- rb_define_method(cArray, "eql?", ary_eql, 1);
- rb_define_method(cArray, "hash", ary_hash, 0);
-
- rb_define_method(cArray, "[]", ary_aref, -1);
- rb_define_method(cArray, "[]=", ary_aset, -1);
- rb_define_method(cArray, "concat", ary_concat, 1);
- rb_define_method(cArray, "<<", ary_push, 1);
- rb_define_method(cArray, "push", ary_push_method, -1);
- rb_define_method(cArray, "pop", ary_pop, 0);
- rb_define_method(cArray, "shift", ary_shift, 0);
- rb_define_method(cArray, "unshift", ary_unshift, 1);
- rb_define_method(cArray, "each", ary_each, 0);
- rb_define_method(cArray, "each_index", ary_each_index, 0);
- rb_define_method(cArray, "reverse_each", ary_reverse_each, 0);
- rb_define_method(cArray, "length", ary_length, 0);
- rb_define_alias(cArray, "size", "length");
- rb_define_method(cArray, "empty?", ary_empty_p, 0);
- rb_define_method(cArray, "index", ary_index, 1);
- rb_define_method(cArray, "indexes", ary_indexes, -2);
- rb_define_method(cArray, "clone", ary_clone, 0);
- rb_define_method(cArray, "dup", ary_dup, 0);
- rb_define_method(cArray, "join", ary_join_method, -1);
- rb_define_method(cArray, "reverse", ary_reverse_method, 0);
- rb_define_method(cArray, "reverse!", ary_reverse, 0);
- rb_define_method(cArray, "sort", ary_sort, 0);
- rb_define_method(cArray, "sort!", ary_sort_bang, 0);
- rb_define_method(cArray, "delete", ary_delete, 1);
- rb_define_method(cArray, "delete_at", ary_delete_at, 1);
- rb_define_method(cArray, "delete_if", ary_delete_if, 0);
-#if 0
- rb_define_method(cArray, "replace", ary_replace, 0);
-#endif
- rb_define_method(cArray, "clear", ary_clear, 0);
- rb_define_method(cArray, "fill", ary_fill, -1);
- rb_define_method(cArray, "include?", ary_includes, 1);
- rb_define_method(cArray, "===", ary_includes, 1);
+ size_t i;
+ int mod = 0;
- rb_define_method(cArray, "assoc", ary_assoc, 1);
- rb_define_method(cArray, "rassoc", ary_rassoc, 1);
+ rb_ary_modify(ary);
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ VALUE ary2 = RARRAY(ary)->ptr[i];
+ if (TYPE(ary2) == T_ARRAY) {
+ rb_ary_replace(ary, i--, 1, ary2);
+ mod = 1;
+ }
+ }
+ if (mod == 0) return Qnil;
+ return ary;
+}
- rb_define_method(cArray, "+", ary_plus, 1);
- rb_define_method(cArray, "*", ary_times, 1);
+static VALUE
+rb_ary_flatten(ary)
+ VALUE ary;
+{
+ VALUE v = rb_ary_flatten_bang(rb_ary_dup(ary));
- rb_define_method(cArray, "-", ary_diff, 1);
- rb_define_method(cArray, "&", ary_and, 1);
- rb_define_method(cArray, "|", ary_or, 1);
+ if (NIL_P(v)) return ary;
+ return v;
+}
- rb_define_method(cArray, "compact", ary_compact, 0);
- rb_define_method(cArray, "compact!", ary_compact_bang, 0);
- rb_define_method(cArray, "nitems", ary_nitems, 0);
+void
+Init_Array()
+{
+ rb_cArray = rb_define_class("Array", rb_cObject);
+ rb_include_module(rb_cArray, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
+ rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
+ rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);
+ rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
+ rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
+ rb_define_method(rb_cArray, "to_ary", rb_ary_to_a, 0);
+
+ rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
+ rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
+
+ rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
+ rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
+ rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
+ rb_define_method(rb_cArray, "===", rb_ary_equal, 1);
+
+ rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
+ rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
+ rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
+ rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
+ rb_define_method(rb_cArray, "push", rb_ary_push_method, -1);
+ rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
+ rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
+ rb_define_method(rb_cArray, "unshift", rb_ary_unshift, 1);
+ rb_define_method(rb_cArray, "each", rb_ary_each, 0);
+ rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
+ rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
+ rb_define_method(rb_cArray, "length", rb_ary_length, 0);
+ rb_define_alias(rb_cArray, "size", "length");
+ rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
+ rb_define_method(rb_cArray, "index", rb_ary_index, 1);
+ rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1);
+ rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
+ rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1);
+ rb_define_method(rb_cArray, "clone", rb_ary_clone, 0);
+ rb_define_method(rb_cArray, "dup", rb_ary_dup, 0);
+ rb_define_method(rb_cArray, "join", rb_ary_join_method, -1);
+ rb_define_method(rb_cArray, "reverse", rb_ary_reverse_method, 0);
+ rb_define_method(rb_cArray, "reverse!", rb_ary_reverse, 0);
+ rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
+ rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
+ rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
+ rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at, 1);
+ rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
+ rb_define_method(rb_cArray, "filter", rb_ary_filter, 0);
+ rb_define_method(rb_cArray, "replace", rb_ary_replace_method, 1);
+ rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
+ rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
+ rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
+ rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
+
+ rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
+ rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
+
+ rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
+ rb_define_method(rb_cArray, "*", rb_ary_times, 1);
+
+ rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
+ rb_define_method(rb_cArray, "&", rb_ary_and, 1);
+ rb_define_method(rb_cArray, "|", rb_ary_or, 1);
+
+ rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
+ rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
+ rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
+ rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
+ rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
+ rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
+ rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
cmp = rb_intern("<=>");
}
diff --git a/bignum.c b/bignum.c
index 17d9c839c5..770e86ad80 100644
--- a/bignum.c
+++ b/bignum.c
@@ -9,28 +9,28 @@
************************************************/
#include "ruby.h"
-#include <ctype.h>
#include <math.h>
+#include <ctype.h>
-extern VALUE cInteger;
-VALUE cBignum;
+VALUE rb_cBignum;
+typedef unsigned short USHORT;
#define BDIGITS(x) RBIGNUM(x)->digits
-#define BITSPERDIG (sizeof(USHORT)*CHAR_BIT)
+#define BITSPERDIG (sizeof(short)*CHAR_BIT)
#define BIGRAD (1L << BITSPERDIG)
-#define DIGSPERINT ((UINT)(sizeof(INT)/sizeof(USHORT)))
-#define BIGUP(x) ((UINT)(x) << BITSPERDIG)
-#define BIGDN(x) ((x) >> BITSPERDIG)
-#define BIGLO(x) ((x) & (BIGRAD-1))
+#define DIGSPERINT ((unsigned int)(sizeof(long)/sizeof(short)))
+#define BIGUP(x) ((unsigned long)(x) << BITSPERDIG)
+#define BIGDN(x) (((x)<0) ? ~((~(x))>>BITSPERDIG) : (x)>>BITSPERDIG)
+#define BIGLO(x) ((USHORT)((x) & (BIGRAD-1)))
static VALUE
-bignew_1(class, len, sign)
- VALUE class;
- UINT len;
+bignew_1(klass, len, sign)
+ VALUE klass;
+ size_t len;
char sign;
{
NEWOBJ(big, struct RBignum);
- OBJSETUP(big, cBignum, T_BIGNUM);
+ OBJSETUP(big, klass, T_BIGNUM);
big->sign = sign;
big->len = len;
BDIGITS(big) = ALLOC_N(USHORT, len);
@@ -38,10 +38,10 @@ bignew_1(class, len, sign)
return (VALUE)big;
}
-#define bignew(len,sign) bignew_1(cBignum,len,sign)
+#define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
VALUE
-big_clone(x)
+rb_big_clone(x)
VALUE x;
{
VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
@@ -51,22 +51,22 @@ big_clone(x)
}
void
-big_2comp(x) /* get 2's complement */
+rb_big_2comp(x) /* get 2's complement */
VALUE x;
{
- UINT i = RBIGNUM(x)->len;
+ int i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
long num;
while (i--) ds[i] = ~ds[i];
i = 0; num = 1;
do {
- num += (long)ds[i];
+ num += ds[i];
ds[i++] = BIGLO(num);
num = BIGDN(num);
} while (i < RBIGNUM(x)->len);
if (ds[0] == 1 || ds[0] == 0) {
- for (i=1;i<RBIGNUM(x)->len;i++) {
+ for (i=1; i<RBIGNUM(x)->len; i++) {
if (ds[i] != 0) return;
}
REALLOC_N(BDIGITS(x), USHORT, RBIGNUM(x)->len++);
@@ -79,39 +79,39 @@ static VALUE
bignorm(x)
VALUE x;
{
- UINT len = RBIGNUM(x)->len;
+ size_t len = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
while (len-- && !ds[len]) ;
RBIGNUM(x)->len = ++len;
- if (len*sizeof(USHORT) < sizeof(VALUE) ||
- (len*sizeof(USHORT) == sizeof(VALUE) &&
- ds[sizeof(VALUE)/sizeof(USHORT)-1] <= 0x3fff)) {
+ if (len*sizeof(USHORT) <= sizeof(VALUE)) {
long num = 0;
while (len--) {
num = BIGUP(num) + ds[len];
}
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return INT2FIX(num);
+ if (num >= 0) {
+ if (RBIGNUM(x)->sign) {
+ if (POSFIXABLE(num)) return INT2FIX(num);
+ }
+ else if (NEGFIXABLE(-(long)num)) return INT2FIX(-(long)num);
}
- else if (NEGFIXABLE(-num)) return INT2FIX(-num);
}
return x;
}
VALUE
-big_norm(x)
+rb_big_norm(x)
VALUE x;
{
- return bignorm(RBIGNUM(x));
+ return bignorm(x);
}
VALUE
-uint2big(n)
- UINT n;
+rb_uint2big(n)
+ unsigned long n;
{
- UINT i = 0;
+ unsigned int i = 0;
USHORT *digits;
VALUE big;
@@ -130,17 +130,17 @@ uint2big(n)
}
VALUE
-int2big(n)
- INT n;
+rb_int2big(n)
+ long n;
{
- INT neg = 0;
+ long neg = 0;
VALUE big;
if (n < 0) {
n = -n;
neg = 1;
}
- big = uint2big(n);
+ big = rb_uint2big(n);
if (neg) {
RBIGNUM(big)->sign = 0;
}
@@ -148,34 +148,39 @@ int2big(n)
}
VALUE
-uint2inum(n)
- UINT n;
+rb_uint2inum(n)
+ unsigned long n;
{
if (POSFIXABLE(n)) return INT2FIX(n);
- return uint2big(n);
+ return rb_uint2big(n);
}
VALUE
-int2inum(n)
- INT n;
+rb_int2inum(n)
+ long n;
{
if (FIXABLE(n)) return INT2FIX(n);
- return int2big(n);
+ return rb_int2big(n);
}
VALUE
-str2inum(str, base)
- UCHAR *str;
+rb_str2inum(str, base)
+ char *str;
int base;
{
char sign = 1, c;
unsigned long num;
- UINT len, blen = 1, i;
+ size_t len, blen = 1;
+ int i;
VALUE z;
USHORT *zds;
- while (isspace(*str)) str++;
- if (*str == '-') {
+ while (ISSPACE(*str)) str++;
+
+ if (*str == '+') {
+ str++;
+ }
+ else if (*str == '-') {
str++;
sign = 0;
}
@@ -195,26 +200,30 @@ str2inum(str, base)
base = 10;
}
}
- len = strlen(str);
if (base == 8) {
- len = 3*len*sizeof(char);
+ while (str[0] == '0') str++;
+ len = 3*strlen(str)*sizeof(char);
}
else { /* base == 10 or 16 */
- len = 4*len*sizeof(char);
+ if (base == 16 && str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
+ str += 2;
+ }
+ while (str[0] == '0') str++;
+ len = 4*strlen(str)*sizeof(char);
}
if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- UINT val = strtoul((char*)str, 0, base);
+ unsigned int val = strtoul((char*)str, 0, base);
if (POSFIXABLE(val)) {
if (sign) return INT2FIX(val);
else {
- INT result = -(INT)val;
+ long result = -(long)val;
return INT2FIX(result);
}
}
else {
- VALUE big = uint2big(val);
+ VALUE big = rb_uint2big(val);
RBIGNUM(big)->sign = sign;
return big;
}
@@ -263,21 +272,21 @@ str2inum(str, base)
static char hexmap[] = "0123456789abcdef";
VALUE
-big2str(x, base)
+rb_big2str(x, base)
VALUE x;
int base;
{
VALUE t;
USHORT *ds;
- UINT i, j, hbase;
+ unsigned int i, j, hbase;
VALUE ss;
- UCHAR *s, c;
+ char *s, c;
if (FIXNUM_P(x)) {
- return fix2str(x, base);
+ return rb_fix2str(x, base);
}
i = RBIGNUM(x)->len;
- if (i == 0) return str_new2("0");
+ if (i == 0) return rb_str_new2("0");
if (base == 10) {
j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i*241L)/800+2;
hbase = 10000;
@@ -297,12 +306,12 @@ big2str(x, base)
else {
j = 0;
hbase = 0;
- Fail("bignum cannot treat base %d", base);
+ rb_raise(rb_eArgError, "bignum cannot treat base %d", base);
}
- t = big_clone(x);
+ t = rb_big_clone(x);
ds = BDIGITS(t);
- ss = str_new(0, j);
+ ss = rb_str_new(0, j);
s = RSTRING(ss)->ptr;
s[0] = RBIGNUM(x)->sign ? '+' : '-';
@@ -311,13 +320,13 @@ big2str(x, base)
unsigned long num = 0;
while (k--) {
num = BIGUP(num) + ds[k];
- ds[k] = num / hbase;
+ ds[k] = (USHORT)(num / hbase);
num %= hbase;
}
if (ds[i-1] == 0) i--;
k = 4;
while (k--) {
- c = num % base;
+ c = (char)(num % base);
s[--j] = hexmap[(int)c];
num /= base;
if (i == 0 && num == 0) break;
@@ -332,44 +341,56 @@ big2str(x, base)
}
static VALUE
-big_to_s(x)
+rb_big_to_s(x)
VALUE x;
{
- return big2str(x, 10);
+ return rb_big2str(x, 10);
}
-INT
-big2int(x)
+unsigned long
+rb_big2ulong(x)
VALUE x;
{
- UINT num;
- UINT len = RBIGNUM(x)->len;
+ unsigned long num;
+ size_t len = RBIGNUM(x)->len;
USHORT *ds;
if (len > sizeof(long)/sizeof(USHORT))
- ArgError("Bignum too big to convert into fixnum");
+ rb_raise(rb_eArgError, "bignum too big to convert into `uint'");
ds = BDIGITS(x);
num = 0;
while (len--) {
num = BIGUP(num);
num += ds[len];
}
- if (!RBIGNUM(x)->sign) return -num;
return num;
}
-VALUE
-big_to_i(x)
+long
+rb_big2long(x)
+ VALUE x;
+{
+ unsigned long num = rb_big2ulong(x);
+
+ if ((long)num < 0) {
+ rb_raise(rb_eArgError, "bignum too big to convert into `int'");
+ }
+ if (!RBIGNUM(x)->sign) return -(long)num;
+ return num;
+}
+
+static VALUE
+rb_big_to_i(x)
VALUE x;
{
return bignorm(x);
}
VALUE
-dbl2big(d)
+rb_dbl2big(d)
double d;
{
- UINT i = 0;
+ unsigned int i = 0;
long c;
USHORT *digits;
VALUE z;
@@ -385,18 +406,18 @@ dbl2big(d)
u *= BIGRAD;
c = (long)u;
u -= c;
- digits[i] = c;
+ digits[i] = (USHORT)c;
}
return bignorm(z);
}
double
-big2dbl(x)
+rb_big2dbl(x)
VALUE x;
{
double d = 0.0;
- UINT i = RBIGNUM(x)->len;
+ size_t i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
while (i--) {
@@ -406,29 +427,29 @@ big2dbl(x)
return d;
}
-VALUE
-big_to_f(x)
+static VALUE
+rb_big_to_f(x)
VALUE x;
{
- return float_new(big2dbl(x));
+ return rb_float_new(rb_big2dbl(x));
}
static VALUE
-big_cmp(x, y)
+rb_big_cmp(x, y)
VALUE x, y;
{
- int xlen = RBIGNUM(x)->len;
+ size_t xlen = RBIGNUM(x)->len;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1);
@@ -446,18 +467,18 @@ big_cmp(x, y)
}
static VALUE
-big_eq(x, y)
+rb_big_eq(x, y)
VALUE x, y;
{
- if (big_cmp(x, y) == INT2FIX(0)) return TRUE;
- return FALSE;
+ if (rb_big_cmp(x, y) == INT2FIX(0)) return Qtrue;
+ return Qfalse;
}
static VALUE
-big_uminus(x)
+rb_big_uminus(x)
VALUE x;
{
- VALUE z = big_clone(x);
+ VALUE z = rb_big_clone(x);
RBIGNUM(z)->sign = !RBIGNUM(x)->sign;
@@ -465,16 +486,16 @@ big_uminus(x)
}
static VALUE
-big_neg(x)
+rb_big_neg(x)
VALUE x;
{
- VALUE z = big_clone(x);
- UINT i = RBIGNUM(x)->len;
+ VALUE z = rb_big_clone(x);
+ size_t i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(z);
- if (!RBIGNUM(x)->sign) big_2comp(z);
+ if (!RBIGNUM(x)->sign) rb_big_2comp(z);
while (i--) ds[i] = ~ds[i];
- if (RBIGNUM(x)->sign) big_2comp(z);
+ if (RBIGNUM(x)->sign) rb_big_2comp(z);
RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
return bignorm(z);
@@ -487,7 +508,7 @@ bigsub(x, y)
VALUE z = 0;
USHORT *zds;
long num;
- UINT i;
+ size_t i;
i = RBIGNUM(x)->len;
/* if x is larger than y, swap */
@@ -535,10 +556,11 @@ bigadd(x, y, sign)
{
VALUE z;
long num;
- UINT i, len;
+ size_t i, len;
- if (RBIGNUM(x)->sign == (RBIGNUM(y)->sign ^ sign)) {
- if (RBIGNUM(y)->sign == sign) return bigsub(y, x);
+ sign = (sign == RBIGNUM(y)->sign);
+ if (RBIGNUM(x)->sign != sign) {
+ if (sign) return bigsub(y, x);
return bigsub(x, y);
}
@@ -549,11 +571,11 @@ bigadd(x, y, sign)
else {
len = RBIGNUM(y)->len + 1;
}
- z = bignew(len, sign==RBIGNUM(y)->sign);
+ z = bignew(len, sign);
len = RBIGNUM(x)->len;
for (i = 0, num = 0; i < len; i++) {
- num += (long)(BDIGITS(x)[i] + BDIGITS(y)[i]);
+ num += BDIGITS(x)[i] + BDIGITS(y)[i];
BDIGITS(z)[i] = BIGLO(num);
num = BIGDN(num);
}
@@ -567,72 +589,72 @@ bigadd(x, y, sign)
BDIGITS(z)[i] = BDIGITS(y)[i];
i++;
}
- BDIGITS(z)[i] = num;
+ BDIGITS(z)[i] = (USHORT)num;
return bignorm(z);
}
VALUE
-big_plus(x, y)
+rb_big_plus(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
/* fall through */
case T_BIGNUM:
return bigadd(x, y, 1);
case T_FLOAT:
- return float_new(big2dbl(x) + RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) + RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
VALUE
-big_minus(x, y)
+rb_big_minus(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
/* fall through */
case T_BIGNUM:
return bigadd(x, y, 0);
case T_FLOAT:
- return float_new(big2dbl(x) - RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) - RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
VALUE
-big_mul(x, y)
+rb_big_mul(x, y)
VALUE x, y;
{
- UINT i = 0, j;
+ size_t i, j;
unsigned long n = 0;
VALUE z;
USHORT *zds;
- if (FIXNUM_P(x)) x = int2big(FIX2INT(x));
+ if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
case T_FLOAT:
- return float_new(big2dbl(x) * RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) * RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
@@ -658,19 +680,21 @@ big_mul(x, y)
}
static void
-bigdivmod(x, y, div, mod)
+bigdivmod(x, y, div, mod, modulo)
VALUE x, y;
VALUE *div, *mod;
+ int modulo;
{
- UINT nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len, i, j;
- VALUE z;
+ size_t nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
+ int i, j;
+ VALUE yy, z;
USHORT *xds, *yds, *zds, *tds;
- unsigned long t2;
+ size_t t2;
long num;
USHORT dd, q;
yds = BDIGITS(y);
- if (ny == 0 && yds[0] == 0) num_zerodiv();
+ if (ny == 0 && yds[0] == 0) rb_num_zerodiv();
if (nx < ny || nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1]) {
if (div) *div = INT2FIX(0);
if (mod) *mod = bignorm(x);
@@ -679,17 +703,17 @@ bigdivmod(x, y, div, mod)
xds = BDIGITS(x);
if (ny == 1) {
dd = yds[0];
- z = big_clone(x);
+ z = rb_big_clone(x);
zds = BDIGITS(z);
t2 = 0; i = nx;
while (i--) {
t2 = BIGUP(t2) + zds[i];
- zds[i] = t2 / dd;
+ zds[i] = (USHORT)(t2 / dd);
t2 %= dd;
}
if (div) *div = bignorm(z);
if (mod) {
- if (!RBIGNUM(y)->sign) t2 = -t2;
+ if (!RBIGNUM(y)->sign) t2 = -(long)t2;
*mod = INT2FIX(t2);
}
return;
@@ -699,12 +723,12 @@ bigdivmod(x, y, div, mod)
if (nx==ny) zds[nx+1] = 0;
while (!yds[ny-1]) ny--;
if ((dd = BIGRAD/(int)(yds[ny-1]+1)) != 1) {
- y = big_clone(y);
- tds = BDIGITS(y);
+ yy = rb_big_clone(y);
+ tds = BDIGITS(yy);
j = 0;
num = 0;
while (j<ny) {
- num += (unsigned long)yds[j]*dd;
+ num += (long)yds[j]*dd;
tds[j++] = BIGLO(num);
num = BIGDN(num);
}
@@ -712,11 +736,11 @@ bigdivmod(x, y, div, mod)
j = 0;
num = 0;
while (j<nx) {
- num += (unsigned long)xds[j]*dd;
+ num += (long)xds[j]*dd;
zds[j++] = BIGLO(num);
num = BIGDN(num);
}
- zds[j] = num;
+ zds[j] = (USHORT)num;
}
else {
zds[nx] = 0;
@@ -726,12 +750,12 @@ bigdivmod(x, y, div, mod)
j = nx==ny?nx+1:nx;
do {
if (zds[j] == yds[ny-1]) q = BIGRAD-1;
- else q = (BIGUP(zds[j]) + zds[j-1])/yds[ny-1];
+ else q = (USHORT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
if (q) {
i = 0; num = 0; t2 = 0;
do { /* multiply and subtract */
int ee;
- t2 += (unsigned long)yds[i] * q;
+ t2 += (long)yds[i] * q;
ee = num - BIGLO(t2);
num = zds[j - ny + i] + ee;
if (ee) zds[j - ny + i] = BIGLO(num);
@@ -753,7 +777,7 @@ bigdivmod(x, y, div, mod)
zds[j] = q;
} while (--j >= ny);
if (div) { /* move quotient down in z */
- *div = big_clone(z);
+ *div = rb_big_clone(z);
zds = BDIGITS(*div);
j = (nx==ny ? nx+2 : nx+1) - ny;
for (i = 0;i < j;i++) zds[i] = zds[i+ny];
@@ -761,105 +785,130 @@ bigdivmod(x, y, div, mod)
*div = bignorm(*div);
}
if (mod) { /* just normalize remainder */
- *mod = big_clone(z);
+ *mod = rb_big_clone(z);
if (dd) {
zds = BDIGITS(*mod);
t2 = 0; i = ny;
while(i--) {
t2 = BIGUP(t2) + zds[i];
- zds[i] = t2 / dd;
+ zds[i] = (USHORT)(t2 / dd);
t2 %= dd;
}
}
RBIGNUM(*mod)->len = ny;
- RBIGNUM(*mod)->sign = RBIGNUM(y)->sign;
+ RBIGNUM(*mod)->sign = RBIGNUM(x)->sign;
+ if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) {
+ size_t len = ny;
+ zds = BDIGITS(*mod);
+ while (len-- && !zds[len]);
+ if (len > 0) {
+ *mod = bigadd(*mod, y, 1);
+ return;
+ }
+ }
*mod = bignorm(*mod);
}
}
static VALUE
-big_div(x, y)
+rb_big_div(x, y)
VALUE x, y;
{
VALUE z;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
case T_FLOAT:
- return float_new(big2dbl(x) / RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, &z, 0);
+ bigdivmod(x, y, &z, 0, 0);
return z;
}
+
static VALUE
-big_mod(x, y)
+rb_big_modulo(x, y, modulo)
VALUE x, y;
+ int modulo;
{
VALUE z;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
case T_FLOAT:
- y = dbl2big(RFLOAT(y)->value);
+ y = rb_dbl2big(RFLOAT(y)->value);
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, 0, &z);
+ bigdivmod(x, y, 0, &z, modulo);
return z;
}
static VALUE
-big_divmod(x, y)
+rb_big_mod(x, y)
+ VALUE x, y;
+{
+ return rb_big_modulo(x, y, 1);
+}
+
+static VALUE
+rb_big_remainder(x, y)
+ VALUE x, y;
+{
+ return rb_big_modulo(x, y, 0);
+}
+
+static VALUE
+rb_big_divmod(x, y)
VALUE x, y;
{
VALUE div, mod;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_FLOAT:
- y = dbl2big(RFLOAT(y)->value);
+ y = rb_dbl2big(RFLOAT(y)->value);
break;
case T_BIGNUM:
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, &div, &mod);
+ bigdivmod(x, y, &div, &mod, 1);
- return assoc_new(div, mod);;
+ return rb_assoc_new(div, mod);;
}
VALUE
-big_pow(x, y)
+rb_big_pow(x, y)
VALUE x, y;
{
double d;
- VALUE z;
+ long yy;
if (y == INT2FIX(0)) return INT2FIX(1);
switch (TYPE(y)) {
@@ -868,57 +917,59 @@ big_pow(x, y)
break;
case T_BIGNUM:
- if (RBIGNUM(y)->sign) goto pos_big;
- d = big2dbl(y);
+ rb_warn("in a**b, b may be too big");
+ d = rb_big2dbl(y);
break;
case T_FIXNUM:
- if (FIX2INT(y) > 0) goto pos_big;
- d = (double)FIX2INT(y);
+ yy = NUM2LONG(y);
+ if (yy > 0) {
+ VALUE z;
+
+ z = x;
+ for (;;) {
+ yy = yy - 1;
+ if (yy == 0) break;
+ while (yy % 2 == 0) {
+ yy = yy / 2;
+ x = rb_big_mul(x, x);
+ }
+ z = rb_big_mul(z, x);
+ }
+ return z;
+ }
+ d = (double)yy;
break;
default:
- return num_coerce_bin(x, y);
- }
- return float_new(pow(big2dbl(x), d));
-
- pos_big:
- z = x;
- for (;;) {
- y = rb_funcall(y, '-', 1, INT2FIX(1));
- if (y == INT2FIX(0)) break;
- while (rb_funcall(y, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
- y = rb_funcall(y, '/', 1, INT2FIX(2));
- x = big_mul(x, x);
- }
- z = big_mul(z, x);
+ return rb_num_coerce_bin(x, y);
}
- return z;
+ return rb_float_new(pow(rb_big2dbl(x), d));
}
VALUE
-big_and(x, y)
+rb_big_and(x, y)
VALUE x, y;
{
VALUE z;
USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ size_t i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -943,33 +994,33 @@ big_and(x, y)
for (; i<l2; i++) {
zds[i] = sign?0:ds2[i];
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
-big_or(x, y)
+rb_big_or(x, y)
VALUE x, y;
{
VALUE z;
USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ unsigned int i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -994,34 +1045,34 @@ big_or(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:(BIGRAD-1);
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
-big_xor(x, y)
+rb_big_xor(x, y)
VALUE x, y;
{
VALUE z;
USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ unsigned int i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1048,26 +1099,26 @@ big_xor(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:~ds2[i];
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
-static VALUE big_rshift();
+static VALUE rb_big_rshift _((VALUE,VALUE));
VALUE
-big_lshift(x, y)
+rb_big_lshift(x, y)
VALUE x, y;
{
USHORT *xds, *zds;
int shift = NUM2INT(y);
- UINT s1 = shift/BITSPERDIG;
- UINT s2 = shift%BITSPERDIG;
+ size_t s1 = shift/BITSPERDIG;
+ size_t s2 = shift%BITSPERDIG;
VALUE z;
unsigned long num = 0;
- UINT len, i;
+ size_t len, i;
- if (shift < 0) return big_rshift(x, INT2FIX(-shift));
+ if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
xds = BDIGITS(x);
len = RBIGNUM(x)->len;
z = bignew(len+s1+1, RBIGNUM(x)->sign);
@@ -1085,19 +1136,19 @@ big_lshift(x, y)
}
static VALUE
-big_rshift(x, y)
+rb_big_rshift(x, y)
VALUE x, y;
{
USHORT *xds, *zds;
int shift = NUM2INT(y);
- UINT s1 = shift/BITSPERDIG;
- UINT s2 = shift%BITSPERDIG;
+ size_t s1 = shift/BITSPERDIG;
+ size_t s2 = shift%BITSPERDIG;
VALUE z;
unsigned long num = 0;
- UINT i = RBIGNUM(x)->len;
- UINT j;
+ size_t i = RBIGNUM(x)->len;
+ size_t j;
- if (shift < 0) return big_lshift(x, INT2FIX(-shift));
+ if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
if (s1 > RBIGNUM(x)->len) {
if (RBIGNUM(x)->sign)
return INT2FIX(0);
@@ -1117,12 +1168,12 @@ big_rshift(x, y)
}
static VALUE
-big_aref(x, y)
+rb_big_aref(x, y)
VALUE x, y;
{
USHORT *xds;
int shift = NUM2INT(y);
- UINT s1, s2;
+ size_t s1, s2;
if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
@@ -1130,8 +1181,8 @@ big_aref(x, y)
if (!RBIGNUM(x)->sign) {
if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
else {
if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
@@ -1143,10 +1194,11 @@ big_aref(x, y)
}
static VALUE
-big_hash(x)
+rb_big_hash(x)
VALUE x;
{
- int i, len, key;
+ size_t i, len;
+ int key;
USHORT *digits;
key = 0; digits = BDIGITS(x);
@@ -1157,27 +1209,29 @@ big_hash(x)
}
static VALUE
-big_coerce(x, y)
+rb_big_coerce(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- return assoc_new(int2big(FIX2INT(y)), x);
+ return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
}
else {
- TypeError("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y)));
+ rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
+ rb_class2name(CLASS_OF(y)));
}
/* not reached */
+ return Qnil;
}
static VALUE
-big_abs(x)
+rb_big_abs(x)
VALUE x;
{
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
+ x = rb_big_clone(x);
RBIGNUM(x)->sign = 1;
}
- return (VALUE)x;
+ return x;
}
/* !!!warnig!!!!
@@ -1185,11 +1239,11 @@ big_abs(x)
*/
VALUE
-big_rand(max)
+rb_big_rand(max)
VALUE max;
{
struct RBignum *v;
- int len;
+ size_t len;
len = RBIGNUM(max)->len;
v = RBIGNUM(bignew(len,1));
@@ -1201,47 +1255,57 @@ big_rand(max)
#endif
}
- return big_mod(v, max);
+ return rb_big_mod((VALUE)v, max);
}
static VALUE
-big_size(big)
+rb_big_size(big)
VALUE big;
{
return INT2FIX(RBIGNUM(big)->len*sizeof(USHORT));
}
+static VALUE
+rb_big_zero_p(big)
+ VALUE big;
+{
+ return Qfalse;
+}
+
void
Init_Bignum()
{
- cBignum = rb_define_class("Bignum", cInteger);
-
- rb_undef_method(CLASS_OF(cBignum), "new");
-
- rb_define_method(cBignum, "to_s", big_to_s, 0);
- rb_define_method(cBignum, "coerce", big_coerce, 1);
- rb_define_method(cBignum, "-@", big_uminus, 0);
- rb_define_method(cBignum, "+", big_plus, 1);
- rb_define_method(cBignum, "-", big_minus, 1);
- rb_define_method(cBignum, "*", big_mul, 1);
- rb_define_method(cBignum, "/", big_div, 1);
- rb_define_method(cBignum, "%", big_mod, 1);
- rb_define_method(cBignum, "divmod", big_divmod, 1);
- rb_define_method(cBignum, "**", big_pow, 1);
- rb_define_method(cBignum, "&", big_and, 1);
- rb_define_method(cBignum, "|", big_or, 1);
- rb_define_method(cBignum, "^", big_xor, 1);
- rb_define_method(cBignum, "~", big_neg, 0);
- rb_define_method(cBignum, "<<", big_lshift, 1);
- rb_define_method(cBignum, ">>", big_rshift, 1);
- rb_define_method(cBignum, "[]", big_aref, 1);
-
- rb_define_method(cBignum, "<=>", big_cmp, 1);
- rb_define_method(cBignum, "==", big_eq, 1);
- rb_define_method(cBignum, "eql?", big_eq, 1);
- rb_define_method(cBignum, "hash", big_hash, 0);
- rb_define_method(cBignum, "to_i", big_to_i, 0);
- rb_define_method(cBignum, "to_f", big_to_f, 0);
- rb_define_method(cBignum, "abs", big_abs, 0);
- rb_define_method(cBignum, "size", big_size, 0);
+ rb_cBignum = rb_define_class("Bignum", rb_cInteger);
+
+ rb_undef_method(CLASS_OF(rb_cBignum), "new");
+
+ rb_define_method(rb_cBignum, "to_s", rb_big_to_s, 0);
+ rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
+ rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
+ rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
+ rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
+ rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
+ rb_define_method(rb_cBignum, "/", rb_big_div, 1);
+ rb_define_method(rb_cBignum, "%", rb_big_mod, 1);
+ rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
+ rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
+ rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
+ rb_define_method(rb_cBignum, "&", rb_big_and, 1);
+ rb_define_method(rb_cBignum, "|", rb_big_or, 1);
+ rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
+ rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
+ rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
+ rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
+ rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
+
+ rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
+ rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "eql?", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
+ rb_define_method(rb_cBignum, "to_i", rb_big_to_i, 0);
+ rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
+ rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
+ rb_define_method(rb_cBignum, "size", rb_big_size, 0);
+ rb_define_method(rb_cBignum, "zero?", rb_big_zero_p, 0);
}
diff --git a/class.c b/class.c
index 13c9298c1c..86ac8c5ae7 100644
--- a/class.c
+++ b/class.c
@@ -6,40 +6,41 @@
$Date$
created at: Tue Aug 10 15:05:44 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "node.h"
#include "st.h"
+#include <ctype.h>
-struct st_table *new_idhash();
-extern st_table *rb_class_tbl;
+#ifdef USE_CWGUSI
+#include <stdio.h>
+#endif
-extern VALUE cClass;
-extern VALUE cModule;
+extern st_table *rb_class_tbl;
VALUE
-class_new(super)
+rb_class_new(super)
VALUE super;
{
NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, cClass, T_CLASS);
+ OBJSETUP(klass, rb_cClass, T_CLASS);
klass->super = super;
klass->iv_tbl = 0;
klass->m_tbl = 0; /* safe GC */
- klass->m_tbl = new_idhash();
+ klass->m_tbl = st_init_numtable();
return (VALUE)klass;
}
VALUE
-singleton_class_new(super)
+rb_singleton_class_new(super)
VALUE super;
{
- VALUE klass = class_new(super);
+ VALUE klass = rb_class_new(super);
FL_SET(klass, FL_SINGLETON);
return klass;
@@ -56,7 +57,7 @@ clone_method(mid, body, tbl)
}
VALUE
-singleton_class_clone(klass)
+rb_singleton_class_clone(klass)
VALUE klass;
{
if (!FL_TEST(klass, FL_SINGLETON))
@@ -69,7 +70,7 @@ singleton_class_clone(klass)
clone->super = RCLASS(klass)->super;
clone->iv_tbl = 0;
clone->m_tbl = 0;
- clone->m_tbl = new_idhash();
+ clone->m_tbl = st_init_numtable();
st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl);
FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
@@ -77,7 +78,7 @@ singleton_class_clone(klass)
}
void
-singleton_class_attached(klass, obj)
+rb_singleton_class_attached(klass, obj)
VALUE klass, obj;
{
if (FL_TEST(klass, FL_SINGLETON))
@@ -91,15 +92,15 @@ rb_define_class_id(id, super)
{
VALUE klass;
- if (!super) super = cObject;
- klass = class_new(super);
+ if (!super) super = rb_cObject;
+ klass = rb_class_new(super);
rb_name_class(klass, id);
/* make metaclass */
- RBASIC(klass)->class = singleton_class_new(RBASIC(super)->class);
- singleton_class_attached(RBASIC(klass)->class, klass);
+ RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
+ rb_singleton_class_attached(RBASIC(klass)->klass, klass);
rb_funcall(super, rb_intern("inherited"), 1, klass);
- return (VALUE)klass;
+ return klass;
}
VALUE
@@ -112,14 +113,15 @@ rb_define_class(name, super)
id = rb_intern(name);
klass = rb_define_class_id(id, super);
+
st_add_direct(rb_class_tbl, id, klass);
return klass;
}
VALUE
-rb_define_class_under(under, name, super)
- VALUE under;
+rb_define_class_under(outer, name, super)
+ VALUE outer;
char *name;
VALUE super;
{
@@ -128,22 +130,22 @@ rb_define_class_under(under, name, super)
id = rb_intern(name);
klass = rb_define_class_id(id, super);
- rb_const_set(under, id, klass);
- rb_set_class_path(klass, under, name);
+ rb_const_set(outer, id, klass);
+ rb_set_class_path(klass, outer, name);
return klass;
}
VALUE
-module_new()
+rb_module_new()
{
NEWOBJ(mdl, struct RClass);
- OBJSETUP(mdl, cModule, T_MODULE);
+ OBJSETUP(mdl, rb_cModule, T_MODULE);
mdl->super = 0;
mdl->iv_tbl = 0;
mdl->m_tbl = 0;
- mdl->m_tbl = new_idhash();
+ mdl->m_tbl = st_init_numtable();
return (VALUE)mdl;
}
@@ -152,9 +154,9 @@ VALUE
rb_define_module_id(id)
ID id;
{
- extern st_table *rb_class_tbl;
- VALUE mdl = module_new();
+ VALUE mdl;
+ mdl = rb_module_new();
rb_name_class(mdl, id);
return mdl;
@@ -175,8 +177,8 @@ rb_define_module(name)
}
VALUE
-rb_define_module_under(under, name)
- VALUE under;
+rb_define_module_under(outer, name)
+ VALUE outer;
char *name;
{
VALUE module;
@@ -184,8 +186,8 @@ rb_define_module_under(under, name)
id = rb_intern(name);
module = rb_define_module_id(id);
- rb_const_set(under, id, module);
- rb_set_class_path(module, under, name);
+ rb_const_set(outer, id, module);
+ rb_set_class_path(module, outer, name);
return module;
}
@@ -195,16 +197,16 @@ include_class_new(module, super)
VALUE module, super;
{
NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, cClass, T_ICLASS);
+ OBJSETUP(klass, rb_cClass, T_ICLASS);
klass->m_tbl = RCLASS(module)->m_tbl;
klass->iv_tbl = RCLASS(module)->iv_tbl;
klass->super = super;
if (TYPE(module) == T_ICLASS) {
- RBASIC(klass)->class = RBASIC(module)->class;
+ RBASIC(klass)->klass = RBASIC(module)->klass;
}
else {
- RBASIC(klass)->class = module;
+ RBASIC(klass)->klass = module;
}
return (VALUE)klass;
@@ -217,61 +219,66 @@ rb_include_module(klass, module)
VALUE p;
if (NIL_P(module)) return;
+ if (klass == module) return;
switch (TYPE(module)) {
case T_MODULE:
case T_CLASS:
+ case T_ICLASS:
break;
default:
Check_Type(module, T_MODULE);
}
- if (klass == module) return;
- rb_clear_cache();
-
while (module) {
/* ignore if the module included already in superclasses */
for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
if (BUILTIN_TYPE(p) == T_ICLASS &&
- RCLASS(p)->m_tbl == RCLASS(module)->m_tbl)
+ RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
+ if (RCLASS(module)->super) {
+ rb_include_module(p, RCLASS(module)->super);
+ }
return;
+ }
}
-
RCLASS(klass)->super =
include_class_new(module, RCLASS(klass)->super);
klass = RCLASS(klass)->super;
module = RCLASS(module)->super;
}
+ rb_clear_cache();
}
VALUE
-mod_included_modules(mod)
+rb_mod_included_modules(mod)
VALUE mod;
{
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
VALUE p;
for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
if (BUILTIN_TYPE(p) == T_ICLASS) {
- ary_push(ary, RBASIC(p)->class);
+ rb_ary_push(ary, RBASIC(p)->klass);
}
}
return ary;
}
VALUE
-mod_ancestors(mod)
+rb_mod_ancestors(mod)
VALUE mod;
{
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
VALUE p;
for (p = mod; p; p = RCLASS(p)->super) {
+ if (FL_TEST(p, FL_SINGLETON))
+ continue;
if (BUILTIN_TYPE(p) == T_ICLASS) {
- ary_push(ary, RBASIC(p)->class);
+ rb_ary_push(ary, RBASIC(p)->klass);
}
else {
- ary_push(ary, p);
+ rb_ary_push(ary, p);
}
}
return ary;
@@ -283,19 +290,43 @@ ins_methods_i(key, body, ary)
NODE *body;
VALUE ary;
{
- if (!body->nd_noex) {
- VALUE name = str_new2(rb_id2name(key));
+ if ((body->nd_noex&(NOEX_PRIVATE|NOEX_PROTECTED)) == 0) {
+ VALUE name = rb_str_new2(rb_id2name(key));
- if (!ary_includes(ary, name)) {
+ if (!rb_ary_includes(ary, name)) {
if (!body->nd_body) {
- ary_push(ary, Qnil);
+ rb_ary_push(ary, Qnil);
}
- ary_push(ary, name);
+ rb_ary_push(ary, name);
+ }
+ }
+ else if (body->nd_body && nd_type(body->nd_body) == NODE_ZSUPER) {
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
+ }
+ return ST_CONTINUE;
+}
+
+static int
+ins_methods_prot_i(key, body, ary)
+ ID key;
+ NODE *body;
+ VALUE ary;
+{
+ if (!body->nd_body) {
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
+ }
+ else if (body->nd_noex & NOEX_PROTECTED) {
+ VALUE name = rb_str_new2(rb_id2name(key));
+
+ if (!rb_ary_includes(ary, name)) {
+ rb_ary_push(ary, name);
}
}
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
@@ -307,19 +338,19 @@ ins_methods_priv_i(key, body, ary)
VALUE ary;
{
if (!body->nd_body) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
- else if (body->nd_noex) {
- VALUE name = str_new2(rb_id2name(key));
+ else if (body->nd_noex & NOEX_PRIVATE) {
+ VALUE name = rb_str_new2(rb_id2name(key));
- if (!ary_includes(ary, name)) {
- ary_push(ary, name);
+ if (!rb_ary_includes(ary, name)) {
+ rb_ary_push(ary, name);
}
}
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
@@ -334,7 +365,7 @@ method_list(mod, option, func)
VALUE klass;
VALUE *p, *q, *pend;
- ary = ary_new();
+ ary = rb_ary_new();
for (klass = mod; klass; klass = RCLASS(klass)->super) {
st_foreach(RCLASS(klass)->m_tbl, func, ary);
if (!option) break;
@@ -352,7 +383,7 @@ method_list(mod, option, func)
}
VALUE
-class_instance_methods(argc, argv, mod)
+rb_class_instance_methods(argc, argv, mod)
int argc;
VALUE *argv;
VALUE mod;
@@ -364,7 +395,19 @@ class_instance_methods(argc, argv, mod)
}
VALUE
-class_private_instance_methods(argc, argv, mod)
+rb_class_protected_instance_methods(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
+{
+ VALUE option;
+
+ rb_scan_args(argc, argv, "01", &option);
+ return method_list(mod, RTEST(option), ins_methods_prot_i);
+}
+
+VALUE
+rb_class_private_instance_methods(argc, argv, mod)
int argc;
VALUE *argv;
VALUE mod;
@@ -376,14 +419,14 @@ class_private_instance_methods(argc, argv, mod)
}
VALUE
-obj_singleton_methods(obj)
+rb_obj_singleton_methods(obj)
VALUE obj;
{
VALUE ary;
VALUE klass;
VALUE *p, *q, *pend;
- ary = ary_new();
+ ary = rb_ary_new();
klass = CLASS_OF(obj);
while (klass && FL_TEST(klass, FL_SINGLETON)) {
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
@@ -409,7 +452,7 @@ rb_define_method_id(klass, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_add_method(klass, name, NEW_CFUNC(func, argc), NOEX_PUBLIC);
+ rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC|NOEX_CFUNC);
}
void
@@ -419,15 +462,22 @@ rb_define_method(klass, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
+ ID id = rb_intern(name);
+
+ rb_add_method(klass, id, NEW_CFUNC(func, argc),
+ ((name[0] == 'i' && id == rb_intern("initialize"))?
+ NOEX_PRIVATE:NOEX_PUBLIC)|NOEX_CFUNC);
}
void
-rb_undef_method(klass, name)
+rb_define_protected_method(klass, name, func, argc)
VALUE klass;
char *name;
+ VALUE (*func)();
+ int argc;
{
- rb_add_method(klass, rb_intern(name), 0, NOEX_PUBLIC);
+ rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
+ NOEX_PROTECTED|NOEX_CFUNC);
}
void
@@ -437,7 +487,16 @@ rb_define_private_method(klass, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
+ rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
+ NOEX_PRIVATE|NOEX_CFUNC);
+}
+
+void
+rb_undef_method(klass, name)
+ VALUE klass;
+ char *name;
+{
+ rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
}
VALUE
@@ -445,14 +504,14 @@ rb_singleton_class(obj)
VALUE obj;
{
if (rb_special_const_p(obj)) {
- TypeError("cannot define singleton");
+ rb_raise(rb_eTypeError, "cannot define singleton");
}
- if (FL_TEST(RBASIC(obj)->class, FL_SINGLETON)) {
- return (VALUE)RBASIC(obj)->class;
+ if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) {
+ return RBASIC(obj)->klass;
}
- RBASIC(obj)->class = singleton_class_new(RBASIC(obj)->class);
- singleton_class_attached(RBASIC(obj)->class, obj);
- return RBASIC(obj)->class;
+ RBASIC(obj)->klass = rb_singleton_class_new(RBASIC(obj)->klass);
+ rb_singleton_class_attached(RBASIC(obj)->klass, obj);
+ return RBASIC(obj)->klass;
}
void
@@ -476,15 +535,13 @@ rb_define_module_function(module, name, func, argc)
rb_define_singleton_method(module, name, func, argc);
}
-extern VALUE mKernel;
-
void
rb_define_global_function(name, func, argc)
char *name;
VALUE (*func)();
int argc;
{
- rb_define_private_method(mKernel, name, func, argc);
+ rb_define_module_function(rb_mKernel, name, func, argc);
}
void
@@ -496,57 +553,50 @@ rb_define_alias(klass, name1, name2)
}
void
-rb_define_attr(klass, id, read, write)
+rb_define_attr(klass, name, read, write)
VALUE klass;
- ID id;
+ char *name;
int read, write;
{
- char *name;
- char *buf;
- ID attr, attreq, attriv;
-
- name = rb_id2name(id);
- attr = rb_intern(name);
- buf = ALLOCA_N(char,strlen(name)+2);
- sprintf(buf, "%s=", name);
- attreq = rb_intern(buf);
- sprintf(buf, "@%s", name);
- attriv = rb_intern(buf);
- if (read) {
- rb_add_method(klass, attr, NEW_IVAR(attriv), 0);
- }
- if (write) {
- rb_add_method(klass, attreq, NEW_ATTRSET(attriv), 0);
- }
+ rb_attr(klass, rb_intern(name), read, write, Qfalse);
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
-#include <ctype.h>
+#define va_init_list(a,b) va_start(a)
+#endif
int
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_scan_args(int argc, VALUE *argv, char *fmt, ...)
+#else
rb_scan_args(argc, argv, fmt, va_alist)
int argc;
VALUE *argv;
char *fmt;
va_dcl
+#endif
{
int n, i;
char *p = fmt;
VALUE *var;
va_list vargs;
- va_start(vargs);
+ va_init_list(vargs, fmt);
if (*p == '*') {
var = va_arg(vargs, VALUE*);
- *var = ary_new4(argc, argv);
+ *var = rb_ary_new4(argc, argv);
return argc;
}
- if (isdigit(*p)) {
+ if (ISDIGIT(*p)) {
n = *p - '0';
if (n > argc)
- ArgError("Wrong # of arguments (%d for %d)", argc, n);
+ rb_raise(rb_eArgError, "Wrong # of arguments (%d for %d)", argc, n);
for (i=0; i<n; i++) {
var = va_arg(vargs, VALUE*);
*var = argv[i];
@@ -557,7 +607,7 @@ rb_scan_args(argc, argv, fmt, va_alist)
goto error;
}
- if (isdigit(*p)) {
+ if (ISDIGIT(*p)) {
n = i + *p - '0';
for (; i<n; i++) {
var = va_arg(vargs, VALUE*);
@@ -574,15 +624,15 @@ rb_scan_args(argc, argv, fmt, va_alist)
if(*p == '*') {
var = va_arg(vargs, VALUE*);
if (argc > i) {
- *var = ary_new4(argc-i, argv+i);
+ *var = rb_ary_new4(argc-i, argv+i);
}
else {
- *var = ary_new();
+ *var = rb_ary_new();
}
}
else if (*p == '\0') {
if (argc > i) {
- ArgError("Wrong # of arguments(%d for %d)", argc, i);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, i);
}
}
else {
@@ -593,6 +643,6 @@ rb_scan_args(argc, argv, fmt, va_alist)
return argc;
error:
- Fatal("bad scan arg format: %s", fmt);
+ rb_fatal("bad scan arg format: %s", fmt);
return 0;
}
diff --git a/compar.c b/compar.c
index e852fb1e49..a6212a86bb 100644
--- a/compar.c
+++ b/compar.c
@@ -6,13 +6,13 @@
$Date$
created at: Thu Aug 26 14:39:48 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-VALUE mComparable;
+VALUE rb_mComparable;
static ID cmp;
@@ -23,8 +23,8 @@ cmp_eq(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t == 0) return TRUE;
- return FALSE;
+ if (t == 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -34,8 +34,8 @@ cmp_gt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t > 0) return TRUE;
- return FALSE;
+ if (t > 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -45,8 +45,8 @@ cmp_ge(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t >= 0) return TRUE;
- return FALSE;
+ if (t >= 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -56,8 +56,8 @@ cmp_lt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t < 0) return TRUE;
- return FALSE;
+ if (t < 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -67,8 +67,8 @@ cmp_le(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t <= 0) return TRUE;
- return FALSE;
+ if (t <= 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -76,25 +76,25 @@ cmp_between(x, min, max)
VALUE x, min, max;
{
VALUE c = rb_funcall(x, cmp, 1, min);
- int t = NUM2INT(c);
- if (t < 0) return FALSE;
+ long t = NUM2LONG(c);
+ if (t < 0) return Qfalse;
c = rb_funcall(x, cmp, 1, max);
- t = NUM2INT(c);
- if (t > 0) return FALSE;
- return TRUE;
+ t = NUM2LONG(c);
+ if (t > 0) return Qfalse;
+ return Qtrue;
}
void
Init_Comparable()
{
- mComparable = rb_define_module("Comparable");
- rb_define_method(mComparable, "==", cmp_eq, 1);
- rb_define_method(mComparable, ">", cmp_gt, 1);
- rb_define_method(mComparable, ">=", cmp_ge, 1);
- rb_define_method(mComparable, "<", cmp_lt, 1);
- rb_define_method(mComparable, "<=", cmp_le, 1);
- rb_define_method(mComparable, "between?", cmp_between, 2);
+ rb_mComparable = rb_define_module("Comparable");
+ rb_define_method(rb_mComparable, "==", cmp_eq, 1);
+ rb_define_method(rb_mComparable, ">", cmp_gt, 1);
+ rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
+ rb_define_method(rb_mComparable, "<", cmp_lt, 1);
+ rb_define_method(rb_mComparable, "<=", cmp_le, 1);
+ rb_define_method(rb_mComparable, "between?", cmp_between, 2);
cmp = rb_intern("<=>");
}
diff --git a/config.guess b/config.guess
index 91dad5ee6a..042d209871 100644
--- a/config.guess
+++ b/config.guess
@@ -1,6 +1,6 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 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
@@ -63,11 +63,53 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+ cat <<EOF >dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
@@ -78,17 +120,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
- Pyramid*:OSx*:*:*)
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
- sun4*:SunOS:5.*:*)
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
@@ -112,25 +191,84 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:NetBSD:*:*)
+ echo powerpc-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
- mips:*:4*:UMIPS)
- echo mips-mips-riscos4sysv
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
exit 0 ;;
- mips:*:5*:RISCos)
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
@@ -174,10 +312,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i[34]86:AIX:*:*)
+ i?86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
@@ -203,7 +341,8 @@ EOF
fi
exit 0 ;;
*:AIX:*:4)
- if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
@@ -236,12 +375,44 @@ EOF
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
- 9000/[3478]??:HP-UX:*:*)
+ 9000/[34678]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;;
- 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ 9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
+ sed 's/^ //' << EOF >dummy.c
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (${CC-cc} dummy.c -o dummy 2>/dev/null ) && HP_ARCH=`./dummy`
+ rm -f dummy.c dummy
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -288,6 +459,13 @@ EOF
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
@@ -315,18 +493,40 @@ EOF
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
- CRAY*C90:*:*:*)
- echo c90-cray-unicos${UNAME_RELEASE}
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
- i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
@@ -340,33 +540,142 @@ EOF
echo i386-pc-bow
exit 0 ;;
i*:CYGWIN*:*)
- echo i386-pc-cygwin32
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
exit 0 ;;
p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin32
+ echo powerpcle-unknown-cygwin
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
- echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux
- exit 0 ;;
+ # uname on the ARM produces all sorts of strangeness, and we need to
+ # filter it out.
+ case "$UNAME_MACHINE" in
+ arm* | sa110*) UNAME_MACHINE="arm" ;;
+ esac
+
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ i?86linux) echo "${UNAME_MACHINE}-pc-linux-aout" ; exit 0 ;;
+ i?86coff) echo "${UNAME_MACHINE}-pc-linux-coff" ; exit 0 ;;
+ sparclinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;;
+ m68klinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;;
+ elf32ppc) echo "powerpc-unknown-linux" ; exit 0 ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >dummy.c <<EOF
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ else
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit 0
+ fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
- i[34]86:DYNIX/ptx:4*:*)
+ i?86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
- i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
- i[34]86:*:3.2:*)
+ i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
@@ -380,6 +689,18 @@ EOF
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
+ i?86:UnixWare:*:*)
+ if /bin/uname -X 2>/dev/null >/dev/null ; then
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ fi
+ echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit 0 ;;
@@ -397,28 +718,36 @@ EOF
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
- M680[234]0:*:R3V[567]*:*)
+ M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
- 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
- uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4.3 && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- uname -p 2>/dev/null | grep 86 >/dev/null \
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
- m680[234]0:LynxOS:2.[23]*:*)
- echo m68k-lynx-lynxos${UNAME_RELEASE}
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
- i[34]86:LynxOS:2.[23]*:*)
- echo i386-lynx-lynxos${UNAME_RELEASE}
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
- TSUNAMI:LynxOS:2.[23]*:*)
- echo sparc-lynx-lynxos${UNAME_RELEASE}
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
- rs6000:LynxOS:2.[23]*:*)
- echo rs6000-lynx-lynxos${UNAME_RELEASE}
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
@@ -431,42 +760,58 @@ EOF
echo ns32k-sni-sysv
fi
exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
- X680[02346]0:Human68k:*:*)
- echo m68k-sharp-human
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
exit 0 ;;
- R[34]000:*System_V*:*:*)
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv`echo ${UNAME_RELEASE} | sed -n 's/\([.0-9]*\).*/\1/p'`
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
- R[34]???:UNIX_SV:4.?MP:*)
- if [ -x /sbin/uversion ]; then
- UVERSION_RELEASE=`(/sbin/uversion -r) 2>/dev/null` \
- || UVERSION_RELEASE=unknown
- UVERSION_SYSTEM=`(/sbin/uversion -s) 2>/dev/null` \
- || UVERSION_SYSTEM=unknown
- case "${UVERSION_RELEASE}:${UVERSION_SYSTEM}" in
- Release*:EWS4800/*)
- suffix=`echo ${UNAME_RELEASE} | tr '[A-Z]' '[a-z]'`
- suffix=${suffix}r`echo ${UVERSION_RELEASE} | \
- sed -e 's/Release//' -e 's/ Rev.*$//'`
- echo mips-nec-sysv${suffix}
- exit 0 ;;
- esac
- fi;;
- *:machten:*:*)
- echo ${UNAME_MACHINE}-apple-machten
- exit 0 ;;
- powerpc:JCC_BSD+:*:*)
- echo powerpc-jcc-bsd4.4
- exit 0 ;;
DS/90*:*:*:V20*)
- echo sparc-fujitsu-uxpds
+ echo sparc-fujitsu-uxpds
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+
+ *:Rhapsody:*:*)
+ arch=`/usr/bin/arch`
+ case "$arch" in
+ ppc)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ ;;
+ i[3456]86)
+ echo i386-apple-rhapsody${UNAME_RELEASE}
+ ;;
+ *)
+ echo $arch-apple-rhapsody${UNAME_RELEASE}
+ ;;
+ esac
exit 0 ;;
esac
@@ -511,7 +856,11 @@ main ()
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+
exit (0);
#endif
@@ -567,16 +916,12 @@ main ()
printf ("i860-alliant-bsd\n"); exit (0);
#endif
-#if defined (__human68k__) || defined (HUMAN68K)
- printf ("m68k-sharp-human\n"); exit (0);
-#endif
-
exit (1);
}
EOF
-${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm -f dummy.c dummy.x dummy && exit 0
-rm -f dummy.c dummy.x dummy
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
# Apollos put the system type in the environment.
diff --git a/config.sub b/config.sub
index 002d408812..858aba7aa5 100644
--- a/config.sub
+++ b/config.sub
@@ -1,6 +1,6 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
-# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
@@ -149,35 +149,43 @@ esac
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
- tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
- | arme[lb] | pyramid \
- | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
- | alpha | we32k | ns16k | clipper | i370 | sh \
- | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
- | pdp11 | mips64el | mips64orion | mips64orionel \
- | sparc | sparclet | sparclite | sparc64)
- basic_machine=$basic_machine-unknown
- ;;
+ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
+ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \
+ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
+ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
+ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+ | mipstx39 | mipstx39el \
+ | sparc | sparclet | sparclite | sparc64 | v850)
+ basic_machine=$basic_machine-unknown
+ ;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
- i[3456]86)
+ i[34567]86)
basic_machine=$basic_machine-pc
;;
+ i[3456]86-TOWNS*)
+ basic_machine=`echo $basic_machine | sed -e 's/-TOWNS.*/-TOWNS/'`
+ ;;
# Object if more than one company name word.
*-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
;;
# Recognize the basic CPU types with company name.
- vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
- | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
- | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
- | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
- | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
- | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
- | mips64el-* | mips64orion-* | mips64orionel-*)
+ vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \
+ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
+ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
+ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+ | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mipstx39-* | mipstx39el-* \
+ | f301-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -204,9 +212,9 @@ case $basic_machine in
amiga | amiga-*)
basic_machine=m68k-cbm
;;
- amigados)
+ amigaos | amigados)
basic_machine=m68k-cbm
- os=-amigados
+ os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-cbm
@@ -292,10 +300,6 @@ case $basic_machine in
encore | umax | mmax)
basic_machine=ns32k-encore
;;
- ews4800)
- basic_machine=mips-nec
- os=-sysv4
- ;;
fx2800)
basic_machine=i860-alliant
;;
@@ -341,24 +345,27 @@ case $basic_machine in
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
+ hppa-next)
+ os=-nextstep3
+ ;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i[3456]86v32)
+ i[34567]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
- i[3456]86v4*)
+ i[34567]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
- i[3456]86v)
+ i[34567]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
- i[3456]86sol2)
+ i[34567]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
@@ -390,6 +397,14 @@ case $basic_machine in
miniframe)
basic_machine=m68000-convergent
;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux
+ ;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
@@ -457,25 +472,23 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
- pentium | p5)
- basic_machine=i586-intel
+ pentium | p5 | k5 | nexen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | k6 | 6x86)
+ basic_machine=i686-pc
;;
- pentiumpro | p6)
- basic_machine=i686-intel
+ pentiumii | pentium2)
+ basic_machine=i786-pc
;;
- pentium-* | p5-*)
+ pentium-* | p5-* | k5-* | nexen-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
- pentiumpro-* | p6-*)
+ pentiumpro-* | p6-* | k6-* | 6x86-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
- k5)
- # We don't have specific support for AMD's K5 yet, so just call it a Pentium
- basic_machine=i586-amd
- ;;
- nexen)
- # We don't have specific support for Nexgen yet, so just call it a Pentium
- basic_machine=i586-nexgen
+ pentiumii-* | pentium2-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
@@ -559,6 +572,12 @@ case $basic_machine in
basic_machine=i386-sequent
os=-dynix
;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
tower | tower-32)
basic_machine=m68k-ncr
;;
@@ -578,6 +597,9 @@ case $basic_machine in
basic_machine=vax-dec
os=-vms
;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
@@ -605,7 +627,11 @@ case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
mips)
- basic_machine=mips-mips
+ if [ x$os = x-linux ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
;;
romp)
basic_machine=romp-ibm
@@ -634,10 +660,6 @@ case $basic_machine in
orion105)
basic_machine=clipper-highlevel
;;
- human)
- basic_machine=m68k-sharp
- os=-human
- ;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
@@ -652,6 +674,10 @@ case $basic_machine in
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
+ human)
+ basic_machine=m68k-sharp
+ os=-human
+ ;;
*)
;;
esac
@@ -670,9 +696,12 @@ case $os in
-solaris)
os=-solaris2
;;
- -unixware* | svr4*)
+ -svr4*)
os=-sysv4
;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
@@ -683,15 +712,16 @@ case $os in
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
- | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
- | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -cygwin32* | -pe* | -psos* | -moss* | -proelf* \
- | -linux* | -bow*)
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux* | -uxpv* | -beos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-sunos5*)
@@ -754,6 +784,9 @@ case $os in
;;
-human)
;;
+ -beos)
+ os=-beos
+ ;;
-none)
;;
*)
@@ -806,6 +839,9 @@ case $basic_machine in
sparc-* | *-sun)
os=-sunos4.1.1
;;
+ *-be)
+ os=-beos
+ ;;
*-ibm)
os=-aix
;;
@@ -819,7 +855,7 @@ case $basic_machine in
os=-sysv
;;
*-cbm)
- os=-amigados
+ os=-amigaos
;;
*-dg)
os=-dgux
@@ -869,6 +905,9 @@ case $basic_machine in
*-masscomp)
os=-rtu
;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
*)
os=-none
;;
@@ -887,9 +926,6 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
- -lynxos*)
- vendor=lynx
- ;;
-aix*)
vendor=ibm
;;
@@ -917,7 +953,7 @@ case $basic_machine in
-ptx*)
vendor=sequent
;;
- -vxworks*)
+ -vxsim* | -vxworks*)
vendor=wrs
;;
-aux*)
diff --git a/config_h.dj b/config_h.dj
new file mode 100644
index 0000000000..ebed8c446a
--- /dev/null
+++ b/config_h.dj
@@ -0,0 +1,64 @@
+#define USE_THREAD 1
+#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
+#define SIZEOF_VOIDP 4
+#define HAVE_PROTOTYPES 1
+#define HAVE_STDARG_PROTOTYPES 1
+#define HAVE_ATTR_NORETURN 1
+#define HAVE_DIRENT_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_SYS_FILE_H 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_PWD_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TIMES_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_WAIT_H 1
+#define HAVE_STRING_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_DIRECT_H 1
+#define HAVE_ST_BLKSIZE 1
+#define HAVE_ST_RDEV 1
+#define GETGROUPS_T gid_t
+#define RETSIGTYPE void
+#define HAVE_ALLOCA 1
+#define vfork fork
+#define HAVE_DUP2 1
+#define HAVE_SETENV 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MKDIR 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRERROR 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRDUP 1
+#define HAVE_FMOD 1
+#define HAVE_RANDOM 1
+#define HAVE_WAITPID 1
+#define HAVE_GETCWD 1
+#define HAVE_TRUNCATE 1
+#define HAVE_CHSIZE 1
+#define HAVE_TIMES 1
+#define HAVE_UTIMES 1
+#define HAVE_FCNTL 1
+/*#define HAVE_SETITIMER 1*/
+#define HAVE_GETGROUPS 1
+#define HAVE_SIGPROCMASK 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETSID 1
+#define POSIX_SIGNAL 1
+#define BSD_SETPGRP setpgrp
+#define RSHIFT(x,y) ((x)>>y)
+#define FILE_COUNT _cnt
+#define DLEXT ".o"
+#define RUBY_LIB "/usr/local/lib/ruby"
+#define RUBY_SITE_LIB "/usr/local/lib/ruby/site_ruby"
+#define RUBY_ARCHLIB "/usr/local/lib/ruby/i386-djgpp"
+#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/site_ruby/i386-djgpp"
+#define RUBY_PLATFORM "i386-djgpp"
diff --git a/config_s.dj b/config_s.dj
new file mode 100644
index 0000000000..e172e30e8b
--- /dev/null
+++ b/config_s.dj
@@ -0,0 +1,51 @@
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@DEFS@% -DUSE_THREAD=1 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_ATTR_NORETURN=1 -DHAVE_DIRENT_H=1 -DSTDC_HEADERS=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_PWD_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_TIMES_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_STRING_H=1 -DHAVE_UTIME_H=1 -DHAVE_MEMORY_H=1 -DHAVE_DIRECT_H=1 -DHAVE_ST_BLKSIZE=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=gid_t -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -Dvfork=fork -DHAVE_DUP2=1 -DHAVE_SETENV=1 -DHAVE_MEMMOVE=1 -DHAVE_MKDIR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRERROR=1 -DHAVE_STRFTIME=1 -DHAVE_STRCHR=1 -DHAVE_STRSTR=1 -DHAVE_STRTOUL=1 -DHAVE_STRDUP=1 -DHAVE_FMOD=1 -DHAVE_RANDOM=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_TRUNCATE=1 -DHAVE_CHSIZE=1 -DHAVE_TIMES=1 -DHAVE_UTIMES=1 -DHAVE_FCNTL=1 -DHAVE_SETITIMER=1 -DHAVE_GETGROUPS=1 -DHAVE_SIGPROCMASK=1 -DHAVE_SIGACTION=1 -DHAVE_SETSID=1 -DPOSIX_SIGNAL=1 -DBSD_SETPGRP=setpgrp -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".so\" -DRUBY_LIB=\"/usr/local/lib/ruby\" -DRUBY_SITE_LIB=\"/usr/local/lib/ruby/site_ruby\" -DRUBY_ARCHLIB=\"/usr/local/lib/ruby/i386-djgpp\" -DRUBY_SITE_ARCHLIB=\"/usr/local/lib/ruby/site_ruby/i386-djgpp\" -DRUBY_PLATFORM=\"i386-djgpp\" %g
+s%@LDFLAGS@%%g
+s%@LIBS@%-lm %g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${exec_prefix}/libexec%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%${prefix}/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%${prefix}/var%g
+s%@libdir@%${exec_prefix}/lib%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/info%g
+s%@mandir@%${prefix}/man%g
+s%@host@%i386-pc-djgpp%g
+s%@host_alias@%i386-djgpp%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%pc%g
+s%@host_os@%djgpp%g
+s%@CC@%gcc%g
+s%@CPP@%gcc -E%g
+s%@YACC@%bison -y%g
+s%@RANLIB@%ranlib%g
+s%@AR@%ar%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@SET_MAKE@%%g
+s%@LIBOBJS@% crypt.o flock.o snprintf.o%g
+s%@ALLOCA@%%g
+s%@DLDFLAGS@%%g
+s%@STATIC@%%g
+s%@CCDLFLAGS@%%g
+s%@LDSHARED@%ld%g
+s%@DLEXT@%o%g
+s%@STRIP@%strip%g
+s%@EXTSTATIC@%%g
+s%@binsuffix@%.exe%g
+s%@setup@%Setup%g
+s%@LIBRUBY@%libruby.a%g
+s%@LIBRUBYARG@%libruby.a%g
+s%@SOLIBS@%%g
+s%@srcdir%.%g
+s%@arch@%i386-djgpp%g
+ac_given_srcdir=.
diff --git a/configure b/configure
index dd18efc8b4..31a40f05e8 100644
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12
+# Generated automatically using autoconf version 2.12.2
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
@@ -16,7 +16,7 @@ ac_help="$ac_help
ac_help="$ac_help
--disable-thread never use user-level thread"
ac_help="$ac_help
---enable-fat-binary build a NeXT Multi Architecture Binary. "
+--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. "
ac_help="$ac_help
--with-dln-a-out use dln_a_out if possible"
ac_help="$ac_help
@@ -59,6 +59,7 @@ mandir='${prefix}/man'
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12
@@ -342,7 +343,7 @@ EOF
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.12"
+ echo "configure generated by autoconf version 2.12.2"
exit 0 ;;
-with-* | --with-*)
@@ -512,9 +513,11 @@ ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
+ac_exeext=
+ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
@@ -562,7 +565,7 @@ fi
if test $rb_thread = yes; then
cat >> confdefs.h <<\EOF
-#define THREAD 1
+#define USE_THREAD 1
EOF
fi
@@ -588,33 +591,32 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# Make sure we can run config.sub.
-if $ac_config_sub sun4 >/dev/null 2>&1; then :
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:597: checking host system type" >&5
+echo "configure:600: checking host system type" >&5
host_alias=$host
case "$host_alias" in
NONE)
case $nonopt in
NONE)
- if host_alias=`$ac_config_guess`; then :
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
fi ;;
*) host_alias=$nonopt ;;
esac ;;
esac
-host=`$ac_config_sub $host_alias`
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
-
fat_binary=no
# Check whether --enable-fat-binary or --disable-fat-binary was given.
if test "${enable_fat_binary+set}" = set; then
@@ -622,18 +624,38 @@ if test "${enable_fat_binary+set}" = set; then
fat_binary=$enableval
fi
-if test "$fat_binary" = yes ; then
+ if test "$fat_binary" = yes ; then
echo $ac_n "checking target architecture ""... $ac_c" 1>&6
-echo "configure:629: checking target architecture " >&5
+echo "configure:631: checking target architecture " >&5
- if test "$TARGET_ARCHS" = "" ; then
- if test `/usr/bin/arch` = "m68k" ; then
- TARGET_ARCHS="m68k i486"
+ case "$host_os" in
+ rhapsody*)
+ echo -n "MacOS X Server: "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
+ ;;
+ nextstep*|openstep*)
+ echo -n "NeXTSTEP/OPENSTEP: "
+
+ if test "$host_os" = "rhapsody" ; then
+ echo -n "Rhapsody: "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i486"
+ fi
else
- TARGET_ARCHS="m68k `/usr/bin/arch`"
+ echo -n "NeXTSTEP/OPENSTEP: "
+ if test "$TARGET_ARCHS" = "" ; then
+ if test `/usr/bin/arch` = "m68k" ; then
+ TARGET_ARCHS="m68k i486"
+ else # Black and Native one
+ TARGET_ARCHS="m68k `/usr/bin/arch`"
+ fi
+ fi
fi
- fi
+ ;;
+ esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS
for archs in $TARGET_ARCHS
do
@@ -647,7 +669,6 @@ EOF
echo "."
fi
-
if test "$program_transform_name" = s,x,x,; then
program_transform_name=
else
@@ -671,15 +692,16 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:675: checking for $ac_word" >&5
+echo "configure:696: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="gcc"
@@ -700,16 +722,17 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:704: checking for $ac_word" >&5
+echo "configure:726: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- for ac_dir in $PATH; do
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
@@ -744,25 +767,61 @@ else
echo "$ac_t""no" 1>&6
fi
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:777: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:752: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:809: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
-cat > conftest.$ac_ext <<EOF
-#line 762 "configure"
+cat > conftest.$ac_ext << EOF
+
+#line 820 "configure"
#include "confdefs.h"
+
main(){return(0);}
EOF
-if { (eval echo configure:766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -776,18 +835,24 @@ else
ac_cv_prog_cc_works=no
fi
rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:786: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:851: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:791: checking whether we are using GNU C" >&5
+echo "configure:856: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -796,7 +861,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:800: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:865: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -807,11 +872,15 @@ echo "$ac_t""$ac_cv_prog_gcc" 1>&6
if test $ac_cv_prog_gcc = yes; then
GCC=yes
- ac_test_CFLAGS="${CFLAGS+set}"
- ac_save_CFLAGS="$CFLAGS"
- CFLAGS=
- echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:815: checking whether ${CC-cc} accepts -g" >&5
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:884: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -826,20 +895,24 @@ rm -f conftest*
fi
echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
- if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
- elif test $ac_cv_prog_cc_g = yes; then
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
- CFLAGS="-O2"
+ CFLAGS="-g"
fi
else
- GCC=
- test "${CFLAGS+set}" = set || CFLAGS="-g"
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:843: checking how to run the C preprocessor" >&5
+echo "configure:916: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -854,14 +927,14 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 858 "configure"
+#line 931 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:864: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:937: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
else
@@ -871,14 +944,31 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 875 "configure"
+#line 948 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:954: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 965 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:881: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:971: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
else
@@ -891,6 +981,8 @@ fi
rm -f conftest*
fi
rm -f conftest*
+fi
+rm -f conftest*
ac_cv_prog_CPP="$CPP"
fi
CPP="$ac_cv_prog_CPP"
@@ -901,13 +993,13 @@ echo "$ac_t""$CPP" 1>&6
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:905: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:997: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
-#line 911 "configure"
+#line 1003 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
@@ -925,7 +1017,7 @@ rm -f conftest*
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 929 "configure"
+#line 1021 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
@@ -951,15 +1043,16 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:955: checking for $ac_word" >&5
+echo "configure:1047: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$YACC"; then
ac_cv_prog_YACC="$YACC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_YACC="$ac_prog"
@@ -983,15 +1076,16 @@ test -n "$YACC" || YACC="yacc"
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:987: checking for $ac_word" >&5
+echo "configure:1080: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_RANLIB="ranlib"
@@ -1015,15 +1109,16 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1019: checking for $ac_word" >&5
+echo "configure:1113: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_AR="$ac_prog"
@@ -1051,28 +1146,30 @@ test -n "$AR" || AR="ar"
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1059: checking for a BSD compatible install" >&5
+echo "configure:1155: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
for ac_dir in $PATH; do
# Account for people who put trailing slashes in PATH elements.
case "$ac_dir/" in
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
- for ac_prog in ginstall installbsd scoinst install; do
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
if test -f $ac_dir/$ac_prog; then
if test $ac_prog = install &&
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
- # OSF/1 installbsd also uses dspmsg, but is usable.
:
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
@@ -1102,10 +1199,12 @@ echo "$ac_t""$INSTALL" 1>&6
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1109: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:1208: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1135,18 +1234,18 @@ fi
# checks for UNIX variants that set C preprocessor variables
ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
-echo "configure:1139: checking for minix/config.h" >&5
+echo "configure:1238: checking for minix/config.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1144 "configure"
+#line 1243 "configure"
#include "confdefs.h"
#include <minix/config.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1248: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
@@ -1183,13 +1282,243 @@ EOF
fi
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:1287: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1295 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(int));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:1326: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1334 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(long));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_long=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+echo $ac_n "checking size of void*""... $ac_c" 1>&6
+echo "configure:1365: checking size of void*" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_voidp'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1373 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(void*));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1384: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_voidp=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_voidp=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_voidp" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_VOIDP $ac_cv_sizeof_voidp
+EOF
+
+
+
+echo $ac_n "checking for prototypes""... $ac_c" 1>&6
+echo "configure:1405: checking for prototypes" >&5
+if eval "test \"`echo '$''{'rb_cv_have_prototypes'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1410 "configure"
+#include "confdefs.h"
+int foo(int x) { return 0; }
+int main() {
+return foo(10);
+; return 0; }
+EOF
+if { (eval echo configure:1417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rb_cv_have_prototypes=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ rb_cv_have_prototypes=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$rb_cv_have_prototypes" 1>&6
+if test "$rb_cv_have_prototypes" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_PROTOTYPES 1
+EOF
+
+fi
+
+echo $ac_n "checking for variable length prototypes and stdarg.h""... $ac_c" 1>&6
+echo "configure:1438: checking for variable length prototypes and stdarg.h" >&5
+if eval "test \"`echo '$''{'rb_cv_stdarg'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1443 "configure"
+#include "confdefs.h"
+
+#include <stdarg.h>
+int foo(int x, ...) {
+ va_list va;
+ va_start(va, x);
+ va_arg(va, int);
+ va_arg(va, char *);
+ va_arg(va, double);
+ return 0;
+}
+
+int main() {
+return foo(10, "", 3.14);
+; return 0; }
+EOF
+if { (eval echo configure:1460: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rb_cv_stdarg=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ rb_cv_stdarg=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$rb_cv_stdarg" 1>&6
+if test "$rb_cv_stdarg" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STDARG_PROTOTYPES 1
+EOF
+
+fi
+
+echo $ac_n "checking for gcc attribute noreturn""... $ac_c" 1>&6
+echo "configure:1481: checking for gcc attribute noreturn" >&5
+if eval "test \"`echo '$''{'rb_cv_have_attr_noreturn'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1486 "configure"
+#include "confdefs.h"
+void exit(int x) __attribute__ ((noreturn));
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1493: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rb_cv_have_attr_noreturn=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ rb_cv_have_attr_noreturn=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$rb_cv_have_attr_noreturn" 1>&6
+if test "$rb_cv_have_attr_noreturn" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ATTR_NORETURN 1
+EOF
+
+fi
+
case "$host_os" in
nextstep*) ;;
+openstep*) ;;
+rhapsody*) ;;
human*) ;;
+beos*) ;;
*) LIBS="-lm $LIBS";;
esac
echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:1193: checking for crypt in -lcrypt" >&5
+echo "configure:1522: checking for crypt in -lcrypt" >&5
ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1197,7 +1526,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1201 "configure"
+#line 1530 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1208,7 +1537,7 @@ int main() {
crypt()
; return 0; }
EOF
-if { (eval echo configure:1212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1236,7 +1565,7 @@ else
fi
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:1240: checking for dlopen in -ldl" >&5
+echo "configure:1569: checking for dlopen in -ldl" >&5
ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1244,7 +1573,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1248 "configure"
+#line 1577 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1255,7 +1584,7 @@ int main() {
dlopen()
; return 0; }
EOF
-if { (eval echo configure:1259: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1283,7 +1612,7 @@ else
fi
# Dynamic linking for SunOS/Solaris and SYSV
echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "configure:1287: checking for shl_load in -ldld" >&5
+echo "configure:1616: checking for shl_load in -ldld" >&5
ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1291,7 +1620,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldld $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1295 "configure"
+#line 1624 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1302,7 +1631,7 @@ int main() {
shl_load()
; return 0; }
EOF
-if { (eval echo configure:1306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1635: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1329,18 +1658,65 @@ else
echo "$ac_t""no" 1>&6
fi
# Dynamic linking for HP-UX
+echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6
+echo "configure:1663: checking for setlocale in -lxpg4" >&5
+ac_lib_var=`echo xpg4'_'setlocale | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lxpg4 $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1671 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char setlocale();
+
+int main() {
+setlocale()
+; return 0; }
+EOF
+if { (eval echo configure:1682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo xpg4 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lxpg4 $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+ # FreeBSD needs this
ac_header_dirent=no
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1339: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1715: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1344 "configure"
+#line 1720 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
@@ -1348,7 +1724,7 @@ int main() {
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:1352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
@@ -1373,7 +1749,7 @@ done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1377: checking for opendir in -ldir" >&5
+echo "configure:1753: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1381,7 +1757,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1385 "configure"
+#line 1761 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1392,7 +1768,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1772: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1414,7 +1790,7 @@ fi
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1418: checking for opendir in -lx" >&5
+echo "configure:1794: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1422,7 +1798,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1426 "configure"
+#line 1802 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1433,7 +1809,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1437: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1456,12 +1832,12 @@ fi
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1460: checking for ANSI C header files" >&5
+echo "configure:1836: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1465 "configure"
+#line 1841 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1469,8 +1845,8 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1473: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
ac_cv_header_stdc=yes
@@ -1486,7 +1862,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1490 "configure"
+#line 1866 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1504,7 +1880,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1508 "configure"
+#line 1884 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1525,7 +1901,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 1529 "configure"
+#line 1905 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1536,7 +1912,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1561,22 +1937,22 @@ fi
for ac_hdr in stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \
sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\
- syscall.h a.out.h string.h utime.h memory.h
+ syscall.h a.out.h string.h utime.h memory.h direct.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1569: checking for $ac_hdr" >&5
+echo "configure:1945: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1574 "configure"
+#line 1950 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1579: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1955: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
@@ -1603,12 +1979,12 @@ done
echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:1607: checking for uid_t in sys/types.h" >&5
+echo "configure:1983: checking for uid_t in sys/types.h" >&5
if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1612 "configure"
+#line 1988 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
@@ -1637,12 +2013,12 @@ EOF
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1641: checking for size_t" >&5
+echo "configure:2017: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1646 "configure"
+#line 2022 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1651,7 +2027,7 @@ else
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
ac_cv_type_size_t=yes
else
@@ -1670,12 +2046,12 @@ EOF
fi
echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
-echo "configure:1674: checking for st_blksize in struct stat" >&5
+echo "configure:2050: checking for st_blksize in struct stat" >&5
if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1679 "configure"
+#line 2055 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -1683,7 +2059,7 @@ int main() {
struct stat s; s.st_blksize;
; return 0; }
EOF
-if { (eval echo configure:1687: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2063: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_blksize=yes
else
@@ -1705,12 +2081,12 @@ fi
save_LIBOJBS="$LIBOBJS"
echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
-echo "configure:1709: checking for st_blocks in struct stat" >&5
+echo "configure:2085: checking for st_blocks in struct stat" >&5
if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1714 "configure"
+#line 2090 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -1718,7 +2094,7 @@ int main() {
struct stat s; s.st_blocks;
; return 0; }
EOF
-if { (eval echo configure:1722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2098: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_blocks=yes
else
@@ -1737,17 +2113,17 @@ if test $ac_cv_struct_st_blocks = yes; then
EOF
else
- LIBOBJS="$LIBOBJS fileblocks.o"
+ LIBOBJS="$LIBOBJS fileblocks.${ac_objext}"
fi
LIBOBJS="$save_LIBOBJS"
echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
-echo "configure:1746: checking for st_rdev in struct stat" >&5
+echo "configure:2122: checking for st_rdev in struct stat" >&5
if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1751 "configure"
+#line 2127 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -1755,7 +2131,7 @@ int main() {
struct stat s; s.st_rdev;
; return 0; }
EOF
-if { (eval echo configure:1759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_rdev=yes
else
@@ -1776,165 +2152,8 @@ EOF
fi
-echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:1781: checking size of short" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1789 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(short));
- exit(0);
-}
-EOF
-if { (eval echo configure:1800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_short=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_short=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_short" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-EOF
-
-
-echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:1820: checking size of int" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1828 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(int));
- exit(0);
-}
-EOF
-if { (eval echo configure:1839: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_int=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_int=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_int" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-EOF
-
-
-echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:1859: checking size of long" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1867 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(long));
- exit(0);
-}
-EOF
-if { (eval echo configure:1878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_long=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_long=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_long" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-EOF
-
-
-echo $ac_n "checking size of void*""... $ac_c" 1>&6
-echo "configure:1898: checking size of void*" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_voidp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1906 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(void*));
- exit(0);
-}
-EOF
-if { (eval echo configure:1917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_voidp=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_voidp=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_voidp" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_VOIDP $ac_cv_sizeof_voidp
-EOF
-
-
-
echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:1938: checking type of array argument to getgroups" >&5
+echo "configure:2157: checking type of array argument to getgroups" >&5
if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1942,7 +2161,7 @@ else
ac_cv_type_getgroups=cross
else
cat > conftest.$ac_ext <<EOF
-#line 1946 "configure"
+#line 2165 "configure"
#include "confdefs.h"
/* Thanks to Mike Rendell for this test. */
@@ -1967,7 +2186,7 @@ main()
}
EOF
-if { (eval echo configure:1971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_type_getgroups=gid_t
else
@@ -1981,7 +2200,7 @@ fi
if test $ac_cv_type_getgroups = cross; then
cat > conftest.$ac_ext <<EOF
-#line 1985 "configure"
+#line 2204 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
@@ -2005,12 +2224,12 @@ EOF
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2009: checking return type of signal handlers" >&5
+echo "configure:2228: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2014 "configure"
+#line 2233 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -2027,7 +2246,7 @@ int main() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2031: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2250: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -2048,19 +2267,19 @@ EOF
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:2052: checking for working alloca.h" >&5
+echo "configure:2271: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2057 "configure"
+#line 2276 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -2081,25 +2300,30 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:2085: checking for alloca" >&5
+echo "configure:2304: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2090 "configure"
+#line 2309 "configure"
#include "confdefs.h"
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
-# if HAVE_ALLOCA_H
-# include <alloca.h>
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
# else
-# ifdef _AIX
- #pragma alloca
+# if HAVE_ALLOCA_H
+# include <alloca.h>
# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
+# endif
# endif
# endif
# endif
@@ -2109,7 +2333,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:2113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@@ -2134,19 +2358,19 @@ if test $ac_cv_func_alloca_works = no; then
# that cause trouble. Some versions do not even contain alloca or
# contain a buggy version. If you still want to use their alloca,
# use ar to extract alloca.o from them instead of compiling alloca.c.
- ALLOCA=alloca.o
+ ALLOCA=alloca.${ac_objext}
cat >> confdefs.h <<\EOF
#define C_ALLOCA 1
EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:2145: checking whether alloca needs Cray hooks" >&5
+echo "configure:2369: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2150 "configure"
+#line 2374 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -2171,12 +2395,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2175: checking for $ac_func" >&5
+echo "configure:2399: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2180 "configure"
+#line 2404 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2199,7 +2423,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2226,7 +2450,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:2230: checking stack direction for C alloca" >&5
+echo "configure:2454: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2234,7 +2458,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 2238 "configure"
+#line 2462 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -2253,7 +2477,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:2257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@@ -2275,12 +2499,12 @@ EOF
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:2279: checking for pid_t" >&5
+echo "configure:2503: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2284 "configure"
+#line 2508 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -2289,7 +2513,7 @@ else
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
ac_cv_type_pid_t=yes
else
@@ -2309,18 +2533,18 @@ fi
ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
-echo "configure:2313: checking for vfork.h" >&5
+echo "configure:2537: checking for vfork.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2318 "configure"
+#line 2542 "configure"
#include "confdefs.h"
#include <vfork.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2323: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:2547: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
@@ -2344,18 +2568,18 @@ else
fi
echo $ac_n "checking for working vfork""... $ac_c" 1>&6
-echo "configure:2348: checking for working vfork" >&5
+echo "configure:2572: checking for working vfork" >&5
if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
echo $ac_n "checking for vfork""... $ac_c" 1>&6
-echo "configure:2354: checking for vfork" >&5
+echo "configure:2578: checking for vfork" >&5
if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2359 "configure"
+#line 2583 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vfork(); below. */
@@ -2378,7 +2602,7 @@ vfork();
; return 0; }
EOF
-if { (eval echo configure:2382: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2606: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vfork=yes"
else
@@ -2397,9 +2621,10 @@ else
echo "$ac_t""no" 1>&6
fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
else
cat > conftest.$ac_ext <<EOF
-#line 2403 "configure"
+#line 2628 "configure"
#include "confdefs.h"
/* Thanks to Paul Eggert for this test. */
#include <stdio.h>
@@ -2494,7 +2719,7 @@ main() {
}
}
EOF
-if { (eval echo configure:2498: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_vfork_works=yes
else
@@ -2516,16 +2741,52 @@ EOF
fi
-for ac_func in dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strstr strtoul strdup crypt flock
+echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
+echo "configure:2746: checking for 8-bit clean memcmp" >&5
+if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_memcmp_clean=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2754 "configure"
+#include "confdefs.h"
+
+main()
+{
+ char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+ exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+}
+
+EOF
+if { (eval echo configure:2764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_memcmp_clean=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_memcmp_clean=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
+test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
+
+for ac_func in dup2 memmove mkdir strcasecmp strerror strftime\
+ strchr strstr strtoul strdup crypt flock vsnprintf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2524: checking for $ac_func" >&5
+echo "configure:2785: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2529 "configure"
+#line 2790 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2548,7 +2809,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2569,24 +2830,24 @@ EOF
else
echo "$ac_t""no" 1>&6
-LIBOBJS="$LIBOBJS ${ac_func}.o"
+LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
fi
done
-for ac_func in fmod killpg random wait4 waitpid syscall getcwd\
+for ac_func in fmod killpg drand48 random wait4 waitpid syscall getcwd\
truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp
+ setpgrp2 getpgid setpgid getgroups getpriority\
+ dlopen sigprocmask sigaction _setjmp setpgrp setsid
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2585: checking for $ac_func" >&5
+echo "configure:2846: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2590 "configure"
+#line 2851 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2609,7 +2870,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2635,12 +2896,12 @@ done
if test "$ac_cv_func_strftime" = no; then
echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:2639: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:2900: checking whether struct tm is in sys/time.h or time.h" >&5
if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2644 "configure"
+#line 2905 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <time.h>
@@ -2648,7 +2909,7 @@ int main() {
struct tm *tp; tp->tm_sec;
; return 0; }
EOF
-if { (eval echo configure:2652: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2913: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm=time.h
else
@@ -2669,12 +2930,12 @@ EOF
fi
echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
-echo "configure:2673: checking for tm_zone in struct tm" >&5
+echo "configure:2934: checking for tm_zone in struct tm" >&5
if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2678 "configure"
+#line 2939 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_cv_struct_tm>
@@ -2682,7 +2943,7 @@ int main() {
struct tm tm; tm.tm_zone;
; return 0; }
EOF
-if { (eval echo configure:2686: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2947: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm_zone=yes
else
@@ -2702,12 +2963,12 @@ EOF
else
echo $ac_n "checking for tzname""... $ac_c" 1>&6
-echo "configure:2706: checking for tzname" >&5
+echo "configure:2967: checking for tzname" >&5
if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2711 "configure"
+#line 2972 "configure"
#include "confdefs.h"
#include <time.h>
#ifndef tzname /* For SGI. */
@@ -2717,7 +2978,7 @@ int main() {
atoi(*tzname);
; return 0; }
EOF
-if { (eval echo configure:2721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_var_tzname=yes
else
@@ -2739,14 +3000,14 @@ EOF
fi
cat > conftest.$ac_ext <<EOF
-#line 2743 "configure"
+#line 3004 "configure"
#include "confdefs.h"
int main() {
extern int daylight; int i = daylight;
; return 0; }
EOF
-if { (eval echo configure:2750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3011: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define HAVE_DAYLIGHT 1
@@ -2766,7 +3027,7 @@ EOF
else
echo $ac_n "checking for BSD signal semantics""... $ac_c" 1>&6
-echo "configure:2770: checking for BSD signal semantics" >&5
+echo "configure:3031: checking for BSD signal semantics" >&5
if eval "test \"`echo '$''{'rb_cv_bsd_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2774,7 +3035,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 2778 "configure"
+#line 3039 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -2796,7 +3057,7 @@ main()
}
EOF
-if { (eval echo configure:2800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_bsd_signal=yes
else
@@ -2830,19 +3091,19 @@ EOF
else
echo $ac_n "checking whether getpgrp() has arg""... $ac_c" 1>&6
-echo "configure:2834: checking whether getpgrp() has arg" >&5
+echo "configure:3095: checking whether getpgrp() has arg" >&5
if eval "test \"`echo '$''{'rb_cv_bsdgetpgrp'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2839 "configure"
+#line 3100 "configure"
#include "confdefs.h"
#include <unistd.h>
int main() {
getpgrp(0);
; return 0; }
EOF
-if { (eval echo configure:2846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3107: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_bsdgetpgrp=yes
else
@@ -2863,19 +3124,19 @@ EOF
fi
echo $ac_n "checking whether setpgrp() has args""... $ac_c" 1>&6
-echo "configure:2867: checking whether setpgrp() has args" >&5
+echo "configure:3128: checking whether setpgrp() has args" >&5
if eval "test \"`echo '$''{'rb_cv_bsdsetpgrp'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2872 "configure"
+#line 3133 "configure"
#include "confdefs.h"
#include <unistd.h>
int main() {
setpgrp(1, 1);
; return 0; }
EOF
-if { (eval echo configure:2879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3140: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_bsdsetpgrp=yes
else
@@ -2897,14 +3158,14 @@ EOF
fi
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:2901: checking whether byte ordering is bigendian" >&5
+echo "configure:3162: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
-#line 2908 "configure"
+#line 3169 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -2915,11 +3176,11 @@ int main() {
#endif
; return 0; }
EOF
-if { (eval echo configure:2919: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3180: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
-#line 2923 "configure"
+#line 3184 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -2930,7 +3191,7 @@ int main() {
#endif
; return 0; }
EOF
-if { (eval echo configure:2934: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3195: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@@ -2950,7 +3211,7 @@ if test "$cross_compiling" = yes; then
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 2954 "configure"
+#line 3215 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@@ -2963,7 +3224,7 @@ main () {
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
-if { (eval echo configure:2967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
@@ -2987,14 +3248,14 @@ EOF
fi
echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
-echo "configure:2991: checking whether char is unsigned" >&5
+echo "configure:3252: checking whether char is unsigned" >&5
if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$GCC" = yes; then
# GCC predefines this symbol on systems where it applies.
cat > conftest.$ac_ext <<EOF
-#line 2998 "configure"
+#line 3259 "configure"
#include "confdefs.h"
#ifdef __CHAR_UNSIGNED__
yes
@@ -3016,7 +3277,7 @@ if test "$cross_compiling" = yes; then
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3020 "configure"
+#line 3281 "configure"
#include "confdefs.h"
/* volatile prevents gcc2 from optimizing the test away on sparcs. */
#if !defined(__STDC__) || __STDC__ != 1
@@ -3026,7 +3287,7 @@ main() {
volatile char c = 255; exit(c < 0);
}
EOF
-if { (eval echo configure:3030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3291: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_char_unsigned=yes
else
@@ -3050,20 +3311,68 @@ EOF
fi
+echo $ac_n "checking whether right shift preserve sign bit""... $ac_c" 1>&6
+echo "configure:3316: checking whether right shift preserve sign bit" >&5
+if eval "test \"`echo '$''{'rb_cv_rshift_sign'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3324 "configure"
+#include "confdefs.h"
+
+int
+main()
+{
+ if (-1==(-1>>1))
+ return 0;
+ return 1;
+}
+
+EOF
+if { (eval echo configure:3336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ rb_cv_rshift_sign=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ rb_cv_rshift_sign=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+ echo "$ac_t""$rb_cv_rshift_sign" 1>&6
+if test "$rb_cv_rshift_sign" = yes; then
+ cat >> confdefs.h <<\EOF
+#define RSHIFT(x,y) ((x)>>y)
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define RSHIFT(x,y) (((x)<0) ? ~((~(x))>>y) : (x)>>y)
+EOF
+
+fi
+
echo $ac_n "checking count field in FILE structures""... $ac_c" 1>&6
-echo "configure:3055: checking count field in FILE structures" >&5
+echo "configure:3364: checking count field in FILE structures" >&5
if eval "test \"`echo '$''{'rb_cv_fcnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3060 "configure"
+#line 3369 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->_cnt = 0;
; return 0; }
EOF
-if { (eval echo configure:3067: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3376: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="_cnt"
else
@@ -3073,14 +3382,14 @@ fi
rm -f conftest*
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3077 "configure"
+#line 3386 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->__cnt = 0;
; return 0; }
EOF
-if { (eval echo configure:3084: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3393: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="__cnt"
else
@@ -3091,14 +3400,14 @@ rm -f conftest*
fi
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3095 "configure"
+#line 3404 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->_r = 0;
; return 0; }
EOF
-if { (eval echo configure:3102: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="_r"
else
@@ -3109,14 +3418,14 @@ rm -f conftest*
fi
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3113 "configure"
+#line 3422 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->readCount = 0;
; return 0; }
EOF
-if { (eval echo configure:3120: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3429: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="readCount"
else
@@ -3139,102 +3448,6 @@ EOF
fi
-if test "$ac_cv_func_getpwent" = yes; then
- echo $ac_n "checking struct passwd""... $ac_c" 1>&6
-echo "configure:3145: checking struct passwd" >&5
- cat > conftest.$ac_ext <<EOF
-#line 3147 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_change" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_CHANGE 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3162 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_quota" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_QUOTA 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3177 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_age" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_AGE 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3192 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_class" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_CLASS 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3207 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_comment" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_COMMENT 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3222 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_expire" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_EXPIRE 1
-EOF
-
-fi
-rm -f conftest*
-
- echo "$ac_t""done" 1>&6
-fi
-
# Check whether --with-dln-a-out or --without-dln-a-out was given.
if test "${with_dln_a_out+set}" = set; then
withval="$with_dln_a_out"
@@ -3251,7 +3464,7 @@ fi
case "$host_os" in
linux*)
echo $ac_n "checking whether ELF binaries are produced""... $ac_c" 1>&6
-echo "configure:3255: checking whether ELF binaries are produced" >&5
+echo "configure:3468: checking whether ELF binaries are produced" >&5
if eval "test \"`echo '$''{'rb_cv_linux_elf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3259,7 +3472,7 @@ else
:
else
cat > conftest.$ac_ext <<EOF
-#line 3263 "configure"
+#line 3476 "configure"
#include "confdefs.h"
/* Test for whether ELF binaries are produced */
@@ -3279,7 +3492,7 @@ main() {
}
EOF
-if { (eval echo configure:3283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_linux_elf=yes
else
@@ -3309,11 +3522,14 @@ STATIC=
if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=unknown
echo $ac_n "checking whether OS depend dynamic link works""... $ac_c" 1>&6
-echo "configure:3313: checking whether OS depend dynamic link works" >&5
+echo "configure:3526: checking whether OS depend dynamic link works" >&5
if test "$GCC" = yes; then
case "$host_os" in
nextstep*) ;;
+ openstep*) ;;
+ rhapsody*) ;;
human*) ;;
+ cygwin*) CCDLFLAGS=-DDLLIMPORT;;
*) CCDLFLAGS=-fpic;;
esac
else
@@ -3343,21 +3559,44 @@ echo "configure:3313: checking whether OS depend dynamic link works" >&5
rb_cv_dlopen=yes ;;
linux*) LDSHARED="gcc -shared"
rb_cv_dlopen=yes ;;
+ freebsd3*) LDSHARED="ld -Bshareable"
+ LDFLAGS="-rdynamic"
+ rb_cv_dlopen=yes ;;
freebsd*) LDSHARED="ld -Bshareable"
rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -Bshareable"
rb_cv_dlopen=yes ;;
- openbsd*) LDSHARED="ld -Bshareable"
+ openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
+ CCDLFLAGS=-fPIC
rb_cv_dlopen=yes ;;
nextstep*) LDSHARED='cc -r'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
+ openstep*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
+ rhapsody*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
rb_cv_dlopen=yes ;;
human*) DLDFLAGS=''
LDSHARED=''
LDFLAGS='' ;;
+ beos*) LDSHARED="ld -xms"
+ case "$host_cpu" in
+ powerpc*)
+ DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
+ ;;
+ *)
+ DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
+ ;;
+ esac
+ rb_cv_dlopen=yes ;;
+ cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb' ;;
*) LDSHARED='ld' ;;
esac
echo "$ac_t""$rb_cv_dlopen" 1>&6
@@ -3367,13 +3606,13 @@ dln_a_out_works=no
if test "$ac_cv_header_a_out_h" = yes; then
if test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown; then
echo $ac_n "checking whether matz's dln works""... $ac_c" 1>&6
-echo "configure:3371: checking whether matz's dln works" >&5
+echo "configure:3610: checking whether matz's dln works" >&5
cat confdefs.h > config.h
if eval "test \"`echo '$''{'rb_cv_dln_a_out'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3377 "configure"
+#line 3616 "configure"
#include "confdefs.h"
#define USE_DLN_A_OUT
@@ -3383,7 +3622,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:3387: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3626: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_dln_a_out=yes
else
@@ -3430,6 +3669,21 @@ EOF
#define DLEXT ".o"
EOF
;;
+ openstep*) DLEXT=bundle
+ cat >> confdefs.h <<\EOF
+#define DLEXT ".bundle"
+EOF
+;;
+ rhapsody*) DLEXT=bundle
+ cat >> confdefs.h <<\EOF
+#define DLEXT ".bundle"
+EOF
+;;
+ cygwin*) DLEXT=dll
+ cat >> confdefs.h <<\EOF
+#define DLEXT ".dll"
+EOF
+;;
*) DLEXT=so
cat >> confdefs.h <<\EOF
#define DLEXT ".so"
@@ -3449,6 +3703,10 @@ case "$host_os" in
STRIP='strip -S -x';;
nextstep*)
STRIP='strip -A -n';;
+ openstep*)
+ STRIP='strip -A -n';;
+ rhapsody*)
+ STRIP='strip -A -n';;
esac
EXTSTATIC=
@@ -3466,7 +3724,7 @@ fi
case "$host_os" in
human*)
echo $ac_n "checking for _harderr in -lsignal""... $ac_c" 1>&6
-echo "configure:3470: checking for _harderr in -lsignal" >&5
+echo "configure:3728: checking for _harderr in -lsignal" >&5
ac_lib_var=`echo signal'_'_harderr | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3474,7 +3732,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsignal $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3478 "configure"
+#line 3736 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3485,7 +3743,7 @@ int main() {
_harderr()
; return 0; }
EOF
-if { (eval echo configure:3489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3513,7 +3771,7 @@ else
fi
echo $ac_n "checking for hmemset in -lhmem""... $ac_c" 1>&6
-echo "configure:3517: checking for hmemset in -lhmem" >&5
+echo "configure:3775: checking for hmemset in -lhmem" >&5
ac_lib_var=`echo hmem'_'hmemset | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3521,7 +3779,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lhmem $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3525 "configure"
+#line 3783 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3532,7 +3790,7 @@ int main() {
hmemset()
; return 0; }
EOF
-if { (eval echo configure:3536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3562,12 +3820,12 @@ fi
for ac_func in select
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3566: checking for $ac_func" >&5
+echo "configure:3824: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3571 "configure"
+#line 3829 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3590,7 +3848,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3594: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3615,7 +3873,7 @@ fi
done
echo $ac_n "checking whether PD libc _dtos18 fail to convert big number""... $ac_c" 1>&6
-echo "configure:3619: checking whether PD libc _dtos18 fail to convert big number" >&5
+echo "configure:3877: checking whether PD libc _dtos18 fail to convert big number" >&5
if eval "test \"`echo '$''{'rb_cv_missing__dtos18'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3623,7 +3881,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3627 "configure"
+#line 3885 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3635,7 +3893,7 @@ main ()
}
EOF
-if { (eval echo configure:3639: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_missing__dtos18=yes
else
@@ -3657,7 +3915,7 @@ EOF
fi
echo $ac_n "checking whether PD libc fconvert fail to round""... $ac_c" 1>&6
-echo "configure:3661: checking whether PD libc fconvert fail to round" >&5
+echo "configure:3919: checking whether PD libc fconvert fail to round" >&5
if eval "test \"`echo '$''{'rb_cv_missing_fconvert'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3665,7 +3923,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3669 "configure"
+#line 3927 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3678,7 +3936,7 @@ main ()
}
EOF
-if { (eval echo configure:3682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_missing_fconvert=yes
else
@@ -3704,6 +3962,10 @@ EOF
binsuffix=.x
setup=Setup.x68
;;
+ cygwin*)
+ binsuffix=.exe
+ setup=Setup
+ ;;
*)
binsuffix=
setup=Setup
@@ -3712,16 +3974,76 @@ esac
+
+
+
if test "$prefix" = NONE; then
prefix=$ac_default_prefix
fi
if test "$fat_binary" = yes ; then
- CFLAGS="$CFLAGS -pipe $ARCH_FLAG"
+ CFLAGS="$CFLAGS $ARCH_FLAG"
+fi
+
+LIBRUBY='libruby.a'
+LIBRUBYARG='libruby.a'
+SOLIBS=
+if test "$host_os" = "beos"; then
+ CFLAGS="$CFLAGS -relax_pointers"
+ LIBRUBY='libruby.so'
+ LIBRUBYARG='-lruby'
+ SOLIBS='-lnet'
+ echo creating ruby.def
+ case "$host_cpu" in
+ powerpc*)
+ cp beos/ruby.def.in ruby.exp
+ ;;
+ *)
+ echo EXPORTS > ruby.def
+ cat beos/ruby.def.in >> ruby.def
+ ;;
+ esac
fi
+if test "$enable_shared" = 'yes'; then
+ LIBRUBY='libruby.so'
+ LIBRUBYARG='-L./ -lruby'
+fi
+
+case "$host_os" in
+ nextstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ openstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ rhasody*)
+ CFLAGS="$CFLAGS -pipe -no-precomp"
+ ;;
+ *)
+ ;;
+esac
+
+
+
+
+
+
+ri_prefix=
+test "$program_prefix" != NONE &&
+ ri_prefix=$program_prefix
+
+ri_suffix=
+test "$program_suffix" != NONE &&
+ ri_suffix=$program_suffix
+
+RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
cat >> confdefs.h <<EOF
-#define RUBY_LIB "${prefix}/lib/ruby"
+#define RUBY_LIB "${prefix}/lib/${RUBY_INSTALL_NAME}"
+EOF
+
+cat >> confdefs.h <<EOF
+#define RUBY_SITE_LIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby"
EOF
@@ -3729,12 +4051,21 @@ if test "$fat_binary" = yes ; then
arch="fat-${host_os}"
cat >> confdefs.h <<EOF
-#define RUBY_THIN_ARCHLIB "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}"
+#define RUBY_THIN_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}"
+EOF
+
+
+ cat >> confdefs.h <<EOF
+#define RUBY_SITE_THIN_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}"
EOF
cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/ruby/${arch}"
+#define RUBY_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}"
+EOF
+
+ cat >> confdefs.h <<EOF
+#define RUBY_SITE_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}"
EOF
cat >> confdefs.h <<EOF
@@ -3744,7 +4075,11 @@ EOF
else
arch="${host_cpu}-${host_os}"
cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/ruby/${arch}"
+#define RUBY_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}"
+EOF
+
+ cat >> confdefs.h <<EOF
+#define RUBY_SITE_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}"
EOF
cat >> confdefs.h <<EOF
@@ -3779,7 +4114,7 @@ EOF
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
- case `(ac_space=' '; set) 2>&1` in
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
*ac_space=\ *)
# `set' does not quote correctly, so add quotes (double-quote substitution
# turns \\\\ into \\, and sed turns \\ into \).
@@ -3858,7 +4193,7 @@ do
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.12"
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
@@ -3878,9 +4213,11 @@ sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
+s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
@@ -3910,6 +4247,7 @@ s%@YACC@%$YACC%g
s%@RANLIB@%$RANLIB%g
s%@AR@%$AR%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@SET_MAKE@%$SET_MAKE%g
s%@LIBOBJS@%$LIBOBJS%g
@@ -3923,6 +4261,9 @@ s%@STRIP@%$STRIP%g
s%@EXTSTATIC@%$EXTSTATIC%g
s%@binsuffix@%$binsuffix%g
s%@setup@%$setup%g
+s%@LIBRUBY@%$LIBRUBY%g
+s%@LIBRUBYARG@%$LIBRUBYARG%g
+s%@SOLIBS@%$SOLIBS%g
s%@arch@%$arch%g
CEOF
diff --git a/configure.bat b/configure.bat
index 35f9d4893d..093d43549d 100644
--- a/configure.bat
+++ b/configure.bat
@@ -2,4 +2,5 @@
sed -f top.sed Makefile.in >Makefile
sed -f top.sed ext/extmk.rb.in > ext\extmk.rb
copy ext\Setup.dj ext\Setup
-copy config.dj config.h
+copy config_h.dj config.h
+copy config_s.dj config.status
diff --git a/configure.in b/configure.in
index 567e58cc3e..0477ade03e 100644
--- a/configure.in
+++ b/configure.in
@@ -24,28 +24,47 @@ AC_ARG_ENABLE(thread, [--disable-thread never use user-level thread], [
rb_thread=$enableval
])
if test $rb_thread = yes; then
- AC_DEFINE(THREAD)
+ AC_DEFINE(USE_THREAD)
fi
AC_CANONICAL_HOST
-
dnl checks for fat-binary
fat_binary=no
AC_ARG_ENABLE( fat-binary,
- [--enable-fat-binary build a NeXT Multi Architecture Binary. ],
+ [--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ],
[ fat_binary=$enableval ] )
-if test "$fat_binary" = yes ; then
+ if test "$fat_binary" = yes ; then
AC_MSG_CHECKING( target architecture )
- if test "$TARGET_ARCHS" = "" ; then
- if test `/usr/bin/arch` = "m68k" ; then
- TARGET_ARCHS="m68k i486"
+ case "$host_os" in
+ rhapsody*)
+ echo -n "MacOS X Server: "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
+ ;;
+ nextstep*|openstep*)
+ echo -n "NeXTSTEP/OPENSTEP: "
+
+ if test "$host_os" = "rhapsody" ; then
+ echo -n "Rhapsody: "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i486"
+ fi
else
- TARGET_ARCHS="m68k `/usr/bin/arch`"
+ echo -n "NeXTSTEP/OPENSTEP: "
+ if test "$TARGET_ARCHS" = "" ; then
+ if test `/usr/bin/arch` = "m68k" ; then
+ TARGET_ARCHS="m68k i486"
+ else # Black and Native one
+ TARGET_ARCHS="m68k `/usr/bin/arch`"
+ fi
+ fi
fi
- fi
+ ;;
+ esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS
for archs in $TARGET_ARCHS
do
@@ -56,7 +75,6 @@ if test "$fat_binary" = yes ; then
echo "."
fi
-
AC_ARG_PROGRAM
dnl Checks for programs.
@@ -72,22 +90,70 @@ AC_PROG_MAKE_SET
# checks for UNIX variants that set C preprocessor variables
AC_MINIX
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(void*)
+
+AC_MSG_CHECKING(for prototypes)
+AC_CACHE_VAL(rb_cv_have_prototypes,
+ [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
+ rb_cv_have_prototypes=yes,
+ rb_cv_have_prototypes=no)])
+AC_MSG_RESULT($rb_cv_have_prototypes)
+if test "$rb_cv_have_prototypes" = yes; then
+ AC_DEFINE(HAVE_PROTOTYPES)
+fi
+
+AC_MSG_CHECKING(for variable length prototypes and stdarg.h)
+AC_CACHE_VAL(rb_cv_stdarg,
+ [AC_TRY_COMPILE([
+#include <stdarg.h>
+int foo(int x, ...) {
+ va_list va;
+ va_start(va, x);
+ va_arg(va, int);
+ va_arg(va, char *);
+ va_arg(va, double);
+ return 0;
+}
+], [return foo(10, "", 3.14);],
+ rb_cv_stdarg=yes,
+ rb_cv_stdarg=no)])
+AC_MSG_RESULT($rb_cv_stdarg)
+if test "$rb_cv_stdarg" = yes; then
+ AC_DEFINE(HAVE_STDARG_PROTOTYPES)
+fi
+
+AC_MSG_CHECKING(for gcc attribute noreturn)
+AC_CACHE_VAL(rb_cv_have_attr_noreturn,
+ [AC_TRY_COMPILE([void exit(int x) __attribute__ ((noreturn));], [],
+ rb_cv_have_attr_noreturn=yes,
+ rb_cv_have_attr_noreturn=no)])
+AC_MSG_RESULT($rb_cv_have_attr_noreturn)
+if test "$rb_cv_have_attr_noreturn" = yes; then
+ AC_DEFINE(HAVE_ATTR_NORETURN)
+fi
+
dnl Checks for libraries.
case "$host_os" in
nextstep*) ;;
+openstep*) ;;
+rhapsody*) ;;
human*) ;;
+beos*) ;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
+AC_CHECK_LIB(xpg4, setlocale) # FreeBSD needs this
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \
sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\
- syscall.h a.out.h string.h utime.h memory.h)
+ syscall.h a.out.h string.h utime.h memory.h direct.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -98,23 +164,19 @@ AC_STRUCT_ST_BLOCKS
LIBOBJS="$save_LIBOBJS"
AC_STRUCT_ST_RDEV
-AC_CHECK_SIZEOF(short)
-AC_CHECK_SIZEOF(int)
-AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(void*)
-
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_TYPE_SIGNAL
AC_FUNC_ALLOCA
AC_FUNC_VFORK
-AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strstr strtoul strdup crypt flock)
-AC_CHECK_FUNCS(fmod killpg random wait4 waitpid syscall getcwd\
+AC_FUNC_MEMCMP
+AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strerror strftime\
+ strchr strstr strtoul strdup crypt flock vsnprintf)
+AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd\
truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp)
+ setpgrp2 getpgid setpgid getgroups getpriority\
+ dlopen sigprocmask sigaction _setjmp setpgrp setsid)
if test "$ac_cv_func_strftime" = no; then
AC_STRUCT_TIMEZONE
AC_TRY_LINK([],
@@ -181,6 +243,26 @@ fi
AC_C_BIGENDIAN
AC_CHAR_UNSIGNED
+AC_MSG_CHECKING(whether right shift preserve sign bit)
+AC_CACHE_VAL(rb_cv_rshift_sign,
+ [AC_TRY_RUN([
+int
+main()
+{
+ if (-1==(-1>>1))
+ return 0;
+ return 1;
+}
+],
+ rb_cv_rshift_sign=yes,
+ rb_cv_rshift_sign=no)])
+ AC_MSG_RESULT($rb_cv_rshift_sign)
+if test "$rb_cv_rshift_sign" = yes; then
+ AC_DEFINE(RSHIFT(x,y), ((x)>>y))
+else
+ AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
+fi
+
AC_MSG_CHECKING([count field in FILE structures])
AC_CACHE_VAL(rb_cv_fcnt,
[AC_TRY_COMPILE([#include <stdio.h>],
@@ -205,17 +287,6 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi
-if test "$ac_cv_func_getpwent" = yes; then
- AC_MSG_CHECKING(struct passwd)
- AC_EGREP_HEADER(pw_change, pwd.h, AC_DEFINE(PW_CHANGE))
- AC_EGREP_HEADER(pw_quota, pwd.h, AC_DEFINE(PW_QUOTA))
- AC_EGREP_HEADER(pw_age, pwd.h, AC_DEFINE(PW_AGE))
- AC_EGREP_HEADER(pw_class, pwd.h, AC_DEFINE(PW_CLASS))
- AC_EGREP_HEADER(pw_comment, pwd.h, AC_DEFINE(PW_COMMENT))
- AC_EGREP_HEADER(pw_expire, pwd.h, AC_DEFINE(PW_EXPIRE))
- AC_MSG_RESULT(done)
-fi
-
dnl wheather use dln_a_out ot not
AC_ARG_WITH(dln-a-out, [--with-dln-a-out use dln_a_out if possible], [
case $withval in
@@ -271,7 +342,10 @@ if test "$with_dln_a_out" != yes; then
if test "$GCC" = yes; then
case "$host_os" in
nextstep*) ;;
+ openstep*) ;;
+ rhapsody*) ;;
human*) ;;
+ cygwin*) CCDLFLAGS=-DDLLIMPORT;;
*) CCDLFLAGS=-fpic;;
esac
else
@@ -301,21 +375,44 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes ;;
linux*) LDSHARED="gcc -shared"
rb_cv_dlopen=yes ;;
+ freebsd3*) LDSHARED="ld -Bshareable"
+ LDFLAGS="-rdynamic"
+ rb_cv_dlopen=yes ;;
freebsd*) LDSHARED="ld -Bshareable"
rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -Bshareable"
rb_cv_dlopen=yes ;;
- openbsd*) LDSHARED="ld -Bshareable"
+ openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
+ CCDLFLAGS=-fPIC
rb_cv_dlopen=yes ;;
nextstep*) LDSHARED='cc -r'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
+ openstep*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
+ rhapsody*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
rb_cv_dlopen=yes ;;
human*) DLDFLAGS=''
LDSHARED=''
LDFLAGS='' ;;
+ beos*) LDSHARED="ld -xms"
+ case "$host_cpu" in
+ powerpc*)
+ DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
+ ;;
+ *)
+ DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
+ ;;
+ esac
+ rb_cv_dlopen=yes ;;
+ cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb' ;;
*) LDSHARED='ld' ;;
esac
AC_MSG_RESULT($rb_cv_dlopen)
@@ -357,6 +454,12 @@ else
AC_DEFINE(DLEXT, ".sl");;
nextstep*) DLEXT=o
AC_DEFINE(DLEXT, ".o");;
+ openstep*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ rhapsody*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ cygwin*) DLEXT=dll
+ AC_DEFINE(DLEXT, ".dll");;
*) DLEXT=so
AC_DEFINE(DLEXT, ".so");;
esac
@@ -374,6 +477,10 @@ case "$host_os" in
STRIP='strip -S -x';;
nextstep*)
STRIP='strip -A -n';;
+ openstep*)
+ STRIP='strip -A -n';;
+ rhapsody*)
+ STRIP='strip -A -n';;
esac
EXTSTATIC=
@@ -435,11 +542,18 @@ rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no)])
binsuffix=.x
setup=Setup.x68
;;
+ cygwin*)
+ binsuffix=.exe
+ setup=Setup
+ ;;
*)
binsuffix=
setup=Setup
;;
esac
+
+
+
AC_SUBST(binsuffix)
AC_SUBST(setup)
@@ -448,23 +562,82 @@ if test "$prefix" = NONE; then
fi
if test "$fat_binary" = yes ; then
- CFLAGS="$CFLAGS -pipe $ARCH_FLAG"
+ CFLAGS="$CFLAGS $ARCH_FLAG"
+fi
+
+LIBRUBY='libruby.a'
+LIBRUBYARG='libruby.a'
+SOLIBS=
+if test "$host_os" = "beos"; then
+ CFLAGS="$CFLAGS -relax_pointers"
+ LIBRUBY='libruby.so'
+ LIBRUBYARG='-lruby'
+ SOLIBS='-lnet'
+ echo creating ruby.def
+ case "$host_cpu" in
+ powerpc*)
+ cp beos/ruby.def.in ruby.exp
+ ;;
+ *)
+ echo EXPORTS > ruby.def
+ cat beos/ruby.def.in >> ruby.def
+ ;;
+ esac
fi
-AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/ruby")
+if test "$enable_shared" = 'yes'; then
+ LIBRUBY='libruby.so'
+ LIBRUBYARG='-L./ -lruby'
+fi
+
+case "$host_os" in
+ nextstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ openstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ rhasody*)
+ CFLAGS="$CFLAGS -pipe -no-precomp"
+ ;;
+ *)
+ ;;
+esac
+
+
+AC_SUBST(LIBRUBY)
+AC_SUBST(LIBRUBYARG)
+AC_SUBST(SOLIBS)
+
+ri_prefix=
+test "$program_prefix" != NONE &&
+ ri_prefix=$program_prefix
+
+ri_suffix=
+test "$program_suffix" != NONE &&
+ ri_suffix=$program_suffix
+
+RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
+AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby")
AC_SUBST(arch)dnl
if test "$fat_binary" = yes ; then
arch="fat-${host_os}"
AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB,
- "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}" )
+ "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" )
+
+ AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
+ "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" )
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/ruby/${arch}")
+ AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
+ AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}" )
else
arch="${host_cpu}-${host_os}"
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/ruby/${arch}")
+ AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
+ AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "${arch}")
fi
diff --git a/defines.h b/defines.h
index a24f9ebff7..fb10d628b4 100644
--- a/defines.h
+++ b/defines.h
@@ -12,18 +12,20 @@
#define RUBY
-/* define EUC/SJIS for default kanji-code */
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__)
-#undef EUC
-#define SJIS
+/* define RUBY_USE_EUC/SJIS for default kanji-code */
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__) || defined(__MACOS__)
+#undef RUBY_USE_EUC
+#define RUBY_USE_SJIS
#else
-#define EUC
-#undef SJIS
+#define RUBY_USE_EUC
+#undef RUBY_USE_SJIS
#endif
#ifdef NeXT
#define DYNAMIC_ENDIAN /* determine endian at runtime */
+#ifndef __APPLE__
#define S_IXUSR _S_IXUSR /* execute/search permission, owner */
+#endif
#define S_IXGRP 0000010 /* execute/search permission, group */
#define S_IXOTH 0000001 /* execute/search permission, other */
#endif /* NeXT */
@@ -32,12 +34,22 @@
#include "missing/nt.h"
#endif
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
#ifdef sparc
#define FLUSH_REGISTER_WINDOWS asm("ta 3")
#else
#define FLUSH_REGISTER_WINDOWS /* empty */
#endif
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__MACOS__)
+#define RUBY_PATH_SEP ";"
+#else
+#define RUBY_PATH_SEP ":"
+#endif
+
#if defined(__human68k__) || defined(__CYGWIN32__)
#undef HAVE_RANDOM
#undef HAVE_SETITIMER
diff --git a/dir.c b/dir.c
index 29ce261272..51d7f9e344 100644
--- a/dir.c
+++ b/dir.c
@@ -6,7 +6,7 @@
$Date$
created at: Wed Jan 5 09:51:01 JST 1994
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -27,6 +27,9 @@
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
+#elif HAVE_DIRECT_H
+# include <direct.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
@@ -39,7 +42,7 @@
# if HAVE_NDIR_H
# include <ndir.h>
# endif
-# ifdef NT
+# if defined(NT) && defined(_MSC_VER)
# include "missing/dir.h"
# endif
#endif
@@ -50,7 +53,11 @@
char *getenv();
#endif
-static VALUE cDir;
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
+
+VALUE rb_cDir;
static void
free_dir(dir)
@@ -59,6 +66,8 @@ free_dir(dir)
if (dir) closedir(dir);
}
+static VALUE dir_close _((VALUE));
+
static VALUE
dir_s_open(dir_class, dirname)
VALUE dir_class, dirname;
@@ -71,7 +80,7 @@ dir_s_open(dir_class, dirname)
dirp = opendir(RSTRING(dirname)->ptr);
if (dirp == NULL) {
if (errno == EMFILE || errno == ENFILE) {
- gc_gc();
+ rb_gc();
dirp = opendir(RSTRING(dirname)->ptr);
}
if (dirp == NULL) {
@@ -81,13 +90,17 @@ dir_s_open(dir_class, dirname)
obj = Data_Wrap_Struct(dir_class, 0, free_dir, dirp);
+ if (rb_iterator_p()) {
+ return rb_ensure(rb_yield, obj, dir_close, obj);
+ }
+
return obj;
}
static void
dir_closed()
{
- Fail("closed directory");
+ rb_raise(rb_eIOError, "closed directory");
}
#define GetDIR(obj, dirp) {\
@@ -96,6 +109,27 @@ dir_closed()
}
static VALUE
+dir_read(dir)
+ VALUE dir;
+{
+ DIR *dirp;
+ struct dirent *dp;
+
+ GetDIR(dir, dirp);
+ errno = 0;
+ dp = readdir(dirp);
+ 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 */
+}
+
+static VALUE
dir_each(dir)
VALUE dir;
{
@@ -105,7 +139,7 @@ dir_each(dir)
GetDIR(dir, dirp);
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- file = str_taint(str_new(dp->d_name, NAMLEN(dp)));
+ file = rb_tainted_str_new(dp->d_name, NAMLEN(dp));
rb_yield(file);
}
return dir;
@@ -118,10 +152,10 @@ dir_tell(dir)
DIR *dirp;
int pos;
-#if !defined(__CYGWIN32__)
+#if !defined(__CYGWIN32__) && !defined(__BEOS__)
GetDIR(dir, dirp);
pos = telldir(dirp);
- return int2inum(pos);
+ return rb_int2inum(pos);
#else
rb_notimplement();
#endif
@@ -133,7 +167,7 @@ dir_seek(dir, pos)
{
DIR *dirp;
-#if !defined(__CYGWIN32__)
+#if !defined(__CYGWIN32__) && !defined(__BEOS__)
GetDIR(dir, dirp);
seekdir(dirp, NUM2INT(pos));
return dir;
@@ -177,8 +211,7 @@ dir_s_chdir(argc, argv, obj)
char *dist = "";
rb_secure(2);
- rb_scan_args(argc, argv, "01", &path);
- if (!NIL_P(path)) {
+ if (rb_scan_args(argc, argv, "01", &path) == 1) {
Check_SafeStr(path);
dist = RSTRING(path)->ptr;
}
@@ -190,7 +223,7 @@ dir_s_chdir(argc, argv, obj)
}
if (chdir(dist) < 0)
- rb_sys_fail(0);
+ rb_sys_fail(dist);
return INT2FIX(0);
}
@@ -199,32 +232,33 @@ static VALUE
dir_s_getwd(dir)
VALUE dir;
{
- extern char *getwd();
char path[MAXPATHLEN];
#ifdef HAVE_GETCWD
if (getcwd(path, sizeof(path)) == 0) rb_sys_fail(path);
#else
+ extern char *getwd();
if (getwd(path) == 0) rb_sys_fail(path);
#endif
- return str_taint(str_new2(path));
+ return rb_tainted_str_new2(path);
}
static VALUE
dir_s_chroot(dir, path)
VALUE dir, path;
{
-#if !defined(DJGPP) && !defined(__CYGWIN32__) && !defined(NT) && !defined(__human68k__)
+#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__)
rb_secure(2);
Check_SafeStr(path);
if (chroot(RSTRING(path)->ptr) == -1)
- rb_sys_fail(0);
+ rb_sys_fail(RSTRING(path)->ptr);
return INT2FIX(0);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
@@ -246,7 +280,7 @@ dir_s_mkdir(argc, argv, obj)
}
Check_SafeStr(path);
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
if (mkdir(RSTRING(path)->ptr, mode) == -1)
rb_sys_fail(RSTRING(path)->ptr);
#else
@@ -266,7 +300,7 @@ dir_s_rmdir(obj, dir)
if (rmdir(RSTRING(dir)->ptr) < 0)
rb_sys_fail(RSTRING(dir)->ptr);
- return TRUE;
+ return Qtrue;
}
#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
@@ -285,7 +319,7 @@ push_globs(ary, s)
if (fnames == (char**)-1) rb_sys_fail(s);
ff = fnames;
while (*ff) {
- ary_push(ary, str_taint(str_new2(*ff)));
+ rb_ary_push(ary, rb_tainted_str_new2(*ff));
free(*ff);
ff++;
}
@@ -341,22 +375,24 @@ push_braces(ary, s)
}
static VALUE
-dir_s_glob(dir, vstr)
- VALUE dir, vstr;
+dir_s_glob(dir, str)
+ VALUE dir, str;
{
char *p, *pend;
char buf[MAXPATHLEN];
char *t, *t0;
int nest;
VALUE ary;
- struct RString *str;
- Check_SafeStr(vstr);
- str = RSTRING(vstr);
- ary = ary_new();
+ Check_SafeStr(str);
+ if (RSTRING(str)->len > MAXPATHLEN) {
+ rb_raise(rb_eArgError, "pathname too long (%d bytes)",
+ RSTRING(str)->len);
+ }
+ ary = rb_ary_new();
- p = str->ptr;
- pend = p + str->len;
+ p = RSTRING(str)->ptr;
+ pend = p + RSTRING(str)->len;
while (p < pend) {
t = buf;
@@ -389,37 +425,48 @@ dir_foreach(io, dirname)
{
VALUE dir;
- dir = dir_s_open(cDir, dirname);
+ dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
return rb_ensure(dir_each, dir, dir_close, dir);
}
-void
-Init_Dir()
+static VALUE
+dir_entries(io, dirname)
+ VALUE io, dirname;
{
- extern VALUE mEnumerable;
-
- cDir = rb_define_class("Dir", cObject);
-
- rb_include_module(cDir, mEnumerable);
-
- rb_define_singleton_method(cDir, "open", dir_s_open, 1);
- rb_define_singleton_method(cDir, "foreach", dir_foreach, 1);
-
- rb_define_method(cDir,"each", dir_each, 0);
- rb_define_method(cDir,"rewind", dir_rewind, 0);
- rb_define_method(cDir,"tell", dir_tell, 0);
- rb_define_method(cDir,"seek", dir_seek, 1);
- rb_define_method(cDir,"close", dir_close, 0);
+ VALUE dir;
- rb_define_singleton_method(cDir,"chdir", dir_s_chdir, -1);
- rb_define_singleton_method(cDir,"getwd", dir_s_getwd, 0);
- rb_define_singleton_method(cDir,"pwd", dir_s_getwd, 0);
- rb_define_singleton_method(cDir,"chroot", dir_s_chroot, 1);
- rb_define_singleton_method(cDir,"mkdir", dir_s_mkdir, -1);
- rb_define_singleton_method(cDir,"rmdir", dir_s_rmdir, 1);
- rb_define_singleton_method(cDir,"delete", dir_s_rmdir, 1);
- rb_define_singleton_method(cDir,"unlink", dir_s_rmdir, 1);
+ dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ return rb_ensure(rb_Array, dir, dir_close, dir);
+}
- rb_define_singleton_method(cDir,"glob", dir_s_glob, 1);
- rb_define_singleton_method(cDir,"[]", dir_s_glob, 1);
+void
+Init_Dir()
+{
+ rb_cDir = rb_define_class("Dir", rb_cObject);
+
+ rb_include_module(rb_cDir, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cDir, "new", dir_s_open, 1);
+ rb_define_singleton_method(rb_cDir, "open", dir_s_open, 1);
+ rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, 1);
+ rb_define_singleton_method(rb_cDir, "entries", dir_entries, 1);
+
+ rb_define_method(rb_cDir,"read", dir_read, 0);
+ rb_define_method(rb_cDir,"each", dir_each, 0);
+ rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
+ rb_define_method(rb_cDir,"tell", dir_tell, 0);
+ rb_define_method(rb_cDir,"seek", dir_seek, 1);
+ rb_define_method(rb_cDir,"close", dir_close, 0);
+
+ rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
+ rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
+ rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
+ rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
+ rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
+ rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
+ rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
+ rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
+
+ rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, 1);
+ rb_define_singleton_method(rb_cDir,"[]", dir_s_glob, 1);
}
diff --git a/dln.c b/dln.c
index f4ab012021..858291d5b7 100644
--- a/dln.c
+++ b/dln.c
@@ -6,20 +6,20 @@
$Date$
created at: Tue Jan 18 17:05:06 JST 1994
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
-#ifdef _AIX
-#pragma alloca
-#endif
-
#include "config.h"
#include "defines.h"
#include "dln.h"
char *dln_argv0;
+#ifdef _AIX
+#pragma alloca
+#endif
+
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
#include <alloca.h>
#endif
@@ -36,7 +36,9 @@ void *xrealloc();
#include <stdio.h>
#ifndef NT
-#include <sys/file.h>
+# ifndef USE_CWGUSI
+# include <sys/file.h>
+# endif
#else
#include "missing/file.h"
#endif
@@ -58,15 +60,25 @@ char *strdup();
char *getenv();
#endif
+#ifdef __MACOS__
+# include <TextUtils.h>
+# include <CodeFragments.h>
+# include <Aliases.h>
+#endif
+
+#ifdef __BEOS__
+# include <image.h>
+#endif
+
int eaccess();
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT)
+#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(__CYGWIN32__) && !defined(_AIX)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || defined(__FreeBSD__) || defined(NeXT)
+# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__)
# define FUNCNAME_PATTERN "_Init_%.200s"
# else
# define FUNCNAME_PATTERN "Init_%.200s"
@@ -81,7 +93,11 @@ init_funcname(buf, file)
/* Load the file as an object one */
for (p = file, slash = p-1; *p; p++) /* Find position of last '/' */
+#ifdef __MACOS__
+ if (*p == ':') slash = p;
+#else
if (*p == '/') slash = p;
+#endif
sprintf(buf, FUNCNAME_PATTERN, slash + 1);
for (p = buf; *p; p++) { /* Delete suffix it it exists */
@@ -407,7 +423,7 @@ load_text_data(fd, hdrp, bss, disp)
}
static int
-undef_print(key, value)
+underb_f_print(key, value)
char *key, *value;
{
fprintf(stderr, " %s\n", key);
@@ -418,7 +434,7 @@ static void
dln_print_undef()
{
fprintf(stderr, " Undefined symbols:\n");
- st_foreach(undef_tbl, undef_print, NULL);
+ st_foreach(undef_tbl, underb_f_print, NULL);
}
static void
@@ -814,7 +830,7 @@ load_1(fd, disp, need_init)
for (sym = syms; sym<end; sym++) {
char *name = sym->n_un.n_name;
if (name[0] == '_' && sym->n_value >= block) {
- if (strcmp(name+1, "libs_to_be_linked") == 0) {
+ if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
libs_to_be_linked = (char**)sym->n_value;
}
else if (strcmp(name+1, buf) == 0) {
@@ -869,11 +885,11 @@ search_undef(key, value, lib_tbl)
}
struct symdef {
- int str_index;
+ int rb_str_index;
int lib_offset;
};
-char *dln_library_path = DLN_DEFAULT_LIB_PATH;
+char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
static int
load_lib(lib)
@@ -904,10 +920,10 @@ load_lib(lib)
/* library search path: */
/* look for environment variable DLN_LIBRARY_PATH first. */
- /* then variable dln_library_path. */
+ /* then variable dln_librrb_ary_path. */
/* if path is still NULL, use "." for path. */
path = getenv("DLN_LIBRARY_PATH");
- if (path == NULL) path = dln_library_path;
+ if (path == NULL) path = dln_librrb_ary_path;
file = dln_find_file(lib, path);
fd = open(file, O_RDONLY);
@@ -936,7 +952,7 @@ load_lib(lib)
base = (struct symdef*)(data + 1);
name_base = (char*)(base + nsym) + sizeof(int);
while (nsym > 0) {
- char *name = name_base + base->str_index;
+ char *name = name_base + base->rb_str_index;
st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
nsym--;
@@ -1065,14 +1081,18 @@ dln_sym(name)
#include "dl.h"
#endif
-#ifdef _AIX
+#if defined(_AIX)
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <sys/ldr.h>
#endif
#ifdef NeXT
-/*#include <mach-o/rld.h>*/
+#if NS_TARGET_MAJOR < 4
+#include <mach-o/rld.h>
+#else
+#include <mach-o/dyld.h>
+#endif
#endif
#ifdef _WIN32
@@ -1109,21 +1129,28 @@ dln_strerror()
#ifdef _WIN32
static char message[1024];
+ int error = GetLastError();
+ char *p = message;
+ p += sprintf(message, "%d: ", error);
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
- GetLastError(),
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- message,
- sizeof message,
+ error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ p,
+ sizeof message - strlen(message),
NULL);
+ for (p = message; *p; p++) {
+ if (*p == '\n' || *p == '\r')
+ *p = ' ';
+ }
return message;
#endif
}
-#ifdef _AIX
+#if defined(_AIX)
static void
aix_loaderror(char *pathname)
{
@@ -1166,7 +1193,7 @@ aix_loaderror(char *pathname)
ERRBUF_APPEND("\n");
}
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- LoadError(errbuf);
+ rb_loaderror(errbuf);
return;
}
#endif
@@ -1193,7 +1220,7 @@ dln_load(file)
/* Load file */
if ((handle =
LoadLibraryExA(winfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) {
- printf("LoadLibraryExA\n");
+ printf("LoadLibraryExA: %s\n", winfile);
goto failed;
}
@@ -1229,15 +1256,15 @@ dln_load(file)
void *handle;
void (*init_fct)();
-# ifndef RTLD_LAZY
-# define RTLD_LAZY 1
-# endif
-# ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
-# endif
+#ifndef RTLD_LAZY
+# define RTLD_LAZY 1
+#endif
+#ifndef RTLD_GLOBAL
+# define RTLD_GLOBAL 0
+#endif
/* Load file */
- if ((handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
+ if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
goto failed;
}
@@ -1260,15 +1287,15 @@ dln_load(file)
flags = BIND_DEFERRED;
lib = shl_load(file, flags, 0);
if (lib == NULL) {
- rb_sys_fail(file);
+ extern int errno;
+ rb_loaderror("%s - %s", strerror(errno), file);
}
shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
if (init_fct == NULL) {
shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
if (init_fct == NULL) {
- extern int errno;
errno = ENOSYM;
- rb_sys_fail(file);
+ rb_loaderror("%s - %s", strerror(ENOSYM), file);
}
}
(*init_fct)();
@@ -1276,7 +1303,7 @@ dln_load(file)
}
#endif /* hpux */
-#ifdef _AIX
+#if defined(_AIX)
#define DLN_DEFINED
{
void (*init_fct)();
@@ -1300,6 +1327,7 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;)
----------------------------------------------------*/
+#if NS_TARGET_MAJOR < 4 /* NeXTSTEP rld functions */
{
unsigned long init_address;
char *object_files[2] = {NULL, NULL};
@@ -1310,12 +1338,12 @@ dln_load(file)
/* Load object file, if return value ==0 , load failed*/
if(rld_load(NULL, NULL, object_files, NULL) == 0) {
- LoadError("Failed to load %.200s", file);
+ rb_loaderror("Failed to load %.200s", file);
}
/* lookup the initial function */
if(rld_lookup(NULL, buf, &init_address) == 0) {
- LoadError("Failed to lookup Init function %.200s",file);
+ rb_loaderror("Failed to lookup Init function %.200s", file);
}
/* Cannot call *init_address directory, so copy this value to
@@ -1325,8 +1353,133 @@ dln_load(file)
(*init_fct)();
return ;
}
+#else/* OPENSTEP dyld functions */
+ {
+ int dyld_result ;
+ NSObjectFileImage obj_file ; /* handle, but not use it */
+ /* "file" is module file name .
+ "buf" is initial function name with "_" . */
+
+ void (*init_fct)();
+
+
+ dyld_result = NSCreateObjectFileImageFromFile( file, &obj_file );
+
+ if (dyld_result != NSObjectFileImageSuccess) {
+ rb_loaderror("Failed to load %.200s", file);
+ }
+
+ NSLinkModule(obj_file, file, TRUE);
+
+ /* lookup the initial function */
+ /*NSIsSymbolNameDefined require function name without "_" */
+ if( NSIsSymbolNameDefined( buf + 1 ) ) {
+ rb_loaderror("Failed to lookup Init function %.200s",file);
+ }
+
+ /* NSLookupAndBindSymbol require function name with "_" !! */
+ init_fct = NSAddressOfSymbol( NSLookupAndBindSymbol( buf ) );
+ (*init_fct)();
+
+ return ;
+ }
+#endif /* rld or dyld */
#endif
+#ifdef __BEOS__
+# define DLN_DEFINED
+ {
+ status_t err_stat; /* BeOS error status code */
+ image_id img_id; /* extention module unique id */
+ void (*init_fct)(); /* initialize function for extention module */
+
+ /* load extention module */
+ img_id = load_add_on(file);
+ if (img_id <= 0) {
+ rb_loaderror("Failed to load %.200s", file);
+ }
+
+ /* find symbol for module initialize function. */
+ /* The Be Book KernelKit Images section described to use
+ B_SYMBOL_TYPE_TEXT for symbol of function, not
+ B_SYMBOL_TYPE_CODE. Why ? */
+ /* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
+ /* "__Fv" dont need! The Be Book Bug ? */
+ err_stat = get_image_symbol(img_id, buf,
+ B_SYMBOL_TYPE_TEXT, &init_fct);
+
+ if (err_stat != B_NO_ERROR) {
+ char real_name[1024];
+ strcpy(real_name, buf);
+ strcat(real_name, "__Fv");
+ err_stat = get_image_symbol(img_id, real_name,
+ B_SYMBOL_TYPE_TEXT, &init_fct);
+ }
+
+ if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
+ unload_add_on(img_id);
+ rb_loaderror("Failed to lookup Init function %.200s", file);
+ }
+ else if (B_NO_ERROR != err_stat) {
+ char errmsg[] = "Internal of BeOS version. %.200s (symbol_name = %s)";
+ unload_add_on(img_id);
+ rb_loaderror(errmsg, strerror(err_stat), buf);
+ }
+
+ /* call module initialize function. */
+ (*init_fct)();
+ return;
+ }
+#endif /* __BEOS__*/
+
+#ifdef __MACOS__
+# define DLN_DEFINED
+ {
+ OSErr err;
+ FSSpec libspec;
+ CFragConnectionID connID;
+ Ptr mainAddr;
+ char errMessage[1024];
+ Boolean isfolder, didsomething;
+ Str63 fragname;
+ Ptr symAddr;
+ CFragSymbolClass class;
+ void (*init_fct)();
+ char fullpath[MAXPATHLEN];
+
+ strcpy(fullpath, file);
+
+ /* resolve any aliases to find the real file */
+ c2pstr(fullpath);
+ (void)FSMakeFSSpec(0, 0, fullpath, &libspec);
+ err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
+ if ( err ) {
+ rb_loaderror("Unresolved Alias - %s", file);
+ }
+
+ /* Load the fragment (or return the connID if it is already loaded */
+ fragname[0] = 0;
+ err = GetDiskFragment(&libspec, 0, 0, fragname,
+ kLoadCFrag, &connID, &mainAddr,
+ errMessage);
+ if ( err ) {
+ p2cstr(errMessage);
+ rb_loaderror("%s - %s",errMessage , file);
+ }
+
+ /* Locate the address of the correct init function */
+ c2pstr(buf);
+ err = FindSymbol(connID, buf, &symAddr, &class);
+ if ( err ) {
+ rb_loaderror("Unresolved symbols - %s" , file);
+ }
+
+ init_fct = (void (*)())symAddr;
+ (*init_fct)();
+ return;
+ }
+#endif /* __MACOS__ */
+
#ifndef DLN_DEFINED
rb_notimplement("dynamic link not supported");
#endif
@@ -1335,7 +1488,7 @@ dln_load(file)
#endif
#if !defined(_AIX) && !defined(NeXT)
failed:
- LoadError("%s - %s", dln_strerror(), file);
+ rb_loaderror("%s - %s", dln_strerror(), file);
#endif
}
@@ -1346,15 +1499,21 @@ dln_find_exe(fname, path)
char *fname;
char *path;
{
+ if (!path) {
#if defined(__human68k__)
- if (!path)
path = getenv("path");
- if (!path)
- path = "/usr/local/bin;/usr/usb;/usr/bin;/bin;.";
#else
- if (!path) path = getenv("PATH");
- if (!path) path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
+ path = getenv("PATH");
#endif
+ }
+
+ if (!path) {
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__MACOS__)
+ path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;.";
+#else
+ path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
+#endif
+ }
return dln_find_1(fname, path, 1);
}
@@ -1367,6 +1526,30 @@ dln_find_file(fname, path)
return dln_find_1(fname, path, 0);
}
+#if defined(__CYGWIN32__)
+char *
+conv_to_posix_path(win32, posix)
+ char *win32;
+ char *posix;
+{
+ char *first = win32;
+ char *p = win32;
+ char *dst = posix;
+
+ for (p = win32; *p; p++)
+ if (*p == ';') {
+ *p = 0;
+ cygwin32_conv_to_posix_path(first, posix);
+ posix += strlen(posix);
+ *posix++ = ':';
+ first = p + 1;
+ *p = ';';
+ }
+ cygwin32_conv_to_posix_path(first, posix);
+ return dst;
+}
+#endif
+
static char fbuf[MAXPATHLEN];
static char *
@@ -1380,15 +1563,24 @@ dln_find_1(fname, path, exe_flag)
register char *bp;
struct stat st;
+#if defined(__CYGWIN32__)
+ char rubypath[MAXPATHLEN];
+ conv_to_posix_path(path, rubypath);
+ path = rubypath;
+#endif
+#ifndef __MACOS__
if (fname[0] == '/') return fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
return fname;
+ if (exe_flag && strchr(fname, '/')) return fname;
#if defined(MSDOS) || defined(NT) || defined(__human68k__)
if (fname[0] == '\\') return fname;
- if (fname[1] == ':') return fname;
+ if (strlen(fname) > 2 && fname[1] == ':') return fname;
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
return fname;
+ if (exe_flag && strchr(fname, '\\')) return fname;
#endif
+#endif /* __MACOS__ */
for (dp = path;; dp = ++ep) {
register int l;
@@ -1396,11 +1588,7 @@ dln_find_1(fname, path, exe_flag)
int fspace;
/* extract a component */
-#if !defined(MSDOS) && !defined(NT) && !defined(__human68k__)
- ep = strchr(dp, ':');
-#else
- ep = strchr(dp, ';');
-#endif
+ ep = strchr(dp, RUBY_PATH_SEP[0]);
if (ep == NULL)
ep = dp+strlen(dp);
@@ -1417,7 +1605,11 @@ dln_find_1(fname, path, exe_flag)
** take the path literally.
*/
- if (*dp == '~' && (l == 1 || dp[1] == '/')) {
+ if (*dp == '~' && (l == 1 ||
+#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+ dp[1] == '\\' ||
+#endif
+ dp[1] == '/')) {
char *home;
home = getenv("HOME");
@@ -1440,7 +1632,11 @@ dln_find_1(fname, path, exe_flag)
/* add a "/" between directory and filename */
if (ep[-1] != '/')
+#ifdef __MACOS__
+ *bp++ = ':';
+#else
*bp++ = '/';
+#endif
}
/* now append the file name */
diff --git a/dln.h b/dln.h
index 0e16170a02..7af1f63a9d 100644
--- a/dln.h
+++ b/dln.h
@@ -11,12 +11,20 @@
#ifndef DLN_H
#define DLN_H
-char *dln_find_exe();
-char *dln_find_file();
+#ifndef _
+#ifndef __STDC__
+# define _(args) ()
+#else
+# define _(args) args
+#endif
+#endif
+
+char *dln_find_exe _((char*,char*));
+char *dln_find_file _((char*,char*));
#ifdef USE_DLN_A_OUT
extern char *dln_argv0;
#endif
-void dln_load();
+void dln_load _((char*));
#endif
diff --git a/enum.c b/enum.c
index d8e2fcdc8b..2b4b904018 100644
--- a/enum.c
+++ b/enum.c
@@ -6,13 +6,13 @@
$Date$
created at: Fri Oct 1 15:15:19 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-VALUE mEnumerable;
+VALUE rb_mEnumerable;
static ID id_each, id_eqq, id_cmp;
VALUE
@@ -27,7 +27,7 @@ grep_i(i, arg)
VALUE i, *arg;
{
if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
- ary_push(arg[1], i);
+ rb_ary_push(arg[1], i);
}
return Qnil;
}
@@ -46,14 +46,14 @@ static VALUE
enum_grep(obj, pat)
VALUE obj, pat;
{
- if (iterator_p()) {
+ if (rb_iterator_p()) {
rb_iterate(rb_each, obj, grep_iter_i, pat);
return obj;
}
else {
VALUE tmp, arg[2];
- arg[0] = pat; arg[1] = tmp = ary_new();
+ arg[0] = pat; arg[1] = tmp = rb_ary_new();
rb_iterate(rb_each, obj, grep_i, (VALUE)arg);
return tmp;
@@ -71,7 +71,7 @@ find_i(i, arg)
struct find_arg *arg;
{
if (RTEST(rb_yield(i))) {
- arg->found = TRUE;
+ arg->found = Qtrue;
arg->val = i;
rb_iter_break();
}
@@ -88,7 +88,7 @@ enum_find(argc, argv, obj)
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
- arg.found = FALSE;
+ arg.found = Qfalse;
rb_iterate(rb_each, obj, find_i, (VALUE)&arg);
if (arg.found) {
return arg.val;
@@ -104,7 +104,7 @@ find_all_i(i, tmp)
VALUE i, tmp;
{
if (RTEST(rb_yield(i))) {
- ary_push(tmp, i);
+ rb_ary_push(tmp, i);
}
return Qnil;
}
@@ -115,7 +115,7 @@ enum_find_all(obj)
{
VALUE tmp;
- tmp = ary_new();
+ tmp = rb_ary_new();
rb_iterate(rb_each, obj, find_all_i, tmp);
return tmp;
@@ -125,12 +125,7 @@ static VALUE
collect_i(i, tmp)
VALUE i, tmp;
{
- VALUE retval;
-
- retval = rb_yield(i);
- if (RTEST(retval)) {
- ary_push(tmp, retval);
- }
+ rb_ary_push(tmp, rb_yield(i));
return Qnil;
}
@@ -140,37 +135,17 @@ enum_collect(obj)
{
VALUE tmp;
- tmp = ary_new();
+ tmp = rb_ary_new();
rb_iterate(rb_each, obj, collect_i, tmp);
return tmp;
}
static VALUE
-reverse_i(i, tmp)
- VALUE i, tmp;
-{
- ary_unshift(tmp, i);
- return Qnil;
-}
-
-static VALUE
-enum_reverse(obj)
- VALUE obj;
-{
- VALUE tmp;
-
- tmp = ary_new();
- rb_iterate(rb_each, obj, reverse_i, tmp);
-
- return tmp;
-}
-
-static VALUE
enum_all(i, ary)
VALUE i, ary;
{
- ary_push(ary, i);
+ rb_ary_push(ary, i);
return Qnil;
}
@@ -180,7 +155,7 @@ enum_to_a(obj)
{
VALUE ary;
- ary = ary_new();
+ ary = rb_ary_new();
rb_iterate(rb_each, obj, enum_all, ary);
return ary;
@@ -190,7 +165,7 @@ static VALUE
enum_sort(obj)
VALUE obj;
{
- return ary_sort(enum_to_a(obj));
+ return rb_ary_sort(enum_to_a(obj));
}
static VALUE
@@ -203,7 +178,7 @@ min_i(i, min)
*min = i;
else {
cmp = rb_funcall(i, id_cmp, 1, *min);
- if (FIX2INT(cmp) < 0)
+ if (FIX2LONG(cmp) < 0)
*min = i;
}
return Qnil;
@@ -218,8 +193,8 @@ min_ii(i, min)
if (NIL_P(*min))
*min = i;
else {
- cmp = rb_yield(assoc_new(i, *min));
- if (FIX2INT(cmp) < 0)
+ cmp = rb_yield(rb_assoc_new(i, *min));
+ if (FIX2LONG(cmp) < 0)
*min = i;
}
return Qnil;
@@ -231,7 +206,7 @@ enum_min(obj)
{
VALUE min = Qnil;
- rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, (VALUE)&min);
+ rb_iterate(rb_each, obj, rb_iterator_p()?min_ii:min_i, (VALUE)&min);
return min;
}
@@ -245,7 +220,7 @@ max_i(i, max)
*max = i;
else {
cmp = rb_funcall(i, id_cmp, 1, *max);
- if (FIX2INT(cmp) > 0)
+ if (FIX2LONG(cmp) > 0)
*max = i;
}
return Qnil;
@@ -260,8 +235,8 @@ max_ii(i, max)
if (NIL_P(*max))
*max = i;
else {
- cmp = rb_yield(assoc_new(i, *max));
- if (FIX2INT(cmp) > 0)
+ cmp = rb_yield(rb_assoc_new(i, *max));
+ if (FIX2LONG(cmp) > 0)
*max = i;
}
return Qnil;
@@ -273,7 +248,7 @@ enum_max(obj)
{
VALUE max = Qnil;
- rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, (VALUE)&max);
+ rb_iterate(rb_each, obj, rb_iterator_p()?max_ii:max_i, (VALUE)&max);
return max;
}
@@ -333,8 +308,8 @@ enum_member(obj, val)
iv.i = 0;
iv.v = val;
rb_iterate(rb_each, obj, member_i, (VALUE)&iv);
- if (iv.i) return TRUE;
- return FALSE;
+ if (iv.i) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -346,7 +321,7 @@ length_i(i, length)
return Qnil;
}
-VALUE
+static VALUE
enum_length(obj)
VALUE obj;
{
@@ -356,26 +331,58 @@ enum_length(obj)
return INT2FIX(length);
}
+VALUE
+rb_enum_length(obj)
+ VALUE obj;
+{
+ return enum_length(obj);
+}
+
+static VALUE
+each_with_index_i(val, indexp)
+ VALUE val;
+ int *indexp;
+{
+#if 1
+ rb_yield(rb_assoc_new(val, INT2FIX(*indexp)));
+#else
+ rb_yield(rb_ary_concat(rb_Array(val), INT2FIX(*indexp)));
+#endif
+ (*indexp)++;
+ return Qnil;
+}
+
+static VALUE
+enum_each_with_index(obj)
+ VALUE obj;
+{
+ int index = 0;
+
+ rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&index);
+ return Qnil;
+}
+
void
Init_Enumerable()
{
- mEnumerable = rb_define_module("Enumerable");
-
- rb_define_method(mEnumerable,"to_a", enum_to_a, 0);
-
- rb_define_method(mEnumerable,"sort", enum_sort, 0);
- rb_define_method(mEnumerable,"grep", enum_grep, 1);
- rb_define_method(mEnumerable,"find", enum_find, -1);
- rb_define_method(mEnumerable,"find_all", enum_find_all, 0);
- rb_define_method(mEnumerable,"collect", enum_collect, 0);
- rb_define_method(mEnumerable,"reverse", enum_reverse, 0);
- rb_define_method(mEnumerable,"min", enum_min, 0);
- rb_define_method(mEnumerable,"max", enum_max, 0);
- rb_define_method(mEnumerable,"index", enum_index, 1);
- rb_define_method(mEnumerable,"member?", enum_member, 1);
- rb_define_method(mEnumerable,"include?", enum_member, 1);
- rb_define_method(mEnumerable,"length", enum_length, 0);
- rb_define_method(mEnumerable,"size", enum_length, 0);
+ rb_mEnumerable = rb_define_module("Enumerable");
+
+ rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
+ rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
+
+ rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
+ rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
+ rb_define_method(rb_mEnumerable,"find", enum_find, -1);
+ rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
+ rb_define_method(rb_mEnumerable,"min", enum_min, 0);
+ rb_define_method(rb_mEnumerable,"max", enum_max, 0);
+ rb_define_method(rb_mEnumerable,"index", enum_index, 1);
+ rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
+ rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
+ rb_define_method(rb_mEnumerable,"length", enum_length, 0);
+ rb_define_method(rb_mEnumerable,"size", enum_length, 0);
+ rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
diff --git a/env.h b/env.h
index ebcfcc5d31..79fdfc2bef 100644
--- a/env.h
+++ b/env.h
@@ -12,6 +12,7 @@
#define ENV_H
extern struct FRAME {
+ VALUE self;
int argc;
VALUE *argv;
ID last_func;
@@ -21,16 +22,16 @@ extern struct FRAME {
char *file;
int line;
int iter;
-} *the_frame;
+} *ruby_frame;
-void gc_mark_frame _((struct FRAME *));
+void rb_gc_mark_frame _((struct FRAME *));
extern struct SCOPE {
struct RBasic super;
ID *local_tbl;
VALUE *local_vars;
int flag;
-} *the_scope;
+} *ruby_scope;
#define SCOPE_ALLOCA 0
#define SCOPE_MALLOC 1
@@ -38,7 +39,7 @@ extern struct SCOPE {
extern int rb_in_eval;
-extern VALUE the_class;
+extern VALUE ruby_class;
struct RVarmap {
struct RBasic super;
@@ -46,6 +47,6 @@ struct RVarmap {
VALUE val;
struct RVarmap *next;
};
-extern struct RVarmap *the_dyna_vars;
+extern struct RVarmap *ruby_dyna_vars;
#endif /* ENV_H */
diff --git a/error.c b/error.c
index 7163f62609..44ca067472 100644
--- a/error.c
+++ b/error.c
@@ -6,56 +6,46 @@
$Date$
created at: Mon Aug 9 16:11:34 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "env.h"
#include <stdio.h>
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
-extern char *sourcefile;
-extern int sourceline;
+#ifdef USE_CWGUSI
+#include <sys/errno.h>
+int sys_nerr = 256;
+#endif
-int nerrs;
+int ruby_nerrs;
static void
-err_sprintf(buf, fmt, args)
+err_snprintf(buf, len, fmt, args)
char *buf, *fmt;
+ int len;
va_list args;
{
- if (!sourcefile) {
- vsprintf(buf, fmt, args);
+ if (!ruby_sourcefile) {
+ vsnprintf(buf, len, fmt, args);
}
else {
- sprintf(buf, "%s:%d: ", sourcefile, sourceline);
- vsprintf((char*)buf+strlen(buf), fmt, args);
- }
-}
-
-static void
-err_append(s)
- char *s;
-{
- extern VALUE errinfo;
-
- if (rb_in_eval) {
- if (NIL_P(errinfo)) {
- errinfo = str_new2(s);
+ int n = snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline);
+ if (len > n) {
+ vsnprintf((char*)buf+n, len-n, fmt, args);
}
- else {
- str_cat(errinfo, "\n", 1);
- str_cat(errinfo, s, strlen(s));
- }
- }
- else {
- fputs(s, stderr);
- fputs("\n", stderr);
- fflush(stderr);
}
}
+static void err_append _((char*));
static void
err_print(fmt, args)
char *fmt;
@@ -63,66 +53,102 @@ err_print(fmt, args)
{
char buf[BUFSIZ];
- err_sprintf(buf, fmt, args);
+ err_snprintf(buf, BUFSIZ, fmt, args);
err_append(buf);
}
void
-Error(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_compile_error(char *fmt, ...)
+#else
+rb_compile_error(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
va_list args;
- va_start(args);
+ va_init_list(args, fmt);
err_print(fmt, args);
va_end(args);
- nerrs++;
+ ruby_nerrs++;
}
void
-Error_Append(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_compile_error_append(char *fmt, ...)
+#else
+rb_compile_error_append(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
va_list args;
char buf[BUFSIZ];
- va_start(args);
- vsprintf(buf, fmt, args);
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
err_append(buf);
}
void
-Warning(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_warn(char *fmt, ...)
+#else
+rb_warn(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ char buf[BUFSIZ];
+ va_list args;
+
+ snprintf(buf, BUFSIZ, "warning: %s", fmt);
+
+ va_init_list(args, fmt);
+ err_print(buf, args);
+ va_end(args);
+}
+
+/* rb_warning() reports only in verbose mode */
+void
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_warning(char *fmt, ...)
+#else
+rb_warning(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
char buf[BUFSIZ];
va_list args;
- if (!RTEST(verbose)) return;
+ if (!RTEST(rb_verbose)) return;
- sprintf(buf, "warning: %s", fmt);
+ snprintf(buf, BUFSIZ, "warning: %s", fmt);
- va_start(args);
+ va_init_list(args, fmt);
err_print(buf, args);
va_end(args);
}
void
-Bug(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_bug(char *fmt, ...)
+#else
+rb_bug(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
char buf[BUFSIZ];
va_list args;
- sprintf(buf, "[BUG] %s", fmt);
+ snprintf(buf, BUFSIZ, "[BUG] %s", fmt);
rb_in_eval = 0;
- va_start(args);
+ va_init_list(args, fmt);
err_print(buf, args);
va_end(args);
abort();
@@ -156,94 +182,133 @@ static struct types {
-1, 0,
};
-extern void TypeError();
-
void
rb_check_type(x, t)
VALUE x;
int t;
{
struct types *type = builtin_types;
+ int tt = TYPE(x);
- if (TYPE(x)!=(t)) {
+ if (tt != t) {
while (type->type >= 0) {
if (type->type == t) {
- TypeError("wrong argument type %s (expected %s)",
- rb_class2name(CLASS_OF(x)), type->name);
+ char *etype;
+
+ if (NIL_P(x)) {
+ etype = "nil";
+ }
+ else if (FIXNUM_P(x)) {
+ etype = "Fixnum";
+ }
+ else if (rb_special_const_p(x)) {
+ etype = RSTRING(rb_obj_as_string(x))->ptr;
+ }
+ else {
+ etype = rb_class2name(CLASS_OF(x));
+ }
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
+ etype, type->name);
}
type++;
}
- Bug("unknown type 0x%x", t);
+ rb_bug("unknown type 0x%x", t);
}
}
/* exception classes */
-#include "errno.h"
-
-extern VALUE cString;
-VALUE eGlobalExit, eException;
-VALUE eSystemExit, eInterrupt, eFatal;
-VALUE eRuntimeError;
-VALUE eSyntaxError;
-VALUE eTypeError;
-VALUE eArgError;
-VALUE eNameError;
-VALUE eIndexError;
-VALUE eNotImpError;
-VALUE eLoadError;
-VALUE eSecurityError;
-
-VALUE eSystemCallError;
-VALUE mErrno;
+#include <errno.h>
+
+VALUE rb_eException;
+VALUE rb_eSystemExit, rb_eInterrupt, rb_eFatal;
+VALUE rb_eStandardError;
+VALUE rb_eRuntimeError;
+VALUE rb_eSyntaxError;
+VALUE rb_eTypeError;
+VALUE rb_eArgError;
+VALUE rb_eNameError;
+VALUE rb_eIndexError;
+VALUE rb_eLoadError;
+VALUE rb_eSecurityError;
+VALUE rb_eNotImpError;
+
+VALUE rb_eSystemCallError;
+VALUE rb_mErrno;
VALUE
-exc_new(etype, ptr, len)
+rb_exc_new(etype, ptr, len)
VALUE etype;
char *ptr;
- UINT len;
+ int len;
{
- NEWOBJ(exc, struct RString);
- OBJSETUP(exc, etype, T_STRING);
-
- exc->len = len;
- exc->orig = 0;
- exc->ptr = ALLOC_N(char,len+1);
- if (ptr) {
- memcpy(exc->ptr, ptr, len);
- }
- exc->ptr[len] = '\0';
- return (VALUE)exc;
+ VALUE exc = rb_obj_alloc(etype);
+
+ rb_iv_set(exc, "mesg", rb_str_new(ptr, len));
+ return exc;
}
VALUE
-exc_new2(etype, s)
+rb_exc_new2(etype, s)
VALUE etype;
char *s;
{
- return exc_new(etype, s, strlen(s));
+ return rb_exc_new(etype, s, strlen(s));
}
VALUE
-exc_new3(etype, str)
+rb_exc_new3(etype, str)
VALUE etype, str;
{
- Check_Type(str, T_STRING);
- return exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len);
+ char *s;
+ int len;
+
+ s = str2cstr(str, &len);
+ return rb_exc_new(etype, s, len);
}
static VALUE
-exc_s_new(argc, argv, etype)
+exc_initialize(argc, argv, exc)
int argc;
VALUE *argv;
- VALUE etype;
+ VALUE exc;
{
- VALUE arg;
+ VALUE mesg;
- if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- return exc_new(etype, 0, 0);
+ if (rb_scan_args(argc, argv, "01", &mesg) == 1) {
+ STR2CSTR(mesg); /* ensure mesg can be converted to String */
}
- Check_Type(arg, T_STRING);
- return exc_new3(etype, arg);
+ rb_iv_set(exc, "mesg", mesg);
+
+ return exc;
+}
+
+static VALUE
+exc_new(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE etype, exc;
+
+ if (argc == 1 && self == argv[0]) return self;
+ etype = CLASS_OF(self);
+ while (FL_TEST(etype, FL_SINGLETON)) {
+ etype = RCLASS(etype)->super;
+ }
+ exc = rb_obj_alloc(etype);
+ rb_obj_call_init(exc);
+
+ return exc;
+}
+
+static VALUE
+exc_to_s(exc)
+ VALUE exc;
+{
+ VALUE mesg = rb_iv_get(exc, "mesg");
+
+ if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc));
+ return mesg;
}
static VALUE
@@ -253,185 +318,314 @@ exc_inspect(exc)
VALUE str, klass;
klass = CLASS_OF(exc);
+ exc = rb_obj_as_string(exc);
if (RSTRING(exc)->len == 0) {
- return rb_class_path(klass);
+ return rb_str_dup(rb_class_path(klass));
}
- str = str_new2("#<");
+ str = rb_str_new2("#<");
klass = rb_class_path(klass);
- str_cat(str, RSTRING(klass)->ptr, RSTRING(klass)->len);
- str_cat(str, ":", 1);
- str_cat(str, RSTRING(exc)->ptr, RSTRING(exc)->len);
- str_cat(str, ">", 1);
+ rb_str_concat(str, klass);
+ rb_str_cat(str, ":", 1);
+ rb_str_concat(str, exc);
+ rb_str_cat(str, ">", 1);
return str;
}
static VALUE
+exc_backtrace(exc)
+ VALUE exc;
+{
+ return rb_iv_get(exc, "bt");
+}
+
+static VALUE
+check_backtrace(bt)
+ VALUE bt;
+{
+ int i;
+ static char *err = "backtrace must be Array of String";
+
+ if (!NIL_P(bt)) {
+ int t = TYPE(bt);
+
+ if (t == T_STRING) return rb_ary_new3(1, bt);
+ if (t != T_ARRAY) {
+ rb_raise(rb_eTypeError, err);
+ }
+ for (i=0;i<RARRAY(bt)->len;i++) {
+ if (TYPE(RARRAY(bt)->ptr[i]) != T_STRING) {
+ rb_raise(rb_eTypeError, err);
+ }
+ }
+ }
+ return bt;
+}
+
+static VALUE
+exc_set_backtrace(exc, bt)
+ VALUE exc;
+{
+ return rb_iv_set(exc, "bt", check_backtrace(bt));
+}
+
+static VALUE
exception(argc, argv)
int argc;
VALUE *argv;
{
- void ArgError();
VALUE v = Qnil;
+ VALUE etype = rb_eStandardError;
int i;
ID id;
if (argc == 0) {
- ArgError("wrong # of arguments");
+ rb_raise(rb_eArgError, "wrong # of arguments");
+ }
+ rb_warn("Exception() is now obsolete");
+ if (TYPE(argv[argc-1]) == T_CLASS) {
+ etype = argv[argc-1];
+ argc--;
+ if (!rb_funcall(etype, '<', 1, rb_eException)) {
+ rb_raise(rb_eTypeError, "exception should be subclass of Exception");
+ }
}
for (i=0; i<argc; i++) { /* argument check */
id = rb_to_id(argv[i]);
if (!rb_id2name(id)) {
- ArgError("argument needs to be symbol or string");
+ rb_raise(rb_eArgError, "argument needs to be symbol or string");
}
if (!rb_is_const_id(id)) {
- ArgError("identifier %s needs to be constant", rb_id2name(id));
+ rb_raise(rb_eArgError, "identifier `%s' needs to be constant",
+ rb_id2name(id));
}
}
for (i=0; i<argc; i++) {
- v = rb_define_class_under(the_class, rb_id2name(rb_to_id(argv[i])), eException);
+ v = rb_define_class_under(ruby_class,
+ rb_id2name(rb_to_id(argv[i])),
+ rb_eStandardError);
}
return v;
}
+#ifdef __BEOS__
+typedef struct {
+ VALUE *list;
+ size_t n;
+} syserr_list_entry;
+
+typedef struct {
+ int ix;
+ size_t n;
+} syserr_index_entry;
+
+static VALUE syserr_list_b_general[16+1];
+static VALUE syserr_list_b_os0[2+1];
+static VALUE syserr_list_b_os1[5+1];
+static VALUE syserr_list_b_os2[2+1];
+static VALUE syserr_list_b_os3[3+1];
+static VALUE syserr_list_b_os4[1+1];
+static VALUE syserr_list_b_app[15+1];
+static VALUE syserr_list_b_interface[0+1];
+static VALUE syserr_list_b_media[8+1];
+static VALUE syserr_list_b_midi[0+1];
+static VALUE syserr_list_b_storage[15+1];
+static VALUE syserr_list_b_posix[38+1];
+static VALUE syserr_list_b_mail[8+1];
+static VALUE syserr_list_b_print[1+1];
+static VALUE syserr_list_b_device[14+1];
+
+# define SYSERR_LIST_B(n) {(n), sizeof(n)/sizeof(VALUE)}
+static const syserr_list_entry syserr_list[] = {
+ SYSERR_LIST_B(syserr_list_b_general),
+ SYSERR_LIST_B(syserr_list_b_os0),
+ SYSERR_LIST_B(syserr_list_b_os1),
+ SYSERR_LIST_B(syserr_list_b_os2),
+ SYSERR_LIST_B(syserr_list_b_os3),
+ SYSERR_LIST_B(syserr_list_b_os4),
+ SYSERR_LIST_B(syserr_list_b_app),
+ SYSERR_LIST_B(syserr_list_b_interface),
+ SYSERR_LIST_B(syserr_list_b_media),
+ SYSERR_LIST_B(syserr_list_b_midi),
+ SYSERR_LIST_B(syserr_list_b_storage),
+ SYSERR_LIST_B(syserr_list_b_posix),
+ SYSERR_LIST_B(syserr_list_b_mail),
+ SYSERR_LIST_B(syserr_list_b_print),
+ SYSERR_LIST_B(syserr_list_b_device),
+};
+# undef SYSERR_LIST_B
+
+static const syserr_index_entry syserr_index[]= {
+ {0, 1}, {1, 5}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, {10, 1}, {11, 1},
+ {12, 1}, {13, 1}, {14, 1}, {0, 0},
+};
+#else
static VALUE *syserr_list;
+#endif
#ifndef NT
extern int sys_nerr;
#endif
-static void
+static VALUE
set_syserr(i, name)
int i;
char *name;
{
+#ifdef __BEOS__
+ VALUE *list;
+ int ix, offset;
+#endif
+ VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
+ rb_define_const(error, "Errno", INT2FIX(i));
+#ifdef __BEOS__
+ i -= B_GENERAL_ERROR_BASE;
+ ix = (i >> 12) & 0xf;
+ offset = (i >> 8) & 0xf;
+ if (offset < syserr_index[ix].n) {
+ ix = syserr_index[ix].ix;
+ if ((i & 0xff) < syserr_list[ix + offset].n) {
+ list = syserr_list[ix + offset].list;
+ list[i & 0xff] = error;
+ rb_global_variable(&list[i & 0xff]);
+ }
+ }
+#else
if (i <= sys_nerr) {
- syserr_list[i] = rb_define_class_under(mErrno, name, eSystemCallError);
- rb_global_variable(&syserr_list[i]);
+ syserr_list[i] = error;
}
+#endif
+ return error;
}
-static void init_syserr();
+static VALUE
+syserr_errno(self)
+ VALUE self;
+{
+ return rb_iv_get(self, "errno");
+}
+
+#ifdef __BEOS__
+static VALUE
+get_syserr(int i)
+{
+ VALUE *list;
+ int ix, offset;
+
+ i -= B_GENERAL_ERROR_BASE;
+ ix = (i >> 12) & 0xf;
+ offset = (i >> 8) & 0xf;
+ if (offset < syserr_index[ix].n) {
+ ix = syserr_index[ix].ix;
+ if ((i & 0xff) < syserr_list[ix + offset].n) {
+ list = syserr_list[ix + offset].list;
+ return list[i & 0xff];
+ }
+ }
+ return 0;
+}
+#endif /* __BEOS__ */
+
+static void init_syserr _((void));
void
Init_Exception()
{
- eGlobalExit = rb_define_class("GlobalExit", cString);
- rb_define_singleton_method(eGlobalExit, "new", exc_s_new, -1);
- rb_define_method(eGlobalExit, "inspect", exc_inspect, 0);
-
- eSystemExit = rb_define_class("SystemExit", eGlobalExit);
- eFatal = rb_define_class("fatal", eGlobalExit);
- eInterrupt = rb_define_class("Interrupt", eGlobalExit);
-
- eException = rb_define_class("Exception", eGlobalExit);
- eSyntaxError = rb_define_class("SyntaxError", eException);
- eTypeError = rb_define_class("TypeError", eException);
- eArgError = rb_define_class("ArgumentError", eException);
- eNameError = rb_define_class("NameError", eException);
- eIndexError = rb_define_class("IndexError", eException);
- eNotImpError = rb_define_class("NotImplementError", eException);
- eLoadError = rb_define_class("LoadError", eException);
-
- eRuntimeError = rb_define_class("RuntimeError", eException);
- eSecurityError = rb_define_class("SecurityError", eException);
+ rb_eException = rb_define_class("Exception", rb_cObject);
+ rb_define_method(rb_eException, "new", exc_new, -1);
+ rb_define_method(rb_eException, "initialize", exc_initialize, -1);
+ rb_define_method(rb_eException, "to_s", exc_to_s, 0);
+ rb_define_method(rb_eException, "to_str", exc_to_s, 0);
+ rb_define_method(rb_eException, "message", exc_to_s, 0);
+ rb_define_method(rb_eException, "inspect", exc_inspect, 0);
+ rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
+ rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
+
+ rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
+ rb_eFatal = rb_define_class("fatal", rb_eException);
+ rb_eInterrupt = rb_define_class("Interrupt", rb_eException);
+
+ rb_eStandardError = rb_define_class("StandardError", rb_eException);
+ rb_eSyntaxError = rb_define_class("SyntaxError", rb_eStandardError);
+ rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
+ rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
+ rb_eNameError = rb_define_class("NameError", rb_eStandardError);
+ rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
+ rb_eLoadError = rb_define_class("LoadError", rb_eStandardError);
+
+ rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
+ rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
+ rb_eNotImpError = rb_define_class("NotImplementError", rb_eException);
init_syserr();
rb_define_global_function("Exception", exception, -1);
}
-#define RAISE_ERROR(class) {\
- va_list args;\
- char buf[BUFSIZ];\
-\
- va_start(args);\
- vsprintf(buf, fmt, args);\
- va_end(args);\
-\
- rb_raise(exc_new2(class, buf));\
-}
-
void
-Raise(exc, fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_raise(VALUE exc, char *fmt, ...)
+#else
+rb_raise(exc, fmt, va_alist)
VALUE exc;
char *fmt;
va_dcl
+#endif
{
- RAISE_ERROR(exc);
-}
-
-void
-TypeError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eTypeError);
-}
-
-void
-ArgError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eArgError);
-}
+ va_list args;
+ char buf[BUFSIZ];
-void
-NameError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eNameError);
+ va_init_list(args,fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
+ va_end(args);
+ rb_exc_raise(rb_exc_new2(exc, buf));
}
void
-IndexError(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_loaderror(char *fmt, ...)
+#else
+rb_loaderror(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
- RAISE_ERROR(eIndexError);
-}
+ va_list args;
+ char buf[BUFSIZ];
-void
-Fail(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eRuntimeError);
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
+ va_end(args);
+ rb_exc_raise(rb_exc_new2(rb_eLoadError, buf));
}
void
rb_notimplement()
{
- Raise(eNotImpError,
- "The %s() function is unimplemented on this machine",
- rb_id2name(the_frame->last_func));
+ rb_raise(rb_eNotImpError,
+ "The %s() function is unimplemented on this machine",
+ rb_id2name(ruby_frame->last_func));
}
void
-LoadError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eLoadError);
-}
-
-void
-Fatal(fmt, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_fatal(char *fmt, ...)
+#else
+rb_fatal(fmt, va_alist)
char *fmt;
va_dcl
+#endif
{
va_list args;
char buf[BUFSIZ];
- va_start(args);
- vsprintf(buf, fmt, args);
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
rb_in_eval = 0;
- rb_fatal(exc_new2(eFatal, buf));
+ rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
}
void
@@ -441,32 +635,79 @@ rb_sys_fail(mesg)
#ifndef NT
char *strerror();
#endif
- char buf[BUFSIZ];
+ char *err;
+ char *buf;
extern int errno;
int n = errno;
+ VALUE ee;
- if (RTEST(mesg))
- sprintf(buf, "%s - %s", strerror(errno), mesg);
- else
- sprintf(buf, "%s", strerror(errno));
+ err = strerror(errno);
+ if (mesg) {
+ buf = ALLOCA_N(char, strlen(err)+strlen(mesg)+4);
+ sprintf(buf, "%s - %s", err, mesg);
+ }
+ else {
+ buf = ALLOCA_N(char, strlen(err)+1);
+ strcpy(buf, err);
+ }
errno = 0;
+#ifdef __BEOS__
+ ee = get_syserr(n);
+ if (!ee) {
+ char name[6];
+
+ sprintf(name, "E%03d", n);
+ ee = set_syserr(n, name);
+ }
+#else
+# ifdef USE_CWGUSI
+ if (n < 0) {
+ int macoserr_index = sys_nerr - 1;
+ if (!syserr_list[macoserr_index]) {
+ char name[6];
+ sprintf(name, "E%03d", macoserr_index);
+ ee = set_syserr(macoserr_index, name);
+ }
+ }
+ else
+#endif /* USE_CWGUSI */
if (n > sys_nerr || !syserr_list[n]) {
char name[6];
sprintf(name, "E%03d", n);
- set_syserr(n, name);
+ ee = set_syserr(n, name);
+ }
+ else {
+ ee = syserr_list[n];
}
- rb_raise(exc_new2(syserr_list[n], buf));
+ ee = rb_exc_new2(ee, buf);
+#endif
+ rb_iv_set(ee, "errno", INT2FIX(n));
+ rb_exc_raise(ee);
}
static void
init_syserr()
{
- eSystemCallError = rb_define_class("SystemCallError", eException);
- mErrno = rb_define_module("Errno");
+#ifdef __BEOS__
+ int i, ix, offset;
+#endif
+ rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
+ rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
+
+ rb_mErrno = rb_define_module("Errno");
+#ifdef __BEOS__
+ for (i = 0; syserr_index[i].n != 0; i++) {
+ ix = syserr_index[i].ix;
+ for (offset = 0; offset < syserr_index[i].n; offset++) {
+ MEMZERO(syserr_list[ix + offset].list, VALUE, syserr_list[ix + offset].n);
+ }
+ }
+#else
syserr_list = ALLOC_N(VALUE, sys_nerr+1);
MEMZERO(syserr_list, VALUE, sys_nerr+1);
+#endif
#ifdef EPERM
set_syserr(EPERM, "EPERM");
@@ -835,3 +1076,28 @@ init_syserr()
set_syserr(EDQUOT, "EDQUOT");
#endif
}
+
+static void
+err_append(s)
+ char *s;
+{
+ extern VALUE rb_errinfo;
+
+ if (rb_in_eval) {
+ if (NIL_P(rb_errinfo)) {
+ rb_errinfo = rb_exc_new2(rb_eSyntaxError, s);
+ }
+ else {
+ VALUE str = rb_str_to_str(rb_errinfo);
+
+ rb_str_cat(str, "\n", 1);
+ rb_str_cat(str, s, strlen(s));
+ rb_errinfo = rb_exc_new3(rb_eSyntaxError, str);
+ }
+ }
+ else {
+ fputs(s, stderr);
+ fputs("\n", stderr);
+ fflush(stderr);
+ }
+}
diff --git a/eval.c b/eval.c
index 42617c2b27..a7da313fbe 100644
--- a/eval.c
+++ b/eval.c
@@ -6,14 +6,14 @@
$Date$
created at: Thu Jun 10 14:22:17 JST 1993
- Copyright (C) 1993-1997 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "node.h"
#include "env.h"
-#include "sig.h"
+#include "rubysig.h"
#include <stdio.h>
#include <setjmp.h>
@@ -21,13 +21,23 @@
#include "dln.h"
#ifndef HAVE_STRING_H
-char *strrchr();
+char *strrchr _((char*,char));
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef __BEOS__
+#include <net/socket.h>
+#endif
+
+#ifdef USE_CWGUSI
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <compat.h>
+#endif
+
#ifndef setjmp
#ifdef HAVE__SETJMP
#define setjmp(env) _setjmp(env)
@@ -35,23 +45,33 @@ char *strrchr();
#endif
#endif
-extern VALUE cData;
-
-VALUE cProc;
+VALUE rb_cProc;
+static VALUE rb_cBinding;
static VALUE proc_call _((VALUE,VALUE));
-static VALUE f_binding _((VALUE));
-static void f_END _((void));
-
-#define SCOPE_PRIVATE FL_USER4
-
-#define CACHE_SIZE 0x200
-#define CACHE_MASK 0x1ff
-#define EXPR1(c,m) ((((int)(c)>>3)^(m))&CACHE_MASK)
+static VALUE rb_f_binding _((VALUE));
+static void rb_f_END _((void));
+static VALUE rb_f_iterator_p _((void));
+static VALUE block_pass _((VALUE,NODE*));
+static VALUE rb_cMethod;
+static VALUE method_proc _((VALUE));
+
+static int scope_vmode;
+#define SCOPE_PUBLIC 0
+#define SCOPE_PRIVATE 1
+#define SCOPE_PROTECTED 2
+#define SCOPE_MODFUNC 5
+#define SCOPE_MASK 7
+#define SCOPE_SET(f) do {scope_vmode=(f);} while(0)
+#define SCOPE_TEST(f) (scope_vmode&(f))
+
+#define CACHE_SIZE 0x800
+#define CACHE_MASK 0x7ff
+#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
struct cache_entry { /* method hash table. */
ID mid; /* method's id */
ID mid0; /* method's original id */
- VALUE class; /* receiver's class */
+ VALUE klass; /* receiver's class */
VALUE origin; /* where method defined */
NODE *method;
int noex;
@@ -87,80 +107,69 @@ rb_clear_cache_by_id(id)
}
void
-rb_add_method(class, mid, node, noex)
- VALUE class;
+rb_add_method(klass, mid, node, noex)
+ VALUE klass;
ID mid;
NODE *node;
int noex;
{
NODE *body;
- if (NIL_P(class)) class = cObject;
- body = NEW_METHOD(node, noex);
- st_insert(RCLASS(class)->m_tbl, mid, body);
-}
-
-void
-rb_remove_method(class, mid)
- VALUE class;
- ID mid;
-{
- NODE *body;
-
- if (!st_delete(RCLASS(class)->m_tbl, &mid, &body)) {
- NameError("method `%s' not defined in %s",
- rb_id2name(mid), rb_class2name(class));
+ if (NIL_P(klass)) klass = rb_cObject;
+ if (klass == rb_cObject) {
+ rb_secure(4);
}
- rb_clear_cache_by_id(mid);
+ body = NEW_METHOD(node, noex);
+ st_insert(RCLASS(klass)->m_tbl, mid, body);
}
static NODE*
-search_method(class, id, origin)
- VALUE class, *origin;
+search_method(klass, id, origin)
+ VALUE klass, *origin;
ID id;
{
NODE *body;
- while (!st_lookup(RCLASS(class)->m_tbl, id, &body)) {
- class = (VALUE)RCLASS(class)->super;
- if (!class) return 0;
+ while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
+ klass = RCLASS(klass)->super;
+ if (!klass) return 0;
}
- if (origin) *origin = class;
+ if (origin) *origin = klass;
return body;
}
static NODE*
-rb_get_method_body(classp, idp, noexp)
- VALUE *classp;
+rb_get_method_body(klassp, idp, noexp)
+ VALUE *klassp;
ID *idp;
int *noexp;
{
ID id = *idp;
- VALUE class = *classp;
+ VALUE klass = *klassp;
VALUE origin;
- NODE *body;
+ NODE * volatile body;
struct cache_entry *ent;
- if ((body = search_method(class, id, &origin)) == 0) {
+ if ((body = search_method(klass, id, &origin)) == 0) {
return 0;
}
if (!body->nd_body) return 0;
/* store in cache */
- ent = cache + EXPR1(class, id);
- ent->class = class;
+ ent = cache + EXPR1(klass, id);
+ ent->klass = klass;
ent->noex = body->nd_noex;
body = body->nd_body;
if (nd_type(body) == NODE_FBODY) {
ent->mid = id;
- *classp = body->nd_orig;
+ *klassp = body->nd_orig;
ent->origin = body->nd_orig;
*idp = ent->mid0 = body->nd_mid;
body = ent->method = body->nd_head;
}
else {
- *classp = (VALUE)origin;
+ *klassp = origin;
ent->origin = origin;
ent->mid = ent->mid0 = id;
ent->method = body;
@@ -171,23 +180,26 @@ rb_get_method_body(classp, idp, noexp)
}
void
-rb_alias(class, name, def)
- VALUE class;
+rb_alias(klass, name, def)
+ VALUE klass;
ID name, def;
{
VALUE origin;
NODE *orig, *body;
if (name == def) return;
- orig = search_method(class, def, &origin);
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ orig = search_method(klass, def, &origin);
if (!orig || !orig->nd_body) {
- if (TYPE(class) == T_MODULE) {
- orig = search_method(cObject, def, &origin);
+ if (TYPE(klass) == T_MODULE) {
+ orig = search_method(rb_cObject, def, &origin);
}
}
if (!orig || !orig->nd_body) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(def), rb_class2name((VALUE)class));
+ rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
+ rb_id2name(def), rb_class2name(klass));
}
body = orig->nd_body;
if (nd_type(body) == NODE_FBODY) { /* was alias */
@@ -196,101 +208,194 @@ rb_alias(class, name, def)
origin = body->nd_orig;
}
- st_insert(RCLASS(class)->m_tbl, name,
+ st_insert(RCLASS(klass)->m_tbl, name,
NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
}
static void
-rb_export_method(class, name, noex)
- VALUE class;
+remove_method(klass, mid)
+ VALUE klass;
+ ID mid;
+{
+ NODE *body;
+
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) {
+ rb_raise(rb_eNameError, "method `%s' not defined in %s",
+ rb_id2name(mid), rb_class2name(klass));
+ }
+ rb_clear_cache_by_id(mid);
+}
+
+void
+rb_remove_method(klass, name)
+ VALUE klass;
+ char *name;
+{
+ remove_method(klass, rb_intern(name));
+}
+
+void
+rb_disable_super(klass, name)
+ VALUE klass;
+ char *name;
+{
+ VALUE origin;
+ NODE *body;
+ ID mid = rb_intern(name);
+
+ body = search_method(klass, mid, &origin);
+ if (!body || !body->nd_body) {
+ rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
+ rb_id2name(mid), rb_class2name(klass));
+ }
+ if (origin == klass) {
+ body->nd_noex |= NOEX_UNDEF;
+ }
+ else {
+ rb_clear_cache_by_id(mid);
+ rb_add_method(ruby_class, mid, 0, NOEX_UNDEF);
+ }
+}
+
+void
+rb_enable_super(klass, name)
+ VALUE klass;
+ char *name;
+{
+ VALUE origin;
+ NODE *body;
+ ID mid = rb_intern(name);
+
+ body = search_method(klass, mid, &origin);
+ if (!body || !body->nd_body || origin != klass) {
+ rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
+ rb_id2name(mid), rb_class2name(klass));
+ }
+ body->nd_noex &= ~NOEX_UNDEF;
+}
+
+static void
+rb_export_method(klass, name, noex)
+ VALUE klass;
ID name;
- int noex;
+ ID noex;
{
NODE *body;
- struct RClass *origin;
+ VALUE origin;
- body = search_method(class, name, &origin);
- if (!body && TYPE(class) == T_MODULE) {
- body = search_method(cObject, name, &origin);
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ body = search_method(klass, name, &origin);
+ if (!body && TYPE(klass) == T_MODULE) {
+ body = search_method(rb_cObject, name, &origin);
}
if (!body) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(name), rb_class2name(class));
+ rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
+ rb_id2name(name), rb_class2name(klass));
}
if (body->nd_noex != noex) {
- if (class == (VALUE)origin) {
+ if (klass == origin) {
body->nd_noex = noex;
}
else {
rb_clear_cache_by_id(name);
- rb_add_method(class, name, NEW_ZSUPER(), noex);
+ rb_add_method(klass, name, NEW_ZSUPER(), noex);
}
}
}
-static VALUE
-method_boundp(class, id, ex)
- VALUE class;
+int
+rb_method_boundp(klass, id, ex)
+ VALUE klass;
ID id;
int ex;
{
int noex;
- if (rb_get_method_body(&class, &id, &noex)) {
- if (ex && noex == NOEX_PRIVATE)
- return FALSE;
- return TRUE;
+ if (rb_get_method_body(&klass, &id, &noex)) {
+ if (ex && noex & NOEX_PRIVATE)
+ return Qfalse;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
-int
-rb_method_boundp(class, id, ex)
- VALUE class;
+void
+rb_attr(klass, id, read, write, ex)
+ VALUE klass;
ID id;
- int ex;
+ int read, write, ex;
{
- if (method_boundp(class, id, ex))
- return TRUE;
- return FALSE;
+ char *name;
+ char *buf;
+ ID attriv;
+ int noex;
+
+ if (!ex) noex = NOEX_PUBLIC;
+ else {
+ if (SCOPE_TEST(SCOPE_PRIVATE)) {
+ noex = NOEX_PRIVATE;
+ rb_warning("private attribute?");
+ }
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
+ }
+ else {
+ noex = NOEX_PUBLIC;
+ }
+ }
+
+ name = rb_id2name(id);
+ if (!name) {
+ rb_raise(rb_eArgError, "argument needs to be symbol or string");
+ }
+ buf = ALLOCA_N(char,strlen(name)+2);
+ sprintf(buf, "@%s", name);
+ attriv = rb_intern(buf);
+ if (read) {
+ rb_add_method(klass, id, NEW_IVAR(attriv), noex);
+ }
+ sprintf(buf, "%s=", name);
+ id = rb_intern(buf);
+ if (write) {
+ rb_add_method(klass, id, NEW_ATTRSET(attriv), noex);
+ }
}
static ID init, eqq, each, aref, aset, match;
-VALUE errinfo = Qnil, errat = Qnil;
-extern NODE *eval_tree0;
-extern NODE *eval_tree;
-extern int nerrs;
-
-extern VALUE mKernel;
-extern VALUE cModule;
-extern VALUE cClass;
-extern VALUE eFatal;
-extern VALUE eGlobalExit;
-extern VALUE eInterrupt;
-extern VALUE eSystemExit;
-extern VALUE eException;
-extern VALUE eRuntimeError;
-extern VALUE eSyntaxError;
-static VALUE eLocalJumpError;
-extern VALUE eSecurityError;
-
-extern VALUE TopSelf;
-
-struct FRAME *the_frame;
-struct SCOPE *the_scope;
+VALUE rb_errinfo = Qnil;
+extern NODE *ruby_eval_tree_begin;
+extern NODE *ruby_eval_tree;
+extern int ruby_nerrs;
+
+static VALUE rb_eLocalJumpError;
+static VALUE rb_eSysStackError;
+
+extern VALUE ruby_top_self;
+
+struct FRAME *ruby_frame;
+struct SCOPE *ruby_scope;
static struct FRAME *top_frame;
static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
- struct FRAME *_frame = ALLOCA_N(struct FRAME,1);\
- _frame->prev = the_frame; \
- _frame->file = sourcefile; \
- _frame->line = sourceline; \
- _frame->iter = the_iter->iter; \
- _frame->cbase = the_frame->cbase; \
- the_frame = _frame; \
-
-#define POP_FRAME() the_frame = _frame->prev; }
+ struct FRAME _frame; \
+ _frame.prev = ruby_frame; \
+ _frame.file = ruby_sourcefile; \
+ _frame.line = ruby_sourceline; \
+ _frame.iter = ruby_iter->iter; \
+ _frame.cbase = ruby_frame->cbase; \
+ _frame.argc = 0; \
+ ruby_frame = &_frame; \
+
+#define POP_FRAME() \
+ ruby_sourcefile = _frame.file; \
+ ruby_sourceline = _frame.line; \
+ ruby_frame = _frame.prev; }
struct BLOCK {
NODE *var;
@@ -298,70 +403,95 @@ struct BLOCK {
VALUE self;
struct FRAME frame;
struct SCOPE *scope;
- VALUE class;
+ VALUE klass;
struct tag *tag;
int iter;
+ int vmode;
struct RVarmap *d_vars;
-#ifdef THREAD
+#ifdef USE_THREAD
VALUE orig_thread;
#endif
struct BLOCK *prev;
-} *the_block;
+};
+static struct BLOCK *ruby_block;
+static struct BLOCK *ruby_calling_block;
#define PUSH_BLOCK(v,b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- _block->tag = prot_tag; \
- _block->var = v; \
- _block->body = b; \
- _block->self = self; \
- _block->frame = *the_frame; \
- _block->class = the_class; \
- _block->frame.file = sourcefile; \
- _block->frame.line = sourceline; \
- _block->scope = the_scope; \
- _block->d_vars = the_dyna_vars; \
- _block->prev = the_block; \
- _block->iter = the_iter->iter; \
- the_block = _block;
+ struct BLOCK _block; \
+ _block.tag = prot_tag; \
+ _block.var = v; \
+ _block.body = b; \
+ _block.self = self; \
+ _block.frame = *ruby_frame; \
+ _block.klass = ruby_class; \
+ _block.frame.file = ruby_sourcefile;\
+ _block.frame.line = ruby_sourceline;\
+ _block.scope = ruby_scope; \
+ _block.d_vars = ruby_dyna_vars; \
+ _block.prev = ruby_block; \
+ _block.iter = ruby_iter->iter; \
+ _block.vmode = scope_vmode; \
+ ruby_block = &_block;
+
+#define POP_BLOCK() \
+ ruby_block = _block.prev; \
+}
#define PUSH_BLOCK2(b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- *_block = *b; \
- _block->prev = the_block; \
- the_block = _block;
+ struct BLOCK * volatile _old; \
+ struct BLOCK * volatile _old_call; \
+ _old = ruby_block; \
+ _old_call = ruby_calling_block; \
+ ruby_calling_block = b; \
+ ruby_block = b;
-#define POP_BLOCK() \
- the_block = the_block->prev; \
+#define POP_BLOCK2() \
+ ruby_calling_block = _old_call; \
+ ruby_block = _old; \
}
-struct RVarmap *the_dyna_vars;
+struct RVarmap *ruby_dyna_vars;
#define PUSH_VARS() { \
- struct RVarmap *_old; \
- _old = the_dyna_vars; \
- the_dyna_vars = 0;
+ struct RVarmap * volatile _oldvmap; \
+ _oldvmap = ruby_dyna_vars; \
+ ruby_dyna_vars = 0;
#define POP_VARS() \
- the_dyna_vars = _old; \
+ ruby_dyna_vars = _oldvmap; \
+}
+
+static struct RVarmap*
+new_dvar(id, value)
+ ID id;
+ VALUE value;
+{
+ NEWOBJ(vars, struct RVarmap);
+ OBJSETUP(vars, 0, T_VARMAP);
+ vars->id = id;
+ vars->val = value;
+ vars->next = ruby_dyna_vars;
+
+ return vars;
}
VALUE
-dyna_var_defined(id)
+rb_dvar_defined(id)
ID id;
{
- struct RVarmap *vars = the_dyna_vars;
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
- if (vars->id == id) return TRUE;
+ if (vars->id == id) return Qtrue;
vars = vars->next;
}
- return FALSE;
+ return Qfalse;
}
VALUE
-dyna_var_ref(id)
+rb_dvar_ref(id)
ID id;
{
- struct RVarmap *vars = the_dyna_vars;
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
if (vars->id == id) {
@@ -372,35 +502,48 @@ dyna_var_ref(id)
return Qnil;
}
-VALUE
-dyna_var_asgn(id, value)
+void
+rb_dvar_push(id, value)
ID id;
VALUE value;
{
- struct RVarmap *vars = the_dyna_vars;
+ ruby_dyna_vars = new_dvar(id, value);
+}
+
+void
+rb_dvar_asgn(id, value)
+ ID id;
+ VALUE value;
+{
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
if (vars->id == id) {
vars->val = value;
- return value;
+ return;
}
vars = vars->next;
}
- {
- NEWOBJ(_vars, struct RVarmap);
- OBJSETUP(_vars, 0, T_VARMAP);
- _vars->id = id;
- _vars->val = value;
- _vars->next = the_dyna_vars;
- the_dyna_vars = _vars;
+ rb_dvar_push(id, value);
+ return;
+}
+
+static void
+dvar_asgn_push(id, value)
+ ID id;
+ VALUE value;
+{
+ rb_dvar_asgn(id, value);
+ if (ruby_calling_block) {
+ ruby_calling_block->d_vars = ruby_dyna_vars;
}
- return value;
}
-static struct iter {
+struct iter {
int iter;
struct iter *prev;
-} *the_iter;
+};
+static struct iter *ruby_iter;
#define ITER_NOT 0
#define ITER_PRE 1
@@ -408,46 +551,35 @@ static struct iter {
#define PUSH_ITER(i) { \
struct iter _iter; \
- _iter.prev = the_iter; \
+ _iter.prev = ruby_iter; \
_iter.iter = (i); \
- the_iter = &_iter; \
+ ruby_iter = &_iter; \
#define POP_ITER() \
- the_iter = _iter.prev; \
+ ruby_iter = _iter.prev; \
}
-#ifdef C_ALLOCA
-/* need to protect retval in struct tag from GC. */
-#define tag_retval_dcl VALUE *dd_retval
-#define tag_retval_init VALUE _tag_retval = Qnil;\
- _tag->dd_retval = &_tag_retval;
-#define tag_retval dd_retval[0]
-#else
-#define tag_retval_dcl VALUE retval
-#define tag_retval_init _tag->retval = Qnil
-#define tag_retval retval
-#endif
-
-static struct tag {
+struct tag {
jmp_buf buf;
struct FRAME *frame;
struct iter *iter;
ID tag;
- tag_retval_dcl;
- ID dst;
+ VALUE retval;
+ int dst;
struct tag *prev;
-} *prot_tag;
+};
+static struct tag *prot_tag;
#define PUSH_TAG(ptag) { \
- struct tag *_tag = ALLOCA_N(struct tag,1);\
- tag_retval_init; \
- _tag->frame = the_frame; \
- _tag->iter = the_iter; \
- _tag->prev = prot_tag; \
- _tag->tag_retval = Qnil; \
- _tag->tag = ptag; \
- _tag->dst = 0; \
- prot_tag = _tag;
+ struct tag _tag; \
+ _tag.retval = Qnil; \
+ _tag.frame = ruby_frame; \
+ _tag.iter = ruby_iter; \
+ _tag.prev = prot_tag; \
+ _tag.retval = Qnil; \
+ _tag.tag = ptag; \
+ _tag.dst = 0; \
+ prot_tag = &_tag;
#define PROT_NONE 0
#define PROT_FUNC -1
@@ -456,13 +588,15 @@ static struct tag {
#define EXEC_TAG() setjmp(prot_tag->buf)
#define JUMP_TAG(st) { \
- the_frame = prot_tag->frame; \
- the_iter = prot_tag->iter; \
+ ruby_frame = prot_tag->frame; \
+ ruby_iter = prot_tag->iter; \
longjmp(prot_tag->buf,(st)); \
}
#define POP_TAG() \
- prot_tag = _tag->prev; \
+ if (_tag.prev) \
+ _tag.prev->retval = _tag.retval;\
+ prot_tag = _tag.prev; \
}
#define TAG_RETURN 0x1
@@ -475,57 +609,68 @@ static struct tag {
#define TAG_FATAL 0x8
#define TAG_MASK 0xf
-VALUE the_class;
+VALUE ruby_class;
+static VALUE ruby_wrapper; /* security wrapper */
#define PUSH_CLASS() { \
- VALUE _class = the_class; \
+ VALUE _class = ruby_class; \
-#define POP_CLASS() the_class = _class; }
+#define POP_CLASS() ruby_class = _class; }
#define PUSH_SCOPE() { \
- struct SCOPE *_old; \
+ volatile int _vmode = scope_vmode; \
+ struct SCOPE * volatile _old; \
NEWOBJ(_scope, struct SCOPE); \
OBJSETUP(_scope, 0, T_SCOPE); \
_scope->local_tbl = 0; \
_scope->local_vars = 0; \
_scope->flag = 0; \
- _old = the_scope; \
- the_scope = _scope; \
+ _old = ruby_scope; \
+ ruby_scope = _scope; \
+ scope_vmode = SCOPE_PUBLIC;
+
+#define SCOPE_DONT_RECYCLE FL_USER2
+
+static void scope_dup(struct SCOPE *);
#define POP_SCOPE() \
- if (the_scope->flag == SCOPE_ALLOCA) {\
- the_scope->local_vars = 0;\
- the_scope->local_tbl = 0;\
- if (the_scope != top_scope)\
- gc_force_recycle(the_scope);\
+ if (ruby_scope->flag == SCOPE_ALLOCA) {\
+ if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE)) {\
+ scope_dup(ruby_scope);\
+ FL_SET(_old, SCOPE_DONT_RECYCLE);\
+ }\
+ else {\
+ ruby_scope->local_vars = 0;\
+ ruby_scope->local_tbl = 0;\
+ if (ruby_scope != top_scope)\
+ rb_gc_force_recycle((VALUE)ruby_scope);\
+ }\
}\
else {\
- the_scope->flag |= SCOPE_NOSTACK;\
+ ruby_scope->flag |= SCOPE_NOSTACK;\
}\
- the_scope = _old;\
+ ruby_scope = _old;\
+ scope_vmode = _vmode;\
}
-static VALUE rb_eval();
-static VALUE eval();
-static NODE *compile();
+static VALUE rb_eval _((VALUE,NODE*));
+static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
+static NODE *compile _((VALUE,char*));
+static VALUE rb_yield_0 _((VALUE, VALUE, VALUE));
-static VALUE rb_call();
-VALUE rb_apply();
-VALUE rb_funcall2();
+static VALUE rb_call _((VALUE,VALUE,ID,int,VALUE*,int));
+static VALUE module_setup _((VALUE,NODE*));
-static VALUE module_setup();
-
-static VALUE massign();
-static void assign();
+static VALUE massign _((VALUE,NODE*,VALUE));
+static void assign _((VALUE,NODE*,VALUE));
static int safe_level = 0;
/* safe-level:
0 - strings from streams/environment/ARGV are tainted (default)
1 - no dangerous operation by tainted string
- 2 - some process operations prohibited
+ 2 - process/file operations prohibited
3 - all genetated strings are tainted
- 4 - no global variable value modification/no direct output
- 5 - no instance variable value modification
+ 4 - no global (non-tainted) variable modification/no direct output
*/
int
@@ -556,8 +701,8 @@ safe_setter(val)
int level = NUM2INT(val);
if (level < safe_level) {
- Raise(eSecurityError, "tried to downgrade safe level from %d to %d",
- safe_level, level);
+ rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
+ safe_level, level);
}
safe_level = level;
}
@@ -567,12 +712,14 @@ rb_check_safe_str(x)
VALUE x;
{
if (TYPE(x)!= T_STRING) {
- TypeError("wrong argument type %s (expected String)",
- rb_class2name(CLASS_OF(x)));
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
+ rb_class2name(CLASS_OF(x)));
}
- if (rb_safe_level() > 0 && str_tainted(x)) {
- Raise(eSecurityError, "Insecure operation - %s",
- rb_id2name(the_frame->last_func));
+ if (OBJ_TAINTED(x)) {
+ if (safe_level > 0){
+ rb_raise(rb_eSecurityError, "Insecure operation - %s",
+ rb_id2name(ruby_frame->last_func));
+ }
}
}
@@ -581,87 +728,95 @@ rb_secure(level)
int level;
{
if (level <= safe_level) {
- Raise(eSecurityError, "Insecure operation `%s' for level %d",
- rb_id2name(the_frame->last_func), level);
+ rb_raise(rb_eSecurityError, "Insecure operation `%s' for level %d",
+ rb_id2name(ruby_frame->last_func), safe_level);
}
}
-extern int sourceline;
-extern char *sourcefile;
-
static VALUE trace_func = 0;
-static void call_trace_func();
+static void call_trace_func _((char*,char*,int,VALUE,ID,VALUE));
static void
error_pos()
{
- if (sourcefile) {
- if (the_frame->last_func) {
- fprintf(stderr, "%s:%d:in `%s'", sourcefile, sourceline,
- rb_id2name(the_frame->last_func));
+ if (ruby_sourcefile) {
+ if (ruby_frame->last_func) {
+ fprintf(stderr, "%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
+ rb_id2name(ruby_frame->last_func));
}
else {
- fprintf(stderr, "%s:%d", sourcefile, sourceline);
+ fprintf(stderr, "%s:%d", ruby_sourcefile, ruby_sourceline);
}
}
}
+static VALUE
+get_backtrace(info)
+ VALUE info;
+{
+ if (NIL_P(info)) return Qnil;
+ return rb_funcall(info, rb_intern("backtrace"), 0);
+}
+
+static void
+set_backtrace(info, bt)
+ VALUE info, bt;
+{
+ rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
+}
+
static void
error_print()
{
+ VALUE errat;
VALUE eclass;
+ VALUE einfo;
+ volatile int safe = safe_level;
- if (NIL_P(errinfo)) return;
+ if (NIL_P(rb_errinfo)) return;
+ errat = get_backtrace(rb_errinfo);
if (!NIL_P(errat)) {
- VALUE mesg = Qnil;
+ VALUE mesg = RARRAY(errat)->ptr[0];
- switch (TYPE(errat)) {
- case T_STRING:
- mesg = errat;
- errat = Qnil;
- break;
- case T_ARRAY:
- mesg = RARRAY(errat)->ptr[0];
- break;
- }
if (NIL_P(mesg)) error_pos();
else {
fwrite(RSTRING(mesg)->ptr, 1, RSTRING(mesg)->len, stderr);
}
}
- eclass = CLASS_OF(errinfo);
- if (eclass == eRuntimeError && RSTRING(errinfo)->len == 0) {
+ eclass = CLASS_OF(rb_errinfo);
+ einfo = rb_obj_as_string(rb_errinfo);
+ if (eclass == rb_eRuntimeError && RSTRING(einfo)->len == 0) {
fprintf(stderr, ": unhandled exception\n");
}
else {
VALUE epath;
epath = rb_class_path(eclass);
- if (RSTRING(errinfo)->len == 0) {
+ if (RSTRING(einfo)->len == 0) {
fprintf(stderr, ": ");
fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr);
putc('\n', stderr);
}
else {
- unsigned char *tail = 0;
- int len = RSTRING(errinfo)->len;
+ char *tail = 0;
+ int len = RSTRING(einfo)->len;
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = strchr(RSTRING(errinfo)->ptr, '\n')) {
- len = tail - RSTRING(errinfo)->ptr;
+ if (tail = strchr(RSTRING(einfo)->ptr, '\n')) {
+ len = tail - RSTRING(einfo)->ptr;
tail++; /* skip newline */
}
fprintf(stderr, ": ");
- fwrite(RSTRING(errinfo)->ptr, 1, len, stderr);
+ fwrite(RSTRING(einfo)->ptr, 1, len, stderr);
if (epath) {
fprintf(stderr, " (");
fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr);
fprintf(stderr, ")\n");
}
if (tail) {
- fwrite(tail, 1, RSTRING(errinfo)->len-len-1, stderr);
+ fwrite(tail, 1, RSTRING(einfo)->len-len-1, stderr);
putc('\n', stderr);
}
}
@@ -677,7 +832,9 @@ error_print()
ep = RARRAY(errat);
for (i=1; i<ep->len; i++) {
- fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
+ if (TYPE(ep->ptr[i]) == T_STRING) {
+ fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
+ }
if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
fprintf(stderr, "\t ... %d levels...\n",
ep->len - TRACE_HEAD - TRACE_TAIL);
@@ -685,18 +842,18 @@ error_print()
}
}
}
+ safe_level = safe;
}
-#ifndef NT
+#if !defined(NT) && !defined(__MACOS__)
extern char **environ;
#endif
-char **origenviron;
+char **rb_origenviron;
void rb_call_inits _((void));
-void init_stack _((void));
-void init_heap _((void));
+void Init_stack _((void));
+void Init_heap _((void));
void Init_ext _((void));
-void gc_call_finalizer_at_exit _((void));
void
ruby_init()
@@ -705,31 +862,36 @@ ruby_init()
static struct iter iter;
int state;
- the_frame = top_frame = &frame;
- the_iter = &iter;
+ ruby_frame = top_frame = &frame;
+ ruby_iter = &iter;
- origenviron = environ;
+#ifdef __MACOS__
+ rb_origenviron = 0;
+#else
+ rb_origenviron = environ;
+#endif
- init_heap();
+ Init_heap();
PUSH_SCOPE();
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
- top_scope = the_scope;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
+ top_scope = ruby_scope;
/* default visibility is private at toplevel */
- FL_SET(top_scope, SCOPE_PRIVATE);
+ SCOPE_SET(SCOPE_PRIVATE);
PUSH_TAG(PROT_NONE)
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
- the_class = cObject;
- the_frame->cbase = (VALUE)node_newnode(NODE_CREF,cObject,0,0);
- rb_define_global_const("TOPLEVEL_BINDING", f_binding(TopSelf));
+ ruby_class = rb_cObject;
+ ruby_frame->self = ruby_top_self;
+ ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,rb_cObject,0,0);
+ rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
ruby_prog_init();
}
POP_TAG();
if (state) error_print();
POP_SCOPE();
- the_scope = top_scope;
+ ruby_scope = top_scope;
}
static int ext_init = 0;
@@ -746,15 +908,14 @@ ruby_options(argc, argv)
NODE *save;
ruby_process_options(argc, argv);
- save = eval_tree;
- eval_tree = 0;
- Init_ext();
- ext_init = 1;
- rb_require_modules();
- eval_tree = save;
+ ext_init = 1; /* Init_ext() called in ruby_process_options */
+ save = ruby_eval_tree;
+ ruby_require_modules();
+ ruby_eval_tree = save;
}
POP_TAG();
if (state) {
+ trace_func = 0;
error_print();
exit(1);
}
@@ -767,16 +928,16 @@ eval_node(self)
VALUE result = Qnil;
NODE *tree;
- if (eval_tree0) {
- tree = eval_tree0;
- eval_tree0 = 0;
+ if (ruby_eval_tree_begin) {
+ tree = ruby_eval_tree_begin;
+ ruby_eval_tree_begin = 0;
rb_eval(self, tree);
}
- if (!eval_tree) return Qnil;
+ if (!ruby_eval_tree) return Qnil;
- tree = eval_tree;
- eval_tree = 0;
+ tree = ruby_eval_tree;
+ ruby_eval_tree = 0;
result = rb_eval(self, tree);
return result;
@@ -784,15 +945,14 @@ eval_node(self)
int rb_in_eval;
-#ifdef THREAD
-static void thread_cleanup();
-static void thread_wait_other_threads();
-static VALUE thread_current();
+#ifdef USE_THREAD
+static void rb_thread_cleanup _((void));
+static void rb_thread_wait_other_threads _((void));
#endif
static int exit_status;
-static void exec_end_proc();
+static void exec_end_proc _((void));
void
ruby_run()
@@ -800,16 +960,15 @@ ruby_run()
int state;
static int ex;
- if (nerrs > 0) exit(nerrs);
+ if (ruby_nerrs > 0) exit(ruby_nerrs);
- init_stack();
- errat = Qnil; /* clear for execution */
+ Init_stack();
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
if (!ext_init) Init_ext();
- eval_node(TopSelf);
+ eval_node(ruby_top_self);
}
POP_ITER();
POP_TAG();
@@ -819,12 +978,10 @@ ruby_run()
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
rb_trap_exit();
-#ifdef THREAD
- thread_cleanup();
- thread_wait_other_threads();
+#ifdef USE_THREAD
+ rb_thread_cleanup();
+ rb_thread_wait_other_threads();
#endif
- exec_end_proc();
- gc_call_finalizer_at_exit();
}
else {
ex = state;
@@ -834,63 +991,69 @@ ruby_run()
switch (ex & 0xf) {
case 0:
- exit(0);
+ ex = 0;
+ break;
case TAG_RETURN:
error_pos();
- fprintf(stderr, "unexpected return\n");
- exit(1);
+ fprintf(stderr, ": unexpected return\n");
+ ex = 1;
break;
case TAG_NEXT:
error_pos();
- fprintf(stderr, "unexpected next\n");
- exit(1);
+ fprintf(stderr, ": unexpected next\n");
+ ex = 1;
break;
case TAG_BREAK:
error_pos();
- fprintf(stderr, "unexpected break\n");
- exit(1);
+ fprintf(stderr, ": unexpected break\n");
+ ex = 1;
break;
case TAG_REDO:
error_pos();
- fprintf(stderr, "unexpected redo\n");
- exit(1);
+ fprintf(stderr, ": unexpected redo\n");
+ ex = 1;
break;
case TAG_RETRY:
error_pos();
- fprintf(stderr, "retry outside of rescue clause\n");
- exit(1);
+ fprintf(stderr, ": retry outside of rescue clause\n");
+ ex = 1;
break;
case TAG_RAISE:
case TAG_FATAL:
- if (obj_is_kind_of(errinfo, eSystemExit)) {
+ if (rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
exit(exit_status);
}
error_print();
- exit(1);
+ ex = 1;
break;
default:
- Bug("Unknown longjmp status %d", ex);
+ rb_bug("Unknown longjmp status %d", ex);
break;
}
+ exec_end_proc();
+ rb_gc_call_finalizer_at_exit();
+ exit(ex);
}
static void
compile_error(at)
char *at;
{
- VALUE mesg;
+ VALUE str;
+ char *mesg;
+ int len;
- mesg = errinfo;
- nerrs = 0;
- errinfo = exc_new2(eSyntaxError, "compile error");
+ mesg = str2cstr(rb_errinfo, &len);
+ ruby_nerrs = 0;
+ str = rb_str_new2("compile error");
if (at) {
- str_cat(errinfo, " in ", 4);
- str_cat(errinfo, at, strlen(at));
+ rb_str_cat(str, " in ", 4);
+ rb_str_cat(str, at, strlen(at));
}
- str_cat(errinfo, "\n", 1);
- str_cat(errinfo, RSTRING(mesg)->ptr, RSTRING(mesg)->len);
- rb_raise(errinfo);
+ rb_str_cat(str, "\n", 1);
+ rb_str_cat(str, mesg, len);
+ rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
}
VALUE
@@ -898,45 +1061,67 @@ rb_eval_string(str)
char *str;
{
VALUE v;
- char *oldsrc = sourcefile;
+ char *oldsrc = ruby_sourcefile;
- sourcefile = "(eval)";
- v = eval(TopSelf, str_new2(str), Qnil);
- sourcefile = oldsrc;
+ ruby_sourcefile = "(eval)";
+ v = eval(ruby_top_self, rb_str_new2(str), Qnil, 0, 0);
+ ruby_sourcefile = oldsrc;
return v;
}
-void
+VALUE
+rb_eval_string_protect(str, state)
+ char *str;
+ int *state;
+{
+ VALUE result; /* OK */
+ int status;
+
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = rb_eval_string(str);
+ }
+ POP_TAG();
+ if (state) {
+ *state = status;
+ }
+ if (status != 0) {
+ return Qnil;
+ }
+
+ return result;
+}
+
+VALUE
rb_eval_cmd(cmd, arg)
VALUE cmd, arg;
{
int state;
+ VALUE val; /* OK */
struct SCOPE *saved_scope;
- volatile int safe = rb_safe_level();
+ volatile int safe = safe_level;
if (TYPE(cmd) != T_STRING) {
- Check_Type(arg, T_ARRAY);
- rb_funcall2(cmd, rb_intern("call"),
- RARRAY(arg)->len, RARRAY(arg)->ptr);
- return;
+ return rb_funcall2(cmd, rb_intern("call"),
+ RARRAY(arg)->len, RARRAY(arg)->ptr);
}
PUSH_CLASS();
PUSH_TAG(PROT_NONE);
- saved_scope = the_scope;
- the_scope = top_scope;
+ saved_scope = ruby_scope;
+ ruby_scope = top_scope;
- the_class = cObject;
- if (str_tainted(cmd)) {
- safe_level = 5;
+ ruby_class = rb_cObject;
+ if (OBJ_TAINTED(cmd)) {
+ safe_level = 4;
}
if ((state = EXEC_TAG()) == 0) {
- eval(TopSelf, cmd, Qnil);
+ val = eval(ruby_top_self, cmd, Qnil, 0, 0);
}
- the_scope = saved_scope;
+ ruby_scope = saved_scope;
safe_level = safe;
POP_TAG();
POP_CLASS();
@@ -945,42 +1130,45 @@ rb_eval_cmd(cmd, arg)
case 0:
break;
case TAG_RETURN:
- Raise(eLocalJumpError, "unexpected return");
+ rb_raise(rb_eLocalJumpError, "unexpected return");
break;
case TAG_NEXT:
- Raise(eLocalJumpError, "unexpected next");
+ rb_raise(rb_eLocalJumpError, "unexpected next");
break;
case TAG_BREAK:
- Raise(eLocalJumpError, "unexpected break");
+ rb_raise(rb_eLocalJumpError, "unexpected break");
break;
case TAG_REDO:
- Raise(eLocalJumpError, "unexpected redo");
+ rb_raise(rb_eLocalJumpError, "unexpected redo");
break;
case TAG_RETRY:
- Raise(eLocalJumpError, "retry outside of rescue clause");
+ rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
break;
default:
JUMP_TAG(state);
break;
}
+ return val;
}
-void
+VALUE
rb_trap_eval(cmd, sig)
VALUE cmd;
int sig;
{
int state;
+ VALUE val; /* OK */
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig)));
+ val = rb_eval_cmd(cmd, rb_ary_new3(1, INT2FIX(sig)));
}
POP_TAG();
if (state) {
- trap_immediate = 0;
+ rb_trap_immediate = 0;
JUMP_TAG(state);
}
+ return val;
}
static VALUE
@@ -988,7 +1176,7 @@ superclass(self, node)
VALUE self;
NODE *node;
{
- VALUE val = 0; /* OK */
+ VALUE val; /* OK */
int state;
PUSH_TAG(PROT_NONE);
@@ -996,21 +1184,23 @@ superclass(self, node)
val = rb_eval(self, node);
}
POP_TAG();
- if (state == TAG_RAISE) {
+ if (state) {
superclass_error:
switch (nd_type(node)) {
case NODE_COLON2:
- TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid));
+ rb_raise(rb_eTypeError, "undefined superclass `%s'",
+ rb_id2name(node->nd_mid));
case NODE_CVAR:
- TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid));
+ rb_raise(rb_eTypeError, "undefined superclass `%s'",
+ rb_id2name(node->nd_vid));
default:
- TypeError("superclass undefined");
+ rb_raise(rb_eTypeError, "superclass undefined");
}
JUMP_TAG(state);
}
if (TYPE(val) != T_CLASS) goto superclass_error;
if (FL_TEST(val, FL_SINGLETON)) {
- TypeError("can't make subclass of virtual class");
+ rb_raise(rb_eTypeError, "can't make subclass of virtual class");
}
return val;
@@ -1023,12 +1213,12 @@ ev_const_defined(cref, id)
{
NODE *cbase = cref;
- while (cbase && cbase->nd_clss != cObject) {
- struct RClass *class = RCLASS(cbase->nd_clss);
+ while (cbase && cbase->nd_clss != rb_cObject) {
+ struct RClass *klass = RCLASS(cbase->nd_clss);
- if (class->iv_tbl &&
- st_lookup(class->iv_tbl, id, 0)) {
- return TRUE;
+ if (klass->iv_tbl &&
+ st_lookup(klass->iv_tbl, id, 0)) {
+ return Qtrue;
}
cbase = cbase->nd_next;
}
@@ -1043,11 +1233,11 @@ ev_const_get(cref, id)
NODE *cbase = cref;
VALUE result;
- while (cbase && cbase->nd_clss != cObject) {
- struct RClass *class = RCLASS(cbase->nd_clss);
+ while (cbase && cbase->nd_clss != rb_cObject) {
+ struct RClass *klass = RCLASS(cbase->nd_clss);
- if (class->iv_tbl &&
- st_lookup(class->iv_tbl, id, &result)) {
+ if (klass->iv_tbl &&
+ st_lookup(klass->iv_tbl, id, &result)) {
return result;
}
cbase = cbase->nd_next;
@@ -1056,43 +1246,43 @@ ev_const_get(cref, id)
}
static VALUE
-mod_nesting()
+rb_mod_nesting()
{
- NODE *cbase = (NODE*)the_frame->cbase;
- VALUE ary = ary_new();
+ NODE *cbase = (NODE*)ruby_frame->cbase;
+ VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != cObject) {
- ary_push(ary, cbase->nd_clss);
+ while (cbase && cbase->nd_clss != rb_cObject) {
+ rb_ary_push(ary, cbase->nd_clss);
cbase = cbase->nd_next;
}
return ary;
}
static VALUE
-mod_s_constants()
+rb_mod_s_constants()
{
- NODE *cbase = (NODE*)the_frame->cbase;
- VALUE ary = ary_new();
+ NODE *cbase = (NODE*)ruby_frame->cbase;
+ VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != cObject) {
- mod_const_at(cbase->nd_clss, ary);
+ while (cbase && cbase->nd_clss != rb_cObject) {
+ rb_mod_const_at(cbase->nd_clss, ary);
cbase = cbase->nd_next;
}
- mod_const_of(((NODE*)the_frame->cbase)->nd_clss, ary);
+ rb_mod_const_of(((NODE*)ruby_frame->cbase)->nd_clss, ary);
return ary;
}
static VALUE
-mod_remove_method(mod, name)
+rb_mod_remove_method(mod, name)
VALUE mod, name;
{
- rb_remove_method(mod, rb_to_id(name));
+ remove_method(mod, rb_to_id(name));
return mod;
}
static VALUE
-mod_undef_method(mod, name)
+rb_mod_undef_method(mod, name)
VALUE mod, name;
{
ID id = rb_to_id(name);
@@ -1103,16 +1293,27 @@ mod_undef_method(mod, name)
}
static VALUE
-mod_alias_method(mod, new, old)
- VALUE mod, new, old;
+rb_mod_alias_method(mod, newname, oldname)
+ VALUE mod, newname, oldname;
{
- ID id = rb_to_id(new);
+ ID id = rb_to_id(newname);
- rb_alias(mod, id, rb_to_id(old));
+ rb_alias(mod, id, rb_to_id(oldname));
rb_clear_cache_by_id(id);
return mod;
}
+#ifdef C_ALLOCA
+# define TMP_PROTECT NODE * volatile __protect_tmp=0
+# define TMP_ALLOC(n) \
+ (__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
+ ALLOC_N(VALUE,n),__protect_tmp,n), \
+ (void*)__protect_tmp->nd_head)
+#else
+# define TMP_PROTECT typedef int foobazzz
+# define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
+#endif
+
#define SETUP_ARGS(anode) {\
NODE *n = anode;\
if (!n) {\
@@ -1122,17 +1323,17 @@ mod_alias_method(mod, new, old)
else if (nd_type(n) == NODE_ARRAY) {\
argc=n->nd_alen;\
if (argc > 0) {\
- char *file = sourcefile;\
- int line = sourceline;\
+ char *file = ruby_sourcefile;\
+ int line = ruby_sourceline;\
int i;\
n = anode;\
- argv = ALLOCA_N(VALUE,argc);\
+ argv = TMP_ALLOC(argc);\
for (i=0;i<argc;i++) {\
argv[i] = rb_eval(self,n->nd_head);\
n=n->nd_next;\
}\
- sourcefile = file;\
- sourceline = line;\
+ ruby_sourcefile = file;\
+ ruby_sourceline = line;\
}\
else {\
argc = 0;\
@@ -1141,19 +1342,31 @@ mod_alias_method(mod, new, old)
}\
else {\
VALUE args = rb_eval(self,n);\
- char *file = sourcefile;\
- int line = sourceline;\
+ char *file = ruby_sourcefile;\
+ int line = ruby_sourceline;\
if (TYPE(args) != T_ARRAY)\
args = rb_Array(args);\
argc = RARRAY(args)->len;\
argv = ALLOCA_N(VALUE, argc);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
- sourcefile = file;\
- sourceline = line;\
+ ruby_sourcefile = file;\
+ ruby_sourceline = line;\
}\
}
-#define MATCH_DATA the_scope->local_vars[node->nd_cnt]
+#define BEGIN_CALLARGS {\
+ struct BLOCK *tmp_block = ruby_block;\
+ if (ruby_iter->iter == ITER_PRE) {\
+ ruby_block = ruby_block->prev;\
+ }\
+ PUSH_ITER(ITER_NOT);
+
+#define END_CALLARGS \
+ ruby_block = tmp_block;\
+ POP_ITER();\
+}
+
+#define MATCH_DATA ruby_scope->local_vars[node->nd_cnt]
static char* is_defined _((VALUE, NODE*, char*));
@@ -1196,9 +1409,9 @@ is_defined(self, node, buf)
switch (nd_type(node)) {
case NODE_SUPER:
case NODE_ZSUPER:
- if (the_frame->last_func == 0) return 0;
- else if (method_boundp(RCLASS(the_frame->last_class)->super,
- the_frame->last_func, 1)) {
+ if (ruby_frame->last_func == 0) return 0;
+ else if (rb_method_boundp(RCLASS(ruby_frame->last_class)->super,
+ ruby_frame->last_func, 1)) {
if (nd_type(node) == NODE_SUPER) {
return arg_defined(self, node->nd_args, buf, "super");
}
@@ -1206,8 +1419,8 @@ is_defined(self, node, buf)
}
break;
- case NODE_FCALL:
case NODE_VCALL:
+ case NODE_FCALL:
val = CLASS_OF(self);
goto check_bound;
@@ -1219,11 +1432,9 @@ is_defined(self, node, buf)
val = CLASS_OF(val);
}
POP_TAG();
- if (state) {
- return 0;
- }
+ if (state) return 0;
check_bound:
- if (method_boundp(val, node->nd_mid, nd_type(node)== NODE_CALL)) {
+ if (rb_method_boundp(val, node->nd_mid, nd_type(node)== NODE_CALL)) {
return arg_defined(self, node->nd_args, buf, "method");
}
break;
@@ -1233,7 +1444,7 @@ is_defined(self, node, buf)
return "method";
case NODE_YIELD:
- if (iterator_p()) {
+ if (rb_iterator_p()) {
return "yield";
}
break;
@@ -1256,14 +1467,16 @@ is_defined(self, node, buf)
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
+ case NODE_DASGN_PUSH:
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
return "assignment";
case NODE_LVAR:
- case NODE_DVAR:
return "local-variable";
+ case NODE_DVAR:
+ return "local-variable(in-block)";
case NODE_GVAR:
if (rb_gvar_defined(node->nd_entry)) {
@@ -1278,7 +1491,7 @@ is_defined(self, node, buf)
break;
case NODE_CVAR:
- if (ev_const_defined(the_frame->cbase, node->nd_vid)) {
+ if (ev_const_defined((NODE*)ruby_frame->cbase, node->nd_vid)) {
return "constant";
}
break;
@@ -1289,28 +1502,30 @@ is_defined(self, node, buf)
val = rb_eval(self, node->nd_head);
}
POP_TAG();
- if (state) {
- return 0;
- }
+ if (state) return 0;
else {
switch (TYPE(val)) {
case T_CLASS:
case T_MODULE:
if (rb_const_defined_at(val, node->nd_mid))
return "constant";
+ default:
+ if (rb_method_boundp(val, node->nd_mid, 1)) {
+ return "method";
+ }
}
}
break;
case NODE_NTH_REF:
- if (reg_nth_defined(node->nd_nth, MATCH_DATA)) {
+ if (rb_reg_nth_defined(node->nd_nth, MATCH_DATA)) {
sprintf(buf, "$%d", node->nd_nth);
return buf;
}
break;
case NODE_BACK_REF:
- if (reg_nth_defined(0, MATCH_DATA)) {
+ if (rb_reg_nth_defined(0, MATCH_DATA)) {
sprintf(buf, "$%c", node->nd_nth);
return buf;
}
@@ -1330,12 +1545,31 @@ is_defined(self, node, buf)
return 0;
}
-static int handle_rescue();
-VALUE rb_yield_0();
+static int handle_rescue _((VALUE,NODE*));
static void blk_free();
static VALUE
+rb_obj_is_block(block)
+ VALUE block;
+{
+ if (TYPE(block) == T_DATA && RDATA(block)->dfree == blk_free) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+rb_obj_is_proc(proc)
+ VALUE proc;
+{
+ if (rb_obj_is_block(proc) && rb_obj_is_kind_of(proc, rb_cProc)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
set_trace_func(obj, trace)
VALUE obj, trace;
{
@@ -1343,58 +1577,73 @@ set_trace_func(obj, trace)
trace_func = 0;
return Qnil;
}
- if (TYPE(trace) != T_DATA || RDATA(trace)->dfree != blk_free) {
- TypeError("trace_func needs to be Proc");
+ if (!rb_obj_is_proc(trace)) {
+ rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
return trace_func = trace;
}
static void
-call_trace_func(event, file, line, self, id)
+call_trace_func(event, file, line, self, id, klass)
char *event;
char *file;
int line;
VALUE self;
ID id;
+ VALUE klass; /* OK */
{
int state;
volatile VALUE trace;
struct FRAME *prev;
+ char *file_save = ruby_sourcefile;
+ int line_save = ruby_sourceline;
if (!trace_func) return;
trace = trace_func;
trace_func = 0;
-#ifdef THREAD
- thread_critical++;
+#ifdef USE_THREAD
+ rb_thread_critical++;
#endif
- prev = the_frame;
+ prev = ruby_frame;
PUSH_FRAME();
- *the_frame = *_frame->prev;
- the_frame->prev = prev;
+ *ruby_frame = *_frame.prev;
+ ruby_frame->prev = prev;
- the_frame->line = sourceline = line;
- the_frame->file = sourcefile = file;
+ if (file) {
+ ruby_frame->line = ruby_sourceline = line;
+ ruby_frame->file = ruby_sourcefile = file;
+ }
+ if (klass) {
+ if (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
+ klass = self;
+ }
+ }
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- proc_call(trace, ary_new3(5, str_new2(event),
- str_new2(sourcefile),
- INT2FIX(sourceline),
- INT2FIX(id),
- self?f_binding(self):Qnil));
+ proc_call(trace, rb_ary_new3(6, rb_str_new2(event),
+ rb_str_new2(ruby_sourcefile),
+ INT2FIX(ruby_sourceline),
+ INT2FIX(id),
+ self?rb_f_binding(self):Qnil,
+ klass));
}
POP_TAG();
POP_FRAME();
-#ifdef THREAD
- thread_critical--;
+#ifdef USE_THREAD
+ rb_thread_critical--;
#endif
if (!trace_func) trace_func = trace;
+ ruby_sourceline = line_save;
+ ruby_sourcefile = file_save;
if (state) JUMP_TAG(state);
}
-static void return_value _((VALUE val));
+static void return_check _((void));
+#define return_value(v) prot_tag->retval = (v)
+
static VALUE
rb_eval(self, node)
VALUE self;
@@ -1402,6 +1651,10 @@ rb_eval(self, node)
{
int state;
volatile VALUE result = Qnil;
+#ifdef NOBLOCK_RECUR
+ NODE * volatile next = 0;
+ NODE * volatile nstack = 0;
+#endif
#define RETURN(v) { result = (v); goto finish; }
@@ -1410,14 +1663,26 @@ rb_eval(self, node)
switch (nd_type(node)) {
case NODE_BLOCK:
+#ifndef NOBLOCK_RECUR
+ if (!node->nd_next) {
+ node = node->nd_head;
+ goto again;
+ }
while (node) {
result = rb_eval(self, node->nd_head);
node = node->nd_next;
}
break;
-
+#else
+ if (next) {
+ nstack = rb_node_newnode(NODE_CREF,next,0,nstack);
+ }
+ next = node->nd_next;
+ node = node->nd_head;
+ goto again;
+#endif
case NODE_POSTEXE:
- f_END();
+ rb_f_END();
nd_set_type(node, NODE_NIL); /* exec just once */
result = Qnil;
break;
@@ -1429,12 +1694,12 @@ rb_eval(self, node)
/* nodes for speed-up(default match) */
case NODE_MATCH:
- result = reg_match2(node->nd_head->nd_lit);
+ result = rb_reg_match2(node->nd_head->nd_lit);
break;
/* nodes for speed-up(literal match) */
case NODE_MATCH2:
- result = reg_match(rb_eval(self,node->nd_recv),
+ result = rb_reg_match(rb_eval(self,node->nd_recv),
rb_eval(self,node->nd_value));
break;
@@ -1444,7 +1709,7 @@ rb_eval(self, node)
VALUE r = rb_eval(self,node->nd_recv);
VALUE l = rb_eval(self,node->nd_value);
if (TYPE(r) == T_STRING) {
- result = reg_match(l, r);
+ result = rb_reg_match(l, r);
}
else {
result = rb_funcall(r, match, 1, l);
@@ -1454,7 +1719,7 @@ rb_eval(self, node)
/* nodes for speed-up(top-level loop for -n/-p) */
case NODE_OPT_N:
- while (!NIL_P(f_gets())) {
+ while (!NIL_P(rb_gets())) {
rb_eval(self, node->nd_body);
}
RETURN(Qnil);
@@ -1466,14 +1731,18 @@ rb_eval(self, node)
RETURN(Qnil);
case NODE_TRUE:
- RETURN(TRUE);
+ RETURN(Qtrue);
case NODE_FALSE:
- RETURN(FALSE);
+ RETURN(Qfalse);
case NODE_IF:
- sourceline = nd_line(node);
+ ruby_sourceline = nd_line(node);
+#ifdef NOBLOCK_RECUR
+ if (RTEST(result)){
+#else
if (RTEST(rb_eval(self, node->nd_cond))) {
+#endif
node = node->nd_body;
}
else {
@@ -1485,7 +1754,11 @@ rb_eval(self, node)
{
VALUE val;
+#ifdef NOBLOCK_RECUR
+ val = result;
+#else
val = rb_eval(self, node->nd_head);
+#endif
node = node->nd_body;
while (node) {
NODE *tag;
@@ -1497,10 +1770,25 @@ rb_eval(self, node)
while (tag) {
if (trace_func) {
call_trace_func("line", tag->nd_file, nd_line(tag),
- self, the_frame->last_func);
+ self, ruby_frame->last_func, 0);
}
- sourceline = nd_line(tag);
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){
+ ruby_sourcefile = tag->nd_file;
+ ruby_sourceline = nd_line(tag);
+ if (nd_type(tag->nd_head) == NODE_WHEN) {
+ VALUE v = rb_eval(self, tag->nd_head->nd_head);
+ int i;
+
+ if (TYPE(v) != T_ARRAY) v = rb_Array(v);
+ for (i=0; i<RARRAY(v)->len; i++) {
+ if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
+ node = node->nd_body;
+ goto again;
+ }
+ }
+ tag = tag->nd_next;
+ continue;
+ }
+ if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
node = node->nd_body;
goto again;
}
@@ -1515,7 +1803,7 @@ rb_eval(self, node)
PUSH_TAG(PROT_NONE);
switch (state = EXEC_TAG()) {
case 0:
- sourceline = nd_line(node);
+ ruby_sourceline = nd_line(node);
if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
goto while_out;
do {
@@ -1539,9 +1827,7 @@ rb_eval(self, node)
}
while_out:
POP_TAG();
- if (state) {
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
RETURN(Qnil);
case NODE_UNTIL:
@@ -1571,11 +1857,13 @@ rb_eval(self, node)
}
until_out:
POP_TAG();
- if (state) {
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
RETURN(Qnil);
+ case NODE_BLOCK_PASS:
+ result = block_pass(self, node);
+ break;
+
case NODE_ITER:
case NODE_FOR:
{
@@ -1592,21 +1880,21 @@ rb_eval(self, node)
}
else {
VALUE recv;
- char *file = sourcefile;
- int line = sourceline;
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
recv = rb_eval(self, node->nd_iter);
PUSH_ITER(ITER_PRE);
- sourcefile = file;
- sourceline = line;
+ ruby_sourcefile = file;
+ ruby_sourceline = line;
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
POP_ITER();
}
}
- else if (the_block->tag->dst == state) {
+ else if (_block.tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
}
}
POP_TAG();
@@ -1646,14 +1934,32 @@ rb_eval(self, node)
JUMP_TAG(TAG_RETRY);
break;
+ case NODE_RESTARGS:
+ result = rb_eval(self, node->nd_head);
+ if (TYPE(result) != T_ARRAY) {
+ result = rb_Array(result);
+ }
+ break;
+
case NODE_YIELD:
- result = rb_yield_0(rb_eval(self, node->nd_stts), 0);
+ if (node->nd_stts) {
+ result = rb_eval(self, node->nd_stts);
+ if (nd_type(node->nd_stts) == NODE_RESTARGS &&
+ RARRAY(result)->len == 1)
+ {
+ result = RARRAY(result)->ptr[0];
+ }
+ }
+ else {
+ result = Qnil;
+ }
+ result = rb_yield_0(result, 0, 0);
break;
case NODE_RESCUE:
retry_entry:
{
- volatile VALUE e_info = errinfo, e_at = errat;
+ volatile VALUE e_info = rb_errinfo;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -1662,6 +1968,7 @@ rb_eval(self, node)
POP_TAG();
if (state == TAG_RAISE) {
NODE * volatile resq = node->nd_resq;
+
while (resq) {
if (handle_rescue(self, resq)) {
state = 0;
@@ -1671,8 +1978,7 @@ rb_eval(self, node)
}
POP_TAG();
if (state == 0) {
- errinfo = e_info;
- errat = e_at;
+ rb_errinfo = e_info;
}
else if (state == TAG_RETRY) {
state = 0;
@@ -1683,8 +1989,9 @@ rb_eval(self, node)
resq = resq->nd_head; /* next rescue */
}
}
- if (state) {
- JUMP_TAG(state);
+ if (state) JUMP_TAG(state);
+ if (node->nd_else) { /* no exception raised, else clause given */
+ result = rb_eval(self, node->nd_else);
}
}
break;
@@ -1695,10 +2002,13 @@ rb_eval(self, node)
result = rb_eval(self, node->nd_head);
}
POP_TAG();
- rb_eval(self, node->nd_ensr);
- if (state) {
- JUMP_TAG(state);
+ if (node->nd_ensr) {
+ VALUE retval = prot_tag->retval; /* save retval */
+
+ rb_eval(self, node->nd_ensr);
+ return_value(retval);
}
+ if (state) JUMP_TAG(state);
break;
case NODE_AND:
@@ -1714,45 +2024,65 @@ rb_eval(self, node)
goto again;
case NODE_NOT:
- if (RTEST(rb_eval(self, node->nd_body))) result = FALSE;
- else result = TRUE;
+ if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse;
+ else result = Qtrue;
break;
case NODE_DOT2:
case NODE_DOT3:
- RETURN(range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end)));
+ result = rb_range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end));
+#if 0
+ break;
+#else
+ result = rb_range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end));
+ if (node->nd_state) break;
+ if (nd_type(node->nd_beg) == NODE_LIT && FIXNUM_P(node->nd_beg->nd_lit) &&
+ nd_type(node->nd_end) == NODE_LIT && FIXNUM_P(node->nd_end->nd_lit))
+ {
+ nd_set_type(node, NODE_LIT);
+ node->nd_lit = result;
+ }
+ else {
+ node->nd_state = 1;
+ }
+#endif
+ break;
case NODE_FLIP2: /* like AWK */
- if (node->nd_state == 0) {
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
+ }
+ if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
if (RTEST(rb_eval(self, node->nd_beg))) {
- node->nd_state = rb_eval(self, node->nd_end)?0:1;
- result = TRUE;
+ ruby_scope->local_vars[node->nd_cnt] =
+ RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
+ result = Qtrue;
}
else {
- result = FALSE;
+ result = Qfalse;
}
}
else {
if (RTEST(rb_eval(self, node->nd_end))) {
- node->nd_state = 0;
+ ruby_scope->local_vars[node->nd_cnt] = Qfalse;
}
- result = TRUE;
+ result = Qtrue;
}
break;
case NODE_FLIP3: /* like SED */
- if (node->nd_state == 0) {
- if (RTEST(rb_eval(self, node->nd_beg))) {
- node->nd_state = 1;
- result = TRUE;
- }
- result = FALSE;
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
+ }
+ if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
+ result = RTEST(rb_eval(self, node->nd_beg));
+ ruby_scope->local_vars[node->nd_cnt] = result;
}
else {
if (RTEST(rb_eval(self, node->nd_end))) {
- node->nd_state = 0;
+ ruby_scope->local_vars[node->nd_cnt] = Qfalse;
}
- result = TRUE;
+ result = Qtrue;
}
break;
@@ -1760,18 +2090,32 @@ rb_eval(self, node)
if (node->nd_stts) {
return_value(rb_eval(self, node->nd_stts));
}
+ return_check();
JUMP_TAG(TAG_RETURN);
break;
+ case NODE_ARGSCAT:
+ result = rb_ary_concat(rb_eval(self, node->nd_head),
+ rb_eval(self, node->nd_body));
+ break;
+
case NODE_CALL:
{
VALUE recv;
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
+#ifdef NOBLOCK_RECUR_incomplete
+ printf("mid %s recv: ", rb_id2name(node->nd_mid));
+ rb_p(result);
+ recv = result;
+#else
recv = rb_eval(self, node->nd_recv);
+#endif
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
}
break;
@@ -1779,10 +2123,12 @@ rb_eval(self, node)
case NODE_FCALL:
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
}
break;
@@ -1795,48 +2141,54 @@ rb_eval(self, node)
case NODE_ZSUPER:
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+ if (ruby_frame->last_class == 0) {
+ rb_raise(rb_eNameError, "superclass method `%s' disabled",
+ rb_id2name(ruby_frame->last_func));
+ }
if (nd_type(node) == NODE_ZSUPER) {
- argc = the_frame->argc;
- argv = the_frame->argv;
+ argc = ruby_frame->argc;
+ argv = ruby_frame->argv;
}
else {
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
}
- PUSH_ITER(the_iter->iter?ITER_PRE:ITER_NOT);
- result = rb_call(RCLASS(the_frame->last_class)->super, self,
- the_frame->last_func, argc, argv, 1);
+ PUSH_ITER(ruby_iter->iter?ITER_PRE:ITER_NOT);
+ result = rb_call(RCLASS(ruby_frame->last_class)->super,
+ ruby_frame->self, ruby_frame->last_func,
+ argc, argv, 3);
POP_ITER();
}
break;
case NODE_SCOPE:
{
- VALUE save = the_frame->cbase;
+ VALUE save = ruby_frame->cbase;
PUSH_SCOPE();
PUSH_TAG(PROT_NONE);
- if (node->nd_rval) the_frame->cbase = (VALUE)node->nd_rval;
+ if (node->nd_rval) ruby_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
*vars++ = (VALUE)node;
- the_scope->local_vars = vars;
- memclear(the_scope->local_vars, node->nd_tbl[0]);
- the_scope->local_tbl = node->nd_tbl;
+ ruby_scope->local_vars = vars;
+ rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+ ruby_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_body);
+ result = rb_eval(self, node->nd_next);
}
POP_TAG();
POP_SCOPE();
- the_frame->cbase = save;
+ ruby_frame->cbase = save;
if (state) JUMP_TAG(state);
}
break;
@@ -1846,12 +2198,23 @@ rb_eval(self, node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
VALUE recv, val;
NODE *rval;
+ TMP_PROTECT;
recv = rb_eval(self, node->nd_recv);
rval = node->nd_args->nd_head;
SETUP_ARGS(node->nd_args->nd_next);
val = rb_funcall2(recv, aref, argc-1, argv);
- val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
+ if (node->nd_mid == 0) { /* OR */
+ if (RTEST(val)) break;
+ val = rb_eval(self, rval);
+ }
+ else if (node->nd_mid == 1) { /* AND */
+ if (!RTEST(val)) break;
+ val = rb_eval(self, rval);
+ }
+ else {
+ val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
+ }
argv[argc-1] = val;
val = rb_funcall2(recv, aset, argc, argv);
result = val;
@@ -1865,75 +2228,94 @@ rb_eval(self, node)
recv = rb_eval(self, node->nd_recv);
val = rb_funcall(recv, id, 0);
+ if (node->nd_next->nd_mid == 0) { /* OR */
+ if (RTEST(val)) break;
+ val = rb_eval(self, node->nd_value);
+ }
+ else if (node->nd_next->nd_mid == 1) { /* AND */
+ if (!RTEST(val)) break;
+ val = rb_eval(self, node->nd_value);
+ }
+ else {
+ val = rb_funcall(val, node->nd_next->nd_mid, 1,
+ rb_eval(self, node->nd_value));
+ }
- val = rb_funcall(val, node->nd_next->nd_mid, 1,
- rb_eval(self, node->nd_value));
-
- rb_funcall2(recv, id_attrset(id), 1, &val);
+ rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
result = val;
}
break;
+ case NODE_OP_ASGN_AND:
+ result = rb_eval(self, node->nd_head);
+ if (RTEST(result)) {
+ result = rb_eval(self, node->nd_value);
+ }
+ break;
+
+ case NODE_OP_ASGN_OR:
+ result = rb_eval(self, node->nd_head);
+ if (!RTEST(result)) {
+ result = rb_eval(self, node->nd_value);
+ }
+ break;
+
case NODE_MASGN:
result = massign(self, node, rb_eval(self, node->nd_value));
break;
case NODE_LASGN:
- if (the_scope->local_vars == 0)
- Bug("unexpected local variable assignment");
- the_scope->local_vars[node->nd_cnt] = rb_eval(self, node->nd_value);
- result = the_scope->local_vars[node->nd_cnt];
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected local variable assignment");
+ result = rb_eval(self, node->nd_value);
+ ruby_scope->local_vars[node->nd_cnt] = result;
break;
case NODE_DASGN:
- result = dyna_var_asgn(node->nd_vid, rb_eval(self, node->nd_value));
+ result = rb_eval(self, node->nd_value);
+ rb_dvar_asgn(node->nd_vid, result);
break;
- case NODE_GASGN:
- {
- VALUE val;
+ case NODE_DASGN_PUSH:
+ result = rb_eval(self, node->nd_value);
+ dvar_asgn_push(node->nd_vid, result);
+ break;
- val = rb_eval(self, node->nd_value);
- rb_gvar_set(node->nd_entry, val);
- result = val;
- }
+ case NODE_GASGN:
+ result = rb_eval(self, node->nd_value);
+ rb_gvar_set(node->nd_entry, result);
break;
case NODE_IASGN:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_value);
- rb_ivar_set(self, node->nd_vid, val);
- result = val;
- }
+ result = rb_eval(self, node->nd_value);
+ rb_ivar_set(self, node->nd_vid, result);
break;
case NODE_CASGN:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_value);
- /* check for static scope constants */
- if (RTEST(verbose) &&
- ev_const_defined(the_frame->cbase, node->nd_vid)) {
- Warning("already initialized constant %s",
- rb_id2name(node->nd_vid));
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class/module to define constant");
+ }
+ result = rb_eval(self, node->nd_value);
+ /* check for static scope constants */
+ if (RTEST(rb_verbose) &&
+ ev_const_defined((NODE*)ruby_frame->cbase, node->nd_vid)) {
+ if (RTEST(rb_verbose)) {
+ rb_warning("already initialized constant %s",
+ rb_id2name(node->nd_vid));
}
- rb_const_set(the_class, node->nd_vid, val);
- result = val;
}
+ rb_const_set(ruby_class, node->nd_vid, result);
break;
case NODE_LVAR:
- if (the_scope->local_vars == 0) {
- Bug("unexpected local variable");
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
}
- result = the_scope->local_vars[node->nd_cnt];
+ result = ruby_scope->local_vars[node->nd_cnt];
break;
case NODE_DVAR:
- result = dyna_var_ref(node->nd_vid);
+ result = rb_dvar_ref(node->nd_vid);
break;
case NODE_GVAR:
@@ -1945,53 +2327,68 @@ rb_eval(self, node)
break;
case NODE_CVAR:
- result = ev_const_get(the_frame->cbase, node->nd_vid);
+ result = ev_const_get((NODE*)ruby_frame->cbase, node->nd_vid);
+ break;
+
+ case NODE_BLOCK_ARG:
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected block argument");
+ if (rb_iterator_p()) {
+ result = rb_f_lambda();
+ ruby_scope->local_vars[node->nd_cnt] = result;
+ }
+ else {
+ result = Qnil;
+ }
break;
case NODE_COLON2:
{
- VALUE cls;
+ VALUE klass;
- cls = rb_eval(self, node->nd_head);
- switch (TYPE(cls)) {
+ klass = rb_eval(self, node->nd_head);
+ switch (TYPE(klass)) {
case T_CLASS:
case T_MODULE:
break;
default:
- Check_Type(cls, T_CLASS);
- break;
+ return rb_funcall(klass, node->nd_mid, 0, 0);
}
- result = rb_const_get_at(cls, node->nd_mid);
+ result = rb_const_get_at(klass, node->nd_mid);
}
break;
+ case NODE_COLON3:
+ result = rb_const_get_at(rb_cObject, node->nd_mid);
+ break;
+
case NODE_NTH_REF:
- result = reg_nth_match(node->nd_nth, MATCH_DATA);
+ result = rb_reg_nth_match(node->nd_nth, MATCH_DATA);
break;
case NODE_BACK_REF:
switch (node->nd_nth) {
case '&':
- result = reg_last_match(MATCH_DATA);
+ result = rb_reg_last_match(MATCH_DATA);
break;
case '`':
- result = reg_match_pre(MATCH_DATA);
+ result = rb_reg_match_pre(MATCH_DATA);
break;
case '\'':
- result = reg_match_post(MATCH_DATA);
+ result = rb_reg_match_post(MATCH_DATA);
break;
case '+':
- result = reg_match_last(MATCH_DATA);
+ result = rb_reg_match_last(MATCH_DATA);
break;
default:
- Bug("unexpected back-ref");
+ rb_bug("unexpected back-ref");
}
break;
case NODE_HASH:
{
NODE *list;
- VALUE hash = hash_new();
+ VALUE hash = rb_hash_new();
VALUE key, val;
list = node->nd_head;
@@ -1999,17 +2396,17 @@ rb_eval(self, node)
key = rb_eval(self, list->nd_head);
list = list->nd_next;
if (list == 0)
- Bug("odd number list for Hash");
+ rb_bug("odd number list for Hash");
val = rb_eval(self, list->nd_head);
list = list->nd_next;
- hash_aset(hash, key, val);
+ rb_hash_aset(hash, key, val);
}
result = hash;
}
break;
case NODE_ZARRAY: /* zero length list */
- result = ary_new();
+ result = rb_ary_new();
break;
case NODE_ARRAY:
@@ -2018,7 +2415,7 @@ rb_eval(self, node)
int i;
i = node->nd_alen;
- ary = ary_new2(i);
+ ary = rb_ary_new2(i);
for (i=0;node;node=node->nd_next) {
RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
RARRAY(ary)->len = i;
@@ -2029,7 +2426,7 @@ rb_eval(self, node)
break;
case NODE_STR:
- result = str_new3(node->nd_lit);
+ result = rb_str_new3(node->nd_lit);
break;
case NODE_DSTR:
@@ -2040,36 +2437,39 @@ rb_eval(self, node)
VALUE str, str2;
NODE *list = node->nd_next;
- str = str_new3(node->nd_lit);
+ str = rb_str_new3(node->nd_lit);
while (list) {
- if (nd_type(list->nd_head) == NODE_STR) {
- str2 = list->nd_head->nd_lit;
- }
- else {
- if (nd_type(list->nd_head) == NODE_EVSTR) {
+ if (list->nd_head) {
+ switch (nd_type(list->nd_head)) {
+ case NODE_STR:
+ str2 = list->nd_head->nd_lit;
+ break;
+ case NODE_EVSTR:
rb_in_eval++;
- eval_tree = 0;
- list->nd_head = compile(list->nd_head->nd_lit);
+ list->nd_head = compile(list->nd_head->nd_lit,0);
+ ruby_eval_tree = 0;
rb_in_eval--;
- if (nerrs > 0) {
- compile_error("string expand");
+ if (ruby_nerrs > 0) {
+ compile_error("string expansion");
}
+ /* fall through */
+ default:
+ str2 = rb_eval(self, list->nd_head);
+ str2 = rb_obj_as_string(str2);
+ break;
}
- str2 = rb_eval(self, list->nd_head);
- str2 = obj_as_string(str2);
- }
- if (str2) {
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
list = list->nd_next;
}
switch (nd_type(node)) {
case NODE_DREGX:
- result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
node->nd_cflag);
break;
case NODE_DREGX_ONCE: /* regexp expand once */
- result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
node->nd_cflag);
nd_set_type(node, NODE_LIT);
node->nd_lit = result;
@@ -2093,9 +2493,10 @@ rb_eval(self, node)
break;
case NODE_ATTRSET:
- if (the_frame->argc != 1)
- ArgError("Wrong # of arguments(%d for 1)", the_frame->argc);
- result = rb_ivar_set(self, node->nd_vid, the_frame->argv[0]);
+ if (ruby_frame->argc != 1)
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for 1)",
+ ruby_frame->argc);
+ result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
break;
case NODE_DEFN:
@@ -2104,28 +2505,51 @@ rb_eval(self, node)
VALUE origin;
int noex;
- body = search_method(the_class, node->nd_mid, &origin);
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to add method");
+ }
+ if (ruby_class == rb_cObject && node->nd_mid == init) {
+ rb_warn("re-defining Object#initialize may cause infinite loop");
+ }
+ body = search_method(ruby_class, node->nd_mid, &origin);
if (body) {
- if (origin == (VALUE)the_class) {
- Warning("discarding old %s", rb_id2name(node->nd_mid));
+ if (origin == ruby_class) {
+ if (safe_level >= 3) {
+ rb_raise(rb_eSecurityError, "re-defining method prohibited");
+ }
+ if (RTEST(rb_verbose)) {
+ rb_warning("discarding old %s", rb_id2name(node->nd_mid));
+ }
}
rb_clear_cache_by_id(node->nd_mid);
}
- if (FL_TEST(the_scope,SCOPE_PRIVATE)) {
+ if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
noex = NOEX_PRIVATE;
}
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
+ }
else {
noex = NOEX_PUBLIC;
}
- rb_add_method(the_class, node->nd_mid, node->nd_defn, noex);
- if (FL_TEST(the_class, FL_SINGLETON)) {
- VALUE recv = rb_iv_get(the_class, "__attached__");
- rb_funcall(recv, rb_intern("singleton_method_added"),
+ if (body && origin == ruby_class && body->nd_noex & NOEX_UNDEF) {
+ noex |= NOEX_UNDEF;
+ }
+ rb_add_method(ruby_class, node->nd_mid, node->nd_defn, noex);
+ if (scope_vmode == SCOPE_MODFUNC) {
+ rb_add_method(rb_singleton_class(ruby_class),
+ node->nd_mid, node->nd_defn, NOEX_PUBLIC);
+ rb_funcall(ruby_class, rb_intern("singleton_method_added"),
+ 1, INT2FIX(node->nd_mid));
+ }
+ if (FL_TEST(ruby_class, FL_SINGLETON)) {
+ rb_funcall(rb_iv_get(ruby_class, "__attached__"),
+ rb_intern("singleton_method_added"),
1, INT2FIX(node->nd_mid));
}
else {
- rb_funcall(the_class, rb_intern("method_added"),
+ rb_funcall(ruby_class, rb_intern("method_added"),
1, INT2FIX(node->nd_mid));
}
result = Qnil;
@@ -2135,28 +2559,38 @@ rb_eval(self, node)
case NODE_DEFS:
if (node->nd_defn) {
VALUE recv = rb_eval(self, node->nd_recv);
- VALUE class;
- NODE *body;
+ VALUE klass;
+ NODE *body = 0;
if (FIXNUM_P(recv)) {
- TypeError("Can't define method \"%s\" for Fixnum",
- rb_id2name(node->nd_mid));
+ rb_raise(rb_eTypeError, "Can't define method \"%s\" for Fixnum",
+ rb_id2name(node->nd_mid));
}
if (NIL_P(recv)) {
- TypeError("Can't define method \"%s\" for nil",
- rb_id2name(node->nd_mid));
+ rb_raise(rb_eTypeError, "Can't define method \"%s\" for nil",
+ rb_id2name(node->nd_mid));
}
if (rb_special_const_p(recv)) {
- TypeError("Can't define method \"%s\" for special constants",
- rb_id2name(node->nd_mid));
+ rb_raise(rb_eTypeError,
+ "Can't define method \"%s\" for special constants",
+ rb_id2name(node->nd_mid));
}
- class = rb_singleton_class(recv);
- if (st_lookup(RCLASS(class)->m_tbl, node->nd_mid, &body)) {
- Warning("redefine %s", rb_id2name(node->nd_mid));
+ if (rb_safe_level() >= 4 && !FL_TEST(recv, FL_TAINT)) {
+ rb_raise(rb_eSecurityError, "can't define singleton method");
+ }
+ klass = rb_singleton_class(recv);
+ if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) {
+ if (safe_level >= 3) {
+ rb_raise(rb_eSecurityError, "re-defining method prohibited");
+ }
+ if (RTEST(rb_verbose)) {
+ rb_warning("redefine %s", rb_id2name(node->nd_mid));
+ }
}
rb_clear_cache_by_id(node->nd_mid);
- rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC);
+ rb_add_method(klass, node->nd_mid, node->nd_defn,
+ NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
rb_funcall(recv, rb_intern("singleton_method_added"),
1, INT2FIX(node->nd_mid));
result = Qnil;
@@ -2168,20 +2602,41 @@ rb_eval(self, node)
VALUE origin;
NODE *body;
- body = search_method(the_class, node->nd_mid, &origin);
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to undef method");
+ }
+ if (ruby_class == rb_cObject) {
+ rb_secure(4);
+ }
+ body = search_method(ruby_class, node->nd_mid, &origin);
if (!body || !body->nd_body) {
- NameError("undefined method `%s' for class `%s'",
- rb_id2name(node->nd_mid), rb_class2name((VALUE)the_class));
+ char *s0 = " class";
+ VALUE klass = ruby_class;
+
+ if (FL_TEST(ruby_class, FL_SINGLETON)) {
+ VALUE obj = rb_iv_get(ruby_class, "__attached__");
+ switch (TYPE(obj)) {
+ case T_MODULE:
+ case T_CLASS:
+ klass = obj;
+ s0 = "";
+ }
+ }
+ rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'",
+ rb_id2name(node->nd_mid),s0,rb_class2name(klass));
}
rb_clear_cache_by_id(node->nd_mid);
- rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC);
+ rb_add_method(ruby_class, node->nd_mid, 0, NOEX_PUBLIC);
result = Qnil;
}
break;
case NODE_ALIAS:
- rb_alias(the_class, node->nd_new, node->nd_old);
- rb_funcall(the_class, rb_intern("method_added"),
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to make alias");
+ }
+ rb_alias(ruby_class, node->nd_new, node->nd_old);
+ rb_funcall(ruby_class, rb_intern("method_added"),
1, INT2FIX(node->nd_mid));
result = Qnil;
break;
@@ -2193,8 +2648,11 @@ rb_eval(self, node)
case NODE_CLASS:
{
- VALUE super, class, tmp;
+ VALUE super, klass, tmp;
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
if (node->nd_super) {
super = superclass(self, node->nd_super);
}
@@ -2202,16 +2660,21 @@ rb_eval(self, node)
super = 0;
}
- if (rb_const_defined_at(the_class, node->nd_cname) &&
- ((VALUE)the_class != cObject ||
- !rb_autoload_defined(node->nd_cname))) {
-
- class = rb_const_get_at(the_class, node->nd_cname);
- if (TYPE(class) != T_CLASS) {
- TypeError("%s is not a class", rb_id2name(node->nd_cname));
+ klass = 0;
+ if (rb_const_defined_at(ruby_class, node->nd_cname) &&
+ (ruby_class != rb_cObject || !rb_autoload_defined(node->nd_cname))) {
+ klass = rb_const_get_at(ruby_class, node->nd_cname);
+ }
+ if (ruby_wrapper && rb_const_defined_at(rb_cObject, node->nd_cname)) {
+ klass = rb_const_get_at(rb_cObject, node->nd_cname);
+ }
+ if (klass) {
+ if (TYPE(klass) != T_CLASS) {
+ rb_raise(rb_eTypeError, "%s is not a class",
+ rb_id2name(node->nd_cname));
}
if (super) {
- tmp = RCLASS(class)->super;
+ tmp = RCLASS(klass)->super;
if (FL_TEST(tmp, FL_SINGLETON)) {
tmp = RCLASS(tmp)->super;
}
@@ -2219,23 +2682,28 @@ rb_eval(self, node)
tmp = RCLASS(tmp)->super;
}
if (tmp != super) {
- TypeError("superclass mismatch for %s",
- rb_id2name(node->nd_cname));
+ rb_raise(rb_eTypeError, "superclass mismatch for %s",
+ rb_id2name(node->nd_cname));
}
}
- if (safe_level >= 4) {
- Raise(eSecurityError, "extending class prohibited");
+ if (safe_level >= 3) {
+ rb_raise(rb_eSecurityError, "extending class prohibited");
}
rb_clear_cache();
}
else {
- if (!super) super = cObject;
- class = rb_define_class_id(node->nd_cname, super);
- rb_const_set(the_class, node->nd_cname, class);
- rb_set_class_path(class,the_class,rb_id2name(node->nd_cname));
+ if (!super) super = rb_cObject;
+ klass = rb_define_class_id(node->nd_cname, super);
+ rb_const_set(ruby_class, node->nd_cname, klass);
+ rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname));
+ rb_obj_call_init(klass);
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
}
- return module_setup(class, node->nd_body);
+ result = module_setup(klass, node->nd_body);
}
break;
@@ -2243,22 +2711,36 @@ rb_eval(self, node)
{
VALUE module;
- if (rb_const_defined_at(the_class, node->nd_cname) &&
- ((VALUE)the_class != cObject ||
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
+ module = 0;
+ if (rb_const_defined_at(ruby_class, node->nd_cname) &&
+ (ruby_class != rb_cObject ||
!rb_autoload_defined(node->nd_cname))) {
-
- module = rb_const_get_at(the_class, node->nd_cname);
+ module = rb_const_get_at(ruby_class, node->nd_cname);
+ }
+ if (ruby_wrapper && rb_const_defined_at(rb_cObject, node->nd_cname)) {
+ module = rb_const_get_at(rb_cObject, node->nd_cname);
+ }
+ if (module) {
if (TYPE(module) != T_MODULE) {
- TypeError("%s is not a module", rb_id2name(node->nd_cname));
+ rb_raise(rb_eTypeError, "%s is not a module",
+ rb_id2name(node->nd_cname));
}
- if (safe_level >= 4) {
- Raise(eSecurityError, "extending module prohibited");
+ if (safe_level >= 3) {
+ rb_raise(rb_eSecurityError, "extending module prohibited");
}
}
else {
module = rb_define_module_id(node->nd_cname);
- rb_const_set(the_class, node->nd_cname, module);
- rb_set_class_path(module,the_class,rb_id2name(node->nd_cname));
+ rb_const_set(ruby_class, node->nd_cname, module);
+ rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
+ rb_obj_call_init(module);
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(module, ruby_wrapper);
+ rb_include_module(module, ruby_wrapper);
}
result = module_setup(module, node->nd_body);
@@ -2267,24 +2749,28 @@ rb_eval(self, node)
case NODE_SCLASS:
{
- VALUE class;
+ VALUE klass;
- class = rb_eval(self, node->nd_recv);
- if (FIXNUM_P(class)) {
- TypeError("No virtual class for Fixnums");
+ klass = rb_eval(self, node->nd_recv);
+ if (FIXNUM_P(klass)) {
+ rb_raise(rb_eTypeError, "No virtual class for Fixnums");
}
- if (NIL_P(class)) {
- TypeError("No virtual class for nil");
+ if (NIL_P(klass)) {
+ rb_raise(rb_eTypeError, "No virtual class for nil");
}
- if (rb_special_const_p(class)) {
- TypeError("No virtual class for special constants");
+ if (rb_special_const_p(klass)) {
+ rb_raise(rb_eTypeError, "No virtual class for special constants");
}
- if (FL_TEST(CLASS_OF(class), FL_SINGLETON)) {
+ if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) {
rb_clear_cache();
- class = rb_singleton_class(class);
}
-
- result = module_setup(class, node->nd_body);
+ klass = rb_singleton_class(klass);
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
+ }
+
+ result = module_setup(klass, node->nd_body);
}
break;
@@ -2293,26 +2779,38 @@ rb_eval(self, node)
char buf[20];
char *desc = is_defined(self, node->nd_head, buf);
- if (desc) result = str_new2(desc);
- else result = FALSE;
+ if (desc) result = rb_str_new2(desc);
+ else result = Qfalse;
}
break;
case NODE_NEWLINE:
- sourcefile = node->nd_file;
- sourceline = node->nd_nth;
+ ruby_sourcefile = node->nd_file;
+ ruby_sourceline = node->nd_nth;
if (trace_func) {
- call_trace_func("line", sourcefile, sourceline,
- self, the_frame->last_func);
+ call_trace_func("line", ruby_sourcefile, ruby_sourceline,
+ self, ruby_frame->last_func, 0);
}
node = node->nd_next;
goto again;
default:
- Bug("unknown node type %d", nd_type(node));
+ rb_bug("unknown node type %d", nd_type(node));
}
finish:
CHECK_INTS;
+#ifdef NOBLOCK_RECUR
+ if (next) {
+ node = next;
+ next = 0;
+ goto again;
+ }
+ if (nstack) {
+ node = nstack->nd_head;
+ nstack = nstack->nd_next;
+ goto again;
+ }
+#endif
return result;
}
@@ -2322,47 +2820,48 @@ module_setup(module, node)
NODE * volatile node;
{
int state;
- VALUE save = the_frame->cbase;
+ VALUE save = ruby_frame->cbase;
VALUE result; /* OK */
- char *file = sourcefile;
- int line = sourceline;
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
+ TMP_PROTECT;
/* fill c-ref */
node->nd_clss = module;
node = node->nd_body;
PUSH_CLASS();
- the_class = module;
+ ruby_class = module;
PUSH_SCOPE();
- if (node->nd_rval) the_frame->cbase = node->nd_rval;
+ if (node->nd_rval) ruby_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
- VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
+ VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
*vars++ = (VALUE)node;
- the_scope->local_vars = vars;
- memclear(the_scope->local_vars, node->nd_tbl[0]);
- the_scope->local_tbl = node->nd_tbl;
+ ruby_scope->local_vars = vars;
+ rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+ ruby_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
if (trace_func) {
call_trace_func("class", file, line,
- the_class, the_frame->last_func);
+ ruby_class, ruby_frame->last_func, 0);
}
- result = rb_eval((VALUE)the_class, node->nd_body);
+ result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
POP_SCOPE();
POP_CLASS();
- the_frame->cbase = save;
+ ruby_frame->cbase = save;
if (trace_func) {
- call_trace_func("end", file, line, 0, the_frame->last_func);
+ call_trace_func("end", file, line, 0, ruby_frame->last_func, 0);
}
if (state) JUMP_TAG(state);
@@ -2375,13 +2874,13 @@ rb_respond_to(obj, id)
ID id;
{
if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-obj_respond_to(argc, argv, obj)
+rb_obj_respond_to(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -2392,19 +2891,19 @@ obj_respond_to(argc, argv, obj)
rb_scan_args(argc, argv, "11", &mid, &priv);
id = rb_to_id(mid);
if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-mod_method_defined(mod, mid)
+rb_mod_method_defined(mod, mid)
VALUE mod, mid;
{
if (rb_method_boundp(mod, rb_to_id(mid), 1)) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
void
@@ -2413,20 +2912,20 @@ rb_exit(status)
{
if (prot_tag) {
exit_status = status;
- rb_raise(exc_new(eSystemExit, 0, 0));
+ rb_exc_raise(rb_exc_new(rb_eSystemExit, 0, 0));
}
exit(status);
}
static VALUE
-f_exit(argc, argv, obj)
+rb_f_exit(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
VALUE status;
- rb_secure(2);
+ rb_secure(4);
if (rb_scan_args(argc, argv, "01", &status) == 1) {
status = NUM2INT(status);
}
@@ -2434,18 +2933,24 @@ f_exit(argc, argv, obj)
status = 0;
}
rb_exit(status);
- /* not reached */
+ return Qnil; /* not reached */
}
-static VALUE
-f_abort()
+static void
+rb_abort()
{
- rb_secure(2);
- if (errinfo) {
+ if (rb_errinfo) {
error_print();
}
rb_exit(1);
- /* not reached */
+}
+
+static VALUE
+rb_f_abort()
+{
+ rb_secure(4);
+ rb_abort();
+ return Qnil; /* not reached */
}
void
@@ -2454,143 +2959,135 @@ rb_iter_break()
JUMP_TAG(TAG_BREAK);
}
-#ifdef __GNUC__
-static volatile voidfn rb_longjmp;
-#endif
-
-static VALUE make_backtrace();
-
-static VALUE
-check_errat(val)
- VALUE val;
-{
- int i;
- static char *err = "value of $@ must be Array of String";
-
- if (!NIL_P(val)) {
- int t = TYPE(val);
-
- if (t == T_STRING) return ary_new3(1, val);
- if (t != T_ARRAY) {
- TypeError(err);
- }
- for (i=0;i<RARRAY(val)->len;i++) {
- if (TYPE(RARRAY(val)->ptr[i]) != T_STRING) {
- TypeError(err);
- }
- }
- }
- return val;
-}
+static void rb_longjmp _((int, VALUE)) NORETURN;
+static VALUE make_backtrace _((void));
static void
-rb_longjmp(tag, mesg, at)
+rb_longjmp(tag, mesg)
int tag;
- VALUE mesg, at;
+ VALUE mesg;
{
- if (NIL_P(errinfo) && NIL_P(mesg)) {
- errinfo = exc_new(eRuntimeError, 0, 0);
+ VALUE at;
+
+ if (NIL_P(mesg)) mesg = rb_errinfo;
+ if (NIL_P(mesg)) {
+ mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
}
- if (!NIL_P(at)) {
- errat = check_errat(at);
+ if (ruby_sourcefile && !NIL_P(mesg)) {
+ at = get_backtrace(mesg);
+ if (NIL_P(at)) {
+ at = make_backtrace();
+ set_backtrace(mesg, at);
+ }
}
- else if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) {
- errat = make_backtrace();
+ if (!NIL_P(mesg)) {
+ rb_errinfo = mesg;
}
- if (!NIL_P(mesg)) {
- if (obj_is_kind_of(mesg, eGlobalExit)) {
- errinfo = mesg;
- }
- else {
- errinfo = exc_new3(eRuntimeError, mesg);
- }
- str_freeze(errinfo);
+ if (RTEST(rb_debug) && !NIL_P(rb_errinfo)
+ && !rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
+ fprintf(stderr, "Exception `%s' at %s:%d\n",
+ rb_class2name(CLASS_OF(rb_errinfo)),
+ ruby_sourcefile, ruby_sourceline);
}
+ rb_trap_restore_mask();
+ if (trace_func && tag != TAG_FATAL) {
+ call_trace_func("raise", ruby_sourcefile, ruby_sourceline,
+ ruby_frame->self, ruby_frame->last_func, 0);
+ }
+ if (!prot_tag) {
+ error_print();
+ }
JUMP_TAG(tag);
}
void
-rb_raise(mesg)
+rb_exc_raise(mesg)
VALUE mesg;
{
- rb_longjmp(TAG_RAISE, mesg, Qnil);
+ rb_longjmp(TAG_RAISE, mesg);
}
void
-rb_fatal(mesg)
+rb_exc_fatal(mesg)
VALUE mesg;
{
- rb_longjmp(TAG_FATAL, mesg, Qnil);
+ rb_longjmp(TAG_FATAL, mesg);
}
void
rb_interrupt()
{
- Raise(eInterrupt, "");
+ rb_raise(rb_eInterrupt, "");
}
static VALUE
-f_raise(argc, argv)
+rb_f_raise(argc, argv)
int argc;
VALUE *argv;
{
VALUE arg1, arg2, arg3;
- VALUE etype, mesg;
+ VALUE mesg;
int n;
- etype = eRuntimeError;
mesg = Qnil;
switch (n = rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3)) {
case 1:
mesg = arg1;
break;
- case 2:
case 3:
- etype = arg1;
- if (obj_is_kind_of(etype, eGlobalExit)) {
- etype = CLASS_OF(etype);
- }
- else {
- Check_Type(etype, T_CLASS);
- }
+ case 2:
mesg = arg2;
break;
}
if (!NIL_P(mesg)) {
- Check_Type(mesg, T_STRING);
- if (n == 2 || !obj_is_kind_of(mesg, eException)) {
- mesg = exc_new3(etype, mesg);
+ if (n == 1 && TYPE(mesg) == T_STRING) {
+ mesg = rb_exc_new3(rb_eRuntimeError, mesg);
+ }
+ else {
+ mesg = rb_funcall(arg1, rb_intern("new"), 1, mesg);
+ }
+ if (!rb_obj_is_kind_of(mesg, rb_eException)) {
+ rb_raise(rb_eTypeError, "exception object expected");
}
+ set_backtrace(mesg, arg3);
}
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
- rb_longjmp(TAG_RAISE, mesg, arg3);
+ *ruby_frame = *_frame.prev->prev;
+ rb_longjmp(TAG_RAISE, mesg);
POP_FRAME();
+
+ return Qnil; /* not reached */
+}
+
+void
+rb_jump_tag(tag)
+ int tag;
+{
+ JUMP_TAG(tag);
}
int
-iterator_p()
+rb_iterator_p()
{
- if (the_frame->iter) return TRUE;
- return FALSE;
+ if (ruby_frame->iter) return Qtrue;
+ return Qfalse;
}
static VALUE
-f_iterator_p()
+rb_f_iterator_p()
{
- if (the_frame->prev && the_frame->prev->iter) return TRUE;
- return FALSE;
+ if (ruby_frame->prev && ruby_frame->prev->iter) return Qtrue;
+ return Qfalse;
}
-VALUE
-rb_yield_0(val, self)
- VALUE val;
- volatile VALUE self;
+static VALUE
+rb_yield_0(val, self, klass)
+ VALUE val, self, klass; /* OK */
{
NODE *node;
volatile VALUE result = Qnil;
@@ -2598,23 +3095,23 @@ rb_yield_0(val, self)
struct SCOPE *old_scope;
struct FRAME frame;
int state;
- static USHORT serial = 1;
+ static unsigned serial = 1;
- if (!iterator_p()) {
- Raise(eLocalJumpError, "yield called out of iterator");
+ if (!ruby_frame->iter || !ruby_block) {
+ rb_raise(rb_eLocalJumpError, "yield called out of iterator");
}
PUSH_VARS();
PUSH_CLASS();
- block = the_block;
+ block = ruby_block;
frame = block->frame;
- frame.prev = the_frame;
- the_frame = &(frame);
- old_scope = the_scope;
- the_scope = block->scope;
- the_block = block->prev;
- the_dyna_vars = block->d_vars;
- the_class = block->class;
+ frame.prev = ruby_frame;
+ ruby_frame = &(frame);
+ old_scope = ruby_scope;
+ ruby_scope = block->scope;
+ ruby_block = block->prev;
+ ruby_dyna_vars = block->d_vars;
+ ruby_class = klass?klass:block->klass;
if (!self) self = block->self;
node = block->body;
if (block->var) {
@@ -2660,9 +3157,11 @@ rb_yield_0(val, self)
POP_ITER();
POP_CLASS();
POP_VARS();
- the_block = block;
- the_frame = the_frame->prev;
- the_scope = old_scope;
+ ruby_block = block;
+ ruby_frame = ruby_frame->prev;
+ if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE))
+ FL_SET(old_scope, SCOPE_DONT_RECYCLE);
+ ruby_scope = old_scope;
if (state) JUMP_TAG(state);
return result;
}
@@ -2671,13 +3170,13 @@ VALUE
rb_yield(val)
VALUE val;
{
- return rb_yield_0(val, 0);
+ return rb_yield_0(val, 0, 0);
}
static VALUE
-f_loop()
+rb_f_loop()
{
- for (;;) { rb_yield(Qnil); }
+ for (;;) { rb_yield_0(Qnil, 0, 0); }
}
static VALUE
@@ -2702,10 +3201,10 @@ massign(self, node, val)
}
if (node->nd_args) {
if (!list && i<len) {
- assign(self, node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i));
+ assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i));
}
else {
- assign(self, node->nd_args, ary_new2(0));
+ assign(self, node->nd_args, rb_ary_new2(0));
}
}
}
@@ -2735,17 +3234,25 @@ assign(self, lhs, val)
break;
case NODE_LASGN:
- if (the_scope->local_vars == 0)
- Bug("unexpected iterator variable assignment");
- the_scope->local_vars[lhs->nd_cnt] = val;
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected iterator variable assignment");
+ ruby_scope->local_vars[lhs->nd_cnt] = val;
break;
case NODE_DASGN:
- dyna_var_asgn(lhs->nd_vid, val);
+ rb_dvar_asgn(lhs->nd_vid, val);
+ break;
+
+ case NODE_DASGN_PUSH:
+ dvar_asgn_push(lhs->nd_vid, val);
break;
case NODE_CASGN:
- rb_const_set(the_class, lhs->nd_vid, val);
+ rb_const_set(ruby_class, lhs->nd_vid, val);
+ break;
+
+ case NODE_MASGN:
+ massign(self, lhs, val);
break;
case NODE_CALL:
@@ -2754,7 +3261,7 @@ assign(self, lhs, val)
recv = rb_eval(self, lhs->nd_recv);
if (!lhs->nd_args->nd_head) {
/* attr set */
- rb_funcall2(recv, lhs->nd_mid, 1, &val);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, 0);
}
else {
/* array set */
@@ -2762,13 +3269,14 @@ assign(self, lhs, val)
args = rb_eval(self, lhs->nd_args);
RARRAY(args)->ptr[RARRAY(args)->len-1] = val;
- rb_apply(recv, lhs->nd_mid, args);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
+ RARRAY(args)->len, RARRAY(args)->ptr, 0);
}
}
break;
default:
- Bug("bug in variable assignment");
+ rb_bug("bug in variable assignment");
break;
}
}
@@ -2781,7 +3289,7 @@ rb_iterate(it_proc, data1, bl_proc, data2)
int state;
volatile VALUE retval = Qnil;
NODE *node = NEW_CFUNC(bl_proc, data2);
- VALUE self = TopSelf;
+ VALUE self = ruby_top_self;
iter_retry:
PUSH_ITER(ITER_PRE);
@@ -2792,10 +3300,10 @@ rb_iterate(it_proc, data1, bl_proc, data2)
if (state == 0) {
retval = (*it_proc)(data1);
}
- if (the_block->tag->dst == state) {
+ if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- retval = prot_tag->tag_retval;
+ retval = prot_tag->retval;
}
}
POP_TAG();
@@ -2828,19 +3336,21 @@ handle_rescue(self, node)
NODE *node;
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
if (!node->nd_args) {
- return obj_is_kind_of(errinfo, eException);
+ return rb_obj_is_kind_of(rb_errinfo, rb_eStandardError);
}
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
while (argc--) {
- if (!obj_is_kind_of(argv[0], cModule)) {
- TypeError("class or module required for rescue clause");
+ if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
+ rb_raise(rb_eTypeError, "class or module required for rescue clause");
}
- if (obj_is_kind_of(errinfo, argv[0])) return 1;
+ if (rb_obj_is_kind_of(rb_errinfo, argv[0])) return 1;
argv++;
}
return 0;
@@ -2853,17 +3363,18 @@ rb_rescue(b_proc, data1, r_proc, data2)
{
int state;
volatile VALUE result;
+ volatile VALUE e_info = rb_errinfo;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
retry_entry:
result = (*b_proc)(data1);
}
- else if (state == TAG_RAISE && obj_is_kind_of(errinfo, eException)) {
+ else if (state == TAG_RAISE && rb_obj_is_kind_of(rb_errinfo, rb_eStandardError)) {
if (r_proc) {
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- result = (*r_proc)(data2, errinfo);
+ result = (*r_proc)(data2, rb_errinfo);
}
POP_TAG();
if (state == TAG_RETRY) {
@@ -2876,7 +3387,7 @@ rb_rescue(b_proc, data1, r_proc, data2)
state = 0;
}
if (state == 0) {
- errat = Qnil;
+ rb_errinfo = e_info;
}
}
POP_TAG();
@@ -2886,42 +3397,69 @@ rb_rescue(b_proc, data1, r_proc, data2)
}
VALUE
+rb_protect(proc, data, state)
+ VALUE (*proc)();
+ VALUE data;
+ int *state;
+{
+ VALUE result; /* OK */
+ int status;
+
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = (*proc)(data);
+ }
+ POP_TAG();
+ if (state) {
+ *state = status;
+ }
+ if (status != 0) {
+ return Qnil;
+ }
+
+ return result;
+}
+
+VALUE
rb_ensure(b_proc, data1, e_proc, data2)
VALUE (*b_proc)();
- void (*e_proc)();
+ VALUE (*e_proc)();
VALUE data1, data2;
{
int state;
volatile VALUE result = Qnil;
+ VALUE retval;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
result = (*b_proc)(data1);
}
POP_TAG();
-
+ retval = prot_tag->retval; /* save retval */
(*e_proc)(data2);
- if (state) {
- JUMP_TAG(state);
- }
+ return_value(retval);
+
+ if (state) JUMP_TAG(state);
return result;
}
static int last_call_status;
-#define CSTAT_NOEX 1
-#define CSTAT_VCALL 2
+
+#define CSTAT_PRIV 1
+#define CSTAT_PROT 2
+#define CSTAT_VCALL 4
static VALUE
-f_missing(argc, argv, obj)
+rb_f_missing(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
- VALUE desc = 0;
ID id;
+ VALUE desc = 0;
char *format = 0;
- char *file = sourcefile;
- int line = sourceline;
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
id = FIX2INT(argv[0]);
argc--; argv++;
@@ -2931,23 +3469,26 @@ f_missing(argc, argv, obj)
format = "undefined method `%s' for nil";
break;
case T_TRUE:
- format = "undefined method `%s' for TRUE";
+ format = "undefined method `%s' for Qtrue";
break;
case T_FALSE:
- format = "undefined method `%s' for FALSE";
+ format = "undefined method `%s' for Qfalse";
break;
case T_OBJECT:
- desc = obj_as_string(obj);
+ desc = rb_any_to_s(obj);
break;
default:
desc = rb_inspect(obj);
break;
}
if (desc) {
- if (last_call_status & CSTAT_NOEX) {
+ if (last_call_status & CSTAT_PRIV) {
format = "private method `%s' called for %s";
}
- else if (iterator_p()) {
+ if (last_call_status & CSTAT_PROT) {
+ format = "protected method `%s' called for %s";
+ }
+ else if (rb_iterator_p()) {
format = "undefined iterator `%s' for %s";
}
else if (last_call_status & CSTAT_VCALL) {
@@ -2961,18 +3502,18 @@ f_missing(argc, argv, obj)
format = "undefined method `%s' for %s";
}
if (RSTRING(desc)->len > 65) {
- desc = any_to_s(obj);
+ desc = rb_any_to_s(obj);
}
}
- sourcefile = file;
- sourceline = line;
+ ruby_sourcefile = file;
+ ruby_sourceline = line;
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
+ *ruby_frame = *_frame.prev->prev;
- NameError(format,
- rb_id2name(id),
- desc?(char*)RSTRING(desc)->ptr:"");
+ rb_raise(rb_eNameError, format,
+ rb_id2name(id),
+ desc?(char*)RSTRING(desc)->ptr:"");
POP_FRAME();
return Qnil; /* not reached */
@@ -3004,58 +3545,127 @@ rb_undefined(obj, id, argc, argv, call_status)
extern int _stacksize;
# define STACK_LEVEL_MAX (_stacksize - 4096)
#else
-# define STACK_LEVEL_MAX 655350
+# define STACK_LEVEL_MAX 655300
#endif
#endif
-extern VALUE *gc_stack_start;
+extern VALUE *rb_gc_stack_start;
static int
stack_length()
{
VALUE pos;
#ifdef sparc
- return gc_stack_start - &pos + 0x80;
+ return rb_gc_stack_start - &pos + 0x80;
#else
- return (&pos < gc_stack_start) ? gc_stack_start - &pos
- : &pos - gc_stack_start;
+ return (&pos < rb_gc_stack_start) ? rb_gc_stack_start - &pos
+ : &pos - rb_gc_stack_start;
#endif
}
static VALUE
-rb_call(class, recv, mid, argc, argv, scope)
- VALUE class, recv;
- ID mid;
+call_cfunc(func, recv, len, argc, argv)
+ VALUE (*func)();
+ VALUE recv;
+ int len, argc;
+ VALUE *argv;
+{
+ if (len >= 0 && argc != len) {
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)",
+ argc, len);
+ }
+
+ switch (len) {
+ case -2:
+ return (*func)(recv, rb_ary_new4(argc, argv));
+ break;
+ case -1:
+ return (*func)(argc, argv, recv);
+ break;
+ case 0:
+ return (*func)(recv);
+ break;
+ case 1:
+ return (*func)(recv, argv[0]);
+ break;
+ case 2:
+ return (*func)(recv, argv[0], argv[1]);
+ break;
+ case 3:
+ return (*func)(recv, argv[0], argv[1], argv[2]);
+ break;
+ case 4:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3]);
+ break;
+ case 5:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ break;
+ case 6:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5]);
+ break;
+ case 7:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6]);
+ break;
+ case 8:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7]);
+ break;
+ case 9:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8]);
+ break;
+ case 10:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9]);
+ break;
+ case 11:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
+ break;
+ case 12:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9],
+ argv[10], argv[11]);
+ break;
+ case 13:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12]);
+ break;
+ case 14:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12], argv[13]);
+ break;
+ case 15:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12], argv[13], argv[14]);
+ break;
+ default:
+ rb_raise(rb_eArgError, "too many arguments(%d)", len);
+ break;
+ }
+ return Qnil; /* not reached */
+}
+
+static VALUE
+rb_call0(klass, recv, id, argc, argv, body, nosuper)
+ VALUE klass, recv;
+ ID id;
int argc; /* OK */
VALUE *argv; /* OK */
- int scope;
+ NODE *body; /* OK */
+ int nosuper;
{
- NODE *body, *b2; /* OK */
- int noex;
- ID id = mid;
- struct cache_entry *ent;
+ NODE *b2; /* OK */
volatile VALUE result = Qnil;
int itr;
- enum node_type type;
static int tick;
+ TMP_PROTECT;
- again:
- /* is it in the method cache? */
- ent = cache + EXPR1(class, mid);
- if (ent->mid == mid && ent->class == class) {
- class = ent->origin;
- id = ent->mid0;
- noex = ent->noex;
- body = ent->method;
- }
- else if ((body = rb_get_method_body(&class, &id, &noex)) == 0) {
- return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- }
-
- /* receiver specified form for private method */
- if (noex == NOEX_PRIVATE && scope == 0)
- return rb_undefined(recv, mid, argc, argv, CSTAT_NOEX);
-
- switch (the_iter->iter) {
+ switch (ruby_iter->iter) {
case ITER_PRE:
itr = ITER_CUR;
break;
@@ -3065,151 +3675,57 @@ rb_call(class, recv, mid, argc, argv, scope)
break;
}
- type = nd_type(body);
- if (type == NODE_ZSUPER) {
- /* for re-scoped/renamed method */
- mid = id;
- if (scope == 0) scope = 1;
- if (RCLASS(class)->super == 0) {
- /* origin is the Module, so need to scan superclass hierarchy. */
- struct RClass *cl = RCLASS(class);
-
- class = RBASIC(recv)->class;
- while (class) {
- if (RCLASS(class)->m_tbl == cl->m_tbl)
- break;
- class = RCLASS(class)->super;
- }
- }
- else {
- class = RCLASS(class)->super;
+ if ((++tick & 0x3ff) == 0) {
+ CHECK_INTS; /* better than nothing */
+ if (stack_length() > STACK_LEVEL_MAX) {
+ rb_raise(rb_eSysStackError, "stack level too deep");
}
- goto again;
}
- if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX)
- Fatal("stack level too deep");
-
PUSH_ITER(itr);
PUSH_FRAME();
- the_frame->last_func = id;
- the_frame->last_class = class;
- the_frame->argc = argc;
- the_frame->argv = argv;
- switch (type) {
+ ruby_frame->last_func = id;
+ ruby_frame->last_class = nosuper?0:klass;
+ ruby_frame->self = recv;
+ ruby_frame->argc = argc;
+ ruby_frame->argv = argv;
+
+ switch (nd_type(body)) {
case NODE_CFUNC:
{
int len = body->nd_argc;
- if (len >= 0 && argc != len) {
- ArgError("Wrong # of arguments(%d for %d)", argc, len);
+ if (len < -2) {
+ rb_bug("bad argc(%d) specified for `%s(%s)'",
+ len, rb_class2name(klass), rb_id2name(id));
}
-
- switch (len) {
- case -2:
- result = (*body->nd_cfnc)(recv, ary_new4(argc, argv));
- break;
- case -1:
- result = (*body->nd_cfnc)(argc, argv, recv);
- break;
- case 0:
- result = (*body->nd_cfnc)(recv);
- break;
- case 1:
- result = (*body->nd_cfnc)(recv, argv[0]);
- break;
- case 2:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1]);
- break;
- case 3:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2]);
- break;
- case 4:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3]);
- break;
- case 5:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4]);
- break;
- case 6:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
- break;
- case 7:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6]);
- break;
- case 8:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7]);
- break;
- case 9:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8]);
- break;
- case 10:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9]);
- break;
- case 11:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10]);
- break;
- case 12:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11]);
- break;
- case 13:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12]);
- break;
- case 14:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13]);
- break;
- case 15:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13], argv[14]);
- break;
- default:
- if (len < 0) {
- Bug("bad argc(%d) specified for `%s(%s)'",
- len, rb_class2name((VALUE)class), rb_id2name(mid));
+ if (trace_func) {
+ int state;
+ char *file = ruby_frame->prev->file;
+ int line = ruby_frame->prev->line;
+ if (!file) {
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
}
- else {
- ArgError("too many arguments(%d)", len);
+
+ call_trace_func("c-call", 0, 0, 0, id, 0);
+ PUSH_TAG(PROT_FUNC);
+ if ((state = EXEC_TAG()) == 0) {
+ result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
- break;
+ POP_TAG();
+ call_trace_func("c-return", 0, 0, recv, id, klass);
+ if (state) JUMP_TAG(state);
+ }
+ else {
+ result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
}
break;
+ /* for re-scoped/renamed method */
+ case NODE_ZSUPER:
/* for attr get/set */
case NODE_ATTRSET:
case NODE_IVAR:
@@ -3223,36 +3739,44 @@ rb_call(class, recv, mid, argc, argv, scope)
PUSH_SCOPE();
- if (body->nd_rval) the_frame->cbase = body->nd_rval;
+ if (body->nd_rval) ruby_frame->cbase = body->nd_rval;
if (body->nd_tbl) {
- local_vars = ALLOCA_N(VALUE, body->nd_tbl[0]+1);
+ local_vars = TMP_ALLOC(body->nd_tbl[0]+1);
*local_vars++ = (VALUE)body;
- memclear(local_vars, body->nd_tbl[0]);
- the_scope->local_tbl = body->nd_tbl;
- the_scope->local_vars = local_vars;
+ rb_mem_clear(local_vars, body->nd_tbl[0]);
+ ruby_scope->local_tbl = body->nd_tbl;
+ ruby_scope->local_vars = local_vars;
}
else {
- local_vars = the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ local_vars = ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
- b2 = body = body->nd_body;
+ b2 = body = body->nd_next;
- PUSH_TAG(PROT_FUNC);
PUSH_VARS();
+ PUSH_TAG(PROT_FUNC);
if ((state = EXEC_TAG()) == 0) {
- if (nd_type(body) == NODE_BLOCK) {
- NODE *node = body->nd_head;
- int i;
+ NODE *node = 0;
+ int i;
+ if (nd_type(body) == NODE_ARGS) {
+ node = body;
+ body = 0;
+ }
+ else if (nd_type(body) == NODE_BLOCK) {
+ node = body->nd_head;
+ body = body->nd_next;
+ }
+ if (node) {
if (nd_type(node) != NODE_ARGS) {
- Bug("no argument-node");
+ rb_bug("no argument-node");
}
- body = body->nd_next;
i = node->nd_cnt;
if (i > argc) {
- ArgError("Wrong # of arguments(%d for %d)", argc, i);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)",
+ argc, i);
}
if (node->nd_rest == -1) {
int opt = argc - i;
@@ -3263,14 +3787,15 @@ rb_call(class, recv, mid, argc, argv, scope)
optnode = optnode->nd_next;
}
if (opt > 0) {
- ArgError("Wrong # of arguments(%d for %d)",
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)",
argc, argc-opt);
}
}
if (local_vars) {
if (i > 0) {
- MEMCPY(local_vars, argv, VALUE, i);
+ /* +2 for $_ and $~ */
+ MEMCPY(local_vars+2, argv, VALUE, i);
}
argv += i; argc -= i;
if (node->nd_opt) {
@@ -3285,53 +3810,52 @@ rb_call(class, recv, mid, argc, argv, scope)
}
if (node->nd_rest >= 0) {
if (argc > 0)
- local_vars[node->nd_rest]=ary_new4(argc,argv);
+ local_vars[node->nd_rest]=rb_ary_new4(argc,argv);
else
- local_vars[node->nd_rest]=ary_new2(0);
+ local_vars[node->nd_rest]=rb_ary_new2(0);
}
}
}
- else if (nd_type(body) == NODE_ARGS) {
- body = 0;
- }
+
if (trace_func) {
call_trace_func("call", b2->nd_file, nd_line(b2),
- recv, the_frame->last_func);
+ recv, ruby_frame->last_func, 0);
}
result = rb_eval(recv, body);
}
else if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
state = 0;
}
- POP_VARS();
POP_TAG();
+ POP_VARS();
POP_SCOPE();
if (trace_func) {
- char *file = the_frame->prev->file;
- int line = the_frame->prev->line;
+ char *file = ruby_frame->prev->file;
+ int line = ruby_frame->prev->line;
if (!file) {
- file = sourcefile;
- line = sourceline;
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
}
- call_trace_func("return", file, line, 0, the_frame->last_func);
+ call_trace_func("return", file, line, recv,
+ ruby_frame->last_func, klass);
}
switch (state) {
case 0:
break;
case TAG_NEXT:
- Raise(eLocalJumpError, "unexpected next");
+ rb_raise(rb_eLocalJumpError, "unexpected next");
break;
case TAG_BREAK:
- Raise(eLocalJumpError, "unexpected break");
+ rb_raise(rb_eLocalJumpError, "unexpected break");
break;
case TAG_REDO:
- Raise(eLocalJumpError, "unexpected redo");
+ rb_raise(rb_eLocalJumpError, "unexpected redo");
break;
case TAG_RETRY:
- if (!iterator_p()) {
- Raise(eLocalJumpError, "retry outside of rescue clause");
+ if (!rb_iterator_p()) {
+ rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
}
default:
JUMP_TAG(state);
@@ -3343,6 +3867,46 @@ rb_call(class, recv, mid, argc, argv, scope)
return result;
}
+static VALUE
+rb_call(klass, recv, mid, argc, argv, scope)
+ VALUE klass, recv;
+ ID mid;
+ int argc; /* OK */
+ VALUE *argv; /* OK */
+ int scope;
+{
+ NODE *body; /* OK */
+ int noex;
+ ID id = mid;
+ struct cache_entry *ent;
+
+ /* is it in the method cache? */
+ ent = cache + EXPR1(klass, mid);
+ if (ent->mid == mid && ent->klass == klass) {
+ klass = ent->origin;
+ id = ent->mid0;
+ noex = ent->noex;
+ body = ent->method;
+ }
+ else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ if (scope == 3) {
+ rb_raise(rb_eNameError, "super: no superclass method `%s'",
+ rb_id2name(mid));
+ }
+ return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
+ }
+
+ /* receiver specified form for private method */
+ if ((noex & NOEX_PRIVATE) && scope == 0)
+ return rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
+
+ /* self must be kind of a specified form for private method */
+ if ((noex & NOEX_PROTECTED) && !rb_obj_is_kind_of(ruby_frame->self, klass))
+ return rb_undefined(recv, mid, argc, argv, CSTAT_PROT);
+
+ return rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF);
+}
+
VALUE
rb_apply(recv, mid, args)
VALUE recv;
@@ -3359,38 +3923,42 @@ rb_apply(recv, mid, args)
}
static VALUE
-f_send(argc, argv, recv)
+rb_f_send(argc, argv, recv)
int argc;
VALUE *argv;
VALUE recv;
{
VALUE vid;
- ID mid;
- if (argc == 0) ArgError("no method name given");
+ if (argc == 0) rb_raise(rb_eArgError, "no method name given");
- vid = argv[0]; argc--; argv++;
- if (TYPE(vid) == T_STRING) {
- mid = rb_intern(RSTRING(vid)->ptr);
- }
- else {
- mid = NUM2INT(vid);
- }
- PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
- vid = rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
+ vid = *argv++; argc--;
+ PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
+ vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1);
POP_ITER();
return vid;
}
+
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
VALUE
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_funcall(VALUE recv, ID mid, int n, ...)
+#else
rb_funcall(recv, mid, n, va_alist)
VALUE recv;
ID mid;
int n;
va_dcl
+#endif
{
va_list ar;
VALUE *argv;
@@ -3400,7 +3968,7 @@ rb_funcall(recv, mid, n, va_alist)
argv = ALLOCA_N(VALUE, n);
- va_start(ar);
+ va_init_list(ar, n);
for (i=0;i<n;i++) {
argv[i] = va_arg(ar, VALUE);
}
@@ -3427,22 +3995,23 @@ static VALUE
backtrace(lev)
int lev;
{
- struct FRAME *frame = the_frame;
+ struct FRAME *frame = ruby_frame;
char buf[BUFSIZ];
VALUE ary;
int slev = safe_level;
safe_level = 0;
- ary = ary_new();
+ ary = rb_ary_new();
if (lev < 0) {
if (frame->last_func) {
- sprintf(buf, "%s:%d:in `%s'", sourcefile, sourceline,
- rb_id2name(frame->last_func));
+ snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
+ ruby_sourcefile, ruby_sourceline,
+ rb_id2name(frame->last_func));
}
else {
- sprintf(buf, "%s:%d", sourcefile, sourceline);
+ snprintf(buf, BUFSIZ, "%s:%d", ruby_sourcefile, ruby_sourceline);
}
- ary_push(ary, str_new2(buf));
+ rb_ary_push(ary, rb_str_new2(buf));
}
else {
while (lev-- > 0) {
@@ -3452,14 +4021,14 @@ backtrace(lev)
}
while (frame && frame->file) {
if (frame->prev && frame->prev->last_func) {
- sprintf(buf, "%s:%d:in `%s'",
- frame->file, frame->line,
- rb_id2name(frame->prev->last_func));
+ snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
+ frame->file, frame->line,
+ rb_id2name(frame->prev->last_func));
}
else {
- sprintf(buf, "%s:%d", frame->file, frame->line);
+ snprintf(buf, BUFSIZ, "%s:%d", frame->file, frame->line);
}
- ary_push(ary, str_new2(buf));
+ rb_ary_push(ary, rb_str_new2(buf));
frame = frame->prev;
}
safe_level = slev;
@@ -3467,7 +4036,7 @@ backtrace(lev)
}
static VALUE
-f_caller(argc, argv)
+rb_f_caller(argc, argv)
int argc;
VALUE *argv;
{
@@ -3478,7 +4047,7 @@ f_caller(argc, argv)
if (NIL_P(level)) lev = 1;
else lev = NUM2INT(level);
- if (lev < 0) ArgError("negative level(%d)", lev);
+ if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev);
return backtrace(lev);
}
@@ -3508,77 +4077,91 @@ make_backtrace()
ID
rb_frame_last_func()
{
- return the_frame->last_func;
+ return ruby_frame->last_func;
}
static NODE*
-compile(src)
+compile(src, place)
VALUE src;
+ char *place;
{
NODE *node;
Check_Type(src, T_STRING);
+ if (place == 0) place = ruby_sourcefile;
+ node = rb_compile_string(place, src);
- node = compile_string(sourcefile, RSTRING(src)->ptr, RSTRING(src)->len);
-
- if (nerrs == 0) return node;
+ if (ruby_nerrs == 0) return node;
return 0;
}
static VALUE
-eval(self, src, scope)
+eval(self, src, scope, file, line)
VALUE self, src, scope;
+ char *file;
+ int line;
{
struct BLOCK *data;
volatile VALUE result = Qnil;
struct SCOPE * volatile old_scope;
struct BLOCK * volatile old_block;
+ struct BLOCK * volatile old_call_block;
struct RVarmap * volatile old_d_vars;
+ int volatile old_vmode;
struct FRAME frame;
- char *file = sourcefile;
- int line = sourceline;
- volatile int iter = the_frame->iter;
+ char *filesave = ruby_sourcefile;
+ int linesave = ruby_sourceline;
+ volatile int iter = ruby_frame->iter;
int state;
+ if (file == 0) {
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
+ }
if (!NIL_P(scope)) {
- if (TYPE(scope) != T_DATA || RDATA(scope)->dfree != blk_free) {
- TypeError("wrong argument type %s (expected Proc/Binding)",
- rb_class2name(CLASS_OF(scope)));
+ if (!rb_obj_is_block(scope)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Binding)",
+ rb_class2name(CLASS_OF(scope)));
}
Data_Get_Struct(scope, struct BLOCK, data);
/* PUSH BLOCK from data */
frame = data->frame;
- frame.prev = the_frame;
- the_frame = &(frame);
- old_scope = the_scope;
- the_scope = data->scope;
- old_block = the_block;
- the_block = data->prev;
- old_d_vars = the_dyna_vars;
- the_dyna_vars = data->d_vars;
+ frame.prev = ruby_frame;
+ ruby_frame = &(frame);
+ old_scope = ruby_scope;
+ ruby_scope = data->scope;
+ old_call_block = ruby_calling_block;
+ ruby_calling_block = data;
+ old_block = ruby_block;
+ ruby_block = data->prev;
+ old_d_vars = ruby_dyna_vars;
+ ruby_dyna_vars = data->d_vars;
+ old_vmode = scope_vmode;
+ scope_vmode = data->vmode;
self = data->self;
- the_frame->iter = data->iter;
+ ruby_frame->iter = data->iter;
}
else {
- if (the_frame->prev) {
- the_frame->iter = the_frame->prev->iter;
+ if (ruby_frame->prev) {
+ ruby_frame->iter = ruby_frame->prev->iter;
}
}
PUSH_CLASS();
- the_class = ((NODE*)the_frame->cbase)->nd_clss;
+ ruby_class = ((NODE*)ruby_frame->cbase)->nd_clss;
rb_in_eval++;
- if (TYPE(the_class) == T_ICLASS) {
- the_class = RBASIC(the_class)->class;
+ if (TYPE(ruby_class) == T_ICLASS) {
+ ruby_class = RBASIC(ruby_class)->klass;
}
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- eval_tree = 0;
- compile(src);
- if (nerrs > 0) {
+ ruby_sourcefile = file;
+ ruby_sourceline = line;
+ compile(src, file);
+ if (ruby_nerrs > 0) {
compile_error(0);
}
result = eval_node(self);
@@ -3587,31 +4170,41 @@ eval(self, src, scope)
POP_CLASS();
rb_in_eval--;
if (!NIL_P(scope)) {
- the_frame = the_frame->prev;
- the_scope = old_scope;
- the_block = old_block;
- the_dyna_vars = old_d_vars;
+ ruby_frame = ruby_frame->prev;
+ if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE))
+ FL_SET(old_scope, SCOPE_DONT_RECYCLE);
+ ruby_scope = old_scope;
+ ruby_block = old_block;
+ ruby_calling_block = old_call_block;
+ data->d_vars = ruby_dyna_vars;
+ ruby_dyna_vars = old_d_vars;
+ data->vmode = scope_vmode; /* write back visibility mode */
+ scope_vmode = old_vmode;
}
else {
- the_frame->iter = iter;
+ ruby_frame->iter = iter;
}
+ ruby_sourcefile = filesave;
+ ruby_sourceline = linesave;
if (state) {
- VALUE err;
-
if (state == TAG_RAISE) {
- sourcefile = file;
- sourceline = line;
- if (strcmp(sourcefile, "(eval)") == 0) {
- err = str_dup(errinfo);
- if (sourceline > 1) {
+ VALUE err;
+ VALUE errat;
+
+ errat = get_backtrace(rb_errinfo);
+ if (strcmp(file, "(eval)") == 0) {
+ if (ruby_sourceline > 1) {
err = RARRAY(errat)->ptr[0];
- str_cat(err, ": ", 2);
- str_cat(err, RSTRING(errinfo)->ptr, RSTRING(errinfo)->len);
+ rb_str_cat(err, ": ", 2);
+ rb_str_concat(err, rb_errinfo);
+ }
+ else {
+ err = rb_str_dup(rb_errinfo);
}
errat = Qnil;
- rb_raise(exc_new3(CLASS_OF(errinfo), err));
+ rb_exc_raise(rb_exc_new3(CLASS_OF(rb_errinfo), err));
}
- rb_raise(Qnil);
+ rb_exc_raise(rb_errinfo);
}
JUMP_TAG(state);
}
@@ -3620,40 +4213,55 @@ eval(self, src, scope)
}
static VALUE
-f_eval(argc, argv, self)
+rb_f_eval(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
- VALUE src, scope;
+ VALUE src, scope, vfile, vline;
+ char *file = "(eval)";
+ int line = 0;
- rb_scan_args(argc, argv, "11", &src, &scope);
+ rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
+ if (argc >= 3) {
+ Check_Type(vfile, T_STRING);
+ file = RSTRING(vfile)->ptr;
+ }
+ if (argc >= 4) {
+ line = NUM2INT(vline);
+ }
Check_SafeStr(src);
- return eval(self, src, scope);
+ return eval(self, src, scope, file, line);
}
static VALUE
-eval_under(under, self, src)
- VALUE under, self, src;
+exec_under(func, under, args)
+ VALUE (*func)();
+ VALUE under;
+ void *args;
{
VALUE val; /* OK */
int state;
- VALUE cbase = the_frame->cbase;
+ int mode;
+ VALUE cbase = ruby_frame->cbase;
PUSH_CLASS();
- the_class = under;
+ ruby_class = under;
PUSH_FRAME();
- the_frame->last_func = _frame->last_func;
- the_frame->last_class = _frame->last_class;
- the_frame->argc = 1;
- the_frame->argv = &src;
- the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase);
+ ruby_frame->last_func = _frame.prev->last_func;
+ ruby_frame->last_class = _frame.prev->last_class;
+ ruby_frame->argc = _frame.prev->argc;
+ ruby_frame->argv = _frame.prev->argv;
+ ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,under,0,cbase);
+ mode = scope_vmode;
+ SCOPE_SET(SCOPE_PUBLIC);
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- val = eval(self, src, Qnil);
+ val = (*func)(args);
}
POP_TAG();
+ SCOPE_SET(mode);
POP_FRAME();
POP_CLASS();
if (state) JUMP_TAG(state);
@@ -3662,36 +4270,145 @@ eval_under(under, self, src)
}
static VALUE
-obj_instance_eval(self, src)
- VALUE self, src;
+eval_under_i(args)
+ VALUE *args;
+{
+ return eval(args[0], args[1], Qnil, (char*)args[2], (int)args[3]);
+}
+
+static VALUE
+eval_under(under, self, src, file, line)
+ VALUE under, self, src;
+ char *file;
+ int line;
+{
+ VALUE args[4];
+
+ Check_SafeStr(src);
+ args[0] = self;
+ args[1] = src;
+ args[2] = (VALUE)file;
+ args[3] = (VALUE)line;
+ return exec_under(eval_under_i, under, args);
+}
+
+static VALUE
+yield_under_i(self)
+ VALUE self;
+{
+ return rb_yield_0(self, self, ruby_class);
+}
+
+static VALUE
+yield_under(under, self)
+ VALUE under, self;
+{
+ rb_secure(4);
+ return exec_under(yield_under_i, under, self);
+}
+
+VALUE
+rb_obj_instance_eval(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- return eval_under(CLASS_OF(self), self, src);
+ char *file = 0;
+ int line = 0;
+ VALUE klass;
+
+ if (argc == 0) {
+ if (!rb_iterator_p()) {
+ rb_raise(rb_eArgError, "block not supplied");
+ }
+ }
+ else if (argc < 4) {
+ Check_SafeStr(argv[0]);
+ if (argc > 1) file = STR2CSTR(argv[1]);
+ if (argc > 2) line = NUM2INT(argv[2]);
+ }
+ else {
+ rb_raise(rb_eArgError, "Wrong # of arguments: %s(src) or %s{..}",
+ rb_id2name(ruby_frame->last_func),
+ rb_id2name(ruby_frame->last_func));
+ }
+
+ if (rb_special_const_p(self)) {
+ klass = Qnil;
+ }
+ else {
+ klass = rb_singleton_class(self);
+ }
+ if (argc == 0) {
+ return yield_under(klass, self);
+ }
+ else {
+ return eval_under(klass, self, argv[0], file, line);
+ }
}
static VALUE
-mod_module_eval(mod, src)
- VALUE mod, src;
+rb_mod_module_eval(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
{
- return eval_under(mod, mod, src);
+ char *file = 0;
+ int line = 0;
+
+ if (argc == 0) {
+ if (!rb_iterator_p()) {
+ rb_raise(rb_eArgError, "block not supplied");
+ }
+ }
+ else if (argc < 4) {
+ Check_SafeStr(argv[0]);
+ if (argc > 1) file = STR2CSTR(argv[1]);
+ if (argc > 2) line = NUM2INT(argv[2]);
+ }
+ else {
+ rb_raise(rb_eArgError, "Wrong # of arguments: %s(src) or %s{..}",
+ rb_id2name(ruby_frame->last_func),
+ rb_id2name(ruby_frame->last_func));
+ }
+
+ if (argc == 0) {
+ return yield_under(mod, mod);
+ }
+ else {
+ return eval_under(mod, mod, argv[0], file, line);
+ }
}
VALUE rb_load_path;
-char *dln_find_file();
+static int
+is_absolute_path(path)
+ char *path;
+{
+ if (path[0] == '/') return 1;
+# if defined(MSDOS) || defined(NT) || defined(__human68k__)
+ if (path[0] == '\\') return 1;
+ if (strlen(path) > 2 && path[1] == ':') return 1;
+# endif
+ return 0;
+}
static char*
find_file(file)
char *file;
{
extern VALUE rb_load_path;
- VALUE vpath;
+ volatile VALUE vpath;
char *path;
- if (file[0] == '/') return file;
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
- if (file[0] == '\\') return file;
- if (file[1] == ':') return file;
-#endif
+ if (is_absolute_path(file)) {
+ FILE *f = fopen(file, "r");
+
+ if (f == NULL) return 0;
+ fclose(f);
+ return file;
+ }
if (rb_load_path) {
int i;
@@ -3700,13 +4417,11 @@ find_file(file)
for (i=0;i<RARRAY(rb_load_path)->len;i++) {
Check_SafeStr(RARRAY(rb_load_path)->ptr[i]);
}
-#if !defined(MSDOS) && !defined(NT) && !defined(__human68k__)
- vpath = ary_join(rb_load_path, str_new2(":"));
-#else
- vpath = ary_join(rb_load_path, str_new2(";"));
-#endif
- Check_SafeStr(vpath);
- path = RSTRING(vpath)->ptr;
+ vpath = rb_ary_join(rb_load_path, rb_str_new2(RUBY_PATH_SEP));
+ path = STR2CSTR(vpath);
+ if (safe_level >= 2 && !rb_path_check(path)) {
+ rb_raise(rb_eSecurityError, "loading from unsefe path %s", path);
+ }
}
else {
path = 0;
@@ -3715,62 +4430,117 @@ find_file(file)
return dln_find_file(file, path);
}
-VALUE
-f_load(obj, fname)
- VALUE obj, fname;
+void
+rb_load(fname, wrap)
+ VALUE fname;
+ int wrap;
{
int state;
char *file;
volatile ID last_func;
+ VALUE self = ruby_top_self;
+ TMP_PROTECT;
- Check_SafeStr(fname);
+ if (wrap) {
+ Check_Type(fname, T_STRING);
+ }
+ else {
+ Check_SafeStr(fname);
+ }
+#ifndef __MACOS__
if (RSTRING(fname)->ptr[0] == '~') {
- fname = file_s_expand_path(0, fname);
+ fname = rb_file_s_expand_path(1, &fname);
}
+#endif
file = find_file(RSTRING(fname)->ptr);
- if (!file) LoadError("No such file to load -- %s", RSTRING(fname)->ptr);
+ if (!file) {
+ rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
+ }
+ PUSH_VARS();
PUSH_TAG(PROT_NONE);
PUSH_CLASS();
- the_class = cObject;
+ if (!wrap) {
+ rb_secure(4); /* should alter global state */
+ ruby_class = rb_cObject;
+ }
+ else {
+ /* load in anonymous module as toplevel */
+ ruby_class = ruby_wrapper = rb_module_new();
+ self = rb_obj_clone(ruby_top_self);
+ rb_extend_object(self, ruby_class);
+ }
+ PUSH_FRAME();
+ ruby_frame->last_func = 0;
+ ruby_frame->self = ruby_top_self;
+ ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0);
PUSH_SCOPE();
- if (top_scope->local_tbl) {
+ if (ruby_class == rb_cObject && top_scope->local_tbl) {
int len = top_scope->local_tbl[0]+1;
ID *tbl = ALLOC_N(ID, len);
- VALUE *vars = ALLOCA_N(VALUE, len);
+ VALUE *vars = TMP_ALLOC(len);
*vars++ = 0;
MEMCPY(tbl, top_scope->local_tbl, ID, len);
MEMCPY(vars, top_scope->local_vars, ID, len-1);
- the_scope->local_tbl = tbl;
- the_scope->local_vars = vars;
+ ruby_scope->local_tbl = tbl; /* copy toplevel scope */
+ ruby_scope->local_vars = vars; /* will not alter toplevel variables */
}
/* default visibility is private at loading toplevel */
- FL_SET(the_scope, SCOPE_PRIVATE);
+ SCOPE_SET(SCOPE_PRIVATE);
state = EXEC_TAG();
- last_func = the_frame->last_func;
- the_frame->last_func = 0;
+ last_func = ruby_frame->last_func;
if (state == 0) {
rb_in_eval++;
rb_load_file(file);
rb_in_eval--;
- if (nerrs == 0) {
- eval_node(TopSelf);
+ if (ruby_nerrs == 0) {
+ eval_node(self);
}
}
- the_frame->last_func = last_func;
- if (the_scope->flag == SCOPE_ALLOCA && the_scope->local_tbl) {
- free(the_scope->local_tbl);
+ ruby_frame->last_func = last_func;
+ if (ruby_scope->flag == SCOPE_ALLOCA && ruby_class == rb_cObject) {
+ if (ruby_scope->local_tbl) /* toplevel was empty */
+ free(ruby_scope->local_tbl);
}
POP_SCOPE();
+ POP_FRAME();
POP_CLASS();
POP_TAG();
- if (nerrs > 0) {
- rb_raise(errinfo);
+ POP_VARS();
+ ruby_wrapper = 0;
+ if (ruby_nerrs > 0) {
+ rb_exc_raise(rb_errinfo);
}
if (state) JUMP_TAG(state);
+}
+
+void
+rb_load_protect(fname, wrap, state)
+ VALUE fname;
+ int wrap;
+ int *state;
+{
+ int status;
+
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ rb_load(fname, wrap);
+ }
+ POP_TAG();
+ if (state) *state = status;
+}
+
+static VALUE
+rb_f_load(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE fname, wrap;
- return TRUE;
+ rb_scan_args(argc, argv, "11", &fname, &wrap);
+ rb_load(fname, RTEST(wrap));
+ return Qtrue;
}
static VALUE rb_features;
@@ -3779,30 +4549,28 @@ static int
rb_provided(feature)
char *feature;
{
- struct RArray *features = RARRAY(rb_features);
VALUE *p, *pend;
char *f;
int len;
- p = features->ptr;
- pend = p + features->len;
+ p = RARRAY(rb_features)->ptr;
+ pend = p + RARRAY(rb_features)->len;
while (p < pend) {
- Check_Type(*p, T_STRING);
- f = RSTRING(*p)->ptr;
- if (strcmp(f, feature) == 0) return TRUE;
+ f = STR2CSTR(*p);
+ if (strcmp(f, feature) == 0) return Qtrue;
len = strlen(feature);
if (strncmp(f, feature, len) == 0
- && (strcmp(f+len, ".rb") == 0 ||strcmp(f+len, ".o") == 0)) {
- return TRUE;
+ && (strcmp(f+len, ".rb") == 0 ||strcmp(f+len, ".so") == 0)) {
+ return Qtrue;
}
p++;
}
- return FALSE;
+ return Qfalse;
}
-#ifdef THREAD
-static int thread_loading();
-static void thread_loading_done();
+#ifdef USE_THREAD
+static int rb_thread_loading _((char*));
+static void rb_thread_loading_done _((void));
#endif
void
@@ -3813,27 +4581,28 @@ rb_provide(feature)
if (!rb_provided(feature)) {
ext = strrchr(feature, '.');
- if (strcmp(DLEXT, ext) == 0) {
- buf = ALLOCA_N(char, strlen(feature)+1);
+ if (ext && strcmp(DLEXT, ext) == 0) {
+ buf = ALLOCA_N(char, strlen(feature)+4);
strcpy(buf, feature);
ext = strrchr(buf, '.');
- strcpy(ext, ".o");
+ strcpy(ext, ".so");
feature = buf;
}
- ary_push(rb_features, str_new2(feature));
+ rb_ary_push(rb_features, rb_str_new2(feature));
}
}
VALUE
-f_require(obj, fname)
+rb_f_require(obj, fname)
VALUE obj, fname;
{
char *ext, *file, *feature, *buf; /* OK */
- VALUE load;
+ volatile VALUE load;
+ rb_secure(4);
Check_SafeStr(fname);
if (rb_provided(RSTRING(fname)->ptr))
- return FALSE;
+ return Qfalse;
ext = strrchr(RSTRING(fname)->ptr, '.');
if (ext) {
@@ -3842,15 +4611,16 @@ f_require(obj, fname)
file = find_file(file);
if (file) goto rb_load;
}
- else if (strcmp(".o", ext) == 0) {
+ else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) {
file = feature = RSTRING(fname)->ptr;
- if (strcmp(".o", DLEXT) != 0) {
+ if (strcmp(ext, DLEXT) != 0) {
buf = ALLOCA_N(char, strlen(file)+sizeof(DLEXT)+1);
strcpy(buf, feature);
ext = strrchr(buf, '.');
strcpy(ext, DLEXT);
- file = find_file(buf);
+ file = feature = buf;
}
+ file = find_file(file);
if (file) goto dyna_load;
}
else if (strcmp(DLEXT, ext) == 0) {
@@ -3860,60 +4630,63 @@ f_require(obj, fname)
}
}
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
- sprintf(buf, "%s.rb", RSTRING(fname)->ptr);
+ strcpy(buf, RSTRING(fname)->ptr);
+ strcat(buf, ".rb");
file = find_file(buf);
if (file) {
- fname = str_new2(file);
+ fname = rb_str_new2(file);
feature = buf;
goto rb_load;
}
- sprintf(buf, "%s%s", RSTRING(fname)->ptr, DLEXT);
+ strcpy(buf, RSTRING(fname)->ptr);
+ strcat(buf, DLEXT);
file = find_file(buf);
if (file) {
feature = buf;
goto dyna_load;
}
- LoadError("No such file to load -- %s", RSTRING(fname)->ptr);
+ rb_raise(rb_eLoadError, "No such file to load -- %s",
+ RSTRING(fname)->ptr);
dyna_load:
-#ifdef THREAD
- if (thread_loading(feature)) return FALSE;
+#ifdef USE_THREAD
+ if (rb_thread_loading(feature)) return Qfalse;
else {
int state;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
#endif
- load = str_new2(file);
+ load = rb_str_new2(file);
file = RSTRING(load)->ptr;
dln_load(file);
rb_provide(feature);
-#ifdef THREAD
+#ifdef USE_THREAD
}
POP_TAG();
- thread_loading_done();
+ rb_thread_loading_done();
if (state) JUMP_TAG(state);
}
#endif
- return TRUE;
+ return Qtrue;
rb_load:
-#ifdef THREAD
- if (thread_loading(feature)) return FALSE;
+#ifdef USE_THREAD
+ if (rb_thread_loading(feature)) return Qfalse;
else {
int state;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
#endif
- f_load(obj, fname);
+ rb_load(fname, 0);
rb_provide(feature);
-#ifdef THREAD
+#ifdef USE_THREAD
}
POP_TAG();
- thread_loading_done();
+ rb_thread_loading_done();
if (state) JUMP_TAG(state);
}
#endif
- return TRUE;
+ return Qtrue;
}
static void
@@ -3921,7 +4694,7 @@ set_method_visibility(self, argc, argv, ex)
VALUE self;
int argc;
VALUE *argv;
- int ex;
+ ID ex;
{
int i;
@@ -3931,13 +4704,13 @@ set_method_visibility(self, argc, argv, ex)
}
static VALUE
-mod_public(argc, argv, module)
+rb_mod_public(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
if (argc == 0) {
- FL_UNSET(the_scope, SCOPE_PRIVATE);
+ SCOPE_SET(SCOPE_PUBLIC);
}
else {
set_method_visibility(module, argc, argv, NOEX_PUBLIC);
@@ -3946,13 +4719,28 @@ mod_public(argc, argv, module)
}
static VALUE
-mod_private(argc, argv, module)
+rb_mod_protected(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
if (argc == 0) {
- FL_SET(the_scope, SCOPE_PRIVATE);
+ SCOPE_SET(SCOPE_PROTECTED);
+ }
+ else {
+ set_method_visibility(module, argc, argv, NOEX_PROTECTED);
+ }
+ return module;
+}
+
+static VALUE
+rb_mod_private(argc, argv, module)
+ int argc;
+ VALUE *argv;
+ VALUE module;
+{
+ if (argc == 0) {
+ SCOPE_SET(SCOPE_PRIVATE);
}
else {
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
@@ -3961,7 +4749,7 @@ mod_private(argc, argv, module)
}
static VALUE
-mod_public_method(argc, argv, obj)
+rb_mod_public_method(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -3971,7 +4759,7 @@ mod_public_method(argc, argv, obj)
}
static VALUE
-mod_private_method(argc, argv, obj)
+rb_mod_private_method(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -3985,7 +4773,7 @@ top_public(argc, argv)
int argc;
VALUE *argv;
{
- return mod_public(argc, argv, cObject);
+ return rb_mod_public(argc, argv, rb_cObject);
}
static VALUE
@@ -3993,11 +4781,11 @@ top_private(argc, argv)
int argc;
VALUE *argv;
{
- return mod_private(argc, argv, cObject);
+ return rb_mod_private(argc, argv, rb_cObject);
}
static VALUE
-mod_modfunc(argc, argv, module)
+rb_mod_modfunc(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
@@ -4006,22 +4794,27 @@ mod_modfunc(argc, argv, module)
ID id;
NODE *body;
- rb_clear_cache();
+ if (argc == 0) {
+ SCOPE_SET(SCOPE_MODFUNC);
+ return module;
+ }
+
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
for (i=0; i<argc; i++) {
id = rb_to_id(argv[i]);
body = search_method(module, id, 0);
if (body == 0 || body->nd_body == 0) {
- NameError("undefined method `%s' for module `%s'",
- rb_id2name(id), rb_class2name(module));
+ rb_raise(rb_eNameError, "undefined method `%s' for module `%s'",
+ rb_id2name(id), rb_class2name(module));
}
+ rb_clear_cache_by_id(id);
rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
}
return module;
}
static VALUE
-mod_append_features(module, include)
+rb_mod_append_features(module, include)
VALUE module, include;
{
switch (TYPE(include)) {
@@ -4038,7 +4831,7 @@ mod_append_features(module, include)
}
static VALUE
-mod_include(argc, argv, module)
+rb_mod_include(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
@@ -4052,21 +4845,29 @@ mod_include(argc, argv, module)
return module;
}
+void
+rb_obj_call_init(obj)
+ VALUE obj;
+{
+ PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
+ rb_funcall2(obj, init, ruby_frame->argc, ruby_frame->argv);
+ POP_ITER();
+}
+
VALUE
-class_new_instance(argc, argv, class)
+rb_class_new_instance(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
VALUE obj;
- if (FL_TEST(class, FL_SINGLETON)) {
- TypeError("can't create instance of virtual class");
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "can't create instance of virtual class");
}
- obj = obj_alloc(class);
- PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
- rb_funcall2(obj, init, argc, argv);
- POP_ITER();
+ obj = rb_obj_alloc(klass);
+ rb_obj_call_init(obj);
+
return obj;
}
@@ -4076,7 +4877,7 @@ top_include(argc, argv)
VALUE *argv;
{
rb_secure(4);
- return mod_include(argc, argv, cObject);
+ return rb_mod_include(argc, argv, rb_cObject);
}
void
@@ -4087,7 +4888,7 @@ rb_extend_object(obj, module)
}
static VALUE
-mod_extend_object(mod, obj)
+rb_mod_extend_object(mod, obj)
VALUE mod, obj;
{
rb_extend_object(obj, mod);
@@ -4095,7 +4896,7 @@ mod_extend_object(mod, obj)
}
static VALUE
-obj_extend(argc, argv, obj)
+rb_obj_extend(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -4109,10 +4910,27 @@ obj_extend(argc, argv, obj)
return obj;
}
-VALUE f_trace_var();
-VALUE f_untrace_var();
+VALUE rb_f_trace_var();
+VALUE rb_f_untrace_var();
-extern void rb_str_setter();
+static void
+errinfo_setter(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ if (!rb_obj_is_kind_of(val, rb_eException)) {
+ rb_raise(rb_eTypeError, "assigning non-exception to $!");
+ }
+ *var = val;
+}
+
+static VALUE
+errat_getter(id)
+ ID id;
+{
+ return get_backtrace(rb_errinfo);
+}
static void
errat_setter(val, id, var)
@@ -4120,18 +4938,52 @@ errat_setter(val, id, var)
ID id;
VALUE *var;
{
- *var = check_errat(val);
+ if (NIL_P(rb_errinfo)) {
+ rb_raise(rb_eArgError, "$! not set");
+ }
+ set_backtrace(rb_errinfo, val);
+}
+
+VALUE rb_f_global_variables();
+VALUE f_instance_variables();
+
+static VALUE
+rb_f_local_variables()
+{
+ ID *tbl;
+ int n, i;
+ VALUE ary = rb_ary_new();
+ struct RVarmap *vars;
+
+ tbl = ruby_scope->local_tbl;
+ if (tbl) {
+ n = *tbl++;
+ for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */
+ if (tbl[i] == 0) continue; /* skip flip states */
+ rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i])));
+ }
+ }
+
+ vars = ruby_dyna_vars;
+ while (vars) {
+ if (vars->id) {
+ rb_ary_push(ary, rb_str_new2(rb_id2name(vars->id)));
+ }
+ vars = vars->next;
+ }
+
+ return ary;
}
-VALUE f_global_variables();
-static VALUE f_catch();
-static VALUE f_throw();
+static VALUE rb_f_catch _((VALUE,VALUE));
+static VALUE rb_f_throw _((int,VALUE*)) NORETURN;
struct end_proc_data {
void (*func)();
VALUE data;
struct end_proc_data *next;
-} *end_proc_data;
+};
+static struct end_proc_data *end_proc_data;
void
rb_set_end_proc(func, data)
@@ -4155,19 +5007,20 @@ call_end_proc(data)
}
static void
-f_END()
+rb_f_END()
{
PUSH_FRAME();
- rb_set_end_proc(call_end_proc, f_lambda());
+ ruby_frame->argc = 0;
+ rb_set_end_proc(call_end_proc, rb_f_lambda());
POP_FRAME();
}
static VALUE
-f_at_exit()
+rb_f_at_exit()
{
VALUE proc;
- proc = f_lambda();
+ proc = rb_f_lambda();
rb_set_end_proc(call_end_proc, proc);
return proc;
@@ -4196,85 +5049,91 @@ Init_eval()
match = rb_intern("=~");
rb_global_variable((VALUE*)&top_scope);
- rb_global_variable((VALUE*)&eval_tree0);
- rb_global_variable((VALUE*)&eval_tree);
- rb_global_variable((VALUE*)&the_dyna_vars);
+ rb_global_variable((VALUE*)&ruby_eval_tree_begin);
+
+ rb_global_variable((VALUE*)&ruby_eval_tree);
+ rb_global_variable((VALUE*)&ruby_dyna_vars);
- rb_define_hooked_variable("$@", &errat, 0, errat_setter);
- rb_define_hooked_variable("$!", &errinfo, 0, rb_str_setter);
+ rb_define_virtual_variable("$@", errat_getter, errat_setter);
+ rb_define_hooked_variable("$!", &rb_errinfo, 0, errinfo_setter);
- rb_define_global_function("eval", f_eval, -1);
- rb_define_global_function("iterator?", f_iterator_p, 0);
- rb_define_global_function("method_missing", f_missing, -1);
- rb_define_global_function("loop", f_loop, 0);
+ rb_define_global_function("eval", rb_f_eval, -1);
+ rb_define_global_function("iterator?", rb_f_iterator_p, 0);
+ rb_define_global_function("method_missing", rb_f_missing, -1);
+ rb_define_global_function("loop", rb_f_loop, 0);
- rb_define_method(mKernel, "respond_to?", obj_respond_to, -1);
+ rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
- rb_define_global_function("raise", f_raise, -1);
- rb_define_alias(mKernel, "fail", "raise");
+ rb_define_global_function("raise", rb_f_raise, -1);
+ rb_define_global_function("fail", rb_f_raise, -1);
- rb_define_global_function("caller", f_caller, -1);
+ rb_define_global_function("caller", rb_f_caller, -1);
- rb_define_global_function("exit", f_exit, -1);
- rb_define_global_function("abort", f_abort, 0);
+ rb_define_global_function("exit", rb_f_exit, -1);
+ rb_define_global_function("abort", rb_f_abort, 0);
- rb_define_global_function("at_exit", f_at_exit, 0);
+ rb_define_global_function("at_exit", rb_f_at_exit, 0);
- rb_define_global_function("catch", f_catch, 1);
- rb_define_global_function("throw", f_throw, -1);
- rb_define_global_function("global_variables", f_global_variables, 0);
+ rb_define_global_function("catch", rb_f_catch, 1);
+ rb_define_global_function("throw", rb_f_throw, -1);
+ rb_define_global_function("global_variables", rb_f_global_variables, 0);
+ rb_define_global_function("local_variables", rb_f_local_variables, 0);
- rb_define_method(mKernel, "send", f_send, -1);
- rb_define_method(mKernel, "instance_eval", obj_instance_eval, 1);
+ rb_define_method(rb_mKernel, "send", rb_f_send, -1);
+ rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
+ rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
- rb_define_private_method(cModule, "append_features", mod_append_features, 1);
- rb_define_private_method(cModule, "extend_object", mod_extend_object, 1);
- rb_define_private_method(cModule, "include", mod_include, -1);
- rb_define_private_method(cModule, "public", mod_public, -1);
- rb_define_private_method(cModule, "private", mod_private, -1);
- rb_define_private_method(cModule, "module_function", mod_modfunc, -1);
- rb_define_method(cModule, "method_defined?", mod_method_defined, 1);
- rb_define_method(cModule, "public_class_method", mod_public_method, -1);
- rb_define_method(cModule, "private_class_method", mod_private_method, -1);
- rb_define_method(cModule, "module_eval", mod_module_eval, 1);
+ rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
+ rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
+ rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
+ rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
+ rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
+ rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
+ rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
+ rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
+ rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
+ rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
+ rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
- rb_define_method(cModule, "remove_method", mod_remove_method, -1);
- rb_define_method(cModule, "undef_method", mod_undef_method, 1);
- rb_define_method(cModule, "alias_method", mod_alias_method, 2);
+ rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, 1);
+ rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, 1);
+ rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
- rb_define_singleton_method(cModule, "nesting", mod_nesting, 0);
- rb_define_singleton_method(cModule, "constants", mod_s_constants, 0);
+ rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
+ rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
- rb_define_singleton_method(TopSelf, "include", top_include, -1);
- rb_define_singleton_method(TopSelf, "public", top_public, -1);
- rb_define_singleton_method(TopSelf, "private", top_private, -1);
+ rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
+ rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
+ rb_define_singleton_method(ruby_top_self, "private", top_private, -1);
- rb_define_method(mKernel, "extend", obj_extend, -1);
+ rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
- rb_define_global_function("trace_var", f_trace_var, -1);
- rb_define_global_function("untrace_var", f_untrace_var, -1);
+ rb_define_global_function("trace_var", rb_f_trace_var, -1);
+ rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
rb_define_global_function("set_trace_func", set_trace_func, 1);
rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
}
-VALUE f_autoload();
+VALUE rb_f_autoload();
void
Init_load()
{
- rb_load_path = ary_new();
+ rb_load_path = rb_ary_new();
rb_define_readonly_variable("$:", &rb_load_path);
rb_define_readonly_variable("$-I", &rb_load_path);
rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
- rb_features = ary_new();
+ rb_features = rb_ary_new();
rb_define_readonly_variable("$\"", &rb_features);
- rb_define_global_function("load", f_load, 1);
- rb_define_global_function("require", f_require, 1);
- rb_define_global_function("autoload", f_autoload, 2);
+ rb_define_global_function("load", rb_f_load, -1);
+ rb_define_global_function("require", rb_f_require, 1);
+ rb_define_global_function("autoload", rb_f_autoload, 2);
+ rb_global_variable(&ruby_wrapper);
}
static void
@@ -4303,36 +5162,99 @@ static void
blk_mark(data)
struct BLOCK *data;
{
- gc_mark_frame(&data->frame);
- gc_mark(data->scope);
- gc_mark(data->var);
- gc_mark(data->body);
- gc_mark(data->self);
- gc_mark(data->d_vars);
+ while (data) {
+ rb_gc_mark_frame(&data->frame);
+ rb_gc_mark(data->scope);
+ rb_gc_mark(data->var);
+ rb_gc_mark(data->body);
+ rb_gc_mark(data->self);
+ rb_gc_mark(data->d_vars);
+ rb_gc_mark(data->klass);
+ data = data->prev;
+ }
}
static void
blk_free(data)
struct BLOCK *data;
{
- free(data->frame.argv);
+ struct BLOCK *tmp;
+
+ while (data) {
+ free(data->frame.argv);
+ tmp = data;
+ data = data->prev;
+ free(tmp);
+ }
+}
+
+static void
+blk_copy_prev(block)
+ struct BLOCK *block;
+{
+ struct BLOCK *tmp;
+
+ while (block->prev) {
+ tmp = ALLOC_N(struct BLOCK, 1);
+ MEMCPY(tmp, block->prev, struct BLOCK, 1);
+ tmp->frame.argv = ALLOC_N(VALUE, tmp->frame.argc);
+ MEMCPY(tmp->frame.argv, block->frame.argv, VALUE, tmp->frame.argc);
+ block->prev = tmp;
+ block = tmp;
+ }
+}
+
+
+static VALUE
+bind_clone(self)
+ VALUE self;
+{
+ struct BLOCK *orig, *data;
+ VALUE bind;
+
+ Data_Get_Struct(self, struct BLOCK, orig);
+ bind = Data_Make_Struct(self,struct BLOCK,blk_mark,blk_free,data);
+ MEMCPY(data, orig, struct BLOCK, 1);
+ data->frame.argv = ALLOC_N(VALUE, orig->frame.argc);
+ MEMCPY(data->frame.argv, orig->frame.argv, VALUE, orig->frame.argc);
+
+ if (data->iter) {
+ blk_copy_prev(data);
+ }
+ else {
+ data->prev = 0;
+ }
+
+ return bind;
}
static VALUE
-f_binding(self)
+rb_f_binding(self)
VALUE self;
{
struct BLOCK *data;
VALUE bind;
PUSH_BLOCK(0,0);
- bind = Data_Make_Struct(cData, struct BLOCK, blk_mark, blk_free, data);
- MEMCPY(data, the_block, struct BLOCK, 1);
+ bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
+ *data = *ruby_block;
- data->iter = f_iterator_p();
- data->frame.last_func = 0;
+#ifdef USE_THREAD
+ data->orig_thread = rb_thread_current();
+#endif
+ data->iter = rb_f_iterator_p();
+ if (ruby_frame->prev) {
+ data->frame.last_func = ruby_frame->prev->last_func;
+ }
data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
+ MEMCPY(data->frame.argv, ruby_block->frame.argv, VALUE, data->frame.argc);
+
+ if (data->iter) {
+ blk_copy_prev(data);
+ }
+ else {
+ data->prev = 0;
+ }
scope_dup(data->scope);
POP_BLOCK();
@@ -4340,62 +5262,110 @@ f_binding(self)
return bind;
}
-#define PROC_TAINT FL_USER0
#define PROC_T3 FL_USER1
#define PROC_T4 FL_USER2
#define PROC_T5 (FL_USER1|FL_USER2)
#define PROC_TMASK (FL_USER1|FL_USER2)
+static void
+proc_save_safe_level(data)
+ VALUE data;
+{
+ if (FL_TEST(data, FL_TAINT)) {
+ switch (safe_level) {
+ case 3:
+ FL_SET(data, PROC_T3);
+ break;
+ case 4:
+ FL_SET(data, PROC_T4);
+ break;
+ case 5:
+ FL_SET(data, PROC_T5);
+ break;
+ }
+ }
+}
+
+static void
+proc_set_safe_level(data)
+ VALUE data;
+{
+ if (FL_TEST(data, FL_TAINT)) {
+ switch (RBASIC(data)->flags & PROC_TMASK) {
+ case PROC_T3:
+ safe_level = 3;
+ break;
+ case PROC_T4:
+ safe_level = 4;
+ break;
+ case PROC_T5:
+ safe_level = 5;
+ break;
+ }
+ }
+}
+
static VALUE
-proc_s_new(class)
- VALUE class;
+proc_s_new(klass)
+ VALUE klass;
{
volatile VALUE proc;
struct BLOCK *data;
- if (!iterator_p() && !f_iterator_p()) {
- ArgError("tryed to create Procedure-Object out of iterator");
+ if (!rb_iterator_p() && !rb_f_iterator_p()) {
+ rb_raise(rb_eArgError, "tried to create Procedure-Object out of iterator");
}
- proc = Data_Make_Struct(class, struct BLOCK, blk_mark, blk_free, data);
- *data = *the_block;
+ proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
+ *data = *ruby_block;
-#ifdef THREAD
- data->orig_thread = thread_current();
+#ifdef USE_THREAD
+ data->orig_thread = rb_thread_current();
#endif
- data->iter = f_iterator_p();
+ data->iter = data->prev?Qtrue:Qfalse;
data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
+ MEMCPY(data->frame.argv, ruby_block->frame.argv, VALUE, data->frame.argc);
+ if (data->iter) {
+ blk_copy_prev(data);
+ }
+ else {
+ data->prev = 0;
+ }
scope_dup(data->scope);
- if (safe_level >= 3) {
- FL_SET(proc, PROC_TAINT);
- switch (safe_level) {
- case 3:
- FL_SET(proc, PROC_T3);
- break;
- case 4:
- FL_SET(proc, PROC_T4);
- break;
- case 5:
- FL_SET(proc, PROC_T5);
- break;
- }
- }
+ proc_save_safe_level(proc);
+ rb_obj_call_init(proc);
return proc;
}
VALUE
-f_lambda()
+rb_f_lambda()
+{
+ return proc_s_new(rb_cProc);
+}
+
+static int
+blk_orphan(data)
+ struct BLOCK *data;
{
- return proc_s_new(cProc);
+ if (data->scope && data->scope != top_scope &&
+ (data->scope->flag & SCOPE_NOSTACK)) {
+ return 1;
+ }
+#ifdef USE_THREAD
+ if (data->orig_thread != rb_thread_current()) {
+ return 1;
+ }
+#endif
+ return 0;
}
static VALUE
proc_call(proc, args)
VALUE proc, args; /* OK */
{
+ struct BLOCK * volatile old_block;
struct BLOCK *data;
volatile VALUE result = Qnil;
int state;
@@ -4414,71 +5384,116 @@ proc_call(proc, args)
}
Data_Get_Struct(proc, struct BLOCK, data);
+ orphan = blk_orphan(data);
+
+ /* PUSH BLOCK from data */
+ old_block = ruby_block;
+ ruby_block = data;
+ PUSH_ITER(ITER_CUR);
+ ruby_frame->iter = ITER_CUR;
- if (data->scope && (data->scope->flag & SCOPE_NOSTACK)) {
- orphan = 1;
- }
- else {
-#ifdef THREAD
- if (data->orig_thread != thread_current()) {
- orphan = 1;
- }
- else
-#endif
- orphan = 0;
- }
if (orphan) {/* orphan procedure */
- if (iterator_p()) {
- data->frame.iter = ITER_CUR;
+ if (rb_iterator_p()) {
+ ruby_block->frame.iter = ITER_CUR;
}
else {
- data->frame.iter = ITER_NOT;
+ ruby_block->frame.iter = ITER_NOT;
}
}
- /* PUSH BLOCK from data */
- PUSH_BLOCK2(data);
- PUSH_ITER(ITER_CUR);
- the_frame->iter = ITER_CUR;
- if (FL_TEST(proc, PROC_TAINT)) {
- switch (RBASIC(proc)->flags & PROC_TMASK) {
- case PROC_T3:
- safe_level = 3;
- break;
- case PROC_T4:
- safe_level = 4;
- break;
- case PROC_T5:
- safe_level = 5;
- break;
+ PUSH_TAG(PROT_NONE);
+ state = EXEC_TAG();
+ if (state == 0) {
+ proc_set_safe_level(proc);
+ result = rb_yield_0(args, 0, 0);
+ }
+ POP_TAG();
+
+ POP_ITER();
+ if (ruby_block->tag->dst == state) {
+ state &= TAG_MASK;
+ }
+ ruby_block = old_block;
+ safe_level = safe;
+
+ if (state) {
+ if (orphan) {/* orphan procedure */
+ switch (state) {
+ case TAG_BREAK:
+ rb_raise(rb_eLocalJumpError, "break from proc-closure");
+ break;
+ case TAG_RETRY:
+ rb_raise(rb_eLocalJumpError, "retry from proc-closure");
+ break;
+ case TAG_RETURN:
+ rb_raise(rb_eLocalJumpError, "return from proc-closure");
+ break;
+ }
}
+ JUMP_TAG(state);
+ }
+ return result;
+}
+
+static VALUE
+block_pass(self, node)
+ VALUE self;
+ NODE *node;
+{
+ VALUE block = rb_eval(self, node->nd_body);
+ struct BLOCK * volatile old_block;
+ struct BLOCK *data;
+ volatile VALUE result = Qnil;
+ int state;
+ volatile int orphan;
+ volatile int safe = safe_level;
+
+ if (NIL_P(block)) {
+ return rb_eval(self, node->nd_iter);
+ }
+ if (rb_obj_is_kind_of(block, rb_cMethod)) {
+ block = method_proc(block);
+ }
+ else if (!rb_obj_is_proc(block)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)",
+ rb_class2name(CLASS_OF(block)));
}
+ Data_Get_Struct(block, struct BLOCK, data);
+ orphan = blk_orphan(data);
+
+ /* PUSH BLOCK from data */
+ old_block = ruby_block;
+ ruby_block = data;
+ PUSH_ITER(ITER_PRE);
+ ruby_frame->iter = ITER_PRE;
+
PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
- result = rb_yield(args);
+ proc_set_safe_level(block);
+ result = rb_eval(self, node->nd_iter);
}
POP_TAG();
-
POP_ITER();
- if (the_block->tag->dst == state) {
+ if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
+ orphan = 2;
}
- POP_BLOCK();
+ ruby_block = old_block;
safe_level = safe;
if (state) {
- if (orphan) {/* orphan procedure */
+ if (orphan == 2) {/* escape from orphan procedure */
switch (state) {
case TAG_BREAK:
- Raise(eLocalJumpError, "break from proc-closure");
+ rb_raise(rb_eLocalJumpError, "break from proc-closure");
break;
case TAG_RETRY:
- Raise(eLocalJumpError, "retry from proc-closure");
+ rb_raise(rb_eLocalJumpError, "retry from proc-closure");
break;
case TAG_RETURN:
- Raise(eLocalJumpError, "return from proc-closure");
+ rb_raise(rb_eLocalJumpError, "return from proc-closure");
break;
}
}
@@ -4487,27 +5502,180 @@ proc_call(proc, args)
return result;
}
+struct METHOD {
+ VALUE klass, oklass;
+ VALUE recv;
+ ID id, oid;
+ NODE *body;
+};
+
+static void
+bm_mark(data)
+ struct METHOD *data;
+{
+ rb_gc_mark(data->oklass);
+ rb_gc_mark(data->klass);
+ rb_gc_mark(data->recv);
+ rb_gc_mark(data->body);
+}
+
+static VALUE
+rb_obj_method(obj, vid)
+ VALUE obj;
+ VALUE vid;
+{
+ VALUE method;
+ VALUE klass = CLASS_OF(obj);
+ ID id;
+ NODE *body;
+ int noex;
+ struct METHOD *data;
+
+ id = rb_to_id(vid);
+
+ again:
+ if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ return rb_undefined(obj, rb_to_id(vid), 0, 0, 0);
+ }
+
+ if (nd_type(body) == NODE_ZSUPER) {
+ klass = RCLASS(klass)->super;
+ goto again;
+ }
+
+ method = Data_Make_Struct(rb_cMethod, struct METHOD, bm_mark, free, data);
+ data->klass = klass;
+ data->recv = obj;
+ data->id = id;
+ data->body = body;
+ data->oklass = CLASS_OF(obj);
+ data->oid = rb_to_id(vid);
+ if (FL_TEST(obj, FL_TAINT)) {
+ FL_SET(method, FL_TAINT);
+ }
+
+ return method;
+}
+
+static VALUE
+method_call(argc, argv, method)
+ int argc;
+ VALUE *argv;
+ VALUE method;
+{
+ VALUE result;
+ struct METHOD *data;
+ int state;
+ volatile int safe = safe_level;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
+ PUSH_TAG(PROT_NONE);
+ if (FL_TEST(data->recv, FL_TAINT) || FL_TEST(method, FL_TAINT)) {
+ FL_SET(method, FL_TAINT);
+ if (safe_level < 4) safe_level = 4;
+ }
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_call0(data->klass, data->recv, data->id,
+ argc, argv, data->body, 0);
+ }
+ POP_TAG();
+ POP_ITER();
+ safe_level = safe;
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+static VALUE
+method_inspect(method)
+ VALUE method;
+{
+ struct METHOD *data;
+ VALUE str;
+ char *s;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ str = rb_str_new2("#<");
+ s = rb_class2name(CLASS_OF(method));
+ rb_str_cat(str, s, strlen(s));
+ rb_str_cat(str, ": ", 2);
+ s = rb_class2name(data->oklass);
+ rb_str_cat(str, s, strlen(s));
+ rb_str_cat(str, "#", 1);
+ s = rb_id2name(data->oid);
+ rb_str_cat(str, s, strlen(s));
+ rb_str_cat(str, ">", 1);
+
+ return str;
+}
+
+static VALUE
+mproc()
+{
+ VALUE proc;
+
+ /* emulate ruby's method call */
+ PUSH_ITER(ITER_CUR);
+ PUSH_FRAME();
+ proc = rb_f_lambda();
+ POP_FRAME();
+ POP_ITER();
+
+ return proc;
+}
+
+static VALUE
+mcall(args, method)
+ VALUE args, method;
+{
+ if (TYPE(args) == T_ARRAY) {
+ return method_call(RARRAY(args)->len, RARRAY(args)->ptr, method);
+ }
+ return method_call(1, &args, method);
+}
+
+static VALUE
+method_proc(method)
+ VALUE method;
+{
+ return rb_iterate(mproc, 0, mcall, method);
+}
+
void
Init_Proc()
{
- eLocalJumpError = rb_define_class("LocalJumpError", eException);
+ rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
+ rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError);
- cProc = rb_define_class("Proc", cObject);
- rb_define_singleton_method(cProc, "new", proc_s_new, 0);
+ rb_cProc = rb_define_class("Proc", rb_cObject);
+ rb_define_singleton_method(rb_cProc, "new", proc_s_new, 0);
- rb_define_method(cProc, "call", proc_call, -2);
- rb_define_global_function("proc", f_lambda, 0);
- rb_define_global_function("lambda", f_lambda, 0);
- rb_define_global_function("binding", f_binding, 0);
+ rb_define_method(rb_cProc, "call", proc_call, -2);
+ rb_define_method(rb_cProc, "[]", proc_call, -2);
+ rb_define_global_function("proc", rb_f_lambda, 0);
+ rb_define_global_function("lambda", rb_f_lambda, 0);
+ rb_define_global_function("binding", rb_f_binding, 0);
+ rb_cBinding = rb_define_class("Binding", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cMethod), "new");
+ rb_define_method(rb_cBinding, "clone", bind_clone, 0);
+
+ rb_cMethod = rb_define_class("Method", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cMethod), "new");
+ rb_define_method(rb_cMethod, "call", method_call, -1);
+ rb_define_method(rb_cMethod, "[]", method_call, -1);
+ rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
+ rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
+ rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
+ rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
}
-#ifdef THREAD
+#ifdef USE_THREAD
-static VALUE eThreadError;
+static VALUE rb_eThreadError;
-int thread_pending = 0;
+int rb_thread_pending = 0;
-static VALUE cThread;
+VALUE rb_cThread;
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
@@ -4527,7 +5695,7 @@ struct timeval {
#include <sys/select.h>
#endif
-extern VALUE last_status;
+extern VALUE rb_last_status;
enum thread_status {
THREAD_RUNNABLE,
@@ -4560,23 +5728,26 @@ struct thread {
struct SCOPE *scope;
struct RVarmap *dyna_vars;
struct BLOCK *block;
+ struct BLOCK *cblock;
struct iter *iter;
struct tag *tag;
- VALUE class;
+ VALUE klass;
+ VALUE wrapper;
VALUE trace;
+ int misc; /* misc. states (vmode/rb_trap_immediate) */
char *file;
int line;
- VALUE errat, errinfo;
+ VALUE rb_errinfo;
VALUE last_status;
VALUE last_line;
VALUE last_match;
int safe;
- enum thread_status status;
+ enum thread_status status;
int wait_for;
int fd;
double delay;
@@ -4584,6 +5755,8 @@ struct thread {
int abort;
+ st_table *locals;
+
VALUE thread;
};
@@ -4619,29 +5792,33 @@ thread_mark(th)
struct FRAME *frame;
struct BLOCK *block;
- gc_mark(th->result);
+ rb_gc_mark(th->result);
+ rb_gc_mark(th->thread);
+ if (th->join) rb_gc_mark(th->join->thread);
+
+ rb_gc_mark(th->klass);
+ rb_gc_mark(th->wrapper);
+
+ rb_gc_mark(th->scope);
+ rb_gc_mark(th->dyna_vars);
+ rb_gc_mark(th->rb_errinfo);
+ rb_gc_mark(th->last_line);
+ rb_gc_mark(th->last_match);
+
+ /* mark data in copied stack */
+ if (th->status == THREAD_KILLED) return;
+ if (th->stk_len == 0) return; /* stack not active, no need to mark. */
if (th->stk_ptr) {
- gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
+ rb_gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
#if defined(THINK_C) || defined(__human68k__)
- gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
+ rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
#endif
}
- gc_mark(th->thread);
- if (th->join) gc_mark(th->join->thread);
-
- gc_mark(th->scope);
- gc_mark(th->dyna_vars);
- gc_mark(th->errat);
- gc_mark(th->errinfo);
- gc_mark(th->last_line);
- gc_mark(th->last_match);
-
- /* mark data in copied stack */
frame = th->frame;
while (frame && frame != top_frame) {
frame = ADJ(frame);
if (frame->argv && !STACK(frame->argv)) {
- gc_mark_frame(frame);
+ rb_gc_mark_frame(frame);
}
frame = frame->prev;
}
@@ -4649,19 +5826,21 @@ thread_mark(th)
while (block) {
block = ADJ(block);
if (block->frame.argv && !STACK(block->frame.argv)) {
- gc_mark_frame(&block->frame);
+ rb_gc_mark_frame(&block->frame);
}
block = block->prev;
}
+ rb_mark_tbl(th->locals);
}
void
-gc_mark_threads()
+rb_gc_mark_threads()
{
thread_t th;
+ if (!curr_thread) return;
FOREACH_THREAD(th) {
- thread_mark(th);
+ rb_gc_mark(th->thread);
} END_FOREACH(th);
}
@@ -4671,60 +5850,63 @@ thread_free(th)
{
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
+ if (th->locals) st_free_table(th->locals);
+ if (th != main_thread) free(th);
}
static thread_t
-thread_check(data)
+rb_thread_check(data)
VALUE data;
{
if (TYPE(data) != T_DATA || RDATA(data)->dfree != thread_free) {
- TypeError("wrong argument type %s (expected Thread)",
- rb_class2name(CLASS_OF(data)));
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
+ rb_class2name(CLASS_OF(data)));
}
return (thread_t)RDATA(data)->data;
}
-VALUE lastline_get();
-void lastline_set();
-VALUE backref_get();
-void backref_set();
-
static void
-thread_save_context(th)
+rb_thread_save_context(th)
thread_t th;
{
VALUE v;
- th->stk_len = stack_length();
- th->stk_pos = (gc_stack_start<(VALUE*)&v)?gc_stack_start
- :gc_stack_start - th->stk_len;
- if (th->stk_len > th->stk_max) {
- th->stk_max = th->stk_len;
- REALLOC_N(th->stk_ptr, VALUE, th->stk_max);
- }
- FLUSH_REGISTER_WINDOWS;
+ int len = stack_length();
+ th->stk_len = 0;
+ th->stk_pos = (rb_gc_stack_start<(VALUE*)&v)?rb_gc_stack_start
+ :rb_gc_stack_start - len;
+ if (len > th->stk_max) {
+ REALLOC_N(th->stk_ptr, VALUE, len);
+ th->stk_max = len;
+ }
+ th->stk_len = len;
+ FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
- th->frame = the_frame;
- th->scope = the_scope;
- th->class = the_class;
- th->dyna_vars = the_dyna_vars;
- th->block = the_block;
- th->iter = the_iter;
+ th->frame = ruby_frame;
+ th->scope = ruby_scope;
+ th->klass = ruby_class;
+ th->wrapper = ruby_wrapper;
+ th->dyna_vars = ruby_dyna_vars;
+ th->block = ruby_block;
+ th->cblock = ruby_calling_block;
+ th->misc = scope_vmode | (rb_trap_immediate<<8);
+ th->iter = ruby_iter;
th->tag = prot_tag;
- th->errat = errat;
- th->errinfo = errinfo;
- th->last_status = last_status;
- th->last_line = lastline_get();
- th->last_match = backref_get();
+ th->rb_errinfo = rb_errinfo;
+ th->last_status = rb_last_status;
+ th->last_line = rb_lastline_get();
+ th->last_match = rb_backref_get();
th->safe = safe_level;
th->trace = trace_func;
- th->file = sourcefile;
- th->line = sourceline;
+ th->file = ruby_sourcefile;
+ th->line = ruby_sourceline;
+
+ th->locals = 0;
}
-static void thread_restore_context();
+static void rb_thread_restore_context _((thread_t,int));
static void
stack_extend(th, exit)
@@ -4734,16 +5916,18 @@ stack_extend(th, exit)
VALUE space[1024];
memset(space, 0, 1); /* prevent array from optimization */
- thread_restore_context(th, exit);
+ rb_thread_restore_context(th, exit);
}
static int th_raise_argc;
static VALUE th_raise_argv[2];
static char *th_raise_file;
static int th_raise_line;
+static VALUE th_cmd;
+static int th_sig;
static void
-thread_restore_context(th, exit)
+rb_thread_restore_context(th, exit)
thread_t th;
int exit;
{
@@ -4751,9 +5935,9 @@ thread_restore_context(th, exit)
static thread_t tmp;
static int ex;
- if (!th->stk_ptr) Bug("unsaved context");
+ if (!th->stk_ptr) rb_bug("unsaved context");
- if (&v < gc_stack_start) {
+ if (&v < rb_gc_stack_start) {
/* Stack grows downward */
if (&v > th->stk_pos) stack_extend(th, exit);
}
@@ -4762,30 +5946,32 @@ thread_restore_context(th, exit)
if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
}
- the_frame = th->frame;
- the_scope = th->scope;
- the_class = th->class;
- the_dyna_vars = th->dyna_vars;
- the_block = th->block;
- the_iter = th->iter;
+ ruby_frame = th->frame;
+ ruby_scope = th->scope;
+ ruby_class = th->klass;
+ ruby_wrapper = th->wrapper;
+ ruby_dyna_vars = th->dyna_vars;
+ ruby_block = th->block;
+ ruby_calling_block = th->cblock;
+ scope_vmode = th->misc&SCOPE_MASK;
+ rb_trap_immediate = th->misc>>8;
+ ruby_iter = th->iter;
prot_tag = th->tag;
- the_class = th->class;
- errat = th->errat;
- errinfo = th->errinfo;
- last_status = th->last_status;
+ rb_errinfo = th->rb_errinfo;
+ rb_last_status = th->last_status;
safe_level = th->safe;
trace_func = th->trace;
- sourcefile = th->file;
- sourceline = th->line;
+ ruby_sourcefile = th->file;
+ ruby_sourceline = th->line;
tmp = th;
ex = exit;
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
- lastline_set(tmp->last_line);
- backref_set(tmp->last_match);
+ rb_lastline_set(tmp->last_line);
+ rb_backref_set(tmp->last_match);
switch (ex) {
case 1:
@@ -4797,10 +5983,15 @@ thread_restore_context(th, exit)
break;
case 3:
- the_frame->last_func = 0;
- sourcefile = th_raise_file;
- sourceline = th_raise_line;
- f_raise(th_raise_argc, th_raise_argv);
+ rb_trap_eval(th_cmd, th_sig);
+ errno = EINTR;
+ break;
+
+ case 4:
+ ruby_frame->last_func = 0;
+ ruby_sourcefile = th_raise_file;
+ ruby_sourceline = th_raise_line;
+ rb_f_raise(th_raise_argc, th_raise_argv);
break;
default:
@@ -4809,7 +6000,7 @@ thread_restore_context(th, exit)
}
static void
-thread_ready(th)
+rb_thread_ready(th)
thread_t th;
{
/* The thread is no longer waiting on anything */
@@ -4827,42 +6018,41 @@ thread_ready(th)
}
static void
-thread_remove()
+rb_thread_remove()
{
- thread_ready(curr_thread);
+ rb_thread_ready(curr_thread);
curr_thread->status = THREAD_KILLED;
curr_thread->prev->next = curr_thread->next;
curr_thread->next->prev = curr_thread->prev;
- thread_schedule();
}
static int
-thread_dead(th)
+rb_thread_dead(th)
thread_t th;
{
return th->status == THREAD_KILLED;
}
static void
-thread_deadlock()
+rb_thread_deadlock()
{
curr_thread = main_thread;
th_raise_argc = 1;
- th_raise_argv[0] = exc_new2(eFatal, "Thread: deadlock");
- th_raise_file = sourcefile;
- th_raise_line = sourceline;
- f_abort();
+ th_raise_argv[0] = rb_exc_new2(rb_eFatal, "Thread: deadlock");
+ th_raise_file = ruby_sourcefile;
+ th_raise_line = ruby_sourceline;
+ rb_abort();
}
void
-thread_schedule()
+rb_thread_schedule()
{
thread_t next; /* OK */
thread_t th;
thread_t curr;
select_err:
- thread_pending = 0;
+ rb_thread_pending = 0;
if (curr_thread == curr_thread->next) return;
next = 0;
@@ -4872,17 +6062,17 @@ thread_schedule()
curr = curr->prev;
}
- FOREACH_THREAD_FROM(curr,th) {
+ FOREACH_THREAD_FROM(curr, th) {
if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) {
next = th;
break;
}
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
if (num_waiting_on_join) {
- FOREACH_THREAD_FROM(curr,th) {
- if ((th->wait_for & WAIT_JOIN) && thread_dead(th->join)) {
+ FOREACH_THREAD_FROM(curr, th) {
+ if ((th->wait_for&WAIT_JOIN) && rb_thread_dead(th->join)) {
th->join = 0;
th->wait_for &= ~WAIT_JOIN;
th->status = THREAD_RUNNABLE;
@@ -4890,7 +6080,7 @@ thread_schedule()
if (!next) next = th;
}
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
}
if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) {
@@ -4904,19 +6094,19 @@ thread_schedule()
max = 0;
FD_ZERO(&readfds);
if (num_waiting_on_fd > 0) {
- FOREACH_THREAD_FROM(curr,th) {
+ FOREACH_THREAD_FROM(curr, th) {
if (th->wait_for & WAIT_FD) {
FD_SET(th->fd, &readfds);
if (th->fd > max) max = th->fd;
}
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
}
delay = DELAY_INFTY;
if (num_waiting_on_timer > 0) {
now = timeofday();
- FOREACH_THREAD_FROM(curr,th) {
+ FOREACH_THREAD_FROM(curr, th) {
if (th->wait_for & WAIT_TIME) {
if (th->delay <= now) {
th->delay = 0.0;
@@ -4929,7 +6119,7 @@ thread_schedule()
}
}
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
}
/* Do the select if needed */
if (num_waiting_on_fd > 0 || !next) {
@@ -4946,19 +6136,19 @@ thread_schedule()
else {
delay -= now;
delay_tv.tv_sec = (unsigned int)delay;
- delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec) * 1e6;
+ delay_tv.tv_usec = (long)((delay-(double)delay_tv.tv_sec)*1e6);
delay_ptr = &delay_tv;
}
n = select(max+1, &readfds, 0, 0, delay_ptr);
if (n < 0) {
- if (trap_pending) rb_trap_exec();
+ if (rb_trap_pending) rb_trap_exec();
goto select_err;
}
if (n > 0) {
/* Some descriptors are ready.
Make the corresponding threads runnable. */
- FOREACH_THREAD_FROM(curr,th) {
+ FOREACH_THREAD_FROM(curr, th) {
if ((th->wait_for&WAIT_FD)
&& FD_ISSET(th->fd, &readfds)) {
/* Wake up only one thread per fd. */
@@ -4970,7 +6160,7 @@ thread_schedule()
if (!next) next = th; /* Found one. */
}
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
}
}
/* The delays for some of the threads should have expired.
@@ -4979,24 +6169,24 @@ thread_schedule()
}
if (!next) {
- curr_thread->file = sourcefile;
- curr_thread->line = sourceline;
- FOREACH_THREAD_FROM(curr,th) {
+ curr_thread->file = ruby_sourcefile;
+ curr_thread->line = ruby_sourceline;
+ FOREACH_THREAD_FROM(curr, th) {
fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n",
th->file, th->line, th->thread, th->status,
th->wait_for, th==main_thread?"(main)":"");
}
- END_FOREACH_FROM(curr,th);
+ END_FOREACH_FROM(curr, th);
/* raise fatal error to main thread */
- thread_deadlock();
+ rb_thread_deadlock();
}
- if (next == curr_thread) {
+ if (next->status == THREAD_RUNNABLE && next == curr_thread) {
return;
}
/* context switch */
if (curr == curr_thread) {
- thread_save_context(curr);
+ rb_thread_save_context(curr);
if (setjmp(curr->context)) {
return;
}
@@ -5005,13 +6195,13 @@ thread_schedule()
curr_thread = next;
if (next->status == THREAD_TO_KILL) {
/* execute ensure-clause if any */
- thread_restore_context(next, 1);
+ rb_thread_restore_context(next, 1);
}
- thread_restore_context(next, 0);
+ rb_thread_restore_context(next, 0);
}
void
-thread_wait_fd(fd)
+rb_thread_wait_fd(fd)
int fd;
{
if (curr_thread == curr_thread->next) return;
@@ -5020,11 +6210,11 @@ thread_wait_fd(fd)
curr_thread->fd = fd;
num_waiting_on_fd++;
curr_thread->wait_for |= WAIT_FD;
- thread_schedule();
+ rb_thread_schedule();
}
void
-thread_fd_writable(fd)
+rb_thread_fd_writable(fd)
int fd;
{
struct timeval zero;
@@ -5037,12 +6227,12 @@ thread_fd_writable(fd)
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (select(fd+1, 0, &fds, 0, &zero) == 1) break;
- thread_schedule();
+ rb_thread_schedule();
}
}
void
-thread_wait_for(time)
+rb_thread_wait_for(time)
struct timeval time;
{
double date;
@@ -5065,7 +6255,7 @@ thread_wait_for(time)
time.tv_sec = (int)d;
time.tv_usec = (int)((d - (int)d)*1e6);
if (time.tv_usec < 0) {
- time.tv_usec += 1e6;
+ time.tv_usec += (long)1e6;
time.tv_sec -= 1;
}
if (time.tv_sec < 0) return;
@@ -5078,19 +6268,19 @@ thread_wait_for(time)
curr_thread->delay = date;
num_waiting_on_timer++;
curr_thread->wait_for |= WAIT_TIME;
- thread_schedule();
+ rb_thread_schedule();
}
-void thread_sleep_forever();
+void rb_thread_sleep_forever _((void));
int
-thread_alone()
+rb_thread_alone()
{
return curr_thread == curr_thread->next;
}
int
-thread_select(max, read, write, except, timeout)
+rb_thread_select(max, read, write, except, timeout)
int max;
fd_set *read, *write, *except;
struct timeval *timeout;
@@ -5102,10 +6292,10 @@ thread_select(max, read, write, except, timeout)
if (!read && !write && !except) {
if (!timeout) {
- thread_sleep_forever();
+ rb_thread_sleep_forever();
return 0;
}
- thread_wait_for(*timeout);
+ rb_thread_wait_for(*timeout);
return 0;
}
@@ -5131,7 +6321,7 @@ thread_select(max, read, write, except, timeout)
double d = timeofday() - limit;
tv.tv_sec = (unsigned int)d;
- tv.tv_usec = (d - (double)tv.tv_sec) * 1e6;
+ tv.tv_usec = (long)((d-(double)tv.tv_sec)*1e6);
}
continue;
}
@@ -5172,124 +6362,126 @@ thread_select(max, read, write, except, timeout)
if (limit <= timeofday()) return 0;
}
- thread_schedule();
+ rb_thread_schedule();
CHECK_INTS;
}
}
static VALUE
-thread_join(dmy, thread)
- VALUE dmy;
+rb_thread_join(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) return thread;
+ if (rb_thread_dead(th)) return thread;
if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
- Raise(eThreadError, "Thread.join: deadlock");
+ rb_raise(rb_eThreadError, "Thread#join: deadlock");
curr_thread->status = THREAD_STOPPED;
curr_thread->join = th;
num_waiting_on_join++;
curr_thread->wait_for |= WAIT_JOIN;
- thread_schedule();
+ rb_thread_schedule();
return thread;
}
static VALUE
-thread_current()
+rb_thread_s_join(dmy, thread) /* will be removed in 1.4 */
+ VALUE dmy;
+ VALUE thread;
+{
+ rb_warn("Thread::join is obsolete; use Thread#join instead");
+ return rb_thread_join(thread);
+}
+
+VALUE
+rb_thread_current()
{
return curr_thread->thread;
}
-static VALUE
-thread_main()
+VALUE
+rb_thread_main()
{
return main_thread->thread;
}
static VALUE
-thread_wakeup(thread)
+rb_thread_wakeup(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- if (th->status == THREAD_KILLED) Raise(eThreadError, "killed thread");
- thread_ready(th);
+ if (th->status == THREAD_KILLED)
+ rb_raise(rb_eThreadError, "killed thread");
+ rb_thread_ready(th);
return thread;
}
static VALUE
-thread_run(thread)
+rb_thread_run(thread)
VALUE thread;
{
- thread_wakeup(thread);
- if (!thread_critical) thread_schedule();
+ rb_thread_wakeup(thread);
+ if (!rb_thread_critical) rb_thread_schedule();
return thread;
}
static VALUE
-thread_kill(thread)
+rb_thread_kill(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
return thread;
if (th == th->next || th == main_thread) rb_exit(0);
- thread_ready(th);
+ rb_thread_ready(th);
th->status = THREAD_TO_KILL;
- thread_schedule();
+ rb_thread_schedule();
return Qnil; /* not reached */
}
static VALUE
-thread_s_kill(obj, th)
+rb_thread_s_kill(obj, th)
VALUE obj, th;
{
- return thread_kill(th);
+ return rb_thread_kill(th);
}
static VALUE
-thread_exit()
+rb_thread_exit()
{
- return thread_kill(curr_thread->thread);
+ return rb_thread_kill(curr_thread->thread);
}
static VALUE
-thread_pass()
+rb_thread_pass()
{
- thread_schedule();
+ rb_thread_schedule();
return Qnil;
}
static VALUE
-thread_stop_method(thread)
- VALUE thread;
+rb_thread_stop()
{
- thread_t th = thread_check(thread);
-
- thread_critical = 0;
- th->status = THREAD_STOPPED;
- thread_schedule();
-
- return thread;
-}
+ rb_thread_critical = 0;
+ curr_thread->status = THREAD_STOPPED;
+ if (curr_thread == curr_thread->next) {
+ rb_raise(rb_eThreadError, "stopping only thread");
+ }
+ rb_thread_schedule();
-static VALUE
-thread_stop()
-{
- thread_stop_method(curr_thread->thread);
return Qnil;
}
-struct timeval time_timeval();
+struct timeval rb_time_timeval();
void
-thread_sleep(sec)
+rb_thread_sleep(sec)
int sec;
{
if (curr_thread == curr_thread->next) {
@@ -5298,15 +6490,15 @@ thread_sleep(sec)
TRAP_END;
return;
}
- thread_wait_for(time_timeval(INT2FIX(sec)));
+ rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
}
void
-thread_sleep_forever()
+rb_thread_sleep_forever()
{
if (curr_thread == curr_thread->next) {
TRAP_BEG;
- sleep((32767<<16)+32767);
+ sleep((32767L<<16)+32767);
TRAP_END;
return;
}
@@ -5315,46 +6507,47 @@ thread_sleep_forever()
curr_thread->delay = DELAY_INFTY;
curr_thread->wait_for |= WAIT_TIME;
curr_thread->status = THREAD_STOPPED;
- thread_schedule();
+ rb_thread_schedule();
}
-static int thread_abort;
+static int rb_thread_abort;
static VALUE
-thread_s_abort_exc()
+rb_thread_s_abort_exc()
{
- return thread_abort?TRUE:FALSE;
+ return rb_thread_abort?Qtrue:Qfalse;
}
static VALUE
-thread_s_abort_exc_set(self, val)
+rb_thread_s_abort_exc_set(self, val)
VALUE self, val;
{
- thread_abort = RTEST(val);
+ rb_thread_abort = RTEST(val);
return val;
}
static VALUE
-thread_abort_exc(thread)
+rb_thread_abort_exc(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- return th->abort?TRUE:FALSE;
+ return th->abort?Qtrue:Qfalse;
}
static VALUE
-thread_abort_exc_set(thread, val)
+rb_thread_abort_exc_set(thread, val)
VALUE thread, val;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
th->abort = RTEST(val);
return val;
}
static thread_t
-thread_alloc()
+rb_thread_alloc(klass)
+ VALUE klass;
{
thread_t th;
@@ -5363,8 +6556,7 @@ thread_alloc()
th->status = 0;
th->result = 0;
- th->errinfo = Qnil;
- th->errat = Qnil;
+ th->rb_errinfo = Qnil;
th->stk_ptr = 0;
th->stk_len = 0;
@@ -5376,19 +6568,19 @@ thread_alloc()
th->frame = 0;
th->scope = 0;
- th->class = 0;
+ th->klass = 0;
+ th->wrapper = 0;
th->dyna_vars = 0;
th->block = 0;
th->iter = 0;
th->tag = 0;
- th->errat = 0;
- th->errinfo = 0;
+ th->rb_errinfo = 0;
th->last_status = 0;
th->last_line = 0;
th->last_match = 0;
th->abort = 0;
- th->thread = data_object_alloc(cThread, th, 0, thread_free);
+ th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
if (curr_thread) {
th->prev = curr_thread;
@@ -5412,153 +6604,201 @@ catch_timer(sig)
#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
signal(sig, catch_timer);
#endif
- if (!thread_critical) {
- if (trap_immediate) {
- trap_immediate = 0;
- thread_schedule();
+ if (!rb_thread_critical) {
+ if (rb_trap_immediate) {
+ rb_thread_schedule();
}
- else thread_pending = 1;
+ else rb_thread_pending = 1;
}
}
#else
-int thread_tick = THREAD_TICK;
+int rb_thread_tick = THREAD_TICK;
#endif
-VALUE
-thread_create(fn, arg)
+static VALUE rb_thread_raise _((int, VALUE*, VALUE));
+
+#define SCOPE_SHARED FL_USER1
+
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+static int thread_init = 0;
+
+void
+rb_thread_start_timer()
+{
+ struct itimerval tval;
+
+ if (!thread_init) return;
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 50000;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+}
+
+void
+rb_thread_stop_timer()
+{
+ struct itimerval tval;
+
+ if (!thread_init) return;
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+}
+#endif
+
+static VALUE
+rb_thread_create_0(fn, arg, klass)
VALUE (*fn)();
void *arg;
+ VALUE klass;
{
- thread_t th = thread_alloc();
+ thread_t th = rb_thread_alloc(klass);
+ enum thread_status status;
int state;
#if defined(HAVE_SETITIMER) && !defined(__BOW__)
- static init = 0;
-
- if (!init) {
- struct itimerval tval;
-
+ if (!thread_init) {
#ifdef POSIX_SIGNAL
posix_signal(SIGVTALRM, catch_timer);
#else
signal(SIGVTALRM, catch_timer);
#endif
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 100000;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-
- init = 1;
+ thread_init = 1;
+ rb_thread_start_timer();
}
#endif
- thread_save_context(curr_thread);
+ FL_SET(ruby_scope, SCOPE_SHARED);
+ rb_thread_save_context(curr_thread);
if (setjmp(curr_thread->context)) {
return th->thread;
}
PUSH_TAG(PROT_THREAD);
if ((state = EXEC_TAG()) == 0) {
- thread_save_context(th);
+ rb_thread_save_context(th);
if (setjmp(th->context) == 0) {
curr_thread = th;
th->result = (*fn)(arg, th);
}
}
POP_TAG();
- if (state && th->status != THREAD_TO_KILL && !NIL_P(errinfo)) {
- if (state == TAG_FATAL || obj_is_kind_of(errinfo, eSystemExit)) {
- /* fatal error or global exit within this thread */
- /* need to stop whole script */
- main_thread->errat = errat;
- main_thread->errinfo = errinfo;
- thread_cleanup();
- }
- else if (thread_abort || curr_thread->abort || RTEST(debug)) {
- f_abort();
+ status = th->status;
+ rb_thread_remove();
+ if (state && status != THREAD_TO_KILL && !NIL_P(rb_errinfo)) {
+ if (state == TAG_FATAL) {
+ /* fatal error within this thread, need to stop whole script */
+ main_thread->rb_errinfo = rb_errinfo;
+ rb_thread_cleanup();
+ }
+ else if (rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
+ /* delegate exception to main_thread */
+ rb_thread_raise(1, &rb_errinfo, main_thread->thread);
+ }
+ else if (rb_thread_abort || curr_thread->abort || RTEST(rb_debug)) {
+ VALUE err = rb_exc_new(rb_eSystemExit, 0, 0);
+ error_print();
+ /* exit on main_thread */
+ rb_thread_raise(1, &err, main_thread->thread);
}
else {
- curr_thread->errat = errat;
- curr_thread->errinfo = errinfo;
+ curr_thread->rb_errinfo = rb_errinfo;
}
}
- thread_remove();
- return 0;
+ rb_thread_schedule();
+ return 0; /* not reached */
+}
+
+VALUE
+rb_thread_create(fn, arg)
+ VALUE (*fn)();
+ void *arg;
+{
+ return rb_thread_create_0(fn, arg, rb_cThread);
+}
+
+int
+rb_thread_scope_shared_p()
+{
+ return FL_TEST(ruby_scope, SCOPE_SHARED);
}
static VALUE
-thread_yield(arg, th)
+rb_thread_yield(arg, th)
int arg;
thread_t th;
{
- scope_dup(the_block->scope);
- rb_yield(th->thread);
- return th->thread;
+ scope_dup(ruby_block->scope);
+ return rb_yield_0(th->thread, 0, 0);
}
static VALUE
-thread_start()
+rb_thread_start(klass)
+ VALUE klass;
{
- if (!iterator_p()) {
- Raise(eThreadError, "must be called as iterator");
+ if (!rb_iterator_p()) {
+ rb_raise(rb_eThreadError, "must be called as iterator");
}
- return thread_create(thread_yield, 0);
+ return rb_thread_create_0(rb_thread_yield, 0, klass);
}
static VALUE
-thread_value(thread)
+rb_thread_value(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
+
+ rb_thread_join(thread);
+ if (!NIL_P(th->rb_errinfo)) {
+ VALUE oldbt = get_backtrace(th->rb_errinfo);
+ VALUE errat = make_backtrace();
- thread_join(0, thread);
- if (!NIL_P(th->errinfo)) {
- errat = make_backtrace();
- ary_unshift(errat, ary_entry(th->errat, 0));
- sourcefile = 0; /* kludge to print errat */
- rb_raise(th->errinfo);
+ rb_ary_unshift(errat, rb_ary_entry(oldbt, 0));
+ set_backtrace(th->rb_errinfo, errat);
+ rb_exc_raise(th->rb_errinfo);
}
return th->result;
}
static VALUE
-thread_status(thread)
+rb_thread_status(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) {
- if (NIL_P(th->errinfo)) return FALSE;
+ if (rb_thread_dead(th)) {
+ if (NIL_P(th->rb_errinfo)) return Qfalse;
return Qnil;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-thread_stopped(thread)
+rb_thread_stop_p(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) return TRUE;
- if (th->status == THREAD_STOPPED) return TRUE;
- return FALSE;
+ if (rb_thread_dead(th)) return Qtrue;
+ if (th->status == THREAD_STOPPED) return Qtrue;
+ return Qfalse;
}
static void
-thread_wait_other_threads()
+rb_thread_wait_other_threads()
{
/* wait other threads to terminate */
while (curr_thread != curr_thread->next) {
- thread_schedule();
+ rb_thread_schedule();
}
}
static void
-thread_cleanup()
+rb_thread_cleanup()
{
thread_t th;
@@ -5575,64 +6815,87 @@ thread_cleanup()
END_FOREACH(th);
}
-int thread_critical;
+int rb_thread_critical;
static VALUE
-thread_get_critical()
+rb_thread_get_critical()
{
- return thread_critical?TRUE:FALSE;
+ return rb_thread_critical?Qtrue:Qfalse;
}
static VALUE
-thread_set_critical(obj, val)
+rb_thread_set_critical(obj, val)
VALUE obj, val;
{
- thread_critical = RTEST(val);
+ rb_thread_critical = RTEST(val);
return val;
}
void
-thread_interrupt()
+rb_thread_interrupt()
{
- thread_critical = 0;
- thread_ready(main_thread);
+ rb_thread_critical = 0;
+ rb_thread_ready(main_thread);
if (curr_thread == main_thread) {
rb_interrupt();
}
- thread_save_context(curr_thread);
+ rb_thread_save_context(curr_thread);
+ if (setjmp(curr_thread->context)) {
+ return;
+ }
+ curr_thread = main_thread;
+ rb_thread_restore_context(curr_thread, 2);
+}
+
+void
+rb_thread_trap_eval(cmd, sig)
+ VALUE cmd;
+ int sig;
+{
+ rb_thread_critical = 0;
+ if (!rb_thread_dead(curr_thread)) {
+ rb_thread_ready(curr_thread);
+ rb_trap_eval(cmd, sig);
+ return;
+ }
+ rb_thread_ready(main_thread);
+ rb_thread_save_context(curr_thread);
if (setjmp(curr_thread->context)) {
return;
}
+ th_cmd = cmd;
+ th_sig = sig;
curr_thread = main_thread;
- thread_restore_context(curr_thread, 2);
+ rb_thread_restore_context(curr_thread, 3);
}
static VALUE
-thread_raise(argc, argv, thread)
+rb_thread_raise(argc, argv, thread)
int argc;
VALUE *argv;
VALUE thread;
{
- thread_t th = thread_check(thread);
+ thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) return thread;
+ if (rb_thread_dead(th)) return thread;
if (curr_thread == th) {
- f_raise(argc, argv);
+ rb_f_raise(argc, argv);
}
- thread_save_context(curr_thread);
+ if (curr_thread->status != THREAD_KILLED)
+ rb_thread_save_context(curr_thread);
if (setjmp(curr_thread->context)) {
return thread;
}
rb_scan_args(argc, argv, "11", &th_raise_argv[0], &th_raise_argv[1]);
- thread_ready(th);
+ rb_thread_ready(th);
curr_thread = th;
th_raise_argc = argc;
- th_raise_file = sourcefile;
- th_raise_line = sourceline;
- thread_restore_context(curr_thread, 3);
+ th_raise_file = ruby_sourcefile;
+ th_raise_line = ruby_sourceline;
+ rb_thread_restore_context(curr_thread, 4);
return Qnil; /* not reached */
}
@@ -5640,75 +6903,223 @@ static thread_t loading_thread;
static int loading_nest;
static int
-thread_loading(feature)
+rb_thread_loading(feature)
char *feature;
{
if (curr_thread != curr_thread->next && loading_thread) {
while (loading_thread != curr_thread) {
- thread_schedule();
+ rb_thread_schedule();
CHECK_INTS;
}
- if (rb_provided(feature)) return TRUE; /* no need to load */
+ if (rb_provided(feature)) return Qtrue; /* no need to load */
}
loading_thread = curr_thread;
loading_nest++;
- return FALSE;
+ return Qfalse;
}
static void
-thread_loading_done()
+rb_thread_loading_done()
{
if (--loading_nest == 0) {
loading_thread = 0;
}
}
+VALUE
+rb_thread_local_aref(thread, id)
+ VALUE thread;
+ ID id;
+{
+ thread_t th;
+ VALUE val;
+
+ th = rb_thread_check(thread);
+ if (!th->locals) return Qnil;
+ if (st_lookup(th->locals, id, &val)) {
+ return val;
+ }
+ return Qnil;
+}
+
+static VALUE
+rb_thread_aref(thread, id)
+ VALUE thread, id;
+{
+ return rb_thread_local_aref(thread, rb_to_id(id));
+}
+
+VALUE
+rb_thread_local_aset(thread, id, val)
+ VALUE thread;
+ ID id;
+ VALUE val;
+{
+ thread_t th;
+
+
+ if (safe_level >= 4 && !FL_TEST(thread, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread values");
+
+ th = rb_thread_check(thread);
+ if (!th->locals) {
+ th->locals = st_init_numtable();
+ }
+ if (NIL_P(val)) {
+ st_delete(th->locals, &id, 0);
+ return Qnil;
+ }
+ st_insert(th->locals, id, val);
+
+ return val;
+}
+
+static VALUE
+rb_thread_aset(thread, id, val)
+ VALUE thread, id, val;
+{
+ return rb_thread_local_aset(thread, rb_to_id(id), val);
+}
+
+static VALUE
+rb_thread_key_p(thread, id)
+ VALUE thread, id;
+{
+ thread_t th = rb_thread_check(thread);
+
+ if (!th->locals) return Qfalse;
+ if (st_lookup(th->locals, rb_to_id(id), 0))
+ return Qtrue;
+ return Qfalse;
+}
+
+static VALUE rb_cContinuation;
+
+static VALUE
+rb_callcc(self)
+ VALUE self;
+{
+ volatile VALUE cont;
+ thread_t th = ALLOC(struct thread);
+
+ th->status = THREAD_RUNNABLE;
+
+ th->status = 0;
+ th->result = 0;
+ th->rb_errinfo = Qnil;
+
+ th->stk_ptr = 0;
+ th->stk_len = 0;
+ th->stk_max = 0;
+ th->wait_for = 0;
+ th->fd = 0;
+ th->delay = 0.0;
+ th->join = 0;
+
+ th->frame = 0;
+ th->scope = 0;
+ th->klass = 0;
+ th->dyna_vars = 0;
+ th->block = 0;
+ th->iter = 0;
+ th->tag = 0;
+ th->rb_errinfo = 0;
+ th->last_status = 0;
+ th->last_line = 0;
+ th->last_match = 0;
+ th->abort = 0;
+
+ th->thread = cont = Data_Wrap_Struct(rb_cContinuation, thread_mark,
+ thread_free, th);
+
+ FL_SET(ruby_scope, SCOPE_DONT_RECYCLE);
+ rb_thread_save_context(th);
+ if (setjmp(th->context)) {
+ return th->result;
+ }
+ else {
+ return rb_yield(th->thread);
+ }
+}
+
+static VALUE
+rb_continuation_call(argc, argv, cont)
+ int argc;
+ VALUE *argv;
+ VALUE cont;
+{
+ thread_t th = rb_thread_check(cont);
+
+ switch (argc) {
+ case 0:
+ th->result = Qnil;
+ break;
+ case 1:
+ th->result = *argv;
+ break;
+ default:
+ th->result = rb_ary_new4(argc, argv);
+ break;
+ }
+ rb_thread_restore_context(th, 0);
+ return Qnil;
+}
+
void
Init_Thread()
{
- eThreadError = rb_define_class("ThreadError", eException);
- cThread = rb_define_class("Thread", cObject);
+ rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
+ rb_cThread = rb_define_class("Thread", rb_cObject);
+
+ rb_define_singleton_method(rb_cThread, "new", rb_thread_start, 0);
+ rb_define_singleton_method(rb_cThread, "start", rb_thread_start, 0);
+ rb_define_singleton_method(rb_cThread, "fork", rb_thread_start, 0);
- rb_define_singleton_method(cThread, "new", thread_start, 0);
- rb_define_singleton_method(cThread, "start", thread_start, 0);
- rb_define_singleton_method(cThread, "fork", thread_start, 0);
+ rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
+ rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
+ rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
+ rb_define_singleton_method(rb_cThread, "pass", rb_thread_pass, 0);
+ rb_define_singleton_method(rb_cThread, "join", rb_thread_s_join, 1);
+ rb_define_singleton_method(rb_cThread, "current", rb_thread_current, 0);
+ rb_define_singleton_method(rb_cThread, "main", rb_thread_main, 0);
- rb_define_singleton_method(cThread, "stop", thread_stop, 0);
- rb_define_singleton_method(cThread, "kill", thread_s_kill, 1);
- rb_define_singleton_method(cThread, "exit", thread_exit, 0);
- rb_define_singleton_method(cThread, "pass", thread_pass, 0);
- rb_define_singleton_method(cThread, "join", thread_join, 1);
- rb_define_singleton_method(cThread, "current", thread_current, 0);
- rb_define_singleton_method(cThread, "main", thread_main, 0);
+ rb_define_singleton_method(rb_cThread, "critical", rb_thread_get_critical, 0);
+ rb_define_singleton_method(rb_cThread, "critical=", rb_thread_set_critical, 1);
- rb_define_singleton_method(cThread, "critical", thread_get_critical, 0);
- rb_define_singleton_method(cThread, "critical=", thread_set_critical, 1);
+ rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
+ rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
- rb_define_singleton_method(cThread, "abort_on_exception", thread_s_abort_exc, 0);
- rb_define_singleton_method(cThread, "abort_on_exception=", thread_s_abort_exc_set, 1);
+ rb_define_method(rb_cThread, "run", rb_thread_run, 0);
+ rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
+ rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
+ rb_define_method(rb_cThread, "value", rb_thread_value, 0);
+ rb_define_method(rb_cThread, "status", rb_thread_status, 0);
+ rb_define_method(rb_cThread, "join", rb_thread_join, 0);
+ rb_define_method(rb_cThread, "alive?", rb_thread_status, 0);
+ rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
+ rb_define_method(rb_cThread, "raise", rb_thread_raise, -1);
- rb_define_method(cThread, "run", thread_run, 0);
- rb_define_method(cThread, "wakeup", thread_wakeup, 0);
- rb_define_method(cThread, "stop", thread_stop_method, 0);
- rb_define_method(cThread, "exit", thread_kill, 0);
- rb_define_method(cThread, "value", thread_value, 0);
- rb_define_method(cThread, "status", thread_status, 0);
- rb_define_method(cThread, "alive?", thread_status, 0);
- rb_define_method(cThread, "stop?", thread_stopped, 0);
- rb_define_method(cThread, "raise", thread_raise, -1);
+ rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
+ rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
- rb_define_method(cThread, "abort_on_exception", thread_abort_exc, 0);
- rb_define_method(cThread, "abort_on_exception=", thread_abort_exc_set, 1);
+ rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
+ rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
+ rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
/* allocate main thread */
- main_thread = thread_alloc();
+ main_thread = rb_thread_alloc(rb_cThread);
+
+ rb_cContinuation = rb_define_class("Continuation", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cContinuation), "new");
+ rb_define_method(rb_cContinuation, "call", rb_continuation_call, -1);
+ rb_define_method(rb_mKernel, "callcc", rb_callcc, 0);
}
#endif
static VALUE
-f_catch(dmy, tag)
+rb_f_catch(dmy, tag)
VALUE dmy, tag;
{
int state;
@@ -5718,10 +7129,10 @@ f_catch(dmy, tag)
t = rb_to_id(tag);
PUSH_TAG(t);
if ((state = EXEC_TAG()) == 0) {
- val = rb_yield(tag);
+ val = rb_yield_0(tag, 0, 0);
}
- else if (state == TAG_THROW && prot_tag->tag == prot_tag->dst) {
- val = prot_tag->tag_retval;
+ else if (state == TAG_THROW && t == prot_tag->dst) {
+ val = prot_tag->retval;
state = 0;
}
POP_TAG();
@@ -5731,7 +7142,23 @@ f_catch(dmy, tag)
}
static VALUE
-f_throw(argc, argv)
+catch_i(tag)
+ ID tag;
+{
+ return rb_f_catch(0, FIX2INT(tag));
+}
+
+VALUE
+rb_catch(tag, proc, data)
+ char *tag;
+ VALUE (*proc)();
+ VALUE data;
+{
+ return rb_iterate(catch_i, rb_intern(tag), proc, data);
+}
+
+static VALUE
+rb_f_throw(argc, argv)
int argc;
VALUE *argv;
{
@@ -5745,44 +7172,55 @@ f_throw(argc, argv)
while (tt) {
if (tt->tag == t) {
tt->dst = t;
- tt->tag_retval = value;
break;
}
-#ifdef THREAD
+#ifdef USE_THREAD
if (tt->tag == PROT_THREAD) {
- Raise(eThreadError, "uncaught throw `%s' in thread 0x%x\n",
- rb_id2name(t),
- curr_thread);
+ rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%x",
+ rb_id2name(t),
+ curr_thread);
}
#endif
tt = tt->prev;
}
-
if (!tt) {
- NameError("uncaught throw `%s'\n", rb_id2name(t));
+ rb_raise(rb_eNameError, "uncaught throw `%s'", rb_id2name(t));
}
+ return_value(value);
+ rb_trap_restore_mask();
JUMP_TAG(TAG_THROW);
/* not reached */
}
-static void
-return_value(val)
+void
+rb_throw(tag, val)
+ char *tag;
VALUE val;
{
+ VALUE argv[2];
+ ID t = rb_intern(tag);
+
+ argv[0] = FIX2INT(t);
+ argv[1] = val;
+ rb_f_throw(2, argv);
+}
+
+static void
+return_check()
+{
+#ifdef USE_THREAD
struct tag *tt = prot_tag;
-
+
while (tt) {
if (tt->tag == PROT_FUNC) {
- tt->tag_retval = val;
break;
}
-#ifdef THREAD
if (tt->tag == PROT_THREAD) {
- Raise(eThreadError, "return from within thread 0x%x\n",
- curr_thread);
+ rb_raise(rb_eThreadError, "return from within thread 0x%x",
+ curr_thread);
}
-#endif
tt = tt->prev;
}
+#endif
}
diff --git a/ext/Setup b/ext/Setup
index c92ac53e00..9e3a2474c3 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -10,3 +10,4 @@
#socket
#tkutil
#tcltklib
+#gtk
diff --git a/ext/Win32API/MANIFEST b/ext/Win32API/MANIFEST
new file mode 100644
index 0000000000..7cc9ac445e
--- /dev/null
+++ b/ext/Win32API/MANIFEST
@@ -0,0 +1,7 @@
+MANIFEST
+depend
+MANIFEST
+Win32API.c
+extconf.rb
+getch.rb
+point.rb
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
new file mode 100644
index 0000000000..f4cb5c726f
--- /dev/null
+++ b/ext/Win32API/Win32API.c
@@ -0,0 +1,223 @@
+/*
+ Win32API - Ruby Win32 API Import Facility
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+
+#define _T_VOID 0
+#define _T_NUMBER 1
+#define _T_POINTER 2
+#define _T_INTEGER 3
+
+typedef char *ApiPointer(void);
+typedef long ApiNumber(void);
+typedef void ApiVoid(void);
+typedef int ApiInteger(void);
+
+#include "ruby.h"
+
+typedef struct {
+ HANDLE dll;
+ HANDLE proc;
+ VALUE dllname;
+ VALUE import;
+ VALUE export;
+} Win32API;
+
+static void
+Win32API_FreeLibrary(hdll)
+ HINSTANCE hdll;
+{
+ FreeLibrary(hdll);
+}
+
+static VALUE
+Win32API_initialize(self, dllname, proc, import, export)
+ VALUE self;
+ VALUE dllname;
+ VALUE proc;
+ VALUE import;
+ VALUE export;
+{
+ HANDLE hproc;
+ HINSTANCE hdll;
+ VALUE str;
+ VALUE a_import;
+ VALUE *ptr;
+ int i;
+ int len;
+ int ex;
+
+ hdll = GetModuleHandle(RSTRING(dllname)->ptr);
+ if (!hdll) {
+ hdll = LoadLibrary(RSTRING(dllname)->ptr);
+ if (!hdll)
+ Fail("LoadLibrary: %s\n", RSTRING(dllname)->ptr);
+ Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll);
+ }
+ hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
+ if (!hproc) {
+ str = str_new3(proc);
+ str = str_cat(str, "A", 1);
+ hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
+ if (!hproc)
+ Fail("GetProcAddress: %s or %s\n",
+ RSTRING(proc)->ptr, RSTRING(str)->ptr);
+ }
+ rb_iv_set(self, "__dll__", INT2NUM((int)hdll));
+ rb_iv_set(self, "__dllname__", dllname);
+ rb_iv_set(self, "__proc__", INT2NUM((int)hproc));
+
+ a_import = ary_new();
+ ptr = RARRAY(import)->ptr;
+ for (i = 0, len = RARRAY(import)->len; i < len; i++) {
+ int c = *(char *)RSTRING(ptr[i])->ptr;
+ switch (c) {
+ case 'N': case 'n': case 'L': case 'l':
+ ary_push(a_import, INT2FIX(_T_NUMBER));
+ break;
+ case 'P': case 'p':
+ ary_push(a_import, INT2FIX(_T_POINTER));
+ break;
+ case 'I': case 'i':
+ ary_push(a_import, INT2FIX(_T_INTEGER));
+ break;
+ }
+ }
+ rb_iv_set(self, "__import__", a_import);
+
+ switch (*RSTRING(export)->ptr) {
+ case 'V': case 'v':
+ ex = _T_VOID;
+ break;
+ case 'N': case 'n': case 'L': case 'l':
+ ex = _T_NUMBER;
+ break;
+ case 'P': case 'p':
+ ex = _T_POINTER;
+ break;
+ case 'I': case 'i':
+ ex = _T_INTEGER;
+ break;
+ }
+ rb_iv_set(self, "__export__", INT2FIX(ex));
+
+ return Qnil;
+}
+
+static VALUE
+Win32API_Call(argc, argv, obj)
+ VALUE argc;
+ VALUE argv;
+ VALUE obj;
+{
+ VALUE args;
+
+ FARPROC ApiFunction;
+
+ ApiPointer *ApiFunctionPointer;
+ ApiNumber *ApiFunctionNumber;
+ ApiVoid *ApiFunctionVoid;
+ ApiInteger *ApiFunctionInteger;
+
+ long lParam;
+ char *pParam;
+
+ VALUE Return;
+
+ VALUE obj_proc;
+ VALUE obj_import;
+ VALUE obj_export;
+ VALUE import_type;
+ int nimport, timport, texport, i;
+ int items;
+
+ items = rb_scan_args(argc, argv, "0*", &args);
+
+ obj_proc = rb_iv_get(obj, "__proc__");
+
+ ApiFunction = (FARPROC)NUM2INT(obj_proc);
+
+ obj_import = rb_iv_get(obj, "__import__");
+ obj_export = rb_iv_get(obj, "__export__");
+ nimport = RARRAY(obj_import)->len;
+ texport = FIX2INT(obj_export);
+
+ if (items != nimport)
+ Fail("Wrong number of parameters: expected %d, got %d.\n",
+ nimport, items);
+
+ if (0 < nimport) {
+ for (i = nimport - 1; 0 <= i; i--) {
+ VALUE str;
+ import_type = ary_entry(obj_import, i);
+ timport = FIX2INT(import_type);
+ switch (timport) {
+ case _T_NUMBER:
+ case _T_INTEGER:
+ lParam = NUM2INT(ary_entry(args, i));
+#if defined(_MSC_VER) || defined(__LCC__)
+ _asm {
+ mov eax, lParam
+ push eax
+ }
+#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+ asm volatile ("pushl %0" :: "g" (lParam));
+#else
+#error
+#endif
+ break;
+ case _T_POINTER:
+ str = ary_entry(args, i);
+ Check_Type(str, T_STRING);
+ str_modify(str);
+ pParam = RSTRING(str)->ptr;
+#if defined(_MSC_VER) || defined(__LCC__)
+ _asm {
+ mov eax, dword ptr pParam
+ push eax
+ }
+#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+ asm volatile ("pushl %0" :: "g" (pParam));
+#else
+#error
+#endif
+ break;
+ }
+ }
+
+ }
+
+ switch (texport) {
+ case _T_NUMBER:
+ ApiFunctionNumber = (ApiNumber *) ApiFunction;
+ Return = INT2NUM(ApiFunctionNumber());
+ break;
+ case _T_POINTER:
+ ApiFunctionPointer = (ApiPointer *) ApiFunction;
+ Return = str_new2((char *)ApiFunctionPointer());
+ break;
+ case _T_INTEGER:
+ ApiFunctionInteger = (ApiInteger *) ApiFunction;
+ Return = INT2NUM(ApiFunctionInteger());
+ break;
+ case _T_VOID:
+ default:
+ ApiFunctionVoid = (ApiVoid *) ApiFunction;
+ ApiFunctionVoid();
+ Return = INT2NUM(0);
+ break;
+ }
+ return Return;
+}
+
+void
+Init_Win32API()
+{
+ VALUE cWin32API = rb_define_class("Win32API", cObject);
+ rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
+ rb_define_method(cWin32API, "call", Win32API_Call, -1);
+ rb_define_alias(cWin32API, "Call", "call");
+}
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
new file mode 100644
index 0000000000..5af3243d96
--- /dev/null
+++ b/ext/Win32API/extconf.rb
@@ -0,0 +1,7 @@
+case PLATFORM
+when /cygwin/,/mingw/
+ $CFLAGS = "-fno-defer-pop"
+ create_makefile("Win32API")
+when /win32/
+ create_makefile("Win32API")
+end
diff --git a/ext/Win32API/getch.rb b/ext/Win32API/getch.rb
new file mode 100644
index 0000000000..c015bbe9bc
--- /dev/null
+++ b/ext/Win32API/getch.rb
@@ -0,0 +1,5 @@
+require 'Win32API'
+
+getch = Win32API.new("crtdll", "_getch", [], 'L')
+
+puts getch.Call.chr
diff --git a/ext/Win32API/point.rb b/ext/Win32API/point.rb
new file mode 100644
index 0000000000..60e265f3ee
--- /dev/null
+++ b/ext/Win32API/point.rb
@@ -0,0 +1,18 @@
+require 'Win32API'
+
+getCursorPos = Win32API.new("user32", "GetCursorPos", ['P'], 'V')
+
+lpPoint = " " * 8 # store two LONGs
+getCursorPos.Call(lpPoint)
+x, y = lpPoint.unpack("LL") # get the actual values
+
+print "x: ", x, "\n"
+print "y: ", y, "\n"
+
+ods = Win32API.new("kernel32", "OutputDebugString", ['P'], 'V')
+ods.Call("Hello, World\n");
+
+GetDesktopWindow = Win32API.new("user32", "GetDesktopWindow", [], 'L')
+GetActiveWindow = Win32API.new("user32", "GetActiveWindow", [], 'L')
+SendMessage = Win32API.new("user32", "SendMessage", ['L'] * 4, 'L')
+SendMessage.Call GetDesktopWindow.Call, 274, 0xf140, 0
diff --git a/ext/aix_ld.rb b/ext/aix_ld.rb
index 1058977b88..42b2087a46 100644
--- a/ext/aix_ld.rb
+++ b/ext/aix_ld.rb
@@ -43,7 +43,7 @@ def extract(nm, out)
else
next
end
- }.sort!
+ }.compact!.sort!
uniq(data)
exp = open(out, "w")
for line in data
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 3ae8db192d..f3d1bc0970 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -2,7 +2,7 @@
* ext/curses/curses.c
*
* by MAEDA Shugo (ender@pic-internet.or.jp)
- * modified by Yukihiro Matsumoto (matz@ruby.club.or.jp)
+ * modified by Yukihiro Matsumoto (matz@netlab.co.jp)
*/
#ifdef HAVE_NCURSES_H
@@ -12,12 +12,18 @@
# include <ncurses/curses.h>
# else
# include <curses.h>
-# if defined(__NetBSD__) && !defined(_maxx)
+# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxx)
# define _maxx maxx
# endif
-# if defined(__NetBSD__) && !defined(_maxy)
+# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxy)
# define _maxy maxy
# endif
+# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begx)
+# define _begx begx
+# endif
+# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begy)
+# define _begy begy
+# endif
# endif
#endif
@@ -32,14 +38,10 @@ struct windata {
WINDOW *window;
};
-#define NUM2CHAR(x) ((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
- RSTRING(x)->ptr[0]:(char)NUM2INT(x)
-#define CHAR2FIX(x) INT2FIX((int)x)
-
static void
no_window()
{
- Fail("already closed window");
+ rb_raise(rb_eRuntimeError, "already closed window");
}
#define GetWINDOW(obj, winp) {\
@@ -55,6 +57,7 @@ free_window(winp)
{
if (winp->window && winp->window != stdscr) delwin(winp->window);
winp->window = 0;
+ free(winp);
}
static VALUE
@@ -66,7 +69,7 @@ prep_window(class, window)
struct windata *winp;
if (window == NULL) {
- Fail("failed to create window");
+ rb_raise(rb_eRuntimeError, "failed to create window");
}
obj = Data_Make_Struct(class, struct windata, 0, free_window, winp);
@@ -83,7 +86,7 @@ curses_init_screen()
{
initscr();
if (stdscr == 0) {
- Fail("cannot initialize curses");
+ rb_raise(rb_eRuntimeError, "cannot initialize curses");
}
clear();
rb_stdscr = prep_window(cWindow, stdscr);
@@ -102,19 +105,33 @@ curses_stdscr()
static VALUE
curses_close_screen()
{
- endwin();
+#ifdef HAVE_ISENDWIN
+ if (!isendwin())
+#endif
+ endwin();
return Qnil;
}
+static void
+curses_finalize()
+{
+ if (stdscr
+#ifdef HAVE_ISENDWIN
+ && !isendwin()
+#endif
+ )
+ endwin();
+}
+
/* def closed? */
static VALUE
curses_closed()
{
-#ifdef HAVE_ENDWIN
+#ifdef HAVE_ISENDWIN
if (isendwin()) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
#else
rb_notimplement();
#endif
@@ -138,12 +155,16 @@ curses_refresh(obj)
return Qnil;
}
-/* def refresh */
+/* def doupdate */
static VALUE
curses_doupdate(obj)
VALUE obj;
{
+#ifdef HAVE_DOUPDATE
doupdate();
+#else
+ refresh();
+#endif
return Qnil;
}
@@ -235,7 +256,9 @@ static VALUE
curses_flash(obj)
VALUE obj;
{
+#ifdef HAVE_FLASH
flash();
+#endif
return Qnil;
}
@@ -287,7 +310,7 @@ static VALUE
curses_inch(obj)
VALUE obj;
{
- return CHAR2FIX(inch());
+ return CHR2FIX(inch());
}
/* def addch(ch) */
@@ -296,7 +319,7 @@ curses_addch(obj, ch)
VALUE obj;
VALUE ch;
{
- addch(NUM2CHAR(ch));
+ addch(NUM2CHR(ch));
return Qnil;
}
@@ -306,7 +329,7 @@ curses_insch(obj, ch)
VALUE obj;
VALUE ch;
{
- insch(NUM2CHAR(ch));
+ insch(NUM2CHR(ch));
return Qnil;
}
@@ -316,7 +339,9 @@ curses_addstr(obj, str)
VALUE obj;
VALUE str;
{
- addstr(RSTRING(str)->ptr);
+ if (!NIL_P(str)) {
+ addstr(STR2CSTR(str));
+ }
return Qnil;
}
@@ -325,7 +350,7 @@ static VALUE
curses_getch(obj)
VALUE obj;
{
- return CHAR2FIX(getch());
+ return CHR2FIX(getch());
}
/* def getstr */
@@ -335,7 +360,7 @@ curses_getstr(obj)
{
char rtn[1024]; /* This should be big enough.. I hope */
getstr(rtn);
- return str_taint(str_new2(rtn));
+ return rb_tainted_str_new2(rtn);
}
/* def delch */
@@ -352,7 +377,9 @@ static VALUE
curses_deleteln(obj)
VALUE obj;
{
+#ifdef HAVE_DELETELN
deleteln();
+#endif
return Qnil;
}
@@ -379,11 +406,15 @@ window_s_new(class, lines, cols, top, left)
VALUE top;
VALUE left;
{
+ VALUE w;
WINDOW *window;
window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left));
wclear(window);
- return prep_window(class, window);
+ w = prep_window(class, window);
+ rb_obj_call_init(w);
+
+ return w;
}
/* def subwin(lines, cols, top, left) */
@@ -412,7 +443,8 @@ window_close(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- free_window(winp);
+ delwin(winp->window);
+ winp->window = 0;
return Qnil;
}
@@ -453,7 +485,7 @@ window_box(obj, vert, hor)
struct windata *winp;
GetWINDOW(obj, winp);
- box(winp->window, NUM2CHAR(vert), NUM2CHAR(hor));
+ box(winp->window, NUM2CHR(vert), NUM2CHR(hor));
return Qnil;
}
@@ -622,7 +654,7 @@ window_inch(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- return CHAR2FIX(winch(winp->window));
+ return CHR2FIX(winch(winp->window));
}
/* def addch(ch) */
@@ -634,7 +666,7 @@ window_addch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- waddch(winp->window, NUM2CHAR(ch));
+ waddch(winp->window, NUM2CHR(ch));
return Qnil;
}
@@ -648,7 +680,7 @@ window_insch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- winsch(winp->window, NUM2CHAR(ch));
+ winsch(winp->window, NUM2CHR(ch));
return Qnil;
}
@@ -659,11 +691,12 @@ window_addstr(obj, str)
VALUE obj;
VALUE str;
{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- waddstr(winp->window, RSTRING(str)->ptr);
-
+ if (!NIL_P(str)) {
+ struct windata *winp;
+
+ GetWINDOW(obj, winp);
+ waddstr(winp->window, STR2CSTR(str));
+ }
return Qnil;
}
@@ -685,7 +718,7 @@ window_getch(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- return CHAR2FIX(wgetch(winp->window));
+ return CHR2FIX(wgetch(winp->window));
}
/* def getstr */
@@ -698,7 +731,7 @@ window_getstr(obj)
GetWINDOW(obj, winp);
wgetstr(winp->window, rtn);
- return str_taint(str_new2(rtn));
+ return rb_tainted_str_new2(rtn);
}
/* def delch */
@@ -718,10 +751,12 @@ static VALUE
window_deleteln(obj)
VALUE obj;
{
+#ifdef HAVE_WDELETELN
struct windata *winp;
GetWINDOW(obj, winp);
wdeleteln(winp->window);
+#endif
return Qnil;
}
@@ -764,7 +799,7 @@ Init_curses()
rb_define_module_function(mCurses, "lines", curses_lines, 0);
rb_define_module_function(mCurses, "cols", curses_cols, 0);
- cWindow = rb_define_class_under(mCurses, "Window", cObject);
+ cWindow = rb_define_class_under(mCurses, "Window", rb_cObject);
rb_define_singleton_method(cWindow, "new", window_s_new, 4);
rb_define_method(cWindow, "subwin", window_subwin, 4);
rb_define_method(cWindow, "close", window_close, 0);
@@ -790,4 +825,6 @@ Init_curses()
rb_define_method(cWindow, "getstr", window_getstr, 0);
rb_define_method(cWindow, "delch", window_delch, 0);
rb_define_method(cWindow, "deleteln", window_deleteln, 0);
+
+ rb_set_end_proc(curses_finalize, 0);
}
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 9b28437843..442a9424a2 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -1,6 +1,9 @@
+require 'mkmf'
$CFLAGS="-I/usr/include/ncurses -I/usr/local/include/ncurses"
$LDFLAGS="-L/usr/local/lib"
make=FALSE
+
+have_library("mytinfo", "tgetent") if /bow/ =~ PLATFORM
if have_header("ncurses.h") and have_library("ncurses", "initscr")
make=TRUE
elsif have_header("ncurses/curses.h") and have_library("ncurses", "initscr")
@@ -14,7 +17,7 @@ else
end
if make then
- for f in ["isendwin", "ungetch", "beep"]
+ for f in %w(isendwin ungetch beep doupdate flash deleteln wdeleteln)
have_func(f)
end
create_makefile("curses")
diff --git a/ext/curses/hello.rb b/ext/curses/hello.rb
index bed7779aac..a1915ce60d 100644
--- a/ext/curses/hello.rb
+++ b/ext/curses/hello.rb
@@ -10,6 +10,7 @@ def show_message(message)
win.box(?|, ?=)
win.setpos(2, 3)
win.addstr(message)
+ win.refresh
win.getch
win.close
end
@@ -18,8 +19,9 @@ init_screen
begin
crmode
# show_message("Hit any key")
- setpos (lines - 5) / 2, (cols - 10) / 2
+ setpos((lines - 5) / 2, (cols - 10) / 2)
addstr("Hit any key")
+ refresh
getch
show_message("Hello, World!")
refresh
diff --git a/ext/curses/view.rb b/ext/curses/view.rb
index e59a74ed44..5ba1a8413c 100644
--- a/ext/curses/view.rb
+++ b/ext/curses/view.rb
@@ -43,6 +43,7 @@ while TRUE
addstr(data_lines[lptr + i]) #if data_lines[lptr + i]
i += 1
end
+ refresh
explicit = FALSE
n = 0
diff --git a/ext/cygwin32_ld.rb b/ext/cygwin32_ld.rb
new file mode 100644
index 0000000000..a9c8e21cb0
--- /dev/null
+++ b/ext/cygwin32_ld.rb
@@ -0,0 +1,90 @@
+#!/usr/local/bin/ruby
+require '../../rbconfig'
+include Config
+
+args = ARGV.join(" ")
+
+objs = []
+flags = []
+libname = ''
+Init = "../init"
+
+path = ''
+
+def writeInit
+ out = open("#{Init}.c", "w")
+
+ out.print %q@
+#include <windows.h>
+#include <stdio.h>
+
+extern struct _reent *__imp_reent_data;
+WINAPI dll_entry(int a, int b, int c)
+{
+ _impure_ptr =__imp_reent_data;
+ return 1;
+}
+main(){}
+//void impure_setup(struct _reent *_impure_ptrMain)
+//{
+// _impure_ptr =__imp_reent_data;
+//}
+@
+ out.close
+end
+
+def xsystem cmd
+ print cmd, "\n"
+ system cmd
+end
+
+if args =~ /-o (\w+)\.dll/i
+ libname = $1
+ # Check for path:
+ if libname =~ /(\w+\/)(\w+)$/
+ path = $1
+ libname = $2
+ end
+ for arg in ARGV
+ case arg
+ when /\.[oa]$/i
+ objs.push(arg)
+ when /-o/, /\w+\.dll/i
+ ;
+ else
+ flags << arg
+ end
+ end
+
+ writeInit unless FileTest.exist?("#{Init}.c")
+ unless FileTest.exist?("#{Init}.o") and
+ File.mtime("#{Init}.c") < File.mtime("#{Init}.o")
+ xsystem "gcc -c #{Init}.c -o #{Init}.o"
+ end
+
+ command = "echo EXPORTS > #{libname}.def"
+ xsystem command
+# xsystem "echo impure_setup >> #{libname}.def"
+ xsystem "nm --extern-only " + objs.join(" ") +
+ " | sed -n '/^........ [CDT] _/s///p' >> #{libname}.def"
+
+ command = "gcc -nostdlib -o junk.o -Wl,--base-file,#{libname}.base,--dll " +
+ objs.join(" ") + " #{Init}.o "
+ command.concat(flags.join(" ") +
+ " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a")
+ xsystem command
+
+ command = "dlltool --as=as --dllname #{libname}.dll --def #{libname}.def --base-file #{libname}.base --output-exp #{libname}.exp"
+ xsystem command
+
+ command = "gcc -s -nostdlib -o #{libname}.dll -Wl,--dll #{libname}.exp " +
+ objs.join(" ") + " #{Init}.o "
+ command.concat(flags.join(" ") +
+ " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a")
+ xsystem command
+ File.unlink "junk.o" if FileTest.exist? "junk.o"
+
+else
+ # no special processing, just call ld
+ xsystem "ld #{args}"
+end
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index b416802241..2764a325e1 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Jan 24 15:59:52 JST 1994
- Copyright (C) 1995 Yukihiro Matsumoto
+ Copyright (C) 1995-1998 Yukihiro Matsumoto
************************************************/
@@ -15,11 +15,12 @@
#include <ndbm.h>
#include <fcntl.h>
#include <errno.h>
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
VALUE cDBM;
-extern VALUE mEnumerable;
-
struct dbmdata {
int di_size;
DBM *di_dbm;
@@ -28,7 +29,7 @@ struct dbmdata {
static void
closed_dbm()
{
- Fail("closed DBM file");
+ rb_raise(rb_eRuntimeError, "closed DBM file");
}
#define GetDBM(obj, dbmp) {\
@@ -41,13 +42,14 @@ free_dbm(dbmp)
struct dbmdata *dbmp;
{
if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
+ free(dbmp);
}
static VALUE
-fdbm_s_open(argc, argv, class)
+fdbm_s_open(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
VALUE file, vmode;
DBM *dbm;
@@ -79,9 +81,10 @@ fdbm_s_open(argc, argv, class)
rb_sys_fail(RSTRING(file)->ptr);
}
- obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+ obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
+ rb_obj_call_init(obj);
return obj;
}
@@ -118,23 +121,23 @@ fdbm_fetch(obj, keystr)
if (value.dptr == 0) {
return Qnil;
}
- return str_taint(str_new(value.dptr, value.dsize));
+ return rb_tainted_str_new(value.dptr, value.dsize);
}
static VALUE
-fdbm_indexes(obj, ag)
- VALUE obj, ag;
+fdbm_indexes(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
- VALUE *p, *pend;
VALUE new;
- int i = 0;
- struct RArray *args = RARRAY(rb_Array(ag));
+ int i;
- new = ary_new2(args->len);
- p = args->ptr; pend = p + args->len;
- while (p < pend) {
- ary_push(new, fdbm_fetch(obj, *p++));
+ new = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, fdbm_fetch(obj, argv[i]));
}
+
return new;
}
@@ -156,13 +159,13 @@ fdbm_delete(obj, keystr)
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
- if (iterator_p()) rb_yield(keystr);
+ if (rb_iterator_p()) rb_yield(keystr);
return Qnil;
}
if (dbm_delete(dbm, key)) {
dbmp->di_size = -1;
- Fail("dbm_delete failed");
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
}
else if (dbmp->di_size >= 0) {
dbmp->di_size--;
@@ -188,9 +191,9 @@ fdbm_shift(obj)
val = dbm_fetch(dbm, key);
dbm_delete(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- return assoc_new(keystr, valstr);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ return rb_assoc_new(keystr, valstr);
}
static VALUE
@@ -207,11 +210,11 @@ fdbm_delete_if(obj)
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- if (RTEST(rb_yield(assoc_new(keystr, valstr)))) {
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
if (dbm_delete(dbm, key)) {
- Fail("dbm_delete failed");
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
}
}
}
@@ -232,13 +235,72 @@ fdbm_clear(obj)
dbmp->di_size = -1;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
if (dbm_delete(dbm, key)) {
- Fail("dbm_delete failed");
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
}
}
return obj;
}
static VALUE
+fdbm_invert(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+ VALUE hash = rb_hash_new();
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_hash_aset(hash, valstr, keystr);
+ }
+ return obj;
+}
+
+static VALUE
+each_pair(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
+}
+
+static VALUE fdbm_store _((VALUE,VALUE,VALUE));
+
+static VALUE
+update_i(pair, dbm)
+ VALUE pair, dbm;
+{
+ Check_Type(pair, T_ARRAY);
+ if (RARRAY(pair)->len < 2) {
+ rb_raise(rb_eArgError, "pair must be [key, value]");
+ }
+ fdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
+ return Qnil;
+}
+
+static VALUE
+fdbm_update(obj, other)
+ VALUE obj, other;
+{
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fdbm_replace(obj, other)
+ VALUE obj, other;
+{
+ fdbm_clear(obj);
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
fdbm_store(obj, keystr, valstr)
VALUE obj, keystr, valstr;
{
@@ -252,14 +314,14 @@ fdbm_store(obj, keystr, valstr)
}
rb_secure(4);
- keystr = obj_as_string(keystr);
+ keystr = rb_obj_as_string(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
if (NIL_P(valstr)) return fdbm_delete(obj, keystr);
- valstr = obj_as_string(valstr);
+ valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -267,9 +329,11 @@ fdbm_store(obj, keystr, valstr)
dbmp->di_size = -1;
dbm = dbmp->di_dbm;
if (dbm_store(dbm, key, val, DBM_REPLACE)) {
+#ifdef HAVE_DBM_CLAERERR
dbm_clearerr(dbm);
- if (errno == EPERM) rb_sys_fail(Qnil);
- Fail("dbm_store failed");
+#endif
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eRuntimeError, "dbm_store failed");
}
return valstr;
@@ -316,8 +380,8 @@ fdbm_empty_p(obj)
else {
i = dbmp->di_size;
}
- if (i == 0) return TRUE;
- return FALSE;
+ if (i == 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -332,7 +396,7 @@ fdbm_each_value(obj)
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- rb_yield(str_taint(str_new(val.dptr, val.dsize)));
+ rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
}
return obj;
}
@@ -348,7 +412,7 @@ fdbm_each_key(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- rb_yield(str_taint(str_new(key.dptr, key.dsize)));
+ rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
}
return obj;
}
@@ -367,9 +431,9 @@ fdbm_each_pair(obj)
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- rb_yield(assoc_new(keystr, valstr));
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_yield(rb_assoc_new(keystr, valstr));
}
return obj;
@@ -387,9 +451,9 @@ fdbm_keys(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- ary_push(ary, str_taint(str_new(key.dptr, key.dsize)));
+ rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
}
return ary;
@@ -407,10 +471,10 @@ fdbm_values(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- ary_push(ary, str_taint(str_new(val.dptr, val.dsize)));
+ rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
}
return ary;
@@ -431,8 +495,8 @@ fdbm_has_key(obj, keystr)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
val = dbm_fetch(dbm, key);
- if (val.dptr) return TRUE;
- return FALSE;
+ if (val.dptr) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -453,9 +517,9 @@ fdbm_has_value(obj, valstr)
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -470,26 +534,29 @@ fdbm_to_a(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- ary_push(ary, assoc_new(str_taint(str_new(key.dptr, key.dsize)),
- str_taint(str_new(val.dptr, val.dsize))));
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize)));
}
return ary;
}
+void
Init_dbm()
{
- cDBM = rb_define_class("DBM", cObject);
- rb_include_module(cDBM, mEnumerable);
+ cDBM = rb_define_class("DBM", rb_cObject);
+ rb_include_module(cDBM, rb_mEnumerable);
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
+ rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1);
rb_define_method(cDBM, "close", fdbm_close, 0);
rb_define_method(cDBM, "[]", fdbm_fetch, 1);
rb_define_method(cDBM, "[]=", fdbm_store, 2);
- rb_define_method(cDBM, "indexes", fdbm_indexes, -2);
+ rb_define_method(cDBM, "indexes", fdbm_indexes, -1);
+ rb_define_method(cDBM, "indices", fdbm_indexes, -1);
rb_define_method(cDBM, "length", fdbm_length, 0);
rb_define_alias(cDBM, "size", "length");
rb_define_method(cDBM, "empty?", fdbm_empty_p, 0);
@@ -503,6 +570,10 @@ Init_dbm()
rb_define_method(cDBM, "delete", fdbm_delete, 1);
rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0);
rb_define_method(cDBM, "clear", fdbm_clear, 0);
+ rb_define_method(cDBM,"invert", fdbm_invert, 0);
+ rb_define_method(cDBM,"update", fdbm_update, 1);
+ rb_define_method(cDBM,"replace", fdbm_replace, 1);
+
rb_define_method(cDBM, "include?", fdbm_has_key, 1);
rb_define_method(cDBM, "has_key?", fdbm_has_key, 1);
rb_define_method(cDBM, "has_value?", fdbm_has_value, 1);
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
index 4a5d41f275..3a96cee12f 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -1,5 +1,9 @@
+require 'mkmf'
$LDFLAGS = "-L/usr/local/lib"
-have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open")
+have_library("gdbm", "dbm_open") or
+ have_library("db", "dbm_open") or
+ have_library("dbm", "dbm_open")
if have_func("dbm_open")
+ have_func("dbm_clearerr")
create_makefile("dbm")
end
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 20cd9295ed..c10680c7d3 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -37,7 +37,7 @@ etc_getlogin(obj)
#endif
if (login)
- return str_new2(login);
+ return rb_tainted_str_new2(login);
return Qnil;
}
@@ -47,34 +47,36 @@ setup_passwd(pwd)
struct passwd *pwd;
{
if (pwd == 0) rb_sys_fail("/etc/passwd");
- return struct_new(sPasswd,
- str_new2(pwd->pw_name),
- str_new2(pwd->pw_passwd),
- INT2FIX(pwd->pw_uid),
- INT2FIX(pwd->pw_gid),
- str_new2(pwd->pw_gecos),
- str_new2(pwd->pw_dir),
- str_new2(pwd->pw_shell),
+ return rb_struct_new(sPasswd,
+ rb_tainted_str_new2(pwd->pw_name),
+ rb_tainted_str_new2(pwd->pw_passwd),
+ INT2FIX(pwd->pw_uid),
+ INT2FIX(pwd->pw_gid),
+#ifdef PW_GECOS
+ rb_tainted_str_new2(pwd->pw_gecos),
+#endif
+ rb_tainted_str_new2(pwd->pw_dir),
+ rb_tainted_str_new2(pwd->pw_shell),
#ifdef PW_CHANGE
- INT2FIX(pwd->pw_change),
+ INT2FIX(pwd->pw_change),
#endif
#ifdef PW_QUOTA
- INT2FIX(pwd->pw_quota),
+ INT2FIX(pwd->pw_quota),
#endif
#ifdef PW_AGE
- INT2FIX(pwd->pw_age),
+ INT2FIX(pwd->pw_age),
#endif
#ifdef PW_CLASS
- str_new2(pwd->pw_class),
+ rb_tainted_str_new2(pwd->pw_class),
#endif
#ifdef PW_COMMENT
- str_new2(pwd->pw_comment),
+ rb_tainted_str_new2(pwd->pw_comment),
#endif
#ifdef PW_EXPIRE
- INT2FIX(pwd->pw_expire),
+ INT2FIX(pwd->pw_expire),
#endif
- 0 /*dummy*/
- );
+ 0 /*dummy*/
+ );
}
#endif
@@ -96,7 +98,7 @@ etc_getpwuid(argc, argv, obj)
uid = getuid();
}
pwd = getpwuid(uid);
- if (pwd == 0) Fail("can't find user for %d", uid);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", uid);
return setup_passwd(pwd);
#else
return Qnil;
@@ -112,7 +114,7 @@ etc_getpwnam(obj, nam)
Check_Type(nam, T_STRING);
pwd = getpwnam(RSTRING(nam)->ptr);
- if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING(nam)->ptr);
return setup_passwd(pwd);
#else
return Qnil;
@@ -123,10 +125,10 @@ static VALUE
etc_passwd(obj)
VALUE obj;
{
-#if defined(HAVE_GETPWENT) && !defined(__CYGWIN32__)
+#if defined(HAVE_GETPWENT)
struct passwd *pw;
- if (iterator_p()) {
+ if (rb_iterator_p()) {
setpwent();
while (pw = getpwent()) {
rb_yield(setup_passwd(pw));
@@ -135,7 +137,7 @@ etc_passwd(obj)
return obj;
}
pw = getpwent();
- if (pw == 0) Fail("can't fetch next -- /etc/passwd");
+ if (pw == 0) rb_raise(rb_eRuntimeError, "can't fetch next -- /etc/passwd");
return setup_passwd(pw);
#else
return Qnil;
@@ -150,17 +152,17 @@ setup_group(grp)
VALUE mem;
char **tbl;
- mem = ary_new();
+ mem = rb_ary_new();
tbl = grp->gr_mem;
while (*tbl) {
- ary_push(mem, str_new2(*tbl));
+ rb_ary_push(mem, rb_tainted_str_new2(*tbl));
tbl++;
}
- return struct_new(sGroup,
- str_new2(grp->gr_name),
- str_new2(grp->gr_passwd),
- INT2FIX(grp->gr_gid),
- mem);
+ return rb_struct_new(sGroup,
+ rb_tainted_str_new2(grp->gr_name),
+ rb_tainted_str_new2(grp->gr_passwd),
+ INT2FIX(grp->gr_gid),
+ mem);
}
#endif
@@ -174,7 +176,7 @@ etc_getgrgid(obj, id)
gid = NUM2INT(id);
grp = getgrgid(gid);
- if (grp == 0) Fail("can't find group for %d", gid);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid);
return setup_group(grp);
#else
return Qnil;
@@ -190,7 +192,7 @@ etc_getgrnam(obj, nam)
Check_Type(nam, T_STRING);
grp = getgrnam(RSTRING(nam)->ptr);
- if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %s", RSTRING(nam)->ptr);
return setup_group(grp);
#else
return Qnil;
@@ -204,7 +206,7 @@ etc_group(obj)
#ifdef HAVE_GETGRENT
struct group *grp;
- if (iterator_p()) {
+ if (rb_iterator_p()) {
setgrent();
while (grp = getgrent()) {
rb_yield(setup_group(grp));
@@ -235,32 +237,35 @@ Init_etc()
rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1);
rb_define_module_function(mEtc, "group", etc_group, 0);
- sPasswd = struct_define("Passwd",
- "name", "passwd", "uid", "gid",
- "gecos", "dir", "shell",
+ sPasswd = rb_struct_define("Passwd",
+ "name", "passwd", "uid", "gid",
+#ifdef PW_GECOS
+ "gecos",
+#endif
+ "dir", "shell",
#ifdef PW_CHANGE
- "change",
+ "change",
#endif
#ifdef PW_QUOTA
- "quota",
+ "quota",
#endif
#ifdef PW_AGE
- "age",
+ "age",
#endif
#ifdef PW_CLASS
- "class",
+ "class",
#endif
#ifdef PW_COMMENT
- "comment",
+ "comment",
#endif
#ifdef PW_EXPIRE
- "expire",
+ "expire",
#endif
- 0);
+ 0);
rb_global_variable(&sPasswd);
#ifdef HAVE_GETGRENT
- sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0);
+ sGroup = rb_struct_define("Group", "name", "passwd", "gid", "mem", 0);
rb_global_variable(&sGroup);
#endif
}
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 884de93ec8..4cf04a3ec3 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -1,7 +1,31 @@
+require 'mkmf'
+
+def etc_grep_header(field)
+ f = open("conftest.c", "w")
+ f.print <<EOF
+#include <pwd.h>
+EOF
+ f.close
+ begin
+ if xsystem("#{CPP} | egrep #{field}")
+ $defs.push(format("-D%s", field.upcase))
+ end
+ ensure
+ system "rm -f conftest.c"
+ end
+end
+
have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4
a = have_func("getlogin")
b = have_func("getpwent")
c = have_func("getgrent")
if a or b or c
+ etc_grep_header("pw_gecos")
+ etc_grep_header("pw_change")
+ etc_grep_header("pw_quota")
+ etc_grep_header("pw_age")
+ etc_grep_header("pw_class")
+ etc_grep_header("pw_comment")
+ etc_grep_header("pw_expire")
create_makefile("etc")
end
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index e1d318d19c..058c144f94 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -1,12 +1,14 @@
#! /usr/local/bin/ruby
-$".push 'mkmf.rb'
+$".push 'mkmf.rb' #"
+load '@top_srcdir@/lib/find.rb'
if ARGV[0] == 'static'
$force_static = TRUE
ARGV.shift
elsif ARGV[0] == 'install'
$install = TRUE
+ $destdir = ARGV[1] || ''
ARGV.shift
elsif ARGV[0] == 'clean'
$clean = TRUE
@@ -19,8 +21,16 @@ $cache_mod = FALSE;
$lib_cache = {}
$func_cache = {}
$hdr_cache = {}
-$topdir = "@top_srcdir@"
-if $topdir !~ "^/"
+$top_srcdir = "@top_srcdir@"
+if $top_srcdir !~ "^/"
+ # get absolute path
+ save = Dir.pwd
+ Dir.chdir $top_srcdir
+ $top_srcdir = Dir.pwd
+ Dir.chdir save
+end
+$topdir = ".."
+if $topdir !~ "^/"
# get absolute path
save = Dir.pwd
Dir.chdir $topdir
@@ -59,23 +69,59 @@ end
if PLATFORM == "m68k-human"
CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
-LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c @LIBS@ %s > nul 2>&1"
-CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c > nul 2>&1"
else
CFLAGS = "@CFLAGS@"
-LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c %s > /dev/null 2>&1"
-CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c > /dev/null 2>&1"
+end
+LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s @LDFLAGS@ %s conftest.c @LIBS@ %s"
+CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s conftest.c"
+
+if /cygwin|mswin32|djgpp|mingw32|m68k-human/i =~ PLATFORM
+ $null = open("nul", "w")
+else
+ $null = open("/dev/null", "w")
+end
+
+$orgerr = $stderr.dup
+$orgout = $stdout.dup
+def xsystem command
+ if $DEBUG
+ return system(command)
+ end
+ $stderr.reopen($null)
+ $stdout.reopen($null)
+ r = system(command)
+ $stderr.reopen($orgerr)
+ $stdout.reopen($orgout)
+ return r
end
def try_link(libs)
- system(format(LINK, $CFLAGS, $LDFLAGS, libs))
+ xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs))
end
def try_cpp
- system(format(CPP, $CFLAGS))
+ xsystem(format(CPP, $CFLAGS))
+end
+
+def install_rb(mfile)
+ path = []
+ dir = []
+ Find.find("lib") do |f|
+ next unless /\.rb$/ =~ f
+ f = f[4..-1]
+ path.push f
+ dir |= File.dirname(f)
+ end
+ for f in dir
+ next if f == "."
+ mfile.printf "\t@test -d $(DESTDIR)$(pkglibdir)/%s || mkdir $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ end
+ for f in path
+ mfile.printf "\t$(INSTALL_DATA) lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ end
end
-def have_library(lib, func)
+def have_library(lib, func="main")
if $lib_cache[lib]
if $lib_cache[lib] == "yes"
if $libs
@@ -89,26 +135,34 @@ def have_library(lib, func)
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
+ if func && func != ""
+ cfile = open("conftest.c", "w")
+ cfile.printf "\
int main() { return 0; }
int t() { %s(); return 0; }
", func
- cfile.close
+ cfile.close
- begin
+ begin
+ if $libs
+ libs = "-l" + lib + " " + $libs
+ else
+ libs = "-l" + lib
+ end
+ unless try_link(libs)
+ $lib_cache[lib] = 'no'
+ $cache_mod = TRUE
+ return FALSE
+ end
+ ensure
+ system "rm -f conftest*"
+ end
+ else
if $libs
libs = "-l" + lib + " " + $libs
else
libs = "-l" + lib
end
- unless try_link(libs)
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
end
$libs = libs
@@ -206,9 +260,19 @@ def create_makefile(target)
end
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end
- $libs = "" unless $libs
- $srcdir = $topdir + "/ext/" + target
+ $DLDFLAGS = '@DLDFLAGS@'
+
+ if PLATFORM =~ /beos/
+ if $libs
+ $libs = $libs + " -lruby"
+ else
+ $libs = "-lruby"
+ end
+ $DLDFLAGS = $DLDFLAGS + " -L" + $topdir
+ end
+
+ $srcdir = $top_srcdir + "/ext/" + target
mfile = open("Makefile", "w")
mfile.printf "\
SHELL = /bin/sh
@@ -222,10 +286,11 @@ hdrdir = #{$topdir}
CC = @CC@
-CFLAGS = %s -I#{$topdir} %s #$CFLAGS %s
-DLDFLAGS = @DLDFLAGS@ #$LDFLAGS
+prefix = @prefix@
+CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s
+DLDFLAGS = #$DLDFLAGS @LDFLAGS@ #$LDFLAGS
LDSHARED = @LDSHARED@
-", if $static then "" else "@CCDLFLAGS@" end, CFLAGS, $defs.join(" ")
+", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
mfile.printf "\
@@ -234,18 +299,20 @@ RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t`
prefix = @prefix@
exec_prefix = @exec_prefix@
-libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@
+libdir = @libdir@
+pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)
+archdir = $(pkglibdir)/@arch@
@SET_MAKE@
#### End of system configuration section. ####
"
- mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs
+ mfile.printf "LOCAL_LIBS = %s\n", $local_libs unless $local_libs == ""
mfile.printf "LIBS = %s\n", $libs
mfile.printf "OBJS = "
if !$objs then
$objs = []
- for f in Dir["#{$topdir}/ext/#{target}/*.{c,cc}"]
+ for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{c,cc}"]
f = File.basename(f)
f.sub!(/\.(c|cc)$/, ".o")
$objs.push f
@@ -254,42 +321,48 @@ libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@
mfile.printf $objs.join(" ")
mfile.printf "\n"
- mfile.printf "\
-TARGET = %s.%s
+ mfile.printf <<EOS
+TARGET = #{target}.#{$static ? "a" : "@DLEXT@"}
-INSTALL = %s@INSTALL@
+INSTALL = #{$dots}@INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
binsuffix = @binsuffix@
all: $(TARGET)
-clean:; @rm -f *.o *.so *.sl
+clean:; @rm -f *.o *.a *.so *.sl
@rm -f Makefile extconf.h conftest.*
@rm -f core ruby$(binsuffix) *~
realclean: clean
-", target,
- if $static then "o" else "@DLEXT@" end, $dots
+EOS
- mfile.printf "\
+ mfile.printf <<EOS
install:
-"
+ @test -d $(DESTDIR)$(libdir) || mkdir $(DESTDIR)$(libdir)
+ @test -d $(DESTDIR)$(pkglibdir) || mkdir $(DESTDIR)$(pkglibdir)
+ @test -d $(DESTDIR)$(archdir) || mkdir $(DESTDIR)$(archdir)
+EOS
if !$static
- mfile.printf "
- @test -d $(libdir) || mkdir $(libdir)
- $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
+ mfile.printf "\
+ $(INSTALL) $(TARGET) $(DESTDIR)$(archdir)/$(TARGET)
"
end
- for rb in Dir["lib/*.rb"]
- mfile.printf "\t$(INSTALL) %s @libdir@/$(RUBY_INSTALL_NAME)\n", rb
- end
+ install_rb(mfile)
mfile.printf "\n"
- if !$static && "@DLEXT@" != "o"
+ if $static
+ mfile.printf "\
+$(TARGET): $(OBJS)
+ @AR@ cru $(TARGET) $(OBJS)
+ @-@RANLIB@ $(TARGET) 2> /dev/null || true
+"
+ elsif "@DLEXT@" != "o"
mfile.printf "\
$(TARGET): $(OBJS)
- $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS)
+ $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS)
"
elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
if PLATFORM == "m68k-human"
@@ -297,16 +370,11 @@ $(TARGET): $(OBJS)
$(TARGET): $(OBJS)
ar cru $(TARGET) $(OBJS)
"
- elsif PLATFORM =~ "-nextstep"
+ elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
mfile.printf "\
$(TARGET): $(OBJS)
cc -r $(CFLAGS) -o $(TARGET) $(OBJS)
"
- elsif $static
- mfile.printf "\
-$(TARGET): $(OBJS)
- ld -r -o $(TARGET) $(OBJS)
-"
else
mfile.printf "\
$(TARGET): $(OBJS)
@@ -324,6 +392,19 @@ $(TARGET): $(OBJS)
dfile.close
end
mfile.close
+
+ if PLATFORM =~ /beos/
+ if PLATFORM =~ /^powerpc/ then
+ deffilename = "ruby.exp"
+ else
+ deffilename = "ruby.def"
+ end
+ print "creating ruby.def\n"
+ open(deffilename, "w") do |file|
+ file.print("EXPORTS\n") if PLATFORM =~ /^i/
+ file.print("Init_#{target}\n")
+ end
+ end
end
def extmake(target)
@@ -335,24 +416,25 @@ def extmake(target)
return if $nodynamic and not $static
- $local_libs = nil
- $libs = nil
$objs = nil
- $CFLAGS = nil
- $LDFLAGS = nil
+ $libs = PLATFORM =~ /cygwin|beos|openstep|nextstep|rhapsody/ ? nil : "-lc"
+ $local_libs = "" # to be assigned in extconf.rb
+ $CFLAGS = ""
+ $LDFLAGS = ""
begin
- system "mkdir " + target unless File.directory?(target)
+ system "mkdir", target unless File.directory?(target)
Dir.chdir target
+ $mdir = target
if $static_ext.size > 0 ||
!File.exist?("./Makefile") ||
- older("./Makefile", "#{$topdir}/ext/@setup@") ||
+ older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
older("./Makefile", "../extmk.rb") ||
- older("./Makefile", "#{$topdir}/ext/#{target}/extconf.rb")
+ older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
then
$defs = []
- if File.exist?("#{$topdir}/ext/#{target}/extconf.rb")
- load "#{$topdir}/ext/#{target}/extconf.rb"
+ if File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
+ load "#{$top_srcdir}/ext/#{target}/extconf.rb"
else
create_makefile(target);
end
@@ -362,7 +444,7 @@ def extmake(target)
$extlist.push [$static,target]
end
if $install
- system "make install"
+ system "make install DESTDIR=#{$destdir}"
elsif $clean
system "make clean"
else
@@ -370,9 +452,10 @@ def extmake(target)
end
end
if $static
- $extlibs += " " + $LDFLAGS if $LDFLAGS
- $extlibs += " " + $local_libs if $local_libs
+ $extlibs ||= ""
+ $extlibs += " " + $LDFLAGS unless $LDFLAGS == ""
$extlibs += " " + $libs if $libs
+ $extlibs += " " + $local_libs unless $local_libs == ""
end
ensure
Dir.chdir ".."
@@ -381,11 +464,11 @@ end
# get static-link modules
$static_ext = {}
-for setup in ["@setup@", "#{$topdir}/ext/@setup@"]
+for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
if File.file? setup
f = open(setup)
while f.gets()
- $_.chop!
+ $_.chomp!
sub!(/#.*$/, '')
next if /^\s*$/
if /^option +nodynamic/
@@ -399,7 +482,7 @@ for setup in ["@setup@", "#{$topdir}/ext/@setup@"]
end
end
-for d in Dir["#{$topdir}/ext/*"]
+for d in Dir["#{$top_srcdir}/ext/*"]
File.directory?(d) || next
File.file?(d + "/MANIFEST") || next
@@ -429,15 +512,16 @@ if $cache_mod
end
exit if $install or $clean
-$extinit += ""
+$extinit = "" unless $extinit
if $extlist.size > 0
for s,t in $extlist
- f = format("%s/%s.o", s, t)
+ f = format("%s/%s.a", s, t)
if File.exist?(f)
$extinit += format("\
\tInit_%s();\n\
\trb_provide(\"%s.o\");\n\
", t, t)
+ $extobjs = "" unless $extobjs
$extobjs += "ext/"
$extobjs += f
$extobjs += " "
@@ -446,7 +530,7 @@ if $extlist.size > 0
end
end
- if older("extinit.c", "#{$topdir}/ext/@setup@")
+ if older("extinit.c", "#{$top_srcdir}/ext/@setup@")
f = open("extinit.c", "w")
f.printf "void Init_ext() {\n"
f.printf $extinit
@@ -461,17 +545,24 @@ if $extlist.size > 0
Dir.chdir ".."
- if older("ruby@binsuffix@", "#{$topdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@")
+ if older("ruby@binsuffix@", "#{$top_srcdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@")
`rm -f ruby@binsuffix@`
end
- $extobjs = "ext/extinit.o " + $extobjs
+ if $extobjs
+ $extobjs = "ext/extinit.o " + $extobjs
+ else
+ $extobjs = "ext/extinit.o "
+ end
+ if PLATFORM =~ /m68k-human|beos/
+ $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
+ end
system format('make ruby@binsuffix@ EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
else
Dir.chdir ".."
if older("ruby@binsuffix@", "miniruby@binsuffix@")
`rm -f ruby@binsuffix@`
- `cp miniruby@binsuffix@ ruby@binsuffix@`
+ system("make ruby@binsuffix@")
end
end
diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt
index 6792f2717b..5836e5c681 100644
--- a/ext/extmk.rb.nt
+++ b/ext/extmk.rb.nt
@@ -1,5 +1,7 @@
#! /usr/local/bin/ruby
+$".push 'mkmf.rb' #"
+
if ARGV[0] == 'static'
$force_static = TRUE
ARGV.shift
@@ -379,7 +381,7 @@ def extmake(target)
end
end
if $static
- #$extlibs = " "
+ $extlibs = " "
$extlibs += " " + $LDFLAGS if $LDFLAGS
$extlibs += " " + $local_libs if $local_libs
$extlibs += " " + $libs if $libs
@@ -438,6 +440,8 @@ if $cache_mod
end
exit if $install or $clean
+$extinit = " " unless $extinit
+$extobjs = ""
if $extlist.size > 0
for s,t in $extlist
#for s,t in $static_ext
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 17aacb13c3..186f9ac893 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -5,7 +5,7 @@
$Author$
created at: Mon Apr 7 18:53:05 JST 1997
- Copyright (C) 1997 Yukihiro Matsumoto
+ Copyright (C) 1997-1998 Yukihiro Matsumoto
************************************************/
diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c
index 6778afcfe6..a3349826f1 100644
--- a/ext/kconv/kconv.c
+++ b/ext/kconv/kconv.c
@@ -1780,12 +1780,30 @@ kconv_kconv(argc, argv)
VALUE src, dst;
VALUE in, out;
int in_code, out_code;
+ char *codename = 0;
rb_scan_args(argc, argv, "12", &src, &out, &in);
Check_Type(src, T_STRING);
if (NIL_P(out)) {
- out_code = _JIS;
+ codename = rb_get_kcode();
+ goto codeselect;
+ }
+ else if (TYPE(out) == T_STRING) {
+ codename = RSTRING(out)->ptr;
+ codeselect:
+ switch (codename[0]) {
+ case 'E': case 'e':
+ out_code = _EUC;
+ break;
+ case 'S': case 's':
+ out_code = _SJIS;
+ break;
+ case 'J': case 'j':
+ default:
+ out_code = _JIS;
+ break;
+ }
}
else {
out_code = NUM2INT(out);
@@ -1794,12 +1812,28 @@ kconv_kconv(argc, argv)
if (NIL_P(in)) {
in_code = _AUTO;
}
+ else if (TYPE(in) == T_STRING) {
+ switch (RSTRING(in)->ptr[0]) {
+ case 'E': case 'e':
+ in_code = _EUC;
+ break;
+ case 'S': case 's':
+ in_code = _SJIS;
+ break;
+ case 'J': case 'j':
+ in_code = _JIS;
+ break;
+ default:
+ in_code = _AUTO;
+ break;
+ }
+ }
else {
in_code = NUM2INT(in);
if (in_code == _NOCONV) return (VALUE)src;
}
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
+ dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, out_code, in_code);
return dst;
@@ -1813,7 +1847,7 @@ kconv_tojis(obj, src)
Check_Type(src, T_STRING);
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
+ dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _JIS, _AUTO);
return dst;
@@ -1827,7 +1861,7 @@ kconv_toeuc(obj, src)
Check_Type(src, T_STRING);
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
+ dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _EUC, _AUTO);
return (VALUE)dst;
@@ -1841,7 +1875,7 @@ kconv_tosjis(obj, src)
Check_Type(src, T_STRING);
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
+ dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _SJIS, _AUTO);
return dst;
@@ -1857,10 +1891,29 @@ static VALUE
kconv_guess(obj, src)
VALUE obj, src;
{
- unsigned char *p = RSTRING(src)->ptr;
- unsigned char *pend = p + RSTRING(src)->len;
+ unsigned char *p;
+ unsigned char *pend;
+ int sequence_counter = 0;
+
+ Check_Type(src, T_STRING);
+
+ p = RSTRING(src)->ptr;
+ pend = p + RSTRING(src)->len;
+
+#define INCR do {\
+ p++;\
+ if (p==pend) return INT2FIX(_UNKNOWN);\
+ sequence_counter++;\
+ if (sequence_counter % 2 == 1 && *p != 0xa4)\
+ sequence_counter = 0;\
+ if (6 <= sequence_counter) {\
+ sequence_counter = 0;\
+ return INT2FIX(_EUC);\
+ }\
+} while (0)
-#define INCR {p++;if (p==pend) return INT2FIX(_UNKNOWN);}
+ if (*p == 0xa4)
+ sequence_counter = 1;
while (p<pend) {
if (*p == '\033') {
@@ -1874,37 +1927,41 @@ kconv_guess(obj, src)
if (0x81 <= *p && *p <= 0x8d) {
return INT2FIX(_SJIS);
}
- if (*p == 0x8e) {
+ if (0x8f <= *p && *p <= 0x9f) {
+ return INT2FIX(_SJIS);
+ }
+ if (*p == 0x8e) { /* SS2 */
INCR;
if ((0x40 <= *p && *p <= 0x7e) ||
(0x80 <= *p && *p <= 0xa0) ||
(0xe0 <= *p && *p <= 0xfc))
return INT2FIX(_SJIS);
}
- if (0xa1 <= *p && *p <= 0xdf) {
+ else if (0xa1 <= *p && *p <= 0xdf) {
INCR;
if (0xf0 <= *p && *p <= 0xfe)
return INT2FIX(_EUC);
if (0xe0 <= *p && *p <= 0xef) {
- while (*p >= 0x40) {
+ while (p < pend && *p >= 0x40) {
if (*p >= 0x81) {
- if (0x8d <= *p || (0x8f <= *p && *p <= 0x9f)) {
+ if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
return INT2FIX(_SJIS);
}
else if (0xfd <= *p && *p <= 0xfe) {
return INT2FIX(_EUC);
}
}
+ INCR;
}
}
- if (*p <= 0x9f) {
+ else if (*p <= 0x9f) {
return INT2FIX(_SJIS);
}
}
- if (0xf0 <= *p && *p <= 0xfe) {
+ else if (0xf0 <= *p && *p <= 0xfe) {
return INT2FIX(_EUC);
}
- if (0xe0 <= *p && *p <= 0xef) {
+ else if (0xe0 <= *p && *p <= 0xef) {
INCR;
if ((0x40 <= *p && *p <= 0x7e) ||
(0x80 <= *p && *p <= 0xa0)) {
@@ -1914,7 +1971,7 @@ kconv_guess(obj, src)
return INT2FIX(_EUC);
}
}
- p++;
+ INCR;
}
return INT2FIX(_UNKNOWN);
}
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
index 47f913792f..a825f96d47 100644
--- a/ext/md5/md5init.c
+++ b/ext/md5/md5init.c
@@ -5,7 +5,7 @@
$Author$
created at: Fri Aug 2 09:24:12 JST 1996
- Copyright (C) 1995 Yukihiro Matsumoto
+ Copyright (C) 1995-1998 Yukihiro Matsumoto
************************************************/
/* This module provides an interface to the RSA Data Security,
@@ -42,7 +42,7 @@ md5_digest(obj)
ctx = *md5;
MD5Final(digest, &ctx);
- return str_new(digest, 16);
+ return rb_str_new(digest, 16);
}
static VALUE
@@ -53,7 +53,7 @@ md5_clone(obj)
MD5_CTX *md5, *md5_new;
Data_Get_Struct(obj, MD5_CTX, md5);
- obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new);
+ obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, free, md5_new);
*md5_new = *md5;
return obj;
@@ -61,6 +61,9 @@ md5_clone(obj)
static VALUE
md5_new(argc, argv, class)
+ int argc;
+ VALUE* argv;
+ VALUE class;
{
int i;
VALUE arg, obj;
@@ -69,18 +72,19 @@ md5_new(argc, argv, class)
rb_scan_args(argc, argv, "01", &arg);
if (!NIL_P(arg)) Check_Type(arg, T_STRING);
- obj = Data_Make_Struct(class, MD5_CTX, 0, 0, md5);
+ obj = Data_Make_Struct(class, MD5_CTX, 0, free, md5);
MD5Init(md5);
if (!NIL_P(arg)) {
md5_update(obj, arg);
}
+ rb_obj_call_init(obj);
return obj;
}
Init_md5()
{
- cMD5 = rb_define_class("MD5", cObject);
+ cMD5 = rb_define_class("MD5", rb_cObject);
rb_define_singleton_method(cMD5, "new", md5_new, -1);
diff --git a/ext/socket/depend b/ext/socket/depend
index 3d54fa073c..6e8c3b7d97 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -1 +1 @@
-socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/io.h $(hdrdir)/sig.h
+socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index f719723864..449d5a2785 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -1,18 +1,22 @@
-$LDFLAGS = "-L/usr/local/lib"
+require 'mkmf'
+$LDFLAGS = "-L/usr/local/lib" if File.directory?("/usr/local/lib")
case PLATFORM
when /mswin32/
test_func = "WSACleanup"
have_library("wsock32", "WSACleanup")
when /cygwin32/
- test_func = "cygwin32_socket"
+ test_func = "socket"
+when /beos/
+ test_func = "socket"
+ have_library("net", "socket")
else
test_func = "socket"
+ have_library("nsl", "t_open")
have_library("socket", "socket")
- have_library("inet", "gethostbyname")
- have_library("nsl", "gethostbyname")
end
have_header("sys/un.h")
if have_func(test_func)
+ have_func("inet_aton")
have_func("hsterror")
unless have_func("gethostname")
have_func("uname")
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index f5d191b056..e9bdbc9e8c 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -9,7 +9,8 @@
************************************************/
#include "ruby.h"
-#include "io.h"
+#include "rubyio.h"
+#include "rubysig.h"
#include <stdio.h>
#include <sys/types.h>
#ifndef NT
@@ -22,7 +23,14 @@
#include <sys/un.h>
#endif
-#if defined(THREAD) && defined(HAVE_FCNTL)
+#ifdef USE_CWGUSI
+extern int fileno(FILE *stream); /* <unix.mac.h> */
+extern int rb_thread_select(int, fd_set*, fd_set*, fd_set*, struct timeval*); /* thread.c */
+# include <sys/errno.h>
+# include <GUSI.h>
+#endif
+
+#if defined(USE_THREAD) && defined(HAVE_FCNTL)
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -34,30 +42,25 @@
#define EWOULDBLOCK EAGAIN
#endif
-extern VALUE cIO;
-extern VALUE cInteger;
-
-VALUE cBasicSocket;
-VALUE cIPsocket;
-VALUE cTCPsocket;
-VALUE cTCPserver;
-VALUE cUDPsocket;
+VALUE rb_cBasicSocket;
+VALUE rb_cIPsocket;
+VALUE rb_cTCPsocket;
+VALUE rb_cTCPserver;
+VALUE rb_cUDPsocket;
#ifdef AF_UNIX
-VALUE cUNIXsocket;
-VALUE cUNIXserver;
+VALUE rb_cUNIXsocket;
+VALUE rb_cUNIXserver;
#endif
-VALUE cSocket;
+VALUE rb_cSocket;
-extern VALUE eException;
-static VALUE eSocket;
+static VALUE rb_eSocket;
#ifdef SOCKS
-VALUE cSOCKSsocket;
+VALUE rb_cSOCKSsocket;
void SOCKSinit();
int Rconnect();
#endif
-FILE *rb_fdopen();
char *strdup();
#define INET_CLIENT 0
@@ -69,9 +72,12 @@ static void
sock_finalize(fptr)
OpenFile *fptr;
{
- SOCKET s = fileno(fptr->f);
+ SOCKET s;
+
+ if (!fptr->f) return;
+ s = fileno(fptr->f);
free(fptr->f);
- free(fptr->f2);
+ if (fptr->f2) free(fptr->f2);
closesocket(s);
}
#endif
@@ -85,6 +91,7 @@ sock_new(class, fd)
NEWOBJ(sock, struct RFile);
OBJSETUP(sock, class, T_FILE);
+ rb_secure(4);
MakeOpenFile(sock, fp);
fp->f = rb_fdopen(fd, "r");
#ifdef NT
@@ -92,7 +99,8 @@ sock_new(class, fd)
#endif
fp->f2 = rb_fdopen(fd, "w");
fp->mode = FMODE_READWRITE;
- io_unbuffered(fp);
+ rb_io_unbuffered(fp);
+ rb_obj_call_init((VALUE)sock);
return (VALUE)sock;
}
@@ -107,12 +115,15 @@ bsock_shutdown(argc, argv, sock)
int how;
OpenFile *fptr;
+ rb_secure(4);
rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil)
how = 2;
else {
how = NUM2INT(howto);
- if (how < 0 && how > 2) how = 2;
+ if (how < 0 || 2 < how) {
+ rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
+ }
}
GetOpenFile(sock, fptr);
if (shutdown(fileno(fptr->f), how) == -1)
@@ -122,9 +133,57 @@ bsock_shutdown(argc, argv, sock)
}
static VALUE
+bsock_close_read(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ rb_secure(4);
+ GetOpenFile(sock, fptr);
+ if (fptr->f2 == 0) {
+ return rb_io_close(sock);
+ }
+ if (shutdown(fileno(fptr->f), 0) == -1)
+ rb_sys_fail(0);
+ fptr->mode &= ~FMODE_READABLE;
+#ifdef NT
+ free(fptr->f);
+#else
+ fclose(fptr->f);
+#endif
+ fptr->f = fptr->f2;
+ fptr->f2 = 0;
+
+ return Qnil;
+}
+
+static VALUE
+bsock_close_write(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ rb_secure(4);
+ GetOpenFile(sock, fptr);
+ if (fptr->f2 == 0) {
+ return rb_io_close(sock);
+ }
+ if (shutdown(fileno(fptr->f), 1) == -1)
+ rb_sys_fail(0);
+ fptr->mode &= ~FMODE_WRITABLE;
+#ifdef NT
+ free(fptr->f2);
+#else
+ fclose(fptr->f2);
+#endif
+ fptr->f2 = 0;
+
+ return Qnil;
+}
+
+static VALUE
bsock_setsockopt(sock, lev, optname, val)
- VALUE sock, lev, optname;
- struct RString *val;
+ VALUE sock, lev, optname, val;
{
int level, option;
OpenFile *fptr;
@@ -148,8 +207,7 @@ bsock_setsockopt(sock, lev, optname, val)
v = (char*)&i; vlen = sizeof(i);
break;
default:
- Check_Type(val, T_STRING);
- v = val->ptr; vlen = val->len;
+ v = rb_str2cstr(val, &vlen);
}
GetOpenFile(sock, fptr);
@@ -163,6 +221,7 @@ static VALUE
bsock_getsockopt(sock, lev, optname)
VALUE sock, lev, optname;
{
+#if !defined(__BEOS__)
int level, option, len;
char *buf;
OpenFile *fptr;
@@ -176,7 +235,10 @@ bsock_getsockopt(sock, lev, optname)
if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
rb_sys_fail(fptr->path);
- return str_new(buf, len);
+ return rb_str_new(buf, len);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -190,7 +252,7 @@ bsock_getsockname(sock)
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getsockname(2)");
- return str_new(buf, len);
+ return rb_str_new(buf, len);
}
static VALUE
@@ -204,7 +266,7 @@ bsock_getpeername(sock)
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getpeername(2)");
- return str_new(buf, len);
+ return rb_str_new(buf, len);
}
static VALUE
@@ -213,31 +275,32 @@ bsock_send(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
- struct RString *msg, *to;
+ VALUE msg, to;
VALUE flags;
OpenFile *fptr;
FILE *f;
int fd, n;
+ char *m, *t;
+ int mlen, tlen;
rb_secure(4);
rb_scan_args(argc, argv, "21", &msg, &flags, &to);
- Check_Type(msg, T_STRING);
-
GetOpenFile(sock, fptr);
- f = fptr->f2?fptr->f2:fptr->f;
+ f = GetWriteFile(fptr);
fd = fileno(f);
retry:
-#ifdef THREAD
- thread_fd_writable(fd);
+#ifdef USE_THREAD
+ rb_thread_fd_writable(fd);
#endif
+ m = rb_str2cstr(msg, &mlen);
if (RTEST(to)) {
- Check_Type(to, T_STRING);
- n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags),
- (struct sockaddr*)to->ptr, to->len);
+ t = rb_str2cstr(to, &tlen);
+ n = sendto(fd, m, mlen, NUM2INT(flags),
+ (struct sockaddr*)t, tlen);
}
else {
- n = send(fd, msg->ptr, msg->len, NUM2INT(flags));
+ n = send(fd, m, mlen, NUM2INT(flags));
}
if (n < 0) {
switch (errno) {
@@ -246,8 +309,8 @@ bsock_send(argc, argv, sock)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
@@ -277,7 +340,6 @@ s_recv(sock, argc, argv, from)
enum sock_recv_type from;
{
OpenFile *fptr;
- FILE f;
VALUE str;
char buf[1024];
int fd, alen = sizeof buf;
@@ -289,12 +351,12 @@ s_recv(sock, argc, argv, from)
if (flg == Qnil) flags = 0;
else flags = NUM2INT(flg);
- str = str_new(0, NUM2INT(len));
+ str = rb_str_new(0, NUM2INT(len));
GetOpenFile(sock, fptr);
fd = fileno(fptr->f);
-#ifdef THREAD
- thread_wait_fd(fd);
+#ifdef USE_THREAD
+ rb_thread_wait_fd(fd);
#endif
TRAP_BEG;
retry:
@@ -309,38 +371,35 @@ s_recv(sock, argc, argv, from)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
rb_sys_fail("recvfrom(2)");
}
- str_taint(str);
+ rb_obj_taint(str);
switch (from) {
case RECV_RECV:
return (VALUE)str;
case RECV_TCP:
if (alen != sizeof(struct sockaddr_in)) {
- TypeError("sockaddr size differs - should not happen");
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
- return assoc_new(str, ipaddr((struct sockaddr_in *)buf));
+ return rb_assoc_new(str, ipaddr((struct sockaddr_in *)buf));
case RECV_UDP:
{
VALUE addr = ipaddr((struct sockaddr_in *)buf);
- return assoc_new(str, assoc_new(RARRAY(addr)->ptr[2],
- RARRAY(addr)->ptr[1]));
+ return rb_assoc_new(str, rb_assoc_new(RARRAY(addr)->ptr[2],
+ RARRAY(addr)->ptr[1]));
}
#ifdef HAVE_SYS_UN_H
case RECV_UNIX:
- if (alen != sizeof(struct sockaddr_un)) {
- TypeError("sockaddr size differs - should not happen");
- }
- return assoc_new(str, unixaddr((struct sockaddr_un *)buf));
+ return rb_assoc_new(str, unixaddr((struct sockaddr_un *)buf));
#endif
case RECV_SOCKET:
- return assoc_new(str, str_new(buf, alen));
+ return rb_assoc_new(str, rb_str_new(buf, alen));
}
}
@@ -353,7 +412,96 @@ bsock_recv(argc, argv, sock)
return s_recv(sock, argc, argv, RECV_RECV);
}
-#if defined(THREAD) && defined(HAVE_FCNTL)
+static VALUE
+mkipaddr(x)
+ unsigned long x;
+{
+ char buf[16];
+
+ x = ntohl(x);
+ sprintf(buf, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+ return rb_str_new2(buf);
+}
+
+static VALUE
+ipaddr(sockaddr)
+ struct sockaddr_in *sockaddr;
+{
+ VALUE family, port, addr1, addr2;
+ VALUE ary;
+ struct hostent *hostent;
+
+ family = rb_str_new2("AF_INET");
+ hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
+ sizeof(sockaddr->sin_addr),
+ AF_INET);
+ addr1 = 0;
+ if (hostent) {
+ addr1 = rb_str_new2(hostent->h_name);
+ }
+ addr2 = mkipaddr(sockaddr->sin_addr.s_addr);
+ if (!addr1) addr1 = addr2;
+
+ port = INT2FIX(ntohs(sockaddr->sin_port));
+ ary = rb_ary_new3(4, family, port, addr1, addr2);
+
+ return ary;
+}
+
+#ifndef HAVE_INET_ATON
+static unsigned long
+inet_aton(host, inp)
+ char *host;
+ struct in_addr *inp;
+{
+ int d1, d2, d3, d4;
+ char ch;
+
+ if (sscanf(host, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ inp->s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+static void
+setipaddr(name, addr)
+ char *name;
+ struct sockaddr_in *addr;
+{
+ struct hostent *hp;
+
+ if (name[0] == 0) {
+ addr->sin_addr.s_addr = INADDR_ANY;
+ }
+ else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
+ addr->sin_addr.s_addr = INADDR_BROADCAST;
+ }
+ else if (inet_aton(name, &addr->sin_addr) != 0) {
+ /* ok to set addr->sin_addr */
+ }
+ else {
+ hp = gethostbyname(name);
+ if (!hp) {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
+#else
+ rb_raise(rb_eSocket, "host not found");
+#endif
+ }
+ memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
+ }
+}
+
+#if defined(USE_THREAD) && defined(HAVE_FCNTL)
static int
thread_connect(fd, sockaddr, len, type)
int fd;
@@ -396,7 +544,7 @@ thread_connect(fd, sockaddr, len, type)
#endif
FD_ZERO(&fds);
FD_SET(fd, &fds);
- thread_select(fd+1, 0, &fds, 0, 0, 0);
+ rb_thread_select(fd+1, 0, &fds, 0, 0);
continue;
#endif
@@ -434,26 +582,25 @@ open_inet(class, h, serv, type)
int hostaddr, hostaddrPtr[2];
int servport;
char *syscall;
- VALUE sock;
if (h) {
Check_SafeStr(h);
host = RSTRING(h)->ptr;
hostent = gethostbyname(host);
if (hostent == NULL) {
- hostaddr = inet_addr(host);
- if (hostaddr == -1) {
+ if (!inet_aton(host, &sockaddr.sin_addr)) {
if (type == INET_SERVER && !strlen(host))
hostaddr = INADDR_ANY;
else {
#ifdef HAVE_HSTRERROR
extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
+ rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
#else
- Raise(eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
}
+ hostaddr = sockaddr.sin_addr.s_addr;
_hostent.h_addr_list = (char **)hostaddrPtr;
_hostent.h_addr_list[0] = (char *)&hostaddr;
_hostent.h_addr_list[1] = NULL;
@@ -467,24 +614,30 @@ open_inet(class, h, serv, type)
servport = FIX2UINT(serv);
goto setup_servent;
}
- Check_Type(serv, T_STRING);
- servent = getservbyname(RSTRING(serv)->ptr, "tcp");
+ servent = getservbyname(STR2CSTR(serv), "tcp");
if (servent == NULL) {
- servport = strtoul(RSTRING(serv)->ptr, 0, 0);
- if (servport == -1) {
- Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr);
+ char *s = STR2CSTR(serv);
+ char *end;
+
+ servport = strtoul(s, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such servce %s", s);
}
setup_servent:
_servent.s_port = htons(servport);
_servent.s_proto = "tcp";
servent = &_servent;
}
+#ifdef __BEOS__
+ fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+#else
protoent = getprotobyname(servent->s_proto);
if (protoent == NULL) {
- Raise(eSocket, "no such proto %s", servent->s_proto);
+ rb_raise(rb_eSocket, "no such proto %s", servent->s_proto);
}
fd = socket(AF_INET, SOCK_STREAM, protoent->p_proto);
+#endif
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
@@ -505,9 +658,9 @@ open_inet(class, h, serv, type)
syscall = "bind(2)";
}
else {
-#if defined(THREAD) && defined(HAVE_FCNTL)
+#if defined(USE_THREAD) && defined(HAVE_FCNTL)
status = thread_connect(fd, (struct sockaddr*)&sockaddr,
- sizeof(sockaddr), type);
+ sizeof(sockaddr), type);
#else
#ifdef SOCKS
if (type == INET_SOCKS) {
@@ -523,7 +676,7 @@ open_inet(class, h, serv, type)
}
if (status < 0) {
- close (fd);
+ close(fd);
rb_sys_fail(syscall);
}
if (type == INET_SERVER) listen(fd, 5);
@@ -558,6 +711,49 @@ socks_s_open(class, host, serv)
#endif
static VALUE
+tcp_s_gethostbyname(obj, host)
+ VALUE obj, host;
+{
+ struct sockaddr_in addr;
+ struct hostent *h;
+ char **pch;
+ VALUE ary, names;
+
+ setipaddr(STR2CSTR(host), &addr);
+ h = gethostbyaddr((char *)&addr.sin_addr,
+ sizeof(addr.sin_addr),
+ AF_INET);
+
+ if (h == NULL) {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
+#else
+ rb_raise(rb_eSocket, "host not found");
+#endif
+ }
+ ary = rb_ary_new();
+ rb_ary_push(ary, rb_str_new2(h->h_name));
+ names = rb_ary_new();
+ rb_ary_push(ary, names);
+ for (pch = h->h_aliases; *pch; pch++) {
+ rb_ary_push(names, rb_str_new2(*pch));
+ }
+ rb_ary_push(ary, NUM2INT(h->h_addrtype));
+#ifdef h_addr
+ for (pch = h->h_addr_list; *pch; pch++) {
+ memcpy((char *) &addr.sin_addr, *pch, h->h_length);
+ rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr));
+ }
+#else
+ memcpy((char *)&addr.sin_addr, h->h_addr, h->h_length);
+ rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr));
+#endif
+
+ return ary;
+}
+
+static VALUE
tcp_svr_s_open(argc, argv, class)
int argc;
VALUE *argv;
@@ -581,8 +777,8 @@ s_accept(class, fd, sockaddr, len)
int fd2;
retry:
-#ifdef THREAD
- thread_wait_fd(fd);
+#ifdef USE_THREAD
+ rb_thread_wait_fd(fd);
#endif
TRAP_BEG;
fd2 = accept(fd, sockaddr, len);
@@ -594,8 +790,8 @@ s_accept(class, fd, sockaddr, len)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
@@ -614,7 +810,7 @@ tcp_accept(sock)
GetOpenFile(sock, fptr);
fromlen = sizeof(struct sockaddr_in);
- return s_accept(cTCPsocket, fileno(fptr->f),
+ return s_accept(rb_cTCPsocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
@@ -670,81 +866,6 @@ open_unix(class, path, server)
}
#endif
-static void
-setipaddr(name, addr)
- char *name;
- struct sockaddr_in *addr;
-{
- int d1, d2, d3, d4;
- char ch;
- struct hostent *hp;
- long x;
-
- if (name[0] == 0) {
- addr->sin_addr.s_addr = INADDR_ANY;
- }
- else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
- addr->sin_addr.s_addr = INADDR_BROADCAST;
- }
- else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
- 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
- 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
- addr->sin_addr.s_addr = htonl(
- ((long) d1 << 24) | ((long) d2 << 16) |
- ((long) d3 << 8) | ((long) d4 << 0));
- }
- else {
- hp = gethostbyname(name);
- if (!hp) {
-#ifdef HAVE_HSTRERROR
- extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
-#else
- Raise(eSocket, "host not found");
-#endif
- }
- memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
- }
-}
-
-static VALUE
-mkipaddr(x)
- unsigned long x;
-{
- char buf[16];
-
- x = ntohl(x);
- sprintf(buf, "%d.%d.%d.%d",
- (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
- (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
- return str_new2(buf);
-}
-
-static VALUE
-ipaddr(sockaddr)
- struct sockaddr_in *sockaddr;
-{
- VALUE family, port, addr1, addr2;
- VALUE ary;
- struct hostent *hostent;
-
- family = str_new2("AF_INET");
- hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
- sizeof(sockaddr->sin_addr),
- AF_INET);
- addr1 = 0;
- if (hostent) {
- addr1 = str_new2(hostent->h_name);
- }
- addr2 = mkipaddr(sockaddr->sin_addr.s_addr);
- if (!addr1) addr1 = addr2;
-
- port = INT2FIX(ntohs(sockaddr->sin_port));
- ary = ary_new3(4, family, port, addr1, addr2);
-
- return ary;
-}
-
static VALUE
ip_addr(sock)
VALUE sock;
@@ -781,13 +902,12 @@ ip_s_getaddress(obj, host)
{
struct sockaddr_in addr;
- if (obj_is_kind_of(host, cInteger)) {
+ if (rb_obj_is_kind_of(host, rb_cInteger)) {
int i = NUM2INT(host);
addr.sin_addr.s_addr = htonl(i);
}
else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, &addr);
+ setipaddr(STR2CSTR(host), &addr);
}
return mkipaddr(addr.sin_addr.s_addr);
@@ -805,37 +925,36 @@ udp_addrsetup(host, port, addr)
VALUE host, port;
struct sockaddr_in *addr;
{
- struct hostent *hostent;
-
memset(addr, 0, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
if (NIL_P(host)) {
addr->sin_addr.s_addr = INADDR_ANY;
}
- else if (obj_is_kind_of(host, cInteger)) {
+ else if (rb_obj_is_kind_of(host, rb_cInteger)) {
int i = NUM2INT(host);
addr->sin_addr.s_addr = htonl(i);
}
else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, addr);
+ setipaddr(STR2CSTR(host), addr);
}
if (FIXNUM_P(port)) {
- addr->sin_port = FIX2INT(port);
+ addr->sin_port = htons(FIX2INT(port));
}
else {
struct servent *servent;
- Check_Type(port, T_STRING);
- servent = getservbyname(RSTRING(port)->ptr, "udp");
+ servent = getservbyname(STR2CSTR(port), "udp");
if (servent) {
addr->sin_port = servent->s_port;
}
else {
- int port = strtoul(RSTRING(port)->ptr, 0, 0);
+ char *s = STR2CSTR(port);
+ char *end;
+ int portno;
- if (port == -1) {
- Raise(eSocket, "no such servce %s", RSTRING(port)->ptr);
+ portno = strtoul(s, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such servce %s", s);
}
addr->sin_port = htons(port);
}
@@ -859,8 +978,8 @@ udp_connect(sock, host, port)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
@@ -896,19 +1015,21 @@ udp_send(argc, argv, sock)
OpenFile *fptr;
FILE *f;
int n;
+ char *m;
+ int mlen;
if (argc == 2) {
return bsock_send(argc, argv, sock);
}
rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
- Check_Type(mesg, T_STRING);
udp_addrsetup(host, port, &addr);
GetOpenFile(sock, fptr);
- f = fptr->f2?fptr->f2:fptr->f;
+ f = GetWriteFile(fptr);
+ m = rb_str2cstr(mesg, &mlen);
retry:
- n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len,
- NUM2INT(flags), (struct sockaddr*)&addr, sizeof(addr));
+ n = sendto(fileno(f), m, mlen, NUM2INT(flags),
+ (struct sockaddr*)&addr, sizeof(addr));
if (n < 0) {
switch (errno) {
case EINTR:
@@ -916,8 +1037,8 @@ udp_send(argc, argv, sock)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
@@ -957,14 +1078,14 @@ unix_path(sock)
rb_sys_fail(0);
fptr->path = strdup(addr.sun_path);
}
- return str_new2(fptr->path);
+ return rb_str_new2(fptr->path);
}
static VALUE
-unix_svr_s_open(class, path)
- VALUE class, path;
+unix_svr_s_open(sock, path)
+ VALUE sock, path;
{
- return open_unix(class, path, 1);
+ return open_unix(sock, path, 1);
}
static VALUE
@@ -986,7 +1107,7 @@ unix_accept(sock)
GetOpenFile(sock, fptr);
fromlen = sizeof(struct sockaddr_un);
- return s_accept(cUNIXsocket, fileno(fptr->f),
+ return s_accept(rb_cUNIXsocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
@@ -994,7 +1115,7 @@ static VALUE
unixaddr(sockaddr)
struct sockaddr_un *sockaddr;
{
- return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path));
+ return rb_assoc_new(rb_str_new2("AF_UNIX"),rb_str_new2(sockaddr->sun_path));
}
static VALUE
@@ -1055,8 +1176,10 @@ setup_domain_and_type(domain, dv, type, tv)
else if (strcmp(ptr, "AF_IMPLINK") == 0)
*dv = AF_IMPLINK;
#endif
+#ifdef PF_INET
else if (strcmp(ptr, "PF_INET") == 0)
*dv = PF_INET;
+#endif
#ifdef PF_UNIX
else if (strcmp(ptr, "PF_UNIX") == 0)
*dv = PF_UNIX;
@@ -1076,7 +1199,7 @@ setup_domain_and_type(domain, dv, type, tv)
*dv = PF_IPX;
#endif
else
- Raise(eSocket, "Unknown socket domain %s", ptr);
+ rb_raise(rb_eSocket, "Unknown socket domain %s", ptr);
}
else {
*dv = NUM2INT(domain);
@@ -1104,7 +1227,7 @@ setup_domain_and_type(domain, dv, type, tv)
*tv = SOCK_PACKET;
#endif
else
- Raise(eSocket, "Unknown socket type %s", ptr);
+ rb_raise(rb_eSocket, "Unknown socket type %s", ptr);
}
else {
*tv = NUM2INT(type);
@@ -1121,6 +1244,7 @@ sock_s_open(class, domain, type, protocol)
setup_domain_and_type(domain, &d, type, &t);
fd = socket(d, t, NUM2INT(protocol));
if (fd < 0) rb_sys_fail("socket(2)");
+
return sock_new(class, fd);
}
@@ -1135,15 +1259,14 @@ static VALUE
sock_s_socketpair(class, domain, type, protocol)
VALUE class, domain, type, protocol;
{
-#if !defined(__CYGWIN32__) && !defined(NT)
- int fd;
+#if !defined(NT) && !defined(__BEOS__)
int d, t, sp[2];
setup_domain_and_type(domain, &d, type, &t);
if (socketpair(d, t, NUM2INT(protocol), sp) < 0)
rb_sys_fail("socketpair(2)");
- return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
+ return rb_assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
#else
rb_notimplement();
#endif
@@ -1156,7 +1279,7 @@ sock_connect(sock, addr)
OpenFile *fptr;
Check_Type(addr, T_STRING);
- str_modify(addr);
+ rb_str_modify(addr);
GetOpenFile(sock, fptr);
retry:
@@ -1167,8 +1290,8 @@ sock_connect(sock, addr)
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
goto retry;
}
@@ -1185,7 +1308,7 @@ sock_bind(sock, addr)
OpenFile *fptr;
Check_Type(addr, T_STRING);
- str_modify(addr);
+ rb_str_modify(addr);
GetOpenFile(sock, fptr);
if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
@@ -1226,9 +1349,9 @@ sock_accept(sock)
int len = sizeof buf;
GetOpenFile(sock, fptr);
- sock2 = s_accept(cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
+ sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
- return assoc_new(sock2, str_new(buf, len));
+ return rb_assoc_new(sock2, rb_str_new(buf, len));
}
#ifdef HAVE_GETHOSTNAME
@@ -1242,7 +1365,7 @@ sock_gethostname(obj)
rb_sys_fail("gethostname");
buf[sizeof buf - 1] = '\0';
- return str_new2(buf);
+ return rb_str_new2(buf);
}
#else
#ifdef HAVE_UNAME
@@ -1256,7 +1379,7 @@ sock_gethostname(obj)
struct utsname un;
uname(&un);
- return str_new2(un.nodename);
+ return rb_str_new2(un.nodename);
}
#else
static VALUE
@@ -1272,32 +1395,31 @@ static VALUE
mkhostent(h)
struct hostent *h;
{
- struct sockaddr_in addr;
char **pch;
VALUE ary, names;
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
+ rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
#else
- Raise(eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
- ary = ary_new();
- ary_push(ary, str_new2(h->h_name));
- names = ary_new();
- ary_push(ary, names);
+ ary = rb_ary_new();
+ rb_ary_push(ary, rb_str_new2(h->h_name));
+ names = rb_ary_new();
+ rb_ary_push(ary, names);
for (pch = h->h_aliases; *pch; pch++) {
- ary_push(names, str_new2(*pch));
+ rb_ary_push(names, rb_str_new2(*pch));
}
- ary_push(ary, INT2FIX(h->h_length));
+ rb_ary_push(ary, NUM2INT(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
- ary_push(ary, str_new(*pch, h->h_length));
+ rb_ary_push(ary, rb_str_new(*pch, h->h_length));
}
#else
- ary_push(ary, str_new(h->h_addr, h->h_length));
+ rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
#endif
return ary;
@@ -1310,13 +1432,12 @@ sock_s_gethostbyname(obj, host)
struct sockaddr_in addr;
struct hostent *h;
- if (obj_is_kind_of(host, cInteger)) {
+ if (rb_obj_is_kind_of(host, rb_cInteger)) {
int i = NUM2INT(host);
addr.sin_addr.s_addr = htonl(i);
}
else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, &addr);
+ setipaddr(STR2CSTR(host), &addr);
}
h = gethostbyaddr((char *)&addr.sin_addr,
sizeof(addr.sin_addr),
@@ -1332,20 +1453,20 @@ sock_s_gethostbyaddr(argc, argv)
{
VALUE vaddr, vtype;
int type;
-
- struct sockaddr_in *addr;
+ int alen;
+ char *addr;
struct hostent *h;
- rb_scan_args(argc, argv, "11", &addr, &type);
- Check_Type(addr, T_STRING);
- if (!NIL_P(type)) {
+ rb_scan_args(argc, argv, "11", &vaddr, &vtype);
+ addr = rb_str2cstr(vaddr, &alen);
+ if (!NIL_P(vtype)) {
type = NUM2INT(vtype);
}
else {
type = AF_INET;
}
- h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type);
+ h = gethostbyaddr(addr, alen, type);
return mkhostent(h);
}
@@ -1361,15 +1482,22 @@ sock_s_getservbyaname(argc, argv)
int port;
rb_scan_args(argc, argv, "11", &service, &protocol);
- Check_Type(service, T_STRING);
if (NIL_P(protocol)) proto = "tcp";
- else proto = RSTRING(protocol)->ptr;
+ else proto = STR2CSTR(protocol);
- sp = getservbyname(RSTRING(service)->ptr, proto);
- if (!sp) {
- Raise(eSocket, "service/proto not found");
+ sp = getservbyname(STR2CSTR(service), proto);
+ if (sp) {
+ port = ntohs(sp->s_port);
+ }
+ else {
+ char *s = STR2CSTR(service);
+ char *end;
+
+ port = strtoul(s, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such servce %s/%s", s, proto);
+ }
}
- port = ntohs(sp->s_port);
return INT2FIX(port);
}
@@ -1377,225 +1505,240 @@ sock_s_getservbyaname(argc, argv)
static VALUE mConst;
static void
-sock_define_const(name, value)
+sock_rb_define_const(name, value)
char *name;
- INT value;
+ int value;
{
- rb_define_const(cSocket, name, INT2FIX(value));
+ rb_define_const(rb_cSocket, name, INT2FIX(value));
rb_define_const(mConst, name, INT2FIX(value));
}
Init_socket()
{
- eSocket = rb_define_class("SocketError", eException);
-
- cBasicSocket = rb_define_class("BasicSocket", cIO);
- rb_undef_method(CLASS_OF(cBasicSocket), "new");
- rb_undef_method(CLASS_OF(cBasicSocket), "open");
- rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1);
- rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3);
- rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2);
- rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0);
- rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0);
- rb_define_method(cBasicSocket, "send", bsock_send, -1);
- rb_define_method(cBasicSocket, "recv", bsock_recv, -1);
-
- cIPsocket = rb_define_class("IPsocket", cBasicSocket);
- rb_define_method(cIPsocket, "addr", ip_addr, 0);
- rb_define_method(cIPsocket, "peeraddr", ip_peeraddr, 0);
- rb_define_singleton_method(cIPsocket, "getaddress", ip_s_getaddress, 1);
-
- cTCPsocket = rb_define_class("TCPsocket", cIPsocket);
- rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2);
- rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2);
- rb_define_method(cTCPsocket, "recvfrom", tcp_recvfrom, -1);
+ rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
+
+ rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
+ rb_undef_method(CLASS_OF(rb_cBasicSocket), "new");
+ rb_undef_method(CLASS_OF(rb_cBasicSocket), "open");
+ rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
+ rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
+ rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
+ rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
+ rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
+ rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
+ rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
+ rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
+ rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
+
+ rb_cIPsocket = rb_define_class("IPsocket", rb_cBasicSocket);
+ rb_define_method(rb_cIPsocket, "addr", ip_addr, 0);
+ rb_define_method(rb_cIPsocket, "peeraddr", ip_peeraddr, 0);
+ rb_define_singleton_method(rb_cIPsocket, "getaddress", ip_s_getaddress, 1);
+
+ rb_cTCPsocket = rb_define_class("TCPsocket", rb_cIPsocket);
+ rb_define_singleton_method(rb_cTCPsocket, "open", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPsocket, "new", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPsocket, "gethostbyname", tcp_s_gethostbyname, 1);
+ rb_define_method(rb_cTCPsocket, "recvfrom", tcp_recvfrom, -1);
#ifdef SOCKS
- cSOCKSsocket = rb_define_class("SOCKSsocket", cTCPsocket);
- rb_define_singleton_method(cSOCKSsocket, "open", socks_s_open, 2);
- rb_define_singleton_method(cSOCKSsocket, "new", socks_s_open, 2);
+ rb_cSOCKSsocket = rb_define_class("SOCKSsocket", rb_cTCPsocket);
+ rb_define_singleton_method(rb_cSOCKSsocket, "open", socks_s_open, 2);
+ rb_define_singleton_method(rb_cSOCKSsocket, "new", socks_s_open, 2);
#endif
- cTCPserver = rb_define_class("TCPserver", cTCPsocket);
- rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1);
- rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1);
- rb_define_method(cTCPserver, "accept", tcp_accept, 0);
+ rb_cTCPserver = rb_define_class("TCPserver", rb_cTCPsocket);
+ rb_define_singleton_method(rb_cTCPserver, "open", tcp_svr_s_open, -1);
+ rb_define_singleton_method(rb_cTCPserver, "new", tcp_svr_s_open, -1);
+ rb_define_method(rb_cTCPserver, "accept", tcp_accept, 0);
- cUDPsocket = rb_define_class("UDPsocket", cIPsocket);
- rb_define_singleton_method(cUDPsocket, "open", udp_s_open, 0);
- rb_define_singleton_method(cUDPsocket, "new", udp_s_open, 0);
- rb_define_method(cUDPsocket, "connect", udp_connect, 2);
- rb_define_method(cUDPsocket, "bind", udp_bind, 2);
- rb_define_method(cUDPsocket, "send", udp_send, -1);
- rb_define_method(cUDPsocket, "recvfrom", udp_recvfrom, -1);
+ rb_cUDPsocket = rb_define_class("UDPsocket", rb_cIPsocket);
+ rb_define_singleton_method(rb_cUDPsocket, "open", udp_s_open, 0);
+ rb_define_singleton_method(rb_cUDPsocket, "new", udp_s_open, 0);
+ rb_define_method(rb_cUDPsocket, "connect", udp_connect, 2);
+ rb_define_method(rb_cUDPsocket, "bind", udp_bind, 2);
+ rb_define_method(rb_cUDPsocket, "send", udp_send, -1);
+ rb_define_method(rb_cUDPsocket, "recvfrom", udp_recvfrom, -1);
#ifdef HAVE_SYS_UN_H
- cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket);
- rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1);
- rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1);
- rb_define_method(cUNIXsocket, "path", unix_path, 0);
- rb_define_method(cUNIXsocket, "addr", unix_addr, 0);
- rb_define_method(cUNIXsocket, "peeraddr", unix_peeraddr, 0);
- rb_define_method(cUNIXsocket, "recvfrom", unix_recvfrom, -1);
-
- cUNIXserver = rb_define_class("UNIXserver", cUNIXsocket);
- rb_define_singleton_method(cUNIXserver, "open", unix_svr_s_open, 1);
- rb_define_singleton_method(cUNIXserver, "new", unix_svr_s_open, 1);
- rb_define_method(cUNIXserver, "accept", unix_accept, 0);
-#endif
-
- cSocket = rb_define_class("Socket", cBasicSocket);
- rb_define_singleton_method(cSocket, "open", sock_s_open, 3);
- rb_define_singleton_method(cSocket, "new", sock_s_open, 3);
- rb_define_singleton_method(cSocket, "for_fd", sock_s_for_fd, 1);
-
- rb_define_method(cSocket, "connect", sock_connect, 1);
- rb_define_method(cSocket, "bind", sock_bind, 1);
- rb_define_method(cSocket, "listen", sock_listen, 1);
- rb_define_method(cSocket, "accept", sock_accept, 0);
-
- rb_define_method(cSocket, "recvfrom", sock_recvfrom, -1);
-
- rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3);
- rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3);
- rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0);
- rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1);
- rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
- rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1);
+ rb_cUNIXsocket = rb_define_class("UNIXsocket", rb_cBasicSocket);
+ rb_define_singleton_method(rb_cUNIXsocket, "open", unix_s_sock_open, 1);
+ rb_define_singleton_method(rb_cUNIXsocket, "new", unix_s_sock_open, 1);
+ rb_define_method(rb_cUNIXsocket, "path", unix_path, 0);
+ rb_define_method(rb_cUNIXsocket, "addr", unix_addr, 0);
+ rb_define_method(rb_cUNIXsocket, "peeraddr", unix_peeraddr, 0);
+ rb_define_method(rb_cUNIXsocket, "recvfrom", unix_recvfrom, -1);
+
+ rb_cUNIXserver = rb_define_class("UNIXserver", rb_cUNIXsocket);
+ rb_define_singleton_method(rb_cUNIXserver, "open", unix_svr_s_open, 1);
+ rb_define_singleton_method(rb_cUNIXserver, "new", unix_svr_s_open, 1);
+ rb_define_method(rb_cUNIXserver, "accept", unix_accept, 0);
+#endif
+
+ rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
+ rb_define_singleton_method(rb_cSocket, "open", sock_s_open, 3);
+ rb_define_singleton_method(rb_cSocket, "new", sock_s_open, 3);
+ rb_define_singleton_method(rb_cSocket, "for_fd", sock_s_for_fd, 1);
+
+ rb_define_method(rb_cSocket, "connect", sock_connect, 1);
+ rb_define_method(rb_cSocket, "bind", sock_bind, 1);
+ rb_define_method(rb_cSocket, "listen", sock_listen, 1);
+ rb_define_method(rb_cSocket, "accept", sock_accept, 0);
+
+ rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
+
+ rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
+ rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
+ rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
+ rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
+ rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
+ rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
/* constants */
- mConst = rb_define_module_under(cSocket, "Constants");
- sock_define_const("SOCK_STREAM", SOCK_STREAM);
- sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
- sock_define_const("SOCK_RAW", SOCK_RAW);
+ mConst = rb_define_module_under(rb_cSocket, "Constants");
+ sock_rb_define_const("SOCK_STREAM", SOCK_STREAM);
+ sock_rb_define_const("SOCK_DGRAM", SOCK_DGRAM);
+#ifdef SOCK_RAW
+ sock_rb_define_const("SOCK_RAW", SOCK_RAW);
+#endif
#ifdef SOCK_RDM
- sock_define_const("SOCK_RDM", SOCK_RDM);
+ sock_rb_define_const("SOCK_RDM", SOCK_RDM);
#endif
#ifdef SOCK_SEQPACKET
- sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
+ sock_rb_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
#endif
#ifdef SOCK_PACKET
- sock_define_const("SOCK_PACKET", SOCK_PACKET);
+ sock_rb_define_const("SOCK_PACKET", SOCK_PACKET);
#endif
- sock_define_const("AF_INET", AF_INET);
- sock_define_const("PF_INET", PF_INET);
+ sock_rb_define_const("AF_INET", AF_INET);
+#ifdef PF_INET
+ sock_rb_define_const("PF_INET", PF_INET);
+#endif
#ifdef AF_UNIX
- sock_define_const("AF_UNIX", AF_UNIX);
- sock_define_const("PF_UNIX", PF_UNIX);
+ sock_rb_define_const("AF_UNIX", AF_UNIX);
+ sock_rb_define_const("PF_UNIX", PF_UNIX);
#endif
#ifdef AF_AX25
- sock_define_const("AF_AX25", AF_AX25);
- sock_define_const("PF_AX25", PF_AX25);
+ sock_rb_define_const("AF_AX25", AF_AX25);
+ sock_rb_define_const("PF_AX25", PF_AX25);
#endif
#ifdef AF_IPX
- sock_define_const("AF_IPX", AF_IPX);
- sock_define_const("PF_IPX", PF_IPX);
+ sock_rb_define_const("AF_IPX", AF_IPX);
+ sock_rb_define_const("PF_IPX", PF_IPX);
#endif
#ifdef AF_APPLETALK
- sock_define_const("AF_APPLETALK", AF_APPLETALK);
- sock_define_const("PF_APPLETALK", PF_APPLETALK);
+ sock_rb_define_const("AF_APPLETALK", AF_APPLETALK);
+ sock_rb_define_const("PF_APPLETALK", PF_APPLETALK);
#endif
- sock_define_const("MSG_OOB", MSG_OOB);
- sock_define_const("MSG_PEEK", MSG_PEEK);
- sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
+ sock_rb_define_const("MSG_OOB", MSG_OOB);
+#ifdef MSG_PEEK
+ sock_rb_define_const("MSG_PEEK", MSG_PEEK);
+#endif
+#ifdef MSG_DONTROUTE
+ sock_rb_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
+#endif
- sock_define_const("SOL_SOCKET", SOL_SOCKET);
+ sock_rb_define_const("SOL_SOCKET", SOL_SOCKET);
#ifdef SOL_IP
- sock_define_const("SOL_IP", SOL_IP);
+ sock_rb_define_const("SOL_IP", SOL_IP);
#endif
#ifdef SOL_IPX
- sock_define_const("SOL_IPX", SOL_IPX);
+ sock_rb_define_const("SOL_IPX", SOL_IPX);
#endif
#ifdef SOL_AX25
- sock_define_const("SOL_AX25", SOL_AX25);
+ sock_rb_define_const("SOL_AX25", SOL_AX25);
#endif
#ifdef SOL_ATALK
- sock_define_const("SOL_ATALK", SOL_ATALK);
+ sock_rb_define_const("SOL_ATALK", SOL_ATALK);
#endif
#ifdef SOL_TCP
- sock_define_const("SOL_TCP", SOL_TCP);
+ sock_rb_define_const("SOL_TCP", SOL_TCP);
#endif
#ifdef SOL_UDP
- sock_define_const("SOL_UDP", SOL_UDP);
+ sock_rb_define_const("SOL_UDP", SOL_UDP);
#endif
#ifdef SO_DEBUG
- sock_define_const("SO_DEBUG", SO_DEBUG);
+ sock_rb_define_const("SO_DEBUG", SO_DEBUG);
#endif
- sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
+ sock_rb_define_const("SO_REUSEADDR", SO_REUSEADDR);
#ifdef SO_TYPE
- sock_define_const("SO_TYPE", SO_TYPE);
+ sock_rb_define_const("SO_TYPE", SO_TYPE);
#endif
#ifdef SO_ERROR
- sock_define_const("SO_ERROR", SO_ERROR);
+ sock_rb_define_const("SO_ERROR", SO_ERROR);
#endif
#ifdef SO_DONTROUTE
- sock_define_const("SO_DONTROUTE", SO_DONTROUTE);
+ sock_rb_define_const("SO_DONTROUTE", SO_DONTROUTE);
#endif
#ifdef SO_BROADCAST
- sock_define_const("SO_BROADCAST", SO_BROADCAST);
+ sock_rb_define_const("SO_BROADCAST", SO_BROADCAST);
#endif
#ifdef SO_SNDBUF
- sock_define_const("SO_SNDBUF", SO_SNDBUF);
+ sock_rb_define_const("SO_SNDBUF", SO_SNDBUF);
#endif
#ifdef SO_RCVBUF
- sock_define_const("SO_RCVBUF", SO_RCVBUF);
+ sock_rb_define_const("SO_RCVBUF", SO_RCVBUF);
+#endif
+#ifdef SO_KEEPALIVE
+ sock_rb_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
#endif
- sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
#ifdef SO_OOBINLINE
- sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
+ sock_rb_define_const("SO_OOBINLINE", SO_OOBINLINE);
#endif
#ifdef SO_NO_CHECK
- sock_define_const("SO_NO_CHECK", SO_NO_CHECK);
+ sock_rb_define_const("SO_NO_CHECK", SO_NO_CHECK);
#endif
#ifdef SO_PRIORITY
- sock_define_const("SO_PRIORITY", SO_PRIORITY);
+ sock_rb_define_const("SO_PRIORITY", SO_PRIORITY);
+#endif
+#ifdef SO_LINGER
+ sock_rb_define_const("SO_LINGER", SO_LINGER);
#endif
- sock_define_const("SO_LINGER", SO_LINGER);
#ifdef SOPRI_INTERACTIVE
- sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
+ sock_rb_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
#endif
#ifdef SOPRI_NORMAL
- sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
+ sock_rb_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
#endif
#ifdef SOPRI_BACKGROUND
- sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
+ sock_rb_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
#endif
#ifdef IP_MULTICAST_IF
- sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
+ sock_rb_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
#endif
#ifdef IP_MULTICAST_TTL
- sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
+ sock_rb_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
#endif
#ifdef IP_MULTICAST_LOOP
- sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
+ sock_rb_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
#endif
#ifdef IP_ADD_MEMBERSHIP
- sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
+ sock_rb_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
#endif
#ifdef IP_DEFAULT_MULTICAST_TTL
- sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
+ sock_rb_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
#endif
#ifdef IP_DEFAULT_MULTICAST_LOOP
- sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
+ sock_rb_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
#endif
#ifdef IP_MAX_MEMBERSHIPS
- sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
+ sock_rb_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
#endif
#ifdef IPX_TYPE
- sock_define_const("IPX_TYPE", IPX_TYPE);
+ sock_rb_define_const("IPX_TYPE", IPX_TYPE);
#endif
#ifdef TCP_NODELAY
- sock_define_const("TCP_NODELAY", TCP_NODELAY);
+ sock_rb_define_const("TCP_NODELAY", TCP_NODELAY);
#endif
#ifdef TCP_MAXSEG
- sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
+ sock_rb_define_const("TCP_MAXSEG", TCP_MAXSEG);
#endif
}
diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb
index 26e7fe7b09..e34e549ca0 100644
--- a/ext/tcltklib/extconf.rb
+++ b/ext/tcltklib/extconf.rb
@@ -1,19 +1,27 @@
# extconf.rb for tcltklib
+require 'mkmf'
+
+have_library("nsl", "t_open")
have_library("socket", "socket")
-have_library("nsl", "gethostbyname")
+have_library("dl", "dlopen")
+have_library("m", "log")
-def search_file(var, include, *path)
+$includes = []
+def search_header(include, *path)
pwd = Dir.getwd
begin
- for i in path.reverse!
+ for i in path.sort!.reverse!
dir = Dir[i]
- for path in dir
+ for path in dir.sort!.reverse!
+ next unless File.directory? path
Dir.chdir path
files = Dir[include]
if files.size > 0
- var << path
- return files.pop
+ unless $includes.include? path
+ $includes << path
+ end
+ return
end
end
end
@@ -22,58 +30,56 @@ def search_file(var, include, *path)
end
end
-$includes = []
-search_file($includes,
- "tcl.h",
- "/usr/include/tcl*",
- "/usr/include",
- "/usr/local/include/tcl*",
- "/usr/local/include")
-search_file($includes,
- "tk.h",
- "/usr/include/tk*",
- "/usr/include",
- "/usr/local/include/tk*",
- "/usr/local/include")
-search_file($includes,
- "X11/Xlib.h",
- "/usr/include",
- "/usr/X11*/include",
- "/usr/include",
- "/usr/X11*/include")
+search_header("tcl.h",
+ "/usr/include/tcl{,8*,7*}",
+ "/usr/include",
+ "/usr/local/include/tcl{,8*,7*}",
+ "/usr/local/include")
+search_header("tk.h",
+ "/usr/include/tk{,8*,4*}",
+ "/usr/include",
+ "/usr/local/include/tk{,8*,4*}",
+ "/usr/local/include")
+search_header("X11/Xlib.h",
+ "/usr/include/X11*",
+ "/usr/include",
+ "/usr/openwin/include",
+ "/usr/X11*/include")
-$CFLAGS = "-Wall " + $includes.collect{|path| "-I" + path}.join(" ")
+$CFLAGS = $includes.collect{|path| "-I" + path}.join(" ")
$libraries = []
-tcllibfile = search_file($libraries,
- "libtcl{,7*,8*}.{a,so}",
- "/usr/lib",
- "/usr/local/lib")
-if tcllibfile
- tcllibfile.sub!(/^lib/, '')
- tcllibfile.sub!(/\.(a|so)$/, '')
-end
-tklibfile = search_file($libraries,
- "libtk{,4*,8*}.{a,so}",
- "/usr/lib",
- "/usr/local/lib")
-if tklibfile
- tklibfile.sub!(/^lib/, '')
- tklibfile.sub!(/\.(a|so)$/, '')
+def search_lib(file, func, *path)
+ for i in path.reverse!
+ dir = Dir[i]
+ for path in dir.sort!.reverse!
+ $LDFLAGS = $libraries.collect{|p| "-L" + p}.join(" ") + " -L" + path
+ files = Dir[path+"/"+file]
+ if files.size > 0
+ for lib in files.sort!.reverse!
+ lib = File::basename(lib)
+ lib.sub!(/^lib/, '')
+ lib.sub!(/\.(a|so)$/, '')
+ if have_library(lib, func)
+ unless $libraries.include? path
+ $libraries << path
+ end
+ return true
+ end
+ end
+ end
+ end
+ end
+ return false;
end
-search_file($libraries,
- "libX11.{a,so}",
- "/usr/lib",
- "/usr/X11*/lib")
-$LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ")
-
-have_library("dl", "dlopen")
-if have_header("tcl.h") &&
- have_header("tk.h") &&
- have_library("X11", "XOpenDisplay") &&
- have_library("m", "log") &&
- have_library(tcllibfile, "Tcl_FindExecutable") &&
- have_library(tklibfile, "Tk_Init")
+if have_header("tcl.h") && have_header("tk.h") &&
+ search_lib("libX11.{so,a}", "XOpenDisplay",
+ "/usr/lib", "/usr/openwin/lib", "/usr/X11*/lib") &&
+ search_lib("libtcl{8*,7*,}.{so,a}", "Tcl_FindExecutable",
+ "/usr/lib", "/usr/local/lib") &&
+ search_lib("libtk{8*,4*,}.{so,a}", "Tk_Init",
+ "/usr/lib", "/usr/local/lib")
+ $LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ")
create_makefile("tcltklib")
end
diff --git a/ext/tcltklib/lib/tcltk.rb b/ext/tcltklib/lib/tcltk.rb
index 81d01f930d..54a00e8f3c 100644
--- a/ext/tcltklib/lib/tcltk.rb
+++ b/ext/tcltklib/lib/tcltk.rb
@@ -1,48 +1,44 @@
# tof
-#### tcltk ¥é¥¤¥Ö¥é¥ê
+#### tcltk library, more direct manipulation of tcl/tk
#### Sep. 5, 1997 Y. Shigehiro
require "tcltklib"
################
-# module TclTk: tcl/tk ¤Î¥é¥¤¥Ö¥é¥êÁ´ÂΤÇɬÍפˤʤë¤â¤Î¤ò½¸¤á¤¿¤â¤Î
-# (¼ç¤Ë, ̾Á°¶õ´Ö¤ÎÅÀ¤«¤é module ¤Ë¤¹¤ë»È¤¦.)
+# module TclTk: collection of tcl/tk utilities (supplies namespace.)
module TclTk
- # ñ¤Ë¤³¤³¤Ë½ñ¤±¤ÐºÇ½é¤Ë 1 Åټ¹Ԥµ¤ì¤ë¤Î¤«??
-
- # À¸À®¤·¤¿°ì°Õ¤Ê̾Á°¤òÊÝ»ý¤·¤Æ¤ª¤¯Ï¢ÁÛÇÛÎó¤ò½é´ü²½¤¹¤ë.
+ # initialize Hash to hold unique symbols and such
@namecnt = {}
- # ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÊÝ»ý¤·¤Æ¤ª¤¯Ï¢ÁÛÇÛÎó¤ò½é´ü²½¤¹¤ë.
+ # initialize Hash to hold callbacks
@callback = {}
end
-# TclTk.mainloop(): TclTkLib.mainloop() ¤ò¸Æ¤Ö.
+# TclTk.mainloop(): call TclTkLib.mainloop()
def TclTk.mainloop()
print("mainloop: start\n") if $DEBUG
TclTkLib.mainloop()
print("mainloop: end\n") if $DEBUG
end
-# TclTk.deletecallbackkey(ca): ¥³¡¼¥ë¥Ð¥Ã¥¯¤ò TclTk module ¤«¤é¼è¤ê½ü¤¯.
-# tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ë¤ª¤¤¤Æ¥³¡¼¥ë¥Ð¥Ã¥¯¤¬¼è¤ê¾Ã¤µ¤ì¤ë¤ï¤±¤Ç¤Ï¤Ê¤¤.
-# ¤³¤ì¤ò¤·¤Ê¤¤¤È, ºÇ¸å¤Ë TclTkInterpreter ¤¬ GC ¤Ç¤­¤Ê¤¤.
-# (GC ¤·¤¿¤¯¤Ê¤±¤ì¤Ð, Ê̤Ë, ¤³¤ì¤ò¤·¤Ê¤¯¤Æ¤âÎɤ¤.)
-# ca: ¥³¡¼¥ë¥Ð¥Ã¥¯(TclTkCallback)
+# TclTk.deletecallbackkey(ca): remove callback from TclTk module
+# this does not remove callbacks from tcl/tk interpreter
+# without calling this method, TclTkInterpreter will not be GCed
+# ca: callback(TclTkCallback)
def TclTk.deletecallbackkey(ca)
print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG
@callback.delete(ca.to_s)
end
-# TclTk.dcb(ca, wid, W): ÇÛÎó¤ËÆþ¤Ã¤Æ¤¤¤ëÊ£¿ô¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¤ËÂФ·¤Æ
-# TclTk.deletecallbackkey() ¤ò¸Æ¤Ö.
-# ¥È¥Ã¥×¥ì¥Ù¥ë¤Î <Destroy> ¥¤¥Ù¥ó¥È¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¤È¤·¤Æ¸Æ¤Ö¤¿¤á¤Î¤â¤Î.
-# ca: ¥³¡¼¥ë¥Ð¥Ã¥¯(TclTkCallback) ¤Î Array
-# wid: ¥È¥Ã¥×¥ì¥Ù¥ë¤Î¥¦¥£¥¸¥§¥Ã¥È(TclTkWidget)
-# w: ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ë %W ¤ÇÍ¿¤¨¤é¤ì¤ë, ¥¦¥¤¥ó¥É¥¦¤Ë´Ø¤¹¤ë¥Ñ¥é¥á¡¼¥¿(String)
+# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks
+# in an array.
+# this is for callback for top-level <Destroy>
+# ca: array of callbacks(TclTkCallback)
+# wid: top-level widget(TclTkWidget)
+# w: information about window given by %W(String)
def TclTk.dcb(ca, wid, w)
if wid.to_s() == w
ca.each{|i|
@@ -51,33 +47,33 @@ def TclTk.dcb(ca, wid, w)
end
end
-# TclTk._addcallback(ca): ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÅÐÏ¿¤¹¤ë.
-# ca: ¥³¡¼¥ë¥Ð¥Ã¥¯(TclTkCallback)
+# TclTk._addcallback(ca): register callback
+# ca: callback(TclTkCallback)
def TclTk._addcallback(ca)
print("_addcallback: ", ca.to_s(), "\n") if $DEBUG
@callback[ca.to_s()] = ca
end
-# TclTk._callcallback(key, arg): ÅÐÏ¿¤·¤¿¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹.
-# key: ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÁªÂò¤¹¤ë¥­¡¼ (TclTkCallback ¤¬ to_s() ¤ÇÊÖ¤¹ÃÍ)
-# arg: tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é¤Î¥Ñ¥é¥á¡¼¥¿
+# TclTk._callcallback(key, arg): invoke registered callback
+# key: key to select callback (to_s value of the TclTkCallback)
+# arg: parameter from tcl/tk interpreter
def TclTk._callcallback(key, arg)
print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG
@callback[key]._call(arg)
- # ¥³¡¼¥ë¥Ð¥Ã¥¯¤«¤é¤ÎÊÖ¤êÃͤϤɤ¦¤»¼Î¤Æ¤é¤ì¤ë.
- # String ¤òÊÖ¤µ¤Ê¤¤¤È, rb_eval_string() ¤¬¥¨¥é¡¼¤Ë¤Ê¤ë.
+ # throw out callback value
+ # should return String to satisfy rb_eval_string()
return ""
end
-# TclTk._newname(prefix): °ì°Õ¤Ê̾Á°(String)¤òÀ¸À®¤·¤ÆÊÖ¤¹.
-# prefix: ̾Á°¤ÎÀÜƬ¸ì
+# TclTk._newname(prefix): generate unique name(String)
+# prefix: prefix of the unique name
def TclTk._newname(prefix)
- # À¸À®¤·¤¿Ì¾Á°¤Î¥«¥¦¥ó¥¿¤Ï @namecnt ¤ËÆþ¤Ã¤Æ¤¤¤ë¤Î¤Ç, Ä´¤Ù¤ë.
+ # generated name counter is stored in @namecnt
if !@namecnt.key?(prefix)
- # ½é¤á¤Æ»È¤¦ÀÜƬ¸ì¤Ê¤Î¤Ç½é´ü²½¤¹¤ë.
+ # first appearing prefix, initialize
@namecnt[prefix] = 1
else
- # »È¤Ã¤¿¤³¤È¤Î¤¢¤ëÀÜƬ¸ì¤Ê¤Î¤Ç, ¼¡¤Î̾Á°¤Ë¤¹¤ë.
+ # already appeared prefix, generate next name
@namecnt[prefix] += 1
end
return "#{prefix}#{@namecnt[prefix]}"
@@ -85,51 +81,48 @@ end
################
-# class TclTkInterpreter: tcl/tk ¤Î¥¤¥ó¥¿¥×¥ê¥¿
+# class TclTkInterpreter: tcl/tk interpreter
class TclTkInterpreter
- # initialize(): ½é´ü²½.
+ # initialize():
def initialize()
- # ¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤¹¤ë.
+ # generate interpreter object
@ip = TclTkIp.new()
- # ¥¤¥ó¥¿¥×¥ê¥¿¤Ë ruby_fmt ¥³¥Þ¥ó¥É¤òÄɲ乤ë.
- # ruby_fmt ¥³¥Þ¥ó¥É¤È¤Ï, ¸å¤í¤Î°ú¿ô¤ò format ¥³¥Þ¥ó¥É¤Ç½èÍý¤·¤Æ
- # ruby ¥³¥Þ¥ó¥É¤ËÅϤ¹¤â¤Î¤Ç¤¢¤ë.
- # (¤Ê¤ª, ruby ¥³¥Þ¥ó¥É¤Ï, °ú¿ô¤ò 1 ¤Ä¤·¤«¤È¤ì¤Ê¤¤.)
+ # add ruby_fmt command to tcl interpreter
+ # ruby_fmt command format arguments by `format' and call `ruby' command
+ # (notice ruby command receives only one argument)
if $DEBUG
@ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; ruby [format $fmt $args] }")
else
@ip._eval("proc ruby_fmt {fmt args} { ruby [format $fmt $args] }")
end
- # @ip._get_eval_string(*args): tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ë
- # ʸ»úÎó(String)¤òÀ¸À®¤·¤ÆÊÖ¤¹.
- # *args: tcl/tk ¤Çɾ²Á¤¹¤ë¥¹¥¯¥ê¥×¥È(¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥ÈÎó)
+ # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter
+ # *args: script which is going to be evaluated under tcl/tk
def @ip._get_eval_string(*args)
argstr = ""
args.each{|arg|
argstr += " " if argstr != ""
- # ¤â¤· to_eval() ¥á¥½¥Ã¥É¤¬
+ # call to_eval if it is defined
if (arg.respond_to?(:to_eval))
- # ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð¤½¤ì¤ò¸Æ¤Ö.
argstr += arg.to_eval()
else
- # ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð to_s() ¤ò¸Æ¤Ö.
+ # call to_s unless defined
argstr += arg.to_s()
end
}
return argstr
end
- # @ip._eval_args(*args): tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤·,
- # ¤½¤Î·ë²Ì(String)¤òÊÖ¤¹.
- # *args: tcl/tk ¤Çɾ²Á¤¹¤ë¥¹¥¯¥ê¥×¥È(¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥ÈÎó)
+ # @ip._eval_args(*args): evaluate string under tcl/tk interpreter
+ # returns result string.
+ # *args: script which is going to be evaluated under tcl/tk
def @ip._eval_args(*args)
- # ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ëʸ»úÎó¤òµá¤á¤ë.
+ # calculate the string to eval in the interpreter
argstr = _get_eval_string(*args)
- # ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ë.
+ # evaluate under the interpreter
print("_eval: \"", argstr, "\"") if $DEBUG
res = _eval(argstr)
if $DEBUG
@@ -137,219 +130,205 @@ class TclTkInterpreter
elsif _return_value() != 0
print(res, "\n")
end
- fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0
+ fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #'
return res
end
- # tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·, Ï¢ÁÛÇÛÎó¤ËÆþ¤ì¤Æ¤ª¤¯.
+ # generate tcl/tk command object and register in the hash
@commands = {}
- # tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ,
+ # for all commands registered in tcl/tk interpreter:
@ip._eval("info command").split(/ /).each{|comname|
if comname =~ /^[.]/
- # ¥³¥Þ¥ó¥É¤¬¥¦¥£¥¸¥§¥Ã¥È(¤Î¥Ñ¥¹Ì¾)¤Î¾ì¹ç¤Ï
- # TclTkWidget ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òºî¤Ã¤ÆÏ¢ÁÛÇÛÎó¤ËÆþ¤ì¤ë.
+ # if command is a widget (path), generate TclTkWidget,
+ # and register it in the hash
@commands[comname] = TclTkWidget.new(@ip, comname)
else
- # ¤½¤¦¤Ç¤Ê¤¤¾ì¹ç¤Ï
- # TclTkCommand ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òºî¤Ã¤ÆÏ¢ÁÛÇÛÎó¤ËÆþ¤ì¤ë.
+ # otherwise, generate TclTkCommand
@commands[comname] = TclTkCommand.new(@ip, comname)
end
}
end
- # commands(): tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò Hash ¤Ë
- # Æþ¤ì¤¿¤â¤Î¤òÊÖ¤¹.
+ # commands(): returns hash of the tcl/tk commands
def commands()
return @commands
end
- # rootwidget(): ¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È(TclTkWidget)¤òÊÖ¤¹.
+ # rootwidget(): returns root widget(TclTkWidget)
def rootwidget()
return @commands["."]
end
- # _tcltkip(): @ip(TclTkIp) ¤òÊÖ¤¹.
+ # _tcltkip(): returns @ip(TclTkIp)
def _tcltkip()
return @ip
end
- # method_missing(id, *args): ̤ÄêµÁ¤Î¥á¥½¥Ã¥É¤Ï tcl/tk ¤Î¥³¥Þ¥ó¥É¤È¤ß¤Ê¤·¤Æ
- # ¼Â¹Ô¤·, ¤½¤Î·ë²Ì(String)¤òÊÖ¤¹.
- # id: ¥á¥½¥Ã¥É¤Î¥·¥ó¥Ü¥ë
- # *args: ¥³¥Þ¥ó¥É¤Î°ú¿ô
+ # method_missing(id, *args): execute undefined method as tcl/tk command
+ # id: method symbol
+ # *args: method arguments
def method_missing(id, *args)
- # ¤â¤·, ¥á¥½¥Ã¥É¤Î tcl/tk ¥³¥Þ¥ó¥É¤¬
+ # if command named by id registered, then execute it
if @commands.key?(id.id2name)
- # ¤¢¤ì¤Ð, ¼Â¹Ô¤·¤Æ·ë²Ì¤òÊÖ¤¹.
return @commands[id.id2name].e(*args)
else
- # ̵¤±¤ì¤Ð¤â¤È¤â¤È¤Î½èÍý.
+ # otherwise, exception
super
end
end
end
-# class TclTkObject: tcl/tk ¤Î¥ª¥Ö¥¸¥§¥¯¥È
-# (´ðÄ쥯¥é¥¹¤È¤·¤Æ»È¤¦.
-# tcltk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¿Í¤¬ TclTkObject.new() ¤¹¤ë¤³¤È¤Ï¤Ê¤¤¤Ï¤º.)
+# class TclTkObject: base class of the tcl/tk objects
class TclTkObject
- # initialize(ip, exp): ½é´ü²½.
- # ip: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkIp)
- # exp: tcl/tk ¤Ç¤Îɽ¸½·Á
+ # initialize(ip, exp):
+ # ip: interpreter(TclTkIp)
+ # exp: tcl/tk representation
def initialize(ip, exp)
fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp)
@ip = ip
@exp = exp
end
- # to_s(): tcl/tk ¤Ç¤Îɽ¸½·Á(String)¤òÊÖ¤¹.
+ # to_s(): returns tcl/tk representation
def to_s()
return @exp
end
end
-# class TclTkCommand: tcl/tk ¤Î¥³¥Þ¥ó¥É
-# (tcltk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¿Í¤¬ TclTkCommand.new() ¤¹¤ë¤³¤È¤Ï¤Ê¤¤¤Ï¤º.
-# TclTkInterpreter:initialize() ¤«¤é new() ¤µ¤ì¤ë.)
+# class TclTkCommand: tcl/tk commands
+# you should not call TclTkCommand.new()
+# commands are created by TclTkInterpreter:initialize()
class TclTkCommand < TclTkObject
- # e(*args): ¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤·, ¤½¤Î·ë²Ì(String)¤òÊÖ¤¹.
- # (e ¤Ï exec ¤Þ¤¿¤Ï eval ¤Î e.)
- # *args: ¥³¥Þ¥ó¥É¤Î°ú¿ô
+ # e(*args): execute command. returns String (e is for exec or eval)
+ # *args: command arguments
def e(*args)
return @ip._eval_args(to_s(), *args)
end
end
-# class TclTkLibCommand: tcl/tk ¤Î¥³¥Þ¥ó¥É
-# (¥é¥¤¥Ö¥é¥ê¤Ë¤è¤ê¼Â¸½¤µ¤ì¤ë¥³¥Þ¥ó¥É¤Ç, tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤ËºÇ½é¤«¤é
-# ¸ºß¤·¤Ê¤¤¤â¤Î¤Ï, ¥¤¥ó¥¿¥×¥ê¥¿¤Î commands() ¤Ç¤ÏÀ¸À®¤Ç¤­¤Ê¤¤.
-# ¤½¤Î¤è¤¦¤Ê¤â¤Î¤ËÂФ·, ¥³¥Þ¥ó¥É¤Î̾Á°¤«¤é TclTkCommand ¥ª¥Ö¥¸¥§¥¯¥È¤ò
-# À¸À®¤¹¤ë.
+# class TclTkLibCommand: tcl/tk commands in the library
class TclTkLibCommand < TclTkCommand
- # initialize(ip, name): ½é´ü²½
- # ip: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkInterpreter)
- # name: ¥³¥Þ¥ó¥É̾ (String)
+ # initialize(ip, name):
+ # ip: interpreter(TclTkInterpreter)
+ # name: command name (String)
def initialize(ip, name)
super(ip._tcltkip, name)
end
end
-# class TclTkVariable: tcl/tk ¤ÎÊÑ¿ô
+# class TclTkVariable: tcl/tk variable
class TclTkVariable < TclTkObject
- # initialize(interp, dat): ½é´ü²½.
- # interp: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkInterpreter)
- # dat: ÀßÄꤹ¤ëÃÍ(String)
- # nil ¤Ê¤é, ÀßÄꤷ¤Ê¤¤.
+ # initialize(interp, dat):
+ # interp: interpreter(TclTkInterpreter)
+ # dat: the value to set(String)
+ # if nil, not initialize variable
def initialize(interp, dat)
- # tcl/tk ¤Ç¤Îɽ¸½·Á(ÊÑ¿ô̾)¤ò¼«Æ°À¸À®¤¹¤ë.
+ # auto-generate tcl/tk representation (variable name)
exp = TclTk._newname("v_")
- # TclTkObject ¤ò½é´ü²½¤¹¤ë.
+ # initialize TclTkObject
super(interp._tcltkip(), exp)
- # set ¥³¥Þ¥ó¥É¤ò»È¤¦¤Î¤Ç¤È¤Ã¤Æ¤ª¤¯.
+ # safe this for `set' command
@set = interp.commands()["set"]
- # ÃͤòÀßÄꤹ¤ë.
+ # set value
set(dat) if dat
end
- # tcl/tk ¤Î set ¤ò»È¤¨¤Ð, ÃͤÎÀßÄê/»²¾È¤Ï¤Ç¤­¤ë¤¬,
- # ¤½¤ì¤À¤±¤Ç¤Ï¤Ê¤ó¤Ê¤Î¤Ç, °ì±þ, ¥á¥½¥Ã¥É¤ò¤«¤Ö¤»¤¿¤â¤Î¤âÍÑ°Õ¤·¤Æ¤ª¤¯.
+ # although you can set/refer variable by using set in tcl/tk,
+ # we provide the method for accessing variables
- # set(data): tcl/tk ¤ÎÊÑ¿ô¤Ë set ¤òÍѤ¤¤ÆÃͤòÀßÄꤹ¤ë.
- # data: ÀßÄꤹ¤ëÃÍ
+ # set(data): set tcl/tk variable using `set'
+ # data: new value
def set(data)
@set.e(to_s(), data.to_s())
end
- # get(): tcl/tk ¤ÎÊÑ¿ô¤ÎÃÍ(String)¤ò set ¤òÍѤ¤¤ÆÆɤߤÀ¤·ÊÖ¤¹.
+ # get(): read tcl/tk variable(String) using `set'
def get()
return @set.e(to_s())
end
end
-# class TclTkWidget: tcl/tk ¤Î¥¦¥£¥¸¥§¥Ã¥È
+# class TclTkWidget: tcl/tk widget
class TclTkWidget < TclTkCommand
- # initialize(*args): ½é´ü²½.
- # *args: ¥Ñ¥é¥á¡¼¥¿
+ # initialize(*args):
+ # *args: parameters
def initialize(*args)
if args[0].kind_of?(TclTkIp)
- # ºÇ½é¤Î°ú¿ô¤¬ TclTkIp ¤Î¾ì¹ç:
+ # in case the 1st argument is TclTkIp:
- # ´û¤Ë tcl/tk ¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥¦¥£¥¸¥§¥Ã¥È¤Ë TclTkWidget ¤Î¹½Â¤¤ò
- # ¤«¤Ö¤»¤ë. (TclTkInterpreter:initialize() ¤«¤é»È¤ï¤ì¤ë.)
+ # Wrap tcl/tk widget by TclTkWidget
+ # (used in TclTkInterpreter#initialize())
- # ¥Ñ¥é¥á¡¼¥¿¿ô¤¬ 2 ¤Ç¤Ê¤±¤ì¤Ð¥¨¥é¡¼.
+ # need two arguments
fail("illegal # of parameter") if args.size != 2
- # ip: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkIp)
- # exp: tcl/tk ¤Ç¤Îɽ¸½·Á
+ # ip: interpreter(TclTkIp)
+ # exp: tcl/tk representation
ip, exp = args
- # TclTkObject ¤ò½é´ü²½¤¹¤ë.
+ # initialize TclTkObject
super(ip, exp)
elsif args[0].kind_of?(TclTkInterpreter)
- # ºÇ½é¤Î°ú¿ô¤¬ TclTkInterpreter ¤Î¾ì¹ç:
+ # in case 1st parameter is TclTkInterpreter:
- # ¿Æ¥¦¥£¥¸¥§¥Ã¥È¤«¤é¿·¤¿¤Ê¥¦¥£¥¸¥§¥È¤òÀ¸À®¤¹¤ë.
+ # generate new widget from parent widget
- # interp: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkInterpreter)
- # parent: ¿Æ¥¦¥£¥¸¥§¥Ã¥È
- # command: ¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë¥³¥Þ¥ó¥É(label Åù)
- # *args: command ¤ËÅϤ¹°ú¿ô
+ # interp: interpreter(TclTkInterpreter)
+ # parent: parent widget
+ # command: widget generating tk command(label Åù)
+ # *args: argument to the command
interp, parent, command, *args = args
- # ¥¦¥£¥¸¥§¥Ã¥È¤Î̾Á°¤òºî¤ë.
+ # generate widget name
exp = parent.to_s()
exp += "." if exp !~ /[.]$/
exp += TclTk._newname("w_")
- # TclTkObject ¤ò½é´ü²½¤¹¤ë.
+ # initialize TclTkObject
super(interp._tcltkip(), exp)
- # ¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë.
+ # generate widget
res = @ip._eval_args(command, exp, *args)
# fail("can't create Widget") if res != exp
- # tk_optionMenu ¤Ç¤Ï, ¥Ü¥¿¥ó̾¤ò exp ¤Ç»ØÄꤹ¤ë¤È
- # res ¤Ë¥á¥Ë¥å¡¼Ì¾¤òÊÖ¤¹¤Î¤Ç res != exp ¤È¤Ê¤ë.
+ # for tk_optionMenu, it is legal res != exp
else
fail("first parameter is not TclTkInterpreter")
end
end
end
-# class TclTkCallback: tcl/tk ¤Î¥³¡¼¥ë¥Ð¥Ã¥¯
+# class TclTkCallback: tcl/tk callbacks
class TclTkCallback < TclTkObject
- # initialize(interp, pr, arg): ½é´ü²½.
- # interp: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkInterpreter)
- # pr: ¥³¡¼¥ë¥Ð¥Ã¥¯¼ê³¤­(Proc)
- # arg: pr ¤Î¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤ËÅϤ¹Ê¸»úÎó
- # tcl/tk ¤Î bind ¥³¥Þ¥ó¥É¤Ç¤Ï¥Ñ¥é¥á¡¼¥¿¤ò¼õ¤±¼è¤ë¤¿¤á¤Ë % ÃÖ´¹¤ò
- # ÍѤ¤¤ë¤¬, pr ¤ÎÆâÉô¤Ç % ¤ò½ñ¤¤¤Æ¤â¤¦¤Þ¤¯¤¤¤«¤Ê¤¤.
- # arg ¤Ëʸ»úÎó¤ò½ñ¤¤¤Æ¤ª¤¯¤È, ¤½¤ÎÃÖ´¹·ë²Ì¤ò, pr ¤Ç
- # ¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤òÄ̤·¤Æ¼õ¤±¼è¤ë¤³¤È¤¬¤Ç¤­¤ë.
- # scrollbar ¥³¥Þ¥ó¥É¤Î -command ¥ª¥×¥·¥ç¥ó¤Î¤è¤¦¤Ë
- # ²¿¤â»ØÄꤷ¤Ê¤¯¤Æ¤â¥Ñ¥é¥á¡¼¥¿¤¬ÉÕ¤¯¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¤Ï,
- # arg ¤ò»ØÄꤷ¤Æ¤Ï¤Ê¤é¤Ê¤¤.
+ # initialize(interp, pr, arg):
+ # interp: interpreter(TclTkInterpreter)
+ # pr: callback procedure(Proc)
+ # arg: string to pass as block parameters of pr
+ # bind command of tcl/tk uses % replacement for parameters
+ # pr can receive replaced data using block parameter
+ # its format is specified by arg string
+ # You should not specify arg for the command like
+ # scrollbar with -command option, which receives parameters
+ # without specifying any replacement
def initialize(interp, pr, arg = nil)
- # tcl/tk ¤Ç¤Îɽ¸½·Á(ÊÑ¿ô̾)¤ò¼«Æ°À¸À®¤¹¤ë.
+ # auto-generate tcl/tk representation (variable name)
exp = TclTk._newname("c_")
- # TclTkObject ¤ò½é´ü²½¤¹¤ë.
+ # initialize TclTkObject
super(interp._tcltkip(), exp)
- # ¥Ñ¥é¥á¡¼¥¿¤ò¤È¤Ã¤Æ¤ª¤¯.
+ # save parameters
@pr = pr
@arg = arg
- # ¥â¥¸¥å¡¼¥ë¤ËÅÐÏ¿¤·¤Æ¤ª¤¯.
+ # register in the module
TclTk._addcallback(self)
end
- # to_eval(): @ip._eval_args ¤Çɾ²Á¤¹¤ë¤È¤­¤Îɽ¸½·Á(String)¤òÊÖ¤¹.
+ # to_eval(): retuens string representation for @ip._eval_args
def to_eval()
if @arg
- # %s ¤Ï ruby_fmt ¤è¤êÁ°¤Ë bind ¤Ë¤è¤êÃÖ´¹¤µ¤ì¤Æ¤·¤Þ¤¦¤Î¤Ç
- # %%s ¤È¤·¤Æ¤¢¤ë. ¤·¤¿¤¬¤Ã¤Æ, ¤³¤ì¤Ï bind ÀìÍÑ.
+ # bind replaces %s before calling ruby_fmt, so %%s is used
s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/
else
s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/
@@ -358,28 +337,28 @@ class TclTkCallback < TclTkObject
return s
end
- # _call(arg): ¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹.
- # arg: ¥³¡¼¥ë¥Ð¥Ã¥¯¤ËÅϤµ¤ì¤ë¥Ñ¥é¥á¡¼¥¿
+ # _call(arg): invoke callback
+ # arg: callback parameter
def _call(arg)
@pr.call(arg)
end
end
-# class TclTkImage: tcl/tk ¤Î¥¤¥á¡¼¥¸
+# class TclTkImage: tcl/tk images
class TclTkImage < TclTkCommand
- # initialize(interp, t, *args): ½é´ü²½.
- # ¥¤¥á¡¼¥¸¤ÎÀ¸À®¤Ï TclTkImage.new() ¤Ç¹Ô¤¦¤¬,
- # Ç˲õ¤Ï image delete ¤Ç¹Ô¤¦. (¤¤¤Þ¤¤¤Á¤À¤±¤É»ÅÊý¤¬Ìµ¤¤.)
- # interp: ¥¤¥ó¥¿¥×¥ê¥¿(TclTkInterpreter)
- # t: ¥¤¥á¡¼¥¸¤Î¥¿¥¤¥× (photo, bitmap, etc.)
- # *args: ¥³¥Þ¥ó¥É¤Î°ú¿ô
+ # initialize(interp, t, *args):
+ # generating image is done by TclTkImage.new()
+ # destrying is done by image delete (inconsistent, sigh)
+ # interp: interpreter(TclTkInterpreter)
+ # t: image type (photo, bitmap, etc.)
+ # *args: command argument
def initialize(interp, t, *args)
- # tcl/tk ¤Ç¤Îɽ¸½·Á(ÊÑ¿ô̾)¤ò¼«Æ°À¸À®¤¹¤ë.
+ # auto-generate tcl/tk representation
exp = TclTk._newname("i_")
- # TclTkObject ¤ò½é´ü²½¤¹¤ë.
+ # initialize TclTkObject
super(interp._tcltkip(), exp)
- # ¥¤¥á¡¼¥¸¤òÀ¸À®¤¹¤ë.
+ # generate image
res = @ip._eval_args("image create", t, exp, *args)
fail("can't create Image") if res != exp
end
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
index e7fe77d2b7..625fe61ccc 100644
--- a/ext/tcltklib/tcltklib.c
+++ b/ext/tcltklib/tcltklib.c
@@ -5,22 +5,31 @@
*/
#include "ruby.h"
-#include "sig.h"
+#include "rubysig.h"
#include <stdio.h>
#include <string.h>
#include <tcl.h>
#include <tk.h>
-/* for debug */
+#ifdef __MACOS__
+# include <tkMac.h>
+# include <Quickdraw.h>
+#endif
-#define DUMP1(ARG1) if (debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
-#define DUMP2(ARG1, ARG2) if (debug) { fprintf(stderr, "tcltklib: ");\
+/* for rb_debug */
+
+#define DUMP1(ARG1) if (rb_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
+#define DUMP2(ARG1, ARG2) if (rb_debug) { fprintf(stderr, "tcltklib: ");\
fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
/*
#define DUMP1(ARG1)
#define DUMP2(ARG1, ARG2)
*/
+/* for callback break & continue */
+VALUE eTkCallbackBreak;
+VALUE eTkCallbackContinue;
+
/* from tkAppInit.c */
/*
@@ -33,26 +42,52 @@ int *tclDummyMathPtr = (int *) matherr;
/*---- module TclTkLib ----*/
-static VALUE thread_safe = Qnil;
+/* Tk_ThreadTimer */
+typedef struct {
+ Tcl_TimerToken token;
+ int flag;
+} Tk_TimerData;
+
+/* timer callback */
+void _timer_for_tcl (ClientData clientData)
+{
+ Tk_TimerData *timer = (Tk_TimerData*)clientData;
+
+ timer->flag = 0;
+ CHECK_INTS;
+#ifdef USE_THREAD
+ if (!rb_thread_critical) rb_thread_schedule();
+#endif
+
+ timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
+ (ClientData)timer);
+ timer->flag = 1;
+}
/* execute Tk_MainLoop */
static VALUE
lib_mainloop(VALUE self)
{
- int old_trapflg;
- int flags = RTEST(thread_safe)?TCL_DONT_WAIT:0;
+ Tk_TimerData *timer;
+
+ timer = (Tk_TimerData *) ckalloc(sizeof(Tk_TimerData));
+ timer->flag = 0;
+ timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
+ (ClientData)timer);
+ timer->flag = 1;
DUMP1("start Tk_Mainloop");
while (Tk_GetNumMainWindows() > 0) {
- old_trapflg = trap_immediate;
- trap_immediate = 1;
- Tcl_DoOneEvent(flags);
- trap_immediate = old_trapflg;
- CHECK_INTS;
- flags = (thread_safe == 0 || thread_safe == Qnil)?0:TCL_DONT_WAIT;
+ Tcl_DoOneEvent(0);
}
DUMP1("stop Tk_Mainloop");
+#ifdef USE_THREAD
+ if (timer->flag) {
+ Tk_DeleteTimerHandler(timer->token);
+ }
+#endif
+
return Qnil;
}
@@ -71,27 +106,49 @@ ip_eval_rescue(VALUE *failed, VALUE einfo)
}
static int
+#if TCL_MAJOR_VERSION >= 8
+ip_ruby(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *CONST argv[])
+#else
ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
+#endif
{
VALUE res;
int old_trapflg;
VALUE failed = 0;
+ char *arg;
+ int dummy;
/* ruby command has 1 arg. */
if (argc != 2) {
- ArgError("wrong # of arguments (%d for 1)", argc);
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
}
+ /* get C string from Tcl object */
+#if TCL_MAJOR_VERSION >= 8
+ arg = Tcl_GetStringFromObj(argv[1], &dummy);
+#else
+ arg = argv[1];
+#endif
+
/* evaluate the argument string by ruby */
- DUMP2("rb_eval_string(%s)", argv[1]);
- old_trapflg = trap_immediate;
- trap_immediate = 0;
- res = rb_rescue(rb_eval_string, argv[1], ip_eval_rescue, &failed);
- trap_immediate = old_trapflg;
+ DUMP2("rb_eval_string(%s)", arg);
+ old_trapflg = rb_trap_immediate;
+ rb_trap_immediate = 0;
+ res = rb_rescue(rb_eval_string, (VALUE)arg, ip_eval_rescue, (VALUE)&failed);
+ rb_trap_immediate = old_trapflg;
+ Tcl_ResetResult(interp);
if (failed) {
- Tcl_AppendResult(interp, RSTRING(failed)->ptr, (char*)NULL);
- return TCL_ERROR;
+ VALUE eclass = CLASS_OF(failed);
+ Tcl_AppendResult(interp, STR2CSTR(failed), (char*)NULL);
+ if (eclass == eTkCallbackBreak) {
+ return TCL_BREAK;
+ } else if (eclass == eTkCallbackContinue) {
+ return TCL_CONTINUE;
+ } else {
+ return TCL_ERROR;
+ }
}
/* result must be string or nil */
@@ -99,12 +156,11 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
DUMP1("(rb_eval_string result) nil");
return TCL_OK;
}
- Check_Type(res, T_STRING);
/* copy result to the tcl interpreter */
- DUMP2("(rb_eval_string result) %s", RSTRING(res)->ptr);
+ DUMP2("(rb_eval_string result) %s", STR2CSTR(res));
DUMP1("Tcl_AppendResult");
- Tcl_AppendResult(interp, RSTRING(res)->ptr, (char *)NULL);
+ Tcl_AppendResult(interp, STR2CSTR(res), (char *)NULL);
return TCL_OK;
}
@@ -115,6 +171,7 @@ ip_free(struct tcltkip *ptr)
{
DUMP1("Tcl_DeleteInterp");
Tcl_DeleteInterp(ptr->ip);
+ free(ptr);
}
/* create and initialize interpreter */
@@ -135,20 +192,26 @@ ip_new(VALUE self)
/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
- Fail("Tcl_Init");
+ rb_raise(rb_eRuntimeError, "Tcl_Init");
}
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
- Fail("Tk_Init");
+ rb_raise(rb_eRuntimeError, "Tk_Init");
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
(Tcl_PackageInitProc *) NULL);
/* add ruby command to the interpreter */
+#if TCL_MAJOR_VERSION >= 8
+ DUMP1("Tcl_CreateObjCommand(\"ruby\")");
+ Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData *)NULL,
+ (Tcl_CmdDeleteProc *)NULL);
+#else
DUMP1("Tcl_CreateCommand(\"ruby\")");
Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData *)NULL,
(Tcl_CmdDeleteProc *)NULL);
+#endif
return obj;
}
@@ -157,6 +220,7 @@ ip_new(VALUE self)
static VALUE
ip_eval(VALUE self, VALUE str)
{
+ char *s;
char *buf; /* Tcl_Eval requires re-writable string region */
struct tcltkip *ptr; /* tcltkip data struct */
@@ -164,18 +228,162 @@ ip_eval(VALUE self, VALUE str)
Data_Get_Struct(self, struct tcltkip, ptr);
/* call Tcl_Eval() */
- Check_Type(str, T_STRING);
- buf = ALLOCA_N(char,RSTRING(str)->len+1);
- strcpy(buf, RSTRING(str)->ptr);
+ s = STR2CSTR(str);
+ buf = ALLOCA_N(char, strlen(s)+1);
+ strcpy(buf, s);
DUMP2("Tcl_Eval(%s)", buf);
ptr->return_value = Tcl_Eval(ptr->ip, buf);
if (ptr->return_value == TCL_ERROR) {
- Fail(ptr->ip->result);
+ rb_raise(rb_eRuntimeError, ptr->ip->result);
}
DUMP2("(TCL_Eval result) %d", ptr->return_value);
/* pass back the result (as string) */
- return(str_new2(ptr->ip->result));
+ return(rb_str_new2(ptr->ip->result));
+}
+
+
+static VALUE
+ip_toUTF8(VALUE self, VALUE str, VALUE encodename)
+{
+#ifndef TCL_UTF_MAX
+ return str;
+#else
+ Tcl_Interp *interp;
+ Tcl_Encoding encoding;
+ Tcl_DString dstr;
+ struct tcltkip *ptr;
+ char *buff1,*buff2;
+
+ Data_Get_Struct(self,struct tcltkip, ptr);
+ interp = ptr->ip;
+
+ encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
+ buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
+ strcpy(buff1,STR2CSTR(str));
+
+ Tcl_DStringInit(&dstr);
+ Tcl_DStringFree(&dstr);
+ Tcl_ExternalToUtfDString(encoding,buff1,strlen(buff1),&dstr);
+ buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
+ strcpy(buff2,Tcl_DStringValue(&dstr));
+
+ Tcl_FreeEncoding(encoding);
+ Tcl_DStringFree(&dstr);
+
+ return rb_str_new2(buff2);
+#endif
+}
+
+static VALUE
+ip_fromUTF8(VALUE self, VALUE str, VALUE encodename)
+{
+#ifndef TCL_UTF_MAX
+ return str;
+#else
+ Tcl_Interp *interp;
+ Tcl_Encoding encoding;
+ Tcl_DString dstr;
+ struct tcltkip *ptr;
+ char *buff1,*buff2;
+
+ Data_Get_Struct(self,struct tcltkip, ptr);
+ interp = ptr->ip;
+
+ encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
+ buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
+ strcpy(buff1,STR2CSTR(str));
+
+ Tcl_DStringInit(&dstr);
+ Tcl_DStringFree(&dstr);
+ Tcl_UtfToExternalDString(encoding,buff1,strlen(buff1),&dstr);
+ buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
+ strcpy(buff2,Tcl_DStringValue(&dstr));
+
+ Tcl_FreeEncoding(encoding);
+ Tcl_DStringFree(&dstr);
+
+ return rb_str_new2(buff2);
+#endif
+}
+
+
+static VALUE
+ip_invoke(int argc, VALUE *argv, VALUE obj)
+{
+ struct tcltkip *ptr; /* tcltkip data struct */
+ int i;
+ int object = 0;
+ Tcl_CmdInfo info;
+ char *cmd;
+ char **av = (char **)NULL;
+#if TCL_MAJOR_VERSION >= 8
+ Tcl_Obj **ov = (Tcl_Obj **)NULL;
+ Tcl_Obj *resultPtr;
+#endif
+
+ /* get the data struct */
+ Data_Get_Struct(obj, struct tcltkip, ptr);
+
+ /* get the command name string */
+ cmd = STR2CSTR(argv[0]);
+
+ /* map from the command name to a C procedure */
+ if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
+ rb_raise(rb_eNameError, "invalid command name `%s'", cmd);
+ }
+#if TCL_MAJOR_VERSION >= 8
+ object = info.isNativeObjectProc;
+#endif
+
+ /* memory allocation for arguments of this command */
+ if (object) {
+#if TCL_MAJOR_VERSION >= 8
+ /* object interface */
+ ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
+ for (i = 0; i < argc; ++i) {
+ char *s = STR2CSTR(argv[i]);
+ ov[i] = Tcl_NewStringObj(s, strlen(s));
+ }
+ ov[argc] = (Tcl_Obj *)NULL;
+#endif
+ } else {
+ /* string interface */
+ av = (char **)ALLOCA_N(char *, argc+1);
+ for (i = 0; i < argc; ++i) {
+ char *s = STR2CSTR(argv[i]);
+
+ av[i] = ALLOCA_N(char, strlen(s)+1);
+ strcpy(av[i], s);
+ }
+ av[argc] = (char *)NULL;
+ }
+
+ Tcl_ResetResult(ptr->ip);
+
+ /* Invoke the C procedure */
+ if (object) {
+#if TCL_MAJOR_VERSION >= 8
+ int dummy;
+ ptr->return_value = (*info.objProc)(info.objClientData,
+ ptr->ip, argc, ov);
+
+ /* get the string value from the result object */
+ resultPtr = Tcl_GetObjResult(ptr->ip);
+ Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
+ TCL_VOLATILE);
+#endif
+ } else {
+ ptr->return_value = (*info.proc)(info.clientData,
+ ptr->ip, argc, av);
+ }
+
+ if (ptr->return_value == TCL_ERROR) {
+ rb_raise(rb_eRuntimeError, ptr->ip->result);
+ }
+
+ /* pass back the result (as string) */
+ return(rb_str_new2(ptr->ip->result));
}
/* get return code from Tcl_Eval() */
@@ -190,27 +398,44 @@ ip_retval(VALUE self)
return (INT2FIX(ptr->return_value));
}
+#ifdef __MACOS__
+static void
+_macinit()
+{
+ tcl_macQdPtr = &qd; /* setup QuickDraw globals */
+ Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
+}
+#endif
+
/*---- initialization ----*/
void Init_tcltklib()
{
extern VALUE rb_argv0; /* the argv[0] */
VALUE lib = rb_define_module("TclTkLib");
- VALUE ip = rb_define_class("TclTkIp", cObject);
+ VALUE ip = rb_define_class("TclTkIp", rb_cObject);
+
+ eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
+ eTkCallbackContinue = rb_define_class("TkCallbackContinue",rb_eStandardError);
rb_define_module_function(lib, "mainloop", lib_mainloop, 0);
rb_define_singleton_method(ip, "new", ip_new, 0);
rb_define_method(ip, "_eval", ip_eval, 1);
+ rb_define_method(ip, "_toUTF8",ip_toUTF8,2);
+ rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2);
+ rb_define_method(ip, "_invoke", ip_invoke, -1);
rb_define_method(ip, "_return_value", ip_retval, 0);
rb_define_method(ip, "mainloop", lib_mainloop, 0);
+#ifdef __MACOS__
+ _macinit();
+#endif
+
/*---- initialize tcl/tk libraries ----*/
/* from Tk_Main() */
DUMP1("Tcl_FindExecutable");
Tcl_FindExecutable(RSTRING(rb_argv0)->ptr);
-
- rb_define_variable("$tk_thread_safe", &thread_safe);
}
/* eof */
diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST
new file mode 100644
index 0000000000..9689186bf0
--- /dev/null
+++ b/ext/tk/MANIFEST
@@ -0,0 +1,25 @@
+MANIFEST
+extconf.rb
+depend
+tkutil.c
+lib/tk.rb
+lib/tkafter.rb
+lib/tkbgerror.rb
+lib/tkcanvas.rb
+lib/tkclass.rb
+lib/tkdialog.rb
+lib/tkentry.rb
+lib/tkfont.rb
+lib/tkmenubar.rb
+lib/tkmngfocus.rb
+lib/tkpalette.rb
+lib/tkscrollbox.rb
+lib/tktext.rb
+lib/tkvirtevent.rb
+sample/tkbiff.rb
+sample/tkbrowse.rb
+sample/tkdialog.rb
+sample/tkfrom.rb
+sample/tkhello.rb
+sample/tkline.rb
+sample/tktimer.rb
diff --git a/ext/tk/depend b/ext/tk/depend
new file mode 100644
index 0000000000..e325a82c0f
--- /dev/null
+++ b/ext/tk/depend
@@ -0,0 +1 @@
+tkutil.o: tkutil.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
new file mode 100644
index 0000000000..f769b06e30
--- /dev/null
+++ b/ext/tk/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile("tkutil")
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
new file mode 100644
index 0000000000..e32723be96
--- /dev/null
+++ b/ext/tk/lib/tk.rb
@@ -0,0 +1,2499 @@
+#
+# tk.rb - Tk interface modue using tcltklib
+# $Date$
+# by Yukihiro Matsumoto <matz@netlab.co.jp>
+
+# use Shigehiro's tcltklib
+require "tcltklib"
+require "tkutil"
+
+module TkComm
+ None = Object.new
+ def None.to_s
+ 'None'
+ end
+
+ Tk_CMDTBL = {}
+ Tk_WINDOWS = {}
+
+ def error_at
+ frames = caller()
+ frames.delete_if do |c|
+ c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
+ end
+ frames
+ end
+ private :error_at
+
+ def _genobj_for_tkwidget(path)
+ return TkRoot.new if path == '.'
+
+ begin
+ tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
+ rescue
+ return path
+ end
+
+ ruby_class = TkClassBind::WidgetClassNameTBL[tk_class]
+ gen_class_name = ruby_class.name + 'GeneratedOnTk'
+ unless Object.const_defined? gen_class_name
+ eval "class #{gen_class_name}<#{ruby_class.name}
+ def initialize(path)
+ @path=path
+ Tk_WINDOWS[@path] = self
+ end
+ end"
+ end
+ eval "#{gen_class_name}.new('#{path}')"
+ end
+
+ def tk_tcl2ruby(val)
+ if val =~ /^rb_out (c\d+)/
+ return Tk_CMDTBL[$1]
+ end
+ if val.include? ?\s
+ return val.split.collect{|v| tk_tcl2ruby(v)}
+ end
+ case val
+ when /^@font/
+ TkFont.get_obj(val)
+ when /^-?\d+$/
+ val.to_i
+ when /^\./
+ Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
+ when / /
+ val.split.collect{|elt|
+ tk_tcl2ruby(elt)
+ }
+ when /^-?\d+\.\d*$/
+ val.to_f
+ else
+ val
+ end
+ end
+
+ def tk_split_list(str)
+ return [] if str == ""
+ idx = str.index('{')
+ return tk_tcl2ruby(str) unless idx
+
+ list = tk_tcl2ruby(str[0,idx])
+ list = [] if list == ""
+ str = str[idx+1..-1]
+ i = -1
+ brace = 1
+ str.each_byte {|c|
+ i += 1
+ brace += 1 if c == ?{
+ brace -= 1 if c == ?}
+ break if brace == 0
+ }
+ if str[0, i] == ' '
+ list.push ' '
+ else
+ list.push tk_split_list(str[0, i])
+ end
+ list += tk_split_list(str[i+1..-1])
+ list
+ end
+
+ def tk_split_simplelist(str)
+ return [] if str == ""
+ idx = str.index('{')
+ return str.split unless idx
+
+ list = str[0,idx].split
+ str = str[idx+1..-1]
+ i = -1
+ brace = 1
+ str.each_byte {|c|
+ i += 1
+ brace += 1 if c == ?{
+ brace -= 1 if c == ?}
+ break if brace == 0
+ }
+ if i == 0
+ list.push ''
+ elsif str[0, i] == ' '
+ list.push ' '
+ else
+ list.push str[0..i-1]
+ end
+ list += tk_split_simplelist(str[i+1..-1])
+ list
+ end
+ private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
+
+ def hash_kv(keys)
+ conf = []
+ if keys and keys != None
+ for k, v in keys
+ conf.push("-#{k}")
+ conf.push(v)
+ end
+ end
+ conf
+ end
+ private :hash_kv
+
+ def array2tk_list(ary)
+ ary.collect{|e|
+ if e.kind_of? Array
+ "{#{array2tk_list(e)}}"
+ elsif e.kind_of? Hash
+ "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
+ else
+ s = _get_eval_string(e)
+ (s.index(/\s/))? "{#{s}}": s
+ end
+ }.join(" ")
+ end
+ private :array2tk_list
+
+ def bool(val)
+ case val
+ when "1", 1, 'yes', 'true'
+ TRUE
+ else
+ FALSE
+ end
+ end
+ def number(val)
+ case val
+ when /^-?\d+$/
+ val.to_i
+ when /^-?\d+\.\d*$/
+ val.to_f
+ else
+ val
+ end
+ end
+ def string(val)
+ if val == "{}"
+ ''
+ elsif val[0] == ?{
+ val[1..-2]
+ else
+ val
+ end
+ end
+ def list(val)
+ tk_split_list(val).to_a
+ end
+ def window(val)
+ Tk_WINDOWS[val]
+ end
+ def procedure(val)
+ if val =~ /^rb_out (c\d+)/
+ Tk_CMDTBL[$1]
+ else
+ nil
+ end
+ end
+ private :bool, :number, :string, :list, :window, :procedure
+
+ def _get_eval_string(str)
+ return nil if str == None
+ if str.kind_of?(Hash)
+ str = hash_kv(str).join(" ")
+ elsif str.kind_of?(Array)
+ str = array2tk_list(str)
+ elsif str.kind_of?(Proc)
+ str = install_cmd(str)
+ elsif str == nil
+ str = ""
+ elsif str == false
+ str = "0"
+ elsif str == true
+ str = "1"
+ elsif (str.respond_to?(:to_eval))
+ str = str.to_eval()
+ else
+ str = str.to_s()
+ end
+ return str
+ end
+ private :_get_eval_string
+
+ Tk_IDs = [0, 0] # [0]-cmdid, [1]-winid
+ def _curr_cmd_id
+ id = format("c%.4d", Tk_IDs[0])
+ end
+ def _next_cmd_id
+ id = _curr_cmd_id
+ Tk_IDs[0] += 1
+ id
+ end
+ def install_cmd(cmd)
+ return '' if cmd == ''
+ id = _next_cmd_id
+ Tk_CMDTBL[id] = cmd
+ @cmdtbl = [] if not @cmdtbl
+ @cmdtbl.push id
+ return format("rb_out %s", id);
+ end
+ def uninstall_cmd(id)
+ Tk_CMDTBL[id] = nil
+ end
+ private :install_cmd, :uninstall_cmd
+
+ def install_win(ppath)
+ id = format("w%.4d", Tk_IDs[1])
+ Tk_IDs[1] += 1
+ if !ppath or ppath == "."
+ @path = format(".%s", id);
+ else
+ @path = format("%s.%s", ppath, id)
+ end
+ Tk_WINDOWS[@path] = self
+ end
+
+ def uninstall_win()
+ Tk_WINDOWS[@path] = nil
+ end
+
+ class Event
+ def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy)
+ @serial = seq
+ @num = b
+ @focus = (f == 1)
+ @height = h
+ @keycode = k
+ @state = s
+ @time = t
+ @width = w
+ @x = x
+ @y = y
+ @char = aa
+ @send_event = (ee == 1)
+ @keysym = kk
+ @keysym_num = nn
+ @type = tt
+ @widget = ww
+ @x_root = xx
+ @y_root = yy
+ end
+ attr :serial
+ attr :num
+ attr :focus
+ attr :height
+ attr :keycode
+ attr :state
+ attr :time
+ attr :width
+ attr :x
+ attr :y
+ attr :char
+ attr :send_event
+ attr :keysym
+ attr :keysym_num
+ attr :type
+ attr :widget
+ attr :x_root
+ attr :y_root
+ end
+
+ def install_bind(cmd, args=nil)
+ if args
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, *arg
+ })
+ id + " " + args
+ else
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, Event.new(*arg)
+ })
+ id + ' %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y'
+ end
+ end
+
+ def tk_event_sequence(context)
+ if context.kind_of? TkVirtualEvent
+ context = context.path
+ end
+ if context.kind_of? Array
+ context = context.collect{|ev|
+ if context.kind_of? TkVirtualEvent
+ ev.path
+ else
+ ev
+ end
+ }.join("><")
+ end
+ if /,/ =~ context
+ context = context.split(/\s*,\s*/).join("><")
+ else
+ context
+ end
+ end
+
+ def _bind_core(mode, path, context, cmd, args=nil)
+ id = install_bind(cmd, args)
+ begin
+ tk_call 'bind', path, "<#{tk_event_sequence(context)}>", mode + id
+ rescue
+ uninstall_cmd(id)
+ fail
+ end
+ end
+
+ def _bind(path, context, cmd, args=nil)
+ _bind_core('', path, context, cmd, args)
+ end
+
+ def _bind_append(path, context, cmd, args=nil)
+ _bind_core('+', path, context, cmd, args)
+ end
+ private :install_bind, :tk_event_sequence, :_bind_core, :_bind, :_bind_append
+
+ def bind_all(context, cmd=Proc.new, args=nil)
+ _bind 'all', context, cmd, args
+ end
+
+ def bind_append_all(context, cmd=Proc.new, args=nil)
+ _bind_append 'all', context, cmd, args
+ end
+
+ def bind(tagOrClass, context, cmd=Proc.new, args=nil)
+ _bind tagOrClass, context, cmd, args
+ end
+
+ def bind_append(tagOrClass, context, cmd=Proc.new, args=nil)
+ _bind_append tagOrClass, context, cmd, args
+ end
+
+ def _bindinfo(tagOrClass, context=nil)
+ if context
+ (tk_call('bind', tagOrClass,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_call 'bind', tagOrClass).collect{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def bindinfo(tagOrClass, context=nil)
+ _bindinfo tagOrClass, context
+ end
+
+ def pack(*args)
+ TkPack.configure *args
+ end
+
+ def grid(*args)
+ TkGrid.configure *args
+ end
+
+ def update(idle=nil)
+ if idle
+ tk_call 'update', 'idletasks'
+ else
+ tk_call 'update'
+ end
+ end
+
+end
+
+module TkCore
+ include TkComm
+ extend TkComm
+
+ INTERP = TclTkIp.new
+
+ INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {return -code $st $ret} {return $ret}")
+
+ def callback_break
+ raise TkCallbackBreak, "Tk callback returns 'break' status"
+ end
+
+ def callback_continue
+ raise TkCallbackContinue, "Tk callback returns 'continue' status"
+ end
+
+ def after(ms, cmd=Proc.new)
+ myid = _curr_cmd_id
+ cmdid = install_cmd(cmd)
+ tk_call("after",ms,cmdid)
+ return
+ if false #defined? Thread
+ Thread.start do
+ ms = Float(ms)/1000
+ ms = 10 if ms == 0
+ sleep ms/1000
+ cmd.call
+ end
+ else
+ cmdid = install_cmd(cmd)
+ tk_call("after",ms,cmdid)
+ end
+ end
+
+ def TkCore.callback(arg)
+ arg = Array(tk_split_list(arg))
+ _get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
+ end
+
+ def appname(name=None)
+ tk_call('tk', 'appname', name)
+ end
+
+ def appsend(interp, async, *args)
+ if async
+ tk_call('send', '-async', '--', interp, *args)
+ else
+ tk_call('send', '--', interp, *args)
+ end
+ end
+
+ def rb_appsend(interp, async, *args)
+ args = args.filter{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
+ args.push(').to_s"')
+ appsend(interp, async, 'ruby "(', *args)
+ end
+
+ def appsend_displayof(interp, win, async, *args)
+ win = '.' if win == nil
+ if async
+ tk_call('send', '-async', '-displayof', win, '--', interp, *args)
+ else
+ tk_call('send', '-displayor', win, '--', interp, *args)
+ end
+ end
+
+ def rb_appsend_displayof(interp, win, async, *args)
+ args = args.filter{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
+ args.push(').to_s"')
+ appsend_displayof(interp, win, async, 'ruby "(', *args)
+ end
+
+ def info(*args)
+ tk_call('info', *args)
+ end
+
+ def mainloop
+ TclTkLib.mainloop
+ end
+
+ def event_generate(window, context, keys=nil)
+ window = window.path if window.kind_of? TkObject
+ if keys
+ tk_call('event', 'generate', window,
+ "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ else
+ tk_call('event', 'generate', window, "<#{tk_event_sequence(context)}>")
+ end
+ end
+
+ def messageBox(keys)
+ tk_call 'tk_messageBox', *hash_kv(keys)
+ end
+
+ def getOpenFile(keys)
+ tk_call 'tk_getOpenFile', *hash_kv(keys)
+ end
+
+ def getSaveFile(keys)
+ tk_call 'tk_getSaveFile', *hash_kv(keys)
+ end
+
+ def chooseColor(keys)
+ tk_call 'tk_chooseColor', *hash_kv(keys)
+ end
+
+ def tk_call(*args)
+ print args.join(" "), "\n" if $DEBUG
+ args.filter {|x|_get_eval_string(x)}
+ args.compact!
+ args.flatten!
+ begin
+ res = INTERP._invoke(*args)
+ rescue NameError
+ err = $!
+ begin
+ args.unshift "unknown"
+ res = INTERP._invoke(*args)
+ rescue
+ raise unless /^invalid command/ =~ $!
+ raise err
+ end
+ end
+ if INTERP._return_value() != 0
+ fail RuntimeError, res, error_at
+ end
+ print "==> ", res, "\n" if $DEBUG
+ return res
+ end
+end
+
+module Tk
+ include TkCore
+ extend Tk
+
+ TCL_VERSION = INTERP._invoke("info", "tclversion")
+ TK_VERSION = INTERP._invoke("set", "tk_version")
+ JAPANIZED_TK = (INTERP._invoke("info", "commands", "kanji") != "")
+
+ def root
+ TkRoot.new
+ end
+
+ def bell
+ tk_call 'bell'
+ end
+
+ def Tk.focus(display=nil)
+ if display == nil
+ r = tk_call('focus')
+ else
+ r = tk_call('focus', '-displayof', display)
+ end
+ tk_tcl2ruby(r)
+ end
+
+ def Tk.focus_lastfor(win)
+ tk_tcl2ruby(tk_call('focus', '-lastfor', win))
+ end
+
+ def toUTF8(str,encoding)
+ INTERP._toUTF8(str,encoding)
+ end
+
+ def fromUTF8(str,encoding)
+ INTERP._fromUTF8(str,encoding)
+ end
+
+ module Scrollable
+ def xscrollcommand(cmd=Proc.new)
+ configure_cmd 'xscrollcommand', cmd
+ end
+ def yscrollcommand(cmd=Proc.new)
+ configure_cmd 'yscrollcommand', cmd
+ end
+ end
+
+ module Wm
+ def aspect(*args)
+ w = window(tk_call('wm', 'grid', path, *args))
+ w.split.collect{|s|s.to_i} if args.length == 0
+ end
+ def client(name=None)
+ tk_call 'wm', 'client', path, name
+ end
+ def colormapwindows(*args)
+ list(tk_call('wm', 'colormapwindows', path, *args))
+ end
+ def wm_command(value=None)
+ string(tk_call('wm', 'command', path, value))
+ end
+ def deiconify
+ tk_call 'wm', 'deiconify', path
+ end
+ def focusmodel(*args)
+ tk_call 'wm', 'focusmodel', path, *args
+ end
+ def frame
+ tk_call 'wm', 'frame', path
+ end
+ def geometry(*args)
+ list(tk_call('wm', 'geometry', path, *args))
+ end
+ def grid(*args)
+ w = tk_call('wm', 'grid', path, *args)
+ list(w) if args.size == 0
+ end
+ def group(*args)
+ tk_call 'wm', 'group', path, *args
+ end
+ def iconbitmap(*args)
+ tk_call 'wm', 'iconbitmap', path, *args
+ end
+ def iconify
+ tk_call 'wm', 'iconify', path
+ end
+ def iconmask(*args)
+ tk_call 'wm', 'iconmask', path, *args
+ end
+ def iconname(*args)
+ tk_call 'wm', 'iconname', path, *args
+ end
+ def iconposition(*args)
+ w = tk_call('wm', 'iconposition', path, *args)
+ list(w) if args.size == 0
+ end
+ def iconwindow(*args)
+ w = tk_call('wm', 'iconwindow', path, *args)
+ window(w) if args.size == 0
+ end
+ def maxsize(*args)
+ w = tk_call('wm', 'maxsize', path, *args)
+ list(w) if not args.size == 0
+ end
+ def minsize(*args)
+ w = tk_call('wm', 'minsize', path, *args)
+ list(w) if args.size == 0
+ end
+ def overrideredirect(bool=None)
+ if bool == None
+ bool(tk_call('wm', 'overrideredirect', path))
+ else
+ tk_call 'wm', 'overrideredirect', path, bool
+ end
+ end
+ def positionfrom(*args)
+ tk_call 'wm', 'positionfrom', path, *args
+ end
+ def protocol(name=nil, cmd=nil)
+ if cmd
+ tk_call('wm', 'protocol', path, name, cmd)
+ elsif name
+ result = tk_call('wm', 'protocol', path, name)
+ (result == "")? nil : tk_tcl2ruby(result)
+ else
+ tk_split_simplelist(tk_call('wm', 'protocol', path))
+ end
+ end
+ def resizable(*args)
+ w = tk_call('wm', 'resizable', path, *args)
+ if args.length == 0
+ list(w).collect{|e| bool(e)}
+ end
+ end
+ def sizefrom(*args)
+ list(tk_call('wm', 'sizefrom', path, *args))
+ end
+ def state
+ tk_call 'wm', 'state', path
+ end
+ def title(*args)
+ tk_call 'wm', 'title', path, *args
+ end
+ def transient(*args)
+ tk_call 'wm', 'transient', path, *args
+ end
+ def withdraw
+ tk_call 'wm', 'withdraw', path
+ end
+ end
+end
+
+class TkVariable
+ include Tk
+ extend TkCore
+
+ TkVar_CB_TBL = {}
+ Tk_VARIABLE_ID = ["v00000"]
+
+ INTERP._invoke("proc", "rb_var", "args", "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
+
+ def TkVariable.callback(args)
+ name1,name2,op = tk_split_list(args)
+ if TkVar_CB_TBL[name1]
+ _get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
+ else
+ ''
+ end
+ end
+
+ def initialize(val="")
+ @id = Tk_VARIABLE_ID[0]
+ Tk_VARIABLE_ID[0] = Tk_VARIABLE_ID[0].succ
+ if val == []
+ INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
+ @id, @id, @id))
+ elsif val.kind_of?(Array)
+ a = []
+ val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
+ s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ elsif val.kind_of?(Hash)
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ else
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ end
+ end
+
+ def wait
+ INTERP._eval("tkwait variable #{@id}")
+ end
+
+ def id
+ @id
+ end
+
+ def value
+ begin
+ INTERP._eval(format('global %s; set %s', @id, @id))
+ rescue
+ if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
+ raise
+ else
+ Hash[*tk_split_simplelist(INTERP\
+ ._eval(format('global %s; array get %s',
+ @id, @id)))]
+ end
+ end
+ end
+
+ def value=(val)
+ begin
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ rescue
+ if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
+ raise
+ else
+ INTERP._eval(format('global %s; unset %s'), @id, @id)
+ if val == []
+ INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
+ @id, @id, @id))
+ elsif val.kind_of?(Array)
+ a = []
+ val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
+ s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ elsif val.kind_of?(Hash)
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ else
+ raise
+ end
+ end
+ end
+ end
+
+ def [](index)
+ INTERP._eval(format('global %s; set %s(%s)',
+ @id, @id, _get_eval_string(index)))
+ end
+
+ def []=(index,val)
+ INTERP._eval(format('global %s; set %s(%s) %s', @id, @id,
+ _get_eval_string(index), _get_eval_string(val)))
+ end
+
+ def to_i
+ Integer(number(value))
+ end
+
+ def to_f
+ Float(number(value))
+ end
+
+ def to_s
+ String(string(value))
+ end
+
+ def inspect
+ format "<TkVariable: %s>", @id
+ end
+
+ def ==(other)
+ case other
+ when TkVariable
+ self.equal(self)
+ when String
+ self.to_s == other
+ when Integer
+ self.to_i == other
+ when Float
+ self.to_f == other
+ when Array
+ self.to_a == other
+ else
+ false
+ end
+ end
+
+ def to_a
+ list(value)
+ end
+
+ def to_eval
+ @id
+ end
+
+ def unset(elem=nil)
+ if elem
+ INTERP._eval(format('global %s; unset %s(%s)',
+ @id, @id, tk_tcl2ruby(elem)))
+ else
+ INTERP._eval(format('global %s; unset %s', @id, @id))
+ end
+ end
+ alias remove unset
+
+ def trace_callback(elem, op)
+ if @trace_var.kind_of? Array
+ @trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ if elem.kind_of? String
+ if @trace_elem[elem].kind_of? Array
+ @trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ end
+ end
+
+ def trace(opts, cmd)
+ @trace_var = [] if @trace_var == nil
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ @trace_var.unshift([opts,cmd])
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ else
+ newopts = @trace_opts.dup
+ opts.each_byte{|c| newopts += c.chr unless @newopts.index(c)}
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_element(elem, opts, cmd)
+ @trace_elem = {} if @trace_elem == nil
+ @trace_elem[elem] = [] if @trace_elem[elem] == nil
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ @trace_elem[elem].unshift([opts,cmd])
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ else
+ newopts = @trace_opts.dup
+ opts.each_byte{|c| newopts += c.chr unless @newopts.index(c)}
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_vinfo
+ return [] unless @trace_var
+ @trace_var.dup
+ end
+ def trace_vinfo_for_element(elem)
+ return [] unless @trace_elem
+ return [] unless @trace_elem[elem]
+ @trace_elem[elem].dup
+ end
+
+ def trace_vdelete(opts,cmd)
+ return unless @trace_var.kind_of? Array
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ idx = -1
+ newopts = ''
+ @trace_var.each_with_index{|i,e|
+ if idx < 0 && e[0] == opts && e[1] == cmd
+ idx = i
+ next
+ end
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ if idx >= 0
+ @trace_var.delete_at(idx)
+ else
+ return
+ end
+
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ }
+
+ newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ if @trace_opts != ''
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_vdelete_for_element(elem,opts,cmd)
+ return unless @trace_elem.kind_of? Hash
+ return unless @trace_elem[elem].kind_of? Array
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ idx = -1
+ @trace_elem[elem].each_with_index{|i,e|
+ if idx < 0 && e[0] == opts && e[1] == cmd
+ idx = i
+ next
+ end
+ }
+ if idx >= 0
+ @trace_elem[elem].delete_at(idx)
+ else
+ return
+ end
+
+ newopts = ''
+ @trace_var.each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ }
+
+ newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ if @trace_opts != ''
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+end
+
+class TkVarAccess<TkVariable
+ def initialize(varname, val=nil)
+ @id = varname
+ if val
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"' #'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ end
+ end
+end
+
+module TkSelection
+ include Tk
+ extend Tk
+ def clear(win=Tk.root)
+ tk_call 'selection', 'clear', win.path
+ end
+ def get(type=None)
+ tk_call 'selection', 'get', type
+ end
+ def TkSelection.handle(win, func, type=None, format=None)
+ id = install_cmd(func)
+ tk_call 'selection', 'handle', win.path, id, type, format
+ end
+ def handle(func, type=None, format=None)
+ TkSelection.handle self, func, type, format
+ end
+ def TkSelection.own(win, func=None)
+ id = install_cmd(func)
+ tk_call 'selection', 'own', win.path, id
+ end
+ def own(func=None)
+ TkSelection.own self, func
+ end
+
+ module_function :clear, :get
+end
+
+module TkKinput
+ include Tk
+ extend Tk
+
+ def TkKinput.start(window, style=None)
+ tk_call 'kinput_start', window.path, style
+ end
+ def kinput_start(style=None)
+ TkKinput.start(self, style)
+ end
+
+ def TkKinput.send_spot(window)
+ tk_call 'kinput_send_spot', window.path
+ end
+ def kinput_send_spot
+ TkKinput.send_spot(self)
+ end
+
+ def TkKinput.input_start(window, keys=nil)
+ tk_call 'kanjiInput', 'start', window.path, *hash_kv(keys)
+ end
+ def kanji_input_start(keys=nil)
+ TkKinput.input_start(self, keys)
+ end
+
+ def TkKinput.attribute_config(window, slot, value=None)
+ if slot.kind_of? Hash
+ tk_call 'kanjiInput', 'attribute', window.path, *hash_kv(slot)
+ else
+ tk_call 'kanjiInput', 'attribute', window.path, "-#{slot}", value
+ end
+ end
+ def kinput_attribute_config(slot, value=None)
+ TkKinput.attribute_config(self, slot, value)
+ end
+
+ def TkKinput.attribute_info(window, slot=nil)
+ if slot
+ conf = tk_split_list(tk_call('kanjiInput', 'attribute',
+ window.path, "-#{slot}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call('kanjiInput', 'attribute',
+ window.path)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+ def kinput_attribute_info(slot=nil)
+ TkKinput.attribute_info(self, slot)
+ end
+
+ def TkKinput.input_end(window)
+ tk_call 'kanjiInput', 'end', window.path
+ end
+ def kanji_input_end
+ TkKinput.input_end(self)
+ end
+end
+
+module TkWinfo
+ include Tk
+ extend Tk
+ def TkWinfo.atom(name)
+ tk_call 'winfo', name
+ end
+ def winfo_atom(name)
+ TkWinfo.atom name
+ end
+ def TkWinfo.atomname(id)
+ tk_call 'winfo', id
+ end
+ def winfo_atomname(id)
+ TkWinfo.atomname id
+ end
+ def TkWinfo.cells(window)
+ number(tk_call('winfo', window.path))
+ end
+ def winfo_cells
+ TkWinfo.cells self
+ end
+ def TkWinfo.children(window)
+ c = tk_call('winfo', 'children', window.path)
+ list(c)
+ end
+ def winfo_children
+ TkWinfo.children self
+ end
+ def TkWinfo.classname(window)
+ tk_call 'winfo', 'class', window.path
+ end
+ def winfo_classname
+ TkWinfo.classname self
+ end
+ def TkWinfo.containing(rootX, rootY)
+ path = tk_call('winfo', 'containing', rootX, rootY)
+ window(path)
+ end
+ def winfo_containing(x, y)
+ TkWinfo.containing x, y
+ end
+ def TkWinfo.depth(window)
+ number(tk_call('winfo', 'depth', window.path))
+ end
+ def winfo_depth
+ TkWinfo.depth self
+ end
+ def TkWinfo.exist?(window)
+ bool(tk_call('winfo', 'exists', window.path))
+ end
+ def winfo_exist?
+ TkWinfo.exist? self
+ end
+ def TkWinfo.fpixels(window, number)
+ number(tk_call('winfo', 'fpixels', window.path, number))
+ end
+ def winfo_fpixels(number)
+ TkWinfo.fpixels self, number
+ end
+ def TkWinfo.geometry(window)
+ list(tk_call('winfo', 'geometry', window.path))
+ end
+ def winfo_geometry
+ TkWinfo.geometry self
+ end
+ def TkWinfo.height(window)
+ number(tk_call('winfo', 'height', window.path))
+ end
+ def winfo_height
+ TkWinfo.height self
+ end
+ def TkWinfo.id(window)
+ number(tk_call('winfo', 'id', window.path))
+ end
+ def winfo_id
+ TkWinfo.id self
+ end
+ def TkWinfo.interps(window=nil)
+ if window
+ tk_split_simplelist(tk_call('winfo', '-displayof', window.path,
+ 'interps'))
+ else
+ tk_split_simplelist(tk_call('winfo', 'interps'))
+ end
+ end
+ def winfo_interps
+ TkWinfo.interps self
+ end
+ def TkWinfo.mapped?(window)
+ bool(tk_call('winfo', 'ismapped', window.path))
+ end
+ def winfo_mapped?
+ TkWinfo.mapped? self
+ end
+ def TkWinfo.appname(window)
+ bool(tk_call('winfo', 'name', window.path))
+ end
+ def winfo_appname
+ TkWinfo.appname self
+ end
+ def TkWinfo.parent(window)
+ window(tk_call('winfo', 'parent', window.path))
+ end
+ def winfo_parent
+ TkWinfo.parent self
+ end
+ def TkWinfo.widget(id)
+ window(tk_call('winfo', 'pathname', id))
+ end
+ def winfo_widget(id)
+ TkWinfo.widget id
+ end
+ def TkWinfo.pixels(window, number)
+ number(tk_call('winfo', 'pixels', window.path, number))
+ end
+ def winfo_pixels(number)
+ TkWinfo.pixels self, number
+ end
+ def TkWinfo.reqheight(window)
+ number(tk_call('winfo', 'reqheight', window.path))
+ end
+ def winfo_reqheight
+ TkWinfo.reqheight self
+ end
+ def TkWinfo.reqwidth(window)
+ number(tk_call('winfo', 'reqwidth', window.path))
+ end
+ def winfo_reqwidth
+ TkWinfo.reqwidth self
+ end
+ def TkWinfo.rgb(window, color)
+ list(tk_call('winfo', 'rgb', window.path, color))
+ end
+ def winfo_rgb(color)
+ TkWinfo.rgb self, color
+ end
+ def TkWinfo.rootx(window)
+ number(tk_call('winfo', 'rootx', window.path))
+ end
+ def winfo_rootx
+ TkWinfo.rootx self
+ end
+ def TkWinfo.rooty(window)
+ number(tk_call('winfo', 'rooty', window.path))
+ end
+ def winfo_rooty
+ TkWinfo.rooty self
+ end
+ def TkWinfo.screen(window)
+ tk_call 'winfo', 'screen', window.path
+ end
+ def winfo_screen
+ TkWinfo.screen self
+ end
+ def TkWinfo.screencells(window)
+ number(tk_call('winfo', 'screencells', window.path))
+ end
+ def winfo_screencells
+ TkWinfo.screencells self
+ end
+ def TkWinfo.screendepth(window)
+ number(tk_call('winfo', 'screendepth', window.path))
+ end
+ def winfo_screendepth
+ TkWinfo.screendepth self
+ end
+ def TkWinfo.screenheight (window)
+ number(tk_call('winfo', 'screenheight', window.path))
+ end
+ def winfo_screenheight
+ TkWinfo.screenheight self
+ end
+ def TkWinfo.screenmmheight(window)
+ number(tk_call('winfo', 'screenmmheight', window.path))
+ end
+ def winfo_screenmmheight
+ TkWinfo.screenmmheight self
+ end
+ def TkWinfo.screenmmwidth(window)
+ number(tk_call('winfo', 'screenmmwidth', window.path))
+ end
+ def winfo_screenmmwidth
+ TkWinfo.screenmmwidth self
+ end
+ def TkWinfo.screenvisual(window)
+ tk_call 'winfo', 'screenvisual', window.path
+ end
+ def winfo_screenvisual
+ TkWinfo.screenvisual self
+ end
+ def TkWinfo.screenwidth(window)
+ number(tk_call('winfo', 'screenwidth', window.path))
+ end
+ def winfo_screenwidth
+ TkWinfo.screenwidth self
+ end
+ def TkWinfo.toplevel(window)
+ window(tk_call('winfo', 'toplevel', window.path))
+ end
+ def winfo_toplevel
+ TkWinfo.toplevel self
+ end
+ def TkWinfo.visual(window)
+ tk_call 'winfo', 'visual', window.path
+ end
+ def winfo_visual
+ TkWinfo.visual self
+ end
+ def TkWinfo.vrootheigh(window)
+ number(tk_call('winfo', 'vrootheight', window.path))
+ end
+ def winfo_vrootheight
+ TkWinfo.vrootheight self
+ end
+ def TkWinfo.vrootwidth(window)
+ number(tk_call('winfo', 'vrootwidth', window.path))
+ end
+ def winfo_vrootwidth
+ TkWinfo.vrootwidth self
+ end
+ def TkWinfo.vrootx(window)
+ number(tk_call('winfo', 'vrootx', window.path))
+ end
+ def winfo_vrootx
+ TkWinfo.vrootx self
+ end
+ def TkWinfo.vrooty(window)
+ number(tk_call('winfo', 'vrooty', window.path))
+ end
+ def winfo_vrooty
+ TkWinfo.vrooty self
+ end
+ def TkWinfo.width(window)
+ number(tk_call('winfo', 'width', window.path))
+ end
+ def winfo_width
+ TkWinfo.width self
+ end
+ def TkWinfo.x(window)
+ number(tk_call('winfo', 'x', window.path))
+ end
+ def winfo_x
+ TkWinfo.x self
+ end
+ def TkWinfo.y(window)
+ number(tk_call('winfo', 'y', window.path))
+ end
+ def winfo_y
+ TkWinfo.y self
+ end
+ def TkWinfo.viewable(window)
+ bool(tk_call 'winfo', 'viewable', window.path)
+ end
+ def winfo_viewable
+ TkWinfo.viewable self
+ end
+ def TkWinfo.pointerx(window)
+ number(tk_call('winfo', 'pointerx', window.path))
+ end
+ def winfo_pointerx
+ TkWinfo.pointerx self
+ end
+ def TkWinfo.pointery(window)
+ number(tk_call('winfo', 'pointery', window.path))
+ end
+ def winfo_pointery
+ TkWinfo.pointery self
+ end
+ def TkWinfo.pointerxy(window)
+ list(tk_call('winfo', 'pointerxy', window.path))
+ end
+ def winfo_pointerxy
+ TkWinfo.pointerxy self
+ end
+end
+
+module TkPack
+ include Tk
+ extend Tk
+ def configure(win, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ end
+ wins = [win.epath]
+ for i in args
+ wins.push i.epath
+ end
+ tk_call "pack", 'configure', *(wins+hash_kv(keys))
+ end
+
+ def forget(*args)
+ tk_call 'pack', 'forget' *args
+ end
+
+ def propagate(master, bool=None)
+ bool(tk_call('pack', 'propagate', master.epath, bool))
+ end
+ module_function :configure, :forget, :propagate
+end
+
+module TkGrid
+ include Tk
+ extend Tk
+
+ def bbox(*args)
+ list(tk_call('grid', 'bbox', *args))
+ end
+
+ def configure(widget, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ end
+ wins = [widget.epath]
+ for i in args
+ wins.push i.epath
+ end
+ tk_call "grid", 'configure', *(wins+hash_kv(keys))
+ end
+
+ def columnconfigure(master, index, args)
+ tk_call "grid", 'columnconfigure', master, index, *hash_kv(args)
+ end
+
+ def rowconfigure(master, index, args)
+ tk_call "grid", 'rowconfigure', master, index, *hash_kv(args)
+ end
+
+ def add(widget, *args)
+ configure(widget, *args)
+ end
+
+ def forget(*args)
+ tk_call 'grid', 'forget', *args
+ end
+
+ def info(slave)
+ list(tk_call('grid', 'info', slave))
+ end
+
+ def location(master, x, y)
+ list(tk_call('grid', 'location', master, x, y))
+ end
+
+ def propagate(master, bool=None)
+ bool(tk_call('grid', 'propagate', master.epath, bool))
+ end
+
+ def remove(*args)
+ tk_call 'grid', 'remove', *args
+ end
+
+ def size(master)
+ tk_call 'grid', 'size', master
+ end
+
+ def slaves(args)
+ list(tk_call('grid', 'slaves', *hash_kv(args)))
+ end
+
+ module_function :bbox, :forget, :propagate, :info
+ module_function :remove, :size, :slaves, :location
+ module_function :configure, :columnconfigure, :rowconfigure
+end
+
+module TkOption
+ include Tk
+ extend Tk
+ def add pat, value, pri=None
+ tk_call 'option', 'add', pat, value, pri
+ end
+ def clear
+ tk_call 'option', 'clear'
+ end
+ def get win, name, klass
+ tk_call 'option', 'get', win ,name, klass
+ end
+ def readfile file, pri=None
+ tk_call 'option', 'readfile', file, pri
+ end
+ module_function :add, :clear, :get, :readfile
+end
+
+module TkTreatFont
+ def font_configinfo
+ ret = TkFont.used_on(self.path)
+ if ret == nil
+ ret = TkFont.init_widget_font(self.path, self.path, 'configure')
+ end
+ ret
+ end
+ alias fontobj font_configinfo
+
+ def font_configure(slot)
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(self.path, self.path,'configure',slot)
+ else
+ latinfont_configure(fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latinfont_configure(ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latinfont_configure(ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjifont_configure(knj) if knj
+ end
+
+ tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latinfont_configure(ltn, keys=nil)
+ fobj = fontobj
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val}
+ if keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciifont_configure latinfont_configure
+
+ def kanjifont_configure(knj, keys=nil)
+ fobj = fontobj
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val}
+ if keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(cond)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def font_copy(window, tag=nil)
+ if tag
+ window.tagfontobj(tag).configinfo.each{|key,value|
+ fontobj.configure(key,value)
+ }
+ fontobj.replace(window.tagfontobj(tag).latin_font,
+ window.tagfontobj(tag).kanji_font)
+ else
+ window.fontobj.configinfo.each{|key,value|
+ fontobj.configure(key,value)
+ }
+ fontobj.replace(window.fontobj.latin_font, window.fontobj.kanji_font)
+ end
+ end
+
+ def latinfont_copy(window, tag=nil)
+ if tag
+ fontobj.latin_replace(window.tagfontobj(tag).latin_font)
+ else
+ fontobj.latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciifont_copy latinfont_copy
+
+ def kanjifont_copy(window, tag=nil)
+ if tag
+ fontobj.kanji_replace(window.tagfontobj(tag).kanji_font)
+ else
+ fontobj.kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkObject<TkKernel
+ include Tk
+ include TkTreatFont
+
+ def path
+ return @path
+ end
+
+ def epath
+ return @path
+ end
+
+ def to_eval
+ @path
+ end
+
+ def tk_send(cmd, *rest)
+ tk_call path, cmd, *rest
+ end
+ private :tk_send
+
+ def method_missing(id, *args)
+ name = id.id2name
+ case args.length
+ when 1
+ configure name, args[0]
+ when 0
+ begin
+ cget name
+ rescue
+ fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
+ end
+ else
+ fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
+ end
+ end
+
+ def [](id)
+ cget id
+ end
+
+ def []=(id, val)
+ configure id, val
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call path, 'cget', "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ if ( slot['font'] || slot['kanjifont'] \
+ || slot['latinfont'] || slot['asciifont'] )
+ font_configure(slot.dup)
+ else
+ tk_call path, 'configure', *hash_kv(slot)
+ end
+
+ else
+ if ( slot == 'font' || slot == 'kanjifont' \
+ || slot == 'latinfont' || slot == 'asciifont' )
+ font_configure({slot=>value})
+ else
+ tk_call path, 'configure', "-#{slot}", value
+ end
+ end
+ end
+
+ def configure_cmd(slot, value)
+ configure slot, install_cmd(value)
+ end
+
+ def configinfo(slot = nil)
+ if slot == 'font' || slot == 'kanjifont'
+ fontobj
+
+ else
+ if slot
+ conf = tk_split_list(tk_send('configure', "-#{slot}") )
+ conf[0] = conf[0][1..-1]
+ conf
+
+ else
+ ret = tk_split_list(tk_send('configure') ).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ if ret.assoc('font')
+ ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
+ ret.push(['font', fontobj])
+ else
+ ret
+ end
+ end
+ end
+ end
+
+ def bind(context, cmd=Proc.new, args=nil)
+ _bind path, context, cmd, args
+ end
+
+ def bind_append(context, cmd=Proc.new, args=nil)
+ _bind_append path, context, cmd, args
+ end
+
+ def bindinfo(context=nil)
+ _bindinfo path, context
+ end
+
+ def event_generate(context, keys=nil)
+ if keys
+ tk_call('event', 'generate', path,
+ "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ else
+ tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
+ end
+ end
+
+ def tk_trace_variable(v)
+ unless v.kind_of?(TkVariable)
+ fail ArgumentError, format("requires TkVariable given %s", v.type)
+ end
+ v
+ end
+ private :tk_trace_variable
+
+ def destroy
+ tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
+ end
+end
+
+module TkClassBind
+ WidgetClassNameTBL = {}
+
+ def TkClassBind.name2class(name)
+ WidgetClassNameTBL[name]
+ end
+
+ def bind(context, cmd=Proc.new, args=nil)
+ Tk.bind to_eval, context, cmd, args
+ end
+
+ def bind_append(context, cmd=Proc.new, args=nil)
+ Tk.bind_append to_eval, context, cmd, args
+ end
+
+ def bindinfo(context=nil)
+ Tk.bindinfo to_eval, context
+ end
+end
+
+class TkWindow<TkObject
+ extend TkClassBind
+
+ def initialize(parent=nil, keys=nil)
+ install_win(if parent then parent.path end)
+ create_self
+ if keys
+ # tk_call @path, 'configure', *hash_kv(keys)
+ configure(keys)
+ end
+ end
+
+ def create_self
+ end
+ private :create_self
+
+ def pack(keys = nil)
+ tk_call 'pack', epath, *hash_kv(keys)
+ self
+ end
+
+ def unpack(keys = nil)
+ tk_call 'pack', 'forget', epath
+ self
+ end
+
+ def grid(keys = nil)
+ tk_call 'grid', epath, *hash_kv(keys)
+ self
+ end
+
+ def ungrid(keys = nil)
+ tk_call 'grid', 'forget', epath
+ self
+ end
+
+ def place(keys = nil)
+ tk_call 'place', epath, *hash_kv(keys)
+ self
+ end
+
+ def unplace(keys = nil)
+ tk_call 'place', 'forget', epath, *hash_kv(keys)
+ self
+ end
+ alias place_forget unplace
+
+ def place_config(keys)
+ tk_call "place", 'configure', epath, *hash_kv(keys)
+ end
+
+ def place_info()
+ ilist = list(tk_call('place', 'info', epath))
+ info = {}
+ while key = ilist.shift
+ info[key[1..-1]] = ilist.shift
+ end
+ return info
+ end
+
+ def pack_slaves()
+ list(tk_call('pack', 'slaves', epath))
+ end
+
+ def pack_info()
+ ilist = list(tk_call('pack', 'info', epath))
+ info = {}
+ while key = ilist.shift
+ info[key[1..-1]] = ilist.shift
+ end
+ return info
+ end
+
+ def place_slaves()
+ list(tk_call('place', 'slaves', epath))
+ end
+
+ def focus(force=false)
+ if force
+ tk_call 'focus', '-force', path
+ else
+ tk_call 'focus', path
+ end
+ self
+ end
+
+ def grab(*args)
+ if !args or args.length == 0
+ tk_call 'grab', 'set', path
+ elsif args.length == 1
+ case args[0]
+ when 'global'
+ tk_call 'grab', 'set', '-global', path
+ else
+ val = tk_call('grab', args[0], path)
+ end
+ case args[0]
+ when 'current'
+ return window(val)
+ when 'status'
+ return val
+ end
+ else
+ fail ArgumentError, 'wrong # of args'
+ end
+ end
+
+ def lower(below=None)
+ tk_call 'lower', path, below
+ self
+ end
+ def raise(above=None)
+ tk_call 'raise', path, above
+ self
+ end
+
+ def command(cmd=Proc.new)
+ configure_cmd 'command', cmd
+ end
+
+ def colormodel model=None
+ tk_call 'tk', 'colormodel', path, model
+ self
+ end
+
+ def destroy
+ tk_call 'destroy', path
+ if @cmdtbl
+ for id in @cmdtbl
+ uninstall_cmd id
+ end
+ end
+ uninstall_win
+ end
+
+ def wait_visibility
+ tk_call 'tkwait', 'visibility', path
+ end
+ alias wait wait_visibility
+
+ def wait_destroy
+ tk_call 'tkwait', 'window', path
+ end
+
+ def bindtags(taglist=nil)
+ if taglist
+ fail unless taglist.kind_of? Array
+ tk_call('bindtags', path, taglist)
+ else
+ tk_split_list(tk_call('bindtags', path)).collect{|tag|
+ if tag == nil
+ '.'
+ elsif tag.kind_of?(String) && (cls = TkClassBind.name2class(tag))
+ cls
+ else
+ tag
+ end
+ }
+ end
+ end
+end
+
+class TkRoot<TkWindow
+ include Wm
+ ROOT = []
+ def TkRoot.new
+ return ROOT[0] if ROOT[0]
+ new = super
+ ROOT[0] = new
+ Tk_WINDOWS["."] = new
+ end
+
+ WidgetClassName = 'Tk'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ @path = '.'
+ end
+ def path
+ "."
+ end
+end
+
+class TkToplevel<TkWindow
+ include Wm
+
+ WidgetClassName = 'Toplevel'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+ if screen.kind_of? Hash
+ keys = screen.dup
+ else
+ @screen = screen
+ end
+ @classname = classname
+ if keys.kind_of? Hash
+ keys = keys.dup
+ if keys['classname']
+ @classname = keys['classname']
+ keys['classname'] = nil
+ end
+ if keys['colormap']
+ @colormap = keys['colormap']
+ keys['colormap'] = nil
+ end
+ if keys['container']
+ @classname = keys['container']
+ keys['classname'] = nil
+ end
+ if keys['screen']
+ @screen = keys['screen']
+ keys['screen'] = nil
+ end
+ if keys['use']
+ @use = keys['use']
+ keys['use'] = nil
+ end
+ if keys['visual']
+ @screen = keys['visual']
+ keys['visual'] = nil
+ end
+ end
+ super(parent, keys)
+ end
+
+ def create_self
+ s = []
+ s.push << "-class" << @classname if @classname
+ s.push << "-colormap" << @colormap if @colormap
+ s.push << "-container" << @container if @container
+ s.push << "-screen" << @screen if @screen
+ s.push << "-use" << @use if @use
+ s.push << "-visual" << @visual if @visual
+ tk_call 'toplevel', @path, *s
+ end
+
+ def specific_class
+ @classname
+ end
+end
+
+class TkFrame<TkWindow
+ WidgetClassName = 'Frame'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def initialize(parent=nil, keys=nil)
+ if keys.kind_of? Hash
+ keys = keys.dup
+ if keys['classname']
+ @classname = keys['classname']
+ keys['classname'] = nil
+ end
+ if keys['colormap']
+ @colormap = keys['colormap']
+ keys['colormap'] = nil
+ end
+ if keys['container']
+ @classname = keys['container']
+ keys['classname'] = nil
+ end
+ if keys['visual']
+ @screen = keys['visual']
+ keys['visual'] = nil
+ end
+ end
+ super(parent, keys)
+ end
+
+ def create_self
+ s = []
+ s.push << "-class" << @classname if @classname
+ s.push << "-colormap" << @colormap if @colormap
+ s.push << "-container" << @container if @container
+ s.push << "-visual" << @visual if @visual
+ tk_call 'frame', @path, *s
+ end
+end
+
+class TkLabel<TkWindow
+ WidgetClassName = 'Label'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'label', @path
+ end
+ def textvariable(v)
+ configure 'textvariable', tk_trace_variable(v)
+ end
+end
+
+class TkButton<TkLabel
+ WidgetClassName = 'Button'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+# def TkButton.to_eval
+ def self.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'button', @path
+ end
+ def invoke
+ tk_send 'invoke'
+ end
+ def flash
+ tk_send 'flash'
+ end
+end
+
+class TkRadioButton<TkButton
+ WidgetClassName = 'Radiobutton'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def TkRadioButton.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'radiobutton', @path
+ end
+ def deselect
+ tk_send 'deselect'
+ end
+ def select
+ tk_send 'select'
+ end
+ def variable(v)
+ configure 'variable', tk_trace_variable(v)
+ end
+end
+
+class TkCheckButton<TkRadioButton
+ TkClassBind::WidgetClassNameTBL['Checkbutton'] = self
+ def TkCheckButton.to_eval
+ 'Checkbutton'
+ end
+ def create_self
+ tk_call 'checkbutton', @path
+ end
+ def toggle
+ tk_send 'toggle'
+ end
+end
+
+class TkMessage<TkLabel
+ TkClassBind::WidgetClassNameTBL['Message'] = self
+ def TkMessage.to_eval
+ 'Message'
+ end
+ def create_self
+ tk_call 'message', @path
+ end
+end
+
+class TkScale<TkWindow
+ WidgetClassName = 'Scale'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'scale', path
+ end
+
+ def get
+ number(tk_send('get'))
+ end
+
+ def set(val)
+ tk_send "set", val
+ end
+
+ def value
+ get
+ end
+
+ def value= (val)
+ set val
+ end
+end
+
+class TkScrollbar<TkWindow
+ WidgetClassName = 'Scrollbar'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'scrollbar', path
+ end
+
+ def delta(deltax=None, deltay=None)
+ number(tk_send('delta', deltax, deltay))
+ end
+
+ def fraction(x=None, y=None)
+ number(tk_send('fraction', x, y))
+ end
+
+ def identify(x=None, y=None)
+ tk_send('fraction', x, y)
+ end
+
+ def get
+ ary1 = tk_send('get', path).split
+ ary2 = []
+ for i in ary1
+ ary2.push number(i)
+ end
+ ary2
+ end
+
+ def set(first, last)
+ tk_send "set", first, last
+ end
+end
+
+class TkTextWin<TkWindow
+ def create_self
+ raise TypeError, "TkTextWin is abstract class"
+ end
+
+ def bbox(index)
+ tk_send 'bbox', index
+ end
+ def delete(first, last=None)
+ tk_send 'delete', first, last
+ end
+ def get(*index)
+ tk_send 'get', *index
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def insert(index, chars, *args)
+ tk_send 'insert', index, chars, *args
+ end
+ def scan_mark(x, y)
+ tk_send 'scan', 'mark', x, y
+ end
+ def scan_dragto(x, y)
+ tk_send 'scan', 'dragto', x, y
+ end
+ def see(index)
+ tk_send 'see', index
+ end
+end
+
+class TkListbox<TkTextWin
+ TkClassBind::WidgetClassNameTBL['Listbox'] = self
+ def TkListbox.to_eval
+ 'Listbox'
+ end
+ def create_self
+ tk_call 'listbox', path
+ end
+
+ def activate(y)
+ tk_send 'activate', y
+ end
+ def curselection
+ list(tk_send('curselection'))
+ end
+ def nearest(y)
+ tk_send('nearest', y).to_i
+ end
+ def size(y)
+ tk_send('size').to_i
+ end
+ def selection_anchor(index)
+ tk_send 'selection', 'anchor', index
+ end
+ def selection_clear(first, last=None)
+ tk_send 'selection', 'clear', first, last
+ end
+ def selection_includes
+ bool(tk_send('selection', 'includes'))
+ end
+ def selection_set(first, last=None)
+ tk_send 'selection', 'set', first, last
+ end
+ def xview(cmd, index, *more)
+ v = tk_send('xview', cmd, index, *more)
+ v.to_i if more.size == 0
+ end
+ def yview(cmd, index, *more)
+ v = tk_send('yview', cmd, index, *more)
+ v.to_i if more.size == 0
+ end
+end
+
+module TkTreatMenuEntryFont
+ def tagfont_configinfo(index)
+ pathname = self.path + ';' + index
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'entryconfigure', index)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(index, slot)
+ pathname = self.path + ';' + index
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'entryconfigure',index,slot)
+ else
+ latintagfont_configure(index, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(index, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(index, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(index, knj) if knj
+ end
+
+ tk_call(self.path, 'entryconfigure', index, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(index, ltn, keys=nil)
+ fobj = tagfontobj(index)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(index, knj, keys=nil)
+ fobj = tagfontobj(index)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(index, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(index).configure(key,value)
+ }
+ tagfontobj(index).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(wintag).configinfo.each{|key,value|
+ tagfontobj(index).configure(key,value)
+ }
+ tagfontobj(index).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(index, window, wintag=nil)
+ if wintag
+ tagfontobj(index).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(index).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(index, window, wintag=nil)
+ if wintag
+ tagfontobj(index).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(index).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkMenu<TkWindow
+ include TkTreatMenuEntryFont
+
+ WidgetClassName = 'Menu'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'menu', path
+ end
+ def activate(index)
+ tk_send 'activate', index
+ end
+ def add(type, keys=nil)
+ tk_send 'add', type, *hash_kv(keys)
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def invoke(index)
+ tk_send 'invoke', index
+ end
+ def insert(index, type, keys=nil)
+ tk_send 'add', index, type, *hash_kv(keys)
+ end
+ def delete(index, last=None)
+ tk_send 'delete', index, last
+ end
+ def post(x, y)
+ tk_send 'post', x, y
+ end
+ def postcascade(index)
+ tk_send 'postcascade', index
+ end
+ def postcommand(cmd=Proc.new)
+ configure_cmd 'postcommand', cmd
+ end
+ def menutype(index)
+ tk_send 'type', index
+ end
+ def unpost
+ tk_send 'unpost'
+ end
+ def yposition(index)
+ number(tk_send('yposition', index))
+ end
+ def entryconfigure(index, keys=nil)
+ tk_send 'entryconfigure', index, *hash_kv(keys)
+ end
+# def entryconfigure(index, keys=nil)
+# tk_send 'entryconfigure', index, *hash_kv(keys)
+# end
+ def entrycget(index, key)
+ tk_tcl2ruby tk_send 'entrycget', index, "-#{key}"
+ end
+ def entryconfigure(index, key, val=None)
+ if key.kind_of? Hash
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(index, key.dup)
+ else
+ tk_send 'entryconfigure', index, *hash_kv(key)
+ end
+
+ else
+ if ( key == 'font' || key == 'kanjifont' \
+ || key == 'latinfont' || key == 'asciifont' )
+ tagfont_configure({key=>val})
+ else
+ tk_call 'entryconfigure', index, "-#{key}", val
+ end
+ end
+ end
+
+ def entryconfiginfo(index, key=nil)
+ if key
+ conf = tk_split_list(tk_send('entryconfigure',index,"-#{key}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send('entryconfigure', index)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+end
+
+class TkMenubutton<TkLabel
+ TkClassBind::WidgetClassNameTBL['Menubutton'] = self
+ def TkMenubutton.to_eval
+ 'Menubutton'
+ end
+ def create_self
+ tk_call 'menubutton', path
+ end
+end
+
+module TkComposite
+ def initialize(parent=nil, *args)
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(*args)
+ end
+
+ def epath
+ @epath
+ end
+
+ def initialize_composite(*args) end
+ private :initialize_composite
+
+ def delegate(option, *wins)
+ unless @delegates
+ @delegates = {}
+ @delegates['DEFAULT'] = @frame
+ end
+ if @delegates[option].kind_of?(Array)
+ for i in wins
+ @delegates[option].push(i)
+ end
+ else
+ @delegates[option] = wins
+ end
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ slot.each{|slot,value| configure slot, value}
+ else
+ if @delegates and @delegates[slot]
+ for i in @delegates[slot]
+ if not i
+ i = @delegates['DEFALUT']
+ redo
+ else
+ last = i.configure(slot, value)
+ end
+ end
+ last
+ else
+ super
+ end
+ end
+ end
+end
+
+module TkClipboard
+ include Tk
+ extend Tk
+
+ def clear
+ tk_call 'clipboard', 'clear'
+ end
+ def get
+ begin
+ tk_call 'selection', 'get', '-selection', 'CLIPBOARD'
+ rescue
+ ''
+ end
+ end
+ def set(data)
+ clear
+ append(data)
+ end
+ def append(data)
+ tk_call 'clipboard', 'append', data
+ end
+
+ module_function :clear, :set, :get, :append
+end
+
+autoload :TkCanvas, 'tkcanvas'
+autoload :TkImage, 'tkcanvas'
+autoload :TkBitmapImage, 'tkcanvas'
+autoload :TkPhotoImage, 'tkcanvas'
+autoload :TkEntry, 'tkentry'
+autoload :TkText, 'tktext'
+autoload :TkDialog, 'tkdialog'
+autoload :TkMenubar, 'tkmenubar'
+autoload :TkAfter, 'tkafter'
+autoload :TkPalette, 'tkpalette'
+autoload :TkFont, 'tkfont'
+autoload :TkVirtualEvent, 'tkvirtevent'
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
new file mode 100644
index 0000000000..be2e50ff3a
--- /dev/null
+++ b/ext/tk/lib/tkafter.rb
@@ -0,0 +1,296 @@
+#
+# tkafter.rb : methods for Tcl/Tk after command
+# 1998/07/02 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkAfter
+ include TkCore
+ extend TkCore
+
+ Tk_CBID = [0]
+ Tk_CBTBL = {}
+
+ INTERP._invoke("proc", "rb_after", "args", "ruby [format \"TkAfter.callback %%Q!%s!\" $args]")
+
+ ###############################
+ # class methods
+ ###############################
+ def TkAfter.callback(arg)
+ @after_id = nil
+ arg = Array(tk_split_list(arg))
+ obj_id = arg.shift
+ ex_obj = Tk_CBTBL[obj_id]
+ return nil if ex_obj == nil; # canceled
+ _get_eval_string(ex_obj.do_callback(*arg))
+ end
+
+ def TkAfter.info
+ tk_call('after', 'info').split(' ').filter{|id|
+ ret = Tk_CBTBL.find{|key,val| val.after_id == id}
+ (ret == nil)? id: ret[1]
+ }
+ end
+
+ ###############################
+ # instance methods
+ ###############################
+ def do_callback(*args)
+ @in_callback = true
+ ret = @current_proc.call(*args)
+ if @set_next
+ set_next_callback(*args)
+ else
+ @set_next = true
+ end
+ @in_callback = false
+ ret
+ end
+
+ def set_callback(sleep, args=nil)
+ @after_script = "rb_after #{@id} #{_get_eval_string(args)}"
+ @after_id = tk_call('after', sleep, @after_script)
+ @current_script = [sleep, @after_script]
+ end
+
+ def set_next_callback(*args)
+ if @running == false || @proc_max == 0 || @do_loop == 0
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ if @current_pos >= @proc_max
+ if @do_loop < 0 || (@do_loop -= 1) > 0
+ @current_pos = 0
+ else
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ end
+
+ @current_args = args
+
+ if @sleep_time.kind_of? Proc
+ sleep = @sleep_time.call(*args)
+ else
+ sleep = @sleep_time
+ end
+ @current_sleep = sleep
+
+ cmd, *cmd_args = @loop_proc[@current_pos]
+ @current_pos += 1
+ @current_proc = cmd
+
+ if cmd_args[0].kind_of? Proc
+ #c = cmd_args.shift
+ #cb_args = c.call(*(cmd_args + args))
+ cb_args = cmd_args[0].call(*args)
+ else
+ cb_args = cmd_args
+ end
+
+ set_callback(sleep, cb_args)
+ end
+
+ def initialize(*args)
+ @id = format("a%.4d", Tk_CBID[0])
+ Tk_CBID[0] += 1
+
+ @set_next = true
+
+ @init_sleep = 0
+ @init_proc = nil
+ @init_args = []
+
+ @current_script = []
+ @current_proc = nil
+ @current_args = nil
+
+ @sleep_time = 0
+ @current_sleep = 0
+ @loop_exec = 0
+ @do_loop = 0
+ @loop_proc = []
+ @proc_max = 0
+ @current_pos = 0
+
+ @after_id = nil
+ @after_script = nil
+
+ set_procs(*args) if args != []
+
+ @running = false
+ end
+
+ attr :after_id
+ attr :after_script
+ attr :current_proc
+ attr :current_sleep
+
+ attr_accessor :loop_exec
+
+ def get_procs
+ [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
+ end
+
+ def current_status
+ [@running, @current_sleep, @current_proc, @current_args, @do_loop]
+ end
+
+ def running?
+ @running
+ end
+
+ def loop_rest
+ @do_loop
+ end
+
+ def loop_rest=(rest)
+ @do_loop = rest
+ end
+
+ def set_procs(interval, loop_exec, *procs)
+ if !interval == 'idle' \
+ && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
+ fail format("%s need to be Integer or Proc", interval.inspect)
+ end
+ @sleep_time = interval
+
+ @loop_proc = []
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+ @current_pos = 0
+
+ @do_loop = 0
+ if loop_exec
+ if loop_exec.kind_of?(Integer) && loop_exec < 0
+ @loop_exec = -1
+ elsif loop_exec == nil || loop_exec == false || loop_exec == 0
+ @loop_exec = 1
+ else
+ if not loop_exec.kind_of?(Integer)
+ fail format("%s need to be Integer", loop_exec.inspect)
+ end
+ @loop_exec = loop_exec
+ end
+ @do_loop = @loop_exec
+ end
+
+ self
+ end
+
+ def add_procs(*procs)
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+
+ self
+ end
+
+ def set_start_proc(sleep, init_proc, *init_args)
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ @init_proc = init_proc
+ @init_args = init_args
+ self
+ end
+
+ def start(*init_args)
+ return nil if @running
+
+ Tk_CBTBL[@id] = self
+ @do_loop = @loop_exec
+ @current_pos = 0
+
+ argc = init_args.size
+ if argc > 0
+ sleep = init_args.shift
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ end
+ @init_proc = init_args.shift if argc > 1
+ @init_args = init_args if argc > 0
+
+ @current_sleep = @init_sleep
+ @running = true
+ if @init_proc
+ if not @init_proc.kind_of? Proc
+ fail format("%s need to be Proc", @init_proc.inspect)
+ end
+ @current_proc = @init_proc
+ set_callback(sleep, @init_args)
+ @set_next = false if @in_callback
+ else
+ set_next_callback(*@init_args)
+ end
+
+ self
+ end
+
+ def restart(*restart_args)
+ cancel if @running
+ if restart_args == []
+ start(@init_sleep, @init_proc, *@init_args)
+ else
+ start(*restart_args)
+ end
+ end
+
+ def cancel
+ @running = false
+ tk_call 'after', 'cancel', @after_id if @after_id
+ @after_id = nil
+ Tk_CBTBL[@id] = nil ;# for GC
+ self
+ end
+ alias stop cancel
+
+ def continue(wait=nil)
+ sleep, cmd = @current_script
+ return nil if cmd == nil || @running == true
+ if wait
+ if not wait.kind_of? Integer
+ fail format("%s need to be Integer", wait.inspect)
+ end
+ sleep = wait
+ end
+ Tk_CBTBL[@id] = self
+ @running = true
+ @after_id = tk_call('after', sleep, cmd)
+ self
+ end
+
+ def skip
+ return nil if @running == false
+ cancel
+ Tk_CBTBL[@id] = self
+ @running = true
+ set_next_callback(@current_args)
+ self
+ end
+
+ def info
+ if @after_id
+ inf = tk_split_list(tk_call('after', 'info', @after_id))
+ [Tk_CBTBL[inf[0][1]], inf[1]]
+ else
+ nil
+ end
+ end
+end
diff --git a/ext/tk/lib/tkbgerror.rb b/ext/tk/lib/tkbgerror.rb
new file mode 100644
index 0000000000..8022077a3f
--- /dev/null
+++ b/ext/tk/lib/tkbgerror.rb
@@ -0,0 +1,17 @@
+#
+# tkbgerror -- bgerror ( tkerror ) module
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkBgError
+ extend Tk
+
+ def bgerror(message)
+ tk_call 'bgerror', message
+ end
+ alias tkerror bgerror
+ alias show bgerror
+
+ module_function :bgerror, :tkerror, :show
+end
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
new file mode 100644
index 0000000000..1cf24eeb7b
--- /dev/null
+++ b/ext/tk/lib/tkcanvas.rb
@@ -0,0 +1,829 @@
+#
+# tkcanvas.rb - Tk canvas classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+# $Date$
+# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+
+require "tk"
+require 'tkfont'
+
+module TkTreatCItemFont
+ def tagfont_configinfo(tagOrId)
+ if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
+ pathname = self.path + ';' + tagOrId.id.to_s
+ else
+ pathname = self.path + ';' + tagOrId.to_s
+ end
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'itemconfigure', tagOrId)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(tagOrId, slot)
+ if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
+ pathname = self.path + ';' + tagOrId.id.to_s
+ else
+ pathname = self.path + ';' + tagOrId.to_s
+ end
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'itemconfigure',tagOrId,slot)
+ else
+ latintagfont_configure(tagOrId, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(tagOrId, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(tagOrId, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(tagOrId, knj) if knj
+ end
+
+ tk_call(self.path, 'itemconfigure', tagOrId, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(tagOrId, ltn, keys=nil)
+ fobj = tagfontobj(tagOrId)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(tagOrId, knj, keys=nil)
+ fobj = tagfontobj(tagOrId)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(tagOrId).configure(key,value)
+ }
+ tagfontobj(tagOrId).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(tagOrId).configinfo.each{|key,value|
+ tagfontobj(tagOrId).configure(key,value)
+ }
+ tagfontobj(tagOrId).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ tagfontobj(tagOrId).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ tagfontobj(tagOrId).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkCanvas<TkWindow
+ include TkTreatCItemFont
+
+ WidgetClassName = 'Canvas'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'canvas', path
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
+ tag.id
+ else
+ tag
+ end
+ end
+ private :tagid
+
+ def addtag(tag, mode, *args)
+ tk_send 'addtag', tagid(tag), mode, *args
+ end
+ def addtag_above(tagOrId, target)
+ addtag(tagOrId, 'above', tagid(target))
+ end
+ def addtag_all(tagOrId)
+ addtag(tagOrId, 'all')
+ end
+ def addtag_below(tagOrId, target)
+ addtag(tagOrId, 'below', tagid(target))
+ end
+ def addtag_closest(tagOrId, x, y, halo=None, start=None)
+ addtag(tagOrId, 'closest', x, y, halo, start)
+ end
+ def addtag_enclosed(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
+ end
+ def addtag_overlapping(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
+ end
+ def addtag_withtag(tagOrId, tag)
+ addtag(tagOrId, 'withtag', tagid(tag))
+ end
+
+ def bbox(tagOrId, *tags)
+ list(tk_send('bbox', tagid(tagOrId), *tags))
+ end
+
+ def itembind(tag, context, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ begin
+ tk_send 'bind', tagid(tag), "<#{tk_event_sequence(context)}>", id
+ rescue
+ uninstall_cmd(cmd)
+ fail
+ end
+ # @cmdtbl.push id
+ end
+
+ def itembindinfo(tag, context=nil)
+ if context
+ (tk_send('bind', tagid(tag),
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_send 'bind', tagid(tag)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def canvasx(x, *args)
+ tk_tcl2ruby(tk_send 'canvasx', x, *args)
+ end
+ def canvasy(y, *args)
+ tk_tcl2ruby(tk_send 'canvasy', y, *args)
+ end
+
+ def coords(tag, *args)
+ if args == []
+ tk_split_list(tk_send('coords', tagid(tag)))
+ else
+ tk_send('coords', tagid(tag), *args)
+ end
+ end
+
+ def dchars(tag, first, last=None)
+ tk_send 'dchars', tagid(tag), first, last
+ end
+
+ def delete(*args)
+ tk_send 'delete', *args
+ end
+ alias remove delete
+
+ def dtag(tag, tag_to_del=None)
+ tk_send 'dtag', tagid(tag), tag_to_del
+ end
+
+ def find(mode, *args)
+ list(tk_send 'find', mode, *args).filter{|id|
+ TkcItem.id2obj(id)
+ }
+ end
+ def find_above(target)
+ find('above', tagid(target))
+ end
+ def find_all
+ find('all')
+ end
+ def find_below(target)
+ find('below', tagid(target))
+ end
+ def find_closest(x, y, halo=None, start=None)
+ find('closest', x, y, halo, start)
+ end
+ def find_enclosed(x1, y1, x2, y2)
+ find('enclosed', x1, y1, x2, y2)
+ end
+ def find_overlapping(x1, y1, x2, y2)
+ find('overlapping', x1, y1, x2, y2)
+ end
+ def find_withtag(tag)
+ find('withtag', tag)
+ end
+
+ def itemfocus(tagOrId=nil)
+ if tagOrId
+ tk_send 'focus', tagid(tagOrId)
+ else
+ ret = tk_send('focus')
+ if ret == ""
+ nil
+ else
+ TkcItem.id2obj(ret)
+ end
+ end
+ end
+
+ def gettags(tagOrId)
+ list(tk_send('gettags', tagid(tagOrId))).collect{|tag|
+ TkcTag.id2obj(tag)
+ }
+ end
+
+ def icursor(tagOrId, index)
+ tk_send 'icursor', tagid(tagOrId), index
+ end
+
+ def index(tagOrId, index)
+ tk_send 'index', tagid(tagOrId), index
+ end
+
+ def insert(tagOrId, index, string)
+ tk_send 'insert', tagid(tagOrId), index, string
+ end
+
+ def itemcget(tagOrId, option)
+ tk_tcl2ruby tk_send 'itemcget', tagid(tagOrId), "-#{option}"
+ end
+
+ def itemconfigure(tagOrId, key, value=None)
+ if key.kind_of? Hash
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tagOrId, key.dup)
+ else
+ tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
+ end
+
+ else
+ if ( key == 'font' || key == 'kanjifont' \
+ || key == 'latinfont' || key == 'asciifont' )
+ tagfont_configure(tagid(tagOrId), {key=>value})
+ else
+ tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
+ end
+ end
+ end
+# def itemconfigure(tagOrId, key, value=None)
+# if key.kind_of? Hash
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
+# else
+# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
+# end
+# end
+# def itemconfigure(tagOrId, keys)
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
+# end
+
+ def itemconfiginfo(tagOrId, key=nil)
+ if key
+ conf = tk_split_list(tk_send 'itemconfigure', tagid(tagOrId), "-#{key}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send 'itemconfigure', tagid(tagOrId)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+
+ def lower(tag, below=None)
+ tk_send 'lower', tagid(tag), below
+ end
+
+ def move(tag, x, y)
+ tk_send 'move', tagid(tag), x, y
+ end
+
+ def postscript(keys)
+ tk_send "postscript", *hash_kv(keys)
+ end
+
+ def raise(tag, above=None)
+ tk_send 'raise', tagid(tag), above
+ end
+
+ def scale(tag, x, y, xs, ys)
+ tk_send 'scale', tagid(tag), x, y, xs, ys
+ end
+
+ def scan_mark(x, y)
+ tk_send 'scan', 'mark', x, y
+ end
+ def scan_dragto(x, y)
+ tk_send 'scan', 'dragto', x, y
+ end
+
+ def select(mode, *args)
+ tk_send 'select', mode, *args
+ end
+ def select_adjust(tagOrId, index)
+ select('adjust', tagid(tagOrId), index)
+ end
+ def select_clear
+ select('clear')
+ end
+ def select_from(tagOrId, index)
+ select('from', tagid(tagOrId), index)
+ end
+ def select_item
+ select('item')
+ end
+ def select_to(tagOrId, index)
+ select('to', tagid(tagOrId), index)
+ end
+
+ def itemtype(tag)
+ TkcItem.type2class(tk_send 'type', tagid(tag))
+ end
+
+ def xview(*index)
+ tk_send 'xview', *index
+ end
+ def yview(*index)
+ tk_send 'yview', *index
+ end
+end
+
+module TkcTagAccess
+ include TkComm
+ include TkTreatTagFont
+
+ def addtag(tag)
+ @c.addtag(tag, 'with', @id)
+ end
+
+ def bbox
+ @c.bbox(@id)
+ end
+
+ def bind(seq, cmd=Proc.new, args=nil)
+ @c.itembind @id, seq, cmd, args
+ end
+
+ def bindinfo(seq=nil)
+ @c.itembindinfo @id, seq
+ end
+
+ def cget(option)
+ @c.itemcget @id, option
+ end
+
+ def configure(key, value=None)
+ @c.itemconfigure @id, key, value
+ end
+# def configure(keys)
+# @c.itemconfigure @id, keys
+# end
+
+ def configinfo(key=nil)
+ @c.itemconfiginfo @id, key
+ end
+
+ def coords(*args)
+ @c.coords @id, *args
+ end
+
+ def dchars(first, last=None)
+ @c.dchars @id, first, last
+ end
+
+ def dtag(tag_to_del=None)
+ @c.dtag @id, tag_to_del
+ end
+
+ def find
+ @c.find 'withtag', @id
+ end
+ alias list find
+
+ def focus
+ @c.itemfocus @id
+ end
+
+ def gettags
+ @c.gettags @id
+ end
+
+ def icursor(index)
+ @c.icursor @id, index
+ end
+
+ def index(index)
+ @c.index @id, index
+ end
+
+ def insert(beforethis, string)
+ @c.insert @id, beforethis, string
+ end
+
+ def lower(belowthis=None)
+ @c.lower @id, belowthis
+ end
+
+ def move(xamount, yamount)
+ @c.move @id, xamount, yamount
+ end
+
+ def raise(abovethis=None)
+ @c.raise @id, abovethis
+ end
+
+ def scale(xorigin, yorigin, xscale, yscale)
+ @c.scale @id, xorigin, yorigin, xscale, yscale
+ end
+
+ def select_adjust(index)
+ @c.select('adjust', @id, index)
+ end
+ def select_from(index)
+ @c.select('from', @id, index)
+ end
+ def select_to(index)
+ @c.select('to', @id, index)
+ end
+
+ def itemtype
+ @c.itemtype @id
+ end
+end
+
+class TkcTag<TkObject
+ include TkcTagAccess
+
+ CTagID_TBL = {}
+
+ def TkcTag.id2obj(id)
+ CTagID_TBL[id]? CTagID_TBL[id]: id
+ end
+
+ $tk_canvas_tag = 'ctag0000'
+ def initialize(parent, mode=nil, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = $tk_canvas_tag
+ CTagID_TBL[@id] = self
+ $tk_canvas_tag = $tk_canvas_tag.succ
+ if mode
+ tk_call @c.path, "addtag", @id, mode, *args
+ end
+ end
+ def id
+ return @id
+ end
+
+ def delete
+ @c.delete @id
+ CTagID_TBL[@id] = nil
+ end
+ alias remove delete
+ alias destroy delete
+
+ def set_to_above(target)
+ @c.addtag_above(@id, target)
+ end
+ alias above set_to_above
+
+ def set_to_all
+ @c.addtag_all(@id)
+ end
+ alias all set_to_all
+
+ def set_to_below(target)
+ @c.addtag_below(@id, target)
+ end
+ alias below set_to_below
+
+ def set_to_closest(x, y, halo=None, start=None)
+ @c.addtag_closest(@id, x, y, halo, start)
+ end
+ alias closest set_to_closest
+
+ def set_to_enclosed(x1, y1, x2, y2)
+ @c.addtag_enclosest(@id, x1, y1, x2, y2)
+ end
+ alias enclosed set_to_enclosed
+
+ def set_to_overlapping(x1, y1, x2, y2)
+ @c.addtag_overlapping(@id, x1, y1, x2, y2)
+ end
+ alias overlapping set_to_overlapping
+
+ def set_to_withtag(target)
+ @c.addtag_withtag(@id, target)
+ end
+ alias withtag set_to_withtag
+end
+
+class TkcTagAll<TkcTag
+ def initialize(parent)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = 'all'
+ CTagID_TBL[@id] = self
+ end
+end
+
+class TkcTagCurrent<TkcTag
+ def initialize(parent)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = 'current'
+ CTagID_TBL[@id] = self
+ end
+end
+
+class TkcGroup<TkcTag
+ $tk_group_id = 'tkg00000'
+ def create_self(parent, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = $tk_group_id
+ CTagID_TBL[@id] = self
+ $tk_group_id = $tk_group_id.succ
+ add(*args) if args != []
+ end
+
+ def include(*tags)
+ for i in tags
+ i.addtag @id
+ end
+ end
+
+ def exclude(*tags)
+ for i in tags
+ i.delete @id
+ end
+ end
+end
+
+
+class TkcItem<TkObject
+ include TkcTagAccess
+
+ CItemTypeToClass = {}
+ CItemID_TBL = {}
+
+ def TkcItem.type2class(type)
+ CItemTypeToClass[type]
+ end
+
+ def TkcItem.id2obj(id)
+ CItemID_TBL[id]? CItemID_TBL[id]: id
+ end
+
+ def initialize(parent, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @parent = @c = parent
+ @path = parent.path
+ if args[-1].kind_of? Hash
+ keys = args.pop
+ end
+ @id = create_self(*args).to_i ;# 'canvas item id' is integer number
+ CItemID_TBL[@id] = self
+ if keys
+ # tk_call @path, 'itemconfigure', @id, *hash_kv(keys)
+ configure(keys) if keys
+ end
+ end
+ def create_self(*args); end
+ private :create_self
+ def id
+ return @id
+ end
+
+ def delete
+ @c.delete @id
+ CItemID_TBL[@id] = nil
+ end
+ alias remove delete
+ alias destroy delete
+end
+
+class TkcArc<TkcItem
+ CItemTypeToClass['arc'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'arc', *args)
+ end
+end
+class TkcBitmap<TkcItem
+ CItemTypeToClass['bitmap'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'bitmap', *args)
+ end
+end
+class TkcImage<TkcItem
+ CItemTypeToClass['image'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'image', *args)
+ end
+end
+class TkcLine<TkcItem
+ CItemTypeToClass['line'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'line', *args)
+ end
+end
+class TkcOval<TkcItem
+ CItemTypeToClass['oval'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'oval', *args)
+ end
+end
+class TkcPolygon<TkcItem
+ CItemTypeToClass['polygon'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'polygon', *args)
+ end
+end
+class TkcRectangle<TkcItem
+ CItemTypeToClass['rectangle'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'rectangle', *args)
+ end
+end
+class TkcText<TkcItem
+ CItemTypeToClass['text'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'text', *args)
+ end
+end
+class TkcWindow<TkcItem
+ CItemTypeToClass['window'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'window', *args)
+ end
+end
+
+class TkImage<TkObject
+ include Tk
+
+ Tk_IMGTBL = {}
+
+ $tk_image_id = 'i00000'
+ def initialize(keys=nil)
+ @path = $tk_image_id
+ $tk_image_id = $tk_image_id.succ
+ tk_call 'image', 'create', @type, @path, *hash_kv(keys)
+ Tk_IMGTBL[@path] = self
+ end
+
+ def delete
+ Tk_IMGTBL[@id] = nil if @id
+ tk_call('image', 'delete', @path)
+ end
+ def height
+ number(tk_call('image', 'height', @path))
+ end
+ def itemtype
+ tk_call('image', 'type', @path)
+ end
+ def width
+ number(tk_call('image', 'width', @path))
+ end
+
+ def TkImage.names
+ Tk.tk_call('image', 'names').split.filter{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
+ end
+
+ def TkImage.types
+ Tk.tk_call('image', 'types').split
+ end
+end
+
+class TkBitmapImage<TkImage
+ def initialize(*args)
+ @type = 'bitmap'
+ super
+ end
+end
+
+class TkPhotoImage<TkImage
+ def initialize(*args)
+ @type = 'photo'
+ super
+ end
+
+ def blank
+ tk_send 'blank'
+ end
+
+ def cget(option)
+ tk_tcl2ruby tk_send 'cget', option
+ end
+
+ def copy(source, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'copy', source, *args
+ end
+
+ def get(x, y)
+ tk_send 'get', x, y
+ end
+
+ def put(data, *to)
+ if to == []
+ tk_send 'put', data
+ else
+ tk_send 'put', data, '-to', *to
+ end
+ end
+
+ def read(file, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'read', file, *args
+ end
+
+ def redither
+ tk_send 'redither'
+ end
+
+ def write(file, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'write', file, *args
+ end
+end
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
new file mode 100644
index 0000000000..0b33d4ec8b
--- /dev/null
+++ b/ext/tk/lib/tkclass.rb
@@ -0,0 +1,38 @@
+#
+# tkclass.rb - Tk classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require "tk"
+
+TopLevel = TkToplevel
+Frame = TkFrame
+Label = TkLabel
+Button = TkButton
+Radiobutton = TkRadioButton
+Checkbutton = TkCheckButton
+Message = TkMessage
+Entry = TkEntry
+Text = TkText
+Scale = TkScale
+Scrollbar = TkScrollbar
+Listbox = TkListbox
+Menu = TkMenu
+Menubutton = TkMenubutton
+Canvas = TkCanvas
+Arc = TkcArc
+Bitmap = TkcBitmap
+Line = TkcLine
+Oval = TkcOval
+Polygon = TkcPolygon
+Rectangle = TkcRectangle
+TextItem = TkcText
+WindowItem = TkcWindow
+Selection = TkSelection
+Winfo = TkWinfo
+Pack = TkPack
+Variable = TkVariable
+
+def Mainloop
+ Tk.mainloop
+end
diff --git a/ext/tk/lib/tkdialog.rb b/ext/tk/lib/tkdialog.rb
new file mode 100644
index 0000000000..1133db6ae9
--- /dev/null
+++ b/ext/tk/lib/tkdialog.rb
@@ -0,0 +1,141 @@
+require "tk"
+
+class TkDialog < TkWindow
+ extend Tk
+
+ # initialize tk_dialog
+ def initialize(keys = nil)
+ super()
+ @var = TkVariable.new
+ id = @var.id
+
+ @title = title
+
+ @message = message
+ @message_config = message_config
+
+ @bitmap = bitmap
+ @bitmap_config = message_config
+
+ @default_button = default_button
+
+ @buttons = buttons
+ @button_configs = proc{|num| button_configs num}
+
+ if keys.kind_of? Hash
+ @title = keys['title'] if keys['title']
+ @message = keys['message'] if keys['message']
+ @bitmap = keys['bitmap'] if keys['bitmap']
+ @default_button = keys['default'] if keys['default']
+ @buttons = keys['buttons'] if keys['buttons']
+
+ @command = keys['prev_command']
+
+ @message_config = keys['message_config'] if keys['message_config']
+ @bitmap_config = keys['bitmap_config'] if keys['bitmap_config']
+ @button_configs = keys['button_configs'] if keys['button_configs']
+ end
+
+ if @title.include? ?\s
+ @title = '{' + @title + '}'
+ end
+
+ @buttons = tk_split_list(@buttons) if @buttons.kind_of? String
+ @buttons = @buttons.collect{|s|
+ if s.kind_of? Array
+ s = s.join(' ')
+ end
+ if s.include? ?\s
+ '{' + s + '}'
+ else
+ s
+ end
+ }
+
+ config = ""
+ if @message_config.kind_of? Hash
+ config << format("%s.msg configure %s\n",
+ @path, hash_kv(@message_config).join(' '))
+ end
+ if @bitmap_config.kind_of? Hash
+ config << format("%s.msg configure %s\n",
+ @path, hash_kv(@bitmap_config).join(' '))
+ end
+ if @button_configs.kind_of? Proc
+ @buttons.each_index{|i|
+ if (c = @button_configs.call(i)).kind_of? Hash
+ config << format("%s.button%s configure %s\n",
+ @path, i, hash_kv(c).join(' '))
+ end
+ }
+ end
+ config = 'after idle {' + config + '};' if config != ""
+
+ if @command.kind_of? Proc
+ @command.call(self)
+ end
+
+ INTERP._eval('eval {global '+id+';'+config+
+ 'set '+id+' [tk_dialog '+
+ @path+" "+@title+" {#{@message}} "+@bitmap+" "+
+ String(@default_button)+" "+@buttons.join(' ')+']}')
+ end
+ def value
+ return @var.value.to_i
+ end
+ ######################################################
+ # #
+ # these methods must be overridden for each dialog #
+ # #
+ ######################################################
+ def title
+ return "DIALOG"
+ end
+ def message
+ return "MESSAGE"
+ end
+ def message_config
+ return nil
+ end
+ def bitmap
+ return "info"
+ end
+ def bitmap_config
+ return nil
+ end
+ def default_button
+ return 0
+ end
+ def buttons
+ #return "BUTTON1 BUTTON2"
+ return ["BUTTON1", "BUTTON2"]
+ end
+ def button_configs(num)
+ return nil
+ end
+end
+
+#
+# dialog for warning
+#
+class TkWarning < TkDialog
+ def initialize(mes)
+ @mes = mes
+ super()
+ end
+ def message
+ return @mes
+ end
+ def title
+ return "WARNING";
+ end
+ def bitmap
+ return "warning";
+ end
+ def default_button
+ return 0;
+ end
+ def buttons
+ return "OK";
+ end
+end
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
new file mode 100644
index 0000000000..b834c455c6
--- /dev/null
+++ b/ext/tk/lib/tkentry.rb
@@ -0,0 +1,73 @@
+#
+# tkentry.rb - Tk entry classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+
+class TkEntry<TkLabel
+ WidgetClassName = 'Entry'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'entry', @path
+ end
+ def scrollcommand(cmd)
+ configure 'scrollcommand', cmd
+ end
+
+ def delete(s, e=None)
+ tk_send 'delete', s, e
+ end
+
+ def cursor
+ tk_send 'index', 'insert'
+ end
+ def cursor=(index)
+ tk_send 'icursor', index
+ end
+ def index(index)
+ number(tk_send('index', index))
+ end
+ def insert(pos,text)
+ tk_send 'insert', pos, text
+ end
+ def mark(pos)
+ tk_send 'scan', 'mark', pos
+ end
+ def dragto(pos)
+ tk_send 'scan', 'dragto', pos
+ end
+ def selection_adjust(index)
+ tk_send 'selection', 'adjust', index
+ end
+ def selection_clear
+ tk_send 'selection', 'clear', 'end'
+ end
+ def selection_from(index)
+ tk_send 'selection', 'from', index
+ end
+ def selection_present()
+ tk_send('selection', 'present') == 1
+ end
+ def selection_range(s, e)
+ tk_send 'selection', 'range', s, e
+ end
+ def selection_to(index)
+ tk_send 'selection', 'to', index
+ end
+ def xview(*index)
+ tk_send 'xview', *index
+ end
+
+ def value
+ tk_send 'get'
+ end
+ def value= (val)
+ tk_send 'delete', 0, 'end'
+ tk_send 'insert', 0, val
+ end
+end
diff --git a/ext/tk/lib/tkfont.rb b/ext/tk/lib/tkfont.rb
new file mode 100644
index 0000000000..421988aeca
--- /dev/null
+++ b/ext/tk/lib/tkfont.rb
@@ -0,0 +1,944 @@
+#
+# tkfont.rb - the class to treat fonts on Ruby/Tk
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class TkFont
+ include Tk
+ extend TkCore
+
+ Tk_FontID = [0]
+ Tk_FontNameTBL = {}
+ Tk_FontUseTBL = {}
+
+ DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
+
+ ###################################
+ # class methods
+ ###################################
+ def TkFont.families(window=nil)
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ ['fixed']
+
+ when /^8\.*/
+ if window
+ tk_split_simplelist(tk_call('font', 'families', '-displayof', window))
+ else
+ tk_split_simplelist(tk_call('font', 'families'))
+ end
+ end
+ end
+
+ def TkFont.names
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ r = ['fixed']
+ r += ['a14', 'k14'] if JAPANIZED_TK
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ r | []
+
+ when /^8\.*/
+ tk_split_simplelist(tk_call('font', 'names'))
+
+ end
+ end
+
+ def TkFont.create_copy(font)
+ keys = {}
+ font.configure.each{|key,value| keys[key] = value }
+ new_font = TkFont.new(font.latin_font, font.kanji_font, keys)
+ end
+
+ def TkFont.get_obj(name)
+ if name =~ /^(@font[0-9]+)(|c|l|k)$/
+ Tk_FontNameTBL[$1]
+ else
+ nil
+ end
+ end
+
+ def TkFont.init_widget_font(path, *args)
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ conf = tk_split_simplelist(tk_call(*args)).
+ find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}.
+ collect{|prop| tk_split_simplelist(prop)}
+ if font_inf = conf.assoc('-font')
+ ltn = font_inf[4]
+ ltn = nil if ltn == []
+ else
+ #ltn = nil
+ raise RuntimeError, "unknown option '-font'"
+ end
+ if font_inf = conf.assoc('-kanjifont')
+ knj = font_inf[4]
+ knj = nil if knj == []
+ else
+ knj = nil
+ end
+ TkFont.new(ltn, knj).call_font_configure(path, *(args + [{}]))
+
+ when /^8\.*/
+ font_prop = tk_split_simplelist(tk_call(*args)).find{|prop|
+ prop[0..5] == '-font '
+ }
+ unless font_prop
+ raise RuntimeError, "unknown option '-font'"
+ end
+ fnt = tk_split_simplelist(font_prop)[4]
+ if fnt == ""
+ TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
+ else
+ begin
+ compound = Hash[*list(tk_call('font', 'configure',
+ fnt))].collect{|key,value|
+ [key[1..-1], value]
+ }.assoc('compound')[1]
+ rescue
+ compound = []
+ end
+ if compound == []
+ TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
+ .call_font_configure(path, *(args + [{}]))
+ else
+ TkFont.new(compound[0], compound[1]) \
+ .call_font_configure(path, *(args + [{}]))
+ end
+ end
+ end
+ end
+
+ def TkFont.used_on(path=nil)
+ if path
+ Tk_FontUseTBL[path]
+ else
+ Tk_FontUseTBL.values | []
+ end
+ end
+
+ ###################################
+ private
+ ###################################
+ def initialize(ltn=nil, knj=nil, keys=nil)
+ @id = format("@font%.4d", Tk_FontID[0])
+ Tk_FontID[0] += 1
+ Tk_FontNameTBL[@id] = self
+
+ ltn = DEFAULT_LATIN_FONT_NAME unless ltn
+ create_latinfont(ltn)
+
+ knj = DEFAULT_KANJI_FONT_NAME unless knj
+ create_kanjifont(knj)
+
+ create_compoundfont(keys)
+ end
+
+ def _get_font_info_from_hash(font)
+ foundry = (info = font['foundry'] .to_s)? info: '*'
+ family = (info = font['family'] .to_s)? info: '*'
+ weight = (info = font['weight'] .to_s)? info: '*'
+ slant = (info = font['slant'] .to_s)? info: '*'
+ swidth = (info = font['swidth'] .to_s)? info: '*'
+ adstyle = (info = font['adstyle'] .to_s)? info: '*'
+ pixels = (info = font['pixels'] .to_s)? info: '*'
+ points = (info = font['points'] .to_s)? info: '*'
+ resx = (info = font['resx'] .to_s)? info: '*'
+ resy = (info = font['resy'] .to_s)? info: '*'
+ space = (info = font['space'] .to_s)? info: '*'
+ avgWidth = (info = font['avgWidth'].to_s)? info: '*'
+ charset = (info = font['charset'] .to_s)? info: '*'
+ encoding = (info = font['encoding'].to_s)? info: '*'
+
+ Array([foundry, family, weight, slant, swidth, adstyle,
+ pixels, points, resx, resy, space, avgWidth, charset, encoding])
+ end
+
+ def create_latinfont_tk4x(font)
+ if font.kind_of? Hash
+ @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+
+ elsif font.kind_of? TkFont
+ @latinfont = font.latin_font
+
+ else
+ @latinfont = font
+
+ end
+ end
+
+ def create_kanjifont_tk4x(font)
+ unless JAPANIZED_TK
+ @kanjifont = ""
+ return
+ end
+
+ if font.kind_of? Hash
+ @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+
+ elsif font.kind_of? TkFont
+ @kanjifont = font.kanji_font
+
+ else
+ @kanjifont = font
+
+ end
+ end
+
+ def create_compoundfont_tk4x(keys)
+ if JAPANIZED_TK
+ @compoundfont = [[@latinfont], [@kanjifont]]
+ @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
+ else
+ @compoundfont = @latinfont
+ @fontslot = {'font'=>@latinfont}
+ end
+ end
+
+ def create_latinfont_tk8x(font)
+ @latinfont = @id + 'l'
+
+ if JAPANIZED_TK
+ if font.kind_of? Hash
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font))
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @latinfont, '-copy', font.latin_font)
+ else
+ tk_call('font', 'create', @latinfont, '-copy', font)
+ end
+ else
+ if font.kind_of? Hash
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.latin_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @latinfont, *hash_kv(keys))
+ end
+ end
+ end
+
+ def create_kanjifont_tk80(font)
+ unless JAPANIZED_TK
+ @kanjifont = ""
+ return
+ end
+
+ @kanjifont = @id + 'k'
+
+ if font.kind_of? Hash
+ if font['charset']
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ tk_call('font', 'create', @kanjifont,
+ '-charset', 'jisx0208.1983', *hash_kv(font))
+ end
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font))
+ tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983')
+
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font)
+
+ else
+ tk_call('font', 'create', @kanjifont, '-copy', font,
+ '-charset', 'jisx0208.1983')
+
+ end
+ end
+
+ def create_kanjifont_tk81(font)
+ @kanjifont = @id + 'k'
+
+ if font.kind_of? Hash
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.kanji_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @kanjifont, *hash_kv(keys))
+ end
+
+ keys = {}
+ actual_core(@kanjifont).each{|key,val| keys[key] = val}
+ begin
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ rescue
+ end
+ end
+
+ def create_compoundfont_tk80(keys)
+ @compoundfont = @id + 'c'
+ if JAPANIZED_TK
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ else
+ tk_call('font', 'create', @compoundfont)
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ end
+
+ def create_compoundfont_tk81(keys)
+ @compoundfont = @id + 'c'
+ tk_call('font', 'create', @compoundfont)
+
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+
+ kanjikeys = {}
+ begin
+ actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val}
+ rescue
+ kanjikeys {}
+ end
+ if kanjikeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys))
+ end
+
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+
+ def actual_core_tk4x(font, window=nil, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ Array([ ['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
+ ['underline',[]], ['overstrike',[]], ['charset',[]],
+ ['pointadjust',[]] ])
+ end
+ end
+
+ def actual_core_tk8x(font, window=nil, option=nil)
+ if option == 'compound'
+ ""
+ elsif option
+ if window
+ tk_call('font', 'actual', font, "-#{option}")
+ else
+ tk_call('font', 'actual', font, "-displayof", window, "-#{option}")
+ end
+ else
+ l = tk_split_simplelist(if window
+ tk_call('font', 'actual', font,
+ "-displayof", window)
+ else
+ tk_call('font', 'actual', font)
+ end)
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ r.push [key[1..-1], l.shift]
+ end
+ end
+ r
+ end
+ end
+
+ def configure_core_tk4x(font, slot, value=None)
+ ""
+ end
+
+ def configinfo_core_tk4x(font, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ Array([ ['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
+ ['underline',[]], ['overstrike',[]], ['charset',[]],
+ ['pointadjust',[]] ])
+ end
+ end
+
+ def configure_core_tk8x(font, slot, value=None)
+ if slot.kind_of? Hash
+ tk_call 'font', 'configure', font, *hash_kv(slot)
+ else
+ tk_call 'font', 'configure', font, "-#{slot}", value
+ end
+ end
+
+ def configinfo_core_tk8x(font, option=nil)
+ if option == 'compound'
+ ""
+ elsif option
+ tk_call('font', 'configure', font, "-#{option}")
+ else
+ l = tk_split_simplelist(tk_call('font', 'configure', font))
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ r.push [key[1..-1], l.shift]
+ end
+ end
+ r
+ end
+ end
+
+ def delete_core_tk4x
+ Tk_FontNameTBL[@id] = nil
+ Tk_FontUseTBL.delete_if{|key,value| value == self}
+ end
+
+ def delete_core_tk8x
+ begin
+ tk_call('font', 'delete', @latinfont)
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @kanjifont)
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @compoundfont)
+ rescue
+ end
+ Tk_FontNameTBL[@id] = nil
+ Tk_FontUseTBL.delete_if{|key,value| value == self}
+ end
+
+ def latin_replace_core_tk4x(ltn)
+ create_latinfont_tk4x(ltn)
+ @compoundfont[0] = [@latinfont] if JAPANIZED_TK
+ @fontslot['font'] = @latinfont
+ Tk_FontUseTBL.dup.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag = w.split(';')
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'font'=>@latinfont})
+ if winobj.kind_of? TkText
+ tk_call(win, 'tag', 'configure', tag, '-font', @latinfont)
+ elsif winobj.kind_of? TkCanvas
+ tk_call(win, 'itemconfigure', tag, '-font', @latinfont)
+ elsif winobj.kind_of? TkMenu
+ tk_call(win, 'entryconfigure', tag, '-font', @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('font'=>@latinfont)
+ tk_call(w, 'configure', '-font', @latinfont)
+ end
+ rescue
+ Tk_FontUseTBL[w] = nil
+ end
+ end
+ }
+ self
+ end
+
+ def kanji_replace_core_tk4x(knj)
+ return self unless JAPANIZED_TK
+
+ create_kanjifont_tk4x(knj)
+ @compoundfont[1] = [@kanjifont]
+ @fontslot['kanjifont'] = @kanjifont
+ Tk_FontUseTBL.dup.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag = w.split(';')
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
+ if winobj.kind_of? TkText
+ tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont)
+ elsif winobj.kind_of? TkCanvas
+ tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont)
+ elsif winobj.kind_of? TkMenu
+ tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont)
+ tk_call(w, 'configure', '-kanjifont', @kanjifont)
+ end
+ rescue
+ Tk_FontUseTBL[w] = nil
+ end
+ end
+ }
+ self
+ end
+
+ def latin_replace_core_tk8x(ltn)
+ begin
+ tk_call('font', 'delete', @latinfont)
+ rescue
+ end
+ create_latinfont(ltn)
+ self
+ end
+
+ def kanji_replace_core_tk80(knj)
+ return self unless JAPANIZED_TK
+
+ begin
+ tk_call('font', 'delete', @kanjifont)
+ rescue
+ end
+ create_kanjifont(knj)
+ self
+ end
+
+ def kanji_replace_core_tk81(knj)
+ if font.kind_of? Hash
+ tk_call('font', 'configure', @compoundfont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.latin_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ self
+ end
+
+ def measure_core_tk4x(window, text)
+ 0
+ end
+
+ def measure_core_tk8x(window, text)
+ if window
+ number(tk_call('font', 'measure', @compoundfont,
+ '-displayof', window, text))
+ else
+ number(tk_call('font', 'measure', @compoundfont, text))
+ end
+ end
+
+ def metrics_core_tk4x(font, window, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ Array([ ['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]] ])
+ end
+ end
+
+ def metrics_core_tk8x(font, window, option=nil)
+ if option
+ if window
+ number(tk_call('font', 'metrics', font, "-#{option}"))
+ else
+ number(tk_call('font', 'metrics', font,
+ "-displayof", window, "-#{option}"))
+ end
+ else
+ l = tk_split_list(if window
+ tk_call('font','metrics',font,"-displayof",window)
+ else
+ tk_call('font','metrics',font)
+ end)
+ r = []
+ while key=l.shift
+ r.push [key[1..-1], l.shift.to_i]
+ end
+ r
+ end
+ end
+
+ ###################################
+ # private alias
+ ###################################
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ alias create_latinfont create_latinfont_tk4x
+ alias create_kanjifont create_kanjifont_tk4x
+ alias create_compoundfont create_compoundfont_tk4x
+ alias actual_core actual_core_tk4x
+ alias configure_core configure_core_tk4x
+ alias configinfo_core configinfo_core_tk4x
+ alias delete_core delete_core_tk4x
+ alias latin_replace_core latin_replace_core_tk4x
+ alias kanji_replace_core kanji_replace_core_tk4x
+ alias measure_core measure_core_tk4x
+ alias metrics_core metrics_core_tk4x
+
+ when /^8\.0/
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk80
+ alias create_compoundfont create_compoundfont_tk80
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk80
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ when /^8\.1/
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk81
+ alias create_compoundfont create_compoundfont_tk81
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk81
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ end
+
+ ###################################
+ public
+ ###################################
+ def call_font_configure(path, *args)
+ args += hash_kv(args.pop.update(@fontslot))
+ tk_call *args
+ Tk_FontUseTBL[path] = self
+ self
+ end
+
+ def used
+ ret = []
+ Tk_FontUseTBL.each{|key,value|
+ if key.include?(';')
+ win, tag = key.split(';')
+ winobj = tk_tcl2ruby(win)
+ if winobj.kind_of? TkText
+ ret.push([winobj, winobj.tagid2obj(tag)])
+ elsif winobj.kind_of? TkCanvas
+ if (tagobj = TkcTag.id2obj(tag)).kind_of? TkcTag
+ ret.push([winobj, tagobj])
+ elsif (tagobj = TkcItem.id2obj(tag)).kind_of? TkcItem
+ ret.push([winobj, tagobj])
+ else
+ ret.push([winobj, tag])
+ end
+ elsif winobj.kind_of? TkMenu
+ ret.push([winobj, tag])
+ else
+ ret.push([win, tag])
+ end
+ else
+ ret.push(tk_tcl2ruby(key)) if value == self
+ end
+ }
+ ret
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ font
+ end
+
+ def font
+ @compoundfont
+ end
+
+ def latin_font
+ @latinfont
+ end
+
+ def kanji_font
+ @kanjifont
+ end
+
+ def actual(option=nil)
+ actual_core(@compoundfont, nil, option)
+ end
+
+ def actual_displayof(window, option=nil)
+ window = '.' unless window
+ actual_core(@compoundfont, window, option)
+ end
+
+ def latin_actual(option=nil)
+ actual_core(@latinfont, nil, option)
+ end
+
+ def latin_actual_displayof(window, option=nil)
+ window = '.' unless window
+ actual_core(@latinfont, window, option)
+ end
+
+ def kanji_actual(option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ actual_core(@kanjifont, nil, option)
+ else
+ actual_core_tk4x(nil, nil, option)
+ end
+ end
+
+ def kanji_actual_displayof(window, option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ window = '.' unless window
+ actual_core(@kanjifont, window, option)
+ else
+ actual_core_tk4x(nil, window, option)
+ end
+ end
+
+ def [](slot)
+ configinfo slot
+ end
+
+ def []=(slot, val)
+ configure slot, val
+ end
+
+ def configure(slot, value=None)
+ configure_core(@compoundfont, slot, value)
+ end
+
+ def configinfo(slot=nil)
+ configinfo_core(@compoundfont, slot)
+ end
+
+ def delete
+ delete_core
+ end
+
+ def latin_configure(slot, value=None)
+ if JAPANIZED_TK
+ configure_core(@latinfont, slot, value)
+ else
+ configure(slot, value)
+ end
+ end
+
+ def latin_configinfo(slot=nil)
+ if JAPANIZED_TK
+ configinfo_core(@latinfont, slot)
+ else
+ configure(slot, value)
+ end
+ end
+
+ def kanji_configure(slot, value=None)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ configure_core(@kanjifont, slot, value)
+ else
+ #""
+ configure(slot, value)
+ end
+ end
+
+ def kanji_configinfo(slot=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ configinfo_core(@kanjifont, slot)
+ else
+ #[]
+ configinfo(slot)
+ end
+ end
+
+ def replace(ltn, knj)
+ latin_replace(ltn)
+ kanji_replace(knj)
+ self
+ end
+
+ def latin_replace(ltn)
+ latin_replace_core(ltn)
+ end
+
+ def kanji_replace(knj)
+ kanji_replace_core(knj)
+ end
+
+ def measure(text)
+ measure_core(nil, text)
+ end
+
+ def measure_displayof(window, text)
+ window = '.' unless window
+ measure_core(window, text)
+ end
+
+ def metrics(option=nil)
+ metrics_core(@compoundfont, nil, option)
+ end
+
+ def metrics_displayof(window, option=nil)
+ window = '.' unless window
+ metrics_core(@compoundfont, window, option)
+ end
+
+ def latin_metrics(option=nil)
+ metrics_core(@latinfont, nil, option)
+ end
+
+ def latin_metrics_displayof(window, option=nil)
+ window = '.' unless window
+ metrics_core(@latinfont, window, option)
+ end
+
+ def kanji_metrics(option=nil)
+ if JAPANIZED_TK
+ metrics_core(@kanjifont, nil, option)
+ else
+ metrics_core_tk4x(nil, nil, option)
+ end
+ end
+
+ def kanji_metrics_displayof(window, option=nil)
+ if JAPANIZED_TK
+ window = '.' unless window
+ metrics_core(@kanjifont, window, option)
+ else
+ metrics_core_tk4x(nil, window, option)
+ end
+ end
+
+ ###################################
+ # public alias
+ ###################################
+ alias ascii_font latin_font
+ alias create_asciifont create_latinfont
+ alias ascii_actual latin_actual
+ alias ascii_actual_displayof latin_actual_displayof
+ alias ascii_configure latin_configure
+ alias ascii_configinfo latin_configinfo
+ alias ascii_replace latin_replace
+ alias ascii_metrics latin_metrics
+
+end
+
+module TkTreatTagFont
+ def font_configinfo
+ @parent.tagfont_configinfo(@id)
+ end
+ alias font font_configinfo
+
+ def font_configure(slot)
+ @parent.tagfont_configure(@id, slot)
+ end
+
+ def latinfont_configure(ltn, keys=nil)
+ @parent.latintagfont_configure(@id, ltn, keys)
+ end
+ alias asciifont_configure latinfont_configure
+
+ def kanjifont_configure(knj, keys=nil)
+ @parent.kanjitagfont_configure(@id, ltn, keys)
+ end
+
+ def font_copy(window, wintag=nil)
+ @parent.tagfont_copy(@id, window, wintag)
+ end
+
+ def latinfont_copy(window, wintag=nil)
+ @parent.latintagfont_copy(@id, window, wintag)
+ end
+ alias asciifont_copy latinfont_copy
+
+ def kanjifont_copy(window, wintag=nil)
+ @parent.kanjitagfont_copy(@id, window, wintag)
+ end
+end
diff --git a/ext/tk/lib/tkmenubar.rb b/ext/tk/lib/tkmenubar.rb
new file mode 100644
index 0000000000..441f3f5c03
--- /dev/null
+++ b/ext/tk/lib/tkmenubar.rb
@@ -0,0 +1,137 @@
+#
+# tkmenubar.rb
+#
+# Copyright (C) 1998 maeda shugo. All rights reserved.
+# This file can be distributed under the terms of the Ruby.
+
+# Usage:
+#
+# menu_spec = [
+# [['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]],
+# [['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]]
+# ]
+# menubar = TkMenubar.new(nil, menu_spec,
+# 'tearoff'=>false,
+# 'foreground'=>'grey40',
+# 'activeforeground'=>'red',
+# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+#
+#
+# OR
+#
+#
+# menubar = TkMenubar.new
+# menubar.add_menu([['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]])
+# menubar.add_menu([['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]])
+# menubar.configure('tearoff', false)
+# menubar.configure('foreground', 'grey40')
+# menubar.configure('activeforeground', 'red')
+# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+
+# The format of the menu_spec is:
+# [
+# [
+# [button text, underline, accelerator],
+# [menu label, command, underline, accelerator],
+# '---', # separator
+# ...
+# ],
+# ...
+# ]
+
+# underline and accelerator are optional parameters.
+# Hashes are OK instead of Arrays.
+
+# To use add_menu, configuration must be done by calling configure after
+# adding all menus by add_menu, not by the constructor arguments.
+
+require "tk"
+
+class TkMenubar<TkFrame
+
+ include TkComposite
+
+ def initialize(parent = nil, spec = nil, options = nil)
+ super(parent, options)
+
+ @menus = []
+
+ if spec
+ for menu_info in spec
+ add_menu(menu_info)
+ end
+ end
+
+ if options
+ for key, value in options
+ configure(key, value)
+ end
+ end
+ end
+
+ def add_menu(menu_info)
+ btn_info = menu_info.shift
+ mbtn = TkMenubutton.new(@frame)
+
+ if btn_info.kind_of?(Hash)
+ for key, value in btn_info
+ mbtn.configure(key, value)
+ end
+ elsif btn_info.kind_of?(Array)
+ mbtn.configure('text', btn_info[0]) if btn_info[0]
+ mbtn.configure('underline', btn_info[1]) if btn_info[1]
+ mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
+ else
+ mbtn.configure('text', btn_info)
+ end
+
+ menu = TkMenu.new(mbtn)
+
+ for item_info in menu_info
+ if item_info.kind_of?(Hash)
+ menu.add('command', item_info)
+ elsif item_info.kind_of?(Array)
+ options = {}
+ options['label'] = item_info[0] if item_info[0]
+ options['command'] = item_info[1] if item_info[1]
+ options['underline'] = item_info[2] if item_info[2]
+ options['accelerator'] = item_info[3] if item_info[3]
+ menu.add('command', options)
+ elsif /^-+$/ =~ item_info
+ menu.add('sep')
+ else
+ menu.add('command', 'label' => item_info)
+ end
+ end
+
+ mbtn.menu(menu)
+ @menus.push([mbtn, menu])
+ delegate('tearoff', menu)
+ delegate('foreground', mbtn, menu)
+ delegate('background', mbtn, menu)
+ delegate('disabledforeground', mbtn, menu)
+ delegate('activeforeground', mbtn, menu)
+ delegate('activebackground', mbtn, menu)
+ delegate('font', mbtn, menu)
+ delegate('kanjifont', mbtn, menu)
+ mbtn.pack('side' => 'left')
+ end
+
+ def [](index)
+ return @menus[index]
+ end
+end
diff --git a/ext/tk/lib/tkmngfocus.rb b/ext/tk/lib/tkmngfocus.rb
new file mode 100644
index 0000000000..921fb646e7
--- /dev/null
+++ b/ext/tk/lib/tkmngfocus.rb
@@ -0,0 +1,27 @@
+#
+# tkmngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkManageFocus
+ extend Tk
+
+ def TkManageFocus.followsMouse
+ tk_call 'tk_focusFollowsMouse'
+ end
+
+ def TkManageFocus.next(window)
+ tk_call 'tk_focusNext', window
+ end
+ def focusNext
+ TkManageFocus.next(self)
+ end
+
+ def TkManageFocus.prev(window)
+ tk_call 'tk_focusPrev', window
+ end
+ def focusPrev
+ TkManageFocus.prev(self)
+ end
+end
diff --git a/ext/tk/lib/tkpalette.rb b/ext/tk/lib/tkpalette.rb
new file mode 100644
index 0000000000..a2dc7c87cb
--- /dev/null
+++ b/ext/tk/lib/tkpalette.rb
@@ -0,0 +1,48 @@
+#
+# tkpalette.rb : methods for Tcl/Tk standard library 'palette.tcl'
+# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkPalette
+ include Tk
+ extend Tk
+
+ def TkPalette.set(*args)
+ args = args.to_a.flatten if args.kind_of? Hash
+ tk_call 'tk_setPalette', *args
+ end
+ def TkPalette.setPalette(*args)
+ TkPalette.set(*args)
+ end
+
+ def TkPalette.bisque
+ tk_call 'tk_bisque'
+ end
+
+ def TkPalette.darken(color, percent)
+ tk_call 'tkDarken', color, percent
+ end
+
+ def TkPalette.recolorTree(window, colors)
+ if not colors.kind_of?(Hash)
+ fail "2nd arg need to be Hash"
+ end
+
+ colors.each{|key, value|
+ begin
+ if window.cget(key) == tk_call('set', "tkPalette(#{key})")
+ window[key] = colors[key]
+ end
+ rescue
+ # ignore
+ end
+ }
+
+ TkWinfo.children(window).each{|w| TkPalette.recolorTree(w, colors)}
+ end
+
+ def recolorTree(colors)
+ TkPalette.recolorTree(self, colors)
+ end
+end
diff --git a/ext/tk/lib/tkscrollbox.rb b/ext/tk/lib/tkscrollbox.rb
new file mode 100644
index 0000000000..8d129b2f4b
--- /dev/null
+++ b/ext/tk/lib/tkscrollbox.rb
@@ -0,0 +1,27 @@
+#
+# tkscrollbox.rb - Tk Listbox with Scrollbar
+# as an example of Composite Widget
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+
+class TkScrollbox<TkListbox
+ include TkComposite
+ def initialize_composite
+ list = TkListbox.new(@frame)
+ scroll = TkScrollbar.new(@frame)
+ @path = list.path
+
+ list.configure 'yscroll', scroll.path+" set"
+ list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
+ scroll.configure 'command', list.path+" yview"
+ scroll.pack 'side'=>'right','fill'=>'y'
+
+ delegate('DEFAULT', list)
+ delegate('foreground', list)
+ delegate('background', list, scroll)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+ end
+end
diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb
new file mode 100644
index 0000000000..02d5a7f3e0
--- /dev/null
+++ b/ext/tk/lib/tktext.rb
@@ -0,0 +1,797 @@
+#
+# tktext.rb - Tk text classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+require 'tkfont'
+
+module TkTreatTextTagFont
+ def tagfont_configinfo(tag)
+ if tag.kind_of? TkTextTag
+ pathname = self.path + ';' + tag.id
+ else
+ pathname = self.path + ';' + tag
+ end
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'tag', 'configure', tag)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(tag, slot)
+ if tag.kind_of? TkTextTag
+ pathname = self.path + ';' + tag.id
+ else
+ pathname = self.path + ';' + tag
+ end
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'tag','configure',tag,slot)
+ else
+ latintagfont_configure(tag, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(tag, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(tag, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(tag, knj) if knj
+ end
+
+ tk_call(self.path, 'tag', 'configure', tag, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(tag, ltn, keys=nil)
+ fobj = tagfontobj(tag)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(tag, knj, keys=nil)
+ fobj = tagfontobj(tag)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(tag, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(tag).configure(key,value)
+ }
+ tagfontobj(tag).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(wintag).configinfo.each{|key,value|
+ tagfontobj(tag).configure(key,value)
+ }
+ tagfontobj(tag).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(tag, window, wintag=nil)
+ if wintag
+ tagfontobj(tag).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(tag).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(tag, window, wintag=nil)
+ if wintag
+ tagfontobj(tag).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(tag).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkText<TkTextWin
+ include TkTreatTextTagFont
+
+ WidgetClassName = 'Text'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ include Scrollable
+ def create_self
+ tk_call 'text', @path
+ @tags = {}
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def value
+ tk_send 'get', "1.0", "end - 1 char"
+ end
+ def value= (val)
+ tk_send 'delete', "1.0", 'end'
+ tk_send 'insert', "1.0", val
+ end
+ def _addcmd(cmd)
+ @cmdtbl.push cmd
+ end
+ def _addtag(name, obj)
+ @tags[name] = obj
+ end
+
+ def tagid2obj(tagid)
+ if not @tags[tagid]
+ tagid
+ else
+ @tags[tagid]
+ end
+ end
+
+ def tag_names(index=None)
+ tk_split_list(tk_send('tag', 'names', index)).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+ def window_names
+ tk_send('window', 'names').collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+ def image_names
+ tk_send('image', 'names').collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def set_insert(index)
+ tk_send 'mark', 'set', 'insert', index
+ end
+ def set_current(index)
+ tk_send 'mark', 'set', 'current', index
+ end
+
+ def insert(index, chars, *tags)
+ super index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')
+ end
+
+ def destroy
+ @tags.each_value do |t|
+ t.destroy
+ end
+ super
+ end
+
+ def backspace
+ self.delete 'insert'
+ end
+
+ def compare(idx1, op, idx2)
+ bool(tk_send('compare', idx1, op, idx2))
+ end
+
+ def debug
+ bool(tk_send('debug'))
+ end
+ def debug=(boolean)
+ tk_send 'debug', boolean
+ end
+
+ def bbox(index)
+ inf = tk_send('bbox', index)
+ (inf == "")? [0,0,0,0]: inf
+ end
+ def dlineinfo(index)
+ inf = tk_send('dlineinfo', index)
+ (inf == "")? [0,0,0,0,0]: inf
+ end
+
+ def yview(*what)
+ tk_send 'yview', *what
+ end
+ def yview_pickplace(*what)
+ tk_send 'yview', '-pickplace', *what
+ end
+
+ def xview(*what)
+ tk_send 'xview', *what
+ end
+ def xview_pickplace(*what)
+ tk_send 'xview', '-pickplace', *what
+ end
+
+ def tag_add(tag,index1,index2=None)
+ tk_send 'tag', 'add', tag, index1, index2
+ end
+
+ def _tag_bind_core(mode, tag, seq, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ tk_send 'tag', 'bind', tag, "<#{tk_event_sequence(seq)}>", mode + id
+ # _addcmd cmd
+ end
+ private :_tag_bind_core
+
+ def tag_bind(tag, seq, cmd=Proc.new, args=nil)
+ _tag_bind_core('', tag, seq, cmd=Proc.new, args=nil)
+ end
+
+ def tag_bind_append(tag, seq, cmd=Proc.new, args=nil)
+ _tag_bind_core('+', tag, seq, cmd=Proc.new, args=nil)
+ end
+
+ def tag_bindinfo(tag, context=nil)
+ if context
+ (tk_send('tag', 'bind', tag,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_send('tag', 'bind', tag)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def tag_cget(tag, key)
+ tk_tcl2ruby tk_call @t.path, 'tag', 'cget', tag, "-#{key}"
+ end
+
+ def tag_configure(tag, key, val=None)
+ if key.kind_of? Hash
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tag, key.dup)
+ else
+ tk_send 'tag', 'configure', tag, *hash_kv(key)
+ end
+
+ else
+ if ( key == 'font' || key == 'kanjifont' \
+ || key == 'latinfont' || key == 'asciifont' )
+ tagfont_configure({key=>val})
+ else
+ tk_call 'tag', 'configure', tag, "-#{key}", val
+ end
+ end
+ end
+
+ def tag_configinfo(tag, key=nil)
+ if key
+ conf = tk_split_list(tk_send('tag','configure',tag,"-#{key}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send('tag', 'configure', tag)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+
+ def tag_raise(tag, above=None)
+ tk_send 'tag', 'raise', tag, above
+ end
+
+ def tag_lower(tag, below=None)
+ tk_send 'tag', 'lower', tag, below
+ end
+
+ def tag_remove(tag, *index)
+ tk_send 'tag', 'remove', tag, *index
+ end
+
+ def tag_ranges(tag)
+ l = tk_split_list(tk_send('tag', 'ranges', tag))
+ r = []
+ while key=l.shift
+ r.push [key, l.shift]
+ end
+ r
+ end
+
+ def tag_nextrange(tag, first, last=None)
+ tk_split_list(tk_send('tag', 'nextrange', tag, first, last))
+ end
+
+ def tag_prevrange(tag, first, last=None)
+ tk_split_list(tk_send('tag', 'prevrange', tag, first, last))
+ end
+
+ def search_with_length(pat,start,stop=None)
+ pat = pat.char if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'>=',stop)
+ txt = get(start,stop)
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(start + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(start + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get(start,'end - 1 char')
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(start + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(start + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def search(pat,start,stop=None)
+ search_with_length(pat,start,stop)[0]
+ end
+
+ def rsearch_with_length(pat,start,stop=None)
+ pat = pat.char if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'<=',stop)
+ txt = get(stop,start)
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(stop + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(stop + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get('1.0',start)
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def rsearch(pat,start,stop=None)
+ rsearch_with_length(pat,start,stop)[0]
+ end
+end
+
+class TkTextTag<TkObject
+ include TkTreatTagFont
+
+ $tk_text_tag = 'tag0000'
+ def initialize(parent, keys=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @parent = @t = parent
+ @path = @id = $tk_text_tag
+ $tk_text_tag = $tk_text_tag.succ
+ #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
+ configure(keys) if keys
+ @t._addtag id, self
+ end
+ def id
+ return @id
+ end
+
+ def first
+ @id + '.first'
+ end
+
+ def last
+ @id + '.last'
+ end
+
+ def add(*index)
+ tk_call @t.path, 'tag', 'add', @id, *index
+ end
+
+ def remove(*index)
+ tk_call @t.path, 'tag', 'remove', @id, *index
+ end
+
+ def ranges
+ l = tk_split_list(tk_call(@t.path, 'tag', 'ranges', @id))
+ r = []
+ while key=l.shift
+ r.push [key, l.shift]
+ end
+ r
+ end
+
+ def nextrange(first, last=None)
+ tk_split_list(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
+ end
+
+ def prevrange(first, last=None)
+ tk_split_list(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
+ end
+
+ def [](key)
+ cget key
+ end
+
+ def []=(key,val)
+ configure key, val
+ end
+
+ def cget(key)
+ tk_tcl2ruby tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
+ end
+
+ def configure(key, val=None)
+ @t.tag_configure @id, key, val
+ end
+# def configure(key, val=None)
+# if key.kind_of? Hash
+# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
+# else
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
+# end
+# end
+# def configure(key, value)
+# if value == FALSE
+# value = "0"
+# elsif value.kind_of? Proc
+# value = install_cmd(value)
+# end
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
+# end
+
+ def configinfo(key=nil)
+ @t.tag_configinfo @id, key
+ end
+# def configinfo(key=nil)
+# if key
+# conf = tk_split_list(tk_call(@t.path, 'tag','configure',@id,"-#{key}"))
+# conf[0] = conf[0][1..-1]
+# conf
+# else
+# tk_split_list(tk_call(@t.path, 'tag', 'configure', @id)).collect{|conf|
+# conf[0] = conf[0][1..-1]
+# conf
+# }
+# end
+# end
+
+ def bind(seq, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ tk_call @t.path, 'tag', 'bind', @id, "<#{tk_event_sequence(seq)}>", id
+ # @t._addcmd cmd
+ end
+
+ def bindinfo(context=nil)
+ if context
+ (tk_call(@t.path, 'tag', 'bind', @id,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_call(@t.path, 'tag', 'bind', @id)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def raise(above=None)
+ tk_call @t.path, 'tag', 'raise', @id, above
+ end
+
+ def lower(below=None)
+ tk_call @t.path, 'tag', 'lower', @id, below
+ end
+
+ def destroy
+ tk_call @t.path, 'tag', 'delete', @id
+ end
+end
+
+class TkTextTagSel<TkTextTag
+ def initialize(parent, keys=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'sel'
+ #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
+ configure(keys) if keys
+ @t._addtag id, self
+ end
+end
+
+class TkTextMark<TkObject
+ $tk_text_mark = 'mark0000'
+ def initialize(parent, index)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = $tk_text_mark
+ $tk_text_mark = $tk_text_mark.succ
+ tk_call @t.path, 'mark', 'set', @id, index
+ @t._addtag id, self
+ end
+ def id
+ return @id
+ end
+
+ def set(where)
+ tk_call @t.path, 'mark', 'set', @id, where
+ end
+
+ def unset
+ tk_call @t.path, 'mark', 'unset', @id
+ end
+ alias destroy unset
+
+ def gravity
+ tk_call @t.path, 'mark', 'gravity', @id
+ end
+
+ def gravity=(direction)
+ tk_call @t.path, 'mark', 'gravity', @id, direction
+ end
+end
+
+class TkTextMarkInsert<TkTextMark
+ def initialize(parent, index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'insert'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
+class TkTextMarkCurrent<TkTextMark
+ def initialize(parent,index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'current'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
+class TkTextWindow<TkObject
+ def initialize(parent, index, keys)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ if index == 'end'
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ elsif index.kind_of? TkTextMark
+ if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ @id = keys['window']
+ if keys['create']
+ @p_create = keys['create']
+ if @p_create.kind_of? Proc
+ keys['create'] = install_cmd(proc{@id = @p_create.call; @id.path})
+ end
+ end
+ tk_call @t.path, 'window', 'create', @index, *hash_kv(keys)
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call @t.path, 'window', 'cget', @index, "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ @id = slot['window'] if slot['window']
+ if slot['create']
+ self.create=value
+ slot['create']=nil
+ end
+ if slot.size > 0
+ tk_call @t.path, 'window', 'configure', @index, *hash_kv(slot)
+ end
+ else
+ @id = value if slot == 'window'
+ if slot == 'create'
+ self.create=value
+ else
+ tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value
+ end
+ end
+ end
+
+ def window
+ @id
+ end
+
+ def window=(value)
+ tk_call @t.path, 'window', 'configure', @index, '-window', value
+ @id = value
+ end
+
+ def create
+ @p_create
+ end
+
+ def create=(value)
+ @p_create = value
+ if @p_create.kind_of? Proc
+ value = install_cmd(proc{@id = @p_create.call})
+ end
+ tk_call @t.path, 'window', 'configure', @index, '-create', value
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ conf = tk_split_list(tk_call @t.path, 'window', 'configure',
+ @index, "-#{slot}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call @t.path, 'window', 'configure',
+ @index).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+end
+
+class TkTextImage<TkObject
+ def initialize(parent, index, keys)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ if index == 'end'
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ elsif index.kind_of? TkTextMark
+ if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ @id = tk_call(@t.path, 'image', 'create', @index, *hash_kv(keys))
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call @t.path, 'image', 'cget', @index, "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ tk_call @t.path, 'image', 'configure', @index, *hash_kv(slot)
+ else
+ tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
+ end
+ end
+# def configure(slot, value)
+# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
+# end
+
+ def image
+ tk_call @t.path, 'image', 'configure', @index, '-image'
+ end
+
+ def image=(value)
+ tk_call @t.path, 'image', 'configure', @index, '-image', value
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ conf = tk_split_list(tk_call @t.path, 'image', 'configure',
+ @index, "-#{slot}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call @t.path, 'image', 'configure',
+ @index).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+end
diff --git a/ext/tk/lib/tkvirtevent.rb b/ext/tk/lib/tkvirtevent.rb
new file mode 100644
index 0000000000..0d100c2186
--- /dev/null
+++ b/ext/tk/lib/tkvirtevent.rb
@@ -0,0 +1,66 @@
+#
+# tkvirtevent.rb : treats virtual events
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkVirtualEvent<TkObject
+ extend Tk
+
+ TkVirturlEventID = [0]
+ TkVirturlEventTBL = {}
+
+ def TkVirtualEvent.getobj(event)
+ obj = TkVirturlEventTBL[event]
+ obj ? obj : event
+ end
+
+ def TkVirtualEvent.info
+ tk_call('event', 'info').split(/\s+/).filter{|seq|
+ TkVirtualEvent.getobj(seq[1..-2])
+ }
+ end
+
+ def initialize(*sequences)
+ @path = @id = format("<VirtEvent%.4d>", TkVirturlEventID[0])
+ TkVirturlEventID[0] += 1
+ add(*sequences)
+ end
+
+ def add(*sequences)
+ if sequences != []
+ tk_call('event', 'add', "<#{@id}>",
+ *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
+ TkVirturlEventTBL[@id] = self
+ end
+ self
+ end
+
+ def delete(*sequences)
+ if sequences == []
+ tk_call('event', 'delete', "<#{@id}>")
+ TkVirturlEventTBL[@id] = nil
+ else
+ tk_call('event', 'delete', "<#{@id}>",
+ *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
+ TkVirturlEventTBL[@id] = nil if info == []
+ end
+ self
+ end
+
+ def info
+ tk_call('event', 'info', "<#{@id}>").split(/\s+/).filter{|seq|
+ l = seq.scan(/<*[^<>]+>*/).filter{|subseq|
+ case (subseq)
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(subseq[1..-2])
+ when /^<[^<>]+>$/
+ subseq[1..-2]
+ else
+ subseq.split('')
+ end
+ }.flatten
+ (l.size == 1) ? l[0] : l
+ }
+ end
+end
diff --git a/ext/tk/sample/tkbiff.rb b/ext/tk/sample/tkbiff.rb
new file mode 100644
index 0000000000..d2d7bf7beb
--- /dev/null
+++ b/ext/tk/sample/tkbiff.rb
@@ -0,0 +1,149 @@
+#! /usr/local/bin/ruby
+
+if ARGV[0] != '-d'
+ unless $DEBUG
+ exit if fork
+ end
+else
+ ARGV.shift
+end
+
+if ARGV.length == 0
+ if ENV['MAIL']
+ $spool = ENV['MAIL']
+ else
+ $spool = '/usr/spool/mail/' + ENV['USER']
+ end
+else
+ $spool = ARGV[0]
+end
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.kind_of?(IO)
+ f = open(f, "r")
+ me = super
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ next if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+require "tkscrollbox"
+
+$top = TkRoot.new
+$top.withdraw
+$list = TkScrollbox.new($top) {
+ relief 'raised'
+ width 80
+ height 8
+ setgrid 'yes'
+ pack
+}
+TkButton.new($top) {
+ text 'Dismiss'
+ command proc {$top.withdraw}
+ pack('fill'=>'both','expand'=>'yes')
+}
+$top.bind "Control-c", proc{exit}
+$top.bind "Control-q", proc{exit}
+$top.bind "space", proc{exit}
+
+$spool_size = 0
+$check_time = Time.now
+
+def check
+ $check_time = Time.now
+ size = File.size($spool)
+ if size and size != $spool_size
+ $spool_size = size
+ pop_up if size > 0
+ end
+ Tk.after 5000, proc{check}
+end
+
+if defined? Thread
+ Thread.start do
+ loop do
+ sleep 600
+ if Time.now - $check_time > 200
+ Tk.after 5000, proc{check}
+ end
+ end
+ end
+end
+
+def pop_up
+ outcount = 0;
+ $list.delete 0, 'end'
+ f = open($spool, "r")
+ while !f.eof?
+ mail = Mail.new(f)
+ date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject']
+ next if !date
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" if ! from
+ subj = "(nil)" if ! subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ $list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ outcount += 1
+ end
+ f.close
+ if outcount == 0
+ $list.insert 'end', "You have no mail."
+ else
+ $list.see 'end'
+ end
+ $top.deiconify
+ Tk.after 2000, proc{$top.withdraw}
+end
+
+$list.insert 'end', "You have no mail."
+check
+Tk.after 2000, proc{$top.withdraw}
+begin
+ Tk.mainloop
+rescue
+ `echo #$! > /tmp/tkbiff`
+end
diff --git a/ext/tk/sample/tkbrowse.rb b/ext/tk/sample/tkbrowse.rb
new file mode 100644
index 0000000000..882f0a489b
--- /dev/null
+++ b/ext/tk/sample/tkbrowse.rb
@@ -0,0 +1,79 @@
+#!/usr/local/bin/ruby
+#
+# This script generates a directory browser, which lists the working
+# directory and allows you to open files or subdirectories by
+# double-clicking.
+
+# Create a scrollbar on the right side of the main window and a listbox
+# on the left side.
+
+require "tkscrollbox"
+
+# The procedure below is invoked to open a browser on a given file; if the
+# file is a directory then another instance of this program is invoked; if
+# the file is a regular file then the Mx editor is invoked to display
+# the file.
+
+$dirlist = {}
+
+def browsedir (dir)
+ if $dirlist.key? dir
+ $dirlist[dir]
+ else
+ top = if $dirlist.size > 0 then TkToplevel.new else nil end
+ list = TkScrollbox.new(top) {
+ relief 'raised'
+ width 20
+ height 20
+ setgrid 'yes'
+ pack
+ }
+ list.insert 'end', *`ls #{dir}`.split
+
+ # Set up bindings for the browser.
+
+ list.focus
+ list.bind "Control-q", proc{exit}
+ list.bind "Control-c", proc{exit}
+ list.bind "Control-p", proc{
+ print "selection <", TkSelection.get, ">\n"
+ }
+
+ list.bind "Double-Button-1", proc{
+ for i in TkSelection.get.split
+ print "clicked ", i, "\n"
+ browse dir, i
+ end
+ }
+ $dirlist[dir] = list
+ end
+end
+
+def browse (dir, file)
+ file="#{dir}/#{file}"
+ if File.directory? file
+ browsedir(file)
+ else
+ if File.file? file
+ if ENV['EDITOR']
+ system format("%s %s&", ENV['EDITOR'], file)
+ else
+ system "xedit #{file}&"
+ end
+ else
+ STDERR.print "\"#{file}\" isn't a directory or regular file"
+ end
+ end
+end
+
+# Fill the listbox with a list of all the files in the directory (run
+# the "ls" command to get that information).
+
+if ARGV.length>0
+ dir = ARGV[0]
+else
+ dir="."
+end
+
+browsedir(dir)
+Tk.mainloop
diff --git a/ext/tk/sample/tkdialog.rb b/ext/tk/sample/tkdialog.rb
new file mode 100644
index 0000000000..e83e16d0a8
--- /dev/null
+++ b/ext/tk/sample/tkdialog.rb
@@ -0,0 +1,62 @@
+#! /usr/local/bin/ruby
+require "tk"
+
+root = TkFrame.new
+top = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+msg = TkMessage.new(top) {
+ text "File main.c hasn't been saved to disk since \
+it was last modified. What should I do?"
+ justify 'center'
+ aspect 200
+ font '-Adobe-helvetica-medium-r-normal--*-240*'
+ pack('padx'=>5, 'pady'=>5, 'expand'=>'yes')
+}
+top.pack('fill'=>'both')
+root.pack
+
+bot = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+
+TkFrame.new(bot) { |left|
+ relief 'sunken'
+ border 1
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10, 'pady'=> 10)
+ TkButton.new(left) {
+ text "Save File"
+ command "quit 'save'"
+ pack('expand'=>'yes','padx'=>6,'pady'=> 6)
+ top.bind "Enter", proc{state 'active'}
+ msg.bind "Enter", proc{state 'active'}
+ bot.bind "Enter", proc{state 'active'}
+ top.bind "Leave", proc{state 'normal'}
+ msg.bind "Leave", proc{state 'normal'}
+ bot.bind "Leave", proc{state 'normal'}
+ Tk.root.bind "ButtonRelease-1", proc{quit 'save'}
+ Tk.root.bind "Return", proc{quit 'save'}
+ }
+}
+TkButton.new(bot) {
+ text "Quit Anyway"
+ command "quit 'quit'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+TkButton.new(bot) {
+ text "Return To Editor"
+ command "quit 'return'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+bot.pack
+root.pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
+
+def quit(button)
+ print "aaa\n"
+ print "You pressed the \"#{button}\" button; bye-bye!\n"
+ exit
+end
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkfrom.rb b/ext/tk/sample/tkfrom.rb
new file mode 100644
index 0000000000..ba0e547799
--- /dev/null
+++ b/ext/tk/sample/tkfrom.rb
@@ -0,0 +1,132 @@
+#! /usr/local/bin/ruby
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.kind_of?(IO)
+ f = open(f, "r")
+ me = super(f)
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ next if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+if ARGV.length == 0
+ if ENV['MAIL']
+ ARGV[0] = ENV['MAIL']
+ elsif ENV['USER']
+ ARGV[0] = '/usr/spool/mail/' + ENV['USER']
+ elsif ENV['LOGNAME']
+ ARGV[0] = '/usr/spool/mail/' + ENV['LOGNAME']
+ end
+end
+
+require "tk"
+list = scroll = nil
+TkFrame.new{|f|
+ list = TkListbox.new(f) {
+ yscroll proc{|idx|
+ scroll.set *idx
+ }
+ relief 'raised'
+# geometry "80x5"
+ width 80
+ height 5
+ setgrid 'yes'
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+ }
+ scroll = TkScrollbar.new(f) {
+ command proc{|idx|
+ list.yview *idx
+ }
+ pack('side'=>'right','fill'=>'y')
+ }
+ pack
+}
+root = Tk.root
+TkButton.new(root) {
+ text 'Dismiss'
+ command proc {exit}
+ pack('fill'=>'both','expand'=>'yes')
+}
+root.bind "Control-c", proc{exit}
+root.bind "Control-q", proc{exit}
+root.bind "space", proc{exit}
+
+$outcount = 0;
+for file in ARGV
+ next if File.exist?(file)
+ atime = File.atime(file)
+ mtime = File.mtime(file)
+ f = open(file, "r")
+ begin
+ until f.eof
+ mail = Mail.new(f)
+ date = mail.header['Date']
+ next unless date
+ from = mail.header['From']
+ subj = mail.header['Subject']
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" unless from
+ subj = "(nil)" unless subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ $outcount += 1
+ end
+ ensure
+ f.close
+ File.utime(atime, mtime, file)
+ list.see 'end'
+ end
+end
+
+limit = 10000
+if $outcount == 0
+ list.insert 'end', "You have no mail."
+ limit = 2000
+end
+Tk.after limit, proc{
+ exit
+}
+Tk.mainloop
diff --git a/ext/tk/sample/tkhello.rb b/ext/tk/sample/tkhello.rb
new file mode 100644
index 0000000000..5188fe1c8c
--- /dev/null
+++ b/ext/tk/sample/tkhello.rb
@@ -0,0 +1,10 @@
+require "tk"
+
+TkButton.new(nil,
+ 'text' => 'hello',
+ 'command' => proc{print "hello\n"}).pack('fill'=>'x')
+TkButton.new(nil,
+ 'text' => 'quit',
+ 'command' => 'exit').pack('fill'=>'x')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkline.rb b/ext/tk/sample/tkline.rb
new file mode 100644
index 0000000000..2406b0749f
--- /dev/null
+++ b/ext/tk/sample/tkline.rb
@@ -0,0 +1,45 @@
+
+require "tkclass"
+
+$tkline_init = FALSE
+def start_random
+ return if $tkline_init
+ $tkline_init = TRUE
+ if defined? Thread
+ Thread.start do
+ loop do
+ sleep 2
+ Line.new($c, rand(400), rand(200), rand(400), rand(200))
+ end
+ end
+ end
+end
+
+$c = Canvas.new
+$c.pack
+$start_x = start_y = 0
+
+def do_press(x, y)
+ $start_x = x
+ $start_y = y
+ $current_line = Line.new($c, x, y, x, y)
+ start_random
+end
+def do_motion(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ end
+end
+
+def do_release(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ $current_line.fill 'black'
+ $current_line = nil
+ end
+end
+
+$c.bind("1", proc{|e| do_press e.x, e.y})
+$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
+$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
+Tk.mainloop
diff --git a/ext/tk/sample/tktimer.rb b/ext/tk/sample/tktimer.rb
new file mode 100644
index 0000000000..34377e2f39
--- /dev/null
+++ b/ext/tk/sample/tktimer.rb
@@ -0,0 +1,50 @@
+#!/usr/local/bin/ruby
+# This script generates a counter with start and stop buttons.
+
+require "tk"
+$label = TkLabel.new {
+ text '0.00'
+ relief 'raised'
+ width 10
+ pack('side'=>'bottom', 'fill'=>'both')
+}
+
+TkButton.new {
+ text 'Start'
+ command proc {
+ if $stopped
+ $stopped = FALSE
+ tick
+ end
+ }
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+}
+TkButton.new {
+ text 'Stop'
+ command proc{
+ exit if $stopped
+ $stopped = TRUE
+ }
+ pack('side'=>'right','fill'=>'both','expand'=>'yes')
+}
+
+$seconds=0
+$hundredths=0
+$stopped=TRUE
+
+def tick
+ if $stopped then return end
+ Tk.after 50, proc{tick}
+ $hundredths+=5
+ if $hundredths >= 100
+ $hundredths=0
+ $seconds+=1
+ end
+ $label.text format("%d.%02d", $seconds, $hundredths)
+end
+
+root = Tk.root
+root.bind "Control-c", proc{root.destroy}
+root.bind "Control-q", proc{root.destroy}
+Tk.root.focus
+Tk.mainloop
diff --git a/ext/tk/tkutil.c b/ext/tk/tkutil.c
new file mode 100644
index 0000000000..e93733bb67
--- /dev/null
+++ b/ext/tk/tkutil.c
@@ -0,0 +1,45 @@
+/************************************************
+
+ tk.c -
+
+ $Author$
+ $Date$
+ created at: Fri Nov 3 00:47:54 JST 1995
+
+************************************************/
+
+#include "ruby.h"
+
+static VALUE
+tk_eval_cmd(argc, argv)
+ int argc;
+ VALUE argv[];
+{
+ VALUE cmd, rest;
+
+ rb_scan_args(argc, argv, "1*", &cmd, &rest);
+ return rb_eval_cmd(cmd, rest);
+}
+
+static VALUE
+tk_s_new(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ VALUE obj = rb_obj_alloc(class);
+
+ rb_funcall2(obj, rb_intern("initialize"), argc, argv);
+ if (rb_iterator_p()) rb_obj_instance_eval(0, 0, obj);
+ return obj;
+}
+
+Init_tkutil()
+{
+ VALUE mTK = rb_define_module("TkUtil");
+ VALUE cTK = rb_define_class("TkKernel", rb_cObject);
+
+ rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1);
+
+ rb_define_singleton_method(cTK, "new", tk_s_new, -1);
+}
diff --git a/file.c b/file.c
index b60ec65d55..11a8dedf14 100644
--- a/file.c
+++ b/file.c
@@ -6,12 +6,17 @@
$Date$
created at: Mon Nov 15 12:24:34 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
+#ifdef NT
+#include "missing/file.h"
+#endif
+
#include "ruby.h"
-#include "io.h"
+#include "rubyio.h"
+#include "rubysig.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -43,44 +48,44 @@ struct timeval {
#endif
#ifndef HAVE_STRING_H
-char *strrchr();
+char *strrchr _((char*,char));
#endif
+#include <sys/types.h>
#include <sys/stat.h>
-#ifndef NT
-char *strdup();
-char *getenv();
+#ifdef USE_CWGUSI
+ #include "macruby_missing.h"
+ extern int fileno(FILE *stream);
+ extern int utimes();
#endif
-extern VALUE cIO;
-VALUE cFile;
-VALUE mFileTest;
+VALUE rb_cFile;
+VALUE rb_mFileTest;
static VALUE sStat;
-VALUE time_new();
-
VALUE
-file_open(fname, mode)
+rb_file_open(fname, mode)
char *fname, *mode;
{
OpenFile *fptr;
NEWOBJ(port, struct RFile);
- OBJSETUP(port, cFile, T_FILE);
+ OBJSETUP(port, rb_cFile, T_FILE);
MakeOpenFile(port, fptr);
- fptr->mode = io_mode_flags(mode);
+ fptr->mode = rb_io_mode_flags(mode);
fptr->f = rb_fopen(fname, mode);
fptr->path = strdup(fname);
+ rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
static VALUE
-file_s_open(argc, argv, class)
+rb_file_s_open(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
VALUE fname, vmode, file;
char *mode;
@@ -88,24 +93,24 @@ file_s_open(argc, argv, class)
rb_scan_args(argc, argv, "11", &fname, &vmode);
Check_SafeStr(fname);
if (!NIL_P(vmode)) {
- Check_Type(vmode, T_STRING);
- mode = RSTRING(vmode)->ptr;
+ mode = STR2CSTR(vmode);
}
else {
mode = "r";
}
- file = file_open(RSTRING(fname)->ptr, mode);
+ file = rb_file_open(RSTRING(fname)->ptr, mode);
- RBASIC(file)->class = class;
- if (iterator_p()) {
- rb_ensure(rb_yield, file, io_close, file);
+ RBASIC(file)->klass = klass;
+ rb_obj_call_init(file);
+ if (rb_iterator_p()) {
+ return rb_ensure(rb_yield, file, rb_io_close, file);
}
return file;
}
static VALUE
-file_reopen(argc, argv, file)
+rb_file_reopen(argc, argv, file)
int argc;
VALUE *argv;
VALUE file;
@@ -114,16 +119,16 @@ file_reopen(argc, argv, file)
char *mode;
OpenFile *fptr;
+ rb_secure(4);
if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
if (TYPE(fname) == T_FILE) { /* fname must be IO */
- return io_reopen(file, fname);
+ return rb_io_reopen(file, fname);
}
}
Check_SafeStr(fname);
if (!NIL_P(nmode)) {
- Check_Type(nmode, T_STRING);
- mode = RSTRING(nmode)->ptr;
+ mode = STR2CSTR(nmode);
}
else {
mode = "r";
@@ -132,12 +137,11 @@ file_reopen(argc, argv, file)
GetOpenFile(file, fptr);
if (fptr->path) free(fptr->path);
fptr->path = strdup(RSTRING(fname)->ptr);
- fptr->mode = io_mode_flags(mode);
+ fptr->mode = rb_io_mode_flags(mode);
if (!fptr->f) {
fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
if (fptr->f2) {
- if (fileno(fptr->f2) < 3) /* need to keep stdio */
- fclose(fptr->f2);
+ fclose(fptr->f2);
fptr->f2 = NULL;
}
return file;
@@ -179,95 +183,20 @@ apply2files(func, vargs, arg)
}
static VALUE
-file_tell(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- long pos;
-
- GetOpenFile(obj, fptr);
-
- pos = ftell(fptr->f);
- if (ferror(fptr->f) != 0) rb_sys_fail(0);
-
- return int2inum(pos);
-}
-
-static VALUE
-file_seek(obj, offset, ptrname)
- VALUE obj, offset, ptrname;
-{
- OpenFile *fptr;
- long pos;
-
- GetOpenFile(obj, fptr);
-
- pos = fseek(fptr->f, NUM2INT(offset), NUM2INT(ptrname));
- if (pos != 0) rb_sys_fail(0);
- clearerr(fptr->f);
-
- return obj;
-}
-
-static VALUE
-file_set_pos(obj, offset)
- VALUE obj, offset;
-{
- OpenFile *fptr;
- long pos;
-
- GetOpenFile(obj, fptr);
- pos = fseek(fptr->f, NUM2INT(offset), 0);
- if (pos != 0) rb_sys_fail(0);
- clearerr(fptr->f);
-
- return obj;
-}
-
-static VALUE
-file_rewind(obj)
- VALUE obj;
-{
- OpenFile *fptr;
-
- GetOpenFile(obj, fptr);
- if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(0);
- clearerr(fptr->f);
-
- return obj;
-}
-
-static VALUE
-file_eof(obj)
+rb_file_path(obj)
VALUE obj;
{
OpenFile *fptr;
GetOpenFile(obj, fptr);
- if (feof(fptr->f) == 0) return FALSE;
- return TRUE;
+ if (fptr->path == NULL) return Qnil;
+ return rb_str_new2(fptr->path);
}
-static VALUE
-file_path(obj)
- VALUE obj;
-{
- OpenFile *fptr;
-
- GetOpenFile(obj, fptr);
- return str_new2(fptr->path);
-}
-
-static VALUE
-file_isatty(obj)
- VALUE obj;
-{
- return FALSE;
-}
-
-#include <sys/types.h>
#ifndef NT
-#include <sys/file.h>
+# ifndef USE_CWGUSI
+# include <sys/file.h>
+# endif
#else
#include "missing/file.h"
#endif
@@ -276,37 +205,53 @@ static VALUE
stat_new(st)
struct stat *st;
{
- if (!st) Bug("stat_new() called with bad value");
- return struct_new(sStat,
- INT2FIX((int)st->st_dev),
- INT2FIX((int)st->st_ino),
- INT2FIX((int)st->st_mode),
- INT2FIX((int)st->st_nlink),
- INT2FIX((int)st->st_uid),
- INT2FIX((int)st->st_gid),
+ if (!st) rb_bug("stat_new() called with bad value");
+ return rb_struct_new(sStat,
+ INT2FIX((int)st->st_dev),
+ INT2FIX((int)st->st_ino),
+ INT2FIX((int)st->st_mode),
+ INT2FIX((int)st->st_nlink),
+ INT2FIX((int)st->st_uid),
+ INT2FIX((int)st->st_gid),
#ifdef HAVE_ST_RDEV
- INT2FIX((int)st->st_rdev),
+ INT2FIX((int)st->st_rdev),
#else
- INT2FIX(0),
+ INT2FIX(0),
#endif
- INT2FIX((int)st->st_size),
+ INT2FIX((int)st->st_size),
#ifdef HAVE_ST_BLKSIZE
- INT2FIX((int)st->st_blksize),
+ INT2FIX((int)st->st_blksize),
#else
- INT2FIX(0),
+ INT2FIX(0),
#endif
#ifdef HAVE_ST_BLOCKS
- INT2FIX((int)st->st_blocks),
+ INT2FIX((int)st->st_blocks),
#else
- INT2FIX(0),
+ INT2FIX(0),
#endif
- time_new(st->st_atime, 0),
- time_new(st->st_mtime, 0),
- time_new(st->st_ctime, 0));
+ rb_time_new(st->st_atime, 0),
+ rb_time_new(st->st_mtime, 0),
+ rb_time_new(st->st_ctime, 0));
+}
+
+static int
+rb_stat(file, st)
+ VALUE file;
+ struct stat *st;
+{
+ if (TYPE(file) == T_FILE) {
+ OpenFile *fptr;
+
+ rb_secure(4);
+ GetOpenFile(file, fptr);
+ return fstat(fileno(fptr->f), st);
+ }
+ Check_SafeStr(file);
+ return stat(RSTRING(file)->ptr, st);
}
static VALUE
-file_s_stat(obj, fname)
+rb_file_s_stat(obj, fname)
VALUE obj, fname;
{
struct stat st;
@@ -319,7 +264,7 @@ file_s_stat(obj, fname)
}
static VALUE
-file_stat(obj)
+rb_io_stat(obj)
VALUE obj;
{
OpenFile *fptr;
@@ -333,7 +278,7 @@ file_stat(obj)
}
static VALUE
-file_s_lstat(obj, fname)
+rb_file_s_lstat(obj, fname)
VALUE obj, fname;
{
#if !defined(MSDOS) && !defined(NT)
@@ -345,25 +290,28 @@ file_s_lstat(obj, fname)
}
return stat_new(&st);
#else
- rb_notimplement();
+ rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
static VALUE
-file_lstat(obj)
+rb_file_lstat(obj)
VALUE obj;
{
#if !defined(MSDOS) && !defined(NT)
OpenFile *fptr;
struct stat st;
+ rb_secure(4);
GetOpenFile(obj, fptr);
if (lstat(fptr->path, &st) == -1) {
rb_sys_fail(fptr->path);
}
return stat_new(&st);
#else
- rb_notimplement();
+ rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
@@ -371,9 +319,9 @@ static int
group_member(gid)
GETGROUPS_T gid;
{
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
if (getgid() == gid || getegid() == gid)
- return TRUE;
+ return Qtrue;
# ifdef HAVE_GETGROUPS
# ifndef NGROUPS
@@ -386,11 +334,11 @@ group_member(gid)
anum = getgroups(NGROUPS, gary);
while (--anum >= 0)
if (gary[anum] == gid)
- return TRUE;
+ return Qtrue;
}
# endif
#endif
- return FALSE;
+ return Qfalse;
}
#ifndef S_IXUGO
@@ -446,10 +394,9 @@ test_d(obj, fname)
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISDIR(st.st_mode)) return TRUE;
- return FALSE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISDIR(st.st_mode)) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -463,12 +410,11 @@ test_p(obj, fname)
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISFIFO(st.st_mode)) return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISFIFO(st.st_mode)) return Qtrue;
#endif
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -493,11 +439,11 @@ test_l(obj, fname)
struct stat st;
Check_SafeStr(fname);
- if (lstat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISLNK(st.st_mode)) return TRUE;
+ if (lstat(RSTRING(fname)->ptr, &st) < 0) return Qfalse;
+ if (S_ISLNK(st.st_mode)) return Qtrue;
#endif
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -521,12 +467,11 @@ test_S(obj, fname)
#ifdef S_ISSOCK
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISSOCK(st.st_mode)) return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISSOCK(st.st_mode)) return Qtrue;
#endif
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -544,12 +489,11 @@ test_b(obj, fname)
#ifdef S_ISBLK
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISBLK(st.st_mode)) return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISBLK(st.st_mode)) return Qtrue;
#endif
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -562,11 +506,10 @@ test_c(obj, fname)
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISBLK(st.st_mode)) return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISBLK(st.st_mode)) return Qtrue;
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -575,9 +518,8 @@ test_e(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -585,8 +527,8 @@ test_r(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (eaccess(RSTRING(fname)->ptr, R_OK) < 0) return FALSE;
- return TRUE;
+ if (eaccess(RSTRING(fname)->ptr, R_OK) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -594,8 +536,8 @@ test_R(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (access(RSTRING(fname)->ptr, R_OK) < 0) return FALSE;
- return TRUE;
+ if (access(RSTRING(fname)->ptr, R_OK) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -603,8 +545,8 @@ test_w(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (eaccess(RSTRING(fname)->ptr, W_OK) < 0) return FALSE;
- return TRUE;
+ if (eaccess(RSTRING(fname)->ptr, W_OK) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -612,8 +554,8 @@ test_W(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (access(RSTRING(fname)->ptr, W_OK) < 0) return FALSE;
- return TRUE;
+ if (access(RSTRING(fname)->ptr, W_OK) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -621,8 +563,8 @@ test_x(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (eaccess(RSTRING(fname)->ptr, X_OK) < 0) return FALSE;
- return TRUE;
+ if (eaccess(RSTRING(fname)->ptr, X_OK) < 0) return Qfalse;
+ return Qtrue;
}
static VALUE
@@ -630,8 +572,8 @@ test_X(obj, fname)
VALUE obj, fname;
{
Check_SafeStr(fname);
- if (access(RSTRING(fname)->ptr, X_OK) < 0) return FALSE;
- return TRUE;
+ if (access(RSTRING(fname)->ptr, X_OK) < 0) return Qfalse;
+ return Qtrue;
}
#ifndef S_ISREG
@@ -644,10 +586,9 @@ test_f(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (S_ISREG(st.st_mode)) return TRUE;
- return FALSE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (S_ISREG(st.st_mode)) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -656,10 +597,9 @@ test_z(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (st.st_size == 0) return TRUE;
- return FALSE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (st.st_size == 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -668,10 +608,9 @@ test_s(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (st.st_size == 0) return FALSE;
- return int2inum(st.st_size);
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (st.st_size == 0) return Qfalse;
+ return rb_int2inum(st.st_size);
}
static VALUE
@@ -680,10 +619,9 @@ test_owned(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (st.st_uid == geteuid()) return TRUE;
- return FALSE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (st.st_uid == geteuid()) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -692,10 +630,9 @@ test_rowned(obj, fname)
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (st.st_uid == getuid()) return TRUE;
- return FALSE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (st.st_uid == getuid()) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -705,11 +642,10 @@ test_grpowned(obj, fname)
#ifndef NT
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE;
- if (st.st_gid == getegid()) return TRUE;
+ if (rb_stat(fname, &st) < 0) return Qfalse;
+ if (st.st_gid == getegid()) return Qtrue;
#endif
- return FALSE;
+ return Qfalse;
}
#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
@@ -720,9 +656,9 @@ check3rdbyte(file, mode)
{
struct stat st;
- if (stat(file, &st) < 0) return FALSE;
- if (st.st_mode & mode) return TRUE;
- return FALSE;
+ if (stat(file, &st) < 0) return Qfalse;
+ if (st.st_mode & mode) return Qtrue;
+ return Qfalse;
}
#endif
@@ -734,7 +670,7 @@ test_suid(obj, fname)
Check_SafeStr(fname);
return check3rdbyte(RSTRING(fname)->ptr, S_ISUID);
#else
- return FALSE;
+ return Qfalse;
#endif
}
@@ -746,7 +682,7 @@ test_sgid(obj, fname)
Check_SafeStr(fname);
return check3rdbyte(RSTRING(fname)->ptr, S_ISGID);
#else
- return FALSE;
+ return Qfalse;
#endif
}
@@ -754,36 +690,40 @@ static VALUE
test_sticky(obj, fname)
VALUE obj, fname;
{
- Check_Type(fname, T_STRING);
#ifdef S_ISVTX
- return check3rdbyte(RSTRING(fname)->ptr, S_ISVTX);
+ return check3rdbyte(STR2CSTR(fname), S_ISVTX);
#else
- return FALSE;
+ return Qfalse;
#endif
}
static VALUE
-file_s_size(obj, fname)
+rb_file_s_size(obj, fname)
VALUE obj, fname;
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0)
+ if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING(fname)->ptr);
- return int2inum(st.st_size);
+ return rb_int2inum(st.st_size);
}
static VALUE
-file_s_ftype(obj, fname)
+rb_file_s_ftype(obj, fname)
VALUE obj, fname;
{
struct stat st;
char *t;
+#if defined(MSDOS) || defined(NT)
+ if (rb_stat(fname, &st) < 0)
+ rb_sys_fail(RSTRING(fname)->ptr);
+#else
Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0)
+ if (lstat(RSTRING(fname)->ptr, &st) == -1) {
rb_sys_fail(RSTRING(fname)->ptr);
+ }
+#endif
if (S_ISREG(st.st_mode)) {
t = "file";
@@ -816,23 +756,22 @@ file_s_ftype(obj, fname)
t = "unknown";
}
- return str_new2(t);
+ return rb_str_new2(t);
}
static VALUE
-file_s_atime(obj, fname)
+rb_file_s_atime(obj, fname)
VALUE obj, fname;
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0)
+ if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING(fname)->ptr);
- return time_new(st.st_atime, 0);
+ return rb_time_new(st.st_atime, 0);
}
static VALUE
-file_atime(obj)
+rb_file_atime(obj)
VALUE obj;
{
OpenFile *fptr;
@@ -842,23 +781,22 @@ file_atime(obj)
if (fstat(fileno(fptr->f), &st) == -1) {
rb_sys_fail(fptr->path);
}
- return time_new(st.st_atime, 0);
+ return rb_time_new(st.st_atime, 0);
}
static VALUE
-file_s_mtime(obj, fname)
+rb_file_s_mtime(obj, fname)
VALUE obj, fname;
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0)
+ if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING(fname)->ptr);
- return time_new(st.st_mtime, 0);
+ return rb_time_new(st.st_mtime, 0);
}
static VALUE
-file_mtime(obj)
+rb_file_mtime(obj)
VALUE obj;
{
OpenFile *fptr;
@@ -868,23 +806,22 @@ file_mtime(obj)
if (fstat(fileno(fptr->f), &st) == -1) {
rb_sys_fail(fptr->path);
}
- return time_new(st.st_mtime, 0);
+ return rb_time_new(st.st_mtime, 0);
}
static VALUE
-file_s_ctime(obj, fname)
+rb_file_s_ctime(obj, fname)
VALUE obj, fname;
{
struct stat st;
- Check_SafeStr(fname);
- if (stat(RSTRING(fname)->ptr, &st) < 0)
+ if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING(fname)->ptr);
- return time_new(st.st_ctime, 0);
+ return rb_time_new(st.st_ctime, 0);
}
static VALUE
-file_ctime(obj)
+rb_file_ctime(obj)
VALUE obj;
{
OpenFile *fptr;
@@ -894,7 +831,7 @@ file_ctime(obj)
if (fstat(fileno(fptr->f), &st) == -1) {
rb_sys_fail(fptr->path);
}
- return time_new(st.st_ctime, 0);
+ return rb_time_new(st.st_ctime, 0);
}
static void
@@ -907,7 +844,7 @@ chmod_internal(path, mode)
}
static VALUE
-file_s_chmod(argc, argv)
+rb_file_s_chmod(argc, argv)
int argc;
VALUE *argv;
{
@@ -923,17 +860,17 @@ file_s_chmod(argc, argv)
}
static VALUE
-file_chmod(obj, vmode)
+rb_file_chmod(obj, vmode)
VALUE obj, vmode;
{
OpenFile *fptr;
int mode;
- rb_secure(2);
+ rb_secure(4);
mode = NUM2INT(vmode);
GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT)
+#if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__)
if (chmod(fptr->path, mode) == -1)
rb_sys_fail(fptr->path);
#else
@@ -958,7 +895,7 @@ chown_internal(path, args)
}
static VALUE
-file_s_chown(argc, argv)
+rb_file_s_chown(argc, argv)
int argc;
VALUE *argv;
{
@@ -985,14 +922,14 @@ file_s_chown(argc, argv)
}
static VALUE
-file_chown(obj, owner, group)
+rb_file_chown(obj, owner, group)
VALUE obj, owner, group;
{
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT)
+#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI)
if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
rb_sys_fail(fptr->path);
#else
@@ -1003,7 +940,7 @@ file_chown(obj, owner, group)
return INT2FIX(0);
}
-struct timeval time_timeval();
+struct timeval rb_time_timeval();
#ifdef HAVE_UTIMES
@@ -1017,7 +954,7 @@ utime_internal(path, tvp)
}
static VALUE
-file_s_utime(argc, argv)
+rb_file_s_utime(argc, argv)
int argc;
VALUE *argv;
{
@@ -1027,8 +964,8 @@ file_s_utime(argc, argv)
rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
- tvp[0] = time_timeval(atime);
- tvp[1] = time_timeval(mtime);
+ tvp[0] = rb_time_timeval(atime);
+ tvp[1] = rb_time_timeval(mtime);
n = apply2files(utime_internal, rest, tvp);
return INT2FIX(n);
@@ -1038,8 +975,14 @@ file_s_utime(argc, argv)
#ifndef HAVE_UTIME_H
# ifdef NT
+# if defined(__BORLANDC__)
+# include <utime.h>
+# else
# include <sys/utime.h>
+# endif
+# if defined(_MSC_VER)
# define utimbuf _utimbuf
+# endif
# else
struct utimbuf {
long actime;
@@ -1058,7 +1001,7 @@ utime_internal(path, utp)
}
static VALUE
-file_s_utime(argc, argv)
+rb_file_s_utime(argc, argv)
int argc;
VALUE *argv;
{
@@ -1069,9 +1012,9 @@ file_s_utime(argc, argv)
rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
- tv = time_timeval(atime);
+ tv = rb_time_timeval(atime);
utbuf.actime = tv.tv_sec;
- tv = time_timeval(mtime);
+ tv = rb_time_timeval(mtime);
utbuf.modtime = tv.tv_sec;
n = apply2files(utime_internal, rest, &utbuf);
@@ -1081,19 +1024,23 @@ file_s_utime(argc, argv)
#endif
static VALUE
-file_s_link(obj, from, to)
+rb_file_s_link(obj, from, to)
VALUE obj, from, to;
{
+#if defined(USE_CWGUSI)
+ rb_notimplement();
+#else
Check_SafeStr(from);
Check_SafeStr(to);
if (link(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0)
rb_sys_fail(RSTRING(from)->ptr);
return INT2FIX(0);
+#endif /* USE_CWGUSI */
}
static VALUE
-file_s_symlink(obj, from, to)
+rb_file_s_symlink(obj, from, to)
VALUE obj, from, to;
{
#if !defined(MSDOS) && !defined(NT)
@@ -1102,14 +1049,15 @@ file_s_symlink(obj, from, to)
if (symlink(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0)
rb_sys_fail(RSTRING(from)->ptr);
- return TRUE;
+ return INT2FIX(0);
#else
- rb_notimplement();
+ rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
static VALUE
-file_s_readlink(obj, path)
+rb_file_s_readlink(obj, path)
VALUE obj, path;
{
#if !defined(MSDOS) && !defined(NT)
@@ -1121,9 +1069,10 @@ file_s_readlink(obj, path)
if ((cc = readlink(RSTRING(path)->ptr, buf, MAXPATHLEN)) < 0)
rb_sys_fail(RSTRING(path)->ptr);
- return str_new(buf, cc);
+ return rb_tainted_str_new(buf, cc);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
@@ -1136,7 +1085,7 @@ unlink_internal(path)
}
static VALUE
-file_s_unlink(obj, args)
+rb_file_s_unlink(obj, args)
VALUE obj, args;
{
int n;
@@ -1146,7 +1095,7 @@ file_s_unlink(obj, args)
}
static VALUE
-file_s_rename(obj, from, to)
+rb_file_s_rename(obj, from, to)
VALUE obj, from, to;
{
Check_SafeStr(from);
@@ -1159,42 +1108,53 @@ file_s_rename(obj, from, to)
}
static VALUE
-file_s_umask(argc, argv)
+rb_file_s_umask(argc, argv)
int argc;
VALUE *argv;
{
+#ifdef USE_CWGUSI
+ rb_notimplement();
+#else
int omask = 0;
+ rb_secure(4);
if (argc == 0) {
- int omask = umask(0);
+ omask = umask(0);
umask(omask);
}
else if (argc == 1) {
omask = umask(NUM2INT(argv[0]));
}
else {
- ArgError("wrong # of argument");
+ rb_raise(rb_eArgError, "wrong # of argument");
}
return INT2FIX(omask);
+#endif /* USE_CWGUSI */
}
VALUE
-file_s_expand_path(obj, fname)
- VALUE obj, fname;
+rb_file_s_expand_path(argc, argv)
+ int argc;
+ VALUE *argv;
{
+ VALUE fname, dname;
char *s, *p;
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN+2];
- Check_Type(fname, T_STRING);
- s = RSTRING(fname)->ptr;
+ rb_scan_args(argc, argv, "11", &fname, &dname);
+ s = STR2CSTR(fname);
p = buf;
if (s[0] == '~') {
- if (s[1] == '/' || s[1] == '\0') {
+ if (s[1] == '/' ||
+#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+ s[1] == '\\' ||
+#endif
+ s[1] == '\0') {
char *dir = getenv("HOME");
if (!dir) {
- Fail("couldn't find HOME environment -- expanding `%s'", s);
+ rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `%s'", s);
}
strcpy(buf, dir);
p = &buf[strlen(buf)];
@@ -1205,7 +1165,6 @@ file_s_expand_path(obj, fname)
struct passwd *pwPtr;
s++;
#endif
-
while (*s && *s != '/') {
*p++ = *s++;
}
@@ -1214,7 +1173,7 @@ file_s_expand_path(obj, fname)
pwPtr = getpwnam(buf);
if (!pwPtr) {
endpwent();
- Fail("user %s doesn't exist", buf);
+ rb_raise(rb_eArgError, "user %s doesn't exist", buf);
}
strcpy(buf, pwPtr->pw_dir);
p = &buf[strlen(buf)];
@@ -1223,12 +1182,19 @@ file_s_expand_path(obj, fname)
}
}
else if (s[0] != '/') {
+ if (argc == 2) {
+ dname = rb_file_s_expand_path(1, &dname);
+ strcpy(buf, RSTRING(dname)->ptr);
+ }
+ else {
#ifdef HAVE_GETCWD
- getcwd(buf, MAXPATHLEN);
+ getcwd(buf, MAXPATHLEN);
#else
- getwd(buf);
+ getwd(buf);
#endif
+ }
p = &buf[strlen(buf)];
+ while (p > buf && *(p - 1) == '/') p--;
}
*p = '/';
@@ -1267,7 +1233,7 @@ file_s_expand_path(obj, fname)
if (p == buf || *p != '/') p++;
*p = '\0';
- return str_taint(str_new2(buf));
+ return rb_tainted_str_new2(buf);
}
static int
@@ -1294,67 +1260,68 @@ rmext(p, e)
}
static VALUE
-file_s_basename(argc, argv)
+rb_file_s_basename(argc, argv)
int argc;
VALUE *argv;
{
- VALUE fname, ext;
- char *p;
+ VALUE fname, fext;
+ char *name, *p, *ext;
int f;
- rb_scan_args(argc, argv, "11", &fname, &ext);
- Check_Type(fname, T_STRING);
- if (!NIL_P(ext)) Check_Type(ext, T_STRING);
- p = strrchr(RSTRING(fname)->ptr, '/');
+ if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
+ ext = STR2CSTR(fext);
+ }
+ name = STR2CSTR(fname);
+ p = strrchr(name, '/');
if (!p) {
- if (!NIL_P(ext)) {
- f = rmext(RSTRING(fname)->ptr, RSTRING(ext)->ptr);
- if (f) return str_new(RSTRING(fname)->ptr, f);
+ if (!NIL_P(fext)) {
+ f = rmext(name, ext);
+ if (f) return rb_str_new(name, f);
}
- return (VALUE)fname;
+ return fname;
}
p++; /* skip last `/' */
- if (!NIL_P(ext)) {
- f = rmext(p, RSTRING(ext)->ptr);
- if (f) return str_new(p, f);
+ if (!NIL_P(fext)) {
+ f = rmext(p, ext);
+ if (f) return rb_str_new(p, f);
}
- return str_taint(str_new2(p));
+ return rb_tainted_str_new2(p);
}
static VALUE
-file_s_dirname(obj, fname)
+rb_file_s_dirname(obj, fname)
VALUE obj, fname;
{
- UCHAR *p;
+ char *name, *p;
- Check_Type(fname, T_STRING);
- p = strrchr(RSTRING(fname)->ptr, '/');
+ name = STR2CSTR(fname);
+ p = strrchr(name, '/');
if (!p) {
- return str_new2(".");
+ return rb_str_new2(".");
}
- if (p == RSTRING(fname)->ptr)
+ if (p == name)
p++;
- return str_taint(str_new(RSTRING(fname)->ptr, p - RSTRING(fname)->ptr));
+ return rb_tainted_str_new(name, p - name);
}
static VALUE
-file_s_split(obj, path)
+rb_file_s_split(obj, path)
VALUE obj, path;
{
- return assoc_new(file_s_dirname(Qnil, path), file_s_basename(1,&path));
+ return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
}
static VALUE separator;
static VALUE
-file_s_join(obj, args)
+rb_file_s_join(obj, args)
VALUE obj, args;
{
- return ary_join(args, separator);
+ return rb_ary_join(args, separator);
}
static VALUE
-file_s_truncate(obj, path, len)
+rb_file_s_truncate(obj, path, len)
VALUE obj, path, len;
{
Check_SafeStr(path);
@@ -1386,20 +1353,19 @@ file_s_truncate(obj, path, len)
rb_notimplement();
# endif
#endif
- return TRUE;
+ return INT2FIX(0);
}
static VALUE
-file_truncate(obj, len)
+rb_file_truncate(obj, len)
VALUE obj, len;
{
OpenFile *fptr;
+ rb_secure(4);
GetOpenFile(obj, fptr);
-
- rb_secure(2);
if (!(fptr->mode & FMODE_WRITABLE)) {
- Fail("not opened for writing");
+ rb_raise(rb_eIOError, "not opened for writing");
}
#ifdef HAVE_TRUNCATE
if (ftruncate(fileno(fptr->f), NUM2INT(len)) < 0)
@@ -1412,29 +1378,71 @@ file_truncate(obj, len)
rb_notimplement();
# endif
#endif
- return TRUE;
+ 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
+
+#if defined(USE_THREAD) && defined(EWOULDBLOCK)
+static int
+rb_thread_flock(fd, op)
+ int fd, op;
+{
+ if (rb_thread_alone() || (op & LOCK_NB)) {
+ return flock(fd, op);
+ }
+ op |= LOCK_NB;
+ while (flock(fd, op) < 0) {
+ switch (errno) {
+ case EINTR: /* can be happen? */
+ case EWOULDBLOCK:
+ rb_thread_schedule(); /* busy wait */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
}
+#define flock rb_thread_flock
+#endif
static VALUE
-file_flock(obj, operation)
+rb_file_flock(obj, operation)
VALUE obj;
VALUE operation;
{
+#ifdef USE_CWGUSI
+ rb_notimplement();
+#else
OpenFile *fptr;
+ rb_secure(4);
GetOpenFile(obj, fptr);
- rb_secure(2);
if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) {
#ifdef EWOULDBLOCK
if (errno == EWOULDBLOCK) {
- return FALSE;
+ return Qfalse;
}
#endif
rb_sys_fail(fptr->path);
}
- return obj;
+ return INT2FIX(0);
+#endif /* USE_CWGUSI */
}
+#undef flock
static void
test_check(n, argc, argv)
@@ -1444,29 +1452,33 @@ test_check(n, argc, argv)
int i;
n+=1;
- if (n < argc) ArgError("Wrong # of arguments(%d for %d)", argc, n);
+ if (n < argc) rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, n);
for (i=1; i<n; i++) {
- Check_SafeStr(argv[i]);
+ switch (TYPE(argv[i])) {
+ case T_STRING:
+ Check_SafeStr(argv[i]);
+ break;
+ case T_FILE:
+ break;
+ default:
+ Check_Type(argv[i], T_STRING);
+ break;
+ }
}
}
#define CHECK(n) test_check((n), argc, argv)
static VALUE
-f_test(argc, argv)
+rb_f_test(argc, argv)
int argc;
VALUE *argv;
{
int cmd;
- if (argc == 0) ArgError("Wrong # of arguments");
- if (TYPE(argv[0]) == T_STRING && RSTRING(argv[0])->len == 1) {
- cmd = RSTRING(argv[0])->ptr[0];
- }
- else {
- cmd = NUM2INT(argv[0]);
- }
- if (cmd == 0) return FALSE;
+ if (argc == 0) rb_raise(rb_eArgError, "Wrong # of arguments");
+ cmd = NUM2CHR(argv[0]);
+ if (cmd == 0) return Qfalse;
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
CHECK(1);
switch (cmd) {
@@ -1543,17 +1555,17 @@ f_test(argc, argv)
struct stat st;
CHECK(1);
- if (stat(RSTRING(argv[1])->ptr, &st) == -1) {
+ if (rb_stat(argv[1], &st) == -1) {
rb_sys_fail(RSTRING(argv[1])->ptr);
}
switch (cmd) {
case 'A':
- return time_new(st.st_atime, 0);
+ return rb_time_new(st.st_atime, 0);
case 'M':
- return time_new(st.st_mtime, 0);
+ return rb_time_new(st.st_mtime, 0);
case 'C':
- return time_new(st.st_ctime, 0);
+ return rb_time_new(st.st_ctime, 0);
}
}
@@ -1561,161 +1573,136 @@ f_test(argc, argv)
struct stat st1, st2;
CHECK(2);
- if (stat(RSTRING(argv[1])->ptr, &st1) < 0) return FALSE;
- if (stat(RSTRING(argv[2])->ptr, &st2) < 0) return FALSE;
+ if (rb_stat(argv[1], &st1) < 0) return Qfalse;
+ if (rb_stat(argv[2], &st2) < 0) return Qfalse;
switch (cmd) {
case '-':
if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
- return TRUE;
+ return Qtrue;
break;
case '=':
- if (st1.st_mtime == st2.st_mtime) return TRUE;
+ if (st1.st_mtime == st2.st_mtime) return Qtrue;
break;
case '>':
- if (st1.st_mtime > st2.st_mtime) return TRUE;
+ if (st1.st_mtime > st2.st_mtime) return Qtrue;
break;
case '<':
- if (st1.st_mtime < st2.st_mtime) return TRUE;
+ if (st1.st_mtime < st2.st_mtime) return Qtrue;
break;
}
}
- return FALSE;
+ /* unknown command */
+ rb_raise(rb_eArgError, "unknow command ?%c", cmd);
+ return Qnil; /* not reached */
}
-extern VALUE mKernel;
-
void
Init_File()
{
- VALUE mConst;
-
- mFileTest = rb_define_module("FileTest");
-
- rb_define_module_function(mFileTest, "directory?", test_d, 1);
- rb_define_module_function(mFileTest, "exist?", test_e, 1);
- rb_define_module_function(mFileTest, "exists?", test_e, 1); /* temporary */
- rb_define_module_function(mFileTest, "readable?", test_r, 1);
- rb_define_module_function(mFileTest, "readable_real?", test_R, 1);
- rb_define_module_function(mFileTest, "writable?", test_w, 1);
- rb_define_module_function(mFileTest, "writable_real?", test_W, 1);
- rb_define_module_function(mFileTest, "executable?", test_x, 1);
- rb_define_module_function(mFileTest, "executable_real?", test_X, 1);
- rb_define_module_function(mFileTest, "file?", test_f, 1);
- rb_define_module_function(mFileTest, "zero?", test_z, 1);
- rb_define_module_function(mFileTest, "size?", test_s, 1);
- rb_define_module_function(mFileTest, "size", test_s, 1);
- rb_define_module_function(mFileTest, "owned?", test_owned, 1);
- rb_define_module_function(mFileTest, "grpowned?", test_grpowned, 1);
-
- rb_define_module_function(mFileTest, "pipe?", test_p, 1);
- rb_define_module_function(mFileTest, "symlink?", test_l, 1);
- rb_define_module_function(mFileTest, "socket?", test_S, 1);
-
- rb_define_module_function(mFileTest, "blockdev?", test_b, 1);
- rb_define_module_function(mFileTest, "chardev?", test_c, 1);
-
- rb_define_module_function(mFileTest, "setuid?", test_suid, 1);
- rb_define_module_function(mFileTest, "setgid?", test_sgid, 1);
- rb_define_module_function(mFileTest, "sticky?", test_sticky, 1);
-
- cFile = rb_define_class("File", cIO);
- rb_extend_object(cFile, CLASS_OF(mFileTest));
-
- rb_define_singleton_method(cFile, "new", file_s_open, -1);
- rb_define_singleton_method(cFile, "open", file_s_open, -1);
-
- rb_define_singleton_method(cFile, "stat", file_s_stat, 1);
- rb_define_singleton_method(cFile, "lstat", file_s_lstat, 1);
- rb_define_singleton_method(cFile, "ftype", file_s_ftype, 1);
-
- rb_define_singleton_method(cFile, "atime", file_s_atime, 1);
- rb_define_singleton_method(cFile, "mtime", file_s_mtime, 1);
- rb_define_singleton_method(cFile, "ctime", file_s_ctime, 1);
- rb_define_singleton_method(cFile, "size", file_s_size, 1);
-
- rb_define_singleton_method(cFile, "utime", file_s_utime, -1);
- rb_define_singleton_method(cFile, "chmod", file_s_chmod, -1);
- rb_define_singleton_method(cFile, "chown", file_s_chown, -1);
-
- rb_define_singleton_method(cFile, "link", file_s_link, 2);
- rb_define_singleton_method(cFile, "symlink", file_s_symlink, 2);
- rb_define_singleton_method(cFile, "readlink", file_s_readlink, 1);
-
- rb_define_singleton_method(cFile, "unlink", file_s_unlink, -2);
- rb_define_singleton_method(cFile, "delete", file_s_unlink, -2);
- rb_define_singleton_method(cFile, "rename", file_s_rename, 2);
- rb_define_singleton_method(cFile, "umask", file_s_umask, -1);
- rb_define_singleton_method(cFile, "truncate", file_s_truncate, 2);
- rb_define_singleton_method(cFile, "expand_path", file_s_expand_path, 1);
- rb_define_singleton_method(cFile, "basename", file_s_basename, -1);
- rb_define_singleton_method(cFile, "dirname", file_s_dirname, 1);
-
- separator = str_new2("/");
- rb_define_const(cFile, "Separator", separator);
- rb_define_singleton_method(cFile, "split", file_s_split, 1);
- rb_define_singleton_method(cFile, "join", file_s_join, -2);
-
- rb_define_method(cFile, "reopen", file_reopen, -1);
-
- rb_define_method(cFile, "stat", file_stat, 0);
- rb_define_method(cFile, "lstat", file_lstat, 0);
-
- rb_define_method(cFile, "atime", file_atime, 0);
- rb_define_method(cFile, "mtime", file_mtime, 0);
- rb_define_method(cFile, "ctime", file_ctime, 0);
-
- rb_define_method(cFile, "chmod", file_chmod, 1);
- rb_define_method(cFile, "chown", file_chown, 2);
- rb_define_method(cFile, "truncate", file_truncate, 1);
-
- rb_define_method(cFile, "tell", file_tell, 0);
- rb_define_method(cFile, "seek", file_seek, 2);
-
- rb_define_method(cFile, "pos", file_tell, 0);
- rb_define_method(cFile, "pos=", file_set_pos, 1);
-
- rb_define_method(cFile, "rewind", file_rewind, 0);
- rb_define_method(cFile, "isatty", file_isatty, 0);
- rb_define_method(cFile, "tty?", file_isatty, 0);
- rb_define_method(cFile, "eof", file_eof, 0);
- rb_define_method(cFile, "eof?", file_eof, 0);
-
- rb_define_method(cFile, "flock", file_flock, 1);
-
-# 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
-
- mConst = rb_define_module_under(cFile, "Constants");
- rb_define_const(cFile, "LOCK_SH", INT2FIX(LOCK_SH));
- rb_define_const(cFile, "LOCK_EX", INT2FIX(LOCK_EX));
- rb_define_const(cFile, "LOCK_UN", INT2FIX(LOCK_UN));
- rb_define_const(cFile, "LOCK_NB", INT2FIX(LOCK_NB));
-
- rb_define_const(mConst, "LOCK_SH", INT2FIX(LOCK_SH));
- rb_define_const(mConst, "LOCK_EX", INT2FIX(LOCK_EX));
- rb_define_const(mConst, "LOCK_UN", INT2FIX(LOCK_UN));
- rb_define_const(mConst, "LOCK_NB", INT2FIX(LOCK_NB));
-
- rb_define_method(cFile, "path", file_path, 0);
-
- rb_define_global_function("test", f_test, -1);
-
- sStat = struct_define("Stat", "dev", "ino", "mode",
- "nlink", "uid", "gid", "rdev",
- "size", "blksize", "blocks",
- "atime", "mtime", "ctime", 0);
+ VALUE rb_mConst;
+
+ rb_mFileTest = rb_define_module("FileTest");
+
+ rb_define_module_function(rb_mFileTest, "directory?", test_d, 1);
+ rb_define_module_function(rb_mFileTest, "exist?", test_e, 1);
+ rb_define_module_function(rb_mFileTest, "exists?", test_e, 1); /* temporary */
+ rb_define_module_function(rb_mFileTest, "readable?", test_r, 1);
+ rb_define_module_function(rb_mFileTest, "readable_real?", test_R, 1);
+ rb_define_module_function(rb_mFileTest, "writable?", test_w, 1);
+ rb_define_module_function(rb_mFileTest, "writable_real?", test_W, 1);
+ rb_define_module_function(rb_mFileTest, "executable?", test_x, 1);
+ rb_define_module_function(rb_mFileTest, "executable_real?", test_X, 1);
+ rb_define_module_function(rb_mFileTest, "file?", test_f, 1);
+ rb_define_module_function(rb_mFileTest, "zero?", test_z, 1);
+ rb_define_module_function(rb_mFileTest, "size?", test_s, 1);
+ rb_define_module_function(rb_mFileTest, "size", test_s, 1);
+ rb_define_module_function(rb_mFileTest, "owned?", test_owned, 1);
+ rb_define_module_function(rb_mFileTest, "grpowned?", test_grpowned, 1);
+
+ rb_define_module_function(rb_mFileTest, "pipe?", test_p, 1);
+ rb_define_module_function(rb_mFileTest, "symlink?", test_l, 1);
+ rb_define_module_function(rb_mFileTest, "socket?", test_S, 1);
+
+ rb_define_module_function(rb_mFileTest, "blockdev?", test_b, 1);
+ rb_define_module_function(rb_mFileTest, "chardev?", test_c, 1);
+
+ rb_define_module_function(rb_mFileTest, "setuid?", test_suid, 1);
+ rb_define_module_function(rb_mFileTest, "setgid?", test_sgid, 1);
+ rb_define_module_function(rb_mFileTest, "sticky?", test_sticky, 1);
+
+ rb_cFile = rb_define_class("File", rb_cIO);
+ rb_extend_object(rb_cFile, CLASS_OF(rb_mFileTest));
+
+ rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1);
+ rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1);
+
+ rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
+ rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
+ rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);
+
+ rb_define_singleton_method(rb_cFile, "atime", rb_file_s_atime, 1);
+ rb_define_singleton_method(rb_cFile, "mtime", rb_file_s_mtime, 1);
+ rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1);
+ rb_define_singleton_method(rb_cFile, "size", rb_file_s_size, 1);
+
+ rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1);
+ rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1);
+ rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
+
+ rb_define_singleton_method(rb_cFile, "link", rb_file_s_link, 2);
+ rb_define_singleton_method(rb_cFile, "symlink", rb_file_s_symlink, 2);
+ rb_define_singleton_method(rb_cFile, "readlink", rb_file_s_readlink, 1);
+
+ rb_define_singleton_method(rb_cFile, "unlink", rb_file_s_unlink, -2);
+ rb_define_singleton_method(rb_cFile, "delete", rb_file_s_unlink, -2);
+ rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, 2);
+ rb_define_singleton_method(rb_cFile, "umask", rb_file_s_umask, -1);
+ rb_define_singleton_method(rb_cFile, "truncate", rb_file_s_truncate, 2);
+ rb_define_singleton_method(rb_cFile, "expand_path", rb_file_s_expand_path, -1);
+ rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1);
+ rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, 1);
+
+ separator = rb_str_new2("/");
+ rb_define_const(rb_cFile, "Separator", separator);
+ rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
+ rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
+
+ rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1);
+
+ rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
+ rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
+
+ rb_define_method(rb_cFile, "atime", rb_file_atime, 0);
+ rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0);
+ rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0);
+
+ rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
+ rb_define_method(rb_cFile, "chown", rb_file_chown, 2);
+ rb_define_method(rb_cFile, "truncate", rb_file_truncate, 1);
+
+ rb_define_method(rb_cFile, "flock", rb_file_flock, 1);
+
+ rb_mConst = rb_define_module_under(rb_cFile, "Constants");
+ rb_define_const(rb_cFile, "LOCK_SH", INT2FIX(LOCK_SH));
+ rb_define_const(rb_cFile, "LOCK_EX", INT2FIX(LOCK_EX));
+ rb_define_const(rb_cFile, "LOCK_UN", INT2FIX(LOCK_UN));
+ rb_define_const(rb_cFile, "LOCK_NB", INT2FIX(LOCK_NB));
+
+ rb_define_const(rb_mConst, "LOCK_SH", INT2FIX(LOCK_SH));
+ rb_define_const(rb_mConst, "LOCK_EX", INT2FIX(LOCK_EX));
+ rb_define_const(rb_mConst, "LOCK_UN", INT2FIX(LOCK_UN));
+ rb_define_const(rb_mConst, "LOCK_NB", INT2FIX(LOCK_NB));
+
+ rb_define_method(rb_cFile, "path", rb_file_path, 0);
+
+ rb_define_global_function("test", rb_f_test, -1);
+
+ sStat = rb_struct_define("Stat", "dev", "ino", "mode",
+ "nlink", "uid", "gid", "rdev",
+ "size", "blksize", "blocks",
+ "atime", "mtime", "ctime", 0);
}
diff --git a/fnmatch.c b/fnmatch.c
index 0847f5cafb..f031749c3d 100644
--- a/fnmatch.c
+++ b/fnmatch.c
@@ -20,6 +20,10 @@ Cambridge, MA 02139, USA. */
#include <errno.h>
#include "fnmatch.h"
+#ifdef USE_CWGUSI
+#include <sys/errno.h>
+#endif
+
#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
# if !defined (errno)
extern int errno;
@@ -51,15 +55,23 @@ fnmatch (pattern, string, flags)
if (*n == '\0')
return (FNM_NOMATCH);
else if ((flags & FNM_PATHNAME) && *n == '/')
+ /* If we are matching a pathname, `?' can never match a `/'. */
return (FNM_NOMATCH);
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ /* `?' cannot match a `.' if it is the first character of the
+ string or if it is the first character following a slash and
+ we are matching a pathname. */
return (FNM_NOMATCH);
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
- c = *p++;
+ {
+ c = *p++;
+ if (c == '\0')
+ return (FNM_NOMATCH);
+ }
if (*n != c)
return (FNM_NOMATCH);
break;
@@ -67,19 +79,38 @@ fnmatch (pattern, string, flags)
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ /* `*' cannot match a `.' if it is the first character of the
+ string or if it is the first character following a slash and
+ we are matching a pathname. */
return (FNM_NOMATCH);
- for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
- if (((flags & FNM_PATHNAME) && *n == '/') ||
- (c == '?' && *n == '\0'))
- return (FNM_NOMATCH);
+ /* Collapse multiple consecutive, `*' and `?', but make sure that
+ one character of the string is consumed for each `?'. */
+ for (c = *p++; c == '?' || c == '*'; c = *p++)
+ {
+ if ((flags & FNM_PATHNAME) && *n == '/')
+ /* A slash does not match a wildcard under FNM_PATHNAME. */
+ return (FNM_NOMATCH);
+ else if (c == '?')
+ {
+ if (*n == '\0')
+ return (FNM_NOMATCH);
+ /* One character of the string is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ fewer than three characters. */
+ n++;
+ }
+ }
if (c == '\0')
return (0);
+ /* General case, use recursion. */
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
+ /* Only call fnmatch if the first character indicates a
+ possible match. */
if ((c == '[' || *n == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return (0);
@@ -94,22 +125,30 @@ fnmatch (pattern, string, flags)
if (*n == '\0')
return (FNM_NOMATCH);
+ /* A character class cannot match a `.' if it is the first
+ character of the string or if it is the first character
+ following a slash and we are matching a pathname. */
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
- /* Make sure there is a closing `]'. If there isn't, the `['
- is just a character to be matched. */
+ /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
+ is not preceded by a backslash and is not part of a bracket
+ expression produces undefined results.' This implementation
+ treats the `[' as just a character to be matched if there is
+ not a closing `]'. This code will have to be changed when
+ POSIX.2 character classes are implemented. */
{
register char *np;
- for (np = p; np && *np && *np != ']'; np++);
+ for (np = p; np && *np && *np != ']'; np++)
+ ;
if (np && !*np)
{
if (*n != '[')
return (FNM_NOMATCH);
- goto next_char;
+ break;
}
}
@@ -120,10 +159,18 @@ fnmatch (pattern, string, flags)
c = *p++;
for (;;)
{
- register char cstart = c, cend = c;
+ register char cstart, cend;
+
+ /* Initialize cstart and cend in case `-' is the last
+ character of the pattern. */
+ cstart = cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
- cstart = cend = *p++;
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ cstart = cend = *p++;
+ }
if (c == '\0')
/* [ (unterminated) loses. */
@@ -135,6 +182,9 @@ fnmatch (pattern, string, flags)
/* [/] can never match. */
return (FNM_NOMATCH);
+ /* This introduces a range, unless the `-' is the last
+ character of the class. Find the end of the range
+ and move past it. */
if (c == '-' && *p != ']')
{
cend = *p++;
@@ -142,6 +192,7 @@ fnmatch (pattern, string, flags)
cend = *p++;
if (cend == '\0')
return (FNM_NOMATCH);
+
c = *p++;
}
@@ -153,8 +204,6 @@ fnmatch (pattern, string, flags)
}
if (!not)
return (FNM_NOMATCH);
-
- next_char:
break;
matched:
@@ -167,8 +216,12 @@ fnmatch (pattern, string, flags)
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
- /* 1003.2d11 is unclear if this is right. %%% */
- ++p;
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
}
if (not)
return (FNM_NOMATCH);
diff --git a/gc.c b/gc.c
index 27065af1cb..31ed11196a 100644
--- a/gc.c
+++ b/gc.c
@@ -6,12 +6,13 @@
$Date$
created at: Tue Oct 5 09:44:46 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
+#define RUBY_NO_INLINE
#include "ruby.h"
-#include "sig.h"
+#include "rubysig.h"
#include "st.h"
#include "node.h"
#include "env.h"
@@ -19,6 +20,9 @@
#include <stdio.h>
#include <setjmp.h>
+void re_free_registers _((struct re_registers*));
+void rb_io_fptr_finalize _((struct OpenFile*));
+
#ifndef setjmp
#ifdef HAVE__SETJMP
#define setjmp(env) _setjmp(env)
@@ -26,43 +30,46 @@
#endif
#endif
-#ifdef _AIX
-#pragma alloca
-#endif
-
#ifdef C_ALLOCA
+#ifndef alloca
void *alloca();
#endif
+#endif
static void run_final();
#ifndef GC_MALLOC_LIMIT
#if defined(MSDOS) || defined(__human68k__)
-#define GC_MALLOC_LIMIT 200000
+#define GC_MALLOC_LIMIT 100000
#else
-#define GC_MALLOC_LIMIT 400000
+#define GC_MALLOC_LIMIT 200000
#endif
#endif
+#define GC_NEWOBJ_LIMIT 1000
static unsigned long malloc_memories = 0;
+static unsigned long alloc_objects = 0;
void *
xmalloc(size)
- unsigned long size;
+ size_t size;
{
void *mem;
+ if (size < 0) {
+ rb_raise(rb_eArgError, "negative allocation size (or too big)");
+ }
if (size == 0) size = 1;
malloc_memories += size;
- if (malloc_memories > GC_MALLOC_LIMIT) {
- gc_gc();
+ if (malloc_memories > GC_MALLOC_LIMIT && alloc_objects > GC_NEWOBJ_LIMIT) {
+ rb_gc();
}
mem = malloc(size);
if (!mem) {
- gc_gc();
+ rb_gc();
mem = malloc(size);
if (!mem)
- Fatal("failed to allocate memory");
+ rb_fatal("failed to allocate memory");
}
return mem;
@@ -70,7 +77,7 @@ xmalloc(size)
void *
xcalloc(n, size)
- unsigned long n, size;
+ size_t n, size;
{
void *mem;
@@ -83,17 +90,22 @@ xcalloc(n, size)
void *
xrealloc(ptr, size)
void *ptr;
- unsigned long size;
+ size_t size;
{
void *mem;
+ if (size < 0) {
+ rb_raise(rb_eArgError, "negative re-allocation size");
+ }
if (!ptr) return xmalloc(size);
+ if (size == 0) size = 1;
+ malloc_memories += size;
mem = realloc(ptr, size);
if (!mem) {
- gc_gc();
+ rb_gc();
mem = realloc(ptr, size);
if (!mem)
- Fatal("failed to allocate memory(realloc)");
+ rb_fatal("failed to allocate memory(realloc)");
}
return mem;
@@ -129,28 +141,30 @@ Paradigm Associates Inc Phone: 617-492-6079
Cambridge, MA 02138
*/
-extern int rb_in_compile;
+extern int ruby_in_compile;
static int dont_gc;
+static int during_gc;
+static int need_call_final = 0;
-VALUE
-gc_s_enable()
+static VALUE
+gc_enable()
{
int old = dont_gc;
- dont_gc = FALSE;
+ dont_gc = Qfalse;
return old;
}
-VALUE
-gc_s_disable()
+static VALUE
+gc_disable()
{
int old = dont_gc;
- dont_gc = TRUE;
+ dont_gc = Qtrue;
return old;
}
-VALUE mGC;
+VALUE rb_mGC;
static struct gc_list {
VALUE *varptr;
@@ -172,12 +186,12 @@ rb_global_variable(var)
typedef struct RVALUE {
union {
struct {
- UINT flag; /* always 0 for freed obj */
+ unsigned long flag; /* always 0 for freed obj */
struct RVALUE *next;
} free;
struct RBasic basic;
struct RObject object;
- struct RClass class;
+ struct RClass klass;
struct RFloat flonum;
struct RString string;
struct RArray array;
@@ -194,7 +208,7 @@ typedef struct RVALUE {
} as;
} RVALUE;
-RVALUE *freelist = 0;
+static RVALUE *freelist = 0;
#define HEAPS_INCREMENT 10
static RVALUE **heaps;
@@ -217,11 +231,11 @@ add_heap()
heaps = (heaps_used>0)?
(RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE)):
(RVALUE**)malloc(heaps_length*sizeof(RVALUE));
- if (heaps == 0) Fatal("can't alloc memory");
+ if (heaps == 0) rb_fatal("can't alloc memory");
}
p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS);
- if (p == 0) Fatal("can't alloc memory");
+ if (p == 0) rb_fatal("add_heap: can't alloc memory");
pend = p + HEAP_SLOTS;
if (lomem == 0 || lomem > p) lomem = p;
if (himem < pend) himem = pend;
@@ -244,23 +258,24 @@ rb_newobj()
retry:
obj = (VALUE)freelist;
freelist = freelist->as.free.next;
+ alloc_objects++;
return obj;
}
- if (dont_gc) add_heap();
- else gc_gc();
+ if (dont_gc || during_gc || rb_prohibit_interrupt) add_heap();
+ else rb_gc();
goto retry;
}
VALUE
-data_object_alloc(class, datap, dmark, dfree)
- VALUE class;
+rb_data_object_alloc(klass, datap, dmark, dfree)
+ VALUE klass;
void *datap;
void (*dfree)();
void (*dmark)();
{
NEWOBJ(data, struct RData);
- OBJSETUP(data, class, T_DATA);
+ OBJSETUP(data, klass, T_DATA);
data->data = datap;
data->dfree = dfree;
data->dmark = dmark;
@@ -269,8 +284,11 @@ data_object_alloc(class, datap, dmark, dfree)
}
extern st_table *rb_class_tbl;
-VALUE *gc_stack_start;
+VALUE *rb_gc_stack_start;
+#if defined(__GNUC__) && __GNUC__ >= 2
+__inline__
+#endif
static int
looks_pointerp(ptr)
void *ptr;
@@ -279,33 +297,33 @@ looks_pointerp(ptr)
register RVALUE *heap_org;
register long i;
- if (p < lomem || p > himem) return FALSE;
+ if (p < lomem || p > himem) return Qfalse;
/* check if p looks like a pointer */
for (i=0; i < heaps_used; i++) {
heap_org = heaps[i];
if (heap_org <= p && p < heap_org + HEAP_SLOTS
&& ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0)
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static void
mark_locations_array(x, n)
- VALUE *x;
- long n;
+ register VALUE *x;
+ register long n;
{
while (n--) {
if (looks_pointerp(*x)) {
- gc_mark(*x);
+ rb_gc_mark(*x);
}
x++;
}
}
void
-gc_mark_locations(start, end)
+rb_gc_mark_locations(start, end)
VALUE *start, *end;
{
VALUE *tmp;
@@ -325,12 +343,12 @@ mark_entry(key, value)
ID key;
VALUE value;
{
- gc_mark(value);
+ rb_gc_mark(value);
return ST_CONTINUE;
}
-static void
-mark_tbl(tbl)
+void
+rb_mark_tbl(tbl)
st_table *tbl;
{
if (!tbl) return;
@@ -342,13 +360,13 @@ mark_hashentry(key, value)
ID key;
VALUE value;
{
- gc_mark(key);
- gc_mark(value);
+ rb_gc_mark(key);
+ rb_gc_mark(value);
return ST_CONTINUE;
}
-static void
-mark_hash(tbl)
+void
+rb_mark_hash(tbl)
st_table *tbl;
{
if (!tbl) return;
@@ -356,16 +374,16 @@ mark_hash(tbl)
}
void
-gc_mark_maybe(obj)
+rb_gc_mark_maybe(obj)
void *obj;
{
if (looks_pointerp(obj)) {
- gc_mark(obj);
+ rb_gc_mark(obj);
}
}
void
-gc_mark(ptr)
+rb_gc_mark(ptr)
void *ptr;
{
register RVALUE *obj = RANY(ptr);
@@ -374,14 +392,18 @@ gc_mark(ptr)
if (FIXNUM_P(obj)) return; /* fixnum not marked */
if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */
if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* marked */
+ if (obj->as.basic.flags & FL_MARK) return; /* already marked */
obj->as.basic.flags |= FL_MARK;
+ if (FL_TEST(obj, FL_EXIVAR)) {
+ rb_mark_generic_ivar((VALUE)obj);
+ }
+
switch (obj->as.basic.flags & T_MASK) {
case T_NIL:
case T_FIXNUM:
- Bug("gc_mark() called for broken object");
+ rb_bug("rb_gc_mark() called for broken object");
break;
case T_NODE:
@@ -389,7 +411,12 @@ gc_mark(ptr)
case NODE_IF: /* 1,2,3 */
case NODE_FOR:
case NODE_ITER:
- gc_mark(obj->as.node.u2.node);
+ case NODE_CREF:
+ case NODE_WHEN:
+ case NODE_MASGN:
+ case NODE_RESCUE:
+ case NODE_RESBODY:
+ rb_gc_mark(obj->as.node.u2.node);
/* fall through */
case NODE_BLOCK: /* 1,3 */
case NODE_ARRAY:
@@ -399,23 +426,47 @@ gc_mark(ptr)
case NODE_DREGX:
case NODE_DREGX_ONCE:
case NODE_FBODY:
+ case NODE_ENSURE:
case NODE_CALL:
- gc_mark(obj->as.node.u1.node);
+ case NODE_DEFS:
+ case NODE_OP_ASGN1:
+ rb_gc_mark(obj->as.node.u1.node);
/* fall through */
case NODE_SUPER: /* 3 */
case NODE_FCALL:
+ case NODE_DEFN:
case NODE_NEWLINE:
obj = RANY(obj->as.node.u3.node);
goto Top;
case NODE_WHILE: /* 1,2 */
case NODE_UNTIL:
+ case NODE_AND:
+ case NODE_OR:
+ case NODE_CASE:
+ case NODE_SCLASS:
+ case NODE_ARGS:
+ case NODE_DOT2:
+ case NODE_DOT3:
+ case NODE_FLIP2:
+ case NODE_FLIP3:
case NODE_MATCH2:
case NODE_MATCH3:
- gc_mark(obj->as.node.u1.node);
+ case NODE_OP_ASGN_OR:
+ case NODE_OP_ASGN_AND:
+ rb_gc_mark(obj->as.node.u1.node);
/* fall through */
case NODE_METHOD: /* 2 */
case NODE_NOT:
+ case NODE_GASGN:
+ case NODE_LASGN:
+ case NODE_DASGN:
+ case NODE_DASGN_PUSH:
+ case NODE_IASGN:
+ case NODE_CASGN:
+ case NODE_MODULE:
+ case NODE_COLON3:
+ case NODE_OPT_N:
obj = RANY(obj->as.node.u2.node);
goto Top;
@@ -425,15 +476,21 @@ gc_mark(ptr)
case NODE_XSTR:
case NODE_DEFINED:
case NODE_MATCH:
+ case NODE_RETURN:
+ case NODE_YIELD:
+ case NODE_COLON2:
obj = RANY(obj->as.node.u1.node);
goto Top;
case NODE_SCOPE: /* 2,3 */
- gc_mark(obj->as.node.u3.node);
+ case NODE_CLASS:
+ case NODE_BLOCK_PASS:
+ rb_gc_mark(obj->as.node.u3.node);
obj = RANY(obj->as.node.u2.node);
goto Top;
case NODE_ZARRAY: /* - */
+ case NODE_ZSUPER:
case NODE_CFUNC:
case NODE_VCALL:
case NODE_GVAR:
@@ -445,18 +502,33 @@ gc_mark(ptr)
case NODE_BACK_REF:
case NODE_ALIAS:
case NODE_VALIAS:
+ case NODE_BREAK:
+ case NODE_NEXT:
+ case NODE_REDO:
+ case NODE_RETRY:
case NODE_UNDEF:
case NODE_SELF:
case NODE_NIL:
+ case NODE_TRUE:
+ case NODE_FALSE:
+ case NODE_ATTRSET:
+ case NODE_BLOCK_ARG:
case NODE_POSTEXE:
break;
+#ifdef C_ALLOCA
+ case NODE_ALLOCA:
+ mark_locations_array((VALUE*)obj->as.node.u1.value,
+ obj->as.node.u3.cnt);
+ obj = RANY(obj->as.node.u2.node);
+ goto Top;
+#endif
default:
if (looks_pointerp(obj->as.node.u1.node)) {
- gc_mark(obj->as.node.u1.node);
+ rb_gc_mark(obj->as.node.u1.node);
}
if (looks_pointerp(obj->as.node.u2.node)) {
- gc_mark(obj->as.node.u2.node);
+ rb_gc_mark(obj->as.node.u2.node);
}
if (looks_pointerp(obj->as.node.u3.node)) {
obj = RANY(obj->as.node.u3.node);
@@ -466,19 +538,14 @@ gc_mark(ptr)
return; /* no need to mark class. */
}
- gc_mark(obj->as.basic.class);
+ rb_gc_mark(obj->as.basic.klass);
switch (obj->as.basic.flags & T_MASK) {
case T_ICLASS:
- gc_mark(obj->as.class.super);
- mark_tbl(obj->as.class.iv_tbl);
- mark_tbl(obj->as.class.m_tbl);
- break;
-
case T_CLASS:
case T_MODULE:
- gc_mark(obj->as.class.super);
- mark_tbl(obj->as.class.m_tbl);
- mark_tbl(obj->as.class.iv_tbl);
+ rb_gc_mark(obj->as.klass.super);
+ rb_mark_tbl(obj->as.klass.m_tbl);
+ rb_mark_tbl(obj->as.klass.iv_tbl);
break;
case T_ARRAY:
@@ -487,12 +554,13 @@ gc_mark(ptr)
VALUE *ptr = obj->as.array.ptr;
for (i=0; i < len; i++)
- gc_mark(*ptr++);
+ rb_gc_mark(*ptr++);
}
break;
case T_HASH:
- mark_hash(obj->as.hash.tbl);
+ rb_mark_hash(obj->as.hash.tbl);
+ rb_gc_mark(obj->as.hash.ifnone);
break;
case T_STRING:
@@ -507,7 +575,7 @@ gc_mark(ptr)
break;
case T_OBJECT:
- mark_tbl(obj->as.object.iv_tbl);
+ rb_mark_tbl(obj->as.object.iv_tbl);
break;
case T_FILE:
@@ -524,7 +592,7 @@ gc_mark(ptr)
break;
case T_VARMAP:
- gc_mark(obj->as.varmap.val);
+ rb_gc_mark(obj->as.varmap.val);
obj = RANY(obj->as.varmap.next);
goto Top;
break;
@@ -535,7 +603,7 @@ gc_mark(ptr)
VALUE *vars = &obj->as.scope.local_vars[-1];
while (n--) {
- gc_mark_maybe(*vars);
+ rb_gc_mark(*vars);
vars++;
}
}
@@ -547,69 +615,95 @@ gc_mark(ptr)
VALUE *ptr = obj->as.rstruct.ptr;
for (i=0; i < len; i++)
- gc_mark(*ptr++);
+ rb_gc_mark(*ptr++);
}
break;
default:
- Bug("gc_mark(): unknown data type 0x%x(0x%x) %s",
- obj->as.basic.flags & T_MASK, obj,
- looks_pointerp(obj)?"corrupted object":"non object");
+ rb_bug("rb_gc_mark(): unknown data type 0x%x(0x%x) %s",
+ obj->as.basic.flags & T_MASK, obj,
+ looks_pointerp(obj)?"corrupted object":"non object");
}
}
#define MIN_FREE_OBJ 512
-static void obj_free();
+static void obj_free _((VALUE));
static void
gc_sweep()
{
- RVALUE *p, *pend;
+ RVALUE *p, *pend, *final_list;
int freed = 0;
- int i;
+ int i, used = heaps_used;
- if (rb_in_compile) {
- for (i = 0; i < heaps_used; i++) {
+ if (ruby_in_compile) {
+ /* sould not reclaim nodes during compilation */
+ for (i = 0; i < used; i++) {
p = heaps[i]; pend = p + HEAP_SLOTS;
while (p < pend) {
if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
- gc_mark(p);
+ rb_gc_mark(p);
p++;
}
}
}
freelist = 0;
- for (i = 0; i < heaps_used; i++) {
- RVALUE *nfreelist;
+ final_list = 0;
+ for (i = 0; i < used; i++) {
int n = 0;
- nfreelist = freelist;
p = heaps[i]; pend = p + HEAP_SLOTS;
-
while (p < pend) {
if (!(p->as.basic.flags & FL_MARK)) {
- if (p->as.basic.flags) obj_free(p);
- p->as.free.flag = 0;
- p->as.free.next = nfreelist;
- nfreelist = p;
+ if (p->as.basic.flags) {
+ obj_free((VALUE)p);
+ }
+ if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+ p->as.free.flag = FL_MARK; /* remain marked */
+ p->as.free.next = final_list;
+ final_list = p;
+ }
+ else {
+ p->as.free.flag = 0;
+ p->as.free.next = freelist;
+ freelist = p;
+ }
n++;
}
- else
+ else if (RBASIC(p)->flags == FL_MARK) {
+ /* objects to be finalized */
+ /* do notning remain marked */
+ }
+ else {
RBASIC(p)->flags &= ~FL_MARK;
+ }
p++;
}
freed += n;
- freelist = nfreelist;
}
if (freed < FREE_MIN) {
add_heap();
}
+ during_gc = 0;
+
+ /* clear finalization list */
+ if (need_call_final) {
+ RVALUE *tmp;
+
+ for (p = final_list; p; p = tmp) {
+ tmp = p->as.free.next;
+ run_final((VALUE)p);
+ p->as.free.flag = 0;
+ p->as.free.next = freelist;
+ freelist = p;
+ }
+ }
}
void
-gc_force_recycle(p)
+rb_gc_force_recycle(p)
VALUE p;
{
RANY(p)->as.free.flag = 0;
@@ -617,8 +711,6 @@ gc_force_recycle(p)
freelist = RANY(p);
}
-static int need_call_final = 0;
-
static void
obj_free(obj)
VALUE obj;
@@ -628,13 +720,14 @@ obj_free(obj)
case T_FIXNUM:
case T_TRUE:
case T_FALSE:
- Bug("obj_free() called for broken object");
+ rb_bug("obj_free() called for broken object");
break;
}
- if (need_call_final) {
- run_final(obj);
+ if (FL_TEST(obj, FL_EXIVAR)) {
+ rb_free_generic_ivar((VALUE)obj);
}
+
switch (RANY(obj)->as.basic.flags & T_MASK) {
case T_OBJECT:
if (RANY(obj)->as.object.iv_tbl) {
@@ -644,35 +737,48 @@ obj_free(obj)
case T_MODULE:
case T_CLASS:
rb_clear_cache();
- st_free_table(RANY(obj)->as.class.m_tbl);
+ st_free_table(RANY(obj)->as.klass.m_tbl);
if (RANY(obj)->as.object.iv_tbl) {
st_free_table(RANY(obj)->as.object.iv_tbl);
}
break;
case T_STRING:
- if (!RANY(obj)->as.string.orig) free(RANY(obj)->as.string.ptr);
+#define STR_NO_ORIG FL_USER3 /* copied from string.c */
+ if (!RANY(obj)->as.string.orig || FL_TEST(obj, STR_NO_ORIG))
+ free(RANY(obj)->as.string.ptr);
break;
case T_ARRAY:
if (RANY(obj)->as.array.ptr) free(RANY(obj)->as.array.ptr);
break;
case T_HASH:
- st_free_table(RANY(obj)->as.hash.tbl);
+ if (RANY(obj)->as.hash.tbl)
+ st_free_table(RANY(obj)->as.hash.tbl);
break;
case T_REGEXP:
- reg_free(RANY(obj)->as.regexp.ptr);
- free(RANY(obj)->as.regexp.str);
+ if (RANY(obj)->as.regexp.ptr) re_free_pattern(RANY(obj)->as.regexp.ptr);
+ if (RANY(obj)->as.regexp.str) free(RANY(obj)->as.regexp.str);
break;
case T_DATA:
- if (RANY(obj)->as.data.dfree && DATA_PTR(obj))
- (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+ if (DATA_PTR(obj)) {
+ if ((long)RANY(obj)->as.data.dfree == -1) {
+ free(DATA_PTR(obj));
+ }
+ else if (RANY(obj)->as.data.dfree) {
+ (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+ }
+ }
break;
case T_MATCH:
- re_free_registers(RANY(obj)->as.match.regs);
- free(RANY(obj)->as.match.regs);
+ if (RANY(obj)->as.match.regs)
+ re_free_registers(RANY(obj)->as.match.regs);
+ if (RANY(obj)->as.match.regs)
+ free(RANY(obj)->as.match.regs);
break;
case T_FILE:
- io_fptr_finalize(RANY(obj)->as.file.fptr);
- free(RANY(obj)->as.file.fptr);
+ if (RANY(obj)->as.file.fptr) {
+ rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
+ free(RANY(obj)->as.file.fptr);
+ }
break;
case T_ICLASS:
/* iClass shares table with the module */
@@ -686,8 +792,17 @@ obj_free(obj)
if (RANY(obj)->as.bignum.digits) free(RANY(obj)->as.bignum.digits);
break;
case T_NODE:
- if (nd_type(obj) == NODE_SCOPE && RANY(obj)->as.node.u1.tbl) {
- free(RANY(obj)->as.node.u1.tbl);
+ switch (nd_type(obj)) {
+ case NODE_SCOPE:
+ if (RANY(obj)->as.node.u1.tbl) {
+ free(RANY(obj)->as.node.u1.tbl);
+ }
+ break;
+#ifdef C_ALLOCA
+ case NODE_ALLOCA:
+ free(RANY(obj)->as.node.u1.value);
+ break;
+#endif
}
return; /* no need to free iv_tbl */
@@ -702,26 +817,22 @@ obj_free(obj)
break;
case T_STRUCT:
- free(RANY(obj)->as.rstruct.ptr);
+ if (RANY(obj)->as.rstruct.ptr)
+ free(RANY(obj)->as.rstruct.ptr);
break;
default:
- Bug("gc_sweep(): unknown data type %d", RANY(obj)->as.basic.flags & T_MASK);
+ rb_bug("gc_sweep(): unknown data type %d",
+ RANY(obj)->as.basic.flags & T_MASK);
}
}
void
-gc_mark_frame(frame)
+rb_gc_mark_frame(frame)
struct FRAME *frame;
{
- int n = frame->argc;
- VALUE *tbl = frame->argv;
-
- while (n--) {
- gc_mark_maybe(*tbl);
- tbl++;
- }
- gc_mark(frame->cbase);
+ mark_locations_array(frame->argv, frame->argc);
+ rb_gc_mark(frame->cbase);
}
#ifdef __GNUC__
@@ -760,68 +871,73 @@ int rb_setjmp (rb_jmp_buf);
#endif /* __GNUC__ */
void
-gc_gc()
+rb_gc()
{
struct gc_list *list;
struct FRAME *frame;
jmp_buf save_regs_gc_mark;
VALUE stack_end;
- if (dont_gc) return;
- dont_gc++;
-
+ alloc_objects = 0;
malloc_memories = 0;
+
+ if (during_gc) return;
+ during_gc++;
+
#ifdef C_ALLOCA
alloca(0);
#endif
/* mark frame stack */
- for (frame = the_frame; frame; frame = frame->prev) {
- gc_mark_frame(frame);
+ for (frame = ruby_frame; frame; frame = frame->prev) {
+ rb_gc_mark_frame(frame);
}
- gc_mark(the_scope);
- gc_mark(the_dyna_vars);
+ rb_gc_mark(ruby_class);
+ rb_gc_mark(ruby_scope);
+ rb_gc_mark(ruby_dyna_vars);
FLUSH_REGISTER_WINDOWS;
/* This assumes that all registers are saved into the jmp_buf */
setjmp(save_regs_gc_mark);
mark_locations_array((VALUE*)&save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
- gc_mark_locations(gc_stack_start, (VALUE*)&stack_end);
+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)&stack_end);
#if defined(THINK_C) || defined(__human68k__)
#ifndef __human68k__
mark_locations_array((VALUE*)((char*)save_regs_gc_mark+2),
sizeof(save_regs_gc_mark) / sizeof(VALUE *));
#endif
- gc_mark_locations((VALUE*)((char*)gc_stack_start + 2),
+ rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
(VALUE*)((char*)&stack_end + 2));
#endif
-#ifdef THREAD
- gc_mark_threads();
+#ifdef USE_THREAD
+ rb_gc_mark_threads();
#endif
/* mark protected global variables */
for (list = Global_List; list; list = list->next) {
- gc_mark(*list->varptr);
+ rb_gc_mark(*list->varptr);
}
+ rb_gc_mark_global_tbl();
- gc_mark_global_tbl();
- mark_tbl(rb_class_tbl);
- gc_mark_trap_list();
+ rb_mark_tbl(rb_class_tbl);
+ rb_gc_mark_trap_list();
+
+ /* mark generic instance variables for special constants */
+ rb_mark_generic_ivar_tbl();
gc_sweep();
- dont_gc--;
}
static VALUE
-gc_method()
+gc_start()
{
- gc_gc();
+ rb_gc();
return Qnil;
}
void
-init_stack()
+Init_stack()
{
#ifdef __human68k__
extern void *_SEND;
@@ -829,14 +945,14 @@ init_stack()
#else
VALUE start;
- gc_stack_start = &start;
+ rb_gc_stack_start = &start;
#endif
}
void
-init_heap()
+Init_heap()
{
- init_stack();
+ Init_stack();
add_heap();
}
@@ -893,7 +1009,7 @@ os_obj_of(of)
case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue;
default:
- if (obj_is_kind_of((VALUE)p, of)) {
+ if (rb_obj_is_kind_of((VALUE)p, of)) {
rb_yield((VALUE)p);
n++;
}
@@ -926,13 +1042,11 @@ static VALUE
add_final(os, proc)
VALUE os, proc;
{
- extern VALUE cProc;
-
- if (!obj_is_kind_of(proc, cProc)) {
- ArgError("wrong type argument %s (Proc required)",
- rb_class2name(CLASS_OF(proc)));
+ if (!rb_obj_is_kind_of(proc, rb_cProc)) {
+ rb_raise(rb_eArgError, "wrong type argument %s (Proc required)",
+ rb_class2name(CLASS_OF(proc)));
}
- ary_push(finalizers, proc);
+ rb_ary_push(finalizers, proc);
return proc;
}
@@ -940,7 +1054,7 @@ static VALUE
rm_final(os, proc)
VALUE os, proc;
{
- ary_delete(finalizers, proc);
+ rb_ary_delete(finalizers, proc);
return proc;
}
@@ -965,24 +1079,31 @@ run_final(obj)
{
int i;
- if (!FL_TEST(obj, FL_FINALIZE)) return;
-
- obj = INT2NUM((int)obj); /* make obj into id */
+ obj = rb_obj_id(obj); /* make obj into id */
for (i=0; i<RARRAY(finalizers)->len; i++) {
- rb_eval_cmd(RARRAY(finalizers)->ptr[i], ary_new3(1,obj));
+ rb_eval_cmd(RARRAY(finalizers)->ptr[i], rb_ary_new3(1, obj));
}
}
void
-gc_call_finalizer_at_exit()
+rb_gc_call_finalizer_at_exit()
{
RVALUE *p, *pend;
int i;
+ /* run finalizers */
+ for (i = 0; i < heaps_used; i++) {
+ p = heaps[i]; pend = p + HEAP_SLOTS;
+ while (p < pend) {
+ if (FL_TEST(p, FL_FINALIZE))
+ run_final((VALUE)p);
+ p++;
+ }
+ }
+ /* run data object's finaliers */
for (i = 0; i < heaps_used; i++) {
p = heaps[i]; pend = p + HEAP_SLOTS;
while (p < pend) {
- run_final(p);
if (BUILTIN_TYPE(p) == T_DATA &&
DATA_PTR(p) &&
RANY(p)->as.data.dfree)
@@ -996,40 +1117,45 @@ static VALUE
id2ref(obj, id)
VALUE obj, id;
{
- INT ptr = NUM2INT(id);
+ unsigned long ptr;
+ rb_secure(4);
+ ptr = NUM2UINT(id);
if (FIXNUM_P(ptr)) return (VALUE)ptr;
+ if (ptr == Qtrue) return Qtrue;
+ if (ptr == Qfalse) return Qfalse;
+ if (ptr == Qnil) return Qnil;
+
+ ptr = id ^ FIXNUM_FLAG;
if (!looks_pointerp(ptr)) {
- IndexError("0x%x is not the id value", ptr);
+ rb_raise(rb_eIndexError, "0x%x is not id value", ptr);
}
- if (RANY(ptr)->as.free.flag == 0) {
- IndexError("0x%x is recycled object", ptr);
+ if (BUILTIN_TYPE(ptr) == 0) {
+ rb_raise(rb_eIndexError, "0x%x is recycled object", ptr);
}
return (VALUE)ptr;
}
-extern VALUE cModule;
-
void
Init_GC()
{
- VALUE mObSpace;
-
- mGC = rb_define_module("GC");
- rb_define_singleton_method(mGC, "start", gc_method, 0);
- rb_define_singleton_method(mGC, "enable", gc_s_enable, 0);
- rb_define_singleton_method(mGC, "disable", gc_s_disable, 0);
- rb_define_method(mGC, "garbage_collect", gc_method, 0);
-
- mObSpace = rb_define_module("ObjectSpace");
- rb_define_module_function(mObSpace, "each_object", os_each_obj, -1);
- rb_define_module_function(mObSpace, "garbage_collect", gc_method, 0);
- rb_define_module_function(mObSpace, "add_finalizer", add_final, 1);
- rb_define_module_function(mObSpace, "remove_finalizer", rm_final, 1);
- rb_define_module_function(mObSpace, "finalizers", finals, 0);
- rb_define_module_function(mObSpace, "call_finalizer", call_final, 1);
- rb_define_module_function(mObSpace, "id2ref", id2ref, 1);
+ VALUE rb_mObSpace;
+
+ rb_mGC = rb_define_module("GC");
+ rb_define_singleton_method(rb_mGC, "start", gc_start, 0);
+ rb_define_singleton_method(rb_mGC, "enable", gc_enable, 0);
+ rb_define_singleton_method(rb_mGC, "disable", gc_disable, 0);
+ rb_define_method(rb_mGC, "garbage_collect", gc_start, 0);
+
+ rb_mObSpace = rb_define_module("ObjectSpace");
+ rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
+ rb_define_module_function(rb_mObSpace, "garbage_collect", gc_start, 0);
+ rb_define_module_function(rb_mObSpace, "add_finalizer", add_final, 1);
+ rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);
+ rb_define_module_function(rb_mObSpace, "finalizers", finals, 0);
+ rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);
+ rb_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
rb_global_variable(&finalizers);
- finalizers = ary_new();
+ finalizers = rb_ary_new();
}
diff --git a/glob.c b/glob.c
index 6c355ad260..09a47e0aa4 100644
--- a/glob.c
+++ b/glob.c
@@ -14,83 +14,79 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
+
/* To whomever it may concern: I have never seen the code which most
Unix programs use to perform this function. I wrote this from scratch
based on specifications for the pattern matching. --RMS. */
#include "config.h"
-#include <sys/types.h>
+#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
+ #pragma alloca
+#endif /* _AIX && RISC6000 && !__GNUC__ */
+
+#if defined (HAVE_ALLOCA_H)
+# include <alloca.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# if defined (SHELL)
+# include "ansi_stdlib.h"
+# endif /* SHELL */
+#endif
-#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
-# if !defined (HAVE_DIRENT_H)
-# define HAVE_DIRENT_H
-# endif /* !HAVE_DIRENT_H */
-#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+#include <sys/types.h>
#if defined (HAVE_DIRENT_H)
# include <dirent.h>
-# if !defined (direct)
-# define direct dirent
-# endif /* !direct */
+# define D_NAMLEN(d) strlen ((d)->d_name)
+#elif HAVE_DIRECT_H
+# include <direct.h>
# define D_NAMLEN(d) strlen ((d)->d_name)
#else /* !HAVE_DIRENT_H */
# define D_NAMLEN(d) ((d)->d_namlen)
-# if defined (USG)
-# if defined (Xenix)
-# include <sys/ndir.h>
-# else /* !Xenix (but USG...) */
-# include "ndir.h"
-# endif /* !Xenix */
-# else /* !USG */
-# if defined(NT)
-# include "missing/dir.h"
-# else
+# if defined (HAVE_SYS_NDIR_H)
+# include <sys/ndir.h>
+# endif
+# if defined (HAVE_SYS_DIR_H)
# include <sys/dir.h>
-# endif /* !NT */
-# endif /* !USG */
+# endif /* HAVE_SYS_DIR_H */
+# if defined (HAVE_NDIR_H)
+# include <ndir.h>
+# endif
+# if !defined (dirent)
+# define dirent direct
+# endif
#endif /* !HAVE_DIRENT_H */
-#if defined (_POSIX_SOURCE) || defined(DJGPP)
+#if defined (_POSIX_SOURCE) || defined(DJGPP) || defined(USE_CWGUSI)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
+#elif defined (__BORLANDC__)
+# define REAL_DIR_ENTRY(dp) 1
#else
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#endif /* _POSIX_SOURCE */
-#if defined (USG) || defined (NeXT)
-# if !defined (HAVE_STRING_H)
-# define HAVE_STRING_H
-# endif /* !HAVE_STRING_H */
-#endif /* USG || NeXT */
-
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
-#ifndef bcopy
-# define bcopy(s, d, n) (memcpy ((d), (s), (n)))
-#endif
-
-#ifdef _AIX
-#pragma alloca
-#else
-#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-#include <alloca.h>
-#else
-char *alloca ();
-#endif
-#endif
-
-#include "fnmatch.h"
+#if !defined (HAVE_BCOPY) && !defined (bcopy)
+# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+#endif /* !HAVE_BCOPY */
/* If the opendir () on your system lets you open non-directory files,
- then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
- SYSDEP_CFLAGS for your machines entry in machines.h. */
+ then we consider that not robust. */
#if defined (OPENDIR_NOT_ROBUST)
# if defined (SHELL)
# include "posixstat.h"
@@ -99,6 +95,8 @@ char *alloca ();
# endif /* !SHELL */
#endif /* OPENDIR_NOT_ROBUST */
+#include "fnmatch.h"
+
extern void *xmalloc (), *xrealloc ();
#if !defined (HAVE_STDLIB_H)
extern void free ();
@@ -113,9 +111,15 @@ extern void free ();
#endif /* !NULL */
#if defined (SHELL)
+extern void throw_to_top_level ();
+
extern int interrupt_state;
#endif /* SHELL */
+#if defined(NT) && defined(_MSC_VER)
+#include "missing/dir.h"
+#endif
+
/* Global variable which controls whether or not * matches .*.
Non-zero means don't match .*. */
int noglob_dot_filenames = 1;
@@ -123,7 +127,6 @@ int noglob_dot_filenames = 1;
/* Global variable to return to signify an error in globbing. */
char *glob_error_return;
-
/* Return nonzero if PATTERN has any special globbing chars in it. */
int
glob_pattern_p (pattern)
@@ -205,7 +208,7 @@ glob_vector (pat, dir)
};
DIR *d;
- register struct direct *dp;
+ register struct dirent *dp;
struct globval *lastlink;
register struct globval *nextlink;
register char *nextname;
@@ -276,7 +279,8 @@ glob_vector (pat, dir)
continue;
/* If a dot must be explicity matched, check to see if they do. */
- if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
+ if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
+ (pat[0] != '\\' || pat[1] != '.'))
continue;
flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
@@ -306,7 +310,9 @@ glob_vector (pat, dir)
}
/* Have we run out of memory? */
+#if defined (SHELL)
lost:
+#endif
if (lose)
{
/* Here free the strings we have got. */
@@ -365,7 +371,14 @@ glob_dir_to_array (dir, array)
+ strlen (array[i]) + 1);
if (result[i] == NULL)
return (NULL);
- sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+#if 1
+ strcpy (result[i], dir);
+ if (add_slash)
+ result[i][l] = '/';
+ strcpy (result[i] + l + add_slash, array[i]);
+#else
+ (void)sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+#endif
}
result[i] = NULL;
@@ -435,10 +448,14 @@ glob_filename (pathname)
if (directories == NULL)
goto memory_error;
else if (directories == (char **)&glob_error_return)
- return ((char **) &glob_error_return);
+ {
+ free ((char *) result);
+ return ((char **) &glob_error_return);
+ }
else if (*directories == NULL)
{
free ((char *) directories);
+ free ((char *) result);
return ((char **) &glob_error_return);
}
diff --git a/hash.c b/hash.c
index 49be7de6aa..9141406410 100644
--- a/hash.c
+++ b/hash.c
@@ -6,37 +6,36 @@
$Date$
created at: Mon Nov 22 18:51:18 JST 1993
- Copyright (C) 1993-1997 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "st.h"
-#include "sig.h"
+#include "rubysig.h"
+#include <sys/types.h>
#include <sys/stat.h>
#ifndef HAVE_STRING_H
-char *strchr();
+char *strchr _((char*,char));
#endif
-#define HASH_DELETED 0x1
-#define HASH_REHASHED 0x2
-
#define HASH_FREEZE FL_USER1
+#define HASH_DELETED FL_USER2
static void
-hash_modify(hash)
+rb_hash_modify(hash)
VALUE hash;
{
- rb_secure(5);
- if (FL_TEST(hash, HASH_FREEZE)) {
- TypeError("can't modify frozen hash");
- }
+ if (FL_TEST(hash, HASH_FREEZE))
+ rb_raise(rb_eTypeError, "can't modify frozen hash");
+ if (rb_safe_level() >= 4 && !FL_TEST(hash, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
}
VALUE
-hash_freeze(hash)
+rb_hash_freeze(hash)
VALUE hash;
{
FL_SET(hash, HASH_FREEZE);
@@ -44,19 +43,15 @@ hash_freeze(hash)
}
static VALUE
-hash_frozen_p(hash)
+rb_hash_frozen_p(hash)
VALUE hash;
{
if (FL_TEST(hash, HASH_FREEZE))
- return TRUE;
- return FALSE;
+ return Qtrue;
+ return Qfalse;
}
-#ifndef NT
-char *getenv();
-#endif
-
-VALUE cHash;
+VALUE rb_cHash;
static VALUE envtbl;
static ID hash;
@@ -69,14 +64,14 @@ rb_hash(obj)
}
static int
-any_cmp(a, b)
+rb_any_cmp(a, b)
VALUE a, b;
{
if (FIXNUM_P(a)) {
if (FIXNUM_P(b)) return a != b;
}
else if (TYPE(a) == T_STRING) {
- if (TYPE(b) == T_STRING) return str_cmp(a, b);
+ if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
}
DEFER_INTS;
@@ -86,9 +81,8 @@ any_cmp(a, b)
}
static int
-any_hash(a, mod)
+rb_any_hash(a)
VALUE a;
- int mod;
{
unsigned int hval;
@@ -98,7 +92,7 @@ any_hash(a, mod)
break;
case T_STRING:
- hval = str_hash(a);
+ hval = rb_str_hash(a);
break;
default:
@@ -108,161 +102,181 @@ any_hash(a, mod)
hval = rb_funcall(hval, '%', 1, INT2FIX(65439));
}
ENABLE_INTS;
- hval = FIX2INT(hval);
+ hval = FIX2LONG(hval);
}
- return hval % mod;
+ return hval;
}
static struct st_hash_type objhash = {
- any_cmp,
- any_hash,
+ rb_any_cmp,
+ rb_any_hash,
};
-struct hash_foreach_arg {
+struct rb_hash_foreach_arg {
VALUE hash;
enum st_retval (*func)();
char *arg;
};
static int
-hash_foreach_iter(key, value, arg)
+rb_hash_foreach_iter(key, value, arg)
VALUE key, value;
- struct hash_foreach_arg *arg;
+ struct rb_hash_foreach_arg *arg;
{
int status;
+ st_table *tbl = RHASH(arg->hash)->tbl;
+ struct st_table_entry **bins = tbl->bins;
if (key == Qnil) return ST_CONTINUE;
status = (*arg->func)(key, value, arg->arg);
- if (RHASH(arg->hash)->status & HASH_REHASHED) return ST_STOP;
+ if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){
+ rb_raise(rb_eIndexError, "rehash occurred during iteration");
+ }
return status;
}
static VALUE
-hash_foreach_call(arg)
- struct hash_foreach_arg *arg;
+rb_hash_foreach_call(arg)
+ struct rb_hash_foreach_arg *arg;
{
- st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, arg);
+ st_foreach(RHASH(arg->hash)->tbl, rb_hash_foreach_iter, arg);
return Qnil;
}
static int
-hash_delete_nil(key, value)
+rb_hash_delete_nil(key, value)
VALUE key, value;
{
- if (key == Qnil) return ST_DELETE;
+ if (value == Qnil) return ST_DELETE;
return ST_CONTINUE;
}
-static void
-hash_foreach_ensure(hash)
+static VALUE
+rb_hash_foreach_ensure(hash)
VALUE hash;
{
RHASH(hash)->iter_lev--;
if (RHASH(hash)->iter_lev == 0) {
- if (RHASH(hash)->status & HASH_DELETED) {
- st_foreach(RHASH(hash)->tbl, hash_delete_nil, 0);
+ if (FL_TEST(hash, HASH_DELETED)) {
+ st_foreach(RHASH(hash)->tbl, rb_hash_delete_nil, 0);
+ FL_UNSET(hash, HASH_DELETED);
}
- RHASH(hash)->status = 0;
}
+ return 0;
}
static int
-hash_foreach(hash, func, farg)
+rb_hash_foreach(hash, func, farg)
VALUE hash;
enum st_retval (*func)();
char *farg;
{
- struct hash_foreach_arg arg;
+ struct rb_hash_foreach_arg arg;
RHASH(hash)->iter_lev++;
arg.hash = hash;
arg.func = func;
arg.arg = farg;
- return rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, (VALUE)hash);
+ return rb_ensure(rb_hash_foreach_call, (VALUE)&arg, rb_hash_foreach_ensure, hash);
}
static VALUE
-hash_s_new(argc, argv, class)
+rb_hash_s_new(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
- VALUE sz;
+ VALUE sz, ifnone;
int size;
NEWOBJ(hash, struct RHash);
- OBJSETUP(hash, class, T_HASH);
-
- rb_scan_args(argc, argv, "01", &sz);
- if (NIL_P(sz)) size = 0;
- else size = NUM2INT(sz);
+ OBJSETUP(hash, klass, T_HASH);
hash->iter_lev = 0;
- hash->status = 0;
+ hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */
+
+ rb_scan_args(argc, argv, "02", &ifnone, &sz);
+ if (NIL_P(sz)) {
+ size = 0;
+ }
+ else size = NUM2INT(sz);
+
+ hash->ifnone = ifnone;
hash->tbl = st_init_table_with_size(&objhash, size);
+ rb_obj_call_init((VALUE)hash);
return (VALUE)hash;
}
static VALUE
-hash_new2(class)
- VALUE class;
+rb_hash_new2(klass)
+ VALUE klass;
{
- return hash_s_new(0, 0, class);
+ NEWOBJ(hash, struct RHash);
+ OBJSETUP(hash, klass, T_HASH);
+
+ hash->iter_lev = 0;
+ hash->ifnone = Qnil;
+ hash->tbl = 0; /* avoid GC crashing */
+ hash->tbl = st_init_table(&objhash);
+
+ return (VALUE)hash;
}
VALUE
-hash_new()
+rb_hash_new()
{
- return hash_new2(cHash);
+ return rb_hash_new2(rb_cHash);
}
static VALUE
-hash_s_create(argc, argv, class)
+rb_hash_s_create(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
VALUE hash;
int i;
if (argc == 1 && TYPE(argv[0]) == T_HASH) {
- if (class == CLASS_OF(argv[0])) return argv[0];
+ if (klass == CLASS_OF(argv[0])) return argv[0];
else {
NEWOBJ(hash, struct RHash);
- OBJSETUP(hash, class, T_HASH);
+ OBJSETUP(hash, klass, T_HASH);
hash->iter_lev = 0;
- hash->status = 0;
+ hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */
hash->tbl = (st_table*)st_copy(RHASH(argv[0])->tbl);
+ rb_obj_call_init((VALUE)hash);
return (VALUE)hash;
}
}
if (argc % 2 != 0) {
- ArgError("odd number args for Hash");
+ rb_raise(rb_eArgError, "odd number args for Hash");
}
- hash = hash_new2(class);
+ hash = rb_hash_new2(klass);
for (i=0; i<argc; i+=2) {
st_insert(RHASH(hash)->tbl, argv[i], argv[i+1]);
}
+ rb_obj_call_init(hash);
return hash;
}
static VALUE
-hash_clone(hash)
+rb_hash_clone(hash)
VALUE hash;
{
NEWOBJ(hash2, struct RHash);
CLONESETUP(hash2, hash);
hash2->iter_lev = 0;
- hash2->status = 0;
+ hash2->ifnone = RHASH(hash)->ifnone;
hash2->tbl = 0; /* avoid GC crashing */
hash2->tbl = (st_table*)st_copy(RHASH(hash)->tbl);
@@ -270,22 +284,29 @@ hash_clone(hash)
}
static VALUE
-hash_dup(hash)
+rb_hash_dup(hash)
VALUE hash;
{
NEWOBJ(hash2, struct RHash);
OBJSETUP(hash2, CLASS_OF(hash), T_HASH);
hash2->iter_lev = 0;
- hash2->status = 0;
+ hash2->ifnone = RHASH(hash)->ifnone;
hash2->tbl = 0; /* avoid GC crashing */
hash2->tbl = (st_table*)st_copy(RHASH(hash)->tbl);
return (VALUE)hash2;
}
+static VALUE
+to_hash(hash)
+ VALUE hash;
+{
+ return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
+}
+
static int
-hash_rehash_i(key, value, tbl)
+rb_hash_rehash_i(key, value, tbl)
VALUE key, value;
st_table *tbl;
{
@@ -296,34 +317,71 @@ hash_rehash_i(key, value, tbl)
}
static VALUE
-hash_rehash(hash)
+rb_hash_rehash(hash)
VALUE hash;
{
st_table *tbl;
tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries);
- st_foreach(RHASH(hash)->tbl, hash_rehash_i, tbl);
+ st_foreach(RHASH(hash)->tbl, rb_hash_rehash_i, tbl);
st_free_table(RHASH(hash)->tbl);
RHASH(hash)->tbl = tbl;
- if (RHASH(hash)->iter_lev > 0) RHASH(hash)->status |= HASH_REHASHED;
- return (VALUE)hash;
+ return hash;
}
VALUE
-hash_aref(hash, key)
+rb_hash_aref(hash, key)
VALUE hash, key;
{
VALUE val;
if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
- return Qnil;
+ return RHASH(hash)->ifnone;
}
return val;
}
static VALUE
-hash_indexes(argc, argv, hash)
+rb_hash_fetch(argc, argv, hash)
+ int argc;
+ VALUE *argv;
+ VALUE hash;
+{
+ VALUE key, if_none;
+ VALUE val;
+
+ rb_scan_args(argc, argv, "11", &key, &if_none);
+
+ if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
+ if (rb_iterator_p()) {
+ if (argc > 1) {
+ rb_raise(rb_eArgError, "wrong # of arguments", argc);
+ }
+ return rb_yield(argv[0]);
+ }
+ return if_none;
+ }
+ return val;
+}
+
+static VALUE
+rb_hash_default(hash)
+ VALUE hash;
+{
+ return RHASH(hash)->ifnone;
+}
+
+static VALUE
+rb_hash_set_default(hash, ifnone)
+ VALUE hash, ifnone;
+{
+ RHASH(hash)->ifnone = ifnone;
+ return hash;
+}
+
+static VALUE
+rb_hash_indexes(argc, argv, hash)
int argc;
VALUE *argv;
VALUE hash;
@@ -331,27 +389,31 @@ hash_indexes(argc, argv, hash)
VALUE indexes;
int i;
- indexes = ary_new2(argc);
+ indexes = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- RARRAY(indexes)->ptr[i] = hash_aref(hash, argv[i]);
+ RARRAY(indexes)->ptr[i] = rb_hash_aref(hash, argv[i]);
}
RARRAY(indexes)->len = i;
return indexes;
}
static VALUE
-hash_delete(hash, key)
+rb_hash_delete(hash, key)
VALUE hash, key;
{
VALUE val;
- hash_modify(hash);
- if (RHASH(hash)->iter_lev > 0
- && st_delete_safe(RHASH(hash)->tbl, &key, &val, Qnil))
+ rb_hash_modify(hash);
+ if (RHASH(hash)->iter_lev > 0 &&
+ st_delete_safe(RHASH(hash)->tbl, &key, &val, Qnil)) {
+ FL_SET(hash, HASH_DELETED);
return val;
+ }
else if (st_delete(RHASH(hash)->tbl, &key, &val))
return val;
- if (iterator_p()) rb_yield(key);
+ if (rb_iterator_p()) {
+ return rb_yield(key);
+ }
return Qnil;
}
@@ -375,17 +437,17 @@ shift_i(key, value, var)
}
static VALUE
-hash_shift(hash)
+rb_hash_shift(hash)
VALUE hash;
{
struct shift_var var;
- hash_modify(hash);
+ rb_hash_modify(hash);
var.stop = 0;
st_foreach(RHASH(hash)->tbl, shift_i, &var);
if (var.stop == 0) return Qnil;
- return assoc_new(var.key, var.val);
+ return rb_assoc_new(var.key, var.val);
}
static int
@@ -393,19 +455,19 @@ delete_if_i(key, value)
VALUE key, value;
{
if (key == Qnil) return ST_CONTINUE;
- if (rb_yield(assoc_new(key, value)))
+ if (rb_yield(rb_assoc_new(key, value)))
return ST_DELETE;
return ST_CONTINUE;
}
static VALUE
-hash_delete_if(hash)
+rb_hash_delete_if(hash)
VALUE hash;
{
- hash_modify(hash);
- hash_foreach(hash, delete_if_i, 0);
+ rb_hash_modify(hash);
+ rb_hash_foreach(hash, delete_if_i, 0);
- return (VALUE)hash;
+ return hash;
}
static int
@@ -416,45 +478,66 @@ clear_i(key, value)
}
static VALUE
-hash_clear(hash)
+rb_hash_clear(hash)
VALUE hash;
{
- hash_modify(hash);
+ rb_hash_modify(hash);
st_foreach(RHASH(hash)->tbl, clear_i);
- return (VALUE)hash;
+ return hash;
}
VALUE
-hash_aset(hash, key, val)
+rb_hash_aset(hash, key, val)
VALUE hash, key, val;
{
- hash_modify(hash);
+ rb_hash_modify(hash);
if (NIL_P(val)) {
- hash_delete(hash, key);
+ rb_hash_delete(hash, key);
return Qnil;
}
- if (TYPE(key) == T_STRING) {
- key = str_dup_freezed(key);
+ if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) {
+ st_insert(RHASH(hash)->tbl, key, val);
+ }
+ else {
+ st_add_direct(RHASH(hash)->tbl, rb_str_dup_frozen(key), val);
}
- st_insert(RHASH(hash)->tbl, key, val);
return val;
}
+static int
+replace_i(key, val, hash)
+ VALUE key, val, hash;
+{
+ rb_hash_aset(hash, key, val);
+ return ST_CONTINUE;
+}
+
static VALUE
-hash_length(hash)
+rb_hash_replace(hash, hash2)
+ VALUE hash, hash2;
+{
+ hash2 = to_hash(hash2);
+ rb_hash_clear(hash);
+ st_foreach(RHASH(hash2)->tbl, replace_i, hash);
+
+ return hash;
+}
+
+static VALUE
+rb_hash_length(hash)
VALUE hash;
{
return INT2FIX(RHASH(hash)->tbl->num_entries);
}
static VALUE
-hash_empty_p(hash)
+rb_hash_empty_p(hash)
VALUE hash;
{
if (RHASH(hash)->tbl->num_entries == 0)
- return TRUE;
- return FALSE;
+ return Qtrue;
+ return Qfalse;
}
static int
@@ -467,11 +550,11 @@ each_value_i(key, value)
}
static VALUE
-hash_each_value(hash)
+rb_hash_each_value(hash)
VALUE hash;
{
- hash_foreach(hash, each_value_i);
- return (VALUE)hash;
+ rb_hash_foreach(hash, each_value_i, 0);
+ return hash;
}
static int
@@ -484,11 +567,11 @@ each_key_i(key, value)
}
static VALUE
-hash_each_key(hash)
+rb_hash_each_key(hash)
VALUE hash;
{
- hash_foreach(hash, each_key_i);
- return (VALUE)hash;
+ rb_hash_foreach(hash, each_key_i, 0);
+ return hash;
}
static int
@@ -496,16 +579,16 @@ each_pair_i(key, value)
VALUE key, value;
{
if (key == Qnil) return ST_CONTINUE;
- rb_yield(assoc_new(key, value));
+ rb_yield(rb_assoc_new(key, value));
return ST_CONTINUE;
}
static VALUE
-hash_each_pair(hash)
+rb_hash_each_pair(hash)
VALUE hash;
{
- hash_foreach(hash, each_pair_i);
- return (VALUE)hash;
+ rb_hash_foreach(hash, each_pair_i, 0);
+ return hash;
}
static int
@@ -513,22 +596,29 @@ to_a_i(key, value, ary)
VALUE key, value, ary;
{
if (key == Qnil) return ST_CONTINUE;
- ary_push(ary, assoc_new(key, value));
+ rb_ary_push(ary, rb_assoc_new(key, value));
return ST_CONTINUE;
}
static VALUE
-hash_to_a(hash)
+rb_hash_to_a(hash)
VALUE hash;
{
VALUE ary;
- ary = ary_new();
+ ary = rb_ary_new();
st_foreach(RHASH(hash)->tbl, to_a_i, ary);
return ary;
}
+static VALUE
+rb_hash_sort(hash)
+ VALUE hash;
+{
+ return rb_ary_sort_bang(rb_hash_to_a(hash));
+}
+
static int
inspect_i(key, value, str)
VALUE key, value, str;
@@ -537,35 +627,60 @@ inspect_i(key, value, str)
if (key == Qnil) return ST_CONTINUE;
if (RSTRING(str)->len > 1) {
- str_cat(str, ", ", 2);
+ rb_str_cat(str, ", ", 2);
}
str2 = rb_inspect(key);
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
- str_cat(str, "=>", 2);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_cat(str, "=>", 2);
str2 = rb_inspect(value);
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return ST_CONTINUE;
}
static VALUE
-hash_inspect(hash)
+inspect_hash(hash)
VALUE hash;
{
VALUE str;
- str = str_new2("{");
+ str = rb_str_new2("{");
st_foreach(RHASH(hash)->tbl, inspect_i, str);
- str_cat(str, "}", 1);
+ rb_str_cat(str, "}", 1);
return str;
}
static VALUE
+rb_hash_inspect(hash)
+ VALUE hash;
+{
+ if (RHASH(hash)->tbl->num_entries == 0) return rb_str_new2("{}");
+ if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
+ return rb_protect_inspect(inspect_hash, hash, 0);
+}
+
+static VALUE
hash_to_s(hash)
VALUE hash;
{
- return ary_to_s(hash_to_a(hash));
+ if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
+ return rb_ary_to_s(rb_hash_to_a(hash));
+}
+
+static VALUE
+rb_hash_to_s(hash)
+ VALUE hash;
+{
+ if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
+ return rb_protect_inspect(hash_to_s, hash, 0);
+}
+
+static VALUE
+rb_hash_to_hash(hash)
+ VALUE hash;
+{
+ return hash;
}
static int
@@ -573,17 +688,17 @@ keys_i(key, value, ary)
VALUE key, value, ary;
{
if (key == Qnil) return ST_CONTINUE;
- ary_push(ary, key);
+ rb_ary_push(ary, key);
return ST_CONTINUE;
}
static VALUE
-hash_keys(hash)
+rb_hash_keys(hash)
VALUE hash;
{
VALUE ary;
- ary = ary_new();
+ ary = rb_ary_new();
st_foreach(RHASH(hash)->tbl, keys_i, ary);
return ary;
@@ -594,55 +709,55 @@ values_i(key, value, ary)
VALUE key, value, ary;
{
if (key == Qnil) return ST_CONTINUE;
- ary_push(ary, value);
+ rb_ary_push(ary, value);
return ST_CONTINUE;
}
static VALUE
-hash_values(hash)
+rb_hash_values(hash)
VALUE hash;
{
VALUE ary;
- ary = ary_new();
+ ary = rb_ary_new();
st_foreach(RHASH(hash)->tbl, values_i, ary);
return ary;
}
static VALUE
-hash_has_key(hash, key)
+rb_hash_has_key(hash, key)
VALUE hash;
VALUE key;
{
if (st_lookup(RHASH(hash)->tbl, key, 0)) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static int
-hash_search_value(key, value, data)
+rb_hash_search_value(key, value, data)
VALUE key, value, *data;
{
if (key == Qnil) return ST_CONTINUE;
if (rb_equal(value, data[1])) {
- data[0] = TRUE;
+ data[0] = Qtrue;
return ST_STOP;
}
return ST_CONTINUE;
}
static VALUE
-hash_has_value(hash, val)
+rb_hash_has_value(hash, val)
VALUE hash;
VALUE val;
{
VALUE data[2];
- data[0] = FALSE;
+ data[0] = Qfalse;
data[1] = val;
- st_foreach(RHASH(hash)->tbl, hash_search_value, data);
+ st_foreach(RHASH(hash)->tbl, rb_hash_search_value, data);
return data[0];
}
@@ -660,79 +775,79 @@ equal_i(key, val1, data)
if (key == Qnil) return ST_CONTINUE;
if (!st_lookup(data->tbl, key, &val2)) {
- data->result = FALSE;
+ data->result = Qfalse;
return ST_STOP;
}
if (!rb_equal(val1, val2)) {
- data->result = FALSE;
+ data->result = Qfalse;
return ST_STOP;
}
return ST_CONTINUE;
}
static VALUE
-hash_equal(hash1, hash2)
+rb_hash_equal(hash1, hash2)
VALUE hash1, hash2;
{
struct equal_data data;
- if (TYPE(hash2) != T_HASH) return FALSE;
+ if (TYPE(hash2) != T_HASH) return Qfalse;
if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
- return FALSE;
+ return Qfalse;
data.tbl = RHASH(hash2)->tbl;
- data.result = TRUE;
+ data.result = Qtrue;
st_foreach(RHASH(hash1)->tbl, equal_i, &data);
return data.result;
}
static int
-hash_invert_i(key, value, hash)
+rb_hash_invert_i(key, value, hash)
VALUE key, value;
VALUE hash;
{
if (key == Qnil) return ST_CONTINUE;
- hash_aset(hash, value, key);
+ rb_hash_aset(hash, value, key);
return ST_CONTINUE;
}
static VALUE
-hash_invert(hash)
+rb_hash_invert(hash)
VALUE hash;
{
- VALUE h = hash_new();
+ VALUE h = rb_hash_new();
- st_foreach(RHASH(hash)->tbl, hash_invert_i, h);
+ st_foreach(RHASH(hash)->tbl, rb_hash_invert_i, h);
return h;
}
static int
-hash_update_i(key, value, hash)
+rb_hash_update_i(key, value, hash)
VALUE key, value;
VALUE hash;
{
if (key == Qnil) return ST_CONTINUE;
- hash_aset(hash, key, value);
+ rb_hash_aset(hash, key, value);
return ST_CONTINUE;
}
static VALUE
-hash_update(hash1, hash2)
+rb_hash_update(hash1, hash2)
VALUE hash1, hash2;
{
- Check_Type(hash2, T_HASH);
-
- st_foreach(RHASH(hash2)->tbl, hash_update_i, hash1);
+ hash2 = to_hash(hash2);
+ st_foreach(RHASH(hash2)->tbl, rb_hash_update_i, hash1);
return hash1;
}
-int env_path_tainted();
+#ifndef __MACOS__ /* no environment variables on MacOS. */
static int path_tainted = -1;
#ifndef NT
extern char **environ;
#endif
+static char **origenviron;
static VALUE
env_delete(obj, name)
@@ -742,10 +857,9 @@ env_delete(obj, name)
char *nam, *val = 0;
rb_secure(4);
- Check_Type(name, T_STRING);
- nam = RSTRING(name)->ptr;
- len = strlen(nam);
+ nam = STR2CSTR(name);
if (strcmp(nam, "PATH") == 0) path_tainted = 0;
+ len = strlen(nam);
for(i=0; environ[i]; i++) {
if (strncmp(environ[i], nam, len) == 0 && environ[i][len] == '=') {
val = environ[i]+len+1;
@@ -757,7 +871,7 @@ env_delete(obj, name)
i++;
}
if (val) {
- return str_new2(val);
+ return rb_str_new2(val);
}
return Qnil;
}
@@ -767,26 +881,26 @@ env_delete_method(obj, name)
VALUE obj, name;
{
VALUE val = env_delete(obj, name);
- if (iterator_p()) rb_yield(name);
+ if (rb_iterator_p()) rb_yield(name);
return val;
}
static VALUE
-f_getenv(obj, name)
+rb_f_getenv(obj, name)
VALUE obj, name;
{
- char *env;
+ char *nam, *env;
+ int len;
- Check_Type(name, T_STRING);
-
- if (strlen(RSTRING(name)->ptr) != RSTRING(name)->len)
- ArgError("Bad environment name");
-
- env = getenv(RSTRING(name)->ptr);
+ nam = str2cstr(name, &len);
+ if (strlen(nam) != len) {
+ rb_raise(rb_eArgError, "Bad environment variable name");
+ }
+ env = getenv(nam);
if (env) {
- if (strcmp(RSTRING(name)->ptr, "PATH") == 0 && !env_path_tainted())
- return str_new2(env);
- return str_taint(str_new2(env));
+ if (strcmp(nam, "PATH") == 0 && !rb_env_path_tainted())
+ return rb_str_new2(env);
+ return rb_tainted_str_new2(env);
}
return Qnil;
}
@@ -800,7 +914,7 @@ path_check_1(path)
char *s;
for (;;) {
- if (stat(path, &st) == 0 && (st.st_mode & 2)) {
+ if (stat(path, &st) == 0 && (st.st_mode & 002)) {
return 0;
}
s = strrchr(path, '/');
@@ -811,19 +925,17 @@ path_check_1(path)
}
}
-static void
-path_check(path)
+int
+rb_path_check(path)
char *path;
{
- char *p = path;
- char *pend = strchr(path, ':');
+ char *p, *pend;
+ const char sep = RUBY_PATH_SEP[0];
- if (!path) {
- path_tainted = 0;
- }
+ if (!path) return 1;
p = path;
- pend = strchr(path, ':');
+ pend = strchr(path, sep);
for (;;) {
int safe;
@@ -831,72 +943,207 @@ path_check(path)
if (pend) *pend = '\0';
safe = path_check_1(p);
if (!pend) break;
- *pend = ':';
+ *pend = sep;
if (!safe) {
- path_tainted = 1;
- return;
+ return 0;
}
p = pend + 1;
- pend = strchr(p, ':');
+ pend = strchr(p, sep);
}
- path_tainted = 0;
+ return 1;
+}
+
+static void
+path_tainted_p(path)
+ char *path;
+{
+ path_tainted = rb_path_check(path)?0:1;
}
int
-env_path_tainted()
+rb_env_path_tainted()
{
if (path_tainted < 0) {
- path_check(getenv("PATH"));
+ path_tainted_p(getenv("PATH"));
}
return path_tainted;
}
+static int
+envix(nam)
+char *nam;
+{
+ register int i, len = strlen(nam);
+
+ for (i = 0; environ[i]; i++) {
+ if (
+#ifdef WIN32
+ strnicmp(environ[i],nam,len) == 0
+#else
+ memcmp(environ[i],nam,len) == 0
+#endif
+ && environ[i][len] == '=')
+ break; /* memcmp must come first to avoid */
+ } /* potential SEGV's */
+ return i;
+}
+
+static void
+my_setenv(name, value)
+ char *name;
+ char *value;
+{
+#ifdef WIN32
+#ifdef USE_WIN32_RTL_ENV
+ register char *envstr;
+ STRLEN namlen = strlen(name);
+ STRLEN vallen;
+ char *oldstr = environ[envix(name)];
+
+ /* putenv() has totally broken semantics in both the Borland
+ * and Microsoft CRTLs. They either store the passed pointer in
+ * the environment without making a copy, or make a copy and don't
+ * free it. And on top of that, they dont free() old entries that
+ * are being replaced/deleted. This means the caller must
+ * free any old entries somehow, or we end up with a memory
+ * leak every time setenv() is called. One might think
+ * one could directly manipulate environ[], like the UNIX code
+ * above, but direct changes to environ are not allowed when
+ * calling putenv(), since the RTLs maintain an internal
+ * *copy* of environ[]. Bad, bad, *bad* stink.
+ * GSAR 97-06-07
+ */
+
+ if (!value) {
+ if (!oldstr)
+ return;
+ value = "";
+ vallen = 0;
+ }
+ else
+ vallen = strlen(val);
+ envstr = ALLOC_N(char, namelen + vallen + 3);
+ sprintf(envstr,"%s=%s",name,value);
+ putenv(envstr);
+ if (oldstr) free(oldstr);
+#ifdef _MSC_VER
+ free(envstr); /* MSVCRT leaks without this */
+#endif
+
+#else /* !USE_WIN32_RTL_ENV */
+
+ /* The sane way to deal with the environment.
+ * Has these advantages over putenv() & co.:
+ * * enables us to store a truly empty value in the
+ * environment (like in UNIX).
+ * * we don't have to deal with RTL globals, bugs and leaks.
+ * * Much faster.
+ * Why you may want to enable USE_WIN32_RTL_ENV:
+ * * environ[] and RTL functions will not reflect changes,
+ * which might be an issue if extensions want to access
+ * the env. via RTL. This cuts both ways, since RTL will
+ * not see changes made by extensions that call the Win32
+ * functions directly, either.
+ * GSAR 97-06-07
+ */
+ SetEnvironmentVariable(name,value);
+#endif
+
+#else /* WIN32 */
+
+ register int i=envix(name); /* where does it go? */
+
+ if (environ == origenviron) { /* need we copy environment? */
+ int j;
+ int max;
+ char **tmpenv;
+
+ for (max = i; environ[max]; max++) ;
+ tmpenv = ALLOC_N(char*, max+2);
+ for (j=0; j<max; j++) /* copy environment */
+ tmpenv[j] = strdup(environ[j]);
+ tmpenv[max] = 0;
+ environ = tmpenv; /* tell exec where it is now */
+ }
+ if (!value) {
+ while (environ[i]) {
+ environ[i] = environ[i+1];
+ i++;
+ }
+ return;
+ }
+ if (!environ[i]) { /* does not exist yet */
+ REALLOC_N(environ, char*, i+2); /* just expand it a bit */
+ environ[i+1] = 0; /* make sure it's null terminated */
+ }
+ else {
+ free(environ[i]);
+ }
+ environ[i] = ALLOC_N(char, strlen(name) + strlen(value) + 2);
+#ifndef MSDOS
+ sprintf(environ[i],"%s=%s",name,value); /* all that work just for this */
+#else
+ /* MS-DOS requires environment variable names to be in uppercase */
+ /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
+ * some utilities and applications may break because they only look
+ * for upper case strings. (Fixed strupr() bug here.)]
+ */
+ strcpy(environ[i],name); strupr(environ[i]);
+ sprintf(environ[i] + strlen(name),"=%s", value);
+#endif /* MSDOS */
+
+#endif /* WIN32 */
+}
+
static VALUE
-f_setenv(obj, name, value)
- VALUE obj, name, value;
+rb_f_setenv(obj, nm, val)
+ VALUE obj, nm, val;
{
+ char *name, *value;
+ int nlen, vlen;
+
if (rb_safe_level() >= 4) {
- extern VALUE eSecurityError;
- Raise(eSecurityError, "cannot change environment variable");
+ rb_raise(rb_eSecurityError, "cannot change environment variable");
}
- Check_SafeStr(name);
- if (NIL_P(value)) {
- env_delete(obj, name);
+ if (NIL_P(val)) {
+ env_delete(obj, nm);
return Qnil;
}
- Check_SafeStr(value);
- if (strlen(RSTRING(name)->ptr) != RSTRING(name)->len)
- ArgError("Bad environment name");
- if (strlen(RSTRING(value)->ptr) != RSTRING(value)->len)
- ArgError("Bad environment value");
+ name = str2cstr(nm, &nlen);
+ value = STR2CSTR(val &vlen);
+ if (strlen(name) != nlen)
+ rb_raise(rb_eArgError, "Bad environment name");
+ if (strlen(value) != vlen)
+ rb_raise(rb_eArgError, "Bad environment value");
- setenv(RSTRING(name)->ptr, RSTRING(value)->ptr, 1);
- if (strcmp(RSTRING(name)->ptr, "PATH") == 0) {
- char *p, pend;
-
- if (str_tainted(value)) {
+ my_setenv(name, value);
+ if (strcmp(name, "PATH") == 0) {
+ if (OBJ_TAINTED(val)) {
/* already tainted, no check */
path_tainted = 1;
- return TRUE;
+ return Qtrue;
+ }
+ else {
+ path_tainted_p(value);
}
-
- path_check(RSTRING(name)->ptr);
}
- return TRUE;
+ return Qtrue;
}
static VALUE
env_keys()
{
char **env;
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- ary_push(ary, str_taint(str_new(*env, s-*env)));
+ if (s) {
+ rb_ary_push(ary, rb_tainted_str_new(*env, s-*env));
+ }
env++;
}
return ary;
@@ -906,19 +1153,31 @@ static VALUE
env_each_key(hash)
VALUE hash;
{
- return ary_each(env_keys());
+ char **env;
+
+ env = environ;
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_yield(rb_tainted_str_new(*env, s-*env));
+ }
+ env++;
+ }
+ return Qnil;
}
static VALUE
env_values()
{
char **env;
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- ary_push(ary, str_taint(str_new2(s+1)));
+ if (s) {
+ rb_ary_push(ary, rb_tainted_str_new2(s+1));
+ }
env++;
}
return ary;
@@ -928,38 +1187,53 @@ static VALUE
env_each_value(hash)
VALUE hash;
{
- return ary_each(env_values());
+ char **env;
+
+ env = environ;
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_yield(rb_tainted_str_new2(s+1));
+ }
+ env++;
+ }
+ return Qnil;
}
static VALUE
env_each(hash)
VALUE hash;
{
- VALUE ary = env_keys();
- VALUE *ptr = RARRAY(ary)->ptr;
- int len = RARRAY(ary)->len;
+ char **env;
- while (len--) {
- VALUE val = f_getenv(Qnil, *ptr);
- if (!NIL_P(val)) {
- rb_yield(assoc_new(*ptr, val));
+ env = environ;
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_yield(rb_assoc_new(rb_tainted_str_new(*env, s-*env),
+ rb_tainted_str_new2(s+1)));
}
- ptr++;
+ env++;
}
- return hash;
+ return Qnil;
}
static VALUE
env_delete_if()
{
- VALUE ary = env_keys();
- VALUE *ptr = RARRAY(ary)->ptr;
- int len = RARRAY(ary)->len;
+ volatile VALUE keys;
+ VALUE *ptr;
+ int len;
+
+ rb_secure(4);
+ keys = env_keys();
+ ptr = RARRAY(keys)->ptr;
+ len = RARRAY(keys)->len;
while (len--) {
- VALUE val = f_getenv(Qnil, *ptr);
+ VALUE val = rb_f_getenv(Qnil, *ptr);
if (!NIL_P(val)) {
- if (RTEST(rb_yield(assoc_new(*ptr, val)))) {
+ if (RTEST(rb_yield(rb_assoc_new(*ptr, val)))) {
env_delete(Qnil, *ptr);
}
}
@@ -971,20 +1245,22 @@ env_delete_if()
static VALUE
env_to_s()
{
- return str_new2("ENV");
+ return rb_str_new2("ENV");
}
static VALUE
env_to_a()
{
char **env;
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- ary_push(ary, assoc_new(str_taint(str_new(*env, s-*env)),
- str_taint(str_new2(s+1))));
+ if (s) {
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(*env, s-*env),
+ rb_tainted_str_new2(s+1)));
+ }
env++;
}
return ary;
@@ -1009,17 +1285,17 @@ env_size()
static VALUE
env_empty_p()
{
- if (environ[0] == 0) return TRUE;
- return FALSE;
+ if (environ[0] == 0) return Qtrue;
+ return Qfalse;
}
static VALUE
env_has_key(env, key)
VALUE env, key;
{
- if (TYPE(key) != T_STRING) return FALSE;
- if (getenv(RSTRING(key)->ptr)) return TRUE;
- return FALSE;
+ if (TYPE(key) != T_STRING) return Qfalse;
+ if (getenv(STR2CSTR(key))) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -1027,18 +1303,20 @@ env_has_value(dmy, value)
VALUE dmy, value;
{
char **env;
- VALUE ary;
+ volatile VALUE ary;
- if (TYPE(value) != T_STRING) return FALSE;
- ary = ary_new();
+ if (TYPE(value) != T_STRING) return Qfalse;
+ ary = rb_ary_new();
env = environ;
while (*env) {
char *s = strchr(*env, '=')+1;
- int len = strlen(s);
- if (strncmp(s, RSTRING(value)->ptr, len) == 0) return TRUE;
+ if (s) {
+ if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0)
+ return Qtrue;
+ }
env++;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -1047,7 +1325,7 @@ env_indexes(argc, argv)
VALUE *argv;
{
int i;
- VALUE indexes = ary_new2(argc);
+ VALUE indexes = rb_ary_new2(argc);
for (i=0;i<argc;i++) {
char *v = 0;
@@ -1055,7 +1333,7 @@ env_indexes(argc, argv)
v = getenv(RSTRING(argv[i])->ptr);
}
if (v) {
- RARRAY(indexes)->ptr[i] = str_new2(v);
+ RARRAY(indexes)->ptr[i] = rb_tainted_str_new2(v);
}
else {
RARRAY(indexes)->ptr[i] = Qnil;
@@ -1066,65 +1344,94 @@ env_indexes(argc, argv)
return indexes;
}
-void
-Init_Hash()
+static VALUE
+env_to_hash(obj)
+ VALUE obj;
{
- extern VALUE mEnumerable;
-
- hash = rb_intern("hash");
-
- cHash = rb_define_class("Hash", cObject);
-
- rb_include_module(cHash, mEnumerable);
-
- rb_define_singleton_method(cHash, "new", hash_s_new, -1);
- rb_define_singleton_method(cHash, "[]", hash_s_create, -1);
-
- rb_define_method(cHash,"clone", hash_clone, 0);
- rb_define_method(cHash,"dup", hash_dup, 0);
- rb_define_method(cHash,"rehash", hash_rehash, 0);
-
- rb_define_method(cHash,"freeze", hash_freeze, 0);
- rb_define_method(cHash,"frozen?",hash_frozen_p, 0);
-
- rb_define_method(cHash,"to_a", hash_to_a, 0);
- rb_define_method(cHash,"to_s", hash_to_s, 0);
- rb_define_method(cHash,"inspect", hash_inspect, 0);
-
- rb_define_method(cHash,"==", hash_equal, 1);
- rb_define_method(cHash,"[]", hash_aref, 1);
- rb_define_method(cHash,"[]=", hash_aset, 2);
- rb_define_method(cHash,"indexes", hash_indexes, -1);
- rb_define_method(cHash,"length", hash_length, 0);
- rb_define_alias(cHash, "size", "length");
- rb_define_method(cHash,"empty?", hash_empty_p, 0);
-
- rb_define_method(cHash,"each", hash_each_pair, 0);
- rb_define_method(cHash,"each_value", hash_each_value, 0);
- rb_define_method(cHash,"each_key", hash_each_key, 0);
- rb_define_method(cHash,"each_pair", hash_each_pair, 0);
-
- rb_define_method(cHash,"keys", hash_keys, 0);
- rb_define_method(cHash,"values", hash_values, 0);
+ char **env;
+ VALUE hash = rb_hash_new();
- rb_define_method(cHash,"shift", hash_shift, 0);
- rb_define_method(cHash,"delete", hash_delete, 1);
- rb_define_method(cHash,"delete_if", hash_delete_if, 0);
- rb_define_method(cHash,"clear", hash_clear, 0);
- rb_define_method(cHash,"invert", hash_invert, 0);
- rb_define_method(cHash,"update", hash_update, 1);
+ env = environ;
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_hash_aset(hash, rb_tainted_str_new(*env, s-*env),
+ rb_tainted_str_new2(s+1));
+ }
+ env++;
+ }
+ return hash;
+}
- rb_define_method(cHash,"include?", hash_has_key, 1);
- rb_define_method(cHash,"has_key?", hash_has_key, 1);
- rb_define_method(cHash,"has_value?", hash_has_value, 1);
- rb_define_method(cHash,"key?", hash_has_key, 1);
- rb_define_method(cHash,"value?", hash_has_value, 1);
+#endif /* ifndef __MACOS__ no environment variables on MacOS. */
- envtbl = obj_alloc(cObject);
- rb_extend_object(envtbl, mEnumerable);
+void
+Init_Hash()
+{
+ hash = rb_intern("hash");
- rb_define_singleton_method(envtbl,"[]", f_getenv, 1);
- rb_define_singleton_method(envtbl,"[]=", f_setenv, 2);
+ rb_cHash = rb_define_class("Hash", rb_cObject);
+
+ rb_include_module(rb_cHash, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cHash, "new", rb_hash_s_new, -1);
+ rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
+
+ rb_define_method(rb_cHash,"clone", rb_hash_clone, 0);
+ rb_define_method(rb_cHash,"dup", rb_hash_dup, 0);
+ rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
+
+ rb_define_method(rb_cHash,"freeze", rb_hash_freeze, 0);
+ rb_define_method(rb_cHash,"frozen?",rb_hash_frozen_p, 0);
+
+ rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
+ rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
+ rb_define_method(rb_cHash,"to_s", rb_hash_to_s, 0);
+ rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
+
+ rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
+ rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
+ rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
+ rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
+ rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
+ rb_define_method(rb_cHash,"default", rb_hash_default, 0);
+ rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
+ rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
+ rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1);
+ rb_define_method(rb_cHash,"length", rb_hash_length, 0);
+ rb_define_alias(rb_cHash, "size", "length");
+ rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0);
+
+ rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0);
+ rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0);
+ rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0);
+ rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
+ rb_define_method(rb_cHash,"sort", rb_hash_sort, 0);
+
+ rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
+ rb_define_method(rb_cHash,"values", rb_hash_values, 0);
+
+ rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
+ rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
+ rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
+ rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
+ rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
+ rb_define_method(rb_cHash,"update", rb_hash_update, 1);
+ rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
+
+ rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
+ rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
+ rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
+ rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
+ rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1);
+
+#ifndef __MACOS__ /* environment variables nothing on MacOS. */
+ origenviron = environ;
+ envtbl = rb_obj_alloc(rb_cObject);
+ rb_extend_object(envtbl, rb_mEnumerable);
+
+ rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1);
+ rb_define_singleton_method(envtbl,"[]=", rb_f_setenv, 2);
rb_define_singleton_method(envtbl,"each", env_each, 0);
rb_define_singleton_method(envtbl,"each_pair", env_each, 0);
rb_define_singleton_method(envtbl,"each_key", env_each_key, 0);
@@ -1135,6 +1442,7 @@ Init_Hash()
rb_define_singleton_method(envtbl,"rehash", env_none, 0);
rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
rb_define_singleton_method(envtbl,"indexes", env_indexes, -1);
+ rb_define_singleton_method(envtbl,"indices", env_indexes, -1);
rb_define_singleton_method(envtbl,"length", env_size, 0);
rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0);
rb_define_singleton_method(envtbl,"keys", env_keys, 0);
@@ -1144,6 +1452,11 @@ Init_Hash()
rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
+ rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
rb_define_global_const("ENV", envtbl);
+#else /* __MACOS__ */
+ envtbl = rb_hash_s_new(0, NULL, rb_cHash);
+ rb_define_global_const("ENV", envtbl);
+#endif /* ifndef __MACOS__ environment variables nothing on MacOS. */
}
diff --git a/inits.c b/inits.c
index 123b32c989..3708edc03a 100644
--- a/inits.c
+++ b/inits.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Dec 28 16:01:58 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -49,14 +49,14 @@ rb_call_inits()
Init_sym();
Init_var_tables();
Init_Object();
- Init_Exception();
-#ifdef THREAD
- Init_Thread();
-#endif
Init_Comparable();
Init_Enumerable();
Init_eval();
Init_String();
+ Init_Exception();
+#ifdef USE_THREAD
+ Init_Thread();
+#endif
Init_Numeric();
Init_Bignum();
Init_Array();
diff --git a/instruby.rb b/instruby.rb
index 8fd77055f2..d489e0f838 100644
--- a/instruby.rb
+++ b/instruby.rb
@@ -1,7 +1,10 @@
-#!./miniruby
+#!./miniruby -I.
+
require "rbconfig.rb"
include Config
+destdir = ARGV[0] || ''
+
$:.unshift CONFIG["srcdir"]+"/lib"
require "ftools"
@@ -12,26 +15,43 @@ else
prefix = CONFIG["prefix"]
end
ruby_install_name = CONFIG["ruby_install_name"]
-bindir = prefix + "/bin"
-libdir = prefix + "/lib/" + ruby_install_name
-archdir = libdir+"/"+CONFIG["arch"]
+bindir = CONFIG["bindir"]
+libdir = CONFIG["libdir"]
+pkglibdir = libdir + "/" + ruby_install_name
+archdir = pkglibdir + "/" + CONFIG["arch"]
mandir = CONFIG["mandir"] + "/man1"
+wdir = Dir.getwd
+File.makedirs "#{destdir}#{bindir}", true
File.install "ruby#{binsuffix}",
- "#{bindir}/#{ruby_install_name}#{binsuffix}", 0755, TRUE
-File.makedirs libdir, TRUE
+ "#{destdir}#{bindir}/#{ruby_install_name}#{binsuffix}", 0755, true
+for dll in Dir['*.dll']
+ File.install dll, "#{destdir}#{bindir}/#{dll}", 0755, true
+end
+File.makedirs "#{destdir}#{libdir}", true
+for lib in ["libruby.so", "libruby.so.LIB"]
+ if File.exist? lib
+ File.install lib, "#{destdir}#{libdir}", 0644, true
+ end
+end
+File.makedirs "#{destdir}#{pkglibdir}", true
+File.makedirs "#{destdir}#{archdir}", true
Dir.chdir "ext"
-system "../miniruby#{binsuffix} extmk.rb install"
+system "../miniruby#{binsuffix} extmk.rb install #{destdir}"
Dir.chdir CONFIG["srcdir"]
-IO.foreach 'MANIFEST' do |$_|
- $_.chop!
- if /^lib/
- File.install $_, libdir, 0644, TRUE
- elsif /^[a-z]+\.h$/
- File.install $_, archdir, 0644, TRUE
- end
- File.install "config.h", archdir, 0644, TRUE
+for f in Dir["lib/*.rb"]
+ File.install f, "#{destdir}#{pkglibdir}", 0644, true
+end
+
+File.makedirs(archdir,true)
+for f in Dir["*.h"]
+ File.install f, "#{destdir}#{archdir}", 0644, true
end
-File.install "rbconfig.rb", archdir, 0644, TRUE
-File.install "ruby.1", mandir, 0644, TRUE
+File.install "libruby.a", "#{destdir}#{archdir}", 0644, true
+
+File.makedirs "#{destdir}#{mandir}", true
+File.install "ruby.1", "#{destdir}#{mandir}", 0644, true
+Dir.chdir wdir
+File.install "config.h", "#{destdir}#{archdir}", 0644, true
+File.install "rbconfig.rb", "#{destdir}#{archdir}", 0644, true
# vi:set sw=2:
diff --git a/intern.h b/intern.h
index 192da014d5..8b88751469 100644
--- a/intern.h
+++ b/intern.h
@@ -3,289 +3,321 @@
*/
/* array.c */
-void memclear _((register VALUE *, register int));
-VALUE assoc_new _((VALUE, VALUE));
-VALUE ary_new _((void));
-VALUE ary_new2 _((int));
-VALUE ary_new3();
-VALUE ary_new4 _((int, VALUE *));
-VALUE ary_freeze _((VALUE));
-void ary_store _((VALUE, int, VALUE));
-VALUE ary_push _((VALUE, VALUE));
-VALUE ary_pop _((VALUE));
-VALUE ary_shift _((VALUE));
-VALUE ary_unshift _((VALUE, VALUE));
-VALUE ary_entry _((VALUE, int));
-VALUE ary_each _((VALUE));
-VALUE ary_join _((VALUE, VALUE));
-VALUE ary_to_s _((VALUE));
-VALUE ary_print_on _((VALUE, VALUE));
-VALUE ary_reverse _((VALUE));
-VALUE ary_sort_bang _((VALUE));
-VALUE ary_sort _((VALUE));
-VALUE ary_delete _((VALUE, VALUE));
-VALUE ary_delete_at _((VALUE, VALUE));
-VALUE ary_plus _((VALUE, VALUE));
-VALUE ary_concat _((VALUE, VALUE));
-VALUE ary_assoc _((VALUE, VALUE));
-VALUE ary_rassoc _((VALUE, VALUE));
-VALUE ary_includes _((VALUE, VALUE));
+void rb_mem_clear _((register VALUE*, register size_t));
+VALUE rb_assoc_new _((VALUE, VALUE));
+VALUE rb_ary_new _((void));
+VALUE rb_ary_new2 _((size_t));
+VALUE rb_ary_new3 __((size_t,...));
+VALUE rb_ary_new4 _((size_t, VALUE *));
+VALUE rb_ary_freeze _((VALUE));
+VALUE rb_ary_aref _((int, VALUE*, VALUE));
+void rb_ary_store _((VALUE, size_t, VALUE));
+VALUE rb_ary_to_s _((VALUE));
+VALUE rb_ary_push _((VALUE, VALUE));
+VALUE rb_ary_pop _((VALUE));
+VALUE rb_ary_shift _((VALUE));
+VALUE rb_ary_unshift _((VALUE, VALUE));
+VALUE rb_ary_entry _((VALUE, size_t));
+VALUE rb_ary_each _((VALUE));
+VALUE rb_ary_join _((VALUE, VALUE));
+VALUE rb_ary_print_on _((VALUE, VALUE));
+VALUE rb_ary_reverse _((VALUE));
+VALUE rb_ary_sort _((VALUE));
+VALUE rb_ary_sort_bang _((VALUE));
+VALUE rb_ary_delete _((VALUE, VALUE));
+VALUE rb_ary_delete_at _((VALUE, VALUE));
+VALUE rb_ary_plus _((VALUE, VALUE));
+VALUE rb_ary_concat _((VALUE, VALUE));
+VALUE rb_ary_assoc _((VALUE, VALUE));
+VALUE rb_ary_rassoc _((VALUE, VALUE));
+VALUE rb_ary_includes _((VALUE, VALUE));
+VALUE rb_protect_inspect _((VALUE(*)(),VALUE,VALUE));
+VALUE rb_inspecting_p _((VALUE));
/* bignum.c */
-VALUE big_clone _((VALUE));
-void big_2comp _((VALUE));
-VALUE big_norm _((VALUE));
-VALUE uint2big _((UINT));
-VALUE int2big _((INT));
-VALUE uint2inum _((UINT));
-VALUE int2inum _((INT));
-VALUE str2inum _((UCHAR *, int));
-VALUE big2str _((VALUE, int));
-INT big2int _((VALUE));
-VALUE big_to_i _((VALUE));
-VALUE dbl2big _((double));
-double big2dbl _((VALUE));
-VALUE big_to_f _((VALUE));
-VALUE big_plus _((VALUE, VALUE));
-VALUE big_minus _((VALUE, VALUE));
-VALUE big_mul _((VALUE, VALUE));
-VALUE big_pow _((VALUE, VALUE));
-VALUE big_and _((VALUE, VALUE));
-VALUE big_or _((VALUE, VALUE));
-VALUE big_xor _((VALUE, VALUE));
-VALUE big_lshift _((VALUE, VALUE));
-VALUE big_rand _((VALUE));
+VALUE rb_big_clone _((VALUE));
+void rb_big_2comp _((VALUE));
+VALUE rb_big_norm _((VALUE));
+VALUE rb_uint2big _((unsigned long));
+VALUE rb_int2big _((long));
+VALUE rb_uint2inum _((unsigned long));
+VALUE rb_int2inum _((long));
+VALUE rb_str2inum _((char*, int));
+VALUE rb_big2str _((VALUE, int));
+long rb_big2long _((VALUE));
+#define rb_big2int(x) rb_big2long(x)
+unsigned long rb_big2ulong _((VALUE));
+#define rb_big2uint(x) rb_big2ulong(x)
+VALUE rb_dbl2big _((double));
+double rb_big2dbl _((VALUE));
+VALUE rb_big_plus _((VALUE, VALUE));
+VALUE rb_big_minus _((VALUE, VALUE));
+VALUE rb_big_mul _((VALUE, VALUE));
+VALUE rb_big_pow _((VALUE, VALUE));
+VALUE rb_big_and _((VALUE, VALUE));
+VALUE rb_big_or _((VALUE, VALUE));
+VALUE rb_big_xor _((VALUE, VALUE));
+VALUE rb_big_lshift _((VALUE, VALUE));
+VALUE rb_big_rand _((VALUE));
/* class.c */
-VALUE class_new _((VALUE));
-VALUE singleton_class_new _((VALUE));
-VALUE singleton_class_clone _((VALUE));
-void singleton_class_attached _((VALUE,VALUE));
+VALUE rb_class_new _((VALUE));
+VALUE rb_singleton_class_new _((VALUE));
+VALUE rb_singleton_class_clone _((VALUE));
+void rb_singleton_class_attached _((VALUE,VALUE));
VALUE rb_define_class_id _((ID, VALUE));
-VALUE module_new _((void));
+VALUE rb_module_new _((void));
VALUE rb_define_module_id _((ID));
-VALUE mod_included_modules _((VALUE));
-VALUE mod_ancestors _((VALUE));
-VALUE class_instance_methods _((int, VALUE *, VALUE));
-VALUE class_private_instance_methods _((int, VALUE *, VALUE));
-VALUE obj_singleton_methods _((VALUE));
+VALUE rb_mod_included_modules _((VALUE));
+VALUE rb_mod_ancestors _((VALUE));
+VALUE rb_class_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_obj_singleton_methods _((VALUE));
void rb_define_method_id _((VALUE, ID, VALUE (*)(), int));
-void rb_undef_method _((VALUE, char *));
-void rb_define_private_method _((VALUE, char *, VALUE (*)(), int));
+void rb_undef_method _((VALUE, char*));
+void rb_define_protected_method _((VALUE, char*, VALUE (*)(), int));
+void rb_define_private_method _((VALUE, char*, VALUE (*)(), int));
void rb_define_singleton_method _((VALUE,char*,VALUE(*)(),int));
void rb_define_private_method _((VALUE,char*,VALUE(*)(),int));
VALUE rb_singleton_class _((VALUE));
/* enum.c */
-VALUE enum_length _((VALUE));
+VALUE rb_enum_length _((VALUE));
/* error.c */
-VALUE exc_new _((VALUE, char *, UINT));
-VALUE exc_new2 _((VALUE, char *));
-VALUE exc_new3 _((VALUE, VALUE));
-#ifdef __GNUC__
-volatile voidfn TypeError;
-volatile voidfn ArgError;
-volatile voidfn NameError;
-volatile voidfn IndexError;
-volatile voidfn LoadError;
-#else
-void TypeError();
-void ArgError();
-void NameError();
-void IndexError();
-void LoadError();
-#endif
+extern int ruby_nerrs;
+VALUE rb_exc_new _((VALUE, char*, int));
+VALUE rb_exc_new2 _((VALUE, char*));
+VALUE rb_exc_new3 _((VALUE, VALUE));
+void rb_loaderror __((char*, ...)) NORETURN;
+void rb_compile_error __((char*, ...));
+void rb_compile_error_append __((char*, ...));
/* eval.c */
+void rb_exc_raise _((VALUE)) NORETURN;
+void rb_exc_fatal _((VALUE)) NORETURN;
+void rb_remove_method _((VALUE, char*));
+void rb_disable_super _((VALUE, char*));
+void rb_enable_super _((VALUE, char*));
void rb_clear_cache _((void));
void rb_alias _((VALUE, ID, ID));
+void rb_attr _((VALUE,ID,int,int,int));
int rb_method_boundp _((VALUE, ID, int));
-VALUE dyna_var_defined _((ID));
-VALUE dyna_var_ref _((ID));
-VALUE dyna_var_asgn _((ID, VALUE));
-void ruby_init _((void));
-void ruby_options _((int, char **));
-void ruby_run _((void));
-void rb_eval_cmd _((VALUE, VALUE));
-void rb_trap_eval _((VALUE, int));
+VALUE rb_dvar_defined _((ID));
+VALUE rb_dvar_ref _((ID));
+void rb_dvar_asgn _((ID, VALUE));
+void rb_dvar_push _((ID, VALUE));
+VALUE rb_eval_cmd _((VALUE, VALUE));
+VALUE rb_trap_eval _((VALUE, int));
int rb_respond_to _((VALUE, ID));
-void rb_raise _((VALUE));
-void rb_fatal _((VALUE));
void rb_interrupt _((void));
-int iterator_p _((void));
-VALUE rb_yield_0 _((VALUE, volatile VALUE));
VALUE rb_apply _((VALUE, ID, VALUE));
-VALUE rb_funcall2 _((VALUE, ID, int, VALUE *));
+VALUE rb_funcall2 _((VALUE, ID, int, VALUE*));
void rb_backtrace _((void));
ID rb_frame_last_func _((void));
-VALUE f_load _((VALUE, VALUE));
-void rb_provide _((char *));
-VALUE f_require _((VALUE, VALUE));
-VALUE class_new_instance _((int, VALUE *, VALUE));
-VALUE f_lambda _((void));
-void rb_set_end_proc _((void (*)(),VALUE));
-void gc_mark_threads _((void));
-void thread_schedule _((void));
-void thread_wait_fd _((int));
-void thread_fd_writable _((int));
-int thread_alone _((void));
-void thread_sleep _((int));
-void thread_sleep_forever _((void));
-VALUE thread_create _((VALUE (*)(), void *));
-void thread_interrupt _((void));
+VALUE rb_obj_instance_eval _((int, VALUE*, VALUE));
+void rb_load _((VALUE, int));
+void rb_load_protect _((VALUE, int, int*));
+void rb_jump_tag _((int)) NORETURN;
+void rb_provide _((char*));
+VALUE rb_f_require _((VALUE, VALUE));
+void rb_obj_call_init _((VALUE));
+VALUE rb_class_new_instance _((int, VALUE*, VALUE));
+VALUE rb_f_lambda _((void));
+VALUE rb_protect _((VALUE (*)(), VALUE, int*));
+void rb_set_end_proc _((void (*)(), VALUE));
+void rb_gc_mark_threads _((void));
+void rb_thread_start_timer _((void));
+void rb_thread_stop_timer _((void));
+void rb_thread_schedule _((void));
+void rb_thread_wait_fd _((int));
+void rb_thread_fd_writable _((int));
+int rb_thread_alone _((void));
+void rb_thread_sleep _((int));
+void rb_thread_sleep_forever _((void));
+VALUE rb_thread_create _((VALUE (*)(), void*));
+int rb_thread_scope_shared_p _((void));
+void rb_thread_interrupt _((void));
+void rb_thread_trap_eval _((VALUE, int));
+int rb_thread_select();
+void rb_thread_wait_for();
+VALUE rb_thread_current _((void));
+VALUE rb_thread_main _((void));
+VALUE rb_thread_local_aref _((VALUE, ID));
+VALUE rb_thread_local_aset _((VALUE, ID, VALUE));
/* file.c */
-VALUE file_open _((char *, char *));
-int eaccess _((char *, int));
-VALUE file_s_expand_path _((VALUE, VALUE));
+VALUE rb_file_open _((char*, char*));
+int eaccess _((char*, int));
+VALUE rb_file_s_expand_path _((int, VALUE *));
/* gc.c */
-void rb_global_variable _((VALUE *));
-void gc_mark_locations _((VALUE *, VALUE *));
-void gc_mark_maybe();
-void gc_mark();
-void gc_force_recycle();
-void gc_gc _((void));
-void init_stack _((void));
-void init_heap _((void));
+void rb_global_variable _((VALUE*));
+void rb_gc_mark_locations _((VALUE*, VALUE*));
+void rb_mark_tbl _((struct st_table*));
+void rb_mark_hash _((struct st_table*));
+void rb_gc_mark_maybe();
+void rb_gc_mark();
+void rb_gc_force_recycle _((VALUE));
+void rb_gc _((void));
+void rb_gc_call_finalizer_at_exit _((void));
/* hash.c */
-VALUE hash_freeze _((VALUE));
VALUE rb_hash _((VALUE));
-VALUE hash_new _((void));
-VALUE hash_aref _((VALUE, VALUE));
-VALUE hash_aset _((VALUE, VALUE, VALUE));
+VALUE rb_hash_new _((void));
+VALUE rb_hash_freeze _((VALUE));
+VALUE rb_hash_aref _((VALUE, VALUE));
+VALUE rb_hash_aset _((VALUE, VALUE, VALUE));
+int rb_path_check _((char *));
+int rb_env_path_tainted _((void));
/* io.c */
-void eof_error _((void));
-VALUE io_write _((VALUE, VALUE));
-VALUE io_gets_method _((int, VALUE*, VALUE));
-VALUE io_gets _((VALUE));
-VALUE io_getc _((VALUE));
-VALUE io_ungetc _((VALUE, VALUE));
-VALUE io_close _((VALUE));
-VALUE io_binmode _((VALUE));
-int io_mode_flags _((char *));
-VALUE io_reopen _((VALUE, VALUE));
-VALUE f_gets _((void));
-void rb_str_setter _((VALUE, ID, VALUE *));
+extern VALUE rb_fs;
+extern VALUE rb_output_fs;
+extern VALUE rb_rs;
+extern VALUE rb_default_rs;
+extern VALUE rb_output_rs;
+VALUE rb_io_write _((VALUE, VALUE));
+VALUE rb_io_gets _((VALUE));
+VALUE rb_io_getc _((VALUE));
+VALUE rb_io_ungetc _((VALUE, VALUE));
+VALUE rb_io_close _((VALUE));
+VALUE rb_io_eof _((VALUE));
+VALUE rb_io_binmode _((VALUE));
+int rb_io_mode_flags _((char*));
+VALUE rb_io_reopen _((VALUE, VALUE));
+VALUE rb_gets _((void));
+void rb_str_setter _((VALUE, ID, VALUE*));
/* numeric.c */
-void num_zerodiv _((void));
-VALUE num_coerce_bin _((VALUE, VALUE));
-VALUE float_new _((double));
-VALUE flo_pow _((VALUE, VALUE));
-VALUE num2fix _((VALUE));
-VALUE fix2str _((VALUE, int));
-VALUE fix_to_s _((VALUE));
-VALUE num_upto _((VALUE, VALUE));
-VALUE fix_upto _((VALUE, VALUE));
+void rb_num_zerodiv _((void));
+VALUE rb_num_coerce_bin _((VALUE, VALUE));
+VALUE rb_float_new _((double));
+VALUE rb_num2fix _((VALUE));
+VALUE rb_fix2str _((VALUE, int));
+VALUE rb_fix_upto _((VALUE, VALUE));
/* object.c */
-VALUE rb_equal _((VALUE, VALUE));
int rb_eql _((VALUE, VALUE));
-VALUE obj_equal _((VALUE, VALUE));
-VALUE any_to_s _((VALUE));
+VALUE rb_any_to_s _((VALUE));
VALUE rb_inspect _((VALUE));
-VALUE obj_is_instance_of _((VALUE, VALUE));
-VALUE obj_is_kind_of _((VALUE, VALUE));
-VALUE obj_alloc _((VALUE));
+VALUE rb_obj_is_instance_of _((VALUE, VALUE));
+VALUE rb_obj_is_kind_of _((VALUE, VALUE));
+VALUE rb_obj_alloc _((VALUE));
+VALUE rb_obj_clone _((VALUE));
+VALUE rb_obj_taint _((VALUE));
+VALUE rb_obj_tainted _((VALUE));
+VALUE rb_obj_untaint _((VALUE));
+VALUE rb_obj_id _((VALUE));
+VALUE rb_convert_type _((VALUE,int,char*,char*));
VALUE rb_Integer _((VALUE));
VALUE rb_Float _((VALUE));
VALUE rb_String _((VALUE));
VALUE rb_Array _((VALUE));
-double num2dbl _((VALUE));
/* parse.y */
+extern int ruby_sourceline;
+extern char *ruby_sourcefile;
int yyparse _((void));
-void pushback _((int));
-ID id_attrset _((ID));
-void yyappend_print _((void));
-void yywhile_loop _((int, int));
+ID rb_id_attrset _((ID));
+void rb_parser_append_print _((void));
+void rb_parser_while_loop _((int, int));
int rb_is_const_id _((ID));
int rb_is_instance_id _((ID));
-void local_var_append _((ID));
-VALUE backref_get _((void));
-void backref_set _((VALUE));
-VALUE lastline_get _((void));
-void lastline_set _((VALUE));
+VALUE rb_backref_get _((void));
+void rb_backref_set _((VALUE));
+VALUE rb_lastline_get _((void));
+void rb_lastline_set _((VALUE));
/* process.c */
-int rb_proc_exec _((char *));
+int rb_proc_exec _((char*));
void rb_syswait _((int));
/* range.c */
-VALUE range_new _((VALUE, VALUE));
-VALUE range_beg_end _((VALUE, int *, int *));
+VALUE rb_range_new _((VALUE, VALUE));
+VALUE rb_range_beg_end _((VALUE, int*, int*));
/* re.c */
-VALUE reg_nth_defined _((int, VALUE));
-VALUE reg_nth_match _((int, VALUE));
-VALUE reg_last_match _((VALUE));
-VALUE reg_match_pre _((VALUE));
-VALUE reg_match_post _((VALUE));
-VALUE reg_match_last _((VALUE));
-VALUE reg_new _((char *, int, int));
-VALUE reg_match _((VALUE, VALUE));
-VALUE reg_match2 _((VALUE));
-void rb_set_kcode _((char *));
+VALUE rb_reg_nth_defined _((int, VALUE));
+VALUE rb_reg_nth_match _((int, VALUE));
+VALUE rb_reg_last_match _((VALUE));
+VALUE rb_reg_match_pre _((VALUE));
+VALUE rb_reg_match_post _((VALUE));
+VALUE rb_reg_match_last _((VALUE));
+VALUE rb_reg_new _((char*, size_t, int));
+VALUE rb_reg_match _((VALUE, VALUE));
+VALUE rb_reg_match2 _((VALUE));
+int rb_reg_options _((VALUE));
+char*rb_get_kcode _((void));
+void rb_set_kcode _((char*));
+int rb_ignorecase_p _((void));
/* ruby.c */
-void rb_require_modules _((void));
-void rb_load_file _((char *));
-void ruby_script _((char *));
+void rb_load_file _((char*));
+void ruby_script _((char*));
void ruby_prog_init _((void));
-void ruby_set_argv _((int, char **));
-void ruby_process_options _((int, char **));
+void ruby_set_argv _((int, char**));
+void ruby_process_options _((int, char**));
+void ruby_require_modules _((void));
+void ruby_load_script _((void));
/* signal.c */
-VALUE f_kill _((int, VALUE *));
-void gc_mark_trap_list _((void));
+VALUE rb_f_kill _((int, VALUE*));
+void rb_gc_mark_trap_list _((void));
+#ifdef POSIX_SIGNAL
+#define posix_signal ruby_posix_signal
void posix_signal _((int, void (*)()));
+#endif
void rb_trap_exit _((void));
void rb_trap_exec _((void));
/* sprintf.c */
-VALUE f_sprintf _((int, VALUE *));
+VALUE rb_f_sprintf _((int, VALUE*));
/* string.c */
-VALUE str_new _((UCHAR *, UINT));
-VALUE str_new2 _((UCHAR *));
-VALUE str_new3 _((VALUE));
-VALUE str_new4 _((VALUE));
-VALUE obj_as_string _((VALUE));
-VALUE str_dup _((VALUE));
-VALUE str_plus _((VALUE, VALUE));
-VALUE str_times _((VALUE, VALUE));
-VALUE str_substr _((VALUE, int, int));
-void str_modify _((VALUE));
-VALUE str_freeze _((VALUE));
-VALUE str_dup_freezed _((VALUE));
-VALUE str_taint _((VALUE));
-VALUE str_tainted _((VALUE));
-VALUE str_resize _((VALUE, int));
-VALUE str_cat _((VALUE, UCHAR *, UINT));
-int str_hash _((VALUE));
-int str_cmp _((VALUE, VALUE));
-VALUE str_upto _((VALUE, VALUE));
-VALUE str_inspect _((VALUE));
-VALUE str_split _((VALUE, char *));
+VALUE rb_str_new _((char*, size_t));
+VALUE rb_str_new2 _((char*));
+VALUE rb_str_new3 _((VALUE));
+VALUE rb_str_new4 _((VALUE));
+VALUE rb_tainted_str_new _((char*, size_t));
+VALUE rb_tainted_str_new2 _((char*));
+VALUE rb_obj_as_string _((VALUE));
+VALUE rb_str_to_str _((VALUE));
+VALUE rb_str_dup _((VALUE));
+VALUE rb_str_plus _((VALUE, VALUE));
+VALUE rb_str_times _((VALUE, VALUE));
+VALUE rb_str_substr _((VALUE, size_t, size_t));
+void rb_str_modify _((VALUE));
+VALUE rb_str_freeze _((VALUE));
+VALUE rb_str_dup_frozen _((VALUE));
+VALUE rb_str_resize _((VALUE, size_t));
+VALUE rb_str_cat _((VALUE, char*, size_t));
+VALUE rb_str_concat _((VALUE, VALUE));
+int rb_str_hash _((VALUE));
+int rb_str_cmp _((VALUE, VALUE));
+VALUE rb_str_upto _((VALUE, VALUE));
+VALUE rb_str_inspect _((VALUE));
+VALUE rb_str_split _((VALUE, char*));
/* struct.c */
-VALUE struct_new();
-VALUE struct_define();
-VALUE struct_alloc _((VALUE, VALUE));
-VALUE struct_aref _((VALUE, VALUE));
-VALUE struct_aset _((VALUE, VALUE, VALUE));
-VALUE struct_getmember _((VALUE, ID));
+VALUE rb_struct_new __((VALUE, ...));
+VALUE rb_struct_define __((char*, ...));
+VALUE rb_struct_alloc _((VALUE, VALUE));
+VALUE rb_struct_aref _((VALUE, VALUE));
+VALUE rb_struct_aset _((VALUE, VALUE, VALUE));
+VALUE rb_struct_getmember _((VALUE, ID));
/* time.c */
-VALUE time_new _((int, int));
-/* util.c */
-void add_suffix _((VALUE, char *));
-unsigned long scan_oct _((char *, int, int *));
-unsigned long scan_hex _((char *, int, int *));
+VALUE rb_time_new _((int, int));
/* variable.c */
-VALUE mod_name _((VALUE));
+VALUE rb_mod_name _((VALUE));
VALUE rb_class_path _((VALUE));
-void rb_set_class_path _((VALUE, VALUE, char *));
-VALUE rb_path2class _((char *));
+void rb_set_class_path _((VALUE, VALUE, char*));
+VALUE rb_path2class _((char*));
void rb_name_class _((VALUE, ID));
-void rb_autoload _((char *, char *));
-VALUE f_autoload _((VALUE, VALUE, VALUE));
-void gc_mark_global_tbl _((void));
-VALUE f_trace_var _((int, VALUE *));
-VALUE f_untrace_var _((int, VALUE *));
-VALUE rb_gvar_set2 _((char *, VALUE));
-VALUE f_global_variables _((void));
+void rb_autoload _((char*, char*));
+VALUE rb_f_autoload _((VALUE, VALUE, VALUE));
+void rb_gc_mark_global_tbl _((void));
+VALUE rb_f_trace_var _((int, VALUE*));
+VALUE rb_f_untrace_var _((int, VALUE*));
+VALUE rb_gvar_set2 _((char*, VALUE));
+VALUE rb_f_global_variables _((void));
void rb_alias_variable _((ID, ID));
+void rb_mark_generic_ivar _((VALUE));
+void rb_mark_generic_ivar_tbl _((void));
+void rb_free_generic_ivar _((VALUE));
VALUE rb_ivar_get _((VALUE, ID));
VALUE rb_ivar_set _((VALUE, ID, VALUE));
VALUE rb_ivar_defined _((VALUE, ID));
-VALUE obj_instance_variables _((VALUE));
-VALUE mod_const_at _((VALUE, VALUE));
-VALUE mod_constants _((VALUE));
-VALUE mod_const_of _((VALUE, VALUE));
+VALUE rb_obj_instance_variables _((VALUE));
+VALUE rb_obj_remove_instance_variable _((VALUE, VALUE));
+VALUE rb_mod_const_at _((VALUE, VALUE));
+VALUE rb_mod_constants _((VALUE));
+VALUE rb_mod_const_of _((VALUE, VALUE));
+VALUE rb_mod_remove_const _((VALUE, VALUE));
int rb_const_defined_at _((VALUE, ID));
int rb_autoload_defined _((ID));
int rb_const_defined _((VALUE, ID));
+/* version.c */
+void ruby_show_version _((void));
+void ruby_show_copyright _((void));
diff --git a/io.c b/io.c
index f84e15e447..5573e76a64 100644
--- a/io.c
+++ b/io.c
@@ -6,12 +6,13 @@
$Date$
created at: Fri Oct 15 18:08:59 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-#include "io.h"
+#include "rubyio.h"
+#include "rubysig.h"
#include <ctype.h>
#include <errno.h>
@@ -39,10 +40,6 @@ struct timeval {
#include <sys/stat.h>
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__)
-#include <fcntl.h>
-#endif
-
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#else
@@ -53,29 +50,43 @@ struct timeval {
#include <unistd.h>
#endif
-VALUE rb_ad_string();
+#ifdef USE_CWGUSI
+ #include <sys/errno.h>
+ #include <unix.mac.h>
+ #include <compat.h>
+#endif
+extern void Init_File _((void));
+
+#ifdef __BEOS__
+#include <net/socket.h>
+#endif
+
+#include "util.h"
-VALUE cIO;
-extern VALUE cFile;
-VALUE eEOFError;
-VALUE eIOError;
+VALUE rb_cIO;
+VALUE rb_eEOFError;
+VALUE rb_eIOError;
VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
-VALUE FS, OFS;
-VALUE RS, ORS;
-VALUE RS_default;
+VALUE rb_fs;
+VALUE rb_output_fs;
+VALUE rb_rs;
+VALUE rb_output_rs;
+VALUE rb_default_rs;
static VALUE argf;
-ID id_write;
+static ID id_write;
-VALUE lastline_get();
-void lastline_set();
+extern char *ruby_inplace_mode;
-extern char *inplace;
+struct timeval rb_time_timeval _((VALUE));
-struct timeval time_timeval();
+static VALUE filename, file;
+static int gets_lineno;
+static int init_p = 0, next_p = 0;
+static VALUE lineno;
#ifdef _STDIO_USES_IOSTREAM /* GNU libc */
# ifdef _IO_fpos_t
@@ -83,86 +94,89 @@ struct timeval time_timeval();
# else
# define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
# endif
+#elif defined(FILE_COUNT)
+# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
+#elif defined(__BEOS__)
+# define ReadDataPending(fp) (fp->_state._eof == 0)
+#elif defined(USE_CWGUSI)
+# define ReadDataPending(fp) (fp->state.eof == 0)
#else
-# ifdef FILE_COUNT
-# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
-# else
/* requires systems own version of the ReadDataPending() */
extern int ReadDataPending();
-# define READ_DATA_PENDING(fp) ReadDataPending(fp)
-# endif
+# define READ_DATA_PENDING(fp) ReadDataPending(fp)
#endif
-#ifndef THREAD
+#ifndef USE_THREAD
# define READ_CHECK(fp) 0
#else
# define READ_CHECK(fp) do {\
- if (!READ_DATA_PENDING(fp)) thread_wait_fd(fileno(fp));\
+ if (!READ_DATA_PENDING(fp)) rb_thread_wait_fd(fileno(fp));\
} while(0)
#endif
void
-eof_error()
+rb_eof_error()
{
- Raise(eEOFError, "End of file reached");
+ rb_raise(rb_eEOFError, "End of file reached");
}
void
-io_writable(fptr)
+rb_io_check_closed(fptr)
OpenFile *fptr;
{
- if (!(fptr->mode & FMODE_WRITABLE)) {
- Raise(eIOError, "not opened for writing");
- }
+ if (fptr->f == NULL && fptr->f2 == NULL)
+ rb_raise(rb_eIOError, "closed stream");
}
void
-io_readable(fptr)
+rb_io_check_readable(fptr)
OpenFile *fptr;
{
if (!(fptr->mode & FMODE_READABLE)) {
- Raise(eIOError, "not opened for reading");
+ rb_raise(rb_eIOError, "not opened for reading");
}
}
-static void
-closed()
+void
+rb_io_check_writable(fptr)
+ OpenFile *fptr;
{
- Raise(eIOError, "closed stream");
+ if (!(fptr->mode & FMODE_WRITABLE)) {
+ rb_raise(rb_eIOError, "not opened for writing");
+ }
}
/* writing functions */
VALUE
-io_write(io, str)
+rb_io_write(io, str)
VALUE io, str;
{
OpenFile *fptr;
FILE *f;
int n;
+ rb_secure(4);
if (TYPE(str) != T_STRING)
- str = obj_as_string(str);
+ str = rb_obj_as_string(str);
if (RSTRING(str)->len == 0) return INT2FIX(0);
if (BUILTIN_TYPE(io) != T_FILE) {
+ /* port is not IO, call write method for it. */
return rb_funcall(io, id_write, 1, str);
}
- rb_secure(4);
GetOpenFile(io, fptr);
- io_writable(fptr);
-
+ rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
- if (f == NULL) closed();
#ifdef __human68k__
{
- register UCHAR *ptr = str->ptr;
- n = (int) str->len;
+ register char *ptr = RSTRING(str)->ptr;
+ n = (int)RSTRING(str)->len;
while (--n >= 0)
if (fputc(*ptr++, f) == EOF)
rb_sys_fail(fptr->path);
- n = ptr - str->ptr;
+ n = ptr - RSTRING(str)->ptr;
}
if (ferror(f))
rb_sys_fail(fptr->path);
@@ -180,24 +194,23 @@ io_write(io, str)
}
static VALUE
-io_addstr(io, str)
+rb_io_addstr(io, str)
VALUE io, str;
{
- io_write(io, str);
+ rb_io_write(io, str);
return io;
}
static VALUE
-io_flush(io)
+rb_io_flush(io)
VALUE io;
{
OpenFile *fptr;
FILE *f;
GetOpenFile(io, fptr);
- io_writable(fptr);
+ rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
- if (f == NULL) closed();
if (fflush(f) == EOF) rb_sys_fail(0);
@@ -205,42 +218,108 @@ io_flush(io)
}
static VALUE
-io_eof(io)
+rb_io_tell(io)
+ VALUE io;
+{
+ OpenFile *fptr;
+ long pos;
+
+ GetOpenFile(io, fptr);
+ pos = ftell(fptr->f);
+ if (ferror(fptr->f) != 0) rb_sys_fail(fptr->path);
+
+ return rb_int2inum(pos);
+}
+
+static VALUE
+rb_io_seek(io, offset, ptrname)
+ VALUE io, offset, ptrname;
+{
+ OpenFile *fptr;
+ long pos;
+
+ GetOpenFile(io, fptr);
+ pos = fseek(fptr->f, NUM2INT(offset), NUM2INT(ptrname));
+ if (pos != 0) rb_sys_fail(fptr->path);
+ clearerr(fptr->f);
+
+ return INT2FIX(0);
+}
+
+#ifndef SEEK_CUR
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+
+static VALUE
+rb_io_set_pos(io, offset)
+ VALUE io, offset;
+{
+ OpenFile *fptr;
+ long pos;
+
+ GetOpenFile(io, fptr);
+ pos = fseek(fptr->f, NUM2INT(offset), SEEK_SET);
+ if (pos != 0) rb_sys_fail(fptr->path);
+ clearerr(fptr->f);
+
+ return INT2NUM(pos);
+}
+
+static VALUE
+rb_io_rewind(io)
+ VALUE io;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(io, fptr);
+ if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path);
+ clearerr(fptr->f);
+
+ return INT2FIX(0);
+}
+
+VALUE
+rb_io_eof(io)
VALUE io;
{
OpenFile *fptr;
int ch;
GetOpenFile(io, fptr);
- io_readable(fptr);
- if (fptr->f == NULL) closed();
-
- if (READ_DATA_PENDING(fptr->f)) return FALSE;
- if (feof(fptr->f)) return TRUE;
+ rb_io_check_readable(fptr);
+ if (READ_DATA_PENDING(fptr->f)) return Qfalse;
+#if 0
+ if (feof(fptr->f)) return Qtrue;
+ return Qfalse;
+#else
+ READ_CHECK(fptr->f);
TRAP_BEG;
ch = getc(fptr->f);
TRAP_END;
if (ch != EOF) {
- (void)ungetc(ch, fptr->f);
- return FALSE;
+ ungetc(ch, fptr->f);
+ return Qfalse;
}
- return TRUE;
+ return Qtrue;
+#endif
}
static VALUE
-io_sync(io)
+rb_io_sync(io)
VALUE io;
{
OpenFile *fptr;
GetOpenFile(io, fptr);
- return (fptr->mode & FMODE_SYNC) ? TRUE : FALSE;
+ return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
}
static VALUE
-io_set_sync(io, mode)
+rb_io_set_sync(io, mode)
VALUE io, mode;
{
OpenFile *fptr;
@@ -256,7 +335,7 @@ io_set_sync(io, mode)
}
static VALUE
-io_fileno(io)
+rb_io_fileno(io)
VALUE io;
{
OpenFile *fptr;
@@ -267,6 +346,13 @@ io_fileno(io)
return INT2FIX(fd);
}
+static VALUE
+rb_io_to_io(io)
+ VALUE io;
+{
+ return io;
+}
+
/* reading functions */
#ifndef S_ISREG
@@ -281,45 +367,52 @@ read_all(port)
{
OpenFile *fptr;
VALUE str = Qnil;
- char *buf;
struct stat st;
- int siz = BUFSIZ;
- int bytes = 0;
+ long siz = BUFSIZ;
+ long bytes = 0;
int n;
GetOpenFile(port, fptr);
- io_readable(fptr);
- if (fptr->f == NULL) closed();
+ rb_io_check_readable(fptr);
- if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)) {
- if (st.st_size == 0) return Qnil;
+ if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
+#ifdef __BEOS__
+ && (st.st_dev > 3)
+#endif
+ )
+ {
+ if (st.st_size == 0) return rb_str_new(0, 0);
else {
- int pos = ftell(fptr->f);
+ long pos = ftell(fptr->f);
if (st.st_size > pos && pos >= 0) {
siz = st.st_size - pos + 1;
}
}
}
- str = str_new(0, siz);
+ str = rb_str_new(0, siz);
for (;;) {
READ_CHECK(fptr->f);
TRAP_BEG;
n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f);
TRAP_END;
- if (n == 0) break;
- if (n < 0) rb_sys_fail(fptr->path);
+ if (n <= 0) {
+ if (ferror(fptr->f)) rb_sys_fail(fptr->path);
+ return rb_str_new(0,0);
+ }
bytes += n;
- if (bytes < siz) break;
+ if (bytes < siz) break;
siz += BUFSIZ;
- str_resize(str, siz);
+ rb_str_resize(str, siz);
}
- if (bytes == 0) return Qnil;
- if (bytes != siz) str_resize(str, bytes);
- return str_taint(str);
+ if (bytes == 0) return rb_str_new(0,0);
+ if (bytes != siz) rb_str_resize(str, bytes);
+ OBJ_TAINT(str);
+
+ return str;
}
static VALUE
-io_read(argc, argv, io)
+rb_io_read(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -328,36 +421,34 @@ io_read(argc, argv, io)
int n, len;
VALUE length, str;
- if (rb_scan_args(argc, argv, "01", &length) == 0) {
+ rb_scan_args(argc, argv, "01", &length);
+ if (NIL_P(length)) {
return read_all(io);
}
len = NUM2INT(length);
GetOpenFile(io, fptr);
- io_readable(fptr);
- if (fptr->f == NULL) closed();
+ rb_io_check_readable(fptr);
- str = str_new(0, len);
+ str = rb_str_new(0, len);
READ_CHECK(fptr->f);
TRAP_BEG;
n = fread(RSTRING(str)->ptr, 1, len, fptr->f);
TRAP_END;
- if (n == 0) return Qnil;
- if (n < 0) {
- rb_sys_fail(fptr->path);
+ if (n <= 0) {
+ if (ferror(fptr->f)) rb_sys_fail(fptr->path);
+ return Qnil;
}
-
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
+ OBJ_TAINT(str);
- return str_taint(str);
+ return str;
}
-static VALUE lineno;
-
-VALUE
-io_gets_method(argc, argv, io)
+static VALUE
+rb_io_gets_internal(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -370,33 +461,36 @@ io_gets_method(argc, argv, io)
int rslen, rspara = 0;
VALUE rs;
- if (argc == 0) rs = RS;
+ if (argc == 0) {
+ rs = rb_rs;
+ }
else {
rb_scan_args(argc, argv, "1", &rs);
if (!NIL_P(rs)) Check_Type(rs, T_STRING);
}
- GetOpenFile(io, fptr);
- io_readable(fptr);
- f = fptr->f;
- if (f == NULL) closed();
-
- if (!NIL_P(rs)) {
+ if (NIL_P(rs)) {
+ rsptr = 0;
+ rslen = 0;
+ }
+ else {
rslen = RSTRING(rs)->len;
if (rslen == 0) {
rsptr = "\n\n";
rslen = 2;
rspara = 1;
}
+ else if (rslen == 1 && RSTRING(rs)->ptr[0] == '\n') {
+ return rb_io_gets(io);
+ }
else {
rsptr = RSTRING(rs)->ptr;
}
}
- else {
- rsptr = 0;
- rslen = 0;
- }
- newline = rslen ? rsptr[rslen - 1] : 0777;
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ f = fptr->f;
if (rspara) {
do {
@@ -411,6 +505,7 @@ io_gets_method(argc, argv, io)
} while (c != EOF);
}
+ newline = rslen ? rsptr[rslen - 1] : 0777;
{
char buf[8192];
char *bp, *bpe = buf + sizeof buf - 3;
@@ -426,7 +521,10 @@ io_gets_method(argc, argv, io)
TRAP_BEG;
c = getc(f);
TRAP_END;
- if (c == EOF) break;
+ if (c == EOF) {
+ if (errno == EINTR) continue;
+ break;
+ }
if ((*bp++ = c) == newline) break;
if (bp == bpe) break;
}
@@ -437,25 +535,29 @@ io_gets_method(argc, argv, io)
TRAP_BEG;
cnt = fread(buf, 1, sizeof(buf), f);
TRAP_END;
- c = cnt ? 0 : EOF;
+ if (cnt == 0) {
+ if (ferror(f)) rb_sys_fail(fptr->path);
+ c = EOF;
+ }
+ else {
+ c = 0;
+ }
}
- if (c == EOF) {
- if (!append && cnt == 0) {
- str = Qnil;
- goto return_gets;
- }
+ if (c == EOF && !append && cnt == 0) {
+ str = Qnil;
+ goto return_gets;
}
if (append)
- str_cat(str, buf, cnt);
+ rb_str_cat(str, buf, cnt);
else
- str = str_new(buf, cnt);
+ str = rb_str_new(buf, cnt);
if (c != EOF &&
(!rslen ||
RSTRING(str)->len < rslen ||
- memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen, rsptr, rslen))) {
+ memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen))) {
append = 1;
goto again;
}
@@ -478,65 +580,161 @@ io_gets_method(argc, argv, io)
if (!NIL_P(str)) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
- str_taint(str);
+ OBJ_TAINT(str);
}
- lastline_set(str);
return str;
}
VALUE
-io_gets(io)
+rb_io_gets(io)
VALUE io;
{
- return io_gets_method(0, 0, io);
+ OpenFile *fptr;
+ FILE *f;
+ VALUE str = Qnil;
+ int c;
+ char buf[8192];
+ char *bp, *bpe = buf + sizeof buf - 3;
+ int cnt;
+ int append = 0;
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ f = fptr->f;
+
+ again:
+ bp = buf;
+ for (;;) {
+ READ_CHECK(f);
+ TRAP_BEG;
+ c = getc(f);
+ TRAP_END;
+ if (c == EOF) {
+ if (errno == EINTR) continue;
+ break;
+ }
+ if ((*bp++ = c) == '\n') break;
+ if (bp == bpe) break;
+ }
+ cnt = bp - buf;
+
+ if (c == EOF && !append && cnt == 0) {
+ str = Qnil;
+ goto return_gets;
+ }
+
+ if (append)
+ rb_str_cat(str, buf, cnt);
+ else
+ str = rb_str_new(buf, cnt);
+
+ if (c != EOF && RSTRING(str)->ptr[RSTRING(str)->len-1] != '\n') {
+ append = 1;
+ goto again;
+ }
+
+ return_gets:
+ if (!NIL_P(str)) {
+ fptr->lineno++;
+ lineno = INT2FIX(fptr->lineno);
+ OBJ_TAINT(str);
+ }
+
+ return str;
}
static VALUE
-io_readline(argc, argv, io)
+rb_io_gets_method(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
{
- VALUE line = io_gets_method(argc, argv, io);
+ VALUE str = rb_io_gets_internal(argc, argv, io);
+
+ if (!NIL_P(str)) {
+ rb_lastline_set(str);
+ }
+ return str;
+}
+
+static VALUE
+rb_io_lineno(io)
+ VALUE io;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ return INT2NUM(fptr->lineno);
+}
+
+static VALUE
+rb_io_set_lineno(io, lineno)
+ VALUE io, lineno;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ return fptr->lineno = NUM2INT(lineno);
+}
+
+static void
+lineno_setter(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ gets_lineno = NUM2INT(val);
+ *var = INT2FIX(gets_lineno);
+}
+
+static VALUE
+rb_io_readline(argc, argv, io)
+ int argc;
+ VALUE *argv;
+ VALUE io;
+{
+ VALUE line = rb_io_gets_method(argc, argv, io);
if (NIL_P(line)) {
- eof_error();
+ rb_eof_error();
}
return line;
}
static VALUE
-io_readlines(argc, argv, io)
+rb_io_readlines(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
{
VALUE line, ary;
- ary = ary_new();
- while (!NIL_P(line = io_gets_method(argc, argv, io))) {
- ary_push(ary, line);
+ ary = rb_ary_new();
+ while (!NIL_P(line = rb_io_gets_internal(argc, argv, io))) {
+ rb_ary_push(ary, line);
}
return ary;
}
static VALUE
-io_each_line(argc, argv, io)
+rb_io_each_line(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
{
VALUE str;
- while (!NIL_P(str = io_gets_method(argc, argv, io))) {
+ while (!NIL_P(str = rb_io_gets_internal(argc, argv, io))) {
rb_yield(str);
}
return Qnil;
}
static VALUE
-io_each_byte(io)
+rb_io_each_byte(io)
VALUE io;
{
OpenFile *fptr;
@@ -544,9 +742,8 @@ io_each_byte(io)
int c;
GetOpenFile(io, fptr);
- io_readable(fptr);
+ rb_io_check_readable(fptr);
f = fptr->f;
- if (f == NULL) closed();
for (;;) {
READ_CHECK(f);
@@ -561,7 +758,7 @@ io_each_byte(io)
}
VALUE
-io_getc(io)
+rb_io_getc(io)
VALUE io;
{
OpenFile *fptr;
@@ -569,9 +766,8 @@ io_getc(io)
int c;
GetOpenFile(io, fptr);
- io_readable(fptr);
+ rb_io_check_readable(fptr);
f = fptr->f;
- if (f == NULL) closed();
READ_CHECK(f);
TRAP_BEG;
@@ -586,27 +782,26 @@ io_getc(io)
}
static VALUE
-io_readchar(io)
+rb_io_readchar(io)
VALUE io;
{
- VALUE c = io_getc(io);
+ VALUE c = rb_io_getc(io);
if (NIL_P(c)) {
- eof_error();
+ rb_eof_error();
}
return c;
}
VALUE
-io_ungetc(io, c)
+rb_io_ungetc(io, c)
VALUE io, c;
{
OpenFile *fptr;
Check_Type(c, T_FIXNUM);
GetOpenFile(io, fptr);
- io_readable(fptr);
- if (fptr->f == NULL) closed();
+ rb_io_check_readable(fptr);
if (ungetc(FIX2INT(c), fptr->f) == EOF)
rb_sys_fail(fptr->path);
@@ -614,16 +809,15 @@ io_ungetc(io, c)
}
static VALUE
-io_isatty(io)
+rb_io_isatty(io)
VALUE io;
{
OpenFile *fptr;
GetOpenFile(io, fptr);
- if (fptr->f == NULL) closed();
if (isatty(fileno(fptr->f)) == 0)
- return FALSE;
- return TRUE;
+ return Qfalse;
+ return Qtrue;
}
static void
@@ -636,23 +830,20 @@ fptr_finalize(fptr)
if (fptr->f2 != NULL) {
fclose(fptr->f2);
}
- if (fptr->path) {
- free(fptr->path);
- fptr->path = NULL;
- }
if (fptr->pid) {
rb_syswait(fptr->pid);
fptr->pid = 0;
}
}
-void
-io_fptr_finalize(fptr)
+static void
+rb_io_fptr_close(fptr)
OpenFile *fptr;
{
+ if (fptr->f == NULL && fptr->f2 == NULL) return;
+
if (fptr->finalize) {
(*fptr->finalize)(fptr);
- fptr->finalize = 0;
}
else {
fptr_finalize(fptr);
@@ -660,30 +851,93 @@ io_fptr_finalize(fptr)
fptr->f = fptr->f2 = NULL;
}
+void
+rb_io_fptr_finalize(fptr)
+ OpenFile *fptr;
+{
+ rb_io_fptr_close(fptr);
+ if (fptr->path) {
+ free(fptr->path);
+ fptr->path = NULL;
+ }
+}
+
+VALUE
+rb_io_close(io)
+ VALUE io;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(io, fptr);
+ rb_io_fptr_close(fptr);
+
+ return Qnil;
+}
+
+static VALUE
+rb_io_close_method(io)
+ VALUE io;
+{
+ rb_secure(4);
+ rb_io_close(io);
+ return Qnil;
+}
+
+static VALUE
+rb_io_closed(io)
+ VALUE io;
+{
+ OpenFile *fptr;
+
+ fptr = RFILE(io)->fptr;
+ return (fptr->f || fptr->f2)?Qfalse:Qtrue;
+}
+
VALUE
-io_close(io)
+rb_io_close_read(io)
VALUE io;
{
OpenFile *fptr;
+ rb_secure(4);
GetOpenFile(io, fptr);
- io_fptr_finalize(fptr);
+ if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for reading");
+ }
+ if (fptr->f2 == 0) {
+ return rb_io_close(io);
+ }
+ fclose(fptr->f);
+ fptr->mode &= ~FMODE_READABLE;
+ fptr->f = fptr->f2;
+ fptr->f2 = 0;
return Qnil;
}
static VALUE
-io_closed(io)
+rb_io_close_write(io)
VALUE io;
{
OpenFile *fptr;
+ rb_secure(4);
GetOpenFile(io, fptr);
- return fptr->f?FALSE:TRUE;
+ if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for writing");
+ }
+ if (fptr->f2 == 0) {
+ return rb_io_close(io);
+ }
+ fclose(fptr->f2);
+ fptr->f2 = 0;
+ fptr->mode &= ~FMODE_WRITABLE;
+
+ return Qnil;
}
static VALUE
-io_syswrite(io, str)
+rb_io_syswrite(io, str)
VALUE io, str;
{
OpenFile *fptr;
@@ -692,15 +946,14 @@ io_syswrite(io, str)
rb_secure(4);
if (TYPE(str) != T_STRING)
- str = obj_as_string(str);
+ str = rb_obj_as_string(str);
GetOpenFile(io, fptr);
- io_writable(fptr);
+ rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
- if (f == NULL) closed();
-#ifdef THREAD
- thread_fd_writable(fileno(f));
+#ifdef USE_THREAD
+ rb_thread_fd_writable(fileno(f));
#endif
n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);
@@ -710,7 +963,7 @@ io_syswrite(io, str)
}
static VALUE
-io_sysread(io, len)
+rb_io_sysread(io, len)
VALUE io, len;
{
OpenFile *fptr;
@@ -719,44 +972,52 @@ io_sysread(io, len)
ilen = NUM2INT(len);
GetOpenFile(io, fptr);
- io_readable(fptr);
- if (fptr->f == NULL) closed();
+ rb_io_check_readable(fptr);
- str = str_new(0, ilen);
+ str = rb_str_new(0, ilen);
-#ifdef THREAD
- thread_wait_fd(fileno(fptr->f));
+#ifdef USE_THREAD
+ rb_thread_wait_fd(fileno(fptr->f));
#endif
TRAP_BEG;
n = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len);
TRAP_END;
if (n == -1) rb_sys_fail(fptr->path);
- if (n == 0) eof_error();
+ if (n == 0) rb_eof_error();
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
- return str_taint(str);
+ OBJ_TAINT(str);
+
+ return str;
}
VALUE
-io_binmode(io)
+rb_io_binmode(io)
VALUE io;
{
-#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__)
+#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) || defined(USE_CWGUSI)
OpenFile *fptr;
GetOpenFile(io, fptr);
#ifdef __human68k__
if (fptr->f)
fmode(fptr->f, _IOBIN);
- if (fptr->f2);
+ if (fptr->f2)
fmode(fptr->f2, _IOBIN);
#else
+# ifndef USE_CWGUSI
if (fptr->f && setmode(fileno(fptr->f), O_BINARY) == -1)
rb_sys_fail(fptr->path);
if (fptr->f2 && setmode(fileno(fptr->f2), O_BINARY) == -1)
rb_sys_fail(fptr->path);
+# else /* USE_CWGUSI */
+ if (fptr->f)
+ fptr->f->mode.binrb_ary_io = 1;
+ if (fptr->f2)
+ fptr->f2->mode.binrb_ary_io = 1;
+# endif /* USE_CWGUSI */
#endif
fptr->mode |= FMODE_BINMODE;
@@ -765,7 +1026,7 @@ io_binmode(io)
}
int
-io_mode_flags(mode)
+rb_io_mode_flags(mode)
char *mode;
{
int flags = 0;
@@ -781,7 +1042,7 @@ io_mode_flags(mode)
flags |= FMODE_WRITABLE;
break;
default:
- ArgError("illegal access mode");
+ rb_raise(rb_eArgError, "illegal access mode");
}
if (mode[1] == 'b') {
@@ -806,7 +1067,7 @@ rb_fopen(fname, mode)
f = fopen(fname, mode);
if (f == NULL) {
if (errno == EMFILE || errno == ENFILE) {
- gc_gc();
+ rb_gc();
f = fopen(fname, mode);
}
if (f == NULL) {
@@ -862,6 +1123,7 @@ pipe_del_fptr(fptr)
if (list->fptr == fptr) {
pipe_list = list->next;
+ free(list);
return;
}
@@ -880,18 +1142,20 @@ static void
pipe_atexit()
{
struct pipe_list *list = pipe_list;
+ struct pipe_list *tmp;
while (list) {
- io_fptr_finalize(list->fptr);
- list = list->next;
+ tmp = list->next;
+ rb_io_fptr_finalize(list->fptr);
+ list = tmp;
}
}
-#if !defined (__CYGWIN32__)
static void
pipe_finalize(fptr)
OpenFile *fptr;
{
+#if !defined (__CYGWIN32__)
if (fptr->f != NULL) {
pclose(fptr->f);
}
@@ -899,16 +1163,18 @@ pipe_finalize(fptr)
pclose(fptr->f2);
}
fptr->f = fptr->f2 = NULL;
+#else
+ fptr_finalize(fptr);
+#endif
pipe_del_fptr(fptr);
}
#endif
-#endif
void
-io_unbuffered(fptr)
+rb_io_unbuffered(fptr)
OpenFile *fptr;
{
- if (fptr->f2 == 0) TypeError("non-writable fptr");
+ if (fptr->f2 == 0) rb_raise(rb_eTypeError, "non-writable fptr");
if (fptr->f != 0) setbuf(fptr->f, NULL);
setbuf(fptr->f2, NULL);
fptr->mode |= FMODE_SYNC;
@@ -918,7 +1184,8 @@ static VALUE
pipe_open(pname, mode)
char *pname, *mode;
{
- int modef = io_mode_flags(mode);
+#ifndef USE_CWGUSI
+ int modef = rb_io_mode_flags(mode);
OpenFile *fptr;
#if defined(NT) || defined(DJGPP) || defined(__human68k__)
@@ -927,7 +1194,7 @@ pipe_open(pname, mode)
if (f == NULL) rb_sys_fail(pname);
else {
NEWOBJ(port, struct RFile);
- OBJSETUP(port, cIO, T_FILE);
+ OBJSETUP(port, rb_cIO, T_FILE);
MakeOpenFile(port, fptr);
fptr->finalize = pipe_finalize;
fptr->mode = modef;
@@ -936,8 +1203,9 @@ pipe_open(pname, mode)
if (modef & FMODE_READABLE) fptr->f = f;
if (modef & FMODE_WRITABLE) {
fptr->f2 = f;
- io_unbuffered(fptr);
+ rb_io_unbuffered(fptr);
}
+ rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
#else
@@ -974,23 +1242,23 @@ pipe_open(pname, mode)
}
if (doexec) {
- extern char *sourcefile;
- extern int sourceline;
+ extern char *ruby_sourcefile;
+ extern int ruby_sourceline;
int fd;
for (fd = 3; fd < NOFILE; fd++)
close(fd);
rb_proc_exec(pname);
fprintf(stderr, "%s:%d: command not found: %s\n",
- sourcefile, sourceline, pname);
+ ruby_sourcefile, ruby_sourceline, pname);
_exit(127);
}
return Qnil;
case -1: /* fork failed */
if (errno == EAGAIN) {
-#ifdef THREAD
- thread_sleep(1);
+#ifdef USE_THREAD
+ rb_thread_sleep(1);
#else
sleep(1);
#endif
@@ -1001,9 +1269,10 @@ pipe_open(pname, mode)
break;
default: /* parent */
- {
+ if (pid < 0) rb_sys_fail(pname);
+ else {
NEWOBJ(port, struct RFile);
- OBJSETUP(port, cIO, T_FILE);
+ OBJSETUP(port, rb_cIO, T_FILE);
MakeOpenFile(port, fptr);
fptr->mode = modef;
fptr->mode |= FMODE_SYNC;
@@ -1021,16 +1290,22 @@ pipe_open(pname, mode)
else fptr->f = f;
}
#if defined (__CYGWIN32__)
+ fptr->finalize = pipe_finalize;
pipe_add_fptr(fptr);
#endif
+ rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
}
#endif
+#else /* USE_CWGUSI */
+ rb_notimplement();
+ return Qnil; /* not reached */
+#endif
}
static VALUE
-io_s_popen(argc, argv, self)
+rb_io_s_popen(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
@@ -1038,34 +1313,35 @@ io_s_popen(argc, argv, self)
char *mode;
VALUE pname, pmode;
- rb_scan_args(argc, argv, "11", &pname, &pmode);
- Check_SafeStr(pname);
- if (NIL_P(pmode)) {
+ if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
mode = "r";
}
else {
- Check_Type(pmode, T_STRING);
- if (RSTRING(pmode)->len == 0 || RSTRING(pmode)->len > 3)
- ArgError("illegal access mode");
- mode = RSTRING(pmode)->ptr;
- }
+ int len;
+
+ mode = STR2CSTR(pmode);
+ len = strlen(mode);
+ if (len == 0 || len > 3)
+ rb_raise(rb_eArgError, "illegal access mode");
+ }
+ Check_SafeStr(pname);
return pipe_open(RSTRING(pname)->ptr, mode);
}
static VALUE
-io_open(fname, mode)
+rb_io_open(fname, mode)
char *fname, *mode;
{
if (fname[0] == '|') {
return pipe_open(fname+1, mode);
}
else {
- return file_open(fname, mode);
+ return rb_file_open(fname, mode);
}
}
static VALUE
-f_open(argc, argv)
+rb_f_open(argc, argv)
int argc;
VALUE *argv;
{
@@ -1079,26 +1355,31 @@ f_open(argc, argv)
mode = "r";
}
else {
- Check_Type(pmode, T_STRING);
- if (RSTRING(pmode)->len == 0 || RSTRING(pmode)->len > 3)
- ArgError("illegal access mode");
- mode = RSTRING(pmode)->ptr;
+ int len;
+
+ mode = STR2CSTR(pmode);
+ len = strlen(mode);
+ if (len == 0 || len > 3)
+ rb_raise(rb_eArgError, "illegal access mode");
}
- port = io_open(RSTRING(pname)->ptr, mode);
- if (iterator_p()) {
- rb_ensure(rb_yield, port, io_close, port);
+ port = rb_io_open(RSTRING(pname)->ptr, mode);
+ if (rb_iterator_p()) {
+ return rb_ensure(rb_yield, port, rb_io_close, port);
}
return port;
}
-#ifndef NT
-extern char *strdup();
-#endif
+static VALUE
+rb_io_get_io(io)
+ VALUE io;
+{
+ return rb_convert_type(io, T_FILE, "IO", "to_io");
+}
static char*
-io_mode_string(fptr)
+rb_io_mode_string(fptr)
OpenFile *fptr;
{
switch (fptr->mode & FMODE_READWRITE) {
@@ -1110,19 +1391,19 @@ io_mode_string(fptr)
case FMODE_READWRITE:
return "r+";
}
- return "r";
}
VALUE
-io_reopen(io, nfile)
+rb_io_reopen(io, nfile)
VALUE io, nfile;
{
OpenFile *fptr, *orig;
char *mode;
int fd;
+ rb_secure(4);
GetOpenFile(io, fptr);
- Check_Type(nfile, T_FILE);
+ nfile = rb_io_get_io(nfile);
GetOpenFile(nfile, orig);
if (orig->f2) {
@@ -1141,20 +1422,27 @@ io_reopen(io, nfile)
else fptr->path = 0;
fptr->finalize = orig->finalize;
- mode = io_mode_string(fptr);
+ mode = rb_io_mode_string(fptr);
fd = fileno(fptr->f);
- if (fileno(fptr->f) < 3) /* need to keep stdio */
+ if (fd < 3) {
+ /* need to keep stdio */
+ if (dup2(fileno(orig->f), fd) < 0)
+ rb_sys_fail(orig->path);
+ }
+ else {
fclose(fptr->f);
- dup2(fileno(orig->f), fd);
- fptr->f = rb_fdopen(fd, mode);
+ if (dup2(fileno(orig->f), fd) < 0)
+ rb_sys_fail(orig->path);
+ fptr->f = rb_fdopen(fd, mode);
+ }
if (fptr->f2) {
fd = fileno(fptr->f2);
- if (fileno(fptr->f2) < 3)
- fclose(fptr->f2);
+ fclose(fptr->f2);
if (orig->f2) {
- dup2(fileno(orig->f2), fd);
- fptr->f = rb_fdopen(fd, "w");
+ if (dup2(fileno(orig->f2), fd) < 0)
+ rb_sys_fail(orig->path);
+ fptr->f2 = rb_fdopen(fd, "w");
}
else {
fptr->f2 = 0;
@@ -1162,15 +1450,15 @@ io_reopen(io, nfile)
}
if (fptr->mode & FMODE_BINMODE) {
- io_binmode(io);
+ rb_io_binmode(io);
}
- RBASIC(io)->class = RBASIC(nfile)->class;
+ RBASIC(io)->klass = RBASIC(nfile)->klass;
return io;
}
static VALUE
-io_clone(io)
+rb_io_clone(io)
VALUE io;
{
OpenFile *fptr, *orig;
@@ -1215,25 +1503,25 @@ io_clone(io)
fptr->f = rb_fdopen(fd, "w");
}
if (fptr->mode & FMODE_BINMODE) {
- io_binmode((VALUE)obj);
+ rb_io_binmode((VALUE)obj);
}
return (VALUE)obj;
}
static VALUE
-io_printf(argc, argv, out)
+rb_io_printf(argc, argv, out)
int argc;
VALUE argv[];
VALUE out;
{
- rb_funcall(out, id_write, 1, f_sprintf(argc, argv));
+ rb_funcall(out, id_write, 1, rb_f_sprintf(argc, argv));
return Qnil;
}
static VALUE
-f_printf(argc, argv)
+rb_rb_f_printf(argc, argv)
int argc;
VALUE argv[];
{
@@ -1249,97 +1537,134 @@ f_printf(argc, argv)
argc--;
}
else {
- NameError("output must responds to `write'");
+ rb_raise(rb_eNameError, "output must responds to `write'");
}
- rb_funcall(out, id_write, 1, f_sprintf(argc, argv));
+ rb_funcall(out, id_write, 1, rb_f_sprintf(argc, argv));
return Qnil;
}
static VALUE
-io_print(argc, argv, out)
+rb_io_print(argc, argv, out)
int argc;
VALUE *argv;
VALUE out;
{
- int i, j;
+ int i;
VALUE line;
/* if no argument given, print `$_' */
if (argc == 0) {
argc = 1;
- line = lastline_get();
+ line = rb_lastline_get();
argv = &line;
}
for (i=0; i<argc; i++) {
- if (!NIL_P(OFS) && i>0) {
- io_write(out, OFS);
+ if (!NIL_P(rb_output_fs) && i>0) {
+ rb_io_write(out, rb_output_fs);
}
switch (TYPE(argv[i])) {
case T_NIL:
- io_write(out, str_new2("nil"));
- break;
- case T_ARRAY:
- for (j=0; j<RARRAY(argv[i])->len; j++) {
- if (!NIL_P(OFS) && j>0) {
- io_write(out, OFS);
- }
- io_write(out, RARRAY(argv[i])->ptr[j]);
- }
+ rb_io_write(out, rb_str_new2("nil"));
break;
default:
- io_write(out, argv[i]);
+ rb_io_write(out, argv[i]);
break;
}
}
- if (!NIL_P(ORS)) {
- io_write(out, ORS);
+ if (!NIL_P(rb_output_rs)) {
+ rb_io_write(out, rb_output_rs);
}
return Qnil;
}
static VALUE
-f_print(argc, argv)
+rb_f_print(argc, argv)
int argc;
VALUE *argv;
{
- io_print(argc, argv, rb_defout);
+ rb_io_print(argc, argv, rb_defout);
+ return Qnil;
+}
+
+static VALUE
+rb_io_putc(io, ch)
+ VALUE io, ch;
+{
+ OpenFile *fptr;
+ FILE *f;
+ int c = NUM2CHR(ch);
+
+ rb_secure(4);
+ GetOpenFile(io, fptr);
+ rb_io_check_writable(fptr);
+ f = GetWriteFile(fptr);
+
+ if (fputc(c, f) == EOF || ferror(f))
+ rb_sys_fail(fptr->path);
+ if (fptr->mode & FMODE_SYNC)
+ fflush(f);
+
+ return ch;
+}
+
+static VALUE
+rb_f_putc(recv, ch)
+ VALUE recv, ch;
+{
+ return rb_io_putc(rb_defout, ch);
+}
+
+static VALUE rb_io_puts _((int, VALUE*, VALUE));
+
+static VALUE
+io_puts_ary(ary, out)
+ VALUE ary, out;
+{
+ VALUE tmp;
+ int i;
+
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ tmp = RARRAY(ary)->ptr[i];
+ if (rb_inspecting_p(tmp)) {
+ tmp = rb_str_new2("[...]");
+ }
+ rb_io_puts(1, &tmp, out);
+ }
return Qnil;
}
static VALUE
-io_puts(argc, argv, out)
+rb_io_puts(argc, argv, out)
int argc;
VALUE *argv;
VALUE out;
{
- int i, j;
+ int i;
VALUE line;
/* if no argument given, print newline. */
if (argc == 0) {
- io_write(out, str_new2("\n"));
+ rb_io_write(out, rb_default_rs);
return Qnil;
}
for (i=0; i<argc; i++) {
switch (TYPE(argv[i])) {
case T_NIL:
- line = str_new2("nil");
+ line = rb_str_new2("nil");
break;
case T_ARRAY:
- for (j=0; j<RARRAY(argv[i])->len; j++) {
- io_puts(1, &RARRAY(argv[i])->ptr[j], out);
- }
+ rb_protect_inspect(io_puts_ary, argv[i], out);
continue;
default:
line = argv[i];
break;
}
- line = obj_as_string(line);
- io_write(out, line);
+ line = rb_obj_as_string(line);
+ rb_io_write(out, line);
if (RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') {
- io_write(out, str_new2("\n"));
+ rb_io_write(out, rb_default_rs);
}
}
@@ -1347,122 +1672,127 @@ io_puts(argc, argv, out)
}
static VALUE
-f_puts(argc, argv)
+rb_f_puts(argc, argv)
int argc;
VALUE *argv;
{
- io_puts(argc, argv, rb_defout);
+ rb_io_puts(argc, argv, rb_defout);
return Qnil;
}
+void
+rb_p(obj) /* for debug print within C code */
+ VALUE obj;
+{
+ obj = rb_obj_as_string(rb_inspect(obj));
+ fwrite(RSTRING(obj)->ptr, 1, RSTRING(obj)->len, stdout);
+ obj = rb_default_rs;
+ fwrite(RSTRING(obj)->ptr, 1, RSTRING(obj)->len, stdout);
+}
+
static VALUE
-f_p(obj, val)
- VALUE obj, val;
+rb_f_p(argc, argv)
+ int argc;
+ VALUE *argv;
{
- VALUE str = rb_inspect(val);
+ int i;
- Check_Type(str, T_STRING);
- io_write(rb_defout, str);
- io_write(rb_defout, str_new2("\n"));
+ for (i=0; i<argc; i++) {
+ rb_p(argv[i]);
+ }
return Qnil;
}
-void
-rb_p(obj) /* for debug print within C code */
- VALUE obj;
+static VALUE
+rb_obj_display(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- f_p(Qnil, obj);
+ VALUE out;
+
+ if (rb_scan_args(argc, argv, "01", &out) == 0) {
+ out = rb_defout;
+ }
+
+ rb_io_write(out, self);
+
+ return Qnil;
}
static void
-io_defset(val, id)
+rb_io_defset(val, id)
VALUE val;
ID id;
{
if (TYPE(val) == T_STRING) {
- val = io_open(RSTRING(val)->ptr, "w");
+ val = rb_io_open(RSTRING(val)->ptr, "w");
}
if (!rb_respond_to(val, id_write)) {
- TypeError("$< must have write method, %s given",
- rb_class2name(CLASS_OF(val)));
+ rb_raise(rb_eTypeError, "$< must have write method, %s given",
+ rb_class2name(CLASS_OF(val)));
}
rb_defout = val;
}
static void
-io_errset(val, id)
+rb_io_stdio_set(val, id, var)
VALUE val;
ID id;
+ VALUE *var;
{
OpenFile *fptr;
int fd;
if (TYPE(val) != T_FILE) {
- TypeError("$stderr must be IO Object");
+ rb_raise(rb_eTypeError, "%s must be IO object", rb_id2name(id));
}
+ GetOpenFile(*var, fptr);
+ fd = fileno(fptr->f);
GetOpenFile(val, fptr);
- io_writable(fptr);
- rb_stderr = val;
-
- fd = fileno(fptr->f2?fptr->f2:fptr->f);
- if (fd != 2) {
- FILE *f;
-
- fflush(stderr);
- dup2(fd, 2);
- f = rb_fdopen(2, io_mode_string(fptr));
- if (fptr->f2) {
- if (fileno(fptr->f2) < 3) /* need to keep stdio */
- fclose(fptr->f2);
- fptr->f2 = f;
- }
- else {
- if (fileno(fptr->f) < 3)
- fclose(fptr->f);
- fptr->f = f;
- }
+ if (fd == 0) {
+ rb_io_check_readable(fptr);
}
+ else {
+ rb_io_check_writable(fptr);
+ }
+ rb_io_reopen(*var, val);
}
static VALUE
-prep_stdio(f, mode)
+prep_stdio(f, mode, klass)
FILE *f;
int mode;
+ VALUE klass;
{
OpenFile *fp;
- NEWOBJ(obj, struct RFile);
- OBJSETUP(obj, cIO, T_FILE);
+ NEWOBJ(io, struct RFile);
+ OBJSETUP(io, klass, T_FILE);
- MakeOpenFile(obj, fp);
+ MakeOpenFile(io, fp);
fp->f = f;
fp->mode = mode;
+ rb_obj_call_init((VALUE)io);
- return (VALUE)obj;
+ return (VALUE)io;
}
static VALUE
-io_s_new(argc, argv)
+rb_io_s_new(argc, argv, klass)
int argc;
VALUE *argv;
+ VALUE klass;
{
VALUE fnum, mode;
- FILE *f;
char *m = "r";
- rb_scan_args(argc, argv, "11", &fnum, &mode);
-
- if (!NIL_P(mode)) {
+ if (rb_scan_args(argc, argv, "11", &fnum, &mode) == 2) {
Check_SafeStr(mode);
m = RSTRING(mode)->ptr;
}
- f = rb_fdopen(NUM2INT(fnum), m);
- return prep_stdio(f, io_mode_flags(m));
+ return prep_stdio(rb_fdopen(NUM2INT(fnum), m), rb_io_mode_flags(m), klass);
}
-static VALUE filename, file;
-static int gets_lineno;
-static int init_p = 0, next_p = 0;
-
static int
next_argv()
{
@@ -1485,32 +1815,33 @@ next_argv()
if (next_p == 1) {
next_p = 0;
if (RARRAY(rb_argv)->len > 0) {
- filename = ary_shift(rb_argv);
+ filename = rb_ary_shift(rb_argv);
fn = RSTRING(filename)->ptr;
if (RSTRING(filename)->len == 1 && fn[0] == '-') {
file = rb_stdin;
- if (inplace) {
+ if (ruby_inplace_mode) {
rb_defout = rb_stdout;
}
}
else {
FILE *fr = rb_fopen(fn, "r");
- if (inplace) {
+ if (ruby_inplace_mode) {
struct stat st, st2;
VALUE str;
FILE *fw;
if (TYPE(rb_defout) == T_FILE && rb_defout != rb_stdout) {
- io_close(rb_defout);
+ rb_io_close(rb_defout);
}
fstat(fileno(fr), &st);
- if (*inplace) {
- str = str_new2(fn);
+ if (*ruby_inplace_mode) {
+ str = rb_str_new2(fn);
#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
- add_suffix(str, inplace);
+ ruby_add_suffix(str, ruby_inplace_mode);
#else
- str_cat(str, inplace, strlen(inplace));
+ rb_str_cat(str, ruby_inplace_mode,
+ strlen(ruby_inplace_mode));
#endif
#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__)
(void)fclose(fr);
@@ -1519,7 +1850,7 @@ next_argv()
fr = rb_fopen(RSTRING(str)->ptr, "r");
#else
if (rename(fn, RSTRING(str)->ptr) < 0) {
- Warning("Can't rename %s to %s: %s, skipping file",
+ rb_warn("Can't rename %s to %s: %s, skipping file",
fn, RSTRING(str)->ptr, strerror(errno));
fclose(fr);
goto retry;
@@ -1529,38 +1860,39 @@ next_argv()
else {
#if !defined(MSDOS) && !defined(__BOW__) && !defined(__CYGWIN32__) && !defined(NT) && !defined(__human68k__)
if (unlink(fn) < 0) {
- Warning("Can't remove %s: %s, skipping file",
- fn, strerror(errno));
+ rb_warn("Can't remove %s: %s, skipping file",
+ fn, strerror(errno));
fclose(fr);
goto retry;
}
#else
- Fatal("Can't do inplace edit without backup");
+ rb_fatal("Can't do inplace edit without backup");
#endif
}
fw = rb_fopen(fn, "w");
-#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__)
+#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__)\
+ && !defined(USE_CWGUSI) && !defined(__BEOS__)
fstat(fileno(fw), &st2);
fchmod(fileno(fw), st.st_mode);
if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
fchown(fileno(fw), st.st_uid, st.st_gid);
}
#endif
- rb_defout = prep_stdio(fw, FMODE_WRITABLE);
+ rb_defout = prep_stdio(fw, FMODE_WRITABLE, rb_cFile);
}
- file = prep_stdio(fr, FMODE_READABLE);
+ file = prep_stdio(fr, FMODE_READABLE, rb_cFile);
}
}
else {
init_p = 0;
- return FALSE;
+ return Qfalse;
}
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-f_gets_method(argc, argv)
+rb_f_gets_internal(argc, argv)
int argc;
VALUE *argv;
{
@@ -1568,9 +1900,9 @@ f_gets_method(argc, argv)
retry:
if (!next_argv()) return Qnil;
- line = io_gets_method(argc, argv, file);
+ line = rb_io_gets_internal(argc, argv, file);
if (NIL_P(line) && next_p != -1) {
- io_close(file);
+ rb_io_close(file);
next_p = 1;
goto retry;
}
@@ -1580,76 +1912,133 @@ f_gets_method(argc, argv)
return line;
}
+static VALUE
+rb_f_gets(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE line = rb_f_gets_internal(argc, argv);
+
+ if (!NIL_P(line)) rb_lastline_set(line);
+ return line;
+}
+
VALUE
-f_gets()
+rb_gets()
{
- return f_gets_method(0,0);
+ VALUE line;
+
+ retry:
+ if (!next_argv()) return Qnil;
+ line = rb_io_gets(file);
+ if (NIL_P(line) && next_p != -1) {
+ rb_io_close(file);
+ next_p = 1;
+ goto retry;
+ }
+ if (!NIL_P(line)) {
+ rb_lastline_set(line);
+ gets_lineno++;
+ lineno = INT2FIX(gets_lineno);
+ }
+
+ return line;
}
static VALUE
-f_readline(argc, argv)
+rb_f_readline(argc, argv)
int argc;
- VALUE argv;
+ VALUE *argv;
{
- VALUE line = f_gets_method(argc, argv);
+ VALUE line = rb_f_gets(argc, argv);
if (NIL_P(line)) {
- eof_error();
+ rb_eof_error();
}
return line;
}
static VALUE
-f_eof()
+rb_f_tell()
+{
+ return rb_io_tell(file);
+}
+
+static VALUE
+rb_f_seek(self, offset, ptrname)
+ VALUE self, offset, ptrname;
+{
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to seek");
+ }
+
+ return rb_io_seek(file, offset, ptrname);
+}
+
+static VALUE
+rb_f_set_pos(self, offset)
+ VALUE self, offset;
+{
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to pos");
+ }
+
+ return rb_io_set_pos(file, offset);
+}
+
+static VALUE
+rb_f_rewind()
+{
+ return rb_io_rewind(file);
+}
+
+static VALUE
+rb_f_eof()
{
if (init_p == 0 && !next_argv())
- return TRUE;
- if (io_eof(file)) {
+ return Qtrue;
+ if (rb_io_eof(file)) {
next_p = 1;
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-f_getc()
+rb_f_getc()
{
- return io_getc(rb_stdin);
+ return rb_io_getc(rb_stdin);
}
static VALUE
-f_ungetc(obj, c)
- VALUE obj, c;
+rb_f_ungetc(self, c)
+ VALUE self, c;
{
- if (!next_argv()) {
- ArgError("no stream to ungetc");
- }
-
- return io_ungetc(file, c);
+ return rb_io_ungetc(rb_stdin, c);
}
static VALUE
-f_readchar()
+rb_f_readchar()
{
- VALUE c = f_getc();
+ VALUE c = rb_f_getc();
if (NIL_P(c)) {
- eof_error();
+ rb_eof_error();
}
return c;
}
static VALUE
-f_readlines(argc, argv)
+rb_f_readlines(argc, argv)
int argc;
- VALUE argv;
+ VALUE *argv;
{
VALUE line, ary;
- ary = ary_new();
- while (!NIL_P(line = f_gets_method(argc, argv))) {
- ary_push(ary, line);
+ ary = rb_ary_new();
+ while (!NIL_P(line = rb_f_gets_internal(argc, argv))) {
+ rb_ary_push(ary, line);
}
return ary;
@@ -1662,13 +2051,13 @@ rb_str_setter(val, id, var)
VALUE *var;
{
if (!NIL_P(val) && TYPE(val) != T_STRING) {
- TypeError("value of %s must be String", rb_id2name(id));
+ rb_raise(rb_eTypeError, "value of %s must be String", rb_id2name(id));
}
*var = val;
}
static VALUE
-f_backquote(obj, str)
+rb_f_backquote(obj, str)
VALUE obj, str;
{
VALUE port, result;
@@ -1677,9 +2066,9 @@ f_backquote(obj, str)
port = pipe_open(RSTRING(str)->ptr, "r");
result = read_all(port);
- io_close(port);
+ rb_io_close(port);
- if (NIL_P(result)) return str_new(0,0);
+ if (NIL_P(result)) return rb_str_new(0,0);
return result;
}
@@ -1691,7 +2080,7 @@ f_backquote(obj, str)
#endif
static VALUE
-f_select(argc, argv, obj)
+rb_f_select(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -1702,7 +2091,7 @@ f_select(argc, argv, obj)
struct timeval *tp, timerec;
OpenFile *fptr;
int i, max = 0, n;
- int interrupt = 0;
+ int interrupt_flag = 0;
int pending = 0;
rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout);
@@ -1710,20 +2099,19 @@ f_select(argc, argv, obj)
tp = NULL;
}
else {
- timerec = time_timeval(timeout);
+ timerec = rb_time_timeval(timeout);
tp = &timerec;
}
FD_ZERO(&pset);
if (!NIL_P(read)) {
-
Check_Type(read, T_ARRAY);
rp = &rset;
FD_ZERO(rp);
for (i=0; i<RARRAY(read)->len; i++) {
- Check_Type(RARRAY(read)->ptr[i], T_FILE);
- GetOpenFile(RARRAY(read)->ptr[i], fptr);
- if (fptr->f == NULL) closed();
+ VALUE io = rb_io_get_io(RARRAY(read)->ptr[i]);
+
+ GetOpenFile(io, fptr);
FD_SET(fileno(fptr->f), rp);
if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
pending++;
@@ -1744,14 +2132,14 @@ f_select(argc, argv, obj)
wp = &wset;
FD_ZERO(wp);
for (i=0; i<RARRAY(write)->len; i++) {
- Check_Type(RARRAY(write)->ptr[i], T_FILE);
- GetOpenFile(RARRAY(write)->ptr[i], fptr);
- if (fptr->f == NULL) closed();
+ VALUE io = rb_io_get_io(RARRAY(write)->ptr[i]);
+
+ GetOpenFile(io, fptr);
FD_SET(fileno(fptr->f), wp);
- if (max > fileno(fptr->f)) max = fileno(fptr->f);
+ if (max < fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
FD_SET(fileno(fptr->f2), wp);
- if (max < (int)fileno(fptr->f2)) max = fileno(fptr->f2);
+ if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
}
}
}
@@ -1763,14 +2151,14 @@ f_select(argc, argv, obj)
ep = &eset;
FD_ZERO(ep);
for (i=0; i<RARRAY(except)->len; i++) {
- Check_Type(RARRAY(except)->ptr[i], T_FILE);
- GetOpenFile(RARRAY(except)->ptr[i], fptr);
- if (fptr->f == NULL) closed();
+ VALUE io = rb_io_get_io(RARRAY(except)->ptr[i]);
+
+ GetOpenFile(io, fptr);
FD_SET(fileno(fptr->f), ep);
if (max < fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
FD_SET(fileno(fptr->f2), ep);
- if (max > (int)fileno(fptr->f2)) max = fileno(fptr->f2);
+ if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
}
}
}
@@ -1779,8 +2167,8 @@ f_select(argc, argv, obj)
max++;
-#ifdef THREAD
- n = thread_select(max, rp, wp, ep, tp);
+#ifdef USE_THREAD
+ n = rb_thread_select(max, rp, wp, ep, tp);
if (n < 0) {
rb_sys_fail(0);
}
@@ -1794,24 +2182,24 @@ f_select(argc, argv, obj)
rb_sys_fail(0);
}
if (tp == NULL) goto retry;
- interrupt = 1;
+ interrupt_flag = 1;
}
#endif
if (!pending && n == 0) return Qnil; /* returns nil on timeout */
- res = ary_new2(3);
- ary_push(res, rp?ary_new():ary_new2(0));
- ary_push(res, wp?ary_new():ary_new2(0));
- ary_push(res, ep?ary_new():ary_new2(0));
+ res = rb_ary_new2(3);
+ rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
+ rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
+ rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
- if (interrupt == 0) {
+ if (interrupt_flag == 0) {
if (rp) {
list = RARRAY(res)->ptr[0];
for (i=0; i< RARRAY(read)->len; i++) {
GetOpenFile(RARRAY(read)->ptr[i], fptr);
if (FD_ISSET(fileno(fptr->f), rp)
|| FD_ISSET(fileno(fptr->f), &pset)) {
- ary_push(list, RARRAY(read)->ptr[i]);
+ rb_ary_push(list, RARRAY(read)->ptr[i]);
}
}
}
@@ -1821,10 +2209,10 @@ f_select(argc, argv, obj)
for (i=0; i< RARRAY(write)->len; i++) {
GetOpenFile(RARRAY(write)->ptr[i], fptr);
if (FD_ISSET(fileno(fptr->f), wp)) {
- ary_push(list, RARRAY(write)->ptr[i]);
+ rb_ary_push(list, RARRAY(write)->ptr[i]);
}
else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), wp)) {
- ary_push(list, RARRAY(write)->ptr[i]);
+ rb_ary_push(list, RARRAY(write)->ptr[i]);
}
}
}
@@ -1834,10 +2222,10 @@ f_select(argc, argv, obj)
for (i=0; i< RARRAY(except)->len; i++) {
GetOpenFile(RARRAY(except)->ptr[i], fptr);
if (FD_ISSET(fileno(fptr->f), ep)) {
- ary_push(list, RARRAY(except)->ptr[i]);
+ rb_ary_push(list, RARRAY(except)->ptr[i]);
}
else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), ep)) {
- ary_push(list, RARRAY(except)->ptr[i]);
+ rb_ary_push(list, RARRAY(except)->ptr[i]);
}
}
}
@@ -1847,27 +2235,28 @@ f_select(argc, argv, obj)
}
static VALUE
-io_ctl(io, req, arg, io_p)
+rb_io_ctl(io, req, arg, io_p)
VALUE io, req, arg;
int io_p;
{
#if !defined(MSDOS) && !defined(__human68k__)
int cmd = NUM2INT(req);
OpenFile *fptr;
- int len, fd;
+ int len = 0;
+ int fd;
long narg = 0;
int retval;
rb_secure(2);
GetOpenFile(io, fptr);
- if (NIL_P(arg) || (VALUE)arg == FALSE) {
+ if (NIL_P(arg) || arg == Qfalse) {
narg = 0;
}
else if (FIXNUM_P(arg)) {
narg = FIX2INT(arg);
}
- else if ((VALUE)arg == TRUE) {
+ else if (arg == Qtrue) {
narg = 1;
}
else {
@@ -1883,38 +2272,47 @@ io_ctl(io, req, arg, io_p)
#else
len = 256; /* otherwise guess at what's safe */
#endif
- str_modify(arg);
+ rb_str_modify(arg);
if (len <= RSTRING(arg)->len) {
len = RSTRING(arg)->len;
}
if (RSTRING(arg)->len < len) {
- str_resize(arg, len+1);
+ rb_str_resize(arg, len+1);
}
RSTRING(arg)->ptr[len] = 17; /* a little sanity check here */
narg = (long)RSTRING(arg)->ptr;
}
fd = fileno(fptr->f);
#ifdef HAVE_FCNTL
+ TRAP_BEG;
+# ifdef USE_CWGUSI
+ retval = io_p?ioctl(fd, cmd, (void*) narg):fcntl(fd, cmd, narg);
+# else
retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg);
+# endif
+ TRAP_END;
#else
if (!io_p) {
rb_notimplement();
}
+ TRAP_BEG;
retval = ioctl(fd, cmd, narg);
+ TRAP_END;
#endif
if (retval < 0) rb_sys_fail(fptr->path);
if (TYPE(arg) == T_STRING && RSTRING(arg)->ptr[len] != 17) {
- ArgError("return value overflowed string");
+ rb_raise(rb_eArgError, "return value overflowed string");
}
return INT2NUM(retval);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
static VALUE
-io_ioctl(argc, argv, io)
+rb_io_ioctl(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -1922,11 +2320,11 @@ io_ioctl(argc, argv, io)
VALUE req, arg;
rb_scan_args(argc, argv, "11", &req, &arg);
- return io_ctl(io, req, arg, 1);
+ return rb_io_ctl(io, req, arg, 1);
}
static VALUE
-io_fcntl(argc, argv, io)
+rb_io_fcntl(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -1935,14 +2333,15 @@ io_fcntl(argc, argv, io)
VALUE req, arg;
rb_scan_args(argc, argv, "11", &req, &arg);
- return io_ctl(io, req, arg, 0);
+ return rb_io_ctl(io, req, arg, 0);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
static VALUE
-f_syscall(argc, argv)
+rb_f_syscall(argc, argv)
int argc;
VALUE *argv;
{
@@ -1962,6 +2361,8 @@ f_syscall(argc, argv)
*/
rb_secure(2);
+ if (argc == 0)
+ rb_raise(rb_eArgError, "too few arguments for syscall");
arg[0] = NUM2INT(argv[0]); argv++;
while (items--) {
if (FIXNUM_P(*argv)) {
@@ -1969,14 +2370,13 @@ f_syscall(argc, argv)
}
else {
Check_Type(*argv, T_STRING);
- str_modify(*argv);
+ rb_str_modify(*argv);
arg[i] = (unsigned long)RSTRING(*argv)->ptr; argv++;
}
i++;
}
+ TRAP_BEG;
switch (argc) {
- case 0:
- ArgError("Too few args to syscall");
case 1:
retval = syscall(arg[0]);
break;
@@ -2029,15 +2429,17 @@ f_syscall(argc, argv)
break;
#endif /* atarist */
}
+ TRAP_END;
if (retval == -1) rb_sys_fail(0);
return INT2FIX(0);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
static VALUE
-io_s_pipe()
+rb_io_s_pipe()
{
#ifndef __human68k__
int pipes[2];
@@ -2050,16 +2452,17 @@ io_s_pipe()
#endif
rb_sys_fail(0);
- r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE);
- w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE);
+ r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
+ w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO);
- ary = ary_new2(2);
- ary_push(ary, r);
- ary_push(ary, w);
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, r);
+ rb_ary_push(ary, w);
return ary;
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
@@ -2070,19 +2473,19 @@ struct foreach_arg {
};
static VALUE
-io_foreach_line(arg)
+rb_io_foreach_line(arg)
struct foreach_arg *arg;
{
VALUE str;
- while (!NIL_P(str = io_gets_method(arg->argc, &arg->sep, arg->io))) {
+ while (!NIL_P(str = rb_io_gets_internal(arg->argc, &arg->sep, arg->io))) {
rb_yield(str);
}
return Qnil;
}
static VALUE
-io_s_foreach(argc, argv, io)
+rb_io_s_foreach(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -2094,26 +2497,26 @@ io_s_foreach(argc, argv, io)
Check_SafeStr(fname);
arg.argc = argc - 1;
- arg.io = io_open(RSTRING(fname)->ptr, "r");
- return rb_ensure(io_foreach_line, &arg, io_close, arg.io);
+ arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
+ return rb_ensure(rb_io_foreach_line, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE
-io_readline_line(arg)
+rb_io_readline_line(arg)
struct foreach_arg *arg;
{
VALUE line, ary;
- ary = ary_new();
- while (!NIL_P(line = io_gets_method(arg->argc, &arg->sep, arg->io))) {
- ary_push(ary, line);
+ ary = rb_ary_new();
+ while (!NIL_P(line = rb_io_gets_internal(arg->argc, &arg->sep, arg->io))) {
+ rb_ary_push(ary, line);
}
return ary;
}
static VALUE
-io_s_readlines(argc, argv, io)
+rb_io_s_readlines(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -2125,14 +2528,20 @@ io_s_readlines(argc, argv, io)
Check_SafeStr(fname);
arg.argc = argc - 1;
- arg.io = io_open(RSTRING(fname)->ptr, "r");
- return rb_ensure(io_readline_line, &arg, io_close, arg.io);
+ arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
+ return rb_ensure(rb_io_readline_line, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE
arg_fileno()
{
- return io_fileno(file);
+ return rb_io_fileno(file);
+}
+
+static VALUE
+arg_to_io()
+{
+ return file;
}
static VALUE
@@ -2141,22 +2550,22 @@ arg_read(argc, argv)
VALUE *argv;
{
VALUE tmp, str;
- int len;
+ size_t len;
if (argc == 1) len = NUM2INT(argv[0]);
str = Qnil;
retry:
if (!next_argv()) return str;
- tmp = io_read(argc, argv, file);
+ tmp = rb_io_read(argc, argv, file);
if (NIL_P(tmp) && next_p != -1) {
- io_close(file);
+ rb_io_close(file);
next_p = 1;
goto retry;
}
- if (NIL_P(tmp)) return str;
+ if (NIL_P(tmp) || RSTRING(tmp)->len == 0) return str;
else if (NIL_P(str)) str = tmp;
- else str_cat(str, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
+ else rb_str_cat(str, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
if (argc == 0) {
goto retry;
}
@@ -2176,9 +2585,9 @@ arg_getc()
retry:
if (!next_argv()) return Qnil;
- byte = io_getc(file);
+ byte = rb_io_getc(file);
if (NIL_P(byte) && next_p != -1) {
- io_close(file);
+ rb_io_close(file);
next_p = 1;
goto retry;
}
@@ -2189,10 +2598,10 @@ arg_getc()
static VALUE
arg_readchar()
{
- VALUE c = io_getc(file);
+ VALUE c = rb_io_getc(file);
if (NIL_P(c)) {
- eof_error();
+ rb_eof_error();
}
return c;
}
@@ -2200,11 +2609,11 @@ arg_readchar()
static VALUE
arg_each_line(argc, argv)
int argc;
- VALUE argv;
+ VALUE *argv;
{
VALUE str;
- while (RTEST(str = f_gets_method(argc, argv))) {
+ while (RTEST(str = rb_f_gets_internal(argc, argv))) {
rb_yield(str);
}
return Qnil;
@@ -2237,7 +2646,7 @@ static VALUE
arg_skip()
{
if (next_p != -1) {
- io_close(file);
+ rb_io_close(file);
next_p = 1;
}
return argf;
@@ -2246,7 +2655,7 @@ arg_skip()
static VALUE
arg_close()
{
- io_close(file);
+ rb_io_close(file);
if (next_p != -1) {
next_p = 1;
}
@@ -2257,162 +2666,186 @@ arg_close()
static VALUE
arg_closed()
{
- return io_closed(file);
+ return rb_io_closed(file);
}
static VALUE
opt_i_get()
{
- if (!inplace) return Qnil;
- return str_new2(inplace);
+ if (!ruby_inplace_mode) return Qnil;
+ return rb_str_new2(ruby_inplace_mode);
}
static void
opt_i_set(val)
VALUE val;
{
- if (NIL_P(val)) {
- inplace = 0;
+ if (!RTEST(val)) {
+ ruby_inplace_mode = 0;
return;
}
- Check_Type(val, T_STRING);
- inplace = RSTRING(val)->ptr;
+ ruby_inplace_mode = STR2CSTR(val);
}
void
Init_IO()
{
- extern VALUE mEnumerable;
- extern VALUE eException;
-
- eEOFError = rb_define_class("EOFError", eException);
+ rb_eIOError = rb_define_class("IOError", rb_eStandardError);
+ rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
id_write = rb_intern("write");
- rb_define_global_function("syscall", f_syscall, -1);
-
- rb_define_global_function("open", f_open, -1);
- rb_define_global_function("printf", f_printf, -1);
- rb_define_global_function("print", f_print, -1);
- rb_define_global_function("puts", f_puts, -1);
- rb_define_global_function("gets", f_gets_method, -1);
- rb_define_global_function("readline", f_readline, -1);
- rb_define_global_function("eof", f_eof, 0);
- rb_define_global_function("eof?", f_eof, 0);
- rb_define_global_function("getc", f_getc, 0);
- rb_define_global_function("readchar", f_readchar, 0);
- rb_define_global_function("select", f_select, -1);
- rb_define_global_function("ungetc", f_ungetc, 1);
-
- rb_define_global_function("readlines", f_readlines, -1);
-
- rb_define_global_function("`", f_backquote, 1);
- rb_define_global_function("pipe", io_s_pipe, 0);
-
- rb_define_global_function("p", f_p, 1);
-
- cIO = rb_define_class("IO", cObject);
- rb_include_module(cIO, mEnumerable);
-
- rb_define_singleton_method(cIO, "new", io_s_new, -1);
- rb_define_singleton_method(cIO, "popen", io_s_popen, -1);
- rb_define_singleton_method(cIO, "foreach", io_s_foreach, -1);
- rb_define_singleton_method(cIO, "readlines", io_s_readlines, -1);
- rb_define_singleton_method(cIO, "select", f_select, -1);
-
- FS = OFS = Qnil;
- rb_define_hooked_variable("$;", &FS, 0, rb_str_setter);
- rb_define_hooked_variable("$-F", &FS, 0, rb_str_setter);
- rb_define_hooked_variable("$,", &OFS, 0, rb_str_setter);
-
- RS = RS_default = str_new2("\n"); ORS = Qnil;
- rb_global_variable(&RS_default);
- rb_define_hooked_variable("$/", &RS, 0, rb_str_setter);
- rb_define_hooked_variable("$-0", &RS, 0, rb_str_setter);
- rb_define_hooked_variable("$\\", &ORS, 0, rb_str_setter);
-
- rb_define_variable("$.", &lineno);
- rb_define_virtual_variable("$_", lastline_get, lastline_set);
-
- rb_define_method(cIO, "clone", io_clone, 0);
- rb_define_method(cIO, "reopen", io_reopen, 1);
-
- rb_define_method(cIO, "print", io_print, -1);
- rb_define_method(cIO, "puts", io_puts, -1);
- rb_define_method(cIO, "printf", io_printf, -1);
-
- rb_define_method(cIO, "each", io_each_line, -1);
- rb_define_method(cIO, "each_line", io_each_line, -1);
- rb_define_method(cIO, "each_byte", io_each_byte, 0);
-
- rb_define_method(cIO, "syswrite", io_syswrite, 1);
- rb_define_method(cIO, "sysread", io_sysread, 1);
-
- rb_define_method(cIO, "fileno", io_fileno, 0);
- rb_define_alias(cIO, "to_i", "fileno");
-
- rb_define_method(cIO, "sync", io_sync, 0);
- rb_define_method(cIO, "sync=", io_set_sync, 1);
-
- rb_define_method(cIO, "readlines", io_readlines, -1);
-
- rb_define_method(cIO, "read", io_read, -1);
- rb_define_method(cIO, "write", io_write, 1);
- rb_define_method(cIO, "gets", io_gets_method, -1);
- rb_define_method(cIO, "readline", io_readline, -1);
- rb_define_method(cIO, "getc", io_getc, 0);
- rb_define_method(cIO, "readchar", io_readchar, 0);
- rb_define_method(cIO, "ungetc",io_ungetc, 1);
- rb_define_method(cIO, "<<", io_addstr, 1);
- rb_define_method(cIO, "flush", io_flush, 0);
- rb_define_method(cIO, "eof", io_eof, 0);
- rb_define_method(cIO, "eof?", io_eof, 0);
-
- rb_define_method(cIO, "close", io_close, 0);
- rb_define_method(cIO, "closed?", io_closed, 0);
-
- rb_define_method(cIO, "isatty", io_isatty, 0);
- rb_define_method(cIO, "tty?", io_isatty, 0);
- rb_define_method(cIO, "binmode", io_binmode, 0);
-
- rb_define_method(cIO, "ioctl", io_ioctl, -1);
- rb_define_method(cIO, "fcntl", io_fcntl, -1);
-
- rb_stdin = prep_stdio(stdin, FMODE_READABLE);
- rb_define_readonly_variable("$stdin", &rb_stdin);
- rb_stdout = prep_stdio(stdout, FMODE_WRITABLE);
- rb_define_readonly_variable("$stdout", &rb_stdout);
- rb_stderr = prep_stdio(stderr, FMODE_WRITABLE);
- rb_define_hooked_variable("$stderr", &rb_stderr, 0, io_errset);
+ rb_define_global_function("syscall", rb_f_syscall, -1);
+
+ rb_define_global_function("open", rb_f_open, -1);
+ rb_define_global_function("printf", rb_rb_f_printf, -1);
+ rb_define_global_function("print", rb_f_print, -1);
+ rb_define_global_function("putc", rb_f_putc, 1);
+ rb_define_global_function("puts", rb_f_puts, -1);
+ rb_define_global_function("gets", rb_f_gets, -1);
+ rb_define_global_function("readline", rb_f_readline, -1);
+ rb_define_global_function("tell", rb_f_tell, 0);
+ rb_define_global_function("seek", rb_f_seek, 2);
+ rb_define_global_function("rewind", rb_f_rewind, 0);
+ rb_define_global_function("eof", rb_f_eof, 0);
+ rb_define_global_function("eof?", rb_f_eof, 0);
+ rb_define_global_function("getc", rb_f_getc, 0);
+ rb_define_global_function("readchar", rb_f_readchar, 0);
+ rb_define_global_function("select", rb_f_select, -1);
+ rb_define_global_function("ungetc", rb_f_ungetc, 1);
+
+ rb_define_global_function("readlines", rb_f_readlines, -1);
+
+ rb_define_global_function("`", rb_f_backquote, 1);
+ rb_define_global_function("pipe", rb_io_s_pipe, 0);
+
+ rb_define_global_function("p", rb_f_p, -1);
+ rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
+
+ rb_cIO = rb_define_class("IO", rb_cObject);
+ rb_include_module(rb_cIO, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
+ rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
+ rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
+ rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
+ rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
+
+ rb_fs = rb_output_fs = Qnil;
+ rb_define_hooked_variable("$;", &rb_fs, 0, rb_str_setter);
+ rb_define_hooked_variable("$-F", &rb_fs, 0, rb_str_setter);
+ rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
+
+ rb_rs = rb_default_rs = rb_str_new2("\n"); rb_output_rs = Qnil;
+ rb_global_variable(&rb_default_rs);
+ rb_str_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_hooked_variable("$.", &lineno, 0, lineno_setter);
+ rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
+
+ rb_define_method(rb_cIO, "clone", rb_io_clone, 0);
+ rb_define_method(rb_cIO, "reopen", rb_io_reopen, 1);
+
+ rb_define_method(rb_cIO, "print", rb_io_print, -1);
+ rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
+ rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
+ rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
+
+ rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
+ rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
+ rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
+
+ rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
+ rb_define_method(rb_cIO, "sysread", rb_io_sysread, 1);
+
+ rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
+ rb_define_alias(rb_cIO, "to_i", "fileno");
+ rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
+
+ rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
+ rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
+
+ rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
+ rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
+
+ rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
+
+ rb_define_method(rb_cIO, "read", rb_io_read, -1);
+ rb_define_method(rb_cIO, "write", rb_io_write, 1);
+ rb_define_method(rb_cIO, "gets", rb_io_gets_method, -1);
+ rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
+ rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
+ rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
+ rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
+ rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
+ rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
+ rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
+ rb_define_method(rb_cIO, "seek", rb_io_seek, 2);
+ rb_define_const(rb_cIO, "SEEK_SET", SEEK_SET);
+ rb_define_const(rb_cIO, "SEEK_CUR", SEEK_CUR);
+ rb_define_const(rb_cIO, "SEEK_END", SEEK_END);
+ rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
+ rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
+ rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
+ rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
+ rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
+
+ rb_define_method(rb_cIO, "close", rb_io_close_method, 0);
+ rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
+ rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
+ rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
+
+ rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
+ rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
+ rb_define_method(rb_cIO, "binmode", rb_io_binmode, 0);
+
+ rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
+ rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
+
+ rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO);
+ rb_define_hooked_variable("$stdin", &rb_stdin, 0, rb_io_stdio_set);
+ rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO);
+ rb_define_hooked_variable("$stdout", &rb_stdout, 0, rb_io_stdio_set);
+ rb_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO);
+ rb_define_hooked_variable("$stderr", &rb_stderr, 0, rb_io_stdio_set);
rb_defout = rb_stdout;
- rb_define_hooked_variable("$>", &rb_defout, 0, io_defset);
+ rb_define_hooked_variable("$>", &rb_defout, 0, rb_io_defset);
rb_define_global_const("STDIN", rb_stdin);
rb_define_global_const("STDOUT", rb_stdout);
rb_define_global_const("STDERR", rb_stderr);
- argf = obj_alloc(cObject);
- rb_extend_object(argf, mEnumerable);
+ argf = rb_obj_alloc(rb_cObject);
+ rb_extend_object(argf, rb_mEnumerable);
rb_define_readonly_variable("$<", &argf);
rb_define_global_const("ARGF", argf);
rb_define_singleton_method(argf, "fileno", arg_fileno, 0);
rb_define_singleton_method(argf, "to_i", arg_fileno, 0);
+ rb_define_singleton_method(argf, "to_io", arg_to_io, 0);
rb_define_singleton_method(argf, "each", arg_each_line, -1);
rb_define_singleton_method(argf, "each_line", arg_each_line, -1);
rb_define_singleton_method(argf, "each_byte", arg_each_byte, 0);
rb_define_singleton_method(argf, "read", arg_read, -1);
- rb_define_singleton_method(argf, "readlines", f_readlines, -1);
- rb_define_singleton_method(argf, "to_a", f_readlines, -1);
- rb_define_singleton_method(argf, "gets", f_gets_method, -1);
- rb_define_singleton_method(argf, "readline", f_readline, -1);
+ rb_define_singleton_method(argf, "readlines", rb_f_readlines, -1);
+ rb_define_singleton_method(argf, "to_a", rb_f_readlines, -1);
+ rb_define_singleton_method(argf, "gets", rb_f_gets, -1);
+ rb_define_singleton_method(argf, "readline", rb_f_readline, -1);
rb_define_singleton_method(argf, "getc", arg_getc, 0);
rb_define_singleton_method(argf, "readchar", arg_readchar, 0);
- rb_define_singleton_method(argf, "eof", f_eof, 0);
- rb_define_singleton_method(argf, "eof?", f_eof, 0);
- rb_define_singleton_method(argf, "ungetc", f_ungetc, 1);
+ rb_define_singleton_method(argf, "tell", rb_f_tell, 0);
+ rb_define_singleton_method(argf, "seek", rb_f_seek, 2);
+ rb_define_singleton_method(argf, "rewind", rb_f_rewind, 0);
+ rb_define_singleton_method(argf, "pos", rb_f_tell, 0);
+ rb_define_singleton_method(argf, "pos=", rb_f_set_pos, 1);
+ rb_define_singleton_method(argf, "eof", rb_f_eof, 0);
+ rb_define_singleton_method(argf, "eof?", rb_f_eof, 0);
+ rb_define_singleton_method(argf, "ungetc", rb_f_ungetc, 1);
rb_define_singleton_method(argf, "to_s", arg_filename, 0);
rb_define_singleton_method(argf, "filename", arg_filename, 0);
@@ -2421,15 +2854,16 @@ Init_IO()
rb_define_singleton_method(argf, "close", arg_close, 0);
rb_define_singleton_method(argf, "closed?", arg_closed, 0);
- filename = str_new2("-");
+ filename = rb_str_new2("-");
rb_define_readonly_variable("$FILENAME", &filename);
file = rb_stdin;
rb_global_variable(&file);
rb_define_virtual_variable("$-i", opt_i_get, opt_i_set);
- Init_File();
#if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__)
atexit(pipe_atexit);
#endif
+
+ Init_File();
}
diff --git a/keywords b/keywords
index 9e3870d1a6..1772de42b0 100644
--- a/keywords
+++ b/keywords
@@ -1,5 +1,7 @@
struct kwtable {char *name; int id[2]; enum lex_state state;};
%%
+__LINE__, k__LINE__, k__LINE__, EXPR_END
+__FILE__, k__FILE__, k__FILE__, EXPR_END
BEGIN, klBEGIN, klBEGIN, EXPR_END
END, klEND, klEND, EXPR_END
alias, kALIAS, kALIAS, EXPR_FNAME
diff --git a/lex.c b/lex.c
index 390471c424..1abc048638 100644
--- a/lex.c
+++ b/lex.c
@@ -2,12 +2,12 @@
/* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ keywords */
struct kwtable {char *name; int id[2]; enum lex_state state;};
-#define TOTAL_KEYWORDS 38
+#define TOTAL_KEYWORDS 40
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 8
#define MIN_HASH_VALUE 6
-#define MAX_HASH_VALUE 52
-/* maximum key range = 47, duplicates = 0 */
+#define MAX_HASH_VALUE 55
+/* maximum key range = 50, duplicates = 0 */
#ifdef __GNUC__
inline
@@ -19,19 +19,19 @@ hash (str, len)
{
static unsigned char asso_values[] =
{
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 11, 53, 53, 34, 53, 1, 35,
- 53, 1, 53, 53, 53, 53, 53, 53, 1, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 29, 1, 2,
- 1, 1, 4, 24, 53, 17, 53, 20, 9, 2,
- 9, 26, 14, 53, 5, 1, 1, 16, 53, 21,
- 24, 9, 53, 53, 53, 53, 53, 53,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 11, 56, 56, 36, 56, 1, 37,
+ 31, 1, 56, 56, 56, 56, 29, 56, 1, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 1, 56, 32, 1, 2,
+ 1, 1, 4, 23, 56, 17, 56, 20, 9, 2,
+ 9, 26, 14, 56, 5, 1, 1, 16, 56, 21,
+ 20, 9, 56, 56, 56, 56, 56, 56,
};
register int hval = len;
@@ -87,17 +87,19 @@ rb_reserved_word (str, len)
{"until", kUNTIL, kUNTIL_MOD, EXPR_BEG},
{"unless", kUNLESS, kUNLESS_MOD, EXPR_BEG},
{"or", kOR, kOR, EXPR_BEG},
- {"and", kAND, kAND, EXPR_BEG},
+ {"next", kNEXT, kNEXT, EXPR_END},
{"when", kWHEN, kWHEN, EXPR_BEG},
{"redo", kREDO, kREDO, EXPR_END},
- {"class", kCLASS, kCLASS, EXPR_CLASS},
- {"next", kNEXT, kNEXT, EXPR_END},
+ {"and", kAND, kAND, EXPR_BEG},
{"begin", kBEGIN, kBEGIN, EXPR_BEG},
+ {"__LINE__", k__LINE__, k__LINE__, EXPR_END},
+ {"class", kCLASS, kCLASS, EXPR_CLASS},
+ {"__FILE__", k__FILE__, k__FILE__, EXPR_END},
{"END", klEND, klEND, EXPR_END},
{"BEGIN", klBEGIN, klBEGIN, EXPR_END},
- {"",}, {"",},
{"while", kWHILE, kWHILE_MOD, EXPR_BEG},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"",},
{"alias", kALIAS, kALIAS, EXPR_FNAME},
};
diff --git a/lib/Env.rb b/lib/Env.rb
new file mode 100644
index 0000000000..b3ee3bae8a
--- /dev/null
+++ b/lib/Env.rb
@@ -0,0 +1,31 @@
+# Env.rb -- imports environment variables as global variables
+#
+# Usage:
+#
+# require 'Env'
+# p $USER
+# $USER = "matz"
+# p ENV["USER"]
+
+for k,v in ENV
+ next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
+ eval <<EOS
+ $#{k} = %q!#{v}!
+ trace_var "$#{k}", proc{|v|
+ ENV[%q!#{k}!] = v;
+ $#{k} = %q!#{v}!
+ if v == nil
+ untrace_var "$#{k}"
+ end
+ }
+EOS
+end
+
+if __FILE__ == $0
+ p $TERM
+ $TERM = nil
+ p $TERM
+ p ENV["TERM"]
+ $TERM = "foo"
+ p ENV["TERM"]
+end
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000000..09e5946ccb
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,61 @@
+English.rb access global variables by english names
+Env.rb access environment variables as globals
+README this file
+base64.rb encode/decode base64 (bit obsolete)
+cgi-lib.rb decode CGI data
+complex.rb complex number suppor
+date.rb date object (compatible)
+date2.rb date object based on Julian date
+debug.rb ruby debugger
+delegate.rb delegate messages to other object
+e2mmap.rb exception utilities
+eregex.rb extended regular expression (just a proof of concept)
+final.rb add finalizer to the object (simple)
+finalize.rb add finalizer to the object
+find.rb traverse directory tree
+ftools.rb file tools
+ftplib.rb ftp access library
+getopts.rb parse command line options
+importenv.rb access environment variables as globals
+jcode.rb japanese text handling (replace String methods)
+mailread.rb read mail headers
+mathn.rb extended math operation
+matrix.rb matrix calculation library
+mkmf.rb Makefile maker
+monitor.rb exclusive region monitor for thread
+mutex_m.rb mutex mixin
+observer.rb observer desing pattern library (provides Observable)
+open3.rb open subprocess connection stdin/stdout/stderr
+ostruct.rb python style object
+parsearg.rb argument parser using getopts
+parsedate.rb parse date string
+ping.rb
+profile.rb ruby profiler
+pstore.rb persistent object strage using marshal
+rational.rb rational number support
+readbytes.rb define IO#readbytes
+shell.rb shell like operation under Ruby (imcomlete)
+shellwords.rb split into words like shell
+singleton.rb singleton design pattern library
+sync.rb 2 phase lock
+telnet.rb telnet library
+tempfile.rb temporary file that automatically removed
+thread.rb thread support
+thwait.rb thread syncronization class
+timeout.rb provids timeout
+tk.rb Tk interface
+tkafter.rb
+tkbgerror.rb Tk error module
+tkcanvas.rb Tk canvas interface
+tkclass.rb provides generic names for Tk classes
+tkdialog.rb Tk dialog class
+tkentry.rb Tk entry class
+tkfont.rb Tk font support
+tkmenubar.rb TK menubar utility
+tkmngfocus.rb focus manager
+tkpalette.rb pallete support
+tkscrollbox.rb scroll box, also example of compound widget
+tktext.rb text classes
+tkvirtevent.rb virtual event support
+tracer.rb execution tracer
+weakref.rb weak reference class
diff --git a/lib/base64.rb b/lib/base64.rb
index 96208a634d..d7461d82e7 100644
--- a/lib/base64.rb
+++ b/lib/base64.rb
@@ -1,50 +1,25 @@
-def decode64(str)
- string = ''
- for line in str.split("\n")
- line.delete!('^A-Za-z0-9+/') # remove non-base64 chars
- line.tr!('A-Za-z0-9+/', ' -_') # convert to uuencoded format
- len = ["#{32 + line.length * 3 / 4}"].pack("c")
- # compute length byte
- string += "#{len}#{line}".unpack("u") # uudecode and concatenate
- end
- return string
-end
+require "kconv"
-def j2e(str)
- while str =~ /\033\$B([^\033]*)\033\(B/
- s = $1
- pre, post = $`, $'
- s.gsub!(/./) { |ch|
- (ch[0]|0x80).chr
- }
- str = pre + s + post
- end
-# str.gsub!(/\033\$B([^\033]*)\033\(B/) {
-# $1.gsub!(/./) { |ch|
-# (ch[0]|0x80).chr
-# }
-# }
- str
+def decode64(str)
+ str.unpack("m")[0]
end
def decode_b(str)
str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/i) {
decode64($1)
}
+ str = Kconv::toeuc(str)
+ str.gsub!(/=\?SHIFT_JIS\?B\?([!->@-~]+)\?=/i) {
+ decode64($1)
+ }
+ str = Kconv::toeuc(str)
str.gsub!(/\n/, ' ')
str.gsub!(/\0/, '')
- j2e(str)
+ str
end
def encode64(bin)
- encode = ""
- pad = 0
- [bin].pack("u").each do |uu|
- len = (2 + (uu[0] - 32)* 4) / 3
- encode << uu[1, len].tr('` -_', 'AA-Za-z0-9+/')
- pad += uu.length - 2 - len
- end
- encode + "=" * (pad % 3)
+ [bin].pack("m")
end
def b64encode(bin, len = 60)
diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb
index 5234e046cc..7033f0f8c1 100644
--- a/lib/cgi-lib.rb
+++ b/lib/cgi-lib.rb
@@ -1,4 +1,3 @@
-#!/usr/local/bin/ruby
#
# Get CGI String
#
@@ -7,26 +6,26 @@
# foo = CGI.new
# foo['field'] <== value of 'field'
# foo.keys <== array of fields
-# foo.inputs <== hash of { <field> => <value> }
+# and foo has Hash class methods
# if running on Windows(IIS or PWS) then change cwd.
if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then
Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '')
end
-require "shellwords.rb"
+require "delegate"
-class CGI
- include Shellwords
+class CGI < SimpleDelegator
attr("inputs")
# original is CGI.pm
def read_from_cmdline
- words = shellwords(if not ARGV.empty? then
+ require "shellwords.rb"
+ words = Shellwords.shellwords(if not ARGV.empty? then
ARGV.join(' ')
else
- print "(offline mode: enter name=value pairs on standard input)\n"
+ STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
readlines.join(' ').gsub(/\n/, '')
end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
@@ -47,32 +46,32 @@ class CGI
end
module_function :escape, :unescape
- def initialize
- # exception messages should be printed to stdout.
- STDERR.reopen(STDOUT)
+ def initialize(input = $stdin)
@inputs = {}
case ENV['REQUEST_METHOD']
when "GET"
+ # exception messages should be printed to stdout.
+ STDERR.reopen(STDOUT)
ENV['QUERY_STRING'] or ""
when "POST"
- $stdin.read ENV['CONTENT_LENGTH'].to_i
+ # exception messages should be printed to stdout.
+ STDERR.reopen(STDOUT)
+ input.read Integer(ENV['CONTENT_LENGTH'])
else
read_from_cmdline
end.split(/&/).each do |x|
key, val = x.split(/=/,2).collect{|x|unescape(x)}
- @inputs[key] += ("\0" if @inputs[key]) + (val or "")
+ if @inputs.include?(key)
+ @inputs[key] += "\0" + (val or "")
+ else
+ @inputs[key] = (val or "")
+ end
end
- end
- def keys
- @inputs.keys
+ super(@inputs)
end
- def [](key)
- @inputs[key]
- end
-
def CGI.message(msg, title = "")
print "Content-type: text/html\n\n"
print "<html><head><title>"
@@ -84,7 +83,7 @@ class CGI
end
def CGI.error
- m = $!.dup
+ m = $!.to_s.dup
m.gsub!(/&/, '&amp;')
m.gsub!(/</, '&lt;')
m.gsub!(/>/, '&gt;')
diff --git a/lib/complex.rb b/lib/complex.rb
index aa5d219d2f..59caad6ebc 100644
--- a/lib/complex.rb
+++ b/lib/complex.rb
@@ -1,8 +1,8 @@
#
# complex.rb -
# $Release Version: 0.5 $
-# $Revision: 1.1 $
-# $Date: 1996/11/11 04:25:19 $
+# $Revision: 1.3 $
+# $Date: 1998/07/08 10:05:28 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# --
@@ -59,6 +59,7 @@ def Complex(a, b = 0)
end
class Complex < Numeric
+ @RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
def Complex.generic?(other)
other.kind_of?(Integer) or
@@ -284,6 +285,11 @@ class Complex < Numeric
@real ^ @image
end
+ def inspect
+ sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
+ end
+
+
I = Complex(0,1)
attr :real
@@ -396,7 +402,7 @@ module Math
cos!(z)
else
Complex(cos!(z.real)*cosh!(z.image),
- sin!(z.real)*sinh!(z.image))
+ -sin!(z.real)*sinh!(z.image))
end
end
@@ -405,7 +411,7 @@ module Math
sin!(z)
else
Complex(sin!(z.real)*cosh!(z.image),
- -cos!(z.real)*sinh!(z.image))
+ cos!(z.real)*sinh!(z.image))
end
end
diff --git a/lib/date.rb b/lib/date.rb
index 998c2e8152..9de49bcbc7 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -1,8 +1,8 @@
#
# Date.rb -
# $Release Version: $
-# $Revision: 1.2 $
-# $Date: 1997/02/14 11:05:29 $
+# $Revision: 1.1.1.1.4.5 $
+# $Date: 1998/03/03 02:39:34 $
# by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
#
# --
@@ -17,15 +17,34 @@
class Date
include Comparable
+ Weektag = [
+ "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
+ ]
+
+ Monthtag = [
+ "January","February","March","April", "May", "June","July",
+ "August", "September", "October", "November", "December"
+ ]
+
+ Monthtab = {
+ "jan"=>1, "feb"=>2, "mar"=>3, "apr"=>4, "may"=>5, "jun"=>6,
+ "jul"=>7, "aug"=>8, "sep"=>9, "oct"=>10, "nov"=>11, "dec"=>12
+ }
+
def initialize(y = 1, m = 1, d = 1)
- if y.kind_of?(String) && y.size == 8
- @year = y[0,4].to_i
- @month = y[4,2].to_i
- @day = y[6,2].to_i
+ if y.kind_of?(String)
+ case y
+ when /(\d\d\d\d)-?(?:(\d\d)-?(\d\d)?)?/
+ @year = $1.to_i
+ @month = if $2 then $2.to_i else 1 end
+ @day = if $3 then $3.to_i else 1 end
+ else
+ require 'parsedate'
+ @year, @month, @day = ParseDate.parsedate(y)
+ end
else
if m.kind_of?(String)
- ml = {"jan"=>1, "feb"=>2, "mar"=>3, "apr"=>4, "may"=>5, "jun"=>6, "jul"=>7, "aug"=>8, "sep"=>9, "oct"=>10, "nov"=>11, "dec"=>12}
- m = ml[m.downcase]
+ m = Monthtab[m.downcase]
if m.nil?
raise ArgumentError, "Wrong argument. (month)"
end
@@ -53,25 +72,35 @@ class Date
def period
return Date.period!(@year, @month, @day)
end
-
+
+ def jd
+ return period + 1721423
+ end
+
+ def mjd
+ return jd - 2400000.5
+ end
+
+ def to_s
+ format("%.3s, %.3s %2d %4d", name_of_week, name_of_month, @day, @year)
+ end
+
+ def inspect
+ to_s
+ end
+
def day_of_week
- dl = Date.daylist(@year)
- d = Date.jan1!(@year)
- for m in 1..(@month - 1)
- d += dl[m]
- end
- d += @day - 1
- if @year == 1752 && @month == 9 && @day >= 14
- d -= (14 - 3)
- end
- return (d % 7)
+ return (period + 5) % 7
end
- Weektag = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
def name_of_week
return Weektag[self.day_of_week]
end
+ def name_of_month
+ return Monthtag[@month-1]
+ end
+
def +(o)
if o.kind_of?(Numeric)
d = Integer(self.period + o)
@@ -80,6 +109,9 @@ class Date
else
raise TypeError, "Illegal type. (Integer or Date)"
end
+ if d <= 0
+ raise ArgumentError, "argument out of range. (self > other)"
+ end
return Date.at(d)
end
@@ -117,14 +149,13 @@ class Date
end
def leapyear?
- if Date.leapyear(@year) == 1
- return FALSE
- else
- return TRUE
- end
+ Date.leapyear(@year) != 1
end
def _check_date
+ if @year == nil or @month == nil or @day == nil
+ raise ArgumentError, "argument contains nil"
+ end
m = Date.daylist(@year)
if @month < 1 || @month > 12
raise ArgumentError, "argument(month) out of range."
@@ -151,7 +182,7 @@ end
def Date.at(d)
if d.kind_of? Time
- return Date.new(1900+d.year, d.mon+1, d.mday)
+ return Date.new(d.year, d.mon, d.mday)
end
if d.kind_of? Date
return Date.at(d.period)
@@ -189,10 +220,10 @@ def Date.period!(y, m, d)
p += dl[mm]
end
p += (y - 1) * 365 + ((y - 1) / 4.0).to_i
- if (y - 1) > 1752
- p -= ((y - 1 - 1752) / 100.0).to_i
- p += ((y - 1 - 1752) / 400.0).to_i
- p -= (14 - 3)
+ if y > 1752
+ p -= ((y - 1) / 100.0).to_i
+ p += ((y - 1) / 400.0).to_i
+ p += 2
elsif y == 1752 && m == 9 && d >= 14 && d <= 30
p -= (14 - 3)
end
diff --git a/lib/date2.rb b/lib/date2.rb
new file mode 100644
index 0000000000..50c2ccfbd9
--- /dev/null
+++ b/lib/date2.rb
@@ -0,0 +1,219 @@
+# date.rb: Written by Tadayoshi Funaba 1998
+# $Id: date.rb,v 1.4 1998/06/01 12:52:33 tadf Exp $
+
+class Date
+
+ include Comparable
+
+ MONTHNAMES = [ '', 'January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December' ]
+
+ DAYNAMES = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
+ 'Friday', 'Saturday' ]
+
+ ITALY = 2299161 # Oct 15, 1582
+ ENGLAND = 2361222 # Sept 14, 1752
+
+ def Date.civil_to_jd(y, m, d, gs = true)
+ if m <= 2 then
+ y -= 1
+ m += 12
+ end
+ a = (y / 100).to_i
+ b = 2 - a + (a / 4).to_i
+ jd = (365.25 * (y + 4716)).to_i +
+ (30.6001 * (m + 1)).to_i +
+ d + b - 1524
+ unless
+ (if gs.kind_of? Numeric then jd >= gs else gs end) then
+ jd -= b
+ end
+ jd
+ end
+
+ def Date.jd_to_civil(jd, gs = true)
+ unless
+ (if gs.kind_of? Numeric then jd >= gs else gs end) then
+ a = jd
+ else
+ x = ((jd - 1867216.25) / 36524.25).to_i
+ a = jd + 1 + x - (x / 4).to_i
+ end
+ b = a + 1524
+ c = ((b - 122.1) / 365.25).to_i
+ d = (365.25 * c).to_i
+ e = ((b - d) / 30.6001).to_i
+ dom = b - d - (30.6001 * e).to_i
+ if e <= 13 then
+ m = e - 1
+ y = c - 4716
+ else
+ m = e - 13
+ y = c - 4715
+ end
+ return y, m, dom
+ end
+
+ def Date.mjd_to_jd(mjd)
+ mjd + 2400000.5
+ end
+
+ def Date.jd_to_mjd(jd)
+ jd - 2400000.5
+ end
+
+ def Date.tjd_to_jd(tjd)
+ tjd + 2440000.5
+ end
+
+ def Date.jd_to_tjd(jd)
+ jd - 2440000.5
+ end
+
+ def Date.julian_leap? (y)
+ y % 4 == 0
+ end
+
+ def Date.gregorian_leap? (y)
+ y % 4 == 0 and y % 100 != 0 or y % 400 == 0
+ end
+
+ def Date.leap? (y)
+ Date.gregorian_leap?(y)
+ end
+
+ def initialize(jd = 0, gs = ITALY)
+ @jd, @gs = jd, gs
+ end
+
+ def Date.exist? (y, m, d, gs = true)
+ jd = Date.civil_to_jd(y, m, d, gs)
+ if [y, m, d] == Date.jd_to_civil(jd, gs) then
+ jd
+ end
+ end
+
+ def Date.new3(y = -4712, m = 1, d = 1, gs = ITALY)
+ unless jd = Date.exist?(y, m, d, gs) then
+ fail ArgumentError, 'invalid date'
+ end
+ Date.new(jd, gs)
+ end
+
+ def Date.today(gs = ITALY)
+ Date.new(Date.civil_to_jd(*(Time.now.to_a[3..5].reverse << gs)), gs)
+ end
+
+ def jd
+ @jd
+ end
+
+ def mjd
+ def self.mjd; @mjd end
+ @mjd = Date.jd_to_mjd(@jd)
+ end
+
+ def tjd
+ def self.tjd; @tjd end
+ @tjd = Date.jd_to_tjd(@jd)
+ end
+
+ def civil
+ def self.year; @year end
+ def self.mon; @mon end
+ def self.mday; @mday end
+ @year, @mon, @mday = Date.jd_to_civil(@jd, @gs)
+ end
+
+ private :civil
+
+ def year
+ civil
+ @year
+ end
+
+ def yday
+ def self.yday; @yday end
+ ns = if @gs.kind_of? Numeric then @jd >= @gs else @gs end
+ jd = Date.civil_to_jd(year - 1, 12, 31, ns)
+ @yday = @jd - jd
+ end
+
+ def mon
+ civil
+ @mon
+ end
+
+ def mday
+ civil
+ @mday
+ end
+
+ def wday
+ def self.wday; @wday end
+ @wday = (@jd + 1) % 7
+ end
+
+ def leap?
+ def self.leap?; @leap_p end
+ ns = if @gs.kind_of? Numeric then @jd >= @gs else @gs end
+ jd = Date.civil_to_jd(year, 2, 28, ns)
+ @leap_p = Date.jd_to_civil(jd + 1, ns)[1] == 2
+ end
+
+ def + (other)
+ if other.kind_of? Numeric then
+ return Date.new(@jd + other, @gs)
+ end
+ fail TypeError, 'expected numeric'
+ end
+
+ def - (other)
+ if other.kind_of? Numeric then
+ return Date.new(@jd - other, @gs)
+ elsif other.kind_of? Date then
+ return @jd - other.jd
+ end
+ fail TypeError, 'expected numeric or date'
+ end
+
+ def <=> (other)
+ if other.kind_of? Numeric then
+ return @jd <=> other
+ elsif other.kind_of? Date then
+ return @jd <=> other.jd
+ end
+ fail TypeError, 'expected numeric or date'
+ end
+
+ def downto(min)
+ @jd.downto(min.jd) do |jd|
+ yield Date.new(jd, @gs)
+ end
+ end
+
+ def upto(max)
+ @jd.upto(max.jd) do |jd|
+ yield Date.new(jd, @gs)
+ end
+ end
+
+ def step(max, step)
+ @jd.step(max.jd, step) do |jd|
+ yield Date.new(jd, @gs)
+ end
+ end
+
+ def eql? (other)
+ self == other
+ end
+
+ def hash
+ @jd
+ end
+
+ def to_s
+ format('%04d-%02d-%02d', year, mon, mday)
+ end
+
+end
diff --git a/lib/debug.rb b/lib/debug.rb
index 432c7b4d19..90270a3fe7 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -11,6 +11,8 @@ class DEBUGGER__
@scripts = {}
end
+ DEBUG_LAST_CMD = []
+
def interrupt
@stop_next = 1
end
@@ -40,6 +42,11 @@ class DEBUGGER__
STDOUT.flush
while input = STDIN.gets
input.chop!
+ if input == ""
+ input = DEBUG_LAST_CMD[0]
+ else
+ DEBUG_LAST_CMD[0] = input
+ end
case input
when /^b(reak)?\s+(([^:\n]+:)?.+)/
pos = $2
@@ -169,7 +176,7 @@ class DEBUGGER__
printf "no sourcefile available for %s\n", file
end
when /^p\s+/
- p debug_eval($', binding)
+ p debug_eval($', binding) #'
else
v = debug_eval(input, binding)
p v unless v == nil
@@ -187,10 +194,13 @@ class DEBUGGER__
return "\n" unless line
return line
end
+ save = $DEBUG
begin
+ $DEBUG = FALSE
f = open(file)
lines = @scripts[file] = f.readlines
rescue
+ $DEBUG = save
@scripts[file] = TRUE
return "\n"
end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index e5943cead8..0771f2feeb 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -1,26 +1,51 @@
# Delegation class that delegates even methods defined in super class,
# which can not be covered with normal method_missing hack.
#
-# Delegater is the abstract delegation class. Need to redefine
-# `__getobj__' method in the subclass. SimpleDelegater is the
+# Delegator is the abstract delegation class. Need to redefine
+# `__getobj__' method in the subclass. SimpleDelegator is the
# concrete subclass for simple delegation.
#
# Usage:
# foo = Object.new
-# foo = SimpleDelegater.new(foo)
-# foo.type # => Object
+# foo2 = SimpleDelegator.new(foo)
+# foo.hash == foo2.hash # => true
+#
+# Foo = DelegateClass(Array)
+#
+# class ExtArray<DelegateClass(Array)
+# ...
+# end
-class Delegater
+class Delegator
def initialize(obj)
- preserved = ["id", "equal?", "__getobj__"]
+ preserved = ::Kernel.instance_methods
+ preserved -= ["to_s","to_a","inspect","==","=~","==="]
for t in self.type.ancestors
preserved |= t.instance_methods
- break if t == Delegater
+ preserved |= t.private_instance_methods
+ preserved |= t.protected_instance_methods
+ break if t == Delegator
end
for method in obj.methods
next if preserved.include? method
- eval "def self.#{method}(*args); __getobj__.send :#{method}, *args; end"
+ eval <<-EOS
+ def self.#{method}(*args, &block)
+ begin
+ __getobj__.__send__(:#{method}, *args, &block)
+ rescue Exception
+ c = -caller(0).size
+ if /:in `__getobj__'$/ =~ $@[c-1] #`
+ n = 1
+ else
+ c -= 1
+ n = 2
+ end
+ $@[c,n] = nil
+ raise
+ end
+ end
+ EOS
end
end
@@ -30,7 +55,7 @@ class Delegater
end
-class SimpleDelegater<Delegater
+class SimpleDelegator<Delegator
def initialize(obj)
super
@@ -41,4 +66,61 @@ class SimpleDelegater<Delegater
@obj
end
+ def __setobj__(obj)
+ @obj = obj
+ end
+end
+
+# backward compatibility ^_^;;;
+Delegater = Delegator
+SimpleDelegater = SimpleDelegator
+
+#
+def DelegateClass(superclass)
+ klass = Class.new
+ methods = superclass.instance_methods
+ methods -= ::Kernel.instance_methods
+ methods |= ["to_s","to_a","inspect","==","=~","==="]
+ klass.module_eval <<-EOS
+ def initialize(obj)
+ @obj = obj
+ end
+ EOS
+ for method in methods
+ klass.module_eval <<-EOS
+ def #{method}(*args, &block)
+ begin
+ @obj.__send__(:#{method}, *args, &block)
+ rescue
+ $@[0,2] = nil
+ raise
+ end
+ end
+ EOS
+ end
+ return klass;
+ end
+
+if __FILE__ == $0
+ class ExtArray<DelegateClass(Array)
+ def initialize()
+ super([])
+ end
+ end
+
+ ary = ExtArray.new
+ p ary.type
+ ary.push 25
+ p ary
+
+ foo = Object.new
+ def foo.test
+ 25
+ end
+ def foo.error
+ raise 'this is OK'
+ end
+ foo2 = SimpleDelegator.new(foo)
+ p foo.test == foo2.test # => true
+ foo2.error # raise error!
end
diff --git a/lib/e2mmap.rb b/lib/e2mmap.rb
index d10657bbad..bf860dc5c1 100644
--- a/lib/e2mmap.rb
+++ b/lib/e2mmap.rb
@@ -1,11 +1,22 @@
#
# e2mmap.rb - for ruby 1.1
-# $Release Version: 1.1$
-# $Revision: 1.4 $
-# $Date: 1997/08/18 07:12:12 $
+# $Release Version: 1.2$
+# $Revision: 1.8 $
+# $Date: 1998/08/19 15:22:22 $
# by Keiju ISHITSUKA
#
# --
+# Usage:
+#
+# class Foo
+# extend Exception2MassageMapper
+# def_exception :NewExceptionClass, "message..."[, superclass]
+# def_e2meggage ExistingExceptionClass, "message..."
+# ...
+# end
+#
+# Foo.Fail NewExceptionClass, arg...
+# Foo.Fail ExistingExceptionClass, arg...
#
#
if VERSION < "1.1"
@@ -13,40 +24,60 @@ if VERSION < "1.1"
else
module Exception2MessageMapper
- RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/e2mmap.rb,v 1.4 1997/08/18 07:12:12 keiju Exp keiju $-'
+ @RCS_ID='-$Id: e2mmap.rb,v 1.8 1998/08/19 15:22:22 keiju Exp keiju $-'
E2MM = Exception2MessageMapper
-
+
def E2MM.extend_object(cl)
super
cl.bind(self)
end
- # °ÊÁ°¤È¤Î¸ß´¹À­¤Î¤¿¤á¤Ë»Ä¤·¤Æ¤¢¤ë.
+ # backward compatibility
def E2MM.extend_to(b)
c = eval("self", b)
c.extend(self)
end
-# public :fail
- # alias e2mm_fail fail
+ # public :fail
+ alias fail! fail
+
+ #def fail(err = nil, *rest)
+ # super
+ #end
- def fail(err = nil, *rest)
- Exception2MessageMapper.fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
+ def Fail(err = nil, *rest)
+ Exception2MessageMapper.Fail Exception2MessageMapper::ErrNotRegisteredException, err.inspect
end
def bind(cl)
self.module_eval %q^
- E2MM_ErrorMSG = {}
+ E2MM_ErrorMSG = {} unless self.const_defined?(:E2MM_ErrorMSG)
# fail(err, *rest)
- # err: Îã³°
- # rest: ¥á¥Ã¥»¡¼¥¸¤ËÅϤ¹¥Ñ¥é¥á¡¼¥¿
+ # err: Exception
+ # rest: Parameter accompanied with the exception
#
+ def self.Fail(err = nil, *rest)
+ if form = E2MM_ErrorMSG[err]
+ $! = err.new(sprintf(form, *rest))
+ $@ = caller(0) if $@.nil?
+ $@.shift
+ # e2mm_fail()
+ raise()
+# elsif self == Exception2MessageMapper
+# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
+ else
+# print "super\n"
+ super
+ end
+ end
+
+ # ²áµî¤Î¸ß´¹À­¤Î¤¿¤á
def self.fail(err = nil, *rest)
- $@ = caller(0) if $@.nil?
- $@.shift
if form = E2MM_ErrorMSG[err]
$! = err.new(sprintf(form, *rest))
+ $@ = caller(0) if $@.nil?
+ $@.shift
# e2mm_fail()
raise()
# elsif self == Exception2MessageMapper
@@ -63,7 +94,6 @@ else
# def_exception(c, m)
# c: exception
# m: message_form
- # Îã³°c¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
#
def self.def_e2message(c, m)
E2MM_ErrorMSG[c] = m
@@ -72,13 +102,21 @@ else
# def_exception(c, m)
# n: exception_name
# m: message_form
- # s: Îã³°¥¹¡¼¥Ñ¡¼¥¯¥é¥¹(¥Ç¥Õ¥©¥ë¥È: Exception)
- # Î㳰̾``c''¤ò¤â¤ÄÎã³°¤òÄêµÁ¤·, ¤½¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
+ # s: superclass_of_exception (default: Exception)
+ # defines excaption named ``c'', whose message is ``m''.
#
#def def_exception(n, m)
- def self.def_exception(n, m, s = Exception)
+ def self.def_exception(n, m, s = nil)
n = n.id2name if n.kind_of?(Fixnum)
+ unless s
+ if defined?(StandardError)
+ s = StandardError
+ else
+ s = Exception
+ end
+ end
e = Class.new(s)
+
const_set(n, e)
E2MM_ErrorMSG[e] = m
# const_get(:E2MM_ErrorMSG)[e] = m
@@ -91,4 +129,3 @@ else
def_exception(:ErrNotRegisteredException, "not registerd exception(%s)")
end
end
-
diff --git a/lib/eregex.rb b/lib/eregex.rb
index f214f6a2d4..384d531e0f 100644
--- a/lib/eregex.rb
+++ b/lib/eregex.rb
@@ -30,10 +30,7 @@ class Regexp
end
end
-p "abc" =~ /b/|/c/
-p "abc" =~ /b/&/c/
-
-
-
-
-
+if __FILE__ == $0
+ p "abc" =~ /b/|/c/
+ p "abc" =~ /b/&/c/
+end
diff --git a/lib/final.rb b/lib/final.rb
new file mode 100644
index 0000000000..cdffd941e7
--- /dev/null
+++ b/lib/final.rb
@@ -0,0 +1,41 @@
+#
+# $Id$
+# Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved.
+
+# The ObjectSpace extension:
+#
+# ObjectSpace.define_finalizer(obj, proc=lambda())
+#
+# Defines the finalizer for the specified object.
+#
+# ObjectSpace.undefine_finalizer(obj)
+#
+# Removes the finalizers for the object. If multiple finalizers are
+# defined for the object, all finalizers will be removed.
+#
+
+module ObjectSpace
+ Finalizers = {}
+ def define_finalizer(obj, proc=lambda())
+ ObjectSpace.call_finalizer(obj)
+ if assoc = Finalizers[obj.id]
+ assoc.push(proc)
+ else
+ Finalizers[obj.id] = [proc]
+ end
+ end
+ def undefine_finalizer(obj)
+ Finalizers.delete(obj.id)
+ end
+ module_function :define_finalizer, :undefine_finalizer
+
+ Generic_Finalizer = proc {|id|
+ if Finalizers.key? id
+ for proc in Finalizers[id]
+ proc.call(id)
+ end
+ Finalizers.delete(id)
+ end
+ }
+ add_finalizer Generic_Finalizer
+end
diff --git a/lib/finalize.rb b/lib/finalize.rb
index 9b2ffefcf5..a07e67d093 100644
--- a/lib/finalize.rb
+++ b/lib/finalize.rb
@@ -1,8 +1,8 @@
#
# finalizer.rb -
-# $Release Version: 0.2$
-# $Revision: 1.3 $
-# $Date: 1998/01/09 08:09:49 $
+# $Release Version: 0.3$
+# $Revision: 1.4 $
+# $Date: 1998/02/27 05:34:33 $
# by Keiju ISHITSUKA
#
# --
@@ -11,44 +11,42 @@
#
# add(obj, dependant, method = :finalize, *opt)
# add_dependency(obj, dependant, method = :finalize, *opt)
-# °Í¸´Ø·¸ R_method(obj, dependant) ¤ÎÄɲÃ
+# add dependency R_method(obj, dependant)
#
# delete(obj_or_id, dependant, method = :finalize)
# delete_dependency(obj_or_id, dependant, method = :finalize)
-# °Í¸´Ø·¸ R_method(obj, dependant) ¤Îºï½ü
+# delete dependency R_method(obj, dependant)
# delete_all_dependency(obj_or_id, dependant)
-# °Í¸´Ø·¸ R_*(obj, dependant) ¤Îºï½ü
+# delete dependency R_*(obj, dependant)
# delete_by_dependant(dependant, method = :finalize)
-# °Í¸´Ø·¸ R_method(*, dependant) ¤Îºï½ü
+# delete dependency R_method(*, dependant)
# delete_all_by_dependant(dependant)
-# °Í¸´Ø·¸ R_*(*, dependant) ¤Îºï½ü
+# delete dependency R_*(*, dependant)
# delete_all
-# Á´¤Æ¤Î°Í¸´Ø·¸¤Îºï½ü.
+# delete all dependency R_*(*, *)
#
# finalize(obj_or_id, dependant, method = :finalize)
# finalize_dependency(obj_or_id, dependant, method = :finalize)
-# °Í¸´ØÏ¢ R_method(obj, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤ò
-# finalize¤¹¤ë.
+# finalize the dependant connected by dependency R_method(obj, dependtant).
# finalize_all_dependency(obj_or_id, dependant)
-# °Í¸´ØÏ¢ R_*(obj, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+# finalize all dependants connected by dependency R_*(obj, dependtant).
# finalize_by_dependant(dependant, method = :finalize)
-# °Í¸´ØÏ¢ R_method(*, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+# finalize the dependant connected by dependency R_method(*, dependtant).
# fainalize_all_by_dependant(dependant)
-# °Í¸´ØÏ¢ R_*(*, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+# finalize all dependants connected by dependency R_*(*, dependant).
# finalize_all
-# Finalizer¤ËÅÐÏ¿¤µ¤ì¤ëÁ´¤Æ¤Îdependant¤òfinalize¤¹¤ë
+# finalize all dependency registered to the Finalizer.
#
# safe{..}
-# gc»þ¤ËFinalizer¤¬µ¯Æ°¤¹¤ë¤Î¤ò»ß¤á¤ë.
-#
+# stop invoking Finalizer on GC.
#
module Finalizer
- RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.3 1998/01/09 08:09:49 keiju Exp keiju $-'
+ RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-'
# @dependency: {id => [[dependant, method, *opt], ...], ...}
- # °Í¸´Ø·¸ R_method(obj, dependant) ¤ÎÄɲÃ
+ # add dependency R_method(obj, dependant)
def add_dependency(obj, dependant, method = :finalize, *opt)
ObjectSpace.call_finalizer(obj)
method = method.intern unless method.kind_of?(Integer)
@@ -61,7 +59,7 @@ module Finalizer
end
alias add add_dependency
- # °Í¸´Ø·¸ R_method(obj, dependant) ¤Îºï½ü
+ # delete dependency R_method(obj, dependant)
def delete_dependency(id, dependant, method = :finalize)
id = id.id unless id.kind_of?(Integer)
method = method.intern unless method.kind_of?(Integer)
@@ -75,7 +73,7 @@ module Finalizer
end
alias delete delete_dependency
- # °Í¸´Ø·¸ R_*(obj, dependant) ¤Îºï½ü
+ # delete dependency R_*(obj, dependant)
def delete_all_dependency(id, dependant)
id = id.id unless id.kind_of?(Integer)
method = method.intern unless method.kind_of?(Integer)
@@ -88,30 +86,29 @@ module Finalizer
end
end
- # °Í¸´Ø·¸ R_method(*, dependant) ¤Îºï½ü
+ # delete dependency R_method(*, dependant)
def delete_by_dependant(dependant, method = :finalize)
method = method.intern unless method.kind_of?(Integer)
- for id in Dependency.keys
+ for id in @dependency.keys
delete(id, dependant, method)
end
end
- # °Í¸´Ø·¸ R_*(*, dependant) ¤Îºï½ü
+ # delete dependency R_*(*, dependant)
def delete_all_by_dependant(dependant)
for id in @dependency.keys
delete_all_dependency(id, dependant)
end
end
- # °Í¸´ØÏ¢ R_method(obj, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹
- # ¤ë.
+ # finalize the depandant connected by dependency R_method(obj, dependtant)
def finalize_dependency(id, dependant, method = :finalize)
id = id.id unless id.kind_of?(Integer)
method = method.intern unless method.kind_of?(Integer)
for assocs in @dependency[id]
assocs.delete_if do
|d, m, *o|
- d.send(m, *o) if ret = d == dependant && m == method
+ d.send(m, id, *o) if ret = d == dependant && m == method
ret
end
@dependency.delete(id) if assoc.empty?
@@ -119,20 +116,20 @@ module Finalizer
end
alias finalize finalize_dependency
- # °Í¸´ØÏ¢ R_*(obj, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+ # finalize all dependants connected by dependency R_*(obj, dependtant)
def finalize_all_dependency(id, dependant)
id = id.id unless id.kind_of?(Integer)
method = method.intern unless method.kind_of?(Integer)
for assoc in @dependency[id]
assoc.delete_if do
|d, m, *o|
- d.send(m, *o) if ret = d == dependant
+ d.send(m, id, *o) if ret = d == dependant
end
@dependency.delete(id) if assoc.empty?
end
end
- # °Í¸´ØÏ¢ R_method(*, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+ # finalize the dependant connected by dependency R_method(*, dependtant)
def finalize_by_dependant(dependant, method = :finalize)
method = method.intern unless method.kind_of?(Integer)
for id in @dependency.keys
@@ -140,14 +137,14 @@ module Finalizer
end
end
- # °Í¸´ØÏ¢ R_*(*, dependtant) ¤Ç·ë¤Ð¤ì¤ëdependant¤òfinalize¤¹¤ë.
+ # finalize all dependants connected by dependency R_*(*, dependtant)
def fainalize_all_by_dependant(dependant)
for id in @dependency.keys
finalize_all_dependency(id, dependant)
end
end
- # Finalizer¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ëÁ´¤Æ¤Îdependant¤òfinalize¤¹¤ë
+ # finalize all dependants registered to the Finalizer.
def finalize_all
for id, assocs in @dependency
for dependant, method, *opt in assocs
@@ -157,7 +154,7 @@ module Finalizer
end
end
- # finalize_* ¤ò°ÂÁ´¤Ë¸Æ¤Ó½Ð¤¹¤¿¤á¤Î¥¤¥Æ¥ì¡¼¥¿
+ # method to call finalize_* safely.
def safe
old_status = Thread.critical
Thread.critical = TRUE
@@ -167,7 +164,7 @@ module Finalizer
Thread.critical = old_status
end
- # ObjectSpace#add_finalizer¤Ø¤ÎÅÐÏ¿´Ø¿ô
+ # registering function to ObjectSpace#add_finalizer
def final_of(id)
if assocs = @dependency.delete(id)
for dependant, method, *opt in assocs
@@ -202,4 +199,3 @@ module Finalizer
private_class_method :final_of
end
-
diff --git a/lib/find.rb b/lib/find.rb
index 5ecc54329c..3f1b82d2b3 100644
--- a/lib/find.rb
+++ b/lib/find.rb
@@ -1,5 +1,5 @@
# Usage:
-# require "find.rb"
+# require "find"
#
# Find.find('/foo','/bar') {|f| ...}
# or
@@ -12,7 +12,7 @@ module Find
while file = path.shift
catch(:prune) {
yield file
- if File.directory? file and not File.symlink? file then
+ if File.directory? file then
d = Dir.open(file)
begin
for f in d
diff --git a/lib/ftools.rb b/lib/ftools.rb
index 59bc81b365..7ccc7a4468 100644
--- a/lib/ftools.rb
+++ b/lib/ftools.rb
@@ -30,7 +30,7 @@ class << File
to.binmode
begin
- while TRUE
+ while true
r = from.sysread(fsize)
rsize = r.size
w = 0
@@ -40,9 +40,9 @@ class << File
end
end
rescue EOFError
- ret = TRUE
+ ret = true
rescue
- ret = FALSE
+ ret = false
ensure
to.close
from.close
@@ -50,7 +50,7 @@ class << File
ret
end
- def copy from, to, verbose = FALSE
+ def copy from, to, verbose = false
$stderr.print from, " -> ", catname(from, to), "\n" if verbose
syscopy from, to
end
@@ -59,11 +59,11 @@ class << File
# move file
- def move from, to, verbose = FALSE
+ def move from, to, verbose = false
to = catname(from, to)
$stderr.print from, " -> ", to, "\n" if verbose
- if PLATFORM =~ /djgpp|cygwin32|mswin32/ and FileTest.file? to
+ if PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to
unlink to
end
begin
@@ -76,10 +76,10 @@ class << File
alias mv move
# compare two files
-# TRUE: identical
-# FALSE: not identical
+# true: identical
+# false: not identical
- def compare from, to, verbose = FALSE
+ def compare from, to, verbose = false
$stderr.print from, " <=> ", to, "\n" if verbose
fsize = size(from)
fsize = 1024 if fsize < 512
@@ -90,7 +90,7 @@ class << File
to = open(to, "r")
to.binmode
- ret = FALSE
+ ret = false
fr = tr = ''
begin
@@ -103,7 +103,7 @@ class << File
end
end
rescue
- ret = FALSE
+ ret = false
ensure
to.close
from.close
@@ -116,7 +116,7 @@ class << File
# unlink files safely
def safe_unlink(*files)
- verbose = if files[-1].is_a? String then FALSE else files.pop end
+ verbose = if files[-1].is_a? String then false else files.pop end
begin
$stderr.print files.join(" "), "\n" if verbose
chmod 0777, *files
@@ -129,7 +129,7 @@ class << File
alias rm_f safe_unlink
def makedirs(*dirs)
- verbose = if dirs[-1].is_a? String then FALSE else dirs.pop end
+ verbose = if dirs[-1].is_a? String then false else dirs.pop end
# mode = if dirs[-1].is_a? Fixnum then dirs.pop else 0755 end
mode = 0755
for dir in dirs
@@ -146,14 +146,15 @@ class << File
alias o_chmod chmod
def chmod(mode, *files)
- verbose = if files[-1].is_a? String then FALSE else files.pop end
+ verbose = if files[-1].is_a? String then false else files.pop end
$stderr.printf "chmod %04o %s\n", mode, files.join(" ") if verbose
o_chmod mode, *files
end
- def install(from, to, mode, verbose)
+ def install(from, to, mode = nil, verbose = false)
to = catname(from, to)
unless FileTest.exist? to and cmp from, to
+ unlink to if FileTest.exist? to
cp from, to, verbose
chmod mode, to, verbose if mode
end
diff --git a/lib/ftplib.rb b/lib/ftplib.rb
index 34ee2f8d62..617d85899b 100644
--- a/lib/ftplib.rb
+++ b/lib/ftplib.rb
@@ -1,617 +1,574 @@
-### ftplib.rb -*- Mode: ruby; tab-width: 8; -*-
+## ftplib.rb
-## $Revision: 1.5 $
-## $Date: 1997/09/16 08:03:31 $
-## by maeda shugo <shugo@po.aianet.ne.jp>
+# Author: Shugo Maeda <shugo@po.aianet.ne.jp>
+# Version: $Revision: 1.7 $
-### Code:
+## Code:
require "socket"
-require "sync" if defined? Thread
+require "monitor"
-class FTPError < Exception; end
+class FTPError < StandardError; end
class FTPReplyError < FTPError; end
class FTPTempError < FTPError; end
class FTPPermError < FTPError; end
class FTPProtoError < FTPError; end
class FTP
-
- RCS_ID = '$Id: ftplib.rb,v 1.5 1997/09/16 08:03:31 shugo Exp $'
-
- FTP_PORT = 21
- CRLF = "\r\n"
-
- attr :passive, TRUE
- attr :return_code, TRUE
- attr :debug_mode, TRUE
- attr :welcome
- attr :lastresp
-
- THREAD_SAFE = defined?(Thread) != FALSE
-
- if THREAD_SAFE
- def synchronize(mode = :EX)
- if @sync
- @sync.synchronize(mode) do
- yield
- end
- end
- end
-
- def sock_synchronize(mode = :EX)
- if @sock
- @sock.synchronize(mode) do
- yield
- end
- end
- end
- else
- def synchronize(mode = :EX)
- yield
- end
-
- def sock_synchronize(mode = :EX)
- yield
- end
- end
- private :sock_synchronize
-
- def FTP.open(host, user = nil, passwd = nil, acct = nil)
- new(host, user, passwd, acct)
- end
+
+ RCS_ID = %q$Id: ftplib.rb,v 1.7 1998/04/13 12:34:24 shugo Exp shugo $
+
+ include MonitorMixin
+
+ FTP_PORT = 21
+ CRLF = "\r\n"
+
+ attr_accessor :passive, :return_code, :debug_mode
+ attr_reader :welcome, :lastresp
+
+ def FTP.open(host, user = nil, passwd = nil, acct = nil)
+ new(host, user, passwd, acct)
+ end
- def initialize(host = nil, user = nil,
- passwd = nil, acct = nil)
- if THREAD_SAFE
- @sync = Sync.new
- end
- @passive = FALSE
- @return_code = "\n"
- @debug_mode = FALSE
- if host
- connect(host)
- if user
- login(user, passwd, acct)
- end
- end
- end
-
- def open_socket(host, port)
- if defined? SOCKSsocket and ENV["SOCKS_SERVER"]
- @passive = TRUE
- SOCKSsocket.open(host, port)
- else
- TCPsocket.open(host, port)
- end
- end
- private :open_socket
-
- def connect(host, port = FTP_PORT)
- if @debug_mode
- print "connect: ", host, ", ", port, "\n"
- end
- synchronize do
- @sock = open_socket(host, port)
- if THREAD_SAFE
- @sock.extend Sync_m
- end
- voidresp
- end
- end
-
- def sanitize(s)
- if s =~ /^PASS /i
- s[0, 5] + "*" * (s.length - 5)
- else
- s
- end
- end
- private :sanitize
-
- def putline(line)
- if @debug_mode
- print "put: ", sanitize(line), "\n"
- end
- line = line + CRLF
- @sock.write(line)
- end
- private :putline
-
- def getline
- line = @sock.readline # if get EOF, raise EOFError
- if line[-2, 2] == CRLF
- line = line[0 .. -3]
- elsif line[-1] == ?\r or
- line[-1] == ?\n
- line = line[0 .. -2]
- end
- if @debug_mode
- print "get: ", sanitize(line), "\n"
- end
- line
- end
- private :getline
-
- def getmultiline
- line = getline
- buff = line
- if line[3] == ?-
- code = line[0, 3]
- begin
- line = getline
- buff << "\n" << line
- end until line[0, 3] == code and line[3] != ?-
- end
- buff << "\n"
- end
- private :getmultiline
-
- def getresp
- resp = getmultiline
- @lastresp = resp[0, 3]
- c = resp[0]
- case c
- when ?1, ?2, ?3
- return resp
- when ?4
- raise FTPTempError, resp
- when ?5
- raise FTPPermError, resp
- else
- raise FTPProtoError, resp
- end
- end
- private :getresp
-
- def voidresp
- resp = getresp
- if resp[0] != ?2
- raise FTPReplyError, resp
- end
- end
- private :voidresp
-
- def sendcmd(cmd)
- synchronize do
- sock_synchronize do
- putline(cmd)
- getresp
- end
- end
- end
-
- def voidcmd(cmd)
- synchronize do
- sock_synchronize do
- putline(cmd)
- voidresp
- end
- end
- nil
- end
-
- def sendport(host, port)
- hbytes = host.split(".")
- pbytes = [port / 256, port % 256]
- bytes = hbytes + pbytes
- cmd = "PORT " + bytes.join(",")
- voidcmd(cmd)
- end
- private :sendport
-
- def makeport
- sock = TCPserver.open(0)
- port = sock.addr[1]
- host = TCPsocket.getaddress(@sock.addr[2])
- resp = sendport(host, port)
- sock
- end
- private :makeport
-
- def transfercmd(cmd)
- if @passive
- host, port = parse227(sendcmd("PASV"))
- conn = open_socket(host, port)
- resp = sendcmd(cmd)
- if resp[0] != ?1
- raise FTPReplyError, resp
- end
- else
- sock = makeport
- resp = sendcmd(cmd)
- if resp[0] != ?1
- raise FTPReplyError, resp
- end
- conn = sock.accept
- end
- conn
- end
- private :transfercmd
-
- def getaddress
- thishost = Socket.gethostname
- if not thishost.index(".")
- thishost = Socket.gethostbyname(thishost)[0]
- end
- if ENV.has_key?("LOGNAME")
- realuser = ENV["LOGNAME"]
- elsif ENV.has_key?("USER")
- realuser = ENV["USER"]
- else
- realuser = "anonymous"
- end
- realuser + "@" + thishost
- end
- private :getaddress
-
- def login(user = "anonymous", passwd = nil, acct = nil)
- if user == "anonymous" and passwd == nil
- passwd = getaddress
- end
-
- resp = ""
- synchronize do
- resp = sendcmd('USER ' + user)
- if resp[0] == ?3
- resp = sendcmd('PASS ' + passwd)
- end
- if resp[0] == ?3
- resp = sendcmd('ACCT ' + acct)
- end
- end
- if resp[0] != ?2
- raise FTPReplyError, resp
- end
- @welcome = resp
- end
+ def initialize(host = nil, user = nil, passwd = nil, acct = nil)
+ super
+ @passive = false
+ @return_code = "\n"
+ @debug_mode = false
+ if host
+ connect(host)
+ if user
+ login(user, passwd, acct)
+ end
+ end
+ end
+
+ def open_socket(host, port)
+ if defined? SOCKSsocket and ENV["SOCKS_SERVER"]
+ @passive = true
+ return SOCKSsocket.open(host, port)
+ else
+ return TCPsocket.open(host, port)
+ end
+ end
+ private :open_socket
+
+ def connect(host, port = FTP_PORT)
+ if @debug_mode
+ print "connect: ", host, ", ", port, "\n"
+ end
+ synchronize do
+ @sock = open_socket(host, port)
+ voidresp
+ end
+ end
+
+ def sanitize(s)
+ if s =~ /^PASS /i
+ return s[0, 5] + "*" * (s.length - 5)
+ else
+ return s
+ end
+ end
+ private :sanitize
+
+ def putline(line)
+ if @debug_mode
+ print "put: ", sanitize(line), "\n"
+ end
+ line = line + CRLF
+ @sock.write(line)
+ end
+ private :putline
+
+ def getline
+ line = @sock.readline # if get EOF, raise EOFError
+ if line[-2, 2] == CRLF
+ line = line[0 .. -3]
+ elsif line[-1] == ?\r or
+ line[-1] == ?\n
+ line = line[0 .. -2]
+ end
+ if @debug_mode
+ print "get: ", sanitize(line), "\n"
+ end
+ return line
+ end
+ private :getline
+
+ def getmultiline
+ line = getline
+ buff = line
+ if line[3] == ?-
+ code = line[0, 3]
+ begin
+ line = getline
+ buff << "\n" << line
+ end until line[0, 3] == code and line[3] != ?-
+ end
+ return buff << "\n"
+ end
+ private :getmultiline
+
+ def getresp
+ resp = getmultiline
+ @lastresp = resp[0, 3]
+ c = resp[0]
+ case c
+ when ?1, ?2, ?3
+ return resp
+ when ?4
+ raise FTPTempError, resp
+ when ?5
+ raise FTPPermError, resp
+ else
+ raise FTPProtoError, resp
+ end
+ end
+ private :getresp
+
+ def voidresp
+ resp = getresp
+ if resp[0] != ?2
+ raise FTPReplyError, resp
+ end
+ end
+ private :voidresp
+
+ def sendcmd(cmd)
+ synchronize do
+ putline(cmd)
+ return getresp
+ end
+ end
- def retrbinary(cmd, blocksize, callback = Proc.new)
- synchronize do
- voidcmd("TYPE I")
- conn = transfercmd(cmd)
- while TRUE
- data = conn.read(blocksize)
- break if data == nil
- callback.call(data)
- end
- conn.close
- voidresp
- end
- end
+ def voidcmd(cmd)
+ synchronize do
+ putline(cmd)
+ voidresp
+ end
+ end
- def retrlines(cmd, callback = nil)
- if iterator?
- callback = Proc.new
- elsif not callback.is_a?(Proc)
- callback = Proc.new {|line| print line, "\n"}
- end
- synchronize do
- voidcmd("TYPE A")
- conn = transfercmd(cmd)
- while TRUE
- line = conn.gets
- break if line == nil
- if line[-2, 2] == CRLF
- line = line[0 .. -3]
- elsif line[-1] == ?\n
- line = line[0 .. -2]
- end
- callback.call(line)
- end
- conn.close
- voidresp
- end
- end
+ def sendport(host, port)
+ hbytes = host.split(".")
+ pbytes = [port / 256, port % 256]
+ bytes = hbytes + pbytes
+ cmd = "PORT " + bytes.join(",")
+ voidcmd(cmd)
+ end
+ private :sendport
+
+ def makeport
+ sock = TCPserver.open(0)
+ port = sock.addr[1]
+ host = TCPsocket.getaddress(@sock.addr[2])
+ resp = sendport(host, port)
+ return sock
+ end
+ private :makeport
+
+ def transfercmd(cmd)
+ if @passive
+ host, port = parse227(sendcmd("PASV"))
+ conn = open_socket(host, port)
+ resp = sendcmd(cmd)
+ if resp[0] != ?1
+ raise FTPReplyError, resp
+ end
+ else
+ sock = makeport
+ resp = sendcmd(cmd)
+ if resp[0] != ?1
+ raise FTPReplyError, resp
+ end
+ conn = sock.accept
+ end
+ return conn
+ end
+ private :transfercmd
+
+ def getaddress
+ thishost = Socket.gethostname
+ if not thishost.index(".")
+ thishost = Socket.gethostbyname(thishost)[0]
+ end
+ if ENV.has_key?("LOGNAME")
+ realuser = ENV["LOGNAME"]
+ elsif ENV.has_key?("USER")
+ realuser = ENV["USER"]
+ else
+ realuser = "anonymous"
+ end
+ return realuser + "@" + thishost
+ end
+ private :getaddress
- def storbinary(cmd, file, blocksize, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- synchronize do
- voidcmd("TYPE I")
- conn = transfercmd(cmd)
- while TRUE
- buf = file.read(blocksize)
- break if buf == nil
- conn.write(buf)
- if use_callback
- callback.call(buf)
- end
- end
- conn.close
- voidresp
- end
- end
+ def login(user = "anonymous", passwd = nil, acct = nil)
+ if user == "anonymous" and passwd == nil
+ passwd = getaddress
+ end
+
+ resp = ""
+ synchronize do
+ resp = sendcmd('USER ' + user)
+ if resp[0] == ?3
+ resp = sendcmd('PASS ' + passwd)
+ end
+ if resp[0] == ?3
+ resp = sendcmd('ACCT ' + acct)
+ end
+ end
+ if resp[0] != ?2
+ raise FTPReplyError, resp
+ end
+ @welcome = resp
+ end
+
+ def retrbinary(cmd, blocksize, callback = Proc.new)
+ synchronize do
+ voidcmd("TYPE I")
+ conn = transfercmd(cmd)
+ loop do
+ data = conn.read(blocksize)
+ break if data == nil
+ callback.call(data)
+ end
+ conn.close
+ voidresp
+ end
+ end
- def storlines(cmd, file, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- synchronize do
- voidcmd("TYPE A")
- conn = transfercmd(cmd)
- while TRUE
- buf = file.gets
- break if buf == nil
- if buf[-2, 2] != CRLF
- if buf[-1] == ?\r or
- buf[-1] == ?\n
- buf = buf[0 .. -2]
- end
- buf = buf + CRLF
- end
- conn.write(buf)
- if use_callback
- callback.call(buf)
- end
- end
- conn.close
- voidresp
- end
- end
+ def retrlines(cmd, callback = nil)
+ if iterator?
+ callback = Proc.new
+ elsif not callback.is_a?(Proc)
+ callback = Proc.new {|line| print line, "\n"}
+ end
+ synchronize do
+ voidcmd("TYPE A")
+ conn = transfercmd(cmd)
+ loop do
+ line = conn.gets
+ break if line == nil
+ if line[-2, 2] == CRLF
+ line = line[0 .. -3]
+ elsif line[-1] == ?\n
+ line = line[0 .. -2]
+ end
+ callback.call(line)
+ end
+ conn.close
+ voidresp
+ end
+ end
+
+ def storbinary(cmd, file, blocksize, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ synchronize do
+ voidcmd("TYPE I")
+ conn = transfercmd(cmd)
+ loop do
+ buf = file.read(blocksize)
+ break if buf == nil
+ conn.write(buf)
+ callback.call(buf) if use_callback
+ end
+ conn.close
+ voidresp
+ end
+ end
- def getbinaryfile(remotefile, localfile,
- blocksize, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- f = open(localfile, "w")
- begin
+ def storlines(cmd, file, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ synchronize do
+ voidcmd("TYPE A")
+ conn = transfercmd(cmd)
+ loop do
+ buf = file.gets
+ break if buf == nil
+ if buf[-2, 2] != CRLF
+ if buf[-1] == ?\r or
+ buf[-1] == ?\n
+ buf = buf[0 .. -2]
+ end
+ buf = buf + CRLF
+ end
+ conn.write(buf)
+ callback.call(buf) if use_callback
+ end
+ conn.close
+ voidresp
+ end
+ end
+
+ def getbinaryfile(remotefile, localfile, blocksize, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ f = open(localfile, "w")
+ begin
f.binmode
- retrbinary("RETR " + remotefile, blocksize) do |data|
- f.write(data)
- if use_callback
- callback.call(data)
- end
- end
- ensure
- f.close
+ retrbinary("RETR " + remotefile, blocksize) do |data|
+ f.write(data)
+ callback.call(data) if use_callback
end
- end
+ ensure
+ f.close
+ end
+ end
- def gettextfile(remotefile, localfile, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- f = open(localfile, "w")
- begin
- retrlines("RETR " + remotefile) do |line|
- line = line + @return_code
- f.write(line)
- if use_callback
- callback.call(line)
- end
- end
- ensure
- f.close
- end
- end
+ def gettextfile(remotefile, localfile, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ f = open(localfile, "w")
+ begin
+ retrlines("RETR " + remotefile) do |line|
+ line = line + @return_code
+ f.write(line)
+ callback.call(line) if use_callback
+ end
+ ensure
+ f.close
+ end
+ end
- def putbinaryfile(localfile, remotefile,
- blocksize, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- f = open(localfile)
- begin
+ def putbinaryfile(localfile, remotefile, blocksize, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ f = open(localfile)
+ begin
f.binmode
- storbinary("STOR " + remotefile, f, blocksize) do |data|
- if use_callback
- callback.call(data)
- end
- end
- ensure
- f.close
+ storbinary("STOR " + remotefile, f, blocksize) do |data|
+ callback.call(data) if use_callback
end
- end
-
- def puttextfile(localfile, remotefile, callback = nil)
- if iterator?
- callback = Proc.new
- end
- use_callback = callback.is_a?(Proc)
- f = open(localfile)
- begin
- storlines("STOR " + remotefile, f) do |line|
- if use_callback
- callback.call(line)
- end
- end
- ensure
- f.close
- end
- end
-
- def acct(account)
- cmd = "ACCT " + account
- voidcmd(cmd)
- end
+ ensure
+ f.close
+ end
+ end
+
+ def puttextfile(localfile, remotefile, callback = nil)
+ if iterator?
+ callback = Proc.new
+ end
+ use_callback = callback.is_a?(Proc)
+ f = open(localfile)
+ begin
+ storlines("STOR " + remotefile, f) do |line|
+ callback.call(line) if use_callback
+ end
+ ensure
+ f.close
+ end
+ end
- def nlst(dir = nil)
- cmd = "NLST"
- if dir
- cmd = cmd + " " + dir
- end
- files = []
+ def acct(account)
+ cmd = "ACCT " + account
+ voidcmd(cmd)
+ end
+
+ def nlst(dir = nil)
+ cmd = "NLST"
+ if dir
+ cmd = cmd + " " + dir
+ end
+ files = []
+ retrlines(cmd) do |line|
+ files.push(line)
+ end
+ return files
+ end
+
+ def list(*args, &block)
+ cmd = "LIST"
+ args.each do |arg|
+ cmd = cmd + " " + arg
+ end
+ if block
+ retrlines(cmd, &block)
+ else
+ lines = []
retrlines(cmd) do |line|
- files.push(line)
+ lines << line
end
- files
- end
-
- def list(*args)
- cmd = "LIST"
- if iterator?
- callback = Proc.new
- elsif args[-1].is_a?(Proc)
- callback = args.pop
- else
- callback = nil
- end
- args.each do |arg|
- cmd = cmd + " " + arg
- end
- retrlines(cmd, callback)
- end
- alias ls list
- alias dir list
-
- def rename(fromname, toname)
- resp = sendcmd("RNFR " + fromname)
- if resp[0] != ?3
- raise FTPReplyError, resp
- end
- voidcmd("RNTO " + toname)
- end
-
- def delete(filename)
- resp = sendcmd("DELE " + filename)
- if resp[0, 3] == "250"
- return
- elsif resp[0] == ?5
- raise FTPPermError, resp
- else
- raise FTPReplyError, resp
- end
- end
-
- def chdir(dirname)
- if dirname == ".."
- begin
- voidcmd("CDUP")
- return
- rescue FTPPermError
- if $![0, 3] != "500"
- raise FTPPermError, $!
- end
- end
- end
- cmd = "CWD " + dirname
- voidcmd(cmd)
- end
-
- def size(filename)
- resp = sendcmd("SIZE " + filename)
- if resp[0, 3] == "213"
- return Integer(resp[3 .. -1].strip)
- end
- end
-
- def mkdir(dirname)
- resp = sendcmd("MKD " + dirname)
- return parse257(resp)
- end
-
- def rmdir(dirname)
- voidcmd("RMD " + dirname)
- end
+ return lines
+ end
+ end
+ alias ls list
+ alias dir list
+
+ def rename(fromname, toname)
+ resp = sendcmd("RNFR " + fromname)
+ if resp[0] != ?3
+ raise FTPReplyError, resp
+ end
+ voidcmd("RNTO " + toname)
+ end
+
+ def delete(filename)
+ resp = sendcmd("DELE " + filename)
+ if resp[0, 3] == "250"
+ return
+ elsif resp[0] == ?5
+ raise FTPPermError, resp
+ else
+ raise FTPReplyError, resp
+ end
+ end
+
+ def chdir(dirname)
+ if dirname == ".."
+ begin
+ voidcmd("CDUP")
+ return
+ rescue FTPPermError
+ if $![0, 3] != "500"
+ raise FTPPermError, $!
+ end
+ end
+ end
+ cmd = "CWD " + dirname
+ voidcmd(cmd)
+ end
- def pwd
- resp = sendcmd("PWD")
+ def size(filename)
+ voidcmd("TYPE I")
+ resp = sendcmd("SIZE " + filename)
+ if resp[0, 3] != "213"
+ raise FTPReplyError, resp
+ end
+ return resp[3..-1].strip
+ end
+
+ MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/
+
+ def mtime(filename, local = false)
+ str = mdtm(filename)
+ ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i}
+ return local ? Time.local(*ary) : Time.gm(*ary)
+ end
+
+ def mkdir(dirname)
+ resp = sendcmd("MKD " + dirname)
+ return parse257(resp)
+ end
+
+ def rmdir(dirname)
+ voidcmd("RMD " + dirname)
+ end
+
+ def pwd
+ resp = sendcmd("PWD")
return parse257(resp)
- end
- alias getdir pwd
-
- def system
- resp = sendcmd("SYST")
- if resp[0, 3] != "215"
- raise FTPReplyError, resp
- end
- return resp[4 .. -1]
- end
-
- def abort
- line = "ABOR" + CRLF
- resp = ""
- sock_synchronize do
- print "put: ABOR\n" if @debug_mode
- @sock.send(line, Socket::MSG_OOB)
- resp = getmultiline
- end
- unless ["426", "226", "225"].include?(resp[0, 3])
- raise FTPProtoError, resp
- end
- resp
- end
-
- def status
- line = "STAT" + CRLF
- resp = ""
- sock_synchronize do
- print "put: STAT\n" if @debug_mode
- @sock.send(line, Socket::MSG_OOB)
- resp = getresp
- end
- resp
- end
-
- def help(arg = nil)
- cmd = "HELP"
- if arg
- cmd = cmd + " " + arg
- end
- sendcmd(cmd)
- end
-
- def quit
- voidcmd("QUIT")
- end
-
- def close
- @sock.close if @sock and not @sock.closed?
- end
+ end
+ alias getdir pwd
+
+ def system
+ resp = sendcmd("SYST")
+ if resp[0, 3] != "215"
+ raise FTPReplyError, resp
+ end
+ return resp[4 .. -1]
+ end
+
+ def abort
+ line = "ABOR" + CRLF
+ print "put: ABOR\n" if @debug_mode
+ @sock.send(line, Socket::MSG_OOB)
+ resp = getmultiline
+ unless ["426", "226", "225"].include?(resp[0, 3])
+ raise FTPProtoError, resp
+ end
+ return resp
+ end
+ def status
+ line = "STAT" + CRLF
+ print "put: STAT\n" if @debug_mode
+ @sock.send(line, Socket::MSG_OOB)
+ return getresp
+ end
+
+ def mdtm(filename)
+ resp = sendcmd("MDTM " + filename)
+ if resp[0, 3] == "213"
+ return resp[3 .. -1].strip
+ end
+ end
+
+ def help(arg = nil)
+ cmd = "HELP"
+ if arg
+ cmd = cmd + " " + arg
+ end
+ sendcmd(cmd)
+ end
+
+ def quit
+ voidcmd("QUIT")
+ end
+
+ def close
+ @sock.close if @sock and not @sock.closed?
+ end
+
def closed?
@sock == nil or @sock.closed?
end
- def parse227(resp)
- if resp[0, 3] != "227"
- raise FTPReplyError, resp
- end
- left = resp.index("(")
- right = resp.index(")")
- if left == nil or right == nil
- raise FTPProtoError, resp
- end
- numbers = resp[left + 1 .. right - 1].split(",")
- if numbers.length != 6
- raise FTPProtoError, resp
- end
- host = numbers[0, 4].join(".")
- port = (Integer(numbers[4]) << 8) + Integer(numbers[5])
- return host, port
- end
- private :parse227
-
- def parse257(resp)
- if resp[0, 3] != "257"
- raise FTPReplyError, resp
- end
- if resp[3, 2] != ' "'
- return ""
- end
- dirname = ""
- i = 5
- n = resp.length
- while i < n
- c = resp[i, 1]
- i = i + 1
- if c == '"'
- if i > n or resp[i, 1] != '"'
- break
- end
- i = i + 1
- end
- dirname = dirname + c
- end
- return dirname
- end
- private :parse257
+ def parse227(resp)
+ if resp[0, 3] != "227"
+ raise FTPReplyError, resp
+ end
+ left = resp.index("(")
+ right = resp.index(")")
+ if left == nil or right == nil
+ raise FTPProtoError, resp
+ end
+ numbers = resp[left + 1 .. right - 1].split(",")
+ if numbers.length != 6
+ raise FTPProtoError, resp
+ end
+ host = numbers[0, 4].join(".")
+ port = (numbers[4].to_i << 8) + numbers[5].to_i
+ return host, port
+ end
+ private :parse227
+
+ def parse257(resp)
+ if resp[0, 3] != "257"
+ raise FTPReplyError, resp
+ end
+ if resp[3, 2] != ' "'
+ return ""
+ end
+ dirname = ""
+ i = 5
+ n = resp.length
+ while i < n
+ c = resp[i, 1]
+ i = i + 1
+ if c == '"'
+ if i > n or resp[i, 1] != '"'
+ break
+ end
+ i = i + 1
+ end
+ dirname = dirname + c
+ end
+ return dirname
+ end
+ private :parse257
end
+
+## ftplib.rb ends here
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
new file mode 100644
index 0000000000..98a73ae3db
--- /dev/null
+++ b/lib/getoptlong.rb
@@ -0,0 +1,473 @@
+# -*- Ruby -*-
+# Copyright (C) 1998 Motoyuki Kasahara
+#
+# 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, 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.
+#
+
+#
+# Documents and latest version of `getoptlong.rb' are found at:
+# http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+#
+
+#
+# Parse command line options just like GNU getopt_long().
+#
+class GetoptLong
+ #
+ # Orderings.
+ #
+ ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
+
+ #
+ # Argument flags.
+ #
+ ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
+ OPTIONAL_ARGUMENT = 2]
+
+ #
+ # Status codes.
+ #
+ STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0..2
+
+ #
+ # Error types.
+ #
+ class AmbigousOption < StandardError; end
+ class NeedlessArgument < StandardError; end
+ class MissingArgument < StandardError; end
+ class InvalidOption < StandardError; end
+
+ #
+ # Initializer.
+ #
+ def initialize(*arguments)
+ #
+ # Current ordering.
+ #
+ if ENV.include?('POSIXLY_CORRECT')
+ @ordering = REQUIRE_ORDER
+ else
+ @ordering = PERMUTE
+ end
+
+ #
+ # Hash table of option names.
+ # Keyes of the table are option names, and their values are canonical
+ # names of the options.
+ #
+ @canonical_names = Hash.new
+
+ #
+ # Hash table of argument flags.
+ # Keyes of the table are option names, and their values are argument
+ # flags of the options.
+ #
+ @argument_flags = Hash.new
+
+ #
+ # Whether error messages are output to stderr.
+ #
+ @quiet_flag = FALSE
+
+ #
+ # Status code.
+ #
+ @status = STATUS_YET
+
+ #
+ # Error code.
+ #
+ @error = nil
+
+ #
+ # Error message.
+ #
+ @error_message = nil
+
+ #
+ # Rest of catinated short options.
+ #
+ @rest_singles = ''
+
+ #
+ # List of non-option-arguments.
+ # Append them to ARGV when option processing is terminated.
+ #
+ @non_option_arguments = Array.new
+
+ if 0 < arguments.length
+ set_options(*arguments)
+ end
+ end
+
+ #
+ # Set ordering.
+ #
+ def ordering=(ordering)
+ #
+ # The method is failed if option processing has already started.
+ #
+ if @status != STATUS_YET
+ set_error(ArgumentError, "argument error")
+ raise RuntimeError,
+ "invoke ordering=, but option processing has already started"
+ end
+
+ #
+ # Check ordering.
+ #
+ if !ORDERINGS.include?(ordering)
+ raise ArgumentError, "invalid ordering `#{ordering}'"
+ end
+ if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
+ @ordering = REQUIRE_ORDER
+ else
+ @ordering = ordering
+ end
+ end
+
+ #
+ # Return ordering.
+ #
+ attr_reader :ordering
+
+ #
+ # Set options
+ #
+ def set_options(*arguments)
+ #
+ # The method is failed if option processing has already started.
+ #
+ if @status != STATUS_YET
+ raise RuntimeError,
+ "invoke set_options, but option processing has already started"
+ end
+
+ #
+ # Clear tables of option names and argument flags.
+ #
+ @canonical_names.clear
+ @argument_flags.clear
+
+ arguments.each do |arg|
+ #
+ # Each argument must be an Array.
+ #
+ if !arg.is_a?(Array)
+ raise ArgumentError, "the option list contains non-Array argument"
+ end
+
+ #
+ # Find an argument flag and it set to `argument_flag'.
+ #
+ argument_flag = nil
+ arg.each do |i|
+ if ARGUMENT_FLAGS.include?(i)
+ if argument_flag != nil
+ raise ArgumentError, "too many argument-flags"
+ end
+ argument_flag = i
+ end
+ end
+ raise ArgumentError, "no argument-flag" if argument_flag == nil
+
+ canonical_name = nil
+ arg.each do |i|
+ #
+ # Check an option name.
+ #
+ next if i == argument_flag
+ begin
+ if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
+ raise ArgumentError, "an invalid option `#{i}'"
+ end
+ if (@canonical_names.include?(i))
+ raise ArgumentError, "option redefined `#{i}'"
+ end
+ rescue
+ @canonical_names.clear
+ @argument_flags.clear
+ raise
+ end
+
+ #
+ # Register the option (`i') to the `@canonical_names' and
+ # `@canonical_names' Hashes.
+ #
+ if canonical_name == nil
+ canonical_name = i
+ end
+ @canonical_names[i] = canonical_name
+ @argument_flags[i] = argument_flag
+ end
+ raise ArgumentError, "no option name" if canonical_name == nil
+ end
+ return self
+ end
+
+ #
+ # Set/Unset `quit' mode.
+ #
+ attr_writer :quiet
+
+ #
+ # Return the flag of `quiet' mode.
+ #
+ attr_reader :quiet
+
+ #
+ # `quiet?' is an alias of `quiet'.
+ #
+ alias quiet? quiet
+
+ #
+ # Termintate option processing.
+ #
+ def terminate
+ return if @status == STATUS_TERMINATED
+ raise RuntimeError, "an error has occured" if @error != nil
+
+ @status = STATUS_TERMINATED
+ @non_option_arguments.reverse_each do |argument|
+ ARGV.unshift(argument)
+ end
+
+ @canonical_names = nil
+ @argument_flags = nil
+ @rest_singles = nil
+ @non_option_arguments = nil
+
+ return self
+ end
+
+ #
+ # Examine whether option processing is termintated or not.
+ #
+ def terminated?
+ return @status == STATUS_TERMINATED
+ end
+
+ #
+ # Set an error (protected).
+ #
+ def set_error(type, message)
+ $stderr.print("#{$0}: #{message}\n") if !@quiet_flag
+
+ @error = type
+ @error_message = message
+ @canonical_names = nil
+ @argument_flags = nil
+ @rest_singles = nil
+ @non_option_arguments = nil
+
+ raise type, message
+ end
+ protected :set_error
+
+ #
+ # Examine whether an option processing is failed.
+ #
+ attr_reader :error
+
+ #
+ # `error?' is an alias of `error'.
+ #
+ alias error? error
+
+ #
+ # Return an error message.
+ #
+ def error_message
+ return @error_message
+ end
+
+ #
+ # Get next option name and its argument as an array.
+ #
+ def get
+ name, argument = nil, ''
+
+ #
+ # Check status.
+ #
+ return if @error != nil
+ case @status
+ when STATUS_YET
+ @status = STATUS_STARTED
+ when STATUS_TERMINATED
+ return
+ end
+
+ #
+ # Get next option argument.
+ #
+ if 0 < @rest_singles.length
+ $_ = '-' + @rest_singles
+ elsif (ARGV.length == 0)
+ terminate
+ return nil
+ elsif @ordering == PERMUTE
+ while 0 < ARGV.length && ARGV[0] !~ /^-./
+ @non_option_arguments.push(ARGV.shift)
+ end
+ if ARGV.length == 0
+ terminate
+ return
+ end
+ $_ = ARGV.shift
+ elsif @ordering == REQUIRE_ORDER
+ if (ARGV[0] !~ /^-./)
+ terminate
+ return nil
+ end
+ $_ = ARGV.shift
+ else
+ $_ = ARGV.shift
+ end
+
+ #
+ # Check the special argument `--'.
+ # `--' indicates the end of the option list.
+ #
+ if $_ == '--' && @rest_singles.length == 0
+ terminate
+ return nil
+ end
+
+ #
+ # Check for long and short options.
+ #
+ if /^(--[^=]+)/ && @rest_singles.length == 0
+ #
+ # This is a long style option, which start with `--'.
+ #
+ pattern = $1
+ if @canonical_names.include?(pattern)
+ name = pattern
+ else
+ #
+ # The option `name' is not registered in `@canonical_names'.
+ # It may be an abbreviated.
+ #
+ match_count = 0
+ @canonical_names.each_key do |key|
+ if key.index(pattern) == 0
+ name = key
+ match_count += 1
+ end
+ end
+ if 2 <= match_count
+ set_error(AmbigousOption, "option `#{$_}' is ambiguous")
+ elsif match_count == 0
+ set_error(InvalidOption, "unrecognized option `#{$_}'")
+ end
+ end
+
+ #
+ # Check an argument to the option.
+ #
+ if @argument_flags[name] == REQUIRED_ARGUMENT
+ if /=(.*)$/
+ argument = $1
+ elsif 0 < ARGV.length
+ argument = ARGV.shift
+ else
+ set_error(MissingArgument, "option `#{$_}' requires an argument")
+ end
+ elsif @argument_flags[name] == OPTIONAL_ARGUMENT
+ if /=(.*)$/
+ argument = $1
+ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+ argument = ARGV.shift
+ else
+ argument = ''
+ end
+ elsif /=(.*)$/
+ set_error(NeedlessArgument,
+ "option `#{name}' doesn't allow an argument")
+ end
+
+ elsif /^(-(.))(.*)/
+ #
+ # This is a short style option, which start with `-' (not `--').
+ # Short options may be catinated (e.g. `-l -g' is equivalent to
+ # `-lg').
+ #
+ name, ch, @rest_singles = $1, $2, $3
+
+ if @canonical_names.include?(name)
+ #
+ # The option `name' is found in `@canonical_names'.
+ # Check its argument.
+ #
+ if @argument_flags[name] == REQUIRED_ARGUMENT
+ if 0 < @rest_singles.length
+ argument = @rest_singles
+ @rest_singles = ''
+ elsif 0 < ARGV.length
+ argument = ARGV.shift
+ else
+ # 1003.2 specifies the format of this message.
+ set_error(MissingArgument, "option requires an argument -- #{ch}")
+ end
+ elsif @argument_flags[name] == OPTIONAL_ARGUMENT
+ if 0 < @rest_singles.length
+ argument = @rest_singles
+ @rest_singles = ''
+ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+ argument = ARGV.shift
+ else
+ argument = ''
+ end
+ end
+ else
+ #
+ # This is an invalid option.
+ # 1003.2 specifies the format of this message.
+ #
+ if ENV.include?('POSIXLY_CORRECT')
+ set_error(InvalidOption, "illegal option -- #{ch}")
+ else
+ set_error(InvalidOption, "invalid option -- #{ch}")
+ end
+ end
+ else
+ #
+ # This is a non-option argument.
+ # Only RETURN_IN_ORDER falled into here.
+ #
+ return '', $_
+ end
+
+ return @canonical_names[name], argument
+ end
+
+ #
+ # `get_option' is an alias of `get'.
+ #
+ alias get_option get
+
+ #
+ # Iterator version of `get'.
+ #
+ def each
+ loop do
+ name, argument = get_option
+ break if name == nil
+ yield name, argument
+ end
+ end
+
+ #
+ # `each_option' is an alias of `each'.
+ #
+ alias each_option each
+end
diff --git a/lib/getopts.rb b/lib/getopts.rb
index 6929f7e4fd..9e1e8a2cf6 100644
--- a/lib/getopts.rb
+++ b/lib/getopts.rb
@@ -1,4 +1,3 @@
-#!/usr/local/bin/ruby
#
# getopts.rb -
# $Release Version: $
@@ -11,7 +10,7 @@
#
#
-$RCS_ID="$Header$"
+$RCS_ID=%q$Header$
def isSingle(lopt)
if lopt.index(":")
diff --git a/lib/importenv.rb b/lib/importenv.rb
index 41253765ea..10b289199c 100644
--- a/lib/importenv.rb
+++ b/lib/importenv.rb
@@ -21,9 +21,12 @@ for k,v in ENV
EOS
end
-p $TERM
-$TERM = nil
-p $TERM
-p ENV["TERM"]
-$TERM = "foo"
-p ENV["TERM"]
+if __FILE__ == $0
+ p $TERM
+ $TERM = nil
+ p $TERM
+ p ENV["TERM"]
+ $TERM = "foo"
+ p ENV["TERM"]
+end
+
diff --git a/lib/jcode.rb b/lib/jcode.rb
index 40ab48ddac..50b7beee9d 100644
--- a/lib/jcode.rb
+++ b/lib/jcode.rb
@@ -11,13 +11,13 @@ class String
alias original_succ succ
private :original_succ
- def mbchar?(c)
+ def mbchar?
if $KCODE =~ /^s/i
- c =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
+ self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
elsif $KCODE =~ /^e/i
- c =~ /[\xa1-\xfe][\xa1-\xfe]/n
+ self =~ /[\xa1-\xfe][\xa1-\xfe]/n
else
- FALSE
+ false
end
end
@@ -25,12 +25,13 @@ class String
if self[-2] && self[-2] & 0x80 != 0
s = self.dup
s[-1] += 1
- s[-1] += 1 if !mbchar?(s)
+ s[-1] += 1 if !s.mbchar?
return s
else
original_succ
end
end
+ alias next succ
def upto(to)
return if self > to
@@ -41,7 +42,7 @@ class String
if self[0..-2] == to[0..-2]
first = self[-2].chr
for c in self[-1] .. to[-1]
- if mbchar?(first+c.chr)
+ if (first+c.chr).mbchar?
yield self[0..-2]+c.chr
end
end
@@ -103,7 +104,7 @@ class String
end
def tr(from, to)
- self.dup.tr!(from, to)
+ (str = self.dup).tr!(from, to) or str
end
def delete!(del)
@@ -126,7 +127,7 @@ class String
end
def delete(del)
- self.dup.delete!(del)
+ (str = self.dup).delete!(del) or str
end
def squeeze!(del=nil)
@@ -154,7 +155,7 @@ class String
end
def squeeze(del=nil)
- self.dup.squeeze!(del)
+ (str = self.dup).squeeze!(del) or str
end
def tr_s!(from, to)
@@ -187,7 +188,7 @@ class String
end
def tr_s(from, to)
- self.dup.tr_s!(from,to)
+ (str = self.dup).tr_s!(from,to) or str
end
alias original_chop! chop!
@@ -201,7 +202,7 @@ class String
end
def chop
- self.dup.chop!
+ (str = self.dup).chop! or str
end
end
$VERBOSE = $vsave
diff --git a/lib/mailread.rb b/lib/mailread.rb
index a5d60c84b4..5e46606c09 100644
--- a/lib/mailread.rb
+++ b/lib/mailread.rb
@@ -1,7 +1,7 @@
class Mail
def initialize(f)
- unless f.kind_of?(IO)
+ unless defined? f.gets
f = open(f, "r")
opened = true
end
@@ -15,7 +15,8 @@ class Mail
break if /^$/ # end of header
if /^(\S+):\s*(.*)/
- @header[attr = $1.capitalize!] = $2
+ (attr = $1).capitalize!
+ @header[attr] = $2
elsif attr
sub!(/^\s*/, '')
@header[attr] += "\n" + $_
diff --git a/lib/mathn.rb b/lib/mathn.rb
index fdf27f6771..265ef1337f 100644
--- a/lib/mathn.rb
+++ b/lib/mathn.rb
@@ -1,8 +1,8 @@
#
# mathn.rb -
# $Release Version: 0.5 $
-# $Revision: 1.1 $
-# $Date: 1997/07/03 04:43:47 $
+# $Revision: 1.1.1.1.4.1 $
+# $Date: 1998/01/16 12:36:05 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# --
@@ -96,6 +96,7 @@ class Prime
@counts.push @seed + @seed
return @seed
end
+ alias next succ
def each
loop do
diff --git a/lib/matrix.rb b/lib/matrix.rb
index 394c66f098..64b0738e1b 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -1,9 +1,8 @@
-#!/usr/local/bin/ruby
#
# matrix.rb -
# $Release Version: 1.0$
-# $Revision: 1.0 $
-# $Date: 97/05/23 11:35:28 $
+# $Revision: 1.6 $
+# $Date: 1998/07/31 03:39:49 $
# Original Version from Smalltalk-80 version
# on July 23, 1985 at 8:37:17 am
# by Keiju ISHITSUKA
@@ -18,9 +17,158 @@
# :
# rown]
#
-# column: Îó
-# row: ¹Ô
#
+# module ExceptionForMatrix::
+# Exceptions:
+# ErrDimensionMismatch
+# number of column/row do not match
+# ErrNotRegular
+# not a regular matrix
+# ErrOperationNotDefined
+# specified operator is not defined (yet)
+#
+# class Matrix
+# include ExceptionForMatrix
+#
+# Methods:
+# class methods:
+# Matrix.[](*rows)
+# creates a matrix where `rows' indicates rows.
+# `rows' is an array of arrays,
+# e.g, Matrix[[11, 12], [21, 22]]
+# Matrix.rows(rows, copy = TRUE)
+# creates a matrix where `rows' indicates rows.
+# if optional argument `copy' is false, use the array as
+# internal structure of the metrix without copying.
+# Matrix.columns(columns)
+# creates a new matrix using `columns` as set of colums vectors.
+# Matrix.diagonal(*values)
+# creates a matrix where `columns' indicates columns.
+# Matrix.scalar(n, value)
+# creates a diagonal matrix such that the diagal compornents is
+# given by `values'.
+# Matrix.scalar(n, value)
+# creates an n-by-n scalar matrix such that the diagal compornent is
+# given by `value'.
+# Matrix.identity(n)
+# Matrix.unit(n)
+# Matrix.I(n)
+# creates an n-by-n unit matrix.
+# Matrix.zero(n)
+# creates an n-by-n zero matrix.
+# Matrix.row_vector(row)
+# creates a 1-by-n matrix such the row vector is `row'.
+# `row' is specifed as a Vector or an Array.
+# Matrix.column_vector(column)
+# creates a 1-by-n matrix such that column vector is `column'.
+# `column' is specifed as a Vector or an Array.
+# accessing:
+# [](i, j)
+# returns (i,j) compornent
+# row_size
+# returns the number of rows
+# column_size
+# returns the number of columns
+# row(i)
+# returns the i-th row vector.
+# when the block is supplied for the method, the block is iterated
+# over all row vectors.
+# column(j)
+# returns the jth column vector.
+# when the block is supplied for the method, the block is iterated
+# over all column vectors.
+# collect
+# map
+# creates a matrix which is the result of iteration of given
+# block over all compornents.
+# minor(*param)
+# returns sub matrix. parameter is specified as the following:
+# 1. from_row, row_size, from_col, size_col
+# 2. from_row..to_row, from_col..to_col
+# TESTING:
+# regular?
+# Is regular?
+# singular?
+# Is singular? i.e. Is non-regular?
+# square?
+# Is square?
+# ARITHMETIC:
+# *(m)
+# times
+# +(m)
+# plus
+# -(m)
+# minus
+# /(m)
+# self * m.inv
+# inverse
+# inv
+# inverse
+# **
+# power
+# Matrix functions:
+# determinant
+# det
+# returns the determinant
+# rank
+# returns the rank
+# trace
+# tr
+# returns the trace
+# transpose
+# t
+# returns the transposed
+# CONVERTING:
+# coerce(other)
+# row_vectors
+# array of row vectors
+# column_vectors
+# array of column vectors
+# to_a
+# converts each element to Array
+# to_f
+# converts each element to Float
+# to_i
+# converts each element to Integer
+# to_r
+# converts each element to Rational
+# PRINTING:
+# to_s
+# returns string representation
+# inspect
+#
+# class Vector
+# include ExceptionForMatrix
+#
+# INSTANCE CREATION:
+# Vector.[](*array)
+# Vector.elements(array, copy = TRUE)
+# ACCSESSING:
+# [](i)
+# size
+# ENUMRATIONS:
+# each2(v)
+# collect2(v)
+# ARITHMETIC:
+# *(x) "is matrix or number"
+# +(v)
+# -(v)
+# VECTOR FUNCTIONS:
+# inner_product(v)
+# collect
+# map
+# map2(v)
+# r
+# CONVERTING:
+# covector
+# to_a
+# to_f
+# to_i
+# to_r
+# coerce(other)
+# PRINTING:
+# to_s
+# inspect
require "e2mmap.rb"
@@ -36,8 +184,8 @@ module ExceptionForMatrix
end
class Matrix
- RCS_ID='-$Header: ruby-mode,v 1.2 91/04/20 17:24:57 keiju Locked $-'
-
+ @RCS_ID='-$Id: matrix.rb,v 1.6 1998/07/31 03:39:49 keiju Exp keiju $-'
+
include ExceptionForMatrix
# instance creations
@@ -144,6 +292,7 @@ class Matrix
if iterator?
for e in @rows[i]
yield e
+
end
else
Vector.elements(@rows[i])
@@ -211,6 +360,38 @@ class Matrix
column_size == row_size
end
+ # COMPARING
+ def ==(other)
+ return FALSE unless Matrix === other
+
+ other.compare_by_row_vectors(@rows)
+ end
+ alias eql? ==
+
+ def compare_by_row_vectors(rows)
+ return FALSE unless @rows.size == rows.size
+
+ 0.upto(@rows.size - 1) do
+ |i|
+ return FALSE unless @rows[i] == rows[i]
+ end
+ TRUE
+ end
+
+ def clone
+ Matrix.rows(@rows)
+ end
+
+ def hash
+ value = 0
+ for row in @rows
+ for e in row
+ value ^= e.hash
+ end
+ end
+ return value
+ end
+
# ARITHMETIC
def *(m) #is matrix or vector or number"
@@ -297,6 +478,25 @@ class Matrix
}
Matrix.rows(rows, FALSE)
end
+
+ def /(other)
+ case other
+ when Numeric
+ rows = @rows.collect {
+ |row|
+ row.collect {
+ |e|
+ e / other
+ }
+ }
+ return Matrix.rows(rows, FALSE)
+ when Matrix
+ return self * other.inverse
+ else
+ x, y = other.coerce(self)
+ rerurn x / y
+ end
+ end
def inverse
Matrix.fail ErrDimensionMismatch unless square?
@@ -597,13 +797,12 @@ end
#----------------------------------------------------------------------
class Vector
include ExceptionForMatrix
-
#INSTANCE CREATION
private_class_method :new
def Vector.[](*array)
- new(:init_elements, array, copy = FALSE)
+ new(:init_elements, array, FALSE)
end
def Vector.elements(array, copy = TRUE)
@@ -649,6 +848,26 @@ class Vector
end
end
+ # COMPARING
+ def ==(other)
+ return FALSE unless Vector === other
+
+ other.compare_by(@elements)
+ end
+ alias eqn? ==
+
+ def compare_by(elements)
+ @elements == elements
+ end
+
+ def clone
+ Vector.elements(@elements)
+ end
+
+ def hash
+ @elements.hash
+ end
+
# ARITHMETIC
def *(x) "is matrix or number"
@@ -733,7 +952,7 @@ class Vector
for e in @elements
v += e*e
end
- return v.sqrt
+ return Math.sqrt(v)
end
# CONVERTING
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 2bf3684920..7e131fe890 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -1,7 +1,8 @@
-# module to create Makefile for extention modules
+# module to create Makefile for extension modules
# invoke like: ruby -r mkmf extconf.rb
require 'rbconfig'
+require 'find'
include Config
@@ -36,6 +37,7 @@ $install = CONFIG["INSTALL_PROGRAM"]
$install_data = CONFIG["INSTALL_DATA"]
if $install !~ /^\// then
$install = CONFIG["srcdir"]+"/"+$install
+ $install_data = CONFIG["srcdir"]+"/"+$install_data
end
if File.exist? $archdir + "/ruby.h"
@@ -47,28 +49,60 @@ else
exit 1
end
-nul = "> /dev/null"
-
CFLAGS = CONFIG["CFLAGS"]
if PLATFORM == "m68k-human"
- nul = "> nul"
CFLAGS.gsub!(/-c..-stack=[0-9]+ */, '')
end
-if $DEBUG
- nul = ""
+if /win32|djgpp|mingw32|m68k-human/i =~ PLATFORM
+ $null = open("nul", "w")
+else
+ $null = open("/dev/null", "w")
+end
+LINK = "#{CONFIG['CC']} -o conftest -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s #{CONFIG['LDFLAGS']} %s conftest.c #{CONFIG['LIBS']} %s"
+CPP = "#{CONFIG['CPP']} -E -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s conftest.c"
+
+$orgerr = $stderr.dup
+$orgout = $stdout.dup
+def xsystem command
+ if $DEBUG
+ print command, "\n"
+ return system(command)
+ end
+ $stderr.reopen($null)
+ $stdout.reopen($null)
+ r = system(command)
+ $stderr.reopen($orgerr)
+ $stdout.reopen($orgout)
+ return r
end
-LINK = CONFIG["CC"]+" -o conftest -I#{$srcdir} " + CFLAGS + " %s " + CONFIG["LDFLAGS"] + " %s conftest.c " + CONFIG["LIBS"] + "%s " + nul + " 2>&1"
-CPP = CONFIG["CPP"] + " -E -I#{$srcdir} " + CFLAGS + " %s conftest.c " + nul + " 2>&1"
def try_link(libs)
- system(format(LINK, $CFLAGS, $LDFLAGS, libs))
+ xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs))
end
def try_cpp
- system(format(CPP, $CFLAGS))
+ xsystem(format(CPP, $CFLAGS))
+end
+
+def install_rb(mfile)
+ path = []
+ dir = []
+ Find.find("lib") do |f|
+ next unless /\.rb$/ =~ f
+ f = f[4..-1]
+ path.push f
+ dir |= File.dirname(f)
+ end
+ for f in dir
+ next if f == "."
+ mfile.printf "\t@test -d $(libdir)/%s || mkdir $(libdir)/%s\n", f, f
+ end
+ for f in path
+ mfile.printf "\t$(INSTALL_DATA) lib/%s $(libdir)/%s\n", f, f
+ end
end
-def have_library(lib, func)
+def have_library(lib, func="main")
printf "checking for %s() in -l%s... ", func, lib
STDOUT.flush
if $lib_cache[lib]
@@ -86,32 +120,40 @@ def have_library(lib, func)
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
+ if func && func != ""
+ cfile = open("conftest.c", "w")
+ cfile.printf "\
int main() { return 0; }
int t() { %s(); return 0; }
", func
- cfile.close
+ cfile.close
- begin
+ begin
+ if $libs
+ libs = "-l" + lib + " " + $libs
+ else
+ libs = "-l" + lib
+ end
+ unless try_link(libs)
+ $lib_cache[lib] = 'no'
+ $cache_mod = TRUE
+ print "no\n"
+ return FALSE
+ end
+ ensure
+ system "rm -f conftest*"
+ end
+ else
if $libs
libs = "-l" + lib + " " + $libs
else
libs = "-l" + lib
end
- unless try_link(libs)
- $lib_found[lib] = 'no'
- $found = TRUE
- print "no\n"
- return FALSE
- end
- ensure
- system "rm -f conftest*"
end
$libs = libs
- $lib_found[lib] = 'yes'
- $found = TRUE
+ $lib_cache[lib] = 'yes'
+ $cache_mod = TRUE
print "yes\n"
return TRUE
end
@@ -221,9 +263,15 @@ def create_makefile(target)
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end
$libs = "" unless $libs
+ $DLDFLAGS = CONFIG["DLDFLAGS"]
+
+ if PLATFORM =~ /beos/
+ $libs = $libs + " -lruby"
+ $DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib"
+ end
- if !$objs then
- $objs = Dir["*.c"]
+ unless $objs then
+ $objs = Dir["*.{c,cc}"]
for f in $objs
f.sub!(/\.(c|cc)$/, ".o")
end
@@ -239,15 +287,18 @@ SHELL = /bin/sh
srcdir = #{$srcdir}
hdrdir = #{$hdrdir}
-CC = gcc
+CC = #{CONFIG["CC"]}
-CFLAGS = #{CONFIG["CCDLFLAGS"]} -I#{$hdrdir} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")}
-DLDFLAGS = #{CONFIG["DLDFLAGS"]} #{$LDFLAGS}
+prefix = #{CONFIG["prefix"]}
+CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) -I#{CONFIG["includedir"]} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")}
+CXXFLAGS = $(CFLAGS)
+DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS}
LDSHARED = #{CONFIG["LDSHARED"]}
prefix = #{CONFIG["prefix"]}
exec_prefix = #{CONFIG["exec_prefix"]}
-libdir = #{$archdir}
+libdir = #{$libdir}
+archdir = #{$archdir}
#### End of system configuration section. ####
@@ -258,6 +309,7 @@ OBJS = #{$objs}
TARGET = #{target}.#{CONFIG["DLEXT"]}
INSTALL = #{$install}
+INSTALL_DATA = #{$install_data}
binsuffix = #{CONFIG["binsuffix"]}
@@ -269,21 +321,20 @@ clean:; @rm -f *.o *.so *.sl
realclean: clean
-install: $(libdir)/$(TARGET)
+install: $(archdir)/$(TARGET)
-$(libdir)/$(TARGET): $(TARGET)
+$(archdir)/$(TARGET): $(TARGET)
@test -d $(libdir) || mkdir $(libdir)
- $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
+ @test -d $(archdir) || mkdir $(archdir)
+ $(INSTALL) $(TARGET) $(archdir)/$(TARGET)
EOMF
- for rb in Dir["lib/*.rb"]
- mfile.printf "\t$(INSTALL) %s %s\n", rb, $libdir
- end
+ install_rb(mfile)
mfile.printf "\n"
if CONFIG["DLEXT"] != "o"
mfile.printf <<EOMF
$(TARGET): $(OBJS)
- $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS)
+ $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS)
EOMF
elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") or
mfile.print "$(TARGET): $(OBJS)\n"
@@ -332,12 +383,19 @@ EOMF
rescue
end
end
+
+ if PLATFORM =~ /beos/
+ print "creating ruby.def\n"
+ open("ruby.def", "w") do |file|
+ file.print("EXPORTS\n") if PLATFORM =~ /^i/
+ file.print("Init_#{target}\n")
+ end
+ end
end
-$local_libs = nil
-$libs = nil
+$libs = PLATFORM =~ /cygwin32|beos/ ? nil : "-lc"
$objs = nil
-$CFLAGS = nil
-$LDFLAGS = nil
+$local_libs = ""
+$CFLAGS = ""
+$LDFLAGS = ""
$defs = []
-
diff --git a/lib/monitor.rb b/lib/monitor.rb
new file mode 100644
index 0000000000..81fe8f2b22
--- /dev/null
+++ b/lib/monitor.rb
@@ -0,0 +1,325 @@
+## monitor.rb
+
+# Author: Shugo Maeda <shugo@po.aianet.ne.jp>
+# Version: $Revision: 0.1 $
+
+# USAGE:
+#
+# foo = Foo.new
+# foo.extend(MonitorMixin)
+# cond = foo.new_cond
+#
+# thread1:
+# foo.synchronize {
+# ...
+# cond.wait_until { foo.done? }
+# ...
+# }
+#
+# thread2:
+# foo.synchronize {
+# foo.do_something
+# cond.signal
+# }
+
+# ATTENTION:
+#
+# If you include MonitorMixin and override `initialize', you should
+# call `super'.
+# If you include MonitorMixin to built-in classes, you should override
+# `new' to call `mon_initialize'.
+
+## Code:
+
+require "final"
+
+module MonitorMixin
+
+ RCS_ID = %q$Id: monitor.rb,v 0.1 1998/03/01 08:40:18 shugo Exp shugo $
+
+ module Primitive
+
+ include MonitorMixin
+
+ MON_OWNER_TABLE = {}
+ MON_COUNT_TABLE = {}
+ MON_ENTERING_QUEUE_TABLE = {}
+ MON_WAITING_QUEUE_TABLE = {}
+
+ FINALIZER = Proc.new { |id|
+ MON_OWNER_TABLE.delete(id)
+ MON_COUNT_TABLE.delete(id)
+ MON_ENTERING_QUEUE_TABLE.delete(id)
+ MON_WAITING_QUEUE_TABLE.delete(id)
+ }
+
+ def self.extend_object(obj)
+ super(obj)
+ obj.mon_initialize
+ end
+
+ def mon_initialize
+ MON_OWNER_TABLE[id] = nil
+ MON_COUNT_TABLE[id] = 0
+ MON_ENTERING_QUEUE_TABLE[id] = []
+ MON_WAITING_QUEUE_TABLE[id] = []
+ ObjectSpace.define_finalizer(self, FINALIZER)
+ end
+
+ def mon_owner
+ return MON_OWNER_TABLE[id]
+ end
+
+ def mon_count
+ return MON_COUNT_TABLE[id]
+ end
+
+ def mon_entering_queue
+ return MON_ENTERING_QUEUE_TABLE[id]
+ end
+
+ def mon_waiting_queue
+ return MON_WAITING_QUEUE_TABLE[id]
+ end
+
+ def set_mon_owner(val)
+ return MON_OWNER_TABLE[id] = val
+ end
+
+ def set_mon_count(val)
+ return MON_COUNT_TABLE[id] = val
+ end
+
+ private :mon_count, :mon_entering_queue, :mon_waiting_queue,
+ :set_mon_owner, :set_mon_count
+ end
+
+ module NonPrimitive
+
+ include MonitorMixin
+
+ attr_reader :mon_owner, :mon_count,
+ :mon_entering_queue, :mon_waiting_queue
+
+ def self.extend_object(obj)
+ super(obj)
+ obj.mon_initialize
+ end
+
+ def mon_initialize
+ @mon_owner = nil
+ @mon_count = 0
+ @mon_entering_queue = []
+ @mon_waiting_queue = []
+ end
+
+ def set_mon_owner(val)
+ @mon_owner = val
+ end
+
+ def set_mon_count(val)
+ @mon_count = val
+ end
+
+ private :mon_count, :mon_entering_queue, :mon_waiting_queue,
+ :set_mon_owner, :set_mon_count
+ end
+
+ def self.extendable_module(obj)
+ if Fixnum === obj or TrueClass === obj or FalseClass === obj or
+ NilClass === obj
+ raise TypeError, "MonitorMixin can't extend #{obj.type}"
+ else
+ begin
+ obj.instance_eval("@mon_owner")
+ return NonPrimitive
+ rescue TypeError
+ return Primitive
+ end
+ end
+ end
+
+ def self.extend_object(obj)
+ obj.extend(extendable_module(obj))
+ end
+
+ def self.includable_module(klass)
+ if klass.instance_of?(Module)
+ return NonPrimitive
+ end
+ begin
+ dummy = klass.new
+ return extendable_module(dummy)
+ rescue ArgumentError
+ if klass.singleton_methods.include?("new")
+ return Primitive
+ else
+ return NonPrimitive
+ end
+ rescue NameError
+ raise TypeError, "#{klass} can't include MonitorMixin"
+ end
+ end
+
+ def self.append_features(klass)
+ mod = includable_module(klass)
+ klass.module_eval("include mod")
+ end
+
+ def initialize(*args)
+ super
+ mon_initialize
+ end
+
+ def try_mon_enter
+ result = false
+ Thread.critical = true
+ if mon_owner.nil?
+ set_mon_owner(Thread.current)
+ end
+ if mon_owner == Thread.current
+ set_mon_count(mon_count + 1)
+ result = true
+ end
+ Thread.critical = false
+ return result
+ end
+
+ def mon_enter
+ Thread.critical = true
+ while mon_owner != nil && mon_owner != Thread.current
+ mon_entering_queue.push(Thread.current)
+ Thread.stop
+ Thread.critical = true
+ end
+ set_mon_owner(Thread.current)
+ set_mon_count(mon_count + 1)
+ Thread.critical = false
+ end
+
+ def mon_exit
+ if mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ set_mon_count(mon_count - 1)
+ if mon_count == 0
+ set_mon_owner(nil)
+ if mon_waiting_queue.empty?
+ t = mon_entering_queue.shift
+ else
+ t = mon_waiting_queue.shift
+ end
+ end
+ t.wakeup if t
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def mon_synchronize
+ mon_enter
+ begin
+ yield
+ ensure
+ mon_exit
+ end
+ end
+ alias synchronize mon_synchronize
+
+ class ConditionVariable
+ def initialize(monitor)
+ @monitor = monitor
+ @waiters = []
+ end
+
+ def wait
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+
+ @monitor.instance_eval(<<MON_EXIT)
+ Thread.critical = true
+ _count = mon_count
+ set_mon_count(0)
+ set_mon_owner(nil)
+ if mon_waiting_queue.empty?
+ t = mon_entering_queue.shift
+ else
+ t = mon_waiting_queue.shift
+ end
+ t.wakeup if t
+ Thread.critical = false
+MON_EXIT
+
+ Thread.critical = true
+ @waiters.push(Thread.current)
+ Thread.stop
+
+ @monitor.instance_eval(<<MON_ENTER)
+ Thread.critical = true
+ while mon_owner != nil && mon_owner != Thread.current
+ mon_waiting_queue.push(Thread.current)
+ Thread.stop
+ Thread.critical = true
+ end
+ set_mon_owner(Thread.current)
+ set_mon_count(_count)
+ Thread.critical = false
+MON_ENTER
+ end
+
+ def wait_while
+ while yield
+ wait
+ end
+ end
+
+ def wait_until
+ until yield
+ wait
+ end
+ end
+
+ def signal
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ t = @waiters.shift
+ t.wakeup if t
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def broadcast
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ for t in @waiters
+ t.wakeup
+ end
+ @waiters.clear
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def count_waiters
+ return @waiters.length
+ end
+ end
+
+ def new_cond
+ return ConditionVariable.new(self)
+ end
+end
+
+class Monitor
+ include MonitorMixin
+ alias try_enter try_mon_enter
+ alias enter mon_enter
+ alias exit mon_exit
+ alias owner mon_owner
+end
+
+## monitor.rb ends here
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
index 823888e72f..4b8d64438e 100644
--- a/lib/mutex_m.rb
+++ b/lib/mutex_m.rb
@@ -1,8 +1,8 @@
#
# mutex_m.rb -
# $Release Version: 2.0$
-# $Revision: 1.2 $
-# $Date: 1997/07/25 02:43:21 $
+# $Revision: 1.7 $
+# $Date: 1998/02/27 04:28:57 $
# Original from mutex.rb
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
@@ -18,21 +18,50 @@
require "finalize"
module Mutex_m
- def Mutex_m.extend_object(obj)
+ def Mutex_m.extendable_module(obj)
if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj
raise TypeError, "Mutex_m can't extend to this class(#{obj.type})"
else
begin
- eval "class << obj
- @mu_locked
- end"
- obj.extend(For_primitive_object)
+ obj.instance_eval "@mu_locked"
+ For_general_object
rescue TypeError
- obj.extend(For_general_object)
+ For_primitive_object
end
end
end
+ def Mutex_m.includable_module(cl)
+ begin
+ dummy = cl.new
+ Mutex_m.extendable_module(dummy)
+ rescue NameError
+ # new¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤»þ¤Ï, DATA¤È¤ß¤Ê¤¹.
+ For_primitive_object
+ end
+ end
+
+ def Mutex_m.extend_class(cl)
+ return super if cl.instance_of?(Module)
+
+ # ¥â¥¸¥å¡¼¥ë¤Î»þ¤Ï²¿¤â¤·¤Ê¤¤. ¥¯¥é¥¹¤Î¾ì¹ç, ŬÀڤʥ⥸¥å¡¼¥ë¤Î·èÄê
+ # ¤Èalias¤ò¹Ô¤¦.
+ real = includable_module(cl)
+ cl.module_eval %q{
+ include real
+
+ alias locked? mu_locked?
+ alias lock mu_lock
+ alias unlock mu_unlock
+ alias try_lock mu_try_lock
+ alias synchronize mu_synchronize
+ }
+ end
+
+ def Mutex_m.extend_object(obj)
+ obj.extend(Mutex_m.extendable_module(obj))
+ end
+
def mu_extended
unless (defined? locked? and
defined? lock and
@@ -40,7 +69,7 @@ module Mutex_m
defined? try_lock and
defined? synchronize)
eval "class << self
- alias locked mu_locked?
+ alias locked? mu_locked?
alias lock mu_lock
alias unlock mu_unlock
alias try_lock mu_try_lock
@@ -49,6 +78,7 @@ module Mutex_m
end
end
+ # locking
def mu_synchronize
begin
mu_lock
@@ -58,6 +88,7 @@ module Mutex_m
end
end
+ # internal class
module For_general_object
include Mutex_m
@@ -118,10 +149,16 @@ module Mutex_m
def For_primitive_object.extend_object(obj)
super
+
obj.mu_extended
Finalizer.add(obj, For_primitive_object, :mu_finalize)
end
+ def mu_extended
+ super
+ initialize
+ end
+
def For_primitive_object.mu_finalize(id)
Thread.critical = TRUE
if wait = Mu_Locked.delete(id)
@@ -146,7 +183,7 @@ module Mutex_m
ret = FALSE
else
Mu_Locked[self.id] = []
- Finalizer.set(self, For_primitive_object, :mu_delete_Locked)
+ Finalizer.add(self, For_primitive_object, :mu_finalize)
ret = TRUE
end
Thread.critical = FALSE
@@ -159,7 +196,7 @@ module Mutex_m
Thread.stop
end
Mu_Locked[self.id] = []
- Finalizer.add(self, For_primitive_object, :mu_delete_Locked)
+ Finalizer.add(self, For_primitive_object, :mu_finalize)
Thread.critical = FALSE
self
end
@@ -180,4 +217,3 @@ module Mutex_m
end
end
-
diff --git a/lib/observer.rb b/lib/observer.rb
index b802dac633..5928367a7d 100644
--- a/lib/observer.rb
+++ b/lib/observer.rb
@@ -30,9 +30,11 @@ module Observable
@observer_state
end
def notify_observers(*arg)
- if @observer_peers and @observer_state
- for i in @observer_peers
- i.update(*arg)
+ if @observer_state
+ if @observer_peers
+ for i in @observer_peers
+ i.update(*arg)
+ end
end
@observer_state = FALSE
end
diff --git a/lib/open3.rb b/lib/open3.rb
new file mode 100644
index 0000000000..e8ba2783da
--- /dev/null
+++ b/lib/open3.rb
@@ -0,0 +1,55 @@
+# Usage:
+# require "open3"
+#
+# in, out, err = Open3.popen3('nroff -man')
+# or
+# include Open3
+# in, out, err = popen3('nroff -man')
+#
+
+module Open3
+ #[stdin, stdout, stderr] = popen3(command);
+ def popen3(cmd)
+ pw = pipe # pipe[0] for read, pipe[1] for write
+ pr = pipe
+ pe = pipe
+
+ pid = fork
+ if pid == nil then # child
+ pw[1].close
+ STDIN.reopen(pw[0])
+ pw[0].close
+
+ pr[0].close
+ STDOUT.reopen(pr[1])
+ pr[1].close
+
+ pe[0].close
+ STDERR.reopen(pe[1])
+ pe[1].close
+
+ exec(cmd)
+ exit
+ else
+ pw[0].close
+ pr[1].close
+ pe[1].close
+ pi = [ pw[1], pr[0], pe[0] ]
+ end
+ end
+ module_function :popen3
+end
+
+if $0 == __FILE__
+ a = Open3.popen3("nroff -man")
+ Thread.start do
+ while gets
+ a[0].print $_
+ end
+ a[0].close
+ end
+ while a[1].gets
+ print ":", $_
+ end
+end
+
diff --git a/lib/parsearg.rb b/lib/parsearg.rb
index a0ef90f018..b9f41d5e5f 100644
--- a/lib/parsearg.rb
+++ b/lib/parsearg.rb
@@ -1,4 +1,3 @@
-#!/usr/local/bin/ruby
#
# parsearg.rb - parse arguments
# $Release Version: $
@@ -11,9 +10,9 @@
#
#
-$RCS_ID="$Header$"
+$RCS_ID=%q$Header$
-load("getopts.rb")
+require "getopts"
def printUsageAndExit()
if $USAGE
diff --git a/lib/parsedate.rb b/lib/parsedate.rb
index 1c1dda76bc..68550c6505 100644
--- a/lib/parsedate.rb
+++ b/lib/parsedate.rb
@@ -4,39 +4,68 @@ module ParseDate
'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 }
MONTHPAT = MONTHS.keys.join('|')
- DAYPAT = 'mon|tue|wed|thu|fri|sat|sun'
+ DAYS = {
+ 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
+ 'thu' => 4, 'fri' => 5, 'sat' => 6 }
+ DAYPAT = DAYS.keys.join('|')
def parsedate(date)
- if date.sub!(/(#{DAYPAT})/i, ' ')
- dayofweek = $1
+ # part of ISO 8601
+ # yyyy-mm-dd | yyyy-mm | yyyy
+ # date hh:mm:ss | date Thh:mm:ss
+ if date =~ /^(\d\d\d\d)-?(?:(\d\d)-?(\d\d)?)? *T?(?:(\d\d):?(\d\d):?(\d\d)?)?$/
+ return $1.to_i,
+ if $2 then $2.to_i else 1 end,
+ if $3 then $3.to_i else 1 end,
+ if $4 then $4.to_i end,
+ if $5 then $5.to_i end,
+ if $6 then $6.to_i end,
+ nil,
+ nil
end
- if date.sub!(/\s+(\d+:\d+(:\d+)?)/, ' ')
- time = $1
+ date = date.dup
+ if date.sub!(/(#{DAYPAT})[a-z]*,?/i, ' ')
+ wday = DAYS[$1.downcase]
end
- if date =~ /19(\d\d)/
- year = Integer($1)
+ if date.sub!(/(\d+):(\d+)(?::(\d+))?\s*(am|pm)?\s*(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4})?|[-+]\d{4}))?/i, ' ')
+ hour = $1.to_i
+ min = $2.to_i
+ if $3
+ sec = $3.to_i
+ end
+ if $4 == 'pm'
+ hour += 12
+ end
+ if $5
+ zone = $5
+ end
end
- if date.sub!(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ')
- dayofmonth = $1.to_i
- monthname = $2
- elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ')
- monthname = $1
- dayofmonth = $2.to_i
- elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ')
- monthname = $1
- dayofmonth = $2.to_i
- elsif date.sub!(/\s*(\d\d?)\/(\d\d?)/, ' ')
- month = $1
- dayofmonth = $2.to_i
+ if date.sub!(/(\d+)\S*\s+(#{MONTHPAT})\S*(?:\s+(\d+))?/i, ' ')
+ mday = $1.to_i
+ mon = MONTHS[$2.downcase]
+ if $3
+ year = $3.to_i
+ end
+ elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*\s*,?(?:\s+(\d+))?/i, ' ')
+ mon = MONTHS[$1.downcase]
+ mday = $2.to_i
+ if $3
+ year = $3.to_i
+ end
+ elsif date.sub!(/(\d+)\/(\d+)(?:\/(\d+))/, ' ')
+ mon = $1.to_i
+ mday = $2.to_i
+ if $3
+ year = $3.to_i
+ end
end
- if monthname
- month = MONTHS[monthname.downcase]
- end
- if ! year && date =~ /\d\d/
- year = Integer($&)
- end
- return year, month, dayofmonth
+ return year, mon, mday, hour, min, sec, zone, wday
end
module_function :parsedate
end
+
+if __FILE__ == $0
+ p Time.now.asctime
+ p ParseDate.parsedate(Time.now.asctime)
+end
diff --git a/lib/ping.rb b/lib/ping.rb
index d742a50f99..065b1d2303 100644
--- a/lib/ping.rb
+++ b/lib/ping.rb
@@ -26,6 +26,10 @@
#
# The timeout in seconds. If not specified it will default to 5 seconds.
#
+# : service
+#
+# The service port to connect. The default is "echo".
+#
#= WARNING
#
# pingecho() uses user-level thread to implement the timeout, so it may block
@@ -33,23 +37,26 @@
#
#=end
+require 'timeout'
+
module Ping
require "socket"
- def pingecho(host, timeout=5)
+ def pingecho(host, timeout=5, service="echo")
begin
- x = Thread.current
- y = Thread.start {
- sleep timeout
- x.raise RuntimeError if x.status
- }
- s = TCPsocket.new(host, "echo")
- s.close
- return TRUE
+ timeout(timeout) do
+ s = TCPsocket.new(host, service)
+ s.close
+ end
rescue
- return FALSE;
- ensure
- Thread.kill y if y.status
+ return false
end
+ return true
end
- module_function "pingecho"
+ module_function :pingecho
+end
+
+if $0 == __FILE__
+ host = ARGV[0]
+ host ||= "localhost"
+ printf("%s alive? - %s\n", host, Ping::pingecho(host, 5))
end
diff --git a/lib/profile.rb b/lib/profile.rb
new file mode 100644
index 0000000000..3abcc37662
--- /dev/null
+++ b/lib/profile.rb
@@ -0,0 +1,53 @@
+
+module Profiler__
+ Start = Float(Time.times[0])
+ top = "toplevel".intern
+ Stack = [[0, 0, top]]
+ MAP = {top => [1, 0, 0, "#toplevel"]}
+
+ p = proc{|event, file, line, id, binding, klass|
+ case event
+ when "call", "c-call"
+ now = Float(Time.times[0])
+ Stack.push [now, 0.0, id]
+ when "return", "c-return"
+ now = Float(Time.times[0])
+ tick = Stack.pop
+ data = MAP[id]
+ unless data
+ name = klass.to_s
+ if klass.kind_of? Class
+ name += "#"
+ else
+ name += "."
+ end
+ data = [0, 0, 0, name+id.id2name]
+ MAP[id] = data
+ end
+ data[0] += 1
+ cost = now - tick[0]
+ data[1] += cost
+ data[2] += cost - tick[1]
+ Stack[-1][1] += cost
+ end
+ }
+ END {
+ set_trace_func nil
+ total = Float(Time.times[0]) - Start
+ MAP[:toplevel][1] = total
+# f = open("./rmon.out", "w")
+ f = STDERR
+ data = MAP.values.sort!{|a,b| b[2] <=> a[2]}
+ sum = 0
+ f.printf " %% cumulative self self total\n"
+ f.printf " time seconds seconds calls ms/call ms/call name\n"
+ for d in data
+ sum += d[2]
+ f.printf "%6.2f %8.2f %8.2f %8d ", d[2]/total*100, sum, d[2], d[0]
+ f.printf "%8.2f %8.2f %s\n", d[2]*1000/d[0], d[1]*1000/d[0], d[3]
+ end
+ p total
+ f.close
+ }
+ set_trace_func p
+end
diff --git a/lib/pstore.rb b/lib/pstore.rb
index 86f086d226..2aa9864b58 100644
--- a/lib/pstore.rb
+++ b/lib/pstore.rb
@@ -1,5 +1,4 @@
-#!/usr/local/bin/ruby
-
+#
# How to use:
#
# db = PStore.new("/tmp/foo")
@@ -16,7 +15,8 @@
require "marshal"
class PStore
- Exception(:Error)
+ class Error < StandardError
+ end
def initialize(file)
dir = File::dirname(file)
@@ -89,33 +89,46 @@ class PStore
catch(:pstore_abort_transaction) do
value = yield(self)
end
+ rescue Exception
+ @abort = true
+ raise
ensure
unless @abort
- File::rename @filename, @filename+"~"
+ begin
+ File::rename @filename, @filename+"~"
+ rescue Errno::ENOENT
+ no_orig = true
+ end
begin
File::open(@filename, "w") do |file|
Marshal::dump(@table, file)
end
rescue
- File::rename @filename+"~", @filename
+ File::rename @filename+"~", @filename unless no_orig
end
end
@abort = false
end
ensure
+ @table = nil
@transaction = false
end
value
end
end
-db = PStore.new("/tmp/foo")
-db.transaction do
- p db.roots
- ary = db["root"] = [1,2,3,4]
- ary[0] = [1,1.5]
-end
+if __FILE__ == $0
+ db = PStore.new("/tmp/foo")
+ db.transaction do
+ p db.roots
+ ary = db["root"] = [1,2,3,4]
+ ary[1] = [1,1.5]
+ end
-db.transaction do
- p db["root"]
+ 1000.times do
+ db.transaction do
+ db["root"][0] += 1
+ p db["root"][0]
+ end
+ end
end
diff --git a/lib/rational.rb b/lib/rational.rb
index d4112c2956..1282f56410 100644
--- a/lib/rational.rb
+++ b/lib/rational.rb
@@ -1,8 +1,8 @@
#
# rational.rb -
# $Release Version: 0.5 $
-# $Revision: 1.1 $
-# $Date: 1996/11/11 04:25:14 $
+# $Revision: 1.3 $
+# $Date: 1998/03/11 14:09:03 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# --
@@ -44,7 +44,11 @@ def Rational(a, b = 1)
end
class Rational < Numeric
+ @RCS_ID='-$Id: rational.rb,v 1.3 1998/03/11 14:09:03 keiju Exp keiju $-'
+
def Rational.reduce(num, den = 1)
+ raise ZeroDivisionError, "denometor is 0" if den == 0
+
if den < 0
num = -num
den = -den
@@ -128,6 +132,7 @@ class Rational < Numeric
den = @denominator * a.numerator
Rational(num, den)
elsif a.kind_of?(Integer)
+ raise ZeroDivisionError, "devided by 0" if a == 0
self / Rational.new!(a, 1)
elsif a.kind_of?(Float)
Float(self) / a
diff --git a/lib/readbytes.rb b/lib/readbytes.rb
new file mode 100644
index 0000000000..d6a3b10afe
--- /dev/null
+++ b/lib/readbytes.rb
@@ -0,0 +1,36 @@
+# readbytes.rb
+#
+# add IO#readbytes, which reads fixed sized data.
+# it guarantees read data size.
+
+class TruncatedDataError<IOError
+ def initialize(mesg, data)
+ @data = data
+ super(mesg)
+ end
+ attr_reader :data
+end
+
+class IO
+ def readbytes(n)
+ str = read(n)
+ if str == nil
+ raise EOFError, "End of file reached"
+ end
+ if str.size < n
+ raise TruncatedDataError.new("data truncated", str)
+ end
+ str
+ end
+end
+
+if __FILE__ == $0
+ begin
+ loop do
+ print STDIN.readbytes(6)
+ end
+ rescue TruncatedDataError
+ p $!.data
+ raise
+ end
+end
diff --git a/lib/shellwords.rb b/lib/shellwords.rb
index 9632f1222a..9154cd84c1 100644
--- a/lib/shellwords.rb
+++ b/lib/shellwords.rb
@@ -18,21 +18,19 @@ module Shellwords
while line != ''
field = ''
while TRUE
- if line.sub! /^"(([^"\\]|\\.)*)"/, '' then
+ if line.sub! /^"(([^"\\]|\\.)*)"/, '' then #"
snippet = $1
snippet.gsub! /\\(.)/, '\1'
- elsif line =~ /^"/ then
- STDOUT.print "Unmatched double quote: $_\n"
- exit
- elsif line.sub! /^'(([^'\\]|\\.)*)'/, '' then
+ elsif line =~ /^"/ then #"
+ raise ArgError, "Unmatched double quote: #{line}"
+ elsif line.sub! /^'(([^'\\]|\\.)*)'/, '' then #'
snippet = $1
snippet.gsub! /\\(.)/, '\1'
- elsif line =~ /^'/ then
- STDOUT.print "Unmatched single quote: $_\n"
- exit
+ elsif line =~ /^'/ then #'
+ raise ArgError, "Unmatched single quote: #{line}"
elsif line.sub! /^\\(.)/, '' then
snippet = $1
- elsif line.sub! /^([^\s\\'"]+)/, '' then
+ elsif line.sub! /^([^\s\\'"]+)/, '' then #'
snippet = $1
else
line.sub! /^\s+/, ''
diff --git a/lib/singleton.rb b/lib/singleton.rb
new file mode 100644
index 0000000000..8167a01aa8
--- /dev/null
+++ b/lib/singleton.rb
@@ -0,0 +1,37 @@
+# Singleton module that ensures only one object to be allocated.
+#
+# Usage:
+# class SomeSingletonClass
+# include Singleton
+# #....
+# end
+# a = SomeSingletonClass.instance
+# b = SomeSingletonClass.instance # a and b are same object
+# p [a,b]
+# a = SomeSingletonClass.new # error (`new' is private)
+
+module Singleton
+ def Singleton.append_features(klass)
+ klass.private_class_method(:new)
+ klass.instance_eval %{
+ def instance
+ unless @__instance__
+ @__instance__ = new
+ end
+ return @__instance__
+ end
+ }
+ end
+end
+
+if __FILE__ == $0
+ class SomeSingletonClass
+ include Singleton
+ #....
+ end
+
+ a = SomeSingletonClass.instance
+ b = SomeSingletonClass.instance # a and b are same object
+ p [a,b]
+ a = SomeSingletonClass.new # error (`new' is private)
+end
diff --git a/lib/sync.rb b/lib/sync.rb
index b5a3fc32b3..9f9706d9ee 100644
--- a/lib/sync.rb
+++ b/lib/sync.rb
@@ -4,6 +4,7 @@
# $Revision$
# $Date$
# by Keiju ISHITSUKA
+# modified by matz
#
# --
# Sync_m, Synchronizer_m
@@ -43,7 +44,7 @@ unless defined? Thread
fail "Thread not available for this ruby interpreter"
end
-require "finalize"
+require "final"
module Sync_m
RCS_ID='-$Header$-'
@@ -54,7 +55,7 @@ module Sync_m
EX = :EX
# Îã³°ÄêµÁ
- class Err < Exception
+ class Err < StandardError
def Err.Fail(*opt)
fail self, sprintf(self::Message, *opt)
end
@@ -296,8 +297,8 @@ module Sync_m
private :sync_try_lock_sub
def sync_synchronize(mode = EX)
+ sync_lock(mode)
begin
- sync_lock(mode)
yield
ensure
sync_unlock
@@ -321,7 +322,11 @@ module Sync_m
def For_primitive_object.extend_object(obj)
super
obj.sync_extended
- Finalizer.add(obj, For_primitive_object, :sync_finalize)
+ # Changed to use `final.rb'.
+ # Finalizer.add(obj, For_primitive_object, :sync_finalize)
+ ObjectSpace.define_finalizer(obj) do |id|
+ For_primitive_object.sync_finalize(id)
+ end
end
def initialize
diff --git a/lib/telnet.rb b/lib/telnet.rb
new file mode 100644
index 0000000000..e3c590c35d
--- /dev/null
+++ b/lib/telnet.rb
@@ -0,0 +1,439 @@
+#
+# telnet.rb
+# ver0.16 1998/10/09
+# Wakou Aoyama <wakou@fsinet.or.jp>
+#
+# ver0.16 1998/10/09
+# preprocess method change for the better
+# add binmode method.
+# change default Binmode
+# TRUE --> FALSE
+#
+# ver0.15 1998/10/04
+# add telnetmode method.
+#
+# ver0.141 1998/09/22
+# change default prompt
+# /[$%#>] $/ --> /[$%#>] \Z/
+#
+# ver0.14 1998/09/01
+# IAC WILL SGA send EOL --> CR+NULL
+# IAC WILL SGA IAC DO BIN send EOL --> CR
+# NONE send EOL --> LF
+# add Dump_log option.
+#
+# ver0.13 1998/08/25
+# add print method.
+#
+# ver0.122 1998/08/05
+# support for HP-UX 10.20 thanks to WATANABE Tetsuya <tetsu@jpn.hp.com>
+# socket.<< --> socket.write
+#
+# ver0.121 1998/07/15
+# string.+= --> string.concat
+#
+# ver0.12 1998/06/01
+# add timeout, waittime.
+#
+# ver0.11 1998/04/21
+# add realtime output.
+#
+# ver0.10 1998/04/13
+# first release.
+#
+# == make new Telnet object
+# host = Telnet.new({"Binmode" => FALSE, default: FALSE
+# "Host" => "localhost", default: "localhost"
+# "Output_log" => "output_log", default: not output
+# "Dump_log" => "dump_log", default: not output
+# "Port" => 23, default: 23
+# "Prompt" => /[$%#>] \Z/, default: /[$%#>] \Z/
+# "Telnetmode" => TRUE, default: TRUE
+# "Timeout" => 10, default: 10
+# "Waittime" => 0}) default: 0
+#
+# if set "Telnetmode" option FALSE. not TELNET command interpretation.
+# "Waittime" is time to confirm "Prompt". There is a possibility that
+# the same character as "Prompt" is included in the data, and, when
+# the network or the host is very heavy, the value is enlarged.
+#
+# == wait for match
+# line = host.waitfor(/match/)
+# line = host.waitfor({"Match" => /match/,
+# "String" => "string",
+# "Timeout" => secs})
+# if set "String" option. Match = Regexp.new(quote(string))
+#
+# realtime output. of cource, set sync=TRUE or flush is necessary.
+# host.waitfor(/match/){|c| print c }
+# host.waitfor({"Match" => /match/,
+# "String" => "string",
+# "Timeout" => secs}){|c| print c}
+#
+# == send string and wait prompt
+# line = host.cmd("string")
+# line = host.cmd({"String" => "string",
+# "Prompt" => /[$%#>] \Z/,
+# "Timeout" => 10})
+#
+# realtime output. of cource, set sync=TRUE or flush is necessary.
+# host.cmd("string"){|c| print c }
+# host.cmd({"String" => "string",
+# "Prompt" => /[$%#>] \Z/,
+# "Timeout" => 10}){|c| print c }
+#
+# == send string
+# host.print("string")
+#
+# == turn telnet command interpretation
+# host.telnetmode # turn on/off
+# host.telnetmode(TRUE) # on
+# host.telnetmode(FALSE) # off
+#
+# == toggle newline translation
+# host.binmode # turn TRUE/FALSE
+# host.binmode(TRUE) # no translate newline
+# host.binmode(FALSE) # translate newline
+#
+# == login
+# host.login("username", "password")
+# host.login({"Name" => "username",
+# "Password" => "password",
+# "Prompt" => /[$%#>] \Z/,
+# "Timeout" => 10})
+#
+# realtime output. of cource, set sync=TRUE or flush is necessary.
+# host.login("username", "password"){|c| print c }
+# host.login({"Name" => "username",
+# "Password" => "password",
+# "Prompt" => /[$%#>] \Z/,
+# "Timeout" => 10}){|c| print c }
+#
+# and Telnet object has socket class methods
+#
+# == sample
+# localhost = Telnet.new({"Host" => "localhost",
+# "Timeout" => 10,
+# "Prompt" => /[$%#>] \Z/})
+# localhost.login("username", "password"){|c| print c }
+# localhost.cmd("command"){|c| print c }
+# localhost.close
+#
+# == sample 2
+# checks a POP server to see if you have mail.
+#
+# pop = Telnet.new({"Host" => "your_destination_host_here",
+# "Port" => 110,
+# "Telnetmode" => FALSE,
+# "Prompt" => /^\+OK/})
+# pop.cmd("user " + "your_username_here"){|c| print c}
+# pop.cmd("pass " + "your_password_here"){|c| print c}
+# pop.cmd("list"){|c| print c}
+
+require "socket"
+require "delegate"
+require "thread"
+
+class TimeOut < Exception
+end
+
+class Telnet < SimpleDelegator
+
+ def timeout(sec)
+ is_timeout = FALSE
+ begin
+ x = Thread.current
+ y = Thread.start {
+ sleep sec
+ if x.alive?
+ #print "timeout!\n"
+ x.raise TimeOut, "timeout"
+ end
+ }
+ begin
+ yield
+ rescue TimeOut
+ is_timeout = TRUE
+ end
+ ensure
+ Thread.kill y if y && y.alive?
+ end
+ is_timeout
+ end
+
+ IAC = 255.chr # interpret as command:
+ DONT = 254.chr # you are not to use option
+ DO = 253.chr # please, you use option
+ WONT = 252.chr # I won't use option
+ WILL = 251.chr # I will use option
+ SB = 250.chr # interpret as subnegotiation
+ GA = 249.chr # you may reverse the line
+ EL = 248.chr # erase the current line
+ EC = 247.chr # erase the current character
+ AYT = 246.chr # are you there
+ AO = 245.chr # abort output--but let prog finish
+ IP = 244.chr # interrupt process--permanently
+ BREAK = 243.chr # break
+ DM = 242.chr # data mark--for connect. cleaning
+ NOP = 241.chr # nop
+ SE = 240.chr # end sub negotiation
+ EOR = 239.chr # end of record (transparent mode)
+ ABORT = 238.chr # Abort process
+ SUSP = 237.chr # Suspend process
+ EOF = 236.chr # End of file
+ SYNCH = 242.chr # for telfunc calls
+
+ OPT_BINARY = 0.chr # Binary Transmission
+ OPT_ECHO = 1.chr # Echo
+ OPT_RCP = 2.chr # Reconnection
+ OPT_SGA = 3.chr # Suppress Go Ahead
+ OPT_NAMS = 4.chr # Approx Message Size Negotiation
+ OPT_STATUS = 5.chr # Status
+ OPT_TM = 6.chr # Timing Mark
+ OPT_RCTE = 7.chr # Remote Controlled Trans and Echo
+ OPT_NAOL = 8.chr # Output Line Width
+ OPT_NAOP = 9.chr # Output Page Size
+ OPT_NAOCRD = 10.chr # Output Carriage-Return Disposition
+ OPT_NAOHTS = 11.chr # Output Horizontal Tab Stops
+ OPT_NAOHTD = 12.chr # Output Horizontal Tab Disposition
+ OPT_NAOFFD = 13.chr # Output Formfeed Disposition
+ OPT_NAOVTS = 14.chr # Output Vertical Tabstops
+ OPT_NAOVTD = 15.chr # Output Vertical Tab Disposition
+ OPT_NAOLFD = 16.chr # Output Linefeed Disposition
+ OPT_XASCII = 17.chr # Extended ASCII
+ OPT_LOGOUT = 18.chr # Logout
+ OPT_BM = 19.chr # Byte Macro
+ OPT_DET = 20.chr # Data Entry Terminal
+ OPT_SUPDUP = 21.chr # SUPDUP
+ OPT_SUPDUPOUTPUT = 22.chr # SUPDUP Output
+ OPT_SNDLOC = 23.chr # Send Location
+ OPT_TTYPE = 24.chr # Terminal Type
+ OPT_EOR = 25.chr # End of Record
+ OPT_TUID = 26.chr # TACACS User Identification
+ OPT_OUTMRK = 27.chr # Output Marking
+ OPT_TTYLOC = 28.chr # Terminal Location Number
+ OPT_3270REGIME = 29.chr # Telnet 3270 Regime
+ OPT_X3PAD = 30.chr # X.3 PAD
+ OPT_NAWS = 31.chr # Negotiate About Window Size
+ OPT_TSPEED = 32.chr # Terminal Speed
+ OPT_LFLOW = 33.chr # Remote Flow Control
+ OPT_LINEMODE = 34.chr # Linemode
+ OPT_XDISPLOC = 35.chr # X Display Location
+ OPT_OLD_ENVIRON = 36.chr # Environment Option
+ OPT_AUTHENTICATION = 37.chr # Authentication Option
+ OPT_ENCRYPT = 38.chr # Encryption Option
+ OPT_NEW_ENVIRON = 39.chr # New Environment Option
+ OPT_EXOPL = 255.chr # Extended-Options-List
+
+ NULL = "\000"
+ CR = "\015"
+ LF = "\012"
+ EOL = CR + LF
+
+ def initialize(options)
+ @options = options
+ @options["Binmode"] = FALSE if not @options.include?("Binmode")
+ @options["Host"] = "localhost" if not @options.include?("Host")
+ @options["Port"] = 23 if not @options.include?("Port")
+ @options["Prompt"] = /[$%#>] \Z/ if not @options.include?("Prompt")
+ @options["Telnetmode"] = TRUE if not @options.include?("Telnetmode")
+ @options["Timeout"] = 10 if not @options.include?("Timeout")
+ @options["Waittime"] = 0 if not @options.include?("Waittime")
+
+ @telnet_option = { "SGA" => FALSE, "BINARY" => FALSE }
+
+ if @options.include?("Output_log")
+ @log = File.open(@options["Output_log"], 'a+')
+ @log.sync = TRUE
+ @log.binmode
+ end
+
+ if @options.include?("Dump_log")
+ @dumplog = File.open(@options["Dump_log"], 'a+')
+ @dumplog.sync = TRUE
+ @dumplog.binmode
+ end
+
+ message = "Trying " + @options["Host"] + "...\n"
+ STDOUT.write(message)
+ @log.write(message) if @options.include?("Output_log")
+ @dumplog.write(message) if @options.include?("Dump_log")
+
+ is_timeout = timeout(@options["Timeout"]){
+ begin
+ @sock = TCPsocket.open(@options["Host"], @options["Port"])
+ rescue
+ @log.write($! + "\n") if @options.include?("Output_log")
+ @dumplog.write($! + "\n") if @options.include?("Dump_log")
+ raise
+ end
+ }
+ raise TimeOut, "timed-out; opening of the host" if is_timeout
+ @sock.sync = TRUE
+ @sock.binmode
+
+ message = "Connected to " + @options["Host"] + ".\n"
+ STDOUT.write(message)
+ @log.write(message) if @options.include?("Output_log")
+ @dumplog.write(message) if @options.include?("Dump_log")
+
+ super(@sock)
+ end
+
+ def telnetmode(mode = 'turn')
+ if 'turn' == mode
+ @options["Telnetmode"] = @options["Telnetmode"] ? FALSE : TRUE
+ else
+ @options["Telnetmode"] = mode ? TRUE : FALSE
+ end
+ end
+
+ def binmode(mode = 'turn')
+ if 'turn' == mode
+ @options["Binmode"] = @options["Binmode"] ? FALSE : TRUE
+ else
+ @options["Binmode"] = mode ? TRUE : FALSE
+ end
+ end
+
+ def preprocess(str)
+
+ if not @options["Binmode"]
+ str.gsub!(/#{CR}#{NULL}/no, CR) # combine CR+NULL into CR
+ str.gsub!(/#{EOL}/no, "\n") # combine EOL into "\n"
+ end
+
+ # respond to "IAC DO x"
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{DO}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ if OPT_BINARY == $1
+ @telnet_option["BINARY"] = TRUE
+ @sock.write(IAC + WILL + OPT_BINARY)
+ else
+ @sock.write(IAC + WONT + $1)
+ end
+ ''
+ }
+
+ # respond to "IAC DON'T x" with "IAC WON'T x"
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{DONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ @sock.write(IAC + WONT + $1)
+ ''
+ }
+
+ # respond to "IAC WILL x"
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{WILL}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ if OPT_SGA == $1
+ @telnet_option["SGA"] = TRUE
+ @sock.write(IAC + DO + OPT_SGA)
+ end
+ ''
+ }
+
+ # ignore "IAC WON'T x"
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{WONT}[#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]/no, '')
+
+ # respond to "IAC AYT" (are you there)
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{AYT}/no){
+ @sock.write("nobody here but us pigeons" + EOL)
+ ''
+ }
+
+ str.gsub(/#{IAC}#{IAC}/no, IAC) # handle escaped IAC characters
+ end
+
+ def waitfor(options)
+ timeout = @options["Timeout"]
+ waittime = @options["Waittime"]
+
+ if options.kind_of?(Hash)
+ prompt = options["Prompt"] if options.include?("Prompt")
+ timeout = options["Timeout"] if options.include?("Timeout")
+ waittime = options["Waittime"] if options.include?("Waittime")
+ prompt = Regexp.new( Regexp.quote(options["String"]) ) if
+ options.include?("String")
+ else
+ prompt = options
+ end
+
+ line = ''
+ until(not select([@sock], nil, nil, waittime) and prompt === line)
+ raise TimeOut, "timed-out; wait for the next data" if
+ not select([@sock], nil, nil, timeout)
+ buf = ''
+ begin
+ buf = @sock.sysread(1024 * 1024)
+ @dumplog.print(buf) if @options.include?("Dump_log")
+ buf = preprocess(buf) if @options["Telnetmode"]
+ rescue EOFError # End of file reached
+ break
+ ensure
+ @log.print(buf) if @options.include?("Output_log")
+ yield buf if iterator?
+ line.concat(buf)
+ end
+ end
+ line
+ end
+
+ def print(string)
+ string.gsub!(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
+ if @options["Binmode"]
+ @sock.write(string)
+ else
+ if @telnet_option["BINARY"] and @telnet_option["SGA"]
+ # IAC WILL SGA IAC DO BIN send EOL --> CR
+ @sock.write(string.gsub(/\n/, CR) + CR)
+ elsif @telnet_option["SGA"]
+ # IAC WILL SGA send EOL --> CR+NULL
+ @sock.write(string.gsub(/\n/, CR + NULL) + CR + NULL)
+ else
+ # NONE send EOL --> LF
+ @sock.write(string.gsub(/\n/, LF) + LF)
+ end
+ end
+ end
+
+ def cmd(options)
+ match = @options["Prompt"]
+ timeout = @options["Timeout"]
+
+ if options.kind_of?(Hash)
+ string = options["String"]
+ match = options["Match"] if options.include?("Match")
+ timeout = options["Timeout"] if options.include?("Timeout")
+ else
+ string = options
+ end
+
+ select(nil, [@sock])
+ print(string)
+ if iterator?
+ waitfor({"Prompt" => match, "Timeout" => timeout}){|c| yield c }
+ else
+ waitfor({"Prompt" => match, "Timeout" => timeout})
+ end
+ end
+
+ def login(options, password = '')
+ if options.kind_of?(Hash)
+ username = options["Name"]
+ password = options["Password"]
+ else
+ username = options
+ end
+
+ if iterator?
+ line = waitfor(/login[: ]*\Z/){|c| yield c }
+ line.concat( cmd({"String" => username,
+ "Match" => /Password[: ]*\Z/}){|c| yield c } )
+ line.concat( cmd(password){|c| yield c } )
+ else
+ line = waitfor(/login[: ]*\Z/)
+ line.concat( cmd({"String" => username,
+ "Match" => /Password[: ]*\Z/}) )
+ line.concat( cmd(password) )
+ end
+ line
+ end
+
+end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
new file mode 100644
index 0000000000..bf51ac2788
--- /dev/null
+++ b/lib/tempfile.rb
@@ -0,0 +1,91 @@
+#
+# $Id$
+#
+# The class for temporary files.
+# o creates a temporary file, which name is "basename.pid.n" with mode "w+".
+# o Tempfile objects can be used like IO object.
+# o with tmpfile.close(true) created temporary files are removed.
+# o created files are also removed on script termination.
+# o with Tempfile#open, you can reopen the temporary file.
+# o file mode of the temporary files are 0600.
+
+require 'delegate'
+require 'final'
+
+class Tempfile < SimpleDelegator
+ Max_try = 10
+
+ def Tempfile.callback(path)
+ lambda{
+ print "removing ", path, "..." if $DEBUG
+ if File.exist?(path)
+ File.unlink(path)
+ end
+ if File.exist?(path + '.lock')
+ Dir.rmdir(path + '.lock')
+ end
+ print "done\n" if $DEBUG
+ }
+ end
+
+ def initialize(basename, tmpdir = '/tmp')
+ umask = File.umask(0177)
+ tmpname = lock = nil
+ begin
+ n = 0
+ while true
+ begin
+ tmpname = sprintf('%s/%s.%d.%d', tmpdir, basename, $$, n)
+ lock = tmpname + '.lock'
+ unless File.exist?(lock)
+ Dir.mkdir(lock)
+ break
+ end
+ rescue
+ raise "cannot generate tmpfile `%s'" % tmpname if n >= Max_try
+ #sleep(1)
+ end
+ n += 1
+ end
+
+ @clean_files = Tempfile.callback(tmpname)
+ ObjectSpace.define_finalizer(self, @clean_files)
+
+ @tmpfile = File.open(tmpname, 'w+')
+ @tmpname = tmpname
+ super(@tmpfile)
+ Dir.rmdir(lock)
+ ensure
+ File.umask(umask)
+ end
+ end
+
+ def Tempfile.open(*args)
+ Tempfile.new(*args)
+ end
+
+ def open
+ @tmpfile.close if @tmpfile
+ @tmpfile = File.open(@tmpname, 'r+')
+ __setobj__(@tmpfile)
+ end
+
+ def close(real=false)
+ @tmpfile.close if @tmpfile
+ @tmpfile = nil
+ if real
+ @clean_files.call
+ ObjectSpace.undefine_finalizer(self)
+ end
+ end
+end
+
+if __FILE__ == $0
+# $DEBUG = true
+ f = Tempfile.new("foo")
+ f.print("foo\n")
+ f.close
+ f.open
+ p f.gets # => "foo\n"
+ f.close(true)
+end
diff --git a/lib/thread.rb b/lib/thread.rb
index 4f294cc9a3..ec75144374 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -9,14 +9,20 @@ unless defined? Thread
end
unless defined? ThreadError
- class ThreadError<Exception
+ class ThreadError<StandardError
end
end
+if $DEBUG
+ Thread.abort_on_exception = true
+end
+
class Mutex
def initialize
@waiting = []
- @locked = FALSE;
+ @locked = false;
+ @waiting.taint # enable tainted comunication
+ self.taint
end
def locked?
@@ -24,42 +30,39 @@ class Mutex
end
def try_lock
- result = FALSE
- Thread.critical = TRUE
+ result = false
+ Thread.critical = true
unless @locked
- @locked = TRUE
- result = TRUE
+ @locked = true
+ result = true
end
- Thread.critical = FALSE
+ Thread.critical = false
result
end
def lock
- while (Thread.critical = TRUE; @locked)
+ while (Thread.critical = true; @locked)
@waiting.push Thread.current
Thread.stop
end
- @locked = TRUE
- Thread.critical = FALSE
+ @locked = true
+ Thread.critical = false
self
end
def unlock
return unless @locked
Thread.critical = TRUE
- wait = @waiting
- @waiting = []
+ t = @waiting.shift
@locked = FALSE
Thread.critical = FALSE
- for w in wait
- w.run
- end
+ t.run if t
self
end
def synchronize
+ lock
begin
- lock
yield
ensure
unlock
@@ -67,37 +70,74 @@ class Mutex
end
end
+class ConditionVariable
+ def initialize
+ @waiters = []
+ @waiters_mutex = Mutex.new
+ @waiters.taint # enable tainted comunication
+ self.taint
+ end
+
+ def wait(mutex)
+ mutex.unlock
+ @waiters_mutex.synchronize {
+ @waiters.push(Thread.current)
+ }
+ Thread.stop
+ mutex.lock
+ end
+
+ def signal
+ @waiters_mutex.synchronize {
+ t = @waiters.shift
+ t.run if t
+ }
+ end
+
+ def broadcast
+ @waiters_mutex.synchronize {
+ for t in @waiters
+ t.run
+ end
+ @waiters.clear
+ }
+ end
+end
+
class Queue
def initialize
@que = []
@waiting = []
+ @que.taint # enable tainted comunication
+ @waiting.taint
+ self.taint
end
def push(obj)
- Thread.critical = TRUE
+ Thread.critical = true
@que.push obj
t = @waiting.shift
- Thread.critical = FALSE
+ Thread.critical = false
t.run if t
end
- def pop non_block=FALSE
- item = nil
- until item
- Thread.critical = TRUE
- if @que.length == 0
- if non_block
- Thread.critical = FALSE
- raise ThreadError, "queue empty"
+ def pop non_block=false
+ Thread.critical = true
+ begin
+ loop do
+ if @que.length == 0
+ if non_block
+ raise ThreadError, "queue empty"
+ end
+ @waiting.push Thread.current
+ Thread.stop
+ else
+ return @que.shift
end
- @waiting.push Thread.current
- Thread.stop
- else
- item = @que.shift
end
+ ensure
+ Thread.critical = false
end
- Thread.critical = FALSE
- item
end
def empty?
@@ -107,4 +147,63 @@ class Queue
def length
@que.length
end
+ alias size length
+
+
+ def num_waiting
+ @waiting.size
+ end
+end
+
+class SizedQueue<Queue
+ def initialize(max)
+ @max = max
+ @queue_wait = []
+ @queue_wait.taint # enable tainted comunication
+ super()
+ end
+
+ def max
+ @max
+ end
+
+ def max=(max)
+ Thread.critical = TRUE
+ if @max >= max
+ @max = max
+ Thread.critical = FALSE
+ else
+ diff = max - @max
+ @max = max
+ Thread.critical = FALSE
+ diff.times do
+ t = @queue_wait.shift
+ t.run if t
+ end
+ end
+ max
+ end
+
+ def push(obj)
+ Thread.critical = true
+ while @que.length >= @max
+ @queue_wait.push Thread.current
+ Thread.stop
+ Thread.critical = true
+ end
+ super
+ end
+
+ def pop(*args)
+ Thread.critical = true
+ if @que.length < @max
+ t = @queue_wait.shift
+ t.run if t
+ end
+ super
+ end
+
+ def num_waiting
+ @waiting.size + @queue_wait.size
+ end
end
diff --git a/lib/thwait.rb b/lib/thwait.rb
index c638335f5d..958163edef 100644
--- a/lib/thwait.rb
+++ b/lib/thwait.rb
@@ -1,34 +1,53 @@
#
-# thwait.rb -
-# $Release Version: $
-# $Revision: 1.1 $
-# $Date: 1997/08/18 03:13:14 $
-# by Keiju ISHITSUKA(Nippon Rational Inc.)
+# thwait.rb - thread synchronization class
+# $Release Version: 0.9 $
+# $Revision: 1.3 $
+# $Date: 1998/06/26 03:19:34 $
+# by Keiju ISHITSUKA(Nihpon Rational Software Co.,Ltd.)
#
# --
+# feature:
+# provides synchronization for multiple threads.
#
-#
+# class methods:
+# * ThreadsWait.all_waits(thread1,...)
+# waits until all of specified threads are terminated.
+# if a block is supplied for the method, evaluates it for
+# each thread termination.
+# * th = ThreadsWait.new(thread1,...)
+# creates synchronization object, specifying thread(s) to wait.
+#
+# methods:
+# * th.threads
+# list threads to be synchronized
+# * th.empty?
+# is there any thread to be synchronized.
+# * th.finished?
+# is there already terminated thread.
+# * th.join(thread1,...)
+# wait for specified thread(s).
+# * th.join_nowait(threa1,...)
+# specifies thread(s) to wait. non-blocking.
+# * th.next_wait
+# waits until any of specified threads is terminated.
+# * th.all_waits
+# waits until all of specified threads are terminated.
+# if a block is supplied for the method, evaluates it for
+# each thread termination.
#
require "thread.rb"
require "e2mmap.rb"
class ThreadsWait
- RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/thwait.rb,v 1.1 1997/08/18 03:13:14 keiju Exp keiju $-'
+ RCS_ID='-$Id: thwait.rb,v 1.3 1998/06/26 03:19:34 keiju Exp keiju $-'
Exception2MessageMapper.extend_to(binding)
- def_exception("ErrWaitThreadsNothing", "Wait threads nothing.")
- def_exception("FinshedThreadsNothing", "finished thread nothing.")
+ def_exception("ErrNoWaitingThread", "No threads for waiting.")
+ def_exception("ErrNoFinshedThread", "No finished threads.")
- # class mthods
- # all_waits
-
- #
- # »ØÄꤷ¤¿¥¹¥ì¥Ã¥É¤¬Á´¤Æ½ªÎ»¤¹¤ë¤Þ¤ÇÂÔ¤Ä. ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤ë¤È
- # »ØÄꤷ¤¿¥¹¥ì¥Ã¥É¤¬½ªÎ»¤¹¤ë¤È¥¤¥Æ¥ì¡¼¥¿¤ò¸Æ¤Ó½Ð¤¹.
- #
def ThreadsWait.all_waits(*threads)
- tw = ThreadsWait.new(th1, th2, th3, th4, th5)
+ tw = ThreadsWait.new(*threads)
if iterator?
tw.all_waits do
|th|
@@ -39,12 +58,6 @@ class ThreadsWait
end
end
- # initialize and terminating:
- # initialize
-
- #
- # ½é´ü²½. ÂԤĥ¹¥ì¥Ã¥É¤Î»ØÄ꤬¤Ç¤­¤ë.
- #
def initialize(*threads)
@threads = []
@wait_queue = Queue.new
@@ -52,24 +65,19 @@ class ThreadsWait
end
# accessing
- # threads
-
- # ÂÔ¤Á¥¹¥ì¥Ã¥É¤Î°ìÍ÷¤òÊÖ¤¹.
+ # threads - list threads to be synchronized
attr :threads
# testing
# empty?
# finished?
- #
-
- #
- # ÂÔ¤Á¥¹¥ì¥Ã¥É¤¬Â¸ºß¤¹¤ë¤«¤É¤¦¤«¤òÊÖ¤¹.
+
+ # is there any thread to be synchronized.
def empty?
@threads.empty?
end
- #
- # ¤¹¤Ç¤Ë½ªÎ»¤·¤¿¥¹¥ì¥Ã¥É¤¬¤¢¤ë¤«¤É¤¦¤«ÊÖ¤¹
+ # is there already terminated thread.
def finished?
!@wait_queue.empty?
end
@@ -80,45 +88,40 @@ class ThreadsWait
# next_wait
# all_wait
- #
- # ÂԤäƤ¤¤ë¥¹¥ì¥Ã¥É¤òÄɲä·ÂÔ¤Á¤Ë¤Ï¤¤¤ë.
- #
+ # adds thread(s) to join, waits for any of waiting threads to terminate.
def join(*threads)
join_nowait(*threads)
next_wait
end
- #
- # ÂԤäƤ¤¤ë¥¹¥ì¥Ã¥É¤òÄɲ乤ë. ÂÔ¤Á¤Ë¤ÏÆþ¤é¤Ê¤¤.
- #
+ # adds thread(s) to join, no wait.
def join_nowait(*threads)
@threads.concat threads
for th in threads
Thread.start do
- th = Thread.join(th)
+ th = th.join
@wait_queue.push th
end
end
end
- #
- # ¼¡¤ÎÂÔ¤Á¤Ë¤Ï¤¤¤ë.
- # ÂԤĤ٤­¥¹¥ì¥Ã¥É¤¬¤Ê¤±¤ì¤Ð, Îã³°ErrWaitThreadsNothing ¤òÊÖ¤¹.
- # nonnlock¤¬¿¿¤Î»þ¤Ë¤Ï, nonblocking¤ÇÄ´¤Ù¤ë. ¸ºß¤·¤Ê¤±¤ì¤Ð, Îã³°
- # FinishedThreadNothing¤òÊÖ¤¹.
- #
+ # waits for any of waiting threads to terminate
+ # if there is no thread to wait, raises ErrNoWaitingThread.
+ # if `nonblock' is true, and there is no terminated thread,
+ # raises ErrNoFinishedThread.
def next_wait(nonblock = nil)
- Threads.Wait.fail ErrWaitThreadsNothing if @threads.empty?
-
- th = @wait_queue.pop(nonblock)
- @threads.delete th
- th
+ ThreadsWait.fail ErrNoWaitingThread if @threads.empty?
+ begin
+ @threads.delete(th = @wait_queue.pop(nonblock))
+ th
+ rescue ThreadError
+ ThreadsWait.fail ErrNoFinshedThread
+ end
end
- #
- # Á´¤Æ¤Î¥¹¥ì¥Ã¥É¤¬½ªÎ»¤¹¤ë¤Þ¤ÇÂÔ¤Ä. ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿»þ¤Ï, ¥¹
- # ¥ì¥Ã¥É¤¬½ªÎ»¤¹¤ëÅÙ¤Ë, ¥¤¥Æ¥ì¡¼¥¿¤ò¸Æ¤Ó½Ð¤¹.
- #
+ # waits until all of specified threads are terminated.
+ # if a block is supplied for the method, evaluates it for
+ # each thread termination.
def all_waits
until @threads.empty?
th = next_wait
@@ -126,3 +129,5 @@ class ThreadsWait
end
end
end
+
+ThWait = ThreadsWait
diff --git a/lib/timeout.rb b/lib/timeout.rb
new file mode 100644
index 0000000000..d4ea758acd
--- /dev/null
+++ b/lib/timeout.rb
@@ -0,0 +1,42 @@
+#
+# timeout.rb -- execution timeout
+#
+#= SYNOPSIS
+#
+# require 'timeout'
+# status = timeout(5) {
+# # something may take time
+# }
+#
+#= DESCRIPTION
+#
+# timeout executes the block. If the block execution terminates successfully
+# before timeout, it returns true. If not, it terminates the execution and
+# raise TimeoutError exception.
+#
+#== Parameters
+#
+# : timout
+#
+# The time in seconds to wait for block teminatation.
+#
+#=end
+
+class TimeoutError<StandardError
+end
+
+Thread.abort_on_exception = true
+
+def timeout(sec)
+ begin
+ x = Thread.current
+ y = Thread.start {
+ sleep sec
+ x.raise TimeoutError, "execution expired" if x.status
+ }
+ yield sec
+ return true
+ ensure
+ Thread.kill y if y.status
+ end
+end
diff --git a/lib/tracer.rb b/lib/tracer.rb
index d37339fd62..fbfca24fe5 100644
--- a/lib/tracer.rb
+++ b/lib/tracer.rb
@@ -1,7 +1,28 @@
+#
+# tracer.rb -
+# $Release Version: 0.2$
+# $Revision: 1.8 $
+# $Date: 1998/05/19 03:42:49 $
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+
+#
+# tracer main class
+#
class Tracer
- MY_FILE_NAME_PATTERN = /^tracer\.(rb)?/
- Threads = Hash.new
- Sources = Hash.new
+ @RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-'
+
+ class << self
+ attr :verbose, TRUE
+ alias verbose? verbose
+ end
+ verbose = TRUE
+
+ MY_FILE_NAME = caller(0)[0].scan(/^(.*):[0-9]+$/)[0][0]
EVENT_SYMBOL = {
"line" => "-",
@@ -10,39 +31,89 @@ class Tracer
"class" => "C",
"end" => "E"}
+ def initialize
+ @threads = Hash.new
+ if defined? Thread.main
+ @threads[Thread.main.id] = 0
+ else
+ @threads[Thread.current.id] = 0
+ end
+
+ @get_line_procs = {}
+ @sources = {}
+
+ @filters = []
+ end
+
def on
- set_trace_func proc{|event, file, line, id, binding|
- trace_func event, file, line, id, binding
- }
- print "Trace on\n"
+ if iterator?
+ on
+ begin
+ yield
+ ensure
+ off
+ end
+ else
+ set_trace_func proc{|event, file, line, id, binding|
+ trace_func event, file, line, id, binding
+ }
+ print "Trace on\n" if Tracer.verbose?
+ end
end
def off
set_trace_func nil
- print "Trace off\n"
+ print "Trace off\n" if Tracer.verbose?
end
-
- def get_thread_no
- unless no = Threads[Thread.current.id]
- Threads[Thread.current.id] = no = Threads.size
- end
- no
+
+ def add_filter(p = proc)
+ @filters.push p
+ end
+
+ def set_get_line_procs(file, p = proc)
+ @get_line_procs[file] = p
end
def get_line(file, line)
- unless list = Sources[file]
- f =open(file)
- begin
- Sources[file] = list = f.readlines
- ensure
- f.close
+ if p = @get_line_procs[file]
+ return p.call line
+ end
+
+ unless list = @sources[file]
+# print file if $DEBUG
+ begin
+ f = open(file)
+ begin
+ @sources[file] = list = f.readlines
+ ensure
+ f.close
+ end
+ rescue
+ @sources[file] = list = []
end
end
- list[line - 1]
+ if l = list[line - 1]
+ l
+ else
+ "-\n"
+ end
+ end
+
+ def get_thread_no
+ if no = @threads[Thread.current.id]
+ no
+ else
+ @threads[Thread.current.id] = @threads.size
+ end
end
def trace_func(event, file, line, id, binding)
- return if File.basename(file) =~ MY_FILE_NAME_PATTERN
+ return if file == MY_FILE_NAME
+ #printf "Th: %s\n", Thread.current.inspect
+
+ for p in @filters
+ return unless p.call event, file, line, id, binding
+ end
Thread.critical = TRUE
printf("#%d:%s:%d:%s: %s",
@@ -56,20 +127,36 @@ class Tracer
Single = new
def Tracer.on
- Single.on
+ if iterator?
+ Single.on{yield}
+ else
+ Single.on
+ end
end
def Tracer.off
Single.off
end
-end
+ def Tracer.set_get_line_procs(file_name, p = proc)
+ Single.set_get_line_procs(file_name, p)
+ end
-if File.basename($0) =~ Tracer::MY_FILE_NAME_PATTERN
- $0 = ARGV.shift
+ def Tracer.add_filter(p = proc)
+ Single.add_filter(p)
+ end
- Tracer.on
- load $0
-else
- Tracer.on
+end
+
+if caller(0).size == 1
+ if $0 == Tracer::MY_FILE_NAME
+ # direct call
+
+ $0 = ARGV[0]
+ ARGV.shift
+ Tracer.on
+ require $0
+ else
+ Tracer.on
+ end
end
diff --git a/lib/weakref.rb b/lib/weakref.rb
index 93b2c65ecd..c31e959e74 100644
--- a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -10,9 +10,10 @@
require "delegate"
-class WeakRef<Delegater
+class WeakRef<Delegator
- Exception :RefError
+ class RefError<StandardError
+ end
ID_MAP = {}
ID_REV_MAP = {}
@@ -31,26 +32,22 @@ class WeakRef<Delegater
def initialize(orig)
super
- @id = orig.id
+ @__id = orig.__id__
ObjectSpace.call_finalizer orig
- ID_MAP[@id] = self.id
- ID_REV_MAP[self.id] = @id
+ ObjectSpace.call_finalizer self
+ ID_MAP[@__id] = self.__id__
+ ID_REV_MAP[self.id] = @__id
end
def __getobj__
- unless ID_MAP[@id]
- $@ = caller(1)
- $! = RefError.new("Illegal Reference - probably recycled")
- raise
+ unless ID_MAP[@__id]
+ raise RefError, "Illegal Reference - probably recycled", caller(2)
end
- ObjectSpace.id2ref(@id)
-# ObjectSpace.each_object do |obj|
-# return obj if obj.id == @id
-# end
+ ObjectSpace._id2ref(@__id)
end
def weakref_alive?
- if ID_MAP[@id]
+ if ID_MAP[@__id]
true
else
false
@@ -62,9 +59,11 @@ class WeakRef<Delegater
end
end
-foo = Object.new
-p foo.hash
-foo = WeakRef.new(foo)
-p foo.hash
-ObjectSpace.garbage_collect
-p foo.hash
+if __FILE__ == $0
+ foo = Object.new
+ p foo.hash # original's hash value
+ foo = WeakRef.new(foo)
+ p foo.hash # should be same hash value
+ ObjectSpace.garbage_collect
+ p foo.hash # should raise exception (recycled)
+end
diff --git a/main.c b/main.c
index 4741f646e8..5fd27cba4c 100644
--- a/main.c
+++ b/main.c
@@ -30,4 +30,5 @@ main(argc, argv, envp)
ruby_init();
ruby_options(argc, argv);
ruby_run();
+ return 0;
}
diff --git a/marshal.c b/marshal.c
index ac95e438ae..6a68b04352 100644
--- a/marshal.c
+++ b/marshal.c
@@ -3,14 +3,13 @@
marshal.c -
$Author$
- $Revision$
$Date$
created at: Thu Apr 27 16:30:01 JST 1995
************************************************/
#include "ruby.h"
-#include "io.h"
+#include "rubyio.h"
#include "st.h"
#define MARSHAL_MAJOR 4
@@ -38,12 +37,7 @@
#define TYPE_LINK '@'
-extern VALUE cString;
-extern VALUE cRegexp;
-extern VALUE cArray;
-extern VALUE cHash;
-
-VALUE rb_path2class();
+VALUE rb_path2class _((char*));
static ID s_dump, s_load;
@@ -69,7 +63,7 @@ w_byte(c, arg)
struct dump_arg *arg;
{
if (arg->fp) putc(c, arg->fp);
- else str_cat(arg->str, (UCHAR*)&c, 1);
+ else rb_str_cat(arg->str, &c, 1);
}
static void
@@ -83,7 +77,7 @@ w_bytes(s, n, arg)
fwrite(s, 1, n, arg->fp);
}
else {
- str_cat(arg->str, s, n);
+ rb_str_cat(arg->str, s, n);
}
}
@@ -94,7 +88,7 @@ w_short(x, arg)
{
int i;
- for (i=0; i<sizeof(USHORT); i++) {
+ for (i=0; i<sizeof(short); i++) {
w_byte((x >> (i*8)) & 0xff, arg);
}
}
@@ -155,7 +149,7 @@ w_symbol(id, arg)
else {
w_byte(TYPE_SYMBOL, arg);
w_bytes(sym, strlen(sym), arg);
- st_insert(arg->symbol, id, arg->symbol->num_entries);
+ st_add_direct(arg->symbol, id, arg->symbol->num_entries);
}
}
@@ -168,10 +162,9 @@ w_unique(s, arg)
}
static void w_object _((VALUE,struct dump_arg*,int));
-extern VALUE cIO, cBignum, cStruct;
static int
-hash_each(key, value, arg)
+rb_hash_each(key, value, arg)
VALUE key, value;
struct dump_call_arg *arg;
{
@@ -181,7 +174,7 @@ hash_each(key, value, arg)
}
static int
-obj_each(id, value, arg)
+rb_obj_each(id, value, arg)
ID id;
VALUE value;
struct dump_call_arg *arg;
@@ -192,11 +185,11 @@ obj_each(id, value, arg)
}
static void
-w_uclass(obj, class, arg)
- VALUE obj, class;
+w_uclass(obj, klass, arg)
+ VALUE obj, klass;
struct dump_arg *arg;
{
- if (CLASS_OF(obj) != class) {
+ if (CLASS_OF(obj) != klass) {
w_byte(TYPE_UCLASS, arg);
w_unique(rb_class2name(CLASS_OF(obj)), arg);
}
@@ -208,23 +201,18 @@ w_object(obj, arg, limit)
struct dump_arg *arg;
int limit;
{
- int n;
struct dump_call_arg c_arg;
if (limit == 0) {
- Fail("exceed depth limit");
+ rb_raise(rb_eRuntimeError, "exceed depth limit");
}
- limit--;
- c_arg.limit = limit;
- c_arg.arg = arg;
-
if (obj == Qnil) {
w_byte(TYPE_NIL, arg);
}
- else if (obj == TRUE) {
+ else if (obj == Qtrue) {
w_byte(TYPE_TRUE, arg);
}
- else if (obj == FALSE) {
+ else if (obj == Qfalse) {
w_byte(TYPE_FALSE, arg);
}
else if (FIXNUM_P(obj)) {
@@ -232,26 +220,30 @@ w_object(obj, arg, limit)
w_byte(TYPE_FIXNUM, arg);
w_long(FIX2INT(obj), arg);
#else
- if (RSHIFT(obj, 32) == 0 || RSHIFT(obj, 32) == -1) {
+ if (RSHIFT((long)obj, 32) == 0 || RSHIFT((long)obj, 32) == -1) {
w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2INT(obj), arg);
+ w_long(FIX2LONG(obj), arg);
}
else {
- obj = int2big(FIX2INT(obj));
- goto write_bignum;
+ w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
+ return;
}
#endif
}
else {
int num;
+ limit--;
+ c_arg.limit = limit;
+ c_arg.arg = arg;
+
if (st_lookup(arg->data, obj, &num)) {
w_byte(TYPE_LINK, arg);
w_long(num, arg);
return;
}
- st_insert(arg->data, obj, arg->data->num_entries);
+ st_add_direct(arg->data, obj, arg->data->num_entries);
if (rb_respond_to(obj, s_dump)) {
VALUE v;
@@ -259,7 +251,7 @@ w_object(obj, arg, limit)
w_unique(rb_class2name(CLASS_OF(obj)), arg);
v = rb_funcall(obj, s_dump, 1, limit);
if (TYPE(v) != T_STRING) {
- TypeError("_dump_to must return String");
+ rb_raise(rb_eTypeError, "_dump_to must return String");
}
w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
return;
@@ -281,12 +273,11 @@ w_object(obj, arg, limit)
return;
case T_BIGNUM:
- write_bignum:
w_byte(TYPE_BIGNUM, arg);
{
char sign = RBIGNUM(obj)->sign?'+':'-';
int len = RBIGNUM(obj)->len;
- USHORT *d = RBIGNUM(obj)->digits;
+ unsigned short *d = RBIGNUM(obj)->digits;
w_byte(sign, arg);
w_long(len, arg);
@@ -298,20 +289,20 @@ w_object(obj, arg, limit)
return;
case T_STRING:
- w_uclass(obj, cString, arg);
+ w_uclass(obj, rb_cString, arg);
w_byte(TYPE_STRING, arg);
w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg);
return;
case T_REGEXP:
- w_uclass(obj, cRegexp, arg);
+ w_uclass(obj, rb_cRegexp, arg);
w_byte(TYPE_REGEXP, arg);
w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg);
- w_byte(FL_TEST(obj, FL_USER1), arg);
+ w_byte(rb_reg_options(obj), arg);
return;
case T_ARRAY:
- w_uclass(obj, cArray, arg);
+ w_uclass(obj, rb_cArray, arg);
w_byte(TYPE_ARRAY, arg);
{
int len = RARRAY(obj)->len;
@@ -326,10 +317,10 @@ w_object(obj, arg, limit)
break;
case T_HASH:
- w_uclass(obj, cHash, arg);
+ w_uclass(obj, rb_cHash, arg);
w_byte(TYPE_HASH, arg);
w_long(RHASH(obj)->tbl->num_entries, arg);
- st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
+ st_foreach(RHASH(obj)->tbl, rb_hash_each, &c_arg);
break;
case T_STRUCT:
@@ -344,10 +335,10 @@ w_object(obj, arg, limit)
w_long(len, arg);
mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__"));
if (mem == Qnil) {
- Fatal("non-initialized struct");
+ rb_raise(rb_eTypeError, "non-initialized struct");
}
for (i=0; i<len; i++) {
- w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), arg);
+ w_symbol(FIX2LONG(RARRAY(mem)->ptr[i]), arg);
w_object(RSTRUCT(obj)->ptr[i], arg, limit);
}
}
@@ -356,17 +347,17 @@ w_object(obj, arg, limit)
case T_OBJECT:
w_byte(TYPE_OBJECT, arg);
{
- VALUE class = CLASS_OF(obj);
+ VALUE klass = CLASS_OF(obj);
char *path;
- if (FL_TEST(class, FL_SINGLETON)) {
- TypeError("singleton can't be dumped");
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "singleton can't be dumped");
}
- path = rb_class2name(class);
+ path = rb_class2name(klass);
w_unique(path, arg);
if (ROBJECT(obj)->iv_tbl) {
w_long(ROBJECT(obj)->iv_tbl->num_entries, arg);
- st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg);
+ st_foreach(ROBJECT(obj)->iv_tbl, rb_obj_each, &c_arg);
}
else {
w_long(0, arg);
@@ -375,7 +366,8 @@ w_object(obj, arg, limit)
break;
default:
- TypeError("can't dump %s", rb_class2name(CLASS_OF(obj)));
+ rb_raise(rb_eTypeError, "can't dump %s",
+ rb_class2name(CLASS_OF(obj)));
break;
}
}
@@ -386,6 +378,7 @@ dump(arg)
struct dump_call_arg *arg;
{
w_object(arg->obj, arg->arg, arg->limit);
+ return 0;
}
static VALUE
@@ -394,6 +387,7 @@ dump_ensure(arg)
{
st_free_table(arg->symbol);
st_free_table(arg->data);
+ return 0;
}
static VALUE
@@ -403,7 +397,6 @@ marshal_dump(argc, argv)
{
VALUE obj, port, a1, a2;
int limit = -1;
- extern VALUE cIO;
struct dump_arg arg;
struct dump_call_arg c_arg;
@@ -418,21 +411,21 @@ marshal_dump(argc, argv)
else port = a1;
}
if (port) {
- if (obj_is_kind_of(port, cIO)) {
+ if (rb_obj_is_kind_of(port, rb_cIO)) {
OpenFile *fptr;
- io_binmode(port);
+ rb_io_binmode(port);
GetOpenFile(port, fptr);
- io_writable(fptr);
+ rb_io_check_writable(fptr);
arg.fp = (fptr->f2) ? fptr->f2 : fptr->f;
}
else {
- TypeError("instance of IO needed");
+ rb_raise(rb_eTypeError, "instance of IO needed");
}
}
else {
arg.fp = 0;
- port = str_new(0, 0);
+ port = rb_str_new(0, 0);
arg.str = port;
}
@@ -445,14 +438,14 @@ marshal_dump(argc, argv)
w_byte(MARSHAL_MAJOR, &arg);
w_byte(MARSHAL_MINOR, &arg);
- rb_ensure(dump, &c_arg, dump_ensure, &arg);
+ rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
return port;
}
struct load_arg {
FILE *fp;
- UCHAR *ptr, *end;
+ char *ptr, *end;
st_table *symbol;
st_table *data;
VALUE proc;
@@ -463,19 +456,19 @@ r_byte(arg)
struct load_arg *arg;
{
if (arg->fp) return getc(arg->fp);
- if (arg->ptr < arg->end) return *arg->ptr++;
+ if (arg->ptr < arg->end) return *(unsigned char*)arg->ptr++;
return EOF;
}
-static USHORT
+static unsigned short
r_short(arg)
struct load_arg *arg;
{
- USHORT x;
+ unsigned short x;
int i;
x = 0;
- for (i=0; i<sizeof(USHORT); i++) {
+ for (i=0; i<sizeof(short); i++) {
x |= r_byte(arg)<<(i*8);
}
@@ -486,16 +479,17 @@ static void
long_toobig(size)
int size;
{
- TypeError("long too big for this architecture (size %d, given %d)",
- sizeof(long), size);
+ rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)",
+ sizeof(long), size);
}
static long
r_long(arg)
struct load_arg *arg;
{
- int c = r_byte(arg), i;
register long x;
+ int c = (char)r_byte(arg);
+ int i;
if (c == 0) return 0;
if (c > 0) {
@@ -505,7 +499,7 @@ r_long(arg)
x |= (long)r_byte(arg) << (8*i);
}
}
- else if (c < 0) {
+ else {
c = -c;
if (c > sizeof(long)) long_toobig((int)c);
x = -1;
@@ -517,12 +511,20 @@ r_long(arg)
return x;
}
-#define r_bytes(s, arg) \
- (s = (char*)r_long(arg), r_bytes0(&s,ALLOCA_N(char,(long)s),(long)s,arg))
+#define r_bytes2(s, len, arg) do { \
+ (len) = r_long(arg); \
+ (s) = ALLOCA_N(char,(len)+1); \
+ r_bytes0((s),(len),(arg)); \
+} while (0)
-static int
-r_bytes0(sp, s, len, arg)
- char **sp, *s;
+#define r_bytes(s, arg) do { \
+ int r_bytes_len; \
+ r_bytes2((s), r_bytes_len, (arg)); \
+} while (0)
+
+static void
+r_bytes0(s, len, arg)
+ char *s;
int len;
struct load_arg *arg;
{
@@ -536,11 +538,7 @@ r_bytes0(sp, s, len, arg)
memcpy(s, arg->ptr, len);
arg->ptr += len;
}
-
- (s)[len] = '\0';
- *sp = s;
-
- return len;
+ s[len] = '\0';
}
static ID
@@ -549,7 +547,6 @@ r_symbol(arg)
{
char *buf;
ID id;
- char type;
if (r_byte(arg) == TYPE_SYMLINK) {
int num = r_long(arg);
@@ -557,7 +554,7 @@ r_symbol(arg)
if (st_lookup(arg->symbol, num, &id)) {
return id;
}
- TypeError("bad symbol");
+ rb_raise(rb_eTypeError, "bad symbol");
}
r_bytes(buf, arg);
id = rb_intern(buf);
@@ -578,9 +575,10 @@ r_string(arg)
struct load_arg *arg;
{
char *buf;
- int len = r_bytes(buf, arg);
+ int len;
- return str_taint(str_new(buf, len));
+ r_bytes2(buf, len, arg);
+ return rb_str_new(buf, len);
}
static VALUE
@@ -588,6 +586,7 @@ r_regist(v, arg)
VALUE v;
struct load_arg *arg;
{
+ OBJ_TAINT(v);
if (arg->proc) {
rb_funcall(arg->proc, rb_intern("call"), 1, v);
}
@@ -604,14 +603,14 @@ r_object(arg)
switch (type) {
case EOF:
- eof_error();
+ rb_eof_error();
return Qnil;
case TYPE_LINK:
if (st_lookup(arg->data, r_long(arg), &v)) {
return v;
}
- ArgError("dump format error (unlinked)");
+ rb_raise(rb_eArgError, "dump format error (unlinked)");
break;
case TYPE_UCLASS:
@@ -619,9 +618,9 @@ r_object(arg)
VALUE c = rb_path2class(r_unique(arg));
v = r_object(arg);
if (rb_special_const_p(v)) {
- ArgError("dump format error (user class)");
+ rb_raise(rb_eArgError, "dump format error (user class)");
}
- RBASIC(v)->class = c;
+ RBASIC(v)->klass = c;
return v;
}
@@ -629,10 +628,10 @@ r_object(arg)
return Qnil;
case TYPE_TRUE:
- return TRUE;
+ return Qtrue;
case TYPE_FALSE:
- return FALSE;
+ return Qfalse;
case TYPE_FIXNUM:
{
@@ -648,26 +647,26 @@ r_object(arg)
char *buf;
r_bytes(buf, arg);
- v = float_new(atof(buf));
+ v = rb_float_new(atof(buf));
return r_regist(v, arg);
}
case TYPE_BIGNUM:
{
int len;
- USHORT *digits;
+ unsigned short *digits;
NEWOBJ(big, struct RBignum);
- OBJSETUP(big, cBignum, T_BIGNUM);
+ OBJSETUP(big, rb_cBignum, T_BIGNUM);
big->sign = (r_byte(arg) == '+');
big->len = len = r_long(arg);
- big->digits = digits = ALLOC_N(USHORT, len);
+ big->digits = digits = ALLOC_N(unsigned short, len);
while (len--) {
*digits++ = r_short(arg);
}
- big = RBIGNUM(big_norm((VALUE)big));
+ big = RBIGNUM(rb_big_norm((VALUE)big));
if (TYPE(big) == T_BIGNUM) {
- r_regist(big, arg);
+ r_regist((VALUE)big, arg);
}
return (VALUE)big;
}
@@ -678,18 +677,21 @@ r_object(arg)
case TYPE_REGEXP:
{
char *buf;
- int len = r_bytes(buf, arg);
- int ci = r_byte(arg);
- return r_regist(reg_new(buf, len, ci), arg);
+ int len;
+ int options;
+
+ r_bytes2(buf, len, arg);
+ options = r_byte(arg);
+ return r_regist(rb_reg_new(buf, len, options), arg);
}
case TYPE_ARRAY:
{
volatile int len = r_long(arg);
- v = ary_new2(len);
+ v = rb_ary_new2(len);
r_regist(v, arg);
while (len--) {
- ary_push(v, r_object(arg));
+ rb_ary_push(v, r_object(arg));
}
return v;
}
@@ -698,46 +700,46 @@ r_object(arg)
{
int len = r_long(arg);
- v = hash_new();
+ v = rb_hash_new();
r_regist(v, arg);
while (len--) {
VALUE key = r_object(arg);
VALUE value = r_object(arg);
- hash_aset(v, key, value);
+ rb_hash_aset(v, key, value);
}
return v;
}
case TYPE_STRUCT:
{
- VALUE class, mem, values;
+ VALUE klass, mem, values;
volatile int i; /* gcc 2.7.2.3 -O2 bug?? */
int len;
ID slot;
- class = rb_path2class(r_unique(arg));
- mem = rb_ivar_get(class, rb_intern("__member__"));
+ klass = rb_path2class(r_unique(arg));
+ mem = rb_ivar_get(klass, rb_intern("__member__"));
if (mem == Qnil) {
- Fatal("non-initialized struct");
+ rb_raise(rb_eTypeError, "non-initialized struct");
}
len = r_long(arg);
- values = ary_new2(len);
+ values = rb_ary_new2(len);
for (i=0; i<len; i++) {
- ary_push(values, Qnil);
+ rb_ary_push(values, Qnil);
}
- v = struct_alloc(class, values);
+ v = rb_struct_alloc(klass, values);
r_regist(v, arg);
for (i=0; i<len; i++) {
slot = r_symbol(arg);
if (RARRAY(mem)->ptr[i] != INT2FIX(slot)) {
- TypeError("struct %s not compatible (:%s for :%s)",
- rb_class2name(class),
- rb_id2name(slot),
- rb_id2name(FIX2INT(RARRAY(mem)->ptr[i])));
+ rb_raise(rb_eTypeError, "struct %s not compatible (:%s for :%s)",
+ rb_class2name(klass),
+ rb_id2name(slot),
+ rb_id2name(FIX2INT(RARRAY(mem)->ptr[i])));
}
- struct_aset(v, INT2FIX(i), r_object(arg));
+ rb_struct_aset(v, INT2FIX(i), r_object(arg));
}
return v;
}
@@ -745,27 +747,26 @@ r_object(arg)
case TYPE_USERDEF:
{
- VALUE class;
- int len;
+ VALUE klass;
- class = rb_path2class(r_unique(arg));
- if (rb_respond_to(class, s_load)) {
- v = rb_funcall(class, s_load, 1, r_string(arg));
+ klass = rb_path2class(r_unique(arg));
+ if (rb_respond_to(klass, s_load)) {
+ v = rb_funcall(klass, s_load, 1, r_string(arg));
return r_regist(v, arg);
}
- TypeError("class %s needs to have method `_load_from'",
- rb_class2name(class));
+ rb_raise(rb_eTypeError, "class %s needs to have method `_load_from'",
+ rb_class2name(klass));
}
break;
case TYPE_OBJECT:
{
- VALUE class;
+ VALUE klass;
int len;
- class = rb_path2class(r_unique(arg));
+ klass = rb_path2class(r_unique(arg));
len = r_long(arg);
- v = obj_alloc(class);
+ v = rb_obj_alloc(klass);
r_regist(v, arg);
if (len > 0) {
while (len--) {
@@ -786,9 +787,10 @@ r_object(arg)
}
default:
- ArgError("dump format error(0x%x)", type);
+ rb_raise(rb_eArgError, "dump format error(0x%x)", type);
break;
}
+ return Qnil; /* not reached */
}
static VALUE
@@ -804,6 +806,7 @@ load_ensure(arg)
{
st_free_table(arg->symbol);
st_free_table(arg->data);
+ return 0;
}
static VALUE
@@ -812,57 +815,57 @@ marshal_load(argc, argv)
VALUE *argv;
{
VALUE port, proc;
- FILE *fp;
int major;
VALUE v;
OpenFile *fptr;
struct load_arg arg;
rb_scan_args(argc, argv, "11", &port, &proc);
- if (TYPE(port) == T_STRING) {
+ if (rb_obj_is_kind_of(port, rb_cIO)) {
+ rb_io_binmode(port);
+ GetOpenFile(port, fptr);
+ rb_io_check_readable(fptr);
+ arg.fp = fptr->f;
+ }
+ else if (rb_respond_to(port, rb_intern("to_str"))) {
+ int len;
+
arg.fp = 0;
- arg.ptr = RSTRING(port)->ptr;
- arg.end = arg.ptr + RSTRING(port)->len;
+ arg.ptr = str2cstr(port, &len);
+ arg.end = arg.ptr + len;
}
else {
- if (obj_is_kind_of(port, cIO)) {
- io_binmode(port);
- GetOpenFile(port, fptr);
- io_readable(fptr);
- arg.fp = fptr->f;
- }
- else {
- TypeError("instance of IO needed");
- }
+ rb_raise(rb_eTypeError, "instance of IO needed");
}
major = r_byte(&arg);
if (major == MARSHAL_MAJOR) {
if (r_byte(&arg) != MARSHAL_MINOR) {
- Warning("Old marshal file format (can be read)");
+ rb_warn("Old marshal file format (can be read)");
}
arg.symbol = st_init_numtable();
arg.data = st_init_numtable();
if (NIL_P(proc)) arg.proc = 0;
else arg.proc = proc;
- v = rb_ensure(load, &arg, load_ensure, &arg);
+ v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
}
else {
- TypeError("Old marshal file format (can't read)");
+ rb_raise(rb_eTypeError, "Old marshal file format (can't read)");
}
return v;
}
+void
Init_marshal()
{
- VALUE mMarshal = rb_define_module("Marshal");
+ VALUE rb_mMarshal = rb_define_module("Marshal");
- s_dump = rb_intern("_dump_to");
- s_load = rb_intern("_load_from");
- rb_define_module_function(mMarshal, "dump", marshal_dump, -1);
- rb_define_module_function(mMarshal, "load", marshal_load, -1);
- rb_define_module_function(mMarshal, "restore", marshal_load, 1);
+ s_dump = rb_intern("_dump");
+ s_load = rb_intern("_load");
+ rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1);
+ rb_define_module_function(rb_mMarshal, "load", marshal_load, -1);
+ rb_define_module_function(rb_mMarshal, "restore", marshal_load, 1);
- rb_provide("marshal.o"); /* for backward compatibility */
+ rb_provide("marshal.so"); /* for backward compatibility */
}
diff --git a/math.c b/math.c
index 0e427035f4..3ea30bdbba 100644
--- a/math.c
+++ b/math.c
@@ -6,14 +6,14 @@
$Date$
created at: Tue Jan 25 14:12:56 JST 1994
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <math.h>
-VALUE mMath;
+VALUE rb_mMath;
#define Need_Float(x) (x) = rb_Float(x)
#define Need_Float2(x,y) {\
@@ -26,7 +26,7 @@ math_atan2(obj, x, y)
VALUE obj, x, y;
{
Need_Float2(x, y);
- return float_new(atan2(RFLOAT(x)->value, RFLOAT(y)->value));
+ return rb_float_new(atan2(RFLOAT(x)->value, RFLOAT(y)->value));
}
static VALUE
@@ -35,7 +35,7 @@ math_cos(obj, x)
{
Need_Float(x);
- return float_new(cos(RFLOAT(x)->value));
+ return rb_float_new(cos(RFLOAT(x)->value));
}
static VALUE
@@ -44,7 +44,7 @@ math_sin(obj, x)
{
Need_Float(x);
- return float_new(sin(RFLOAT(x)->value));
+ return rb_float_new(sin(RFLOAT(x)->value));
}
static VALUE
@@ -53,7 +53,7 @@ math_tan(obj, x)
{
Need_Float(x);
- return float_new(tan(RFLOAT(x)->value));
+ return rb_float_new(tan(RFLOAT(x)->value));
}
static VALUE
@@ -61,7 +61,7 @@ math_exp(obj, x)
VALUE obj, x;
{
Need_Float(x);
- return float_new(exp(RFLOAT(x)->value));
+ return rb_float_new(exp(RFLOAT(x)->value));
}
static VALUE
@@ -69,7 +69,7 @@ math_log(obj, x)
VALUE obj, x;
{
Need_Float(x);
- return float_new(log(RFLOAT(x)->value));
+ return rb_float_new(log(RFLOAT(x)->value));
}
static VALUE
@@ -77,7 +77,7 @@ math_log10(obj, x)
VALUE obj, x;
{
Need_Float(x);
- return float_new(log10(RFLOAT(x)->value));
+ return rb_float_new(log10(RFLOAT(x)->value));
}
static VALUE
@@ -86,34 +86,60 @@ math_sqrt(obj, x)
{
Need_Float(x);
- if (RFLOAT(x)->value < 0.0) ArgError("square root for negative number");
- return float_new(sqrt(RFLOAT(x)->value));
+ if (RFLOAT(x)->value < 0.0) rb_raise(rb_eArgError, "square root for negative number");
+ return rb_float_new(sqrt(RFLOAT(x)->value));
+}
+
+static VALUE
+math_frexp(obj, x)
+ VALUE obj, x;
+{
+ double d;
+ int exp;
+
+ Need_Float(x);
+ d = frexp(RFLOAT(x)->value, &exp);
+
+ return rb_assoc_new(rb_float_new(d), INT2NUM(exp));
+}
+
+static VALUE
+math_ldexp(obj, x, n)
+ VALUE obj, x, n;
+{
+ double d;
+
+ Need_Float(x);
+ return rb_float_new(d = ldexp(RFLOAT(x)->value, NUM2INT(n)));
}
void
Init_Math()
{
- mMath = rb_define_module("Math");
+ rb_mMath = rb_define_module("Math");
#ifdef M_PI
- rb_define_const(mMath, "PI", float_new(M_PI));
+ rb_define_const(rb_mMath, "PI", rb_float_new(M_PI));
#else
- rb_define_const(mMath, "PI", float_new(atan(1.0)*4.0));
+ rb_define_const(rb_mMath, "PI", rb_float_new(atan(1.0)*4.0));
#endif
#ifdef M_E
- rb_define_const(mMath, "E", float_new(M_E));
+ rb_define_const(rb_mMath, "E", rb_float_new(M_E));
#else
- rb_define_const(mMath, "E", float_new(exp(1.0)));
+ rb_define_const(rb_mMath, "E", rb_float_new(exp(1.0)));
#endif
- rb_define_module_function(mMath, "atan2", math_atan2, 2);
- rb_define_module_function(mMath, "cos", math_cos, 1);
- rb_define_module_function(mMath, "sin", math_sin, 1);
- rb_define_module_function(mMath, "tan", math_tan, 1);
+ rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);
+ rb_define_module_function(rb_mMath, "cos", math_cos, 1);
+ rb_define_module_function(rb_mMath, "sin", math_sin, 1);
+ rb_define_module_function(rb_mMath, "tan", math_tan, 1);
+
+ rb_define_module_function(rb_mMath, "exp", math_exp, 1);
+ rb_define_module_function(rb_mMath, "log", math_log, 1);
+ rb_define_module_function(rb_mMath, "log10", math_log10, 1);
+ rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
- rb_define_module_function(mMath, "exp", math_exp, 1);
- rb_define_module_function(mMath, "log", math_log, 1);
- rb_define_module_function(mMath, "log10", math_log10, 1);
- rb_define_module_function(mMath, "sqrt", math_sqrt, 1);
+ rb_define_module_function(rb_mMath, "frexp", math_frexp, 1);
+ rb_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
}
diff --git a/misc/README b/misc/README
new file mode 100644
index 0000000000..adc119d02e
--- /dev/null
+++ b/misc/README
@@ -0,0 +1,5 @@
+README this file
+inf-ruby.el program to run ruby under emacs
+ruby-mode.el ruby mode for emacs
+rubydb2x.el ruby debugger support for emacs 19.2x or before
+rubydb3x.el ruby debugger support for emacs 19.3x or later
diff --git a/misc/inf-ruby.el b/misc/inf-ruby.el
new file mode 100644
index 0000000000..025ef2fb2a
--- /dev/null
+++ b/misc/inf-ruby.el
@@ -0,0 +1,316 @@
+(J;;;(B (J-*-Emacs-Lisp-*-(B
+;;;
+;;; $Id$
+;;; $Author$
+;;; $Date$
+;;;
+;;; Inferior Ruby Mode - ruby process in a buffer.
+;;; adapted from cmuscheme.el
+;;;
+;;; Usage:
+;;;
+;;; (0) check ruby-program-name variable that can run your environment.
+;;;
+;;; (1) modify .emacs to use ruby-mode
+;;; for example :
+;;;
+;;; (autoload 'ruby-mode "ruby-mode"
+;;; "Mode for editing ruby source files")
+;;; (setq auto-mode-alist
+;;; (append '(("\\.rb$" . ruby-mode)) auto-mode-alist))
+;;; (setq interpreter-mode-alist (append '(("^#!.*ruby" . ruby-mode))
+;;; interpreter-mode-alist))
+;;;
+;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode.
+;;;
+;;; (autoload 'run-ruby "inf-ruby"
+;;; "Run an inferior Ruby process")
+;;; (autoload 'inf-ruby-keys "inf-ruby"
+;;; "Set local key defs for inf-ruby in ruby-mode")
+;;; (add-hook 'ruby-mode-hook
+;;; '(lambda ()
+;;; (inf-ruby-keys)
+;;; ))
+;;;
+;;; HISTORY
+;;; senda - 8 Apr 1998: Created.
+;;; $Log$
+;;; Revision 1.1.1.1 1999/01/20 04:59:36 matz
+;;; ruby 1.3 cycle
+;;;
+;;; Revision 1.1.2.1 1998/12/16 07:30:36 matz
+;;; first public release of 1.1d (pre1.2) series
+;;;
+;;; Revision 1.4 1998/05/20 02:45:58 senda
+;;; default program to irb
+;;;
+;;; Revision 1.3 1998/04/10 04:11:30 senda
+;;; modification by Matsumoto san (1.1b9_09)
+;;; remove-in-string defined
+;;; global variable :
+;;; inferior-ruby-first-prompt-pattern
+;;; inferior-ruby-prompt-pattern
+;;; defined
+;;;
+;;; Revision 1.2 1998/04/09 07:53:42 senda
+;;; remove M-C-x in inferior-ruby-mode
+;;;
+;;; Revision 1.1 1998/04/09 07:28:36 senda
+;;; Initial revision
+;;;
+;;;
+
+(require 'comint)
+(require 'ruby-mode)
+
+;;
+;; you may change these variables
+;;
+;(defvar ruby-program-name "rbc --noreadline"
+; "*Program invoked by the run-ruby command")
+;
+;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *"
+; "first prompt regex pattern of ruby interpreter.")
+;
+;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+"
+; "prompt regex pattern of ruby interpreter.")
+
+;;;; for irb
+(defvar ruby-program-name "irb --inf-ruby-mode"
+ "*Program invoked by the run-ruby command")
+
+(defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *"
+ "first prompt regex pattern of ruby interpreter.")
+
+(defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+"
+ "prompt regex pattern of ruby interpreter.")
+
+;;
+;; mode variables
+;;
+(defvar inferior-ruby-mode-hook nil
+ "*Hook for customising inferior-ruby mode.")
+(defvar inferior-ruby-mode-map nil
+ "*Mode map for inferior-ruby-mode")
+
+(cond ((not inferior-ruby-mode-map)
+ (setq inferior-ruby-mode-map
+ (copy-keymap comint-mode-map))
+; (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention
+; 'ruby-send-definition)
+; (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
+ (define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file)
+))
+
+(defun inf-ruby-keys ()
+ "Set local key defs for inf-ruby in ruby-mode"
+ (define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition)
+; (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
+ (define-key ruby-mode-map "\C-c\C-e" 'ruby-send-definition)
+ (define-key ruby-mode-map "\C-c\M-e" 'ruby-send-definition-and-go)
+ (define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region)
+ (define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go)
+ (define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby)
+ (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file)
+ (define-key ruby-mode-map "\C-c\C-s" 'run-ruby)
+)
+
+(defvar ruby-buffer nil "current ruby (actually irb) process buffer.")
+
+(defun inferior-ruby-mode ()
+ "Major mode for interacting with an inferior ruby (irb) process.
+
+The following commands are available:
+\\{inferior-ruby-mode-map}
+
+A ruby process can be fired up with M-x run-ruby.
+
+Customisation: Entry to this mode runs the hooks on comint-mode-hook and
+inferior-ruby-mode-hook (in that order).
+
+You can send text to the inferior ruby process from other buffers containing
+Ruby source.
+ switch-to-ruby switches the current buffer to the ruby process buffer.
+ ruby-send-definition sends the current definition to the ruby process.
+ ruby-send-region sends the current region to the ruby process.
+
+ ruby-send-definition-and-go, ruby-send-region-and-go,
+ switch to the ruby process buffer after sending their text.
+For information on running multiple processes in multiple buffers, see
+documentation for variable ruby-buffer.
+
+Commands:
+Return after the end of the process' output sends the text from the
+ end of process to point.
+Return before the end of the process' output copies the sexp ending at point
+ to the end of the process' output, and sends it.
+Delete converts tabs to spaces as it moves back.
+Tab indents for ruby; with argument, shifts rest
+ of expression rigidly with the current line.
+C-M-q does Tab on each line starting within following expression.
+Paragraphs are separated only by blank lines. # start comments.
+If you accidentally suspend your process, use \\[comint-continue-subjob]
+to continue it."
+ (interactive)
+ (comint-mode)
+ ;; Customise in inferior-ruby-mode-hook
+ ;(setq comint-prompt-regexp "^[^>\n]*>+ *")
+ (setq comint-prompt-regexp inferior-ruby-prompt-pattern)
+ ;;(scheme-mode-variables)
+ (ruby-mode-variables)
+ (setq major-mode 'inferior-ruby-mode)
+ (setq mode-name "Inferior Ruby")
+ (setq mode-line-process '(":%s"))
+ (use-local-map inferior-ruby-mode-map)
+ (setq comint-input-filter (function ruby-input-filter))
+ (setq comint-get-old-input (function ruby-get-old-input))
+ (run-hooks 'inferior-ruby-mode-hook))
+
+(defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
+ "*Input matching this regexp are not saved on the history list.
+Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
+
+(defun ruby-input-filter (str)
+ "Don't save anything matching inferior-ruby-filter-regexp"
+ (not (string-match inferior-ruby-filter-regexp str)))
+
+;; adapted from replace-in-string in XEmacs (subr.el)
+(defun remove-in-string (str regexp)
+ "Remove all matches in STR for REGEXP and returns the new string."
+ (let ((rtn-str "") (start 0) match prev-start)
+ (while (setq match (string-match regexp str start))
+ (setq prev-start start
+ start (match-end 0)
+ rtn-str (concat rtn-str (substring str prev-start match))))
+ (concat rtn-str (substring str start))))
+
+(defun ruby-get-old-input ()
+ "Snarf the sexp ending at point"
+ (save-excursion
+ (let ((end (point)))
+ (re-search-backward inferior-ruby-first-prompt-pattern)
+ (remove-in-string (buffer-substring (point) end)
+ inferior-ruby-prompt-pattern)
+ )))
+
+(defun ruby-args-to-list (string)
+ (let ((where (string-match "[ \t]" string)))
+ (cond ((null where) (list string))
+ ((not (= where 0))
+ (cons (substring string 0 where)
+ (ruby-args-to-list (substring string (+ 1 where)
+ (length string)))))
+ (t (let ((pos (string-match "[^ \t]" string)))
+ (if (null pos)
+ nil
+ (ruby-args-to-list (substring string pos
+ (length string)))))))))
+
+(defun run-ruby (cmd)
+ "Run an inferior Ruby process, input and output via buffer *ruby*.
+If there is a process already running in `*ruby*', switch to that buffer.
+With argument, allows you to edit the command line (default is value
+of `ruby-program-name'). Runs the hooks `inferior-ruby-mode-hook'
+\(after the `comint-mode-hook' is run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
+
+ (interactive (list (if current-prefix-arg
+ (read-string "Run Ruby: " ruby-program-name)
+ ruby-program-name)))
+ (if (not (comint-check-proc "*ruby*"))
+ (let ((cmdlist (ruby-args-to-list cmd)))
+ (set-buffer (apply 'make-comint "ruby" (car cmdlist)
+ nil (cdr cmdlist)))
+ (inferior-ruby-mode)))
+ (setq ruby-program-name cmd)
+ (setq ruby-buffer "*ruby*")
+ (pop-to-buffer "*ruby*"))
+
+(defun ruby-send-region (start end)
+ "Send the current region to the inferior Ruby process."
+ (interactive "r")
+ (comint-send-region (ruby-proc) start end)
+ (comint-send-string (ruby-proc) "\n"))
+
+(defun ruby-send-definition ()
+ "Send the current definition to the inferior Ruby process."
+ (interactive)
+ (save-excursion
+ (ruby-end-of-defun)
+ (let ((end (point)))
+ (ruby-beginning-of-defun)
+ (ruby-send-region (point) end))))
+
+;(defun ruby-send-last-sexp ()
+; "Send the previous sexp to the inferior Ruby process."
+; (interactive)
+; (ruby-send-region (save-excursion (backward-sexp) (point)) (point)))
+
+(defun switch-to-ruby (eob-p)
+ "Switch to the ruby process buffer.
+With argument, positions cursor at end of buffer."
+ (interactive "P")
+ (if (get-buffer ruby-buffer)
+ (pop-to-buffer ruby-buffer)
+ (error "No current process buffer. See variable ruby-buffer."))
+ (cond (eob-p
+ (push-mark)
+ (goto-char (point-max)))))
+
+(defun ruby-send-region-and-go (start end)
+ "Send the current region to the inferior Ruby process.
+Then switch to the process buffer."
+ (interactive "r")
+ (ruby-send-region start end)
+ (switch-to-ruby t))
+
+(defun ruby-send-definition-and-go ()
+ "Send the current definition to the inferior Ruby.
+Then switch to the process buffer."
+ (interactive)
+ (ruby-send-definition)
+ (switch-to-ruby t))
+
+(defvar ruby-source-modes '(ruby-mode)
+ "*Used to determine if a buffer contains Ruby source code.
+If it's loaded into a buffer that is in one of these major modes, it's
+considered a ruby source file by ruby-load-file.
+Used by these commands to determine defaults.")
+
+(defvar ruby-prev-l/c-dir/file nil
+ "Caches the last (directory . file) pair.
+Caches the last pair used in the last ruby-load-file command.
+Used for determining the default in the
+next one.")
+
+(defun ruby-load-file (file-name)
+ "Load a Ruby file into the inferior Ruby process."
+ (interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file
+ ruby-source-modes t)) ; T because LOAD
+ ; needs an exact name
+ (comint-check-source file-name) ; Check to see if buffer needs saved.
+ (setq ruby-prev-l/c-dir/file (cons (file-name-directory file-name)
+ (file-name-nondirectory file-name)))
+ (comint-send-string (ruby-proc) (concat "(load \""
+ file-name
+ "\"\)\n")))
+
+(defun ruby-proc ()
+ "Returns the current ruby process. See variable ruby-buffer."
+ (let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode)
+ (current-buffer)
+ ruby-buffer))))
+ (or proc
+ (error "No current process. See variable ruby-buffer"))))
+
+;;; Do the user's customisation...
+
+(defvar inf-ruby-load-hook nil
+ "This hook is run when inf-ruby is loaded in.
+This is a good place to put keybindings.")
+
+(run-hooks 'inf-ruby-load-hook)
+
+(provide 'inf-ruby)
+
+;;; inf-ruby.el ends here
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
new file mode 100644
index 0000000000..cf53574481
--- /dev/null
+++ b/misc/ruby-mode.el
@@ -0,0 +1,699 @@
+;;;
+;;; ruby-mode.el -
+;;;
+;;; $Author$
+;;; $Date$
+;;; created at: Fri Feb 4 14:49:13 JST 1994
+;;;
+
+(defconst ruby-mode-revision "$Revision$")
+
+(defconst ruby-mode-version
+ (progn
+ (string-match "[0-9.]+" ruby-mode-revision)
+ (substring ruby-mode-revision (match-beginning 0) (match-end 0))))
+
+(defconst ruby-block-beg-re
+ "class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do"
+ )
+
+(defconst ruby-indent-beg-re
+ "\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin"
+ )
+
+(defconst ruby-modifier-re
+ "if\\|unless\\|while\\|until"
+ )
+
+(defconst ruby-block-mid-re
+ "then\\|else\\|elsif\\|when\\|rescue\\|ensure"
+ )
+
+(defconst ruby-block-op-re
+ "and\\|or\\|not"
+ )
+
+(defconst ruby-block-end-re "end")
+
+(defconst ruby-delimiter
+ (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\("
+ ruby-block-beg-re
+ "\\|" ruby-block-end-re
+ "\\)\\>\\|^=begin")
+ )
+
+(defconst ruby-negative
+ (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|\\("
+ ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
+ )
+
+(defconst ruby-operator-chars ",.+*/%-&|^~=<>:")
+(defconst ruby-operator-re (concat "[" ruby-operator-chars "]"))
+
+(defconst ruby-symbol-chars "a-zA-Z0-9_")
+(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]"))
+
+(defvar ruby-mode-abbrev-table nil
+ "Abbrev table in use in ruby-mode buffers.")
+
+(define-abbrev-table 'ruby-mode-abbrev-table ())
+
+(defvar ruby-mode-map nil "Keymap used in ruby mode.")
+
+(if ruby-mode-map
+ nil
+ (setq ruby-mode-map (make-sparse-keymap))
+ (define-key ruby-mode-map "{" 'ruby-electric-brace)
+ (define-key ruby-mode-map "}" 'ruby-electric-brace)
+ (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
+ (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
+ (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
+ (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
+ (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
+ (define-key ruby-mode-map "\t" 'ruby-indent-command)
+ (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
+ (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
+ (define-key ruby-mode-map "\C-m" 'newline))
+
+(defvar ruby-mode-syntax-table nil
+ "Syntax table in use in ruby-mode buffers.")
+
+(if ruby-mode-syntax-table
+ ()
+ (setq ruby-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?# "<" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table)
+ (modify-syntax-entry ?$ "/" ruby-mode-syntax-table)
+ (modify-syntax-entry ?? "_" ruby-mode-syntax-table)
+ (modify-syntax-entry ?_ "_" ruby-mode-syntax-table)
+ (modify-syntax-entry ?< "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?> "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?& "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?| "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?% "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?= "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?/ "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?+ "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?* "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?- "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?\; "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?\( "()" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\} "){" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
+ )
+
+(defvar ruby-indent-level 2
+ "*Indentation of ruby statements.")
+
+(defun ruby-mode-variables ()
+ (set-syntax-table ruby-mode-syntax-table)
+ (setq local-abbrev-table ruby-mode-abbrev-table)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'ruby-indent-line)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-variable-buffer-local 'comment-start)
+ (setq comment-start "# ")
+ (make-variable-buffer-local 'comment-end)
+ (setq comment-end "")
+ (make-variable-buffer-local 'comment-column)
+ (setq comment-column 32)
+ (make-variable-buffer-local 'comment-start-skip)
+ (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (setq parse-sexp-ignore-comments t)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "$\\|" page-delimiter))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'paragraph-ignore-fill-prefix)
+ (setq paragraph-ignore-fill-prefix t))
+
+(defun ruby-mode ()
+ "Major mode for editing ruby scripts.
+\\[ruby-indent-command] properly indents subexpressions of multi-line
+class, module, def, if, while, for, do, and case statements, taking
+nesting into account.
+
+The variable ruby-indent-level controls the amount of indentation.
+\\{ruby-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map ruby-mode-map)
+ (setq mode-name "Ruby")
+ (setq major-mode 'ruby-mode)
+ (ruby-mode-variables)
+ (run-hooks 'ruby-mode-hook))
+
+(defun ruby-current-indentation ()
+ (save-excursion
+ (beginning-of-line)
+ (back-to-indentation)
+ (current-column)))
+
+(defun ruby-indent-line (&optional flag)
+ "Correct indentation of the current ruby line."
+ (ruby-indent-to (ruby-calculate-indent)))
+
+(defun ruby-indent-command ()
+ (interactive)
+ (ruby-indent-line t))
+
+(defun ruby-indent-to (x)
+ (if x
+ (let (shift top beg)
+ (and (< x 0)
+ (error "invalid nest"))
+ (setq shift (current-column))
+ (beginning-of-line)
+ (setq beg (point))
+ (back-to-indentation)
+ (setq top (current-column))
+ (skip-chars-backward " \t")
+ (cond
+ ((>= x shift)
+ (setq shift 0))
+ ((>= shift top)
+ (setq shift (- shift top)))
+ (t (setq shift 0)))
+ (if (and (bolp)
+ (= x top))
+ (move-to-column (+ x shift))
+ (move-to-column top)
+ (delete-region beg (point))
+ (beginning-of-line)
+ (indent-to x)
+ (move-to-column (+ x shift))))))
+
+(defun ruby-expr-beg (&optional modifier pnt)
+ (save-excursion
+ (if (looking-at "\\?")
+ (progn
+ (or (bolp) (forward-char -1))
+ (not (looking-at "\\sw")))
+ (store-match-data nil)
+ (skip-chars-backward " \t")
+ (or (bolp) (forward-char -1))
+ (or (bolp)
+ (looking-at ruby-operator-re)
+ (looking-at "[\\[({]")
+ (and (not modifier) (looking-at "[!?]"))
+ (and (looking-at ruby-symbol-re)
+ (forward-word -1)
+ (if (and (not modifier) (bolp))
+ t
+ (if (or (looking-at ruby-block-beg-re)
+ (looking-at ruby-block-op-re)
+ (looking-at ruby-block-mid-re))
+ (progn
+ (goto-char (match-end 0))
+ (looking-at "\\>")))))))))
+
+(defun ruby-parse-region (start end)
+ (let ((indent-point end)
+ (indent 0)
+ (in-string nil)
+ (in-paren nil)
+ (depth 0)
+ (nest nil)
+ (pcol nil))
+ (save-excursion
+ (if start
+ (goto-char start)
+ (ruby-beginning-of-indent))
+ (save-restriction
+ (narrow-to-region (point) end)
+ (while (and (> indent-point (point))
+ (re-search-forward ruby-delimiter indent-point t))
+ (let ((pnt (point)) w)
+ (goto-char (match-beginning 0))
+ (cond
+ ((or (looking-at "\"") ;skip string
+ (looking-at "'")
+ (looking-at "`"))
+ (setq w (char-after (point)))
+ (cond
+ ((and (not (eobp))
+ (re-search-forward (format "[^\\]\\(\\\\\\\\\\)*%c" w) indent-point t))
+ nil)
+ (t
+ (setq in-string (point))
+ (goto-char indent-point))))
+ ((looking-at "/")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg))
+ (if (re-search-forward "[^\\]/" indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "%")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg)
+ (looking-at "%[Qqrxw]?\\(.\\)"))
+ (setq w (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ (cond
+ ((string= w "[") (setq w "]"))
+ ((string= w "{") (setq w "}"))
+ ((string= w "(") (setq w ")"))
+ ((string= w "<") (setq w ">")))
+ (goto-char (match-end 0))
+ (if (search-forward w indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\?") ;skip ?char
+ (cond
+ ((ruby-expr-beg)
+ (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
+ (goto-char (match-end 0)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\$") ;skip $char
+ (goto-char pnt)
+ (forward-char 1))
+ ((looking-at "#") ;skip comment
+ (forward-line 1)
+ (goto-char (point))
+ )
+ ((looking-at "(")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq pcol (cons (cons pnt depth) pcol))
+ (setq depth 0)
+ (goto-char pnt)
+ )
+ ((looking-at "[\\[{]")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq depth (1+ depth))
+ (goto-char pnt)
+ )
+ ((looking-at ")")
+ (setq nest (cdr nest))
+ (setq depth (cdr (car pcol)))
+ (setq pcol (cdr pcol))
+ (goto-char pnt))
+ ((looking-at "[])}]")
+ (setq nest (cdr nest))
+ (setq depth (1- depth))
+ (goto-char pnt))
+ ((looking-at ruby-block-end-re)
+ (if (or (and (not (bolp))
+ (progn
+ (forward-char -1)
+ (eq ?_ (char-after (point)))))
+ (progn
+ (goto-char pnt)
+ (setq w (char-after (point)))
+ (or (eq ?_ w)
+ (eq ?! w)
+ (eq ?? w))))
+ nil
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))
+ (goto-char pnt))
+ ((looking-at "def\\s +[^(\n;]*")
+ (if (or (bolp)
+ (progn
+ (forward-char -1)
+ (not (eq ?_ (char-after (point))))))
+ (progn
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth))))
+ (goto-char (match-end 0)))
+ ((looking-at ruby-block-beg-re)
+ (and
+ (or (bolp)
+ (progn
+ (forward-char -1)
+ (not (eq ?_ (char-after (point))))))
+ (goto-char pnt)
+ (setq w (char-after (point)))
+ (not (eq ?_ w))
+ (not (eq ?! w))
+ (not (eq ?? w))
+ (skip-chars-forward " \t")
+ (if (not (eolp))
+ (progn
+ (goto-char (match-beginning 0))
+ (if (looking-at ruby-modifier-re)
+ (ruby-expr-beg t)
+ t))
+ t)
+ (goto-char pnt)
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth)))
+ (goto-char pnt))
+ ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?")
+ (goto-char (match-end 0)))
+ ((or (looking-at "\\.")
+ (looking-at "\\.\\.\\.?")
+ (looking-at "\\.[0-9]+")
+ (looking-at "\\.[a-zA-Z_0-9]+"))
+ (goto-char (match-end 0)))
+ ((looking-at "^=begin")
+ (if (re-search-forward "^=end" indent-point t)
+ (forward-line 1)
+ (setq in-string (match-end 0))
+ (goto-char indent-point)))
+ (t
+ (error (format "bad string %s"
+ (buffer-substring (point) pnt)
+ )))))))
+ (list in-string (car nest) depth (car (car pcol))))))
+
+(defun ruby-indent-size (pos nest)
+ (+ pos (* (if nest nest 1) ruby-indent-level)))
+
+(defun ruby-calculate-indent (&optional parse-start)
+ (save-excursion
+ (beginning-of-line)
+ (let ((indent-point (point))
+ (case-fold-search nil)
+ state bol eol
+ (indent 0))
+ (if parse-start
+ (goto-char parse-start)
+ (ruby-beginning-of-indent)
+ (setq parse-start (point)))
+ (back-to-indentation)
+ (setq indent (current-column))
+ (setq state (ruby-parse-region parse-start indent-point))
+ (cond
+ ((nth 0 state) ; within string
+ (setq indent nil)) ; do nothing
+
+ ((car (nth 1 state)) ; in paren
+ (goto-char (cdr (nth 1 state)))
+ (if (eq (car (nth 1 state)) ?\( )
+ (let ((column (current-column))
+ (s (ruby-parse-region (point) indent-point)))
+ (cond
+ ((and (nth 2 s) (> (nth 2 s) 0))
+ (goto-char (cdr (nth 1 s)))
+ (forward-word -1)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (setq indent (current-column)))))
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+ ))
+
+ ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
+ (if (null (cdr (nth 1 state)))
+ (error "invalid nest"))
+ (goto-char (cdr (nth 1 state)))
+ (forward-word -1) ; skip back a keyword
+ (cond
+ ((looking-at "do") ; iter block is a special case
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))))
+ (t
+ (setq indent (+ (current-column) ruby-indent-level)))))
+
+ ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
+ (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+
+ (cond
+ (indent
+ (goto-char indent-point)
+ (end-of-line)
+ (setq eol (point))
+ (beginning-of-line)
+ (cond
+ ((re-search-forward ruby-negative eol t)
+ (and (not (eq ?_ (char-after (match-end 0))))
+ (setq indent (- indent ruby-indent-level))))
+ ;;operator terminated lines
+ ((and
+ (save-excursion
+ (beginning-of-line)
+ (not (bobp)))
+ (or (null (car (nth 1 state))) ;not in parens
+ (and (eq (car (nth 1 state)) ?\{)
+ (save-excursion ;except non-block braces
+ (goto-char (cdr (nth 1 state)))
+ (or (bobp) (forward-char -1))
+ (not (ruby-expr-beg))))))
+ ;; goto beginning of non-empty no-comment line
+ (let (end done)
+ (while (not done)
+ (skip-chars-backward " \t\n")
+ (setq end (point))
+ (beginning-of-line)
+ (if (re-search-forward "^\\s *#" end t)
+ (beginning-of-line)
+ (setq done t))))
+ (setq bol (point))
+ (end-of-line)
+ (skip-chars-backward " \t")
+ (and (re-search-backward "#" (save-excursion
+ (beginning-of-line)
+ (point)) t)
+ (setq state (ruby-parse-region parse-start (point)))
+ (nth 0 state)
+ (goto-char (nth 0 state)))
+ (or (bobp) (forward-char -1))
+ (and
+ (or (and (looking-at ruby-symbol-re)
+ (skip-chars-backward ruby-symbol-chars)
+ (looking-at ruby-block-op-re)
+ (save-excursion
+ (goto-char (match-end 0))
+ (not (looking-at "[a-z_]"))))
+ (and (looking-at ruby-operator-re)
+ (or (not (eq ?/ (char-after (point))))
+ (null (nth 0 (ruby-parse-region parse-start (point)))))
+ (not (eq (char-after (1- (point))) ?$))
+ (or (not (eq ?| (char-after (point))))
+ (save-excursion
+ (or (eolp) (forward-char -1))
+ (and (search-backward "|")
+ (skip-chars-backward " \t\n")
+ (and (not (eolp))
+ (progn
+ (forward-char -1)
+ (not (looking-at "\\{")))
+ (progn
+ (forward-word -1)
+ (not (looking-at "do\\>[^_]")))))))))
+ (setq indent (+ indent ruby-indent-level)))))))
+ indent)))
+
+(defun ruby-electric-brace (arg)
+ (interactive "P")
+ (self-insert-command (prefix-numeric-value arg))
+ (ruby-indent-line t))
+
+(defun ruby-beginning-of-defun (&optional arg)
+ "Move backward to next beginning-of-defun.
+With argument, do this that many times.
+Returns t unless search stops due to end of buffer."
+ (interactive "p")
+ (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b")
+ nil 'move (or arg 1))
+ (progn (beginning-of-line) t)))
+
+(defun ruby-beginning-of-indent ()
+ (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b")
+ nil 'move)
+ (progn
+ (beginning-of-line)
+ t)))
+
+(defun ruby-end-of-defun (&optional arg)
+ "Move forward to next end of defun.
+An end of a defun is found by moving forward from the beginning of one."
+ (interactive "p")
+ (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)")
+ nil 'move (or arg 1))
+ (progn (beginning-of-line) t))
+ (forward-line 1))
+
+(defun ruby-move-to-block (n)
+ (let (start pos done down)
+ (setq start (ruby-calculate-indent))
+ (if (eobp)
+ nil
+ (while (and (not (bobp)) (not done))
+ (forward-line n)
+ (cond
+ ((looking-at "^$"))
+ ((looking-at "^\\s *#"))
+ (t
+ (setq pos (current-indentation))
+ (cond
+ ((< start pos)
+ (setq down t))
+ ((and down (= pos start))
+ (setq done t))
+ ((> start pos)
+ (setq done t)))))
+ (if done
+ (progn
+ (back-to-indentation)
+ (if (looking-at ruby-block-mid-re)
+ (setq done nil)))))))
+ (back-to-indentation))
+
+(defun ruby-beginning-of-block ()
+ "Move backward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block -1))
+
+(defun ruby-end-of-block ()
+ "Move forward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block 1))
+
+(defun ruby-reindent-then-newline-and-indent ()
+ (interactive "*")
+ (save-excursion
+ (delete-region (point) (progn (skip-chars-backward " \t") (point))))
+ (newline)
+ (save-excursion
+ (forward-line -1)
+ (indent-according-to-mode))
+ (indent-according-to-mode))
+
+(fset 'ruby-encomment-region (symbol-function 'comment-region))
+
+(defun ruby-decomment-region (beg end)
+ (interactive "r")
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward "^\\([ \t]*\\)#" end t)
+ (replace-match "\\1" nil nil)
+ (save-excursion
+ (ruby-indent-line)))))
+
+(defun ruby-insert-end ()
+ (interactive)
+ (insert "end")
+ (ruby-indent-line t)
+ (end-of-line))
+
+(defun ruby-mark-defun ()
+ "Put mark at end of this Ruby function, point at beginning."
+ (interactive)
+ (push-mark (point))
+ (ruby-end-of-defun)
+ (push-mark (point) nil t)
+ (ruby-beginning-of-defun)
+ (re-search-backward "^\n" (- (point) 1) t))
+
+(cond
+ ((featurep 'hilit19)
+ (hilit-set-mode-patterns
+ 'ruby-mode
+ '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
+ ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
+ ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
+ ("^\\s *#.*$" nil comment)
+ ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment)
+ ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
+ ("^\\s *\\(require\\|load\\).*$" nil include)
+ ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
+ ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun)
+ ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun)
+ ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|self\\|nil\\)\\>[^_]" 1 keyword)
+ ("\\$\\(.\\|\\sw+\\)" nil type)
+ ("[$@].[a-zA-Z_0-9]*" nil struct)
+ ("^__END__" nil label))))
+
+ ((featurep 'font-lock)
+ (or (boundp 'font-lock-variable-name-face)
+ (setq font-lock-variable-name-face font-lock-type-face))
+ (defvar ruby-font-lock-keywords
+ (list
+ (cons (concat
+ "\\(^\\|[^_:.]\\|\\.\\.\\)\\b\\("
+ (mapconcat
+ 'identity
+ '("alias"
+ "and"
+ "begin"
+ "break"
+ "case"
+ "class"
+ "def"
+ "do"
+ "elsif"
+ "else"
+ "fail"
+ "ensure"
+ "for"
+ "end"
+ "if"
+ "in"
+ "module"
+ "next"
+ "not"
+ "or"
+ "raise"
+ "redo"
+ "rescue"
+ "retry"
+ "return"
+ "then"
+ "self"
+ "super"
+ "unless"
+ "undef"
+ "until"
+ "when"
+ "while"
+ )
+ "\\|")
+ "\\)\\b")
+ 2)
+ ;; variables
+ '("\\b\\(nil\\|self\\|true\\|false\\)\\b"
+ 1 font-lock-variable-name-face)
+ ;; variables
+ '("[$@].[a-zA-Z0-9_]*"
+ 0 font-lock-variable-name-face)
+ ;; constants
+ '("\\(^\\|[^_]\\)\\b\\([A-Z]+[a-zA-Z0-9_]*\\)"
+ 2 font-lock-type-face)
+ ;; functions
+ '("^\\s *def\\s *\\<\\(\\(\\w\\|\\s_\\)+\\.\\)?\\(\\(\\w\\|\\s_\\)+\\)\\>"
+ 3 font-lock-function-name-face t))
+ "*Additional expressions to highlight in ruby mode.")
+ (if (and (>= (string-to-int emacs-version) 19)
+ (not (featurep 'xemacs)))
+ (add-hook
+ 'ruby-mode-hook
+ (lambda ()
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '((ruby-font-lock-keywords) nil nil ((?\_ . "w"))))))
+ (add-hook 'ruby-mode-hook
+ (lambda ()
+ (setq font-lock-keywords ruby-font-lock-keywords))))))
+
+(provide 'ruby-mode)
diff --git a/misc/rubydb2x.el b/misc/rubydb2x.el
new file mode 100644
index 0000000000..a74265fb0e
--- /dev/null
+++ b/misc/rubydb2x.el
@@ -0,0 +1,104 @@
+(require 'gud)
+(provide 'rubydb)
+
+;; ======================================================================
+;; rubydb functions
+
+;;; History of argument lists passed to rubydb.
+(defvar gud-rubydb-history nil)
+
+(defun gud-rubydb-massage-args (file args)
+ (cons "-I" (cons "." (cons "-r" (cons "debug" (cons file args))))))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-rubydb-marker-acc "")
+
+(defun gud-rubydb-marker-filter (string)
+ (save-match-data
+ (setq gud-marker-acc (concat gud-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-marker-acc (substring gud-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "\032.*\\'" gud-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-marker-acc
+ (substring gud-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-marker-acc)
+ gud-marker-acc ""))
+
+ output)))
+
+(defun gud-rubydb-find-file (f)
+ (find-file-noselect f))
+
+(defvar rubydb-command-name "ruby"
+ "File name for executing ruby.")
+
+;;;###autoload
+(defun rubydb (command-line)
+ "Run rubydb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run rubydb (like this): "
+ (if (consp gud-rubydb-history)
+ (car gud-rubydb-history)
+ (concat rubydb-command-name " "))
+ nil nil
+ '(gud-rubydb-history . 1))))
+
+ (gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args)
+ (gud-marker-filter . gud-rubydb-marker-filter)
+ (gud-find-file . gud-rubydb-find-file)
+ ))
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
+
+ (setq comint-prompt-regexp "^(rdb:-) ")
+ (setq paragraph-start comint-prompt-regexp)
+ (run-hooks 'rubydb-mode-hook)
+ )
diff --git a/misc/rubydb3x.el b/misc/rubydb3x.el
new file mode 100644
index 0000000000..9d4e31f90e
--- /dev/null
+++ b/misc/rubydb3x.el
@@ -0,0 +1,104 @@
+(require 'gud)
+(provide 'rubydb)
+
+;; ======================================================================
+;; rubydb functions
+
+;;; History of argument lists passed to rubydb.
+(defvar gud-rubydb-history nil)
+
+(defun gud-rubydb-massage-args (file args)
+ (cons "-r" (cons "debug" args)))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-rubydb-marker-acc "")
+
+(defun gud-rubydb-marker-filter (string)
+ (setq gud-marker-acc (concat gud-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-marker-acc (substring gud-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "\032.*\\'" gud-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-marker-acc
+ (substring gud-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-marker-acc)
+ gud-marker-acc ""))
+
+ output))
+
+(defun gud-rubydb-find-file (f)
+ (save-excursion
+ (let ((buf (find-file-noselect f)))
+ (set-buffer buf)
+ (gud-make-debug-menu)
+ buf)))
+
+(defvar rubydb-command-name "ruby"
+ "File name for executing ruby.")
+
+;;;###autoload
+(defun rubydb (command-line)
+ "Run rubydb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run rubydb (like this): "
+ (if (consp gud-rubydb-history)
+ (car gud-rubydb-history)
+ (concat rubydb-command-name " "))
+ nil nil
+ '(gud-rubydb-history . 1))))
+
+ (gud-common-init command-line 'gud-rubydb-massage-args
+ 'gud-rubydb-marker-filter 'gud-rubydb-find-file)
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
+
+ (setq comint-prompt-regexp "^(rdb:-) ")
+ (setq paragraph-start comint-prompt-regexp)
+ (run-hooks 'rubydb-mode-hook)
+ )
diff --git a/missing/dir.h b/missing/dir.h
index 34be77b9c0..2e61f04443 100644
--- a/missing/dir.h
+++ b/missing/dir.h
@@ -1,11 +1,11 @@
-/* $RCSfile: dir.h,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:10 $
+/* $RCSfile: dir.h,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:10 $
*
* (C) Copyright 1987, 1990 Diomidis Spinellis.
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: dir.h,v $
+ * $Log: dir.h,v $
* Revision 4.0.1.1 91/06/07 11:22:10 lwall
* patch4: new copyright notice
*
@@ -61,125 +61,3 @@ void rewinddir(DIR *dirp);
void closedir(DIR *dirp);
#endif /* __DIR_INCLUDED */
-/* $RCSfile: dir.h,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:10 $
- *
- * (C) Copyright 1987, 1990 Diomidis Spinellis.
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file.
- *
- * $Log: dir.h,v $
- * Revision 4.0.1.1 91/06/07 11:22:10 lwall
- * patch4: new copyright notice
- *
- * Revision 4.0 91/03/20 01:34:20 lwall
- * 4.0 baseline.
- *
- * Revision 3.0.1.1 90/03/27 16:07:08 lwall
- * patch16: MSDOS support
- *
- * Revision 1.1 90/03/18 20:32:29 dds
- * Initial revision
- *
- *
- */
-
-/*
- * defines the type returned by the directory(3) functions
- */
-
-#ifndef __DIR_INCLUDED
-#define __DIR_INCLUDED
-
-/*Directory entry size */
-#ifdef DIRSIZ
-#undef DIRSIZ
-#endif
-#define DIRSIZ(rp) (sizeof(struct direct))
-
-/*
- * Structure of a directory entry
- */
-struct direct {
- ino_t d_ino; /* inode number (not used by MS-DOS) */
- int d_namlen; /* Name length */
- char d_name[256]; /* file name */
-};
-
-struct _dir_struc { /* Structure used by dir operations */
- char *start; /* Starting position */
- char *curr; /* Current position */
- struct direct dirstr; /* Directory structure to return */
-};
-
-typedef struct _dir_struc DIR; /* Type returned by dir operations */
-
-DIR *cdecl opendir(char *filename);
-struct direct *readdir(DIR *dirp);
-long telldir(DIR *dirp);
-void seekdir(DIR *dirp,long loc);
-void rewinddir(DIR *dirp);
-void closedir(DIR *dirp);
-
-#endif /* __DIR_INCLUDED */
-/* $RCSfile: dir.h,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:10 $
- *
- * (C) Copyright 1987, 1990 Diomidis Spinellis.
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file.
- *
- * $Log: dir.h,v $
- * Revision 4.0.1.1 91/06/07 11:22:10 lwall
- * patch4: new copyright notice
- *
- * Revision 4.0 91/03/20 01:34:20 lwall
- * 4.0 baseline.
- *
- * Revision 3.0.1.1 90/03/27 16:07:08 lwall
- * patch16: MSDOS support
- *
- * Revision 1.1 90/03/18 20:32:29 dds
- * Initial revision
- *
- *
- */
-
-/*
- * defines the type returned by the directory(3) functions
- */
-
-#ifndef __DIR_INCLUDED
-#define __DIR_INCLUDED
-
-/*Directory entry size */
-#ifdef DIRSIZ
-#undef DIRSIZ
-#endif
-#define DIRSIZ(rp) (sizeof(struct direct))
-
-/*
- * Structure of a directory entry
- */
-struct direct {
- ino_t d_ino; /* inode number (not used by MS-DOS) */
- int d_namlen; /* Name length */
- char d_name[256]; /* file name */
-};
-
-struct _dir_struc { /* Structure used by dir operations */
- char *start; /* Starting position */
- char *curr; /* Current position */
- struct direct dirstr; /* Directory structure to return */
-};
-
-typedef struct _dir_struc DIR; /* Type returned by dir operations */
-
-DIR *cdecl opendir(char *filename);
-struct direct *readdir(DIR *dirp);
-long telldir(DIR *dirp);
-void seekdir(DIR *dirp,long loc);
-void rewinddir(DIR *dirp);
-void closedir(DIR *dirp);
-
-#endif /* __DIR_INCLUDED */
diff --git a/missing/file.h b/missing/file.h
index 0207dddb3a..79f5f65f5d 100644
--- a/missing/file.h
+++ b/missing/file.h
@@ -24,7 +24,6 @@
#define F_OK 0 /* does file exist */
-
#define X_OK 1 /* is it executable by caller */
#define W_OK 2 /* is it writable by caller */
#define R_OK 4 /* is it readable by caller */
diff --git a/missing/memcmp.c b/missing/memcmp.c
new file mode 100644
index 0000000000..762eaf5260
--- /dev/null
+++ b/missing/memcmp.c
@@ -0,0 +1,21 @@
+/*
+ * memcmp --- compare memories.
+ *
+ */
+
+int
+memcmp(s1,s2,len)
+ char *s1;
+ char *s2;
+ register int len;
+{
+ register unsigned char *a = (unsigned char*)s1;
+ register unsigned char *b = (unsigned char*)s2;
+ register int tmp;
+
+ while (len--) {
+ if (tmp = *a++ - *b++)
+ return tmp;
+ }
+ return 0;
+}
diff --git a/missing/strchr.c b/missing/strchr.c
new file mode 100644
index 0000000000..50714c9942
--- /dev/null
+++ b/missing/strchr.c
@@ -0,0 +1,45 @@
+/*
+ * strchr --- search a string for a character
+ *
+ * We supply this routine for those systems that aren't standard yet.
+ */
+
+#include <stdio.h>
+
+char *
+strchr(str, c)
+register const char *str, c;
+{
+ if (c == '\0') {
+ /* thanks to Mike Brennan ... */
+ do {
+ if (*str == c)
+ return (char *) str;
+ } while (*str++);
+ } else {
+ for (; *str; str++)
+ if (*str == c)
+ return (char *) str;
+ }
+
+ return NULL;
+}
+
+/*
+ * strrchr --- find the last occurrence of a character in a string
+ *
+ * We supply this routine for those systems that aren't standard yet.
+ */
+
+char *
+strrchr(str, c)
+register const char *str, c;
+{
+ register const char *save = NULL;
+
+ for (; *str; str++)
+ if (*str == c)
+ save = str;
+
+ return (char *) save;
+}
diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
new file mode 100644
index 0000000000..f0e9e8c672
--- /dev/null
+++ b/missing/vsnprintf.c
@@ -0,0 +1,1153 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/* SNPRINTF.C
+ * fjc 7-31-97 Modified by Mib Software to be a standalone snprintf.c module.
+ * http://www.mibsoftware.com
+ * Mib Software does not warrant this software any differently than the
+ * University of California, Berkeley as described above. All warranties
+ * are disclaimed. Use this software at your own risk.
+ *
+ * All code referencing FILE * functions was eliminated, since it could
+ * never be called. All header files and necessary files are collapsed
+ * into one file, internal functions are declared static. This should
+ * allow inclusion into libraries with less chance of namespace collisions.
+ *
+ * snprintf should be the only externally visible item.
+ *
+ * As of 7-31-97 FLOATING_POINT is NOT provided. The code is somewhat
+ * non-portable, so it is disabled.
+ */
+
+/* Define FLOATING_POINT to get floating point. */
+/*
+#define FLOATING_POINT
+*/
+
+#include <sys/types.h>
+#ifdef NT
+typedef unsigned int size_t;
+#endif
+#define u_long unsigned long
+#define u_short unsigned short
+#define u_int unsigned int
+
+#undef __P
+#if defined(__STDC__)
+# include <stdarg.h>
+# if !defined(__P)
+# define __P(x) x
+# endif
+#else
+# define __P(x) ()
+# if !defined(const)
+# define const
+# endif
+# include <varargs.h>
+#endif
+#ifndef _BSD_VA_LIST_
+#define _BSD_VA_LIST_ va_list
+#endif
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# ifndef LONG_MAX
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# else
+ /* assuming 32bit(2's compliment) long */
+# define LONG_MAX 2147483647
+# endif
+# endif
+#endif
+
+#if defined(__hpux) && !defined(__GNUC__)
+#define const
+#endif
+
+#if defined(sgi)
+#undef __const
+#define __const
+#endif /* People who don't like const sys_error */
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * NB: to fit things in six character monocase externals, the stdio
+ * code uses the prefix `__s' for stdio objects, typically followed
+ * by a three-character attempt at a mnemonic.
+ */
+
+/* stdio buffers */
+struct __sbuf {
+ unsigned char *_base;
+ int _size;
+};
+
+
+/*
+ * stdio state variables.
+ *
+ * The following always hold:
+ *
+ * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
+ * _lbfsize is -_bf._size, else _lbfsize is 0
+ * if _flags&__SRD, _w is 0
+ * if _flags&__SWR, _r is 0
+ *
+ * This ensures that the getc and putc macros (or inline functions) never
+ * try to write or read from a file that is in `read' or `write' mode.
+ * (Moreover, they can, and do, automatically switch from read mode to
+ * write mode, and back, on "r+" and "w+" files.)
+ *
+ * _lbfsize is used only to make the inline line-buffered output stream
+ * code as compact as possible.
+ *
+ * _ub, _up, and _ur are used when ungetc() pushes back more characters
+ * than fit in the current _bf, or when ungetc() pushes back a character
+ * that does not match the previous one in _bf. When this happens,
+ * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
+ * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
+ *
+ * NB: see WARNING above before changing the layout of this structure!
+ */
+typedef struct __sFILE {
+ unsigned char *_p; /* current position in (some) buffer */
+ int _r; /* read space left for getc() */
+ int _w; /* write space left for putc() */
+ short _flags; /* flags, below; this FILE is free if 0 */
+ short _file; /* fileno, if Unix descriptor, else -1 */
+ struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
+ int _lbfsize; /* 0 or -_bf._size, for inline putc */
+} FILE;
+
+
+#define __SLBF 0x0001 /* line buffered */
+#define __SNBF 0x0002 /* unbuffered */
+#define __SRD 0x0004 /* OK to read */
+#define __SWR 0x0008 /* OK to write */
+ /* RD and WR are never simultaneously asserted */
+#define __SRW 0x0010 /* open for reading & writing */
+#define __SEOF 0x0020 /* found EOF */
+#define __SERR 0x0040 /* found error */
+#define __SMBF 0x0080 /* _buf is from malloc */
+#define __SAPP 0x0100 /* fdopen()ed in append mode */
+#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
+#define __SOPT 0x0400 /* do fseek() optimisation */
+#define __SNPT 0x0800 /* do not do fseek() optimisation */
+#define __SOFF 0x1000 /* set iff _offset is in fact correct */
+#define __SMOD 0x2000 /* true => fgetln modified _p text */
+
+
+#define EOF (-1)
+
+
+/*
+ * The __sfoo macros are here so that we can
+ * define function versions in the C library.
+ */
+#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
+#if defined(__GNUC__) && defined(__STDC__)
+static __inline int __sputc(int _c, FILE *_p) {
+ if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
+ return (*_p->_p++ = _c);
+ else
+ return (__swbuf(_c, _p));
+}
+#else
+/*
+ * This has been tuned to generate reasonable code on the vax using pcc.
+ */
+#define __sputc(c, p) \
+ (--(p)->_w < 0 ? \
+ (p)->_w >= (p)->_lbfsize ? \
+ (*(p)->_p = (c)), *(p)->_p != '\n' ? \
+ (int)*(p)->_p++ : \
+ __swbuf('\n', p) : \
+ __swbuf((int)(c), p) : \
+ (*(p)->_p = (c), (int)*(p)->_p++))
+#endif
+
+#define __sfeof(p) (((p)->_flags & __SEOF) != 0)
+#define __sferror(p) (((p)->_flags & __SERR) != 0)
+#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
+#define __sfileno(p) ((p)->_file)
+
+#define feof(p) __sfeof(p)
+#define ferror(p) __sferror(p)
+#define clearerr(p) __sclearerr(p)
+
+#ifndef _ANSI_SOURCE
+#define fileno(p) __sfileno(p)
+#endif
+
+#ifndef lint
+#define getc(fp) __sgetc(fp)
+#define putc(x, fp) __sputc(x, fp)
+#endif /* lint */
+
+
+#if defined(__hpux) && !defined(__GNUC__)
+#include <string.h>
+#endif
+
+/*
+ * I/O descriptors for __sfvwrite().
+ */
+struct __siov {
+ void *iov_base;
+ size_t iov_len;
+};
+struct __suio {
+ struct __siov *uio_iov;
+ int uio_iovcnt;
+ int uio_resid;
+};
+
+/*
+ * Write some memory regions. Return zero on success, EOF on error.
+ *
+ * This routine is large and unsightly, but most of the ugliness due
+ * to the three different kinds of output buffering is handled here.
+ */
+static BSD__sfvwrite(fp, uio)
+ register FILE *fp;
+ register struct __suio *uio;
+{
+ register size_t len;
+ register char *p;
+ register struct __siov *iov;
+ register int w, s;
+ char *nl;
+ int nlknown, nldist;
+
+ if ((len = uio->uio_resid) == 0)
+ return (0);
+#ifndef __hpux
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+
+ iov = uio->uio_iov;
+ p = iov->iov_base;
+ len = iov->iov_len;
+ iov++;
+#define GETIOV(extra_work) \
+ while (len == 0) { \
+ extra_work; \
+ p = iov->iov_base; \
+ len = iov->iov_len; \
+ iov++; \
+ }
+ if (fp->_flags & __SNBF) {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ } else if ((fp->_flags & __SLBF) == 0) {
+ /*
+ * Fully buffered: fill partially full buffer, if any,
+ * and then flush. If there is no partial buffer, write
+ * one _bf._size byte chunk directly (without copying).
+ *
+ * String output is a special case: write as many bytes
+ * as fit, but pretend we wrote everything. This makes
+ * snprintf() return the number of bytes needed, rather
+ * than the number used, and avoids its write function
+ * (so that the write function can be invalid).
+ */
+ do {
+ GETIOV(;);
+ w = fp->_w;
+ if (fp->_flags & __SSTR) {
+ if (len < w)
+ w = len;
+ COPY(w); /* copy MIN(fp->_w,len), */
+ fp->_w -= w;
+ fp->_p += w;
+ w = len; /* but pretend copied all */
+ } else {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ }
+ p += w;
+ len -= w;
+ } while ((uio->uio_resid -= w) != 0);
+ } else {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ }
+ return (0);
+
+err:
+ fp->_flags |= __SERR;
+ return (EOF);
+}
+
+/*
+ * Actual printf innards.
+ *
+ * This code is large and complicated...
+ */
+
+#if !defined(__CYGWIN32__) && defined(__hpux) && !defined(__GNUC__)
+#include <stdlib.h>
+#endif
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ */
+static int
+BSD__sprint(fp, uio)
+ FILE *fp;
+ register struct __suio *uio;
+{
+ register int err;
+
+ if (uio->uio_resid == 0) {
+ uio->uio_iovcnt = 0;
+ return (0);
+ }
+ err = BSD__sfvwrite(fp, uio);
+ uio->uio_resid = 0;
+ uio->uio_iovcnt = 0;
+ return (err);
+}
+
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+BSD__sbprintf(fp, fmt, ap)
+ register FILE *fp;
+ const char *fmt;
+ va_list ap;
+{
+/* We don't support files. */
+ return 0;
+}
+
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static char *
+BSD__ultoa(val, endp, base, octzero, xdigs)
+ register u_long val;
+ char *endp;
+ int base, octzero;
+ char *xdigs;
+{
+ register char *cp = endp;
+ register long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ /*
+ abort();
+ */
+ break; /* fjc 7-31-97. Don't reference abort() here */
+ }
+ return (cp);
+}
+
+#ifdef FLOATING_POINT
+#include <math.h>
+#include "floatio.h"
+
+#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
+#define DEFPREC 6
+
+static char *cvt __P((double, int, int, char *, int *, int, int *));
+static int exponent __P((char *, int, int));
+
+#else /* no FLOATING_POINT */
+
+#define BUF 68
+
+#endif /* FLOATING_POINT */
+
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double; unimplemented */
+#define LONGINT 0x010 /* long integer */
+
+#ifdef _HAVE_SANE_QUAD_
+#define QUADINT 0x020 /* quad integer */
+#endif /* _HAVE_SANE_QUAD_ */
+
+#define SHORTINT 0x040 /* short integer */
+#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
+#define FPT 0x100 /* Floating point number */
+static int
+BSD_vfprintf(fp, fmt0, ap)
+ FILE *fp;
+ const char *fmt0;
+ va_list ap;
+{
+ register char *fmt; /* format string */
+ register int ch; /* character from fmt */
+ register int n; /* handy integer (short term usage) */
+ register char *cp; /* handy char pointer (short term usage) */
+ register struct __siov *iovp;/* for PRINT macro */
+ register int flags; /* flags as above */
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format (%.3d), or -1 */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+#ifdef FLOATING_POINT
+ char softsign; /* temporary negative sign for floats */
+ double _double; /* double precision arguments %[eEfgG] */
+ int expt; /* integer value of exponent */
+ int expsize; /* character count for expstr */
+ int ndig; /* actual number of digits returned by cvt */
+ char expstr[7]; /* buffer for exponent string */
+#endif
+ u_long ulval; /* integer arguments %[diouxX] */
+#ifdef _HAVE_SANE_QUAD_
+ u_quad_t uqval; /* %q integers */
+#endif /* _HAVE_SANE_QUAD_ */
+ int base; /* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int fieldsz; /* field size expanded by sign, etc */
+ int realsz; /* field size expanded by dprec */
+ int size; /* size of converted field or string */
+ char *xdigs; /* digits for [xX] conversion */
+#define NIOV 8
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
+ char ox[2]; /* space for 0x hex-prefix */
+
+ /*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+ static char blanks[PADSIZE] =
+ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+ static char zeroes[PADSIZE] =
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+ /*
+ * BEWARE, these `goto error' on error, and PAD uses `n'.
+ */
+#define PRINT(ptr, len) { \
+ iovp->iov_base = (ptr); \
+ iovp->iov_len = (len); \
+ uio.uio_resid += (len); \
+ iovp++; \
+ if (++uio.uio_iovcnt >= NIOV) { \
+ if (BSD__sprint(fp, &uio)) \
+ goto error; \
+ iovp = iov; \
+ } \
+}
+#define PAD(howmany, with) { \
+ if ((n = (howmany)) > 0) { \
+ while (n > PADSIZE) { \
+ PRINT(with, PADSIZE); \
+ n -= PADSIZE; \
+ } \
+ PRINT(with, n); \
+ } \
+}
+#define FLUSH() { \
+ if (uio.uio_resid && BSD__sprint(fp, &uio)) \
+ goto error; \
+ uio.uio_iovcnt = 0; \
+ iovp = iov; \
+}
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ (flags&LONGINT ? va_arg(ap, long) : \
+ flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
+ (long)va_arg(ap, int))
+#define UARG() \
+ (flags&LONGINT ? va_arg(ap, u_long) : \
+ flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
+ (u_long)va_arg(ap, u_int))
+
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ return (BSD__sbprintf(fp, fmt0, ap));
+
+ fmt = (char *)fmt0;
+ uio.uio_iov = iovp = iov;
+ uio.uio_resid = 0;
+ uio.uio_iovcnt = 0;
+ ret = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ /* void */;
+ if ((n = fmt - cp) != 0) {
+ PRINT(cp, n);
+ ret += n;
+ }
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ sign = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ /*
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ if ((width = va_arg(ap, int)) >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ n = va_arg(ap, int);
+ prec = n < 0 ? -1 : n;
+ goto rflag;
+ }
+ n = 0;
+ while (is_digit(ch)) {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ }
+ prec = n < 0 ? -1 : n;
+ goto reswitch;
+ case '0':
+ /*
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ width = n;
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ flags |= SHORTINT;
+ goto rflag;
+ case 'l':
+ flags |= LONGINT;
+ goto rflag;
+#ifdef _HAVE_SANE_QUAD_
+ case 'q':
+ flags |= QUADINT;
+ goto rflag;
+#endif /* _HAVE_SANE_QUAD_ */
+ case 'c':
+ *(cp = buf) = va_arg(ap, int);
+ size = 1;
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT) {
+ uqval = va_arg(ap, quad_t);
+ if ((quad_t)uqval < 0) {
+ uqval = -uqval;
+ sign = '-';
+ }
+ } else {
+#else /* _HAVE_SANE_QUAD_ */
+ {
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = SARG();
+ if ((long)ulval < 0) {
+ ulval = -ulval;
+ sign = '-';
+ }
+ }
+ base = 10;
+ goto number;
+#ifdef FLOATING_POINT
+ case 'e': /* anomalous precision */
+ case 'E':
+ prec = (prec == -1) ?
+ DEFPREC + 1 : prec + 1;
+ /* FALLTHROUGH */
+ goto fp_begin;
+ case 'f': /* always print trailing zeroes */
+ if (prec != 0)
+ flags |= ALT;
+ case 'g':
+ case 'G':
+ if (prec == -1)
+ prec = DEFPREC;
+fp_begin: _double = va_arg(ap, double);
+ /* do this before tricky precision changes */
+ if (isinf(_double)) {
+ if (_double < 0)
+ sign = '-';
+ cp = "Inf";
+ size = 3;
+ break;
+ }
+ if (isnan(_double)) {
+ cp = "NaN";
+ size = 3;
+ break;
+ }
+ flags |= FPT;
+ cp = cvt(_double, prec, flags, &softsign,
+ &expt, ch, &ndig);
+ if (ch == 'g' || ch == 'G') {
+ if (expt <= -4 || expt > prec)
+ ch = (ch == 'g') ? 'e' : 'E';
+ else
+ ch = 'g';
+ }
+ if (ch <= 'e') { /* 'e' or 'E' fmt */
+ --expt;
+ expsize = exponent(expstr, expt, ch);
+ size = expsize + ndig;
+ if (ndig > 1 || flags & ALT)
+ ++size;
+ } else if (ch == 'f') { /* f fmt */
+ if (expt > 0) {
+ size = expt;
+ if (prec || flags & ALT)
+ size += prec + 1;
+ } else /* "0.X" */
+ size = prec + 2;
+ } else if (expt >= ndig) { /* fixed g fmt */
+ size = expt;
+ if (flags & ALT)
+ ++size;
+ } else
+ size = ndig + (expt > 0 ?
+ 1 : 2 - expt);
+
+ if (softsign)
+ sign = '-';
+ break;
+#endif /* FLOATING_POINT */
+ case 'n':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ *va_arg(ap, quad_t *) = ret;
+ else if (flags & LONGINT)
+#else /* _HAVE_SANE_QUAD_ */
+ if (flags & LONGINT)
+#endif /* _HAVE_SANE_QUAD_ */
+ *va_arg(ap, long *) = ret;
+ else if (flags & SHORTINT)
+ *va_arg(ap, short *) = ret;
+ else
+ *va_arg(ap, int *) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 8;
+ goto nosign;
+ case 'p':
+ /*
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ ulval = (u_long)va_arg(ap, void *);
+ base = 16;
+ xdigs = "0123456789abcdef";
+#ifdef _HAVE_SANE_QUAD_
+ flags = (flags & ~QUADINT) | HEXPREFIX;
+#else /* _HAVE_SANE_QUAD_ */
+ flags = (flags) | HEXPREFIX;
+#endif /* _HAVE_SANE_QUAD_ */
+ ch = 'x';
+ goto nosign;
+ case 's':
+ if ((cp = va_arg(ap, char *)) == NULL)
+ cp = "(null)";
+ if (prec >= 0) {
+ /*
+ * can't use strlen; can only look for the
+ * NUL in the first `prec' characters, and
+ * strlen() will go further.
+ */
+ char *p = (char *)memchr(cp, 0, prec);
+
+ if (p != NULL) {
+ size = p - cp;
+ if (size > prec)
+ size = prec;
+ } else
+ size = prec;
+ } else
+ size = strlen(cp);
+ sign = '\0';
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 10;
+ goto nosign;
+ case 'X':
+ xdigs = "0123456789ABCDEF";
+ goto hex;
+ case 'x':
+ xdigs = "0123456789abcdef";
+hex:
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 16;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT &&
+#ifdef _HAVE_SANE_QUAD_
+ (flags & QUADINT ? uqval != 0 : ulval != 0))
+#else /* _HAVE_SANE_QUAD_ */
+ ulval != 0)
+#endif /* _HAVE_SANE_QUAD_ */
+ flags |= HEXPREFIX;
+
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ */
+ cp = buf + BUF;
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT) {
+ if (uqval != 0 || prec != 0)
+ cp = __uqtoa(uqval, cp, base,
+ flags & ALT, xdigs);
+ } else {
+#else /* _HAVE_SANE_QUAD_ */
+ {
+#endif /* _HAVE_SANE_QUAD_ */
+ if (ulval != 0 || prec != 0)
+ cp = BSD__ultoa(ulval, cp, base,
+ flags & ALT, xdigs);
+ }
+ size = buf + BUF - cp;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * fieldsz excludes decimal prec; realsz includes it.
+ */
+ fieldsz = size;
+ if (sign)
+ fieldsz++;
+ else if (flags & HEXPREFIX)
+ fieldsz += 2;
+ realsz = dprec > fieldsz ? dprec : fieldsz;
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD(width - realsz, blanks);
+
+ /* prefix */
+ if (sign) {
+ PRINT(&sign, 1);
+ } else if (flags & HEXPREFIX) {
+ ox[0] = '0';
+ ox[1] = ch;
+ PRINT(ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD(width - realsz, zeroes);
+
+ /* leading zeroes from decimal precision */
+ PAD(dprec - fieldsz, zeroes);
+
+ /* the string or number proper */
+#ifdef FLOATING_POINT
+ if ((flags & FPT) == 0) {
+ PRINT(cp, size);
+ } else { /* glue together f_p fragments */
+ if (ch >= 'f') { /* 'f' or 'g' */
+ if (_double == 0) {
+ /* kludge for __dtoa irregularity */
+ if (prec == 0 ||
+ (flags & ALT) == 0) {
+ PRINT("0", 1);
+ } else {
+ PRINT("0.", 2);
+ PAD(ndig - 1, zeroes);
+ }
+ } else if (expt <= 0) {
+ PRINT("0.", 2);
+ PAD(-expt, zeroes);
+ PRINT(cp, ndig);
+ } else if (expt >= ndig) {
+ PRINT(cp, ndig);
+ PAD(expt - ndig, zeroes);
+ if (flags & ALT)
+ PRINT(".", 1);
+ } else {
+ PRINT(cp, expt);
+ cp += expt;
+ PRINT(".", 1);
+ PRINT(cp, ndig-expt);
+ }
+ } else { /* 'e' or 'E' */
+ if (ndig > 1 || flags & ALT) {
+ ox[0] = *cp++;
+ ox[1] = '.';
+ PRINT(ox, 2);
+ if (_double || flags & ALT == 0) {
+ PRINT(cp, ndig-1);
+ } else /* 0.[0..] */
+ /* __dtoa irregularity */
+ PAD(ndig - 1, zeroes);
+ } else /* XeYYY */
+ PRINT(cp, 1);
+ PRINT(expstr, expsize);
+ }
+ }
+#else
+ PRINT(cp, size);
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD(width - realsz, blanks);
+
+ /* finally, adjust ret */
+ ret += width > realsz ? width : realsz;
+
+ FLUSH(); /* copy out the I/O vectors */
+ }
+done:
+ FLUSH();
+error:
+ return (__sferror(fp) ? EOF : ret);
+ /* NOTREACHED */
+}
+
+#ifdef FLOATING_POINT
+
+extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
+
+static char *
+cvt(value, ndigits, flags, sign, decpt, ch, length)
+ double value;
+ int ndigits, flags, *decpt, ch, *length;
+ char *sign;
+{
+ int mode, dsgn;
+ char *digits, *bp, *rve;
+
+ if (ch == 'f')
+ mode = 3;
+ else {
+ mode = 2;
+ }
+ if (value < 0) {
+ value = -value;
+ *sign = '-';
+ } else
+ *sign = '\000';
+ digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
+ if (flags & ALT) { /* Print trailing zeros */
+ bp = digits + ndigits;
+ if (ch == 'f') {
+ if (*digits == '0' && value)
+ *decpt = -ndigits + 1;
+ bp += *decpt;
+ }
+ if (value == 0) /* kludge for __dtoa irregularity */
+ rve = bp;
+ while (rve < bp)
+ *rve++ = '0';
+ }
+ *length = rve - digits;
+ return (digits);
+}
+
+static int
+exponent(p0, exp, fmtch)
+ char *p0;
+ int exp, fmtch;
+{
+ register char *p, *t;
+ char expbuf[MAXEXP];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXP;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXP; *p++ = *t++);
+ }
+ else {
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+#endif /* FLOATING_POINT */
+
+int
+vsnprintf(str, n, fmt, ap)
+ char *str;
+ size_t n;
+ const char *fmt;
+ _BSD_VA_LIST_ ap;
+{
+ int ret;
+ FILE f;
+
+ if ((int)n < 1)
+ return (EOF);
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n - 1;
+ ret = BSD_vfprintf(&f, fmt, ap);
+ *f._p = 0;
+ return (ret);
+}
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stddef.h>
+
+#if defined(__STDC__)
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+int
+#if defined(__STDC__)
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+char *str, *fmt;
+size_t n;
+va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+ FILE f;
+
+ if ((int)n < 1)
+ return (EOF);
+
+#if defined(__STDC__)
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n - 1;
+ ret = BSD_vfprintf(&f, fmt, ap);
+ *f._p = 0;
+ va_end(ap);
+ return (ret);
+}
diff --git a/missing/x68.c b/missing/x68.c
index 8fd9c3e879..dbfe662874 100644
--- a/missing/x68.c
+++ b/missing/x68.c
@@ -10,3 +10,27 @@
#include "x68/_round.c"
#include "x68/fconvert.c"
#endif
+
+/* missing some basic syscalls */
+int
+link(const char *src, const char *dst)
+{
+ return symlink(src, dst);
+}
+
+#include <time.h>
+#include <sys/time.h>
+
+struct timezone {
+ int tz_minueswest;
+ int tz_dsttime;
+};
+
+int
+gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ tv->tv_sec = (long)time((time_t*)0);
+ tv->tv_usec = 0;
+
+ return 0;
+}
diff --git a/mkconfig.rb b/mkconfig.rb
index 5232943d8d..903cddad3c 100644
--- a/mkconfig.rb
+++ b/mkconfig.rb
@@ -26,14 +26,14 @@ v_others = []
File.foreach "config.status" do |$_|
next if /^#/
if /^s%@program_transform_name@%s,(.*)%g$/
- ptn = $1.sub(/\$\$/, '$').split(/,/)
+ ptn = $1.sub(/\$\$/, '$').split(/,/) #'
v_fast << " CONFIG[\"ruby_install_name\"] = \"" + "ruby".sub(ptn[0],ptn[1]) + "\"\n"
elsif /^s%@(\w+)@%(.*)%g/
name = $1
val = $2 || ""
next if name =~ /^(INSTALL|DEFS|configure_input|srcdir|top_srcdir)$/
v = " CONFIG[\"" + name + "\"] = " +
- val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$\{?([^}]*)\}?/) {
+ val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$[{(]?([^})]+)[})]?/) {
"\#{CONFIG[\\\"#{$1}\\\"]}"
} + "\n"
if fast[name]
diff --git a/node.h b/node.h
index cdb354c007..c1923fba75 100644
--- a/node.h
+++ b/node.h
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 28 15:14:02 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -41,11 +41,14 @@ enum node_type {
NODE_MASGN,
NODE_LASGN,
NODE_DASGN,
+ NODE_DASGN_PUSH,
NODE_GASGN,
NODE_IASGN,
NODE_CASGN,
NODE_OP_ASGN1,
NODE_OP_ASGN2,
+ NODE_OP_ASGN_AND,
+ NODE_OP_ASGN_OR,
NODE_CALL,
NODE_FCALL,
NODE_VCALL,
@@ -63,8 +66,6 @@ enum node_type {
NODE_CVAR,
NODE_NTH_REF,
NODE_BACK_REF,
- NODE_MATCH_REF,
- NODE_LASTLINE,
NODE_MATCH,
NODE_MATCH2,
NODE_MATCH3,
@@ -77,6 +78,10 @@ enum node_type {
NODE_DREGX,
NODE_DREGX_ONCE,
NODE_ARGS,
+ NODE_ARGSCAT,
+ NODE_RESTARGS,
+ NODE_BLOCK_ARG,
+ NODE_BLOCK_PASS,
NODE_DEFN,
NODE_DEFS,
NODE_ALIAS,
@@ -86,6 +91,7 @@ enum node_type {
NODE_MODULE,
NODE_SCLASS,
NODE_COLON2,
+ NODE_COLON3,
NODE_CNAME,
NODE_CREF,
NODE_DOT2,
@@ -98,13 +104,15 @@ enum node_type {
NODE_TRUE,
NODE_FALSE,
NODE_DEFINED,
- NODE_TAG,
NODE_NEWLINE,
NODE_POSTEXE,
+#ifdef C_ALLOCA
+ NODE_ALLOCA,
+#endif
};
typedef struct RNode {
- UINT flags;
+ unsigned long flags;
char *nd_file;
union {
struct RNode *node;
@@ -131,13 +139,15 @@ typedef struct RNode {
#define RNODE(obj) (R_CAST(RNode)(obj))
-#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0x7f)
+#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0xff)
#define nd_set_type(n,t) \
RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK))
-#define nd_line(n) (((RNODE(n))->flags>>18)&0x3fff)
+#define NODE_LSHIFT (FL_USHIFT+8)
+#define NODE_LMASK ((1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
+#define nd_line(n) (((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK)
#define nd_set_line(n,l) \
- RNODE(n)->flags=((RNODE(n)->flags&~(-1<<18))|(((l)&0x7fff)<<18))
+ RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
#define nd_head u1.node
#define nd_alen u2.argc
@@ -185,8 +195,8 @@ typedef struct RNode {
#define nd_noex u1.id
#define nd_defn u3.node
+#define nd_old u1.id
#define nd_new u2.id
-#define nd_old u3.id
#define nd_cfnc u1.cfunc
#define nd_argc u2.argc
@@ -200,114 +210,133 @@ typedef struct RNode {
#define nd_beg u1.node
#define nd_end u2.node
#define nd_state u3.state
-#define nd_rval u3.value
+#define nd_rval u2.value
#define nd_nth u2.argc
#define nd_tag u1.id
-#define nd_tlev u3.cnt
#define nd_tval u2.value
-#define NEW_METHOD(n,x) node_newnode(NODE_METHOD,x,n,0)
-#define NEW_FBODY(n,i,o) node_newnode(NODE_FBODY,n,i,o)
-#define NEW_DEFN(i,a,d,p) node_newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d))
-#define NEW_DEFS(r,i,a,d) node_newnode(NODE_DEFS,r,i,NEW_RFUNC(a,d))
-#define NEW_CFUNC(f,c) node_newnode(NODE_CFUNC,f,c,0)
+#define NEW_METHOD(n,x) rb_node_newnode(NODE_METHOD,x,n,0)
+#define NEW_FBODY(n,i,o) rb_node_newnode(NODE_FBODY,n,i,o)
+#define NEW_DEFN(i,a,d,p) rb_node_newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d))
+#define NEW_DEFS(r,i,a,d) rb_node_newnode(NODE_DEFS,r,i,NEW_RFUNC(a,d))
+#define NEW_CFUNC(f,c) rb_node_newnode(NODE_CFUNC,f,c,0)
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
-#define NEW_SCOPE(b) node_newnode(NODE_SCOPE,local_tbl(),(b),cur_cref)
-#define NEW_BLOCK(a) node_newnode(NODE_BLOCK,a,0,0)
-#define NEW_IF(c,t,e) node_newnode(NODE_IF,c,t,e)
-#define NEW_UNLESS(c,t,e) node_newnode(NODE_IF,c,e,t)
-#define NEW_CASE(h,b) node_newnode(NODE_CASE,h,b,0)
-#define NEW_WHEN(c,t,e) node_newnode(NODE_WHEN,c,t,e)
-#define NEW_OPT_N(b) node_newnode(NODE_OPT_N,0,b,0)
-#define NEW_WHILE(c,b,n) node_newnode(NODE_WHILE,c,b,n)
-#define NEW_UNTIL(c,b,n) node_newnode(NODE_UNTIL,c,b,n)
-#define NEW_FOR(v,i,b) node_newnode(NODE_FOR,v,b,i)
-#define NEW_ITER(v,i,b) node_newnode(NODE_ITER,v,b,i)
-#define NEW_BREAK() node_newnode(NODE_BREAK,0,0,0)
-#define NEW_NEXT() node_newnode(NODE_NEXT,0,0,0)
-#define NEW_REDO() node_newnode(NODE_REDO,0,0,0)
-#define NEW_RETRY() node_newnode(NODE_RETRY,0,0,0)
-#define NEW_BEGIN(b) node_newnode(NODE_BEGIN,0,b,0)
-#define NEW_RESCUE(b,res) node_newnode(NODE_RESCUE,b,res,0)
-#define NEW_RESBODY(a,ex,n) node_newnode(NODE_RESBODY,n,ex,a)
-#define NEW_ENSURE(b,en) node_newnode(NODE_ENSURE,b,0,en)
-#define NEW_RET(s) node_newnode(NODE_RETURN,s,0,0)
-#define NEW_YIELD(a) node_newnode(NODE_YIELD,a,0,0)
+#define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),cur_cref,(b))
+#define NEW_BLOCK(a) rb_node_newnode(NODE_BLOCK,a,0,0)
+#ifdef NOBLOCK_RECUR
+#define NEW_IF(c,t,e) block_append(c,rb_node_newnode(NODE_IF,0,t,e))
+#else
+#define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e)
+#endif
+#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
+#ifdef NOBLOCK_RECUR
+#define NEW_CASE(h,b) block_append(h,rb_node_newnode(NODE_CASE,0,b,0))
+#else
+#define NEW_CASE(h,b) rb_node_newnode(NODE_CASE,h,b,0)
+#endif
+#define NEW_WHEN(c,t,e) rb_node_newnode(NODE_WHEN,c,t,e)
+#define NEW_OPT_N(b) rb_node_newnode(NODE_OPT_N,0,b,0)
+#define NEW_WHILE(c,b,n) rb_node_newnode(NODE_WHILE,c,b,n)
+#define NEW_UNTIL(c,b,n) rb_node_newnode(NODE_UNTIL,c,b,n)
+#define NEW_FOR(v,i,b) rb_node_newnode(NODE_FOR,v,b,i)
+#define NEW_ITER(v,i,b) rb_node_newnode(NODE_ITER,v,b,i)
+#define NEW_BREAK() rb_node_newnode(NODE_BREAK,0,0,0)
+#define NEW_NEXT() rb_node_newnode(NODE_NEXT,0,0,0)
+#define NEW_REDO() rb_node_newnode(NODE_REDO,0,0,0)
+#define NEW_RETRY() rb_node_newnode(NODE_RETRY,0,0,0)
+#define NEW_BEGIN(b) rb_node_newnode(NODE_BEGIN,0,b,0)
+#define NEW_RESCUE(b,res,e) rb_node_newnode(NODE_RESCUE,b,res,e)
+#define NEW_RESBODY(a,ex,n) rb_node_newnode(NODE_RESBODY,n,ex,a)
+#define NEW_ENSURE(b,en) rb_node_newnode(NODE_ENSURE,b,0,en)
+#define NEW_RETURN(s) rb_node_newnode(NODE_RETURN,s,0,0)
+#define NEW_YIELD(a) rb_node_newnode(NODE_YIELD,a,0,0)
#define NEW_LIST(a) NEW_ARRAY(a)
-#define NEW_ARRAY(a) node_newnode(NODE_ARRAY,a,1,0)
-#define NEW_ZARRAY() node_newnode(NODE_ZARRAY,0,0,0)
-#define NEW_HASH(a) node_newnode(NODE_HASH,a,0,0)
-#define NEW_NOT(a) node_newnode(NODE_NOT,0,a,0)
-#define NEW_MASGN(l,r) node_newnode(NODE_MASGN,l,0,r)
-#define NEW_GASGN(v,val) node_newnode(NODE_GASGN,v,val,rb_global_entry(v))
-#define NEW_LASGN(v,val) node_newnode(NODE_LASGN,v,val,local_cnt(v))
-#define NEW_DASGN(v,val) node_newnode(NODE_DASGN,v,val,0);
-#define NEW_IASGN(v,val) node_newnode(NODE_IASGN,v,val,0)
-#define NEW_CASGN(v,val) node_newnode(NODE_CASGN,v,val,0)
-#define NEW_OP_ASGN1(p,id,a) node_newnode(NODE_OP_ASGN1,p,id,a)
-#define NEW_OP_ASGN2(r,i,o,val) node_newnode(NODE_OP_ASGN2,r,val,NEW_OP_ASGN3(i,o))
-#define NEW_OP_ASGN3(i,o) node_newnode(NODE_OP_ASGN2,i,o,0)
-#define NEW_GVAR(v) node_newnode(NODE_GVAR,v,0,rb_global_entry(v))
-#define NEW_LVAR(v) node_newnode(NODE_LVAR,v,0,local_cnt(v))
-#define NEW_DVAR(v) node_newnode(NODE_DVAR,v,0,0);
-#define NEW_IVAR(v) node_newnode(NODE_IVAR,v,0,0)
-#define NEW_CVAR(v) node_newnode(NODE_CVAR,v,0,0)
-#define NEW_NTH_REF(n) node_newnode(NODE_NTH_REF,0,n,local_cnt('~'))
-#define NEW_BACK_REF(n) node_newnode(NODE_BACK_REF,0,n,local_cnt('~'))
-#define NEW_MATCH(c) node_newnode(NODE_MATCH,c,0,0)
-#define NEW_MATCH2(n1,n2) node_newnode(NODE_MATCH2,n1,n2,0)
-#define NEW_MATCH3(r,n2) node_newnode(NODE_MATCH3,r,n2,0)
-#define NEW_LIT(l) node_newnode(NODE_LIT,l,0,0)
-#define NEW_STR(s) node_newnode(NODE_STR,s,0,0)
-#define NEW_DSTR(s) node_newnode(NODE_DSTR,s,0,0)
-#define NEW_XSTR(s) node_newnode(NODE_XSTR,s,0,0)
-#define NEW_DXSTR(s) node_newnode(NODE_DXSTR,s,0,0)
-#define NEW_EVSTR(s,l) node_newnode(NODE_EVSTR,str_new(s,l),0,0)
-#define NEW_CALL(r,m,a) node_newnode(NODE_CALL,r,m,a)
-#define NEW_FCALL(m,a) node_newnode(NODE_FCALL,0,m,a)
-#define NEW_VCALL(m) node_newnode(NODE_VCALL,0,m,0)
-#define NEW_SUPER(a) node_newnode(NODE_SUPER,0,0,a)
-#define NEW_ZSUPER() node_newnode(NODE_ZSUPER,0,0,0)
-#define NEW_ARGS(f,o,r) node_newnode(NODE_ARGS,o,r,f)
-#define NEW_ALIAS(n,o) node_newnode(NODE_ALIAS,0,n,o)
-#define NEW_VALIAS(n,o) node_newnode(NODE_VALIAS,0,n,o)
-#define NEW_UNDEF(i) node_newnode(NODE_UNDEF,0,i,0)
-#define NEW_CLASS(n,b,s) node_newnode(NODE_CLASS,n,NEW_CBODY(b),s)
-#define NEW_SCLASS(r,b) node_newnode(NODE_SCLASS,r,NEW_CBODY(b),0)
-#define NEW_MODULE(n,b) node_newnode(NODE_MODULE,n,NEW_CBODY(b),0)
-#define NEW_COLON2(c,i) node_newnode(NODE_COLON2,c,i,0)
-#define NEW_CREF0() (cur_cref=node_newnode(NODE_CREF,RNODE(the_frame->cbase)->nd_clss,0,0))
-#define NEW_CREF() (cur_cref=node_newnode(NODE_CREF,0,0,cur_cref))
+#define NEW_ARRAY(a) rb_node_newnode(NODE_ARRAY,a,1,0)
+#define NEW_ZARRAY() rb_node_newnode(NODE_ZARRAY,0,0,0)
+#define NEW_HASH(a) rb_node_newnode(NODE_HASH,a,0,0)
+#define NEW_NOT(a) rb_node_newnode(NODE_NOT,0,a,0)
+#define NEW_MASGN(l,r) rb_node_newnode(NODE_MASGN,l,0,r)
+#define NEW_GASGN(v,val) rb_node_newnode(NODE_GASGN,v,val,rb_global_entry(v))
+#define NEW_LASGN(v,val) rb_node_newnode(NODE_LASGN,v,val,local_cnt(v))
+#define NEW_DASGN(v,val) rb_node_newnode(NODE_DASGN,v,val,0);
+#define NEW_DASGN_PUSH(v,val) rb_node_newnode(NODE_DASGN_PUSH,v,val,0);
+#define NEW_IASGN(v,val) rb_node_newnode(NODE_IASGN,v,val,0)
+#define NEW_CASGN(v,val) rb_node_newnode(NODE_CASGN,v,val,0)
+#define NEW_OP_ASGN1(p,id,a) rb_node_newnode(NODE_OP_ASGN1,p,id,a)
+#define NEW_OP_ASGN2(r,i,o,val) rb_node_newnode(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o))
+#define NEW_OP_ASGN22(i,o) rb_node_newnode(NODE_OP_ASGN2,i,o,rb_id_attrset(i))
+#define NEW_OP_ASGN_OR(i,val) rb_node_newnode(NODE_OP_ASGN_OR,i,val,0)
+#define NEW_OP_ASGN_AND(i,val) rb_node_newnode(NODE_OP_ASGN_AND,i,val,0)
+#define NEW_GVAR(v) rb_node_newnode(NODE_GVAR,v,0,rb_global_entry(v))
+#define NEW_LVAR(v) rb_node_newnode(NODE_LVAR,v,0,local_cnt(v))
+#define NEW_DVAR(v) rb_node_newnode(NODE_DVAR,v,0,0);
+#define NEW_IVAR(v) rb_node_newnode(NODE_IVAR,v,0,0)
+#define NEW_CVAR(v) rb_node_newnode(NODE_CVAR,v,0,0)
+#define NEW_NTH_REF(n) rb_node_newnode(NODE_NTH_REF,0,n,local_cnt('~'))
+#define NEW_BACK_REF(n) rb_node_newnode(NODE_BACK_REF,0,n,local_cnt('~'))
+#define NEW_MATCH(c) rb_node_newnode(NODE_MATCH,c,0,0)
+#define NEW_MATCH2(n1,n2) rb_node_newnode(NODE_MATCH2,n1,n2,0)
+#define NEW_MATCH3(r,n2) rb_node_newnode(NODE_MATCH3,r,n2,0)
+#define NEW_LIT(l) rb_node_newnode(NODE_LIT,l,0,0)
+#define NEW_STR(s) rb_node_newnode(NODE_STR,s,0,0)
+#define NEW_DSTR(s) rb_node_newnode(NODE_DSTR,s,0,0)
+#define NEW_XSTR(s) rb_node_newnode(NODE_XSTR,s,0,0)
+#define NEW_DXSTR(s) rb_node_newnode(NODE_DXSTR,s,0,0)
+#define NEW_EVSTR(s,l) rb_node_newnode(NODE_EVSTR,rb_str_new(s,l),0,0)
+#ifdef NOBLOCK_RECUR_incomplete
+#define NEW_CALL(r,m,a) block_append(r,rb_node_newnode(NODE_CALL,0,m,a))
+#else
+#define NEW_CALL(r,m,a) rb_node_newnode(NODE_CALL,r,m,a)
+#endif
+#define NEW_FCALL(m,a) rb_node_newnode(NODE_FCALL,0,m,a)
+#define NEW_VCALL(m) rb_node_newnode(NODE_VCALL,0,m,0)
+#define NEW_SUPER(a) rb_node_newnode(NODE_SUPER,0,0,a)
+#define NEW_ZSUPER() rb_node_newnode(NODE_ZSUPER,0,0,0)
+#define NEW_ARGS(f,o,r) rb_node_newnode(NODE_ARGS,o,r,f)
+#define NEW_ARGSCAT(a,b) rb_node_newnode(NODE_ARGSCAT,a,b,0)
+#define NEW_RESTARGS(a) rb_node_newnode(NODE_RESTARGS,a,0,0)
+#define NEW_BLOCK_ARG(v) rb_node_newnode(NODE_BLOCK_ARG,v,0,local_cnt(v))
+#define NEW_BLOCK_PASS(b) rb_node_newnode(NODE_BLOCK_PASS,0,b,0)
+#define NEW_ALIAS(n,o) rb_node_newnode(NODE_ALIAS,o,n,0)
+#define NEW_VALIAS(n,o) rb_node_newnode(NODE_VALIAS,o,n,0)
+#define NEW_UNDEF(i) rb_node_newnode(NODE_UNDEF,0,i,0)
+#define NEW_CLASS(n,b,s) rb_node_newnode(NODE_CLASS,n,NEW_CBODY(b),(s))
+#define NEW_SCLASS(r,b) rb_node_newnode(NODE_SCLASS,r,NEW_CBODY(b),0)
+#define NEW_MODULE(n,b) rb_node_newnode(NODE_MODULE,n,NEW_CBODY(b),0)
+#define NEW_COLON2(c,i) rb_node_newnode(NODE_COLON2,c,i,0)
+#define NEW_COLON3(i) rb_node_newnode(NODE_COLON3,0,i,0)
+#define NEW_CREF0() (cur_cref=rb_node_newnode(NODE_CREF,RNODE(ruby_frame->cbase)->nd_clss,0,0))
+#define NEW_CREF() (cur_cref=rb_node_newnode(NODE_CREF,0,0,cur_cref))
#define NEW_CBODY(b) (cur_cref->nd_body=NEW_SCOPE(b),cur_cref)
-#define NEW_DOT2(b,e) node_newnode(NODE_DOT2,b,e,0)
-#define NEW_DOT3(b,e) node_newnode(NODE_DOT3,b,e,0)
-#define NEW_ATTRSET(a) node_newnode(NODE_ATTRSET,a,0,0)
-#define NEW_SELF() node_newnode(NODE_SELF,0,0,0)
-#define NEW_NIL() node_newnode(NODE_NIL,0,0,0)
-#define NEW_TRUE() node_newnode(NODE_TRUE,0,0,0)
-#define NEW_FALSE() node_newnode(NODE_FALSE,0,0,0)
-#define NEW_DEFINED(e) node_newnode(NODE_DEFINED,e,0,0)
-#define NEW_NEWLINE(n) node_newnode(NODE_NEWLINE,0,0,n)
+#define NEW_DOT2(b,e) rb_node_newnode(NODE_DOT2,b,e,0)
+#define NEW_DOT3(b,e) rb_node_newnode(NODE_DOT3,b,e,0)
+#define NEW_ATTRSET(a) rb_node_newnode(NODE_ATTRSET,a,0,0)
+#define NEW_SELF() rb_node_newnode(NODE_SELF,0,0,0)
+#define NEW_NIL() rb_node_newnode(NODE_NIL,0,0,0)
+#define NEW_TRUE() rb_node_newnode(NODE_TRUE,0,0,0)
+#define NEW_FALSE() rb_node_newnode(NODE_FALSE,0,0,0)
+#define NEW_DEFINED(e) rb_node_newnode(NODE_DEFINED,e,0,0)
+#define NEW_NEWLINE(n) rb_node_newnode(NODE_NEWLINE,0,0,n)
#define NEW_PREEXE(b) NEW_SCOPE(b)
-#define NEW_POSTEXE() node_newnode(NODE_POSTEXE,0,0,0)
+#define NEW_POSTEXE() rb_node_newnode(NODE_POSTEXE,0,0,0)
-NODE *node_newnode();
+NODE *rb_node_newnode();
VALUE rb_method_booundp();
-#define NOEX_PUBLIC 0
-#define NOEX_PRIVATE 1
+#define NOEX_PUBLIC 0
+#define NOEX_UNDEF 1
+#define NOEX_CFUNC 1
+#define NOEX_PRIVATE 2
+#define NOEX_PROTECTED 4
-NODE *compile_string _((char *, char *, int));
-NODE *compile_file _((char *, VALUE, int));
+NODE *rb_compile_cstr _((char *, char *, int));
+NODE *rb_compile_string _((char *, VALUE));
+NODE *rb_compile_file _((char *, VALUE, int));
void rb_add_method _((VALUE, ID, NODE *, int));
-void rb_remove_method _((VALUE, ID));
-NODE *node_newnode();
-
-enum node_type nodetype _((NODE *));
-int nodeline _((NODE *));
+NODE *rb_node_newnode();
struct global_entry *rb_global_entry _((ID));
VALUE rb_gvar_get _((struct global_entry *));
diff --git a/numeric.c b/numeric.c
index b0d5f7f522..e8ea6075a9 100644
--- a/numeric.c
+++ b/numeric.c
@@ -6,58 +6,95 @@
$Date$
created at: Fri Aug 13 18:33:09 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <math.h>
+#include <stdio.h>
static ID coerce;
static ID to_i;
-VALUE cNumeric;
-VALUE cFloat;
-VALUE cInteger;
-VALUE cFixnum;
+VALUE rb_cNumeric;
+VALUE rb_cFloat;
+VALUE rb_cInteger;
+VALUE rb_cFixnum;
-VALUE eZeroDiv;
+VALUE rb_eZeroDiv;
ID rb_frame_last_func();
-VALUE float_new();
-double big2dbl();
+VALUE rb_float_new();
+double rb_big2dbl();
void
-num_zerodiv()
+rb_num_zerodiv()
{
- Raise(eZeroDiv, "divided by 0");
+ rb_raise(rb_eZeroDiv, "divided by 0");
}
static VALUE
num_coerce(x, y)
VALUE x, y;
{
- return assoc_new(rb_Float(x),rb_Float(y));
+ if (CLASS_OF(x) == CLASS_OF(y))
+ return rb_assoc_new(x, y);
+ return rb_assoc_new(rb_Float(x), rb_Float(y));
}
-VALUE
-num_coerce_bin(x, y)
- VALUE x, y;
+static VALUE
+coerce_body(x)
+ VALUE *x;
+{
+ return rb_funcall(x[1], coerce, 1, x[0]);
+}
+
+static VALUE
+coerce_rescue(x)
+ VALUE *x;
+{
+ rb_raise(rb_eTypeError, "%s can't be coerced into %s",
+ rb_special_const_p(x[1])?
+ STR2CSTR(rb_inspect(x[1])):
+ rb_class2name(CLASS_OF(x[1])),
+ rb_class2name(CLASS_OF(x[0])));
+}
+
+static void
+do_coerce(x, y)
+ VALUE *x, *y;
{
VALUE ary;
+ VALUE a[2];
- ary = rb_funcall(y, coerce, 1, x);
+ a[0] = *x; a[1] = *y;
+ ary = rb_rescue(coerce_body, (VALUE)a, coerce_rescue, (VALUE)a);
if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
- TypeError("coerce must return [x, y]");
+ rb_raise(rb_eTypeError, "coerce must return [x, y]");
}
- x = RARRAY(ary)->ptr[0];
- y = RARRAY(ary)->ptr[1];
+ *x = RARRAY(ary)->ptr[0];
+ *y = RARRAY(ary)->ptr[1];
+}
+VALUE
+rb_num_coerce_bin(x, y)
+ VALUE x, y;
+{
+ do_coerce(&x, &y);
return rb_funcall(x, rb_frame_last_func(), 1, y);
}
static VALUE
+num_clone(x)
+ VALUE x;
+{
+ /* Numerics are immutable values, which need not to copy */
+ return x;
+}
+
+static VALUE
num_uplus(num)
VALUE num;
{
@@ -68,17 +105,12 @@ static VALUE
num_uminus(num)
VALUE num;
{
- VALUE ary, x, y;
+ VALUE zero;
- ary = rb_funcall(num, coerce, 1, INT2FIX(0));
- if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
- TypeError("coerce must return [x, y]");
- }
-
- x = RARRAY(ary)->ptr[0];
- y = RARRAY(ary)->ptr[1];
+ zero = INT2FIX(0);
+ do_coerce(&zero, &num);
- return rb_funcall(x, '-', 1, y);
+ return rb_funcall(zero, '-', 1, num);
}
static VALUE
@@ -92,49 +124,56 @@ num_divmod(x, y)
double d = floor(RFLOAT(div)->value);
if (RFLOAT(div)->value > d) {
- div = float_new(d);
+ div = rb_float_new(d);
}
}
mod = rb_funcall(x, '%', 1, y);
- return assoc_new(div, mod);
+ return rb_assoc_new(div, mod);
}
static VALUE
num_int_p(num)
VALUE num;
{
- return FALSE;
+ return Qfalse;
}
static VALUE
-num_chr(num)
+num_abs(num)
VALUE num;
{
- char c;
- INT i = NUM2INT(num);
+ if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
+ return rb_funcall(num, rb_intern("-@"), 0);
+ }
+ return num;
+}
- if (i < 0 || 0xff < i)
- Fail("%d out of char range", i);
- c = i;
- return str_new(&c, 1);
+static VALUE
+num_zero_p(num)
+ VALUE num;
+{
+ if (RTEST(rb_equal(num, INT2FIX(0)))) {
+ return Qtrue;
+ }
+ return Qfalse;
}
static VALUE
-num_abs(num)
+num_nonzero_p(num)
VALUE num;
{
- if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
- return rb_funcall(num, rb_intern("-@"), 0);
+ if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
+ return Qfalse;
}
return num;
}
VALUE
-float_new(d)
+rb_float_new(d)
double d;
{
NEWOBJ(flt, struct RFloat);
- OBJSETUP(flt, cFloat, T_FLOAT);
+ OBJSETUP(flt, rb_cFloat, T_FLOAT);
flt->value = d;
return (VALUE)flt;
@@ -160,21 +199,21 @@ flo_to_s(flt)
}
}
- return str_new2(buf);
+ return rb_str_new2(buf);
}
static VALUE
flo_coerce(x, y)
VALUE x, y;
{
- return assoc_new(rb_Float(y), x);
+ return rb_assoc_new(rb_Float(y), x);
}
static VALUE
flo_uminus(flt)
VALUE flt;
{
- return float_new(-RFLOAT(flt)->value);
+ return rb_float_new(-RFLOAT(flt)->value);
}
static VALUE
@@ -183,15 +222,13 @@ flo_plus(x, y)
{
switch (TYPE(y)) {
case T_FIXNUM:
- return float_new(RFLOAT(x)->value + (double)FIX2INT(y));
+ return rb_float_new(RFLOAT(x)->value + (double)FIX2LONG(y));
case T_BIGNUM:
- return float_new(RFLOAT(x)->value + big2dbl(y));
+ return rb_float_new(RFLOAT(x)->value + rb_big2dbl(y));
case T_FLOAT:
- return float_new(RFLOAT(x)->value + RFLOAT(y)->value);
- case T_STRING:
- return str_plus(obj_as_string(x), y);
+ return rb_float_new(RFLOAT(x)->value + RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -201,13 +238,13 @@ flo_minus(x, y)
{
switch (TYPE(y)) {
case T_FIXNUM:
- return float_new(RFLOAT(x)->value - (double)FIX2INT(y));
+ return rb_float_new(RFLOAT(x)->value - (double)FIX2LONG(y));
case T_BIGNUM:
- return float_new(RFLOAT(x)->value - big2dbl(y));
+ return rb_float_new(RFLOAT(x)->value - rb_big2dbl(y));
case T_FLOAT:
- return float_new(RFLOAT(x)->value - RFLOAT(y)->value);
+ return rb_float_new(RFLOAT(x)->value - RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -217,15 +254,13 @@ flo_mul(x, y)
{
switch (TYPE(y)) {
case T_FIXNUM:
- return float_new(RFLOAT(x)->value * (double)FIX2INT(y));
+ return rb_float_new(RFLOAT(x)->value * (double)FIX2LONG(y));
case T_BIGNUM:
- return float_new(RFLOAT(x)->value * big2dbl(y));
+ return rb_float_new(RFLOAT(x)->value * rb_big2dbl(y));
case T_FLOAT:
- return float_new(RFLOAT(x)->value * RFLOAT(y)->value);
- case T_STRING:
- return str_times(y, INT2FIX((int)RFLOAT(x)->value));
+ return rb_float_new(RFLOAT(x)->value * RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -233,73 +268,92 @@ static VALUE
flo_div(x, y)
VALUE x, y;
{
- INT f_y;
+ long f_y;
double d;
switch (TYPE(y)) {
case T_FIXNUM:
- f_y = FIX2INT(y);
- if (f_y == 0) num_zerodiv();
- return float_new(RFLOAT(x)->value / (double)f_y);
+ f_y = FIX2LONG(y);
+ if (f_y == 0) rb_num_zerodiv();
+ return rb_float_new(RFLOAT(x)->value / (double)f_y);
case T_BIGNUM:
- d = big2dbl(y);
- if (d == 0.0) num_zerodiv();
- return float_new(RFLOAT(x)->value / d);
+ d = rb_big2dbl(y);
+ if (d == 0.0) rb_num_zerodiv();
+ return rb_float_new(RFLOAT(x)->value / d);
case T_FLOAT:
- if (RFLOAT(y)->value == 0.0) num_zerodiv();
- return float_new(RFLOAT(x)->value / RFLOAT(y)->value);
+ if (RFLOAT(y)->value == 0.0) rb_num_zerodiv();
+ return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
static VALUE
-flo_mod(x, y)
+flo_modulo(x, y, modulo)
VALUE x, y;
+ int modulo;
{
- double value;
+ double value, result;
switch (TYPE(y)) {
case T_FIXNUM:
- value = (double)FIX2INT(y);
+ value = (double)FIX2LONG(y);
break;
case T_BIGNUM:
- value = big2dbl(y);
+ value = rb_big2dbl(y);
break;
case T_FLOAT:
value = RFLOAT(y)->value;
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
+
#ifdef HAVE_FMOD
- value = fmod(RFLOAT(x)->value, value);
+ result = fmod(RFLOAT(x)->value, value);
#else
{
double value1 = RFLOAT(x)->value;
double value2;
modf(value1/value, &value2);
- value = value1 - value2 * value;
+ result = value1 - value2 * value;
}
#endif
+ if (modulo &&
+ (RFLOAT(x)->value < 0.0) != (result < 0.0) && result != 0.0) {
+ result += value;
+ }
+ return rb_float_new(result);
+}
- return float_new(value);
+static VALUE
+flo_mod(x, y)
+ VALUE x, y;
+{
+ return flo_modulo(x,y,1);
}
-VALUE
+static VALUE
+flo_remainder(x, y)
+ VALUE x, y;
+{
+ return flo_modulo(x,y,0);
+}
+
+static VALUE
flo_pow(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
case T_FIXNUM:
- return float_new(pow(RFLOAT(x)->value, (double)FIX2INT(y)));
+ return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
case T_BIGNUM:
- return float_new(pow(RFLOAT(x)->value, big2dbl(y)));
+ return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
case T_FLOAT:
- return float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
+ return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -307,7 +361,7 @@ static VALUE
num_eql(x, y)
VALUE x, y;
{
- if (TYPE(x) != TYPE(y)) return FALSE;
+ if (TYPE(x) != TYPE(y)) return Qfalse;
return rb_equal(x, y);
}
@@ -326,12 +380,12 @@ flo_eq(x, y)
{
switch (TYPE(y)) {
case T_FIXNUM:
- if (RFLOAT(x)->value == FIX2INT(y)) return TRUE;
- return FALSE;
+ if (RFLOAT(x)->value == FIX2LONG(y)) return Qtrue;
+ return Qfalse;
case T_BIGNUM:
- return (RFLOAT(x)->value == big2dbl(y))?TRUE:FALSE;
+ return (RFLOAT(x)->value == rb_big2dbl(y))?Qtrue:Qfalse;
case T_FLOAT:
- return (RFLOAT(x)->value == RFLOAT(y)->value)?TRUE:FALSE;
+ return (RFLOAT(x)->value == RFLOAT(y)->value)?Qtrue:Qfalse;
default:
return num_equal(x, y);
}
@@ -363,11 +417,11 @@ flo_cmp(x, y)
a = RFLOAT(x)->value;
switch (TYPE(y)) {
case T_FIXNUM:
- b = (double)FIX2INT(y);
+ b = (double)FIX2LONG(y);
break;
case T_BIGNUM:
- b = big2dbl(y);
+ b = rb_big2dbl(y);
break;
case T_FLOAT:
@@ -375,7 +429,7 @@ flo_cmp(x, y)
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
if (a == b) return INT2FIX(0);
if (a > b) return INT2FIX(1);
@@ -383,13 +437,117 @@ flo_cmp(x, y)
}
static VALUE
+flo_gt(x, y)
+ VALUE x, y;
+{
+ double a, b;
+
+ a = RFLOAT(x)->value;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ b = (double)FIX2LONG(y);
+ break;
+
+ case T_BIGNUM:
+ b = rb_big2dbl(y);
+ break;
+
+ case T_FLOAT:
+ b = RFLOAT(y)->value;
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ return (a > b)?Qtrue:Qfalse;
+}
+
+static VALUE
+flo_ge(x, y)
+ VALUE x, y;
+{
+ double a, b;
+
+ a = RFLOAT(x)->value;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ b = (double)FIX2LONG(y);
+ break;
+
+ case T_BIGNUM:
+ b = rb_big2dbl(y);
+ break;
+
+ case T_FLOAT:
+ b = RFLOAT(y)->value;
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ return (a >= b)?Qtrue:Qfalse;
+}
+
+static VALUE
+flo_lt(x, y)
+ VALUE x, y;
+{
+ double a, b;
+
+ a = RFLOAT(x)->value;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ b = (double)FIX2LONG(y);
+ break;
+
+ case T_BIGNUM:
+ b = rb_big2dbl(y);
+ break;
+
+ case T_FLOAT:
+ b = RFLOAT(y)->value;
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ return (a < b)?Qtrue:Qfalse;
+}
+
+static VALUE
+flo_le(x, y)
+ VALUE x, y;
+{
+ double a, b;
+
+ a = RFLOAT(x)->value;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ b = (double)FIX2LONG(y);
+ break;
+
+ case T_BIGNUM:
+ b = rb_big2dbl(y);
+ break;
+
+ case T_FLOAT:
+ b = RFLOAT(y)->value;
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ return (a <= b)?Qtrue:Qfalse;
+}
+
+static VALUE
flo_eql(x, y)
VALUE x, y;
{
if (TYPE(y) == T_FLOAT) {
- if (RFLOAT(x)->value == RFLOAT(y)->value) return TRUE;
+ if (RFLOAT(x)->value == RFLOAT(y)->value) return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -397,10 +555,55 @@ flo_to_i(num)
VALUE num;
{
double f = RFLOAT(num)->value;
- INT val;
+ long val;
+
+ if (!FIXABLE(f)) {
+ return rb_dbl2big(f);
+ }
+ val = f;
+ return INT2FIX(val);
+}
+
+static VALUE
+flo_floor(num)
+ VALUE num;
+{
+ double f = floor(RFLOAT(num)->value);
+ long val;
+
+ if (!FIXABLE(f)) {
+ return rb_dbl2big(f);
+ }
+ val = f;
+ return INT2FIX(val);
+}
+
+static VALUE
+flo_ceil(num)
+ VALUE num;
+{
+ double f = ceil(RFLOAT(num)->value);
+ long val;
+
+ if (!FIXABLE(f)) {
+ return rb_dbl2big(f);
+ }
+ val = f;
+ return INT2FIX(val);
+}
+
+static VALUE
+flo_round(num)
+ VALUE num;
+{
+ double f = RFLOAT(num)->value;
+ long val;
+
+ if (f > 0.0) f = floor(f+0.5);
+ if (f < 0.0) f = ceil(f-0.5);
if (!FIXABLE(f)) {
- return dbl2big(f);
+ return rb_dbl2big(f);
}
val = f;
return INT2FIX(val);
@@ -418,7 +621,17 @@ flo_abs(flt)
VALUE flt;
{
double val = fabs(RFLOAT(flt)->value);
- return float_new(val);
+ return rb_float_new(val);
+}
+
+static VALUE
+flo_zero_p(num)
+ VALUE num;
+{
+ if (RFLOAT(num)->value == 0.0) {
+ return Qtrue;
+ }
+ return Qfalse;
}
static VALUE
@@ -432,64 +645,116 @@ static VALUE
fail_to_integer(val)
VALUE val;
{
- TypeError("failed to convert %s into Integer",
- rb_class2name(CLASS_OF(val)));
+ rb_raise(rb_eTypeError, "failed to convert %s into Integer",
+ rb_class2name(CLASS_OF(val)));
}
-int
-num2int(val)
+long
+rb_num2long(val)
VALUE val;
{
- if (NIL_P(val)) return 0;
+ if (NIL_P(val)) {
+ rb_raise(rb_eTypeError, "no implicit conversion from nil");
+ }
- switch (TYPE(val)) {
- case T_FIXNUM:
- return FIX2INT(val);
+ if (FIXNUM_P(val)) return FIX2LONG(val);
+ switch (TYPE(val)) {
case T_FLOAT:
- if (RFLOAT(val)->value <= (double) LONG_MAX
- && RFLOAT(val)->value >= (double) LONG_MIN) {
- return (int)(RFLOAT(val)->value);
+ if (RFLOAT(val)->value <= (double)LONG_MAX
+ && RFLOAT(val)->value >= (double)LONG_MIN) {
+ return (long)(RFLOAT(val)->value);
}
else {
- Fail("float %g out of rang of integer", RFLOAT(val)->value);
+ rb_raise(rb_eTypeError, "float %g out of rang of integer",
+ RFLOAT(val)->value);
}
case T_BIGNUM:
- return big2int(val);
+ return rb_big2long(val);
+
+ case T_STRING:
+ rb_raise(rb_eTypeError, "no implicit conversion from string");
+ return Qnil; /* not reached */
default:
val = rb_rescue(to_integer, val, fail_to_integer, val);
- return NUM2INT(val);
+ if (!rb_obj_is_kind_of(val, rb_cInteger)) {
+ rb_raise(rb_eTypeError, "`to_i' need to return integer");
+ }
+ return NUM2LONG(val);
}
}
-VALUE
-num2fix(val)
+unsigned long
+rb_num2ulong(val)
VALUE val;
{
- INT v;
+ if (TYPE(val) == T_BIGNUM) {
+ return rb_big2ulong(val);
+ }
+ return (unsigned long)rb_num2long(val);
+}
- if (NIL_P(val)) return INT2FIX(0);
- switch (TYPE(val)) {
- case T_FIXNUM:
- return val;
+#if SIZEOF_INT < SIZEOF_LONG
+int
+rb_num2int(val)
+ VALUE val;
+{
+ long num = rb_num2long(val);
- case T_FLOAT:
- case T_BIGNUM:
- default:
- v = num2int(val);
- if (!FIXABLE(v))
- Fail("integer %d out of range of Fixnum", v);
- return INT2FIX(v);
+ if (num < INT_MIN || INT_MAX < num) {
+ rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
}
+ return (int)num;
+}
+
+int
+rb_fix2int(val)
+ VALUE val;
+{
+ long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
+
+ if (num < INT_MIN || INT_MAX < num) {
+ rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
+ }
+ return (int)num;
+}
+#else
+int
+rb_num2int(val)
+ VALUE val;
+{
+ return rb_num2long(val);
+}
+
+int
+rb_fix2int(val)
+ VALUE val;
+{
+ return FIX2INT(val);
+}
+#endif
+
+VALUE
+rb_num2fix(val)
+ VALUE val;
+{
+ long v;
+
+ if (FIXNUM_P(val)) return val;
+
+ v = rb_num2long(val);
+ if (!FIXABLE(v))
+ rb_raise(rb_eTypeError, "integer %d out of range of fixnum", v);
+ return INT2FIX(v);
}
static VALUE
int_int_p(num)
VALUE num;
{
- return TRUE;
+ return Qtrue;
}
static VALUE
@@ -500,14 +765,27 @@ int_succ(num)
}
static VALUE
+int_chr(num)
+ VALUE num;
+{
+ char c;
+ long i = NUM2LONG(num);
+
+ if (i < 0 || 0xff < i)
+ rb_raise(rb_eTypeError, "%d out of char range", i);
+ c = i;
+ return rb_str_new(&c, 1);
+}
+
+static VALUE
fix_uminus(num)
VALUE num;
{
- return int2inum(-FIX2INT(num));
+ return rb_int2inum(-FIX2LONG(num));
}
VALUE
-fix2str(x, base)
+rb_fix2str(x, base)
VALUE x;
int base;
{
@@ -517,130 +795,140 @@ fix2str(x, base)
if (base == 10) fmt[2] = 'd';
else if (base == 16) fmt[2] = 'x';
else if (base == 8) fmt[2] = 'o';
- else Fatal("fixnum cannot treat base %d", base);
+ else rb_fatal("fixnum cannot treat base %d", base);
- sprintf(buf, fmt, FIX2INT(x));
- return str_new2(buf);
+ sprintf(buf, fmt, FIX2LONG(x));
+ return rb_str_new2(buf);
}
-VALUE
+static VALUE
fix_to_s(in)
VALUE in;
{
- return fix2str(in, 10);
+ return rb_fix2str(in, 10);
}
static VALUE
fix_plus(x, y)
VALUE x, y;
{
- switch (TYPE(y)) {
- case T_FIXNUM:
- {
- INT a, b, c;
- VALUE r;
-
- a = FIX2INT(x);
- b = FIX2INT(y);
- c = a + b;
- r = INT2FIX(c);
-
- if (FIX2INT(r) != c) {
- r = big_plus(int2big(a), int2big(b));
- }
- return r;
+ if (FIXNUM_P(y)) {
+ long a, b, c;
+ VALUE r;
+
+ a = FIX2LONG(x);
+ b = FIX2LONG(y);
+ c = a + b;
+ r = INT2FIX(c);
+
+ if (FIX2LONG(r) != c) {
+ r = rb_big_plus(rb_int2big(a), rb_int2big(b));
}
- case T_FLOAT:
- return float_new((double)FIX2INT(x) + RFLOAT(y)->value);
- default:
- return num_coerce_bin(x, y);
+ return r;
+ }
+ if (TYPE(y) == T_FLOAT) {
+ return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
}
+ return rb_num_coerce_bin(x, y);
}
static VALUE
fix_minus(x, y)
VALUE x, y;
{
- switch (TYPE(y)) {
- case T_FIXNUM:
- {
- INT a, b, c;
- VALUE r;
-
- a = FIX2INT(x);
- b = FIX2INT(y);
- c = a - b;
- r = INT2FIX(c);
-
- if (FIX2INT(r) != c) {
- r = big_minus(int2big(a), int2big(b));
- }
- return r;
+ if (FIXNUM_P(y)) {
+ long a, b, c;
+ VALUE r;
+
+ a = FIX2LONG(x);
+ b = FIX2LONG(y);
+ c = a - b;
+ r = INT2FIX(c);
+
+ if (FIX2LONG(r) != c) {
+ r = rb_big_minus(rb_int2big(a), rb_int2big(b));
}
- case T_FLOAT:
- return float_new((double)FIX2INT(x) - RFLOAT(y)->value);
- default:
- return num_coerce_bin(x, y);
+ return r;
+ }
+ if (TYPE(y) == T_FLOAT) {
+ return rb_float_new((double)FIX2LONG(x) - RFLOAT(y)->value);
}
+ return rb_num_coerce_bin(x, y);
}
static VALUE
fix_mul(x, y)
VALUE x, y;
{
- switch (TYPE(y)) {
- case T_FIXNUM:
- {
- INT a, b, c;
- VALUE r;
+ if (FIXNUM_P(y)) {
+ long a, b, c;
+ VALUE r;
- a = FIX2INT(x);
- if (a == 0) return x;
+ a = FIX2LONG(x);
+ if (a == 0) return x;
- b = FIX2INT(y);
- c = a * b;
- r = INT2FIX(c);
+ b = FIX2LONG(y);
+ c = a * b;
+ r = INT2FIX(c);
- if (FIX2INT(r) != c || c/a != b) {
- r = big_mul(int2big(a), int2big(b));
- }
- return r;
+ if (FIX2LONG(r) != c || c/a != b) {
+ r = rb_big_mul(rb_int2big(a), rb_int2big(b));
}
- case T_FLOAT:
- return float_new((double)FIX2INT(x) * RFLOAT(y)->value);
- default:
- return num_coerce_bin(x, y);
+ return r;
+ }
+ if (TYPE(y) == T_FLOAT) {
+ return rb_float_new((double)FIX2LONG(x) * RFLOAT(y)->value);
}
+ return rb_num_coerce_bin(x, y);
}
static VALUE
fix_div(x, y)
VALUE x, y;
{
- INT i;
+ if (FIXNUM_P(y)) {
+ long i;
- if (TYPE(y) == T_FIXNUM) {
- i = FIX2INT(y);
- if (i == 0) num_zerodiv();
- i = FIX2INT(x)/i;
+ i = FIX2LONG(y);
+ if (i == 0) rb_num_zerodiv();
+ i = FIX2LONG(x)/i;
return INT2FIX(i);
}
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
static VALUE
-fix_mod(x, y)
+fix_modulo(x, y, modulo)
VALUE x, y;
{
- INT i;
+ long i;
- if (TYPE(y) == T_FIXNUM) {
- i = FIX2INT(y);
- if (i == 0) num_zerodiv();
- i = FIX2INT(x)%i;
+ if (FIXNUM_P(y)) {
+ i = FIX2LONG(y);
+ if (i == 0) rb_num_zerodiv();
+ i = FIX2LONG(x)%i;
+ if (modulo &&
+ (FIX2LONG(x) < 0) != (FIX2LONG(y) < 0) &&
+ i != 0) {
+ i += FIX2LONG(y);
+ }
return INT2FIX(i);
}
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
+}
+
+static VALUE
+fix_mod(x, y)
+ VALUE x, y;
+{
+ return fix_modulo(x, y, 1);
+}
+
+static VALUE
+fix_remainder(x, y)
+ VALUE x, y;
+{
+ return fix_modulo(x, y, 0);
}
static VALUE
@@ -648,20 +936,20 @@ fix_pow(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a, b;
+ long a, b;
- b = FIX2INT(y);
+ b = FIX2LONG(y);
if (b == 0) return INT2FIX(1);
- a = FIX2INT(x);
+ a = FIX2LONG(x);
if (b > 0) {
- return big_pow(int2big(a), y);
+ return rb_big_pow(rb_int2big(a), y);
}
- return float_new(pow((double)a, (double)b));
+ return rb_float_new(pow((double)a, (double)b));
}
else if (NIL_P(y)) {
return INT2FIX(1);
}
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
static VALUE
@@ -669,7 +957,7 @@ fix_equal(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- return (FIX2INT(x) == FIX2INT(y))?TRUE:FALSE;
+ return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse;
}
else {
return num_equal(x, y);
@@ -681,14 +969,14 @@ fix_cmp(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a = FIX2INT(x), b = FIX2INT(y);
+ long a = FIX2LONG(x), b = FIX2LONG(y);
if (a == b) return INT2FIX(0);
if (a > b) return INT2FIX(1);
return INT2FIX(-1);
}
else {
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -697,13 +985,13 @@ fix_gt(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a = FIX2INT(x), b = FIX2INT(y);
+ long a = FIX2LONG(x), b = FIX2LONG(y);
- if (a > b) return TRUE;
- return FALSE;
+ if (a > b) return Qtrue;
+ return Qfalse;
}
else {
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -712,13 +1000,13 @@ fix_ge(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a = FIX2INT(x), b = FIX2INT(y);
+ long a = FIX2LONG(x), b = FIX2LONG(y);
- if (a >= b) return TRUE;
- return FALSE;
+ if (a >= b) return Qtrue;
+ return Qfalse;
}
else {
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -727,13 +1015,13 @@ fix_lt(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a = FIX2INT(x), b = FIX2INT(y);
+ long a = FIX2LONG(x), b = FIX2LONG(y);
- if (a < b) return TRUE;
- return FALSE;
+ if (a < b) return Qtrue;
+ return Qfalse;
}
else {
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -742,13 +1030,13 @@ fix_le(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- INT a = FIX2INT(x), b = FIX2INT(y);
+ long a = FIX2LONG(x), b = FIX2LONG(y);
- if (a <= b) return TRUE;
- return FALSE;
+ if (a <= b) return Qtrue;
+ return Qfalse;
}
else {
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
@@ -756,10 +1044,10 @@ static VALUE
fix_rev(num)
VALUE num;
{
- unsigned long val = FIX2UINT(num);
+ unsigned long val = FIX2ULONG(num);
val = ~val;
- return INT2FIX(val);
+ return rb_int2inum(val);
}
static VALUE
@@ -769,10 +1057,10 @@ fix_and(x, y)
long val;
if (TYPE(y) == T_BIGNUM) {
- return big_and(y, x);
+ return rb_big_and(y, x);
}
- val = NUM2INT(x) & NUM2INT(y);
- return int2inum(val);
+ val = FIX2LONG(x) & NUM2LONG(y);
+ return rb_int2inum(val);
}
static VALUE
@@ -782,10 +1070,10 @@ fix_or(x, y)
long val;
if (TYPE(y) == T_BIGNUM) {
- return big_or(y, x);
+ return rb_big_or(y, x);
}
- val = NUM2INT(x) | NUM2INT(y);
- return INT2FIX(val);
+ val = FIX2LONG(x) | NUM2LONG(y);
+ return rb_int2inum(val);
}
static VALUE
@@ -795,26 +1083,27 @@ fix_xor(x, y)
long val;
if (TYPE(y) == T_BIGNUM) {
- return big_xor(y, x);
+ return rb_big_xor(y, x);
}
- val = NUM2INT(x) ^ NUM2INT(y);
- return INT2FIX(val);
+ val = FIX2LONG(x) ^ NUM2LONG(y);
+ return rb_int2inum(val);
}
static VALUE
fix_lshift(x, y)
VALUE x, y;
{
- long val, width;
+ long val;
+ int width;
- val = NUM2INT(x);
+ val = NUM2LONG(x);
width = NUM2INT(y);
if (width > (sizeof(VALUE)*CHAR_BIT-1)
- || (unsigned)val>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
- return big_lshift(int2big(val), y);
+ || ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
+ return rb_big_lshift(rb_int2big(val), y);
}
val = val << width;
- return int2inum(val);
+ return rb_int2inum(val);
}
static VALUE
@@ -823,9 +1112,9 @@ fix_rshift(x, y)
{
long i, val;
- i = NUM2INT(y);
- if (y < 32) {
- val = RSHIFT(FIX2INT(x), i);
+ i = NUM2LONG(y);
+ if (i < sizeof(long) * 8) {
+ val = RSHIFT(FIX2LONG(x), i);
return INT2FIX(val);
}
@@ -836,8 +1125,8 @@ static VALUE
fix_aref(fix, idx)
VALUE fix, idx;
{
- unsigned long val = FIX2INT(fix);
- int i = FIX2INT(idx);
+ unsigned long val = FIX2LONG(fix);
+ int i = FIX2LONG(idx);
if (i < 0 || sizeof(VALUE)*CHAR_BIT-1 < i)
return INT2FIX(0);
@@ -859,27 +1148,27 @@ fix_to_f(num)
{
double val;
- val = (double)FIX2INT(num);
+ val = (double)FIX2LONG(num);
- return float_new(val);
+ return rb_float_new(val);
}
static VALUE
fix_type(fix)
VALUE fix;
{
- return cFixnum;
+ return rb_cFixnum;
}
static VALUE
fix_abs(fix)
VALUE fix;
{
- INT i = FIX2INT(fix);
+ long i = FIX2LONG(fix);
if (i < 0) i = -i;
- return int2inum(i);
+ return rb_int2inum(i);
}
static VALUE
@@ -887,7 +1176,7 @@ fix_id2name(fix)
VALUE fix;
{
char *name = rb_id2name(FIX2UINT(fix));
- if (name) return str_new2(name);
+ if (name) return rb_str_new2(name);
return Qnil;
}
@@ -895,20 +1184,20 @@ static VALUE
fix_succ(fix)
VALUE fix;
{
- INT i = FIX2INT(fix) + 1;
+ long i = FIX2LONG(fix) + 1;
- return int2inum(i);
+ return rb_int2inum(i);
}
static VALUE
fix_size(fix)
VALUE fix;
{
- return INT2FIX(sizeof(INT));
+ return INT2FIX(sizeof(long));
}
-VALUE
-num_upto(from, to)
+static VALUE
+int_upto(from, to)
VALUE from, to;
{
VALUE i = from;
@@ -922,7 +1211,7 @@ num_upto(from, to)
}
static VALUE
-num_downto(from, to)
+int_downto(from, to)
VALUE from, to;
{
VALUE i = from;
@@ -936,14 +1225,14 @@ num_downto(from, to)
}
static VALUE
-num_step(from, to, step)
+int_step(from, to, step)
VALUE from, to, step;
{
VALUE i = from;
ID cmp;
- if (step == INT2FIX(0)) {
- ArgError("step cannot be 0");
+ if (NUM2INT(step) == 0) {
+ rb_raise(rb_eArgError, "step cannot be 0");
}
if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
@@ -961,7 +1250,7 @@ num_step(from, to, step)
}
static VALUE
-num_dotimes(num)
+int_dotimes(num)
VALUE num;
{
VALUE i = INT2FIX(0);
@@ -974,30 +1263,37 @@ num_dotimes(num)
return num;
}
-VALUE
+static VALUE
fix_upto(from, to)
VALUE from, to;
{
- INT i, end;
+ long i, end;
- if (!FIXNUM_P(to)) return num_upto(from, to);
- end = FIX2INT(to);
- for (i = FIX2INT(from); i <= end; i++) {
+ if (!FIXNUM_P(to)) return int_upto(from, to);
+ end = FIX2LONG(to);
+ for (i = FIX2LONG(from); i <= end; i++) {
rb_yield(INT2FIX(i));
}
return from;
}
+VALUE
+rb_fix_upto(from, to)
+ VALUE from, to;
+{
+ return fix_upto(from, to);
+}
+
static VALUE
fix_downto(from, to)
VALUE from, to;
{
- INT i, end;
+ long i, end;
- if (!FIXNUM_P(to)) return num_downto(from, to);
- end = FIX2INT(to);
- for (i=FIX2INT(from); i >= end; i--) {
+ if (!FIXNUM_P(to)) return int_downto(from, to);
+ end = FIX2LONG(to);
+ for (i=FIX2LONG(from); i >= end; i--) {
rb_yield(INT2FIX(i));
}
@@ -1008,24 +1304,24 @@ static VALUE
fix_step(from, to, step)
VALUE from, to, step;
{
- INT i, end, diff;
+ long i, end, diff;
if (!FIXNUM_P(to) || !FIXNUM_P(step))
- return num_step(from, to, step);
+ return int_step(from, to, step);
- end = FIX2INT(to);
- diff = FIX2INT(step);
+ end = FIX2LONG(to);
+ diff = FIX2LONG(step);
if (diff == 0) {
- ArgError("step cannot be 0");
+ rb_raise(rb_eArgError, "step cannot be 0");
}
else if (diff > 0) {
- for (i=FIX2INT(from); i <= end; i+=diff) {
+ for (i=FIX2LONG(from); i <= end; i+=diff) {
rb_yield(INT2FIX(i));
}
}
else {
- for (i=FIX2INT(from); i >= end; i+=diff) {
+ for (i=FIX2LONG(from); i >= end; i+=diff) {
rb_yield(INT2FIX(i));
}
}
@@ -1036,17 +1332,24 @@ static VALUE
fix_dotimes(num)
VALUE num;
{
- INT i, end;
+ long i, end;
- end = FIX2INT(num);
+ end = FIX2LONG(num);
for (i=0; i<end; i++) {
rb_yield(INT2FIX(i));
}
return num;
}
-extern VALUE mComparable;
-extern VALUE eException;
+static VALUE
+fix_zero_p(num)
+ VALUE num;
+{
+ if (FIX2LONG(num) == 0) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
void
Init_Numeric()
@@ -1054,93 +1357,110 @@ Init_Numeric()
coerce = rb_intern("coerce");
to_i = rb_intern("to_i");
- eZeroDiv = rb_define_class("ZeroDivisionError", eException);
- cNumeric = rb_define_class("Numeric", cObject);
-
- rb_include_module(cNumeric, mComparable);
- rb_define_method(cNumeric, "coerce", num_coerce, 1);
-
- rb_define_method(cNumeric, "+@", num_uplus, 0);
- rb_define_method(cNumeric, "-@", num_uminus, 0);
- rb_define_method(cNumeric, "eql?", num_eql, 1);
- rb_define_method(cNumeric, "divmod", num_divmod, 1);
- rb_define_method(cNumeric, "abs", num_abs, 0);
-
- rb_define_method(cNumeric, "upto", num_upto, 1);
- rb_define_method(cNumeric, "downto", num_downto, 1);
- rb_define_method(cNumeric, "step", num_step, 2);
- rb_define_method(cNumeric, "times", num_dotimes, 0);
- rb_define_method(cNumeric, "integer?", num_int_p, 0);
- rb_define_method(cNumeric, "chr", num_chr, 0);
-
- cInteger = rb_define_class("Integer", cNumeric);
- rb_define_method(cInteger, "integer?", int_int_p, 0);
- rb_define_method(cInteger, "succ", int_succ, 0);
-
- cFixnum = rb_define_class("Fixnum", cInteger);
-
- rb_undef_method(CLASS_OF(cFixnum), "new");
-
- rb_define_method(cFixnum, "to_s", fix_to_s, 0);
- rb_define_method(cFixnum, "type", fix_type, 0);
-
- rb_define_method(cFixnum, "id2name", fix_id2name, 0);
-
- rb_define_method(cFixnum, "-@", fix_uminus, 0);
- rb_define_method(cFixnum, "+", fix_plus, 1);
- rb_define_method(cFixnum, "-", fix_minus, 1);
- rb_define_method(cFixnum, "*", fix_mul, 1);
- rb_define_method(cFixnum, "/", fix_div, 1);
- rb_define_method(cFixnum, "%", fix_mod, 1);
- rb_define_method(cFixnum, "**", fix_pow, 1);
-
- rb_define_method(cFixnum, "abs", fix_abs, 0);
-
- rb_define_method(cFixnum, "==", fix_equal, 1);
- rb_define_method(cFixnum, "<=>", fix_cmp, 1);
- rb_define_method(cFixnum, ">", fix_gt, 1);
- rb_define_method(cFixnum, ">=", fix_ge, 1);
- rb_define_method(cFixnum, "<", fix_lt, 1);
- rb_define_method(cFixnum, "<=", fix_le, 1);
-
- rb_define_method(cFixnum, "~", fix_rev, 0);
- rb_define_method(cFixnum, "&", fix_and, 1);
- rb_define_method(cFixnum, "|", fix_or, 1);
- rb_define_method(cFixnum, "^", fix_xor, 1);
- rb_define_method(cFixnum, "[]", fix_aref, 1);
-
- rb_define_method(cFixnum, "<<", fix_lshift, 1);
- rb_define_method(cFixnum, ">>", fix_rshift, 1);
-
- rb_define_method(cFixnum, "to_i", fix_to_i, 0);
- rb_define_method(cFixnum, "to_f", fix_to_f, 0);
-
- rb_define_method(cFixnum, "succ", fix_succ, 0);
- rb_define_method(cFixnum, "size", fix_size, 0);
-
- rb_define_method(cFixnum, "upto", fix_upto, 1);
- rb_define_method(cFixnum, "downto", fix_downto, 1);
- rb_define_method(cFixnum, "step", fix_step, 2);
- rb_define_method(cFixnum, "times", fix_dotimes, 0);
-
- cFloat = rb_define_class("Float", cNumeric);
-
- rb_undef_method(CLASS_OF(cFloat), "new");
-
- rb_define_method(cFloat, "to_s", flo_to_s, 0);
- rb_define_method(cFloat, "coerce", flo_coerce, 1);
- rb_define_method(cFloat, "-@", flo_uminus, 0);
- rb_define_method(cFloat, "+", flo_plus, 1);
- rb_define_method(cFloat, "-", flo_minus, 1);
- rb_define_method(cFloat, "*", flo_mul, 1);
- rb_define_method(cFloat, "/", flo_div, 1);
- rb_define_method(cFloat, "%", flo_mod, 1);
- rb_define_method(cFloat, "**", flo_pow, 1);
- rb_define_method(cFloat, "==", flo_eq, 1);
- rb_define_method(cFloat, "<=>", flo_cmp, 1);
- rb_define_method(cFloat, "eql?", flo_eql, 1);
- rb_define_method(cFloat, "hash", flo_hash, 0);
- rb_define_method(cFloat, "to_i", flo_to_i, 0);
- rb_define_method(cFloat, "to_f", flo_to_f, 0);
- rb_define_method(cFloat, "abs", flo_abs, 0);
+ rb_eZeroDiv = rb_define_class("ZeroDivisionError", rb_eStandardError);
+ rb_cNumeric = rb_define_class("Numeric", rb_cObject);
+
+ rb_include_module(rb_cNumeric, rb_mComparable);
+ rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
+ rb_define_method(rb_cNumeric, "clone", num_clone, 0);
+
+ rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
+ rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
+ rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
+ rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
+ rb_define_method(rb_cNumeric, "abs", num_abs, 0);
+
+ rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
+ rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
+ rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
+
+ rb_cInteger = rb_define_class("Integer", rb_cNumeric);
+ rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
+ rb_define_method(rb_cInteger, "upto", int_upto, 1);
+ rb_define_method(rb_cInteger, "downto", int_downto, 1);
+ rb_define_method(rb_cInteger, "step", int_step, 2);
+ rb_define_method(rb_cInteger, "times", int_dotimes, 0);
+ rb_define_method(rb_cInteger, "succ", int_succ, 0);
+ rb_define_method(rb_cInteger, "next", int_succ, 0);
+ rb_define_method(rb_cInteger, "chr", int_chr, 0);
+
+ rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
+
+ rb_undef_method(CLASS_OF(rb_cFixnum), "new");
+
+ rb_define_method(rb_cFixnum, "to_s", fix_to_s, 0);
+ rb_define_method(rb_cFixnum, "type", fix_type, 0);
+
+ rb_define_method(rb_cFixnum, "id2name", fix_id2name, 0);
+
+ rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
+ rb_define_method(rb_cFixnum, "+", fix_plus, 1);
+ rb_define_method(rb_cFixnum, "-", fix_minus, 1);
+ rb_define_method(rb_cFixnum, "*", fix_mul, 1);
+ rb_define_method(rb_cFixnum, "/", fix_div, 1);
+ rb_define_method(rb_cFixnum, "%", fix_mod, 1);
+ rb_define_method(rb_cFixnum, "remainder", fix_remainder, 1);
+ rb_define_method(rb_cFixnum, "**", fix_pow, 1);
+
+ rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
+
+ rb_define_method(rb_cFixnum, "==", fix_equal, 1);
+ rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
+ rb_define_method(rb_cFixnum, ">", fix_gt, 1);
+ rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
+ rb_define_method(rb_cFixnum, "<", fix_lt, 1);
+ rb_define_method(rb_cFixnum, "<=", fix_le, 1);
+
+ rb_define_method(rb_cFixnum, "~", fix_rev, 0);
+ rb_define_method(rb_cFixnum, "&", fix_and, 1);
+ rb_define_method(rb_cFixnum, "|", fix_or, 1);
+ rb_define_method(rb_cFixnum, "^", fix_xor, 1);
+ rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
+
+ rb_define_method(rb_cFixnum, "<<", fix_lshift, 1);
+ rb_define_method(rb_cFixnum, ">>", fix_rshift, 1);
+
+ rb_define_method(rb_cFixnum, "to_i", fix_to_i, 0);
+ rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
+
+ rb_define_method(rb_cFixnum, "succ", fix_succ, 0);
+ rb_define_method(rb_cFixnum, "next", fix_succ, 0);
+ rb_define_method(rb_cFixnum, "size", fix_size, 0);
+
+ rb_define_method(rb_cFixnum, "upto", fix_upto, 1);
+ rb_define_method(rb_cFixnum, "downto", fix_downto, 1);
+ rb_define_method(rb_cFixnum, "step", fix_step, 2);
+ rb_define_method(rb_cFixnum, "times", fix_dotimes, 0);
+ rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
+
+ rb_cFloat = rb_define_class("Float", rb_cNumeric);
+
+ rb_undef_method(CLASS_OF(rb_cFloat), "new");
+
+ rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
+ rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
+ rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
+ rb_define_method(rb_cFloat, "+", flo_plus, 1);
+ rb_define_method(rb_cFloat, "-", flo_minus, 1);
+ rb_define_method(rb_cFloat, "*", flo_mul, 1);
+ rb_define_method(rb_cFloat, "/", flo_div, 1);
+ rb_define_method(rb_cFloat, "%", flo_mod, 1);
+ rb_define_method(rb_cFloat, "remainder", flo_remainder, 1);
+ rb_define_method(rb_cFloat, "**", flo_pow, 1);
+ rb_define_method(rb_cFloat, "==", flo_eq, 1);
+ rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
+ rb_define_method(rb_cFloat, ">", flo_gt, 1);
+ rb_define_method(rb_cFloat, ">=", flo_ge, 1);
+ rb_define_method(rb_cFloat, "<", flo_lt, 1);
+ rb_define_method(rb_cFloat, "<=", flo_le, 1);
+ rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
+ rb_define_method(rb_cFloat, "hash", flo_hash, 0);
+ rb_define_method(rb_cFloat, "to_i", flo_to_i, 0);
+ rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
+ rb_define_method(rb_cFloat, "abs", flo_abs, 0);
+ rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
+
+ rb_define_method(rb_cFloat, "floor", flo_floor, 0);
+ rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
+ rb_define_method(rb_cFloat, "round", flo_round, 0);
}
diff --git a/object.c b/object.c
index 2e614b3a41..15e757d054 100644
--- a/object.c
+++ b/object.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Jul 15 12:01:24 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -14,22 +14,18 @@
#include "st.h"
#include <stdio.h>
-VALUE mKernel;
-VALUE cObject;
-VALUE cModule;
-VALUE cClass;
-extern VALUE cFixnum;
-VALUE cData;
+VALUE rb_mKernel;
+VALUE rb_cObject;
+VALUE rb_cModule;
+VALUE rb_cClass;
+VALUE rb_cData;
-static VALUE cNilClass;
-static VALUE cTrueClass;
-static VALUE cFalseClass;
+VALUE rb_cNilClass;
+VALUE rb_cTrueClass;
+VALUE rb_cFalseClass;
-struct st_table *new_idhash();
-
-VALUE f_sprintf();
-
-VALUE obj_alloc();
+VALUE rb_f_sprintf();
+VALUE rb_obj_alloc();
static ID eq, eql;
static ID inspect;
@@ -40,10 +36,11 @@ rb_equal(obj1, obj2)
{
VALUE result;
+ if (obj1 == obj2) return Qtrue;
result = rb_funcall(obj1, eq, 1, obj2);
- if (result == FALSE || NIL_P(result))
- return FALSE;
- return TRUE;
+ if (result == Qfalse || NIL_P(result))
+ return Qfalse;
+ return Qtrue;
}
int
@@ -53,82 +50,98 @@ rb_eql(obj1, obj2)
return rb_funcall(obj1, eql, 1, obj2);
}
-VALUE
-obj_equal(obj1, obj2)
+static VALUE
+rb_obj_equal(obj1, obj2)
VALUE obj1, obj2;
{
- if (obj1 == obj2) return TRUE;
- return FALSE;
+ if (obj1 == obj2) return Qtrue;
+ return Qfalse;
}
static VALUE
-any_to_a(obj)
+rb_any_to_a(obj)
VALUE obj;
{
- return ary_new3(1, obj);
+ return rb_ary_new3(1, obj);
}
static VALUE
-obj_id(obj)
+rb_obj_hash(obj)
VALUE obj;
{
- return INT2NUM((int)obj);
+ return (long)obj|FIXNUM_FLAG;
+}
+
+VALUE
+rb_obj_id(obj)
+ VALUE obj;
+{
+ if (rb_special_const_p(obj)) {
+ return INT2NUM((long)obj);
+ }
+ return (long)obj|FIXNUM_FLAG;
}
static VALUE
-obj_type(obj)
+rb_obj_type(obj)
VALUE obj;
{
VALUE cl = CLASS_OF(obj);
- if (FL_TEST(cl, FL_SINGLETON)) {
+ while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
cl = RCLASS(cl)->super;
}
return cl;
}
-static VALUE
-obj_clone(obj)
+VALUE
+rb_obj_clone(obj)
VALUE obj;
{
VALUE clone;
if (TYPE(obj) != T_OBJECT) {
- TypeError("can't clone %s", rb_class2name(CLASS_OF(obj)));
+ rb_raise(rb_eTypeError, "can't clone %s", rb_class2name(CLASS_OF(obj)));
}
- clone = obj_alloc(RBASIC(obj)->class);
+ clone = rb_obj_alloc(RBASIC(obj)->klass);
CLONESETUP(clone,obj);
if (ROBJECT(obj)->iv_tbl) {
ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl);
- RBASIC(clone)->class = singleton_class_clone(RBASIC(obj)->class);
- RBASIC(clone)->flags = RBASIC(obj)->flags;
+ RBASIC(clone)->klass = rb_singleton_class_clone(RBASIC(obj)->klass);
+ RBASIC(clone)->flags = RBASIC(obj)->flags;
}
return clone;
}
static VALUE
-obj_dup(obj)
+rb_obj_dup(obj)
VALUE obj;
{
return rb_funcall(obj, rb_intern("clone"), 0, 0);
}
VALUE
-any_to_s(obj)
+rb_any_to_s(obj)
VALUE obj;
{
- char buf[256];
+ char *s;
+ char *cname = rb_class2name(CLASS_OF(obj));
+ VALUE str;
+
+ s = ALLOCA_N(char, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:eos */
+ sprintf(s, "#<%s:0x%x>", cname, obj);
+ str = rb_str_new2(s);
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
- sprintf(buf, "#<%s:0x%x>", rb_class2name(CLASS_OF(obj)), obj);
- return str_new2(buf);
+ return str;
}
VALUE
rb_inspect(obj)
VALUE obj;
{
- return obj_as_string(rb_funcall(obj, inspect, 0, 0));
+ return rb_obj_as_string(rb_funcall(obj, inspect, 0, 0));
}
static int
@@ -142,29 +155,35 @@ inspect_i(id, value, str)
/* need not to show internal data */
if (CLASS_OF(value) == 0) return ST_CONTINUE;
+ if (!rb_is_instance_id(id)) return ST_CONTINUE;
if (RSTRING(str)->ptr[0] == '-') {
RSTRING(str)->ptr[0] = '#';
- str_cat(str, ": ", 2);
+ rb_str_cat(str, ": ", 2);
}
else {
- str_cat(str, ", ", 2);
+ rb_str_cat(str, ", ", 2);
}
ivname = rb_id2name(id);
- str_cat(str, ivname, strlen(ivname));
- str_cat(str, "=", 1);
- if (TYPE(value) == T_OBJECT) {
- str2 = any_to_s(value);
- }
- else {
- str2 = rb_inspect(value);
- }
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_cat(str, ivname, strlen(ivname));
+ rb_str_cat(str, "=", 1);
+ str2 = rb_inspect(value);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return ST_CONTINUE;
}
static VALUE
-obj_inspect(obj)
+inspect_obj(obj, str)
+ VALUE obj, str;
+{
+ st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str);
+ rb_str_cat(str, ">", 1);
+
+ return str;
+}
+
+static VALUE
+rb_obj_inspect(obj)
VALUE obj;
{
if (TYPE(obj) == T_OBJECT
@@ -173,19 +192,21 @@ obj_inspect(obj)
VALUE str;
char *b;
- str = str_new2("-<");
b = rb_class2name(CLASS_OF(obj));
- str_cat(str, b, strlen(b));
- st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str);
- str_cat(str, ">", 1);
-
- return str;
+ if (rb_inspecting_p(obj)) {
+ char *buf = ALLOCA_N(char, strlen(b)+8);
+ sprintf(buf, "#<%s:...>", b);
+ return rb_str_new2(buf);
+ }
+ str = rb_str_new2("-<");
+ rb_str_cat(str, b, strlen(b));
+ return rb_protect_inspect(inspect_obj, obj, str);
}
return rb_funcall(obj, rb_intern("to_s"), 0, 0);
}
VALUE
-obj_is_instance_of(obj, c)
+rb_obj_is_instance_of(obj, c)
VALUE obj, c;
{
VALUE cl;
@@ -196,31 +217,31 @@ obj_is_instance_of(obj, c)
break;
case T_NIL:
- if (NIL_P(obj)) return TRUE;
- return FALSE;
+ if (NIL_P(obj)) return Qtrue;
+ return Qfalse;
case T_FALSE:
- if (obj) return FALSE;
- return TRUE;
+ if (obj) return Qfalse;
+ return Qtrue;
case T_TRUE:
- if (obj) return TRUE;
- return FALSE;
+ if (obj) return Qtrue;
+ return Qfalse;
default:
- TypeError("class or module required");
+ rb_raise(rb_eTypeError, "class or module required");
}
cl = CLASS_OF(obj);
- while (FL_TEST(cl, FL_SINGLETON)) {
+ while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
cl = RCLASS(cl)->super;
}
- if (c == cl) return TRUE;
- return FALSE;
+ if (c == cl) return Qtrue;
+ return Qfalse;
}
VALUE
-obj_is_kind_of(obj, c)
+rb_obj_is_kind_of(obj, c)
VALUE obj, c;
{
VALUE cl = CLASS_OF(obj);
@@ -230,70 +251,93 @@ obj_is_kind_of(obj, c)
case T_CLASS:
break;
- case T_NIL:
- if (NIL_P(obj)) return TRUE;
- return FALSE;
-
- case T_FALSE:
- if (obj) return FALSE;
- return TRUE;
-
- case T_TRUE:
- if (obj) return TRUE;
- return FALSE;
-
default:
- TypeError("class or module required");
+ rb_raise(rb_eTypeError, "class or module required");
}
while (cl) {
if (cl == c || RCLASS(cl)->m_tbl == RCLASS(c)->m_tbl)
- return TRUE;
+ return Qtrue;
cl = RCLASS(cl)->super;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-obj_dummy(obj)
+rb_obj_dummy(obj)
VALUE obj;
{
return Qnil;
}
+VALUE
+rb_obj_tainted(obj)
+ VALUE obj;
+{
+ if (OBJ_TAINTED(obj))
+ return Qtrue;
+ return Qfalse;
+}
+
+VALUE
+rb_obj_taint(obj)
+ VALUE obj;
+{
+ OBJ_TAINT(obj);
+ return obj;
+}
+
+VALUE
+rb_obj_untaint(obj)
+ VALUE obj;
+{
+ rb_secure(3);
+ FL_UNSET(obj, FL_TAINT);
+ return obj;
+}
+
+static VALUE
+nil_to_i(obj)
+ VALUE obj;
+{
+ return INT2FIX(0);
+}
+
static VALUE
nil_to_s(obj)
VALUE obj;
{
- return str_new2("");
+ return rb_str_new2("");
}
static VALUE
nil_to_a(obj)
VALUE obj;
{
- return ary_new2(0);
+ return rb_ary_new2(0);
}
static VALUE
nil_inspect(obj)
VALUE obj;
{
- return str_new2("nil");
+ return rb_str_new2("nil");
}
static VALUE
nil_type(obj)
VALUE obj;
{
- return cNilClass;
+ return rb_cNilClass;
}
+#ifdef NIL_PLUS
static VALUE
nil_plus(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
+ case T_NIL:
case T_FIXNUM:
case T_FLOAT:
case T_BIGNUM:
@@ -301,74 +345,132 @@ nil_plus(x, y)
case T_ARRAY:
return y;
default:
- TypeError("tried to add %s(%s) to nil",
- RSTRING(obj_as_string(y))->ptr, rb_class2name(CLASS_OF(y)));
+ rb_raise(rb_eTypeError, "tried to add %s(%s) to nil",
+ STR2CSTR(rb_inspect(y)),
+ rb_class2name(CLASS_OF(y)));
}
/* not reached */
}
+#endif
static VALUE
main_to_s(obj)
VALUE obj;
{
- return str_new2("main");
+ return rb_str_new2("main");
}
static VALUE
true_to_s(obj)
VALUE obj;
{
- return str_new2("true");
+ return rb_str_new2("true");
+}
+
+static VALUE
+true_to_i(obj)
+ VALUE obj;
+{
+ return INT2FIX(1);
}
static VALUE
true_type(obj)
VALUE obj;
{
- return cTrueClass;
+ return rb_cTrueClass;
+}
+
+static VALUE
+true_and(obj, obj2)
+ VALUE obj, obj2;
+{
+ return RTEST(obj2)?Qtrue:Qfalse;
+}
+
+static VALUE
+true_or(obj, obj2)
+ VALUE obj, obj2;
+{
+ return Qtrue;
+}
+
+static VALUE
+true_xor(obj, obj2)
+ VALUE obj, obj2;
+{
+ return RTEST(obj2)?Qfalse:Qtrue;
}
static VALUE
false_to_s(obj)
VALUE obj;
{
- return str_new2("false");
+ return rb_str_new2("false");
+}
+
+static VALUE
+false_to_i(obj)
+ VALUE obj;
+{
+ return INT2FIX(0);
}
static VALUE
false_type(obj)
VALUE obj;
{
- return cFalseClass;
+ return rb_cFalseClass;
+}
+
+static VALUE
+false_and(obj, obj2)
+ VALUE obj, obj2;
+{
+ return Qfalse;
+}
+
+static VALUE
+false_or(obj, obj2)
+ VALUE obj, obj2;
+{
+ return RTEST(obj2)?Qtrue:Qfalse;
+}
+
+static VALUE
+false_xor(obj, obj2)
+ VALUE obj, obj2;
+{
+ return RTEST(obj2)?Qtrue:Qfalse;
}
static VALUE
rb_true(obj)
VALUE obj;
{
- return TRUE;
+ return Qtrue;
}
static VALUE
rb_false(obj)
VALUE obj;
{
- return FALSE;
+ return Qfalse;
}
VALUE
-obj_alloc(class)
- VALUE class;
+rb_obj_alloc(klass)
+ VALUE klass;
{
NEWOBJ(obj, struct RObject);
- OBJSETUP(obj, class, T_OBJECT);
+ OBJSETUP(obj, klass, T_OBJECT);
obj->iv_tbl = 0;
return (VALUE)obj;
}
static VALUE
-mod_clone(module)
+rb_mod_clone(module)
VALUE module;
{
NEWOBJ(clone, struct RClass);
@@ -377,27 +479,28 @@ mod_clone(module)
clone->super = RCLASS(module)->super;
clone->iv_tbl = 0;
clone->m_tbl = 0; /* avoid GC crashing */
+ clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl);
clone->m_tbl = st_copy(RCLASS(module)->m_tbl);
return (VALUE)clone;
}
static VALUE
-mod_to_s(class)
- VALUE class;
+rb_mod_to_s(klass)
+ VALUE klass;
{
- return rb_class_path(class);
+ return rb_str_dup(rb_class_path(klass));
}
static VALUE
-mod_eqq(mod, arg)
+rb_mod_eqq(mod, arg)
VALUE mod, arg;
{
- return obj_is_kind_of(arg, mod);
+ return rb_obj_is_kind_of(arg, mod);
}
static VALUE
-mod_le(mod, arg)
+rb_mod_le(mod, arg)
VALUE mod, arg;
{
switch (TYPE(arg)) {
@@ -405,28 +508,28 @@ mod_le(mod, arg)
case T_CLASS:
break;
default:
- TypeError("compared with non class/module");
+ rb_raise(rb_eTypeError, "compared with non class/module");
}
while (mod) {
if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl)
- return TRUE;
+ return Qtrue;
mod = RCLASS(mod)->super;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-mod_lt(mod, arg)
+rb_mod_lt(mod, arg)
VALUE mod, arg;
{
- if (mod == arg) return FALSE;
- return mod_le(mod, arg);
+ if (mod == arg) return Qfalse;
+ return rb_mod_le(mod, arg);
}
static VALUE
-mod_ge(mod, arg)
+rb_mod_ge(mod, arg)
VALUE mod, arg;
{
switch (TYPE(arg)) {
@@ -434,22 +537,22 @@ mod_ge(mod, arg)
case T_CLASS:
break;
default:
- TypeError("compared with non class/module");
+ rb_raise(rb_eTypeError, "compared with non class/module");
}
- return mod_lt(arg, mod);
+ return rb_mod_lt(arg, mod);
}
static VALUE
-mod_gt(mod, arg)
+rb_mod_gt(mod, arg)
VALUE mod, arg;
{
- if (mod == arg) return FALSE;
- return mod_ge(mod, arg);
+ if (mod == arg) return Qfalse;
+ return rb_mod_ge(mod, arg);
}
static VALUE
-mod_cmp(mod, arg)
+rb_mod_cmp(mod, arg)
VALUE mod, arg;
{
if (mod == arg) return INT2FIX(0);
@@ -459,52 +562,63 @@ mod_cmp(mod, arg)
case T_CLASS:
break;
default:
- TypeError("<=> requires Class or Module (%s given)",
- rb_class2name(CLASS_OF(arg)));
+ rb_raise(rb_eTypeError, "<=> requires Class or Module (%s given)",
+ rb_class2name(CLASS_OF(arg)));
break;
}
- if (mod_le(mod, arg)) {
+ if (rb_mod_le(mod, arg)) {
return INT2FIX(-1);
}
return INT2FIX(1);
}
-VALUE module_new();
-VALUE class_new_instance();
+static VALUE
+rb_module_s_new(klass)
+{
+ VALUE mod = rb_module_new();
+
+ RBASIC(mod)->klass = klass;
+ rb_obj_call_init(mod);
+ return mod;
+}
+
+VALUE rb_class_new_instance();
static VALUE
-class_s_new(argc, argv)
+rb_class_s_new(argc, argv)
int argc;
VALUE *argv;
{
VALUE super, klass;
- rb_scan_args(argc, argv, "01", &super);
- if (NIL_P(super)) super = cObject;
+ if (rb_scan_args(argc, argv, "01", &super) == 0) {
+ super = rb_cObject;
+ }
Check_Type(super, T_CLASS);
if (FL_TEST(super, FL_SINGLETON)) {
- TypeError("can't make subclass of virtual class");
+ rb_raise(rb_eTypeError, "can't make subclass of virtual class");
}
- klass = class_new(super);
+ klass = rb_class_new(super);
/* make metaclass */
- RBASIC(klass)->class = singleton_class_new(RBASIC(super)->class);
- singleton_class_attached(RBASIC(klass)->class, klass);
+ RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
+ rb_singleton_class_attached(RBASIC(klass)->klass, klass);
+ rb_obj_call_init(klass);
return klass;
}
-VALUE mod_name();
-VALUE mod_included_modules();
-VALUE mod_ancestors();
-VALUE class_instance_methods();
-VALUE class_private_instance_methods();
+static VALUE
+rb_class_s_inherited()
+{
+ rb_raise(rb_eTypeError, "can't make subclass of Class");
+}
static VALUE
-class_superclass(cl)
- VALUE cl;
+rb_class_superclass(klass)
+ VALUE klass;
{
- VALUE super = RCLASS(cl)->super;
+ VALUE super = RCLASS(klass)->super;
while (TYPE(super) == T_ICLASS) {
super = RCLASS(super)->super;
@@ -519,79 +633,82 @@ ID
rb_to_id(name)
VALUE name;
{
+ ID id;
+
if (TYPE(name) == T_STRING) {
return rb_intern(RSTRING(name)->ptr);
}
- Check_Type(name, T_FIXNUM);
- return FIX2UINT(name);
+ id = NUM2UINT(name);
+ if (!rb_id2name(id)) {
+ rb_raise(rb_eArgError, "%d is not a symbol", id);
+ }
+ return id;
}
static VALUE
-mod_attr(argc, argv, class)
+rb_mod_attr(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
VALUE name, pub;
rb_scan_args(argc, argv, "11", &name, &pub);
- rb_define_attr(class, rb_to_id(name), 1, RTEST(pub));
+ rb_attr(klass, rb_to_id(name), 1, RTEST(pub), Qtrue);
return Qnil;
}
static VALUE
-mod_attr_reader(argc, argv, class)
+rb_mod_attr_reader(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
int i;
for (i=0; i<argc; i++) {
- rb_define_attr(class, rb_to_id(argv[i]), 1, 0);
+ rb_attr(klass, rb_to_id(argv[i]), 1, 0, Qtrue);
}
return Qnil;
}
static VALUE
-mod_attr_writer(argc, argv, class)
+rb_mod_attr_writer(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
int i;
for (i=0; i<argc; i++) {
- rb_define_attr(class, rb_to_id(argv[i]), 0, 1);
+ rb_attr(klass, rb_to_id(argv[i]), 0, 1, Qtrue);
}
return Qnil;
}
static VALUE
-mod_attr_accessor(argc, argv, class)
+rb_mod_attr_accessor(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
int i;
for (i=0; i<argc; i++) {
- rb_define_attr(class, rb_to_id(argv[i]), 1, 1);
+ rb_attr(klass, rb_to_id(argv[i]), 1, 1, Qtrue);
}
return Qnil;
}
-VALUE mod_constants();
-
static VALUE
-mod_const_get(mod, name)
+rb_mod_const_get(mod, name)
VALUE mod, name;
{
return rb_const_get_at(mod, rb_to_id(name));
}
static VALUE
-mod_const_set(mod, name, value)
+rb_mod_const_set(mod, name, value)
VALUE mod, name, value;
{
rb_const_set(mod, rb_to_id(name), value);
@@ -599,159 +716,201 @@ mod_const_set(mod, name, value)
}
static VALUE
-mod_const_defined(mod, name)
+rb_mod_const_defined(mod, name)
VALUE mod, name;
{
return rb_const_defined_at(mod, rb_to_id(name));
}
static VALUE
-obj_methods(obj)
+rb_obj_methods(obj)
VALUE obj;
{
VALUE argv[1];
- argv[0] = TRUE;
- return class_instance_methods(1, argv, CLASS_OF(obj));
+ argv[0] = Qtrue;
+ return rb_class_instance_methods(1, argv, CLASS_OF(obj));
}
-VALUE obj_singleton_methods();
+VALUE rb_obj_singleton_methods();
static VALUE
-obj_private_methods(obj)
+rb_obj_protected_methods(obj)
VALUE obj;
{
VALUE argv[1];
- argv[0] = TRUE;
- return class_private_instance_methods(1, argv, CLASS_OF(obj));
+ argv[0] = Qtrue;
+ return rb_class_protected_instance_methods(1, argv, CLASS_OF(obj));
}
-VALUE obj_instance_variables();
-VALUE obj_remove_instance_variable();
-
static VALUE
-f_integer(obj, arg)
- VALUE obj, arg;
+rb_obj_private_methods(obj)
+ VALUE obj;
{
- int i;
+ VALUE argv[1];
- switch (TYPE(arg)) {
+ argv[0] = Qtrue;
+ return rb_class_private_instance_methods(1, argv, CLASS_OF(obj));
+}
+
+VALUE
+rb_Integer(val)
+ VALUE val;
+{
+ long i;
+
+ switch (TYPE(val)) {
case T_FLOAT:
- if (RFLOAT(arg)->value <= (double)FIXNUM_MAX
- && RFLOAT(arg)->value >= (double)FIXNUM_MIN) {
- i = (int)RFLOAT(arg)->value;
+ if (RFLOAT(val)->value <= (double)FIXNUM_MAX
+ && RFLOAT(val)->value >= (double)FIXNUM_MIN) {
+ i = (long)RFLOAT(val)->value;
break;
}
- return dbl2big(RFLOAT(arg)->value);
+ return rb_dbl2big(RFLOAT(val)->value);
case T_BIGNUM:
- return arg;
+ return val;
case T_STRING:
- return str2inum(RSTRING(arg)->ptr, 0);
+ return rb_str2inum(RSTRING(val)->ptr, 0);
+
+ case T_NIL:
+ return INT2FIX(0);
default:
- i = NUM2INT(arg);
+ i = NUM2LONG(val);
}
return INT2NUM(i);
}
-VALUE
-rb_Integer(val)
- VALUE val;
+static VALUE
+rb_f_integer(obj, arg)
+ VALUE obj, arg;
{
- return f_integer(Qnil, val);
+ return rb_Integer(arg);
}
-static VALUE
-to_flo(val)
+struct arg_to {
VALUE val;
+ char *s;
+};
+
+static VALUE
+to_type(arg)
+ struct arg_to *arg;
{
- return rb_funcall(val, rb_intern("to_f"), 0);
+ return rb_funcall(arg->val, rb_intern(arg->s), 0);
}
static VALUE
-fail_to_flo(val)
+fail_to_type(arg)
+ struct arg_to *arg;
+{
+ rb_raise(rb_eTypeError, "failed to convert %s into %s",
+ NIL_P(arg->val) ? "nil" :
+ arg->val == Qtrue ? "true" :
+ arg->val == Qfalse ? "false" :
+ rb_class2name(CLASS_OF(arg->val)),
+ arg->s);
+}
+
+VALUE
+rb_convert_type(val, type, tname, method)
VALUE val;
+ int type;
+ char *tname, *method;
{
- TypeError("failed to convert %s into Float", rb_class2name(CLASS_OF(val)));
+ struct arg_to arg1, arg2;
+
+ if (TYPE(val) == type) return val;
+ arg1.val = arg2.val = val;
+ arg1.s = method;
+ arg2.s = tname;
+ val = rb_rescue(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2);
+ Check_Type(val, type);
+ return val;
}
-double big2dbl();
+double rb_big2dbl _((VALUE));
-static VALUE
-f_float(obj, arg)
- VALUE obj, arg;
+VALUE
+rb_Float(val)
+ VALUE val;
{
- switch (TYPE(arg)) {
+ switch (TYPE(val)) {
case T_FIXNUM:
- return float_new((double)FIX2INT(arg));
+ return rb_float_new((double)FIX2LONG(val));
case T_FLOAT:
- return arg;
+ return val;
case T_BIGNUM:
- return float_new(big2dbl(arg));
+ return rb_float_new(rb_big2dbl(val));
default:
- return rb_rescue(to_flo, arg, fail_to_flo, arg);
+ return rb_convert_type(val, T_FLOAT, "Float", "to_f");
}
}
-VALUE
-rb_Float(val)
- VALUE val;
+static VALUE
+rb_f_float(obj, arg)
+ VALUE obj, arg;
{
- return f_float(Qnil, val);
+ return rb_Float(arg);
}
double
-num2dbl(val)
+rb_num2dbl(val)
VALUE val;
{
VALUE v = rb_Float(val);
return RFLOAT(v)->value;
}
-static VALUE
-f_string(obj, arg)
- VALUE obj, arg;
+char*
+rb_str2cstr(str, len)
+ VALUE str;
+ int *len;
{
- return rb_funcall(arg, rb_intern("to_s"), 0);
+ if (TYPE(str) != T_STRING) {
+ str = rb_str_to_str(str);
+ }
+ if (len) *len = RSTRING(str)->len;
+ return RSTRING(str)->ptr;
}
VALUE
rb_String(val)
VALUE val;
{
- return f_string(Qnil, val);
+ return rb_convert_type(val, T_STRING, "String", "to_s");
}
static VALUE
-f_array(obj, arg)
+rb_f_string(obj, arg)
VALUE obj, arg;
{
- if (TYPE(arg) == T_ARRAY) return arg;
- arg = rb_funcall(arg, rb_intern("to_a"), 0);
- if (TYPE(arg) != T_ARRAY) {
- TypeError("`to_a' did not return Array");
- }
- return arg;
+ return rb_String(arg);
}
VALUE
rb_Array(val)
VALUE val;
{
- return f_array(Qnil, val);
+ if (TYPE(val) == T_ARRAY) return val;
+ val = rb_funcall(val, rb_intern("to_a"), 0);
+ if (TYPE(val) != T_ARRAY) {
+ rb_raise(rb_eTypeError, "`to_a' did not return Array");
+ }
+ return val;
}
-VALUE
-rb_to_a(val) /* backward compatibility */
- VALUE val;
+static VALUE
+rb_f_array(obj, arg)
+ VALUE obj, arg;
{
- return f_array(Qnil, val);
+ return rb_Array(arg);
}
static VALUE
@@ -760,47 +919,36 @@ boot_defclass(name, super)
VALUE super;
{
extern st_table *rb_class_tbl;
- VALUE obj = class_new(super);
+ VALUE obj = rb_class_new(super);
ID id = rb_intern(name);
rb_name_class(obj, id);
st_add_direct(rb_class_tbl, id, obj);
- return (VALUE)obj;
-}
-
-VALUE
-rb_class_of(obj)
- VALUE obj;
-{
- if (FIXNUM_P(obj)) return cFixnum;
- if (obj == Qnil) return cNilClass;
- if (obj == FALSE) return cFalseClass;
- if (obj == TRUE) return cTrueClass;
-
- return RBASIC(obj)->class;
+ return obj;
}
-VALUE TopSelf;
+VALUE ruby_top_self;
void
Init_Object()
{
VALUE metaclass;
- cObject = boot_defclass("Object", 0);
- cModule = boot_defclass("Module", cObject);
- cClass = boot_defclass("Class", cModule);
+ rb_cObject = boot_defclass("Object", 0);
+ rb_cModule = boot_defclass("Module", rb_cObject);
+ rb_cClass = boot_defclass("Class", rb_cModule);
- metaclass = RBASIC(cObject)->class = singleton_class_new(cClass);
- singleton_class_attached(metaclass, cObject);
- metaclass = RBASIC(cModule)->class = singleton_class_new(metaclass);
- singleton_class_attached(metaclass, cModule);
- metaclass = RBASIC(cClass)->class = singleton_class_new(metaclass);
- singleton_class_attached(metaclass, cClass);
+ metaclass = RBASIC(rb_cObject)->klass = rb_singleton_class_new(rb_cClass);
+ rb_singleton_class_attached(metaclass, rb_cObject);
+ metaclass = RBASIC(rb_cModule)->klass = rb_singleton_class_new(metaclass);
+ rb_singleton_class_attached(metaclass, rb_cModule);
+ metaclass = RBASIC(rb_cClass)->klass = rb_singleton_class_new(metaclass);
+ rb_singleton_class_attached(metaclass, rb_cClass);
- mKernel = rb_define_module("Kernel");
- rb_include_module(cObject, mKernel);
- rb_define_private_method(cClass, "inherited", obj_dummy, 1);
+ rb_mKernel = rb_define_module("Kernel");
+ rb_include_module(rb_cObject, rb_mKernel);
+ rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, -1);
+ rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
/*
* Ruby's Class Hierarchy Chart
@@ -826,111 +974,132 @@ Init_Object()
* + All metaclasses are instances of the class `Class'.
*/
- rb_define_method(mKernel, "nil?", rb_false, 0);
- rb_define_method(mKernel, "==", obj_equal, 1);
- rb_define_alias(mKernel, "equal?", "==");
- rb_define_alias(mKernel, "===", "==");
- rb_define_method(mKernel, "=~", rb_false, 1);
-
- rb_define_method(mKernel, "eql?", obj_equal, 1);
-
- rb_define_method(mKernel, "hash", obj_id, 0);
- rb_define_method(mKernel, "id", obj_id, 0);
- rb_define_method(mKernel, "type", obj_type, 0);
-
- rb_define_method(mKernel, "clone", obj_clone, 0);
- rb_define_method(mKernel, "dup", obj_dup, 0);
-
- rb_define_method(mKernel, "to_a", any_to_a, 0);
- rb_define_method(mKernel, "to_s", any_to_s, 0);
- rb_define_method(mKernel, "inspect", obj_inspect, 0);
- rb_define_method(mKernel, "methods", obj_methods, 0);
- rb_define_method(mKernel, "singleton_methods", obj_singleton_methods, 0);
- rb_define_method(mKernel, "private_methods", obj_private_methods, 0);
- rb_define_method(mKernel, "instance_variables", obj_instance_variables, 0);
- rb_define_method(mKernel, "remove_instance_variable", obj_remove_instance_variable, 0);
-
- rb_define_method(mKernel, "instance_of?", obj_is_instance_of, 1);
- rb_define_method(mKernel, "kind_of?", obj_is_kind_of, 1);
- rb_define_method(mKernel, "is_a?", obj_is_kind_of, 1);
-
- rb_define_global_function("sprintf", f_sprintf, -1);
- rb_define_alias(mKernel, "format", "sprintf");
-
- rb_define_global_function("Integer", f_integer, 1);
- rb_define_global_function("Float", f_float, 1);
-
- rb_define_global_function("String", f_string, 1);
- rb_define_global_function("Array", f_array, 1);
-
- cNilClass = rb_define_class("NilClass", cObject);
- rb_define_method(cNilClass, "type", nil_type, 0);
- rb_define_method(cNilClass, "to_s", nil_to_s, 0);
- rb_define_method(cNilClass, "to_a", nil_to_a, 0);
- rb_define_method(cNilClass, "inspect", nil_inspect, 0);
-
- rb_define_method(cNilClass, "nil?", rb_true, 0);
- rb_undef_method(CLASS_OF(cNilClass), "new");
+ rb_define_method(rb_mKernel, "nil?", rb_false, 0);
+ rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
+ rb_define_alias(rb_mKernel, "equal?", "==");
+ rb_define_alias(rb_mKernel, "===", "==");
+ rb_define_method(rb_mKernel, "=~", rb_false, 1);
+
+ rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
+
+ rb_define_method(rb_mKernel, "hash", rb_obj_hash, 0);
+ rb_define_method(rb_mKernel, "id", rb_obj_id, 0);
+ rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
+ rb_define_method(rb_mKernel, "type", rb_obj_type, 0);
+
+ rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
+ rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
+
+ rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
+ rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
+ rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
+
+ rb_define_method(rb_mKernel, "to_a", rb_any_to_a, 0);
+ rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
+ rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
+ rb_define_method(rb_mKernel, "methods", rb_obj_methods, 0);
+ rb_define_method(rb_mKernel, "public_methods", rb_obj_methods, 0);
+ rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, 0);
+ rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, 0);
+ rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, 0);
+ rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0);
+ rb_define_private_method(rb_mKernel, "remove_instance_variable",
+ rb_obj_remove_instance_variable, 0);
+
+ rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
+ rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
+ rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
+
+ rb_define_global_function("sprintf", rb_f_sprintf, -1);
+ rb_define_global_function("format", rb_f_sprintf, -1);
+
+ rb_define_global_function("Integer", rb_f_integer, 1);
+ rb_define_global_function("Float", rb_f_float, 1);
+
+ rb_define_global_function("String", rb_f_string, 1);
+ rb_define_global_function("Array", rb_f_array, 1);
+
+ rb_cNilClass = rb_define_class("NilClass", rb_cObject);
+ rb_define_method(rb_cNilClass, "type", nil_type, 0);
+ rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0);
+ rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
+ rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
+ rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
+
+ rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
+ rb_undef_method(CLASS_OF(rb_cNilClass), "new");
rb_define_global_const("NIL", Qnil);
/* default addition */
- rb_define_method(cNilClass, "+", nil_plus, 1);
-
- rb_define_global_function("initialize", obj_dummy, -1);
- rb_define_global_function("singleton_method_added", obj_dummy, 1);
-
- rb_define_method(cModule, "===", mod_eqq, 1);
- rb_define_method(cModule, "<=>", mod_cmp, 1);
- rb_define_method(cModule, "<", mod_lt, 1);
- rb_define_method(cModule, "<=", mod_le, 1);
- rb_define_method(cModule, ">", mod_gt, 1);
- rb_define_method(cModule, ">=", mod_ge, 1);
- rb_define_method(cModule, "clone", mod_clone, 0);
- rb_define_method(cModule, "to_s", mod_to_s, 0);
- rb_define_method(cModule, "included_modules", mod_included_modules, 0);
- rb_define_method(cModule, "name", mod_name, 0);
- rb_define_method(cModule, "ancestors", mod_ancestors, 0);
-
- rb_define_private_method(cModule, "attr", mod_attr, -1);
- rb_define_private_method(cModule, "attr_reader", mod_attr_reader, -1);
- rb_define_private_method(cModule, "attr_writer", mod_attr_writer, -1);
- rb_define_private_method(cModule, "attr_accessor", mod_attr_accessor, -1);
-
- rb_define_singleton_method(cModule, "new", module_new, 0);
- rb_define_method(cModule, "instance_methods", class_instance_methods, -1);
- rb_define_method(cModule, "private_instance_methods", class_private_instance_methods, -1);
-
- rb_define_method(cModule, "constants", mod_constants, 0);
- rb_define_method(cModule, "const_get", mod_const_get, 1);
- rb_define_method(cModule, "const_set", mod_const_set, 2);
- rb_define_method(cModule, "const_defined?", mod_const_defined, 1);
- rb_define_private_method(cModule, "method_added", obj_dummy, 1);
-
- rb_define_method(cClass, "new", class_new_instance, -1);
- rb_define_method(cClass, "superclass", class_superclass, 0);
- rb_define_singleton_method(cClass, "new", class_s_new, -1);
- rb_undef_method(cClass, "extend_object");
- rb_undef_method(cClass, "append_features");
-
- rb_define_singleton_method(cClass, "new", class_s_new, -1);
-
- cData = rb_define_class("Data", cObject);
-
- TopSelf = obj_alloc(cObject);
- rb_global_variable(&TopSelf);
- rb_define_singleton_method(TopSelf, "to_s", main_to_s, 0);
-
- cTrueClass = rb_define_class("TrueClass", cObject);
- rb_define_method(cTrueClass, "to_s", true_to_s, 0);
- rb_define_method(cTrueClass, "type", true_type, 0);
- rb_undef_method(CLASS_OF(cTrueClass), "new");
- rb_define_global_const("TRUE", TRUE);
-
- cFalseClass = rb_define_class("FalseClass", cObject);
- rb_define_method(cFalseClass, "to_s", false_to_s, 0);
- rb_define_method(cFalseClass, "type", false_type, 0);
- rb_undef_method(CLASS_OF(cFalseClass), "new");
- rb_define_global_const("FALSE", FALSE);
+#ifdef NIL_PLUS
+ rb_define_method(rb_cNilClass, "+", nil_plus, 1);
+#endif
+
+ rb_define_global_function("singleton_method_added", rb_obj_dummy, 1);
+
+ rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
+ rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1);
+ rb_define_method(rb_cModule, "<", rb_mod_lt, 1);
+ rb_define_method(rb_cModule, "<=", rb_mod_le, 1);
+ rb_define_method(rb_cModule, ">", rb_mod_gt, 1);
+ rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
+ rb_define_method(rb_cModule, "clone", rb_mod_clone, 0);
+ rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
+ rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0);
+ rb_define_method(rb_cModule, "name", rb_mod_name, 0);
+ rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0);
+
+ rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
+ rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
+ rb_define_private_method(rb_cModule, "attr_writer", rb_mod_attr_writer, -1);
+ rb_define_private_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
+
+ rb_define_singleton_method(rb_cModule, "new", rb_module_s_new, 0);
+ rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1);
+ rb_define_method(rb_cModule, "public_instance_methods", rb_class_instance_methods, -1);
+ rb_define_method(rb_cModule, "protected_instance_methods", rb_class_protected_instance_methods, -1);
+ rb_define_method(rb_cModule, "private_instance_methods", rb_class_private_instance_methods, -1);
+
+ rb_define_method(rb_cModule, "constants", rb_mod_constants, 0);
+ rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1);
+ rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
+ rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1);
+ rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_const, 1);
+ rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
+
+ rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
+ rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
+ rb_define_singleton_method(rb_cClass, "new", rb_class_s_new, -1);
+ rb_undef_method(rb_cClass, "extend_object");
+ rb_undef_method(rb_cClass, "append_features");
+ rb_define_singleton_method(rb_cClass, "inherited", rb_class_s_inherited, 1);
+
+ rb_cData = rb_define_class("Data", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cData), "new");
+
+ ruby_top_self = rb_obj_alloc(rb_cObject);
+ rb_global_variable(&ruby_top_self);
+ rb_define_singleton_method(ruby_top_self, "to_s", main_to_s, 0);
+
+ rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
+ rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
+ rb_define_method(rb_cTrueClass, "to_i", true_to_i, 0);
+ rb_define_method(rb_cTrueClass, "type", true_type, 0);
+ rb_define_method(rb_cTrueClass, "&", true_and, 1);
+ rb_define_method(rb_cTrueClass, "|", true_or, 1);
+ rb_define_method(rb_cTrueClass, "^", true_xor, 1);
+ rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
+ rb_define_global_const("TRUE", Qtrue);
+
+ rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
+ rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
+ rb_define_method(rb_cFalseClass, "to_i", false_to_i, 0);
+ rb_define_method(rb_cFalseClass, "type", false_type, 0);
+ rb_define_method(rb_cFalseClass, "&", false_and, 1);
+ rb_define_method(rb_cFalseClass, "|", false_or, 1);
+ rb_define_method(rb_cFalseClass, "^", false_xor, 1);
+ rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
+ rb_define_global_const("FALSE", Qfalse);
eq = rb_intern("==");
eql = rb_intern("eql?");
diff --git a/pack.c b/pack.c
index 20d12d4003..dc393b83fe 100644
--- a/pack.c
+++ b/pack.c
@@ -6,13 +6,13 @@
$Date$
created at: Thu Feb 10 15:17:05 JST 1994
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-#include <ctype.h>
#include <sys/types.h>
+#include <ctype.h>
#define swaps(x) ((((x)&0xFF)<<8) + (((x)>>8)&0xFF))
#define swapl(x) ((((x)&0xFF)<<24) \
@@ -74,14 +74,22 @@ endian()
#endif
#endif
-extern VALUE cString, cArray;
-#ifndef atof
-double atof();
-#endif
-
static char *toofew = "too few arguments";
-static void encodes();
+static void encodes _((VALUE,char*,int,int));
+static void qpencode _((VALUE,VALUE,int));
+
+static void
+pack_add_ptr(str, add)
+ VALUE str, add;
+{
+#define STR_NO_ORIG FL_USER3 /* copied from string.c */
+ if (!RSTRING(str)->orig) {
+ RSTRING(str)->orig = rb_ary_new();
+ FL_SET(str, STR_NO_ORIG);
+ }
+ rb_ary_push(RSTRING(str)->orig, add);
+}
static VALUE
pack_pack(ary, fmt)
@@ -89,23 +97,22 @@ pack_pack(ary, fmt)
{
static char *nul10 = "\0\0\0\0\0\0\0\0\0\0";
static char *spc10 = " ";
- UCHAR *p, *pend;
+ char *p, *pend;
VALUE res, from;
char type;
int items, len, idx;
- UCHAR *ptr;
+ char *ptr;
int plen;
- Check_Type(fmt, T_STRING);
-
- p = RSTRING(fmt)->ptr;
- pend = RSTRING(fmt)->ptr + RSTRING(fmt)->len;
- res = str_new(0, 0);
+
+ p = rb_str2cstr(fmt, &plen);
+ pend = p + plen;
+ res = rb_str_new(0, 0);
items = RARRAY(ary)->len;
idx = 0;
-#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (ArgError(toofew),0))
+#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (rb_raise(rb_eArgError, toofew),0))
while (p < pend) {
type = *p++; /* get data type */
@@ -114,7 +121,7 @@ pack_pack(ary, fmt)
len = strchr("@Xxu", type) ? 0 : items;
p++;
}
- else if (isdigit(*p)) {
+ else if (ISDIGIT(*p)) {
len = strtoul(p, (char**)&p, 10);
}
else {
@@ -127,11 +134,11 @@ pack_pack(ary, fmt)
case 'H': case 'h':
from = NEXTFROM;
if (NIL_P(from)) {
- ptr = 0;
+ ptr = "";
plen = 0;
}
else {
- from = obj_as_string(from);
+ from = rb_obj_as_string(from);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
}
@@ -143,15 +150,15 @@ pack_pack(ary, fmt)
case 'a':
case 'A':
if (plen >= len)
- str_cat(res, ptr, len);
+ rb_str_cat(res, ptr, len);
else {
- str_cat(res, ptr, plen);
+ rb_str_cat(res, ptr, plen);
len -= plen;
while (len >= 10) {
- str_cat(res, (type == 'A')?spc10:nul10, 10);
+ rb_str_cat(res, (type == 'A')?spc10:nul10, 10);
len -= 10;
}
- str_cat(res, (type == 'A')?spc10:nul10, len);
+ rb_str_cat(res, (type == 'A')?spc10:nul10, len);
}
break;
@@ -167,7 +174,7 @@ pack_pack(ary, fmt)
byte >>= 1;
else {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
byte = 0;
}
}
@@ -175,7 +182,7 @@ pack_pack(ary, fmt)
char c;
byte >>= 7 - (len & 7);
c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
}
}
break;
@@ -191,7 +198,7 @@ pack_pack(ary, fmt)
byte <<= 1;
else {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
byte = 0;
}
}
@@ -199,7 +206,7 @@ pack_pack(ary, fmt)
char c;
byte <<= 7 - (len & 7);
c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
}
}
break;
@@ -210,8 +217,8 @@ pack_pack(ary, fmt)
int i;
for (i=0; i++ < len; ptr++) {
- if (isxdigit(*ptr)) {
- if (isalpha(*ptr))
+ if (ISXDIGIT(*ptr)) {
+ if (ISALPHA(*ptr))
byte |= (((*ptr & 15) + 9) & 15) << 4;
else
byte |= (*ptr & 15) << 4;
@@ -219,14 +226,14 @@ pack_pack(ary, fmt)
byte >>= 4;
else {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
byte = 0;
}
}
}
if (len & 1) {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
}
}
break;
@@ -237,8 +244,8 @@ pack_pack(ary, fmt)
int i;
for (i=0; i++ < len; ptr++) {
- if (isxdigit(*ptr)) {
- if (isalpha(*ptr))
+ if (ISXDIGIT(*ptr)) {
+ if (ISALPHA(*ptr))
byte |= ((*ptr & 15) + 9) & 15;
else
byte |= *ptr & 15;
@@ -246,14 +253,14 @@ pack_pack(ary, fmt)
byte <<= 4;
else {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
byte = 0;
}
}
}
if (len & 1) {
char c = byte & 0xff;
- str_cat(res, &c, 1);
+ rb_str_cat(res, &c, 1);
}
}
break;
@@ -270,7 +277,7 @@ pack_pack(ary, fmt)
else {
c = NUM2INT(from);
}
- str_cat(res, &c, sizeof(char));
+ rb_str_cat(res, &c, sizeof(char));
}
break;
@@ -284,7 +291,7 @@ pack_pack(ary, fmt)
else {
s = NUM2INT(from);
}
- str_cat(res, (UCHAR*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, sizeof(short));
}
break;
@@ -296,9 +303,9 @@ pack_pack(ary, fmt)
from = NEXTFROM;
if (NIL_P(from)) i = 0;
else {
- i = NUM2INT(from);
+ i = NUM2UINT(from);
}
- str_cat(res, (UCHAR*)&i, sizeof(int));
+ rb_str_cat(res, (char*)&i, sizeof(int));
}
break;
@@ -310,9 +317,9 @@ pack_pack(ary, fmt)
from = NEXTFROM;
if (NIL_P(from)) l = 0;
else {
- l = NUM2INT(from);
+ l = NUM2ULONG(from);
}
- str_cat(res, (UCHAR*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, sizeof(long));
}
break;
@@ -326,7 +333,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htons(s);
- str_cat(res, (UCHAR*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, sizeof(short));
}
break;
@@ -337,10 +344,10 @@ pack_pack(ary, fmt)
from = NEXTFROM;
if (NIL_P(from)) l = 0;
else {
- l = NUM2INT(from);
+ l = NUM2ULONG(from);
}
l = htonl(l);
- str_cat(res, (UCHAR*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, sizeof(long));
}
break;
@@ -354,7 +361,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htovs(s);
- str_cat(res, (UCHAR*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, sizeof(short));
}
break;
@@ -365,10 +372,10 @@ pack_pack(ary, fmt)
from = NEXTFROM;
if (NIL_P(from)) l = 0;
else {
- l = NUM2INT(from);
+ l = NUM2ULONG(from);
}
l = htovl(l);
- str_cat(res, (UCHAR*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, sizeof(long));
}
break;
@@ -388,7 +395,7 @@ pack_pack(ary, fmt)
f = (float)NUM2INT(from);
break;
}
- str_cat(res, (UCHAR*)&f, sizeof(float));
+ rb_str_cat(res, (char*)&f, sizeof(float));
}
break;
@@ -408,23 +415,23 @@ pack_pack(ary, fmt)
d = (double)NUM2INT(from);
break;
}
- str_cat(res, (UCHAR*)&d, sizeof(double));
+ rb_str_cat(res, (char*)&d, sizeof(double));
}
break;
case 'x':
grow:
while (len >= 10) {
- str_cat(res, nul10, 10);
+ rb_str_cat(res, nul10, 10);
len -= 10;
}
- str_cat(res, nul10, len);
+ rb_str_cat(res, nul10, len);
break;
case 'X':
shrink:
if (RSTRING(res)->len < len)
- ArgError("X outside of string");
+ rb_raise(rb_eArgError, "X outside of string");
RSTRING(res)->len -= len;
RSTRING(res)->ptr[RSTRING(res)->len] = '\0';
break;
@@ -437,12 +444,12 @@ pack_pack(ary, fmt)
break;
case '%':
- ArgError("% may only be used in unpack");
+ rb_raise(rb_eArgError, "% may only be used in unpack");
break;
case 'u':
case 'm':
- from = obj_as_string(NEXTFROM);
+ from = rb_obj_as_string(NEXTFROM);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
@@ -463,6 +470,29 @@ pack_pack(ary, fmt)
}
break;
+ case 'M':
+ from = rb_obj_as_string(NEXTFROM);
+ if (len <= 1)
+ len = 72;
+ qpencode(res, from, len);
+ break;
+
+ case 'P':
+ len = 1;
+ /* FALL THROUGH */
+ case 'p':
+ while (len-- > 0) {
+ char *t;
+ from = NEXTFROM;
+ if (NIL_P(from)) t = "";
+ else {
+ t = STR2CSTR(from);
+ pack_add_ptr(res, from);
+ }
+ rb_str_cat(res, (char*)&t, sizeof(char*));
+ }
+ break;
+
default:
break;
}
@@ -479,42 +509,124 @@ static char b64_table[] =
static void
encodes(str, s, len, type)
VALUE str;
- UCHAR *s;
+ char *s;
int len;
int type;
{
- char hunk[4];
- UCHAR *p, *pend;
+ char *buff = ALLOCA_N(char, len * 4 / 3 + 6);
+ int i = 0;
char *trans = type == 'u' ? uu_table : b64_table;
int padding;
if (type == 'u') {
- *hunk = len + ' ';
- str_cat(str, hunk, 1);
+ buff[i++] = len + ' ';
padding = '`';
}
else {
padding = '=';
}
- while (len > 0) {
- hunk[0] = trans[077 & (*s >> 2)];
- hunk[1] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- hunk[2] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
- hunk[3] = trans[077 & s[2]];
- str_cat(str, hunk, 4);
+ while (len >= 3) {
+ 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;
}
- p = RSTRING(str)->ptr;
- pend = RSTRING(str)->ptr + RSTRING(str)->len;
- if (len == -1) {
- pend[-1] = padding;
+ 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;
+ }
+ buff[i++] = '\n';
+ rb_str_cat(str, buff, i);
+}
+
+static char hex_table[] = "0123456789ABCDEF";
+
+static void
+qpencode(str, from, len)
+ VALUE str, from;
+ int len;
+{
+ char buff[1024];
+ int i = 0, n = 0, prev = EOF;
+ unsigned char *s = RSTRING(from)->ptr;
+ unsigned char *send = s + RSTRING(from)->len;
+
+ 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_str_cat(str, buff, i);
+ i = 0;
+ }
+ s++;
+ }
+ if (n > 0) {
+ buff[i++] = '=';
+ buff[i++] = '\n';
}
- else if (len == -2) {
- pend[-2] = padding;
- pend[-1] = padding;
+ if (i > 0) {
+ rb_str_cat(str, buff, i);
+ }
+}
+
+#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
+static __inline__ int
+#else
+static int
+#endif
+hex2num(c)
+ 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;
}
- str_cat(str, "\n", 1);
}
static VALUE
@@ -522,27 +634,25 @@ pack_unpack(str, fmt)
VALUE str, fmt;
{
static char *hexdigits = "0123456789abcdef0123456789ABCDEFx";
- UCHAR *s, *send;
- UCHAR *p, *pend;
+ char *s, *send;
+ char *p, *pend;
VALUE ary;
char type;
int len;
- Check_Type(fmt, T_STRING);
-
- s = RSTRING(str)->ptr;
- send = s + RSTRING(str)->len;
- p = RSTRING(fmt)->ptr;
- pend = p + RSTRING(fmt)->len;
+ s = rb_str2cstr(str, &len);
+ send = s + len;
+ p = rb_str2cstr(fmt, &len);
+ pend = p + len;
- ary = ary_new();
+ ary = rb_ary_new();
while (p < pend) {
type = *p++;
if (*p == '*') {
len = send - s;
p++;
}
- else if (isdigit(*p)) {
+ else if (ISDIGIT(*p)) {
len = strtoul(p, (char**)&p, 10);
}
else {
@@ -551,41 +661,41 @@ pack_unpack(str, fmt)
switch (type) {
case '%':
- ArgError("% is not supported(yet)");
+ rb_raise(rb_eArgError, "% is not supported(yet)");
break;
case 'A':
if (len > send - s) len = send - s;
{
int end = len;
- UCHAR *t = s + len - 1;
+ char *t = s + len - 1;
while (t >= s) {
if (*t != ' ' && *t != '\0') break;
t--;
len--;
}
- ary_push(ary, str_new(s, len));
+ rb_ary_push(ary, rb_str_new(s, len));
s += end;
}
break;
case 'a':
if (len > send - s) len = send - s;
- ary_push(ary, str_new(s, len));
+ rb_ary_push(ary, rb_str_new(s, len));
s += len;
break;
case 'b':
{
VALUE bitstr;
- UCHAR *t;
+ char *t;
int bits, i;
if (p[-1] == '*' || len > (send - s) * 8)
len = (send - s) * 8;
bits = 0;
- ary_push(ary, bitstr = str_new(0, len));
+ rb_ary_push(ary, bitstr = rb_str_new(0, len));
t = RSTRING(bitstr)->ptr;
for (i=0; i<len; i++) {
if (i & 7) bits >>= 1;
@@ -598,13 +708,13 @@ pack_unpack(str, fmt)
case 'B':
{
VALUE bitstr;
- UCHAR *t;
+ char *t;
int bits, i;
if (p[-1] == '*' || len > (send - s) * 8)
len = (send - s) * 8;
bits = 0;
- ary_push(ary, bitstr = str_new(0, len));
+ rb_ary_push(ary, bitstr = rb_str_new(0, len));
t = RSTRING(bitstr)->ptr;
for (i=0; i<len; i++) {
if (i & 7) bits <<= 1;
@@ -617,13 +727,13 @@ pack_unpack(str, fmt)
case 'h':
{
VALUE bitstr;
- UCHAR *t;
+ char *t;
int bits, i;
if (p[-1] == '*' || len > (send - s) * 2)
len = (send - s) * 2;
bits = 0;
- ary_push(ary, bitstr = str_new(0, len));
+ rb_ary_push(ary, bitstr = rb_str_new(0, len));
t = RSTRING(bitstr)->ptr;
for (i=0; i<len; i++) {
if (i & 1)
@@ -638,13 +748,13 @@ pack_unpack(str, fmt)
case 'H':
{
VALUE bitstr;
- UCHAR *t;
+ char *t;
int bits, i;
if (p[-1] == '*' || len > (send - s) * 2)
len = (send - s) * 2;
bits = 0;
- ary_push(ary, bitstr = str_new(0, len));
+ rb_ary_push(ary, bitstr = rb_str_new(0, len));
t = RSTRING(bitstr)->ptr;
for (i=0; i<len; i++) {
if (i & 1)
@@ -662,7 +772,7 @@ pack_unpack(str, fmt)
while (len-- > 0) {
int c = *s++;
if (c > (char)127) c-=256;
- ary_push(ary, INT2FIX(c));
+ rb_ary_push(ary, INT2FIX(c));
}
break;
@@ -670,8 +780,8 @@ pack_unpack(str, fmt)
if (len > send - s)
len = send - s;
while (len-- > 0) {
- UCHAR c = *s++;
- ary_push(ary, INT2FIX(c));
+ unsigned char c = *s++;
+ rb_ary_push(ary, INT2FIX(c));
}
break;
@@ -682,7 +792,7 @@ pack_unpack(str, fmt)
short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
- ary_push(ary, INT2FIX(tmp));
+ rb_ary_push(ary, INT2FIX(tmp));
}
break;
@@ -693,7 +803,7 @@ pack_unpack(str, fmt)
unsigned short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
- ary_push(ary, INT2FIX(tmp));
+ rb_ary_push(ary, INT2FIX(tmp));
}
break;
@@ -704,7 +814,7 @@ pack_unpack(str, fmt)
int tmp;
memcpy(&tmp, s, sizeof(int));
s += sizeof(int);
- ary_push(ary, int2inum(tmp));
+ rb_ary_push(ary, rb_int2inum(tmp));
}
break;
@@ -715,7 +825,7 @@ pack_unpack(str, fmt)
unsigned int tmp;
memcpy(&tmp, s, sizeof(int));
s += sizeof(int);
- ary_push(ary, int2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -726,7 +836,7 @@ pack_unpack(str, fmt)
long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
- ary_push(ary, int2inum(tmp));
+ rb_ary_push(ary, rb_int2inum(tmp));
}
break;
@@ -737,7 +847,7 @@ pack_unpack(str, fmt)
unsigned long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
- ary_push(ary, uint2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -749,7 +859,7 @@ pack_unpack(str, fmt)
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
tmp = ntohs(tmp);
- ary_push(ary, uint2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -761,7 +871,7 @@ pack_unpack(str, fmt)
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
tmp = ntohl(tmp);
- ary_push(ary, uint2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -773,7 +883,7 @@ pack_unpack(str, fmt)
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
tmp = vtohs(tmp);
- ary_push(ary, uint2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -785,7 +895,7 @@ pack_unpack(str, fmt)
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
tmp = vtohl(tmp);
- ary_push(ary, uint2inum(tmp));
+ rb_ary_push(ary, rb_uint2inum(tmp));
}
break;
@@ -797,7 +907,7 @@ pack_unpack(str, fmt)
float tmp;
memcpy(&tmp, s, sizeof(float));
s += sizeof(float);
- ary_push(ary, float_new((double)tmp));
+ rb_ary_push(ary, rb_float_new((double)tmp));
}
break;
@@ -809,14 +919,14 @@ pack_unpack(str, fmt)
double tmp;
memcpy(&tmp, s, sizeof(double));
s += sizeof(double);
- ary_push(ary, float_new(tmp));
+ rb_ary_push(ary, rb_float_new(tmp));
}
break;
case 'u':
{
- VALUE str = str_new(0, (send - s)*3/4);
- UCHAR *ptr = RSTRING(str)->ptr;
+ VALUE str = rb_str_new(0, (send - s)*3/4);
+ char *ptr = RSTRING(str)->ptr;
int total = 0;
while (s < send && *s > ' ' && *s < 'a') {
@@ -863,15 +973,14 @@ pack_unpack(str, fmt)
s += 2; /* possible checksum byte */
}
RSTRING(str)->len = total;
- ary_push(ary, str);
+ rb_ary_push(ary, str);
}
break;
case 'm':
{
- VALUE str = str_new(0, (send - s)*3/4);
- UCHAR *ptr = RSTRING(str)->ptr;
- int total = 0;
+ VALUE str = rb_str_new(0, (send - s)*3/4);
+ char *ptr = RSTRING(str)->ptr;
int a,b,c,d;
static int first = 1;
static int b64_xtable[256];
@@ -906,7 +1015,33 @@ pack_unpack(str, fmt)
*ptr++ = b << 4 | c >> 2;
}
RSTRING(str)->len = ptr - RSTRING(str)->ptr;
- ary_push(ary, str);
+ rb_ary_push(ary, str);
+ }
+ break;
+
+ case 'M':
+ {
+ VALUE str = rb_str_new(0, send - s);
+ char *ptr = RSTRING(str)->ptr;
+ int c1, c2;
+
+ while (s < send) {
+ if (*s == '=') {
+ if (++s == send) break;
+ 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++;
+ }
+ RSTRING(str)->len = ptr - RSTRING(str)->ptr;
+ rb_ary_push(ary, str);
}
break;
@@ -916,16 +1051,46 @@ pack_unpack(str, fmt)
case 'X':
if (len > s - RSTRING(str)->ptr)
- ArgError("X outside of string");
+ rb_raise(rb_eArgError, "X outside of string");
s -= len;
break;
case 'x':
if (len > send - s)
- ArgError("x outside of string");
+ rb_raise(rb_eArgError, "x outside of string");
s += len;
break;
+ case 'P':
+ if (sizeof(char *) <= send - s) {
+ char *t;
+ VALUE str = rb_str_new(0, 0);
+ memcpy(&t, s, sizeof(char *));
+ s += sizeof(char *);
+ if (t)
+ rb_str_cat(str, t, len);
+ rb_ary_push(ary, str);
+ }
+ break;
+
+ case 'p':
+ if (len > (send - s) / sizeof(char *))
+ len = (send - s) / sizeof(char *);
+ while (len-- > 0) {
+ if (send - s < sizeof(char *))
+ break;
+ else {
+ char *t;
+ VALUE str = rb_str_new(0, 0);
+ memcpy(&t, s, sizeof(char *));
+ s += sizeof(char *);
+ if (t)
+ rb_str_cat(str, t, strlen(t));
+ rb_ary_push(ary, str);
+ }
+ }
+ break;
+
default:
break;
}
@@ -937,6 +1102,6 @@ pack_unpack(str, fmt)
void
Init_pack()
{
- rb_define_method(cArray, "pack", pack_pack, 1);
- rb_define_method(cString, "unpack", pack_unpack, 1);
+ rb_define_method(rb_cArray, "pack", pack_pack, 1);
+ rb_define_method(rb_cString, "unpack", pack_unpack, 1);
}
diff --git a/parse.y b/parse.y
index 4bf13cf398..a4142bbe20 100644
--- a/parse.y
+++ b/parse.y
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 28 18:02:42 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -32,23 +32,18 @@
#define ID_ATTRSET 0x04
#define ID_CONST 0x05
-#define is_id_nonop(id) ((id)>LAST_TOKEN)
-#define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
-#define is_global_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
-#define is_instance_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
-#define is_attrset_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
-#define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
+#define is_id_notop(id) ((id)>LAST_TOKEN)
+#define is_local_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
+#define is_global_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
+#define is_instance_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
+#define is_attrset_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
+#define is_const_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-struct op_tbl {
- ID token;
- char *name;
-};
-
-NODE *eval_tree0 = 0;
-NODE *eval_tree = 0;
+NODE *ruby_eval_tree_begin = 0;
+NODE *ruby_eval_tree = 0;
-char *sourcefile; /* current source file */
-int sourceline; /* current line no. */
+char *ruby_sourcefile; /* current source file */
+int ruby_sourceline; /* current line no. */
static int yylex();
static int yyerror();
@@ -57,9 +52,10 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
- EXPR_ARG, /* newline significant, +/- may be a sign. */
- EXPR_FNAME, /* ignore newline, +/- is a operator. */
- EXPR_CLASS, /* immediate after `class' no here document. */
+ EXPR_ARG, /* newline significant, +/- is a operator. */
+ EXPR_FNAME, /* ignore newline, +/- is a operator, no reserved words. */
+ EXPR_DOT, /* immediate after `.', no reserved words. */
+ EXPR_CLASS, /* immediate after `class', no here document. */
} lex_state;
static int class_nest = 0;
@@ -80,15 +76,20 @@ static NODE *arg_add();
static NODE *call_op();
static int in_defined = 0;
+static NODE *arg_blk_pass();
+static NODE *new_call();
+static NODE *new_fcall();
+
static NODE *gettable();
static NODE *assignable();
static NODE *aryset();
static NODE *attrset();
-static void backref_error();
+static void rb_backref_error();
static NODE *match_gen();
static void local_push();
static void local_pop();
+static int local_append();
static int local_cnt();
static int local_id();
static ID *local_tbl();
@@ -97,9 +98,6 @@ static struct RVarmap *dyna_push();
static void dyna_pop();
static int dyna_in_block();
-VALUE dyna_var_asgn();
-VALUE dyna_var_defined();
-
#define cref_push() NEW_CREF()
static void cref_pop();
static NODE *cur_cref;
@@ -158,46 +156,51 @@ static void top_local_setup();
kDEFINED
klBEGIN
klEND
+ k__LINE__
+ k__FILE__
-%token <id> IDENTIFIER FID GVAR IVAR CONSTANT
-%token <val> INTEGER FLOAT STRING XSTRING REGEXP
-%token <node> DSTRING DXSTRING DREGEXP NTH_REF BACK_REF
+%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
+%token <val> tINTEGER tFLOAT tSTRING tXSTRING tREGEXP
+%token <node> tDSTRING tDXSTRING tDREGEXP tNTH_REF tBACK_REF
%type <node> singleton
%type <val> literal numeric
%type <node> compstmt stmts stmt expr arg primary command_call method_call
-%type <node> if_tail opt_else case_body cases rescue ensure iterator
-%type <node> call_args call_args0 ret_args args mrhs opt_list var_ref
-%type <node> superclass f_arglist f_args f_optarg f_opt
-%type <node> array assoc_list assocs assoc undef_list
+%type <node> if_tail opt_else case_body cases rescue ensure
+%type <node> opt_call_args call_args ret_args args when_args
+%type <node> aref_args opt_block_arg block_arg
+%type <node> mrhs opt_list superclass iterator var_ref
+%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
+%type <node> array assoc_list assocs assoc undef_list backref
%type <node> iter_var opt_iter_var iter_block iter_do_block
-%type <node> mlhs mlhs_head mlhs_tail lhs backref
-%type <id> variable symbol operation assoc_kw
-%type <id> cname fname op rest_arg
+%type <node> mlhs mlhs_head mlhs_tail mlhs_basic mlhs_entry mlhs_item lhs
+%type <id> variable symbol operation
+%type <id> cname fname op f_rest_arg
%type <num> f_arg
-%token oUPLUS /* unary+ */
-%token MINUS /* unary- */
-%token POW /* ** */
-%token CMP /* <=> */
-%token EQ /* == */
-%token EQQ /* === */
-%token NEQ /* != <> */
-%token GEQ /* >= */
-%token LEQ /* <= */
-%token ANDOP OROP /* && and || */
-%token MATCH NMATCH /* =~ and !~ */
-%token DOT2 DOT3 /* .. and ... */
-%token AREF ASET /* [] and []= */
-%token LSHFT RSHFT /* << and >> */
-%token COLON2 /* :: */
-%token <id> OP_ASGN /* +=, -= etc. */
-%token ASSOC /* => */
-%token KW_ASSOC /* -> */
-%token LPAREN /* ( */
-%token LBRACK /* [ */
-%token LBRACE /* { */
-%token STAR /* * */
-%token SYMBEG
+%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 tLBRACK /* [ */
+%token tLBRACE /* { */
+%token tSTAR /* * */
+%token tAMPER /* & */
+%token tSYMBEG
/*
* precedence table
@@ -207,36 +210,39 @@ static void top_local_setup();
%left kOR kAND
%right kNOT
%nonassoc kDEFINED
-%right '=' OP_ASGN
-%nonassoc DOT2 DOT3
-%left OROP
-%left ANDOP
-%nonassoc CMP EQ EQQ NEQ MATCH NMATCH
-%left '>' GEQ '<' LEQ
+%right '=' tOP_ASGN
+%right '?' ':'
+%nonassoc tDOT2 tDOT3
+%left tOROP
+%left tANDOP
+%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
+%left '>' tGEQ '<' tLEQ
%left '|' '^'
%left '&'
-%left LSHFT RSHFT
+%left tLSHFT tRSHFT
%left '+' '-'
%left '*' '/' '%'
-%right '!' '~' UPLUS UMINUS
-%right POW
+%right '!' '~' tUPLUS tUMINUS
+%right tPOW
%token LAST_TOKEN
%%
program : {
+ $<vars>$ = ruby_dyna_vars;
lex_state = EXPR_BEG;
top_local_init();
NEW_CREF0(); /* initialize constant c-ref */
- if ((VALUE)the_class == cObject) class_nest = 0;
+ if ((VALUE)ruby_class == rb_cObject) class_nest = 0;
else class_nest = 1;
}
compstmt
{
- eval_tree = block_append(eval_tree, $2);
+ ruby_eval_tree = block_append(ruby_eval_tree, $2);
top_local_setup();
cur_cref = 0;
class_nest = 0;
+ ruby_dyna_vars = $<vars>1;
}
compstmt : stmts opt_terms
@@ -260,6 +266,9 @@ stmts : /* none */
stmt : iterator iter_do_block
{
+ if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
+ rb_compile_error("both block arg and actual block given");
+ }
$2->nd_iter = $1;
$$ = $2;
fixpos($$, $2);
@@ -270,13 +279,13 @@ stmt : iterator iter_do_block
yyerror("alias within method");
$$ = NEW_ALIAS($2, $4);
}
- | kALIAS GVAR GVAR
+ | kALIAS tGVAR tGVAR
{
if (cur_mid || in_single)
yyerror("alias within method");
$$ = NEW_VALIAS($2, $3);
}
- | kALIAS GVAR BACK_REF
+ | kALIAS tGVAR tBACK_REF
{
char buf[3];
@@ -285,7 +294,7 @@ stmt : iterator iter_do_block
sprintf(buf, "$%c", $3->nd_nth);
$$ = NEW_VALIAS($2, rb_intern(buf));
}
- | kALIAS GVAR NTH_REF
+ | kALIAS tGVAR tNTH_REF
{
yyerror("can't make alias for the number variables");
$$ = 0;
@@ -299,12 +308,14 @@ stmt : iterator iter_do_block
| stmt kIF_MOD expr
{
value_expr($3);
- $$ = node_newnode(NODE_AND, cond($3), $1);
+ $$ = NEW_IF(cond($3), $1, 0);
+ fixpos($$, $3);
}
| stmt kUNLESS_MOD expr
{
value_expr($3);
- $$ = node_newnode(NODE_OR, cond($3), $1);
+ $$ = NEW_UNLESS(cond($3), $1, 0);
+ fixpos($$, $3);
}
| stmt kWHILE_MOD expr
{
@@ -316,7 +327,7 @@ stmt : iterator iter_do_block
$$ = NEW_WHILE(cond($3), $1, 1);
}
}
- | expr kUNTIL_MOD expr
+ | stmt kUNTIL_MOD expr
{
value_expr($3);
if (nd_type($1) == NODE_BEGIN) {
@@ -326,7 +337,7 @@ stmt : iterator iter_do_block
$$ = NEW_UNTIL(cond($3), $1, 1);
}
}
- | klBEGIN
+ | klBEGIN
{
if (cur_mid || in_single) {
yyerror("BEGIN in method");
@@ -336,7 +347,8 @@ stmt : iterator iter_do_block
}
'{' compstmt '}'
{
- eval_tree0 = block_append(eval_tree0,NEW_PREEXE($4));
+ ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
+ NEW_PREEXE($4));
local_pop();
$$ = 0;
}
@@ -361,7 +373,7 @@ expr : mlhs '=' mrhs
value_expr($2);
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
- $$ = NEW_RET($2);
+ $$ = NEW_RETURN($2);
}
| kYIELD ret_args
{
@@ -382,31 +394,31 @@ expr : mlhs '=' mrhs
value_expr($2);
$$ = NEW_NOT(cond($2));
}
- | '!' command_call
+ | '!' command_call
{
value_expr($2);
$$ = NEW_NOT(cond($2));
}
| arg
-command_call : operation call_args0
+command_call : operation call_args
{
- $$ = NEW_FCALL($1, $2);
+ $$ = new_fcall($1, $2);
fixpos($$, $2);
}
- | primary '.' operation call_args0
+ | primary '.' operation call_args
{
value_expr($1);
- $$ = NEW_CALL($1, $3, $4);
+ $$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | primary COLON2 operation call_args0
+ | primary tCOLON2 operation call_args
{
value_expr($1);
- $$ = NEW_CALL($1, $3, $4);
+ $$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | kSUPER call_args0
+ | kSUPER call_args
{
if (!cur_mid && !in_single && !in_defined)
yyerror("super called outside of method");
@@ -414,11 +426,23 @@ command_call : operation call_args0
fixpos($$, $2);
}
-mlhs : mlhs_head
+mlhs : mlhs_basic
+ | tLPAREN mlhs_entry ')'
+ {
+ $$ = $2;
+ }
+
+mlhs_entry : mlhs_basic
+ | tLPAREN mlhs_entry ')'
+ {
+ $$ = NEW_MASGN(NEW_LIST($2), 0);
+ }
+
+mlhs_basic : mlhs_head
{
$$ = NEW_MASGN(NEW_LIST($1), 0);
}
- | mlhs_head STAR lhs
+ | mlhs_head tSTAR lhs
{
$$ = NEW_MASGN(NEW_LIST($1), $3);
}
@@ -426,22 +450,31 @@ mlhs : mlhs_head
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2), 0);
}
- | mlhs_head mlhs_tail ',' STAR lhs
+ | mlhs_head mlhs_tail ',' tSTAR lhs
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5);
}
- | STAR lhs
+ | tSTAR lhs
{
$$ = NEW_MASGN(0, $2);
}
-mlhs_head : lhs ','
+mlhs_item : lhs
+ | tLPAREN mlhs_entry ')'
+ {
+ $$ = $2;
+ }
+
+mlhs_head : mlhs_item ','
+ {
+ $$ = $1;
+ }
-mlhs_tail : lhs
+mlhs_tail : mlhs_item
{
$$ = NEW_LIST($1);
}
- | mlhs_tail ',' lhs
+ | mlhs_tail ',' mlhs_item
{
$$ = list_append($1, $3);
}
@@ -450,38 +483,39 @@ lhs : variable
{
$$ = assignable($1, 0);
}
- | primary '[' call_args ']'
+ | primary '[' aref_args ']'
{
$$ = aryset($1, $3, 0);
}
- | primary '.' IDENTIFIER
- {
- $$ = attrset($1, $3, 0);
- }
- | primary '.' CONSTANT
+ | primary '.' tIDENTIFIER
{
$$ = attrset($1, $3, 0);
}
| backref
{
- backref_error($1);
+ rb_backref_error($1);
$$ = 0;
}
-cname : IDENTIFIER
+cname : tIDENTIFIER
{
yyerror("class/module name must be CONSTANT");
}
- | CONSTANT
+ | tCONSTANT
-fname : IDENTIFIER
- | CONSTANT
- | FID
+fname : tIDENTIFIER
+ | tCONSTANT
+ | tFID
| op
{
lex_state = EXPR_END;
$$ = $1;
}
+ | reswords
+ {
+ lex_state = EXPR_END;
+ $$ = $<id>1;
+ }
undef_list : fname
{
@@ -492,46 +526,61 @@ undef_list : fname
$$ = block_append($1, NEW_UNDEF($4));
}
-op : DOT2 { $$ = DOT2; }
+op : tDOT2 { $$ = tDOT2; }
| '|' { $$ = '|'; }
| '^' { $$ = '^'; }
| '&' { $$ = '&'; }
- | CMP { $$ = CMP; }
- | EQ { $$ = EQ; }
- | EQQ { $$ = EQQ; }
- | MATCH { $$ = MATCH; }
+ | tCMP { $$ = tCMP; }
+ | tEQ { $$ = tEQ; }
+ | tEQQ { $$ = tEQQ; }
+ | tMATCH { $$ = tMATCH; }
| '>' { $$ = '>'; }
- | GEQ { $$ = GEQ; }
+ | tGEQ { $$ = tGEQ; }
| '<' { $$ = '<'; }
- | LEQ { $$ = LEQ; }
- | LSHFT { $$ = LSHFT; }
- | RSHFT { $$ = RSHFT; }
+ | tLEQ { $$ = tLEQ; }
+ | tLSHFT { $$ = tLSHFT; }
+ | tRSHFT { $$ = tRSHFT; }
| '+' { $$ = '+'; }
| '-' { $$ = '-'; }
| '*' { $$ = '*'; }
- | STAR { $$ = '*'; }
+ | tSTAR { $$ = '*'; }
| '/' { $$ = '/'; }
| '%' { $$ = '%'; }
- | POW { $$ = POW; }
+ | tPOW { $$ = tPOW; }
| '~' { $$ = '~'; }
- | UPLUS { $$ = UMINUS; }
- | UMINUS { $$ = UPLUS; }
- | AREF { $$ = AREF; }
- | ASET { $$ = ASET; }
+ | tUPLUS { $$ = tUPLUS; }
+ | tUMINUS { $$ = tUMINUS; }
+ | tAREF { $$ = tAREF; }
+ | tASET { $$ = tASET; }
| '`' { $$ = '`'; }
-arg : variable '=' arg
+reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
+ | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
+ | kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
+ | kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
+ | kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
+ | kWHILE_MOD | kYIELD
+
+arg : variable '=' {$$ = assignable($1, 0);} arg
{
- value_expr($3);
- $$ = assignable($1, $3);
- fixpos($$, $3);
+ $$ = $<node>3;
+ if ($$) {
+ $$->nd_value = $4;
+ fixpos($$, $4);
+ }
}
- | primary '[' call_args ']' '=' arg
+ | primary '[' aref_args ']' '=' arg
{
$$ = aryset($1, $3, $6);
fixpos($$, $1);
}
- | primary '.' IDENTIFIER '=' arg
+ | primary '.' tIDENTIFIER '=' arg
+ {
+ $$ = attrset($1, $3, $5);
+ fixpos($$, $5);
+ }
+ | primary '.' tCONSTANT '=' arg
{
$$ = attrset($1, $3, $5);
fixpos($$, $5);
@@ -539,46 +588,72 @@ arg : variable '=' arg
| backref '=' arg
{
value_expr($3);
- backref_error($1);
+ rb_backref_error($1);
$$ = 0;
}
- | variable OP_ASGN arg
+ | variable tOP_ASGN {$$ = assignable($1, 0);} arg
{
- value_expr($3);
- if (is_local_id($1)&&!local_id($1)&&dyna_in_block())
- dyna_var_asgn($1, TRUE);
- $$ = assignable($1, call_op(gettable($1), $2, 1, $3));
- fixpos($$, $3);
+ if ($2 == tOROP) {
+ $<node>3->nd_value = $4;
+ $$ = NEW_OP_ASGN_OR(gettable($1), $<node>3);
+ }
+ else if ($2 == tANDOP) {
+ $<node>3->nd_value = $4;
+ $$ = NEW_OP_ASGN_AND(gettable($1), $<node>3);
+ }
+ else {
+ $$ = $<node>3;
+ $$->nd_value = call_op(gettable($1), $2, 1, $4);
+ }
+ fixpos($$, $4);
}
- | primary '[' call_args ']' OP_ASGN arg
+ | primary '[' aref_args ']' tOP_ASGN arg
{
NODE *args = NEW_LIST($6);
- list_append($3, NEW_NIL());
+ list_append($3, NEW_NIL());
list_concat(args, $3);
+ if ($5 == tOROP) {
+ $5 = 0;
+ }
+ else if ($5 == tANDOP) {
+ $5 = 1;
+ }
$$ = NEW_OP_ASGN1($1, $5, args);
fixpos($$, $1);
}
- | primary '.' IDENTIFIER OP_ASGN arg
+ | primary '.' tIDENTIFIER tOP_ASGN arg
{
+ if ($4 == tOROP) {
+ $4 = 0;
+ }
+ else if ($4 == tANDOP) {
+ $4 = 1;
+ }
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
fixpos($$, $1);
}
- | primary '.' CONSTANT OP_ASGN arg
+ | primary '.' tCONSTANT tOP_ASGN arg
{
+ if ($4 == tOROP) {
+ $4 = 0;
+ }
+ else if ($4 == tANDOP) {
+ $4 = 1;
+ }
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
fixpos($$, $1);
}
- | backref OP_ASGN arg
+ | backref tOP_ASGN arg
{
- backref_error($1);
+ rb_backref_error($1);
$$ = 0;
}
- | arg DOT2 arg
+ | arg tDOT2 arg
{
$$ = NEW_DOT2($1, $3);
}
- | arg DOT3 arg
+ | arg tDOT3 arg
{
$$ = NEW_DOT3($1, $3);
}
@@ -602,17 +677,17 @@ arg : variable '=' arg
{
$$ = call_op($1, '%', 1, $3);
}
- | arg POW arg
+ | arg tPOW arg
{
- $$ = call_op($1, POW, 1, $3);
+ $$ = call_op($1, tPOW, 1, $3);
}
- | UPLUS arg
+ | tUPLUS arg
{
- $$ = call_op($2, UPLUS, 0);
+ $$ = call_op($2, tUPLUS, 0);
}
- | UMINUS arg
+ | tUMINUS arg
{
- $$ = call_op($2, UMINUS, 0);
+ $$ = call_op($2, tUMINUS, 0);
}
| arg '|' arg
{
@@ -626,43 +701,43 @@ arg : variable '=' arg
{
$$ = call_op($1, '&', 1, $3);
}
- | arg CMP arg
+ | arg tCMP arg
{
- $$ = call_op($1, CMP, 1, $3);
+ $$ = call_op($1, tCMP, 1, $3);
}
| arg '>' arg
{
$$ = call_op($1, '>', 1, $3);
}
- | arg GEQ arg
+ | arg tGEQ arg
{
- $$ = call_op($1, GEQ, 1, $3);
+ $$ = call_op($1, tGEQ, 1, $3);
}
| arg '<' arg
{
$$ = call_op($1, '<', 1, $3);
}
- | arg LEQ arg
+ | arg tLEQ arg
{
- $$ = call_op($1, LEQ, 1, $3);
+ $$ = call_op($1, tLEQ, 1, $3);
}
- | arg EQ arg
+ | arg tEQ arg
{
- $$ = call_op($1, EQ, 1, $3);
+ $$ = call_op($1, tEQ, 1, $3);
}
- | arg EQQ arg
+ | arg tEQQ arg
{
- $$ = call_op($1, EQQ, 1, $3);
+ $$ = call_op($1, tEQQ, 1, $3);
}
- | arg NEQ arg
+ | arg tNEQ arg
{
- $$ = NEW_NOT(call_op($1, EQ, 1, $3));
+ $$ = NEW_NOT(call_op($1, tEQ, 1, $3));
}
- | arg MATCH arg
+ | arg tMATCH arg
{
$$ = match_gen($1, $3);
}
- | arg NMATCH arg
+ | arg tNMATCH arg
{
$$ = NEW_NOT(match_gen($1, $3));
}
@@ -675,19 +750,19 @@ arg : variable '=' arg
{
$$ = call_op($2, '~', 0);
}
- | arg LSHFT arg
+ | arg tLSHFT arg
{
- $$ = call_op($1, LSHFT, 1, $3);
+ $$ = call_op($1, tLSHFT, 1, $3);
}
- | arg RSHFT arg
+ | arg tRSHFT arg
{
- $$ = call_op($1, RSHFT, 1, $3);
+ $$ = call_op($1, tRSHFT, 1, $3);
}
- | arg ANDOP arg
+ | arg tANDOP arg
{
$$ = logop(NODE_AND, $1, $3);
}
- | arg OROP arg
+ | arg tOROP arg
{
$$ = logop(NODE_OR, $1, $3);
}
@@ -696,56 +771,92 @@ arg : variable '=' arg
in_defined = 0;
$$ = NEW_DEFINED($4);
}
+ | arg '?' arg ':' arg
+ {
+ value_expr($1);
+ $$ = NEW_IF(cond($1), $3, $5);
+ fixpos($$, $1);
+ }
| primary
{
$$ = $1;
}
-call_args : /* none */
+aref_args : opt_call_args
+ {
+ if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
+ rb_compile_error("block argument should not be given");
+ }
+ $$ = $1;
+ }
+
+opt_call_args : /* none */
{
$$ = 0;
}
- | call_args0 opt_nl
+ | call_args opt_nl
-call_args0 : command_call
+call_args : command_call
{
value_expr($1);
$$ = NEW_LIST($1);
}
- | args
- | args ',' STAR arg
+ | args opt_block_arg
+ {
+ $$ = arg_blk_pass($1, $2);
+ }
+ | args ',' tSTAR arg opt_block_arg
{
$$ = arg_add($1, $4);
+ $$ = arg_blk_pass($$, $5);
}
- | assocs
+ | assocs opt_block_arg
{
$$ = NEW_LIST(NEW_HASH($1));
+ $$ = arg_blk_pass($$, $2);
}
- | assocs ',' STAR arg
+ | assocs ',' tSTAR arg opt_block_arg
{
- $$ = NEW_LIST(NEW_HASH($1));
- $$ = arg_add($$, $4);
+ $$ = arg_add(NEW_LIST(NEW_HASH($1)), $4);
+ $$ = arg_blk_pass($$, $5);
}
- | args ',' assocs
+ | args ',' assocs opt_block_arg
{
$$ = list_append($1, NEW_HASH($3));
+ $$ = arg_blk_pass($$, $4);
}
- | args ',' assocs ',' STAR arg
+ | args ',' assocs ',' tSTAR arg opt_block_arg
{
- $$ = list_append($1, NEW_HASH($3));
- $$ = arg_add($$, $6);
+ $$ = arg_add(list_append($1, NEW_HASH($3)), $6);
+ $$ = arg_blk_pass($$, $7);
}
- | STAR arg
+ | tSTAR arg opt_block_arg
{
value_expr($2);
+ $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
+ }
+ | block_arg
+
+block_arg : tAMPER arg
+ {
+ value_expr($2);
+ $$ = NEW_BLOCK_PASS($2);
+ }
+
+opt_block_arg : ',' block_arg
+ {
$$ = $2;
}
+ | /* none */
+ {
+ $$ = 0;
+ }
-opt_list : /* none */
+opt_list : args
+ | /* none */
{
$$ = 0;
}
- | args
args : arg
{
@@ -762,32 +873,36 @@ mrhs : args
{
if ($1 &&
nd_type($1) == NODE_ARRAY &&
- $1->nd_next == 0) {
+ $1->nd_next == 0)
+ {
$$ = $1->nd_head;
}
else {
$$ = $1;
}
}
- | args ',' STAR arg
+ | args ',' tSTAR arg
{
+ value_expr($4);
$$ = arg_add($1, $4);
}
- | STAR arg
+ | tSTAR arg
{
value_expr($2);
$$ = $2;
}
-ret_args : call_args0
+ret_args : call_args
{
- if ($1 &&
- nd_type($1) == NODE_ARRAY &&
- $1->nd_next == 0) {
- $$ = $1->nd_head;
- }
- else {
- $$ = $1;
+ $$ = $1;
+ if ($1) {
+ if (nd_type($1) == NODE_ARRAY &&
+ $1->nd_next == 0) {
+ $$ = $1->nd_head;
+ }
+ else if (nd_type($1) == NODE_BLOCK_PASS) {
+ rb_compile_error("block argument should not be given");
+ }
}
}
@@ -801,29 +916,39 @@ primary : literal
{
$$ = NEW_LIT($1);
}
- | primary COLON2 cname
+ | primary tCOLON2 tCONSTANT
{
+ value_expr($1);
$$ = NEW_COLON2($1, $3);
}
- | STRING
+ | primary tCOLON2 tIDENTIFIER
+ {
+ value_expr($1);
+ $$ = new_call($1, $3, 0);
+ }
+ | tCOLON3 cname
+ {
+ $$ = NEW_COLON3($2);
+ }
+ | tSTRING
{
$$ = NEW_STR($1);
}
- | DSTRING
- | XSTRING
+ | tDSTRING
+ | tXSTRING
{
$$ = NEW_XSTR($1);
}
- | DXSTRING
- | DREGEXP
+ | tDXSTRING
+ | tDREGEXP
| var_ref
| backref
- | primary '[' call_args ']'
+ | primary '[' aref_args ']'
{
value_expr($1);
- $$ = NEW_CALL($1, AREF, $3);
+ $$ = NEW_CALL($1, tAREF, $3);
}
- | LBRACK array ']'
+ | tLBRACK array ']'
{
if ($2 == 0)
$$ = NEW_ZARRAY(); /* zero length array*/
@@ -831,7 +956,7 @@ primary : literal
$$ = $2;
}
}
- | LBRACE assoc_list '}'
+ | tLBRACE assoc_list '}'
{
$$ = NEW_HASH($2);
}
@@ -840,19 +965,19 @@ primary : literal
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
value_expr($3);
- $$ = NEW_RET($3);
+ $$ = NEW_RETURN($3);
}
| kRETURN '(' ')'
{
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
- $$ = NEW_RET(0);
+ $$ = NEW_RETURN(0);
}
| kRETURN
{
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
- $$ = NEW_RET(0);
+ $$ = NEW_RETURN(0);
}
| kYIELD '(' ret_args ')'
{
@@ -872,9 +997,9 @@ primary : literal
in_defined = 0;
$$ = NEW_DEFINED($5);
}
- | FID
+ | tFID
{
- $$ = NEW_FCALL($1, 0);
+ $$ = NEW_VCALL($1);
}
| operation iter_block
{
@@ -884,6 +1009,9 @@ primary : literal
| method_call
| method_call iter_block
{
+ if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
+ rb_compile_error("both block arg and actual block given");
+ }
$2->nd_iter = $1;
$$ = $2;
fixpos($$, $1);
@@ -941,19 +1069,24 @@ primary : literal
| kBEGIN
compstmt
rescue
+ opt_else
ensure
kEND
{
- if (!$3 && !$4)
+ if (!$3 && !$4 && !$5)
$$ = NEW_BEGIN($2);
else {
- if ($3) $2 = NEW_RESCUE($2, $3);
- if ($4) $2 = NEW_ENSURE($2, $4);
+ if ($3) $2 = NEW_RESCUE($2, $3, $4);
+ else if ($4) {
+ rb_warn("else without rescue is useless");
+ $2 = block_append($2, $4);
+ }
+ if ($5) $2 = NEW_ENSURE($2, $5);
$$ = $2;
}
fixpos($$, $2);
}
- | LPAREN compstmt ')'
+ | tLPAREN compstmt ')'
{
$$ = $2;
}
@@ -975,11 +1108,8 @@ primary : literal
cref_pop();
class_nest--;
}
- | kCLASS LSHFT expr term
+ | kCLASS tLSHFT expr term
{
- if (cur_mid || in_single)
- yyerror("class definition in method body");
-
class_nest++;
cref_push();
local_push();
@@ -1027,7 +1157,7 @@ primary : literal
local_pop();
cur_mid = 0;
}
- | kDEF singleton '.' {lex_state = EXPR_FNAME;} fname
+ | kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
{
value_expr($2);
in_single++;
@@ -1066,7 +1196,6 @@ then : term
do : term
| kDO
- | term kDO
if_tail : opt_else
| kELSIF expr then
@@ -1094,11 +1223,11 @@ opt_iter_var : /* node */
{
$$ = 0;
}
- | '|' /* none */ '|'
+ | '|' /* none */ '|'
{
$$ = 0;
}
- | OROP
+ | tOROP
{
$$ = 0;
}
@@ -1120,7 +1249,7 @@ iter_do_block : kDO
dyna_pop($<vars>2);
}
-iter_block : '{'
+iter_block : '{'
{
$<vars>$ = dyna_push();
}
@@ -1132,44 +1261,45 @@ iter_block : '{'
dyna_pop($<vars>2);
}
-iterator : IDENTIFIER
+iterator : tIDENTIFIER
{
- $$ = NEW_FCALL($1, 0);
+ $$ = NEW_VCALL($1);
}
- | CONSTANT
+ | tCONSTANT
{
- $$ = NEW_FCALL($1, 0);
+ $$ = NEW_VCALL($1);
}
- | FID
+ | tFID
{
- $$ = NEW_FCALL($1, 0);
+ $$ = NEW_VCALL($1);
}
| method_call
| command_call
-method_call : operation '(' call_args ')'
+method_call : operation '(' opt_call_args ')'
{
- $$ = NEW_FCALL($1, $3);
+ $$ = new_fcall($1, $3);
fixpos($$, $3);
}
- | primary '.' operation '(' call_args ')'
+ | primary '.' operation '(' opt_call_args ')'
{
value_expr($1);
- $$ = NEW_CALL($1, $3, $5);
+ $$ = new_call($1, $3, $5);
fixpos($$, $1);
}
| primary '.' operation
{
value_expr($1);
- $$ = NEW_CALL($1, $3, 0);
+ $$ = new_call($1, $3, 0);
+ fixpos($$, $1);
}
- | primary COLON2 operation '(' call_args ')'
+ | primary tCOLON2 operation '(' opt_call_args ')'
{
value_expr($1);
- $$ = NEW_CALL($1, $3, $5);
+ $$ = new_call($1, $3, $5);
fixpos($$, $1);
}
- | kSUPER '(' call_args ')'
+ | kSUPER '(' opt_call_args ')'
{
if (!cur_mid && !in_single && !in_defined)
yyerror("super called outside of method");
@@ -1183,19 +1313,31 @@ method_call : operation '(' call_args ')'
}
-case_body : kWHEN args then
+case_body : kWHEN when_args then
compstmt
cases
{
$$ = NEW_WHEN($2, $4, $5);
}
+when_args : args
+ | args ',' tSTAR arg
+ {
+ value_expr($4);
+ $$ = list_append($1, NEW_WHEN($4, 0, 0));
+ }
+ | tSTAR arg
+ {
+ value_expr($2);
+ $$ = NEW_LIST(NEW_WHEN($2, 0, 0));
+ }
+
cases : opt_else
| case_body
rescue : kRESCUE opt_list do
compstmt
- rescue
+ rescue
{
$$ = NEW_RESBODY($2, $4, $5);
fixpos($$, $2?$2:$4);
@@ -1215,35 +1357,37 @@ ensure : /* none */
}
literal : numeric
- | SYMBEG symbol
+ | tSYMBEG symbol
{
$$ = INT2FIX($2);
}
- | REGEXP
+ | tREGEXP
symbol : fname
- | IVAR
- | GVAR
+ | tIVAR
+ | tGVAR
-numeric : INTEGER
- | FLOAT
+numeric : tINTEGER
+ | tFLOAT
-variable : IDENTIFIER
- | IVAR
- | GVAR
- | CONSTANT
+variable : tIDENTIFIER
+ | tIVAR
+ | tGVAR
+ | tCONSTANT
| kNIL {$$ = kNIL;}
| kSELF {$$ = kSELF;}
- | kTRUE {$$ = kTRUE;}
+ | kTRUE {$$ = kTRUE;}
| kFALSE {$$ = kFALSE;}
+ | k__FILE__ {$$ = k__FILE__;}
+ | k__LINE__ {$$ = k__LINE__;}
var_ref : variable
{
$$ = gettable($1);
}
-backref : NTH_REF
- | BACK_REF
+backref : tNTH_REF
+ | tBACK_REF
superclass : term
{
@@ -1257,9 +1401,9 @@ superclass : term
{
$$ = $3;
}
- | error term {yyerrok;}
+ | error term {yyerrok; $$ = 0;}
-f_arglist : '(' f_args ')'
+f_arglist : '(' f_args opt_nl ')'
{
$$ = $2;
lex_state = EXPR_BEG;
@@ -1269,47 +1413,51 @@ f_arglist : '(' f_args ')'
$$ = $1;
}
-f_args : /* no arg */
+f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
{
- $$ = NEW_ARGS(0, 0, -1);
+ $$ = block_append(NEW_ARGS($1, $3, $5), $6);
}
- | f_arg
+ | f_arg ',' f_optarg opt_f_block_arg
{
- $$ = NEW_ARGS($1, 0, -1);
+ $$ = block_append(NEW_ARGS($1, $3, -1), $4);
}
- | f_arg ',' rest_arg
+ | f_arg ',' f_rest_arg opt_f_block_arg
{
- $$ = NEW_ARGS($1, 0, $3);
+ $$ = block_append(NEW_ARGS($1, 0, $3), $4);
}
- | f_arg ',' f_optarg
+ | f_arg opt_f_block_arg
{
- $$ = NEW_ARGS($1, $3, -1);
+ $$ = block_append(NEW_ARGS($1, 0, -1), $2);
}
- | f_arg ',' f_optarg ',' rest_arg
+ | f_optarg ',' f_rest_arg opt_f_block_arg
{
- $$ = NEW_ARGS($1, $3, $5);
+ $$ = block_append(NEW_ARGS(0, $1, $3), $4);
}
- | f_optarg
+ | f_optarg opt_f_block_arg
{
- $$ = NEW_ARGS(0, $1, -1);
+ $$ = block_append(NEW_ARGS(0, $1, -1), $2);
}
- | f_optarg ',' rest_arg
+ | f_rest_arg opt_f_block_arg
{
- $$ = NEW_ARGS(0, $1, $3);
+ $$ = block_append(NEW_ARGS(0, 0, $1), $2);
}
- | rest_arg
+ | f_block_arg
{
- $$ = NEW_ARGS(0, 0, $1);
+ $$ = block_append(NEW_ARGS(0, 0, -1), $1);
+ }
+ | /* none */
+ {
+ $$ = NEW_ARGS(0, 0, -1);
}
-f_arg : IDENTIFIER
+f_arg : tIDENTIFIER
{
if (!is_local_id($1))
yyerror("formal argument must be local variable");
local_cnt($1);
$$ = 1;
}
- | f_arg ',' IDENTIFIER
+ | f_arg ',' tIDENTIFIER
{
if (!is_local_id($3))
yyerror("formal argument must be local variable");
@@ -1317,7 +1465,7 @@ f_arg : IDENTIFIER
$$ += 1;
}
-f_opt : IDENTIFIER '=' arg
+f_opt : tIDENTIFIER '=' arg
{
if (!is_local_id($1))
yyerror("formal argument must be local variable");
@@ -1334,13 +1482,27 @@ f_optarg : f_opt
$$ = block_append($1, $3);
}
-rest_arg : STAR IDENTIFIER
+f_rest_arg : tSTAR tIDENTIFIER
{
if (!is_local_id($2))
yyerror("rest argument must be local variable");
$$ = local_cnt($2);
}
+f_block_arg : tAMPER tIDENTIFIER
+ {
+ $$ = NEW_BLOCK_ARG($2);
+ }
+
+opt_f_block_arg : ',' f_block_arg
+ {
+ $$ = $2;
+ }
+ | /* none */
+ {
+ $$ = 0;
+ }
+
singleton : var_ref
{
if (nd_type($1) == NODE_SELF) {
@@ -1354,7 +1516,7 @@ singleton : var_ref
$$ = $1;
}
}
- | LPAREN expr opt_nl ')'
+ | tLPAREN expr opt_nl ')'
{
switch (nd_type($2)) {
case NODE_STR:
@@ -1394,21 +1556,17 @@ assocs : assoc
$$ = list_concat($1, $3);
}
-assoc : arg ASSOC arg
+assoc : arg tASSOC arg
{
$$ = list_append(NEW_LIST($1), $3);
}
- | assoc_kw KW_ASSOC arg
- {
- $$ = list_append(NEW_LIST(NEW_STR(str_new2(rb_id2name($1)))), $3);
- }
-assoc_kw : IDENTIFIER
- | CONSTANT
+operation : tIDENTIFIER
+ | tCONSTANT
+ | tFID
-operation : IDENTIFIER
- | CONSTANT
- | FID
+dot_or_colon : '.'
+ | tCOLON2
opt_terms : /* none */
| terms
@@ -1431,21 +1589,18 @@ terms : term
#include "regex.h"
#include "util.h"
-#define is_identchar(c) ((c)!=-1&&(isalnum(c) || (c) == '_' || ismbchar(c)))
+#define is_identchar(c) ((c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
static char *tokenbuf = NULL;
static int tokidx, toksiz = 0;
-VALUE newregexp();
-VALUE newstring();
-VALUE newfloat();
-VALUE newinteger();
char *strdup();
-static NODE *str_extend();
+static NODE *rb_str_extend();
#define LEAVE_BS 1
+static VALUE (*lex_gets)(); /* gets function */
static VALUE lex_input; /* non-nil if File */
static VALUE lex_lastline; /* gc protect */
static char *lex_pbeg;
@@ -1459,7 +1614,7 @@ yyerror(msg)
char *p, *pe, *buf;
int len, i;
- Error("%s", msg);
+ rb_compile_error("%s", msg);
p = lex_p;
while (lex_pbeg <= p) {
if (*p == '\n') break;
@@ -1478,7 +1633,7 @@ yyerror(msg)
buf = ALLOCA_N(char, len+2);
MEMCPY(buf, p, char, len);
buf[len] = '\0';
- Error_Append("%s", buf);
+ rb_compile_error_append("%s", buf);
i = lex_p - p;
p = buf; pe = p + len;
@@ -1489,15 +1644,17 @@ yyerror(msg)
}
buf[i] = '^';
buf[i+1] = '\0';
- Error_Append("%s", buf);
+ rb_compile_error_append("%s", buf);
}
return 0;
}
static int newline_seen;
+static int heredoc_end;
-int rb_in_compile = 0;
+int ruby_in_compile = 0;
+int ruby__end__seen;
static NODE*
yycompile(f)
@@ -1505,41 +1662,89 @@ yycompile(f)
{
int n;
+ ruby__end__seen = 0;
+ ruby_eval_tree = 0;
newline_seen = 0;
- sourcefile = strdup(f);
- rb_in_compile = 1;
+ ruby_sourcefile = f;
+ ruby_in_compile = 1;
n = yyparse();
- rb_in_compile = 0;
- if (n == 0) return eval_tree;
+ ruby_in_compile = 0;
+ if (n == 0) return ruby_eval_tree;
return 0;
}
+static int lex_gets_ptr;
+
+static VALUE
+lex_get_str(s)
+ VALUE s;
+{
+ char *beg, *end, *pend;
+
+ beg = RSTRING(s)->ptr;
+ if (lex_gets_ptr) {
+ if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
+ beg += lex_gets_ptr;
+ }
+ pend = RSTRING(s)->ptr + RSTRING(s)->len;
+ end = beg;
+ while (end < pend) {
+ if (*end++ == '\n') break;
+ }
+ lex_gets_ptr = end - RSTRING(s)->ptr;
+ return rb_str_new(beg, end - beg);
+}
+
NODE*
-compile_string(f, s, len)
- char *f, *s;
- int len;
+rb_compile_string(f, s)
+ char *f;
+ VALUE s;
{
- lex_pbeg = lex_p = s;
- lex_pend = s + len;
- lex_input = 0;
- if (!sourcefile || strcmp(f, sourcefile)) /* not in eval() */
- sourceline = 1;
+ lex_gets = lex_get_str;
+ lex_gets_ptr = 0;
+ lex_input = s;
+ lex_pbeg = lex_p = lex_pend = 0;
+ if (!ruby_sourcefile || strcmp(f, ruby_sourcefile)) /* not in eval() */
+ ruby_sourceline = 1;
return yycompile(f);
}
NODE*
-compile_file(f, file, start)
+rb_compile_cstr(f, s, len)
+ char *f, *s;
+ int len;
+{
+ return rb_compile_string(f, rb_str_new(s, len));
+}
+
+NODE*
+rb_compile_file(f, file, start)
char *f;
VALUE file;
int start;
{
+ lex_gets = rb_io_gets;
lex_input = file;
lex_pbeg = lex_p = lex_pend = 0;
- sourceline = start;
+ ruby_sourceline = start;
- return yycompile(f);
+ return yycompile(strdup(f));
+}
+
+
+static void
+normalize_newline(line)
+ VALUE line;
+{
+ if (RSTRING(line)->len >= 2 &&
+ RSTRING(line)->ptr[RSTRING(line)->len-1] == '\n' &&
+ RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
+ {
+ RSTRING(line)->ptr[RSTRING(line)->len-2] = '\n';
+ RSTRING(line)->len--;
+ }
}
static int
@@ -1549,13 +1754,28 @@ nextc()
if (lex_p == lex_pend) {
if (lex_input) {
- VALUE v = io_gets(lex_input);
+ VALUE v = (*lex_gets)(lex_input);
if (NIL_P(v)) return -1;
+ if (heredoc_end > 0) {
+ ruby_sourceline = heredoc_end+1;
+ heredoc_end = 0;
+ }
+ normalize_newline(v);
+ while (RSTRING(v)->len >= 2 &&
+ RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' &&
+ RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') {
+ VALUE v2 = (*lex_gets)(lex_input);
+
+ if (!NIL_P(v2)) {
+ normalize_newline(v2);
+ rb_str_cat(v, RSTRING(v2)->ptr, RSTRING(v2)->len);
+ }
+ }
lex_pbeg = lex_p = RSTRING(v)->ptr;
lex_pend = lex_p + RSTRING(v)->len;
- if (RSTRING(v)->len == 8 &&
- strncmp(lex_pbeg, "__END__", 7) == 0) {
+ if (strncmp(lex_pbeg, "__END__", 7) == 0 && lex_pbeg[7] == '\n') {
+ ruby__end__seen = 1;
lex_lastline = 0;
return -1;
}
@@ -1571,7 +1791,7 @@ nextc()
return c;
}
-void
+static void
pushback(c)
int c;
{
@@ -1668,7 +1888,7 @@ read_escape()
for (i=0; i<2; i++) {
buf[i] = nextc();
if (buf[i] == -1) goto eof;
- if (!isxdigit(buf[i])) {
+ if (!ISXDIGIT(buf[i])) {
pushback(buf[i]);
break;
}
@@ -1680,6 +1900,9 @@ read_escape()
case 'b': /* backspace */
return '\b';
+ case 's': /* space */
+ return ' ';
+
case 'M':
if ((c = nextc()) != '-') {
yyerror("Invalid escape character syntax");
@@ -1701,7 +1924,6 @@ read_escape()
return '\0';
}
case 'c':
- case '^':
if ((c = nextc())== '\\') {
c = read_escape();
}
@@ -1721,24 +1943,28 @@ read_escape()
}
static int
-parse_regx(term)
+parse_regx(term, paren)
int term;
{
register int c;
char kcode = 0;
int once = 0;
- int casefold = 0;
+ int nest = 0;
+ int options = 0;
int in_brack = 0;
- int re_start = sourceline;
+ int re_start = ruby_sourceline;
NODE *list = 0;
newtok();
while ((c = nextc()) != -1) {
- if (!in_brack && c == term) {
+ if ((!in_brack && c == term) || nest > 0) {
goto regx_end;
}
switch (c) {
+ case '\n':
+ ruby_sourceline++;
+ break;
case '[':
in_brack = 1;
break;
@@ -1747,24 +1973,26 @@ parse_regx(term)
break;
case '#':
- list = str_extend(list, term);
+ list = rb_str_extend(list, term);
if (list == (NODE*)-1) return 0;
continue;
case '\\':
switch (c = nextc()) {
case -1:
- sourceline = re_start;
- Error("unterminated regexp meets end of file"); /* */
+ ruby_sourceline = re_start;
+ rb_compile_error("unterminated regexp meets end of file");
return 0;
case '\n':
- sourceline++;
+ ruby_sourceline++;
break;
case '\\':
+ case '^':
+ case 's':
tokadd('\\');
- tokadd('\\');
+ tokadd(c);
break;
case '1': case '2': case '3':
@@ -1775,11 +2003,6 @@ parse_regx(term)
tokadd(c);
break;
- case '^': /* no \^ escape in regexp */
- tokadd('\\');
- tokadd('^');
- break;
-
case 'b':
if (!in_brack) {
tokadd('\\');
@@ -1788,8 +2011,10 @@ parse_regx(term)
}
/* fall through */
default:
+ if (c == paren) nest++;
+ if (c == term) nest--;
if (c == '\n') {
- sourceline++;
+ ruby_sourceline++;
}
else if (c == term) {
tokadd(c);
@@ -1803,13 +2028,17 @@ parse_regx(term)
continue;
case -1:
- Error("unterminated regexp");
+ rb_compile_error("unterminated regexp");
return 0;
default:
if (ismbchar(c)) {
- tokadd(c);
- c = nextc();
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ tokadd(c);
+ c = nextc();
+ }
}
break;
@@ -1817,19 +2046,25 @@ parse_regx(term)
for (;;) {
switch (c = nextc()) {
case 'i':
- casefold = 1;
+ options |= RE_OPTION_IGNORECASE;
+ break;
+ case 'x':
+ options |= RE_OPTION_EXTENDED;
break;
case 'o':
once = 1;
break;
case 'n':
- kcode = 2;
+ kcode = 4;
break;
case 'e':
- kcode = 4;
+ kcode = 8;
break;
case 's':
- kcode = 6;
+ kcode = 12;
+ break;
+ case 'u':
+ kcode = 16;
break;
default:
pushback(c);
@@ -1842,64 +2077,74 @@ parse_regx(term)
lex_state = EXPR_END;
if (list) {
if (toklen() > 0) {
- VALUE ss = str_new(tok(), toklen());
+ VALUE ss = rb_str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
}
nd_set_type(list, once?NODE_DREGX_ONCE:NODE_DREGX);
- list->nd_cflag = kcode | casefold;
+ list->nd_cflag = options | kcode;
yylval.node = list;
- return DREGEXP;
+ return tDREGEXP;
}
else {
- yylval.val = reg_new(tok(), toklen(), kcode | casefold);
- return REGEXP;
+ yylval.val = rb_reg_new(tok(), toklen(), options | kcode);
+ return tREGEXP;
}
}
tokadd(c);
}
- Error("unterminated regexp");
+ rb_compile_error("unterminated regexp");
return 0;
}
-static int parse_qstring();
+static int parse_qstring _((int,int));
static int
-parse_string(func,term)
- int func, term;
+parse_string(func, term, paren)
+ int func, term, paren;
{
int c;
NODE *list = 0;
int strstart;
+ int nest = 0;
if (func == '\'') {
- return parse_qstring(term);
+ return parse_qstring(term, paren);
+ }
+ if (func == 0) { /* read 1 line for heredoc */
+ ruby_sourceline++;
+ /* -1 for chomp */
+ yylval.val = rb_str_new(lex_pbeg, lex_pend - lex_pbeg - 1);
+ return tSTRING;
}
- strstart = sourceline;
+ strstart = ruby_sourceline;
newtok();
-
- while ((c = nextc()) != term) {
- if (c == -1) {
+ while ((c = nextc()) != term || nest > 0) {
+ if (c == -1) {
unterm_str:
- sourceline = strstart;
- Error("unterminated string meets end of file");
+ ruby_sourceline = strstart;
+ rb_compile_error("unterminated string meets end of file");
return 0;
}
if (ismbchar(c)) {
- tokadd(c);
- c = nextc();
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ tokadd(c);
+ c = nextc();
+ }
}
else if (c == '\n') {
- sourceline++;
+ ruby_sourceline++;
}
else if (c == '#') {
- list = str_extend(list, term);
+ list = rb_str_extend(list, term);
if (list == (NODE*)-1) goto unterm_str;
continue;
}
else if (c == '\\') {
c = nextc();
if (c == '\n') {
- sourceline++;
+ ruby_sourceline++;
}
else if (c == term) {
tokadd(c);
@@ -1911,6 +2156,11 @@ parse_string(func,term)
}
continue;
}
+ if (c == paren) nest++;
+ if (c == term) {
+ nest--;
+ if (nest == 0) break;
+ }
tokadd(c);
}
@@ -1918,51 +2168,56 @@ parse_string(func,term)
lex_state = EXPR_END;
if (list) {
if (toklen() > 0) {
- VALUE ss = str_new(tok(), toklen());
+ VALUE ss = rb_str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
}
yylval.node = list;
if (func == '`') {
nd_set_type(list, NODE_DXSTR);
- return DXSTRING;
+ return tDXSTRING;
}
else {
- return DSTRING;
+ return tDSTRING;
}
}
else {
- yylval.val = str_new(tok(), toklen());
- return (func == '`') ? XSTRING : STRING;
+ yylval.val = rb_str_new(tok(), toklen());
+ return (func == '`') ? tXSTRING : tSTRING;
}
}
static int
-parse_qstring(term)
- int term;
+parse_qstring(term, paren)
+ int term, paren;
{
int strstart;
int c;
+ int nest = 0;
- strstart = sourceline;
+ strstart = ruby_sourceline;
newtok();
- while ((c = nextc()) != term) {
- if (c == -1) {
- sourceline = strstart;
- Error("unterminated string meets end of file");
+ while ((c = nextc()) != term || nest > 0) {
+ if (c == -1) {
+ ruby_sourceline = strstart;
+ rb_compile_error("unterminated string meets end of file");
return 0;
}
if (ismbchar(c)) {
- tokadd(c);
- c = nextc();
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ tokadd(c);
+ c = nextc();
+ }
}
else if (c == '\n') {
- sourceline++;
+ ruby_sourceline++;
}
else if (c == '\\') {
c = nextc();
switch (c) {
case '\n':
- sourceline++;
+ ruby_sourceline++;
continue;
case '\\':
@@ -1979,27 +2234,45 @@ parse_qstring(term)
tokadd('\\');
}
}
+ if (c == paren) nest++;
+ if (c == term) {
+ nest--;
+ if (nest == 0) break;
+ }
tokadd(c);
}
tokfix();
- yylval.val = str_new(tok(), toklen());
+ yylval.val = rb_str_new(tok(), toklen());
lex_state = EXPR_END;
- return STRING;
+ return tSTRING;
+}
+
+static int
+parse_quotedword(term, paren)
+ int term, paren;
+{
+ if (parse_qstring(term, paren) == 0) return 0;
+ yylval.node = NEW_CALL(NEW_STR(yylval.val), rb_intern("split"), 0);
+ return tDSTRING;
}
char *strdup();
static int
-here_document(term)
+here_document(term, indent)
char term;
+ int indent;
{
int c;
- char *eos;
+ char *eos, *p;
int len;
- VALUE str, line;
- char *save_beg, *save_end, *save_lexp;
+ VALUE str;
+ volatile VALUE line;
+ VALUE lastline_save;
+ int offset_save;
NODE *list = 0;
+ int linesave = ruby_sourceline;
newtok();
switch (term) {
@@ -2009,14 +2282,15 @@ here_document(term)
while ((c = nextc()) != term) {
tokadd(c);
}
+ if (term == '\'') term = 0;
break;
default:
- c = term;
+ c = term;
term = '"';
if (!is_identchar(c)) {
- yyerror("illegal here document");
- return 0;
+ rb_warn("Use of bare << to mean <<\"\" is deprecated");
+ break;
}
while (is_identchar(c)) {
tokadd(c);
@@ -2026,44 +2300,56 @@ here_document(term)
break;
}
tokfix();
- save_lexp = lex_p;
- save_beg = lex_pbeg;
- save_end = lex_pend;
+ lastline_save = lex_lastline;
+ offset_save = lex_p - lex_pbeg;
eos = strdup(tok());
len = strlen(eos);
- str = str_new(0,0);
+ str = rb_str_new(0,0);
for (;;) {
- line = io_gets(lex_input);
+ line = (*lex_gets)(lex_input);
if (NIL_P(line)) {
error:
- Error("unterminated string meets end of file");
+ ruby_sourceline = linesave;
+ rb_compile_error("can't find string \"%s\" anywhere before EOF", eos);
free(eos);
return 0;
}
- if (strncmp(eos, RSTRING(line)->ptr, len) == 0 &&
- (RSTRING(line)->ptr[len] == '\n' ||
- RSTRING(line)->ptr[len] == '\r')) {
+ normalize_newline(line);
+ ruby_sourceline++;
+ p = RSTRING(line)->ptr;
+ if (indent) {
+ while (*p && (*p == ' ' || *p == '\t')) {
+ p++;
+ }
+ }
+ if (strncmp(eos, p, len) == 0 && p[len] == '\n') {
break;
}
lex_pbeg = lex_p = RSTRING(line)->ptr;
lex_pend = lex_p + RSTRING(line)->len;
- sourceline++;
- switch (parse_string(term, '\n')) {
- case STRING:
- case XSTRING:
- str_cat(yylval.val, "\n", 1);
+#if 0
+ if (indent) {
+ while (*lex_p && *lex_p == '\t') {
+ lex_p++;
+ }
+ }
+#endif
+ switch (parse_string(term, '\n', '\n')) {
+ case tSTRING:
+ case tXSTRING:
+ rb_str_cat(yylval.val, "\n", 1);
if (!list) {
- str_cat(str, RSTRING(yylval.val)->ptr, RSTRING(yylval.val)->len);
+ rb_str_cat(str, RSTRING(yylval.val)->ptr, RSTRING(yylval.val)->len);
}
else {
list_append(list, NEW_STR(yylval.val));
}
break;
- case DSTRING:
- case DXSTRING:
- list_append(yylval.node, NEW_STR(str_new2("\n")));
+ case tDSTRING:
+ case tDXSTRING:
+ list_append(yylval.node, NEW_STR(rb_str_new2("\n")));
nd_set_type(yylval.node, NODE_STR);
if (!list) list = NEW_DSTR(str);
yylval.node = NEW_LIST(yylval.node);
@@ -2076,22 +2362,28 @@ here_document(term)
}
}
free(eos);
- lex_p = save_lexp;
- lex_pbeg = save_beg;
- lex_pend = save_end;
+ lex_lastline = lastline_save;
+ lex_pbeg = RSTRING(lex_lastline)->ptr;
+ lex_pend = lex_pbeg + RSTRING(lex_lastline)->len;
+ lex_p = lex_pbeg + offset_save;
+
+ lex_state = EXPR_END;
+ heredoc_end = ruby_sourceline;
+ ruby_sourceline = linesave;
if (list) {
yylval.node = list;
}
switch (term) {
+ case '\0':
case '\'':
case '"':
- if (list) return DSTRING;
- yylval.val = str;
- return STRING;
+ if (list) return tDSTRING;
+ yylval.val = str;
+ return tSTRING;
case '`':
- if (list) return DXSTRING;
- return XSTRING;
+ if (list) return tDXSTRING;
+ return tXSTRING;
}
return 0;
}
@@ -2101,7 +2393,7 @@ here_document(term)
static void
arg_ambiguous()
{
- Warning("ambiguous first argument; make sure");
+ rb_warning("ambiguous first argument; make sure");
}
#ifndef atof
@@ -2116,7 +2408,7 @@ yylex()
struct kwtable *kw;
if (newline_seen) {
- sourceline+=newline_seen;
+ ruby_sourceline += newline_seen;
newline_seen = 0;
}
@@ -2140,21 +2432,30 @@ retry:
return 0;
if (c == '\\') { /* skip a char */
c = nextc();
- if (c == '\n') sourceline++;
+ if (c == '\n') ruby_sourceline++;
}
if (ismbchar(c)) {
- c = nextc();
- if (c == '\n') {
- sourceline++;
- break;
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ c = nextc();
+ if (c == '\n') {
+ ruby_sourceline++;
+ break;
+ }
}
}
}
/* fall through */
case '\n':
- if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME) {
- sourceline++;
+ switch (lex_state) {
+ case EXPR_BEG:
+ case EXPR_FNAME:
+ case EXPR_DOT:
+ ruby_sourceline++;
goto retry;
+ default:
+ break;
}
newline_seen++;
lex_state = EXPR_BEG;
@@ -2164,25 +2465,26 @@ retry:
if ((c = nextc()) == '*') {
lex_state = EXPR_BEG;
if (nextc() == '=') {
- yylval.id = POW;
- return OP_ASGN;
+ yylval.id = tPOW;
+ return tOP_ASGN;
}
pushback(c);
- return POW;
+ return tPOW;
}
if (c == '=') {
yylval.id = '*';
lex_state = EXPR_BEG;
- return OP_ASGN;
+ return tOP_ASGN;
}
pushback(c);
- if (lex_state == EXPR_ARG && space_seen && !isspace(c)){
+ if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
arg_ambiguous();
lex_state = EXPR_BEG;
- return STAR;
+ return tSTAR;
}
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- return STAR;
+ lex_state = EXPR_BEG;
+ return tSTAR;
}
lex_state = EXPR_BEG;
return '*';
@@ -2190,10 +2492,10 @@ retry:
case '!':
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
- return NEQ;
+ return tNEQ;
}
if (c == '~') {
- return NMATCH;
+ return tNMATCH;
}
pushback(c);
return '!';
@@ -2201,21 +2503,21 @@ retry:
case '=':
if (lex_p == lex_pbeg + 1) {
/* skip embedded rd document */
- if (strncmp(lex_p, "begin", 5) == 0 && isspace(lex_p[5])) {
+ if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
for (;;) {
- sourceline++;
+ ruby_sourceline++;
lex_p = lex_pend;
c = nextc();
if (c == -1) {
- Error("embedded document meets end of file");
+ rb_compile_error("embedded document meets end of file");
return 0;
}
if (c != '=') continue;
- if (strncmp(lex_p, "end", 3) == 0 && isspace(lex_p[3])) {
+ if (strncmp(lex_p, "end", 3) == 0 && ISSPACE(lex_p[3])) {
break;
}
}
- sourceline++;
+ ruby_sourceline++;
lex_p = lex_pend;
goto retry;
}
@@ -2224,16 +2526,16 @@ retry:
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
if ((c = nextc()) == '=') {
- return EQQ;
+ return tEQQ;
}
pushback(c);
- return EQ;
+ return tEQ;
}
if (c == '~') {
- return MATCH;
+ return tMATCH;
}
else if (c == '>') {
- return ASSOC;
+ return tASSOC;
}
pushback(c);
return '=';
@@ -2241,33 +2543,34 @@ retry:
case '<':
c = nextc();
if (c == '<' &&
- lex_state != EXPR_END
- && lex_state != EXPR_CLASS &&
+ lex_state != EXPR_END && lex_state != EXPR_CLASS &&
(lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc();
- if (!isspace(c2) && (strchr("\"'`", c2) || is_identchar(c2))) {
- if (!lex_input) {
- ArgError("here document not available");
- }
- return here_document(c2);
+ int indent = 0;
+ if (c2 == '-') {
+ indent = 1;
+ c2 = nextc();
+ }
+ if (!ISSPACE(c2) && (strchr("\"'`", c2) || is_identchar(c2))) {
+ return here_document(c2, indent);
}
pushback(c2);
}
lex_state = EXPR_BEG;
if (c == '=') {
if ((c = nextc()) == '>') {
- return CMP;
+ return tCMP;
}
pushback(c);
- return LEQ;
+ return tLEQ;
}
if (c == '<') {
if (nextc() == '=') {
- yylval.id = LSHFT;
- return OP_ASGN;
+ yylval.id = tLSHFT;
+ return tOP_ASGN;
}
pushback(c);
- return LSHFT;
+ return tLSHFT;
}
pushback(c);
return '<';
@@ -2275,57 +2578,89 @@ retry:
case '>':
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
- return GEQ;
+ return tGEQ;
}
if (c == '>') {
if ((c = nextc()) == '=') {
- yylval.id = RSHFT;
- return OP_ASGN;
+ yylval.id = tRSHFT;
+ return tOP_ASGN;
}
pushback(c);
- return RSHFT;
+ return tRSHFT;
}
pushback(c);
return '>';
case '"':
- return parse_string(c,c);
+ return parse_string(c,c,c);
case '`':
if (lex_state == EXPR_FNAME) return c;
- return parse_string(c,c);
+ return parse_string(c,c,c);
case '\'':
- return parse_qstring(c);
+ return parse_qstring(c,c);
case '?':
- if ((c = nextc()) == '\\') {
+ if (lex_state == EXPR_END) {
+ lex_state = EXPR_BEG;
+ return '?';
+ }
+ c = nextc();
+ if (lex_state == EXPR_ARG && ISSPACE(c)){
+ pushback(c);
+ arg_ambiguous();
+ lex_state = EXPR_BEG;
+ return '?';
+ }
+ if (c == '\\') {
c = read_escape();
}
c &= 0xff;
yylval.val = INT2FIX(c);
lex_state = EXPR_END;
- return INTEGER;
+ return tINTEGER;
case '&':
- lex_state = EXPR_BEG;
if ((c = nextc()) == '&') {
- return ANDOP;
+ lex_state = EXPR_BEG;
+ if ((c = nextc()) == '=') {
+ yylval.id = tANDOP;
+ return tOP_ASGN;
+ }
+ pushback(c);
+ return tANDOP;
}
else if (c == '=') {
yylval.id = '&';
- return OP_ASGN;
+ lex_state = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(c);
+ if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
+ arg_ambiguous();
+ lex_state = EXPR_BEG;
+ return tAMPER;
+ }
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ lex_state = EXPR_BEG;
+ return tAMPER;
+ }
+ lex_state = EXPR_BEG;
return '&';
case '|':
lex_state = EXPR_BEG;
if ((c = nextc()) == '|') {
- return OROP;
+ if ((c = nextc()) == '=') {
+ yylval.id = tOROP;
+ return tOP_ASGN;
+ }
+ pushback(c);
+ return tOROP;
}
else if (c == '=') {
yylval.id = '|';
- return OP_ASGN;
+ return tOP_ASGN;
}
pushback(c);
return '|';
@@ -2334,7 +2669,7 @@ retry:
c = nextc();
if (lex_state == EXPR_FNAME) {
if (c == '@') {
- return UPLUS;
+ return tUPLUS;
}
pushback(c);
return '+';
@@ -2342,23 +2677,15 @@ retry:
if (c == '=') {
lex_state = EXPR_BEG;
yylval.id = '+';
- return OP_ASGN;
- }
- if (lex_state == EXPR_ARG) {
- if (space_seen && !isspace(c)) {
- arg_ambiguous();
- }
- else {
- lex_state = EXPR_END;
- }
+ return tOP_ASGN;
}
- if (lex_state != EXPR_END) {
- if (isdigit(c)) {
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ if (ISDIGIT(c)) {
goto start_num;
}
pushback(c);
lex_state = EXPR_BEG;
- return UPLUS;
+ return tUPLUS;
}
lex_state = EXPR_BEG;
pushback(c);
@@ -2368,7 +2695,7 @@ retry:
c = nextc();
if (lex_state == EXPR_FNAME) {
if (c == '@') {
- return UMINUS;
+ return tUMINUS;
}
pushback(c);
return '-';
@@ -2376,29 +2703,17 @@ retry:
if (c == '=') {
lex_state = EXPR_BEG;
yylval.id = '-';
- return OP_ASGN;
- }
- if (c == '>') {
- lex_state = EXPR_BEG;
- return KW_ASSOC;
- }
- if (lex_state == EXPR_ARG) {
- if (space_seen && !isspace(c)) {
- arg_ambiguous();
- }
- else {
- lex_state = EXPR_END;
- }
+ return tOP_ASGN;
}
- if (lex_state != EXPR_END) {
- if (isdigit(c)) {
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ if (ISDIGIT(c)) {
pushback(c);
c = '-';
goto start_num;
}
lex_state = EXPR_BEG;
pushback(c);
- return UMINUS;
+ return tUMINUS;
}
lex_state = EXPR_BEG;
pushback(c);
@@ -2408,13 +2723,14 @@ retry:
lex_state = EXPR_BEG;
if ((c = nextc()) == '.') {
if ((c = nextc()) == '.') {
- return DOT3;
+ return tDOT3;
}
pushback(c);
- return DOT2;
+ return tDOT2;
}
pushback(c);
- if (!isdigit(c)) {
+ if (!ISDIGIT(c)) {
+ lex_state = EXPR_DOT;
return '.';
}
c = '.';
@@ -2439,13 +2755,13 @@ retry:
/* hexadecimal */
while (c = nextc()) {
if (c == '_') continue;
- if (!isxdigit(c)) break;
+ if (!ISXDIGIT(c)) break;
tokadd(c);
}
pushback(c);
tokfix();
- yylval.val = str2inum(tok(), 16);
- return INTEGER;
+ yylval.val = rb_str2inum(tok(), 16);
+ return tINTEGER;
}
else if (c >= '0' && c <= '7') {
/* octal */
@@ -2456,8 +2772,8 @@ retry:
} while (c >= '0' && c <= '9');
pushback(c);
tokfix();
- yylval.val = str2inum(tok(), 8);
- return INTEGER;
+ yylval.val = rb_str2inum(tok(), 8);
+ return tINTEGER;
}
else if (c > '7' && c <= '9') {
yyerror("Illegal octal digit");
@@ -2468,7 +2784,7 @@ retry:
else {
pushback(c);
yylval.val = INT2FIX(0);
- return INTEGER;
+ return tINTEGER;
}
}
@@ -2480,12 +2796,12 @@ retry:
break;
case '.':
- if (seen_point) {
+ if (seen_point || seen_e) {
goto decode_num;
}
else {
int c0 = nextc();
- if (!isdigit(c0)) {
+ if (!ISDIGIT(c0)) {
pushback(c0);
goto decode_num;
}
@@ -2524,11 +2840,11 @@ retry:
pushback(c);
tokfix();
if (is_float) {
- yylval.val = float_new(atof(tok()));
- return FLOAT;
+ yylval.val = rb_float_new(atof(tok()));
+ return tFLOAT;
}
- yylval.val = str2inum(tok(), 10);
- return INTEGER;
+ yylval.val = rb_str2inum(tok(), 10);
+ return tINTEGER;
}
case ']':
@@ -2540,29 +2856,40 @@ retry:
case ':':
c = nextc();
if (c == ':') {
- lex_state = EXPR_BEG;
- return COLON2;
+ if (lex_state == EXPR_BEG) {
+ lex_state = EXPR_BEG;
+ return tCOLON3;
+ }
+ if (lex_state == EXPR_ARG && space_seen) {
+ arg_ambiguous();
+ lex_state = EXPR_BEG;
+ return tCOLON3;
+ }
+ lex_state = EXPR_DOT;
+ return tCOLON2;
}
pushback(c);
- if (isspace(c))
+ if (lex_state == EXPR_END || ISSPACE(c)) {
+ lex_state = EXPR_BEG;
return ':';
+ }
lex_state = EXPR_FNAME;
- return SYMBEG;
+ return tSYMBEG;
case '/':
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- return parse_regx('/');
+ return parse_regx('/', '/');
}
if ((c = nextc()) == '=') {
lex_state = EXPR_BEG;
yylval.id = '/';
- return OP_ASGN;
+ return tOP_ASGN;
}
if (lex_state == EXPR_ARG) {
- if (space_seen && !isspace(c)) {
+ if (space_seen && !ISSPACE(c)) {
pushback(c);
arg_ambiguous();
- return parse_regx('/');
+ return parse_regx('/', '/');
}
}
lex_state = EXPR_BEG;
@@ -2573,15 +2900,12 @@ retry:
lex_state = EXPR_BEG;
if (nextc() == '=') {
yylval.id = '^';
- return OP_ASGN;
+ return tOP_ASGN;
}
pushback(c);
return c;
case ',':
- lex_state = EXPR_BEG;
- return c;
-
case ';':
lex_state = EXPR_BEG;
return c;
@@ -2597,12 +2921,7 @@ retry:
case '(':
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- c = LPAREN;
- lex_state = EXPR_BEG;
- }
- else if (lex_state == EXPR_ARG && space_seen) {
- arg_ambiguous();
- c = LPAREN;
+ c = tLPAREN;
lex_state = EXPR_BEG;
}
else {
@@ -2614,34 +2933,34 @@ retry:
if (lex_state == EXPR_FNAME) {
if ((c = nextc()) == ']') {
if ((c = nextc()) == '=') {
- return ASET;
+ return tASET;
}
pushback(c);
- return AREF;
+ return tAREF;
}
pushback(c);
return '[';
}
else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- c = LBRACK;
+ c = tLBRACK;
}
else if (lex_state == EXPR_ARG && space_seen) {
arg_ambiguous();
- c = LBRACK;
+ c = tLBRACK;
}
lex_state = EXPR_BEG;
return c;
case '{':
if (lex_state != EXPR_END && lex_state != EXPR_ARG)
- c = LBRACE;
+ c = tLBRACE;
lex_state = EXPR_BEG;
return c;
case '\\':
c = nextc();
if (c == '\n') {
- sourceline++;
+ ruby_sourceline++;
space_seen = 1;
goto retry; /* skip \\n */
}
@@ -2651,29 +2970,22 @@ retry:
case '%':
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
int term;
+ int paren;
c = nextc();
quotation:
- if (!isalnum(c)) {
+ if (!ISALNUM(c)) {
term = c;
- switch (c) {
- case '\'':
- c = 'q'; break;
- case '/':
- c = 'r'; break;
- case '`':
- c = 'x'; break;
- default:
- c = 'Q';break;
- }
+ c = 'Q';
}
else {
term = nextc();
}
if (c == -1 || term == -1) {
- Error("unterminated quoted string meets end of file");
+ rb_compile_error("unterminated quoted string meets end of file");
return 0;
}
+ paren = term;
if (term == '(') term = ')';
else if (term == '[') term = ']';
else if (term == '{') term = '}';
@@ -2681,28 +2993,31 @@ retry:
switch (c) {
case 'Q':
- return parse_string('"', term);
+ return parse_string('"', term, paren);
case 'q':
- return parse_qstring(term);
+ return parse_qstring(term, paren);
+
+ case 'w':
+ return parse_quotedword(term, paren);
case 'x':
- return parse_string('`', term);
+ return parse_string('`', term, paren);
case 'r':
- return parse_regx(term);
+ return parse_regx(term, paren);
default:
- yyerror("unknown type of string `%c'", c);
+ yyerror("unknown type of %string");
return 0;
}
}
if ((c = nextc()) == '=') {
yylval.id = '%';
- return OP_ASGN;
+ return tOP_ASGN;
}
if (lex_state == EXPR_ARG) {
- if (space_seen && !isspace(c)) {
+ if (space_seen && !ISSPACE(c)) {
arg_ambiguous();
goto quotation;
}
@@ -2740,7 +3055,7 @@ retry:
tokadd(c);
tokfix();
yylval.id = rb_intern(tok());
- return GVAR;
+ return tGVAR;
case '-':
tokadd('$');
@@ -2749,26 +3064,26 @@ retry:
tokadd(c);
tokfix();
yylval.id = rb_intern(tok());
- return GVAR;
+ return tGVAR;
case '&': /* $&: last match */
case '`': /* $`: string before last match */
case '\'': /* $': string after last match */
case '+': /* $+: string matches last paren. */
yylval.node = NEW_BACK_REF(c);
- return BACK_REF;
+ return tBACK_REF;
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
- while (isdigit(c)) {
+ while (ISDIGIT(c)) {
tokadd(c);
c = nextc();
}
pushback(c);
tokfix();
yylval.node = NEW_NTH_REF(atoi(tok()));
- return NTH_REF;
+ return tNTH_REF;
default:
if (!is_identchar(c)) {
@@ -2791,8 +3106,8 @@ retry:
break;
default:
- if (c != '_' && !isalpha(c) && !ismbchar(c)) {
- Error("Invalid char '%c' in expression", c);
+ if (c != '_' && !ISALPHA(c) && !ismbchar(c)) {
+ rb_compile_error("Invalid char '%c' in expression", c);
goto retry;
}
@@ -2803,12 +3118,17 @@ retry:
while (is_identchar(c)) {
tokadd(c);
if (ismbchar(c)) {
- c = nextc();
+ int i, len = mbclen(c)-1;
+
tokadd(c);
+ for (i = 0; i < len; i++) {
+ c = nextc();
+ tokadd(c);
+ }
}
c = nextc();
}
- if (c == '!' || c == '?') {
+ if ((c == '!' || c == '?') && is_identchar(tok()[0])) {
tokadd(c);
}
else {
@@ -2822,44 +3142,51 @@ retry:
switch (tok()[0]) {
case '$':
lex_state = EXPR_END;
- result = GVAR;
+ result = tGVAR;
break;
case '@':
lex_state = EXPR_END;
- result = IVAR;
+ result = tIVAR;
break;
default:
- /* See if it is a reserved word. */
- kw = rb_reserved_word(tok(), toklen());
- if (kw) {
- enum lex_state state = lex_state;
- lex_state = kw->state;
- return kw->id[state != EXPR_BEG];
+ if (lex_state != EXPR_DOT) {
+ /* See if it is a reserved word. */
+ kw = rb_reserved_word(tok(), toklen());
+ if (kw) {
+ enum lex_state state = lex_state;
+ if (lex_state == EXPR_FNAME) {
+ yylval.id = rb_intern(kw->name);
+ }
+ lex_state = kw->state;
+ return kw->id[state != EXPR_BEG];
+ }
}
- if (lex_state == EXPR_FNAME) {
- lex_state = EXPR_END;
- if ((c = nextc()) == '=') {
- tokadd(c);
- }
- else {
- pushback(c);
+ if (ISUPPER(tok()[0])) {
+ result = tCONSTANT;
+ }
+ else if (toklast() == '!' || toklast() == '?') {
+ result = tFID;
+ } else {
+ result = tIDENTIFIER;
+ if (lex_state == EXPR_FNAME) {
+ lex_state = EXPR_END;
+ if ((c = nextc()) == '=') {
+ tokadd(c);
+ }
+ else {
+ pushback(c);
+ }
}
}
- else if (lex_state == EXPR_BEG){
+ if (lex_state == EXPR_BEG ||
+ lex_state == EXPR_DOT ||
+ lex_state == EXPR_ARG){
lex_state = EXPR_ARG;
}
else {
lex_state = EXPR_END;
}
- if (isupper(tok()[0])) {
- result = CONSTANT;
- }
- else if (toklast() == '!' || toklast() == '?') {
- result = FID;
- } else {
- result = IDENTIFIER;
- }
}
tokfix();
yylval.id = rb_intern(tok());
@@ -2868,11 +3195,12 @@ retry:
}
static NODE*
-str_extend(list, term)
+rb_str_extend(list, term)
NODE *list;
char term;
{
- int c, brace;
+ int c;
+ int brace = -1;
VALUE ss;
NODE *node;
int nest;
@@ -2889,7 +3217,7 @@ str_extend(list, term)
return list;
}
- ss = str_new(tok(), toklen());
+ ss = rb_str_new(tok(), toklen());
if (list == 0) {
list = NEW_DSTR(ss);
}
@@ -2907,7 +3235,7 @@ str_extend(list, term)
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
- while (isdigit(c)) {
+ while (ISDIGIT(c)) {
tokadd(c);
c = nextc();
}
@@ -2926,7 +3254,7 @@ str_extend(list, term)
default:
if (c == term) {
- list_append(list, NEW_STR(str_new2("#$")));
+ list_append(list, NEW_STR(rb_str_new2("#$")));
pushback(c);
newtok();
return list;
@@ -2946,14 +3274,19 @@ str_extend(list, term)
}
/* through */
- case '@':
+ case '@':
tokadd(c);
c = nextc();
while (is_identchar(c)) {
tokadd(c);
if (ismbchar(c)) {
- c = nextc();
+ int i, len = mbclen(c)-1;
+
tokadd(c);
+ for (i = 0; i < len; i++) {
+ c = nextc();
+ tokadd(c);
+ }
}
c = nextc();
}
@@ -2975,7 +3308,6 @@ str_extend(list, term)
}
return (NODE*)-1;
case '}':
- case ')':
if (c == brace) {
if (nest == 0) break;
nest--;
@@ -2987,16 +3319,16 @@ str_extend(list, term)
tokadd(c);
goto loop_again;
case '{':
- if (brace == c) nest++;
+ if (brace != -1) nest++;
case '\"':
case '/':
case '`':
if (c == term) {
pushback(c);
- list_append(list, NEW_STR(str_new2("#")));
- Warning("bad substitution in string");
+ list_append(list, NEW_STR(rb_str_new2("#")));
+ rb_warning("bad substitution in string");
tokfix();
- list_append(list, NEW_STR(str_new(tok(), toklen())));
+ list_append(list, NEW_STR(rb_str_new(tok(), toklen())));
newtok();
return list;
}
@@ -3017,7 +3349,7 @@ str_extend(list, term)
}
NODE*
-node_newnode(type, a0, a1, a2)
+rb_node_newnode(type, a0, a1, a2)
enum node_type type;
NODE *a0, *a1, *a2;
{
@@ -3025,8 +3357,8 @@ node_newnode(type, a0, a1, a2)
n->flags |= T_NODE;
nd_set_type(n, type);
- nd_set_line(n, sourceline);
- n->nd_file = sourcefile;
+ nd_set_line(n, ruby_sourceline);
+ n->nd_file = ruby_sourcefile;
n->u1.node = a0;
n->u2.node = a1;
@@ -3035,14 +3367,14 @@ node_newnode(type, a0, a1, a2)
return n;
}
-enum node_type
+static enum node_type
nodetype(node) /* for debug */
NODE *node;
{
return (enum node_type)nd_type(node);
}
-int
+static int
nodeline(node)
NODE *node;
{
@@ -3091,7 +3423,7 @@ block_append(head, tail)
end = head->nd_end;
}
- if (RTEST(verbose)) {
+ if (RTEST(rb_verbose)) {
NODE *nd = end->nd_head;
newline:
switch (nd_type(nd)) {
@@ -3100,7 +3432,7 @@ block_append(head, tail)
case NODE_NEXT:
case NODE_REDO:
case NODE_RETRY:
- Warning("statement not reached");
+ rb_warning("statement not reached");
break;
case NODE_NEWLINE:
@@ -3133,7 +3465,7 @@ list_append(head, tail)
while (last->nd_next) {
last = last->nd_next;
}
-
+
last->nd_next = NEW_LIST(tail);
head->nd_alen += 1;
return head;
@@ -3200,7 +3532,7 @@ match_gen(node1, node2)
}
}
- return NEW_CALL(node1, MATCH, NEW_LIST(node2));
+ return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
}
static NODE*
@@ -3219,9 +3551,15 @@ gettable(id)
else if (id == kFALSE) {
return NEW_FALSE();
}
+ else if (id == k__FILE__) {
+ return NEW_STR(rb_str_new2(ruby_sourcefile));
+ }
+ else if (id == k__LINE__) {
+ return NEW_LIT(INT2FIX(ruby_sourceline));
+ }
else if (is_local_id(id)) {
+ if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id);
if (local_id(id)) return NEW_LVAR(id);
- if (dyna_var_defined(id)) return NEW_DVAR(id);
/* method call without arguments */
return NEW_VCALL(id);
}
@@ -3234,7 +3572,7 @@ gettable(id)
else if (is_const_id(id)) {
return NEW_CVAR(id);
}
- Bug("invalid id for gettable");
+ rb_bug("invalid id for gettable");
return 0;
}
@@ -3245,6 +3583,7 @@ assignable(id, val)
{
NODE *lhs = 0;
+ value_expr(val);
if (id == kSELF) {
yyerror("Can't change the value of self");
}
@@ -3257,13 +3596,22 @@ assignable(id, val)
else if (id == kFALSE) {
yyerror("Can't assign to false");
}
+ else if (id == k__FILE__) {
+ yyerror("Can't assign to __FILE__");
+ }
+ else if (id == k__LINE__) {
+ yyerror("Can't assign to __LINE__");
+ }
else if (is_local_id(id)) {
- if (local_id(id) || !dyna_in_block()) {
+ if (rb_dvar_defined(id)) {
+ lhs = NEW_DASGN(id, val);
+ }
+ else if (local_id(id) || !dyna_in_block()) {
lhs = NEW_LASGN(id, val);
}
else{
- dyna_var_asgn(id, TRUE);
- lhs = NEW_DASGN(id, val);
+ rb_dvar_push(id, 0);
+ lhs = NEW_DASGN_PUSH(id, val);
}
}
else if (is_global_id(id)) {
@@ -3278,7 +3626,7 @@ assignable(id, val)
lhs = NEW_CASGN(id, val);
}
else {
- Bug("bad id for variable");
+ rb_bug("bad id for variable");
}
return lhs;
}
@@ -3288,7 +3636,7 @@ arg_add(node1, node2)
NODE *node1;
NODE *node2;
{
- return call_op(node1, rb_intern("concat"), 1, node2);
+ return NEW_ARGSCAT(node1, node2);
}
static NODE *
@@ -3305,11 +3653,11 @@ aryset(recv, idx, val)
idx = arg_add(idx, val);
}
}
- return NEW_CALL(recv, ASET, idx);
+ return NEW_CALL(recv, tASET, idx);
}
ID
-id_attrset(id)
+rb_id_attrset(id)
ID id;
{
id &= ~ID_SCOPE_MASK;
@@ -3324,23 +3672,20 @@ attrset(recv, id, val)
{
value_expr(recv);
value_expr(val);
-
- id &= ~ID_SCOPE_MASK;
- id |= ID_ATTRSET;
- return NEW_CALL(recv, id, NEW_LIST(val));
+ return NEW_CALL(recv, rb_id_attrset(id), NEW_LIST(val));
}
static void
-backref_error(node)
+rb_backref_error(node)
NODE *node;
{
switch (nd_type(node)) {
case NODE_NTH_REF:
- Error("Can't set variable $%d", node->nd_nth);
+ rb_compile_error("Can't set variable $%d", node->nd_nth);
break;
case NODE_BACK_REF:
- Error("Can't set variable $%c", node->nd_nth);
+ rb_compile_error("Can't set variable $%c", node->nd_nth);
break;
}
}
@@ -3349,7 +3694,7 @@ static int
value_expr(node)
NODE *node;
{
- if (node == 0) return TRUE;
+ if (node == 0) return Qtrue;
switch (nd_type(node)) {
case NODE_RETURN:
@@ -3364,7 +3709,7 @@ value_expr(node)
case NODE_DEFN:
case NODE_DEFS:
yyerror("void value expression");
- return FALSE;
+ return Qfalse;
break;
case NODE_BLOCK:
@@ -3380,18 +3725,64 @@ value_expr(node)
return value_expr(node->nd_next);
default:
- return TRUE;
+ return Qtrue;
}
}
static NODE *cond2();
+static int
+assign_in_cond(node)
+ 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:
+ case NODE_CASGN:
+ break;
+
+ case NODE_NEWLINE:
+ default:
+ return 0;
+ }
+
+ switch (nd_type(node->nd_value)) {
+ case NODE_LIT:
+ case NODE_STR:
+ case NODE_DSTR:
+ case NODE_XSTR:
+ case NODE_DXSTR:
+ case NODE_EVSTR:
+ case NODE_DREGX:
+ case NODE_NIL:
+ case NODE_TRUE:
+ case NODE_FALSE:
+ /* reports always */
+ rb_warn("found = in conditional, should be ==");
+ return 1;
+
+ default:
+ break;
+ }
+ if (assign_in_cond(node->nd_value) == 0) {
+ rb_warning("assignment in condition");
+ }
+ return 1;
+}
+
static NODE*
cond0(node)
NODE *node;
{
enum node_type type = nd_type(node);
+ assign_in_cond(node);
switch (type) {
case NODE_DREGX:
case NODE_DREGX_ONCE:
@@ -3405,6 +3796,7 @@ cond0(node)
node->nd_end = cond2(node->nd_end);
if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
+ node->nd_cnt = local_append(0);
return node;
case NODE_LIT:
@@ -3416,7 +3808,7 @@ cond0(node)
if (TYPE(node->nd_lit) == T_STRING) {
local_cnt('_');
local_cnt('~');
- return NEW_MATCH(reg_new(RSTRING(node)->ptr,RSTRING(node)->len,0));
+ return NEW_MATCH(rb_reg_new(RSTRING(node)->ptr,RSTRING(node)->len,0));
}
default:
return node;
@@ -3427,24 +3819,11 @@ static NODE*
cond(node)
NODE *node;
{
- enum node_type type = nd_type(node);
-
- switch (type) {
- case NODE_MASGN:
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_GASGN:
- case NODE_IASGN:
- case NODE_CASGN:
- Warning("assignment in condition");
- break;
- case NODE_NEWLINE:
+ if (node == 0) return 0;
+ if (nd_type(node) == NODE_NEWLINE){
node->nd_next = cond0(node->nd_next);
return node;
- default:
- break;
}
-
return cond0(node);
}
@@ -3458,7 +3837,7 @@ cond2(node)
type = nd_type(node);
if (type == NODE_NEWLINE) node = node->nd_next;
if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
- return call_op(node,EQ,1,NEW_GVAR(rb_intern("$.")));
+ return call_op(node,tEQ,1,NEW_GVAR(rb_intern("$.")));
}
return node;
}
@@ -3469,11 +3848,45 @@ logop(type, left, right)
NODE *left, *right;
{
value_expr(left);
+ return rb_node_newnode(type, cond(left), cond(right), 0);
+}
+
+static NODE *
+arg_blk_pass(node1, node2)
+ NODE *node1;
+ NODE *node2;
+{
+ if (node2) {
+ node2->nd_head = node1;
+ return node2;
+ }
+ return node1;
+}
- return node_newnode(type, cond(left), cond(right));
+static NODE*
+new_call(r,m,a)
+ NODE *r;
+ ID m;
+ NODE *a;
+{
+ if (a && nd_type(a) == NODE_BLOCK_PASS) {
+ a->nd_iter = NEW_CALL(r,m,a->nd_head);
+ return a;
+ }
+ return NEW_CALL(r,m,a);
}
-st_table *new_idhash();
+static NODE*
+new_fcall(m,a)
+ ID m;
+ NODE *a;
+{
+ if (a && nd_type(a) == NODE_BLOCK_PASS) {
+ a->nd_iter = NEW_FCALL(m,a->nd_head);
+ return a;
+ }
+ return NEW_FCALL(m,a);
+}
static struct local_vars {
ID *tbl;
@@ -3500,14 +3913,14 @@ local_push()
static void
local_pop()
{
- struct local_vars *local = lvtbl;
+ struct local_vars *local = lvtbl->prev;
- lvtbl = local->prev;
- if (local->tbl) {
- local->tbl[0] = local->cnt;
- if (!local->nofree) free(local->tbl);
+ if (lvtbl->tbl) {
+ if (!lvtbl->nofree) free(lvtbl->tbl);
+ else lvtbl->tbl[0] = lvtbl->cnt;
}
- free(local);
+ free(lvtbl);
+ lvtbl = local;
}
static ID*
@@ -3518,21 +3931,17 @@ local_tbl()
}
static int
-local_cnt(id)
+local_append(id)
ID id;
{
- int cnt, max;
-
- if (id == 0) return lvtbl->cnt;
-
- for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
- if (lvtbl->tbl[cnt] == id) return cnt-1;
- }
-
-
if (lvtbl->tbl == 0) {
- lvtbl->tbl = ALLOC_N(ID, 2);
+ lvtbl->tbl = ALLOC_N(ID, 4);
lvtbl->tbl[0] = 0;
+ lvtbl->tbl[1] = '_';
+ lvtbl->tbl[2] = '~';
+ lvtbl->cnt = 2;
+ if (id == '_') return 0;
+ if (id == '~') return 1;
}
else {
REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
@@ -3543,31 +3952,45 @@ local_cnt(id)
}
static int
+local_cnt(id)
+ ID id;
+{
+ int cnt, max;
+
+ if (id == 0) return lvtbl->cnt;
+
+ for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
+ if (lvtbl->tbl[cnt] == id) return cnt-1;
+ }
+ return local_append(id);
+}
+
+static int
local_id(id)
ID id;
{
int i, max;
- if (lvtbl == 0) return FALSE;
- for (i=1, max=lvtbl->cnt+1; i<max; i++) {
- if (lvtbl->tbl[i] == id) return TRUE;
+ if (lvtbl == 0) return Qfalse;
+ for (i=3, max=lvtbl->cnt+1; i<max; i++) {
+ if (lvtbl->tbl[i] == id) return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static void
top_local_init()
{
local_push();
- lvtbl->cnt = the_scope->local_tbl?the_scope->local_tbl[0]:0;
+ lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
if (lvtbl->cnt > 0) {
- lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1);
- MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt+1);
+ lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
+ MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
}
else {
lvtbl->tbl = 0;
}
- if (the_dyna_vars && the_dyna_vars->id)
+ if (ruby_dyna_vars)
lvtbl->dlev = 1;
else
lvtbl->dlev = 0;
@@ -3583,33 +4006,31 @@ top_local_setup()
i = lvtbl->tbl[0];
if (i < len) {
- if (i == 0 || the_scope->flag == SCOPE_ALLOCA) {
+ if (i == 0 || ruby_scope->flag == SCOPE_ALLOCA) {
VALUE *vars = ALLOC_N(VALUE, len+1);
- if (the_scope->local_vars) {
- *vars++ = the_scope->local_vars[-1];
- MEMCPY(vars, the_scope->local_vars, VALUE, i);
- memclear(vars+i, len-i);
+ if (ruby_scope->local_vars) {
+ *vars++ = ruby_scope->local_vars[-1];
+ MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
+ rb_mem_clear(vars+i, len-i);
}
else {
*vars++ = 0;
- memclear(vars, len);
+ rb_mem_clear(vars, len);
}
- the_scope->local_vars = vars;
- the_scope->flag |= SCOPE_MALLOC;
+ ruby_scope->local_vars = vars;
+ ruby_scope->flag |= SCOPE_MALLOC;
}
else {
- VALUE *vars = the_scope->local_vars-1;
+ VALUE *vars = ruby_scope->local_vars-1;
REALLOC_N(vars, VALUE, len+1);
- the_scope->local_vars = vars+1;
- memclear(the_scope->local_vars+i, len-i);
+ ruby_scope->local_vars = vars+1;
+ rb_mem_clear(ruby_scope->local_vars+i, len-i);
}
- lvtbl->tbl[0] = len;
- if (the_scope->local_tbl && the_scope->local_vars[-1] == 0) {
- free(the_scope->local_tbl);
+ if (ruby_scope->local_tbl && ruby_scope->local_vars[-1] == 0) {
+ free(ruby_scope->local_tbl);
}
- the_scope->local_vars[-1] = 0;
- the_scope->local_tbl = lvtbl->tbl;
- lvtbl->nofree = 1;
+ ruby_scope->local_vars[-1] = 0;
+ ruby_scope->local_tbl = local_tbl();
}
}
local_pop();
@@ -3619,7 +4040,7 @@ static struct RVarmap*
dyna_push()
{
lvtbl->dlev++;
- return the_dyna_vars;
+ return ruby_dyna_vars;
}
static void
@@ -3627,7 +4048,7 @@ dyna_pop(vars)
struct RVarmap* vars;
{
lvtbl->dlev--;
- the_dyna_vars = vars;
+ ruby_dyna_vars = vars;
}
static int
@@ -3643,35 +4064,38 @@ cref_pop()
}
void
-yyappend_print()
+rb_parser_append_print()
{
- eval_tree =
- block_append(eval_tree,
+ ruby_eval_tree =
+ block_append(ruby_eval_tree,
NEW_FCALL(rb_intern("print"),
NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
}
void
-yywhile_loop(chop, split)
+rb_parser_while_loop(chop, split)
int chop, split;
{
if (split) {
- eval_tree =
+ ruby_eval_tree =
block_append(NEW_GASGN(rb_intern("$F"),
NEW_CALL(NEW_GVAR(rb_intern("$_")),
rb_intern("split"), 0)),
- eval_tree);
+ ruby_eval_tree);
}
if (chop) {
- eval_tree =
+ ruby_eval_tree =
block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("chop!"), 0), eval_tree);
+ rb_intern("chop!"), 0), ruby_eval_tree);
}
- eval_tree = NEW_OPT_N(eval_tree);
+ ruby_eval_tree = NEW_OPT_N(ruby_eval_tree);
}
-static struct op_tbl rb_op_tbl[] = {
- DOT2, "..",
+static struct {
+ ID token;
+ char *name;
+} op_tbl[] = {
+ tDOT2, "..",
'+', "+",
'-', "-",
'+', "+(binary)",
@@ -3679,35 +4103,36 @@ static struct op_tbl rb_op_tbl[] = {
'*', "*",
'/', "/",
'%', "%",
- POW, "**",
- UPLUS, "+@",
- UMINUS, "-@",
- UPLUS, "+(unary)",
- UMINUS, "-(unary)",
+ tPOW, "**",
+ tUPLUS, "+@",
+ tUMINUS, "-@",
+ tUPLUS, "+(unary)",
+ tUMINUS, "-(unary)",
'|', "|",
'^', "^",
'&', "&",
- CMP, "<=>",
+ tCMP, "<=>",
'>', ">",
- GEQ, ">=",
+ tGEQ, ">=",
'<', "<",
- LEQ, "<=",
- EQ, "==",
- EQQ, "===",
- NEQ, "!=",
- MATCH, "=~",
- NMATCH, "!~",
+ tLEQ, "<=",
+ tEQ, "==",
+ tEQQ, "===",
+ tNEQ, "!=",
+ tMATCH, "=~",
+ tNMATCH, "!~",
'!', "!",
'~', "~",
'!', "!(unary)",
'~', "~(unary)",
'!', "!@",
'~', "~@",
- AREF, "[]",
- ASET, "[]=",
- LSHFT, "<<",
- RSHFT, ">>",
- COLON2, "::",
+ tAREF, "[]",
+ tASET, "[]=",
+ tLSHFT, "<<",
+ tRSHFT, ">>",
+ tCOLON2, "::",
+ tCOLON3, "::",
'`', "`",
0, 0,
};
@@ -3715,16 +4140,14 @@ static struct op_tbl rb_op_tbl[] = {
char *rb_id2name();
char *rb_class2name();
-static st_table *rb_symbol_tbl;
-
-#define sym_tbl rb_symbol_tbl
+static st_table *sym_tbl;
+static st_table *sym_rev_tbl;
void
Init_sym()
{
- int strcmp();
-
- sym_tbl = st_init_strtable();
+ sym_tbl = st_init_strtable_with_size(200);
+ sym_rev_tbl = st_init_numtable_with_size(200);
rb_global_variable((VALUE*)&cur_cref);
rb_global_variable((VALUE*)&lex_lastline);
}
@@ -3740,8 +4163,7 @@ rb_intern(name)
if (st_lookup(sym_tbl, name, &id))
return id;
- id = ++last_id;
- id <<= ID_SCOPE_SHIFT;
+ id = 0;
switch (name[0]) {
case '$':
id |= ID_GLOBAL;
@@ -3749,24 +4171,20 @@ rb_intern(name)
case '@':
id |= ID_INSTANCE;
break;
- /* fall through */
default:
- if (name[0] != '_' && !isalpha(name[0]) && !ismbchar(name[0])) {
+ if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
/* operator */
int i;
- id = 0;
- for (i=0; rb_op_tbl[i].token; i++) {
- if (*rb_op_tbl[i].name == *name &&
- strcmp(rb_op_tbl[i].name, name) == 0) {
- id = rb_op_tbl[i].token;
- break;
+ for (i=0; op_tbl[i].token; i++) {
+ if (*op_tbl[i].name == *name &&
+ strcmp(op_tbl[i].name, name) == 0) {
+ id = op_tbl[i].token;
+ goto id_regist;
}
}
- if (id == 0) NameError("Unknown operator `%s'", name);
- break;
}
-
+
last = strlen(name)-1;
if (name[last] == '=') {
/* attribute assignment */
@@ -3775,66 +4193,55 @@ rb_intern(name)
strncpy(buf, name, last);
buf[last] = '\0';
id = rb_intern(buf);
- id &= ~ID_SCOPE_MASK;
+ if (id > LAST_TOKEN) {
+ id = rb_id_attrset(id);
+ goto id_regist;
+ }
id |= ID_ATTRSET;
}
- else if (isupper(name[0])) {
- id |= ID_CONST;
+ else if (ISUPPER(name[0])) {
+ id = ID_CONST;
}
else {
- id |= ID_LOCAL;
+ id = ID_LOCAL;
}
break;
}
- st_add_direct(sym_tbl, strdup(name), id);
+ id |= ++last_id << ID_SCOPE_SHIFT;
+ id_regist:
+ name = strdup(name);
+ st_add_direct(sym_tbl, name, id);
+ st_add_direct(sym_rev_tbl, id, name);
return id;
}
-struct find_ok {
- ID id;
- char *name;
-};
-
-static int
-id_find(name, id1, ok)
- char *name;
- ID id1;
- struct find_ok *ok;
-{
- if (id1 == ok->id) {
- ok->name = name;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
char *
rb_id2name(id)
ID id;
{
- struct find_ok ok;
+ char *name;
if (id < LAST_TOKEN) {
int i = 0;
- for (i=0; rb_op_tbl[i].token; i++) {
- if (rb_op_tbl[i].token == id)
- return rb_op_tbl[i].name;
+ for (i=0; op_tbl[i].token; i++) {
+ if (op_tbl[i].token == id)
+ return op_tbl[i].name;
}
}
- ok.name = 0;
- ok.id = id;
- st_foreach(sym_tbl, id_find, &ok);
- if (!ok.name && is_attrset_id(id)) {
+ if (st_lookup(sym_rev_tbl, id, &name))
+ return name;
+
+ if (is_attrset_id(id)) {
char *res;
- ID id2;
+ ID id2;
id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
res = rb_id2name(id2);
if (res) {
- char *buf = ALLOCA_N(char,strlen(res)+2);
+ char *buf = ALLOCA_N(char, strlen(res)+2);
strcpy(buf, res);
strcat(buf, "=");
@@ -3842,55 +4249,23 @@ rb_id2name(id)
return rb_id2name(id);
}
}
- return ok.name;
+ return 0;
}
int
rb_is_const_id(id)
ID id;
{
- if (is_const_id(id)) return TRUE;
- return FALSE;
+ if (is_const_id(id)) return Qtrue;
+ return Qfalse;
}
int
rb_is_instance_id(id)
ID id;
{
- if (is_instance_id(id)) return TRUE;
- return FALSE;
-}
-
-void
-local_var_append(id)
- ID id;
-{
- struct local_vars tmp;
- struct local_vars *save = lvtbl;
-
- if (the_scope->local_tbl) {
- tmp.cnt = the_scope->local_tbl[0];
- tmp.tbl = the_scope->local_tbl;
- lvtbl->dlev = 0;
- }
- lvtbl = &tmp;
- local_cnt(id);
- lvtbl = save;
-}
-
-static VALUE
-special_local_get(c)
- char c;
-{
- int cnt, max;
-
- if (!the_scope->local_vars) return Qnil;
- for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) {
- if (the_scope->local_tbl[cnt] == c) {
- return the_scope->local_vars[cnt-1];
- }
- }
- return Qnil;
+ if (is_instance_id(id)) return Qtrue;
+ return Qfalse;
}
static void
@@ -3898,46 +4273,52 @@ special_local_set(c, val)
char c;
VALUE val;
{
- int cnt, max;
+ int cnt;
- if (the_scope->local_tbl) {
- for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) {
- if (the_scope->local_tbl[cnt] == c) {
- the_scope->local_vars[cnt-1] = val;
- return;
- }
- }
- }
top_local_init();
cnt = local_cnt(c);
top_local_setup();
- the_scope->local_vars[cnt] = val;
+ ruby_scope->local_vars[cnt] = val;
}
VALUE
-backref_get()
+rb_backref_get()
{
- return special_local_get('~');
+ if (ruby_scope->local_vars) {
+ return ruby_scope->local_vars[1];
+ }
+ return Qnil;
}
void
-backref_set(val)
+rb_backref_set(val)
VALUE val;
{
- special_local_set('~', val);
+ if (ruby_scope->local_vars) {
+ ruby_scope->local_vars[1] = val;
+ }
+ else {
+ special_local_set('~', val);
+ }
}
VALUE
-lastline_get()
+rb_lastline_get()
{
- VALUE v = special_local_get('_');
- if (v == 1) return Qnil; /* $_ undefined */
- return v;
+ if (ruby_scope->local_vars) {
+ return ruby_scope->local_vars[0];
+ }
+ return Qnil;
}
void
-lastline_set(val)
+rb_lastline_set(val)
VALUE val;
{
- special_local_set('_', val);
+ if (ruby_scope->local_vars) {
+ ruby_scope->local_vars[0] = val;
+ }
+ else {
+ special_local_set('_', val);
+ }
}
diff --git a/process.c b/process.c
index 9d50fea8bf..d3e6559ca3 100644
--- a/process.c
+++ b/process.c
@@ -6,15 +6,14 @@
$Date$
created at: Tue Aug 10 14:30:50 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-#include "sig.h"
+#include "rubysig.h"
#include <stdio.h>
#include <errno.h>
-#include <ctype.h>
#include <signal.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -29,8 +28,9 @@ struct timeval {
};
#endif
#endif /* NT */
+#include <ctype.h>
-struct timeval time_timeval();
+struct timeval rb_time_timeval _((VALUE));
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
@@ -43,6 +43,11 @@ struct timeval time_timeval();
#endif
#include "st.h"
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+# include "macruby_missing.h"
+#endif
+
static VALUE
get_pid()
{
@@ -59,12 +64,11 @@ get_ppid()
#endif
}
-VALUE last_status = Qnil;
+VALUE rb_last_status = Qnil;
#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
+#define NO_WAITPID
static st_table *pid_tbl;
-#else
-# define WAIT_CALL
#endif
static int
@@ -74,69 +78,54 @@ rb_waitpid(pid, flags, st)
int *st;
{
int result;
-#if defined(THREAD) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT4))
+#ifndef NO_WAITPID
+#if defined(USE_THREAD)
int oflags = flags;
- if (!thread_alone()) { /* there're other threads to run */
+ if (!rb_thread_alone()) { /* there're other threads to run */
flags |= WNOHANG;
}
#endif
-#ifdef HAVE_WAITPID
retry:
+#ifdef HAVE_WAITPID
result = waitpid(pid, st, flags);
- if (result < 0) {
- if (errno == EINTR) {
-#ifdef THREAD
- thread_schedule();
-#endif
- goto retry;
- }
- return -1;
- }
-#ifdef THREAD
- if (result == 0) {
- if (oflags & WNOHANG) return 0;
- thread_schedule();
- if (thread_alone()) flags = oflags;
- goto retry;
- }
-#endif
-#else
-#ifdef HAVE_WAIT4
- retry:
-
+#else /* HAVE_WAIT4 */
result = wait4(pid, st, flags, NULL);
+#endif
if (result < 0) {
if (errno == EINTR) {
+#ifdef USE_THREAD
+ rb_thread_schedule();
+#endif
goto retry;
}
return -1;
}
-#ifdef THREAD
+#ifdef USE_THREAD
if (result == 0) {
if (oflags & WNOHANG) return 0;
- thread_schedule();
- if (thread_alone()) flags = oflags;
+ rb_thread_schedule();
+ if (rb_thread_alone()) flags = oflags;
goto retry;
}
#endif
-#else
+#else /* NO_WAITPID */
if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
- last_status = INT2FIX(*st);
+ rb_last_status = INT2FIX(*st);
st_delete(pid_tbl, &pid, NULL);
return pid;
}
if (flags) {
- ArgError("Can't do waitpid with flags");
+ rb_raise(rb_eArgError, "Can't do waitpid with flags");
}
for (;;) {
result = wait(st);
if (result < 0) {
if (errno == EINTR) {
-#ifdef THREAD
- thread_schedule();
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
continue;
}
@@ -148,14 +137,16 @@ rb_waitpid(pid, flags, st)
if (!pid_tbl)
pid_tbl = st_init_numtable();
st_insert(pid_tbl, pid, st);
- }
+#ifdef USE_THREAD
+ if (!thread_alone()) rb_thread_schedule();
#endif
+ }
#endif
- last_status = INT2FIX(*st);
+ rb_last_status = INT2FIX(*st);
return result;
}
-#ifndef WAIT_CALL
+#ifdef NO_WAITPID
struct wait_data {
int pid;
int status;
@@ -175,36 +166,38 @@ wait_each(key, value, data)
#endif
static VALUE
-f_wait()
+rb_f_wait()
{
int pid, state;
-#ifndef WAIT_CALL
+#ifdef NO_WAITPID
struct wait_data data;
data.status = -1;
st_foreach(pid_tbl, wait_each, &data);
if (data.status != -1) {
- last_status = data.status;
+ rb_last_status = data.status;
return INT2FIX(data.pid);
}
-#endif
while ((pid = wait(&state)) < 0) {
- if (errno == EINTR) {
-#ifdef THREAD
- thread_schedule();
+ if (errno == EINTR) {
+#ifdef USE_THREAD
+ rb_thread_schedule();
#endif
- continue;
- }
- if (errno == ECHILD) return Qnil;
- rb_sys_fail(0);
+ continue;
+ }
+ rb_sys_fail(0);
}
- last_status = INT2FIX(state);
+ rb_last_status = INT2FIX(state);
+#else
+ if ((pid = rb_waitpid(-1, 0, &state)) < 0)
+ rb_sys_fail(0);
+#endif
return INT2FIX(pid);
}
static VALUE
-f_waitpid(obj, vpid, vflags)
+rb_f_waitpid(obj, vpid, vflags)
VALUE obj, vpid, vflags;
{
int pid, flags, status;
@@ -219,46 +212,26 @@ f_waitpid(obj, vpid, vflags)
char *strtok();
-#if defined(THREAD) && defined(HAVE_SETITIMER)
-static void
-before_exec()
-{
- struct itimerval tval;
-
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 0;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-}
-
-static void
-after_exec()
-{
- struct itimerval tval;
-
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 100000;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-}
+#if defined(USE_THREAD) && defined(HAVE_SETITIMER)
+#define before_exec() rb_thread_stop_timer()
+#define after_exec() rb_thread_start_timer()
#else
#define before_exec()
#define after_exec()
#endif
extern char *dln_find_exe();
-int env_path_tainted();
static void
security(str)
char *str;
{
- extern VALUE eSecurityError;
-
if (rb_safe_level() > 0) {
- if (env_path_tainted()) {
- Raise(eSecurityError, "Insecure PATH - %s", str);
+#ifndef USE_CWGUSI
+ if (rb_env_path_tainted()) {
+ rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
}
+#endif
}
}
@@ -267,6 +240,7 @@ proc_exec_v(argv, prog)
char **argv;
char *prog;
{
+#ifndef USE_CWGUSI
if (prog) {
security(prog);
}
@@ -315,6 +289,9 @@ proc_exec_v(argv, prog)
execv(prog, argv);
after_exec();
return -1;
+#else /* USE_CWGUSI */
+ rb_notimplement();
+#endif /* USE_CWGUSI */
}
static int
@@ -328,12 +305,10 @@ proc_exec_n(argc, argv, progv)
int i;
if (progv) {
- Check_SafeStr(progv);
prog = RSTRING(progv)->ptr;
}
args = ALLOCA_N(char*, argc+1);
for (i=0; i<argc; i++) {
- Check_SafeStr(argv[i]);
args[i] = RSTRING(argv[i])->ptr;
}
args[i] = 0;
@@ -347,12 +322,13 @@ int
rb_proc_exec(str)
char *str;
{
+#ifndef USE_CWGUSI
char *s = str, *t;
char **argv, **a;
security(str);
for (s=str; *s; s++) {
- if (*s != ' ' && !isalpha(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
+ if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
#if defined(MSDOS)
int state;
before_exec();
@@ -361,7 +337,7 @@ rb_proc_exec(str)
if (state != -1)
exit(state);
#else
-#if defined(__human68k__)
+#if defined(__human68k__) || defined(__CYGWIN32__)
char *shell = dln_find_exe("sh", 0);
int state = -1;
before_exec();
@@ -395,6 +371,9 @@ rb_proc_exec(str)
}
errno = ENOENT;
return -1;
+#else /* USE_CWGUSI */
+ rb_notimplement();
+#endif /* USE_CWGUSI */
}
#if defined(__human68k__)
@@ -466,15 +445,18 @@ proc_spawn_n(argc, argv, prog)
}
static int
-proc_spawn(str)
- char *str;
+proc_spawn(sv)
+ VALUE sv;
{
- char *s = str, *t;
+ char *str;
+ char *s, *t;
char **argv, **a;
int state;
+ Check_SafeStr(sv);
+ str = s = RSTRING(sv)->ptr;
for (s = str; *s; s++) {
- if (*s != ' ' && !isalpha(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
+ if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
char *shell = dln_find_exe("sh", 0);
before_exec();
state = shell ? spawnl(P_WAIT, shell, "sh", "-c", str, (char *) NULL) : system(str) ;
@@ -495,15 +477,19 @@ proc_spawn(str)
#endif /* __human68k__ */
static VALUE
-f_exec(argc, argv)
+rb_f_exec(argc, argv)
int argc;
VALUE *argv;
{
VALUE prog = 0;
+ int i;
+ if (argc == 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments");
+ }
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
prog = RARRAY(argv[0])->ptr[0];
argv[0] = RARRAY(argv[0])->ptr[1];
@@ -511,13 +497,18 @@ f_exec(argc, argv)
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
prog = RARRAY(argv[0])->ptr[0];
argv[0] = RARRAY(argv[0])->ptr[1];
}
+ if (prog) {
+ Check_SafeStr(prog);
+ }
+ for (i = 0; i < argc; i++) {
+ Check_SafeStr(argv[i]);
+ }
if (argc == 1 && prog == 0) {
- Check_SafeStr(argv[0]);
rb_proc_exec(RSTRING(argv[0])->ptr);
}
else {
@@ -527,7 +518,7 @@ f_exec(argc, argv)
}
static VALUE
-f_fork(obj)
+rb_f_fork(obj)
VALUE obj;
{
#if !defined(__human68k__)
@@ -539,7 +530,7 @@ f_fork(obj)
#ifdef linux
after_exec();
#endif
- if (iterator_p()) {
+ if (rb_iterator_p()) {
rb_yield(Qnil);
_exit(0);
}
@@ -558,17 +549,21 @@ f_fork(obj)
}
static VALUE
-f_exit_bang(obj, status)
+rb_f_exit_bang(obj, status)
VALUE obj, status;
{
int code = -1;
- rb_secure(2);
+ rb_secure(4);
if (FIXNUM_P(status)) {
code = INT2FIX(status);
}
+#ifdef USE_CWGUSI
+ exit(code);
+#else
_exit(code);
+#endif
/* not reached */
}
@@ -579,6 +574,7 @@ rb_syswait(pid)
{
RETSIGTYPE (*hfunc)(), (*qfunc)(), (*ifunc)();
int status;
+ int i;
#ifdef SIGHUP
hfunc = signal(SIGHUP, SIG_IGN);
@@ -588,7 +584,9 @@ rb_syswait(pid)
#endif
ifunc = signal(SIGINT, SIG_IGN);
- if (rb_waitpid(pid, 0, &status) < 0) rb_sys_fail("wait");
+ do {
+ i = rb_waitpid(pid, 0, &status);
+ } while (i == -1 && errno == EINTR);
#ifdef SIGHUP
signal(SIGHUP, hfunc);
@@ -600,7 +598,7 @@ rb_syswait(pid)
}
static VALUE
-f_system(argc, argv)
+rb_f_system(argc, argv)
int argc;
VALUE *argv;
{
@@ -610,18 +608,18 @@ f_system(argc, argv)
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
argv[0] = RARRAY(argv[0])->ptr[0];
}
- cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+ cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
Check_SafeStr(cmd);
state = do_spawn(RSTRING(cmd)->ptr);
- last_status = INT2FIX(state);
+ rb_last_status = INT2FIX(state);
- if (state == 0) return TRUE;
- return FALSE;
+ if (state == 0) return Qtrue;
+ return Qfalse;
#else
#if defined(DJGPP)
VALUE cmd;
@@ -629,18 +627,18 @@ f_system(argc, argv)
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
argv[0] = RARRAY(argv[0])->ptr[0];
}
- cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+ cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
Check_SafeStr(cmd);
state = system(RSTRING(cmd)->ptr);
- last_status = INT2FIX(state);
+ rb_last_status = INT2FIX(state);
- if (state == 0) return TRUE;
- return FALSE;
+ if (state == 0) return Qtrue;
+ return Qfalse;
#else
#if defined(__human68k__)
VALUE prog = 0;
@@ -651,48 +649,52 @@ f_system(argc, argv)
fflush(stdout);
fflush(stderr);
if (argc == 0) {
- last_status = INT2FIX(0);
+ rb_last_status = INT2FIX(0);
return INT2FIX(0);
}
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
prog = RARRAY(argv[0])->ptr[0];
argv[0] = RARRAY(argv[0])->ptr[1];
}
if (argc == 1 && prog == 0) {
- state = proc_spawn(RSTRING(argv[0])->ptr);
+ state = proc_spawn(argv[0]);
}
else {
state = proc_spawn_n(argc, argv, prog);
}
- last_status = state == -1 ? INT2FIX(127) : INT2FIX(state);
-
- return state == 0 ? TRUE : FALSE ;
+ rb_last_status = state == -1 ? INT2FIX(127) : INT2FIX(state);
+ return state == 0 ? Qtrue : Qfalse ;
#else
- VALUE prog = 0;
- int i;
+ volatile VALUE prog = 0;
int pid;
+ int i;
- fflush(stdin); /* is it really needed? */
fflush(stdout);
fflush(stderr);
if (argc == 0) {
- last_status = INT2FIX(0);
+ rb_last_status = INT2FIX(0);
return INT2FIX(0);
}
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
- ArgError("wrong first argument");
+ rb_raise(rb_eArgError, "wrong first argument");
}
prog = RARRAY(argv[0])->ptr[0];
argv[0] = RARRAY(argv[0])->ptr[1];
}
+ if (prog) {
+ Check_SafeStr(prog);
+ }
+ for (i = 0; i < argc; i++) {
+ Check_SafeStr(argv[i]);
+ }
retry:
switch (pid = vfork()) {
case 0:
@@ -707,8 +709,8 @@ f_system(argc, argv)
case -1:
if (errno == EAGAIN) {
-#ifdef THREAD
- thread_sleep(1);
+#ifdef USE_THREAD
+ rb_thread_sleep(1);
#else
sleep(1);
#endif
@@ -721,27 +723,27 @@ f_system(argc, argv)
rb_syswait(pid);
}
- if (last_status == INT2FIX(0)) return TRUE;
- return FALSE;
+ if (rb_last_status == INT2FIX(0)) return Qtrue;
+ return Qfalse;
#endif
#endif
#endif
}
static VALUE
-f_sleep(argc, argv)
+rb_f_sleep(argc, argv)
int argc;
VALUE *argv;
{
int beg, end;
beg = time(0);
-#ifdef THREAD
+#ifdef USE_THREAD
if (argc == 0) {
- thread_sleep_forever();
+ rb_thread_sleep_forever();
}
else if (argc == 1) {
- thread_wait_for(time_timeval(argv[0]));
+ rb_thread_wait_for(rb_time_timeval(argv[0]));
}
#else
if (argc == 0) {
@@ -753,7 +755,7 @@ f_sleep(argc, argv)
struct timeval tv;
int n;
- tv = time_timeval(argv[0]);
+ tv = rb_time_timeval(argv[0]);
TRAP_BEG;
n = select(0, 0, 0, 0, &tv);
TRAP_END;
@@ -761,7 +763,7 @@ f_sleep(argc, argv)
}
#endif
else {
- ArgError("wrong # of arguments");
+ rb_raise(rb_eArgError, "wrong # of arguments");
}
end = time(0) - beg;
@@ -769,7 +771,7 @@ f_sleep(argc, argv)
return INT2FIX(end);
}
-#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__)
+#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__) && !defined(USE_CWGUSI)
static VALUE
proc_getpgrp(argc, argv)
int argc;
@@ -781,7 +783,7 @@ proc_getpgrp(argc, argv)
int pid;
rb_scan_args(argc, argv, "01", &vpid);
- pid = NUM2INT(vpid);
+ pid = NIL_P(vpid)?0:NUM2INT(vpid);
pgrp = BSD_GETPGRP(pid);
#else
rb_scan_args(argc, argv, "0");
@@ -796,27 +798,45 @@ proc_setpgrp(argc, argv)
int argc;
VALUE *argv;
{
+#ifdef HAVE_SETPGRP
#ifdef BSD_SETPGRP
VALUE pid, pgrp;
int ipid, ipgrp;
rb_scan_args(argc, argv, "02", &pid, &pgrp);
- ipid = NUM2INT(pid);
- ipgrp = NUM2INT(pgrp);
+ ipid = NIL_P(pid)?0:NUM2INT(pid);
+ ipgrp = NIL_P(pgrp)?0:NUM2INT(pgrp);
if (BSD_SETPGRP(ipid, ipgrp) < 0) rb_sys_fail(0);
#else
rb_scan_args(argc, argv, "0");
if (setpgrp() < 0) rb_sys_fail(0);
#endif
return Qnil;
+#else
+ rb_notimplement();
+#endif
+}
+
+static VALUE
+proc_getpgid(obj, pid)
+ VALUE obj, pid;
+{
+#ifdef HAVE_GETPGID
+ int i;
+
+ i = getpgid(NUM2INT(pid));
+ return INT2NUM(i);
+#else
+ rb_notimplement();
+#endif
}
-#ifdef HAVE_SETPGID
static VALUE
proc_setpgid(obj, pid, pgrp)
VALUE obj, pid, pgrp;
{
+#ifdef HAVE_SETPGID
int ipid, ipgrp;
ipid = NUM2INT(pid);
@@ -824,8 +844,23 @@ proc_setpgid(obj, pid, pgrp)
if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
return Qnil;
+#else
+ rb_notimplement();
+#endif
}
+
+static VALUE
+proc_setsid()
+{
+#ifdef HAVE_SETSID
+ int pid = setsid();
+
+ if (pid < 0) rb_sys_fail(0);
+ return INT2FIX(pid);
+#else
+ rb_notimplement();
#endif
+}
static VALUE
proc_getpriority(obj, which, who)
@@ -880,12 +915,12 @@ proc_setuid(obj, id)
int uid;
uid = NUM2INT(id);
-#ifdef HAVE_SETRUID
- setruid(uid);
-#else
#ifdef HAVE_SETREUID
setreuid(uid, -1);
#else
+#ifdef HAVE_SETRUID
+ setruid(uid);
+#else
{
if (geteuid() == uid)
setuid(uid);
@@ -985,74 +1020,83 @@ proc_setegid(obj, egid)
return egid;
}
-VALUE mProcess;
-
-extern VALUE f_kill();
+VALUE rb_mProcess;
void
Init_process()
{
+#ifndef USE_CWGUSI
rb_define_virtual_variable("$$", get_pid, 0);
- rb_define_readonly_variable("$?", &last_status);
- rb_define_global_function("exec", f_exec, -1);
-#ifndef NT
- rb_define_global_function("fork", f_fork, 0);
#endif
- rb_define_global_function("exit!", f_exit_bang, 1);
- rb_define_global_function("system", f_system, -1);
- rb_define_global_function("sleep", f_sleep, -1);
+ rb_define_readonly_variable("$?", &rb_last_status);
+#ifndef USE_CWGUSI
+ rb_define_global_function("exec", rb_f_exec, -1);
+#endif
+#if !defined(NT) && !defined(USE_CWGUSI)
+ rb_define_global_function("fork", rb_f_fork, 0);
+#endif
+ rb_define_global_function("exit!", rb_f_exit_bang, 1);
+#ifndef USE_CWGUSI
+ rb_define_global_function("system", rb_f_system, -1);
+#endif
+ rb_define_global_function("sleep", rb_f_sleep, -1);
- mProcess = rb_define_module("Process");
+ rb_mProcess = rb_define_module("Process");
#if !defined(NT) && !defined(DJGPP)
#ifdef WNOHANG
- rb_define_const(mProcess, "WNOHANG", INT2FIX(WNOHANG));
+ rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
#else
- rb_define_const(mProcess, "WNOHANG", INT2FIX(0));
+ rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
#endif
#ifdef WUNTRACED
- rb_define_const(mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
+ rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
#else
- rb_define_const(mProcess, "WUNTRACED", INT2FIX(0));
+ rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
#endif
#endif
-#ifndef NT
- rb_define_singleton_method(mProcess, "fork", f_fork, 0);
+#if !defined(NT) && !defined(USE_CWGUSI)
+ rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
+#endif
+ rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, 1);
+#ifndef USE_CWGUSI
+ rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1);
#endif
- rb_define_singleton_method(mProcess, "exit!", f_exit_bang, 1);
- rb_define_module_function(mProcess, "kill", f_kill, -1);
#ifndef NT
- rb_define_module_function(mProcess, "wait", f_wait, 0);
- rb_define_module_function(mProcess, "waitpid", f_waitpid, 2);
+ rb_define_module_function(rb_mProcess, "wait", rb_f_wait, 0);
+ rb_define_module_function(rb_mProcess, "waitpid", rb_f_waitpid, 2);
- rb_define_module_function(mProcess, "pid", get_pid, 0);
- rb_define_module_function(mProcess, "ppid", get_ppid, 0);
-#endif
+#ifndef USE_CWGUSI
+ rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
+ rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
+#endif /* ifndef USE_CWGUSI */
+#endif /* ifndef NT */
-#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__)
- rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, -1);
- rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, -1);
-#ifdef HAVE_SETPGID
- rb_define_module_function(mProcess, "setpgid", proc_setpgid, 2);
-#endif
+#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__) && !defined(USE_CWGUSI)
+ rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, -1);
+ rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, -1);
+ rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
+ rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
-#ifdef HAVE_GETPRIORITY
- rb_define_module_function(mProcess, "getpriority", proc_getpriority, 2);
- rb_define_module_function(mProcess, "setpriority", proc_setpriority, 3);
+ rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
+
+ rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
+ rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
- rb_define_const(mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
- rb_define_const(mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
- rb_define_const(mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
+#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_define_module_function(mProcess, "uid", proc_getuid, 0);
- rb_define_module_function(mProcess, "uid=", proc_setuid, 1);
- rb_define_module_function(mProcess, "gid", proc_getgid, 0);
- rb_define_module_function(mProcess, "gid=", proc_setgid, 1);
- rb_define_module_function(mProcess, "euid", proc_geteuid, 0);
- rb_define_module_function(mProcess, "euid=", proc_seteuid, 1);
- rb_define_module_function(mProcess, "egid", proc_getegid, 0);
- rb_define_module_function(mProcess, "egid=", proc_setegid, 1);
+ rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
+ rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
+ rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
+ rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
+ rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
+ rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
+ rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
+ rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
#endif
}
diff --git a/random.c b/random.c
index d0a5756b69..7b57d472cd 100644
--- a/random.c
+++ b/random.c
@@ -6,17 +6,80 @@
$Date$
created at: Fri Dec 24 16:39:21 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
+#include <time.h>
+#ifndef NT
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif
+#endif /* NT */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+/*
+ * Prefer to use drand48, otherwise use random, or rand as a last resort.
+ */
+#ifdef HAVE_DRAND48
+
+#ifndef HAVE_DRAND48_DECL
+double drand48 _((void));
+void srand48 _((long));
+#endif
+
+#define SRANDOM(s) srand48((long)(s))
+#define RANDOM_NUMBER drand48()
+
+#else /* not HAVE_DRAND48 */
+
+/*
+ * The largest number returned by the random number generator is
+ * RANDOM_MAX. If we're using `rand' it's RAND_MAX, but if we're
+ * using `random' it's 2^31-1.
+ */
+#ifndef RANDOM_MAX
+# ifndef HAVE_RANDOM
+# define RANDOM_MAX RAND_MAX
+# else
+# define RANDOM_MAX 2147483647.0
+# endif
+#endif
+
+#ifdef HAVE_RANDOM
+
+#define RANDOM random
+#define SRANDOM srandom
+
+#else /* HAVE_RANDOM */
+
+#define RANDOM rand
+#define SRANDOM srand
+
+#endif /* HAVE_RANDOM */
+
+/* 0 <= RANDOM_NUMBER <= 1 */
+#define RANDOM_NUMBER (((double)RANDOM())/(double)RANDOM_MAX)
+
+#endif /* not HAVE_DRAND48 */
+
+#ifdef HAVE_RANDOM
static int first = 1;
static char state[256];
+#endif
static VALUE
-f_srand(argc, argv, obj)
+rb_f_srand(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -26,10 +89,13 @@ f_srand(argc, argv, obj)
static int saved_seed;
if (rb_scan_args(argc, argv, "01", &seed) == 0) {
- seed = time(0);
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+ seed = tv.tv_sec ^ tv.tv_usec;
}
else {
- seed = NUM2INT(seed);
+ seed = NUM2UINT(seed);
}
#ifdef HAVE_RANDOM
@@ -40,62 +106,44 @@ f_srand(argc, argv, obj)
else {
setstate(state);
}
+#endif
- srandom(seed);
- old = saved_seed;
- saved_seed = seed;
-
- return int2inum(old);
-#else
- srand(seed);
+ SRANDOM(seed);
old = saved_seed;
saved_seed = seed;
- return int2inum(old);
-#endif
+ return rb_int2inum(old);
}
static VALUE
-f_rand(obj, vmax)
+rb_f_rand(obj, vmax)
VALUE obj, vmax;
{
- int val, max;
-
-#ifdef HAVE_RANDOM
- if (first == 1) {
- initstate(1, state, sizeof state);
- first = 0;
- }
-#endif
+ long val, max;
switch (TYPE(vmax)) {
case T_BIGNUM:
- return big_rand(vmax);
+ return rb_big_rand(vmax);
case T_FLOAT:
if (RFLOAT(vmax)->value > LONG_MAX || RFLOAT(vmax)->value < LONG_MIN)
- return big_rand(dbl2big(RFLOAT(vmax)->value));
+ return rb_big_rand(rb_dbl2big(RFLOAT(vmax)->value));
break;
}
- max = NUM2INT(vmax);
- if (max == 0) ArgError("rand(0)");
-
-#ifdef HAVE_RANDOM
- val = random() % max;
-#else
- val = rand() % max;
-#endif
+ max = NUM2LONG(vmax);
+ if (max == 0) {
+ return rb_float_new(RANDOM_NUMBER);
+ }
+ val = max*RANDOM_NUMBER;
if (val < 0) val = -val;
- return int2inum(val);
+ return rb_int2inum(val);
}
void
Init_Random()
{
- extern VALUE mKernel;
-
- rb_define_global_function("srand", f_srand, -1);
- rb_define_global_function("rand", f_rand, 1);
+ rb_define_global_function("srand", rb_f_srand, -1);
+ rb_define_global_function("rand", rb_f_rand, 1);
}
diff --git a/range.c b/range.c
index 9596e07f93..9fc363e2a8 100644
--- a/range.c
+++ b/range.c
@@ -6,81 +6,93 @@
$Date$
created at: Thu Aug 19 17:46:47 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-static VALUE cRange;
-extern VALUE cNumeric;
+VALUE rb_cRange;
+static ID id_upto, id_cmp;
+static ID id_beg, id_end;
-static ID upto;
+static VALUE
+range_check(args)
+ VALUE *args;
+{
+ rb_funcall(args[0], id_cmp, 1, args[1]);
+ return Qnil;
+}
+
+static VALUE
+range_failed()
+{
+ rb_raise(rb_eArgError, "bad value for range");
+}
static VALUE
-range_s_new(class, first, last)
- VALUE class, first, last;
+range_s_new(klass, beg, end)
+ VALUE klass, beg, end;
{
VALUE obj;
- if (!(FIXNUM_P(first) && FIXNUM_P(last))
- && (TYPE(first) != TYPE(last)
- || CLASS_OF(first) != CLASS_OF(last)
- || !rb_respond_to(first, upto))
- && !(obj_is_kind_of(first, cNumeric)
- && obj_is_kind_of(last, cNumeric))) {
- ArgError("bad value for range");
+ if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
+ VALUE args[2];
+
+ args[0] = beg; args[1] = end;
+ rb_rescue(range_check, (VALUE)args, range_failed, 0);
}
- obj = obj_alloc(class);
+ obj = rb_obj_alloc(klass);
- rb_iv_set(obj, "first", first);
- rb_iv_set(obj, "last", last);
+ rb_ivar_set(obj, id_beg, beg);
+ rb_ivar_set(obj, id_end, end);
+ rb_obj_call_init(obj);
return obj;
}
VALUE
-range_new(first, last)
- VALUE first, last;
+rb_range_new(beg, end)
+ VALUE beg, end;
{
- return range_s_new(cRange, first, last);
+ return range_s_new(rb_cRange, beg, end);
}
static VALUE
range_eqq(rng, obj)
VALUE rng, obj;
{
- VALUE first, last;
+ VALUE beg, end;
- first = rb_iv_get(rng, "first");
- last = rb_iv_get(rng, "last");
+ beg = rb_ivar_get(rng, id_beg);
+ end = rb_ivar_get(rng, id_end);
- if (FIXNUM_P(first) && FIXNUM_P(obj) && FIXNUM_P(last)) {
- if (FIX2INT(first) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(last)) {
- return TRUE;
+ if (FIXNUM_P(beg) && FIXNUM_P(obj) && FIXNUM_P(end)) {
+ if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
else {
- if (RTEST(rb_funcall(first, rb_intern("<="), 1, obj)) &&
- RTEST(rb_funcall(last, rb_intern(">="), 1, obj))) {
- return TRUE;
+ if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj)) &&
+ RTEST(rb_funcall(end, rb_intern(">="), 1, obj))) {
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
}
struct upto_data {
- VALUE first;
- VALUE last;
+ VALUE beg;
+ VALUE end;
};
static VALUE
range_upto(data)
struct upto_data *data;
{
- return rb_funcall(data->first, upto, 1, data->last);
+ return rb_funcall(data->beg, id_upto, 1, data->end);
}
static VALUE
@@ -89,19 +101,19 @@ range_each(obj)
{
VALUE b, e;
- b = rb_iv_get(obj, "first");
- e = rb_iv_get(obj, "last");
+ b = rb_ivar_get(obj, id_beg);
+ e = rb_ivar_get(obj, id_end);
if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
- num_upto(b, e);
+ rb_fix_upto(b, e);
}
else {
struct upto_data data;
- data.first = b;
- data.last = e;
+ data.beg = b;
+ data.end = e;
- rb_iterate(range_upto, &data, rb_yield, 0);
+ rb_iterate(range_upto, (VALUE)&data, rb_yield, 0);
}
return Qnil;
@@ -113,7 +125,7 @@ range_first(obj)
{
VALUE b;
- b = rb_iv_get(obj, "first");
+ b = rb_ivar_get(obj, id_beg);
return b;
}
@@ -123,22 +135,22 @@ range_last(obj)
{
VALUE e;
- e = rb_iv_get(obj, "last");
+ e = rb_ivar_get(obj, id_end);
return e;
}
VALUE
-range_beg_end(range, begp, endp)
+rb_range_beg_end(range, begp, endp)
VALUE range;
int *begp, *endp;
{
- VALUE first, last;
+ VALUE beg, end;
- if (!obj_is_kind_of(range, cRange)) return FALSE;
+ if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
- first = rb_iv_get(range, "first"); *begp = NUM2INT(first);
- last = rb_iv_get(range, "last"); *endp = NUM2INT(last);
- return TRUE;
+ beg = rb_ivar_get(range, id_beg); *begp = NUM2INT(beg);
+ end = rb_ivar_get(range, id_end); *endp = NUM2INT(end);
+ return Qtrue;
}
static VALUE
@@ -147,10 +159,10 @@ range_to_s(range)
{
VALUE str, str2;
- str = obj_as_string(rb_iv_get(range, "first"));
- str2 = obj_as_string(rb_iv_get(range, "last"));
- str_cat(str, "..", 2);
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ str = rb_obj_as_string(rb_ivar_get(range, id_beg));
+ str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
+ rb_str_cat(str, "..", 2);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return str;
}
@@ -161,52 +173,56 @@ range_inspect(range)
{
VALUE str, str2;
- str = rb_inspect(rb_iv_get(range, "first"));
- str2 = rb_inspect(rb_iv_get(range, "last"));
- str_cat(str, "..", 2);
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ str = rb_inspect(rb_ivar_get(range, id_beg));
+ str2 = rb_inspect(rb_ivar_get(range, id_end));
+ rb_str_cat(str, "..", 2);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return str;
}
-VALUE enum_length();
-
static VALUE
range_length(rng)
VALUE rng;
{
- VALUE first, last;
+ VALUE beg, end;
VALUE size;
- first = rb_iv_get(rng, "first");
- last = rb_iv_get(rng, "last");
+ beg = rb_ivar_get(rng, id_beg);
+ end = rb_ivar_get(rng, id_end);
- if (!obj_is_kind_of(first, cNumeric)) {
- return enum_length(rng);
+ if (RTEST(rb_funcall(beg, '>', 1, end))) {
+ return INT2FIX(0);
+ }
+ if (!rb_obj_is_kind_of(beg, rb_cNumeric)) {
+ return rb_enum_length(rng);
}
- size = rb_funcall(last, '-', 1, first);
+ size = rb_funcall(end, '-', 1, beg);
size = rb_funcall(size, '+', 1, INT2FIX(1));
return size;
}
-extern VALUE mEnumerable;
-
void
Init_Range()
{
- cRange = rb_define_class("Range", cObject);
- rb_include_module(cRange, mEnumerable);
- rb_define_singleton_method(cRange, "new", range_s_new, 2);
- rb_define_method(cRange, "===", range_eqq, 1);
- rb_define_method(cRange, "each", range_each, 0);
- rb_define_method(cRange, "first", range_first, 0);
- rb_define_method(cRange, "last", range_last, 0);
- rb_define_method(cRange, "to_s", range_to_s, 0);
- rb_define_method(cRange, "inspect", range_inspect, 0);
-
- rb_define_method(cRange, "length", range_length, 0);
- rb_define_method(cRange, "size", range_length, 0);
-
- upto = rb_intern("upto");
+ rb_cRange = rb_define_class("Range", rb_cObject);
+ rb_include_module(rb_cRange, rb_mEnumerable);
+ rb_define_singleton_method(rb_cRange, "new", range_s_new, 2);
+ rb_define_method(rb_cRange, "===", range_eqq, 1);
+ rb_define_method(rb_cRange, "each", range_each, 0);
+ rb_define_method(rb_cRange, "first", range_first, 0);
+ rb_define_method(rb_cRange, "last", range_last, 0);
+ rb_define_method(rb_cRange, "begin", range_first, 0);
+ rb_define_method(rb_cRange, "end", range_last, 0);
+ rb_define_method(rb_cRange, "to_s", range_to_s, 0);
+ rb_define_method(rb_cRange, "inspect", range_inspect, 0);
+
+ rb_define_method(rb_cRange, "length", range_length, 0);
+ rb_define_method(rb_cRange, "size", range_length, 0);
+
+ id_upto = rb_intern("upto");
+ id_cmp = rb_intern("<=>");
+ id_beg = rb_intern("begin");
+ id_end = rb_intern("end");
}
diff --git a/re.c b/re.c
index cb0ade9aaf..287c6c1bd4 100644
--- a/re.c
+++ b/re.c
@@ -3,17 +3,16 @@
re.c -
$Author$
- $Date$
created at: Mon Aug 9 18:24:49 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "re.h"
-static VALUE eRegxpError;
+static VALUE rb_eRegxpError;
#define BEG(no) regs->beg[no]
#define END(no) regs->end[no]
@@ -69,16 +68,16 @@ static char casetable[] = {
>>> "You lose. You will need a translation table for your character set." <<<
#endif
-#define min(a,b) (((a)>(b))?(b):(a))
+#define MIN(a,b) (((a)>(b))?(b):(a))
int
-str_cicmp(str1, str2)
+rb_str_cicmp(str1, str2)
VALUE str1, str2;
{
int len, i;
char *p1, *p2;
- len = min(RSTRING(str1)->len, RSTRING(str2)->len);
+ len = MIN(RSTRING(str1)->len, RSTRING(str2)->len);
p1 = RSTRING(str1)->ptr; p2 = RSTRING(str2)->ptr;
for (i = 0; i < len; i++, p1++, p2++) {
@@ -89,27 +88,33 @@ str_cicmp(str1, str2)
}
#define REG_IGNORECASE FL_USER0
+#define REG_CASESTATE FL_USER1
#define KCODE_NONE 0
#define KCODE_EUC FL_USER2
#define KCODE_SJIS FL_USER3
-#define KCODE_FIXED FL_USER4
-#define KCODE_MASK (KCODE_EUC|KCODE_SJIS)
+#define KCODE_UTF8 FL_USER4
+#define KCODE_FIXED FL_USER5
+#define KCODE_MASK (KCODE_EUC|KCODE_SJIS|KCODE_UTF8)
static int reg_kcode =
-#ifdef EUC
+#ifdef RUBY_USE_EUC
KCODE_EUC;
#else
-# ifdef SJIS
+# ifdef RUBY_USE_SJIS
KCODE_SJIS;
# else
+# ifdef RUBY_USE_UTF8
+ KCODE_UTF8
+# else
KCODE_NONE;
+# endif
# endif
#endif
static void
kcode_euc(reg)
- VALUE reg;
+ struct RRegexp *reg;
{
FL_UNSET(reg, KCODE_MASK);
FL_SET(reg, KCODE_EUC);
@@ -118,7 +123,7 @@ kcode_euc(reg)
static void
kcode_sjis(reg)
- VALUE reg;
+ struct RRegexp *reg;
{
FL_UNSET(reg, KCODE_MASK);
FL_SET(reg, KCODE_SJIS);
@@ -126,54 +131,72 @@ kcode_sjis(reg)
}
static void
+kcode_utf8(reg)
+ struct RRegexp *reg;
+{
+ FL_UNSET(reg, KCODE_MASK);
+ FL_SET(reg, KCODE_UTF8);
+ FL_SET(reg, KCODE_FIXED);
+}
+
+static void
kcode_none(reg)
- VALUE reg;
+ struct RRegexp *reg;
{
FL_UNSET(reg, KCODE_MASK);
FL_SET(reg, KCODE_FIXED);
}
+static int curr_kcode;
+
static void
kcode_set_option(reg)
VALUE reg;
{
if (!FL_TEST(reg, KCODE_FIXED)) return;
- re_syntax_options &= ~RE_MBCTYPE_MASK;
- switch ((RBASIC(reg)->flags & KCODE_MASK)) {
+ curr_kcode = RBASIC(reg)->flags & KCODE_MASK;
+ if (reg_kcode == curr_kcode) return;
+ switch (curr_kcode) {
case KCODE_NONE:
+ re_mbcinit(MBCTYPE_ASCII);
break;
case KCODE_EUC:
- re_syntax_options |= RE_MBCTYPE_EUC;
+ re_mbcinit(MBCTYPE_EUC);
break;
case KCODE_SJIS:
- re_syntax_options |= RE_MBCTYPE_SJIS;
+ re_mbcinit(MBCTYPE_SJIS);
+ break;
+ case KCODE_UTF8:
+ re_mbcinit(MBCTYPE_UTF8);
break;
}
- re_set_syntax(re_syntax_options);
}
-void
+static void
kcode_reset_option()
{
- re_syntax_options &= ~RE_MBCTYPE_MASK;
+ if (reg_kcode == curr_kcode) return;
switch (reg_kcode) {
case KCODE_NONE:
+ re_mbcinit(MBCTYPE_ASCII);
break;
case KCODE_EUC:
- re_syntax_options |= RE_MBCTYPE_EUC;
+ re_mbcinit(MBCTYPE_EUC);
break;
case KCODE_SJIS:
- re_syntax_options |= RE_MBCTYPE_SJIS;
+ re_mbcinit(MBCTYPE_SJIS);
+ break;
+ case KCODE_UTF8:
+ re_mbcinit(MBCTYPE_UTF8);
break;
}
- re_set_syntax(re_syntax_options);
}
-extern int rb_in_eval;
+extern int ruby_in_compile;
static void
-reg_expr_str(str, s, len)
+rb_reg_expr_str(str, s, len)
VALUE str;
char *s;
int len;
@@ -190,18 +213,18 @@ reg_expr_str(str, s, len)
p++;
}
if (!slash) {
- str_cat(str, s, len);
+ rb_str_cat(str, s, len);
}
else {
p = s;
while (p<pend) {
if (*p == '/') {
char c = '\\';
- str_cat(str, &c, 1);
- str_cat(str, p, 1);
+ rb_str_cat(str, &c, 1);
+ rb_str_cat(str, p, 1);
}
else {
- str_cat(str, p, 1);
+ rb_str_cat(str, p, 1);
}
p++;
}
@@ -209,27 +232,30 @@ reg_expr_str(str, s, len)
}
static VALUE
-reg_desc(s, len, re)
+rb_reg_desc(s, len, re)
char *s;
int len;
VALUE re;
{
- VALUE str = str_new2("/");
- reg_expr_str(str, s, len);
- str_cat(str, "/", 1);
+ VALUE str = rb_str_new2("/");
+ rb_reg_expr_str(str, s, len);
+ rb_str_cat(str, "/", 1);
if (re) {
- if (FL_TEST(re,REG_IGNORECASE))
- str_cat(str, "i", 1);
- if (FL_TEST(re,KCODE_FIXED)) {
+ if (FL_TEST(re, REG_IGNORECASE))
+ rb_str_cat(str, "i", 1);
+ if (FL_TEST(re, KCODE_FIXED)) {
switch ((RBASIC(re)->flags & KCODE_MASK)) {
case KCODE_NONE:
- str_cat(str, "n", 1);
+ rb_str_cat(str, "n", 1);
break;
case KCODE_EUC:
- str_cat(str, "e", 1);
+ rb_str_cat(str, "e", 1);
break;
case KCODE_SJIS:
- str_cat(str, "s", 1);
+ rb_str_cat(str, "s", 1);
+ break;
+ case KCODE_UTF8:
+ rb_str_cat(str, "u", 1);
break;
}
}
@@ -238,47 +264,47 @@ reg_desc(s, len, re)
}
static VALUE
-reg_source(re)
+rb_reg_source(re)
VALUE re;
{
- VALUE str = str_new(0,0);
- reg_expr_str(str, RREGEXP(re)->str,RREGEXP(re)->len,re);
+ VALUE str = rb_str_new(0,0);
+ rb_reg_expr_str(str, RREGEXP(re)->str,RREGEXP(re)->len);
return str;
}
static VALUE
-reg_inspect(re)
+rb_reg_inspect(re)
VALUE re;
{
- return reg_desc(RREGEXP(re)->str, RREGEXP(re)->len, re);
+ return rb_reg_desc(RREGEXP(re)->str, RREGEXP(re)->len, re);
}
static void
-reg_raise(s, len, err, re)
+rb_reg_raise(s, len, err, re)
char *s;
int len;
char *err;
VALUE re;
{
- VALUE desc = reg_desc(s, len, re);
+ VALUE desc = rb_reg_desc(s, len, re);
- if (rb_in_eval)
- Raise(eRegxpError, "%s: %s", err, RSTRING(desc)->ptr);
+ if (ruby_in_compile)
+ rb_compile_error("%s: %s", err, RSTRING(desc)->ptr);
else
- Error("%s: %s", err, RSTRING(desc)->ptr);
+ rb_raise(rb_eRegxpError, "%s: %s", err, RSTRING(desc)->ptr);
}
static VALUE
-reg_casefold_p(re)
+rb_reg_casefold_p(re)
VALUE re;
{
- if (FL_TEST(re, REG_IGNORECASE)) return TRUE;
- return FALSE;
+ if (FL_TEST(re, REG_IGNORECASE)) return Qtrue;
+ return Qfalse;
}
static VALUE
-reg_kcode_method(re)
+rb_reg_kcode_method(re)
VALUE re;
{
char *kcode = "$KCODE";
@@ -291,18 +317,20 @@ reg_kcode_method(re)
kcode = "euc"; break;
case KCODE_SJIS:
kcode = "sjis"; break;
+ case KCODE_UTF8:
+ kcode = "utf8"; break;
default:
break;
}
}
- return str_new2(kcode);
+ return rb_str_new2(kcode);
}
static Regexp*
make_regexp(s, len, flag)
char *s;
- int len, flag;
+ size_t len, flag;
{
Regexp *rp;
char *err;
@@ -320,27 +348,26 @@ make_regexp(s, len, flag)
rp->allocated = 16;
rp->fastmap = ALLOC_N(char, 256);
if (flag) {
- rp->translate = casetable;
+ rp->options = flag;
}
- err = re_compile_pattern(s, (size_t)len, rp);
- kcode_reset_option();
+ err = re_compile_pattern(s, len, rp);
if (err != NULL) {
- reg_raise(s, len, err, 0);
+ rb_reg_raise(s, len, err, 0);
}
return rp;
}
-extern VALUE cData;
-static VALUE cMatch;
+static VALUE rb_cMatch;
static VALUE
match_alloc()
{
NEWOBJ(match, struct RMatch);
- OBJSETUP(match, cMatch, T_MATCH);
+ OBJSETUP(match, rb_cMatch, T_MATCH);
match->str = 0;
+ match->regs = 0;
match->regs = ALLOC(struct re_registers);
MEMZERO(match->regs, struct re_registers, 1);
@@ -351,88 +378,91 @@ static VALUE
match_clone(orig)
VALUE orig;
{
- struct re_registers *rr;
-
NEWOBJ(match, struct RMatch);
- OBJSETUP(match, cMatch, T_MATCH);
+ OBJSETUP(match, rb_cMatch, T_MATCH);
match->str = RMATCH(orig)->str;
+ match->regs = 0;
match->regs = ALLOC(struct re_registers);
match->regs->allocated = 0;
re_copy_registers(match->regs, RMATCH(orig)->regs);
+ CLONESETUP(match, orig);
return (VALUE)match;
}
-VALUE ignorecase;
+int ruby_ignorecase;
+static int may_need_recompile;
static VALUE matchcache;
-void
-reg_prepare_re(reg)
+static void
+rb_reg_prepare_re(reg)
VALUE reg;
{
- int result;
- int casefold = RTEST(ignorecase);
int need_recompile = 0;
- /* case-flag set for the object */
- if (FL_TEST(reg, REG_IGNORECASE)) {
- casefold = TRUE;
- }
- if (casefold) {
- if (RREGEXP(reg)->ptr->translate != casetable) {
- RREGEXP(reg)->ptr->translate = casetable;
- RREGEXP(reg)->ptr->fastmap_accurate = 0;
+ /* case-flag not set for the object */
+ if (!FL_TEST(reg, REG_IGNORECASE)) {
+ int state = FL_TEST(reg, REG_CASESTATE);
+
+ if ((ruby_ignorecase || state) && !(ruby_ignorecase && state)) {
+ RBASIC(reg)->flags ^= REG_CASESTATE;
need_recompile = 1;
}
}
- else if (RREGEXP(reg)->ptr->translate) {
- RREGEXP(reg)->ptr->translate = NULL;
- RREGEXP(reg)->ptr->fastmap_accurate = 0;
- need_recompile = 1;
- }
- if (FL_TEST(reg, KCODE_FIXED)) {
- kcode_set_option(reg);
- }
- else if ((RBASIC(reg)->flags & KCODE_MASK) != reg_kcode) {
+ if (!FL_TEST(reg, KCODE_FIXED) &&
+ (RBASIC(reg)->flags & KCODE_MASK) != reg_kcode) {
need_recompile = 1;
- RBASIC(reg)->flags = RBASIC(reg)->flags & ~KCODE_MASK;
+ RBASIC(reg)->flags &= ~KCODE_MASK;
RBASIC(reg)->flags |= reg_kcode;
}
if (need_recompile) {
char *err;
+ if (FL_TEST(reg, KCODE_FIXED))
+ kcode_set_option(reg);
+ RREGEXP(reg)->ptr->fastmap_accurate = 0;
err = re_compile_pattern(RREGEXP(reg)->str, RREGEXP(reg)->len, RREGEXP(reg)->ptr);
if (err != NULL) {
- kcode_reset_option();
- reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len, err, reg);
+ rb_reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len, err, reg);
}
}
}
int
-reg_search(reg, str, start, regs)
+rb_reg_search(reg, str, start, reverse)
VALUE reg, str;
- int start;
- struct re_registers *regs;
+ int start, reverse;
{
int result;
- int casefold = RTEST(ignorecase);
- VALUE match = 0;
- struct re_registers *regs0 = 0;
- int need_recompile = 0;
+ VALUE match;
+ struct re_registers *regs = 0;
+ int range;
if (start > RSTRING(str)->len) return -1;
- reg_prepare_re(reg);
+ if (may_need_recompile)
+ rb_reg_prepare_re(reg);
+
+ if (FL_TEST(reg, KCODE_FIXED))
+ kcode_set_option(reg);
+ else if (reg_kcode != curr_kcode)
+ kcode_reset_option();
- if (regs == (struct re_registers*)-1) {
- regs = 0;
+#ifdef USE_THREAD
+ if (rb_thread_scope_shared_p()) {
+ match = Qnil;
}
else {
+ match = rb_backref_get();
+ }
+#else
+ match = rb_backref_get();
+#endif
+ if (NIL_P(match)) {
if (matchcache) {
match = matchcache;
matchcache = 0;
@@ -440,45 +470,49 @@ reg_search(reg, str, start, regs)
else {
match = match_alloc();
}
- regs0 = RMATCH(match)->regs;
}
+ regs = RMATCH(match)->regs;
+ if (reverse) {
+ range = -start;
+ }
+ else {
+ range = RSTRING(str)->len - start;
+ }
result = re_search(RREGEXP(reg)->ptr,RSTRING(str)->ptr,RSTRING(str)->len,
- start,RSTRING(str)->len-start,regs0);
- kcode_reset_option();
+ start, range, regs);
- if (start == -2) {
- reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len,
+ if (result == -2) {
+ rb_reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len,
"Stack overfow in regexp matcher", reg);
}
if (result < 0) {
matchcache = match;
- backref_set(Qnil);
+ rb_backref_set(Qnil);
}
- else if (match) {
- RMATCH(match)->str = str_new4(str);
- backref_set(match);
+ else {
+ RMATCH(match)->str = rb_str_new4(str);
+ rb_backref_set(match);
}
- if (regs && regs0) re_copy_registers(regs, regs0);
return result;
}
VALUE
-reg_nth_defined(nth, match)
+rb_reg_nth_defined(nth, match)
int nth;
VALUE match;
{
if (NIL_P(match)) return Qnil;
if (nth >= RMATCH(match)->regs->num_regs) {
- return FALSE;
+ return Qfalse;
}
- if (RMATCH(match)->BEG(nth) == -1) return FALSE;
- return TRUE;
+ if (RMATCH(match)->BEG(nth) == -1) return Qfalse;
+ return Qtrue;
}
VALUE
-reg_nth_match(nth, match)
+rb_reg_nth_match(nth, match)
int nth;
VALUE match;
{
@@ -492,37 +526,37 @@ reg_nth_match(nth, match)
if (start == -1) return Qnil;
end = RMATCH(match)->END(nth);
len = end - start;
- return str_new(RSTRING(RMATCH(match)->str)->ptr + start, len);
+ return rb_str_new(RSTRING(RMATCH(match)->str)->ptr + start, len);
}
VALUE
-reg_last_match(match)
+rb_reg_last_match(match)
VALUE match;
{
- return reg_nth_match(0, match);
+ return rb_reg_nth_match(0, match);
}
VALUE
-reg_match_pre(match)
+rb_reg_match_pre(match)
VALUE match;
{
if (NIL_P(match)) return Qnil;
if (RMATCH(match)->BEG(0) == -1) return Qnil;
- return str_new(RSTRING(RMATCH(match)->str)->ptr, RMATCH(match)->BEG(0));
+ return rb_str_new(RSTRING(RMATCH(match)->str)->ptr, RMATCH(match)->BEG(0));
}
VALUE
-reg_match_post(match)
+rb_reg_match_post(match)
VALUE match;
{
if (NIL_P(match)) return Qnil;
if (RMATCH(match)->BEG(0) == -1) return Qnil;
- return str_new(RSTRING(RMATCH(match)->str)->ptr+RMATCH(match)->END(0),
+ return rb_str_new(RSTRING(RMATCH(match)->str)->ptr+RMATCH(match)->END(0),
RSTRING(RMATCH(match)->str)->len-RMATCH(match)->END(0));
}
VALUE
-reg_match_last(match)
+rb_reg_match_last(match)
VALUE match;
{
int i;
@@ -533,31 +567,31 @@ reg_match_last(match)
for (i=RMATCH(match)->regs->num_regs-1; RMATCH(match)->BEG(i) == -1 && i > 0; i--)
;
if (i == 0) return Qnil;
- return reg_nth_match(i, match);
+ return rb_reg_nth_match(i, match);
}
static VALUE
last_match_getter()
{
- return reg_last_match(backref_get());
+ return rb_reg_last_match(rb_backref_get());
}
static VALUE
prematch_getter()
{
- return reg_match_pre(backref_get());
+ return rb_reg_match_pre(rb_backref_get());
}
static VALUE
postmatch_getter()
{
- return reg_match_post(backref_get());
+ return rb_reg_match_post(rb_backref_get());
}
static VALUE
last_paren_match_getter()
{
- return reg_match_last(backref_get());
+ return rb_reg_match_last(rb_backref_get());
}
static VALUE
@@ -565,13 +599,13 @@ match_to_a(match)
VALUE match;
{
struct re_registers *regs = RMATCH(match)->regs;
- VALUE ary = ary_new2(regs->num_regs);
+ VALUE ary = rb_ary_new2(regs->num_regs);
char *ptr = RSTRING(RMATCH(match)->str)->ptr;
int i;
for (i=0; i<regs->num_regs; i++) {
- if (regs->beg[0] == -1) ary_push(ary, Qnil);
- else ary_push(ary, str_new(ptr+regs->beg[i],
+ if (regs->beg[i] == -1) rb_ary_push(ary, Qnil);
+ else rb_ary_push(ary, rb_str_new(ptr+regs->beg[i],
regs->end[i]-regs->beg[i]));
}
return ary;
@@ -591,7 +625,7 @@ match_aref(argc, argv, match)
rb_scan_args(argc, argv, "11", &idx, &rest);
if (!NIL_P(rest) || !FIXNUM_P(idx) || FIX2INT(idx) < 0) {
- return ary_aref(argc, argv, match_to_a(match));
+ return rb_ary_aref(argc, argv, match_to_a(match));
}
regs = RMATCH(match)->regs;
@@ -600,100 +634,111 @@ match_aref(argc, argv, match)
if (i>=regs->num_regs) return Qnil;
ptr = RSTRING(RMATCH(match)->str)->ptr;
- return str_new(ptr+regs->beg[i], regs->end[i]-regs->beg[i]);
+ return rb_str_new(ptr+regs->beg[i], regs->end[i]-regs->beg[i]);
}
static VALUE
match_to_s(match)
VALUE match;
{
- VALUE str = reg_last_match(match);
+ VALUE str = rb_reg_last_match(match);
- if (NIL_P(str)) return str_new(0,0);
+ if (NIL_P(str)) return rb_str_new(0,0);
return str;
}
-void
-reg_free(rp)
-Regexp *rp;
-{
- free(rp->buffer);
- free(rp->fastmap);
- free(rp);
-}
-
-VALUE cRegexp;
+VALUE rb_cRegexp;
static VALUE
-reg_new_1(class, s, len, flag)
- VALUE class;
+rb_reg_new_1(klass, s, len, options)
+ VALUE klass;
char *s;
- int len;
- int flag; /* CASEFOLD = 0x1 */
- /* CODE_NONE = 0x2 */
- /* CODE_EUC = 0x4 */
- /* CODE_SJIS = 0x6 */
+ size_t len;
+ int options; /* CASEFOLD = 1 */
+ /* EXTENDED = 2 */
+ /* CODE_NONE = 4 */
+ /* CODE_EUC = 8 */
+ /* CODE_SJIS = 12 */
+ /* CODE_UTF8 = 16 */
{
NEWOBJ(re, struct RRegexp);
- OBJSETUP(re, class, T_REGEXP);
+ OBJSETUP(re, klass, T_REGEXP);
+ re->ptr = 0;
+ re->str = 0;
- if (flag & 0x1) {
+ if (options & RE_OPTION_IGNORECASE) {
FL_SET(re, REG_IGNORECASE);
}
- switch (flag & ~0x1) {
+ switch (options & ~0x3) {
case 0:
default:
FL_SET(re, reg_kcode);
break;
- case 2:
+ case 4:
kcode_none(re);
break;
- case 4:
+ case 8:
kcode_euc(re);
break;
- case 6:
+ case 12:
kcode_sjis(re);
break;
+ case 16:
+ kcode_utf8(re);
+ break;
}
- kcode_set_option(re);
- re->ptr = make_regexp(s, len, flag & 0x1);
+ if (options & ~0x3) {
+ kcode_set_option((VALUE)re);
+ }
+ if (ruby_ignorecase) {
+ options |= RE_OPTION_IGNORECASE;
+ FL_SET(re, REG_CASESTATE);
+ }
+ re->ptr = make_regexp(s, len, options & 0x3);
re->str = ALLOC_N(char, len+1);
memcpy(re->str, s, len);
re->str[len] = '\0';
re->len = len;
+ if (options & ~0x3) {
+ kcode_reset_option();
+ }
+ rb_obj_call_init((VALUE)re);
return (VALUE)re;
}
VALUE
-reg_new(s, len, flag)
+rb_reg_new(s, len, options)
char *s;
- int len, flag;
+ size_t len;
+ int options;
{
- return reg_new_1(cRegexp, s, len, flag);
+ return rb_reg_new_1(rb_cRegexp, s, len, options);
}
-static int ign_cache;
+static int case_cache;
+static int kcode_cache;
static VALUE reg_cache;
VALUE
-reg_regcomp(str)
+rb_reg_regcomp(str)
VALUE str;
{
- int ignc = RTEST(ignorecase);
-
if (reg_cache && RREGEXP(reg_cache)->len == RSTRING(str)->len
- && ign_cache == ignc
+ && case_cache == ruby_ignorecase
+ && kcode_cache == reg_kcode
&& memcmp(RREGEXP(reg_cache)->str, RSTRING(str)->ptr, RSTRING(str)->len) == 0)
return reg_cache;
- ign_cache = ignc;
- return reg_cache = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, ignc);
+ case_cache = ruby_ignorecase;
+ kcode_cache = reg_kcode;
+ return reg_cache = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ ruby_ignorecase);
}
static int
-reg_cur_kcode(re)
+rb_reg_cur_kcode(re)
VALUE re;
{
if (FL_TEST(re, KCODE_FIXED)) {
@@ -703,57 +748,58 @@ reg_cur_kcode(re)
}
static VALUE
-reg_equal(re1, re2)
+rb_reg_equal(re1, re2)
VALUE re1, re2;
{
int min;
- if (re1 == re2) return TRUE;
- if (TYPE(re2) != T_REGEXP) return FALSE;
- if (RREGEXP(re1)->len != RREGEXP(re2)->len) return FALSE;
+ if (re1 == re2) return Qtrue;
+ if (TYPE(re2) != T_REGEXP) return Qfalse;
+ if (RREGEXP(re1)->len != RREGEXP(re2)->len) return Qfalse;
min = RREGEXP(re1)->len;
if (min > RREGEXP(re2)->len) min = RREGEXP(re2)->len;
if (memcmp(RREGEXP(re1)->str, RREGEXP(re2)->str, min) == 0 &&
- reg_cur_kcode(re1) == reg_cur_kcode(re2) &&
+ rb_reg_cur_kcode(re1) == rb_reg_cur_kcode(re2) &&
!(FL_TEST(re1,REG_IGNORECASE) ^ FL_TEST(re2,REG_IGNORECASE))) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
VALUE
-reg_match(re, str)
+rb_reg_match(re, str)
VALUE re, str;
{
int start;
- if (TYPE(str) != T_STRING) return FALSE;
- start = reg_search(re, str, 0, 0);
+ if (NIL_P(str)) return Qnil;
+ str = rb_str_to_str(str);
+ start = rb_reg_search(re, str, 0, 0);
if (start < 0) {
- return FALSE;
+ return Qnil;
}
return INT2FIX(start);
}
VALUE
-reg_match2(re)
+rb_reg_match2(re)
VALUE re;
{
int start;
- VALUE line = lastline_get();
+ VALUE line = rb_lastline_get();
if (TYPE(line) != T_STRING)
- return FALSE;
+ return Qnil;
- start = reg_search(re, line, 0, 0);
+ start = rb_reg_search(re, line, 0, 0);
if (start < 0) {
- return FALSE;
+ return Qnil;
}
return INT2FIX(start);
}
static VALUE
-reg_s_new(argc, argv, self)
+rb_reg_s_new(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
@@ -762,22 +808,23 @@ reg_s_new(argc, argv, self)
int flag = 0;
if (argc == 0 || argc > 3) {
- ArgError("wrong # of argument");
+ rb_raise(rb_eArgError, "wrong # of argument");
}
if (argc >= 2 && RTEST(argv[1])) {
- flag = 1;
+ flag = RE_OPTION_IGNORECASE;
}
if (argc == 3) {
- Check_Type(argv[2], T_STRING);
- switch (RSTRING(argv[2])->ptr[0]) {
+ char *kcode = STR2CSTR(argv[2]);
+
+ switch (kcode[0]) {
case 'n': case 'N':
- flag |= 2;
+ flag |= 4;
break;
case 'e': case 'E':
- flag |= 4;
+ flag |= 8;
break;
case 's': case 'S':
- flag |= 6;
+ flag |= 12;
break;
default:
break;
@@ -785,37 +832,37 @@ reg_s_new(argc, argv, self)
}
src = argv[0];
- switch (TYPE(src)) {
- case T_STRING:
- return reg_new_1(self, RSTRING(src)->ptr, RSTRING(src)->len, flag);
- break;
-
- case T_REGEXP:
- return reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, flag);
- break;
-
- default:
- Check_Type(src, T_STRING);
+ if (TYPE(src) == T_REGEXP) {
+ return rb_reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, flag);
}
+ else {
+ char *p;
+ size_t len;
- return Qnil;
+ p = str2cstr(src, &len);
+ return rb_reg_new_1(self, p, len, flag);
+ }
}
static VALUE
-reg_s_quote(re, str)
+rb_reg_s_quote(re, str)
VALUE re, str;
{
char *s, *send, *t;
char *tmp;
+ int len;
- Check_Type(str, T_STRING);
-
- tmp = ALLOCA_N(char, RSTRING(str)->len*2);
-
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
+ s = str2cstr(str, &len);
+ send = s + len;
+ tmp = ALLOCA_N(char, len*2);
t = tmp;
for (; s != send; s++) {
+ if (ismbchar(*s)) {
+ *t++ = *s++;
+ *t++ = *s;
+ continue;
+ }
if (*s == '[' || *s == ']'
|| *s == '{' || *s == '}'
|| *s == '(' || *s == ')'
@@ -828,22 +875,36 @@ reg_s_quote(re, str)
*t++ = *s;
}
- return str_new(tmp, t - tmp);
+ return rb_str_new(tmp, t - tmp);
+}
+
+int
+rb_kcode()
+{
+ switch (reg_kcode) {
+ case KCODE_EUC:
+ return MBCTYPE_EUC;
+ case KCODE_SJIS:
+ return MBCTYPE_SJIS;
+ case KCODE_NONE:
+ return MBCTYPE_ASCII;
+ }
+ rb_bug("wrong reg_kcode value (0x%x)", reg_kcode);
}
static int
-reg_get_kcode(re)
+rb_reg_get_kcode(re)
VALUE re;
{
int kcode = 0;
switch (RBASIC(re)->flags & KCODE_MASK) {
case KCODE_NONE:
- kcode |= 2; break;
- case KCODE_EUC:
kcode |= 4; break;
+ case KCODE_EUC:
+ kcode |= 8; break;
case KCODE_SJIS:
- kcode |= 6; break;
+ kcode |= 12; break;
default:
break;
}
@@ -851,25 +912,38 @@ reg_get_kcode(re)
return kcode;
}
-static VALUE
-reg_clone(re)
+int
+rb_reg_options(re)
VALUE re;
{
- int flag = FL_TEST(re, REG_IGNORECASE)?1:0;
+ int options = 0;
+ if (FL_TEST(re, REG_IGNORECASE))
+ options |= RE_OPTION_IGNORECASE;
if (FL_TEST(re, KCODE_FIXED)) {
- flag |= reg_get_kcode(re);
+ options |= rb_reg_get_kcode(re);
}
- return reg_new_1(CLASS_OF(re), RREGEXP(re)->str, RREGEXP(re)->len, flag);
+ return options;
+}
+
+static VALUE
+rb_reg_clone(orig)
+ VALUE orig;
+{
+ VALUE reg;
+
+ reg = rb_reg_new_1(CLASS_OF(orig), RREGEXP(orig)->str, RREGEXP(orig)->len,
+ rb_reg_options(orig));
+ CLONESETUP(reg, orig);
+ return reg;
}
VALUE
-reg_regsub(str, src, regs)
+rb_reg_regsub(str, src, regs)
VALUE str, src;
struct re_registers *regs;
{
VALUE val = 0;
- VALUE tmp;
char *p, *s, *e, c;
int no;
@@ -880,10 +954,14 @@ reg_regsub(str, src, regs)
char *ss = s;
c = *s++;
- if (c != '\\') continue;
+ if (ismbchar(c)) {
+ s++;
+ continue;
+ }
+ if (c != '\\' || s == e) continue;
- if (!val) val = str_new(p, ss-p);
- else str_cat(val, p, ss-p);
+ if (!val) val = rb_str_new(p, ss-p);
+ else rb_str_cat(val, p, ss-p);
c = *s++;
p = s;
@@ -897,11 +975,11 @@ reg_regsub(str, src, regs)
break;
case '`':
- str_cat(val, RSTRING(src)->ptr, BEG(0));
+ rb_str_cat(val, RSTRING(src)->ptr, BEG(0));
continue;
case '\'':
- str_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0));
+ rb_str_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0));
continue;
case '+':
@@ -911,117 +989,110 @@ reg_regsub(str, src, regs)
break;
case '\\':
- str_cat(val, s-1, 1);
+ rb_str_cat(val, s-1, 1);
continue;
default:
- str_cat(val, s-2, 2);
+ rb_str_cat(val, s-2, 2);
continue;
}
if (no >= 0) {
if (BEG(no) == -1) continue;
- str_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no));
+ rb_str_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no));
}
}
if (p < e) {
- if (!val) val = str_new(p, e-p);
- else str_cat(val, p, e-p);
+ if (!val) val = rb_str_new(p, e-p);
+ else rb_str_cat(val, p, e-p);
}
- if (!val) return (VALUE)str;
+ if (!val) return str;
return val;
}
-#define IS_KCODE_FIXED(re) (FL_TEST((re), KCODE_FIXED)?1:0)
-
-static int
-reg_prepare_operation(re1, re2)
- VALUE re1, re2;
+char*
+rb_get_kcode()
{
- int flag = 0;
-
- Check_Type(re2, T_REGEXP);
- flag = IS_KCODE_FIXED(re1)+IS_KCODE_FIXED(re2)*2;
- switch (IS_KCODE_FIXED(re1)+IS_KCODE_FIXED(re2)*2) {
- case 3: /* both have fixed kcode (must match) */
- if (((RBASIC(re1)->flags^RBASIC(re2)->flags)&KCODE_MASK) != 0) {
- Raise(eRegxpError, "kanji code mismatch");
- }
- /* fall through */
- case 2: /* re2 has fixed kcode */
- flag = reg_get_kcode(re2);
- break;
- case 1: /* re1 has fixed kcode */
- flag = reg_get_kcode(re1);
- break;
- case 0: /* neither has fixed kcode */
- flag = 0;
- break;
- }
-
- if (FL_TEST(re1, REG_IGNORECASE) ^ FL_TEST(re2, REG_IGNORECASE)) {
- Raise(eRegxpError, "casefold mismatch");
+ switch (reg_kcode) {
+ case KCODE_SJIS:
+ return "SJIS";
+ case KCODE_EUC:
+ return "EUC";
+ case KCODE_UTF8:
+ return "UTF8";
+ default:
+ return "NONE";
}
- if (FL_TEST(re1, REG_IGNORECASE)) flag |= 0x1;
-
- return flag;
}
static VALUE
kcode_getter()
{
- switch (reg_kcode) {
- case KCODE_SJIS:
- return str_new2("SJIS");
- case KCODE_EUC:
- return str_new2("EUC");
- default:
- return str_new2("NONE");
- }
+ return rb_str_new2(rb_get_kcode());
}
void
rb_set_kcode(code)
char *code;
{
- re_syntax_options &= ~RE_MBCTYPE_MASK;
if (code == 0) goto set_no_conversion;
switch (code[0]) {
case 'E':
case 'e':
reg_kcode = KCODE_EUC;
- re_syntax_options |= RE_MBCTYPE_EUC;
+ re_mbcinit(MBCTYPE_EUC);
break;
case 'S':
case 's':
reg_kcode = KCODE_SJIS;
- re_syntax_options |= RE_MBCTYPE_SJIS;
+ re_mbcinit(MBCTYPE_SJIS);
+ break;
+ case 'U':
+ case 'u':
+ reg_kcode = KCODE_UTF8;
+ re_mbcinit(MBCTYPE_UTF8);
break;
default:
case 'N':
case 'n':
+ case 'A':
+ case 'a':
set_no_conversion:
reg_kcode = KCODE_NONE;
+ re_mbcinit(MBCTYPE_ASCII);
break;
}
- re_set_syntax(re_syntax_options);
}
static void
kcode_setter(val)
struct RString *val;
{
- Check_Type(val, T_STRING);
- rb_set_kcode(val->ptr);
+ may_need_recompile = 1;
+ rb_set_kcode(STR2CSTR(val));
+}
+
+static VALUE
+ignorecase_getter()
+{
+ return ruby_ignorecase?Qtrue:Qfalse;
+}
+
+static void
+ignorecase_setter(val)
+ VALUE val;
+{
+ may_need_recompile = 1;
+ ruby_ignorecase = RTEST(val);
}
static VALUE
match_getter()
{
- return backref_get();
+ return match_clone(rb_backref_get());
}
static void
@@ -1029,27 +1100,28 @@ match_setter(val)
VALUE val;
{
Check_Type(val, T_MATCH);
- backref_set(val);
+ rb_backref_set(val);
}
-VALUE any_to_s();
-
void
Init_Regexp()
{
- extern VALUE eException;
+ rb_eRegxpError = rb_define_class("RegxpError", rb_eStandardError);
- eRegxpError = rb_define_class("RegxpError", eException);
-
- re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR
- | RE_INTERVALS
- | RE_NO_BK_BRACES
- | RE_CONTEXTUAL_INVALID_OPS
- | RE_BACKSLASH_ESCAPE_IN_LISTS
-#ifdef DEFAULT_MBCTYPE
- | DEFAULT_MBCTYPE
+ re_set_casetable(casetable);
+#ifdef RUBY_USE_EUC
+ re_mbcinit(MBCTYPE_EUC);
+#else
+#ifdef RUBY_USE_SJIS
+ re_mbcinit(MBCTYPE_SJIS);
+#else
+#ifdef RUBY_USE_UTF8
+ re_mbcinit(MBCTYPE_UTF8);
+#else
+ re_mbcinit(MBCTYPE_ASCII);
+#endif
+#endif
#endif
- );
rb_define_virtual_variable("$~", match_getter, match_setter);
rb_define_virtual_variable("$&", last_match_getter, 0);
@@ -1057,31 +1129,32 @@ Init_Regexp()
rb_define_virtual_variable("$'", postmatch_getter, 0);
rb_define_virtual_variable("$+", last_paren_match_getter, 0);
- rb_define_variable("$=", &ignorecase);
+ 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);
- cRegexp = rb_define_class("Regexp", cObject);
- rb_define_singleton_method(cRegexp, "new", reg_s_new, -1);
- rb_define_singleton_method(cRegexp, "compile", reg_s_new, -1);
- rb_define_singleton_method(cRegexp, "quote", reg_s_quote, 1);
-
- rb_define_method(cRegexp, "clone", reg_clone, 0);
- rb_define_method(cRegexp, "==", reg_equal, 1);
- rb_define_method(cRegexp, "=~", reg_match, 1);
- rb_define_method(cRegexp, "===", reg_match, 1);
- rb_define_method(cRegexp, "~", reg_match2, 0);
- rb_define_method(cRegexp, "inspect", reg_inspect, 0);
- rb_define_method(cRegexp, "source", reg_source, 0);
- rb_define_method(cRegexp, "casefold?", reg_casefold_p, 0);
- rb_define_method(cRegexp, "kcode", reg_kcode_method, 0);
+ rb_cRegexp = rb_define_class("Regexp", rb_cObject);
+ rb_define_singleton_method(rb_cRegexp, "new", rb_reg_s_new, -1);
+ rb_define_singleton_method(rb_cRegexp, "compile", rb_reg_s_new, -1);
+ rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
+
+ rb_define_method(rb_cRegexp, "clone", rb_reg_clone, 0);
+ rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
+ rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
+ rb_define_method(rb_cRegexp, "===", rb_reg_match, 1);
+ rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
+ rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
+ rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
+ rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
+ rb_define_method(rb_cRegexp, "kcode", rb_reg_kcode_method, 0);
rb_global_variable(&reg_cache);
rb_global_variable(&matchcache);
- cMatch = rb_define_class("MatchingData", cData);
- rb_define_method(cMatch, "to_a", match_to_a, 0);
- rb_define_method(cMatch, "[]", match_aref, -1);
- rb_define_method(cMatch, "to_s", match_to_s, 0);
- rb_define_method(cMatch, "inspect", any_to_s, 0);
+ rb_cMatch = rb_define_class("MatchingData", rb_cData);
+ rb_define_method(rb_cMatch, "clone", match_clone, 0);
+ rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
+ rb_define_method(rb_cMatch, "[]", match_aref, -1);
+ rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
+ rb_define_method(rb_cMatch, "inspect", rb_any_to_s, 0);
}
diff --git a/re.h b/re.h
index 8769d6ef39..4d7220b5e6 100644
--- a/re.h
+++ b/re.h
@@ -3,11 +3,10 @@
re.h -
$Author$
- $Revision$
$Date$
created at: Thu Sep 30 14:18:32 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -29,9 +28,12 @@ struct RMatch {
#define RMATCH(obj) (R_CAST(RMatch)(obj))
-int str_cicmp _((VALUE, VALUE));
-VALUE reg_regcomp _((VALUE));
-int reg_search _((VALUE, VALUE, int, struct re_registers *));
-VALUE reg_regsub _((VALUE, VALUE, struct re_registers *));
-void reg_free _((Regexp *));
+int rb_str_cicmp _((VALUE, VALUE));
+VALUE rb_reg_regcomp _((VALUE));
+int rb_reg_search _((VALUE, VALUE, int, int));
+VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *));
+
+int rb_kcode _((void));
+
+extern int ruby_ignorecase;
#endif
diff --git a/regex.h b/regex.h
index 91442a8b2b..f61b980648 100644
--- a/regex.h
+++ b/regex.h
@@ -22,6 +22,8 @@
#ifndef __REGEXP_LIBRARY
#define __REGEXP_LIBRARY
+#include <stddef.h>
+
/* Define number of parens for which we record the beginnings and ends.
This affects how much space the `struct re_registers' type takes up. */
#ifndef RE_NREGS
@@ -38,174 +40,52 @@
#endif
-/* This defines the various regexp syntaxes. */
-extern long re_syntax_options;
-
-
-/* The following bits are used in the re_syntax_options variable to choose among
- alternative regexp syntaxes. */
-
-/* If this bit is set, plain parentheses serve as grouping, and backslash
- parentheses are needed for literal searching.
- If not set, backslash-parentheses are grouping, and plain parentheses
- are for literal searching. */
-#define RE_NO_BK_PARENS 1L
-
-/* If this bit is set, plain | serves as the `or'-operator, and \| is a
- literal.
- If not set, \| serves as the `or'-operator, and | is a literal. */
-#define RE_NO_BK_VBAR (1L << 1)
-
-/* If this bit is set, | binds tighter than ^ or $.
- If not set, the contrary. */
-#define RE_TIGHT_VBAR (1L << 3)
-
-/* If this bit is set, then treat newline as an OR operator.
- If not set, treat it as a normal character. */
-#define RE_NEWLINE_OR (1L << 4)
-
-/* If this bit is set, then special characters may act as normal
- characters in some contexts. Specifically, this applies to:
- ^ -- only special at the beginning, or after ( or |;
- $ -- only special at the end, or before ) or |;
- *, +, ? -- only special when not after the beginning, (, or |.
- If this bit is not set, special characters (such as *, ^, and $)
- always have their special meaning regardless of the surrounding
- context. */
-#define RE_CONTEXT_INDEP_OPS (1L << 5)
-
-/* If this bit is not set, then \ before anything inside [ and ] is taken as
- a real \.
- If set, then such a \ escapes the following character. This is a
- special case for awk. */
-#define RE_AWK_CLASS_HACK (1L << 6)
-
-/* If this bit is set, then \{ and \} or { and } serve as interval operators.
- If not set, then \{ and \} and { and } are treated as literals. */
-#define RE_INTERVALS (1L << 7)
-
-/* If this bit is not set, then \{ and \} serve as interval operators and
- { and } are literals.
- If set, then { and } serve as interval operators and \{ and \} are
- literals. */
-#define RE_NO_BK_CURLY_BRACES (1L << 8)
-#define RE_NO_BK_BRACES RE_NO_BK_CURLY_BRACES
-
/* If this bit is set, then character classes are supported; they are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (1L << 9)
-/* If this bit is set, then the dot re doesn't match a null byte.
- If not set, it does. */
-#define RE_DOT_NOT_NULL (1L << 10)
-
-/* If this bit is set, then [^...] doesn't match a newline.
- If not set, it does. */
-#define RE_HAT_NOT_NEWLINE (1L << 11)
-
-/* If this bit is set, back references are recognized.
- If not set, they aren't. */
-#define RE_NO_BK_REFS (1L << 12)
-
-/* If this bit is set, back references must refer to a preceding
- subexpression. If not set, a back reference to a nonexistent
- subexpression is treated as literal characters. */
-#define RE_NO_EMPTY_BK_REF (1L << 13)
-
-/* If this bit is set, bracket expressions can't be empty.
- If it is set, they can be empty. */
-#define RE_NO_EMPTY_BRACKETS (1L << 14)
-
-/* If this bit is set, then *, +, ? and { cannot be first in an re or
- immediately after a |, or a (. Furthermore, a | cannot be first or
- last in an re, or immediately follow another | or a (. Also, a ^
- cannot appear in a nonleading position and a $ cannot appear in a
- nontrailing position (outside of bracket expressions, that is). */
-#define RE_CONTEXTUAL_INVALID_OPS (1L << 15)
-
-/* If this bit is set, then +, ? and | aren't recognized as operators.
- If it's not, they are. */
-#define RE_LIMITED_OPS (1L << 16)
-
-/* If this bit is set, then an ending range point has to collate higher
- or equal to the starting range point.
- If it's not set, then when the ending range point collates higher
- than the starting range point, the range is just considered empty. */
-#define RE_NO_EMPTY_RANGES (1L << 17)
-
-/* If this bit is set, then a hyphen (-) can't be an ending range point.
- If it isn't, then it can. */
-#define RE_NO_HYPHEN_RANGE_END (1L << 18)
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
- If set, then such a \ quotes the following character. */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS (1L << 19)
-
-/* Define combinations of bits for the standard possibilities. */
-#define RE_SYNTAX_POSIX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
- | RE_CONTEXT_INDEP_OPS)
-#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_AWK_CLASS_HACK)
-#define RE_SYNTAX_EGREP (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
- | RE_CONTEXT_INDEP_OPS | RE_NEWLINE_OR)
-#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
-#define RE_SYNTAX_EMACS 0
-#define RE_SYNTAX_POSIX_BASIC (RE_INTERVALS | RE_BK_PLUS_QM \
- | RE_CHAR_CLASSES | RE_DOT_NOT_NULL \
- | RE_HAT_NOT_NEWLINE | RE_NO_EMPTY_BK_REF \
- | RE_NO_EMPTY_BRACKETS | RE_LIMITED_OPS \
- | RE_NO_EMPTY_RANGES | RE_NO_HYPHEN_RANGE_END)
-
-#define RE_SYNTAX_POSIX_EXTENDED (RE_INTERVALS | RE_NO_BK_CURLY_BRACES \
- | RE_NO_BK_VBAR | RE_NO_BK_PARENS \
- | RE_HAT_NOT_NEWLINE | RE_CHAR_CLASSES \
- | RE_NO_EMPTY_BRACKETS | RE_CONTEXTUAL_INVALID_OPS \
- | RE_NO_BK_REFS | RE_NO_EMPTY_RANGES \
- | RE_NO_HYPHEN_RANGE_END)
+#define RE_OPTION_EXTENDED (1L<<0)
+#define RE_OPTION_IGNORECASE (1L<<1)
+#define RE_MAY_IGNORECASE (1L<<2)
+#define RE_OPTIMIZE_ANCHOR (1L<<4)
+#define RE_OPTIMIZE_EXACTN (1L<<5)
+#define RE_OPTIMIZE_NO_BM (1L<<6)
/* For multi-byte char support */
-#define RE_MBCTYPE_EUC (1L << 20)
-#define RE_MBCTYPE_SJIS (1L << 21)
-#define RE_MBCTYPE_MASK (RE_MBCTYPE_EUC | RE_MBCTYPE_SJIS)
+#define MBCTYPE_ASCII 0
+#define MBCTYPE_EUC 1
+#define MBCTYPE_SJIS 2
+#define MBCTYPE_UTF8 3
-#ifdef EUC
-#define DEFAULT_MBCTYPE RE_MBCTYPE_EUC
-#else
-#ifdef SJIS
-#define DEFAULT_MBCTYPE RE_MBCTYPE_SJIS
+#ifdef __STDC__
+extern const unsigned char *re_mbctab;
+void re_mbcinit (int);
#else
-#define DEFAULT_MBCTYPE 0
-#endif
+extern unsigned char *re_mbctab;
+void re_mbcinit ();
#endif
#undef ismbchar
-#define ismbchar(c) \
- (re_syntax_options & RE_MBCTYPE_EUC \
- ? ((unsigned char) (c) >= 0x80) \
- : (re_syntax_options & RE_MBCTYPE_SJIS \
- ? (( 0x80 <= (unsigned char) (c) \
- && (unsigned char) (c) <= 0x9f) \
- || (0xe0 <= (unsigned char) (c))) \
- : 0))
+#define ismbchar(c) re_mbctab[(unsigned char)(c)]
+#define mbclen(c) (re_mbctab[(unsigned char)(c)]+1)
/* This data structure is used to represent a compiled pattern. */
struct re_pattern_buffer
{
char *buffer; /* Space holding the compiled pattern commands. */
- long allocated; /* Size of space that `buffer' points to. */
- long used; /* Length of portion of buffer actually occupied */
+ size_t allocated; /* Size of space that `buffer' points to. */
+ size_t used; /* Length of portion of buffer actually occupied */
char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
/* re_search uses the fastmap, if there is one,
to skip over totally implausible characters. */
- char *translate; /* Translate table to apply to all characters before
- comparing, or zero for no translation.
- The translation is applied to a pattern when it is
- compiled and to data when it is matched. */
char *must; /* Pointer to exact pattern which strings should have
to be matched. */
-
+ int *must_skip; /* Pointer to exact pattern skip table for bm_search */
+ char *stclass; /* Pointer to character class list at top */
+ long options; /* Flags for options such as extended_pattern. */
long re_nsub; /* Number of subexpressions found by the compiler. */
char fastmap_accurate;
/* Set to zero when a new pattern is stored,
@@ -219,11 +99,7 @@ struct re_pattern_buffer
listed in the fastmap. */
};
-
-/* search.c (search_buffer) needs this one value. It is defined both in
- regex.c and here. */
-#define RE_EXACTN_VALUE 1
-
+typedef struct re_pattern_buffer regex_t;
/* Structure to store register contents data in.
@@ -237,12 +113,23 @@ struct re_pattern_buffer
struct re_registers
{
- unsigned allocated;
- unsigned num_regs;
+ size_t allocated;
+ size_t num_regs;
int *beg;
int *end;
};
+/* Type for byte offsets within the string. POSIX mandates this. */
+typedef size_t regoff_t;
+
+/* POSIX specification for registers. Aside from the different names than
+ `re_registers', POSIX uses an array of structures, instead of a
+ structure of arrays. */
+typedef struct
+{
+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
+} regmatch_t;
#ifdef NeXT
@@ -252,14 +139,16 @@ struct re_registers
#ifdef __STDC__
extern char *re_compile_pattern (char *, size_t, struct re_pattern_buffer *);
+void re_free_pattern (struct re_pattern_buffer *);
/* Is this really advertised? */
extern void re_compile_fastmap (struct re_pattern_buffer *);
-extern int re_search (struct re_pattern_buffer *, char*, int, int, int,
+extern int re_search (struct re_pattern_buffer *, char*, size_t, size_t, size_t,
struct re_registers *);
-extern int re_match (struct re_pattern_buffer *, char *, int, int,
+extern int re_match (struct re_pattern_buffer *, char *, size_t, size_t,
struct re_registers *);
-extern long re_set_syntax (long syntax);
+extern void re_set_casetable (char *table);
extern void re_copy_registers (struct re_registers*, struct re_registers*);
+extern void re_free_registers (struct re_registers*);
#ifndef RUBY
/* 4.2 bsd compatibility. */
@@ -270,19 +159,15 @@ extern int re_exec (char *);
#else /* !__STDC__ */
extern char *re_compile_pattern ();
+void re_free_regexp ();
/* Is this really advertised? */
extern void re_compile_fastmap ();
extern int re_search ();
extern int re_match ();
-extern long re_set_syntax();
+extern void re_set_casetable ();
extern void re_copy_registers ();
extern void re_free_registers ();
#endif /* __STDC__ */
-
-#ifdef SYNTAX_TABLE
-extern char *re_syntax_table;
-#endif
-
#endif /* !__REGEXP_LIBRARY */
diff --git a/ruby.1 b/ruby.1
index fe1e76007a..8665ca79bb 100644
--- a/ruby.1
+++ b/ruby.1
@@ -1,45 +1,8 @@
-.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@ruby.club.co.jp>.
-.\"
-.\"This source is distributed under the conditions blow:
-.\"
-.\" 1. You may make and give away verbatim copies of the source form of
-.\" the software without restriction, provided that you do not modify
-.\" the original distribution files.
-.\"
-.\" If you want to distribute the modified version in any way, contact
-.\" the author.
-.\"
-.\" 2. You may distribute the software in object code or executable
-.\" form, provided that you distribute it with instructions on where
-.\" to get the software.
-.\"
-.\" 3. You may modify the software in any way, provided that you do not
-.\" distribute the modified version.
-.\"
-.\" 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 this terms.
-.\" They are gc.c(partly)$B!$(Butils.c(partly), regex.[ch]$B!$(Bfnmatch.[ch]$B!$(B
-.\" glob.c, st.[ch] and somme files under the ./missing directory. See
-.\" each files for the copying condition.
-.\"
-.\" 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE.
-.\"
-.\" $Id$
-.\"
+.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.co.jp>.
.na
-.TH RUBY 1 "ruby 1.0" "19/Sep/97" "Ruby Programmers Reference Guide"
+.TH RUBY 1 "ruby 1.3" "18/Jan/99" "Ruby Programmers Reference Guide"
.SH NAME
-ruby - Interpreted scripting language
+ruby - Interpreted object-oriented scripting language
.SH SYNOPSIS
.B ruby \c
[ \c
@@ -94,99 +57,96 @@ ruby - Interpreted scripting language
] [ programfile ] [ argument ] ...
.SH PREFACE
-Ruby is the 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,
+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 the
+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 DESCRIPTION
Ruby's features are as follows:
.TP
.B "\(bu Interpretive"
-Ruby is the interpreted language, so you don't have to
-recompile to execute the program written in ruby.
+Ruby is an interpreted language, so you don't have to recompile
+programs written in Ruby to execute them.
.TP
.B "\(bu 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 weaker
-compile time check.
-.TP
+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.
+.TP
.B "\(bu No declaration needed"
-You can use variables in your ruby programs without any
-declarations. Variable name itself denotes its scope (local,
-global, instance, etc.)
+You can use variables in your Ruby programs without any declarations.
+Variable names denote their scope, local, global, instance, etc.
.TP
.B "\(bu Simple syntax"
-Ruby has simple syntax influenced slightly from Eiffel.
+Ruby has a simple syntax influenced slightly from Eiffel.
.TP
.B "\(bu No user-level memory management"
Ruby has automatic memory management. Objects no longer
referenced from anywhere are automatically collected by the
-garbage collector built in the interpreter.
+garbage collector built into the interpreter.
.TP
-.B "\(bu Everything is object"
-Ruby is the pure object-oriented language from the beginning.
-Even basic data like integers are treated uniformly as objects.
+.B "\(bu 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.
.TP
.B "\(bu Class, inheritance, methods"
-Of course, as a O-O language, ruby has basic features like
-classes, inheritance, methods, etc.
+Of course, as an object-oriented language, Ruby has such basic
+features like classes, inheritance, and methods.
.TP
.B "\(bu Singleton methods"
-Ruby has the feature to define methods for certain specified
-object. For example, you can define a press-button action for
-certain GUI button 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).
+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.
.TP
.B "\(bu Mix-in by modules"
-Ruby does not have the multiple inheritance intentionally. IMO,
-It is the source of confusion. Instead, ruby has modules to
-share the implementation across the inheritance tree. It is
-often called "Mix-in."
+Ruby intentioanlly does not have the multiple inheritance as it is a
+souce of confusion. Instead, Ruby has the ability to share
+implementations acrss the inheritance tree. This is oftern called
+`Mix-in'.
.TP
.B "\(bu Iterators"
Ruby has iterators for loop abstraction.
.TP
.B "\(bu Closures"
-In ruby, you can objectify the procedure.
+In Ruby, you can objectify the procedure.
.TP
.B "\(bu Text processing and regular expression"
-Ruby has bunch of text processing features like in perl.
+Ruby has a bunch of text processing features like in Perl.
.TP
.B "\(bu Bignums"
-With bu ilt-in bignums, you can calculate factorial(400), for
-example.
+With built-in bignums, you can for example calculate factorial(400).
.TP
.B "\(bu Exception handling"
As in Java(tm).
.TP
-.B "\(bu Direct access to OS"
-Ruby can call most of system calls on UNIX boxes. It can be
-used in system programming.
+.B "\(bu Direct access to the OS"
+Ruby can use most UNIX system calls, often used in system programming.
.TP
.B "\(bu Dynamic loading"
-You can load object files into ruby interpreter on-the-fly, on
-most of UNIXes.
+On most UNIX systems, you can load object files into the Ruby
+interpreter on-the-fly.
.PP
-.SH Command line options
+.SH COMMAND LINE OPTIONS
Ruby interpreter accepts following command-line options (switches).
-Basically they are quite similar to those of Perl.
+They are quite similar to those of Perl.
.TP
.B -0digit
-specifies the input record separator ($/) as an octal number.
-If no digits given, the null character is the separator. Other
-switches may follow the digits. -00 turns ruby into paragraph
-mode. -0777 makes ruby read whole file at once as a single
-string, since there is no legal character with that value.
+pecifies the input record separator ($/) as an octal number. If no
+digit is given, the null character is taken as the separator. Other
+switches may follow the digits. -00 turns Ruby into paragraph mode. -
+0777 makes Ruby read whole file at once as a single string since there
+is no legal character with that value.
.TP
.B -a
turns on auto-split mode when used with -n or -p. In auto-split
-mode, ruby executes
+mode, Ruby executes
.nf
.ne 1
\& $F = $_.split
@@ -194,20 +154,20 @@ at beginning of each loop.
.fi
.TP
.B -c
-causes ruby to check the syntax of the script and exit without
-executing. If there is no syntax error, ruby will print "Syntax
+causes Ruby to check the syntax of the script and exit without
+executing. If there are no syntax errors, Ruby will print "Syntax
OK" to the standard output.
.TP
.B -Kc
-specifies KANJI (Japanese character) code-set.
+specifies KANJI (Japanese) code-set.
.TP
.B
-d --debug
turns on debug mode. $DEBUG will set TRUE.
.TP
.B -e script
-specifies script from command-line. if -e switch specified,
-ruby will not look for a script filename in the arguments.
+specifies script from command-line while telling Ruby to not
+search argv for script filenames.
.TP
.B -F regexp
specifies input field separator ($;).
@@ -229,16 +189,15 @@ example:
.fi
.TP
.B -I directory
-used to tell ruby where to load the library scripts. Directory
-path will be added to the load-path variable ($:').
+used to tell Ruby where to load the library scripts. Directory path
+will be added to the load-path variable ($:').
.TP
.B -l
-enables automatic line-ending processing, which means firstly
-set $\ to the value of $/, and secondly chops every line read
-using chop!.
+enables automatic line-ending processing, which means to firstly set
+$\ to the value of $/, and secondly chops every line read using chop!.
.TP
.B -n
-causes ruby to assume the following loop around your script,
+causes Ruby to assume the following loop around your script,
which makes it iterate over filename arguments somewhat like
sed -n or awk.
.nf
@@ -259,24 +218,23 @@ example:
.fi
.TP
.B -r filename
-causes ruby to load the file using [4]require. It is useful
+causes Ruby to load the file using [4]require. It is useful
with switches -n or -p.
.TP
.B -s
-enables some switch parsing for switches after script name but
-before any filename arguments (or before a --). Any switches
-found there is removed from ARGV and set the corresponding
-variable in the script.
+enables some switch parsing for switches after script name but before
+any filename arguments (or before a --). Any switches found there are
+removed from ARGV and set the corresponding variable in the script.
example:
.nf
.ne 3
\& #! /usr/local/bin/ruby -s
\& # prints "true" if invoked with `-xyz' switch.
-\& print "true\n" if $xyz
+\& print "true\en" if $xyz
.fi
.TP
.B -S
-makes ruby uses the PATH environment variable to search for
+makes Ruby use the PATH environment variable to search for
script, unless if its name begins with a slash. This is used to
emulate #! on machines that don't support it, in the following
manner:
@@ -286,44 +244,40 @@ manner:
\& # This line makes the next one a comment in ruby \\
\& exec /usr/local/bin/ruby -S $0 $*
.fi
-On some systems $0 does not always contain the full pathname,
-so you need -S switch to tell ruby to search for the script if
-necessary.
-To handle embedded spaces or such, A better construct than $*
-would be ${1+"$@"}, but it does not work if the script is being
-interpreted by csh.
+On some systems $0 does not always contain the full pathname, so you
+need -S switch to tell Ruby to search for the script if necessary. To
+handle embedded spaces or such. A better construct than $* would be
+${1+"$@"}, but it does not work if the script is being interpreted by
+csh.
.TP
.B -v --verbose
-enables verbose mode. Ruby will prints its version at the
-beginning, and set the variable `$VERBOSE' to TRUE. Some
-methods prints extra messages if this variable is TRUE. If this
-switch is given, and no other switches present, ruby quits
-after printing its version.
+enables verbose mode. Ruby will print its version at the beginning,
+and set the variable `$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.
.TP
.B --version
-prints the version of ruby executable.
+prints the version of Ruby interpreter.
.TP
.B -w
enables verbose mode without printing version message at the
-beginning. It set the variable `$VERBOSE' to TRUE.
+beginning. It set the `$VERBOSE' variable to true.
.TP
.B -x[directory]
-tells ruby that the script is embedded in a message. Leading
-garbage will be discarded until the first that starts with "#!"
-and contains string "ruby". Any meaningful switches on that
-line will applied. The end of script must be specified with
-either EOF, ^D (control-D), ^Z (control-Z), or reserved word
-__END__.If the directory name is specified, ruby will switch to
-that directory before executing script.
+tells Ruby that the script is embedded in a message. Leading garbage
+will be discarded until the first that starts with "#!" and contains
+the string, "ruby". Any meaningful switches on that line will applied.
+The end of script must be specified with either EOF, ^D (control-D),
+^Z (control-Z), or reserved word __END__.If the directory name is
+specified, Ruby will switch to that directory before executing script.
.TP
.B -X directory
-causes ruby to switch to the directory.
+causes Ruby to switch to the directory.
.TP
.B -y --yydebug
-turns on compiler debug mode. ruby will print 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 itself.
+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
.SH AUTHOR
- Ruby is designed and implemented by Yukihiro Matsumoto <matz@ruby.club.co.jp>.
+ Ruby is designed and implemented by Yukihiro Matsumoto <matz@netlab.co.jp>.
diff --git a/ruby.c b/ruby.c
index 6e748f249d..9bf28022e8 100644
--- a/ruby.c
+++ b/ruby.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Aug 10 12:47:31 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -14,102 +14,117 @@
#include <windows.h>
#endif
#include "ruby.h"
-#include "re.h"
#include "dln.h"
+#include "node.h"
#include <stdio.h>
-#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
+#include <ctype.h>
+
+#ifdef __hpux
+#include <sys/pstat.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
+#ifdef USE_CWGUSI
+#include "macruby_missing.h"
+#endif
+
#ifndef HAVE_STRING_H
-char *strchr();
-char *strrchr();
-char *strstr();
+char *strchr _((char*,char));
+char *strrchr _((char*,char));
+char *strstr _((char*,char*));
#endif
+#include "util.h"
+
+#ifndef HAVE_STDLIB_H
char *getenv();
+#endif
static int version, copyright;
-VALUE debug = FALSE;
-VALUE verbose = FALSE;
-int tainting = FALSE;
-static int sflag = FALSE;
+VALUE rb_debug = Qfalse;
+VALUE rb_verbose = Qfalse;
+int rb_tainting = Qfalse;
+static int sflag = Qfalse;
-char *inplace = FALSE;
+char *ruby_inplace_mode = Qfalse;
char *strdup();
-extern char *sourcefile;
extern int yydebug;
-extern int nerrs;
+static int xflag = Qfalse;
-static int xflag = FALSE;
-extern VALUE RS, RS_default, ORS, FS;
-
-static void load_stdin();
+static void load_stdin _((void));
static void load_file _((char *, int));
static void forbid_setid _((char *));
-static VALUE do_loop = FALSE, do_print = FALSE;
-static VALUE do_check = FALSE, do_line = FALSE;
-static VALUE do_split = FALSE;
+static VALUE do_loop = Qfalse, do_print = Qfalse;
+static VALUE do_check = Qfalse, do_line = Qfalse;
+static VALUE do_split = Qfalse;
static char *script;
static int origargc;
static char **origargv;
-extern int sourceline;
-extern char *sourcefile;
-
#ifndef RUBY_LIB
#define RUBY_LIB "/usr/local/lib/ruby"
#endif
-
-#if defined(MSDOS) || defined(NT)
-#define RUBY_LIB_SEP ';'
-#else
-#define RUBY_LIB_SEP ':'
+#ifndef RUBY_SITE_LIB
+#define RUBY_SITE_LIB "/usr/local/lib/site_ruby"
#endif
extern VALUE rb_load_path;
-VALUE Frequire();
+
+static FILE *e_fp;
+static char *e_tmpname;
static void
addpath(path)
char *path;
{
+ const char sep = RUBY_PATH_SEP[0];
+
if (path == 0) return;
- if (strchr(path, RUBY_LIB_SEP)) {
+#if defined(__CYGWIN32__)
+ {
+ char rubylib[FILENAME_MAX];
+ conv_to_posix_path(path, rubylib);
+ path = rubylib;
+ }
+#endif
+ if (strchr(path, sep)) {
char *p, *s;
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
p = path;
while (*p) {
- while (*p == RUBY_LIB_SEP) p++;
- if (s = strchr(p, RUBY_LIB_SEP)) {
- ary_push(ary, str_new(p, (int)(s-p)));
+ while (*p == sep) p++;
+ if (s = strchr(p, sep)) {
+ rb_ary_push(ary, rb_str_new(p, (int)(s-p)));
p = s + 1;
}
else {
- ary_push(ary, str_new2(p));
+ rb_ary_push(ary, rb_str_new2(p));
break;
}
}
- rb_load_path = ary_plus(ary, rb_load_path);
+ rb_load_path = rb_ary_plus(ary, rb_load_path);
}
else {
- ary_unshift(rb_load_path, str_new2(path));
+ rb_ary_unshift(rb_load_path, rb_str_new2(path));
}
}
struct req_list {
char *name;
struct req_list *next;
-} *req_list;
+} req_list_head;
+struct req_list *req_list_last = &req_list_head;
static void
add_modules(mod)
@@ -119,25 +134,28 @@ add_modules(mod)
list = ALLOC(struct req_list);
list->name = mod;
- list->next = req_list;
- req_list = list;
+ list->next = 0;
+ req_list_last->next = list;
+ req_list_last = list;
}
void
-rb_require_modules()
+ruby_require_modules()
{
- struct req_list *list = req_list;
+ struct req_list *list = req_list_head.next;
struct req_list *tmp;
- req_list = 0;
+ req_list_last = 0;
while (list) {
- f_require(Qnil, str_new2(list->name));
+ rb_f_require(Qnil, rb_str_new2(list->name));
tmp = list->next;
free(list);
list = tmp;
}
}
+extern void Init_ext _((void));
+
static void
proc_options(argcp, argvp)
int *argcp;
@@ -150,9 +168,10 @@ proc_options(argcp, argvp)
if (argc == 0) return;
- version = FALSE;
- do_search = FALSE;
+ version = Qfalse;
+ do_search = Qfalse;
script_given = 0;
+ e_tmpname = NULL;
for (argc--,argv++; argc > 0; argc--,argv++) {
if (argv[0][0] != '-' || !argv[0][1]) break;
@@ -161,20 +180,21 @@ proc_options(argcp, argvp)
reswitch:
switch (*s) {
case 'a':
- do_split = TRUE;
+ do_split = Qtrue;
s++;
goto reswitch;
case 'p':
- do_print = TRUE;
+ do_print = Qtrue;
/* through */
case 'n':
- do_loop = TRUE;
+ do_loop = Qtrue;
s++;
goto reswitch;
case 'd':
- debug = TRUE;
+ rb_debug = Qtrue;
+ rb_verbose |= 1;
s++;
goto reswitch;
@@ -184,47 +204,52 @@ proc_options(argcp, argvp)
goto reswitch;
case 'v':
- show_version();
- verbose = 2;
+ ruby_show_version();
+ rb_verbose = 2;
case 'w':
- verbose |= 1;
+ rb_verbose |= 1;
s++;
goto reswitch;
case 'c':
- do_check = TRUE;
+ do_check = Qtrue;
s++;
goto reswitch;
case 's':
forbid_setid("-s");
- sflag = TRUE;
+ sflag = Qtrue;
s++;
goto reswitch;
case 'l':
- do_line = TRUE;
- ORS = RS;
+ do_line = Qtrue;
+ rb_output_rs = rb_rs;
s++;
goto reswitch;
case 'S':
forbid_setid("-S");
- do_search = TRUE;
+ do_search = Qtrue;
s++;
goto reswitch;
case 'e':
forbid_setid("-e");
- script_given++;
- if (script == 0) script = "-e";
- if (argv[1]) {
- compile_string("-e", argv[1], strlen(argv[1]));
- argc--,argv++;
+ if (!e_fp) {
+ e_tmpname = ruby_mktemp();
+ if (!e_tmpname) rb_fatal("Can't mktemp");
+ e_fp = fopen(e_tmpname, "w");
+ if (!e_fp) {
+ rb_fatal("Cannot open temporary file: %s", e_tmpname);
+ }
+ if (script == 0) script = e_tmpname;
}
- else {
- compile_string("-e", "", 0);
+ if (argv[1]) {
+ fputs(argv[1], e_fp);
+ argc--, argv++;
}
+ putc('\n', e_fp);
break;
case 'r':
@@ -240,15 +265,15 @@ proc_options(argcp, argvp)
case 'i':
forbid_setid("-i");
- if (inplace) free(inplace);
- inplace = strdup(s+1);
+ if (ruby_inplace_mode) free(ruby_inplace_mode);
+ ruby_inplace_mode = strdup(s+1);
break;
case 'x':
- xflag = TRUE;
+ xflag = Qtrue;
s++;
if (*s && chdir(s) < 0) {
- Fatal("Can't chdir to %s", s);
+ rb_fatal("Can't chdir to %s", s);
}
break;
@@ -259,12 +284,12 @@ proc_options(argcp, argvp)
argc--,argv++;
}
if (*s && chdir(s) < 0) {
- Fatal("Can't chdir to %s", s);
+ rb_fatal("Can't chdir to %s", s);
}
break;
case 'F':
- FS = str_new2(s+1);
+ rb_fs = rb_str_new2(s+1);
break;
case 'K':
@@ -283,7 +308,7 @@ proc_options(argcp, argvp)
if (numlen == 0) v = 1;
}
rb_set_safe_level(v);
- tainting = TRUE;
+ rb_tainting = Qtrue;
}
break;
@@ -305,13 +330,13 @@ proc_options(argcp, argvp)
v = scan_oct(s, 4, &numlen);
s += numlen;
- if (v > 0377) RS = Qnil;
+ if (v > 0377) rb_rs = Qnil;
else if (v == 0 && numlen >= 2) {
- RS = str_new2("\n\n");
+ rb_rs = rb_str_new2("\n\n");
}
else {
c = v & 0xff;
- RS = str_new(&c, 1);
+ rb_rs = rb_str_new(&c, 1);
}
}
goto reswitch;
@@ -325,15 +350,15 @@ proc_options(argcp, argvp)
if (strcmp("copyright", s) == 0)
copyright = 1;
else if (strcmp("debug", s) == 0)
- debug = 1;
+ rb_debug = 1;
else if (strcmp("version", s) == 0)
version = 1;
else if (strcmp("verbose", s) == 0)
- verbose = 2;
+ rb_verbose = 2;
else if (strcmp("yydebug", s) == 0)
yydebug = 1;
else {
- Fatal("Unrecognized long option: --%s",s);
+ rb_fatal("Unrecognized long option: --%s",s);
}
break;
@@ -343,7 +368,7 @@ proc_options(argcp, argvp)
break;
default:
- Fatal("Unrecognized switch: -%s",s);
+ rb_fatal("Unrecognized switch: -%s",s);
case 0:
break;
@@ -353,17 +378,26 @@ proc_options(argcp, argvp)
switch_end:
if (*argvp[0] == 0) return;
+ if (e_fp) {
+ if (fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
+ rb_fatal("Cannot write to temp file for -e");
+ e_fp = NULL;
+ argc++, argv--;
+ argv[0] = e_tmpname;
+ }
+
if (version) {
- show_version();
+ ruby_show_version();
exit(0);
}
if (copyright) {
- show_copyright();
+ ruby_show_copyright();
}
- if (script_given == FALSE) {
+ Init_ext(); /* should be called here for some reason :-( */
+ if (script_given == Qfalse) {
if (argc == 0) { /* no more args */
- if (verbose == 3) exit(0);
+ if (rb_verbose == 3) exit(0);
script = "-";
load_stdin();
}
@@ -391,9 +425,10 @@ proc_options(argcp, argvp)
argc--; argv++;
}
}
- if (verbose) verbose = TRUE;
+ if (rb_verbose) rb_verbose = Qtrue;
+ if (rb_debug) rb_debug = Qtrue;
- xflag = FALSE;
+ xflag = Qfalse;
*argvp = argv;
*argcp = argc;
@@ -409,17 +444,20 @@ proc_options(argcp, argvp)
argv[0][0] = '$';
if (s = strchr(argv[0], '=')) {
*s++ = '\0';
- rb_gvar_set2(argv[0], str_new2(s));
+ rb_gvar_set2(argv[0], rb_str_new2(s));
}
else {
- rb_gvar_set2(argv[0], TRUE);
+ rb_gvar_set2(argv[0], Qtrue);
}
+ argv[0][0] = '-';
}
*argcp = argc; *argvp = argv;
}
}
+extern int ruby__end__seen;
+
static void
load_file(fname, script)
char *fname;
@@ -433,42 +471,43 @@ load_file(fname, script)
f = rb_stdin;
}
else {
- f = file_open(fname, "r");
+ FILE *fp = fopen(fname, "r");
+
+ if (fp == NULL) {
+ rb_raise(rb_eLoadError, "No such file to load -- %s", fname);
+ }
+ fclose(fp);
+
+ f = rb_file_open(fname, "r");
}
if (script) {
VALUE c;
VALUE line;
- VALUE rs = RS;
+ char *p;
- RS = RS_default;
if (xflag) {
forbid_setid("-x");
- xflag = FALSE;
- while (!NIL_P(line = io_gets(f))) {
+ xflag = Qfalse;
+ while (!NIL_P(line = rb_io_gets(f))) {
line_start++;
if (RSTRING(line)->len > 2
&& RSTRING(line)->ptr[0] == '#'
&& RSTRING(line)->ptr[1] == '!') {
- if (strstr(RSTRING(line)->ptr, "ruby")) {
+ if (p = strstr(RSTRING(line)->ptr, "ruby")) {
goto start_read;
}
}
}
- RS = rs;
- LoadError("No Ruby script found in input");
+ rb_raise(rb_eLoadError, "No Ruby script found in input");
}
- c = io_getc(f);
+ c = rb_io_getc(f);
if (c == INT2FIX('#')) {
- line = io_gets(f);
+ line = rb_io_gets(f);
line_start++;
- if (RSTRING(line)->len > 2
- && RSTRING(line)->ptr[0] == '!') {
-
- char *p;
-
+ if (RSTRING(line)->len > 2 && RSTRING(line)->ptr[0] == '!') {
if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) {
/* not ruby script, kick the program */
char **argv;
@@ -479,10 +518,10 @@ load_file(fname, script)
if (pend[-1] == '\n') pend--; /* chomp line */
if (pend[-1] == '\r') pend--;
*pend = '\0';
- while (p < pend && isspace(*p))
+ while (p < pend && ISSPACE(*p))
p++;
path = p; /* interpreter path */
- while (p < pend && !isspace(*p))
+ while (p < pend && !ISSPACE(*p))
p++;
*p++ = '\0';
if (p < pend) {
@@ -494,36 +533,48 @@ load_file(fname, script)
argv = origargv;
}
argv[0] = path;
+#ifndef USE_CWGUSI
execv(path, argv);
- sourcefile = fname;
- sourceline = 1;
- Fatal("Can't exec %s", path);
+#endif
+ ruby_sourcefile = fname;
+ ruby_sourceline = 1;
+ rb_fatal("Can't exec %s", path);
}
start_read:
- if (p = strstr(RSTRING(line)->ptr, "ruby -")) {
+ p += 4;
+ RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
+ if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
+ RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
+ if (p = strstr(p, " -")) {
int argc; char *argv[2]; char **argvp = argv;
- UCHAR *s;
-
- s = RSTRING(line)->ptr;
- while (isspace(*s))
- s++;
- *s = '\0';
- RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
- if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
- RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
- argc = 2; argv[0] = 0; argv[1] = p + 5;
- proc_options(&argc, &argvp);
+ char *s = ++p;
+
+ argc = 2; argv[0] = 0;
+ while (*p == '-') {
+ while (*s && !ISSPACE(*s))
+ s++;
+ *s = '\0';
+ argv[1] = p;
+ proc_options(&argc, &argvp);
+ p = ++s;
+ while (*p && ISSPACE(*p))
+ p++;
+ }
}
}
}
else if (!NIL_P(c)) {
- io_ungetc(f, c);
+ rb_io_ungetc(f, c);
}
- RS = rs;
}
- compile_file(fname, f, line_start);
- if (f != rb_stdin) io_close(f);
+ rb_compile_file(fname, f, line_start);
+ if (script && ruby__end__seen) {
+ rb_define_global_const("DATA", f);
+ }
+ else if (f != rb_stdin) {
+ rb_io_close(f);
+ }
}
void
@@ -553,8 +604,8 @@ set_arg0(val, id)
int i;
static int len;
- if (origargv == 0) Fail("$0 not initialized");
- Check_Type(val, T_STRING);
+ if (origargv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized");
+#ifndef __hpux
if (len == 0) {
s = origargv[0];
s += strlen(s);
@@ -565,8 +616,9 @@ set_arg0(val, id)
}
len = s - origargv[0];
}
- s = RSTRING(val)->ptr;
- i = RSTRING(val)->len;
+#endif
+ s = rb_str2cstr(val, &i);
+#ifndef __hpux
if (i > len) {
memcpy(origargv[0], s, len);
origargv[0][len] = '\0';
@@ -578,7 +630,22 @@ set_arg0(val, id)
while (++i < len)
*s++ = ' ';
}
- rb_progname = str_taint(str_new2(origargv[0]));
+ rb_progname = rb_tainted_str_new2(origargv[0]);
+#else
+ if (i >= PST_CLEN) {
+ union pstun j;
+ j.pst_command = s;
+ i = PST_CLEN;
+ RSTRING(val)->len = i;
+ *(s + i) = '\0';
+ pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0);
+ } else {
+ union pstun j;
+ j.pst_command = s;
+ pstat(PSTAT_SETCMD, j, i, 0, 0);
+ }
+ rb_progname = rb_tainted_str_new(s, i);
+#endif
}
void
@@ -586,8 +653,8 @@ ruby_script(name)
char *name;
{
if (name) {
- rb_progname = str_taint(str_new2(name));
- sourcefile = name;
+ rb_progname = rb_tainted_str_new2(name);
+ ruby_sourcefile = name;
}
}
@@ -614,9 +681,11 @@ forbid_setid(s)
char *s;
{
if (euid != uid)
- Fatal("No %s allowed while running setuid", s);
+ rb_raise(rb_eSecurityError, "No %s allowed while running setuid", s);
if (egid != gid)
- Fatal("No %s allowed while running setgid", s);
+ 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);
}
#if defined(_WIN32) || defined(DJGPP)
@@ -658,37 +727,48 @@ ruby_prog_init()
{
init_ids();
- sourcefile = "ruby";
- rb_define_variable("$VERBOSE", &verbose);
- rb_define_variable("$-v", &verbose);
- rb_define_variable("$DEBUG", &debug);
- rb_define_variable("$-d", &debug);
+ ruby_sourcefile = "ruby";
+ rb_define_variable("$VERBOSE", &rb_verbose);
+ rb_define_variable("$-v", &rb_verbose);
+ rb_define_variable("$DEBUG", &rb_debug);
+ rb_define_variable("$-d", &rb_debug);
rb_define_readonly_variable("$-p", &do_print);
rb_define_readonly_variable("$-l", &do_line);
+ if (rb_safe_level() == 0) {
+ addpath(".");
+ }
+
+ addpath(RUBY_LIB);
#if defined(_WIN32) || defined(DJGPP)
addpath(ruby_libpath());
#endif
+#ifdef __MACOS__
+ setup_macruby_libpath();
+#endif
- if (rb_safe_level() == 0) {
- addpath(getenv("RUBYLIB"));
- }
-
+#ifdef RUBY_ARCHLIB
+ addpath(RUBY_ARCHLIB);
+#endif
#ifdef RUBY_THIN_ARCHLIB
addpath(RUBY_THIN_ARCHLIB);
#endif
-#ifdef RUBY_ARCHLIB
- addpath(RUBY_ARCHLIB);
+ addpath(RUBY_SITE_LIB);
+#ifdef RUBY_SITE_ARCHLIB
+ addpath(RUBY_SITE_ARCHLIB);
#endif
- addpath(RUBY_LIB);
+#ifdef RUBY_SITE_THIN_ARCHLIB
+ addpath(RUBY_SITE_THIN_ARCHLIB);
+#endif
+
if (rb_safe_level() == 0) {
- addpath(".");
+ addpath(getenv("RUBYLIB"));
}
rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
- rb_argv = ary_new();
+ rb_argv = rb_ary_new();
rb_define_readonly_variable("$*", &rb_argv);
rb_define_global_const("ARGV", rb_argv);
rb_define_readonly_variable("$-a", &do_split);
@@ -716,7 +796,7 @@ ruby_set_argv(argc, argv)
else dln_argv0 = argv[0];
#endif
for (i=0; i < argc; i++) {
- ary_push(rb_argv, str_taint(str_new2(argv[i])));
+ rb_ary_push(rb_argv, rb_tainted_str_new2(argv[i]));
}
}
@@ -725,12 +805,9 @@ ruby_process_options(argc, argv)
int argc;
char **argv;
{
- extern VALUE errat;
- int i;
-
origargc = argc; origargv = argv;
ruby_script(argv[0]); /* for the time being */
- rb_argv0 = str_taint(str_new2(argv[0]));
+ rb_argv0 = rb_progname;
#if defined(USE_DLN_A_OUT)
dln_argv0 = argv[0];
#endif
@@ -738,14 +815,22 @@ ruby_process_options(argc, argv)
ruby_script(script);
ruby_set_argv(argc, argv);
- if (do_check && nerrs == 0) {
+ if (do_check && ruby_nerrs == 0) {
printf("Syntax OK\n");
exit(0);
}
if (do_print) {
- yyappend_print();
+ rb_parser_append_print();
}
if (do_loop) {
- yywhile_loop(do_line, do_split);
+ rb_parser_while_loop(do_line, do_split);
+ }
+ if (e_fp) {
+ fclose(e_fp);
+ e_fp = NULL;
+ }
+ if (e_tmpname) {
+ unlink(e_tmpname);
+ e_tmpname = NULL;
}
}
diff --git a/ruby.h b/ruby.h
index ac53f620a9..44c1abd2c6 100644
--- a/ruby.h
+++ b/ruby.h
@@ -6,17 +6,26 @@
$Date$
created at: Thu Jun 10 14:26:32 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
*************************************************/
#ifndef RUBY_H
#define RUBY_H
-#include "config.h"
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#include "config.h"
#include "defines.h"
+#if 0
+#ifndef RUBY_RENAME
+#include "rename2.h"
+#endif
+#endif
+
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
@@ -27,6 +36,19 @@
# include <strings.h>
#endif
+#include <stddef.h>
+#include <stdio.h>
+
+/* need to include <ctype.h> to use these macros */
+#define ISSPACE(c) isspace((unsigned char)(c))
+#define ISUPPER(c) isupper((unsigned char)(c))
+#define ISLOWER(c) islower((unsigned char)(c))
+#define ISPRINT(c) isprint((unsigned char)(c))
+#define ISALNUM(c) isalnum((unsigned char)(c))
+#define ISALPHA(c) isalpha((unsigned char)(c))
+#define ISDIGIT(c) isdigit((unsigned char)(c))
+#define ISXDIGIT(c) isxdigit((unsigned char)(c))
+
#ifndef __STDC__
# define volatile
# ifdef __GNUC__
@@ -34,34 +56,48 @@
# else
# define const
# endif
+#endif
+
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
# define _(args) ()
+#endif
+
+#ifdef HAVE_STDARG_PROTOTYPES
+# define __(args) args
#else
-# define _(args) args
+# define __(args) ()
+#endif
+
+#ifdef HAVE_ATTR_NORETURN
+# define NORETURN __attribute__ ((noreturn))
+#else
+# define NORETURN
#endif
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
#include <alloca.h>
#endif
+#if defined(__CYGWIN32__)
+#if defined(DLLIMPORT)
+#include "import.h"
+#else
+#define environ (*__imp___cygwin_environ)
+#endif
+#endif
+
#ifdef _AIX
#pragma alloca
#endif
-typedef unsigned short USHORT;
-typedef unsigned long UINT;
-
-#if SIZEOF_INT == SIZEOF_VOIDP
-typedef int INT;
-#elif SIZEOF_LONG == SIZEOF_VOIDP
-typedef long INT;
-#else
----->> ruby requires sizeof(void*) == sizeof(int/long) to be compiled. <<----
-#endif
-typedef UINT VALUE;
+#if SIZEOF_LONG != SIZEOF_VOIDP
+---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
+# endif
+typedef unsigned long VALUE;
typedef unsigned int ID;
-typedef unsigned char UCHAR;
-
#ifdef __STDC__
# include <limits.h>
#else
@@ -69,15 +105,12 @@ typedef unsigned char UCHAR;
# ifdef HAVE_LIMITS_H
# include <limits.h>
# else
-# define LONG_MAX 2147483647 /* assuming 32bit(2's compliment) LONG */
+ /* assuming 32bit(2's compliment) long */
+# define LONG_MAX 2147483647
# endif
# endif
# ifndef LONG_MIN
-# if (0 != ~0)
-# define LONG_MIN (-LONG_MAX-1)
-# else
-# define LONG_MIN (-LONG_MAX)
-# endif
+# define LONG_MIN (-LONG_MAX-1)
# endif
# ifndef CHAR_BIT
# define CHAR_BIT 8
@@ -85,32 +118,21 @@ typedef unsigned char UCHAR;
#endif
#define FIXNUM_MAX (LONG_MAX>>1)
-#define FIXNUM_MIN RSHIFT((INT)LONG_MIN,1)
+#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
#define FIXNUM_FLAG 0x01
-#define INT2FIX(i) (VALUE)(((INT)(i))<<1 | FIXNUM_FLAG)
-VALUE int2inum _((INT));
-#define INT2NUM(v) int2inum(v)
-
-#if (-1==(((-1)<<1)&FIXNUM_FLAG)>>1)
-# define RSHIFT(x,y) ((x)>>y)
-#else
-# define RSHIFT(x,y) (((x)<0) ? ~((~(x))>>y) : (x)>>y)
-#endif
-#define FIX2INT(x) RSHIFT((INT)x,1)
+#define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG)
+VALUE rb_int2inum _((long));
+#define INT2NUM(v) rb_int2inum(v)
-#define FIX2UINT(f) (((UINT)(f))>>1)
+#define FIX2LONG(x) RSHIFT((long)x,1)
+#define FIX2ULONG(x) (((unsigned long)(x))>>1)
#define FIXNUM_P(f) (((long)(f))&FIXNUM_FLAG)
#define POSFIXABLE(f) ((f) <= FIXNUM_MAX)
#define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
/* special contants - i.e. non-zero and non-fixnum constants */
-#undef FALSE
-#undef TRUE
-#define FALSE 0
-#define TRUE 2
-#define NIL 4
#define Qfalse 0
#define Qtrue 2
#define Qnil 4
@@ -118,36 +140,35 @@ VALUE int2inum _((INT));
# define RTEST(v) rb_test_false_or_nil((VALUE)(v))
#define NIL_P(v) ((VALUE)(v) == Qnil)
-extern VALUE cObject;
-
-VALUE rb_class_of _((VALUE));
#define CLASS_OF(v) rb_class_of((VALUE)(v))
-#define T_NIL 0x00
-#define T_OBJECT 0x01
-#define T_CLASS 0x02
-#define T_ICLASS 0x03
-#define T_MODULE 0x04
-#define T_FLOAT 0x05
-#define T_STRING 0x06
-#define T_REGEXP 0x07
-#define T_ARRAY 0x08
-#define T_FIXNUM 0x09
-#define T_HASH 0x0a
-#define T_STRUCT 0x0b
-#define T_BIGNUM 0x0c
-#define T_FILE 0x0d
+#define T_NONE 0x00
+
+#define T_NIL 0x01
+#define T_OBJECT 0x02
+#define T_CLASS 0x03
+#define T_ICLASS 0x04
+#define T_MODULE 0x05
+#define T_FLOAT 0x06
+#define T_STRING 0x07
+#define T_REGEXP 0x08
+#define T_ARRAY 0x09
+#define T_FIXNUM 0x0a
+#define T_HASH 0x0b
+#define T_STRUCT 0x0c
+#define T_BIGNUM 0x0d
+#define T_FILE 0x0e
#define T_TRUE 0x20
#define T_FALSE 0x21
#define T_DATA 0x22
#define T_MATCH 0x23
-#define T_VARMAP 0xfd
-#define T_SCOPE 0xfe
-#define T_NODE 0xff
+#define T_VARMAP 0x7d
+#define T_SCOPE 0x7e
+#define T_NODE 0x7f
-#define T_MASK 0xff
+#define T_MASK 0x7f
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
@@ -159,26 +180,50 @@ void rb_check_safe_str _((VALUE));
#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
void rb_secure _((int));
-int num2int _((VALUE));
-#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):num2int(x))
+long rb_num2long _((VALUE));
+unsigned long rb_num2ulong _((VALUE));
+#define NUM2LONG(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2long((VALUE)x))
+#define NUM2ULONG(x) rb_num2ulong((VALUE)x)
+#if SIZEOF_INT < SIZEOF_LONG
+int rb_num2int _((VALUE));
+#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2int((VALUE)x))
+int rb_fix2int _((VALUE));
+#define FIX2INT(x) rb_fix2int((VALUE)x)
+#define NUM2UINT(x) ((unsigned int)NUM2ULONG(x))
+#define FIX2UINT(x) ((unsigned int)FIX2ULONG(x))
+#else
+#define NUM2INT(x) NUM2LONG(x)
+#define NUM2UINT(x) NUM2ULONG(x)
+#define FIX2INT(x) FIX2LONG(x)
+#define FIX2UINT(x) FIX2ULONG(x)
+#endif
+
+double rb_num2dbl _((VALUE));
+#define NUM2DBL(x) rb_num2dbl((VALUE)(x))
+
+char *rb_str2cstr _((VALUE,int*));
+#define str2cstr(x,l) rb_str2cstr((VALUE)(x),(l))
+#define STR2CSTR(x) rb_str2cstr((VALUE)(x),0)
-double num2dbl _((VALUE));
-#define NUM2DBL(x) num2dbl((VALUE)(x))
+#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
+ RSTRING(x)->ptr[0]:(char)NUM2INT(x))
+#define CHR2FIX(x) INT2FIX((int)x)
VALUE rb_newobj _((void));
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
#define OBJSETUP(obj,c,t) {\
- RBASIC(obj)->class = (c);\
+ RBASIC(obj)->klass = (c);\
RBASIC(obj)->flags = (t);\
+ if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
}
#define CLONESETUP(clone,obj) {\
- OBJSETUP(clone,singleton_class_clone(RBASIC(obj)->class),RBASIC(obj)->flags);\
- singleton_class_attached(RBASIC(clone)->class, (VALUE)clone);\
+ OBJSETUP(clone,rb_singleton_class_clone(RBASIC(obj)->klass),RBASIC(obj)->flags);\
+ rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
}
struct RBasic {
- UINT flags;
- VALUE class;
+ unsigned long flags;
+ VALUE klass;
};
struct RObject {
@@ -200,33 +245,34 @@ struct RFloat {
struct RString {
struct RBasic basic;
- UINT len;
- UCHAR *ptr;
+ size_t len;
+ char *ptr;
VALUE orig;
};
struct RArray {
struct RBasic basic;
- UINT len, capa;
+ size_t len, capa;
VALUE *ptr;
};
struct RRegexp {
struct RBasic basic;
struct re_pattern_buffer *ptr;
- UINT len;
- UCHAR *str;
+ size_t len;
+ char *str;
};
struct RHash {
struct RBasic basic;
struct st_table *tbl;
int iter_lev;
- UINT status;
+ VALUE ifnone;
};
struct RFile {
struct RBasic basic;
+ struct st_table *iv_tbl;
struct OpenFile *fptr;
};
@@ -237,17 +283,18 @@ struct RData {
void *data;
};
+extern VALUE rb_cData;
#define DATA_PTR(dta) (RDATA(dta)->data)
-VALUE data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
-#define Data_Make_Struct(class,type,mark,free,sval) (\
+VALUE rb_data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
+#define Data_Make_Struct(klass,type,mark,free,sval) (\
sval = ALLOC(type),\
memset(sval, 0, sizeof(type)),\
- data_object_alloc(class,sval,mark,free)\
+ rb_data_object_alloc(klass,sval,mark,free)\
)
-#define Data_Wrap_Struct(class,mark,free,sval) (\
- data_object_alloc(class,sval,mark,free)\
+#define Data_Wrap_Struct(klass,mark,free,sval) (\
+ rb_data_object_alloc(klass,sval,mark,free)\
)
#define Data_Get_Struct(obj,type,sval) {\
@@ -257,21 +304,22 @@ VALUE data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
struct RStruct {
struct RBasic basic;
- UINT len;
+ size_t len;
VALUE *ptr;
};
struct RBignum {
struct RBasic basic;
char sign;
- UINT len;
- USHORT *digits;
+ size_t len;
+ unsigned short *digits;
};
-#define R_CAST(st) (struct st*)
+#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
#define RCLASS(obj) (R_CAST(RClass)(obj))
+#define RMODULE(obj) RCLASS(obj)
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
@@ -282,9 +330,11 @@ struct RBignum {
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))
-#define FL_SINGLETON (1<<8)
-#define FL_MARK (1<<9)
-#define FL_FINALIZE (1<<10)
+#define FL_SINGLETON FL_USER0
+#define FL_MARK (1<<7)
+#define FL_FINALIZE (1<<8)
+#define FL_TAINT (1<<9)
+#define FL_EXIVAR (1<<10)
#define FL_USHIFT 11
@@ -295,8 +345,9 @@ struct RBignum {
#define FL_USER4 (1<<(FL_USHIFT+4))
#define FL_USER5 (1<<(FL_USHIFT+5))
#define FL_USER6 (1<<(FL_USHIFT+6))
+#define FL_USER7 (1<<(FL_USHIFT+7))
-#define FL_UMASK (0x7f<<FL_USHIFT)
+#define FL_UMASK (0xff<<FL_USHIFT)
#define FL_ABLE(x) (!(FIXNUM_P(x)||rb_special_const_p((VALUE)(x))))
#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
@@ -304,38 +355,12 @@ struct RBignum {
#define FL_UNSET(x,f) if(FL_ABLE(x)){RBASIC(x)->flags &= ~(f);}
#define FL_REVERSE(x,f) if(FL_ABLE(x)){RBASIC(x)->flags ^= f;}
-#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
-extern __inline__ int
-rb_type(VALUE obj)
-{
- if (FIXNUM_P(obj)) return T_FIXNUM;
- if (obj == Qnil) return T_NIL;
- if (obj == FALSE) return T_FALSE;
- if (obj == TRUE) return T_TRUE;
-
- return BUILTIN_TYPE(obj);
-}
-
-extern __inline__ int
-rb_special_const_p(VALUE obj)
-{
- return (FIXNUM_P(obj)||obj == Qnil||obj == FALSE||obj == TRUE)?TRUE:FALSE;
-}
-
-extern __inline__ int
-rb_test_false_or_nil(VALUE v)
-{
- return (v != Qnil) && (v != FALSE);
-}
-#else
-int rb_type _((VALUE));
-int rb_special_const_p _((VALUE));
-int rb_test_false_or_nil _((VALUE));
-#endif
+#define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
+#define OBJ_TAINT(x) FL_SET((x), FL_TAINT)
-void *xmalloc _((unsigned long));
-void *xcalloc _((unsigned long,unsigned long));
-void *xrealloc _((void*,unsigned long));
+void *xmalloc _((size_t));
+void *xcalloc _((size_t,size_t));
+void *xrealloc _((void*,size_t));
#define ALLOC_N(type,n) (type*)xmalloc(sizeof(type)*(n))
#define ALLOC(type) (type*)xmalloc(sizeof(type))
#define REALLOC_N(var,type,n) (var)=(type*)xrealloc((char*)(var),sizeof(type)*(n))
@@ -362,13 +387,12 @@ void rb_define_const _((VALUE,char*,VALUE));
void rb_define_global_const _((char*,VALUE));
void rb_define_method _((VALUE,char*,VALUE(*)(),int));
-void rb_define_function _((VALUE,char*,VALUE(*)(),int));
void rb_define_module_function _((VALUE,char*,VALUE(*)(),int));
-void rb_define_global_function _((char *, VALUE (*)(), int));
+void rb_define_global_function _((char*,VALUE(*)(),int));
void rb_undef_method _((VALUE,char*));
void rb_define_alias _((VALUE,char*,char*));
-void rb_define_attr _((VALUE,ID,int,int));
+void rb_define_attr _((VALUE,char*,int,int));
ID rb_intern _((char*));
char *rb_id2name _((ID));
@@ -379,8 +403,9 @@ char *rb_class2name _((VALUE));
void rb_p _((VALUE));
VALUE rb_eval_string _((char*));
-VALUE rb_funcall();
-int rb_scan_args();
+VALUE rb_eval_string_protect _((char*, int*));
+VALUE rb_funcall __((VALUE, ID, int, ...));
+int rb_scan_args __((int, VALUE*, char*, ...));
VALUE rb_iv_get _((VALUE, char *));
VALUE rb_iv_set _((VALUE, char *, VALUE));
@@ -390,53 +415,140 @@ void rb_const_set _((VALUE, ID, VALUE));
VALUE rb_equal _((VALUE,VALUE));
-extern VALUE verbose, debug;
+EXTERN VALUE rb_verbose, rb_debug;
int rb_safe_level _((void));
void rb_set_safe_level _((int));
-#ifdef __GNUC__
-typedef void voidfn ();
-volatile voidfn Raise;
-volatile voidfn Fail;
-volatile voidfn Fatal;
-volatile voidfn Bug;
-volatile voidfn WrongType;
-volatile voidfn rb_sys_fail;
-volatile voidfn rb_iter_break;
-volatile voidfn rb_exit;
-volatile voidfn rb_fatal;
-volatile voidfn rb_raise;
-volatile voidfn rb_notimplement;
-#else
-void Raise();
-void Fail();
-void Fatal();
-void Bug();
-void WrongType();
-void rb_sys_fail _((char *));
-void rb_iter_break _((void));
-void rb_exit _((int));
-void rb_raise _((VALUE));
-void rb_fatal _((VALUE));
-void rb_notimplement _((void));
-#endif
+void rb_raise __((VALUE, char*, ...)) NORETURN;
+void rb_fatal __((char*, ...)) NORETURN;
+void rb_bug __((char*, ...)) NORETURN;
+void rb_sys_fail _((char*)) NORETURN;
+void rb_iter_break _((void)) NORETURN;
+void rb_exit _((int)) NORETURN;
+void rb_notimplement _((void)) NORETURN;
-void Error();
-void Warning();
+void rb_warn __((char*, ...));
+void rb_warning __((char*, ...)); /* reports if `-w' specified */
VALUE rb_each _((VALUE));
VALUE rb_yield _((VALUE));
-int iterator_p _((void));
-VALUE rb_iterate();
-VALUE rb_rescue();
-VALUE rb_ensure();
+int rb_iterator_p _((void));
+VALUE rb_iterate _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
+VALUE rb_rescue _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
+VALUE rb_ensure _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
+VALUE rb_catch _((char*,VALUE(*)(),VALUE));
+void rb_throw _((char*,VALUE)) NORETURN;
+
+void ruby_init _((void));
+void ruby_options _((int, char**));
+void ruby_run _((void));
+
+EXTERN VALUE rb_mKernel;
+EXTERN VALUE rb_mComparable;
+EXTERN VALUE rb_mEnumerable;
+EXTERN VALUE rb_mErrno;
+EXTERN VALUE rb_mFileTest;
+EXTERN VALUE rb_mGC;
+EXTERN VALUE rb_mMath;
+EXTERN VALUE rb_mProcess;
+
+EXTERN VALUE rb_cObject;
+EXTERN VALUE rb_cArray;
+EXTERN VALUE rb_cBignum;
+EXTERN VALUE rb_cClass;
+EXTERN VALUE rb_cDir;
+EXTERN VALUE rb_cData;
+EXTERN VALUE rb_cFalseClass;
+EXTERN VALUE rb_cFile;
+EXTERN VALUE rb_cFixnum;
+EXTERN VALUE rb_cFloat;
+EXTERN VALUE rb_cHash;
+EXTERN VALUE rb_cInteger;
+EXTERN VALUE rb_cIO;
+EXTERN VALUE rb_cModule;
+EXTERN VALUE rb_cNilClass;
+EXTERN VALUE rb_cNumeric;
+EXTERN VALUE rb_cProc;
+EXTERN VALUE rb_cRange;
+EXTERN VALUE rb_cRegexp;
+EXTERN VALUE rb_cString;
+EXTERN VALUE rb_cThread;
+EXTERN VALUE rb_cTime;
+EXTERN VALUE rb_cTrueClass;
+EXTERN VALUE rb_cStruct;
+
+EXTERN VALUE rb_eException;
+EXTERN VALUE rb_eStandardError;
+EXTERN VALUE rb_eSystemExit, rb_eInterrupt, rb_eFatal;
+EXTERN VALUE rb_eArgError;
+EXTERN VALUE rb_eEOFError;
+EXTERN VALUE rb_eIndexError;
+EXTERN VALUE rb_eIOError;
+EXTERN VALUE rb_eLoadError;
+EXTERN VALUE rb_eNameError;
+EXTERN VALUE rb_eRuntimeError;
+EXTERN VALUE rb_eSecurityError;
+EXTERN VALUE rb_eSyntaxError;
+EXTERN VALUE rb_eSystemCallError;
+EXTERN VALUE rb_eTypeError;
+EXTERN VALUE rb_eZeroDiv;
+EXTERN VALUE rb_eNotImpError;
+
+#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
+extern __inline__ VALUE rb_class_of _((VALUE));
+extern __inline__ int rb_type _((VALUE));
+extern __inline__ int rb_special_const_p _((VALUE));
+extern __inline__ int rb_test_false_or_nil _((VALUE));
+
+extern __inline__ VALUE
+rb_class_of(VALUE obj)
+{
+ if (FIXNUM_P(obj)) return rb_cFixnum;
+ if (obj == Qnil) return rb_cNilClass;
+ if (obj == Qfalse) return rb_cFalseClass;
+ if (obj == Qtrue) return rb_cTrueClass;
+
+ return RBASIC(obj)->klass;
+}
+
+extern __inline__ int
+rb_type(VALUE obj)
+{
+ if (FIXNUM_P(obj)) return T_FIXNUM;
+ if (obj == Qnil) return T_NIL;
+ if (obj == Qfalse) return T_FALSE;
+ if (obj == Qtrue) return T_TRUE;
+ return BUILTIN_TYPE(obj);
+}
+
+extern __inline__ int
+rb_special_const_p(VALUE obj)
+{
+ return (FIXNUM_P(obj)||obj == Qnil||obj == Qfalse||obj == Qtrue)?Qtrue:Qfalse;
+}
+
+extern __inline__ int
+rb_test_false_or_nil(VALUE v)
+{
+ return (v != Qnil) && (v != Qfalse);
+}
+#else
+VALUE rb_class_of _((VALUE));
+int rb_type _((VALUE));
+int rb_special_const_p _((VALUE));
+int rb_test_false_or_nil _((VALUE));
+#endif
#include "intern.h"
#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
/* hook for external modules */
-static char *libs_to_be_linked[] = { EXTLIB, 0 };
+static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
#endif
+#if defined(__cplusplus)
+} /* extern "C" { */
#endif
+
+#endif /* ifndef RUBY_H */
diff --git a/rubyio.h b/rubyio.h
new file mode 100644
index 0000000000..5b8baf0f15
--- /dev/null
+++ b/rubyio.h
@@ -0,0 +1,60 @@
+/************************************************
+
+ rubyio.h -
+
+ $Author$
+ $Revision$
+ $Date$
+ created at: Fri Nov 12 16:47:09 JST 1993
+
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
+
+************************************************/
+
+#ifndef IO_H
+#define IO_H
+
+#include <stdio.h>
+#include <errno.h>
+
+typedef struct OpenFile {
+ FILE *f; /* stdio ptr for read/write */
+ FILE *f2; /* additional ptr for rw pipes */
+ int mode; /* mode flags */
+ int pid; /* child's pid (for pipes) */
+ int lineno; /* number of lines read */
+ char *path; /* pathname for file */
+ void (*finalize)(); /* finalize proc */
+} OpenFile;
+
+#define FMODE_READABLE 1
+#define FMODE_WRITABLE 2
+#define FMODE_READWRITE 3
+#define FMODE_BINMODE 4
+#define FMODE_SYNC 8
+
+#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(obj)->fptr)
+
+#define MakeOpenFile(obj, fp) do {\
+ fp = RFILE(obj)->fptr = ALLOC(OpenFile);\
+ fp->f = fp->f2 = NULL;\
+ fp->mode = 0;\
+ fp->pid = 0;\
+ fp->lineno = 0;\
+ fp->path = NULL;\
+ fp->finalize = 0;\
+} while (0)
+
+#define GetReadFile(fptr) ((fptr)->f)
+#define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f)
+
+FILE *rb_fopen _((char *, char *));
+FILE *rb_fdopen _((int, char *));
+void rb_io_check_writable _((OpenFile *));
+void rb_io_check_readable _((OpenFile *));
+void rb_io_fptr_finalize _((OpenFile *));
+void rb_io_unbuffered _((OpenFile *));
+void rb_io_check_closed _((OpenFile *));
+void rb_eof_error _((void));
+
+#endif
diff --git a/rubysig.h b/rubysig.h
new file mode 100644
index 0000000000..6c6ce571e3
--- /dev/null
+++ b/rubysig.h
@@ -0,0 +1,54 @@
+/************************************************
+
+ rubysig.h -
+
+ $Author$
+ $Date$
+ created at: Wed Aug 16 01:15:38 JST 1995
+
+************************************************/
+#ifndef SIG_H
+#define SIG_H
+
+extern int rb_trap_immediate;
+#define TRAP_BEG (rb_trap_immediate=1)
+#define TRAP_END (rb_trap_immediate=0)
+
+extern int rb_prohibit_interrupt;
+#define DEFER_INTS {rb_prohibit_interrupt++;}
+#define ALLOW_INTS {rb_prohibit_interrupt--; CHECK_INTS;}
+#define ENABLE_INTS {rb_prohibit_interrupt--;}
+
+extern int rb_trap_pending;
+void rb_trap_restore_mask _((void));
+
+#ifdef USE_THREAD
+extern int rb_thread_critical;
+void rb_thread_schedule _((void));
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+extern int rb_thread_pending;
+# define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+ if (rb_thread_pending && !rb_thread_critical) rb_thread_schedule();\
+}
+# else
+/* pseudo preemptive thread switching */
+extern int rb_thread_tick;
+#define THREAD_TICK 500
+# define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+ if (!rb_thread_critical) {\
+ if (rb_thread_tick-- <= 0) {\
+ rb_thread_tick = THREAD_TICK;\
+ rb_thread_schedule();\
+ }\
+ }\
+}
+# endif
+#else
+# define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+}
+#endif
+
+#endif
diff --git a/rubytest.rb b/rubytest.rb
index f0e4bf8c8e..cf583c1dfb 100644
--- a/rubytest.rb
+++ b/rubytest.rb
@@ -1,3 +1,5 @@
+#! ./miniruby -I.
+
require 'rbconfig'
include Config
diff --git a/sample/README b/sample/README
new file mode 100644
index 0000000000..90ac0c7220
--- /dev/null
+++ b/sample/README
@@ -0,0 +1,60 @@
+README this file
+biorhythm.rb biorhythm calculator
+cal.rb cal(1) clone
+cbreak.rb no echo done by ioctl
+clnt.rb socket client
+dbmtest.rb test for dbm
+dir.rb directory access
+dstore.rb object database on dbm
+eval.rb simple evaluator
+export.rb method access example
+exyacc.rb extrace BNF from yacc file
+fact.rb factorial calculator
+fib.awk Fibonacci number (AWK)
+fib.pl Fibonacci number (Perl)
+fib.py Fibonacci number (Python)
+fib.rb Fibonacci number (Ruby)
+fib.scm Fibonacci number (Scheme)
+freq.rb count word occurrence
+from.rb scan mail spool
+fullpath.rb convert ls -lR to fullpath format
+getopts.test test fot getopt.rb
+goodfriday.rb print various christian calendar event.
+inf-ruby.el program to run ruby under emacs
+io.rb io test
+less.rb front end for less
+list.rb stupid object sample
+list2.rb stupid object sample
+list3.rb stupid object sample
+mine.rb simple mine sweeper
+mkproto.rb extract protptype from C
+mpart.rb split file int multi part
+mrshtest.rb test marshal
+observ.rb observer design pattern sample
+occur.pl count word occurrence (Perl)
+occur.rb count word occurrence (Ruby)
+occur2.rb count word occurrence - another style
+philos.rb famous dining philosophers
+pi.rb calculate PI
+rbc.rb interactive ruby, to be removed by irb
+rcs.awk random character stereogram (AWK)
+rcs.rb random character stereogram (Ruby)
+rcs.dat data for random character stereogram
+regx.rb regular expression tester
+ruby-mode.el ruby mode for emacs
+rubydb2x.el ruby debugger support for emacs 19.2x or before
+rubydb3x.el ruby debugger support for emacs 19.3x or later
+sieve.rb sieve of Eratosthenes
+svr.rb socket server
+test.rb test suite used by `make test'
+time.rb /usr/bin/time clone
+tkbiff.rb mail notifier using Tk
+tkbrowse.rb directory browser using Tk
+tkdialog.rb dialog example
+tkfrom.rb scan mail spool using Tk
+tkhello.rb simple Tk example
+tkline.rb simple Tk example
+tktimer.rb stopwatch
+trojan.rb simple tool to find file that may be trojan horse.
+tsvr.rb socket server using thread
+uumerge.rb merge files and uudecode them
diff --git a/sample/cal.rb b/sample/cal.rb
new file mode 100644
index 0000000000..a5f4b4db18
--- /dev/null
+++ b/sample/cal.rb
@@ -0,0 +1,118 @@
+#! /usr/local/bin/ruby
+
+# cal.rb (bsd compatible version): Written by Tadayoshi Funaba 1998
+# $Id: bsdcal.rb,v 1.2 1998/12/01 13:47:40 tadf Exp $
+
+require 'date2'
+
+$tab =
+{
+ 'cn' => true, # China
+ 'de' => 2342032, # Germany (protestant states)
+ 'dk' => 2342032, # Denmark
+ 'es' => 2299161, # Spain
+ 'fi' => 2361390, # Finland
+ 'fr' => 2299227, # France
+ 'gb' => 2361222, # United Kingdom
+ 'gr' => 2423868, # Greece
+ 'hu' => 2301004, # Hungary
+ 'it' => 2299161, # Italy
+ 'jp' => true, # Japan
+ 'no' => 2342032, # Norway
+ 'pl' => 2299161, # Poland
+ 'pt' => 2299161, # Portugal
+ 'ru' => 2421639, # Russia
+ 'se' => 2361390, # Sweden
+ 'us' => 2361222, # United States
+ 'os' => false, # (old style)
+ 'ns' => true # (new style)
+}
+
+$cc = 'gb'
+
+def usage
+ $stderr.puts 'usage: cal [-c iso3166] [-jy] [[month] year]'
+ exit 1
+end
+
+def cal(m, y, gs)
+ for d in 1..31
+ break if jd = Date.exist?(y, m, d, gs)
+ end
+ fst = cur = Date.new(jd, gs)
+ ti = Date::MONTHNAMES[m]
+ ti << ' ' << y.to_s unless $yr
+ mo = ti.center((($w + 1) * 7) - 1) << "\n"
+ mo << ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S'].
+ collect{|x| x.rjust($w)}.join(' ') << "\n"
+ mo << ' ' * (($w + 1) * fst.wday)
+ while cur.mon == fst.mon
+ mo << (if $jd then cur.yday else cur.mday end).to_s.rjust($w)
+ mo << (if (cur += 1).wday != 0 then "\s" else "\n" end)
+ end
+ mo << "\n" * (6 - ((fst.wday + (cur - fst)) / 7))
+ mo
+end
+
+def zip(xs)
+ yr = ''
+ until xs.empty?
+ ln = (if $jd then l, r, *xs = xs; [l, r]
+ else l, c, r, *xs = xs; [l, c, r] end).
+ collect{|x| x.split(/\n/no, -1)}
+ 8.times do
+ yr << ln.collect{|x|
+ x.shift.ljust((($w + 1) * 7) - 1)}.join(' ') << "\n"
+ end
+ end
+ yr
+end
+
+while /^-(.*)$/no =~ $*[0]
+ a = $1
+ if /^c(.+)?$/no =~ a then
+ if $1 then
+ $cc = $1.downcase
+ elsif $*.length >= 2 then
+ $cc = $*[1].downcase
+ $*.shift
+ else
+ usage
+ end
+ else
+ a.scan(/./no) do |c|
+ case c
+ when 'j'; $jd = true
+ when 'y'; $yr = true
+ else usage
+ end
+ end
+ end
+ $*.shift
+end
+usage if (gs = $tab[$cc]).nil?
+case $*.length
+when 0
+ td = Date.today
+ m = td.mon
+ y = td.year
+when 1
+ y = $*[0].to_i
+ $yr = true
+when 2
+ m = $*[0].to_i
+ y = $*[1].to_i
+else
+ usage
+end
+usage unless m.nil? or (1..12) === m
+usage unless y >= -4712
+$w = if $jd then 3 else 2 end
+unless $yr then
+ print cal(m, y, gs)
+else
+ print y.to_s.center(((($w + 1) * 7) - 1) *
+ (if $jd then 2 else 3 end) +
+ (if $jd then 2 else 4 end)), "\n\n",
+ zip((1..12).collect{|m| cal(m, y, gs)}), "\n"
+end
diff --git a/sample/fib.py b/sample/fib.py
new file mode 100644
index 0000000000..8318021d24
--- /dev/null
+++ b/sample/fib.py
@@ -0,0 +1,10 @@
+# calculate Fibonacci(20)
+# for benchmark
+def fib(n):
+ if n<2:
+ return n
+ else:
+ return fib(n-2)+fib(n-1)
+
+print fib(20)
+
diff --git a/sample/fib.scm b/sample/fib.scm
index 8eba75bb9e..5c2b86e656 100644
--- a/sample/fib.scm
+++ b/sample/fib.scm
@@ -3,4 +3,6 @@
n
(+ (fib (- n 2)) (fib (- n 1)))))
-(fib 20)
+(display (fib 20))
+(newline)
+
diff --git a/sample/freq.rb b/sample/freq.rb
index d951591735..4e0206c114 100644
--- a/sample/freq.rb
+++ b/sample/freq.rb
@@ -1,13 +1,13 @@
# word occurrence listing
# usege: ruby freq.rb file..
-freq = {}
+freq = Hash.new(0)
while gets
while sub!(/\w+/, '')
word = $&
- freq[word] +=1
+ freq[word] += 1
end
end
-for word in freq.keys.sort
- printf("%s -- %d\n", word, freq[word])
+for word in freq.keys.sort!
+ print word, " -- ", freq[word], "\n"
end
diff --git a/sample/from.rb b/sample/from.rb
index d39bb70084..93b6c4bade 100644
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -9,8 +9,6 @@ include Kconv
class String
- public :kconv
-
def kconv(code = Kconv::EUC)
Kconv.kconv(self, code, Kconv::AUTO)
end
@@ -32,13 +30,20 @@ if ARGV[0] == '-w'
end
if ARGV.length == 0
- user = ENV['USER']
+ file = ENV['MAIL']
+ user = ENV['USER'] || ENV['USERNAME'] || ENV['LOGNAME']
else
- user = ARGV[0]
+ file = user = ARGV[0]
+ ARGV.clear
end
-[ENV['SPOOLDIR'], '/usr/spool', '/var/spool', '/usr', '/var'].each do |m|
- break if File.exist? ARGV[0] = "#{m}/mail/#{user}"
+if file == nil or !File.exist? file
+ [ENV['SPOOLDIR'], '/usr/spool', '/var/spool', '/usr', '/var'].each do |m|
+ if File.exist? f = "#{m}/mail/#{user}"
+ file = f
+ break
+ end
+ end
end
$outcount = 0;
@@ -63,18 +68,23 @@ def fromout(date, from, subj)
end
from = from.kconv(lang).kjust(28)
subj = subj.kconv(lang).kjust(40)
- printf "%02d/%02d/%02d [%s] %s\n",y,m,d,from,subj
+ printf "%02d/%02d/%02d [%s] %s\n",y%100,m,d,from,subj
$outcount += 1
end
-for file in ARGV
- next if !File.exist?(file)
+if File.exist?(file)
+ atime = File.atime(file)
+ mtime = File.mtime(file)
f = open(file, "r")
- while !f.eof?
- mail = Mail.new(f)
- fromout mail.header['Date'], mail.header['From'], mail.header['Subject']
+ begin
+ until f.eof?
+ mail = Mail.new(f)
+ fromout mail.header['Date'],mail.header['From'],mail.header['Subject']
+ end
+ ensure
+ f.close
+ File.utime(atime, mtime, file)
end
- f.close
end
if $outcount == 0
diff --git a/sample/goodfriday.rb b/sample/goodfriday.rb
new file mode 100644
index 0000000000..f0027ec5dd
--- /dev/null
+++ b/sample/goodfriday.rb
@@ -0,0 +1,48 @@
+#! /usr/local/bin/ruby
+
+# goodfriday.rb: Written by Tadayoshi Funaba 1998
+# $Id: goodfriday.rb,v 1.1 1998/03/08 09:44:44 tadf Exp $
+
+require 'date2'
+
+def easter(y)
+ g = (y % 19) + 1
+ c = (y / 100) + 1
+ x = (3 * c / 4) - 12
+ z = ((8 * c + 5) / 25) - 5
+ d = (5 * y / 4) - x - 10
+ e = (11 * g + 20 + z - x) % 30
+ e += 1 if e == 25 and g > 11 or e == 24
+ n = 44 - e
+ n += 30 if n < 21
+ n = n + 7 - ((d + n) % 7)
+ if n <= 31 then [y, 3, n] else [y, 4, n - 31] end
+end
+
+es = Date.new3(*easter(Time.now.year))
+[[-9*7, 'Septuagesima Sunday'],
+ [-8*7, 'Sexagesima Sunday'],
+ [-7*7, 'Quinquagesima Sunday (Shrove Sunday)'],
+ [-48, 'Shrove Monday'],
+ [-47, 'Shrove Tuesday'],
+ [-46, 'Ash Wednesday'],
+ [-6*7, 'Quadragesima Sunday'],
+ [-3*7, 'Mothering Sunday'],
+ [-2*7, 'Passion Sunday'],
+ [-7, 'Palm Sunday'],
+ [-3, 'Maunday Thursday'],
+ [-2, 'Good Friday'],
+ [-1, 'Easter Eve'],
+ [0, 'Easter Day'],
+ [1, 'Easter Monday'],
+ [7, 'Low Sunday'],
+ [5*7, 'Rogation Sunday'],
+ [39, 'Ascension Day (Holy Thursday)'],
+ [42, 'Sunday after Ascension Day'],
+ [7*7, 'Pentecost (Whitsunday)'],
+ [50, 'Whitmonday'],
+ [8*7, 'Trinity Sunday'],
+ [60, 'Corpus Christi (Thursday after Trinity)']].
+each do |xs|
+ puts ((es + xs.shift).to_s + ' ' + xs.shift)
+end
diff --git a/sample/mkproto.rb b/sample/mkproto.rb
index 97006f9f54..8661240085 100644
--- a/sample/mkproto.rb
+++ b/sample/mkproto.rb
@@ -8,17 +8,17 @@ while gets()
arg.gsub! ' +', ' '
if arg =~ /,/
if arg =~ /(([^*]+) *\** *[\w\d_]+),/
- type = $2.strip!
- args.push $1.strip!
+ type = $2.strip
+ args.push $1.strip
arg = $'
else
type = ""
end
while arg.sub!(/(\** *[\w\d_]+)(,|$)/, "")
- args.push type + " " + $1.strip!
+ args.push type + " " + $1.strip
end
else
- args.push arg.strip!
+ args.push arg.strip
end
end
printf "%s);\n", args.join(', ')
diff --git a/sample/observ.rb b/sample/observ.rb
index f7b1e73137..72e5178b38 100644
--- a/sample/observ.rb
+++ b/sample/observ.rb
@@ -7,25 +7,26 @@ class Tick
include Observable
def initialize
Thread.start do
- while TRUE
+ loop do
sleep 0.999
+ now = Time.now
changed
- notify_observers(Time.now.strftime("%H:%M:%S"))
+ notify_observers(now.hour, now.min, now.sec)
end
end
end
end
class Clock
- def initialize
- @tick = Tick.new
+ def initialize(tick)
+ @tick = tick
@tick.add_observer(self)
end
- def update(time)
- print "\e[8D", time
+ def update(h, m, s)
+ printf "\e[8D%02d:%02d:%02d", h, m, s
STDOUT.flush
end
end
-clock = Clock.new
+clock = Clock.new(Tick.new)
sleep
diff --git a/sample/occur.rb b/sample/occur.rb
index 2141fade38..f489beee17 100644
--- a/sample/occur.rb
+++ b/sample/occur.rb
@@ -1,12 +1,12 @@
# word occurrence listing
# usege: ruby occur.rb file..
-freq = {}
+freq = Hash.new(0)
while gets()
for word in $_.split(/\W+/)
- freq[word] +=1
+ freq[word] += 1
end
end
-for word in freq.keys.sort
- printf("%s -- %d\n", word, freq[word])
+for word in freq.keys.sort!
+ print word, " -- ", freq[word], "\n"
end
diff --git a/sample/rbc.rb b/sample/rbc.rb
index 88a5b2d069..83796255cc 100644
--- a/sample/rbc.rb
+++ b/sample/rbc.rb
@@ -1,9 +1,9 @@
#!/usr/local/bin/ruby
#
# rbc.rb -
-# $Release Version: 0.6 $
-# $Revision: 1.2 $
-# $Date: 1997/11/27 13:46:06 $
+# $Release Version: 0.8 $
+# $Revision: 1.8 $
+# $Date: 1998/03/11 05:43:00 $
# by Keiju ISHITSUKA(Nippon Rational Inc.)
#
# --
@@ -11,46 +11,46 @@
#
# rbc.rb [options] file_name opts
# options:
-# -d ¥Ç¥Ð¥Ã¥°¥â¡¼¥É(ÍøÍѤ·¤Ê¤¤Êý¤¬Îɤ¤¤Ç¤·¤ç¤¦)
-# -m bc¥â¡¼¥É(ʬ¿ô, ¹ÔÎó¤Î·×»»¤¬¤Ç¤­¤Þ¤¹)
-# -r load-module ruby -r ¤ÈƱ¤¸
-# --inspect ·ë²Ì½ÐÎϤËinspect¤òÍѤ¤¤ë(bc¥â¡¼¥É°Ê³°¤Ï¥Ç
-# ¥Õ¥©¥ë¥È).
-# --noinspect ·ë²Ì½ÐÎϤËinspect¤òÍѤ¤¤Ê¤¤.
-# --noreadline readline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤Ê¤¤(¥Ç¥Õ¥©¥ë¥È
-# ¤Ç¤Ïreadline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤è¤¦¤È¤¹¤ë).
+# -d debug mode (not recommended)
+# -f does not read ~/.irbrc
+# -m bc mode (rational/matrix calc)
+# -r load-module same as `ruby -r'
+# --inspect use inspect for result output
+# (default for non-bc mode)
+# --noinspect does not use inspect for result output
+# --noreadline does not use readline library
+# (default: try to use readline)
#
-# Äɲà private method:
-# exit, quit ½ªÎ»¤¹¤ë.
-# inspect(sw = nil) ¥¤¥ó¥¹¥Ú¥¯¥È¥â¡¼¥É¤Î¥È¥°¥ë
-# trace_load(sw = nil) load/require»þ¤Ërbc¤ÎfileÆɤ߹þ¤ßµ¡Ç½¤òÍÑ
-# ¤¤¤ë¥â¡¼¥É¤Î¥¹¥¤¥Ã¥Á(¥Ç¥Õ¥©¥ë¥È¤Ï¥È¥ì¡¼¥¹
-# ¥â¡¼¥É)
+# additional private method (as function):
+# exit, quit terminate the interpreter
+# inspect_mode(sw = nil) toggle inspect mode
+# trace_load(sw = nil) change trace mode for file loading using
+# load/require. (default: trace-mode on)
#
require "e2mmap.rb"
$stdout.sync = TRUE
module BC_APPLICATION__
- RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/ruby/RCS/rbc.rb,v 1.2 1997/11/27 13:46:06 keiju Exp keiju $-'
+ RCS_ID='-$Id: rbc.rb,v 1.8 1998/03/11 05:43:00 keiju Exp keiju $-'
extend Exception2MessageMapper
def_exception :UnrecognizedSwitch, "Unrecognized switch: %s"
- $DEBUG = FALSE
- $INSPECT = nil
-
CONFIG = {}
CONFIG[0] = $0
CONFIG[:USE_READLINE] = TRUE
CONFIG[:LOAD_MODULES] = []
CONFIG[:INSPECT] = nil
- CONFIG[:TRACE_LOAD] = TRUE
+ CONFIG[:TRACE_LOAD] = FALSE
+ CONFIG[:RC] = TRUE
+
+ CONFIG[:DEBUG] = FALSE
while opt = ARGV.shift
case opt
when "-d"
- $DEBUG = TRUE
+ CONFIG[:DEBUG] = TRUE
when "-m"
CONFIG[:INSPECT] = FALSE if CONFIG[:INSPECT].nil?
require "mathn.rb"
@@ -58,6 +58,9 @@ module BC_APPLICATION__
when "-r"
opt = ARGV.shift
CONFIG[:LOAD_MODULES].push opt if opt
+ when "-f"
+ opt = ARGV.shift
+ CONFIG[:RC] = FALSE
when "--inspect"
CONFIG[:INSPECT] = TRUE
when "--noinspect"
@@ -66,7 +69,7 @@ module BC_APPLICATION__
CONFIG[:USE_READLINE] = FALSE
when /^-/
# print UnrecognizedSwitch.inspect, "\n"
- BC.fail UnrecognizedSwitch, opt
+ BC_APPLICATION__.fail UnrecognizedSwitch, opt
else
CONFIG[:USE_READLINE] = FALSE
$0 = opt
@@ -104,7 +107,7 @@ module BC_APPLICATION__
line = line + l
lex(l) if l != "\n"
- print @quoted.inspect, "\n" if $DEBUG
+ print @quoted.inspect, "\n" if CONFIG[:DEBUG]
if @ltype
@io.prompt = format(PROMPTs, @indent, @ltype)
next
@@ -120,9 +123,9 @@ module BC_APPLICATION__
if line != "\n"
begin
if CONFIG[:INSPECT]
- print (cont._=eval(line, bind)).inspect, "\n"
+ print((cont._=eval(line, bind)).inspect, "\n")
else
- print (cont._=eval(line, bind)), "\n"
+ print((cont._=eval(line, bind)), "\n")
end
rescue
# $! = 'exception raised' unless $!
@@ -182,7 +185,8 @@ module BC_APPLICATION__
"case", "class", "def", "do", "for", "if",
"module", "unless", "until", "while", "begin" #, "when"
]
- DEINDENT_CLAUSE = ["end"]
+ DEINDENT_CLAUSE = ["end" #, "when"
+ ]
PARCENT_LTYPE = {
"q" => "\'",
@@ -197,7 +201,7 @@ module BC_APPLICATION__
"<" => ">",
"(" => ")"
}
-
+
def lex_init()
@OP = Trie.new
@OP.def_rules("\0", "\004", "\032"){}
@@ -211,7 +215,7 @@ module BC_APPLICATION__
identify_comment(rests)
end
@OP.def_rule("\n") do
- print "\\n\n" if $DEBUG
+ print "\\n\n" if CONFIG[:DEBUG]
if @lex_state == EXPR_BEG || @lex_state == EXPR_FNAME
@continue = TRUE
else
@@ -220,9 +224,9 @@ module BC_APPLICATION__
end
@OP.def_rules("*", "*=", "**=", "**") {@lex_state = EXPR_BEG}
@OP.def_rules("!", "!=", "!~") {@lex_state = EXPR_BEG}
- @OP.def_rules("=", "==", "===", "=~", "=>") {@lex_state = EXPR_BEG}
- @OP.def_rules("<", "<=", "<=>", "<<", "<=") {@lex_state = EXPR_BEG}
- @OP.def_rules(">", ">=", ">>", ">=") {@lex_state = EXPR_BEG}
+ @OP.def_rules("=", "==", "===", "=~", "<=>") {@lex_state = EXPR_BEG}
+ @OP.def_rules("<", "<=", "<<") {@lex_state = EXPR_BEG}
+ @OP.def_rules(">", ">=", ">>") {@lex_state = EXPR_BEG}
@OP.def_rules("'", '"') do
|op, rests|
@ltype = op
@@ -268,10 +272,14 @@ module BC_APPLICATION__
if rests[0] =~ /[0-9]/
rests.unshift op
identify_number(rests)
+ else
+ # obj.if ¤Ê¤É¤ÎÂбþ
+ identify_identifier(rests, TRUE)
+ @lex_state = EXPR_ARG
end
end
@OP.def_rules("..", "...") {@lex_state = EXPR_BEG}
-
+
lex_int2
end
@@ -280,8 +288,12 @@ module BC_APPLICATION__
@lex_state = EXPR_END
@indent -= 1
end
- @OP.def_rule(":") {}
- @OP.def_rule("::") {@lex_state = EXPR_BEG}
+ @OP.def_rule(":") {|op,rests|
+ identify_identifier(rests, TRUE)
+ }
+ @OP.def_rule("::") {|op,rests|
+ identify_identifier(rests, TRUE);
+ }
@OP.def_rule("/") do
|op, rests|
if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
@@ -343,16 +355,26 @@ module BC_APPLICATION__
identify_identifier(rests)
end
end
+ @OP.def_rule("def", proc{|op, chrs| /\s/ =~ chrs[0]}) do
+ |op, rests|
+ @indent += 1
+ @lex_state = EXPR_END
+ until rests[0] == "\n" or rests[0] == ";"
+ rests.shift
+ end
+ end
@OP.def_rule("") do
|op, rests|
- printf "match: start %s: %s", op, rests.inspect if $DEBUG
+ printf "MATCH: start %s: %s\n", op, rests.inspect if CONFIG[:DEBUG]
if rests[0] =~ /[0-9]/
identify_number(rests)
elsif rests[0] =~ /[\w_]/
identify_identifier(rests)
end
- printf "match: end %s: %s", op, rests.inspect if $DEBUG
+ printf "MATCH: end %s: %s\n", op, rests.inspect if CONFIG[:DEBUG]
end
+
+ p @OP if CONFIG[:DEBUG]
end
def lex(l)
@@ -380,9 +402,9 @@ module BC_APPLICATION__
until chrs.empty?
@space_seen = FALSE
- printf "perse: %s\n", chrs.join("") if $DEBUG
+ printf "perse: %s\n", chrs.join("") if CONFIG[:DEBUG]
@OP.match(chrs)
- printf "lex_state: %s continue: %s\n", @lex_state.id2name, @continue if $DEBUG
+ printf "lex_state: %s continue: %s\n", @lex_state.id2name, @continue if CONFIG[:DEBUG]
end
end
@@ -421,11 +443,11 @@ module BC_APPLICATION__
end
end
- def identify_identifier(chrs)
+ def identify_identifier(chrs, escaped = FALSE)
token = ""
- token.concat chrs.shift if chrs[0] =~ /[$@]/
+ token.concat chrs.shift if chrs[0] =~ /[$@]/ or escaped
while (ch = chrs.shift) =~ /\w|_/
- print ":", ch, ":" if $DEBUG
+ print ":", ch, ":" if CONFIG[:DEBUG]
token.concat ch
end
chrs.unshift ch
@@ -436,12 +458,12 @@ module BC_APPLICATION__
end
# fix token
- if token =~ /^[$@]/
+ if token =~ /^[$@]/ or escaped
@lex_state = EXPR_END
return
end
- print token, "\n" if $DEBUG
+ print token, "\n" if CONFIG[:DEBUG]
if state = CLAUSE_STATE_TRANS[token]
if @lex_state != EXPR_BEG and token =~ /^(if|unless|while|until)/
# ½¤¾þ»Ò
@@ -624,14 +646,9 @@ module BC_APPLICATION__
@preproc = preproc
@postproc = postproc
end
-
- def preproc(p)
- @preproc = p
- end
-
- def postproc(p)
- @postproc = p
- end
+
+ attr :preproc, TRUE
+ attr :postproc, TRUE
def search(chrs, opt = nil)
return self if chrs.empty?
@@ -649,10 +666,29 @@ module BC_APPLICATION__
end
def create_subnode(chrs, preproc = nil, postproc = nil)
+ if chrs.empty?
+ if @postproc
+ p node
+ Trie.fail ErrNodeAlreadyExists
+ else
+ print "Warn: change abstruct node to real node\n" if CONFIG[:DEBUG]
+ @preproc = preproc
+ @postproc = postproc
+ end
+ return self
+ end
+
ch = chrs.shift
if node = @Tree[ch]
if chrs.empty?
- Trie.fail ErrNodeAlreadyExists
+ if node.postproc
+ p node
+ Trie.fail ErrNodeAlreadyExists
+ else
+ print "Warn: change abstruct node to real node\n" if CONFIG[:DEBUG]
+ node.preproc = preproc
+ node.postproc = postproc
+ end
else
node.create_subnode(chrs, preproc, postproc)
end
@@ -669,10 +705,10 @@ module BC_APPLICATION__
end
def match(chrs, op = "")
- print "match: ", chrs, ":", op, "\n" if $DEBUG
+ print "match>: ", chrs, "op:", op, "\n" if CONFIG[:DEBUG]
if chrs.empty?
if @preproc.nil? || @preproc.call(op, chrs)
- printf "op1: %s\n", op if $DEBUG
+ printf "op1: %s\n", op if CONFIG[:DEBUG]
@postproc.call(op, chrs)
""
else
@@ -683,23 +719,23 @@ module BC_APPLICATION__
if node = @Tree[ch]
if ret = node.match(chrs, op+ch)
return ch+ret
- elsif @postproc and @preproc.nil? || @preproc.call(op, chrs)
- chrs.unshift ch
- printf "op2: %s\n", op if $DEBUG
- @postproc.call(op, chrs)
- return ""
else
chrs.unshift ch
- return nil
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+ printf "op2: %s\n", op.inspect if CONFIG[:DEBUG]
+ @postproc.call(op, chrs)
+ return ""
+ else
+ return nil
+ end
end
else
+ chrs.unshift ch
if @postproc and @preproc.nil? || @preproc.call(op, chrs)
- printf "op3: %s\n", op if $DEBUG
- chrs.unshift ch
+ printf "op3: %s\n", op if CONFIG[:DEBUG]
@postproc.call(op, chrs)
return ""
else
- chrs.unshift ch
return nil
end
end
@@ -712,14 +748,9 @@ module BC_APPLICATION__
end
def def_rule(token, preproc = nil, postproc = nil)
- node = search(token, :CREATE)
-# print node.inspect, "\n" if $DEBUG
- node.preproc(preproc)
- if iterator?
- node.postproc(proc)
- elsif postproc
- node.postproc(postproc)
- end
+# print node.inspect, "\n" if CONFIG[:DEBUG]
+ postproc = proc if iterator?
+ node = create(token, preproc, postproc)
end
def def_rules(*tokens)
@@ -731,24 +762,28 @@ module BC_APPLICATION__
end
end
- def preporc(token)
+ def preporc(token, proc)
node = search(token)
- node.preproc proc
+ node.preproc=proc
end
def postproc(token)
- node = search(token)
- node.postproc proc
+ node = search(token, proc)
+ node.postproc=proc
end
- def search(token, opt = nil)
- @head.search(token.split(//), opt)
+ def search(token)
+ @head.search(token.split(//))
+ end
+
+ def create(token, preproc = nil, postproc = nil)
+ @head.create_subnode(token.split(//), preproc, postproc)
end
def match(token)
token = token.split(//) if token.kind_of?(String)
ret = @head.match(token)
- printf "match end: %s:%s", ret, token.inspect if $DEBUG
+ printf "match end: %s:%s", ret, token.inspect if CONFIG[:DEBUG]
ret
end
@@ -795,25 +830,26 @@ module BC_APPLICATION__
module CONTEXT
def _=(value)
- @_ = value
+ CONFIG[:_] = value
+ eval "_=BC_APPLICATION__::CONFIG[:_]", CONFIG[:BIND]
end
- def _
- @_
- end
+# def _
+# eval "_", CONFIG[:BIND]
+# end
def quit
exit
end
def trace_load(opt = nil)
- if opt
- @Trace_require = opt
+ if !opt.nil?
+ CONFIG[:TRACE_LOAD] = opt
else
- @Trace_require = !@Trace_require
+ CONFIG[:TRACE_LOAD] = !CONFIG[:TRACE_LOAD]
end
- print "Switch to load/require #{unless @Trace_require; ' non';end} trace mode.\n"
- if @Trace_require
+ print "Switch to load/require #{unless CONFIG[:TRACE_LOAD]; ' non';end} trace mode.\n"
+ if CONFIG[:TRACE_LOAD]
eval %{
class << self
alias load rbc_load
@@ -828,7 +864,7 @@ module BC_APPLICATION__
end
}
end
- @Trace_require
+ CONFIG[:TRACE_LOAD]
end
alias rbc_load_org load
@@ -845,17 +881,18 @@ module BC_APPLICATION__
case file_name
when /\.rb$/
if load_sub(file_name)
- $:.push file_name
+ $".push file_name
return true
end
when /\.(so|o|sl)$/
- require_org(file_name)
+ rbc_require_org(file_name)
end
if load_sub(f = file_name + ".rb")
- $:.push f
+ $".push f
+ return true
end
- require(file_name)
+ rbc_require_org(file_name)
end
def load_sub(fn)
@@ -874,19 +911,34 @@ module BC_APPLICATION__
return false
end
- def inspect(opt = nil)
+ def inspect_mode(opt = nil)
if opt
CONFIG[:INSPECT] = opt
else
- CONFIG[:INSPECT] = !$INSPECT
+ CONFIG[:INSPECT] = !CONFIG[:INSPECT]
end
- print "Switch to#{unless $INSPECT; ' non';end} inspect mode.\n"
- $INSPECT
+ print "Switch to#{unless CONFIG[:INSPECT]; ' non';end} inspect mode.\n"
+ CONFIG[:INSPECT]
end
- def run
- CONFIG[:BIND] = proc
+ def run(bind)
+ CONFIG[:BIND] = bind
+ if CONFIG[:RC]
+ rc = File.expand_path("~/.irbrc")
+ if File.exists?(rc)
+ begin
+ load rc
+ rescue
+ print "load error: #{rc}\n"
+ print $!.type, ": ", $!, "\n"
+ for err in $@[0, $@.size - 2]
+ print "\t", err, "\n"
+ end
+ end
+ end
+ end
+
if CONFIG[:TRACE_LOAD]
trace_load true
end
@@ -898,7 +950,7 @@ module BC_APPLICATION__
print $@[0], ":", $!.type, ": ", $!, "\n"
end
end
-
+
if !$0.equal?(CONFIG[0])
io = FileInputMethod.new($0)
elsif defined? Readline
@@ -959,4 +1011,5 @@ module BC_APPLICATION__
end
extend BC_APPLICATION__::CONTEXT
-run{}
+run(binding)
+
diff --git a/sample/sieve.rb b/sample/sieve.rb
index 03ff8a67f4..5e9f792d81 100644
--- a/sample/sieve.rb
+++ b/sample/sieve.rb
@@ -1,7 +1,6 @@
# sieve of Eratosthenes
sieve = []
-if ! max = ARGV.shift; max = 100; end
-max = max.to_i
+max = Integer(ARGV.shift || 100)
print "1"
for i in 2 .. max
diff --git a/sample/test.rb b/sample/test.rb
index 0a9d41c2ed..f28327659e 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -24,6 +24,24 @@ end
# make sure conditional operators work
+check "assignment"
+
+a=[]; a[0] ||= "bar";
+ok(a[0] == "bar")
+h={}; h["foo"] ||= "bar";
+ok(h["foo"] == "bar")
+
+aa = 5
+aa ||= 25
+ok(aa == 5)
+bb ||= 25
+ok(bb == 25)
+cc &&=33
+ok(cc == nil)
+cc = 5
+cc &&=44
+ok(cc == 44)
+
check "condition"
$x = '0';
@@ -109,8 +127,8 @@ tmp.close
$bad = false
tmp = open("while_tmp", "r")
while tmp.gets()
- next if /vt100/;
- $bad = 1 if /vt100/;
+ next if /vt100/;
+ $bad = 1 if /vt100/;
end
ok(!(!tmp.eof? || /vt100/ || $bad))
tmp.close
@@ -240,6 +258,18 @@ while true
end
ok(!$bad)
+ok(catch(:foo) {
+ loop do
+ loop do
+ throw :foo, true
+ break
+ end
+ break
+ ok(false) # should no reach here
+ end
+ false
+ })
+
check "array"
ok([1, 2] + [3, 4] == [1, 2, 3, 4])
ok([1, 2] * 2 == [1, 2, 1, 2])
@@ -265,11 +295,20 @@ ok($x[0] == -1 && $x[1] == 10)
$x[-1, 1] = 20
ok($x[-1] == 20 && $x.pop == 20)
+# array and/or
+ok(([1,2,3]&[2,4,6]) == [2])
+ok(([1,2,3]|[2,4,6]) == [1,2,3,4,6])
+
# compact
$x = [nil, 1, nil, nil, 5, nil, nil]
$x.compact!
ok($x == [1, 5])
+# uniq
+$x = [1, 1, 4, 2, 5, 4, 5, 1, 2]
+$x.uniq!
+ok($x == [1, 4, 2, 5])
+
# empty?
ok(!$x.empty?)
$x = []
@@ -287,7 +326,8 @@ ok($x == [7,5,3,2,1])
# split test
$x = "The Book of Mormon"
-ok($x.split(//).reverse!.join == "nomroM fo kooB ehT")
+ok($x.split(//).reverse!.join == $x.reverse)
+ok($x.reverse == $x.reverse!)
ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1")
$x = "a b c d"
ok($x.split == ['a', 'b', 'c', 'd'])
@@ -296,7 +336,7 @@ ok(defined? "a".chomp)
ok("abc".scan(/./) == ["a", "b", "c"])
ok("1a2b3c".scan(/(\d.)/) == [["1a"], ["2b"], ["3c"]])
# non-greedy match
-ok("a=12;b=22".scan(/(.*?)=(\d*?);?/) == [["a", "12"], ["b", "22"]])
+ok("a=12;b=22".scan(/(.*?)=(\d*);?/) == [["a", "12"], ["b", "22"]])
$x = [1]
ok(($x * 5).join(":") == '1:1:1:1:1')
@@ -374,17 +414,6 @@ tt{|i| break if i == 5}
ok(i == 5)
# iterator break/redo/next/retry
-unless defined? loop
- def loop
- while true
- yield
- end
- end
- ok(false)
-else
- ok(true)
-end
-
done = true
loop{
break
@@ -431,6 +460,76 @@ end
ok($x.size == 10)
ok($x == [1, 2, 3, 1, 2, 3, 4, 5, 6, 7])
+# append method to built-in class
+class Array
+ def iter_test1
+ collect{|e| [e, yield(e)]}.sort{|a,b|a[1]<=>b[1]}
+ end
+ def iter_test2
+ a = collect{|e| [e, yield(e)]}
+ a.sort{|a,b|a[1]<=>b[1]}
+ end
+end
+$x = [[1,2],[3,4],[5,6]]
+ok($x.iter_test1{|x|x} == $x.iter_test2{|x|x})
+
+class IterTest
+ def initialize(e); @body = e; end
+
+ def each0(&block); @body.each(&block); end
+ def each1(&block); @body.each { |*x| block.call(*x) } end
+ def each2(&block); @body.each { |*x| block.call(x) } end
+ def each3(&block); @body.each { |x| block.call(*x) } end
+ def each4(&block); @body.each { |x| block.call(x) } end
+ def each5; @body.each { |*x| yield(*x) } end
+ def each6; @body.each { |*x| yield(x) } end
+ def each7; @body.each { |x| yield(*x) } end
+ def each8; @body.each { |x| yield(x) } end
+end
+
+IterTest.new([0]).each0 { |x| $x = x }
+ok($x == 0)
+IterTest.new([1]).each1 { |x| $x = x }
+ok($x == 1)
+IterTest.new([2]).each2 { |x| $x = x }
+ok($x == [2])
+IterTest.new([3]).each3 { |x| $x = x }
+ok($x == 3)
+IterTest.new([4]).each4 { |x| $x = x }
+ok($x == 4)
+IterTest.new([5]).each5 { |x| $x = x }
+ok($x == 5)
+IterTest.new([6]).each6 { |x| $x = x }
+ok($x == [6])
+IterTest.new([7]).each7 { |x| $x = x }
+ok($x == 7)
+IterTest.new([8]).each8 { |x| $x = x }
+ok($x == 8)
+
+IterTest.new([[0]]).each0 { |x| $x = x }
+ok($x == [0])
+IterTest.new([[1]]).each1 { |x| $x = x }
+ok($x == 1)
+IterTest.new([[2]]).each2 { |x| $x = x }
+ok($x == [2])
+IterTest.new([[3]]).each3 { |x| $x = x }
+ok($x == 3)
+IterTest.new([[4]]).each4 { |x| $x = x }
+ok($x == [4])
+IterTest.new([[5]]).each5 { |x| $x = x }
+ok($x == 5)
+IterTest.new([[6]]).each6 { |x| $x = x }
+ok($x == [6])
+IterTest.new([[7]]).each7 { |x| $x = x }
+ok($x == 7)
+IterTest.new([[8]]).each8 { |x| $x = x }
+ok($x == [8])
+
+IterTest.new([[0,0]]).each0 { |x| $x = x }
+ok($x == [0,0])
+IterTest.new([[8,8]]).each8 { |x| $x = x }
+ok($x == [8,8])
+
check "bignum"
def fact(n)
return 1 if n == 0
@@ -482,7 +581,9 @@ ok($good)
$good = true;
for i in 4000..4096
n1 = 1 << i;
- $good = false if ((n1**2-1) / (n1+1) != (n1-1))
+ if (n1**2-1) / (n1+1) != (n1-1)
+ $good = false
+ end
end
ok($good)
@@ -491,9 +592,9 @@ check "string & char"
ok("abcd" == "abcd")
ok("abcd" =~ "abcd")
ok("abcd" === "abcd")
-ok(("abc" =~ /^$/) == false)
-ok(("abc\n" =~ /^$/) == false)
-ok(("abc" =~ /^d*$/) == false)
+ok("abc" !~ /^$/)
+ok("abc\n" !~ /^$/)
+ok("abc" !~ /^d*$/)
ok(("abc" =~ /d*$/) == 3)
ok("" =~ /^$/)
ok("\n" =~ /^$/)
@@ -539,6 +640,8 @@ ok(?\M-\C-a == 129)
ok("a".upcase![0] == ?A)
ok("A".downcase![0] == ?a)
ok("abc".tr!("a-z", "A-Z") == "ABC")
+ok("aabbcccc".tr_s!("a-z", "A-Z") == "ABC")
+ok("abc".tr!("0-9", "A-Z") == nil)
ok("abcc".squeeze!("a-z") == "abc")
ok("abcd".delete!("bc") == "ad")
@@ -571,10 +674,13 @@ ok(a == 1)
a, *b = 1, 2, 3
ok(a == 1 && b == [2, 3])
+a, (b, c), d = 1, [2, 3], 4
+ok(a == 1 && b == 2 && c == 3 && d == 4)
+
*a = 1, 2, 3
ok(a == [1, 2, 3])
-*a = 1..3
+*a = 1..3 # array conversion
ok(a == [1, 2, 3])
check "call"
@@ -614,14 +720,14 @@ ok($proc.call(2) == 4)
ok($proc.call(3) == 6)
proc{
- iii=5 # dynamic local variable
+ iii=5 # nested local variable
$proc = proc{|i|
iii = i
}
$proc2 = proc {
- $x = iii # dynamic variables shared by procs
+ $x = iii # nested variables shared by procs
}
- # scope of dynamic variables
+ # scope of nested variables
ok(defined?(iii))
}.call
ok(!defined?(iii)) # out of scope
@@ -649,9 +755,7 @@ if defined? Process.kill
rescue
x = $!
end
- ok(x && x =~ /Interrupt/)
-else
- ok(false)
+ ok(x && /Interrupt/ =~ x)
end
check "eval"
@@ -691,8 +795,8 @@ def test_ev
end
$x = test_ev
-ok(eval("local1", $x) == "local1") # static local var
-ok(eval("local2", $x) == "local2") # dynamic local var
+ok(eval("local1", $x) == "local1") # normal local var
+ok(eval("local2", $x) == "local2") # nested local var
$bad = true
begin
p eval("local1")
@@ -716,6 +820,51 @@ rescue NameError # must raise error
end
ok(!$bad)
+x = proc{}
+eval "i4 = 1", x
+ok(eval("i4", x) == 1)
+x = proc{proc{}}.call
+eval "i4 = 22", x
+ok(eval("i4", x) == 22)
+$x = []
+x = proc{proc{}}.call
+eval "(0..9).each{|i5| $x[i5] = proc{i5*2}}", x
+ok($x[4].call == 8)
+
+x = binding
+eval "i = 1", x
+ok(eval("i", x) == 1)
+x = proc{binding}.call
+eval "i = 22", x
+ok(eval("i", x) == 22)
+$x = []
+x = proc{binding}.call
+eval "(0..9).each{|i5| $x[i5] = proc{i5*2}}", x
+ok($x[4].call == 8)
+
+proc {
+ p = binding
+ eval "foo11 = 1", p
+ proc{foo11=22}.call
+ ok(eval("foo11", p) == eval("foo11"))
+ ok(eval("foo11") == 1)
+}.call
+
+p1 = proc{i6 = 0; proc{i6}}.call
+ok(p1.call == 0)
+eval "i6=5", p1
+ok(p1.call == 5)
+ok(!defined?(i6))
+
+p1 = proc{i6 = 0; proc{i6}}.call
+i6 = nil
+ok(p1.call == 0)
+eval "i6=1", p1
+ok(p1.call == 1)
+eval "i6=5", p1
+ok(p1.call == 5)
+ok(i6 == nil)
+
check "system"
ok(`echo foobar` == "foobar\n")
ok(`./ruby -e 'print "foobar"'` == 'foobar')
@@ -766,6 +915,14 @@ ok(done)
File.unlink "script_tmp" or `/bin/rm -f "script_tmp"`
File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"`
+$bad = false
+for script in Dir["{lib,sample}/*.rb"]
+ unless `./ruby -c #{script}`.chomp == "Syntax OK"
+ $bad = true
+ end
+end
+ok(!$bad)
+
check "const"
TEST1 = 1
TEST2 = 2
@@ -809,6 +966,11 @@ rescue
ok true
end
+check "marshal"
+$x = [1,2,3,[4,5,"foo"],{1=>"bar"},2.5,fact(30)]
+$y = Marshal.dump($x)
+ok($x == Marshal.load($y))
+
check "pack"
$format = "c2x5CCxsdila6";
diff --git a/sample/trojan.rb b/sample/trojan.rb
index 2024da0908..edf8ee63ce 100644
--- a/sample/trojan.rb
+++ b/sample/trojan.rb
@@ -2,10 +2,10 @@
path = ENV['PATH'].split(/:/)
for dir in path
- if File.d(dir)
+ if File.directory?(dir)
for f in d = Dir.open(dir)
fpath = dir+"/"+f
- if File.f(fpath) && (File.stat(fpath).mode & 022) != 0
+ if File.file?(fpath) && (File.stat(fpath).mode & 022) != 0
printf("file %s is writable from other users\n", fpath)
end
end
diff --git a/sample/tsvr.rb b/sample/tsvr.rb
index fbc6545bb5..d6a5620d11 100644
--- a/sample/tsvr.rb
+++ b/sample/tsvr.rb
@@ -13,7 +13,7 @@ while TRUE
ns = gs.accept
print(ns, " is accepted\n")
Thread.start do
- s = ns # save to dynamic variable
+ s = ns # save to thread-local variable
while s.gets
s.write($_)
end
diff --git a/signal.c b/signal.c
index e5621b4ec1..d7ce4921b2 100644
--- a/signal.c
+++ b/signal.c
@@ -9,16 +9,25 @@
************************************************/
#include "ruby.h"
-#include "sig.h"
+#include "rubysig.h"
#include <signal.h>
#include <stdio.h>
+#ifdef __BEOS__
+#undef SIGBUS
+#endif
+
#ifndef NSIG
-#ifdef DJGPP
-#define NSIG SIGMAX
-#else
-#define NSIG (_SIGMAX + 1) /* For QNX */
+# ifdef DJGPP
+# define NSIG SIGMAX
+# else
+# define NSIG (_SIGMAX + 1) /* For QNX */
+# endif
#endif
+
+#ifdef USE_CWGUSI
+# undef NSIG
+# define NSIG __signal_max
#endif
static struct signals {
@@ -171,31 +180,33 @@ signm2signo(nm)
}
VALUE
-f_kill(argc, argv)
+rb_f_kill(argc, argv)
int argc;
VALUE *argv;
{
+#ifdef USE_CWGUSI
+ rb_notimplement();
+#else
+ int negative = 0;
int sig;
int i;
char *s;
rb_secure(2);
if (argc < 2)
- ArgError("wrong # of arguments -- kill(sig, pid...)");
+ rb_raise(rb_eArgError, "wrong # of arguments -- kill(sig, pid...)");
switch (TYPE(argv[0])) {
case T_FIXNUM:
sig = FIX2UINT(argv[0]);
if (sig >= NSIG) {
s = rb_id2name(sig);
- if (!s) ArgError("Bad signal");
+ if (!s) rb_raise(rb_eArgError, "Bad signal");
goto str_signal;
}
break;
case T_STRING:
- {
- int negative = 0;
-
+ {
s = RSTRING(argv[0])->ptr;
if (s[0] == '-') {
negative++;
@@ -205,7 +216,7 @@ f_kill(argc, argv)
if (strncmp("SIG", s, 3) == 0)
s += 3;
if((sig = signm2signo(s)) == 0)
- ArgError("Unrecognized signal name `%s'", s);
+ rb_raise(rb_eArgError, "Unrecognized signal name `%s'", s);
if (negative)
sig = -sig;
@@ -213,7 +224,8 @@ f_kill(argc, argv)
break;
default:
- ArgError("bad signal type %s", rb_class2name(CLASS_OF(argv[0])));
+ rb_raise(rb_eArgError, "bad signal type %s",
+ rb_class2name(CLASS_OF(argv[0])));
break;
}
@@ -237,23 +249,26 @@ f_kill(argc, argv)
}
}
return INT2FIX(i-1);
+#endif /* USE_CWGUSI */
}
static VALUE trap_list[NSIG];
static int trap_pending_list[NSIG];
-int trap_pending;
-int trap_immediate;
-int prohibit_interrupt;
+int rb_trap_pending;
+int rb_trap_immediate;
+int rb_prohibit_interrupt;
void
-gc_mark_trap_list()
+rb_gc_mark_trap_list()
{
+#ifndef MACOS_UNUSE_SIGNAL
int i;
for (i=0; i<NSIG; i++) {
if (trap_list[i])
- gc_mark(trap_list[i]);
+ rb_gc_mark(trap_list[i]);
}
+#endif /* MACOS_UNUSE_SIGNAL */
}
#ifdef POSIX_SIGNAL
@@ -271,31 +286,32 @@ posix_signal(signum, handler)
}
#endif
+#ifdef USE_THREAD
+# define rb_interrupt rb_thread_interrupt
+# define rb_trap_eval rb_thread_trap_eval
+#endif
+
static RETSIGTYPE
sighandle(sig)
int sig;
{
if (sig >= NSIG ||(sig != SIGINT && !trap_list[sig]))
- Bug("trap_handler: Bad signal %d", sig);
+ rb_bug("trap_handler: Bad signal %d", sig);
#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
signal(sig, sighandle);
#endif
- if (trap_immediate) {
- trap_immediate = 0;
+ if (rb_trap_immediate) {
+ rb_trap_immediate = 0;
if (sig == SIGINT && !trap_list[SIGINT]) {
-#ifdef THREAD
- thread_interrupt();
-#else
rb_interrupt();
-#endif
}
rb_trap_eval(trap_list[sig], sig);
- trap_immediate = 1;
+ rb_trap_immediate = 1;
}
else {
- trap_pending++;
+ rb_trap_pending++;
trap_pending_list[sig]++;
}
}
@@ -305,7 +321,7 @@ static RETSIGTYPE
sigbus(sig)
int sig;
{
- Bug("Bus Error");
+ rb_bug("Bus Error");
}
#endif
@@ -314,41 +330,42 @@ static RETSIGTYPE
sigsegv(sig)
int sig;
{
- Bug("Segmentation fault");
+ rb_bug("Segmentation fault");
}
#endif
void
rb_trap_exit()
{
- if (trap_list[0])
- rb_eval_cmd(trap_list[0], ary_new3(1, INT2FIX(0)));
+#ifndef MACOS_UNUSE_SIGNAL
+ if (trap_list[0]) {
+ rb_eval_cmd(trap_list[0], rb_ary_new3(1, INT2FIX(0)));
+ }
+#endif
}
void
rb_trap_exec()
{
+#ifndef MACOS_UNUSE_SIGNAL
int i;
for (i=0; i<NSIG; i++) {
if (trap_pending_list[i]) {
trap_pending_list[i] = 0;
if (i == SIGINT && trap_list[SIGINT] == 0) {
-#ifdef THREAD
- thread_interrupt();
-#else
rb_interrupt();
-#endif
return;
}
rb_trap_eval(trap_list[i], i);
}
}
- trap_pending = 0;
+#endif /* MACOS_UNUSE_SIGNAL */
+ rb_trap_pending = 0;
}
struct trap_arg {
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
# ifdef HAVE_SIGPROCMASK
sigset_t mask;
# else
@@ -358,6 +375,12 @@ struct trap_arg {
VALUE sig, cmd;
};
+# ifdef HAVE_SIGPROCMASK
+static sigset_t trap_last_mask;
+# else
+static int trap_last_mask;
+# endif
+
static RETSIGTYPE
sigexit()
{
@@ -415,17 +438,17 @@ trap(arg)
s += 3;
sig = signm2signo(s);
if (sig == 0 && strcmp(s, "EXIT") != 0)
- ArgError("Invalid signal SIG%s", s);
+ rb_raise(rb_eArgError, "Invalid signal SIG%s", s);
}
else {
sig = NUM2INT(arg->sig);
}
if (sig < 0 || sig > NSIG) {
- ArgError("Invalid signal no %d", sig);
+ rb_raise(rb_eArgError, "Invalid signal no %d", sig);
}
-#if defined(THREAD) && defined(HAVE_SETITIMER) && !defined(__BOW__)
+#if defined(USE_THREAD) && defined(HAVE_SETITIMER) && !defined(__BOW__)
if (sig == SIGVTALRM) {
- ArgError("SIGVTALRM reserved for Thread; cannot set handler");
+ rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; cannot set handler");
}
#endif
if (func == SIG_DFL) {
@@ -455,7 +478,7 @@ trap(arg)
trap_list[sig] = command;
/* enable at least specified signal. */
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
#ifdef HAVE_SIGPROCMASK
sigdelset(&arg->mask, sig);
#else
@@ -465,8 +488,8 @@ trap(arg)
return old;
}
-#ifndef NT
-static void
+#if !defined(NT) && !defined(USE_CWGUSI)
+static VALUE
trap_ensure(arg)
struct trap_arg *arg;
{
@@ -476,11 +499,25 @@ trap_ensure(arg)
#else
sigsetmask(arg->mask);
#endif
+ trap_last_mask = arg->mask;
+ return 0;
}
#endif
+void
+rb_trap_restore_mask()
+{
+#ifndef NT
+# ifdef HAVE_SIGPROCMASK
+ sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
+# else
+ sigsetmask(trap_last_mask);
+# endif
+#endif
+}
+
static VALUE
-f_trap(argc, argv)
+rb_f_trap(argc, argv)
int argc;
VALUE *argv;
{
@@ -488,18 +525,18 @@ f_trap(argc, argv)
rb_secure(2);
if (argc == 0 || argc > 2) {
- ArgError("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}");
+ rb_raise(rb_eArgError, "wrong # of arguments -- trap(sig, cmd)/trap(sig){...}");
}
arg.sig = argv[0];
if (argc == 1) {
- arg.cmd = f_lambda();
+ arg.cmd = rb_f_lambda();
}
else if (argc == 2) {
arg.cmd = argv[1];
}
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
/* disable interrupt */
# ifdef HAVE_SIGPROCMASK
sigfillset(&arg.mask);
@@ -508,7 +545,7 @@ f_trap(argc, argv)
arg.mask = sigblock(~0);
# endif
- return rb_ensure(trap, &arg, trap_ensure, &arg);
+ return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
#else
return trap(&arg);
#endif
@@ -517,9 +554,8 @@ f_trap(argc, argv)
void
Init_signal()
{
- extern VALUE mKernel;
-
- rb_define_global_function("trap", f_trap, -1);
+#ifndef MACOS_UNUSE_SIGNAL
+ rb_define_global_function("trap", rb_f_trap, -1);
#ifdef POSIX_SIGNAL
posix_signal(SIGINT, sighandle);
#else
@@ -531,4 +567,5 @@ Init_signal()
#ifdef SIGSEGV
signal(SIGSEGV, sigsegv);
#endif
+#endif /* MACOS_UNUSE_SIGNAL */
}
diff --git a/sprintf.c b/sprintf.c
index 7862a469e8..3c09a8ed2a 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -6,14 +6,14 @@
$Date$
created at: Fri Oct 15 10:39:26 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <ctype.h>
-static void fmt_setup();
+static void fmt_setup _((char*,char,int,int,int));
static char*
remove_sign_bits(str, base)
@@ -23,20 +23,21 @@ remove_sign_bits(str, base)
char *s, *t, *end;
s = t = str;
+ end = str + strlen(str);
if (base == 16) {
x_retry:
switch (*t) {
- case 'c':
- *t = '8';
+ case 'c': case 'C':
+ *t = '4';
break;
- case 'd':
- *t = '9';
+ case 'd': case 'D':
+ *t = '5';
break;
- case 'e':
+ case 'e': case 'E':
*t = '2';
break;
- case 'f':
+ case 'f': case 'F':
if (t[1] > '8') {
t++;
goto x_retry;
@@ -99,32 +100,16 @@ remove_sign_bits(str, base)
return str;
}
-double big2dbl();
-#ifndef atof
-double atof();
-#endif
-
-VALUE
-f_sprintf(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fmt;
- char *buf, *p, *end;
- int blen, bsiz;
- VALUE result;
+double rb_big2dbl _((VALUE));
#define FNONE 0
#define FSHARP 1
#define FMINUS 2
#define FPLUS 4
#define FZERO 8
-#define FWIDTH 16
-#define FPREC 32
-
- int width = 0, prec = 0, flags = FNONE;
- VALUE str;
-
+#define FSPACE 16
+#define FWIDTH 32
+#define FPREC 64
#define CHECK(l) {\
while (blen + (l) >= bsiz) {\
@@ -140,17 +125,30 @@ f_sprintf(argc, argv)
}
#define GETARG() \
- ((argc == 0)?(ArgError("too few argument."),0):(argc--,((argv++)[0])))
+ ((argc == 0)?(rb_raise(rb_eArgError, "too few argument."),0):(argc--,((argv++)[0])))
- fmt = GETARG();
- Check_Type(fmt, T_STRING);
+VALUE
+rb_f_sprintf(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE fmt;
+ char *buf, *p, *end;
+ int blen, bsiz;
+ VALUE result;
+
+ int width, prec, flags = FNONE;
+ VALUE tmp;
+ VALUE str;
+ fmt = GETARG();
+ p = str2cstr(fmt, &blen);
+ end = p + blen;
blen = 0;
bsiz = 120;
buf = ALLOC_N(char, bsiz);
- end = RSTRING(fmt)->ptr + RSTRING(fmt)->len;
- for (p = RSTRING(fmt)->ptr; p < end; p++) {
+ for (; p < end; p++) {
char *t;
for (t = p; t < end && *t != '%'; t++) ;
@@ -162,16 +160,18 @@ f_sprintf(argc, argv)
}
p = t + 1; /* skip `%' */
+ width = prec = -1;
retry:
switch (*p) {
default:
- if (isprint(*p))
- ArgError("malformed format string - %%%c", *p);
+ if (ISPRINT(*p))
+ rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
else
- ArgError("malformed format string");
+ rb_raise(rb_eArgError, "malformed format string");
break;
case ' ':
+ flags |= FSPACE;
p++;
goto retry;
@@ -199,51 +199,50 @@ f_sprintf(argc, argv)
case '5': case '6': case '7': case '8': case '9':
flags |= FWIDTH;
width = 0;
- for (; p < end && isdigit(*p); p++) {
+ for (; p < end && ISDIGIT(*p); p++) {
width = 10 * width + (*p - '0');
}
if (p >= end) {
- ArgError("malformed format string - %%[0-9]");
+ rb_raise(rb_eArgError, "malformed format string - %%[0-9]");
}
goto retry;
case '*':
if (flags & FWIDTH) {
- ArgError("width given twice");
+ rb_raise(rb_eArgError, "width given twice");
}
flags |= FWIDTH;
- width = GETARG();
- width = NUM2INT(width);
+ tmp = GETARG();
+ width = NUM2INT(tmp);
if (width < 0) {
flags |= FMINUS;
- width = - width;
+ width = -width;
}
p++;
goto retry;
case '.':
if (flags & FPREC) {
- ArgError("precision given twice");
+ rb_raise(rb_eArgError, "precision given twice");
}
prec = 0;
p++;
- if (*p == '0') flags |= FZERO;
if (*p == '*') {
- prec = GETARG();
- prec = NUM2INT(prec);
+ tmp = GETARG();
+ prec = NUM2INT(tmp);
if (prec > 0)
flags |= FPREC;
p++;
goto retry;
}
- for (; p < end && isdigit(*p); p++) {
+ for (; p < end && ISDIGIT(*p); p++) {
prec = 10 * prec + (*p - '0');
}
if (p >= end) {
- ArgError("malformed format string - %%.[0-9]");
+ rb_raise(rb_eArgError, "malformed format string - %%.[0-9]");
}
if (prec > 0)
flags |= FPREC;
@@ -261,8 +260,13 @@ f_sprintf(argc, argv)
VALUE val = GETARG();
char c;
+ if (!(flags & FMINUS))
+ while (--width > 0)
+ PUSH(" ", 1);
c = NUM2INT(val) & 0xff;
PUSH(&c, 1);
+ while (--width > 0)
+ PUSH(" ", 1);
}
break;
@@ -271,7 +275,7 @@ f_sprintf(argc, argv)
VALUE arg = GETARG();
int len;
- str = obj_as_string(arg);
+ str = rb_obj_as_string(arg);
len = RSTRING(str)->len;
if (flags&FPREC) {
if (prec < len) {
@@ -283,8 +287,8 @@ f_sprintf(argc, argv)
}
if (flags&FWIDTH) {
if (width > len) {
- width -= len;
CHECK(width);
+ width -= len;
if (!(flags&FMINUS)) {
while (width--) {
buf[blen++] = ' ';
@@ -306,28 +310,58 @@ f_sprintf(argc, argv)
}
break;
- case 'b':
- case 'B':
+ case 'd':
+ case 'i':
case 'o':
case 'x':
+ case 'X':
+ case 'b':
case 'u':
{
volatile VALUE val = GETARG();
char fbuf[32], nbuf[64], *s, *t;
- int v, base, bignum = 0;
- int len, slen, pos;
+ char *prefix = 0;
+ int sign = 0;
+ char sc = 0;
+ long v;
+ int base, bignum = 0;
+ int len, pos;
+
+ switch (*p) {
+ case 'd':
+ case 'i':
+ sign = 1; break;
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'b':
+ case 'u':
+ default:
+ if (flags&(FPLUS|FSPACE)) sign = 1;
+ break;
+ }
+ if (flags & FSHARP) {
+ if (*p == 'o') prefix = "0";
+ else if (*p == 'x') prefix = "0x";
+ else if (*p == 'X') prefix = "0X";
+ else if (*p == 'b') prefix = "0b";
+ if (prefix) {
+ width -= strlen(prefix);
+ }
+ }
bin_retry:
switch (TYPE(val)) {
case T_FIXNUM:
- v = FIX2INT(val);
+ v = FIX2LONG(val);
break;
case T_FLOAT:
- val = dbl2big(RFLOAT(val)->value);
+ val = rb_dbl2big(RFLOAT(val)->value);
+ if (FIXNUM_P(val)) goto bin_retry;
bignum = 1;
break;
case T_STRING:
- val = str2inum(RSTRING(val)->ptr, 0);
+ val = rb_str2inum(RSTRING(val)->ptr, 10);
goto bin_retry;
case T_BIGNUM:
bignum = 1;
@@ -337,51 +371,90 @@ f_sprintf(argc, argv)
break;
}
- if (*p == 'x') base = 16;
+ if (*p == 'u' || *p == 'd' || *p == 'i') base = 10;
+ else if (*p == 'x' || *p == 'X') base = 16;
else if (*p == 'o') base = 8;
- else if (*p == 'u') base = 10;
- else if (*p == 'b' || *p == 'B') base = 2;
+ else if (*p == 'b') base = 2;
if (!bignum) {
- if (*p == 'b' || *p == 'B') {
- val = int2big(v);
+ if (base == 2) {
+ val = rb_int2big(v);
+ goto bin_retry;
}
- else {
- s = nbuf;
+ if (sign) {
+ char c = *p;
+ if (c == 'i') c = 'd'; /* %d and %i are identical */
if (v < 0) {
- strcpy(s, "..");
- s += 2;
- bignum = 2;
+ v = -v;
+ sc = '-';
+ width--;
}
- sprintf(fbuf, "%%%c", *p);
- sprintf(s, fbuf, v);
- if (v < 0) {
- char d = 0;
-
- remove_sign_bits(s, base);
- switch (base) {
- case 16:
- d = 'f'; break;
- case 8:
- d = '7'; break;
- }
- if (d && *s != d) {
- memmove(s+1, s, strlen(s)+1);
- *s = d;
- }
+ else if (flags & FPLUS) {
+ sc = '+';
+ width--;
}
+ else if (flags & FSPACE) {
+ sc = ' ';
+ width--;
+ }
+ sprintf(fbuf, "%%l%c", c);
+ sprintf(nbuf, fbuf, v);
s = nbuf;
- goto unsigned_format;
+ goto format_integer;
+ }
+ s = nbuf;
+ if (v < 0) {
+ strcpy(s, "..");
+ s += 2;
+ }
+ sprintf(fbuf, "%%l%c", *p);
+ sprintf(s, fbuf, v);
+ if (v < 0) {
+ char d = 0;
+
+ remove_sign_bits(s, base);
+ switch (base) {
+ case 16:
+ d = 'f';
+ break;
+ case 8:
+ d = '7'; break;
+ }
+ if (d && *s != d) {
+ memmove(s+1, s, strlen(s)+1);
+ *s = d;
+ }
}
+ s = nbuf;
+ goto format_integer;
}
- if (*p != 'B' && !RBIGNUM(val)->sign) {
- val = big_clone(val);
- big_2comp(val);
+
+ if (sign) {
+ val = rb_big2str(val, base);
+ s = RSTRING(val)->ptr;
+ if (s[0] == '-') {
+ s++;
+ sc = '-';
+ width--;
+ }
+ else if (flags & FPLUS) {
+ sc = '+';
+ width--;
+ }
+ else if (flags & FSPACE) {
+ sc = ' ';
+ width--;
+ }
+ goto format_integer;
+ }
+ if (!RBIGNUM(val)->sign) {
+ val = rb_big_clone(val);
+ rb_big_2comp(val);
}
- val = big2str(val, base);
+ val = rb_big2str(val, base);
s = RSTRING(val)->ptr;
- if (*s == '-' && *p != 'B') {
+ if (*s == '-') {
remove_sign_bits(++s, base);
- val = str_new(0, 3+strlen(s));
+ val = rb_str_new(0, 3+strlen(s));
t = RSTRING(val)->ptr;
strcpy(t, "..");
t += 2;
@@ -396,165 +469,79 @@ f_sprintf(argc, argv)
}
s = RSTRING(val)->ptr;
- unsigned_format:
- slen = len = strlen(s);
- pos = blen;
- if (flags&FWIDTH) {
- if (width <= len) flags &= ~FWIDTH;
- else {
- slen = width;
+ format_integer:
+ pos = -1;
+ len = strlen(s);
+
+ if (*p == 'X') {
+ char *pp = s;
+ while (*pp) {
+ *pp = toupper(*pp);
+ pp++;
}
}
- if (flags&FPREC) {
- if (prec <= len) flags &= ~FPREC;
- else {
- if (prec >= slen) {
- flags &= ~FWIDTH;
- slen = prec;
- }
+ if (prec < len) prec = len;
+ width -= prec;
+ if (!(flags&(FZERO|FMINUS)) && s[0] != '.') {
+ CHECK(width);
+ while (width-->0) {
+ buf[blen++] = ' ';
}
}
- if (slen > len) {
- int n = slen-len;
- char d = ' ';
- if (flags & FZERO) d = '0';
- CHECK(n);
- while (n--) {
- buf[blen++] = d;
- }
+ if (sc) PUSH(&sc, 1);
+ if (prefix) {
+ int plen = strlen(prefix);
+ CHECK(plen);
+ strcpy(&buf[blen], prefix);
+ blen += plen;
+ if (pos) pos += plen;
}
- if ((flags&(FWIDTH|FPREC)) == (FWIDTH|FPREC)) {
- if (prec < width) {
- pos = width - prec;
+ if (!(flags & FMINUS)) {
+ char c = ' ';
+
+ if (s[0] == '.') {
+ c = '.';
+ if ((flags & FPREC) && prec > len) {
+ pos = blen;
+ }
+ else {
+ pos = blen + 2;
+ }
+ }
+ else if (flags & FZERO) c = '0';
+ CHECK(width);
+ while (width-->0) {
+ buf[blen++] = c;
}
}
+ CHECK(prec - len);
+ while (len < prec--) {
+ buf[blen++] = s[0]=='.'?'.':'0';
+ }
CHECK(len);
strcpy(&buf[blen], s);
blen += len;
- t = &buf[pos];
- if (bignum == 2) {
- char d = '.';
+ CHECK(width);
+ while (width-->0) {
+ buf[blen++] = ' ';
+ }
+ if (pos >= 0 && buf[pos] == '.') {
+ char c = '.';
switch (base) {
case 16:
- d = 'f'; break;
+ if (*p == 'X') c = 'F';
+ else c = 'f';
+ break;
case 8:
- d = '7'; break;
+ c = '7'; break;
case '2':
- d = '1'; break;
- }
-
- if ((flags & FPREC) == 0 || prec <= len-2) {
- *t++ = '.'; *t++ = '.';
- }
- while (*t == ' ' || *t == '.') {
- *t++ = d;
- }
- }
- else if (flags & (FPREC|FZERO)) {
- while (*t == ' ') {
- *t++ = '0';
- }
- }
- }
- break;
-
- case 'd':
- case 'D':
- case 'O':
- case 'X':
- {
- volatile VALUE val = GETARG();
- char fbuf[32], c = *p;
- int bignum = 0, base;
- int v;
-
- if (c == 'D') c = 'd';
- int_retry:
- switch (TYPE(val)) {
- case T_FIXNUM:
- v = FIX2INT(val);
- break;
- case T_FLOAT:
- v = RFLOAT(val)->value;
- break;
- case T_STRING:
- val = str2inum(RSTRING(val)->ptr, 0);
- goto int_retry;
- case T_BIGNUM:
- if (c == 'd') base = 10;
- else if (c == 'X') base = 16;
- else if (c == 'O') base = 8;
- val = big2str(val, base);
- bignum = 1;
- break;
- default:
- val = num2fix(val);
- goto int_retry;
- }
-
- if (bignum) {
- char *s = RSTRING(val)->ptr;
- int slen, len, pos_b, pos;
-
- slen = len = strlen(s);
- pos = pos_b = blen;
- if (flags&FWIDTH) {
- if (width <= len) flags &= ~FWIDTH;
- else {
- slen = width;
- }
- }
- if (flags&FPREC) {
- if (prec <= len) flags &= ~FPREC;
- else {
- if (prec >= slen) {
- flags &= ~FWIDTH;
- slen = prec;
- }
- }
- }
- if (slen > len) {
- int n = slen-len;
- CHECK(n);
- while (n--) {
- buf[blen++] = ' ';
- }
+ c = '1'; break;
}
- if ((flags&(FWIDTH|FPREC)) == (FWIDTH|FPREC)) {
- if (prec < width) {
- pos = width - prec;
- }
- }
- CHECK(len);
- strcpy(&buf[blen], s);
- blen += len;
- if (flags & (FPREC|FZERO)) {
- char *t = &buf[pos];
- char *b = &buf[pos_b];
-
- if (s[0] == '-') {
- if (slen > len && t != b ) t[-1] = '-';
- else *t++ = '-';
- }
- while (*t == ' ' || *t == '-') {
- *t++ = '0';
- }
- }
- }
- else {
- int max = 11;
-
- if ((flags & FPREC) && prec > max) max = prec;
- if ((flags & FWIDTH) && width > max) max = width;
- CHECK(max);
- if (v < 0 && (c == 'X' || c == 'O')) {
- v = -v;
- PUSH("-", 1);
+ s = &buf[pos];
+ while (*s && *s == '.') {
+ *s++ = c;
}
- fmt_setup(fbuf, c, flags, width, prec);
- sprintf(&buf[blen], fbuf, v);
- blen += strlen(&buf[blen]);
}
}
break;
@@ -562,6 +549,7 @@ f_sprintf(argc, argv)
case 'f':
case 'g':
case 'e':
+ case 'E':
{
VALUE val = GETARG();
double fval;
@@ -569,13 +557,13 @@ f_sprintf(argc, argv)
switch (TYPE(val)) {
case T_FIXNUM:
- fval = FIX2INT(val);
+ fval = (double)FIX2LONG(val);
break;
case T_FLOAT:
fval = RFLOAT(val)->value;
break;
case T_BIGNUM:
- fval = big2dbl(val);
+ fval = rb_big2dbl(val);
break;
case T_STRING:
fval = atof(RSTRING(val)->ptr);
@@ -597,10 +585,10 @@ f_sprintf(argc, argv)
}
sprint_exit:
- if (RTEST(verbose) && argc > 1) {
- ArgError("too many argument for format string");
+ if (RTEST(rb_verbose) && argc > 1) {
+ rb_raise(rb_eArgError, "too many argument for format string");
}
- result = str_new(buf, blen);
+ result = rb_str_new(buf, blen);
free(buf);
return result;
@@ -616,6 +604,7 @@ fmt_setup(buf, c, flags, width, prec)
if (flags & FPLUS) *buf++ = '+';
if (flags & FMINUS) *buf++ = '-';
if (flags & FZERO) *buf++ = '0';
+ if (flags & FSPACE) *buf++ = ' ';
if (flags & FWIDTH) {
sprintf(buf, "%d", width);
diff --git a/string.c b/string.c
index 3c3d24f3cf..e5f0dd2a63 100644
--- a/string.c
+++ b/string.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Aug 9 17:12:58 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -16,32 +16,28 @@
#define BEG(no) regs->beg[no]
#define END(no) regs->end[no]
-#include <stdio.h>
#include <ctype.h>
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-VALUE cString;
-
-#define STRLEN(s) RSTRING(s)->len
+VALUE rb_cString;
#define STR_FREEZE FL_USER1
-#define STR_TAINT FL_USER2
-void reg_prepare_re _((VALUE));
-void kcode_reset_option _((void));
+#define STR_NO_ORIG FL_USER3
+
+extern VALUE rb_rs;
VALUE
-str_new(ptr, len)
- UCHAR *ptr;
- UINT len;
+rb_str_new(ptr, len)
+ char *ptr;
+ size_t len;
{
NEWOBJ(str, struct RString);
- OBJSETUP(str, cString, T_STRING);
+ OBJSETUP(str, rb_cString, T_STRING);
- if (rb_safe_level() >= 3) {
- FL_SET(str, STR_TAINT);
- }
+ str->ptr = 0;
str->len = len;
str->orig = 0;
str->ptr = ALLOC_N(char,len+1);
@@ -53,57 +49,98 @@ str_new(ptr, len)
}
VALUE
-str_new2(ptr)
- UCHAR *ptr;
+rb_str_new2(ptr)
+ char *ptr;
+{
+ return rb_str_new(ptr, strlen(ptr));
+}
+
+VALUE
+rb_tainted_str_new(ptr, len)
+ char *ptr;
+ size_t len;
{
- return str_new(ptr, strlen(ptr));
+ return rb_obj_taint(rb_str_new(ptr, len));
}
VALUE
-str_new3(str)
+rb_tainted_str_new2(ptr)
+ char *ptr;
+{
+ return rb_obj_taint(rb_str_new2(ptr));
+}
+
+VALUE
+rb_str_new3(str)
VALUE str;
{
NEWOBJ(str2, struct RString);
- OBJSETUP(str2, cString, T_STRING);
+ OBJSETUP(str2, rb_cString, T_STRING);
str2->len = RSTRING(str)->len;
str2->ptr = RSTRING(str)->ptr;
str2->orig = str;
- if (rb_safe_level() >= 3) {
- FL_SET(str2, STR_TAINT);
- }
-
return (VALUE)str2;
}
VALUE
-str_new4(orig)
+rb_str_new4(orig)
VALUE orig;
{
- NEWOBJ(str, struct RString);
- OBJSETUP(str, cString, T_STRING);
-
- str->len = RSTRING(orig)->len;
- str->ptr = RSTRING(orig)->ptr;
- if (RSTRING(orig)->orig) {
- str->orig = RSTRING(orig)->orig;
+ if (FL_TEST(orig, STR_FREEZE)) {
+ return orig;
+ }
+ else if (RSTRING(orig)->orig && !FL_TEST(orig, STR_NO_ORIG)) {
+ return rb_str_freeze(RSTRING(orig)->orig);
}
else {
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ str->len = RSTRING(orig)->len;
+ str->ptr = RSTRING(orig)->ptr;
RSTRING(orig)->orig = (VALUE)str;
str->orig = 0;
+ if (rb_safe_level() >= 3) {
+ FL_SET(str, FL_TAINT);
+ }
+ return (VALUE)str;
}
- if (rb_safe_level() >= 3) {
- FL_SET(str, STR_TAINT);
- }
+}
- return (VALUE)str;
+VALUE
+rb_str_to_str(str)
+ VALUE str;
+{
+ return rb_convert_type(str, T_STRING, "String", "to_str");
+}
+
+static void
+rb_str_assign(str, str2)
+ VALUE str, str2;
+{
+ if (str == str2) return;
+ if (NIL_P(str2)) {
+ RSTRING(str)->ptr = 0;
+ RSTRING(str)->len = 0;
+ RSTRING(str)->orig = 0;
+ return;
+ }
+ if ((!RSTRING(str)->orig||FL_TEST(str, STR_NO_ORIG))&&RSTRING(str)->ptr)
+ free(RSTRING(str)->ptr);
+ RSTRING(str)->ptr = RSTRING(str2)->ptr;
+ RSTRING(str)->len = RSTRING(str2)->len;
+ RSTRING(str)->orig = RSTRING(str2)->orig;
+ RSTRING(str2)->ptr = 0; /* abandon str2 */
+ RSTRING(str2)->len = 0;
+ if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
-static ID pr_str;
+static ID to_str;
VALUE
-obj_as_string(obj)
+rb_obj_as_string(obj)
VALUE obj;
{
VALUE str;
@@ -111,111 +148,130 @@ obj_as_string(obj)
if (TYPE(obj) == T_STRING) {
return obj;
}
- str = rb_funcall(obj, pr_str, 0);
+ str = rb_funcall(obj, to_str, 0);
if (TYPE(str) != T_STRING)
- return any_to_s(obj);
+ return rb_any_to_s(obj);
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
return str;
}
static VALUE
-str_clone(orig)
+rb_str_clone(orig)
VALUE orig;
{
VALUE str;
- if (RSTRING(orig)->orig)
- str = str_new3(RSTRING(orig)->orig);
+ if (RSTRING(orig)->orig && !FL_TEST(orig, STR_NO_ORIG))
+ str = rb_str_new3(RSTRING(orig)->orig);
else
- str = str_new(RSTRING(orig)->ptr, RSTRING(orig)->len);
+ str = rb_str_new(RSTRING(orig)->ptr, RSTRING(orig)->len);
+ if (RSTRING(orig)->orig && FL_TEST(orig, STR_NO_ORIG))
+ RSTRING(str)->orig = RSTRING(orig)->orig;
CLONESETUP(str, orig);
return str;
}
VALUE
-str_dup(str)
+rb_str_dup(str)
VALUE str;
{
- VALUE s = str_new(RSTRING(str)->ptr, RSTRING(str)->len);
- if (str_tainted(str)) s = str_taint(s);
+ VALUE s;
+
+ if (TYPE(str) != T_STRING) str = rb_str_to_str(str);
+ s = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len);
+ if (OBJ_TAINTED(str)) OBJ_TAINT(s);
+
return s;
}
static VALUE
-str_s_new(class, orig)
- VALUE class;
+rb_str_s_new(klass, orig)
+ VALUE klass;
VALUE orig;
{
NEWOBJ(str, struct RString);
- OBJSETUP(str, class, T_STRING);
+ OBJSETUP(str, klass, T_STRING);
- orig = obj_as_string(orig);
+ str->orig = 0;
+ orig = rb_obj_as_string(orig);
str->len = RSTRING(orig)->len;
- str->ptr = ALLOC_N(char, RSTRING(orig)->len+1);
- if (str->ptr) {
+ if (RSTRING(orig)->ptr) {
+ str->ptr = ALLOC_N(char, RSTRING(orig)->len+1);
memcpy(str->ptr, RSTRING(orig)->ptr, RSTRING(orig)->len);
+ str->ptr[RSTRING(orig)->len] = '\0';
}
- str->ptr[RSTRING(orig)->len] = '\0';
- str->orig = 0;
if (rb_safe_level() >= 3) {
- FL_SET(str, STR_TAINT);
+ FL_SET(str, FL_TAINT);
}
+ rb_obj_call_init((VALUE)str);
return (VALUE)str;
}
static VALUE
-str_length(str)
+rb_str_length(str)
VALUE str;
{
return INT2FIX(RSTRING(str)->len);
}
+static VALUE
+rb_str_empty(str)
+ VALUE str;
+{
+ if (RSTRING(str)->len == 0)
+ return Qtrue;
+ return Qfalse;
+}
+
VALUE
-str_plus(str1, str2)
+rb_str_plus(str1, str2)
VALUE str1, str2;
{
VALUE str3;
- str2 = obj_as_string(str2);
- str3 = str_new(0, RSTRING(str1)->len+RSTRING(str2)->len);
+ if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
+ str3 = rb_str_new(0, RSTRING(str1)->len+RSTRING(str2)->len);
memcpy(RSTRING(str3)->ptr, RSTRING(str1)->ptr, RSTRING(str1)->len);
- memcpy(RSTRING(str3)->ptr+RSTRING(str1)->len, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ memcpy(RSTRING(str3)->ptr + RSTRING(str1)->len,
+ RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str3)->ptr[RSTRING(str3)->len] = '\0';
- if (str_tainted(str1) || str_tainted(str2))
- return str_taint(str3);
- return (VALUE)str3;
+ if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
+ OBJ_TAINT(str3);
+ return str3;
}
VALUE
-str_times(str, times)
+rb_str_times(str, times)
VALUE str;
VALUE times;
{
VALUE str2;
- int i, len;
+ size_t i, len;
len = NUM2INT(times);
if (len < 0) {
- ArgError("negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
- str2 = str_new(0, RSTRING(str)->len*len);
+ str2 = rb_str_new(0, RSTRING(str)->len*len);
for (i=0; i<len; i++) {
- memcpy(RSTRING(str2)->ptr+(i*RSTRING(str)->len), RSTRING(str)->ptr, RSTRING(str)->len);
+ memcpy(RSTRING(str2)->ptr+(i*RSTRING(str)->len),
+ RSTRING(str)->ptr, RSTRING(str)->len);
}
RSTRING(str2)->ptr[RSTRING(str2)->len] = '\0';
- if (str_tainted(str)) {
- return str_taint((VALUE)str2);
+ if (OBJ_TAINTED(str)) {
+ OBJ_TAINT(str2);
}
return str2;
}
-VALUE
-str_format(str, arg)
+static VALUE
+rb_str_format(str, arg)
VALUE str, arg;
{
VALUE *argv;
@@ -224,44 +280,47 @@ str_format(str, arg)
argv = ALLOCA_N(VALUE, RARRAY(arg)->len + 1);
argv[0] = str;
MEMCPY(argv+1, RARRAY(arg)->ptr, VALUE, RARRAY(arg)->len);
- return f_sprintf(RARRAY(arg)->len+1, argv);
+ return rb_f_sprintf(RARRAY(arg)->len+1, argv);
}
argv = ALLOCA_N(VALUE, 2);
argv[0] = str;
argv[1] = arg;
- return f_sprintf(2, argv);
+ return rb_f_sprintf(2, argv);
}
VALUE
-str_substr(str, start, len)
+rb_str_substr(str, start, len)
VALUE str;
- int start, len;
+ size_t start, len;
{
- struct RString *str2;
+ VALUE str2;
if (start < 0) {
start = RSTRING(str)->len + start;
}
if (RSTRING(str)->len <= start || len < 0) {
- return str_new(0,0);
+ return rb_str_new(0,0);
}
if (RSTRING(str)->len < start + len) {
len = RSTRING(str)->len - start;
}
- return str_new(RSTRING(str)->ptr+start, len);
+ str2 = rb_str_new(RSTRING(str)->ptr+start, len);
+ if (OBJ_TAINTED(str)) OBJ_TAINT(str2);
+
+ return str2;
}
static VALUE
-str_subseq(str, beg, end)
+rb_str_subseq(str, beg, end)
VALUE str;
- int beg, end;
+ size_t beg, end;
{
- int len;
+ size_t len;
if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- IndexError("end smaller than beg [%d..%d]", beg, end);
+ rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", beg, end);
}
if (beg < 0) {
@@ -277,7 +336,7 @@ str_subseq(str, beg, end)
}
if (beg >= RSTRING(str)->len) {
- return str_new(0, 0);
+ return rb_str_new(0, 0);
}
len = end - beg + 1;
@@ -285,24 +344,20 @@ str_subseq(str, beg, end)
len = 0;
}
- return str_substr(str, beg, len);
+ return rb_str_substr(str, beg, len);
}
-extern VALUE ignorecase;
-
void
-str_modify(str)
+rb_str_modify(str)
VALUE str;
{
- UCHAR *ptr;
+ char *ptr;
- if (rb_safe_level() >= 5) {
- extern VALUE eSecurityError;
- Raise(eSecurityError, "cannot change string status");
- }
if (FL_TEST(str, STR_FREEZE))
- TypeError("can't modify frozen string");
- if (!RSTRING(str)->orig) return;
+ rb_raise(rb_eTypeError, "can't modify frozen string");
+ if (rb_safe_level() >= 4 && !FL_TEST(str, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify string");
+ if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return;
ptr = RSTRING(str)->ptr;
RSTRING(str)->ptr = ALLOC_N(char, RSTRING(str)->len+1);
if (RSTRING(str)->ptr) {
@@ -313,7 +368,7 @@ str_modify(str)
}
VALUE
-str_freeze(str)
+rb_str_freeze(str)
VALUE str;
{
FL_SET(str, STR_FREEZE);
@@ -321,48 +376,32 @@ str_freeze(str)
}
static VALUE
-str_frozen_p(str)
+rb_str_frozen_p(str)
VALUE str;
{
if (FL_TEST(str, STR_FREEZE))
- return TRUE;
- return FALSE;
-}
-
-VALUE
-str_dup_freezed(str)
- VALUE str;
-{
- str = str_dup(str);
- str_freeze(str);
- return str;
+ return Qtrue;
+ return Qfalse;
}
VALUE
-str_taint(str)
+rb_str_dup_frozen(str)
VALUE str;
{
- if (TYPE(str) == T_STRING) {
- FL_SET(str, STR_TAINT);
+ if (RSTRING(str)->orig && !FL_TEST(str, STR_NO_ORIG)) {
+ return rb_str_freeze(RSTRING(str)->orig);
}
- return str;
-}
-
-VALUE
-str_tainted(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_TAINT))
- return TRUE;
- return FALSE;
+ if (FL_TEST(str, STR_FREEZE))
+ return str;
+ return rb_str_freeze(rb_str_dup(str));
}
VALUE
-str_resize(str, len)
+rb_str_resize(str, len)
VALUE str;
- int len;
+ size_t len;
{
- str_modify(str);
+ rb_str_modify(str);
if (len >= 0) {
if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) {
@@ -371,17 +410,17 @@ str_resize(str, len)
RSTRING(str)->len = len;
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
}
- return (VALUE)str;
+ return str;
}
VALUE
-str_cat(str, ptr, len)
+rb_str_cat(str, ptr, len)
VALUE str;
- UCHAR *ptr;
- UINT len;
+ char *ptr;
+ size_t len;
{
if (len > 0) {
- str_modify(str);
+ rb_str_modify(str);
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len + len + 1);
if (ptr)
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
@@ -391,24 +430,30 @@ str_cat(str, ptr, len)
return str;
}
-static VALUE
-str_concat(str1, str2)
+VALUE
+rb_str_concat(str1, str2)
VALUE str1, str2;
{
- str2 = obj_as_string(str2);
- str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
- return str1;
+ if (FIXNUM_P(str2)) {
+ int i = FIX2INT(str2);
+ if (0 <= i && i <= 0xff) { /* byte */
+ char c = i;
+ return rb_str_cat(str1, &c, 1);
+ }
+ }
+ if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
+ return rb_str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
int
-str_hash(str)
+rb_str_hash(str)
VALUE str;
{
- register int len = RSTRING(str)->len;
- register UCHAR *p = RSTRING(str)->ptr;
+ register size_t len = RSTRING(str)->len;
+ register char *p = RSTRING(str)->ptr;
register int key = 0;
- if (RTEST(ignorecase)) {
+ if (ruby_ignorecase) {
while (len--) {
key = key*65599 + toupper(*p);
p++;
@@ -424,75 +469,79 @@ str_hash(str)
}
static VALUE
-str_hash_method(str)
+rb_str_hash_method(str)
VALUE str;
{
- int key = str_hash(str);
+ int key = rb_str_hash(str);
return INT2FIX(key);
}
-#define min(a,b) (((a)>(b))?(b):(a))
+#define lesser(a,b) (((a)>(b))?(b):(a))
int
-str_cmp(str1, str2)
+rb_str_cmp(str1, str2)
VALUE str1, str2;
{
- UINT len;
+ size_t len;
int retval;
- if (RTEST(ignorecase)) {
- return str_cicmp(str1, str2);
+ if (ruby_ignorecase) {
+ return rb_str_cicmp(str1, str2);
}
- len = min(RSTRING(str1)->len, RSTRING(str2)->len);
+ len = lesser(RSTRING(str1)->len, RSTRING(str2)->len);
retval = memcmp(RSTRING(str1)->ptr, RSTRING(str2)->ptr, len);
if (retval == 0) {
- return RSTRING(str1)->ptr[len] - RSTRING(str2)->ptr[len];
+ if (RSTRING(str1)->len == RSTRING(str2)->len) return 0;
+ if (RSTRING(str1)->len > RSTRING(str2)->len) return 1;
+ return -1;
}
- return retval;
+ if (retval == 0) return 0;
+ if (retval > 0) return 1;
+ return -1;
}
static VALUE
-str_equal(str1, str2)
+rb_str_equal(str1, str2)
VALUE str1, str2;
{
if (TYPE(str2) != T_STRING)
- return FALSE;
+ return Qfalse;
if (RSTRING(str1)->len == RSTRING(str2)->len
- && str_cmp(str1, str2) == 0) {
- return TRUE;
+ && rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-str_cmp_method(str1, str2)
+rb_str_cmp_method(str1, str2)
VALUE str1, str2;
{
int result;
- str2 = obj_as_string(str2);
- result = str_cmp(str1, str2);
+ if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
+ result = rb_str_cmp(str1, str2);
return INT2FIX(result);
}
static VALUE
-str_match(x, y)
+rb_str_match(x, y)
VALUE x, y;
{
VALUE reg;
- int start;
+ size_t start;
switch (TYPE(y)) {
case T_REGEXP:
- return reg_match(y, x);
+ return rb_reg_match(y, x);
case T_STRING:
- reg = reg_regcomp(y);
- start = reg_search(reg, x, 0, 0);
+ reg = rb_reg_regcomp(y);
+ start = rb_reg_search(reg, x, 0, 0);
if (start == -1) {
- return FALSE;
+ return Qfalse;
}
return INT2FIX(start);
@@ -502,19 +551,19 @@ str_match(x, y)
}
static VALUE
-str_match2(str)
+rb_str_match2(str)
VALUE str;
{
- return reg_match2(reg_regcomp(str));
+ return rb_reg_match2(rb_reg_regcomp(str));
}
-static int
-str_index(str, sub, offset)
+static size_t
+rb_str_index(str, sub, offset)
VALUE str, sub;
- int offset;
+ size_t offset;
{
- UCHAR *s, *e, *p;
- int len;
+ char *s, *e, *p;
+ size_t len;
if (RSTRING(str)->len - offset < RSTRING(sub)->len) return -1;
s = RSTRING(str)->ptr+offset;
@@ -527,21 +576,21 @@ str_index(str, sub, offset)
}
s++;
}
- return -1;
+ return (size_t)-1;
}
static VALUE
-str_index_method(argc, argv, str)
+rb_str_index_method(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE sub;
VALUE initpos;
- int pos;
+ size_t pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2INT(initpos);
+ pos = NUM2UINT(initpos);
}
else {
pos = 0;
@@ -549,17 +598,17 @@ str_index_method(argc, argv, str)
switch (TYPE(sub)) {
case T_REGEXP:
- pos = reg_search(sub, str, pos, (struct re_registers *)-1);
+ pos = rb_reg_search(sub, str, pos, 0);
break;
case T_STRING:
- pos = str_index(str, sub, pos);
+ pos = rb_str_index(str, sub, pos);
break;
case T_FIXNUM:
{
int c = FIX2INT(sub);
- int len = RSTRING(str)->len;
+ size_t len = RSTRING(str)->len;
char *p = RSTRING(str)->ptr;
for (;pos<len;pos++) {
@@ -569,7 +618,8 @@ str_index_method(argc, argv, str)
}
default:
- TypeError("Type mismatch: %s given", rb_class2name(CLASS_OF(sub)));
+ rb_raise(rb_eTypeError, "Type mismatch: %s given",
+ rb_class2name(CLASS_OF(sub)));
}
if (pos == -1) return Qnil;
@@ -577,18 +627,18 @@ str_index_method(argc, argv, str)
}
static VALUE
-str_rindex(argc, argv, str)
+rb_str_rindex(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE sub;
VALUE initpos;
- int pos, len;
- UCHAR *s, *sbeg, *t;
+ size_t pos, len;
+ char *s, *sbeg, *t;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2INT(initpos);
+ pos = NUM2UINT(initpos);
if (pos >= RSTRING(str)->len) pos = RSTRING(str)->len;
}
else {
@@ -597,11 +647,7 @@ str_rindex(argc, argv, str)
switch (TYPE(sub)) {
case T_REGEXP:
- reg_prepare_re(sub);
- pos = re_search(RREGEXP(sub)->ptr,
- RSTRING(str)->ptr, RSTRING(str)->len,
- pos, -pos, 0);
- kcode_reset_option();
+ pos = rb_reg_search(sub, str, pos, 1);
if (pos >= 0) return INT2FIX(pos);
break;
@@ -631,14 +677,15 @@ str_rindex(argc, argv, str)
}
default:
- TypeError("Type mismatch: %s given", rb_class2name(CLASS_OF(sub)));
+ rb_raise(rb_eTypeError, "Type mismatch: %s given",
+ rb_class2name(CLASS_OF(sub)));
}
return Qnil;
}
-static UCHAR
+static char
succ_char(s)
- UCHAR *s;
+ char *s;
{
char c = *s;
@@ -662,19 +709,19 @@ succ_char(s)
}
static VALUE
-str_succ(orig)
+rb_str_succ(orig)
VALUE orig;
{
VALUE str, str2;
- UCHAR *sbeg, *s;
+ char *sbeg, *s;
char c = -1;
- str = str_new(RSTRING(orig)->ptr, RSTRING(orig)->len);
+ str = rb_str_new(RSTRING(orig)->ptr, RSTRING(orig)->len);
sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1;
while (sbeg <= s) {
- if (isalnum(*s) && (c = succ_char(s)) == 0) break;
+ if (ISALNUM(*s) && (c = succ_char(s)) == 0) break;
s--;
}
if (s < sbeg) {
@@ -682,35 +729,45 @@ str_succ(orig)
RSTRING(str)->ptr[RSTRING(str)->len-1] += 1;
}
else {
- str2 = str_new(0, RSTRING(str)->len+1);
+ str2 = rb_str_new(0, RSTRING(str)->len+1);
RSTRING(str2)->ptr[0] = c;
memcpy(RSTRING(str2)->ptr+1, RSTRING(str)->ptr, RSTRING(str)->len);
str = str2;
}
}
- if (str_tainted(orig)) {
- return str_taint(str);
+ if (OBJ_TAINTED(orig)) {
+ OBJ_TAINT(str);
}
return str;
}
+static VALUE
+rb_str_succ_bang(str)
+ VALUE str;
+{
+ rb_str_modify(str);
+ rb_str_assign(str, rb_str_succ(str));
+
+ return str;
+}
+
VALUE
-str_upto(beg, end)
+rb_str_upto(beg, end)
VALUE beg, end;
{
VALUE current;
- Check_Type(end, T_STRING);
+ if (TYPE(end) != T_STRING) end = rb_str_to_str(end);
if (RTEST(rb_funcall(beg, '>', 1, end)))
return Qnil;
current = beg;
for (;;) {
rb_yield(current);
- if (str_equal(current, end)) break;
- current = str_succ(current);
+ if (rb_str_equal(current, end)) break;
+ current = rb_str_succ(current);
if (RSTRING(current)->len > RSTRING(end)->len)
break;
}
@@ -719,11 +776,11 @@ str_upto(beg, end)
}
static VALUE
-str_aref(str, indx)
+rb_str_aref(str, indx)
VALUE str;
VALUE indx;
{
- int idx;
+ size_t idx;
switch (TYPE(indx)) {
case T_FIXNUM:
@@ -735,31 +792,32 @@ str_aref(str, indx)
if (idx < 0 || RSTRING(str)->len <= idx) {
return Qnil;
}
- return (VALUE)INT2FIX(RSTRING(str)->ptr[idx] & 0xff);
+ return INT2FIX(RSTRING(str)->ptr[idx] & 0xff);
case T_REGEXP:
- if (str_match(str, indx))
- return reg_last_match(0);
+ if (rb_reg_search(indx, str, 0, 0) >= 0)
+ return rb_reg_last_match(rb_backref_get());
return Qnil;
case T_STRING:
- if (str_index(str, indx, 0) != -1) return indx;
+ if (rb_str_index(str, indx, 0) != (size_t)-1) return indx;
return Qnil;
default:
/* check if indx is Range */
{
- int beg, end;
- if (range_beg_end(indx, &beg, &end)) {
- return str_subseq(str, beg, end);
+ size_t beg, end;
+ if (rb_range_beg_end(indx, &beg, &end)) {
+ return rb_str_subseq(str, beg, end);
}
}
- IndexError("Invalid index for string");
+ rb_raise(rb_eIndexError, "Invalid index for string");
}
+ return Qnil; /* not reached */
}
static VALUE
-str_aref_method(argc, argv, str)
+rb_str_aref_method(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@@ -767,15 +825,15 @@ str_aref_method(argc, argv, str)
VALUE arg1, arg2;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- return str_substr(str, NUM2INT(arg1), NUM2INT(arg2));
+ return rb_str_substr(str, NUM2INT(arg1), NUM2INT(arg2));
}
- return str_aref(str, arg1);
+ return rb_str_aref(str, arg1);
}
static void
-str_replace(str, beg, len, val)
+rb_str_replace(str, beg, len, val)
VALUE str, val;
- int beg, len;
+ size_t beg, len;
{
if (len < RSTRING(val)->len) {
/* expand string */
@@ -783,25 +841,28 @@ str_replace(str, beg, len, val)
}
if (len != RSTRING(val)->len) {
- memmove(RSTRING(str)->ptr+beg+RSTRING(val)->len,
- RSTRING(str)->ptr+beg+len,
- RSTRING(str)->len-(beg+len));
+ memmove(RSTRING(str)->ptr + beg + RSTRING(val)->len,
+ RSTRING(str)->ptr + beg + len,
+ RSTRING(str)->len - (beg + len));
+ }
+ if (RSTRING(str)->len < beg && len < 0) {
+ MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, -len);
}
memcpy(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len);
RSTRING(str)->len += RSTRING(val)->len - len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
}
-/* str_replace2() understands negatice offset */
+/* rb_str_replace2() understands negatice offset */
static void
-str_replace2(str, beg, end, val)
- VALUE str, *val;
- int beg, end;
+rb_str_replace2(str, beg, end, val)
+ VALUE str, val;
+ size_t beg, end;
{
- int len;
+ size_t len;
if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- IndexError("end smaller than beg [%d..%d]", beg, end);
+ rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", beg, end);
}
if (beg < 0) {
@@ -827,307 +888,295 @@ str_replace2(str, beg, end, val)
len = 0;
}
- str_replace(str, beg, len, val);
+ rb_str_replace(str, beg, len, val);
}
-static VALUE
-str_sub_s(str, pat, val, once)
- VALUE str, pat, val;
- int once;
-{
- VALUE result, repl;
- int beg, offset, n;
- struct re_registers *regs;
-
- switch (TYPE(pat)) {
- case T_REGEXP:
- break;
-
- case T_STRING:
- pat = reg_regcomp(pat);
- break;
-
- default:
- /* type failed */
- Check_Type(pat, T_REGEXP);
- }
-
- val = obj_as_string(val);
- result = str_new(0,0);
- offset=0; n=0;
- while ((beg=reg_search(pat, str, offset, 0)) >= 0) {
- n++;
-
- regs = RMATCH(backref_get())->regs;
- str_cat(result, RSTRING(str)->ptr+offset, beg-offset);
-
- repl = reg_regsub(val, str, regs);
- str_cat(result, RSTRING(repl)->ptr, RSTRING(repl)->len);
- if (END(0) == offset) {
- /*
- * Always consume at least one character of the input string
- * in order to prevent infinite loops.
- */
- if (RSTRING(str)->len > 0) {
- str_cat(result, RSTRING(str)->ptr+END(0), 1);
- }
- offset = END(0)+1;
- }
- else {
- offset = END(0);
- }
-
- if (once) break;
- if (offset >= STRLEN(str)) break;
- }
- if (n == 0) return Qnil;
- if (RSTRING(str)->len > offset) {
- str_cat(result, RSTRING(str)->ptr+offset, RSTRING(str)->len-offset);
- }
-
- if (str_tainted(val)) str_taint(result);
- return result;
-}
+static VALUE rb_str_sub_bang _((int, VALUE*, VALUE));
static VALUE
-str_sub_f(str, pat, val, once)
- VALUE str;
- VALUE pat;
- VALUE val;
- int once;
-{
- VALUE result;
-
- str_modify(str);
- result = str_sub_s(str, pat, val, once);
-
- if (NIL_P(result)) return Qnil;
- str_resize(str, RSTRING(result)->len);
- memcpy(RSTRING(str)->ptr, RSTRING(result)->ptr, RSTRING(result)->len);
- if (str_tainted(result)) str_taint(str);
-
- return (VALUE)str;
-}
-
-static VALUE
-str_sub_iter_s(str, pat, once)
- VALUE str;
- VALUE pat;
- int once;
-{
- VALUE val, result;
- int beg, offset, n, null;
- struct re_registers *regs;
-
- if (!iterator_p()) {
- ArgError("Wrong # of arguments(1 for 2)");
- }
-
- switch (TYPE(pat)) {
- case T_REGEXP:
- break;
-
- case T_STRING:
- pat = reg_regcomp(pat);
- break;
-
- default:
- /* type failed */
- Check_Type(pat, T_REGEXP);
- }
-
- result = str_new(0,0);
- n = 0; offset = 0;
- while ((beg=reg_search(pat, str, offset, 0)) >= 0) {
- n++;
-
- null = 0;
- str_cat(result, RSTRING(str)->ptr+offset, beg-offset);
-
- regs = RMATCH(backref_get())->regs;
- if (END(0) == offset) {
- null = 1;
- offset = END(0)+1;
- }
- else {
- offset = END(0);
- }
-
- val = rb_yield(reg_nth_match(0, backref_get()));
- val = obj_as_string(val);
- str_cat(result, RSTRING(val)->ptr, RSTRING(val)->len);
- if (null && RSTRING(str)->len) {
- str_cat(result, RSTRING(str)->ptr+offset-1, 1);
- }
-
- if (once) break;
- if (offset >= STRLEN(str)) break;
- }
- if (n == 0) return Qnil;
- if (RSTRING(str)->len > offset) {
- str_cat(result, RSTRING(str)->ptr+offset, RSTRING(str)->len-offset);
- }
-
- return result;
-}
-
-static VALUE
-str_sub_iter_f(str, pat, once)
- VALUE str;
- VALUE pat;
- int once;
-{
- VALUE result;
-
- str_modify(str);
- result = str_sub_iter_s(str, pat, once);
-
- if (NIL_P(result)) return Qnil;
- str_resize(str, RSTRING(result)->len);
- memcpy(RSTRING(str)->ptr, RSTRING(result)->ptr, RSTRING(result)->len);
-
- return (VALUE)str;
-}
-
-static VALUE
-str_aset(str, indx, val)
+rb_str_aset(str, indx, val)
VALUE str;
VALUE indx, val;
{
- int idx, beg, end, offset;
+ size_t idx, beg, end;
switch (TYPE(indx)) {
case T_FIXNUM:
- idx = NUM2INT(indx);
+ idx = NUM2UINT(indx);
if (idx < 0) {
idx = RSTRING(str)->len + idx;
}
if (idx < 0 || RSTRING(str)->len <= idx) {
- IndexError("index %d out of range [0..%d]", idx, RSTRING(str)->len-1);
+ rb_raise(rb_eIndexError, "index %d out of range [0..%d]", idx,
+ RSTRING(str)->len - 1);
+ }
+ if (TYPE(val) == T_STRING) {
+ rb_str_replace(str, idx, 1, val);
+ }
+ else {
+ RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff;
}
- RSTRING(str)->ptr[idx] = FIX2INT(val) & 0xff;
return val;
case T_REGEXP:
- str_sub_f(str, indx, val, 0);
+ {
+ VALUE args[2];
+ args[0] = indx;
+ args[1] = val;
+ rb_str_sub_bang(2, args, str);
+ }
return val;
case T_STRING:
- for (offset=0;
- (beg=str_index(str, indx, offset)) >= 0;
- offset=beg+STRLEN(val)) {
- end = beg + STRLEN(indx) - 1;
- str_replace2(str, beg, end, val);
+ beg = rb_str_index(str, indx, 0);
+ if (beg != (size_t)-1) {
+ end = beg + RSTRING(indx)->len - 1;
+ rb_str_replace2(str, beg, end, val);
}
- if (offset == 0) return Qnil;
return val;
default:
/* check if indx is Range */
{
- int beg, end;
- if (range_beg_end(indx, &beg, &end)) {
- str_replace2(str, beg, end, val);
+ size_t beg, end;
+ if (rb_range_beg_end(indx, &beg, &end)) {
+ if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
+ rb_str_replace2(str, beg, end, val);
return val;
}
}
- IndexError("Invalid index for string");
+ rb_raise(rb_eIndexError, "Invalid index for string");
}
}
static VALUE
-str_aset_method(argc, argv, str)
+rb_str_aset_method(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE arg1, arg2, arg3;
- str_modify(str);
+ rb_str_modify(str);
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- int beg, len;
-
- Check_Type(arg3, T_STRING);
+ size_t beg, len;
- beg = NUM2INT(arg1);
+ if (TYPE(arg3) != T_STRING) arg3 = rb_str_to_str(arg3);
+ beg = NUM2UINT(arg1);
if (beg < 0) {
beg = RSTRING(str)->len + beg;
if (beg < 0) beg = 0;
}
- len = NUM2INT(arg2);
- if (len < 0) IndexError("negative length %d", len);
+ len = NUM2UINT(arg2);
+ if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
if (beg + len > RSTRING(str)->len) {
len = RSTRING(str)->len - beg;
}
- str_replace(str, beg, len, arg3);
+ rb_str_replace(str, beg, len, arg3);
return arg3;
}
- return str_aset(str, arg1, arg2);
+ return rb_str_aset(str, arg1, arg2);
}
static VALUE
-str_sub_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
+get_pat(pat)
+ VALUE pat;
{
- VALUE pat, val;
+ switch (TYPE(pat)) {
+ case T_REGEXP:
+ break;
+
+ case T_STRING:
+ pat = rb_reg_regcomp(pat);
+ break;
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter_f(str, pat, 1);
+ default:
+ /* type failed */
+ Check_Type(pat, T_REGEXP);
}
- return str_sub_f(str, pat, val, 1);
+ return pat;
}
static VALUE
-str_sub(argc, argv, str)
+rb_str_sub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- VALUE pat, val, v;
+ VALUE pat, repl, match;
+ struct re_registers *regs;
+ int iter = 0;
+ size_t plen;
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- v = str_sub_iter_s(str, pat, 1);
+ if (argc == 1 && rb_iterator_p()) {
+ iter = 1;
+ }
+ else if (argc == 2) {
+ repl = rb_obj_as_string(argv[1]);;
}
else {
- v = str_sub_s(str, pat, val, 1);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
}
- if (NIL_P(v)) return str_dup(str);
- return v;
+
+ pat = get_pat(argv[0]);
+ if (rb_reg_search(pat, str, 0, 0) >= 0) {
+ rb_str_modify(str);
+ match = rb_backref_get();
+ regs = RMATCH(match)->regs;
+
+ if (iter) {
+ repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+ }
+ else {
+ repl = rb_reg_regsub(repl, str, regs);
+ }
+ plen = END(0) - BEG(0);
+ if (RSTRING(repl)->len > plen) {
+ REALLOC_N(RSTRING(str)->ptr, char,
+ RSTRING(str)->len + RSTRING(repl)->len - plen + 1);
+ }
+ if (RSTRING(repl)->len != plen) {
+ memmove(RSTRING(str)->ptr + BEG(0) + RSTRING(repl)->len,
+ RSTRING(str)->ptr + BEG(0) + plen,
+ RSTRING(str)->len - BEG(0) - plen);
+ }
+ memcpy(RSTRING(str)->ptr + BEG(0),
+ RSTRING(repl)->ptr, RSTRING(repl)->len);
+ RSTRING(str)->len += RSTRING(repl)->len - plen;
+ RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
+ return str;
+ }
+ return Qnil;
}
static VALUE
-str_gsub_bang(argc, argv, str)
+rb_str_sub(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- VALUE pat, val;
+ VALUE val = rb_str_sub_bang(argc, argv, str = rb_str_dup(str));
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter_f(str, pat, 0);
- }
- return str_sub_f(str, pat, val, 0);
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_gsub(argc, argv, str)
+rb_str_gsub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- VALUE pat, val, v;
+ VALUE pat, val, repl, match;
+ struct re_registers *regs;
+ int beg, offset, n;
+ int iter = 0;
+ char *buf, *bp, *cp;
+ size_t blen, len;
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- v = str_sub_iter_s(str, pat, 0);
+ if (argc == 1 && rb_iterator_p()) {
+ iter = 1;
+ }
+ else if (argc == 2) {
+ repl = rb_obj_as_string(argv[1]);;
}
else {
- v = str_sub_s(str, pat, val, 0);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
+ }
+
+ pat = get_pat(argv[0]);
+ offset=0; n=0;
+ beg = rb_reg_search(pat, str, 0, 0);
+ if (beg < 0) return Qnil; /* no match, no substitution */
+
+ blen = RSTRING(str)->len + 30; /* len + margin */
+ buf = ALLOC_N(char, blen);
+ bp = buf;
+ cp = RSTRING(str)->ptr;
+
+ while (beg >= 0) {
+ n++;
+ match = rb_backref_get();
+ regs = RMATCH(match)->regs;
+ if (iter) {
+ val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+ }
+ else {
+ val = rb_reg_regsub(repl, str, regs);
+ }
+ len = (bp - buf) + (beg - offset) + RSTRING(val)->len + 3;
+ if (blen < len) {
+ while (blen < len) blen *= 2;
+ len = bp - buf;
+ REALLOC_N(buf, char, blen);
+ bp = buf + len;
+ }
+ len = beg - offset; /* copy pre-match substr */
+ memcpy(bp, cp, len);
+ bp += len;
+ memcpy(bp, RSTRING(val)->ptr, RSTRING(val)->len);
+ bp += RSTRING(val)->len;
+ if (BEG(0) == END(0)) {
+ /*
+ * Always consume at least one character of the input string
+ * in order to prevent infinite loops.
+ */
+ len = mbclen(RSTRING(str)->ptr[END(0)]);
+ if (RSTRING(str)->len > END(0)) {
+ memcpy(bp, RSTRING(str)->ptr+END(0), len);
+ bp += len;
+ }
+ offset = END(0) + len;
+ }
+ else {
+ offset = END(0);
+ }
+ cp = RSTRING(str)->ptr + offset;
+ if (offset > RSTRING(str)->len) break;
+ beg = rb_reg_search(pat, str, offset, 0);
+ }
+ if (RSTRING(str)->len > offset) {
+ len = bp - buf;
+ if (blen - len < RSTRING(str)->len - offset) {
+ REALLOC_N(buf, char, len + RSTRING(str)->len - offset + 1);
+ bp = buf + len;
+ }
+ memcpy(bp, cp, RSTRING(str)->len - offset);
+ bp += RSTRING(str)->len - offset;
}
- if (NIL_P(v)) return str_dup(str);
- return v;
+ rb_str_modify(str);
+ free(RSTRING(str)->ptr);
+ RSTRING(str)->ptr = buf;
+ RSTRING(str)->len = len = bp - buf;
+ RSTRING(str)->ptr[len] = '\0';
+
+ return str;
+}
+
+static VALUE
+rb_str_gsub(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
+{
+ VALUE val = rb_str_gsub_bang(argc, argv, str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
+}
+
+static VALUE
+rb_str_replace_method(str, str2)
+ VALUE str, str2;
+{
+ if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
+ rb_str_modify(str);
+ rb_str_resize(str, RSTRING(str2)->len);
+ memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
+
+ return str;
}
static VALUE
@@ -1135,108 +1184,86 @@ uscore_get()
{
VALUE line;
- line = lastline_get();
+ line = rb_lastline_get();
if (TYPE(line) != T_STRING) {
- TypeError("$_ value need to be String (%s given)",
- rb_class2name(CLASS_OF(line)));
+ rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
+ NIL_P(line)?"nil":rb_class2name(CLASS_OF(line)));
}
return line;
}
static VALUE
-f_sub_bang(argc, argv)
+rb_f_sub_bang(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val, line;
-
- line = uscore_get();
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter_f(line, pat, 1);
- }
- return str_sub_f(line, pat, val, 1);
+ return rb_str_sub_bang(argc, argv, uscore_get());
}
static VALUE
-f_sub(argc, argv)
+rb_f_sub(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val, line, v;
+ VALUE line, v;
- line = uscore_get();
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- v = str_sub_iter_s(line, pat, 1);
- }
- else {
- v = str_sub_s(line, pat, val, 1);
- }
- if (!NIL_P(v)) {
- lastline_set(v);
- return v;
- }
- return line;
+ line = rb_str_dup(uscore_get());
+ v = rb_str_sub_bang(argc, argv, line);
+ if (NIL_P(v)) return line;
+ rb_lastline_set(v);
+ return v;
}
static VALUE
-f_gsub_bang(argc, argv)
+rb_f_gsub_bang(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val, line;
-
- line = uscore_get();
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter_f(line, pat, 0);
- }
- return str_sub_f(line, pat, val, 0);
+ return rb_str_gsub_bang(argc, argv, uscore_get());
}
static VALUE
-f_gsub(argc, argv)
+rb_f_gsub(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val, line, v;
-
- line = uscore_get();
- if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- v = str_sub_iter_s(line, pat, 0);
- }
- else {
- v = str_sub_s(line, pat, val, 0);
- }
- if (NIL_P(v)) v = str_dup(line);
- lastline_set(v);
+ VALUE line, v;
+ line = rb_str_dup(uscore_get());
+ v = rb_str_gsub_bang(argc, argv, line);
+ if (NIL_P(v)) return line;
+ rb_lastline_set(v);
return v;
}
static VALUE
-str_reverse_bang(str)
+rb_str_reverse_bang(str)
VALUE str;
{
- UCHAR *s, *e, *p;
+ char *s, *e, *p, *q;
s = RSTRING(str)->ptr;
e = s + RSTRING(str)->len - 1;
- p = ALLOCA_N(char, RSTRING(str)->len);
+ p = q = ALLOCA_N(char, RSTRING(str)->len);
while (e >= s) {
*p++ = *e--;
}
- MEMCPY(RSTRING(str)->ptr, p, char, RSTRING(str)->len);
+ MEMCPY(RSTRING(str)->ptr, q, char, RSTRING(str)->len);
- return (VALUE)str;
+ return str;
}
static VALUE
-str_reverse(str)
+rb_str_reverse(str)
VALUE str;
{
- VALUE obj = str_new(0, RSTRING(str)->len);
- UCHAR *s, *e, *p;
+ VALUE obj;
+ char *s, *e, *p;
+
+ if (RSTRING(str)->len <= 1) return str;
+ obj = rb_str_new(0, RSTRING(str)->len);
s = RSTRING(str)->ptr; e = s + RSTRING(str)->len - 1;
p = RSTRING(obj)->ptr;
@@ -1248,14 +1275,14 @@ str_reverse(str)
}
static VALUE
-str_include(str, arg)
+rb_str_include(str, arg)
VALUE str, arg;
{
- int i;
+ size_t i;
if (FIXNUM_P(arg)) {
int c = FIX2INT(arg);
- int len = RSTRING(str)->len;
+ size_t len = RSTRING(str)->len;
char *p = RSTRING(str)->ptr;
for (i=0; i<len; i++) {
@@ -1263,51 +1290,47 @@ str_include(str, arg)
return INT2FIX(i);
}
}
- return FALSE;
+ return Qfalse;
}
- Check_Type(arg, T_STRING);
- i = str_index(str, arg, 0);
+ if (TYPE(arg) != T_STRING) arg = rb_str_to_str(arg);
+ i = rb_str_index(str, arg, 0);
- if (i == -1) return FALSE;
+ if (i == (size_t)-1) return Qfalse;
return INT2FIX(i);
}
static VALUE
-str_to_i(str)
+rb_str_to_i(str)
VALUE str;
{
- return str2inum(RSTRING(str)->ptr, 10);
+ return rb_str2inum(RSTRING(str)->ptr, 10);
}
-#ifndef atof
-double atof();
-#endif
-
static VALUE
-str_to_f(str)
+rb_str_to_f(str)
VALUE str;
{
double f = atof(RSTRING(str)->ptr);
- return float_new(f);
+ return rb_float_new(f);
}
static VALUE
-str_to_s(str)
+rb_str_to_s(str)
VALUE str;
{
return str;
}
VALUE
-str_inspect(str)
+rb_str_inspect(str)
VALUE str;
{
#define STRMAX 80
- UCHAR buf[STRMAX];
- UCHAR *p, *pend;
- UCHAR *b;
+ char buf[STRMAX];
+ char *p, *pend;
+ char *b;
p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
b = buf;
@@ -1322,23 +1345,26 @@ str_inspect(str)
}
while (p < pend) {
- UCHAR c = *p++;
+ char c = *p++;
if (ismbchar(c) && p < pend) {
- CHECK(2);
+ int len = mbclen(c)-1;
+
+ CHECK(len);
*b++ = c;
- *b++ = *p++;
+ while (len--) {
+ *b++ = *p++;
+ }
}
- else if (c == '"') {
- CHECK(2);
- *b++ = '\\';
- *b++ = '"';
+ else if ((c & 0x80) && rb_kcode() != MBCTYPE_EUC) {
+ CHECK(1);
+ *b++ = c;
}
- else if (c == '\\') {
+ else if (c == '"'|| c == '\\') {
CHECK(2);
*b++ = '\\';
- *b++ = '\\';
+ *b++ = c;
}
- else if (isprint(c)) {
+ else if (ISPRINT(c)) {
CHECK(1);
*b++ = c;
}
@@ -1362,7 +1388,7 @@ str_inspect(str)
*b++ = '\\';
*b++ = 'f';
}
- else if (c == '\13') {
+ else if (c == '\013') {
CHECK(2);
*b++ = '\\';
*b++ = 'v';
@@ -1380,123 +1406,248 @@ str_inspect(str)
else {
CHECK(4);
*b++ = '\\';
- sprintf(b, "%03o", c);
+ sprintf(b, "%03o", c & 0377);
b += 3;
}
}
*b++ = '"';
- return str_new(buf, b - buf);
+ return rb_str_new(buf, b - buf);
+}
+
+static VALUE
+rb_str_dump(str)
+ VALUE str;
+{
+ size_t len;
+ char *p, *pend;
+ char *q, *qend;
+ VALUE result;
+
+ len = 2; /* "" */
+ p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
+ while (p < pend) {
+ char c = *p++;
+ switch (c) {
+ case '"': case '\\':
+ case '\n': case '\r':
+ case '\t': case '\f':
+ case '\013': case '\007': case '\033':
+ len += 2;
+ break;
+
+ default:
+ if (ISPRINT(c)) {
+ len++;
+ }
+ else {
+ len += 4; /* \nnn */
+ }
+ break;
+ }
+ }
+
+ result = rb_str_new(0, len);
+ p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
+ q = RSTRING(result)->ptr; qend = q + len;
+
+ *q++ = '"';
+ while (p < pend) {
+ char c = *p++;
+
+ if (c == '"' || c == '\\') {
+ *q++ = '\\';
+ *q++ = c;
+ }
+ else if (ISPRINT(c)) {
+ *q++ = c;
+ }
+ else if (c == '\n') {
+ *q++ = '\\';
+ *q++ = 'n';
+ }
+ else if (c == '\r') {
+ *q++ = '\\';
+ *q++ = 'r';
+ }
+ else if (c == '\t') {
+ *q++ = '\\';
+ *q++ = 't';
+ }
+ else if (c == '\f') {
+ *q++ = '\\';
+ *q++ = 'f';
+ }
+ else if (c == '\013') {
+ *q++ = '\\';
+ *q++ = 'v';
+ }
+ else if (c == '\007') {
+ *q++ = '\\';
+ *q++ = 'a';
+ }
+ else if (c == '\033') {
+ *q++ = '\\';
+ *q++ = 'e';
+ }
+ else {
+ *q++ = '\\';
+ sprintf(q, "%03o", c&0xff);
+ q += 3;
+ }
+ }
+ *q++ = '"';
+
+ return result;
}
static VALUE
-str_upcase_bang(str)
+rb_str_upcase_bang(str)
VALUE str;
{
- UCHAR *s, *send;
+ char *s, *send;
+ int modify = 0;
- str_modify(str);
+ rb_str_modify(str);
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
- if (islower(*s)) {
+ if (ismbchar(*s)) {
+ s+=mbclen(*s);
+ }
+ else if (islower(*s)) {
*s = toupper(*s);
+ modify = 1;
}
s++;
}
- return (VALUE)str;
+ if (modify) return str;
+ return Qnil;
}
static VALUE
-str_upcase(str)
+rb_str_upcase(str)
VALUE str;
{
- return str_upcase_bang(str_dup(str));
+ VALUE val = rb_str_upcase_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_downcase_bang(str)
+rb_str_downcase_bang(str)
VALUE str;
{
- UCHAR *s, *send;
+ char *s, *send;
+ int modify = 0;
- str_modify(str);
+ rb_str_modify(str);
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
- if (isupper(*s)) {
+ if (ismbchar(*s)) {
+ s+=mbclen(*s);
+ }
+ else if (ISUPPER(*s)) {
*s = tolower(*s);
+ modify = 1;
}
s++;
}
- return (VALUE)str;
+ if (modify) return str;
+ return Qnil;
}
static VALUE
-str_downcase(str)
+rb_str_downcase(str)
VALUE str;
{
- return str_downcase_bang(str_dup(str));
+ VALUE val = rb_str_downcase_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_capitalize_bang(str)
+rb_str_capitalize_bang(str)
VALUE str;
{
- UCHAR *s, *send;
+ char *s, *send;
+ int modify = 0;
- str_modify(str);
+ rb_str_modify(str);
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- if (islower(*s))
+ if (ISLOWER(*s)) {
*s = toupper(*s);
+ modify = 1;
+ }
while (++s < send) {
- if (isupper(*s)) {
+ if (ismbchar(*s)) {
+ s+=mbclen(*s);
+ }
+ else if (ISUPPER(*s)) {
*s = tolower(*s);
+ modify = 1;
}
}
- return (VALUE)str;
+ if (modify) return str;
+ return Qnil;
}
static VALUE
-str_capitalize(str)
+rb_str_capitalize(str)
VALUE str;
{
- return str_capitalize_bang(str_dup(str));
+ VALUE val = rb_str_capitalize_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_swapcase_bang(str)
+rb_str_swapcase_bang(str)
VALUE str;
{
- UCHAR *s, *send;
+ char *s, *send;
+ int modify = 0;
- str_modify(str);
+ rb_str_modify(str);
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
- if (isupper(*s)) {
+ if (ismbchar(*s)) {
+ s+=mbclen(*s);
+ }
+ else if (ISUPPER(*s)) {
*s = tolower(*s);
+ modify = 1;
}
- else if (islower(*s)) {
+ else if (ISLOWER(*s)) {
*s = toupper(*s);
+ modify = 1;
}
s++;
}
- return (VALUE)str;
+ if (modify) return str;
+ return Qnil;
}
static VALUE
-str_swapcase(str)
+rb_str_swapcase(str)
VALUE str;
{
- return str_swapcase_bang(str_dup(str));
+ VALUE val = rb_str_swapcase_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
-typedef UCHAR *USTR;
+typedef unsigned char *USTR;
-static struct tr {
+struct tr {
int gen, now, max;
- UCHAR *p, *pend;
-} trsrc, trrepl;
+ char *p, *pend;
+};
static int
trnext(t)
@@ -1505,7 +1656,7 @@ trnext(t)
for (;;) {
if (!t->gen) {
if (t->p == t->pend) return -1;
- t->now = *t->p++;
+ t->now = *(USTR)t->p++;
if (t->p < t->pend && *t->p == '-') {
t->p++;
if (t->p < t->pend) {
@@ -1529,7 +1680,7 @@ trnext(t)
}
}
-static VALUE str_delete_bang();
+static VALUE rb_str_delete_bang _((VALUE,VALUE));
static VALUE
tr_trans(str, src, repl, sflag)
@@ -1538,19 +1689,21 @@ tr_trans(str, src, repl, sflag)
{
struct tr trsrc, trrepl;
int cflag = 0;
- UCHAR trans[256];
- int i, c, c0;
- UCHAR *s, *send, *t;
+ char trans[256];
+ int i, c, c0, modify = 0;
+ char *s, *send;
- Check_Type(src, T_STRING);
+ rb_str_modify(str);
+ if (TYPE(src) != T_STRING) src = rb_str_to_str(src);
trsrc.p = RSTRING(src)->ptr; trsrc.pend = trsrc.p + RSTRING(src)->len;
if (RSTRING(src)->len > 2 && RSTRING(src)->ptr[0] == '^') {
cflag++;
trsrc.p++;
}
- Check_Type(repl, T_STRING);
- if (RSTRING(repl)->len == 0) return str_delete_bang(str, src);
- trrepl.p = RSTRING(repl)->ptr; trrepl.pend = trrepl.p + RSTRING(repl)->len;
+ if (TYPE(repl) != T_STRING) repl = rb_str_to_str(repl);
+ if (RSTRING(repl)->len == 0) return rb_str_delete_bang(str, src);
+ trrepl.p = RSTRING(repl)->ptr;
+ trrepl.pend = trrepl.p + RSTRING(repl)->len;
trsrc.gen = trrepl.gen = 0;
trsrc.now = trrepl.now = 0;
trsrc.max = trrepl.max = 0;
@@ -1590,48 +1743,64 @@ tr_trans(str, src, repl, sflag)
}
}
- str_modify(str);
- t = s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
+ s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
c0 = -1;
if (sflag) {
+ char *t = s;
+
while (s < send) {
c = trans[*s++ & 0xff] & 0xff;
if (s[-1] == c || c != c0) {
c0 = (s[-1] == c)?-1:c;
+ if (*t != c) {
+ *t = c;
+ modify = 1;
+ }
*t++ = c;
}
}
+ if (RSTRING(str)->len > (t - RSTRING(str)->ptr)) {
+ RSTRING(str)->len = (t - RSTRING(str)->ptr);
+ modify = 1;
+ *t = '\0';
+ }
}
else {
while (s < send) {
- c = trans[*s++ & 0xff] & 0xff;
- *t++ = c;
+ c = trans[*s & 0xff] & 0xff;
+ if (*s != c) {
+ *s = c;
+ modify = 1;
+ }
+ s++;
}
}
- *t = '\0';
- if (sflag) RSTRING(str)->len = (t - RSTRING(str)->ptr);
- return (VALUE)str;
+ if (modify) return str;
+ return Qnil;
}
static VALUE
-str_tr_bang(str, src, repl)
+rb_str_tr_bang(str, src, repl)
VALUE str, src, repl;
{
return tr_trans(str, src, repl, 0);
}
static VALUE
-str_tr(str, src, repl)
+rb_str_tr(str, src, repl)
VALUE str, src, repl;
{
- return tr_trans(str_dup(str), src, repl, 0);
+ VALUE val = tr_trans(str = rb_str_dup(str), src, repl, 0);
+
+ if (NIL_P(val)) return str;
+ return val;
}
static void
tr_setup_table(str, table)
VALUE str;
- UCHAR table[256];
+ char table[256];
{
struct tr tr;
int i, cflag = 0;
@@ -1653,45 +1822,51 @@ tr_setup_table(str, table)
}
static VALUE
-str_delete_bang(str1, str2)
- VALUE str1, *str2;
+rb_str_delete_bang(str1, str2)
+ VALUE str1, str2;
{
- UCHAR *s, *send, *t;
- UCHAR squeez[256];
+ char *s, *send, *t;
+ char squeez[256];
+ int modify = 0;
- Check_Type(str2, T_STRING);
+ if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
tr_setup_table(str2, squeez);
- str_modify(str1);
+ rb_str_modify(str1);
s = t = RSTRING(str1)->ptr;
send = s + RSTRING(str1)->len;
while (s < send) {
- if (!squeez[*s & 0xff]) {
+ if (squeez[*s & 0xff])
+ modify = 1;
+ else
*t++ = *s;
- }
s++;
}
*t = '\0';
RSTRING(str1)->len = t - RSTRING(str1)->ptr;
- return (VALUE)str1;
+ if (modify) return str1;
+ return Qnil;
}
static VALUE
-str_delete(str1, str2)
- VALUE str1, *str2;
+rb_str_delete(str1, str2)
+ VALUE str1, str2;
{
- return str_delete_bang(str_dup(str1), str2);
+ VALUE val = rb_str_delete_bang(str1 = rb_str_dup(str1), str2);
+
+ if (NIL_P(val)) return str1;
+ return val;
}
static VALUE
tr_squeeze(str1, str2)
VALUE str1, str2;
{
- UCHAR squeez[256];
- UCHAR *s, *send, *t;
- char c, save;
+ char squeez[256];
+ char *s, *send, *t;
+ char c, save, modify = 0;
if (!NIL_P(str2)) {
tr_setup_table(str2, squeez);
@@ -1704,7 +1879,7 @@ tr_squeeze(str1, str2)
}
}
- str_modify(str1);
+ rb_str_modify(str1);
s = t = RSTRING(str1)->ptr;
send = s + RSTRING(str1)->len;
@@ -1713,78 +1888,82 @@ tr_squeeze(str1, str2)
c = *s++ & 0xff;
if (c != save || !squeez[c & 0xff]) {
*t++ = save = c;
+ modify = 1;
}
}
*t = '\0';
RSTRING(str1)->len = t - RSTRING(str1)->ptr;
- return (VALUE)str1;
+ if (modify) return str1;
+ return Qnil;
}
static VALUE
-str_squeeze_bang(argc, argv, str1)
+rb_str_squeeze_bang(argc, argv, str1)
int argc;
VALUE *argv;
VALUE str1;
{
VALUE str2;
- if (rb_scan_args(argc, argv, "01", &str2) == 1) {
- Check_Type(str2, T_STRING);
+ if (rb_scan_args(argc, argv, "01", &str2) == 1 && TYPE(str2) != T_STRING) {
+ str2 = rb_str_to_str(str2);
}
return tr_squeeze(str1, str2);
}
static VALUE
-str_squeeze(argc, argv, str)
+rb_str_squeeze(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- return str_squeeze_bang(argc, argv, str_dup(str));
+ VALUE val = rb_str_squeeze_bang(argc, argv, str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_tr_s_bang(str, src, repl)
+rb_str_tr_s_bang(str, src, repl)
VALUE str, src, repl;
{
- Check_Type(src, T_STRING);
- Check_Type(repl, T_STRING);
-
return tr_trans(str, src, repl, 1);
}
static VALUE
-str_tr_s(str, src, repl)
+rb_str_tr_s(str, src, repl)
VALUE str, src, repl;
{
- return str_tr_s_bang(str_dup(str), src, repl);
+ VALUE val = tr_trans(str = rb_str_dup(str), src, repl, 1);
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-str_split_method(argc, argv, str)
+rb_str_split_method(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- extern VALUE FS;
VALUE spat;
VALUE limit;
- char char_sep = 0;
- int beg, end, lim, i;
+ int char_sep = -1;
+ int beg, end, i;
+ int lim = 0;
VALUE result, tmp;
- rb_scan_args(argc, argv, "02", &spat, &limit);
- if (!NIL_P(limit)) {
+ if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
lim = NUM2INT(limit);
- if (lim == 0) limit = Qnil;
- else if (lim == 1) return ary_new3(1, str);
+ if (lim <= 0) limit = Qnil;
+ else if (lim == 1) return rb_ary_new3(1, str);
i = 1;
}
- if (NIL_P(spat)) {
- if (!NIL_P(FS)) {
- spat = FS;
+ if (argc == 0) {
+ if (!NIL_P(rb_fs)) {
+ spat = rb_fs;
goto fs_set;
}
char_sep = ' ';
@@ -1793,33 +1972,33 @@ str_split_method(argc, argv, str)
switch (TYPE(spat)) {
case T_STRING:
fs_set:
- if (STRLEN(spat) == 1) {
- char_sep = RSTRING(spat)->ptr[0];
+ if (RSTRING(spat)->len == 1) {
+ char_sep = (unsigned char)RSTRING(spat)->ptr[0];
}
else {
- spat = reg_regcomp(spat);
+ spat = rb_reg_regcomp(spat);
}
break;
case T_REGEXP:
break;
default:
- ArgError("split(): bad separator");
+ rb_raise(rb_eArgError, "bad separator");
}
}
- result = ary_new();
+ result = rb_ary_new();
beg = 0;
- if (char_sep != 0) {
- UCHAR *ptr = RSTRING(str)->ptr;
- int len = RSTRING(str)->len;
- UCHAR *eptr = ptr + len;
+ if (char_sep >= 0) {
+ char *ptr = RSTRING(str)->ptr;
+ size_t len = RSTRING(str)->len;
+ char *eptr = ptr + len;
if (char_sep == ' ') { /* AWK emulation */
int skip = 1;
for (end = beg = 0; ptr<eptr; ptr++) {
if (skip) {
- if (isspace(*ptr)) {
+ if (ISSPACE(*ptr)) {
beg++;
}
else {
@@ -1828,8 +2007,8 @@ str_split_method(argc, argv, str)
}
}
else {
- if (isspace(*ptr)) {
- ary_push(result, str_substr(str, beg, end-beg));
+ if (ISSPACE(*ptr)) {
+ rb_ary_push(result, rb_str_substr(str, beg, end-beg));
skip = 1;
beg = end + 1;
if (!NIL_P(limit) && lim <= ++i) break;
@@ -1842,8 +2021,8 @@ str_split_method(argc, argv, str)
}
else {
for (end = beg = 0; ptr<eptr; ptr++) {
- if (*ptr == char_sep) {
- ary_push(result, str_substr(str, beg, end-beg));
+ if (*ptr == (char)char_sep) {
+ rb_ary_push(result, rb_str_substr(str, beg, end-beg));
beg = end + 1;
if (!NIL_P(limit) && lim <= ++i) break;
}
@@ -1852,29 +2031,26 @@ str_split_method(argc, argv, str)
}
}
else {
- int start = beg;
+ size_t start = beg;
int last_null = 0;
- int idx;
+ size_t idx;
struct re_registers *regs;
- while ((end = reg_search(spat, str, start, 0)) >= 0) {
- regs = RMATCH(backref_get())->regs;
+ while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
+ regs = RMATCH(rb_backref_get())->regs;
if (start == end && BEG(0) == END(0)) {
if (last_null == 1) {
- if (ismbchar(RSTRING(str)->ptr[beg]))
- ary_push(result, str_substr(str, beg, 2));
- else
- ary_push(result, str_substr(str, beg, 1));
+ rb_ary_push(result, rb_str_substr(str, beg, mbclen(RSTRING(str)->ptr[beg])));
beg = start;
}
else {
- start += ismbchar(RSTRING(str)->ptr[start])?2:1;
+ start += mbclen(RSTRING(str)->ptr[start]);
last_null = 1;
continue;
}
}
else {
- ary_push(result, str_substr(str, beg, end-beg));
+ rb_ary_push(result, rb_str_substr(str, beg, end-beg));
beg = start = END(0);
}
last_null = 0;
@@ -1882,67 +2058,69 @@ str_split_method(argc, argv, str)
for (idx=1; idx < regs->num_regs; idx++) {
if (BEG(idx) == -1) continue;
if (BEG(idx) == END(idx))
- tmp = str_new(0, 0);
+ tmp = rb_str_new(0, 0);
else
- tmp = str_subseq(str, BEG(idx), END(idx)-1);
- ary_push(result, tmp);
+ tmp = rb_str_subseq(str, BEG(idx), END(idx)-1);
+ rb_ary_push(result, tmp);
}
if (!NIL_P(limit) && lim <= ++i) break;
}
}
- if (RSTRING(str)->len > beg) {
- ary_push(result, str_subseq(str, beg, -1));
+ if (!NIL_P(limit) || RSTRING(str)->len > beg || lim < 0) {
+ rb_ary_push(result, rb_str_subseq(str, beg, -1));
+ }
+ if (NIL_P(limit) && lim == 0) {
+ while (RARRAY(result)->len > 0 &&
+ RSTRING(RARRAY(result)->ptr[RARRAY(result)->len-1])->len == 0)
+ rb_ary_pop(result);
}
return result;
}
VALUE
-str_split(str, sep0)
+rb_str_split(str, sep0)
VALUE str;
char *sep0;
{
VALUE sep;
- Check_Type(str, T_STRING);
- sep = str_new2(sep0);
- return str_split_method(1, &sep, str);
+ if (TYPE(str) != T_STRING) str = rb_str_to_str(str);
+ sep = rb_str_new2(sep0);
+ return rb_str_split_method(1, &sep, str);
}
static VALUE
-f_split(argc, argv)
+rb_f_split(argc, argv)
int argc;
VALUE *argv;
{
- return str_split_method(argc, argv, uscore_get());
+ return rb_str_split_method(argc, argv, uscore_get());
}
static VALUE
-str_each_line(argc, argv, str)
+rb_str_each_line(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- extern VALUE RS;
VALUE rs;
int newline;
int rslen;
- UCHAR *p = RSTRING(str)->ptr, *pend = p + RSTRING(str)->len, *s;
- UCHAR *ptr = p;
- int len = RSTRING(str)->len;
+ char *p = RSTRING(str)->ptr, *pend = p + RSTRING(str)->len, *s;
+ char *ptr = p;
+ size_t len = RSTRING(str)->len;
VALUE line;
- if (rb_scan_args(argc, argv, "01", &rs) == 1) {
- if (!NIL_P(rs)) Check_Type(rs, T_STRING);
- }
- else {
- rs = RS;
+ if (rb_scan_args(argc, argv, "01", &rs) == 0) {
+ rs = rb_rs;
}
if (NIL_P(rs)) {
rb_yield(str);
return Qnil;
}
+ if (TYPE(rs) != T_STRING) rs = rb_str_to_str(rs);
rslen = RSTRING(rs)->len;
if (rslen == 0) {
@@ -1954,25 +2132,22 @@ str_each_line(argc, argv, str)
for (s = p, p += rslen; p < pend; p++) {
if (rslen == 0 && *p == '\n') {
- if (*(p+1) != '\n') continue;
+ if (p[1] != '\n') continue;
while (*p == '\n') p++;
- p--;
}
- if (*p == newline &&
+ if (p[-1] == newline &&
(rslen <= 1 ||
- memcmp(RSTRING(rs)->ptr, p-rslen+1, rslen) == 0)) {
- line = str_new(s, p - s + 1);
- lastline_set(line);
+ memcmp(RSTRING(rs)->ptr, p-rslen, rslen) == 0)) {
+ line = rb_str_new(s, p - s);
rb_yield(line);
if (RSTRING(str)->ptr != ptr || RSTRING(str)->len != len)
- Fail("string modified");
- s = p + 1;
+ rb_raise(rb_eArgError, "string modified");
+ s = p;
}
}
if (s != pend) {
- line = str_new(s, p - s);
- lastline_set(line);
+ line = rb_str_new(s, p - s);
rb_yield(line);
}
@@ -1980,10 +2155,10 @@ str_each_line(argc, argv, str)
}
static VALUE
-str_each_byte(str)
+rb_str_each_byte(str)
struct RString* str;
{
- int i;
+ size_t i;
for (i=0; i<RSTRING(str)->len; i++) {
rb_yield(INT2FIX(RSTRING(str)->ptr[i] & 0xff));
@@ -1992,12 +2167,11 @@ str_each_byte(str)
}
static VALUE
-str_chop_bang(str)
+rb_str_chop_bang(str)
VALUE str;
{
- str_modify(str);
-
if (RSTRING(str)->len > 0) {
+ rb_str_modify(str);
RSTRING(str)->len--;
if (RSTRING(str)->ptr[RSTRING(str)->len] == '\n') {
if (RSTRING(str)->len > 0 &&
@@ -2006,90 +2180,132 @@ str_chop_bang(str)
}
}
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
+ return str;
}
-
- return str;
+ return Qnil;
}
static VALUE
-str_chop(str)
+rb_str_chop(str)
VALUE str;
{
- return str_chop_bang(str_dup(str));
+ VALUE val = rb_str_chop_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-f_chop_bang(str)
+rb_f_chop_bang(str)
VALUE str;
{
- return str_chop_bang(uscore_get());
+ return rb_str_chop_bang(uscore_get());
}
static VALUE
-f_chop()
+rb_f_chop()
{
- return str_chop_bang(str_dup(uscore_get()));
+ VALUE str = rb_str_dup(uscore_get());
+ VALUE val = rb_str_chop_bang(str);
+
+ if (NIL_P(str)) return str;
+ rb_lastline_set(val);
+ return val;
}
static VALUE
-str_chomp_bang(str)
+rb_str_chomp_bang(argc, argv, str)
+ int argc;
+ VALUE *argv;
VALUE str;
{
- str_modify(str);
+ VALUE rs;
+ int newline;
+ int rslen;
+ char *p = RSTRING(str)->ptr;
+ size_t len = RSTRING(str)->len;
- if (RSTRING(str)->len > 0 &&
- RSTRING(str)->ptr[RSTRING(str)->len-1] == '\n') {
- RSTRING(str)->len--;
- if (RSTRING(str)->len > 0 &&
- RSTRING(str)->ptr[RSTRING(str)->len] == '\r') {
- RSTRING(str)->len--;
+ if (rb_scan_args(argc, argv, "01", &rs) == 0) {
+ rs = rb_rs;
+ }
+ if (NIL_P(rs)) return Qnil;
+
+ if (TYPE(rs) != T_STRING) rs = rb_str_to_str(rs);
+ rslen = RSTRING(rs)->len;
+ if (rslen == 0) {
+ while (len>0 && p[len-1] == '\n') {
+ len--;
+ }
+ if (len < RSTRING(str)->len) {
+ RSTRING(str)->len = len;
+ RSTRING(str)->ptr[len] = '\0';
+ return str;
}
+ return Qnil;
+ }
+ if (rslen > len) return Qnil;
+ newline = RSTRING(rs)->ptr[rslen-1];
+
+ if (p[len-1] == newline &&
+ (rslen <= 1 ||
+ memcmp(RSTRING(rs)->ptr, p+len-rslen, rslen) == 0)) {
+ RSTRING(str)->len -= rslen;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
+ return str;
}
- return str;
+ return Qnil;
}
static VALUE
-str_chomp(str)
+rb_str_chomp(argc, argv, str)
+ int argc;
+ VALUE *argv;
VALUE str;
{
- return str_chomp_bang(str_dup(str));
+ VALUE val = rb_str_chomp_bang(argc, argv, str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
-f_chomp_bang(str)
- VALUE str;
+rb_f_chomp_bang(argc, argv)
+ int argc;
+ VALUE *argv;
{
- return str_chomp_bang(uscore_get());
+ return rb_str_chomp_bang(argc, argv, uscore_get());
}
static VALUE
-f_chomp()
+rb_f_chomp(argc, argv)
+ int argc;
+ VALUE *argv;
{
- return str_chomp_bang(str_dup(uscore_get()));
+ VALUE str = rb_str_dup(uscore_get());
+ VALUE val = rb_str_chomp_bang(argc, argv, str);
+ return val;
}
static VALUE
-str_strip_bang(str)
+rb_str_strip_bang(str)
VALUE str;
{
- UCHAR *s, *t, *e;
-
- str_modify(str);
+ char *s, *t, *e;
+ rb_str_modify(str);
s = RSTRING(str)->ptr;
e = t = s + RSTRING(str)->len;
/* remove spaces at head */
- while (s < t && isspace(*s)) s++;
+ while (s < t && ISSPACE(*s)) s++;
/* remove trailing spaces */
t--;
- while (s <= t && isspace(*t)) t--;
+ while (s <= t && ISSPACE(*t)) t--;
t++;
RSTRING(str)->len = t-s;
if (s > RSTRING(str)->ptr) {
- UCHAR *p = RSTRING(str)->ptr;
+ char *p = RSTRING(str)->ptr;
RSTRING(str)->ptr = ALLOC_N(char, RSTRING(str)->len+1);
memcpy(RSTRING(str)->ptr, s, RSTRING(str)->len);
@@ -2099,38 +2315,50 @@ str_strip_bang(str)
else if (t < e) {
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
}
+ else {
+ return Qnil;
+ }
- return (VALUE)str;
+ return str;
+}
+
+static VALUE
+rb_str_strip(str)
+ VALUE str;
+{
+ VALUE val = rb_str_strip_bang(str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ return val;
}
static VALUE
scan_once(str, pat, start)
VALUE str, pat;
- int *start;
+ size_t *start;
{
- VALUE result;
+ VALUE result, match;
struct re_registers *regs;
- int i;
+ size_t i;
- if (reg_search(pat, str, *start, 0) >= 0) {
- regs = RMATCH(backref_get())->regs;
- if (END(0) == *start) {
- *start = END(0)+1;
+ if (rb_reg_search(pat, str, *start, 0) >= 0) {
+ match = rb_backref_get();
+ regs = RMATCH(match)->regs;
+ if (BEG(0) == END(0)) {
+ /*
+ * Always consume at least one character of the input string
+ */
+ *start = END(0)+mbclen(RSTRING(str)->ptr[END(0)]);
}
else {
*start = END(0);
}
if (regs->num_regs == 1) {
- return str_substr(str, BEG(0), END(0)-BEG(0));
+ return rb_reg_nth_match(0, match);
}
- result = ary_new2(regs->num_regs);
+ result = rb_ary_new2(regs->num_regs);
for (i=1; i < regs->num_regs; i++) {
- if (BEG(i) == -1) {
- ary_push(result, Qnil);
- }
- else {
- ary_push(result, str_substr(str, BEG(i), END(i)-BEG(i)));
- }
+ rb_ary_push(result, rb_reg_nth_match(i, match));
}
return result;
@@ -2139,27 +2367,18 @@ scan_once(str, pat, start)
}
static VALUE
-str_scan(str, pat)
+rb_str_scan(str, pat)
VALUE str, pat;
{
VALUE result;
- int start = 0;
-
- switch (TYPE(pat)) {
- case T_STRING:
- pat = reg_regcomp(pat);
- break;
- case T_REGEXP:
- break;
- default:
- Check_Type(pat, T_REGEXP);
- }
+ size_t start = 0;
- if (!iterator_p()) {
- VALUE ary = ary_new();
+ pat = get_pat(pat);
+ if (!rb_iterator_p()) {
+ VALUE ary = rb_ary_new();
while (!NIL_P(result = scan_once(str, pat, &start))) {
- ary_push(ary, result);
+ rb_ary_push(ary, result);
}
return ary;
}
@@ -2171,65 +2390,66 @@ str_scan(str, pat)
}
static VALUE
-str_strip(str)
+rb_str_hex(str)
VALUE str;
{
- return str_strip_bang(str_dup(str));
+ return rb_str2inum(RSTRING(str)->ptr, 16);
}
static VALUE
-str_hex(str)
+rb_str_oct(str)
VALUE str;
{
- return str2inum(RSTRING(str)->ptr, 16);
-}
+ int base = 8;
-static VALUE
-str_oct(str)
- VALUE str;
-{
- return str2inum(RSTRING(str)->ptr, 8);
+ if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0' &&
+ (RSTRING(str)->ptr[1] == 'x' || RSTRING(str)->ptr[1] == 'X')) {
+ base = 16;
+ }
+ return rb_str2inum(RSTRING(str)->ptr, base);
}
static VALUE
-str_crypt(str, salt)
+rb_str_crypt(str, salt)
VALUE str, salt;
{
extern char *crypt();
- salt = obj_as_string(salt);
+
+ if (TYPE(salt) != T_STRING) salt = rb_str_to_str(salt);
if (RSTRING(salt)->len < 2)
- ArgError("salt too short(need >2 bytes)");
- return str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr));
+ rb_raise(rb_eArgError, "salt too short(need >2 bytes)");
+ return rb_str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr));
}
static VALUE
-str_intern(str)
+rb_str_intern(str)
VALUE str;
{
ID id;
if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
- ArgError("string contains `\0'");
+ rb_raise(rb_eArgError, "string contains `\\0'");
id = rb_intern(RSTRING(str)->ptr);
return INT2FIX(id);
}
static VALUE
-str_sum(argc, argv, str)
+rb_str_sum(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE vbits;
int bits;
- UCHAR *p, *pend;
+ char *p, *pend;
- rb_scan_args(argc, argv, "01", &vbits);
- if (NIL_P(vbits)) bits = 16;
+ if (rb_scan_args(argc, argv, "01", &vbits) == 0) {
+ bits = 16;
+ }
else bits = NUM2INT(vbits);
p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
- if (bits > 32) {
+ if (bits > sizeof(long)*CHAR_BIT) {
VALUE res = INT2FIX(0);
VALUE mod;
@@ -2237,36 +2457,39 @@ str_sum(argc, argv, str)
mod = rb_funcall(mod, '-', 1, INT2FIX(1));
while (p < pend) {
- res = rb_funcall(res, '+', 1, INT2FIX((UINT)*p));
- res = rb_funcall(res, '%', 1, mod);
+ res = rb_funcall(res, '+', 1, INT2FIX((unsigned int)*p));
p++;
}
+ res = rb_funcall(res, '&', 1, mod);
return res;
}
else {
- UINT res = 0;
- UINT mod = (1<<bits)-1;
+ unsigned int res = 0;
+ unsigned int mod = (1<<bits)-1;
+ if (mod == 0) {
+ mod = -1;
+ }
while (p < pend) {
- res += (UINT)*p;
- res %= mod;
+ res += (unsigned int)*p;
p++;
}
- return int2inum(res);
+ res &= mod;
+ return rb_int2inum(res);
}
}
static VALUE
-str_ljust(str, w)
+rb_str_ljust(str, w)
VALUE str;
VALUE w;
{
- int width = NUM2INT(w);
+ size_t width = NUM2UINT(w);
VALUE res;
- UCHAR *p, *pend;
+ char *p, *pend;
- if (RSTRING(str)->len >= width) return (VALUE)str;
- res = str_new(0, width);
+ if (width < 0 || RSTRING(str)->len >= width) return str;
+ res = rb_str_new(0, width);
memcpy(RSTRING(res)->ptr, RSTRING(str)->ptr, RSTRING(str)->len);
p = RSTRING(res)->ptr + RSTRING(str)->len; pend = RSTRING(res)->ptr + width;
while (p < pend) {
@@ -2276,16 +2499,16 @@ str_ljust(str, w)
}
static VALUE
-str_rjust(str, w)
+rb_str_rjust(str, w)
VALUE str;
VALUE w;
{
- int width = NUM2INT(w);
+ size_t width = NUM2UINT(w);
VALUE res;
- UCHAR *p, *pend;
+ char *p, *pend;
- if (RSTRING(str)->len >= width) return (VALUE)str;
- res = str_new(0, width);
+ if (width < 0 || RSTRING(str)->len >= width) return str;
+ res = rb_str_new(0, width);
p = RSTRING(res)->ptr; pend = p + width - RSTRING(str)->len;
while (p < pend) {
*p++ = ' ';
@@ -2295,17 +2518,17 @@ str_rjust(str, w)
}
static VALUE
-str_center(str, w)
+rb_str_center(str, w)
VALUE str;
VALUE w;
{
- int width = NUM2INT(w);
+ size_t width = NUM2UINT(w);
VALUE res;
- UCHAR *p, *pend;
- int n;
+ char *p, *pend;
+ size_t n;
- if (RSTRING(str)->len >= width) return (VALUE)str;
- res = str_new(0, width);
+ if (width < 0 || RSTRING(str)->len >= width) return str;
+ res = rb_str_new(0, width);
n = (width - RSTRING(str)->len)/2;
p = RSTRING(res)->ptr; pend = p + n;
while (p < pend) {
@@ -2319,122 +2542,118 @@ str_center(str, w)
return res;
}
-extern VALUE mKernel;
-extern VALUE mComparable;
-extern VALUE mEnumerable;
-extern VALUE eGlobalExit;
-
void
Init_String()
{
- cString = rb_define_class("String", cObject);
- rb_include_module(cString, mComparable);
- rb_include_module(cString, mEnumerable);
- rb_define_singleton_method(cString, "new", str_s_new, 1);
- rb_define_method(cString, "clone", str_clone, 0);
- rb_define_method(cString, "dup", str_dup, 0);
- rb_define_method(cString, "<=>", str_cmp_method, 1);
- rb_define_method(cString, "==", str_equal, 1);
- rb_define_method(cString, "===", str_equal, 1);
- rb_define_method(cString, "eql?", str_equal, 1);
- rb_define_method(cString, "hash", str_hash_method, 0);
- rb_define_method(cString, "+", str_plus, 1);
- rb_define_method(cString, "*", str_times, 1);
- rb_define_method(cString, "%", str_format, 1);
- rb_define_method(cString, "[]", str_aref_method, -1);
- rb_define_method(cString, "[]=", str_aset_method, -1);
- rb_define_method(cString, "length", str_length, 0);
- rb_define_alias(cString, "size", "length");
- rb_define_method(cString, "=~", str_match, 1);
- rb_define_method(cString, "~", str_match2, 0);
- rb_define_method(cString, "succ", str_succ, 0);
- rb_define_method(cString, "upto", str_upto, 1);
- rb_define_method(cString, "index", str_index_method, -1);
- rb_define_method(cString, "rindex", str_rindex, -1);
-
- rb_define_method(cString, "freeze", str_freeze, 0);
- rb_define_method(cString, "frozen?", str_frozen_p, 0);
-
- rb_define_method(cString, "taint", str_taint, 0);
- rb_define_method(cString, "tainted?", str_tainted, 0);
-
- rb_define_method(cString, "to_i", str_to_i, 0);
- rb_define_method(cString, "to_f", str_to_f, 0);
- rb_define_method(cString, "to_s", str_to_s, 0);
- rb_define_method(cString, "inspect", str_inspect, 0);
-
- rb_define_method(cString, "upcase", str_upcase, 0);
- rb_define_method(cString, "downcase", str_downcase, 0);
- rb_define_method(cString, "capitalize", str_capitalize, 0);
- rb_define_method(cString, "swapcase", str_swapcase, 0);
-
- rb_define_method(cString, "upcase!", str_upcase_bang, 0);
- rb_define_method(cString, "downcase!", str_downcase_bang, 0);
- rb_define_method(cString, "capitalize!", str_capitalize_bang, 0);
- rb_define_method(cString, "swapcase!", str_swapcase_bang, 0);
-
- rb_define_method(cString, "hex", str_hex, 0);
- rb_define_method(cString, "oct", str_oct, 0);
- rb_define_method(cString, "split", str_split_method, -1);
- rb_define_method(cString, "reverse", str_reverse, 0);
- rb_define_method(cString, "reverse!", str_reverse_bang, 0);
- rb_define_method(cString, "concat", str_concat, 1);
- rb_define_method(cString, "<<", str_concat, 1);
- rb_define_method(cString, "crypt", str_crypt, 1);
- rb_define_method(cString, "intern", str_intern, 0);
-
- rb_define_method(cString, "include?", str_include, 1);
-
- rb_define_method(cString, "scan", str_scan, 1);
-
- rb_define_method(cString, "ljust", str_ljust, 1);
- rb_define_method(cString, "rjust", str_rjust, 1);
- rb_define_method(cString, "center", str_center, 1);
-
- rb_define_method(cString, "sub", str_sub, -1);
- rb_define_method(cString, "gsub", str_gsub, -1);
- rb_define_method(cString, "chop", str_chop, 0);
- rb_define_method(cString, "chomp", str_chomp, 0);
- rb_define_method(cString, "strip", str_strip, 0);
-
- rb_define_method(cString, "sub!", str_sub_bang, -1);
- rb_define_method(cString, "gsub!", str_gsub_bang, -1);
- rb_define_method(cString, "strip!", str_strip_bang, 0);
- rb_define_method(cString, "chop!", str_chop_bang, 0);
- rb_define_method(cString, "chomp!", str_chomp_bang, 0);
-
- rb_define_method(cString, "tr", str_tr, 2);
- rb_define_method(cString, "tr_s", str_tr_s, 2);
- rb_define_method(cString, "delete", str_delete, 1);
- rb_define_method(cString, "squeeze", str_squeeze, -1);
-
- rb_define_method(cString, "tr!", str_tr_bang, 2);
- rb_define_method(cString, "tr_s!", str_tr_s_bang, 2);
- rb_define_method(cString, "delete!", str_delete_bang, 1);
- rb_define_method(cString, "squeeze!", str_squeeze_bang, -1);
-
- rb_define_method(cString, "each_line", str_each_line, -1);
- rb_define_method(cString, "each", str_each_line, -1);
- rb_define_method(cString, "each_byte", str_each_byte, 0);
-
- rb_define_method(cString, "sum", str_sum, -1);
-
- rb_define_global_function("sub", f_sub, -1);
- rb_define_global_function("gsub", f_gsub, -1);
-
- rb_define_global_function("sub!", f_sub_bang, -1);
- rb_define_global_function("gsub!", f_gsub_bang, -1);
-
- rb_define_global_function("chop", f_chop, 0);
- rb_define_global_function("chop!", f_chop_bang, 0);
-
- rb_define_global_function("chomp", f_chomp, 0);
- rb_define_global_function("chomp!", f_chomp_bang, 0);
-
- rb_define_global_function("split", f_split, -1);
-
- pr_str = rb_intern("to_s");
-
- /* Fix-up initialize ordering */
- RCLASS(eGlobalExit)->super = cString;
+ rb_cString = rb_define_class("String", rb_cObject);
+ rb_include_module(rb_cString, rb_mComparable);
+ rb_include_module(rb_cString, rb_mEnumerable);
+ rb_define_singleton_method(rb_cString, "new", rb_str_s_new, 1);
+ rb_define_method(rb_cString, "clone", rb_str_clone, 0);
+ rb_define_method(rb_cString, "dup", rb_str_dup, 0);
+ rb_define_method(rb_cString, "<=>", rb_str_cmp_method, 1);
+ rb_define_method(rb_cString, "==", rb_str_equal, 1);
+ rb_define_method(rb_cString, "===", rb_str_equal, 1);
+ rb_define_method(rb_cString, "eql?", rb_str_equal, 1);
+ rb_define_method(rb_cString, "hash", rb_str_hash_method, 0);
+ rb_define_method(rb_cString, "+", rb_str_plus, 1);
+ rb_define_method(rb_cString, "*", rb_str_times, 1);
+ rb_define_method(rb_cString, "%", rb_str_format, 1);
+ rb_define_method(rb_cString, "[]", rb_str_aref_method, -1);
+ rb_define_method(rb_cString, "[]=", rb_str_aset_method, -1);
+ rb_define_method(rb_cString, "length", rb_str_length, 0);
+ rb_define_alias(rb_cString, "size", "length");
+ rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
+ rb_define_method(rb_cString, "=~", rb_str_match, 1);
+ rb_define_method(rb_cString, "~", rb_str_match2, 0);
+ rb_define_method(rb_cString, "succ", rb_str_succ, 0);
+ rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
+ rb_define_method(rb_cString, "next", rb_str_succ, 0);
+ rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
+ rb_define_method(rb_cString, "upto", rb_str_upto, 1);
+ rb_define_method(rb_cString, "index", rb_str_index_method, -1);
+ rb_define_method(rb_cString, "rindex", rb_str_rindex, -1);
+ rb_define_method(rb_cString, "replace", rb_str_replace_method, 1);
+
+ rb_define_method(rb_cString, "freeze", rb_str_freeze, 0);
+ rb_define_method(rb_cString, "frozen?", rb_str_frozen_p, 0);
+
+ rb_define_method(rb_cString, "to_i", rb_str_to_i, 0);
+ rb_define_method(rb_cString, "to_f", rb_str_to_f, 0);
+ rb_define_method(rb_cString, "to_s", rb_str_to_s, 0);
+ rb_define_method(rb_cString, "to_str", rb_str_to_s, 0);
+ rb_define_method(rb_cString, "inspect", rb_str_inspect, 0);
+ rb_define_method(rb_cString, "dump", rb_str_dump, 0);
+
+ rb_define_method(rb_cString, "upcase", rb_str_upcase, 0);
+ rb_define_method(rb_cString, "downcase", rb_str_downcase, 0);
+ rb_define_method(rb_cString, "capitalize", rb_str_capitalize, 0);
+ rb_define_method(rb_cString, "swapcase", rb_str_swapcase, 0);
+
+ rb_define_method(rb_cString, "upcase!", rb_str_upcase_bang, 0);
+ rb_define_method(rb_cString, "downcase!", rb_str_downcase_bang, 0);
+ rb_define_method(rb_cString, "capitalize!", rb_str_capitalize_bang, 0);
+ rb_define_method(rb_cString, "swapcase!", rb_str_swapcase_bang, 0);
+
+ rb_define_method(rb_cString, "hex", rb_str_hex, 0);
+ rb_define_method(rb_cString, "oct", rb_str_oct, 0);
+ rb_define_method(rb_cString, "split", rb_str_split_method, -1);
+ rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
+ rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
+ rb_define_method(rb_cString, "concat", rb_str_concat, 1);
+ rb_define_method(rb_cString, "<<", rb_str_concat, 1);
+ rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
+ rb_define_method(rb_cString, "intern", rb_str_intern, 0);
+
+ rb_define_method(rb_cString, "include?", rb_str_include, 1);
+
+ rb_define_method(rb_cString, "scan", rb_str_scan, 1);
+
+ rb_define_method(rb_cString, "ljust", rb_str_ljust, 1);
+ rb_define_method(rb_cString, "rjust", rb_str_rjust, 1);
+ rb_define_method(rb_cString, "center", rb_str_center, 1);
+
+ rb_define_method(rb_cString, "sub", rb_str_sub, -1);
+ rb_define_method(rb_cString, "gsub", rb_str_gsub, -1);
+ rb_define_method(rb_cString, "chop", rb_str_chop, 0);
+ rb_define_method(rb_cString, "chomp", rb_str_chomp, -1);
+ rb_define_method(rb_cString, "strip", rb_str_strip, 0);
+
+ rb_define_method(rb_cString, "sub!", rb_str_sub_bang, -1);
+ rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1);
+ rb_define_method(rb_cString, "strip!", rb_str_strip_bang, 0);
+ rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0);
+ rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1);
+
+ rb_define_method(rb_cString, "tr", rb_str_tr, 2);
+ rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2);
+ rb_define_method(rb_cString, "delete", rb_str_delete, 1);
+ rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1);
+
+ rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2);
+ rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2);
+ rb_define_method(rb_cString, "delete!", rb_str_delete_bang, 1);
+ rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1);
+
+ rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
+ rb_define_method(rb_cString, "each", rb_str_each_line, -1);
+ rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
+
+ rb_define_method(rb_cString, "sum", rb_str_sum, -1);
+
+ rb_define_global_function("sub", rb_f_sub, -1);
+ rb_define_global_function("gsub", rb_f_gsub, -1);
+
+ rb_define_global_function("sub!", rb_f_sub_bang, -1);
+ rb_define_global_function("gsub!", rb_f_gsub_bang, -1);
+
+ rb_define_global_function("chop", rb_f_chop, 0);
+ rb_define_global_function("chop!", rb_f_chop_bang, 0);
+
+ rb_define_global_function("chomp", rb_f_chomp, -1);
+ rb_define_global_function("chomp!", rb_f_chomp_bang, -1);
+
+ rb_define_global_function("split", rb_f_split, -1);
+
+ to_str = rb_intern("to_s");
}
diff --git a/struct.c b/struct.c
index 7234d1e5d2..7aaf4e8d25 100644
--- a/struct.c
+++ b/struct.c
@@ -10,25 +10,37 @@
#include "ruby.h"
-ID rb_frame_last_func();
-VALUE cStruct;
-extern VALUE mEnumerable;
+#ifdef USE_CWGUSI
+#include <stdio.h>
+#endif
+
+VALUE rb_cStruct;
static VALUE
-struct_s_members(obj)
+class_of(obj)
VALUE obj;
{
- struct RArray *member;
- VALUE ary, *p, *pend;
+ obj = CLASS_OF(obj);
+ if (FL_TEST(obj, FL_SINGLETON))
+ return RCLASS(obj)->super;
+ return obj;
+}
- member = RARRAY(rb_iv_get(obj, "__member__"));
+static VALUE
+rb_struct_s_members(obj)
+ VALUE obj;
+{
+ VALUE member, ary;
+ VALUE *p, *pend;
+
+ member = rb_iv_get(obj, "__member__");
if (NIL_P(member)) {
- Fatal("non-initialized struct");
+ rb_bug("non-initialized struct");
}
- ary = ary_new2(member->len);
- p = member->ptr; pend = p + member->len;
+ ary = rb_ary_new2(RARRAY(member)->len);
+ p = RARRAY(member)->ptr; pend = p + RARRAY(member)->len;
while (p < pend) {
- ary_push(ary, str_new2(rb_id2name(FIX2INT(*p))));
+ rb_ary_push(ary, rb_str_new2(rb_id2name(FIX2INT(*p))));
p++;
}
@@ -36,24 +48,23 @@ struct_s_members(obj)
}
static VALUE
-struct_members(obj)
+rb_struct_members(obj)
VALUE obj;
{
- return struct_s_members(CLASS_OF(obj));
+ return rb_struct_s_members(class_of(obj));
}
VALUE
-struct_getmember(obj, id)
+rb_struct_getmember(obj, id)
VALUE obj;
ID id;
{
- VALUE nstr, member, slot;
+ VALUE member, slot;
int i;
- nstr = CLASS_OF(obj);
- member = rb_iv_get(nstr, "__member__");
+ member = rb_iv_get(class_of(obj), "__member__");
if (NIL_P(member)) {
- Bug("non-initialized struct");
+ rb_bug("non-initialized struct");
}
slot = INT2FIX(id);
for (i=0; i<RARRAY(member)->len; i++) {
@@ -61,190 +72,209 @@ struct_getmember(obj, id)
return RSTRUCT(obj)->ptr[i];
}
}
- NameError("%s is not struct member", rb_id2name(id));
- /* not reached */
+ rb_raise(rb_eNameError, "%s is not struct member", rb_id2name(id));
+ return Qnil; /* not reached */
}
static VALUE
-struct_ref(obj)
+rb_struct_ref(obj)
VALUE obj;
{
- return struct_getmember(obj, rb_frame_last_func());
+ return rb_struct_getmember(obj, rb_frame_last_func());
}
-static VALUE struct_ref0(obj) VALUE obj; {return RSTRUCT(obj)->ptr[0];}
-static VALUE struct_ref1(obj) VALUE obj; {return RSTRUCT(obj)->ptr[1];}
-static VALUE struct_ref2(obj) VALUE obj; {return RSTRUCT(obj)->ptr[2];}
-static VALUE struct_ref3(obj) VALUE obj; {return RSTRUCT(obj)->ptr[3];}
-static VALUE struct_ref4(obj) VALUE obj; {return RSTRUCT(obj)->ptr[4];}
-static VALUE struct_ref5(obj) VALUE obj; {return RSTRUCT(obj)->ptr[5];}
-static VALUE struct_ref6(obj) VALUE obj; {return RSTRUCT(obj)->ptr[6];}
-static VALUE struct_ref7(obj) VALUE obj; {return RSTRUCT(obj)->ptr[7];}
-static VALUE struct_ref8(obj) VALUE obj; {return RSTRUCT(obj)->ptr[8];}
-static VALUE struct_ref9(obj) VALUE obj; {return RSTRUCT(obj)->ptr[9];}
+static VALUE rb_struct_ref0(obj) VALUE obj; {return RSTRUCT(obj)->ptr[0];}
+static VALUE rb_struct_ref1(obj) VALUE obj; {return RSTRUCT(obj)->ptr[1];}
+static VALUE rb_struct_ref2(obj) VALUE obj; {return RSTRUCT(obj)->ptr[2];}
+static VALUE rb_struct_ref3(obj) VALUE obj; {return RSTRUCT(obj)->ptr[3];}
+static VALUE rb_struct_ref4(obj) VALUE obj; {return RSTRUCT(obj)->ptr[4];}
+static VALUE rb_struct_ref5(obj) VALUE obj; {return RSTRUCT(obj)->ptr[5];}
+static VALUE rb_struct_ref6(obj) VALUE obj; {return RSTRUCT(obj)->ptr[6];}
+static VALUE rb_struct_ref7(obj) VALUE obj; {return RSTRUCT(obj)->ptr[7];}
+static VALUE rb_struct_ref8(obj) VALUE obj; {return RSTRUCT(obj)->ptr[8];}
+static VALUE rb_struct_ref9(obj) VALUE obj; {return RSTRUCT(obj)->ptr[9];}
VALUE (*ref_func[10])() = {
- struct_ref0,
- struct_ref1,
- struct_ref2,
- struct_ref3,
- struct_ref4,
- struct_ref5,
- struct_ref6,
- struct_ref7,
- struct_ref8,
- struct_ref9,
+ 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 VALUE
-struct_set(obj, val)
+rb_struct_set(obj, val)
VALUE obj, val;
{
- VALUE nstr, member, slot;
+ VALUE member, slot;
int i;
- nstr = CLASS_OF(obj);
- member = rb_iv_get(nstr, "__member__");
+ member = rb_iv_get(class_of(obj), "__member__");
if (NIL_P(member)) {
- Fatal("non-initialized struct");
+ rb_bug("non-initialized struct");
}
for (i=0; i<RARRAY(member)->len; i++) {
slot = RARRAY(member)->ptr[i];
- if (id_attrset(FIX2INT(slot)) == rb_frame_last_func()) {
+ if (rb_id_attrset(FIX2INT(slot)) == rb_frame_last_func()) {
return RSTRUCT(obj)->ptr[i] = val;
}
}
- NameError("not struct member");
- /* not reached */
+ rb_raise(rb_eNameError, "not struct member");
+ return Qnil; /* not reached */
}
-VALUE struct_alloc();
-
static VALUE
-make_struct(name, member)
- VALUE name, member;
+make_struct(name, member, klass)
+ VALUE name, member, klass;
{
VALUE nstr;
ID id;
int i;
- id = rb_intern(RSTRING(name)->ptr);
- if (!rb_is_const_id(id)) {
- NameError("identifier %s needs to be constant", RSTRING(name)->ptr);
+ if (NIL_P(name)) {
+ nstr = rb_class_new(klass);
+ }
+ else {
+ char *cname = STR2CSTR(name);
+ id = rb_intern(cname);
+ if (!rb_is_const_id(id)) {
+ rb_raise(rb_eNameError, "identifier %s needs to be constant", cname);
+ }
+ nstr = rb_define_class_under(klass, cname, klass);
}
- nstr = rb_define_class_under(cStruct, RSTRING(name)->ptr, cStruct);
rb_iv_set(nstr, "__size__", INT2FIX(RARRAY(member)->len));
rb_iv_set(nstr, "__member__", member);
- rb_define_singleton_method(nstr, "new", struct_alloc, -2);
- rb_define_singleton_method(nstr, "[]", struct_alloc, -2);
- rb_define_singleton_method(nstr, "members", struct_s_members, 0);
+ rb_define_singleton_method(nstr, "new", rb_struct_alloc, -2);
+ rb_define_singleton_method(nstr, "[]", rb_struct_alloc, -2);
+ rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0);
for (i=0; i< RARRAY(member)->len; i++) {
ID id = FIX2INT(RARRAY(member)->ptr[i]);
if (i<10) {
rb_define_method_id(nstr, id, ref_func[i], 0);
}
else {
- rb_define_method_id(nstr, id, struct_ref, 0);
+ rb_define_method_id(nstr, id, rb_struct_ref, 0);
}
- rb_define_method_id(nstr, id_attrset(id), struct_set, 1);
+ rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1);
}
return nstr;
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
VALUE
-struct_define(name, va_alist)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_struct_define(char *name, ...)
+#else
+rb_struct_define(name, va_alist)
char *name;
va_dcl
+#endif
{
va_list ar;
VALUE nm, ary;
char *mem;
- nm = str_new2(name);
- ary = ary_new();
+ nm = rb_str_new2(name);
+ ary = rb_ary_new();
- va_start(ar);
+ va_init_list(ar, name);
while (mem = va_arg(ar, char*)) {
ID slot = rb_intern(mem);
- ary_push(ary, INT2FIX(slot));
+ rb_ary_push(ary, INT2FIX(slot));
}
va_end(ar);
- return make_struct(nm, ary);
+ return make_struct(nm, ary, rb_cStruct);
}
static VALUE
-struct_s_def(argc, argv)
+rb_struct_s_def(argc, argv, klass)
int argc;
VALUE *argv;
{
- struct RString *name;
- struct RArray *rest;
+ VALUE name, rest;
int i;
+ VALUE st;
rb_scan_args(argc, argv, "1*", &name, &rest);
- Check_Type(name, T_STRING);
- for (i=0; i<rest->len; i++) {
- ID id = rb_to_id(rest->ptr[i]);
- rest->ptr[i] = INT2FIX(id);
+ for (i=0; i<RARRAY(rest)->len; i++) {
+ ID id = rb_to_id(RARRAY(rest)->ptr[i]);
+ RARRAY(rest)->ptr[i] = INT2FIX(id);
}
- return make_struct(name, rest);
+ st = make_struct(name, rest, klass);
+ rb_obj_call_init(st);
+
+ return st;
}
VALUE
-struct_alloc(class, values)
- VALUE class, values;
+rb_struct_alloc(klass, values)
+ VALUE klass, values;
{
VALUE size;
int n;
- size = rb_iv_get(class, "__size__");
+ size = rb_iv_get(klass, "__size__");
n = FIX2INT(size);
- if (n < RARRAY(values)->len) {
- ArgError("struct size differs");
+ if (n != RARRAY(values)->len) {
+ rb_raise(rb_eArgError, "struct size differs");
}
else {
NEWOBJ(st, struct RStruct);
- OBJSETUP(st, class, T_STRUCT);
- st->len = n;
- st->ptr = 0; /* avoid GC crashing */
+ OBJSETUP(st, klass, T_STRUCT);
+ st->len = 0; /* avoid GC crashing */
st->ptr = ALLOC_N(VALUE, n);
+ st->len = n;
MEMCPY(st->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
- memclear(st->ptr+RARRAY(values)->len, n - RARRAY(values)->len);
+ rb_obj_call_init((VALUE)st);
return (VALUE)st;
}
- /* not reached */
+ return Qnil; /* not reached */
}
VALUE
-struct_new(class, va_alist)
- VALUE class;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_struct_new(VALUE klass, ...)
+#else
+rb_struct_new(klass, va_alist)
+ VALUE klass;
va_dcl
+#endif
{
VALUE val, mem;
- int size;
+ int size, i;
va_list args;
- val = rb_iv_get(class, "__size__");
+ val = rb_iv_get(klass, "__size__");
size = FIX2INT(val);
- mem = ary_new();
- va_start(args);
- while (size--) {
+ mem = rb_ary_new2(size);
+ va_init_list(args, klass);
+ for (i=0; i<size; i++) {
val = va_arg(args, VALUE);
- ary_push(mem, val);
+ rb_ary_store(mem, i, val);
}
va_end(args);
- return struct_alloc(class, mem);
+ return rb_struct_alloc(klass, mem);
}
static VALUE
-struct_each(s)
+rb_struct_each(s)
VALUE s;
{
int i;
@@ -255,145 +285,213 @@ struct_each(s)
return Qnil;
}
-char *rb_class2name();
-
static VALUE
-struct_to_s(s)
+rb_struct_to_s(s)
VALUE s;
{
- char *name, *buf;
+ char *cname = rb_class2name(CLASS_OF(s));
+ char *buf = ALLOCA_N(char, strlen(cname) + 4);
- name = rb_class2name(CLASS_OF(s));
- buf = ALLOCA_N(char, strlen(name)+1);
- sprintf(buf, "%s", name);
- return str_new2(buf);
+ sprintf(buf, "#<%s>", cname);
+ return rb_str_new2(buf);
}
static VALUE
-struct_inspect(s)
+inspect_struct(s)
VALUE s;
{
- char *name = rb_class2name(CLASS_OF(s));
+ char *cname = rb_class2name(CLASS_OF(s));
VALUE str, member;
- char buf[256];
int i;
member = rb_iv_get(CLASS_OF(s), "__member__");
if (NIL_P(member)) {
- Fatal("non-initialized struct");
+ rb_bug("non-initialized struct");
}
- sprintf(buf, "#<%s ", name);
- str = str_new2(buf);
+ str = rb_str_new2("#<");
+ rb_str_cat(str, cname, strlen(cname));
+ rb_str_cat(str, " ", 1);
for (i=0; i<RSTRUCT(s)->len; i++) {
VALUE str2, slot;
char *p;
if (i > 0) {
- str_cat(str, ", ", 2);
+ rb_str_cat(str, ", ", 2);
}
slot = RARRAY(member)->ptr[i];
p = rb_id2name(FIX2INT(slot));
- str_cat(str, p, strlen(p));
- str_cat(str, "=", 1);
+ rb_str_cat(str, p, strlen(p));
+ rb_str_cat(str, "=", 1);
str2 = rb_inspect(RSTRUCT(s)->ptr[i]);
- str2 = obj_as_string(str2);
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
- str_cat(str, ">", 1);
+ rb_str_cat(str, ">", 1);
return str;
}
static VALUE
-struct_to_a(s)
+rb_struct_inspect(s)
VALUE s;
{
- return ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr);
+ if (rb_inspecting_p(s)) {
+ char *cname = rb_class2name(CLASS_OF(s));
+ char *buf = ALLOCA_N(char, strlen(cname) + 8);
+
+ sprintf(buf, "#<%s:...>", cname);
+ return rb_str_new2(buf);
+ }
+ return rb_protect_inspect(inspect_struct, s, 0);
}
static VALUE
-struct_clone(s)
+rb_struct_to_a(s)
+ VALUE s;
+{
+ return rb_ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr);
+}
+
+static VALUE
+rb_struct_clone(s)
VALUE s;
{
NEWOBJ(st, struct RStruct);
CLONESETUP(st, s);
- st->len = RSTRUCT(s)->len;
- st->ptr = 0; /* avoid GC crashing */
+ st->len = 0; /* avoid GC crashing */
st->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len);
+ st->len = RSTRUCT(s)->len;
MEMCPY(st->ptr, RSTRUCT(s)->ptr, VALUE, st->len);
return (VALUE)st;
}
+static VALUE
+rb_struct_aref_id(s, id)
+ VALUE s;
+ ID id;
+{
+ VALUE member;
+ int i, len;
+
+ member = rb_iv_get(CLASS_OF(s), "__member__");
+ if (NIL_P(member)) {
+ rb_bug("non-initialized struct");
+ }
+
+ len = RARRAY(member)->len;
+ for (i=0; i<len; i++) {
+ if (FIX2UINT(RARRAY(member)->ptr[i]) == id) {
+ return RSTRUCT(s)->ptr[i];
+ }
+ }
+ rb_raise(rb_eNameError, "no member '%s' in struct", rb_id2name(id));
+ return Qnil; /* not reached */
+}
+
VALUE
-struct_aref(s, idx)
+rb_struct_aref(s, idx)
VALUE s, idx;
{
int i;
+ if (TYPE(idx) == T_STRING) {
+ return rb_struct_aref_id(s, rb_to_id(idx));
+ }
+
i = NUM2INT(idx);
- if (i < 0) i = RSTRUCT(s)->len - i;
+ if (i < 0) i = RSTRUCT(s)->len + i;
if (i < 0)
- IndexError("offset %d too small for struct(size:%d)", i, RSTRUCT(s)->len);
+ rb_raise(rb_eIndexError, "offset %d too small for struct(size:%d)",
+ i, RSTRUCT(s)->len);
if (RSTRUCT(s)->len <= i)
- IndexError("offset %d too large for struct(size:%d)", i, RSTRUCT(s)->len);
+ rb_raise(rb_eIndexError, "offset %d too large for struct(size:%d)",
+ i, RSTRUCT(s)->len);
return RSTRUCT(s)->ptr[i];
}
+static VALUE
+rb_struct_aset_id(s, id, val)
+ VALUE s, val;
+ ID id;
+{
+ VALUE member;
+ int i, len;
+
+ member = rb_iv_get(CLASS_OF(s), "__member__");
+ if (NIL_P(member)) {
+ rb_bug("non-initialized struct");
+ }
+
+ len = RARRAY(member)->len;
+ for (i=0; i<len; i++) {
+ if (FIX2UINT(RARRAY(member)->ptr[i]) == id) {
+ RSTRUCT(s)->ptr[i] = val;
+ return val;
+ }
+ }
+ rb_raise(rb_eNameError, "no member '%s' in struct", rb_id2name(id));
+}
+
VALUE
-struct_aset(s, idx, val)
+rb_struct_aset(s, idx, val)
VALUE s, idx, val;
{
int i;
+ if (TYPE(idx) == T_STRING) {
+ return rb_struct_aset_id(s, rb_to_id(idx), val);
+ }
+
i = NUM2INT(idx);
- if (i < 0) i = RSTRUCT(s)->len - i;
+ if (i < 0) i = RSTRUCT(s)->len + i;
if (i < 0)
- IndexError("offset %d too small for struct(size:%d)", i, RSTRUCT(s)->len);
+ rb_raise(rb_eIndexError, "offset %d too small for struct(size:%d)",
+ i, RSTRUCT(s)->len);
if (RSTRUCT(s)->len <= i)
- IndexError("offset %d too large for struct(size:%d)", i, RSTRUCT(s)->len);
+ rb_raise(rb_eIndexError, "offset %d too large for struct(size:%d)",
+ i, RSTRUCT(s)->len);
return RSTRUCT(s)->ptr[i] = val;
}
static VALUE
-struct_equal(s, s2)
+rb_struct_equal(s, s2)
VALUE s, s2;
{
int i;
- if (TYPE(s2) != T_STRUCT) return FALSE;
- if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE;
+ if (TYPE(s2) != T_STRUCT) return Qfalse;
+ if (CLASS_OF(s) != CLASS_OF(s2)) return Qfalse;
if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
- Bug("inconsistent struct"); /* should never happen */
+ rb_bug("inconsistent struct"); /* should never happen */
}
for (i=0; i<RSTRUCT(s)->len; i++) {
- if (!rb_equal(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return FALSE;
+ if (!rb_equal(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-struct_eql(s, s2)
+rb_struct_eql(s, s2)
VALUE s, s2;
{
int i;
- if (TYPE(s2) != T_STRUCT) return FALSE;
- if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE;
+ if (TYPE(s2) != T_STRUCT) return Qfalse;
+ if (CLASS_OF(s) != CLASS_OF(s2)) return Qfalse;
if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
- Bug("inconsistent struct"); /* should never happen */
+ rb_bug("inconsistent struct"); /* should never happen */
}
for (i=0; i<RSTRUCT(s)->len; i++) {
- if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return FALSE;
+ if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-struct_hash(s)
+rb_struct_hash(s)
VALUE s;
{
int i, h;
@@ -408,25 +506,25 @@ struct_hash(s)
void
Init_Struct()
{
- cStruct = rb_define_class("Struct", cObject);
- rb_include_module(cStruct, mEnumerable);
+ rb_cStruct = rb_define_class("Struct", rb_cObject);
+ rb_include_module(rb_cStruct, rb_mEnumerable);
- rb_define_singleton_method(cStruct, "new", struct_s_def, -1);
+ rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
- rb_define_method(cStruct, "clone", struct_clone, 0);
+ rb_define_method(rb_cStruct, "clone", rb_struct_clone, 0);
- rb_define_method(cStruct, "==", struct_equal, 1);
- rb_define_method(cStruct, "eql?", struct_eql, 1);
- rb_define_method(cStruct, "hash", struct_hash, 0);
+ rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
+ rb_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
+ rb_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
- rb_define_method(cStruct, "to_s", struct_to_s, 0);
- rb_define_method(cStruct, "inspect", struct_inspect, 0);
- rb_define_method(cStruct, "to_a", struct_to_a, 0);
- rb_define_method(cStruct, "values", struct_to_a, 0);
+ rb_define_method(rb_cStruct, "to_s", rb_struct_to_s, 0);
+ rb_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
+ rb_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
+ rb_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
- rb_define_method(cStruct, "each", struct_each, 0);
- rb_define_method(cStruct, "[]", struct_aref, 1);
- rb_define_method(cStruct, "[]=", struct_aset, 2);
+ rb_define_method(rb_cStruct, "each", rb_struct_each, 0);
+ rb_define_method(rb_cStruct, "[]", rb_struct_aref, 1);
+ rb_define_method(rb_cStruct, "[]=", rb_struct_aset, 2);
- rb_define_method(cStruct, "members", struct_members, 0);
+ rb_define_method(rb_cStruct, "members", rb_struct_members, 0);
}
diff --git a/time.c b/time.c
index 1749c32319..fc14d8e5b6 100644
--- a/time.c
+++ b/time.c
@@ -6,13 +6,18 @@
$Date$
created at: Tue Dec 28 14:31:59 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <sys/types.h>
+#ifdef USE_CWGUSI
+int gettimeofday(struct timeval*, struct timezone*);
+int strcasecmp(char*, char*);
+#endif
+
#include <time.h>
#ifndef NT
#ifdef HAVE_SYS_TIME_H
@@ -30,11 +35,10 @@ struct timeval {
#endif
#include <math.h>
-static VALUE cTime;
+VALUE rb_cTime;
#if defined(HAVE_TIMES) || defined(NT)
static VALUE S_Tms;
#endif
-extern VALUE mComparable;
struct time_object {
struct timeval tv;
@@ -50,31 +54,34 @@ struct time_object {
}
static VALUE
-time_s_now(class)
- VALUE class;
+time_s_now(klass)
+ VALUE klass;
{
VALUE obj;
struct time_object *tobj;
- obj = Data_Make_Struct(class, struct time_object, 0, 0, tobj);
+ obj = Data_Make_Struct(klass, struct time_object, 0, free, tobj);
tobj->tm_got=0;
if (gettimeofday(&(tobj->tv), 0) == -1) {
rb_sys_fail("gettimeofday");
}
+ rb_obj_call_init(obj);
return obj;
}
static VALUE
-time_new_internal(class, sec, usec)
- VALUE class;
+time_new_internal(klass, sec, usec)
+ VALUE klass;
int sec, usec;
{
VALUE obj;
struct time_object *tobj;
- obj = Data_Make_Struct(class, struct time_object, 0, 0, tobj);
+ if (sec < 0 || (sec == 0 && usec < 0))
+ rb_raise(rb_eArgError, "time must be positive");
+ obj = Data_Make_Struct(klass, struct time_object, 0, free, tobj);
tobj->tm_got = 0;
tobj->tv.tv_sec = sec;
tobj->tv.tv_usec = usec;
@@ -83,14 +90,14 @@ time_new_internal(class, sec, usec)
}
VALUE
-time_new(sec, usec)
+rb_time_new(sec, usec)
int sec, usec;
{
- return time_new_internal(cTime, sec, usec);
+ return time_new_internal(rb_cTime, sec, usec);
}
struct timeval
-time_timeval(time)
+rb_time_timeval(time)
VALUE time;
{
struct time_object *tobj;
@@ -98,34 +105,30 @@ time_timeval(time)
switch (TYPE(time)) {
case T_FIXNUM:
- t.tv_sec = FIX2UINT(time);
+ t.tv_sec = FIX2INT(time);
if (t.tv_sec < 0)
- ArgError("time must be positive");
+ rb_raise(rb_eArgError, "time must be positive");
t.tv_usec = 0;
break;
case T_FLOAT:
- {
- double seconds, microseconds;
-
- if (RFLOAT(time)->value < 0.0)
- ArgError("time must be positive");
- seconds = floor(RFLOAT(time)->value);
- microseconds = (RFLOAT(time)->value - seconds) * 1000000.0;
- t.tv_sec = seconds;
- t.tv_usec = microseconds;
- }
+ if (RFLOAT(time)->value < 0.0)
+ rb_raise(rb_eArgError, "time must be positive");
+ t.tv_sec = (long)floor(RFLOAT(time)->value);
+ t.tv_usec = (long)((RFLOAT(time)->value - t.tv_sec) * 1000000.0);
break;
case T_BIGNUM:
t.tv_sec = NUM2INT(time);
+ if (t.tv_sec < 0)
+ rb_raise(rb_eArgError, "time must be positive");
t.tv_usec = 0;
break;
default:
- if (!obj_is_kind_of(time, cTime)) {
- TypeError("Can't convert %s into Time",
- rb_class2name(CLASS_OF(time)));
+ if (!rb_obj_is_kind_of(time, rb_cTime)) {
+ rb_raise(rb_eTypeError, "Can't convert %s into Time",
+ rb_class2name(CLASS_OF(time)));
}
GetTimeval(time, tobj);
t = tobj->tv;
@@ -135,13 +138,13 @@ time_timeval(time)
}
static VALUE
-time_s_at(class, time)
- VALUE class, time;
+time_s_at(klass, time)
+ VALUE klass, time;
{
struct timeval tv;
- tv = time_timeval(time);
- return time_new_internal(class, tv.tv_sec, tv.tv_usec);
+ tv = rb_time_timeval(time);
+ return time_new_internal(klass, tv.tv_sec, tv.tv_usec);
}
static char *months [12] = {
@@ -149,6 +152,17 @@ static char *months [12] = {
"jul", "aug", "sep", "oct", "nov", "dec",
};
+static int
+obj2int(obj)
+ VALUE obj;
+{
+ if (TYPE(obj) == T_STRING) {
+ obj = rb_str2inum(RSTRING(obj)->ptr, 10);
+ }
+
+ return NUM2INT(obj);
+}
+
static void
time_arg(argc, argv, args)
int argc;
@@ -158,12 +172,22 @@ time_arg(argc, argv, args)
VALUE v[6];
int i;
- rb_scan_args(argc, argv, "15", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
+ 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];
+ }
+ else {
+ rb_scan_args(argc, argv, "15", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5]);
+ }
- args[0] = NUM2INT(v[0]);
+ args[0] = obj2int(v[0]);
if (args[0] < 70) args[0] += 100;
if (args[0] > 1900) args[0] -= 1900;
- if (v[1] == Qnil) {
+ if (NIL_P(v[1])) {
args[1] = 0;
}
else if (TYPE(v[1]) == T_STRING) {
@@ -178,44 +202,46 @@ time_arg(argc, argv, args)
char c = RSTRING(v[1])->ptr[0];
if ('0' <= c && c <= '9') {
- args[1] = NUM2INT(v[1])-1;
+ args[1] = obj2int(v[1])-1;
}
}
}
else {
- args[1] = NUM2INT(v[1]);
+ args[1] = obj2int(v[1]) - 1;
}
- if (v[2] == Qnil) {
+ if (NIL_P(v[2])) {
args[2] = 1;
}
else {
- args[2] = NUM2INT(v[2]);
+ args[2] = obj2int(v[2]);
}
for (i=3;i<6;i++) {
- if (v[i] == Qnil) {
+ if (NIL_P(v[i])) {
args[i] = 0;
}
else {
- args[i] = NUM2INT(v[i]);
+ args[i] = obj2int(v[i]);
}
}
/* value validation */
- if ( args[0] < 70|| args[1] > 137
+ if ( args[0] < 70|| args[0] > 137
|| args[1] < 0 || args[1] > 11
|| args[2] < 1 || args[2] > 31
|| args[3] < 0 || args[3] > 23
- || args[4] < 0 || args[4] > 60
- || args[5] < 0 || args[5] > 61)
- ArgError("argument out of range");
+ || args[4] < 0 || args[4] > 59
+ || args[5] < 0 || args[5] > 60)
+ rb_raise(rb_eArgError, "argument out of range");
}
+static VALUE time_gmtime _((VALUE));
+static VALUE time_localtime _((VALUE));
static VALUE
-time_gm_or_local(argc, argv, gm_or_local, class)
+time_gm_or_local(argc, argv, gm_or_local, klass)
int argc;
VALUE *argv;
int gm_or_local;
- VALUE class;
+ VALUE klass;
{
int args[6];
struct timeval tv;
@@ -223,6 +249,7 @@ time_gm_or_local(argc, argv, gm_or_local, class)
time_t guess, t;
int diff;
struct tm *(*fn)();
+ VALUE time;
fn = (gm_or_local) ? gmtime : localtime;
time_arg(argc, argv, args);
@@ -233,9 +260,9 @@ time_gm_or_local(argc, argv, gm_or_local, class)
tm = (*fn)(&guess);
if (!tm) goto error;
t = args[0];
- while (diff = t - tm->tm_year) {
+ while (diff = t - (tm->tm_year)) {
guess += diff * 364 * 24 * 3600;
- if (guess < 0) ArgError("too far future");
+ if (guess < 0) rb_raise(rb_eArgError, "too far future");
tm = (*fn)(&guess);
if (!tm) goto error;
}
@@ -250,28 +277,31 @@ time_gm_or_local(argc, argv, gm_or_local, class)
guess += (args[4] - tm->tm_min) * 60;
guess += args[5] - tm->tm_sec;
- return time_new_internal(class, guess, 0);
+ time = time_new_internal(klass, guess, 0);
+ if (gm_or_local) return time_gmtime(time);
+ return time_localtime(time);
error:
- ArgError("gmtime error");
+ rb_raise(rb_eArgError, "gmtime/localtime error");
+ return Qnil; /* not reached */
}
static VALUE
-time_s_timegm(argc, argv, class)
+time_s_timegm(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
- return time_gm_or_local(argc, argv, 1, class);
+ return time_gm_or_local(argc, argv, 1, klass);
}
static VALUE
-time_s_timelocal(argc, argv, class)
+time_s_timelocal(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
- return time_gm_or_local(argc, argv, 0, class);
+ return time_gm_or_local(argc, argv, 0, klass);
}
static VALUE
@@ -281,7 +311,7 @@ time_to_i(time)
struct time_object *tobj;
GetTimeval(time, tobj);
- return int2inum(tobj->tv.tv_sec);
+ return rb_int2inum(tobj->tv.tv_sec);
}
static VALUE
@@ -291,7 +321,7 @@ time_to_f(time)
struct time_object *tobj;
GetTimeval(time, tobj);
- return float_new((double)tobj->tv.tv_sec+(double)tobj->tv.tv_usec/1000000);
+ return rb_float_new((double)tobj->tv.tv_sec+(double)tobj->tv.tv_usec/1000000);
}
static VALUE
@@ -331,7 +361,7 @@ time_cmp(time1, time2)
}
}
- if (obj_is_instance_of(time2, cTime)) {
+ if (rb_obj_is_instance_of(time2, rb_cTime)) {
GetTimeval(time2, tobj2);
if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0);
@@ -354,13 +384,13 @@ time_eql(time1, time2)
struct time_object *tobj1, *tobj2;
GetTimeval(time1, tobj1);
- if (obj_is_instance_of(time2, cTime)) {
+ if (rb_obj_is_instance_of(time2, rb_cTime)) {
GetTimeval(time2, tobj2);
if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
- if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return TRUE;
+ if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return Qtrue;
}
}
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -414,6 +444,23 @@ time_asctime(time)
VALUE time;
{
struct time_object *tobj;
+ char *s;
+
+ GetTimeval(time, tobj);
+ if (tobj->tm_got == 0) {
+ time_localtime(time);
+ }
+ s = asctime(&(tobj->tm));
+ if (s[24] == '\n') s[24] = '\0';
+
+ return rb_str_new2(s);
+}
+
+static VALUE
+time_to_s(time)
+ VALUE time;
+{
+ struct time_object *tobj;
char buf[64];
int len;
@@ -430,7 +477,7 @@ time_asctime(time)
{
len = strftime(buf, 64, "%a %b %d %H:%M:%S %Z %Y", &(tobj->tm));
}
- return str_new(buf, len);
+ return rb_str_new(buf, len);
}
static VALUE
@@ -438,15 +485,15 @@ time_plus(time1, time2)
VALUE time1, time2;
{
struct time_object *tobj1, *tobj2;
- int sec, usec;
+ long sec, usec;
GetTimeval(time1, tobj1);
if (TYPE(time2) == T_FLOAT) {
unsigned int nsec = (unsigned int)RFLOAT(time2)->value;
sec = tobj1->tv.tv_sec + nsec;
- usec = tobj1->tv.tv_usec + (RFLOAT(time2)->value - (double)nsec)*1e6;
+ usec = tobj1->tv.tv_usec + (long)(RFLOAT(time2)->value-(double)nsec)*1e6;
}
- else if (obj_is_instance_of(time2, cTime)) {
+ else if (rb_obj_is_instance_of(time2, rb_cTime)) {
GetTimeval(time2, tobj2);
sec = tobj1->tv.tv_sec + tobj2->tv.tv_sec;
usec = tobj1->tv.tv_usec + tobj2->tv.tv_usec;
@@ -460,7 +507,7 @@ time_plus(time1, time2)
sec++;
usec -= 1000000;
}
- return time_new(sec, usec);
+ return rb_time_new(sec, usec);
}
static VALUE
@@ -471,7 +518,7 @@ time_minus(time1, time2)
int sec, usec;
GetTimeval(time1, tobj1);
- if (obj_is_instance_of(time2, cTime)) {
+ if (rb_obj_is_instance_of(time2, rb_cTime)) {
double f;
GetTimeval(time2, tobj2);
@@ -479,7 +526,7 @@ time_minus(time1, time2)
f += (tobj1->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
- return float_new(f);
+ return rb_float_new(f);
}
else if (TYPE(time2) == T_FLOAT) {
sec = tobj1->tv.tv_sec - (int)RFLOAT(time2)->value;
@@ -494,7 +541,7 @@ time_minus(time1, time2)
sec--;
usec += 1000000;
}
- return time_new(sec, usec);
+ return rb_time_new(sec, usec);
}
static VALUE
@@ -559,7 +606,7 @@ time_mon(time)
if (tobj->tm_got == 0) {
time_localtime(time);
}
- return INT2FIX(tobj->tm.tm_mon);
+ return INT2FIX(tobj->tm.tm_mon+1);
}
static VALUE
@@ -572,7 +619,7 @@ time_year(time)
if (tobj->tm_got == 0) {
time_localtime(time);
}
- return INT2FIX(tobj->tm.tm_year);
+ return INT2FIX(tobj->tm.tm_year+1900);
}
static VALUE
@@ -611,7 +658,7 @@ time_isdst(time)
if (tobj->tm_got == 0) {
time_localtime(time);
}
- return INT2FIX(tobj->tm.tm_isdst);
+ return tobj->tm.tm_isdst?Qtrue:Qfalse;
}
static VALUE
@@ -628,7 +675,7 @@ time_zone(time)
}
len = strftime(buf, 10, "%Z", &(tobj->tm));
- return str_new(buf, len);
+ return rb_str_new(buf, len);
}
static VALUE
@@ -636,23 +683,22 @@ time_to_a(time)
VALUE time;
{
struct time_object *tobj;
- VALUE ary;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
time_localtime(time);
}
- ary = ary_new3(9,
- 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),
- INT2FIX(tobj->tm.tm_year),
- INT2FIX(tobj->tm.tm_wday),
- INT2FIX(tobj->tm.tm_yday),
- INT2FIX(tobj->tm.tm_isdst));
- return ary;
+ 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),
+ INT2FIX(tobj->tm.tm_year+1900),
+ INT2FIX(tobj->tm.tm_wday),
+ INT2FIX(tobj->tm.tm_yday),
+ tobj->tm.tm_isdst?Qtrue:Qfalse,
+ time_zone(time));
}
#define SMALLBUF 100
@@ -677,7 +723,8 @@ rb_strftime(buf, format, time)
return len;
}
- ArgError("bad strftime format or result too long");
+ rb_raise(rb_eArgError, "bad strftime format or result too long");
+ return Qnil; /* not reached */
}
static VALUE
@@ -686,32 +733,32 @@ time_strftime(time, format)
{
struct time_object *tobj;
char buffer[SMALLBUF];
+ char *fmt;
char *buf = buffer;
int len;
VALUE str;
- Check_Type(format, T_STRING);
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
time_localtime(time);
}
- if (strlen(RSTRING(format)->ptr) < RSTRING(format)->len) {
+ fmt = str2cstr(format, &len);
+ if (strlen(fmt) < len) {
/* Ruby string may contain \0's. */
- int l;
- char *p = RSTRING(format)->ptr, *pe = p + RSTRING(format)->len;
+ char *p = fmt, *pe = fmt + len;
- str = str_new(0, 0);
+ str = rb_str_new(0, 0);
while (p < pe) {
len = rb_strftime(&buf, p, &(tobj->tm));
- str_cat(str, buf, len);
+ rb_str_cat(str, buf, len);
p += strlen(p) + 1;
if (len > SMALLBUF) free(buf);
}
return str;
}
len = rb_strftime(&buf, RSTRING(format)->ptr, &(tobj->tm));
- str = str_new(buf, len);
- if (len > SMALLBUF) free(buf);
+ str = rb_str_new(buf, len);
+ if (buf != buffer) free(buf);
return str;
}
@@ -726,11 +773,11 @@ time_s_times(obj)
struct tms buf;
if (times(&buf) == -1) rb_sys_fail(0);
- return struct_new(S_Tms,
- float_new((double)buf.tms_utime / HZ),
- float_new((double)buf.tms_stime / HZ),
- float_new((double)buf.tms_cutime / HZ),
- float_new((double)buf.tms_cstime / HZ));
+ return rb_struct_new(S_Tms,
+ rb_float_new((double)buf.tms_utime / HZ),
+ rb_float_new((double)buf.tms_stime / HZ),
+ rb_float_new((double)buf.tms_cutime / HZ),
+ rb_float_new((double)buf.tms_cstime / HZ));
#else
#ifdef NT
FILETIME create, exit, kernel, user;
@@ -738,69 +785,121 @@ time_s_times(obj)
hProc = GetCurrentProcess();
GetProcessTimes(hProc,&create, &exit, &kernel, &user);
- return struct_new(S_Tms,
- float_new((double)(kernel.dwHighDateTime*2e32+kernel.dwLowDateTime)/2e6),
- float_new((double)(user.dwHighDateTime*2e32+user.dwLowDateTime)/2e6),
- float_new((double)0),
- float_new((double)0));
+ return rb_struct_new(S_Tms,
+ rb_float_new((double)(kernel.dwHighDateTime*2e32+kernel.dwLowDateTime)/2e6),
+ rb_float_new((double)(user.dwHighDateTime*2e32+user.dwLowDateTime)/2e6),
+ rb_float_new((double)0),
+ rb_float_new((double)0));
#else
rb_notimplement();
#endif
#endif
}
+static VALUE
+time_dump(time, limit)
+ VALUE time, limit;
+{
+ struct time_object *tobj;
+ int sec, usec;
+ unsigned char buf[8];
+ int i;
+
+ GetTimeval(time, tobj);
+ sec = tobj->tv.tv_sec;
+ usec = tobj->tv.tv_usec;
+
+ for (i=0; i<4; i++) {
+ buf[i] = sec & 0xff;
+ sec = RSHIFT(sec, 8);
+ }
+ for (i=4; i<8; i++) {
+ buf[i] = usec & 0xff;
+ usec = RSHIFT(usec, 8);
+ }
+ return rb_str_new(buf, 8);
+}
+
+static VALUE
+time_load(klass, str)
+ VALUE klass, str;
+{
+ int sec, usec;
+ unsigned char *buf;
+ int i;
+
+ buf = str2cstr(str, &i);
+ if (i != 8) {
+ rb_raise(rb_eTypeError, "marshaled time format differ");
+ }
+
+ sec = usec = 0;
+ for (i=0; i<4; i++) {
+ sec |= buf[i]<<(8*i);
+ }
+ for (i=4; i<8; i++) {
+ usec |= buf[i]<<(8*(i-4));
+ }
+
+ return time_new_internal(klass, sec, usec);
+}
+
void
Init_Time()
{
- cTime = rb_define_class("Time", cObject);
- rb_include_module(cTime, mComparable);
-
- rb_define_singleton_method(cTime, "now", time_s_now, 0);
- rb_define_singleton_method(cTime, "new", time_s_now, 0);
- rb_define_singleton_method(cTime, "at", time_s_at, 1);
- rb_define_singleton_method(cTime, "gm", time_s_timegm, -1);
- rb_define_singleton_method(cTime, "local", time_s_timelocal, -1);
- rb_define_singleton_method(cTime, "mktime", time_s_timelocal, -1);
-
- rb_define_singleton_method(cTime, "times", time_s_times, 0);
-
- rb_define_method(cTime, "to_i", time_to_i, 0);
- rb_define_method(cTime, "to_f", time_to_f, 0);
- rb_define_method(cTime, "<=>", time_cmp, 1);
- rb_define_method(cTime, "eql?", time_eql, 0);
- rb_define_method(cTime, "hash", time_hash, 0);
-
- rb_define_method(cTime, "localtime", time_localtime, 0);
- rb_define_method(cTime, "gmtime", time_gmtime, 0);
- rb_define_method(cTime, "ctime", time_asctime, 0);
- rb_define_method(cTime, "asctime", time_asctime, 0);
- rb_define_method(cTime, "to_s", time_asctime, 0);
- rb_define_method(cTime, "inspect", time_asctime, 0);
- rb_define_method(cTime, "to_a", time_to_a, 0);
-
- rb_define_method(cTime, "+", time_plus, 1);
- rb_define_method(cTime, "-", time_minus, 1);
-
- rb_define_method(cTime, "sec", time_sec, 0);
- rb_define_method(cTime, "min", time_min, 0);
- rb_define_method(cTime, "hour", time_hour, 0);
- rb_define_method(cTime, "mday", time_mday, 0);
- rb_define_method(cTime, "day", time_mday, 0);
- rb_define_method(cTime, "mon", time_mon, 0);
- rb_define_method(cTime, "month", time_mon, 0);
- rb_define_method(cTime, "year", time_year, 0);
- rb_define_method(cTime, "wday", time_wday, 0);
- rb_define_method(cTime, "yday", time_yday, 0);
- rb_define_method(cTime, "isdst", time_isdst, 0);
- rb_define_method(cTime, "zone", time_zone, 0);
-
- rb_define_method(cTime, "tv_sec", time_to_i, 0);
- rb_define_method(cTime, "tv_usec", time_usec, 0);
- rb_define_method(cTime, "usec", time_usec, 0);
-
- rb_define_method(cTime, "strftime", time_strftime, 1);
+ rb_cTime = rb_define_class("Time", rb_cObject);
+ rb_include_module(rb_cTime, rb_mComparable);
+
+ rb_define_singleton_method(rb_cTime, "now", time_s_now, 0);
+ rb_define_singleton_method(rb_cTime, "new", time_s_now, 0);
+ rb_define_singleton_method(rb_cTime, "at", time_s_at, 1);
+ rb_define_singleton_method(rb_cTime, "gm", time_s_timegm, -1);
+ rb_define_singleton_method(rb_cTime, "local", time_s_timelocal, -1);
+ rb_define_singleton_method(rb_cTime, "mktime", time_s_timelocal, -1);
+
+ rb_define_singleton_method(rb_cTime, "times", time_s_times, 0);
+
+ rb_define_method(rb_cTime, "to_i", time_to_i, 0);
+ rb_define_method(rb_cTime, "to_f", time_to_f, 0);
+ rb_define_method(rb_cTime, "<=>", time_cmp, 1);
+ rb_define_method(rb_cTime, "eql?", time_eql, 1);
+ rb_define_method(rb_cTime, "hash", time_hash, 0);
+
+ rb_define_method(rb_cTime, "localtime", time_localtime, 0);
+ rb_define_method(rb_cTime, "gmtime", time_gmtime, 0);
+ rb_define_method(rb_cTime, "ctime", time_asctime, 0);
+ rb_define_method(rb_cTime, "asctime", time_asctime, 0);
+ rb_define_method(rb_cTime, "to_s", time_to_s, 0);
+ rb_define_method(rb_cTime, "inspect", time_to_s, 0);
+ rb_define_method(rb_cTime, "to_a", time_to_a, 0);
+
+ rb_define_method(rb_cTime, "+", time_plus, 1);
+ rb_define_method(rb_cTime, "-", time_minus, 1);
+
+ rb_define_method(rb_cTime, "sec", time_sec, 0);
+ rb_define_method(rb_cTime, "min", time_min, 0);
+ rb_define_method(rb_cTime, "hour", time_hour, 0);
+ rb_define_method(rb_cTime, "mday", time_mday, 0);
+ rb_define_method(rb_cTime, "day", time_mday, 0);
+ rb_define_method(rb_cTime, "mon", time_mon, 0);
+ rb_define_method(rb_cTime, "month", time_mon, 0);
+ rb_define_method(rb_cTime, "year", time_year, 0);
+ rb_define_method(rb_cTime, "wday", time_wday, 0);
+ rb_define_method(rb_cTime, "yday", time_yday, 0);
+ rb_define_method(rb_cTime, "isdst", time_isdst, 0);
+ rb_define_method(rb_cTime, "zone", time_zone, 0);
+
+ rb_define_method(rb_cTime, "tv_sec", time_to_i, 0);
+ rb_define_method(rb_cTime, "tv_usec", time_usec, 0);
+ rb_define_method(rb_cTime, "usec", time_usec, 0);
+
+ rb_define_method(rb_cTime, "strftime", time_strftime, 1);
#if defined(HAVE_TIMES) || defined(NT)
- S_Tms = struct_define("Tms", "utime", "stime", "cutime", "cstime", 0);
+ S_Tms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", 0);
#endif
+
+ /* methods for marshaling */
+ rb_define_singleton_method(rb_cTime, "_load", time_load, 1);
+ rb_define_method(rb_cTime, "_dump", time_dump, 1);
}
diff --git a/top.sed b/top.sed
index 934f60142d..a9ec12f7b6 100644
--- a/top.sed
+++ b/top.sed
@@ -1,52 +1,58 @@
/^SHELL/s,/bin/sh,$(COMPSEC),
s/@srcdir@/./g
s/@top_srcdir@/../
-s/@CC@/gcc/
-s/@CPP@/gcc -E/
-s/@CPPFLAGS@//
-s/@AR@/ar/
-s/@RANLIB@/ranlib/
-s/@YACC@/bison -y/
-s/@INSTALL@/ginstall -c/
-s/@INSTALL_PROGRAM@/${INSTALL}/
-s/@INSTALL_DATA@/${INSTALL} -m 644/
-s/@SET_MAKE@//
-s/@CFLAGS@/-g -O2 -I./
-s/@STATIC@//
-s/@LDFLAGS@//
-s/@LIBS@//
-s/@LIBOBJS@/crypt.o flock.o/
-s/@ALLOCA@//
-s!@prefix@!/usr/local!
-s/@exec_prefix@/${prefix}/
-s!@bindir@!${exec_prefix}/bin!
-s!@libdir@!${exec_prefix}/lib!
-s/@STRIP@/strip/
-s!/bin/rm!rm!
-s/@DLEXT@/o/
-s/@CCDLFLAGS@/-fpic/
-s/@DLDFLAGS@//
-s/@LDSHARED@//
-s/@binsuffix@/.exe/g
-s/@setup@/Setup/g
-s/|| true//
-s!@archlib@!/usr/local/lib/ruby/i386-djgpp!
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@LDFLAGS@%%g
+s%@LIBS@%-lm %g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${exec_prefix}/libexec%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%${prefix}/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%${prefix}/var%g
+s%@libdir@%${exec_prefix}/lib%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/info%g
+s%@mandir@%${prefix}/man%g
+s%@host@%i386-pc-djgpp%g
+s%@host_alias@%i386-djgpp%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%pc%g
+s%@host_os@%djgpp%g
+s%@CC@%gcc%g
+s%@CPP@%gcc -E%g
+s%@YACC@%bison -y%g
+s%@RANLIB@%ranlib%g
+s%@AR@%ar%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@SET_MAKE@%%g
+s%@LIBOBJS@% crypt.o flock.o vsnprintf.o%g
+s%@ALLOCA@%%g
+s%@DLDFLAGS@%%g
+s%@STATIC@%%g
+s%@CCDLFLAGS@%%g
+s%@LDSHARED@%ld%g
+s%@DLEXT@%o%g
+s%@STRIP@%strip%g
+s%@EXTSTATIC@%%g
+s%@binsuffix@%.exe%g
+s%@setup@%Setup.dj%g
+s%@LIBRUBY@%libruby.a%g
+s%@LIBRUBYARG@%libruby.a%g
+s%@SOLIBS@%%g
+s%@arch@%i386-djgpp%g
+s%/bin/rm%rm%
+s%|| true%%
+s%@archlib@%/usr/local/lib/ruby/i386-djgpp%
/\/dev\/null/ {
s,/dev/null 2>&1, nul,
s,2> /dev/null,,
}
-s/y\.tab\.c/y_tab.c/
-#/if older/s/"ruby"/"ruby.exe"/g
-#/`rm -f ruby`/s//`rm -f ruby.exe`/
-#/`cp miniruby ruby`/s//`cp miniruby.exe ruby.exe`/
-/^all:.*miniruby/ {
- n;c\
- cd ext\
- ../miniruby ./extmk.rb\
- cd ..
-}
-/^clean:;/ {
- n;n;s!cd.*!cd ext\
- ../miniruby ./extmk.rb clean\
- cd ..!
-}
+s%y\.tab\.c%y_tab.c%
diff --git a/util.c b/util.c
index 21e0a55639..ae0914d217 100644
--- a/util.c
+++ b/util.c
@@ -6,21 +6,39 @@
$Date$
created at: Fri Mar 10 17:22:34 JST 1995
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
+#include <stdio.h>
+
+#ifdef NT
+#include "missing/file.h"
+#endif
+
#define RUBY_NO_INLINE
#include "ruby.h"
+VALUE
+rb_class_of(obj)
+ VALUE obj;
+{
+ if (FIXNUM_P(obj)) return rb_cFixnum;
+ if (obj == Qnil) return rb_cNilClass;
+ if (obj == Qfalse) return rb_cFalseClass;
+ if (obj == Qtrue) return rb_cTrueClass;
+
+ return RBASIC(obj)->klass;
+}
+
int
rb_type(obj)
VALUE obj;
{
if (FIXNUM_P(obj)) return T_FIXNUM;
if (obj == Qnil) return T_NIL;
- if (obj == FALSE) return T_FALSE;
- if (obj == TRUE) return T_TRUE;
+ if (obj == Qfalse) return T_FALSE;
+ if (obj == Qtrue) return T_TRUE;
return BUILTIN_TYPE(obj);
}
@@ -29,24 +47,24 @@ int
rb_special_const_p(obj)
VALUE obj;
{
- if (FIXNUM_P(obj)) return TRUE;
- if (obj == Qnil) return TRUE;
- if (obj == FALSE) return TRUE;
- if (obj == TRUE) return TRUE;
+ if (FIXNUM_P(obj)) return Qtrue;
+ if (obj == Qnil) return Qtrue;
+ if (obj == Qfalse) return Qtrue;
+ if (obj == Qtrue) return Qtrue;
- return FALSE;
+ return Qfalse;
}
int
rb_test_false_or_nil(v)
VALUE v;
{
- return (v != Qnil) && (v != FALSE);
+ return (v != Qnil) && (v != Qfalse);
}
#include "util.h"
#ifndef HAVE_STRING_H
-char *strchr();
+char *strchr _((char*,char));
#endif
unsigned long
@@ -86,8 +104,55 @@ int *retlen;
return retval;
}
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(HAVE_FCNTL)
#include <fcntl.h>
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
+#endif
+
+#ifdef NT
+#include "missing/file.h"
+#endif
+
+static char *
+check_dir(dir)
+ char *dir;
+{
+ struct stat st;
+
+ if (dir == NULL) return NULL;
+ if (stat(dir, &st) < 0) return NULL;
+ if (!S_ISDIR(st.st_mode)) return NULL;
+ if (eaccess(dir, W_OK) < 0) return NULL;
+ return dir;
+}
+
+char *
+ruby_mktemp()
+{
+ char *dir;
+ char *buf;
+
+ dir = check_dir(getenv("TMP"));
+ if (!dir) dir = check_dir(getenv("TMPDIR"));
+ if (!dir) dir = "/tmp";
+
+ buf = ALLOC_N(char,strlen(dir)+10);
+ sprintf(buf, "%s/rbXXXXXX", dir);
+ dir = mktemp(buf);
+ if (dir == NULL) free(buf);
+
+ return dir;
+}
+
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
/*
* Copyright (c) 1993, Intergraph Corporation
*
@@ -167,7 +232,9 @@ static char suffix2[] = ".~~~";
#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
void
-add_suffix(VALUE str, char *suffix)
+ruby_add_suffix(str, suffix)
+ VALUE str;
+ char *suffix;
{
int baselen;
int extlen = strlen(suffix);
@@ -176,12 +243,13 @@ add_suffix(VALUE str, char *suffix)
char buf[1024];
if (RSTRING(str)->len > 1000)
- Fatal("Cannot do inplace edit on long filename (%d characters)", RSTRING(str)->len);
+ rb_fatal("Cannot do inplace edit on long filename (%d characters)",
+ RSTRING(str)->len);
#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT)
/* Style 0 */
slen = RSTRING(str)->len;
- str_cat(str, suffix, extlen);
+ rb_str_cat(str, suffix, extlen);
#if defined(DJGPP)
if (_USE_LFN) return;
#else
@@ -224,7 +292,7 @@ add_suffix(VALUE str, char *suffix)
fallback:
(void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
}
- str_resize(str, strlen(buf));
+ rb_str_resize(str, strlen(buf));
memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
}
@@ -262,12 +330,10 @@ valid_filename(char *s)
#include <libc/stubs.h>
#include <stdio.h> /* For FILENAME_MAX */
#include <errno.h> /* For errno */
-#include <ctype.h> /* For tolower */
#include <fcntl.h> /* For LFN stuff */
#include <go32.h>
#include <dpmi.h> /* For dpmisim */
#include <crt0.h> /* For crt0 flags */
-#include <sys/stat.h>
#include <libc/dosio.h>
static unsigned use_lfn;
@@ -486,3 +552,256 @@ int main (int argc, char *argv[])
#endif
#endif
+
+/* mm.c */
+
+static int mmkind, mmsize, high, low;
+
+#define A ((int*)a)
+#define B ((int*)b)
+#define C ((int*)c)
+#define D ((int*)d)
+
+static void mmprepare(base, size) void *base; int size;
+{
+#ifdef DEBUG
+ if (sizeof(int) != 4) die("sizeof(int) != 4");
+ if (size <= 0) die("mmsize <= 0");
+#endif
+
+ if ( ((int)base & (4-1)) == 0 && (size & (4-1)) == 0 )
+ if (size >= 16) mmkind = 1;
+ else mmkind = 0;
+ else mmkind = -1;
+
+ mmsize = size;
+ high = (size & (-16));
+ low = (size & 0x0C );
+}
+
+static void mmswap(a, b) register char *a, *b;
+{
+ 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 + mmsize;
+ do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
+ }
+}
+
+static void mmswapblock(a, b, size) register char *a, *b; int size;
+{
+ register int s;
+ if (mmkind >= 0) {
+ register char *t = a + (size & (-16)); register int lo = (size & 0x0C);
+ if (size >= 16) {
+ 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 (lo != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
+ if (lo >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
+ if (lo == 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);
+ }
+}
+
+static void mmrot3(a, b, c) register char *a, *b, *c;
+{
+ 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 + mmsize;
+ do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
+ }
+}
+
+/* qs6.c */
+/*****************************************************/
+/* */
+/* qs6 (Quick sort function) */
+/* */
+/* by Tomoyuki Kawamura 1995.4.21 */
+/* kawamura@tokuyama.ac.jp */
+/*****************************************************/
+
+typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
+#define PUSH(ll,rr) {top->LL = (ll); top->RR = (rr); ++top;} /* Push L,l,R,r */
+#define POP(ll,rr) {--top; ll = top->LL; rr = top->RR;} /* Pop L,l,R,r */
+
+#define med3(a,b,c) ((*cmp)(a,b)<0 ? \
+ ((*cmp)(b,c)<0 ? b : ((*cmp)(a,c)<0 ? c : a)) : \
+ ((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c)) )
+
+void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)();
+{
+ 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 */
+
+ 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) {if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;}/* 2 elements */
+
+ 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)) < 0) { /*3-5-?*/
+ if ((t = (*cmp)(m,r)) < 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) > 0) goto fail;
+ goto nxt;
+ }
+ fail: goto loopA; /*3-5-7*/
+ }
+ if (t > 0) {
+ if ((*cmp)(l,r) <= 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)) > 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) < 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) <= 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)) < 0) {goto loopA;} /*5-5-7*/
+ if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
+
+ /* deteming 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)) > 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)) > 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)) < 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)) < 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)) > 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 */
+ }
+}
diff --git a/util.h b/util.h
index 570d894ccb..756daeeac6 100644
--- a/util.h
+++ b/util.h
@@ -6,13 +6,33 @@
$Date$
created at: Thu Mar 9 11:55:53 JST 1995
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
#ifndef UTIL_H
#define UTIL_H
-unsigned long scan_hex();
-unsigned long scan_oct();
+#ifndef _
+# ifdef __STDC__
+# define _(args) args
+# else
+# define _(args) ()
+# endif
+#endif
+
+#define scan_oct ruby_scan_oct
+unsigned long scan_oct _((char*, int, int*));
+#define scan_hex ruby_scan_hex
+unsigned long scan_hex _((char*, int, int*));
+
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
+#define add_suffix ruby_add_suffix
+void add_suffix();
+#endif
+
+char *ruby_mktemp _((void));
+
+void ruby_qsort _((void*, int, int, int (*)()));
+#define qsort(b,n,s,c) ruby_qsort(b,n,s,c)
#endif /* UTIL_H */
diff --git a/variable.c b/variable.c
index 0115b87d68..03262c5d83 100644
--- a/variable.c
+++ b/variable.c
@@ -13,24 +13,18 @@
#include "node.h"
#include "st.h"
+#ifdef USE_CWGUSI
+char* strdup(char*);
+#endif
+
static st_table *rb_global_tbl;
st_table *rb_class_tbl;
-#define global_tbl rb_global_tbl
-#define class_tbl rb_class_tbl
-
-int rb_const_defined();
-
-st_table*
-new_idhash()
-{
- return st_init_numtable();
-}
void
Init_var_tables()
{
- global_tbl = new_idhash();
- class_tbl = new_idhash();
+ rb_global_tbl = st_init_numtable();
+ rb_class_tbl = st_init_numtable();
}
struct fc_result {
@@ -41,8 +35,6 @@ struct fc_result {
struct fc_result *prev;
};
-extern VALUE cModule;
-
static int
fc_i(key, value, res)
ID key;
@@ -56,19 +48,19 @@ fc_i(key, value, res)
name = rb_id2name(key);
if (res->path) {
- path = str_dup(res->path);
- str_cat(path, "::", 2);
- str_cat(path, name, strlen(name));
+ path = rb_str_dup(res->path);
+ rb_str_cat(path, "::", 2);
+ rb_str_cat(path, name, strlen(name));
}
else {
- path = str_new2(name);
+ path = rb_str_new2(name);
}
if (value == res->klass) {
res->name = key;
res->path = path;
return ST_STOP;
}
- if (obj_is_kind_of(value, cModule)) {
+ if (rb_obj_is_kind_of(value, rb_cModule)) {
struct fc_result arg;
struct fc_result *list;
@@ -97,99 +89,108 @@ fc_i(key, value, res)
}
static VALUE
-find_class_path(cls)
- VALUE cls;
+find_class_path(klass)
+ VALUE klass;
{
struct fc_result arg;
arg.name = 0;
arg.path = 0;
- arg.klass = cls;
- arg.track = cObject;
+ arg.klass = klass;
+ arg.track = rb_cObject;
arg.prev = 0;
- if (RCLASS(cObject)->iv_tbl) {
- st_foreach(RCLASS(cObject)->iv_tbl, fc_i, &arg);
+ if (RCLASS(rb_cObject)->iv_tbl) {
+ st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg);
}
if (arg.name == 0) {
- st_foreach(class_tbl, fc_i, &arg);
+ st_foreach(rb_class_tbl, fc_i, &arg);
}
if (arg.name) {
- rb_iv_set(cls, "__classpath__", arg.path);
+ rb_iv_set(klass, "__classpath__", arg.path);
return arg.path;
}
return Qnil;
}
static VALUE
-classname(cls)
- VALUE cls;
+classname(klass)
+ VALUE klass;
{
VALUE path;
+ ID classpath = rb_intern("__classpath__");
- while (TYPE(cls) == T_ICLASS || FL_TEST(cls, FL_SINGLETON)) {
- cls = (VALUE)RCLASS(cls)->super;
+ while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
+ klass = (VALUE)RCLASS(klass)->super;
}
- path = rb_iv_get(cls, "__classpath__");
- if (NIL_P(path)) {
- path = rb_iv_get(cls, "__classid__");
+ if (!klass) klass = rb_cObject;
+ if (!ROBJECT(klass)->iv_tbl ||
+ !st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
+ ID classid = rb_intern("__classid__");
+
+ path = rb_ivar_get(klass, classid);
if (!NIL_P(path)) {
- path = str_new2(rb_id2name(FIX2INT(path)));
+ path = rb_str_new2(rb_id2name(FIX2INT(path)));
+ if (!ROBJECT(klass)->iv_tbl)
+ ROBJECT(klass)->iv_tbl = st_init_numtable();
+ st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
+ st_delete(RCLASS(klass)->iv_tbl, &classid, 0);
}
}
if (NIL_P(path)) {
- path = find_class_path(cls);
+ path = find_class_path(klass);
if (NIL_P(path)) {
return 0;
}
return path;
}
- if (TYPE(path) != T_STRING) Bug("class path is not set properly");
+ if (TYPE(path) != T_STRING)
+ rb_bug("class path is not set properly");
return path;
}
VALUE
-mod_name(mod)
+rb_mod_name(mod)
VALUE mod;
{
VALUE path = classname(mod);
- if (path) return path;
- return str_new(0,0);
+ if (path) return rb_str_dup(path);
+ return rb_str_new(0,0);
}
VALUE
-rb_class_path(cls)
- VALUE cls;
+rb_class_path(klass)
+ VALUE klass;
{
- VALUE path = classname(cls);
+ VALUE path = classname(klass);
if (path) return path;
else {
char buf[256];
char *s = "Class";
- if (TYPE(cls) == T_MODULE) s = "Module";
- sprintf(buf, "#<%s 0x%x>", s, cls);
- return str_new2(buf);
+ if (TYPE(klass) == T_MODULE) s = "Module";
+ sprintf(buf, "#<%s 0x%x>", s, klass);
+ return rb_str_new2(buf);
}
}
void
-rb_set_class_path(cls, under, name)
- VALUE cls, under;
+rb_set_class_path(klass, under, name)
+ VALUE klass, under;
char *name;
{
VALUE str;
- if (under == cObject) {
- str = str_new2(name);
+ if (under == rb_cObject) {
+ str = rb_str_new2(name);
}
else {
- str = str_dup(rb_class_path(under));
- str_cat(str, "::", 2);
- str_cat(str, name, strlen(name));
+ str = rb_str_dup(rb_class_path(under));
+ rb_str_cat(str, "::", 2);
+ rb_str_cat(str, name, strlen(name));
}
- rb_iv_set(cls, "__classpath__", str);
+ rb_iv_set(klass, "__classpath__", str);
}
VALUE
@@ -197,24 +198,17 @@ rb_path2class(path)
char *path;
{
if (path[0] == '#') {
- ArgError("can't retrieve anonymous class %s", path);
+ rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
}
return rb_eval_string(path);
}
void
-rb_name_class(cls, id)
- VALUE cls;
+rb_name_class(klass, id)
+ VALUE klass;
ID id;
{
- extern VALUE cString;
-
- if (cString) {
- rb_iv_set(cls, "__classpath__", str_new2(rb_id2name(id)));
- }
- else {
- rb_iv_set(cls, "__classid__", INT2FIX(id));
- }
+ rb_iv_set(klass, "__classid__", INT2FIX(id));
}
static st_table *autoload_tbl = 0;
@@ -225,38 +219,36 @@ rb_autoload_id(id, filename)
char *filename;
{
if (!rb_is_const_id(id)) {
- NameError("autoload must be constant name", rb_id2name(id));
+ rb_raise(rb_eNameError, "autoload must be constant name",
+ rb_id2name(id));
}
if (!autoload_tbl) {
- autoload_tbl = new_idhash();
+ autoload_tbl = st_init_numtable();
}
st_insert(autoload_tbl, id, strdup(filename));
}
void
-rb_autoload(cls, filename)
- char *cls, *filename;
+rb_autoload(klass, filename)
+ char *klass, *filename;
{
- rb_autoload_id(rb_intern(cls), filename);
+ rb_autoload_id(rb_intern(klass), filename);
}
VALUE
-f_autoload(obj, cls, file)
- VALUE obj, cls, file;
+rb_f_autoload(obj, klass, file)
+ VALUE obj, klass, file;
{
- ID id = rb_to_id(cls);
-
- Check_Type(file, T_STRING);
- rb_autoload_id(id, RSTRING(file)->ptr);
+ rb_autoload_id(rb_to_id(klass), STR2CSTR(file));
return Qnil;
}
char *
-rb_class2name(cls)
- VALUE cls;
+rb_class2name(klass)
+ VALUE klass;
{
- return RSTRING(rb_class_path(cls))->ptr;
+ return RSTRING(rb_class_path(klass))->ptr;
}
struct trace_var {
@@ -294,9 +286,9 @@ rb_global_entry(id)
{
struct global_entry *entry;
- if (!st_lookup(global_tbl, id, &entry)) {
+ if (!st_lookup(rb_global_tbl, id, &entry)) {
entry = ALLOC(struct global_entry);
- st_insert(global_tbl, id, entry);
+ st_add_direct(rb_global_tbl, id, entry);
entry->id = id;
entry->data = 0;
entry->getter = undef_getter;
@@ -313,7 +305,9 @@ static VALUE
undef_getter(id)
ID id;
{
- Warning("global variable `%s' not initialized", rb_id2name(id));
+ if (rb_verbose) {
+ rb_warning("global variable `%s' not initialized", rb_id2name(id));
+ }
return Qnil;
}
@@ -358,7 +352,7 @@ static void
val_marker(data)
void *data;
{
- if (data) gc_mark_maybe(data);
+ if (data) rb_gc_mark_maybe(data);
}
static VALUE
@@ -383,7 +377,7 @@ static void
var_marker(var)
VALUE **var;
{
- if (var) gc_mark_maybe(*var);
+ if (var) rb_gc_mark_maybe(*var);
}
static void
@@ -392,7 +386,7 @@ readonly_setter(val, id, var)
ID id;
void *var;
{
- NameError("Can't set variable %s", rb_id2name(id));
+ rb_raise(rb_eNameError, "Can't set variable %s", rb_id2name(id));
}
static int
@@ -405,16 +399,16 @@ mark_global_entry(key, entry)
(*entry->marker)(entry->data);
trace = entry->trace;
while (trace) {
- if (trace->data) gc_mark_maybe(trace->data);
+ if (trace->data) rb_gc_mark_maybe(trace->data);
trace = trace->next;
}
return ST_CONTINUE;
}
void
-gc_mark_global_tbl()
+rb_gc_mark_global_tbl()
{
- st_foreach(global_tbl, mark_global_entry, 0);
+ st_foreach(rb_global_tbl, mark_global_entry, 0);
}
static ID
@@ -481,11 +475,11 @@ static void
rb_trace_eval(cmd, val)
VALUE cmd, val;
{
- rb_eval_cmd(cmd, ary_new3(1, val));
+ rb_eval_cmd(cmd, rb_ary_new3(1, val));
}
VALUE
-f_trace_var(argc, argv)
+rb_f_trace_var(argc, argv)
int argc;
VALUE *argv;
{
@@ -495,14 +489,15 @@ f_trace_var(argc, argv)
struct trace_var *trace;
if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
- cmd = f_lambda();
+ cmd = rb_f_lambda();
}
if (NIL_P(cmd)) {
- return f_untrace_var(argc, argv);
+ return rb_f_untrace_var(argc, argv);
}
id = rb_to_id(var);
- if (!st_lookup(global_tbl, id, &entry)) {
- NameError("undefined global variable %s", rb_id2name(id));
+ if (!st_lookup(rb_global_tbl, id, &entry)) {
+ rb_raise(rb_eNameError, "undefined global variable %s",
+ rb_id2name(id));
}
trace = ALLOC(struct trace_var);
trace->next = entry->trace;
@@ -536,7 +531,7 @@ remove_trace(entry)
}
VALUE
-f_untrace_var(argc, argv)
+rb_f_untrace_var(argc, argv)
int argc;
VALUE *argv;
{
@@ -547,16 +542,18 @@ f_untrace_var(argc, argv)
rb_scan_args(argc, argv, "11", &var, &cmd);
id = rb_to_id(var);
- if (!st_lookup(global_tbl, id, &entry)) {
- NameError("undefined global variable %s", rb_id2name(id));
+ if (!st_lookup(rb_global_tbl, id, &entry)) {
+ rb_raise(rb_eNameError, "undefined global variable %s",
+ rb_id2name(id));
}
+
+ trace = entry->trace;
if (NIL_P(cmd)) {
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
- trace = entry->trace;
while (trace) {
struct trace_var *next = trace->next;
- ary_push(ary, (VALUE)trace->data);
+ rb_ary_push(ary, (VALUE)trace->data);
trace->removed = 1;
trace = next;
}
@@ -570,7 +567,7 @@ f_untrace_var(argc, argv)
if (trace->data == (void*)cmd) {
trace->removed = 1;
if (!entry->block_trace) remove_trace(entry);
- return ary_new3(1, cmd);
+ return rb_ary_new3(1, cmd);
}
trace = trace->next;
}
@@ -589,7 +586,7 @@ struct trace_data {
VALUE val;
};
-static void
+static VALUE
trace_ev(data)
struct trace_data *data;
{
@@ -599,14 +596,16 @@ trace_ev(data)
(*trace->func)(trace->data, data->val);
trace = trace->next;
}
+ return Qnil; /* not reached */
}
-static void
+static VALUE
trace_en(entry)
struct global_entry *entry;
{
entry->block_trace = 0;
remove_trace(entry);
+ return Qnil; /* not reached */
}
VALUE
@@ -616,17 +615,15 @@ rb_gvar_set(entry, val)
{
struct trace_data trace;
- if (rb_safe_level() >= 4) {
- extern VALUE eSecurityError;
- Raise(eSecurityError, "cannot change global variable value");
- }
+ if (rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
(*entry->setter)(val, entry->id, entry->data, entry);
if (entry->trace && !entry->block_trace) {
entry->block_trace = 1;
trace.trace = entry->trace;
trace.val = val;
- rb_ensure(trace_ev, &trace, trace_en, entry);
+ rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)entry);
}
return val;
}
@@ -646,8 +643,8 @@ VALUE
rb_gvar_defined(entry)
struct global_entry *entry;
{
- if (entry->getter == undef_getter) return FALSE;
- return TRUE;
+ if (entry->getter == undef_getter) return Qfalse;
+ return Qtrue;
}
static int
@@ -656,21 +653,23 @@ gvar_i(key, entry, ary)
struct global_entry *entry;
VALUE ary;
{
- ary_push(ary, str_new2(rb_id2name(entry->id)));
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
return ST_CONTINUE;
}
VALUE
-f_global_variables()
+rb_f_global_variables()
{
- VALUE ary = ary_new();
- char buf[3];
- char *s = "^&`'+123456789";
+ VALUE ary = rb_ary_new();
+ char buf[4];
+ char *s = "&`'+123456789";
- st_foreach(global_tbl, gvar_i, ary);
- while (*s) {
- sprintf(buf, "$%c", *s++);
- ary_push(ary, str_new2(buf));
+ st_foreach(rb_global_tbl, gvar_i, ary);
+ if (!NIL_P(rb_backref_get())) {
+ while (*s) {
+ sprintf(buf, "$%c", *s++);
+ rb_ary_push(ary, rb_str_new2(buf));
+ }
}
return ary;
}
@@ -691,6 +690,133 @@ rb_alias_variable(name1, name2)
entry1->marker = entry2->marker;
}
+static int special_generic_ivar = 0;
+static st_table *generic_iv_tbl;
+
+static VALUE
+generic_ivar_get(obj, id)
+ VALUE obj;
+ ID id;
+{
+ st_table *tbl;
+ VALUE val;
+
+ if (!generic_iv_tbl) return Qnil;
+ if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil;
+ if (st_lookup(tbl, id, &val)) {
+ return val;
+ }
+ return Qnil;
+}
+
+static void
+generic_ivar_set(obj, id, val)
+ VALUE obj;
+ ID id;
+ VALUE val;
+{
+ st_table *tbl;
+
+ if (rb_special_const_p(obj)) {
+ special_generic_ivar = 1;
+ }
+ if (!generic_iv_tbl) {
+ generic_iv_tbl = st_init_numtable();
+ }
+
+ if (!st_lookup(generic_iv_tbl, obj, &tbl)) {
+ FL_SET(obj, FL_EXIVAR);
+ tbl = st_init_numtable();
+ st_add_direct(generic_iv_tbl, obj, tbl);
+ st_add_direct(tbl, id, val);
+ return;
+ }
+ st_insert(tbl, id, val);
+}
+
+static VALUE
+generic_ivar_defined(obj, id)
+ VALUE obj;
+ ID id;
+{
+ st_table *tbl;
+ VALUE val;
+
+ if (!generic_iv_tbl) return Qfalse;
+ if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qfalse;
+ if (st_lookup(tbl, id, &val)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+generic_ivar_remove(obj, id)
+ VALUE obj;
+ ID id;
+{
+ st_table *tbl;
+ VALUE val;
+
+ if (!generic_iv_tbl) return Qnil;
+ if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil;
+ st_delete(tbl, &id, &val);
+ if (tbl->num_entries == 0) {
+ st_delete(generic_iv_tbl, &obj, &tbl);
+ st_free_table(tbl);
+ }
+ return val;
+}
+
+static int
+givar_mark_i(key, value)
+ ID key;
+ VALUE value;
+{
+ rb_gc_mark(value);
+ return ST_CONTINUE;
+}
+
+void
+rb_mark_generic_ivar(obj)
+ VALUE obj;
+{
+ st_table *tbl;
+
+ if (st_lookup(generic_iv_tbl, obj, &tbl)) {
+ rb_mark_tbl(tbl);
+ }
+}
+
+static int
+givar_i(obj, tbl)
+ VALUE obj;
+ st_table *tbl;
+{
+ if (rb_special_const_p(obj)) {
+ st_foreach(tbl, givar_mark_i, 0);
+ }
+ return ST_CONTINUE;
+}
+
+void
+rb_mark_generic_ivar_tbl()
+{
+ if (special_generic_ivar == 0) return;
+ if (!generic_iv_tbl) return;
+ st_foreach(generic_iv_tbl, givar_i, 0);
+}
+
+void
+rb_free_generic_ivar(obj)
+ VALUE obj;
+{
+ st_table *tbl;
+
+ if (st_delete(generic_iv_tbl, &obj, &tbl))
+ st_free_table(tbl);
+}
+
VALUE
rb_ivar_get(obj, id)
VALUE obj;
@@ -702,15 +828,18 @@ rb_ivar_get(obj, id)
case T_OBJECT:
case T_CLASS:
case T_MODULE:
+ case T_FILE:
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
return val;
- return Qnil;
+ break;
default:
- TypeError("class %s can not have instance variables",
- rb_class2name(CLASS_OF(obj)));
+ if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
+ return generic_ivar_get(obj, id);
break;
}
- Warning("instance var %s not initialized", rb_id2name(id));
+ if (rb_verbose) {
+ rb_warning("instance var %s not initialized", rb_id2name(id));
+ }
return Qnil;
}
@@ -720,20 +849,18 @@ rb_ivar_set(obj, id, val)
ID id;
VALUE val;
{
- if (rb_safe_level() >= 5) {
- extern VALUE eSecurityError;
- Raise(eSecurityError, "cannot change object status");
- }
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = new_idhash();
+ case T_FILE:
+ if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
+ if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
st_insert(ROBJECT(obj)->iv_tbl, id, val);
break;
default:
- TypeError("class %s can not have instance variables",
- rb_class2name(CLASS_OF(obj)));
+ generic_ivar_set(obj, id, val);
break;
}
return val;
@@ -744,119 +871,136 @@ rb_ivar_defined(obj, id)
VALUE obj;
ID id;
{
- if (!rb_is_instance_id(id)) return FALSE;
+ if (!rb_is_instance_id(id)) return Qfalse;
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
+ case T_FILE:
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
- return TRUE;
+ return Qtrue;
+ break;
+ default:
+ if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
+ return generic_ivar_defined(obj, id);
break;
}
- return FALSE;
+ return Qfalse;
}
static int
-ivar_i(key, value, hash)
+ivar_i(key, entry, ary)
ID key;
- VALUE value;
- VALUE hash;
+ struct global_entry *entry;
+ VALUE ary;
{
if (rb_is_instance_id(key)) {
- hash_aset(hash, str_new2(rb_id2name(key)), value);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
VALUE
-obj_instance_variables(obj)
+rb_obj_instance_variables(obj)
VALUE obj;
{
- VALUE hash = hash_new();
+ VALUE ary;
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
+ case T_FILE:
+ ary = rb_ary_new();
if (ROBJECT(obj)->iv_tbl) {
- st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, hash);
+ st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary);
}
- break;
+ return ary;
default:
- break;
+ if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
+ st_table *tbl;
+
+ if (st_lookup(generic_iv_tbl, obj, &tbl)) {
+ ary = rb_ary_new();
+ st_foreach(tbl, ivar_i, ary);
+ return ary;
+ }
+ }
}
- return hash;
+ return Qnil;
}
VALUE
-obj_remove_instance_variable(obj, name)
+rb_obj_remove_instance_variable(obj, name)
VALUE obj, name;
{
- VALUE val;
+ VALUE val = Qnil;
ID id = rb_to_id(name);
- if (rb_ivar_defined(obj, id)) {
- NameError("`%s' is not an instance variable", rb_id2name(id));
+ if (!rb_is_instance_id(id)) {
+ rb_raise(rb_eNameError, "`%s' is not an instance variable",
+ rb_id2name(id));
}
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
+ case T_FILE:
if (ROBJECT(obj)->iv_tbl) {
st_delete(ROBJECT(obj)->iv_tbl, &id, &val);
}
break;
default:
- TypeError("object %s can not have instance variables",
- rb_class2name(CLASS_OF(obj)));
+ if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
+ return generic_ivar_remove(obj, id);
break;
}
- return obj;
+ return val;
}
VALUE
-rb_const_get_at(cls, id)
- VALUE cls;
+rb_const_get_at(klass, id)
+ VALUE klass;
ID id;
{
VALUE value;
- if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, &value)) {
+ if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
return value;
}
- if (cls == cObject) {
- return rb_const_get(cls, id);
+ if (klass == rb_cObject) {
+ return rb_const_get(klass, id);
}
- NameError("Uninitialized constant %s::%s",
- RSTRING(rb_class_path(cls))->ptr,
- rb_id2name(id));
- /* not reached */
+ rb_raise(rb_eNameError, "Uninitialized constant %s::%s",
+ RSTRING(rb_class_path(klass))->ptr,
+ rb_id2name(id));
+ return Qnil; /* not reached */
}
VALUE
-rb_const_get(cls, id)
- VALUE cls;
+rb_const_get(klass, id)
+ VALUE klass;
ID id;
{
VALUE value;
VALUE tmp;
- tmp = cls;
+ tmp = klass;
while (tmp) {
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
return value;
}
tmp = RCLASS(tmp)->super;
}
- if (BUILTIN_TYPE(cls) == T_MODULE) {
- return rb_const_get(cObject, id);
+ if (BUILTIN_TYPE(klass) == T_MODULE) {
+ return rb_const_get(rb_cObject, id);
}
/* pre-defined class */
- if (st_lookup(class_tbl, id, &value)) return value;
+ if (st_lookup(rb_class_tbl, id, &value)) return value;
/* autoload */
if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
@@ -864,21 +1008,21 @@ rb_const_get(cls, id)
VALUE module;
st_delete(autoload_tbl, &id, &modname);
- module = str_new2(modname);
+ module = rb_str_new2(modname);
free(modname);
- f_require(0, module);
- return rb_const_get(cls, id);
+ rb_f_require(Qnil, module);
+ return rb_const_get(klass, id);
}
/* Uninitialized constant */
- if (cls && cls != cObject)
- NameError("Uninitialized constant %s::%s",
- RSTRING(rb_class_path(cls))->ptr,
- rb_id2name(id));
+ if (klass && klass != rb_cObject)
+ rb_raise(rb_eNameError, "Uninitialized constant %s::%s",
+ RSTRING(rb_class_path(klass))->ptr,
+ rb_id2name(id));
else {
- NameError("Uninitialized constant %s",rb_id2name(id));
+ rb_raise(rb_eNameError, "Uninitialized constant %s",rb_id2name(id));
}
- /* not reached */
+ return Qnil; /* not reached */
}
static int
@@ -888,36 +1032,59 @@ const_i(key, value, ary)
VALUE ary;
{
if (rb_is_const_id(key)) {
- VALUE kval = str_new2(rb_id2name(key));
- if (!ary_includes(ary, kval)) {
- ary_push(ary, kval);
+ VALUE kval = rb_str_new2(rb_id2name(key));
+ if (!rb_ary_includes(ary, kval)) {
+ rb_ary_push(ary, kval);
}
}
return ST_CONTINUE;
}
+VALUE
+rb_mod_remove_const(mod, name)
+ VALUE mod, name;
+{
+ ID id = rb_to_id(name);
+ VALUE val;
+
+ if (!rb_is_const_id(id)) {
+ rb_raise(rb_eNameError, "`%s' is not constant", rb_id2name(id));
+ }
+
+ if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
+ return val;
+ }
+ if (rb_const_defined_at(mod, id)) {
+ rb_raise(rb_eNameError, "cannot remove %s::%s",
+ rb_class2name(mod), rb_id2name(id));
+ }
+ rb_raise(rb_eNameError, "constant %s::%s not defined",
+ rb_class2name(mod), rb_id2name(id));
+ return Qnil; /* not reached */
+}
+
static int
autoload_i(key, name, ary)
ID key;
char *name;
VALUE ary;
{
- VALUE kval = str_new2(rb_id2name(key));
- if (!ary_includes(ary, kval)) {
- ary_push(ary, kval);
+ VALUE kval = rb_str_new2(rb_id2name(key));
+ if (!rb_ary_includes(ary, kval)) {
+ rb_ary_push(ary, kval);
}
return ST_CONTINUE;
}
VALUE
-mod_const_at(mod, ary)
+rb_mod_const_at(mod, ary)
VALUE mod, ary;
{
if (RCLASS(mod)->iv_tbl) {
st_foreach(RCLASS(mod)->iv_tbl, const_i, ary);
}
- if ((VALUE)mod == cObject) {
- st_foreach(class_tbl, const_i, ary);
+ if ((VALUE)mod == rb_cObject) {
+ st_foreach(rb_class_tbl, const_i, ary);
if (autoload_tbl) {
st_foreach(autoload_tbl, autoload_i, ary);
}
@@ -926,38 +1093,38 @@ mod_const_at(mod, ary)
}
VALUE
-mod_constants(mod)
+rb_mod_constants(mod)
VALUE mod;
{
- return mod_const_at(mod, ary_new());
+ return rb_mod_const_at(mod, rb_ary_new());
}
VALUE
-mod_const_of(mod, ary)
+rb_mod_const_of(mod, ary)
VALUE mod;
VALUE ary;
{
- mod_const_at(mod, ary);
+ rb_mod_const_at(mod, ary);
for (;;) {
mod = RCLASS(mod)->super;
if (!mod) break;
- mod_const_at(mod, ary);
+ rb_mod_const_at(mod, ary);
}
return ary;
}
int
-rb_const_defined_at(cls, id)
- VALUE cls;
+rb_const_defined_at(klass, id)
+ VALUE klass;
ID id;
{
- if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) {
- return TRUE;
+ if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
+ return Qtrue;
}
- if (cls == cObject) {
- return rb_const_defined(cls, id);
+ if (klass == rb_cObject) {
+ return rb_const_defined(klass, id);
}
- return FALSE;
+ return Qfalse;
}
int
@@ -965,53 +1132,65 @@ rb_autoload_defined(id)
ID id;
{
if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
- return TRUE;
- return FALSE;
+ return Qtrue;
+ return Qfalse;
}
int
-rb_const_defined(cls, id)
- VALUE cls;
+rb_const_defined(klass, id)
+ VALUE klass;
ID id;
{
- while (cls) {
- if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) {
- return TRUE;
+ VALUE tmp = klass;
+
+ while (tmp) {
+ if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
+ return Qtrue;
}
- cls = RCLASS(cls)->super;
+ tmp = RCLASS(tmp)->super;
+ }
+ if (BUILTIN_TYPE(klass) == T_MODULE) {
+ return rb_const_defined(rb_cObject, id);
}
- if (st_lookup(class_tbl, id, 0))
- return TRUE;
+ if (st_lookup(rb_class_tbl, id, 0))
+ return Qtrue;
return rb_autoload_defined(id);
}
void
-rb_const_set(cls, id, val)
- VALUE cls;
+rb_const_set(klass, id, val)
+ VALUE klass;
ID id;
VALUE val;
{
- if (!RCLASS(cls)->iv_tbl) {
- RCLASS(cls)->iv_tbl = new_idhash();
+ if (rb_safe_level() >= 4 && !FL_TEST(klass, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't set constant");
+ if (!RCLASS(klass)->iv_tbl) {
+ RCLASS(klass)->iv_tbl = st_init_numtable();
}
- else if (st_lookup(RCLASS(cls)->iv_tbl, id, 0)) {
- NameError("already initialized constant %s", rb_id2name(id));
+ else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
+ rb_raise(rb_eNameError, "already initialized constant %s",
+ rb_id2name(id));
}
- st_insert(RCLASS(cls)->iv_tbl, id, val);
+ st_add_direct(RCLASS(klass)->iv_tbl, id, val);
}
void
-rb_define_const(cls, name, val)
- VALUE cls;
+rb_define_const(klass, name, val)
+ VALUE klass;
char *name;
VALUE val;
{
ID id = rb_intern(name);
+
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
if (!rb_is_const_id(id)) {
- NameError("wrong constant name %s", name);
+ rb_raise(rb_eNameError, "wrong constant name %s", name);
}
- rb_const_set(cls, id, val);
+ rb_const_set(klass, id, val);
}
void
@@ -1019,7 +1198,7 @@ rb_define_global_const(name, val)
char *name;
VALUE val;
{
- rb_define_const(cObject, name, val);
+ rb_define_const(rb_cObject, name, val);
}
VALUE
diff --git a/version.c b/version.c
index 71f531c963..22393f0f4a 100644
--- a/version.c
+++ b/version.c
@@ -7,7 +7,7 @@
$Date$
created at: Thu Sep 30 20:08:01 JST 1993
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -18,19 +18,19 @@
void
Init_version()
{
- rb_define_global_const("VERSION", str_new2(RUBY_VERSION));
- rb_define_global_const("PLATFORM", str_new2(RUBY_PLATFORM));
+ rb_define_global_const("VERSION", rb_str_new2(RUBY_VERSION));
+ rb_define_global_const("PLATFORM", rb_str_new2(RUBY_PLATFORM));
}
void
-show_version()
+ruby_show_version()
{
fprintf(stderr, "ruby %s(%s) [%s]\n", RUBY_VERSION, VERSION_DATE, RUBY_PLATFORM);
}
void
-show_copyright()
+ruby_show_copyright()
{
- fprintf(stderr, "ruby - Copyright (C) 1993-1997 Yukihiro Matsumoto\n");
+ fprintf(stderr, "ruby - Copyright (C) 1993-1998 Yukihiro Matsumoto\n");
exit(0);
}
diff --git a/version.h b/version.h
index b737876434..3b291392b3 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "1.1b5"
-#define VERSION_DATE "98/01/16"
+#define RUBY_VERSION "1.3.1"
+#define VERSION_DATE "99/01/20"
diff --git a/win32/Makefile b/win32/Makefile
index c7e8b8dbec..152bdc88ea 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -15,12 +15,12 @@ INSTALL_DATA = $(INSTALL) -m 644
PURIFY =
-CFLAGS = -nologo -DNT=1 -Ox
+CFLAGS = -nologo -DNT=1 -Ox -I. -I./missing
LDFLAGS = $(CFLAGS) -Fm
#CFLAGS = -nologo -DNT=1 -Zi -MD
#LDFLAGS = $(CFLAGS) -Fm -MD
LIBS = $(EXTLIBS) advapi32.lib wsock32.lib
-MISSING = crypt.obj setenv.obj alloca.obj nt.obj
+MISSING = crypt.obj alloca.obj win32.obj
prefix =
binprefix =
@@ -30,7 +30,6 @@ libdir =
STACK = 0x200000
ORGLIBPATH = $(LIB)
-#MISCLIBS = win32\sdbm.lib
#### End of system configuration section. ####
@@ -157,9 +156,6 @@ memmove.obj: missing/memmove.c
mkdir.obj: missing/mkdir.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/mkdir.c
-setenv.obj: missing/setenv.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/setenv.c
-
strerror.obj: missing/strerror.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strerror.c
@@ -180,22 +176,15 @@ strtoul.obj: missing/strtoul.c
# when I use -I., there is confliction at "OpenFile"
# so, set . into environment varible "include"
-nt.obj: missing/nt.c
+win32.obj: win32/win32.c
@set include=$(INCLUDE);.
- $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/nt.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c win32/win32.c
parse.c: parse.y
$(YACC) $(YFLAGS) parse.y
sed -e "s!^extern char \*getenv();!/* & */!" y.tab.c > parse.c
@rm y.tab.c
-win32\sdbm.lib : win32\sdbm.c win32\sdbm.h
- cd win32
- $(CC) $(CFLAGS) $(CPPFLAGS) -DMSDOS -c sdbm.c
- lib /OUT:sdbm.lib sdbm.obj
- copy sdbm.h ndbm.h
- cd ..
-
# Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT:
###
@@ -210,26 +199,26 @@ dln.obj: dln.c config.h defines.h dln.h st.h
dmyext.obj: dmyext.c
enum.obj: enum.c ruby.h config.h defines.h
error.obj: error.c ruby.h config.h defines.h env.h
-eval.obj: eval.c ruby.h config.h defines.h env.h node.h sig.h st.h dln.h
-file.obj: file.c ruby.h config.h defines.h io.h sig.h
+eval.obj: eval.c ruby.h config.h defines.h env.h node.h rubysig.h st.h dln.h
+file.obj: file.c ruby.h config.h defines.h rubyio.h rubysig.h
fnmatch.obj: fnmatch.c config.h fnmatch.h
-gc.obj: gc.c ruby.h config.h defines.h env.h sig.h st.h node.h re.h regex.h
+gc.obj: gc.c ruby.h config.h defines.h env.h rubysig.h st.h node.h re.h regex.h
glob.obj: glob.c config.h fnmatch.h
hash.obj: hash.c ruby.h config.h defines.h st.h
inits.obj: inits.c ruby.h config.h defines.h
-io.obj: io.c ruby.h config.h defines.h io.h sig.h
+io.obj: io.c ruby.h config.h defines.h rubyio.h rubysig.h
main.obj: main.c
math.obj: math.c ruby.h config.h defines.h
numeric.obj: numeric.c ruby.h config.h defines.h
object.obj: object.c ruby.h config.h defines.h st.h
pack.obj: pack.c ruby.h config.h defines.h
-process.obj: process.c ruby.h config.h defines.h sig.h st.h
+process.obj: process.c ruby.h config.h defines.h rubysig.h st.h
random.obj: random.c ruby.h config.h defines.h
range.obj: range.c ruby.h config.h defines.h
re.obj: re.c ruby.h config.h defines.h re.h regex.h
regex.obj: regex.c config.h defines.h regex.h util.h
ruby.obj: ruby.c ruby.h config.h defines.h re.h regex.h dln.h
-signal.obj: signal.c ruby.h config.h defines.h sig.h
+signal.obj: signal.c ruby.h config.h defines.h rubysig.h
sprintf.obj: sprintf.c ruby.h config.h defines.h
st.obj: st.c config.h st.h
string.obj: string.c ruby.h config.h defines.h re.h regex.h
diff --git a/win32/config.h b/win32/config.h
index cf5cb332bf..8385154cd5 100644
--- a/win32/config.h
+++ b/win32/config.h
@@ -1,4 +1,10 @@
-#define THREAD 1
+#define USE_THREAD 1
+#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
+#define SIZEOF_VOIDP 4
+#define HAVE_PROTOTYPES 1
+#define HAVE_STDARG_PROTOTYPES 1
+/* #define HAVE_ATTR_NORETURN 1 */
/* #define HAVE_DIRENT_H 1 */
/* #define HAVE_UNISTD_H 1 */
#define HAVE_STDLIB_H 1
@@ -31,6 +37,7 @@
/* #define HAVE_SETITIMER 1 */
#define HAVE_GETGROUPS 1
/* #define HAVE_SIGPROCMASK 1 */
+#define RSHIFT(x,y) ((x)>>y)
#define FILE_COUNT _cnt
#define DLEXT ".dll"
#define RUBY_LIB ";/usr/local/lib/ruby;."
@@ -43,6 +50,9 @@
#define pclose _pclose
#define pipe _pipe
#define bzero(x, y) memset(x, 0, y)
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+
#define S_IFMT _S_IFMT
#define S_IFDIR _S_IFDIR
diff --git a/win32/ruby.def b/win32/ruby.def
index e8ece2ae50..dfe63e5ba6 100644
--- a/win32/ruby.def
+++ b/win32/ruby.def
@@ -1,37 +1,58 @@
LIBRARY rubymw.dll
-CODE LOADONCALL
-DATA LOADONCALL
DESCRIPTION 'win32 rubymw.dll'
EXPORTS
-;global objects
+;;global objects
;array.c:
- cArray
+ rb_cArray
;bignum.c:
- cBignum
+ rb_cBignum
+;enum.c
+ rb_mEnumerable
+;error.c
+ rb_eException;
+ rb_eSystemExit
+ rb_eInterrupt
+ rb_eFatal;
+ rb_eStandardError;
+ rb_eRuntimeError;
+ rb_eSyntaxError;
+ rb_eTypeError;
+ rb_eArgError;
+ rb_eNameError;
+ rb_eIndexError;
+ rb_eLoadError;
+ rb_eSecurityError;
+ rb_eNotImpError;
+ rb_eSystemCallError;
+ rb_mErrno;
;eval.c:
- cProc
+ rb_cProc
;file.c:
- cFile
+ rb_cFile
;hash.c:
- cHash
+ rb_cHash
;io.c:
- cIO
+ rb_cIO
;numeric.c:
- cNumeric
- cFloat
- cInteger
- cFixnum
+ rb_cNumeric
+ rb_cFloat
+ rb_cInteger
+ rb_cFixnum
;object.c
- cObject
- cModule
- cClass
- cFixnum
- cData
+ rb_mKernel
+ rb_cObject
+ rb_cModule
+ rb_cClass
+ rb_cData
+
+ rb_cNilClass
+ rb_cTrueClass
+ rb_cFalseClass
;re.c:
- cRegexp
+ rb_cRegexp
;string.c:
- cString
- cStruct
+ rb_cString
+ rb_cStruct
; procedures/methods
;missing/nt.c
@@ -60,64 +81,63 @@ EXPORTS
mygetservbyname
mygetservbyport
;array.c
- memclear
- ary_freeze
- ary_new2
- ary_new
- ary_new3
- ary_new4
- assoc_new
- ary_store
- ary_push
- ary_pop
- ary_shift
- ary_unshift
- ary_entry
- ary_each
- ary_join
- ary_to_s
- ary_reverse
- ary_sort_bang
- ary_sort
- ary_delete
- ary_delete_at
- ary_plus
- ary_concat
- ary_assoc
- ary_rassoc
- ary_includes
+ rb_ary_freeze
+ rb_ary_new2
+ rb_ary_new
+ rb_ary_new3
+ rb_ary_new4
+ rb_assoc_new
+ rb_ary_store
+ rb_ary_push
+ rb_ary_pop
+ rb_ary_shift
+ rb_ary_unshift
+ rb_ary_entry
+ rb_ary_aref
+ rb_ary_each
+ rb_ary_join
+ rb_ary_to_s
+ rb_ary_reverse
+ rb_ary_sort_bang
+ rb_ary_sort
+ rb_ary_delete
+ rb_ary_delete_at
+ rb_ary_plus
+ rb_ary_concat
+ rb_ary_assoc
+ rb_ary_rassoc
+ rb_ary_includes
;bignum.c
- big_clone
- big_2comp
- big_norm
- uint2big
- int2big
- uint2inum
- int2inum
- str2inum
- big2str
- big2int
- big_to_i
- dbl2big
- big2dbl
- big_to_f
- big_plus
- big_minus
- big_mul
- big_pow
- big_and
- big_or
- big_xor
- big_lshift
- big_rand
+ rb_big_clone
+ rb_big_2comp
+ rb_big_norm
+ rb_uint2big
+ rb_int2big
+ rb_uint2inum
+ rb_int2inum
+ rb_str2inum
+ rb_big2str
+ rb_big2ulong
+ rb_big2long
+ rb_dbl2big
+ rb_big2dbl
+ rb_big_plus
+ rb_big_minus
+ rb_big_mul
+ rb_big_pow
+ rb_big_and
+ rb_big_or
+ rb_big_xor
+ rb_big_lshift
+ rb_big_rand
;class.c
- class_new
- singleton_class_new
- singleton_class_clone
+ rb_class_new
+ rb_singleton_class_new
+ rb_singleton_class_clone
rb_define_class_id
rb_define_class
rb_define_class_under
- module_new
+ rb_module_new
rb_define_module_id
rb_define_module
rb_define_module_under
@@ -126,6 +146,7 @@ EXPORTS
rb_define_method
rb_undef_method
rb_define_private_method
+ rb_define_protected_method
rb_singleton_class
rb_define_singleton_method
rb_define_module_function
@@ -134,39 +155,37 @@ EXPORTS
rb_define_attr
rb_scan_args
; dln.c
+ dln_find_exe
+ dln_find_file
dln_load
dln_find_exe
dln_find_file
; enum.c
rb_each
- enum_length
+ rb_enum_length
; error.c
- Error
- Error_Append
- Warning
- Bug
+ rb_compile_error
+ rb_compile_error_append
+ rb_warn
+ rb_warning
+ rb_bug
rb_check_type
- exc_new
- exc_new2
- exc_new3
- Raise
- TypeError
- ArgError
- NameError
- IndexError
- Fail
+ rb_exc_new
+ rb_exc_new2
+ rb_exc_new3
+ rb_raise
+ rb_loaderror
rb_notimplement
- LoadError
- Fatal
+ rb_fatal
rb_sys_fail
;eval.c
rb_clear_cache
- rb_add_method
rb_alias
+ rb_add_method
+ rb_remove_method
+ rb_disable_super
+ rb_enable_super
rb_method_boundp
- dyna_var_defined
- dyna_var_ref
- dyna_var_asgn
rb_safe_level
rb_set_safe_level
rb_check_safe_str
@@ -183,9 +202,7 @@ EXPORTS
rb_raise
rb_fatal
rb_interrupt
- iterator_p
- rb_yield_0
- rb_yield
+ rb_iterator_p
rb_iterate
rb_rescue
rb_ensure
@@ -194,88 +211,89 @@ EXPORTS
rb_funcall2
rb_backtrace
rb_frame_last_func
- f_load
+ rb_load
rb_provide
- f_require
- class_new_instance
+ rb_f_require
+ rb_obj_instance_eval
+ rb_obj_call_init
+ rb_class_new_instance
rb_extend_object
- f_lambda
- gc_mark_threads
- thread_schedule
- thread_wait_fd
- thread_fd_writable
- thread_wait_for
- thread_alone
- thread_select
- thread_sleep
- thread_sleep_forever
- thread_create
- thread_interrupt
+ rb_f_global_variables
+ rb_set_end_proc
+ rb_f_autoload
+ rb_f_lambda
+ rb_gc_mark_threads
+ rb_thread_schedule
+ rb_thread_wait_fd
+ rb_thread_fd_writable
+ rb_thread_wait_for
+ rb_thread_alone
+ rb_thread_select
+ rb_thread_sleep
+ rb_thread_sleep_forever
+ rb_thread_create
+ rb_thread_scope_shared_p
+ rb_thread_interrupt
+ rb_thread_trap_eval
+ rb_catch
+ rb_throw
+ rb_yield
; file.c
- file_open
+ rb_file_open
eaccess
- file_s_expand_path
+ rb_file_s_expand_path
; gc.c
xmalloc
xcalloc
xrealloc
- gc_s_enable
- gc_s_disable
rb_global_variable
rb_newobj
- data_object_alloc
- gc_mark_locations
- gc_mark_maybe
- gc_mark
- gc_force_recycle
- gc_mark_frame
- gc_gc
+ rb_data_object_alloc
+ rb_gc_mark_locations
+ rb_gc_mark_maybe
+ rb_gc_mark
+ rb_gc_force_recycle
+ rb_gc_mark_frame
+ rb_gc
; hash.c
+ rb_hash_freeze
rb_hash
- hash_new
- hash_aref
- hash_aset
+ rb_hash_new
+ rb_hash_aref
+ rb_hash_aset
; inits.c
rb_call_inits
; io.c
- eof_error
- io_writable
- io_readable
- io_write
- io_gets_method
- io_gets
- io_getc
- io_ungetc
- io_fptr_finalize
- io_close
- io_binmode
- io_mode_flags
+ rb_eof_error
+ rb_io_write
+ rb_io_gets
+ rb_io_getc
+ rb_io_ungetc
+ rb_io_fptr_finalize
+ rb_io_close
+ rb_io_binmode
+ rb_io_mode_flags
rb_fopen
rb_fdopen
- io_unbuffered
- io_reopen
- f_gets
+ rb_io_unbuffered
+ rb_io_reopen
rb_str_setter
; numeric.c
- num_zerodiv
- num_coerce_bin
- float_new
- flo_pow
- num2int
- num2fix
- fix2str
- fix_to_s
- num_upto
- fix_upto
+ rb_num_zerodiv
+ rb_num_coerce_bin
+ rb_float_new
+ rb_num2long
+ rb_num2ulong
+ rb_num2fix
+ rb_fix2str
; object.c
rb_equal
rb_eql
- obj_equal
- any_to_s
+ rb_any_to_s
rb_inspect
- obj_is_instance_of
- obj_is_kind_of
- obj_alloc
+ rb_obj_is_instance_of
+ rb_obj_is_kind_of
+ rb_obj_alloc
rb_to_id
rb_class_of
rb_type
@@ -285,54 +303,51 @@ EXPORTS
rb_String
rb_Array
; parse.c
- ;;compile_string
- ;;compile_file
- ;;node_newnode
- nodetype
- nodeline
- id_attrset
+ rb_node_newnode
+ rb_id_attrset
rb_intern
rb_id2name
rb_is_const_id
rb_is_instance_id
- local_var_append
- backref_get
- backref_set
- lastline_get
- lastline_set
+ rb_backref_get
+ rb_backref_set
+ rb_lastline_get
+ rb_lastline_set
; process.c
rb_proc_exec
rb_syswait
; range.c
- range_new
- range_beg_end
+ rb_range_new
+ rb_range_beg_end
; re.c
- str_cicmp
- reg_search
- reg_nth_defined
- reg_nth_match
- reg_last_match
- reg_match_pre
- reg_match_post
- reg_match_last
- reg_free
- reg_new
- reg_regcomp
- reg_match
- reg_match2
- reg_regsub
+ rb_str_cicmp
+ rb_reg_search
+ rb_reg_nth_defined
+ rb_reg_nth_match
+ rb_reg_last_match
+ rb_reg_match_pre
+ rb_reg_match_post
+ rb_reg_match_last
+ rb_reg_new
+ rb_reg_regcomp
+ rb_reg_match
+ rb_reg_match2
+ rb_reg_regsub
+ rb_get_kcode
rb_set_kcode
; ruby.c
- rb_require_modules
+ ruby_require_modules
rb_load_file
ruby_script
ruby_prog_init
ruby_set_argv
ruby_process_options
; signal.c
- gc_mark_trap_list
+ rb_gc_mark_trap_list
rb_trap_exit
rb_trap_exec
+; sprintf.c
+ rb_f_sprintf
; st.c
st_init_table_with_size
st_init_table
@@ -342,58 +357,61 @@ EXPORTS
st_lookup
st_insert
st_add_direct
- st_find_or_add
st_copy
st_delete
st_delete_safe
st_foreach
; string.c
- str_new
- str_new2
- str_new3
- str_new4
- obj_as_string
- str_dup
- str_plus
- str_times
- str_substr
- str_modify
- str_freeze
- str_dup_freezed
- str_taint
- str_tainted
- str_resize
- str_cat
- str_hash
- str_cmp
- str_upto
- str_inspect
- str_split
+ rb_str_new
+ rb_str_new2
+ rb_tainted_str_new
+ rb_tainted_str_new2
+ rb_str_new3
+ rb_str_new4
+ rb_str_to_str
+ rb_obj_as_string
+ rb_str_dup
+ rb_str_plus
+ rb_str_times
+ rb_str_substr
+ rb_str_modify
+ rb_str_freeze
+ rb_str_dup_frozen
+ rb_str_resize
+ rb_str_cat
+ rb_str_hash
+ rb_str_cmp
+ rb_str_upto
+ rb_str_inspect
+ rb_str_split
; struct.c
- struct_getmember
- struct_define
- struct_alloc
- struct_new
- struct_aref
- struct_aset
+ rb_struct_getmember
+ rb_struct_define
+ rb_struct_alloc
+ rb_struct_new
+ rb_struct_aref
+ rb_struct_aset
; time.c
- time_new
- time_timeval
+ rb_time_new
+ rb_time_timeval
; util.c
- scan_oct
- scan_hex
- add_suffix
+ rb_class_of
+ rb_type
+ rb_special_const_p
+ rb_test_false_or_nil
+ ruby_scan_oct
+ ruby_scan_hex
+ rb_add_suffix
;variable.c
- new_idhash
rb_class_path
rb_set_class_path
rb_path2class
rb_name_class
rb_autoload
- f_autoload
+ rb_f_autoload
rb_class2name
rb_global_entry
- gc_mark_global_tbl
+ rb_gc_mark_global_tbl
rb_define_hooked_variable
rb_define_variable
rb_define_readonly_variable
@@ -408,7 +426,9 @@ EXPORTS
rb_ivar_defined
rb_const_get_at
rb_const_get
- mod_constants
+ rb_mod_const_at
+ rb_mod_constants
+ rb_mod_const_of
rb_const_defined_at
rb_autoload_defined
rb_const_defined
@@ -418,7 +438,6 @@ EXPORTS
rb_iv_get
rb_iv_set
; version.c
- show_version
- show_copyright
-
+ ruby_show_version
+ ruby_show_copyright
diff --git a/win32/sdbm.c b/win32/sdbm.c
index 0e4673bbb5..d2d2171875 100644
--- a/win32/sdbm.c
+++ b/win32/sdbm.c
@@ -634,7 +634,7 @@ register DBM *db;
*/
#ifndef lint
-/*char pair_rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";*/
+/*char pair_rcsid[] = "$Id: sdbm.c,v 1.1.1.1.2.1 1998/01/16 12:36:12 matz Exp $";*/
#endif
#ifndef BSD42